From db20f3f1bb8595633a7e16c8900fd401a453a6b5 Mon Sep 17 00:00:00 2001 From: Jiyoung Yun Date: Tue, 27 Dec 2016 16:46:08 +0900 Subject: [PATCH] Imported Upstream version 1.0.0.9127 --- .gitignore | 306 - .gitmirror | 1 - .gitmirrorselective | 1 + BuildToolsVersion.txt | 2 +- CMakeLists.txt | 130 +- Documentation/README.md | 2 +- .../botr/{_tableOfContents.md => README.md} | 0 Documentation/botr/clr-abi.md | 6 +- Documentation/botr/exceptions.md | 12 +- Documentation/botr/garbage-collection.md | 2 +- Documentation/building/crossgen.md | 43 +- Documentation/building/linux-instructions.md | 8 + Documentation/building/osx-instructions.md | 20 +- Documentation/building/testing-with-corefx.md | 6 +- Documentation/building/viewing-jit-dumps.md | 2 +- Documentation/building/windows-instructions.md | 196 +- Documentation/coding-guidelines/clr-code-guide.md | 5 +- Documentation/design-docs/multi-reg-call-nodes.md | 230 + .../project-docs/adding_new_public_apis.md | 23 +- Documentation/project-docs/ci-trigger-phrases.md | 112 +- Documentation/project-docs/glossary.md | 2 + Documentation/workflow/EditingAndDebugging.md | 49 + Documentation/workflow/IssuesFeedbackEngagement.md | 37 + Documentation/workflow/OfficalAndDailyBuilds.md | 79 + Documentation/workflow/RunningTests.md | 10 + Documentation/workflow/UsingCoreRun.md | 83 + Documentation/workflow/UsingYourBuild.md | 215 + DotnetCLIVersion.txt | 2 +- README.md | 292 +- binclash.log | 0 build-packages.cmd | 36 +- build-packages.sh | 90 +- build-test.cmd | 82 +- build.cmd | 89 +- build.proj | 4 - build.sh | 171 +- clean.cmd | 2 +- clr.coreclr.props | 3 + clr.defines.targets | 3 + clrdefinitions.cmake | 17 + config.json | 113 +- cross/arm/sources.list.jessie | 3 + cross/arm/sources.list.xenial | 11 + cross/arm64/sources.list.xenial | 11 + cross/build-rootfs.sh | 96 +- cross/x86/sources.list.trusty | 11 + cross/x86/sources.list.vivid | 11 + cross/x86/sources.list.wily | 11 + cross/x86/sources.list.xenial | 11 + cross/x86/toolchain.cmake | 40 + cross/x86/tryrun.cmake | 127 + crosscomponents.cmake | 1 + dependencies.props | 24 +- dir.props | 8 +- extract-from-json.py | 56 - functions.cmake | 18 + init-tools.cmd | 18 +- init-tools.log | 539 + init-tools.sh | 224 +- netci.groovy | 838 +- perf.groovy | 141 +- pgosupport.cmake | 14 +- publish-packages.cmd | 4 +- publish-packages.sh | 3 + run.cmd | 8 +- run.sh | 4 +- src/.gitmirrorselective | 2 + .../Microsoft.NETCore.ILAsm.builds | 16 + .../Microsoft.NETCore.ILAsm.pkgproj | 14 +- .../alpine/3.4.3/Microsoft.NETCore.ILAsm.pkgproj | 29 + .../linux/Microsoft.NETCore.ILAsm.pkgproj | 29 + .../ubuntu/14.04/Microsoft.NETCore.ILAsm.pkgproj | 6 +- .../ubuntu/16.04/Microsoft.NETCore.ILAsm.pkgproj | 6 +- .../Microsoft.NETCore.ILDAsm.builds | 16 + .../Microsoft.NETCore.ILDAsm.pkgproj | 14 +- .../alpine/3.4.3/Microsoft.NETCore.ILDAsm.pkgproj | 29 + .../linux/Microsoft.NETCore.ILDAsm.pkgproj | 29 + .../ubuntu/14.04/Microsoft.NETCore.ILDAsm.pkgproj | 6 +- .../ubuntu/16.04/Microsoft.NETCore.ILDAsm.pkgproj | 6 +- .../Microsoft.NETCore.Jit.builds | 16 + .../Microsoft.NETCore.Jit.pkgproj | 14 +- .../alpine/3.4.3/Microsoft.NETCore.Jit.pkgproj | 29 + .../linux/Microsoft.NETCore.Jit.pkgproj | 29 + .../ubuntu/14.04/Microsoft.NETCore.Jit.pkgproj | 6 +- .../ubuntu/16.04/Microsoft.NETCore.Jit.pkgproj | 6 +- .../win/Microsoft.NETCore.Jit.pkgproj | 1 + .../Microsoft.NETCore.Runtime.CoreCLR.builds | 17 +- .../Microsoft.NETCore.Runtime.CoreCLR.pkgproj | 29 +- .../Microsoft.NETCore.Runtime.CoreCLR.pkgproj | 56 + .../Microsoft.NETCore.Runtime.CoreCLR.pkgproj | 56 + .../Microsoft.NETCore.Runtime.CoreCLR.pkgproj | 10 +- .../Microsoft.NETCore.Runtime.CoreCLR.pkgproj | 10 +- .../win/Microsoft.NETCore.Runtime.CoreCLR.pkgproj | 6 +- .../Microsoft.NETCore.TestHost.builds | 16 + .../Microsoft.NETCore.TestHost.pkgproj | 19 +- .../3.4.3/Microsoft.NETCore.TestHost.pkgproj | 29 + .../linux/Microsoft.NETCore.TestHost.pkgproj | 29 + .../14.04/Microsoft.NETCore.TestHost.pkgproj | 6 +- .../16.04/Microsoft.NETCore.TestHost.pkgproj | 6 +- src/.nuget/optdata/project.json | 11 - src/.nuget/packages.builds | 3 + src/ToolBox/.gitmirrorselective | 1 + src/ToolBox/SOS/NETCore/SymbolReader.cs | 97 +- src/ToolBox/SOS/NETCore/project.json | 2 +- src/ToolBox/SOS/Strike/CMakeLists.txt | 11 +- src/ToolBox/SOS/Strike/ExpressionNode.cpp | 20 +- src/ToolBox/SOS/Strike/ExpressionNode.h | 14 +- src/ToolBox/SOS/Strike/datatarget.cpp | 4 +- src/ToolBox/SOS/Strike/sildasm.cpp | 2 +- src/ToolBox/SOS/Strike/sos_stacktrace.h | 8 +- src/ToolBox/SOS/Strike/sosdocsunix.txt | 1 + src/ToolBox/SOS/Strike/stressLogDump.cpp | 2 +- src/ToolBox/SOS/Strike/strike.cpp | 65 +- src/ToolBox/SOS/Strike/util.cpp | 66 +- src/ToolBox/SOS/Strike/util.h | 16 +- src/ToolBox/SOS/Strike/vm.cpp | 10 +- src/ToolBox/SOS/lldbplugin/CMakeLists.txt | 7 + src/ToolBox/SOS/lldbplugin/services.cpp | 2 + src/ToolBox/SOS/tests/OnCrash.do | 2 - src/ToolBox/SOS/tests/README.md | 43 +- src/ToolBox/SOS/tests/Test.cs | 94 + src/ToolBox/SOS/tests/dumpil.py | 26 - src/ToolBox/SOS/tests/dumpmodule.py | 26 - src/ToolBox/SOS/tests/runprocess.py | 34 - src/ToolBox/SOS/tests/t_cmd_bpmd_clear.py | 62 + src/ToolBox/SOS/tests/t_cmd_bpmd_clearall.py | 62 + src/ToolBox/SOS/tests/t_cmd_bpmd_methoddesc.py | 45 + .../SOS/tests/t_cmd_bpmd_module_function.py | 43 + .../tests/t_cmd_bpmd_module_function_iloffset.py | 43 + .../t_cmd_bpmd_nofuturemodule_module_function.py | 48 + src/ToolBox/SOS/tests/t_cmd_clrstack.py | 36 + src/ToolBox/SOS/tests/t_cmd_clrthreads.py | 31 + src/ToolBox/SOS/tests/t_cmd_clru.py | 46 + src/ToolBox/SOS/tests/t_cmd_dso.py | 31 + src/ToolBox/SOS/tests/t_cmd_dumpclass.py | 68 + src/ToolBox/SOS/tests/t_cmd_dumpheap.py | 31 + src/ToolBox/SOS/tests/t_cmd_dumpil.py | 38 + src/ToolBox/SOS/tests/t_cmd_dumplog.py | 31 + src/ToolBox/SOS/tests/t_cmd_dumpmd.py | 46 + src/ToolBox/SOS/tests/t_cmd_dumpmodule.py | 46 + src/ToolBox/SOS/tests/t_cmd_dumpmt.py | 68 + src/ToolBox/SOS/tests/t_cmd_dumpobj.py | 69 + src/ToolBox/SOS/tests/t_cmd_dumpstack.py | 31 + src/ToolBox/SOS/tests/t_cmd_eeheap.py | 31 + src/ToolBox/SOS/tests/t_cmd_eestack.py | 31 + src/ToolBox/SOS/tests/t_cmd_gcroot.py | 61 + src/ToolBox/SOS/tests/t_cmd_histclear.py | 31 + src/ToolBox/SOS/tests/t_cmd_histinit.py | 31 + src/ToolBox/SOS/tests/t_cmd_histobj.py | 61 + src/ToolBox/SOS/tests/t_cmd_histobjfind.py | 61 + src/ToolBox/SOS/tests/t_cmd_histroot.py | 61 + src/ToolBox/SOS/tests/t_cmd_ip2md.py | 53 + src/ToolBox/SOS/tests/t_cmd_name2ee.py | 46 + src/ToolBox/SOS/tests/t_cmd_pe.py | 28 + src/ToolBox/SOS/tests/t_cmd_sos.py | 31 + src/ToolBox/SOS/tests/t_cmd_soshelp.py | 31 + src/ToolBox/SOS/tests/test_libsosplugin.py | 338 +- src/ToolBox/SOS/tests/testutils.py | 234 +- src/ToolBox/dirs.proj | 2 + .../superpmi/superpmi-shared/compileresult.h | 2 +- .../superpmi/superpmi-shared/icorjitcompilerimpl.h | 4 + .../superpmi/superpmi-shared/icorjitinfoimpl.h | 4 +- src/ToolBox/superpmi/superpmi-shared/logging.cpp | 6 +- src/ToolBox/superpmi/superpmi-shared/lwmlist.h | 1 + src/ToolBox/superpmi/superpmi-shared/mclist.cpp | 2 +- .../superpmi/superpmi-shared/methodcontext.cpp | 34 +- .../superpmi/superpmi-shared/methodcontext.h | 13 +- .../superpmi-shim-collector/icorjitcompiler.cpp | 2 +- .../superpmi-shim-collector/icorjitinfo.cpp | 8 +- .../superpmi-shim-counter/icorjitcompiler.cpp | 2 +- .../superpmi/superpmi-shim-counter/icorjitinfo.cpp | 4 +- .../superpmi-shim-simple/icorjitcompiler.cpp | 2 +- .../superpmi/superpmi-shim-simple/icorjitinfo.cpp | 4 +- src/ToolBox/superpmi/superpmi/icorjitinfo.cpp | 9 +- .../superpmi/superpmi/methodstatsemitter.cpp | 22 +- src/ToolBox/superpmi/superpmi/neardiffer.cpp | 2 +- src/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp | 6 +- src/ToolBox/superpmi/superpmi/superpmi.cpp | 2 + src/ToolBox/superpmi/superpmi/superpmi.h | 3 +- src/classlibnative/bcltype/arraynative.cpp | 4 +- src/classlibnative/bcltype/number.cpp | 6 +- src/classlibnative/bcltype/system.cpp | 12 +- src/classlibnative/bcltype/system.h | 1 + src/classlibnative/float/floatsingle.cpp | 228 + src/classlibnative/inc/floatsingle.h | 19 + src/classlibnative/inc/nlsinfo.h | 13 +- src/classlibnative/nls/nlsinfo.cpp | 131 +- src/coreclr/hosts/coreconsole/coreconsole.cpp | 11 +- src/coreclr/hosts/corerun/corerun.cpp | 9 +- .../hosts/unixcoreruncommon/coreruncommon.cpp | 3 - .../System.Globalization.Native/CMakeLists.txt | 40 +- .../System.Globalization.Native/calendarData.cpp | 2 +- src/corefx/System.Globalization.Native/casing.cpp | 3 +- .../System.Globalization.Native/collation.cpp | 44 +- src/corefx/System.Globalization.Native/errors.h | 8 +- src/corefx/System.Globalization.Native/holders.h | 8 - src/corefx/System.Globalization.Native/icushim.cpp | 226 + src/corefx/System.Globalization.Native/icushim.h | 243 + src/corefx/System.Globalization.Native/idna.cpp | 2 +- src/corefx/System.Globalization.Native/locale.cpp | 51 + src/corefx/System.Globalization.Native/locale.hpp | 2 - .../localeNumberData.cpp | 3 +- .../localeStringData.cpp | 104 +- .../System.Globalization.Native/normalization.cpp | 2 +- .../System.Globalization.Native/timeZoneInfo.cpp | 2 +- src/debug/daccess/daccess.cpp | 18 +- src/debug/daccess/daccess.targets | 6 + src/debug/daccess/dacdbiimpl.cpp | 35 +- src/debug/daccess/dacdbiimpl.h | 10 +- src/debug/daccess/dacfn.cpp | 4 +- src/debug/daccess/enummem.cpp | 11 +- src/debug/daccess/fntableaccess.cpp | 5 +- src/debug/daccess/fntableaccess.h | 3 + src/debug/daccess/nidump.cpp | 21 +- src/debug/daccess/request.cpp | 78 +- src/debug/daccess/request_svr.cpp | 4 +- src/debug/di/breakpoint.cpp | 2 +- src/debug/di/module.cpp | 377 +- src/debug/di/process.cpp | 14 +- src/debug/di/rsenumerator.hpp | 6 +- src/debug/di/rsmain.cpp | 2 + src/debug/di/rspriv.h | 86 +- src/debug/di/rspriv.inl | 2 +- src/debug/di/rsthread.cpp | 11 +- src/debug/di/rstype.cpp | 122 + src/debug/ee/controller.cpp | 6 +- src/debug/ee/controller.h | 14 +- src/debug/ee/debugger.cpp | 13 +- src/debug/ee/debugger.h | 4 +- src/debug/ee/functioninfo.cpp | 43 +- src/debug/ee/i386/dbghelpers.S | 70 + src/debug/ee/wks/CMakeLists.txt | 4 +- src/debug/ildbsymlib/symwrite.h | 3 +- src/debug/inc/common.h | 24 +- src/debug/inc/dacdbiinterface.h | 27 +- src/debug/shared/dbgtransportsession.cpp | 36 +- src/dlls/dbgshim/dbgshim.cpp | 2 +- src/dlls/mscordac/CMakeLists.txt | 8 +- src/dlls/mscordac/mscordac_unixexports.src | 16 +- src/dlls/mscoree/coreclr/coreclr.nativeproj | 6 + src/dlls/mscoree/mscoree.cpp | 2 - src/dlls/mscoree/mscorwks_unixexports.src | 1 + src/dlls/mscoree/unixinterface.cpp | 26 +- src/dlls/mscorpe/ceefilegenwriter.cpp | 19 +- src/gc/CMakeLists.txt | 12 + src/gc/env/gcenv.base.h | 2 +- src/gc/env/gcenv.ee.h | 38 +- src/gc/env/gcenv.object.h | 2 + src/gc/env/gcenv.os.h | 3 +- src/gc/gc.cpp | 972 +- src/gc/gc.h | 571 +- src/gc/gccommon.cpp | 67 +- src/gc/gcee.cpp | 226 +- src/gc/gcenv.ee.standalone.inl | 176 + src/gc/gcenv.unix.cpp | 308 + src/gc/gcenv.windows.cpp | 625 + src/gc/gcimpl.h | 72 +- src/gc/gcinterface.ee.h | 133 + src/gc/gcinterface.h | 622 + src/gc/gcpriv.h | 57 +- src/gc/gcrecord.h | 2 +- src/gc/gcscan.cpp | 23 +- src/gc/gcscan.h | 6 +- src/gc/handletable.cpp | 8 +- src/gc/handletablecache.cpp | 6 + src/gc/handletablecore.cpp | 7 +- src/gc/handletablescan.cpp | 12 +- src/gc/objecthandle.cpp | 137 +- src/gc/objecthandle.h | 7 +- src/gc/sample/CMakeLists.txt | 4 +- src/gc/sample/GCSample.cpp | 10 +- src/gc/sample/GCSample.vcxproj | 7 +- src/gc/sample/GCSample.vcxproj.filters | 2 +- src/gc/sample/gcenv.ee.cpp | 54 +- src/gc/sample/gcenv.h | 13 +- src/gc/sample/gcenv.unix.cpp | 14 - src/gc/sample/gcenv.windows.cpp | 453 - src/gc/softwarewritewatch.cpp | 1 + src/gcdump/gcdump.cpp | 2 + src/gcdump/gcdumpnonx86.cpp | 4 +- src/gcdump/i386/gcdumpx86.cpp | 26 +- src/gcinfo/gcinfoencoder.cpp | 143 +- src/ilasm/CMakeLists.txt | 11 +- src/ilasm/assembler.cpp | 2 +- src/ilasm/main.cpp | 2 +- src/ilasm/prebuilt/asmparse.c | 4907 -- src/ilasm/prebuilt/asmparse.cpp | 4907 ++ src/ildasm/dis.cpp | 6 +- src/ildasm/dres.cpp | 4 +- src/ildasm/gui.cpp | 2 +- src/ildasm/windasm.cpp | 40 +- src/inc/CMakeLists.txt | 9 +- src/inc/bitposition.h | 6 +- src/inc/clrconfigvalues.h | 24 +- src/inc/clrnt.h | 12 +- src/inc/corcompile.h | 16 +- src/inc/cordebug.idl | 135 +- src/inc/corinfo.h | 28 +- src/inc/corjit.h | 170 +- src/inc/corprof.idl | 87 + src/inc/daccess.h | 4 +- src/inc/dacprivate.h | 113 +- src/inc/dacvars.h | 14 +- src/inc/debugreturn.h | 12 +- src/inc/eetwain.h | 54 +- src/inc/eventtrace.h | 22 + src/inc/fstring.h | 3 + src/inc/gcdecoder.cpp | 372 +- src/inc/gcdump.h | 12 +- src/inc/gcinfo.h | 20 +- src/inc/gcinfodecoder.h | 91 +- src/inc/gcinfoencoder.h | 11 +- src/inc/gcinfotypes.h | 95 +- src/inc/jithelpers.h | 17 +- src/inc/livedatatarget.h | 2 + src/inc/longfilepathwrappers.h | 8 +- src/inc/shash.inl | 4 +- src/inc/sortversioning.h | 12 +- src/inc/stacktrace.h | 6 +- src/inc/stresslog.h | 2 +- src/inc/utilcode.h | 20 +- src/inc/winwrap.h | 7 - src/inc/{xmlparser_i.c => xmlparser_i.cpp} | 0 src/inc/zapper.h | 2 +- src/ipcman/ipcshared.h | 4 +- src/jit/CMakeLists.txt | 27 +- src/jit/ICorJitInfo_API_names.h | 171 + src/jit/ICorJitInfo_API_wrapper.hpp | 1666 + src/jit/assertionprop.cpp | 119 +- src/jit/bitsetasuint64.h | 2 +- src/jit/block.cpp | 37 +- src/jit/block.h | 24 +- src/jit/codegen.h | 36 +- src/jit/codegenarm.cpp | 1078 +- src/jit/codegenarm64.cpp | 1467 +- src/jit/codegenclassic.h | 7 - src/jit/codegencommon.cpp | 622 +- src/jit/codegeninterface.h | 6 +- src/jit/codegenlegacy.cpp | 448 +- src/jit/codegenlinear.cpp | 1773 + src/jit/codegenlinear.h | 78 +- src/jit/codegenxarch.cpp | 9227 ++- src/{ToolBox => jit/compatjit}/.gitmirror | 0 src/jit/compatjit/CMakeLists.txt | 66 + src/jit/compiler.cpp | 1399 +- src/jit/compiler.h | 297 +- src/jit/compiler.hpp | 110 +- src/jit/compphases.h | 15 +- src/jit/crossgen/CMakeLists.txt | 4 +- src/jit/decomposelongs.cpp | 1056 +- src/jit/decomposelongs.h | 12 +- src/jit/dll/CMakeLists.txt | 10 +- src/jit/dll/jit.nativeproj | 6 +- src/jit/earlyprop.cpp | 42 +- src/jit/ee_il_dll.cpp | 53 +- src/jit/ee_il_dll.hpp | 4 + src/jit/emit.cpp | 80 +- src/jit/emit.h | 27 +- src/jit/emitarm.cpp | 20 +- src/jit/emitarm64.cpp | 2 - src/jit/emitxarch.cpp | 710 +- src/jit/emitxarch.h | 118 +- src/jit/error.cpp | 4 +- src/jit/error.h | 199 +- src/jit/flowgraph.cpp | 2349 +- src/jit/gcencode.cpp | 267 +- src/jit/gentree.cpp | 1311 +- src/jit/gentree.h | 563 +- src/jit/gschecks.cpp | 48 +- src/jit/gtlist.h | 333 +- src/jit/gtstructs.h | 4 +- src/jit/importer.cpp | 760 +- src/jit/inline.cpp | 138 +- src/jit/inline.def | 10 +- src/jit/inline.h | 17 +- src/jit/inlinepolicy.cpp | 232 +- src/jit/inlinepolicy.h | 98 +- src/jit/instr.cpp | 14 +- src/jit/instr.h | 10 +- src/jit/instrsxarch.h | 19 +- src/jit/jit.h | 49 +- src/jit/jit.settings.targets | 3 +- src/jit/jitconfig.h | 2 + src/jit/jitconfigvalues.h | 50 +- src/jit/jitee.h | 264 + src/jit/jiteh.cpp | 12 +- src/jit/jitgcinfo.h | 3 + src/jit/lclvars.cpp | 97 +- src/{ => jit/legacyjit}/.gitmirror | 0 src/jit/legacyjit/CMakeLists.txt | 62 + src/jit/lir.cpp | 49 +- src/jit/liveness.cpp | 37 +- src/jit/loopcloning.cpp | 2 +- src/jit/lower.cpp | 742 +- src/jit/lower.h | 18 +- src/jit/lowerarm.cpp | 138 +- src/jit/lowerarm64.cpp | 149 +- src/jit/lowerxarch.cpp | 1104 +- src/jit/lsra.cpp | 1051 +- src/jit/lsra.h | 87 +- src/jit/morph.cpp | 1656 +- src/jit/nodeinfo.h | 47 +- src/jit/optcse.cpp | 88 +- src/jit/optimizer.cpp | 688 +- src/jit/protojit/CMakeLists.txt | 8 +- src/jit/rangecheck.cpp | 5 +- src/jit/rationalize.cpp | 250 +- src/jit/regalloc.cpp | 208 +- src/jit/regalloc.h | 24 +- src/jit/registerfp.cpp | 6 - src/jit/regset.cpp | 10 + src/jit/scopeinfo.cpp | 18 +- src/jit/sideeffects.h | 6 + src/jit/simd.cpp | 137 +- src/jit/simd.h | 15 +- src/jit/simdcodegenxarch.cpp | 698 +- src/jit/simdintrinsiclist.h | 9 +- src/jit/ssabuilder.cpp | 223 +- src/jit/stackfp.cpp | 23 +- src/jit/standalone/CMakeLists.txt | 21 +- src/jit/target.h | 47 +- src/jit/tinyarray.h | 2 +- src/jit/unwindamd64.cpp | 15 +- src/jit/utils.cpp | 24 +- src/jit/valuenum.cpp | 246 +- src/jit/valuenum.h | 59 +- src/jit/valuenumfuncs.h | 4 +- src/md/ceefilegen/cceegen.cpp | 24 +- src/md/winmd/adapter.cpp | 28 +- src/md/winmd/inc/adapter.h | 2 +- src/md/winmd/winmdimport.cpp | 30 +- src/mscorlib/Common/PinnableBufferCache.cs | 97 - src/mscorlib/System.Private.CoreLib.csproj | 4 + src/mscorlib/System.Private.CoreLib.sln | 5 + src/mscorlib/corefx/Debug.cs | 29 + src/mscorlib/corefx/Interop/Unix/Interop.Errors.cs | 207 + .../corefx/Interop/Unix/Interop.IOErrors.cs | 170 + .../corefx/Interop/Unix/Interop.Libraries.cs | 7 + .../Interop.Collation.cs | 5 +- .../System.Globalization.Native/Interop.Idna.cs | 21 + .../System.Globalization.Native/Interop.Locale.cs | 3 + .../Interop.Normalization.cs | 19 + .../Interop.ResultCode.cs | 1 + .../Interop/Unix/System.Native/Interop.Close.cs | 15 + .../Interop/Unix/System.Native/Interop.FLock.cs | 31 + .../Interop/Unix/System.Native/Interop.FSync.cs | 15 + .../Unix/System.Native/Interop.FTruncate.cs | 15 + .../Interop/Unix/System.Native/Interop.Fcntl.cs | 21 + .../Interop/Unix/System.Native/Interop.GetCwd.cs | 74 + .../Unix/System.Native/Interop.GetUnixName.cs | 21 + .../Interop/Unix/System.Native/Interop.LSeek.cs | 22 + .../Interop/Unix/System.Native/Interop.MksTemps.cs | 17 + .../Interop/Unix/System.Native/Interop.Open.cs | 15 + .../Unix/System.Native/Interop.OpenFlags.cs | 27 + .../Interop/Unix/System.Native/Interop.PathConf.cs | 73 + .../Unix/System.Native/Interop.Permissions.cs | 32 + .../Unix/System.Native/Interop.PosixFAdvise.cs | 36 + .../Interop/Unix/System.Native/Interop.Read.cs | 25 + .../Interop/Unix/System.Native/Interop.Stat.cs | 59 + .../Interop/Unix/System.Native/Interop.Unlink.cs | 15 + .../Interop/Unix/System.Native/Interop.Write.cs | 27 + .../Windows/BCrypt/Interop.BCryptGenRandom.cs | 26 + .../Interop/Windows/BCrypt/Interop.NTSTATUS.cs | 19 + .../Windows/Crypt32/Interop.CryptProtectMemory.cs | 22 + .../corefx/Interop/Windows/Interop.BOOL.cs | 21 + .../corefx/Interop/Windows/Interop.Libraries.cs | 82 + .../Interop/Windows/NtDll/Interop.ZeroMemory.cs | 19 + .../Interop/Windows/mincore/Interop.CancelIoEx.cs | 16 + .../Interop/Windows/mincore/Interop.CloseHandle.cs | 16 + .../Interop/Windows/mincore/Interop.CreateFile.cs | 40 + .../Interop/Windows/mincore/Interop.Errors.cs | 74 + .../Windows/mincore/Interop.FileOperations.cs | 35 + .../Interop/Windows/mincore/Interop.FileTypes.cs | 16 + .../Windows/mincore/Interop.FlushFileBuffers.cs | 17 + .../Windows/mincore/Interop.FormatMessage.cs | 112 + .../Interop.GetFileInformationByHandleEx.cs | 26 + .../mincore/Interop.GetFileType_SafeHandle.cs | 15 + .../Windows/mincore/Interop.GetFullPathNameW.cs | 18 + .../Windows/mincore/Interop.GetLongPathNameW.cs | 18 + .../Windows/mincore/Interop.GetTempFileNameW.cs | 16 + .../Windows/mincore/Interop.GetTempPathW.cs | 16 + .../corefx/Interop/Windows/mincore/Interop.Idna.cs | 37 + .../Interop/Windows/mincore/Interop.LockFile.cs | 20 + .../mincore/Interop.ReadFile_SafeHandle_IntPtr.cs | 21 + ...Interop.ReadFile_SafeHandle_NativeOverlapped.cs | 22 + .../Windows/mincore/Interop.SECURITY_ATTRIBUTES.cs | 21 + .../Windows/mincore/Interop.SafeCreateFile.cs | 45 + .../Windows/mincore/Interop.SecurityOptions.cs | 18 + .../Windows/mincore/Interop.SetEndOfFile.cs | 15 + .../Windows/mincore/Interop.SetErrorMode.cs | 14 + .../mincore/Interop.SetFileInformationByHandle.cs | 72 + .../Windows/mincore/Interop.SetFilePointerEx.cs | 15 + .../Windows/mincore/Interop.ThreadPoolIO.cs | 27 + .../Windows/mincore/Interop.UnsafeCreateFile.cs | 25 + .../Windows/mincore/Interop.WideCharToMultiByte.cs | 22 + .../mincore/Interop.WriteFile_SafeHandle_IntPtr.cs | 24 + ...nterop.WriteFile_SafeHandle_NativeOverlapped.cs | 22 + .../Windows/oleaut32/Interop.SysAllocStringLen.cs | 16 + .../Windows/oleaut32/Interop.SysStringLen.cs | 22 + .../Win32/SafeHandles/SafeFileHandle.Unix.cs | 122 + .../Win32/SafeHandles/SafeFileHandle.Windows.cs | 50 + .../Win32/SafeHandles/SafeThreadPoolIOHandle.cs | 28 + src/mscorlib/corefx/SR.cs | 823 +- src/mscorlib/corefx/System/Buffers/ArrayPool.cs | 113 + .../corefx/System/Buffers/ArrayPoolEventSource.cs | 78 + .../corefx/System/Buffers/ConfigurableArrayPool.cs | 265 + .../TlsOverPerCoreLockedStacksArrayPool.Unix.cs | 28 + .../TlsOverPerCoreLockedStacksArrayPool.Windows.cs | 20 + .../Buffers/TlsOverPerCoreLockedStacksArrayPool.cs | 328 + src/mscorlib/corefx/System/Buffers/Utilities.cs | 35 + .../corefx/System/Globalization/Calendar.cs | 42 +- .../System/Globalization/CalendarAlgorithmType.cs | 20 + .../System/Globalization/CalendarData.Unix.cs | 3 +- .../corefx/System/Globalization/CalendarData.cs | 8 +- .../Globalization/CalendricalCalculationsHelper.cs | 31 +- .../corefx/System/Globalization/CharUnicodeInfo.cs | 110 +- .../System/Globalization/CharUnicodeInfoData.cs | 25 + .../Globalization/ChineseLunisolarCalendar.cs | 4 +- .../System/Globalization/CompareInfo.Unix.cs | 140 +- .../System/Globalization/CompareInfo.Windows.cs | 78 +- .../corefx/System/Globalization/CompareInfo.cs | 283 +- .../System/Globalization/CultureData.Unix.cs | 164 +- .../System/Globalization/CultureData.Windows.cs | 132 +- .../corefx/System/Globalization/CultureData.cs | 392 +- .../System/Globalization/CultureInfo.Windows.cs | 6 +- .../corefx/System/Globalization/CultureInfo.cs | 528 +- .../Globalization/CultureNotFoundException.cs | 35 +- .../corefx/System/Globalization/CultureTypes.cs | 28 + .../System/Globalization/DateTimeFormatInfo.cs | 343 +- .../corefx/System/Globalization/DayLightTime.cs | 49 +- .../corefx/System/Globalization/DigitShapes.cs | 17 + .../Globalization/EastAsianLunisolarCalendar.cs | 41 +- .../System/Globalization/GregorianCalendar.cs | 57 +- .../Globalization/GregorianCalendarHelper.cs | 24 +- .../corefx/System/Globalization/HebrewCalendar.cs | 43 +- .../corefx/System/Globalization/HebrewNumber.cs | 11 +- .../System/Globalization/HijriCalendar.Win32.cs | 86 + .../System/Globalization/HijriCalendar.WinRT.cs | 16 + .../System/Globalization/HijriCalendar.Windows.cs | 16 - .../corefx/System/Globalization/HijriCalendar.cs | 31 +- .../corefx/System/Globalization/IdnMapping.Unix.cs | 134 + .../System/Globalization/IdnMapping.Windows.cs | 113 + .../corefx/System/Globalization/IdnMapping.cs | 152 + .../System/Globalization/JapaneseCalendar.Unix.cs | 3 - .../System/Globalization/JapaneseCalendar.Win32.cs | 209 + ...lendar.Windows.cs => JapaneseCalendar.WinRT.cs} | 0 .../System/Globalization/JapaneseCalendar.cs | 18 +- .../corefx/System/Globalization/JulianCalendar.cs | 37 +- .../corefx/System/Globalization/KoreanCalendar.cs | 11 +- .../Globalization/KoreanLunisolarCalendar.cs | 4 +- .../corefx/System/Globalization/LocaleData.Unix.cs | 4572 ++ .../System/Globalization/NumberFormatInfo.cs | 91 +- .../corefx/System/Globalization/PersianCalendar.cs | 54 +- .../corefx/System/Globalization/RegionInfo.cs | 117 +- src/mscorlib/corefx/System/Globalization/STUBS.cs | 180 - .../corefx/System/Globalization/SortKey.cs | 209 + .../corefx/System/Globalization/SortVersion.cs | 101 + .../corefx/System/Globalization/StringInfo.cs | 89 +- .../corefx/System/Globalization/TaiwanCalendar.cs | 13 +- .../System/Globalization/TextElementEnumerator.cs | 10 +- .../corefx/System/Globalization/TextInfo.Unix.cs | 5 +- .../System/Globalization/TextInfo.Windows.cs | 6 +- .../corefx/System/Globalization/TextInfo.cs | 324 +- .../System/Globalization/ThaiBuddhistCalendar.cs | 11 +- .../System/Globalization/UmAlQuraCalendar.cs | 40 +- src/mscorlib/corefx/System/HResults.cs | 236 + src/mscorlib/corefx/System/IO/Error.cs | 44 + .../corefx/System/IO/FileStream.NetStandard17.cs | 76 + src/mscorlib/corefx/System/IO/FileStream.Unix.cs | 934 + src/mscorlib/corefx/System/IO/FileStream.Win32.cs | 1770 + src/mscorlib/corefx/System/IO/FileStream.cs | 654 + .../System/IO/FileStreamCompletionSource.Win32.cs | 221 + src/mscorlib/corefx/System/IO/Path.Unix.cs | 256 + src/mscorlib/corefx/System/IO/Path.Win32.cs | 36 + src/mscorlib/corefx/System/IO/Path.Windows.cs | 153 + src/mscorlib/corefx/System/IO/Path.cs | 578 + .../corefx/System/IO/PathHelper.Windows.cs | 389 + .../System/IO/PathInternal.CaseSensitivity.cs | 75 + src/mscorlib/corefx/System/IO/PathInternal.Unix.cs | 122 + .../System/IO/PathInternal.Windows.StringBuffer.cs | 89 + .../corefx/System/IO/PathInternal.Windows.cs | 482 + src/mscorlib/corefx/System/IO/PathInternal.cs | 230 + src/mscorlib/corefx/System/IO/Win32Marshal.cs | 134 + .../System/Runtime/InteropServices/NativeBuffer.cs | 157 + .../Runtime/InteropServices/SafeHeapHandle.cs | 109 + .../Runtime/InteropServices/SafeHeapHandleCache.cs | 97 + .../System/Runtime/InteropServices/StringBuffer.cs | 354 + .../System/Security/CryptographicException.cs | 44 + .../corefx/System/Security/SafeBSTRHandle.cs | 81 + .../corefx/System/Security/SecureString.Unix.cs | 295 + .../corefx/System/Security/SecureString.Windows.cs | 310 + .../corefx/System/Security/SecureString.cs | 189 + .../System/Threading/ClrThreadPoolBoundHandle.cs | 319 + .../ClrThreadPoolBoundHandleOverlapped.cs | 52 + .../ClrThreadPoolPreAllocatedOverlapped.cs | 105 + .../System/Threading/DeferredDisposableLifetime.cs | 116 + src/mscorlib/facade/TypeForwards.cs | 37 - src/mscorlib/facade/mscorlib.csproj | 37 +- src/mscorlib/facade/project.json | 1 + src/mscorlib/model.xml | 1110 +- src/mscorlib/mscorlib.shared.sources.props | 220 +- src/mscorlib/ref/mscorlib.cs | 839 +- .../Runtime/Augments/EnvironmentAugments.cs | 7 + .../src/Internal/Runtime/Augments/RuntimeThread.cs | 198 + src/mscorlib/src/Microsoft/Win32/OAVariantLib.cs | 6 +- src/mscorlib/src/Microsoft/Win32/Registry.cs | 24 +- src/mscorlib/src/Microsoft/Win32/RegistryKey.cs | 296 +- .../Microsoft/Win32/SafeHandles/SafeFileHandle.cs | 43 - .../Win32/SafeHandles/SafeFileMappingHandle.cs | 4 - .../Microsoft/Win32/SafeHandles/SafeFindHandle.cs | 3 - .../Win32/SafeHandles/SafeLibraryHandle.cs | 12 - .../Win32/SafeHandles/SafeLocalAllocHandle.cs | 6 +- .../Win32/SafeHandles/SafeRegistryHandle.cs | 4 - .../Win32/SafeHandles/SafeViewOfFileHandle.cs | 4 - .../Microsoft/Win32/SafeHandles/SafeWaitHandle.cs | 2 - .../Win32/SafeHandles/Win32SafeHandles.cs | 25 - .../src/Microsoft/Win32/UnsafeNativeMethods.cs | 8 - src/mscorlib/src/Microsoft/Win32/Win32Native.cs | 115 +- src/mscorlib/src/System.Private.CoreLib.txt | 1251 +- src/mscorlib/src/System/Action.cs | 43 +- src/mscorlib/src/System/Activator.cs | 136 +- src/mscorlib/src/System/AggregateException.cs | 17 +- src/mscorlib/src/System/AppContext/AppContext.cs | 56 +- .../AppContext/AppContextDefaultValues.Defaults.cs | 12 +- .../System/AppContext/AppContextDefaultValues.cs | 6 - .../src/System/AppContext/AppContextSwitches.cs | 30 - src/mscorlib/src/System/AppDomain.cs | 2190 +- src/mscorlib/src/System/AppDomainManager.cs | 171 +- src/mscorlib/src/System/AppDomainSetup.cs | 469 +- src/mscorlib/src/System/ApplicationId.cs | 6 +- src/mscorlib/src/System/ArgIterator.cs | 11 - src/mscorlib/src/System/ArgumentException.cs | 3 +- src/mscorlib/src/System/ArgumentNullException.cs | 1 - .../src/System/ArgumentOutOfRangeException.cs | 3 +- src/mscorlib/src/System/Array.cs | 433 +- src/mscorlib/src/System/ArraySegment.cs | 96 +- src/mscorlib/src/System/Attribute.cs | 137 +- src/mscorlib/src/System/BCLDebug.cs | 32 - src/mscorlib/src/System/BadImageFormatException.cs | 3 - src/mscorlib/src/System/BitConverter.cs | 61 +- src/mscorlib/src/System/Boolean.cs | 2 +- src/mscorlib/src/System/Buffer.cs | 50 +- src/mscorlib/src/System/ByReference.cs | 31 + src/mscorlib/src/System/Byte.cs | 4 - src/mscorlib/src/System/CLRConfig.cs | 2 - src/mscorlib/src/System/CfgParser.cs | 14 +- src/mscorlib/src/System/Char.cs | 94 +- src/mscorlib/src/System/Collections/ArrayList.cs | 179 +- src/mscorlib/src/System/Collections/BitArray.cs | 524 - .../src/System/Collections/CollectionBase.cs | 10 +- src/mscorlib/src/System/Collections/Comparer.cs | 5 +- .../src/System/Collections/CompatibleComparer.cs | 2 +- .../Collections/Concurrent/ConcurrentDictionary.cs | 216 +- .../Collections/Concurrent/ConcurrentQueue.cs | 21 +- .../Collections/Concurrent/ConcurrentStack.cs | 91 +- .../Concurrent/IProducerConsumerCollection.cs | 2 +- .../Collections/Concurrent/OrderablePartitioner.cs | 1 - .../System/Collections/Concurrent/Partitioner.cs | 1 - .../Collections/Concurrent/PartitionerStatic.cs | 104 +- .../src/System/Collections/DictionaryEntry.cs | 7 + .../Collections/EmptyReadOnlyDictionaryInternal.cs | 20 +- .../System/Collections/Generic/ArraySortHelper.cs | 452 +- .../src/System/Collections/Generic/Comparer.cs | 18 +- .../src/System/Collections/Generic/DebugView.cs | 2 +- .../src/System/Collections/Generic/Dictionary.cs | 101 +- .../System/Collections/Generic/EqualityComparer.cs | 171 +- .../src/System/Collections/Generic/KeyValuePair.cs | 17 + .../src/System/Collections/Generic/List.cs | 116 +- src/mscorlib/src/System/Collections/Hashtable.cs | 187 +- .../System/Collections/ListDictionaryInternal.cs | 30 +- .../System/Collections/ObjectModel/Collection.cs | 8 +- .../Collections/ObjectModel/KeyedCollection.cs | 4 +- .../Collections/ObjectModel/ReadOnlyCollection.cs | 8 +- .../Collections/ObjectModel/ReadOnlyDictionary.cs | 14 +- src/mscorlib/src/System/Collections/SortedList.cs | 39 +- src/mscorlib/src/System/Collections/Stack.cs | 13 +- src/mscorlib/src/System/CompatibilitySwitches.cs | 72 - src/mscorlib/src/System/ContextBoundObject.cs | 24 - src/mscorlib/src/System/ContextStaticAttribute.cs | 32 - src/mscorlib/src/System/Convert.cs | 80 +- src/mscorlib/src/System/Currency.cs | 2 - src/mscorlib/src/System/CurrentTimeZone.cs | 276 +- src/mscorlib/src/System/DBNull.cs | 1 - src/mscorlib/src/System/DateTime.cs | 86 +- src/mscorlib/src/System/DateTimeOffset.cs | 34 +- src/mscorlib/src/System/Decimal.cs | 60 +- src/mscorlib/src/System/DefaultBinder.cs | 26 +- src/mscorlib/src/System/Delegate.cs | 107 +- .../src/System/DelegateSerializationHolder.cs | 29 +- src/mscorlib/src/System/Diagnostics/Assert.cs | 18 - .../src/System/Diagnostics/AssertFilter.cs | 1 - .../src/System/Diagnostics/Contracts/Contracts.cs | 19 +- .../System/Diagnostics/Contracts/ContractsBCL.cs | 62 +- src/mscorlib/src/System/Diagnostics/Debugger.cs | 9 - .../src/System/Diagnostics/DebuggerAttributes.cs | 20 +- .../System/Diagnostics/Eventing/ActivityTracker.cs | 13 +- .../System/Diagnostics/Eventing/EventProvider.cs | 66 +- .../src/System/Diagnostics/Eventing/EventSource.cs | 465 +- .../Diagnostics/Eventing/EventSource_CoreCLR.cs | 4 - .../Eventing/TraceLogging/DataCollector.cs | 1 - .../Eventing/TraceLogging/EventPayload.cs | 9 +- .../Eventing/TraceLogging/EventSourceActivity.cs | 2 +- .../Eventing/TraceLogging/FieldMetadata.cs | 2 +- .../Eventing/TraceLogging/PropertyValue.cs | 7 +- .../Eventing/TraceLogging/SimpleTypeInfos.cs | 3 +- .../Diagnostics/Eventing/TraceLogging/Statics.cs | 2 +- .../TraceLogging/TraceLoggingDataCollector.cs | 1 - .../TraceLogging/TraceLoggingEventSource.cs | 18 +- .../TraceLogging/TraceLoggingEventTypes.cs | 10 +- .../TraceLogging/TraceLoggingMetadataCollector.cs | 6 +- .../Eventing/TraceLogging/TraceLoggingTypeInfo.cs | 4 +- .../Diagnostics/Eventing/XplatEventLogger.cs | 28 +- src/mscorlib/src/System/Diagnostics/LogSwitch.cs | 7 +- src/mscorlib/src/System/Diagnostics/Stackframe.cs | 23 +- src/mscorlib/src/System/Diagnostics/Stacktrace.cs | 79 +- .../System/Diagnostics/SymbolStore/ISymWriter.cs | 30 - src/mscorlib/src/System/Diagnostics/log.cs | 5 +- src/mscorlib/src/System/Double.cs | 8 - src/mscorlib/src/System/Empty.cs | 3 +- src/mscorlib/src/System/Enum.cs | 174 +- src/mscorlib/src/System/Environment.cs | 1154 +- src/mscorlib/src/System/Exception.cs | 88 +- src/mscorlib/src/System/FormattableString.cs | 2 +- src/mscorlib/src/System/GC.cs | 172 +- src/mscorlib/src/System/Globalization/Calendar.cs | 18 +- .../src/System/Globalization/CalendarData.cs | 6 +- .../Globalization/CalendricalCalculationsHelper.cs | 17 +- .../src/System/Globalization/CharUnicodeInfo.cs | 66 +- .../Globalization/ChineseLunisolarCalendar.cs | 4 +- .../src/System/Globalization/CompareInfo.cs | 171 +- .../src/System/Globalization/CultureData.cs | 445 +- .../src/System/Globalization/CultureInfo.cs | 167 +- .../Globalization/CultureNotFoundException.cs | 3 +- .../src/System/Globalization/DateTimeFormat.cs | 134 +- .../src/System/Globalization/DateTimeFormatInfo.cs | 248 +- .../Globalization/DateTimeFormatInfoScanner.cs | 3 - .../src/System/Globalization/DateTimeParse.cs | 90 +- .../src/System/Globalization/DaylightTime.cs | 23 +- .../Globalization/EastAsianLunisolarCalendar.cs | 26 +- .../src/System/Globalization/EncodingDataItem.cs | 7 +- .../src/System/Globalization/EncodingTable.Unix.cs | 9 +- .../src/System/Globalization/EncodingTable.cs | 16 +- .../System/Globalization/GlobalizationAssembly.cs | 8 +- .../src/System/Globalization/GregorianCalendar.cs | 50 +- .../Globalization/GregorianCalendarHelper.cs | 24 +- .../src/System/Globalization/HebrewCalendar.cs | 31 +- .../src/System/Globalization/HebrewNumber.cs | 3 +- .../src/System/Globalization/HijriCalendar.cs | 24 +- .../src/System/Globalization/IdnMapping.cs | 156 +- .../src/System/Globalization/JapaneseCalendar.cs | 5 +- .../src/System/Globalization/JulianCalendar.cs | 18 +- .../src/System/Globalization/KoreanCalendar.cs | 2 +- .../Globalization/KoreanLunisolarCalendar.cs | 4 +- .../src/System/Globalization/NumberFormatInfo.cs | 66 +- .../src/System/Globalization/PersianCalendar.cs | 37 +- .../src/System/Globalization/RegionInfo.cs | 200 +- src/mscorlib/src/System/Globalization/SortKey.cs | 7 +- .../src/System/Globalization/StringInfo.cs | 29 +- .../src/System/Globalization/TaiwanCalendar.cs | 4 +- .../System/Globalization/TextElementEnumerator.cs | 7 +- src/mscorlib/src/System/Globalization/TextInfo.cs | 77 +- .../System/Globalization/ThaiBuddhistCalendar.cs | 2 +- .../src/System/Globalization/TimeSpanFormat.cs | 30 +- .../src/System/Globalization/TimeSpanParse.cs | 33 +- .../src/System/Globalization/UmAlQuraCalendar.cs | 31 +- src/mscorlib/src/System/Guid.cs | 37 +- src/mscorlib/src/System/IAppDomain.cs | 246 +- src/mscorlib/src/System/IAppDomainPauseManager.cs | 15 +- src/mscorlib/src/System/IO/BinaryReader.cs | 46 +- src/mscorlib/src/System/IO/BinaryWriter.cs | 37 +- src/mscorlib/src/System/IO/BufferedStream.cs | 1320 - src/mscorlib/src/System/IO/Directory.cs | 642 +- src/mscorlib/src/System/IO/DirectoryInfo.cs | 265 +- src/mscorlib/src/System/IO/DriveInfo.cs | 281 - src/mscorlib/src/System/IO/EncodingCache.cs | 13 + src/mscorlib/src/System/IO/File.cs | 658 +- src/mscorlib/src/System/IO/FileAttributes.cs | 20 +- src/mscorlib/src/System/IO/FileInfo.cs | 207 +- src/mscorlib/src/System/IO/FileLoadException.cs | 14 - .../src/System/IO/FileNotFoundException.cs | 11 - src/mscorlib/src/System/IO/FileSecurityState.cs | 133 - .../src/System/IO/FileSecurityStateAccess.cs | 32 - src/mscorlib/src/System/IO/FileStream.cs | 2695 - src/mscorlib/src/System/IO/FileSystemEnumerable.cs | 185 +- src/mscorlib/src/System/IO/FileSystemInfo.cs | 137 +- src/mscorlib/src/System/IO/LongPathHelper.cs | 521 - src/mscorlib/src/System/IO/MemoryStream.cs | 112 +- src/mscorlib/src/System/IO/Path.cs | 1435 - src/mscorlib/src/System/IO/PathHelper.cs | 448 - src/mscorlib/src/System/IO/PathInternal.cs | 806 - .../src/System/IO/PinnedBufferMemoryStream.cs | 6 +- src/mscorlib/src/System/IO/Stream.cs | 144 +- .../src/System/IO/StreamHelpers.CopyValidation.cs | 46 + src/mscorlib/src/System/IO/StreamReader.cs | 100 +- src/mscorlib/src/System/IO/StreamWriter.cs | 175 +- src/mscorlib/src/System/IO/StringReader.cs | 187 - src/mscorlib/src/System/IO/StringWriter.cs | 196 - src/mscorlib/src/System/IO/TextReader.cs | 36 +- src/mscorlib/src/System/IO/TextWriter.cs | 37 +- .../src/System/IO/UnmanagedMemoryAccessor.cs | 215 +- .../src/System/IO/UnmanagedMemoryStream.cs | 187 +- .../src/System/IO/UnmanagedMemoryStreamWrapper.cs | 9 +- .../src/System/IO/__DebugOutputTextWriter.cs | 76 - src/mscorlib/src/System/IO/__Error.cs | 12 +- src/mscorlib/src/System/Int16.cs | 3 - src/mscorlib/src/System/Int32.cs | 4 - src/mscorlib/src/System/Int64.cs | 4 - src/mscorlib/src/System/IntPtr.cs | 27 +- src/mscorlib/src/System/Internal.cs | 19 +- .../src/System/InvalidTimeZoneException.cs | 12 +- src/mscorlib/src/System/Lazy.cs | 23 +- src/mscorlib/src/System/LowLevelConsole.cs | 3 - src/mscorlib/src/System/MarshalByRefObject.cs | 245 +- src/mscorlib/src/System/Math.cs | 191 +- src/mscorlib/src/System/MathF.cs | 253 + src/mscorlib/src/System/MissingFieldException.cs | 1 - src/mscorlib/src/System/MissingMemberException.cs | 5 +- src/mscorlib/src/System/MissingMethodException.cs | 1 - src/mscorlib/src/System/MulticastDelegate.cs | 40 +- .../src/System/NotFiniteNumberException.cs | 3 +- src/mscorlib/src/System/Nullable.cs | 2 +- src/mscorlib/src/System/Number.cs | 191 +- .../src/System/Numerics/Hashing/HashHelpers.cs | 19 + src/mscorlib/src/System/Object.cs | 48 +- src/mscorlib/src/System/ObjectDisposedException.cs | 1 - src/mscorlib/src/System/OleAutBinder.cs | 21 - src/mscorlib/src/System/OperatingSystem.cs | 7 +- src/mscorlib/src/System/ParseNumbers.cs | 8 - src/mscorlib/src/System/Progress.cs | 4 +- src/mscorlib/src/System/Random.cs | 74 +- src/mscorlib/src/System/ReadOnlySpan.cs | 397 + src/mscorlib/src/System/Reflection/Assembly.cs | 1048 +- .../src/System/Reflection/AssemblyAttributes.cs | 2 +- src/mscorlib/src/System/Reflection/AssemblyName.cs | 274 +- src/mscorlib/src/System/Reflection/Associates.cs | 9 +- .../src/System/Reflection/ComInterfaces.cs | 572 +- .../src/System/Reflection/ConstructorInfo.cs | 145 +- .../src/System/Reflection/CustomAttribute.cs | 168 +- .../src/System/Reflection/Emit/AQNBuilder.cs | 30 - .../src/System/Reflection/Emit/AssemblyBuilder.cs | 1145 +- .../Reflection/Emit/AssemblyBuilderAccess.cs | 6 +- .../System/Reflection/Emit/AssemblyBuilderData.cs | 40 +- .../src/System/Reflection/Emit/ComInterfaces.cs | 173 +- .../System/Reflection/Emit/ConstructorBuilder.cs | 61 - .../Reflection/Emit/CustomAttributeBuilder.cs | 143 +- .../System/Reflection/Emit/DynamicILGenerator.cs | 69 +- .../src/System/Reflection/Emit/DynamicMethod.cs | 224 +- .../src/System/Reflection/Emit/EnumBuilder.cs | 30 +- .../src/System/Reflection/Emit/EventBuilder.cs | 47 +- .../src/System/Reflection/Emit/FieldBuilder.cs | 54 +- .../src/System/Reflection/Emit/FlowControl.cs | 3 - .../Reflection/Emit/GenericTypeParameterBuilder.cs | 3 - .../src/System/Reflection/Emit/ILGenerator.cs | 111 +- .../src/System/Reflection/Emit/ISymWrapperCore.cs | 136 - .../src/System/Reflection/Emit/LocalBuilder.cs | 22 - .../src/System/Reflection/Emit/MethodBuilder.cs | 165 +- .../src/System/Reflection/Emit/ModuleBuilder.cs | 489 +- .../System/Reflection/Emit/ModuleBuilderData.cs | 6 +- src/mscorlib/src/System/Reflection/Emit/Opcode.cs | 118 - .../src/System/Reflection/Emit/OpcodeType.cs | 3 - .../src/System/Reflection/Emit/OperandType.cs | 3 - .../src/System/Reflection/Emit/ParameterBuilder.cs | 35 +- .../src/System/Reflection/Emit/PropertyBuilder.cs | 49 +- .../src/System/Reflection/Emit/SignatureHelper.cs | 69 +- .../src/System/Reflection/Emit/SymbolMethod.cs | 1 - .../src/System/Reflection/Emit/SymbolType.cs | 2 +- .../src/System/Reflection/Emit/TypeBuilder.cs | 324 +- .../Reflection/Emit/TypeBuilderInstantiation.cs | 4 +- .../src/System/Reflection/Emit/UnmanagedMarshal.cs | 1 - .../Emit/XXXOnTypeBuilderInstantiation.cs | 13 +- src/mscorlib/src/System/Reflection/EventInfo.cs | 55 +- src/mscorlib/src/System/Reflection/FieldInfo.cs | 98 +- .../System/Reflection/IntrospectionExtensions.cs | 23 +- .../Reflection/InvalidFilterCriteriaException.cs | 4 - .../src/System/Reflection/LoaderAllocator.cs | 2 - src/mscorlib/src/System/Reflection/MdConstant.cs | 1 - src/mscorlib/src/System/Reflection/MdImport.cs | 55 - src/mscorlib/src/System/Reflection/MemberInfo.cs | 31 - .../Reflection/MemberInfoSerializationHolder.cs | 6 +- .../Reflection/Metadata/AssemblyExtensions.cs | 4 +- src/mscorlib/src/System/Reflection/MethodBase.cs | 50 +- src/mscorlib/src/System/Reflection/MethodBody.cs | 3 +- src/mscorlib/src/System/Reflection/MethodInfo.cs | 164 +- src/mscorlib/src/System/Reflection/Missing.cs | 3 +- src/mscorlib/src/System/Reflection/Module.cs | 158 +- .../src/System/Reflection/ParameterInfo.cs | 90 +- src/mscorlib/src/System/Reflection/Pointer.cs | 14 +- src/mscorlib/src/System/Reflection/PropertyInfo.cs | 51 +- .../src/System/Reflection/ReflectionContext.cs | 2 +- .../Reflection/ReflectionTypeLoadException.cs | 3 +- .../Reflection/RuntimeReflectionExtensions.cs | 4 +- .../src/System/Reflection/StrongNameKeyPair.cs | 115 +- .../src/System/Reflection/TargetException.cs | 4 - .../System/Reflection/TargetInvocationException.cs | 4 - .../Reflection/TargetParameterCountException.cs | 4 - .../src/System/Reflection/TypeDelegator.cs | 5 +- .../System/Resources/FileBasedResourceGroveler.cs | 31 +- .../src/System/Resources/IResourceGroveler.cs | 5 - .../Resources/LooselyLinkedResourceReference.cs | 10 +- .../Resources/ManifestBasedResourceGroveler.cs | 153 +- .../Resources/NeutralResourcesLanguageAttribute.cs | 4 +- .../System/Resources/ResourceFallbackManager.cs | 14 - .../src/System/Resources/ResourceManager.cs | 306 +- .../src/System/Resources/ResourceReader.cs | 71 +- src/mscorlib/src/System/Resources/ResourceSet.cs | 21 +- .../src/System/Resources/RuntimeResourceSet.cs | 9 +- .../Resources/SatelliteContractVersionAttribute.cs | 2 +- .../src/System/Resources/__FastResourceComparer.cs | 14 +- src/mscorlib/src/System/RtType.cs | 861 +- .../Runtime/CompilerServices/AsyncMethodBuilder.cs | 58 +- .../Runtime/CompilerServices/CallingConvention.cs | 30 - .../CompilerServices/ConditionalWeakTable.cs | 905 +- .../CompilerServices/DecimalConstantAttribute.cs | 7 +- .../CompilerServices/FormattableStringFactory.cs | 4 +- .../CompilerServices/HasCopySemanticsAttribute.cs | 14 - .../CompilerServices/IDispatchConstantAttribute.cs | 26 - .../Runtime/CompilerServices/INotifyCompletion.cs | 1 - .../CompilerServices/IUnknownConstantAttribute.cs | 27 - .../src/System/Runtime/CompilerServices/IsBoxed.cs | 11 - .../System/Runtime/CompilerServices/IsByValue.cs | 11 - .../src/System/Runtime/CompilerServices/IsConst.cs | 11 - .../Runtime/CompilerServices/IsCopyConstructed.cs | 11 - .../CompilerServices/IsExplicitlyDereferenced.cs | 22 - .../CompilerServices/IsImplicitlyDereferenced.cs | 22 - .../Runtime/CompilerServices/IsJitIntrinsic.cs | 12 - .../src/System/Runtime/CompilerServices/IsLong.cs | 18 - .../System/Runtime/CompilerServices/IsPinned.cs | 11 - .../CompilerServices/IsSignUnspecifiedByte.cs | 16 - .../System/Runtime/CompilerServices/IsUdtReturn.cs | 11 - .../CompilerServices/NativeCppClassAttribute.cs | 16 - .../CompilerServices/RequiredAttributeAttribute.cs | 26 - .../Runtime/CompilerServices/RuntimeHelpers.cs | 92 +- .../CompilerServices/RuntimeWrappedException.cs | 3 +- .../CompilerServices/ScopelessEnumAttribute.cs | 14 - .../System/Runtime/CompilerServices/TaskAwaiter.cs | 23 +- .../CompilerServices/TypeDependencyAttribute.cs | 2 +- .../CompilerServices/TypeForwardedFromAttribute.cs | 2 +- .../CompilerServices/TypeForwardedToAttribute.cs | 1 - .../src/System/Runtime/CompilerServices/Unsafe.cs | 80 + .../Runtime/CompilerServices/YieldAwaitable.cs | 6 +- .../System/Runtime/CompilerServices/jithelpers.cs | 52 +- .../ExceptionServices/ExceptionNotification.cs | 41 + .../ExceptionServices/ExceptionServicesCommon.cs | 2 +- src/mscorlib/src/System/Runtime/GcSettings.cs | 7 - .../Runtime/InteropServices/ArrayWithOffset.cs | 2 - .../System/Runtime/InteropServices/Attributes.cs | 12 +- .../System/Runtime/InteropServices/BStrWrapper.cs | 8 - .../System/Runtime/InteropServices/COMException.cs | 1 - .../Runtime/InteropServices/ComEventsHelper.cs | 16 +- .../Runtime/InteropServices/ComEventsInfo.cs | 5 - .../Runtime/InteropServices/ComEventsSink.cs | 9 - .../Runtime/InteropServices/CriticalHandle.cs | 11 - .../Runtime/InteropServices/CurrencyWrapper.cs | 2 +- .../Runtime/InteropServices/DispatchWrapper.cs | 4 - .../System/Runtime/InteropServices/ErrorWrapper.cs | 6 +- .../InteropServices/ExtensibleClassFactory.cs | 1 - .../Runtime/InteropServices/ExternalException.cs | 2 - .../src/System/Runtime/InteropServices/GcHandle.cs | 21 +- .../InteropServices/ICustomQueryInterface.cs | 1 - .../System/Runtime/InteropServices/IException.cs | 48 +- .../InteropServices/IRegistrationServices.cs | 6 - .../src/System/Runtime/InteropServices/Marshal.cs | 622 +- .../System/Runtime/InteropServices/NativeBuffer.cs | 175 - .../Runtime/InteropServices/NativeMethods.cs | 4 - .../System/Runtime/InteropServices/NonPortable.cs | 34 + .../InteropServices/RegistrationServices.cs | 52 +- .../Runtime/InteropServices/RuntimeEnvironment.cs | 57 +- .../System/Runtime/InteropServices/SafeBuffer.cs | 28 +- .../System/Runtime/InteropServices/SafeHandle.cs | 13 - .../Runtime/InteropServices/SafeHeapHandle.cs | 115 - .../System/Runtime/InteropServices/StringBuffer.cs | 402 - .../TCEAdapterGen/EventProviderWriter.cs | 67 +- .../TCEAdapterGen/EventSinkHelperWriter.cs | 9 +- .../Runtime/InteropServices/TypeLibConverter.cs | 595 - .../src/System/Runtime/InteropServices/Variant.cs | 1 - .../BindableVectorToCollectionAdapter.cs | 11 +- .../WindowsRuntime/BindableVectorToListAdapter.cs | 30 +- .../WindowsRuntime/CLRIPropertyValueImpl.cs | 8 - .../WindowsRuntime/CLRIReferenceImpl.cs | 11 +- .../WindowsRuntime/ConstantSplittableMap.cs | 4 +- .../WindowsRuntime/CustomPropertyImpl.cs | 6 +- .../WindowsRuntime/DictionaryKeyCollection.cs | 8 +- .../WindowsRuntime/DictionaryToMapAdapter.cs | 12 +- .../WindowsRuntime/DictionaryValueCollection.cs | 8 +- .../WindowsRuntime/EnumeratorToIteratorAdapter.cs | 7 +- .../InteropServices/WindowsRuntime/IClosable.cs | 8 +- .../WindowsRuntime/ICustomPropertyProvider.cs | 7 - .../IMapViewToIReadOnlyDictionaryAdapter.cs | 29 +- .../IReadOnlyDictionaryToIMapViewAdapter.cs | 6 +- .../IReadOnlyListToIVectorViewAdapter.cs | 8 +- .../WindowsRuntime/IRestrictedErrorInfo.cs | 2 - .../IVectorViewToIReadOnlyListAdapter.cs | 8 +- .../WindowsRuntime/IteratorToEnumeratorAdapter.cs | 19 +- .../WindowsRuntime/ListToBindableVectorAdapter.cs | 15 +- .../ListToBindableVectorViewAdapter.cs | 4 +- .../WindowsRuntime/ListToVectorAdapter.cs | 19 +- .../WindowsRuntime/ManagedActivationFactory.cs | 5 +- .../WindowsRuntime/MapToCollectionAdapter.cs | 14 +- .../WindowsRuntime/MapToDictionaryAdapter.cs | 23 +- .../MapViewToReadOnlyCollectionAdapter.cs | 4 +- .../WindowsRuntime/NativeMethods.cs | 7 - .../InteropServices/WindowsRuntime/RuntimeClass.cs | 9 - .../WindowsRuntime/VectorToCollectionAdapter.cs | 14 +- .../WindowsRuntime/VectorToListAdapter.cs | 24 +- .../VectorViewToReadOnlyCollectionAdapter.cs | 4 +- .../WindowsRuntime/WindowsRuntimeBufferHelper.cs | 2 - .../WindowsRuntime/WindowsRuntimeMarshal.cs | 52 +- .../WindowsRuntime/WindowsRuntimeMetadata.cs | 5 +- .../System/Runtime/Loader/AssemblyLoadContext.cs | 92 +- src/mscorlib/src/System/Runtime/MemoryFailPoint.cs | 16 +- .../src/System/Runtime/ProfileOptimization.cs | 4 - .../Runtime/Reliability/CriticalFinalizerObject.cs | 6 - .../src/System/Runtime/Remoting/ObjectHandle.cs | 42 +- .../Runtime/Serialization/FormatterConverter.cs | 34 +- .../Runtime/Serialization/FormatterServices.cs | 76 +- .../Runtime/Serialization/IObjectReference.cs | 1 - .../System/Runtime/Serialization/ISerializable.cs | 1 - .../Serialization/ISerializationSurrogate.cs | 2 - .../Runtime/Serialization/ISurrogateSelector.cs | 3 - .../Serialization/SafeSerializationManager.cs | 446 + .../Serialization/SerializationFieldInfo.cs | 36 +- .../Runtime/Serialization/SerializationInfo.cs | 98 +- .../Serialization/SerializationInfoEnumerator.cs | 15 +- .../Runtime/Versioning/BinaryCompatibility.cs | 485 - .../Runtime/Versioning/CompatibilitySwitch.cs | 5 - .../Versioning/ComponentGuaranteesAttribute.cs | 44 - .../Runtime/Versioning/ResourceAttributes.cs | 237 - .../Runtime/Versioning/TargetFrameworkAttribute.cs | 2 +- src/mscorlib/src/System/RuntimeHandles.cs | 273 +- src/mscorlib/src/System/SByte.cs | 3 - .../src/System/Security/AccessControl/Enums.cs | 6 - src/mscorlib/src/System/Security/Attributes.cs | 11 +- .../src/System/Security/BuiltInPermissionSets.cs | 103 +- .../src/System/Security/CodeAccessPermission.cs | 69 +- .../System/Security/CodeAccessSecurityEngine.cs | 468 +- .../src/System/Security/FrameSecurityDescriptor.cs | 31 +- .../src/System/Security/HostProtectionException.cs | 5 +- .../src/System/Security/HostSecurityManager.cs | 131 +- .../src/System/Security/IEvidenceFactory.cs | 15 +- .../src/System/Security/ISecurityEncodable.cs | 18 +- .../System/Security/ISecurityPolicyEncodable.cs | 17 +- .../src/System/Security/NamedPermissionSet.cs | 202 +- .../src/System/Security/PermissionListSet.cs | 29 +- src/mscorlib/src/System/Security/PermissionSet.cs | 1100 +- .../src/System/Security/PermissionSetEnumerator.cs | 14 - .../src/System/Security/PermissionSetTriple.cs | 20 +- .../src/System/Security/PermissionToken.cs | 202 +- .../Security/Permissions/EnvironmentPermission.cs | 60 +- .../Security/Permissions/FileDialogPermission.cs | 33 +- .../Security/Permissions/FileIOPermission.cs | 304 +- .../Security/Permissions/GACIdentityPermission.cs | 16 - .../Permissions/HostProtectionPermission.cs | 34 - .../Permissions/IsolatedStorageFilePermission.cs | 13 - .../Permissions/IsolatedStoragePermission.cs | 91 - .../Security/Permissions/PermissionAttributes.cs | 314 +- .../Security/Permissions/ReflectionPermission.cs | 39 - .../Security/Permissions/RegistryPermission.cs | 131 - .../Security/Permissions/SecurityPermission.cs | 96 +- .../Security/Permissions/SiteIdentityPermission.cs | 108 - .../Permissions/StrongNameIdentityPermission.cs | 90 +- .../Permissions/StrongNamePublicKeyBlob.cs | 2 +- .../System/Security/Permissions/UIPermission.cs | 44 - .../Security/Permissions/URLIdentityPermission.cs | 111 +- .../Security/Permissions/ZoneIdentityPermission.cs | 101 - .../Security/Permissions/keycontainerpermission.cs | 72 +- .../src/System/Security/Policy/ApplicationTrust.cs | 573 +- .../src/System/Security/Policy/Evidence.cs | 1865 - .../src/System/Security/Policy/EvidenceBase.cs | 31 +- .../Security/Policy/EvidenceTypeDescriptor.cs | 20 +- .../Security/Policy/IDelayEvaluatedEvidence.cs | 1 - .../src/System/Security/Policy/PolicyStatement.cs | 302 +- src/mscorlib/src/System/Security/Policy/Site.cs | 29 +- .../src/System/Security/Policy/StrongName.cs | 59 +- src/mscorlib/src/System/Security/Policy/URL.cs | 29 +- src/mscorlib/src/System/Security/Policy/Zone.cs | 66 +- .../Security/Principal/TokenImpersonationLevel.cs | 9 +- .../src/System/Security/SafeSecurityHandles.cs | 16 - .../src/System/Security/SecurityContext.cs | 238 +- .../src/System/Security/SecurityElement.cs | 100 +- .../src/System/Security/SecurityException.cs | 608 +- .../src/System/Security/SecurityManager.cs | 524 +- .../src/System/Security/SecurityRuntime.cs | 156 +- src/mscorlib/src/System/Security/SecurityState.cs | 10 +- src/mscorlib/src/System/Security/Util/Config.cs | 48 - src/mscorlib/src/System/Security/Util/Hex.cs | 2 +- .../System/Security/Util/StringExpressionSet.cs | 41 +- .../src/System/Security/Util/TokenBasedSet.cs | 32 +- src/mscorlib/src/System/Security/Util/URLString.cs | 17 +- src/mscorlib/src/System/Security/Util/XMLUtil.cs | 272 +- src/mscorlib/src/System/Security/securestring.cs | 31 +- src/mscorlib/src/System/SharedStatics.cs | 64 +- src/mscorlib/src/System/Single.cs | 16 +- src/mscorlib/src/System/Span.cs | 477 + src/mscorlib/src/System/String.Comparison.cs | 82 +- src/mscorlib/src/System/String.Manipulation.cs | 475 +- src/mscorlib/src/System/String.Searching.cs | 36 +- src/mscorlib/src/System/String.cs | 126 +- src/mscorlib/src/System/StringComparer.cs | 35 +- src/mscorlib/src/System/StubHelpers.cs | 161 +- src/mscorlib/src/System/Text/ASCIIEncoding.cs | 77 +- .../src/System/Text/BaseCodePageEncoding.cs | 30 +- src/mscorlib/src/System/Text/CodePageEncoding.cs | 13 +- .../src/System/Text/DBCSCodePageEncoding.cs | 102 +- src/mscorlib/src/System/Text/Decoder.cs | 32 +- .../src/System/Text/DecoderBestFitFallback.cs | 9 +- src/mscorlib/src/System/Text/DecoderFallback.cs | 13 +- src/mscorlib/src/System/Text/DecoderNLS.cs | 43 +- .../src/System/Text/DecoderReplacementFallback.cs | 9 +- src/mscorlib/src/System/Text/EUCJPEncoding.cs | 3 - src/mscorlib/src/System/Text/Encoder.cs | 32 +- .../src/System/Text/EncoderBestFitFallback.cs | 12 +- .../src/System/Text/EncoderExceptionFallback.cs | 6 +- src/mscorlib/src/System/Text/EncoderFallback.cs | 8 +- src/mscorlib/src/System/Text/EncoderNLS.cs | 43 +- .../src/System/Text/EncoderReplacementFallback.cs | 10 +- src/mscorlib/src/System/Text/Encoding.cs | 222 +- src/mscorlib/src/System/Text/EncodingForwarder.cs | 98 +- src/mscorlib/src/System/Text/EncodingNLS.cs | 4 - src/mscorlib/src/System/Text/EncodingProvider.cs | 2 +- src/mscorlib/src/System/Text/GB18030Encoding.cs | 60 +- src/mscorlib/src/System/Text/ISCIIEncoding.cs | 88 +- src/mscorlib/src/System/Text/ISO2022Encoding.cs | 74 +- src/mscorlib/src/System/Text/Latin1Encoding.cs | 66 +- .../src/System/Text/MLangCodePageEncoding.cs | 19 +- src/mscorlib/src/System/Text/Normalization.Unix.cs | 123 + .../src/System/Text/Normalization.Windows.cs | 286 + src/mscorlib/src/System/Text/Normalization.cs | 314 - .../src/System/Text/SBCSCodePageEncoding.cs | 93 +- src/mscorlib/src/System/Text/StringBuilder.cs | 309 +- src/mscorlib/src/System/Text/SurrogateEncoder.cs | 7 +- src/mscorlib/src/System/Text/UTF32Encoding.cs | 71 +- src/mscorlib/src/System/Text/UTF7Encoding.cs | 55 +- src/mscorlib/src/System/Text/UTF8Encoding.cs | 96 +- src/mscorlib/src/System/Text/UnicodeEncoding.cs | 92 +- src/mscorlib/src/System/Threading/AsyncLocal.cs | 387 +- .../src/System/Threading/AutoResetEvent.cs | 1 - .../src/System/Threading/CancellationToken.cs | 14 +- .../Threading/CancellationTokenRegistration.cs | 1 - .../System/Threading/CancellationTokenSource.cs | 37 +- .../src/System/Threading/CountdownEvent.cs | 23 +- .../src/System/Threading/EventWaitHandle.cs | 69 +- .../src/System/Threading/ExecutionContext.cs | 1222 +- src/mscorlib/src/System/Threading/Interlocked.cs | 17 - .../src/System/Threading/LazyInitializer.cs | 4 +- .../src/System/Threading/LockRecursionException.cs | 3 - .../src/System/Threading/ManualResetEvent.cs | 1 - .../src/System/Threading/ManualResetEventSlim.cs | 33 +- src/mscorlib/src/System/Threading/Monitor.cs | 26 +- src/mscorlib/src/System/Threading/Mutex.cs | 208 +- src/mscorlib/src/System/Threading/Overlapped.cs | 42 +- .../src/System/Threading/ReaderWriterLock.cs | 36 +- src/mscorlib/src/System/Threading/Semaphore.cs | 35 +- .../src/System/Threading/SemaphoreFullException.cs | 3 - src/mscorlib/src/System/Threading/SemaphoreSlim.cs | 50 +- src/mscorlib/src/System/Threading/SpinLock.cs | 110 +- src/mscorlib/src/System/Threading/SpinWait.cs | 18 +- .../src/System/Threading/SynchronizationContext.cs | 90 +- .../System/Threading/Tasks/AsyncCausalityTracer.cs | 4 +- .../Threading/Tasks/BeginEndAwaitableAdapter.cs | 16 +- .../Tasks/ConcurrentExclusiveSchedulerPair.cs | 42 +- .../src/System/Threading/Tasks/FutureFactory.cs | 148 +- .../src/System/Threading/Tasks/Parallel.cs | 229 +- .../System/Threading/Tasks/ParallelLoopState.cs | 7 +- .../System/Threading/Tasks/ParallelRangeManager.cs | 9 +- .../Threading/Tasks/ProducerConsumerQueues.cs | 12 +- .../src/System/Threading/Tasks/TPLETWProvider.cs | 12 - src/mscorlib/src/System/Threading/Tasks/Task.cs | 229 +- .../System/Threading/Tasks/TaskCompletionSource.cs | 6 +- .../src/System/Threading/Tasks/TaskContinuation.cs | 64 +- .../System/Threading/Tasks/TaskExceptionHolder.cs | 36 +- .../src/System/Threading/Tasks/TaskFactory.cs | 100 +- .../src/System/Threading/Tasks/TaskScheduler.cs | 21 +- .../src/System/Threading/Tasks/TaskToApm.cs | 5 +- .../Threading/Tasks/ThreadPoolTaskScheduler.cs | 7 +- src/mscorlib/src/System/Threading/Tasks/future.cs | 27 +- src/mscorlib/src/System/Threading/Thread.cs | 633 +- .../src/System/Threading/ThreadAbortException.cs | 1 - src/mscorlib/src/System/Threading/ThreadLocal.cs | 17 +- src/mscorlib/src/System/Threading/ThreadPool.cs | 230 +- src/mscorlib/src/System/Threading/Timer.cs | 79 +- src/mscorlib/src/System/Threading/Volatile.cs | 6 - src/mscorlib/src/System/Threading/WaitHandle.cs | 83 +- .../Threading/WaitHandleCannotBeOpenedException.cs | 4 - .../src/System/Threading/WaitHandleExtensions.cs | 46 - src/mscorlib/src/System/ThrowHelper.cs | 211 +- src/mscorlib/src/System/TimeSpan.cs | 28 +- src/mscorlib/src/System/TimeZone.cs | 4 +- src/mscorlib/src/System/TimeZoneInfo.cs | 641 +- .../src/System/TimeZoneNotFoundException.cs | 3 - src/mscorlib/src/System/Tuple.cs | 23 +- src/mscorlib/src/System/Type.cs | 144 +- .../src/System/TypeInitializationException.cs | 1 - src/mscorlib/src/System/TypeLoadException.cs | 9 +- src/mscorlib/src/System/TypeNameParser.cs | 30 +- src/mscorlib/src/System/TypedReference.cs | 10 +- src/mscorlib/src/System/UInt16.cs | 4 - src/mscorlib/src/System/UInt32.cs | 4 - src/mscorlib/src/System/UInt64.cs | 4 - src/mscorlib/src/System/UIntPtr.cs | 25 +- src/mscorlib/src/System/UnSafeCharBuffer.cs | 57 - .../src/System/UnhandledExceptionEventHandler.cs | 3 - .../src/System/UnitySerializationHolder.cs | 4 +- src/mscorlib/src/System/ValueType.cs | 4 - src/mscorlib/src/System/Variant.cs | 27 +- src/mscorlib/src/System/Version.cs | 164 +- src/mscorlib/src/System/WeakReference.cs | 23 +- src/mscorlib/src/System/WeakReferenceOfT.cs | 10 +- src/mscorlib/src/System/_LocalDataStore.cs | 6 +- src/mscorlib/src/System/_LocalDataStoreMgr.cs | 13 +- src/mscorlib/src/System/__ComObject.cs | 13 +- src/mscorlib/src/System/cominterfaces.cs | 34 +- src/mscorlib/src/System/mda.cs | 11 - src/mscorlib/src/mscorlib.Friends.cs | 2 - src/mscorlib/src/mscorlib.txt | 3494 -- src/nativeresources/resourcestring.cpp | 10 +- src/pal/inc/mbusafecrt.h | 16 +- src/pal/inc/pal.h | 196 +- src/pal/inc/pal_char16.h | 3 +- src/pal/inc/pal_mstypes.h | 11 +- src/pal/inc/rt/palrt.h | 180 +- src/pal/inc/rt/safecrt.h | 13 +- src/pal/inc/strsafe.h | 2222 +- src/pal/inc/unixasmmacros.inc | 4 +- src/pal/inc/unixasmmacrosamd64.inc | 2 +- src/pal/inc/unixasmmacrosarm.inc | 3 +- src/pal/inc/unixasmmacrosarm64.inc | 2 +- src/pal/inc/unixasmmacrosx86.inc | 87 + .../prebuilt/idl/{clrdata_i.c => clrdata_i.cpp} | 0 .../idl/{clrinternal_i.c => clrinternal_i.cpp} | 0 ...rivappxhosting_i.c => clrprivappxhosting_i.cpp} | 0 .../{clrprivbinding_i.c => clrprivbinding_i.cpp} | 0 .../{clrprivhosting_i.c => clrprivhosting_i.cpp} | 0 ...timebinders_i.c => clrprivruntimebinders_i.cpp} | 0 src/pal/prebuilt/idl/cordebug_i.c | 451 - src/pal/prebuilt/idl/cordebug_i.cpp | 463 + src/pal/prebuilt/idl/corprof_i.c | 134 - src/pal/prebuilt/idl/corprof_i.cpp | 140 + src/pal/prebuilt/idl/{corpub_i.c => corpub_i.cpp} | 0 src/pal/prebuilt/idl/{corsym_i.c => corsym_i.cpp} | 0 .../idl/{fusionpriv_i.c => fusionpriv_i.cpp} | 0 src/pal/prebuilt/idl/{gchost_i.c => gchost_i.cpp} | 0 .../idl/{ivalidator_i.c => ivalidator_i.cpp} | 0 .../idl/{ivehandler_i.c => ivehandler_i.cpp} | 0 .../prebuilt/idl/{mscorsvc_i.c => mscorsvc_i.cpp} | 0 src/pal/prebuilt/idl/sospriv_i.c | 100 - src/pal/prebuilt/idl/sospriv_i.cpp | 98 + .../idl/{tlbimpexp_i.c => tlbimpexp_i.cpp} | 0 .../prebuilt/idl/{xclrdata_i.c => xclrdata_i.cpp} | 0 .../idl/{xcordebug_i.c => xcordebug_i.cpp} | 0 src/pal/prebuilt/inc/cordebug.h | 485 +- src/pal/prebuilt/inc/corprof.h | 6302 +- src/pal/prebuilt/inc/xclrdata.h | 12 +- src/pal/src/CMakeLists.txt | 108 +- .../{i386 => amd64}/activationhandlerwrapper.S | 0 src/pal/src/arch/amd64/asmconstants.h | 106 + src/pal/src/arch/{i386 => amd64}/context.S | 0 src/pal/src/arch/amd64/context2.S | 259 + src/pal/src/arch/amd64/debugbreak.S | 12 + .../{i386 => amd64}/dispatchexceptionwrapper.S | 0 src/pal/src/arch/amd64/exceptionhelper.S | 42 + src/pal/src/arch/amd64/optimizedtls.cpp | 237 + src/pal/src/arch/amd64/processor.cpp | 64 + src/pal/src/arch/arm/exceptionhelper.S | 2 +- src/pal/src/arch/i386/asmconstants.h | 76 - src/pal/src/arch/i386/context2.S | 354 +- src/pal/src/arch/i386/exceptionhelper.S | 47 +- src/pal/src/arch/i386/optimizedtls.cpp | 237 - src/pal/src/config.h.in | 1 - src/pal/src/configure.cmake | 11 +- src/pal/src/cruntime/lstr.cpp | 210 - src/pal/src/cruntime/math.cpp | 367 + src/pal/src/cruntime/mbstring.cpp | 54 - src/pal/src/cruntime/path.cpp | 482 - src/pal/src/cruntime/printf.cpp | 202 - src/pal/src/cruntime/string.cpp | 55 - src/pal/src/cruntime/wchar.cpp | 211 - src/pal/src/debug/debug.cpp | 1087 +- src/pal/src/examples/CMakeLists.txt | 2 +- src/pal/src/examples/{example1.c => example1.cpp} | 0 src/pal/src/exception/machexception.cpp | 7 + src/pal/src/exception/machmessage.cpp | 2 +- src/pal/src/exception/machmessage.h | 4 +- src/pal/src/exception/seh-unwind.cpp | 76 +- src/pal/src/exception/seh.cpp | 8 +- src/pal/src/exception/signal.cpp | 6 + src/pal/src/file/find.cpp | 10 +- src/pal/src/include/pal/context.h | 24 + src/pal/src/include/pal/palinternal.h | 45 +- src/pal/src/init/pal.cpp | 3 +- src/pal/src/map/virtual.cpp | 5 +- src/pal/src/misc/sysinfo.cpp | 2 +- src/pal/src/safecrt/input.inl | 4 +- .../src/safecrt/{makepath_s.c => makepath_s.cpp} | 0 src/pal/src/safecrt/mbusafecrt.c | 254 - src/pal/src/safecrt/mbusafecrt.cpp | 249 + src/pal/src/safecrt/{memcpy_s.c => memcpy_s.cpp} | 0 src/pal/src/safecrt/{memmove_s.c => memmove_s.cpp} | 0 src/pal/src/safecrt/output.inl | 39 +- .../{safecrt_input_s.c => safecrt_input_s.cpp} | 0 .../{safecrt_output_l.c => safecrt_output_l.cpp} | 0 .../{safecrt_output_s.c => safecrt_output_s.cpp} | 0 .../{safecrt_winput_s.c => safecrt_winput_s.cpp} | 0 .../{safecrt_woutput_s.c => safecrt_woutput_s.cpp} | 0 src/pal/src/safecrt/snprintf.c | 18 - src/pal/src/safecrt/snprintf.cpp | 18 + .../src/safecrt/{splitpath_s.c => splitpath_s.cpp} | 0 src/pal/src/safecrt/sprintf.c | 98 - src/pal/src/safecrt/sprintf_s.cpp | 98 + src/pal/src/safecrt/sscanf.c | 249 - src/pal/src/safecrt/sscanf_s.cpp | 249 + src/pal/src/safecrt/{strcat_s.c => strcat_s.cpp} | 0 src/pal/src/safecrt/{strcpy_s.c => strcpy_s.cpp} | 0 src/pal/src/safecrt/strlen_s.c | 58 - src/pal/src/safecrt/strlen_s.cpp | 58 + src/pal/src/safecrt/{strncat_s.c => strncat_s.cpp} | 0 src/pal/src/safecrt/{strncpy_s.c => strncpy_s.cpp} | 0 src/pal/src/safecrt/{strtok_s.c => strtok_s.cpp} | 0 src/pal/src/safecrt/swprintf.c | 120 - src/pal/src/safecrt/swprintf.cpp | 120 + src/pal/src/safecrt/vsprintf.c | 268 - src/pal/src/safecrt/vsprintf.cpp | 268 + src/pal/src/safecrt/vswprint.c | 282 - src/pal/src/safecrt/vswprint.cpp | 211 + src/pal/src/safecrt/{wcscat_s.c => wcscat_s.cpp} | 0 src/pal/src/safecrt/{wcscpy_s.c => wcscpy_s.cpp} | 0 src/pal/src/safecrt/{wcslen_s.c => wcslen_s.cpp} | 0 src/pal/src/safecrt/{wcsncat_s.c => wcsncat_s.cpp} | 0 src/pal/src/safecrt/{wcsncpy_s.c => wcsncpy_s.cpp} | 0 src/pal/src/safecrt/{wcstok_s.c => wcstok_s.cpp} | 0 .../src/safecrt/{wmakepath_s.c => wmakepath_s.cpp} | 0 .../safecrt/{wsplitpath_s.c => wsplitpath_s.cpp} | 0 src/pal/src/safecrt/{xtoa_s.c => xtoa_s.cpp} | 0 src/pal/src/safecrt/{xtow_s.c => xtow_s.cpp} | 0 src/pal/src/safecrt/xtox_s.inl | 29 - src/pal/src/synchmgr/synchmanager.cpp | 2 +- src/pal/src/thread/context.cpp | 108 +- src/pal/src/thread/process.cpp | 12 +- src/pal/tests/CMakeLists.txt | 15 +- src/pal/tests/palsuite/c_runtime/CMakeLists.txt | 35 +- .../c_runtime/__iscsym/test1/CMakeLists.txt | 2 +- .../__iscsym/test1/{__iscsym.c => __iscsym.cpp} | 0 .../c_runtime/_alloca/test1/CMakeLists.txt | 2 +- .../c_runtime/_alloca/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/_ecvt/test1/CMakeLists.txt | 2 +- .../c_runtime/_ecvt/test1/{test1.c => test1.cpp} | 0 .../c_runtime/_fdopen/test1/CMakeLists.txt | 2 +- .../c_runtime/_fdopen/test1/{test1.c => test1.cpp} | 0 .../c_runtime/_finite/test1/CMakeLists.txt | 2 +- .../c_runtime/_finite/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/_finitef/CMakeLists.txt | 3 + .../c_runtime/_finitef/test1/CMakeLists.txt | 19 + .../palsuite/c_runtime/_finitef/test1/test1.c | 119 + .../palsuite/c_runtime/_finitef/test1/testinfo.dat | 13 + .../c_runtime/_fullpath/test1/CMakeLists.txt | 2 +- .../_fullpath/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/_gcvt/test1/CMakeLists.txt | 2 +- .../c_runtime/_gcvt/test1/{_gcvt.c => _gcvt.cpp} | 0 .../palsuite/c_runtime/_gcvt/test2/CMakeLists.txt | 2 +- .../c_runtime/_gcvt/test2/{test2.c => test2.cpp} | 0 .../palsuite/c_runtime/_getw/test1/CMakeLists.txt | 2 +- .../c_runtime/_getw/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/_isnan/test1/CMakeLists.txt | 2 +- .../c_runtime/_isnan/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/_isnanf/CMakeLists.txt | 3 + .../c_runtime/_isnanf/test1/CMakeLists.txt | 19 + .../tests/palsuite/c_runtime/_isnanf/test1/test1.c | 115 + .../palsuite/c_runtime/_isnanf/test1/testinfo.dat | 16 + .../palsuite/c_runtime/_itow/test1/CMakeLists.txt | 2 +- .../tests/palsuite/c_runtime/_itow/test1/test1.c | 102 - .../tests/palsuite/c_runtime/_itow/test1/test1.cpp | 101 + .../palsuite/c_runtime/_itow/test1/testinfo.dat | 6 +- .../palsuite/c_runtime/_makepath/CMakeLists.txt | 4 - .../c_runtime/_makepath/test1/CMakeLists.txt | 19 - .../palsuite/c_runtime/_makepath/test1/test1.c | 65 - .../c_runtime/_makepath/test1/testinfo.dat | 14 - .../c_runtime/_mbsdec/test1/CMakeLists.txt | 2 +- .../c_runtime/_mbsdec/test1/{test1.c => test1.cpp} | 0 .../c_runtime/_mbsinc/test1/CMakeLists.txt | 2 +- .../c_runtime/_mbsinc/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/_mbslen/CMakeLists.txt | 4 - .../c_runtime/_mbslen/test1/CMakeLists.txt | 19 - .../tests/palsuite/c_runtime/_mbslen/test1/test1.c | 66 - .../palsuite/c_runtime/_mbslen/test1/testinfo.dat | 15 - .../c_runtime/_mbsninc/test1/CMakeLists.txt | 2 +- .../_mbsninc/test1/{test1.c => test1.cpp} | 0 .../c_runtime/_open_osfhandle/test1/CMakeLists.txt | 2 +- .../_open_osfhandle/test1/{test1.c => test1.cpp} | 0 .../c_runtime/_open_osfhandle/test2/CMakeLists.txt | 2 +- .../_open_osfhandle/test2/{test2.c => test2.cpp} | 0 .../c_runtime/_putenv/test1/CMakeLists.txt | 2 +- .../c_runtime/_putenv/test1/{test1.c => test1.cpp} | 0 .../c_runtime/_putenv/test2/CMakeLists.txt | 2 +- .../c_runtime/_putenv/test2/{test2.c => test2.cpp} | 0 .../c_runtime/_putenv/test3/CMakeLists.txt | 2 +- .../c_runtime/_putenv/test3/{test3.c => test3.cpp} | 0 .../c_runtime/_putenv/test4/CMakeLists.txt | 2 +- .../c_runtime/_putenv/test4/{test4.c => test4.cpp} | 0 .../palsuite/c_runtime/_putw/test1/CMakeLists.txt | 2 +- .../tests/palsuite/c_runtime/_putw/test1/test1.c | 112 - .../tests/palsuite/c_runtime/_putw/test1/test1.cpp | 112 + .../palsuite/c_runtime/_snprintf/CMakeLists.txt | 22 - .../tests/palsuite/c_runtime/_snprintf/_snprintf.h | 194 - .../c_runtime/_snprintf/test1/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snprintf/test1/test1.c | 58 - .../c_runtime/_snprintf/test1/testinfo.dat | 12 - .../c_runtime/_snprintf/test10/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snprintf/test10/test10.c | 55 - .../c_runtime/_snprintf/test10/testinfo.dat | 12 - .../c_runtime/_snprintf/test11/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snprintf/test11/test11.c | 54 - .../c_runtime/_snprintf/test11/testinfo.dat | 12 - .../c_runtime/_snprintf/test12/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snprintf/test12/test12.c | 55 - .../c_runtime/_snprintf/test12/testinfo.dat | 12 - .../c_runtime/_snprintf/test13/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snprintf/test13/test13.c | 55 - .../c_runtime/_snprintf/test13/testinfo.dat | 12 - .../c_runtime/_snprintf/test14/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snprintf/test14/test14.c | 57 - .../c_runtime/_snprintf/test14/testinfo.dat | 12 - .../c_runtime/_snprintf/test15/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snprintf/test15/test15.c | 56 - .../c_runtime/_snprintf/test15/testinfo.dat | 12 - .../c_runtime/_snprintf/test16/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snprintf/test16/test16.c | 52 - .../c_runtime/_snprintf/test16/testinfo.dat | 12 - .../c_runtime/_snprintf/test17/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snprintf/test17/test17.c | 53 - .../c_runtime/_snprintf/test17/testinfo.dat | 12 - .../c_runtime/_snprintf/test18/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snprintf/test18/test18.c | 53 - .../c_runtime/_snprintf/test18/testinfo.dat | 12 - .../c_runtime/_snprintf/test19/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snprintf/test19/test19.c | 76 - .../c_runtime/_snprintf/test19/testinfo.dat | 12 - .../c_runtime/_snprintf/test2/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snprintf/test2/test2.c | 44 - .../c_runtime/_snprintf/test2/testinfo.dat | 12 - .../c_runtime/_snprintf/test3/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snprintf/test3/test3.c | 45 - .../c_runtime/_snprintf/test3/testinfo.dat | 12 - .../c_runtime/_snprintf/test4/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snprintf/test4/test4.c | 69 - .../c_runtime/_snprintf/test4/testinfo.dat | 12 - .../c_runtime/_snprintf/test5/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snprintf/test5/test5.c | 61 - .../c_runtime/_snprintf/test5/testinfo.dat | 12 - .../c_runtime/_snprintf/test6/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snprintf/test6/test6.c | 47 - .../c_runtime/_snprintf/test6/testinfo.dat | 12 - .../c_runtime/_snprintf/test7/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snprintf/test7/test7.c | 47 - .../c_runtime/_snprintf/test7/testinfo.dat | 12 - .../c_runtime/_snprintf/test8/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snprintf/test8/test8.c | 56 - .../c_runtime/_snprintf/test8/testinfo.dat | 12 - .../c_runtime/_snprintf/test9/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snprintf/test9/test9.c | 55 - .../c_runtime/_snprintf/test9/testinfo.dat | 12 - .../palsuite/c_runtime/_snprintf_s/CMakeLists.txt | 21 + .../palsuite/c_runtime/_snprintf_s/_snprintf_s.h | 194 + .../c_runtime/_snprintf_s/test1/CMakeLists.txt | 19 + .../palsuite/c_runtime/_snprintf_s/test1/test1.cpp | 58 + .../c_runtime/_snprintf_s/test1/testinfo.dat | 12 + .../c_runtime/_snprintf_s/test10/CMakeLists.txt | 19 + .../c_runtime/_snprintf_s/test10/test10.cpp | 55 + .../c_runtime/_snprintf_s/test10/testinfo.dat | 12 + .../c_runtime/_snprintf_s/test11/CMakeLists.txt | 19 + .../c_runtime/_snprintf_s/test11/test11.cpp | 54 + .../c_runtime/_snprintf_s/test11/testinfo.dat | 12 + .../c_runtime/_snprintf_s/test12/CMakeLists.txt | 19 + .../c_runtime/_snprintf_s/test12/test12.cpp | 55 + .../c_runtime/_snprintf_s/test12/testinfo.dat | 12 + .../c_runtime/_snprintf_s/test13/CMakeLists.txt | 19 + .../c_runtime/_snprintf_s/test13/test13.cpp | 55 + .../c_runtime/_snprintf_s/test13/testinfo.dat | 12 + .../c_runtime/_snprintf_s/test14/CMakeLists.txt | 19 + .../c_runtime/_snprintf_s/test14/test14.cpp | 57 + .../c_runtime/_snprintf_s/test14/testinfo.dat | 12 + .../c_runtime/_snprintf_s/test15/CMakeLists.txt | 19 + .../c_runtime/_snprintf_s/test15/test15.cpp | 56 + .../c_runtime/_snprintf_s/test15/testinfo.dat | 12 + .../c_runtime/_snprintf_s/test16/CMakeLists.txt | 19 + .../c_runtime/_snprintf_s/test16/test16.cpp | 52 + .../c_runtime/_snprintf_s/test16/testinfo.dat | 12 + .../c_runtime/_snprintf_s/test17/CMakeLists.txt | 19 + .../c_runtime/_snprintf_s/test17/test17.cpp | 53 + .../c_runtime/_snprintf_s/test17/testinfo.dat | 12 + .../c_runtime/_snprintf_s/test18/CMakeLists.txt | 19 + .../c_runtime/_snprintf_s/test18/test18.cpp | 53 + .../c_runtime/_snprintf_s/test18/testinfo.dat | 12 + .../c_runtime/_snprintf_s/test19/CMakeLists.txt | 19 + .../c_runtime/_snprintf_s/test19/test19.cpp | 70 + .../c_runtime/_snprintf_s/test19/testinfo.dat | 12 + .../c_runtime/_snprintf_s/test2/CMakeLists.txt | 19 + .../palsuite/c_runtime/_snprintf_s/test2/test2.cpp | 44 + .../c_runtime/_snprintf_s/test2/testinfo.dat | 12 + .../c_runtime/_snprintf_s/test3/CMakeLists.txt | 19 + .../palsuite/c_runtime/_snprintf_s/test3/test3.cpp | 45 + .../c_runtime/_snprintf_s/test3/testinfo.dat | 12 + .../c_runtime/_snprintf_s/test4/CMakeLists.txt | 19 + .../palsuite/c_runtime/_snprintf_s/test4/test4.cpp | 69 + .../c_runtime/_snprintf_s/test4/testinfo.dat | 12 + .../c_runtime/_snprintf_s/test6/CMakeLists.txt | 19 + .../palsuite/c_runtime/_snprintf_s/test6/test6.cpp | 47 + .../c_runtime/_snprintf_s/test6/testinfo.dat | 12 + .../c_runtime/_snprintf_s/test7/CMakeLists.txt | 19 + .../palsuite/c_runtime/_snprintf_s/test7/test7.cpp | 47 + .../c_runtime/_snprintf_s/test7/testinfo.dat | 12 + .../c_runtime/_snprintf_s/test8/CMakeLists.txt | 19 + .../palsuite/c_runtime/_snprintf_s/test8/test8.cpp | 56 + .../c_runtime/_snprintf_s/test8/testinfo.dat | 12 + .../c_runtime/_snprintf_s/test9/CMakeLists.txt | 19 + .../palsuite/c_runtime/_snprintf_s/test9/test9.cpp | 55 + .../c_runtime/_snprintf_s/test9/testinfo.dat | 12 + .../palsuite/c_runtime/_snwprintf/CMakeLists.txt | 22 - .../palsuite/c_runtime/_snwprintf/_snwprintf.h | 199 - .../c_runtime/_snwprintf/test1/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snwprintf/test1/test1.c | 62 - .../c_runtime/_snwprintf/test1/testinfo.dat | 12 - .../c_runtime/_snwprintf/test10/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snwprintf/test10/test10.c | 54 - .../c_runtime/_snwprintf/test10/testinfo.dat | 12 - .../c_runtime/_snwprintf/test11/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snwprintf/test11/test11.c | 54 - .../c_runtime/_snwprintf/test11/testinfo.dat | 12 - .../c_runtime/_snwprintf/test12/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snwprintf/test12/test12.c | 54 - .../c_runtime/_snwprintf/test12/testinfo.dat | 12 - .../c_runtime/_snwprintf/test13/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snwprintf/test13/test13.c | 54 - .../c_runtime/_snwprintf/test13/testinfo.dat | 12 - .../c_runtime/_snwprintf/test14/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snwprintf/test14/test14.c | 66 - .../c_runtime/_snwprintf/test14/testinfo.dat | 12 - .../c_runtime/_snwprintf/test15/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snwprintf/test15/test15.c | 67 - .../c_runtime/_snwprintf/test15/testinfo.dat | 12 - .../c_runtime/_snwprintf/test16/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snwprintf/test16/test16.c | 65 - .../c_runtime/_snwprintf/test16/testinfo.dat | 12 - .../c_runtime/_snwprintf/test17/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snwprintf/test17/test17.c | 68 - .../c_runtime/_snwprintf/test17/testinfo.dat | 12 - .../c_runtime/_snwprintf/test18/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snwprintf/test18/test18.c | 69 - .../c_runtime/_snwprintf/test18/testinfo.dat | 12 - .../c_runtime/_snwprintf/test19/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snwprintf/test19/test19.c | 90 - .../c_runtime/_snwprintf/test19/testinfo.dat | 12 - .../c_runtime/_snwprintf/test2/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snwprintf/test2/test2.c | 44 - .../c_runtime/_snwprintf/test2/testinfo.dat | 12 - .../c_runtime/_snwprintf/test3/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snwprintf/test3/test3.c | 44 - .../c_runtime/_snwprintf/test3/testinfo.dat | 12 - .../c_runtime/_snwprintf/test4/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snwprintf/test4/test4.c | 71 - .../c_runtime/_snwprintf/test4/testinfo.dat | 12 - .../c_runtime/_snwprintf/test5/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snwprintf/test5/test5.c | 63 - .../c_runtime/_snwprintf/test5/testinfo.dat | 12 - .../c_runtime/_snwprintf/test6/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snwprintf/test6/test6.c | 46 - .../c_runtime/_snwprintf/test6/testinfo.dat | 12 - .../c_runtime/_snwprintf/test7/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snwprintf/test7/test7.c | 46 - .../c_runtime/_snwprintf/test7/testinfo.dat | 12 - .../c_runtime/_snwprintf/test8/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snwprintf/test8/test8.c | 53 - .../c_runtime/_snwprintf/test8/testinfo.dat | 12 - .../c_runtime/_snwprintf/test9/CMakeLists.txt | 19 - .../palsuite/c_runtime/_snwprintf/test9/test9.c | 53 - .../c_runtime/_snwprintf/test9/testinfo.dat | 12 - .../palsuite/c_runtime/_snwprintf_s/CMakeLists.txt | 21 + .../palsuite/c_runtime/_snwprintf_s/_snwprintf_s.h | 199 + .../c_runtime/_snwprintf_s/test1/CMakeLists.txt | 19 + .../c_runtime/_snwprintf_s/test1/test1.cpp | 62 + .../c_runtime/_snwprintf_s/test1/testinfo.dat | 12 + .../c_runtime/_snwprintf_s/test10/CMakeLists.txt | 19 + .../c_runtime/_snwprintf_s/test10/test10.cpp | 54 + .../c_runtime/_snwprintf_s/test10/testinfo.dat | 12 + .../c_runtime/_snwprintf_s/test11/CMakeLists.txt | 19 + .../c_runtime/_snwprintf_s/test11/test11.cpp | 54 + .../c_runtime/_snwprintf_s/test11/testinfo.dat | 12 + .../c_runtime/_snwprintf_s/test12/CMakeLists.txt | 19 + .../c_runtime/_snwprintf_s/test12/test12.cpp | 54 + .../c_runtime/_snwprintf_s/test12/testinfo.dat | 12 + .../c_runtime/_snwprintf_s/test13/CMakeLists.txt | 19 + .../c_runtime/_snwprintf_s/test13/test13.cpp | 54 + .../c_runtime/_snwprintf_s/test13/testinfo.dat | 12 + .../c_runtime/_snwprintf_s/test14/CMakeLists.txt | 19 + .../c_runtime/_snwprintf_s/test14/test14.cpp | 66 + .../c_runtime/_snwprintf_s/test14/testinfo.dat | 12 + .../c_runtime/_snwprintf_s/test15/CMakeLists.txt | 19 + .../c_runtime/_snwprintf_s/test15/test15.cpp | 67 + .../c_runtime/_snwprintf_s/test15/testinfo.dat | 12 + .../c_runtime/_snwprintf_s/test16/CMakeLists.txt | 19 + .../c_runtime/_snwprintf_s/test16/test16.cpp | 65 + .../c_runtime/_snwprintf_s/test16/testinfo.dat | 12 + .../c_runtime/_snwprintf_s/test17/CMakeLists.txt | 19 + .../c_runtime/_snwprintf_s/test17/test17.cpp | 68 + .../c_runtime/_snwprintf_s/test17/testinfo.dat | 12 + .../c_runtime/_snwprintf_s/test18/CMakeLists.txt | 19 + .../c_runtime/_snwprintf_s/test18/test18.cpp | 69 + .../c_runtime/_snwprintf_s/test18/testinfo.dat | 12 + .../c_runtime/_snwprintf_s/test19/CMakeLists.txt | 19 + .../c_runtime/_snwprintf_s/test19/test19.cpp | 82 + .../c_runtime/_snwprintf_s/test19/testinfo.dat | 12 + .../c_runtime/_snwprintf_s/test2/CMakeLists.txt | 19 + .../c_runtime/_snwprintf_s/test2/test2.cpp | 44 + .../c_runtime/_snwprintf_s/test2/testinfo.dat | 12 + .../c_runtime/_snwprintf_s/test3/CMakeLists.txt | 19 + .../c_runtime/_snwprintf_s/test3/test3.cpp | 44 + .../c_runtime/_snwprintf_s/test3/testinfo.dat | 12 + .../c_runtime/_snwprintf_s/test4/CMakeLists.txt | 19 + .../c_runtime/_snwprintf_s/test4/test4.cpp | 71 + .../c_runtime/_snwprintf_s/test4/testinfo.dat | 12 + .../c_runtime/_snwprintf_s/test6/CMakeLists.txt | 19 + .../c_runtime/_snwprintf_s/test6/test6.cpp | 46 + .../c_runtime/_snwprintf_s/test6/testinfo.dat | 12 + .../c_runtime/_snwprintf_s/test7/CMakeLists.txt | 19 + .../c_runtime/_snwprintf_s/test7/test7.cpp | 46 + .../c_runtime/_snwprintf_s/test7/testinfo.dat | 12 + .../c_runtime/_snwprintf_s/test8/CMakeLists.txt | 19 + .../c_runtime/_snwprintf_s/test8/test8.cpp | 53 + .../c_runtime/_snwprintf_s/test8/testinfo.dat | 12 + .../c_runtime/_snwprintf_s/test9/CMakeLists.txt | 19 + .../c_runtime/_snwprintf_s/test9/test9.cpp | 53 + .../c_runtime/_snwprintf_s/test9/testinfo.dat | 12 + .../palsuite/c_runtime/_splitpath/CMakeLists.txt | 4 - .../c_runtime/_splitpath/test1/CMakeLists.txt | 19 - .../palsuite/c_runtime/_splitpath/test1/test1.c | 108 - .../c_runtime/_splitpath/test1/testinfo.dat | 15 - .../c_runtime/_stricmp/test1/CMakeLists.txt | 2 +- .../_stricmp/test1/{test1.c => test1.cpp} | 0 .../c_runtime/_strlwr/test1/CMakeLists.txt | 2 +- .../c_runtime/_strlwr/test1/{test1.c => test1.cpp} | 0 .../c_runtime/_strnicmp/test1/CMakeLists.txt | 2 +- .../_strnicmp/test1/{test1.c => test1.cpp} | 0 .../tests/palsuite/c_runtime/_swab/CMakeLists.txt | 4 - .../palsuite/c_runtime/_swab/test1/CMakeLists.txt | 19 - .../tests/palsuite/c_runtime/_swab/test1/test1.c | 45 - .../palsuite/c_runtime/_swab/test1/testinfo.dat | 14 - .../palsuite/c_runtime/_vsnprintf/_vsnprintf.h | 14 +- .../c_runtime/_vsnprintf/test1/CMakeLists.txt | 2 +- .../_vsnprintf/test1/{test1.c => test1.cpp} | 0 .../c_runtime/_vsnprintf/test1/testinfo.dat | 2 +- .../c_runtime/_vsnprintf/test10/CMakeLists.txt | 2 +- .../_vsnprintf/test10/{test10.c => test10.cpp} | 0 .../c_runtime/_vsnprintf/test10/testinfo.dat | 2 +- .../c_runtime/_vsnprintf/test11/CMakeLists.txt | 2 +- .../_vsnprintf/test11/{test11.c => test11.cpp} | 0 .../c_runtime/_vsnprintf/test11/testinfo.dat | 2 +- .../c_runtime/_vsnprintf/test12/CMakeLists.txt | 2 +- .../_vsnprintf/test12/{test12.c => test12.cpp} | 0 .../c_runtime/_vsnprintf/test12/testinfo.dat | 2 +- .../c_runtime/_vsnprintf/test13/CMakeLists.txt | 2 +- .../_vsnprintf/test13/{test13.c => test13.cpp} | 0 .../c_runtime/_vsnprintf/test13/testinfo.dat | 2 +- .../c_runtime/_vsnprintf/test14/CMakeLists.txt | 2 +- .../_vsnprintf/test14/{test14.c => test14.cpp} | 0 .../c_runtime/_vsnprintf/test14/testinfo.dat | 2 +- .../c_runtime/_vsnprintf/test15/CMakeLists.txt | 2 +- .../_vsnprintf/test15/{test15.c => test15.cpp} | 0 .../c_runtime/_vsnprintf/test15/testinfo.dat | 2 +- .../c_runtime/_vsnprintf/test16/CMakeLists.txt | 2 +- .../_vsnprintf/test16/{test16.c => test16.cpp} | 0 .../c_runtime/_vsnprintf/test16/testinfo.dat | 2 +- .../c_runtime/_vsnprintf/test17/CMakeLists.txt | 2 +- .../_vsnprintf/test17/{test17.c => test17.cpp} | 0 .../c_runtime/_vsnprintf/test17/testinfo.dat | 2 +- .../c_runtime/_vsnprintf/test18/CMakeLists.txt | 2 +- .../_vsnprintf/test18/{test18.c => test18.cpp} | 0 .../c_runtime/_vsnprintf/test18/testinfo.dat | 2 +- .../c_runtime/_vsnprintf/test19/CMakeLists.txt | 2 +- .../palsuite/c_runtime/_vsnprintf/test19/test19.c | 103 - .../c_runtime/_vsnprintf/test19/test19.cpp | 103 + .../c_runtime/_vsnprintf/test19/testinfo.dat | 2 +- .../c_runtime/_vsnprintf/test2/CMakeLists.txt | 2 +- .../_vsnprintf/test2/{test2.c => test2.cpp} | 0 .../c_runtime/_vsnprintf/test2/testinfo.dat | 2 +- .../c_runtime/_vsnprintf/test3/CMakeLists.txt | 2 +- .../_vsnprintf/test3/{test3.c => test3.cpp} | 0 .../c_runtime/_vsnprintf/test3/testinfo.dat | 2 +- .../c_runtime/_vsnprintf/test4/CMakeLists.txt | 2 +- .../_vsnprintf/test4/{test4.c => test4.cpp} | 0 .../c_runtime/_vsnprintf/test4/testinfo.dat | 2 +- .../c_runtime/_vsnprintf/test5/CMakeLists.txt | 2 +- .../_vsnprintf/test5/{test5.c => test5.cpp} | 0 .../c_runtime/_vsnprintf/test5/testinfo.dat | 2 +- .../c_runtime/_vsnprintf/test6/CMakeLists.txt | 2 +- .../_vsnprintf/test6/{test6.c => test6.cpp} | 0 .../c_runtime/_vsnprintf/test6/testinfo.dat | 2 +- .../c_runtime/_vsnprintf/test7/CMakeLists.txt | 2 +- .../_vsnprintf/test7/{test7.c => test7.cpp} | 0 .../c_runtime/_vsnprintf/test7/testinfo.dat | 2 +- .../c_runtime/_vsnprintf/test8/CMakeLists.txt | 2 +- .../_vsnprintf/test8/{test8.c => test8.cpp} | 0 .../c_runtime/_vsnprintf/test8/testinfo.dat | 2 +- .../c_runtime/_vsnprintf/test9/CMakeLists.txt | 2 +- .../_vsnprintf/test9/{test9.c => test9.cpp} | 0 .../c_runtime/_vsnprintf/test9/testinfo.dat | 2 +- .../palsuite/c_runtime/_vsnwprintf/CMakeLists.txt | 22 - .../palsuite/c_runtime/_vsnwprintf/_vsnwprintf.h | 133 - .../c_runtime/_vsnwprintf/test1/CMakeLists.txt | 19 - .../palsuite/c_runtime/_vsnwprintf/test1/test1.c | 60 - .../c_runtime/_vsnwprintf/test1/testinfo.dat | 14 - .../c_runtime/_vsnwprintf/test10/CMakeLists.txt | 19 - .../palsuite/c_runtime/_vsnwprintf/test10/test10.c | 50 - .../c_runtime/_vsnwprintf/test10/testinfo.dat | 14 - .../c_runtime/_vsnwprintf/test11/CMakeLists.txt | 19 - .../palsuite/c_runtime/_vsnwprintf/test11/test11.c | 50 - .../c_runtime/_vsnwprintf/test11/testinfo.dat | 14 - .../c_runtime/_vsnwprintf/test12/CMakeLists.txt | 19 - .../palsuite/c_runtime/_vsnwprintf/test12/test12.c | 50 - .../c_runtime/_vsnwprintf/test12/testinfo.dat | 14 - .../c_runtime/_vsnwprintf/test13/CMakeLists.txt | 19 - .../palsuite/c_runtime/_vsnwprintf/test13/test13.c | 50 - .../c_runtime/_vsnwprintf/test13/testinfo.dat | 14 - .../c_runtime/_vsnwprintf/test14/CMakeLists.txt | 19 - .../palsuite/c_runtime/_vsnwprintf/test14/test14.c | 63 - .../c_runtime/_vsnwprintf/test14/testinfo.dat | 14 - .../c_runtime/_vsnwprintf/test15/CMakeLists.txt | 19 - .../palsuite/c_runtime/_vsnwprintf/test15/test15.c | 64 - .../c_runtime/_vsnwprintf/test15/testinfo.dat | 14 - .../c_runtime/_vsnwprintf/test16/CMakeLists.txt | 19 - .../palsuite/c_runtime/_vsnwprintf/test16/test16.c | 63 - .../c_runtime/_vsnwprintf/test16/testinfo.dat | 14 - .../c_runtime/_vsnwprintf/test17/CMakeLists.txt | 19 - .../palsuite/c_runtime/_vsnwprintf/test17/test17.c | 65 - .../c_runtime/_vsnwprintf/test17/testinfo.dat | 14 - .../c_runtime/_vsnwprintf/test18/CMakeLists.txt | 19 - .../palsuite/c_runtime/_vsnwprintf/test18/test18.c | 65 - .../c_runtime/_vsnwprintf/test18/testinfo.dat | 14 - .../c_runtime/_vsnwprintf/test19/CMakeLists.txt | 19 - .../palsuite/c_runtime/_vsnwprintf/test19/test19.c | 139 - .../c_runtime/_vsnwprintf/test19/testinfo.dat | 14 - .../c_runtime/_vsnwprintf/test2/CMakeLists.txt | 19 - .../palsuite/c_runtime/_vsnwprintf/test2/test2.c | 40 - .../c_runtime/_vsnwprintf/test2/testinfo.dat | 14 - .../c_runtime/_vsnwprintf/test3/CMakeLists.txt | 19 - .../palsuite/c_runtime/_vsnwprintf/test3/test3.c | 40 - .../c_runtime/_vsnwprintf/test3/testinfo.dat | 14 - .../c_runtime/_vsnwprintf/test4/CMakeLists.txt | 19 - .../palsuite/c_runtime/_vsnwprintf/test4/test4.c | 121 - .../c_runtime/_vsnwprintf/test4/testinfo.dat | 14 - .../c_runtime/_vsnwprintf/test5/CMakeLists.txt | 19 - .../palsuite/c_runtime/_vsnwprintf/test5/test5.c | 81 - .../c_runtime/_vsnwprintf/test5/testinfo.dat | 14 - .../c_runtime/_vsnwprintf/test6/CMakeLists.txt | 19 - .../palsuite/c_runtime/_vsnwprintf/test6/test6.c | 43 - .../c_runtime/_vsnwprintf/test6/testinfo.dat | 14 - .../c_runtime/_vsnwprintf/test7/CMakeLists.txt | 19 - .../palsuite/c_runtime/_vsnwprintf/test7/test7.c | 43 - .../c_runtime/_vsnwprintf/test7/testinfo.dat | 14 - .../c_runtime/_vsnwprintf/test8/CMakeLists.txt | 19 - .../palsuite/c_runtime/_vsnwprintf/test8/test8.c | 49 - .../c_runtime/_vsnwprintf/test8/testinfo.dat | 14 - .../c_runtime/_vsnwprintf/test9/CMakeLists.txt | 19 - .../palsuite/c_runtime/_vsnwprintf/test9/test9.c | 49 - .../c_runtime/_vsnwprintf/test9/testinfo.dat | 14 - .../c_runtime/_vsnwprintf_s/CMakeLists.txt | 21 + .../c_runtime/_vsnwprintf_s/_vsnwprintf_s.h | 133 + .../c_runtime/_vsnwprintf_s/test1/CMakeLists.txt | 19 + .../c_runtime/_vsnwprintf_s/test1/test1.cpp | 60 + .../c_runtime/_vsnwprintf_s/test1/testinfo.dat | 14 + .../c_runtime/_vsnwprintf_s/test10/CMakeLists.txt | 19 + .../c_runtime/_vsnwprintf_s/test10/test10.cpp | 50 + .../c_runtime/_vsnwprintf_s/test10/testinfo.dat | 14 + .../c_runtime/_vsnwprintf_s/test11/CMakeLists.txt | 19 + .../c_runtime/_vsnwprintf_s/test11/test11.cpp | 50 + .../c_runtime/_vsnwprintf_s/test11/testinfo.dat | 14 + .../c_runtime/_vsnwprintf_s/test12/CMakeLists.txt | 19 + .../c_runtime/_vsnwprintf_s/test12/test12.cpp | 50 + .../c_runtime/_vsnwprintf_s/test12/testinfo.dat | 14 + .../c_runtime/_vsnwprintf_s/test13/CMakeLists.txt | 19 + .../c_runtime/_vsnwprintf_s/test13/test13.cpp | 50 + .../c_runtime/_vsnwprintf_s/test13/testinfo.dat | 14 + .../c_runtime/_vsnwprintf_s/test14/CMakeLists.txt | 19 + .../c_runtime/_vsnwprintf_s/test14/test14.cpp | 63 + .../c_runtime/_vsnwprintf_s/test14/testinfo.dat | 14 + .../c_runtime/_vsnwprintf_s/test15/CMakeLists.txt | 19 + .../c_runtime/_vsnwprintf_s/test15/test15.cpp | 64 + .../c_runtime/_vsnwprintf_s/test15/testinfo.dat | 14 + .../c_runtime/_vsnwprintf_s/test16/CMakeLists.txt | 19 + .../c_runtime/_vsnwprintf_s/test16/test16.cpp | 63 + .../c_runtime/_vsnwprintf_s/test16/testinfo.dat | 14 + .../c_runtime/_vsnwprintf_s/test17/CMakeLists.txt | 19 + .../c_runtime/_vsnwprintf_s/test17/test17.cpp | 65 + .../c_runtime/_vsnwprintf_s/test17/testinfo.dat | 14 + .../c_runtime/_vsnwprintf_s/test18/CMakeLists.txt | 19 + .../c_runtime/_vsnwprintf_s/test18/test18.cpp | 65 + .../c_runtime/_vsnwprintf_s/test18/testinfo.dat | 14 + .../c_runtime/_vsnwprintf_s/test19/CMakeLists.txt | 19 + .../c_runtime/_vsnwprintf_s/test19/test19.cpp | 139 + .../c_runtime/_vsnwprintf_s/test19/testinfo.dat | 14 + .../c_runtime/_vsnwprintf_s/test2/CMakeLists.txt | 19 + .../c_runtime/_vsnwprintf_s/test2/test2.cpp | 40 + .../c_runtime/_vsnwprintf_s/test2/testinfo.dat | 14 + .../c_runtime/_vsnwprintf_s/test3/CMakeLists.txt | 19 + .../c_runtime/_vsnwprintf_s/test3/test3.cpp | 40 + .../c_runtime/_vsnwprintf_s/test3/testinfo.dat | 14 + .../c_runtime/_vsnwprintf_s/test4/CMakeLists.txt | 19 + .../c_runtime/_vsnwprintf_s/test4/test4.cpp | 121 + .../c_runtime/_vsnwprintf_s/test4/testinfo.dat | 14 + .../c_runtime/_vsnwprintf_s/test6/CMakeLists.txt | 19 + .../c_runtime/_vsnwprintf_s/test6/test6.cpp | 43 + .../c_runtime/_vsnwprintf_s/test6/testinfo.dat | 14 + .../c_runtime/_vsnwprintf_s/test7/CMakeLists.txt | 19 + .../c_runtime/_vsnwprintf_s/test7/test7.cpp | 43 + .../c_runtime/_vsnwprintf_s/test7/testinfo.dat | 14 + .../c_runtime/_vsnwprintf_s/test8/CMakeLists.txt | 19 + .../c_runtime/_vsnwprintf_s/test8/test8.cpp | 49 + .../c_runtime/_vsnwprintf_s/test8/testinfo.dat | 14 + .../c_runtime/_vsnwprintf_s/test9/CMakeLists.txt | 19 + .../c_runtime/_vsnwprintf_s/test9/test9.cpp | 49 + .../c_runtime/_vsnwprintf_s/test9/testinfo.dat | 14 + .../c_runtime/_wcsicmp/test1/CMakeLists.txt | 2 +- .../_wcsicmp/test1/{test1.c => test1.cpp} | 0 .../c_runtime/_wcslwr/test1/CMakeLists.txt | 2 +- .../c_runtime/_wcslwr/test1/{test1.c => test1.cpp} | 0 .../c_runtime/_wcsnicmp/test1/CMakeLists.txt | 2 +- .../_wcsnicmp/test1/{test1.c => test1.cpp} | 0 .../c_runtime/_wfopen/test1/CMakeLists.txt | 2 +- .../c_runtime/_wfopen/test1/{test1.c => test1.cpp} | 0 .../c_runtime/_wfopen/test2/CMakeLists.txt | 2 +- .../c_runtime/_wfopen/test2/{test2.c => test2.cpp} | 0 .../c_runtime/_wfopen/test3/CMakeLists.txt | 2 +- .../c_runtime/_wfopen/test3/{test3.c => test3.cpp} | 0 .../c_runtime/_wfopen/test4/CMakeLists.txt | 2 +- .../c_runtime/_wfopen/test4/{test4.c => test4.cpp} | 0 .../c_runtime/_wfopen/test5/CMakeLists.txt | 2 +- .../c_runtime/_wfopen/test5/{test5.c => test5.cpp} | 0 .../c_runtime/_wfopen/test6/CMakeLists.txt | 2 +- .../c_runtime/_wfopen/test6/{test6.c => test6.cpp} | 0 .../c_runtime/_wfopen/test7/CMakeLists.txt | 2 +- .../c_runtime/_wfopen/test7/{test7.c => test7.cpp} | 0 .../palsuite/c_runtime/_wmakepath/CMakeLists.txt | 4 - .../c_runtime/_wmakepath/test1/CMakeLists.txt | 19 - .../palsuite/c_runtime/_wmakepath/test1/test1.c | 76 - .../c_runtime/_wmakepath/test1/testinfo.dat | 13 - .../palsuite/c_runtime/_wsplitpath/CMakeLists.txt | 4 - .../c_runtime/_wsplitpath/test1/CMakeLists.txt | 19 - .../palsuite/c_runtime/_wsplitpath/test1/test1.c | 151 - .../c_runtime/_wsplitpath/test1/testinfo.dat | 15 - .../palsuite/c_runtime/_wtoi/test1/CMakeLists.txt | 2 +- .../c_runtime/_wtoi/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/abs/test1/CMakeLists.txt | 2 +- .../c_runtime/abs/test1/{abs.c => abs.cpp} | 0 .../palsuite/c_runtime/acos/test1/CMakeLists.txt | 2 +- .../c_runtime/acos/test1/{test1.c => test1.cpp} | 0 .../tests/palsuite/c_runtime/acosf/CMakeLists.txt | 3 + .../palsuite/c_runtime/acosf/test1/CMakeLists.txt | 19 + .../tests/palsuite/c_runtime/acosf/test1/test1.c | 129 + .../palsuite/c_runtime/acosf/test1/testinfo.dat | 14 + .../palsuite/c_runtime/asin/test1/CMakeLists.txt | 2 +- .../c_runtime/asin/test1/{test1.c => test1.cpp} | 0 .../tests/palsuite/c_runtime/asinf/CMakeLists.txt | 3 + .../palsuite/c_runtime/asinf/test1/CMakeLists.txt | 19 + .../tests/palsuite/c_runtime/asinf/test1/test1.c | 145 + .../palsuite/c_runtime/asinf/test1/testinfo.dat | 14 + .../palsuite/c_runtime/atan/test1/CMakeLists.txt | 2 +- .../c_runtime/atan/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/atan2/test1/CMakeLists.txt | 2 +- .../c_runtime/atan2/test1/{test1.c => test1.cpp} | 0 .../tests/palsuite/c_runtime/atan2f/CMakeLists.txt | 3 + .../palsuite/c_runtime/atan2f/test1/CMakeLists.txt | 19 + .../tests/palsuite/c_runtime/atan2f/test1/test1.c | 147 + .../palsuite/c_runtime/atan2f/test1/testinfo.dat | 14 + .../tests/palsuite/c_runtime/atanf/CMakeLists.txt | 3 + .../palsuite/c_runtime/atanf/test1/CMakeLists.txt | 19 + .../tests/palsuite/c_runtime/atanf/test1/test1.c | 127 + .../palsuite/c_runtime/atanf/test1/testinfo.dat | 13 + .../palsuite/c_runtime/atof/test1/CMakeLists.txt | 2 +- .../c_runtime/atof/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/atoi/test1/CMakeLists.txt | 2 +- .../c_runtime/atoi/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/atol/test1/CMakeLists.txt | 2 +- .../c_runtime/atol/test1/{test1.c => test1.cpp} | 0 .../c_runtime/bsearch/test1/CMakeLists.txt | 2 +- .../c_runtime/bsearch/test1/{test1.c => test1.cpp} | 0 .../c_runtime/bsearch/test2/CMakeLists.txt | 2 +- .../c_runtime/bsearch/test2/{test2.c => test2.cpp} | 0 .../palsuite/c_runtime/ceil/test1/CMakeLists.txt | 2 +- .../c_runtime/ceil/test1/{test1.c => test1.cpp} | 0 .../tests/palsuite/c_runtime/ceilf/CMakeLists.txt | 3 + .../palsuite/c_runtime/ceilf/test1/CMakeLists.txt | 19 + .../tests/palsuite/c_runtime/ceilf/test1/test1.c | 131 + .../palsuite/c_runtime/ceilf/test1/testinfo.dat | 14 + .../palsuite/c_runtime/cos/test1/CMakeLists.txt | 2 +- .../c_runtime/cos/test1/{test1.c => test1.cpp} | 0 .../tests/palsuite/c_runtime/cosf/CMakeLists.txt | 3 + .../palsuite/c_runtime/cosf/test1/CMakeLists.txt | 19 + .../tests/palsuite/c_runtime/cosf/test1/test1.c | 130 + .../palsuite/c_runtime/cosf/test1/testinfo.dat | 13 + .../palsuite/c_runtime/cosh/test1/CMakeLists.txt | 2 +- .../c_runtime/cosh/test1/{test1.c => test1.cpp} | 0 .../tests/palsuite/c_runtime/coshf/CMakeLists.txt | 3 + .../palsuite/c_runtime/coshf/test1/CMakeLists.txt | 19 + .../tests/palsuite/c_runtime/coshf/test1/test1.c | 129 + .../palsuite/c_runtime/coshf/test1/testinfo.dat | 13 + .../palsuite/c_runtime/ctime/test1/CMakeLists.txt | 2 +- .../c_runtime/ctime/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/errno/test1/CMakeLists.txt | 2 +- .../c_runtime/errno/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/errno/test2/CMakeLists.txt | 2 +- .../c_runtime/errno/test2/{test2.c => test2.cpp} | 0 .../palsuite/c_runtime/exit/test1/CMakeLists.txt | 2 +- .../c_runtime/exit/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/exit/test2/CMakeLists.txt | 2 +- .../c_runtime/exit/test2/{test2.c => test2.cpp} | 0 .../palsuite/c_runtime/exp/test1/CMakeLists.txt | 2 +- .../c_runtime/exp/test1/{test1.c => test1.cpp} | 0 .../tests/palsuite/c_runtime/expf/CMakeLists.txt | 3 + .../palsuite/c_runtime/expf/test1/CMakeLists.txt | 19 + .../tests/palsuite/c_runtime/expf/test1/test1.c | 137 + .../palsuite/c_runtime/expf/test1/testinfo.dat | 12 + .../palsuite/c_runtime/fabs/test1/CMakeLists.txt | 2 +- .../c_runtime/fabs/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/fabsf/test1/CMakeLists.txt | 2 +- .../c_runtime/fabsf/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/fclose/test1/CMakeLists.txt | 2 +- .../c_runtime/fclose/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/fclose/test2/CMakeLists.txt | 2 +- .../c_runtime/fclose/test2/{test2.c => test2.cpp} | 0 .../palsuite/c_runtime/feof/test1/CMakeLists.txt | 2 +- .../c_runtime/feof/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/ferror/test1/CMakeLists.txt | 2 +- .../c_runtime/ferror/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/ferror/test2/CMakeLists.txt | 2 +- .../c_runtime/ferror/test2/{test2.c => test2.cpp} | 0 .../palsuite/c_runtime/fflush/test1/CMakeLists.txt | 2 +- .../c_runtime/fflush/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/fgets/test1/CMakeLists.txt | 2 +- .../c_runtime/fgets/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/fgets/test2/CMakeLists.txt | 2 +- .../c_runtime/fgets/test2/{test2.c => test2.cpp} | 0 .../palsuite/c_runtime/fgets/test3/CMakeLists.txt | 2 +- .../c_runtime/fgets/test3/{test3.c => test3.cpp} | 0 .../palsuite/c_runtime/floor/test1/CMakeLists.txt | 2 +- .../c_runtime/floor/test1/{test1.c => test1.cpp} | 0 .../tests/palsuite/c_runtime/floorf/CMakeLists.txt | 3 + .../palsuite/c_runtime/floorf/test1/CMakeLists.txt | 19 + .../tests/palsuite/c_runtime/floorf/test1/test1.c | 131 + .../palsuite/c_runtime/floorf/test1/testinfo.dat | 13 + .../palsuite/c_runtime/fmod/test1/CMakeLists.txt | 2 +- .../c_runtime/fmod/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/fmodf/test1/CMakeLists.txt | 2 +- .../c_runtime/fmodf/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/fopen/test1/CMakeLists.txt | 2 +- .../c_runtime/fopen/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/fopen/test2/CMakeLists.txt | 2 +- .../c_runtime/fopen/test2/{test2.c => test2.cpp} | 0 .../palsuite/c_runtime/fopen/test3/CMakeLists.txt | 2 +- .../c_runtime/fopen/test3/{test3.c => test3.cpp} | 0 .../palsuite/c_runtime/fopen/test4/CMakeLists.txt | 2 +- .../c_runtime/fopen/test4/{test4.c => test4.cpp} | 0 .../palsuite/c_runtime/fopen/test5/CMakeLists.txt | 2 +- .../c_runtime/fopen/test5/{test5.c => test5.cpp} | 0 .../palsuite/c_runtime/fopen/test6/CMakeLists.txt | 2 +- .../c_runtime/fopen/test6/{test6.c => test6.cpp} | 0 .../palsuite/c_runtime/fopen/test7/CMakeLists.txt | 2 +- .../c_runtime/fopen/test7/{test7.c => test7.cpp} | 0 src/pal/tests/palsuite/c_runtime/fprintf/fprintf.h | 14 +- .../c_runtime/fprintf/test1/CMakeLists.txt | 2 +- .../c_runtime/fprintf/test1/{test1.c => test1.cpp} | 0 .../c_runtime/fprintf/test10/CMakeLists.txt | 2 +- .../fprintf/test10/{test10.c => test10.cpp} | 0 .../c_runtime/fprintf/test11/CMakeLists.txt | 2 +- .../fprintf/test11/{test11.c => test11.cpp} | 0 .../c_runtime/fprintf/test12/CMakeLists.txt | 2 +- .../fprintf/test12/{test12.c => test12.cpp} | 0 .../c_runtime/fprintf/test13/CMakeLists.txt | 2 +- .../fprintf/test13/{test13.c => test13.cpp} | 0 .../c_runtime/fprintf/test14/CMakeLists.txt | 2 +- .../fprintf/test14/{test14.c => test14.cpp} | 0 .../c_runtime/fprintf/test15/CMakeLists.txt | 2 +- .../fprintf/test15/{test15.c => test15.cpp} | 0 .../c_runtime/fprintf/test16/CMakeLists.txt | 2 +- .../fprintf/test16/{test16.c => test16.cpp} | 0 .../c_runtime/fprintf/test17/CMakeLists.txt | 2 +- .../fprintf/test17/{test17.c => test17.cpp} | 0 .../c_runtime/fprintf/test18/CMakeLists.txt | 2 +- .../fprintf/test18/{test18.c => test18.cpp} | 0 .../c_runtime/fprintf/test19/CMakeLists.txt | 2 +- .../fprintf/test19/{test19.c => test19.cpp} | 0 .../c_runtime/fprintf/test2/CMakeLists.txt | 2 +- .../c_runtime/fprintf/test2/{test2.c => test2.cpp} | 0 .../c_runtime/fprintf/test3/CMakeLists.txt | 2 +- .../c_runtime/fprintf/test3/{test3.c => test3.cpp} | 0 .../c_runtime/fprintf/test4/CMakeLists.txt | 2 +- .../c_runtime/fprintf/test4/{test4.c => test4.cpp} | 0 .../c_runtime/fprintf/test5/CMakeLists.txt | 2 +- .../c_runtime/fprintf/test5/{test5.c => test5.cpp} | 0 .../c_runtime/fprintf/test6/CMakeLists.txt | 2 +- .../c_runtime/fprintf/test6/{test6.c => test6.cpp} | 0 .../c_runtime/fprintf/test7/CMakeLists.txt | 2 +- .../c_runtime/fprintf/test7/{test7.c => test7.cpp} | 0 .../c_runtime/fprintf/test8/CMakeLists.txt | 2 +- .../c_runtime/fprintf/test8/{test8.c => test8.cpp} | 0 .../c_runtime/fprintf/test9/CMakeLists.txt | 2 +- .../c_runtime/fprintf/test9/{test9.c => test9.cpp} | 0 .../palsuite/c_runtime/fputs/test1/CMakeLists.txt | 2 +- .../c_runtime/fputs/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/fputs/test2/CMakeLists.txt | 2 +- .../c_runtime/fputs/test2/{test2.c => test2.cpp} | 0 .../palsuite/c_runtime/fread/test1/CMakeLists.txt | 2 +- .../c_runtime/fread/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/fread/test2/CMakeLists.txt | 2 +- .../c_runtime/fread/test2/{test2.c => test2.cpp} | 0 .../palsuite/c_runtime/fread/test3/CMakeLists.txt | 2 +- .../c_runtime/fread/test3/{test3.c => test3.cpp} | 0 .../palsuite/c_runtime/free/test1/CMakeLists.txt | 2 +- .../c_runtime/free/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/fseek/test1/CMakeLists.txt | 2 +- .../tests/palsuite/c_runtime/fseek/test1/test1.c | 193 - .../tests/palsuite/c_runtime/fseek/test1/test1.cpp | 193 + .../palsuite/c_runtime/ftell/test1/CMakeLists.txt | 2 +- .../c_runtime/ftell/test1/{ftell.c => ftell.cpp} | 0 .../tests/palsuite/c_runtime/fwprintf/fwprintf.h | 34 +- .../c_runtime/fwprintf/test1/CMakeLists.txt | 2 +- .../fwprintf/test1/{test1.c => test1.cpp} | 0 .../c_runtime/fwprintf/test10/CMakeLists.txt | 2 +- .../fwprintf/test10/{test10.c => test10.cpp} | 0 .../c_runtime/fwprintf/test11/CMakeLists.txt | 2 +- .../fwprintf/test11/{test11.c => test11.cpp} | 0 .../c_runtime/fwprintf/test12/CMakeLists.txt | 2 +- .../fwprintf/test12/{test12.c => test12.cpp} | 0 .../c_runtime/fwprintf/test13/CMakeLists.txt | 2 +- .../fwprintf/test13/{test13.c => test13.cpp} | 0 .../c_runtime/fwprintf/test14/CMakeLists.txt | 2 +- .../fwprintf/test14/{test14.c => test14.cpp} | 0 .../c_runtime/fwprintf/test15/CMakeLists.txt | 2 +- .../fwprintf/test15/{test15.c => test15.cpp} | 0 .../c_runtime/fwprintf/test16/CMakeLists.txt | 2 +- .../fwprintf/test16/{test16.c => test16.cpp} | 0 .../c_runtime/fwprintf/test17/CMakeLists.txt | 2 +- .../fwprintf/test17/{test17.c => test17.cpp} | 0 .../c_runtime/fwprintf/test18/CMakeLists.txt | 2 +- .../fwprintf/test18/{test18.c => test18.cpp} | 0 .../c_runtime/fwprintf/test19/CMakeLists.txt | 2 +- .../palsuite/c_runtime/fwprintf/test19/test19.c | 81 - .../palsuite/c_runtime/fwprintf/test19/test19.cpp | 81 + .../c_runtime/fwprintf/test2/CMakeLists.txt | 2 +- .../fwprintf/test2/{test2.c => test2.cpp} | 0 .../c_runtime/fwprintf/test3/CMakeLists.txt | 2 +- .../fwprintf/test3/{test3.c => test3.cpp} | 0 .../c_runtime/fwprintf/test4/CMakeLists.txt | 2 +- .../fwprintf/test4/{test4.c => test4.cpp} | 0 .../c_runtime/fwprintf/test5/CMakeLists.txt | 2 +- .../fwprintf/test5/{test5.c => test5.cpp} | 0 .../c_runtime/fwprintf/test6/CMakeLists.txt | 2 +- .../fwprintf/test6/{test6.c => test6.cpp} | 0 .../c_runtime/fwprintf/test7/CMakeLists.txt | 2 +- .../fwprintf/test7/{test7.c => test7.cpp} | 0 .../c_runtime/fwprintf/test8/CMakeLists.txt | 2 +- .../fwprintf/test8/{test8.c => test8.cpp} | 0 .../c_runtime/fwprintf/test9/CMakeLists.txt | 2 +- .../fwprintf/test9/{test9.c => test9.cpp} | 0 .../palsuite/c_runtime/fwrite/test1/CMakeLists.txt | 2 +- .../c_runtime/fwrite/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/getc/test1/CMakeLists.txt | 2 +- .../c_runtime/getc/test1/{getc.c => getc.cpp} | 0 .../palsuite/c_runtime/getenv/test1/CMakeLists.txt | 2 +- .../c_runtime/getenv/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/getenv/test2/CMakeLists.txt | 2 +- .../c_runtime/getenv/test2/{test2.c => test2.cpp} | 0 .../palsuite/c_runtime/getenv/test3/CMakeLists.txt | 2 +- .../c_runtime/getenv/test3/{test3.c => test3.cpp} | 0 .../c_runtime/isalnum/test1/CMakeLists.txt | 2 +- .../c_runtime/isalnum/test1/{test1.c => test1.cpp} | 0 .../c_runtime/isalpha/test1/CMakeLists.txt | 2 +- .../c_runtime/isalpha/test1/{test1.c => test1.cpp} | 0 .../c_runtime/isdigit/test1/CMakeLists.txt | 2 +- .../c_runtime/isdigit/test1/{test1.c => test1.cpp} | 0 .../c_runtime/islower/test1/CMakeLists.txt | 2 +- .../c_runtime/islower/test1/{test1.c => test1.cpp} | 0 .../c_runtime/isprint/test1/CMakeLists.txt | 2 +- .../isprint/test1/{isprint.c => isprint.cpp} | 0 .../c_runtime/isprint/test2/CMakeLists.txt | 2 +- .../c_runtime/isprint/test2/{test2.c => test2.cpp} | 0 .../c_runtime/isspace/test1/CMakeLists.txt | 2 +- .../c_runtime/isspace/test1/{test1.c => test1.cpp} | 0 .../c_runtime/isupper/test1/CMakeLists.txt | 2 +- .../c_runtime/isupper/test1/{test1.c => test1.cpp} | 0 .../c_runtime/iswdigit/test1/CMakeLists.txt | 2 +- .../iswdigit/test1/{test1.c => test1.cpp} | 0 .../c_runtime/iswprint/test1/CMakeLists.txt | 2 +- .../iswprint/test1/{test1.c => test1.cpp} | 0 .../c_runtime/iswspace/test1/CMakeLists.txt | 2 +- .../iswspace/test1/{test1.c => test1.cpp} | 0 .../c_runtime/iswupper/test1/CMakeLists.txt | 2 +- .../iswupper/test1/{test1.c => test1.cpp} | 0 .../c_runtime/iswxdigit/test1/CMakeLists.txt | 2 +- .../iswxdigit/test1/{test1.c => test1.cpp} | 0 .../c_runtime/isxdigit/test1/CMakeLists.txt | 2 +- .../isxdigit/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/labs/test1/CMakeLists.txt | 2 +- .../c_runtime/labs/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/llabs/test1/CMakeLists.txt | 2 +- .../c_runtime/llabs/test1/{test1.c => test1.cpp} | 0 .../c_runtime/localtime/test1/CMakeLists.txt | 2 +- .../localtime/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/log/test1/CMakeLists.txt | 2 +- .../c_runtime/log/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/log10/test1/CMakeLists.txt | 2 +- .../c_runtime/log10/test1/{test1.c => test1.cpp} | 0 .../tests/palsuite/c_runtime/log10f/CMakeLists.txt | 3 + .../palsuite/c_runtime/log10f/test1/CMakeLists.txt | 19 + .../tests/palsuite/c_runtime/log10f/test1/test1.c | 144 + .../palsuite/c_runtime/log10f/test1/testinfo.dat | 17 + .../tests/palsuite/c_runtime/logf/CMakeLists.txt | 3 + .../palsuite/c_runtime/logf/test1/CMakeLists.txt | 19 + .../tests/palsuite/c_runtime/logf/test1/test1.c | 139 + .../palsuite/c_runtime/logf/test1/testinfo.dat | 14 + .../palsuite/c_runtime/malloc/test1/CMakeLists.txt | 2 +- .../c_runtime/malloc/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/malloc/test2/CMakeLists.txt | 2 +- .../c_runtime/malloc/test2/{test2.c => test2.cpp} | 0 .../palsuite/c_runtime/memchr/test1/CMakeLists.txt | 2 +- .../c_runtime/memchr/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/memcmp/test1/CMakeLists.txt | 2 +- .../c_runtime/memcmp/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/memcpy/test1/CMakeLists.txt | 2 +- .../c_runtime/memcpy/test1/{test1.c => test1.cpp} | 0 .../c_runtime/memmove/test1/CMakeLists.txt | 2 +- .../tests/palsuite/c_runtime/memmove/test1/test1.c | 116 - .../palsuite/c_runtime/memmove/test1/test1.cpp | 116 + .../palsuite/c_runtime/memset/test1/CMakeLists.txt | 2 +- .../c_runtime/memset/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/modf/test1/CMakeLists.txt | 2 +- .../c_runtime/modf/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/modff/test1/CMakeLists.txt | 2 +- .../c_runtime/modff/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/pow/test1/CMakeLists.txt | 2 +- .../c_runtime/pow/test1/{test1.c => test1.cpp} | 0 .../tests/palsuite/c_runtime/powf/CMakeLists.txt | 3 + .../palsuite/c_runtime/powf/test1/CMakeLists.txt | 19 + .../tests/palsuite/c_runtime/powf/test1/test1.c | 229 + .../palsuite/c_runtime/powf/test1/testinfo.dat | 17 + src/pal/tests/palsuite/c_runtime/printf/printf.h | 34 +- .../palsuite/c_runtime/printf/test1/CMakeLists.txt | 2 +- .../c_runtime/printf/test1/{test1.c => test1.cpp} | 0 .../c_runtime/printf/test10/CMakeLists.txt | 2 +- .../printf/test10/{test10.c => test10.cpp} | 0 .../c_runtime/printf/test11/CMakeLists.txt | 2 +- .../printf/test11/{test11.c => test11.cpp} | 0 .../c_runtime/printf/test12/CMakeLists.txt | 2 +- .../printf/test12/{test12.c => test12.cpp} | 0 .../c_runtime/printf/test13/CMakeLists.txt | 2 +- .../printf/test13/{test13.c => test13.cpp} | 0 .../c_runtime/printf/test14/CMakeLists.txt | 2 +- .../printf/test14/{test14.c => test14.cpp} | 0 .../c_runtime/printf/test15/CMakeLists.txt | 2 +- .../printf/test15/{test15.c => test15.cpp} | 0 .../c_runtime/printf/test16/CMakeLists.txt | 2 +- .../printf/test16/{test16.c => test16.cpp} | 0 .../c_runtime/printf/test17/CMakeLists.txt | 2 +- .../printf/test17/{test17.c => test17.cpp} | 0 .../c_runtime/printf/test18/CMakeLists.txt | 2 +- .../printf/test18/{test18.c => test18.cpp} | 0 .../c_runtime/printf/test19/CMakeLists.txt | 2 +- .../palsuite/c_runtime/printf/test19/test19.c | 76 - .../palsuite/c_runtime/printf/test19/test19.cpp | 76 + .../palsuite/c_runtime/printf/test2/CMakeLists.txt | 2 +- .../c_runtime/printf/test2/{test2.c => test2.cpp} | 0 .../palsuite/c_runtime/printf/test3/CMakeLists.txt | 2 +- .../c_runtime/printf/test3/{test3.c => test3.cpp} | 0 .../palsuite/c_runtime/printf/test4/CMakeLists.txt | 2 +- .../c_runtime/printf/test4/{test4.c => test4.cpp} | 0 .../palsuite/c_runtime/printf/test5/CMakeLists.txt | 2 +- .../c_runtime/printf/test5/{test5.c => test5.cpp} | 0 .../palsuite/c_runtime/printf/test6/CMakeLists.txt | 2 +- .../c_runtime/printf/test6/{test6.c => test6.cpp} | 0 .../palsuite/c_runtime/printf/test7/CMakeLists.txt | 2 +- .../c_runtime/printf/test7/{test7.c => test7.cpp} | 0 .../palsuite/c_runtime/printf/test8/CMakeLists.txt | 2 +- .../c_runtime/printf/test8/{test8.c => test8.cpp} | 0 .../palsuite/c_runtime/printf/test9/CMakeLists.txt | 2 +- .../c_runtime/printf/test9/{test9.c => test9.cpp} | 0 .../palsuite/c_runtime/qsort/test1/CMakeLists.txt | 2 +- .../c_runtime/qsort/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/qsort/test2/CMakeLists.txt | 2 +- .../c_runtime/qsort/test2/{test2.c => test2.cpp} | 0 .../c_runtime/rand_srand/test1/CMakeLists.txt | 2 +- .../rand_srand/test1/{test1.c => test1.cpp} | 0 .../c_runtime/realloc/test1/CMakeLists.txt | 2 +- .../tests/palsuite/c_runtime/realloc/test1/test1.c | 66 - .../palsuite/c_runtime/realloc/test1/test1.cpp | 66 + .../palsuite/c_runtime/sin/test1/CMakeLists.txt | 2 +- .../c_runtime/sin/test1/{test1.c => test1.cpp} | 0 .../tests/palsuite/c_runtime/sinf/CMakeLists.txt | 3 + .../palsuite/c_runtime/sinf/test1/CMakeLists.txt | 19 + .../tests/palsuite/c_runtime/sinf/test1/test1.c | 130 + .../palsuite/c_runtime/sinf/test1/testinfo.dat | 13 + .../palsuite/c_runtime/sinh/test1/CMakeLists.txt | 2 +- .../c_runtime/sinh/test1/{test1.c => test1.cpp} | 0 .../tests/palsuite/c_runtime/sinhf/CMakeLists.txt | 3 + .../palsuite/c_runtime/sinhf/test1/CMakeLists.txt | 19 + .../tests/palsuite/c_runtime/sinhf/test1/test1.c | 129 + .../palsuite/c_runtime/sinhf/test1/testinfo.dat | 13 + .../palsuite/c_runtime/sprintf/CMakeLists.txt | 22 - src/pal/tests/palsuite/c_runtime/sprintf/sprintf.h | 195 - .../c_runtime/sprintf/test1/CMakeLists.txt | 19 - .../tests/palsuite/c_runtime/sprintf/test1/test1.c | 45 - .../palsuite/c_runtime/sprintf/test1/testinfo.dat | 12 - .../c_runtime/sprintf/test10/CMakeLists.txt | 19 - .../palsuite/c_runtime/sprintf/test10/test10.c | 55 - .../palsuite/c_runtime/sprintf/test10/testinfo.dat | 12 - .../c_runtime/sprintf/test11/CMakeLists.txt | 19 - .../palsuite/c_runtime/sprintf/test11/test11.c | 55 - .../palsuite/c_runtime/sprintf/test11/testinfo.dat | 12 - .../c_runtime/sprintf/test12/CMakeLists.txt | 19 - .../palsuite/c_runtime/sprintf/test12/test12.c | 56 - .../palsuite/c_runtime/sprintf/test12/testinfo.dat | 12 - .../c_runtime/sprintf/test13/CMakeLists.txt | 19 - .../palsuite/c_runtime/sprintf/test13/test13.c | 56 - .../palsuite/c_runtime/sprintf/test13/testinfo.dat | 12 - .../c_runtime/sprintf/test14/CMakeLists.txt | 19 - .../palsuite/c_runtime/sprintf/test14/test14.c | 53 - .../palsuite/c_runtime/sprintf/test14/testinfo.dat | 12 - .../c_runtime/sprintf/test15/CMakeLists.txt | 19 - .../palsuite/c_runtime/sprintf/test15/test15.c | 53 - .../palsuite/c_runtime/sprintf/test15/testinfo.dat | 12 - .../c_runtime/sprintf/test16/CMakeLists.txt | 19 - .../palsuite/c_runtime/sprintf/test16/test16.c | 52 - .../palsuite/c_runtime/sprintf/test16/testinfo.dat | 12 - .../c_runtime/sprintf/test17/CMakeLists.txt | 19 - .../palsuite/c_runtime/sprintf/test17/test17.c | 54 - .../palsuite/c_runtime/sprintf/test17/testinfo.dat | 12 - .../c_runtime/sprintf/test18/CMakeLists.txt | 19 - .../palsuite/c_runtime/sprintf/test18/test18.c | 53 - .../palsuite/c_runtime/sprintf/test18/testinfo.dat | 12 - .../c_runtime/sprintf/test19/CMakeLists.txt | 19 - .../palsuite/c_runtime/sprintf/test19/test19.c | 78 - .../palsuite/c_runtime/sprintf/test19/testinfo.dat | 12 - .../c_runtime/sprintf/test2/CMakeLists.txt | 19 - .../tests/palsuite/c_runtime/sprintf/test2/test2.c | 47 - .../palsuite/c_runtime/sprintf/test2/testinfo.dat | 12 - .../c_runtime/sprintf/test3/CMakeLists.txt | 19 - .../tests/palsuite/c_runtime/sprintf/test3/test3.c | 47 - .../palsuite/c_runtime/sprintf/test3/testinfo.dat | 12 - .../c_runtime/sprintf/test4/CMakeLists.txt | 19 - .../tests/palsuite/c_runtime/sprintf/test4/test4.c | 69 - .../palsuite/c_runtime/sprintf/test4/testinfo.dat | 12 - .../c_runtime/sprintf/test5/CMakeLists.txt | 19 - .../tests/palsuite/c_runtime/sprintf/test5/test5.c | 62 - .../palsuite/c_runtime/sprintf/test5/testinfo.dat | 12 - .../c_runtime/sprintf/test6/CMakeLists.txt | 19 - .../tests/palsuite/c_runtime/sprintf/test6/test6.c | 50 - .../palsuite/c_runtime/sprintf/test6/testinfo.dat | 12 - .../c_runtime/sprintf/test7/CMakeLists.txt | 19 - .../tests/palsuite/c_runtime/sprintf/test7/test7.c | 49 - .../palsuite/c_runtime/sprintf/test7/testinfo.dat | 12 - .../c_runtime/sprintf/test8/CMakeLists.txt | 19 - .../tests/palsuite/c_runtime/sprintf/test8/test8.c | 55 - .../palsuite/c_runtime/sprintf/test8/testinfo.dat | 12 - .../c_runtime/sprintf/test9/CMakeLists.txt | 19 - .../tests/palsuite/c_runtime/sprintf/test9/test9.c | 55 - .../palsuite/c_runtime/sprintf/test9/testinfo.dat | 12 - .../palsuite/c_runtime/sprintf_s/CMakeLists.txt | 21 + .../tests/palsuite/c_runtime/sprintf_s/sprintf_s.h | 195 + .../c_runtime/sprintf_s/test1/CMakeLists.txt | 19 + .../palsuite/c_runtime/sprintf_s/test1/test1.cpp | 45 + .../c_runtime/sprintf_s/test1/testinfo.dat | 12 + .../c_runtime/sprintf_s/test10/CMakeLists.txt | 19 + .../palsuite/c_runtime/sprintf_s/test10/test10.cpp | 55 + .../c_runtime/sprintf_s/test10/testinfo.dat | 12 + .../c_runtime/sprintf_s/test11/CMakeLists.txt | 19 + .../palsuite/c_runtime/sprintf_s/test11/test11.cpp | 55 + .../c_runtime/sprintf_s/test11/testinfo.dat | 12 + .../c_runtime/sprintf_s/test12/CMakeLists.txt | 19 + .../palsuite/c_runtime/sprintf_s/test12/test12.cpp | 56 + .../c_runtime/sprintf_s/test12/testinfo.dat | 12 + .../c_runtime/sprintf_s/test13/CMakeLists.txt | 19 + .../palsuite/c_runtime/sprintf_s/test13/test13.cpp | 56 + .../c_runtime/sprintf_s/test13/testinfo.dat | 12 + .../c_runtime/sprintf_s/test14/CMakeLists.txt | 19 + .../palsuite/c_runtime/sprintf_s/test14/test14.cpp | 53 + .../c_runtime/sprintf_s/test14/testinfo.dat | 12 + .../c_runtime/sprintf_s/test15/CMakeLists.txt | 19 + .../palsuite/c_runtime/sprintf_s/test15/test15.cpp | 53 + .../c_runtime/sprintf_s/test15/testinfo.dat | 12 + .../c_runtime/sprintf_s/test16/CMakeLists.txt | 19 + .../palsuite/c_runtime/sprintf_s/test16/test16.cpp | 52 + .../c_runtime/sprintf_s/test16/testinfo.dat | 12 + .../c_runtime/sprintf_s/test17/CMakeLists.txt | 19 + .../palsuite/c_runtime/sprintf_s/test17/test17.cpp | 54 + .../c_runtime/sprintf_s/test17/testinfo.dat | 12 + .../c_runtime/sprintf_s/test18/CMakeLists.txt | 19 + .../palsuite/c_runtime/sprintf_s/test18/test18.cpp | 53 + .../c_runtime/sprintf_s/test18/testinfo.dat | 12 + .../c_runtime/sprintf_s/test19/CMakeLists.txt | 19 + .../palsuite/c_runtime/sprintf_s/test19/test19.cpp | 71 + .../c_runtime/sprintf_s/test19/testinfo.dat | 12 + .../c_runtime/sprintf_s/test2/CMakeLists.txt | 19 + .../palsuite/c_runtime/sprintf_s/test2/test2.cpp | 47 + .../c_runtime/sprintf_s/test2/testinfo.dat | 12 + .../c_runtime/sprintf_s/test3/CMakeLists.txt | 19 + .../palsuite/c_runtime/sprintf_s/test3/test3.cpp | 47 + .../c_runtime/sprintf_s/test3/testinfo.dat | 12 + .../c_runtime/sprintf_s/test4/CMakeLists.txt | 19 + .../palsuite/c_runtime/sprintf_s/test4/test4.cpp | 69 + .../c_runtime/sprintf_s/test4/testinfo.dat | 12 + .../c_runtime/sprintf_s/test6/CMakeLists.txt | 19 + .../palsuite/c_runtime/sprintf_s/test6/test6.cpp | 50 + .../c_runtime/sprintf_s/test6/testinfo.dat | 12 + .../c_runtime/sprintf_s/test7/CMakeLists.txt | 19 + .../palsuite/c_runtime/sprintf_s/test7/test7.cpp | 49 + .../c_runtime/sprintf_s/test7/testinfo.dat | 12 + .../c_runtime/sprintf_s/test8/CMakeLists.txt | 19 + .../palsuite/c_runtime/sprintf_s/test8/test8.cpp | 55 + .../c_runtime/sprintf_s/test8/testinfo.dat | 12 + .../c_runtime/sprintf_s/test9/CMakeLists.txt | 19 + .../palsuite/c_runtime/sprintf_s/test9/test9.cpp | 55 + .../c_runtime/sprintf_s/test9/testinfo.dat | 12 + .../palsuite/c_runtime/sqrt/test1/CMakeLists.txt | 2 +- .../c_runtime/sqrt/test1/{test1.c => test1.cpp} | 0 .../lstrcpynW => c_runtime/sqrtf}/CMakeLists.txt | 0 .../palsuite/c_runtime/sqrtf/test1/CMakeLists.txt | 19 + .../tests/palsuite/c_runtime/sqrtf/test1/test1.c | 122 + .../palsuite/c_runtime/sqrtf/test1/testinfo.dat | 17 + src/pal/tests/palsuite/c_runtime/sscanf/sscanf.h | 246 - .../palsuite/c_runtime/sscanf/test1/CMakeLists.txt | 19 - .../tests/palsuite/c_runtime/sscanf/test1/test1.c | 53 - .../palsuite/c_runtime/sscanf/test1/testinfo.dat | 12 - .../c_runtime/sscanf/test10/CMakeLists.txt | 19 - .../palsuite/c_runtime/sscanf/test10/test10.c | 37 - .../palsuite/c_runtime/sscanf/test10/testinfo.dat | 12 - .../c_runtime/sscanf/test11/CMakeLists.txt | 19 - .../palsuite/c_runtime/sscanf/test11/test11.c | 36 - .../palsuite/c_runtime/sscanf/test11/testinfo.dat | 12 - .../c_runtime/sscanf/test12/CMakeLists.txt | 19 - .../palsuite/c_runtime/sscanf/test12/test12.c | 35 - .../palsuite/c_runtime/sscanf/test12/testinfo.dat | 12 - .../c_runtime/sscanf/test13/CMakeLists.txt | 19 - .../palsuite/c_runtime/sscanf/test13/test13.c | 37 - .../palsuite/c_runtime/sscanf/test13/testinfo.dat | 12 - .../c_runtime/sscanf/test14/CMakeLists.txt | 19 - .../palsuite/c_runtime/sscanf/test14/test14.c | 36 - .../palsuite/c_runtime/sscanf/test14/testinfo.dat | 12 - .../c_runtime/sscanf/test15/CMakeLists.txt | 19 - .../palsuite/c_runtime/sscanf/test15/test15.c | 36 - .../palsuite/c_runtime/sscanf/test15/testinfo.dat | 12 - .../c_runtime/sscanf/test16/CMakeLists.txt | 19 - .../palsuite/c_runtime/sscanf/test16/test16.c | 37 - .../palsuite/c_runtime/sscanf/test16/testinfo.dat | 12 - .../c_runtime/sscanf/test17/CMakeLists.txt | 19 - .../palsuite/c_runtime/sscanf/test17/test17.c | 37 - .../palsuite/c_runtime/sscanf/test17/testinfo.dat | 12 - .../palsuite/c_runtime/sscanf/test2/CMakeLists.txt | 19 - .../tests/palsuite/c_runtime/sscanf/test2/test2.c | 44 - .../palsuite/c_runtime/sscanf/test2/testinfo.dat | 12 - .../palsuite/c_runtime/sscanf/test3/CMakeLists.txt | 19 - .../tests/palsuite/c_runtime/sscanf/test3/test3.c | 35 - .../palsuite/c_runtime/sscanf/test3/testinfo.dat | 12 - .../palsuite/c_runtime/sscanf/test4/CMakeLists.txt | 19 - .../tests/palsuite/c_runtime/sscanf/test4/test4.c | 44 - .../palsuite/c_runtime/sscanf/test4/testinfo.dat | 12 - .../palsuite/c_runtime/sscanf/test5/CMakeLists.txt | 19 - .../tests/palsuite/c_runtime/sscanf/test5/test5.c | 43 - .../palsuite/c_runtime/sscanf/test5/testinfo.dat | 12 - .../palsuite/c_runtime/sscanf/test6/CMakeLists.txt | 19 - .../tests/palsuite/c_runtime/sscanf/test6/test6.c | 43 - .../palsuite/c_runtime/sscanf/test6/testinfo.dat | 12 - .../palsuite/c_runtime/sscanf/test7/CMakeLists.txt | 19 - .../tests/palsuite/c_runtime/sscanf/test7/test7.c | 43 - .../palsuite/c_runtime/sscanf/test7/testinfo.dat | 12 - .../palsuite/c_runtime/sscanf/test8/CMakeLists.txt | 19 - .../tests/palsuite/c_runtime/sscanf/test8/test8.c | 43 - .../palsuite/c_runtime/sscanf/test8/testinfo.dat | 12 - .../palsuite/c_runtime/sscanf/test9/CMakeLists.txt | 19 - .../tests/palsuite/c_runtime/sscanf/test9/test9.c | 38 - .../palsuite/c_runtime/sscanf/test9/testinfo.dat | 12 - .../c_runtime/{sscanf => sscanf_s}/CMakeLists.txt | 0 .../tests/palsuite/c_runtime/sscanf_s/sscanf_s.h | 246 + .../c_runtime/sscanf_s/test1/CMakeLists.txt | 19 + .../palsuite/c_runtime/sscanf_s/test1/test1.cpp | 53 + .../palsuite/c_runtime/sscanf_s/test1/testinfo.dat | 12 + .../c_runtime/sscanf_s/test10/CMakeLists.txt | 19 + .../palsuite/c_runtime/sscanf_s/test10/test10.cpp | 37 + .../c_runtime/sscanf_s/test10/testinfo.dat | 12 + .../c_runtime/sscanf_s/test11/CMakeLists.txt | 19 + .../palsuite/c_runtime/sscanf_s/test11/test11.cpp | 36 + .../c_runtime/sscanf_s/test11/testinfo.dat | 12 + .../c_runtime/sscanf_s/test12/CMakeLists.txt | 19 + .../palsuite/c_runtime/sscanf_s/test12/test12.cpp | 35 + .../c_runtime/sscanf_s/test12/testinfo.dat | 12 + .../c_runtime/sscanf_s/test13/CMakeLists.txt | 19 + .../palsuite/c_runtime/sscanf_s/test13/test13.cpp | 37 + .../c_runtime/sscanf_s/test13/testinfo.dat | 12 + .../c_runtime/sscanf_s/test14/CMakeLists.txt | 19 + .../palsuite/c_runtime/sscanf_s/test14/test14.cpp | 36 + .../c_runtime/sscanf_s/test14/testinfo.dat | 12 + .../c_runtime/sscanf_s/test15/CMakeLists.txt | 19 + .../palsuite/c_runtime/sscanf_s/test15/test15.cpp | 36 + .../c_runtime/sscanf_s/test15/testinfo.dat | 12 + .../c_runtime/sscanf_s/test16/CMakeLists.txt | 19 + .../palsuite/c_runtime/sscanf_s/test16/test16.cpp | 37 + .../c_runtime/sscanf_s/test16/testinfo.dat | 12 + .../c_runtime/sscanf_s/test17/CMakeLists.txt | 19 + .../palsuite/c_runtime/sscanf_s/test17/test17.cpp | 37 + .../c_runtime/sscanf_s/test17/testinfo.dat | 12 + .../c_runtime/sscanf_s/test2/CMakeLists.txt | 19 + .../palsuite/c_runtime/sscanf_s/test2/test2.cpp | 44 + .../palsuite/c_runtime/sscanf_s/test2/testinfo.dat | 12 + .../c_runtime/sscanf_s/test3/CMakeLists.txt | 19 + .../palsuite/c_runtime/sscanf_s/test3/test3.cpp | 35 + .../palsuite/c_runtime/sscanf_s/test3/testinfo.dat | 12 + .../c_runtime/sscanf_s/test4/CMakeLists.txt | 19 + .../palsuite/c_runtime/sscanf_s/test4/test4.cpp | 44 + .../palsuite/c_runtime/sscanf_s/test4/testinfo.dat | 12 + .../c_runtime/sscanf_s/test5/CMakeLists.txt | 19 + .../palsuite/c_runtime/sscanf_s/test5/test5.cpp | 43 + .../palsuite/c_runtime/sscanf_s/test5/testinfo.dat | 12 + .../c_runtime/sscanf_s/test6/CMakeLists.txt | 19 + .../palsuite/c_runtime/sscanf_s/test6/test6.cpp | 43 + .../palsuite/c_runtime/sscanf_s/test6/testinfo.dat | 12 + .../c_runtime/sscanf_s/test7/CMakeLists.txt | 19 + .../palsuite/c_runtime/sscanf_s/test7/test7.cpp | 43 + .../palsuite/c_runtime/sscanf_s/test7/testinfo.dat | 12 + .../c_runtime/sscanf_s/test8/CMakeLists.txt | 19 + .../palsuite/c_runtime/sscanf_s/test8/test8.cpp | 43 + .../palsuite/c_runtime/sscanf_s/test8/testinfo.dat | 12 + .../c_runtime/sscanf_s/test9/CMakeLists.txt | 19 + .../palsuite/c_runtime/sscanf_s/test9/test9.cpp | 38 + .../palsuite/c_runtime/sscanf_s/test9/testinfo.dat | 12 + .../palsuite/c_runtime/strcat/test1/CMakeLists.txt | 2 +- .../c_runtime/strcat/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/strchr/test1/CMakeLists.txt | 2 +- .../c_runtime/strchr/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/strcmp/test1/CMakeLists.txt | 2 +- .../c_runtime/strcmp/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/strcpy/test1/CMakeLists.txt | 2 +- .../c_runtime/strcpy/test1/{test1.c => test1.cpp} | 0 .../c_runtime/strcspn/test1/CMakeLists.txt | 2 +- .../c_runtime/strcspn/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/strlen/test1/CMakeLists.txt | 2 +- .../c_runtime/strlen/test1/{test1.c => test1.cpp} | 0 .../c_runtime/strncat/test1/CMakeLists.txt | 2 +- .../c_runtime/strncat/test1/{test1.c => test1.cpp} | 0 .../c_runtime/strncmp/test1/CMakeLists.txt | 2 +- .../c_runtime/strncmp/test1/{test1.c => test1.cpp} | 0 .../c_runtime/strncpy/test1/CMakeLists.txt | 2 +- .../c_runtime/strncpy/test1/{test1.c => test1.cpp} | 0 .../c_runtime/strpbrk/test1/CMakeLists.txt | 2 +- .../c_runtime/strpbrk/test1/{test1.c => test1.cpp} | 0 .../c_runtime/strrchr/test1/CMakeLists.txt | 2 +- .../c_runtime/strrchr/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/strspn/test1/CMakeLists.txt | 2 +- .../c_runtime/strspn/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/strstr/test1/CMakeLists.txt | 2 +- .../c_runtime/strstr/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/strtod/test1/CMakeLists.txt | 2 +- .../c_runtime/strtod/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/strtod/test2/CMakeLists.txt | 2 +- .../c_runtime/strtod/test2/{test2.c => test2.cpp} | 0 .../palsuite/c_runtime/strtok/test1/CMakeLists.txt | 2 +- .../c_runtime/strtok/test1/{test1.c => test1.cpp} | 0 .../c_runtime/strtoul/test1/CMakeLists.txt | 2 +- .../c_runtime/strtoul/test1/{test1.c => test1.cpp} | 0 .../tests/palsuite/c_runtime/swprintf/swprintf.h | 32 +- .../c_runtime/swprintf/test1/CMakeLists.txt | 2 +- .../swprintf/test1/{test1.c => test1.cpp} | 0 .../c_runtime/swprintf/test10/CMakeLists.txt | 2 +- .../swprintf/test10/{test10.c => test10.cpp} | 0 .../c_runtime/swprintf/test11/CMakeLists.txt | 2 +- .../swprintf/test11/{test11.c => test11.cpp} | 0 .../c_runtime/swprintf/test12/CMakeLists.txt | 2 +- .../swprintf/test12/{test12.c => test12.cpp} | 0 .../c_runtime/swprintf/test13/CMakeLists.txt | 2 +- .../swprintf/test13/{test13.c => test13.cpp} | 0 .../c_runtime/swprintf/test14/CMakeLists.txt | 2 +- .../swprintf/test14/{test14.c => test14.cpp} | 0 .../c_runtime/swprintf/test15/CMakeLists.txt | 2 +- .../swprintf/test15/{test15.c => test15.cpp} | 0 .../c_runtime/swprintf/test16/CMakeLists.txt | 2 +- .../swprintf/test16/{test16.c => test16.cpp} | 0 .../c_runtime/swprintf/test17/CMakeLists.txt | 2 +- .../swprintf/test17/{test17.c => test17.cpp} | 0 .../c_runtime/swprintf/test18/CMakeLists.txt | 2 +- .../swprintf/test18/{test18.c => test18.cpp} | 0 .../c_runtime/swprintf/test19/CMakeLists.txt | 2 +- .../palsuite/c_runtime/swprintf/test19/test19.c | 109 - .../palsuite/c_runtime/swprintf/test19/test19.cpp | 109 + .../c_runtime/swprintf/test2/CMakeLists.txt | 2 +- .../swprintf/test2/{test2.c => test2.cpp} | 0 .../c_runtime/swprintf/test3/CMakeLists.txt | 2 +- .../swprintf/test3/{test3.c => test3.cpp} | 0 .../c_runtime/swprintf/test4/CMakeLists.txt | 2 +- .../swprintf/test4/{test4.c => test4.cpp} | 0 .../c_runtime/swprintf/test5/CMakeLists.txt | 2 +- .../swprintf/test5/{test5.c => test5.cpp} | 0 .../c_runtime/swprintf/test6/CMakeLists.txt | 2 +- .../swprintf/test6/{test6.c => test6.cpp} | 0 .../c_runtime/swprintf/test7/CMakeLists.txt | 2 +- .../swprintf/test7/{test7.c => test7.cpp} | 0 .../c_runtime/swprintf/test8/CMakeLists.txt | 2 +- .../swprintf/test8/{test8.c => test8.cpp} | 0 .../c_runtime/swprintf/test9/CMakeLists.txt | 2 +- .../swprintf/test9/{test9.c => test9.cpp} | 0 src/pal/tests/palsuite/c_runtime/swscanf/swscanf.h | 22 +- .../c_runtime/swscanf/test1/CMakeLists.txt | 2 +- .../c_runtime/swscanf/test1/{test1.c => test1.cpp} | 0 .../c_runtime/swscanf/test10/CMakeLists.txt | 2 +- .../swscanf/test10/{test10.c => test10.cpp} | 0 .../c_runtime/swscanf/test11/CMakeLists.txt | 2 +- .../swscanf/test11/{test11.c => test11.cpp} | 0 .../c_runtime/swscanf/test12/CMakeLists.txt | 2 +- .../swscanf/test12/{test12.c => test12.cpp} | 0 .../c_runtime/swscanf/test13/CMakeLists.txt | 2 +- .../swscanf/test13/{test13.c => test13.cpp} | 0 .../c_runtime/swscanf/test14/CMakeLists.txt | 2 +- .../swscanf/test14/{test14.c => test14.cpp} | 0 .../c_runtime/swscanf/test15/CMakeLists.txt | 2 +- .../swscanf/test15/{test15.c => test15.cpp} | 0 .../c_runtime/swscanf/test16/CMakeLists.txt | 2 +- .../swscanf/test16/{test16.c => test16.cpp} | 0 .../c_runtime/swscanf/test17/CMakeLists.txt | 2 +- .../swscanf/test17/{test17.c => test17.cpp} | 0 .../c_runtime/swscanf/test2/CMakeLists.txt | 2 +- .../c_runtime/swscanf/test2/{test2.c => test2.cpp} | 0 .../c_runtime/swscanf/test3/CMakeLists.txt | 2 +- .../c_runtime/swscanf/test3/{test3.c => test3.cpp} | 0 .../c_runtime/swscanf/test4/CMakeLists.txt | 2 +- .../c_runtime/swscanf/test4/{test4.c => test4.cpp} | 0 .../c_runtime/swscanf/test5/CMakeLists.txt | 2 +- .../c_runtime/swscanf/test5/{test5.c => test5.cpp} | 0 .../c_runtime/swscanf/test6/CMakeLists.txt | 2 +- .../c_runtime/swscanf/test6/{test6.c => test6.cpp} | 0 .../c_runtime/swscanf/test7/CMakeLists.txt | 2 +- .../c_runtime/swscanf/test7/{test7.c => test7.cpp} | 0 .../c_runtime/swscanf/test8/CMakeLists.txt | 2 +- .../c_runtime/swscanf/test8/{test8.c => test8.cpp} | 0 .../c_runtime/swscanf/test9/CMakeLists.txt | 2 +- .../c_runtime/swscanf/test9/{test9.c => test9.cpp} | 0 .../palsuite/c_runtime/tan/test1/CMakeLists.txt | 2 +- .../c_runtime/tan/test1/{test1.c => test1.cpp} | 0 .../tests/palsuite/c_runtime/tanf/CMakeLists.txt | 3 + .../palsuite/c_runtime/tanf/test1/CMakeLists.txt | 19 + .../tests/palsuite/c_runtime/tanf/test1/test1.c | 136 + .../palsuite/c_runtime/tanf/test1/testinfo.dat | 13 + .../palsuite/c_runtime/tanh/test1/CMakeLists.txt | 2 +- .../c_runtime/tanh/test1/{test1.c => test1.cpp} | 0 .../tests/palsuite/c_runtime/tanhf/CMakeLists.txt | 3 + .../palsuite/c_runtime/tanhf/test1/CMakeLists.txt | 19 + .../tests/palsuite/c_runtime/tanhf/test1/test1.c | 129 + .../palsuite/c_runtime/tanhf/test1/testinfo.dat | 13 + .../palsuite/c_runtime/time/test1/CMakeLists.txt | 2 +- .../c_runtime/time/test1/{test1.c => test1.cpp} | 0 .../c_runtime/tolower/test1/CMakeLists.txt | 2 +- .../c_runtime/tolower/test1/{test1.c => test1.cpp} | 0 .../c_runtime/toupper/test1/CMakeLists.txt | 2 +- .../c_runtime/toupper/test1/{test1.c => test1.cpp} | 0 .../c_runtime/towlower/test1/CMakeLists.txt | 2 +- .../towlower/test1/{test1.c => test1.cpp} | 0 .../c_runtime/towupper/test1/CMakeLists.txt | 2 +- .../towupper/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/ungetc/test1/CMakeLists.txt | 2 +- .../ungetc/test1/{ungetc.c => ungetc.cpp} | 0 .../palsuite/c_runtime/ungetc/test2/CMakeLists.txt | 2 +- .../ungetc/test2/{ungetc.c => ungetc.cpp} | 0 .../c_runtime/vfprintf/test1/CMakeLists.txt | 2 +- .../vfprintf/test1/{test1.c => test1.cpp} | 0 .../c_runtime/vfprintf/test10/CMakeLists.txt | 2 +- .../vfprintf/test10/{test10.c => test10.cpp} | 0 .../c_runtime/vfprintf/test11/CMakeLists.txt | 2 +- .../vfprintf/test11/{test11.c => test11.cpp} | 0 .../c_runtime/vfprintf/test12/CMakeLists.txt | 2 +- .../vfprintf/test12/{test12.c => test12.cpp} | 0 .../c_runtime/vfprintf/test13/CMakeLists.txt | 2 +- .../vfprintf/test13/{test13.c => test13.cpp} | 0 .../c_runtime/vfprintf/test14/CMakeLists.txt | 2 +- .../vfprintf/test14/{test14.c => test14.cpp} | 0 .../c_runtime/vfprintf/test15/CMakeLists.txt | 2 +- .../vfprintf/test15/{test15.c => test15.cpp} | 0 .../c_runtime/vfprintf/test16/CMakeLists.txt | 2 +- .../vfprintf/test16/{test16.c => test16.cpp} | 0 .../c_runtime/vfprintf/test17/CMakeLists.txt | 2 +- .../vfprintf/test17/{test17.c => test17.cpp} | 0 .../c_runtime/vfprintf/test18/CMakeLists.txt | 2 +- .../vfprintf/test18/{test18.c => test18.cpp} | 0 .../c_runtime/vfprintf/test19/CMakeLists.txt | 2 +- .../palsuite/c_runtime/vfprintf/test19/test19.c | 76 - .../palsuite/c_runtime/vfprintf/test19/test19.cpp | 76 + .../c_runtime/vfprintf/test2/CMakeLists.txt | 2 +- .../vfprintf/test2/{test2.c => test2.cpp} | 0 .../c_runtime/vfprintf/test3/CMakeLists.txt | 2 +- .../vfprintf/test3/{test3.c => test3.cpp} | 0 .../c_runtime/vfprintf/test4/CMakeLists.txt | 2 +- .../vfprintf/test4/{test4.c => test4.cpp} | 0 .../c_runtime/vfprintf/test5/CMakeLists.txt | 2 +- .../vfprintf/test5/{test5.c => test5.cpp} | 0 .../c_runtime/vfprintf/test6/CMakeLists.txt | 2 +- .../vfprintf/test6/{test6.c => test6.cpp} | 0 .../c_runtime/vfprintf/test7/CMakeLists.txt | 2 +- .../vfprintf/test7/{test7.c => test7.cpp} | 0 .../c_runtime/vfprintf/test8/CMakeLists.txt | 2 +- .../vfprintf/test8/{test8.c => test8.cpp} | 0 .../c_runtime/vfprintf/test9/CMakeLists.txt | 2 +- .../vfprintf/test9/{test9.c => test9.cpp} | 0 .../tests/palsuite/c_runtime/vfprintf/vfprintf.h | 34 +- .../c_runtime/vprintf/test1/CMakeLists.txt | 2 +- .../c_runtime/vprintf/test1/{test1.c => test1.cpp} | 0 .../c_runtime/vprintf/test10/CMakeLists.txt | 2 +- .../vprintf/test10/{test10.c => test10.cpp} | 0 .../c_runtime/vprintf/test11/CMakeLists.txt | 2 +- .../vprintf/test11/{test11.c => test11.cpp} | 0 .../c_runtime/vprintf/test12/CMakeLists.txt | 2 +- .../vprintf/test12/{test12.c => test12.cpp} | 0 .../c_runtime/vprintf/test13/CMakeLists.txt | 2 +- .../vprintf/test13/{test13.c => test13.cpp} | 0 .../c_runtime/vprintf/test14/CMakeLists.txt | 2 +- .../vprintf/test14/{test14.c => test14.cpp} | 0 .../c_runtime/vprintf/test15/CMakeLists.txt | 2 +- .../vprintf/test15/{test15.c => test15.cpp} | 0 .../c_runtime/vprintf/test16/CMakeLists.txt | 2 +- .../vprintf/test16/{test16.c => test16.cpp} | 0 .../c_runtime/vprintf/test17/CMakeLists.txt | 2 +- .../vprintf/test17/{test17.c => test17.cpp} | 0 .../c_runtime/vprintf/test18/CMakeLists.txt | 2 +- .../vprintf/test18/{test18.c => test18.cpp} | 0 .../c_runtime/vprintf/test19/CMakeLists.txt | 2 +- .../palsuite/c_runtime/vprintf/test19/test19.c | 76 - .../palsuite/c_runtime/vprintf/test19/test19.cpp | 76 + .../c_runtime/vprintf/test2/CMakeLists.txt | 2 +- .../c_runtime/vprintf/test2/{test2.c => test2.cpp} | 0 .../c_runtime/vprintf/test3/CMakeLists.txt | 2 +- .../c_runtime/vprintf/test3/{test3.c => test3.cpp} | 0 .../c_runtime/vprintf/test4/CMakeLists.txt | 2 +- .../c_runtime/vprintf/test4/{test4.c => test4.cpp} | 0 .../c_runtime/vprintf/test5/CMakeLists.txt | 2 +- .../c_runtime/vprintf/test5/{test5.c => test5.cpp} | 0 .../c_runtime/vprintf/test6/CMakeLists.txt | 2 +- .../c_runtime/vprintf/test6/{test6.c => test6.cpp} | 0 .../c_runtime/vprintf/test7/CMakeLists.txt | 2 +- .../c_runtime/vprintf/test7/{test7.c => test7.cpp} | 0 .../c_runtime/vprintf/test8/CMakeLists.txt | 2 +- .../c_runtime/vprintf/test8/{test8.c => test8.cpp} | 0 .../c_runtime/vprintf/test9/CMakeLists.txt | 2 +- .../c_runtime/vprintf/test9/{test9.c => test9.cpp} | 0 src/pal/tests/palsuite/c_runtime/vprintf/vprintf.h | 34 +- .../c_runtime/vsprintf/test1/CMakeLists.txt | 2 +- .../vsprintf/test1/{test1.c => test1.cpp} | 0 .../c_runtime/vsprintf/test10/CMakeLists.txt | 2 +- .../vsprintf/test10/{test10.c => test10.cpp} | 0 .../c_runtime/vsprintf/test11/CMakeLists.txt | 2 +- .../vsprintf/test11/{test11.c => test11.cpp} | 0 .../c_runtime/vsprintf/test12/CMakeLists.txt | 2 +- .../vsprintf/test12/{test12.c => test12.cpp} | 0 .../c_runtime/vsprintf/test13/CMakeLists.txt | 2 +- .../vsprintf/test13/{test13.c => test13.cpp} | 0 .../c_runtime/vsprintf/test14/CMakeLists.txt | 2 +- .../vsprintf/test14/{test14.c => test14.cpp} | 0 .../c_runtime/vsprintf/test15/CMakeLists.txt | 2 +- .../vsprintf/test15/{test15.c => test15.cpp} | 0 .../c_runtime/vsprintf/test16/CMakeLists.txt | 2 +- .../vsprintf/test16/{test16.c => test16.cpp} | 0 .../c_runtime/vsprintf/test17/CMakeLists.txt | 2 +- .../vsprintf/test17/{test17.c => test17.cpp} | 0 .../c_runtime/vsprintf/test18/CMakeLists.txt | 2 +- .../vsprintf/test18/{test18.c => test18.cpp} | 0 .../c_runtime/vsprintf/test19/CMakeLists.txt | 2 +- .../palsuite/c_runtime/vsprintf/test19/test19.c | 67 - .../palsuite/c_runtime/vsprintf/test19/test19.cpp | 67 + .../c_runtime/vsprintf/test2/CMakeLists.txt | 2 +- .../vsprintf/test2/{test2.c => test2.cpp} | 0 .../c_runtime/vsprintf/test3/CMakeLists.txt | 2 +- .../vsprintf/test3/{test3.c => test3.cpp} | 0 .../c_runtime/vsprintf/test4/CMakeLists.txt | 2 +- .../vsprintf/test4/{test4.c => test4.cpp} | 0 .../c_runtime/vsprintf/test5/CMakeLists.txt | 2 +- .../vsprintf/test5/{test5.c => test5.cpp} | 0 .../c_runtime/vsprintf/test6/CMakeLists.txt | 2 +- .../vsprintf/test6/{test6.c => test6.cpp} | 0 .../c_runtime/vsprintf/test7/CMakeLists.txt | 2 +- .../vsprintf/test7/{test7.c => test7.cpp} | 0 .../c_runtime/vsprintf/test8/CMakeLists.txt | 2 +- .../vsprintf/test8/{test8.c => test8.cpp} | 0 .../c_runtime/vsprintf/test9/CMakeLists.txt | 2 +- .../vsprintf/test9/{test9.c => test9.cpp} | 0 .../tests/palsuite/c_runtime/vsprintf/vsprintf.h | 34 +- .../c_runtime/vswprintf/test1/CMakeLists.txt | 2 +- .../vswprintf/test1/{test1.c => test1.cpp} | 0 .../c_runtime/vswprintf/test10/CMakeLists.txt | 2 +- .../vswprintf/test10/{test10.c => test10.cpp} | 0 .../c_runtime/vswprintf/test11/CMakeLists.txt | 2 +- .../vswprintf/test11/{test11.c => test11.cpp} | 0 .../c_runtime/vswprintf/test12/CMakeLists.txt | 2 +- .../vswprintf/test12/{test12.c => test12.cpp} | 0 .../c_runtime/vswprintf/test13/CMakeLists.txt | 2 +- .../vswprintf/test13/{test13.c => test13.cpp} | 0 .../c_runtime/vswprintf/test14/CMakeLists.txt | 2 +- .../vswprintf/test14/{test14.c => test14.cpp} | 0 .../c_runtime/vswprintf/test15/CMakeLists.txt | 2 +- .../vswprintf/test15/{test15.c => test15.cpp} | 0 .../c_runtime/vswprintf/test16/CMakeLists.txt | 2 +- .../vswprintf/test16/{test16.c => test16.cpp} | 0 .../c_runtime/vswprintf/test17/CMakeLists.txt | 2 +- .../vswprintf/test17/{test17.c => test17.cpp} | 0 .../c_runtime/vswprintf/test18/CMakeLists.txt | 2 +- .../vswprintf/test18/{test18.c => test18.cpp} | 0 .../c_runtime/vswprintf/test19/CMakeLists.txt | 2 +- .../palsuite/c_runtime/vswprintf/test19/test19.c | 137 - .../palsuite/c_runtime/vswprintf/test19/test19.cpp | 137 + .../c_runtime/vswprintf/test2/CMakeLists.txt | 2 +- .../vswprintf/test2/{test2.c => test2.cpp} | 0 .../c_runtime/vswprintf/test3/CMakeLists.txt | 2 +- .../vswprintf/test3/{test3.c => test3.cpp} | 0 .../c_runtime/vswprintf/test4/CMakeLists.txt | 2 +- .../vswprintf/test4/{test4.c => test4.cpp} | 0 .../c_runtime/vswprintf/test5/CMakeLists.txt | 2 +- .../vswprintf/test5/{test5.c => test5.cpp} | 0 .../c_runtime/vswprintf/test6/CMakeLists.txt | 2 +- .../vswprintf/test6/{test6.c => test6.cpp} | 0 .../c_runtime/vswprintf/test7/CMakeLists.txt | 2 +- .../vswprintf/test7/{test7.c => test7.cpp} | 0 .../c_runtime/vswprintf/test8/CMakeLists.txt | 2 +- .../vswprintf/test8/{test8.c => test8.cpp} | 0 .../c_runtime/vswprintf/test9/CMakeLists.txt | 2 +- .../vswprintf/test9/{test9.c => test9.cpp} | 0 .../tests/palsuite/c_runtime/vswprintf/vswprintf.h | 14 +- .../palsuite/c_runtime/wcscat/test1/CMakeLists.txt | 2 +- .../tests/palsuite/c_runtime/wcscat/test1/test1.c | 71 - .../palsuite/c_runtime/wcscat/test1/test1.cpp | 71 + .../palsuite/c_runtime/wcschr/test1/CMakeLists.txt | 2 +- .../c_runtime/wcschr/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/wcscmp/test1/CMakeLists.txt | 2 +- .../c_runtime/wcscmp/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/wcscpy/test1/CMakeLists.txt | 2 +- .../tests/palsuite/c_runtime/wcscpy/test1/test1.c | 47 - .../palsuite/c_runtime/wcscpy/test1/test1.cpp | 47 + .../palsuite/c_runtime/wcslen/test1/CMakeLists.txt | 2 +- .../c_runtime/wcslen/test1/{test1.c => test1.cpp} | 0 .../c_runtime/wcsncat/test1/CMakeLists.txt | 2 +- .../c_runtime/wcsncat/test1/{test1.c => test1.cpp} | 0 .../c_runtime/wcsncmp/test1/CMakeLists.txt | 2 +- .../c_runtime/wcsncmp/test1/{test1.c => test1.cpp} | 0 .../c_runtime/wcsncpy/test1/CMakeLists.txt | 2 +- .../c_runtime/wcsncpy/test1/{test1.c => test1.cpp} | 0 .../c_runtime/wcspbrk/test1/CMakeLists.txt | 2 +- .../c_runtime/wcspbrk/test1/{test1.c => test1.cpp} | 0 .../c_runtime/wcsrchr/test1/CMakeLists.txt | 2 +- .../c_runtime/wcsrchr/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/wcsstr/test1/CMakeLists.txt | 2 +- .../c_runtime/wcsstr/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/wcstod/test1/CMakeLists.txt | 2 +- .../c_runtime/wcstod/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/wcstod/test2/CMakeLists.txt | 2 +- .../c_runtime/wcstod/test2/{test2.c => test2.cpp} | 0 .../palsuite/c_runtime/wcstok/test1/CMakeLists.txt | 2 +- .../c_runtime/wcstok/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/wcstol/test1/CMakeLists.txt | 2 +- .../c_runtime/wcstol/test1/{test1.c => test1.cpp} | 0 .../palsuite/c_runtime/wcstol/test2/CMakeLists.txt | 2 +- .../c_runtime/wcstol/test2/{test2.c => test2.cpp} | 0 .../palsuite/c_runtime/wcstol/test3/CMakeLists.txt | 2 +- .../c_runtime/wcstol/test3/{test3.c => test3.cpp} | 0 .../palsuite/c_runtime/wcstol/test4/CMakeLists.txt | 2 +- .../c_runtime/wcstol/test4/{test4.c => test4.cpp} | 0 .../palsuite/c_runtime/wcstol/test5/CMakeLists.txt | 2 +- .../c_runtime/wcstol/test5/{test5.c => test5.cpp} | 0 .../palsuite/c_runtime/wcstol/test6/CMakeLists.txt | 2 +- .../c_runtime/wcstol/test6/{test6.c => test6.cpp} | 0 .../c_runtime/wcstoul/test1/CMakeLists.txt | 2 +- .../c_runtime/wcstoul/test1/{test1.c => test1.cpp} | 0 .../c_runtime/wcstoul/test2/CMakeLists.txt | 2 +- .../c_runtime/wcstoul/test2/{test2.c => test2.cpp} | 0 .../c_runtime/wcstoul/test3/CMakeLists.txt | 2 +- .../c_runtime/wcstoul/test3/{test3.c => test3.cpp} | 0 .../c_runtime/wcstoul/test4/CMakeLists.txt | 2 +- .../c_runtime/wcstoul/test4/{test4.c => test4.cpp} | 0 .../c_runtime/wcstoul/test5/CMakeLists.txt | 2 +- .../c_runtime/wcstoul/test5/{test5.c => test5.cpp} | 0 .../c_runtime/wcstoul/test6/CMakeLists.txt | 2 +- .../c_runtime/wcstoul/test6/{test6.c => test6.cpp} | 0 .../c_runtime/wprintf/test1/CMakeLists.txt | 2 +- .../c_runtime/wprintf/test1/{test1.c => test1.cpp} | 0 .../c_runtime/wprintf/test2/CMakeLists.txt | 2 +- .../c_runtime/wprintf/test2/{test2.c => test2.cpp} | 0 src/pal/tests/palsuite/c_runtime/wprintf/wprintf.h | 32 +- src/pal/tests/palsuite/common/palsuite.h | 6 +- .../event/nonshared/CMakeLists.txt | 4 +- .../event/nonshared/{event.c => event.cpp} | 0 .../event/nonshared/{main.c => main.cpp} | 0 .../object_management/event/shared/CMakeLists.txt | 4 +- .../event/shared/{event.c => event.cpp} | 0 .../event/shared/{main.c => main.cpp} | 0 .../mutex/nonshared/CMakeLists.txt | 4 +- .../mutex/nonshared/{main.c => main.cpp} | 0 .../mutex/nonshared/{mutex.c => mutex.cpp} | 0 .../object_management/mutex/shared/CMakeLists.txt | 4 +- .../mutex/shared/{main.c => main.cpp} | 0 .../mutex/shared/{mutex.c => mutex.cpp} | 0 .../semaphore/nonshared/CMakeLists.txt | 4 +- .../semaphore/nonshared/{main.c => main.cpp} | 0 .../nonshared/{semaphore.c => semaphore.cpp} | 0 .../semaphore/shared/CMakeLists.txt | 4 +- .../semaphore/shared/{main.c => main.cpp} | 0 .../shared/{semaphore.c => semaphore.cpp} | 0 .../synchronization/criticalsection/CMakeLists.txt | 4 +- .../{criticalsection.c => criticalsection.cpp} | 0 .../{mainWrapper.c => mainWrapper.cpp} | 0 .../nativecriticalsection/CMakeLists.txt | 2 +- ...ite_native_cs.c => pal_composite_native_cs.cpp} | 0 .../nativecs_interlocked/CMakeLists.txt | 2 +- ...ite_native_cs.c => pal_composite_native_cs.cpp} | 0 .../threading/threadsuspension/CMakeLists.txt | 4 +- .../mainWrapper.cpp} | 0 .../{threadsuspension.c => threadsuspension.cpp} | 0 .../threadsuspension_switchthread/CMakeLists.txt | 4 +- .../mainWrapper.cpp} | 0 .../{threadsuspension.c => threadsuspension.cpp} | 0 .../tests/palsuite/composite/wfmo/CMakeLists.txt | 4 +- .../palsuite/composite/wfmo/{main.c => main.cpp} | 0 .../palsuite/composite/wfmo/{mutex.c => mutex.cpp} | 0 .../debug_api/DebugBreak/test1/CMakeLists.txt | 2 +- .../DebugBreak/test1/{test1.c => test1.cpp} | 0 .../OutputDebugStringA/test1/CMakeLists.txt | 4 +- .../test1/{helper.c => helper.cpp} | 0 .../test1/{test1.c => test1.cpp} | 0 .../OutputDebugStringW/test1/CMakeLists.txt | 2 +- .../test1/{test1.c => test1.cpp} | 0 .../WriteProcessMemory/test1/CMakeLists.txt | 4 +- .../debug_api/WriteProcessMemory/test1/helper.c | 243 - .../debug_api/WriteProcessMemory/test1/helper.cpp | 243 + .../debug_api/WriteProcessMemory/test1/test1.c | 189 - .../debug_api/WriteProcessMemory/test1/test1.cpp | 189 + .../WriteProcessMemory/test3/CMakeLists.txt | 4 +- .../test3/{helper.c => helper.cpp} | 0 .../debug_api/WriteProcessMemory/test3/test3.c | 205 - .../debug_api/WriteProcessMemory/test3/test3.cpp | 205 + .../WriteProcessMemory/test4/CMakeLists.txt | 4 +- .../test4/{helper.c => helper.cpp} | 0 .../test4/{test4.c => test4.cpp} | 0 .../PAL_EXCEPT_FILTER/test1/CMakeLists.txt | 2 +- .../{PAL_EXCEPT_FILTER.c => PAL_EXCEPT_FILTER.cpp} | 0 .../PAL_EXCEPT_FILTER/test2/CMakeLists.txt | 2 +- .../{pal_except_filter.c => pal_except_filter.cpp} | 0 .../PAL_EXCEPT_FILTER/test3/CMakeLists.txt | 2 +- .../{pal_except_filter.c => pal_except_filter.cpp} | 0 .../PAL_EXCEPT_FILTER_EX/test1/CMakeLists.txt | 2 +- ...EXCEPT_FILTER_EX.c => PAL_EXCEPT_FILTER_EX.cpp} | 0 .../PAL_EXCEPT_FILTER_EX/test2/CMakeLists.txt | 2 +- ...except_filter_ex.c => pal_except_filter_ex.cpp} | 0 .../PAL_EXCEPT_FILTER_EX/test3/CMakeLists.txt | 2 +- .../{pal_except_filter.c => pal_except_filter.cpp} | 0 .../PAL_TRY_EXCEPT/test1/CMakeLists.txt | 2 +- .../test1/{PAL_TRY_EXCEPT.c => PAL_TRY_EXCEPT.cpp} | 0 .../PAL_TRY_EXCEPT/test2/CMakeLists.txt | 2 +- .../test2/{PAL_TRY_EXCEPT.c => PAL_TRY_EXCEPT.cpp} | 0 .../PAL_TRY_EXCEPT_EX/test1/CMakeLists.txt | 2 +- .../{PAL_TRY_EXCEPT_EX.c => PAL_TRY_EXCEPT_EX.cpp} | 0 .../PAL_TRY_EXCEPT_EX/test2/CMakeLists.txt | 2 +- .../{PAL_TRY_EXCEPT_EX.c => PAL_TRY_EXCEPT_EX.cpp} | 0 .../PAL_TRY_EXCEPT_EX/test3/CMakeLists.txt | 2 +- .../{PAL_TRY_EXCEPT_EX.c => PAL_TRY_EXCEPT_EX.cpp} | 0 .../PAL_TRY_LEAVE_FINALLY/test1/CMakeLists.txt | 2 +- ...Y_LEAVE_FINALLY.c => PAL_TRY_LEAVE_FINALLY.cpp} | 0 .../test1/CMakeLists.txt | 2 +- .../test1/{test1.c => test1.cpp} | 0 .../pal_except/test1/CMakeLists.txt | 2 +- .../pal_except/test1/{test1.c => test1.cpp} | 0 .../pal_except/test2/CMakeLists.txt | 2 +- .../pal_except/test2/{test2.c => test2.cpp} | 0 .../pal_except/test3/CMakeLists.txt | 2 +- .../pal_except/test3/{test3.c => test3.cpp} | 0 .../pal_except/test4/CMakeLists.txt | 2 +- .../pal_except/test4/{test4.c => test4.cpp} | 0 .../pal_except/test5/CMakeLists.txt | 2 +- .../pal_except/test5/{test5.c => test5.cpp} | 0 .../pal_except/test6/CMakeLists.txt | 2 +- .../pal_except/test6/{test6.c => test6.cpp} | 0 .../pal_except/test7/CMakeLists.txt | 2 +- .../pal_except/test7/{test7.c => test7.cpp} | 0 .../pal_finally/test1/CMakeLists.txt | 2 +- .../test1/{pal_finally.c => pal_finally.cpp} | 0 .../exception_handling/pal_sxs/test1/dlltest1.cpp | 14 +- .../exception_handling/pal_sxs/test1/dlltest2.cpp | 14 +- .../{AreFileApisANSI.c => AreFileApisANSI.cpp} | 0 .../file_io/AreFileApisANSI/test1/CMakeLists.txt | 2 +- .../file_io/CompareFileTime/test1/CMakeLists.txt | 2 +- .../{CompareFileTime.c => CompareFileTime.cpp} | 0 .../file_io/CopyFileA/test1/CMakeLists.txt | 2 +- .../CopyFileA/test1/{CopyFileA.c => CopyFileA.cpp} | 0 .../file_io/CopyFileA/test2/CMakeLists.txt | 2 +- .../file_io/CopyFileA/test2/{test2.c => test2.cpp} | 0 .../file_io/CopyFileA/test3/CMakeLists.txt | 2 +- .../file_io/CopyFileA/test3/{test3.c => test3.cpp} | 0 .../file_io/CopyFileA/test4/CMakeLists.txt | 2 +- .../file_io/CopyFileA/test4/{test4.c => test4.cpp} | 0 .../file_io/CopyFileW/test1/CMakeLists.txt | 2 +- .../CopyFileW/test1/{CopyFileW.c => CopyFileW.cpp} | 0 .../file_io/CopyFileW/test2/CMakeLists.txt | 2 +- .../file_io/CopyFileW/test2/{test2.c => test2.cpp} | 0 .../file_io/CopyFileW/test3/CMakeLists.txt | 2 +- .../file_io/CopyFileW/test3/{test3.c => test3.cpp} | 0 .../file_io/CreateDirectoryA/test1/CMakeLists.txt | 2 +- .../CreateDirectoryA/test1/CreateDirectoryA.c | 296 - .../CreateDirectoryA/test1/CreateDirectoryA.cpp | 296 + .../file_io/CreateDirectoryA/test2/CMakeLists.txt | 2 +- .../{createdirectorya.c => createdirectorya.cpp} | 0 .../file_io/CreateDirectoryW/test1/CMakeLists.txt | 2 +- .../CreateDirectoryW/test1/CreateDirectoryW.c | 347 - .../CreateDirectoryW/test1/CreateDirectoryW.cpp | 347 + .../file_io/CreateDirectoryW/test2/CMakeLists.txt | 2 +- .../{createdirectoryw.c => createdirectoryw.cpp} | 0 .../file_io/CreateFileA/test1/CMakeLists.txt | 2 +- .../file_io/CreateFileA/test1/CreateFileA.c | 145 - .../file_io/CreateFileA/test1/CreateFileA.cpp | 145 + .../file_io/CreateFileW/test1/CMakeLists.txt | 2 +- .../file_io/CreateFileW/test1/CreateFileW.c | 152 - .../file_io/CreateFileW/test1/CreateFileW.cpp | 152 + .../file_io/DeleteFileW/test1/CMakeLists.txt | 2 +- .../test1/{DeleteFileW.c => DeleteFileW.cpp} | 0 .../file_io/FILECanonicalizePath/CMakeLists.txt | 2 +- .../FILECanonicalizePath/FILECanonicalizePath.c | 83 - .../FILECanonicalizePath/FILECanonicalizePath.cpp | 83 + .../FileTimeToDosDateTime/test1/CMakeLists.txt | 2 +- .../test1/{test1.c => test1.cpp} | 0 .../file_io/FindClose/test1/CMakeLists.txt | 2 +- .../FindClose/test1/{FindClose.c => FindClose.cpp} | 0 .../file_io/FindFirstFileA/test1/CMakeLists.txt | 2 +- .../test1/{FindFirstFileA.c => FindFirstFileA.cpp} | 0 .../file_io/FindFirstFileW/test1/CMakeLists.txt | 2 +- .../test1/{FindFirstFileW.c => FindFirstFileW.cpp} | 0 .../file_io/FindNextFileA/test1/CMakeLists.txt | 2 +- .../test1/{FindNextFileA.c => FindNextFileA.cpp} | 0 .../file_io/FindNextFileA/test2/CMakeLists.txt | 2 +- .../test2/{findnextfilea.c => findnextfilea.cpp} | 0 .../file_io/FindNextFileW/test1/CMakeLists.txt | 2 +- .../test1/{FindNextFileW.c => FindNextFileW.cpp} | 0 .../file_io/FindNextFileW/test2/CMakeLists.txt | 2 +- .../test2/{findnextfilew.c => findnextfilew.cpp} | 0 .../file_io/FlushFileBuffers/test1/CMakeLists.txt | 2 +- .../{FlushFileBuffers.c => FlushFileBuffers.cpp} | 0 .../file_io/GetConsoleCP/test1/CMakeLists.txt | 2 +- .../test1/{GetConsoleCP.c => GetConsoleCP.cpp} | 0 .../GetConsoleOutputCP/test1/CMakeLists.txt | 2 +- ...GetConsoleOutputCP.c => GetConsoleOutputCP.cpp} | 0 .../GetCurrentDirectoryA/test1/CMakeLists.txt | 2 +- ...urrentDirectoryA.c => GetCurrentDirectoryA.cpp} | 0 .../GetCurrentDirectoryW/test1/CMakeLists.txt | 2 +- ...urrentDirectoryW.c => GetCurrentDirectoryW.cpp} | 0 .../file_io/GetDiskFreeSpaceW/test1/CMakeLists.txt | 2 +- .../{GetDiskFreeSpaceW.c => GetDiskFreeSpaceW.cpp} | 0 .../file_io/GetDiskFreeSpaceW/test2/CMakeLists.txt | 2 +- .../{getdiskfreespacew.c => getdiskfreespacew.cpp} | 0 .../GetFileAttributesA/test1/CMakeLists.txt | 2 +- ...GetFileAttributesA.c => GetFileAttributesA.cpp} | 0 .../GetFileAttributesExW/test1/CMakeLists.txt | 2 +- .../test1/{test1.c => test1.cpp} | 0 .../GetFileAttributesExW/test2/CMakeLists.txt | 2 +- .../test2/{test2.c => test2.cpp} | 0 .../GetFileAttributesW/test1/CMakeLists.txt | 2 +- ...GetFileAttributesW.c => GetFileAttributesW.cpp} | 0 .../file_io/GetFileSize/test1/CMakeLists.txt | 2 +- .../test1/{GetFileSize.c => GetFileSize.cpp} | 0 .../file_io/GetFileSizeEx/test1/CMakeLists.txt | 2 +- .../test1/{GetFileSizeEx.c => GetFileSizeEx.cpp} | 0 .../file_io/GetFileTime/test1/CMakeLists.txt | 2 +- .../test1/{GetFileTime.c => GetFileTime.cpp} | 0 .../file_io/GetFileTime/test2/CMakeLists.txt | 2 +- .../test2/{GetFileTime.c => GetFileTime.cpp} | 0 .../file_io/GetFileTime/test3/CMakeLists.txt | 2 +- .../test3/{GetFileTime.c => GetFileTime.cpp} | 0 .../file_io/GetFileTime/test4/CMakeLists.txt | 2 +- .../test4/{GetFileTime.c => GetFileTime.cpp} | 0 .../file_io/GetFileTime/test5/CMakeLists.txt | 2 +- .../test5/{getfiletime.c => getfiletime.cpp} | 0 .../file_io/GetFileTime/test6/CMakeLists.txt | 2 +- .../test6/{getfiletime.c => getfiletime.cpp} | 0 .../file_io/GetFileTime/test7/CMakeLists.txt | 2 +- .../test7/{getfiletime.c => getfiletime.cpp} | 0 .../file_io/GetFileType/test1/CMakeLists.txt | 2 +- .../test1/{GetFileType.c => GetFileType.cpp} | 0 .../file_io/GetFileType/test2/CMakeLists.txt | 2 +- .../test2/{getfiletype.c => getfiletype.cpp} | 0 .../file_io/GetFileType/test3/CMakeLists.txt | 2 +- .../test3/{getfiletype.c => getfiletype.cpp} | 0 .../file_io/GetFullPathNameA/test1/CMakeLists.txt | 2 +- .../{GetFullPathNameA.c => GetFullPathNameA.cpp} | 0 .../file_io/GetFullPathNameA/test2/CMakeLists.txt | 2 +- .../GetFullPathNameA/test2/{test2.c => test2.cpp} | 0 .../file_io/GetFullPathNameA/test3/CMakeLists.txt | 2 +- .../GetFullPathNameA/test3/{test3.c => test3.cpp} | 0 .../file_io/GetFullPathNameA/test4/CMakeLists.txt | 2 +- .../GetFullPathNameA/test4/{test4.c => test4.cpp} | 0 .../file_io/GetFullPathNameW/test1/CMakeLists.txt | 2 +- .../{GetFullPathNameW.c => GetFullPathNameW.cpp} | 0 .../file_io/GetFullPathNameW/test2/CMakeLists.txt | 2 +- .../GetFullPathNameW/test2/{test2.c => test2.cpp} | 0 .../file_io/GetFullPathNameW/test3/CMakeLists.txt | 2 +- .../GetFullPathNameW/test3/{test3.c => test3.cpp} | 0 .../file_io/GetFullPathNameW/test4/CMakeLists.txt | 2 +- .../GetFullPathNameW/test4/{test4.c => test4.cpp} | 0 .../file_io/GetLongPathNameW/test1/CMakeLists.txt | 2 +- .../{GetLongPathNameW.c => GetLongPathNameW.cpp} | 0 .../file_io/GetLongPathNameW/test2/CMakeLists.txt | 2 +- .../{getlongpathnamew.c => getlongpathnamew.cpp} | 0 .../file_io/GetStdHandle/test1/CMakeLists.txt | 2 +- .../test1/{GetStdHandle.c => GetStdHandle.cpp} | 0 .../file_io/GetStdHandle/test2/CMakeLists.txt | 2 +- .../test2/{GetStdHandle.c => GetStdHandle.cpp} | 0 .../file_io/GetSystemTime/test1/CMakeLists.txt | 2 +- .../GetSystemTime/test1/{test.c => test.cpp} | 0 .../GetSystemTimeAsFileTime/test1/CMakeLists.txt | 2 +- ...imeAsFileTime.c => GetSystemTimeAsFileTime.cpp} | 0 .../file_io/GetTempFileNameA/test1/CMakeLists.txt | 2 +- .../GetTempFileNameA/test1/GetTempFileNameA.c | 125 - .../GetTempFileNameA/test1/GetTempFileNameA.cpp | 125 + .../file_io/GetTempFileNameA/test2/CMakeLists.txt | 2 +- .../{GetTempFileNameA.c => GetTempFileNameA.cpp} | 0 .../file_io/GetTempFileNameA/test3/CMakeLists.txt | 2 +- .../{gettempfilenamea.c => gettempfilenamea.cpp} | 0 .../file_io/GetTempFileNameW/test1/CMakeLists.txt | 2 +- .../{GetTempFileNameW.c => GetTempFileNameW.cpp} | 0 .../file_io/GetTempFileNameW/test2/CMakeLists.txt | 2 +- .../{GetTempFileNameW.c => GetTempFileNameW.cpp} | 0 .../file_io/GetTempFileNameW/test3/CMakeLists.txt | 2 +- .../{gettempfilenamew.c => gettempfilenamew.cpp} | 0 .../file_io/GetTempPathW/test1/CMakeLists.txt | 2 +- .../file_io/GetTempPathW/test1/GetTempPathW.c | 103 - .../file_io/GetTempPathW/test1/GetTempPathW.cpp | 103 + .../file_io/MoveFileA/test1/CMakeLists.txt | 2 +- .../palsuite/file_io/MoveFileA/test1/MoveFileA.c | 469 - .../palsuite/file_io/MoveFileA/test1/MoveFileA.cpp | 469 + .../file_io/MoveFileExA/test1/CMakeLists.txt | 2 +- .../test1/{MoveFileExA.c => MoveFileExA.cpp} | 0 .../file_io/MoveFileExW/test1/CMakeLists.txt | 2 +- .../test1/{MoveFileExW.c => MoveFileExW.cpp} | 0 .../file_io/MoveFileW/test1/CMakeLists.txt | 2 +- .../palsuite/file_io/MoveFileW/test1/MoveFileW.c | 478 - .../palsuite/file_io/MoveFileW/test1/MoveFileW.cpp | 478 + .../palsuite/file_io/ReadFile/test1/CMakeLists.txt | 2 +- .../ReadFile/test1/{ReadFile.c => ReadFile.cpp} | 0 .../palsuite/file_io/ReadFile/test2/CMakeLists.txt | 2 +- .../ReadFile/test2/{ReadFile.c => ReadFile.cpp} | 0 .../palsuite/file_io/ReadFile/test3/CMakeLists.txt | 2 +- .../ReadFile/test3/{ReadFile.c => ReadFile.cpp} | 0 .../palsuite/file_io/ReadFile/test4/CMakeLists.txt | 2 +- .../ReadFile/test4/{readfile.c => readfile.cpp} | 0 .../RemoveDirectoryA/test1/RemoveDirectoryA.cpp | 12 +- .../file_io/RemoveDirectoryW/test1/CMakeLists.txt | 2 +- .../RemoveDirectoryW/test1/RemoveDirectoryW.c | 282 - .../RemoveDirectoryW/test1/RemoveDirectoryW.cpp | 282 + .../file_io/SearchPathA/test1/CMakeLists.txt | 2 +- .../file_io/SearchPathA/test1/SearchPathA.c | 144 - .../file_io/SearchPathA/test1/SearchPathA.cpp | 139 + .../file_io/SearchPathW/test1/CMakeLists.txt | 2 +- .../file_io/SearchPathW/test1/SearchPathW.c | 198 - .../file_io/SearchPathW/test1/SearchPathW.cpp | 193 + .../SetCurrentDirectoryA/test1/CMakeLists.txt | 2 +- .../test1/SetCurrentDirectoryA.c | 215 - .../test1/SetCurrentDirectoryA.cpp | 215 + .../SetCurrentDirectoryA/test2/CMakeLists.txt | 2 +- .../test2/setcurrentdirectorya.c | 142 - .../test2/setcurrentdirectorya.cpp | 142 + .../SetCurrentDirectoryA/test3/CMakeLists.txt | 2 +- ...urrentdirectorya.c => setcurrentdirectorya.cpp} | 0 .../SetCurrentDirectoryW/test1/CMakeLists.txt | 2 +- .../test1/SetCurrentDirectoryW.c | 178 - .../test1/SetCurrentDirectoryW.cpp | 178 + .../SetCurrentDirectoryW/test2/CMakeLists.txt | 2 +- .../test2/setcurrentdirectoryw.c | 147 - .../test2/setcurrentdirectoryw.cpp | 147 + .../SetCurrentDirectoryW/test3/CMakeLists.txt | 2 +- ...urrentdirectoryw.c => setcurrentdirectoryw.cpp} | 0 .../file_io/SetEndOfFile/test1/CMakeLists.txt | 2 +- .../test1/{SetEndOfFile.c => SetEndOfFile.cpp} | 0 .../file_io/SetEndOfFile/test2/CMakeLists.txt | 2 +- .../test2/{SetEndOfFile.c => SetEndOfFile.cpp} | 0 .../file_io/SetEndOfFile/test3/CMakeLists.txt | 2 +- .../test3/{SetEndOfFile.c => SetEndOfFile.cpp} | 0 .../file_io/SetEndOfFile/test4/CMakeLists.txt | 2 +- .../test4/{setendoffile.c => setendoffile.cpp} | 0 .../file_io/SetEndOfFile/test5/CMakeLists.txt | 2 +- .../SetEndOfFile/test5/{test5.c => test5.cpp} | 0 .../SetFileAttributesA/test1/CMakeLists.txt | 2 +- ...SetFileAttributesA.c => SetFileAttributesA.cpp} | 0 .../SetFileAttributesA/test2/CMakeLists.txt | 2 +- ...SetFileAttributesA.c => SetFileAttributesA.cpp} | 0 .../SetFileAttributesA/test3/CMakeLists.txt | 2 +- ...SetFileAttributesA.c => SetFileAttributesA.cpp} | 0 .../SetFileAttributesA/test4/CMakeLists.txt | 2 +- ...SetFileAttributesA.c => SetFileAttributesA.cpp} | 0 .../SetFileAttributesW/test1/CMakeLists.txt | 2 +- ...SetFileAttributesW.c => SetFileAttributesW.cpp} | 0 .../SetFileAttributesW/test2/CMakeLists.txt | 2 +- ...SetFileAttributesW.c => SetFileAttributesW.cpp} | 0 .../SetFileAttributesW/test3/CMakeLists.txt | 2 +- ...SetFileAttributesW.c => SetFileAttributesW.cpp} | 0 .../SetFileAttributesW/test4/CMakeLists.txt | 2 +- ...SetFileAttributesW.c => SetFileAttributesW.cpp} | 0 .../file_io/SetFilePointer/test1/CMakeLists.txt | 2 +- .../test1/{SetFilePointer.c => SetFilePointer.cpp} | 0 .../file_io/SetFilePointer/test2/CMakeLists.txt | 2 +- .../test2/{SetFilePointer.c => SetFilePointer.cpp} | 0 .../file_io/SetFilePointer/test3/CMakeLists.txt | 2 +- .../test3/{SetFilePointer.c => SetFilePointer.cpp} | 0 .../file_io/SetFilePointer/test4/CMakeLists.txt | 2 +- .../test4/{SetFilePointer.c => SetFilePointer.cpp} | 0 .../file_io/SetFilePointer/test5/CMakeLists.txt | 2 +- .../test5/{SetFilePointer.c => SetFilePointer.cpp} | 0 .../file_io/SetFilePointer/test6/CMakeLists.txt | 2 +- .../test6/{SetFilePointer.c => SetFilePointer.cpp} | 0 .../file_io/SetFilePointer/test7/CMakeLists.txt | 2 +- .../test7/{SetFilePointer.c => SetFilePointer.cpp} | 0 .../file_io/SetFileTime/test1/CMakeLists.txt | 2 +- .../test1/{SetFileTime.c => SetFileTime.cpp} | 0 .../file_io/SetFileTime/test2/CMakeLists.txt | 2 +- .../test2/{SetFileTime.c => SetFileTime.cpp} | 0 .../file_io/SetFileTime/test3/CMakeLists.txt | 2 +- .../test3/{SetFileTime.c => SetFileTime.cpp} | 0 .../file_io/SetFileTime/test4/CMakeLists.txt | 2 +- .../test4/{SetFileTime.c => SetFileTime.cpp} | 0 .../file_io/WriteFile/test1/CMakeLists.txt | 2 +- .../WriteFile/test1/{WriteFile.c => WriteFile.cpp} | 0 .../file_io/WriteFile/test2/CMakeLists.txt | 2 +- .../WriteFile/test2/{WriteFile.c => WriteFile.cpp} | 0 .../file_io/WriteFile/test3/CMakeLists.txt | 2 +- .../WriteFile/test3/{WriteFile.c => WriteFile.cpp} | 0 .../file_io/WriteFile/test4/CMakeLists.txt | 2 +- .../WriteFile/test4/{writefile.c => writefile.cpp} | 0 .../file_io/WriteFile/test5/CMakeLists.txt | 2 +- .../WriteFile/test5/{writefile.c => writefile.cpp} | 0 .../file_io/errorpathnotfound/test1/CMakeLists.txt | 2 +- .../errorpathnotfound/test1/{test1.c => test1.cpp} | 0 .../file_io/errorpathnotfound/test2/CMakeLists.txt | 2 +- .../errorpathnotfound/test2/{test2.c => test2.cpp} | 0 .../file_io/errorpathnotfound/test3/CMakeLists.txt | 2 +- .../errorpathnotfound/test3/{test3.c => test3.cpp} | 0 .../file_io/errorpathnotfound/test4/CMakeLists.txt | 2 +- .../errorpathnotfound/test4/{test4.c => test4.cpp} | 0 .../file_io/gettemppatha/test1/CMakeLists.txt | 2 +- .../test1/{gettemppatha.c => gettemppatha.cpp} | 0 .../palsuite/filemapping_memmgt/CMakeLists.txt | 2 +- .../CreateFileMappingA/test1/CMakeLists.txt | 2 +- .../{CreateFileMapping.c => CreateFileMapping.cpp} | 0 .../CreateFileMappingA/test3/CMakeLists.txt | 2 +- .../{CreateFileMapping.c => CreateFileMapping.cpp} | 0 .../CreateFileMappingA/test4/CMakeLists.txt | 2 +- .../{CreateFileMapping.c => CreateFileMapping.cpp} | 0 .../CreateFileMappingA/test5/CMakeLists.txt | 2 +- .../{CreateFileMapping.c => CreateFileMapping.cpp} | 0 .../CreateFileMappingA/test6/CMakeLists.txt | 2 +- .../{CreateFileMapping.c => CreateFileMapping.cpp} | 0 .../CreateFileMappingA/test7/CMakeLists.txt | 2 +- .../{createfilemapping.c => createfilemapping.cpp} | 0 .../CreateFileMappingA/test8/CMakeLists.txt | 2 +- .../{createfilemapping.c => createfilemapping.cpp} | 0 .../CreateFileMappingA/test9/CMakeLists.txt | 2 +- .../{createfilemapping.c => createfilemapping.cpp} | 0 .../CreateFileMapping_neg1/CMakeLists.txt | 2 +- ...FileMapping_neg.c => CreateFileMapping_neg.cpp} | 0 .../CreateFileMappingW/test1/CMakeLists.txt | 2 +- ...CreateFileMappingW.c => CreateFileMappingW.cpp} | 0 .../CreateFileMappingW/test2/CMakeLists.txt | 2 +- .../CreateFileMappingW/test2/CreateFileMappingW.c | 124 - .../test2/CreateFileMappingW.cpp | 124 + .../CreateFileMappingW/test3/CMakeLists.txt | 2 +- ...CreateFileMappingW.c => CreateFileMappingW.cpp} | 0 .../CreateFileMappingW/test4/CMakeLists.txt | 2 +- ...CreateFileMappingW.c => CreateFileMappingW.cpp} | 0 .../CreateFileMappingW/test5/CMakeLists.txt | 2 +- ...CreateFileMappingW.c => CreateFileMappingW.cpp} | 0 .../CreateFileMappingW/test6/CMakeLists.txt | 2 +- ...CreateFileMappingW.c => CreateFileMappingW.cpp} | 0 .../CreateFileMappingW/test7/CMakeLists.txt | 2 +- .../{createfilemapping.c => createfilemapping.cpp} | 0 .../CreateFileMappingW/test8/CMakeLists.txt | 2 +- .../{createfilemapping.c => createfilemapping.cpp} | 0 .../CreateFileMappingW/test9/CMakeLists.txt | 2 +- .../{createfilemapping.c => createfilemapping.cpp} | 0 .../FreeLibrary/test1/CMakeLists.txt | 4 +- .../test1/{FreeLibrary.c => FreeLibrary.cpp} | 0 .../FreeLibrary/test1/{dlltest.c => dlltest.cpp} | 0 .../FreeLibrary/test2/CMakeLists.txt | 2 +- .../FreeLibrary/test2/{test2.c => test2.cpp} | 0 .../FreeLibraryAndExitThread/test1/CMakeLists.txt | 4 +- .../test1/{dlltest.c => dlltest.cpp} | 0 .../FreeLibraryAndExitThread/test1/test1.c | 183 - .../FreeLibraryAndExitThread/test1/test1.cpp | 183 + .../GetModuleFileNameA/test1/CMakeLists.txt | 2 +- ...GetModuleFileNameA.c => GetModuleFileNameA.cpp} | 0 .../GetModuleFileNameA/test2/CMakeLists.txt | 2 +- ...GetModuleFileNameA.c => GetModuleFileNameA.cpp} | 0 .../GetModuleFileNameW/test1/CMakeLists.txt | 2 +- .../GetModuleFileNameW/test1/GetModuleFileNameW.c | 112 - .../test1/GetModuleFileNameW.cpp | 112 + .../GetModuleFileNameW/test2/CMakeLists.txt | 2 +- .../GetModuleFileNameW/test2/GetModuleFileNameW.c | 57 - .../test2/GetModuleFileNameW.cpp | 57 + .../GetProcAddress/test1/CMakeLists.txt | 4 +- .../GetProcAddress/test1/{test1.c => test1.cpp} | 0 .../test1/{testlib.c => testlib.cpp} | 0 .../GetProcAddress/test2/CMakeLists.txt | 4 +- .../GetProcAddress/test2/{test2.c => test2.cpp} | 0 .../test2/{testlib.c => testlib.cpp} | 0 .../GetProcessHeap/test1/CMakeLists.txt | 2 +- .../test1/{GetProcessHeap.c => GetProcessHeap.cpp} | 0 .../HeapAlloc/test1/CMakeLists.txt | 2 +- .../HeapAlloc/test1/{HeapAlloc.c => HeapAlloc.cpp} | 0 .../HeapAlloc/test2/CMakeLists.txt | 2 +- .../HeapAlloc/test2/{HeapAlloc.c => HeapAlloc.cpp} | 0 .../HeapAlloc/test3/CMakeLists.txt | 2 +- .../HeapAlloc/test3/{HeapAlloc.c => HeapAlloc.cpp} | 0 .../HeapFree/test1/CMakeLists.txt | 2 +- .../HeapFree/test1/{HeapFree.c => HeapFree.cpp} | 0 .../HeapReAlloc/test1/CMakeLists.txt | 2 +- .../filemapping_memmgt/HeapReAlloc/test1/test1.c | 72 - .../filemapping_memmgt/HeapReAlloc/test1/test1.cpp | 72 + .../HeapReAlloc/test2/CMakeLists.txt | 2 +- .../filemapping_memmgt/HeapReAlloc/test2/test2.c | 79 - .../filemapping_memmgt/HeapReAlloc/test2/test2.cpp | 79 + .../HeapReAlloc/test3/CMakeLists.txt | 2 +- .../filemapping_memmgt/HeapReAlloc/test3/test3.c | 78 - .../filemapping_memmgt/HeapReAlloc/test3/test3.cpp | 78 + .../HeapReAlloc/test4/CMakeLists.txt | 2 +- .../HeapReAlloc/test4/{test4.c => test4.cpp} | 0 .../HeapReAlloc/test5/CMakeLists.txt | 2 +- .../filemapping_memmgt/HeapReAlloc/test5/test5.c | 69 - .../filemapping_memmgt/HeapReAlloc/test5/test5.cpp | 69 + .../LocalAlloc/test1/CMakeLists.txt | 2 +- .../test1/{LocalAlloc.c => LocalAlloc.cpp} | 0 .../LocalFree/test1/CMakeLists.txt | 2 +- .../LocalFree/test1/{LocalFree.c => LocalFree.cpp} | 0 .../LocalFree/test2/CMakeLists.txt | 2 +- .../LocalFree/test2/{LocalFree.c => LocalFree.cpp} | 0 .../LockFile/test1/CMakeLists.txt | 4 +- .../LockFile/test1/{helper.c => helper.cpp} | 0 .../LockFile/test1/{test1.c => test1.cpp} | 0 .../LockFile/test2/CMakeLists.txt | 2 +- .../LockFile/test2/{test2.c => test2.cpp} | 0 .../LockFile/test3/CMakeLists.txt | 4 +- .../LockFile/test3/{helper.c => helper.cpp} | 0 .../LockFile/test3/{test3.c => test3.cpp} | 0 .../LockFile/test4/CMakeLists.txt | 2 +- .../LockFile/test4/{test4.c => test4.cpp} | 0 .../LockFile/test5/CMakeLists.txt | 4 +- .../LockFile/test5/{helper.c => helper.cpp} | 0 .../LockFile/test5/{test5.c => test5.cpp} | 0 .../LockFile/test6/CMakeLists.txt | 4 +- .../LockFile/test6/{helper.c => helper.cpp} | 0 .../LockFile/test6/{test6.c => test6.cpp} | 0 .../LockFile/test7/CMakeLists.txt | 2 +- .../LockFile/test7/{test7.c => test7.cpp} | 0 .../MapViewOfFile/test1/CMakeLists.txt | 2 +- .../test1/{MapViewOfFile.c => MapViewOfFile.cpp} | 0 .../MapViewOfFile/test2/CMakeLists.txt | 2 +- .../test2/{MapViewOfFile.c => MapViewOfFile.cpp} | 0 .../MapViewOfFile/test3/CMakeLists.txt | 2 +- .../test3/{MapViewOfFile.c => MapViewOfFile.cpp} | 0 .../MapViewOfFile/test4/CMakeLists.txt | 2 +- .../test4/{mapviewoffile.c => mapviewoffile.cpp} | 0 .../MapViewOfFile/test5/CMakeLists.txt | 2 +- .../test5/{mapviewoffile.c => mapviewoffile.cpp} | 0 .../MapViewOfFile/test6/CMakeLists.txt | 2 +- .../test6/{mapviewoffile.c => mapviewoffile.cpp} | 0 .../OpenFileMappingA/test1/CMakeLists.txt | 2 +- .../{OpenFileMappingA.c => OpenFileMappingA.cpp} | 0 .../OpenFileMappingA/test2/CMakeLists.txt | 2 +- .../{OpenFileMappingA.c => OpenFileMappingA.cpp} | 0 .../OpenFileMappingA/test3/CMakeLists.txt | 2 +- .../{OpenFileMappingA.c => OpenFileMappingA.cpp} | 0 .../OpenFileMappingW/test1/CMakeLists.txt | 2 +- .../{OpenFileMappingW.c => OpenFileMappingW.cpp} | 0 .../OpenFileMappingW/test2/CMakeLists.txt | 2 +- .../{OpenFileMappingW.c => OpenFileMappingW.cpp} | 0 .../OpenFileMappingW/test3/CMakeLists.txt | 2 +- .../{OpenFileMappingW.c => OpenFileMappingW.cpp} | 0 .../filemapping_memmgt/ProbeMemory/CMakeLists.txt | 5 + .../ProbeMemory/ProbeMemory_neg1/CMakeLists.txt | 19 + .../ProbeMemory_neg1/ProbeMemory_neg.cpp | 95 + .../ProbeMemory/ProbeMemory_neg1/testinfo.dat | 12 + .../ProbeMemory/test1/CMakeLists.txt | 19 + .../ProbeMemory/test1/ProbeMemory.cpp | 94 + .../ProbeMemory/test1/testinfo.dat | 12 + .../ReadProcessMemory/CMakeLists.txt | 6 - .../ReadProcessMemory_neg1/CMakeLists.txt | 19 - .../ReadProcessMemory_neg1/ReadProcessMemory_neg.c | 127 - .../ReadProcessMemory_neg1/testinfo.dat | 12 - .../ReadProcessMemory/test1/CMakeLists.txt | 19 - .../ReadProcessMemory/test1/ReadProcessMemory.c | 126 - .../ReadProcessMemory/test1/testinfo.dat | 12 - .../ReadProcessMemory/test2/CMakeLists.txt | 36 - .../ReadProcessMemory/test2/commonconsts.h | 48 - .../ReadProcessMemory/test2/helper.c | 249 - .../ReadProcessMemory/test2/test2.c | 258 - .../ReadProcessMemory/test2/testinfo.dat | 18 - .../RtlMoveMemory/test1/CMakeLists.txt | 2 +- .../RtlMoveMemory/test1/{test1.c => test1.cpp} | 0 .../RtlMoveMemory/test3/CMakeLists.txt | 2 +- .../RtlMoveMemory/test3/{test3.c => test3.cpp} | 0 .../RtlMoveMemory/test4/CMakeLists.txt | 2 +- .../RtlMoveMemory/test4/{test4.c => test4.cpp} | 0 .../RtlMoveMemory/test5/CMakeLists.txt | 2 +- .../RtlMoveMemory/test5/{test5.c => test5.cpp} | 0 .../UnlockFile/test1/CMakeLists.txt | 4 +- .../UnlockFile/test1/{helper.c => helper.cpp} | 0 .../UnlockFile/test1/{test1.c => test1.cpp} | 0 .../UnlockFile/test2/CMakeLists.txt | 2 +- .../UnlockFile/test2/{test2.c => test2.cpp} | 0 .../UnlockFile/test3/CMakeLists.txt | 4 +- .../UnlockFile/test3/{helper.c => helper.cpp} | 0 .../UnlockFile/test3/{test3.c => test3.cpp} | 0 .../UnlockFile/test4/CMakeLists.txt | 2 +- .../UnlockFile/test4/{test4.c => test4.cpp} | 0 .../UnmapViewOfFile/test1/CMakeLists.txt | 2 +- .../{UnmapViewOfFile.c => UnmapViewOfFile.cpp} | 0 .../UnmapViewOfFile/test2/CMakeLists.txt | 2 +- .../{unmapviewoffile.c => unmapviewoffile.cpp} | 0 .../filemapping_memmgt/VirtualAlloc/CMakeLists.txt | 1 + .../VirtualAlloc/test1/CMakeLists.txt | 2 +- .../test1/{VirtualAlloc.c => VirtualAlloc.cpp} | 0 .../VirtualAlloc/test10/CMakeLists.txt | 2 +- .../test10/{VirtualAlloc.c => VirtualAlloc.cpp} | 0 .../VirtualAlloc/test11/CMakeLists.txt | 2 +- .../test11/{VirtualAlloc.c => VirtualAlloc.cpp} | 0 .../VirtualAlloc/test12/CMakeLists.txt | 2 +- .../test12/{VirtualAlloc.c => VirtualAlloc.cpp} | 0 .../VirtualAlloc/test13/CMakeLists.txt | 2 +- .../test13/{VirtualAlloc.c => VirtualAlloc.cpp} | 0 .../VirtualAlloc/test14/CMakeLists.txt | 2 +- .../test14/{VirtualAlloc.c => VirtualAlloc.cpp} | 0 .../VirtualAlloc/test15/CMakeLists.txt | 2 +- .../test15/{VirtualAlloc.c => VirtualAlloc.cpp} | 0 .../VirtualAlloc/test16/CMakeLists.txt | 2 +- .../test16/{VirtualAlloc.c => VirtualAlloc.cpp} | 0 .../VirtualAlloc/test17/CMakeLists.txt | 2 +- .../test17/{VirtualAlloc.c => VirtualAlloc.cpp} | 0 .../VirtualAlloc/test18/CMakeLists.txt | 2 +- .../test18/{VirtualAlloc.c => VirtualAlloc.cpp} | 0 .../VirtualAlloc/test19/CMakeLists.txt | 2 +- .../test19/{VirtualAlloc.c => VirtualAlloc.cpp} | 0 .../VirtualAlloc/test2/CMakeLists.txt | 2 +- .../test2/{VirtualAlloc.c => VirtualAlloc.cpp} | 0 .../VirtualAlloc/test20/CMakeLists.txt | 2 +- .../test20/{virtualalloc.c => virtualalloc.cpp} | 0 .../VirtualAlloc/test21/CMakeLists.txt | 2 +- .../test21/{virtualalloc.c => virtualalloc.cpp} | 0 .../VirtualAlloc/test22/CMakeLists.txt | 19 + .../VirtualAlloc/test22/VirtualAlloc.cpp | 44 + .../VirtualAlloc/test22/testinfo.dat | 13 + .../VirtualAlloc/test3/CMakeLists.txt | 2 +- .../test3/{VirtualAlloc.c => VirtualAlloc.cpp} | 0 .../VirtualAlloc/test4/CMakeLists.txt | 2 +- .../test4/{VirtualAlloc.c => VirtualAlloc.cpp} | 0 .../VirtualAlloc/test5/CMakeLists.txt | 2 +- .../test5/{VirtualAlloc.c => VirtualAlloc.cpp} | 0 .../VirtualAlloc/test6/CMakeLists.txt | 2 +- .../test6/{VirtualAlloc.c => VirtualAlloc.cpp} | 0 .../VirtualAlloc/test7/CMakeLists.txt | 2 +- .../test7/{VirtualAlloc.c => VirtualAlloc.cpp} | 0 .../VirtualAlloc/test8/CMakeLists.txt | 2 +- .../test8/{VirtualAlloc.c => VirtualAlloc.cpp} | 0 .../VirtualAlloc/test9/CMakeLists.txt | 2 +- .../test9/{VirtualAlloc.c => VirtualAlloc.cpp} | 0 .../VirtualFree/test1/CMakeLists.txt | 2 +- .../test1/{VirtualFree.c => VirtualFree.cpp} | 0 .../VirtualFree/test2/CMakeLists.txt | 2 +- .../test2/{VirtualFree.c => VirtualFree.cpp} | 0 .../VirtualFree/test3/CMakeLists.txt | 2 +- .../test3/{VirtualFree.c => VirtualFree.cpp} | 0 .../VirtualProtect/test1/CMakeLists.txt | 2 +- .../test1/{VirtualProtect.c => VirtualProtect.cpp} | 0 .../VirtualProtect/test2/CMakeLists.txt | 2 +- .../test2/{VirtualProtect.c => VirtualProtect.cpp} | 0 .../VirtualProtect/test3/CMakeLists.txt | 2 +- .../test3/{VirtualProtect.c => VirtualProtect.cpp} | 0 .../VirtualProtect/test4/CMakeLists.txt | 2 +- .../test4/{VirtualProtect.c => VirtualProtect.cpp} | 0 .../VirtualProtect/test6/CMakeLists.txt | 2 +- .../test6/{VirtualProtect.c => VirtualProtect.cpp} | 0 .../VirtualProtect/test7/CMakeLists.txt | 2 +- .../test7/{VirtualProtect.c => VirtualProtect.cpp} | 0 .../VirtualQuery/test1/CMakeLists.txt | 2 +- .../test1/{VirtualQuery.c => VirtualQuery.cpp} | 0 .../loader/LoadLibraryA/test1/CMakeLists.txt | 2 +- .../test1/{LoadLibraryA.c => LoadLibraryA.cpp} | 0 .../loader/LoadLibraryA/test2/CMakeLists.txt | 2 +- .../test2/{LoadLibraryA.c => LoadLibraryA.cpp} | 0 .../test2/{MyModule.c => MyModule.cpp} | 0 .../loader/LoadLibraryA/test3/CMakeLists.txt | 2 +- .../test3/{loadlibrarya.c => loadlibrarya.cpp} | 0 .../loader/LoadLibraryA/test5/CMakeLists.txt | 2 +- .../loader/LoadLibraryA/test5/loadlibrarya.c | 67 - .../loader/LoadLibraryA/test5/loadlibrarya.cpp | 67 + .../loader/LoadLibraryA/test6/CMakeLists.txt | 4 +- .../{test8/dlltest.c => test6/dlltest.cpp} | 0 .../test6/{loadlibrarya.c => loadlibrarya.cpp} | 0 .../loader/LoadLibraryA/test7/CMakeLists.txt | 2 +- .../test7/{LoadLibraryA.c => LoadLibraryA.cpp} | 0 .../loader/LoadLibraryA/test8/CMakeLists.txt | 4 +- .../{test6/dlltest.c => test8/dlltest.cpp} | 0 .../test8/{loadlibrarya.c => loadlibrarya.cpp} | 0 .../loader/LoadLibraryW/test1/CMakeLists.txt | 2 +- .../test1/{LoadLibraryW.c => LoadLibraryW.cpp} | 0 .../loader/LoadLibraryW/test2/CMakeLists.txt | 2 +- .../test2/{loadlibraryw.c => loadlibraryw.cpp} | 0 .../loader/LoadLibraryW/test3/CMakeLists.txt | 2 +- .../test3/{loadlibraryw.c => loadlibraryw.cpp} | 0 .../loader/LoadLibraryW/test5/CMakeLists.txt | 2 +- .../loader/LoadLibraryW/test5/loadlibraryw.c | 71 - .../loader/LoadLibraryW/test5/loadlibraryw.cpp | 71 + .../CompareStringA/test1/CMakeLists.txt | 2 +- .../CompareStringA/test1/{test1.c => test1.cpp} | 0 .../CompareStringW/test1/CMakeLists.txt | 2 +- .../CompareStringW/test1/{test1.c => test1.cpp} | 0 .../locale_info/GetACP/test1/CMakeLists.txt | 2 +- .../GetACP/test1/{test1.c => test1.cpp} | 0 .../locale_info/GetCPInfo/test1/CMakeLists.txt | 2 +- .../GetCPInfo/test1/{test1.c => test1.cpp} | 0 .../locale_info/GetCPInfo/test2/CMakeLists.txt | 2 +- .../GetCPInfo/test2/{test2.c => test2.cpp} | 0 .../locale_info/GetCPInfo/test3/CMakeLists.txt | 2 +- .../GetCPInfo/test3/{test3.c => test3.cpp} | 0 .../GetLocaleInfoW/test1/CMakeLists.txt | 2 +- .../GetLocaleInfoW/test1/{test1.c => test1.cpp} | 0 .../GetLocaleInfoW/test2/CMakeLists.txt | 2 +- .../GetLocaleInfoW/test2/{test2.c => test2.cpp} | 0 .../GetStringTypeExW/test1/CMakeLists.txt | 2 +- .../GetStringTypeExW/test1/{test1.c => test1.cpp} | 0 .../GetStringTypeExW/test2/CMakeLists.txt | 2 +- .../GetStringTypeExW/test2/{test2.c => test2.cpp} | 0 .../GetSystemDefaultLangID/test1/CMakeLists.txt | 2 +- .../test1/{test1.c => test1.cpp} | 0 .../GetThreadLocale/test1/CMakeLists.txt | 2 +- .../GetThreadLocale/test1/{test1.c => test1.cpp} | 0 .../GetTimeZoneInformation/test1/CMakeLists.txt | 2 +- .../test1/{test1.c => test1.cpp} | 0 .../GetUserDefaultLCID/test1/CMakeLists.txt | 2 +- .../test1/{test1.c => test1.cpp} | 0 .../GetUserDefaultLangID/test1/CMakeLists.txt | 2 +- .../test1/{test1.c => test1.cpp} | 0 .../IsDBCSLeadByte/test1/CMakeLists.txt | 2 +- .../IsDBCSLeadByte/test1/{test1.c => test1.cpp} | 0 .../IsDBCSLeadByteEx/test1/CMakeLists.txt | 2 +- .../IsDBCSLeadByteEx/test1/{test1.c => test1.cpp} | 0 .../IsValidCodePage/test1/CMakeLists.txt | 2 +- .../IsValidCodePage/test1/{test1.c => test1.cpp} | 0 .../IsValidCodePage/test2/CMakeLists.txt | 2 +- .../IsValidCodePage/test2/{test2.c => test2.cpp} | 0 .../locale_info/IsValidLocale/test1/CMakeLists.txt | 2 +- .../IsValidLocale/test1/{test1.c => test1.cpp} | 0 .../MultiByteToWideChar/test1/CMakeLists.txt | 2 +- .../test1/{test1.c => test1.cpp} | 0 .../MultiByteToWideChar/test2/CMakeLists.txt | 2 +- .../test2/{test2.c => test2.cpp} | 0 .../MultiByteToWideChar/test3/CMakeLists.txt | 2 +- .../test3/{test3.c => test3.cpp} | 0 .../MultiByteToWideChar/test4/CMakeLists.txt | 2 +- .../locale_info/MultiByteToWideChar/test4/test4.c | 230 - .../MultiByteToWideChar/test4/test4.cpp | 230 + .../SetThreadLocale/test1/CMakeLists.txt | 2 +- .../SetThreadLocale/test1/{test1.c => test1.cpp} | 0 .../WideCharToMultiByte/test1/CMakeLists.txt | 2 +- .../test1/{test1.c => test1.cpp} | 0 .../WideCharToMultiByte/test2/CMakeLists.txt | 2 +- .../test2/{test2.c => test2.cpp} | 0 .../WideCharToMultiByte/test3/CMakeLists.txt | 2 +- .../test3/{test3.c => test3.cpp} | 0 .../WideCharToMultiByte/test4/CMakeLists.txt | 2 +- .../test4/{test4.c => test4.cpp} | 0 .../WideCharToMultiByte/test5/CMakeLists.txt | 2 +- .../locale_info/WideCharToMultiByte/test5/test5.c | 154 - .../WideCharToMultiByte/test5/test5.cpp | 154 + .../tests/palsuite/miscellaneous/CMakeLists.txt | 6 - .../miscellaneous/CharNextA/test1/CMakeLists.txt | 2 +- .../CharNextA/test1/{test.c => test.cpp} | 0 .../miscellaneous/CharNextA/test2/CMakeLists.txt | 2 +- .../CharNextA/test2/{test.c => test.cpp} | 0 .../miscellaneous/CharNextExA/test1/CMakeLists.txt | 2 +- .../CharNextExA/test1/{test.c => test.cpp} | 0 .../miscellaneous/CharNextExA/test2/CMakeLists.txt | 2 +- .../CharNextExA/test2/{test.c => test.cpp} | 0 .../miscellaneous/CloseHandle/test1/CMakeLists.txt | 2 +- .../miscellaneous/CloseHandle/test1/test.c | 64 - .../miscellaneous/CloseHandle/test1/test.cpp | 64 + .../miscellaneous/CloseHandle/test2/CMakeLists.txt | 2 +- .../CloseHandle/test2/{test.c => test.cpp} | 0 .../miscellaneous/CreatePipe/test1/CMakeLists.txt | 2 +- .../CreatePipe/test1/{test1.c => test1.cpp} | 0 .../FlushInstructionCache/test1/CMakeLists.txt | 2 +- .../test1/{test1.c => test1.cpp} | 0 .../FormatMessageW/test1/CMakeLists.txt | 2 +- .../FormatMessageW/test1/{test.c => test.cpp} | 0 .../FormatMessageW/test2/CMakeLists.txt | 2 +- .../FormatMessageW/test2/{test.c => test.cpp} | 0 .../FormatMessageW/test3/CMakeLists.txt | 2 +- .../FormatMessageW/test3/{test.c => test.cpp} | 0 .../FormatMessageW/test4/CMakeLists.txt | 2 +- .../FormatMessageW/test4/{test.c => test.cpp} | 0 .../FormatMessageW/test5/CMakeLists.txt | 2 +- .../FormatMessageW/test5/{test.c => test.cpp} | 0 .../FormatMessageW/test6/CMakeLists.txt | 2 +- .../FormatMessageW/test6/{test.c => test.cpp} | 0 .../FreeEnvironmentStringsW/test1/CMakeLists.txt | 2 +- .../test1/{test.c => test.cpp} | 0 .../FreeEnvironmentStringsW/test2/CMakeLists.txt | 2 +- .../test2/{test.c => test.cpp} | 0 .../GetCalendarInfoW/test1/CMakeLists.txt | 2 +- .../{GetCalendarInfoW.c => GetCalendarInfoW.cpp} | 0 .../GetCalendarInfoW/test2/CMakeLists.txt | 2 +- .../{GetCalendarInfoW.c => GetCalendarInfoW.cpp} | 0 .../GetCommandLineW/test1/CMakeLists.txt | 2 +- .../miscellaneous/GetCommandLineW/test1/test.c | 71 - .../miscellaneous/GetCommandLineW/test1/test.cpp | 71 + .../GetComputerNameW/test1/CMakeLists.txt | 2 +- .../GetComputerNameW/test1/{test.c => test.cpp} | 0 .../GetDateFormatW_neg1/CMakeLists.txt | 2 +- .../GetDateFormatW_neg1/GetDateFormatW_neg.c | 85 - .../GetDateFormatW_neg1/GetDateFormatW_neg.cpp | 85 + .../GetDateFormatW_neg2/CMakeLists.txt | 2 +- .../GetDateFormatW_neg2/GetDateFormatW_neg.c | 98 - .../GetDateFormatW_neg2/GetDateFormatW_neg.cpp | 98 + .../GetDateFormatW/test1/CMakeLists.txt | 2 +- .../GetDateFormatW/test1/GetDateFormatW.c | 100 - .../GetDateFormatW/test1/GetDateFormatW.cpp | 100 + .../GetEnvironmentStringsW/test1/CMakeLists.txt | 2 +- .../test1/{test.c => test.cpp} | 0 .../GetEnvironmentVariableA/test1/CMakeLists.txt | 2 +- .../GetEnvironmentVariableA/test1/test.c | 84 - .../GetEnvironmentVariableA/test1/test.cpp | 84 + .../GetEnvironmentVariableA/test2/CMakeLists.txt | 2 +- .../test2/{test.c => test.cpp} | 0 .../GetEnvironmentVariableA/test3/CMakeLists.txt | 2 +- .../test3/{test.c => test.cpp} | 0 .../GetEnvironmentVariableA/test4/CMakeLists.txt | 2 +- .../GetEnvironmentVariableA/test4/test.c | 75 - .../GetEnvironmentVariableA/test4/test.cpp | 75 + .../GetEnvironmentVariableA/test5/CMakeLists.txt | 2 +- .../GetEnvironmentVariableA/test5/test5.c | 145 - .../GetEnvironmentVariableA/test5/test5.cpp | 145 + .../GetEnvironmentVariableA/test6/CMakeLists.txt | 2 +- .../GetEnvironmentVariableA/test6/test6.c | 99 - .../GetEnvironmentVariableA/test6/test6.cpp | 99 + .../GetEnvironmentVariableW/test1/CMakeLists.txt | 2 +- .../GetEnvironmentVariableW/test1/test.c | 79 - .../GetEnvironmentVariableW/test1/test.cpp | 79 + .../GetEnvironmentVariableW/test2/CMakeLists.txt | 2 +- .../test2/{test.c => test.cpp} | 0 .../GetEnvironmentVariableW/test3/CMakeLists.txt | 2 +- .../test3/{test.c => test.cpp} | 0 .../GetEnvironmentVariableW/test4/CMakeLists.txt | 2 +- .../GetEnvironmentVariableW/test4/test.c | 63 - .../GetEnvironmentVariableW/test4/test.cpp | 63 + .../GetEnvironmentVariableW/test5/CMakeLists.txt | 2 +- .../GetEnvironmentVariableW/test5/test5.c | 144 - .../GetEnvironmentVariableW/test5/test5.cpp | 144 + .../GetEnvironmentVariableW/test6/CMakeLists.txt | 2 +- .../GetEnvironmentVariableW/test6/test6.c | 99 - .../GetEnvironmentVariableW/test6/test6.cpp | 99 + .../GetLastError/test1/CMakeLists.txt | 2 +- .../GetLastError/test1/{test.c => test.cpp} | 0 .../GetSystemInfo/test1/CMakeLists.txt | 2 +- .../GetSystemInfo/test1/{test.c => test.cpp} | 0 .../GetTickCount/test1/CMakeLists.txt | 2 +- .../GetTickCount/test1/{test.c => test.cpp} | 0 .../GetUserNameW/test1/CMakeLists.txt | 2 +- .../GetUserNameW/test1/{test.c => test.cpp} | 0 .../GetVersionExA/test1/CMakeLists.txt | 2 +- .../GetVersionExA/test1/{test.c => test.cpp} | 0 .../GetVersionExW/test1/CMakeLists.txt | 2 +- .../GetVersionExW/test1/{test.c => test.cpp} | 0 .../IsBadCodePtr/test1/CMakeLists.txt | 2 +- .../IsBadCodePtr/test1/{test1.c => test1.cpp} | 0 .../IsBadReadPtr/test1/CMakeLists.txt | 2 +- .../IsBadReadPtr/test1/{test.c => test.cpp} | 0 .../IsBadWritePtr/test1/CMakeLists.txt | 2 +- .../IsBadWritePtr/test1/{test.c => test.cpp} | 0 .../IsBadWritePtr/test2/CMakeLists.txt | 2 +- .../IsBadWritePtr/test2/{test2.c => test2.cpp} | 0 .../IsBadWritePtr/test3/CMakeLists.txt | 2 +- .../IsBadWritePtr/test3/{test3.c => test3.cpp} | 0 .../miscellaneous/MessageBoxW/test1/CMakeLists.txt | 2 +- .../MessageBoxW/test1/{test.c => test.cpp} | 0 .../miscellaneous/MessageBoxW/test2/CMakeLists.txt | 2 +- .../MessageBoxW/test2/{test.c => test.cpp} | 0 .../SetEnvironmentVariableA/test1/CMakeLists.txt | 2 +- .../test1/{test1.c => test1.cpp} | 0 .../SetEnvironmentVariableA/test2/CMakeLists.txt | 2 +- .../test2/{test2.c => test2.cpp} | 0 .../SetEnvironmentVariableA/test3/CMakeLists.txt | 2 +- .../SetEnvironmentVariableA/test3/test3.c | 144 - .../SetEnvironmentVariableA/test3/test3.cpp | 144 + .../SetEnvironmentVariableA/test4/CMakeLists.txt | 2 +- .../SetEnvironmentVariableA/test4/test4.c | 100 - .../SetEnvironmentVariableA/test4/test4.cpp | 100 + .../SetEnvironmentVariableW/test1/CMakeLists.txt | 2 +- .../test1/{test.c => test.cpp} | 0 .../SetEnvironmentVariableW/test2/CMakeLists.txt | 2 +- .../test2/{test.c => test.cpp} | 0 .../SetEnvironmentVariableW/test3/CMakeLists.txt | 2 +- .../SetEnvironmentVariableW/test3/test3.c | 143 - .../SetEnvironmentVariableW/test3/test3.cpp | 143 + .../SetEnvironmentVariableW/test4/CMakeLists.txt | 2 +- .../SetEnvironmentVariableW/test4/test4.c | 99 - .../SetEnvironmentVariableW/test4/test4.cpp | 99 + .../SetLastError/test1/CMakeLists.txt | 2 +- .../SetLastError/test1/{test.c => test.cpp} | 0 .../miscellaneous/_i64tow/test1/CMakeLists.txt | 2 +- .../palsuite/miscellaneous/_i64tow/test1/test1.c | 76 - .../palsuite/miscellaneous/_i64tow/test1/test1.cpp | 76 + .../miscellaneous/_i64tow/test1/testinfo.dat | 6 +- .../palsuite/miscellaneous/_ui64tow/CMakeLists.txt | 5 - .../miscellaneous/_ui64tow/test1/CMakeLists.txt | 19 - .../miscellaneous/_ui64tow/test1/_ui64tow.c | 101 - .../miscellaneous/_ui64tow/test1/testinfo.dat | 12 - .../miscellaneous/_ui64tow/test2/CMakeLists.txt | 19 - .../miscellaneous/_ui64tow/test2/_ui64tow.c | 88 - .../miscellaneous/_ui64tow/test2/testinfo.dat | 13 - .../palsuite/miscellaneous/lstrcatW/CMakeLists.txt | 7 - .../miscellaneous/lstrcatW/test1/CMakeLists.txt | 19 - .../palsuite/miscellaneous/lstrcatW/test1/test.c | 59 - .../miscellaneous/lstrcatW/test1/testinfo.dat | 16 - .../miscellaneous/lstrcatW/test2/CMakeLists.txt | 19 - .../palsuite/miscellaneous/lstrcatW/test2/test2.c | 53 - .../miscellaneous/lstrcatW/test2/testinfo.dat | 12 - .../miscellaneous/lstrcatW/test3/CMakeLists.txt | 19 - .../palsuite/miscellaneous/lstrcatW/test3/test3.c | 46 - .../miscellaneous/lstrcatW/test3/testinfo.dat | 26 - .../miscellaneous/lstrcatW/test4/CMakeLists.txt | 19 - .../palsuite/miscellaneous/lstrcatW/test4/test4.c | 101 - .../miscellaneous/lstrcatW/test4/testinfo.dat | 28 - .../palsuite/miscellaneous/lstrcpyW/CMakeLists.txt | 4 - .../miscellaneous/lstrcpyW/test1/CMakeLists.txt | 19 - .../palsuite/miscellaneous/lstrcpyW/test1/test.c | 66 - .../miscellaneous/lstrcpyW/test1/testinfo.dat | 16 - .../miscellaneous/lstrcpynW/test1/CMakeLists.txt | 19 - .../palsuite/miscellaneous/lstrcpynW/test1/test.c | 73 - .../miscellaneous/lstrcpynW/test1/testinfo.dat | 16 - .../miscellaneous/lstrlenA/test1/CMakeLists.txt | 2 +- .../lstrlenA/test1/{test.c => test.cpp} | 0 .../miscellaneous/lstrlenW/test1/CMakeLists.txt | 2 +- .../lstrlenW/test1/{test.c => test.cpp} | 0 .../queryperformancecounter/test1/CMakeLists.txt | 2 +- .../test1/{test1.c => test1.cpp} | 0 .../queryperformancefrequency/test1/CMakeLists.txt | 2 +- .../test1/{test1.c => test1.cpp} | 0 .../miscellaneous/wsprintfA/CMakeLists.txt | 13 - .../miscellaneous/wsprintfA/test1/CMakeLists.txt | 19 - .../palsuite/miscellaneous/wsprintfA/test1/test.c | 58 - .../miscellaneous/wsprintfA/test1/testinfo.dat | 14 - .../miscellaneous/wsprintfA/test11/CMakeLists.txt | 19 - .../palsuite/miscellaneous/wsprintfA/test11/test.c | 128 - .../miscellaneous/wsprintfA/test11/testinfo.dat | 14 - .../miscellaneous/wsprintfA/test12/CMakeLists.txt | 19 - .../palsuite/miscellaneous/wsprintfA/test12/test.c | 119 - .../miscellaneous/wsprintfA/test12/testinfo.dat | 14 - .../miscellaneous/wsprintfA/test13/CMakeLists.txt | 19 - .../palsuite/miscellaneous/wsprintfA/test13/test.c | 120 - .../miscellaneous/wsprintfA/test13/testinfo.dat | 14 - .../miscellaneous/wsprintfA/test2/CMakeLists.txt | 19 - .../palsuite/miscellaneous/wsprintfA/test2/test.c | 123 - .../miscellaneous/wsprintfA/test2/testinfo.dat | 14 - .../miscellaneous/wsprintfA/test3/CMakeLists.txt | 19 - .../palsuite/miscellaneous/wsprintfA/test3/test.c | 121 - .../miscellaneous/wsprintfA/test3/testinfo.dat | 14 - .../miscellaneous/wsprintfA/test6/CMakeLists.txt | 19 - .../palsuite/miscellaneous/wsprintfA/test6/test.c | 114 - .../miscellaneous/wsprintfA/test6/testinfo.dat | 14 - .../miscellaneous/wsprintfA/test7/CMakeLists.txt | 19 - .../palsuite/miscellaneous/wsprintfA/test7/test.c | 112 - .../miscellaneous/wsprintfA/test7/testinfo.dat | 14 - .../miscellaneous/wsprintfA/test8/CMakeLists.txt | 19 - .../palsuite/miscellaneous/wsprintfA/test8/test.c | 120 - .../miscellaneous/wsprintfA/test8/testinfo.dat | 14 - .../miscellaneous/wsprintfA/test9/CMakeLists.txt | 19 - .../palsuite/miscellaneous/wsprintfA/test9/test.c | 122 - .../miscellaneous/wsprintfA/test9/testinfo.dat | 14 - .../miscellaneous/wsprintfW/CMakeLists.txt | 13 - .../miscellaneous/wsprintfW/test1/CMakeLists.txt | 19 - .../palsuite/miscellaneous/wsprintfW/test1/test.c | 64 - .../miscellaneous/wsprintfW/test1/testinfo.dat | 14 - .../miscellaneous/wsprintfW/test11/CMakeLists.txt | 19 - .../palsuite/miscellaneous/wsprintfW/test11/test.c | 139 - .../miscellaneous/wsprintfW/test11/testinfo.dat | 14 - .../miscellaneous/wsprintfW/test12/CMakeLists.txt | 19 - .../palsuite/miscellaneous/wsprintfW/test12/test.c | 128 - .../miscellaneous/wsprintfW/test12/testinfo.dat | 14 - .../miscellaneous/wsprintfW/test13/CMakeLists.txt | 19 - .../palsuite/miscellaneous/wsprintfW/test13/test.c | 126 - .../miscellaneous/wsprintfW/test13/testinfo.dat | 14 - .../miscellaneous/wsprintfW/test2/CMakeLists.txt | 19 - .../palsuite/miscellaneous/wsprintfW/test2/test.c | 108 - .../miscellaneous/wsprintfW/test2/testinfo.dat | 14 - .../miscellaneous/wsprintfW/test3/CMakeLists.txt | 19 - .../palsuite/miscellaneous/wsprintfW/test3/test.c | 127 - .../miscellaneous/wsprintfW/test3/testinfo.dat | 14 - .../miscellaneous/wsprintfW/test6/CMakeLists.txt | 19 - .../palsuite/miscellaneous/wsprintfW/test6/test.c | 115 - .../miscellaneous/wsprintfW/test6/testinfo.dat | 14 - .../miscellaneous/wsprintfW/test7/CMakeLists.txt | 19 - .../palsuite/miscellaneous/wsprintfW/test7/test.c | 117 - .../miscellaneous/wsprintfW/test7/testinfo.dat | 14 - .../miscellaneous/wsprintfW/test8/CMakeLists.txt | 19 - .../palsuite/miscellaneous/wsprintfW/test8/test.c | 128 - .../miscellaneous/wsprintfW/test8/testinfo.dat | 14 - .../miscellaneous/wsprintfW/test9/CMakeLists.txt | 19 - .../palsuite/miscellaneous/wsprintfW/test9/test.c | 128 - .../miscellaneous/wsprintfW/test9/testinfo.dat | 14 - .../PAL_GetPALDirectoryW/test1/CMakeLists.txt | 2 +- .../test1/PAL_GetPALDirectoryW.c | 78 - .../test1/PAL_GetPALDirectoryW.cpp | 78 + .../PAL_GetUserTempDirectoryW/test1/CMakeLists.txt | 2 +- ...pDirectoryW.c => PAL_GetUserTempDirectoryW.cpp} | 0 .../PAL_Initialize_Terminate/test1/CMakeLists.txt | 2 +- ...ze_Terminate.c => PAL_Initialize_Terminate.cpp} | 0 .../PAL_Initialize_Terminate/test2/CMakeLists.txt | 2 +- ...initialize_twice.c => pal_initialize_twice.cpp} | 0 .../test1/CMakeLists.txt | 2 +- .../PAL_RegisterLibraryW_UnregisterLibraryW.c | 64 - .../PAL_RegisterLibraryW_UnregisterLibraryW.cpp | 64 + .../test2_neg/CMakeLists.txt | 2 +- .../test2_neg/reg_unreg_libraryw_neg.c | 62 - .../test2_neg/reg_unreg_libraryw_neg.cpp | 62 + .../pal_specific/PAL_errno/test1/CMakeLists.txt | 2 +- .../PAL_errno/test1/{PAL_errno.c => PAL_errno.cpp} | 0 .../PAL_get_stderr/test1/CMakeLists.txt | 2 +- .../test1/{PAL_get_stderr.c => PAL_get_stderr.cpp} | 0 .../PAL_get_stdin/test1/CMakeLists.txt | 2 +- .../test1/{PAL_get_stdin.c => PAL_get_stdin.cpp} | 0 .../PAL_get_stdout/test1/CMakeLists.txt | 2 +- .../test1/{PAL_get_stdout.c => PAL_get_stdout.cpp} | 0 .../pal_entrypoint/test1/CMakeLists.txt | 2 +- .../test1/{pal_entrypoint.c => pal_entrypoint.cpp} | 0 .../pal_initializedebug/test1/CMakeLists.txt | 2 +- ...l_initializedebug.c => pal_initializedebug.cpp} | 0 src/pal/tests/palsuite/paltestlist.txt | 226 +- .../tests/palsuite/paltestlist_to_be_reviewed.txt | 9 +- src/pal/tests/palsuite/palverify.dat | 210 +- .../tests/palsuite/samples/test1/CMakeLists.txt | 2 +- .../palsuite/samples/test1/{test.c => test.cpp} | 0 .../tests/palsuite/samples/test2/CMakeLists.txt | 2 +- .../palsuite/samples/test2/{test.c => test.cpp} | 0 .../threading/CreateEventA/test1/CMakeLists.txt | 2 +- .../CreateEventA/test1/{test1.c => test1.cpp} | 0 .../threading/CreateEventA/test2/CMakeLists.txt | 2 +- .../CreateEventA/test2/{test2.c => test2.cpp} | 0 .../threading/CreateEventA/test3/CMakeLists.txt | 2 +- .../CreateEventA/test3/{test3.c => test3.cpp} | 0 .../threading/CreateEventW/test1/CMakeLists.txt | 2 +- .../CreateEventW/test1/{test1.c => test1.cpp} | 0 .../threading/CreateEventW/test2/CMakeLists.txt | 2 +- .../CreateEventW/test2/{test2.c => test2.cpp} | 0 .../threading/CreateEventW/test3/CMakeLists.txt | 2 +- .../CreateEventW/test3/{test3.c => test3.cpp} | 0 .../CreateMutexA_ReleaseMutex/test1/CMakeLists.txt | 2 +- .../test1/{CreateMutexA.c => CreateMutexA.cpp} | 0 .../CreateMutexA_ReleaseMutex/test2/CMakeLists.txt | 2 +- .../CreateMutexA_ReleaseMutex/test2/CreateMutexA.c | 331 - .../test2/CreateMutexA.cpp | 331 + .../CreateMutexW_ReleaseMutex/test1/CMakeLists.txt | 2 +- .../test1/{CreateMutexW.c => CreateMutexW.cpp} | 0 .../CreateMutexW_ReleaseMutex/test2/CMakeLists.txt | 2 +- .../test2/{CreateMutexW.c => CreateMutexW.cpp} | 0 .../threading/CreateProcessA/test1/CMakeLists.txt | 4 +- .../test1/{childProcess.c => childProcess.cpp} | 0 .../test1/{parentProcess.c => parentProcess.cpp} | 0 .../threading/CreateProcessA/test2/CMakeLists.txt | 4 +- .../test2/{childprocess.c => childprocess.cpp} | 0 .../test2/{parentprocess.c => parentprocess.cpp} | 0 .../threading/CreateProcessW/test1/CMakeLists.txt | 4 +- .../threading/CreateProcessW/test1/childProcess.c | 150 - .../CreateProcessW/test1/childProcess.cpp | 150 + .../test1/{parentProcess.c => parentProcess.cpp} | 0 .../threading/CreateProcessW/test2/CMakeLists.txt | 4 +- .../test2/{childprocess.c => childprocess.cpp} | 0 .../test2/{parentprocess.c => parentprocess.cpp} | 0 .../test1/CMakeLists.txt | 2 +- .../{CreateSemaphore.c => CreateSemaphore.cpp} | 0 .../test2/CMakeLists.txt | 2 +- .../{CreateSemaphore.c => CreateSemaphore.cpp} | 0 .../test3/CMakeLists.txt | 2 +- .../{createsemaphore.c => createsemaphore.cpp} | 0 .../test1/CMakeLists.txt | 2 +- .../{CreateSemaphore.c => CreateSemaphore.cpp} | 0 .../test2/CMakeLists.txt | 2 +- .../{CreateSemaphore.c => CreateSemaphore.cpp} | 0 .../test3/CMakeLists.txt | 2 +- .../{createsemaphore.c => createsemaphore.cpp} | 0 .../threading/CreateThread/test1/CMakeLists.txt | 2 +- .../palsuite/threading/CreateThread/test1/test1.c | 119 - .../threading/CreateThread/test1/test1.cpp | 119 + .../threading/CreateThread/test2/CMakeLists.txt | 2 +- .../palsuite/threading/CreateThread/test2/test2.c | 184 - .../threading/CreateThread/test2/test2.cpp | 184 + .../threading/CreateThread/test3/CMakeLists.txt | 2 +- .../CreateThread/test3/{test3.c => test3.cpp} | 0 .../CriticalSectionFunctions/test1/CMakeLists.txt | 2 +- ...icalSection.c => InitializeCriticalSection.cpp} | 0 .../CriticalSectionFunctions/test2/CMakeLists.txt | 2 +- .../test2/{test2.c => test2.cpp} | 0 .../CriticalSectionFunctions/test3/CMakeLists.txt | 2 +- .../test3/{test3.c => test3.cpp} | 0 .../CriticalSectionFunctions/test4/CMakeLists.txt | 2 +- .../test4/{test4.c => test4.cpp} | 0 .../CriticalSectionFunctions/test5/CMakeLists.txt | 2 +- .../test5/{test5.c => test5.cpp} | 0 .../CriticalSectionFunctions/test6/CMakeLists.txt | 2 +- .../test6/{test6.c => test6.cpp} | 0 .../CriticalSectionFunctions/test7/CMakeLists.txt | 2 +- .../test7/{test7.c => test7.cpp} | 0 .../CriticalSectionFunctions/test8/CMakeLists.txt | 2 +- .../test8/{test8.c => test8.cpp} | 0 .../test1/{test1.c => test1.cpp} | 0 .../test1/{testlib.c => testlib.cpp} | 0 .../test2/{dllmain1.c => dllmain1.cpp} | 0 .../test2/{dllmain2.c => dllmain2.cpp} | 0 .../test2/{test2.c => test2.cpp} | 0 .../threading/DuplicateHandle/CMakeLists.txt | 1 - .../threading/DuplicateHandle/test1/CMakeLists.txt | 2 +- .../DuplicateHandle/test1/{test1.c => test1.cpp} | 0 .../DuplicateHandle/test10/CMakeLists.txt | 2 +- .../test10/{test10.c => test10.cpp} | 0 .../DuplicateHandle/test11/CMakeLists.txt | 4 +- .../test11/{childprocess.c => childprocess.cpp} | 0 .../test11/{test11.c => test11.cpp} | 0 .../DuplicateHandle/test12/CMakeLists.txt | 2 +- .../test12/{test12.c => test12.cpp} | 0 .../threading/DuplicateHandle/test2/CMakeLists.txt | 2 +- .../DuplicateHandle/test2/{test2.c => test2.cpp} | 0 .../threading/DuplicateHandle/test3/CMakeLists.txt | 2 +- .../DuplicateHandle/test3/{test3.c => test3.cpp} | 0 .../threading/DuplicateHandle/test4/CMakeLists.txt | 2 +- .../DuplicateHandle/test4/{test4.c => test4.cpp} | 0 .../threading/DuplicateHandle/test5/CMakeLists.txt | 2 +- .../DuplicateHandle/test5/{test5.c => test5.cpp} | 0 .../threading/DuplicateHandle/test6/CMakeLists.txt | 2 +- .../DuplicateHandle/test6/{test6.c => test6.cpp} | 0 .../threading/DuplicateHandle/test7/CMakeLists.txt | 2 +- .../DuplicateHandle/test7/{test7.c => test7.cpp} | 0 .../threading/DuplicateHandle/test8/CMakeLists.txt | 2 +- .../DuplicateHandle/test8/{test8.c => test8.cpp} | 0 .../threading/DuplicateHandle/test9/CMakeLists.txt | 2 +- .../DuplicateHandle/test9/{test9.c => test9.cpp} | 0 .../threading/ExitProcess/test1/CMakeLists.txt | 2 +- .../test1/{ExitProcess.c => ExitProcess.cpp} | 0 .../threading/ExitProcess/test2/CMakeLists.txt | 2 +- .../ExitProcess/test2/{test2.c => test2.cpp} | 0 .../threading/ExitProcess/test3/CMakeLists.txt | 2 +- .../ExitProcess/test3/{test3.c => test3.cpp} | 0 .../threading/ExitThread/test1/CMakeLists.txt | 2 +- .../palsuite/threading/ExitThread/test1/test1.c | 114 - .../palsuite/threading/ExitThread/test1/test1.cpp | 114 + .../threading/ExitThread/test2/CMakeLists.txt | 4 +- .../test2/{childprocess.c => childprocess.cpp} | 0 .../ExitThread/test2/{test2.c => test2.cpp} | 0 .../ExitThread/test3/{dllmain.c => dllmain.cpp} | 0 .../ExitThread/test3/{test3.c => test3.cpp} | 0 .../GetCurrentProcess/test1/CMakeLists.txt | 2 +- .../test1/{process.c => process.cpp} | 0 .../GetCurrentProcessId/test1/CMakeLists.txt | 2 +- .../test1/{processId.c => processId.cpp} | 0 .../GetCurrentThread/test1/CMakeLists.txt | 2 +- .../test1/{thread.c => thread.cpp} | 0 .../GetCurrentThread/test2/CMakeLists.txt | 2 +- .../GetCurrentThread/test2/{test2.c => test2.cpp} | 0 .../GetCurrentThreadId/test1/CMakeLists.txt | 2 +- .../test1/{threadId.c => threadId.cpp} | 0 .../GetExitCodeProcess/test1/CMakeLists.txt | 4 +- .../test1/{childProcess.c => childProcess.cpp} | 0 .../test1/{test1.c => test1.cpp} | 0 .../threading/GetProcessTimes/test2/CMakeLists.txt | 2 +- .../threading/GetProcessTimes/test2/test2.c | 122 - .../threading/GetProcessTimes/test2/test2.cpp | 122 + .../threading/GetThreadTimes/test1/CMakeLists.txt | 2 +- .../threading/GetThreadTimes/test1/test1.c | 102 - .../threading/GetThreadTimes/test1/test1.cpp | 102 + .../threading/NamedMutex/test1/namedmutex.cpp | 12 +- .../threading/OpenEventW/test1/CMakeLists.txt | 2 +- .../OpenEventW/test1/{test1.c => test1.cpp} | 0 .../threading/OpenEventW/test2/CMakeLists.txt | 2 +- .../OpenEventW/test2/{test2.c => test2.cpp} | 0 .../threading/OpenEventW/test3/CMakeLists.txt | 4 +- .../test3/{childprocess.c => childprocess.cpp} | 0 .../palsuite/threading/OpenEventW/test3/test3.c | 187 - .../palsuite/threading/OpenEventW/test3/test3.cpp | 187 + .../threading/OpenEventW/test4/CMakeLists.txt | 2 +- .../OpenEventW/test4/{test4.c => test4.cpp} | 0 .../threading/OpenEventW/test5/CMakeLists.txt | 2 +- .../OpenEventW/test5/{test5.c => test5.cpp} | 0 .../threading/OpenProcess/test1/CMakeLists.txt | 4 +- .../test1/{childProcess.c => childProcess.cpp} | 0 .../OpenProcess/test1/{test1.c => test1.cpp} | 0 .../QueryThreadCycleTime/test1/CMakeLists.txt | 2 +- .../threading/QueryThreadCycleTime/test1/test1.c | 98 - .../threading/QueryThreadCycleTime/test1/test1.cpp | 98 + .../threading/QueueUserAPC/test1/CMakeLists.txt | 2 +- .../QueueUserAPC/test1/{test1.c => test1.cpp} | 0 .../threading/QueueUserAPC/test2/CMakeLists.txt | 2 +- .../QueueUserAPC/test2/{test2.c => test2.cpp} | 0 .../threading/QueueUserAPC/test3/CMakeLists.txt | 2 +- .../QueueUserAPC/test3/{test3.c => test3.cpp} | 0 .../threading/QueueUserAPC/test4/CMakeLists.txt | 2 +- .../QueueUserAPC/test4/{test4.c => test4.cpp} | 0 .../threading/QueueUserAPC/test5/CMakeLists.txt | 2 +- .../QueueUserAPC/test5/{test5.c => test5.cpp} | 0 .../threading/QueueUserAPC/test6/CMakeLists.txt | 2 +- .../QueueUserAPC/test6/{test6.c => test6.cpp} | 0 .../threading/QueueUserAPC/test7/CMakeLists.txt | 2 +- .../QueueUserAPC/test7/{test7.c => test7.cpp} | 0 .../threading/ReleaseMutex/test3/CMakeLists.txt | 2 +- .../test3/{ReleaseMutex.c => ReleaseMutex.cpp} | 0 .../threading/ResetEvent/test1/CMakeLists.txt | 2 +- .../ResetEvent/test1/{test1.c => test1.cpp} | 0 .../threading/ResetEvent/test2/CMakeLists.txt | 2 +- .../ResetEvent/test2/{test2.c => test2.cpp} | 0 .../threading/ResetEvent/test3/CMakeLists.txt | 2 +- .../ResetEvent/test3/{test3.c => test3.cpp} | 0 .../threading/ResetEvent/test4/CMakeLists.txt | 2 +- .../ResetEvent/test4/{test4.c => test4.cpp} | 0 .../threading/ResumeThread/test1/CMakeLists.txt | 2 +- .../palsuite/threading/ResumeThread/test1/test1.c | 141 - .../threading/ResumeThread/test1/test1.cpp | 141 + .../threading/SetErrorMode/test1/CMakeLists.txt | 2 +- .../SetErrorMode/test1/{test1.c => test1.cpp} | 0 .../threading/SetEvent/test1/CMakeLists.txt | 2 +- .../SetEvent/test1/{test1.c => test1.cpp} | 0 .../threading/SetEvent/test2/CMakeLists.txt | 2 +- .../SetEvent/test2/{test2.c => test2.cpp} | 0 .../threading/SetEvent/test3/CMakeLists.txt | 2 +- .../SetEvent/test3/{test3.c => test3.cpp} | 0 .../threading/SetEvent/test4/CMakeLists.txt | 2 +- .../SetEvent/test4/{test4.c => test4.cpp} | 0 .../palsuite/threading/Sleep/test1/CMakeLists.txt | 2 +- .../threading/Sleep/test1/{Sleep.c => Sleep.cpp} | 0 .../palsuite/threading/Sleep/test2/CMakeLists.txt | 2 +- .../threading/Sleep/test2/{sleep.c => sleep.cpp} | 0 .../threading/SleepEx/test1/CMakeLists.txt | 2 +- .../threading/SleepEx/test1/{test1.c => test1.cpp} | 0 .../threading/SleepEx/test2/CMakeLists.txt | 2 +- .../threading/SleepEx/test2/{test2.c => test2.cpp} | 0 .../threading/SwitchToThread/test1/CMakeLists.txt | 2 +- .../SwitchToThread/test1/{test1.c => test1.cpp} | 0 .../palsuite/threading/TLS/test1/CMakeLists.txt | 2 +- .../threading/TLS/test1/{TLS.c => TLS.cpp} | 0 .../palsuite/threading/TLS/test2/CMakeLists.txt | 2 +- .../threading/TLS/test2/{TLS.c => TLS.cpp} | 0 .../palsuite/threading/TLS/test3/CMakeLists.txt | 2 +- .../threading/TLS/test3/{TLS.c => TLS.cpp} | 0 .../palsuite/threading/TLS/test4/CMakeLists.txt | 2 +- .../threading/TLS/test4/{test4.c => test4.cpp} | 0 .../palsuite/threading/TLS/test5/CMakeLists.txt | 2 +- .../threading/TLS/test5/{test5.c => test5.cpp} | 0 .../TLS/test6_optimizedtls/CMakeLists.txt | 2 +- .../TLS/test6_optimizedtls/{test.c => test.cpp} | 0 .../TerminateProcess/test1/CMakeLists.txt | 2 +- .../{TerminateProcess.c => TerminateProcess.cpp} | 0 .../threading/ThreadPriority/test1/CMakeLists.txt | 2 +- .../test1/{ThreadPriority.c => ThreadPriority.cpp} | 0 .../WaitForMultipleObjects/test1/CMakeLists.txt | 2 +- .../test1/{test1.c => test1.cpp} | 0 .../WaitForMultipleObjectsEx/test1/CMakeLists.txt | 2 +- .../test1/{test1.c => test1.cpp} | 0 .../WaitForMultipleObjectsEx/test2/CMakeLists.txt | 2 +- .../test2/{test2.c => test2.cpp} | 0 .../WaitForMultipleObjectsEx/test3/CMakeLists.txt | 2 +- .../test3/{test3.c => test3.cpp} | 0 .../WaitForMultipleObjectsEx/test4/CMakeLists.txt | 2 +- .../test4/{test4.c => test4.cpp} | 0 .../WaitForMultipleObjectsEx/test5/CMakeLists.txt | 4 +- .../WaitForMultipleObjectsEx/test5/helper.c | 122 - .../WaitForMultipleObjectsEx/test5/helper.cpp | 122 + .../WaitForMultipleObjectsEx/test5/test5.c | 506 - .../WaitForMultipleObjectsEx/test5/test5.cpp | 506 + .../WaitForMultipleObjectsEx/test6/CMakeLists.txt | 4 +- .../WaitForMultipleObjectsEx/test6/child6.c | 211 - .../WaitForMultipleObjectsEx/test6/child6.cpp | 211 + .../WaitForMultipleObjectsEx/test6/test6.c | 709 - .../WaitForMultipleObjectsEx/test6/test6.cpp | 709 + .../WFSOExMutexTest/CMakeLists.txt | 2 +- .../{WFSOExMutexTest.c => WFSOExMutexTest.cpp} | 0 .../WFSOExSemaphoreTest/CMakeLists.txt | 2 +- ...SOExSemaphoreTest.c => WFSOExSemaphoreTest.cpp} | 0 .../WFSOExThreadTest/CMakeLists.txt | 2 +- .../{WFSOExThreadTest.c => WFSOExThreadTest.cpp} | 0 .../WFSOMutexTest/CMakeLists.txt | 2 +- .../WFSOMutexTest/WFSOMutexTest.c | 184 - .../WFSOMutexTest/WFSOMutexTest.cpp | 184 + .../WFSOProcessTest/CMakeLists.txt | 4 +- .../{ChildProcess.c => ChildProcess.cpp} | 0 .../{WFSOProcessTest.c => WFSOProcessTest.cpp} | 0 .../WFSOSemaphoreTest/CMakeLists.txt | 2 +- .../WFSOSemaphoreTest/WFSOSemaphoreTest.c | 183 - .../WFSOSemaphoreTest/WFSOSemaphoreTest.cpp | 183 + .../WFSOThreadTest/CMakeLists.txt | 2 +- .../WFSOThreadTest/WFSOThreadTest.c | 179 - .../WFSOThreadTest/WFSOThreadTest.cpp | 179 + .../WaitForSingleObject/test1/CMakeLists.txt | 2 +- .../test1/{test1.c => test1.cpp} | 0 .../threading/YieldProcessor/test1/CMakeLists.txt | 2 +- .../YieldProcessor/test1/{test1.c => test1.cpp} | 0 .../releasesemaphore/test1/CMakeLists.txt | 2 +- .../releasesemaphore/test1/{test.c => test.cpp} | 0 src/pal/tools/gen-buildsys-clang.sh | 19 +- src/pal/tools/gen-buildsys-win.bat | 2 +- src/palrt/path.cpp | 23 +- src/palrt/urlpars.cpp | 6 +- src/publish.proj | 13 +- src/strongname/api/common.h | 4 +- src/syncAzure.proj | 7 +- src/tools/crossgen/crossgen.cpp | 15 +- src/utilcode/CMakeLists.txt | 2 +- src/utilcode/clrhost_nodependencies.cpp | 4 +- src/utilcode/debug.cpp | 20 +- src/utilcode/fstring.cpp | 12 +- src/utilcode/longfilepathwrappers.cpp | 4 +- src/utilcode/makepath.cpp | 2 +- src/utilcode/md5.cpp | 2 +- src/utilcode/opinfo.cpp | 5 - src/utilcode/regutil.cpp | 3 +- src/utilcode/securitywrapper.cpp | 35 +- src/utilcode/splitpath.cpp | 4 +- src/utilcode/sstring.cpp | 4 +- src/utilcode/stacktrace.cpp | 4 +- src/utilcode/stresslog.cpp | 2 +- src/vm/CMakeLists.txt | 25 +- src/vm/amd64/CrtHelpers.asm | 734 +- src/vm/amd64/asmconstants.h | 4 +- src/vm/amd64/cgencpu.h | 6 +- src/vm/amd64/excepamd64.cpp | 2 +- src/vm/amd64/jitinterfaceamd64.cpp | 2 +- src/vm/amd64/umthunkstub.S | 2 +- src/vm/appdomain.cpp | 53 +- src/vm/appdomain.hpp | 14 +- src/vm/arm/asmconstants.h | 4 +- src/vm/arm/cgencpu.h | 6 +- src/vm/arm/stubs.cpp | 2 +- src/vm/assemblynative.cpp | 35 + src/vm/assemblynative.hpp | 1 + src/vm/assemblyspec.hpp | 14 + src/vm/callhelpers.cpp | 88 +- src/vm/callingconvention.h | 4 + src/vm/ceeload.cpp | 30 +- src/vm/ceeload.h | 22 +- src/vm/ceemain.cpp | 37 +- src/vm/cgensys.h | 11 +- src/vm/class.cpp | 4 + src/vm/class.h | 5 + src/vm/class.inl | 2 + src/vm/classcompat.cpp | 2 +- src/vm/classnames.h | 3 + src/vm/clrprivbinderwinrt.cpp | 11 +- src/vm/clsload.hpp | 2 +- src/vm/codeman.cpp | 158 +- src/vm/codeman.h | 46 +- src/vm/comdelegate.cpp | 128 +- src/vm/comdependenthandle.cpp | 21 + src/vm/comdependenthandle.h | 2 + src/vm/commemoryfailpoint.cpp | 2 +- src/vm/commethodrental.cpp | 4 +- src/vm/commodule.cpp | 3 +- src/vm/common.h | 2 +- src/vm/compile.cpp | 64 +- src/vm/compile.h | 2 +- src/vm/comsynchronizable.cpp | 6 +- src/vm/comthreadpool.cpp | 17 +- src/vm/comutilnative.cpp | 62 +- src/vm/constrainedexecutionregion.cpp | 5 - src/vm/constrainedexecutionregion.h | 3 + src/vm/corhost.cpp | 10 +- src/vm/crossgen/CMakeLists.txt | 7 +- .../crossgen_mscorlib/mscorlib_crossgen.nativeproj | 7 + src/vm/crossgencompile.cpp | 4 +- src/vm/crst.cpp | 4 +- src/vm/customattribute.cpp | 84 +- src/vm/dac/dacwks.targets | 1 + src/vm/dataimage.cpp | 2 + src/vm/debugdebugger.cpp | 42 +- src/vm/debughelp.cpp | 21 +- src/vm/dllimport.cpp | 22 +- src/vm/dllimportcallback.cpp | 26 +- src/vm/dllimportcallback.h | 16 +- src/vm/domainfile.cpp | 4 +- src/vm/dwreport.cpp | 2 +- src/vm/ecalllist.h | 113 +- src/vm/eedbginterfaceimpl.cpp | 4 +- src/vm/eepolicy.cpp | 2 +- src/vm/eetoprofinterfaceimpl.cpp | 164 +- src/vm/eetoprofinterfaceimpl.h | 15 +- src/vm/eetoprofinterfaceimpl.inl | 6 + src/vm/eetwain.cpp | 209 +- src/vm/encee.cpp | 15 +- src/vm/eventtrace.cpp | 37 +- src/vm/eventtracepriv.h | 5 +- src/vm/excep.cpp | 95 +- src/vm/excep.h | 7 +- src/vm/exceptionhandling.cpp | 2 +- src/vm/exceptmacros.h | 2 +- src/vm/exinfo.cpp | 8 + src/vm/exinfo.h | 2 + src/vm/finalizerthread.cpp | 28 +- src/vm/frames.cpp | 2 +- src/vm/frames.h | 8 +- src/vm/frameworkexceptionloader.cpp | 2 +- src/vm/gc.h | 5 - src/vm/gccover.cpp | 36 +- src/vm/gcenv.ee.cpp | 437 +- src/vm/gcenv.ee.h | 46 +- src/vm/gcenv.h | 2 - src/vm/gcenv.os.cpp | 67 +- src/vm/gcheaputilities.cpp | 19 + src/vm/gcheaputilities.h | 129 + src/vm/gchelpers.cpp | 89 +- src/vm/gchost.cpp | 12 +- src/vm/gcinfodecoder.cpp | 197 +- src/vm/gcinterface.h | 5 + src/vm/gcstress.h | 12 +- src/vm/gdbjit.cpp | 2124 +- src/vm/gdbjit.h | 386 +- src/vm/gdbjithelpers.h | 2 + src/vm/hash.cpp | 4 +- src/vm/i386/RedirectedHandledJITCase.asm | 2 +- src/vm/i386/asmconstants.h | 18 + src/vm/i386/asmhelpers.S | 1140 + src/vm/i386/asmhelpers.asm | 28 - src/vm/i386/cgencpu.h | 9 +- src/vm/i386/cgenx86.cpp | 79 +- src/vm/i386/excepcpu.h | 31 +- src/vm/i386/excepx86.cpp | 86 +- src/vm/i386/gmsasm.S | 28 + src/vm/i386/gmsx86.cpp | 136 +- src/vm/i386/jithelp.S | 749 + src/vm/i386/jithelp.asm | 30 + src/vm/i386/jitinterfacex86.cpp | 18 +- src/vm/i386/stublinkerx86.cpp | 27 +- src/vm/i386/stublinkerx86.h | 19 +- src/vm/i386/umthunkstub.S | 177 + src/vm/i386/unixstubs.cpp | 106 + src/vm/i386/virtualcallstubcpu.hpp | 2 +- src/vm/ilmarshalers.cpp | 2 +- src/vm/ilstubcache.cpp | 2 +- src/vm/ilstubresolver.cpp | 10 +- src/vm/ilstubresolver.h | 6 +- src/vm/interoputil.cpp | 2 +- src/vm/interpreter.cpp | 27 +- src/vm/interpreter.h | 2 +- src/vm/jithelpers.cpp | 32 +- src/vm/jitinterface.cpp | 456 +- src/vm/jitinterface.h | 24 +- src/vm/jitinterfacegen.cpp | 2 +- src/vm/marshalnative.cpp | 2 +- src/vm/marshalnative.h | 2 +- src/vm/mdaassistants.cpp | 4 +- src/vm/memberload.cpp | 2 +- src/vm/message.cpp | 2 +- src/vm/metasig.h | 3 + src/vm/method.cpp | 4 +- src/vm/method.hpp | 18 +- src/vm/methodtable.cpp | 8 +- src/vm/methodtablebuilder.cpp | 47 +- src/vm/methodtablebuilder.h | 1 + src/vm/microsoft.comservices_i.c | 16 +- src/vm/mlinfo.cpp | 4 +- src/vm/mscorlib.h | 36 +- src/vm/multicorejitplayer.cpp | 2 +- src/vm/nativeoverlapped.cpp | 24 +- src/vm/nativeoverlapped.h | 3 +- src/vm/object.cpp | 32 +- src/vm/object.h | 25 +- src/vm/prestub.cpp | 66 +- src/vm/profattach.cpp | 2 +- src/vm/profilinghelper.cpp | 2 +- src/vm/proftoeeinterfaceimpl.cpp | 368 +- src/vm/proftoeeinterfaceimpl.h | 24 +- src/vm/rcwwalker.cpp | 4 +- src/vm/readytoruninfo.cpp | 82 + src/vm/reflectioninvocation.cpp | 8 +- src/vm/reflectioninvocation.h | 6 +- src/vm/rejit.cpp | 11 +- src/vm/rexcep.h | 4 + src/vm/runtimecallablewrapper.cpp | 7 +- src/vm/safehandle.cpp | 4 +- src/vm/securityattributes.cpp | 7 +- src/vm/securitydeclarativecache.cpp | 9 +- src/vm/securityprincipal.h | 4 + src/vm/siginfo.cpp | 2 +- src/vm/stacksampler.cpp | 10 +- src/vm/stacksampler.h | 4 +- src/vm/stackwalk.cpp | 8 +- src/vm/stackwalk.h | 4 +- src/vm/stubcache.h | 2 +- src/vm/stubgen.cpp | 39 +- src/vm/stubgen.h | 2 +- src/vm/stubhelpers.cpp | 12 +- src/vm/syncblk.cpp | 16 +- src/vm/syncclean.cpp | 2 +- src/vm/testhookmgr.cpp | 2 +- src/vm/threadpoolrequest.cpp | 4 +- src/vm/threads.cpp | 133 +- src/vm/threads.h | 16 +- src/vm/threadsuspend.cpp | 70 +- src/vm/typeparse.cpp | 6 +- src/vm/typeparse.h | 7 +- src/vm/util.cpp | 40 +- src/vm/vars.cpp | 9 + src/vm/vars.hpp | 11 +- src/vm/virtualcallstub.cpp | 2 +- src/vm/vm.settings | 7 + src/vm/win32threadpool.cpp | 22 +- src/vm/win32threadpool.h | 8 +- src/vm/winrtredirector.h | 2 +- src/vm/wks/wks.targets | 1 + src/zap/zapcode.cpp | 2 +- src/zap/zapheaders.cpp | 136 +- src/zap/zapheaders.h | 34 +- src/zap/zapimage.cpp | 51 +- src/zap/zapimage.h | 2 +- src/zap/zapinfo.cpp | 71 +- src/zap/zapinfo.h | 2 +- src/zap/zapmetadata.cpp | 4 +- src/zap/zapper.cpp | 69 +- src/zap/zapreadytorun.cpp | 3 - sync.cmd | 5 +- tests/arm64/Tests.lst | 84 +- tests/build.proj | 1 + .../ConfigFilesGenerators/ConfigTemplate.txt | 32 + .../ConfigFilesGenerators/GenerateConfig.cmd | 53 + .../ConfigFilesGenerators/GenerateConfig.sh | 65 + tests/debugger_tests/ScriptGenerator/Program.cs | Bin 0 -> 8256 bytes tests/debugger_tests/ScriptGenerator/project.json | Bin 0 -> 1106 bytes tests/debugger_tests/setup-debuggertests.cmd | 119 + tests/debugger_tests/setup-debuggertests.sh | Bin 0 -> 6494 bytes tests/dir.props | 3 +- tests/helix.targets | 78 - tests/issues.targets | 65 +- tests/override.targets | 2 - tests/publishdependency.targets | 189 +- tests/runtest.cmd | 58 +- tests/runtest.proj | 50 +- tests/runtest.sh | 72 +- tests/scripts/arm32_ci_script.sh | 66 +- tests/scripts/arm64_post_build.py | 311 + tests/scripts/format.py | 46 +- tests/scripts/perf-prep.sh | 78 + tests/scripts/project.json | 23 +- tests/scripts/run-xunit-perf.cmd | 52 +- tests/scripts/run-xunit-perf.sh | 70 +- tests/setup-runtime-dependencies.cmd | 2 +- tests/setup-runtime-dependencies.sh | 4 + tests/src/CLRTest.Execute.Bash.targets | 11 +- tests/src/CLRTest.Execute.Batch.targets | 11 +- tests/src/CLRTest.Execute.targets | 1 + tests/src/CLRTest.Jit.targets | 86 + tests/src/Common/Platform/platformdefines.cpp | 4 +- tests/src/Common/Platform/platformdefines.h | 6 +- .../build_against_pkg_dependencies.csproj | 15 + .../build_against_pkg_dependencies/project.json | 32 + tests/src/Common/empty/project.json | 2 +- tests/src/Common/netcoreapp/project.json | 74 + tests/src/Common/targeting_pack_ref/project.json | 22 + .../targeting_pack_ref/targeting_pack_ref.csproj | 12 + tests/src/Common/test_dependencies/project.json | 136 +- .../test_dependencies/test_dependencies.csproj | 4 +- tests/src/Common/test_runtime/project.json | 5 +- tests/src/Common/test_runtime/test_runtime.csproj | 4 +- .../cti/system/datetime/datetimeparse1.cs | 8 +- tests/src/CoreMangLib/system/span/BasicSpanTest.cs | 804 + tests/src/GC/API/GC/GetGenerationWR2.csproj | 1 + tests/src/GC/API/GCHandleCollector/Usage.cs | 3 +- .../src/GC/Features/HeapExpansion/pluggaps.csproj | 1 + .../Framework/GCPerfTestFramework.csproj | 31 +- tests/src/GC/Performance/Framework/packages.config | 24 +- .../GC/Regressions/v2.0-rtm/494226/494226.csproj | 3 +- tests/src/GC/Scenarios/DoublinkList/dlcollect.cs | 6 + tests/src/GC/Scenarios/DoublinkList/dlstack.cs | 6 + tests/src/GC/Scenarios/DoublinkList/doublinkgen.cs | 6 + .../Scenarios/FinalizeTimeout/FinalizeTimeout.cs | 7 +- .../GC/Scenarios/ServerModel/servermodel.csproj | 1 + .../Stress/Framework/ReliabilityFramework.csproj | 2 +- tests/src/GC/Stress/Tests/dir.targets | 6 + .../ByValArray/MarshalArrayByValNative.cpp | 130 +- .../PrimitiveMarshalling/Bool/BoolNative.cpp | 2 + .../Interop/RefCharArray/RefCharArrayNative.cpp | 2 +- .../Interop/SimpleStruct/SimpleStructNative.cpp | 4 +- .../StringMarshalling/UTF8/UTF8TestNative.cpp | 4 +- .../PInvoke/MarshalStructAsParamDLL.cpp | 53 +- .../PInvoke/MarshalStructAsParamDLL.h | 173 +- tests/src/Interop/common/types.h | 4 +- tests/src/JIT/CodeGenBringUpTests/Rotate.cs | 96 +- tests/src/JIT/CodeGenBringUpTests/Shift.cs | 86 + tests/src/JIT/CodeGenBringUpTests/Shift.csproj | 40 + tests/src/JIT/Directed/pinvoke/pinvoke-examples.cs | 223 + .../JIT/Directed/pinvoke/pinvoke-examples.csproj | 44 + .../src/JIT/Methodical/fp/exgen/10w5d_cs_d.csproj | 5 +- .../src/JIT/Methodical/fp/exgen/10w5d_cs_r.csproj | 5 +- .../structs/systemvbringup/structpinvoketests.cs | 1096 +- tests/src/JIT/Methodical/structs/valuetuple.cs | 95 + tests/src/JIT/Methodical/structs/valuetuple.csproj | 41 + .../Performance/CodeQuality/BenchF/Adams/Adams.cs | 9 +- .../CodeQuality/BenchF/BenchMk2/BenchMk2.cs | 3 + .../CodeQuality/BenchF/BenchMrk/BenchMrk.cs | 3 + .../CodeQuality/BenchF/Bisect/Bisect.cs | 3 + .../Performance/CodeQuality/BenchF/DMath/DMath.cs | 3 + .../JIT/Performance/CodeQuality/BenchF/FFT/FFT.cs | 3 + .../CodeQuality/BenchF/InProd/InProd.cs | 3 + .../Performance/CodeQuality/BenchF/InvMt/InvMt.cs | 3 + .../CodeQuality/BenchF/LLoops/LLoops.cs | 3 + .../CodeQuality/BenchF/Lorenz/Lorenz.cs | 3 + .../CodeQuality/BenchF/MatInv4/MatInv4.cs | 17 +- .../Performance/CodeQuality/BenchF/NewtE/NewtE.cs | 3 + .../Performance/CodeQuality/BenchF/NewtR/NewtR.cs | 3 + .../CodeQuality/BenchF/Regula/Regula.cs | 3 + .../CodeQuality/BenchF/Romber/Romber.cs | 3 + .../CodeQuality/BenchF/Secant/Secant.cs | 3 + .../CodeQuality/BenchF/Simpsn/Simpsn.cs | 3 + .../Performance/CodeQuality/BenchF/SqMtx/SqMtx.cs | 3 + .../Performance/CodeQuality/BenchF/Trap/Trap.cs | 3 + .../CodeQuality/BenchF/Whetsto/Whetsto.cs | 3 + .../CodeQuality/BenchI/8Queens/8Queens.cs | 7 +- .../CodeQuality/BenchI/Ackermann/Ackermann.cs | 7 +- .../CodeQuality/BenchI/AddArray/AddArray.cs | 9 +- .../CodeQuality/BenchI/AddArray2/AddArray2.cs | 3 + .../CodeQuality/BenchI/Array1/Array1.cs | 3 + .../CodeQuality/BenchI/Array2/Array2.cs | 7 +- .../CodeQuality/BenchI/BenchE/BenchE.cs | 3 + .../CodeQuality/BenchI/BubbleSort/BubbleSort.cs | 7 +- .../CodeQuality/BenchI/BubbleSort2/BubbleSort2.cs | 5 +- .../CodeQuality/BenchI/CSieve/CSieve.cs | 5 +- .../JIT/Performance/CodeQuality/BenchI/Fib/Fib.cs | 7 +- .../CodeQuality/BenchI/HeapSort/HeapSort.cs | 7 +- .../CodeQuality/BenchI/IniArray/IniArray.cs | 5 +- .../CodeQuality/BenchI/LogicArray/LogicArray.cs | 5 +- .../CodeQuality/BenchI/Midpoint/Midpoint.cs | 5 +- .../CodeQuality/BenchI/MulMatrix/MulMatrix.cs | 7 +- .../CodeQuality/BenchI/NDhrystone/NDhrystone.cs | 45 +- .../CodeQuality/BenchI/Permutate/Permutate.cs | 3 + .../JIT/Performance/CodeQuality/BenchI/Pi/Pi.cs | 5 +- .../CodeQuality/BenchI/Puzzle/Puzzle.cs | 3 + .../CodeQuality/BenchI/QuickSort/QuickSort.cs | 7 +- .../CodeQuality/BenchI/TreeInsert/TreeInsert.cs | 3 + .../CodeQuality/BenchI/TreeSort/TreeSort.cs | 9 +- .../CodeQuality/BenchI/XposMatrix/XposMatrix.cs | 7 +- .../binarytrees/binarytrees.csharp.cs | 7 +- .../BenchmarksGame/fasta/fasta.csharp-2.cs | 3 + .../BenchmarksGame/fastaredux/fastaredux.csharp.cs | 3 + .../BenchmarksGame/nbody/nbody.csharp-3.cs | 3 + .../BenchmarksGame/pidigits/pi-digits.cs | 5 +- .../BenchmarksGame/spectralnorm/spectralnorm.cs | 9 +- .../CodeQuality/Inlining/ConstantArgsByte.cs | 3 + .../CodeQuality/Inlining/ConstantArgsChar.cs | 3 + .../CodeQuality/Inlining/ConstantArgsDouble.cs | 3 + .../CodeQuality/Inlining/ConstantArgsFloat.cs | 3 + .../CodeQuality/Inlining/ConstantArgsInt.cs | 3 + .../CodeQuality/Inlining/ConstantArgsLong.cs | 3 + .../CodeQuality/Inlining/ConstantArgsSByte.cs | 3 + .../CodeQuality/Inlining/ConstantArgsShort.cs | 3 + .../CodeQuality/Inlining/ConstantArgsString.cs | 3 + .../CodeQuality/Inlining/ConstantArgsUInt.cs | 3 + .../CodeQuality/Inlining/ConstantArgsULong.cs | 3 + .../CodeQuality/Inlining/ConstantArgsUShort.cs | 3 + .../CodeQuality/Inlining/InlineGCStruct.cs | 148 + .../CodeQuality/Inlining/InlineGCStruct.csproj | 44 + .../CodeQuality/Inlining/NoThrowInline.cs | 5 +- .../SIMD/ConsoleMandel/ConsoleMandel.cs | 4 +- .../CodeQuality/SIMD/RayTracer/RayTracerBench.cs | 7 +- .../CodeQuality/SIMD/SeekUnroll/SeekUnroll.cs | 159 + .../CodeQuality/SIMD/SeekUnroll/SeekUnroll.csproj | 43 + .../CodeQuality/Serialization/Deserialize.cs | 7 +- .../CodeQuality/Serialization/Serialize.cs | 5 +- .../Performance/CodeQuality/V8/Crypto/Crypto.cs | 2 +- .../CodeQuality/V8/DeltaBlue/DeltaBlue.cs | 5 +- .../CodeQuality/V8/Richards/Richards.cs | 18 +- .../Performance/RunBenchmarks/RunBenchmarks.cmd | 2 +- .../JIT/Performance/RunBenchmarks/RunBenchmarks.sh | 53 + .../CLR-x86-JIT/V2.0-RTM/b475589/b475589.il | 71 - .../CLR-x86-JIT/V2.0-RTM/b475589/b475589.ilproj | 40 - .../JitBlue/DevDiv_142976/DevDiv_142976.cs | 56 + .../JitBlue/DevDiv_142976/DevDiv_142976.csproj | 46 + .../JitBlue/DevDiv_255294/DevDiv_255294.cs | 62374 +++++++++++++++++++ .../JitBlue/DevDiv_255294/DevDiv_255294.csproj | 46 + .../JitBlue/DevDiv_278365/DevDiv_278365.cs | 49 + .../JitBlue/DevDiv_278365/DevDiv_278365.csproj | 46 + .../JitBlue/DevDiv_278369/DevDiv_278369.il | 58 + .../JitBlue/DevDiv_278369/DevDiv_278369.ilproj | 41 + .../JitBlue/DevDiv_278371/DevDiv_278371.il | 88 + .../JitBlue/DevDiv_278371/DevDiv_278371.ilproj | 41 + .../JitBlue/DevDiv_278372/DevDiv_278372.il | 156 + .../JitBlue/DevDiv_278372/DevDiv_278372.ilproj | 51 + .../JitBlue/DevDiv_278375/DevDiv_278375.cs | 131 + .../JitBlue/DevDiv_278375/DevDiv_278375.csproj | 46 + .../JitBlue/DevDiv_278376/DevDiv_278376.cs | 36 + .../JitBlue/DevDiv_278376/DevDiv_278376.csproj | 46 + .../JitBlue/DevDiv_278523/DevDiv_278523.il | 113 + .../JitBlue/DevDiv_278523/DevDiv_278523.ilproj | 41 + .../JitBlue/DevDiv_278526/DevDiv_278526.cs | 47 + .../JitBlue/DevDiv_278526/DevDiv_278526.csproj | 46 + .../JitBlue/DevDiv_279396/DevDiv_279396.il | 39 + .../JitBlue/DevDiv_279396/DevDiv_279396.ilproj | 41 + .../JitBlue/DevDiv_279829/DevDiv_279829.il | 36 + .../JitBlue/DevDiv_279829/DevDiv_279829.ilproj | 46 + .../JitBlue/DevDiv_280120/DevDiv_280120.cs | 22 + .../JitBlue/DevDiv_280120/DevDiv_280120.csproj | 56 + .../JitBlue/DevDiv_280123/DevDiv_280123.cs | 42 + .../JitBlue/DevDiv_280123/DevDiv_280123.csproj | 46 + .../JitBlue/DevDiv_280127/DevDiv_280127.cs | 37 + .../JitBlue/DevDiv_280127/DevDiv_280127.csproj | 46 + .../JitBlue/DevDiv_283795/DevDiv_283795.cs | 55 + .../JitBlue/DevDiv_283795/DevDiv_283795.csproj | 46 + .../JitBlue/DevDiv_284785/DevDiv_284785.cs | 39 + .../JitBlue/DevDiv_284785/DevDiv_284785.csproj | 46 + .../JitBlue/DevDiv_288222/DevDiv_288222.cs | 50 + .../JitBlue/DevDiv_288222/DevDiv_288222.csproj | 46 + .../JitBlue/DevDiv_359734/DevDiv_359734.il | 118 + .../JitBlue/DevDiv_359734/DevDiv_359734.ilproj | 41 + .../JitBlue/DevDiv_359736/DevDiv_359736.cs | 42 + .../JitBlue/DevDiv_359736/DevDiv_359736_d.csproj | 45 + .../JitBlue/DevDiv_359736/DevDiv_359736_do.csproj | 45 + .../JitBlue/DevDiv_359736/DevDiv_359736_r.csproj | 45 + .../JitBlue/DevDiv_359736/DevDiv_359736_ro.csproj | 45 + .../Regression/JitBlue/GitHub_7906/GitHub_7906.cs | 47 + .../JitBlue/GitHub_7906/GitHub_7906.csproj | 44 + .../Regression/JitBlue/GitHub_7907/GitHub_7907.cs | 53 + .../JitBlue/GitHub_7907/GitHub_7907.csproj | 46 + .../Regression/JitBlue/GitHub_8133/GitHub_8133.il | 112 + .../JitBlue/GitHub_8133/GitHub_8133.ilproj | 41 + .../Regression/JitBlue/GitHub_8170/GitHub_8170.cs | 23 + .../JitBlue/GitHub_8170/GitHub_8170.csproj | 46 + .../Regression/JitBlue/GitHub_8220/GitHub_8220.cs | 170 + .../JitBlue/GitHub_8220/GitHub_8220.csproj | 45 + .../Regression/JitBlue/GitHub_8231/GitHub_8231.cs | 62 + .../JitBlue/GitHub_8231/GitHub_8231.csproj | 39 + .../Regression/JitBlue/GitHub_8460/GitHub_8460.cs | 38 + .../JitBlue/GitHub_8460/GitHub_8460.csproj | 46 + .../Regression/JitBlue/GitHub_8599/GitHub_8599.cs | 42 + .../JitBlue/GitHub_8599/GitHub_8599.csproj | 46 + .../GitHub_CoreRT_2073/GitHub_CoreRT_2073.il | 55 + .../GitHub_CoreRT_2073/GitHub_CoreRT_2073.ilproj | 38 + .../VS-ia64-JIT/V2.0-Beta2/b311420/b311420.csproj | 5 +- tests/src/JIT/SIMD/Vector3Interop.cs | 6 +- tests/src/JIT/SIMD/VectorDot.cs | 7 +- tests/src/JIT/SIMD/VectorIntEquals.cs | 61 +- tests/src/JIT/SIMD/VectorUtil.cs | 2 +- tests/src/JIT/config/benchmark+roslyn/project.json | 46 +- .../JIT/config/benchmark+serialize/project.json | 43 +- tests/src/JIT/config/benchmark/project.json | 51 +- tests/src/JIT/config/extra/project.json | 34 +- tests/src/JIT/config/minimal/project.json | 12 +- tests/src/JIT/config/threading+thread/project.json | 16 +- tests/src/JIT/config/threading/project.json | 12 +- tests/src/JIT/jit64/opt/cse/HugeArray.csproj | 5 +- tests/src/JIT/jit64/verif/sniff/fg/ver_fg_13.il | 7 +- .../opt/Inline/regression/mismatch32/mismatch32.il | 6 +- .../opt/Inline/regression/mismatch64/mismatch64.il | 6 +- .../JIT/opt/Tailcall/TailcallVerifyWithPrefix.il | 30 + .../bigvtbl/bigvtbl_cs_d.csproj | 3 + .../bigvtbl/bigvtbl_cs_r.csproj | 3 + .../InterfaceFolding/Nested_I/TestCase0.il | 21 +- .../InterfaceFolding/Nested_I/TestCase1.il | 20 +- .../InterfaceFolding/Nested_I/TestCase2.il | 20 +- .../InterfaceFolding/Nested_I/TestCase3.il | 20 +- .../InterfaceFolding/Nested_I/TestCase4.il | 22 +- .../InterfaceFolding/Nested_I/TestCase5.il | 20 +- .../InterfaceFolding/Nested_I/TestCase6.il | 20 +- .../Nested_I_Nested_J/TestCase0.il | 21 +- .../Nested_I_Nested_J/TestCase1.il | 20 +- .../Nested_I_Nested_J/TestCase2.il | 20 +- .../Nested_I_Nested_J/TestCase3.il | 20 +- .../Nested_I_Nested_J/TestCase4.il | 20 +- .../Nested_I_Nested_J/TestCase5.il | 19 +- .../Nested_I_Nested_J/TestCase6.il | 18 +- .../InterfaceFolding/Nested_J/TestCase0.il | 21 +- .../InterfaceFolding/Nested_J/TestCase1.il | 20 +- .../InterfaceFolding/Nested_J/TestCase2.il | 20 +- .../InterfaceFolding/Nested_J/TestCase3.il | 20 +- .../InterfaceFolding/Nested_J/TestCase4.il | 20 +- .../InterfaceFolding/Nested_J/TestCase5.il | 20 +- .../InterfaceFolding/Nested_J/TestCase6.il | 20 +- .../Nested_J_Nested_I/TestCase0.il | 21 +- .../Nested_J_Nested_I/TestCase1.il | 20 +- .../Nested_J_Nested_I/TestCase2.il | 20 +- .../Nested_J_Nested_I/TestCase3.il | 20 +- .../Nested_J_Nested_I/TestCase4.il | 20 +- .../Nested_J_Nested_I/TestCase5.il | 20 +- .../Nested_J_Nested_I/TestCase6.il | 20 +- .../classloader/InterfaceFolding/TestCase0.il | 15 +- .../classloader/InterfaceFolding/TestCase1.il | 18 +- .../classloader/InterfaceFolding/TestCase2.il | 18 +- .../classloader/InterfaceFolding/TestCase3.il | 18 +- .../classloader/InterfaceFolding/TestCase4.il | 18 +- .../classloader/InterfaceFolding/TestCase5.il | 18 +- .../classloader/InterfaceFolding/TestCase6.il | 18 +- .../classloader/InterfaceFolding/TestCase7.il | 19 +- .../Test2_NonFriendPriInterface.csproj | 35 - .../classloader/generics/Visibility/A_Types.csproj | 35 - .../classloader/generics/Visibility/B_Types.csproj | 35 - .../regressions/549411/exploit.csproj | 1 + .../regressions/dev10_710121/dev10_710121.il | 15 +- tests/src/TestWrappersConfig/project.json | 13 +- .../FixedAddressValueType/FixedAddressValueType.cs | 60 + .../FixedAddressValueType.csproj | 44 + .../ExecuteCodeWithGuaranteedCleanup.cs | 62 + .../ExecuteCodeWithGuaranteedCleanup.csproj | 42 + .../RuntimeWrappedException.cs | 63 + .../RuntimeWrappedException.csproj | 45 + .../RuntimeWrappedException/StringThrower.il | 40 + .../RuntimeWrappedException/StringThrower.ilproj | 40 + .../compilerservices/modulector/moduleCctor.il | 110 + .../compilerservices/modulector/moduleCctor.ilproj | 40 + .../modulector/runmoduleconstructor.cs | 38 + .../modulector/runmoduleconstructor.csproj | 45 + tests/src/dir.common.props | 7 +- tests/src/dir.props | 13 +- tests/src/dir.targets | 28 +- tests/src/jit/Directed/pinvoke/pinvoke-bug.cs | 60 + tests/src/jit/Directed/pinvoke/pinvoke-bug.csproj | 44 + tests/src/performance/perflab/BlockCopyPerf.cs | 29 +- tests/src/performance/perflab/CastingPerf.cs | 644 +- tests/src/performance/perflab/CastingPerf2.cs | 34 +- tests/src/performance/perflab/DelegatePerf.cs | 144 +- tests/src/performance/perflab/EnumPerf.cs | 109 +- tests/src/performance/perflab/LowLevelPerf.cs | 1283 +- tests/src/performance/perflab/ReflectionPerf.cs | 6317 +- tests/src/performance/perflab/StackWalk.cs | 129 +- tests/src/performance/perflab/ThreadingPerf.cs | 111 +- tests/src/performance/project.json | 54 +- tests/src/readytorun/generics.cs | 92 +- tests/src/readytorun/main.cs | 14 +- tests/src/reflection/ldtoken/byrefs.il | 88 + tests/src/reflection/ldtoken/byrefs.ilproj | 35 + tests/tests.targets | 4 +- tests/testsFailingOutsideWindows.txt | 3 +- tests/testsUnsupportedOnARM32.txt | 9 +- tests/testsUnsupportedOutsideWindows.txt | 1 + tests/x86/compatjit_x86_testenv.cmd | 8 + tests/x86/legacyjit_x86_testenv.cmd | 52 + tests/x86/ryujit_x86_testenv.cmd | 58 +- tests/x86_jit32_issues.targets | 8 +- tests/x86_legacy_backend_issues.targets | 23 +- tests/xunitwrapper.targets | 2 +- verify-so.sh | 20 + 4534 files changed, 192341 insertions(+), 125517 deletions(-) delete mode 100644 .gitignore delete mode 100644 .gitmirror create mode 100644 .gitmirrorselective rename Documentation/botr/{_tableOfContents.md => README.md} (100%) create mode 100644 Documentation/design-docs/multi-reg-call-nodes.md create mode 100644 Documentation/workflow/EditingAndDebugging.md create mode 100644 Documentation/workflow/IssuesFeedbackEngagement.md create mode 100644 Documentation/workflow/OfficalAndDailyBuilds.md create mode 100644 Documentation/workflow/RunningTests.md create mode 100644 Documentation/workflow/UsingCoreRun.md create mode 100644 Documentation/workflow/UsingYourBuild.md create mode 100755 binclash.log create mode 100644 cross/arm/sources.list.jessie create mode 100644 cross/arm/sources.list.xenial create mode 100644 cross/arm64/sources.list.xenial create mode 100644 cross/x86/sources.list.trusty create mode 100644 cross/x86/sources.list.vivid create mode 100644 cross/x86/sources.list.wily create mode 100644 cross/x86/sources.list.xenial create mode 100644 cross/x86/toolchain.cmake create mode 100644 cross/x86/tryrun.cmake delete mode 100755 extract-from-json.py create mode 100644 init-tools.log create mode 100644 src/.gitmirrorselective create mode 100644 src/.nuget/Microsoft.NETCore.ILAsm/alpine/3.4.3/Microsoft.NETCore.ILAsm.pkgproj create mode 100644 src/.nuget/Microsoft.NETCore.ILAsm/linux/Microsoft.NETCore.ILAsm.pkgproj create mode 100644 src/.nuget/Microsoft.NETCore.ILDAsm/alpine/3.4.3/Microsoft.NETCore.ILDAsm.pkgproj create mode 100644 src/.nuget/Microsoft.NETCore.ILDAsm/linux/Microsoft.NETCore.ILDAsm.pkgproj create mode 100644 src/.nuget/Microsoft.NETCore.Jit/alpine/3.4.3/Microsoft.NETCore.Jit.pkgproj create mode 100644 src/.nuget/Microsoft.NETCore.Jit/linux/Microsoft.NETCore.Jit.pkgproj create mode 100644 src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/alpine/3.4.3/Microsoft.NETCore.Runtime.CoreCLR.pkgproj create mode 100644 src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/linux/Microsoft.NETCore.Runtime.CoreCLR.pkgproj create mode 100644 src/.nuget/Microsoft.NETCore.TestHost/alpine/3.4.3/Microsoft.NETCore.TestHost.pkgproj create mode 100644 src/.nuget/Microsoft.NETCore.TestHost/linux/Microsoft.NETCore.TestHost.pkgproj delete mode 100644 src/.nuget/optdata/project.json create mode 100644 src/ToolBox/.gitmirrorselective delete mode 100644 src/ToolBox/SOS/tests/OnCrash.do create mode 100644 src/ToolBox/SOS/tests/Test.cs delete mode 100644 src/ToolBox/SOS/tests/dumpil.py delete mode 100644 src/ToolBox/SOS/tests/dumpmodule.py delete mode 100644 src/ToolBox/SOS/tests/runprocess.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_bpmd_clear.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_bpmd_clearall.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_bpmd_methoddesc.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_bpmd_module_function.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_bpmd_module_function_iloffset.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_bpmd_nofuturemodule_module_function.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_clrstack.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_clrthreads.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_clru.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_dso.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_dumpclass.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_dumpheap.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_dumpil.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_dumplog.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_dumpmd.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_dumpmodule.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_dumpmt.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_dumpobj.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_dumpstack.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_eeheap.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_eestack.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_gcroot.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_histclear.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_histinit.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_histobj.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_histobjfind.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_histroot.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_ip2md.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_name2ee.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_pe.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_sos.py create mode 100644 src/ToolBox/SOS/tests/t_cmd_soshelp.py create mode 100644 src/corefx/System.Globalization.Native/icushim.cpp create mode 100644 src/corefx/System.Globalization.Native/icushim.h create mode 100644 src/debug/ee/i386/dbghelpers.S create mode 100644 src/gc/gcenv.ee.standalone.inl create mode 100644 src/gc/gcenv.unix.cpp create mode 100644 src/gc/gcenv.windows.cpp create mode 100644 src/gc/gcinterface.ee.h create mode 100644 src/gc/gcinterface.h delete mode 100644 src/gc/sample/gcenv.unix.cpp delete mode 100644 src/gc/sample/gcenv.windows.cpp delete mode 100644 src/ilasm/prebuilt/asmparse.c create mode 100644 src/ilasm/prebuilt/asmparse.cpp rename src/inc/{xmlparser_i.c => xmlparser_i.cpp} (100%) create mode 100644 src/jit/ICorJitInfo_API_names.h create mode 100644 src/jit/ICorJitInfo_API_wrapper.hpp mode change 100755 => 100644 src/jit/codegencommon.cpp create mode 100644 src/jit/codegenlinear.cpp rename src/{ToolBox => jit/compatjit}/.gitmirror (100%) create mode 100644 src/jit/compatjit/CMakeLists.txt mode change 100755 => 100644 src/jit/ee_il_dll.cpp create mode 100644 src/jit/jitee.h rename src/{ => jit/legacyjit}/.gitmirror (100%) create mode 100644 src/jit/legacyjit/CMakeLists.txt create mode 100644 src/mscorlib/corefx/Debug.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/Interop.Errors.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/Interop.IOErrors.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Idna.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Normalization.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Close.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/System.Native/Interop.FLock.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/System.Native/Interop.FSync.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/System.Native/Interop.FTruncate.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Fcntl.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/System.Native/Interop.GetCwd.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/System.Native/Interop.GetUnixName.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/System.Native/Interop.LSeek.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/System.Native/Interop.MksTemps.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Open.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/System.Native/Interop.OpenFlags.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/System.Native/Interop.PathConf.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Permissions.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/System.Native/Interop.PosixFAdvise.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Read.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Stat.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Unlink.cs create mode 100644 src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Write.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/BCrypt/Interop.BCryptGenRandom.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/BCrypt/Interop.NTSTATUS.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/Crypt32/Interop.CryptProtectMemory.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/Interop.BOOL.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/Interop.Libraries.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/NtDll/Interop.ZeroMemory.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.CancelIoEx.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.CloseHandle.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.CreateFile.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.Errors.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.FileOperations.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.FileTypes.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.FlushFileBuffers.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.FormatMessage.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetFileInformationByHandleEx.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetFileType_SafeHandle.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetFullPathNameW.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetLongPathNameW.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetTempFileNameW.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetTempPathW.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.Idna.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.LockFile.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.ReadFile_SafeHandle_IntPtr.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.ReadFile_SafeHandle_NativeOverlapped.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.SECURITY_ATTRIBUTES.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.SafeCreateFile.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.SecurityOptions.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.SetEndOfFile.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.SetErrorMode.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.SetFileInformationByHandle.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.SetFilePointerEx.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.ThreadPoolIO.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.UnsafeCreateFile.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.WideCharToMultiByte.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.WriteFile_SafeHandle_IntPtr.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/mincore/Interop.WriteFile_SafeHandle_NativeOverlapped.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/oleaut32/Interop.SysAllocStringLen.cs create mode 100644 src/mscorlib/corefx/Interop/Windows/oleaut32/Interop.SysStringLen.cs create mode 100644 src/mscorlib/corefx/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs create mode 100644 src/mscorlib/corefx/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs create mode 100644 src/mscorlib/corefx/Microsoft/Win32/SafeHandles/SafeThreadPoolIOHandle.cs create mode 100644 src/mscorlib/corefx/System/Buffers/ArrayPool.cs create mode 100644 src/mscorlib/corefx/System/Buffers/ArrayPoolEventSource.cs create mode 100644 src/mscorlib/corefx/System/Buffers/ConfigurableArrayPool.cs create mode 100644 src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.Unix.cs create mode 100644 src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.Windows.cs create mode 100644 src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs create mode 100644 src/mscorlib/corefx/System/Buffers/Utilities.cs create mode 100644 src/mscorlib/corefx/System/Globalization/CalendarAlgorithmType.cs create mode 100644 src/mscorlib/corefx/System/Globalization/CultureTypes.cs create mode 100644 src/mscorlib/corefx/System/Globalization/DigitShapes.cs create mode 100644 src/mscorlib/corefx/System/Globalization/HijriCalendar.Win32.cs create mode 100644 src/mscorlib/corefx/System/Globalization/HijriCalendar.WinRT.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/HijriCalendar.Windows.cs create mode 100644 src/mscorlib/corefx/System/Globalization/IdnMapping.Unix.cs create mode 100644 src/mscorlib/corefx/System/Globalization/IdnMapping.Windows.cs create mode 100644 src/mscorlib/corefx/System/Globalization/IdnMapping.cs create mode 100644 src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Win32.cs rename src/mscorlib/corefx/System/Globalization/{JapaneseCalendar.Windows.cs => JapaneseCalendar.WinRT.cs} (100%) create mode 100644 src/mscorlib/corefx/System/Globalization/LocaleData.Unix.cs delete mode 100644 src/mscorlib/corefx/System/Globalization/STUBS.cs create mode 100644 src/mscorlib/corefx/System/Globalization/SortKey.cs create mode 100644 src/mscorlib/corefx/System/Globalization/SortVersion.cs create mode 100644 src/mscorlib/corefx/System/HResults.cs create mode 100644 src/mscorlib/corefx/System/IO/Error.cs create mode 100644 src/mscorlib/corefx/System/IO/FileStream.NetStandard17.cs create mode 100644 src/mscorlib/corefx/System/IO/FileStream.Unix.cs create mode 100644 src/mscorlib/corefx/System/IO/FileStream.Win32.cs create mode 100644 src/mscorlib/corefx/System/IO/FileStream.cs create mode 100644 src/mscorlib/corefx/System/IO/FileStreamCompletionSource.Win32.cs create mode 100644 src/mscorlib/corefx/System/IO/Path.Unix.cs create mode 100644 src/mscorlib/corefx/System/IO/Path.Win32.cs create mode 100644 src/mscorlib/corefx/System/IO/Path.Windows.cs create mode 100644 src/mscorlib/corefx/System/IO/Path.cs create mode 100644 src/mscorlib/corefx/System/IO/PathHelper.Windows.cs create mode 100644 src/mscorlib/corefx/System/IO/PathInternal.CaseSensitivity.cs create mode 100644 src/mscorlib/corefx/System/IO/PathInternal.Unix.cs create mode 100644 src/mscorlib/corefx/System/IO/PathInternal.Windows.StringBuffer.cs create mode 100644 src/mscorlib/corefx/System/IO/PathInternal.Windows.cs create mode 100644 src/mscorlib/corefx/System/IO/PathInternal.cs create mode 100644 src/mscorlib/corefx/System/IO/Win32Marshal.cs create mode 100644 src/mscorlib/corefx/System/Runtime/InteropServices/NativeBuffer.cs create mode 100644 src/mscorlib/corefx/System/Runtime/InteropServices/SafeHeapHandle.cs create mode 100644 src/mscorlib/corefx/System/Runtime/InteropServices/SafeHeapHandleCache.cs create mode 100644 src/mscorlib/corefx/System/Runtime/InteropServices/StringBuffer.cs create mode 100644 src/mscorlib/corefx/System/Security/CryptographicException.cs create mode 100644 src/mscorlib/corefx/System/Security/SafeBSTRHandle.cs create mode 100644 src/mscorlib/corefx/System/Security/SecureString.Unix.cs create mode 100644 src/mscorlib/corefx/System/Security/SecureString.Windows.cs create mode 100644 src/mscorlib/corefx/System/Security/SecureString.cs create mode 100644 src/mscorlib/corefx/System/Threading/ClrThreadPoolBoundHandle.cs create mode 100644 src/mscorlib/corefx/System/Threading/ClrThreadPoolBoundHandleOverlapped.cs create mode 100644 src/mscorlib/corefx/System/Threading/ClrThreadPoolPreAllocatedOverlapped.cs create mode 100644 src/mscorlib/corefx/System/Threading/DeferredDisposableLifetime.cs delete mode 100644 src/mscorlib/facade/TypeForwards.cs create mode 100644 src/mscorlib/src/Internal/Runtime/Augments/RuntimeThread.cs delete mode 100644 src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.cs create mode 100644 src/mscorlib/src/System/ByReference.cs delete mode 100644 src/mscorlib/src/System/Collections/BitArray.cs delete mode 100644 src/mscorlib/src/System/ContextBoundObject.cs delete mode 100644 src/mscorlib/src/System/ContextStaticAttribute.cs delete mode 100644 src/mscorlib/src/System/IO/BufferedStream.cs delete mode 100644 src/mscorlib/src/System/IO/DriveInfo.cs create mode 100644 src/mscorlib/src/System/IO/EncodingCache.cs delete mode 100644 src/mscorlib/src/System/IO/FileSecurityState.cs delete mode 100644 src/mscorlib/src/System/IO/FileSecurityStateAccess.cs delete mode 100644 src/mscorlib/src/System/IO/FileStream.cs delete mode 100644 src/mscorlib/src/System/IO/LongPathHelper.cs delete mode 100644 src/mscorlib/src/System/IO/Path.cs delete mode 100644 src/mscorlib/src/System/IO/PathHelper.cs delete mode 100644 src/mscorlib/src/System/IO/PathInternal.cs create mode 100644 src/mscorlib/src/System/IO/StreamHelpers.CopyValidation.cs delete mode 100644 src/mscorlib/src/System/IO/StringReader.cs delete mode 100644 src/mscorlib/src/System/IO/StringWriter.cs delete mode 100644 src/mscorlib/src/System/IO/__DebugOutputTextWriter.cs create mode 100644 src/mscorlib/src/System/MathF.cs create mode 100644 src/mscorlib/src/System/Numerics/Hashing/HashHelpers.cs create mode 100644 src/mscorlib/src/System/ReadOnlySpan.cs delete mode 100644 src/mscorlib/src/System/Runtime/CompilerServices/CallingConvention.cs delete mode 100644 src/mscorlib/src/System/Runtime/CompilerServices/HasCopySemanticsAttribute.cs delete mode 100644 src/mscorlib/src/System/Runtime/CompilerServices/IDispatchConstantAttribute.cs delete mode 100644 src/mscorlib/src/System/Runtime/CompilerServices/IUnknownConstantAttribute.cs delete mode 100644 src/mscorlib/src/System/Runtime/CompilerServices/IsBoxed.cs delete mode 100644 src/mscorlib/src/System/Runtime/CompilerServices/IsByValue.cs delete mode 100644 src/mscorlib/src/System/Runtime/CompilerServices/IsConst.cs delete mode 100644 src/mscorlib/src/System/Runtime/CompilerServices/IsCopyConstructed.cs delete mode 100644 src/mscorlib/src/System/Runtime/CompilerServices/IsExplicitlyDereferenced.cs delete mode 100644 src/mscorlib/src/System/Runtime/CompilerServices/IsImplicitlyDereferenced.cs delete mode 100644 src/mscorlib/src/System/Runtime/CompilerServices/IsJitIntrinsic.cs delete mode 100644 src/mscorlib/src/System/Runtime/CompilerServices/IsLong.cs delete mode 100644 src/mscorlib/src/System/Runtime/CompilerServices/IsPinned.cs delete mode 100644 src/mscorlib/src/System/Runtime/CompilerServices/IsSignUnspecifiedByte.cs delete mode 100644 src/mscorlib/src/System/Runtime/CompilerServices/IsUdtReturn.cs delete mode 100644 src/mscorlib/src/System/Runtime/CompilerServices/NativeCppClassAttribute.cs delete mode 100644 src/mscorlib/src/System/Runtime/CompilerServices/RequiredAttributeAttribute.cs delete mode 100644 src/mscorlib/src/System/Runtime/CompilerServices/ScopelessEnumAttribute.cs create mode 100644 src/mscorlib/src/System/Runtime/CompilerServices/Unsafe.cs create mode 100644 src/mscorlib/src/System/Runtime/ExceptionServices/ExceptionNotification.cs delete mode 100644 src/mscorlib/src/System/Runtime/InteropServices/NativeBuffer.cs delete mode 100644 src/mscorlib/src/System/Runtime/InteropServices/SafeHeapHandle.cs delete mode 100644 src/mscorlib/src/System/Runtime/InteropServices/StringBuffer.cs delete mode 100644 src/mscorlib/src/System/Runtime/InteropServices/TypeLibConverter.cs create mode 100644 src/mscorlib/src/System/Runtime/Serialization/SafeSerializationManager.cs delete mode 100644 src/mscorlib/src/System/Runtime/Versioning/BinaryCompatibility.cs delete mode 100644 src/mscorlib/src/System/Runtime/Versioning/ComponentGuaranteesAttribute.cs delete mode 100644 src/mscorlib/src/System/Runtime/Versioning/ResourceAttributes.cs create mode 100644 src/mscorlib/src/System/Span.cs create mode 100644 src/mscorlib/src/System/Text/Normalization.Unix.cs create mode 100644 src/mscorlib/src/System/Text/Normalization.Windows.cs delete mode 100644 src/mscorlib/src/System/Threading/WaitHandleExtensions.cs delete mode 100644 src/mscorlib/src/System/UnSafeCharBuffer.cs delete mode 100644 src/mscorlib/src/mscorlib.txt create mode 100644 src/pal/inc/unixasmmacrosx86.inc rename src/pal/prebuilt/idl/{clrdata_i.c => clrdata_i.cpp} (100%) rename src/pal/prebuilt/idl/{clrinternal_i.c => clrinternal_i.cpp} (100%) rename src/pal/prebuilt/idl/{clrprivappxhosting_i.c => clrprivappxhosting_i.cpp} (100%) rename src/pal/prebuilt/idl/{clrprivbinding_i.c => clrprivbinding_i.cpp} (100%) rename src/pal/prebuilt/idl/{clrprivhosting_i.c => clrprivhosting_i.cpp} (100%) rename src/pal/prebuilt/idl/{clrprivruntimebinders_i.c => clrprivruntimebinders_i.cpp} (100%) delete mode 100644 src/pal/prebuilt/idl/cordebug_i.c create mode 100644 src/pal/prebuilt/idl/cordebug_i.cpp delete mode 100644 src/pal/prebuilt/idl/corprof_i.c create mode 100644 src/pal/prebuilt/idl/corprof_i.cpp rename src/pal/prebuilt/idl/{corpub_i.c => corpub_i.cpp} (100%) rename src/pal/prebuilt/idl/{corsym_i.c => corsym_i.cpp} (100%) rename src/pal/prebuilt/idl/{fusionpriv_i.c => fusionpriv_i.cpp} (100%) rename src/pal/prebuilt/idl/{gchost_i.c => gchost_i.cpp} (100%) rename src/pal/prebuilt/idl/{ivalidator_i.c => ivalidator_i.cpp} (100%) rename src/pal/prebuilt/idl/{ivehandler_i.c => ivehandler_i.cpp} (100%) rename src/pal/prebuilt/idl/{mscorsvc_i.c => mscorsvc_i.cpp} (100%) delete mode 100644 src/pal/prebuilt/idl/sospriv_i.c create mode 100644 src/pal/prebuilt/idl/sospriv_i.cpp rename src/pal/prebuilt/idl/{tlbimpexp_i.c => tlbimpexp_i.cpp} (100%) rename src/pal/prebuilt/idl/{xclrdata_i.c => xclrdata_i.cpp} (100%) rename src/pal/prebuilt/idl/{xcordebug_i.c => xcordebug_i.cpp} (100%) rename src/pal/src/arch/{i386 => amd64}/activationhandlerwrapper.S (100%) create mode 100644 src/pal/src/arch/amd64/asmconstants.h rename src/pal/src/arch/{i386 => amd64}/context.S (100%) create mode 100644 src/pal/src/arch/amd64/context2.S create mode 100644 src/pal/src/arch/amd64/debugbreak.S rename src/pal/src/arch/{i386 => amd64}/dispatchexceptionwrapper.S (100%) create mode 100644 src/pal/src/arch/amd64/exceptionhelper.S create mode 100644 src/pal/src/arch/amd64/optimizedtls.cpp create mode 100644 src/pal/src/arch/amd64/processor.cpp delete mode 100644 src/pal/src/arch/i386/optimizedtls.cpp rename src/pal/src/examples/{example1.c => example1.cpp} (100%) rename src/pal/src/safecrt/{makepath_s.c => makepath_s.cpp} (100%) delete mode 100644 src/pal/src/safecrt/mbusafecrt.c create mode 100644 src/pal/src/safecrt/mbusafecrt.cpp rename src/pal/src/safecrt/{memcpy_s.c => memcpy_s.cpp} (100%) rename src/pal/src/safecrt/{memmove_s.c => memmove_s.cpp} (100%) rename src/pal/src/safecrt/{safecrt_input_s.c => safecrt_input_s.cpp} (100%) rename src/pal/src/safecrt/{safecrt_output_l.c => safecrt_output_l.cpp} (100%) rename src/pal/src/safecrt/{safecrt_output_s.c => safecrt_output_s.cpp} (100%) rename src/pal/src/safecrt/{safecrt_winput_s.c => safecrt_winput_s.cpp} (100%) rename src/pal/src/safecrt/{safecrt_woutput_s.c => safecrt_woutput_s.cpp} (100%) delete mode 100644 src/pal/src/safecrt/snprintf.c create mode 100644 src/pal/src/safecrt/snprintf.cpp rename src/pal/src/safecrt/{splitpath_s.c => splitpath_s.cpp} (100%) delete mode 100644 src/pal/src/safecrt/sprintf.c create mode 100644 src/pal/src/safecrt/sprintf_s.cpp delete mode 100644 src/pal/src/safecrt/sscanf.c create mode 100644 src/pal/src/safecrt/sscanf_s.cpp rename src/pal/src/safecrt/{strcat_s.c => strcat_s.cpp} (100%) rename src/pal/src/safecrt/{strcpy_s.c => strcpy_s.cpp} (100%) delete mode 100644 src/pal/src/safecrt/strlen_s.c create mode 100644 src/pal/src/safecrt/strlen_s.cpp rename src/pal/src/safecrt/{strncat_s.c => strncat_s.cpp} (100%) rename src/pal/src/safecrt/{strncpy_s.c => strncpy_s.cpp} (100%) rename src/pal/src/safecrt/{strtok_s.c => strtok_s.cpp} (100%) delete mode 100644 src/pal/src/safecrt/swprintf.c create mode 100644 src/pal/src/safecrt/swprintf.cpp delete mode 100644 src/pal/src/safecrt/vsprintf.c create mode 100644 src/pal/src/safecrt/vsprintf.cpp delete mode 100644 src/pal/src/safecrt/vswprint.c create mode 100644 src/pal/src/safecrt/vswprint.cpp rename src/pal/src/safecrt/{wcscat_s.c => wcscat_s.cpp} (100%) rename src/pal/src/safecrt/{wcscpy_s.c => wcscpy_s.cpp} (100%) rename src/pal/src/safecrt/{wcslen_s.c => wcslen_s.cpp} (100%) rename src/pal/src/safecrt/{wcsncat_s.c => wcsncat_s.cpp} (100%) rename src/pal/src/safecrt/{wcsncpy_s.c => wcsncpy_s.cpp} (100%) rename src/pal/src/safecrt/{wcstok_s.c => wcstok_s.cpp} (100%) rename src/pal/src/safecrt/{wmakepath_s.c => wmakepath_s.cpp} (100%) rename src/pal/src/safecrt/{wsplitpath_s.c => wsplitpath_s.cpp} (100%) rename src/pal/src/safecrt/{xtoa_s.c => xtoa_s.cpp} (100%) rename src/pal/src/safecrt/{xtow_s.c => xtow_s.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/__iscsym/test1/{__iscsym.c => __iscsym.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_alloca/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_ecvt/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_fdopen/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_finite/test1/{test1.c => test1.cpp} (100%) create mode 100644 src/pal/tests/palsuite/c_runtime/_finitef/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_finitef/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_finitef/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/_finitef/test1/testinfo.dat rename src/pal/tests/palsuite/c_runtime/_fullpath/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_gcvt/test1/{_gcvt.c => _gcvt.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_gcvt/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_getw/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_isnan/test1/{test1.c => test1.cpp} (100%) create mode 100644 src/pal/tests/palsuite/c_runtime/_isnanf/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_isnanf/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_isnanf/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/_isnanf/test1/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_itow/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/_itow/test1/test1.cpp delete mode 100644 src/pal/tests/palsuite/c_runtime/_makepath/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_makepath/test1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_makepath/test1/test1.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_makepath/test1/testinfo.dat rename src/pal/tests/palsuite/c_runtime/_mbsdec/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_mbsinc/test1/{test1.c => test1.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/c_runtime/_mbslen/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_mbslen/test1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_mbslen/test1/test1.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_mbslen/test1/testinfo.dat rename src/pal/tests/palsuite/c_runtime/_mbsninc/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_putenv/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_putenv/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_putenv/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_putenv/test4/{test4.c => test4.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/c_runtime/_putw/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/_putw/test1/test1.cpp delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/_snprintf.h delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test1/test1.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test1/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test10/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test10/test10.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test10/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test11/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test11/test11.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test11/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test12/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test12/test12.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test12/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test13/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test13/test13.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test13/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test14/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test14/test14.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test14/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test15/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test15/test15.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test15/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test16/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test16/test16.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test16/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test17/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test17/test17.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test17/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test18/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test18/test18.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test18/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test19/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test19/test19.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test19/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test2/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test2/test2.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test2/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test3/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test3/test3.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test3/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test4/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test4/test4.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test4/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test5/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test5/test5.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test5/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test6/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test6/test6.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test6/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test7/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test7/test7.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test7/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test8/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test8/test8.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test8/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test9/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test9/test9.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf/test9/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/_snprintf_s.h create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/test1.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/test10.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/test11.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/test12.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/test13.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/test14.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/test15.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/test16.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/test17.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/test18.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/test19.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/test2.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/test3.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/test4.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/test6.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/test7.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/test8.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/test9.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/_snwprintf.h delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test1/test1.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test1/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test10/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test10/test10.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test10/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test11/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test11/test11.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test11/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test12/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test12/test12.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test12/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test13/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test13/test13.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test13/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test14/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test14/test14.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test14/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test15/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test15/test15.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test15/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test16/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test16/test16.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test16/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test17/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test17/test17.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test17/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test18/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test18/test18.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test18/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test19/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test19/test19.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test19/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test2/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test2/test2.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test2/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test3/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test3/test3.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test3/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test4/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test4/test4.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test4/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test5/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test5/test5.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test5/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test6/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test6/test6.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test6/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test7/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test7/test7.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test7/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test8/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test8/test8.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test8/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test9/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test9/test9.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf/test9/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/_snwprintf_s.h create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/test1.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/test10.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/test11.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/test12.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/test13.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/test14.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/test15.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/test16.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/test17.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/test18.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/test19.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/test2.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/test3.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/test4.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/test6.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/test7.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/test8.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/test9.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_splitpath/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_splitpath/test1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_splitpath/test1/test1.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_splitpath/test1/testinfo.dat rename src/pal/tests/palsuite/c_runtime/_stricmp/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_strlwr/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_strnicmp/test1/{test1.c => test1.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/c_runtime/_swab/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_swab/test1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_swab/test1/test1.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_swab/test1/testinfo.dat rename src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/{test10.c => test10.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/{test11.c => test11.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/{test12.c => test12.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/{test13.c => test13.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/{test14.c => test14.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/{test15.c => test15.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/{test16.c => test16.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/{test17.c => test17.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/{test18.c => test18.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/test19.c create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/test19.cpp rename src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/{test6.c => test6.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/{test7.c => test7.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/{test8.c => test8.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/{test9.c => test9.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/_vsnwprintf.h delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/test1.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/test10.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/test11.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/test12.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/test13.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/test14.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/test15.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/test16.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/test17.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/test18.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/test19.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/test2.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/test3.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/test4.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/test5.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/test6.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/test7.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/test8.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/test9.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/_vsnwprintf_s.h create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/test1.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/test10.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/test11.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/test12.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/test13.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/test14.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/test15.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/test16.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/test17.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/test18.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/test19.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/test2.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/test3.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/test4.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/test6.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/test7.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/test8.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/test9.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/testinfo.dat rename src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_wcslwr/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_wfopen/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_wfopen/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_wfopen/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_wfopen/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_wfopen/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_wfopen/test6/{test6.c => test6.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/_wfopen/test7/{test7.c => test7.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/c_runtime/_wmakepath/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_wmakepath/test1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_wmakepath/test1/test1.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_wmakepath/test1/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/_wsplitpath/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/test1.c delete mode 100644 src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/testinfo.dat rename src/pal/tests/palsuite/c_runtime/_wtoi/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/abs/test1/{abs.c => abs.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/acos/test1/{test1.c => test1.cpp} (100%) create mode 100644 src/pal/tests/palsuite/c_runtime/acosf/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/acosf/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/acosf/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/acosf/test1/testinfo.dat rename src/pal/tests/palsuite/c_runtime/asin/test1/{test1.c => test1.cpp} (100%) create mode 100644 src/pal/tests/palsuite/c_runtime/asinf/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/asinf/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/asinf/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/asinf/test1/testinfo.dat rename src/pal/tests/palsuite/c_runtime/atan/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/atan2/test1/{test1.c => test1.cpp} (100%) create mode 100644 src/pal/tests/palsuite/c_runtime/atan2f/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/atan2f/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/atan2f/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/atan2f/test1/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/atanf/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/atanf/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/atanf/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/atanf/test1/testinfo.dat rename src/pal/tests/palsuite/c_runtime/atof/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/atoi/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/atol/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/bsearch/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/bsearch/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/ceil/test1/{test1.c => test1.cpp} (100%) create mode 100644 src/pal/tests/palsuite/c_runtime/ceilf/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/ceilf/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/ceilf/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/ceilf/test1/testinfo.dat rename src/pal/tests/palsuite/c_runtime/cos/test1/{test1.c => test1.cpp} (100%) create mode 100644 src/pal/tests/palsuite/c_runtime/cosf/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/cosf/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/cosf/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/cosf/test1/testinfo.dat rename src/pal/tests/palsuite/c_runtime/cosh/test1/{test1.c => test1.cpp} (100%) create mode 100644 src/pal/tests/palsuite/c_runtime/coshf/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/coshf/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/coshf/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/coshf/test1/testinfo.dat rename src/pal/tests/palsuite/c_runtime/ctime/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/errno/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/errno/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/exit/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/exit/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/exp/test1/{test1.c => test1.cpp} (100%) create mode 100644 src/pal/tests/palsuite/c_runtime/expf/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/expf/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/expf/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/expf/test1/testinfo.dat rename src/pal/tests/palsuite/c_runtime/fabs/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fabsf/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fclose/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fclose/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/feof/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/ferror/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/ferror/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fflush/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fgets/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fgets/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fgets/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/floor/test1/{test1.c => test1.cpp} (100%) create mode 100644 src/pal/tests/palsuite/c_runtime/floorf/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/floorf/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/floorf/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/floorf/test1/testinfo.dat rename src/pal/tests/palsuite/c_runtime/fmod/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fmodf/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fopen/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fopen/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fopen/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fopen/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fopen/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fopen/test6/{test6.c => test6.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fopen/test7/{test7.c => test7.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fprintf/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fprintf/test10/{test10.c => test10.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fprintf/test11/{test11.c => test11.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fprintf/test12/{test12.c => test12.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fprintf/test13/{test13.c => test13.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fprintf/test14/{test14.c => test14.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fprintf/test15/{test15.c => test15.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fprintf/test16/{test16.c => test16.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fprintf/test17/{test17.c => test17.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fprintf/test18/{test18.c => test18.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fprintf/test19/{test19.c => test19.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fprintf/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fprintf/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fprintf/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fprintf/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fprintf/test6/{test6.c => test6.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fprintf/test7/{test7.c => test7.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fprintf/test8/{test8.c => test8.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fprintf/test9/{test9.c => test9.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fputs/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fputs/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fread/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fread/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fread/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/free/test1/{test1.c => test1.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/c_runtime/fseek/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/fseek/test1/test1.cpp rename src/pal/tests/palsuite/c_runtime/ftell/test1/{ftell.c => ftell.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fwprintf/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fwprintf/test10/{test10.c => test10.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fwprintf/test11/{test11.c => test11.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fwprintf/test12/{test12.c => test12.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fwprintf/test13/{test13.c => test13.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fwprintf/test14/{test14.c => test14.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fwprintf/test15/{test15.c => test15.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fwprintf/test16/{test16.c => test16.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fwprintf/test17/{test17.c => test17.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fwprintf/test18/{test18.c => test18.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/c_runtime/fwprintf/test19/test19.c create mode 100644 src/pal/tests/palsuite/c_runtime/fwprintf/test19/test19.cpp rename src/pal/tests/palsuite/c_runtime/fwprintf/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fwprintf/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fwprintf/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fwprintf/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fwprintf/test6/{test6.c => test6.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fwprintf/test7/{test7.c => test7.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fwprintf/test8/{test8.c => test8.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fwprintf/test9/{test9.c => test9.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/fwrite/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/getc/test1/{getc.c => getc.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/getenv/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/getenv/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/getenv/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/isalnum/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/isalpha/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/isdigit/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/islower/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/isprint/test1/{isprint.c => isprint.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/isprint/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/isspace/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/isupper/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/iswdigit/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/iswprint/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/iswspace/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/iswupper/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/iswxdigit/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/isxdigit/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/labs/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/llabs/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/localtime/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/log/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/log10/test1/{test1.c => test1.cpp} (100%) create mode 100644 src/pal/tests/palsuite/c_runtime/log10f/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/log10f/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/log10f/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/log10f/test1/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/logf/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/logf/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/logf/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/logf/test1/testinfo.dat rename src/pal/tests/palsuite/c_runtime/malloc/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/malloc/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/memchr/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/memcmp/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/memcpy/test1/{test1.c => test1.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/c_runtime/memmove/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/memmove/test1/test1.cpp rename src/pal/tests/palsuite/c_runtime/memset/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/modf/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/modff/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/pow/test1/{test1.c => test1.cpp} (100%) create mode 100644 src/pal/tests/palsuite/c_runtime/powf/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/powf/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/powf/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/powf/test1/testinfo.dat rename src/pal/tests/palsuite/c_runtime/printf/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/printf/test10/{test10.c => test10.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/printf/test11/{test11.c => test11.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/printf/test12/{test12.c => test12.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/printf/test13/{test13.c => test13.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/printf/test14/{test14.c => test14.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/printf/test15/{test15.c => test15.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/printf/test16/{test16.c => test16.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/printf/test17/{test17.c => test17.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/printf/test18/{test18.c => test18.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/c_runtime/printf/test19/test19.c create mode 100644 src/pal/tests/palsuite/c_runtime/printf/test19/test19.cpp rename src/pal/tests/palsuite/c_runtime/printf/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/printf/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/printf/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/printf/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/printf/test6/{test6.c => test6.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/printf/test7/{test7.c => test7.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/printf/test8/{test8.c => test8.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/printf/test9/{test9.c => test9.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/qsort/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/qsort/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/rand_srand/test1/{test1.c => test1.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/c_runtime/realloc/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/realloc/test1/test1.cpp rename src/pal/tests/palsuite/c_runtime/sin/test1/{test1.c => test1.cpp} (100%) create mode 100644 src/pal/tests/palsuite/c_runtime/sinf/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sinf/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sinf/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/sinf/test1/testinfo.dat rename src/pal/tests/palsuite/c_runtime/sinh/test1/{test1.c => test1.cpp} (100%) create mode 100644 src/pal/tests/palsuite/c_runtime/sinhf/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sinhf/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sinhf/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/sinhf/test1/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/sprintf.h delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test1/test1.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test1/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test10/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test10/test10.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test10/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test11/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test11/test11.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test11/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test12/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test12/test12.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test12/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test13/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test13/test13.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test13/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test14/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test14/test14.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test14/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test15/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test15/test15.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test15/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test16/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test16/test16.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test16/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test17/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test17/test17.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test17/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test18/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test18/test18.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test18/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test19/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test19/test19.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test19/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test2/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test2/test2.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test2/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test3/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test3/test3.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test3/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test4/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test4/test4.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test4/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test5/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test5/test5.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test5/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test6/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test6/test6.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test6/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test7/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test7/test7.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test7/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test8/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test8/test8.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test8/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test9/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test9/test9.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sprintf/test9/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/sprintf_s.h create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test1/test1.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test1/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test10/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test10/test10.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test10/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test11/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test11/test11.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test11/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test12/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test12/test12.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test12/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test13/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test13/test13.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test13/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test14/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test14/test14.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test14/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test15/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test15/test15.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test15/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test16/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test16/test16.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test16/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test17/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test17/test17.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test17/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test18/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test18/test18.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test18/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test19/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test19/test19.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test19/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test2/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test2/test2.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test2/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test3/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test3/test3.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test3/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test4/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test4/test4.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test4/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test6/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test6/test6.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test6/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test7/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test7/test7.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test7/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test8/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test8/test8.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test8/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test9/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test9/test9.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sprintf_s/test9/testinfo.dat rename src/pal/tests/palsuite/c_runtime/sqrt/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/{miscellaneous/lstrcpynW => c_runtime/sqrtf}/CMakeLists.txt (100%) create mode 100644 src/pal/tests/palsuite/c_runtime/sqrtf/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sqrtf/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/sqrtf/test1/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/sscanf.h delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test1/test1.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test1/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test10/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test10/test10.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test10/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test11/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test11/test11.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test11/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test12/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test12/test12.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test12/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test13/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test13/test13.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test13/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test14/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test14/test14.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test14/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test15/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test15/test15.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test15/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test16/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test16/test16.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test16/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test17/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test17/test17.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test17/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test2/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test2/test2.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test2/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test3/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test3/test3.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test3/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test4/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test4/test4.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test4/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test5/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test5/test5.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test5/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test6/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test6/test6.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test6/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test7/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test7/test7.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test7/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test8/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test8/test8.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test8/testinfo.dat delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test9/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test9/test9.c delete mode 100644 src/pal/tests/palsuite/c_runtime/sscanf/test9/testinfo.dat rename src/pal/tests/palsuite/c_runtime/{sscanf => sscanf_s}/CMakeLists.txt (100%) create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/sscanf_s.h create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test1/test1.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test1/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test10/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test10/test10.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test10/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test11/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test11/test11.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test11/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test12/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test12/test12.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test12/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test13/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test13/test13.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test13/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test14/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test14/test14.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test14/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test15/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test15/test15.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test15/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test16/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test16/test16.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test16/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test17/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test17/test17.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test17/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test2/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test2/test2.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test2/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test3/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test3/test3.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test3/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test4/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test4/test4.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test4/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test5/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test5/test5.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test5/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test6/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test6/test6.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test6/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test7/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test7/test7.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test7/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test8/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test8/test8.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test8/testinfo.dat create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test9/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test9/test9.cpp create mode 100644 src/pal/tests/palsuite/c_runtime/sscanf_s/test9/testinfo.dat rename src/pal/tests/palsuite/c_runtime/strcat/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/strchr/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/strcmp/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/strcpy/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/strcspn/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/strlen/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/strncat/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/strncmp/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/strncpy/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/strpbrk/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/strrchr/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/strspn/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/strstr/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/strtod/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/strtod/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/strtok/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/strtoul/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swprintf/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swprintf/test10/{test10.c => test10.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swprintf/test11/{test11.c => test11.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swprintf/test12/{test12.c => test12.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swprintf/test13/{test13.c => test13.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swprintf/test14/{test14.c => test14.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swprintf/test15/{test15.c => test15.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swprintf/test16/{test16.c => test16.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swprintf/test17/{test17.c => test17.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swprintf/test18/{test18.c => test18.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/c_runtime/swprintf/test19/test19.c create mode 100644 src/pal/tests/palsuite/c_runtime/swprintf/test19/test19.cpp rename src/pal/tests/palsuite/c_runtime/swprintf/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swprintf/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swprintf/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swprintf/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swprintf/test6/{test6.c => test6.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swprintf/test7/{test7.c => test7.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swprintf/test8/{test8.c => test8.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swprintf/test9/{test9.c => test9.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swscanf/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swscanf/test10/{test10.c => test10.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swscanf/test11/{test11.c => test11.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swscanf/test12/{test12.c => test12.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swscanf/test13/{test13.c => test13.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swscanf/test14/{test14.c => test14.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swscanf/test15/{test15.c => test15.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swscanf/test16/{test16.c => test16.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swscanf/test17/{test17.c => test17.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swscanf/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swscanf/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swscanf/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swscanf/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swscanf/test6/{test6.c => test6.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swscanf/test7/{test7.c => test7.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swscanf/test8/{test8.c => test8.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/swscanf/test9/{test9.c => test9.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/tan/test1/{test1.c => test1.cpp} (100%) create mode 100644 src/pal/tests/palsuite/c_runtime/tanf/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/tanf/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/tanf/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/tanf/test1/testinfo.dat rename src/pal/tests/palsuite/c_runtime/tanh/test1/{test1.c => test1.cpp} (100%) create mode 100644 src/pal/tests/palsuite/c_runtime/tanhf/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/tanhf/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/c_runtime/tanhf/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/tanhf/test1/testinfo.dat rename src/pal/tests/palsuite/c_runtime/time/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/tolower/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/toupper/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/towlower/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/towupper/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/ungetc/test1/{ungetc.c => ungetc.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/ungetc/test2/{ungetc.c => ungetc.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vfprintf/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vfprintf/test10/{test10.c => test10.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vfprintf/test11/{test11.c => test11.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vfprintf/test12/{test12.c => test12.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vfprintf/test13/{test13.c => test13.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vfprintf/test14/{test14.c => test14.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vfprintf/test15/{test15.c => test15.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vfprintf/test16/{test16.c => test16.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vfprintf/test17/{test17.c => test17.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vfprintf/test18/{test18.c => test18.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/c_runtime/vfprintf/test19/test19.c create mode 100644 src/pal/tests/palsuite/c_runtime/vfprintf/test19/test19.cpp rename src/pal/tests/palsuite/c_runtime/vfprintf/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vfprintf/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vfprintf/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vfprintf/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vfprintf/test6/{test6.c => test6.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vfprintf/test7/{test7.c => test7.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vfprintf/test8/{test8.c => test8.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vfprintf/test9/{test9.c => test9.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vprintf/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vprintf/test10/{test10.c => test10.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vprintf/test11/{test11.c => test11.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vprintf/test12/{test12.c => test12.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vprintf/test13/{test13.c => test13.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vprintf/test14/{test14.c => test14.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vprintf/test15/{test15.c => test15.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vprintf/test16/{test16.c => test16.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vprintf/test17/{test17.c => test17.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vprintf/test18/{test18.c => test18.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/c_runtime/vprintf/test19/test19.c create mode 100644 src/pal/tests/palsuite/c_runtime/vprintf/test19/test19.cpp rename src/pal/tests/palsuite/c_runtime/vprintf/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vprintf/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vprintf/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vprintf/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vprintf/test6/{test6.c => test6.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vprintf/test7/{test7.c => test7.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vprintf/test8/{test8.c => test8.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vprintf/test9/{test9.c => test9.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vsprintf/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vsprintf/test10/{test10.c => test10.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vsprintf/test11/{test11.c => test11.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vsprintf/test12/{test12.c => test12.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vsprintf/test13/{test13.c => test13.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vsprintf/test14/{test14.c => test14.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vsprintf/test15/{test15.c => test15.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vsprintf/test16/{test16.c => test16.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vsprintf/test17/{test17.c => test17.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vsprintf/test18/{test18.c => test18.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/c_runtime/vsprintf/test19/test19.c create mode 100644 src/pal/tests/palsuite/c_runtime/vsprintf/test19/test19.cpp rename src/pal/tests/palsuite/c_runtime/vsprintf/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vsprintf/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vsprintf/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vsprintf/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vsprintf/test6/{test6.c => test6.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vsprintf/test7/{test7.c => test7.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vsprintf/test8/{test8.c => test8.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vsprintf/test9/{test9.c => test9.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vswprintf/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vswprintf/test10/{test10.c => test10.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vswprintf/test11/{test11.c => test11.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vswprintf/test12/{test12.c => test12.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vswprintf/test13/{test13.c => test13.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vswprintf/test14/{test14.c => test14.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vswprintf/test15/{test15.c => test15.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vswprintf/test16/{test16.c => test16.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vswprintf/test17/{test17.c => test17.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vswprintf/test18/{test18.c => test18.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/c_runtime/vswprintf/test19/test19.c create mode 100644 src/pal/tests/palsuite/c_runtime/vswprintf/test19/test19.cpp rename src/pal/tests/palsuite/c_runtime/vswprintf/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vswprintf/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vswprintf/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vswprintf/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vswprintf/test6/{test6.c => test6.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vswprintf/test7/{test7.c => test7.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vswprintf/test8/{test8.c => test8.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/vswprintf/test9/{test9.c => test9.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/c_runtime/wcscat/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/wcscat/test1/test1.cpp rename src/pal/tests/palsuite/c_runtime/wcschr/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcscmp/test1/{test1.c => test1.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/c_runtime/wcscpy/test1/test1.c create mode 100644 src/pal/tests/palsuite/c_runtime/wcscpy/test1/test1.cpp rename src/pal/tests/palsuite/c_runtime/wcslen/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcsncat/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcsncmp/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcsncpy/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcspbrk/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcsrchr/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcsstr/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcstod/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcstod/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcstok/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcstol/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcstol/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcstol/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcstol/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcstol/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcstol/test6/{test6.c => test6.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcstoul/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcstoul/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcstoul/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcstoul/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcstoul/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wcstoul/test6/{test6.c => test6.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wprintf/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/c_runtime/wprintf/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/composite/object_management/event/nonshared/{event.c => event.cpp} (100%) rename src/pal/tests/palsuite/composite/object_management/event/nonshared/{main.c => main.cpp} (100%) rename src/pal/tests/palsuite/composite/object_management/event/shared/{event.c => event.cpp} (100%) rename src/pal/tests/palsuite/composite/object_management/event/shared/{main.c => main.cpp} (100%) rename src/pal/tests/palsuite/composite/object_management/mutex/nonshared/{main.c => main.cpp} (100%) rename src/pal/tests/palsuite/composite/object_management/mutex/nonshared/{mutex.c => mutex.cpp} (100%) rename src/pal/tests/palsuite/composite/object_management/mutex/shared/{main.c => main.cpp} (100%) rename src/pal/tests/palsuite/composite/object_management/mutex/shared/{mutex.c => mutex.cpp} (100%) rename src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/{main.c => main.cpp} (100%) rename src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/{semaphore.c => semaphore.cpp} (100%) rename src/pal/tests/palsuite/composite/object_management/semaphore/shared/{main.c => main.cpp} (100%) rename src/pal/tests/palsuite/composite/object_management/semaphore/shared/{semaphore.c => semaphore.cpp} (100%) rename src/pal/tests/palsuite/composite/synchronization/criticalsection/{criticalsection.c => criticalsection.cpp} (100%) rename src/pal/tests/palsuite/composite/synchronization/criticalsection/{mainWrapper.c => mainWrapper.cpp} (100%) rename src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/{pal_composite_native_cs.c => pal_composite_native_cs.cpp} (100%) rename src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/{pal_composite_native_cs.c => pal_composite_native_cs.cpp} (100%) rename src/pal/tests/palsuite/composite/threading/{threadsuspension_switchthread/mainWrapper.c => threadsuspension/mainWrapper.cpp} (100%) rename src/pal/tests/palsuite/composite/threading/threadsuspension/{threadsuspension.c => threadsuspension.cpp} (100%) rename src/pal/tests/palsuite/composite/threading/{threadsuspension/mainWrapper.c => threadsuspension_switchthread/mainWrapper.cpp} (100%) rename src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/{threadsuspension.c => threadsuspension.cpp} (100%) rename src/pal/tests/palsuite/composite/wfmo/{main.c => main.cpp} (100%) rename src/pal/tests/palsuite/composite/wfmo/{mutex.c => mutex.cpp} (100%) rename src/pal/tests/palsuite/debug_api/DebugBreak/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/{helper.c => helper.cpp} (100%) rename src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/{test1.c => test1.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/helper.c create mode 100644 src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/helper.cpp delete mode 100644 src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/test1.c create mode 100644 src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/test1.cpp rename src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/{helper.c => helper.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/test3.c create mode 100644 src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/test3.cpp rename src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/{helper.c => helper.cpp} (100%) rename src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/{PAL_EXCEPT_FILTER.c => PAL_EXCEPT_FILTER.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/{pal_except_filter.c => pal_except_filter.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/{pal_except_filter.c => pal_except_filter.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/{PAL_EXCEPT_FILTER_EX.c => PAL_EXCEPT_FILTER_EX.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/{pal_except_filter_ex.c => pal_except_filter_ex.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/{pal_except_filter.c => pal_except_filter.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/{PAL_TRY_EXCEPT.c => PAL_TRY_EXCEPT.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/{PAL_TRY_EXCEPT.c => PAL_TRY_EXCEPT.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/{PAL_TRY_EXCEPT_EX.c => PAL_TRY_EXCEPT_EX.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/{PAL_TRY_EXCEPT_EX.c => PAL_TRY_EXCEPT_EX.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/{PAL_TRY_EXCEPT_EX.c => PAL_TRY_EXCEPT_EX.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/{PAL_TRY_LEAVE_FINALLY.c => PAL_TRY_LEAVE_FINALLY.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/pal_except/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/pal_except/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/pal_except/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/pal_except/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/pal_except/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/pal_except/test6/{test6.c => test6.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/pal_except/test7/{test7.c => test7.cpp} (100%) rename src/pal/tests/palsuite/exception_handling/pal_finally/test1/{pal_finally.c => pal_finally.cpp} (100%) rename src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/{AreFileApisANSI.c => AreFileApisANSI.cpp} (100%) rename src/pal/tests/palsuite/file_io/CompareFileTime/test1/{CompareFileTime.c => CompareFileTime.cpp} (100%) rename src/pal/tests/palsuite/file_io/CopyFileA/test1/{CopyFileA.c => CopyFileA.cpp} (100%) rename src/pal/tests/palsuite/file_io/CopyFileA/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/file_io/CopyFileA/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/file_io/CopyFileA/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/file_io/CopyFileW/test1/{CopyFileW.c => CopyFileW.cpp} (100%) rename src/pal/tests/palsuite/file_io/CopyFileW/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/file_io/CopyFileW/test3/{test3.c => test3.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/CreateDirectoryA.c create mode 100644 src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/CreateDirectoryA.cpp rename src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/{createdirectorya.c => createdirectorya.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/CreateDirectoryW.c create mode 100644 src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/CreateDirectoryW.cpp rename src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/{createdirectoryw.c => createdirectoryw.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/file_io/CreateFileA/test1/CreateFileA.c create mode 100644 src/pal/tests/palsuite/file_io/CreateFileA/test1/CreateFileA.cpp delete mode 100644 src/pal/tests/palsuite/file_io/CreateFileW/test1/CreateFileW.c create mode 100644 src/pal/tests/palsuite/file_io/CreateFileW/test1/CreateFileW.cpp rename src/pal/tests/palsuite/file_io/DeleteFileW/test1/{DeleteFileW.c => DeleteFileW.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/file_io/FILECanonicalizePath/FILECanonicalizePath.c create mode 100644 src/pal/tests/palsuite/file_io/FILECanonicalizePath/FILECanonicalizePath.cpp rename src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/file_io/FindClose/test1/{FindClose.c => FindClose.cpp} (100%) rename src/pal/tests/palsuite/file_io/FindFirstFileA/test1/{FindFirstFileA.c => FindFirstFileA.cpp} (100%) rename src/pal/tests/palsuite/file_io/FindFirstFileW/test1/{FindFirstFileW.c => FindFirstFileW.cpp} (100%) rename src/pal/tests/palsuite/file_io/FindNextFileA/test1/{FindNextFileA.c => FindNextFileA.cpp} (100%) rename src/pal/tests/palsuite/file_io/FindNextFileA/test2/{findnextfilea.c => findnextfilea.cpp} (100%) rename src/pal/tests/palsuite/file_io/FindNextFileW/test1/{FindNextFileW.c => FindNextFileW.cpp} (100%) rename src/pal/tests/palsuite/file_io/FindNextFileW/test2/{findnextfilew.c => findnextfilew.cpp} (100%) rename src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/{FlushFileBuffers.c => FlushFileBuffers.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetConsoleCP/test1/{GetConsoleCP.c => GetConsoleCP.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/{GetConsoleOutputCP.c => GetConsoleOutputCP.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/{GetCurrentDirectoryA.c => GetCurrentDirectoryA.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/{GetCurrentDirectoryW.c => GetCurrentDirectoryW.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/{GetDiskFreeSpaceW.c => GetDiskFreeSpaceW.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/{getdiskfreespacew.c => getdiskfreespacew.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/{GetFileAttributesA.c => GetFileAttributesA.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/{GetFileAttributesW.c => GetFileAttributesW.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFileSize/test1/{GetFileSize.c => GetFileSize.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/{GetFileSizeEx.c => GetFileSizeEx.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFileTime/test1/{GetFileTime.c => GetFileTime.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFileTime/test2/{GetFileTime.c => GetFileTime.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFileTime/test3/{GetFileTime.c => GetFileTime.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFileTime/test4/{GetFileTime.c => GetFileTime.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFileTime/test5/{getfiletime.c => getfiletime.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFileTime/test6/{getfiletime.c => getfiletime.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFileTime/test7/{getfiletime.c => getfiletime.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFileType/test1/{GetFileType.c => GetFileType.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFileType/test2/{getfiletype.c => getfiletype.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFileType/test3/{getfiletype.c => getfiletype.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/{GetFullPathNameA.c => GetFullPathNameA.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/{GetFullPathNameW.c => GetFullPathNameW.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/{GetLongPathNameW.c => GetLongPathNameW.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/{getlongpathnamew.c => getlongpathnamew.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetStdHandle/test1/{GetStdHandle.c => GetStdHandle.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetStdHandle/test2/{GetStdHandle.c => GetStdHandle.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetSystemTime/test1/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/{GetSystemTimeAsFileTime.c => GetSystemTimeAsFileTime.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/GetTempFileNameA.c create mode 100644 src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/GetTempFileNameA.cpp rename src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/{GetTempFileNameA.c => GetTempFileNameA.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/{gettempfilenamea.c => gettempfilenamea.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/{GetTempFileNameW.c => GetTempFileNameW.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/{GetTempFileNameW.c => GetTempFileNameW.cpp} (100%) rename src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/{gettempfilenamew.c => gettempfilenamew.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/file_io/GetTempPathW/test1/GetTempPathW.c create mode 100644 src/pal/tests/palsuite/file_io/GetTempPathW/test1/GetTempPathW.cpp delete mode 100644 src/pal/tests/palsuite/file_io/MoveFileA/test1/MoveFileA.c create mode 100644 src/pal/tests/palsuite/file_io/MoveFileA/test1/MoveFileA.cpp rename src/pal/tests/palsuite/file_io/MoveFileExA/test1/{MoveFileExA.c => MoveFileExA.cpp} (100%) rename src/pal/tests/palsuite/file_io/MoveFileExW/test1/{MoveFileExW.c => MoveFileExW.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/file_io/MoveFileW/test1/MoveFileW.c create mode 100644 src/pal/tests/palsuite/file_io/MoveFileW/test1/MoveFileW.cpp rename src/pal/tests/palsuite/file_io/ReadFile/test1/{ReadFile.c => ReadFile.cpp} (100%) rename src/pal/tests/palsuite/file_io/ReadFile/test2/{ReadFile.c => ReadFile.cpp} (100%) rename src/pal/tests/palsuite/file_io/ReadFile/test3/{ReadFile.c => ReadFile.cpp} (100%) rename src/pal/tests/palsuite/file_io/ReadFile/test4/{readfile.c => readfile.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/RemoveDirectoryW.c create mode 100644 src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/RemoveDirectoryW.cpp delete mode 100644 src/pal/tests/palsuite/file_io/SearchPathA/test1/SearchPathA.c create mode 100644 src/pal/tests/palsuite/file_io/SearchPathA/test1/SearchPathA.cpp delete mode 100644 src/pal/tests/palsuite/file_io/SearchPathW/test1/SearchPathW.c create mode 100644 src/pal/tests/palsuite/file_io/SearchPathW/test1/SearchPathW.cpp delete mode 100644 src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/SetCurrentDirectoryA.c create mode 100644 src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/SetCurrentDirectoryA.cpp delete mode 100644 src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/setcurrentdirectorya.c create mode 100644 src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/setcurrentdirectorya.cpp rename src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/{setcurrentdirectorya.c => setcurrentdirectorya.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/SetCurrentDirectoryW.c create mode 100644 src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/SetCurrentDirectoryW.cpp delete mode 100644 src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/setcurrentdirectoryw.c create mode 100644 src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/setcurrentdirectoryw.cpp rename src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/{setcurrentdirectoryw.c => setcurrentdirectoryw.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetEndOfFile/test1/{SetEndOfFile.c => SetEndOfFile.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetEndOfFile/test2/{SetEndOfFile.c => SetEndOfFile.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetEndOfFile/test3/{SetEndOfFile.c => SetEndOfFile.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetEndOfFile/test4/{setendoffile.c => setendoffile.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetEndOfFile/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/{SetFileAttributesA.c => SetFileAttributesA.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/{SetFileAttributesA.c => SetFileAttributesA.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/{SetFileAttributesA.c => SetFileAttributesA.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/{SetFileAttributesA.c => SetFileAttributesA.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/{SetFileAttributesW.c => SetFileAttributesW.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/{SetFileAttributesW.c => SetFileAttributesW.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/{SetFileAttributesW.c => SetFileAttributesW.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/{SetFileAttributesW.c => SetFileAttributesW.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetFilePointer/test1/{SetFilePointer.c => SetFilePointer.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetFilePointer/test2/{SetFilePointer.c => SetFilePointer.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetFilePointer/test3/{SetFilePointer.c => SetFilePointer.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetFilePointer/test4/{SetFilePointer.c => SetFilePointer.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetFilePointer/test5/{SetFilePointer.c => SetFilePointer.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetFilePointer/test6/{SetFilePointer.c => SetFilePointer.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetFilePointer/test7/{SetFilePointer.c => SetFilePointer.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetFileTime/test1/{SetFileTime.c => SetFileTime.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetFileTime/test2/{SetFileTime.c => SetFileTime.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetFileTime/test3/{SetFileTime.c => SetFileTime.cpp} (100%) rename src/pal/tests/palsuite/file_io/SetFileTime/test4/{SetFileTime.c => SetFileTime.cpp} (100%) rename src/pal/tests/palsuite/file_io/WriteFile/test1/{WriteFile.c => WriteFile.cpp} (100%) rename src/pal/tests/palsuite/file_io/WriteFile/test2/{WriteFile.c => WriteFile.cpp} (100%) rename src/pal/tests/palsuite/file_io/WriteFile/test3/{WriteFile.c => WriteFile.cpp} (100%) rename src/pal/tests/palsuite/file_io/WriteFile/test4/{writefile.c => writefile.cpp} (100%) rename src/pal/tests/palsuite/file_io/WriteFile/test5/{writefile.c => writefile.cpp} (100%) rename src/pal/tests/palsuite/file_io/errorpathnotfound/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/file_io/errorpathnotfound/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/file_io/errorpathnotfound/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/file_io/errorpathnotfound/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/file_io/gettemppatha/test1/{gettemppatha.c => gettemppatha.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/{CreateFileMapping.c => CreateFileMapping.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/{CreateFileMapping.c => CreateFileMapping.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/{CreateFileMapping.c => CreateFileMapping.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/{CreateFileMapping.c => CreateFileMapping.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/{CreateFileMapping.c => CreateFileMapping.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/{createfilemapping.c => createfilemapping.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/{createfilemapping.c => createfilemapping.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/{createfilemapping.c => createfilemapping.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/{CreateFileMapping_neg.c => CreateFileMapping_neg.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/{CreateFileMappingW.c => CreateFileMappingW.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CreateFileMappingW.c create mode 100644 src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CreateFileMappingW.cpp rename src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/{CreateFileMappingW.c => CreateFileMappingW.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/{CreateFileMappingW.c => CreateFileMappingW.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/{CreateFileMappingW.c => CreateFileMappingW.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/{CreateFileMappingW.c => CreateFileMappingW.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/{createfilemapping.c => createfilemapping.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/{createfilemapping.c => createfilemapping.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/{createfilemapping.c => createfilemapping.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/{FreeLibrary.c => FreeLibrary.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/{dlltest.c => dlltest.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/{dlltest.c => dlltest.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/test1.c create mode 100644 src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/test1.cpp rename src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/{GetModuleFileNameA.c => GetModuleFileNameA.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/{GetModuleFileNameA.c => GetModuleFileNameA.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/GetModuleFileNameW.c create mode 100644 src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/GetModuleFileNameW.cpp delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/GetModuleFileNameW.c create mode 100644 src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/GetModuleFileNameW.cpp rename src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/{testlib.c => testlib.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/{testlib.c => testlib.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/{GetProcessHeap.c => GetProcessHeap.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/{HeapAlloc.c => HeapAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/{HeapAlloc.c => HeapAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/{HeapAlloc.c => HeapAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/{HeapFree.c => HeapFree.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/test1.c create mode 100644 src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/test1.cpp delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/test2.c create mode 100644 src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/test2.cpp delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/test3.c create mode 100644 src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/test3.cpp rename src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/{test4.c => test4.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/test5.c create mode 100644 src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/test5.cpp rename src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/{LocalAlloc.c => LocalAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/{LocalFree.c => LocalFree.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/{LocalFree.c => LocalFree.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/{helper.c => helper.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/{helper.c => helper.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/{helper.c => helper.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/{helper.c => helper.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/{test6.c => test6.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/{test7.c => test7.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/{MapViewOfFile.c => MapViewOfFile.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/{MapViewOfFile.c => MapViewOfFile.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/{MapViewOfFile.c => MapViewOfFile.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/{mapviewoffile.c => mapviewoffile.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/{mapviewoffile.c => mapviewoffile.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/{mapviewoffile.c => mapviewoffile.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/{OpenFileMappingA.c => OpenFileMappingA.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/{OpenFileMappingA.c => OpenFileMappingA.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/{OpenFileMappingA.c => OpenFileMappingA.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/{OpenFileMappingW.c => OpenFileMappingW.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/{OpenFileMappingW.c => OpenFileMappingW.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/{OpenFileMappingW.c => OpenFileMappingW.cpp} (100%) create mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/ProbeMemory_neg.cpp create mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/testinfo.dat create mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/ProbeMemory.cpp create mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/testinfo.dat delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/ReadProcessMemory_neg.c delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/testinfo.dat delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/ReadProcessMemory.c delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/testinfo.dat delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/commonconsts.h delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/helper.c delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/test2.c delete mode 100644 src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/testinfo.dat rename src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/{helper.c => helper.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/{helper.c => helper.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/{UnmapViewOfFile.c => UnmapViewOfFile.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/{unmapviewoffile.c => unmapviewoffile.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/{VirtualAlloc.c => VirtualAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/{VirtualAlloc.c => VirtualAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/{VirtualAlloc.c => VirtualAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/{VirtualAlloc.c => VirtualAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/{VirtualAlloc.c => VirtualAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/{VirtualAlloc.c => VirtualAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/{VirtualAlloc.c => VirtualAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/{VirtualAlloc.c => VirtualAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/{VirtualAlloc.c => VirtualAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/{VirtualAlloc.c => VirtualAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/{VirtualAlloc.c => VirtualAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/{VirtualAlloc.c => VirtualAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/{virtualalloc.c => virtualalloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/{virtualalloc.c => virtualalloc.cpp} (100%) create mode 100644 src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/CMakeLists.txt create mode 100644 src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/VirtualAlloc.cpp create mode 100644 src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/testinfo.dat rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/{VirtualAlloc.c => VirtualAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/{VirtualAlloc.c => VirtualAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/{VirtualAlloc.c => VirtualAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/{VirtualAlloc.c => VirtualAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/{VirtualAlloc.c => VirtualAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/{VirtualAlloc.c => VirtualAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/{VirtualAlloc.c => VirtualAlloc.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/{VirtualFree.c => VirtualFree.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/{VirtualFree.c => VirtualFree.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/{VirtualFree.c => VirtualFree.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/{VirtualProtect.c => VirtualProtect.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/{VirtualProtect.c => VirtualProtect.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/{VirtualProtect.c => VirtualProtect.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/{VirtualProtect.c => VirtualProtect.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/{VirtualProtect.c => VirtualProtect.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/{VirtualProtect.c => VirtualProtect.cpp} (100%) rename src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/{VirtualQuery.c => VirtualQuery.cpp} (100%) rename src/pal/tests/palsuite/loader/LoadLibraryA/test1/{LoadLibraryA.c => LoadLibraryA.cpp} (100%) rename src/pal/tests/palsuite/loader/LoadLibraryA/test2/{LoadLibraryA.c => LoadLibraryA.cpp} (100%) rename src/pal/tests/palsuite/loader/LoadLibraryA/test2/{MyModule.c => MyModule.cpp} (100%) rename src/pal/tests/palsuite/loader/LoadLibraryA/test3/{loadlibrarya.c => loadlibrarya.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/loader/LoadLibraryA/test5/loadlibrarya.c create mode 100644 src/pal/tests/palsuite/loader/LoadLibraryA/test5/loadlibrarya.cpp rename src/pal/tests/palsuite/loader/LoadLibraryA/{test8/dlltest.c => test6/dlltest.cpp} (100%) rename src/pal/tests/palsuite/loader/LoadLibraryA/test6/{loadlibrarya.c => loadlibrarya.cpp} (100%) rename src/pal/tests/palsuite/loader/LoadLibraryA/test7/{LoadLibraryA.c => LoadLibraryA.cpp} (100%) rename src/pal/tests/palsuite/loader/LoadLibraryA/{test6/dlltest.c => test8/dlltest.cpp} (100%) rename src/pal/tests/palsuite/loader/LoadLibraryA/test8/{loadlibrarya.c => loadlibrarya.cpp} (100%) rename src/pal/tests/palsuite/loader/LoadLibraryW/test1/{LoadLibraryW.c => LoadLibraryW.cpp} (100%) rename src/pal/tests/palsuite/loader/LoadLibraryW/test2/{loadlibraryw.c => loadlibraryw.cpp} (100%) rename src/pal/tests/palsuite/loader/LoadLibraryW/test3/{loadlibraryw.c => loadlibraryw.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/loader/LoadLibraryW/test5/loadlibraryw.c create mode 100644 src/pal/tests/palsuite/loader/LoadLibraryW/test5/loadlibraryw.cpp rename src/pal/tests/palsuite/locale_info/CompareStringA/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/locale_info/CompareStringW/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/locale_info/GetACP/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/locale_info/GetCPInfo/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/locale_info/GetCPInfo/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/locale_info/GetCPInfo/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/locale_info/IsValidLocale/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/{test3.c => test3.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/test4.c create mode 100644 src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/test4.cpp rename src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/{test4.c => test4.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/test5.c create mode 100644 src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/test5.cpp rename src/pal/tests/palsuite/miscellaneous/CharNextA/test1/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/CharNextA/test2/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/{test.c => test.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/test.c create mode 100644 src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/test.cpp rename src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/{GetCalendarInfoW.c => GetCalendarInfoW.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/{GetCalendarInfoW.c => GetCalendarInfoW.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/test.c create mode 100644 src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/test.cpp rename src/pal/tests/palsuite/miscellaneous/GetComputerNameW/test1/{test.c => test.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg1/GetDateFormatW_neg.c create mode 100644 src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg1/GetDateFormatW_neg.cpp delete mode 100644 src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/GetDateFormatW_neg.c create mode 100644 src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/GetDateFormatW_neg.cpp delete mode 100644 src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/GetDateFormatW.c create mode 100644 src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/GetDateFormatW.cpp rename src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/{test.c => test.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/test.c create mode 100644 src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/test.cpp rename src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/{test.c => test.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/test.c create mode 100644 src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/test.cpp delete mode 100644 src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/test5.c create mode 100644 src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/test5.cpp delete mode 100644 src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/test6.c create mode 100644 src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/test6.cpp delete mode 100644 src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/test.c create mode 100644 src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/test.cpp rename src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/{test.c => test.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/test.c create mode 100644 src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/test.cpp delete mode 100644 src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/test5.c create mode 100644 src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/test5.cpp delete mode 100644 src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/test6.c create mode 100644 src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/test6.cpp rename src/pal/tests/palsuite/miscellaneous/GetLastError/test1/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/{test2.c => test2.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/test3.c create mode 100644 src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/test3.cpp delete mode 100644 src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/test4.c create mode 100644 src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/test4.cpp rename src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/{test.c => test.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/test3.c create mode 100644 src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/test3.cpp delete mode 100644 src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/test4.c create mode 100644 src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/test4.cpp rename src/pal/tests/palsuite/miscellaneous/SetLastError/test1/{test.c => test.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/miscellaneous/_i64tow/test1/test1.c create mode 100644 src/pal/tests/palsuite/miscellaneous/_i64tow/test1/test1.cpp delete mode 100644 src/pal/tests/palsuite/miscellaneous/_ui64tow/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/_ui64tow/test1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/_ui64tow/test1/_ui64tow.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/_ui64tow/test1/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/_ui64tow.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/lstrcatW/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/test2.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/test3.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/test4.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/lstrcpyW/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/testinfo.dat rename src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/{test1.c => test1.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/testinfo.dat delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/CMakeLists.txt delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/test.c delete mode 100644 src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/testinfo.dat delete mode 100644 src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/PAL_GetPALDirectoryW.c create mode 100644 src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/PAL_GetPALDirectoryW.cpp rename src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/{PAL_GetUserTempDirectoryW.c => PAL_GetUserTempDirectoryW.cpp} (100%) rename src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/{PAL_Initialize_Terminate.c => PAL_Initialize_Terminate.cpp} (100%) rename src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/{pal_initialize_twice.c => pal_initialize_twice.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/PAL_RegisterLibraryW_UnregisterLibraryW.c create mode 100644 src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/PAL_RegisterLibraryW_UnregisterLibraryW.cpp delete mode 100644 src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/reg_unreg_libraryw_neg.c create mode 100644 src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/reg_unreg_libraryw_neg.cpp rename src/pal/tests/palsuite/pal_specific/PAL_errno/test1/{PAL_errno.c => PAL_errno.cpp} (100%) rename src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/{PAL_get_stderr.c => PAL_get_stderr.cpp} (100%) rename src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/{PAL_get_stdin.c => PAL_get_stdin.cpp} (100%) rename src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/{PAL_get_stdout.c => PAL_get_stdout.cpp} (100%) rename src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/{pal_entrypoint.c => pal_entrypoint.cpp} (100%) rename src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/{pal_initializedebug.c => pal_initializedebug.cpp} (100%) rename src/pal/tests/palsuite/samples/test1/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/samples/test2/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/threading/CreateEventA/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/threading/CreateEventA/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/threading/CreateEventA/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/threading/CreateEventW/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/threading/CreateEventW/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/threading/CreateEventW/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/{CreateMutexA.c => CreateMutexA.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CreateMutexA.c create mode 100644 src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CreateMutexA.cpp rename src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/{CreateMutexW.c => CreateMutexW.cpp} (100%) rename src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/{CreateMutexW.c => CreateMutexW.cpp} (100%) rename src/pal/tests/palsuite/threading/CreateProcessA/test1/{childProcess.c => childProcess.cpp} (100%) rename src/pal/tests/palsuite/threading/CreateProcessA/test1/{parentProcess.c => parentProcess.cpp} (100%) rename src/pal/tests/palsuite/threading/CreateProcessA/test2/{childprocess.c => childprocess.cpp} (100%) rename src/pal/tests/palsuite/threading/CreateProcessA/test2/{parentprocess.c => parentprocess.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/threading/CreateProcessW/test1/childProcess.c create mode 100644 src/pal/tests/palsuite/threading/CreateProcessW/test1/childProcess.cpp rename src/pal/tests/palsuite/threading/CreateProcessW/test1/{parentProcess.c => parentProcess.cpp} (100%) rename src/pal/tests/palsuite/threading/CreateProcessW/test2/{childprocess.c => childprocess.cpp} (100%) rename src/pal/tests/palsuite/threading/CreateProcessW/test2/{parentprocess.c => parentprocess.cpp} (100%) rename src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/{CreateSemaphore.c => CreateSemaphore.cpp} (100%) rename src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/{CreateSemaphore.c => CreateSemaphore.cpp} (100%) rename src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/{createsemaphore.c => createsemaphore.cpp} (100%) rename src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/{CreateSemaphore.c => CreateSemaphore.cpp} (100%) rename src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/{CreateSemaphore.c => CreateSemaphore.cpp} (100%) rename src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/{createsemaphore.c => createsemaphore.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/threading/CreateThread/test1/test1.c create mode 100644 src/pal/tests/palsuite/threading/CreateThread/test1/test1.cpp delete mode 100644 src/pal/tests/palsuite/threading/CreateThread/test2/test2.c create mode 100644 src/pal/tests/palsuite/threading/CreateThread/test2/test2.cpp rename src/pal/tests/palsuite/threading/CreateThread/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/{InitializeCriticalSection.c => InitializeCriticalSection.cpp} (100%) rename src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/{test6.c => test6.cpp} (100%) rename src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/{test7.c => test7.cpp} (100%) rename src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/{test8.c => test8.cpp} (100%) rename src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/{testlib.c => testlib.cpp} (100%) rename src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/{dllmain1.c => dllmain1.cpp} (100%) rename src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/{dllmain2.c => dllmain2.cpp} (100%) rename src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/threading/DuplicateHandle/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/threading/DuplicateHandle/test10/{test10.c => test10.cpp} (100%) rename src/pal/tests/palsuite/threading/DuplicateHandle/test11/{childprocess.c => childprocess.cpp} (100%) rename src/pal/tests/palsuite/threading/DuplicateHandle/test11/{test11.c => test11.cpp} (100%) rename src/pal/tests/palsuite/threading/DuplicateHandle/test12/{test12.c => test12.cpp} (100%) rename src/pal/tests/palsuite/threading/DuplicateHandle/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/threading/DuplicateHandle/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/threading/DuplicateHandle/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/threading/DuplicateHandle/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/threading/DuplicateHandle/test6/{test6.c => test6.cpp} (100%) rename src/pal/tests/palsuite/threading/DuplicateHandle/test7/{test7.c => test7.cpp} (100%) rename src/pal/tests/palsuite/threading/DuplicateHandle/test8/{test8.c => test8.cpp} (100%) rename src/pal/tests/palsuite/threading/DuplicateHandle/test9/{test9.c => test9.cpp} (100%) rename src/pal/tests/palsuite/threading/ExitProcess/test1/{ExitProcess.c => ExitProcess.cpp} (100%) rename src/pal/tests/palsuite/threading/ExitProcess/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/threading/ExitProcess/test3/{test3.c => test3.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/threading/ExitThread/test1/test1.c create mode 100644 src/pal/tests/palsuite/threading/ExitThread/test1/test1.cpp rename src/pal/tests/palsuite/threading/ExitThread/test2/{childprocess.c => childprocess.cpp} (100%) rename src/pal/tests/palsuite/threading/ExitThread/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/threading/ExitThread/test3/{dllmain.c => dllmain.cpp} (100%) rename src/pal/tests/palsuite/threading/ExitThread/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/threading/GetCurrentProcess/test1/{process.c => process.cpp} (100%) rename src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/{processId.c => processId.cpp} (100%) rename src/pal/tests/palsuite/threading/GetCurrentThread/test1/{thread.c => thread.cpp} (100%) rename src/pal/tests/palsuite/threading/GetCurrentThread/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/{threadId.c => threadId.cpp} (100%) rename src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/{childProcess.c => childProcess.cpp} (100%) rename src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/{test1.c => test1.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/threading/GetProcessTimes/test2/test2.c create mode 100644 src/pal/tests/palsuite/threading/GetProcessTimes/test2/test2.cpp delete mode 100644 src/pal/tests/palsuite/threading/GetThreadTimes/test1/test1.c create mode 100644 src/pal/tests/palsuite/threading/GetThreadTimes/test1/test1.cpp rename src/pal/tests/palsuite/threading/OpenEventW/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/threading/OpenEventW/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/threading/OpenEventW/test3/{childprocess.c => childprocess.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/threading/OpenEventW/test3/test3.c create mode 100644 src/pal/tests/palsuite/threading/OpenEventW/test3/test3.cpp rename src/pal/tests/palsuite/threading/OpenEventW/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/threading/OpenEventW/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/threading/OpenProcess/test1/{childProcess.c => childProcess.cpp} (100%) rename src/pal/tests/palsuite/threading/OpenProcess/test1/{test1.c => test1.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/test1.c create mode 100644 src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/test1.cpp rename src/pal/tests/palsuite/threading/QueueUserAPC/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/threading/QueueUserAPC/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/threading/QueueUserAPC/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/threading/QueueUserAPC/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/threading/QueueUserAPC/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/threading/QueueUserAPC/test6/{test6.c => test6.cpp} (100%) rename src/pal/tests/palsuite/threading/QueueUserAPC/test7/{test7.c => test7.cpp} (100%) rename src/pal/tests/palsuite/threading/ReleaseMutex/test3/{ReleaseMutex.c => ReleaseMutex.cpp} (100%) rename src/pal/tests/palsuite/threading/ResetEvent/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/threading/ResetEvent/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/threading/ResetEvent/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/threading/ResetEvent/test4/{test4.c => test4.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/threading/ResumeThread/test1/test1.c create mode 100644 src/pal/tests/palsuite/threading/ResumeThread/test1/test1.cpp rename src/pal/tests/palsuite/threading/SetErrorMode/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/threading/SetEvent/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/threading/SetEvent/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/threading/SetEvent/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/threading/SetEvent/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/threading/Sleep/test1/{Sleep.c => Sleep.cpp} (100%) rename src/pal/tests/palsuite/threading/Sleep/test2/{sleep.c => sleep.cpp} (100%) rename src/pal/tests/palsuite/threading/SleepEx/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/threading/SleepEx/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/threading/SwitchToThread/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/threading/TLS/test1/{TLS.c => TLS.cpp} (100%) rename src/pal/tests/palsuite/threading/TLS/test2/{TLS.c => TLS.cpp} (100%) rename src/pal/tests/palsuite/threading/TLS/test3/{TLS.c => TLS.cpp} (100%) rename src/pal/tests/palsuite/threading/TLS/test4/{test4.c => test4.cpp} (100%) rename src/pal/tests/palsuite/threading/TLS/test5/{test5.c => test5.cpp} (100%) rename src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/{test.c => test.cpp} (100%) rename src/pal/tests/palsuite/threading/TerminateProcess/test1/{TerminateProcess.c => TerminateProcess.cpp} (100%) rename src/pal/tests/palsuite/threading/ThreadPriority/test1/{ThreadPriority.c => ThreadPriority.cpp} (100%) rename src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/{test2.c => test2.cpp} (100%) rename src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/{test3.c => test3.cpp} (100%) rename src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/{test4.c => test4.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/helper.c create mode 100644 src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/helper.cpp delete mode 100644 src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/test5.c create mode 100644 src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/test5.cpp delete mode 100644 src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/child6.c create mode 100644 src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/child6.cpp delete mode 100644 src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/test6.c create mode 100644 src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/test6.cpp rename src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/{WFSOExMutexTest.c => WFSOExMutexTest.cpp} (100%) rename src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/{WFSOExSemaphoreTest.c => WFSOExSemaphoreTest.cpp} (100%) rename src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/{WFSOExThreadTest.c => WFSOExThreadTest.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/WFSOMutexTest.c create mode 100644 src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/WFSOMutexTest.cpp rename src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/{ChildProcess.c => ChildProcess.cpp} (100%) rename src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/{WFSOProcessTest.c => WFSOProcessTest.cpp} (100%) delete mode 100644 src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/WFSOSemaphoreTest.c create mode 100644 src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/WFSOSemaphoreTest.cpp delete mode 100644 src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/WFSOThreadTest.c create mode 100644 src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/WFSOThreadTest.cpp rename src/pal/tests/palsuite/threading/WaitForSingleObject/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/threading/YieldProcessor/test1/{test1.c => test1.cpp} (100%) rename src/pal/tests/palsuite/threading/releasesemaphore/test1/{test.c => test.cpp} (100%) delete mode 100644 src/vm/gc.h create mode 100644 src/vm/gcheaputilities.cpp create mode 100644 src/vm/gcheaputilities.h create mode 100644 src/vm/gcinterface.h create mode 100644 src/vm/i386/asmhelpers.S create mode 100644 src/vm/i386/gmsasm.S create mode 100644 src/vm/i386/jithelp.S create mode 100644 src/vm/i386/umthunkstub.S create mode 100644 src/vm/i386/unixstubs.cpp create mode 100644 tests/debugger_tests/ConfigFilesGenerators/ConfigTemplate.txt create mode 100644 tests/debugger_tests/ConfigFilesGenerators/GenerateConfig.cmd create mode 100644 tests/debugger_tests/ConfigFilesGenerators/GenerateConfig.sh create mode 100644 tests/debugger_tests/ScriptGenerator/Program.cs create mode 100644 tests/debugger_tests/ScriptGenerator/project.json create mode 100644 tests/debugger_tests/setup-debuggertests.cmd create mode 100644 tests/debugger_tests/setup-debuggertests.sh delete mode 100644 tests/helix.targets create mode 100644 tests/scripts/arm64_post_build.py create mode 100755 tests/scripts/perf-prep.sh mode change 100644 => 100755 tests/scripts/run-xunit-perf.sh create mode 100644 tests/src/CLRTest.Jit.targets create mode 100644 tests/src/Common/build_against_pkg_dependencies/build_against_pkg_dependencies.csproj create mode 100644 tests/src/Common/build_against_pkg_dependencies/project.json create mode 100644 tests/src/Common/netcoreapp/project.json create mode 100644 tests/src/Common/targeting_pack_ref/project.json create mode 100644 tests/src/Common/targeting_pack_ref/targeting_pack_ref.csproj create mode 100644 tests/src/CoreMangLib/system/span/BasicSpanTest.cs create mode 100644 tests/src/GC/Stress/Tests/dir.targets create mode 100644 tests/src/JIT/CodeGenBringUpTests/Shift.cs create mode 100644 tests/src/JIT/CodeGenBringUpTests/Shift.csproj create mode 100644 tests/src/JIT/Directed/pinvoke/pinvoke-examples.cs create mode 100644 tests/src/JIT/Directed/pinvoke/pinvoke-examples.csproj create mode 100644 tests/src/JIT/Methodical/structs/valuetuple.cs create mode 100644 tests/src/JIT/Methodical/structs/valuetuple.csproj create mode 100644 tests/src/JIT/Performance/CodeQuality/Inlining/InlineGCStruct.cs create mode 100644 tests/src/JIT/Performance/CodeQuality/Inlining/InlineGCStruct.csproj create mode 100644 tests/src/JIT/Performance/CodeQuality/SIMD/SeekUnroll/SeekUnroll.cs create mode 100644 tests/src/JIT/Performance/CodeQuality/SIMD/SeekUnroll/SeekUnroll.csproj create mode 100755 tests/src/JIT/Performance/RunBenchmarks/RunBenchmarks.sh delete mode 100644 tests/src/JIT/Regression/CLR-x86-JIT/V2.0-RTM/b475589/b475589.il delete mode 100644 tests/src/JIT/Regression/CLR-x86-JIT/V2.0-RTM/b475589/b475589.ilproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_142976/DevDiv_142976.cs create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_142976/DevDiv_142976.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_255294/DevDiv_255294.cs create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_255294/DevDiv_255294.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_278365/DevDiv_278365.cs create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_278365/DevDiv_278365.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_278369/DevDiv_278369.il create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_278369/DevDiv_278369.ilproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_278371/DevDiv_278371.il create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_278371/DevDiv_278371.ilproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_278372/DevDiv_278372.il create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_278372/DevDiv_278372.ilproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_278375/DevDiv_278375.cs create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_278375/DevDiv_278375.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_278376/DevDiv_278376.cs create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_278376/DevDiv_278376.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_278523/DevDiv_278523.il create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_278523/DevDiv_278523.ilproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_278526/DevDiv_278526.cs create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_278526/DevDiv_278526.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_279396/DevDiv_279396.il create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_279396/DevDiv_279396.ilproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_279829/DevDiv_279829.il create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_279829/DevDiv_279829.ilproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_280120/DevDiv_280120.cs create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_280120/DevDiv_280120.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_280123/DevDiv_280123.cs create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_280123/DevDiv_280123.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_280127/DevDiv_280127.cs create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_280127/DevDiv_280127.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_283795/DevDiv_283795.cs create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_283795/DevDiv_283795.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_284785/DevDiv_284785.cs create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_284785/DevDiv_284785.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_288222/DevDiv_288222.cs create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_288222/DevDiv_288222.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_359734/DevDiv_359734.il create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_359734/DevDiv_359734.ilproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_359736/DevDiv_359736.cs create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_359736/DevDiv_359736_d.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_359736/DevDiv_359736_do.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_359736/DevDiv_359736_r.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/DevDiv_359736/DevDiv_359736_ro.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_7906/GitHub_7906.cs create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_7906/GitHub_7906.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_7907/GitHub_7907.cs create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_7907/GitHub_7907.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_8133/GitHub_8133.il create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_8133/GitHub_8133.ilproj create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_8170/GitHub_8170.cs create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_8170/GitHub_8170.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_8220/GitHub_8220.cs create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_8220/GitHub_8220.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_8231/GitHub_8231.cs create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_8231/GitHub_8231.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_8460/GitHub_8460.cs create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_8460/GitHub_8460.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_8599/GitHub_8599.cs create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_8599/GitHub_8599.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_CoreRT_2073/GitHub_CoreRT_2073.il create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_CoreRT_2073/GitHub_CoreRT_2073.ilproj delete mode 100644 tests/src/Loader/classloader/PrivateInterfaceImpl/Test2_NonFriendPriInterface.csproj delete mode 100644 tests/src/Loader/classloader/generics/Visibility/A_Types.csproj delete mode 100644 tests/src/Loader/classloader/generics/Visibility/B_Types.csproj create mode 100644 tests/src/baseservices/compilerservices/FixedAddressValueType/FixedAddressValueType.cs create mode 100644 tests/src/baseservices/compilerservices/FixedAddressValueType/FixedAddressValueType.csproj create mode 100644 tests/src/baseservices/compilerservices/RuntimeHelpers/ExecuteCodeWithGuaranteedCleanup.cs create mode 100644 tests/src/baseservices/compilerservices/RuntimeHelpers/ExecuteCodeWithGuaranteedCleanup.csproj create mode 100644 tests/src/baseservices/compilerservices/RuntimeWrappedException/RuntimeWrappedException.cs create mode 100644 tests/src/baseservices/compilerservices/RuntimeWrappedException/RuntimeWrappedException.csproj create mode 100644 tests/src/baseservices/compilerservices/RuntimeWrappedException/StringThrower.il create mode 100644 tests/src/baseservices/compilerservices/RuntimeWrappedException/StringThrower.ilproj create mode 100644 tests/src/baseservices/compilerservices/modulector/moduleCctor.il create mode 100644 tests/src/baseservices/compilerservices/modulector/moduleCctor.ilproj create mode 100644 tests/src/baseservices/compilerservices/modulector/runmoduleconstructor.cs create mode 100644 tests/src/baseservices/compilerservices/modulector/runmoduleconstructor.csproj create mode 100644 tests/src/jit/Directed/pinvoke/pinvoke-bug.cs create mode 100644 tests/src/jit/Directed/pinvoke/pinvoke-bug.csproj create mode 100644 tests/src/reflection/ldtoken/byrefs.il create mode 100644 tests/src/reflection/ldtoken/byrefs.ilproj create mode 100644 tests/x86/compatjit_x86_testenv.cmd create mode 100644 tests/x86/legacyjit_x86_testenv.cmd create mode 100755 verify-so.sh diff --git a/.gitignore b/.gitignore deleted file mode 100644 index b3ac01b..0000000 --- a/.gitignore +++ /dev/null @@ -1,306 +0,0 @@ -syntax: glob - -[Bb]inaries/ - -# Build tools related files -/[Tt]ools/ - -### VisualStudio ### - -# User-specific files -*.suo -*.user -*.userosscache -*.sln.docstates - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -build/ -bld/ -[Bb]in/ -[Oo]bj/ -msbuild.log - -# Visual Studio 2015 -.vs/ - -# Visual Studio 2015 Pre-CTP6 -*.sln.ide -*.ide/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -#NUNIT -*.VisualState.xml -TestResult.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.html -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db - -# Visual Studio profiler -*.psess -*.vsp -*.vspx - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# JustCode is a .NET coding addin-in -.JustCode - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# NCrunch -_NCrunch_* -.*crunch*.local.xml - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -*.pubxml -*.publishproj - -# NuGet Packages -*.nupkg -**/packages/* -project.lock.json - -# Windows Azure Build Output -csx/ -*.build.csdef - -# Windows Store app package directory -AppPackages/ - -# Others -sql/ -*.Cache -ClientBin/ -[Ss]tyle[Cc]op.* -~$* -*.dbmdl -*.dbproj.schemaview -*.pfx -*.publishsettings -node_modules/ -*.metaproj -*.metaproj.tmp -.atom-build.json -tags -TAGS - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -*.mdf -*.ldf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings - -# Microsoft Fakes -FakesAssemblies/ - -# C/C++ extension for Visual Studio Code -browse.VC.db - -# Local settings folder for Visual Studio Code -.vscode/ - -### MonoDevelop ### - -*.pidb -*.userprefs - -### Windows ### - -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msm -*.msp - -# Windows shortcuts -*.lnk - -# Common binary extensions on Windows -*.exe -*.dll -*.lib - -### Linux ### - -*~ -\#*\# - -# KDE directory preferences -.directory - -### OSX ### - -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - -# Thumbnails -._* - -# Files that might appear on external disk -.Spotlight-V100 -.Trashes - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -# We have some checked in prebuilt generated files -!src/pal/prebuilt/idl/*_i.c - -# Valid 'debug' folder, that contains CLR debugging code -!src/debug - -# Ignore folders created by the test build -TestWrappers_x64_[d|D]ebug -TestWrappers_x64_[c|C]hecked -TestWrappers_x64_[r|R]elease -TestWrappers_x86_[d|D]ebug -TestWrappers_x86_[c|C]hecked -TestWrappers_x86_[r|R]elease -TestWrappers_arm_[d|D]ebug -TestWrappers_arm_[c|C]hecked -TestWrappers_arm_[r|R]elease -TestWrappers_arm64_[d|D]ebug -TestWrappers_arm64_[c|C]hecked -TestWrappers_arm64_[r|R]elease -tests/src/common/test_runtime/project.json - -Vagrantfile -.vagrant - -# CMake files -CMakeFiles/ -cmake_install.cmake -CMakeCache.txt -Makefile - -# Cross compilation -cross/rootfs/* - -#python import files -*.pyc - -# JIT32 files -src/jit32 - -# performance testing sandbox -sandbox diff --git a/.gitmirror b/.gitmirror deleted file mode 100644 index f507630..0000000 --- a/.gitmirror +++ /dev/null @@ -1 +0,0 @@ -Only contents of this folder, excluding subfolders, will be mirrored by the Git-TFS Mirror. \ No newline at end of file diff --git a/.gitmirrorselective b/.gitmirrorselective new file mode 100644 index 0000000..e831038 --- /dev/null +++ b/.gitmirrorselective @@ -0,0 +1 @@ +src \ No newline at end of file diff --git a/BuildToolsVersion.txt b/BuildToolsVersion.txt index acf5f59..f271787 100644 --- a/BuildToolsVersion.txt +++ b/BuildToolsVersion.txt @@ -1 +1 @@ -1.0.26-prerelease-00719-02 \ No newline at end of file +1.0.27-prerelease-01008-01 \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index a257421..61c689b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,6 @@ include(functions.cmake) if (WIN32) message(STATUS "VS_PLATFORM_TOOLSET is ${CMAKE_VS_PLATFORM_TOOLSET}") message(STATUS "VS_PLATFORM_NAME is ${CMAKE_VS_PLATFORM_NAME}") - message(STATUS "VS_WINDOWS_TARGET_PLATFORM_VERSION is ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}") endif (WIN32) # Set commonly used directory names @@ -40,11 +39,19 @@ endif() # Ensure other tools are present if (WIN32) if(CLR_CMAKE_HOST_ARCH STREQUAL arm) + + # Confirm that Windows SDK is present + if(NOT DEFINED CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION OR CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION STREQUAL "" ) + message(FATAL_ERROR "Windows SDK is required for the Arm32 build.") + else() + message("Using Windows SDK version ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}") + endif() + # Explicitly specify the assembler to be used for Arm32 compile file(TO_CMAKE_PATH "$ENV{VCINSTALLDIR}\\bin\\x86_arm\\armasm.exe" CMAKE_ASM_COMPILER) set(CMAKE_ASM_MASM_COMPILER ${CMAKE_ASM_COMPILER}) - message(CMAKE_ASM_MASM_COMPILER explicitly set to: ${CMAKE_ASM_MASM_COMPILER}) + message("CMAKE_ASM_MASM_COMPILER explicitly set to: ${CMAKE_ASM_MASM_COMPILER}") # Enable generic assembly compilation to avoid CMake generate VS proj files that explicitly # use ml[64].exe as the assembler. @@ -94,9 +101,11 @@ else (WIN32) else (CMAKE_SYSTEM_NAME STREQUAL Darwin) # Ensure that objcopy is present - if (DEFINED ENV{CROSSCOMPILE}) + if (DEFINED ENV{CROSSCOMPILE} AND NOT DEFINED CLR_CROSS_COMPONENTS_BUILD) if (CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l OR CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64) find_program(OBJCOPY ${TOOLCHAIN}-objcopy) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL i686) + find_program(OBJCOPY objcopy) else() clr_unknown_arch() endif() @@ -113,25 +122,52 @@ endif(WIN32) #---------------------------------------- # Detect and set platform variable names -# - for non-windows build platform & architecture is detected using inbuilt CMAKE variables +# - for non-windows build platform & architecture is detected using inbuilt CMAKE variables and cross target component configure # - for windows we use the passed in parameter to CMAKE to determine build arch #---------------------------------------- if(CMAKE_SYSTEM_NAME STREQUAL Linux) set(CLR_CMAKE_PLATFORM_UNIX 1) - # CMAKE_SYSTEM_PROCESSOR returns the value of `uname -p`. - # For the AMD/Intel 64bit architecure two different strings are common. - # Linux and Darwin identify it as "x86_64" while FreeBSD and netbsd uses the - # "amd64" string. Accept either of the two here. - if(CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL amd64) - set(CLR_CMAKE_PLATFORM_UNIX_AMD64 1) - elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l) - set(CLR_CMAKE_PLATFORM_UNIX_ARM 1) - elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64) - set(CLR_CMAKE_PLATFORM_UNIX_ARM64 1) + if(CLR_CROSS_COMPONENTS_BUILD) + # CMAKE_HOST_SYSTEM_PROCESSOR returns the value of `uname -p` on host. + if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL x86_64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL amd64) + if(CLR_CMAKE_TARGET_ARCH STREQUAL "arm") + set(CLR_CMAKE_PLATFORM_UNIX_X86 1) + else() + set(CLR_CMAKE_PLATFORM_UNIX_AMD64 1) + endif() + elseif(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL i686) + set(CLR_CMAKE_PLATFORM_UNIX_X86 1) + else() + clr_unknown_arch() + endif() else() - clr_unknown_arch() + # CMAKE_SYSTEM_PROCESSOR returns the value of `uname -p` on target. + # For the AMD/Intel 64bit architecure two different strings are common. + # Linux and Darwin identify it as "x86_64" while FreeBSD and netbsd uses the + # "amd64" string. Accept either of the two here. + if(CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL amd64) + set(CLR_CMAKE_PLATFORM_UNIX_AMD64 1) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l) + set(CLR_CMAKE_PLATFORM_UNIX_ARM 1) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64) + set(CLR_CMAKE_PLATFORM_UNIX_ARM64 1) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL i686) + set(CLR_CMAKE_PLATFORM_UNIX_X86 1) + else() + clr_unknown_arch() + endif() endif() set(CLR_CMAKE_PLATFORM_LINUX 1) + + # Detect Alpine Linux + SET(OS_RELEASE_FILENAME "/etc/os-release") + if (EXISTS ${OS_RELEASE_FILENAME}) + file(READ ${OS_RELEASE_FILENAME} OS_RELEASE) + string(FIND "${OS_RELEASE}" "ID=alpine" CLR_CMAKE_PLATFORM_ALPINE_LINUX) + if(CLR_CMAKE_PLATFORM_ALPINE_LINUX EQUAL -1) + unset(CLR_CMAKE_PLATFORM_ALPINE_LINUX) + endif(CLR_CMAKE_PLATFORM_ALPINE_LINUX EQUAL -1) + endif(EXISTS ${OS_RELEASE_FILENAME}) endif(CMAKE_SYSTEM_NAME STREQUAL Linux) if(CMAKE_SYSTEM_NAME STREQUAL Darwin) @@ -190,27 +226,30 @@ endif(CMAKE_SYSTEM_NAME STREQUAL SunOS) #------------------------------------------------------------- # Set HOST architecture variables if(CLR_CMAKE_PLATFORM_UNIX_ARM) - set(CLR_CMAKE_PLATFORM_ARCH_ARM 1) - set(CLR_CMAKE_HOST_ARCH "arm") + set(CLR_CMAKE_PLATFORM_ARCH_ARM 1) + set(CLR_CMAKE_HOST_ARCH "arm") elseif(CLR_CMAKE_PLATFORM_UNIX_ARM64) - set(CLR_CMAKE_PLATFORM_ARCH_ARM64 1) - set(CLR_CMAKE_HOST_ARCH "arm64") + set(CLR_CMAKE_PLATFORM_ARCH_ARM64 1) + set(CLR_CMAKE_HOST_ARCH "arm64") elseif(CLR_CMAKE_PLATFORM_UNIX_AMD64) - set(CLR_CMAKE_PLATFORM_ARCH_AMD64 1) - set(CLR_CMAKE_HOST_ARCH "x64") -elseif(WIN32) - # CLR_CMAKE_HOST_ARCH is passed in as param to cmake - if (CLR_CMAKE_HOST_ARCH STREQUAL x64) set(CLR_CMAKE_PLATFORM_ARCH_AMD64 1) - elseif(CLR_CMAKE_HOST_ARCH STREQUAL x86) + set(CLR_CMAKE_HOST_ARCH "x64") +elseif(CLR_CMAKE_PLATFORM_UNIX_X86) set(CLR_CMAKE_PLATFORM_ARCH_I386 1) - elseif(CLR_CMAKE_HOST_ARCH STREQUAL arm) - set(CLR_CMAKE_PLATFORM_ARCH_ARM 1) - elseif(CLR_CMAKE_HOST_ARCH STREQUAL arm64) - set(CLR_CMAKE_PLATFORM_ARCH_ARM64 1) - else() - clr_unknown_arch() - endif() + set(CLR_CMAKE_HOST_ARCH "x86") +elseif(WIN32) + # CLR_CMAKE_HOST_ARCH is passed in as param to cmake + if (CLR_CMAKE_HOST_ARCH STREQUAL x64) + set(CLR_CMAKE_PLATFORM_ARCH_AMD64 1) + elseif(CLR_CMAKE_HOST_ARCH STREQUAL x86) + set(CLR_CMAKE_PLATFORM_ARCH_I386 1) + elseif(CLR_CMAKE_HOST_ARCH STREQUAL arm) + set(CLR_CMAKE_PLATFORM_ARCH_ARM 1) + elseif(CLR_CMAKE_HOST_ARCH STREQUAL arm64) + set(CLR_CMAKE_PLATFORM_ARCH_ARM64 1) + else() + clr_unknown_arch() + endif() endif() # Set TARGET architecture variables @@ -235,9 +274,9 @@ endif() # check if host & target arch combination are valid if(NOT(CLR_CMAKE_TARGET_ARCH STREQUAL CLR_CMAKE_HOST_ARCH)) - if(NOT((CLR_CMAKE_PLATFORM_ARCH_AMD64 AND CLR_CMAKE_TARGET_ARCH_ARM64) OR (CLR_CMAKE_PLATFORM_ARCH_I386 AND CLR_CMAKE_TARGET_ARCH_ARM))) - message(FATAL_ERROR "Invalid host and target arch combination") - endif() + if(NOT((CLR_CMAKE_PLATFORM_ARCH_AMD64 AND CLR_CMAKE_TARGET_ARCH_ARM64) OR (CLR_CMAKE_PLATFORM_ARCH_I386 AND CLR_CMAKE_TARGET_ARCH_ARM))) + message(FATAL_ERROR "Invalid host and target arch combination") + endif() endif() #----------------------------------------------------- @@ -265,10 +304,8 @@ if (WIN32) endforeach (Definition) endforeach (Config) - if(NOT CLR_CMAKE_PLATFORM_ARCH_ARM64) - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /guard:cf") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /guard:cf") - endif (NOT CLR_CMAKE_PLATFORM_ARCH_ARM64) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /guard:cf") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /guard:cf") # Incremental linking with CFG is broken until next VS release. # This needs to be appended to the last for each build type to override the default flag. @@ -278,7 +315,15 @@ if (WIN32) # # Disable the following line for UNIX altjit on Windows set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /MANIFEST:NO") #Do not create Side-by-Side Assembly Manifest - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SUBSYSTEM:WINDOWS,6.00") #windows subsystem + + if (CLR_CMAKE_PLATFORM_ARCH_ARM) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SUBSYSTEM:WINDOWS,6.02") #windows subsystem - arm minimum is 6.02 + elseif(CLR_CMAKE_PLATFORM_ARCH_ARM64) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SUBSYSTEM:WINDOWS,6.03") #windows subsystem - arm64 minimum is 6.03 + else () + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SUBSYSTEM:WINDOWS,6.01") #windows subsystem + endif () + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /LARGEADDRESSAWARE") # can handle addresses larger than 2 gigabytes set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /RELEASE") #sets the checksum in the header set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NXCOMPAT") #Compatible with Data Execution Prevention @@ -425,6 +470,9 @@ if (CLR_CMAKE_PLATFORM_UNIX) elseif(CLR_CMAKE_PLATFORM_UNIX_ARM64) message("Detected Linux ARM64") add_definitions(-DLINUX64) + elseif(CLR_CMAKE_PLATFORM_UNIX_X86) + message("Detected Linux i686") + add_definitions(-DLINUX32) else() clr_unknown_arch() endif() @@ -567,4 +615,4 @@ if(CLR_CMAKE_BUILD_TESTS) add_subdirectory(tests) endif(CLR_CMAKE_BUILD_TESTS) -include(definitionsconsistencycheck.cmake) \ No newline at end of file +include(definitionsconsistencycheck.cmake) diff --git a/Documentation/README.md b/Documentation/README.md index 7e29013..1a3906b 100644 --- a/Documentation/README.md +++ b/Documentation/README.md @@ -59,7 +59,7 @@ Book of the Runtime The Book of the Runtime is a set of chapters that go in depth into various interesting aspects of the design of the .NET Framework. -- [Book of the Runtime](botr/_tableOfContents.md) +- [Book of the Runtime](botr/README.md) For your convenience, here are a few quick links to popular chapters: diff --git a/Documentation/botr/_tableOfContents.md b/Documentation/botr/README.md similarity index 100% rename from Documentation/botr/_tableOfContents.md rename to Documentation/botr/README.md diff --git a/Documentation/botr/clr-abi.md b/Documentation/botr/clr-abi.md index cbd5fc9..caa5c7a 100644 --- a/Documentation/botr/clr-abi.md +++ b/Documentation/botr/clr-abi.md @@ -6,6 +6,8 @@ It describes requirements that the Just-In-Time (JIT) compiler imposes on the VM A note on the JIT codebases: JIT32 refers to the original JIT codebase that originally generated x86 code and was later ported to generate ARM code. Later, it was ported and re-architected to generate AMD64 code (making its name something of a confusing misnomer). This work is referred to as RyuJIT. RyuJIT is being ported to generate ARM64 code. JIT64 refers to the legacy codebase that supports AMD64. +CoreRT refers to https://github.com/dotnet/corert runtime that is optimized for AOT. The CoreRT ABI differs in a few details for simplicity and consistency across platforms. + # Getting started Read everything in the documented Windows ABI. @@ -289,6 +291,8 @@ On ARM and ARM64, for all second pass funclets (finally, fault, catch, and filte Catch, Filter, and Filter-handlers also get an Exception object (GC ref) as an argument (`REG_EXCEPTION_OBJECT`). On AMD64 it is the second argument and thus passed in RDX. On ARM and ARM64 this is the first argument and passed in R0. +CoreRT does not use PSPSym. For filter funclets the VM sets the frame register to be the same as the parent function. For second pass funclets the VM restores all non-volatile registers. The same convention is used across all platforms. + (Note that the JIT64 source code contains a comment that says, "The current CLR doesn't always pass the correct establisher frame to the funclet. Funclet may receive establisher frame of funclet when expecting that of original routine." It indicates this is the reason that a PSPSym is required in all funclets as well as the main function, whereas if the establisher frame was correctly reported, the PSPSym could be omitted in some cases.) ## Funclet Return Values @@ -468,7 +472,7 @@ Filters are invoked in the 1st pass of EH processing and as such execution might Duplicated clauses are a special set of entries in the EH tables to assist the VM. Specifically, if handler 'A' is also protected by an outer EH clause 'B', then the JIT must emit a duplicated clause, a duplicate of 'B', that marks the whole handler 'A' (which is now lexically disjoint for the range of code for the corresponding try body 'A') as being protected by the handler for 'B'. -Duplicated clauses are not needed for x86. +Duplicated clauses are not needed for x86 and for CoreRT ABI. During exception dispatch the VM uses these duplicated clauses to know when to skip any frames between the handler and its parent function. After skipping to the parent function, due to a duplicated clause, the VM searches for a regular/non-duplicate clause in the parent function. The order of duplicated clauses is important. They should appear after all of the main function clauses. They should still follow the normal sorting rules (inner-to-outer, top-to-bottom), but because the try-start/try-end will all be the same for a given handler, they should maintain the ordering, regarding inner-to-outer, as the corresponding original clause. diff --git a/Documentation/botr/exceptions.md b/Documentation/botr/exceptions.md index daa684b..8e4b77a 100644 --- a/Documentation/botr/exceptions.md +++ b/Documentation/botr/exceptions.md @@ -278,10 +278,16 @@ To use the callout filter, instead of this: write this: BOOL OneShot = TRUE; - - PAL_TRY + struct Param { + BSTR* pBSTR; + int length; + }; + struct Param param; + param.pBSTR = pBSTR; + + PAL_TRY(Param*, pParam, ¶m) { - length = SysStringLen(pBSTR); + pParam->length = SysStringLen(pParam->pBSTR); } PAL_EXCEPT_FILTER(CallOutFilter, &OneShot) { diff --git a/Documentation/botr/garbage-collection.md b/Documentation/botr/garbage-collection.md index 9e16131..789c4e9 100644 --- a/Documentation/botr/garbage-collection.md +++ b/Documentation/botr/garbage-collection.md @@ -2,7 +2,7 @@ Garbage Collection Design ========================= Author: Maoni Stephens ([@maoni0](https://github.com/maoni0)) - 2015 -Note: See the The Garbage Collection Handbook referenced in the resources section at the end of this document to learn more about garbage collection topics. +Note: See _The Garbage Collection Handbook_ (referenced in the resources section at the end of this document) to learn more about garbage collection topics. Component Architecture ====================== diff --git a/Documentation/building/crossgen.md b/Documentation/building/crossgen.md index c74a5e6..bf013e2 100644 --- a/Documentation/building/crossgen.md +++ b/Documentation/building/crossgen.md @@ -7,7 +7,7 @@ Introduction When you create a .NET assembly using C# compiler, your assembly contains only MSIL code. When the app runs, the JIT compiler translates the MSIL code into native code, before the CPU can execute them. This execution model has some advantages. For example, your assembly code can be portable across all platforms and architectures that support .NET Core. -However, this portability comes with a performance penalty. Your app starts up slower, because the JIT compiler has to spend time to translate the code. +However, this portability comes with a performance cost. Your app starts up more slowly, because the JIT compiler has to spend time to translate the code. To help make your app start up faster, CoreCLR includes a tool called CrossGen, which can pre-compile the MSIL code into native code. @@ -18,7 +18,7 @@ If you build CoreCLR yourself, the CrossGen tool (`crossgen.exe` on Windows, or If you install CoreCLR using a NuGet package, you can find CrossGen in the `tools` folder of the NuGet package. Regardless of how you obtain CrossGen, it is very important that it must match other CoreCLR binaries. -- If you build CrossGen yourself, you should use it with coreclr and mscorlib generated from the same build. Do not attempt to mix CrossGen from one build with binaries generated from another build. +- If you build CrossGen yourself, you should use it with runtime and `System.Private.CoreLib.dll` generated from the same build. Do not attempt to mix CrossGen from one build with binaries generated from another build. - If you install CrossGen from NuGet, make sure you use CrossGen from exactly the same NuGet package as the rest of your CoreCLR binaries. Do not attempt to mix binaries from multiple NuGet packages. If you do not follow the above rules, you are likely to encounter errors while running CrossGen. @@ -26,26 +26,30 @@ If you do not follow the above rules, you are likely to encounter errors while r Using CrossGen -------------- -In most cases, the build script automatically runs CrossGen to create the native image for mscorlib. -When this happens, you will find both `mscorlib.dll` and `mscorlib.ni.dll` in your output directory. -`mscorlib.dll` is the MSIL assembly created by the C# compiler, while `mscorlib.ni.dll` is the native image that contains CPU-specific code. -Once the build is done, you only need `mscorlib.ni.dll` to use CoreCLR. -As a matter of fact, most CoreCLR NuGet packages contain only `mscorlib.ni.dll`, without `mscorlib.dll` +In most cases, the build script automatically runs CrossGen to create the native image for `System.Private.CoreLib.dll` and `mscorlib.dll`. +When this happens, you will find `System.Private.CoreLib.ni.dll` and `mscorlib.ni.dll` in your output directory. +`System.Private.CoreLib.dll` and `mscorlib.dll` are the MSIL assemblies created by the C# compiler, while `System.Private.CoreLib.ni.dll` and `mscorlib.ni.dll` are the native images that contain CPU-specific code. +Once the build is done, you only need `System.Private.CoreLib.ni.dll` and `mscorlib.ni.dll` to use CoreCLR. +The original MSIL assemblies are no longer needed by the runtime. -If for some reason you did not get `mscorlib.ni.dll` with the rest of your CoreCLR, you can easily create it yourself using CrossGen. -First, make sure you have `crossgen.exe` (on Windows) or `crossgen` (other platforms) in the same directory as `mscorlib.dll`. -Then, run one of the following two commands (first command for Windows, second command for other platforms): +If you installed CoreCLR from a NuGet package, `System.Private.CoreLib.ni.dll` and `mscorlib.ni.dll` are included in the package. +If for some reason you did not get `System.Private.CoreLib.dll` or `mscorlib.ni.dll` with the rest of your CoreCLR, you can easily create it yourself using CrossGen. + +If your `System.Private.CoreLib.dll`, `mscorlib.dll` and JIT compiler (`clrjit.dll` on Windows or `libclrjit.*` on other platforms) are all in the same directory as CrossGen itself, you can compile `System.Private.CoreLib.dll` and `mscorlib.dll` with the following commands (first two commands for Windows, next two commands for other platforms): + + .\crossgen.exe System.Private.CoreLib.dll .\crossgen.exe mscorlib.dll + ./crossgen System.Private.CoreLib.dll ./crossgen mscorlib.dll -To create native images for other assemblies, the command line is slightly more complex: +If your files are scattered in different directories, or if you want to create native images for other assemblies, the command line is slightly more complex: - .\crossgen.exe /Platform_Assemblies_Paths "path1;path2;..." assemblyName.dll - ./crossgen /Platform_Assemblies_Paths "path1:path2:..." assemblyName.dll + .\crossgen.exe /JITPath path\clrjit.dll /Platform_Assemblies_Paths "path1;path2;..." path\assemblyName.dll + ./crossgen -JITPath path/libclrjit.so -Platform_Assemblies_Paths "path1:path2:..." path/assemblyName.dll -The /Platform_Assemblies_Paths is used to specify the location of all the dependencies of the input assembly. -You should use full paths for this locations. Relative paths do not always work. +The /Platform_Assemblies_Paths is used to specify the locations of all the dependencies of the input assembly, including the input assembly itself. +You should use full paths for these locations. Relative paths do not always work. If there are multiple paths, separate them with semicolons (`;`) on Windows, or colons (`:`) on non-Windows platforms. It is generally a good idea to enclose the path list in quotes to protect any special characters from the shell. @@ -53,14 +57,13 @@ Using native images ------------------- Running CrossGen on an assembly creates a "native image" file, with the extension of `.ni.dll` or `.ni.exe`. -You should include the native images in your app, at the same location where you normally install the MSIL assemblies. -Once you have included native images, you do not need to include the original MSIL assemblies in your apps. +You should include the native images in your app, either by replacing the original MSIL assmblies with the native images, or by putting the native images next to the MSIL assemblies. +When the native images are present, CoreCLR runtime will automatically use it instead of the original MSIL assemblies. Common errors ------------- The following are some of the command errors while creating or using native images: -- "Could not load file or assembly 'mscorlib.dll' or one of its dependencies. The native image could not be loaded, because it was generated for use by a different version of the runtime. (Exception from HRESULT: 0x80131059)": This error indicates that there is a mismatch between CrossGen and mscorlib.ni.dll. Make sure to use CrossGen and mscorlib.ni.dll from the same build or NuGet package. - "Error: Could not load file or assembly '...' or one of its dependencies. The system cannot find the file specified. (Exception from HRESULT: 0x80070002)": CrossGen wasn't able to find a particular dependency that it needs. Verify that you have the assembly specified in the error message, and make sure its location is included in `/Platform_Assemblies_Paths`. -- CoreCLR unable to initialize: While there are many possible causes of this error, one possibility is a mismatch between mscorlib.ni.dll and coreclr.dll (or libcoreclr.so). Make sure they come from the same build or NuGet package. -- "Unable to load Jit Compiler": Please get a copy of `clrjit.dll` (or `libclrjit.so` or `libclrjit.dylib`, depending on your platform), and place it in the same directory as CrossGen. You can either build `clrjit.dll` yourself, or get it from `Microsoft.NETCore.Jit` NuGet package. To avoid possible issues, please use `clrjit.dll` from the same build as `crossgen.exe` if possible. +- CoreCLR unable to initialize: While there are many possible causes of this error, one possibility is a mismatch between System.Private.CoreLib.ni.dll and coreclr.dll (or libcoreclr.so). Make sure they come from the same build or NuGet package. +- "Unable to load Jit Compiler": Please get a copy of `clrjit.dll` (or `libclrjit.so` or `libclrjit.dylib`, depending on your platform), and place it in the same directory as CrossGen (or use /JITPath option). You can either build `clrjit.dll` yourself, or get it from `Microsoft.NETCore.Jit` NuGet package. To avoid possible issues, please use `clrjit.dll` from the same build as `crossgen.exe` if possible. diff --git a/Documentation/building/linux-instructions.md b/Documentation/building/linux-instructions.md index c948ecd..ddd4274 100644 --- a/Documentation/building/linux-instructions.md +++ b/Documentation/building/linux-instructions.md @@ -47,6 +47,10 @@ ellismg@linux:~$ sudo apt-get install cmake llvm-3.5 clang-3.5 lldb-3.6 lldb-3.6 You now have all the required components. +If you are using Fedora 23 or 24, then you will need to install the following packages: + +`$ sudo dnf install llvm cmake clang lldb-devel libunwind-devel lttng-ust-devel libuuid-devel libicu-devel` + Git Setup --------- @@ -57,6 +61,10 @@ Set the maximum number of file-handles To ensure that your system can allocate enough file-handles for the corefx build run `sysctl fs.file-max`. If it is less than 100000, add `fs.file-max = 100000` to `/etc/sysctl.conf`, and then run `sudo sysctl -p`. +On Fedora 23 or 24: + +`$ sudo dnf install mono-devel` + Build the Runtime and Microsoft Core Library ============================================= diff --git a/Documentation/building/osx-instructions.md b/Documentation/building/osx-instructions.md index 6d3469b..9e6b913 100644 --- a/Documentation/building/osx-instructions.md +++ b/Documentation/building/osx-instructions.md @@ -51,7 +51,25 @@ The CoreFX cryptography libraries are built on OpenSSL. The version of OpenSSL i ```sh brew install openssl -brew link --force openssl + +# We need to make the runtime libraries discoverable, as well as make +# pkg-config be able to find the headers and current ABI version. +# +# Ensure the paths we will need exist +mkdir -p /usr/local/lib/pkgconfig + +# The rest of these instructions assume a default Homebrew path of +# /usr/local/opt/, with /usr/local being the answer to +# `brew --prefix`. +# +# Runtime dependencies +ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/ +ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/ + +# Compile-time dependences (for pkg-config) +ln -s /usr/local/opt/openssl/lib/pkgconfig/libcrypto.pc /usr/local/lib/pkgconfig/ +ln -s /usr/local/opt/openssl/lib/pkgconfig/libssl.pc /usr/local/lib/pkgconfig/ +ln -s /usr/local/opt/openssl/lib/pkgconfig/openssl.pc /usr/local/lib/pkgconfig/ ``` Build the Runtime and Microsoft Core Library diff --git a/Documentation/building/testing-with-corefx.md b/Documentation/building/testing-with-corefx.md index 6609a0a..4f9886f 100644 --- a/Documentation/building/testing-with-corefx.md +++ b/Documentation/building/testing-with-corefx.md @@ -7,7 +7,11 @@ It may be valuable to use CoreFX tests to validate your changes to CoreCLR or ms As part of building tests, CoreFX restores a copy of the runtime from myget, in order to update the runtime that is deployed, a special build property `BUILDTOOLS_OVERRIDE_RUNTIME` can be used. If this is set, the CoreFX testing targets will copy all the files in the folder it points to into the test folder, overwriting any files that exist. -To run tests, follow the procedure for [running tests in CoreFX](https://github.com/dotnet/corefx/blob/master/Documentation/building/windows-instructions.md). You can pass `/p:BUILDTOOLS_OVERRIDE_RUNTIME=\bin\Product\Windows_NT.x64.Release` to build.cmd to set this property. +To run tests, follow the procedure for [running tests in CoreFX](https://github.com/dotnet/corefx/blob/master/Documentation/building/windows-instructions.md). You can pass `/p:BUILDTOOLS_OVERRIDE_RUNTIME=\bin\Product\Windows_NT.x64.Release` to build.cmd to set this property, e.g. (note the space between the "--" and the "/p" option): + +``` +build.cmd -Release -- /p:BUILDTOOLS_OVERRIDE_RUNTIME=\bin\Product\Windows_NT.x64.Checked +``` **FreeBSD, Linux, NetBSD, OS X** diff --git a/Documentation/building/viewing-jit-dumps.md b/Documentation/building/viewing-jit-dumps.md index 5303b47..607c5e6 100644 --- a/Documentation/building/viewing-jit-dumps.md +++ b/Documentation/building/viewing-jit-dumps.md @@ -35,7 +35,7 @@ The first thing we want to do is setup the .NET Core app we want to dump. Here a } ``` -You can find a list of RIDs and their corresponding OSes [here](http://dotnet.github.io/docs/core-concepts/rid-catalog.html). +You can find a list of RIDs and their corresponding OSes [here](https://docs.microsoft.com/en-us/dotnet/articles/core/rid-catalog). * Edit `Program.cs`, and call the method(s) you want to dump in there. Make sure they are, directly or indirectly, called from `Main`. In this example, we'll be looking at the disassembly of our custom function `InefficientJoin`: diff --git a/Documentation/building/windows-instructions.md b/Documentation/building/windows-instructions.md index f68ed2c..8ba021b 100644 --- a/Documentation/building/windows-instructions.md +++ b/Documentation/building/windows-instructions.md @@ -1,21 +1,19 @@ Build CoreCLR on Windows ======================== -These instructions will lead you through building CoreCLR and running a "Hello World" demo on Windows. +These instructions will lead you through building CoreCLR. -Environment -=========== +---------------- +#Environment You must install several components to build the CoreCLR and CoreFX repos. These instructions were tested on Windows 7+. -Visual Studio -------------- +## Visual Studio Visual Studio must be installed. Supported versions: +- [Visual Studio 2015](https://www.visualstudio.com/downloads/visual-studio-2015-downloads-vs) (Community, Professional, Enterprise). The community version is completely free. -- [Visual Studio 2015](https://www.visualstudio.com/downloads/visual-studio-2015-downloads-vs) (Community, Professional, Enterprise) - -To debug managed code, ensure you have installed atleast [Visual Studio 2015 Update 3](https://www.visualstudio.com/en-us/news/releasenotes/vs2015-update3-vs). +To debug managed code, ensure you have installed at least [Visual Studio 2015 Update 3](https://www.visualstudio.com/en-us/news/releasenotes/vs2015-update3-vs). Make sure that you install "VC++ Tools". By default, they will not be installed. @@ -23,166 +21,100 @@ To build for Arm32, you need to have [Windows SDK for Windows 10](https://develo Visual Studio Express is not supported. -CMake ------ +##CMake The CoreCLR repo build has been validated using CMake 3.5.2. - Install [CMake](http://www.cmake.org/download) for Windows. -- Add it to the PATH environment variable. +- Add its location (e.g. C:\Program Files (x86)\CMake\bin) to the PATH environment variable. + The installation script has a check box to do this, but you can do it yourself after the fact + following the instructions at [Adding to the Default PATH variable](#adding-to-the-default-path-variable) + + +##Python -Python ---------- Python is used in the build system. We are currently using python 2.7.9, although any recent (2.4+) version of Python should work, including Python 3. - Install [Python](https://www.python.org/downloads/) for Windows. -- Add it to the PATH environment variable. - -PowerShell ----------- -PowerShell is used in the build system. Ensure that it is accessible via the PATH environment variable. Typically this is %SYSTEMROOT%\System32\WindowsPowerShell\v1.0\. +- Add its location (e.g. C:\Python*\) to the PATH environment variable. + The installation script has a check box to do this, but you can do it yourself after the fact + following the instructions at [Adding to the Default PATH variable](#adding-to-the-default-path-variable) -Powershell version must be 3.0 or higher. This should be the case for Windows 8 and later builds. -- Windows 7 SP1 can install Powershell version 4 [here](https://www.microsoft.com/en-us/download/details.aspx?id=40855). +##Git -Git Setup ---------- +For actual user operations, it is often more convinient to use the GIT features built into Visual Studio 2015. +However the CoreCLR and the tests use the GIT command line utilities directly so you need to install them +for these to work properly. You can get it from -Clone the CoreCLR and CoreFX repositories (either upstream or a fork). +- Install [Git For Windows](https://git-for-windows.github.io/) +- Add its location (e.g. C:\Program Files\Git\cmd) to the PATH environment variable. + The installation script has a check box to do this, but you can do it yourself after the fact + following the instructions at [Adding to the Default PATH variable](#adding-to-the-default-path-variable) -```bat -C:\git>git clone https://github.com/dotnet/coreclr -C:\git>git clone https://github.com/dotnet/corefx -``` +##PowerShell +PowerShell is used in the build system. Ensure that it is accessible via the PATH environment variable. +Typically this is %SYSTEMROOT%\System32\WindowsPowerShell\v1.0\. -This guide assumes that you've cloned the CoreCLR and CoreFX repositories into C:\git using the default repo names. If your setup is different, you'll need to pay attention to the commands you run. The guide will always show you the current directory. +Powershell version must be 3.0 or higher. This should be the case for Windows 8 and later builds. +- Windows 7 SP1 can install Powershell version 4 [here](https://www.microsoft.com/en-us/download/details.aspx?id=40855). -The repository is configured to allow Git to make the right decision about handling CRLF. Specifically, if you are working on **Windows**, please ensure that **core.autocrlf** is set to **true**. On **non-Windows** platforms, please set it to **input**. +##DotNet Core SDK +While not strictly needed to build or tests the .NET Core repository, having the .NET Core SDK installed lets +you use the dotnet.exe command to run .NET Core applications in the 'normal' way. We use this in the +[Using Your Build](Documentation/workflow/UsingYourBuild.md) instructions. Visual Studio 2015 (update 3) should have +installed the .NET Core SDK, but in case it did not you can get it from the [Installing the .Net Core SDK](https://www.microsoft.com/net/core) page. -Demo directory --------------- +##Adding to the default PATH variable -In order to keep everything tidy, create a new directory for the files that you will build or acquire. +The commands above need to be on your command lookup path. Some installers will automatically add them to +the path as part of installation, but if not here is how you can do it. -```bat -c:\git>mkdir \coreclr-demo\runtime -c:\git>mkdir \coreclr-demo\ref +You can of course add a directory to the PATH environment variable with the syntax +``` + set PATH=%PATH%;DIRECTORY_TO_ADD_TO_PATH ``` +However the change above will only last until the command windows closes. You can make your change to +the PATH variable persistent by going to Control Panel -> System And Security -> System -> Advanced system settings -> Environment Variables, +and select the 'Path' variable in the 'System variables' (if you want to change it for all users) or 'User variables' (if you only want +to change it for the currnet user). Simply edit the PATH variable's value and add the directory (with a semicolon separator). -Build the Runtime -================= +------------------------------------- +#Building -To build CoreCLR, run `build.cmd` from the root of the coreclr repository. This will do a x64/Debug build of CoreCLR, its native components, mscorlib.dll, and the tests. +Once all the necessary tools are in place, building is trivial. Simply run build build.cmd script that lives at +the base of the repository. - C:\git\coreclr>build -rebuild +```bat + .\build [Lots of build spew] - Repo successfully built. - Product binaries are available at C:\git\coreclr\bin\Product\Windows_NT.x64.debug Test binaries are available at C:\git\coreclr\bin\tests\Windows_NT.x64.debug +``` -**Note:** To avoid building the tests, pass the 'skiptestbuild' option to build. - -**build -?** will list supported parameters. - -Check the build output. +As shown above the product will be placed in - Product binaries will be dropped in `bin\Product\..` folder. - A NuGet package, Microsoft.Dotnet.CoreCLR, will be created under `bin\Product\..\.nuget` folder. - Test binaries will be dropped under `bin\Tests\..` folder -You will see several files. The interesting ones are: - -- `corerun`: The command line host. This program loads and starts the CoreCLR runtime and passes the managed program you want to run to it. -- `coreclr.dll`: The CoreCLR runtime itself. -- `mscorlib.dll`: The core managed library for CoreCLR, which contains all of the fundamental data types and functionality. - -Copy these files into the demo directory. - -```bat -C:\git\coreclr>copy bin\Product\Windows_NT.x64.debug\clrjit.dll \coreclr-demo\runtime -C:\git\coreclr>copy bin\Product\Windows_NT.x64.debug\CoreRun.exe \coreclr-demo\runtime -C:\git\coreclr>copy bin\Product\Windows_NT.x64.debug\coreclr.dll \coreclr-demo\runtime -C:\git\coreclr>copy bin\Product\Windows_NT.x64.debug\mscorlib.dll \coreclr-demo\runtime -C:\git\coreclr>copy bin\Product\Windows_NT.x64.debug\System.Private.CoreLib.dll \coreclr-demo\runtime -``` - -Build the Framework -=================== - -Build the framework out of the corefx directory. +By default build generates a 'Debug' build type, that has extra checking (assert) compiled into it. You can +also build the 'release' version which does not have these checks - c:\git\corefx>build.cmd +The build places logs in `bin\Logs` and these are useful when the build fails. - [Lots of build spew] - - 0 Warning(s) - 0 Error(s) - Time Elapsed 00:03:14.53 - Build Exit Code = 0 - -It's also possible to add -rebuild to build.cmd to force it to delete the previously built assemblies. - -For the purposes of this demo, you need to copy a few required assemblies to the demo folder. - -```bat -C:\git\corefx>copy bin\Windows_NT.AnyCPU.Debug\System.Console\System.Console.dll \coreclr-demo\runtime -C:\git\corefx>copy bin\Windows_NT.AnyCPU.Debug\System.Diagnostics.Debug\System.Diagnostics.Debug.dll \coreclr-demo\runtime -C:\git\corefx>copy bin\AnyOS.AnyCPU.Debug\System.IO\System.IO.dll \coreclr-demo\runtime -C:\git\corefx>copy bin\AnyOS.AnyCPU.Debug\System.IO.FileSystem.Primitives\System.IO.FileSystem.Primitives.dll \coreclr-demo\runtime -C:\git\corefx>copy bin\AnyOS.AnyCPU.Debug\System.Runtime\System.Runtime.dll \coreclr-demo\runtime -C:\git\corefx>copy bin\AnyOS.AnyCPU.Debug\System.Runtime.InteropServices\System.Runtime.InteropServices.dll \coreclr-demo\runtime -C:\git\corefx>copy bin\AnyOS.AnyCPU.Debug\System.Text.Encoding\System.Text.Encoding.dll \coreclr-demo\runtime -C:\git\corefx>copy bin\AnyOS.AnyCPU.Debug\System.Text.Encoding.Extensions\System.Text.Encoding.Extensions.dll \coreclr-demo\runtime -C:\git\corefx>copy bin\AnyOS.AnyCPU.Debug\System.Threading\System.Threading.dll \coreclr-demo\runtime -C:\git\corefx>copy bin\AnyOS.AnyCPU.Debug\System.Threading.Tasks\System.Threading.Tasks.dll \coreclr-demo\runtime -``` - -You also need to copy reference assemblies, which will be used during compilation. - -```bat -C:\git\corefx>copy bin\ref\System.Runtime\4.0.0.0\System.Runtime.dll \coreclr-demo\ref -C:\git\corefx>copy bin\ref\System.Console\4.0.0.0\System.Console.dll \coreclr-demo\ref -``` - -Compile the Demo -================ +The build places all of its output in the `bin` directory, so if you remove that directory you can force a +full rebuild. -Now you need a Hello World application to run. You can write your own, if you'd like. Here's a very simple one: +Build has a number of options that you can learn about using build -?. Some of the more important options are -```C# -using System; + * skiptests - don't build the tests. This can shorten build times quite a bit, but means you can't run tests. + * release - build the 'Release' build type that does not have extra development-time checking compiled in. + * -rebuild - force the build not to be incremental but to recompile everything. + You want this if you are going to do performance testing on your build. -public class Program -{ - public static void Main() - { - Console.WriteLine("Hello, Windows"); - Console.WriteLine("Love from CoreCLR."); - } -} -``` - -Personally, I'm partial to the one on corefxlab which will print a picture for you. Download the [corefxlab demo](https://raw.githubusercontent.com/dotnet/corefxlab/master/demos/CoreClrConsoleApplications/HelloWorld/HelloWorld.cs) to `\coreclr-demo`. - -Then you just need to build it, with csc, the .NET Framework C# compiler. It may be easier to do this step within the "Developer Command Prompt for VS2015", if csc is not in your path. Because you need to compile the app against the .NET Core surface area, you need to pass references to the contract assemblies you restored using NuGet: - -```bat -csc /nostdlib /noconfig /r:ref\System.Runtime.dll /r:ref\System.Console.dll /out:runtime\hello.exe hello.cs -``` - -Run the demo -============ - -You're ready to run Hello World! To do that, run corerun, passing the path to the managed exe, plus any arguments. In this case, no arguments are necessary. - -```bat -C:\coreclr-demo>cd runtime -C:\coreclr-demo\runtime>CoreRun.exe hello.exe -``` +See [Using Your Build](../workflow/UsingYourBuild.md) for instructions on running code with your build. -If `CoreRun.exe` fails for some reason, you will see an empty output. To diagnose the issue, you can use `/v` to switch verbose mode on: `CoreRun.exe /v hello.exe`. +See [Running Tests](../workflow/RunningTests.md) for instructions on running the tests. -Over time, this process will get easier. Thanks for trying out CoreCLR. Feel free to try a more interesting demo. diff --git a/Documentation/coding-guidelines/clr-code-guide.md b/Documentation/coding-guidelines/clr-code-guide.md index 84ba5f2..c1f69b0 100644 --- a/Documentation/coding-guidelines/clr-code-guide.md +++ b/Documentation/coding-guidelines/clr-code-guide.md @@ -27,7 +27,7 @@ Written in 2006, by: * [2.1.10 How to know if a function can trigger a GC](#2.1.10) * [2.1.10.1 GC_NOTRIGGER/TRIGGERSGC on a scope](#2.1.10.1) * [2.2 Are you using holders to track your resources?](#2.2) - * [2.2.1 What are holders and we are they important?](#2.2.1) + * [2.2.1 What are holders and why are they important?](#2.2.1) * [2.2.2 An example of holder usage:](#2.2.2) * [2.2.3 Common Features of Holders](#2.2.3) * [2.2.4 Where do I find a holder?](#2.2.4) @@ -462,7 +462,7 @@ One difference between the standalone TRIGGERSGC and the contract GC_TRIGGERS: t ## 2.2 Are you using holders to track your resources? -### 2.2.1 What are holders and we are they important? +### 2.2.1 What are holders and why are they important? The CLR team has coined the name **holder** to refer to the infrastructure that encapsulates the common grunt work of writing robust **backout code**. **Backout code** is code that deallocate resources or restore CLR data structure consistency when we abort an operation due to an error or an asynchronous event. Oftentimes, the same backout code will execute in non-error paths for resources allocated for use of a single scope, but error-time backout is still needed even for longer lived resources. @@ -616,6 +616,7 @@ Holders consistently release on destruction – that's their whole purpose. Sadl #### 2.2.8.4 Critical Section Holder **Wrong:** + pCrst->Enter(); pCrst->Leave(); diff --git a/Documentation/design-docs/multi-reg-call-nodes.md b/Documentation/design-docs/multi-reg-call-nodes.md new file mode 100644 index 0000000..e89ca2a --- /dev/null +++ b/Documentation/design-docs/multi-reg-call-nodes.md @@ -0,0 +1,230 @@ +Support for multiple destination regs, GT_CALL and GT_RETURN nodes that return a value in multiple registers: +============================================================================================================ + +The following targets allow a GT_CALL/GT_RETURN node to return a value in more than one register: + +x64 Unix: +Structs of size betwee 9-16 bytes will be returned in RAX/RDX and/or XMM0/XMM1. + +Arm64: +HFA structs will be returned in 1-4 successive VFP registers s0-s3 or d0-d3. +Structs of size 16-bytes will be returned in two return registers. + +Arm32: +Long type value is returned in two return registers r0 and r1. +HFA structs will be returned in 1-4 successive VFP registers s0-s3 or d0-d3 + +x86: +Long type value is returned in two return registers EDX and EAX. + +Legacy backend used reg-pairs for representing long return value on 32-bit targets, which makes reg allocation and codegen complex. Also this approach doesn't scale well to types that are returned in more than 2 registers. Arm32 HFA support in Legacy backend requires that HFA return value of a call is always stored to local in memory and with the local marked as not promotable. Original implementation of multi-reg return of structs on x64 Unix was similar to Arm32 and further LSRA was not ware of multi-reg call nodes because of which Codegen made some assumptions (e.g. multi-reg return value of a call node is never spilled) that are not always guaranteed. + +This doc proposes new IR forms and an implementation design to support multi-reg call nodes in RyuJIT that is scalable without the limitations/complexity that Legacy backend implementation had. + +Post Importation IR Forms +------------------------- +In importer any call returning a (struct or long type) value in two or more registers is forced to a temp +and temp is used in place of call node subsequently in IR. Note that creation of 'tmp' is avoided if return value of call is getting assigned to a local in IL. + +``` +// tmp = GT_CALL, where tmp is of TYP_STRUCT or TYP_LONG +GT_ASG(TYP_STRUCT or TYP_LONG, tmp, GT_CALL node) +``` + +Similarly importer will force IR of GT_RETURN node returning a value in multiple return registers to be +of the following form if operand of GT_RETURN is anything but a lclVar. + +``` +GT_ASG(TYP_STRUCT or TYP_LONG, tmp, op1) +GT_RETURN(tmp) +``` + +Post struct promotion IR forms +------------------------------ +Before global morph of basic blocks, struct promotion takes place. It will give rise to the following +three cases: + +Case 1: +tmp is not struct promoted or Type Dependently Promoted (P-DEP). + +Case 2: +tmp is Type Independently Promoted (P-INDEP) but its field layout doesn't match the layout of return registers or tmp is P-FULL promoted struct (e.g. SIMD type structs). + +For example, tmp could be a struct of 4 integers. But on x64 unix, two fields of such a struct +will be returned in one 8-byte return register. + +Case 3: +tmp is P-INDEP promoted and its field layout matches the layout of return registers. That is one promoted field will get mapped to a single, un-shared register in the ABI for returning values. +An example is a struct containing two fields of `{TYP_REF, TYP_DOUBLE} `on X64 Unix. + +Post Global Morph, IR forms of tmp=GT_CALL where tmp is of TYP_STRUCT +--------------------------------------------------------------------- +Case 3 is morphed into + + `GT_STORE_MULTI_VAR(TYP_STRUCT, , op1 = GT_CALL)` + + Where FieldLcl[1..4] are lcl numbers of P-INDEP promoted fields of tmp. The limit of 2-4 locals + is statically dependent on target platform/architecture. + + GT_STORE_MULTI_VAR is a new GenTree node to represent the store operation to 2-4 locals + using multi-reg/mem value of a call/lclvar respectively. It also will have additional fields + to store the registers into which FieldLcl[1..4] need to be stored and also a spill mask + to indicate which of the locals needs to be spilled. + + During codegen, return value of call in multiple return registers need to be stored to the + corresponding registers of the locals by properly handling any circular dependencies. + +Case 1 is morphed as + `GT_OBJ(&tmp) = GT_CALL` + + Post rationalization this will get converted to GT_STORE_OBJ/BLK(&tmp, GT_CALL) and + block op codegen will special case for multi-reg call case. This case simpler because, although it is + consuming multiple registers from the call, it doesn't have the complication of multiple + destination registers. + +Case 2 can be handled one of the following two ways + a) Force tmp to memory and morph it as in case 1 above + b) Create 2-4 temp locals matching the type of respective return registers of GT_CALL and + use them to create following IR + +``` +GT_STORE_MULTI_VAR(TYP_STRUCT, , op1 = GT_CALL) +``` + + Example: say on x64 unix, return type is a struct with 3 fields: TYP_INT, TYP_INT and TYP_REF. + First two fields would be combined into a single local of TYP_LONG and third field would + would go into a single local of TYP_REF. + + Additional IR nodes can be created to extract/assemble fields of tmp struct from individual tmpLcls. + +Platform agnostic ReturnTypeDesc on a GT_CALL node +-------------------------------------------------- +Every GT_CALL node will have a light-weight ReturnTypeDesc that provides a platform independent interface to query the following: + - Respective return types of a multi-reg return value + - Respective Return register numbers in which the value is returned. + +ReturnTypeDesc is initialized during importation while creating GenTreeCall node. + +GT_CALL node is augmented with the following additional state: + gtOtherRegs - an array of MAX_RET_REG_COUNT-1 reg numbers of multi-reg return. gtRegNum field + will always be the first return reg. + gtSpillFlags - an array to hold GTF_SPILL/GTF_SPILLED state of each reg. This allows us to + spill/reload individual return registers of a multi-reg call node work. + +Post Global Morph, IR forms of GT_RETURN(tmp) where tmp is of TYP_STRUCT +------------------------------------------------------------------------ +Case 3 is morphed into + +``` + GT_RETURN (TYP_STRUCT, op1 = GT_MULTI_VAR(TYP_STRUCT, )) +``` + + Where FieldLcl[1..4] are lcl numbers of independently promoted fields of tmp and + GT_MULTI_VAR is a new node that represents 2-4 independent local vars. + +Case 1 remains unchanged + + `GT_RETURN(TYP_STRUCT, op1 = tmp)` + +Case 2 is handled as follows: + a) Force tmp to memory and morph it as in case 1 above + b) Create 2-4 temp locals matching the type of respective return registers of GT_RETURN and + use them to extract individual fields from tmp and morph it as in case 3 above. + + tmpLcl1 = GenTree Nodes to extract first 8-bytes from tmp + tmpLcl2 = GenTree Nodes to extract next 8-bytes from tmp and so on + +``` + GT_RETURN(TYP_STRUCT, op1 = GT_STORE_MULTI_VAR(TYP_STRUCT, , tmp)) +``` + + +Post Lowering, IR forms of GT_CALL node returning TYP_LONG value +---------------------------------------------------------------- +During Lowering, such call nodes are lowered into tmp=GT_CALL if the return value of call node is not already assigned to a local. Further tmp is decomposed into GT_LONG. + +Post IR lowering, GT_CALL will be transformed into + +``` + GT_STORE_LCL_VAR(TYP_LONG, lcl Num of tmp, op1 = GT_CALL) +``` + + where tmp is decomposed into GT_LONG(GT_LCL_VAR(tmpHi), GT_LCL_VAR(tmpLo)) + and finally GT_STORE_LCL_VAR is transformed into + +``` + GT_STORE_MULTI_VAR(TYP_LONG, , op1=GT_CALL) +``` + + where tmpHi and tmpLo are promoted lcl fields of tmp. + +Post Lowering, IR forms of GT_RETURN(tmp) where tmp is of TYP_LONG +------------------------------------------------------------------ +LclVar tmp will be decomposed into two locals and the resulting IR would be GT_RETURN(GT_LONG) + +Lowering Register specification +-------------------------------- +DstCount of GT_CALL node returning multi-reg return value will be set to 2 or 3 or 4 depending on the number of return registers and its dstCandidates is set to the fixed mask of return registers. + +SrcCount and DstCount of GT_STORE_MULTI_VAR will be set 2 or 3 or 4 depending on the number of locals to which a value is assigned. Note that those locals that do not require a value to be assigned are represented as BAD_VAR_NUM. + +SrcCount of GT_RETURN returning a multi-reg value will be set to 2 or 3 or 4 depending on the number of return registers. + +LSRA Considerations +------------------- +LSRA needs to add support for multi-reg destination GT_CALL, GT_MULTI_VAR and GT_STORE_MULTI_VAR nodes. + +Codegen Considerations +---------------------- +genProduceReg()/genConsumeReg() code paths need to support mullti-reg destination GT_CALL, GT_MULTI_VAR and GT_STORE_MULTI_VAR nodes. + +GT_RETURN(tmp) where tmp is of TYP_STRUCT + - tmp would either be in memory GT_LCL_VAR or GT_MULTI_VAR of TYP_STRUCT + +GT_RETURN(op1) where op1 is of TYP_LONG + - op1 should be always of the form GT_LONG(tmpLclHi, tmpLclLo) + + +Sub work items +-------------- + +The following are the sub work items and against each is indicated its current status: + +1. (Done) Refactor code to abstract structDesc field of GenTreeCall node +ReturnTypeDesc would abstract away existing structDesc (x64 unix) and implement +an API and replace all uses of structDesc of call node with the API. This would be +a pure code refactoring with the addition of ReturnTypeDesc on a GenTreeCall node. + +2. (Done) Get rid of structDesc and replace it with ReturnTypeDesc. +Note that on x64 Unix, we still query structDesc from VM and use it to initialize ReturnTypeDesc. + +3. (Done) Phase 1 Implementation of multi-reg GT_CALL/GT_RETURN node support for x64 Unix + - Importer changes to force IR to be of the form tmp=call always for multi-reg call nodes + - Importer changes to force IR to be of the form GT_RETURN(tmp) always for multi-reg return + - tmp will always be an in memory lcl var. + - Till First class struct support for GT_OBJ/GT_STORE_OBJ comes on-line IR will be of the form + + `GT_STORE_LCL_VAR(tmpLcl, op1 = GT_CALL)` + + where tmpLcl will always be an in memory lcl var of TYP_STRUCT + - Lowering/LSRA/Codegen support to allocate multiple regs to GT_CALL nodes. + - GT_CALL nodes will be governed by a single spill flag i.e. all return registers are spilled together. + - GT_RETURN(tmp) - lowering will mark op1=tmp as contained and generate code as existing code does. + +4. Phase 2 implementation of multi-reg GT_CALL/GT_RETURN node support for x64 unix + - Add new gentree nodes GT_MULTI_VAR and GT_STORE_MULTI_VAR and plumb through rest of JIT phases. + - Global morph code changes to support Case 3 (i.e P-DEP promoted structs) + - Lowering/LSRA/Codegen changes to support GT_MULTI_VAR and GT_STORE_MULTI_VAR + +5. When First class structs support comes on-line, leverage GT_OBJ/GT_STORE_OBJ to store multi-reg +return value of a GT_CALL node to memory cleaning up the code in GT_STORE_LCL_VAR. + +6. (Done) HFA and multi-reg struct return support for Arm64 + +7. (Done) x86 long return support + +8. (Optimization) Phase 3 implementation of multi-reg GT_CALL/GT_RETURN node support for x64 unix + - Global morph code changes to support some of the important Case 2 efficiently + +9. HFA struct and long return support for Arm32 RyuJIT - we should be able to leverage x86 long return and Arm64 HFA struct return work here. + diff --git a/Documentation/project-docs/adding_new_public_apis.md b/Documentation/project-docs/adding_new_public_apis.md index dbf305d..289ba7d 100644 --- a/Documentation/project-docs/adding_new_public_apis.md +++ b/Documentation/project-docs/adding_new_public_apis.md @@ -1,26 +1,25 @@ -Adding new public APIs to mscorlib -================================== +Adding new public APIs to System.Private.CoreLib +================================================ -Many of the CoreFX libraries type-forward their public APIs to the implementations in mscorlib. -- The CoreFX build uses published contracts for mscorlib, and the CoreFX test build uses published contracts for some of the CoreFX libraries. -- Some of the CoreFX libraries are not built in the CoreFX repository. For example, System.Runtime.Loader.dll is purely a facade and type-forwards everything to mscorlib. These libraries are built and published through a separate process. -- Hence, when adding a new public API to mscorlib, changes must be staged to ensure that new prerequisites are published before they are used. +Many of the CoreFX libraries type-forward their public APIs to the implementations in System.Private.CoreLib. +- The CoreFX build uses System.Private.CoreLib via Microsoft.TargetingPack.Private.CoreCLR Nuget package. +- Some of the CoreFX libraries are not built in the CoreFX repository. For example, System.Runtime.Loader.dll is purely a facade and type-forwards everything to System.Private.CoreLib. These libraries are built and published through a separate process. +- Hence, when adding a new public API to System.Private.CoreLib, changes must be staged to ensure that new prerequisites are published before they are used. **Staging the changes** -Make the changes to CoreCLR, including mscorlib +Make the changes to CoreCLR, including System.Private.CoreLib - Update `coreclr/src/mscorlib/model.xml` with the new APIs. APIs that are not listed in this file will be stripped out prior to publishing. -- Note that at the moment, merging changes with new public APIs will cause an internal build failure. Please work with your PR reviewer to have these build breaks be fixed soon after merging, otherwise it will block the publishing process. - Merge the changes -- Wait for a new mscorlib contract to be published. Check the latest published version [here](http://myget.org/gallery/dotnet-core). +- Wait for a new System.Private.CoreLib to be published. Check the latest published version [here](https://dotnet.myget.org/feed/dotnet-core/package/nuget/Microsoft.TargetingPack.Private.CoreCLR). -Make the changes to CoreFX consuming the new APIs in mscorlib +Make the changes to CoreFX consuming the new APIs in System.Private.CoreLib - If the changes are to libraries that are built out of the CoreFX repository: - - You will likely see a build failure until a new mscorlib contract is published + - You will likely see a build failure until a new System.Private.CoreLib contract is published - If the changes are to libraries that are **not** built out of the CoreFX repository: - For example, pure facades such as System.Runtime.Loader.dll - There will likely not be a build failure - - But you will still need to wait for the new mscorlib contract to be published before merging the change, otherwise, facade generation will fail + - But you will still need to wait for the new System.Private.CoreLib contract to be published before merging the change, otherwise, facade generation will fail - Merge the changes - Wait for new contracts to be published for libraries with new APIs. Check the latest published versions [here](http://myget.org/gallery/dotnet-core). diff --git a/Documentation/project-docs/ci-trigger-phrases.md b/Documentation/project-docs/ci-trigger-phrases.md index 3652565..03e071d 100644 --- a/Documentation/project-docs/ci-trigger-phrases.md +++ b/Documentation/project-docs/ci-trigger-phrases.md @@ -3,6 +3,8 @@ When submitting a PR to the CoreCLR repo, you may want to run more test suites than are included in the default set of checks run with each PR. In this document you will find a list of all possible jobs to trigger, as well as the phrase that will trigger that job. +You can also ask the CI system to show you all to available trigger phrases by using `@dotnet-bot help`. + These phrases are ordered by OS. They will usually be in the form of "{OS} {Architecture} {Configuration} {Scenario}", so use that format if you are trying to ctrl-f a certain job. To trigger a job, post a comment on your PR with "@dotnet-bot {trigger-phrase}". @@ -79,64 +81,64 @@ To trigger a job, post a comment on your PR with "@dotnet-bot {trigger-phrase}". - **Windows_NT x64 Checked CoreFX JitStressRegs=8 Build & Test:** "test Windows_NT corefx_jitstressregs8" - **Windows_NT x64 Checked CoreFX JitStressRegs=0x10 Build & Test:** "test Windows_NT corefx_jitstressregs0x10" - **Windows_NT x64 Checked CoreFX JitStressRegs=0x80 Build & Test:** "test Windows_NT corefx_jitstressregs0x80" -- **Windows_NT x86 RyuJit Checked Priority 0 Build & Test:** "test Windows_NT x86 ryujit" +- **Windows_NT x86 Checked Priority 0 Build & Test:** "test Windows_NT x86" - **Windows_NT x86 legacy_backend Checked Priority 0 Build & Test:** "test Windows_NT x86 legacy_backend" -- **Windows_NT x86 RyuJit Release Ready-To-Run Priority 0 Build & Test:** "test Windows_NT x86 ryujit Release r2r" +- **Windows_NT x86 Release Ready-To-Run Priority 0 Build & Test:** "test Windows_NT x86 Release r2r" - **Windows_NT x86 legacy_backend Release Ready-To-Run Priority 0 Build & Test:** "test Windows_NT x86 legacy_backend Release r2r" -- **Windows_NT x86 RyuJit Release Ready-To-Run Priority 1 Build & Test:** "test Windows_NT x86 ryujit Release pri1r2r" +- **Windows_NT x86 Release Ready-To-Run Priority 1 Build & Test:** "test Windows_NT x86 Release pri1r2r" - **Windows_NT x86 legacy_backend Release Ready-To-Run Priority 1 Build & Test:** "test Windows_NT x86 legacy_backend Release pri1r2r" -- **Windows_NT x86 RyuJit Release GCStress=15 Ready-To-Run Priority 1 Build & Test:** "test Windows_NT x86 ryujit Release gcstress15_pri1r2r" +- **Windows_NT x86 Release GCStress=15 Ready-To-Run Priority 1 Build & Test:** "test Windows_NT x86 Release gcstress15_pri1r2r" - **Windows_NT x86 legacy_backend Release GCStress=15 Ready-To-Run Priority 1 Build & Test:** "test Windows_NT x86 legacy_backend Release gcstress15_pri1r2r" -- **Windows_NT x86 RyuJit Release jitstress1 R2R Build & Test:** "test Windows_NT x86 ryujit Release jitstress1 R2R" -- **Windows_NT x86 RyuJit Checked jitstress1 R2R Build & Test:** "test Windows_NT x86 ryujit Checked jitstress1 R2R" -- **Windows_NT x86 RyuJit Release jitstress2 R2R Build & Test:** "test Windows_NT x86 ryujit Release jitstress2 R2R" -- **Windows_NT x86 RyuJit Checked jitstress2 R2R Build & Test:** "test Windows_NT x86 ryujit Checked jitstress2 R2R" -- **Windows_NT x86 RyuJit Release jitstressregs1 R2R Build & Test:** "test Windows_NT x86 ryujit Release jitstressregs1 R2R" -- **Windows_NT x86 RyuJit Checked jitstressregs1 R2R Build & Test:** "test Windows_NT x86 ryujit Checked jitstressregs1 R2R" -- **Windows_NT x86 RyuJit Release jitstressregs2 R2R Build & Test:** "test Windows_NT x86 ryujit Release jitstressregs2 R2R" -- **Windows_NT x86 RyuJit Checked jitstressregs2 R2R Build & Test:** "test Windows_NT x86 ryujit Checked jitstressregs2 R2R" -- **Windows_NT x86 RyuJit Release jitstressregs3 R2R Build & Test:** "test Windows_NT x86 ryujit Release jitstressregs3 R2R" -- **Windows_NT x86 RyuJit Checked jitstressregs3 R2R Build & Test:** "test Windows_NT x86 ryujit Checked jitstressregs3 R2R" -- **Windows_NT x86 RyuJit Release jitstressregs4 R2R Build & Test:** "test Windows_NT x86 ryujit Release jitstressregs4 R2R" -- **Windows_NT x86 RyuJit Checked jitstressregs4 R2R Build & Test:** "test Windows_NT x86 ryujit Checked jitstressregs4 R2R" -- **Windows_NT x86 RyuJit Release jitstressregs8 R2R Build & Test:** "test Windows_NT x86 ryujit Release jitstressregs8 R2R" -- **Windows_NT x86 RyuJit Checked jitstressregs8 R2R Build & Test:** "test Windows_NT x86 ryujit Checked jitstressregs8 R2R" -- **Windows_NT x86 RyuJit Release jitstressregsx10 R2R Build & Test:** "test Windows_NT x86 ryujit Release jitstressregsx10 R2R" -- **Windows_NT x86 RyuJit Checked jitstressregsx10 R2R Build & Test:** "test Windows_NT x86 ryujit Checked jitstressregsx10 R2R" -- **Windows_NT x86 RyuJit Release jitstressregsx80 R2R Build & Test:** "test Windows_NT x86 ryujit Release jitstressregsx80 R2R" -- **Windows_NT x86 RyuJit Checked jitstressregsx80 R2R Build & Test:** "test Windows_NT x86 ryujit Checked jitstressregsx80 R2R" -- **Windows_NT x86 RyuJit Release JITMinOpts R2R Build & Test:** "test Windows_NT x86 ryujit Release JITMinOpts R2R" -- **Windows_NT x86 RyuJit Checked JITMinOpts R2R Build & Test:** "test Windows_NT x86 ryujit Checked JITMinOpts R2R" -- **Windows_NT x86 RyuJit Release ForceRelocs R2R Build & Test:** "test Windows_NT x86 ryujit Release ForceRelocs R2R" -- **Windows_NT x86 RyuJit Checked ForceRelocs R2R Build & Test:** "test Windows_NT x86 ryujit Checked ForceRelocs R2R" -- **Windows_NT x86 RyuJit Checked JIT MinOpts Build & Test:** "test Windows_NT x86 ryujit minopts" -- **Windows_NT x86 RyuJit Checked JITStress=1 Build & Test:** "test Windows_NT x86 ryujit jitstress1" -- **Windows_NT x86 RyuJit Checked JITStress=2 Build & Test:** "test Windows_NT x86 ryujit jitstress2" -- **Windows_NT x86 RyuJit Checked Jit ForceRelocs Build & Test:** "test Windows_NT x86 ryujit forcerelocs" -- **Windows_NT x86 RyuJit Checked JITStressRegs=1 Build & Test:** "test Windows_NT x86 ryujit jitstressregs1" -- **Windows_NT x86 RyuJit Checked JITStressRegs=2 Build & Test:** "test Windows_NT x86 ryujit jitstressregs2" -- **Windows_NT x86 RyuJit Checked JITStressRegs=3 Build & Test:** "test Windows_NT x86 ryujit jitstressregs3" -- **Windows_NT x86 RyuJit Checked JITStressRegs=4 Build & Test:** "test Windows_NT x86 ryujit jitstressregs4" -- **Windows_NT x86 RyuJit Checked JITStressRegs=8 Build & Test:** "test Windows_NT x86 ryujit jitstressregs8" -- **Windows_NT x86 RyuJit Checked JITStressRegs=0x10 Build & Test:** "test Windows_NT x86 ryujit jitstressregs0x10" -- **Windows_NT x86 RyuJit Checked JITStressRegs=0x80 Build & Test:** "test Windows_NT x86 ryujit jitstressregs0x80" -- **Windows_NT x86 RyuJit Checked JitStress=2 JITStressRegs=1 Build & Test:** "test Windows_NT x86 ryujit jitstress2_jitstressregs1" -- **Windows_NT x86 RyuJit Checked JitStress=2 JITStressRegs=2 Build & Test:** "test Windows_NT x86 ryujit jitstress2_jitstressregs2" -- **Windows_NT x86 RyuJit Checked JitStress=2 JITStressRegs=3 Build & Test:** "test Windows_NT x86 ryujit jitstress2_jitstressregs3" -- **Windows_NT x86 RyuJit Checked JitStress=2 JITStressRegs=4 Build & Test:** "test Windows_NT x86 ryujit jitstress2_jitstressregs4" -- **Windows_NT x86 RyuJit Checked JitStress=2 JITStressRegs=8 Build & Test:** "test Windows_NT x86 ryujit jitstress2_jitstressregs8" -- **Windows_NT x86 RyuJit Checked JitStress=2 JITStressRegs=0x10 Build & Test:** "test Windows_NT x86 ryujit jitstress2_jitstressregs0x10" -- **Windows_NT x86 RyuJit Checked JitStress=2 JITStressRegs=0x80 Build & Test:** "test Windows_NT x86 ryujit jitstress2_jitstressregs0x80" -- **Windows_NT x86 RyuJit Checked GCStress=0x3 Build & Test:** "test Windows_NT x86 ryujit gcstress0x3" -- **Windows_NT x86 RyuJit Checked GCStress=0xc Build & Test:** "test Windows_NT x86 ryujit gcstress0xc" -- **Windows_NT x86 RyuJit Checked zapdisable Build & Test:** "test Windows_NT x86 ryujit zapdisable" -- **Windows_NT x86 RyuJit Checked Heap Verify 1 Build & Test:** "test Windows_NT x86 ryujit heapverify1" -- **Windows_NT x86 RyuJit Checked GCStress=0xc zapdisable Build & Test:** "test Windows_NT x86 ryujit gcstress0xc_zapdisable" -- **Windows_NT x86 RyuJit Checked GCStress=0xc JitStress=2 zapdisable Build & Test:** "test Windows_NT x86 ryujit gcstress0xc_zapdisable_jitstress2" -- **Windows_NT x86 RyuJit Checked GCStress=0xc zapdisable Heap Verify 1 Build & Test:** "test Windows_NT x86 ryujit gcstress0xc_zapdisable_heapverify1" -- **Windows_NT x86 RyuJit Checked GCStress=0xc JitStress=1 Build & Test:** "test Windows_NT x86 ryujit gcstress0xc_jitstress1" -- **Windows_NT x86 RyuJit Checked GCStress=0xc JitStress=2 Build & Test:** "test Windows_NT x86 ryujit gcstress0xc_jitstress2" -- **Windows_NT x86 RyuJit Checked GCStress=0xc MinOpts Heap Verify 1 Build & Test:** "test Windows_NT x86 ryujit gcstress0xc_minopts_heapverify1" +- **Windows_NT x86 Release jitstress1 R2R Build & Test:** "test Windows_NT x86 Release jitstress1 R2R" +- **Windows_NT x86 Checked jitstress1 R2R Build & Test:** "test Windows_NT x86 Checked jitstress1 R2R" +- **Windows_NT x86 Release jitstress2 R2R Build & Test:** "test Windows_NT x86 Release jitstress2 R2R" +- **Windows_NT x86 Checked jitstress2 R2R Build & Test:** "test Windows_NT x86 Checked jitstress2 R2R" +- **Windows_NT x86 Release jitstressregs1 R2R Build & Test:** "test Windows_NT x86 Release jitstressregs1 R2R" +- **Windows_NT x86 Checked jitstressregs1 R2R Build & Test:** "test Windows_NT x86 Checked jitstressregs1 R2R" +- **Windows_NT x86 Release jitstressregs2 R2R Build & Test:** "test Windows_NT x86 Release jitstressregs2 R2R" +- **Windows_NT x86 Checked jitstressregs2 R2R Build & Test:** "test Windows_NT x86 Checked jitstressregs2 R2R" +- **Windows_NT x86 Release jitstressregs3 R2R Build & Test:** "test Windows_NT x86 Release jitstressregs3 R2R" +- **Windows_NT x86 Checked jitstressregs3 R2R Build & Test:** "test Windows_NT x86 Checked jitstressregs3 R2R" +- **Windows_NT x86 Release jitstressregs4 R2R Build & Test:** "test Windows_NT x86 Release jitstressregs4 R2R" +- **Windows_NT x86 Checked jitstressregs4 R2R Build & Test:** "test Windows_NT x86 Checked jitstressregs4 R2R" +- **Windows_NT x86 Release jitstressregs8 R2R Build & Test:** "test Windows_NT x86 Release jitstressregs8 R2R" +- **Windows_NT x86 Checked jitstressregs8 R2R Build & Test:** "test Windows_NT x86 Checked jitstressregs8 R2R" +- **Windows_NT x86 Release jitstressregsx10 R2R Build & Test:** "test Windows_NT x86 Release jitstressregsx10 R2R" +- **Windows_NT x86 Checked jitstressregsx10 R2R Build & Test:** "test Windows_NT x86 Checked jitstressregsx10 R2R" +- **Windows_NT x86 Release jitstressregsx80 R2R Build & Test:** "test Windows_NT x86 Release jitstressregsx80 R2R" +- **Windows_NT x86 Checked jitstressregsx80 R2R Build & Test:** "test Windows_NT x86 Checked jitstressregsx80 R2R" +- **Windows_NT x86 Release JITMinOpts R2R Build & Test:** "test Windows_NT x86 Release JITMinOpts R2R" +- **Windows_NT x86 Checked JITMinOpts R2R Build & Test:** "test Windows_NT x86 Checked JITMinOpts R2R" +- **Windows_NT x86 Release ForceRelocs R2R Build & Test:** "test Windows_NT x86 Release ForceRelocs R2R" +- **Windows_NT x86 Checked ForceRelocs R2R Build & Test:** "test Windows_NT x86 Checked ForceRelocs R2R" +- **Windows_NT x86 Checked JIT MinOpts Build & Test:** "test Windows_NT x86 minopts" +- **Windows_NT x86 Checked JITStress=1 Build & Test:** "test Windows_NT x86 jitstress1" +- **Windows_NT x86 Checked JITStress=2 Build & Test:** "test Windows_NT x86 jitstress2" +- **Windows_NT x86 Checked Jit ForceRelocs Build & Test:** "test Windows_NT x86 forcerelocs" +- **Windows_NT x86 Checked JITStressRegs=1 Build & Test:** "test Windows_NT x86 jitstressregs1" +- **Windows_NT x86 Checked JITStressRegs=2 Build & Test:** "test Windows_NT x86 jitstressregs2" +- **Windows_NT x86 Checked JITStressRegs=3 Build & Test:** "test Windows_NT x86 jitstressregs3" +- **Windows_NT x86 Checked JITStressRegs=4 Build & Test:** "test Windows_NT x86 jitstressregs4" +- **Windows_NT x86 Checked JITStressRegs=8 Build & Test:** "test Windows_NT x86 jitstressregs8" +- **Windows_NT x86 Checked JITStressRegs=0x10 Build & Test:** "test Windows_NT x86 jitstressregs0x10" +- **Windows_NT x86 Checked JITStressRegs=0x80 Build & Test:** "test Windows_NT x86 jitstressregs0x80" +- **Windows_NT x86 Checked JitStress=2 JITStressRegs=1 Build & Test:** "test Windows_NT x86 jitstress2_jitstressregs1" +- **Windows_NT x86 Checked JitStress=2 JITStressRegs=2 Build & Test:** "test Windows_NT x86 jitstress2_jitstressregs2" +- **Windows_NT x86 Checked JitStress=2 JITStressRegs=3 Build & Test:** "test Windows_NT x86 jitstress2_jitstressregs3" +- **Windows_NT x86 Checked JitStress=2 JITStressRegs=4 Build & Test:** "test Windows_NT x86 jitstress2_jitstressregs4" +- **Windows_NT x86 Checked JitStress=2 JITStressRegs=8 Build & Test:** "test Windows_NT x86 jitstress2_jitstressregs8" +- **Windows_NT x86 Checked JitStress=2 JITStressRegs=0x10 Build & Test:** "test Windows_NT x86 jitstress2_jitstressregs0x10" +- **Windows_NT x86 Checked JitStress=2 JITStressRegs=0x80 Build & Test:** "test Windows_NT x86 jitstress2_jitstressregs0x80" +- **Windows_NT x86 Checked GCStress=0x3 Build & Test:** "test Windows_NT x86 gcstress0x3" +- **Windows_NT x86 Checked GCStress=0xc Build & Test:** "test Windows_NT x86 gcstress0xc" +- **Windows_NT x86 Checked zapdisable Build & Test:** "test Windows_NT x86 zapdisable" +- **Windows_NT x86 Checked Heap Verify 1 Build & Test:** "test Windows_NT x86 heapverify1" +- **Windows_NT x86 Checked GCStress=0xc zapdisable Build & Test:** "test Windows_NT x86 gcstress0xc_zapdisable" +- **Windows_NT x86 Checked GCStress=0xc JitStress=2 zapdisable Build & Test:** "test Windows_NT x86 gcstress0xc_zapdisable_jitstress2" +- **Windows_NT x86 Checked GCStress=0xc zapdisable Heap Verify 1 Build & Test:** "test Windows_NT x86 gcstress0xc_zapdisable_heapverify1" +- **Windows_NT x86 Checked GCStress=0xc JitStress=1 Build & Test:** "test Windows_NT x86 gcstress0xc_jitstress1" +- **Windows_NT x86 Checked GCStress=0xc JitStress=2 Build & Test:** "test Windows_NT x86 gcstress0xc_jitstress2" +- **Windows_NT x86 Checked GCStress=0xc MinOpts Heap Verify 1 Build & Test:** "test Windows_NT x86 gcstress0xc_minopts_heapverify1" - **Windows_NT x86 legacy_backend Release jitstress1 R2R Build & Test:** "test Windows_NT x86 legacy_backend Release jitstress1 R2R" - **Windows_NT x86 legacy_backend Checked jitstress1 R2R Build & Test:** "test Windows_NT x86 legacy_backend Checked jitstress1 R2R" - **Windows_NT x86 legacy_backend Release jitstress2 R2R Build & Test:** "test Windows_NT x86 legacy_backend Release jitstress2 R2R" @@ -159,7 +161,7 @@ To trigger a job, post a comment on your PR with "@dotnet-bot {trigger-phrase}". - **Windows_NT x86 legacy_backend Checked JITMinOpts R2R Build & Test:** "test Windows_NT x86 legacy_backend Checked JITMinOpts R2R" - **Windows_NT x86 legacy_backend Release ForceRelocs R2R Build & Test:** "test Windows_NT x86 legacy_backend Release ForceRelocs R2R" - **Windows_NT x86 legacy_backend Checked ForceRelocs R2R Build & Test:** "test Windows_NT x86 legacy_backend Checked ForceRelocs R2R" -- **Windows_NT x86 RyuJit Release Long-Running GC Build & Test:** "test Windows_NT x86 ryujit Release longgc" +- **Windows_NT x86 Release Long-Running GC Build & Test:** "test Windows_NT x86 Release longgc" - **Windows_NT x86 legacy_backend Release Long-Running GC Build & Test:** "test Windows_NT x86 legacy_backend Release longgc" - **Ubuntu x64 Release Priority 1 Build & Test:** "test Ubuntu pri1" - **Ubuntu x64 Release IL RoundTrip Build & Test:** "test Ubuntu ilrt" diff --git a/Documentation/project-docs/glossary.md b/Documentation/project-docs/glossary.md index 6b13ba8..670254d 100644 --- a/Documentation/project-docs/glossary.md +++ b/Documentation/project-docs/glossary.md @@ -15,6 +15,7 @@ As much as possible, we should link to the most authoritative and recent source * JIT: [Just-in-Time](https://github.com/dotnet/coreclr/blob/master/Documentation/botr/ryujit-overview.md) compiler. RyuJIT is the code name for the next generation Just-in-Time(aka "JIT") for the .NET runtime. * LCG: Lightweight Code Generation. An early name for [dynamic methods](https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/Reflection/Emit/DynamicMethod.cs). * NGen: Native Image Generator. +* NYI: Not Yet Implemented * PAL: [Platform Adaptation Layer](http://archive.oreilly.com/pub/a/dotnet/2002/03/04/rotor.html). Provides an abstraction layer between the runtime and the operating system * PE: Portable Executable. * ProjectN: Codename for the first version of [.NET Native for UWP](https://msdn.microsoft.com/en-us/vstudio/dotnetnative.aspx). @@ -22,6 +23,7 @@ As much as possible, we should link to the most authoritative and recent source * Redhawk: Codename for experimental minimal managed code runtime that evolved into [CoreRT](https://github.com/dotnet/corert/). * SOS: [Son of Strike](http://blogs.msdn.com/b/jasonz/archive/2003/10/21/53581.aspx). The debugging extension for DbgEng based debuggers. Uses the DAC as an abstraction layer for its operation. * 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. +* 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. * URT: Universal Runtime. Ancient name for what ended up being .NET, is used in the WinError facility name FACILITY_URT. * VSD: [Virtual Stub Dispatch](../botr/virtual-stub-dispatch.md). Technique of using stubs for virtual method invocations instead of the traditional virtual method table. * VM: Virtual machine. diff --git a/Documentation/workflow/EditingAndDebugging.md b/Documentation/workflow/EditingAndDebugging.md new file mode 100644 index 0000000..66b4d4f --- /dev/null +++ b/Documentation/workflow/EditingAndDebugging.md @@ -0,0 +1,49 @@ + +# Editing and Debugging + +If you are editing on the Windows Operating system, Using Visual Studio 2015 is a good option for editing +the code in this repository. You can of course also use the editor of your choice. One further option +is to use [VSCode](https://code.visualstudio.com/) which is a light weight, cross-platform tool that like +Visual Studio, is optimized for development workflow (code editing and debugging) but works on more platforms +(in particular OSX and Linux) + +[VSCode](https://code.visualstudio.com/) has built-in support for syntax highlighting and previewing +markdown (`*.md`) files that GIT repositories like this one use for documentation. If you want to modify +the docs, VSCode is a good choice. See [Markdown and VSCOde](https://code.visualstudio.com/Docs/languages/markdown) +for more on VSCode support and [Mastering Markdown](https://guides.github.com/features/mastering-markdown/) for +more on Markdown in general. + +# Visual Studio Solutions + +The repository has a number of Visual Studio Solutions files (`*.sln`) that are useful for editing parts of +what are in the repository. In particular + + * `src\mscorlib\System.Private.CorLib.sln` - This solution is for all managed (C#) code that is defined + in the runtime itself. This is all class library support of one form or another. + * `bin\obj\Windows_NT..\CoreCLR.sln` - this solution contains most native (C++) projects + associated with the repository, including + * `coreclr` - This is the main runtime DLL (the GC, class loader, interop are all here) + * `corjit` - This is the Just In Time (JIT) compiler that compiles .NET Intermediate language to native code. + * `corerun` - This is the simple host program that can load the CLR and run a .NET Core application + * `crossgen` - This is the host program that runs the JIT compiler and produces .NET Native images (`*.ni.dll`) + for C# code. + +Thus opening one of these two solution files (double clicking on them in Explorer) is typically all you need +to do most editing. + +Notice that the CoreCLR solution is under the 'bin' directory. This is because it is created as part of the build. +Thus you can only launch this solution after you have built at least once. + +* See [Debugging](../building/debugging-instructions.md) + +### Interacting with GIT in Visual Studio + +Most interactions with GIT can be done from within Visual Studio. See the following for more details. +* [Setting up with a fork with Visual Studio 2015](https://github.com/Microsoft/perfview/blob/master/documentation/OpenSourceGitWorkflow.md) + +# See Also + +Before you make modifications, you probably want to learn more about the general architecture of .NET Core. +See the following docs for more. + + * [Documentation on the .NET Core Runtime](../README.md) diff --git a/Documentation/workflow/IssuesFeedbackEngagement.md b/Documentation/workflow/IssuesFeedbackEngagement.md new file mode 100644 index 0000000..a6c0550 --- /dev/null +++ b/Documentation/workflow/IssuesFeedbackEngagement.md @@ -0,0 +1,37 @@ + +# Engage, Log Issues and Provide Feedback + +## Reporting Problems (Bugs) + +We track bugs, feature requests and other issues [in this repo](https://github.com/dotnet/coreclr/issues). +If you have a problem and believe that the issue is in the native runtime you should log it there. If in the managed code log it in the [CoreFX repo](https://github.com/dotnet/corefx/issues) _even if the code is in this CoreCLR repo_ (ie., in mscorlib/System.Private.Corelib). The reason for this is we sometimes move managed types between the two and it makes sense to keep all the issues together. + +Before you log a new issue, you should try using the search tool on the issue page on a few keywords to see if the issue was already logged. + +### NET Forums +If you want to ask a question, or want wider discussion (to see if others share you issue), we encourage you to start a thread +in the [.NET Foundation forums](http://forums.dotnetfoundation.org/). + +###Chat with the CoreCLR Community + +For more real-time feedback you can also start a chat session by clicking on the icons below. + +[![.NET Slack Status](https://aspnetcoreslack.herokuapp.com/badge.svg?2)](http://tattoocoder.com/aspnet-slack-sign-up/) [![Join the chat at https://gitter.im/dotnet/coreclr](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/dotnet/coreclr?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +### Security issues + +To avoid tipping off malicious users wishing to exploit a vulnerability, +security issues and bugs should be reported privately, via email, to the +Microsoft Security Response Center (MSRC) . You should +receive a response within 24 hours. If for some reason you do not, please follow +up via email to ensure we received your original message. Further information, +including the MSRC PGP key, can be found in the +[Security TechCenter](https://technet.microsoft.com/en-us/security/ff852094.aspx) + +### Issues with the .NET Desktop runtime + +The .NET Core repository is not an appropriate place to log issues for the 'Desktop' .NET Framework built into the Windows +operating system. If you are having issues with the Full .NET Framework or .NET Runtime the best ways to file a bug +are at [Connect](http://connect.microsoft.com/VisualStudio) or through +[Product Support](https://support.microsoft.com/en-us/contactus?ws=support) if you have a contract. + diff --git a/Documentation/workflow/OfficalAndDailyBuilds.md b/Documentation/workflow/OfficalAndDailyBuilds.md new file mode 100644 index 0000000..5a36af6 --- /dev/null +++ b/Documentation/workflow/OfficalAndDailyBuilds.md @@ -0,0 +1,79 @@ +# Official Releases and Daily Builds of CoreCLR and CoreFX components + +If you are not planning on actually making bug fixes or experimenting with new features, then you probably +don't need to don't need build CoreCLR yourself, as the .NET Runtime team routinely does this for you. + +Roughly every three months, the .NET Runtime team publishes a new version of .NET Core to Nuget. .NET Core's +official home on NuGet is + + * + +and you can expect to see new versions roughly three months. However it is also the case that the .NET +Team publishes **daily builds** of all sorts of packages including those built by the CoreCLR and CoreFX +repositories. You can see what is available from + + * , and in particular you can see the builds of CoreCLR at + * . + +Thus if your goal is just to get the latest bug fixes and features, you don't need to build CoreCLR yourself you +can simply add to your Nuget Feed list. + +## Package Version Numbers + +Version numbers for Nuget packages look like the following +``` + 1.0.24214.01 +``` +Which have the form +``` + ... +``` + +* The major version number represents a compatibility band. If the next release of the package is not + backward compatible (most apps that run on version N-1 will run on version N) then this number is increased. + This number is not likely to change (we care about compatibility alot) + +* The minor number is increased every time interesting new features are added (not just minor bug fixes). + For CoreCLR we tend to update this every time we create a public release (every 3 months). + +* The Major Build Number is a number that represents a daily build. The last 2 digits of this build number + is the **day of the month** of the GIT commit that is being built. Thus we know in the example above this + build's last commit to GIT happened on the 14th day of the month. The most significant digits represents + the month count since April 1996. In the example above 242 represents Jun 2016. + +* The Minor Build number is something that disambiguates different builds that share the same + commit (or the different commits on the same day). It is a sequential number and is typically 1 for + official builds, and 0 for developer builds. (You can set the environment variable BuildNumberMinor if + you wish to set it for your own builds). + + + +See the [Package and File Versioning](https://github.com/dotnet/corefx/blob/master/Documentation/building/versioning.md) page +for more details on how the build version number is generated. + + + +# Build/Test Status of the repository + +As mentioned we build the CoreCLR repository daily, and as part of that build we also run all +the tests associted with this repository. Below is a table of the most recent results for all +the different operating systems and architectures that we routinely build. + +If you click on the images below, you can get more details about the build (including the binaries) +and the exact test results (in case your build is failing tests and you are wondering if it is +something affecting all builds). + +| | Debug | Release | +|---|:-----:|:-------:| +|**CentOS 7.1**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_centos7.1.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_centos7.1)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_centos7.1.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_centos7.1)| +|**Debian 8.4**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_debian8.4.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_debian8.4)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_debian8.4.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_debian8.4)| +|**FreeBSD 10.1**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_freebsd.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_freebsd)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_freebsd.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_freebsd)| +|**openSUSE 13.2**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_opensuse13.2.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_opensuse13.2)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_opensuse13.2.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_opensuse13.2)| +|**openSUSE 42.1**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_opensuse42.1.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_opensuse42.1)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_opensuse42.1.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_opensuse42.1)| +|**OS X 10.11**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_osx.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_osx)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_osx.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_osx)| +|**Red Hat 7.2**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_rhel7.2.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_rhel7.2)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_rhel7.2.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_rhel7.2)| +|**Fedora 23**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_fedora23.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_fedora23)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_fedora23.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_fedora23)| +|**Ubuntu 14.04**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_ubuntu.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_ubuntu)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_ubuntu.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_ubuntu)| +|**Ubuntu 16.04**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_ubuntu16.04.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_ubuntu16.04)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_ubuntu16.04.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_ubuntu16.04)| +|**Ubuntu 16.10**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_ubuntu16.10.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_ubuntu16.10)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_ubuntu16.10.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_ubuntu16.10)| +|**Windows 8.1**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_windows_nt.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_windows_nt)
[![arm64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/arm64_cross_debug_windows_nt.svg?label=arm64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/arm64_cross_debug_windows_nt)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_windows_nt.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_windows_nt)
[![arm64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/arm64_cross_release_windows_nt.svg?label=arm64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/arm64_cross_release_windows_nt)| diff --git a/Documentation/workflow/RunningTests.md b/Documentation/workflow/RunningTests.md new file mode 100644 index 0000000..0cf84be --- /dev/null +++ b/Documentation/workflow/RunningTests.md @@ -0,0 +1,10 @@ + +#Running .NET Core Tests + +TODO - Incomplete. + +See [Windows Instructions](../building/windows-test-instructions.md) +See [Unix Instructions](../building/unix-test-instructions.md) + + + diff --git a/Documentation/workflow/UsingCoreRun.md b/Documentation/workflow/UsingCoreRun.md new file mode 100644 index 0000000..3979f13 --- /dev/null +++ b/Documentation/workflow/UsingCoreRun.md @@ -0,0 +1,83 @@ + +# Using corerun To Run .NET Core Application + +In page [Using Your Build](UsingYourBuild.md) gives detailed instructions on using the standard +command line host and SDK, dotnet.exe to run a .NET application with the modified build of the +.NET Core runtime built here. This is the preferred mechanism for you to officially deploy +your changes to other people since dotnet.exe and Nuget insure that you end up with a consistent +set of DLLs that can work together. + +However packing and unpacking the runtime DLLs adds extra steps to the deployment process and when +you are in the tight code-build-debug loop these extra steps are an issue. + +For this situation there is an alternative host to dotnet.exe called corerun.exe that is well suited +for this. It does not know about Nuget at all, and has very simple rules. It needs to find the +.NET Core runtime (that is coreclr.dll) and additionally any class library DLLs (e.g. System.Runtime.dll System.IO.dll ...). + +It does this by looking at two environment variables. + + + * `CORE_ROOT` - The directory where to find the runtime DLLs itself (e.g. CoreCLR.dll). + Defaults to be next to the corerun.exe host itself. + * `CORE_LIBRARIES` - A Semicolon separated list of directories to look for DLLS to resolve any assembly references. + It defaults CORE_ROOT if it is not specified. + +These simple rules can be used in a number of ways + +## Getting the class library from the shared system-wide runtime + +Consider that you already have a .NET application DLL called HelloWorld.dll and wish to run it +(You could make such a DLL by using 'dotnet new' 'dotnet restore' 'dotnet build' in a 'HelloWorld' directory). + +If you execute the following +```bat + set PATH=%PATH%;%CoreCLR%\bin\Product\Windows_NT.x64.Debug + set CORE_LIBRARIES=%ProgramFiles%\dotnet\shared\Microsoft.NETCore.App\1.0.0 + + + corerun HelloWorld.dll +``` + +for Linux use /usr/share for %Program Files% + +Where %CoreCLR% is the base of your CoreCLR repository, then it will run your HelloWorld. application. +You can see why this works. The first line puts build output directory (Your OS, architecture, and buildType +may be different) and thus corerun.exe you just built is on your path. +The second line tells corerun.exe where to find class library files, in this case we tell it +to find them where the installation of dotnet.exe placed its copy. (Note that version number in the path above may change) + +Thus when you run 'corerun HelloWorld.dll' Corerun knows where to get the DLLs it needs. Notice that once +you set up the path and CORE_LIBRARIES environment, after a rebuild you can simply use corerun to run your +application (you don't have to move DLLs around) + +## Using corerun.exe to Execute a Published Application + +When 'dotnet publish' publishes an application it deploys all the class libraries needed as well. +Thus if you simply change the CORE_LIBRARIES definition in the previous instructions to point at +that publication directory but RUN the corerun from your build output the effect will be that you +run your new runtime getting all the other code needed from that deployed application. This is +very convenient because you don't need to modify the deployed application in order to test +your new runtime. + +## How CoreCLR Tests use corerun.exe + +When you execute 'tests\runTest.cmd' one of the things that it does is set up a directory where it +gathers the CoreCLR that has just been built with the pieces of the class library that tests need. +It places this runtime in the directory +```bat + bin\Product\..\test +``` +off the CoreCLR Repository. The way the tests are expected to work is that you set the environment +variable CORE_ROOT to this directory +(you don't have to set CORE_LIBRARIES) and you can run any tests. For example after building the tests +(running build-test at the repository base) and running 'test\runtest') you can do the following + +```bat + set PATH=%PATH%;%CoreCLR%\bin\Product\Windows_NT.x64.Debug + set CORE_ROOT=%CoreCLR%\bin\tests\Windows_NT.x64.Debug\Tests\Core_Root +``` +sets you up so that corerun can run any of the test. For example +```bat + corerun bin\tests\Windows_NT.X64.Debug\GC\Features\Finalizer\finalizeio\finalizeio\finalizeio.exe +``` +runs the finalizerio test. \ No newline at end of file diff --git a/Documentation/workflow/UsingYourBuild.md b/Documentation/workflow/UsingYourBuild.md new file mode 100644 index 0000000..c783dd1 --- /dev/null +++ b/Documentation/workflow/UsingYourBuild.md @@ -0,0 +1,215 @@ + +# Using your .NET Core Runtime Build + +We assume that you have successfully built CoreCLR repository and thus have file of the form +``` + bin\Product\..\.nuget\pkg\Microsoft.NETCore.Runtime.CoreCLR..nupkg +``` +And now you wish to try it out. We will be using Windows OS as an example and thus will use \ rather +than / for directory separators and things like Windows_NT instead of Linux but it should be +pretty obvious how to adapt these instructions for other operating systems. + +To run your newly built .NET Core Runtime in addition to the application itself, you will need +a 'host' program that will load the Runtime as well as all the other .NET Core Framework +code that your application needs. The easiest way to get all this other stuff is to simply use the +standard 'dotnet' host that installs with .NET Core SDK. + +The released version of 'dotnet' tool may not be compatible with the live CoreCLR repository. The following steps +assume use of unreleased version of 'dotnet' tool that is downloaded as part of the CoreCLR repository +build at `\Tools\dotnetcli`. [Add `Tools\dotnetcli` directory to your path](../building/windows-instructions.md#adding-to-the-default-path-variable) +and type: + +* dotnet -? + +and it prints some help text, you are ready. + +### Step 1: Create a App using the Default Runtime +At this point you can create a new 'Hello World' program in the standard way. + +```bat +mkdir HelloWorld +cd HelloWorld +dotnet new +``` + +### Step 2: Get the Version number of the CoreCLR package you built. + +This makes a 'standard' hello world application but uses the .NET Core Runtime version that +came with the dotnet.exe tool. First you need to modify your app to ask for the .NET Core +you have built, and to do that, we need to know the version number of what you built. Get +this by simply listing the name of the Microsoft.NETCore.Runtime.CoreCLR you built. + +```bat + dir bin\Product\Windows_NT.x64.Release\.nuget\pkg +``` + +and you will get name of the which looks something like this + +``` + Microsoft.NETCore.Runtime.CoreCLR.1.2.0-beta-24528-0.nupkg +``` + +This gets us the version number, in the above case it is 1.2.0-beta-24528-0. We will +use this in the next step. + +### Step 3: Modify the Project.json for the App to refer to your Runtime. + +Replace the HelloWorld\project.json with [project.json](../../tests/src/Common/netcoreapp/project.json), and update +`1.2.0-beta-XXXXX-X` version number in the dependencies section with the version number for your build of the runtime. +This is the line that tells the tools that you want YOUR version of the CoreCLR runtime. +``` + "Microsoft.NETCore.Runtime.CoreCLR": "1.2.0-beta-24528-0" +``` + +The differences between the project.json generated by the tool and the replacement: + +- Removed Microsoft.NETCore.App platform dependency (`"type": "platform"`). This tells the build system that you don't want to +use runtime and libraries that came with the dotnet.exe tool but to fetch the dependencies from the Nuget cache. If you don't do this +the tools will ignore your request to make the app use an explicitly specified runtime. +- Added the 'runtimes' line at the top level. The runtime name includes the OS name and the architecture name +you can find the appropriate name for your OS [here](https://github.com/dotnet/core-docs/blob/master/docs/core/rid-catalog.md). +This tells the tools exactly which flavor of OS and processor architecture you are running on, so it can find the right +Nuget package for the runtime. +- Changed netcoreapp1.0 to netcoreapp1.1. This tells the tools that you want to use the latest .NET Core Framework. +- Expanded Microsoft.NETCore.App metapackage into explicit list of the .NET Core Framework packages because of there is no good published +build of Microsoft.NETCore.App metapackage for netcoreapp1.1 yet. + +### Step 4: Place your build directory and beta .NET Core Framework feed on your Nuget Path + +You can do this by creating a file named Nuget.Config in the 'HelloWorld' directory with the following XML +Obviously **you need to update path in the XML to be the path to output directory for your build**. +On Windows you also have the alternative of modifying the Nuget.Config +at %HOMEPATH%\AppData\Roaming\Nuget\Nuget.Config (~/.nuget/NuGet/NuGet.Config on Linux) with the new location. +This will allow your new +runtime to be used on any 'dotnet restore' run by the current user. +Alternatively you can skip creating this file and pass the path to your package directory using +the -s SOURCE qualifer on the dotnet restore command below. The important part is that somehow +you have told the tools where to find your new package. + +```xml + + + + + + + + + + + + +``` + +### Step 5: Restore the Nuget Packages for your application + +This consist of simply running the command +``` + dotnet restore +``` +which should find the .NET Runtime package in your build output and unpacks it to the local Nuget cache (on windows this is in %HOMEPATH%\.nuget\packages) + + +### Step 6: Run your application + +You can run your 'HelloWorld' applications by simply executing the following in the 'HelloWorld' directory. + +``` + dotnet run +``` +This will compile and run your app. What the command is really doing is building files in helloWorld\bin\Debug\netcoreapp1.1\win7-x64\ +and then running 'dotnet helloWorld\bin\Debug\netcoreapp1.1\win7-x64\HelloWorld.dll' to actually run the app. + +### Step 6: (Optional) Publish your application + +In Step 5 you will notice that the helloWorld\bin\Debug\netcoreapp1.1\win7-x64 directory does NOT actually contain your Runtime code. +What is going on is that runtime is being loaded directly out of the local Nuget cache (on windows this is in %HOMEPATH%\.nuget\packages). +The app can find this cache because of the HelloWorld.runtimeconfig.dev.json file which specifies that that this location should be +added to the list of places to look for dependencies. + +This setup fine for development time, but is not a reasonable way of allowing end users to use your new runtime. Instead what +you want all the necessary code to be gather up so that the app is self-contained. This is what the following command does. +``` + dotnet publish +``` +After running this in the 'HelloWorld' directory you will see that the following path + +* helloWorld\bin\Debug\netcoreapp1.1\win7-x64\publish + +Has all the binaries needed, including the CoreCLR.dll and System.Private.CoreLib.dll that you build locally. To +run the application simple run the EXE that is in this publish directory (it is the name of the app, or specified +in the project.json file). Thus at this point this directory has NO dependency outside this publication directory +(including dotnet.exe). You can copy this publication directory to another machine and run( the exe in it and +will 'just work'. Note that your managed app's code is still in the 'app'.dll file, the 'app'.exe file is +actually simply a rename of dotnet.exe. + +### Step 7: (Optional) Confirm that the app used your new runtime + +Congratulations, you have successfully used your newly built runtime. To confirm that everything worked, you +should compare the file creation timestamps for the CoreCLR.dll and System.Private.Runtime.dll in the publishing +directory and the build output directory. They should be identical. If not, something went wrong and the +dotnet tool picked up a different version of your runtime. + +### Step 8: Update BuildNumberMinor Environment Variable! + +One possible problem with the technique above is that Nuget assumes that distinct builds have distinct version numbers. +Thus if you modify the source and create a new NuGet package you must it a new version number and use that in your +application's project.json. Otherwise the dotnet.exe tool will assume that the existing version is fine and you +won't get the updated bits. This is what the Minor Build number is all about. By default it is 0, but you can +give it a value by setting the BuildNumberMinor environment variable. +```bat + set BuildNumberMinor=3 +``` +before packaging. You should see this number show up in the version number (e.g. 1.2.0-beta-24521-03). + +As an alternative you can delete the existing copy of the package from the Nuget cache. For example on +windows (on Linux substitute ~/ for %HOMEPATH%) you could delete +```bat + %HOMEPATH%\.nuget\packages\Microsoft.NETCore.Runtime.CoreCLR\1.2.0-beta-24521-02 +``` +which should make things work (but is fragile, confirm wile file timestamps that you are getting the version you expect) + + +## Step 8.1 (Optional) Quick updates in place. + +The 'dotnet publish' step in step 6 above creates a directory that has all the files necessary to run your app +including the CoreCLR and the parts of CoreFX that were needed. You can use this fact to skip some steps if +you wish to update the DLLs. For example typically when you update CoreCLR you end up updating one of two DLLs + +* coreclr.dll - Most modifications (with the exception of the JIT compiler and tools) that are C++ code update + this DLL. +* System.Private.CoreLib.dll - If you modified C# it will end up here. +* System.Private.CoreLib.ni.dll - the native image (code) for System.Private.Corelib. If you modify C# code +you will want to update both of these together in the target installation. + +Thus after making a change and building, you can simply copy the updated binary from the `bin\Product\..` +directory to your publication directory (e.g. `helloWorld\bin\Debug\netcoreapp1.1\win7-x64\publish`) to quickly +deploy your new bits. You can build just the .NET Library part of the build by doing (debug, for release add 'release qualifier) +(on Linux / OSX us ./build.sh) +```bat + .\build skiptests skipnative +``` +Which builds System.Private.CoreLib.dll AND System.Private.CoreLib.ni.dll (you will always want both) if you modify +C# code. If you wish to only compile the coreclr.dll you can do + ```bat + .\build skiptests skipmscorlib +``` +Note that this technique does not work on .NET Apps that have not been published (that is you have not created +a directory with all DLLs needed to run the all) That is because the runtime is either fetched from the system-wide +location that dotnet.exe installed, OR it is fetched from the local nuget package cache (which is where your +build was put when you did a 'dotnet restore' and had a dependency on your particular runtime). In theory you +could update these locations in place, but that is not recommended since they are shared more widely. + +### Using your Runtime For Real. + +You can see that it is straightforward for anyone to use your runtime. They just need to modify their project.json +and modify their NuGet search path. This is the expected way of distributing your modified runtime. + +-------------------------- +## Using CoreRun to run your .NET Core Application + +Generally using dotnet.exe tool to run your .NET Core application is the preferred mechanism to run .NET Core Apps. +However there is a simpler 'host' for .NET Core applications called 'CoreRun' that can also be used. The value +of this host is that it is simpler (in particular it knows nothing about NuGet), but precisely because of this +it can be harder to use (since you are responsible for insuring all the dependencies you need are gather together) +See [Using CoreRun To Run .NET Core Application](UsingCoreRun.md) for more. diff --git a/DotnetCLIVersion.txt b/DotnetCLIVersion.txt index dd7bc31..b0f8213 100644 --- a/DotnetCLIVersion.txt +++ b/DotnetCLIVersion.txt @@ -1 +1 @@ -1.0.0-preview2-002733 \ No newline at end of file +1.0.0-preview3-003223 \ No newline at end of file diff --git a/README.md b/README.md index ffcffff..98dcb1a 100644 --- a/README.md +++ b/README.md @@ -1,106 +1,232 @@ -.NET Core Runtime (CoreCLR) +.NET Core Common Language Runtime (CoreCLR) =========================== -The CoreCLR repo contains the complete runtime implementation for [.NET Core](http://github.com/dotnet/core). It includes RyuJIT, the .NET GC, native interop and many other components. It is cross-platform, with multiple OS and CPU ports in progress. +This repository contains complete source code the runtime of [.NET Core](http://dotnet.github.io). +If you are new to .NET Core start with the [About .NET](https://docs.microsoft.com/en-us/dotnet/articles/about/) +that quickly points you to [.NET Core Tutorials](https://docs.microsoft.com/en-us/dotnet/articles/core/getting-started) + + +.NET Core is best thought of as 'agile .NET'. Generally speaking it is the same as +the [Desktop .NET Framework](https://en.wikipedia.org/wiki/.NET_Framework) +distributed as part of the Windows operating system, but it is a cross platform +(Windows, Linux, OSX) and cross architecture (x86, x64, arm) subset that can be deployed +as part of the application (if desired), and thus can be updated quickly to fix bugs or add features. + +## If You Just Want to Use .NET Core + +Most users don't need to build .NET Core from source since there is already an built and tested version for any supported platform. +You can get the latest **released** version of the .NET Core SDK by following the instructions on +the [.NET Core Getting Started](http://dotnet.github.io/getting-started/) page. +If you need the most up to date (daily) version of this .NET Core installer you can get it from the +[latest Installers of .NET Core and .NET Core SDK](https://github.com/dotnet/cli#installers-and-binaries). + +## Are you Here for Something Besides the Source Code? + +In addition to providing the source code, this repository also acts as a useful nexus for things +related to .NET Core including: + + * Want to **learn more** about .NET Runtime Internals? See the [Documentation on the .NET Core Runtime](Documentation/README.md) page. + * Need to **log a issue** or Provide Feedback? See then [Issues and Feedback Page](Documentation/workflow/IssuesFeedbackEngagement.md) page. + * Want to **chat** with other members of the CoreCLR community? See the [Chat Section](Documentation/workflow/IssuesFeedbackEngagement.md#Chat-with-the-CoreCLR-community) page. + * Need a **current build** or **test results** of the CoreCLR repository? See the [Official and Daily Builds](Documentation/workflow/OfficalAndDailyBuilds.md) page. + * If you want powerful search of the source code for both CoreClr and CoreFx see [.NET Source Code Index](https://source.dot.net) + +## What Can you Make from this Repository? + +.NET Core relies heavily on the [Nuget](https://en.wikipedia.org/wiki/NuGet) package manager, +which is a system to package, distribute and version software components. See [https://www.nuget.org/](https://www.nuget.org/) +for more information on Nuget. For now it is enough to know Nuget is a system that +bundles components into `*.nupkg` files (which are ZIP archives) and these packages can be 'published' +either through a local file system path or by a URL (e.g. https://www.nuget.org/). There are then tools +(e.g. Nuget.exe, Visual Studio, dotnet.exe) that based on a configuration file (project.json) know +how to search these publishing locations and pull down consistent set of packages for the +application. + +In concrete terms, this repository is best thought of as the source code for the following Nuget package + + * **Microsoft.NETCore.Runtime.CoreCLR** - Represents the object allocator, garbage collector (GC), class + loader, type system, interop and the most fundamental parts of the .NET class library (e.g. + System.Object, System.String ...) + +It also contains the source code for the following closely related support packages. + + * **Microsoft.NETCore.Jit** - The Just In Time (JIT) compiler for the + [.NET Intermediate language (IL)](https://en.wikipedia.org/wiki/Common_Intermediate_Language) + * **Microsoft.NETCore.ILAsm** - An assembler for the + [.NET Intermediate language (IL)](https://en.wikipedia.org/wiki/Common_Intermediate_Language) + * **Microsoft.NETCore.ILDAsm** - A disassembler (Pretty printer) for the + [.NET Intermediate language (IL)](https://en.wikipedia.org/wiki/Common_Intermediate_Language) + * **Microsoft.NETCore.TestHost** - This contains the corehost.exe program, which is a small wrapper + that uses the .NET Runtime to run IL DLLs passed to it on the command line. + * **Microsoft.TargetingPack.Private.CoreCLR** - A set of assemblies that represent the compile time surface + area of the class library implemented by the runtime itself. + +## Relationship with the [CoreFX](https://github.com/dotnet/corefx) Repository + +By itself, the Microsoft.NETCore.Runtime.CoreCLR package is actually not enough to do much. +One reason for this is that the CoreCLR package tries to minimize the amount of the class library that it implements. +Only types that have a strong dependency on the internal workings of the runtime are included (e.g, +System.Object, System.String System.Thread, System.Threading.Tasks.Task and most foundational interfaces). +Instead most of the class library is implemented as independent Nuget packages that simply use the .NET Core +runtime as a dependency. Many of the most familiar classes (System.Collections, System.IO, System.Xml and +so on), live in packages defined in the [dotnet/corefx](https://github.com/dotnet/corefx) repository. + +But the main reason you can't do much with CoreCLR is that **ALL** of the types in the class library **LOOK** +like they are defined by the CoreFX framework and not CoreCLR. Any library code defined here +lives in a single DLL called System.Private.CoreLib.dll and as its name suggests is private (hidden). +Instead for any particular PUBLIC type defined in CoreCLR, we found the 'right' package in CoreFX where it naturally +belongs and use that package as its **public publishing** point. That 'facade' package then forwards references +to the (private) implementation in System.Private.CoreLib.dll defined here. +For example the *System.Runtime* package defined in CoreFX declares the PUBLIC name for types like +System.Object and System.String. Thus from an applications point of view these types live in System.Runtime.dll. +However, System.Runtime.dll (defined in the CoreFX repo) forwards references ultimately to System.Private.CoreLib.dll +which is defined here. + +Thus in order to run an application, you need BOTH the Microsoft.NETCore.Runtime.CoreCLR Nuget package +(defined in this repository) as well as packages for whatever you actually reference that were defined +in the CoreFX repository (which at a minimum includes the System.Runtime package). You also need some +sort of 'host' executable that loads the CoreCLR package as well as the CoreFX packages and starts your code (typically +you use dotnet.exe for this). + +These extra pieces are not defined here, however you don't need to build them in order to use the CoreCLR +Nuget package you create here. There are already versions of the CoreFX packages published on +https://www.nuget.org/ so you can have your test application's project.json specify the CoreCLR you +built and it will naturally pull anything else it needs from the official location https://www.nuget.org/ to +make a complete application. More on this in the [Using Your Build](Documentation/workflow/UsingYourBuild.md) page. + +-------------------------- +## Setting up your GIT Clone of the CoreCLR Repository + +The first step in making a build of the CoreCLR Repository is to clone it locally. If you already know +how to do this, just skip this section. Otherwise if you are developing on windows you can see +[Setting Up A Git Repository In Visual Studio 2015](https://github.com/Microsoft/perfview/blob/master/documentation/SettingUpRepoInVS2015.md) +for for instructions on setting up. This link uses a different repository as an example, but the issues (do you fork or not) and +the procedure are equally applicable to this repository. + +-------------------------- +## Building the Repository + +The build depends on GIT, CMAKE, Python and of course a C++ compiler. Once these prerequisites are installed +the build is simply a matter of invoking the 'Build' script (Build.cmd or build.sh) at the base of the +repository. + +The details of installing the components differ depending on the operating system. See the following +pages based on your OS. There is no cross-building across OS (only for ARM, which is built on X64). +You have to be on the particular platform to build that platform. + + * [Windows Build Instructions](Documentation/building/windows-instructions.md) + * [Linux Build Instructions](Documentation/building/linux-instructions.md) + * [OSX Build Instructions](Documentation/building/osx-instructions.md) + * [FreeBSD Build Instructions](Documentation/building/freebsd-instructions.md) + * [NetBSD Build Instructions](Documentation/building/netbsd-instructions.md) + +The build has two main 'buildTypes' + + * Debug (default)- This compiles the runtime with additional runtime checks (asserts). These checks slow + runtime execution but are really valuable for debugging, and is recommended for normal development and testing. + * Release - This compiles without any development time runtime checks. This is what end users will use but + can be difficult to debug. Passing 'release' to the build script select this. + +In addition, by default the build will not only create the runtime executables, but it will also +build all the tests. There are quite a few tests so this does take a significant amount of time +that is not necessary if you want to experiment with changes. You can submit the building +of the tests with the 'skiptests' argument to the build script. + +Thus to get a build as quickly as possible type the following (using \ as the directory separator, use / on Unix machines) +```bat + .\build skiptests +``` +which will build the Debug flavor which has development time checks (asserts), or +```bat + .\build release skiptests +``` +to build the release (full speed) flavor. You can find more build options with build by using the -? or -help qualifier. + +## Using Your Build + +The build places all of its generated files under the 'bin' directory at the base of the repository. There +is a 'bin\Log' directory that contains log files generated during the build (Most useful when the build fails). +The the actual output is placed in a directory like this + +* bin\Product\Windows_NT.x64.Release + +Where you can see the operating system and CPU architecture, and the build type are part of the name. While +the 'raw' output of the build is sometimes useful, normally you are only interested in the Nuget packages +that were built, which are placed in the directory + +* bin\Product\Windows_NT.x64.Release\.nuget\pkg + +These packages are the 'output' of your build. + +There are two basic techniques for using your new runtime. + + 1. **Use dotnet.exe and Nuget to compose an application**. See [Using Your Build](Documentation/workflow/UsingYourBuild.md) for + instructions on creating a program that uses + your new runtime by using the NuGet packages you just created and the'dotnet' command line interface. This + is the expected way non-runtime developers are likely to consume your new runtime. + + 2. **Use corerun.exe to run an application using unpackaged Dlls**. This repository also defines a simple host called + corerun.exe that does NOT take any dependency on NuGet. Basically it has to be told where to get all the + necessary DLLs you actually use, and you have to gather them together 'by hand'. This is the technique that + all the tests in the repo use, and is useful for quick local 'edit-compile-debug' loop (e.g. preliminary unit testsing). + See [Executing .NET Core Apps with CoreRun.exe](Documentation/workflow/UsingCoreRun.md) for details on using + this technique. + +## Editing and Debugging -Note that the library implementation CoreFX (System.Collections, System.IO, System.Xml and so on) lives in another repo [dotnet/corefx](https://github.com/dotnet/corefx). +Typically users run through the build and use instructions first with an unmodified build, just to familiarize +themselves with the procedures and to confirm that the instructions work. After that you will want to actually +make modifications and debug any issues those modifications might cause. See the following links for more. -Build Status ------------- + * [Editing and Debugging](Documentation/workflow/EditingAndDebugging.md) and + * [Documentation on the .NET Core Runtime](Documentation/README.md) -| | Debug | Release | -|---|:-----:|:-------:| -|**CentOS 7.1**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_centos7.1.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_centos7.1)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_centos7.1.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_centos7.1)| -|**Debian 8.4**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_debian8.4.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_debian8.4)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_debian8.4.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_debian8.4)| -|**FreeBSD 10.1**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_freebsd.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_freebsd)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_freebsd.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_freebsd)| -|**openSUSE 13.2**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_opensuse13.2.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_opensuse13.2)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_opensuse13.2.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_opensuse13.2)| -|**openSUSE 42.1**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_opensuse42.1.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_opensuse42.1)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_opensuse42.1.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_opensuse42.1)| -|**OS X 10.11**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_osx.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_osx)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_osx.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_osx)| -|**Red Hat 7.2**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_rhel7.2.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_rhel7.2)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_rhel7.2.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_rhel7.2)| -|**Fedora 23**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_fedora23.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_fedora23)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_fedora23.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_fedora23)| -|**Ubuntu 14.04**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_ubuntu.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_ubuntu)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_ubuntu.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_ubuntu)| -|**Ubuntu 16.04**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_ubuntu16.04.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_ubuntu16.04)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_ubuntu16.04.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_ubuntu16.04)| -|**Windows 8.1**|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/debug_windows_nt.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/debug_windows_nt)
[![arm64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/arm64_cross_debug_windows_nt.svg?label=arm64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/arm64_cross_debug_windows_nt)|[![x64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/release_windows_nt.svg?label=x64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/release_windows_nt)
[![arm64 status](https://img.shields.io/jenkins/s/http/dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/arm64_cross_release_windows_nt.svg?label=arm64)](http://dotnet-ci.cloudapp.net/job/dotnet_coreclr/job/master/job/arm64_cross_release_windows_nt)| +## Running Tests -Building the Repo -------------- +After you have your modification basically working, and want to determine if you have broken anything it is +time to runt tests. See [Running .NET Core Tests](Documentation/workflow/RunningTests.md) for more. -|Linux |Windows |Mac OS X |FreeBSD | NetBSD | -|--------|--------|---------|---------|--------| -| [Instructions](Documentation/building/linux-instructions.md) | [Instructions](Documentation/building/windows-instructions.md) | [Instructions](Documentation/building/osx-instructions.md) | [Instructions](Documentation/building/freebsd-instructions.md) | [Instructions](Documentation/building/netbsd-instructions.md) | +## Contributing to Repository -Get .NET Core ----------------------- -You can get the latest released .NET Core SDK from the [.NET Core Getting started](http://dotnet.github.io/getting-started/) page. You can also get the latest development builds of .NET Core and the SDK from the [dotnet/cli repo](https://github.com/dotnet/cli#installers-and-binaries). - -Chat Room ---------- - -Want to chat with other members of the CoreCLR community? - -[![.NET Slack Status](https://aspnetcoreslack.herokuapp.com/badge.svg?2)](http://tattoocoder.com/aspnet-slack-sign-up/) [![Join the chat at https://gitter.im/dotnet/coreclr](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/dotnet/coreclr?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - -Learn about CoreCLR and .NET Core ---------------------------------- - -The best ways to learn about CoreCLR are to try out the product instructions and to read the "Book of the Runtime" architecture documents that describe the inner workings of the product. New devs to the CLR team are encouraged to read these documents before making substative changes to the product. They are equally useful for open source contributors. - -- [.NET Core Roadmap](https://github.com/dotnet/core/blob/master/roadmap.md) -- [Product instructions](Documentation/README.md) -- [Introduction to the Common Language Runtime](Documentation/botr/intro-to-clr.md) -- [Book of the Runtime](Documentation/README.md#book-of-the-runtime) -- [CoreCLR Documents](Documentation) - -.NET Core is part of ASP.NET Core and is a subset of the .NET Framework. You can learn more about .NET Core and how and where you can use it in the [CoreCLR is open source][coreclr blog post] blog post. - -The [.NET Core Libraries][corefx] repo contains the base class libraries, which provides data types and base functionality (ex: String, Collections, HttpClient) on top of CoreCLR. The two repos together make up .NET Core. The [.NET Core is Open Source][.NET Core oss] and [Introducing .NET Core][Introducing .NET Core] blog posts describes our .NET Core OSS strategy and road map in more detail. - -Engage, Contribute and Provide Feedback ---------------------------------------- - -Some of the best ways to contribute are to try things out, file bugs, and join in design conversations. You are encouraged to start a discussion by filing an issue, or starting a thread in the [.NET Foundation forums](http://forums.dotnetfoundation.org/). If you are having issues with the Full .NET Framework or .NET Runtime the best ways to file a bug are at [Connect](http://connect.microsoft.com/VisualStudio) or through [Product Support](https://support.microsoft.com/en-us/contactus?ws=support) if you have a contract. - -Looking for something to work on? The list of [up-for-grabs issues](https://github.com/dotnet/coreclr/issues?q=is%3Aopen+is%3Aissue+label%3Aup-for-grabs) is a great place to start. +Looking for something to work on? The list +of [up-for-grabs issues](https://github.com/dotnet/coreclr/issues?q=is%3Aopen+is%3Aissue+label%3Aup-for-grabs) is a great place to start. Please read the following documents to get started. * [Contributing Guide](Documentation/project-docs/contributing.md) * [Developer Guide](Documentation/project-docs/developer-guide.md) -This project has adopted the code of conduct defined by the [Contributor Covenant](http://contributor-covenant.org/) to clarify expected behavior in our community. For more information, see the [.NET Foundation Code of Conduct](http://www.dotnetfoundation.org/code-of-conduct). +This project has adopted the code of conduct defined by the [Contributor Covenant](http://contributor-covenant.org/) +to clarify expected behavior in our community. For more information, see the [.NET Foundation Code of Conduct](http://www.dotnetfoundation.org/code-of-conduct). -### Reporting security issues and security bugs +------------------- +## Related Projects -Security issues and bugs should be reported privately, via email, to the -Microsoft Security Response Center (MSRC) . You should -receive a response within 24 hours. If for some reason you do not, please follow -up via email to ensure we received your original message. Further information, -including the MSRC PGP key, can be found in the -[Security TechCenter](https://technet.microsoft.com/en-us/security/ff852094.aspx). +As noted above, the CoreCLR Repository does not contain all the source code that makes up the .NET Core distribution. +Here is a list of the other repositories that complete the picture. -License -------- +* [dotnet/corefx](https://github.com/dotnet/corefx) - Source for the most common classes in the .NET Framework library. +* [dotnet/core-setup](https://github.com/dotnet/core-setup) - Source code for the dotnet.exe program and the policy logic +to launch basic .NET Core code (hostfxr, hostpolicy) which allow you to say 'dotnet SOME_CORE_CLR_DLL' to run the app. +* [dotnet/cli repo](https://github.com/dotnet/cli) - Source for build time actions supported by dotnet.exe Command line Interface (CLI). +Thus this is the code that runs when you do 'dotnet build', 'dotnet restore' or 'dotnet publish'. +* [dotnet/core-docs](https://github.com/dotnet/core-docs) - Master copy of documentation for +[http://docs.microsoft.com/en-us/dotnet/](https://docs.microsoft.com/en-us/dotnet/) -.NET Core (including the coreclr repo) is licensed under the [MIT license](LICENSE.TXT). - -.NET Foundation ---------------- +## See Also -.NET Core is a [.NET Foundation](http://www.dotnetfoundation.org/projects) project. +* [Dotnet.github.io](http://dotnet.github.io) is a good place to discover .NET Foundation projects. +* .NET Core is a [.NET Foundation](http://www.dotnetfoundation.org/projects) project. +* [.NET home repo](https://github.com/Microsoft/dotnet) links to 100s of .NET projects, from Microsoft and the community. +* The [.NET Core repo](https://github.com/dotnet/core) links to .NET Core related projects from Microsoft. +* The [ASP.NET home repo](https://github.com/aspnet/home) is the best place to start learning about ASP.NET Core. -Related Projects ----------------- +## Important Blog Entries -There are many .NET projects on GitHub. +* [Announcement of .NET Core Open Source Project](http://blogs.msdn.com/b/dotnet/archive/2014/11/12/net-core-is-open-source.aspx) +* [Introducing .NET Core](http://blogs.msdn.com/b/dotnet/archive/2014/12/04/introducing-net-core.aspx) +* [Announcement of CoreCLR](http://blogs.msdn.com/b/dotnet/archive/2015/02/03/coreclr-is-now-open-source.aspx) -- The -[.NET home repo](https://github.com/Microsoft/dotnet) links to 100s of .NET projects, from Microsoft and the community. -- The [.NET Core repo](https://github.com/dotnet/core) links to .NET Core related projects from Microsoft. -- The [ASP.NET home repo](https://github.com/aspnet/home) is the best place to start learning about ASP.NET Core. -- [dotnet.github.io](http://dotnet.github.io) is a good place to discover .NET Foundation projects. +## License -[.NET Core oss]: http://blogs.msdn.com/b/dotnet/archive/2014/11/12/net-core-is-open-source.aspx -[Introducing .NET Core]: http://blogs.msdn.com/b/dotnet/archive/2014/12/04/introducing-net-core.aspx -[coreclr blog post]: http://blogs.msdn.com/b/dotnet/archive/2015/02/03/coreclr-is-now-open-source.aspx -[corefx]: http://github.com/dotnet/corefx -[coreclr]: http://github.com/dotnet/coreclr +.NET Core (including the coreclr repo) is licensed under the [MIT license](LICENSE.TXT). diff --git a/binclash.log b/binclash.log new file mode 100755 index 0000000..e69de29 diff --git a/build-packages.cmd b/build-packages.cmd index 3297bfc..f80e39f 100644 --- a/build-packages.cmd +++ b/build-packages.cmd @@ -1,4 +1,4 @@ -@if "%_echo%" neq "on" echo off +@if not defined _echo @echo off setlocal EnableDelayedExpansion set "__ProjectDir=%~dp0" @@ -7,39 +7,9 @@ set allargs=%* if /I [%1] == [/?] goto Usage if /I [%1] == [/help] goto Usage -call %__ProjectDir%/run.cmd build-packages -Project=%__ProjectDir%/src/.nuget/Microsoft.NETCore.Runtime.CoreClr/Microsoft.NETCore.Runtime.CoreCLR.builds -FilterToOSGroup=Windows_NT %allargs% +call %__ProjectDir%/run.cmd build-packages -Project=%__ProjectDir%\src\.nuget\packages.builds -FilterToOSGroup=Windows_NT %allargs% if NOT [!ERRORLEVEL!]==[0] ( - echo ERROR: An error occurred while building CoreCLR Runtime package, see build-packages.log for more details. - exit /b 1 -) - -call %__ProjectDir%/run.cmd build-packages -Project=%__ProjectDir%/src/.nuget/Microsoft.NETCore.Jit/Microsoft.NETCore.Jit.builds -FilterToOSGroup=Windows_NT %allargs% -if NOT [!ERRORLEVEL!]==[0] ( - echo ERROR: An error occurred while building Jit package, see build-packages.log for more details. - exit /b 1 -) - -call %__ProjectDir%/run.cmd build-packages -Project=%__ProjectDir%/src/.nuget/Microsoft.NETCore.ILAsm/Microsoft.NETCore.ILAsm.builds -FilterToOSGroup=Windows_NT %allargs% -if NOT [!ERRORLEVEL!]==[0] ( - echo ERROR: An error occurred while building ILAsm package, see build-packages.log for more details. - exit /b 1 -) - -call %__ProjectDir%/run.cmd build-packages -Project=%__ProjectDir%/src/.nuget/Microsoft.NETCore.ILDAsm/Microsoft.NETCore.ILDAsm.builds -FilterToOSGroup=Windows_NT %allargs% -if NOT [!ERRORLEVEL!]==[0] ( - echo ERROR: An error occurred while building ILDAsm package, see build-packages.log for more details. - exit /b 1 -) - -call %__ProjectDir%/run.cmd build-packages -Project=%__ProjectDir%/src/.nuget/Microsoft.TargetingPack.Private.CoreCLR/Microsoft.TargetingPack.Private.CoreCLR.pkgproj -FilterToOSGroup=Windows_NT %allargs% -if NOT [!ERRORLEVEL!]==[0] ( - echo ERROR: An error occurred while building CoreCLR TargetingPack package, see build-packages.log for more details. - exit /b 1 -) - -call %__ProjectDir%/run.cmd build-packages -Project=%__ProjectDir%\src\.nuget\Microsoft.NETCore.TestHost\Microsoft.NETCore.TestHost.builds -FilterToOSGroup=Windows_NT %allargs% -if NOT [!ERRORLEVEL!]==[0] ( - echo ERROR: An error occurred while building packages, see %packagesLog% for more details. + echo ERROR: An error occurred while building packages, see build-packages.log for more details. exit /b 1 ) diff --git a/build-packages.sh b/build-packages.sh index 5e03ac2..0dd1035 100755 --- a/build-packages.sh +++ b/build-packages.sh @@ -3,14 +3,56 @@ usage() { echo "Builds the NuGet packages from the binaries that were built in the Build product binaries step." - echo "Usage: build-packages -BuildArch -BuildType" - echo "arch can be x64, x86, arm, arm64 (default is x64)" - echo "configuration can be release, checked, debug (default is debug)" + echo "Usage: build-packages -BuildArch -BuildType [portableLinux]" + echo "BuildArch can be x64, x86, arm, arm64 (default is x64)" + echo "BuildType can be release, checked, debug (default is debug)" + echo "portableLinux - build for Portable Linux Distribution" echo exit 1 } __ProjectRoot="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +__PortableLinux=0 + +# Use uname to determine what the OS is. +OSName=$(uname -s) +case $OSName in + Linux) + __BuildOS=Linux + __HostOS=Linux + ;; + + Darwin) + __BuildOS=OSX + __HostOS=OSX + ;; + + FreeBSD) + __BuildOS=FreeBSD + __HostOS=FreeBSD + ;; + + OpenBSD) + __BuildOS=OpenBSD + __HostOS=OpenBSD + ;; + + NetBSD) + __BuildOS=NetBSD + __HostOS=NetBSD + ;; + + SunOS) + __BuildOS=SunOS + __HostOS=SunOS + ;; + + *) + echo "Unsupported OS $OSName detected, configuring as if for Linux" + __BuildOS=Linux + __HostOS=Linux + ;; +esac unprocessedBuildArgs= @@ -28,46 +70,34 @@ while :; do unprocessedBuildArgs="$unprocessedBuildArgs $1" __Arch=$(echo $1| cut -d'=' -f 2) ;; + + portableLinux) + if [ "$__BuildOS" == "Linux" ]; then + __PortableLinux=1 + else + echo "ERROR: portableLinux not supported for non-Linux platforms." + exit 1 + fi + ;; *) unprocessedBuildArgs="$unprocessedBuildArgs $1" esac shift done -$__ProjectRoot/run.sh build-packages -Project=$__ProjectRoot/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/Microsoft.NETCore.Runtime.CoreCLR.builds -DistroRid=\${OSRid}-$__Arch -UseSharedCompilation=false -BuildNugetPackage=false $unprocessedBuildArgs -if [ $? -ne 0 ] -then - echo "ERROR: An error occurred while building packages; See build-packages.log for more details." - exit 1 -fi - -$__ProjectRoot/run.sh build-packages -Project=$__ProjectRoot/src/.nuget/Microsoft.NETCore.Jit/Microsoft.NETCore.Jit.builds -DistroRid=\${OSRid}-$__Arch -UseSharedCompilation=false -BuildNugetPackage=false $unprocessedBuildArgs -if [ $? -ne 0 ] -then - echo "ERROR: An error occurred while building packages; See build-packages.log for more details." - exit 1 +# Portable builds target the base RID only for Linux based platforms +if [ $__PortableLinux == 1 ]; then + export __DistroRid="linux-$__Arch" +else + export __DistroRid="\${OSRid}-$__Arch" fi -$__ProjectRoot/run.sh build-packages -Project=$__ProjectRoot/src/.nuget/Microsoft.NETCore.ILAsm/Microsoft.NETCore.ILAsm.builds -DistroRid=\${OSRid}-$__Arch -UseSharedCompilation=false -BuildNugetPackage=false $unprocessedBuildArgs +$__ProjectRoot/run.sh build-packages -Project=$__ProjectRoot/src/.nuget/packages.builds -DistroRid=$__DistroRid -UseSharedCompilation=false -BuildNugetPackage=false $unprocessedBuildArgs if [ $? -ne 0 ] then echo "ERROR: An error occurred while building packages; See build-packages.log for more details." exit 1 fi -$__ProjectRoot/run.sh build-packages -Project=$__ProjectRoot/src/.nuget/Microsoft.NETCore.ILDAsm/Microsoft.NETCore.ILDAsm.builds -DistroRid=\${OSRid}-$__Arch -UseSharedCompilation=false -BuildNugetPackage=false $unprocessedBuildArgs -if [ $? -ne 0 ] -then - echo "ERROR: An error occurred while building packages; See build-packages.log for more details." - exit 1 -fi - -# Build the TestHost package -$__ProjectRoot/run.sh build-packages -Project=$__ProjectRoot/src/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.builds -DistroRid=\${OSRid}-$__Arch -UseSharedCompilation=false -BuildNugetPackage=false $unprocessedBuildArgs -if [ $? -ne 0 ]; then - echo "ERROR: An error occurred while building packages, see $build_packages_log for more details." - exit 1 -fi - echo "Done building packages." exit 0 diff --git a/build-test.cmd b/build-test.cmd index d22b489..215fb53 100644 --- a/build-test.cmd +++ b/build-test.cmd @@ -1,4 +1,4 @@ -@if not defined __echo @echo off +@if not defined _echo @echo off setlocal EnableDelayedExpansion :: Set the default arguments for build @@ -28,6 +28,9 @@ set "__args= %*" set processedArgs= set __unprocessedBuildArgs= set __RunArgs= +set __BuildAgainstPackages= +set __BuildAgainstPackagesArg= +set __RuntimeId= :Arg_Loop if "%1" == "" goto ArgsDone @@ -48,6 +51,8 @@ if /i "%1" == "checked" (set __BuildType=Checked&set processedArgs if /i "%1" == "skipmanaged" (set __SkipManaged=1&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) if /i "%1" == "updateinvalidpackages" (set __UpdateInvalidPackagesArg=1&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) if /i "%1" == "toolset_dir" (set __ToolsetDir=%2&set __PassThroughArgs=%__PassThroughArgs% %2&set processedArgs=!processedArgs! %1 %2&shift&shift&goto Arg_Loop) +if /i "%1" == "buildagainstpackages" (set __BuildAgainstPackages=1&set __BuildAgainstPackagesArg=-BuildTestsAgainstPackages&shift&goto Arg_Loop) +if /i "%1" == "runtimeid" (set __RuntimeId=%2&set processedArgs=!processedArgs! %1 %2&shift&shift&goto Arg_Loop) if [!processedArgs!]==[] ( call set __UnprocessedBuildArgs=!__args! @@ -93,7 +98,7 @@ if not exist "%__LogsDir%" md "%__LogsDir%" echo %__MsgPrefix%Checking prerequisites :: Eval the output from probe-win1.ps1 -for /f "delims=" %%a in ('powershell -NoProfile -ExecutionPolicy RemoteSigned "& ""%__SourceDir%\pal\tools\probe-win.ps1"""') do %%a +for /f "delims=" %%a in ('powershell -NoProfile -ExecutionPolicy ByPass "& ""%__SourceDir%\pal\tools\probe-win.ps1"""') do %%a REM ========================================================================================= REM === @@ -129,7 +134,7 @@ if defined __ToolsetDir ( :: Set the environment for the native build echo %__MsgPrefix%Using environment: "%__VSToolsRoot%\..\..\VC\vcvarsall.bat" %__VCBuildArch% call "%__VSToolsRoot%\..\..\VC\vcvarsall.bat" %__VCBuildArch% -@if defined __echo @echo on +@if defined _echo @echo on if not defined VSINSTALLDIR ( echo %__MsgPrefix%Error: VSINSTALLDIR variable not defined. @@ -141,7 +146,7 @@ if not exist "%VSINSTALLDIR%DIA SDK" goto NoDIA pushd "%__NativeTestIntermediatesDir%" call "%__SourceDir%\pal\tools\gen-buildsys-win.bat" ""%__ProjectFilesDir%"" %__VSVersion% %__BuildArch% -@if defined __echo @echo on +@if defined _echo @echo on popd if not exist "%__NativeTestIntermediatesDir%\install.vcxproj" ( @@ -176,21 +181,56 @@ if errorlevel 1 ( :skipnative -if defined __SkipManaged exit /b 0 +set __BuildLogRootName=Restore_Product +set __BuildLog=%__LogsDir%\%__BuildLogRootName%_%__BuildOS%__%__BuildArch%__%__BuildType%.log +set __BuildWrn=%__LogsDir%\%__BuildLogRootName%_%__BuildOS%__%__BuildArch%__%__BuildType%.wrn +set __BuildErr=%__LogsDir%\%__BuildLogRootName%_%__BuildOS%__%__BuildArch%__%__BuildType%.err +set __msbuildLog=/flp:Verbosity=normal;LogFile="%__BuildLog%" +set __msbuildWrn=/flp1:WarningsOnly;LogFile="%__BuildWrn%" +set __msbuildErr=/flp2:ErrorsOnly;LogFile="%__BuildErr%" +if not defined __BuildAgainstPackages goto SkipRestoreProduct REM ========================================================================================= REM === -REM === Managed test build section +REM === Restore product binaries from packages REM === REM ========================================================================================= -echo %__MsgPrefix%Starting the Managed Tests Build +set "__TestWorkingDir=%__RootBinDir%\tests\%__BuildOS%.%__BuildArch%.%__BuildType%" +if not defined XunitTestBinBase set XunitTestBinBase=%__TestWorkingDir% +set "CORE_ROOT=%XunitTestBinBase%\Tests\Core_Root" +set "CORE_OVERLAY=%XunitTestBinBase%\Tests\coreoverlay" -if not defined VSINSTALLDIR ( - echo %__MsgPrefix%Error: buildtest.cmd should be run from a Visual Studio Command Prompt. Please see https://github.com/dotnet/coreclr/blob/master/Documentation/project-docs/developer-guide.md for build instructions. +call %__ProjectDir%\run.cmd build -Project=%__ProjectDir%\tests\build.proj -UpdateDependencies -BatchRestorePackages -MsBuildLog=!__msbuildLog! -MsBuildWrn=!__msbuildWrn! -MsBuildErr=!__msbuildErr! %__RunArgs% %__BuildAgainstPackagesArg% %__unprocessedBuildArgs% + +set __BuildLogRootName=Tests_GenerateRuntimeLayout + +call %__ProjectDir%\run.cmd build -Project=%__ProjectDir%\tests\runtest.proj -BinPlaceRef -BinPlaceProduct -CopyCrossgenToProduct -MsBuildLog=!__msbuildLog! -MsBuildWrn=!__msbuildWrn! -MsBuildErr=!__msbuildErr! %__RunArgs% %__BuildAgainstPackagesArg% %__unprocessedBuildArgs% +if errorlevel 1 ( + echo BinPlace of mscorlib.dll failed exit /b 1 ) +if defined __RuntimeId ( + + if not exist %__PackagesDir%\TestNativeBins ( + echo %__MsgPrefix%Error: Ensure you have run sync.cmd -ab before building a non-Windows test overlay against packages + exit /b 1 + ) + + call %__ProjectDir%\run.cmd build -Project=%__ProjectDir%\tests\runtest.proj -CreateNonWindowsTestOverlay -RuntimeId="%__RuntimeId%" -MsBuildLog=!__msbuildLog! -MsBuildWrn=!__msbuildWrn! -MsBuildErr=!__msbuildErr! %__RunArgs% %__BuildAgainstPackagesArg% %__unprocessedBuildArgs% + for /R %__PackagesDir%\TestNativeBins\%__RuntimeId% %%f in (*.so) do copy %%f %Core_Overlay% + for /R %__PackagesDir%\TestNativeBins\%__RuntimeId% %%f in (*.dylib) do copy %%f %Core_Overlay% + + echo %__MsgPrefix% Created the runtime layout for %__RuntimeId% in %CORE_OVERLAY% +) + +echo %__MsgPrefix% Created the runtime layout with all dependencies in %CORE_ROOT% + +:SkipRestoreProduct + +if defined __SkipManaged exit /b 0 + set __BuildLogRootName=Tests_Managed set __BuildLog=%__LogsDir%\%__BuildLogRootName%_%__BuildOS%__%__BuildArch%__%__BuildType%.log set __BuildWrn=%__LogsDir%\%__BuildLogRootName%_%__BuildOS%__%__BuildArch%__%__BuildType%.wrn @@ -199,6 +239,19 @@ set __msbuildLog=/flp:Verbosity=normal;LogFile="%__BuildLog%" set __msbuildWrn=/flp1:WarningsOnly;LogFile="%__BuildWrn%" set __msbuildErr=/flp2:ErrorsOnly;LogFile="%__BuildErr%" +REM ========================================================================================= +REM === +REM === Managed test build section +REM === +REM ========================================================================================= + +echo %__MsgPrefix%Starting the Managed Tests Build + +if not defined VSINSTALLDIR ( + echo %__MsgPrefix%Error: buildtest.cmd should be run from a Visual Studio Command Prompt. Please see https://github.com/dotnet/coreclr/blob/master/Documentation/project-docs/developer-guide.md for build instructions. + exit /b 1 +) + if defined __UpdateInvalidPackagesArg ( set __up=-updateinvalidpackageversions ) @@ -253,6 +306,17 @@ echo. -? -h -help: view this message. echo Build architecture: -buildArch: only x64 is currently allowed ^(default: x64^). echo Build type: -buildType: one of Debug, Checked, Release ^(default: Debug^). echo updateinvalidpackageversions: Runs the target to update package versions. +echo buildagainstpackages: builds tests against restored packages, instead of against a built product. +echo runtimeid ^: Builds a test overlay for the specified OS (Only supported when building against packages). Supported IDs are: +echo debian.8-x64: Builds overlay for Debian 8 +echo fedora.23-x64: Builds overlay for Fedora 23 +echo opensuse.13.2-x64: Builds overlay for OpenSUSE 13.2 +echo opensuse.42.1-x64: Builds overlay for OpenSUSE 42.1 +echo osx.10.10-x64: Builds overlay for OSX 10.10 +echo rhel.7-x64: Builds overlay for RHEL 7 or CentOS +echo ubuntu.14.04-x64: Builds overlay for Ubuntu 14.04 +echo ubuntu.16.04-x64: Builds overlay for Ubuntu 16.04 +echo ubuntu.16.10-x64: Builds overlay for Ubuntu 16.10 echo -- ... : all arguments following this tag will be passed directly to msbuild. echo -priority=^ : specify a set of test that will be built and run, with priority N. echo 0: Build only priority 0 cases as essential testcases (default) diff --git a/build.cmd b/build.cmd index 2dc479c..f8c49e3 100644 --- a/build.cmd +++ b/build.cmd @@ -1,6 +1,7 @@ -@if not defined __echo @echo off +@if not defined _echo @echo off setlocal EnableDelayedExpansion EnableExtensions +echo Starting Build at %TIME% set __ThisScriptFull="%~f0" set __VSToolsRoot=%VS140COMNTOOLS% :: Note that the msbuild project files (specifically, dir.proj) will use the following variables, if set: @@ -51,6 +52,7 @@ set __BuildTypeDebug=0 set __BuildTypeChecked=0 set __BuildTypeRelease=0 set __BuildJit32="-DBUILD_JIT32=0" +set __BuildStandaloneGC="-DFEATURE_STANDALONE_GC=0" set __PgoInstrument=0 @@ -107,6 +109,12 @@ if /i "%1" == "usenmakemakefiles" (set __NMakeMakefiles=1&set __ConfigureOnly= if /i "%1" == "buildjit32" (set __BuildJit32="-DBUILD_JIT32=1"&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) if /i "%1" == "pgoinstrument" (set __PgoInstrument=1&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) if /i "%1" == "toolset_dir" (set __ToolsetDir=%2&set __PassThroughArgs=%__PassThroughArgs% %2&set processedArgs=!processedArgs! %1 %2&shift&shift&goto Arg_Loop) +if /i "%1" == "compatjitcrossgen" (set __CompatJitCrossgen=1&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) +if /i "%1" == "legacyjitcrossgen" (set __LegacyJitCrossgen=1&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) +if /i "%1" == "buildstandalonegc" (set __BuildStandaloneGC="-DFEATURE_STANDALONE_GC=1"&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) + +@REM The following can be deleted once the CI system that passes it is updated to not pass it. +if /i "%1" == "altjitcrossgen" (set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) if [!processedArgs!]==[] ( call set __UnprocessedBuildArgs=!__args! @@ -170,13 +178,18 @@ if not exist "%__BinDir%" md "%__BinDir%" if not exist "%__IntermediatesDir%" md "%__IntermediatesDir%" if not exist "%__LogsDir%" md "%__LogsDir%" +REM It is convinient to have your Nuget search path include the location where the build +REM will plass packages. However nuget used during the build will fail if that directory +REM does not exist. Avoid this in at least one case by agressively creating the directory. +if not exist "%__BinDir%\.nuget\pkg" md "%__BinDir%\.nuget\pkg" + echo %__MsgPrefix%Commencing CoreCLR Repo build :: Set the remaining variables based upon the determined build configuration echo %__MsgPrefix%Checking prerequisites :: Eval the output from probe-win1.ps1 -for /f "delims=" %%a in ('powershell -NoProfile -ExecutionPolicy RemoteSigned "& ""%__SourceDir%\pal\tools\probe-win.ps1"""') do %%a +for /f "delims=" %%a in ('powershell -NoProfile -ExecutionPolicy ByPass "& ""%__SourceDir%\pal\tools\probe-win.ps1"""') do %%a REM ========================================================================================= REM === @@ -191,15 +204,6 @@ call "%__VSToolsRoot%\VsDevCmd.bat" REM ========================================================================================= REM === -REM === Restore optimization profile data -REM === -REM ========================================================================================= - -echo %__MsgPrefix%Restoring the OptimizationData Package -@call %__ProjectDir%\run.cmd sync -optdata - -REM ========================================================================================= -REM === REM === Build the CLR VM REM === REM ========================================================================================= @@ -224,25 +228,32 @@ if %__BuildNative% EQU 1 ( :: Set the environment for the native build set __VCBuildArch=x86_amd64 if /i "%__BuildArch%" == "x86" ( set __VCBuildArch=x86 ) - if /i "%__BuildArch%" == "arm" (set __VCBuildArch=x86_arm) + if /i "%__BuildArch%" == "arm" ( + set __VCBuildArch=x86_arm + + REM Make CMake pick the highest installed version in the 10.0.* range + set ___SDKVersion="-DCMAKE_SYSTEM_VERSION=10.0" + ) + echo %__MsgPrefix%Using environment: "%__VSToolsRoot%\..\..\VC\vcvarsall.bat" !__VCBuildArch! call "%__VSToolsRoot%\..\..\VC\vcvarsall.bat" !__VCBuildArch! - @if defined __echo @echo on + @if defined _echo @echo on if not defined VSINSTALLDIR ( echo %__MsgPrefix%Error: VSINSTALLDIR variable not defined. exit /b 1 ) if not exist "!VSINSTALLDIR!DIA SDK" goto NoDIA + :GenVSSolution if defined __SkipConfigure goto SkipConfigure echo %__MsgPrefix%Regenerating the Visual Studio solution pushd "%__IntermediatesDir%" - set __ExtraCmakeArgs="-DCLR_CMAKE_TARGET_OS=%__BuildOs%" "-DCLR_CMAKE_PACKAGES_DIR=%__PackagesDir%" "-DCLR_CMAKE_PGO_INSTRUMENT=%__PgoInstrument%" - call "%__SourceDir%\pal\tools\gen-buildsys-win.bat" "%__ProjectDir%" %__VSVersion% %__BuildArch% %__BuildJit32% !__ExtraCmakeArgs! - @if defined __echo @echo on + set __ExtraCmakeArgs=!___SDKVersion! "-DCLR_CMAKE_TARGET_OS=%__BuildOs%" "-DCLR_CMAKE_PACKAGES_DIR=%__PackagesDir%" "-DCLR_CMAKE_PGO_INSTRUMENT=%__PgoInstrument%" + call "%__SourceDir%\pal\tools\gen-buildsys-win.bat" "%__ProjectDir%" %__VSVersion% %__BuildArch% %__BuildJit32% %__BuildStandaloneGC% !__ExtraCmakeArgs! + @if defined _echo @echo on popd :SkipConfigure if defined __ConfigureOnly goto SkipNativeBuild @@ -286,7 +297,7 @@ if /i "%__DoCrossArchBuild%"=="1" ( set __VCBuildArch=x86_amd64 if /i "%__CrossArch%" == "x86" ( set __VCBuildArch=x86 ) @call "%__VSToolsRoot%\..\..\VC\vcvarsall.bat" !__VCBuildArch! - @if defined __echo @echo on + @if defined _echo @echo on if not exist "%__CrossCompIntermediatesDir%" md "%__CrossCompIntermediatesDir%" if defined __SkipConfigure goto SkipConfigureCrossBuild @@ -296,7 +307,7 @@ if /i "%__DoCrossArchBuild%"=="1" ( set "__CMakeBinDir=!__CMakeBinDir:\=/!" set __ExtraCmakeArgs="-DCLR_CROSS_COMPONENTS_BUILD=1" "-DCLR_CMAKE_TARGET_ARCH=%__BuildArch%" "-DCLR_CMAKE_TARGET_OS=%__BuildOs%" "-DCLR_CMAKE_PACKAGES_DIR=%__PackagesDir%" "-DCLR_CMAKE_PGO_INSTRUMENT=%__PgoInstrument%" call "%__SourceDir%\pal\tools\gen-buildsys-win.bat" "%__ProjectDir%" %__VSVersion% %__CrossArch% !__ExtraCmakeArgs! - @if defined __echo @echo on + @if defined _echo @echo on popd :SkipConfigureCrossBuild if not exist "%__CrossCompIntermediatesDir%\install.vcxproj" ( @@ -357,13 +368,32 @@ if %__BuildCoreLib% EQU 1 ( ) ) +REM Need diasymreader.dll on your path for /CreatePdb +set PATH=%PATH%;%WinDir%\Microsoft.Net\Framework64\V4.0.30319;%WinDir%\Microsoft.Net\Framework\V4.0.30319 + if %__BuildNativeCoreLib% EQU 1 ( echo %__MsgPrefix%Generating native image of System.Private.CoreLib for %__BuildOS%.%__BuildArch%.%__BuildType% - + + if "%__CompatJitCrossgen%"=="1" ( + set COMPlus_UseWindowsX86CoreLegacyJit=1 + ) + + if "%__LegacyJitCrossgen%"=="1" ( + set COMPlus_AltJit=* + set COMPlus_AltJitNgen=* + set COMPlus_AltJitName=legacyjit.dll + ) + echo "%__CrossgenExe%" /Platform_Assemblies_Paths "%__BinDir%" /out "%__BinDir%\System.Private.CoreLib.ni.dll" "%__BinDir%\System.Private.CoreLib.dll" "%__CrossgenExe%" /Platform_Assemblies_Paths "%__BinDir%" /out "%__BinDir%\System.Private.CoreLib.ni.dll" "%__BinDir%\System.Private.CoreLib.dll" > "%__CrossGenCoreLibLog%" 2>&1 if NOT !errorlevel! == 0 ( - echo %__MsgPrefix%Error: CrossGen System.Private.CoreLib build failed. Refer to the build log file for details: + echo %__MsgPrefix%Error: CrossGen System.Private.CoreLib build failed. Refer to %__CrossGenCoreLibLog% + echo %__CrossGenCoreLibLog% + exit /b 1 + ) + "%__CrossgenExe%" /Platform_Assemblies_Paths "%__BinDir%" /CreatePdb "%__BinDir%\PDB" "%__BinDir%\System.Private.CoreLib.ni.dll" >> "%__CrossGenCoreLibLog%" 2>&1 + if NOT !errorlevel! == 0 ( + echo %__MsgPrefix%Error: CrossGen /CreatePdb System.Private.CoreLib build failed. Refer to %__CrossGenCoreLibLog% echo %__CrossGenCoreLibLog% exit /b 1 ) @@ -372,8 +402,21 @@ if %__BuildNativeCoreLib% EQU 1 ( set "__CrossGenCoreLibLog=%__LogsDir%\CrossgenMSCoreLib_%__BuildOS%__%__BuildArch%__%__BuildType%.log" set "__CrossgenExe=%__CrossComponentBinDir%\crossgen.exe" + "!__CrossgenExe!" /Platform_Assemblies_Paths "%__BinDir%" /out "%__BinDir%\mscorlib.ni.dll" "%__BinDir%\mscorlib.dll" > "!__CrossGenCoreLibLog!" 2>&1 - if NOT !errorlevel! == 0 ( + set err=!errorlevel! + + if "%__CompatJitCrossgen%"=="1" ( + set COMPlus_UseWindowsX86CoreLegacyJit= + ) + + if "%__LegacyJitCrossgen%"=="1" ( + set COMPlus_AltJit= + set COMPlus_AltJitNgen= + set COMPlus_AltJitName= + ) + + if NOT !err! == 0 ( echo %__MsgPrefix%Error: CrossGen mscorlib facade build failed. Refer to the build log file for details: echo !__CrossGenCoreLibLog! exit /b 1 @@ -381,6 +424,8 @@ if %__BuildNativeCoreLib% EQU 1 ( ) if %__BuildPackages% EQU 1 ( + echo %__MsgPrefix%Building Packages for %__BuildOS%.%__BuildArch%.%__BuildType% + set __MsbuildLog=/flp:Verbosity=normal;LogFile="%__LogsDir%\Nuget_%__BuildOS%__%__BuildArch%__%__BuildType%.log" set __MsbuildWrn=/flp1:WarningsOnly;LogFile="%__LogsDir%\Nuget_%__BuildOS%__%__BuildArch%__%__BuildType%.wrn" set __MsbuildErr=/flp2:ErrorsOnly;LogFile="%__LogsDir%\Nuget_%__BuildOS%__%__BuildArch%__%__BuildType%.err" @@ -427,7 +472,7 @@ REM === All builds complete! REM === REM ========================================================================================= -echo %__MsgPrefix%Repo successfully built. +echo %__MsgPrefix%Repo successfully built. Finished at %TIME% echo %__MsgPrefix%Product binaries are available at !__BinDir! if %__BuildTests% EQU 1 ( echo %__MsgPrefix%Test binaries are available at !__TestBinDir! diff --git a/build.proj b/build.proj index c8d7a5d..7df2904 100644 --- a/build.proj +++ b/build.proj @@ -24,10 +24,6 @@ - - - - diff --git a/build.sh b/build.sh index e639ca0..ca27844 100755 --- a/build.sh +++ b/build.sh @@ -42,6 +42,7 @@ usage() echo "skipmscorlib - do not build mscorlib.dll." echo "skiptests - skip the tests in the 'tests' subdirectory." echo "skipnuget - skip building nuget packages." + echo "portableLinux - build for Portable Linux Distribution" echo "verbose - optional argument to enable verbose build output." echo "-skiprestore: skip restoring packages ^(default: packages are restored during build^)." echo "-disableoss: Disable Open Source Signing for System.Private.CoreLib." @@ -56,19 +57,41 @@ usage() exit 1 } -initDistroRid() +initHostDistroRid() { - if [ "$__BuildOS" == "Linux" ]; then + if [ "$__HostOS" == "Linux" ]; then if [ ! -e /etc/os-release ]; then echo "WARNING: Can not determine runtime id for current distro." - export __DistroRid="" + __HostDistroRid="" else source /etc/os-release - export __DistroRid="$ID.$VERSION_ID-$__HostArch" + __HostDistroRid="$ID.$VERSION_ID-$__HostArch" fi fi } +initTargetDistroRid() +{ + if [ $__CrossBuild == 1 ]; then + if [ "$__BuildOS" == "Linux" ]; then + if [ ! -e $ROOTFS_DIR/etc/os-release ]; then + echo "WARNING: Can not determine runtime id for current distro." + export __DistroRid="" + else + source $ROOTFS_DIR/etc/os-release + export __DistroRid="$ID.$VERSION_ID-$__BuildArch" + fi + fi + else + export __DistroRid="$__HostDistroRid" + fi + + # Portable builds target the base RID only for Linux based platforms + if [ $__PortableLinux == 1 ]; then + export __DistroRid="linux-$__BuildArch" + fi +} + setup_dirs() { echo Setting up directories for build @@ -77,6 +100,11 @@ setup_dirs() mkdir -p "$__BinDir" mkdir -p "$__LogsDir" mkdir -p "$__IntermediatesDir" + + if [ $__CrossBuild == 1 ]; then + mkdir -p "$__CrossComponentBinDir" + mkdir -p "$__CrossCompIntermediatesDir" + fi } # Check the system to ensure the right prereqs are in place @@ -93,11 +121,10 @@ check_prereqs() } -build_coreclr() -{ +generate_event_logging_sources() +{ if [ $__SkipCoreCLR == 1 ]; then - echo "Skipping CoreCLR build." return fi @@ -143,10 +170,23 @@ build_coreclr() fi rm -rf "$__GeneratedIntermediateEventProvider" +} - # All set to commence the build +build_native() +{ + skipCondition=$1 + platformArch="$2" + intermediatesForBuild="$3" + extraCmakeArguments="$4" + message="$5" + + if [ $skipCondition == 1 ]; then + echo "Skipping $message build." + return + fi - echo "Commencing build of native components for $__BuildOS.$__BuildArch.$__BuildType in $__IntermediatesDir" + # All set to commence the build + echo "Commencing build of $message for $__BuildOS.$__BuildArch.$__BuildType in $intermediatesForBuild" generator="" buildFile="Makefile" @@ -167,34 +207,34 @@ build_coreclr() if [ $__SkipConfigure == 0 ]; then # if msbuild is not supported, then set __SkipGenerateVersion to 1 if [ $__isMSBuildOnNETCoreSupported == 0 ]; then __SkipGenerateVersion=1; fi - # Drop version.c file - __versionSourceFile=$__IntermediatesDir/version.cpp + # Drop version.cpp file + __versionSourceFile="$intermediatesForBuild/version.cpp" if [ $__SkipGenerateVersion == 0 ]; then + pwd "$__ProjectRoot/run.sh" build -Project=$__ProjectDir/build.proj -generateHeaderUnix -NativeVersionSourceFile=$__versionSourceFile $__RunArgs $__UnprocessedBuildArgs else + # Generate the dummy version.cpp, but only if it didn't exist to make sure we don't trigger unnecessary rebuild __versionSourceLine="static char sccsid[] __attribute__((used)) = \"@(#)No version information produced\";" - echo $__versionSourceLine > $__versionSourceFile + if [ -e $__versionSourceFile ]; then + read existingVersionSourceLine < $__versionSourceFile + fi + if [ "$__versionSourceLine" != "$existingVersionSourceLine" ]; then + echo $__versionSourceLine > $__versionSourceFile + fi fi - echo "Restoring the OptimizationData package" - "$__ProjectRoot/run.sh" sync -optdata - - pushd "$__IntermediatesDir" + pushd "$intermediatesForBuild" # Regenerate the CMake solution - __ExtraCmakeArgs="-DCLR_CMAKE_TARGET_OS=$__BuildOS -DCLR_CMAKE_PACKAGES_DIR=$__PackagesDir -DCLR_CMAKE_PGO_INSTRUMENT=$__PgoInstrument" - echo "Invoking \"$__ProjectRoot/src/pal/tools/gen-buildsys-clang.sh\" \"$__ProjectRoot\" $__ClangMajorVersion $__ClangMinorVersion $__BuildArch $__BuildType $__CodeCoverage $__IncludeTests $generator $__ExtraCmakeArgs $__cmakeargs" - "$__ProjectRoot/src/pal/tools/gen-buildsys-clang.sh" "$__ProjectRoot" $__ClangMajorVersion $__ClangMinorVersion $__BuildArch $__BuildType $__CodeCoverage $__IncludeTests $generator "$__ExtraCmakeArgs" "$__cmakeargs" + echo "Invoking \"$__ProjectRoot/src/pal/tools/gen-buildsys-clang.sh\" \"$__ProjectRoot\" $__ClangMajorVersion $__ClangMinorVersion $platformArch $__BuildType $__CodeCoverage $__IncludeTests $generator $extraCmakeArguments $__cmakeargs" + "$__ProjectRoot/src/pal/tools/gen-buildsys-clang.sh" "$__ProjectRoot" $__ClangMajorVersion $__ClangMinorVersion $platformArch $__BuildType $__CodeCoverage $__IncludeTests $generator "$extraCmakeArguments" "$__cmakeargs" popd fi - # Check that the makefiles were created. - pushd "$__IntermediatesDir" - - if [ ! -f "$__IntermediatesDir/$buildFile" ]; then - echo "Failed to generate native component build project!" + if [ ! -f "$intermediatesForBuild/$buildFile" ]; then + echo "Failed to generate $message build project!" exit 1 fi - + # Get the number of processors available to the scheduler # Other techniques such as `nproc` only get the number of # processors available to a single process. @@ -206,21 +246,24 @@ build_coreclr() NumProc=$(($(getconf _NPROCESSORS_ONLN)+1)) fi - # Build CoreCLR - + # Build if [ $__ConfigureOnly == 1 ]; then - echo "Skipping CoreCLR build." + echo "Finish configuration & skipping $message build." return fi + # Check that the makefiles were created. + pushd "$intermediatesForBuild" + echo "Executing $buildTool install -j $NumProc" $buildTool install -j $NumProc if [ $? != 0 ]; then - echo "Failed to build coreclr components." + echo "Failed to build $message." exit 1 fi - popd + + popd } isMSBuildOnNETCoreSupported() @@ -230,7 +273,7 @@ isMSBuildOnNETCoreSupported() if [ "$__HostArch" == "x64" ]; then if [ "$__HostOS" == "Linux" ]; then - case "$__DistroRid" in + case "$__HostDistroRid" in "centos.7-x64") __isMSBuildOnNETCoreSupported=1 ;; @@ -261,6 +304,9 @@ isMSBuildOnNETCoreSupported() "ubuntu.16.10-x64") __isMSBuildOnNETCoreSupported=1 ;; + "alpine.3.4.3-x64") + __isMSBuildOnNETCoreSupported=1 + ;; *) esac elif [ "$__HostOS" == "OSX" ]; then @@ -475,9 +521,12 @@ __CrossBuild=0 __ClangMajorVersion=0 __ClangMinorVersion=0 __NuGetPath="$__PackagesDir/NuGet.exe" +__HostDistroRid="" __DistroRid="" __cmakeargs="" __SkipGenerateVersion=0 +__DoCrossArchBuild=0 +__PortableLinux=0 while :; do if [ $# -le 0 ]; then @@ -530,8 +579,17 @@ while :; do cross) __CrossBuild=1 ;; - - verbose) + + portablelinux) + if [ "$__BuildOS" == "Linux" ]; then + __PortableLinux=1 + else + echo "ERROR: portableLinux not supported for non-Linux platforms." + exit 1 + fi + ;; + + verbose) __VerboseBuild=1 ;; @@ -572,7 +630,6 @@ while :; do __ConfigureOnly=1 __SkipMSCorLib=1 __SkipNuget=1 - __IncludeTests= ;; skipconfigure) @@ -589,6 +646,10 @@ while :; do __SkipCoreCLR=1 ;; + crosscomponent) + __DoCrossArchBuild=1 + ;; + skipmscorlib) __SkipMSCorLib=1 ;; @@ -664,8 +725,8 @@ fi # Set dependent variables __LogsDir="$__RootBinDir/Logs" -# init the distro name -initDistroRid +# init the host distro name +initHostDistroRid # Set the remaining variables based upon the determined build configuration __BinDir="$__RootBinDir/Product/$__BuildOS.$__BuildArch.$__BuildType" @@ -675,6 +736,18 @@ __TestWorkingDir="$__RootBinDir/tests/$__BuildOS.$__BuildArch.$__BuildType" export __IntermediatesDir="$__RootBinDir/obj/$__BuildOS.$__BuildArch.$__BuildType" __TestIntermediatesDir="$__RootBinDir/tests/obj/$__BuildOS.$__BuildArch.$__BuildType" __isMSBuildOnNETCoreSupported=0 +__CrossComponentBinDir="$__BinDir" +__CrossCompIntermediatesDir="$__IntermediatesDir/crossgen" + +__CrossArch="$__HostArch" +if [[ "$__HostArch" == "x64" && "$__BuildArch" == "arm" ]]; then + __CrossArch="x86" +fi +if [ $__CrossBuild == 1 ]; then + __CrossComponentBinDir="$__CrossComponentBinDir/$__CrossArch" +fi +__CrossgenCoreLibLog="$__LogsDir/CrossgenCoreLib_$__BuildOS.$BuildArch.$__BuildType.log" +__CrossgenExe="$__CrossComponentBinDir/crossgen" # Init if MSBuild for .NET Core is supported for this platform isMSBuildOnNETCoreSupported @@ -701,17 +774,37 @@ if [ $__CrossBuild == 1 ]; then fi fi -# Make the directories necessary for build if they don't exist +# init the target distro name +initTargetDistroRid +# Make the directories necessary for build if they don't exist setup_dirs # Check prereqs. - check_prereqs +# Generate event logging infrastructure sources +generate_event_logging_sources + # Build the coreclr (native) components. +__ExtraCmakeArgs="-DCLR_CMAKE_TARGET_OS=$__BuildOS -DCLR_CMAKE_PACKAGES_DIR=$__PackagesDir -DCLR_CMAKE_PGO_INSTRUMENT=$__PgoInstrument" +build_native $__SkipCoreCLR "$__BuildArch" "$__IntermediatesDir" "$__ExtraCmakeArgs" "CoreCLR component" -build_coreclr +# Build cross-architecture components +if [ $__CrossBuild == 1 ]; then + __SkipCrossArchBuild=1 + if [ $__DoCrossArchBuild == 1 ]; then + # build cross-architecture components for x86-host/arm-target + if [[ "$__BuildArch" == "arm" && "$__CrossArch" == "x86" ]]; then + __SkipCrossArchBuild=0 + fi + fi + + export __CMakeBinDir="$__CrossComponentBinDir" + export CROSSCOMPONENT=1 + __ExtraCmakeArgs="-DCLR_CMAKE_TARGET_ARCH=$__BuildArch -DCLR_CMAKE_TARGET_OS=$__BuildOS -DCLR_CMAKE_PACKAGES_DIR=$__PackagesDir -DCLR_CMAKE_PGO_INSTRUMENT=$__PgoInstrument" + build_native $__SkipCrossArchBuild "$__CrossArch" "$__CrossCompIntermediatesDir" "$__ExtraCmakeArgs" "cross-architecture component" +fi # Build System.Private.CoreLib. diff --git a/clean.cmd b/clean.cmd index 50e709e..42b9e59 100644 --- a/clean.cmd +++ b/clean.cmd @@ -1,4 +1,4 @@ -@if not defined __echo @echo off +@if not defined _echo @echo off setlocal EnableDelayedExpansion echo Running clean.cmd diff --git a/clr.coreclr.props b/clr.coreclr.props index 50b3b4f..447b302 100644 --- a/clr.coreclr.props +++ b/clr.coreclr.props @@ -21,6 +21,7 @@ true true true + true true true true @@ -33,6 +34,7 @@ true true true + true true true true @@ -49,6 +51,7 @@ true true + true true true diff --git a/clr.defines.targets b/clr.defines.targets index 9667a77..a45d0dd 100644 --- a/clr.defines.targets +++ b/clr.defines.targets @@ -92,11 +92,13 @@ $(CDefines);FEATURE_RWLOCK $(CDefines);FEATURE_SERIALIZATION $(CDefines);FEATURE_SORT_TABLES + $(CDefines);FEATURE_SPAN_OF_T $(CDefines);FEATURE_STACK_PROBE $(CDefines);FEATURE_STANDALONE_SN $(CDefines);FEATURE_STRONGNAME_DELAY_SIGNING_ALLOWED $(CDefines);FEATURE_STRONGNAME_MIGRATION $(CDefines);FEATURE_SVR_GC + $(CDefines);FEATURE_SYNCHRONIZATIONCONTEXT_WAIT $(CDefines);FEATURE_PERFMAP $(CDefines);FEATURE_SYNCHRONIZATIONCONTEXT_WAIT $(CDefines);FEATURE_SYNTHETIC_CULTURES @@ -187,6 +189,7 @@ $(DefineConstants);FEATURE_RWLOCK $(DefineConstants);FEATURE_SERIALIZATION $(DefineConstants);FEATURE_SORT_TABLES + $(DefineConstants);FEATURE_SPAN_OF_T $(DefineConstants);FEATURE_STRONGNAME_MIGRATION $(DefineConstants);FEATURE_SYNCHRONIZATIONCONTEXT_WAIT $(DefineConstants);FEATURE_SYNTHETIC_CULTURES diff --git a/clrdefinitions.cmake b/clrdefinitions.cmake index b61ab8f..91346ec 100644 --- a/clrdefinitions.cmake +++ b/clrdefinitions.cmake @@ -61,6 +61,12 @@ if (CLR_CMAKE_PLATFORM_UNIX) endif(CLR_CMAKE_PLATFORM_UNIX) +if(CLR_CMAKE_PLATFORM_ALPINE_LINUX) + # Alpine Linux doesn't have fixed stack limit, this define disables some stack pointer + # sanity checks in debug / checked build that rely on a fixed stack limit + add_definitions(-DNO_FIXED_STACK_LIMIT) +endif(CLR_CMAKE_PLATFORM_ALPINE_LINUX) + add_definitions(-D_BLD_CLR) add_definitions(-DDEBUGGING_SUPPORTED) add_definitions(-DPROFILING_SUPPORTED) @@ -118,12 +124,16 @@ if(CLR_CMAKE_PLATFORM_UNIX) add_definitions(-DFEATURE_EVENTSOURCE_XPLAT=1) endif(CLR_CMAKE_PLATFORM_UNIX) add_definitions(-DFEATURE_EXCEPTIONDISPATCHINFO) +add_definitions(-DFEATURE_EXCEPTION_NOTIFICATIONS) # NetBSD doesn't implement this feature if(NOT CMAKE_SYSTEM_NAME STREQUAL NetBSD) add_definitions(-DFEATURE_HIJACK) endif(NOT CMAKE_SYSTEM_NAME STREQUAL NetBSD) add_definitions(-DFEATURE_HOST_ASSEMBLY_RESOLVER) add_definitions(-DFEATURE_ICASTABLE) +if (WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386)) +add_definitions(-DFEATURE_INTEROP_DEBUGGING) +endif (WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386)) if (CLR_CMAKE_PLATFORM_UNIX OR CLR_CMAKE_TARGET_ARCH_ARM64) add_definitions(-DFEATURE_IMPLICIT_TLS) set(FEATURE_IMPLICIT_TLS 1) @@ -157,6 +167,10 @@ add_definitions(-DFEATURE_RANDOMIZED_STRING_HASHING) add_definitions(-DFEATURE_READYTORUN) set(FEATURE_READYTORUN 1) +if (FEATURE_STANDALONE_GC) + add_definitions(-DFEATURE_STANDALONE_GC) +endif(FEATURE_STANDALONE_GC) + if (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386) add_definitions(-DFEATURE_REJIT) endif(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386) @@ -169,6 +183,7 @@ if (CLR_CMAKE_PLATFORM_UNIX OR CLR_CMAKE_TARGET_ARCH_ARM64) endif () add_definitions(-DFEATURE_SVR_GC) add_definitions(-DFEATURE_SYMDIFF) +add_definitions(-DFEATURE_SYNCHRONIZATIONCONTEXT_WAIT) add_definitions(-DFEATURE_SYNTHETIC_CULTURES) if(CLR_CMAKE_PLATFORM_UNIX_AMD64) add_definitions(-DFEATURE_MULTIREG_RETURN) @@ -192,3 +207,5 @@ add_definitions(-DFEATURE_WINMD_RESILIENT) add_definitions(-D_SECURE_SCL=0) add_definitions(-DUNICODE) add_definitions(-D_UNICODE) + +add_definitions(-DFEATURE_SPAN_OF_T) diff --git a/config.json b/config.json index d25fdba..1849272 100644 --- a/config.json +++ b/config.json @@ -24,6 +24,12 @@ "values": [], "defaultValue": "" }, + "__Container": { + "description": "Container name for Azure upload.", + "valueType": "property", + "values": [], + "defaultValue": "" + }, "MsBuildFileLogging": { "description": "MsBuild logging options.", "valueType": "passThrough", @@ -48,12 +54,6 @@ "values": [], "defaultValue": "" }, - "RestoreOptData": { - "description": "MsBuild target that restores optimization profile data.", - "valueType": "target", - "values": [], - "defaultValue": "" - }, "RestoreDuringBuild": { "description": "Enables/disables package restore.", "valueType": "property", @@ -246,6 +246,12 @@ "values": [], "defaultValue": "" }, + "CreateNonWindowsTestOverlay": { + "description": "Runs CreateNonWindowsTestOverlay target.", + "valueType": "target", + "values": [], + "defaultValue": "" + }, "Verbosity": { "description": "Sets build verbosity.", "valueType": "passThrough", @@ -270,6 +276,60 @@ "values": [], "defaultValue": "" }, + "GenerateRuntimeLayout": { + "description": "Generates Core_Root folder", + "valueType": "property", + "values": [ true, false ], + "defaultValue": true + }, + "BuildTestsAgainstPackages": { + "description": "Sets the property specifying if we're building tests against packages", + "valueType": "property", + "values": [ true, false ], + "defaultValue": true + }, + "PublishTestNativeBins": { + "description": "Publishes test native binaries to Azure on non-windows", + "valueType": "property", + "values": [ true, false ], + "defaultValue": true + }, + "RuntimeId": { + "description": "Specifies the OS to build Core_Root for", + "valueType": "property", + "values": [ "debian.8-x64", "fedora.23-x64", "opensuse.13.2-x64", "opensuse.42.1-x64", "osx.10.10-x64", "rhel.7-x64", "ubuntu.14.04-x64", "ubuntu.16.04-x64", "ubuntu.16.10-x64" ], + "defaultValue": "${__RuntimeId}" + }, + "UpdateDependencies": { + "description": "MsBuild target that updates project.json dependencies.", + "valueType": "target", + "values": [], + "defaultValue": "" + }, + "BatchRestorePackages": { + "description": "MsBuild target that restores the packages.", + "valueType": "target", + "values": [], + "defaultValue": "" + }, + "BinPlaceRef": { + "description": "Place mscorlib.dll in bin/Product ref folder for building tests against", + "valueType": "target", + "values": [], + "defaultValue": "" + }, + "BinPlaceProduct": { + "description": "Place test dependencies in bin/Product folder for building tests against", + "valueType": "target", + "values": [], + "defaultValue": "" + }, + "CopyCrossgenToProduct": { + "description": "Place crossgen.exe in bin/Product folder for building tests against", + "valueType": "target", + "values": [], + "defaultValue": "" + }, "ExtraParameters": { "description": "Extra parameters will be passed to the selected command.", "valueType": "passThrough", @@ -354,7 +414,8 @@ "settings": { "MsBuildLog": "default", "MsBuildWrn": "default", - "MsBuildErr": "default" + "MsBuildErr": "default", + "MsBuildEventLogging": "default" } } }, @@ -368,14 +429,6 @@ "RestoreNETCorePlatforms": "default" } }, - "optdata": { - "description": "Restores optimization profile data for the repository.", - "settings": { - "Project": "./build.proj", - "RestoreDuringBuild": true, - "RestoreOptData": "default" - } - }, "ab": { "description": "Downloads the latests product packages from Azure. The values for '-AzureAccount' and '-AzureToken' are required", "settings": { @@ -394,6 +447,12 @@ "CloudDropAccountName": "default" } }, + "container": { + "description": "Container name to download from in Azure Blob storage.", + "settings": { + "__Container": "default" + } + }, "verbose": { "description": "Passes /flp:v=diag to the msbuild command or the value passed by the user.", "settings": { @@ -411,6 +470,12 @@ "settings": { "BuildNumberMinor": "default" } + }, + "PublishTestNativeBins": { + "description": "Downloads Published test native binaries.", + "settings": { + "PublishTestNativeBins": "default" + } } }, "defaultValues": { @@ -434,6 +499,12 @@ "CloudDropAccountName": "default" } }, + "container": { + "description": "Container name to upload into in Azure Blob storage.", + "settings": { + "__Container": "default" + } + }, "buildArch": { "description": "Specifies architecture to publish, can be x64, x86, arm or arm64", "settings": { @@ -451,6 +522,18 @@ "settings": { "__BuildOS": "default" } + }, + "distroRid": { + "description": "Specifies distro rid for Unix OS.", + "settings": { + "__DistroRid": "default" + } + }, + "PublishTestNativeBins": { + "description": "Publishes test native binaries.", + "settings": { + "PublishTestNativeBins": "default" + } } }, "defaultValues": { diff --git a/cross/arm/sources.list.jessie b/cross/arm/sources.list.jessie new file mode 100644 index 0000000..4d142ac --- /dev/null +++ b/cross/arm/sources.list.jessie @@ -0,0 +1,3 @@ +# Debian (sid) # UNSTABLE +deb http://ftp.debian.org/debian/ sid main contrib non-free +deb-src http://ftp.debian.org/debian/ sid main contrib non-free diff --git a/cross/arm/sources.list.xenial b/cross/arm/sources.list.xenial new file mode 100644 index 0000000..eacd86b --- /dev/null +++ b/cross/arm/sources.list.xenial @@ -0,0 +1,11 @@ +deb http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted universe +deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted universe + +deb http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted universe +deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted universe + +deb http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted +deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted + +deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse +deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse \ No newline at end of file diff --git a/cross/arm64/sources.list.xenial b/cross/arm64/sources.list.xenial new file mode 100644 index 0000000..eacd86b --- /dev/null +++ b/cross/arm64/sources.list.xenial @@ -0,0 +1,11 @@ +deb http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted universe +deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted universe + +deb http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted universe +deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted universe + +deb http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted +deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted + +deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse +deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse \ No newline at end of file diff --git a/cross/build-rootfs.sh b/cross/build-rootfs.sh index b786420..cfa1a66 100755 --- a/cross/build-rootfs.sh +++ b/cross/build-rootfs.sh @@ -2,9 +2,10 @@ usage() { - echo "Usage: $0 [BuildArch] [UbuntuCodeName]" - echo "BuildArch can be: arm, arm-softfp, arm64" - echo "UbuntuCodeName - optional, Code name for Ubuntu, can be: trusty(default), vivid, wily. If BuildArch is arm-softfp, UbuntuCodeName is ignored." + echo "Usage: $0 [BuildArch] [UbuntuCodeName] [lldbx.y]" + echo "BuildArch can be: arm(default), arm-softfp, arm64, x86" + echo "UbuntuCodeName - optional, Code name for Ubuntu, can be: trusty(default), vivid, wily, xenial. If BuildArch is arm-softfp, UbuntuCodeName is ignored." + echo "lldbx.y - optional, LLDB version, can be: lldb3.6(default), lldb3.8" exit 1 } @@ -17,64 +18,79 @@ __BuildArch=arm __UbuntuArch=armhf __UbuntuRepo="http://ports.ubuntu.com/" __UbuntuPackagesBase="build-essential libunwind8-dev gettext symlinks liblttng-ust-dev libicu-dev" -__UbuntuPackages="$__UbuntuPackagesBase" -if [ -z "$LLVM_ARM_HOME" ]; then - __LLDB_Package="lldb-3.6-dev" -fi -__MachineTriple=arm-linux-gnueabihf +__LLDB_Package="lldb-3.6-dev" __UnprocessedBuildArgs= + for i in "$@" do lowerI="$(echo $i | awk '{print tolower($0)}')" case $lowerI in -?|-h|--help) - usage - exit 1 - ;; + usage + exit 1 + ;; arm) - __BuildArch=arm - __UbuntuArch=armhf - __UbuntuPackages="$__UbuntuPackagesBase $__LLDB_Package" - __MachineTriple=arm-linux-gnueabihf - ;; + __BuildArch=arm + __UbuntuArch=armhf + ;; arm64) - __BuildArch=arm64 - __UbuntuArch=arm64 - __UbuntuPackages="$__UbuntuPackagesBase" - __MachineTriple=aarch64-linux-gnu - ;; + __BuildArch=arm64 + __UbuntuArch=arm64 + ;; arm-softfp) - __BuildArch=arm-softfp - __UbuntuArch=armel - __UbuntuRepo="http://ftp.debian.org/debian/" - __UbuntuPackages="$__UbuntuPackagesBase $__LLDB_Package" - __MachineTriple=arm-linux-gnueabi - __UbuntuCodeName=jessie - ;; + __BuildArch=arm-softfp + __UbuntuArch=armel + __UbuntuRepo="http://ftp.debian.org/debian/" + __UbuntuCodeName=jessie + ;; + x86) + __BuildArch=x86 + __UbuntuArch=i386 + __UbuntuRepo="http://archive.ubuntu.com/ubuntu/" + ;; + lldb3.6) + __LLDB_Package="lldb-3.6-dev" + ;; + lldb3.8) + __LLDB_Package="lldb-3.8-dev" + ;; vivid) - if [ "$__UbuntuCodeName" != "jessie" ]; then - __UbuntuCodeName=vivid - fi - ;; + if [ "$__UbuntuCodeName" != "jessie" ]; then + __UbuntuCodeName=vivid + fi + ;; wily) - if [ "$__UbuntuCodeName" != "jessie" ]; then - __UbuntuCodeName=wily - fi - ;; + if [ "$__UbuntuCodeName" != "jessie" ]; then + __UbuntuCodeName=wily + fi + ;; + xenial) + if [ "$__UbuntuCodeName" != "jessie" ]; then + __UbuntuCodeName=xenial + fi + ;; + jessie) + __UbuntuCodeName=jessie + __UbuntuRepo="http://ftp.debian.org/debian/" + ;; *) - __UnprocessedBuildArgs="$__UnprocessedBuildArgs $i" - ;; + __UnprocessedBuildArgs="$__UnprocessedBuildArgs $i" + ;; esac done __RootfsDir="$__CrossDir/rootfs/$__BuildArch" +__UbuntuPackages="$__UbuntuPackagesBase $__LLDB_Package" if [[ -n "$ROOTFS_DIR" ]]; then __RootfsDir=$ROOTFS_DIR fi -umount $__RootfsDir/* -rm -rf $__RootfsDir +if [ -d "$__RootfsDir" ]; then + umount $__RootfsDir/* + rm -rf $__RootfsDir +fi + qemu-debootstrap --arch $__UbuntuArch $__UbuntuCodeName $__RootfsDir $__UbuntuRepo cp $__CrossDir/$__BuildArch/sources.list.$__UbuntuCodeName $__RootfsDir/etc/apt/sources.list chroot $__RootfsDir apt-get update diff --git a/cross/x86/sources.list.trusty b/cross/x86/sources.list.trusty new file mode 100644 index 0000000..9b30854 --- /dev/null +++ b/cross/x86/sources.list.trusty @@ -0,0 +1,11 @@ +deb http://archive.ubuntu.com/ubuntu/ trusty main restricted universe +deb-src http://archive.ubuntu.com/ubuntu/ trusty main restricted universe + +deb http://archive.ubuntu.com/ubuntu/ trusty-updates main restricted universe +deb-src http://archive.ubuntu.com/ubuntu/ trusty-updates main restricted universe + +deb http://archive.ubuntu.com/ubuntu/ trusty-backports main restricted +deb-src http://archive.ubuntu.com/ubuntu/ trusty-backports main restricted + +deb http://archive.ubuntu.com/ubuntu/ trusty-security main restricted universe multiverse +deb-src http://archive.ubuntu.com/ubuntu/ trusty-security main restricted universe multiverse diff --git a/cross/x86/sources.list.vivid b/cross/x86/sources.list.vivid new file mode 100644 index 0000000..26d37b2 --- /dev/null +++ b/cross/x86/sources.list.vivid @@ -0,0 +1,11 @@ +deb http://archive.ubuntu.com/ubuntu/ vivid main restricted universe +deb-src http://archive.ubuntu.com/ubuntu/ vivid main restricted universe + +deb http://archive.ubuntu.com/ubuntu/ vivid-updates main restricted universe +deb-src http://archive.ubuntu.com/ubuntu/ vivid-updates main restricted universe + +deb http://archive.ubuntu.com/ubuntu/ vivid-backports main restricted +deb-src http://archive.ubuntu.com/ubuntu/ vivid-backports main restricted + +deb http://archive.ubuntu.com/ubuntu/ vivid-security main restricted universe multiverse +deb-src http://archive.ubuntu.com/ubuntu/ vivid-security main restricted universe multiverse diff --git a/cross/x86/sources.list.wily b/cross/x86/sources.list.wily new file mode 100644 index 0000000..c4b0b44 --- /dev/null +++ b/cross/x86/sources.list.wily @@ -0,0 +1,11 @@ +deb http://archive.ubuntu.com/ubuntu/ wily main restricted universe +deb-src http://archive.ubuntu.com/ubuntu/ wily main restricted universe + +deb http://archive.ubuntu.com/ubuntu/ wily-updates main restricted universe +deb-src http://archive.ubuntu.com/ubuntu/ wily-updates main restricted universe + +deb http://archive.ubuntu.com/ubuntu/ wily-backports main restricted +deb-src http://archive.ubuntu.com/ubuntu/ wily-backports main restricted + +deb http://archive.ubuntu.com/ubuntu/ wily-security main restricted universe multiverse +deb-src http://archive.ubuntu.com/ubuntu/ wily-security main restricted universe multiverse diff --git a/cross/x86/sources.list.xenial b/cross/x86/sources.list.xenial new file mode 100644 index 0000000..ad9c5a0 --- /dev/null +++ b/cross/x86/sources.list.xenial @@ -0,0 +1,11 @@ +deb http://archive.ubuntu.com/ubuntu/ xenial main restricted universe +deb-src http://archive.ubuntu.com/ubuntu/ xenial main restricted universe + +deb http://archive.ubuntu.com/ubuntu/ xenial-updates main restricted universe +deb-src http://archive.ubuntu.com/ubuntu/ xenial-updates main restricted universe + +deb http://archive.ubuntu.com/ubuntu/ xenial-backports main restricted +deb-src http://archive.ubuntu.com/ubuntu/ xenial-backports main restricted + +deb http://archive.ubuntu.com/ubuntu/ xenial-security main restricted universe multiverse +deb-src http://archive.ubuntu.com/ubuntu/ xenial-security main restricted universe multiverse diff --git a/cross/x86/toolchain.cmake b/cross/x86/toolchain.cmake new file mode 100644 index 0000000..63c6487 --- /dev/null +++ b/cross/x86/toolchain.cmake @@ -0,0 +1,40 @@ + +set(CROSS_ROOTFS $ENV{ROOTFS_DIR}) + +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR i686) + +add_compile_options("-m32") +add_compile_options("--sysroot=${CROSS_ROOTFS}") +add_compile_options("-Wno-error=unused-command-line-argument") + +set(CROSS_LINK_FLAGS "${CROSS_LINK_FLAGS} --sysroot=${CROSS_ROOTFS}") +set(CROSS_LINK_FLAGS "${CROSS_LINK_FLAGS} -B ${CROSS_ROOTFS}/usr/lib/gcc/i686-linux-gnu") +set(CROSS_LINK_FLAGS "${CROSS_LINK_FLAGS} -L${CROSS_ROOTFS}/lib/i386-linux-gnu") +set(CROSS_LINK_FLAGS "${CROSS_LINK_FLAGS} -m32") + +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CROSS_LINK_FLAGS}" CACHE STRING "" FORCE) +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${CROSS_LINK_FLAGS}" CACHE STRING "" FORCE) +set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${CROSS_LINK_FLAGS}" CACHE STRING "" FORCE) + +set(CMAKE_FIND_ROOT_PATH "${CROSS_ROOTFS}") +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +set(LLVM_CROSS_DIR "$ENV{LLVM_CROSS_HOME}") +if(LLVM_CROSS_DIR) + set(WITH_LLDB_LIBS "${LLVM_CROSS_DIR}/lib/" CACHE STRING "") + set(WITH_LLDB_INCLUDES "${LLVM_CROSS_DIR}/include" CACHE STRING "") + set(LLDB_H "${WITH_LLDB_INCLUDES}" CACHE STRING "") + set(LLDB "${LLVM_CROSS_DIR}/lib/liblldb.so" CACHE STRING "") +else() + set(WITH_LLDB_LIBS "${CROSS_ROOTFS}/usr/lib/i386-linux-gnu" CACHE STRING "") + set(CHECK_LLVM_DIR "${CROSS_ROOTFS}/usr/lib/llvm-3.8/include") + if(EXISTS "${CHECK_LLVM_DIR}" AND IS_DIRECTORY "${CHECK_LLVM_DIR}") + set(WITH_LLDB_INCLUDES "${CHECK_LLVM_DIR}") + else() + set(WITH_LLDB_INCLUDES "${CROSS_ROOTFS}/usr/lib/llvm-3.6/include") + endif() +endif() diff --git a/cross/x86/tryrun.cmake b/cross/x86/tryrun.cmake new file mode 100644 index 0000000..cfc5208 --- /dev/null +++ b/cross/x86/tryrun.cmake @@ -0,0 +1,127 @@ +SET( REALPATH_SUPPORTS_NONEXISTENT_FILES_EXITCODE + 1 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( SSCANF_SUPPORT_ll_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( SSCANF_CANNOT_HANDLE_MISSING_EXPONENT_EXITCODE + 1 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_LARGE_SNPRINTF_SUPPORT_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_SCHED_GET_PRIORITY_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_WORKING_GETTIMEOFDAY_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_WORKING_CLOCK_GETTIME_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_CLOCK_MONOTONIC_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_MMAP_DEV_ZERO_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS_EXITCODE + 1 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( PTHREAD_CREATE_MODIFIES_ERRNO_EXITCODE + 1 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( SEM_INIT_MODIFIES_ERRNO_EXITCODE + 1 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_COMPATIBLE_ACOS_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_COMPATIBLE_ASIN_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_COMPATIBLE_POW_EXITCODE + 1 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_VALID_NEGATIVE_INF_POW_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_VALID_POSITIVE_INF_POW_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_COMPATIBLE_ATAN2_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_COMPATIBLE_LOG_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_COMPATIBLE_LOG10_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( UNGETC_NOT_RETURN_EOF_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAS_POSIX_SEMAPHORES_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( GETPWUID_R_SETS_ERRNO_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( FILE_OPS_CHECK_FERROR_OF_PREVIOUS_CALL_EXITCODE + 1 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_CLOCK_THREAD_CPUTIME_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_SCHED_GETCPU_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_CLOCK_MONOTONIC_COARSE_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_PROCFS_CTL_EXITCODE + 1 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_PROCFS_MAPS_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_PROCFS_STAT_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_PROCFS_STATUS_EXITCODE + 0 + CACHE STRING "Result from TRY_RUN" FORCE) + +SET( HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES + 0 + CACHE STRING "Result from TRY_RUN" FORCE) diff --git a/crosscomponents.cmake b/crosscomponents.cmake index e0d5c1a..7575570 100644 --- a/crosscomponents.cmake +++ b/crosscomponents.cmake @@ -6,4 +6,5 @@ set (CLR_CROSS_COMPONENTS_LIST mscordbi sos clrjit + protojit ) diff --git a/dependencies.props b/dependencies.props index 52b4a87..3094a3d 100644 --- a/dependencies.props +++ b/dependencies.props @@ -1,30 +1,25 @@ - 35258a932ae9971cbc8df1d83b4eb893947a1724 - 35258a932ae9971cbc8df1d83b4eb893947a1724 + 014ac653f680703f5b9a7bf3ebc99b1a5b912c7b + 014ac653f680703f5b9a7bf3ebc99b1a5b912c7b - preview1-24628-02 + beta-24820-02 - 1.1.0 - 2.1.0 - - - 1.0.0 - 1.0.4 - 1.0.1 + 1.2.0-beta-24820-02 + 2.2.0-beta2-build3300 build-info/dotnet/ - release/1.1.0 + master $(MSBuildThisFileFullPath) @@ -37,7 +32,7 @@ $(BaseDotNetBuildInfo)coreclr/$(DependencyBranch) $(CoreClrCurrentRef) - + https://raw.githubusercontent.com/dotnet/versions @@ -66,6 +61,7 @@ $(XunitPackageVersion) + @@ -73,11 +69,11 @@ - 1.0.0-alpha-build0035 + 1.0.0-alpha-build0040 - 1.0.2-prerelease-00101 + 1.0.2-prerelease-00177 diff --git a/dir.props b/dir.props index 5b96cd1..b9bf081 100644 --- a/dir.props +++ b/dir.props @@ -139,7 +139,7 @@ - servicing + beta $(SourceDir).nuget/descriptions.json $(SourceDir).nuget/dotnet_library_license.txt $(SourceDir).nuget/ThirdPartyNotices.txt @@ -153,12 +153,12 @@ https://dot.net - 1.1.1 + 1.2.0 false - $(Version) - + $(PackageVersion) + diff --git a/extract-from-json.py b/extract-from-json.py deleted file mode 100755 index e432b2b..0000000 --- a/extract-from-json.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/python - -import argparse -import json -import sys - -def parse_args(): - parser = argparse.ArgumentParser( - description="""Extracts information from a json file by navigating the JSON object using a - sequence of property accessors and returning the JSON subtree, or the raw data, found - at that location.""" - ) - - parser.add_argument( - '-f', '--file', - metavar='', - help="Path to project.json file to parse", - required=True, - ) - - parser.add_argument( - 'property', - metavar='property_name', - help="""Name of property to extract using object notation. - Pass multiple values to drill down into nested objects (in order).""", - nargs='*', - ) - - parser.add_argument( - '-r', '--raw', - help="""Dumps the raw object found at the requested location. - If omitted, returns a JSON formatted object instead.""", - action='store_true', - default=False - ) - - return parser.parse_args() - -def main(): - args = parse_args() - - with open(args.file) as json_file: - selected_property = json.load(json_file) - - for prop in args.property: - selected_property = selected_property[prop] - - if args.raw: - print(selected_property) - else: - print(json.dumps(selected_property)) - - return 0 - -if __name__ == "__main__": - sys.exit(main()) diff --git a/functions.cmake b/functions.cmake index f8a2eea..e1a9abb 100644 --- a/functions.cmake +++ b/functions.cmake @@ -1,6 +1,8 @@ function(clr_unknown_arch) if (WIN32) message(FATAL_ERROR "Only AMD64, ARM64, ARM and I386 are supported") + elseif(CLR_CROSS_COMPONENTS_BUILD) + message(FATAL_ERROR "Only AMD64, I386 are supported for cross-architecture component") else() message(FATAL_ERROR "Only AMD64, ARM64 and ARM are supported") endif() @@ -216,3 +218,19 @@ function(_install) install(${ARGV}) endif() endfunction() + +function(verify_dependencies targetName errorMessage) + # We don't need to verify dependencies on OSX, since missing dependencies + # result in link error over there. + if (NOT CLR_CMAKE_PLATFORM_DARWIN) + add_custom_command( + TARGET ${targetName} + POST_BUILD + VERBATIM + COMMAND ${CMAKE_SOURCE_DIR}/verify-so.sh + $ + ${errorMessage} + COMMENT "Verifying ${targetName} dependencies" + ) + endif() +endfunction() diff --git a/init-tools.cmd b/init-tools.cmd index 1bdf2a8..cb1aad4 100644 --- a/init-tools.cmd +++ b/init-tools.cmd @@ -1,4 +1,4 @@ -@echo off +@if not defined _echo @echo off setlocal set INIT_TOOLS_LOG=%~dp0init-tools.log @@ -6,13 +6,13 @@ set PACKAGES_DIR=%~dp0packages\ set TOOLRUNTIME_DIR=%~dp0Tools set DOTNET_PATH=%TOOLRUNTIME_DIR%\dotnetcli\ set DOTNET_CMD=%DOTNET_PATH%dotnet.exe -if [%BUILDTOOLS_SOURCE%]==[] set BUILDTOOLS_SOURCE=https://www.myget.org/F/dotnet-buildtools/ +if [%BUILDTOOLS_SOURCE%]==[] set BUILDTOOLS_SOURCE=https://dotnet.myget.org/F/dotnet-buildtools/api/v3/index.json set /P BUILDTOOLS_VERSION=< "%~dp0BuildToolsVersion.txt" set BUILD_TOOLS_PATH=%PACKAGES_DIR%Microsoft.DotNet.BuildTools\%BUILDTOOLS_VERSION%\lib\ set PROJECT_JSON_PATH=%TOOLRUNTIME_DIR%\%BUILDTOOLS_VERSION% set PROJECT_JSON_FILE=%PROJECT_JSON_PATH%\project.json set PROJECT_JSON_CONTENTS={ "dependencies": { "Microsoft.DotNet.BuildTools": "%BUILDTOOLS_VERSION%" , "Microsoft.DotNet.BuildTools.Coreclr": "1.0.4-prerelease"}, "frameworks": { "dnxcore50": { } } } -set BUILD_TOOLS_SEMAPHORE=%PROJECT_JSON_PATH%\init-tools.completed +set BUILD_TOOLS_SEMAPHORE=%PROJECT_JSON_PATH%\init-tools.completed0 set TOOLS_INIT_RETURN_CODE=0 :: if force option is specified then clean the tool runtime and build tools package directory to force it to get recreated @@ -39,13 +39,13 @@ if NOT exist "%PROJECT_JSON_PATH%" mkdir "%PROJECT_JSON_PATH%" echo %PROJECT_JSON_CONTENTS% > "%PROJECT_JSON_FILE%" echo Running %0 > "%INIT_TOOLS_LOG%" +set /p DOTNET_VERSION=< "%~dp0DotnetCLIVersion.txt" if exist "%DOTNET_CMD%" goto :afterdotnetrestore echo Installing dotnet cli... if NOT exist "%DOTNET_PATH%" mkdir "%DOTNET_PATH%" -set /p DOTNET_VERSION=< "%~dp0DotnetCLIVersion.txt" if [%PROCESSOR_ARCHITECTURE%]==[x86] (set DOTNET_ZIP_NAME=dotnet-dev-win-x86.%DOTNET_VERSION%.zip) else (set DOTNET_ZIP_NAME=dotnet-dev-win-x64.%DOTNET_VERSION%.zip) -set DOTNET_REMOTE_PATH=https://dotnetcli.blob.core.windows.net/dotnet/preview/Binaries/%DOTNET_VERSION%/%DOTNET_ZIP_NAME% +set DOTNET_REMOTE_PATH=https://dotnetcli.blob.core.windows.net/dotnet/Sdk/%DOTNET_VERSION%/%DOTNET_ZIP_NAME% set DOTNET_LOCAL_PATH=%DOTNET_PATH%%DOTNET_ZIP_NAME% echo Installing '%DOTNET_REMOTE_PATH%' to '%DOTNET_LOCAL_PATH%' >> "%INIT_TOOLS_LOG%" powershell -NoProfile -ExecutionPolicy unrestricted -Command "$retryCount = 0; $success = $false; do { try { (New-Object Net.WebClient).DownloadFile('%DOTNET_REMOTE_PATH%', '%DOTNET_LOCAL_PATH%'); $success = $true; } catch { if ($retryCount -ge 6) { throw; } else { $retryCount++; Start-Sleep -Seconds (5 * $retryCount); } } } while ($success -eq $false); Add-Type -Assembly 'System.IO.Compression.FileSystem' -ErrorVariable AddTypeErrors; if ($AddTypeErrors.Count -eq 0) { [System.IO.Compression.ZipFile]::ExtractToDirectory('%DOTNET_LOCAL_PATH%', '%DOTNET_PATH%') } else { (New-Object -com shell.application).namespace('%DOTNET_PATH%').CopyHere((new-object -com shell.application).namespace('%DOTNET_LOCAL_PATH%').Items(),16) }" >> "%INIT_TOOLS_LOG%" @@ -73,6 +73,14 @@ echo Initializing BuildTools ... echo Running: "%BUILD_TOOLS_PATH%init-tools.cmd" "%~dp0" "%DOTNET_CMD%" "%TOOLRUNTIME_DIR%" >> "%INIT_TOOLS_LOG%" call "%BUILD_TOOLS_PATH%init-tools.cmd" "%~dp0" "%DOTNET_CMD%" "%TOOLRUNTIME_DIR%" >> "%INIT_TOOLS_LOG%" +echo Updating CLI NuGet Frameworks map... +robocopy "%TOOLRUNTIME_DIR%" "%TOOLRUNTIME_DIR%\dotnetcli\sdk\%DOTNET_VERSION%" NuGet.Frameworks.dll /XO >> "%INIT_TOOLS_LOG%" +set UPDATE_CLI_ERRORLEVEL=%ERRORLEVEL% +if %UPDATE_CLI_ERRORLEVEL% GTR 1 ( + echo ERROR: Failed to update Nuget for CLI {Error level %UPDATE_CLI_ERRORLEVEL%}. Please check '%INIT_TOOLS_LOG%' for more details. 1>&2 + exit /b %UPDATE_CLI_ERRORLEVEL% +) + :: Create sempahore file echo Done initializing tools. echo Init-Tools.cmd completed for BuildTools Version: %BUILDTOOLS_VERSION% > "%BUILD_TOOLS_SEMAPHORE%" diff --git a/init-tools.log b/init-tools.log new file mode 100644 index 0000000..7a96daa --- /dev/null +++ b/init-tools.log @@ -0,0 +1,539 @@ +Running: /home/jyoung/git/dotnet/coreclr-1.0.0/init-tools.sh +Installing 'https://dotnetcli.blob.core.windows.net/dotnet/Sdk/1.0.0-preview3-003223/dotnet-dev-ubuntu-x64.1.0.0-preview3-003223.tar.gz' to '/home/jyoung/git/dotnet/coreclr-1.0.0/Tools/dotnetcli/dotnet.tar' +Running: /home/jyoung/git/dotnet/coreclr-1.0.0/Tools/dotnetcli/dotnet restore "/home/jyoung/git/dotnet/coreclr-1.0.0/Tools/1.0.27-prerelease-01008-01/project.json" --no-cache --packages /home/jyoung/git/dotnet/coreclr-1.0.0/packages --source https://dotnet.myget.org/F/dotnet-buildtools/api/v3/index.json +log : Restoring packages for /home/jyoung/git/dotnet/coreclr-1.0.0/Tools/1.0.27-prerelease-01008-01/project.json... +log : Installing Microsoft.DotNet.BuildTools 1.0.27-prerelease-01008-01. +log : Writing lock file to disk. Path: /home/jyoung/git/dotnet/coreclr-1.0.0/Tools/1.0.27-prerelease-01008-01/project.lock.json +log : /home/jyoung/git/dotnet/coreclr-1.0.0/Tools/1.0.27-prerelease-01008-01/project.json +log : Restore completed in 4349ms. +Running: /home/jyoung/git/dotnet/coreclr-1.0.0/packages/Microsoft.DotNet.BuildTools/1.0.27-prerelease-01008-01/lib/init-tools.sh /home/jyoung/git/dotnet/coreclr-1.0.0 /home/jyoung/git/dotnet/coreclr-1.0.0/Tools/dotnetcli/dotnet /home/jyoung/git/dotnet/coreclr-1.0.0/Tools +Running: /home/jyoung/git/dotnet/coreclr-1.0.0/Tools/dotnetcli/dotnet restore "/home/jyoung/git/dotnet/coreclr-1.0.0/packages/Microsoft.DotNet.BuildTools/1.0.27-prerelease-01008-01/lib/tool-runtime/project.json" --source https://dotnet.myget.org/F/dotnet-core/api/v3/index.json --source https://dotnet.myget.org/F/dotnet-buildtools/api/v3/index.json --source https://api.nuget.org/v3/index.json +log : Restoring packages for /home/jyoung/git/dotnet/coreclr-1.0.0/packages/Microsoft.DotNet.BuildTools/1.0.27-prerelease-01008-01/lib/tool-runtime/project.json... +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: MSBuild from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> MSBuild +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: MSBuild from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> MSBuild +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: MSBuild from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> MSBuild +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: MSBuild from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> MSBuild +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: MSBuild from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> MSBuild +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: MSBuild from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> MSBuild +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: MSBuild from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> MSBuild +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: MSBuild from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> MSBuild +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: MSBuild from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> MSBuild +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: MSBuild from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> MSBuild +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: MSBuild from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> MSBuild +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: MSBuild from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> MSBuild +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: MSBuild from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> MSBuild +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Utilities.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Utilities.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Utilities.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Tasks.Core from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Tasks.Core +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Tasks.Core (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: MSBuild from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Targets (>= 0.1.0-preview-00024-160610) -> MSBuild +warn : tool-runtime (>= 1.0.0) -> MSBuild (>= 0.1.0-preview-00024-160610) +warn : Detected package downgrade: Microsoft.Build.Framework from 0.0.0 to 0.1.0-preview-00024-160610 +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build (>= 0.1.0-preview-00024-160610) -> Microsoft.Build.Framework +warn : tool-runtime (>= 1.0.0) -> Microsoft.Build.Framework (>= 0.1.0-preview-00024-160610) +log : Writing lock file to disk. Path: /home/jyoung/git/dotnet/coreclr-1.0.0/packages/Microsoft.DotNet.BuildTools/1.0.27-prerelease-01008-01/lib/tool-runtime/project.lock.json +log : /home/jyoung/git/dotnet/coreclr-1.0.0/packages/Microsoft.DotNet.BuildTools/1.0.27-prerelease-01008-01/lib/tool-runtime/project.json +log : Restore completed in 3868ms. +Running: /home/jyoung/git/dotnet/coreclr-1.0.0/Tools/dotnetcli/dotnet publish "/home/jyoung/git/dotnet/coreclr-1.0.0/packages/Microsoft.DotNet.BuildTools/1.0.27-prerelease-01008-01/lib/tool-runtime/project.json" -f netcoreapp1.0 -r ubuntu.14.04-x64 -o /home/jyoung/git/dotnet/coreclr-1.0.0/Tools +Publishing tool-runtime for .NETCoreApp,Version=v1.0/ubuntu.14.04-x64 +Project tool-runtime (.NETCoreApp,Version=v1.0) will be compiled because expected outputs are missing +Compiling tool-runtime for .NETCoreApp,Version=v1.0 + +Compilation succeeded. + 0 Warning(s) + 0 Error(s) + +Time elapsed 00:00:00.8157822 + + +publish: Published to /home/jyoung/git/dotnet/coreclr-1.0.0/Tools +Published 1/1 projects successfully +Running: "/home/jyoung/git/dotnet/coreclr-1.0.0/Tools/dotnetcli/dotnet" restore "/home/jyoung/git/dotnet/coreclr-1.0.0/Tools/generated/project.json" --source https://dotnet.myget.org/F/dotnet-buildtools/api/v3/index.json --source https://api.nuget.org/v3/index.json --packages "/home/jyoung/git/dotnet/coreclr-1.0.0/Tools/." +log : Restoring packages for /home/jyoung/git/dotnet/coreclr-1.0.0/Tools/generated/project.json... +log : Installing Microsoft.Portable.Targets 0.1.1-dev. +log : Installing MicroBuild.Core 0.2.0. +log : Writing lock file to disk. Path: /home/jyoung/git/dotnet/coreclr-1.0.0/Tools/generated/project.lock.json +log : /home/jyoung/git/dotnet/coreclr-1.0.0/Tools/generated/project.json +log : Restore completed in 1274ms. diff --git a/init-tools.sh b/init-tools.sh index e6966cc..cc8a5d8 100755 --- a/init-tools.sh +++ b/init-tools.sh @@ -1,121 +1,169 @@ #!/usr/bin/env bash -initDistroName() -{ - if [ "$1" == "Linux" ]; then - if [ ! -e /etc/os-release ]; then - echo "WARNING: Can not determine runtime id for current distro." - export __DistroRid="" - else - source /etc/os-release - export __DistroRid="$ID.$VERSION_ID-x64" - fi - fi -} - __scriptpath=$(cd "$(dirname "$0")"; pwd -P) - -# CI_SPECIFIC - On CI machines, $HOME may not be set. In such a case, create a subfolder and set the variable to set. -# This is needed by CLI to function. -if [ -z "$HOME" ]; then - if [ ! -d "$__scriptpath/temp_home" ]; then - mkdir temp_home - fi - export HOME=$__scriptpath/temp_home - echo "HOME not defined; setting it to $HOME" -fi - +__init_tools_log=$__scriptpath/init-tools.log __PACKAGES_DIR=$__scriptpath/packages __TOOLRUNTIME_DIR=$__scriptpath/Tools __DOTNET_PATH=$__TOOLRUNTIME_DIR/dotnetcli __DOTNET_CMD=$__DOTNET_PATH/dotnet -if [ -z "$__BUILDTOOLS_SOURCE" ]; then __BUILDTOOLS_SOURCE=https://www.myget.org/F/dotnet-buildtools/; fi +if [ -z "$__BUILDTOOLS_SOURCE" ]; then __BUILDTOOLS_SOURCE=https://dotnet.myget.org/F/dotnet-buildtools/api/v3/index.json; fi __BUILD_TOOLS_PACKAGE_VERSION=$(cat $__scriptpath/BuildToolsVersion.txt) __DOTNET_TOOLS_VERSION=$(cat $__scriptpath/DotnetCLIVersion.txt) __BUILD_TOOLS_PATH=$__PACKAGES_DIR/Microsoft.DotNet.BuildTools/$__BUILD_TOOLS_PACKAGE_VERSION/lib __PROJECT_JSON_PATH=$__TOOLRUNTIME_DIR/$__BUILD_TOOLS_PACKAGE_VERSION __PROJECT_JSON_FILE=$__PROJECT_JSON_PATH/project.json -__PROJECT_JSON_CONTENTS="{ \"dependencies\": { \"Microsoft.DotNet.BuildTools\": \"$__BUILD_TOOLS_PACKAGE_VERSION\" }, \"frameworks\": { \"dnxcore50\": { } } }" -__DistroRid="" - -OSName=$(uname -s) -case $OSName in - Darwin) - OS=OSX - __DOTNET_PKG=dotnet-dev-osx-x64 - ;; - - Linux) - OS=Linux - - if [ ! -e /etc/os-release ]; then - echo "Cannot determine Linux distribution, asuming Ubuntu 14.04." - __DOTNET_PKG=dotnet-dev-ubuntu.14.04-x64 - else - source /etc/os-release - __DOTNET_PKG="dotnet-dev-$ID.$VERSION_ID-x64" +__PROJECT_JSON_CONTENTS="{ \"dependencies\": { \"Microsoft.DotNet.BuildTools\": \"$__BUILD_TOOLS_PACKAGE_VERSION\" }, \"frameworks\": { \"netcoreapp1.0\": { } } }" +__INIT_TOOLS_DONE_MARKER=$__PROJECT_JSON_PATH/done + +# Extended version of platform detection logic from dotnet/cli/scripts/obtain/dotnet-install.sh 16692fc +get_current_linux_name() { + # Detect Distro + if [ "$(cat /etc/*-release | grep -cim1 ubuntu)" -eq 1 ]; then + if [ "$(cat /etc/*-release | grep -cim1 16.04)" -eq 1 ]; then + echo "ubuntu.16.04" + return 0 + fi + if [ "$(cat /etc/*-release | grep -cim1 16.10)" -eq 1 ]; then + echo "ubuntu.16.10" + return 0 fi - ;; - - *) - echo "Unsupported OS $OSName detected. Downloading ubuntu-x64 tools" - OS=Linux - __DOTNET_PKG=dotnet-dev-ubuntu.14.04-x64 - ;; -esac -# Initialize Linux Distribution name and .NET CLI package name. + echo "ubuntu" + return 0 + elif [ "$(cat /etc/*-release | grep -cim1 centos)" -eq 1 ]; then + echo "centos" + return 0 + elif [ "$(cat /etc/*-release | grep -cim1 rhel)" -eq 1 ]; then + echo "rhel" + return 0 + elif [ "$(cat /etc/*-release | grep -cim1 debian)" -eq 1 ]; then + echo "debian" + return 0 + elif [ "$(cat /etc/*-release | grep -cim1 alpine)" -eq 1 ]; then + echo "alpine" + return 0 + elif [ "$(cat /etc/*-release | grep -cim1 fedora)" -eq 1 ]; then + if [ "$(cat /etc/*-release | grep -cim1 23)" -eq 1 ]; then + echo "fedora.23" + return 0 + fi + if [ "$(cat /etc/*-release | grep -cim1 24)" -eq 1 ]; then + echo "fedora.24" + return 0 + fi + elif [ "$(cat /etc/*-release | grep -cim1 opensuse)" -eq 1 ]; then + if [ "$(cat /etc/*-release | grep -cim1 13.2)" -eq 1 ]; then + echo "opensuse.13.2" + return 0 + fi + if [ "$(cat /etc/*-release | grep -cim1 42.1)" -eq 1 ]; then + echo "opensuse.42.1" + return 0 + fi + fi -initDistroName $OS + # Cannot determine Linux distribution, assuming Ubuntu 14.04. + echo "ubuntu" + return 0 +} -# Work around mac build issue -if [ "$OS" == "OSX" ]; then - echo Raising file open limit - otherwise Mac build may fail - echo ulimit -n 2048 - ulimit -n 2048 +if [ -z "$__DOTNET_PKG" ]; then +OSName=$(uname -s) + case $OSName in + Darwin) + OS=OSX + __DOTNET_PKG=dotnet-dev-osx-x64 + ulimit -n 2048 + ;; + + Linux) + __DOTNET_PKG="dotnet-dev-$(get_current_linux_name)-x64" + OS=Linux + ;; + + *) + echo "Unsupported OS '$OSName' detected. Downloading ubuntu-x64 tools." + OS=Linux + __DOTNET_PKG=dotnet-dev-ubuntu-x64 + ;; + esac fi -__CLIDownloadURL=https://dotnetcli.blob.core.windows.net/dotnet/preview/Binaries/${__DOTNET_TOOLS_VERSION}/${__DOTNET_PKG}.${__DOTNET_TOOLS_VERSION}.tar.gz -echo ".NET CLI will be downloaded from $__CLIDownloadURL" -echo "Locating $__PROJECT_JSON_FILE to see if we already downloaded .NET CLI tools..." +if [ ! -e $__INIT_TOOLS_DONE_MARKER ]; then + __PATCH_CLI_NUGET_FRAMEWORKS=0 -if [ ! -e $__PROJECT_JSON_FILE ]; then - echo "$__PROJECT_JSON_FILE not found. Proceeding to download .NET CLI tools. " if [ -e $__TOOLRUNTIME_DIR ]; then rm -rf -- $__TOOLRUNTIME_DIR; fi + echo "Running: $__scriptpath/init-tools.sh" > $__init_tools_log if [ ! -e $__DOTNET_PATH ]; then - # curl has HTTPS CA trust-issues less often than wget, so lets try that first. - which curl > /dev/null 2> /dev/null - if [ $? -ne 0 ]; then - mkdir -p "$__DOTNET_PATH" - wget -q -O $__DOTNET_PATH/dotnet.tar $__CLIDownloadURL - echo "wget -q -O $__DOTNET_PATH/dotnet.tar $__CLIDownloadURL" + + mkdir -p "$__DOTNET_PATH" + + if [ -n "$DOTNET_TOOLSET_DIR" ] && [ -d "$DOTNET_TOOLSET_DIR/$__DOTNET_TOOLS_VERSION" ]; then + echo "Copying $DOTNET_TOOLSET_DIR/$__DOTNET_TOOLS_VERSION to $__DOTNET_PATH" >> $__init_tools_log + cp -r $DOTNET_TOOLSET_DIR/$__DOTNET_TOOLS_VERSION/* $__DOTNET_PATH + elif [ -n "$DOTNET_TOOL_DIR" ] && [ -d "$DOTNET_TOOL_DIR" ]; then + echo "Copying $DOTNET_TOOL_DIR to $__DOTNET_PATH" >> $__init_tools_log + cp -r $DOTNET_TOOL_DIR/* $__DOTNET_PATH else - curl --retry 10 -sSL --create-dirs -o $__DOTNET_PATH/dotnet.tar $__CLIDownloadURL - echo "curl --retry 10 -sSL --create-dirs -o $__DOTNET_PATH/dotnet.tar $__CLIDownloadURL" + echo "Installing dotnet cli..." + __DOTNET_LOCATION="https://dotnetcli.blob.core.windows.net/dotnet/Sdk/${__DOTNET_TOOLS_VERSION}/${__DOTNET_PKG}.${__DOTNET_TOOLS_VERSION}.tar.gz" + # curl has HTTPS CA trust-issues less often than wget, so lets try that first. + echo "Installing '${__DOTNET_LOCATION}' to '$__DOTNET_PATH/dotnet.tar'" >> $__init_tools_log + which curl > /dev/null 2> /dev/null + if [ $? -ne 0 ]; then + wget -q -O $__DOTNET_PATH/dotnet.tar ${__DOTNET_LOCATION} + else + curl --retry 10 -sSL --create-dirs -o $__DOTNET_PATH/dotnet.tar ${__DOTNET_LOCATION} + fi + cd $__DOTNET_PATH + tar -xf $__DOTNET_PATH/dotnet.tar + + cd $__scriptpath + + __PATCH_CLI_NUGET_FRAMEWORKS=1 fi - cd $__DOTNET_PATH - tar -xf $__DOTNET_PATH/dotnet.tar - if [ -n "$BUILDTOOLS_OVERRIDE_RUNTIME" ]; then - find $__DOTNET_PATH -name *.ni.* | xargs rm 2>/dev/null - cp -R $BUILDTOOLS_OVERRIDE_RUNTIME/* $__DOTNET_PATH/bin - cp -R $BUILDTOOLS_OVERRIDE_RUNTIME/* $__DOTNET_PATH/bin/dnx - cp -R $BUILDTOOLS_OVERRIDE_RUNTIME/* $__DOTNET_PATH/runtime/coreclr + fi + + + if [ -n "$BUILD_TOOLS_TOOLSET_DIR" ] && [ -d "$BUILD_TOOLS_TOOLSET_DIR/$__BUILD_TOOLS_PACKAGE_VERSION" ]; then + echo "Copying $BUILD_TOOLS_TOOLSET_DIR/$__BUILD_TOOLS_PACKAGE_VERSION to $__TOOLRUNTIME_DIR" >> $__init_tools_log + cp -r $BUILD_TOOLS_TOOLSET_DIR/$__BUILD_TOOLS_PACKAGE_VERSION/* $__TOOLRUNTIME_DIR + elif [ -n "$BUILD_TOOLS_TOOL_DIR" ] && [ -d "$BUILD_TOOLS_TOOL_DIR" ]; then + echo "Copying $BUILD_TOOLS_TOOL_DIR to $__TOOLRUNTIME_DIR" >> $__init_tools_log + cp -r $BUILD_TOOLS_TOOL_DIR/* $__TOOLRUNTIME_DIR + else + if [ ! -d "$__PROJECT_JSON_PATH" ]; then mkdir "$__PROJECT_JSON_PATH"; fi + echo $__PROJECT_JSON_CONTENTS > "$__PROJECT_JSON_FILE" + + if [ ! -e $__BUILD_TOOLS_PATH ]; then + echo "Restoring BuildTools version $__BUILD_TOOLS_PACKAGE_VERSION..." + echo "Running: $__DOTNET_CMD restore \"$__PROJECT_JSON_FILE\" --no-cache --packages $__PACKAGES_DIR --source $__BUILDTOOLS_SOURCE" >> $__init_tools_log + $__DOTNET_CMD restore "$__PROJECT_JSON_FILE" --no-cache --packages $__PACKAGES_DIR --source $__BUILDTOOLS_SOURCE >> $__init_tools_log + if [ ! -e "$__BUILD_TOOLS_PATH/init-tools.sh" ]; then echo "ERROR: Could not restore build tools correctly. See '$__init_tools_log' for more details."1>&2; fi fi - cd $__scriptpath + echo "Initializing BuildTools..." + echo "Running: $__BUILD_TOOLS_PATH/init-tools.sh $__scriptpath $__DOTNET_CMD $__TOOLRUNTIME_DIR" >> $__init_tools_log + $__BUILD_TOOLS_PATH/init-tools.sh $__scriptpath $__DOTNET_CMD $__TOOLRUNTIME_DIR >> $__init_tools_log + if [ "$?" != "0" ]; then + echo "ERROR: An error occured when trying to initialize the tools. Please check '$__init_tools_log' for more details."1>&2 + exit 1 + fi fi - mkdir "$__PROJECT_JSON_PATH" - echo $__PROJECT_JSON_CONTENTS > "$__PROJECT_JSON_FILE" - - if [ ! -e $__BUILD_TOOLS_PATH ]; then - $__DOTNET_CMD restore "$__PROJECT_JSON_FILE" --packages $__PACKAGES_DIR --source $__BUILDTOOLS_SOURCE + if [ $__PATCH_CLI_NUGET_FRAMEWORKS -eq 1 ]; then + echo "Updating CLI NuGet Frameworks map..." + cp $__TOOLRUNTIME_DIR/NuGet.Frameworks.dll $__TOOLRUNTIME_DIR/dotnetcli/sdk/$__DOTNET_TOOLS_VERSION >> $__init_tools_log + if [ "$?" != "0" ]; then + echo "ERROR: An error occured when updating Nuget for CLI . Please check '$__init_tools_log' for more details."1>&2 + exit 1 + fi fi - # On ubuntu 14.04, /bin/sh (symbolic link) calls /bin/dash by default. - $__BUILD_TOOLS_PATH/init-tools.sh $__scriptpath $__DOTNET_CMD $__TOOLRUNTIME_DIR + touch $__INIT_TOOLS_DONE_MARKER + echo "Done initializing tools." else - echo "$__PROJECT_JSON_FILE found. Skipping .NET CLI installation." + echo "Tools are already initialized" fi diff --git a/netci.groovy b/netci.groovy index 8527b2c..b1ffaf8 100755 --- a/netci.groovy +++ b/netci.groovy @@ -15,6 +15,7 @@ def static getOSGroup(def os) { def osGroupMap = ['Ubuntu':'Linux', 'RHEL7.2': 'Linux', 'Ubuntu16.04': 'Linux', + 'Ubuntu16.10': 'Linux', 'Debian8.4':'Linux', 'Fedora23':'Linux', 'OSX':'OSX', @@ -31,20 +32,43 @@ def static getOSGroup(def os) { // We use this class (vs variables) so that the static functions can access data here. class Constants { + // Innerloop build OS's // The Windows_NT_BuildOnly OS is a way to speed up the Non-NT builds temporarily by avoiding // test execution in the build flow runs. It generates the exact same build // as Windows_NT but without the tests. - def static osList = ['Ubuntu', 'Debian8.4', 'OSX', 'Windows_NT', 'Windows_NT_BuildOnly', 'FreeBSD', 'CentOS7.1', 'OpenSUSE13.2', 'OpenSUSE42.1', 'RHEL7.2', 'LinuxARMEmulator', 'Ubuntu16.04', 'Fedora23'] + def static osList = [ + 'Ubuntu', + 'Debian8.4', + 'OSX', + 'Windows_NT', + 'Windows_NT_BuildOnly', + 'FreeBSD', + 'CentOS7.1', + 'OpenSUSE13.2', + 'OpenSUSE42.1', + 'RHEL7.2', + 'LinuxARMEmulator', + 'Ubuntu16.04', + 'Ubuntu16.10', + 'Fedora23'] + def static crossList = ['Ubuntu', 'OSX', 'CentOS7.1', 'RHEL7.2', 'Debian8.4', 'OpenSUSE13.2'] + // This is a set of JIT stress modes combined with the set of variables that // need to be set to actually enable that stress mode. The key of the map is the stress mode and // the values are the environment variables - def static jitStressModeScenarios = ['minopts' : ['COMPlus_JITMinOpts' : '1'], 'forcerelocs' : ['COMPlus_ForceRelocs' : '1'], - 'jitstress1' : ['COMPlus_JitStress' : '1'], 'jitstress2' : ['COMPlus_JitStress' : '2'], - 'jitstressregs1' : ['COMPlus_JitStressRegs' : '1'], 'jitstressregs2' : ['COMPlus_JitStressRegs' : '2'], - 'jitstressregs3' : ['COMPlus_JitStressRegs' : '3'], 'jitstressregs4' : ['COMPlus_JitStressRegs' : '4'], - 'jitstressregs8' : ['COMPlus_JitStressRegs' : '8'], 'jitstressregs0x10' : ['COMPlus_JitStressRegs' : '0x10'], + def static jitStressModeScenarios = [ + 'minopts' : ['COMPlus_JITMinOpts' : '1'], + 'forcerelocs' : ['COMPlus_ForceRelocs' : '1'], + 'jitstress1' : ['COMPlus_JitStress' : '1'], + 'jitstress2' : ['COMPlus_JitStress' : '2'], + 'jitstressregs1' : ['COMPlus_JitStressRegs' : '1'], + 'jitstressregs2' : ['COMPlus_JitStressRegs' : '2'], + 'jitstressregs3' : ['COMPlus_JitStressRegs' : '3'], + 'jitstressregs4' : ['COMPlus_JitStressRegs' : '4'], + 'jitstressregs8' : ['COMPlus_JitStressRegs' : '8'], + 'jitstressregs0x10' : ['COMPlus_JitStressRegs' : '0x10'], 'jitstressregs0x80' : ['COMPlus_JitStressRegs' : '0x80'], 'jitstress2_jitstressregs1' : ['COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '1'], 'jitstress2_jitstressregs2' : ['COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '2'], @@ -53,33 +77,62 @@ class Constants { 'jitstress2_jitstressregs8' : ['COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '8'], 'jitstress2_jitstressregs0x10' : ['COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '0x10'], 'jitstress2_jitstressregs0x80' : ['COMPlus_JitStress' : '2', 'COMPlus_JitStressRegs' : '0x80'], - 'corefx_baseline' : [ : ], // corefx baseline - 'corefx_minopts' : ['COMPlus_JITMinOpts' : '1'], + 'corefx_baseline' : [ : ], // corefx baseline + 'corefx_minopts' : ['COMPlus_JITMinOpts' : '1'], 'corefx_jitstress1' : ['COMPlus_JitStress' : '1'], 'corefx_jitstress2' : ['COMPlus_JitStress' : '2'], - 'corefx_jitstressregs1' : ['COMPlus_JitStressRegs' : '1'], 'corefx_jitstressregs2' : ['COMPlus_JitStressRegs' : '2'], - 'corefx_jitstressregs3' : ['COMPlus_JitStressRegs' : '3'], 'corefx_jitstressregs4' : ['COMPlus_JitStressRegs' : '4'], - 'corefx_jitstressregs8' : ['COMPlus_JitStressRegs' : '8'], 'corefx_jitstressregs0x10' : ['COMPlus_JitStressRegs' : '0x10'], + 'corefx_jitstressregs1' : ['COMPlus_JitStressRegs' : '1'], + 'corefx_jitstressregs2' : ['COMPlus_JitStressRegs' : '2'], + 'corefx_jitstressregs3' : ['COMPlus_JitStressRegs' : '3'], + 'corefx_jitstressregs4' : ['COMPlus_JitStressRegs' : '4'], + 'corefx_jitstressregs8' : ['COMPlus_JitStressRegs' : '8'], + 'corefx_jitstressregs0x10' : ['COMPlus_JitStressRegs' : '0x10'], 'corefx_jitstressregs0x80' : ['COMPlus_JitStressRegs' : '0x80'], - 'gcstress0x3' : ['COMPlus_GCStress' : '0x3'], 'gcstress0xc' : ['COMPlus_GCStress' : '0xC'], - 'zapdisable' : ['COMPlus_ZapDisable' : '0xC'], - 'heapverify1' : ['COMPlus_HeapVerify' : '1'], - 'gcstress0xc_zapdisable' : ['COMPlus_GCStress' : '0xC', 'COMPlus_ZapDisable' : '1'], - 'gcstress0xc_zapdisable_jitstress2' : ['COMPlus_GCStress' : '0xC', 'COMPlus_ZapDisable' : '1', 'COMPlus_JitStress' : '2'], - 'gcstress0xc_zapdisable_heapverify1' : ['COMPlus_GCStress' : '0xC', 'COMPlus_ZapDisable' : '1', 'COMPlus_HeapVerify' : '1'], - 'gcstress0xc_jitstress1' : ['COMPlus_GCStress' : '0xC', 'COMPlus_JitStress' : '1'], - 'gcstress0xc_jitstress2' : ['COMPlus_GCStress' : '0xC', 'COMPlus_JitStress' : '2'], - 'gcstress0xc_minopts_heapverify1' : ['COMPlus_GCStress' : '0xC', 'COMPlus_JITMinOpts' : '1', 'COMPlus_HeapVerify' : '1'] + 'gcstress0x3' : ['COMPlus_GCStress' : '0x3'], + 'gcstress0xc' : ['COMPlus_GCStress' : '0xC'], + 'zapdisable' : ['COMPlus_ZapDisable' : '1'], + 'heapverify1' : ['COMPlus_HeapVerify' : '1'], + 'gcstress0xc_zapdisable' : ['COMPlus_GCStress' : '0xC', 'COMPlus_ZapDisable' : '1'], + 'gcstress0xc_zapdisable_jitstress2' : ['COMPlus_GCStress' : '0xC', 'COMPlus_ZapDisable' : '1', 'COMPlus_JitStress' : '2'], + 'gcstress0xc_zapdisable_heapverify1' : ['COMPlus_GCStress' : '0xC', 'COMPlus_ZapDisable' : '1', 'COMPlus_HeapVerify' : '1'], + 'gcstress0xc_jitstress1' : ['COMPlus_GCStress' : '0xC', 'COMPlus_JitStress' : '1'], + 'gcstress0xc_jitstress2' : ['COMPlus_GCStress' : '0xC', 'COMPlus_JitStress' : '2'], + 'gcstress0xc_minopts_heapverify1' : ['COMPlus_GCStress' : '0xC', 'COMPlus_JITMinOpts' : '1', 'COMPlus_HeapVerify' : '1'] ] + // This is a set of r2r jit stress scenarios - def static r2rJitStressScenarios = ['r2r_jitstress1', 'r2r_jitstress2', 'r2r_jitstressregs1', 'r2r_jitstressregs2', 'r2r_jitstressregs3', - 'r2r_jitstressregs4', 'r2r_jitstressregs8', 'r2r_jitstressregsx10', 'r2r_jitstressregsx80', - 'r2r_jitminopts', 'r2r_jitforcerelocs'] + def static r2rJitStressScenarios = [ + 'r2r_jitstress1', + 'r2r_jitstress2', + 'r2r_jitstressregs1', + 'r2r_jitstressregs2', + 'r2r_jitstressregs3', + 'r2r_jitstressregs4', + 'r2r_jitstressregs8', + 'r2r_jitstressregsx10', + 'r2r_jitstressregsx80', + 'r2r_jitminopts', + 'r2r_jitforcerelocs'] + // This is the basic set of scenarios - def static basicScenarios = ['default', 'pri1', 'ilrt', 'r2r', 'pri1r2r', 'gcstress15_pri1r2r', 'longgc', 'coverage', 'formatting', 'gcsimulator'] + r2rJitStressScenarios + def static basicScenarios = [ + 'default', + 'pri1', + 'ilrt', + 'r2r', + 'pri1r2r', + 'gcstress15_pri1r2r', + 'longgc', + 'coverage', + 'formatting', + 'gcsimulator', + 'jitdiff', + 'standalone_gc'] + r2rJitStressScenarios + def static configurationList = ['Debug', 'Checked', 'Release'] + // This is the set of architectures - def static architectureList = ['arm', 'arm64', 'x64', 'x86ryujit', 'x86lb'] + def static architectureList = ['arm', 'arm64', 'x64', 'x86', 'x86compatjit', 'x86lb'] } def static setMachineAffinity(def job, def os, def architecture) { @@ -139,6 +192,10 @@ def static isLongGc(def scenario) { return (scenario == 'longgc' || scenario == 'gcsimulator') } +def static isJitDiff(def scenario) { + return (scenario == 'jitdiff') +} + def static setTestJobTimeOut(newJob, scenario) { if (isGCStressRelatedTesting(scenario)) { Utilities.setJobTimeout(newJob, 4320) @@ -158,6 +215,9 @@ def static setTestJobTimeOut(newJob, scenario) { else if (isLongGc(scenario)) { Utilities.setJobTimeout(newJob, 1440) } + else if (isJitDiff(scenario)) { + Utilities.setJobTimeout(newJob, 240) + } // Non-test jobs use the default timeout value. } @@ -267,8 +327,11 @@ def static getJobName(def configuration, def architecture, def os, def scenario, baseName = architecture.toLowerCase() + '_emulator_cross_' + configuration.toLowerCase() + '_' + os.toLowerCase() } break - case 'x86ryujit': - baseName = 'x86_ryujit_' + configuration.toLowerCase() + '_' + os.toLowerCase() + case 'x86': + baseName = architecture.toLowerCase() + '_' + configuration.toLowerCase() + '_' + os.toLowerCase() + break + case 'x86compatjit': + baseName = 'x86_compatjit_' + configuration.toLowerCase() + '_' + os.toLowerCase() break case 'x86lb': baseName = 'x86_lb_' + configuration.toLowerCase() + '_' + os.toLowerCase() @@ -305,7 +368,8 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os, case 'default': switch (architecture) { case 'x64': - case 'x86ryujit': + case 'x86': + case 'x86compatjit': case 'x86lb': if (isFlowJob || os == 'Windows_NT' || !(os in Constants.crossList)) { Utilities.addGithubPushTrigger(job) @@ -366,7 +430,7 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os, } } // For x86, only add per-commit jobs for Windows - else if (architecture == 'x86ryujit' || architecture == 'x86lb') { + else if (architecture == 'x86' || architecture == 'x86compatjit' || architecture == 'x86lb') { if (os == 'Windows_NT') { Utilities.addGithubPushTrigger(job) } @@ -411,7 +475,7 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os, } } // For x86, only add per-commit jobs for Windows - else if (architecture == 'x86ryujit' || architecture == 'x86lb') { + else if (architecture == 'x86' || architecture == 'x86compatjit' || architecture == 'x86lb') { if (os == 'Windows_NT') { Utilities.addPeriodicTrigger(job, 'H H * * 3,6') // some time every Wednesday and Saturday } @@ -434,6 +498,13 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os, // TODO: Add once external email sending is available again // addEmailPublisher(job, 'dotnetgctests@microsoft.com') break + case 'standalone_gc': + assert (os == 'Windows_NT') + assert (configuration == 'Release' || configuration == 'Checked') + // TODO: Add once external email sending is available again + // addEmailPublisher(job, 'dotnetgctests@microsoft.com') + Utilities.addPeriodicTrigger(job, '@weekly') + break case 'ilrt': assert !(os in bidailyCrossList) // ILASM/ILDASM roundtrip one gets a daily build, and only for release @@ -445,6 +516,12 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os, } } break + case 'jitdiff': + assert (os == 'Ubuntu' || os == 'Windows_NT' || os == 'OSX') + assert configuration == 'Checked' + assert (architecture == 'x64' || architecture == 'x86') + Utilities.addGithubPushTrigger(job) + break case 'coverage': assert (os == 'Ubuntu' || os == 'Windows_NT') assert configuration == 'Release' @@ -539,7 +616,7 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os, // We generally only have a distinct set of default triggers but a bunch of on-demand ones. def osGroup = getOSGroup(os) switch (architecture) { - case 'x64': + case 'x64': // editor brace matching: { if (scenario == 'coverage') { assert configuration == 'Release' if (os == 'Ubuntu') { @@ -551,7 +628,7 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os, if (scenario == 'formatting') { assert configuration == 'Checked' if (os == 'Windows_NT' || os == 'Ubuntu') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} Formatting", "(?i).*test\\W+${os}\\W+formatting.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} Formatting") } break } @@ -572,6 +649,7 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os, break case 'Fedora23': case 'Ubuntu16.04': + case 'Ubuntu16.10': case 'OpenSUSE42.1': assert !isFlowJob assert scenario == 'default' @@ -597,6 +675,11 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os, Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Priority 1 Build and Test", "(?i).*test\\W+${os}\\W+${scenario}.*") } break + case 'jitdiff': + if (configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Jit Diff Build and Test", "(?i).*test\\W+${os}\\W+${scenario}.*") + } + break case 'ilrt': if (configuration == 'Release') { Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} IL RoundTrip Build and Test", "(?i).*test\\W+${os}\\W+${scenario}.*") @@ -874,6 +957,11 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os, Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Priority 1 Build and Test") } break + case 'jitdiff': + if (configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Jit Diff Build and Test", "(?i).*test\\W+${os}\\W+${scenario}.*") + } + break case 'ilrt': if (configuration == 'Release') { Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} IL RoundTrip Build and Test", "(?i).*test\\W+${os}\\W+${scenario}.*") @@ -959,6 +1047,11 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os, Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} GC Simulator", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*") } break + case 'standalone_gc': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Standalone GC", "(?i).*test\\W+${os}\\W+${configuration}\\W+${scenario}.*") + } + break case 'minopts': assert (os == 'Windows_NT') || (os in Constants.crossList) Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - MinOpts)", @@ -1070,7 +1163,8 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os, break } break - case 'arm': + // editor brace matching: } + case 'arm': // editor brace matching: { assert scenario == 'default' switch (os) { case 'Ubuntu': @@ -1082,13 +1176,20 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os, Utilities.addGithubPRTriggerForBranch(job, branch, "Linux ARM Emulator Cross ${configuration} Build") } break + case 'Windows_NT': + if (configuration == 'Debug' || configuration == 'Release') + { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} Cross ${configuration} Build") + } + break default: println("NYI os: ${os}"); assert false break } break - case 'arm64': + // editor brace matching: } + case 'arm64': // editor brace matching: { assert (scenario == 'default') || (scenario == 'pri1r2r') || (scenario == 'gcstress0x3') || (scenario == 'gcstress0xc') // Set up a private trigger @@ -1123,165 +1224,360 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os, break } break - case 'x86ryujit': - def arch = 'x86' - def jit = 'ryujit' + // editor brace matching: } + case 'x86': // editor brace matching: { + assert (os == 'Windows_NT') switch (scenario) { case 'default': - // Default trigger - if (os == 'Windows_NT') { - if (configuration == 'Checked') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Build and Test") - } + if (configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test") } - else { - // default trigger - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Build", "(?i).*test\\W+${arch}\\W+${osGroup}.\\W+${jit}.*") + break + case 'pri1': + if (configuration == 'Release') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Priority 1 Build and Test") + } + break + case 'ilrt': + if (configuration == 'Release') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} IL RoundTrip Build and Test", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + } + break + case 'r2r': + if (configuration == 'Checked' || configuration == 'Release') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} R2R pri0 Build & Test", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + } + break + case 'pri1r2r': + if (configuration == 'Checked' || configuration == 'Release') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} R2R pri1 Build & Test", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + } + break + case 'gcstress15_pri1r2r': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} GCStress 15 R2R pri1 Build & Test", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + } + break + case 'r2r_jitstress1': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} jitstress1 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + } + break + case 'r2r_jitstress2': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} jitstress2 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + } + break + case 'r2r_jitstressregs1': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} jitstressregs1 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + } + break + case 'r2r_jitstressregs2': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} jitstressregs2 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + } + break + case 'r2r_jitstressregs3': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} jitstressregs3 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + } + break + case 'r2r_jitstressregs4': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} jitstressregs4 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + } + break + case 'r2r_jitstressregs8': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} jitstressregs8 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + } + break + case 'r2r_jitstressregsx10': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} jitstressregsx10 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + } + break + case 'r2r_jitstressregsx80': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} jitstressregsx80 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + } + break + case 'r2r_jitminopts': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} JITMinOpts R2R Build & Test", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + } + break + case 'r2r_jitforcerelocs': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} ForceRelocs R2R Build & Test", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + } + break + case 'longgc': + if (configuration == 'Release') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Long-Running GC Build & Test", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + } + break + case 'gcsimulator': + if (configuration == 'Release') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} GC Simulator", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + } + break + case 'standalone_gc': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Standalone GC", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + } + break + case 'minopts': + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - MinOpts)", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + break + case 'forcerelocs': + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - ForceRelocs)", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + break + case 'jitstress1': + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - JitStress=1)", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + break + case 'jitstress2': + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - JitStress=2)", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + break + case 'jitstressregs1': + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - JitStressRegs=1)", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + break + case 'jitstressregs2': + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - JitStressRegs=2)", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + break + case 'jitstressregs3': + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - JitStressRegs=3)", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + break + case 'jitstressregs4': + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - JitStressRegs=4)", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + break + case 'jitstressregs8': + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - JitStressRegs=8)", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + break + case 'jitstressregs0x10': + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - JitStressRegs=0x10)", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + break + case 'jitstressregs0x80': + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - JitStressRegs=0x80)", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + break + case 'jitstress2_jitstressregs1': + case 'jitstress2_jitstressregs2': + case 'jitstress2_jitstressregs3': + case 'jitstress2_jitstressregs4': + case 'jitstress2_jitstressregs8': + case 'jitstress2_jitstressregs0x10': + case 'jitstress2_jitstressregs0x80': + case 'gcstress0x3': + case 'gcstress0xc': + case 'zapdisable': + case 'heapverify1': + case 'gcstress0xc_zapdisable': + case 'gcstress0xc_zapdisable_jitstress2': + case 'gcstress0xc_zapdisable_heapverify1': + case 'gcstress0xc_jitstress1': + case 'gcstress0xc_jitstress2': + case 'gcstress0xc_minopts_heapverify1': + def displayStr = getStressModeDisplayName(scenario) + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} Build and Test (Jit - ${displayStr})", + "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") + break + default: + println("Unknown scenario: ${os} ${architecture} ${scenario}"); + assert false + break + } + break + // editor brace matching: } + case 'x86compatjit': // editor brace matching: { + assert (os == 'Windows_NT') + def arch = 'x86' + def jit = 'compatjit' + switch (scenario) { + case 'default': + if (configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Build and Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}.*") } break case 'pri1': - // Default trigger if (configuration == 'Release') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Priority 1 Build and Test") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Priority 1 Build and Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+Priority 1 Build and Test.*") } break case 'ilrt': if (configuration == 'Release') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} IL RoundTrip Build and Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} IL RoundTrip Build and Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } break case 'r2r': if (configuration == 'Checked' || configuration == 'Release') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} R2R pri0 Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} R2R pri0 Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } break case 'pri1r2r': if (configuration == 'Checked' || configuration == 'Release') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} R2R pri1 Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} R2R pri1 Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } break case 'gcstress15_pri1r2r': if (configuration == 'Release' || configuration == 'Checked') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} GCStress 15 R2R pri1 Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} GCStress 15 R2R pri1 Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } break case 'r2r_jitstress1': if (configuration == 'Release' || configuration == 'Checked') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstress1 R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstress1 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } break case 'r2r_jitstress2': if (configuration == 'Release' || configuration == 'Checked') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstress2 R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstress2 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } break case 'r2r_jitstressregs1': if (configuration == 'Release' || configuration == 'Checked') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregs1 R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregs1 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } break case 'r2r_jitstressregs2': if (configuration == 'Release' || configuration == 'Checked') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregs2 R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregs2 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } break case 'r2r_jitstressregs3': if (configuration == 'Release' || configuration == 'Checked') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregs3 R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregs3 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } break case 'r2r_jitstressregs4': if (configuration == 'Release' || configuration == 'Checked') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregs4 R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregs4 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } break case 'r2r_jitstressregs8': if (configuration == 'Release' || configuration == 'Checked') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregs8 R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregs8 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } break case 'r2r_jitstressregsx10': if (configuration == 'Release' || configuration == 'Checked') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregsx10 R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregsx10 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } break case 'r2r_jitstressregsx80': if (configuration == 'Release' || configuration == 'Checked') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregsx80 R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregsx80 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } break case 'r2r_jitminopts': if (configuration == 'Release' || configuration == 'Checked') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} JITMinOpts R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} JITMinOpts R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } break case 'r2r_jitforcerelocs': if (configuration == 'Release' || configuration == 'Checked') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} ForceRelocs R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} ForceRelocs R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } break case 'longgc': if (configuration == 'Release') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Long-Running GC Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Long-Running GC Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } break case 'gcsimulator': if (configuration == 'Release') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} GC Simulator", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} GC Simulator", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } break case 'minopts': - assert (os == 'Windows_NT') Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Build and Test (Jit - MinOpts)", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") break case 'forcerelocs': - assert (os == 'Windows_NT') Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Build and Test (Jit - ForceRelocs)", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") break case 'jitstress1': - assert (os == 'Windows_NT') Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Build and Test (Jit - JitStress=1)", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") break case 'jitstress2': - assert (os == 'Windows_NT') Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Build and Test (Jit - JitStress=2)", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") break case 'jitstressregs1': - assert (os == 'Windows_NT') Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Build and Test (Jit - JitStressRegs=1)", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") break case 'jitstressregs2': - assert (os == 'Windows_NT') Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Build and Test (Jit - JitStressRegs=2)", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") break case 'jitstressregs3': - assert (os == 'Windows_NT') Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Build and Test (Jit - JitStressRegs=3)", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") break case 'jitstressregs4': - assert (os == 'Windows_NT') Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Build and Test (Jit - JitStressRegs=4)", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") break case 'jitstressregs8': - assert (os == 'Windows_NT') Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Build and Test (Jit - JitStressRegs=8)", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") break case 'jitstressregs0x10': - assert (os == 'Windows_NT') Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Build and Test (Jit - JitStressRegs=0x10)", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") break case 'jitstressregs0x80': - assert (os == 'Windows_NT') Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Build and Test (Jit - JitStressRegs=0x80)", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") break @@ -1303,150 +1599,138 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os, case 'gcstress0xc_jitstress2': case 'gcstress0xc_minopts_heapverify1': def displayStr = getStressModeDisplayName(scenario) - assert (os == 'Windows_NT') Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Build and Test (Jit - ${displayStr})", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") break default: - println("Unknown scenario: ${arch} ${jit} ${scenario}"); + println("Unknown scenario: ${os} ${arch} ${jit} ${scenario}"); assert false break } break - case 'x86lb': - assert (scenario == 'default' || scenario == 'r2r' || scenario == 'pri1r2r' || scenario == 'gcstress15_pri1r2r' || scenario == 'longgc' || scenario == 'gcsimulator' || + // editor brace matching: } + case 'x86lb': // editor brace matching: { + assert (os == 'Windows_NT') + assert (scenario == 'default' || + scenario == 'r2r' || + scenario == 'pri1r2r' || + scenario == 'gcstress15_pri1r2r' || + scenario == 'longgc' || + scenario == 'gcsimulator' || Constants.r2rJitStressScenarios.indexOf(scenario) != -1) - // For windows, x86 runs by default + def arch = 'x86' - def jit = 'ryujit' - if (architecture == 'x86lb') { - jit = 'legacy_backend' - } - - if (scenario == 'default') { - if (os == 'Windows_NT') { + def jit = 'legacy_backend' + switch (scenario) { + case 'default': if (configuration == 'Checked') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Build and Test") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Build and Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}.*") } - } - else { - // default trigger - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Build", "(?i).*test\\W+${arch}\\W+${osGroup}.\\W+${jit}.*") - } - } - else if (scenario == 'r2r') { - if (os == 'Windows_NT') { + break + case 'r2r': if (configuration == 'Release') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} R2R pri0 Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} R2R pri0 Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } - } - } - else if (scenario == 'pri1r2r') { - if (os == 'Windows_NT') { + break + case 'pri1r2r': if (configuration == 'Release') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} R2R pri1 Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} R2R pri1 Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } - } - } - else if (scenario == 'gcstress15_pri1r2r'){ - if (os == 'Windows_NT'){ - if (configuration == 'Release'){ - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} GCStress 15 R2R pri1 Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + break + case 'gcstress15_pri1r2r': + if (configuration == 'Release') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} GCStress 15 R2R pri1 Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } - } - } - else if (scenario == 'r2r_jitstress1'){ - if (configuration == 'Release' || configuration == 'Checked') { - if (os == 'Windows_NT'){ - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstress1 R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + break + case 'r2r_jitstress1': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstress1 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } - } - } - else if (scenario == 'r2r_jitstress2'){ - if (configuration == 'Release' || configuration == 'Checked') { - if (os == 'Windows_NT'){ - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstress2 R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + break + case 'r2r_jitstress2': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstress2 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } - } - } - else if (scenario == 'r2r_jitstressregs1'){ - if (configuration == 'Release' || configuration == 'Checked') { - if (os == 'Windows_NT'){ - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregs1 R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + break + case 'r2r_jitstressregs1': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregs1 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } - } - } - else if (scenario == 'r2r_jitstressregs2'){ - if (configuration == 'Release' || configuration == 'Checked') { - if (os == 'Windows_NT'){ - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregs2 R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + break + case 'r2r_jitstressregs2': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregs2 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } - } - } - else if (scenario == 'r2r_jitstressregs3'){ - if (configuration == 'Release' || configuration == 'Checked') { - if (os == 'Windows_NT'){ - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregs3 R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + break + case 'r2r_jitstressregs3': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregs3 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } - } - } - else if (scenario == 'r2r_jitstressregs4'){ - if (configuration == 'Release' || configuration == 'Checked') { - if (os == 'Windows_NT'){ - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregs4 R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + break + case 'r2r_jitstressregs4': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregs4 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } - } - } - else if (scenario == 'r2r_jitstressregs8'){ - if (configuration == 'Release' || configuration == 'Checked') { - if (os == 'Windows_NT'){ - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregs8 R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + break + case 'r2r_jitstressregs8': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregs8 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } - } - } - else if (scenario == 'r2r_jitstressregsx10'){ - if (configuration == 'Release' || configuration == 'Checked') { - if (os == 'Windows_NT'){ - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregsx10 R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + break + case 'r2r_jitstressregsx10': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregsx10 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } - } - } - else if (scenario == 'r2r_jitstressregsx80'){ - if (configuration == 'Release' || configuration == 'Checked') { - if (os == 'Windows_NT'){ - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregsx80 R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + break + case 'r2r_jitstressregsx80': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitstressregsx80 R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } - } - } - else if (scenario == 'r2r_jitminopts'){ - if (configuration == 'Release' || configuration == 'Checked') { - if (os == 'Windows_NT'){ - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitminopts R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + break + case 'r2r_jitminopts': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitminopts R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } - } - } - else if (scenario == 'r2r_jitforcerelocs'){ - if (configuration == 'Release' || configuration == 'Checked') { - if (os == 'Windows_NT'){ - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitforcerelocs R2R Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + break + case 'r2r_jitforcerelocs': + if (configuration == 'Release' || configuration == 'Checked') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} jitforcerelocs R2R Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } - } - } - else if (scenario == 'longgc') { - if (os == 'Windows_NT'){ - if (configuration == 'Release'){ - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Long-Running GC Build & Test", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + break + case 'longgc': + if (configuration == 'Release') { + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} Long-Running GC Build & Test", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } - } - } - else if (scenario == 'gcsimulator') { - if (os == 'Windows_NT') { + break + case 'gcsimulator': if (configuration == 'Release') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} GC Simulator", "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${arch} ${jit} ${configuration} GC Simulator", + "(?i).*test\\W+${os}\\W+${arch}\\W+${jit}\\W+${configuration}\\W+${scenario}.*") } - } + break + default: + println("Unknown scenario: ${os} ${arch} ${jit} ${scenario}"); + assert false + break } break + // editor brace matching: } default: println("Unknown architecture: ${architecture}"); assert false @@ -1470,6 +1754,14 @@ combinedScenarios.each { scenario -> os = 'Windows_NT' } + // WinArm32 is only built for Debug and Release + if (os == 'Windows_NT' && architecture == 'arm') + { + if (configuration == 'Checked') + { + return + } + } // If the OS is LinuxARMEmulator and arch is arm, set the isLinuxEmulatorBuild // flag to true and reset the os to Ubuntu // The isLinuxEmulatorBuild flag will be used at a later time to execute the right @@ -1497,12 +1789,12 @@ combinedScenarios.each { scenario -> } break case 'arm': - // Only Ubuntu cross implemented - if (os != 'Ubuntu') { + if ((os != 'Ubuntu') && (os != 'Windows_NT')) { return } break - case 'x86ryujit': + case 'x86': + case 'x86compatjit': case 'x86lb': // Skip non-windows if (os != 'Windows_NT') { @@ -1517,6 +1809,7 @@ combinedScenarios.each { scenario -> assert false break } + // Skip scenarios (blanket skipping for jit stress modes, which are good most everywhere // with checked builds def enableCorefxTesting = false @@ -1529,7 +1822,7 @@ combinedScenarios.each { scenario -> // Since these are just execution time differences, // skip platforms that don't execute the tests here (Windows_NT only) - def isEnabledOS = os == 'Windows_NT' || (os == 'Ubuntu' && enableCorefxTesting) + def isEnabledOS = (os == 'Windows_NT') || (os == 'Ubuntu' && enableCorefxTesting) if (!isEnabledOS || isBuildOnly) { return } @@ -1543,17 +1836,22 @@ combinedScenarios.each { scenario -> case 'x64': // Everything implemented break - case 'x86ryujit': + case 'x86': if (enableCorefxTesting) { return } break + case 'x86compatjit': + case 'x86lb': + // No stress modes for compatjit.dll, legacyjit.dll. + // (There's no technical reason we couldn't allow these.) + return default: return } } else { - // If this is a r2r jitstress, jitstressregs, jitminopts or forcerelocs scenario + // If this is a r2r jitstress, jitstressregs, jitminopts, or forcerelocs scenario // and configuration is not Checked, bail out. if (configuration != 'Checked' && Constants.r2rJitStressScenarios.indexOf(scenario) != -1) { return; @@ -1587,6 +1885,17 @@ combinedScenarios.each { scenario -> return } break + case 'jitdiff': + if (os != 'Windows_NT' && os != 'Ubuntu' && os != 'OSX') { + return + } + if (architecture != 'x64') { + return + } + if (configuration != 'Checked') { + return + } + break case 'r2r': // The r2r build isn't necessary except for Windows_NT. Non-Windows NT uses // the default scenario build @@ -1642,6 +1951,19 @@ combinedScenarios.each { scenario -> return } break + case 'standalone_gc': + if (os != 'Windows_NT') { + return + } + + if (architecture != 'x64') { + return + } + + if (configuration != 'Release' && configuration != 'Checked') { + return + } + break // We need Windows x64 Release bits for the code coverage build case 'coverage': if (os != 'Windows_NT') { @@ -1698,21 +2020,29 @@ combinedScenarios.each { scenario -> // Calculate the build steps, archival, and xunit results switch (os) { - case 'Windows_NT': + case 'Windows_NT': // editor brace matching: { switch (architecture) { case 'x64': - case 'x86ryujit': + case 'x86': + case 'x86compatjit': case 'x86lb': def arch = architecture - if (architecture == 'x86ryujit' || architecture == 'x86lb') { + def buildOpts = '' + if (architecture == 'x86compatjit') { arch = 'x86' + buildOpts = 'compatjitcrossgen' + } + else if (architecture == 'x86lb') { + arch = 'x86' + buildOpts = 'legacyjitcrossgen' } if (Constants.jitStressModeScenarios.containsKey(scenario) || scenario == 'default' || scenario == 'r2r' || + scenario == 'jitdiff' || Constants.r2rJitStressScenarios.indexOf(scenario) != -1) { - buildOpts = enableCorefxTesting ? 'skiptests' : '' + buildOpts += enableCorefxTesting ? ' skiptests' : '' buildCommands += "set __TestIntermediateDir=int&&build.cmd ${lowerConfiguration} ${arch} ${buildOpts}" } @@ -1723,19 +2053,23 @@ combinedScenarios.each { scenario -> // 35 characters long. else if (scenario == 'pri1' || scenario == 'pri1r2r' || scenario == 'gcstress15_pri1r2r'|| scenario == 'coverage') { - buildCommands += "set __TestIntermediateDir=int&&build.cmd ${lowerConfiguration} ${arch} -priority=1" + buildCommands += "set __TestIntermediateDir=int&&build.cmd ${lowerConfiguration} ${arch} ${buildOpts} -priority=1" } else if (scenario == 'ilrt') { // First do the build with skiptests and then build the tests with ilasm roundtrip - buildCommands += "build.cmd ${lowerConfiguration} ${arch} skiptests" + buildCommands += "build.cmd ${lowerConfiguration} ${arch} ${buildOpts} skiptests" buildCommands += "set __TestIntermediateDir=int&&build-test.cmd ${lowerConfiguration} ${arch} -ilasmroundtrip" } else if (isLongGc(scenario)) { - buildCommands += "build.cmd ${lowerConfiguration} ${arch} skiptests" + buildCommands += "build.cmd ${lowerConfiguration} ${arch} ${buildOpts} skiptests" buildCommands += "set __TestIntermediateDir=int&&build-test.cmd ${lowerConfiguration} ${arch}" } + else if (scenario == 'standalone_gc') { + buildCommands += "build.cmd ${lowerConfiguration} ${arch} ${buildOpts} buildstandalonegc" + } else if (scenario == 'formatting') { buildCommands += "python -u tests\\scripts\\format.py -c %WORKSPACE% -o Windows_NT -a ${arch}" + Utilities.addArchival(newJob, "format.patch", "", true, false) break } else { @@ -1754,6 +2088,7 @@ combinedScenarios.each { scenario -> def runjitstressregsStr = '' def runjitmioptsStr = '' def runjitforcerelocsStr = '' + def runjitdisasmStr = '' def gcstressStr = '' def runtestArguments = '' def gcTestArguments = '' @@ -1804,11 +2139,17 @@ combinedScenarios.each { scenario -> gcstressStr = 'gcstresslevel 0xF' } + if (scenario == 'jitdiff') + { + runjitdisasmStr = 'jitdisasm crossgen' + } + if (isLongGc(scenario)) { gcTestArguments = "${scenario} sequential" } - runtestArguments = "${lowerConfiguration} ${arch} ${gcstressStr} ${crossgenStr} ${runcrossgentestsStr} ${runjitstressStr} ${runjitstressregsStr} ${runjitmioptsStr} ${runjitforcerelocsStr} ${gcTestArguments}" + runtestArguments = "${lowerConfiguration} ${arch} ${gcstressStr} ${crossgenStr} ${runcrossgentestsStr} ${runjitstressStr} ${runjitstressregsStr} ${runjitmioptsStr} ${runjitforcerelocsStr} ${runjitdisasmStr} ${gcTestArguments}" + if (Constants.jitStressModeScenarios.containsKey(scenario)) { if (enableCorefxTesting) { // Sync to corefx repo @@ -1825,29 +2166,21 @@ combinedScenarios.each { scenario -> } else { def stepScriptLocation = "%WORKSPACE%\\bin\\tests\\SetStressModes.bat" - - if (architecture == 'x86ryujit'){ - def x86Vars = ['COMPLUS_AltJit' : '*', 'COMPLUS_AltJitName' : 'protojit.dll', 'COMPLUS_NoGuiOnAssert' : '1'] - buildCommands += genStressModeScriptStep(os, scenario, Constants.jitStressModeScenarios[scenario] + x86Vars, stepScriptLocation) - } - else { - buildCommands += genStressModeScriptStep(os, scenario, Constants.jitStressModeScenarios[scenario], stepScriptLocation) - } - + buildCommands += genStressModeScriptStep(os, scenario, Constants.jitStressModeScenarios[scenario], stepScriptLocation) // Run tests with the buildCommands += "tests\\runtest.cmd ${runtestArguments} TestEnv ${stepScriptLocation}" } } - else if (architecture == 'x64') { + else if (architecture == 'x64' || architecture == 'x86') { buildCommands += "tests\\runtest.cmd ${runtestArguments}" } - else if (architecture == 'x86ryujit') { - def testEnvLocation = "%WORKSPACE%\\tests\\x86\\ryujit_x86_testenv.cmd" - - buildCommands += "tests\\runtest.cmd ${runtestArguments} TestEnv ${testEnvLocation}" + else if (architecture == 'x86compatjit') { + def testEnvLocation = "%WORKSPACE%\\tests\\x86\\compatjit_x86_testenv.cmd" + buildCommands += "tests\\runtest.cmd ${runtestArguments} Exclude0 x86_legacy_backend_issues.targets TestEnv ${testEnvLocation}" } else if (architecture == 'x86lb') { - buildCommands += "tests\\runtest.cmd ${runtestArguments} Exclude0 x86_legacy_backend_issues.targets" + def testEnvLocation = "%WORKSPACE%\\tests\\x86\\legacyjit_x86_testenv.cmd" + buildCommands += "tests\\runtest.cmd ${runtestArguments} Exclude0 x86_legacy_backend_issues.targets TestEnv ${testEnvLocation}" } } @@ -1857,16 +2190,24 @@ combinedScenarios.each { scenario -> buildCommands += "build.cmd ${lowerConfiguration} ${arch} linuxmscorlib" buildCommands += "build.cmd ${lowerConfiguration} ${arch} freebsdmscorlib" buildCommands += "build.cmd ${lowerConfiguration} ${arch} osxmscorlib" - + // Zip up the tests directory so that we don't use so much space/time copying // 10s of thousands of files around. buildCommands += "powershell -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('.\\bin\\tests\\${osGroup}.${arch}.${configuration}', '.\\bin\\tests\\tests.zip')\""; - - if (!Constants.jitStressModeScenarios.containsKey(scenario)) { + + if (!Constants.jitStressModeScenarios.containsKey(scenario) && scenario != 'jitdiff') { // For windows, pull full test results and test drops for x86/x64. // No need to pull for stress mode scenarios (downstream builds use the default scenario) Utilities.addArchival(newJob, "bin/Product/**,bin/tests/tests.zip") } + + if (scenario == 'jitdiff') { + // retrive jit-dasm output for base commit, and run jit-diff + if (!isBuildOnly) { + // if this is a build only job, we want to keep the default (build) artifacts for the flow job + Utilities.addArchival(newJob, "bin/tests/${osGroup}.${arch}.${configuration}/dasm/**") + } + } if (!isBuildOnly) { if (architecture == 'x64' || !isPR) { @@ -1889,6 +2230,22 @@ combinedScenarios.each { scenario -> } break + case 'arm': + assert (scenario == 'default') + + // Set time out + setTestJobTimeOut(newJob, scenario) + + if ( lowerConfiguration == "debug" ) { + // For Debug builds, we will do a P1 test build + buildCommands += "set __TestIntermediateDir=int&&build.cmd ${lowerConfiguration} ${architecture} -priority=1" + } + else { + buildCommands += "set __TestIntermediateDir=int&&build.cmd ${lowerConfiguration} ${architecture}" + } + // Add archival. + Utilities.addArchival(newJob, "bin/Product/**") + break case 'arm64': assert (scenario == 'default') || (scenario == 'pri1r2r') || (scenario == 'gcstress0x3') || (scenario == 'gcstress0xc') // Set time out @@ -1901,8 +2258,8 @@ combinedScenarios.each { scenario -> else { buildCommands += "set __TestIntermediateDir=int&&build.cmd skiptests ${lowerConfiguration} ${architecture} toolset_dir C:\\ats2" // Test build and run are launched together. - buildCommands += "Z:\\arm64\\common\\scripts\\arm64PostLauncher.cmd %WORKSPACE% ${architecture} ${lowerConfiguration} ${scenario}" - Utilities.addXUnitDotNETResults(newJob, 'bin/tests/testResults.xml') + buildCommands += "python tests\\scripts\\arm64_post_build.py -repo_root %WORKSPACE% -arch ${architecture} -build_type ${lowerConfiguration} -scenario ${scenario} -key_location C:\\tools\\key.txt" + //Utilities.addXUnitDotNETResults(newJob, 'bin/tests/testResults.xml') } // Add archival. @@ -1914,8 +2271,10 @@ combinedScenarios.each { scenario -> break } break + // editor brace matching: } case 'Ubuntu': case 'Ubuntu16.04': + case 'Ubuntu16.10': case 'Debian8.4': case 'OSX': case 'FreeBSD': @@ -1923,18 +2282,20 @@ combinedScenarios.each { scenario -> case 'RHEL7.2': case 'OpenSUSE13.2': case 'OpenSUSE42.1': - case 'Fedora23': + case 'Fedora23': // editor brace matching: { switch (architecture) { case 'x64': - case 'x86ryujit': + case 'x86': + case 'x86compatjit': case 'x86lb': def arch = architecture - if (architecture == 'x86ryujit' || architecture == 'x86lb') { + if (architecture == 'x86compatjit' || architecture == 'x86lb') { arch = 'x86' } if (scenario == 'formatting') { buildCommands += "python tests/scripts/format.py -c \${WORKSPACE} -o Linux -a ${arch}" + Utilities.addArchival(newJob, "format.patch", "", true, false) break } @@ -2043,12 +2404,13 @@ combinedScenarios.each { scenario -> break } break + // editor brace matching: } default: println("Unknown os: ${os}"); assert false break - } - + } // os + newJob.with { steps { if (os == 'Windows_NT') { @@ -2078,7 +2440,7 @@ combinedScenarios.each { scenario -> latestSuccessful(true) } } - copyArtifacts("${corefxFolder}/linuxarmemulator_cross_${lowerConfiguration}") { + copyArtifacts("${corefxFolder}/linuxarmemulator_softfp_cross_${lowerConfiguration}") { includePatterns('bin/build.tar.gz') buildSelector { latestSuccessful(true) @@ -2091,7 +2453,7 @@ combinedScenarios.each { scenario -> } } } - } + } // newJob.with } // os } // configuration @@ -2160,6 +2522,10 @@ combinedScenarios.each { scenario -> return } break + case 'jitdiff': + if (configuration != 'Checked') { + return; + } case 'r2r': //Skip configs that aren't Checked or Release (so just Debug, for now) if (configuration != 'Checked' && configuration != 'Release') { @@ -2196,6 +2562,10 @@ combinedScenarios.each { scenario -> return } break + case 'standalone_gc': + if (configuration != 'Release' && configuration != 'Checked') { + return + } case 'coverage': //We only want Ubuntu Release for coverage if (os != 'Ubuntu') { @@ -2273,6 +2643,7 @@ combinedScenarios.each { scenario -> def runjitstressregsStr = '' def runjitmioptsStr = '' def runjitforcerelocsStr = '' + def runjitdisasmStr = '' def gcstressStr = '' if (scenario == 'r2r' || @@ -2321,6 +2692,11 @@ combinedScenarios.each { scenario -> gcstressStr = '--gcstresslevel=0xF' } + if (scenario == 'jitdiff') + { + runjitdisasmStr = '--jitdisasm --crossgen' + } + if (isLongGc(scenario)) { // Long GC tests behave very poorly when they are not // the only test running (many of them allocate until OOM). @@ -2486,7 +2862,7 @@ combinedScenarios.each { scenario -> --coreFxBinDir=\"\${WORKSPACE}/bin/${osGroup}.AnyCPU.Release;\${WORKSPACE}/bin/Unix.AnyCPU.Release;\${WORKSPACE}/bin/AnyOS.AnyCPU.Release\" \\ --coreFxNativeBinDir=\"\${WORKSPACE}/bin/${osGroup}.${architecture}.Release\" \\ --limitedDumpGeneration \\ - ${testEnvOpt} ${serverGCString} ${gcstressStr} ${crossgenStr} ${runcrossgentestsStr} ${runjitstressStr} ${runjitstressregsStr} ${runjitmioptsStr} ${runjitforcerelocsStr} ${sequentialString} ${playlistString}""") + ${testEnvOpt} ${serverGCString} ${gcstressStr} ${crossgenStr} ${runcrossgentestsStr} ${runjitstressStr} ${runjitstressregsStr} ${runjitmioptsStr} ${runjitforcerelocsStr} ${runjitdisasmStr} ${sequentialString} ${playlistString}""") } } } @@ -2498,6 +2874,10 @@ combinedScenarios.each { scenario -> // addEmailPublisher(newJob, 'clrcoverage@microsoft.com') } + if (scenario == 'jitdiff') { + Utilities.addArchival(newJob, "bin/tests/${osGroup}.${architecture}.${configuration}/dasm/**") + } + // Experimental: If on Ubuntu 14.04, then attempt to pull in crash dump links if (os in ['Ubuntu']) { SummaryBuilder summaries = new SummaryBuilder() @@ -2566,4 +2946,4 @@ JobReport.Report.generateJobReport(out) // Make the call to generate the help job Utilities.createHelperJob(this, project, branch, "Welcome to the ${project} Repository", // This is prepended to the help message - "Have a nice day!") // This is appended to the help message. You might put known issues here. \ No newline at end of file + "Have a nice day!") // This is appended to the help message. You might put known issues here. diff --git a/perf.groovy b/perf.groovy index a95b681..d7eb783 100644 --- a/perf.groovy +++ b/perf.groovy @@ -4,10 +4,11 @@ import jobs.generation.*; def project = GithubProject def branch = GithubBranchName -def projectFolder = Utilities.getFolderName(project) + '/' + Utilities.getFolderName(branch) +def projectName = Utilities.getFolderName(project) +def projectFolder = projectName + '/' + Utilities.getFolderName(branch) def static getOSGroup(def os) { - def osGroupMap = ['Ubuntu':'Linux', + def osGroupMap = ['Ubuntu14.04':'Linux', 'RHEL7.2': 'Linux', 'Ubuntu16.04': 'Linux', 'Debian8.4':'Linux', @@ -19,7 +20,7 @@ def static getOSGroup(def os) { 'OpenSUSE13.2': 'Linux', 'OpenSUSE42.1': 'Linux', 'LinuxARMEmulator': 'Linux'] - def osGroup = osGroupMap.get(os, null) + def osGroup = osGroupMap.get(os, null) assert osGroup != null : "Could not find os group for ${os}" return osGroupMap[os] } @@ -27,9 +28,6 @@ def static getOSGroup(def os) { [true, false].each { isPR -> ['Windows_NT'].each { os -> ['x64'].each { architecture -> - def configuration = 'Release' - def runType = isPR ? 'private' : 'rolling' - def benchViewName = isPR ? 'coreclr private %ghprbPullTitle%' : 'coreclr rolling %GIT_BRANCH_WITHOUT_ORIGIN% %GIT_COMMIT%' def newJob = job(Utilities.getFullJobName(project, "perf_perflab_${os}", isPR)) { // Set the label. label('windows_clr_perf') @@ -39,20 +37,32 @@ def static getOSGroup(def os) { } } + if (isPR) + { + parameters + { + stringParam('BenchviewCommitName', '%ghprbPullTitle%', 'The name that you will be used to build the full title of a run in Benchview. The final name will be of the form private BenchviewCommitName') + } + } + def configuration = 'Release' + def runType = isPR ? 'private' : 'rolling' + def benchViewName = isPR ? 'coreclr private %BenchviewCommitName%' : 'coreclr rolling %GIT_BRANCH_WITHOUT_ORIGIN% %GIT_COMMIT%' + steps { // Batch - - batchFile("C:\\Tools\\nuget.exe install Microsoft.BenchView.JSONFormat -Source http://benchviewtestfeed.azurewebsites.net/nuget -OutputDirectory C:\\tools -Prerelease -ExcludeVersion") + + batchFile("if exist \"%WORKSPACE%\\Microsoft.BenchView.JSONFormat\" rmdir /s /q \"%WORKSPACE%\\Microsoft.BenchView.JSONFormat\"") + batchFile("C:\\Tools\\nuget.exe install Microsoft.BenchView.JSONFormat -Source http://benchviewtestfeed.azurewebsites.net/nuget -OutputDirectory \"%WORKSPACE%\" -Prerelease -ExcludeVersion") //Do this here to remove the origin but at the front of the branch name as this is a problem for BenchView //we have to do it all as one statement because cmd is called each time and we lose the set environment variable batchFile("if [%GIT_BRANCH:~0,7%] == [origin/] (set GIT_BRANCH_WITHOUT_ORIGIN=%GIT_BRANCH:origin/=%) else (set GIT_BRANCH_WITHOUT_ORIGIN=%GIT_BRANCH%)\n" + - "py C:\\tools\\Microsoft.BenchView.JSONFormat\\tools\\submission-metadata.py --name " + "\"" + benchViewName + "\"" + " --user " + "\"dotnet-bot@microsoft.com\"\n" + - "py C:\\tools\\Microsoft.BenchView.JSONFormat\\tools\\build.py git --branch %GIT_BRANCH_WITHOUT_ORIGIN% --type " + runType) - batchFile("py C:\\tools\\Microsoft.BenchView.JSONFormat\\tools\\machinedata.py") + "py \"%WORKSPACE%\\Microsoft.BenchView.JSONFormat\\tools\\submission-metadata.py\" --name " + "\"" + benchViewName + "\"" + " --user " + "\"dotnet-bot@microsoft.com\"\n" + + "py \"%WORKSPACE%\\Microsoft.BenchView.JSONFormat\\tools\\build.py\" git --branch %GIT_BRANCH_WITHOUT_ORIGIN% --type " + runType) + batchFile("py \"%WORKSPACE%\\Microsoft.BenchView.JSONFormat\\tools\\machinedata.py\"") batchFile("set __TestIntermediateDir=int&&build.cmd release ${architecture}") batchFile("tests\\runtest.cmd release ${architecture} GenerateLayoutOnly") - batchFile("tests\\scripts\\run-xunit-perf.cmd -arch ${architecture} -configuration ${configuration} -testBinLoc bin\\tests\\Windows_NT.${architecture}.Release\\performance\\perflab\\Perflab -library -uploadToBenchview C:\\Tools\\Microsoft.Benchview.JSONFormat\\tools -runtype " + runType) - batchFile("tests\\scripts\\run-xunit-perf.cmd -arch ${architecture} -configuration ${configuration} -testBinLoc bin\\tests\\Windows_NT.${architecture}.Release\\Jit\\Performance\\CodeQuality -uploadToBenchview C:\\Tools\\Microsoft.Benchview.JSONFormat\\tools -runtype " + runType) + batchFile("tests\\scripts\\run-xunit-perf.cmd -arch ${architecture} -configuration ${configuration} -testBinLoc bin\\tests\\Windows_NT.${architecture}.Release\\performance\\perflab\\Perflab -library -uploadToBenchview \"%WORKSPACE%\\Microsoft.Benchview.JSONFormat\\tools\" -runtype " + runType) + batchFile("tests\\scripts\\run-xunit-perf.cmd -arch ${architecture} -configuration ${configuration} -testBinLoc bin\\tests\\Windows_NT.${architecture}.Release\\Jit\\Performance\\CodeQuality -uploadToBenchview \"%WORKSPACE%\\Microsoft.Benchview.JSONFormat\\tools\" -runtype " + runType) } } @@ -63,7 +73,7 @@ def static getOSGroup(def os) { Utilities.addArchival(newJob, archiveSettings) Utilities.standardJobSetup(newJob, project, isPR, "*/${branch}") - + if (isPR) { TriggerBuilder builder = TriggerBuilder.triggerOnPullRequest() builder.setGithubContext("${os} CoreCLR Perf Tests") @@ -83,72 +93,67 @@ def static getOSGroup(def os) { // Create the Linux/OSX/CentOS coreclr test leg for debug and release and each scenario [true, false].each { isPR -> - ['Ubuntu'].each { os -> - def osGroup = getOSGroup(os) - def architecture = 'x64' - def configuration = 'Checked' - def newJob = job(Utilities.getFullJobName(project, "perf_${osGroup}", isPR)) { - parameters { - stringParam('CORECLR_WINDOWS_BUILD', '', 'Build number to copy CoreCLR windows test binaries from') - stringParam('CORECLR_BUILD', '', "Build number to copy CoreCLR ${osGroup} binaries from") - } - + ['Ubuntu14.04'].each { os -> + def newJob = job(Utilities.getFullJobName(project, "perf_${os}", isPR)) { + + label('linux_clr_perf') + wrappers { + credentialsBinding { + string('BV_UPLOAD_SAS_TOKEN', 'CoreCLR Perf BenchView Sas') + } + } + + if (isPR) + { + parameters + { + stringParam('BenchviewCommitName', '\$ghprbPullTitle', 'The name that you will be used to build the full title of a run in Benchview. The final name will be of the form private BenchviewCommitName') + } + } + def osGroup = getOSGroup(os) + def architecture = 'x64' + def configuration = 'Release' + def runType = isPR ? 'private' : 'rolling' + def benchViewName = isPR ? 'coreclr private \$BenchviewCommitName' : 'coreclr rolling \$GIT_BRANCH_WITHOUT_ORIGIN \$GIT_COMMIT' + steps { - // Set up the copies - // Coreclr build containing the tests and mscorlib - copyArtifacts("dotnet_coreclr/master/x64_checked_windows_nt_pri1_bld") { - excludePatterns('**/testResults.xml', '**/*.ni.dll') - buildSelector { - buildNumber('${CORECLR_WINDOWS_BUILD}') - } - } - - // Coreclr build we are trying to test - copyArtifacts("dotnet_coreclr/master/checked_ubuntu") { - excludePatterns('**/testResults.xml', '**/*.ni.dll') - buildSelector { - buildNumber('${CORECLR_BUILD}') - } - } - - def corefxFolder = Utilities.getFolderName('dotnet/corefx') + '/' + 'master' - - // Corefx components. We now have full stack builds on all distros we test here, so we can copy straight from CoreFX jobs. - def osJobName = (os == 'Ubuntu') ? 'ubuntu14.04' : os.toLowerCase() - copyArtifacts("${corefxFolder}/${osJobName}_release") { - includePatterns('bin/build.tar.gz') - buildSelector { - latestSuccessful(true) - } - } - - // Unpack the corefx binaries - shell("tar -xf ./bin/build.tar.gz") - - // Unzip the tests first. Exit with 0 - shell("unzip -q -o ./bin/tests/tests.zip -d ./bin/tests/Windows_NT.${architecture}.${configuration} || exit 0") - - // Execute the tests - shell('./init-tools.sh') - - shell("""sudo bash ./tests/scripts/run-xunit-perf.sh \\ + shell("bash ./tests/scripts/perf-prep.sh") + shell("./init-tools.sh") + shell("./build.sh ${architecture} ${configuration}") + shell("GIT_BRANCH_WITHOUT_ORIGIN=\$(echo \$GIT_BRANCH | sed \"s/[^/]*\\/\\(.*\\)/\\1 /\")\n" + + "python3.5 \"\${WORKSPACE}/tests/scripts/Microsoft.BenchView.JSONFormat/tools/submission-metadata.py\" --name " + "\"" + benchViewName + "\"" + " --user " + "\"dotnet-bot@microsoft.com\"\n" + + "python3.5 \"\${WORKSPACE}/tests/scripts/Microsoft.BenchView.JSONFormat/tools/build.py\" git --branch \$GIT_BRANCH_WITHOUT_ORIGIN --type " + runType) + shell("""sudo -E bash ./tests/scripts/run-xunit-perf.sh \\ --testRootDir=\"\${WORKSPACE}/bin/tests/Windows_NT.${architecture}.${configuration}\" \\ --testNativeBinDir=\"\${WORKSPACE}/bin/obj/${osGroup}.${architecture}.${configuration}/tests\" \\ --coreClrBinDir=\"\${WORKSPACE}/bin/Product/${osGroup}.${architecture}.${configuration}\" \\ --mscorlibDir=\"\${WORKSPACE}/bin/Product/${osGroup}.${architecture}.${configuration}\" \\ - --coreFxBinDir=\"\${WORKSPACE}/bin/${osGroup}.AnyCPU.Release;\${WORKSPACE}/bin/Unix.AnyCPU.Release;\${WORKSPACE}/bin/AnyOS.AnyCPU.Release\" \\ - --coreFxNativeBinDir=\"\${WORKSPACE}/bin/${osGroup}.${architecture}.Release\"""") + --coreFxBinDir=\"\${WORKSPACE}/corefx/bin/${osGroup}.AnyCPU.${configuration};\${WORKSPACE}/corefx/bin/Unix.AnyCPU.${configuration};\${WORKSPACE}/corefx/bin/AnyOS.AnyCPU.${configuration}\" \\ + --coreFxNativeBinDir=\"\${WORKSPACE}/corefx/bin/${osGroup}.${architecture}.${configuration}\" \\ + --runType=\"${runType}\" \\ + --benchViewOS=\"${os}\" \\ + --uploadToBenchview""") } } - Utilities.setMachineAffinity(newJob, os, 'latest-or-auto') // Just run against Linux VM's for now. - // Save machinedata.json to /artifact/bin/ Jenkins dir def archiveSettings = new ArchivalSettings() - archiveSettings.addFiles('perf-*.xml') + archiveSettings.addFiles('sandbox/perf-*.xml') + archiveSettings.addFiles('machinedata.json') Utilities.addArchival(newJob, archiveSettings) Utilities.standardJobSetup(newJob, project, isPR, "*/${branch}") + + // For perf, we need to keep the run results longer + newJob.with { + // Enable the log rotator + logRotator { + artifactDaysToKeep(7) + daysToKeep(300) + artifactNumToKeep(25) + numToKeep(1000) + } + } if (isPR) { TriggerBuilder builder = TriggerBuilder.triggerOnPullRequest() builder.setGithubContext("${os} Perf Tests") @@ -163,4 +168,4 @@ def static getOSGroup(def os) { builder.emitTrigger(newJob) } } // os -} // isPR \ No newline at end of file +} // isPR diff --git a/pgosupport.cmake b/pgosupport.cmake index 27fe13d..015eed6 100644 --- a/pgosupport.cmake +++ b/pgosupport.cmake @@ -13,7 +13,7 @@ function(add_pgo TargetName) endif(WIN32) file(TO_NATIVE_PATH - "${CLR_CMAKE_PACKAGES_DIR}/${CLR_CMAKE_OPTDATA_PACKAGEWITHRID}/${CLR_CMAKE_OPTDATA_VERSION}/data/${ProfileFileName}" + "${CLR_CMAKE_PACKAGES_DIR}/Microsoft.DotNet.OptimizationData.Coreclr/${CLR_CMAKE_TARGET_OS}.${CLR_CMAKE_TARGET_ARCH}/${ProfileFileName}" ProfilePath ) @@ -37,18 +37,6 @@ function(add_pgo TargetName) endforeach(ConfigType) endfunction(add_pgo) -set(CLR_CMAKE_OPTDATA_PACKAGEID "optimization.PGO.CoreCLR") -set(CLR_CMAKE_OPTDATA_PACKAGEWITHRID "optimization.${CLR_CMAKE_TARGET_OS}-${CLR_CMAKE_TARGET_ARCH}.PGO.CoreCLR") - -# Parse optdata package version from project.json -file(TO_NATIVE_PATH "${CMAKE_SOURCE_DIR}/extract-from-json.py" ExtractFromJsonScript) -file(TO_NATIVE_PATH "${CMAKE_SOURCE_DIR}/src/.nuget/optdata/project.json" OptDataProjectJsonPath) -execute_process( - COMMAND python "${ExtractFromJsonScript}" -rf "${OptDataProjectJsonPath}" dependencies "${CLR_CMAKE_OPTDATA_PACKAGEID}" - OUTPUT_VARIABLE CLR_CMAKE_OPTDATA_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE -) - if(WIN32) if(CLR_CMAKE_PGO_INSTRUMENT) # Instrumented PGO binaries on Windows introduce an additional runtime dependency, pgort.dll. diff --git a/publish-packages.cmd b/publish-packages.cmd index 5831d29..d23ff23 100644 --- a/publish-packages.cmd +++ b/publish-packages.cmd @@ -1,4 +1,4 @@ -@if "%_echo%" neq "on" echo off +@if not defined _echo @echo off setlocal EnableDelayedExpansion if /I [%1] == [-?] goto Usage @@ -18,6 +18,8 @@ echo -AzureAccount="account name" echo -AzureToken="access token" echo -BuildType="Configuration" echo -BuildArch="Architecture" +echo To specify the name of the container to publish into, use the following property: +echo -Container="container name" echo Architecture can be x64, x86, arm, or arm64 echo Configuration can be Release, Debug, or Checked exit /b \ No newline at end of file diff --git a/publish-packages.sh b/publish-packages.sh index 8170419..d5d4caa 100755 --- a/publish-packages.sh +++ b/publish-packages.sh @@ -8,6 +8,8 @@ usage() echo " -AzureToken=\"access token\"" echo " -BuildType=\"Configuration\"" echo " -BuildArch=\"Architecture\"" + echo "To specify the name of the container to publish into, use the following property:" + echo " -Container=\"container name\"" echo "Configuration can be Release, Checked, or Debug" echo "Architecture can be x64, x86, arm, or arm64" exit 1 @@ -16,6 +18,7 @@ usage() working_tree_root="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" $working_tree_root/run.sh publish-packages -BuildOS $* +$working_tree_root/run.sh publish-packages -BuildOS -distroRid -PublishTestNativeBins $* if [ $? -ne 0 ] then echo "ERROR: An error occurred while publishing packages; see $working_tree_root/publish-packages.log for more details. There may have been networking problems, so please try again in a few minutes." diff --git a/run.cmd b/run.cmd index 3647198..6c761b6 100644 --- a/run.cmd +++ b/run.cmd @@ -1,4 +1,4 @@ -@if "%_echo%" neq "on" echo off +@if not defined _echo @echo off setlocal if not defined VisualStudioVersion ( @@ -30,10 +30,10 @@ if NOT [%ERRORLEVEL%]==[0] ( set _toolRuntime=%~dp0Tools set _dotnet=%_toolRuntime%\dotnetcli\dotnet.exe -echo Running: %_dotnet% %_toolRuntime%\run.exe %* -call %_dotnet% %_toolRuntime%\run.exe %* +echo Running: %_dotnet% %_toolRuntime%\run.exe %~dp0config.json %* +call %_dotnet% %_toolRuntime%\run.exe %~dp0config.json %* if NOT [%ERRORLEVEL%]==[0] ( exit /b 1 ) -exit /b 0 \ No newline at end of file +exit /b 0 diff --git a/run.sh b/run.sh index 1c9299a..bd6a68f 100755 --- a/run.sh +++ b/run.sh @@ -8,8 +8,8 @@ $working_tree_root/init-tools.sh toolRuntime=$working_tree_root/Tools dotnet=$toolRuntime/dotnetcli/dotnet -echo "Running: $dotnet $toolRuntime/run.exe $*" -$dotnet $toolRuntime/run.exe $* +echo "Running: $dotnet $toolRuntime/run.exe $working_tree_root/config.json $*" +$dotnet $toolRuntime/run.exe $working_tree_root/config.json $* if [ $? -ne 0 ] then echo "ERROR: An error occured in $dotnet $toolRuntime/run $#. Check $# logs under $working_tree_root." diff --git a/src/.gitmirrorselective b/src/.gitmirrorselective new file mode 100644 index 0000000..94b143d --- /dev/null +++ b/src/.gitmirrorselective @@ -0,0 +1,2 @@ +jit +ToolBox \ No newline at end of file diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/Microsoft.NETCore.ILAsm.builds b/src/.nuget/Microsoft.NETCore.ILAsm/Microsoft.NETCore.ILAsm.builds index 4cc7e10..e568ca5 100644 --- a/src/.nuget/Microsoft.NETCore.ILAsm/Microsoft.NETCore.ILAsm.builds +++ b/src/.nuget/Microsoft.NETCore.ILAsm/Microsoft.NETCore.ILAsm.builds @@ -27,6 +27,10 @@ Windows_NT arm + + Linux + amd64 + Linux amd64 @@ -55,14 +59,26 @@ Linux amd64 + + Linux + arm + Linux amd64 + + Linux + arm + Linux amd64 + + Linux + amd64 + OSX amd64 diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/Microsoft.NETCore.ILAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILAsm/Microsoft.NETCore.ILAsm.pkgproj index d2cc6d3..c0b2134 100644 --- a/src/.nuget/Microsoft.NETCore.ILAsm/Microsoft.NETCore.ILAsm.pkgproj +++ b/src/.nuget/Microsoft.NETCore.ILAsm/Microsoft.NETCore.ILAsm.pkgproj @@ -22,6 +22,9 @@ arm + + amd64 + amd64 @@ -43,15 +46,24 @@ amd64 + + arm + amd64 + + arm + amd64 + + amd64 + amd64 - \ No newline at end of file + diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/alpine/3.4.3/Microsoft.NETCore.ILAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILAsm/alpine/3.4.3/Microsoft.NETCore.ILAsm.pkgproj new file mode 100644 index 0000000..41a5b4c --- /dev/null +++ b/src/.nuget/Microsoft.NETCore.ILAsm/alpine/3.4.3/Microsoft.NETCore.ILAsm.pkgproj @@ -0,0 +1,29 @@ + + + + + true + alpine.3.4.3-$(PackagePlatform) + + x64; + + + + + + runtimes/$(PackageTargetRuntime)/native + + + + + + + + + + runtimes/$(PackageTargetRuntime)/native + true + + + + \ No newline at end of file diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/linux/Microsoft.NETCore.ILAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILAsm/linux/Microsoft.NETCore.ILAsm.pkgproj new file mode 100644 index 0000000..ce3bf63 --- /dev/null +++ b/src/.nuget/Microsoft.NETCore.ILAsm/linux/Microsoft.NETCore.ILAsm.pkgproj @@ -0,0 +1,29 @@ + + + + + true + linux-$(PackagePlatform) + + x64; + + + + + + runtimes/$(PackageTargetRuntime)/native + + + + + + + + + + runtimes/$(PackageTargetRuntime)/native + true + + + + \ No newline at end of file diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/ubuntu/14.04/Microsoft.NETCore.ILAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILAsm/ubuntu/14.04/Microsoft.NETCore.ILAsm.pkgproj index 0864a65..cacadc7 100644 --- a/src/.nuget/Microsoft.NETCore.ILAsm/ubuntu/14.04/Microsoft.NETCore.ILAsm.pkgproj +++ b/src/.nuget/Microsoft.NETCore.ILAsm/ubuntu/14.04/Microsoft.NETCore.ILAsm.pkgproj @@ -4,8 +4,8 @@ true ubuntu.14.04-$(PackagePlatform) - - x64; + + x64;arm; @@ -26,4 +26,4 @@ - \ No newline at end of file + diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/ubuntu/16.04/Microsoft.NETCore.ILAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILAsm/ubuntu/16.04/Microsoft.NETCore.ILAsm.pkgproj index b48290b..818495e 100644 --- a/src/.nuget/Microsoft.NETCore.ILAsm/ubuntu/16.04/Microsoft.NETCore.ILAsm.pkgproj +++ b/src/.nuget/Microsoft.NETCore.ILAsm/ubuntu/16.04/Microsoft.NETCore.ILAsm.pkgproj @@ -4,8 +4,8 @@ true ubuntu.16.04-$(PackagePlatform) - - x64; + + x64;arm; @@ -26,4 +26,4 @@ - \ No newline at end of file + diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/Microsoft.NETCore.ILDAsm.builds b/src/.nuget/Microsoft.NETCore.ILDAsm/Microsoft.NETCore.ILDAsm.builds index e7ae8e2..5939fda 100644 --- a/src/.nuget/Microsoft.NETCore.ILDAsm/Microsoft.NETCore.ILDAsm.builds +++ b/src/.nuget/Microsoft.NETCore.ILDAsm/Microsoft.NETCore.ILDAsm.builds @@ -27,6 +27,10 @@ Windows_NT arm + + Linux + amd64 + Linux amd64 @@ -55,14 +59,26 @@ Linux amd64 + + Linux + arm + Linux amd64 + + Linux + arm + Linux amd64 + + Linux + amd64 + OSX amd64 diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/Microsoft.NETCore.ILDAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILDAsm/Microsoft.NETCore.ILDAsm.pkgproj index 945bef9..47683ef 100644 --- a/src/.nuget/Microsoft.NETCore.ILDAsm/Microsoft.NETCore.ILDAsm.pkgproj +++ b/src/.nuget/Microsoft.NETCore.ILDAsm/Microsoft.NETCore.ILDAsm.pkgproj @@ -22,6 +22,9 @@ arm + + amd64 + amd64 @@ -43,15 +46,24 @@ amd64 + + arm + amd64 + + arm + amd64 + + amd64 + amd64 - \ No newline at end of file + diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/alpine/3.4.3/Microsoft.NETCore.ILDAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILDAsm/alpine/3.4.3/Microsoft.NETCore.ILDAsm.pkgproj new file mode 100644 index 0000000..b27fe08 --- /dev/null +++ b/src/.nuget/Microsoft.NETCore.ILDAsm/alpine/3.4.3/Microsoft.NETCore.ILDAsm.pkgproj @@ -0,0 +1,29 @@ + + + + + true + alpine.3.4.3-$(PackagePlatform) + + x64; + + + + + + runtimes/$(PackageTargetRuntime)/native + + + + + + + + + + runtimes/$(PackageTargetRuntime)/native + true + + + + \ No newline at end of file diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/linux/Microsoft.NETCore.ILDAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILDAsm/linux/Microsoft.NETCore.ILDAsm.pkgproj new file mode 100644 index 0000000..7a7f82d --- /dev/null +++ b/src/.nuget/Microsoft.NETCore.ILDAsm/linux/Microsoft.NETCore.ILDAsm.pkgproj @@ -0,0 +1,29 @@ + + + + + true + linux-$(PackagePlatform) + + x64; + + + + + + runtimes/$(PackageTargetRuntime)/native + + + + + + + + + + runtimes/$(PackageTargetRuntime)/native + true + + + + \ No newline at end of file diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/ubuntu/14.04/Microsoft.NETCore.ILDAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILDAsm/ubuntu/14.04/Microsoft.NETCore.ILDAsm.pkgproj index e5bdb51..e087645 100644 --- a/src/.nuget/Microsoft.NETCore.ILDAsm/ubuntu/14.04/Microsoft.NETCore.ILDAsm.pkgproj +++ b/src/.nuget/Microsoft.NETCore.ILDAsm/ubuntu/14.04/Microsoft.NETCore.ILDAsm.pkgproj @@ -4,8 +4,8 @@ true ubuntu.14.04-$(PackagePlatform) - - x64; + + x64;arm; @@ -26,4 +26,4 @@ - \ No newline at end of file + diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/ubuntu/16.04/Microsoft.NETCore.ILDAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILDAsm/ubuntu/16.04/Microsoft.NETCore.ILDAsm.pkgproj index b20c9c9..776e59b 100644 --- a/src/.nuget/Microsoft.NETCore.ILDAsm/ubuntu/16.04/Microsoft.NETCore.ILDAsm.pkgproj +++ b/src/.nuget/Microsoft.NETCore.ILDAsm/ubuntu/16.04/Microsoft.NETCore.ILDAsm.pkgproj @@ -4,8 +4,8 @@ true ubuntu.16.04-$(PackagePlatform) - - x64; + + x64;arm; @@ -26,4 +26,4 @@ - \ No newline at end of file + diff --git a/src/.nuget/Microsoft.NETCore.Jit/Microsoft.NETCore.Jit.builds b/src/.nuget/Microsoft.NETCore.Jit/Microsoft.NETCore.Jit.builds index 9095196..61c690e 100644 --- a/src/.nuget/Microsoft.NETCore.Jit/Microsoft.NETCore.Jit.builds +++ b/src/.nuget/Microsoft.NETCore.Jit/Microsoft.NETCore.Jit.builds @@ -27,6 +27,10 @@ Windows_NT arm + + Linux + amd64 + Linux amd64 @@ -55,14 +59,26 @@ Linux amd64 + + Linux + arm + Linux amd64 + + Linux + arm + Linux amd64 + + Linux + amd64 + OSX amd64 diff --git a/src/.nuget/Microsoft.NETCore.Jit/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/Microsoft.NETCore.Jit.pkgproj index a6a2c19..bcd4e42 100644 --- a/src/.nuget/Microsoft.NETCore.Jit/Microsoft.NETCore.Jit.pkgproj +++ b/src/.nuget/Microsoft.NETCore.Jit/Microsoft.NETCore.Jit.pkgproj @@ -21,6 +21,9 @@ arm + + amd64 + amd64 @@ -42,15 +45,24 @@ amd64 + + arm + amd64 + + arm + amd64 + + amd64 + amd64 - \ No newline at end of file + diff --git a/src/.nuget/Microsoft.NETCore.Jit/alpine/3.4.3/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/alpine/3.4.3/Microsoft.NETCore.Jit.pkgproj new file mode 100644 index 0000000..96851ff --- /dev/null +++ b/src/.nuget/Microsoft.NETCore.Jit/alpine/3.4.3/Microsoft.NETCore.Jit.pkgproj @@ -0,0 +1,29 @@ + + + + + true + alpine.3.4.3-$(PackagePlatform) + + x64; + + + + + + runtimes/$(PackageTargetRuntime)/native + + + + + + + + + + runtimes/$(PackageTargetRuntime)/native + true + + + + \ No newline at end of file diff --git a/src/.nuget/Microsoft.NETCore.Jit/linux/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/linux/Microsoft.NETCore.Jit.pkgproj new file mode 100644 index 0000000..541b81e --- /dev/null +++ b/src/.nuget/Microsoft.NETCore.Jit/linux/Microsoft.NETCore.Jit.pkgproj @@ -0,0 +1,29 @@ + + + + + true + linux-$(PackagePlatform) + + x64; + + + + + + runtimes/$(PackageTargetRuntime)/native + + + + + + + + + + runtimes/$(PackageTargetRuntime)/native + true + + + + \ No newline at end of file diff --git a/src/.nuget/Microsoft.NETCore.Jit/ubuntu/14.04/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/ubuntu/14.04/Microsoft.NETCore.Jit.pkgproj index e6775da..50d343f 100644 --- a/src/.nuget/Microsoft.NETCore.Jit/ubuntu/14.04/Microsoft.NETCore.Jit.pkgproj +++ b/src/.nuget/Microsoft.NETCore.Jit/ubuntu/14.04/Microsoft.NETCore.Jit.pkgproj @@ -4,8 +4,8 @@ true ubuntu.14.04-$(PackagePlatform) - - x64; + + x64;arm; @@ -26,4 +26,4 @@ - \ No newline at end of file + diff --git a/src/.nuget/Microsoft.NETCore.Jit/ubuntu/16.04/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/ubuntu/16.04/Microsoft.NETCore.Jit.pkgproj index dc59c2a..e57b7c5 100644 --- a/src/.nuget/Microsoft.NETCore.Jit/ubuntu/16.04/Microsoft.NETCore.Jit.pkgproj +++ b/src/.nuget/Microsoft.NETCore.Jit/ubuntu/16.04/Microsoft.NETCore.Jit.pkgproj @@ -4,8 +4,8 @@ true ubuntu.16.04-$(PackagePlatform) - - x64; + + x64;arm; @@ -26,4 +26,4 @@ - \ No newline at end of file + diff --git a/src/.nuget/Microsoft.NETCore.Jit/win/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/win/Microsoft.NETCore.Jit.pkgproj index 0a43ac4..66106c3 100644 --- a/src/.nuget/Microsoft.NETCore.Jit/win/Microsoft.NETCore.Jit.pkgproj +++ b/src/.nuget/Microsoft.NETCore.Jit/win/Microsoft.NETCore.Jit.pkgproj @@ -8,6 +8,7 @@ + runtimes/$(PackageTargetRuntime)/native diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/Microsoft.NETCore.Runtime.CoreCLR.builds b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/Microsoft.NETCore.Runtime.CoreCLR.builds index 341ec28..c7bfdc3 100644 --- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/Microsoft.NETCore.Runtime.CoreCLR.builds +++ b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/Microsoft.NETCore.Runtime.CoreCLR.builds @@ -6,7 +6,6 @@ $(PackageOutputPath) - @@ -27,6 +26,10 @@ Windows_NT arm + + Linux + amd64 + Linux amd64 @@ -55,14 +58,26 @@ Linux amd64 + + Linux + arm + Linux amd64 + + Linux + arm + Linux amd64 + + Linux + amd64 + OSX amd64 diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/Microsoft.NETCore.Runtime.CoreCLR.pkgproj index 65adcfe..a1405d5 100644 --- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/Microsoft.NETCore.Runtime.CoreCLR.pkgproj +++ b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/Microsoft.NETCore.Runtime.CoreCLR.pkgproj @@ -9,18 +9,6 @@ true - - - win8-arm - $(RuntimeWin8ArmMicrosoftNETCoreRuntimeCoreCLRPackageVersion) - - - - $(MicrosoftNETCoreWindowsApiSetsPackageVersion) - amd64 @@ -31,6 +19,12 @@ x86 + + arm + + + amd64 + amd64 @@ -52,15 +46,24 @@ amd64 + + arm + amd64 + + arm + amd64 + + amd64 + amd64 - \ No newline at end of file + diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/alpine/3.4.3/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/alpine/3.4.3/Microsoft.NETCore.Runtime.CoreCLR.pkgproj new file mode 100644 index 0000000..c779349 --- /dev/null +++ b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/alpine/3.4.3/Microsoft.NETCore.Runtime.CoreCLR.pkgproj @@ -0,0 +1,56 @@ + + + + + true + alpine.3.4.3-$(PackagePlatform) + + x64; + + + + + + + + + + + + + + + + + + + + runtimes/$(PackageTargetRuntime)/native + + + + runtimes/$(PackageTargetRuntime)/lib/netstandard1.0 + + + + ref/netstandard1.0 + + + tools + + + + + + + + + + + + runtimes/$(PackageTargetRuntime)/native + true + + + + diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/linux/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/linux/Microsoft.NETCore.Runtime.CoreCLR.pkgproj new file mode 100644 index 0000000..31e7196 --- /dev/null +++ b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/linux/Microsoft.NETCore.Runtime.CoreCLR.pkgproj @@ -0,0 +1,56 @@ + + + + + true + linux-$(PackagePlatform) + + x64; + + + + + + + + + + + + + + + + + + + + runtimes/$(PackageTargetRuntime)/native + + + + runtimes/$(PackageTargetRuntime)/lib/netstandard1.0 + + + + ref/netstandard1.0 + + + tools + + + + + + + + + + + + runtimes/$(PackageTargetRuntime)/native + true + + + + diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/ubuntu/14.04/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/ubuntu/14.04/Microsoft.NETCore.Runtime.CoreCLR.pkgproj index 4b1f151..86cb61a 100644 --- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/ubuntu/14.04/Microsoft.NETCore.Runtime.CoreCLR.pkgproj +++ b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/ubuntu/14.04/Microsoft.NETCore.Runtime.CoreCLR.pkgproj @@ -4,12 +4,12 @@ true ubuntu.14.04-$(PackagePlatform) - - x64; + + x64;arm; - + @@ -17,8 +17,8 @@ - - + + diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/ubuntu/16.04/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/ubuntu/16.04/Microsoft.NETCore.Runtime.CoreCLR.pkgproj index 7163623..72c48ee 100644 --- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/ubuntu/16.04/Microsoft.NETCore.Runtime.CoreCLR.pkgproj +++ b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/ubuntu/16.04/Microsoft.NETCore.Runtime.CoreCLR.pkgproj @@ -4,12 +4,12 @@ true ubuntu.16.04-$(PackagePlatform) - - x64; + + x64;arm; - + @@ -17,8 +17,8 @@ - - + + diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/win/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/win/Microsoft.NETCore.Runtime.CoreCLR.pkgproj index f77ac72..844fb0b 100644 --- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/win/Microsoft.NETCore.Runtime.CoreCLR.pkgproj +++ b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/win/Microsoft.NETCore.Runtime.CoreCLR.pkgproj @@ -39,7 +39,7 @@ - + @@ -84,13 +84,13 @@ + Include="@(LongNameFiles -> 'tools\$(CrossTargetComponentFolder)_$(PackagePlatform)\%(FileName)$(CrossTargetLongNameSuffix)%(Extension)')" /> runtimes\$(PackageTargetRuntime)\native true - tools/$(CrossTargetComponentFolder)_$(PackagePlatform) + tools\$(CrossTargetComponentFolder)_$(PackagePlatform) true diff --git a/src/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.builds b/src/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.builds index 2ae0292..c1d076f 100644 --- a/src/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.builds +++ b/src/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.builds @@ -27,6 +27,10 @@ Windows_NT arm + + Linux + amd64 + Linux amd64 @@ -55,14 +59,26 @@ Linux amd64 + + Linux + arm + Linux amd64 + + Linux + arm + Linux amd64 + + Linux + amd64 + OSX amd64 diff --git a/src/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.pkgproj b/src/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.pkgproj index fd6f7aa..325461d 100644 --- a/src/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.pkgproj +++ b/src/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.pkgproj @@ -9,11 +9,6 @@ true - - - win7-arm - $(RuntimeWin7ArmMicrosoftNETCoreTestHostPackageVersion) - amd64 @@ -26,6 +21,9 @@ arm + + amd64 + amd64 @@ -47,15 +45,24 @@ amd64 + + arm + amd64 + + arm + amd64 + + amd64 + amd64 - \ No newline at end of file + diff --git a/src/.nuget/Microsoft.NETCore.TestHost/alpine/3.4.3/Microsoft.NETCore.TestHost.pkgproj b/src/.nuget/Microsoft.NETCore.TestHost/alpine/3.4.3/Microsoft.NETCore.TestHost.pkgproj new file mode 100644 index 0000000..dd142f6 --- /dev/null +++ b/src/.nuget/Microsoft.NETCore.TestHost/alpine/3.4.3/Microsoft.NETCore.TestHost.pkgproj @@ -0,0 +1,29 @@ + + + + + true + alpine.3.4.3-$(PackagePlatform) + + x64; + + + + + + runtimes/$(PackageTargetRuntime)/native + + + + + + + + + + runtimes/$(PackageTargetRuntime)/native + true + + + + \ No newline at end of file diff --git a/src/.nuget/Microsoft.NETCore.TestHost/linux/Microsoft.NETCore.TestHost.pkgproj b/src/.nuget/Microsoft.NETCore.TestHost/linux/Microsoft.NETCore.TestHost.pkgproj new file mode 100644 index 0000000..06a6f4c --- /dev/null +++ b/src/.nuget/Microsoft.NETCore.TestHost/linux/Microsoft.NETCore.TestHost.pkgproj @@ -0,0 +1,29 @@ + + + + + true + linux-$(PackagePlatform) + + x64; + + + + + + runtimes/$(PackageTargetRuntime)/native + + + + + + + + + + runtimes/$(PackageTargetRuntime)/native + true + + + + \ No newline at end of file diff --git a/src/.nuget/Microsoft.NETCore.TestHost/ubuntu/14.04/Microsoft.NETCore.TestHost.pkgproj b/src/.nuget/Microsoft.NETCore.TestHost/ubuntu/14.04/Microsoft.NETCore.TestHost.pkgproj index a73159a..8750e16 100644 --- a/src/.nuget/Microsoft.NETCore.TestHost/ubuntu/14.04/Microsoft.NETCore.TestHost.pkgproj +++ b/src/.nuget/Microsoft.NETCore.TestHost/ubuntu/14.04/Microsoft.NETCore.TestHost.pkgproj @@ -4,8 +4,8 @@ true ubuntu.14.04-$(PackagePlatform) - - x64; + + x64;arm; @@ -26,4 +26,4 @@ - \ No newline at end of file + diff --git a/src/.nuget/Microsoft.NETCore.TestHost/ubuntu/16.04/Microsoft.NETCore.TestHost.pkgproj b/src/.nuget/Microsoft.NETCore.TestHost/ubuntu/16.04/Microsoft.NETCore.TestHost.pkgproj index 0613194..3f1397f 100644 --- a/src/.nuget/Microsoft.NETCore.TestHost/ubuntu/16.04/Microsoft.NETCore.TestHost.pkgproj +++ b/src/.nuget/Microsoft.NETCore.TestHost/ubuntu/16.04/Microsoft.NETCore.TestHost.pkgproj @@ -4,8 +4,8 @@ true ubuntu.16.04-$(PackagePlatform) - - x64; + + x64;arm; @@ -26,4 +26,4 @@ - \ No newline at end of file + diff --git a/src/.nuget/optdata/project.json b/src/.nuget/optdata/project.json deleted file mode 100644 index e8b45c8..0000000 --- a/src/.nuget/optdata/project.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "dependencies": { - "optimization.PGO.CoreCLR": "1.1.0-release-20161025" - }, - "frameworks": { - "netstandard": {} - }, - "runtimes": { - "win7-x64": {} - } -} diff --git a/src/.nuget/packages.builds b/src/.nuget/packages.builds index 89952ce..7458c8e 100644 --- a/src/.nuget/packages.builds +++ b/src/.nuget/packages.builds @@ -9,6 +9,9 @@ + + + diff --git a/src/ToolBox/.gitmirrorselective b/src/ToolBox/.gitmirrorselective new file mode 100644 index 0000000..8174296 --- /dev/null +++ b/src/ToolBox/.gitmirrorselective @@ -0,0 +1 @@ +superpmi \ No newline at end of file diff --git a/src/ToolBox/SOS/NETCore/SymbolReader.cs b/src/ToolBox/SOS/NETCore/SymbolReader.cs index f4a3ce3..492f7cb 100644 --- a/src/ToolBox/SOS/NETCore/SymbolReader.cs +++ b/src/ToolBox/SOS/NETCore/SymbolReader.cs @@ -28,13 +28,16 @@ namespace SOS { public IntPtr points; public int size; + public IntPtr locals; + public int localsSize; + } /// /// Read memory callback /// /// number of bytes read or 0 for error - internal unsafe delegate int ReadMemoryDelegate(IntPtr address, byte* buffer, int count); + internal unsafe delegate int ReadMemoryDelegate(ulong address, byte* buffer, int count); private sealed class OpenedReader : IDisposable { @@ -58,7 +61,7 @@ namespace SOS /// private class TargetStream : Stream { - readonly IntPtr _address; + readonly ulong _address; readonly ReadMemoryDelegate _readMemory; public override long Position { get; set; } @@ -67,7 +70,7 @@ namespace SOS public override bool CanRead { get { return true; } } public override bool CanWrite { get { return false; } } - public TargetStream(IntPtr address, int size, ReadMemoryDelegate readMemory) + public TargetStream(ulong address, int size, ReadMemoryDelegate readMemory) : base() { _address = address; @@ -86,7 +89,7 @@ namespace SOS { fixed (byte* p = &buffer[offset]) { - int read = _readMemory(new IntPtr(_address.ToInt64() + Position), p, count); + int read = _readMemory(_address + (ulong)Position, p, count); Position += read; return read; } @@ -126,6 +129,19 @@ namespace SOS } /// + /// Quick fix for Path.GetFileName which incorrectly handles Windows-style paths on Linux + /// + /// File path to be processed + /// Last component of path + private static string GetFileName(string pathName) + { + int pos = pathName.LastIndexOfAny(new char[] { '/', '\\'}); + if (pos < 0) + return pathName; + return pathName.Substring(pos + 1); + } + + /// /// Checks availability of debugging information for given assembly. /// /// @@ -141,18 +157,18 @@ namespace SOS /// in memory PDB address or zero /// in memory PDB size /// Symbol reader handle or zero if error - internal static IntPtr LoadSymbolsForModule(string assemblyPath, bool isFileLayout, IntPtr loadedPeAddress, int loadedPeSize, - IntPtr inMemoryPdbAddress, int inMemoryPdbSize, ReadMemoryDelegate readMemory) + internal static IntPtr LoadSymbolsForModule(string assemblyPath, bool isFileLayout, ulong loadedPeAddress, int loadedPeSize, + ulong inMemoryPdbAddress, int inMemoryPdbSize, ReadMemoryDelegate readMemory) { try { TargetStream peStream = null; - if (assemblyPath == null && loadedPeAddress != IntPtr.Zero) + if (assemblyPath == null && loadedPeAddress != 0) { peStream = new TargetStream(loadedPeAddress, loadedPeSize, readMemory); } TargetStream pdbStream = null; - if (inMemoryPdbAddress != IntPtr.Zero) + if (inMemoryPdbAddress != 0) { pdbStream = new TargetStream(inMemoryPdbAddress, inMemoryPdbSize, readMemory); } @@ -207,7 +223,7 @@ namespace SOS try { - string fileName = Path.GetFileName(filePath); + string fileName = GetFileName(filePath); foreach (MethodDebugInformationHandle methodDebugInformationHandle in reader.MethodDebugInformation) { MethodDebugInformation methodDebugInfo = reader.GetMethodDebugInformation(methodDebugInformationHandle); @@ -215,7 +231,7 @@ namespace SOS foreach (SequencePoint point in sequencePoints) { string sourceName = reader.GetString(reader.GetDocument(point.Document).Name); - if (point.StartLine == lineNumber && Path.GetFileName(sourceName) == fileName) + if (point.StartLine == lineNumber && GetFileName(sourceName) == fileName) { methodToken = MetadataTokens.GetToken(methodDebugInformationHandle.ToDefinitionHandle()); ilOffset = point.Offset; @@ -378,7 +394,48 @@ namespace SOS } return false; } + internal static bool GetLocalsInfoForMethod(string assemblyPath, int methodToken, out List locals) + { + locals = null; + + OpenedReader openedReader = GetReader(assemblyPath, isFileLayout: true, peStream: null, pdbStream: null); + if (openedReader == null) + return false; + + using (openedReader) + { + try + { + Handle handle = MetadataTokens.Handle(methodToken); + if (handle.Kind != HandleKind.MethodDefinition) + return false; + + locals = new List(); + MethodDebugInformationHandle methodDebugHandle = + ((MethodDefinitionHandle)handle).ToDebugInformationHandle(); + LocalScopeHandleCollection localScopes = openedReader.Reader.GetLocalScopes(methodDebugHandle); + foreach (LocalScopeHandle scopeHandle in localScopes) + { + LocalScope scope = openedReader.Reader.GetLocalScope(scopeHandle); + LocalVariableHandleCollection localVars = scope.GetLocalVariables(); + foreach (LocalVariableHandle varHandle in localVars) + { + LocalVariable localVar = openedReader.Reader.GetLocalVariable(varHandle); + if (localVar.Attributes == LocalVariableAttributes.DebuggerHidden) + continue; + locals.Add(openedReader.Reader.GetString(localVar.Name)); + } + } + } + catch + { + return false; + } + } + return true; + + } /// /// Returns source name, line numbers and IL offsets for given method token. /// @@ -392,11 +449,17 @@ namespace SOS try { List points = null; + List locals = null; if (!GetDebugInfoForMethod(assemblyPath, methodToken, out points)) { return false; } + + if (!GetLocalsInfoForMethod(assemblyPath, methodToken, out locals)) + { + return false; + } var structSize = Marshal.SizeOf(); debugInfo.size = points.Count; @@ -407,6 +470,14 @@ namespace SOS Marshal.StructureToPtr(info, ptr, false); ptr = (IntPtr)(ptr.ToInt64() + structSize); } + debugInfo.localsSize = locals.Count; + debugInfo.locals = Marshal.AllocHGlobal(debugInfo.localsSize * Marshal.SizeOf()); + IntPtr ptrLocals = debugInfo.locals; + foreach (string s in locals) + { + Marshal.WriteIntPtr(ptrLocals, Marshal.StringToHGlobalUni(s)); + ptrLocals += Marshal.SizeOf(); + } return true; } catch @@ -446,12 +517,10 @@ namespace SOS foreach (SequencePoint point in sequencePoints) { - if (point.StartLine == 0 || point.StartLine == SequencePoint.HiddenLine) - continue; DebugInfo debugInfo = new DebugInfo(); debugInfo.lineNumber = point.StartLine; - debugInfo.fileName = openedReader.Reader.GetString(openedReader.Reader.GetDocument(point.Document).Name); + debugInfo.fileName = GetFileName(openedReader.Reader.GetString(openedReader.Reader.GetDocument(point.Document).Name)); debugInfo.ilOffset = point.Offset; points.Add(debugInfo); } @@ -609,7 +678,7 @@ namespace SOS { try { - pdbPath = Path.Combine(Path.GetDirectoryName(assemblyPath), Path.GetFileName(pdbPath)); + pdbPath = Path.Combine(Path.GetDirectoryName(assemblyPath), GetFileName(pdbPath)); } catch { diff --git a/src/ToolBox/SOS/NETCore/project.json b/src/ToolBox/SOS/NETCore/project.json index e9e4f09..7a3cf4f 100644 --- a/src/ToolBox/SOS/NETCore/project.json +++ b/src/ToolBox/SOS/NETCore/project.json @@ -3,7 +3,7 @@ "Microsoft.NETCore.Platforms": "1.0.1", "System.IO.FileSystem": "4.0.1", "System.Runtime.InteropServices": "4.1.0", - "System.Reflection.Metadata": "1.4.1-beta-24417-02" + "System.Reflection.Metadata": "1.4.1" }, "frameworks": { "netcoreapp1.0": {} diff --git a/src/ToolBox/SOS/Strike/CMakeLists.txt b/src/ToolBox/SOS/Strike/CMakeLists.txt index 5d25865..8ba0ade 100644 --- a/src/ToolBox/SOS/Strike/CMakeLists.txt +++ b/src/ToolBox/SOS/Strike/CMakeLists.txt @@ -24,7 +24,9 @@ elseif(CLR_CMAKE_PLATFORM_ARCH_I386) add_definitions(-DSOS_TARGET_X86=1) add_definitions(-D_TARGET_X86_=1) add_definitions(-DDBG_TARGET_32BIT) - add_definitions(-DSOS_TARGET_ARM=1) + if(WIN32) + add_definitions(-DSOS_TARGET_ARM=1) + endif(WIN32) elseif(CLR_CMAKE_PLATFORM_ARCH_ARM) add_definitions(-DSOS_TARGET_ARM=1) add_definitions(-D_TARGET_WIN32_=1) @@ -155,8 +157,13 @@ if(CLR_CMAKE_PLATFORM_ARCH_AMD64) elseif(CLR_CMAKE_PLATFORM_ARCH_I386) set(SOS_SOURCES_ARCH disasmX86.cpp - disasmARM.cpp ) + if(WIN32) + list(APPEND + SOS_SOURCES_ARCH + disasmARM.cpp + ) + endif(WIN32) elseif(CLR_CMAKE_PLATFORM_ARCH_ARM) set(SOS_SOURCES_ARCH disasmARM.cpp diff --git a/src/ToolBox/SOS/Strike/ExpressionNode.cpp b/src/ToolBox/SOS/Strike/ExpressionNode.cpp index 6516823..920afba 100644 --- a/src/ToolBox/SOS/Strike/ExpressionNode.cpp +++ b/src/ToolBox/SOS/Strike/ExpressionNode.cpp @@ -129,7 +129,7 @@ VOID ExpressionNode::DFSVisit(ExpressionNodeVisitorCallback pFunc, VOID* pUserDa // Creates a new expression with a given debuggee value and frame -ExpressionNode::ExpressionNode(__in_z WCHAR* pExpression, ICorDebugValue* pValue, ICorDebugILFrame* pFrame) +ExpressionNode::ExpressionNode(__in_z const WCHAR* pExpression, ICorDebugValue* pValue, ICorDebugILFrame* pFrame) { Init(pValue, NULL, pFrame); _snwprintf_s(pAbsoluteExpression, MAX_EXPRESSION, _TRUNCATE, L"%s", pExpression); @@ -137,7 +137,7 @@ ExpressionNode::ExpressionNode(__in_z WCHAR* pExpression, ICorDebugValue* pValue } // Creates a new expression that has an error and no value -ExpressionNode::ExpressionNode(__in_z WCHAR* pExpression, __in_z WCHAR* pErrorMessage) +ExpressionNode::ExpressionNode(__in_z const WCHAR* pExpression, __in_z const WCHAR* pErrorMessage) { Init(NULL, NULL, NULL); _snwprintf_s(pAbsoluteExpression, MAX_EXPRESSION, _TRUNCATE, L"%s", pExpression); @@ -146,7 +146,7 @@ ExpressionNode::ExpressionNode(__in_z WCHAR* pExpression, __in_z WCHAR* pErrorMe } // Creates a new child expression -ExpressionNode::ExpressionNode(__in_z WCHAR* pParentExpression, ChildKind ck, __in_z WCHAR* pRelativeExpression, ICorDebugValue* pValue, ICorDebugType* pType, ICorDebugILFrame* pFrame, UVCP_CONSTANT pDefaultValue, ULONG cchDefaultValue) +ExpressionNode::ExpressionNode(__in_z const WCHAR* pParentExpression, ChildKind ck, __in_z const WCHAR* pRelativeExpression, ICorDebugValue* pValue, ICorDebugType* pType, ICorDebugILFrame* pFrame, UVCP_CONSTANT pDefaultValue, ULONG cchDefaultValue) { Init(pValue, pType, pFrame); if(ck == ChildKind_BaseClass) @@ -1979,7 +1979,7 @@ HRESULT ExpressionNode::GetCanonicalElementTypeForTypeName(__in_z WCHAR* pTypeNa // Searches the debuggee for any ICorDebugType that matches the given fully qualified name // This will search across all AppDomains and Assemblies -HRESULT ExpressionNode::FindTypeByName(__in_z WCHAR* pTypeName, ICorDebugType** ppType) +HRESULT ExpressionNode::FindTypeByName(__in_z const WCHAR* pTypeName, ICorDebugType** ppType) { HRESULT Status = S_OK; ToRelease pAppDomainEnum; @@ -2001,7 +2001,7 @@ HRESULT ExpressionNode::FindTypeByName(__in_z WCHAR* pTypeName, ICorDebugType** // Searches the debuggee for any ICorDebugType that matches the given fully qualified name // This will search across all Assemblies in the given AppDomain -HRESULT ExpressionNode::FindTypeByName(ICorDebugAppDomain* pAppDomain, __in_z WCHAR* pTypeName, ICorDebugType** ppType) +HRESULT ExpressionNode::FindTypeByName(ICorDebugAppDomain* pAppDomain, __in_z const WCHAR* pTypeName, ICorDebugType** ppType) { HRESULT Status = S_OK; ToRelease pAssemblyEnum; @@ -2022,7 +2022,7 @@ HRESULT ExpressionNode::FindTypeByName(ICorDebugAppDomain* pAppDomain, __in_z WC } // Searches the assembly for any ICorDebugType that matches the given fully qualified name -HRESULT ExpressionNode::FindTypeByName(ICorDebugAssembly* pAssembly, __in_z WCHAR* pTypeName, ICorDebugType** ppType) +HRESULT ExpressionNode::FindTypeByName(ICorDebugAssembly* pAssembly, __in_z const WCHAR* pTypeName, ICorDebugType** ppType) { HRESULT Status = S_OK; ToRelease pModuleEnum; @@ -2043,7 +2043,7 @@ HRESULT ExpressionNode::FindTypeByName(ICorDebugAssembly* pAssembly, __in_z WCHA } // Searches a given module for any ICorDebugType that matches the given fully qualified type name -HRESULT ExpressionNode::FindTypeByName(ICorDebugModule* pModule, __in_z WCHAR* pTypeName, ICorDebugType** ppType) +HRESULT ExpressionNode::FindTypeByName(ICorDebugModule* pModule, __in_z const WCHAR* pTypeName, ICorDebugType** ppType) { HRESULT Status = S_OK; ToRelease pMDUnknown; @@ -2054,7 +2054,7 @@ HRESULT ExpressionNode::FindTypeByName(ICorDebugModule* pModule, __in_z WCHAR* p // If the name contains a generic argument list, extract the type name from // before the list WCHAR rootName[mdNameLen]; - WCHAR* pRootName = NULL; + const WCHAR* pRootName = NULL; int typeNameLen = (int) _wcslen(pTypeName); int genericParamListStart = (int) _wcscspn(pTypeName, L"<"); if(genericParamListStart != typeNameLen) @@ -2107,11 +2107,11 @@ HRESULT ExpressionNode::FindTypeByName(ICorDebugModule* pModule, __in_z WCHAR* p } typeParams = new ToRelease[countTypeParams]; - WCHAR* pCurName = pTypeName + genericParamListStart+1; + const WCHAR* pCurName = pTypeName + genericParamListStart+1; for(int i = 0; i < countTypeParams; i++) { WCHAR typeParamName[mdNameLen]; - WCHAR* pNextComma = _wcschr(pCurName, L','); + const WCHAR* pNextComma = _wcschr(pCurName, L','); int len = (pNextComma != NULL) ? (int)(pNextComma - pCurName) : (int)_wcslen(pCurName)-1; if(len > mdNameLen) return E_FAIL; diff --git a/src/ToolBox/SOS/Strike/ExpressionNode.h b/src/ToolBox/SOS/Strike/ExpressionNode.h index 507a8a5..48cc036 100644 --- a/src/ToolBox/SOS/Strike/ExpressionNode.h +++ b/src/ToolBox/SOS/Strike/ExpressionNode.h @@ -134,13 +134,13 @@ private: }; // Creates a new expression with a given debuggee value and frame - ExpressionNode(__in_z WCHAR* pExpression, ICorDebugValue* pValue, ICorDebugILFrame* pFrame); + ExpressionNode(__in_z const WCHAR* pExpression, ICorDebugValue* pValue, ICorDebugILFrame* pFrame); // Creates a new expression that has an error and no value - ExpressionNode(__in_z WCHAR* pExpression, __in_z WCHAR* pErrorMessage); + ExpressionNode(__in_z const WCHAR* pExpression, __in_z const WCHAR* pErrorMessage); // Creates a new child expression - ExpressionNode(__in_z WCHAR* pParentExpression, ChildKind ck, __in_z WCHAR* pRelativeExpression, ICorDebugValue* pValue, ICorDebugType* pType, ICorDebugILFrame* pFrame, UVCP_CONSTANT pDefaultValue = NULL, ULONG cchDefaultValue = 0); + ExpressionNode(__in_z const WCHAR* pParentExpression, ChildKind ck, __in_z const WCHAR* pRelativeExpression, ICorDebugValue* pValue, ICorDebugType* pType, ICorDebugILFrame* pFrame, UVCP_CONSTANT pDefaultValue = NULL, ULONG cchDefaultValue = 0); // Common member initialization for the constructors VOID Init(ICorDebugValue* pValue, ICorDebugType* pTypeCast, ICorDebugILFrame* pFrame); @@ -288,17 +288,17 @@ private: // Searches the debuggee for any ICorDebugType that matches the given fully qualified name // This will search across all AppDomains and Assemblies - static HRESULT FindTypeByName(__in_z WCHAR* pTypeName, ICorDebugType** ppType); + static HRESULT FindTypeByName(__in_z const WCHAR* pTypeName, ICorDebugType** ppType); // Searches the debuggee for any ICorDebugType that matches the given fully qualified name // This will search across all Assemblies in the given AppDomain - static HRESULT FindTypeByName(ICorDebugAppDomain* pAppDomain, __in_z WCHAR* pTypeName, ICorDebugType** ppType); + static HRESULT FindTypeByName(ICorDebugAppDomain* pAppDomain, __in_z const WCHAR* pTypeName, ICorDebugType** ppType); // Searches the assembly for any ICorDebugType that matches the given fully qualified name - static HRESULT FindTypeByName(ICorDebugAssembly* pAssembly, __in_z WCHAR* pTypeName, ICorDebugType** ppType); + static HRESULT FindTypeByName(ICorDebugAssembly* pAssembly, __in_z const WCHAR* pTypeName, ICorDebugType** ppType); // Searches a given module for any ICorDebugType that matches the given fully qualified type name - static HRESULT FindTypeByName(ICorDebugModule* pModule, __in_z WCHAR* pTypeName, ICorDebugType** ppType); + static HRESULT FindTypeByName(ICorDebugModule* pModule, __in_z const WCHAR* pTypeName, ICorDebugType** ppType); // Checks whether the given token is or refers to type System.ValueType or System.Enum static HRESULT IsTokenValueTypeOrEnum(mdToken token, IMetaDataImport* pMetadata, BOOL* pResult); diff --git a/src/ToolBox/SOS/Strike/datatarget.cpp b/src/ToolBox/SOS/Strike/datatarget.cpp index 8f24b7d..fe90f0e 100644 --- a/src/ToolBox/SOS/Strike/datatarget.cpp +++ b/src/ToolBox/SOS/Strike/datatarget.cpp @@ -83,9 +83,9 @@ DataTarget::GetPointerSize( { #if defined(SOS_TARGET_AMD64) || defined(SOS_TARGET_ARM64) *size = 8; -#elif defined(SOS_TARGET_ARM) +#elif defined(SOS_TARGET_ARM) || defined(SOS_TARGET_X86) *size = 4; -#elif +#else #error Unsupported architecture #endif diff --git a/src/ToolBox/SOS/Strike/sildasm.cpp b/src/ToolBox/SOS/Strike/sildasm.cpp index 6bd3bb4..911ff09 100644 --- a/src/ToolBox/SOS/Strike/sildasm.cpp +++ b/src/ToolBox/SOS/Strike/sildasm.cpp @@ -789,7 +789,7 @@ PCCOR_SIGNATURE PrettyPrintType( { //if (sizes[i] != 0 || lowerBounds[i] != 0) { - if (lowerBounds[i] == 0 && i < numSizes) + if (i < numSizes && lowerBounds[i] == 0) appendStrNum(out, sizes[i]); else { diff --git a/src/ToolBox/SOS/Strike/sos_stacktrace.h b/src/ToolBox/SOS/Strike/sos_stacktrace.h index 4aba4ea..0af241c 100644 --- a/src/ToolBox/SOS/Strike/sos_stacktrace.h +++ b/src/ToolBox/SOS/Strike/sos_stacktrace.h @@ -119,7 +119,7 @@ HRESULT CALLBACK _EFN_StackTrace( // cbString - number of characters available in the string buffer. // // The output will be truncated of cbString is not long enough for the full stack trace. -HRESULT _EFN_GetManagedExcepStack( +HRESULT CALLBACK _EFN_GetManagedExcepStack( PDEBUG_CLIENT client, ULONG64 StackObjAddr, __out_ecount(cbString) PSTR szStackString, @@ -128,7 +128,7 @@ HRESULT _EFN_GetManagedExcepStack( // _EFN_GetManagedExcepStackW - same as _EFN_GetManagedExcepStack, but returns // the stack as a wide string. -HRESULT _EFN_GetManagedExcepStackW( +HRESULT CALLBACK _EFN_GetManagedExcepStackW( PDEBUG_CLIENT client, ULONG64 StackObjAddr, __out_ecount(cchString) PWSTR wszStackString, @@ -141,7 +141,7 @@ HRESULT _EFN_GetManagedExcepStackW( // szName - a buffer to be filled with the full type name // cbName - the number of characters available in the buffer // -HRESULT _EFN_GetManagedObjectName( +HRESULT CALLBACK _EFN_GetManagedObjectName( PDEBUG_CLIENT client, ULONG64 objAddr, __out_ecount(cbName) PSTR szName, @@ -158,7 +158,7 @@ HRESULT _EFN_GetManagedObjectName( // pOffset - the offset from objAddr to the field. This parameter can be NULL. // // At least one of pValue and pOffset must be non-NULL. -HRESULT _EFN_GetManagedObjectFieldInfo( +HRESULT CALLBACK _EFN_GetManagedObjectFieldInfo( PDEBUG_CLIENT client, ULONG64 objAddr, __out_ecount (mdNameLen) PSTR szFieldName, diff --git a/src/ToolBox/SOS/Strike/sosdocsunix.txt b/src/ToolBox/SOS/Strike/sosdocsunix.txt index 52ec86d..5ab2b31 100644 --- a/src/ToolBox/SOS/Strike/sosdocsunix.txt +++ b/src/ToolBox/SOS/Strike/sosdocsunix.txt @@ -844,6 +844,7 @@ corruption bug caused by invalid GCEncoding for a particular method. COMMAND: bpmd. bpmd [-nofuturemodule] [] +bpmd : bpmd -md bpmd -list bpmd -clear diff --git a/src/ToolBox/SOS/Strike/stressLogDump.cpp b/src/ToolBox/SOS/Strike/stressLogDump.cpp index f277f92..9dfbe1e 100644 --- a/src/ToolBox/SOS/Strike/stressLogDump.cpp +++ b/src/ToolBox/SOS/Strike/stressLogDump.cpp @@ -34,7 +34,7 @@ static const WCHAR* getTime(const FILETIME* time, __out_ecount (buffLen) WCHAR* return badTime; #ifdef FEATURE_PAL - int length = _snwprintf(buff, buffLen, W("%02d:%02d:%02d"), systemTime.wHour, systemTime.wMinute, systemTime.wSecond); + int length = _snwprintf_s(buff, buffLen, _TRUNCATE, W("%02d:%02d:%02d"), systemTime.wHour, systemTime.wMinute, systemTime.wSecond); if (length <= 0) return badTime; #else // FEATURE_PAL diff --git a/src/ToolBox/SOS/Strike/strike.cpp b/src/ToolBox/SOS/Strike/strike.cpp index 731e2f5..3bb3f50 100644 --- a/src/ToolBox/SOS/Strike/strike.cpp +++ b/src/ToolBox/SOS/Strike/strike.cpp @@ -4361,8 +4361,10 @@ DECLARE_API(VerifyObj) ExtOut("Unable to build snapshot of the garbage collector state\n"); goto Exit; } - DacpGcHeapDetails *pheapDetails = g_snapshot.GetHeap(taddrObj); - bValid = VerifyObject(*pheapDetails, taddrObj, taddrMT, objSize, TRUE); + { + DacpGcHeapDetails *pheapDetails = g_snapshot.GetHeap(taddrObj); + bValid = VerifyObject(*pheapDetails, taddrObj, taddrMT, objSize, TRUE); + } Exit: if (bValid) @@ -5888,6 +5890,56 @@ HRESULT PrintSpecialThreads() } #endif //FEATURE_PAL +HRESULT SwitchToExceptionThread() +{ + HRESULT Status; + + DacpThreadStoreData ThreadStore; + if ((Status = ThreadStore.Request(g_sos)) != S_OK) + { + Print("Failed to request ThreadStore\n"); + return Status; + } + + DacpThreadData Thread; + CLRDATA_ADDRESS CurThread = ThreadStore.firstThread; + while (CurThread) + { + if (IsInterrupt()) + break; + + if ((Status = Thread.Request(g_sos, CurThread)) != S_OK) + { + PrintLn("Failed to request Thread at ", Pointer(CurThread)); + return Status; + } + + TADDR taLTOH; + if (Thread.lastThrownObjectHandle != NULL) + { + if (SafeReadMemory(TO_TADDR(Thread.lastThrownObjectHandle), &taLTOH, sizeof(taLTOH), NULL)) + { + if (taLTOH != NULL) + { + ULONG id; + if (g_ExtSystem->GetThreadIdBySystemId(Thread.osThreadId, &id) == S_OK) + { + if (g_ExtSystem->SetCurrentThreadId(id) == S_OK) + { + PrintLn("Found managed exception on thread ", ThreadID(Thread.osThreadId)); + break; + } + } + } + } + } + + CurThread = Thread.nextThread; + } + + return Status; +} + struct ThreadStateTable { unsigned int State; @@ -5961,12 +6013,14 @@ DECLARE_API(Threads) BOOL bPrintSpecialThreads = FALSE; BOOL bPrintLiveThreadsOnly = FALSE; + BOOL bSwitchToManagedExceptionThread = FALSE; BOOL dml = FALSE; CMDOption option[] = { // name, vptr, type, hasValue {"-special", &bPrintSpecialThreads, COBOOL, FALSE}, {"-live", &bPrintLiveThreadsOnly, COBOOL, FALSE}, + {"-managedexception", &bSwitchToManagedExceptionThread, COBOOL, FALSE}, #ifndef FEATURE_PAL {"/d", &dml, COBOOL, FALSE}, #endif @@ -5975,6 +6029,11 @@ DECLARE_API(Threads) { return Status; } + + if (bSwitchToManagedExceptionThread) + { + return SwitchToExceptionThread(); + } // We need to support minidumps for this command. BOOL bMiniDump = IsMiniDumpFile(); @@ -9119,7 +9178,7 @@ DECLARE_API (ProcInfo) if (pFntGetProcessTimes && pFntGetProcessTimes (hProcess,&CreationTime,&ExitTime,&KernelTime,&UserTime)) { ExtOut("---------------------------------------\n"); ExtOut("Process Times\n"); - static char *Month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", + static const char *Month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; SYSTEMTIME SystemTime; FILETIME LocalFileTime; diff --git a/src/ToolBox/SOS/Strike/util.cpp b/src/ToolBox/SOS/Strike/util.cpp index 9eec76e..b6336fb 100644 --- a/src/ToolBox/SOS/Strike/util.cpp +++ b/src/ToolBox/SOS/Strike/util.cpp @@ -254,47 +254,49 @@ HRESULT CreateInstanceCustomImpl( typedef HRESULT (__stdcall IDebugSymbols3::*GetPathFunc)(LPWSTR , ULONG, ULONG*); - // Handle both the image path and the symbol path - GetPathFunc rgGetPathFuncs[] = - { &IDebugSymbols3::GetImagePathWide, &IDebugSymbols3::GetSymbolPathWide }; - - for (int i = 0; i < _countof(rgGetPathFuncs); ++i) { - ULONG pathSize = 0; + // Handle both the image path and the symbol path + GetPathFunc rgGetPathFuncs[] = + { &IDebugSymbols3::GetImagePathWide, &IDebugSymbols3::GetSymbolPathWide }; - // get the path buffer size - if ((spSym3.GetPtr()->*rgGetPathFuncs[i])(NULL, 0, &pathSize) != S_OK) + for (int i = 0; i < _countof(rgGetPathFuncs); ++i) { - continue; - } + ULONG pathSize = 0; - ArrayHolder imgPath = new WCHAR[pathSize+MAX_LONGPATH+1]; - if (imgPath == NULL) - { - continue; - } + // get the path buffer size + if ((spSym3.GetPtr()->*rgGetPathFuncs[i])(NULL, 0, &pathSize) != S_OK) + { + continue; + } - // actually get the path - if ((spSym3.GetPtr()->*rgGetPathFuncs[i])(imgPath, pathSize, NULL) != S_OK) - { - continue; - } + ArrayHolder imgPath = new WCHAR[pathSize+MAX_LONGPATH+1]; + if (imgPath == NULL) + { + continue; + } - LPWSTR ctx; - LPCWSTR pathElem = wcstok_s(imgPath, W(";"), &ctx); - while (pathElem != NULL) - { - WCHAR fullName[MAX_LONGPATH]; - wcscpy_s(fullName, _countof(fullName), pathElem); - if (wcscat_s(fullName, W("\\")) == 0 && wcscat_s(fullName, dllName) == 0) + // actually get the path + if ((spSym3.GetPtr()->*rgGetPathFuncs[i])(imgPath, pathSize, NULL) != S_OK) + { + continue; + } + + LPWSTR ctx; + LPCWSTR pathElem = wcstok_s(imgPath, W(";"), &ctx); + while (pathElem != NULL) { - if (SUCCEEDED(CreateInstanceFromPath(clsid, iid, fullName, ppItf))) + WCHAR fullName[MAX_LONGPATH]; + wcscpy_s(fullName, _countof(fullName), pathElem); + if (wcscat_s(fullName, W("\\")) == 0 && wcscat_s(fullName, dllName) == 0) { - return S_OK; + if (SUCCEEDED(CreateInstanceFromPath(clsid, iid, fullName, ppItf))) + { + return S_OK; + } } - } - pathElem = wcstok_s(NULL, W(";"), &ctx); + pathElem = wcstok_s(NULL, W(";"), &ctx); + } } } @@ -6132,7 +6134,7 @@ HRESULT SymbolReader::LoadSymbolsForWindowsPDB(___in IMetaDataImport* pMD, ___in int ReadMemoryForSymbols(ULONG64 address, char *buffer, int cb) { ULONG read; - if (SafeReadMemory(address, (PVOID)buffer, cb, &read)) + if (SafeReadMemory(TO_TADDR(address), (PVOID)buffer, cb, &read)) { return read; } diff --git a/src/ToolBox/SOS/Strike/util.h b/src/ToolBox/SOS/Strike/util.h index f444c9f..4612acc 100644 --- a/src/ToolBox/SOS/Strike/util.h +++ b/src/ToolBox/SOS/Strike/util.h @@ -2258,13 +2258,9 @@ void GetMethodName(mdMethodDef methodDef, IMetaDataImport * pImport, CQuickBytes #ifndef _TARGET_WIN64_ #define itoa_s_ptr _itoa_s #define itow_s_ptr _itow_s -#define itoa_ptr _itoa -#define itow_ptr _itow #else #define itoa_s_ptr _i64toa_s #define itow_s_ptr _i64tow_s -#define itoa_ptr _i64toa -#define itow_ptr _i64tow #endif #ifdef FEATURE_PAL @@ -2359,11 +2355,11 @@ static const char *SymbolReaderDllName = "SOS.NETCore"; static const char *SymbolReaderClassName = "SOS.SymbolReader"; typedef int (*ReadMemoryDelegate)(ULONG64, char *, int); -typedef ULONG64 (*LoadSymbolsForModuleDelegate)(const char*, BOOL, ULONG64, int, ULONG64, int, ReadMemoryDelegate); -typedef void (*DisposeDelegate)(ULONG64); -typedef BOOL (*ResolveSequencePointDelegate)(ULONG64, const char*, unsigned int, unsigned int*, unsigned int*); -typedef BOOL (*GetLocalVariableName)(ULONG64, int, int, BSTR*); -typedef BOOL (*GetLineByILOffsetDelegate)(ULONG64, mdMethodDef, ULONG64, ULONG *, BSTR*); +typedef PVOID (*LoadSymbolsForModuleDelegate)(const char*, BOOL, ULONG64, int, ULONG64, int, ReadMemoryDelegate); +typedef void (*DisposeDelegate)(PVOID); +typedef BOOL (*ResolveSequencePointDelegate)(PVOID, const char*, unsigned int, unsigned int*, unsigned int*); +typedef BOOL (*GetLocalVariableName)(PVOID, int, int, BSTR*); +typedef BOOL (*GetLineByILOffsetDelegate)(PVOID, mdMethodDef, ULONG64, ULONG *, BSTR*); class SymbolReader { @@ -2371,7 +2367,7 @@ private: #ifndef FEATURE_PAL ISymUnmanagedReader* m_pSymReader; #endif - ULONG64 m_symbolReaderHandle; + PVOID m_symbolReaderHandle; static LoadSymbolsForModuleDelegate loadSymbolsForModuleDelegate; static DisposeDelegate disposeDelegate; diff --git a/src/ToolBox/SOS/Strike/vm.cpp b/src/ToolBox/SOS/Strike/vm.cpp index e7e5701..70e9210 100644 --- a/src/ToolBox/SOS/Strike/vm.cpp +++ b/src/ToolBox/SOS/Strike/vm.cpp @@ -82,7 +82,7 @@ typedef struct _VM_STATS typedef struct PROTECT_MASK { DWORD Bit; - PSTR Name; + PCSTR Name; } PROTECT_MASK, *PPROTECT_MASK; @@ -324,7 +324,7 @@ PrintVmStatsHeader( VOID PrintIndividualStat( - ___in __in_z IN PSTR Name, + ___in __in_z IN PCSTR Name, IN PINDIVIDUAL_STAT Stat ) { @@ -379,7 +379,7 @@ PrintIndividualStat( VOID PrintVmStats( - ___in __in_z IN PSTR Name, + ___in __in_z IN PCSTR Name, IN PVM_STATS Stats ) { @@ -443,7 +443,7 @@ VmStateToString( size_t capacity_Buffer ) { - PSTR result; + PCSTR result; CHAR invalidStr[sizeof("12345678")]; switch( State ) @@ -478,7 +478,7 @@ VmTypeToString( size_t capacity_Buffer ) { - PSTR result; + PCSTR result; CHAR invalidStr[sizeof("12345678")]; switch( Type ) diff --git a/src/ToolBox/SOS/lldbplugin/CMakeLists.txt b/src/ToolBox/SOS/lldbplugin/CMakeLists.txt index 9f90a54..7f1fa77 100644 --- a/src/ToolBox/SOS/lldbplugin/CMakeLists.txt +++ b/src/ToolBox/SOS/lldbplugin/CMakeLists.txt @@ -21,6 +21,10 @@ if(CLR_CMAKE_PLATFORM_ARCH_AMD64) add_definitions(-DDBG_TARGET_AMD64=1) add_definitions(-DDBG_TARGET_WIN64=1) add_definitions(-DBIT64) +elseif(CLR_CMAKE_PLATFORM_ARCH_I386) + add_definitions(-D_TARGET_X86_=1) + add_definitions(-DDBG_TARGET_32BIT=1) + add_definitions(-DDBG_TARGET_X86=1) elseif(CLR_CMAKE_PLATFORM_ARCH_ARM) add_definitions(-D_TARGET_ARM_=1) add_definitions(-DDBG_TARGET_32BIT=1) @@ -33,6 +37,9 @@ endif() set(ENABLE_LLDBPLUGIN ${CLR_CMAKE_PLATFORM_UNIX} CACHE BOOL "Enable building the SOS plugin for LLDB.") set(REQUIRE_LLDBPLUGIN ${CLR_CMAKE_PLATFORM_LINUX} CACHE BOOL "Require building the SOS plugin for LLDB.") +if(SKIP_LLDBPLUGIN) + SET(REQUIRE_LLDBPLUGIN false) +endif() set(LLVM_HOST_DIR "$ENV{LLVM_HOME}") set(WITH_LLDB_LIBS "${LLVM_HOST_DIR}/lib" CACHE PATH "Path to LLDB libraries") set(WITH_LLDB_INCLUDES "${LLVM_HOST_DIR}/include" CACHE PATH "Path to LLDB headers") diff --git a/src/ToolBox/SOS/lldbplugin/services.cpp b/src/ToolBox/SOS/lldbplugin/services.cpp index f6b4213..d2d2cf9 100644 --- a/src/ToolBox/SOS/lldbplugin/services.cpp +++ b/src/ToolBox/SOS/lldbplugin/services.cpp @@ -167,6 +167,8 @@ LLDBServices::VirtualUnwind( #ifdef DBG_TARGET_AMD64 DWORD64 spToFind = dtcontext->Rsp; +#elif DBG_TARGET_X86 + DWORD spToFind = dtcontext->Esp; #elif DBG_TARGET_ARM DWORD spToFind = dtcontext->Sp; #endif diff --git a/src/ToolBox/SOS/tests/OnCrash.do b/src/ToolBox/SOS/tests/OnCrash.do deleted file mode 100644 index b1da861..0000000 --- a/src/ToolBox/SOS/tests/OnCrash.do +++ /dev/null @@ -1,2 +0,0 @@ -script open("/tmp/flag_fail", "a").close() -q diff --git a/src/ToolBox/SOS/tests/README.md b/src/ToolBox/SOS/tests/README.md index ed4c8d0..1b9c1ea 100644 --- a/src/ToolBox/SOS/tests/README.md +++ b/src/ToolBox/SOS/tests/README.md @@ -1,18 +1,28 @@ Testing libsosplugin ===================================== -**Test assembly** -The test asembly file must follow two rules: -1. the test class must be named `Program` and -2. it must have a static `Main` method. - -**Running tests** -Make sure that python's lldb module is accessible. To run the tests, use the following command: -`python test_libsosplugin.py --clr-args="/path/to/corerun [corerun_options] /path/to/test_assembly.exe"` -`--clr-args` is a command that would normally be used to launch `corerun` -This will run the test suite on the specified assembly. - -**Writing tests** +**Test assembly** +Compile test assembly file using any C# compiler you have, for example: +- `gmcs test.cs` +- `corerun csc.exe /nologo /r:System.Private.CoreLib.dll test.cs` + + +**Running tests** +Make sure that python's lldb module is accessible. To run the tests, use the following command: +`python2 test_libsosplugin.py --corerun=corerun --sosplugin=sosplugin --assembly=assembly --timeout=timeout` +- `lldb` is a path to `lldb` to run +- `clrdir` is a directory with `corerun` and sosplugin +- `assembly` is a compiled test assembly (e.g. Test.exe) +- `timeout` is a deadline for a single test (in seconds) +- `regex` is a regular expression matching tests to run +- `repeat` is a number of passes for each test + + + +Log files for both failed and passed tests are `*.log` and `*.log.2` for standard output and error correspondingly. + + +**Writing tests** Tests start with the `TestSosCommands` class defined in `test_libsosplugin.py`. To add a test to the suite, start with implementing a new method inside this class whose name begins with `test_`. Most new commands will require only one line of code in this method: `self.do_test("scenarioname")`. This command will launch a new `lldb` instance, which in turn will call the `runScenario` method from `scenarioname` module. `scenarioname` is the name of the python module that will be running the scenario inside `lldb` (found in `tests` folder alongside with `test_libsosplugin.py` and named `scenarioname.py`). An example of a scenario looks like this: @@ -25,9 +35,10 @@ An example of a scenario looks like this: process.Continue() return True - `runScenario` method does all the work related to running the scenario: setting breakpoints, running SOS commands and examining their output. It should return a boolean value indicating a success or a failure. + `runScenario` method does all the work related to running the scenario: setting breakpoints, running SOS commands and examining their output. It should return a boolean value indicating a success or a failure. ***Note:*** `testutils.py` defines some useful commands that can be reused in many scenarios. -**Useful links** -[Python scripting in LLDB](http://lldb.llvm.org/python-reference.html) -[Python unittest framework](https://docs.python.org/2.7/library/unittest.html) \ No newline at end of file + +**Useful links** +[Python scripting in LLDB](http://lldb.llvm.org/python-reference.html) +[Python unittest framework](https://docs.python.org/2.7/library/unittest.html) diff --git a/src/ToolBox/SOS/tests/Test.cs b/src/ToolBox/SOS/tests/Test.cs new file mode 100644 index 0000000..e4ef76b --- /dev/null +++ b/src/ToolBox/SOS/tests/Test.cs @@ -0,0 +1,94 @@ +using System; + +class Test +{ + static void LikelyInlined() + { + Console.WriteLine("I would like to be inlined"); + } + + static void UnlikelyInlined() + { + Console.Write("I"); + Console.Write(" "); + Console.Write("w"); + Console.Write("o"); + Console.Write("u"); + Console.Write("l"); + Console.Write("d"); + Console.Write(" "); + Console.Write("n"); + Console.Write("o"); + Console.Write("t"); + Console.Write(" "); + Console.Write("l"); + Console.Write("i"); + Console.Write("k"); + Console.Write("e"); + Console.Write(" "); + Console.Write("t"); + Console.Write("o"); + Console.Write(" "); + Console.Write("b"); + Console.Write("e"); + Console.Write(" "); + Console.Write("i"); + Console.Write("n"); + Console.Write("l"); + Console.Write("i"); + Console.Write("n"); + Console.Write("e"); + Console.Write("d"); + Console.Write("\n"); + } + + static void ClrU() + { + Console.WriteLine("test dumpclass"); + } + + static void DumpClass() + { + Console.WriteLine("test dumpclass"); + } + + static void DumpIL() + { + Console.WriteLine("test dumpil"); + } + + static void DumpMD() + { + Console.WriteLine("test dumpmd"); + } + + static void DumpModule() + { + Console.WriteLine("test dumpmodule"); + } + + static void DumpObject() + { + Console.WriteLine("test dumpobject"); + } + + static void DumpStackObjects() + { + Console.WriteLine("test dso"); + } + + static void Name2EE() + { + Console.WriteLine("test name2ee"); + } + + + static int Main() + { + DumpIL(); + LikelyInlined(); + UnlikelyInlined(); + + return 0; + } +} diff --git a/src/ToolBox/SOS/tests/dumpil.py b/src/ToolBox/SOS/tests/dumpil.py deleted file mode 100644 index 9539b61..0000000 --- a/src/ToolBox/SOS/tests/dumpil.py +++ /dev/null @@ -1,26 +0,0 @@ -import lldb -import lldbutil -import re -import os -import testutils - -def runScenario(assemblyName, debugger, target): - process = target.GetProcess() - res = lldb.SBCommandReturnObject() - ci = debugger.GetCommandInterpreter() - - testutils.stop_in_main(ci, process, assemblyName) - addr = testutils.exec_and_find(ci, "name2ee " + assemblyName + " Program.Main", "MethodDesc:\s+([0-9a-fA-F]+)") - - result = False - if addr is not None: - ci.HandleCommand("dumpil " + addr, res) - if res.Succeeded(): - result = True - else: - print("DumpIL failed:") - print(res.GetOutput()) - print(res.GetError()) - - process.Continue() - return result diff --git a/src/ToolBox/SOS/tests/dumpmodule.py b/src/ToolBox/SOS/tests/dumpmodule.py deleted file mode 100644 index 04a5764..0000000 --- a/src/ToolBox/SOS/tests/dumpmodule.py +++ /dev/null @@ -1,26 +0,0 @@ -import lldb -import lldbutil -import re -import os -import testutils - -def runScenario(assemblyName, debugger, target): - process = target.GetProcess() - res = lldb.SBCommandReturnObject() - ci = debugger.GetCommandInterpreter() - - testutils.stop_in_main(ci, process, assemblyName) - addr = testutils.exec_and_find(ci, "name2ee " + assemblyName + " Program.Main", "Module:\s+([0-9a-fA-F]+)") - - result = False - if addr is not None: - ci.HandleCommand("dumpmodule " + addr, res) - if res.Succeeded(): - result = True - else: - print("DumpModule failed:") - print(res.GetOutput()) - print(res.GetError()) - - process.Continue() - return result \ No newline at end of file diff --git a/src/ToolBox/SOS/tests/runprocess.py b/src/ToolBox/SOS/tests/runprocess.py deleted file mode 100644 index d9367b3..0000000 --- a/src/ToolBox/SOS/tests/runprocess.py +++ /dev/null @@ -1,34 +0,0 @@ -import os -import lldb -import sys -import importlib -from test_libsosplugin import fail_flag - -def run(assemblyName, moduleName): - global fail_flag - - print(fail_flag) - # set the flag, if it is not set - if not os.access(fail_flag, os.R_OK): - open(fail_flag, "a").close() - - - debugger = lldb.debugger - - debugger.SetAsync(False) - target = lldb.target - - debugger.HandleCommand("process launch -s") - debugger.HandleCommand("breakpoint set -n LoadLibraryExW") - - target.GetProcess().Continue() - - debugger.HandleCommand("breakpoint delete 1") - #run the scenario - print("starting scenario...") - i = importlib.import_module(moduleName) - scenarioResult = i.runScenario(os.path.basename(assemblyName), debugger, target) - - # clear the failed flag if the exit status is OK - if scenarioResult is True and target.GetProcess().GetExitStatus() == 0: - os.unlink(fail_flag) diff --git a/src/ToolBox/SOS/tests/t_cmd_bpmd_clear.py b/src/ToolBox/SOS/tests/t_cmd_bpmd_clear.py new file mode 100644 index 0000000..814d114 --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_bpmd_clear.py @@ -0,0 +1,62 @@ +import lldb +import re +import testutils as test + +# bpmd -clearall + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + # Set breakpoint + + ci.HandleCommand("bpmd " + assembly + " Test.UnlikelyInlined", res) + out_msg = res.GetOutput() + err_msg = res.GetError() + print(out_msg) + print(err_msg) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + # Output is not empty + # Should be at least 'Adding pending breakpoints...' + test.assertTrue(len(out_msg) > 0) + + # Error message is empty + test.assertTrue(len(err_msg) == 0) + + # Delete the first breakpoint + + ci.HandleCommand("bpmd -clear 1", res) + out_msg = res.GetOutput() + err_msg = res.GetError() + print(out_msg) + print(err_msg) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + match = re.search('Cleared', out_msg) + # Check for specific output + test.assertTrue(match) + + # Error message is empty + test.assertEqual(err_msg, '') + + process.Continue() + # Process must be exited + test.assertEqual(process.GetState(), lldb.eStateExited) + + # The reason of this stop must be a breakpoint + test.assertEqual(process.GetSelectedThread().GetStopReason(), + lldb.eStopReasonNone) + + # + + # Delete all breakpoints, continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_bpmd_clearall.py b/src/ToolBox/SOS/tests/t_cmd_bpmd_clearall.py new file mode 100644 index 0000000..8da9239 --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_bpmd_clearall.py @@ -0,0 +1,62 @@ +import lldb +import re +import testutils as test + +# bpmd -clearall + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + # Set breakpoint + + ci.HandleCommand("bpmd " + assembly + " Test.UnlikelyInlined", res) + out_msg = res.GetOutput() + err_msg = res.GetError() + print(out_msg) + print(err_msg) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + # Output is not empty + # Should be at least 'Adding pending breakpoints...' + test.assertTrue(len(out_msg) > 0) + + # Error message is empty + test.assertTrue(len(err_msg) == 0) + + # Delete all breakpoints + + ci.HandleCommand("bpmd -clearall", res) + out_msg = res.GetOutput() + err_msg = res.GetError() + print(out_msg) + print(err_msg) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + match = re.search('All pending breakpoints cleared.', out_msg) + # Check for specific output + test.assertTrue(match) + + # Error message is empty + test.assertEqual(err_msg, '') + + process.Continue() + # Process must be exited + test.assertEqual(process.GetState(), lldb.eStateExited) + + # The reason of this stop must be a breakpoint + test.assertEqual(process.GetSelectedThread().GetStopReason(), + lldb.eStopReasonNone) + + # + + # Delete all breakpoints, continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_bpmd_methoddesc.py b/src/ToolBox/SOS/tests/t_cmd_bpmd_methoddesc.py new file mode 100644 index 0000000..dfd7543 --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_bpmd_methoddesc.py @@ -0,0 +1,45 @@ +import lldb +import re +import testutils as test + +# bpmd -md + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + md_addr = test.get_methoddesc(debugger, assembly, "Test.UnlikelyInlined") + + ci.HandleCommand("bpmd -md %s" % md_addr, res) + out_msg = res.GetOutput() + err_msg = res.GetError() + print(out_msg) + print(err_msg) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + # Output is not empty + # Should be at least 'Adding pending breakpoints...' + test.assertTrue(len(out_msg) > 0) + + # Error message is empty + test.assertTrue(len(err_msg) == 0) + + process.Continue() + # Process must be stopped at UnlinkelyInlined + test.assertEqual(process.GetState(), lldb.eStateStopped) + + # The reason of this stop must be a breakpoint + test.assertEqual(process.GetSelectedThread().GetStopReason(), + lldb.eStopReasonBreakpoint) + + # + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_bpmd_module_function.py b/src/ToolBox/SOS/tests/t_cmd_bpmd_module_function.py new file mode 100644 index 0000000..e407ab3 --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_bpmd_module_function.py @@ -0,0 +1,43 @@ +import lldb +import re +import testutils as test + +# bpmd + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("bpmd " + assembly + " Test.UnlikelyInlined", res) + out_msg = res.GetOutput() + err_msg = res.GetError() + print(out_msg) + print(err_msg) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + # Output is not empty + # Should be at least 'Adding pending breakpoints...' + test.assertTrue(len(out_msg) > 0) + + # Error message is empty + test.assertTrue(len(err_msg) == 0) + + process.Continue() + # Process must be stopped at UnlinkelyInlined + test.assertEqual(process.GetState(), lldb.eStateStopped) + + # The reason of this stop must be a breakpoint + test.assertEqual(process.GetSelectedThread().GetStopReason(), + lldb.eStopReasonBreakpoint) + + # + + # Delete all breakpoints, continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_bpmd_module_function_iloffset.py b/src/ToolBox/SOS/tests/t_cmd_bpmd_module_function_iloffset.py new file mode 100644 index 0000000..91fb1cd --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_bpmd_module_function_iloffset.py @@ -0,0 +1,43 @@ +import lldb +import re +import testutils as test + +# bpmd [] + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("bpmd " + assembly + " Test.UnlikelyInlined 66", res) + out_msg = res.GetOutput() + err_msg = res.GetError() + print(out_msg) + print(err_msg) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + # Output is not empty + # Should be at least 'Adding pending breakpoints...' + test.assertTrue(len(out_msg) > 0) + + # Error message is empty + test.assertTrue(len(err_msg) == 0) + + process.Continue() + # Process must be stopped at UnlinkelyInlined + test.assertEqual(process.GetState(), lldb.eStateStopped) + + # The reason of this stop must be a breakpoint + test.assertEqual(process.GetSelectedThread().GetStopReason(), + lldb.eStopReasonBreakpoint) + + # + + # Delete all breakpoints, continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_bpmd_nofuturemodule_module_function.py b/src/ToolBox/SOS/tests/t_cmd_bpmd_nofuturemodule_module_function.py new file mode 100644 index 0000000..64efad7 --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_bpmd_nofuturemodule_module_function.py @@ -0,0 +1,48 @@ +import lldb +import re +import testutils as test + +# bpmd -nofuturemodule + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Process must be stopped here while libcoreclr loading. + # This test usually fails on release version of coreclr + # since we depend on 'LoadLibraryExW' symbol present. + test.assertEqual(process.GetState(), lldb.eStateStopped) + + # The reason of this stop must be a breakpoint + test.assertEqual(process.GetSelectedThread().GetStopReason(), + lldb.eStopReasonBreakpoint) + + ci.HandleCommand("bpmd -nofuturemodule " + assembly + " Test.Main", res) + out_msg = res.GetOutput() + err_msg = res.GetError() + print(out_msg) + print(err_msg) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + # Output is not empty + # Should be at least 'Adding pending breakpoints...' + test.assertTrue(len(out_msg) == 0) + + # Error message is empty + test.assertTrue(len(err_msg) == 0) + + process.Continue() + # Process must be exited because of -nofuturemodule flag + test.assertEqual(process.GetState(), lldb.eStateExited) + + # The reason of this stop must be a breakpoint + test.assertEqual(process.GetSelectedThread().GetStopReason(), + lldb.eStopReasonNone) + + # + + # Delete all breakpoints, continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_clrstack.py b/src/ToolBox/SOS/tests/t_cmd_clrstack.py new file mode 100644 index 0000000..28a1a8b --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_clrstack.py @@ -0,0 +1,36 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("clrstack", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + match = re.search('OS Thread Id', output) + # Specific string must be in the output + test.assertTrue(match) + + match = re.search('Failed to start', output) + # Check if a fail was reported + test.assertFalse(match) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_clrthreads.py b/src/ToolBox/SOS/tests/t_cmd_clrthreads.py new file mode 100644 index 0000000..ff731da --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_clrthreads.py @@ -0,0 +1,31 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("clrthreads", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + # Specific string must be in the output + test.assertNotEqual(output.find("ThreadCount:"), -1) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_clru.py b/src/ToolBox/SOS/tests/t_cmd_clru.py new file mode 100644 index 0000000..81a583e --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_clru.py @@ -0,0 +1,46 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("name2ee " + assembly + " Test.Main", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + match = re.search('JITTED Code Address:\s+([0-9a-fA-F]+)', output) + # Line matched + test.assertTrue(match) + + groups = match.groups() + # Match has a single subgroup + test.assertEqual(len(groups), 1) + + jit_addr = groups[0] + # Address must be a hex number + test.assertTrue(test.is_hexnum(jit_addr)) + + ci.HandleCommand("clru " + jit_addr, res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_dso.py b/src/ToolBox/SOS/tests/t_cmd_dso.py new file mode 100644 index 0000000..492204d --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_dso.py @@ -0,0 +1,31 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("dso", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + # Specific string must be in the output + test.assertNotEqual(output.find("SP/REG"), -1) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_dumpclass.py b/src/ToolBox/SOS/tests/t_cmd_dumpclass.py new file mode 100644 index 0000000..6a69070 --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_dumpclass.py @@ -0,0 +1,68 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("name2ee " + assembly + " Test.Main", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + match = re.search('MethodDesc:\s+([0-9a-fA-F]+)', output) + # Line matched + test.assertTrue(match) + + groups = match.groups() + # Match has a single subgroup + test.assertEqual(len(groups), 1) + + md_addr = groups[0] + # Address must be a hex number + test.assertTrue(test.is_hexnum(md_addr)) + + ci.HandleCommand("dumpmd " + md_addr, res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + match = re.search('Class:\s+([0-9a-fA-F]+)', output) + # Line matched + test.assertTrue(match) + + groups = match.groups() + # Match has a single subgroup + test.assertEqual(len(groups), 1) + + class_addr = groups[0] + # Address must be a hex number + test.assertTrue(test.is_hexnum(class_addr)) + + ci.HandleCommand("dumpmd " + class_addr, res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_dumpheap.py b/src/ToolBox/SOS/tests/t_cmd_dumpheap.py new file mode 100644 index 0000000..8546de7 --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_dumpheap.py @@ -0,0 +1,31 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("dumpheap", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + # Specific string must be in the output + test.assertNotEqual(output.find("Address"), -1) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_dumpil.py b/src/ToolBox/SOS/tests/t_cmd_dumpil.py new file mode 100644 index 0000000..295cf19 --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_dumpil.py @@ -0,0 +1,38 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + md_addr = test.get_methoddesc(debugger, assembly, "Test.DumpIL") + + ci.HandleCommand("dumpil " + md_addr, res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + insts = res.GetOutput() + print(insts) + # Function must have some instructions + test.assertTrue(len(insts) > 0) + + match = re.search(r'IL_\w{4}:\sldstr.*test\sdumpil.*' + + r'IL_\w{4}:\scall.*System\.Console::WriteLine.*' + + r'IL_\w{4}:\sret', + insts.replace('\n', ' ')) + # Must have ldstr, call and ret instructions + test.assertTrue(match) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_dumplog.py b/src/ToolBox/SOS/tests/t_cmd_dumplog.py new file mode 100644 index 0000000..ab33b66 --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_dumplog.py @@ -0,0 +1,31 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("dumplog", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + # Specific string must be in the output + test.assertNotEqual(output.find(" dump "), -1) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_dumpmd.py b/src/ToolBox/SOS/tests/t_cmd_dumpmd.py new file mode 100644 index 0000000..0340eb5 --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_dumpmd.py @@ -0,0 +1,46 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("name2ee " + assembly + " Test.Main", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + match = re.search('MethodDesc:\s+([0-9a-fA-F]+)', output) + # Line matched + test.assertTrue(match) + + groups = match.groups() + # Match has a single subgroup + test.assertEqual(len(groups), 1) + + md_addr = groups[0] + # Address must be a hex number + test.assertTrue(test.is_hexnum(md_addr)) + + ci.HandleCommand("dumpmd " + md_addr, res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_dumpmodule.py b/src/ToolBox/SOS/tests/t_cmd_dumpmodule.py new file mode 100644 index 0000000..2dd0048 --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_dumpmodule.py @@ -0,0 +1,46 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("name2ee " + assembly + " Test.Main", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + match = re.search('Module:\s+([0-9a-fA-F]+)', output) + # Line matched + test.assertTrue(match) + + groups = match.groups() + # Match has a single subgroup + test.assertEqual(len(groups), 1) + + md_addr = groups[0] + # Address must be a hex number + test.assertTrue(test.is_hexnum(md_addr)) + + ci.HandleCommand("dumpmodule " + md_addr, res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_dumpmt.py b/src/ToolBox/SOS/tests/t_cmd_dumpmt.py new file mode 100644 index 0000000..059060b --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_dumpmt.py @@ -0,0 +1,68 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("name2ee " + assembly + " Test.Main", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + match = re.search('MethodDesc:\s+([0-9a-fA-F]+)', output) + # Line matched + test.assertTrue(match) + + groups = match.groups() + # Match has a single subgroup + test.assertEqual(len(groups), 1) + + md_addr = groups[0] + # Address must be a hex number + test.assertTrue(test.is_hexnum(md_addr)) + + ci.HandleCommand("dumpmd " + md_addr, res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + match = re.search('MethodTable:\s+([0-9a-fA-F]+)', output) + # Line matched + test.assertTrue(match) + + groups = match.groups() + # Match has a single subgroup + test.assertEqual(len(groups), 1) + + mt_addr = groups[0] + # Address must be a hex number + test.assertTrue(test.is_hexnum(mt_addr)) + + ci.HandleCommand("dumpmt " + mt_addr, res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_dumpobj.py b/src/ToolBox/SOS/tests/t_cmd_dumpobj.py new file mode 100644 index 0000000..93f32cd --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_dumpobj.py @@ -0,0 +1,69 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("dso", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + # Get all objects + objects = [] + for line in output.split('\n'): + match = re.match('([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s', line) + # Not all lines list objects + if match: + groups = match.groups() + # Match has exactly two subgroups + test.assertEqual(len(groups), 2) + + obj_addr = groups[1] + # Address must be a hex number + test.assertTrue(test.is_hexnum(obj_addr)) + + objects.append(obj_addr) + + # There must be at least one object + test.assertTrue(len(objects) > 0) + + for obj in objects: + ci.HandleCommand("dumpobj " + obj, res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + match = re.search('Name:\s+\S+', output) + test.assertTrue(match) + match = re.search('MethodTable:\s+[0-9a-fA-F]+', output) + test.assertTrue(match) + match = re.search('EEClass:\s+[0-9a-fA-F]+', output) + test.assertTrue(match) + match = re.search('Size:\s+[0-9a-fA-F]+', output) + test.assertTrue(match) + match = re.search('Fields:', output) + test.assertTrue(match) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_dumpstack.py b/src/ToolBox/SOS/tests/t_cmd_dumpstack.py new file mode 100644 index 0000000..3e15f8b --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_dumpstack.py @@ -0,0 +1,31 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("dumpstack", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + # Specific string must be in the output + test.assertNotEqual(output.find("Test.Main()"), -1) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_eeheap.py b/src/ToolBox/SOS/tests/t_cmd_eeheap.py new file mode 100644 index 0000000..50d8977 --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_eeheap.py @@ -0,0 +1,31 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("eeheap", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + # Specific string must be in the output + test.assertNotEqual(output.find("Loader Heap"), -1) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_eestack.py b/src/ToolBox/SOS/tests/t_cmd_eestack.py new file mode 100644 index 0000000..bc36592 --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_eestack.py @@ -0,0 +1,31 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("eestack", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + # Specific string must be in the output + test.assertNotEqual(output.find("Current frame"), -1) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_gcroot.py b/src/ToolBox/SOS/tests/t_cmd_gcroot.py new file mode 100644 index 0000000..e6b727c --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_gcroot.py @@ -0,0 +1,61 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("dso", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + # Get all objects + objects = [] + for line in output.split('\n'): + match = re.match('([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s', line) + # Not all lines list objects + if match: + groups = match.groups() + # Match has exactly two subgroups + test.assertEqual(len(groups), 2) + + obj_addr = groups[1] + # Address must be a hex number + test.assertTrue(test.is_hexnum(obj_addr)) + + objects.append(obj_addr) + + # There must be at least one object + test.assertTrue(len(objects) > 0) + + for obj in objects: + ci.HandleCommand("gcroot " + obj, res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + match = re.search('Found', output) + test.assertTrue(match) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_histclear.py b/src/ToolBox/SOS/tests/t_cmd_histclear.py new file mode 100644 index 0000000..db29bd8 --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_histclear.py @@ -0,0 +1,31 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("histclear", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + # Specific string must be in the output + test.assertNotEqual(output.find("Completed successfully."), -1) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_histinit.py b/src/ToolBox/SOS/tests/t_cmd_histinit.py new file mode 100644 index 0000000..5119128 --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_histinit.py @@ -0,0 +1,31 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("histinit", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + # Specific string must be in the output + test.assertNotEqual(output.find("STRESS LOG:"), -1) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_histobj.py b/src/ToolBox/SOS/tests/t_cmd_histobj.py new file mode 100644 index 0000000..c88bdac --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_histobj.py @@ -0,0 +1,61 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("dso", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + # Get all objects + objects = [] + for line in output.split('\n'): + match = re.match('([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s', line) + # Not all lines list objects + if match: + groups = match.groups() + # Match has exactly two subgroups + test.assertEqual(len(groups), 2) + + obj_addr = groups[1] + # Address must be a hex number + test.assertTrue(test.is_hexnum(obj_addr)) + + objects.append(obj_addr) + + # There must be at least one object + test.assertTrue(len(objects) > 0) + + for obj in objects: + ci.HandleCommand("histobj " + obj, res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + match = re.search('GCCount', output) + test.assertTrue(match) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_histobjfind.py b/src/ToolBox/SOS/tests/t_cmd_histobjfind.py new file mode 100644 index 0000000..ffe5dbf --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_histobjfind.py @@ -0,0 +1,61 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("dso", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + # Get all objects + objects = [] + for line in output.split('\n'): + match = re.match('([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s', line) + # Not all lines list objects + if match: + groups = match.groups() + # Match has exactly two subgroups + test.assertEqual(len(groups), 2) + + obj_addr = groups[1] + # Address must be a hex number + test.assertTrue(test.is_hexnum(obj_addr)) + + objects.append(obj_addr) + + # There must be at least one object + test.assertTrue(len(objects) > 0) + + for obj in objects: + ci.HandleCommand("histobjfind " + obj, res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + match = re.search('GCCount', output) + test.assertTrue(match) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_histroot.py b/src/ToolBox/SOS/tests/t_cmd_histroot.py new file mode 100644 index 0000000..7b73caa --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_histroot.py @@ -0,0 +1,61 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("dso", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + # Get all objects + objects = [] + for line in output.split('\n'): + match = re.match('([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s', line) + # Not all lines list objects + if match: + groups = match.groups() + # Match has exactly two subgroups + test.assertEqual(len(groups), 2) + + obj_addr = groups[1] + # Address must be a hex number + test.assertTrue(test.is_hexnum(obj_addr)) + + objects.append(obj_addr) + + # There must be at least one object + test.assertTrue(len(objects) > 0) + + for obj in objects: + ci.HandleCommand("histroot " + obj, res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + match = re.search('GCCount', output) + test.assertTrue(match) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_ip2md.py b/src/ToolBox/SOS/tests/t_cmd_ip2md.py new file mode 100644 index 0000000..1384c38 --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_ip2md.py @@ -0,0 +1,53 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("name2ee " + assembly + " Test.Main", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + match = re.search('JITTED Code Address:\s+([0-9a-fA-F]+)', output) + # Line matched + test.assertTrue(match) + + groups = match.groups() + # Match has a single subgroup + test.assertEqual(len(groups), 1) + + jit_addr = groups[0] + # Address must be a hex number + test.assertTrue(test.is_hexnum(jit_addr)) + + ci.HandleCommand("ip2md " + jit_addr, res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + # Specific string must be in the output + test.assertNotEqual(output.find("MethodDesc:"), -1) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_name2ee.py b/src/ToolBox/SOS/tests/t_cmd_name2ee.py new file mode 100644 index 0000000..b617020 --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_name2ee.py @@ -0,0 +1,46 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("name2ee " + assembly + " Test.Main", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + match = re.search('Module:\s+[0-9a-fA-F]+', output) + test.assertTrue(match) + match = re.search('Assembly:\s+\S+', output) + test.assertTrue(match) + match = re.search('Token:\s+[0-9a-fA-F]+', output) + test.assertTrue(match) + match = re.search('MethodDesc:\s+[0-9a-fA-F]+', output) + test.assertTrue(match) + match = re.search('Name:\s+\S+', output) + test.assertTrue(match) + + process.Continue() + # Process must exit + test.assertEqual(process.GetState(), lldb.eStateExited) + + # Process must exit with zero code + test.assertEqual(process.GetExitStatus(), 0) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_pe.py b/src/ToolBox/SOS/tests/t_cmd_pe.py new file mode 100644 index 0000000..0a87014 --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_pe.py @@ -0,0 +1,28 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("dso", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_sos.py b/src/ToolBox/SOS/tests/t_cmd_sos.py new file mode 100644 index 0000000..b407491 --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_sos.py @@ -0,0 +1,31 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("sos", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + # Specific string must be in the output + test.assertNotEqual(output.find("SOS"), -1) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/t_cmd_soshelp.py b/src/ToolBox/SOS/tests/t_cmd_soshelp.py new file mode 100644 index 0000000..8bb51da --- /dev/null +++ b/src/ToolBox/SOS/tests/t_cmd_soshelp.py @@ -0,0 +1,31 @@ +import lldb +import re +import testutils as test + + +def runScenario(assembly, debugger, target): + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + ci = debugger.GetCommandInterpreter() + + # Run debugger, wait until libcoreclr is loaded, + # set breakpoint at Test.Main and stop there + test.stop_in_main(debugger, assembly) + + ci.HandleCommand("soshelp", res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + test.assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + test.assertTrue(len(output) > 0) + + # Specific string must be in the output + test.assertNotEqual(output.find("soshelp "), -1) + + # TODO: test other use cases + + # Continue current process and checks its exit code + test.exit_lldb(debugger, assembly) diff --git a/src/ToolBox/SOS/tests/test_libsosplugin.py b/src/ToolBox/SOS/tests/test_libsosplugin.py index e4f59eb..e5a5906 100644 --- a/src/ToolBox/SOS/tests/test_libsosplugin.py +++ b/src/ToolBox/SOS/tests/test_libsosplugin.py @@ -1,3 +1,4 @@ +from __future__ import print_function import unittest import argparse import re @@ -5,80 +6,279 @@ import tempfile import subprocess import threading import os -import os.path import sys +import inspect + +lldb = '' +clrdir = '' +workdir = '' +corerun = '' +sosplugin = '' +assembly = '' +fail_flag = '' +fail_flag_lldb = '' +summary_file = '' +timeout = 0 +regex = '' +repeat = 0 + + +def runWithTimeout(cmd): + p = None + + def run(): + global p + p = subprocess.Popen(cmd, shell=True) + p.communicate() + + thread = threading.Thread(target=run) + thread.start() + + thread.join(timeout) + if thread.is_alive(): + with open(summary_file, 'a+') as summary: + print('Timeout!', file=summary) + p.kill() + thread.join() + -assemblyName='' -clrArgs='' -fail_flag='/tmp/fail_flag' - -# helper functions - -def prepareScenarioFile(moduleName): - global assemblyName - #create a temporary scenario file - fd, scenarioFileName = tempfile.mkstemp() - scenarioFile = open(scenarioFileName, 'w') - scenarioFile.write('script from runprocess import run\n') - scenarioFile.write('script run("'+assemblyName+'", "'+moduleName+'")\n') - scenarioFile.write('quit\n') - scenarioFile.close() - os.close(fd) - return scenarioFileName - -def runWithTimeout(cmd, timeout): - d = {'process': None} - def run(): - d['process'] = subprocess.Popen(cmd, shell=True) - d['process'].communicate() - - thread = threading.Thread(target=run) - thread.start() - - thread.join(timeout) - if thread.is_alive(): - d['process'].terminate() - thread.join() - -# Test class class TestSosCommands(unittest.TestCase): - def do_test(self, command): - global clrArgs - global fail_flag - filename = prepareScenarioFile(command) - cmd = "lldb --source "+filename+" -b -K \"OnCrash.do\" -- "+clrArgs+" > "+command+".log 2>"+command+".log.2" - runWithTimeout(cmd, 120) - self.assertFalse(os.path.isfile(fail_flag)) - os.unlink(filename) + def do_test(self, command): + open(fail_flag, 'a').close() + try: + os.unlink(fail_flag_lldb) + except: + pass + + cmd = (('%s -b ' % lldb) + + ("-k \"script open('%s', 'a').close()\" " % fail_flag_lldb) + + ("-k 'quit' ") + + ("--no-lldbinit ") + + ("-O \"plugin load %s \" " % sosplugin) + + ("-o \"script import testutils as test\" ") + + ("-o \"script test.fail_flag = '%s'\" " % fail_flag) + + ("-o \"script test.summary_file = '%s'\" " % summary_file) + + ("-o \"script test.run('%s', '%s')\" " % (assembly, command)) + + ("-o \"quit\" ") + + (" -- %s %s > %s.log 2> %s.log.2" % (corerun, assembly, + command, command))) + + runWithTimeout(cmd) + self.assertFalse(os.path.isfile(fail_flag)) + self.assertFalse(os.path.isfile(fail_flag_lldb)) + + try: + os.unlink(fail_flag) + except: + pass + try: + os.unlink(fail_flag_lldb) + except: + pass + + def t_cmd_bpmd_nofuturemodule_module_function(self): + self.do_test('t_cmd_bpmd_nofuturemodule_module_function') + + def t_cmd_bpmd_module_function(self): + self.do_test('t_cmd_bpmd_module_function') + + def t_cmd_bpmd_module_function_iloffset(self): + self.do_test('t_cmd_bpmd_module_function_iloffset') + + def t_cmd_bpmd_methoddesc(self): + self.do_test('t_cmd_bpmd_methoddesc') + + def t_cmd_bpmd_clearall(self): + self.do_test('t_cmd_bpmd_clearall') + + def t_cmd_clrstack(self): + self.do_test('t_cmd_clrstack') + + def t_cmd_clrthreads(self): + self.do_test('t_cmd_clrthreads') + + def t_cmd_clru(self): + self.do_test('t_cmd_clru') + + def t_cmd_dumpclass(self): + self.do_test('t_cmd_dumpclass') + + def t_cmd_dumpheap(self): + self.do_test('t_cmd_dumpheap') + + def t_cmd_dumpil(self): + self.do_test('t_cmd_dumpil') + + def t_cmd_dumplog(self): + self.do_test('t_cmd_dumplog') + + def t_cmd_dumpmd(self): + self.do_test('t_cmd_dumpmd') + + def t_cmd_dumpmodule(self): + self.do_test('t_cmd_dumpmodule') + + def t_cmd_dumpmt(self): + self.do_test('t_cmd_dumpmt') + + def t_cmd_dumpobj(self): + self.do_test('t_cmd_dumpobj') + + def t_cmd_dumpstack(self): + self.do_test('t_cmd_dumpstack') + + def t_cmd_dso(self): + self.do_test('t_cmd_dso') + + def t_cmd_eeheap(self): + self.do_test('t_cmd_eeheap') - def test_dumpmodule(self): - self.do_test("dumpmodule") + def t_cmd_eestack(self): + self.do_test('t_cmd_eestack') + + def t_cmd_gcroot(self): + self.do_test('t_cmd_gcroot') + + def t_cmd_ip2md(self): + self.do_test('t_cmd_ip2md') + + def t_cmd_name2ee(self): + self.do_test('t_cmd_name2ee') + + def t_cmd_pe(self): + self.do_test('t_cmd_pe') + + def t_cmd_histclear(self): + self.do_test('t_cmd_histclear') + + def t_cmd_histinit(self): + self.do_test('t_cmd_histinit') + + def t_cmd_histobj(self): + self.do_test('t_cmd_histobj') + + def t_cmd_histobjfind(self): + self.do_test('t_cmd_histobjfind') + + def t_cmd_histroot(self): + self.do_test('t_cmd_histroot') + + def t_cmd_sos(self): + self.do_test('t_cmd_sos') + + def t_cmd_soshelp(self): + self.do_test('t_cmd_soshelp') + + +def generate_report(): + report = [{'name': 'TOTAL', True: 0, False: 0, 'completed': True}] + fail_messages = [] + + if not os.path.isfile(summary_file): + print('No summary file to process!') + return + + with open(summary_file, 'r') as summary: + for line in summary: + if line.startswith('new_suite: '): + report.append({'name': line.split()[-1], True: 0, False: 0, + 'completed': False, 'timeout': False}) + elif line.startswith('True'): + report[-1][True] += 1 + elif line.startswith('False'): + report[-1][False] += 1 + elif line.startswith('Completed!'): + report[-1]['completed'] = True + elif line.startswith('Timeout!'): + report[-1]['timeout'] = True + elif line.startswith('!!! '): + fail_messages.append(line.rstrip('\n')) + + for suite in report[1:]: + report[0][True] += suite[True] + report[0][False] += suite[False] + report[0]['completed'] &= suite['completed'] + + for line in fail_messages: + print(line) + + print() + print('=' * 79) + print('{:72} {:6}'.format('Test suite', 'Result')) + print('-' * 79) + for suite in report[1:]: + if suite['timeout']: + result = 'Timeout' + elif suite[False]: + result = 'Fail' + elif not suite['completed']: + result = 'Crash' + elif suite[True]: + result = 'Success' + else: + result = 'Please, report' + print('{:68} {:>10}'.format(suite['name'], result)) + print('=' * 79) - def test_dumpil(self): - self.do_test("dumpil") - if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('--clr-args', default='') - parser.add_argument('unittest_args', nargs='*') - - args = parser.parse_args() - - clrArgs = args.clr_args - print("ClrArgs: " + clrArgs) - # find assembly name among lldb arguments - assembly_regexp = re.compile("([^\s]+\.exe)") - assemblyMatch = assembly_regexp.search(clrArgs) - if assemblyMatch is not None: - assemblyName = assemblyMatch.group(1) - else: - print("Assembly not recognized") - exit(1) - - print("Assembly name: "+assemblyName) - sys.argv[1:] = args.unittest_args - suite = unittest.TestLoader().loadTestsFromTestCase(TestSosCommands) - unittest.TextTestRunner(verbosity=2).run(suite) - os.unlink(fail_flag) \ No newline at end of file + parser = argparse.ArgumentParser() + parser.add_argument('--lldb', default='lldb') + parser.add_argument('--clrdir', default='.') + parser.add_argument('--workdir', default='.') + parser.add_argument('--assembly', default='Test.exe') + parser.add_argument('--timeout', default=90) + parser.add_argument('--regex', default='t_cmd_') + parser.add_argument('--repeat', default=1) + parser.add_argument('unittest_args', nargs='*') + + args = parser.parse_args() + + lldb = args.lldb + clrdir = args.clrdir + workdir = args.workdir + assembly = args.assembly + timeout = int(args.timeout) + regex = args.regex + repeat = int(args.repeat) + print("lldb: %s" % lldb) + print("clrdir: %s" % clrdir) + print("workdir: %s" % workdir) + print("assembly: %s" % assembly) + print("timeout: %i" % timeout) + print("regex: %s" % regex) + print("repeat: %i" % repeat) + + corerun = os.path.join(clrdir, 'corerun') + sosplugin = os.path.join(clrdir, 'libsosplugin.so') + if os.name != 'posix': + print('Not implemented: corerun.exe, sosplugin.dll?') + exit(1) + + print("corerun: %s" % corerun) + print("sosplugin: %s" % sosplugin) + + fail_flag = os.path.join(workdir, 'fail_flag') + fail_flag_lldb = os.path.join(workdir, 'fail_flag.lldb') + + print("fail_flag: %s" % fail_flag) + print("fail_flag_lldb: %s" % fail_flag_lldb) + + summary_file = os.path.join(workdir, 'summary') + print("summary_file: %s" % summary_file) + + try: + os.unlink(summary_file) + except: + pass + + sys.argv[1:] = args.unittest_args + suite = unittest.TestSuite() + all_tests = inspect.getmembers(TestSosCommands, predicate=inspect.ismethod) + for (test_name, test_func) in all_tests: + if re.match(regex, test_name): + suite.addTest(TestSosCommands(test_name)) + unittest.TextTestRunner(verbosity=1).run(suite) + + generate_report() diff --git a/src/ToolBox/SOS/tests/testutils.py b/src/ToolBox/SOS/tests/testutils.py index 1ddb656..1f784b4 100644 --- a/src/ToolBox/SOS/tests/testutils.py +++ b/src/ToolBox/SOS/tests/testutils.py @@ -1,40 +1,206 @@ +from __future__ import print_function import lldb import re +import inspect +import sys +import os +import importlib + +summary_file = '' +fail_flag = '' + +failed = False + + +def assertCommon(passed, fatal): + global failed + with open(summary_file, 'a+') as summary: + print(bool(passed), file=summary) + if (not passed): + failed = True + print('!!! test failed:', file=summary) + for s in inspect.stack()[2:]: + print("!!! %s:%i" % (s[1], s[2]), file=summary) + print("!!! %s" % s[4][0], file=summary) + if re.match('\W*t_\w+\.py$', s[1]): + break + print('!!! ', file=summary) + + if fatal: + exit(1) + + +def assertTrue(x, fatal=True): + passed = bool(x) + assertCommon(passed, fatal) + + +def assertFalse(x, fatal=True): + passed = not bool(x) + assertCommon(passed, fatal) + + +def assertEqual(x, y, fatal=True): + passed = (x == y) + if not passed: + print(str(x), ' != ', str(y)) + assertCommon(passed, fatal) + + +def assertNotEqual(x, y, fatal=True): + passed = (x != y) + if not passed: + print(str(x), ' == ', str(y)) + assertCommon(passed, fatal) + def checkResult(res): - if not res.Succeeded(): - print(res.GetOutput()) - print(res.GetError()) - exit(1) + if not res.Succeeded(): + print(res.GetOutput()) + print(res.GetError()) + exit(1) + + +def is_hexnum(s): + try: + int(s, 16) + return True + except ValueError: + return False + def exec_and_find(commandInterpreter, cmd, regexp): - res = lldb.SBCommandReturnObject() - commandInterpreter.HandleCommand(cmd, res) - checkResult(res) - - expr = re.compile(regexp) - addr = None - - print(res.GetOutput()) - lines = res.GetOutput().splitlines() - for line in lines: - match = expr.match(line) - if match is not None: - addr = match.group(1) - break - - print("Found addr: " + str(addr)) - return addr - -def stop_in_main(commandInterpreter, process, assemblyName): - res = lldb.SBCommandReturnObject() - commandInterpreter.HandleCommand("bpmd " + assemblyName + " Program.Main", res) - checkResult(res) - print(res.GetOutput()) - print(res.GetError()) - res.Clear() - - - # Use Python API to continue the process. The listening thread should be - # able to receive the state changed events. - process.Continue() \ No newline at end of file + res = lldb.SBCommandReturnObject() + commandInterpreter.HandleCommand(cmd, res) + checkResult(res) + + expr = re.compile(regexp) + addr = None + + print(res.GetOutput()) + lines = res.GetOutput().splitlines() + for line in lines: + match = expr.match(line) + if match: + addr = match.group(1) + break + + print("Found addr: " + str(addr)) + return addr + + +def stop_in_main(debugger, assembly): + ci = debugger.GetCommandInterpreter() + target = debugger.GetSelectedTarget() + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + + # Process must be stopped here while libcoreclr loading. + # This test usually fails on release version of coreclr + # since we depend on 'LoadLibraryExW' symbol present. + assertEqual(process.GetState(), lldb.eStateStopped) + + # The reason of this stop must be a breakpoint + assertEqual(process.GetSelectedThread().GetStopReason(), + lldb.eStopReasonBreakpoint) + + ci.HandleCommand("bpmd " + assembly + " Test.Main", res) + out_msg = res.GetOutput() + err_msg = res.GetError() + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + assertTrue(res.Succeeded()) + + # Output is not empty + # Should be at least 'Adding pending breakpoints...' + assertTrue(len(out_msg) > 0) + + # Error message is empty + assertTrue(len(err_msg) == 0) + + process.Continue() + # Process must be stopped here if bpmd works at all + assertEqual(process.GetState(), lldb.eStateStopped) + + # The reason of this stop must be a breakpoint + assertEqual(process.GetSelectedThread().GetStopReason(), + lldb.eStopReasonBreakpoint) + + +def exit_lldb(debugger, assembly): + ci = debugger.GetCommandInterpreter() + target = debugger.GetSelectedTarget() + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + + ci.HandleCommand("breakpoint delete --force", res) + out_msg = res.GetOutput() + err_msg = res.GetError() + print(out_msg) + print(err_msg) + # Interpreter must have this command and able to run it + # assertTrue(res.Succeeded()) + + process.Continue() + # Process must exit + assertEqual(process.GetState(), lldb.eStateExited) + + # Process must exit with zero code + assertEqual(process.GetExitStatus(), 0) + + +def get_methoddesc(debugger, assembly, funcname): + ci = debugger.GetCommandInterpreter() + target = debugger.GetSelectedTarget() + process = target.GetProcess() + res = lldb.SBCommandReturnObject() + + ci.HandleCommand("name2ee %s %s" % (assembly, funcname), res) + print(res.GetOutput()) + print(res.GetError()) + # Interpreter must have this command and able to run it + assertTrue(res.Succeeded()) + + output = res.GetOutput() + # Output is not empty + assertTrue(len(output) > 0) + + match = re.search('MethodDesc:\s+([0-9a-fA-F]+)', output) + # Line matched + assertTrue(match) + + groups = match.groups() + # Match has a single subgroup + assertEqual(len(groups), 1) + + md_addr = groups[0] + # Address must be a hex number + assertTrue(is_hexnum(md_addr)) + + return md_addr + + +def run(assembly, module): + with open(summary_file, 'a+') as summary: + print('new_suite: %s' % module, file=summary) + + debugger = lldb.debugger + + debugger.SetAsync(False) + target = lldb.target + + debugger.HandleCommand("breakpoint set --one-shot --name coreclr_execute_assembly") + debugger.HandleCommand("process launch") + + # run the scenario + print("starting scenario...") + i = importlib.import_module(module) + scenarioResult = i.runScenario(os.path.basename(assembly), debugger, + target) + + if (target.GetProcess().GetExitStatus() == 0) and not failed: + os.unlink(fail_flag) + + with open(summary_file, 'a+') as summary: + print('Completed!', file=summary) diff --git a/src/ToolBox/dirs.proj b/src/ToolBox/dirs.proj index 9ac295d..e16ddd1 100644 --- a/src/ToolBox/dirs.proj +++ b/src/ToolBox/dirs.proj @@ -79,7 +79,9 @@ + PK diff --git a/src/ToolBox/superpmi/superpmi-shared/compileresult.h b/src/ToolBox/superpmi/superpmi-shared/compileresult.h index 8fc3f7a..87853f4 100644 --- a/src/ToolBox/superpmi/superpmi-shared/compileresult.h +++ b/src/ToolBox/superpmi/superpmi-shared/compileresult.h @@ -203,7 +203,7 @@ public: void recReportInliningDecision(CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd, CorInfoInline inlineResult, const char * reason); void dmpReportInliningDecision(DWORD key, const Agnostic_ReportInliningDecision& value); - CorInfoInline CompileResult::repReportInliningDecision(CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd); + CorInfoInline repReportInliningDecision(CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd); void recSetEHcount(unsigned cEH); void dmpSetEHcount(DWORD key, DWORD value); diff --git a/src/ToolBox/superpmi/superpmi-shared/icorjitcompilerimpl.h b/src/ToolBox/superpmi/superpmi-shared/icorjitcompilerimpl.h index 671b45b..e1190d7 100644 --- a/src/ToolBox/superpmi/superpmi-shared/icorjitcompilerimpl.h +++ b/src/ToolBox/superpmi/superpmi-shared/icorjitcompilerimpl.h @@ -57,7 +57,11 @@ public: // When the EE loads the System.Numerics.Vectors assembly, it asks the JIT what length (in bytes) of // SIMD vector it supports as an intrinsic type. Zero means that the JIT does not support SIMD // intrinsics, so the EE should use the default size (i.e. the size of the IL implementation). +#if COR_JIT_EE_VERSION > 460 + unsigned getMaxIntrinsicSIMDVectorLength(CORJIT_FLAGS cpuCompileFlags); /* { return 0; } */ +#else unsigned getMaxIntrinsicSIMDVectorLength(DWORD cpuCompileFlags); /* { return 0; } */ +#endif // IL obfuscators sometimes interpose on the EE-JIT interface. This function allows the VM to // tell the JIT to use a particular ICorJitCompiler to implement the methods of this interface, diff --git a/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h b/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h index 6eb862c..b847d9b 100644 --- a/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h +++ b/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h @@ -653,7 +653,7 @@ public: // in the code are. The native compiler will ensure that these places // have a corresponding break point in native code. // - // Note that unless CORJIT_FLG_DEBUG_CODE is specified, this function will + // Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will // be used only as a hint and the native compiler should not change its // code generation. void getBoundaries( @@ -683,7 +683,7 @@ public: // under debugging, the JIT needs to keep them live over their // entire scope so that they can be inspected. // - // Note that unless CORJIT_FLG_DEBUG_CODE is specified, this function will + // Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will // be used only as a hint and the native compiler should not change its // code generation. void getVars( diff --git a/src/ToolBox/superpmi/superpmi-shared/logging.cpp b/src/ToolBox/superpmi/superpmi-shared/logging.cpp index 5f7aa48..69c321b 100644 --- a/src/ToolBox/superpmi/superpmi-shared/logging.cpp +++ b/src/ToolBox/superpmi/superpmi-shared/logging.cpp @@ -262,9 +262,9 @@ void Logger::LogVprintf(const char *function, const char *file, int line, const char *timeStr = ""; #endif // FEATURE_PAL - const char *logEntryFmtStr = "%s - %s [%s:%d] - %s - %s\r\n"; - size_t logEntryBuffSize = _snprintf(nullptr, 0, logEntryFmtStr, - timeStr, function, file, line, logLevelStr, fullMsg) + 1; + const char logEntryFmtStr[] = "%s - %s [%s:%d] - %s - %s\r\n"; + size_t logEntryBuffSize = sizeof(logEntryFmtStr) + strlen(timeStr) + strlen(function) + + strlen(file) + 10 + strlen(logLevelStr) + strlen(fullMsg); char *logEntry = new char[logEntryBuffSize]; sprintf_s(logEntry, logEntryBuffSize, logEntryFmtStr, diff --git a/src/ToolBox/superpmi/superpmi-shared/lwmlist.h b/src/ToolBox/superpmi/superpmi-shared/lwmlist.h index 774e732..de0db3a 100644 --- a/src/ToolBox/superpmi/superpmi-shared/lwmlist.h +++ b/src/ToolBox/superpmi/superpmi-shared/lwmlist.h @@ -85,6 +85,7 @@ LWM(GetFunctionFixedEntryPoint, DWORDLONG, Agnostic_CORINFO_CONST_LOOKUP) LWM(GetGSCookie, DWORD, DLDL) LWM(GetHelperFtn, DWORD, DLDL) LWM(GetHelperName, DWORD, DWORD) +LWM(GetHFAType, DWORDLONG, DWORD) LWM(GetInlinedCallFrameVptr, DWORD, DLDL) LWM(GetIntConfigValue, Agnostic_ConfigIntInfo, DWORD) LWM(GetIntrinsicID, DWORDLONG, DD) diff --git a/src/ToolBox/superpmi/superpmi-shared/mclist.cpp b/src/ToolBox/superpmi/superpmi-shared/mclist.cpp index 6a6f870..511893f 100644 --- a/src/ToolBox/superpmi/superpmi-shared/mclist.cpp +++ b/src/ToolBox/superpmi/superpmi-shared/mclist.cpp @@ -237,7 +237,7 @@ void MCList::AddMethodToMCL(int methodIndex) DWORD charCount = 0; DWORD bytesWritten = 0; - charCount = sprintf(strMethodIndex, "%d\r\n", methodIndex); + charCount = sprintf_s(strMethodIndex, sizeof(strMethodIndex), "%d\r\n", methodIndex); if (!WriteFile(hMCLFile, strMethodIndex, charCount, &bytesWritten, nullptr) || bytesWritten != charCount) { diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp index 2c46065..5768d38 100644 --- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp @@ -744,7 +744,7 @@ void MethodContext::recCompileMethod(CORINFO_METHOD_INFO *info, unsigned flags) void MethodContext::dmpCompileMethod(DWORD key, const Agnostic_CompileMethod& value) { printf("CompiledMethod key %u, value ftn-%016llX scp-%016llX ilo-%u ils-%u ms-%u ehc-%u opt-%u rk-%u " - "args{cc-%u rc-%016llX rts-%016llX rt-%u(%s) flg-%08X nA-%u cc-%u ci-%u mc-%u mi-%u arg-%016llX cb-%u pSig-%u scp-%016llX tok-%08X} " + "args{cc-%u rc-%016llX rts-%016llX rt-%u(%s) flg-%08X nA-%u cc-%u ci-%u mc-%u mi-%u arg-%016llX cb-%u pSig-%u scp-%016llX tok-%08X} " "locals{cc-%u rc-%016llX rts-%016llX rt-%u(%s) flg-%08X nA-%u cc-%u ci-%u mc-%u mi-%u arg-%016llX cb-%u pSig-%u scp-%016llX tok-%08X} " "flg-%08X", key, @@ -1098,8 +1098,8 @@ void MethodContext::recGetJitFlags(CORJIT_FLAGS *jitFlags, DWORD sizeInBytes, DW } void MethodContext::dmpGetJitFlags(DWORD key, DD value) { - CORJIT_FLAGS *flags = (CORJIT_FLAGS*)GetJitFlags->GetBuffer(value.A); - printf("GetJitFlags key %u sizeInBytes-%u corJitFlags-%08X corJitFlags2-%08X", key, value.B, flags->corJitFlags, flags->corJitFlags2); + CORJIT_FLAGS *jitflags = (CORJIT_FLAGS*)GetJitFlags->GetBuffer(value.A); + printf("GetJitFlags key %u sizeInBytes-%u jitFlags-%016llX", key, value.B, jitflags->GetFlagsRaw()); GetJitFlags->Unlock(); } DWORD MethodContext::repGetJitFlags(CORJIT_FLAGS *jitFlags, DWORD sizeInBytes) @@ -2842,6 +2842,34 @@ CORINFO_CLASS_HANDLE MethodContext::repGetArgClass(CORINFO_SIG_INFO* sig, CORINF return (CORINFO_CLASS_HANDLE)value.result; } +void MethodContext::recGetHFAType(CORINFO_CLASS_HANDLE clsHnd, CorInfoType result) +{ + if (GetHFAType == nullptr) + GetHFAType = new LightWeightMap(); + + GetHFAType->Add((DWORDLONG)clsHnd, (DWORD)result); + DEBUG_REC(dmpGetHFAType((DWORDLONG)clsHnd, (DWORD)result)); + return; +} + +void MethodContext::dmpGetHFAType(DWORDLONG key, DWORD value) +{ + printf("GetHFAType key %016llX, value %u ", key, value); + return; +} + +CorInfoType MethodContext::repGetHFAType(CORINFO_CLASS_HANDLE clsHnd) +{ + DWORD value; + + AssertCodeMsg(GetHFAType != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX", (DWORDLONG)clsHnd); + AssertCodeMsg(GetHFAType->GetIndex((DWORDLONG)clsHnd) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX", (DWORDLONG)clsHnd); + + value = GetHFAType->Get((DWORDLONG)clsHnd); + DEBUG_REP(dmpGetHFAType((DWORDLONG)clsHnd, value)); + return (CorInfoType)value; +} + void MethodContext::recGetMethodInfo(CORINFO_METHOD_HANDLE ftn, CORINFO_METHOD_INFO *info, bool result, DWORD exceptionCode) { if (GetMethodInfo == nullptr) diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontext.h b/src/ToolBox/superpmi/superpmi-shared/methodcontext.h index 5869c85..0d49666 100644 --- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.h +++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.h @@ -513,9 +513,9 @@ public: void dmpGetMethodName(DLD key, DD value); const char *repGetMethodName(CORINFO_METHOD_HANDLE ftn, const char **moduleName); - void MethodContext::recGetJitFlags(CORJIT_FLAGS *jitFlags, DWORD sizeInBytes, DWORD result); - void MethodContext::dmpGetJitFlags(DWORD key, DD value); - DWORD MethodContext::repGetJitFlags(CORJIT_FLAGS *jitFlags, DWORD sizeInBytes); + void recGetJitFlags(CORJIT_FLAGS *jitFlags, DWORD sizeInBytes, DWORD result); + void dmpGetJitFlags(DWORD key, DD value); + DWORD repGetJitFlags(CORJIT_FLAGS *jitFlags, DWORD sizeInBytes); void recGetJitTimeLogFilename(LPCWSTR tempFileName); void dmpGetJitTimeLogFilename(DWORD key, DWORD value); @@ -674,6 +674,10 @@ public: void dmpGetArgClass(const Agnostic_GetArgClass& key, const Agnostic_GetArgClass_Value& value); CORINFO_CLASS_HANDLE repGetArgClass(CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_HANDLE args, DWORD *exceptionCode); + void recGetHFAType(CORINFO_CLASS_HANDLE clsHnd, CorInfoType result); + void dmpGetHFAType(DWORDLONG key, DWORD value); + CorInfoType repGetHFAType(CORINFO_CLASS_HANDLE clsHnd); + void recGetMethodInfo(CORINFO_METHOD_HANDLE ftn, CORINFO_METHOD_INFO *info, bool result, DWORD exceptionCode); void dmpGetMethodInfo(DWORDLONG key, const Agnostic_GetMethodInfo& value); bool repGetMethodInfo(CORINFO_METHOD_HANDLE ftn, CORINFO_METHOD_INFO *info, DWORD *exceptionCode); @@ -1012,7 +1016,7 @@ private: // ********************* Please keep this up-to-date to ease adding more *************** -// Highest packet number: 158 +// Highest packet number: 159 // ************************************************************************************* enum mcPackets { @@ -1055,6 +1059,7 @@ enum mcPackets Packet_GetAddrOfCaptureThreadGlobal = 27, Retired1 = 28, Packet_GetArgClass = 139, //retired as 28 on 2013/07/03 + Packet_GetHFAType = 159, Packet_GetArgNext = 29, Retired2 = 30, Packet_GetArgType = 140, //retired as 30 on 2013/07/03 diff --git a/src/ToolBox/superpmi/superpmi-shim-collector/icorjitcompiler.cpp b/src/ToolBox/superpmi/superpmi-shim-collector/icorjitcompiler.cpp index e3f5ae2..c5f6d8a 100644 --- a/src/ToolBox/superpmi/superpmi-shim-collector/icorjitcompiler.cpp +++ b/src/ToolBox/superpmi/superpmi-shim-collector/icorjitcompiler.cpp @@ -109,7 +109,7 @@ void interceptor_ICJC::getVersionIdentifier(GUID* versionIdentifier /* OUT */) original_ICorJitCompiler->getVersionIdentifier(versionIdentifier); } -unsigned interceptor_ICJC::getMaxIntrinsicSIMDVectorLength(DWORD cpuCompileFlags) +unsigned interceptor_ICJC::getMaxIntrinsicSIMDVectorLength(CORJIT_FLAGS cpuCompileFlags) { return original_ICorJitCompiler->getMaxIntrinsicSIMDVectorLength(cpuCompileFlags); } diff --git a/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp index fb91636..1813ed2 100644 --- a/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -1173,7 +1173,7 @@ bool interceptor_ICJI::isFieldStatic(CORINFO_FIELD_HANDLE fldHnd) // in the code are. The native compiler will ensure that these places // have a corresponding break point in native code. // -// Note that unless CORJIT_FLG_DEBUG_CODE is specified, this function will +// Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will // be used only as a hint and the native compiler should not change its // code generation. void interceptor_ICJI::getBoundaries( @@ -1214,7 +1214,7 @@ void interceptor_ICJI::setBoundaries( // under debugging, the JIT needs to keep them live over their // entire scope so that they can be inspected. // -// Note that unless CORJIT_FLG_DEBUG_CODE is specified, this function will +// Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will // be used only as a hint and the native compiler should not change its // code generation. void interceptor_ICJI::getVars( @@ -1388,7 +1388,9 @@ CorInfoType interceptor_ICJI::getHFAType ( ) { mc->cr->AddCall("getHFAType"); - return original_ICorJitInfo->getHFAType(hClass); + CorInfoType temp = original_ICorJitInfo->getHFAType(hClass); + this->mc->recGetHFAType(hClass, temp); + return temp; } /***************************************************************************** diff --git a/src/ToolBox/superpmi/superpmi-shim-counter/icorjitcompiler.cpp b/src/ToolBox/superpmi/superpmi-shim-counter/icorjitcompiler.cpp index da766cc..2e088d4 100644 --- a/src/ToolBox/superpmi/superpmi-shim-counter/icorjitcompiler.cpp +++ b/src/ToolBox/superpmi/superpmi-shim-counter/icorjitcompiler.cpp @@ -55,7 +55,7 @@ void interceptor_ICJC::getVersionIdentifier(GUID* versionIdentifier /* OUT */) original_ICorJitCompiler->getVersionIdentifier(versionIdentifier); } -unsigned interceptor_ICJC::getMaxIntrinsicSIMDVectorLength(DWORD cpuCompileFlags) +unsigned interceptor_ICJC::getMaxIntrinsicSIMDVectorLength(CORJIT_FLAGS cpuCompileFlags) { mcs->AddCall("getMaxIntrinsicSIMDVectorLength"); return original_ICorJitCompiler->getMaxIntrinsicSIMDVectorLength(cpuCompileFlags); diff --git a/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp index 77519ca..448fb1f 100644 --- a/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp +++ b/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp @@ -961,7 +961,7 @@ bool interceptor_ICJI::isFieldStatic(CORINFO_FIELD_HANDLE fldHnd) // in the code are. The native compiler will ensure that these places // have a corresponding break point in native code. // -// Note that unless CORJIT_FLG_DEBUG_CODE is specified, this function will +// Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will // be used only as a hint and the native compiler should not change its // code generation. void interceptor_ICJI::getBoundaries( @@ -999,7 +999,7 @@ void interceptor_ICJI::setBoundaries( // under debugging, the JIT needs to keep them live over their // entire scope so that they can be inspected. // -// Note that unless CORJIT_FLG_DEBUG_CODE is specified, this function will +// Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will // be used only as a hint and the native compiler should not change its // code generation. void interceptor_ICJI::getVars( diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/icorjitcompiler.cpp b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitcompiler.cpp index f6fceb2..ec266e1 100644 --- a/src/ToolBox/superpmi/superpmi-shim-simple/icorjitcompiler.cpp +++ b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitcompiler.cpp @@ -48,7 +48,7 @@ void interceptor_ICJC::getVersionIdentifier(GUID* versionIdentifier /* OUT */) original_ICorJitCompiler->getVersionIdentifier(versionIdentifier); } -unsigned interceptor_ICJC::getMaxIntrinsicSIMDVectorLength(DWORD cpuCompileFlags) +unsigned interceptor_ICJC::getMaxIntrinsicSIMDVectorLength(CORJIT_FLAGS cpuCompileFlags) { return original_ICorJitCompiler->getMaxIntrinsicSIMDVectorLength(cpuCompileFlags); } diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp index 89b19d8..4d145f6 100644 --- a/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp +++ b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp @@ -876,7 +876,7 @@ bool interceptor_ICJI::isFieldStatic(CORINFO_FIELD_HANDLE fldHnd) // in the code are. The native compiler will ensure that these places // have a corresponding break point in native code. // -// Note that unless CORJIT_FLG_DEBUG_CODE is specified, this function will +// Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will // be used only as a hint and the native compiler should not change its // code generation. void interceptor_ICJI::getBoundaries( @@ -912,7 +912,7 @@ void interceptor_ICJI::setBoundaries( // under debugging, the JIT needs to keep them live over their // entire scope so that they can be inspected. // -// Note that unless CORJIT_FLG_DEBUG_CODE is specified, this function will +// Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will // be used only as a hint and the native compiler should not change its // code generation. void interceptor_ICJI::getVars( diff --git a/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp index 41b0195..b746d3f 100644 --- a/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp +++ b/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp @@ -1018,7 +1018,7 @@ bool MyICJI::isFieldStatic(CORINFO_FIELD_HANDLE fldHnd) // in the code are. The native compiler will ensure that these places // have a corresponding break point in native code. // -// Note that unless CORJIT_FLG_DEBUG_CODE is specified, this function will +// Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will // be used only as a hint and the native compiler should not change its // code generation. void MyICJI::getBoundaries( @@ -1068,7 +1068,7 @@ void MyICJI::setBoundaries( // under debugging, the JIT needs to keep them live over their // entire scope so that they can be inspected. // -// Note that unless CORJIT_FLG_DEBUG_CODE is specified, this function will +// Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will // be used only as a hint and the native compiler should not change its // code generation. void MyICJI::getVars( @@ -1192,9 +1192,8 @@ CorInfoType MyICJI::getHFAType ( ) { jitInstance->mc->cr->AddCall("getHFAType"); - LogError("Hit unimplemented getHFAType"); - DebugBreakorAV(75); - return (CorInfoType)0; + CorInfoType value = jitInstance->mc->repGetHFAType(hClass); + return value; } /***************************************************************************** diff --git a/src/ToolBox/superpmi/superpmi/methodstatsemitter.cpp b/src/ToolBox/superpmi/superpmi/methodstatsemitter.cpp index 0a43f02..5cebc97 100644 --- a/src/ToolBox/superpmi/superpmi/methodstatsemitter.cpp +++ b/src/ToolBox/superpmi/superpmi/methodstatsemitter.cpp @@ -50,11 +50,11 @@ void MethodStatsEmitter::Emit(int methodNumber, MethodContext *mc, ULONGLONG fir if (mc->dumpMethodMD5HashToBuffer(md5Hash, MD5_HASH_BUFFER_SIZE) != MD5_HASH_BUFFER_SIZE) md5Hash[0] = 0; - charCount += sprintf(rowData + charCount, "%s,", md5Hash); + charCount += sprintf_s(rowData + charCount, _countof(rowData) - charCount, "%s,", md5Hash); } if (strchr(statsTypes, '*') != NULL || strchr(statsTypes, 'n') != NULL || strchr(statsTypes, 'N') != NULL) { - charCount += sprintf(rowData + charCount, "%d,", methodNumber); + charCount += sprintf_s(rowData + charCount, _countof(rowData) - charCount, "%d,", methodNumber); } if (strchr(statsTypes, '*') != NULL || strchr(statsTypes, 'i') != NULL || strchr(statsTypes, 'I') != NULL) { @@ -63,7 +63,7 @@ void MethodStatsEmitter::Emit(int methodNumber, MethodContext *mc, ULONGLONG fir unsigned flags = 0; mc->repCompileMethod(&info, &flags); - charCount += sprintf(rowData + charCount, "%d,", info.ILCodeSize); + charCount += sprintf_s(rowData + charCount, _countof(rowData) - charCount, "%d,", info.ILCodeSize); } if (strchr(statsTypes, '*') != NULL || strchr(statsTypes, 'a') != NULL || strchr(statsTypes, 'A') != NULL) { @@ -76,11 +76,11 @@ void MethodStatsEmitter::Emit(int methodNumber, MethodContext *mc, ULONGLONG fir else codeSize = 0;//this is likely a thin mc - charCount += sprintf(rowData + charCount, "%d,", codeSize); + charCount += sprintf_s(rowData + charCount, _countof(rowData) - charCount, "%d,", codeSize); } if (strchr(statsTypes, '*') != NULL || strchr(statsTypes, 't') != NULL || strchr(statsTypes, 'T') != NULL) { - charCount += sprintf(rowData + charCount, "%llu,%llu,", firstTime, secondTime); + charCount += sprintf_s(rowData + charCount, _countof(rowData) - charCount, "%llu,%llu,", firstTime, secondTime); } //get rid of the final ',' and replace it with a '\n' @@ -105,15 +105,15 @@ void MethodStatsEmitter::SetStatsTypes(char *types) DWORD bytesWritten = 0; if (strchr(statsTypes, '*') != NULL || strchr(statsTypes, 'h') != NULL || strchr(statsTypes, 'H') != NULL) - charCount += sprintf(rowHeader + charCount, "HASH,"); + charCount += sprintf_s(rowHeader + charCount, _countof(rowHeader) - charCount, "HASH,"); if (strchr(statsTypes, '*') != NULL || strchr(statsTypes, 'n') != NULL || strchr(statsTypes, 'N') != NULL) - charCount += sprintf(rowHeader + charCount, "METHOD_NUMBER,"); + charCount += sprintf_s(rowHeader + charCount, _countof(rowHeader) - charCount, "METHOD_NUMBER,"); if (strchr(statsTypes, '*') != NULL || strchr(statsTypes, 'i') != NULL || strchr(statsTypes, 'I') != NULL) - charCount += sprintf(rowHeader + charCount, "IL_CODE_SIZE,"); + charCount += sprintf_s(rowHeader + charCount, _countof(rowHeader) - charCount, "IL_CODE_SIZE,"); if (strchr(statsTypes, '*') != NULL || strchr(statsTypes, 'a') != NULL || strchr(statsTypes, 'A') != NULL) - charCount += sprintf(rowHeader + charCount, "ASM_CODE_SIZE,"); + charCount += sprintf_s(rowHeader + charCount, _countof(rowHeader) - charCount, "ASM_CODE_SIZE,"); if (strchr(statsTypes, '*') != NULL || strchr(statsTypes, 't') != NULL || strchr(statsTypes, 'T') != NULL) - charCount += sprintf(rowHeader + charCount, "Time1,Time2,"); + charCount += sprintf_s(rowHeader + charCount, _countof(rowHeader) - charCount, "Time1,Time2,"); //get rid of the final ',' and replace it with a '\n' rowHeader[charCount - 1] = '\n'; @@ -123,4 +123,4 @@ void MethodStatsEmitter::SetStatsTypes(char *types) LogError("Failed to write row header '%s'. GetLastError()=%u", rowHeader, GetLastError()); } } -} \ No newline at end of file +} diff --git a/src/ToolBox/superpmi/superpmi/neardiffer.cpp b/src/ToolBox/superpmi/superpmi/neardiffer.cpp index 5b2e3b1..3f2c4db 100644 --- a/src/ToolBox/superpmi/superpmi/neardiffer.cpp +++ b/src/ToolBox/superpmi/superpmi/neardiffer.cpp @@ -154,7 +154,7 @@ void NearDiffer::DumpCodeBlock(unsigned char *block, ULONG blocksize, void *orig const size_t minInstrBytes = 7; size_t instrBytes = max(instrSize, minInstrBytes); - size_t buffSize = _snprintf(nullptr, 0, "%p %s\n", (void*)((size_t)originalAddr+offset), instrMnemonic) + 3 * instrBytes + 1; + size_t buffSize = sizeof("%p %s\n") + 10 + count + 3 * instrBytes + 1; char *buff = new char[buffSize]; int written = 0; written += sprintf_s(buff, buffSize, "%p ", (void*)((size_t)originalAddr+offset)); diff --git a/src/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp b/src/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp index 8c52323..301db3c 100644 --- a/src/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp +++ b/src/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp @@ -138,7 +138,7 @@ bool WriteArrayToMCL(char *mclFilename, int *arr, int count) DWORD charCount = 0; DWORD bytesWritten = 0; - charCount = sprintf(strMethodIndex, "%d\r\n", arr[i]); + charCount = sprintf_s(strMethodIndex, sizeof(strMethodIndex), "%d\r\n", arr[i]); if (!WriteFile(hMCLFile, strMethodIndex, charCount, &bytesWritten, nullptr) || (bytesWritten != charCount)) { @@ -232,7 +232,7 @@ void ProcessChildStdOut(const CommandLine::Options& o, char *stdoutFilename, int if (o.applyDiff) { int temp1 = 0, temp2 = 0, temp3 = 0, temp4 = 0; - int converted = sscanf(buff, g_AsmDiffsSummaryFormatString, &temp1, &temp2, &temp3, &temp4); + int converted = sscanf_s(buff, g_AsmDiffsSummaryFormatString, &temp1, &temp2, &temp3, &temp4); if (converted != 4) { LogError("Couldn't parse status message: \"%s\"", buff); @@ -248,7 +248,7 @@ void ProcessChildStdOut(const CommandLine::Options& o, char *stdoutFilename, int else { int temp1 = 0, temp2 = 0, temp3 = 0; - int converted = sscanf(buff, g_SummaryFormatString, &temp1, &temp2, &temp3); + int converted = sscanf_s(buff, g_SummaryFormatString, &temp1, &temp2, &temp3); if (converted != 3) { LogError("Couldn't parse status message: \"%s\"", buff); diff --git a/src/ToolBox/superpmi/superpmi/superpmi.cpp b/src/ToolBox/superpmi/superpmi/superpmi.cpp index ce35207..980792d 100644 --- a/src/ToolBox/superpmi/superpmi/superpmi.cpp +++ b/src/ToolBox/superpmi/superpmi/superpmi.cpp @@ -45,6 +45,8 @@ void SetSuperPmiTargetArchitecture(const char* targetArchitecture) } #elif defined(_TARGET_X86_) SpmiTargetArchitecture = SPMI_TARGET_ARCHITECTURE_X86; +#elif defined(_TARGET_ARM_) + SpmiTargetArchitecture = SPMI_TARGET_ARCHITECTURE_ARM; #endif } diff --git a/src/ToolBox/superpmi/superpmi/superpmi.h b/src/ToolBox/superpmi/superpmi/superpmi.h index d5b7bda..ce53599 100644 --- a/src/ToolBox/superpmi/superpmi/superpmi.h +++ b/src/ToolBox/superpmi/superpmi/superpmi.h @@ -12,7 +12,8 @@ enum SPMI_TARGET_ARCHITECTURE { SPMI_TARGET_ARCHITECTURE_X86, SPMI_TARGET_ARCHITECTURE_AMD64, - SPMI_TARGET_ARCHITECTURE_ARM64 + SPMI_TARGET_ARCHITECTURE_ARM64, + SPMI_TARGET_ARCHITECTURE_ARM }; extern SPMI_TARGET_ARCHITECTURE SpmiTargetArchitecture; diff --git a/src/classlibnative/bcltype/arraynative.cpp b/src/classlibnative/bcltype/arraynative.cpp index b1aa6f8..58fa4dd 100644 --- a/src/classlibnative/bcltype/arraynative.cpp +++ b/src/classlibnative/bcltype/arraynative.cpp @@ -176,7 +176,6 @@ void ArrayInitializeWorker(ARRAYBASEREF * arrayRef, #ifdef _X86_ BEGIN_CALL_TO_MANAGED(); - typedef void (__fastcall * CtorFtnType)(BYTE*, BYTE*); for (SIZE_T i = 0; i < cElements; i++) { @@ -197,6 +196,7 @@ void ArrayInitializeWorker(ARRAYBASEREF * arrayRef, nop // Mark the fact that we can call managed code } #else // _DEBUG + typedef void (__fastcall * CtorFtnType)(BYTE*, BYTE*); (*(CtorFtnType)ctorFtn)(thisPtr, (BYTE*)pElemMT); #endif // _DEBUG @@ -961,7 +961,7 @@ void memmoveGCRefs(void *dest, const void *src, size_t len) } } - GCHeap::GetGCHeap()->SetCardsAfterBulkCopy((Object**)dest, len); + GCHeapUtilities::GetGCHeap()->SetCardsAfterBulkCopy((Object**)dest, len); } void ArrayNative::ArrayCopyNoTypeCheck(BASEARRAYREF pSrc, unsigned int srcIndex, BASEARRAYREF pDest, unsigned int destIndex, unsigned int length) diff --git a/src/classlibnative/bcltype/number.cpp b/src/classlibnative/bcltype/number.cpp index 349bffb..6ca24d8 100644 --- a/src/classlibnative/bcltype/number.cpp +++ b/src/classlibnative/bcltype/number.cpp @@ -82,7 +82,7 @@ static const char* const negNumberFormats[] = { static const char posNumberFormat[] = "#"; -#if defined(_TARGET_X86_) +#if defined(_TARGET_X86_) && !defined(FEATURE_PAL) extern "C" void _cdecl /*__stdcall*/ DoubleToNumber(double value, int precision, NUMBER* number); extern "C" void _cdecl /*__stdcall*/ NumberToDouble(NUMBER* number, double* value); @@ -132,7 +132,7 @@ unsigned int Int64DivMod1E9(unsigned __int64* value) #pragma warning(default:4035) -#else // !(defined(_TARGET_X86_) +#else // _TARGET_X86_ && !FEATURE_PAL #pragma warning(disable:4273) extern "C" char* __cdecl _ecvt(double, int, int*, int*); @@ -607,7 +607,7 @@ unsigned int Int64DivMod1E9(unsigned __int64* value) -#endif // !(defined(_TARGET_X86_) +#endif // _TARGET_X86_ && !FEATURE_PAL #if defined(_MSC_VER) && defined(_TARGET_X86_) #pragma optimize("y", on) // Small critical routines, don't put in EBP frame diff --git a/src/classlibnative/bcltype/system.cpp b/src/classlibnative/bcltype/system.cpp index e902734..8bb3409 100644 --- a/src/classlibnative/bcltype/system.cpp +++ b/src/classlibnative/bcltype/system.cpp @@ -63,6 +63,16 @@ FCIMPLEND; +FCIMPL0(UINT32, SystemNative::GetCurrentProcessorNumber) +{ + FCALL_CONTRACT; + + return ::GetCurrentProcessorNumber(); +} +FCIMPLEND; + + + FCIMPL0(UINT32, SystemNative::GetTickCount) { FCALL_CONTRACT; @@ -673,7 +683,7 @@ FCIMPL0(FC_BOOL_RET, SystemNative::IsServerGC) { FCALL_CONTRACT; - FC_RETURN_BOOL(GCHeap::IsServerHeap()); + FC_RETURN_BOOL(GCHeapUtilities::IsServerHeap()); } FCIMPLEND diff --git a/src/classlibnative/bcltype/system.h b/src/classlibnative/bcltype/system.h index 60355b3..9edc595 100644 --- a/src/classlibnative/bcltype/system.h +++ b/src/classlibnative/bcltype/system.h @@ -72,6 +72,7 @@ private: public: // Functions on the System.Environment class static FCDECL0(INT64, __GetSystemTimeAsFileTime); + static FCDECL0(UINT32, GetCurrentProcessorNumber); static FCDECL0(UINT32, GetTickCount); static FCDECL1(FC_BOOL_RET, GetOSVersion, OSVERSIONINFOObject *osVer); static FCDECL1(FC_BOOL_RET, GetOSVersionEx, OSVERSIONINFOEXObject *osVer); diff --git a/src/classlibnative/float/floatsingle.cpp b/src/classlibnative/float/floatsingle.cpp index dd1bb43..7e2ea0a 100644 --- a/src/classlibnative/float/floatsingle.cpp +++ b/src/classlibnative/float/floatsingle.cpp @@ -11,6 +11,22 @@ #define IS_FLT_INFINITY(x) (((*((INT32*)((void*)&x))) & 0x7FFFFFFF) == 0x7F800000) +// 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(FEATURE_PAL) + +#if !defined(_isnanf) +#define _isnanf _isnan +#endif + +#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 @@ -39,6 +55,218 @@ FCIMPL1(float, COMSingle::Abs, float x) return (float)fabsf(x); FCIMPLEND +/*=====================================Acos===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Acos, float x) + FCALL_CONTRACT; + + return (float)acosf(x); +FCIMPLEND + +/*=====================================Asin===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Asin, float x) + FCALL_CONTRACT; + + return (float)asinf(x); +FCIMPLEND + +/*=====================================Atan===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Atan, float x) + FCALL_CONTRACT; + + return (float)atanf(x); +FCIMPLEND + +/*=====================================Atan2==================================== +** +==============================================================================*/ +FCIMPL2(float, COMSingle::Atan2, float y, float x) + FCALL_CONTRACT; + + // atan2f(+/-INFINITY, +/-INFINITY) produces +/-0.785398163f (x is +INFINITY) and + // +/-2.35619449f (x is -INFINITY) instead of the expected value of NaN. We handle + // that case here ourselves. + if (IS_FLT_INFINITY(y) && IS_FLT_INFINITY(x)) { + return (float)(y / x); + } + + return (float)atan2f(y, x); +FCIMPLEND + +/*====================================Ceil====================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Ceil, float x) + FCALL_CONTRACT; + + return (float)ceilf(x); +FCIMPLEND + +/*=====================================Cos====================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Cos, float x) + FCALL_CONTRACT; + + return (float)cosf(x); +FCIMPLEND + +/*=====================================Cosh===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Cosh, float x) + FCALL_CONTRACT; + + return (float)coshf(x); +FCIMPLEND + +/*=====================================Exp====================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Exp, float x) + FCALL_CONTRACT; + + return (float)expf(x); +FCIMPLEND + +/*====================================Floor===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Floor, float x) + FCALL_CONTRACT; + + return (float)floorf(x); +FCIMPLEND + +/*=====================================Log====================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Log, float x) + FCALL_CONTRACT; + + return (float)logf(x); +FCIMPLEND + +/*====================================Log10===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Log10, float x) + FCALL_CONTRACT; + + return (float)log10f(x); +FCIMPLEND + +/*=====================================ModF===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::ModF, float* iptr) + FCALL_CONTRACT; + + return (float)modff(*iptr, iptr); +FCIMPLEND + +/*=====================================Pow====================================== +** +==============================================================================*/ +FCIMPL2(float, COMSingle::Pow, float x, float y) + FCALL_CONTRACT; + + // The CRT version of pow preserves the NaN payload of x over the NaN payload of y. + + if(_isnanf(y)) { + return y; // IEEE 754-2008: NaN payload must be preserved + } + + if(_isnanf(x)) { + return x; // IEEE 754-2008: NaN payload must be preserved + } + + // The CRT version of powf does not return NaN for powf(-1.0f, +/-INFINITY) and + // instead returns +1.0f. + + if(IS_FLT_INFINITY(y) && (x == -1.0f)) { + INT32 result = CLR_NAN_32; + return (*((float*)((INT32*)&result))); + } + + return (float)powf(x, y); +FCIMPLEND + +/*====================================Round===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Round, float x) + FCALL_CONTRACT; + + // If the number has no fractional part do nothing + // This shortcut is necessary to workaround precision loss in borderline cases on some platforms + if (x == (float)((INT32)x)) { + return x; + } + + // We had a number that was equally close to 2 integers. + // We need to return the even one. + + float tempVal = (x + 0.5f); + float flrTempVal = floorf(tempVal); + + if ((flrTempVal == tempVal) && (fmodf(tempVal, 2.0f) != 0)) { + flrTempVal -= 1.0f; + } + + return _copysignf(flrTempVal, x); +FCIMPLEND + +/*=====================================Sin====================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Sin, float x) + FCALL_CONTRACT; + + return (float)sinf(x); +FCIMPLEND + +/*=====================================Sinh===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Sinh, float x) + FCALL_CONTRACT; + + return (float)sinhf(x); +FCIMPLEND + +/*=====================================Sqrt===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Sqrt, float x) + FCALL_CONTRACT; + + return (float)sqrtf(x); +FCIMPLEND + +/*=====================================Tan====================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Tan, float x) + FCALL_CONTRACT; + + return (float)tanf(x); +FCIMPLEND + +/*=====================================Tanh===================================== +** +==============================================================================*/ +FCIMPL1(float, COMSingle::Tanh, float x) + FCALL_CONTRACT; + + return (float)tanhf(x); +FCIMPLEND + #ifdef _MSC_VER #pragma float_control(precise, on ) #endif diff --git a/src/classlibnative/inc/floatsingle.h b/src/classlibnative/inc/floatsingle.h index 6d123ec..f8a1dda 100644 --- a/src/classlibnative/inc/floatsingle.h +++ b/src/classlibnative/inc/floatsingle.h @@ -11,6 +11,25 @@ class COMSingle { public: FCDECL1(static float, Abs, float x); + FCDECL1(static float, Acos, float x); + FCDECL1(static float, Asin, float x); + FCDECL1(static float, Atan, float x); + FCDECL2(static float, Atan2, float y, float x); + FCDECL1(static float, Ceil, float x); + FCDECL1(static float, Cos, float x); + FCDECL1(static float, Cosh, float x); + FCDECL1(static float, Exp, float x); + FCDECL1(static float, Floor, float x); + FCDECL1(static float, Log, float x); + FCDECL1(static float, Log10, float x); + FCDECL1(static float, ModF, float* iptr); + FCDECL2(static float, Pow, float x, float y); + FCDECL1(static float, Round, float x); + FCDECL1(static float, Sin, float x); + FCDECL1(static float, Sinh, float x); + FCDECL1(static float, Sqrt, float x); + FCDECL1(static float, Tan, float x); + FCDECL1(static float, Tanh, float x); }; #endif // _FLOATSINGLE_H_ diff --git a/src/classlibnative/inc/nlsinfo.h b/src/classlibnative/inc/nlsinfo.h index 1c1ff01..a5dc13f 100644 --- a/src/classlibnative/inc/nlsinfo.h +++ b/src/classlibnative/inc/nlsinfo.h @@ -115,19 +115,8 @@ public: static INT_PTR InternalInitVersionedSortHandle(LPCWSTR localeName, INT_PTR* handleOrigin); static INT_PTR InternalInitVersionedSortHandle(LPCWSTR localeName, INT_PTR* handleOrigin, DWORD sortVersion); static DWORD QCALLTYPE InternalGetSortVersion(); - static BOOL QCALLTYPE InternalGetNlsVersionEx(INT_PTR handle, INT_PTR handleOrigin, LPCWSTR lpLocaleName, NLSVERSIONINFOEX * lpVersionInformation); #endif - - -#ifndef FEATURE_CORECLR - // - // Native helper function for methods in TimeZone - // - static FCDECL0(LONG, nativeGetTimeZoneMinuteOffset); - static FCDECL0(Object*, nativeGetStandardName); - static FCDECL0(Object*, nativeGetDaylightName); - static FCDECL1(Object*, nativeGetDaylightChanges, int year); -#endif // FEATURE_CORECLR + static BOOL QCALLTYPE InternalGetNlsVersionEx(INT_PTR handle, INT_PTR handleOrigin, LPCWSTR lpLocaleName, NLSVERSIONINFOEX * lpVersionInformation); // // Native helper function for methods in EncodingTable diff --git a/src/classlibnative/nls/nlsinfo.cpp b/src/classlibnative/nls/nlsinfo.cpp index 864f998..0e034c4 100644 --- a/src/classlibnative/nls/nlsinfo.cpp +++ b/src/classlibnative/nls/nlsinfo.cpp @@ -1057,7 +1057,7 @@ FCIMPLEND #define CULTURETYPES_FRAMEWORKCULTURES 0x0040 -const LPWSTR WHIDBEY_FRAMEWORK_CULTURE_LIST [] = +const LPCWSTR WHIDBEY_FRAMEWORK_CULTURE_LIST [] = { W(""), W("af"), @@ -1877,127 +1877,6 @@ INT32 QCALLTYPE COMNlsInfo::InternalGetGlobalizedHashCode(INT_PTR handle, INT_PT return(iReturnHash); } -#ifndef FEATURE_CORECLR // FCalls used by System.TimeZone - -FCIMPL0(LONG, COMNlsInfo::nativeGetTimeZoneMinuteOffset) -{ - FCALL_CONTRACT; - - TIME_ZONE_INFORMATION timeZoneInfo; - - GetTimeZoneInformation(&timeZoneInfo); - - // - // In Win32, UTC = local + offset. So for Pacific Standard Time, offset = 8. - // In NLS+, Local time = UTC + offset. So for PST, offset = -8. - // So we have to reverse the sign here. - // - return (timeZoneInfo.Bias * -1); -} -FCIMPLEND - -FCIMPL0(Object*, COMNlsInfo::nativeGetStandardName) -{ - FCALL_CONTRACT; - - STRINGREF refRetVal = NULL; - HELPER_METHOD_FRAME_BEGIN_RET_1(refRetVal); - - TIME_ZONE_INFORMATION timeZoneInfo; - GetTimeZoneInformation(&timeZoneInfo); - - refRetVal = StringObject::NewString(timeZoneInfo.StandardName); - - HELPER_METHOD_FRAME_END(); - return OBJECTREFToObject(refRetVal); -} -FCIMPLEND - -FCIMPL0(Object*, COMNlsInfo::nativeGetDaylightName) -{ - FCALL_CONTRACT; - - STRINGREF refRetVal = NULL; - HELPER_METHOD_FRAME_BEGIN_RET_1(refRetVal); - - TIME_ZONE_INFORMATION timeZoneInfo; - GetTimeZoneInformation(&timeZoneInfo); - // Instead of returning null when daylight saving is not used, now we return the same result as the OS. - //In this case, if daylight saving time is used, the standard name is returned. - -#if 0 - if (result == TIME_ZONE_ID_UNKNOWN || timeZoneInfo.DaylightDate.wMonth == 0) { - // If daylight saving time is not used in this timezone, return null. - // - // Windows NT/2000: TIME_ZONE_ID_UNKNOWN is returned if daylight saving time is not used in - // the current time zone, because there are no transition dates. - // - // For Windows 9x, a zero in the wMonth in DaylightDate means daylight saving time - // is not specified. - // - // If the current timezone uses daylight saving rule, but user unchekced the - // "Automatically adjust clock for daylight saving changes", the value - // for DaylightBias will be 0. - return (I2ARRAYREF)NULL; - } -#endif // 0 - - refRetVal = StringObject::NewString(timeZoneInfo.DaylightName); - - HELPER_METHOD_FRAME_END(); - return OBJECTREFToObject(refRetVal); -} -FCIMPLEND - -FCIMPL1(Object*, COMNlsInfo::nativeGetDaylightChanges, int year) -{ - FCALL_CONTRACT; - - I2ARRAYREF pResultArray = NULL; - HELPER_METHOD_FRAME_BEGIN_RET_1(pResultArray); - - TIME_ZONE_INFORMATION timeZoneInfo; - DWORD result = GetTimeZoneInformation(&timeZoneInfo); - - if (result == TIME_ZONE_ID_UNKNOWN || timeZoneInfo.DaylightBias == 0 - || timeZoneInfo.DaylightDate.wMonth == 0 - ) { - // If daylight saving time is not used in this timezone, return null. - // - // If the current timezone uses daylight saving rule, but user unchekced the - // "Automatically adjust clock for daylight saving changes", the value - // for DaylightBias will be 0. - goto lExit; - } - - pResultArray = (I2ARRAYREF)AllocatePrimitiveArray(ELEMENT_TYPE_I2, 17); - - // - // The content of timeZoneInfo.StandardDate is 8 words, which - // contains year, month, day, dayOfWeek, hour, minute, second, millisecond. - // - memcpyNoGCRefs(pResultArray->m_Array, - (LPVOID)&timeZoneInfo.DaylightDate, - 8 * sizeof(INT16)); - - // - // The content of timeZoneInfo.DaylightDate is 8 words, which - // contains year, month, day, dayOfWeek, hour, minute, second, millisecond. - // - memcpyNoGCRefs(((INT16*)pResultArray->m_Array) + 8, - (LPVOID)&timeZoneInfo.StandardDate, - 8 * sizeof(INT16)); - - ((INT16*)pResultArray->m_Array)[16] = (INT16)timeZoneInfo.DaylightBias * -1; - -lExit: ; - HELPER_METHOD_FRAME_END(); - return OBJECTREFToObject(pResultArray); -} -FCIMPLEND - -#endif // FEATURE_CORECLR - inline BOOL IsInvariantLocale(STRINGREF localeName) { return localeName->GetStringLength() == 0; @@ -3411,7 +3290,6 @@ INT_PTR COMNlsInfo::InternalInitOsSortHandle(LPCWSTR localeName, __out INT_PTR* return pSort; } -#ifndef FEATURE_CORECLR BOOL QCALLTYPE COMNlsInfo::InternalGetNlsVersionEx(INT_PTR handle, INT_PTR handleOrigin, LPCWSTR lpLocaleName, NLSVERSIONINFOEX * lpVersionInformation) { CONTRACTL { @@ -3421,7 +3299,7 @@ BOOL QCALLTYPE COMNlsInfo::InternalGetNlsVersionEx(INT_PTR handle, INT_PTR handl BOOL ret = FALSE; BEGIN_QCALL; - +#ifndef FEATURE_CORECLR AppDomain* curDomain = GetAppDomain(); if(curDomain->m_bUseOsSorting) @@ -3449,12 +3327,15 @@ BOOL QCALLTYPE COMNlsInfo::InternalGetNlsVersionEx(INT_PTR handle, INT_PTR handl lpVersionInformation->dwEffectiveId = 0; ZeroMemory(&(lpVersionInformation->guidCustomVersion), sizeof(GUID)); } - +#else + ret = GetNLSVersionEx(COMPARE_STRING, lpLocaleName, lpVersionInformation); +#endif // FEATURE_CORECLR END_QCALL; return ret; } +#ifndef FEATURE_CORECLR DWORD QCALLTYPE COMNlsInfo::InternalGetSortVersion() { CONTRACTL { diff --git a/src/coreclr/hosts/coreconsole/coreconsole.cpp b/src/coreclr/hosts/coreconsole/coreconsole.cpp index 1533dff..ea4e2e7 100644 --- a/src/coreclr/hosts/coreconsole/coreconsole.cpp +++ b/src/coreclr/hosts/coreconsole/coreconsole.cpp @@ -44,7 +44,7 @@ public: m_capacity = m_defaultSize; } if (m_length + strLen + 1 > m_capacity) { - size_t newCapacity = m_capacity * 2; + size_t newCapacity = (m_length + strLen + 1) * 2; wchar_t* newBuffer = new wchar_t[newCapacity]; wcsncpy_s(newBuffer, newCapacity, m_buffer, m_length); delete[] m_buffer; @@ -185,7 +185,7 @@ public: } } - bool TPAListContainsFile(_In_z_ wchar_t* fileNameWithoutExtension, _In_reads_(countExtensions) wchar_t** rgTPAExtensions, int countExtensions) + bool TPAListContainsFile(_In_z_ wchar_t* fileNameWithoutExtension, _In_reads_(countExtensions) const wchar_t** rgTPAExtensions, int countExtensions) { if (!m_tpaList.CStr()) return false; @@ -225,7 +225,7 @@ public: } } - void AddFilesFromDirectoryToTPAList(_In_z_ wchar_t* targetPath, _In_reads_(countExtensions) wchar_t** rgTPAExtensions, int countExtensions) + void AddFilesFromDirectoryToTPAList(_In_z_ wchar_t* targetPath, _In_reads_(countExtensions) const wchar_t** rgTPAExtensions, int countExtensions) { *m_log << W("Adding assemblies from ") << targetPath << W(" to the TPA list") << Logger::endl; wchar_t assemblyPath[MAX_LONGPATH]; @@ -288,7 +288,7 @@ public: // On first call, scans the coreclr directory for dlls and adds them all to the list. const wchar_t * GetTpaList() { if (!m_tpaList.CStr()) { - wchar_t *rgTPAExtensions[] = { + const wchar_t *rgTPAExtensions[] = { W("*.ni.dll"), // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir W("*.dll"), W("*.ni.exe"), @@ -457,7 +457,6 @@ bool TryRun(const int argc, const wchar_t* argv[], Logger &log, const bool verbo W("APP_PATHS"), W("APP_NI_PATHS"), W("NATIVE_DLL_SEARCH_DIRECTORIES"), - W("AppDomainCompatSwitch") }; const wchar_t *property_values[] = { // TRUSTED_PLATFORM_ASSEMBLIES @@ -468,8 +467,6 @@ bool TryRun(const int argc, const wchar_t* argv[], Logger &log, const bool verbo appNiPath, // NATIVE_DLL_SEARCH_DIRECTORIES nativeDllSearchDirs, - // AppDomainCompatSwitch - W("UseLatestBehaviorWhenTFMNotSpecified") }; diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp index e7ddab2..dfbb79c 100644 --- a/src/coreclr/hosts/corerun/corerun.cpp +++ b/src/coreclr/hosts/corerun/corerun.cpp @@ -161,7 +161,7 @@ public: } } - bool TPAListContainsFile(_In_z_ wchar_t* fileNameWithoutExtension, _In_reads_(countExtensions) wchar_t** rgTPAExtensions, int countExtensions) + bool TPAListContainsFile(_In_z_ wchar_t* fileNameWithoutExtension, _In_reads_(countExtensions) const wchar_t** rgTPAExtensions, int countExtensions) { if (m_tpaList.IsEmpty()) return false; @@ -201,7 +201,7 @@ public: } } - void AddFilesFromDirectoryToTPAList(_In_z_ const wchar_t* targetPath, _In_reads_(countExtensions) wchar_t** rgTPAExtensions, int countExtensions) + void AddFilesFromDirectoryToTPAList(_In_z_ const wchar_t* targetPath, _In_reads_(countExtensions) const wchar_t** rgTPAExtensions, int countExtensions) { *m_log << W("Adding assemblies from ") << targetPath << W(" to the TPA list") << Logger::endl; StackSString assemblyPath; @@ -259,7 +259,7 @@ public: // On first call, scans the coreclr directory for dlls and adds them all to the list. const wchar_t * GetTpaList() { if (m_tpaList.IsEmpty()) { - wchar_t *rgTPAExtensions[] = { + const wchar_t *rgTPAExtensions[] = { W("*.ni.dll"), // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir W("*.dll"), W("*.ni.exe"), @@ -495,7 +495,6 @@ bool TryRun(const int argc, const wchar_t* argv[], Logger &log, const bool verbo W("APP_PATHS"), W("APP_NI_PATHS"), W("NATIVE_DLL_SEARCH_DIRECTORIES"), - W("AppDomainCompatSwitch"), W("APP_LOCAL_WINMETADATA") }; const wchar_t *property_values[] = { @@ -507,8 +506,6 @@ bool TryRun(const int argc, const wchar_t* argv[], Logger &log, const bool verbo appNiPath, // NATIVE_DLL_SEARCH_DIRECTORIES nativeDllSearchDirs, - // AppDomainCompatSwitch - W("UseLatestBehaviorWhenTFMNotSpecified"), // APP_LOCAL_WINMETADATA appLocalWinmetadata }; diff --git a/src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp b/src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp index b3a0c07..d7186d7 100644 --- a/src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp +++ b/src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp @@ -379,7 +379,6 @@ int ExecuteManagedAssembly( "APP_PATHS", "APP_NI_PATHS", "NATIVE_DLL_SEARCH_DIRECTORIES", - "AppDomainCompatSwitch", "System.GC.Server", }; const char *propertyValues[] = { @@ -391,8 +390,6 @@ int ExecuteManagedAssembly( appPath.c_str(), // NATIVE_DLL_SEARCH_DIRECTORIES nativeDllSearchDirs.c_str(), - // AppDomainCompatSwitch - "UseLatestBehaviorWhenTFMNotSpecified", // System.GC.Server useServerGc, }; diff --git a/src/corefx/System.Globalization.Native/CMakeLists.txt b/src/corefx/System.Globalization.Native/CMakeLists.txt index 3d9e392..90f5067 100644 --- a/src/corefx/System.Globalization.Native/CMakeLists.txt +++ b/src/corefx/System.Globalization.Native/CMakeLists.txt @@ -14,7 +14,7 @@ if(UTYPES_H STREQUAL UTYPES_H-NOTFOUND) return() endif() -if(NOT CLR_CMAKE_PLATFORM_DARWIN) +if (FEATURE_FIXED_ICU_VERSION AND NOT CLR_CMAKE_PLATFORM_DARWIN) find_library(ICUUC icuuc) if(ICUUC STREQUAL ICUUC-NOTFOUND) message(FATAL_ERROR "Cannot find libicuuc, try installing libicu-dev (or the appropriate package for your platform)") @@ -26,12 +26,16 @@ if(NOT CLR_CMAKE_PLATFORM_DARWIN) message(FATAL_ERROR "Cannot find libicui18n, try installing libicu-dev (or the appropriate package for your platform)") return() endif() -else() +endif() + +if(CLR_CMAKE_PLATFORM_DARWIN) find_library(ICUCORE icucore) if(ICUI18N STREQUAL ICUCORE-NOTFOUND) message(FATAL_ERROR "Cannot find libicucore, skipping build for System.Globalization.Native. .NET globalization is not expected to function.") return() endif() + # On Darwin, we always use the OS provided ICU + SET(FEATURE_FIXED_ICU_VERSION 1) endif() include(configure.cmake) @@ -50,6 +54,12 @@ set(NATIVEGLOBALIZATION_SOURCES timeZoneInfo.cpp ) +if (NOT FEATURE_FIXED_ICU_VERSION) + list(APPEND NATIVEGLOBALIZATION_SOURCES + icushim.cpp + ) +endif() + include_directories(${UTYPES_H}) _add_library(System.Globalization.Native @@ -60,11 +70,21 @@ _add_library(System.Globalization.Native # Disable the "lib" prefix. set_target_properties(System.Globalization.Native PROPERTIES PREFIX "") +if (FEATURE_FIXED_ICU_VERSION) + add_definitions(-DFEATURE_FIXED_ICU_VERSION) +endif() + if(NOT CLR_CMAKE_PLATFORM_DARWIN) - target_link_libraries(System.Globalization.Native - ${ICUUC} - ${ICUI18N} - ) + if (FEATURE_FIXED_ICU_VERSION) + target_link_libraries(System.Globalization.Native + ${ICUUC} + ${ICUI18N} + ) + elseif(NOT CMAKE_SYSTEM_NAME STREQUAL FreeBSD AND NOT CMAKE_SYSTEM_NAME STREQUAL NetBSD) + target_link_libraries(System.Globalization.Native + dl + ) + endif() else() target_link_libraries(System.Globalization.Native ${ICUCORE} @@ -73,5 +93,11 @@ else() add_definitions(-DU_DISABLE_RENAMING=1) endif() +verify_dependencies( + System.Globalization.Native + "Verification failed. System.Globalization.Native.so has undefined dependencies. These are likely ICU APIs that need to be added to icushim.h." +) + # add the install targets -install_clr(System.Globalization.Native) \ No newline at end of file +install_clr(System.Globalization.Native) + diff --git a/src/corefx/System.Globalization.Native/calendarData.cpp b/src/corefx/System.Globalization.Native/calendarData.cpp index f91cc0c..4943607 100644 --- a/src/corefx/System.Globalization.Native/calendarData.cpp +++ b/src/corefx/System.Globalization.Native/calendarData.cpp @@ -6,7 +6,7 @@ #include #include -#include "config.h" +#include "icushim.h" #include "locale.hpp" #include "holders.h" #include "errors.h" diff --git a/src/corefx/System.Globalization.Native/casing.cpp b/src/corefx/System.Globalization.Native/casing.cpp index 58b47fc..918b8fe 100644 --- a/src/corefx/System.Globalization.Native/casing.cpp +++ b/src/corefx/System.Globalization.Native/casing.cpp @@ -5,8 +5,7 @@ #include #include -#include -#include +#include "icushim.h" /* Function: diff --git a/src/corefx/System.Globalization.Native/collation.cpp b/src/corefx/System.Globalization.Native/collation.cpp index 6039a9e..f372112 100644 --- a/src/corefx/System.Globalization.Native/collation.cpp +++ b/src/corefx/System.Globalization.Native/collation.cpp @@ -8,12 +8,10 @@ #include #include #include -#include -#include -#include -#include -#include "config.h" +#include "icushim.h" +#include "locale.hpp" +#include "errors.h" const int32_t CompareOptionsIgnoreCase = 0x1; const int32_t CompareOptionsIgnoreNonSpace = 0x2; @@ -298,7 +296,7 @@ UCollator* CloneCollatorWithOptions(const UCollator* pCollator, int32_t options, // Returns TRUE if all the collation elements in str are completely ignorable bool CanIgnoreAllCollationElements(const UCollator* pColl, const UChar* lpStr, int32_t length) { - bool result = FALSE; + bool result = false; UErrorCode err = U_ZERO_ERROR; UCollationElements* pCollElem = ucol_openElements(pColl, lpStr, length, &err); @@ -306,20 +304,20 @@ bool CanIgnoreAllCollationElements(const UCollator* pColl, const UChar* lpStr, i { int32_t curCollElem = UCOL_NULLORDER; - result = TRUE; + result = true; while ((curCollElem = ucol_next(pCollElem, &err)) != UCOL_NULLORDER) { if (curCollElem != 0) { - result = FALSE; + result = false; break; } } if (U_FAILURE(err)) { - result = FALSE; + result = false; } ucol_closeElements(pCollElem); @@ -329,24 +327,36 @@ bool CanIgnoreAllCollationElements(const UCollator* pColl, const UChar* lpStr, i } -extern "C" SortHandle* GlobalizationNative_GetSortHandle(const char* lpLocaleName) +extern "C" int32_t GlobalizationNative_GetSortVersion() { - SortHandle* pSortHandle = new SortHandle(); + // we didn't use UCOL_TAILORINGS_VERSION because it is deprecated in ICU v5 + return UCOL_RUNTIME_VERSION << 16 | UCOL_BUILDER_VERSION; +} + +extern "C" ResultCode GlobalizationNative_GetSortHandle(const char* lpLocaleName, SortHandle** ppSortHandle) +{ + assert(ppSortHandle != nullptr); + + *ppSortHandle = new (std::nothrow) SortHandle(); + if ((*ppSortHandle) == nullptr) + { + return GetResultCode(U_MEMORY_ALLOCATION_ERROR); + } UErrorCode err = U_ZERO_ERROR; - pSortHandle->regular = ucol_open(lpLocaleName, &err); + (*ppSortHandle)->regular = ucol_open(lpLocaleName, &err); if (U_FAILURE(err)) { - if (pSortHandle->regular != nullptr) - ucol_close(pSortHandle->regular); + if ((*ppSortHandle)->regular != nullptr) + ucol_close((*ppSortHandle)->regular); - delete pSortHandle; - pSortHandle = nullptr; + delete (*ppSortHandle); + (*ppSortHandle) = nullptr; } - return pSortHandle; + return GetResultCode(err); } extern "C" void GlobalizationNative_CloseSortHandle(SortHandle* pSortHandle) diff --git a/src/corefx/System.Globalization.Native/errors.h b/src/corefx/System.Globalization.Native/errors.h index 2bfbdb2..b23a0da 100644 --- a/src/corefx/System.Globalization.Native/errors.h +++ b/src/corefx/System.Globalization.Native/errors.h @@ -4,8 +4,6 @@ #pragma once -#include - /* * These values should be kept in sync with * Interop.GlobalizationInterop.ResultCode @@ -15,6 +13,7 @@ enum ResultCode : int32_t Success = 0, UnknownError = 1, InsufficentBuffer = 2, + OutOfMemory = 3 }; /* @@ -26,6 +25,11 @@ static ResultCode GetResultCode(UErrorCode err) { return InsufficentBuffer; } + + if (err == U_MEMORY_ALLOCATION_ERROR) + { + return OutOfMemory; + } if (U_SUCCESS(err)) { diff --git a/src/corefx/System.Globalization.Native/holders.h b/src/corefx/System.Globalization.Native/holders.h index 529451f..83e253d 100644 --- a/src/corefx/System.Globalization.Native/holders.h +++ b/src/corefx/System.Globalization.Native/holders.h @@ -2,14 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#include -#include -#include -#include -#include -#include -#include - // IcuHolder is a template that can manage the lifetime of a raw pointer to ensure that it is cleaned up at the correct // time. The general usage pattern is to aquire some ICU resource via an _open call, then construct a holder using the // pointer and UErrorCode to manage the lifetime. When the holder goes out of scope, the coresponding close method is diff --git a/src/corefx/System.Globalization.Native/icushim.cpp b/src/corefx/System.Globalization.Native/icushim.cpp new file mode 100644 index 0000000..63f111b --- /dev/null +++ b/src/corefx/System.Globalization.Native/icushim.cpp @@ -0,0 +1,226 @@ +// 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. +// + +#include +#include +#include +#include +#include + +#include "icushim.h" + +// Define pointers to all the used ICU functions +#define PER_FUNCTION_BLOCK(fn, lib) decltype(fn)* fn##_ptr; +FOR_ALL_ICU_FUNCTIONS +#undef PER_FUNCTION_BLOCK + +static void* libicuuc = nullptr; +static void* libicui18n = nullptr; + +// Version ranges to search for each of the three version components +// The rationale for major version range is that we support versions higher or +// equal to the version we are built against and less or equal to that version +// plus 20 to give us enough headspace. The ICU seems to version about twice +// a year. +static const int MinICUVersion = U_ICU_VERSION_MAJOR_NUM; +static const int MaxICUVersion = MinICUVersion + 20; +static const int MinMinorICUVersion = 1; +static const int MaxMinorICUVersion = 5; +static const int MinSubICUVersion = 1; +static const int MaxSubICUVersion = 5; + +// .x.x.x, considering the max number of decimal digits for each component +static const int MaxICUVersionStringLength = 33; + +// Get filename of an ICU library with the requested version in the name +// There are three possible cases of the version components values: +// 1. Only majorVer is not equal to -1 => result is baseFileName.majorver +// 2. Only majorVer and minorVer are not equal to -1 => result is baseFileName.majorver.minorVer +// 3. All components are not equal to -1 => result is baseFileName.majorver.minorVer.subver +void GetVersionedLibFileName(const char* baseFileName, int majorVer, int minorVer, int subVer, char* result) +{ + assert(majorVer != -1); + + int nameLen = sprintf(result, "%s.%d", baseFileName, majorVer); + + if (minorVer != -1) + { + nameLen += sprintf(result + nameLen, ".%d", minorVer); + if (subVer != -1) + { + sprintf(result + nameLen, ".%d", subVer); + } + } +} + +// Try to open the necessary ICU libraries +bool OpenICULibraries(int majorVer, int minorVer, int subVer) +{ + char libicuucName[64]; + char libicui18nName[64]; + + static_assert(sizeof("libicuuc.so") + MaxICUVersionStringLength <= sizeof(libicuucName), "The libicuucName is too small"); + GetVersionedLibFileName("libicuuc.so", majorVer, minorVer, subVer, libicuucName); + + static_assert(sizeof("libicui18n.so") + MaxICUVersionStringLength <= sizeof(libicui18nName), "The libicui18nName is too small"); + GetVersionedLibFileName("libicui18n.so", majorVer, minorVer, subVer, libicui18nName); + + libicuuc = dlopen(libicuucName, RTLD_LAZY); + if (libicuuc != nullptr) + { + libicui18n = dlopen(libicui18nName, RTLD_LAZY); + if (libicui18n == nullptr) + { + dlclose(libicuuc); + libicuuc = nullptr; + } + } + + return libicuuc != nullptr; +} + +// Select libraries using the version override specified by the CLR_ICU_VERSION_OVERRIDE +// environment variable. +// The format of the string in this variable is majorVer[.minorVer[.subVer]] (the brackets +// indicate optional parts). +bool FindLibUsingOverride(int* majorVer, int* minorVer, int* subVer) +{ + char* versionOverride = getenv("CLR_ICU_VERSION_OVERRIDE"); + if (versionOverride != nullptr) + { + int first = -1; + int second = -1; + int third = -1; + + int matches = sscanf(versionOverride, "%d.%d.%d", &first, &second, &third); + if (matches > 0) + { + if (OpenICULibraries(first, second, third)) + { + *majorVer = first; + *minorVer = second; + *subVer = third; + return true; + } + } + } + + return false; +} + +// Select the highest supported version of ICU present on the local machine +// Search for library files with names including the major and minor version. +bool FindLibWithMajorMinorVersion(int* majorVer, int* minorVer) +{ + for (int i = MaxICUVersion; i >= MinICUVersion; i--) + { + for (int j = MaxMinorICUVersion; j >= MinMinorICUVersion; j--) + { + if (OpenICULibraries(i, j, -1)) + { + *majorVer = i; + *minorVer = j; + return true; + } + } + } + + return false; +} + +// Select the highest supported version of ICU present on the local machine +// Search for library files with names including the major, minor and sub version. +bool FindLibWithMajorMinorSubVersion(int* majorVer, int* minorVer, int* subVer) +{ + for (int i = MaxICUVersion; i >= MinICUVersion; i--) + { + for (int j = MaxMinorICUVersion; j >= MinMinorICUVersion; j--) + { + for (int k = MaxSubICUVersion; k >= MinSubICUVersion; k--) + { + if (OpenICULibraries(i, j, k)) + { + *majorVer = i; + *minorVer = j; + *subVer = k; + return true; + } + } + } + } + + return false; +} + +// This function is ran at the end of dlopen for the current shared library +__attribute__((constructor)) +void InitializeICUShim() +{ + int majorVer = -1; + int minorVer = -1; + int subVer = -1; + + if (!FindLibUsingOverride(&majorVer, &minorVer, &subVer) && + !FindLibWithMajorMinorVersion(&majorVer, &minorVer) && + !FindLibWithMajorMinorSubVersion(&majorVer, &minorVer, &subVer)) + { + // No usable ICU version found + fprintf(stderr, "No usable version of the ICU libraries was found\n"); + abort(); + } + + char symbolName[128]; + char symbolVersion[MaxICUVersionStringLength + 1] = ""; + + // Find out the format of the version string added to each symbol + // First try just the unversioned symbol + if (dlsym(libicuuc, "u_strlen") == nullptr) + { + // Now try just the _majorVer added + sprintf(symbolVersion, "_%d", majorVer); + sprintf(symbolName, "u_strlen%s", symbolVersion); + if (dlsym(libicuuc, symbolName) == nullptr) + { + // Now try the _majorVer_minorVer added + sprintf(symbolVersion, "_%d_%d", majorVer, minorVer); + sprintf(symbolName, "u_strlen%s", symbolVersion); + if (dlsym(libicuuc, symbolName) == nullptr) + { + // Finally, try the _majorVer_minorVer_subVer added + sprintf(symbolVersion, "_%d_%d_%d", majorVer, minorVer, subVer); + sprintf(symbolName, "u_strlen%s", symbolVersion); + if (dlsym(libicuuc, symbolName) == nullptr) + { + fprintf(stderr, "ICU libraries use unknown symbol versioning\n"); + abort(); + } + } + } + } + + // Get pointers to all the ICU functions that are needed +#define PER_FUNCTION_BLOCK(fn, lib) \ + static_assert((sizeof(#fn) + MaxICUVersionStringLength + 1) <= sizeof(symbolName), "The symbolName is too small for symbol " #fn); \ + sprintf(symbolName, #fn "%s", symbolVersion); \ + fn##_ptr = (decltype(fn)*)dlsym(lib, symbolName); \ + if (fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from " #lib "\n", symbolName); abort(); } + + FOR_ALL_ICU_FUNCTIONS +#undef PER_FUNCTION_BLOCK +} + +__attribute__((destructor)) +void ShutdownICUShim() +{ + if (libicuuc != nullptr) + { + dlclose(libicuuc); + } + + if (libicui18n != nullptr) + { + dlclose(libicui18n); + } +} diff --git a/src/corefx/System.Globalization.Native/icushim.h b/src/corefx/System.Globalization.Native/icushim.h new file mode 100644 index 0000000..8ec13d5 --- /dev/null +++ b/src/corefx/System.Globalization.Native/icushim.h @@ -0,0 +1,243 @@ +// 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. +// + +// Enable calling ICU functions through shims to enable support for +// multiple versions of ICU if the FEATURE_FIXED_ICU_VERSION is +// not defined. + +#ifndef __ICUSHIM_H__ +#define __ICUSHIM_H__ + +#include "config.h" + +#ifndef FEATURE_FIXED_ICU_VERSION +#define U_DISABLE_RENAMING 1 +#endif + +// All ICU headers need to be included here so that all function prototypes are +// available before the function pointers are declared below. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef FEATURE_FIXED_ICU_VERSION + +// List of all functions from the ICU libraries that are used in the System.Globalization.Native.so +#define FOR_ALL_UNCONDITIONAL_ICU_FUNCTIONS \ + PER_FUNCTION_BLOCK(u_charsToUChars, libicuuc) \ + PER_FUNCTION_BLOCK(u_strlen, libicuuc) \ + PER_FUNCTION_BLOCK(u_strncpy, libicuuc) \ + PER_FUNCTION_BLOCK(u_tolower, libicuuc) \ + PER_FUNCTION_BLOCK(u_toupper, libicuuc) \ + PER_FUNCTION_BLOCK(ucal_add, libicui18n) \ + PER_FUNCTION_BLOCK(ucal_close, libicui18n) \ + PER_FUNCTION_BLOCK(ucal_get, libicui18n) \ + PER_FUNCTION_BLOCK(ucal_getAttribute, libicui18n) \ + PER_FUNCTION_BLOCK(ucal_getKeywordValuesForLocale, libicui18n) \ + PER_FUNCTION_BLOCK(ucal_getLimit, libicui18n) \ + PER_FUNCTION_BLOCK(ucal_getTimeZoneDisplayName, libicui18n) \ + PER_FUNCTION_BLOCK(ucal_open, libicui18n) \ + PER_FUNCTION_BLOCK(ucal_set, libicui18n) \ + PER_FUNCTION_BLOCK(ucol_close, libicui18n) \ + PER_FUNCTION_BLOCK(ucol_closeElements, libicui18n) \ + PER_FUNCTION_BLOCK(ucol_getRules, libicui18n) \ + PER_FUNCTION_BLOCK(ucol_getSortKey, libicui18n) \ + PER_FUNCTION_BLOCK(ucol_getStrength, libicui18n) \ + PER_FUNCTION_BLOCK(ucol_next, libicui18n) \ + PER_FUNCTION_BLOCK(ucol_open, libicui18n) \ + PER_FUNCTION_BLOCK(ucol_openElements, libicui18n) \ + PER_FUNCTION_BLOCK(ucol_openRules, libicui18n) \ + PER_FUNCTION_BLOCK(ucol_safeClone, libicui18n) \ + PER_FUNCTION_BLOCK(ucol_setAttribute, libicui18n) \ + PER_FUNCTION_BLOCK(ucol_strcoll, libicui18n) \ + PER_FUNCTION_BLOCK(ucurr_forLocale, libicui18n) \ + PER_FUNCTION_BLOCK(ucurr_getName, libicui18n) \ + PER_FUNCTION_BLOCK(udat_close, libicui18n) \ + PER_FUNCTION_BLOCK(udat_countSymbols, libicui18n) \ + PER_FUNCTION_BLOCK(udat_getSymbols, libicui18n) \ + PER_FUNCTION_BLOCK(udat_open, libicui18n) \ + PER_FUNCTION_BLOCK(udat_setCalendar, libicui18n) \ + PER_FUNCTION_BLOCK(udat_toPattern, libicui18n) \ + PER_FUNCTION_BLOCK(udatpg_close, libicui18n) \ + PER_FUNCTION_BLOCK(udatpg_getBestPattern, libicui18n) \ + PER_FUNCTION_BLOCK(udatpg_open, libicui18n) \ + PER_FUNCTION_BLOCK(uenum_close, libicuuc) \ + PER_FUNCTION_BLOCK(uenum_count, libicuuc) \ + PER_FUNCTION_BLOCK(uenum_next, libicuuc) \ + PER_FUNCTION_BLOCK(uidna_close, libicuuc) \ + PER_FUNCTION_BLOCK(uidna_nameToASCII, libicuuc) \ + PER_FUNCTION_BLOCK(uidna_nameToUnicode, libicuuc) \ + PER_FUNCTION_BLOCK(uidna_openUTS46, libicuuc) \ + PER_FUNCTION_BLOCK(uldn_close, libicui18n) \ + PER_FUNCTION_BLOCK(uldn_keyValueDisplayName, libicui18n) \ + PER_FUNCTION_BLOCK(uldn_open, libicui18n) \ + PER_FUNCTION_BLOCK(uloc_canonicalize, libicuuc) \ + PER_FUNCTION_BLOCK(uloc_countAvailable, libicuuc) \ + PER_FUNCTION_BLOCK(uloc_getAvailable, libicuuc) \ + PER_FUNCTION_BLOCK(uloc_getBaseName, libicuuc) \ + PER_FUNCTION_BLOCK(uloc_getCharacterOrientation, libicuuc) \ + PER_FUNCTION_BLOCK(uloc_getCountry, libicuuc) \ + PER_FUNCTION_BLOCK(uloc_getDefault, libicuuc) \ + PER_FUNCTION_BLOCK(uloc_getDisplayCountry, libicuuc) \ + PER_FUNCTION_BLOCK(uloc_getDisplayLanguage, libicuuc) \ + PER_FUNCTION_BLOCK(uloc_getDisplayName, libicuuc) \ + PER_FUNCTION_BLOCK(uloc_getISO3Country, libicuuc) \ + PER_FUNCTION_BLOCK(uloc_getISO3Language, libicuuc) \ + PER_FUNCTION_BLOCK(uloc_getKeywordValue, libicuuc) \ + PER_FUNCTION_BLOCK(uloc_getLanguage, libicuuc) \ + PER_FUNCTION_BLOCK(uloc_getLCID, libicuuc) \ + PER_FUNCTION_BLOCK(uloc_getName, libicuuc) \ + PER_FUNCTION_BLOCK(uloc_getParent, libicuuc) \ + PER_FUNCTION_BLOCK(uloc_setKeywordValue, libicuuc) \ + PER_FUNCTION_BLOCK(ulocdata_getMeasurementSystem, libicui18n) \ + PER_FUNCTION_BLOCK(unorm2_getNFCInstance, libicuuc) \ + PER_FUNCTION_BLOCK(unorm2_getNFDInstance, libicuuc) \ + PER_FUNCTION_BLOCK(unorm2_getNFKCInstance, libicuuc) \ + PER_FUNCTION_BLOCK(unorm2_getNFKDInstance, libicuuc) \ + PER_FUNCTION_BLOCK(unorm2_isNormalized, libicuuc) \ + PER_FUNCTION_BLOCK(unorm2_normalize, libicuuc) \ + PER_FUNCTION_BLOCK(unum_close, libicui18n) \ + PER_FUNCTION_BLOCK(unum_getAttribute, libicui18n) \ + PER_FUNCTION_BLOCK(unum_getSymbol, libicui18n) \ + PER_FUNCTION_BLOCK(unum_open, libicui18n) \ + PER_FUNCTION_BLOCK(unum_toPattern, libicui18n) \ + PER_FUNCTION_BLOCK(ures_close, libicuuc) \ + PER_FUNCTION_BLOCK(ures_getByKey, libicuuc) \ + PER_FUNCTION_BLOCK(ures_getSize, libicuuc) \ + PER_FUNCTION_BLOCK(ures_getStringByIndex, libicuuc) \ + PER_FUNCTION_BLOCK(ures_open, libicuuc) \ + PER_FUNCTION_BLOCK(usearch_close, libicui18n) \ + PER_FUNCTION_BLOCK(usearch_first, libicui18n) \ + PER_FUNCTION_BLOCK(usearch_getMatchedLength, libicui18n) \ + PER_FUNCTION_BLOCK(usearch_last, libicui18n) \ + PER_FUNCTION_BLOCK(usearch_openFromCollator, libicui18n) + +#if HAVE_SET_MAX_VARIABLE +#define FOR_ALL_ICU_FUNCTIONS \ + FOR_ALL_UNCONDITIONAL_ICU_FUNCTIONS \ + PER_FUNCTION_BLOCK(ucol_setMaxVariable, libicui18n) +#else +#define FOR_ALL_ICU_FUNCTIONS \ + FOR_ALL_UNCONDITIONAL_ICU_FUNCTIONS \ + PER_FUNCTION_BLOCK(ucol_setVariableTop, libicui18n) +#endif + +// Declare pointers to all the used ICU functions +#define PER_FUNCTION_BLOCK(fn, lib) extern decltype(fn)* fn##_ptr; +FOR_ALL_ICU_FUNCTIONS +#undef PER_FUNCTION_BLOCK + +// Redefine all calls to ICU functions as calls through pointers that are set +// to the functions of the selected version of ICU in the initialization. +#define u_charsToUChars(...) u_charsToUChars_ptr(__VA_ARGS__) +#define u_strlen(...) u_strlen_ptr(__VA_ARGS__) +#define u_strncpy(...) u_strncpy_ptr(__VA_ARGS__) +#define u_tolower(...) u_tolower_ptr(__VA_ARGS__) +#define u_toupper(...) u_toupper_ptr(__VA_ARGS__) +#define ucal_add(...) ucal_add_ptr(__VA_ARGS__) +#define ucal_close(...) ucal_close_ptr(__VA_ARGS__) +#define ucal_get(...) ucal_get_ptr(__VA_ARGS__) +#define ucal_getAttribute(...) ucal_getAttribute_ptr(__VA_ARGS__) +#define ucal_getKeywordValuesForLocale(...) ucal_getKeywordValuesForLocale_ptr(__VA_ARGS__) +#define ucal_getLimit(...) ucal_getLimit_ptr(__VA_ARGS__) +#define ucal_getTimeZoneDisplayName(...) ucal_getTimeZoneDisplayName_ptr(__VA_ARGS__) +#define ucal_open(...) ucal_open_ptr(__VA_ARGS__) +#define ucal_set(...) ucal_set_ptr(__VA_ARGS__) +#define ucol_close(...) ucol_close_ptr(__VA_ARGS__) +#define ucol_closeElements(...) ucol_closeElements_ptr(__VA_ARGS__) +#define ucol_getRules(...) ucol_getRules_ptr(__VA_ARGS__) +#define ucol_getSortKey(...) ucol_getSortKey_ptr(__VA_ARGS__) +#define ucol_getStrength(...) ucol_getStrength_ptr(__VA_ARGS__) +#define ucol_next(...) ucol_next_ptr(__VA_ARGS__) +#define ucol_open(...) ucol_open_ptr(__VA_ARGS__) +#define ucol_openElements(...) ucol_openElements_ptr(__VA_ARGS__) +#define ucol_openRules(...) ucol_openRules_ptr(__VA_ARGS__) +#define ucol_safeClone(...) ucol_safeClone_ptr(__VA_ARGS__) +#define ucol_setAttribute(...) ucol_setAttribute_ptr(__VA_ARGS__) +#if HAVE_SET_MAX_VARIABLE +#define ucol_setMaxVariable(...) ucol_setMaxVariable_ptr(__VA_ARGS__) +#else +#define ucol_setVariableTop(...) ucol_setVariableTop_ptr(__VA_ARGS__) +#endif +#define ucol_strcoll(...) ucol_strcoll_ptr(__VA_ARGS__) +#define ucurr_forLocale(...) ucurr_forLocale_ptr(__VA_ARGS__) +#define ucurr_getName(...) ucurr_getName_ptr(__VA_ARGS__) +#define udat_close(...) udat_close_ptr(__VA_ARGS__) +#define udat_countSymbols(...) udat_countSymbols_ptr(__VA_ARGS__) +#define udat_getSymbols(...) udat_getSymbols_ptr(__VA_ARGS__) +#define udat_open(...) udat_open_ptr(__VA_ARGS__) +#define udat_setCalendar(...) udat_setCalendar_ptr(__VA_ARGS__) +#define udat_toPattern(...) udat_toPattern_ptr(__VA_ARGS__) +#define udatpg_close(...) udatpg_close_ptr(__VA_ARGS__) +#define udatpg_getBestPattern(...) udatpg_getBestPattern_ptr(__VA_ARGS__) +#define udatpg_open(...) udatpg_open_ptr(__VA_ARGS__) +#define uenum_close(...) uenum_close_ptr(__VA_ARGS__) +#define uenum_count(...) uenum_count_ptr(__VA_ARGS__) +#define uenum_next(...) uenum_next_ptr(__VA_ARGS__) +#define uidna_close(...) uidna_close_ptr(__VA_ARGS__) +#define uidna_nameToASCII(...) uidna_nameToASCII_ptr(__VA_ARGS__) +#define uidna_nameToUnicode(...) uidna_nameToUnicode_ptr(__VA_ARGS__) +#define uidna_openUTS46(...) uidna_openUTS46_ptr(__VA_ARGS__) +#define uldn_close(...) uldn_close_ptr(__VA_ARGS__) +#define uldn_keyValueDisplayName(...) uldn_keyValueDisplayName_ptr(__VA_ARGS__) +#define uldn_open(...) uldn_open_ptr(__VA_ARGS__) +#define uloc_canonicalize(...) uloc_canonicalize_ptr(__VA_ARGS__) +#define uloc_countAvailable(...) uloc_countAvailable_ptr(__VA_ARGS__) +#define uloc_getAvailable(...) uloc_getAvailable_ptr(__VA_ARGS__) +#define uloc_getBaseName(...) uloc_getBaseName_ptr(__VA_ARGS__) +#define uloc_getCharacterOrientation(...) uloc_getCharacterOrientation_ptr(__VA_ARGS__) +#define uloc_getCountry(...) uloc_getCountry_ptr(__VA_ARGS__) +#define uloc_getDefault(...) uloc_getDefault_ptr(__VA_ARGS__) +#define uloc_getDisplayCountry(...) uloc_getDisplayCountry_ptr(__VA_ARGS__) +#define uloc_getDisplayLanguage(...) uloc_getDisplayLanguage_ptr(__VA_ARGS__) +#define uloc_getDisplayName(...) uloc_getDisplayName_ptr(__VA_ARGS__) +#define uloc_getISO3Country(...) uloc_getISO3Country_ptr(__VA_ARGS__) +#define uloc_getISO3Language(...) uloc_getISO3Language_ptr(__VA_ARGS__) +#define uloc_getKeywordValue(...) uloc_getKeywordValue_ptr(__VA_ARGS__) +#define uloc_getLanguage(...) uloc_getLanguage_ptr(__VA_ARGS__) +#define uloc_getLCID(...) uloc_getLCID_ptr(__VA_ARGS__) +#define uloc_getName(...) uloc_getName_ptr(__VA_ARGS__) +#define uloc_getParent(...) uloc_getParent_ptr(__VA_ARGS__) +#define uloc_setKeywordValue(...) uloc_setKeywordValue_ptr(__VA_ARGS__) +#define ulocdata_getMeasurementSystem(...) ulocdata_getMeasurementSystem_ptr(__VA_ARGS__) +#define unorm2_getNFCInstance(...) unorm2_getNFCInstance_ptr(__VA_ARGS__) +#define unorm2_getNFDInstance(...) unorm2_getNFDInstance_ptr(__VA_ARGS__) +#define unorm2_getNFKCInstance(...) unorm2_getNFKCInstance_ptr(__VA_ARGS__) +#define unorm2_getNFKDInstance(...) unorm2_getNFKDInstance_ptr(__VA_ARGS__) +#define unorm2_isNormalized(...) unorm2_isNormalized_ptr(__VA_ARGS__) +#define unorm2_normalize(...) unorm2_normalize_ptr(__VA_ARGS__) +#define unum_close(...) unum_close_ptr(__VA_ARGS__) +#define unum_getAttribute(...) unum_getAttribute_ptr(__VA_ARGS__) +#define unum_getSymbol(...) unum_getSymbol_ptr(__VA_ARGS__) +#define unum_open(...) unum_open_ptr(__VA_ARGS__) +#define unum_toPattern(...) unum_toPattern_ptr(__VA_ARGS__) +#define ures_close(...) ures_close_ptr(__VA_ARGS__) +#define ures_getByKey(...) ures_getByKey_ptr(__VA_ARGS__) +#define ures_getSize(...) ures_getSize_ptr(__VA_ARGS__) +#define ures_getStringByIndex(...) ures_getStringByIndex_ptr(__VA_ARGS__) +#define ures_open(...) ures_open_ptr(__VA_ARGS__) +#define usearch_close(...) usearch_close_ptr(__VA_ARGS__) +#define usearch_first(...) usearch_first_ptr(__VA_ARGS__) +#define usearch_getMatchedLength(...) usearch_getMatchedLength_ptr(__VA_ARGS__) +#define usearch_last(...) usearch_last_ptr(__VA_ARGS__) +#define usearch_openFromCollator(...) usearch_openFromCollator_ptr(__VA_ARGS__) + +#endif // !FEATURE_ICU_VERSION_RESILIENT + +#endif // __ICUSHIM_H__ diff --git a/src/corefx/System.Globalization.Native/idna.cpp b/src/corefx/System.Globalization.Native/idna.cpp index 4820d2c..23942b3 100644 --- a/src/corefx/System.Globalization.Native/idna.cpp +++ b/src/corefx/System.Globalization.Native/idna.cpp @@ -4,7 +4,7 @@ // #include -#include +#include "icushim.h" const uint32_t AllowUnassigned = 0x1; const uint32_t UseStd3AsciiRules = 0x2; diff --git a/src/corefx/System.Globalization.Native/locale.cpp b/src/corefx/System.Globalization.Native/locale.cpp index 1cb564a..951179d 100644 --- a/src/corefx/System.Globalization.Native/locale.cpp +++ b/src/corefx/System.Globalization.Native/locale.cpp @@ -9,6 +9,7 @@ #include #include +#include "icushim.h" #include "locale.hpp" int32_t UErrorCodeToBool(UErrorCode status) @@ -147,6 +148,56 @@ const char* DetectDefaultLocaleName() return uloc_getDefault(); } +// GlobalizationNative_GetLocales gets all locale names and store it in the value buffer +// in case of success, it returns the count of the characters stored in value buffer +// in case of failure, it returns negative number. +// if the input value buffer is null, it returns the length needed to store the +// locale names list. +// if the value is not null, it fills the value with locale names separated by the length +// of each name. +extern "C" int32_t GlobalizationNative_GetLocales(UChar *value, int32_t valueLength) +{ + int32_t totalLength = 0; + int32_t index = 0; + int32_t localeCount = uloc_countAvailable(); + + if (localeCount <= 0) + return -1; // failed + + for (int32_t i = 0; i < localeCount; i++) + { + const char *pLocaleName = uloc_getAvailable(i); + if (pLocaleName[0] == 0) // unexpected empty name + return -2; + + int32_t localeNameLength = strlen(pLocaleName); + + totalLength += localeNameLength + 1; // add 1 for the name length + + if (value != nullptr) + { + if (totalLength > valueLength) + return -3; + + value[index++] = (UChar) localeNameLength; + + for (int j=0; j #include -#include - +#include "icushim.h" #include "locale.hpp" #include "holders.h" diff --git a/src/corefx/System.Globalization.Native/localeStringData.cpp b/src/corefx/System.Globalization.Native/localeStringData.cpp index 927da67..b8eaa30 100644 --- a/src/corefx/System.Globalization.Native/localeStringData.cpp +++ b/src/corefx/System.Globalization.Native/localeStringData.cpp @@ -7,6 +7,7 @@ #include #include +#include "icushim.h" #include "locale.hpp" #include "holders.h" @@ -27,6 +28,8 @@ enum LocaleStringData : int32_t ThousandSeparator = 0x0000000F, Digits = 0x00000013, MonetarySymbol = 0x00000014, + CurrencyEnglishName = 0x00001007, + CurrencyNativeName = 0x00001008, Iso4217MonetarySymbol = 0x00000015, MonetaryDecimalSeparator = 0x00000016, MonetaryThousandSeparator = 0x00000017, @@ -34,8 +37,10 @@ enum LocaleStringData : int32_t PMDesignator = 0x00000029, PositiveSign = 0x00000050, NegativeSign = 0x00000051, - Iso639LanguageName = 0x00000059, + Iso639LanguageTwoLetterName = 0x00000059, + Iso639LanguageThreeLetterName = 0x00000067, Iso3166CountryName = 0x0000005A, + Iso3166CountryName2= 0x00000068, NaNSymbol = 0x00000069, PositiveInfinitySymbol = 0x0000006a, ParentName = 0x0000006d, @@ -111,11 +116,11 @@ UErrorCode GetLocaleInfoAmPm(const char* locale, bool am, UChar* value, int32_t /* Function: -GetLocaleIso639LanguageName +GetLocaleIso639LanguageTwoLetterName Gets the language name for a locale (via uloc_getLanguage) and converts the result to UChars */ -UErrorCode GetLocaleIso639LanguageName(const char* locale, UChar* value, int32_t valueLength) +UErrorCode GetLocaleIso639LanguageTwoLetterName(const char* locale, UChar* value, int32_t valueLength) { UErrorCode status = U_ZERO_ERROR; int32_t length = uloc_getLanguage(locale, nullptr, 0, &status); @@ -135,6 +140,23 @@ UErrorCode GetLocaleIso639LanguageName(const char* locale, UChar* value, int32_t /* Function: +GetLocaleIso639LanguageThreeLetterName + +Gets the language name for a locale (via uloc_getISO3Language) and converts the result to UChars +*/ +UErrorCode GetLocaleIso639LanguageThreeLetterName(const char* locale, UChar* value, int32_t valueLength) +{ + const char *isoLanguage = uloc_getISO3Language(locale); + if (isoLanguage[0] == 0) + { + return U_ILLEGAL_ARGUMENT_ERROR; + } + + return u_charsToUChars_safe(isoLanguage, value, valueLength); +} + +/* +Function: GetLocaleIso3166CountryName Gets the country name for a locale (via uloc_getCountry) and converts the result to UChars @@ -158,6 +180,66 @@ UErrorCode GetLocaleIso3166CountryName(const char* locale, UChar* value, int32_t } /* +Function: +GetLocaleIso3166CountryCode + +Gets the 3 letter country code for a locale (via uloc_getISO3Country) and converts the result to UChars +*/ +UErrorCode GetLocaleIso3166CountryCode(const char* locale, UChar* value, int32_t valueLength) +{ + const char *pIsoCountryName = uloc_getISO3Country(locale); + int len = strlen(pIsoCountryName); + + if (len == 0) + { + return U_ILLEGAL_ARGUMENT_ERROR; + } + + return u_charsToUChars_safe(pIsoCountryName, value, valueLength); +} + +/* +Function: +GetLocaleCurrencyName + +Gets the locale currency English or native name and convert the result to UChars +*/ +UErrorCode GetLocaleCurrencyName(const char* locale, bool nativeName, UChar* value, int32_t valueLength) +{ + UErrorCode status = U_ZERO_ERROR; + + UChar currencyThreeLettersName[4]; // 3 letters currency iso name + NULL + ucurr_forLocale(locale, currencyThreeLettersName, 4, &status); + if (!U_SUCCESS(status)) + { + return status; + } + + int32_t len; + UBool formatChoice; + const UChar *pCurrencyLongName = ucurr_getName( + currencyThreeLettersName, + nativeName ? locale : ULOC_US, + UCURR_LONG_NAME, + &formatChoice, + &len, + &status); + if (!U_SUCCESS(status)) + { + return status; + } + + if (len >= valueLength) // we need to have room for NULL too + { + return U_BUFFER_OVERFLOW_ERROR; + } + u_strncpy(value, pCurrencyLongName, len); + value[len] = 0; + + return status; +} + +/* PAL Function: GetLocaleInfoString @@ -226,6 +308,12 @@ extern "C" int32_t GlobalizationNative_GetLocaleInfoString( case Iso4217MonetarySymbol: status = GetLocaleInfoDecimalFormatSymbol(locale, UNUM_INTL_CURRENCY_SYMBOL, value, valueLength); break; + case CurrencyEnglishName: + status = GetLocaleCurrencyName(locale, false, value, valueLength); + break; + case CurrencyNativeName: + status = GetLocaleCurrencyName(locale, true, value, valueLength); + break; case MonetaryDecimalSeparator: status = GetLocaleInfoDecimalFormatSymbol(locale, UNUM_MONETARY_SEPARATOR_SYMBOL, value, valueLength); break; @@ -245,12 +333,18 @@ extern "C" int32_t GlobalizationNative_GetLocaleInfoString( case NegativeSign: status = GetLocaleInfoDecimalFormatSymbol(locale, UNUM_MINUS_SIGN_SYMBOL, value, valueLength); break; - case Iso639LanguageName: - status = GetLocaleIso639LanguageName(locale, value, valueLength); + case Iso639LanguageTwoLetterName: + status = GetLocaleIso639LanguageTwoLetterName(locale, value, valueLength); + break; + case Iso639LanguageThreeLetterName: + status = GetLocaleIso639LanguageThreeLetterName(locale, value, valueLength); break; case Iso3166CountryName: status = GetLocaleIso3166CountryName(locale, value, valueLength); break; + case Iso3166CountryName2: + status = GetLocaleIso3166CountryCode(locale, value, valueLength); + break; case NaNSymbol: status = GetLocaleInfoDecimalFormatSymbol(locale, UNUM_NAN_SYMBOL, value, valueLength); break; diff --git a/src/corefx/System.Globalization.Native/normalization.cpp b/src/corefx/System.Globalization.Native/normalization.cpp index f96f5ee..014894a 100644 --- a/src/corefx/System.Globalization.Native/normalization.cpp +++ b/src/corefx/System.Globalization.Native/normalization.cpp @@ -4,7 +4,7 @@ // #include -#include +#include "icushim.h" /* * These values should be kept in sync with System.Text.NormalizationForm diff --git a/src/corefx/System.Globalization.Native/timeZoneInfo.cpp b/src/corefx/System.Globalization.Native/timeZoneInfo.cpp index d0e01e5..0dd28b4 100644 --- a/src/corefx/System.Globalization.Native/timeZoneInfo.cpp +++ b/src/corefx/System.Globalization.Native/timeZoneInfo.cpp @@ -5,8 +5,8 @@ #include #include -#include +#include "icushim.h" #include "locale.hpp" #include "holders.h" #include "errors.h" diff --git a/src/debug/daccess/daccess.cpp b/src/debug/daccess/daccess.cpp index ba3995b..69167ab 100644 --- a/src/debug/daccess/daccess.cpp +++ b/src/debug/daccess/daccess.cpp @@ -5888,14 +5888,15 @@ ClrDataAccess::RawGetMethodName( LPCWSTR wszStubManagerName = pStubManager->GetStubManagerName(TO_TADDR(address)); _ASSERTE(wszStubManagerName != NULL); - HRESULT hr = StringCchPrintfW( + int result = _snwprintf_s( symbolBuf, bufLen, + _TRUNCATE, s_wszFormatNameWithStubManager, wszStubManagerName, // Arg 1 = stub name TO_TADDR(address)); // Arg 2 = stub hex address - if (hr == S_OK) + if (result != -1) { // Printf succeeded, so we have an exact char count to return if (symbolLen) @@ -5951,13 +5952,14 @@ NameFromMethodDesc: // XXX Microsoft - Should this case have a more specific name? static WCHAR s_wszFormatNameAddressOnly[] = W("CLRStub@%I64x"); - HRESULT hr = StringCchPrintfW( + int result = _snwprintf_s( symbolBuf, bufLen, + _TRUNCATE, s_wszFormatNameAddressOnly, TO_TADDR(address)); - if (hr == S_OK) + if (result != -1) { // Printf succeeded, so we have an exact char count to return if (symbolLen) @@ -7352,7 +7354,7 @@ Exit: //---------------------------------------------------------------------------- // -// IsExceptionFromManagedCode - report if pExceptionRecord points to a exception belonging to the current runtime +// IsExceptionFromManagedCode - report if pExceptionRecord points to an exception belonging to the current runtime // // Arguments: // pExceptionRecord - the exception record @@ -7974,7 +7976,7 @@ HRESULT DacHandleWalker::Init(ClrDataAccess *dac, UINT types[], UINT typeCount, { SUPPORTS_DAC; - if (gen < 0 || gen > (int)GCHeap::GetMaxGeneration()) + if (gen < 0 || gen > (int)GCHeapUtilities::GetMaxGeneration()) return E_INVALIDARG; mGenerationFilter = gen; @@ -8033,7 +8035,7 @@ bool DacHandleWalker::FetchMoreHandles(HANDLESCANPROC callback) int max_slots = 1; #ifdef FEATURE_SVR_GC - if (GCHeap::IsServerHeap()) + if (GCHeapUtilities::IsServerHeap()) max_slots = GCHeapCount(); #endif // FEATURE_SVR_GC @@ -8089,7 +8091,7 @@ bool DacHandleWalker::FetchMoreHandles(HANDLESCANPROC callback) HndScanHandlesForGC(hTable, callback, (LPARAM)¶m, 0, &handleType, 1, - mGenerationFilter, GCHeap::GetMaxGeneration(), 0); + mGenerationFilter, GCHeapUtilities::GetMaxGeneration(), 0); else HndEnumHandles(hTable, &handleType, 1, callback, (LPARAM)¶m, 0, FALSE); } diff --git a/src/debug/daccess/daccess.targets b/src/debug/daccess/daccess.targets index a7d9e41..43da554 100644 --- a/src/debug/daccess/daccess.targets +++ b/src/debug/daccess/daccess.targets @@ -4,6 +4,12 @@ + + + + + true + diff --git a/src/debug/daccess/dacdbiimpl.cpp b/src/debug/daccess/dacdbiimpl.cpp index 9b17f4c..ae266e8 100644 --- a/src/debug/daccess/dacdbiimpl.cpp +++ b/src/debug/daccess/dacdbiimpl.cpp @@ -90,7 +90,7 @@ IDacDbiInterface::IAllocator * g_pAllocator = NULL; // // Need a class to serve as a tag that we can use to overload New/Delete. -#define forDbi (*(forDbiWorker *)NULL) +forDbiWorker forDbi; void * operator new(size_t lenBytes, const forDbiWorker &) { @@ -2364,10 +2364,12 @@ TypeHandle DacDbiInterfaceImpl::FindLoadedFnptrType(DWORD numTypeArgs, TypeHandl // Lookup operations run the class loader in non-load mode. ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE(); - // @dbgtodo : Do we need to worry about calling convention here? - return ClassLoader::LoadFnptrTypeThrowing(0, - numTypeArgs, - pInst, + // @dbgtodo : Do we need to worry about calling convention here? + // LoadFnptrTypeThrowing expects the count of arguments, not + // including return value, so we subtract 1 from numTypeArgs. + return ClassLoader::LoadFnptrTypeThrowing(0, + numTypeArgs - 1, + pInst, ClassLoader::DontLoadTypes); } // DacDbiInterfaceImpl::FindLoadedFnptrType @@ -6517,7 +6519,7 @@ HRESULT DacHeapWalker::Init(CORDB_ADDRESS start, CORDB_ADDRESS end) if (thread == NULL) continue; - alloc_context *ctx = thread->GetAllocContext(); + gc_alloc_context *ctx = thread->GetAllocContext(); if (ctx == NULL) continue; @@ -6533,7 +6535,7 @@ HRESULT DacHeapWalker::Init(CORDB_ADDRESS start, CORDB_ADDRESS end) } #ifdef FEATURE_SVR_GC - HRESULT hr = GCHeap::IsServerHeap() ? InitHeapDataSvr(mHeaps, mHeapCount) : InitHeapDataWks(mHeaps, mHeapCount); + HRESULT hr = GCHeapUtilities::IsServerHeap() ? InitHeapDataSvr(mHeaps, mHeapCount) : InitHeapDataWks(mHeaps, mHeapCount); #else HRESULT hr = InitHeapDataWks(mHeaps, mHeapCount); #endif @@ -6777,7 +6779,7 @@ HRESULT DacDbiInterfaceImpl::GetHeapSegments(OUT DacDbiArrayList *p HeapData *heaps = 0; #ifdef FEATURE_SVR_GC - HRESULT hr = GCHeap::IsServerHeap() ? DacHeapWalker::InitHeapDataSvr(heaps, heapCount) : DacHeapWalker::InitHeapDataWks(heaps, heapCount); + HRESULT hr = GCHeapUtilities::IsServerHeap() ? DacHeapWalker::InitHeapDataSvr(heaps, heapCount) : DacHeapWalker::InitHeapDataWks(heaps, heapCount); #else HRESULT hr = DacHeapWalker::InitHeapDataWks(heaps, heapCount); #endif @@ -6987,6 +6989,21 @@ HRESULT DacDbiInterfaceImpl::GetTypeID(CORDB_ADDRESS dbgObj, COR_TYPEID *pID) return hr; } +HRESULT DacDbiInterfaceImpl::GetTypeIDForType(VMPTR_TypeHandle vmTypeHandle, COR_TYPEID *pID) +{ + DD_ENTER_MAY_THROW; + + _ASSERTE(pID != NULL); + _ASSERTE(!vmTypeHandle.IsNull()); + + TypeHandle th = TypeHandle::FromPtr(vmTypeHandle.GetDacPtr()); + PTR_MethodTable pMT = th.GetMethodTable(); + pID->token1 = pMT.GetAddr(); + _ASSERTE(pID->token1 != 0); + pID->token2 = 0; + return S_OK; +} + HRESULT DacDbiInterfaceImpl::GetObjectFields(COR_TYPEID id, ULONG32 celt, COR_FIELD *layout, ULONG32 *pceltFetched) { if (layout == NULL || pceltFetched == NULL) @@ -7171,7 +7188,7 @@ void DacDbiInterfaceImpl::GetGCHeapInformation(COR_HEAPINFO * pHeapInfo) pHeapInfo->areGCStructuresValid = GCScan::GetGcRuntimeStructuresValid(); #ifdef FEATURE_SVR_GC - if (GCHeap::IsServerHeap()) + if (GCHeapUtilities::IsServerHeap()) { pHeapInfo->gcType = CorDebugServerGC; pHeapInfo->numHeaps = DacGetNumHeaps(); diff --git a/src/debug/daccess/dacdbiimpl.h b/src/debug/daccess/dacdbiimpl.h index 56d7b0d..a860723 100644 --- a/src/debug/daccess/dacdbiimpl.h +++ b/src/debug/daccess/dacdbiimpl.h @@ -138,11 +138,13 @@ public: HRESULT WalkRefs(RefWalkHandle handle, ULONG count, OUT DacGcReference * objects, OUT ULONG *pFetched); HRESULT GetTypeID(CORDB_ADDRESS obj, COR_TYPEID *pID); + + HRESULT GetTypeIDForType(VMPTR_TypeHandle vmTypeHandle, COR_TYPEID *pID); - HRESULT GetObjectFields(COR_TYPEID id, ULONG32 celt, COR_FIELD *layout, ULONG32 *pceltFetched); - HRESULT GetTypeLayout(COR_TYPEID id, COR_TYPE_LAYOUT *pLayout); - HRESULT GetArrayLayout(COR_TYPEID id, COR_ARRAY_LAYOUT *pLayout); - void GetGCHeapInformation(COR_HEAPINFO * pHeapInfo); + HRESULT GetObjectFields(COR_TYPEID id, ULONG32 celt, COR_FIELD *layout, ULONG32 *pceltFetched); + HRESULT GetTypeLayout(COR_TYPEID id, COR_TYPE_LAYOUT *pLayout); + HRESULT GetArrayLayout(COR_TYPEID id, COR_ARRAY_LAYOUT *pLayout); + void GetGCHeapInformation(COR_HEAPINFO * pHeapInfo); HRESULT GetPEFileMDInternalRW(VMPTR_PEFile vmPEFile, OUT TADDR* pAddrMDInternalRW); HRESULT GetReJitInfo(VMPTR_Module vmModule, mdMethodDef methodTk, OUT VMPTR_ReJitInfo* pReJitInfo); HRESULT GetReJitInfo(VMPTR_MethodDesc vmMethod, CORDB_ADDRESS codeStartAddress, OUT VMPTR_ReJitInfo* pReJitInfo); diff --git a/src/debug/daccess/dacfn.cpp b/src/debug/daccess/dacfn.cpp index 88d4599..d8bae77 100644 --- a/src/debug/daccess/dacfn.cpp +++ b/src/debug/daccess/dacfn.cpp @@ -217,7 +217,7 @@ DacWriteAll(TADDR addr, PVOID buffer, ULONG32 size, bool throwEx) return S_OK; } -#if defined(WIN64EXCEPTIONS) && defined(FEATURE_PAL) +#ifdef FEATURE_PAL HRESULT DacVirtualUnwind(DWORD threadId, PCONTEXT context, PT_KNONVOLATILE_CONTEXT_POINTERS contextPointers) { @@ -242,7 +242,7 @@ DacVirtualUnwind(DWORD threadId, PCONTEXT context, PT_KNONVOLATILE_CONTEXT_POINT return hr; } -#endif // defined(WIN64EXCEPTIONS) && defined(FEATURE_PAL) +#endif // FEATURE_PAL // DacAllocVirtual - Allocate memory from the target process // Note: this is only available to clients supporting the legacy diff --git a/src/debug/daccess/enummem.cpp b/src/debug/daccess/enummem.cpp index 068c2f2..d66af05 100644 --- a/src/debug/daccess/enummem.cpp +++ b/src/debug/daccess/enummem.cpp @@ -250,9 +250,9 @@ HRESULT ClrDataAccess::EnumMemCLRStatic(IN CLRDataEnumMemoryFlags flags) ReportMem(m_globalBase + g_dacGlobals.SharedDomain__m_pSharedDomain, sizeof(SharedDomain)); - // We need GCHeap pointer to make EEVersion work + // We need IGCHeap pointer to make EEVersion work ReportMem(m_globalBase + g_dacGlobals.dac__g_pGCHeap, - sizeof(GCHeap *)); + sizeof(IGCHeap *)); // see synblk.cpp, the pointer is pointed to a static byte[] SyncBlockCache::s_pSyncBlockCache.EnumMem(); @@ -292,7 +292,9 @@ HRESULT ClrDataAccess::EnumMemCLRStatic(IN CLRDataEnumMemoryFlags flags) CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_pValueTypeClass.EnumMem(); ) CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_pEnumClass.EnumMem(); ) CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_pThreadClass.EnumMem(); ) +#ifdef FEATURE_CER CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_pCriticalFinalizerObjectClass.EnumMem(); ) +#endif CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_pFreeObjectMethodTable.EnumMem(); ) CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_pObjectCtorMD.EnumMem(); ) CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_fHostConfig.EnumMem(); ) @@ -316,7 +318,7 @@ HRESULT ClrDataAccess::EnumMemCLRStatic(IN CLRDataEnumMemoryFlags flags) #ifdef FEATURE_SVR_GC CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED ( - GCHeap::gcHeapType.EnumMem(); + IGCHeap::gcHeapType.EnumMem(); ); #endif // FEATURE_SVR_GC @@ -796,10 +798,9 @@ HRESULT ClrDataAccess::EnumMemWalkStackHelper(CLRDataEnumMemoryFlags flags, currentSP = dac_cast(pThread->GetCachedStackLimit()) + sizeof(TADDR); // exhaust the frames using DAC api - bool frameHadContext; for (; status == S_OK; ) { - frameHadContext = false; + bool frameHadContext = false; status = pStackWalk->GetFrame(&pFrame); PCODE addr = NULL; if (status == S_OK && pFrame != NULL) diff --git a/src/debug/daccess/fntableaccess.cpp b/src/debug/daccess/fntableaccess.cpp index e7b96ec..6dcd584 100644 --- a/src/debug/daccess/fntableaccess.cpp +++ b/src/debug/daccess/fntableaccess.cpp @@ -11,6 +11,7 @@ #include "stdafx.h" +#ifndef FEATURE_PAL #ifndef _TARGET_X86_ // @@ -388,6 +389,7 @@ static NTSTATUS OutOfProcessFunctionTableCallback_Stub(IN ReadMemoryFunction #endif // DEBUGSUPPORT_STUBS_HAVE_UNWIND_INFO + BOOL ReadMemory(PVOID pUserContext, LPCVOID lpBaseAddress, PVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead) { HANDLE hProcess = (HANDLE)pUserContext; @@ -456,6 +458,5 @@ extern "C" NTSTATUS OutOfProcessFunctionTableCallbackEx() return STATUS_UNSUCCESSFUL; } - - #endif // !_TARGET_X86_ +#endif // !FEATURE_PAL \ No newline at end of file diff --git a/src/debug/daccess/fntableaccess.h b/src/debug/daccess/fntableaccess.h index 0dbabdf..b5ea545 100644 --- a/src/debug/daccess/fntableaccess.h +++ b/src/debug/daccess/fntableaccess.h @@ -51,6 +51,9 @@ typedef struct _FakeHpRealCodeHdr LPVOID phdrDebugInfo; LPVOID phdrJitEHInfo; // changed from EE_ILEXCEPTION* LPVOID phdrJitGCInfo; // changed from BYTE* +#if defined (FEATURE_GDBJIT) + LPVOID pCalledMethods; +#endif LPVOID hdrMDesc; // changed from MethodDesc* DWORD nUnwindInfos; T_RUNTIME_FUNCTION unwindInfos[0]; diff --git a/src/debug/daccess/nidump.cpp b/src/debug/daccess/nidump.cpp index 32eab49..23e76c4 100644 --- a/src/debug/daccess/nidump.cpp +++ b/src/debug/daccess/nidump.cpp @@ -1187,12 +1187,12 @@ NativeImageDumper::DumpNativeImage() mscorlib->fIsMscorlib = TRUE; _ASSERTE(mscorlib->fIsHardbound); } + + _ASSERTE(mscorlib != NULL); if( mscorlib->fIsHardbound ) { m_isMscorlibHardBound = true; } - - _ASSERTE(mscorlib != NULL); if( m_isMscorlibHardBound ) { //go through the module to the binder. @@ -3120,7 +3120,7 @@ void NativeImageDumper::DumpCompleteMethod(PTR_Module module, MethodIterator& mi #ifdef _TARGET_X86_ InfoHdr hdr; stringOutFn( "method info Block:\n" ); - curGCInfoPtr += gcDump.DumpInfoHdr(PTR_CBYTE(gcInfoToken.Info), &hdr, &methodSize, 0); + curGCInfoPtr += gcDump.DumpInfoHdr(curGCInfoPtr, &hdr, &methodSize, 0); stringOutFn( "\n" ); #endif @@ -4088,6 +4088,7 @@ void NativeImageDumper::DumpModule( PTR_Module module ) (int)(module->m_maxDynamicEntries * sizeof(*(module->m_pDynamicStaticsInfo)))); +#ifdef FEATURE_CER DisplayWriteFieldInt( m_dwReliabilityContract, module->m_dwReliabilityContract, Module, MODULE ); @@ -4105,6 +4106,7 @@ void NativeImageDumper::DumpModule( PTR_Module module ) offsetof(Module, m_pCerNgenRootTable), fieldsize(Module, m_pCerNgenRootTable) ); } +#endif _ASSERTE(module->m_debuggerSpecificData.m_pDynamicILCrst == NULL); @@ -4152,6 +4154,7 @@ bool NativeImageDumper::isPrecode(TADDR maybePrecode) return !!module->IsZappedPrecode(maybePrecode); } +#ifdef FEATURE_CER void NativeImageDumper::DumpNgenRootTable( PTR_CerNgenRootTable table, const char * name, unsigned offset, unsigned fieldSize ) @@ -4231,6 +4234,8 @@ void NativeImageDumper::DumpNgenRootTable( PTR_CerNgenRootTable table, DisplayEndStructure( MODULE ); //CERNgenRootTable } +#endif // FEATURE_CER + void NativeImageDumper::IterateTypeDefToMTCallback( TADDR mtTarget, TADDR flags, PTR_LookupMapBase map, @@ -9034,12 +9039,14 @@ NativeImageDumper::DumpEEClassForMethodTable( PTR_MethodTable mt ) DisplayWriteFieldInt( m_cbModuleDynamicID, pClassOptional->m_cbModuleDynamicID, EEClassOptionalFields, EECLASSES ); +#ifdef FEATURE_CER /* REVISIT_TODO Fri 10/14/2005 * Use the macros from ConstrainedExecutionRegion.cpp on this? */ DisplayWriteFieldUInt( m_dwReliabilityContract, clazz->GetReliabilityContract(), EEClassOptionalFields, EECLASSES ); +#endif DisplayWriteFieldEnumerated( m_SecProps, clazz->GetSecurityProperties()->dwFlags, EEClassOptionalFields, s_SecurityProperties, W("|"), @@ -9439,10 +9446,12 @@ void NativeImageDumper::DumpReadyToRunMethod(PCODE pEntryPoint, PTR_RUNTIME_FUNC g_holdStringOutData.Clear(); GCDump gcDump(GCINFO_VERSION); gcDump.gcPrintf = stringOutFn; -#if !defined(_TARGET_X86_) && defined(USE_GC_INFO_DECODER) UINT32 r2rversion = m_pReadyToRunHeader->MajorVersion; UINT32 gcInfoVersion = GCInfoToken::ReadyToRunVersionToGcInfoVersion(r2rversion); - GcInfoDecoder gcInfoDecoder({ curGCInfoPtr, gcInfoVersion }, DECODE_CODE_LENGTH); + GCInfoToken gcInfoToken = { curGCInfoPtr, gcInfoVersion }; + +#if !defined(_TARGET_X86_) && defined(USE_GC_INFO_DECODER) + GcInfoDecoder gcInfoDecoder(gcInfoToken, DECODE_CODE_LENGTH); methodSize = gcInfoDecoder.GetCodeLength(); #endif @@ -9541,8 +9550,10 @@ mdTypeRef NativeImageDumper::FindTypeRefForMT( PTR_MethodTable mt ) #undef GC_NOTRIGGER #if defined _DEBUG && defined _TARGET_X86_ +#ifdef _MSC_VER // disable FPO for checked build #pragma optimize("y", off) +#endif // _MSC_VER #endif #undef _ASSERTE diff --git a/src/debug/daccess/request.cpp b/src/debug/daccess/request.cpp index a30ec37..35ab5a0 100644 --- a/src/debug/daccess/request.cpp +++ b/src/debug/daccess/request.cpp @@ -725,7 +725,7 @@ ClrDataAccess::GetHeapAllocData(unsigned int count, struct DacpGenerationAllocDa SOSDacEnter(); #if defined(FEATURE_SVR_GC) - if (GCHeap::IsServerHeap()) + if (GCHeapUtilities::IsServerHeap()) { hr = GetServerAllocData(count, data, pNeeded); } @@ -2809,7 +2809,7 @@ ClrDataAccess::GetGCHeapDetails(CLRDATA_ADDRESS heap, struct DacpGcHeapDetails * SOSDacEnter(); // doesn't make sense to call this on WKS mode - if (!GCHeap::IsServerHeap()) + if (!GCHeapUtilities::IsServerHeap()) hr = E_INVALIDARG; else #ifdef FEATURE_SVR_GC @@ -2884,7 +2884,7 @@ ClrDataAccess::GetHeapSegmentData(CLRDATA_ADDRESS seg, struct DacpHeapSegmentDat SOSDacEnter(); - if (GCHeap::IsServerHeap()) + if (GCHeapUtilities::IsServerHeap()) { #if !defined(FEATURE_SVR_GC) _ASSERTE(0); @@ -2924,7 +2924,7 @@ ClrDataAccess::GetGCHeapList(unsigned int count, CLRDATA_ADDRESS heaps[], unsign SOSDacEnter(); // make sure we called this in appropriate circumstances (i.e., we have multiple heaps) - if (GCHeap::IsServerHeap()) + if (GCHeapUtilities::IsServerHeap()) { #if !defined(FEATURE_SVR_GC) _ASSERTE(0); @@ -2960,45 +2960,49 @@ ClrDataAccess::GetGCHeapData(struct DacpGcHeapData *gcheapData) SOSDacEnter(); - // Now get the heap type. The first data member of the GCHeap class is the GC_HEAP_TYPE, which has - // three possible values: + // for server GC-capable builds only, we need to check and see if IGCHeap::gcHeapType + // is GC_HEAP_INVALID, in which case we fail. + // IGCHeap::gcHeapType doesn't exist on non-server-GC capable builds. +#ifdef FEATURE_SVR_GC + ULONG32 gcHeapValue = IGCHeap::gcHeapType; + + // GC_HEAP_TYPE has three possible values: // GC_HEAP_INVALID = 0, // GC_HEAP_WKS = 1, // GC_HEAP_SVR = 2 + // If we get something other than that, we probably read the wrong location. + _ASSERTE(gcHeapValue >= IGCHeap::GC_HEAP_INVALID && gcHeapValue <= IGCHeap::GC_HEAP_SVR); - TADDR gcHeapLocation = g_pGCHeap.GetAddrRaw (); // get the starting address of the global GCHeap instance - size_t gcHeapValue = 0; // this will hold the heap type - ULONG32 returned = 0; - - // @todo Microsoft: we should probably be capturing the HRESULT from ReadVirtual. We could - // provide a more informative error message. E_FAIL is a wretchedly vague thing to return. - hr = m_pTarget->ReadVirtual(gcHeapLocation, (PBYTE)&gcHeapValue, sizeof(gcHeapValue), &returned); - - //@todo Microsoft: We have an enumerated type, we probably should use the symbolic name // we have GC_HEAP_INVALID if gcHeapValue == 0, so we're done - if (SUCCEEDED(hr) && ((returned != sizeof(gcHeapValue)) || (gcHeapValue == 0))) + if (gcHeapValue == IGCHeap::GC_HEAP_INVALID) + { hr = E_FAIL; + goto cleanup; + } +#endif - if (SUCCEEDED(hr)) + // Now we can get other important information about the heap + gcheapData->g_max_generation = GCHeapUtilities::GetMaxGeneration(); + gcheapData->bServerMode = GCHeapUtilities::IsServerHeap(); + gcheapData->bGcStructuresValid = GCScan::GetGcRuntimeStructuresValid(); + if (GCHeapUtilities::IsServerHeap()) { - // Now we can get other important information about the heap - gcheapData->g_max_generation = GCHeap::GetMaxGeneration(); - gcheapData->bServerMode = GCHeap::IsServerHeap(); - gcheapData->bGcStructuresValid = GCScan::GetGcRuntimeStructuresValid(); - if (GCHeap::IsServerHeap()) - { #if !defined (FEATURE_SVR_GC) - _ASSERTE(0); - gcheapData->HeapCount = 1; + _ASSERTE(0); + gcheapData->HeapCount = 1; #else // !defined (FEATURE_SVR_GC) - gcheapData->HeapCount = GCHeapCount(); + gcheapData->HeapCount = GCHeapCount(); #endif // !defined (FEATURE_SVR_GC) - } - else - { - gcheapData->HeapCount = 1; - } } + else + { + gcheapData->HeapCount = 1; + } + +#ifdef FEATURE_SVR_GC +cleanup: + ; +#endif SOSDacLeave(); return hr; @@ -3014,7 +3018,7 @@ ClrDataAccess::GetOOMStaticData(struct DacpOomData *oomData) memset(oomData, 0, sizeof(DacpOomData)); - if (!GCHeap::IsServerHeap()) + if (!GCHeapUtilities::IsServerHeap()) { oom_history* pOOMInfo = &(WKS::gc_heap::oom_info); oomData->reason = pOOMInfo->reason; @@ -3043,7 +3047,7 @@ ClrDataAccess::GetOOMData(CLRDATA_ADDRESS oomAddr, struct DacpOomData *data) SOSDacEnter(); memset(data, 0, sizeof(DacpOomData)); - if (!GCHeap::IsServerHeap()) + if (!GCHeapUtilities::IsServerHeap()) hr = E_FAIL; // doesn't make sense to call this on WKS mode #ifdef FEATURE_SVR_GC @@ -3090,7 +3094,7 @@ ClrDataAccess::GetGCInterestingInfoStaticData(struct DacpGCInterestingInfoData * SOSDacEnter(); memset(data, 0, sizeof(DacpGCInterestingInfoData)); - if (!GCHeap::IsServerHeap()) + if (!GCHeapUtilities::IsServerHeap()) { for (int i = 0; i < NUM_GC_DATA_POINTS; i++) data->interestingDataPoints[i] = WKS::interesting_data_per_heap[i]; @@ -3123,7 +3127,7 @@ ClrDataAccess::GetGCInterestingInfoData(CLRDATA_ADDRESS interestingInfoAddr, str SOSDacEnter(); memset(data, 0, sizeof(DacpGCInterestingInfoData)); - if (!GCHeap::IsServerHeap()) + if (!GCHeapUtilities::IsServerHeap()) hr = E_FAIL; // doesn't make sense to call this on WKS mode #ifdef FEATURE_SVR_GC @@ -3149,7 +3153,7 @@ ClrDataAccess::GetHeapAnalyzeData(CLRDATA_ADDRESS addr, struct DacpGcHeapAnalyz SOSDacEnter(); - if (!GCHeap::IsServerHeap()) + if (!GCHeapUtilities::IsServerHeap()) hr = E_FAIL; // doesn't make sense to call this on WKS mode #ifdef FEATURE_SVR_GC @@ -3856,7 +3860,7 @@ ClrDataAccess::EnumWksGlobalMemoryRegions(CLRDataEnumMemoryFlags flags) // enumerating the generations from max (which is normally gen2) to max+1 gives you // the segment list for all the normal segements plus the large heap segment (max+1) // this is the convention in the GC so it is repeated here - for (ULONG i = GCHeap::GetMaxGeneration(); i <= GCHeap::GetMaxGeneration()+1; i++) + for (ULONG i = GCHeapUtilities::GetMaxGeneration(); i <= GCHeapUtilities::GetMaxGeneration()+1; i++) { __DPtr seg = dac_cast(WKS::generation_table[i].start_segment); while (seg) diff --git a/src/debug/daccess/request_svr.cpp b/src/debug/daccess/request_svr.cpp index 429f300..1fe20e2 100644 --- a/src/debug/daccess/request_svr.cpp +++ b/src/debug/daccess/request_svr.cpp @@ -256,7 +256,7 @@ ClrDataAccess::EnumSvrGlobalMemoryRegions(CLRDataEnumMemoryFlags flags) // enumerating the generations from max (which is normally gen2) to max+1 gives you // the segment list for all the normal segements plus the large heap segment (max+1) // this is the convention in the GC so it is repeated here - for (ULONG i = GCHeap::GetMaxGeneration(); i <= GCHeap::GetMaxGeneration()+1; i++) + for (ULONG i = GCHeapUtilities::GetMaxGeneration(); i <= GCHeapUtilities::GetMaxGeneration()+1; i++) { __DPtr seg = dac_cast(pHeap->generation_table[i].start_segment); while (seg) @@ -271,7 +271,7 @@ ClrDataAccess::EnumSvrGlobalMemoryRegions(CLRDataEnumMemoryFlags flags) DWORD DacGetNumHeaps() { - if (GCHeap::IsServerHeap()) + if (GCHeapUtilities::IsServerHeap()) return (DWORD)SVR::gc_heap::n_heaps; // workstation gc diff --git a/src/debug/di/breakpoint.cpp b/src/debug/di/breakpoint.cpp index 1e381a5..e3e4fb0 100644 --- a/src/debug/di/breakpoint.cpp +++ b/src/debug/di/breakpoint.cpp @@ -15,7 +15,7 @@ CordbBreakpoint::CordbBreakpoint(CordbProcess * pProcess, CordbBreakpointType bpType) : CordbBase(pProcess, 0, enumCordbBreakpoint), - m_active(false), m_type(bpType) + m_active(false), m_pAppDomain(NULL), m_type(bpType) { } diff --git a/src/debug/di/module.cpp b/src/debug/di/module.cpp index 6717e85..36cc6f5 100644 --- a/src/debug/di/module.cpp +++ b/src/debug/di/module.cpp @@ -3755,7 +3755,269 @@ HRESULT FindNativeInfoInILVariableArray(DWORD return CORDBG_E_IL_VAR_NOT_AVAILABLE; } // FindNativeInfoInILVariableArray -//* ------------------------------------------------------------------------- * + +// * ------------------------------------------------------------------------- * +// * Variable Enum class +// * ------------------------------------------------------------------------- * +//----------------------------------------------------------------------------- +// CordbVariableHome constructor +// Arguments: +// Input: +// pCode - CordbNativeCode instance containing this variable home +// pNativeVarInfo - native location, lifetime, and index information for +// this variable +// isLocal - indicates whether the instance is a local variable, +// as opposed to an argument +// index - the argument or slot index +// Output: +// fields of the CordbVariableHome instance have been initialized +//----------------------------------------------------------------------------- +CordbVariableHome::CordbVariableHome(CordbNativeCode *pCode, + const ICorDebugInfo::NativeVarInfo nativeVarInfo, + BOOL isLocal, + ULONG index) : + CordbBase(pCode->GetModule()->GetProcess(), 0) +{ + _ASSERTE(pCode != NULL); + + m_pCode.Assign(pCode); + m_nativeVarInfo = nativeVarInfo; + m_isLocal = isLocal; + m_index = index; +} + +CordbVariableHome::~CordbVariableHome() +{ + _ASSERTE(this->IsNeutered()); +} + +void CordbVariableHome::Neuter() +{ + m_pCode.Clear(); + CordbBase::Neuter(); +} + +//----------------------------------------------------------------------------- +// Public method for IUnknown::QueryInterface. +// Has standard QI semantics. +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::QueryInterface(REFIID id, void **pInterface) +{ + if (id == IID_ICorDebugVariableHome) + { + *pInterface = static_cast(this); + } + else if (id == IID_IUnknown) + { + *pInterface = static_cast(static_cast(this)); + } + else + { + *pInterface = NULL; + return E_NOINTERFACE; + } + + ExternalAddRef(); + return S_OK; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetCode +// Public method to get the Code object containing this variable home. +// +// Parameters: +// ppCode - OUT: returns the Code object for this variable home. +// +// Returns: +// S_OK - on success. +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetCode(ICorDebugCode **ppCode) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(ppCode, ICorDebugCode **); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + HRESULT hr = m_pCode->QueryInterface(IID_ICorDebugCode, (LPVOID*)ppCode); + + return hr; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetSlotIndex +// Public method to get the slot index for this variable home. +// +// Parameters: +// pSlotIndex - OUT: returns the managed slot-index of this variable home. +// +// Returns: +// S_OK - on success +// E_FAIL - if the variable is not a local variable, but an argument +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetSlotIndex(ULONG32 *pSlotIndex) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(pSlotIndex, ULONG32 *); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + if (!m_isLocal) + { + return E_FAIL; + } + *pSlotIndex = m_index; + return S_OK; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetArgumentIndex +// Public method to get the slot index for this variable home. +// +// Parameters: +// pSlotIndex - OUT: returns the managed argument-index of this variable home. +// +// Returns: +// S_OK - on success +// E_FAIL - if the variable is not an argument, but a local variable +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetArgumentIndex(ULONG32 *pArgumentIndex) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(pArgumentIndex, ULONG32 *); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + if (m_isLocal) + { + return E_FAIL; + } + *pArgumentIndex = m_index; + return S_OK; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetLiveRange +// Public method to get the native range over which this variable is live. +// +// Parameters: +// pStartOffset - OUT: returns the logical offset at which the variable is +// first live +// pEndOffset - OUT: returns the logical offset immediately after that at +// which the variable is last live +// +// Returns: +// S_OK - on success +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetLiveRange(ULONG32 *pStartOffset, + ULONG32 *pEndOffset) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(pStartOffset, ULONG32 *); + VALIDATE_POINTER_TO_OBJECT(pEndOffset, ULONG32 *); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + *pStartOffset = m_nativeVarInfo.startOffset; + *pEndOffset = m_nativeVarInfo.endOffset; + return S_OK; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetLocationType +// Public method to get the type of native location for this variable home. +// +// Parameters: +// pLocationType - OUT: the type of native location +// +// Returns: +// S_OK - on success +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetLocationType(VariableLocationType *pLocationType) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(pLocationType, VariableLocationType *); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + switch (m_nativeVarInfo.loc.vlType) + { + case ICorDebugInfo::VLT_REG: + *pLocationType = VLT_REGISTER; + break; + case ICorDebugInfo::VLT_STK: + *pLocationType = VLT_REGISTER_RELATIVE; + break; + default: + *pLocationType = VLT_INVALID; + } + return S_OK; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetRegister +// Public method to get the register or base register for this variable hom. +// +// Parameters: +// pRegister - OUT: for VLT_REGISTER location types, gives the register. +// for VLT_REGISTER_RELATIVE location types, gives the base +// register. +// +// Returns: +// S_OK - on success +// E_FAIL - for VLT_INVALID location types +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetRegister(CorDebugRegister *pRegister) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(pRegister, CorDebugRegister *); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + switch (m_nativeVarInfo.loc.vlType) + { + case ICorDebugInfo::VLT_REG: + *pRegister = ConvertRegNumToCorDebugRegister(m_nativeVarInfo.loc.vlReg.vlrReg); + break; + case ICorDebugInfo::VLT_STK: + *pRegister = ConvertRegNumToCorDebugRegister(m_nativeVarInfo.loc.vlStk.vlsBaseReg); + break; + default: + return E_FAIL; + } + return S_OK; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetOffset +// Public method to get the offset from the base register for this variable home. +// +// Parameters: +// pOffset - OUT: gives the offset from the base register +// +// Returns: +// S_OK - on success +// E_FAIL - for location types other than VLT_REGISTER_RELATIVE +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetOffset(LONG *pOffset) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(pOffset, LONG *); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + switch (m_nativeVarInfo.loc.vlType) + { + case ICorDebugInfo::VLT_STK: + *pOffset = m_nativeVarInfo.loc.vlStk.vlsOffset; + break; + default: + return E_FAIL; + } + return S_OK; +} + + +// * ------------------------------------------------------------------------- * // * Native Code class // * ------------------------------------------------------------------------- */ @@ -3780,7 +4042,7 @@ CordbNativeCode::CordbNativeCode(CordbFunction * pFunction, m_fIsInstantiatedGeneric(fIsInstantiatedGeneric != FALSE) { _ASSERTE(GetVersion() >= CorDB_DEFAULT_ENC_FUNCTION_VERSION); - + for (CodeBlobRegion region = kHot; region < MAX_REGIONS; ++region) { m_rgCodeRegions[region] = pJitData->m_rgCodeRegions[region]; @@ -3805,6 +4067,10 @@ HRESULT CordbNativeCode::QueryInterface(REFIID id, void ** pInterface) { *pInterface = static_cast(this); } + else if (id == IID_ICorDebugCode4) + { + *pInterface = static_cast(this); + } else if (id == IID_IUnknown) { *pInterface = static_cast(static_cast(this)); @@ -4111,6 +4377,113 @@ HRESULT CordbNativeCode::GetReturnValueLiveOffset(ULONG32 ILoffset, ULONG32 buff return hr; } +//----------------------------------------------------------------------------- +// CordbNativeCode::EnumerateVariableHomes +// Public method to get an enumeration of native variable homes. This may +// include multiple ICorDebugVariableHomes for the same slot or argument index +// if they have different homes at different points in the function. +// +// Parameters: +// ppEnum - OUT: returns the enum of variable homes. +// +// Returns: +// HRESULT for success or failure. +//----------------------------------------------------------------------------- +HRESULT CordbNativeCode::EnumerateVariableHomes(ICorDebugVariableHomeEnum **ppEnum) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(ppEnum, ICorDebugVariableHomeEnum **); + ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); + + HRESULT hr = S_OK; + + // Get the argument count + ULONG argCount = 0; + CordbFunction *func = GetFunction(); + _ASSERTE(func != NULL); + IfFailRet(func->GetSig(NULL, &argCount, NULL)); + +#ifdef _DEBUG + // Get the number of locals + ULONG localCount = 0; + EX_TRY + { + GetFunction()->GetILCode()->GetLocalVarSig(NULL, &localCount); + } + EX_CATCH_HRESULT(hr); + IfFailRet(hr); +#endif + + RSSmartPtr *rsHomes = NULL; + + EX_TRY + { + CordbProcess *pProcess = GetProcess(); + _ASSERTE(pProcess != NULL); + + const DacDbiArrayList *pOffsetInfoList = m_nativeVarData.GetOffsetInfoList(); + _ASSERTE(pOffsetInfoList != NULL); + DWORD countHomes = 0; + for (int i = 0; i < pOffsetInfoList->Count(); i++) + { + const ICorDebugInfo::NativeVarInfo *pNativeVarInfo = &((*pOffsetInfoList)[i]); + _ASSERTE(pNativeVarInfo != NULL); + + // The variable information list can include variables + // with special varNumbers representing, for instance, the + // parameter types for generic methods. Here we are only + // interested in local variables and arguments. + if (pNativeVarInfo->varNumber < (DWORD)ICorDebugInfo::MAX_ILNUM) + { + countHomes++; + } + } + rsHomes = new RSSmartPtr[countHomes]; + + DWORD varHomeInd = 0; + for (int i = 0; i < pOffsetInfoList->Count(); i++) + { + const ICorDebugInfo::NativeVarInfo *pNativeVarInfo = &((*pOffsetInfoList)[i]); + + // Again, only look for native var info representing local + // variables and arguments. + if (pNativeVarInfo->varNumber < (DWORD)ICorDebugInfo::MAX_ILNUM) + { + // determine whether this variable home represents and argument or local variable + BOOL isLocal = ((ULONG)pNativeVarInfo->varNumber >= argCount); + + // determine the argument-index or slot-index of this variable home + ULONG argOrSlotIndex; + if (isLocal) { + argOrSlotIndex = pNativeVarInfo->varNumber - argCount; + _ASSERTE(argOrSlotIndex < localCount); + } else { + argOrSlotIndex = pNativeVarInfo->varNumber; + } + + RSInitHolder pCVH(new CordbVariableHome(this, + (*pOffsetInfoList)[i], + isLocal, + argOrSlotIndex)); + pProcess->GetContinueNeuterList()->Add(pProcess, pCVH); + _ASSERTE(varHomeInd < countHomes); + rsHomes[varHomeInd].Assign(pCVH); + pCVH.ClearAndMarkDontNeuter(); + varHomeInd++; + } + } + + RSInitHolder pCDVHE( + new CordbVariableHomeEnumerator(GetProcess(), &rsHomes, countHomes)); + pProcess->GetContinueNeuterList()->Add(pProcess, pCDVHE); + pCDVHE.TransferOwnershipExternal(ppEnum); + } + EX_CATCH_HRESULT(hr); + + return hr; +} + int CordbNativeCode::GetCallInstructionLength(BYTE *ip, ULONG32 count) { #if defined(DBG_TARGET_ARM) diff --git a/src/debug/di/process.cpp b/src/debug/di/process.cpp index 44e4a0c..a5496ee 100644 --- a/src/debug/di/process.cpp +++ b/src/debug/di/process.cpp @@ -7334,6 +7334,7 @@ CordbUnmanagedThread *CordbProcess::HandleUnmanagedCreateThread(DWORD dwThreadId if (!SUCCEEDED(hr)) { delete ut; + ut = NULL; LOG((LF_CORDB, LL_INFO10000, "Failed adding unmanaged thread to process!\n")); CORDBSetUnrecoverableError(this, hr, 0); @@ -8119,7 +8120,9 @@ void CordbProcess::DispatchUnmanagedInBandEvent() break; // Get the thread for this event + _ASSERTE(pUnmanagedThread == NULL); pUnmanagedThread = pUnmanagedEvent->m_owner; + _ASSERTE(pUnmanagedThread != NULL); // We better not have dispatched it yet! _ASSERTE(!pUnmanagedEvent->IsDispatched()); @@ -8177,13 +8180,10 @@ void CordbProcess::DispatchUnmanagedInBandEvent() m_pShim->GetWin32EventThread()->DoDbgContinue(this, pUnmanagedEvent); // Release our reference to the unmanaged thread that we dispatched - if (pUnmanagedThread) - { - // This event should have been continued long ago... - _ASSERTE(!pUnmanagedThread->IBEvent()->IsEventWaitingForContinue()); - pUnmanagedThread->InternalRelease(); - pUnmanagedThread = NULL; - } + // This event should have been continued long ago... + _ASSERTE(!pUnmanagedThread->IBEvent()->IsEventWaitingForContinue()); + pUnmanagedThread->InternalRelease(); + pUnmanagedThread = NULL; } m_dispatchingUnmanagedEvent = false; diff --git a/src/debug/di/rsenumerator.hpp b/src/debug/di/rsenumerator.hpp index eb7a225..84e6194 100644 --- a/src/debug/di/rsenumerator.hpp +++ b/src/debug/di/rsenumerator.hpp @@ -99,8 +99,8 @@ CordbEnumerator diff --git a/src/debug/di/rsmain.cpp b/src/debug/di/rsmain.cpp index b568575..0f57787 100644 --- a/src/debug/di/rsmain.cpp +++ b/src/debug/di/rsmain.cpp @@ -40,6 +40,8 @@ RSDebuggingInfo g_RSDebuggingInfo_OutOfProc = {0 }; // set to NULL RSDebuggingInfo * g_pRSDebuggingInfo = &g_RSDebuggingInfo_OutOfProc; +// The following instances are used for invoking overloaded new/delete +forDbiWorker forDbi; #ifdef _DEBUG // For logs, we can print the string name for the debug codes. diff --git a/src/debug/di/rspriv.h b/src/debug/di/rspriv.h index 8537678..18920ad 100644 --- a/src/debug/di/rspriv.h +++ b/src/debug/di/rspriv.h @@ -85,6 +85,7 @@ class CordbJITILFrame; class CordbInternalFrame; class CordbContext; class CordbThread; +class CordbVariableHome; #ifdef FEATURE_INTEROP_DEBUGGING class CordbUnmanagedThread; @@ -176,7 +177,7 @@ private: USHORT m_usPort; }; -#define forDbi (*(forDbiWorker *)NULL) +extern forDbiWorker forDbi; // for dbi we just default to new, but we need to have these defined for both dac and dbi inline void * operator new(size_t lenBytes, const forDbiWorker &) @@ -1586,7 +1587,7 @@ template< typename ElemType, typename ElemPublicType, typename EnumInterfaceType, ElemPublicType (*GetPublicType)(ElemType)> -class CordbEnumerator : public CordbBase, EnumInterfaceType +class CordbEnumerator : public CordbBase, public EnumInterfaceType { private: // the list of items being enumerated over @@ -1680,6 +1681,11 @@ typedef CordbEnumerator CordbGuidToTypeEnumerator; +typedef CordbEnumerator, + ICorDebugVariableHome*, + ICorDebugVariableHomeEnum, + QueryInterfaceConvert, ICorDebugVariableHome> > CordbVariableHomeEnumerator; + // ---------------------------------------------------------------------------- // Hash table for CordbBase objects. // - Uses Internal AddRef/Release (not external) @@ -2920,7 +2926,7 @@ class CordbProcess : public ICorDebugProcess4, public ICorDebugProcess5, public ICorDebugProcess7, - public ICorDebugProcess8, + public ICorDebugProcess8, public IDacDbiInterface::IAllocator, public IDacDbiInterface::IMetaDataLookup, public IProcessShimHooks @@ -4696,7 +4702,7 @@ public: // See definition of ICorDebugType for further invariants on types. // -class CordbType : public CordbBase, public ICorDebugType +class CordbType : public CordbBase, public ICorDebugType, public ICorDebugType2 { public: CordbType(CordbAppDomain *appdomain, CorElementType ty, unsigned int rank); @@ -4736,6 +4742,11 @@ public: COM_METHOD GetRank(ULONG32 *pnRank); //----------------------------------------------------------- + // ICorDebugType2 + //----------------------------------------------------------- + COM_METHOD GetTypeID(COR_TYPEID *pId); + + //----------------------------------------------------------- // Non-COM members //----------------------------------------------------------- @@ -5812,7 +5823,10 @@ private: * code, including an optional set of mappings from IL to offsets in the native Code. * ------------------------------------------------------------------------- */ -class CordbNativeCode : public CordbCode, public ICorDebugCode2, public ICorDebugCode3 +class CordbNativeCode : public CordbCode, + public ICorDebugCode2, + public ICorDebugCode3, + public ICorDebugCode4 { public: CordbNativeCode(CordbFunction * pFunction, @@ -5853,6 +5867,11 @@ public: //----------------------------------------------------------- + // ICorDebugCode4 + //----------------------------------------------------------- + COM_METHOD EnumerateVariableHomes(ICorDebugVariableHomeEnum **ppEnum); + + //----------------------------------------------------------- // Internal members //----------------------------------------------------------- @@ -8539,6 +8558,63 @@ private: typedef enum {kUnboxed, kBoxed} BoxedValue; #define EMPTY_BUFFER TargetBuffer(PTR_TO_CORDB_ADDRESS((void *)NULL), 0) +/* ------------------------------------------------------------------------- * + * Variable Home class + * ------------------------------------------------------------------------- */ +class CordbVariableHome : public CordbBase, public ICorDebugVariableHome +{ +public: + CordbVariableHome(CordbNativeCode *pCode, + const ICorDebugInfo::NativeVarInfo nativeVarInfo, + BOOL isLoc, + ULONG index); + ~CordbVariableHome(); + virtual void Neuter(); + +#ifdef _DEBUG + virtual const char * DbgGetName() { return "CordbVariableHome"; } +#endif + + //----------------------------------------------------------- + // IUnknown + //----------------------------------------------------------- + ULONG STDMETHODCALLTYPE AddRef() + { + return (BaseAddRef()); + } + ULONG STDMETHODCALLTYPE Release() + { + return (BaseRelease()); + } + + COM_METHOD QueryInterface(REFIID riid, void **ppInterface); + + //----------------------------------------------------------- + // ICorDebugVariableHome + //----------------------------------------------------------- + + COM_METHOD GetCode(ICorDebugCode **ppCode); + + COM_METHOD GetSlotIndex(ULONG32 *pSlotIndex); + + COM_METHOD GetArgumentIndex(ULONG32* pArgumentIndex); + + COM_METHOD GetLiveRange(ULONG32* pStartOffset, + ULONG32 *pEndOffset); + + COM_METHOD GetLocationType(VariableLocationType *pLocationType); + + COM_METHOD GetRegister(CorDebugRegister *pRegister); + + COM_METHOD GetOffset(LONG *pOffset); +private: + RSSmartPtr m_pCode; + ICorDebugInfo::NativeVarInfo m_nativeVarInfo; + BOOL m_isLocal; + ULONG m_index; +}; + + // for an inheritance graph of the ICDValue types, // See file:./ICorDebugValueTypes.vsd for a diagram of the types. /* ------------------------------------------------------------------------- * * Value class diff --git a/src/debug/di/rspriv.inl b/src/debug/di/rspriv.inl index 00e4c23..5de99c6 100644 --- a/src/debug/di/rspriv.inl +++ b/src/debug/di/rspriv.inl @@ -162,7 +162,7 @@ void CordbProcess::ForceDacFlush() { if (m_pDacPrimitives != NULL) { - STRESS_LOG1(LF_CORDB, LL_INFO1000, "Flush() - old counter: %d", m_flushCounter); + STRESS_LOG1(LF_CORDB, LL_INFO1000, "Flush() - old counter: %d\n", m_flushCounter); m_flushCounter++; HRESULT hr = S_OK; EX_TRY diff --git a/src/debug/di/rsthread.cpp b/src/debug/di/rsthread.cpp index ae9b43c..a4660be 100644 --- a/src/debug/di/rsthread.cpp +++ b/src/debug/di/rsthread.cpp @@ -1493,7 +1493,7 @@ void CordbThread::Get32bitFPRegisters(CONTEXT * pContext) for (i = 0; i <= floatStackTop; i++) { - long double td; + double td = 0.0; __asm fstp td // copy out the double m_floatValues[i] = td; } @@ -4585,7 +4585,7 @@ void CordbUnmanagedThread::SaveRaiseExceptionEntryContext() LOG((LF_CORDB, LL_INFO1000, "CP::SREEC: failed to read exception information pointer.\n")); return; } -#elif +#else _ASSERTE(!"Implement this for your platform"); return; #endif @@ -8935,8 +8935,13 @@ HRESULT CordbJITILFrame::GetReturnValueForILOffsetImpl(ULONG32 ILoffset, ICorDeb bool found = false; ULONG32 currentOffset = m_nativeFrame->GetIPOffset(); for (ULONG32 i = 0; i < count; ++i) - if ((found = currentOffset == offsets[i])) + { + if (currentOffset == offsets[i]) + { + found = true; break; + } + } if (!found) return E_UNEXPECTED; diff --git a/src/debug/di/rstype.cpp b/src/debug/di/rstype.cpp index b183fdf..e537613 100644 --- a/src/debug/di/rstype.cpp +++ b/src/debug/di/rstype.cpp @@ -276,6 +276,8 @@ HRESULT CordbType::QueryInterface(REFIID id, void **pInterface) { if (id == IID_ICorDebugType) *pInterface = static_cast(this); + else if (id == IID_ICorDebugType2) + *pInterface = static_cast(this); else if (id == IID_IUnknown) *pInterface = static_cast(static_cast(this)); else @@ -2280,6 +2282,126 @@ HRESULT CordbType::GetBase(ICorDebugType ** ppType) return hr; } +//----------------------------------------------------------------------------- +// CordbType::GetTypeID +// Method to get the COR_TYPEID corresponding to this CordbType. +// +// Parameters: +// pId - OUT: gives the COR_TYPEID for this CordbType +// +// Returns: +// S_OK if succeeded. +// CORDBG_E_CLASS_NOT_LOADED if the type which this CordbType represents has +// not been loaded in the runtime. +// E_POINTER if pId is NULL +// CORDBG_E_UNSUPPORTED for unsupported types. +// +HRESULT CordbType::GetTypeID(COR_TYPEID *pId) +{ + LOG((LF_CORDB, LL_INFO1000, "GetTypeID\n")); + if (pId == NULL) + return E_POINTER; + + HRESULT hr = S_OK; + + PUBLIC_API_ENTRY(this); + RSLockHolder stopGoLock(GetProcess()->GetStopGoLock()); + RSLockHolder procLock(GetProcess()->GetProcessLock()); + + EX_TRY + { + hr = Init(FALSE); + IfFailThrow(hr); + + VMPTR_TypeHandle vmTypeHandle; + + CorElementType et = GetElementType(); + switch (et) + { + case ELEMENT_TYPE_OBJECT: + case ELEMENT_TYPE_VOID: + case ELEMENT_TYPE_BOOLEAN: + case ELEMENT_TYPE_CHAR: + case ELEMENT_TYPE_I1: + case ELEMENT_TYPE_U1: + case ELEMENT_TYPE_I2: + case ELEMENT_TYPE_U2: + case ELEMENT_TYPE_I4: + case ELEMENT_TYPE_U4: + case ELEMENT_TYPE_I8: + case ELEMENT_TYPE_U8: + case ELEMENT_TYPE_R4: + case ELEMENT_TYPE_R8: + case ELEMENT_TYPE_STRING: + case ELEMENT_TYPE_TYPEDBYREF: + case ELEMENT_TYPE_I: + case ELEMENT_TYPE_U: + { + mdTypeDef mdToken; + VMPTR_Module vmModule = VMPTR_Module::NullPtr(); + VMPTR_DomainFile vmDomainFile = VMPTR_DomainFile::NullPtr(); + + // get module and token of the simple type + GetProcess()->GetDAC()->GetSimpleType(GetAppDomain()->GetADToken(), + et, + &mdToken, + &vmModule, + &vmDomainFile); + + vmTypeHandle = GetProcess()->GetDAC()->GetTypeHandle(vmModule, mdToken); + } + break; + case ELEMENT_TYPE_ARRAY: + case ELEMENT_TYPE_SZARRAY: + { + LOG((LF_CORDB, LL_INFO1000, "GetTypeID: parameterized type\n")); + if (m_typeHandleExact.IsNull()) + { + hr = InitInstantiationTypeHandle(FALSE); + IfFailThrow(hr); + } + vmTypeHandle = m_typeHandleExact; + } + break; + case ELEMENT_TYPE_CLASS: + { + ICorDebugClass *pICDClass = NULL; + hr = GetClass(&pICDClass); + IfFailThrow(hr); + CordbClass *pClass = (CordbClass*)pICDClass; + _ASSERTE(pClass != NULL); + + if (pClass->HasTypeParams()) + { + vmTypeHandle = m_typeHandleExact; + } + else + { + mdTypeDef mdToken; + hr = pClass->GetToken(&mdToken); + IfFailThrow(hr); + + VMPTR_Module vmModule = GetModule(); + vmTypeHandle = GetProcess()->GetDAC()->GetTypeHandle(vmModule, mdToken); + } + } + break; + case ELEMENT_TYPE_PTR: + case ELEMENT_TYPE_BYREF: + case ELEMENT_TYPE_FNPTR: + IfFailThrow(CORDBG_E_UNSUPPORTED); + default: + _ASSERTE(!"unexpected element type!"); + IfFailThrow(CORDBG_E_UNSUPPORTED); + break; + } + + GetProcess()->GetDAC()->GetTypeIDForType(vmTypeHandle, pId); + } + EX_CATCH_HRESULT(hr); + + return hr; +} //----------------------------------------------------------------------------- // Get rich field information given a token. diff --git a/src/debug/ee/controller.cpp b/src/debug/ee/controller.cpp index 7f4d445..3a87fdf 100644 --- a/src/debug/ee/controller.cpp +++ b/src/debug/ee/controller.cpp @@ -2824,6 +2824,8 @@ DPOSS_ACTION DebuggerController::DispatchPatchOrSingleStep(Thread *thread, CONTE CrstHolderWithState lockController(&g_criticalSection); + TADDR originalAddress = 0; + #ifdef EnC_SUPPORTED DebuggerControllerPatch *dcpEnCOriginal = NULL; @@ -2878,7 +2880,7 @@ DPOSS_ACTION DebuggerController::DispatchPatchOrSingleStep(Thread *thread, CONTE // If we setip, then that will change the address in the context. // Remeber the old address so that we can compare it to the context's ip and see if it changed. // If it did change, then don't dispatch our current event. - TADDR originalAddress = (TADDR) address; + originalAddress = (TADDR) address; #ifdef _DEBUG // If we do a SetIP after this point, the value of address will be garbage. Set it to a distictive pattern now, so @@ -4486,7 +4488,7 @@ void DebuggerPatchSkip::DebuggerDetachClean() // THIS FIX IS INCOMPLETE!It attempts to update the IP in the cases we can easily detect.However, // if a thread is in pre - emptive mode, and its filter context has been propagated to a VEH // context, then the filter context we get will be NULL and this fix will not work.Our belief is - // that this scenario is rare enough that it doesnÂ’t justify the cost and risk associated with a + // that this scenario is rare enough that it doesnt justify the cost and risk associated with a // complete fix, in which we would have to either : // 1. Change the reference counting for DebuggerController and then change the exception handling // logic in the debuggee so that we can handle the debugger event after detach. diff --git a/src/debug/ee/controller.h b/src/debug/ee/controller.h index 6611e04..a314874 100644 --- a/src/debug/ee/controller.h +++ b/src/debug/ee/controller.h @@ -227,23 +227,23 @@ public: LONG AddRef() { - InterlockedIncrement(&m_refCount); - _ASSERTE(m_refCount > 0); - return m_refCount; + LONG newRefCount = InterlockedIncrement(&m_refCount); + _ASSERTE(newRefCount > 0); + return newRefCount; } LONG Release() { - LONG result = InterlockedDecrement(&m_refCount); - _ASSERTE(m_refCount >= 0); + LONG newRefCount = InterlockedDecrement(&m_refCount); + _ASSERTE(newRefCount >= 0); - if (m_refCount == 0) + if (newRefCount == 0) { TRACE_FREE(this); DeleteInteropSafeExecutable(this); } - return result; + return newRefCount; } // "PatchBypass" must be the first field of this class for alignment to be correct. diff --git a/src/debug/ee/debugger.cpp b/src/debug/ee/debugger.cpp index a06811c..2aed8bd 100644 --- a/src/debug/ee/debugger.cpp +++ b/src/debug/ee/debugger.cpp @@ -75,6 +75,9 @@ SVAL_IMPL_INIT(BOOL, Debugger, s_fCanChangeNgenFlags, TRUE); bool g_EnableSIS = false; +// The following instances are used for invoking overloaded new/delete +InteropSafe interopsafe; +InteropSafeExecutable interopsafeEXEC; #ifndef DACCESS_COMPILE @@ -594,8 +597,8 @@ void DoAssertOnType(DebuggerIPCEventType event, int count) if (g_iDbgRuntimeCounter[event & 0x00ff] == count) { char tmpStr[256]; - sprintf(tmpStr, "%s == %d, break now!", - IPCENames::GetName(event), count); + _snprintf_s(tmpStr, _countof(tmpStr), _TRUNCATE, "%s == %d, break now!", + IPCENames::GetName(event), count); // fire the assertion DbgAssertDialog(__FILE__, __LINE__, tmpStr); @@ -608,8 +611,8 @@ void DoAssertOnType(DebuggerIPCEventType event, int count) if (g_iDbgDebuggerCounter[event & 0x00ff] == count) { char tmpStr[256]; - sprintf(tmpStr, "%s == %d, break now!", - IPCENames::GetName(event), count); + _snprintf_s(tmpStr, _countof(tmpStr), _TRUNCATE, "%s == %d, break now!", + IPCENames::GetName(event), count); // fire the assertion DbgAssertDialog(__FILE__, __LINE__, tmpStr); @@ -11907,7 +11910,7 @@ HRESULT Debugger::GetAndSendInterceptCommand(DebuggerIPCEvent *event) // // Save off this breakpoint, so that if the exception gets unwound before we hit - // the breakpoint - the exeception info can call back to remove it. + // the breakpoint - the exception info can call back to remove it. // pExState->GetDebuggerState()->SetDebuggerInterceptContext((void *)pBreakpoint); diff --git a/src/debug/ee/debugger.h b/src/debug/ee/debugger.h index 6368647..9cdf546 100644 --- a/src/debug/ee/debugger.h +++ b/src/debug/ee/debugger.h @@ -3512,10 +3512,10 @@ public: * ------------------------------------------------------------------------ */ class InteropSafe {}; -#define interopsafe (*(InteropSafe*)NULL) +extern InteropSafe interopsafe; class InteropSafeExecutable {}; -#define interopsafeEXEC (*(InteropSafeExecutable*)NULL) +extern InteropSafeExecutable interopsafeEXEC; #ifndef DACCESS_COMPILE inline void * __cdecl operator new(size_t n, const InteropSafe&) diff --git a/src/debug/ee/functioninfo.cpp b/src/debug/ee/functioninfo.cpp index 83c185c..aa75b30 100644 --- a/src/debug/ee/functioninfo.cpp +++ b/src/debug/ee/functioninfo.cpp @@ -890,7 +890,6 @@ DebuggerJitInfo::~DebuggerJitInfo() LOG((LF_CORDB,LL_EVERYTHING, "DJI::~DJI : deleted at 0x%p\n", this)); } - // Lazy initialize the Debugger-Jit-Info void DebuggerJitInfo::LazyInitBounds() { @@ -903,24 +902,22 @@ void DebuggerJitInfo::LazyInitBounds() PRECONDITION(!g_pDebugger->HasDebuggerDataLock()); } CONTRACTL_END; - //@todo: this method is not synchronized. Mei-chin's recent work should cover this one + LOG((LF_CORDB, LL_EVERYTHING, "DJI::LazyInitBounds: this=0x%x m_fAttemptInit %s\n", this, m_fAttemptInit == true ? "true": "false")); + // Only attempt lazy-init once - // new LOG message - LOG((LF_CORDB,LL_EVERYTHING, "DJI::LazyInitBounds: this=0x%x m_fAttemptInit %s\n", this, m_fAttemptInit == true? "true": "false")); if (m_fAttemptInit) { return; } - m_fAttemptInit = true; EX_TRY { - LOG((LF_CORDB,LL_EVERYTHING, "DJI::LazyInitBounds: this=0x%x Initing\n", this)); + LOG((LF_CORDB, LL_EVERYTHING, "DJI::LazyInitBounds: this=0x%x Initing\n", this)); + // Should have already been jitted _ASSERTE(this->m_jitComplete); MethodDesc * mdesc = this->m_fd; - DebugInfoRequest request; _ASSERTE(this->m_addrOfCode != NULL); // must have address to disambguate the Enc cases. @@ -928,7 +925,6 @@ void DebuggerJitInfo::LazyInitBounds() // Note the MethodDesc may not yet have the jitted info, so we'll also use the starting address we got in the jit complete callback. request.InitFromStartingAddr(mdesc, (PCODE)this->m_addrOfCode); - // Bounds info. ULONG32 cMap = 0; ICorDebugInfo::OffsetMapping *pMap = NULL; @@ -940,12 +936,26 @@ void DebuggerJitInfo::LazyInitBounds() InteropSafeNew, NULL, // allocator &cMap, &pMap, &cVars, &pVars); + LOG((LF_CORDB,LL_EVERYTHING, "DJI::LazyInitBounds: this=0x%x GetBoundariesAndVars success=0x%x\n", this, fSuccess)); - if (fSuccess) + + Debugger::DebuggerDataLockHolder debuggerDataLockHolder(g_pDebugger); + + if (!m_fAttemptInit) { - this->SetBoundaries(cMap, pMap); - this->SetVars(cVars, pVars); + if (fSuccess) + { + this->SetBoundaries(cMap, pMap); + this->SetVars(cVars, pVars); + } + m_fAttemptInit = true; } + else + { + DeleteInteropSafe(pMap); + DeleteInteropSafe(pVars); + } + // DebuggerDataLockHolder out of scope - release implied } EX_CATCH { @@ -963,10 +973,7 @@ void DebuggerJitInfo::SetVars(ULONG32 cVars, ICorDebugInfo::NativeVarInfo *pVars { LIMITED_METHOD_CONTRACT; - if (m_varNativeInfo) - { - return; - } + _ASSERTE(m_varNativeInfo == NULL); m_varNativeInfo = pVars; m_varNativeInfoCount = cVars; @@ -1020,15 +1027,11 @@ void DebuggerJitInfo::SetBoundaries(ULONG32 cMap, ICorDebugInfo::OffsetMapping * LOG((LF_CORDB,LL_EVERYTHING, "DJI::SetBoundaries: this=0x%x cMap=0x%x pMap=0x%x\n", this, cMap, pMap)); _ASSERTE((cMap == 0) == (pMap == NULL)); + _ASSERTE(m_sequenceMap == NULL); if (cMap == 0) return; - if (m_sequenceMap) - { - return; - } - ULONG ilLast = 0; #ifdef _DEBUG // We assume that the map is sorted by native offset diff --git a/src/debug/ee/i386/dbghelpers.S b/src/debug/ee/i386/dbghelpers.S new file mode 100644 index 0000000..d0a1101 --- /dev/null +++ b/src/debug/ee/i386/dbghelpers.S @@ -0,0 +1,70 @@ +// 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. + +.intel_syntax noprefix +#include "unixasmmacros.inc" + +//extern FuncEvalHijackWorker:proc + +// @dbgtodo- once we port Funceval, use the ExceptionHijack stub instead of this func-eval stub. +NESTED_ENTRY FuncEvalHijack, _TEXT, UnhandledExceptionHandlerUnix + push eax // the ptr to the DebuggerEval + call C_FUNC(FuncEvalHijackWorker) + jmp eax // return is the patch addresss to jmp to + +NESTED_END FuncEvalHijack, _TEXT + +// +// Flares for interop debugging. +// Flares are exceptions (breakpoints) at well known addresses which the RS +// listens for when interop debugging. +// + +// This exception is from managed code. +LEAF_ENTRY SignalHijackStartedFlare, _TEXT + int 3 + // make sure that the basic block is unique + test eax,1 + ret +LEAF_END SignalHijackStartedFlare, _TEXT + +// Start the handoff +LEAF_ENTRY ExceptionForRuntimeHandoffStartFlare, _TEXT + int 3 + // make sure that the basic block is unique + test eax,2 + ret +LEAF_END ExceptionForRuntimeHandoffStartFlare, _TEXT + +// Finish the handoff. +LEAF_ENTRY ExceptionForRuntimeHandoffCompleteFlare, _TEXT + int 3 + // make sure that the basic block is unique + test eax,3 + ret +LEAF_END ExceptionForRuntimeHandoffCompleteFlare, _TEXT + +// Signal execution return to unhijacked state +LEAF_ENTRY SignalHijackCompleteFlare, _TEXT + int 3 + // make sure that the basic block is unique + test eax,4 + ret +LEAF_END SignalHijackCompleteFlare, _TEXT + +// This exception is from unmanaged code. +LEAF_ENTRY ExceptionNotForRuntimeFlare, _TEXT + int 3 + // make sure that the basic block is unique + test eax,5 + ret +LEAF_END ExceptionNotForRuntimeFlare, _TEXT + +// The Runtime is synchronized. +LEAF_ENTRY NotifyRightSideOfSyncCompleteFlare, _TEXT + int 3 + // make sure that the basic block is unique + test eax,6 + ret +LEAF_END NotifyRightSideOfSyncCompleteFlare, _TEXT diff --git a/src/debug/ee/wks/CMakeLists.txt b/src/debug/ee/wks/CMakeLists.txt index a096cbf..2b1aff5 100644 --- a/src/debug/ee/wks/CMakeLists.txt +++ b/src/debug/ee/wks/CMakeLists.txt @@ -55,9 +55,7 @@ else () add_compile_options(-fPIC) -if(CLR_CMAKE_PLATFORM_ARCH_AMD64) - add_library_clr(cordbee_wks ${CORDBEE_SOURCES_WKS} ../${ARCH_SOURCES_DIR}/dbghelpers.S) -elseif(CLR_CMAKE_PLATFORM_ARCH_ARM) +if(CLR_CMAKE_PLATFORM_ARCH_AMD64 OR CLR_CMAKE_PLATFORM_ARCH_ARM OR CLR_CMAKE_PLATFORM_ARCH_I386) add_library_clr(cordbee_wks ${CORDBEE_SOURCES_WKS} ../${ARCH_SOURCES_DIR}/dbghelpers.S) elseif(CLR_CMAKE_PLATFORM_ARCH_ARM64) add_library_clr(cordbee_wks ${CORDBEE_SOURCES_WKS}) diff --git a/src/debug/ildbsymlib/symwrite.h b/src/debug/ildbsymlib/symwrite.h index 055b8ec..54ab11a 100644 --- a/src/debug/ildbsymlib/symwrite.h +++ b/src/debug/ildbsymlib/symwrite.h @@ -839,7 +839,8 @@ public: { // Help mitigate the impact of buffer overflow // Fail fast with a null-reference AV - return *(static_cast(0)) ; + volatile char* nullPointer = nullptr; + *nullPointer; } return m_array[ i ]; } diff --git a/src/debug/inc/common.h b/src/debug/inc/common.h index 77fe27a..3bbf0a6 100644 --- a/src/debug/inc/common.h +++ b/src/debug/inc/common.h @@ -295,29 +295,7 @@ inline CORDB_ADDRESS ALIGN_ADDRESS( CORDB_ADDRESS val, CORDB_ADDRESS alignment ) return result; } -// -// Whenever a structure is marshalled between different platforms, we need to ensure the -// layout is the same in both cases. We tell GCC to use the MSVC-style packing with -// the following attribute. The main thing this appears to control is whether -// 8-byte values are aligned at 4-bytes (GCC default) or 8-bytes (MSVC default). -// This attribute affects only the immediate struct it is applied to, you must also apply -// it to any nested structs if you want their layout affected as well. You also must -// apply this to unions embedded in other structures, since it can influence the starting -// alignment. -// -// Note that there doesn't appear to be any disadvantage to applying this a little -// more agressively than necessary, so we generally use it on all classes / structures -// defined in a file that defines marshalled data types (eg. DacDbiStructures.h) -// The -mms-bitfields compiler option also does this for the whole file, but we don't -// want to go changing the layout of, for example, structures defined in OS header files -// so we explicitly opt-in with this attribute. -// -#ifdef __GNUC__ -#define MSLAYOUT __attribute__((__ms_struct__)) -#else -#define MSLAYOUT -#endif - +#include "dacprivate.h" // for MSLAYOUT #include "dumpcommon.h" #endif //DEBUGGER_COMMON_H diff --git a/src/debug/inc/dacdbiinterface.h b/src/debug/inc/dacdbiinterface.h index fe58724..569ccba 100644 --- a/src/debug/inc/dacdbiinterface.h +++ b/src/debug/inc/dacdbiinterface.h @@ -32,7 +32,7 @@ template void DeleteDbiMemory(T *p); // Need a class to serve as a tag that we can use to overload New/Delete. class forDbiWorker {}; -#define forDbi (*(forDbiWorker *)NULL) +extern forDbiWorker forDbi; extern void * operator new(size_t lenBytes, const forDbiWorker &); extern void * operator new[](size_t lenBytes, const forDbiWorker &); extern void operator delete(void *p, const forDbiWorker &); @@ -2508,17 +2508,20 @@ public: virtual HRESULT GetTypeID(CORDB_ADDRESS obj, COR_TYPEID * pType) = 0; - virtual - HRESULT GetObjectFields(COR_TYPEID id, ULONG32 celt, OUT COR_FIELD * layout, OUT ULONG32 * pceltFetched) = 0; - - virtual - HRESULT GetTypeLayout(COR_TYPEID id, COR_TYPE_LAYOUT * pLayout) = 0; - - virtual - HRESULT GetArrayLayout(COR_TYPEID id, COR_ARRAY_LAYOUT * pLayout) = 0; - - virtual - void GetGCHeapInformation(OUT COR_HEAPINFO * pHeapInfo) = 0; + virtual + HRESULT GetTypeIDForType(VMPTR_TypeHandle vmTypeHandle, COR_TYPEID *pId) = 0; + + virtual + HRESULT GetObjectFields(COR_TYPEID id, ULONG32 celt, OUT COR_FIELD * layout, OUT ULONG32 * pceltFetched) = 0; + + virtual + HRESULT GetTypeLayout(COR_TYPEID id, COR_TYPE_LAYOUT * pLayout) = 0; + + virtual + HRESULT GetArrayLayout(COR_TYPEID id, COR_ARRAY_LAYOUT * pLayout) = 0; + + virtual + void GetGCHeapInformation(OUT COR_HEAPINFO * pHeapInfo) = 0; // If a PEFile has an RW capable IMDInternalImport, this returns the address of the MDInternalRW // object which implements it. diff --git a/src/debug/shared/dbgtransportsession.cpp b/src/debug/shared/dbgtransportsession.cpp index 14b509a..95fdf25 100644 --- a/src/debug/shared/dbgtransportsession.cpp +++ b/src/debug/shared/dbgtransportsession.cpp @@ -1140,33 +1140,6 @@ DbgTransportSession::Message * DbgTransportSession::RemoveMessageFromSendQueue(D #ifndef RIGHT_SIDE_COMPILE -#ifdef FEATURE_PAL -__attribute__((noinline)) -__attribute__((optnone)) -static void -ProbeMemory(__in_ecount(cbBuffer) volatile PBYTE pbBuffer, DWORD cbBuffer, bool fWriteAccess) -{ - // Need an throw in this function to fool the C++ runtime into handling the - // possible h/w exception below. - if (pbBuffer == NULL) - { - throw PAL_SEHException(); - } - - // Simple one byte at a time probing - while (cbBuffer > 0) - { - volatile BYTE read = *pbBuffer; - if (fWriteAccess) - { - *pbBuffer = read; - } - ++pbBuffer; - --cbBuffer; - } -} -#endif // FEATURE_PAL - // Check read and optionally write memory access to the specified range of bytes. Used to check // ReadProcessMemory and WriteProcessMemory requests. HRESULT DbgTransportSession::CheckBufferAccess(__in_ecount(cbBuffer) PBYTE pbBuffer, DWORD cbBuffer, bool fWriteAccess) @@ -1220,14 +1193,7 @@ HRESULT DbgTransportSession::CheckBufferAccess(__in_ecount(cbBuffer) PBYTE pbBuf } while (cbBuffer > 0); #else - try - { - // Need to explicit h/w exception holder so to catch them in ProbeMemory - CatchHardwareExceptionHolder __catchHardwareException; - - ProbeMemory(pbBuffer, cbBuffer, fWriteAccess); - } - catch(...) + if (!PAL_ProbeMemory(pbBuffer, cbBuffer, fWriteAccess)) { return HRESULT_FROM_WIN32(ERROR_INVALID_ADDRESS); } diff --git a/src/dlls/dbgshim/dbgshim.cpp b/src/dlls/dbgshim/dbgshim.cpp index 4d6dc5a..aeee778 100644 --- a/src/dlls/dbgshim/dbgshim.cpp +++ b/src/dlls/dbgshim/dbgshim.cpp @@ -433,7 +433,7 @@ public: DWORD arrayLength = 0; // Wake up runtime(s) - HRESULT hr = InternalEnumerateCLRs(&handleArray, &stringArray, &arrayLength); + HRESULT hr = EnumerateCLRs(m_processId, &handleArray, &stringArray, &arrayLength); if (SUCCEEDED(hr)) { WakeRuntimes(handleArray, arrayLength); diff --git a/src/dlls/mscordac/CMakeLists.txt b/src/dlls/mscordac/CMakeLists.txt index 02bba4a..8780db9 100644 --- a/src/dlls/mscordac/CMakeLists.txt +++ b/src/dlls/mscordac/CMakeLists.txt @@ -45,6 +45,10 @@ if(CLR_CMAKE_PLATFORM_LINUX OR CLR_CMAKE_PLATFORM_FREEBSD OR CLR_CMAKE_PLATFORM_ set(START_LIBRARY_GROUP -Wl,--start-group) set(END_LIBRARY_GROUP -Wl,--end-group) + # These options are used to force every object to be included even if it's unused. + set(START_WHOLE_ARCHIVE -Wl,--whole-archive) + set(END_WHOLE_ARCHIVE -Wl,--no-whole-archive) + # Add linker exports file option set(EXPORTS_LINKER_OPTION -Wl,--version-script=${EXPORTS_FILE}) endif(CLR_CMAKE_PLATFORM_LINUX OR CLR_CMAKE_PLATFORM_FREEBSD OR CLR_CMAKE_PLATFORM_NETBSD) @@ -112,7 +116,9 @@ if(WIN32) else(WIN32) list(APPEND COREDAC_LIBRARIES mscorrc_debug + ${START_WHOLE_ARCHIVE} # force all PAL objects to be included so all exports are available coreclrpal + ${END_WHOLE_ARCHIVE} palrt ) endif(WIN32) @@ -120,4 +126,4 @@ endif(WIN32) target_link_libraries(mscordaccore PRIVATE ${COREDAC_LIBRARIES}) # add the install targets -install_clr(mscordaccore) \ No newline at end of file +install_clr(mscordaccore) diff --git a/src/dlls/mscordac/mscordac_unixexports.src b/src/dlls/mscordac/mscordac_unixexports.src index 466a1bf..7d60c1e 100644 --- a/src/dlls/mscordac/mscordac_unixexports.src +++ b/src/dlls/mscordac/mscordac_unixexports.src @@ -26,6 +26,7 @@ PAL_GetSymbolModuleBase PAL_GetTransportPipeName PAL_InitializeDLL PAL_IsDebuggerPresent +PAL_ProbeMemory PAL_iswspace PAL_memcpy PAL_malloc @@ -49,12 +50,15 @@ PAL_wcsstr _wcsicmp _stricmp -_snprintf -_snwprintf -_vsnwprintf -_itow -_i64tow +sprintf_s +swprintf_s +_snwprintf_s +_vsnprintf_s +_vsnwprintf_s +_itow_s +_i64tow_s memcpy_s +sscanf_s CoCreateGuid CopyFileW @@ -171,4 +175,4 @@ _ZN25NativeExceptionHolderBase4PushEv _ZN25NativeExceptionHolderBaseC2Ev _ZN25NativeExceptionHolderBaseD2Ev _ZN28CatchHardwareExceptionHolderC1Ev -_ZN28CatchHardwareExceptionHolderD1Ev \ No newline at end of file +_ZN28CatchHardwareExceptionHolderD1Ev diff --git a/src/dlls/mscoree/coreclr/coreclr.nativeproj b/src/dlls/mscoree/coreclr/coreclr.nativeproj index d9350bc..484790e 100644 --- a/src/dlls/mscoree/coreclr/coreclr.nativeproj +++ b/src/dlls/mscoree/coreclr/coreclr.nativeproj @@ -1,5 +1,11 @@ + + + + + true + diff --git a/src/dlls/mscoree/mscoree.cpp b/src/dlls/mscoree/mscoree.cpp index 3d33337..4c613ff 100644 --- a/src/dlls/mscoree/mscoree.cpp +++ b/src/dlls/mscoree/mscoree.cpp @@ -75,8 +75,6 @@ HINSTANCE g_hThisInst; // This library. #include // for __security_init_cookie() -void* __stdcall GetCLRFunction(LPCSTR FunctionName); - extern "C" IExecutionEngine* __stdcall IEE(); #ifdef NO_CRT_INIT diff --git a/src/dlls/mscoree/mscorwks_unixexports.src b/src/dlls/mscoree/mscorwks_unixexports.src index 9c151a9..f7862d3 100644 --- a/src/dlls/mscoree/mscorwks_unixexports.src +++ b/src/dlls/mscoree/mscorwks_unixexports.src @@ -98,6 +98,7 @@ UnlockFile UnmapViewOfFile VirtualAlloc VirtualFree +GlobalMemoryStatusEx VirtualQuery WideCharToMultiByte WriteFile diff --git a/src/dlls/mscoree/unixinterface.cpp b/src/dlls/mscoree/unixinterface.cpp index 8d75ff2..edd361c 100644 --- a/src/dlls/mscoree/unixinterface.cpp +++ b/src/dlls/mscoree/unixinterface.cpp @@ -247,21 +247,23 @@ int coreclr_initialize( host.SuppressRelease(); *hostHandle = host; #ifdef FEATURE_GDBJIT - - hr = coreclr_create_delegate(*hostHandle, - *domainId, - "SOS.NETCore", - "SOS.SymbolReader", - "GetInfoForMethod", - (void**)&getInfoForMethodDelegate); - - if (!SUCCEEDED(hr)) + HRESULT createDelegateResult; + createDelegateResult = coreclr_create_delegate(*hostHandle, + *domainId, + "SOS.NETCore", + "SOS.SymbolReader", + "GetInfoForMethod", + (void**)&getInfoForMethodDelegate); + +#if defined(_DEBUG) + if (!SUCCEEDED(createDelegateResult)) { fprintf(stderr, - "Can't create delegate for 'System.Diagnostics.Debug.SymbolReader.SymbolReader.GetInfoForMethod' " - "method - status: 0x%08x\n", hr); + "Can't create delegate for 'SOS.SymbolReader.GetInfoForMethod' " + "method - status: 0x%08x\n", createDelegateResult); } - hr = S_OK; // We don't need to fail if we can't create delegate +#endif // _DEBUG + #endif } return hr; diff --git a/src/dlls/mscorpe/ceefilegenwriter.cpp b/src/dlls/mscorpe/ceefilegenwriter.cpp index cfd1ebb..04bacd7 100644 --- a/src/dlls/mscorpe/ceefilegenwriter.cpp +++ b/src/dlls/mscorpe/ceefilegenwriter.cpp @@ -973,7 +973,7 @@ BOOL RunProcess(LPCWSTR tempResObj, LPCWSTR pszFilename, DWORD* pdwExitCode, PEW if (FAILED(GetClrSystemDirectory(wszSystemDir))) return FALSE; - WCHAR* wzMachine; + const WCHAR* wzMachine; if(pewriter.isIA64()) wzMachine = L"IA64"; else if(pewriter.isAMD64()) @@ -1167,6 +1167,13 @@ HRESULT CeeFileGenWriter::emitResourceSection() const BYTE *pbStartOfMappedMem; IMAGE_SECTION_HEADER *rsrc[2] = { NULL, NULL }; S_SIZE_T cbTotalSizeOfRawData; + + char *data = NULL; + SIZE_T cReloc = 0; + IMAGE_RELOCATION *pReloc = NULL; + SIZE_T cSymbol = 0; + IMAGE_SYMBOL *pSymbolTable = NULL; + // create a mapped view of the .res file pParam->hFile = WszCreateFile(pParam->szResFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (pParam->hFile == INVALID_HANDLE_VALUE) @@ -1308,7 +1315,7 @@ HRESULT CeeFileGenWriter::emitResourceSection() if (FAILED(pParam->hr)) goto lDone; rsrcSection->directoryEntry(IMAGE_DIRECTORY_ENTRY_RESOURCE); - char *data = rsrcSection->getBlock(static_cast(cbTotalSizeOfRawData.Value()), 8); + data = rsrcSection->getBlock(static_cast(cbTotalSizeOfRawData.Value()), 8); if(data == NULL) { pParam->hr = E_OUTOFMEMORY; @@ -1319,11 +1326,11 @@ HRESULT CeeFileGenWriter::emitResourceSection() memcpy(data, (char *)pParam->hMod + VAL32(rsrc[0]->PointerToRawData), VAL32(rsrc[0]->SizeOfRawData)); // Map all the relocs in .rsrc$01 using the reloc and symbol tables in the COFF object., - SIZE_T cReloc = 0; // Total number of relocs - IMAGE_RELOCATION *pReloc = NULL; // Reloc table start + cReloc = 0; // Total number of relocs + pReloc = NULL; // Reloc table start - SIZE_T cSymbol = 0; // Total number of symbols - IMAGE_SYMBOL *pSymbolTable = NULL; // Symbol table start + cSymbol = 0; // Total number of symbols + pSymbolTable = NULL; // Symbol table start { // Check that the relocations and symbols lie within the resource diff --git a/src/gc/CMakeLists.txt b/src/gc/CMakeLists.txt index 61e1ced..d32d1c2 100644 --- a/src/gc/CMakeLists.txt +++ b/src/gc/CMakeLists.txt @@ -38,6 +38,18 @@ set( GC_SOURCES_WKS set( GC_SOURCES_DAC ${GC_SOURCES_DAC_AND_WKS_COMMON}) +if(FEATURE_STANDALONE_GC) + if(CLR_CMAKE_PLATFORM_UNIX) + set ( GC_SOURCES_WKS + ${GC_SOURCES_WKS} + gcenv.unix.cpp) + else() + set ( GC_SOURCES_WKS + ${GC_SOURCES_WKS} + gcenv.windows.cpp) + endif(CLR_CMAKE_PLATFORM_UNIX) +endif(FEATURE_STANDALONE_GC) + convert_to_absolute_path(GC_SOURCES_WKS ${GC_SOURCES_WKS}) convert_to_absolute_path(GC_SOURCES_DAC ${GC_SOURCES_DAC}) diff --git a/src/gc/env/gcenv.base.h b/src/gc/env/gcenv.base.h index a94f1a6..94f7376 100644 --- a/src/gc/env/gcenv.base.h +++ b/src/gc/env/gcenv.base.h @@ -447,7 +447,7 @@ extern bool g_fFinalizerRunOnShutDown; // Locks // -struct alloc_context; +struct gc_alloc_context; class Thread; Thread * GetThread(); diff --git a/src/gc/env/gcenv.ee.h b/src/gc/env/gcenv.ee.h index 0c1fd49..beb0c1a 100644 --- a/src/gc/env/gcenv.ee.h +++ b/src/gc/env/gcenv.ee.h @@ -7,35 +7,11 @@ #ifndef __GCENV_EE_H__ #define __GCENV_EE_H__ -struct ScanContext; -class CrawlFrame; - -typedef void promote_func(PTR_PTR_Object, ScanContext*, uint32_t); - -typedef void enum_alloc_context_func(alloc_context*, void*); - -typedef struct -{ - promote_func* f; - ScanContext* sc; - CrawlFrame * cf; -} GCCONTEXT; - -// GC background thread function prototype -typedef uint32_t (__stdcall *GCBackgroundThreadFunction)(void* param); +#include "gcinterface.h" class GCToEEInterface { public: - // - // Suspend/Resume callbacks - // - typedef enum - { - SUSPEND_FOR_GC = 1, - SUSPEND_FOR_GC_PREP = 6 - } SUSPEND_REASON; - static void SuspendEE(SUSPEND_REASON reason); static void RestartEE(bool bFinishedGC); //resume threads. @@ -74,12 +50,22 @@ public: static void EnablePreemptiveGC(Thread * pThread); static void DisablePreemptiveGC(Thread * pThread); - static alloc_context * GetAllocContext(Thread * pThread); + static gc_alloc_context * GetAllocContext(Thread * pThread); static bool CatchAtSafePoint(Thread * pThread); static void GcEnumAllocContexts(enum_alloc_context_func* fn, void* param); static Thread* CreateBackgroundThread(GCBackgroundThreadFunction threadStart, void* arg); + + // Diagnostics methods. + static void DiagGCStart(int gen, bool isInduced); + static void DiagUpdateGenerationBounds(); + static void DiagGCEnd(size_t index, int gen, int reason, bool fConcurrent); + static void DiagWalkFReachableObjects(void* gcContext); + static void DiagWalkSurvivors(void* gcContext); + static void DiagWalkLOHSurvivors(void* gcContext); + static void DiagWalkBGCSurvivors(void* gcContext); + static void StompWriteBarrier(WriteBarrierParameters* args); }; #endif // __GCENV_EE_H__ diff --git a/src/gc/env/gcenv.object.h b/src/gc/env/gcenv.object.h index c999e45..db8995a 100644 --- a/src/gc/env/gcenv.object.h +++ b/src/gc/env/gcenv.object.h @@ -31,6 +31,8 @@ public: void ClrGCBit() { m_uSyncBlockValue &= ~BIT_SBLK_GC_RESERVE; } }; +static_assert(sizeof(ObjHeader) == sizeof(uintptr_t), "this assumption is made by the VM!"); + #define MTFlag_ContainsPointers 1 #define MTFlag_HasFinalizer 2 #define MTFlag_IsArray 4 diff --git a/src/gc/env/gcenv.os.h b/src/gc/env/gcenv.os.h index bb0153f..6a126f2 100644 --- a/src/gc/env/gcenv.os.h +++ b/src/gc/env/gcenv.os.h @@ -73,13 +73,12 @@ public: // Reserve virtual memory range. // Parameters: - // address - starting virtual address, it can be NULL to let the function choose the starting address // size - size of the virtual memory range // alignment - requested memory alignment // flags - flags to control special settings like write watching // Return: // Starting virtual address of the reserved range - static void* VirtualReserve(void *address, size_t size, size_t alignment, uint32_t flags); + static void* VirtualReserve(size_t size, size_t alignment, uint32_t flags); // Release virtual memory range previously reserved using VirtualReserve // Parameters: diff --git a/src/gc/gc.cpp b/src/gc/gc.cpp index a62b02d..6187938 100644 --- a/src/gc/gc.cpp +++ b/src/gc/gc.cpp @@ -21,22 +21,6 @@ #define USE_INTROSORT -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) -inline BOOL ShouldTrackMovementForProfilerOrEtw() -{ -#ifdef GC_PROFILING - if (CORProfilerTrackGC()) - return true; -#endif - -#ifdef FEATURE_EVENT_TRACE - if (ETW::GCLog::ShouldTrackMovementForEtw()) - return true; -#endif - - return false; -} -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) #if defined(BACKGROUND_GC) && defined(FEATURE_EVENT_TRACE) BOOL bgc_heap_walk_for_etw_p = FALSE; @@ -349,8 +333,8 @@ void gc_heap::add_to_history_per_heap() #endif //BACKGROUND_GC current_hist->fgc_lowest = lowest_address; current_hist->fgc_highest = highest_address; - current_hist->g_lowest = g_lowest_address; - current_hist->g_highest = g_highest_address; + current_hist->g_lowest = g_gc_lowest_address; + current_hist->g_highest = g_gc_highest_address; gchist_index_per_heap++; if (gchist_index_per_heap == max_history_count) @@ -1418,8 +1402,8 @@ int mark_time, plan_time, sweep_time, reloc_time, compact_time; #ifndef MULTIPLE_HEAPS -#define ephemeral_low g_ephemeral_low -#define ephemeral_high g_ephemeral_high +#define ephemeral_low g_gc_ephemeral_low +#define ephemeral_high g_gc_ephemeral_high #endif // MULTIPLE_HEAPS @@ -1544,7 +1528,7 @@ void WaitLongerNoInstru (int i) } else if (g_TrapReturningThreads) { - GCHeap::GetGCHeap()->WaitUntilGCComplete(); + g_theGCHeap->WaitUntilGCComplete(); } } @@ -1573,7 +1557,7 @@ retry: unsigned int i = 0; while (VolatileLoad(lock) >= 0) { - if ((++i & 7) && !GCHeap::IsGCInProgress()) + if ((++i & 7) && !IsGCInProgress()) { if (g_SystemInfo.dwNumberOfProcessors > 1) { @@ -1584,11 +1568,11 @@ retry: #endif //!MULTIPLE_HEAPS for (int j = 0; j < spin_count; j++) { - if (VolatileLoad(lock) < 0 || GCHeap::IsGCInProgress()) + if (VolatileLoad(lock) < 0 || IsGCInProgress()) break; YieldProcessor(); // indicate to the processor that we are spining } - if (VolatileLoad(lock) >= 0 && !GCHeap::IsGCInProgress()) + if (VolatileLoad(lock) >= 0 && !IsGCInProgress()) { safe_switch_to_thread(); } @@ -2192,6 +2176,55 @@ int log2(unsigned int n) return pos; } +#ifndef DACCESS_COMPILE + +void stomp_write_barrier_resize(bool is_runtime_suspended, bool requires_upper_bounds_check) +{ + WriteBarrierParameters args = {}; + args.operation = WriteBarrierOp::StompResize; + args.is_runtime_suspended = is_runtime_suspended; + args.requires_upper_bounds_check = requires_upper_bounds_check; + args.card_table = g_gc_card_table; + args.lowest_address = g_gc_lowest_address; + args.highest_address = g_gc_highest_address; + GCToEEInterface::StompWriteBarrier(&args); +} + +void stomp_write_barrier_ephemeral(bool is_runtime_suspended, uint8_t* ephemeral_lo, uint8_t* ephemeral_hi) +{ + WriteBarrierParameters args = {}; + args.operation = WriteBarrierOp::StompEphemeral; + args.is_runtime_suspended = is_runtime_suspended; + args.ephemeral_lo = g_gc_ephemeral_low; + args.ephemeral_hi = g_gc_ephemeral_high; +#ifdef MULTIPLE_HEAPS + // It is not correct to update the EE's g_ephemeral_low and g_ephemeral_high + // to anything other than their default values when using Server GC, since + // there is no single ephemeral generation across all of the heaps. + // Server GC write barriers do not reference these two globals, but ErectWriteBarrier does. + // + // When MULTIPLE_HEAPS is defined, g_gc_ephemeral_low and g_gc_ephemeral_high should + // always have their default values. + assert(args.ephemeral_lo == (uint8_t*)1); + assert(args.ephemeral_hi == (uint8_t*)~0); +#endif // MULTIPLE_HEAPS + GCToEEInterface::StompWriteBarrier(&args); +} + +void stomp_write_barrier_initialize() +{ + WriteBarrierParameters args = {}; + args.operation = WriteBarrierOp::Initialize; + args.is_runtime_suspended = true; + args.requires_upper_bounds_check = false; + args.card_table = g_gc_card_table; + args.lowest_address = g_gc_lowest_address; + args.highest_address = g_gc_highest_address; + GCToEEInterface::StompWriteBarrier(&args); +} + +#endif // DACCESS_COMPILE + //extract the low bits [0,low[ of a uint32_t #define lowbits(wrd, bits) ((wrd) & ((1 << (bits))-1)) //extract the high bits [high, 32] of a uint32_t @@ -3422,7 +3455,7 @@ inline size_t ro_seg_begin_index (heap_segment* seg) { size_t begin_index = (size_t)seg / gc_heap::min_segment_size; - begin_index = max (begin_index, (size_t)g_lowest_address / gc_heap::min_segment_size); + begin_index = max (begin_index, (size_t)g_gc_lowest_address / gc_heap::min_segment_size); return begin_index; } @@ -3430,14 +3463,14 @@ inline size_t ro_seg_end_index (heap_segment* seg) { size_t end_index = (size_t)(heap_segment_reserved (seg) - 1) / gc_heap::min_segment_size; - end_index = min (end_index, (size_t)g_highest_address / gc_heap::min_segment_size); + end_index = min (end_index, (size_t)g_gc_highest_address / gc_heap::min_segment_size); return end_index; } void seg_mapping_table_add_ro_segment (heap_segment* seg) { #ifdef GROWABLE_SEG_MAPPING_TABLE - if ((heap_segment_reserved (seg) <= g_lowest_address) || (heap_segment_mem (seg) >= g_highest_address)) + if ((heap_segment_reserved (seg) <= g_gc_lowest_address) || (heap_segment_mem (seg) >= g_gc_highest_address)) return; #endif //GROWABLE_SEG_MAPPING_TABLE @@ -3621,7 +3654,7 @@ gc_heap* seg_mapping_table_heap_of_worker (uint8_t* o) gc_heap* seg_mapping_table_heap_of (uint8_t* o) { #ifdef GROWABLE_SEG_MAPPING_TABLE - if ((o < g_lowest_address) || (o >= g_highest_address)) + if ((o < g_gc_lowest_address) || (o >= g_gc_highest_address)) return 0; #endif //GROWABLE_SEG_MAPPING_TABLE @@ -3631,7 +3664,7 @@ gc_heap* seg_mapping_table_heap_of (uint8_t* o) gc_heap* seg_mapping_table_heap_of_gc (uint8_t* o) { #if defined(FEATURE_BASICFREEZE) && defined(GROWABLE_SEG_MAPPING_TABLE) - if ((o < g_lowest_address) || (o >= g_highest_address)) + if ((o < g_gc_lowest_address) || (o >= g_gc_highest_address)) return 0; #endif //FEATURE_BASICFREEZE || GROWABLE_SEG_MAPPING_TABLE @@ -3643,7 +3676,7 @@ gc_heap* seg_mapping_table_heap_of_gc (uint8_t* o) heap_segment* seg_mapping_table_segment_of (uint8_t* o) { #if defined(FEATURE_BASICFREEZE) && defined(GROWABLE_SEG_MAPPING_TABLE) - if ((o < g_lowest_address) || (o >= g_highest_address)) + if ((o < g_gc_lowest_address) || (o >= g_gc_highest_address)) #ifdef FEATURE_BASICFREEZE return ro_segment_lookup (o); #else @@ -3686,7 +3719,7 @@ heap_segment* seg_mapping_table_segment_of (uint8_t* o) #ifdef FEATURE_BASICFREEZE // TODO: This was originally written assuming that the seg_mapping_table would always contain entries for ro - // segments whenever the ro segment falls into the [g_lowest_address,g_highest_address) range. I.e., it had an + // segments whenever the ro segment falls into the [g_gc_lowest_address,g_gc_highest_address) range. I.e., it had an // extra "&& (size_t)(entry->seg1) & ro_in_entry" expression. However, at the moment, grow_brick_card_table does // not correctly go through the ro segments and add them back to the seg_mapping_table when the [lowest,highest) // range changes. We should probably go ahead and modify grow_brick_card_table and put back the @@ -3743,9 +3776,9 @@ public: BOOL fSmallObjectHeapPtr = FALSE, fLargeObjectHeapPtr = FALSE; if (!noRangeChecks) { - fSmallObjectHeapPtr = GCHeap::GetGCHeap()->IsHeapPointer(this, TRUE); + fSmallObjectHeapPtr = g_theGCHeap->IsHeapPointer(this, TRUE); if (!fSmallObjectHeapPtr) - fLargeObjectHeapPtr = GCHeap::GetGCHeap()->IsHeapPointer(this); + fLargeObjectHeapPtr = g_theGCHeap->IsHeapPointer(this); _ASSERTE(fSmallObjectHeapPtr || fLargeObjectHeapPtr); } @@ -3763,14 +3796,14 @@ public: #ifdef VERIFY_HEAP if (bDeep && (g_pConfig->GetHeapVerifyLevel() & EEConfig::HEAPVERIFY_GC)) - GCHeap::GetGCHeap()->ValidateObjectMember(this); + g_theGCHeap->ValidateObjectMember(this); #endif if (fSmallObjectHeapPtr) { #ifdef FEATURE_BASICFREEZE - _ASSERTE(!GCHeap::GetGCHeap()->IsLargeObject(pMT) || GCHeap::GetGCHeap()->IsInFrozenSegment(this)); + _ASSERTE(!g_theGCHeap->IsLargeObject(pMT) || g_theGCHeap->IsInFrozenSegment(this)); #else - _ASSERTE(!GCHeap::GetGCHeap()->IsLargeObject(pMT)); + _ASSERTE(!g_theGCHeap->IsLargeObject(pMT)); #endif } } @@ -4086,8 +4119,8 @@ BOOL reserve_initial_memory (size_t normal_size, size_t large_size, size_t num_h memory_details.current_block_normal = 0; memory_details.current_block_large = 0; - g_lowest_address = MAX_PTR; - g_highest_address = 0; + g_gc_lowest_address = MAX_PTR; + g_gc_highest_address = 0; if (((size_t)MAX_PTR - large_size) < normal_size) { @@ -4107,8 +4140,8 @@ BOOL reserve_initial_memory (size_t normal_size, size_t large_size, size_t num_h uint8_t* allatonce_block = (uint8_t*)virtual_alloc (requestedMemory); if (allatonce_block) { - g_lowest_address = allatonce_block; - g_highest_address = allatonce_block + (memory_details.block_count * (large_size + normal_size)); + g_gc_lowest_address = allatonce_block; + g_gc_highest_address = allatonce_block + (memory_details.block_count * (large_size + normal_size)); memory_details.allocation_pattern = initial_memory_details::ALLATONCE; for(size_t i = 0; i < memory_details.block_count; i++) @@ -4131,8 +4164,8 @@ BOOL reserve_initial_memory (size_t normal_size, size_t large_size, size_t num_h if (b2) { memory_details.allocation_pattern = initial_memory_details::TWO_STAGE; - g_lowest_address = min(b1,b2); - g_highest_address = max(b1 + memory_details.block_count*normal_size, + g_gc_lowest_address = min(b1,b2); + g_gc_highest_address = max(b1 + memory_details.block_count*normal_size, b2 + memory_details.block_count*large_size); for(size_t i = 0; i < memory_details.block_count; i++) { @@ -4178,10 +4211,10 @@ BOOL reserve_initial_memory (size_t normal_size, size_t large_size, size_t num_h } else { - if (current_block->memory_base < g_lowest_address) - g_lowest_address = current_block->memory_base; - if (((uint8_t *) current_block->memory_base + block_size) > g_highest_address) - g_highest_address = (current_block->memory_base + block_size); + if (current_block->memory_base < g_gc_lowest_address) + g_gc_lowest_address = current_block->memory_base; + if (((uint8_t *) current_block->memory_base + block_size) > g_gc_highest_address) + g_gc_highest_address = (current_block->memory_base + block_size); } reserve_success = TRUE; } @@ -4288,7 +4321,7 @@ void* virtual_alloc (size_t size) flags = VirtualReserveFlags::WriteWatch; } #endif // !FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP - void* prgmem = GCToOSInterface::VirtualReserve (0, requested_size, card_size * card_word_width, flags); + void* prgmem = GCToOSInterface::VirtualReserve (requested_size, card_size * card_word_width, flags); void *aligned_mem = prgmem; // We don't want (prgmem + size) to be right at the end of the address space @@ -4361,7 +4394,7 @@ static size_t get_valid_segment_size (BOOL large_seg=FALSE) // if seg_size is small but not 0 (0 is default if config not set) // then set the segment to the minimum size - if (!GCHeap::IsValidSegmentSize(seg_size)) + if (!g_theGCHeap->IsValidSegmentSize(seg_size)) { // if requested size is between 1 byte and 4MB, use min if ((seg_size >> 1) && !(seg_size >> 22)) @@ -4623,22 +4656,22 @@ gc_heap::get_segment (size_t size, BOOL loh_p) { uint8_t* start; uint8_t* end; - if (mem < g_lowest_address) + if (mem < g_gc_lowest_address) { start = (uint8_t*)mem; } else { - start = (uint8_t*)g_lowest_address; + start = (uint8_t*)g_gc_lowest_address; } - if (((uint8_t*)mem + size) > g_highest_address) + if (((uint8_t*)mem + size) > g_gc_highest_address) { end = (uint8_t*)mem + size; } else { - end = (uint8_t*)g_highest_address; + end = (uint8_t*)g_gc_highest_address; } if (gc_heap::grow_brick_card_tables (start, end, size, result, __this, loh_p) != 0) @@ -4703,10 +4736,7 @@ heap_segment* gc_heap::get_segment_for_loh (size_t size FireEtwGCCreateSegment_V1((size_t)heap_segment_mem(res), (size_t)(heap_segment_reserved (res) - heap_segment_mem(res)), ETW::GCLog::ETW_GC_INFO::LARGE_OBJECT_HEAP, GetClrInstanceId()); -#ifdef GC_PROFILING - if (CORProfilerTrackGC()) - UpdateGenerationBounds(); -#endif // GC_PROFILING + GCToEEInterface::DiagUpdateGenerationBounds(); #ifdef MULTIPLE_HEAPS hp->thread_loh_segment (res); @@ -5231,7 +5261,7 @@ void gc_heap::gc_thread_function () gc_heap::ee_suspend_event.Wait(INFINITE, FALSE); BEGIN_TIMING(suspend_ee_during_log); - GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_FOR_GC); + GCToEEInterface::SuspendEE(SUSPEND_FOR_GC); END_TIMING(suspend_ee_during_log); proceed_with_gc_p = TRUE; @@ -5340,7 +5370,7 @@ heap_segment* gc_heap::segment_of (uint8_t* add, ptrdiff_t& delta, BOOL verify_p uint8_t* sadd = add; heap_segment* hs = 0; heap_segment* hs1 = 0; - if (!((add >= g_lowest_address) && (add < g_highest_address))) + if (!((add >= g_gc_lowest_address) && (add < g_gc_highest_address))) { delta = 0; return 0; @@ -5523,7 +5553,6 @@ public: saved_post_plug_reloc = temp; } -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) void swap_pre_plug_and_saved_for_profiler() { gap_reloc_pair temp; @@ -5539,7 +5568,6 @@ public: memcpy (saved_post_plug_info_start, &saved_post_plug, sizeof (saved_post_plug)); saved_post_plug = temp; } -#endif //GC_PROFILING || //FEATURE_EVENT_TRACE // We should think about whether it's really necessary to have to copy back the pre plug // info since it was already copied during compacting plugs. But if a plug doesn't move @@ -5775,7 +5803,7 @@ void gc_heap::fix_allocation_context (alloc_context* acontext, BOOL for_gc_p, //used by the heap verification for concurrent gc. //it nulls out the words set by fix_allocation_context for heap_verification -void repair_allocation (alloc_context* acontext, void*) +void repair_allocation (gc_alloc_context* acontext, void*) { uint8_t* point = acontext->alloc_ptr; @@ -5788,7 +5816,7 @@ void repair_allocation (alloc_context* acontext, void*) } } -void void_allocation (alloc_context* acontext, void*) +void void_allocation (gc_alloc_context* acontext, void*) { uint8_t* point = acontext->alloc_ptr; @@ -5818,10 +5846,10 @@ struct fix_alloc_context_args void* heap; }; -void fix_alloc_context(alloc_context* acontext, void* param) +void fix_alloc_context(gc_alloc_context* acontext, void* param) { fix_alloc_context_args* args = (fix_alloc_context_args*)param; - GCHeap::GetGCHeap()->FixAllocContext(acontext, FALSE, (void*)(size_t)(args->for_gc_p), args->heap); + g_theGCHeap->FixAllocContext(acontext, FALSE, (void*)(size_t)(args->for_gc_p), args->heap); } void gc_heap::fix_allocation_contexts(BOOL for_gc_p) @@ -6399,7 +6427,7 @@ void gc_heap::set_card (size_t card) inline void gset_card (size_t card) { - g_card_table [card_word (card)] |= (1 << card_bit (card)); + g_gc_card_table [card_word (card)] |= (1 << card_bit (card)); } inline @@ -6510,7 +6538,7 @@ size_t size_card_bundle_of (uint8_t* from, uint8_t* end) uint32_t* translate_card_bundle_table (uint32_t* cb) { - return (uint32_t*)((uint8_t*)cb - ((((size_t)g_lowest_address) / (card_size*card_word_width*card_bundle_size*card_bundle_word_width)) * sizeof (uint32_t))); + return (uint32_t*)((uint8_t*)cb - ((((size_t)g_gc_lowest_address) / (card_size*card_word_width*card_bundle_size*card_bundle_word_width)) * sizeof (uint32_t))); } void gc_heap::enable_card_bundles () @@ -6722,7 +6750,7 @@ size_t size_mark_array_of (uint8_t* from, uint8_t* end) // according to the lowest_address. uint32_t* translate_mark_array (uint32_t* ma) { - return (uint32_t*)((uint8_t*)ma - size_mark_array_of (0, g_lowest_address)); + return (uint32_t*)((uint8_t*)ma - size_mark_array_of (0, g_gc_lowest_address)); } // from and end must be page aligned addresses. @@ -6850,16 +6878,16 @@ void release_card_table (uint32_t* c_table) { destroy_card_table (c_table); // sever the link from the parent - if (&g_card_table[card_word (gcard_of(g_lowest_address))] == c_table) + if (&g_gc_card_table[card_word (gcard_of(g_gc_lowest_address))] == c_table) { - g_card_table = 0; + g_gc_card_table = 0; #ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP SoftwareWriteWatch::StaticClose(); #endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP } else { - uint32_t* p_table = &g_card_table[card_word (gcard_of(g_lowest_address))]; + uint32_t* p_table = &g_gc_card_table[card_word (gcard_of(g_gc_lowest_address))]; if (p_table) { while (p_table && (card_table_next (p_table) != c_table)) @@ -6881,8 +6909,8 @@ void destroy_card_table (uint32_t* c_table) uint32_t* gc_heap::make_card_table (uint8_t* start, uint8_t* end) { - assert (g_lowest_address == start); - assert (g_highest_address == end); + assert (g_gc_lowest_address == start); + assert (g_gc_highest_address == end); uint32_t virtual_reserve_flags = VirtualReserveFlags::None; @@ -6902,7 +6930,7 @@ uint32_t* gc_heap::make_card_table (uint8_t* start, uint8_t* end) if (can_use_write_watch_for_card_table()) { virtual_reserve_flags |= VirtualReserveFlags::WriteWatch; - cb = size_card_bundle_of (g_lowest_address, g_highest_address); + cb = size_card_bundle_of (g_gc_lowest_address, g_gc_highest_address); } #endif //CARD_BUNDLE @@ -6918,7 +6946,7 @@ uint32_t* gc_heap::make_card_table (uint8_t* start, uint8_t* end) #endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP #ifdef GROWABLE_SEG_MAPPING_TABLE - size_t st = size_seg_mapping_table_of (g_lowest_address, g_highest_address); + size_t st = size_seg_mapping_table_of (g_gc_lowest_address, g_gc_highest_address); size_t st_table_offset = sizeof(card_table_info) + cs + bs + cb + wws; size_t st_table_offset_aligned = align_for_seg_mapping_table (st_table_offset); @@ -6932,7 +6960,7 @@ uint32_t* gc_heap::make_card_table (uint8_t* start, uint8_t* end) size_t alloc_size = sizeof (uint8_t)*(sizeof(card_table_info) + cs + bs + cb + wws + st + ms); size_t alloc_size_aligned = Align (alloc_size, g_SystemInfo.dwAllocationGranularity-1); - uint8_t* mem = (uint8_t*)GCToOSInterface::VirtualReserve (0, alloc_size_aligned, 0, virtual_reserve_flags); + uint8_t* mem = (uint8_t*)GCToOSInterface::VirtualReserve (alloc_size_aligned, 0, virtual_reserve_flags); if (!mem) return 0; @@ -6973,7 +7001,7 @@ uint32_t* gc_heap::make_card_table (uint8_t* start, uint8_t* end) #ifdef GROWABLE_SEG_MAPPING_TABLE seg_mapping_table = (seg_mapping*)(mem + st_table_offset_aligned); seg_mapping_table = (seg_mapping*)((uint8_t*)seg_mapping_table - - size_seg_mapping_table_of (0, (align_lower_segment (g_lowest_address)))); + size_seg_mapping_table_of (0, (align_lower_segment (g_gc_lowest_address)))); #endif //GROWABLE_SEG_MAPPING_TABLE #ifdef MARK_ARRAY @@ -7012,10 +7040,10 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, gc_heap* hp, BOOL loh_p) { - uint8_t* la = g_lowest_address; - uint8_t* ha = g_highest_address; - uint8_t* saved_g_lowest_address = min (start, g_lowest_address); - uint8_t* saved_g_highest_address = max (end, g_highest_address); + uint8_t* la = g_gc_lowest_address; + uint8_t* ha = g_gc_highest_address; + uint8_t* saved_g_lowest_address = min (start, g_gc_lowest_address); + uint8_t* saved_g_highest_address = max (end, g_gc_highest_address); #ifdef BACKGROUND_GC // This value is only for logging purpose - it's not necessarily exactly what we // would commit for mark array but close enough for diagnostics purpose. @@ -7045,18 +7073,18 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, #endif // BIT64 ps *= 2; - if (saved_g_lowest_address < g_lowest_address) + if (saved_g_lowest_address < g_gc_lowest_address) { - if (ps > (size_t)g_lowest_address) + if (ps > (size_t)g_gc_lowest_address) saved_g_lowest_address = (uint8_t*)OS_PAGE_SIZE; else { - assert (((size_t)g_lowest_address - ps) >= OS_PAGE_SIZE); - saved_g_lowest_address = min (saved_g_lowest_address, (g_lowest_address - ps)); + assert (((size_t)g_gc_lowest_address - ps) >= OS_PAGE_SIZE); + saved_g_lowest_address = min (saved_g_lowest_address, (g_gc_lowest_address - ps)); } } - if (saved_g_highest_address > g_highest_address) + if (saved_g_highest_address > g_gc_highest_address) { saved_g_highest_address = max ((saved_g_lowest_address + ps), saved_g_highest_address); if (saved_g_highest_address > top) @@ -7069,7 +7097,7 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, bool write_barrier_updated = false; uint32_t virtual_reserve_flags = VirtualReserveFlags::None; - uint32_t* saved_g_card_table = g_card_table; + uint32_t* saved_g_card_table = g_gc_card_table; uint32_t* ct = 0; uint32_t* translated_ct = 0; short* bt = 0; @@ -7125,7 +7153,7 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, dprintf (GC_TABLE_LOG, ("card table: %Id; brick table: %Id; card bundle: %Id; sw ww table: %Id; seg table: %Id; mark array: %Id", cs, bs, cb, wws, st, ms)); - uint8_t* mem = (uint8_t*)GCToOSInterface::VirtualReserve (0, alloc_size_aligned, 0, virtual_reserve_flags); + uint8_t* mem = (uint8_t*)GCToOSInterface::VirtualReserve (alloc_size_aligned, 0, virtual_reserve_flags); if (!mem) { @@ -7152,7 +7180,7 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, card_table_refcount (ct) = 0; card_table_lowest_address (ct) = saved_g_lowest_address; card_table_highest_address (ct) = saved_g_highest_address; - card_table_next (ct) = &g_card_table[card_word (gcard_of (la))]; + card_table_next (ct) = &g_gc_card_table[card_word (gcard_of (la))]; //clear the card table /* @@ -7179,9 +7207,9 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, seg_mapping* new_seg_mapping_table = (seg_mapping*)(mem + st_table_offset_aligned); new_seg_mapping_table = (seg_mapping*)((uint8_t*)new_seg_mapping_table - size_seg_mapping_table_of (0, (align_lower_segment (saved_g_lowest_address)))); - memcpy(&new_seg_mapping_table[seg_mapping_word_of(g_lowest_address)], - &seg_mapping_table[seg_mapping_word_of(g_lowest_address)], - size_seg_mapping_table_of(g_lowest_address, g_highest_address)); + memcpy(&new_seg_mapping_table[seg_mapping_word_of(g_gc_lowest_address)], + &seg_mapping_table[seg_mapping_word_of(g_gc_lowest_address)], + size_seg_mapping_table_of(g_gc_lowest_address, g_gc_highest_address)); seg_mapping_table = new_seg_mapping_table; } @@ -7243,12 +7271,14 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, // Note on points where the runtime is suspended anywhere in this function. Upon an attempt to suspend the // runtime, a different thread may suspend first, causing this thread to block at the point of the suspend call. // So, at any suspend point, externally visible state needs to be consistent, as code that depends on that state - // may run while this thread is blocked. This includes updates to g_card_table, g_lowest_address, and - // g_highest_address. + // may run while this thread is blocked. This includes updates to g_gc_card_table, g_gc_lowest_address, and + // g_gc_highest_address. suspend_EE(); } - g_card_table = translated_ct; + g_gc_card_table = translated_ct; + g_gc_lowest_address = saved_g_lowest_address; + g_gc_highest_address = saved_g_highest_address; SoftwareWriteWatch::SetResizedUntranslatedTable( mem + sw_ww_table_offset, @@ -7260,7 +7290,7 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, // grow version of the write barrier. This test tells us if the new // segment was allocated at a lower address than the old, requiring // that we start doing an upper bounds check in the write barrier. - StompWriteBarrierResize(true, la != saved_g_lowest_address); + stomp_write_barrier_resize(true, la != saved_g_lowest_address); write_barrier_updated = true; if (!is_runtime_suspended) @@ -7271,9 +7301,12 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, else #endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP { - g_card_table = translated_ct; + g_gc_card_table = translated_ct; } + g_gc_lowest_address = saved_g_lowest_address; + g_gc_highest_address = saved_g_highest_address; + if (!write_barrier_updated) { // This passes a bool telling whether we need to switch to the post @@ -7284,19 +7317,9 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, // to be changed, so we are doing this after all global state has // been updated. See the comment above suspend_EE() above for more // info. - StompWriteBarrierResize(!!IsGCThread(), la != saved_g_lowest_address); + stomp_write_barrier_resize(!!IsGCThread(), la != saved_g_lowest_address); } - // We need to make sure that other threads executing checked write barriers - // will see the g_card_table update before g_lowest/highest_address updates. - // Otherwise, the checked write barrier may AV accessing the old card table - // with address that it does not cover. Write barriers access card table - // without memory barriers for performance reasons, so we need to flush - // the store buffers here. - GCToOSInterface::FlushProcessWriteBuffers(); - - g_lowest_address = saved_g_lowest_address; - VolatileStore(&g_highest_address, saved_g_highest_address); return 0; @@ -7305,7 +7328,7 @@ fail: if (mem) { - assert(g_card_table == saved_g_card_table); + assert(g_gc_card_table == saved_g_card_table); //delete (uint32_t*)((uint8_t*)ct - sizeof(card_table_info)); if (!GCToOSInterface::VirtualRelease (mem, alloc_size_aligned)) @@ -7463,7 +7486,7 @@ void gc_heap::copy_brick_card_table() assert (ha == card_table_highest_address (&old_card_table[card_word (card_of (la))])); /* todo: Need a global lock for this */ - uint32_t* ct = &g_card_table[card_word (gcard_of (g_lowest_address))]; + uint32_t* ct = &g_gc_card_table[card_word (gcard_of (g_gc_lowest_address))]; own_card_table (ct); card_table = translate_card_table (ct); /* End of global lock */ @@ -7476,8 +7499,8 @@ void gc_heap::copy_brick_card_table() if (gc_can_use_concurrent) { mark_array = translate_mark_array (card_table_mark_array (ct)); - assert (mark_word_of (g_highest_address) == - mark_word_of (align_on_mark_word (g_highest_address))); + assert (mark_word_of (g_gc_highest_address) == + mark_word_of (align_on_mark_word (g_gc_highest_address))); } else mark_array = NULL; @@ -7486,13 +7509,13 @@ void gc_heap::copy_brick_card_table() #ifdef CARD_BUNDLE #if defined(MARK_ARRAY) && defined(_DEBUG) #ifdef GROWABLE_SEG_MAPPING_TABLE - size_t st = size_seg_mapping_table_of (g_lowest_address, g_highest_address); + size_t st = size_seg_mapping_table_of (g_gc_lowest_address, g_gc_highest_address); #else //GROWABLE_SEG_MAPPING_TABLE size_t st = 0; #endif //GROWABLE_SEG_MAPPING_TABLE #endif //MARK_ARRAY && _DEBUG card_bundle_table = translate_card_bundle_table (card_table_card_bundle_table (ct)); - assert (&card_bundle_table [card_bundle_word (cardw_card_bundle (card_word (card_of (g_lowest_address))))] == + assert (&card_bundle_table [card_bundle_word (cardw_card_bundle (card_word (card_of (g_gc_lowest_address))))] == card_table_card_bundle_table (ct)); //set the card table if we are in a heap growth scenario @@ -9330,13 +9353,13 @@ void gc_heap::update_card_table_bundle() bool success = GCToOSInterface::GetWriteWatch (false /* resetState */ , base_address, region_size, (void**)g_addresses, &bcount); - assert (success); + assert (success && "GetWriteWatch failed!"); dprintf (3,("Found %d pages written", bcount)); for (unsigned i = 0; i < bcount; i++) { size_t bcardw = (uint32_t*)(max(g_addresses[i],base_address)) - &card_table[0]; size_t ecardw = (uint32_t*)(min(g_addresses[i]+OS_PAGE_SIZE, high_address)) - &card_table[0]; - assert (bcardw >= card_word (card_of (g_lowest_address))); + assert (bcardw >= card_word (card_of (g_gc_lowest_address))); card_bundles_set (cardw_card_bundle (bcardw), cardw_card_bundle (align_cardw_on_bundle (ecardw))); @@ -9648,7 +9671,7 @@ void gc_heap::adjust_ephemeral_limits (bool is_runtime_suspended) (size_t)ephemeral_low, (size_t)ephemeral_high)) // This updates the write barrier helpers with the new info. - StompWriteBarrierEphemeral(is_runtime_suspended); + stomp_write_barrier_ephemeral(is_runtime_suspended, ephemeral_low, ephemeral_high); } #if defined(TRACE_GC) || defined(GC_CONFIG_DRIVEN) @@ -9821,9 +9844,9 @@ HRESULT gc_heap::initialize_gc (size_t segment_size, settings.first_init(); - g_card_table = make_card_table (g_lowest_address, g_highest_address); + g_gc_card_table = make_card_table (g_gc_lowest_address, g_gc_highest_address); - if (!g_card_table) + if (!g_gc_card_table) return E_OUTOFMEMORY; gc_started = FALSE; @@ -9972,8 +9995,8 @@ gc_heap::init_semi_shared() { goto cleanup; } -#endif //BACKGROUND_GC } +#endif //BACKGROUND_GC memset (¤t_no_gc_region_info, 0, sizeof (current_no_gc_region_info)); @@ -10306,7 +10329,7 @@ gc_heap::init_gc_heap (int h_number) #endif //MULTIPLE_HEAPS /* todo: Need a global lock for this */ - uint32_t* ct = &g_card_table [card_word (card_of (g_lowest_address))]; + uint32_t* ct = &g_gc_card_table [card_word (card_of (g_gc_lowest_address))]; own_card_table (ct); card_table = translate_card_table (ct); /* End of global lock */ @@ -10317,13 +10340,13 @@ gc_heap::init_gc_heap (int h_number) #ifdef CARD_BUNDLE card_bundle_table = translate_card_bundle_table (card_table_card_bundle_table (ct)); - assert (&card_bundle_table [card_bundle_word (cardw_card_bundle (card_word (card_of (g_lowest_address))))] == + assert (&card_bundle_table [card_bundle_word (cardw_card_bundle (card_word (card_of (g_gc_lowest_address))))] == card_table_card_bundle_table (ct)); #endif //CARD_BUNDLE #ifdef MARK_ARRAY if (gc_can_use_concurrent) - mark_array = translate_mark_array (card_table_mark_array (&g_card_table[card_word (card_of (g_lowest_address))])); + mark_array = translate_mark_array (card_table_mark_array (&g_gc_card_table[card_word (card_of (g_gc_lowest_address))])); else mark_array = NULL; #endif //MARK_ARRAY @@ -10360,6 +10383,7 @@ gc_heap::init_gc_heap (int h_number) (size_t)(heap_segment_reserved (lseg) - heap_segment_mem(lseg)), ETW::GCLog::ETW_GC_INFO::LARGE_OBJECT_HEAP, GetClrInstanceId()); + #ifdef SEG_MAPPING_TABLE seg_mapping_table_add_segment (lseg, __this); #else //SEG_MAPPING_TABLE @@ -10384,10 +10408,10 @@ gc_heap::init_gc_heap (int h_number) heap_segment_heap (lseg) = this; //initialize the alloc context heap - generation_alloc_context (generation_of (0))->alloc_heap = vm_heap; + generation_alloc_context (generation_of (0))->set_alloc_heap(vm_heap); //initialize the alloc context heap - generation_alloc_context (generation_of (max_generation+1))->alloc_heap = vm_heap; + generation_alloc_context (generation_of (max_generation+1))->set_alloc_heap(vm_heap); #endif //MULTIPLE_HEAPS @@ -13043,12 +13067,12 @@ int gc_heap::try_allocate_more_space (alloc_context* acontext, size_t size, if (can_allocate) { - //ETW trace for allocation tick size_t alloc_context_bytes = acontext->alloc_limit + Align (min_obj_size, align_const) - acontext->alloc_ptr; int etw_allocation_index = ((gen_number == 0) ? 0 : 1); etw_allocation_running_amount[etw_allocation_index] += alloc_context_bytes; + if (etw_allocation_running_amount[etw_allocation_index] > etw_allocation_tick) { #ifdef FEATURE_REDHAWK @@ -13080,10 +13104,10 @@ void gc_heap::balance_heaps (alloc_context* acontext) { if (acontext->alloc_count == 0) { - acontext->home_heap = GCHeap::GetHeap( heap_select::select_heap(acontext, 0) ); - gc_heap* hp = acontext->home_heap->pGenGCHeap; + acontext->set_home_heap(GCHeap::GetHeap( heap_select::select_heap(acontext, 0) )); + gc_heap* hp = acontext->get_home_heap()->pGenGCHeap; dprintf (3, ("First allocation for context %Ix on heap %d\n", (size_t)acontext, (size_t)hp->heap_number)); - acontext->alloc_heap = acontext->home_heap; + acontext->set_alloc_heap(acontext->get_home_heap()); hp->alloc_context_count++; } } @@ -13094,9 +13118,9 @@ void gc_heap::balance_heaps (alloc_context* acontext) if (heap_select::can_find_heap_fast()) { - if (acontext->home_heap != NULL) - hint = acontext->home_heap->pGenGCHeap->heap_number; - if (acontext->home_heap != GCHeap::GetHeap(hint = heap_select::select_heap(acontext, hint)) || ((acontext->alloc_count & 15) == 0)) + if (acontext->get_home_heap() != NULL) + hint = acontext->get_home_heap()->pGenGCHeap->heap_number; + if (acontext->get_home_heap() != GCHeap::GetHeap(hint = heap_select::select_heap(acontext, hint)) || ((acontext->alloc_count & 15) == 0)) { set_home_heap = TRUE; } @@ -13122,7 +13146,7 @@ void gc_heap::balance_heaps (alloc_context* acontext) else */ { - gc_heap* org_hp = acontext->alloc_heap->pGenGCHeap; + gc_heap* org_hp = acontext->get_alloc_heap()->pGenGCHeap; dynamic_data* dd = org_hp->dynamic_data_of (0); ptrdiff_t org_size = dd_new_allocation (dd); @@ -13141,9 +13165,9 @@ try_again: { max_hp = org_hp; max_size = org_size + delta; - acontext->home_heap = GCHeap::GetHeap( heap_select::select_heap(acontext, hint) ); + acontext->set_home_heap(GCHeap::GetHeap( heap_select::select_heap(acontext, hint) )); - if (org_hp == acontext->home_heap->pGenGCHeap) + if (org_hp == acontext->get_home_heap()->pGenGCHeap) max_size = max_size + delta; org_alloc_context_count = org_hp->alloc_context_count; @@ -13156,7 +13180,7 @@ try_again: gc_heap* hp = GCHeap::GetHeap(i%n_heaps)->pGenGCHeap; dd = hp->dynamic_data_of (0); ptrdiff_t size = dd_new_allocation (dd); - if (hp == acontext->home_heap->pGenGCHeap) + if (hp == acontext->get_home_heap()->pGenGCHeap) size = size + delta; int hp_alloc_context_count = hp->alloc_context_count; if (hp_alloc_context_count > 0) @@ -13183,7 +13207,7 @@ try_again: { org_hp->alloc_context_count--; max_hp->alloc_context_count++; - acontext->alloc_heap = GCHeap::GetHeap(max_hp->heap_number); + acontext->set_alloc_heap(GCHeap::GetHeap(max_hp->heap_number)); #if !defined(FEATURE_PAL) if (CPUGroupInfo::CanEnableGCCPUGroups()) { //only set ideal processor when max_hp and org_hp are in the same cpu @@ -13221,7 +13245,7 @@ try_again: #endif // !FEATURE_PAL dprintf (3, ("Switching context %p (home heap %d) ", acontext, - acontext->home_heap->pGenGCHeap->heap_number)); + acontext->get_home_heap()->pGenGCHeap->heap_number)); dprintf (3, (" from heap %d (%Id free bytes, %d contexts) ", org_hp->heap_number, org_size, @@ -13239,7 +13263,7 @@ try_again: gc_heap* gc_heap::balance_heaps_loh (alloc_context* acontext, size_t /*size*/) { - gc_heap* org_hp = acontext->alloc_heap->pGenGCHeap; + gc_heap* org_hp = acontext->get_alloc_heap()->pGenGCHeap; //dprintf (1, ("LA: %Id", size)); //if (size > 128*1024) @@ -13316,7 +13340,7 @@ BOOL gc_heap::allocate_more_space(alloc_context* acontext, size_t size, if (alloc_generation_number == 0) { balance_heaps (acontext); - status = acontext->alloc_heap->pGenGCHeap->try_allocate_more_space (acontext, size, alloc_generation_number); + status = acontext->get_alloc_heap()->pGenGCHeap->try_allocate_more_space (acontext, size, alloc_generation_number); } else { @@ -14785,6 +14809,9 @@ int gc_heap::generation_to_condemn (int n_initial, dprintf (GTC_LOG, ("h%d: alloc full - BLOCK", heap_number)); n = max_generation; *blocking_collection_p = TRUE; + if ((local_settings->reason == reason_oos_loh) || + (local_settings->reason == reason_alloc_loh)) + evaluate_elevation = FALSE; local_condemn_reasons->set_condition (gen_before_oom); } @@ -15183,7 +15210,7 @@ void gc_heap::gc1() vm_heap->GcCondemnedGeneration = settings.condemned_generation; - assert (g_card_table == card_table); + assert (g_gc_card_table == card_table); { if (n == max_generation) @@ -15472,7 +15499,15 @@ void gc_heap::gc1() #ifdef FEATURE_EVENT_TRACE if (bgc_heap_walk_for_etw_p && settings.concurrent) { - make_free_lists_for_profiler_for_bgc(); + GCToEEInterface::DiagWalkBGCSurvivors(__this); + +#ifdef MULTIPLE_HEAPS + bgc_t_join.join(this, gc_join_after_profiler_heap_walk); + if (bgc_t_join.joined()) + { + bgc_t_join.restart(); + } +#endif // MULTIPLE_HEAPS } #endif // FEATURE_EVENT_TRACE #endif //BACKGROUND_GC @@ -16382,7 +16417,7 @@ int gc_heap::garbage_collect (int n) for (int i = 0; i < n_heaps; i++) { //copy the card and brick tables - if (g_card_table != g_heaps[i]->card_table) + if (g_gc_card_table != g_heaps[i]->card_table) { g_heaps[i]->copy_brick_card_table(); } @@ -16406,100 +16441,67 @@ int gc_heap::garbage_collect (int n) } #endif //BACKGROUND_GC // check for card table growth - if (g_card_table != card_table) + if (g_gc_card_table != card_table) copy_brick_card_table(); #endif //MULTIPLE_HEAPS - BOOL should_evaluate_elevation = FALSE; - BOOL should_do_blocking_collection = FALSE; + BOOL should_evaluate_elevation = FALSE; + BOOL should_do_blocking_collection = FALSE; #ifdef MULTIPLE_HEAPS - int gen_max = condemned_generation_num; - for (int i = 0; i < n_heaps; i++) - { - if (gen_max < g_heaps[i]->condemned_generation_num) - gen_max = g_heaps[i]->condemned_generation_num; - if ((!should_evaluate_elevation) && (g_heaps[i]->elevation_requested)) - should_evaluate_elevation = TRUE; - if ((!should_do_blocking_collection) && (g_heaps[i]->blocking_collection)) - should_do_blocking_collection = TRUE; - } + int gen_max = condemned_generation_num; + for (int i = 0; i < n_heaps; i++) + { + if (gen_max < g_heaps[i]->condemned_generation_num) + gen_max = g_heaps[i]->condemned_generation_num; + if ((!should_evaluate_elevation) && (g_heaps[i]->elevation_requested)) + should_evaluate_elevation = TRUE; + if ((!should_do_blocking_collection) && (g_heaps[i]->blocking_collection)) + should_do_blocking_collection = TRUE; + } - settings.condemned_generation = gen_max; -//logically continues after GC_PROFILING. + settings.condemned_generation = gen_max; #else //MULTIPLE_HEAPS - settings.condemned_generation = generation_to_condemn (n, - &blocking_collection, - &elevation_requested, - FALSE); - should_evaluate_elevation = elevation_requested; - should_do_blocking_collection = blocking_collection; -#endif //MULTIPLE_HEAPS - - settings.condemned_generation = joined_generation_to_condemn ( - should_evaluate_elevation, - settings.condemned_generation, - &should_do_blocking_collection - STRESS_HEAP_ARG(n) - ); + settings.condemned_generation = generation_to_condemn (n, + &blocking_collection, + &elevation_requested, + FALSE); + should_evaluate_elevation = elevation_requested; + should_do_blocking_collection = blocking_collection; +#endif //MULTIPLE_HEAPS + + settings.condemned_generation = joined_generation_to_condemn ( + should_evaluate_elevation, + settings.condemned_generation, + &should_do_blocking_collection + STRESS_HEAP_ARG(n) + ); - STRESS_LOG1(LF_GCROOTS|LF_GC|LF_GCALLOC, LL_INFO10, - "condemned generation num: %d\n", settings.condemned_generation); + STRESS_LOG1(LF_GCROOTS|LF_GC|LF_GCALLOC, LL_INFO10, + "condemned generation num: %d\n", settings.condemned_generation); - record_gcs_during_no_gc(); + record_gcs_during_no_gc(); - if (settings.condemned_generation > 1) - settings.promotion = TRUE; + if (settings.condemned_generation > 1) + settings.promotion = TRUE; #ifdef HEAP_ANALYZE - // At this point we've decided what generation is condemned - // See if we've been requested to analyze survivors after the mark phase - if (AnalyzeSurvivorsRequested(settings.condemned_generation)) - { - heap_analyze_enabled = TRUE; - } -#endif // HEAP_ANALYZE - -#ifdef GC_PROFILING - - // If we're tracking GCs, then we need to walk the first generation - // before collection to track how many items of each class has been - // allocated. - UpdateGenerationBounds(); - GarbageCollectionStartedCallback(settings.condemned_generation, settings.reason == reason_induced); + // At this point we've decided what generation is condemned + // See if we've been requested to analyze survivors after the mark phase + if (AnalyzeSurvivorsRequested(settings.condemned_generation)) { - BEGIN_PIN_PROFILER(CORProfilerTrackGC()); - size_t profiling_context = 0; - -#ifdef MULTIPLE_HEAPS - int hn = 0; - for (hn = 0; hn < gc_heap::n_heaps; hn++) - { - gc_heap* hp = gc_heap::g_heaps [hn]; - - // When we're walking objects allocated by class, then we don't want to walk the large - // object heap because then it would count things that may have been around for a while. - hp->walk_heap (&AllocByClassHelper, (void *)&profiling_context, 0, FALSE); - } -#else - // When we're walking objects allocated by class, then we don't want to walk the large - // object heap because then it would count things that may have been around for a while. - gc_heap::walk_heap (&AllocByClassHelper, (void *)&profiling_context, 0, FALSE); -#endif //MULTIPLE_HEAPS - - // Notify that we've reached the end of the Gen 0 scan - g_profControlBlock.pProfInterface->EndAllocByClass(&profiling_context); - END_PIN_PROFILER(); + heap_analyze_enabled = TRUE; } +#endif // HEAP_ANALYZE -#endif // GC_PROFILING + GCToEEInterface::DiagGCStart(settings.condemned_generation, settings.reason == reason_induced); #ifdef BACKGROUND_GC if ((settings.condemned_generation == max_generation) && (recursive_gc_sync::background_running_p())) { - //TODO BACKGROUND_GC If we just wait for the end of gc, it won't woork + //TODO BACKGROUND_GC If we just wait for the end of gc, it won't work // because we have to collect 0 and 1 properly // in particular, the allocation contexts are gone. // For now, it is simpler to collect max_generation-1 @@ -19625,12 +19627,7 @@ void gc_heap::mark_phase (int condemned_gen_number, BOOL mark_only_p) dprintf (3, ("Finalize marking")); finalize_queue->ScanForFinalization (GCHeap::Promote, condemned_gen_number, mark_only_p, __this); -#ifdef GC_PROFILING - if (CORProfilerTrackGC()) - { - finalize_queue->WalkFReachableObjects (__this); - } -#endif //GC_PROFILING + GCToEEInterface::DiagWalkFReachableObjects(__this); #endif // FEATURE_PREMORTEM_FINALIZATION // Scan dependent handles again to promote any secondaries associated with primaries that were promoted @@ -21105,8 +21102,7 @@ void gc_heap::relocate_in_loh_compact() generation_free_obj_space (gen))); } -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) -void gc_heap::walk_relocation_loh (size_t profiling_context) +void gc_heap::walk_relocation_for_loh (size_t profiling_context, record_surv_fn fn) { generation* gen = large_object_generation; heap_segment* seg = heap_segment_rw (generation_start_segment (gen)); @@ -21136,14 +21132,7 @@ void gc_heap::walk_relocation_loh (size_t profiling_context) STRESS_LOG_PLUG_MOVE(o, (o + size), -reloc); - { - ETW::GCLog::MovedReference( - o, - (o + size), - reloc, - profiling_context, - settings.compaction); - } + fn (o, (o + size), reloc, profiling_context, settings.compaction, FALSE); o = o + size; if (o < heap_segment_allocated (seg)) @@ -21160,7 +21149,6 @@ void gc_heap::walk_relocation_loh (size_t profiling_context) } } } -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) BOOL gc_heap::loh_object_p (uint8_t* o) { @@ -22250,7 +22238,7 @@ void gc_heap::plan_phase (int condemned_gen_number) #endif //TIME_GC // We may update write barrier code. We assume here EE has been suspended if we are on a GC thread. - assert(GCHeap::IsGCInProgress()); + assert(IsGCInProgress()); BOOL should_expand = FALSE; BOOL should_compact= FALSE; @@ -22318,10 +22306,7 @@ void gc_heap::plan_phase (int condemned_gen_number) if (!loh_compacted_p) #endif //FEATURE_LOH_COMPACTION { -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - if (ShouldTrackMovementForProfilerOrEtw()) - notify_profiler_of_surviving_large_objects(); -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) + GCToEEInterface::DiagWalkLOHSurvivors(__this); sweep_large_objects(); } } @@ -22432,7 +22417,7 @@ void gc_heap::plan_phase (int condemned_gen_number) for (i = 0; i < n_heaps; i++) { //copy the card and brick tables - if (g_card_table!= g_heaps[i]->card_table) + if (g_gc_card_table!= g_heaps[i]->card_table) { g_heaps[i]->copy_brick_card_table(); } @@ -22523,12 +22508,7 @@ void gc_heap::plan_phase (int condemned_gen_number) assert (generation_allocation_segment (consing_gen) == ephemeral_heap_segment); -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - if (ShouldTrackMovementForProfilerOrEtw()) - { - record_survived_for_profiler(condemned_gen_number, first_condemned_address); - } -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) + GCToEEInterface::DiagWalkSurvivors(__this); relocate_phase (condemned_gen_number, first_condemned_address); compact_phase (condemned_gen_number, first_condemned_address, @@ -22738,12 +22718,7 @@ void gc_heap::plan_phase (int condemned_gen_number) fix_older_allocation_area (older_gen); } -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - if (ShouldTrackMovementForProfilerOrEtw()) - { - record_survived_for_profiler(condemned_gen_number, first_condemned_address); - } -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) + GCToEEInterface::DiagWalkSurvivors(__this); gen0_big_free_spaces = 0; make_free_lists (condemned_gen_number); @@ -23949,8 +23924,7 @@ void gc_heap::relocate_survivors (int condemned_gen_number, } } -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) -void gc_heap::walk_plug (uint8_t* plug, size_t size, BOOL check_last_object_p, walk_relocate_args* args, size_t profiling_context) +void gc_heap::walk_plug (uint8_t* plug, size_t size, BOOL check_last_object_p, walk_relocate_args* args) { if (check_last_object_p) { @@ -23970,15 +23944,10 @@ void gc_heap::walk_plug (uint8_t* plug, size_t size, BOOL check_last_object_p, w } ptrdiff_t last_plug_relocation = node_relocation_distance (plug); - ptrdiff_t reloc = settings.compaction ? last_plug_relocation : 0; - STRESS_LOG_PLUG_MOVE(plug, (plug + size), -last_plug_relocation); + ptrdiff_t reloc = settings.compaction ? last_plug_relocation : 0; - ETW::GCLog::MovedReference(plug, - (plug + size), - reloc, - profiling_context, - settings.compaction); + (args->fn) (plug, (plug + size), reloc, args->profiling_context, settings.compaction, FALSE); if (check_last_object_p) { @@ -23995,12 +23964,12 @@ void gc_heap::walk_plug (uint8_t* plug, size_t size, BOOL check_last_object_p, w } } -void gc_heap::walk_relocation_in_brick (uint8_t* tree, walk_relocate_args* args, size_t profiling_context) +void gc_heap::walk_relocation_in_brick (uint8_t* tree, walk_relocate_args* args) { assert ((tree != NULL)); if (node_left_child (tree)) { - walk_relocation_in_brick (tree + node_left_child (tree), args, profiling_context); + walk_relocation_in_brick (tree + node_left_child (tree), args); } uint8_t* plug = tree; @@ -24029,7 +23998,7 @@ void gc_heap::walk_relocation_in_brick (uint8_t* tree, walk_relocate_args* args, assert (last_plug_size >= Align (min_obj_size)); } - walk_plug (args->last_plug, last_plug_size, check_last_object_p, args, profiling_context); + walk_plug (args->last_plug, last_plug_size, check_last_object_p, args); } else { @@ -24042,18 +24011,14 @@ void gc_heap::walk_relocation_in_brick (uint8_t* tree, walk_relocate_args* args, if (node_right_child (tree)) { - walk_relocation_in_brick (tree + node_right_child (tree), args, profiling_context); - + walk_relocation_in_brick (tree + node_right_child (tree), args); } } -void gc_heap::walk_relocation (int condemned_gen_number, - uint8_t* first_condemned_address, - size_t profiling_context) - +void gc_heap::walk_relocation (size_t profiling_context, record_surv_fn fn) { - generation* condemned_gen = generation_of (condemned_gen_number); - uint8_t* start_address = first_condemned_address; + generation* condemned_gen = generation_of (settings.condemned_generation); + uint8_t* start_address = generation_allocation_start (condemned_gen); size_t current_brick = brick_of (start_address); heap_segment* current_heap_segment = heap_segment_rw (generation_start_segment (condemned_gen)); @@ -24066,6 +24031,8 @@ void gc_heap::walk_relocation (int condemned_gen_number, args.is_shortened = FALSE; args.pinned_plug_entry = 0; args.last_plug = 0; + args.profiling_context = profiling_context; + args.fn = fn; while (1) { @@ -24075,8 +24042,8 @@ void gc_heap::walk_relocation (int condemned_gen_number, { walk_plug (args.last_plug, (heap_segment_allocated (current_heap_segment) - args.last_plug), - args.is_shortened, - &args, profiling_context); + args.is_shortened, + &args); args.last_plug = 0; } if (heap_segment_next_rw (current_heap_segment)) @@ -24097,16 +24064,29 @@ void gc_heap::walk_relocation (int condemned_gen_number, { walk_relocation_in_brick (brick_address (current_brick) + brick_entry - 1, - &args, - profiling_context); + &args); } } current_brick++; } } +void gc_heap::walk_survivors (record_surv_fn fn, size_t context, walk_surv_type type) +{ + if (type == walk_for_gc) + walk_survivors_relocation (context, fn); +#if defined(BACKGROUND_GC) && defined(FEATURE_EVENT_TRACE) + else if (type == walk_for_bgc) + walk_survivors_for_bgc (context, fn); +#endif //BACKGROUND_GC && FEATURE_EVENT_TRACE + else if (type == walk_for_loh) + walk_survivors_for_loh (context, fn); + else + assert (!"unknown type!"); +} + #if defined(BACKGROUND_GC) && defined(FEATURE_EVENT_TRACE) -void gc_heap::walk_relocation_for_bgc(size_t profiling_context) +void gc_heap::walk_survivors_for_bgc (size_t profiling_context, record_surv_fn fn) { // This should only be called for BGCs assert(settings.concurrent); @@ -24140,8 +24120,7 @@ void gc_heap::walk_relocation_for_bgc(size_t profiling_context) uint8_t* end = heap_segment_allocated (seg); while (o < end) - { - + { if (method_table(o) == g_pFreeObjectMethodTable) { o += Align (size (o), align_const); @@ -24164,51 +24143,18 @@ void gc_heap::walk_relocation_for_bgc(size_t profiling_context) uint8_t* plug_end = o; - // Note on last parameter: since this is for bgc, only ETW - // should be sending these events so that existing profapi profilers - // don't get confused. - ETW::GCLog::MovedReference( - plug_start, + fn (plug_start, plug_end, 0, // Reloc distance == 0 as this is non-compacting profiling_context, FALSE, // Non-compacting - FALSE); // fAllowProfApiNotification + TRUE); // BGC } seg = heap_segment_next (seg); } } - -void gc_heap::make_free_lists_for_profiler_for_bgc () -{ - assert(settings.concurrent); - - size_t profiling_context = 0; - ETW::GCLog::BeginMovedReferences(&profiling_context); - - // This provides the profiler with information on what blocks of - // memory are moved during a gc. - - walk_relocation_for_bgc(profiling_context); - - // Notify the EE-side profiling code that all the references have been traced for - // this heap, and that it needs to flush all cached data it hasn't sent to the - // profiler and release resources it no longer needs. Since this is for bgc, only - // ETW should be sending these events so that existing profapi profilers don't get confused. - ETW::GCLog::EndMovedReferences(profiling_context, FALSE /* fAllowProfApiNotification */); - -#ifdef MULTIPLE_HEAPS - bgc_t_join.join(this, gc_join_after_profiler_heap_walk); - if (bgc_t_join.joined()) - { - bgc_t_join.restart(); - } -#endif // MULTIPLE_HEAPS -} - #endif // defined(BACKGROUND_GC) && defined(FEATURE_EVENT_TRACE) -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) void gc_heap::relocate_phase (int condemned_gen_number, uint8_t* first_condemned_address) @@ -24809,7 +24755,7 @@ void gc_heap::compact_phase (int condemned_gen_number, #pragma warning(push) #pragma warning(disable:4702) // C4702: unreachable code: gc_thread_function may not return #endif //_MSC_VER -void __stdcall gc_heap::gc_thread_stub (void* arg) +void gc_heap::gc_thread_stub (void* arg) { ClrFlsSetThreadType (ThreadType_GC); STRESS_LOG_RESERVE_MEM (GC_STRESSLOG_MULTIPLY); @@ -25177,14 +25123,14 @@ BOOL gc_heap::commit_mark_array_new_seg (gc_heap* hp, if (new_card_table == 0) { - new_card_table = g_card_table; + new_card_table = g_gc_card_table; } if (hp->card_table != new_card_table) { if (new_lowest_address == 0) { - new_lowest_address = g_lowest_address; + new_lowest_address = g_gc_lowest_address; } uint32_t* ct = &new_card_table[card_word (gcard_of (new_lowest_address))]; @@ -26046,9 +25992,9 @@ gc_heap::suspend_EE () dprintf (2, ("suspend_EE")); #ifdef MULTIPLE_HEAPS gc_heap* hp = gc_heap::g_heaps[0]; - GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_FOR_GC_PREP); + GCToEEInterface::SuspendEE(SUSPEND_FOR_GC_PREP); #else - GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_FOR_GC_PREP); + GCToEEInterface::SuspendEE(SUSPEND_FOR_GC_PREP); #endif //MULTIPLE_HEAPS } @@ -26062,7 +26008,7 @@ gc_heap::bgc_suspend_EE () } gc_started = TRUE; dprintf (2, ("bgc_suspend_EE")); - GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_FOR_GC_PREP); + GCToEEInterface::SuspendEE(SUSPEND_FOR_GC_PREP); gc_started = FALSE; for (int i = 0; i < n_heaps; i++) @@ -26077,7 +26023,7 @@ gc_heap::bgc_suspend_EE () reset_gc_done(); gc_started = TRUE; dprintf (2, ("bgc_suspend_EE")); - GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_FOR_GC_PREP); + GCToEEInterface::SuspendEE(SUSPEND_FOR_GC_PREP); gc_started = FALSE; set_gc_done(); } @@ -29174,7 +29120,7 @@ generation* gc_heap::expand_heap (int condemned_generation, return consing_gen; //copy the card and brick tables - if (g_card_table!= card_table) + if (g_gc_card_table!= card_table) copy_brick_card_table(); BOOL new_segment_p = (heap_segment_next (new_seg) == 0); @@ -30469,7 +30415,7 @@ CObjectHeader* gc_heap::allocate_large_object (size_t jsize, int64_t& alloc_byte acontext.alloc_limit = 0; acontext.alloc_bytes = 0; #ifdef MULTIPLE_HEAPS - acontext.alloc_heap = vm_heap; + acontext.set_alloc_heap(vm_heap); #endif //MULTIPLE_HEAPS #ifdef MARK_ARRAY @@ -30484,14 +30430,11 @@ CObjectHeader* gc_heap::allocate_large_object (size_t jsize, int64_t& alloc_byte #endif //BACKGROUND_GC #endif // MARK_ARRAY + #if BIT64 + size_t maxObjectSize = (INT64_MAX - 7 - Align(min_obj_size)); + #else size_t maxObjectSize = (INT32_MAX - 7 - Align(min_obj_size)); - -#ifdef BIT64 - if (g_pConfig->GetGCAllowVeryLargeObjects()) - { - maxObjectSize = (INT64_MAX - 7 - Align(min_obj_size)); - } -#endif + #endif if (jsize >= maxObjectSize) { @@ -30499,12 +30442,7 @@ CObjectHeader* gc_heap::allocate_large_object (size_t jsize, int64_t& alloc_byte { GCToOSInterface::DebugBreak(); } - -#ifndef FEATURE_REDHAWK - ThrowOutOfMemoryDimensionsExceeded(); -#else - return 0; -#endif + return NULL; } size_t size = AlignQword (jsize); @@ -30627,35 +30565,21 @@ BOOL gc_heap::large_object_marked (uint8_t* o, BOOL clearp) return m; } -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) -void gc_heap::record_survived_for_profiler(int condemned_gen_number, uint8_t * start_address) +void gc_heap::walk_survivors_relocation (size_t profiling_context, record_surv_fn fn) { - size_t profiling_context = 0; - - ETW::GCLog::BeginMovedReferences(&profiling_context); - // Now walk the portion of memory that is actually being relocated. - walk_relocation(condemned_gen_number, start_address, profiling_context); + walk_relocation (profiling_context, fn); #ifdef FEATURE_LOH_COMPACTION if (loh_compacted_p) { - walk_relocation_loh (profiling_context); + walk_relocation_for_loh (profiling_context, fn); } #endif //FEATURE_LOH_COMPACTION - - // Notify the EE-side profiling code that all the references have been traced for - // this heap, and that it needs to flush all cached data it hasn't sent to the - // profiler and release resources it no longer needs. - ETW::GCLog::EndMovedReferences(profiling_context); } -void gc_heap::notify_profiler_of_surviving_large_objects () +void gc_heap::walk_survivors_for_loh (size_t profiling_context, record_surv_fn fn) { - size_t profiling_context = 0; - - ETW::GCLog::BeginMovedReferences(&profiling_context); - generation* gen = large_object_generation; heap_segment* seg = heap_segment_rw (generation_start_segment (gen));; @@ -30665,13 +30589,6 @@ void gc_heap::notify_profiler_of_surviving_large_objects () uint8_t* plug_end = o; uint8_t* plug_start = o; - // Generally, we can only get here if this is TRUE: - // (CORProfilerTrackGC() || ETW::GCLog::ShouldTrackMovementForEtw()) - // But we can't always assert that, as races could theoretically cause GC profiling - // or ETW to turn off just before we get here. This is harmless (we do checks later - // on, under appropriate locks, before actually calling into profilers), though it's - // a slowdown to determine these plugs for nothing. - while (1) { if (o >= heap_segment_allocated (seg)) @@ -30699,12 +30616,7 @@ void gc_heap::notify_profiler_of_surviving_large_objects () plug_end = o; - ETW::GCLog::MovedReference( - plug_start, - plug_end, - 0, - profiling_context, - FALSE); + fn (plug_start, plug_end, 0, profiling_context, FALSE, FALSE); } else { @@ -30714,9 +30626,7 @@ void gc_heap::notify_profiler_of_surviving_large_objects () } } } - ETW::GCLog::EndMovedReferences(profiling_context); } -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) #ifdef BACKGROUND_GC @@ -31946,11 +31856,10 @@ void gc_heap::descr_card_table () #endif //TRACE_GC } -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) void gc_heap::descr_generations_to_profiler (gen_walk_fn fn, void *context) { #ifdef MULTIPLE_HEAPS - int n_heaps = GCHeap::GetGCHeap()->GetNumberOfHeaps (); + int n_heaps = g_theGCHeap->GetNumberOfHeaps (); for (int i = 0; i < n_heaps; i++) { gc_heap* hp = GCHeap::GetHeap(i)->pGenGCHeap; @@ -32027,7 +31936,6 @@ void gc_heap::descr_generations_to_profiler (gen_walk_fn fn, void *context) } } } -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) #ifdef TRACE_GC // Note that when logging is on it can take a long time to go through the free items. @@ -32522,7 +32430,7 @@ void gc_heap::clear_all_mark_array() void gc_heap::verify_mark_array_cleared (heap_segment* seg) { #if defined (VERIFY_HEAP) && defined (MARK_ARRAY) - assert (card_table == g_card_table); + assert (card_table == g_gc_card_table); size_t markw = mark_word_of (heap_segment_mem (seg)); size_t markw_end = mark_word_of (heap_segment_reserved (seg)); @@ -32870,8 +32778,8 @@ gc_heap::verify_heap (BOOL begin_gc_p) #endif //BACKGROUND_GC #ifndef MULTIPLE_HEAPS - if ((g_ephemeral_low != generation_allocation_start (generation_of (max_generation - 1))) || - (g_ephemeral_high != heap_segment_reserved (ephemeral_heap_segment))) + if ((g_gc_ephemeral_low != generation_allocation_start (generation_of (max_generation - 1))) || + (g_gc_ephemeral_high != heap_segment_reserved (ephemeral_heap_segment))) { FATAL_GC_ERROR(); } @@ -32930,7 +32838,7 @@ gc_heap::verify_heap (BOOL begin_gc_p) for (int i = 0; i < n_heaps; i++) { //copy the card and brick tables - if (g_card_table != g_heaps[i]->card_table) + if (g_gc_card_table != g_heaps[i]->card_table) { g_heaps[i]->copy_brick_card_table(); } @@ -32939,7 +32847,7 @@ gc_heap::verify_heap (BOOL begin_gc_p) current_join->restart(); } #else - if (g_card_table != card_table) + if (g_gc_card_table != card_table) copy_brick_card_table(); #endif //MULTIPLE_HEAPS @@ -33306,8 +33214,12 @@ gc_heap::verify_heap (BOOL begin_gc_p) #endif //BACKGROUND_GC } +#endif //VERIFY_HEAP + + void GCHeap::ValidateObjectMember (Object* obj) { +#ifdef VERIFY_HEAP size_t s = size (obj); uint8_t* o = (uint8_t*)obj; @@ -33325,9 +33237,8 @@ void GCHeap::ValidateObjectMember (Object* obj) } } } ); - +#endif // VERIFY_HEAP } -#endif //VERIFY_HEAP void DestructObject (CObjectHeader* hdr) { @@ -33361,11 +33272,11 @@ HRESULT GCHeap::Shutdown () //CloseHandle (WaitForGCEvent); //find out if the global card table hasn't been used yet - uint32_t* ct = &g_card_table[card_word (gcard_of (g_lowest_address))]; + uint32_t* ct = &g_gc_card_table[card_word (gcard_of (g_gc_lowest_address))]; if (card_table_refcount (ct) == 0) { destroy_card_table (ct); - g_card_table = 0; + g_gc_card_table = 0; #ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP SoftwareWriteWatch::StaticClose(); #endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP @@ -33525,7 +33436,7 @@ HRESULT GCHeap::Initialize () return E_FAIL; } - StompWriteBarrierResize(true, false); + stomp_write_barrier_initialize(); #ifndef FEATURE_REDHAWK // Redhawk forces relocation a different way #if defined (STRESS_HEAP) && !defined (MULTIPLE_HEAPS) @@ -33562,10 +33473,7 @@ HRESULT GCHeap::Initialize () { GCScan::GcRuntimeStructuresValid (TRUE); -#ifdef GC_PROFILING - if (CORProfilerTrackGC()) - UpdateGenerationBounds(); -#endif // GC_PROFILING + GCToEEInterface::DiagUpdateGenerationBounds(); } return hr; @@ -33640,16 +33548,16 @@ BOOL GCHeap::IsEphemeral (Object* object) return hp->ephemeral_pointer_p (o); } -#ifdef VERIFY_HEAP // Return NULL if can't find next object. When EE is not suspended, // the result is not accurate: if the input arg is in gen0, the function could // return zeroed out memory as next object Object * GCHeap::NextObj (Object * object) { +#ifdef VERIFY_HEAP uint8_t* o = (uint8_t*)object; #ifndef FEATURE_BASICFREEZE - if (!((o < g_highest_address) && (o >= g_lowest_address))) + if (!((o < g_gc_highest_address) && (o >= g_gc_lowest_address))) { return NULL; } @@ -33687,8 +33595,13 @@ Object * GCHeap::NextObj (Object * object) } return (Object *)nextobj; +#else + return nullptr; +#endif // VERIFY_HEAP } +#ifdef VERIFY_HEAP + #ifdef FEATURE_BASICFREEZE BOOL GCHeap::IsInFrozenSegment (Object * object) { @@ -33715,7 +33628,7 @@ BOOL GCHeap::IsHeapPointer (void* vpObject, BOOL small_heap_only) uint8_t* object = (uint8_t*) vpObject; #ifndef FEATURE_BASICFREEZE - if (!((object < g_highest_address) && (object >= g_lowest_address))) + if (!((object < g_gc_highest_address) && (object >= g_gc_lowest_address))) return FALSE; #endif //!FEATURE_BASICFREEZE @@ -33918,11 +33831,16 @@ int StressRNG(int iMaxValue) int randValue = (((lHoldrand = lHoldrand * 214013L + 2531011L) >> 16) & 0x7fff); return randValue % iMaxValue; } +#endif // STRESS_HEAP +#endif // !FEATURE_REDHAWK // free up object so that things will move and then do a GC //return TRUE if GC actually happens, otherwise FALSE -BOOL GCHeap::StressHeap(alloc_context * acontext) +BOOL GCHeap::StressHeap(gc_alloc_context * context) { +#if defined(STRESS_HEAP) && !defined(FEATURE_REDHAWK) + alloc_context* acontext = static_cast(context); + // if GC stress was dynamically disabled during this run we return FALSE if (!GCStressPolicy::IsEnabled()) return FALSE; @@ -34102,11 +34020,12 @@ BOOL GCHeap::StressHeap(alloc_context * acontext) } return TRUE; +#else + UNREFERENCED_PARAMETER(context); + return FALSE; +#endif // defined(STRESS_HEAP) && !defined(FEATURE_REDHAWK) } -#endif // STRESS_HEAP -#endif // FEATURE_REDHAWK - #ifdef FEATURE_PREMORTEM_FINALIZATION #define REGISTER_FOR_FINALIZATION(_object, _size) \ @@ -34115,7 +34034,6 @@ BOOL GCHeap::StressHeap(alloc_context * acontext) #define REGISTER_FOR_FINALIZATION(_object, _size) true #endif // FEATURE_PREMORTEM_FINALIZATION -#ifdef FEATURE_REDHAWK #define CHECK_ALLOC_AND_POSSIBLY_REGISTER_FOR_FINALIZATION(_object, _size, _register) do { \ if ((_object) == NULL || ((_register) && !REGISTER_FOR_FINALIZATION(_object, _size))) \ { \ @@ -34123,19 +34041,6 @@ BOOL GCHeap::StressHeap(alloc_context * acontext) return NULL; \ } \ } while (false) -#else // FEATURE_REDHAWK -#define CHECK_ALLOC_AND_POSSIBLY_REGISTER_FOR_FINALIZATION(_object, _size, _register) do { \ - if ((_object) == NULL) \ - { \ - STRESS_LOG_OOM_STACK(_size); \ - ThrowOutOfMemory(); \ - } \ - if (_register) \ - { \ - REGISTER_FOR_FINALIZATION(_object, _size); \ - } \ -} while (false) -#endif // FEATURE_REDHAWK // // Small Object Allocator @@ -34145,27 +34050,12 @@ Object * GCHeap::Alloc( size_t size, uint32_t flags REQD_ALIGN_DCL) { CONTRACTL { -#ifdef FEATURE_REDHAWK - // Under Redhawk NULL is returned on failure. NOTHROW; -#else - THROWS; -#endif GC_TRIGGERS; } CONTRACTL_END; -#if defined(_DEBUG) && !defined(FEATURE_REDHAWK) - if (g_pConfig->ShouldInjectFault(INJECTFAULT_GCHEAP)) - { - char *a = new char; - delete a; - } -#endif //_DEBUG && !FEATURE_REDHAWK - TRIGGERSGC(); - assert (!GCHeap::UseAllocationContexts()); - Object* newAlloc = NULL; #ifdef TRACE_GC @@ -34237,23 +34127,16 @@ GCHeap::Alloc( size_t size, uint32_t flags REQD_ALIGN_DCL) return newAlloc; } -#ifdef FEATURE_64BIT_ALIGNMENT // Allocate small object with an alignment requirement of 8-bytes. Non allocation context version. Object * GCHeap::AllocAlign8( size_t size, uint32_t flags) { +#ifdef FEATURE_64BIT_ALIGNMENT CONTRACTL { -#ifdef FEATURE_REDHAWK - // Under Redhawk NULL is returned on failure. NOTHROW; -#else - THROWS; -#endif GC_TRIGGERS; } CONTRACTL_END; - assert (!GCHeap::UseAllocationContexts()); - Object* newAlloc = NULL; { @@ -34270,61 +34153,60 @@ GCHeap::AllocAlign8( size_t size, uint32_t flags) } return newAlloc; +#else + UNREFERENCED_PARAMETER(size); + UNREFERENCED_PARAMETER(flags); + assert(!"should not call GCHeap::AllocAlign8 without FEATURE_64BIT_ALIGNMENT defined!"); + return nullptr; +#endif //FEATURE_64BIT_ALIGNMENT } // Allocate small object with an alignment requirement of 8-bytes. Allocation context version. Object* -GCHeap::AllocAlign8(alloc_context* acontext, size_t size, uint32_t flags ) +GCHeap::AllocAlign8(gc_alloc_context* ctx, size_t size, uint32_t flags ) { +#ifdef FEATURE_64BIT_ALIGNMENT CONTRACTL { -#ifdef FEATURE_REDHAWK - // Under Redhawk NULL is returned on failure. NOTHROW; -#else - THROWS; -#endif GC_TRIGGERS; } CONTRACTL_END; + alloc_context* acontext = static_cast(ctx); + #ifdef MULTIPLE_HEAPS - if (acontext->alloc_heap == 0) + if (acontext->get_alloc_heap() == 0) { AssignHeap (acontext); - assert (acontext->alloc_heap); + assert (acontext->get_alloc_heap()); } - gc_heap* hp = acontext->alloc_heap->pGenGCHeap; + gc_heap* hp = acontext->get_alloc_heap()->pGenGCHeap; #else gc_heap* hp = pGenGCHeap; #endif //MULTIPLE_HEAPS return AllocAlign8Common(hp, acontext, size, flags); +#else + UNREFERENCED_PARAMETER(ctx); + UNREFERENCED_PARAMETER(size); + UNREFERENCED_PARAMETER(flags); + assert(!"should not call GCHeap::AllocAlign8 without FEATURE_64BIT_ALIGNMENT defined!"); + return nullptr; +#endif //FEATURE_64BIT_ALIGNMENT } // Common code used by both variants of AllocAlign8 above. Object* GCHeap::AllocAlign8Common(void* _hp, alloc_context* acontext, size_t size, uint32_t flags) { +#ifdef FEATURE_64BIT_ALIGNMENT CONTRACTL { -#ifdef FEATURE_REDHAWK - // Under Redhawk NULL is returned on failure. NOTHROW; -#else - THROWS; -#endif GC_TRIGGERS; } CONTRACTL_END; gc_heap* hp = (gc_heap*)_hp; -#if defined(_DEBUG) && !defined(FEATURE_REDHAWK) - if (g_pConfig->ShouldInjectFault(INJECTFAULT_GCHEAP)) - { - char *a = new char; - delete a; - } -#endif //_DEBUG && !FEATURE_REDHAWK - TRIGGERSGC(); Object* newAlloc = NULL; @@ -34424,30 +34306,24 @@ GCHeap::AllocAlign8Common(void* _hp, alloc_context* acontext, size_t size, uint3 AllocCount++; #endif //TRACE_GC return newAlloc; -} +#else + UNREFERENCED_PARAMETER(_hp); + UNREFERENCED_PARAMETER(acontext); + UNREFERENCED_PARAMETER(size); + UNREFERENCED_PARAMETER(flags); + assert(!"Should not call GCHeap::AllocAlign8Common without FEATURE_64BIT_ALIGNMENT defined!"); + return nullptr; #endif // FEATURE_64BIT_ALIGNMENT +} Object * GCHeap::AllocLHeap( size_t size, uint32_t flags REQD_ALIGN_DCL) { CONTRACTL { -#ifdef FEATURE_REDHAWK - // Under Redhawk NULL is returned on failure. NOTHROW; -#else - THROWS; -#endif GC_TRIGGERS; } CONTRACTL_END; -#if defined(_DEBUG) && !defined(FEATURE_REDHAWK) - if (g_pConfig->ShouldInjectFault(INJECTFAULT_GCHEAP)) - { - char *a = new char; - delete a; - } -#endif //_DEBUG && !FEATURE_REDHAWK - TRIGGERSGC(); Object* newAlloc = NULL; @@ -34499,29 +34375,17 @@ GCHeap::AllocLHeap( size_t size, uint32_t flags REQD_ALIGN_DCL) } Object* -GCHeap::Alloc(alloc_context* acontext, size_t size, uint32_t flags REQD_ALIGN_DCL) +GCHeap::Alloc(gc_alloc_context* context, size_t size, uint32_t flags REQD_ALIGN_DCL) { CONTRACTL { -#ifdef FEATURE_REDHAWK - // Under Redhawk NULL is returned on failure. NOTHROW; -#else - THROWS; -#endif GC_TRIGGERS; } CONTRACTL_END; -#if defined(_DEBUG) && !defined(FEATURE_REDHAWK) - if (g_pConfig->ShouldInjectFault(INJECTFAULT_GCHEAP)) - { - char *a = new char; - delete a; - } -#endif //_DEBUG && !FEATURE_REDHAWK - TRIGGERSGC(); Object* newAlloc = NULL; + alloc_context* acontext = static_cast(context); #ifdef TRACE_GC #ifdef COUNT_CYCLES @@ -34534,10 +34398,10 @@ GCHeap::Alloc(alloc_context* acontext, size_t size, uint32_t flags REQD_ALIGN_DC #endif //TRACE_GC #ifdef MULTIPLE_HEAPS - if (acontext->alloc_heap == 0) + if (acontext->get_alloc_heap() == 0) { AssignHeap (acontext); - assert (acontext->alloc_heap); + assert (acontext->get_alloc_heap()); } #endif //MULTIPLE_HEAPS @@ -34546,7 +34410,7 @@ GCHeap::Alloc(alloc_context* acontext, size_t size, uint32_t flags REQD_ALIGN_DC #endif // FEATURE_REDHAWK #ifdef MULTIPLE_HEAPS - gc_heap* hp = acontext->alloc_heap->pGenGCHeap; + gc_heap* hp = acontext->get_alloc_heap()->pGenGCHeap; #else gc_heap* hp = pGenGCHeap; #ifdef _PREFAST_ @@ -34591,8 +34455,9 @@ GCHeap::Alloc(alloc_context* acontext, size_t size, uint32_t flags REQD_ALIGN_DC } void -GCHeap::FixAllocContext (alloc_context* acontext, BOOL lockp, void* arg, void *heap) +GCHeap::FixAllocContext (gc_alloc_context* context, BOOL lockp, void* arg, void *heap) { + alloc_context* acontext = static_cast(context); #ifdef MULTIPLE_HEAPS if (arg != 0) @@ -35017,7 +34882,6 @@ void gc_heap::do_post_gc() { if (!settings.concurrent) { - GCProfileWalkHeap(); initGCShadow(); } @@ -35037,13 +34901,10 @@ void gc_heap::do_post_gc() GCToEEInterface::GcDone(settings.condemned_generation); -#ifdef GC_PROFILING - if (!settings.concurrent) - { - UpdateGenerationBounds(); - GarbageCollectionFinishedCallback(); - } -#endif // GC_PROFILING + GCToEEInterface::DiagGCEnd(VolatileLoad(&settings.gc_index), + (uint32_t)settings.condemned_generation, + (uint32_t)settings.reason, + !!settings.concurrent); //dprintf (1, (" ****end of Garbage Collection**** %d(gen0:%d)(%d)", dprintf (1, ("*EGC* %d(gen0:%d)(%d)(%s)", @@ -35168,7 +35029,7 @@ GCHeap::GarbageCollectGeneration (unsigned int gen, gc_reason reason) dprintf (2, ("Suspending EE")); BEGIN_TIMING(suspend_ee_during_log); - GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_FOR_GC); + GCToEEInterface::SuspendEE(SUSPEND_FOR_GC); END_TIMING(suspend_ee_during_log); gc_heap::proceed_with_gc_p = gc_heap::should_proceed_with_gc(); gc_heap::disable_preemptive (current_thread, cooperative_mode); @@ -35383,8 +35244,8 @@ size_t GCHeap::ApproxTotalBytesInUse(BOOL small_heap_only) void GCHeap::AssignHeap (alloc_context* acontext) { // Assign heap based on processor - acontext->alloc_heap = GetHeap(heap_select::select_heap(acontext, 0)); - acontext->home_heap = acontext->alloc_heap; + acontext->set_alloc_heap(GetHeap(heap_select::select_heap(acontext, 0))); + acontext->set_home_heap(acontext->get_alloc_heap()); } GCHeap* GCHeap::GetHeap (int n) { @@ -35393,11 +35254,12 @@ GCHeap* GCHeap::GetHeap (int n) } #endif //MULTIPLE_HEAPS -bool GCHeap::IsThreadUsingAllocationContextHeap(alloc_context* acontext, int thread_number) +bool GCHeap::IsThreadUsingAllocationContextHeap(gc_alloc_context* context, int thread_number) { + alloc_context* acontext = static_cast(context); #ifdef MULTIPLE_HEAPS - return ((acontext->home_heap == GetHeap(thread_number)) || - ((acontext->home_heap == 0) && (thread_number == 0))); + return ((acontext->get_home_heap() == GetHeap(thread_number)) || + ((acontext->get_home_heap() == 0) && (thread_number == 0))); #else UNREFERENCED_PARAMETER(acontext); UNREFERENCED_PARAMETER(thread_number); @@ -35427,7 +35289,8 @@ int GCHeap::GetHomeHeapNumber () { if (pThread) { - GCHeap *hp = GCToEEInterface::GetAllocContext(pThread)->home_heap; + gc_alloc_context* ctx = GCToEEInterface::GetAllocContext(pThread); + GCHeap *hp = static_cast(ctx)->get_home_heap(); if (hp == gc_heap::g_heaps[i]->vm_heap) return i; } } @@ -35639,7 +35502,7 @@ size_t GCHeap::GetValidGen0MaxSize(size_t seg_size) { size_t gen0size = g_pConfig->GetGCgen0size(); - if ((gen0size == 0) || !GCHeap::IsValidGen0MaxSize(gen0size)) + if ((gen0size == 0) || !g_theGCHeap->IsValidGen0MaxSize(gen0size)) { #ifdef SERVER_GC // performance data seems to indicate halving the size results @@ -35869,19 +35732,19 @@ GCHeap::SetCardsAfterBulkCopy( Object **StartPoint, size_t len ) #ifdef BACKGROUND_GC (!gc_heap::settings.concurrent) && #endif //BACKGROUND_GC - (GCHeap::GetGCHeap()->WhichGeneration( (Object*) StartPoint ) == 0)) + (g_theGCHeap->WhichGeneration( (Object*) StartPoint ) == 0)) return; rover = StartPoint; end = StartPoint + (len/sizeof(Object*)); while (rover < end) { - if ( (((uint8_t*)*rover) >= g_ephemeral_low) && (((uint8_t*)*rover) < g_ephemeral_high) ) + if ( (((uint8_t*)*rover) >= g_gc_ephemeral_low) && (((uint8_t*)*rover) < g_gc_ephemeral_high) ) { // Set Bit For Card and advance to next card size_t card = gcard_of ((uint8_t*)rover); - Interlocked::Or (&g_card_table[card/card_word_width], (1U << (card % card_word_width))); + Interlocked::Or (&g_gc_card_table[card/card_word_width], (1U << (card % card_word_width))); // Skip to next card for the object rover = (Object**)align_on_card ((uint8_t*)(rover+1)); } @@ -36000,12 +35863,7 @@ bool CFinalize::RegisterForFinalization (int gen, Object* obj, size_t size) { CONTRACTL { -#ifdef FEATURE_REDHAWK - // Under Redhawk false is returned on failure. NOTHROW; -#else - THROWS; -#endif GC_NOTRIGGER; } CONTRACTL_END; @@ -36043,11 +35901,7 @@ CFinalize::RegisterForFinalization (int gen, Object* obj, size_t size) { GCToOSInterface::DebugBreak(); } -#ifdef FEATURE_REDHAWK return false; -#else - ThrowOutOfMemory(); -#endif } } Object*** end_si = &SegQueueLimit (dest); @@ -36333,21 +36187,17 @@ CFinalize::GcScanRoots (promote_func* fn, int hn, ScanContext *pSC) } } -#ifdef GC_PROFILING -void CFinalize::WalkFReachableObjects (gc_heap* hp) +void CFinalize::WalkFReachableObjects (fq_walk_fn fn) { - BEGIN_PIN_PROFILER(CORProfilerPresent()); Object** startIndex = SegQueue (CriticalFinalizerListSeg); Object** stopCriticalIndex = SegQueueLimit (CriticalFinalizerListSeg); Object** stopIndex = SegQueueLimit (FinalizerListSeg); for (Object** po = startIndex; po < stopIndex; po++) { //report *po - g_profControlBlock.pProfInterface->FinalizeableObjectQueued(po < stopCriticalIndex, (ObjectID)*po); + fn(po < stopCriticalIndex, *po); } - END_PIN_PROFILER(); } -#endif //GC_PROFILING BOOL CFinalize::ScanForFinalization (promote_func* pfn, int gen, BOOL mark_only_p, @@ -36374,7 +36224,7 @@ CFinalize::ScanForFinalization (promote_func* pfn, int gen, BOOL mark_only_p, { CObjectHeader* obj = (CObjectHeader*)*i; dprintf (3, ("scanning: %Ix", (size_t)obj)); - if (!GCHeap::GetGCHeap()->IsPromoted (obj)) + if (!g_theGCHeap->IsPromoted (obj)) { dprintf (3, ("freacheable: %Ix", (size_t)obj)); @@ -36507,7 +36357,7 @@ CFinalize::UpdatePromotedGenerations (int gen, BOOL gen_0_empty_p) for (Object** po = startIndex; po < SegQueueLimit (gen_segment(i)); po++) { - int new_gen = GCHeap::GetGCHeap()->WhichGeneration (*po); + int new_gen = g_theGCHeap->WhichGeneration (*po); if (new_gen != i) { if (new_gen > i) @@ -36567,7 +36417,7 @@ void CFinalize::CheckFinalizerObjects() for (Object **po = startIndex; po < stopIndex; po++) { - if ((int)GCHeap::GetGCHeap()->WhichGeneration (*po) < i) + if ((int)g_theGCHeap->WhichGeneration (*po) < i) FATAL_GC_ERROR (); ((CObjectHeader*)*po)->Validate(); } @@ -36583,8 +36433,7 @@ void CFinalize::CheckFinalizerObjects() // End of VM specific support // //------------------------------------------------------------------------------ - -void gc_heap::walk_heap (walk_fn fn, void* context, int gen_number, BOOL walk_large_object_heap_p) +void gc_heap::walk_heap_per_heap (walk_fn fn, void* context, int gen_number, BOOL walk_large_object_heap_p) { generation* gen = gc_heap::generation_of (gen_number); heap_segment* seg = generation_start_segment (gen); @@ -36640,8 +36489,28 @@ void gc_heap::walk_heap (walk_fn fn, void* context, int gen_number, BOOL walk_la } } -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) -void GCHeap::WalkObject (Object* obj, walk_fn fn, void* context) +void gc_heap::walk_finalize_queue (fq_walk_fn fn) +{ +#ifdef FEATURE_PREMORTEM_FINALIZATION + finalize_queue->WalkFReachableObjects (fn); +#endif //FEATURE_PREMORTEM_FINALIZATION +} + +void gc_heap::walk_heap (walk_fn fn, void* context, int gen_number, BOOL walk_large_object_heap_p) +{ +#ifdef MULTIPLE_HEAPS + for (int hn = 0; hn < gc_heap::n_heaps; hn++) + { + gc_heap* hp = gc_heap::g_heaps [hn]; + + hp->walk_heap_per_heap (fn, context, gen_number, walk_large_object_heap_p); + } +#else + walk_heap_per_heap(fn, context, gen_number, walk_large_object_heap_p); +#endif //MULTIPLE_HEAPS +} + +void GCHeap::DiagWalkObject (Object* obj, walk_fn fn, void* context) { uint8_t* o = (uint8_t*)obj; if (o) @@ -36658,7 +36527,46 @@ void GCHeap::WalkObject (Object* obj, walk_fn fn, void* context) ); } } -#endif //defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) + +void GCHeap::DiagWalkSurvivorsWithType (void* gc_context, record_surv_fn fn, size_t diag_context, walk_surv_type type) +{ + gc_heap* hp = (gc_heap*)gc_context; + hp->walk_survivors (fn, diag_context, type); +} + +void GCHeap::DiagWalkHeap (walk_fn fn, void* context, int gen_number, BOOL walk_large_object_heap_p) +{ + gc_heap::walk_heap (fn, context, gen_number, walk_large_object_heap_p); +} + +void GCHeap::DiagWalkFinalizeQueue (void* gc_context, fq_walk_fn fn) +{ + gc_heap* hp = (gc_heap*)gc_context; + hp->walk_finalize_queue (fn); +} + +void GCHeap::DiagScanFinalizeQueue (fq_scan_fn fn, ScanContext* sc) +{ +#ifdef MULTIPLE_HEAPS + for (int hn = 0; hn < gc_heap::n_heaps; hn++) + { + gc_heap* hp = gc_heap::g_heaps [hn]; + hp->finalize_queue->GcScanRoots(fn, hn, sc); + } +#else + pGenGCHeap->finalize_queue->GcScanRoots(fn, 0, sc); +#endif //MULTIPLE_HEAPS +} + +void GCHeap::DiagScanHandles (handle_scan_fn fn, int gen_number, ScanContext* context) +{ + GCScan::GcScanHandlesForProfilerAndETW (max_generation, context, fn); +} + +void GCHeap::DiagScanDependentHandles (handle_scan_fn fn, int gen_number, ScanContext* context) +{ + GCScan::GcScanDependentHandlesForProfilerAndETW (max_generation, context, fn); +} // Go through and touch (read) each page straddled by a memory block. void TouchPages(void * pStart, size_t cb) @@ -36704,11 +36612,11 @@ void initGCShadow() if (!(g_pConfig->GetHeapVerifyLevel() & EEConfig::HEAPVERIFY_BARRIERCHECK)) return; - size_t len = g_highest_address - g_lowest_address; + size_t len = g_gc_highest_address - g_gc_lowest_address; if (len > (size_t)(g_GCShadowEnd - g_GCShadow)) { deleteGCShadow(); - g_GCShadowEnd = g_GCShadow = (uint8_t *)GCToOSInterface::VirtualReserve(0, len, 0, VirtualReserveFlags::None); + g_GCShadowEnd = g_GCShadow = (uint8_t *)GCToOSInterface::VirtualReserve(len, 0, VirtualReserveFlags::None); if (g_GCShadow == NULL || !GCToOSInterface::VirtualCommit(g_GCShadow, len)) { _ASSERTE(!"Not enough memory to run HeapVerify level 2"); @@ -36723,10 +36631,10 @@ void initGCShadow() g_GCShadowEnd += len; } - // save the value of g_lowest_address at this time. If this value changes before + // save the value of g_gc_lowest_address at this time. If this value changes before // the next call to checkGCWriteBarrier() it means we extended the heap (with a // large object segment most probably), and the whole shadow segment is inconsistent. - g_shadow_lowest_address = g_lowest_address; + g_shadow_lowest_address = g_gc_lowest_address; //****** Copy the whole GC heap ****** // @@ -36736,7 +36644,7 @@ void initGCShadow() generation* gen = gc_heap::generation_of (max_generation); heap_segment* seg = heap_segment_rw (generation_start_segment (gen)); - ptrdiff_t delta = g_GCShadow - g_lowest_address; + ptrdiff_t delta = g_GCShadow - g_gc_lowest_address; BOOL small_object_segments = TRUE; while(1) { @@ -36764,7 +36672,7 @@ void initGCShadow() // test to see if 'ptr' was only updated via the write barrier. inline void testGCShadow(Object** ptr) { - Object** shadow = (Object**) &g_GCShadow[((uint8_t*) ptr - g_lowest_address)]; + Object** shadow = (Object**) &g_GCShadow[((uint8_t*) ptr - g_gc_lowest_address)]; if (*ptr != 0 && (uint8_t*) shadow < g_GCShadowEnd && *ptr != *shadow) { @@ -36823,9 +36731,9 @@ void testGCShadowHelper (uint8_t* x) // Walk the whole heap, looking for pointers that were not updated with the write barrier. void checkGCWriteBarrier() { - // g_shadow_lowest_address != g_lowest_address means the GC heap was extended by a segment + // g_shadow_lowest_address != g_gc_lowest_address means the GC heap was extended by a segment // and the GC shadow segment did not track that change! - if (g_GCShadowEnd <= g_GCShadow || g_shadow_lowest_address != g_lowest_address) + if (g_GCShadowEnd <= g_GCShadow || g_shadow_lowest_address != g_gc_lowest_address) { // No shadow stack, nothing to check. return; diff --git a/src/gc/gc.h b/src/gc/gc.h index 14c6bae..b7f1e95 100644 --- a/src/gc/gc.h +++ b/src/gc/gc.h @@ -14,9 +14,24 @@ Module Name: #ifndef __GC_H #define __GC_H -#ifdef PROFILING_SUPPORTED -#define GC_PROFILING //Turn on profiling -#endif // PROFILING_SUPPORTED +#ifdef Sleep +// This is a funny workaround for the fact that "common.h" defines Sleep to be +// Dont_Use_Sleep, with the hope of causing linker errors whenever someone tries to use sleep. +// +// However, GCToOSInterface defines a function called Sleep, which (due to this define) becomes +// "Dont_Use_Sleep", which the GC in turn happily uses. The symbol that GCToOSInterface actually +// exported was called "GCToOSInterface::Dont_Use_Sleep". While we progress in making the GC standalone, +// we'll need to break the dependency on common.h (the VM header) and this problem will become moot. +#undef Sleep +#endif // Sleep + +#include "gcinterface.h" +#include "env/gcenv.os.h" +#include "env/gcenv.ee.h" + +#ifdef FEATURE_STANDALONE_GC +#include "gcenv.ee.standalone.inl" +#endif // FEATURE_STANDALONE_GC /* * Promotion Function Prototypes @@ -26,19 +41,6 @@ typedef void enum_func (Object*); // callback functions for heap walkers typedef void object_callback_func(void * pvContext, void * pvDataLoc); -// stub type to abstract a heap segment -struct gc_heap_segment_stub; -typedef gc_heap_segment_stub *segment_handle; - -struct segment_info -{ - void * pvMem; // base of the allocation, not the first object (must add ibFirstObject) - size_t ibFirstObject; // offset to the base of the first object in the segment - size_t ibAllocated; // limit of allocated memory in the segment (>= firstobject) - size_t ibCommit; // limit of committed memory in the segment (>= alllocated) - size_t ibReserved; // limit of reserved memory in the segment (>= commit) -}; - /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ /* If you modify failure_get_memory and */ /* oom_reason be sure to make the corresponding */ @@ -80,6 +82,24 @@ enum oom_reason oom_unproductive_full_gc = 6 }; +// TODO : it would be easier to make this an ORed value +enum gc_reason +{ + reason_alloc_soh = 0, + reason_induced = 1, + reason_lowmemory = 2, + reason_empty = 3, + reason_alloc_loh = 4, + reason_oos_soh = 5, + reason_oos_loh = 6, + reason_induced_noforce = 7, // it's an induced GC and doesn't have to be blocking. + reason_gcstress = 8, // this turns into reason_induced & gc_mechanisms.stress_induced = true + reason_lowmemory_blocking = 9, + reason_induced_compacting = 10, + reason_lowmemory_host = 11, + reason_max +}; + struct oom_history { oom_reason reason; @@ -97,28 +117,16 @@ struct oom_history class CObjectHeader; class Object; -class GCHeap; +class IGCHeapInternal; /* misc defines */ #define LARGE_OBJECT_SIZE ((size_t)(85000)) -GPTR_DECL(GCHeap, g_pGCHeap); - #ifdef GC_CONFIG_DRIVEN #define MAX_GLOBAL_GC_MECHANISMS_COUNT 6 GARY_DECL(size_t, gc_global_mechanisms, MAX_GLOBAL_GC_MECHANISMS_COUNT); #endif //GC_CONFIG_DRIVEN -#ifndef DACCESS_COMPILE -extern "C" { -#endif -GPTR_DECL(uint8_t,g_lowest_address); -GPTR_DECL(uint8_t,g_highest_address); -GPTR_DECL(uint32_t,g_card_table); -#ifndef DACCESS_COMPILE -} -#endif - #ifdef DACCESS_COMPILE class DacHeapWalker; #endif @@ -127,137 +135,28 @@ class DacHeapWalker; #define _LOGALLOC #endif -#ifdef WRITE_BARRIER_CHECK -//always defined, but should be 0 in Server GC -extern uint8_t* g_GCShadow; -extern uint8_t* g_GCShadowEnd; -// saves the g_lowest_address in between GCs to verify the consistency of the shadow segment -extern uint8_t* g_shadow_lowest_address; -#endif - #define MP_LOCKS -extern "C" uint8_t* g_ephemeral_low; -extern "C" uint8_t* g_ephemeral_high; +extern "C" uint32_t* g_gc_card_table; +extern "C" uint8_t* g_gc_lowest_address; +extern "C" uint8_t* g_gc_highest_address; +extern "C" uint8_t* g_gc_ephemeral_low; +extern "C" uint8_t* g_gc_ephemeral_high; namespace WKS { - ::GCHeap* CreateGCHeap(); + ::IGCHeapInternal* CreateGCHeap(); class GCHeap; class gc_heap; } #if defined(FEATURE_SVR_GC) namespace SVR { - ::GCHeap* CreateGCHeap(); + ::IGCHeapInternal* CreateGCHeap(); class GCHeap; class gc_heap; } #endif // defined(FEATURE_SVR_GC) -/* - * Ephemeral Garbage Collected Heap Interface - */ - - -struct alloc_context -{ - friend class WKS::gc_heap; -#if defined(FEATURE_SVR_GC) - friend class SVR::gc_heap; - friend class SVR::GCHeap; -#endif // defined(FEATURE_SVR_GC) - friend struct ClassDumpInfo; - - uint8_t* alloc_ptr; - uint8_t* alloc_limit; - int64_t alloc_bytes; //Number of bytes allocated on SOH by this context - int64_t alloc_bytes_loh; //Number of bytes allocated on LOH by this context -#if defined(FEATURE_SVR_GC) - SVR::GCHeap* alloc_heap; - SVR::GCHeap* home_heap; -#endif // defined(FEATURE_SVR_GC) - int alloc_count; -public: - - void init() - { - LIMITED_METHOD_CONTRACT; - - alloc_ptr = 0; - alloc_limit = 0; - alloc_bytes = 0; - alloc_bytes_loh = 0; -#if defined(FEATURE_SVR_GC) - alloc_heap = 0; - home_heap = 0; -#endif // defined(FEATURE_SVR_GC) - alloc_count = 0; - } -}; - -struct ScanContext -{ - Thread* thread_under_crawl; - int thread_number; - uintptr_t stack_limit; // Lowest point on the thread stack that the scanning logic is permitted to read - BOOL promotion; //TRUE: Promotion, FALSE: Relocation. - BOOL concurrent; //TRUE: concurrent scanning -#if CHECK_APP_DOMAIN_LEAKS || defined (FEATURE_APPDOMAIN_RESOURCE_MONITORING) || defined (DACCESS_COMPILE) - AppDomain *pCurrentDomain; -#endif //CHECK_APP_DOMAIN_LEAKS || FEATURE_APPDOMAIN_RESOURCE_MONITORING || DACCESS_COMPILE - -#ifndef FEATURE_REDHAWK -#if defined(GC_PROFILING) || defined (DACCESS_COMPILE) - MethodDesc *pMD; -#endif //GC_PROFILING || DACCESS_COMPILE -#endif // FEATURE_REDHAWK -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - EtwGCRootKind dwEtwRootKind; -#endif // GC_PROFILING || FEATURE_EVENT_TRACE - - ScanContext() - { - LIMITED_METHOD_CONTRACT; - - thread_under_crawl = 0; - thread_number = -1; - stack_limit = 0; - promotion = FALSE; - concurrent = FALSE; -#ifdef GC_PROFILING - pMD = NULL; -#endif //GC_PROFILING -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - dwEtwRootKind = kEtwGCRootKindOther; -#endif // GC_PROFILING || FEATURE_EVENT_TRACE - } -}; - -typedef BOOL (* walk_fn)(Object*, void*); -typedef void (* gen_walk_fn)(void *context, int generation, uint8_t *range_start, uint8_t * range_end, uint8_t *range_reserved); - -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) -struct ProfilingScanContext : ScanContext -{ - BOOL fProfilerPinned; - void * pvEtwContext; - void *pHeapId; - - ProfilingScanContext(BOOL fProfilerPinnedParam) : ScanContext() - { - LIMITED_METHOD_CONTRACT; - - pHeapId = NULL; - fProfilerPinned = fProfilerPinnedParam; - pvEtwContext = NULL; -#ifdef FEATURE_CONSERVATIVE_GC - // To not confuse GCScan::GcScanRoots - promotion = g_pConfig->GetGCConservative(); -#endif - } -}; -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - #ifdef STRESS_HEAP #define IN_STRESS_HEAP(x) x #define STRESS_HEAP_ARG(x) ,x @@ -266,7 +165,6 @@ struct ProfilingScanContext : ScanContext #define STRESS_HEAP_ARG(x) #endif // STRESS_HEAP - //dynamic data interface struct gc_counters { @@ -275,51 +173,6 @@ struct gc_counters size_t collection_count; }; -// !!!!!!!!!!!!!!!!!!!!!!! -// make sure you change the def in bcl\system\gc.cs -// if you change this! -enum collection_mode -{ - collection_non_blocking = 0x00000001, - collection_blocking = 0x00000002, - collection_optimized = 0x00000004, - collection_compacting = 0x00000008 -#ifdef STRESS_HEAP - , collection_gcstress = 0x80000000 -#endif // STRESS_HEAP -}; - -// !!!!!!!!!!!!!!!!!!!!!!! -// make sure you change the def in bcl\system\gc.cs -// if you change this! -enum wait_full_gc_status -{ - wait_full_gc_success = 0, - wait_full_gc_failed = 1, - wait_full_gc_cancelled = 2, - wait_full_gc_timeout = 3, - wait_full_gc_na = 4 -}; - -// !!!!!!!!!!!!!!!!!!!!!!! -// make sure you change the def in bcl\system\gc.cs -// if you change this! -enum start_no_gc_region_status -{ - start_no_gc_success = 0, - start_no_gc_no_memory = 1, - start_no_gc_too_large = 2, - start_no_gc_in_progress = 3 -}; - -enum end_no_gc_region_status -{ - end_no_gc_success = 0, - end_no_gc_not_in_progress = 1, - end_no_gc_induced = 2, - end_no_gc_alloc_exceeded = 3 -}; - enum bgc_state { bgc_not_in_process = 0, @@ -352,321 +205,82 @@ void record_changed_seg (uint8_t* start, uint8_t* end, void record_global_mechanism (int mech_index); #endif //GC_CONFIG_DRIVEN -//constants for the flags parameter to the gc call back - -#define GC_CALL_INTERIOR 0x1 -#define GC_CALL_PINNED 0x2 -#define GC_CALL_CHECK_APP_DOMAIN 0x4 - -//flags for GCHeap::Alloc(...) -#define GC_ALLOC_FINALIZE 0x1 -#define GC_ALLOC_CONTAINS_REF 0x2 -#define GC_ALLOC_ALIGN8_BIAS 0x4 -#define GC_ALLOC_ALIGN8 0x8 - -class GCHeap { - friend struct ::_DacGlobals; -#ifdef DACCESS_COMPILE - friend class ClrDataAccess; -#endif - -public: - - virtual ~GCHeap() {} - - static GCHeap *GetGCHeap() +struct alloc_context : gc_alloc_context +{ +#ifdef FEATURE_SVR_GC + inline SVR::GCHeap* get_alloc_heap() { - LIMITED_METHOD_CONTRACT; - - _ASSERTE(g_pGCHeap != NULL); - return g_pGCHeap; + return static_cast(gc_reserved_1); } -#ifndef DACCESS_COMPILE - static BOOL IsGCInProgress(BOOL bConsiderGCStart = FALSE) + inline void set_alloc_heap(SVR::GCHeap* heap) { - WRAPPER_NO_CONTRACT; - - return (IsGCHeapInitialized() ? GetGCHeap()->IsGCInProgressHelper(bConsiderGCStart) : false); - } -#endif - - static BOOL IsGCHeapInitialized() - { - LIMITED_METHOD_CONTRACT; - - return (g_pGCHeap != NULL); + gc_reserved_1 = heap; } - static void WaitForGCCompletion(BOOL bConsiderGCStart = FALSE) + inline SVR::GCHeap* get_home_heap() { - WRAPPER_NO_CONTRACT; - - if (IsGCHeapInitialized()) - GetGCHeap()->WaitUntilGCComplete(bConsiderGCStart); - } - - // The runtime needs to know whether we're using workstation or server GC - // long before the GCHeap is created. So IsServerHeap cannot be a virtual - // method on GCHeap. Instead we make it a static method and initialize - // gcHeapType before any of the calls to IsServerHeap. Note that this also - // has the advantage of getting the answer without an indirection - // (virtual call), which is important for perf critical codepaths. - - #ifndef DACCESS_COMPILE - static void InitializeHeapType(bool bServerHeap) - { - LIMITED_METHOD_CONTRACT; -#ifdef FEATURE_SVR_GC - gcHeapType = bServerHeap ? GC_HEAP_SVR : GC_HEAP_WKS; -#ifdef WRITE_BARRIER_CHECK - if (gcHeapType == GC_HEAP_SVR) - { - g_GCShadow = 0; - g_GCShadowEnd = 0; - } -#endif -#else // FEATURE_SVR_GC - UNREFERENCED_PARAMETER(bServerHeap); - CONSISTENCY_CHECK(bServerHeap == false); -#endif // FEATURE_SVR_GC - } - #endif - - static BOOL IsValidSegmentSize(size_t cbSize) - { - //Must be aligned on a Mb and greater than 4Mb - return (((cbSize & (1024*1024-1)) ==0) && (cbSize >> 22)); + return static_cast(gc_reserved_2); } - static BOOL IsValidGen0MaxSize(size_t cbSize) + inline void set_home_heap(SVR::GCHeap* heap) { - return (cbSize >= 64*1024); + gc_reserved_2 = heap; } - - inline static bool IsServerHeap() - { - LIMITED_METHOD_CONTRACT; -#ifdef FEATURE_SVR_GC - _ASSERTE(gcHeapType != GC_HEAP_INVALID); - return (gcHeapType == GC_HEAP_SVR); -#else // FEATURE_SVR_GC - return false; #endif // FEATURE_SVR_GC - } +}; - inline static bool UseAllocationContexts() - { - WRAPPER_NO_CONTRACT; -#ifdef FEATURE_REDHAWK - // SIMPLIFY: only use allocation contexts - return true; -#else -#if defined(_TARGET_ARM_) || defined(FEATURE_PAL) - return true; -#else - return ((IsServerHeap() ? true : (g_SystemInfo.dwNumberOfProcessors >= 2))); +class IGCHeapInternal : public IGCHeap { + friend struct ::_DacGlobals; +#ifdef DACCESS_COMPILE + friend class ClrDataAccess; #endif -#endif - } - - inline static bool MarkShouldCompeteForStatics() - { - WRAPPER_NO_CONTRACT; - - return IsServerHeap() && g_SystemInfo.dwNumberOfProcessors >= 2; - } -#ifndef DACCESS_COMPILE - static GCHeap * CreateGCHeap() - { - WRAPPER_NO_CONTRACT; - - GCHeap * pGCHeap; - -#if defined(FEATURE_SVR_GC) - pGCHeap = (IsServerHeap() ? SVR::CreateGCHeap() : WKS::CreateGCHeap()); -#else - pGCHeap = WKS::CreateGCHeap(); -#endif // defined(FEATURE_SVR_GC) - - g_pGCHeap = pGCHeap; - return pGCHeap; - } -#endif // DACCESS_COMPILE +public: -private: - typedef enum - { - GC_HEAP_INVALID = 0, - GC_HEAP_WKS = 1, - GC_HEAP_SVR = 2 - } GC_HEAP_TYPE; - -#ifdef FEATURE_SVR_GC - SVAL_DECL(uint32_t,gcHeapType); -#endif // FEATURE_SVR_GC + virtual ~IGCHeapInternal() {} -public: - // TODO Synchronization, should be moved out - virtual BOOL IsGCInProgressHelper (BOOL bConsiderGCStart = FALSE) = 0; - virtual uint32_t WaitUntilGCComplete (BOOL bConsiderGCStart = FALSE) = 0; - virtual void SetGCInProgress(BOOL fInProgress) = 0; - virtual CLREventStatic * GetWaitForGCEvent() = 0; - - virtual void SetFinalizationRun (Object* obj) = 0; - virtual Object* GetNextFinalizable() = 0; - virtual size_t GetNumberOfFinalizable() = 0; - - virtual void SetFinalizeQueueForShutdown(BOOL fHasLock) = 0; - virtual BOOL FinalizeAppDomain(AppDomain *pDomain, BOOL fRunFinalizers) = 0; - virtual BOOL ShouldRestartFinalizerWatchDog() = 0; - - //wait for concurrent GC to finish - virtual void WaitUntilConcurrentGCComplete () = 0; // Use in managed threads -#ifndef DACCESS_COMPILE - virtual HRESULT WaitUntilConcurrentGCCompleteAsync(int millisecondsTimeout) = 0; // Use in native threads. TRUE if succeed. FALSE if failed or timeout -#endif - virtual BOOL IsConcurrentGCInProgress() = 0; - - // Enable/disable concurrent GC - virtual void TemporaryEnableConcurrentGC() = 0; - virtual void TemporaryDisableConcurrentGC() = 0; - virtual BOOL IsConcurrentGCEnabled() = 0; - - virtual void FixAllocContext (alloc_context* acontext, BOOL lockp, void* arg, void *heap) = 0; - virtual Object* Alloc (alloc_context* acontext, size_t size, uint32_t flags) = 0; - - // This is safe to call only when EE is suspended. - virtual Object* GetContainingObject(void *pInteriorPtr) = 0; - - // TODO Should be folded into constructor - virtual HRESULT Initialize () = 0; - - virtual HRESULT GarbageCollect (int generation = -1, BOOL low_memory_p=FALSE, int mode = collection_blocking) = 0; - virtual Object* Alloc (size_t size, uint32_t flags) = 0; -#ifdef FEATURE_64BIT_ALIGNMENT - virtual Object* AllocAlign8 (size_t size, uint32_t flags) = 0; - virtual Object* AllocAlign8 (alloc_context* acontext, size_t size, uint32_t flags) = 0; private: - virtual Object* AllocAlign8Common (void* hp, alloc_context* acontext, size_t size, uint32_t flags) = 0; + virtual Object* AllocAlign8Common (void* hp, alloc_context* acontext, size_t size, uint32_t flags) = 0; public: -#endif // FEATURE_64BIT_ALIGNMENT - virtual Object* AllocLHeap (size_t size, uint32_t flags) = 0; - virtual void SetReservedVMLimit (size_t vmlimit) = 0; - virtual void SetCardsAfterBulkCopy( Object**, size_t ) = 0; -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - virtual void WalkObject (Object* obj, walk_fn fn, void* context) = 0; -#endif //defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - - virtual bool IsThreadUsingAllocationContextHeap(alloc_context* acontext, int thread_number) = 0; virtual int GetNumberOfHeaps () = 0; virtual int GetHomeHeapNumber () = 0; - - virtual int CollectionCount (int generation, int get_bgc_fgc_count = 0) = 0; - - // Finalizer queue stuff (should stay) - virtual bool RegisterForFinalization (int gen, Object* obj) = 0; - - // General queries to the GC - virtual BOOL IsPromoted (Object *object) = 0; - virtual unsigned WhichGeneration (Object* object) = 0; - virtual BOOL IsEphemeral (Object* object) = 0; - virtual BOOL IsHeapPointer (void* object, BOOL small_heap_only = FALSE) = 0; - - virtual unsigned GetCondemnedGeneration() = 0; - virtual int GetGcLatencyMode() = 0; - virtual int SetGcLatencyMode(int newLatencyMode) = 0; - - virtual int GetLOHCompactionMode() = 0; - virtual void SetLOHCompactionMode(int newLOHCompactionyMode) = 0; - - virtual BOOL RegisterForFullGCNotification(uint32_t gen2Percentage, - uint32_t lohPercentage) = 0; - virtual BOOL CancelFullGCNotification() = 0; - virtual int WaitForFullGCApproach(int millisecondsTimeout) = 0; - virtual int WaitForFullGCComplete(int millisecondsTimeout) = 0; - - virtual int StartNoGCRegion(uint64_t totalSize, BOOL lohSizeKnown, uint64_t lohSize, BOOL disallowFullBlockingGC) = 0; - virtual int EndNoGCRegion() = 0; + virtual size_t GetPromotedBytes(int heap_index) = 0; - virtual BOOL IsObjectInFixedHeap(Object *pObj) = 0; - virtual size_t GetTotalBytesInUse () = 0; - virtual size_t GetCurrentObjSize() = 0; - virtual size_t GetLastGCStartTime(int generation) = 0; - virtual size_t GetLastGCDuration(int generation) = 0; - virtual size_t GetNow() = 0; - virtual unsigned GetGcCount() = 0; - virtual void TraceGCSegments() = 0; + unsigned GetMaxGeneration() + { + return IGCHeap::maxGeneration; + } - virtual void PublishObject(uint8_t* obj) = 0; + BOOL IsValidSegmentSize(size_t cbSize) + { + //Must be aligned on a Mb and greater than 4Mb + return (((cbSize & (1024*1024-1)) ==0) && (cbSize >> 22)); + } - // static if since restricting for all heaps is fine - virtual size_t GetValidSegmentSize(BOOL large_seg = FALSE) = 0; + BOOL IsValidGen0MaxSize(size_t cbSize) + { + return (cbSize >= 64*1024); + } - static BOOL IsLargeObject(MethodTable *mt) { + BOOL IsLargeObject(MethodTable *mt) + { WRAPPER_NO_CONTRACT; return mt->GetBaseSize() >= LARGE_OBJECT_SIZE; } - static unsigned GetMaxGeneration() { - LIMITED_METHOD_DAC_CONTRACT; - return max_generation; - } - - virtual size_t GetPromotedBytes(int heap_index) = 0; - -private: - enum { - max_generation = 2, - }; - -public: - -#ifdef FEATURE_BASICFREEZE - // frozen segment management functions - virtual segment_handle RegisterFrozenSegment(segment_info *pseginfo) = 0; - virtual void UnregisterFrozenSegment(segment_handle seg) = 0; -#endif //FEATURE_BASICFREEZE - - // debug support -#ifndef FEATURE_REDHAWK // Redhawk forces relocation a different way -#ifdef STRESS_HEAP - //return TRUE if GC actually happens, otherwise FALSE - virtual BOOL StressHeap(alloc_context * acontext = 0) = 0; -#endif -#endif // FEATURE_REDHAWK -#ifdef VERIFY_HEAP - virtual void ValidateObjectMember (Object *obj) = 0; -#endif - -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - virtual void DescrGenerationsToProfiler (gen_walk_fn fn, void *context) = 0; -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - protected: -#ifdef VERIFY_HEAP public: - // Return NULL if can't find next object. When EE is not suspended, - // the result is not accurate: if the input arg is in gen0, the function could - // return zeroed out memory as next object - virtual Object * NextObj (Object * object) = 0; -#ifdef FEATURE_BASICFREEZE +#if defined(FEATURE_BASICFREEZE) && defined(VERIFY_HEAP) // Return TRUE if object lives in frozen segment virtual BOOL IsInFrozenSegment (Object * object) = 0; -#endif //FEATURE_BASICFREEZE -#endif //VERIFY_HEAP +#endif // defined(FEATURE_BASICFREEZE) && defined(VERIFY_HEAP) }; -extern VOLATILE(int32_t) m_GCLock; - // Go through and touch (read) each page straddled by a memory block. void TouchPages(void * pStart, size_t cb); -// For low memory notification from host -extern int32_t g_bLowMemoryFromHost; - #ifdef WRITE_BARRIER_CHECK void updateGCShadow(Object** ptr, Object* val); #endif @@ -677,4 +291,27 @@ extern MethodTable *pWeakReferenceMT; extern MethodTable *pWeakReferenceOfTCanonMT; extern void FinalizeWeakReference(Object * obj); +// The single GC heap instance, shared with the VM. +extern IGCHeapInternal* g_theGCHeap; + +#ifndef DACCESS_COMPILE +inline BOOL IsGCInProgress(bool bConsiderGCStart = FALSE) +{ + WRAPPER_NO_CONTRACT; + + return g_theGCHeap != nullptr ? g_theGCHeap->IsGCInProgressHelper(bConsiderGCStart) : false; +} +#endif // DACCESS_COMPILE + +inline BOOL IsServerHeap() +{ + LIMITED_METHOD_CONTRACT; +#ifdef FEATURE_SVR_GC + _ASSERTE(IGCHeap::gcHeapType != IGCHeap::GC_HEAP_INVALID); + return (IGCHeap::gcHeapType == IGCHeap::GC_HEAP_SVR); +#else // FEATURE_SVR_GC + return false; +#endif // FEATURE_SVR_GC +} + #endif // __GC_H diff --git a/src/gc/gccommon.cpp b/src/gc/gccommon.cpp index 779aac7..d1ccddd 100644 --- a/src/gc/gccommon.cpp +++ b/src/gc/gccommon.cpp @@ -15,17 +15,16 @@ #include "gc.h" #ifdef FEATURE_SVR_GC -SVAL_IMPL_INIT(uint32_t,GCHeap,gcHeapType,GCHeap::GC_HEAP_INVALID); +SVAL_IMPL_INIT(uint32_t,IGCHeap,gcHeapType,IGCHeap::GC_HEAP_INVALID); #endif // FEATURE_SVR_GC -GPTR_IMPL(GCHeap,g_pGCHeap); +SVAL_IMPL_INIT(uint32_t,IGCHeap,maxGeneration,2); -/* global versions of the card table and brick table */ -GPTR_IMPL(uint32_t,g_card_table); +IGCHeapInternal* g_theGCHeap; -/* absolute bounds of the GC memory */ -GPTR_IMPL_INIT(uint8_t,g_lowest_address,0); -GPTR_IMPL_INIT(uint8_t,g_highest_address,0); +#ifdef FEATURE_STANDALONE_GC +IGCToCLR* g_theGCToCLR; +#endif // FEATURE_STANDALONE_GC #ifdef GC_CONFIG_DRIVEN GARY_IMPL(size_t, gc_global_mechanisms, MAX_GLOBAL_GC_MECHANISMS_COUNT); @@ -33,15 +32,18 @@ GARY_IMPL(size_t, gc_global_mechanisms, MAX_GLOBAL_GC_MECHANISMS_COUNT); #ifndef DACCESS_COMPILE -uint8_t* g_ephemeral_low = (uint8_t*)1; -uint8_t* g_ephemeral_high = (uint8_t*)~0; - #ifdef WRITE_BARRIER_CHECK uint8_t* g_GCShadow; uint8_t* g_GCShadowEnd; uint8_t* g_shadow_lowest_address = NULL; #endif +uint32_t* g_gc_card_table; +uint8_t* g_gc_lowest_address = 0; +uint8_t* g_gc_highest_address = 0; +uint8_t* g_gc_ephemeral_low = (uint8_t*)1; +uint8_t* g_gc_ephemeral_high = (uint8_t*)~0; + VOLATILE(int32_t) m_GCLock = -1; #ifdef GC_CONFIG_DRIVEN @@ -112,4 +114,49 @@ void record_changed_seg (uint8_t* start, uint8_t* end, } } +// The runtime needs to know whether we're using workstation or server GC +// long before the GCHeap is created. +void InitializeHeapType(bool bServerHeap) +{ + LIMITED_METHOD_CONTRACT; +#ifdef FEATURE_SVR_GC + IGCHeap::gcHeapType = bServerHeap ? IGCHeap::GC_HEAP_SVR : IGCHeap::GC_HEAP_WKS; +#ifdef WRITE_BARRIER_CHECK + if (IGCHeap::gcHeapType == IGCHeap::GC_HEAP_SVR) + { + g_GCShadow = 0; + g_GCShadowEnd = 0; + } +#endif // WRITE_BARRIER_CHECK +#else // FEATURE_SVR_GC + UNREFERENCED_PARAMETER(bServerHeap); + CONSISTENCY_CHECK(bServerHeap == false); +#endif // FEATURE_SVR_GC +} + +IGCHeap* InitializeGarbageCollector(IGCToCLR* clrToGC) +{ + LIMITED_METHOD_CONTRACT; + + IGCHeapInternal* heap; +#ifdef FEATURE_SVR_GC + assert(IGCHeap::gcHeapType != IGCHeap::GC_HEAP_INVALID); + heap = IGCHeap::gcHeapType == IGCHeap::GC_HEAP_SVR ? SVR::CreateGCHeap() : WKS::CreateGCHeap(); +#else + heap = WKS::CreateGCHeap(); +#endif + + g_theGCHeap = heap; + +#ifdef FEATURE_STANDALONE_GC + assert(clrToGC != nullptr); + g_theGCToCLR = clrToGC; +#else + UNREFERENCED_PARAMETER(clrToGC); + assert(clrToGC == nullptr); +#endif + + return heap; +} + #endif // !DACCESS_COMPILE diff --git a/src/gc/gcee.cpp b/src/gc/gcee.cpp index d37eaf4..c93cc91 100644 --- a/src/gc/gcee.cpp +++ b/src/gc/gcee.cpp @@ -148,7 +148,7 @@ void GCHeap::UpdatePostGCCounters() // if a max gen garbage collection was performed, resync the GC Handle counter; // if threads are currently suspended, we do not need to obtain a lock on each handle table if (condemned_gen == max_generation) - total_num_gc_handles = HndCountAllHandles(!GCHeap::IsGCInProgress()); + total_num_gc_handles = HndCountAllHandles(!IsGCInProgress()); #endif //FEATURE_REDHAWK // per generation calculation. @@ -381,209 +381,6 @@ size_t GCHeap::GetNow() return GetHighPrecisionTimeStamp(); } -void ProfScanRootsHelper(Object** ppObject, ScanContext *pSC, uint32_t dwFlags) -{ -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - Object *pObj = *ppObject; -#ifdef INTERIOR_POINTERS - if (dwFlags & GC_CALL_INTERIOR) - { - uint8_t *o = (uint8_t*)pObj; - gc_heap* hp = gc_heap::heap_of (o); - - if ((o < hp->gc_low) || (o >= hp->gc_high)) - { - return; - } - pObj = (Object*) hp->find_object(o, hp->gc_low); - } -#endif //INTERIOR_POINTERS - ScanRootsHelper(pObj, ppObject, pSC, dwFlags); -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) -} - -// TODO - at some point we would like to completely decouple profiling -// from ETW tracing using a pattern similar to this, where the -// ProfilingScanContext has flags about whether or not certain things -// should be tracked, and each one of these ProfilerShouldXYZ functions -// will check these flags and determine what to do based upon that. -// GCProfileWalkHeapWorker can, in turn, call those methods without fear -// of things being ifdef'd out. - -// Returns TRUE if GC profiling is enabled and the profiler -// should scan dependent handles, FALSE otherwise. -BOOL ProfilerShouldTrackConditionalWeakTableElements() -{ -#if defined(GC_PROFILING) - return CORProfilerTrackConditionalWeakTableElements(); -#else - return FALSE; -#endif // defined (GC_PROFILING) -} - -// If GC profiling is enabled, informs the profiler that we are done -// tracing dependent handles. -void ProfilerEndConditionalWeakTableElementReferences(void* heapId) -{ -#if defined (GC_PROFILING) - g_profControlBlock.pProfInterface->EndConditionalWeakTableElementReferences(heapId); -#else - UNREFERENCED_PARAMETER(heapId); -#endif // defined (GC_PROFILING) -} - -// If GC profiling is enabled, informs the profiler that we are done -// tracing root references. -void ProfilerEndRootReferences2(void* heapId) -{ -#if defined (GC_PROFILING) - g_profControlBlock.pProfInterface->EndRootReferences2(heapId); -#else - UNREFERENCED_PARAMETER(heapId); -#endif // defined (GC_PROFILING) -} - -// This is called only if we've determined that either: -// a) The Profiling API wants to do a walk of the heap, and it has pinned the -// profiler in place (so it cannot be detached), and it's thus safe to call into the -// profiler, OR -// b) ETW infrastructure wants to do a walk of the heap either to log roots, -// objects, or both. -// This can also be called to do a single walk for BOTH a) and b) simultaneously. Since -// ETW can ask for roots, but not objects -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - -void GCProfileWalkHeapWorker(BOOL fProfilerPinned, BOOL fShouldWalkHeapRootsForEtw, BOOL fShouldWalkHeapObjectsForEtw) -{ - { - ProfilingScanContext SC(fProfilerPinned); - - // **** Scan roots: Only scan roots if profiling API wants them or ETW wants them. - if (fProfilerPinned || fShouldWalkHeapRootsForEtw) - { -#ifdef MULTIPLE_HEAPS - int hn; - - // Must emulate each GC thread number so we can hit each - // heap for enumerating the roots. - for (hn = 0; hn < gc_heap::n_heaps; hn++) - { - // Ask the vm to go over all of the roots for this specific - // heap. - gc_heap* hp = gc_heap::g_heaps [hn]; - SC.thread_number = hn; - GCScan::GcScanRoots(&ProfScanRootsHelper, max_generation, max_generation, &SC); - - // The finalizer queue is also a source of roots - SC.dwEtwRootKind = kEtwGCRootKindFinalizer; - hp->finalize_queue->GcScanRoots(&ProfScanRootsHelper, hn, &SC); - } -#else - // Ask the vm to go over all of the roots - GCScan::GcScanRoots(&ProfScanRootsHelper, max_generation, max_generation, &SC); - - // The finalizer queue is also a source of roots - SC.dwEtwRootKind = kEtwGCRootKindFinalizer; - pGenGCHeap->finalize_queue->GcScanRoots(&ProfScanRootsHelper, 0, &SC); - -#endif // MULTIPLE_HEAPS - // Handles are kept independent of wks/svr/concurrent builds - SC.dwEtwRootKind = kEtwGCRootKindHandle; - GCScan::GcScanHandlesForProfilerAndETW(max_generation, &SC); - - // indicate that regular handle scanning is over, so we can flush the buffered roots - // to the profiler. (This is for profapi only. ETW will flush after the - // entire heap was is complete, via ETW::GCLog::EndHeapDump.) - if (fProfilerPinned) - { - ProfilerEndRootReferences2(&SC.pHeapId); - } - } - - // **** Scan dependent handles: only if the profiler supports it or ETW wants roots - if ((fProfilerPinned && ProfilerShouldTrackConditionalWeakTableElements()) || - fShouldWalkHeapRootsForEtw) - { - // GcScanDependentHandlesForProfiler double-checks - // CORProfilerTrackConditionalWeakTableElements() before calling into the profiler - - GCScan::GcScanDependentHandlesForProfilerAndETW(max_generation, &SC); - - // indicate that dependent handle scanning is over, so we can flush the buffered roots - // to the profiler. (This is for profapi only. ETW will flush after the - // entire heap was is complete, via ETW::GCLog::EndHeapDump.) - if (fProfilerPinned && ProfilerShouldTrackConditionalWeakTableElements()) - { - ProfilerEndConditionalWeakTableElementReferences(&SC.pHeapId); - } - } - - ProfilerWalkHeapContext profilerWalkHeapContext(fProfilerPinned, SC.pvEtwContext); - - // **** Walk objects on heap: only if profiling API wants them or ETW wants them. - if (fProfilerPinned || fShouldWalkHeapObjectsForEtw) - { -#ifdef MULTIPLE_HEAPS - int hn; - - // Walk the heap and provide the objref to the profiler - for (hn = 0; hn < gc_heap::n_heaps; hn++) - { - gc_heap* hp = gc_heap::g_heaps [hn]; - hp->walk_heap(&HeapWalkHelper, &profilerWalkHeapContext, max_generation, TRUE /* walk the large object heap */); - } -#else - gc_heap::walk_heap(&HeapWalkHelper, &profilerWalkHeapContext, max_generation, TRUE); -#endif //MULTIPLE_HEAPS - } - -#ifdef FEATURE_EVENT_TRACE - // **** Done! Indicate to ETW helpers that the heap walk is done, so any buffers - // should be flushed into the ETW stream - if (fShouldWalkHeapObjectsForEtw || fShouldWalkHeapRootsForEtw) - { - ETW::GCLog::EndHeapDump(&profilerWalkHeapContext); - } -#endif // FEATURE_EVENT_TRACE - } -} -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - -void GCProfileWalkHeap() -{ - BOOL fWalkedHeapForProfiler = FALSE; - -#ifdef FEATURE_EVENT_TRACE - if (ETW::GCLog::ShouldWalkStaticsAndCOMForEtw()) - ETW::GCLog::WalkStaticsAndCOMForETW(); - - BOOL fShouldWalkHeapRootsForEtw = ETW::GCLog::ShouldWalkHeapRootsForEtw(); - BOOL fShouldWalkHeapObjectsForEtw = ETW::GCLog::ShouldWalkHeapObjectsForEtw(); -#else // !FEATURE_EVENT_TRACE - BOOL fShouldWalkHeapRootsForEtw = FALSE; - BOOL fShouldWalkHeapObjectsForEtw = FALSE; -#endif // FEATURE_EVENT_TRACE - -#if defined (GC_PROFILING) - { - BEGIN_PIN_PROFILER(CORProfilerTrackGC()); - GCProfileWalkHeapWorker(TRUE /* fProfilerPinned */, fShouldWalkHeapRootsForEtw, fShouldWalkHeapObjectsForEtw); - fWalkedHeapForProfiler = TRUE; - END_PIN_PROFILER(); - } -#endif // defined (GC_PROFILING) - -#if defined (GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - // we need to walk the heap if one of GC_PROFILING or FEATURE_EVENT_TRACE - // is defined, since both of them make use of the walk heap worker. - if (!fWalkedHeapForProfiler && - (fShouldWalkHeapRootsForEtw || fShouldWalkHeapObjectsForEtw)) - { - GCProfileWalkHeapWorker(FALSE /* fProfilerPinned */, fShouldWalkHeapRootsForEtw, fShouldWalkHeapObjectsForEtw); - } -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) -} - BOOL GCHeap::IsGCInProgressHelper (BOOL bConsiderGCStart) { return GcInProgress || (bConsiderGCStart? VolatileLoad(&gc_heap::gc_started) : FALSE); @@ -782,11 +579,11 @@ void gc_heap::background_gc_wait_lh (alloc_wait_reason awr) /******************************************************************************/ -::GCHeap* CreateGCHeap() { +IGCHeapInternal* CreateGCHeap() { return new(nothrow) GCHeap(); // we return wks or svr } -void GCHeap::TraceGCSegments() +void GCHeap::DiagTraceGCSegments() { #ifdef FEATURE_EVENT_TRACE heap_segment* seg = 0; @@ -823,16 +620,16 @@ void GCHeap::TraceGCSegments() #endif // FEATURE_EVENT_TRACE } -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) -void GCHeap::DescrGenerationsToProfiler (gen_walk_fn fn, void *context) +void GCHeap::DiagDescrGenerations (gen_walk_fn fn, void *context) { +#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) pGenGCHeap->descr_generations_to_profiler(fn, context); -} #endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) +} -#ifdef FEATURE_BASICFREEZE segment_handle GCHeap::RegisterFrozenSegment(segment_info *pseginfo) { +#ifdef FEATURE_BASICFREEZE heap_segment * seg = new (nothrow) heap_segment; if (!seg) { @@ -863,10 +660,15 @@ segment_handle GCHeap::RegisterFrozenSegment(segment_info *pseginfo) } return reinterpret_cast< segment_handle >(seg); +#else + assert(!"Should not call GCHeap::RegisterFrozenSegment without FEATURE_BASICFREEZE defined!"); + return NULL; +#endif // FEATURE_BASICFREEZE } void GCHeap::UnregisterFrozenSegment(segment_handle seg) { +#ifdef FEATURE_BASICFREEZE #if defined (MULTIPLE_HEAPS) && !defined (ISOLATED_HEAPS) gc_heap* heap = gc_heap::g_heaps[0]; #else @@ -874,8 +676,10 @@ void GCHeap::UnregisterFrozenSegment(segment_handle seg) #endif //MULTIPLE_HEAPS && !ISOLATED_HEAPS heap->remove_ro_segment(reinterpret_cast(seg)); -} +#else + assert(!"Should not call GCHeap::UnregisterFrozenSegment without FEATURE_BASICFREEZE defined!"); #endif // FEATURE_BASICFREEZE +} #endif // !DACCESS_COMPILE diff --git a/src/gc/gcenv.ee.standalone.inl b/src/gc/gcenv.ee.standalone.inl new file mode 100644 index 0000000..3b64586 --- /dev/null +++ b/src/gc/gcenv.ee.standalone.inl @@ -0,0 +1,176 @@ +// 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. + +#ifndef __GCTOENV_EE_STANDALONE_INL__ +#define __GCTOENV_EE_STANDALONE_INL__ + +#include "env/gcenv.ee.h" + +// The singular interface instance. All calls in GCToEEInterface +// will be fowarded to this interface instance. +extern IGCToCLR* g_theGCToCLR; + +// When we are building the GC in a standalone environment, we +// will be dispatching virtually against g_theGCToCLR to call +// into the EE. This class provides an identical API to the existing +// GCToEEInterface, but only forwards the call onto the global +// g_theGCToCLR instance. +inline void GCToEEInterface::SuspendEE(SUSPEND_REASON reason) +{ + assert(g_theGCToCLR != nullptr); + g_theGCToCLR->SuspendEE(reason); +} + +inline void GCToEEInterface::RestartEE(bool bFinishedGC) +{ + assert(g_theGCToCLR != nullptr); + g_theGCToCLR->RestartEE(bFinishedGC); +} + +inline void GCToEEInterface::GcScanRoots(promote_func* fn, int condemned, int max_gen, ScanContext* sc) +{ + assert(g_theGCToCLR != nullptr); + g_theGCToCLR->GcScanRoots(fn, condemned, max_gen, sc); +} + +inline void GCToEEInterface::GcStartWork(int condemned, int max_gen) +{ + assert(g_theGCToCLR != nullptr); + g_theGCToCLR->GcStartWork(condemned, max_gen); +} + +inline void GCToEEInterface::AfterGcScanRoots(int condemned, int max_gen, ScanContext* sc) +{ + assert(g_theGCToCLR != nullptr); + g_theGCToCLR->AfterGcScanRoots(condemned, max_gen, sc); +} + +inline void GCToEEInterface::GcBeforeBGCSweepWork() +{ + assert(g_theGCToCLR != nullptr); + g_theGCToCLR->GcBeforeBGCSweepWork(); +} + +inline void GCToEEInterface::GcDone(int condemned) +{ + assert(g_theGCToCLR != nullptr); + g_theGCToCLR->GcDone(condemned); +} + +inline bool GCToEEInterface::RefCountedHandleCallbacks(Object * pObject) +{ + assert(g_theGCToCLR != nullptr); + return g_theGCToCLR->RefCountedHandleCallbacks(pObject); +} + +inline void GCToEEInterface::SyncBlockCacheWeakPtrScan(HANDLESCANPROC scanProc, uintptr_t lp1, uintptr_t lp2) +{ + assert(g_theGCToCLR != nullptr); + g_theGCToCLR->SyncBlockCacheWeakPtrScan(scanProc, lp1, lp2); +} + +inline void GCToEEInterface::SyncBlockCacheDemote(int max_gen) +{ + assert(g_theGCToCLR != nullptr); + g_theGCToCLR->SyncBlockCacheDemote(max_gen); +} + +inline void GCToEEInterface::SyncBlockCachePromotionsGranted(int max_gen) +{ + assert(g_theGCToCLR != nullptr); + g_theGCToCLR->SyncBlockCachePromotionsGranted(max_gen); +} + +inline bool GCToEEInterface::IsPreemptiveGCDisabled(Thread * pThread) +{ + assert(g_theGCToCLR != nullptr); + return g_theGCToCLR->IsPreemptiveGCDisabled(pThread); +} + + +inline void GCToEEInterface::EnablePreemptiveGC(Thread * pThread) +{ + assert(g_theGCToCLR != nullptr); + g_theGCToCLR->EnablePreemptiveGC(pThread); +} + +inline void GCToEEInterface::DisablePreemptiveGC(Thread * pThread) +{ + assert(g_theGCToCLR != nullptr); + g_theGCToCLR->DisablePreemptiveGC(pThread); +} + +inline gc_alloc_context * GCToEEInterface::GetAllocContext(Thread * pThread) +{ + assert(g_theGCToCLR != nullptr); + return g_theGCToCLR->GetAllocContext(pThread); +} + +inline bool GCToEEInterface::CatchAtSafePoint(Thread * pThread) +{ + assert(g_theGCToCLR != nullptr); + return g_theGCToCLR->CatchAtSafePoint(pThread); +} + +inline void GCToEEInterface::GcEnumAllocContexts(enum_alloc_context_func* fn, void* param) +{ + assert(g_theGCToCLR != nullptr); + g_theGCToCLR->GcEnumAllocContexts(fn, param); +} + +inline Thread* GCToEEInterface::CreateBackgroundThread(GCBackgroundThreadFunction threadStart, void* arg) +{ + assert(g_theGCToCLR != nullptr); + return g_theGCToCLR->CreateBackgroundThread(threadStart, arg); +} + +inline void GCToEEInterface::DiagGCStart(int gen, bool isInduced) +{ + assert(g_theGCToCLR != nullptr); + g_theGCToCLR->DiagGCStart(gen, isInduced); +} + +inline void GCToEEInterface::DiagUpdateGenerationBounds() +{ + assert(g_theGCToCLR != nullptr); + g_theGCToCLR->DiagUpdateGenerationBounds(); +} + +inline void GCToEEInterface::DiagGCEnd(size_t index, int gen, int reason, bool fConcurrent) +{ + assert(g_theGCToCLR != nullptr); + g_theGCToCLR->DiagGCEnd(index, gen, reason, fConcurrent); +} + +inline void GCToEEInterface::DiagWalkFReachableObjects(void* gcContext) +{ + assert(g_theGCToCLR != nullptr); + g_theGCToCLR->DiagWalkFReachableObjects(gcContext); +} + +inline void GCToEEInterface::DiagWalkSurvivors(void* gcContext) +{ + assert(g_theGCToCLR != nullptr); + g_theGCToCLR->DiagWalkSurvivors(gcContext); +} + +inline void GCToEEInterface::DiagWalkLOHSurvivors(void* gcContext) +{ + assert(g_theGCToCLR != nullptr); + g_theGCToCLR->DiagWalkLOHSurvivors(gcContext); +} + +inline void GCToEEInterface::DiagWalkBGCSurvivors(void* gcContext) +{ + assert(g_theGCToCLR != nullptr); + return g_theGCToCLR->DiagWalkBGCSurvivors(gcContext); +} + +inline void GCToEEInterface::StompWriteBarrier(WriteBarrierParameters* args) +{ + assert(g_theGCToCLR != nullptr); + g_theGCToCLR->StompWriteBarrier(args); +} + +#endif // __GCTOENV_EE_STANDALONE_INL__ diff --git a/src/gc/gcenv.unix.cpp b/src/gc/gcenv.unix.cpp new file mode 100644 index 0000000..0235952 --- /dev/null +++ b/src/gc/gcenv.unix.cpp @@ -0,0 +1,308 @@ +// 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. + +#include "env/gcenv.structs.h" +#include "env/gcenv.base.h" +#include "env/gcenv.os.h" + +// Initialize the interface implementation +// Return: +// true if it has succeeded, false if it has failed +bool GCToOSInterface::Initialize() +{ + throw nullptr; +} + +// Shutdown the interface implementation +void GCToOSInterface::Shutdown() +{ + throw nullptr; +} + +// Get numeric id of the current thread if possible on the +// current platform. It is indended for logging purposes only. +// Return: +// Numeric id of the current thread or 0 if the +uint64_t GCToOSInterface::GetCurrentThreadIdForLogging() +{ + throw nullptr; +} + +// Get id of the process +uint32_t GCToOSInterface::GetCurrentProcessId() +{ + throw nullptr; +} + +// Set ideal affinity for the current thread +// Parameters: +// affinity - ideal processor affinity for the thread +// Return: +// true if it has succeeded, false if it has failed +bool GCToOSInterface::SetCurrentThreadIdealAffinity(GCThreadAffinity* affinity) +{ + throw nullptr; +} + +// Get the number of the current processor +uint32_t GCToOSInterface::GetCurrentProcessorNumber() +{ + throw nullptr; +} + +// Check if the OS supports getting current processor number +bool GCToOSInterface::CanGetCurrentProcessorNumber() +{ + throw nullptr; +} + +// Flush write buffers of processors that are executing threads of the current process +void GCToOSInterface::FlushProcessWriteBuffers() +{ + throw nullptr; +} + +// Break into a debugger +void GCToOSInterface::DebugBreak() +{ + throw nullptr; +} + +// Get number of logical processors +uint32_t GCToOSInterface::GetLogicalCpuCount() +{ + throw nullptr; +} + +// Causes the calling thread to sleep for the specified number of milliseconds +// Parameters: +// sleepMSec - time to sleep before switching to another thread +void GCToOSInterface::Sleep(uint32_t sleepMSec) +{ + throw nullptr; +} + +// Causes the calling thread to yield execution to another thread that is ready to run on the current processor. +// Parameters: +// switchCount - number of times the YieldThread was called in a loop +void GCToOSInterface::YieldThread(uint32_t switchCount) +{ + throw nullptr; +} + +// Reserve virtual memory range. +// Parameters: +// size - size of the virtual memory range +// alignment - requested memory alignment, 0 means no specific alignment requested +// flags - flags to control special settings like write watching +// Return: +// Starting virtual address of the reserved range +void* GCToOSInterface::VirtualReserve(size_t size, size_t alignment, uint32_t flags) +{ + throw nullptr; +} + +// Release virtual memory range previously reserved using VirtualReserve +// Parameters: +// address - starting virtual address +// size - size of the virtual memory range +// Return: +// true if it has succeeded, false if it has failed +bool GCToOSInterface::VirtualRelease(void* address, size_t size) +{ + throw nullptr; +} + +// Commit virtual memory range. It must be part of a range reserved using VirtualReserve. +// Parameters: +// address - starting virtual address +// size - size of the virtual memory range +// Return: +// true if it has succeeded, false if it has failed +bool GCToOSInterface::VirtualCommit(void* address, size_t size) +{ + throw nullptr; +} + +// Decomit virtual memory range. +// Parameters: +// address - starting virtual address +// size - size of the virtual memory range +// Return: +// true if it has succeeded, false if it has failed +bool GCToOSInterface::VirtualDecommit(void* address, size_t size) +{ + throw nullptr; +} + +// Reset virtual memory range. Indicates that data in the memory range specified by address and size is no +// longer of interest, but it should not be decommitted. +// Parameters: +// address - starting virtual address +// size - size of the virtual memory range +// unlock - true if the memory range should also be unlocked +// Return: +// true if it has succeeded, false if it has failed +bool GCToOSInterface::VirtualReset(void * address, size_t size, bool unlock) +{ + throw nullptr; +} + +// Check if the OS supports write watching +bool GCToOSInterface::SupportsWriteWatch() +{ + throw nullptr; +} + +// Reset the write tracking state for the specified virtual memory range. +// Parameters: +// address - starting virtual address +// size - size of the virtual memory range +void GCToOSInterface::ResetWriteWatch(void* address, size_t size) +{ + throw nullptr; +} + +// Retrieve addresses of the pages that are written to in a region of virtual memory +// Parameters: +// resetState - true indicates to reset the write tracking state +// address - starting virtual address +// size - size of the virtual memory range +// pageAddresses - buffer that receives an array of page addresses in the memory region +// pageAddressesCount - on input, size of the lpAddresses array, in array elements +// on output, the number of page addresses that are returned in the array. +// Return: +// true if it has succeeded, false if it has failed +bool GCToOSInterface::GetWriteWatch(bool resetState, void* address, size_t size, void** pageAddresses, uintptr_t* pageAddressesCount) +{ + throw nullptr; +} + +// Get size of the largest cache on the processor die +// Parameters: +// trueSize - true to return true cache size, false to return scaled up size based on +// the processor architecture +// Return: +// Size of the cache +size_t GCToOSInterface::GetLargestOnDieCacheSize(bool trueSize) +{ + throw nullptr; +} + +// Get affinity mask of the current process +// Parameters: +// processMask - affinity mask for the specified process +// systemMask - affinity mask for the system +// Return: +// true if it has succeeded, false if it has failed +// Remarks: +// A process affinity mask is a bit vector in which each bit represents the processors that +// a process is allowed to run on. A system affinity mask is a bit vector in which each bit +// represents the processors that are configured into a system. +// A process affinity mask is a subset of the system affinity mask. A process is only allowed +// to run on the processors configured into a system. Therefore, the process affinity mask cannot +// specify a 1 bit for a processor when the system affinity mask specifies a 0 bit for that processor. +bool GCToOSInterface::GetCurrentProcessAffinityMask(uintptr_t* processMask, uintptr_t* systemMask) +{ + throw nullptr; +} + +// Get number of processors assigned to the current process +// Return: +// The number of processors +uint32_t GCToOSInterface::GetCurrentProcessCpuCount() +{ + throw nullptr; +} + +// Return the size of the user-mode portion of the virtual address space of this process. +// Return: +// non zero if it has succeeded, 0 if it has failed +size_t GCToOSInterface::GetVirtualMemoryLimit() +{ + throw nullptr; +} + +// Get the physical memory that this process can use. +// Return: +// non zero if it has succeeded, 0 if it has failed +// Remarks: +// If a process runs with a restricted memory limit, it returns the limit. If there's no limit +// specified, it returns amount of actual physical memory. +uint64_t GCToOSInterface::GetPhysicalMemoryLimit() +{ + throw nullptr; +} + +// Get memory status +// Parameters: +// memory_load - A number between 0 and 100 that specifies the approximate percentage of physical memory +// that is in use (0 indicates no memory use and 100 indicates full memory use). +// available_physical - The amount of physical memory currently available, in bytes. +// available_page_file - The maximum amount of memory the current process can commit, in bytes. +void GCToOSInterface::GetMemoryStatus(uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file) +{ + throw nullptr; +} + +// Get a high precision performance counter +// Return: +// The counter value +int64_t GCToOSInterface::QueryPerformanceCounter() +{ + throw nullptr; +} + +// Get a frequency of the high precision performance counter +// Return: +// The counter frequency +int64_t GCToOSInterface::QueryPerformanceFrequency() +{ + throw nullptr; +} + +// Get a time stamp with a low precision +// Return: +// Time stamp in milliseconds +uint32_t GCToOSInterface::GetLowPrecisionTimeStamp() +{ + throw nullptr; +} + + +// Create a new thread for GC use +// Parameters: +// function - the function to be executed by the thread +// param - parameters of the thread +// affinity - processor affinity of the thread +// Return: +// true if it has succeeded, false if it has failed +bool GCToOSInterface::CreateThread(GCThreadFunction function, void* param, GCThreadAffinity* affinity) +{ + throw nullptr; +} + +// Initialize the critical section +void CLRCriticalSection::Initialize() +{ + throw nullptr; +} + +// Destroy the critical section +void CLRCriticalSection::Destroy() +{ + throw nullptr; +} + +// Enter the critical section. Blocks until the section can be entered. +void CLRCriticalSection::Enter() +{ + throw nullptr; +} + +// Leave the critical section +void CLRCriticalSection::Leave() +{ + throw nullptr; +} \ No newline at end of file diff --git a/src/gc/gcenv.windows.cpp b/src/gc/gcenv.windows.cpp new file mode 100644 index 0000000..a636478 --- /dev/null +++ b/src/gc/gcenv.windows.cpp @@ -0,0 +1,625 @@ +// 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. + +#include +#include +#include +#include +#include "windows.h" +#include "psapi.h" +#include "env/gcenv.structs.h" +#include "env/gcenv.base.h" +#include "env/gcenv.os.h" + +GCSystemInfo g_SystemInfo; + +typedef BOOL (WINAPI *PGET_PROCESS_MEMORY_INFO)(HANDLE handle, PROCESS_MEMORY_COUNTERS* memCounters, uint32_t cb); +static PGET_PROCESS_MEMORY_INFO GCGetProcessMemoryInfo = 0; + +static size_t g_RestrictedPhysicalMemoryLimit = (size_t)UINTPTR_MAX; + +typedef BOOL (WINAPI *PIS_PROCESS_IN_JOB)(HANDLE processHandle, HANDLE jobHandle, BOOL* result); +typedef BOOL (WINAPI *PQUERY_INFORMATION_JOB_OBJECT)(HANDLE jobHandle, JOBOBJECTINFOCLASS jobObjectInfoClass, void* lpJobObjectInfo, DWORD cbJobObjectInfoLength, LPDWORD lpReturnLength); + +namespace { + +void GetProcessMemoryLoad(LPMEMORYSTATUSEX pMSEX) +{ + pMSEX->dwLength = sizeof(MEMORYSTATUSEX); + BOOL fRet = ::GlobalMemoryStatusEx(pMSEX); + assert(fRet); + + // If the machine has more RAM than virtual address limit, let us cap it. + // Our GC can never use more than virtual address limit. + if (pMSEX->ullAvailPhys > pMSEX->ullTotalVirtual) + { + pMSEX->ullAvailPhys = pMSEX->ullAvailVirtual; + } +} + +static size_t GetRestrictedPhysicalMemoryLimit() +{ + LIMITED_METHOD_CONTRACT; + + // The limit was cached already + if (g_RestrictedPhysicalMemoryLimit != (size_t)UINTPTR_MAX) + return g_RestrictedPhysicalMemoryLimit; + + size_t job_physical_memory_limit = (size_t)UINTPTR_MAX; + BOOL in_job_p = FALSE; + HINSTANCE hinstKernel32 = 0; + + PIS_PROCESS_IN_JOB GCIsProcessInJob = 0; + PQUERY_INFORMATION_JOB_OBJECT GCQueryInformationJobObject = 0; + + hinstKernel32 = LoadLibraryEx(L"kernel32.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); + if (!hinstKernel32) + goto exit; + + GCIsProcessInJob = (PIS_PROCESS_IN_JOB)GetProcAddress(hinstKernel32, "IsProcessInJob"); + if (!GCIsProcessInJob) + goto exit; + + if (!GCIsProcessInJob(GetCurrentProcess(), NULL, &in_job_p)) + goto exit; + + if (in_job_p) + { + GCGetProcessMemoryInfo = (PGET_PROCESS_MEMORY_INFO)GetProcAddress(hinstKernel32, "K32GetProcessMemoryInfo"); + + if (!GCGetProcessMemoryInfo) + goto exit; + + GCQueryInformationJobObject = (PQUERY_INFORMATION_JOB_OBJECT)GetProcAddress(hinstKernel32, "QueryInformationJobObject"); + + if (!GCQueryInformationJobObject) + goto exit; + + JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info; + if (GCQueryInformationJobObject (NULL, JobObjectExtendedLimitInformation, &limit_info, + sizeof(limit_info), NULL)) + { + size_t job_memory_limit = (size_t)UINTPTR_MAX; + size_t job_process_memory_limit = (size_t)UINTPTR_MAX; + size_t job_workingset_limit = (size_t)UINTPTR_MAX; + + // Notes on the NT job object: + // + // You can specific a bigger process commit or working set limit than + // job limit which is pointless so we use the smallest of all 3 as + // to calculate our "physical memory load" or "available physical memory" + // when running inside a job object, ie, we treat this as the amount of physical memory + // our process is allowed to use. + // + // The commit limit is already reflected by default when you run in a + // job but the physical memory load is not. + // + if ((limit_info.BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_JOB_MEMORY) != 0) + job_memory_limit = limit_info.JobMemoryLimit; + if ((limit_info.BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_PROCESS_MEMORY) != 0) + job_process_memory_limit = limit_info.ProcessMemoryLimit; + if ((limit_info.BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_WORKINGSET) != 0) + job_workingset_limit = limit_info.BasicLimitInformation.MaximumWorkingSetSize; + + job_physical_memory_limit = min (job_memory_limit, job_process_memory_limit); + job_physical_memory_limit = min (job_physical_memory_limit, job_workingset_limit); + + MEMORYSTATUSEX ms; + ::GetProcessMemoryLoad(&ms); + + // A sanity check in case someone set a larger limit than there is actual physical memory. + job_physical_memory_limit = (size_t) min (job_physical_memory_limit, ms.ullTotalPhys); + } + } + +exit: + if (job_physical_memory_limit == (size_t)UINTPTR_MAX) + { + job_physical_memory_limit = 0; + + FreeLibrary(hinstKernel32); + } + + VolatileStore(&g_RestrictedPhysicalMemoryLimit, job_physical_memory_limit); + return g_RestrictedPhysicalMemoryLimit; +} + +} // anonymous namespace + +// Initialize the interface implementation +// Return: +// true if it has succeeded, false if it has failed +bool GCToOSInterface::Initialize() +{ + SYSTEM_INFO systemInfo; + GetSystemInfo(&systemInfo); + + g_SystemInfo.dwNumberOfProcessors = systemInfo.dwNumberOfProcessors; + g_SystemInfo.dwPageSize = systemInfo.dwPageSize; + g_SystemInfo.dwAllocationGranularity = systemInfo.dwAllocationGranularity; + + return true; +} + +// Shutdown the interface implementation +void GCToOSInterface::Shutdown() +{ + // nothing to do. +} + +// Get numeric id of the current thread if possible on the +// current platform. It is indended for logging purposes only. +// Return: +// Numeric id of the current thread or 0 if the +uint64_t GCToOSInterface::GetCurrentThreadIdForLogging() +{ + return ::GetCurrentThreadId(); +} + +// Get id of the process +uint32_t GCToOSInterface::GetCurrentProcessId() +{ + return ::GetCurrentThreadId(); +} + +// Set ideal affinity for the current thread +// Parameters: +// affinity - ideal processor affinity for the thread +// Return: +// true if it has succeeded, false if it has failed +bool GCToOSInterface::SetCurrentThreadIdealAffinity(GCThreadAffinity* affinity) +{ + bool success = true; + +#if !defined(FEATURE_CORESYSTEM) + SetThreadIdealProcessor(GetCurrentThread(), (DWORD)affinity->Processor); +#else + PROCESSOR_NUMBER proc; + + if (affinity->Group != -1) + { + proc.Group = (WORD)affinity->Group; + proc.Number = (BYTE)affinity->Processor; + proc.Reserved = 0; + + success = !!SetThreadIdealProcessorEx(GetCurrentThread(), &proc, NULL); + } + else + { + if (GetThreadIdealProcessorEx(GetCurrentThread(), &proc)) + { + proc.Number = affinity->Processor; + success = !!SetThreadIdealProcessorEx(GetCurrentThread(), &proc, NULL); + } + } +#endif + + return success; +} + +// Get the number of the current processor +uint32_t GCToOSInterface::GetCurrentProcessorNumber() +{ + assert(GCToOSInterface::CanGetCurrentProcessorNumber()); + return ::GetCurrentProcessorNumber(); +} + +// Check if the OS supports getting current processor number +bool GCToOSInterface::CanGetCurrentProcessorNumber() +{ + // on all Windows platforms we support this API exists + return true; +} + +// Flush write buffers of processors that are executing threads of the current process +void GCToOSInterface::FlushProcessWriteBuffers() +{ + ::FlushProcessWriteBuffers(); +} + +// Break into a debugger +void GCToOSInterface::DebugBreak() +{ + ::DebugBreak(); +} + +// Get number of logical processors +uint32_t GCToOSInterface::GetLogicalCpuCount() +{ + // TODO(segilles) processor detection + return 1; +} + +// Causes the calling thread to sleep for the specified number of milliseconds +// Parameters: +// sleepMSec - time to sleep before switching to another thread +void GCToOSInterface::Sleep(uint32_t sleepMSec) +{ + // TODO(segilles) CLR implementation of __SwitchToThread spins for short sleep durations + // to avoid context switches - is that interesting or useful here? + if (sleepMSec > 0) + { + ::SleepEx(sleepMSec, FALSE); + } +} + +// Causes the calling thread to yield execution to another thread that is ready to run on the current processor. +// Parameters: +// switchCount - number of times the YieldThread was called in a loop +void GCToOSInterface::YieldThread(uint32_t switchCount) +{ + UNREFERENCED_PARAMETER(switchCount); + SwitchToThread(); +} + +// Reserve virtual memory range. +// Parameters: +// address - starting virtual address, it can be NULL to let the function choose the starting address +// size - size of the virtual memory range +// alignment - requested memory alignment, 0 means no specific alignment requested +// flags - flags to control special settings like write watching +// Return: +// Starting virtual address of the reserved range +void* GCToOSInterface::VirtualReserve(size_t size, size_t alignment, uint32_t flags) +{ + // Windows already ensures 64kb alignment on VirtualAlloc. The current CLR + // implementation ignores it on Windows, other than making some sanity checks on it. + UNREFERENCED_PARAMETER(alignment); + assert((alignment & (alignment - 1)) == 0); + assert(alignment <= 0x10000); + DWORD memFlags = (flags & VirtualReserveFlags::WriteWatch) ? (MEM_RESERVE | MEM_WRITE_WATCH) : MEM_RESERVE; + return ::VirtualAlloc(nullptr, size, memFlags, PAGE_READWRITE); +} + +// Release virtual memory range previously reserved using VirtualReserve +// Parameters: +// address - starting virtual address +// size - size of the virtual memory range +// Return: +// true if it has succeeded, false if it has failed +bool GCToOSInterface::VirtualRelease(void* address, size_t size) +{ + return !!::VirtualFree(address, 0, MEM_RELEASE); +} + +// Commit virtual memory range. It must be part of a range reserved using VirtualReserve. +// Parameters: +// address - starting virtual address +// size - size of the virtual memory range +// Return: +// true if it has succeeded, false if it has failed +bool GCToOSInterface::VirtualCommit(void* address, size_t size) +{ + return ::VirtualAlloc(address, size, MEM_COMMIT, PAGE_READWRITE) != nullptr; +} + +// Decomit virtual memory range. +// Parameters: +// address - starting virtual address +// size - size of the virtual memory range +// Return: +// true if it has succeeded, false if it has failed +bool GCToOSInterface::VirtualDecommit(void* address, size_t size) +{ + return !!::VirtualFree(address, size, MEM_DECOMMIT); +} + +// Reset virtual memory range. Indicates that data in the memory range specified by address and size is no +// longer of interest, but it should not be decommitted. +// Parameters: +// address - starting virtual address +// size - size of the virtual memory range +// unlock - true if the memory range should also be unlocked +// Return: +// true if it has succeeded, false if it has failed. Returns false also if +// unlocking was requested but the unlock failed. +bool GCToOSInterface::VirtualReset(void * address, size_t size, bool unlock) +{ + bool success = ::VirtualAlloc(address, size, MEM_RESET, PAGE_READWRITE) != nullptr; + if (success && unlock) + { + ::VirtualUnlock(address, size); + } + + return success; +} + +// Check if the OS supports write watching +bool GCToOSInterface::SupportsWriteWatch() +{ + void* mem = GCToOSInterface::VirtualReserve(g_SystemInfo.dwAllocationGranularity, 0, VirtualReserveFlags::WriteWatch); + if (mem != nullptr) + { + GCToOSInterface::VirtualRelease(mem, g_SystemInfo.dwAllocationGranularity); + return true; + } + + return false; +} + +// Reset the write tracking state for the specified virtual memory range. +// Parameters: +// address - starting virtual address +// size - size of the virtual memory range +void GCToOSInterface::ResetWriteWatch(void* address, size_t size) +{ + ::ResetWriteWatch(address, size); +} + +// Retrieve addresses of the pages that are written to in a region of virtual memory +// Parameters: +// resetState - true indicates to reset the write tracking state +// address - starting virtual address +// size - size of the virtual memory range +// pageAddresses - buffer that receives an array of page addresses in the memory region +// pageAddressesCount - on input, size of the lpAddresses array, in array elements +// on output, the number of page addresses that are returned in the array. +// Return: +// true if it has succeeded, false if it has failed +bool GCToOSInterface::GetWriteWatch(bool resetState, void* address, size_t size, void** pageAddresses, uintptr_t* pageAddressesCount) +{ + uint32_t flags = resetState ? 1 : 0; + ULONG granularity; + + bool success = ::GetWriteWatch(flags, address, size, pageAddresses, (ULONG_PTR*)pageAddressesCount, &granularity) == 0; + if (success) + { + assert(granularity == OS_PAGE_SIZE); + } + + return success; +} + +// Get size of the largest cache on the processor die +// Parameters: +// trueSize - true to return true cache size, false to return scaled up size based on +// the processor architecture +// Return: +// Size of the cache +size_t GCToOSInterface::GetLargestOnDieCacheSize(bool trueSize) +{ + // TODO(segilles) processor detection (see src/vm/util.cpp:1935) + return 0; +} + +// Get affinity mask of the current process +// Parameters: +// processMask - affinity mask for the specified process +// systemMask - affinity mask for the system +// Return: +// true if it has succeeded, false if it has failed +// Remarks: +// A process affinity mask is a bit vector in which each bit represents the processors that +// a process is allowed to run on. A system affinity mask is a bit vector in which each bit +// represents the processors that are configured into a system. +// A process affinity mask is a subset of the system affinity mask. A process is only allowed +// to run on the processors configured into a system. Therefore, the process affinity mask cannot +// specify a 1 bit for a processor when the system affinity mask specifies a 0 bit for that processor. +bool GCToOSInterface::GetCurrentProcessAffinityMask(uintptr_t* processMask, uintptr_t* systemMask) +{ + return !!::GetProcessAffinityMask(::GetCurrentProcess(), (PDWORD_PTR)processMask, (PDWORD_PTR)systemMask); +} + +// Get number of processors assigned to the current process +// Return: +// The number of processors +uint32_t GCToOSInterface::GetCurrentProcessCpuCount() +{ + // TODO(segilles) this does not take into account process affinity + return g_SystemInfo.dwNumberOfProcessors; +} + +// Return the size of the user-mode portion of the virtual address space of this process. +// Return: +// non zero if it has succeeded, 0 if it has failed +size_t GCToOSInterface::GetVirtualMemoryLimit() +{ + MEMORYSTATUSEX memStatus; + if (::GlobalMemoryStatusEx(&memStatus)) + { + return (size_t)memStatus.ullAvailVirtual; + } + + return 0; +} + +// Get the physical memory that this process can use. +// Return: +// non zero if it has succeeded, 0 if it has failed +// Remarks: +// If a process runs with a restricted memory limit, it returns the limit. If there's no limit +// specified, it returns amount of actual physical memory. +uint64_t GCToOSInterface::GetPhysicalMemoryLimit() +{ + size_t restricted_limit = GetRestrictedPhysicalMemoryLimit(); + if (restricted_limit != 0) + return restricted_limit; + + MEMORYSTATUSEX memStatus; + if (::GlobalMemoryStatusEx(&memStatus)) + { + return memStatus.ullTotalPhys; + } + + return 0; +} + +// Get memory status +// Parameters: +// memory_load - A number between 0 and 100 that specifies the approximate percentage of physical memory +// that is in use (0 indicates no memory use and 100 indicates full memory use). +// available_physical - The amount of physical memory currently available, in bytes. +// available_page_file - The maximum amount of memory the current process can commit, in bytes. +void GCToOSInterface::GetMemoryStatus(uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file) +{ + uint64_t restricted_limit = GetRestrictedPhysicalMemoryLimit(); + if (restricted_limit != 0) + { + PROCESS_MEMORY_COUNTERS pmc; + if (GCGetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) + { + if (memory_load) + *memory_load = (uint32_t)((float)pmc.WorkingSetSize * 100.0 / (float)restricted_limit); + if (available_physical) + *available_physical = restricted_limit - pmc.WorkingSetSize; + // Available page file doesn't mean much when physical memory is restricted since + // we don't know how much of it is available to this process so we are not going to + // bother to make another OS call for it. + if (available_page_file) + *available_page_file = 0; + + return; + } + } + + MEMORYSTATUSEX ms; + ::GetProcessMemoryLoad(&ms); + + if (memory_load != nullptr) + *memory_load = ms.dwMemoryLoad; + if (available_physical != nullptr) + *available_physical = ms.ullAvailPhys; + if (available_page_file != nullptr) + *available_page_file = ms.ullAvailPageFile; +} + +// Get a high precision performance counter +// Return: +// The counter value +int64_t GCToOSInterface::QueryPerformanceCounter() +{ + LARGE_INTEGER ts; + if (!::QueryPerformanceCounter(&ts)) + { + assert(false && "Failed to query performance counter"); + } + + return ts.QuadPart; +} + +// Get a frequency of the high precision performance counter +// Return: +// The counter frequency +int64_t GCToOSInterface::QueryPerformanceFrequency() +{ + LARGE_INTEGER ts; + if (!::QueryPerformanceFrequency(&ts)) + { + assert(false && "Failed to query performance counter"); + } + + return ts.QuadPart; +} + +// Get a time stamp with a low precision +// Return: +// Time stamp in milliseconds +uint32_t GCToOSInterface::GetLowPrecisionTimeStamp() +{ + return ::GetTickCount(); +} + +// Parameters of the GC thread stub +struct GCThreadStubParam +{ + GCThreadFunction GCThreadFunction; + void* GCThreadParam; +}; + +// GC thread stub to convert GC thread function to an OS specific thread function +static DWORD GCThreadStub(void* param) +{ + GCThreadStubParam *stubParam = (GCThreadStubParam*)param; + GCThreadFunction function = stubParam->GCThreadFunction; + void* threadParam = stubParam->GCThreadParam; + + delete stubParam; + + function(threadParam); + + return 0; +} + + +// Create a new thread for GC use +// Parameters: +// function - the function to be executed by the thread +// param - parameters of the thread +// affinity - processor affinity of the thread +// Return: +// true if it has succeeded, false if it has failed +bool GCToOSInterface::CreateThread(GCThreadFunction function, void* param, GCThreadAffinity* affinity) +{ + uint32_t thread_id; + + std::unique_ptr stubParam(new (std::nothrow) GCThreadStubParam()); + if (!stubParam) + { + return false; + } + + stubParam->GCThreadFunction = function; + stubParam->GCThreadParam = param; + + HANDLE gc_thread = ::CreateThread( + nullptr, + 512 * 1024 /* Thread::StackSize_Medium */, + (LPTHREAD_START_ROUTINE)GCThreadStub, + stubParam.get(), + CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION, + (DWORD*)&thread_id); + + if (!gc_thread) + { + return false; + } + + stubParam.release(); + bool result = !!::SetThreadPriority(gc_thread, /* THREAD_PRIORITY_ABOVE_NORMAL );*/ THREAD_PRIORITY_HIGHEST ); + assert(result && "failed to set thread priority"); + + if (affinity->Group != GCThreadAffinity::None) + { + assert(affinity->Processor != GCThreadAffinity::None); + GROUP_AFFINITY ga; + ga.Group = (WORD)affinity->Group; + ga.Reserved[0] = 0; // reserve must be filled with zero + ga.Reserved[1] = 0; // otherwise call may fail + ga.Reserved[2] = 0; + ga.Mask = (size_t)1 << affinity->Processor; + + bool result = !!::SetThreadGroupAffinity(gc_thread, &ga, nullptr); + assert(result && "failed to set thread affinity"); + } + else if (affinity->Processor != GCThreadAffinity::None) + { + ::SetThreadAffinityMask(gc_thread, (DWORD_PTR)1 << affinity->Processor); + } + + return true; +} + +// Initialize the critical section +void CLRCriticalSection::Initialize() +{ + ::InitializeCriticalSection(&m_cs); +} + +// Destroy the critical section +void CLRCriticalSection::Destroy() +{ + ::DeleteCriticalSection(&m_cs); +} + +// Enter the critical section. Blocks until the section can be entered. +void CLRCriticalSection::Enter() +{ + ::EnterCriticalSection(&m_cs); +} + +// Leave the critical section +void CLRCriticalSection::Leave() +{ + ::LeaveCriticalSection(&m_cs); +} diff --git a/src/gc/gcimpl.h b/src/gc/gcimpl.h index 6a4ee86..7e3a13a 100644 --- a/src/gc/gcimpl.h +++ b/src/gc/gcimpl.h @@ -36,29 +36,10 @@ inline void checkGCWriteBarrier() {} void GCProfileWalkHeap(); -class GCHeap; class gc_heap; class CFinalize; -// TODO : it would be easier to make this an ORed value -enum gc_reason -{ - reason_alloc_soh = 0, - reason_induced = 1, - reason_lowmemory = 2, - reason_empty = 3, - reason_alloc_loh = 4, - reason_oos_soh = 5, - reason_oos_loh = 6, - reason_induced_noforce = 7, // it's an induced GC and doesn't have to be blocking. - reason_gcstress = 8, // this turns into reason_induced & gc_mechanisms.stress_induced = true - reason_lowmemory_blocking = 9, - reason_induced_compacting = 10, - reason_lowmemory_host = 11, - reason_max -}; - -class GCHeap : public ::GCHeap +class GCHeap : public IGCHeapInternal { protected: @@ -96,7 +77,7 @@ public: size_t GetLastGCDuration(int generation); size_t GetNow(); - void TraceGCSegments (); + void DiagTraceGCSegments (); void PublishObject(uint8_t* obj); BOOL IsGCInProgressHelper (BOOL bConsiderGCStart = FALSE); @@ -111,17 +92,15 @@ public: //flags can be GC_ALLOC_CONTAINS_REF GC_ALLOC_FINALIZE Object* Alloc (size_t size, uint32_t flags); -#ifdef FEATURE_64BIT_ALIGNMENT Object* AllocAlign8 (size_t size, uint32_t flags); - Object* AllocAlign8 (alloc_context* acontext, size_t size, uint32_t flags); + Object* AllocAlign8 (gc_alloc_context* acontext, size_t size, uint32_t flags); private: Object* AllocAlign8Common (void* hp, alloc_context* acontext, size_t size, uint32_t flags); public: -#endif // FEATURE_64BIT_ALIGNMENT Object* AllocLHeap (size_t size, uint32_t flags); - Object* Alloc (alloc_context* acontext, size_t size, uint32_t flags); + Object* Alloc (gc_alloc_context* acontext, size_t size, uint32_t flags); - void FixAllocContext (alloc_context* acontext, + void FixAllocContext (gc_alloc_context* acontext, BOOL lockp, void* arg, void *heap); Object* GetContainingObject(void *pInteriorPtr); @@ -132,7 +111,7 @@ public: #endif //MULTIPLE_HEAPS int GetHomeHeapNumber (); - bool IsThreadUsingAllocationContextHeap(alloc_context* acontext, int thread_number); + bool IsThreadUsingAllocationContextHeap(gc_alloc_context* acontext, int thread_number); int GetNumberOfHeaps (); void HideAllocContext(alloc_context*); void RevealAllocContext(alloc_context*); @@ -176,9 +155,7 @@ public: BOOL IsEphemeral (Object* object); BOOL IsHeapPointer (void* object, BOOL small_heap_only = FALSE); -#ifdef VERIFY_HEAP void ValidateObjectMember (Object *obj); -#endif //_DEBUG PER_HEAP size_t ApproxTotalBytesInUse(BOOL small_heap_only = FALSE); PER_HEAP size_t ApproxFreeBytes(); @@ -199,8 +176,6 @@ public: int StartNoGCRegion(uint64_t totalSize, BOOL lohSizeKnown, uint64_t lohSize, BOOL disallowFullBlockingGC); int EndNoGCRegion(); - - PER_HEAP_ISOLATED unsigned GetMaxGeneration(); unsigned GetGcCount(); @@ -224,9 +199,7 @@ public: BOOL ShouldRestartFinalizerWatchDog(); void SetCardsAfterBulkCopy( Object**, size_t); -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - void WalkObject (Object* obj, walk_fn fn, void* context); -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) + void DiagWalkObject (Object* obj, walk_fn fn, void* context); public: // FIX @@ -249,11 +222,9 @@ public: // FIX // Interface with gc_heap size_t GarbageCollectTry (int generation, BOOL low_memory_p=FALSE, int mode=collection_blocking); -#ifdef FEATURE_BASICFREEZE // frozen segment management functions virtual segment_handle RegisterFrozenSegment(segment_info *pseginfo); virtual void UnregisterFrozenSegment(segment_handle seg); -#endif // FEATURE_BASICFREEZE void WaitUntilConcurrentGCComplete (); // Use in managd threads #ifndef DACCESS_COMPILE @@ -281,11 +252,12 @@ private: // the condition here may have to change as well. return g_TrapReturningThreads == 0; } -#ifndef FEATURE_REDHAWK // Redhawk forces relocation a different way -#ifdef STRESS_HEAP public: //return TRUE if GC actually happens, otherwise FALSE - BOOL StressHeap(alloc_context * acontext = 0); + BOOL StressHeap(gc_alloc_context * acontext = 0); + +#ifndef FEATURE_REDHAWK // Redhawk forces relocation a different way +#ifdef STRESS_HEAP protected: // only used in BACKGROUND_GC, but the symbol is not defined yet... @@ -300,17 +272,25 @@ protected: #endif // STRESS_HEAP #endif // FEATURE_REDHAWK -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - virtual void DescrGenerationsToProfiler (gen_walk_fn fn, void *context); -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) + virtual void DiagDescrGenerations (gen_walk_fn fn, void *context); + + virtual void DiagWalkSurvivorsWithType (void* gc_context, record_surv_fn fn, size_t diag_context, walk_surv_type type); + + virtual void DiagWalkFinalizeQueue (void* gc_context, fq_walk_fn fn); + + virtual void DiagScanFinalizeQueue (fq_scan_fn fn, ScanContext* context); + + virtual void DiagScanHandles (handle_scan_fn fn, int gen_number, ScanContext* context); + + virtual void DiagScanDependentHandles (handle_scan_fn fn, int gen_number, ScanContext* context); + + virtual void DiagWalkHeap(walk_fn fn, void* context, int gen_number, BOOL walk_large_object_heap_p); -#ifdef VERIFY_HEAP public: Object * NextObj (Object * object); -#ifdef FEATURE_BASICFREEZE +#if defined (FEATURE_BASICFREEZE) && defined (VERIFY_HEAP) BOOL IsInFrozenSegment (Object * object); -#endif //FEATURE_BASICFREEZE -#endif //VERIFY_HEAP +#endif // defined (FEATURE_BASICFREEZE) && defined (VERIFY_HEAP) }; #endif // GCIMPL_H_ diff --git a/src/gc/gcinterface.ee.h b/src/gc/gcinterface.ee.h new file mode 100644 index 0000000..c5f87ef --- /dev/null +++ b/src/gc/gcinterface.ee.h @@ -0,0 +1,133 @@ +// 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. + +#ifndef _GCINTERFACE_EE_H_ +#define _GCINTERFACE_EE_H_ + +// This interface provides the interface that the GC will use to speak to the rest +// of the execution engine. Everything that the GC does that requires the EE +// to be informed or that requires EE action must go through this interface. +// +// When FEATURE_STANDALONE_GC is defined, this class is named IGCToCLR and is +// an abstract class. The EE will provide a class that fulfills this interface, +// and the GC will dispatch virtually on it to call into the EE. When FEATURE_STANDALONE_GC +// is not defined, this class is named GCToEEInterface and the GC will dispatch statically on it. +class IGCToCLR { +public: + // Suspends the EE for the given reason. + virtual + void SuspendEE(SUSPEND_REASON reason) = 0; + + // Resumes all paused threads, with a boolean indicating + // if the EE is being restarted because a GC is complete. + virtual + void RestartEE(bool bFinishedGC) = 0; + + // Performs a stack walk of all managed threads and invokes the given promote_func + // on all GC roots encountered on the stack. Depending on the condemned generation, + // this function may also enumerate all static GC refs if necessary. + virtual + void GcScanRoots(promote_func* fn, int condemned, int max_gen, ScanContext* sc) = 0; + + // Callback from the GC informing the EE that it is preparing to start working. + virtual + void GcStartWork(int condemned, int max_gen) = 0; + + // Callback from the GC informing the EE that it has completed the managed stack + // scan. User threads are still suspended at this point. + virtual + void AfterGcScanRoots(int condemned, int max_gen, ScanContext* sc) = 0; + + // Callback from the GC informing the EE that the background sweep phase of a BGC is + // about to begin. + virtual + void GcBeforeBGCSweepWork() = 0; + + // Callback from the GC informing the EE that a GC has completed. + virtual + void GcDone(int condemned) = 0; + + // Predicate for the GC to query whether or not a given refcounted handle should + // be promoted. + virtual + bool RefCountedHandleCallbacks(Object * pObject) = 0; + + // Performs a weak pointer scan of the sync block cache. + virtual + void SyncBlockCacheWeakPtrScan(HANDLESCANPROC scanProc, uintptr_t lp1, uintptr_t lp2) = 0; + + // Indicates to the EE that the GC intends to demote objects in the sync block cache. + virtual + void SyncBlockCacheDemote(int max_gen) = 0; + + // Indicates to the EE that the GC has granted promotion to objects in the sync block cache. + virtual + void SyncBlockCachePromotionsGranted(int max_gen) = 0; + + // Queries whether or not the given thread has preemptive GC disabled. + virtual + bool IsPreemptiveGCDisabled(Thread * pThread) = 0; + + // Enables preemptive GC on the given thread. + virtual + void EnablePreemptiveGC(Thread * pThread) = 0; + + // Disables preemptive GC on the given thread. + virtual + void DisablePreemptiveGC(Thread * pThread) = 0; + + // Retrieves the alloc context associated with a given thread. + virtual + gc_alloc_context * GetAllocContext(Thread * pThread) = 0; + + // Returns true if this thread is waiting to reach a safe point. + virtual + bool CatchAtSafePoint(Thread * pThread) = 0; + + // Calls the given enum_alloc_context_func with every active alloc context. + virtual + void GcEnumAllocContexts(enum_alloc_context_func* fn, void* param) = 0; + + // Creates and returns a new background thread. + virtual + Thread* CreateBackgroundThread(GCBackgroundThreadFunction threadStart, void* arg) = 0; + + // When a GC starts, gives the diagnostics code a chance to run. + virtual + void DiagGCStart(int gen, bool isInduced) = 0; + + // When GC heap segments change, gives the diagnostics code a chance to run. + virtual + void DiagUpdateGenerationBounds() = 0; + + // When a GC ends, gives the diagnostics code a chance to run. + virtual + void DiagGCEnd(size_t index, int gen, int reason, bool fConcurrent) = 0; + + // During a GC after we discover what objects' finalizers should run, gives the diagnostics code a chance to run. + virtual + void DiagWalkFReachableObjects(void* gcContext) = 0; + + // During a GC after we discover the survivors and the relocation info, + // gives the diagnostics code a chance to run. This includes LOH if we are + // compacting LOH. + virtual + void DiagWalkSurvivors(void* gcContext) = 0; + + // During a full GC after we discover what objects to survive on LOH, + // gives the diagnostics code a chance to run. + virtual + void DiagWalkLOHSurvivors(void* gcContext) = 0; + + // At the end of a background GC, gives the diagnostics code a chance to run. + virtual + void DiagWalkBGCSurvivors(void* gcContext) = 0; + + // Informs the EE of changes to the location of the card table, potentially updating the write + // barrier if it needs to be updated. + virtual + void StompWriteBarrier(WriteBarrierParameters* args) = 0; +}; + +#endif // _GCINTERFACE_EE_H_ diff --git a/src/gc/gcinterface.h b/src/gc/gcinterface.h new file mode 100644 index 0000000..1457848 --- /dev/null +++ b/src/gc/gcinterface.h @@ -0,0 +1,622 @@ +// 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. + +#ifndef _GC_INTERFACE_H_ +#define _GC_INTERFACE_H_ + +struct ScanContext; +struct gc_alloc_context; +class CrawlFrame; + +// Callback passed to GcScanRoots. +typedef void promote_func(PTR_PTR_Object, ScanContext*, uint32_t); + +// Callback passed to GcEnumAllocContexts. +typedef void enum_alloc_context_func(gc_alloc_context*, void*); + +// Callback passed to CreateBackgroundThread. +typedef uint32_t (__stdcall *GCBackgroundThreadFunction)(void* param); + +// Struct often used as a parameter to callbacks. +typedef struct +{ + promote_func* f; + ScanContext* sc; + CrawlFrame * cf; +} GCCONTEXT; + +// SUSPEND_REASON is the reason why the GC wishes to suspend the EE, +// used as an argument to IGCToCLR::SuspendEE. +typedef enum +{ + SUSPEND_FOR_GC = 1, + SUSPEND_FOR_GC_PREP = 6 +} SUSPEND_REASON; + +typedef enum +{ + walk_for_gc = 1, + walk_for_bgc = 2, + walk_for_loh = 3 +} walk_surv_type; + +// Different operations that can be done by GCToEEInterface::StompWriteBarrier +enum class WriteBarrierOp +{ + StompResize, + StompEphemeral, + Initialize +}; + +// Arguments to GCToEEInterface::StompWriteBarrier +struct WriteBarrierParameters +{ + // The operation that StompWriteBarrier will perform. + WriteBarrierOp operation; + + // Whether or not the runtime is currently suspended. If it is not, + // the EE will need to suspend it before bashing the write barrier. + // Used for all operations. + bool is_runtime_suspended; + + // Whether or not the GC has moved the ephemeral generation to no longer + // be at the top of the heap. When the ephemeral generation is at the top + // of the heap, and the write barrier observes that a pointer is greater than + // g_ephemeral_low, it does not need to check that the pointer is less than + // g_ephemeral_high because there is nothing in the GC heap above the ephemeral + // generation. When this is not the case, however, the GC must inform the EE + // so that the EE can switch to a write barrier that checks that a pointer + // is both greater than g_ephemeral_low and less than g_ephemeral_high. + // Used for WriteBarrierOp::StompResize. + bool requires_upper_bounds_check; + + // The new card table location. May or may not be the same as the previous + // card table. Used for WriteBarrierOp::Initialize and WriteBarrierOp::StompResize. + uint32_t* card_table; + + // The heap's new low boundary. May or may not be the same as the previous + // value. Used for WriteBarrierOp::Initialize and WriteBarrierOp::StompResize. + uint8_t* lowest_address; + + // The heap's new high boundary. May or may not be the same as the previous + // value. Used for WriteBarrierOp::Initialize and WriteBarrierOp::StompResize. + uint8_t* highest_address; + + // The new start of the ephemeral generation. + // Used for WriteBarrierOp::StompEphemeral. + uint8_t* ephemeral_lo; + + // The new end of the ephemeral generation. + // Used for WriteBarrierOp::StompEphemeral. + uint8_t* ephemeral_hi; +}; + +#include "gcinterface.ee.h" + +// The allocation context must be known to the VM for use in the allocation +// fast path and known to the GC for performing the allocation. Every Thread +// has its own allocation context that it hands to the GC when allocating. +struct gc_alloc_context +{ + uint8_t* alloc_ptr; + uint8_t* alloc_limit; + int64_t alloc_bytes; //Number of bytes allocated on SOH by this context + int64_t alloc_bytes_loh; //Number of bytes allocated on LOH by this context + // These two fields are deliberately not exposed past the EE-GC interface. + void* gc_reserved_1; + void* gc_reserved_2; + int alloc_count; +public: + + void init() + { + LIMITED_METHOD_CONTRACT; + + alloc_ptr = 0; + alloc_limit = 0; + alloc_bytes = 0; + alloc_bytes_loh = 0; + gc_reserved_1 = 0; + gc_reserved_2 = 0; + alloc_count = 0; + } +}; + +// stub type to abstract a heap segment +struct gc_heap_segment_stub; +typedef gc_heap_segment_stub *segment_handle; + +struct segment_info +{ + void * pvMem; // base of the allocation, not the first object (must add ibFirstObject) + size_t ibFirstObject; // offset to the base of the first object in the segment + size_t ibAllocated; // limit of allocated memory in the segment (>= firstobject) + size_t ibCommit; // limit of committed memory in the segment (>= alllocated) + size_t ibReserved; // limit of reserved memory in the segment (>= commit) +}; + +#ifdef PROFILING_SUPPORTED +#define GC_PROFILING //Turn on profiling +#endif // PROFILING_SUPPORTED + +#define LARGE_OBJECT_SIZE ((size_t)(85000)) + +// The minimum size of an object is three pointers wide: one for the syncblock, +// one for the object header, and one for the first field in the object. +#define min_obj_size ((sizeof(uint8_t*) + sizeof(uintptr_t) + sizeof(size_t))) + +#define max_generation 2 + +class Object; +class IGCHeap; + +// Initializes the garbage collector. Should only be called +// once, during EE startup. +IGCHeap* InitializeGarbageCollector(IGCToCLR* clrToGC); + +// The runtime needs to know whether we're using workstation or server GC +// long before the GCHeap is created. This function sets the type of +// heap that will be created, before InitializeGarbageCollector is called +// and the heap is actually recated. +void InitializeHeapType(bool bServerHeap); + +#ifdef WRITE_BARRIER_CHECK +//always defined, but should be 0 in Server GC +extern uint8_t* g_GCShadow; +extern uint8_t* g_GCShadowEnd; +// saves the g_lowest_address in between GCs to verify the consistency of the shadow segment +extern uint8_t* g_shadow_lowest_address; +#endif + +// For low memory notification from host +extern int32_t g_bLowMemoryFromHost; + +extern VOLATILE(int32_t) m_GCLock; + +// !!!!!!!!!!!!!!!!!!!!!!! +// make sure you change the def in bcl\system\gc.cs +// if you change this! +enum collection_mode +{ + collection_non_blocking = 0x00000001, + collection_blocking = 0x00000002, + collection_optimized = 0x00000004, + collection_compacting = 0x00000008 +#ifdef STRESS_HEAP + , collection_gcstress = 0x80000000 +#endif // STRESS_HEAP +}; + +// !!!!!!!!!!!!!!!!!!!!!!! +// make sure you change the def in bcl\system\gc.cs +// if you change this! +enum wait_full_gc_status +{ + wait_full_gc_success = 0, + wait_full_gc_failed = 1, + wait_full_gc_cancelled = 2, + wait_full_gc_timeout = 3, + wait_full_gc_na = 4 +}; + +// !!!!!!!!!!!!!!!!!!!!!!! +// make sure you change the def in bcl\system\gc.cs +// if you change this! +enum start_no_gc_region_status +{ + start_no_gc_success = 0, + start_no_gc_no_memory = 1, + start_no_gc_too_large = 2, + start_no_gc_in_progress = 3 +}; + +enum end_no_gc_region_status +{ + end_no_gc_success = 0, + end_no_gc_not_in_progress = 1, + end_no_gc_induced = 2, + end_no_gc_alloc_exceeded = 3 +}; + +typedef BOOL (* walk_fn)(Object*, void*); +typedef void (* gen_walk_fn)(void* context, int generation, uint8_t* range_start, uint8_t* range_end, uint8_t* range_reserved); +typedef void (* record_surv_fn)(uint8_t* begin, uint8_t* end, ptrdiff_t reloc, size_t context, BOOL compacting_p, BOOL bgc_p); +typedef void (* fq_walk_fn)(BOOL, void*); +typedef void (* fq_scan_fn)(Object** ppObject, ScanContext *pSC, uint32_t dwFlags); +typedef void (* handle_scan_fn)(Object** pRef, Object* pSec, uint32_t flags, ScanContext* context, BOOL isDependent); + +// IGCHeap is the interface that the VM will use when interacting with the GC. +class IGCHeap { +public: + /* + =========================================================================== + Hosting APIs. These are used by GC hosting. The code that + calls these methods may possibly be moved behind the interface - + today, the VM handles the setting of segment size and max gen 0 size. + (See src/vm/corehost.cpp) + =========================================================================== + */ + + // Returns whether or not the given size is a valid segment size. + virtual BOOL IsValidSegmentSize(size_t size) = 0; + + // Returns whether or not the given size is a valid gen 0 max size. + virtual BOOL IsValidGen0MaxSize(size_t size) = 0; + + // Gets a valid segment size. + virtual size_t GetValidSegmentSize(BOOL large_seg = FALSE) = 0; + + // Sets the limit for reserved virtual memory. + virtual void SetReservedVMLimit(size_t vmlimit) = 0; + + /* + =========================================================================== + Concurrent GC routines. These are used in various places in the VM + to synchronize with the GC, when the VM wants to update something that + the GC is potentially using, if it's doing a background GC. + + Concrete examples of this are moving async pinned handles across appdomains + and profiling/ETW scenarios. + =========================================================================== + */ + + // Blocks until any running concurrent GCs complete. + virtual void WaitUntilConcurrentGCComplete() = 0; + + // Returns true if a concurrent GC is in progress, false otherwise. + virtual BOOL IsConcurrentGCInProgress() = 0; + + // Temporarily enables concurrent GC, used during profiling. + virtual void TemporaryEnableConcurrentGC() = 0; + + // Temporarily disables concurrent GC, used during profiling. + virtual void TemporaryDisableConcurrentGC() = 0; + + // Returns whether or not Concurrent GC is enabled. + virtual BOOL IsConcurrentGCEnabled() = 0; + + // Wait for a concurrent GC to complete if one is in progress, with the given timeout. + virtual HRESULT WaitUntilConcurrentGCCompleteAsync(int millisecondsTimeout) = 0; // Use in native threads. TRUE if succeed. FALSE if failed or timeout + + + /* + =========================================================================== + Finalization routines. These are used by the finalizer thread to communicate + with the GC. + =========================================================================== + */ + + // Finalizes an app domain by finalizing objects within that app domain. + virtual BOOL FinalizeAppDomain(AppDomain* pDomain, BOOL fRunFinalizers) = 0; + + // Finalizes all registered objects for shutdown, even if they are still reachable. + virtual void SetFinalizeQueueForShutdown(BOOL fHasLock) = 0; + + // Gets the number of finalizable objects. + virtual size_t GetNumberOfFinalizable() = 0; + + // Traditionally used by the finalizer thread on shutdown to determine + // whether or not to time out. Returns true if the GC lock has not been taken. + virtual BOOL ShouldRestartFinalizerWatchDog() = 0; + + // Gets the next finalizable object. + virtual Object* GetNextFinalizable() = 0; + + /* + =========================================================================== + BCL routines. These are routines that are directly exposed by mscorlib + as a part of the `System.GC` class. These routines behave in the same + manner as the functions on `System.GC`. + =========================================================================== + */ + + // Gets the current GC latency mode. + virtual int GetGcLatencyMode() = 0; + + // Sets the current GC latency mode. newLatencyMode has already been + // verified by mscorlib to be valid. + virtual int SetGcLatencyMode(int newLatencyMode) = 0; + + // Gets the current LOH compaction mode. + virtual int GetLOHCompactionMode() = 0; + + // Sets the current LOH compaction mode. newLOHCompactionMode has + // already been verified by mscorlib to be valid. + virtual void SetLOHCompactionMode(int newLOHCompactionMode) = 0; + + // Registers for a full GC notification, raising a notification if the gen 2 or + // LOH object heap thresholds are exceeded. + virtual BOOL RegisterForFullGCNotification(uint32_t gen2Percentage, uint32_t lohPercentage) = 0; + + // Cancels a full GC notification that was requested by `RegisterForFullGCNotification`. + virtual BOOL CancelFullGCNotification() = 0; + + // Returns the status of a registered notification for determining whether a blocking + // Gen 2 collection is about to be initiated, with the given timeout. + virtual int WaitForFullGCApproach(int millisecondsTimeout) = 0; + + // Returns the status of a registered notification for determining whether a blocking + // Gen 2 collection has completed, with the given timeout. + virtual int WaitForFullGCComplete(int millisecondsTimeout) = 0; + + // Returns the generation in which obj is found. Also used by the VM + // in some places, in particular syncblk code. + virtual unsigned WhichGeneration(Object* obj) = 0; + + // Returns the number of GCs that have transpired in the given generation + // since the beginning of the life of the process. Also used by the VM + // for debug code and app domains. + virtual int CollectionCount(int generation, int get_bgc_fgc_coutn = 0) = 0; + + // Begins a no-GC region, returning a code indicating whether entering the no-GC + // region was successful. + virtual int StartNoGCRegion(uint64_t totalSize, BOOL lohSizeKnown, uint64_t lohSize, BOOL disallowFullBlockingGC) = 0; + + // Exits a no-GC region. + virtual int EndNoGCRegion() = 0; + + // Gets the total number of bytes in use. + virtual size_t GetTotalBytesInUse() = 0; + + // Forces a garbage collection of the given generation. Also used extensively + // throughout the VM. + virtual HRESULT GarbageCollect(int generation = -1, BOOL low_memory_p = FALSE, int mode = collection_blocking) = 0; + + // Gets the largest GC generation. Also used extensively throughout the VM. + virtual unsigned GetMaxGeneration() = 0; + + // Indicates that an object's finalizer should not be run upon the object's collection. + virtual void SetFinalizationRun(Object* obj) = 0; + + // Indicates that an object's finalizer should be run upon the object's collection. + virtual bool RegisterForFinalization(int gen, Object* obj) = 0; + + /* + =========================================================================== + Miscellaneous routines used by the VM. + =========================================================================== + */ + + // Initializes the GC heap, returning whether or not the initialization + // was successful. + virtual HRESULT Initialize() = 0; + + // Returns whether nor this GC was promoted by the last GC. + virtual BOOL IsPromoted(Object* object) = 0; + + // Returns true if this pointer points into a GC heap, false otherwise. + virtual BOOL IsHeapPointer(void* object, BOOL small_heap_only = FALSE) = 0; + + // Return the generation that has been condemned by the current GC. + virtual unsigned GetCondemnedGeneration() = 0; + + // Returns whether or not a GC is in progress. + virtual BOOL IsGCInProgressHelper(BOOL bConsiderGCStart = FALSE) = 0; + + // Returns the number of GCs that have occured. Mainly used for + // sanity checks asserting that a GC has not occured. + virtual unsigned GetGcCount() = 0; + + // Sets cards after an object has been memmoved. + virtual void SetCardsAfterBulkCopy(Object** obj, size_t length) = 0; + + // Gets whether or not the home heap of this alloc context matches the heap + // associated with this thread. + virtual bool IsThreadUsingAllocationContextHeap(gc_alloc_context* acontext, int thread_number) = 0; + + // Returns whether or not this object resides in an ephemeral generation. + virtual BOOL IsEphemeral(Object* object) = 0; + + // Blocks until a GC is complete, returning a code indicating the wait was successful. + virtual uint32_t WaitUntilGCComplete(BOOL bConsiderGCStart = FALSE) = 0; + + // "Fixes" an allocation context by binding its allocation pointer to a + // location on the heap. + virtual void FixAllocContext(gc_alloc_context* acontext, BOOL lockp, void* arg, void* heap) = 0; + + // Gets the total survived size plus the total allocated bytes on the heap. + virtual size_t GetCurrentObjSize() = 0; + + // Sets whether or not a GC is in progress. + virtual void SetGCInProgress(BOOL fInProgress) = 0; + + /* + ============================================================================ + Add/RemoveMemoryPressure support routines. These are on the interface + for now, but we should move Add/RemoveMemoryPressure from the VM to the GC. + When that occurs, these three routines can be removed from the interface. + ============================================================================ + */ + + // Get the timestamp corresponding to the last GC that occured for the + // given generation. + virtual size_t GetLastGCStartTime(int generation) = 0; + + // Gets the duration of the last GC that occured for the given generation. + virtual size_t GetLastGCDuration(int generation) = 0; + + // Gets a timestamp for the current moment in time. + virtual size_t GetNow() = 0; + + /* + =========================================================================== + Allocation routines. These all call into the GC's allocator and may trigger a garbage + collection. All allocation routines return NULL when the allocation request + couldn't be serviced due to being out of memory. + =========================================================================== + */ + + // Allocates an object on the given allocation context with the given size and flags. + virtual Object* Alloc(gc_alloc_context* acontext, size_t size, uint32_t flags) = 0; + + // Allocates an object on the default allocation context with the given size and flags. + virtual Object* Alloc(size_t size, uint32_t flags) = 0; + + // Allocates an object on the large object heap with the given size and flags. + virtual Object* AllocLHeap(size_t size, uint32_t flags) = 0; + + // Allocates an object on the default allocation context, aligned to 64 bits, + // with the given size and flags. + virtual Object* AllocAlign8 (size_t size, uint32_t flags) = 0; + + // Allocates an object on the given allocation context, aligned to 64 bits, + // with the given size and flags. + virtual Object* AllocAlign8 (gc_alloc_context* acontext, size_t size, uint32_t flags) = 0; + + // This is for the allocator to indicate it's done allocating a large object during a + // background GC as the BGC threads also need to walk LOH. + virtual void PublishObject(uint8_t* obj) = 0; + + // Gets the event that suspended threads will use to wait for the + // end of a GC. + virtual CLREventStatic* GetWaitForGCEvent() = 0; + + /* + =========================================================================== + Heap verification routines. These are used during heap verification only. + =========================================================================== + */ + // Returns whether or not this object is in the fixed heap. + virtual BOOL IsObjectInFixedHeap(Object* pObj) = 0; + + // Walks an object and validates its members. + virtual void ValidateObjectMember(Object* obj) = 0; + + // Retrieves the next object after the given object. When the EE + // is not suspended, the result is not accurate - if the input argument + // is in Gen0, the function could return zeroed out memory as the next object. + virtual Object* NextObj(Object* object) = 0; + + // Given an interior pointer, return a pointer to the object + // containing that pointer. This is safe to call only when the EE is suspended. + virtual Object* GetContainingObject(void* pInteriorPtr) = 0; + + /* + =========================================================================== + Profiling routines. Used for event tracing and profiling to broadcast + information regarding the heap. + =========================================================================== + */ + + // Walks an object, invoking a callback on each member. + virtual void DiagWalkObject(Object* obj, walk_fn fn, void* context) = 0; + + // Walk the heap object by object. + virtual void DiagWalkHeap(walk_fn fn, void* context, int gen_number, BOOL walk_large_object_heap_p) = 0; + + // Walks the survivors and get the relocation information if objects have moved. + virtual void DiagWalkSurvivorsWithType(void* gc_context, record_surv_fn fn, size_t diag_context, walk_surv_type type) = 0; + + // Walks the finalization queue. + virtual void DiagWalkFinalizeQueue(void* gc_context, fq_walk_fn fn) = 0; + + // Scan roots on finalizer queue. This is a generic function. + virtual void DiagScanFinalizeQueue(fq_scan_fn fn, ScanContext* context) = 0; + + // Scan handles for profiling or ETW. + virtual void DiagScanHandles(handle_scan_fn fn, int gen_number, ScanContext* context) = 0; + + // Scan dependent handles for profiling or ETW. + virtual void DiagScanDependentHandles(handle_scan_fn fn, int gen_number, ScanContext* context) = 0; + + // Describes all generations to the profiler, invoking a callback on each generation. + virtual void DiagDescrGenerations(gen_walk_fn fn, void* context) = 0; + + // Traces all GC segments and fires ETW events with information on them. + virtual void DiagTraceGCSegments() = 0; + + /* + =========================================================================== + GC Stress routines. Used only when running under GC Stress. + =========================================================================== + */ + + // Returns TRUE if GC actually happens, otherwise FALSE + virtual BOOL StressHeap(gc_alloc_context* acontext = 0) = 0; + + /* + =========================================================================== + Routines to register read only segments for frozen objects. + Only valid if FEATURE_BASICFREEZE is defined. + =========================================================================== + */ + + // Registers a frozen segment with the GC. + virtual segment_handle RegisterFrozenSegment(segment_info *pseginfo) = 0; + + // Unregisters a frozen segment. + virtual void UnregisterFrozenSegment(segment_handle seg) = 0; + + IGCHeap() {} + virtual ~IGCHeap() {} + + typedef enum + { + GC_HEAP_INVALID = 0, + GC_HEAP_WKS = 1, + GC_HEAP_SVR = 2 + } GC_HEAP_TYPE; + +#ifdef FEATURE_SVR_GC + SVAL_DECL(uint32_t, gcHeapType); +#endif + + SVAL_DECL(uint32_t, maxGeneration); +}; + +#ifdef WRITE_BARRIER_CHECK +void updateGCShadow(Object** ptr, Object* val); +#endif + +//constants for the flags parameter to the gc call back + +#define GC_CALL_INTERIOR 0x1 +#define GC_CALL_PINNED 0x2 +#define GC_CALL_CHECK_APP_DOMAIN 0x4 + +//flags for IGCHeapAlloc(...) +#define GC_ALLOC_FINALIZE 0x1 +#define GC_ALLOC_CONTAINS_REF 0x2 +#define GC_ALLOC_ALIGN8_BIAS 0x4 +#define GC_ALLOC_ALIGN8 0x8 + +struct ScanContext +{ + Thread* thread_under_crawl; + int thread_number; + uintptr_t stack_limit; // Lowest point on the thread stack that the scanning logic is permitted to read + BOOL promotion; //TRUE: Promotion, FALSE: Relocation. + BOOL concurrent; //TRUE: concurrent scanning +#if CHECK_APP_DOMAIN_LEAKS || defined (FEATURE_APPDOMAIN_RESOURCE_MONITORING) || defined (DACCESS_COMPILE) + AppDomain *pCurrentDomain; +#endif //CHECK_APP_DOMAIN_LEAKS || FEATURE_APPDOMAIN_RESOURCE_MONITORING || DACCESS_COMPILE + +#ifndef FEATURE_REDHAWK +#if defined(GC_PROFILING) || defined (DACCESS_COMPILE) + MethodDesc *pMD; +#endif //GC_PROFILING || DACCESS_COMPILE +#endif // FEATURE_REDHAWK +#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) + EtwGCRootKind dwEtwRootKind; +#endif // GC_PROFILING || FEATURE_EVENT_TRACE + + ScanContext() + { + LIMITED_METHOD_CONTRACT; + + thread_under_crawl = 0; + thread_number = -1; + stack_limit = 0; + promotion = FALSE; + concurrent = FALSE; +#ifdef GC_PROFILING + pMD = NULL; +#endif //GC_PROFILING +#ifdef FEATURE_EVENT_TRACE + dwEtwRootKind = kEtwGCRootKindOther; +#endif // FEATURE_EVENT_TRACE + } +}; + +#endif // _GC_INTERFACE_H_ diff --git a/src/gc/gcpriv.h b/src/gc/gcpriv.h index 03a2345..3bed8c2 100644 --- a/src/gc/gcpriv.h +++ b/src/gc/gcpriv.h @@ -24,7 +24,9 @@ inline void FATAL_GC_ERROR() { +#ifndef DACCESS_COMPILE GCToOSInterface::DebugBreak(); +#endif // DACCESS_COMPILE _ASSERTE(!"Fatal Error in GC."); EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); } @@ -1073,9 +1075,6 @@ enum interesting_data_point }; //class definition of the internal class -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) -extern void GCProfileWalkHeapWorker(BOOL fProfilerPinned, BOOL fShouldWalkHeapRootsForEtw, BOOL fShouldWalkHeapObjectsForEtw); -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) class gc_heap { friend struct ::_DacGlobals; @@ -1225,7 +1224,7 @@ public: static gc_heap* balance_heaps_loh (alloc_context* acontext, size_t size); static - void __stdcall gc_thread_stub (void* arg); + void gc_thread_stub (void* arg); #endif //MULTIPLE_HEAPS CObjectHeader* try_fast_alloc (size_t jsize); @@ -1283,35 +1282,48 @@ public: protected: - PER_HEAP + PER_HEAP_ISOLATED void walk_heap (walk_fn fn, void* context, int gen_number, BOOL walk_large_object_heap_p); + PER_HEAP + void walk_heap_per_heap (walk_fn fn, void* context, int gen_number, BOOL walk_large_object_heap_p); + struct walk_relocate_args { uint8_t* last_plug; BOOL is_shortened; mark* pinned_plug_entry; + size_t profiling_context; + record_surv_fn fn; }; PER_HEAP + void walk_survivors (record_surv_fn fn, size_t context, walk_surv_type type); + + PER_HEAP void walk_plug (uint8_t* plug, size_t size, BOOL check_last_object_p, - walk_relocate_args* args, size_t profiling_context); + walk_relocate_args* args); PER_HEAP - void walk_relocation (int condemned_gen_number, - uint8_t* first_condemned_address, size_t profiling_context); + void walk_relocation (size_t profiling_context, record_surv_fn fn); PER_HEAP - void walk_relocation_in_brick (uint8_t* tree, walk_relocate_args* args, size_t profiling_context); + void walk_relocation_in_brick (uint8_t* tree, walk_relocate_args* args); -#if defined(BACKGROUND_GC) && defined(FEATURE_EVENT_TRACE) PER_HEAP - void walk_relocation_for_bgc(size_t profiling_context); + void walk_finalize_queue (fq_walk_fn fn); +#if defined(BACKGROUND_GC) && defined(FEATURE_EVENT_TRACE) PER_HEAP - void make_free_lists_for_profiler_for_bgc(); + void walk_survivors_for_bgc (size_t profiling_context, record_surv_fn fn); #endif // defined(BACKGROUND_GC) && defined(FEATURE_EVENT_TRACE) + // used in blocking GCs after plan phase so this walks the plugs. + PER_HEAP + void walk_survivors_relocation (size_t profiling_context, record_surv_fn fn); + PER_HEAP + void walk_survivors_for_loh (size_t profiling_context, record_surv_fn fn); + PER_HEAP int generation_to_condemn (int n, BOOL* blocking_collection_p, @@ -2148,10 +2160,8 @@ protected: PER_HEAP void relocate_in_loh_compact(); -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) PER_HEAP - void walk_relocation_loh (size_t profiling_context); -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) + void walk_relocation_for_loh (size_t profiling_context, record_surv_fn fn); PER_HEAP BOOL loh_enque_pinned_plug (uint8_t* plug, size_t len); @@ -2547,14 +2557,8 @@ protected: PER_HEAP void descr_generations (BOOL begin_gc_p); -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) PER_HEAP_ISOLATED void descr_generations_to_profiler (gen_walk_fn fn, void *context); - PER_HEAP - void record_survived_for_profiler(int condemned_gen_number, uint8_t * first_condemned_address); - PER_HEAP - void notify_profiler_of_surviving_large_objects (); -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) /*------------ Multiple non isolated heaps ----------------*/ #ifdef MULTIPLE_HEAPS @@ -2978,7 +2982,7 @@ protected: PER_HEAP VOLATILE(int) alloc_context_count; #else //MULTIPLE_HEAPS -#define vm_heap ((GCHeap*) g_pGCHeap) +#define vm_heap ((GCHeap*) g_theGCHeap) #define heap_number (0) #endif //MULTIPLE_HEAPS @@ -3763,9 +3767,7 @@ public: Object* GetNextFinalizableObject (BOOL only_non_critical=FALSE); BOOL ScanForFinalization (promote_func* fn, int gen,BOOL mark_only_p, gc_heap* hp); void RelocateFinalizationData (int gen, gc_heap* hp); -#ifdef GC_PROFILING - void WalkFReachableObjects (gc_heap* hp); -#endif //GC_PROFILING + void WalkFReachableObjects (fq_walk_fn fn); void GcScanRoots (promote_func* fn, int hn, ScanContext *pSC); void UpdatePromotedGenerations (int gen, BOOL gen_0_empty_p); size_t GetPromotedCount(); @@ -4073,8 +4075,6 @@ size_t generation_unusable_fragmentation (generation* inst) } #define plug_skew sizeof(ObjHeader) -#define min_obj_size (sizeof(uint8_t*)+plug_skew+sizeof(size_t))//syncblock + vtable+ first field -//Note that this encodes the fact that plug_skew is a multiple of uint8_t*. // We always use USE_PADDING_TAIL when fitting so items on the free list should be // twice the min_obj_size. #define min_free_list (2*min_obj_size) @@ -4319,9 +4319,6 @@ dynamic_data* gc_heap::dynamic_data_of (int gen_number) return &dynamic_data_table [ gen_number ]; } -extern "C" uint8_t* g_ephemeral_low; -extern "C" uint8_t* g_ephemeral_high; - #define card_word_width ((size_t)32) // diff --git a/src/gc/gcrecord.h b/src/gc/gcrecord.h index 8c95ad0..fff1fc5 100644 --- a/src/gc/gcrecord.h +++ b/src/gc/gcrecord.h @@ -13,7 +13,7 @@ Module Name: #ifndef __gc_record_h__ #define __gc_record_h__ -#define max_generation 2 +//#define max_generation 2 // We pack the dynamic tuning for deciding which gen to condemn in a uint32_t. // We assume that 2 bits are enough to represent the generation. diff --git a/src/gc/gcscan.cpp b/src/gc/gcscan.cpp index 42989e0..b4e6352 100644 --- a/src/gc/gcscan.cpp +++ b/src/gc/gcscan.cpp @@ -129,7 +129,7 @@ static void CALLBACK CheckPromoted(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t * /* LOG((LF_GC, LL_INFO100000, LOG_HANDLE_OBJECT_CLASS("Checking referent of Weak-", pObjRef, "to ", *pObjRef))); Object **pRef = (Object **)pObjRef; - if (!GCHeap::GetGCHeap()->IsPromoted(*pRef)) + if (!g_theGCHeap->IsPromoted(*pRef)) { LOG((LF_GC, LL_INFO100, LOG_HANDLE_OBJECT_CLASS("Severing Weak-", pObjRef, "to unreachable ", *pObjRef))); @@ -192,33 +192,32 @@ void GCScan::GcScanHandles (promote_func* fn, int condemned, int max_gen, } } - -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - /* * Scan all handle roots in this 'namespace' for profiling */ -void GCScan::GcScanHandlesForProfilerAndETW (int max_gen, ScanContext* sc) +void GCScan::GcScanHandlesForProfilerAndETW (int max_gen, ScanContext* sc, handle_scan_fn fn) { LIMITED_METHOD_CONTRACT; +#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) LOG((LF_GC|LF_GCROOTS, LL_INFO10, "Profiler Root Scan Phase, Handles\n")); - Ref_ScanPointersForProfilerAndETW(max_gen, (uintptr_t)sc); + Ref_ScanHandlesForProfilerAndETW(max_gen, (uintptr_t)sc, fn); +#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) } /* * Scan dependent handles in this 'namespace' for profiling */ -void GCScan::GcScanDependentHandlesForProfilerAndETW (int max_gen, ProfilingScanContext* sc) +void GCScan::GcScanDependentHandlesForProfilerAndETW (int max_gen, ScanContext* sc, handle_scan_fn fn) { LIMITED_METHOD_CONTRACT; +#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) LOG((LF_GC|LF_GCROOTS, LL_INFO10, "Profiler Root Scan Phase, DependentHandles\n")); - Ref_ScanDependentHandlesForProfilerAndETW(max_gen, sc); -} - + Ref_ScanDependentHandlesForProfilerAndETW(max_gen, sc, fn); #endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) +} void GCScan::GcRuntimeStructuresValid (BOOL bValid) { @@ -240,14 +239,14 @@ void GCScan::GcRuntimeStructuresValid (BOOL bValid) void GCScan::GcDemote (int condemned, int max_gen, ScanContext* sc) { Ref_RejuvenateHandles (condemned, max_gen, (uintptr_t)sc); - if (!GCHeap::IsServerHeap() || sc->thread_number == 0) + if (!IsServerHeap() || sc->thread_number == 0) GCToEEInterface::SyncBlockCacheDemote(max_gen); } void GCScan::GcPromotionsGranted (int condemned, int max_gen, ScanContext* sc) { Ref_AgeHandles(condemned, max_gen, (uintptr_t)sc); - if (!GCHeap::IsServerHeap() || sc->thread_number == 0) + if (!IsServerHeap() || sc->thread_number == 0) GCToEEInterface::SyncBlockCachePromotionsGranted(max_gen); } diff --git a/src/gc/gcscan.h b/src/gc/gcscan.h index 3515b8e..362370f 100644 --- a/src/gc/gcscan.h +++ b/src/gc/gcscan.h @@ -52,10 +52,8 @@ class GCScan static void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); #endif // DACCESS_COMPILE -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - static void GcScanHandlesForProfilerAndETW (int max_gen, ScanContext* sc); - static void GcScanDependentHandlesForProfilerAndETW (int max_gen, ProfilingScanContext* sc); -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) + static void GcScanHandlesForProfilerAndETW (int max_gen, ScanContext* sc, handle_scan_fn fn); + static void GcScanDependentHandlesForProfilerAndETW (int max_gen, ScanContext* sc, handle_scan_fn fn); // scan for dead weak pointers static void GcWeakPtrScan (promote_func* fn, int condemned, int max_gen, ScanContext*sc ); diff --git a/src/gc/handletable.cpp b/src/gc/handletable.cpp index 43b43ff..29ee435 100644 --- a/src/gc/handletable.cpp +++ b/src/gc/handletable.cpp @@ -755,7 +755,7 @@ void HndLogSetEvent(OBJECTHANDLE handle, _UNCHECKED_OBJECTREF value) uint32_t hndType = HandleFetchType(handle); ADIndex appDomainIndex = HndGetHandleADIndex(handle); AppDomain* pAppDomain = SystemDomain::GetAppDomainAtIndex(appDomainIndex); - uint32_t generation = value != 0 ? GCHeap::GetGCHeap()->WhichGeneration(value) : 0; + uint32_t generation = value != 0 ? g_theGCHeap->WhichGeneration(value) : 0; FireEtwSetGCHandle((void*) handle, value, hndType, generation, (int64_t) pAppDomain, GetClrInstanceId()); FireEtwPrvSetGCHandle((void*) handle, value, hndType, generation, (int64_t) pAppDomain, GetClrInstanceId()); @@ -774,14 +774,14 @@ void HndLogSetEvent(OBJECTHANDLE handle, _UNCHECKED_OBJECTREF value) for (size_t i = 0; i < num; i ++) { value = ppObj[i]; - uint32_t generation = value != 0 ? GCHeap::GetGCHeap()->WhichGeneration(value) : 0; + uint32_t generation = value != 0 ? g_theGCHeap->WhichGeneration(value) : 0; FireEtwSetGCHandle(overlapped, value, HNDTYPE_PINNED, generation, (int64_t) pAppDomain, GetClrInstanceId()); } } else { value = OBJECTREF_TO_UNCHECKED_OBJECTREF(overlapped->m_userObject); - uint32_t generation = value != 0 ? GCHeap::GetGCHeap()->WhichGeneration(value) : 0; + uint32_t generation = value != 0 ? g_theGCHeap->WhichGeneration(value) : 0; FireEtwSetGCHandle(overlapped, value, HNDTYPE_PINNED, generation, (int64_t) pAppDomain, GetClrInstanceId()); } } @@ -838,7 +838,7 @@ void HndWriteBarrier(OBJECTHANDLE handle, OBJECTREF objref) if (*pClumpAge != 0) // Perf optimization: if clumpAge is 0, nothing more to do { // find out generation - int generation = GCHeap::GetGCHeap()->WhichGeneration(value); + int generation = g_theGCHeap->WhichGeneration(value); uint32_t uType = HandleFetchType(handle); #ifndef FEATURE_REDHAWK diff --git a/src/gc/handletablecache.cpp b/src/gc/handletablecache.cpp index b2af40c..aaf3370 100644 --- a/src/gc/handletablecache.cpp +++ b/src/gc/handletablecache.cpp @@ -15,6 +15,12 @@ #include "gcenv.h" +#ifdef Sleep // TODO(segilles) +#undef Sleep +#endif // Sleep + +#include "env/gcenv.os.h" + #include "handletablepriv.h" /**************************************************************************** diff --git a/src/gc/handletablecore.cpp b/src/gc/handletablecore.cpp index 5e077de..5776c26 100644 --- a/src/gc/handletablecore.cpp +++ b/src/gc/handletablecore.cpp @@ -14,6 +14,7 @@ #include "common.h" #include "gcenv.h" +#include "gc.h" #ifndef FEATURE_REDHAWK #include "nativeoverlapped.h" @@ -610,7 +611,7 @@ TableSegment *SegmentAlloc(HandleTable *pTable) _ASSERTE(HANDLE_SEGMENT_ALIGNMENT >= HANDLE_SEGMENT_SIZE); _ASSERTE(HANDLE_SEGMENT_ALIGNMENT == 0x10000); - pSegment = (TableSegment *)GCToOSInterface::VirtualReserve(NULL, HANDLE_SEGMENT_SIZE, HANDLE_SEGMENT_ALIGNMENT, VirtualReserveFlags::None); + pSegment = (TableSegment *)GCToOSInterface::VirtualReserve(HANDLE_SEGMENT_SIZE, HANDLE_SEGMENT_ALIGNMENT, VirtualReserveFlags::None); _ASSERTE(((size_t)pSegment % HANDLE_SEGMENT_ALIGNMENT) == 0); // bail out if we couldn't get any memory @@ -1111,13 +1112,13 @@ SLOW_PATH: // we have the lock held but the part we care about (the async table scan) takes the table lock during // a preparation step so we'll be able to complete our segment moves before the async scan has a // chance to interfere with us (or vice versa). - if (GCHeap::GetGCHeap()->IsConcurrentGCInProgress()) + if (g_theGCHeap->IsConcurrentGCInProgress()) { // A concurrent GC is in progress so someone might be scanning our segments asynchronously. // Release the lock, wait for the GC to complete and try again. The order is important; if we wait // before releasing the table lock we can deadlock with an async table scan. ch.Release(); - GCHeap::GetGCHeap()->WaitUntilConcurrentGCComplete(); + g_theGCHeap->WaitUntilConcurrentGCComplete(); continue; } diff --git a/src/gc/handletablescan.cpp b/src/gc/handletablescan.cpp index 863b5a5..86ce62d 100644 --- a/src/gc/handletablescan.cpp +++ b/src/gc/handletablescan.cpp @@ -818,7 +818,7 @@ void BlockResetAgeMapForBlocksWorker(uint32_t *pdwGen, uint32_t dwClumpMask, Sca { if (!HndIsNullOrDestroyedHandle(*pValue)) { - int thisAge = GCHeap::GetGCHeap()->WhichGeneration(*pValue); + int thisAge = g_theGCHeap->WhichGeneration(*pValue); if (minAge > thisAge) minAge = thisAge; @@ -830,7 +830,7 @@ void BlockResetAgeMapForBlocksWorker(uint32_t *pdwGen, uint32_t dwClumpMask, Sca if (pOverlapped->m_userObject != NULL) { Object * pUserObject = OBJECTREFToObject(pOverlapped->m_userObject); - thisAge = GCHeap::GetGCHeap()->WhichGeneration(pUserObject); + thisAge = g_theGCHeap->WhichGeneration(pUserObject); if (minAge > thisAge) minAge = thisAge; if (pOverlapped->m_isArray) @@ -840,7 +840,7 @@ void BlockResetAgeMapForBlocksWorker(uint32_t *pdwGen, uint32_t dwClumpMask, Sca size_t num = pUserArrayObject->GetNumComponents(); for (size_t i = 0; i < num; i ++) { - thisAge = GCHeap::GetGCHeap()->WhichGeneration(pObj[i]); + thisAge = g_theGCHeap->WhichGeneration(pObj[i]); if (minAge > thisAge) minAge = thisAge; } @@ -925,10 +925,10 @@ static void VerifyObjectAndAge(_UNCHECKED_OBJECTREF *pValue, _UNCHECKED_OBJECTRE UNREFERENCED_PARAMETER(pValue); VerifyObject(from, obj); - int thisAge = GCHeap::GetGCHeap()->WhichGeneration(obj); + int thisAge = g_theGCHeap->WhichGeneration(obj); //debugging code - //if (minAge > thisAge && thisAge < GCHeap::GetGCHeap()->GetMaxGeneration()) + //if (minAge > thisAge && thisAge < g_theGCHeap->GetMaxGeneration()) //{ // if ((*pValue) == obj) // printf("Handle (age %u) %p -> %p (age %u)", minAge, pValue, obj, thisAge); @@ -946,7 +946,7 @@ static void VerifyObjectAndAge(_UNCHECKED_OBJECTREF *pValue, _UNCHECKED_OBJECTRE // } //} - if (minAge >= GEN_MAX_AGE || (minAge > thisAge && thisAge < static_cast(GCHeap::GetGCHeap()->GetMaxGeneration()))) + if (minAge >= GEN_MAX_AGE || (minAge > thisAge && thisAge < static_cast(g_theGCHeap->GetMaxGeneration()))) { _ASSERTE(!"Fatal Error in HandleTable."); EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); diff --git a/src/gc/objecthandle.cpp b/src/gc/objecthandle.cpp index 74a8a71..e8eed93 100644 --- a/src/gc/objecthandle.cpp +++ b/src/gc/objecthandle.cpp @@ -95,7 +95,7 @@ void CALLBACK PromoteRefCounted(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pExtra Object *pOldObj = pObj; #endif - if (!HndIsNullOrDestroyedHandle(pObj) && !GCHeap::GetGCHeap()->IsPromoted(pObj)) + if (!HndIsNullOrDestroyedHandle(pObj) && !g_theGCHeap->IsPromoted(pObj)) { if (GCToEEInterface::RefCountedHandleCallbacks(pObj)) { @@ -110,6 +110,21 @@ void CALLBACK PromoteRefCounted(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pExtra } #endif // FEATURE_COMINTEROP || FEATURE_REDHAWK + +// Only used by profiling/ETW. +//---------------------------------------------------------------------------- + +/* + * struct DIAG_DEPSCANINFO + * + * used when tracing dependent handles for profiling/ETW. + */ +struct DIAG_DEPSCANINFO +{ + HANDLESCANPROC pfnTrace; // tracing function to use + uintptr_t pfnProfilingOrETW; +}; + void CALLBACK TraceDependentHandle(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pExtraInfo, uintptr_t lp1, uintptr_t lp2) { WRAPPER_NO_CONTRACT; @@ -122,14 +137,15 @@ void CALLBACK TraceDependentHandle(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pEx // object should also be non-NULL. _ASSERTE(*pExtraInfo == NULL || *pObjRef != NULL); - // lp2 is a HANDLESCANPROC - HANDLESCANPROC pfnTrace = (HANDLESCANPROC) lp2; + struct DIAG_DEPSCANINFO *pInfo = (struct DIAG_DEPSCANINFO*)lp2; + + HANDLESCANPROC pfnTrace = pInfo->pfnTrace; // is the handle's secondary object non-NULL? if ((*pObjRef != NULL) && (*pExtraInfo != 0)) { // yes - call the tracing function for this handle - pfnTrace(pObjRef, NULL, lp1, *pExtraInfo); + pfnTrace(pObjRef, NULL, lp1, (uintptr_t)(pInfo->pfnProfilingOrETW)); } } @@ -186,9 +202,9 @@ void CALLBACK PromoteDependentHandle(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *p ScanContext *sc = (ScanContext*)lp1; DhContext *pDhContext = Ref_GetDependentHandleContext(sc); - if (*pObjRef && GCHeap::GetGCHeap()->IsPromoted(*pPrimaryRef)) + if (*pObjRef && g_theGCHeap->IsPromoted(*pPrimaryRef)) { - if (!GCHeap::GetGCHeap()->IsPromoted(*pSecondaryRef)) + if (!g_theGCHeap->IsPromoted(*pSecondaryRef)) { LOG((LF_GC|LF_ENC, LL_INFO10000, "\tPromoting secondary " LOG_OBJECT_CLASS(*pSecondaryRef))); _ASSERTE(lp2); @@ -221,7 +237,7 @@ void CALLBACK ClearDependentHandle(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pEx LOG((LF_GC|LF_ENC, LL_INFO1000, LOG_HANDLE_OBJECT_CLASS("\tPrimary:\t", pPrimaryRef, "to ", *pPrimaryRef))); LOG((LF_GC|LF_ENC, LL_INFO1000, LOG_HANDLE_OBJECT_CLASS("\tSecondary\t", pSecondaryRef, "to ", *pSecondaryRef))); - if (!GCHeap::GetGCHeap()->IsPromoted(*pPrimaryRef)) + if (!g_theGCHeap->IsPromoted(*pPrimaryRef)) { LOG((LF_GC|LF_ENC, LL_INFO1000, "\tunreachable ", LOG_OBJECT_CLASS(*pPrimaryRef))); LOG((LF_GC|LF_ENC, LL_INFO1000, "\tunreachable ", LOG_OBJECT_CLASS(*pSecondaryRef))); @@ -230,7 +246,7 @@ void CALLBACK ClearDependentHandle(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pEx } else { - _ASSERTE(GCHeap::GetGCHeap()->IsPromoted(*pSecondaryRef)); + _ASSERTE(g_theGCHeap->IsPromoted(*pSecondaryRef)); LOG((LF_GC|LF_ENC, LL_INFO10000, "\tPrimary is reachable " LOG_OBJECT_CLASS(*pPrimaryRef))); LOG((LF_GC|LF_ENC, LL_INFO10000, "\tSecondary is reachable " LOG_OBJECT_CLASS(*pSecondaryRef))); } @@ -330,7 +346,7 @@ void CALLBACK CheckPromoted(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pExtraInfo LOG((LF_GC, LL_INFO100000, LOG_HANDLE_OBJECT_CLASS("Checking referent of Weak-", pObjRef, "to ", *pObjRef))); Object **ppRef = (Object **)pObjRef; - if (!GCHeap::GetGCHeap()->IsPromoted(*ppRef)) + if (!g_theGCHeap->IsPromoted(*ppRef)) { LOG((LF_GC, LL_INFO100, LOG_HANDLE_OBJECT_CLASS("Severing Weak-", pObjRef, "to unreachable ", *pObjRef))); @@ -355,9 +371,9 @@ void CALLBACK CalculateSizedRefSize(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pE ScanContext* sc = (ScanContext *)lp1; promote_func* callback = (promote_func*) lp2; - size_t sizeBegin = GCHeap::GetGCHeap()->GetPromotedBytes(sc->thread_number); + size_t sizeBegin = g_theGCHeap->GetPromotedBytes(sc->thread_number); callback(ppSizedRef, (ScanContext *)lp1, 0); - size_t sizeEnd = GCHeap::GetGCHeap()->GetPromotedBytes(sc->thread_number); + size_t sizeEnd = g_theGCHeap->GetPromotedBytes(sc->thread_number); *pSize = sizeEnd - sizeBegin; } @@ -414,7 +430,7 @@ void CALLBACK ScanPointerForProfilerAndETW(_UNCHECKED_OBJECTREF *pObjRef, uintpt CONTRACTL_END; #endif // FEATURE_REDHAWK UNREFERENCED_PARAMETER(pExtraInfo); - UNREFERENCED_PARAMETER(lp2); + handle_scan_fn fn = (handle_scan_fn)lp2; LOG((LF_GC | LF_CORPROF, LL_INFO100000, LOG_HANDLE_OBJECT_CLASS("Notifying profiler of ", pObjRef, "to ", *pObjRef))); @@ -422,7 +438,7 @@ void CALLBACK ScanPointerForProfilerAndETW(_UNCHECKED_OBJECTREF *pObjRef, uintpt Object **pRef = (Object **)pObjRef; // Get a hold of the heap ID that's tacked onto the end of the scancontext struct. - ProfilingScanContext *pSC = (ProfilingScanContext *)lp1; + ScanContext *pSC = (ScanContext *)lp1; uint32_t rootFlags = 0; BOOL isDependent = FALSE; @@ -487,60 +503,15 @@ void CALLBACK ScanPointerForProfilerAndETW(_UNCHECKED_OBJECTREF *pObjRef, uintpt _UNCHECKED_OBJECTREF pSec = NULL; -#ifdef GC_PROFILING - // Give the profiler the objectref. - if (pSC->fProfilerPinned) + if (isDependent) { - if (!isDependent) - { - BEGIN_PIN_PROFILER(CORProfilerTrackGC()); - g_profControlBlock.pProfInterface->RootReference2( - (uint8_t *)*pRef, - kEtwGCRootKindHandle, - (EtwGCRootFlags)rootFlags, - pRef, - &pSC->pHeapId); - END_PIN_PROFILER(); - } - else - { - BEGIN_PIN_PROFILER(CORProfilerTrackConditionalWeakTableElements()); - pSec = (_UNCHECKED_OBJECTREF)HndGetHandleExtraInfo(handle); - g_profControlBlock.pProfInterface->ConditionalWeakTableElementReference( - (uint8_t*)*pRef, - (uint8_t*)pSec, - pRef, - &pSC->pHeapId); - END_PIN_PROFILER(); - } + pSec = (_UNCHECKED_OBJECTREF)HndGetHandleExtraInfo(handle); } -#endif // GC_PROFILING - -#if defined(FEATURE_EVENT_TRACE) - // Notify ETW of the handle - if (ETW::GCLog::ShouldWalkHeapRootsForEtw()) - { - if (isDependent && (pSec == NULL)) - { - pSec = (_UNCHECKED_OBJECTREF)HndGetHandleExtraInfo(handle); - } - - ETW::GCLog::RootReference( - handle, - *pRef, // object being rooted - pSec, // pSecondaryNodeForDependentHandle - isDependent, - pSC, - 0, // dwGCFlags, - rootFlags); // ETW handle flags - } -#endif // defined(FEATURE_EVENT_TRACE) + fn(pRef, pSec, rootFlags, pSC, isDependent); } #endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) - - /* * Scan callback for updating pointers. * @@ -583,10 +554,10 @@ int getNumberOfSlots() { WRAPPER_NO_CONTRACT; - // when Ref_Initialize called, GCHeap::GetNumberOfHeaps() is still 0, so use #procs as a workaround + // when Ref_Initialize called, IGCHeap::GetNumberOfHeaps() is still 0, so use #procs as a workaround // it is legal since even if later #heaps < #procs we create handles by thread home heap // and just have extra unused slots in HandleTableBuckets, which does not take a lot of space - if (!GCHeap::IsServerHeap()) + if (!IsServerHeap()) return 1; #ifdef FEATURE_REDHAWK @@ -874,7 +845,7 @@ int getSlotNumber(ScanContext* sc) { WRAPPER_NO_CONTRACT; - return (GCHeap::IsServerHeap() ? sc->thread_number : 0); + return (IsServerHeap() ? sc->thread_number : 0); } // - reexpress as complete only like hndtable does now!!! -fmh @@ -1152,7 +1123,7 @@ void Ref_TraceNormalRoots(uint32_t condemned, uint32_t maxgen, ScanContext* sc, // promote objects pointed to by strong handles // during ephemeral GCs we also want to promote the ones pointed to by sizedref handles. uint32_t types[2] = {HNDTYPE_STRONG, HNDTYPE_SIZEDREF}; - uint32_t uTypeCount = (((condemned >= maxgen) && !GCHeap::GetGCHeap()->IsConcurrentGCInProgress()) ? 1 : _countof(types)); + uint32_t uTypeCount = (((condemned >= maxgen) && !g_theGCHeap->IsConcurrentGCInProgress()) ? 1 : _countof(types)); uint32_t flags = (sc->concurrent) ? HNDGCF_ASYNC : HNDGCF_NORMAL; HandleTableMap *walk = &g_HandleTableMap; @@ -1417,13 +1388,15 @@ void Ref_ScanDependentHandlesForRelocation(uint32_t condemned, uint32_t maxgen, /* loop scan version of TraceVariableHandles for single-thread-managed Ref_* functions should be kept in sync with the code above + Only used by profiling/ETW. */ -void TraceDependentHandlesBySingleThread(HANDLESCANPROC pfnTrace, uintptr_t lp1, uint32_t condemned, uint32_t maxgen, uint32_t flags) +void TraceDependentHandlesBySingleThread(HANDLESCANPROC pfnTrace, uintptr_t lp1, uintptr_t lp2, uint32_t condemned, uint32_t maxgen, uint32_t flags) { WRAPPER_NO_CONTRACT; // set up to scan variable handles with the specified mask and trace function uint32_t type = HNDTYPE_DEPENDENT; + struct DIAG_DEPSCANINFO info = { pfnTrace, lp2 }; HandleTableMap *walk = &g_HandleTableMap; while (walk) { @@ -1436,14 +1409,13 @@ void TraceDependentHandlesBySingleThread(HANDLESCANPROC pfnTrace, uintptr_t lp1, HHANDLETABLE hTable = walk->pBuckets[i]->pTable[uCPUindex]; if (hTable) HndScanHandlesForGC(hTable, TraceDependentHandle, - lp1, (uintptr_t)pfnTrace, &type, 1, condemned, maxgen, HNDGCF_EXTRAINFO | flags); + lp1, (uintptr_t)&info, &type, 1, condemned, maxgen, HNDGCF_EXTRAINFO | flags); } } walk = walk->pNext; } } - // We scan handle tables by their buckets (ie, AD index). We could get into the situation where // the AD indices are not very compacted (for example if we have just unloaded ADs and their // indices haven't been reused yet) and we could be scanning them in an unbalanced fashion. @@ -1454,7 +1426,7 @@ void ScanSizedRefByAD(uint32_t maxgen, HANDLESCANPROC scanProc, ScanContext* sc, HandleTableMap *walk = &g_HandleTableMap; uint32_t type = HNDTYPE_SIZEDREF; int uCPUindex = getSlotNumber(sc); - int n_slots = GCHeap::GetGCHeap()->GetNumberOfHeaps(); + int n_slots = g_theGCHeap->GetNumberOfHeaps(); while (walk) { @@ -1574,11 +1546,11 @@ void Ref_UpdatePointers(uint32_t condemned, uint32_t maxgen, ScanContext* sc, Re // @TODO cwb: wait for compelling performance measurements. BOOL bDo = TRUE; - if (GCHeap::IsServerHeap()) + if (IsServerHeap()) { bDo = (Interlocked::Increment(&uCount) == 1); - Interlocked::CompareExchange (&uCount, 0, GCHeap::GetGCHeap()->GetNumberOfHeaps()); - _ASSERTE (uCount <= GCHeap::GetGCHeap()->GetNumberOfHeaps()); + Interlocked::CompareExchange (&uCount, 0, g_theGCHeap->GetNumberOfHeaps()); + _ASSERTE (uCount <= g_theGCHeap->GetNumberOfHeaps()); } if (bDo) @@ -1623,7 +1595,7 @@ void Ref_UpdatePointers(uint32_t condemned, uint32_t maxgen, ScanContext* sc, Re #if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) // Please update this if you change the Ref_UpdatePointers function above. -void Ref_ScanPointersForProfilerAndETW(uint32_t maxgen, uintptr_t lp1) +void Ref_ScanHandlesForProfilerAndETW(uint32_t maxgen, uintptr_t lp1, handle_scan_fn fn) { WRAPPER_NO_CONTRACT; @@ -1662,16 +1634,16 @@ void Ref_ScanPointersForProfilerAndETW(uint32_t maxgen, uintptr_t lp1) { HHANDLETABLE hTable = walk->pBuckets[i]->pTable[uCPUindex]; if (hTable) - HndScanHandlesForGC(hTable, &ScanPointerForProfilerAndETW, lp1, 0, types, _countof(types), maxgen, maxgen, flags); + HndScanHandlesForGC(hTable, &ScanPointerForProfilerAndETW, lp1, (uintptr_t)fn, types, _countof(types), maxgen, maxgen, flags); } walk = walk->pNext; } // update pointers in variable handles whose dynamic type is VHT_WEAK_SHORT, VHT_WEAK_LONG or VHT_STRONG - TraceVariableHandlesBySingleThread(&ScanPointerForProfilerAndETW, lp1, 0, VHT_WEAK_SHORT | VHT_WEAK_LONG | VHT_STRONG, maxgen, maxgen, flags); + TraceVariableHandlesBySingleThread(&ScanPointerForProfilerAndETW, lp1, (uintptr_t)fn, VHT_WEAK_SHORT | VHT_WEAK_LONG | VHT_STRONG, maxgen, maxgen, flags); } -void Ref_ScanDependentHandlesForProfilerAndETW(uint32_t maxgen, ProfilingScanContext * SC) +void Ref_ScanDependentHandlesForProfilerAndETW(uint32_t maxgen, ScanContext * SC, handle_scan_fn fn) { WRAPPER_NO_CONTRACT; @@ -1680,12 +1652,7 @@ void Ref_ScanDependentHandlesForProfilerAndETW(uint32_t maxgen, ProfilingScanCon uint32_t flags = HNDGCF_NORMAL; uintptr_t lp1 = (uintptr_t)SC; - // we'll re-use pHeapId (which was either unused (0) or freed by EndRootReferences2 - // (-1)), so reset it to NULL - _ASSERTE((*((size_t *)(&SC->pHeapId)) == (size_t)(-1)) || - (*((size_t *)(&SC->pHeapId)) == (size_t)(0))); - SC->pHeapId = NULL; - TraceDependentHandlesBySingleThread(&ScanPointerForProfilerAndETW, lp1, maxgen, maxgen, flags); + TraceDependentHandlesBySingleThread(&ScanPointerForProfilerAndETW, lp1, (uintptr_t)fn, maxgen, maxgen, flags); } #endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) @@ -1906,9 +1873,9 @@ int GetCurrentThreadHomeHeapNumber() { WRAPPER_NO_CONTRACT; - if (!GCHeap::IsGCHeapInitialized()) + if (g_theGCHeap == nullptr) return 0; - return GCHeap::GetGCHeap()->GetHomeHeapNumber(); + return g_theGCHeap->GetHomeHeapNumber(); } bool HandleTableBucket::Contains(OBJECTHANDLE handle) @@ -1921,7 +1888,7 @@ bool HandleTableBucket::Contains(OBJECTHANDLE handle) } HHANDLETABLE hTable = HndGetHandleTable(handle); - for (int uCPUindex=0; uCPUindex < GCHeap::GetGCHeap()->GetNumberOfHeaps(); uCPUindex++) + for (int uCPUindex=0; uCPUindex < g_theGCHeap->GetNumberOfHeaps(); uCPUindex++) { if (hTable == this->pTable[uCPUindex]) { diff --git a/src/gc/objecthandle.h b/src/gc/objecthandle.h index 8936526..34c2a0e 100644 --- a/src/gc/objecthandle.h +++ b/src/gc/objecthandle.h @@ -652,7 +652,6 @@ BOOL Ref_ContainHandle(HandleTableBucket *pBucket, OBJECTHANDLE handle); */ struct ScanContext; struct DhContext; -struct ProfilingScanContext; void Ref_BeginSynchronousGC (uint32_t uCondemnedGeneration, uint32_t uMaxGeneration); void Ref_EndSynchronousGC (uint32_t uCondemnedGeneration, uint32_t uMaxGeneration); @@ -672,10 +671,12 @@ void Ref_ScanSizedRefHandles(uint32_t condemned, uint32_t maxgen, ScanContext* s void Ref_ScanPointers(uint32_t condemned, uint32_t maxgen, ScanContext* sc, Ref_promote_func* fn); #endif +typedef void (* handle_scan_fn)(Object** pRef, Object* pSec, uint32_t flags, ScanContext* context, BOOL isDependent); + void Ref_CheckReachable (uint32_t uCondemnedGeneration, uint32_t uMaxGeneration, uintptr_t lp1); void Ref_CheckAlive (uint32_t uCondemnedGeneration, uint32_t uMaxGeneration, uintptr_t lp1); -void Ref_ScanPointersForProfilerAndETW(uint32_t uMaxGeneration, uintptr_t lp1); -void Ref_ScanDependentHandlesForProfilerAndETW(uint32_t uMaxGeneration, ProfilingScanContext * SC); +void Ref_ScanHandlesForProfilerAndETW(uint32_t uMaxGeneration, uintptr_t lp1, handle_scan_fn fn); +void Ref_ScanDependentHandlesForProfilerAndETW(uint32_t uMaxGeneration, ScanContext * SC, handle_scan_fn fn); void Ref_AgeHandles (uint32_t uCondemnedGeneration, uint32_t uMaxGeneration, uintptr_t lp1); void Ref_RejuvenateHandles(uint32_t uCondemnedGeneration, uint32_t uMaxGeneration, uintptr_t lp1); diff --git a/src/gc/sample/CMakeLists.txt b/src/gc/sample/CMakeLists.txt index 572fba3..9552cc5 100644 --- a/src/gc/sample/CMakeLists.txt +++ b/src/gc/sample/CMakeLists.txt @@ -22,11 +22,11 @@ set(SOURCES if(WIN32) list(APPEND SOURCES - gcenv.windows.cpp) + ../gcenv.windows.cpp) add_definitions(-DUNICODE=1) else() list(APPEND SOURCES - gcenv.unix.cpp) + ../gcenv.unix.cpp) endif() _add_executable(gcsample diff --git a/src/gc/sample/GCSample.cpp b/src/gc/sample/GCSample.cpp index 7e07834..664dc38 100644 --- a/src/gc/sample/GCSample.cpp +++ b/src/gc/sample/GCSample.cpp @@ -68,7 +68,7 @@ Object * AllocateObject(MethodTable * pMT) } else { - pObject = GCHeap::GetGCHeap()->Alloc(acontext, size, 0); + pObject = g_theGCHeap->Alloc(acontext, size, 0); if (pObject == NULL) return NULL; } @@ -91,14 +91,14 @@ inline void ErectWriteBarrier(Object ** dst, Object * ref) { // if the dst is outside of the heap (unboxed value classes) then we // simply exit - if (((uint8_t*)dst < g_lowest_address) || ((uint8_t*)dst >= g_highest_address)) + if (((uint8_t*)dst < g_gc_lowest_address) || ((uint8_t*)dst >= g_gc_highest_address)) return; - if((uint8_t*)ref >= g_ephemeral_low && (uint8_t*)ref < g_ephemeral_high) + if((uint8_t*)ref >= g_gc_ephemeral_low && (uint8_t*)ref < g_gc_ephemeral_high) { // volatile is used here to prevent fetch of g_card_table from being reordered // with g_lowest/highest_address check above. See comment in code:gc_heap::grow_brick_card_tables. - uint8_t* pCardByte = (uint8_t *)*(volatile uint8_t **)(&g_card_table) + card_byte((uint8_t *)dst); + uint8_t* pCardByte = (uint8_t *)*(volatile uint8_t **)(&g_gc_card_table) + card_byte((uint8_t *)dst); if(*pCardByte != 0xFF) *pCardByte = 0xFF; } @@ -137,7 +137,7 @@ int __cdecl main(int argc, char* argv[]) // // Initialize GC heap // - GCHeap *pGCHeap = GCHeap::CreateGCHeap(); + IGCHeap *pGCHeap = InitializeGarbageCollector(nullptr); if (!pGCHeap) return -1; diff --git a/src/gc/sample/GCSample.vcxproj b/src/gc/sample/GCSample.vcxproj index b196e1f..1716f46 100644 --- a/src/gc/sample/GCSample.vcxproj +++ b/src/gc/sample/GCSample.vcxproj @@ -84,10 +84,12 @@ - + + NotUsing + @@ -96,8 +98,7 @@ - Create - Create + Create diff --git a/src/gc/sample/GCSample.vcxproj.filters b/src/gc/sample/GCSample.vcxproj.filters index e46c054..f6aacfd 100644 --- a/src/gc/sample/GCSample.vcxproj.filters +++ b/src/gc/sample/GCSample.vcxproj.filters @@ -59,7 +59,7 @@ Source Files - + Source Files diff --git a/src/gc/sample/gcenv.ee.cpp b/src/gc/sample/gcenv.ee.cpp index 330564a..ac227b4 100644 --- a/src/gc/sample/gcenv.ee.cpp +++ b/src/gc/sample/gcenv.ee.cpp @@ -9,6 +9,12 @@ #include "gcenv.h" #include "gc.h" +MethodTable * g_pFreeObjectMethodTable; + +int32_t g_TrapReturningThreads; + +bool g_fFinalizerRunOnShutDown; + EEConfig * g_pConfig; bool CLREventStatic::CreateManualEventNoThrow(bool bInitialState) @@ -129,9 +135,9 @@ void ThreadStore::AttachCurrentThread() g_pThreadList = pThread; } -void GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_REASON reason) +void GCToEEInterface::SuspendEE(SUSPEND_REASON reason) { - GCHeap::GetGCHeap()->SetGCInProgress(TRUE); + g_theGCHeap->SetGCInProgress(TRUE); // TODO: Implement } @@ -140,7 +146,7 @@ void GCToEEInterface::RestartEE(bool bFinishedGC) { // TODO: Implement - GCHeap::GetGCHeap()->SetGCInProgress(FALSE); + g_theGCHeap->SetGCInProgress(FALSE); } void GCToEEInterface::GcScanRoots(promote_func* fn, int condemned, int max_gen, ScanContext* sc) @@ -184,7 +190,7 @@ void GCToEEInterface::DisablePreemptiveGC(Thread * pThread) pThread->DisablePreemptiveGC(); } -alloc_context * GCToEEInterface::GetAllocContext(Thread * pThread) +gc_alloc_context * GCToEEInterface::GetAllocContext(Thread * pThread) { return pThread->GetAllocContext(); } @@ -221,6 +227,38 @@ Thread* GCToEEInterface::CreateBackgroundThread(GCBackgroundThreadFunction threa return NULL; } +void GCToEEInterface::DiagGCStart(int gen, bool isInduced) +{ +} + +void GCToEEInterface::DiagUpdateGenerationBounds() +{ +} + +void GCToEEInterface::DiagGCEnd(size_t index, int gen, int reason, bool fConcurrent) +{ +} + +void GCToEEInterface::DiagWalkFReachableObjects(void* gcContext) +{ +} + +void GCToEEInterface::DiagWalkSurvivors(void* gcContext) +{ +} + +void GCToEEInterface::DiagWalkLOHSurvivors(void* gcContext) +{ +} + +void GCToEEInterface::DiagWalkBGCSurvivors(void* gcContext) +{ +} + +void GCToEEInterface::StompWriteBarrier(WriteBarrierParameters* args) +{ +} + void FinalizerThread::EnableFinalization() { // Signal to finalizer thread that there are objects to finalize @@ -238,14 +276,6 @@ bool IsGCSpecialThread() return false; } -void StompWriteBarrierEphemeral(bool /* isRuntimeSuspended */) -{ -} - -void StompWriteBarrierResize(bool /* isRuntimeSuspended */, bool /*bReqUpperBoundsCheck*/) -{ -} - bool IsGCThread() { return false; diff --git a/src/gc/sample/gcenv.h b/src/gc/sample/gcenv.h index d560789..4505f1a 100644 --- a/src/gc/sample/gcenv.h +++ b/src/gc/sample/gcenv.h @@ -2,6 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +// The sample is to be kept simple, so building the sample +// in tandem with a standalone GC is currently not supported. +#ifdef FEATURE_STANDALONE_GC +#undef FEATURE_STANDALONE_GC +#endif // FEATURE_STANDALONE_GC + #if defined(_DEBUG) #ifndef _DEBUG_IMPL #define _DEBUG_IMPL 1 @@ -17,12 +23,12 @@ #include "gcenv.structs.h" #include "gcenv.base.h" -#include "gcenv.ee.h" #include "gcenv.os.h" #include "gcenv.interlocked.h" #include "gcenv.interlocked.inl" #include "gcenv.object.h" #include "gcenv.sync.h" +#include "gcenv.ee.h" #define MAX_LONGPATH 1024 @@ -64,6 +70,9 @@ #define LOG(x) +#define SVAL_IMPL_INIT(type, cls, var, init) \ + type cls::var = init + // // Thread // @@ -177,8 +186,6 @@ public: int GetGCTrimCommit() const { return 0; } int GetGCLOHCompactionMode() const { return 0; } - bool GetGCAllowVeryLargeObjects() const { return false; } - bool GetGCConservative() const { return true; } }; diff --git a/src/gc/sample/gcenv.unix.cpp b/src/gc/sample/gcenv.unix.cpp deleted file mode 100644 index a5e9e83..0000000 --- a/src/gc/sample/gcenv.unix.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// 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. - -// -// Implementation of the GC environment -// - -#include "common.h" - -#include "gcenv.h" -#include "gc.h" - -// TODO: Implement diff --git a/src/gc/sample/gcenv.windows.cpp b/src/gc/sample/gcenv.windows.cpp deleted file mode 100644 index 76187f2..0000000 --- a/src/gc/sample/gcenv.windows.cpp +++ /dev/null @@ -1,453 +0,0 @@ -// 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. - -// -// Implementation of the GC environment -// - -#include "common.h" - -#include "windows.h" - -#include "gcenv.h" -#include "gc.h" - -MethodTable * g_pFreeObjectMethodTable; - -int32_t g_TrapReturningThreads; - -bool g_fFinalizerRunOnShutDown; - -GCSystemInfo g_SystemInfo; - -static LARGE_INTEGER g_performanceFrequency; - -// Initialize the interface implementation -// Return: -// true if it has succeeded, false if it has failed -bool GCToOSInterface::Initialize() -{ - if (!::QueryPerformanceFrequency(&g_performanceFrequency)) - { - return false; - } - - SYSTEM_INFO systemInfo; - GetSystemInfo(&systemInfo); - - g_SystemInfo.dwNumberOfProcessors = systemInfo.dwNumberOfProcessors; - g_SystemInfo.dwPageSize = systemInfo.dwPageSize; - g_SystemInfo.dwAllocationGranularity = systemInfo.dwAllocationGranularity; - - return true; -} - -// Shutdown the interface implementation -void GCToOSInterface::Shutdown() -{ -} - -// Get numeric id of the current thread if possible on the -// current platform. It is indended for logging purposes only. -// Return: -// Numeric id of the current thread or 0 if the -uint64_t GCToOSInterface::GetCurrentThreadIdForLogging() -{ - return ::GetCurrentThreadId(); -} - -// Get id of the process -// Return: -// Id of the current process -uint32_t GCToOSInterface::GetCurrentProcessId() -{ - return ::GetCurrentProcessId(); -} - -// Set ideal affinity for the current thread -// Parameters: -// affinity - ideal processor affinity for the thread -// Return: -// true if it has succeeded, false if it has failed -bool GCToOSInterface::SetCurrentThreadIdealAffinity(GCThreadAffinity* affinity) -{ - bool success = true; - -#if !defined(FEATURE_CORESYSTEM) - SetThreadIdealProcessor(GetCurrentThread(), (DWORD)affinity->Processor); -#else - PROCESSOR_NUMBER proc; - - if (affinity->Group != -1) - { - proc.Group = (WORD)affinity->Group; - proc.Number = (BYTE)affinity->Processor; - proc.Reserved = 0; - - success = !!SetThreadIdealProcessorEx(GetCurrentThread(), &proc, NULL); - } - else - { - if (GetThreadIdealProcessorEx(GetCurrentThread(), &proc)) - { - proc.Number = affinity->Processor; - success = !!SetThreadIdealProcessorEx(GetCurrentThread(), &proc, NULL); - } - } -#endif - - return success; -} - -// Get the number of the current processor -uint32_t GCToOSInterface::GetCurrentProcessorNumber() -{ - _ASSERTE(GCToOSInterface::CanGetCurrentProcessorNumber()); - return ::GetCurrentProcessorNumber(); -} - -// Check if the OS supports getting current processor number -bool GCToOSInterface::CanGetCurrentProcessorNumber() -{ - return true; -} - -// Flush write buffers of processors that are executing threads of the current process -void GCToOSInterface::FlushProcessWriteBuffers() -{ - ::FlushProcessWriteBuffers(); -} - -// Break into a debugger -void GCToOSInterface::DebugBreak() -{ - ::DebugBreak(); -} - -// Get number of logical processors -uint32_t GCToOSInterface::GetLogicalCpuCount() -{ - return g_SystemInfo.dwNumberOfProcessors; -} - -// Causes the calling thread to sleep for the specified number of milliseconds -// Parameters: -// sleepMSec - time to sleep before switching to another thread -void GCToOSInterface::Sleep(uint32_t sleepMSec) -{ - ::Sleep(sleepMSec); -} - -// Causes the calling thread to yield execution to another thread that is ready to run on the current processor. -// Parameters: -// switchCount - number of times the YieldThread was called in a loop -void GCToOSInterface::YieldThread(uint32_t switchCount) -{ - SwitchToThread(); -} - -// Reserve virtual memory range. -// Parameters: -// address - starting virtual address, it can be NULL to let the function choose the starting address -// size - size of the virtual memory range -// alignment - requested memory alignment -// flags - flags to control special settings like write watching -// Return: -// Starting virtual address of the reserved range -void* GCToOSInterface::VirtualReserve(void* address, size_t size, size_t alignment, uint32_t flags) -{ - DWORD memFlags = (flags & VirtualReserveFlags::WriteWatch) ? (MEM_RESERVE | MEM_WRITE_WATCH) : MEM_RESERVE; - return ::VirtualAlloc(0, size, memFlags, PAGE_READWRITE); -} - -// Release virtual memory range previously reserved using VirtualReserve -// Parameters: -// address - starting virtual address -// size - size of the virtual memory range -// Return: -// true if it has succeeded, false if it has failed -bool GCToOSInterface::VirtualRelease(void* address, size_t size) -{ - UNREFERENCED_PARAMETER(size); - return !!::VirtualFree(address, 0, MEM_RELEASE); -} - -// Commit virtual memory range. It must be part of a range reserved using VirtualReserve. -// Parameters: -// address - starting virtual address -// size - size of the virtual memory range -// Return: -// true if it has succeeded, false if it has failed -bool GCToOSInterface::VirtualCommit(void* address, size_t size) -{ - return ::VirtualAlloc(address, size, MEM_COMMIT, PAGE_READWRITE) != NULL; -} - -// Decomit virtual memory range. -// Parameters: -// address - starting virtual address -// size - size of the virtual memory range -// Return: -// true if it has succeeded, false if it has failed -bool GCToOSInterface::VirtualDecommit(void* address, size_t size) -{ - return !!::VirtualFree(address, size, MEM_DECOMMIT); -} - -// Reset virtual memory range. Indicates that data in the memory range specified by address and size is no -// longer of interest, but it should not be decommitted. -// Parameters: -// address - starting virtual address -// size - size of the virtual memory range -// unlock - true if the memory range should also be unlocked -// Return: -// true if it has succeeded, false if it has failed -bool GCToOSInterface::VirtualReset(void * address, size_t size, bool unlock) -{ - bool success = ::VirtualAlloc(address, size, MEM_RESET, PAGE_READWRITE) != NULL; - if (success && unlock) - { - // Remove the page range from the working set - ::VirtualUnlock(address, size); - } - - return success; -} - -// Check if the OS supports write watching -bool GCToOSInterface::SupportsWriteWatch() -{ - return false; -} - -// Reset the write tracking state for the specified virtual memory range. -// Parameters: -// address - starting virtual address -// size - size of the virtual memory range -void GCToOSInterface::ResetWriteWatch(void* address, size_t size) -{ -} - -// Retrieve addresses of the pages that are written to in a region of virtual memory -// Parameters: -// resetState - true indicates to reset the write tracking state -// address - starting virtual address -// size - size of the virtual memory range -// pageAddresses - buffer that receives an array of page addresses in the memory region -// pageAddressesCount - on input, size of the lpAddresses array, in array elements -// on output, the number of page addresses that are returned in the array. -// Return: -// true if it has succeeded, false if it has failed -bool GCToOSInterface::GetWriteWatch(bool resetState, void* address, size_t size, void** pageAddresses, uintptr_t* pageAddressesCount) -{ - return false; -} - -// Get size of the largest cache on the processor die -// Parameters: -// trueSize - true to return true cache size, false to return scaled up size based on -// the processor architecture -// Return: -// Size of the cache -size_t GCToOSInterface::GetLargestOnDieCacheSize(bool trueSize) -{ - // TODO: implement - return 0; -} - -// Get affinity mask of the current process -// Parameters: -// processMask - affinity mask for the specified process -// systemMask - affinity mask for the system -// Return: -// true if it has succeeded, false if it has failed -// Remarks: -// A process affinity mask is a bit vector in which each bit represents the processors that -// a process is allowed to run on. A system affinity mask is a bit vector in which each bit -// represents the processors that are configured into a system. -// A process affinity mask is a subset of the system affinity mask. A process is only allowed -// to run on the processors configured into a system. Therefore, the process affinity mask cannot -// specify a 1 bit for a processor when the system affinity mask specifies a 0 bit for that processor. -bool GCToOSInterface::GetCurrentProcessAffinityMask(uintptr_t* processMask, uintptr_t* systemMask) -{ - return false; -} - -// Get number of processors assigned to the current process -// Return: -// The number of processors -uint32_t GCToOSInterface::GetCurrentProcessCpuCount() -{ - return g_SystemInfo.dwNumberOfProcessors; -} - -// Return the size of the user-mode portion of the virtual address space of this process. -// Return: -// non zero if it has succeeded, 0 if it has failed -size_t GCToOSInterface::GetVirtualMemoryLimit() -{ - MEMORYSTATUSEX memStatus; - - memStatus.dwLength = sizeof(MEMORYSTATUSEX); - BOOL fRet = GlobalMemoryStatusEx(&memStatus); - _ASSERTE(fRet); - - return (size_t)memStatus.ullTotalVirtual; -} - -// Get the physical memory that this process can use. -// Return: -// non zero if it has succeeded, 0 if it has failed -uint64_t GCToOSInterface::GetPhysicalMemoryLimit() -{ - MEMORYSTATUSEX memStatus; - - memStatus.dwLength = sizeof(MEMORYSTATUSEX); - BOOL fRet = GlobalMemoryStatusEx(&memStatus); - _ASSERTE(fRet); - - return memStatus.ullTotalPhys; -} - -// Get memory status -// Parameters: -// memory_load - A number between 0 and 100 that specifies the approximate percentage of physical memory -// that is in use (0 indicates no memory use and 100 indicates full memory use). -// available_physical - The amount of physical memory currently available, in bytes. -// available_page_file - The maximum amount of memory the current process can commit, in bytes. -void GCToOSInterface::GetMemoryStatus(uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file) -{ - MEMORYSTATUSEX memStatus; - - memStatus.dwLength = sizeof(MEMORYSTATUSEX); - BOOL fRet = GlobalMemoryStatusEx(&memStatus); - _ASSERTE (fRet); - - // If the machine has more RAM than virtual address limit, let us cap it. - // The GC can never use more than virtual address limit. - if (memStatus.ullAvailPhys > memStatus.ullTotalVirtual) - { - memStatus.ullAvailPhys = memStatus.ullAvailVirtual; - } - - if (memory_load != NULL) - *memory_load = memStatus.dwMemoryLoad; - if (available_physical != NULL) - *available_physical = memStatus.ullAvailPhys; - if (available_page_file != NULL) - *available_page_file = memStatus.ullAvailPageFile; -} - -// Get a high precision performance counter -// Return: -// The counter value -int64_t GCToOSInterface::QueryPerformanceCounter() -{ - LARGE_INTEGER ts; - if (!::QueryPerformanceCounter(&ts)) - { - _ASSERTE(!"Fatal Error - cannot query performance counter."); - abort(); - } - - return ts.QuadPart; -} - -// Get a frequency of the high precision performance counter -// Return: -// The counter frequency -int64_t GCToOSInterface::QueryPerformanceFrequency() -{ - return g_performanceFrequency.QuadPart; -} - -// Get a time stamp with a low precision -// Return: -// Time stamp in milliseconds -uint32_t GCToOSInterface::GetLowPrecisionTimeStamp() -{ - return ::GetTickCount(); -} - -// Parameters of the GC thread stub -struct GCThreadStubParam -{ - GCThreadFunction GCThreadFunction; - void* GCThreadParam; -}; - -// GC thread stub to convert GC thread function to an OS specific thread function -static DWORD __stdcall GCThreadStub(void* param) -{ - GCThreadStubParam *stubParam = (GCThreadStubParam*)param; - GCThreadFunction function = stubParam->GCThreadFunction; - void* threadParam = stubParam->GCThreadParam; - - delete stubParam; - - function(threadParam); - - return 0; -} - -// Create a new thread -// Parameters: -// function - the function to be executed by the thread -// param - parameters of the thread -// affinity - processor affinity of the thread -// Return: -// true if it has succeeded, false if it has failed -bool GCToOSInterface::CreateThread(GCThreadFunction function, void* param, GCThreadAffinity* affinity) -{ - DWORD thread_id; - - GCThreadStubParam* stubParam = new (nothrow) GCThreadStubParam(); - if (stubParam == NULL) - { - return false; - } - - stubParam->GCThreadFunction = function; - stubParam->GCThreadParam = param; - - HANDLE gc_thread = ::CreateThread(NULL, 0, GCThreadStub, stubParam, CREATE_SUSPENDED, &thread_id); - - if (!gc_thread) - { - delete stubParam; - return false; - } - - SetThreadPriority(gc_thread, /* THREAD_PRIORITY_ABOVE_NORMAL );*/ THREAD_PRIORITY_HIGHEST ); - - ResumeThread(gc_thread); - - CloseHandle(gc_thread); - - return true; -} - -// Initialize the critical section -void CLRCriticalSection::Initialize() -{ - ::InitializeCriticalSection(&m_cs); -} - -// Destroy the critical section -void CLRCriticalSection::Destroy() -{ - ::DeleteCriticalSection(&m_cs); -} - -// Enter the critical section. Blocks until the section can be entered. -void CLRCriticalSection::Enter() -{ - ::EnterCriticalSection(&m_cs); -} - -// Leave the critical section -void CLRCriticalSection::Leave() -{ - ::LeaveCriticalSection(&m_cs); -} diff --git a/src/gc/softwarewritewatch.cpp b/src/gc/softwarewritewatch.cpp index 5197449..fa14a04 100644 --- a/src/gc/softwarewritewatch.cpp +++ b/src/gc/softwarewritewatch.cpp @@ -6,6 +6,7 @@ #include "softwarewritewatch.h" #include "gcenv.h" +#include "env/gcenv.os.h" #ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP #ifndef DACCESS_COMPILE diff --git a/src/gcdump/gcdump.cpp b/src/gcdump/gcdump.cpp index 1c512c8..c89dd6c 100644 --- a/src/gcdump/gcdump.cpp +++ b/src/gcdump/gcdump.cpp @@ -11,7 +11,9 @@ * to the standard code-manager spec. */ +#ifndef FEATURE_PAL #include "utilcode.h" // For _ASSERTE() +#endif //!FEATURE_PAL #include "gcdump.h" /*****************************************************************************/ diff --git a/src/gcdump/gcdumpnonx86.cpp b/src/gcdump/gcdumpnonx86.cpp index 7343ac9..ca8cc75 100644 --- a/src/gcdump/gcdumpnonx86.cpp +++ b/src/gcdump/gcdumpnonx86.cpp @@ -505,7 +505,7 @@ size_t GCDump::DumpGCTable(PTR_CBYTE gcInfoBlock, /*****************************************************************************/ -void GCDump::DumpPtrsInFrame(PTR_CBYTE infoBlock, +void GCDump::DumpPtrsInFrame(PTR_CBYTE gcInfoBlock, PTR_CBYTE codeBlock, unsigned offs, bool verifyGCTables) @@ -520,7 +520,7 @@ void GCDump::DumpPtrsInFrame(PTR_CBYTE infoBlock, #define LOG(x) ((void)0) #endif -#define GCINFODECODER_CONTRACT(contract) +#define GCINFODECODER_CONTRACT ((void)0) #define GET_CALLER_SP(pREGDISPLAY) ((size_t)GetSP(pREGDISPLAY->pCallerContext)) #define VALIDATE_OBJECTREF(objref, fDeep) ((void)0) #define VALIDATE_ROOT(isInterior, hCallBack, pObjRef) ((void)0) diff --git a/src/gcdump/i386/gcdumpx86.cpp b/src/gcdump/i386/gcdumpx86.cpp index 70334de..23e6c68 100644 --- a/src/gcdump/i386/gcdumpx86.cpp +++ b/src/gcdump/i386/gcdumpx86.cpp @@ -9,7 +9,9 @@ #ifdef _TARGET_X86_ /*****************************************************************************/ +#ifndef FEATURE_PAL #include "utilcode.h" // For _ASSERTE() +#endif //!FEATURE_PAL #include "gcdump.h" @@ -60,12 +62,13 @@ const char * CalleeSavedRegName(unsigned reg) /*****************************************************************************/ -unsigned GCDump::DumpInfoHdr (PTR_CBYTE table, +unsigned GCDump::DumpInfoHdr (PTR_CBYTE gcInfoBlock, InfoHdr* header, unsigned * methodSize, bool verifyGCTables) { unsigned count; + PTR_CBYTE table = gcInfoBlock; PTR_CBYTE tableStart = table; PTR_CBYTE bp = table; @@ -76,7 +79,7 @@ unsigned GCDump::DumpInfoHdr (PTR_CBYTE table, table += decodeUnsigned(table, methodSize); - table = decodeHeader(table, header); + table = decodeHeader(table, gcInfoVersion, header); BOOL hasArgTabOffset = FALSE; if (header->untrackedCnt == HAS_UNTRACKED) @@ -107,6 +110,12 @@ unsigned GCDump::DumpInfoHdr (PTR_CBYTE table, header->syncEndOffset = count; } + if (header->revPInvokeOffset == HAS_REV_PINVOKE_FRAME_OFFSET) + { + table += decodeUnsigned(table, &count); + header->revPInvokeOffset = count; + } + // // First print out all the basic information // @@ -931,12 +940,12 @@ DONE_REGTAB: /*****************************************************************************/ -void GCDump::DumpPtrsInFrame(PTR_CBYTE infoBlock, +void GCDump::DumpPtrsInFrame(PTR_CBYTE gcInfoBlock, PTR_CBYTE codeBlock, unsigned offs, bool verifyGCTables) { - PTR_CBYTE table = infoBlock; + PTR_CBYTE table = gcInfoBlock; size_t methodSize; size_t stackSize; @@ -963,7 +972,7 @@ void GCDump::DumpPtrsInFrame(PTR_CBYTE infoBlock, // Typically only uses one-byte to store everything. // InfoHdr header; - table = decodeHeader(table, &header); + table = decodeHeader(table, gcInfoVersion, &header); if (header.untrackedCnt == HAS_UNTRACKED) { @@ -994,6 +1003,13 @@ void GCDump::DumpPtrsInFrame(PTR_CBYTE infoBlock, header.syncEndOffset = offset; _ASSERTE(offset != INVALID_SYNC_OFFSET); } + if (header.revPInvokeOffset == HAS_REV_PINVOKE_FRAME_OFFSET) + { + unsigned offset; + table += decodeUnsigned(table, &offset); + header.revPInvokeOffset = offset; + _ASSERTE(offset != INVALID_REV_PINVOKE_OFFSET); + } prologSize = header.prologSize; epilogSize = header.epilogSize; diff --git a/src/gcinfo/gcinfoencoder.cpp b/src/gcinfo/gcinfoencoder.cpp index 6785222..15d6ed9 100644 --- a/src/gcinfo/gcinfoencoder.cpp +++ b/src/gcinfo/gcinfoencoder.cpp @@ -343,10 +343,13 @@ GcInfoSize& GcInfoSize::operator+=(const GcInfoSize& other) NumRanges += other.NumRanges; NumRegs += other.NumRegs; NumStack += other.NumStack; - NumEh += other.NumEh; + NumUntracked += other.NumUntracked; NumTransitions += other.NumTransitions; SizeOfCode += other.SizeOfCode; + EncPreservedSlots += other.EncPreservedSlots; + UntrackedSlotSize += other.UntrackedSlotSize; + NumUntrackedSize += other.NumUntrackedSize; FlagsSize += other.FlagsSize; CodeLengthSize += other.CodeLengthSize; ProEpilogSize += other.ProEpilogSize; @@ -366,7 +369,6 @@ GcInfoSize& GcInfoSize::operator+=(const GcInfoSize& other) RegSlotSize += other.RegSlotSize; StackSlotSize += other.StackSlotSize; CallSiteStateSize += other.CallSiteStateSize; - NumEhSize += other.NumEhSize; EhPosSize += other.EhPosSize; EhStateSize += other.EhStateSize; ChunkPtrSize += other.ChunkPtrSize; @@ -389,12 +391,15 @@ void GcInfoSize::Log(DWORD level, const char * header) LogSpew(LF_GCINFO, level, "NumRanges: %Iu\n", NumRanges); LogSpew(LF_GCINFO, level, "NumRegs: %Iu\n", NumRegs); LogSpew(LF_GCINFO, level, "NumStack: %Iu\n", NumStack); - LogSpew(LF_GCINFO, level, "NumEh: %Iu\n", NumEh); + LogSpew(LF_GCINFO, level, "NumUntracked: %Iu\n", NumUntracked); LogSpew(LF_GCINFO, level, "NumTransitions: %Iu\n", NumTransitions); LogSpew(LF_GCINFO, level, "SizeOfCode: %Iu\n", SizeOfCode); + LogSpew(LF_GCINFO, level, "EncPreservedSlots: %Iu\n", EncPreservedSlots); LogSpew(LF_GCINFO, level, "---SIZES(bits)---\n"); LogSpew(LF_GCINFO, level, "Total: %Iu\n", TotalSize); + LogSpew(LF_GCINFO, level, "UntrackedSlot: %Iu\n", UntrackedSlotSize); + LogSpew(LF_GCINFO, level, "NumUntracked: %Iu\n", NumUntrackedSize); LogSpew(LF_GCINFO, level, "Flags: %Iu\n", FlagsSize); LogSpew(LF_GCINFO, level, "CodeLength: %Iu\n", CodeLengthSize); LogSpew(LF_GCINFO, level, "Prolog/Epilog: %Iu\n", ProEpilogSize); @@ -414,7 +419,6 @@ void GcInfoSize::Log(DWORD level, const char * header) LogSpew(LF_GCINFO, level, "RegSlots: %Iu\n", RegSlotSize); LogSpew(LF_GCINFO, level, "StackSlots: %Iu\n", StackSlotSize); LogSpew(LF_GCINFO, level, "CallSiteStates: %Iu\n", CallSiteStateSize); - LogSpew(LF_GCINFO, level, "NumEh: %Iu\n", NumEhSize); LogSpew(LF_GCINFO, level, "EhOffsets: %Iu\n", EhPosSize); LogSpew(LF_GCINFO, level, "EhStates: %Iu\n", EhStateSize); LogSpew(LF_GCINFO, level, "ChunkPointers: %Iu\n", ChunkPtrSize); @@ -426,17 +430,6 @@ void GcInfoSize::Log(DWORD level, const char * header) #endif -#ifndef DISABLE_EH_VECTORS -inline BOOL IsEssential(EE_ILEXCEPTION_CLAUSE *pClause) -{ - _ASSERTE(pClause->TryEndPC >= pClause->TryStartPC); - if(pClause->TryEndPC == pClause->TryStartPC) - return FALSE; - - return TRUE; -} -#endif - GcInfoEncoder::GcInfoEncoder( ICorJitInfo* pCorJitInfo, CORINFO_METHOD_INFO* pMethodInfo, @@ -1170,7 +1163,8 @@ void GcInfoEncoder::Build() int size_tCount = (m_NumSlots + BITS_PER_SIZE_T - 1) / BITS_PER_SIZE_T; BitArray liveState(m_pAllocator, size_tCount); BitArray couldBeLive(m_pAllocator, size_tCount); - + liveState.ClearAll(); + couldBeLive.ClearAll(); #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED _ASSERTE(m_NumCallSites == 0 || m_pCallSites != NULL); @@ -1354,83 +1348,6 @@ void GcInfoEncoder::Build() #endif } - -#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED - /////////////////////////////////////////////////////////////////////// - // Gather EH information - /////////////////////////////////////////////////////////////////////// - - couldBeLive.ClearAll(); - -#ifndef DISABLE_EH_VECTORS - UINT32 numEHClauses; - EE_ILEXCEPTION *pEHInfo = (EE_ILEXCEPTION*) m_pCorJitInfo->getEHInfo(); - if (!pEHInfo) - numEHClauses = 0; - else - numEHClauses = pEHInfo->EHCount(); - - UINT32 numUsedEHClauses = numEHClauses; - for (UINT32 clauseIndex = 0; clauseIndex < numEHClauses; clauseIndex++) - { - EE_ILEXCEPTION_CLAUSE * pClause; - pClause = pEHInfo->EHClause(clauseIndex); - - if(!IsEssential(pClause)) - numUsedEHClauses--; - } - - UINT32 ehTableBitCount = m_NumSlots * numUsedEHClauses; - BitArray ehLiveSlots(m_pAllocator, (ehTableBitCount + BITS_PER_SIZE_T - 1) / BITS_PER_SIZE_T); - ehLiveSlots.ClearAll(); - - UINT32 basePos = 0; - for (UINT32 clauseIndex = 0; clauseIndex < numEHClauses; clauseIndex++) - { - EE_ILEXCEPTION_CLAUSE * pClause; - pClause = pEHInfo->EHClause(clauseIndex); - - _ASSERTE(pClause->TryEndPC <= m_CodeLength); - if(!IsEssential(pClause)) - continue; - - liveState.ClearAll(); - - for(pCurrent = pTransitions; pCurrent < pEndTransitions; pCurrent++) - { - if(pCurrent->CodeOffset > pClause->TryStartPC) - break; - - UINT32 slotIndex = pCurrent->SlotId; - BYTE becomesLive = pCurrent->BecomesLive; - _ASSERTE(liveState.ReadBit(slotIndex) && !becomesLive - || !liveState.ReadBit(slotIndex) && becomesLive); - liveState.WriteBit(slotIndex, becomesLive); - } - - for( ; pCurrent < pEndTransitions; pCurrent++) - { - if(pCurrent->CodeOffset >= pClause->TryEndPC) - break; - - UINT32 slotIndex = pCurrent->SlotId; - liveState.ClearBit(slotIndex); - } - - // Copy to the EH live state table - for(UINT32 i = 0; i < m_NumSlots; i++) - { - if(liveState.ReadBit(i)) - ehLiveSlots.SetBit(basePos + i); - } - basePos += m_NumSlots; - - // Keep track of which slots are used - couldBeLive |= liveState; - } -#endif // DISABLE_EH_VECTORS -#endif // PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED - #if CODE_OFFSETS_NEED_NORMALIZATION // Do a pass to normalize transition offsets for(pCurrent = pTransitions; pCurrent < pEndTransitions; pCurrent++) @@ -1444,6 +1361,7 @@ void GcInfoEncoder::Build() // Find out which slots are really used /////////////////////////////////////////////////////////////////// + couldBeLive.ClearAll(); #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED if(m_NumCallSites) @@ -1994,40 +1912,6 @@ void GcInfoEncoder::Build() #endif // MUST_CALL_JITALLOCATOR_FREE } - - //----------------------------------------------------------------- - // Encode EH clauses and bit vectors - //----------------------------------------------------------------- - -#ifndef DISABLE_EH_VECTORS - GCINFO_WRITE_VARL_U(m_Info1, numUsedEHClauses, NUM_EH_CLAUSES_ENCBASE, NumEhSize); - - basePos = 0; - for(UINT32 clauseIndex = 0; clauseIndex < numEHClauses; clauseIndex++) - { - EE_ILEXCEPTION_CLAUSE * pClause; - pClause = pEHInfo->EHClause(clauseIndex); - - if(!IsEssential(pClause)) - continue; - - UINT32 normStartOffset = NORMALIZE_CODE_OFFSET(pClause->TryStartPC); - UINT32 normStopOffset = NORMALIZE_CODE_OFFSET(pClause->TryEndPC); - _ASSERTE(normStopOffset > normStartOffset); - - GCINFO_WRITE(m_Info1, normStartOffset, numBitsPerOffset, EhPosSize); - GCINFO_WRITE(m_Info1, normStopOffset - 1, numBitsPerOffset, EhPosSize); - - for(UINT slotIndex = 0; slotIndex < m_NumSlots; slotIndex++) - { - if(!m_SlotTable[slotIndex].IsDeleted()) - { - GCINFO_WRITE(m_Info1, ehLiveSlots.ReadBit(basePos + slotIndex) ? 1 : 0, 1, EhStateSize); - } - } - basePos += m_NumSlots; - } -#endif // DISABLE_EH_VECTORS #endif // PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED @@ -2358,11 +2242,6 @@ lExitSuccess:; m_CurrentMethodSize.NumMethods = 1; #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED m_CurrentMethodSize.NumCallSites = m_NumCallSites; -#ifdef DISABLE_EH_VECTORS - m_CurrentMethodSize.NumEh = 0; -#else - m_CurrentMethodSize.NumEh = numUsedEHClauses; -#endif #endif m_CurrentMethodSize.NumRanges = numInterruptibleRanges; m_CurrentMethodSize.NumRegs = numRegisters; diff --git a/src/ilasm/CMakeLists.txt b/src/ilasm/CMakeLists.txt index 34ec799..9e99d02 100644 --- a/src/ilasm/CMakeLists.txt +++ b/src/ilasm/CMakeLists.txt @@ -22,25 +22,23 @@ set(ILASM_SOURCES asmman.cpp main.cpp assembler.cpp - prebuilt/asmparse.c + prebuilt/asmparse.cpp ) if(WIN32) set(ILASM_RESOURCES Native.rc) add_definitions(-DFX_VER_INTERNALNAME_STR=ilasm.exe) endif(WIN32) -set_source_files_properties( prebuilt/asmparse.c PROPERTIES LANGUAGE CXX ) if(CLR_CMAKE_PLATFORM_UNIX) - add_compile_options(-x c++) - # Need generate a right form of asmparse.c to avoid the following options. + # Need generate a right form of asmparse.cpp to avoid the following options. # Clang also produces a bad-codegen on this prebuilt file with optimization. # https://github.com/dotnet/coreclr/issues/2305 add_compile_options(-Wno-delete-non-virtual-dtor) add_compile_options(-Wno-deprecated-register) add_compile_options(-Wno-array-bounds) add_compile_options(-Wno-unused-label) - set_source_files_properties( prebuilt/asmparse.c PROPERTIES COMPILE_FLAGS -O0 ) + set_source_files_properties( prebuilt/asmparse.cpp PROPERTIES COMPILE_FLAGS "-O0" ) endif(CLR_CMAKE_PLATFORM_UNIX) _add_executable(ilasm @@ -82,4 +80,5 @@ else() ) endif(CLR_CMAKE_PLATFORM_UNIX) -install_clr(ilasm) \ No newline at end of file +install_clr(ilasm) + diff --git a/src/ilasm/assembler.cpp b/src/ilasm/assembler.cpp index 690da64..49d4ee9 100644 --- a/src/ilasm/assembler.cpp +++ b/src/ilasm/assembler.cpp @@ -1725,7 +1725,7 @@ void Assembler::EmitInstrBrOffset(Instr* instr, int offset) unsigned opc=instr->opcode; if(m_fOptimize) { - if((-128 >= offset)&&(offset <= 127)) + if((-128 <= offset)&&(offset <= 127)) { opc = instr->opcode = ShortOf(opc); } diff --git a/src/ilasm/main.cpp b/src/ilasm/main.cpp index 811c656..2bef40d 100644 --- a/src/ilasm/main.cpp +++ b/src/ilasm/main.cpp @@ -768,7 +768,7 @@ extern "C" int _cdecl wmain(int argc, __in WCHAR **argv) for(iFile = 0; iFile < NumDeltaFiles; iFile++) { wcscpy_s(wzNewOutputFilename,MAX_FILENAME_LENGTH+16,wzOutputFilename); - exitval = (int)StringCchPrintfW(&wzNewOutputFilename[wcslen(wzNewOutputFilename)], 32, + exitval = _snwprintf_s(&wzNewOutputFilename[wcslen(wzNewOutputFilename)], 32, _TRUNCATE, W(".%d"),iFile+1); MakeProperSourceFileName(pwzDeltaFiles[iFile], uCodePage, wzInputFilename, szInputFilename); if(pAsm->m_fReportProgress) diff --git a/src/ilasm/prebuilt/asmparse.c b/src/ilasm/prebuilt/asmparse.c deleted file mode 100644 index 71b31a5..0000000 --- a/src/ilasm/prebuilt/asmparse.c +++ /dev/null @@ -1,4907 +0,0 @@ -/* - * Created by Microsoft VCBU Internal YACC from "asmparse.y" - */ - -#line 2 "asmparse.y" - - // 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. -// -// File asmparse.y -// -#include "ilasmpch.h" - -#include "grammar_before.cpp" - - -#line 16 "asmparse.y" - -#define UNION 1 -typedef union { - CorRegTypeAttr classAttr; - CorMethodAttr methAttr; - CorFieldAttr fieldAttr; - CorMethodImpl implAttr; - CorEventAttr eventAttr; - CorPropertyAttr propAttr; - CorPinvokeMap pinvAttr; - CorDeclSecurity secAct; - CorFileFlags fileAttr; - CorAssemblyFlags asmAttr; - CorAssemblyFlags asmRefAttr; - CorTypeAttr exptAttr; - CorManifestResourceFlags manresAttr; - double* float64; - __int64* int64; - __int32 int32; - char* string; - BinStr* binstr; - Labels* labels; - Instr* instr; // instruction opcode - NVPair* pair; - pTyParList typarlist; - mdToken token; - TypeDefDescr* tdd; - CustomDescr* cad; - unsigned short opcode; -} YYSTYPE; -# define ERROR_ 257 -# define BAD_COMMENT_ 258 -# define BAD_LITERAL_ 259 -# define ID 260 -# define DOTTEDNAME 261 -# define QSTRING 262 -# define SQSTRING 263 -# define INT32 264 -# define INT64 265 -# define FLOAT64 266 -# define HEXBYTE 267 -# define TYPEDEF_T 268 -# define TYPEDEF_M 269 -# define TYPEDEF_F 270 -# define TYPEDEF_TS 271 -# define TYPEDEF_MR 272 -# define TYPEDEF_CA 273 -# define DCOLON 274 -# define ELIPSIS 275 -# define VOID_ 276 -# define BOOL_ 277 -# define CHAR_ 278 -# define UNSIGNED_ 279 -# define INT_ 280 -# define INT8_ 281 -# define INT16_ 282 -# define INT32_ 283 -# define INT64_ 284 -# define FLOAT_ 285 -# define FLOAT32_ 286 -# define FLOAT64_ 287 -# define BYTEARRAY_ 288 -# define UINT_ 289 -# define UINT8_ 290 -# define UINT16_ 291 -# define UINT32_ 292 -# define UINT64_ 293 -# define FLAGS_ 294 -# define CALLCONV_ 295 -# define MDTOKEN_ 296 -# define OBJECT_ 297 -# define STRING_ 298 -# define NULLREF_ 299 -# define DEFAULT_ 300 -# define CDECL_ 301 -# define VARARG_ 302 -# define STDCALL_ 303 -# define THISCALL_ 304 -# define FASTCALL_ 305 -# define CLASS_ 306 -# define TYPEDREF_ 307 -# define UNMANAGED_ 308 -# define FINALLY_ 309 -# define HANDLER_ 310 -# define CATCH_ 311 -# define FILTER_ 312 -# define FAULT_ 313 -# define EXTENDS_ 314 -# define IMPLEMENTS_ 315 -# define TO_ 316 -# define AT_ 317 -# define TLS_ 318 -# define TRUE_ 319 -# define FALSE_ 320 -# define _INTERFACEIMPL 321 -# define VALUE_ 322 -# define VALUETYPE_ 323 -# define NATIVE_ 324 -# define INSTANCE_ 325 -# define SPECIALNAME_ 326 -# define FORWARDER_ 327 -# define STATIC_ 328 -# define PUBLIC_ 329 -# define PRIVATE_ 330 -# define FAMILY_ 331 -# define FINAL_ 332 -# define SYNCHRONIZED_ 333 -# define INTERFACE_ 334 -# define SEALED_ 335 -# define NESTED_ 336 -# define ABSTRACT_ 337 -# define AUTO_ 338 -# define SEQUENTIAL_ 339 -# define EXPLICIT_ 340 -# define ANSI_ 341 -# define UNICODE_ 342 -# define AUTOCHAR_ 343 -# define IMPORT_ 344 -# define ENUM_ 345 -# define VIRTUAL_ 346 -# define NOINLINING_ 347 -# define AGGRESSIVEINLINING_ 348 -# define NOOPTIMIZATION_ 349 -# define UNMANAGEDEXP_ 350 -# define BEFOREFIELDINIT_ 351 -# define STRICT_ 352 -# define RETARGETABLE_ 353 -# define WINDOWSRUNTIME_ 354 -# define NOPLATFORM_ 355 -# define METHOD_ 356 -# define FIELD_ 357 -# define PINNED_ 358 -# define MODREQ_ 359 -# define MODOPT_ 360 -# define SERIALIZABLE_ 361 -# define PROPERTY_ 362 -# define TYPE_ 363 -# define ASSEMBLY_ 364 -# define FAMANDASSEM_ 365 -# define FAMORASSEM_ 366 -# define PRIVATESCOPE_ 367 -# define HIDEBYSIG_ 368 -# define NEWSLOT_ 369 -# define RTSPECIALNAME_ 370 -# define PINVOKEIMPL_ 371 -# define _CTOR 372 -# define _CCTOR 373 -# define LITERAL_ 374 -# define NOTSERIALIZED_ 375 -# define INITONLY_ 376 -# define REQSECOBJ_ 377 -# define CIL_ 378 -# define OPTIL_ 379 -# define MANAGED_ 380 -# define FORWARDREF_ 381 -# define PRESERVESIG_ 382 -# define RUNTIME_ 383 -# define INTERNALCALL_ 384 -# define _IMPORT 385 -# define NOMANGLE_ 386 -# define LASTERR_ 387 -# define WINAPI_ 388 -# define AS_ 389 -# define BESTFIT_ 390 -# define ON_ 391 -# define OFF_ 392 -# define CHARMAPERROR_ 393 -# define INSTR_NONE 394 -# define INSTR_VAR 395 -# define INSTR_I 396 -# define INSTR_I8 397 -# define INSTR_R 398 -# define INSTR_BRTARGET 399 -# define INSTR_METHOD 400 -# define INSTR_FIELD 401 -# define INSTR_TYPE 402 -# define INSTR_STRING 403 -# define INSTR_SIG 404 -# define INSTR_TOK 405 -# define INSTR_SWITCH 406 -# define _CLASS 407 -# define _NAMESPACE 408 -# define _METHOD 409 -# define _FIELD 410 -# define _DATA 411 -# define _THIS 412 -# define _BASE 413 -# define _NESTER 414 -# define _EMITBYTE 415 -# define _TRY 416 -# define _MAXSTACK 417 -# define _LOCALS 418 -# define _ENTRYPOINT 419 -# define _ZEROINIT 420 -# define _EVENT 421 -# define _ADDON 422 -# define _REMOVEON 423 -# define _FIRE 424 -# define _OTHER 425 -# define _PROPERTY 426 -# define _SET 427 -# define _GET 428 -# define _PERMISSION 429 -# define _PERMISSIONSET 430 -# define REQUEST_ 431 -# define DEMAND_ 432 -# define ASSERT_ 433 -# define DENY_ 434 -# define PERMITONLY_ 435 -# define LINKCHECK_ 436 -# define INHERITCHECK_ 437 -# define REQMIN_ 438 -# define REQOPT_ 439 -# define REQREFUSE_ 440 -# define PREJITGRANT_ 441 -# define PREJITDENY_ 442 -# define NONCASDEMAND_ 443 -# define NONCASLINKDEMAND_ 444 -# define NONCASINHERITANCE_ 445 -# define _LINE 446 -# define P_LINE 447 -# define _LANGUAGE 448 -# define _CUSTOM 449 -# define INIT_ 450 -# define _SIZE 451 -# define _PACK 452 -# define _VTABLE 453 -# define _VTFIXUP 454 -# define FROMUNMANAGED_ 455 -# define CALLMOSTDERIVED_ 456 -# define _VTENTRY 457 -# define RETAINAPPDOMAIN_ 458 -# define _FILE 459 -# define NOMETADATA_ 460 -# define _HASH 461 -# define _ASSEMBLY 462 -# define _PUBLICKEY 463 -# define _PUBLICKEYTOKEN 464 -# define ALGORITHM_ 465 -# define _VER 466 -# define _LOCALE 467 -# define EXTERN_ 468 -# define _MRESOURCE 469 -# define _MODULE 470 -# define _EXPORT 471 -# define LEGACY_ 472 -# define LIBRARY_ 473 -# define X86_ 474 -# define IA64_ 475 -# define AMD64_ 476 -# define ARM_ 477 -# define MARSHAL_ 478 -# define CUSTOM_ 479 -# define SYSSTRING_ 480 -# define FIXED_ 481 -# define VARIANT_ 482 -# define CURRENCY_ 483 -# define SYSCHAR_ 484 -# define DECIMAL_ 485 -# define DATE_ 486 -# define BSTR_ 487 -# define TBSTR_ 488 -# define LPSTR_ 489 -# define LPWSTR_ 490 -# define LPTSTR_ 491 -# define OBJECTREF_ 492 -# define IUNKNOWN_ 493 -# define IDISPATCH_ 494 -# define STRUCT_ 495 -# define SAFEARRAY_ 496 -# define BYVALSTR_ 497 -# define LPVOID_ 498 -# define ANY_ 499 -# define ARRAY_ 500 -# define LPSTRUCT_ 501 -# define IIDPARAM_ 502 -# define IN_ 503 -# define OUT_ 504 -# define OPT_ 505 -# define PARAM_ 506 -# define _OVERRIDE 507 -# define WITH_ 508 -# define NULL_ 509 -# define HRESULT_ 510 -# define CARRAY_ 511 -# define USERDEFINED_ 512 -# define RECORD_ 513 -# define FILETIME_ 514 -# define BLOB_ 515 -# define STREAM_ 516 -# define STORAGE_ 517 -# define STREAMED_OBJECT_ 518 -# define STORED_OBJECT_ 519 -# define BLOB_OBJECT_ 520 -# define CF_ 521 -# define CLSID_ 522 -# define VECTOR_ 523 -# define _SUBSYSTEM 524 -# define _CORFLAGS 525 -# define ALIGNMENT_ 526 -# define _IMAGEBASE 527 -# define _STACKRESERVE 528 -# define _TYPEDEF 529 -# define _TEMPLATE 530 -# define _TYPELIST 531 -# define _MSCORLIB 532 -# define P_DEFINE 533 -# define P_UNDEF 534 -# define P_IFDEF 535 -# define P_IFNDEF 536 -# define P_ELSE 537 -# define P_ENDIF 538 -# define P_INCLUDE 539 -#define yyclearin yychar = -1 -#define yyerrok yyerrflag = 0 -#ifndef YYMAXDEPTH -#define YYMAXDEPTH 150 -#endif -YYSTYPE yylval, yyval; -#ifndef YYFARDATA -#define YYFARDATA /*nothing*/ -#endif -#if ! defined YYSTATIC -#define YYSTATIC /*nothing*/ -#endif -#if ! defined YYCONST -#define YYCONST /*nothing*/ -#endif -#ifndef YYACT -#define YYACT yyact -#endif -#ifndef YYPACT -#define YYPACT yypact -#endif -#ifndef YYPGO -#define YYPGO yypgo -#endif -#ifndef YYR1 -#define YYR1 yyr1 -#endif -#ifndef YYR2 -#define YYR2 yyr2 -#endif -#ifndef YYCHK -#define YYCHK yychk -#endif -#ifndef YYDEF -#define YYDEF yydef -#endif -#ifndef YYV -#define YYV yyv -#endif -#ifndef YYS -#define YYS yys -#endif -#ifndef YYLOCAL -#define YYLOCAL -#endif -#ifndef YYR_T -#define YYR_T int -#endif -typedef YYR_T yyr_t; -#ifndef YYEXIND_T -#define YYEXIND_T unsigned int -#endif -typedef YYEXIND_T yyexind_t; -#ifndef YYOPTTIME -#define YYOPTTIME 0 -#endif -# define YYERRCODE 256 - -#line 2051 "asmparse.y" - - -#include "grammar_after.cpp" -YYSTATIC YYCONST short yyexca[] = { -#if !(YYOPTTIME) --1, 1, -#endif - 0, -1, - -2, 0, -#if !(YYOPTTIME) --1, 452, -#endif - 41, 532, - -2, 308, -#if !(YYOPTTIME) --1, 621, -#endif - 274, 549, - 47, 549, - -2, 227, -#if !(YYOPTTIME) --1, 642, -#endif - 40, 307, - 60, 307, - -2, 549, -#if !(YYOPTTIME) --1, 663, -#endif - 41, 532, - -2, 308, -#if !(YYOPTTIME) --1, 686, -#endif - 274, 549, - 47, 549, - -2, 510, -#if !(YYOPTTIME) --1, 803, -#endif - 123, 232, - -2, 549, -#if !(YYOPTTIME) --1, 828, -#endif - 41, 532, - -2, 308, -#if !(YYOPTTIME) --1, 953, -#endif - 41, 532, - -2, 308, -#if !(YYOPTTIME) --1, 986, -#endif - 41, 532, - -2, 308, -#if !(YYOPTTIME) --1, 987, -#endif - 41, 532, - -2, 308, -#if !(YYOPTTIME) --1, 1308, -#endif - 41, 532, - -2, 308, -#if !(YYOPTTIME) --1, 1309, -#endif - 41, 532, - -2, 308, -#if !(YYOPTTIME) --1, 1315, -#endif - 41, 532, - -2, 308, -#if !(YYOPTTIME) --1, 1322, -#endif - 41, 532, - -2, 308, -#if !(YYOPTTIME) --1, 1447, -#endif - 41, 532, - -2, 308, -#if !(YYOPTTIME) --1, 1479, -#endif - 41, 532, - -2, 308, -#if !(YYOPTTIME) --1, 1545, -#endif - 41, 532, - -2, 308, -#if !(YYOPTTIME) --1, 1562, -#endif - 41, 532, - -2, 308, - -}; - -# define YYNPROD 838 -#if YYOPTTIME -YYSTATIC YYCONST yyexind_t yyexcaind[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 42, 46, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 50, 54, - 0, 0, 0, 0, 0, 58, 0, 0, 0, 0, - 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 78 -}; -#endif -# define YYLAST 3904 - -YYSTATIC YYCONST short YYFARDATA YYACT[] = { - 699, 1398, 1121, 1466, 658, 1467, 639, 1024, 1465, 878, - 1464, 963, 784, 753, 964, 221, 775, 26, 698, 725, - 73, 75, 275, 414, 624, 877, 966, 1399, 535, 191, - 477, 1503, 150, 788, 751, 756, 1134, 110, 1065, 107, - 690, 852, 273, 153, 219, 660, 24, 44, 776, 218, - 307, 10, 190, 176, 78, 81, 6, 86, 5, 598, - 673, 262, 204, 515, 3, 188, 217, 983, 17, 301, - 603, 136, 76, 1550, 1194, 1242, 214, 264, 7, 1238, - 1057, 1239, 1113, 1111, 85, 1112, 580, 74, 715, 88, - 87, 137, 89, 300, 115, 56, 139, 712, 672, 113, - 1058, 98, 112, 178, 179, 180, 181, 74, 272, 696, - 322, 519, 1015, 461, 220, 56, 18, 452, 536, 338, - 278, 88, 87, 1021, 89, 268, 216, 269, 1240, 225, - 56, 265, 277, 277, 1228, 1229, 106, 1226, 1227, 590, - 277, 343, 361, 360, 359, 358, 654, 368, 345, 653, - 68, 310, 312, 314, 316, 318, 185, 1554, 460, 1126, - 1127, 1414, 98, 931, 932, 327, 277, 348, 339, 1027, - 342, 778, 1026, 779, 373, 366, 154, 277, 695, 133, - 694, 991, 379, 271, 362, 84, 258, 364, 363, 376, - 614, 192, 387, 105, 1519, 662, 513, 930, 365, 1059, - 369, 202, 203, 371, 370, 1487, 374, 1264, 596, 450, - 661, 451, 763, 372, 416, 469, 186, 467, 471, 470, - 442, 26, 74, 376, 456, 417, 418, 346, 376, 1559, - 352, 472, 474, 599, 353, 305, 483, 388, 88, 87, - 596, 89, 410, 1263, 1478, 500, 492, 1314, 457, 441, - 24, 1200, 357, 491, 435, 10, 825, 797, 787, 56, - 486, 432, 490, 428, 475, 478, 479, 773, 476, 429, - 494, 434, 17, 192, 108, 666, 511, 511, 528, 534, - 375, 433, 7, 351, 267, 321, 480, 481, 473, 485, - 152, 710, 74, 484, 1234, 540, 1345, 116, 1496, 1391, - 56, 1540, 499, 80, 79, 498, 543, 493, 1417, 571, - 959, 268, 1351, 1544, 574, 348, 575, 154, 576, 436, - 18, 266, 548, 1335, 1116, 578, 579, 504, 541, 46, - 420, 544, 421, 422, 423, 933, 934, 570, 935, 88, - 572, 947, 89, 573, 46, 594, 854, 855, 856, 1128, - 640, 641, 600, 135, 198, 88, 87, 962, 89, 199, - 1541, 200, 568, 1510, 192, 487, 1341, 201, 612, 154, - 755, 482, 277, 674, 1543, 510, 510, 527, 533, 74, - 605, 744, 745, 746, 195, 808, 182, 623, 943, 611, - 599, 581, 582, 1141, 497, 1233, 700, 1252, 1142, 196, - 565, 367, 375, 620, 595, 258, 610, 88, 87, 518, - 89, 74, 606, 607, 608, 609, 747, 748, 749, 1542, - 643, 613, 599, 537, 340, 341, 634, 1489, 348, 807, - 459, 618, 619, 621, 780, 1130, 321, 876, 648, 649, - 638, 88, 87, 177, 89, 1231, 88, 87, 847, 89, - 152, 781, 702, 754, 347, 650, 664, 1502, 413, 88, - 87, 670, 946, 1488, 651, 88, 87, 155, 89, 681, - 642, 1518, 1126, 1127, 545, 743, 1118, 177, 993, 994, - 995, 996, 177, 587, 505, 859, 352, 1513, 667, 988, - 353, 678, 80, 79, 479, 177, 647, 692, 646, 1512, - 782, 1511, 61, 62, 47, 63, 536, 1508, 357, 645, - 685, 198, 741, 669, 480, 481, 199, 689, 200, 82, - 63, 74, 701, 479, 201, 711, 680, 453, 72, 679, - 88, 87, 519, 89, 512, 520, 74, 507, 508, 351, - 686, 195, 88, 480, 481, 89, 74, 723, 71, 70, - 354, 355, 356, 538, 691, 216, 196, 1141, 225, 1506, - 1241, 724, 1142, 675, 676, 677, 720, 657, 721, 49, - 50, 51, 52, 53, 54, 55, 671, 709, 74, 644, - 479, 730, 1504, 80, 79, 714, 80, 79, 348, 49, - 50, 51, 52, 53, 54, 55, 719, 74, 1141, 716, - 480, 481, 726, 1142, 49, 50, 51, 52, 53, 54, - 55, 156, 157, 158, 69, 758, 74, 542, 74, 88, - 87, 592, 89, 600, 67, 764, 765, 155, 88, 87, - 688, 89, 74, 783, 98, 638, 729, 1320, 1319, 1318, - 1317, 750, 74, 697, 325, 74, 703, 1172, 1171, 1170, - 1169, 542, 705, 348, 706, 177, 377, 1499, 324, 769, - 770, 771, 1337, 1338, 1339, 642, 815, 789, 813, 819, - 853, 88, 87, 816, 89, 822, 541, 1180, 801, 802, - 80, 79, 798, 823, 88, 812, 806, 89, 74, 66, - 818, 626, 627, 628, 74, 1117, 833, 834, 762, 1450, - 495, 826, 216, 786, 591, 225, 1439, 800, 793, 803, - 74, 809, 796, 636, 846, 824, 382, 383, 384, 385, - 817, 152, 74, 857, 74, 56, 629, 630, 631, 922, - 74, 740, 821, 49, 50, 51, 52, 53, 54, 55, - 1437, 850, 936, 937, 860, 1490, 516, 761, 88, 87, - 375, 89, 832, 1327, 844, 1247, 1243, 1244, 1245, 1246, - 1179, 1435, 769, 600, 949, 192, 845, 942, 1433, 848, - 276, 156, 157, 158, 49, 50, 51, 52, 53, 54, - 55, 97, 74, 924, 111, 925, 926, 927, 928, 929, - 952, 1001, 1416, 1407, 985, 152, 635, 938, 1406, 277, - 1013, 965, 362, 1326, 1011, 74, 354, 355, 356, 442, - 1000, 1009, 528, 605, 1404, 585, 954, 584, 583, 145, - 1390, 1012, 948, 1388, 586, 799, 960, 955, 277, 1017, - 958, 692, 692, 1032, 1378, 1376, 1237, 350, 441, 999, - 1008, 817, 1022, 435, 997, 1007, 851, 1374, 1037, 1014, - 432, 817, 428, 849, 1019, 1035, 1016, 1018, 429, 1039, - 434, 989, 326, 323, 88, 87, 94, 89, 74, 1372, - 433, 1033, 1034, 1045, 352, 772, 828, 277, 353, 1030, - 80, 79, 479, 1050, 277, 56, 1370, 1368, 691, 691, - 88, 87, 348, 89, 74, 954, 357, 337, 155, 348, - 1366, 1364, 480, 481, 668, 1362, 817, 1359, 436, 998, - 1006, 527, 1356, 1123, 1354, 1350, 56, 1334, 1312, 1055, - 152, 1196, 88, 87, 718, 89, 177, 351, 1044, 1053, - 193, 615, 1043, 194, 1051, 348, 1042, 352, 1041, 46, - 352, 353, 1122, 1023, 768, 820, 1067, 814, 1068, 1126, - 1127, 501, 733, 617, 616, 1124, 198, 177, 1132, 357, - 145, 199, 357, 200, 88, 87, 577, 89, 758, 201, - 564, 1300, 155, 1236, 308, 1119, 455, 109, 1054, 1140, - 1129, 92, 529, 1138, 1125, 1394, 195, 1298, 1115, 1185, - 351, 1183, 1184, 351, 88, 87, 1186, 89, 1178, 277, - 177, 196, 1296, 1491, 1064, 1060, 1061, 1062, 1063, 1025, - 1492, 1133, 145, 1182, 1415, 328, 329, 330, 1294, 1181, - 956, 96, 1301, 590, 104, 103, 102, 101, 1219, 99, - 100, 105, 56, 1, 1175, 1332, 1195, 1173, 1299, 1203, - 332, 941, 156, 157, 158, 1167, 1187, 1188, 1189, 1190, - 1230, 766, 1202, 1297, 1165, 1232, 1191, 1192, 1193, 80, - 79, 479, 588, 1131, 1223, 1225, 1224, 1222, 984, 1295, - 1235, 1197, 1400, 88, 87, 1163, 89, 1198, 1161, 1199, - 945, 480, 481, 589, 1218, 1176, 189, 708, 1174, 88, - 87, 1005, 89, 1003, 1004, 1159, 1168, 155, 1010, 46, - 707, 205, 152, 1157, 704, 1166, 633, 1412, 412, 187, - 625, 790, 61, 62, 47, 63, 156, 157, 158, 1248, - 1177, 192, 192, 192, 192, 177, 1164, 277, 1268, 1162, - 46, 192, 192, 192, 331, 1266, 333, 334, 335, 336, - 1155, 625, 1251, 192, 1411, 1265, 1160, 1269, 1410, 1271, - 1273, 1274, 1255, 1277, 1158, 1279, 1280, 1281, 1282, 1283, - 1284, 1285, 1270, 1287, 1288, 1289, 1290, 1291, 1292, 1293, - 1254, 1401, 1259, 56, 1302, 1303, 1153, 1305, 1304, 1151, - 1272, 1149, 1275, 1276, 1147, 1278, 1221, 1048, 1267, 1047, - 836, 1156, 1307, 1286, 354, 355, 356, 1145, 1143, 49, - 50, 51, 52, 53, 54, 55, 742, 1316, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 665, 1313, 352, 317, 1154, 454, 353, - 1152, 315, 1150, 313, 1328, 1148, 378, 1330, 1331, 521, - 1321, 156, 157, 158, 311, 45, 46, 357, 1146, 1144, - 1336, 1340, 309, 1333, 817, 41, 43, 354, 355, 356, - 354, 355, 356, 1135, 1342, 277, 277, 1140, 1552, 526, - 590, 88, 87, 306, 89, 63, 415, 308, 351, 155, - 1315, 1343, 308, 1257, 308, 56, 277, 503, 1452, 512, - 590, 1451, 507, 508, 140, 308, 1380, 1381, 1382, 1383, - 1384, 1385, 1386, 308, 944, 1347, 63, 177, 590, 1539, - 590, 1329, 1344, 1392, 1393, 193, 531, 1346, 194, 532, - 1397, 1396, 940, 831, 308, 138, 1379, 1402, 1403, 1031, - 1524, 590, 923, 1408, 590, 590, 1395, 830, 811, 767, - 760, 198, 177, 1405, 717, 566, 199, 349, 200, 258, - 303, 792, 1564, 117, 201, 97, 1555, 1553, 1140, 49, - 50, 51, 52, 53, 54, 55, 1546, 1523, 817, 1486, - 1485, 195, 1484, 1454, 1449, 1446, 1443, 1442, 1438, 56, - 524, 1436, 1434, 1432, 1419, 1413, 196, 46, 1409, 1389, - 49, 50, 51, 52, 53, 54, 55, 134, 1445, 1387, - 1377, 1375, 1373, 1371, 1369, 1367, 1365, 1363, 1361, 1360, - 526, 1455, 1456, 1457, 1358, 1357, 1355, 1453, 1353, 1444, - 1448, 1352, 63, 156, 157, 158, 1349, 1324, 1348, 1325, - 1458, 1323, 523, 1311, 1470, 525, 1310, 1471, 1469, 1468, - 1306, 1256, 1253, 258, 1476, 693, 1220, 88, 87, 1114, - 89, 1052, 1481, 1038, 1480, 1036, 1029, 1028, 1020, 961, - 951, 950, 56, 1498, 939, 1483, 1505, 1507, 1509, 858, - 1505, 1507, 1509, 530, 841, 840, 1495, 1507, 1516, 838, - 1520, 1517, 1515, 1514, 1522, 1521, 88, 835, 829, 89, - 827, 56, 810, 1497, 1500, 1501, 791, 774, 738, 46, - 737, 1538, 736, 1493, 735, 734, 49, 50, 51, 52, - 53, 54, 55, 732, 731, 1529, 1505, 1507, 1509, 684, - 637, 524, 569, 425, 424, 344, 258, 320, 206, 1562, - 1547, 1525, 817, 1545, 1479, 1475, 1474, 1473, 1472, 1447, - 1534, 1441, 1440, 1431, 1430, 354, 355, 356, 1551, 1429, - 1549, 1428, 1427, 1548, 1535, 1536, 1537, 449, 1426, 1425, - 1424, 1423, 1561, 63, 1422, 1421, 1560, 1563, 1420, 1418, - 1300, 1298, 1296, 523, 1294, 1322, 525, 1175, 1173, 1557, - 88, 1558, 1167, 89, 1556, 1526, 1527, 1528, 1530, 1531, - 1532, 1533, 1165, 46, 1163, 96, 1161, 1159, 104, 103, - 102, 101, 56, 99, 100, 105, 1157, 1155, 1153, 1151, - 1149, 1309, 1308, 817, 1250, 1249, 1066, 1056, 1049, 1040, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 987, 986, 953, 843, 59, 842, 839, - 837, 208, 259, 210, 228, 212, 213, 49, 50, 51, - 52, 53, 54, 55, 728, 41, 43, 727, 713, 687, - 683, 682, 663, 88, 632, 602, 89, 601, 593, 567, - 547, 546, 61, 62, 47, 63, 46, 496, 419, 411, - 874, 386, 319, 223, 304, 522, 514, 868, 517, 869, - 870, 871, 509, 506, 56, 502, 302, 222, 36, 184, - 93, 33, 468, 466, 465, 46, 464, 463, 244, 462, - 227, 243, 215, 209, 245, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 863, 864, 865, - 95, 59, 226, 224, 207, 208, 259, 210, 228, 212, - 213, 211, 879, 31, 56, 1002, 992, 439, 795, 41, - 43, 431, 794, 430, 427, 539, 1046, 270, 83, 49, - 50, 51, 52, 53, 54, 55, 61, 62, 47, 63, - 29, 57, 862, 866, 867, 34, 872, 223, 25, 873, - 16, 263, 15, 14, 261, 13, 260, 12, 11, 9, - 8, 222, 1086, 4, 2, 234, 242, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 990, 241, 240, 239, 59, 238, 46, 237, 208, 259, - 210, 228, 212, 213, 236, 235, 226, 224, 233, 232, - 231, 230, 41, 43, 229, 114, 77, 42, 56, 38, - 30, 58, 32, 59, 752, 656, 655, 1482, 299, 61, - 62, 47, 63, 49, 50, 51, 52, 53, 54, 55, - 223, 41, 43, 90, 183, 861, 1139, 757, 785, 1258, - 957, 1137, 1136, 604, 222, 1461, 1460, 1459, 61, 62, - 47, 63, 1477, 1463, 1462, 60, 35, 1201, 1120, 597, - 659, 21, 777, 91, 37, 1069, 739, 65, 64, 197, - 875, 39, 40, 0, 426, 0, 0, 0, 0, 226, - 224, 0, 982, 981, 980, 0, 975, 974, 973, 972, - 0, 970, 971, 105, 0, 979, 978, 977, 976, 0, - 0, 0, 969, 967, 0, 0, 49, 50, 51, 52, - 53, 54, 55, 0, 0, 0, 0, 0, 0, 0, - 38, 30, 58, 32, 59, 0, 19, 20, 46, 22, - 23, 48, 0, 27, 28, 49, 50, 51, 52, 53, - 54, 55, 41, 43, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, - 62, 47, 63, 0, 0, 0, 60, 35, 968, 0, - 0, 0, 21, 0, 0, 37, 444, 1097, 0, 874, - 0, 0, 39, 40, 0, 0, 868, 0, 869, 870, - 871, 0, 0, 0, 0, 0, 1073, 1074, 0, 1081, - 1095, 1075, 1076, 1077, 1078, 0, 1079, 1080, 0, 1096, - 1082, 1083, 1084, 1085, 0, 0, 0, 0, 0, 0, - 0, 0, 46, 0, 0, 0, 863, 864, 865, 0, - 0, 0, 0, 0, 0, 0, 0, 19, 20, 0, - 22, 23, 48, 0, 27, 28, 49, 50, 51, 52, - 53, 54, 55, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 448, 0, 58, 32, 59, 0, 0, 0, - 444, 862, 866, 867, 0, 872, 445, 0, 873, 0, - 0, 446, 0, 0, 41, 43, 0, 146, 874, 0, - 0, 0, 0, 0, 0, 868, 0, 869, 870, 871, - 0, 61, 62, 47, 63, 0, 437, 438, 0, 921, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 447, 0, 0, 0, - 0, 0, 0, 0, 0, 863, 864, 865, 49, 50, - 51, 52, 53, 54, 55, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 448, 0, 58, 32, - 59, 443, 440, 0, 0, 0, 0, 0, 0, 0, - 445, 0, 0, 0, 0, 446, 0, 0, 41, 43, - 862, 866, 867, 0, 872, 0, 0, 873, 49, 50, - 51, 52, 53, 54, 55, 61, 62, 47, 63, 1494, - 437, 438, 1071, 1072, 0, 1087, 1088, 1089, 0, 1090, - 1091, 0, 0, 1092, 1093, 0, 1094, 0, 0, 0, - 447, 0, 0, 0, 0, 0, 0, 0, 0, 1070, - 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, - 1108, 1109, 1110, 893, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 443, 440, 920, 0, 0, - 0, 0, 885, 886, 0, 894, 911, 887, 888, 889, - 890, 0, 891, 892, 0, 912, 895, 896, 897, 898, - 893, 0, 49, 50, 51, 52, 53, 54, 55, 0, - 0, 0, 0, 0, 920, 146, 0, 0, 0, 885, - 886, 0, 894, 911, 887, 888, 889, 890, 0, 891, - 892, 0, 912, 895, 896, 897, 898, 0, 0, 0, - 909, 0, 913, 0, 0, 175, 0, 915, 0, 151, - 148, 163, 161, 170, 0, 164, 165, 166, 167, 0, - 168, 169, 917, 0, 171, 172, 173, 174, 563, 0, - 0, 142, 162, 152, 0, 0, 0, 909, 0, 913, - 141, 147, 0, 0, 915, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 918, 143, 144, 149, 917, - 555, 0, 549, 550, 551, 552, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 146, 0, 0, 0, 0, - 352, 0, 0, 0, 768, 0, 0, 0, 0, 0, - 160, 0, 918, 0, 0, 0, 0, 0, 557, 558, - 559, 560, 357, 0, 554, 0, 0, 0, 561, 562, - 553, 0, 0, 0, 0, 982, 981, 980, 0, 975, - 974, 973, 972, 0, 970, 971, 105, 0, 979, 978, - 977, 976, 0, 622, 0, 969, 967, 0, 0, 0, - 0, 0, 0, 0, 0, 880, 0, 881, 882, 883, - 884, 899, 900, 901, 916, 902, 903, 904, 905, 906, - 907, 908, 910, 914, 0, 0, 0, 919, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 880, 0, 881, 882, 883, 884, 899, 900, - 901, 916, 902, 903, 904, 905, 906, 907, 908, 910, - 914, 968, 88, 87, 919, 89, 0, 0, 0, 0, - 155, 0, 556, 175, 0, 0, 0, 151, 148, 163, - 161, 170, 0, 164, 165, 166, 167, 0, 168, 169, - 0, 0, 171, 172, 173, 174, 146, 0, 177, 142, - 162, 352, 0, 0, 0, 353, 0, 0, 141, 147, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 357, 143, 144, 149, 0, 0, 175, - 0, 0, 0, 0, 0, 163, 161, 170, 0, 164, - 165, 166, 167, 0, 168, 169, 0, 0, 171, 172, - 173, 174, 0, 0, 622, 1261, 162, 0, 160, 159, - 0, 0, 88, 87, 0, 89, 0, 0, 0, 0, - 155, 0, 0, 175, 0, 0, 0, 151, 148, 163, - 161, 170, 0, 164, 165, 166, 167, 0, 168, 169, - 0, 0, 171, 172, 173, 174, 0, 0, 177, 142, - 162, 0, 0, 1262, 0, 0, 0, 0, 141, 147, - 0, 0, 0, 0, 156, 157, 158, 0, 0, 0, - 0, 1260, 0, 0, 143, 144, 149, 0, 0, 0, - 0, 0, 0, 0, 297, 198, 146, 0, 0, 0, - 199, 352, 200, 0, 0, 353, 0, 0, 201, 0, - 0, 63, 0, 0, 0, 0, 0, 0, 160, 0, - 354, 355, 356, 357, 0, 195, 284, 0, 279, 280, - 281, 282, 283, 0, 640, 641, 0, 287, 0, 0, - 196, 0, 0, 0, 0, 0, 285, 0, 0, 0, - 295, 0, 286, 0, 622, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 288, 289, 290, 291, 292, 293, - 294, 298, 0, 0, 156, 157, 158, 296, 0, 0, - 0, 0, 0, 88, 87, 0, 89, 0, 0, 0, - 146, 155, 0, 0, 175, 0, 0, 0, 151, 148, - 163, 161, 170, 0, 164, 165, 166, 167, 0, 168, - 169, 0, 0, 171, 172, 173, 174, 0, 0, 177, - 142, 162, 0, 0, 0, 0, 0, 0, 0, 141, - 147, 0, 0, 0, 348, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 143, 144, 149, 274, 1217, - 1216, 1211, 0, 1210, 1209, 1208, 1207, 146, 1205, 1206, - 105, 0, 1215, 1214, 1213, 1212, 0, 0, 0, 0, - 0, 1204, 0, 0, 0, 0, 0, 0, 0, 160, - 0, 354, 355, 356, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 640, 641, 982, 981, 980, - 0, 975, 974, 973, 972, 0, 970, 971, 105, 0, - 979, 978, 977, 976, 0, 274, 0, 969, 967, 0, - 0, 0, 0, 88, 87, 0, 89, 0, 0, 0, - 0, 155, 0, 0, 175, 156, 157, 158, 151, 148, - 163, 161, 170, 0, 164, 165, 166, 167, 0, 168, - 169, 0, 0, 171, 172, 173, 174, 146, 0, 177, - 142, 162, 0, 0, 0, 0, 0, 0, 0, 141, - 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 968, 0, 143, 144, 149, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 274, 0, 88, 87, 160, - 89, 354, 355, 356, 146, 155, 0, 0, 175, 0, - 0, 0, 151, 148, 163, 161, 170, 0, 164, 165, - 166, 167, 0, 168, 169, 0, 0, 171, 172, 173, - 174, 0, 0, 177, 142, 162, 0, 0, 0, 0, - 0, 0, 0, 141, 147, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 156, 157, 158, 0, 143, - 144, 149, 274, 805, 88, 87, 0, 89, 0, 0, - 0, 0, 155, 0, 0, 175, 0, 0, 0, 151, - 148, 163, 161, 170, 0, 164, 165, 166, 167, 0, - 168, 169, 0, 160, 171, 172, 173, 174, 146, 0, - 177, 142, 162, 0, 0, 0, 0, 804, 0, 0, - 141, 147, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 143, 144, 149, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, - 157, 158, 0, 0, 0, 0, 274, 0, 0, 0, - 160, 159, 0, 0, 88, 87, 146, 89, 0, 0, - 0, 0, 155, 0, 0, 175, 0, 0, 0, 151, - 148, 163, 161, 170, 0, 164, 165, 166, 167, 0, - 168, 169, 0, 0, 171, 172, 173, 174, 0, 0, - 177, 142, 162, 0, 0, 0, 0, 0, 0, 0, - 141, 147, 0, 0, 0, 0, 156, 157, 158, 0, - 0, 0, 0, 0, 274, 0, 143, 144, 149, 0, - 0, 88, 87, 0, 89, 0, 0, 0, 0, 155, - 0, 0, 175, 0, 0, 0, 151, 148, 163, 161, - 170, 0, 164, 165, 166, 167, 0, 168, 169, 0, - 160, 171, 172, 173, 174, 0, 0, 177, 142, 162, - 0, 0, 0, 0, 0, 0, 0, 759, 147, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 143, 144, 149, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 146, 0, 0, 0, 0, 156, 157, 158, 0, - 0, 0, 0, 0, 0, 88, 87, 160, 89, 0, - 0, 0, 0, 155, 0, 0, 175, 0, 0, 0, - 151, 148, 163, 161, 170, 0, 164, 165, 166, 167, - 0, 168, 169, 0, 0, 171, 172, 173, 174, 0, - 0, 177, 142, 162, 0, 0, 146, 0, 0, 0, - 0, 141, 147, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 156, 157, 158, 0, 143, 144, 149, - 0, 0, 0, 88, 87, 0, 89, 0, 0, 0, - 0, 155, 0, 0, 175, 0, 0, 0, 151, 148, - 163, 161, 170, 0, 164, 165, 166, 167, 0, 168, - 169, 652, 146, 171, 172, 173, 174, 0, 0, 177, - 142, 162, 88, 87, 0, 89, 0, 0, 0, 141, - 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 143, 144, 149, 0, 0, - 0, 0, 0, 0, 0, 0, 409, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 146, 156, 157, 158, - 988, 0, 0, 0, 0, 0, 0, 0, 0, 458, - 0, 0, 0, 0, 391, 0, 0, 0, 407, 0, - 0, 389, 390, 0, 0, 0, 393, 394, 405, 395, - 396, 397, 398, 399, 400, 401, 402, 392, 0, 0, - 0, 0, 0, 406, 0, 0, 404, 0, 0, 0, - 146, 0, 0, 403, 722, 0, 0, 0, 0, 0, - 0, 0, 408, 0, 0, 156, 157, 158, 488, 175, - 489, 0, 0, 151, 148, 163, 161, 170, 0, 164, - 165, 166, 167, 0, 168, 169, 0, 0, 171, 172, - 173, 174, 0, 0, 177, 142, 162, 0, 0, 0, - 0, 0, 0, 0, 141, 147, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 143, 144, 149, 380, 175, 381, 0, 0, 151, 148, - 163, 161, 170, 0, 164, 165, 166, 167, 0, 168, - 169, 0, 0, 171, 172, 173, 174, 0, 0, 0, - 142, 162, 0, 0, 160, 0, 0, 0, 0, 141, - 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 143, 144, 149, 0, 0, - 175, 0, 0, 0, 151, 148, 163, 161, 170, 0, - 164, 165, 166, 167, 0, 168, 169, 0, 0, 171, - 172, 173, 174, 0, 0, 0, 142, 162, 0, 160, - 0, 0, 0, 0, 0, 141, 147, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 143, 144, 149, 175, 0, 0, 0, 151, 148, - 163, 161, 170, 0, 164, 165, 166, 167, 0, 168, - 169, 0, 0, 171, 172, 173, 174, 0, 0, 0, - 142, 162, 0, 0, 0, 160, 0, 0, 0, 141, - 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 143, 144, 149, 175, 0, - 0, 0, 151, 148, 163, 161, 170, 0, 164, 165, - 166, 167, 0, 168, 169, 0, 0, 171, 172, 173, - 174, 0, 0, 0, 142, 162, 0, 0, 0, 160, - 0, 0, 0, 141, 147, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, - 144, 149, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 160 -}; - -YYSTATIC YYCONST short YYFARDATA YYPACT[] = { --1000, 1543,-1000, 566, 501,-1000,-1000,-1000,-1000,-1000, --1000,-1000, 491, 426, 425, 405,-1000,-1000,-1000, 28, - 28, -454, 39, 39,-1000,-1000,-1000, 396,-1000, -129, - 411,-1000, 890, 743, 7, 886, 28, -366, -369,-1000, - -171, 777, 7, 777,-1000,-1000,-1000, 90, 2292, 411, - 411, 411, 411,-1000,-1000, 124,-1000,-1000,-1000, -162, - 1048,-1000,-1000, 1046, 7, 7,-1000,-1000, 1403,-1000, --1000,-1000,-1000,-1000,-1000,-1000, 28, -139,-1000,-1000, --1000,-1000, 359, -132, 2954, 1220,-1000,-1000,-1000,-1000, - 2430,-1000, 28,-1000, 1317,-1000, 1308, 1644, 7, 1233, - 1212, 1204, 1193, 1191, 1186, 1642, 1486, 18,-1000, 28, - 600, 662,-1000,-1000, 95, 1220, 411, 2954,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000, 1484, 166, 1303, 448, -244, -245, -246, - -247, 359,-1000, -118, 359, 661, 368,-1000,-1000, -76, --1000, 3547, 186, 1189,-1000,-1000,-1000,-1000,-1000, 3383, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, - 435,-1000,-1000,-1000,-1000,-1000, 1220, 1641, 326, 1220, - 1220, 1220,-1000, 3222, 79,-1000,-1000, 1639, 1047, 2854, --1000, 3547,-1000,-1000,-1000, 216, 216,-1000, 1638,-1000, --1000, 29, 1483, 1482, 1779, 1432,-1000,-1000, 28,-1000, - 28, 77,-1000,-1000,-1000,-1000, 1170,-1000,-1000,-1000, --1000,-1000, 885, 28, 3183,-1000, 67, -94,-1000,-1000, - 424, 28, 39, 228, 7, 424, 661, 3328, 2954, -95, - 216, 2854, 1637,-1000, 282,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, - 826, 71, 1114, 857,-1000, 87,-1000, 298, 359,-1000, --1000, 2954,-1000,-1000, 181, 899, 216, 411,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000, 1631, 1630, 2084, - 877, 275, 1301, 1629, 79, 1481, 0,-1000, 28, 0, --1000, 39,-1000, 28,-1000, 28,-1000, 28,-1000,-1000, --1000,-1000, 873,-1000, 28, 28,-1000, 1220,-1000,-1000, --1000, -387,-1000,-1000,-1000,-1000,-1000, 662, 488, 94, --1000,-1000, 1220, 1022,-1000, 1292, 581, 1628,-1000, 82, - 411, 115,-1000,-1000,-1000, 1627, 1625, 3547, 411, 411, - 411, 411,-1000, 359,-1000,-1000, 3547, 604,-1000, 1220, --1000, -90,-1000, 899, 838, 861, 860, 411, 411, 2693, --1000,-1000,-1000,-1000,-1000,-1000, 28, 1292, 1081,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000, 362,-1000,-1000,-1000, 1624, - 1045,-1000, 673, 1479,-1000,-1000, 2553,-1000,-1000, 28, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, 386, - 375, 373,-1000,-1000,-1000,-1000,-1000, 28, 28, 332, - 3115,-1000,-1000, -214, -217,-1000,-1000,-1000,-1000,-1000, --1000,-1000, -65, 1622,-1000, 28, 1165, 1, 216, 813, - 28,-1000, -94, 63, 63, 63, 63, 2954, 282,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, - 1621, 1620, 1478,-1000,-1000,-1000, 2693,-1000,-1000,-1000, --1000, 1292, 1619, 7, 3547,-1000, 424, 1320,-1000, -136, - -138,-1000,-1000, -356,-1000,-1000, 7, 354, 391, 7, --1000,-1000, 1043,-1000,-1000, 7,-1000, 7,-1000, 1039, - 1026,-1000,-1000, 411, -177, -371, 1618,-1000,-1000,-1000, --1000, 411, -380,-1000,-1000, -350,-1000,-1000,-1000, 1300, --1000, 831, 411, 3547, 1220, 3493, 28, 53, 1187,-1000, --1000,-1000,-1000,-1000,-1000,-1000, 1617,-1000,-1000,-1000, --1000,-1000,-1000, 1614,-1000,-1000, 1317, 53, 1473,-1000, - 1472, 859, 1464, 1463, 1461, 1459, 1457,-1000, 468, 1148, --1000, 86, 1220,-1000,-1000,-1000, 52, 411, 53, 330, - 108, 3021,-1000,-1000, 1296, 1220,-1000, 654,-1000,-1000, - -63, 2954, 2954, 989, 1295, 899, 1220, 1220, 1220, 1220, --1000, 2392,-1000, 1220,-1000, 411, 411, 411, 782, 1220, - -7, 1220, 147, 1456,-1000, 128,-1000,-1000,-1000,-1000, --1000,-1000, 28,-1000, 1292,-1000,-1000, 661, -16, 1051, --1000,-1000, 1220, 1455, 1226,-1000,-1000,-1000,-1000,-1000, --1000, -17, 216, 734, 2954, 2787, 59, 488, 1451, 1294, --1000,-1000, 3493, -65, 854, 28, -22, 3547, 28, 1220, - 852,-1000,-1000,-1000, 424,-1000,-1000,-1000,-1000,-1000, --1000,-1000, 28, 39,-1000, -18, 1220, 53, 1449, 836, - 1447, 1293, 1279,-1000, 79, 28, 28, 1446, 1132,-1000, --1000, 1292, 1600, 1438, 1599, 1434, 1433, 1598, 1596, 1220, - 411,-1000, 411, 28, 131, 411, 7, 2954, 411, 753, - 902, 192, -157, 1428, 96, 1824, 120, 2016, 28,-1000, - 1291,-1000, 883,-1000, 883, 883, 883, 883, 883, -120, --1000, 28, 28, 411,-1000,-1000,-1000,-1000,-1000,-1000, - 1220, 1423, 1278, 980,-1000,-1000, 263, 1260, 1019, 199, - 78,-1000, -42, 28, 1420, 1419,-1000, 3547, 1595, 1189, - 1189, 1189, 411, 411,-1000, 958, 270, 128,-1000,-1000, --1000,-1000,-1000, 1418, 232, 1635, 1007, -22, 1594, 1593, - 3439,-1000,-1000, 1685, 56, 666, 973, -22, 3547, 28, - 1220, -337, 411, 1220,-1000,-1000, 3547,-1000,-1000, 1220, --1000, -65, 192, 1417, -266,-1000,-1000, 1220, 2693, 850, - 948, -144, -147, 1416, 1415, 411, 1288,-1000, -65,-1000, - 424, 424,-1000,-1000,-1000,-1000, 354,-1000,-1000,-1000, --1000,-1000,-1000,-1000, 1189, 1220, 1414, 28, 1220, 1412, --1000, 411, -22, 1579, 845, 843, 839, 835,-1000, 53, - 1715,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000, 1131, 1129, 1578, 948, 79, 1410, 887, 7, - 1577, -400, -78,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000, 724,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000, 1576, 1576,-1000, 1576, - 1750,-1000,-1000, -412,-1000, -402,-1000,-1000, -417,-1000, --1000,-1000, 1408,-1000,-1000,-1000,-1000,-1000,-1000,-1000, - 79,-1000,-1000,-1000,-1000,-1000, 61, 432, 1220,-1000, - 53, 630, 224,-1000, 3021, 312, 1002,-1000,-1000,-1000, --1000,-1000, 899, -65, 1189, 1220,-1000, 411, 1219, 2954, --1000,-1000,-1000, 200,-1000,-1000,-1000, 1158, 1157, 1144, - 1141, 1139, 1136, 1100, 1063, 1055, 1038, 1035, 1014, 1005, - 366, 997, 994, 7, 637, 1051, -65, -65, 28, 934, --1000,-1000,-1000, 661, 661, 661, 661,-1000,-1000,-1000, --1000,-1000,-1000, 661, 661, 661,-1000,-1000,-1000,-1000, --1000, -434, 2693, 828,-1000, 661, 1220, 1187,-1000, 79, --1000, 79, -23,-1000,-1000, 2602, 79, 28,-1000,-1000, - 1220,-1000, 1405,-1000,-1000, 1128,-1000,-1000, -301, 1050, - 2016,-1000,-1000,-1000,-1000, 1292,-1000, -254, -257, 28, --1000,-1000,-1000,-1000, 352, 169, 53, 882, 745,-1000, --1000,-1000,-1000,-1000,-1000,-1000, -423,-1000,-1000, 37, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000, 475,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, 28,-1000, --1000,-1000,-1000, 1575, 1292, 1574,-1000,-1000,-1000,-1000, --1000, 274, 1401, 1219,-1000, 128, 1400, 1239,-1000, 2348, --1000,-1000,-1000, -56, 28, 829, 28, 2650, 28, 314, - 28, 795, 28, 39, 28, 28, 28, 28, 28, 28, - 28, 39, 28, 28, 28, 28, 28, 28, 28, 978, - 962, 947, 931, 28, 28, -160, 28, 1399, 1292,-1000, --1000, 1572, 1571, 1395, 1392, 825,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000, 216, -27,-1000, 1240,-1000,-1000, - -22,-1000,-1000, 1292,-1000, 1570, 1569, 1568, 1567, 1566, - 1557, 356, 1556, 1554, 1552, 1542, 1538, 1537,-1000,-1000, --1000, 354,-1000, 1535, 1390, 1386,-1000,-1000,-1000,-1000, - 1388,-1000, 710, 28,-1000, 1267, 28, 28, 974, 53, - 824,-1000,-1000,-1000,-1000,-1000,-1000,-1000, 60, 28, - 381, 241,-1000,-1000,-1000,-1000,-1000, 2954, 205,-1000, --1000,-1000, 1011, 1387, 1385, 822, 49, 1380, 1377, 821, - 1375, 819, 1374, 1373, 814, 1368, 1367, 812, 1366, 808, - 1365, 807, 1364, 794, 1363, 793, 1362, 776, 1361, 754, - 1360, 742, 1359, 741, 39, 28, 28, 28, 28, 28, - 28, 28, 1358, 730, 1348, 727,-1000, 174, -65, -65, --1000,-1000, 923, 3547, -22, -65, 1012, 1534, 1532, 1531, - 1530, 1113, -65,-1000,-1000,-1000,-1000, 28, 721, 53, - 705, 700, 28, 1292,-1000,-1000, 1347, 1090, 1086, 1049, - 1344,-1000, 36,-1000, 953, 699, 45,-1000,-1000,-1000, - 1529, 1343,-1000,-1000, 1528,-1000, 1525,-1000,-1000, 1524, --1000,-1000, 1521,-1000, 1520,-1000, 1519,-1000, 1518,-1000, - 1512,-1000, 1511,-1000, 1509,-1000, 1504,-1000, 1503, 1342, - 675, 1341, 668, 1340, 647, 1337, 613,-1000, 1502,-1000, - 1501,-1000, 1336, 1335,-1000, 2693, 1012, 1334, 1499,-1000, - 398, 354, 1333, 606,-1000, 1247,-1000, 2053, 1332,-1000, - 28, 28, 28,-1000,-1000, 2650,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000, 1498,-1000, 1497,-1000, 1496,-1000, 1495, --1000,-1000,-1000,-1000, -30, 1494, 948, -65,-1000,-1000, --1000, 53,-1000, 887,-1000, 1331, 1329, 1328,-1000, 164, - 704, 2188, 257, 616, 416, 541, 518, 466, 322, 460, - 458, 446,-1000,-1000,-1000,-1000, 430, 153, -22, -65, --1000, 1326, 1207, 1265,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000, 38,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000, 319, 378, 333, 272,-1000,-1000, --1000, 1493, 1325,-1000,-1000,-1000,-1000,-1000,-1000,-1000, --1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, 1490, 53, --1000,-1000,-1000,-1000,-1000, -65, -435, 28, 1227, 1316, - -199, 1315,-1000,-1000, 216,-1000, 3547, 2693, -45, -22, - 1012, 1489, -65, 1311,-1000 -}; - -YYSTATIC YYCONST short YYFARDATA YYPGO[] = { - 0, 53, 57, 6, 1900, 43, 40, 29, 1899, 0, - 1898, 1897, 1896, 195, 50, 1895, 1893, 2, 1892, 48, - 38, 1, 27, 30, 31, 4, 1890, 45, 22, 59, - 1889, 136, 39, 9, 25, 7, 13, 1888, 41, 1887, - 14, 26, 1884, 1883, 5, 3, 8, 10, 1882, 1877, - 1876, 1875, 32, 33, 70, 1873, 1872, 1871, 1870, 12, - 1869, 1868, 11, 1867, 35, 1866, 18, 36, 16, 24, - 42, 23, 458, 65, 1276, 52, 127, 1864, 1863, 1848, - 1847, 1846, 1845, 19, 34, 1844, 1353, 1837, 1836, 28, - 784, 119, 1835, 47, 1245, 1834, 1831, 1830, 1829, 1828, - 1825, 1824, 1817, 1815, 1813, 1812, 1811, 1796, 1795, 1033, - 1794, 64, 62, 1793, 58, 150, 56, 76, 1790, 1789, - 49, 1788, 1787, 1786, 1785, 1784, 1783, 61, 1782, 1781, - 1780, 66, 114, 44, 1778, 15, 284, 1775, 1771, 1770, - 1758, 1757, 1755, 1754, 1753, 1752, 1751, 1748, 1747, 770, - 1746, 1745, 1743, 1742, 1741, 1734, 1713, 1712, 60, 1711, - 1710, 113, 1709, 1708, 1707, 98, 1706, 1704, 1703, 1702, - 1701, 1700, 1699, 69, 1696, 67, 1698, 63, 1695, 484, - 1693, 1692, 1688, 1686, 1685, 1473 -}; -YYSTATIC YYCONST yyr_t YYFARDATA YYR1[]={ - - 0, 109, 109, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 136, - 136, 36, 36, 133, 133, 133, 2, 2, 1, 1, - 1, 9, 24, 24, 23, 23, 23, 134, 134, 134, - 134, 134, 135, 135, 135, 135, 135, 135, 135, 135, - 135, 93, 93, 93, 93, 94, 94, 94, 94, 10, - 11, 73, 72, 72, 59, 61, 61, 61, 62, 62, - 62, 65, 65, 132, 132, 132, 60, 60, 60, 60, - 60, 60, 130, 130, 130, 119, 12, 12, 12, 12, - 12, 12, 118, 137, 113, 138, 139, 111, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 140, 140, 141, 141, 112, - 112, 142, 142, 56, 56, 57, 57, 69, 69, 18, - 18, 18, 18, 18, 19, 19, 68, 68, 67, 67, - 58, 21, 21, 22, 143, 143, 143, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 143, 143, 143, 116, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, - 4, 4, 35, 35, 16, 16, 75, 75, 75, 75, - 75, 75, 75, 7, 7, 7, 7, 8, 8, 8, - 8, 8, 8, 8, 76, 74, 74, 74, 74, 74, - 74, 144, 144, 81, 81, 81, 145, 145, 150, 150, - 150, 150, 150, 150, 150, 150, 146, 82, 82, 82, - 147, 147, 151, 151, 151, 151, 151, 151, 151, 152, - 38, 38, 34, 34, 153, 114, 78, 78, 78, 78, - 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, - 78, 78, 78, 78, 78, 78, 78, 78, 78, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 3, 3, 3, 13, 13, - 13, 13, 13, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 154, 115, - 115, 155, 155, 155, 155, 155, 155, 155, 155, 155, - 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, - 155, 155, 155, 155, 155, 158, 159, 156, 161, 161, - 160, 160, 160, 163, 162, 162, 162, 162, 166, 166, - 166, 169, 164, 167, 168, 165, 165, 165, 117, 170, - 170, 172, 172, 172, 171, 171, 173, 173, 14, 14, - 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, - 174, 174, 174, 174, 174, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 41, 175, 31, 31, 32, 32, 39, - 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 42, 42, - 42, 43, 43, 43, 47, 47, 46, 46, 45, 45, - 44, 44, 48, 48, 49, 49, 49, 50, 50, 50, - 50, 51, 51, 149, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 6, 6, 6, 6, 6, 53, 53, 54, 54, - 55, 55, 25, 25, 26, 26, 27, 27, 27, 70, - 70, 70, 70, 70, 70, 70, 70, 70, 70, 5, - 5, 71, 71, 71, 71, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 20, 20, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 30, 30, 29, 29, 29, 29, 29, - 131, 131, 131, 131, 131, 131, 64, 64, 64, 63, - 63, 87, 87, 84, 84, 85, 17, 17, 37, 37, - 37, 37, 37, 37, 37, 37, 86, 86, 86, 86, - 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, - 86, 176, 176, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 121, 121, 88, 88, 89, 89, - 177, 122, 90, 90, 90, 90, 90, 90, 90, 90, - 90, 90, 123, 123, 178, 178, 178, 66, 66, 179, - 179, 179, 179, 179, 179, 180, 182, 181, 124, 124, - 125, 125, 183, 183, 183, 183, 126, 148, 91, 91, - 91, 91, 91, 91, 91, 91, 91, 91, 127, 127, - 184, 184, 184, 184, 184, 184, 184, 128, 128, 92, - 92, 92, 129, 129, 185, 185, 185, 185 }; -YYSTATIC YYCONST yyr_t YYFARDATA YYR2[]={ - - 0, 0, 2, 4, 4, 3, 1, 1, 1, 1, - 1, 1, 4, 4, 4, 4, 1, 1, 1, 2, - 2, 3, 2, 2, 1, 1, 1, 4, 1, 0, - 2, 1, 3, 2, 4, 6, 1, 1, 1, 1, - 3, 1, 1, 1, 1, 4, 4, 4, 4, 4, - 4, 4, 2, 3, 2, 2, 2, 1, 1, 2, - 1, 2, 4, 6, 3, 5, 7, 9, 3, 4, - 7, 1, 1, 1, 2, 0, 2, 2, 0, 6, - 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, - 2, 3, 1, 2, 3, 7, 0, 2, 2, 2, - 2, 2, 3, 3, 2, 1, 4, 3, 0, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, - 3, 2, 2, 2, 5, 0, 2, 0, 2, 0, - 2, 3, 1, 0, 1, 1, 3, 0, 3, 1, - 1, 1, 1, 1, 0, 2, 4, 3, 0, 2, - 3, 0, 1, 5, 3, 4, 4, 4, 1, 1, - 1, 1, 1, 2, 2, 4, 13, 22, 1, 1, - 5, 3, 4, 7, 0, 2, 2, 2, 2, 2, - 2, 2, 5, 2, 2, 2, 2, 2, 2, 5, - 0, 2, 0, 2, 0, 3, 9, 9, 7, 7, - 1, 1, 1, 2, 2, 1, 4, 0, 1, 1, - 2, 2, 2, 2, 4, 2, 5, 3, 2, 2, - 1, 4, 3, 0, 2, 2, 0, 2, 2, 2, - 2, 2, 1, 1, 1, 1, 9, 0, 2, 2, - 0, 2, 2, 2, 2, 1, 1, 1, 1, 1, - 0, 4, 1, 3, 1, 13, 0, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 5, 8, 6, 5, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 4, 4, 4, 4, 5, 1, 1, 1, 0, 4, - 4, 4, 4, 0, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 5, 1, 0, - 2, 2, 1, 2, 4, 5, 1, 1, 1, 1, - 2, 1, 1, 1, 1, 1, 4, 6, 4, 4, - 11, 1, 5, 3, 5, 3, 1, 2, 2, 1, - 2, 4, 4, 1, 2, 2, 2, 2, 2, 2, - 2, 1, 2, 1, 1, 1, 4, 4, 2, 4, - 2, 0, 1, 1, 3, 1, 3, 1, 0, 3, - 5, 4, 3, 5, 5, 5, 5, 5, 5, 2, - 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, - 4, 4, 4, 5, 5, 5, 5, 4, 4, 4, - 4, 4, 4, 3, 2, 0, 1, 1, 2, 1, - 1, 1, 1, 4, 4, 5, 4, 4, 4, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, - 8, 8, 8, 7, 7, 7, 7, 7, 0, 2, - 2, 0, 2, 2, 0, 2, 0, 2, 0, 2, - 0, 2, 0, 2, 0, 2, 2, 0, 2, 3, - 2, 0, 2, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, - 2, 2, 2, 2, 2, 3, 2, 2, 2, 5, - 3, 2, 2, 2, 2, 2, 5, 4, 6, 2, - 4, 0, 3, 3, 1, 1, 0, 3, 0, 1, - 1, 3, 0, 1, 1, 3, 1, 3, 4, 4, - 4, 4, 5, 1, 1, 1, 1, 1, 1, 1, - 3, 1, 3, 4, 1, 0, 10, 6, 5, 6, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, - 2, 3, 4, 6, 5, 1, 1, 1, 1, 1, - 1, 1, 2, 2, 1, 2, 2, 4, 1, 2, - 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, - 0, 5, 0, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, - 1, 1, 1, 3, 2, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 1, 3, 2, 3, 4, 2, 2, 2, - 5, 5, 7, 4, 3, 2, 3, 2, 1, 1, - 2, 3, 2, 1, 2, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, - 1, 1, 1, 1, 3, 0, 1, 1, 3, 2, - 6, 7, 3, 3, 3, 6, 0, 1, 3, 5, - 6, 4, 4, 1, 3, 3, 1, 1, 1, 1, - 4, 1, 6, 6, 6, 4, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 3, 2, 5, 4, 7, 6, 7, - 6, 9, 8, 3, 8, 4, 0, 2, 0, 1, - 3, 3, 0, 2, 2, 2, 3, 2, 2, 2, - 2, 2, 0, 2, 3, 1, 1, 1, 1, 3, - 8, 2, 3, 1, 1, 3, 3, 3, 4, 6, - 0, 2, 3, 1, 3, 1, 4, 3, 0, 2, - 2, 2, 3, 3, 3, 3, 3, 3, 0, 2, - 2, 3, 3, 4, 2, 1, 1, 3, 5, 0, - 2, 2, 0, 2, 4, 3, 1, 1 }; -YYSTATIC YYCONST short YYFARDATA YYCHK[]={ - --1000,-109,-110,-111,-113,-114,-116,-117,-118,-119, --120,-121,-122,-124,-126,-128,-130,-131,-132, 524, - 525, 459, 527, 528,-133,-134,-135, 531, 532,-139, - 408,-152, 410,-170,-137, 454,-176, 462, 407, 469, - 470, 429, -87, 430, -93, -94, 273, 448, 529, 533, - 534, 535, 536, 537, 538, 539, 59,-138, 409, 411, - 453, 446, 447, 449, -10, -11, 123, 123,-115, 123, - 123, 123, 123, -9, 264, -9, 526, -88, -24, 265, - 264, -24, 123,-140, 314, -1, -2, 261, 260, 263, - -78, -16, 91,-171, 123,-174, 278, 38,-175, 286, - 287, 284, 283, 282, 281, 288, -31, -32, 267, 91, - -9, -90, 468, 468, -92, -1, 468, -86, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 443, 444, 445, -31, -86, 263, -28, -70, -74, -93, - -94, 306, 297, 322, 323,-149, 33, 307, 276, 324, - -52, 275, 91, -5, -76, 268, 412, 413, 414, 357, - 356, 278, 298, 277, 281, 282, 283, 284, 286, 287, - 279, 290, 291, 292, 293, 271, -1, 296, -1, -1, - -1, -1, 262, -77,-172, 318, 378, 61, -73, 40, - -75, -7, -76, 269, 272, 325, 340, -8, 295, 300, - 302, 308, -31, -31,-112,-109, 125,-155, 415,-156, - 417,-154, 419, 420,-117,-157, -2,-131,-120,-133, --132,-135, 471, 457, 507,-158, 506,-160, 418, -95, - -96, -97, -98, -99,-108,-100,-101,-102,-103,-104, --105,-106,-107,-159,-163, 394, 395, 396, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 123, 416, --123,-125,-127,-129, -9, -1, 460,-136, -70, -76, --141, 315, -71, -70, 91, -28,-149, 46, -7, 328, - 329, 330, 331, 332, 326, 346, 352, 337, 364, 365, - 366, 367, 368, 369, 370, 350, 377, 294, 371, -79, - -9,-173,-174, 42, 40, -31, 40, -14, 91, 40, - -14, 40, -14, 40, -14, 40, -14, 40, -14, 40, - 41, 267, -9, 263, 58, 44, 262, -1, 353, 354, - 355, 472, 378, 474, 475, 476, 477, -90, -91, -1, - 329, 330, -1, -71, 41, -36, 61, 288, 262, 44, - 389, 91, 38, 42, 358, 359, 360, 60, 389, 389, - 389, 389, -70, 306, -70, -75, -7, 33, -9, -1, - 280, 279, 289, -28, -1, -76, 42, 470, 47, -28, - 270, 272, 281, 282, 283, 284, 40, -36, -1, 329, - 330, 322, 345, 334, 335, 337, 338, 339, 340, 341, - 342, 343, 344, 361, 354, 336, 351, 326, 370, 294, - -2, 40, 61, -72, -71, -74, -28, -7, -7, 40, - 301, 303, 304, 305, 41, 41, 125,-143,-114,-111, --144,-146,-116,-117,-131,-120,-132, 451, 452,-148, - 507,-133,-135, 506, 321, 421, 426, 471, 407, 125, - -9, -9, 40, 450, 58, 91, -9, -71, 356, 363, - 91,-161,-162,-164,-166,-167,-168, 311,-169, 309, - 313, 312, -9, -2, -9, -24, 40, -23, -24, 266, - 286, 287, -31, -9, -2, -75, -28, -76, 270, 272, - -71, -36, 341,-175, -7, -72, 40,-115,-158, -2, - -9, 125,-178, 461,-131,-179,-180, 466, 467,-181, --132,-135, 463, 125,-183,-177,-179,-182, 338, 461, - 464, 125,-184, 459, 407, 462, 296,-132,-135, 125, --185, 459, 462,-132,-135, -89, 419, 125,-136,-142, - -71, -1, 470, -7, -1, -13, 40, 40, -28, 328, - 329, 330, 331, 376, 370, 326, 478, 364, 365, 366, - 367, 374, 375, 294, 93, 125, 44, 40, -2, 41, - -23, -9, -23, -24, -9, -9, -9, 93, -9, -9, - 473, -1, -1, 330, 329, 327, 336, 389, 40, 61, - 43, 123, 40, 40, 263, -1, 93, -30, -29, 275, - -9, 40, 40, -54, -55, -28, -1, -1, -1, -1, - -70, -28, -9, -1, 280, 93, 93, 93, -1, -1, - -71, -1, 91, -9, -69, 60, 329, 330, 331, 364, - 365, 366, 40, 61, -36, 123, 40, 41, -71, -3, - 372, 373, -1, -9,-115, 123, 123, 123, -9, -9, - 123, -71, 356, 363, 363, -81, -82, -91, -25, -26, - -27, 275, -13, 40, -9, 58, 274, -7, 91, -1, - -9,-161,-165,-158, 310,-165,-165,-165, -71,-158, - -2, -9, 40, 40, 41, -71, -1, 40, -31, -28, - -6, -2, -9, 125, 316, 316, 465, -31, -66, -9, - 42, -36, 61, -31, 61, -31, -31, 61, 61, -1, - 468, -9, 468, 40, -1, 468,-177, 44, 93, -1, - -28, -28, 91, -9, -36, -83, -1, 40, 40,-173, - -36, 41, 41, 93, 41, 41, 41, 41, 41, -12, - 263, 44, 58, 389, 329, 330, 331, 364, 365, 366, - -1, -84, -85, -36, 123, 262, -64, -63, -71, 306, - 44, 93, 44, 275, -71, -71, 62, 44, 42, -5, - -5, -5, 93, 274, 41, -68, -19, -18, 43, 45, - 306, 323, 372, -9, -59, -61, -73, 274, -53, -22, - 60, 41, 125,-112,-145,-147,-127, 274, -7, 91, - -1, -71, -71, -1, 370, 326, -7, 370, 326, -1, - 41, 44, -28, -25, 93, -9, -3, -1, -28, -9, - 93, -2, -9, -9, -24, 274, -36, 41, 40, 41, - 44, 44, -2, -9, -9, 41, 58, 40, 41, 40, - 41, 41, 40, 40, -5, -1, -9, 317, -1, -31, - -71, 93, -38, 478, 503, 504, 505, -9, 41, 389, - -83, 41, 386, 341, 342, 343, 387, 388, 301, 303, - 304, 305, 390, 393, 294, -4, 317, -34, -33,-153, - 479, 481, 482, 483, 484, 276, 277, 281, 282, 283, - 284, 286, 287, 257, 279, 290, 291, 292, 293, 485, - 486, 487, 489, 490, 491, 492, 493, 494, 495, 334, - 496, 280, 289, 336, 497, 341, 488, 356, 389, 501, - 271, 123, -9, 41, -14, -14, -14, -14, -14, -14, - 317, 283, 284, 455, 456, 458, -9, -9, -1, 41, - 44, 61, -59, 125, 44, 61, 263, 263, -29, -9, - 41, 41, -28, 40, -5, -1, 62, -58, -1, 40, - -19, 41, 125, -62, -40,-135, -41, 298, 363, 297, - 286, 287, 284, 283, 282, 281, 293, 292, 291, 290, - 279, 278, 277,-175, 61, -3, 40, 40, 91, -54, - 125, 125,-150, 422, 423, 424, 425,-120,-132,-133, --135, 125,-151, 427, 428, 425,-132,-120,-133,-135, - 125, -3, -28, -9, -93, 449, -1, -28, -27, -38, - 41, 389, -71, 93, -35, 61, 316, 316, 41, 41, - -1, 41, -25, -6, -6, -66, 41, -9, 41, -3, - 40, 93, 93, 93, 93, -36, 41, 58, 58, 40, - -35, -2, 41, 42, 91, -32, 40, 480, 500, 277, - 281, 282, 283, 284, 280, -20, 40, -20, -20, -15, - 509, 482, 483, 276, 277, 281, 282, 283, 284, 286, - 287, 279, 290, 291, 292, 293, 42, 485, 486, 487, - 489, 490, 493, 494, 496, 280, 289, 257, 510, 511, - 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, - 522, 495, 487, 499, 41, -2, 263, 263, 44, -84, - -37, -17, -9, 283, -36, -70, 319, 320, 125, -64, - 123, 61, -25, -1, -67, 44, -56, -57, -71, -65, --135, 357, 362, 40, 91, 40, 91, 40, 91, 40, - 91, 40, 91, 40, 91, 40, 91, 40, 91, 40, - 91, 40, 91, 40, 91, 40, 91, 40, 91, 284, - 283, 282, 281, 40, 91, 40, 91, -31, -36, 123, - 40, -53, -22, -25, -25, -9, 62, -75, -75, -75, - -75, -75, -75, -75, 508, -71, 93, -1, -2, -2, - 274, -39, -41, -36, 299, 286, 287, 284, 283, 282, - 281, 279, 293, 292, 291, 290, 278, 277, -2, -9, - 41, 58, -89, -69, -34, -83, 391, 392, 391, 392, - -9, 93, -9, 43, 125, -36, 91, 91, 502, 44, - 91, 523, 38, 281, 282, 283, 284, 280, -9, 40, - 40, -62, 123, 41, -67, -68, 41, 44, -60, -52, - 363, 297, 345, 299, 263, -9, 306, -70, 299, -9, - -40, -9, -23, -9, -9, -23, -24, -9, -24, -9, - -9, -9, -9, -9, -9, -9, -24, -9, -9, -9, - -9, -9, -9, -9, 40, 91, 40, 91, 40, 91, - 40, 91, -9, -9, -17, -9, 41, -59, 40, 40, - 41, 41, 93, -7, 274, 40, -3, 284, 283, 282, - 281, -66, 40, 41, 41, 41, 93, 43, -9, 44, - -9, -9, 61, -36, 93, 263, -9, 281, 282, 283, - -9, 125, -62, -71, -1, 91, 306, -70, 41, 41, - 93, 263, 41, 41, 93, 41, 93, 41, 41, 93, - 41, 41, 93, 41, 93, 41, 93, 41, 93, 41, - 93, 41, 93, 41, 93, 41, 93, 41, 93, -24, - -9, -9, -9, -9, -9, -9, -9, 41, 93, 41, - 93, 125, -25, -25, 62, -28, -3, -25, -21, -22, - 60, 58, -25, -9, 93, -36, 93, 93, -9, 41, - 58, 58, 58, 41, 125, 61, 93, 263, 40, 41, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 41, 93, 41, 93, 41, 93, 41, 93, - 40, 40, 41, 41, -71, -21, 41, 40, -66, 41, - 93, 44, 41, -33, 41, -9, -9, -9, -40, -49, - -50, -51, -42, -43, -47, -46, -45, -44, -47, -46, - -45, -44, 40, 40, 40, 40, -45, -48, 274, 40, - -35, -25, -80, -36, 41, 41, 41, 41, 299, 263, - 41, 299, 306, -70, 41, -40, 41, -23, -9, 41, - -23, -24, 41, -24, 41, -9, 41, -9, 41, -9, - 41, 41, 41, 41, -47, -46, -45, -44, 41, 41, - -17, -3, -25, 41, 123, 324, 378, 379, 380, 308, - 381, 382, 383, 384, 333, 347, 348, 349, 294, 44, - 263, 41, 41, 41, 41, 40, 41, 40, -36, -25, - 508, -9, 41, 41, 356, 41, -7, -28, -71, 274, - -3, -21, 40, -25, 41 }; -YYSTATIC YYCONST short YYFARDATA YYDEF[]={ - - 1, -2, 2, 0, 0, 329, 6, 7, 8, 9, - 10, 11, 0, 0, 0, 0, 16, 17, 18, 0, - 0, 766, 0, 0, 24, 25, 26, 0, 28, 135, - 0, 266, 204, 0, 425, 0, 0, 772, 105, 829, - 92, 0, 425, 0, 83, 84, 85, 0, 0, 0, - 0, 0, 0, 57, 58, 0, 60, 108, 259, 381, - 0, 751, 752, 217, 425, 425, 139, 1, 0, 782, - 800, 818, 832, 19, 41, 20, 0, 0, 22, 42, - 43, 23, 29, 137, 0, 104, 38, 39, 36, 37, - 217, 184, 0, 378, 0, 385, 0, 0, 425, 388, - 388, 388, 388, 388, 388, 0, 0, 426, 427, 0, - 754, 0, 772, 808, 0, 93, 0, 0, 736, 737, - 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, - 748, 749, 750, 0, 0, 33, 0, 0, 0, 0, - 0, 0, 662, 0, 0, 217, 0, 678, 679, 0, - 683, 0, 0, 543, 230, 545, 546, 547, 548, 0, - 483, 685, 686, 687, 688, 689, 690, 691, 692, 693, - 0, 698, 699, 700, 701, 702, 549, 0, 52, 54, - 55, 56, 59, 0, 380, 382, 383, 0, 61, 0, - 71, 0, 210, 211, 212, 217, 217, 215, 0, 218, - 219, 0, 0, 0, 0, 0, 5, 330, 0, 332, - 0, 0, 336, 337, 338, 339, 0, 341, 342, 343, - 344, 345, 0, 0, 0, 351, 0, 0, 328, 498, - 0, 0, 0, 0, 425, 0, 217, 0, 0, 0, - 217, 0, 0, 329, 0, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 356, 363, - 0, 0, 0, 0, 21, 768, 767, 0, 29, 544, - 107, 0, 136, 551, 0, 554, 217, 0, 308, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 0, 0, 0, - 0, 0, 387, 0, 0, 0, 0, 399, 0, 0, - 400, 0, 401, 0, 402, 0, 403, 0, 404, 424, - 102, 428, 0, 753, 0, 0, 763, 771, 773, 774, - 775, 0, 777, 778, 779, 780, 781, 0, 0, 827, - 830, 831, 94, 712, 713, 714, 0, 0, 31, 0, - 0, 705, 667, 668, 669, 0, 0, 528, 0, 0, - 0, 0, 661, 0, 664, 225, 0, 0, 675, 677, - 680, 0, 682, 684, 0, 0, 0, 0, 0, 0, - 228, 229, 694, 695, 696, 697, 0, 53, 147, 109, - 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 0, 131, 132, 133, 0, - 0, 103, 0, 0, 72, 73, 0, 213, 214, 0, - 220, 221, 222, 223, 64, 68, 3, 140, 329, 0, - 0, 0, 168, 169, 170, 171, 172, 0, 0, 0, - 0, 178, 179, 0, 0, 233, 247, 808, 105, 4, - 331, 333, -2, 0, 340, 0, 0, 0, 217, 0, - 0, 357, 359, 0, 0, 0, 0, 0, 0, 373, - 374, 371, 499, 500, 501, 502, 497, 503, 504, 44, - 0, 0, 0, 506, 507, 508, 0, 511, 512, 513, - 514, 515, 0, 425, 0, 519, 521, 0, 360, 0, - 0, 12, 783, 0, 785, 786, 425, 0, 0, 425, - 793, 794, 0, 13, 801, 425, 803, 425, 805, 0, - 0, 14, 819, 0, 0, 0, 0, 825, 826, 15, - 833, 0, 0, 836, 837, 765, 769, 27, 30, 138, - 142, 0, 0, 0, 40, 0, 0, 289, 0, 185, - 186, 187, 188, 189, 190, 191, 0, 193, 194, 195, - 196, 197, 198, 0, 205, 384, 0, 0, 0, 392, - 0, 0, 0, 0, 0, 0, 0, 96, 756, 0, - 776, 798, 806, 809, 810, 811, 0, 0, 0, 0, - 0, 716, 721, 722, 34, 47, 665, 0, 703, 706, - 707, 0, 0, 0, 529, 530, 48, 49, 50, 51, - 663, 0, 674, 676, 681, 0, 0, 0, 0, 550, - 0, -2, 705, 0, 106, 154, 125, 126, 127, 128, - 129, 130, 0, 379, 62, 75, 69, 217, 0, 526, - 305, 306, -2, 0, 0, 139, 236, 250, 173, 174, - 818, 0, 217, 0, 0, 0, 217, 0, 0, 533, - 534, 536, 0, -2, 0, 0, 0, 0, 0, 353, - 0, 358, 364, 375, 0, 365, 366, 367, 372, 368, - 369, 370, 0, 0, 505, 0, -2, 0, 0, 0, - 0, 524, 525, 355, 0, 0, 0, 0, 0, 787, - 788, 791, 0, 0, 0, 0, 0, 0, 0, 820, - 0, 824, 0, 0, 0, 0, 425, 0, 552, 0, - 0, 260, 0, 0, 289, 0, 200, 555, 0, 386, - 0, 391, 388, 389, 388, 388, 388, 388, 388, 0, - 755, 0, 0, 0, 812, 813, 814, 815, 816, 817, - 828, 0, 723, 0, 75, 32, 0, 717, 0, 0, - 0, 666, 705, 709, 0, 0, 673, 0, 668, 539, - 540, 541, 0, 0, 224, 0, 0, 154, 149, 150, - 151, 152, 153, 0, 0, 78, 65, 0, 0, 0, - 528, 216, 164, 0, 0, 0, 0, 0, 0, 0, - 181, 0, 0, -2, 234, 235, 0, 248, 249, 807, - 334, 308, 260, 0, 346, 348, 349, 307, 0, 0, - 202, 0, 0, 0, 0, 0, 0, 517, -2, 520, - 521, 521, 361, 362, 784, 789, 0, 797, 792, 795, - 802, 804, 770, 796, 821, 822, 0, 0, 835, 0, - 141, 553, 0, 0, 0, 0, 0, 0, 285, 0, - 0, 288, 290, 291, 292, 293, 294, 295, 296, 297, - 298, 299, 0, 0, 0, 202, 0, 0, 262, 0, - 0, 0, 560, 561, 562, 563, 564, 565, 566, 567, - 568, 569, 570, 571, 0, 576, 577, 578, 579, 585, - 586, 587, 588, 589, 590, 591, 610, 610, 594, 610, - 612, 598, 600, 0, 602, 0, 604, 606, 0, 608, - 609, 264, 0, 390, 393, 394, 395, 396, 397, 398, - 0, 97, 98, 99, 100, 101, 758, 760, 799, 710, - 0, 0, 0, 715, 716, 0, 37, 35, 704, 708, - 670, 671, 531, -2, 542, 226, 148, 0, 158, 143, - 155, 134, 63, 74, 76, 77, 432, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 425, 0, 526, -2, -2, 0, 0, - 165, 166, 237, 217, 217, 217, 217, 242, 243, 244, - 245, 167, 251, 217, 217, 217, 255, 256, 257, 258, - 175, 0, 0, 0, 182, 217, 231, 0, 535, 537, - 335, 0, 0, 352, 354, 0, 0, 0, 45, 46, - 509, 516, 0, 522, 523, 0, 823, 834, 768, 147, - 555, 309, 310, 311, 312, 289, 287, 0, 0, 0, - 183, 201, 192, 580, 0, 0, 0, 0, 0, 605, - 572, 573, 574, 575, 599, 592, 0, 593, 595, 596, - 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, - 623, 0, 628, 629, 630, 631, 632, 636, 637, 638, - 639, 640, 641, 642, 643, 644, 646, 647, 648, 649, - 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, - 660, 601, 603, 607, 199, 95, 757, 759, 0, 724, - 725, 728, 729, 0, 731, 0, 726, 727, 711, 718, - 78, 0, 0, 158, 157, 154, 0, 144, 145, 0, - 80, 81, 82, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 66, 75, - 70, 0, 0, 0, 0, 0, 527, 238, 239, 240, - 241, 252, 253, 254, 217, 0, 180, 0, 538, 347, - 0, 203, 429, 430, 431, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 376, 377, - 518, 0, 764, 0, 0, 0, 300, 301, 302, 303, - 0, 581, 0, 0, 263, 0, 0, 0, 0, 0, - 0, 634, 635, 624, 625, 626, 627, 645, 762, 0, - 0, 0, 78, 672, 156, 159, 160, 0, 0, 86, - 87, 88, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 423, 0, -2, -2, - 208, 209, 0, 0, 0, -2, 161, 0, 0, 0, - 0, 0, -2, 261, 286, 304, 582, 0, 0, 0, - 0, 0, 0, 597, 633, 761, 0, 0, 0, 0, - 0, 719, 0, 146, 0, 0, 0, 90, 433, 434, - 0, 0, 436, 437, 0, 438, 0, 405, 407, 0, - 406, 408, 0, 409, 0, 410, 0, 411, 0, 412, - 0, 417, 0, 418, 0, 419, 0, 420, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 421, 0, 422, - 0, 67, 0, 0, 163, 0, 161, 0, 0, 162, - 0, 0, 0, 0, 584, 0, 558, 555, 0, 730, - 0, 0, 0, 735, 720, 0, 91, 89, 474, 435, - 477, 481, 458, 461, 464, 466, 468, 470, 464, 466, - 468, 470, 413, 0, 414, 0, 415, 0, 416, 0, - 468, 472, 206, 207, 0, 0, 202, -2, 790, 313, - 583, 0, 557, 559, 611, 0, 0, 0, 79, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 464, 466, 468, 470, 0, 0, 0, -2, - 246, 0, 0, 0, 732, 733, 734, 455, 475, 476, - 456, 478, 0, 480, 457, 482, 439, 459, 460, 440, - 462, 463, 441, 465, 442, 467, 443, 469, 444, 471, - 445, 446, 447, 448, 0, 0, 0, 0, 453, 454, - 473, 0, 0, 350, 265, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 0, 0, - 479, 449, 450, 451, 452, -2, 0, 0, 0, 0, - 0, 0, 556, 176, 217, 327, 0, 0, 0, 0, - 161, 0, -2, 0, 177 }; -#ifdef YYRECOVER -YYSTATIC YYCONST short yyrecover[] = { --1000 -}; -#endif - -/* SCCSWHAT( "@(#)yypars.c 3.1 88/11/16 22:00:49 " ) */ -#line 3 "D:\\ProjectK3\\src\\tools\\devdiv\\x86\\yypars.c" -#if ! defined(YYAPI_PACKAGE) -/* -** YYAPI_TOKENNAME : name used for return value of yylex -** YYAPI_TOKENTYPE : type of the token -** YYAPI_TOKENEME(t) : the value of the token that the parser should see -** YYAPI_TOKENNONE : the representation when there is no token -** YYAPI_VALUENAME : the name of the value of the token -** YYAPI_VALUETYPE : the type of the value of the token (if null, then the value is derivable from the token itself) -** YYAPI_VALUEOF(v) : how to get the value of the token. -*/ -#define YYAPI_TOKENNAME yychar -#define YYAPI_TOKENTYPE int -#define YYAPI_TOKENEME(t) (t) -#define YYAPI_TOKENNONE -1 -#define YYAPI_TOKENSTR(t) (sprintf(yytokbuf, "%d", t), yytokbuf) -#define YYAPI_VALUENAME yylval -#define YYAPI_VALUETYPE YYSTYPE -#define YYAPI_VALUEOF(v) (v) -#endif -#if ! defined(YYAPI_CALLAFTERYYLEX) -#define YYAPI_CALLAFTERYYLEX -#endif - -# define YYFLAG -1000 -# define YYERROR goto yyerrlab -# define YYACCEPT return(0) -# define YYABORT return(1) - -#ifdef YYDEBUG /* RRR - 10/9/85 */ -char yytokbuf[20]; -# ifndef YYDBFLG -# define YYDBFLG (yydebug) -# endif -# define yyprintf(a, b, c, d) if (YYDBFLG) YYPRINT(a, b, c, d) -#else -# define yyprintf(a, b, c, d) -#endif - -#ifndef YYPRINT -#define YYPRINT printf -#endif - -/* parser for yacc output */ - -#ifdef YYDUMP -int yydump = 1; /* 1 for dumping */ -void yydumpinfo(void); -#endif -#ifdef YYDEBUG -YYSTATIC int yydebug = 0; /* 1 for debugging */ -#endif -YYSTATIC YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */ -YYSTATIC short yys[YYMAXDEPTH]; /* the parse stack */ - -#if ! defined(YYRECURSIVE) -YYSTATIC YYAPI_TOKENTYPE YYAPI_TOKENNAME = YYAPI_TOKENNONE; -#if defined(YYAPI_VALUETYPE) -// YYSTATIC YYAPI_VALUETYPE YYAPI_VALUENAME; FIX -#endif -YYSTATIC int yynerrs = 0; /* number of errors */ -YYSTATIC short yyerrflag = 0; /* error recovery flag */ -#endif - -#ifdef YYRECOVER -/* -** yyscpy : copy f onto t and return a ptr to the null terminator at the -** end of t. -*/ -YYSTATIC char *yyscpy(register char*t, register char*f) - { - while(*t = *f++) - t++; - return(t); /* ptr to the null char */ - } -#endif - -#ifndef YYNEAR -#define YYNEAR -#endif -#ifndef YYPASCAL -#define YYPASCAL -#endif -#ifndef YYLOCAL -#define YYLOCAL -#endif -#if ! defined YYPARSER -#define YYPARSER yyparse -#endif -#if ! defined YYLEX -#define YYLEX yylex -#endif - -#if defined(YYRECURSIVE) - - YYSTATIC YYAPI_TOKENTYPE YYAPI_TOKENNAME = YYAPI_TOKENNONE; - #if defined(YYAPI_VALUETYPE) - YYSTATIC YYAPI_VALUETYPE YYAPI_VALUENAME; - #endif - YYSTATIC int yynerrs = 0; /* number of errors */ - YYSTATIC short yyerrflag = 0; /* error recovery flag */ - - YYSTATIC short yyn; - YYSTATIC short yystate = 0; - YYSTATIC short *yyps= &yys[-1]; - YYSTATIC YYSTYPE *yypv= &yyv[-1]; - YYSTATIC short yyj; - YYSTATIC short yym; - -#endif - -#pragma warning(disable:102) -YYLOCAL YYNEAR YYPASCAL YYPARSER() -{ -#if ! defined(YYRECURSIVE) - - register short yyn; - short yystate, *yyps; - YYSTYPE *yypv; - short yyj, yym; - - YYAPI_TOKENNAME = YYAPI_TOKENNONE; - yystate = 0; - yyps= &yys[-1]; - yypv= &yyv[-1]; -#endif - -#ifdef YYDUMP - yydumpinfo(); -#endif - yystack: /* put a state and value onto the stack */ - -#ifdef YYDEBUG - if(YYAPI_TOKENNAME == YYAPI_TOKENNONE) { - yyprintf( "state %d, token # '%d'\n", yystate, -1, 0 ); - } - else { - yyprintf( "state %d, token # '%s'\n", yystate, YYAPI_TOKENSTR(YYAPI_TOKENNAME), 0 ); - } -#endif - if( ++yyps > &yys[YYMAXDEPTH] ) { - yyerror( "yacc stack overflow" ); - return(1); - } - *yyps = yystate; - ++yypv; - - *yypv = yyval; - -yynewstate: - - yyn = YYPACT[yystate]; - - if( yyn <= YYFLAG ) { /* simple state, no lookahead */ - goto yydefault; - } - if( YYAPI_TOKENNAME == YYAPI_TOKENNONE ) { /* need a lookahead */ - YYAPI_TOKENNAME = YYLEX(); - YYAPI_CALLAFTERYYLEX(YYAPI_TOKENNAME); - } - if( ((yyn += YYAPI_TOKENEME(YYAPI_TOKENNAME)) < 0) || (yyn >= YYLAST) ) { - goto yydefault; - } - if( YYCHK[ yyn = YYACT[ yyn ] ] == YYAPI_TOKENEME(YYAPI_TOKENNAME) ) { /* valid shift */ - yyval = YYAPI_VALUEOF(YYAPI_VALUENAME); - yystate = yyn; - yyprintf( "SHIFT: saw token '%s', now in state %4d\n", YYAPI_TOKENSTR(YYAPI_TOKENNAME), yystate, 0 ); - YYAPI_TOKENNAME = YYAPI_TOKENNONE; - if( yyerrflag > 0 ) { - --yyerrflag; - } - goto yystack; - } - - yydefault: - /* default state action */ - - if( (yyn = YYDEF[yystate]) == -2 ) { - register YYCONST short *yyxi; - - if( YYAPI_TOKENNAME == YYAPI_TOKENNONE ) { - YYAPI_TOKENNAME = YYLEX(); - YYAPI_CALLAFTERYYLEX(YYAPI_TOKENNAME); - yyprintf("LOOKAHEAD: token '%s'\n", YYAPI_TOKENSTR(YYAPI_TOKENNAME), 0, 0); - } -/* -** search exception table, we find a -1 followed by the current state. -** if we find one, we'll look through terminal,state pairs. if we find -** a terminal which matches the current one, we have a match. -** the exception table is when we have a reduce on a terminal. -*/ - -#if YYOPTTIME - yyxi = yyexca + yyexcaind[yystate]; - while(( *yyxi != YYAPI_TOKENEME(YYAPI_TOKENNAME) ) && ( *yyxi >= 0 )){ - yyxi += 2; - } -#else - for(yyxi = yyexca; - (*yyxi != (-1)) || (yyxi[1] != yystate); - yyxi += 2 - ) { - ; /* VOID */ - } - - while( *(yyxi += 2) >= 0 ){ - if( *yyxi == YYAPI_TOKENEME(YYAPI_TOKENNAME) ) { - break; - } - } -#endif - if( (yyn = yyxi[1]) < 0 ) { - return(0); /* accept */ - } - } - - if( yyn == 0 ){ /* error */ - /* error ... attempt to resume parsing */ - - switch( yyerrflag ){ - - case 0: /* brand new error */ -#ifdef YYRECOVER - { - register int i,j; - - for(i = 0; - (yyrecover[i] != -1000) && (yystate > yyrecover[i]); - i += 3 - ) { - ; - } - if(yystate == yyrecover[i]) { - yyprintf("recovered, from state %d to state %d on token # %d\n", - yystate,yyrecover[i+2],yyrecover[i+1] - ); - j = yyrecover[i + 1]; - if(j < 0) { - /* - ** here we have one of the injection set, so we're not quite - ** sure that the next valid thing will be a shift. so we'll - ** count it as an error and continue. - ** actually we're not absolutely sure that the next token - ** we were supposed to get is the one when j > 0. for example, - ** for(+) {;} error recovery with yyerrflag always set, stops - ** after inserting one ; before the +. at the point of the +, - ** we're pretty sure the guy wants a 'for' loop. without - ** setting the flag, when we're almost absolutely sure, we'll - ** give him one, since the only thing we can shift on this - ** error is after finding an expression followed by a + - */ - yyerrflag++; - j = -j; - } - if(yyerrflag <= 1) { /* only on first insertion */ - yyrecerr(YYAPI_TOKENNAME, j); /* what was, what should be first */ - } - yyval = yyeval(j); - yystate = yyrecover[i + 2]; - goto yystack; - } - } -#endif - yyerror("syntax error"); - - yyerrlab: - ++yynerrs; - - case 1: - case 2: /* incompletely recovered error ... try again */ - - yyerrflag = 3; - - /* find a state where "error" is a legal shift action */ - - while ( yyps >= yys ) { - yyn = YYPACT[*yyps] + YYERRCODE; - if( yyn>= 0 && yyn < YYLAST && YYCHK[YYACT[yyn]] == YYERRCODE ){ - yystate = YYACT[yyn]; /* simulate a shift of "error" */ - yyprintf( "SHIFT 'error': now in state %4d\n", yystate, 0, 0 ); - goto yystack; - } - yyn = YYPACT[*yyps]; - - /* the current yyps has no shift onn "error", pop stack */ - - yyprintf( "error recovery pops state %4d, uncovers %4d\n", *yyps, yyps[-1], 0 ); - --yyps; - --yypv; - } - - /* there is no state on the stack with an error shift ... abort */ - - yyabort: - return(1); - - - case 3: /* no shift yet; clobber input char */ - - yyprintf( "error recovery discards token '%s'\n", YYAPI_TOKENSTR(YYAPI_TOKENNAME), 0, 0 ); - - if( YYAPI_TOKENEME(YYAPI_TOKENNAME) == 0 ) goto yyabort; /* don't discard EOF, quit */ - YYAPI_TOKENNAME = YYAPI_TOKENNONE; - goto yynewstate; /* try again in the same state */ - } - } - - /* reduction by production yyn */ -yyreduce: - { - register YYSTYPE *yypvt; - yypvt = yypv; - yyps -= YYR2[yyn]; - yypv -= YYR2[yyn]; - yyval = yypv[1]; - yyprintf("REDUCE: rule %4d, popped %2d tokens, uncovered state %4d, ",yyn, YYR2[yyn], *yyps); - yym = yyn; - yyn = YYR1[yyn]; /* consult goto table to find next state */ - yyj = YYPGO[yyn] + *yyps + 1; - if( (yyj >= YYLAST) || (YYCHK[ yystate = YYACT[yyj] ] != -yyn) ) { - yystate = YYACT[YYPGO[yyn]]; - } - yyprintf("goto state %4d\n", yystate, 0, 0); -#ifdef YYDUMP - yydumpinfo(); -#endif - switch(yym){ - -case 3: -#line 189 "asmparse.y" -{ PASM->EndClass(); } break; -case 4: -#line 190 "asmparse.y" -{ PASM->EndNameSpace(); } break; -case 5: -#line 191 "asmparse.y" -{ if(PASM->m_pCurMethod->m_ulLines[1] ==0) - { PASM->m_pCurMethod->m_ulLines[1] = PASM->m_ulCurLine; - PASM->m_pCurMethod->m_ulColumns[1]=PASM->m_ulCurColumn;} - PASM->EndMethod(); } break; -case 12: -#line 201 "asmparse.y" -{ PASMM->EndAssembly(); } break; -case 13: -#line 202 "asmparse.y" -{ PASMM->EndAssembly(); } break; -case 14: -#line 203 "asmparse.y" -{ PASMM->EndComType(); } break; -case 15: -#line 204 "asmparse.y" -{ PASMM->EndManifestRes(); } break; -case 19: -#line 208 "asmparse.y" -{ -#ifdef _PREFAST_ -#pragma warning(push) -#pragma warning(disable:22011) // Suppress PREFast warning about integer overflow/underflow -#endif - PASM->m_dwSubsystem = yypvt[-0].int32; -#ifdef _PREFAST_ -#pragma warning(pop) -#endif - } break; -case 20: -#line 218 "asmparse.y" -{ PASM->m_dwComImageFlags = yypvt[-0].int32; } break; -case 21: -#line 219 "asmparse.y" -{ PASM->m_dwFileAlignment = yypvt[-0].int32; - if((yypvt[-0].int32 & (yypvt[-0].int32 - 1))||(yypvt[-0].int32 < 0x200)||(yypvt[-0].int32 > 0x10000)) - PASM->report->error("Invalid file alignment, must be power of 2 from 0x200 to 0x10000\n");} break; -case 22: -#line 222 "asmparse.y" -{ PASM->m_stBaseAddress = (ULONGLONG)(*(yypvt[-0].int64)); delete yypvt[-0].int64; - if(PASM->m_stBaseAddress & 0xFFFF) - PASM->report->error("Invalid image base, must be 0x10000-aligned\n");} break; -case 23: -#line 225 "asmparse.y" -{ PASM->m_stSizeOfStackReserve = (size_t)(*(yypvt[-0].int64)); delete yypvt[-0].int64; } break; -case 28: -#line 230 "asmparse.y" -{ PASM->m_fIsMscorlib = TRUE; } break; -case 31: -#line 237 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 32: -#line 238 "asmparse.y" -{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; } break; -case 33: -#line 241 "asmparse.y" -{ LPCSTRToGuid(yypvt[-0].string,&(PASM->m_guidLang)); } break; -case 34: -#line 242 "asmparse.y" -{ LPCSTRToGuid(yypvt[-2].string,&(PASM->m_guidLang)); - LPCSTRToGuid(yypvt[-0].string,&(PASM->m_guidLangVendor));} break; -case 35: -#line 244 "asmparse.y" -{ LPCSTRToGuid(yypvt[-4].string,&(PASM->m_guidLang)); - LPCSTRToGuid(yypvt[-2].string,&(PASM->m_guidLangVendor)); - LPCSTRToGuid(yypvt[-2].string,&(PASM->m_guidDoc));} break; -case 36: -#line 249 "asmparse.y" -{ yyval.string = yypvt[-0].string; } break; -case 37: -#line 250 "asmparse.y" -{ yyval.string = yypvt[-0].string; } break; -case 38: -#line 253 "asmparse.y" -{ yyval.string = yypvt[-0].string; } break; -case 39: -#line 254 "asmparse.y" -{ yyval.string = yypvt[-0].string; } break; -case 40: -#line 255 "asmparse.y" -{ yyval.string = newStringWDel(yypvt[-2].string, '.', yypvt[-0].string); } break; -case 41: -#line 258 "asmparse.y" -{ yyval.int32 = yypvt[-0].int32; } break; -case 42: -#line 261 "asmparse.y" -{ yyval.int64 = yypvt[-0].int64; } break; -case 43: -#line 262 "asmparse.y" -{ yyval.int64 = neg ? new __int64(yypvt[-0].int32) : new __int64((unsigned)yypvt[-0].int32); } break; -case 44: -#line 265 "asmparse.y" -{ yyval.float64 = yypvt[-0].float64; } break; -case 45: -#line 266 "asmparse.y" -{ float f; *((__int32*) (&f)) = yypvt[-1].int32; yyval.float64 = new double(f); } break; -case 46: -#line 267 "asmparse.y" -{ yyval.float64 = (double*) yypvt[-1].int64; } break; -case 47: -#line 271 "asmparse.y" -{ PASM->AddTypeDef(yypvt[-2].binstr,yypvt[-0].string); } break; -case 48: -#line 272 "asmparse.y" -{ PASM->AddTypeDef(yypvt[-2].token,yypvt[-0].string); } break; -case 49: -#line 273 "asmparse.y" -{ PASM->AddTypeDef(yypvt[-2].token,yypvt[-0].string); } break; -case 50: -#line 274 "asmparse.y" -{ yypvt[-2].cad->tkOwner = 0; PASM->AddTypeDef(yypvt[-2].cad,yypvt[-0].string); } break; -case 51: -#line 275 "asmparse.y" -{ PASM->AddTypeDef(yypvt[-2].cad,yypvt[-0].string); } break; -case 52: -#line 280 "asmparse.y" -{ DefineVar(yypvt[-0].string, NULL); } break; -case 53: -#line 281 "asmparse.y" -{ DefineVar(yypvt[-1].string, yypvt[-0].binstr); } break; -case 54: -#line 282 "asmparse.y" -{ UndefVar(yypvt[-0].string); } break; -case 55: -#line 283 "asmparse.y" -{ SkipToken = !IsVarDefined(yypvt[-0].string); - IfEndif++; - } break; -case 56: -#line 286 "asmparse.y" -{ SkipToken = IsVarDefined(yypvt[-0].string); - IfEndif++; - } break; -case 57: -#line 289 "asmparse.y" -{ if(IfEndif == 1) SkipToken = !SkipToken;} break; -case 58: -#line 290 "asmparse.y" -{ if(IfEndif == 0) - PASM->report->error("Unmatched #endif\n"); - else IfEndif--; - } break; -case 59: -#line 294 "asmparse.y" -{ _ASSERTE(!"yylex should have dealt with this"); } break; -case 60: -#line 295 "asmparse.y" -{ } break; -case 61: -#line 299 "asmparse.y" -{ yyval.cad = new CustomDescr(PASM->m_tkCurrentCVOwner, yypvt[-0].token, NULL); } break; -case 62: -#line 300 "asmparse.y" -{ yyval.cad = new CustomDescr(PASM->m_tkCurrentCVOwner, yypvt[-2].token, yypvt[-0].binstr); } break; -case 63: -#line 301 "asmparse.y" -{ yyval.cad = new CustomDescr(PASM->m_tkCurrentCVOwner, yypvt[-4].token, yypvt[-1].binstr); } break; -case 64: -#line 302 "asmparse.y" -{ yyval.cad = new CustomDescr(PASM->m_tkCurrentCVOwner, yypvt[-2].int32, yypvt[-1].binstr); } break; -case 65: -#line 305 "asmparse.y" -{ yyval.cad = new CustomDescr(yypvt[-2].token, yypvt[-0].token, NULL); } break; -case 66: -#line 306 "asmparse.y" -{ yyval.cad = new CustomDescr(yypvt[-4].token, yypvt[-2].token, yypvt[-0].binstr); } break; -case 67: -#line 308 "asmparse.y" -{ yyval.cad = new CustomDescr(yypvt[-6].token, yypvt[-4].token, yypvt[-1].binstr); } break; -case 68: -#line 309 "asmparse.y" -{ yyval.cad = new CustomDescr(PASM->m_tkCurrentCVOwner, yypvt[-2].int32, yypvt[-1].binstr); } break; -case 69: -#line 312 "asmparse.y" -{ yyval.int32 = yypvt[-2].token; bParsingByteArray = TRUE; } break; -case 70: -#line 316 "asmparse.y" -{ PASM->m_pCustomDescrList = NULL; - PASM->m_tkCurrentCVOwner = yypvt[-4].token; - yyval.int32 = yypvt[-2].token; bParsingByteArray = TRUE; } break; -case 71: -#line 321 "asmparse.y" -{ yyval.token = yypvt[-0].token; } break; -case 72: -#line 324 "asmparse.y" -{ yyval.token = yypvt[-0].token; } break; -case 73: -#line 325 "asmparse.y" -{ yyval.token = yypvt[-0].token; } break; -case 74: -#line 329 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; - yyval.binstr->appendInt16(nCustomBlobNVPairs); - yyval.binstr->append(yypvt[-0].binstr); - nCustomBlobNVPairs = 0; } break; -case 75: -#line 335 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt16(VAL16(0x0001)); } break; -case 76: -#line 336 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; - yyval.binstr->appendFrom(yypvt[-0].binstr, (*(yypvt[-0].binstr->ptr()) == ELEMENT_TYPE_SZARRAY) ? 2 : 1); } break; -case 77: -#line 338 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; } break; -case 78: -#line 341 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 79: -#line 343 "asmparse.y" -{ yyval.binstr = yypvt[-5].binstr; yyval.binstr->appendInt8(yypvt[-4].int32); - yyval.binstr->append(yypvt[-3].binstr); - AppendStringWithLength(yyval.binstr,yypvt[-2].string); - yyval.binstr->appendFrom(yypvt[-0].binstr, (*(yypvt[-0].binstr->ptr()) == ELEMENT_TYPE_SZARRAY) ? 2 : 1); - nCustomBlobNVPairs++; } break; -case 80: -#line 348 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; } break; -case 81: -#line 351 "asmparse.y" -{ yyval.int32 = SERIALIZATION_TYPE_FIELD; } break; -case 82: -#line 352 "asmparse.y" -{ yyval.int32 = SERIALIZATION_TYPE_PROPERTY; } break; -case 83: -#line 355 "asmparse.y" -{ if(yypvt[-0].cad->tkOwner && !yypvt[-0].cad->tkInterfacePair) - PASM->DefineCV(yypvt[-0].cad); - else if(PASM->m_pCustomDescrList) - PASM->m_pCustomDescrList->PUSH(yypvt[-0].cad); } break; -case 84: -#line 359 "asmparse.y" -{ PASM->DefineCV(yypvt[-0].cad); } break; -case 85: -#line 360 "asmparse.y" -{ CustomDescr* pNew = new CustomDescr(yypvt[-0].tdd->m_pCA); - if(pNew->tkOwner == 0) pNew->tkOwner = PASM->m_tkCurrentCVOwner; - if(pNew->tkOwner) - PASM->DefineCV(pNew); - else if(PASM->m_pCustomDescrList) - PASM->m_pCustomDescrList->PUSH(pNew); } break; -case 86: -#line 368 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 87: -#line 369 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_TYPE); } break; -case 88: -#line 370 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_TAGGED_OBJECT); } break; -case 89: -#line 371 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); - AppendStringWithLength(yyval.binstr,yypvt[-0].string); } break; -case 90: -#line 373 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); - AppendStringWithLength(yyval.binstr,PASM->ReflectionNotation(yypvt[-0].token)); } break; -case 91: -#line 375 "asmparse.y" -{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 92: -#line 380 "asmparse.y" -{ PASMM->SetModuleName(NULL); PASM->m_tkCurrentCVOwner=1; } break; -case 93: -#line 381 "asmparse.y" -{ PASMM->SetModuleName(yypvt[-0].string); PASM->m_tkCurrentCVOwner=1; } break; -case 94: -#line 382 "asmparse.y" -{ BinStr* pbs = new BinStr(); - unsigned L = (unsigned)strlen(yypvt[-0].string); - memcpy((char*)(pbs->getBuff(L)),yypvt[-0].string,L); - PASM->EmitImport(pbs); delete pbs;} break; -case 95: -#line 389 "asmparse.y" -{ /*PASM->SetDataSection(); PASM->EmitDataLabel($7);*/ - PASM->m_VTFList.PUSH(new VTFEntry((USHORT)yypvt[-4].int32, (USHORT)yypvt[-2].int32, yypvt[-0].string)); } break; -case 96: -#line 393 "asmparse.y" -{ yyval.int32 = 0; } break; -case 97: -#line 394 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32 | COR_VTABLE_32BIT; } break; -case 98: -#line 395 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32 | COR_VTABLE_64BIT; } break; -case 99: -#line 396 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32 | COR_VTABLE_FROM_UNMANAGED; } break; -case 100: -#line 397 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32 | COR_VTABLE_CALL_MOST_DERIVED; } break; -case 101: -#line 398 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32 | COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN; } break; -case 102: -#line 401 "asmparse.y" -{ PASM->m_pVTable = yypvt[-1].binstr; } break; -case 103: -#line 404 "asmparse.y" -{ bParsingByteArray = TRUE; } break; -case 104: -#line 408 "asmparse.y" -{ PASM->StartNameSpace(yypvt[-0].string); } break; -case 105: -#line 411 "asmparse.y" -{ newclass = TRUE; } break; -case 106: -#line 414 "asmparse.y" -{ if(yypvt[-0].typarlist) FixupConstraints(); - PASM->StartClass(yypvt[-1].string, yypvt[-2].classAttr, yypvt[-0].typarlist); - TyParFixupList.RESET(false); - newclass = FALSE; - } break; -case 107: -#line 420 "asmparse.y" -{ PASM->AddClass(); } break; -case 108: -#line 423 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) 0; } break; -case 109: -#line 424 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdVisibilityMask) | tdPublic); } break; -case 110: -#line 425 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdVisibilityMask) | tdNotPublic); } break; -case 111: -#line 426 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | 0x80000000 | tdSealed); } break; -case 112: -#line 427 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | 0x40000000); } break; -case 113: -#line 428 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdInterface | tdAbstract); } break; -case 114: -#line 429 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdSealed); } break; -case 115: -#line 430 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdAbstract); } break; -case 116: -#line 431 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdLayoutMask) | tdAutoLayout); } break; -case 117: -#line 432 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdLayoutMask) | tdSequentialLayout); } break; -case 118: -#line 433 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdLayoutMask) | tdExplicitLayout); } break; -case 119: -#line 434 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdStringFormatMask) | tdAnsiClass); } break; -case 120: -#line 435 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdStringFormatMask) | tdUnicodeClass); } break; -case 121: -#line 436 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdStringFormatMask) | tdAutoClass); } break; -case 122: -#line 437 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdImport); } break; -case 123: -#line 438 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdSerializable); } break; -case 124: -#line 439 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdWindowsRuntime); } break; -case 125: -#line 440 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedPublic); } break; -case 126: -#line 441 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedPrivate); } break; -case 127: -#line 442 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedFamily); } break; -case 128: -#line 443 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedAssembly); } break; -case 129: -#line 444 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedFamANDAssem); } break; -case 130: -#line 445 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedFamORAssem); } break; -case 131: -#line 446 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdBeforeFieldInit); } break; -case 132: -#line 447 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdSpecialName); } break; -case 133: -#line 448 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr); } break; -case 134: -#line 449 "asmparse.y" -{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].int32); } break; -case 136: -#line 453 "asmparse.y" -{ PASM->m_crExtends = yypvt[-0].token; } break; -case 141: -#line 464 "asmparse.y" -{ PASM->AddToImplList(yypvt[-0].token); } break; -case 142: -#line 465 "asmparse.y" -{ PASM->AddToImplList(yypvt[-0].token); } break; -case 143: -#line 469 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 144: -#line 470 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 145: -#line 473 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt32(yypvt[-0].token); } break; -case 146: -#line 474 "asmparse.y" -{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->appendInt32(yypvt[-0].token); } break; -case 147: -#line 477 "asmparse.y" -{ yyval.typarlist = NULL; PASM->m_TyParList = NULL;} break; -case 148: -#line 478 "asmparse.y" -{ yyval.typarlist = yypvt[-1].typarlist; PASM->m_TyParList = yypvt[-1].typarlist;} break; -case 149: -#line 481 "asmparse.y" -{ yyval.int32 = gpCovariant; } break; -case 150: -#line 482 "asmparse.y" -{ yyval.int32 = gpContravariant; } break; -case 151: -#line 483 "asmparse.y" -{ yyval.int32 = gpReferenceTypeConstraint; } break; -case 152: -#line 484 "asmparse.y" -{ yyval.int32 = gpNotNullableValueTypeConstraint; } break; -case 153: -#line 485 "asmparse.y" -{ yyval.int32 = gpDefaultConstructorConstraint; } break; -case 154: -#line 488 "asmparse.y" -{ yyval.int32 = 0; } break; -case 155: -#line 489 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32 | yypvt[-0].int32; } break; -case 156: -#line 492 "asmparse.y" -{yyval.typarlist = new TyParList(yypvt[-3].int32, yypvt[-2].binstr, yypvt[-1].string, yypvt[-0].typarlist);} break; -case 157: -#line 493 "asmparse.y" -{yyval.typarlist = new TyParList(yypvt[-2].int32, NULL, yypvt[-1].string, yypvt[-0].typarlist);} break; -case 158: -#line 496 "asmparse.y" -{ yyval.typarlist = NULL; } break; -case 159: -#line 497 "asmparse.y" -{ yyval.typarlist = yypvt[-0].typarlist; } break; -case 160: -#line 500 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; } break; -case 161: -#line 503 "asmparse.y" -{ yyval.int32= 0; } break; -case 162: -#line 504 "asmparse.y" -{ yyval.int32 = yypvt[-0].int32; } break; -case 163: -#line 507 "asmparse.y" -{ yyval.int32 = yypvt[-2].int32; } break; -case 164: -#line 511 "asmparse.y" -{ if(PASM->m_pCurMethod->m_ulLines[1] ==0) - { PASM->m_pCurMethod->m_ulLines[1] = PASM->m_ulCurLine; - PASM->m_pCurMethod->m_ulColumns[1]=PASM->m_ulCurColumn;} - PASM->EndMethod(); } break; -case 165: -#line 515 "asmparse.y" -{ PASM->EndClass(); } break; -case 166: -#line 516 "asmparse.y" -{ PASM->EndEvent(); } break; -case 167: -#line 517 "asmparse.y" -{ PASM->EndProp(); } break; -case 173: -#line 523 "asmparse.y" -{ PASM->m_pCurClass->m_ulSize = yypvt[-0].int32; } break; -case 174: -#line 524 "asmparse.y" -{ PASM->m_pCurClass->m_ulPack = yypvt[-0].int32; } break; -case 175: -#line 525 "asmparse.y" -{ PASMM->EndComType(); } break; -case 176: -#line 527 "asmparse.y" -{ BinStr *sig1 = parser->MakeSig(yypvt[-7].int32, yypvt[-6].binstr, yypvt[-1].binstr); - BinStr *sig2 = new BinStr(); sig2->append(sig1); - PASM->AddMethodImpl(yypvt[-11].token,yypvt[-9].string,sig1,yypvt[-5].token,yypvt[-3].string,sig2); - PASM->ResetArgNameList(); - } break; -case 177: -#line 533 "asmparse.y" -{ PASM->AddMethodImpl(yypvt[-17].token,yypvt[-15].string, - (yypvt[-14].int32==0 ? parser->MakeSig(yypvt[-19].int32,yypvt[-18].binstr,yypvt[-12].binstr) : - parser->MakeSig(yypvt[-19].int32| IMAGE_CEE_CS_CALLCONV_GENERIC,yypvt[-18].binstr,yypvt[-12].binstr,yypvt[-14].int32)), - yypvt[-6].token,yypvt[-4].string, - (yypvt[-3].int32==0 ? parser->MakeSig(yypvt[-8].int32,yypvt[-7].binstr,yypvt[-1].binstr) : - parser->MakeSig(yypvt[-8].int32| IMAGE_CEE_CS_CALLCONV_GENERIC,yypvt[-7].binstr,yypvt[-1].binstr,yypvt[-3].int32))); - PASM->ResetArgNameList(); - } break; -case 180: -#line 543 "asmparse.y" -{ if((yypvt[-1].int32 > 0) && (yypvt[-1].int32 <= (int)PASM->m_pCurClass->m_NumTyPars)) - PASM->m_pCustomDescrList = PASM->m_pCurClass->m_TyPars[yypvt[-1].int32-1].CAList(); - else - PASM->report->error("Type parameter index out of range\n"); - } break; -case 181: -#line 548 "asmparse.y" -{ int n = PASM->m_pCurClass->FindTyPar(yypvt[-0].string); - if(n >= 0) - PASM->m_pCustomDescrList = PASM->m_pCurClass->m_TyPars[n].CAList(); - else - PASM->report->error("Type parameter '%s' undefined\n",yypvt[-0].string); - } break; -case 182: -#line 554 "asmparse.y" -{ yypvt[-0].cad->tkInterfacePair = yypvt[-1].token; - if(PASM->m_pCustomDescrList) - PASM->m_pCustomDescrList->PUSH(yypvt[-0].cad); - } break; -case 183: -#line 562 "asmparse.y" -{ yypvt[-3].binstr->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); - PASM->AddField(yypvt[-2].string, yypvt[-3].binstr, yypvt[-4].fieldAttr, yypvt[-1].string, yypvt[-0].binstr, yypvt[-5].int32); } break; -case 184: -#line 566 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) 0; } break; -case 185: -#line 567 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].fieldAttr | fdStatic); } break; -case 186: -#line 568 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdPublic); } break; -case 187: -#line 569 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdPrivate); } break; -case 188: -#line 570 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdFamily); } break; -case 189: -#line 571 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].fieldAttr | fdInitOnly); } break; -case 190: -#line 572 "asmparse.y" -{ yyval.fieldAttr = yypvt[-1].fieldAttr; } break; -case 191: -#line 573 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].fieldAttr | fdSpecialName); } break; -case 192: -#line 586 "asmparse.y" -{ PASM->m_pMarshal = yypvt[-1].binstr; } break; -case 193: -#line 587 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdAssembly); } break; -case 194: -#line 588 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdFamANDAssem); } break; -case 195: -#line 589 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdFamORAssem); } break; -case 196: -#line 590 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdPrivateScope); } break; -case 197: -#line 591 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].fieldAttr | fdLiteral); } break; -case 198: -#line 592 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].fieldAttr | fdNotSerialized); } break; -case 199: -#line 593 "asmparse.y" -{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].int32); } break; -case 200: -#line 596 "asmparse.y" -{ yyval.string = 0; } break; -case 201: -#line 597 "asmparse.y" -{ yyval.string = yypvt[-0].string; } break; -case 202: -#line 600 "asmparse.y" -{ yyval.binstr = NULL; } break; -case 203: -#line 601 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 204: -#line 604 "asmparse.y" -{ yyval.int32 = 0xFFFFFFFF; } break; -case 205: -#line 605 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32; } break; -case 206: -#line 610 "asmparse.y" -{ PASM->ResetArgNameList(); - if (yypvt[-3].binstr == NULL) - { - if((iCallConv)&&((yypvt[-8].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); - yyval.token = PASM->MakeMemberRef(yypvt[-6].token, yypvt[-4].string, parser->MakeSig(yypvt[-8].int32|iCallConv, yypvt[-7].binstr, yypvt[-1].binstr)); - } - else - { - mdToken mr; - if((iCallConv)&&((yypvt[-8].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); - mr = PASM->MakeMemberRef(yypvt[-6].token, yypvt[-4].string, - parser->MakeSig(yypvt[-8].int32 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, yypvt[-7].binstr, yypvt[-1].binstr, corCountArgs(yypvt[-3].binstr))); - yyval.token = PASM->MakeMethodSpec(mr, - parser->MakeSig(IMAGE_CEE_CS_CALLCONV_INSTANTIATION, 0, yypvt[-3].binstr)); - } - } break; -case 207: -#line 627 "asmparse.y" -{ PASM->ResetArgNameList(); - if((iCallConv)&&((yypvt[-8].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); - yyval.token = PASM->MakeMemberRef(yypvt[-6].token, yypvt[-4].string, - parser->MakeSig(yypvt[-8].int32 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, yypvt[-7].binstr, yypvt[-1].binstr, yypvt[-3].int32)); - } break; -case 208: -#line 633 "asmparse.y" -{ PASM->ResetArgNameList(); - if (yypvt[-3].binstr == NULL) - { - if((iCallConv)&&((yypvt[-6].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); - yyval.token = PASM->MakeMemberRef(mdTokenNil, yypvt[-4].string, parser->MakeSig(yypvt[-6].int32|iCallConv, yypvt[-5].binstr, yypvt[-1].binstr)); - } - else - { - mdToken mr; - if((iCallConv)&&((yypvt[-6].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); - mr = PASM->MakeMemberRef(mdTokenNil, yypvt[-4].string, parser->MakeSig(yypvt[-6].int32 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, yypvt[-5].binstr, yypvt[-1].binstr, corCountArgs(yypvt[-3].binstr))); - yyval.token = PASM->MakeMethodSpec(mr, - parser->MakeSig(IMAGE_CEE_CS_CALLCONV_INSTANTIATION, 0, yypvt[-3].binstr)); - } - } break; -case 209: -#line 649 "asmparse.y" -{ PASM->ResetArgNameList(); - if((iCallConv)&&((yypvt[-6].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); - yyval.token = PASM->MakeMemberRef(mdTokenNil, yypvt[-4].string, parser->MakeSig(yypvt[-6].int32 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, yypvt[-5].binstr, yypvt[-1].binstr, yypvt[-3].int32)); - } break; -case 210: -#line 653 "asmparse.y" -{ yyval.token = yypvt[-0].token; } break; -case 211: -#line 654 "asmparse.y" -{ yyval.token = yypvt[-0].tdd->m_tkTypeSpec; } break; -case 212: -#line 655 "asmparse.y" -{ yyval.token = yypvt[-0].tdd->m_tkTypeSpec; } break; -case 213: -#line 658 "asmparse.y" -{ yyval.int32 = (yypvt[-0].int32 | IMAGE_CEE_CS_CALLCONV_HASTHIS); } break; -case 214: -#line 659 "asmparse.y" -{ yyval.int32 = (yypvt[-0].int32 | IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS); } break; -case 215: -#line 660 "asmparse.y" -{ yyval.int32 = yypvt[-0].int32; } break; -case 216: -#line 661 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32; } break; -case 217: -#line 664 "asmparse.y" -{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_DEFAULT; } break; -case 218: -#line 665 "asmparse.y" -{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_DEFAULT; } break; -case 219: -#line 666 "asmparse.y" -{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_VARARG; } break; -case 220: -#line 667 "asmparse.y" -{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_C; } break; -case 221: -#line 668 "asmparse.y" -{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_STDCALL; } break; -case 222: -#line 669 "asmparse.y" -{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_THISCALL; } break; -case 223: -#line 670 "asmparse.y" -{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_FASTCALL; } break; -case 224: -#line 673 "asmparse.y" -{ yyval.token = yypvt[-1].int32; } break; -case 225: -#line 676 "asmparse.y" -{ yyval.token = yypvt[-0].token; - PASM->delArgNameList(PASM->m_firstArgName); - PASM->m_firstArgName = parser->m_ANSFirst.POP(); - PASM->m_lastArgName = parser->m_ANSLast.POP(); - PASM->SetMemberRefFixup(yypvt[-0].token,iOpcodeLen); } break; -case 226: -#line 682 "asmparse.y" -{ yypvt[-3].binstr->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); - yyval.token = PASM->MakeMemberRef(yypvt[-2].token, yypvt[-0].string, yypvt[-3].binstr); - PASM->SetMemberRefFixup(yyval.token,iOpcodeLen); } break; -case 227: -#line 686 "asmparse.y" -{ yypvt[-1].binstr->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); - yyval.token = PASM->MakeMemberRef(NULL, yypvt[-0].string, yypvt[-1].binstr); - PASM->SetMemberRefFixup(yyval.token,iOpcodeLen); } break; -case 228: -#line 689 "asmparse.y" -{ yyval.token = yypvt[-0].tdd->m_tkTypeSpec; - PASM->SetMemberRefFixup(yyval.token,iOpcodeLen); } break; -case 229: -#line 691 "asmparse.y" -{ yyval.token = yypvt[-0].tdd->m_tkTypeSpec; - PASM->SetMemberRefFixup(yyval.token,iOpcodeLen); } break; -case 230: -#line 693 "asmparse.y" -{ yyval.token = yypvt[-0].token; - PASM->SetMemberRefFixup(yyval.token,iOpcodeLen); } break; -case 231: -#line 698 "asmparse.y" -{ PASM->ResetEvent(yypvt[-0].string, yypvt[-1].token, yypvt[-2].eventAttr); } break; -case 232: -#line 699 "asmparse.y" -{ PASM->ResetEvent(yypvt[-0].string, mdTypeRefNil, yypvt[-1].eventAttr); } break; -case 233: -#line 703 "asmparse.y" -{ yyval.eventAttr = (CorEventAttr) 0; } break; -case 234: -#line 704 "asmparse.y" -{ yyval.eventAttr = yypvt[-1].eventAttr; } break; -case 235: -#line 705 "asmparse.y" -{ yyval.eventAttr = (CorEventAttr) (yypvt[-1].eventAttr | evSpecialName); } break; -case 238: -#line 712 "asmparse.y" -{ PASM->SetEventMethod(0, yypvt[-0].token); } break; -case 239: -#line 713 "asmparse.y" -{ PASM->SetEventMethod(1, yypvt[-0].token); } break; -case 240: -#line 714 "asmparse.y" -{ PASM->SetEventMethod(2, yypvt[-0].token); } break; -case 241: -#line 715 "asmparse.y" -{ PASM->SetEventMethod(3, yypvt[-0].token); } break; -case 246: -#line 724 "asmparse.y" -{ PASM->ResetProp(yypvt[-4].string, - parser->MakeSig((IMAGE_CEE_CS_CALLCONV_PROPERTY | - (yypvt[-6].int32 & IMAGE_CEE_CS_CALLCONV_HASTHIS)),yypvt[-5].binstr,yypvt[-2].binstr), yypvt[-7].propAttr, yypvt[-0].binstr);} break; -case 247: -#line 729 "asmparse.y" -{ yyval.propAttr = (CorPropertyAttr) 0; } break; -case 248: -#line 730 "asmparse.y" -{ yyval.propAttr = yypvt[-1].propAttr; } break; -case 249: -#line 731 "asmparse.y" -{ yyval.propAttr = (CorPropertyAttr) (yypvt[-1].propAttr | prSpecialName); } break; -case 252: -#line 739 "asmparse.y" -{ PASM->SetPropMethod(0, yypvt[-0].token); } break; -case 253: -#line 740 "asmparse.y" -{ PASM->SetPropMethod(1, yypvt[-0].token); } break; -case 254: -#line 741 "asmparse.y" -{ PASM->SetPropMethod(2, yypvt[-0].token); } break; -case 259: -#line 749 "asmparse.y" -{ PASM->ResetForNextMethod(); - uMethodBeginLine = PASM->m_ulCurLine; - uMethodBeginColumn=PASM->m_ulCurColumn; - } break; -case 260: -#line 755 "asmparse.y" -{ yyval.binstr = NULL; } break; -case 261: -#line 756 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; } break; -case 262: -#line 759 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 263: -#line 760 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; } break; -case 264: -#line 763 "asmparse.y" -{ bParsingByteArray = TRUE; } break; -case 265: -#line 767 "asmparse.y" -{ BinStr* sig; - if (yypvt[-5].typarlist == NULL) sig = parser->MakeSig(yypvt[-10].int32, yypvt[-8].binstr, yypvt[-3].binstr); - else { - FixupTyPars(yypvt[-8].binstr); - sig = parser->MakeSig(yypvt[-10].int32 | IMAGE_CEE_CS_CALLCONV_GENERIC, yypvt[-8].binstr, yypvt[-3].binstr, yypvt[-5].typarlist->Count()); - FixupConstraints(); - } - PASM->StartMethod(yypvt[-6].string, sig, yypvt[-11].methAttr, yypvt[-7].binstr, yypvt[-9].int32, yypvt[-5].typarlist); - TyParFixupList.RESET(false); - PASM->SetImplAttr((USHORT)yypvt[-1].implAttr); - PASM->m_pCurMethod->m_ulLines[0] = uMethodBeginLine; - PASM->m_pCurMethod->m_ulColumns[0]=uMethodBeginColumn; - } break; -case 266: -#line 782 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) 0; } break; -case 267: -#line 783 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdStatic); } break; -case 268: -#line 784 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdPublic); } break; -case 269: -#line 785 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdPrivate); } break; -case 270: -#line 786 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdFamily); } break; -case 271: -#line 787 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdFinal); } break; -case 272: -#line 788 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdSpecialName); } break; -case 273: -#line 789 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdVirtual); } break; -case 274: -#line 790 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdCheckAccessOnOverride); } break; -case 275: -#line 791 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdAbstract); } break; -case 276: -#line 792 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdAssem); } break; -case 277: -#line 793 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdFamANDAssem); } break; -case 278: -#line 794 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdFamORAssem); } break; -case 279: -#line 795 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdPrivateScope); } break; -case 280: -#line 796 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdHideBySig); } break; -case 281: -#line 797 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdNewSlot); } break; -case 282: -#line 798 "asmparse.y" -{ yyval.methAttr = yypvt[-1].methAttr; } break; -case 283: -#line 799 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdUnmanagedExport); } break; -case 284: -#line 800 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdRequireSecObject); } break; -case 285: -#line 801 "asmparse.y" -{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].int32); } break; -case 286: -#line 803 "asmparse.y" -{ PASM->SetPinvoke(yypvt[-4].binstr,0,yypvt[-2].binstr,yypvt[-1].pinvAttr); - yyval.methAttr = (CorMethodAttr) (yypvt[-7].methAttr | mdPinvokeImpl); } break; -case 287: -#line 806 "asmparse.y" -{ PASM->SetPinvoke(yypvt[-2].binstr,0,NULL,yypvt[-1].pinvAttr); - yyval.methAttr = (CorMethodAttr) (yypvt[-5].methAttr | mdPinvokeImpl); } break; -case 288: -#line 809 "asmparse.y" -{ PASM->SetPinvoke(new BinStr(),0,NULL,yypvt[-1].pinvAttr); - yyval.methAttr = (CorMethodAttr) (yypvt[-4].methAttr | mdPinvokeImpl); } break; -case 289: -#line 813 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) 0; } break; -case 290: -#line 814 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmNoMangle); } break; -case 291: -#line 815 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCharSetAnsi); } break; -case 292: -#line 816 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCharSetUnicode); } break; -case 293: -#line 817 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCharSetAuto); } break; -case 294: -#line 818 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmSupportsLastError); } break; -case 295: -#line 819 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCallConvWinapi); } break; -case 296: -#line 820 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCallConvCdecl); } break; -case 297: -#line 821 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCallConvStdcall); } break; -case 298: -#line 822 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCallConvThiscall); } break; -case 299: -#line 823 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCallConvFastcall); } break; -case 300: -#line 824 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-3].pinvAttr | pmBestFitEnabled); } break; -case 301: -#line 825 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-3].pinvAttr | pmBestFitDisabled); } break; -case 302: -#line 826 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-3].pinvAttr | pmThrowOnUnmappableCharEnabled); } break; -case 303: -#line 827 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-3].pinvAttr | pmThrowOnUnmappableCharDisabled); } break; -case 304: -#line 828 "asmparse.y" -{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].int32); } break; -case 305: -#line 831 "asmparse.y" -{ yyval.string = newString(COR_CTOR_METHOD_NAME); } break; -case 306: -#line 832 "asmparse.y" -{ yyval.string = newString(COR_CCTOR_METHOD_NAME); } break; -case 307: -#line 833 "asmparse.y" -{ yyval.string = yypvt[-0].string; } break; -case 308: -#line 836 "asmparse.y" -{ yyval.int32 = 0; } break; -case 309: -#line 837 "asmparse.y" -{ yyval.int32 = yypvt[-3].int32 | pdIn; } break; -case 310: -#line 838 "asmparse.y" -{ yyval.int32 = yypvt[-3].int32 | pdOut; } break; -case 311: -#line 839 "asmparse.y" -{ yyval.int32 = yypvt[-3].int32 | pdOptional; } break; -case 312: -#line 840 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32 + 1; } break; -case 313: -#line 843 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (miIL | miManaged); } break; -case 314: -#line 844 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) ((yypvt[-1].implAttr & 0xFFF4) | miNative); } break; -case 315: -#line 845 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) ((yypvt[-1].implAttr & 0xFFF4) | miIL); } break; -case 316: -#line 846 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) ((yypvt[-1].implAttr & 0xFFF4) | miOPTIL); } break; -case 317: -#line 847 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) ((yypvt[-1].implAttr & 0xFFFB) | miManaged); } break; -case 318: -#line 848 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) ((yypvt[-1].implAttr & 0xFFFB) | miUnmanaged); } break; -case 319: -#line 849 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miForwardRef); } break; -case 320: -#line 850 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miPreserveSig); } break; -case 321: -#line 851 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miRuntime); } break; -case 322: -#line 852 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miInternalCall); } break; -case 323: -#line 853 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miSynchronized); } break; -case 324: -#line 854 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miNoInlining); } break; -case 325: -#line 855 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miAggressiveInlining); } break; -case 326: -#line 856 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miNoOptimization); } break; -case 327: -#line 857 "asmparse.y" -{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].int32); } break; -case 328: -#line 860 "asmparse.y" -{ PASM->delArgNameList(PASM->m_firstArgName); PASM->m_firstArgName = NULL;PASM->m_lastArgName = NULL; - } break; -case 331: -#line 868 "asmparse.y" -{ PASM->EmitByte(yypvt[-0].int32); } break; -case 332: -#line 869 "asmparse.y" -{ delete PASM->m_SEHD; PASM->m_SEHD = PASM->m_SEHDstack.POP(); } break; -case 333: -#line 870 "asmparse.y" -{ PASM->EmitMaxStack(yypvt[-0].int32); } break; -case 334: -#line 871 "asmparse.y" -{ PASM->EmitLocals(parser->MakeSig(IMAGE_CEE_CS_CALLCONV_LOCAL_SIG, 0, yypvt[-1].binstr)); - } break; -case 335: -#line 873 "asmparse.y" -{ PASM->EmitZeroInit(); - PASM->EmitLocals(parser->MakeSig(IMAGE_CEE_CS_CALLCONV_LOCAL_SIG, 0, yypvt[-1].binstr)); - } break; -case 336: -#line 876 "asmparse.y" -{ PASM->EmitEntryPoint(); } break; -case 337: -#line 877 "asmparse.y" -{ PASM->EmitZeroInit(); } break; -case 340: -#line 880 "asmparse.y" -{ PASM->AddLabel(PASM->m_CurPC,yypvt[-1].string); /*PASM->EmitLabel($1);*/ } break; -case 346: -#line 886 "asmparse.y" -{ if(PASM->m_pCurMethod->m_dwExportOrdinal == 0xFFFFFFFF) - { - PASM->m_pCurMethod->m_dwExportOrdinal = yypvt[-1].int32; - PASM->m_pCurMethod->m_szExportAlias = NULL; - if(PASM->m_pCurMethod->m_wVTEntry == 0) PASM->m_pCurMethod->m_wVTEntry = 1; - if(PASM->m_pCurMethod->m_wVTSlot == 0) PASM->m_pCurMethod->m_wVTSlot = yypvt[-1].int32 + 0x8000; - } - else - PASM->report->warn("Duplicate .export directive, ignored\n"); - } break; -case 347: -#line 896 "asmparse.y" -{ if(PASM->m_pCurMethod->m_dwExportOrdinal == 0xFFFFFFFF) - { - PASM->m_pCurMethod->m_dwExportOrdinal = yypvt[-3].int32; - PASM->m_pCurMethod->m_szExportAlias = yypvt[-0].string; - if(PASM->m_pCurMethod->m_wVTEntry == 0) PASM->m_pCurMethod->m_wVTEntry = 1; - if(PASM->m_pCurMethod->m_wVTSlot == 0) PASM->m_pCurMethod->m_wVTSlot = yypvt[-3].int32 + 0x8000; - } - else - PASM->report->warn("Duplicate .export directive, ignored\n"); - } break; -case 348: -#line 906 "asmparse.y" -{ PASM->m_pCurMethod->m_wVTEntry = (WORD)yypvt[-2].int32; - PASM->m_pCurMethod->m_wVTSlot = (WORD)yypvt[-0].int32; } break; -case 349: -#line 909 "asmparse.y" -{ PASM->AddMethodImpl(yypvt[-2].token,yypvt[-0].string,NULL,NULL,NULL,NULL); } break; -case 350: -#line 912 "asmparse.y" -{ PASM->AddMethodImpl(yypvt[-6].token,yypvt[-4].string, - (yypvt[-3].int32==0 ? parser->MakeSig(yypvt[-8].int32,yypvt[-7].binstr,yypvt[-1].binstr) : - parser->MakeSig(yypvt[-8].int32| IMAGE_CEE_CS_CALLCONV_GENERIC,yypvt[-7].binstr,yypvt[-1].binstr,yypvt[-3].int32)) - ,NULL,NULL,NULL); - PASM->ResetArgNameList(); - } break; -case 352: -#line 919 "asmparse.y" -{ if((yypvt[-1].int32 > 0) && (yypvt[-1].int32 <= (int)PASM->m_pCurMethod->m_NumTyPars)) - PASM->m_pCustomDescrList = PASM->m_pCurMethod->m_TyPars[yypvt[-1].int32-1].CAList(); - else - PASM->report->error("Type parameter index out of range\n"); - } break; -case 353: -#line 924 "asmparse.y" -{ int n = PASM->m_pCurMethod->FindTyPar(yypvt[-0].string); - if(n >= 0) - PASM->m_pCustomDescrList = PASM->m_pCurMethod->m_TyPars[n].CAList(); - else - PASM->report->error("Type parameter '%s' undefined\n",yypvt[-0].string); - } break; -case 354: -#line 931 "asmparse.y" -{ if( yypvt[-2].int32 ) { - ARG_NAME_LIST* pAN=PASM->findArg(PASM->m_pCurMethod->m_firstArgName, yypvt[-2].int32 - 1); - if(pAN) - { - PASM->m_pCustomDescrList = &(pAN->CustDList); - pAN->pValue = yypvt[-0].binstr; - } - else - { - PASM->m_pCustomDescrList = NULL; - if(yypvt[-0].binstr) delete yypvt[-0].binstr; - } - } else { - PASM->m_pCustomDescrList = &(PASM->m_pCurMethod->m_RetCustDList); - PASM->m_pCurMethod->m_pRetValue = yypvt[-0].binstr; - } - PASM->m_tkCurrentCVOwner = 0; - } break; -case 355: -#line 951 "asmparse.y" -{ PASM->m_pCurMethod->CloseScope(); } break; -case 356: -#line 954 "asmparse.y" -{ PASM->m_pCurMethod->OpenScope(); } break; -case 360: -#line 965 "asmparse.y" -{ PASM->m_SEHD->tryTo = PASM->m_CurPC; } break; -case 361: -#line 966 "asmparse.y" -{ PASM->SetTryLabels(yypvt[-2].string, yypvt[-0].string); } break; -case 362: -#line 967 "asmparse.y" -{ if(PASM->m_SEHD) {PASM->m_SEHD->tryFrom = yypvt[-2].int32; - PASM->m_SEHD->tryTo = yypvt[-0].int32;} } break; -case 363: -#line 971 "asmparse.y" -{ PASM->NewSEHDescriptor(); - PASM->m_SEHD->tryFrom = PASM->m_CurPC; } break; -case 364: -#line 976 "asmparse.y" -{ PASM->EmitTry(); } break; -case 365: -#line 977 "asmparse.y" -{ PASM->EmitTry(); } break; -case 366: -#line 978 "asmparse.y" -{ PASM->EmitTry(); } break; -case 367: -#line 979 "asmparse.y" -{ PASM->EmitTry(); } break; -case 368: -#line 983 "asmparse.y" -{ PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; -case 369: -#line 984 "asmparse.y" -{ PASM->SetFilterLabel(yypvt[-0].string); - PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; -case 370: -#line 986 "asmparse.y" -{ PASM->m_SEHD->sehFilter = yypvt[-0].int32; - PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; -case 371: -#line 990 "asmparse.y" -{ PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FILTER; - PASM->m_SEHD->sehFilter = PASM->m_CurPC; } break; -case 372: -#line 994 "asmparse.y" -{ PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_NONE; - PASM->SetCatchClass(yypvt[-0].token); - PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; -case 373: -#line 999 "asmparse.y" -{ PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FINALLY; - PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; -case 374: -#line 1003 "asmparse.y" -{ PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FAULT; - PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; -case 375: -#line 1007 "asmparse.y" -{ PASM->m_SEHD->sehHandlerTo = PASM->m_CurPC; } break; -case 376: -#line 1008 "asmparse.y" -{ PASM->SetHandlerLabels(yypvt[-2].string, yypvt[-0].string); } break; -case 377: -#line 1009 "asmparse.y" -{ PASM->m_SEHD->sehHandler = yypvt[-2].int32; - PASM->m_SEHD->sehHandlerTo = yypvt[-0].int32; } break; -case 379: -#line 1017 "asmparse.y" -{ PASM->EmitDataLabel(yypvt[-1].string); } break; -case 381: -#line 1021 "asmparse.y" -{ PASM->SetDataSection(); } break; -case 382: -#line 1022 "asmparse.y" -{ PASM->SetTLSSection(); } break; -case 383: -#line 1023 "asmparse.y" -{ PASM->SetILSection(); } break; -case 388: -#line 1034 "asmparse.y" -{ yyval.int32 = 1; } break; -case 389: -#line 1035 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32; - if(yypvt[-1].int32 <= 0) { PASM->report->error("Illegal item count: %d\n",yypvt[-1].int32); - if(!PASM->OnErrGo) yyval.int32 = 1; }} break; -case 390: -#line 1040 "asmparse.y" -{ PASM->EmitDataString(yypvt[-1].binstr); } break; -case 391: -#line 1041 "asmparse.y" -{ PASM->EmitDD(yypvt[-1].string); } break; -case 392: -#line 1042 "asmparse.y" -{ PASM->EmitData(yypvt[-1].binstr->ptr(),yypvt[-1].binstr->length()); } break; -case 393: -#line 1044 "asmparse.y" -{ float f = (float) (*yypvt[-2].float64); float* p = new (nothrow) float[yypvt[-0].int32]; - if(p != NULL) { - for(int i=0; i < yypvt[-0].int32; i++) p[i] = f; - PASM->EmitData(p, sizeof(float)*yypvt[-0].int32); delete yypvt[-2].float64; delete [] p; - } else PASM->report->error("Out of memory emitting data block %d bytes\n", - sizeof(float)*yypvt[-0].int32); } break; -case 394: -#line 1051 "asmparse.y" -{ double* p = new (nothrow) double[yypvt[-0].int32]; - if(p != NULL) { - for(int i=0; iEmitData(p, sizeof(double)*yypvt[-0].int32); delete yypvt[-2].float64; delete [] p; - } else PASM->report->error("Out of memory emitting data block %d bytes\n", - sizeof(double)*yypvt[-0].int32); } break; -case 395: -#line 1058 "asmparse.y" -{ __int64* p = new (nothrow) __int64[yypvt[-0].int32]; - if(p != NULL) { - for(int i=0; iEmitData(p, sizeof(__int64)*yypvt[-0].int32); delete yypvt[-2].int64; delete [] p; - } else PASM->report->error("Out of memory emitting data block %d bytes\n", - sizeof(__int64)*yypvt[-0].int32); } break; -case 396: -#line 1065 "asmparse.y" -{ __int32* p = new (nothrow) __int32[yypvt[-0].int32]; - if(p != NULL) { - for(int i=0; iEmitData(p, sizeof(__int32)*yypvt[-0].int32); delete [] p; - } else PASM->report->error("Out of memory emitting data block %d bytes\n", - sizeof(__int32)*yypvt[-0].int32); } break; -case 397: -#line 1072 "asmparse.y" -{ __int16 i = (__int16) yypvt[-2].int32; FAIL_UNLESS(i == yypvt[-2].int32, ("Value %d too big\n", yypvt[-2].int32)); - __int16* p = new (nothrow) __int16[yypvt[-0].int32]; - if(p != NULL) { - for(int j=0; jEmitData(p, sizeof(__int16)*yypvt[-0].int32); delete [] p; - } else PASM->report->error("Out of memory emitting data block %d bytes\n", - sizeof(__int16)*yypvt[-0].int32); } break; -case 398: -#line 1080 "asmparse.y" -{ __int8 i = (__int8) yypvt[-2].int32; FAIL_UNLESS(i == yypvt[-2].int32, ("Value %d too big\n", yypvt[-2].int32)); - __int8* p = new (nothrow) __int8[yypvt[-0].int32]; - if(p != NULL) { - for(int j=0; jEmitData(p, sizeof(__int8)*yypvt[-0].int32); delete [] p; - } else PASM->report->error("Out of memory emitting data block %d bytes\n", - sizeof(__int8)*yypvt[-0].int32); } break; -case 399: -#line 1087 "asmparse.y" -{ PASM->EmitData(NULL, sizeof(float)*yypvt[-0].int32); } break; -case 400: -#line 1088 "asmparse.y" -{ PASM->EmitData(NULL, sizeof(double)*yypvt[-0].int32); } break; -case 401: -#line 1089 "asmparse.y" -{ PASM->EmitData(NULL, sizeof(__int64)*yypvt[-0].int32); } break; -case 402: -#line 1090 "asmparse.y" -{ PASM->EmitData(NULL, sizeof(__int32)*yypvt[-0].int32); } break; -case 403: -#line 1091 "asmparse.y" -{ PASM->EmitData(NULL, sizeof(__int16)*yypvt[-0].int32); } break; -case 404: -#line 1092 "asmparse.y" -{ PASM->EmitData(NULL, sizeof(__int8)*yypvt[-0].int32); } break; -case 405: -#line 1096 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R4); - float f = (float)(*yypvt[-1].float64); - yyval.binstr->appendInt32(*((__int32*)&f)); delete yypvt[-1].float64; } break; -case 406: -#line 1099 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R8); - yyval.binstr->appendInt64((__int64 *)yypvt[-1].float64); delete yypvt[-1].float64; } break; -case 407: -#line 1101 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R4); - yyval.binstr->appendInt32(yypvt[-1].int32); } break; -case 408: -#line 1103 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R8); - yyval.binstr->appendInt64((__int64 *)yypvt[-1].int64); delete yypvt[-1].int64; } break; -case 409: -#line 1105 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I8); - yyval.binstr->appendInt64((__int64 *)yypvt[-1].int64); delete yypvt[-1].int64; } break; -case 410: -#line 1107 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I4); - yyval.binstr->appendInt32(yypvt[-1].int32); } break; -case 411: -#line 1109 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I2); - yyval.binstr->appendInt16(yypvt[-1].int32); } break; -case 412: -#line 1111 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I1); - yyval.binstr->appendInt8(yypvt[-1].int32); } break; -case 413: -#line 1113 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U8); - yyval.binstr->appendInt64((__int64 *)yypvt[-1].int64); delete yypvt[-1].int64; } break; -case 414: -#line 1115 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U4); - yyval.binstr->appendInt32(yypvt[-1].int32); } break; -case 415: -#line 1117 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U2); - yyval.binstr->appendInt16(yypvt[-1].int32); } break; -case 416: -#line 1119 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U1); - yyval.binstr->appendInt8(yypvt[-1].int32); } break; -case 417: -#line 1121 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U8); - yyval.binstr->appendInt64((__int64 *)yypvt[-1].int64); delete yypvt[-1].int64; } break; -case 418: -#line 1123 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U4); - yyval.binstr->appendInt32(yypvt[-1].int32); } break; -case 419: -#line 1125 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U2); - yyval.binstr->appendInt16(yypvt[-1].int32); } break; -case 420: -#line 1127 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U1); - yyval.binstr->appendInt8(yypvt[-1].int32); } break; -case 421: -#line 1129 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_CHAR); - yyval.binstr->appendInt16(yypvt[-1].int32); } break; -case 422: -#line 1131 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_BOOLEAN); - yyval.binstr->appendInt8(yypvt[-1].int32);} break; -case 423: -#line 1133 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_STRING); - yyval.binstr->append(yypvt[-1].binstr); delete yypvt[-1].binstr;} break; -case 424: -#line 1137 "asmparse.y" -{ bParsingByteArray = TRUE; } break; -case 425: -#line 1140 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 426: -#line 1141 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 427: -#line 1144 "asmparse.y" -{ __int8 i = (__int8) yypvt[-0].int32; yyval.binstr = new BinStr(); yyval.binstr->appendInt8(i); } break; -case 428: -#line 1145 "asmparse.y" -{ __int8 i = (__int8) yypvt[-0].int32; yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt8(i); } break; -case 429: -#line 1149 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 430: -#line 1150 "asmparse.y" -{ yyval.binstr = BinStrToUnicode(yypvt[-0].binstr,true); yyval.binstr->insertInt8(ELEMENT_TYPE_STRING);} break; -case 431: -#line 1151 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_CLASS); - yyval.binstr->appendInt32(0); } break; -case 432: -#line 1156 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 433: -#line 1157 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_STRING); yyval.binstr->appendInt8(0xFF); } break; -case 434: -#line 1158 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_STRING); - AppendStringWithLength(yyval.binstr,yypvt[-1].string); delete [] yypvt[-1].string;} break; -case 435: -#line 1160 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_TYPE); - AppendStringWithLength(yyval.binstr,yypvt[-1].string); delete [] yypvt[-1].string;} break; -case 436: -#line 1162 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_TYPE); - AppendStringWithLength(yyval.binstr,PASM->ReflectionNotation(yypvt[-1].token));} break; -case 437: -#line 1164 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_TYPE); yyval.binstr->appendInt8(0xFF); } break; -case 438: -#line 1165 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt8(SERIALIZATION_TYPE_TAGGED_OBJECT);} break; -case 439: -#line 1167 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_R4); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 440: -#line 1171 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_R8); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 441: -#line 1175 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_I8); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 442: -#line 1179 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_I4); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 443: -#line 1183 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_I2); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 444: -#line 1187 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_I1); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 445: -#line 1191 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_U8); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 446: -#line 1195 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_U4); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 447: -#line 1199 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_U2); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 448: -#line 1203 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_U1); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 449: -#line 1207 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_U8); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 450: -#line 1211 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_U4); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 451: -#line 1215 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_U2); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 452: -#line 1219 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_U1); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 453: -#line 1223 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_CHAR); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 454: -#line 1227 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_BOOLEAN); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 455: -#line 1231 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(ELEMENT_TYPE_STRING); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 456: -#line 1235 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(SERIALIZATION_TYPE_TYPE); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 457: -#line 1239 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); - yyval.binstr->insertInt8(SERIALIZATION_TYPE_TAGGED_OBJECT); - yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 458: -#line 1245 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 459: -#line 1246 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; - float f = (float) (*yypvt[-0].float64); yyval.binstr->appendInt32(*((__int32*)&f)); delete yypvt[-0].float64; } break; -case 460: -#line 1248 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; - yyval.binstr->appendInt32(yypvt[-0].int32); } break; -case 461: -#line 1252 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 462: -#line 1253 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; - yyval.binstr->appendInt64((__int64 *)yypvt[-0].float64); delete yypvt[-0].float64; } break; -case 463: -#line 1255 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; - yyval.binstr->appendInt64((__int64 *)yypvt[-0].int64); delete yypvt[-0].int64; } break; -case 464: -#line 1259 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 465: -#line 1260 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; - yyval.binstr->appendInt64((__int64 *)yypvt[-0].int64); delete yypvt[-0].int64; } break; -case 466: -#line 1264 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 467: -#line 1265 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt32(yypvt[-0].int32);} break; -case 468: -#line 1268 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 469: -#line 1269 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt16(yypvt[-0].int32);} break; -case 470: -#line 1272 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 471: -#line 1273 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt8(yypvt[-0].int32); } break; -case 472: -#line 1276 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 473: -#line 1277 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; - yyval.binstr->appendInt8(yypvt[-0].int32);} break; -case 474: -#line 1281 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 475: -#line 1282 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt8(0xFF); } break; -case 476: -#line 1283 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; - AppendStringWithLength(yyval.binstr,yypvt[-0].string); delete [] yypvt[-0].string;} break; -case 477: -#line 1287 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 478: -#line 1288 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt8(0xFF); } break; -case 479: -#line 1289 "asmparse.y" -{ yyval.binstr = yypvt[-2].binstr; - AppendStringWithLength(yyval.binstr,yypvt[-0].string); delete [] yypvt[-0].string;} break; -case 480: -#line 1291 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; - AppendStringWithLength(yyval.binstr,PASM->ReflectionNotation(yypvt[-0].token));} break; -case 481: -#line 1295 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 482: -#line 1296 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; } break; -case 483: -#line 1300 "asmparse.y" -{ parser->m_ANSFirst.PUSH(PASM->m_firstArgName); - parser->m_ANSLast.PUSH(PASM->m_lastArgName); - PASM->m_firstArgName = NULL; - PASM->m_lastArgName = NULL; } break; -case 484: -#line 1306 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 485: -#line 1309 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 486: -#line 1312 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 487: -#line 1315 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 488: -#line 1318 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 489: -#line 1321 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 490: -#line 1324 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); - if((!PASM->OnErrGo)&& - ((yypvt[-0].opcode == CEE_NEWOBJ)|| - (yypvt[-0].opcode == CEE_CALLVIRT))) - iCallConv = IMAGE_CEE_CS_CALLCONV_HASTHIS; - } break; -case 491: -#line 1332 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 492: -#line 1335 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 493: -#line 1338 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 494: -#line 1341 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 495: -#line 1344 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); iOpcodeLen = PASM->OpcodeLen(yyval.instr); } break; -case 496: -#line 1347 "asmparse.y" -{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; -case 497: -#line 1350 "asmparse.y" -{ yyval.instr = yypvt[-1].instr; bParsingByteArray = TRUE; } break; -case 498: -#line 1354 "asmparse.y" -{ PASM->EmitOpcode(yypvt[-0].instr); } break; -case 499: -#line 1355 "asmparse.y" -{ PASM->EmitInstrVar(yypvt[-1].instr, yypvt[-0].int32); } break; -case 500: -#line 1356 "asmparse.y" -{ PASM->EmitInstrVarByName(yypvt[-1].instr, yypvt[-0].string); } break; -case 501: -#line 1357 "asmparse.y" -{ PASM->EmitInstrI(yypvt[-1].instr, yypvt[-0].int32); } break; -case 502: -#line 1358 "asmparse.y" -{ PASM->EmitInstrI8(yypvt[-1].instr, yypvt[-0].int64); } break; -case 503: -#line 1359 "asmparse.y" -{ PASM->EmitInstrR(yypvt[-1].instr, yypvt[-0].float64); delete (yypvt[-0].float64);} break; -case 504: -#line 1360 "asmparse.y" -{ double f = (double) (*yypvt[-0].int64); PASM->EmitInstrR(yypvt[-1].instr, &f); } break; -case 505: -#line 1361 "asmparse.y" -{ unsigned L = yypvt[-1].binstr->length(); - FAIL_UNLESS(L >= sizeof(float), ("%d hexbytes, must be at least %d\n", - L,sizeof(float))); - if(L < sizeof(float)) {YYERROR; } - else { - double f = (L >= sizeof(double)) ? *((double *)(yypvt[-1].binstr->ptr())) - : (double)(*(float *)(yypvt[-1].binstr->ptr())); - PASM->EmitInstrR(yypvt[-2].instr,&f); } - delete yypvt[-1].binstr; } break; -case 506: -#line 1370 "asmparse.y" -{ PASM->EmitInstrBrOffset(yypvt[-1].instr, yypvt[-0].int32); } break; -case 507: -#line 1371 "asmparse.y" -{ PASM->EmitInstrBrTarget(yypvt[-1].instr, yypvt[-0].string); } break; -case 508: -#line 1373 "asmparse.y" -{ PASM->SetMemberRefFixup(yypvt[-0].token,PASM->OpcodeLen(yypvt[-1].instr)); - PASM->EmitInstrI(yypvt[-1].instr,yypvt[-0].token); - PASM->m_tkCurrentCVOwner = yypvt[-0].token; - PASM->m_pCustomDescrList = NULL; - iCallConv = 0; - } break; -case 509: -#line 1380 "asmparse.y" -{ yypvt[-3].binstr->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); - mdToken mr = PASM->MakeMemberRef(yypvt[-2].token, yypvt[-0].string, yypvt[-3].binstr); - PASM->SetMemberRefFixup(mr, PASM->OpcodeLen(yypvt[-4].instr)); - PASM->EmitInstrI(yypvt[-4].instr,mr); - PASM->m_tkCurrentCVOwner = mr; - PASM->m_pCustomDescrList = NULL; - } break; -case 510: -#line 1388 "asmparse.y" -{ yypvt[-1].binstr->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); - mdToken mr = PASM->MakeMemberRef(mdTokenNil, yypvt[-0].string, yypvt[-1].binstr); - PASM->SetMemberRefFixup(mr, PASM->OpcodeLen(yypvt[-2].instr)); - PASM->EmitInstrI(yypvt[-2].instr,mr); - PASM->m_tkCurrentCVOwner = mr; - PASM->m_pCustomDescrList = NULL; - } break; -case 511: -#line 1395 "asmparse.y" -{ mdToken mr = yypvt[-0].token; - PASM->SetMemberRefFixup(mr, PASM->OpcodeLen(yypvt[-1].instr)); - PASM->EmitInstrI(yypvt[-1].instr,mr); - PASM->m_tkCurrentCVOwner = mr; - PASM->m_pCustomDescrList = NULL; - } break; -case 512: -#line 1401 "asmparse.y" -{ mdToken mr = yypvt[-0].tdd->m_tkTypeSpec; - PASM->SetMemberRefFixup(mr, PASM->OpcodeLen(yypvt[-1].instr)); - PASM->EmitInstrI(yypvt[-1].instr,mr); - PASM->m_tkCurrentCVOwner = mr; - PASM->m_pCustomDescrList = NULL; - } break; -case 513: -#line 1407 "asmparse.y" -{ mdToken mr = yypvt[-0].tdd->m_tkTypeSpec; - PASM->SetMemberRefFixup(mr, PASM->OpcodeLen(yypvt[-1].instr)); - PASM->EmitInstrI(yypvt[-1].instr,mr); - PASM->m_tkCurrentCVOwner = mr; - PASM->m_pCustomDescrList = NULL; - } break; -case 514: -#line 1413 "asmparse.y" -{ PASM->EmitInstrI(yypvt[-1].instr, yypvt[-0].token); - PASM->m_tkCurrentCVOwner = yypvt[-0].token; - PASM->m_pCustomDescrList = NULL; - } break; -case 515: -#line 1417 "asmparse.y" -{ PASM->EmitInstrStringLiteral(yypvt[-1].instr, yypvt[-0].binstr,TRUE); } break; -case 516: -#line 1419 "asmparse.y" -{ PASM->EmitInstrStringLiteral(yypvt[-4].instr, yypvt[-1].binstr,FALSE); } break; -case 517: -#line 1421 "asmparse.y" -{ PASM->EmitInstrStringLiteral(yypvt[-3].instr, yypvt[-1].binstr,FALSE,TRUE); } break; -case 518: -#line 1423 "asmparse.y" -{ PASM->EmitInstrSig(yypvt[-5].instr, parser->MakeSig(yypvt[-4].int32, yypvt[-3].binstr, yypvt[-1].binstr)); - PASM->ResetArgNameList(); - } break; -case 519: -#line 1427 "asmparse.y" -{ PASM->EmitInstrI(yypvt[-1].instr,yypvt[-0].token); - PASM->m_tkCurrentCVOwner = yypvt[-0].token; - PASM->m_pCustomDescrList = NULL; - iOpcodeLen = 0; - } break; -case 520: -#line 1432 "asmparse.y" -{ PASM->EmitInstrSwitch(yypvt[-3].instr, yypvt[-1].labels); } break; -case 521: -#line 1435 "asmparse.y" -{ yyval.labels = 0; } break; -case 522: -#line 1436 "asmparse.y" -{ yyval.labels = new Labels(yypvt[-2].string, yypvt[-0].labels, TRUE); } break; -case 523: -#line 1437 "asmparse.y" -{ yyval.labels = new Labels((char *)(UINT_PTR)yypvt[-2].int32, yypvt[-0].labels, FALSE); } break; -case 524: -#line 1438 "asmparse.y" -{ yyval.labels = new Labels(yypvt[-0].string, NULL, TRUE); } break; -case 525: -#line 1439 "asmparse.y" -{ yyval.labels = new Labels((char *)(UINT_PTR)yypvt[-0].int32, NULL, FALSE); } break; -case 526: -#line 1443 "asmparse.y" -{ yyval.binstr = NULL; } break; -case 527: -#line 1444 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; } break; -case 528: -#line 1447 "asmparse.y" -{ yyval.binstr = NULL; } break; -case 529: -#line 1448 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 530: -#line 1451 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 531: -#line 1452 "asmparse.y" -{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; } break; -case 532: -#line 1456 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 533: -#line 1457 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr;} break; -case 534: -#line 1460 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 535: -#line 1461 "asmparse.y" -{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; } break; -case 536: -#line 1464 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_SENTINEL); } break; -case 537: -#line 1465 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->append(yypvt[-1].binstr); PASM->addArgName(NULL, yypvt[-1].binstr, yypvt[-0].binstr, yypvt[-2].int32); } break; -case 538: -#line 1466 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->append(yypvt[-2].binstr); PASM->addArgName(yypvt[-0].string, yypvt[-2].binstr, yypvt[-1].binstr, yypvt[-3].int32);} break; -case 539: -#line 1470 "asmparse.y" -{ yyval.token = PASM->ResolveClassRef(PASM->GetAsmRef(yypvt[-2].string), yypvt[-0].string, NULL); delete[] yypvt[-2].string;} break; -case 540: -#line 1471 "asmparse.y" -{ yyval.token = PASM->ResolveClassRef(yypvt[-2].token, yypvt[-0].string, NULL); } break; -case 541: -#line 1472 "asmparse.y" -{ yyval.token = PASM->ResolveClassRef(mdTokenNil, yypvt[-0].string, NULL); } break; -case 542: -#line 1473 "asmparse.y" -{ yyval.token = PASM->ResolveClassRef(PASM->GetModRef(yypvt[-2].string),yypvt[-0].string, NULL); delete[] yypvt[-2].string;} break; -case 543: -#line 1474 "asmparse.y" -{ yyval.token = PASM->ResolveClassRef(1,yypvt[-0].string,NULL); } break; -case 544: -#line 1475 "asmparse.y" -{ yyval.token = yypvt[-0].token; } break; -case 545: -#line 1476 "asmparse.y" -{ yyval.token = yypvt[-0].tdd->m_tkTypeSpec; } break; -case 546: -#line 1477 "asmparse.y" -{ if(PASM->m_pCurClass != NULL) yyval.token = PASM->m_pCurClass->m_cl; - else { yyval.token = 0; PASM->report->error(".this outside class scope\n"); } - } break; -case 547: -#line 1480 "asmparse.y" -{ if(PASM->m_pCurClass != NULL) { - yyval.token = PASM->m_pCurClass->m_crExtends; - if(RidFromToken(yyval.token) == 0) - PASM->report->error(".base undefined\n"); - } else { yyval.token = 0; PASM->report->error(".base outside class scope\n"); } - } break; -case 548: -#line 1486 "asmparse.y" -{ if(PASM->m_pCurClass != NULL) { - if(PASM->m_pCurClass->m_pEncloser != NULL) yyval.token = PASM->m_pCurClass->m_pEncloser->m_cl; - else { yyval.token = 0; PASM->report->error(".nester undefined\n"); } - } else { yyval.token = 0; PASM->report->error(".nester outside class scope\n"); } - } break; -case 549: -#line 1493 "asmparse.y" -{ yyval.string = yypvt[-0].string; } break; -case 550: -#line 1494 "asmparse.y" -{ yyval.string = newStringWDel(yypvt[-2].string, NESTING_SEP, yypvt[-0].string); } break; -case 551: -#line 1497 "asmparse.y" -{ yyval.token = yypvt[-0].token;} break; -case 552: -#line 1498 "asmparse.y" -{ yyval.token = PASM->GetAsmRef(yypvt[-1].string); delete[] yypvt[-1].string;} break; -case 553: -#line 1499 "asmparse.y" -{ yyval.token = PASM->GetModRef(yypvt[-1].string); delete[] yypvt[-1].string;} break; -case 554: -#line 1500 "asmparse.y" -{ yyval.token = PASM->ResolveTypeSpec(yypvt[-0].binstr); } break; -case 555: -#line 1504 "asmparse.y" -{ yyval.binstr = new BinStr(); } break; -case 556: -#line 1506 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_CUSTOMMARSHALER); - corEmitInt(yyval.binstr,yypvt[-7].binstr->length()); yyval.binstr->append(yypvt[-7].binstr); - corEmitInt(yyval.binstr,yypvt[-5].binstr->length()); yyval.binstr->append(yypvt[-5].binstr); - corEmitInt(yyval.binstr,yypvt[-3].binstr->length()); yyval.binstr->append(yypvt[-3].binstr); - corEmitInt(yyval.binstr,yypvt[-1].binstr->length()); yyval.binstr->append(yypvt[-1].binstr); - PASM->report->warn("Deprecated 4-string form of custom marshaler, first two strings ignored\n");} break; -case 557: -#line 1513 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_CUSTOMMARSHALER); - corEmitInt(yyval.binstr,0); - corEmitInt(yyval.binstr,0); - corEmitInt(yyval.binstr,yypvt[-3].binstr->length()); yyval.binstr->append(yypvt[-3].binstr); - corEmitInt(yyval.binstr,yypvt[-1].binstr->length()); yyval.binstr->append(yypvt[-1].binstr); } break; -case 558: -#line 1518 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_FIXEDSYSSTRING); - corEmitInt(yyval.binstr,yypvt[-1].int32); } break; -case 559: -#line 1521 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_FIXEDARRAY); - corEmitInt(yyval.binstr,yypvt[-2].int32); yyval.binstr->append(yypvt[-0].binstr); } break; -case 560: -#line 1523 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_VARIANT); - PASM->report->warn("Deprecated native type 'variant'\n"); } break; -case 561: -#line 1525 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_CURRENCY); } break; -case 562: -#line 1526 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_SYSCHAR); - PASM->report->warn("Deprecated native type 'syschar'\n"); } break; -case 563: -#line 1528 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_VOID); - PASM->report->warn("Deprecated native type 'void'\n"); } break; -case 564: -#line 1530 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_BOOLEAN); } break; -case 565: -#line 1531 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_I1); } break; -case 566: -#line 1532 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_I2); } break; -case 567: -#line 1533 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_I4); } break; -case 568: -#line 1534 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_I8); } break; -case 569: -#line 1535 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_R4); } break; -case 570: -#line 1536 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_R8); } break; -case 571: -#line 1537 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_ERROR); } break; -case 572: -#line 1538 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U1); } break; -case 573: -#line 1539 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U2); } break; -case 574: -#line 1540 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U4); } break; -case 575: -#line 1541 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U8); } break; -case 576: -#line 1542 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U1); } break; -case 577: -#line 1543 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U2); } break; -case 578: -#line 1544 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U4); } break; -case 579: -#line 1545 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U8); } break; -case 580: -#line 1546 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt8(NATIVE_TYPE_PTR); - PASM->report->warn("Deprecated native type '*'\n"); } break; -case 581: -#line 1548 "asmparse.y" -{ yyval.binstr = yypvt[-2].binstr; if(yyval.binstr->length()==0) yyval.binstr->appendInt8(NATIVE_TYPE_MAX); - yyval.binstr->insertInt8(NATIVE_TYPE_ARRAY); } break; -case 582: -#line 1550 "asmparse.y" -{ yyval.binstr = yypvt[-3].binstr; if(yyval.binstr->length()==0) yyval.binstr->appendInt8(NATIVE_TYPE_MAX); - yyval.binstr->insertInt8(NATIVE_TYPE_ARRAY); - corEmitInt(yyval.binstr,0); - corEmitInt(yyval.binstr,yypvt[-1].int32); - corEmitInt(yyval.binstr,0); } break; -case 583: -#line 1555 "asmparse.y" -{ yyval.binstr = yypvt[-5].binstr; if(yyval.binstr->length()==0) yyval.binstr->appendInt8(NATIVE_TYPE_MAX); - yyval.binstr->insertInt8(NATIVE_TYPE_ARRAY); - corEmitInt(yyval.binstr,yypvt[-1].int32); - corEmitInt(yyval.binstr,yypvt[-3].int32); - corEmitInt(yyval.binstr,ntaSizeParamIndexSpecified); } break; -case 584: -#line 1560 "asmparse.y" -{ yyval.binstr = yypvt[-4].binstr; if(yyval.binstr->length()==0) yyval.binstr->appendInt8(NATIVE_TYPE_MAX); - yyval.binstr->insertInt8(NATIVE_TYPE_ARRAY); - corEmitInt(yyval.binstr,yypvt[-1].int32); } break; -case 585: -#line 1563 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_DECIMAL); - PASM->report->warn("Deprecated native type 'decimal'\n"); } break; -case 586: -#line 1565 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_DATE); - PASM->report->warn("Deprecated native type 'date'\n"); } break; -case 587: -#line 1567 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_BSTR); } break; -case 588: -#line 1568 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_LPSTR); } break; -case 589: -#line 1569 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_LPWSTR); } break; -case 590: -#line 1570 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_LPTSTR); } break; -case 591: -#line 1571 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_OBJECTREF); - PASM->report->warn("Deprecated native type 'objectref'\n"); } break; -case 592: -#line 1573 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_IUNKNOWN); - if(yypvt[-0].int32 != -1) corEmitInt(yyval.binstr,yypvt[-0].int32); } break; -case 593: -#line 1575 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_IDISPATCH); - if(yypvt[-0].int32 != -1) corEmitInt(yyval.binstr,yypvt[-0].int32); } break; -case 594: -#line 1577 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_STRUCT); } break; -case 595: -#line 1578 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_INTF); - if(yypvt[-0].int32 != -1) corEmitInt(yyval.binstr,yypvt[-0].int32); } break; -case 596: -#line 1580 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_SAFEARRAY); - corEmitInt(yyval.binstr,yypvt[-0].int32); - corEmitInt(yyval.binstr,0);} break; -case 597: -#line 1583 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_SAFEARRAY); - corEmitInt(yyval.binstr,yypvt[-2].int32); - corEmitInt(yyval.binstr,yypvt[-0].binstr->length()); yyval.binstr->append(yypvt[-0].binstr); } break; -case 598: -#line 1587 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_INT); } break; -case 599: -#line 1588 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_UINT); } break; -case 600: -#line 1589 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_UINT); } break; -case 601: -#line 1590 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_NESTEDSTRUCT); - PASM->report->warn("Deprecated native type 'nested struct'\n"); } break; -case 602: -#line 1592 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_BYVALSTR); } break; -case 603: -#line 1593 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_ANSIBSTR); } break; -case 604: -#line 1594 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_TBSTR); } break; -case 605: -#line 1595 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_VARIANTBOOL); } break; -case 606: -#line 1596 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_FUNC); } break; -case 607: -#line 1597 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_ASANY); } break; -case 608: -#line 1598 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_LPSTRUCT); } break; -case 609: -#line 1599 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->append(yypvt[-0].tdd->m_pbsTypeSpec); } break; -case 610: -#line 1602 "asmparse.y" -{ yyval.int32 = -1; } break; -case 611: -#line 1603 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32; } break; -case 612: -#line 1606 "asmparse.y" -{ yyval.int32 = VT_EMPTY; } break; -case 613: -#line 1607 "asmparse.y" -{ yyval.int32 = VT_NULL; } break; -case 614: -#line 1608 "asmparse.y" -{ yyval.int32 = VT_VARIANT; } break; -case 615: -#line 1609 "asmparse.y" -{ yyval.int32 = VT_CY; } break; -case 616: -#line 1610 "asmparse.y" -{ yyval.int32 = VT_VOID; } break; -case 617: -#line 1611 "asmparse.y" -{ yyval.int32 = VT_BOOL; } break; -case 618: -#line 1612 "asmparse.y" -{ yyval.int32 = VT_I1; } break; -case 619: -#line 1613 "asmparse.y" -{ yyval.int32 = VT_I2; } break; -case 620: -#line 1614 "asmparse.y" -{ yyval.int32 = VT_I4; } break; -case 621: -#line 1615 "asmparse.y" -{ yyval.int32 = VT_I8; } break; -case 622: -#line 1616 "asmparse.y" -{ yyval.int32 = VT_R4; } break; -case 623: -#line 1617 "asmparse.y" -{ yyval.int32 = VT_R8; } break; -case 624: -#line 1618 "asmparse.y" -{ yyval.int32 = VT_UI1; } break; -case 625: -#line 1619 "asmparse.y" -{ yyval.int32 = VT_UI2; } break; -case 626: -#line 1620 "asmparse.y" -{ yyval.int32 = VT_UI4; } break; -case 627: -#line 1621 "asmparse.y" -{ yyval.int32 = VT_UI8; } break; -case 628: -#line 1622 "asmparse.y" -{ yyval.int32 = VT_UI1; } break; -case 629: -#line 1623 "asmparse.y" -{ yyval.int32 = VT_UI2; } break; -case 630: -#line 1624 "asmparse.y" -{ yyval.int32 = VT_UI4; } break; -case 631: -#line 1625 "asmparse.y" -{ yyval.int32 = VT_UI8; } break; -case 632: -#line 1626 "asmparse.y" -{ yyval.int32 = VT_PTR; } break; -case 633: -#line 1627 "asmparse.y" -{ yyval.int32 = yypvt[-2].int32 | VT_ARRAY; } break; -case 634: -#line 1628 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32 | VT_VECTOR; } break; -case 635: -#line 1629 "asmparse.y" -{ yyval.int32 = yypvt[-1].int32 | VT_BYREF; } break; -case 636: -#line 1630 "asmparse.y" -{ yyval.int32 = VT_DECIMAL; } break; -case 637: -#line 1631 "asmparse.y" -{ yyval.int32 = VT_DATE; } break; -case 638: -#line 1632 "asmparse.y" -{ yyval.int32 = VT_BSTR; } break; -case 639: -#line 1633 "asmparse.y" -{ yyval.int32 = VT_LPSTR; } break; -case 640: -#line 1634 "asmparse.y" -{ yyval.int32 = VT_LPWSTR; } break; -case 641: -#line 1635 "asmparse.y" -{ yyval.int32 = VT_UNKNOWN; } break; -case 642: -#line 1636 "asmparse.y" -{ yyval.int32 = VT_DISPATCH; } break; -case 643: -#line 1637 "asmparse.y" -{ yyval.int32 = VT_SAFEARRAY; } break; -case 644: -#line 1638 "asmparse.y" -{ yyval.int32 = VT_INT; } break; -case 645: -#line 1639 "asmparse.y" -{ yyval.int32 = VT_UINT; } break; -case 646: -#line 1640 "asmparse.y" -{ yyval.int32 = VT_UINT; } break; -case 647: -#line 1641 "asmparse.y" -{ yyval.int32 = VT_ERROR; } break; -case 648: -#line 1642 "asmparse.y" -{ yyval.int32 = VT_HRESULT; } break; -case 649: -#line 1643 "asmparse.y" -{ yyval.int32 = VT_CARRAY; } break; -case 650: -#line 1644 "asmparse.y" -{ yyval.int32 = VT_USERDEFINED; } break; -case 651: -#line 1645 "asmparse.y" -{ yyval.int32 = VT_RECORD; } break; -case 652: -#line 1646 "asmparse.y" -{ yyval.int32 = VT_FILETIME; } break; -case 653: -#line 1647 "asmparse.y" -{ yyval.int32 = VT_BLOB; } break; -case 654: -#line 1648 "asmparse.y" -{ yyval.int32 = VT_STREAM; } break; -case 655: -#line 1649 "asmparse.y" -{ yyval.int32 = VT_STORAGE; } break; -case 656: -#line 1650 "asmparse.y" -{ yyval.int32 = VT_STREAMED_OBJECT; } break; -case 657: -#line 1651 "asmparse.y" -{ yyval.int32 = VT_STORED_OBJECT; } break; -case 658: -#line 1652 "asmparse.y" -{ yyval.int32 = VT_BLOB_OBJECT; } break; -case 659: -#line 1653 "asmparse.y" -{ yyval.int32 = VT_CF; } break; -case 660: -#line 1654 "asmparse.y" -{ yyval.int32 = VT_CLSID; } break; -case 661: -#line 1658 "asmparse.y" -{ if(yypvt[-0].token == PASM->m_tkSysString) - { yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_STRING); } - else if(yypvt[-0].token == PASM->m_tkSysObject) - { yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_OBJECT); } - else - yyval.binstr = parser->MakeTypeClass(ELEMENT_TYPE_CLASS, yypvt[-0].token); } break; -case 662: -#line 1664 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_OBJECT); } break; -case 663: -#line 1665 "asmparse.y" -{ yyval.binstr = parser->MakeTypeClass(ELEMENT_TYPE_VALUETYPE, yypvt[-0].token); } break; -case 664: -#line 1666 "asmparse.y" -{ yyval.binstr = parser->MakeTypeClass(ELEMENT_TYPE_VALUETYPE, yypvt[-0].token); } break; -case 665: -#line 1667 "asmparse.y" -{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; -case 666: -#line 1668 "asmparse.y" -{ yyval.binstr = parser->MakeTypeArray(ELEMENT_TYPE_ARRAY, yypvt[-3].binstr, yypvt[-1].binstr); } break; -case 667: -#line 1669 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_BYREF); } break; -case 668: -#line 1670 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_PTR); } break; -case 669: -#line 1671 "asmparse.y" -{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_PINNED); } break; -case 670: -#line 1672 "asmparse.y" -{ yyval.binstr = parser->MakeTypeClass(ELEMENT_TYPE_CMOD_REQD, yypvt[-1].token); - yyval.binstr->append(yypvt[-4].binstr); } break; -case 671: -#line 1674 "asmparse.y" -{ yyval.binstr = parser->MakeTypeClass(ELEMENT_TYPE_CMOD_OPT, yypvt[-1].token); - yyval.binstr->append(yypvt[-4].binstr); } break; -case 672: -#line 1677 "asmparse.y" -{ yyval.binstr = parser->MakeSig(yypvt[-5].int32, yypvt[-4].binstr, yypvt[-1].binstr); - yyval.binstr->insertInt8(ELEMENT_TYPE_FNPTR); - PASM->delArgNameList(PASM->m_firstArgName); - PASM->m_firstArgName = parser->m_ANSFirst.POP(); - PASM->m_lastArgName = parser->m_ANSLast.POP(); - } break; -case 673: -#line 1683 "asmparse.y" -{ if(yypvt[-1].binstr == NULL) yyval.binstr = yypvt[-3].binstr; - else { - yyval.binstr = new BinStr(); - yyval.binstr->appendInt8(ELEMENT_TYPE_GENERICINST); - yyval.binstr->append(yypvt[-3].binstr); - corEmitInt(yyval.binstr, corCountArgs(yypvt[-1].binstr)); - yyval.binstr->append(yypvt[-1].binstr); delete yypvt[-3].binstr; delete yypvt[-1].binstr; }} break; -case 674: -#line 1690 "asmparse.y" -{ //if(PASM->m_pCurMethod) { - // if(($3 < 0)||((DWORD)$3 >= PASM->m_pCurMethod->m_NumTyPars)) - // PASM->report->error("Invalid method type parameter '%d'\n",$3); - yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_MVAR); corEmitInt(yyval.binstr, yypvt[-0].int32); - //} else PASM->report->error("Method type parameter '%d' outside method scope\n",$3); - } break; -case 675: -#line 1696 "asmparse.y" -{ //if(PASM->m_pCurClass) { - // if(($2 < 0)||((DWORD)$2 >= PASM->m_pCurClass->m_NumTyPars)) - // PASM->report->error("Invalid type parameter '%d'\n",$2); - yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_VAR); corEmitInt(yyval.binstr, yypvt[-0].int32); - //} else PASM->report->error("Type parameter '%d' outside class scope\n",$2); - } break; -case 676: -#line 1702 "asmparse.y" -{ int eltype = ELEMENT_TYPE_MVAR; - int n=-1; - if(PASM->m_pCurMethod) n = PASM->m_pCurMethod->FindTyPar(yypvt[-0].string); - else { - if(PASM->m_TyParList) n = PASM->m_TyParList->IndexOf(yypvt[-0].string); - if(n == -1) - { n = TyParFixupList.COUNT(); - TyParFixupList.PUSH(yypvt[-0].string); - eltype = ELEMENT_TYPE_MVARFIXUP; - } - } - if(n == -1) { PASM->report->error("Invalid method type parameter '%s'\n",yypvt[-0].string); - n = 0x1FFFFFFF; } - yyval.binstr = new BinStr(); yyval.binstr->appendInt8(eltype); corEmitInt(yyval.binstr,n); - } break; -case 677: -#line 1717 "asmparse.y" -{ int eltype = ELEMENT_TYPE_VAR; - int n=-1; - if(PASM->m_pCurClass && !newclass) n = PASM->m_pCurClass->FindTyPar(yypvt[-0].string); - else { - if(PASM->m_TyParList) n = PASM->m_TyParList->IndexOf(yypvt[-0].string); - if(n == -1) - { n = TyParFixupList.COUNT(); - TyParFixupList.PUSH(yypvt[-0].string); - eltype = ELEMENT_TYPE_VARFIXUP; - } - } - if(n == -1) { PASM->report->error("Invalid type parameter '%s'\n",yypvt[-0].string); - n = 0x1FFFFFFF; } - yyval.binstr = new BinStr(); yyval.binstr->appendInt8(eltype); corEmitInt(yyval.binstr,n); - } break; -case 678: -#line 1732 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_TYPEDBYREF); } break; -case 679: -#line 1733 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_VOID); } break; -case 680: -#line 1734 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I); } break; -case 681: -#line 1735 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U); } break; -case 682: -#line 1736 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U); } break; -case 683: -#line 1737 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 684: -#line 1738 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_SENTINEL); } break; -case 685: -#line 1741 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_CHAR); } break; -case 686: -#line 1742 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_STRING); } break; -case 687: -#line 1743 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_BOOLEAN); } break; -case 688: -#line 1744 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I1); } break; -case 689: -#line 1745 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I2); } break; -case 690: -#line 1746 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I4); } break; -case 691: -#line 1747 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I8); } break; -case 692: -#line 1748 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R4); } break; -case 693: -#line 1749 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R8); } break; -case 694: -#line 1750 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U1); } break; -case 695: -#line 1751 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U2); } break; -case 696: -#line 1752 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U4); } break; -case 697: -#line 1753 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U8); } break; -case 698: -#line 1754 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U1); } break; -case 699: -#line 1755 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U2); } break; -case 700: -#line 1756 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U4); } break; -case 701: -#line 1757 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U8); } break; -case 702: -#line 1758 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->append(yypvt[-0].tdd->m_pbsTypeSpec); } break; -case 703: -#line 1761 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; } break; -case 704: -#line 1762 "asmparse.y" -{ yyval.binstr = yypvt[-2].binstr; yypvt[-2].binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; } break; -case 705: -#line 1765 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt32(0x7FFFFFFF); yyval.binstr->appendInt32(0x7FFFFFFF); } break; -case 706: -#line 1766 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt32(0x7FFFFFFF); yyval.binstr->appendInt32(0x7FFFFFFF); } break; -case 707: -#line 1767 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt32(0); yyval.binstr->appendInt32(yypvt[-0].int32); } break; -case 708: -#line 1768 "asmparse.y" -{ FAIL_UNLESS(yypvt[-2].int32 <= yypvt[-0].int32, ("lower bound %d must be <= upper bound %d\n", yypvt[-2].int32, yypvt[-0].int32)); - if (yypvt[-2].int32 > yypvt[-0].int32) { YYERROR; }; - yyval.binstr = new BinStr(); yyval.binstr->appendInt32(yypvt[-2].int32); yyval.binstr->appendInt32(yypvt[-0].int32-yypvt[-2].int32+1); } break; -case 709: -#line 1771 "asmparse.y" -{ yyval.binstr = new BinStr(); yyval.binstr->appendInt32(yypvt[-1].int32); yyval.binstr->appendInt32(0x7FFFFFFF); } break; -case 710: -#line 1776 "asmparse.y" -{ PASM->AddPermissionDecl(yypvt[-4].secAct, yypvt[-3].token, yypvt[-1].pair); } break; -case 711: -#line 1778 "asmparse.y" -{ PASM->AddPermissionDecl(yypvt[-5].secAct, yypvt[-4].token, yypvt[-1].binstr); } break; -case 712: -#line 1779 "asmparse.y" -{ PASM->AddPermissionDecl(yypvt[-1].secAct, yypvt[-0].token, (NVPair *)NULL); } break; -case 713: -#line 1780 "asmparse.y" -{ PASM->AddPermissionSetDecl(yypvt[-2].secAct, yypvt[-1].binstr); } break; -case 714: -#line 1782 "asmparse.y" -{ PASM->AddPermissionSetDecl(yypvt[-1].secAct,BinStrToUnicode(yypvt[-0].binstr,true));} break; -case 715: -#line 1784 "asmparse.y" -{ BinStr* ret = new BinStr(); - ret->insertInt8('.'); - corEmitInt(ret, nSecAttrBlobs); - ret->append(yypvt[-1].binstr); - PASM->AddPermissionSetDecl(yypvt[-4].secAct,ret); - nSecAttrBlobs = 0; } break; -case 716: -#line 1792 "asmparse.y" -{ yyval.binstr = new BinStr(); nSecAttrBlobs = 0;} break; -case 717: -#line 1793 "asmparse.y" -{ yyval.binstr = yypvt[-0].binstr; nSecAttrBlobs = 1; } break; -case 718: -#line 1794 "asmparse.y" -{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->append(yypvt[-0].binstr); nSecAttrBlobs++; } break; -case 719: -#line 1798 "asmparse.y" -{ yyval.binstr = PASM->EncodeSecAttr(PASM->ReflectionNotation(yypvt[-4].token),yypvt[-1].binstr,nCustomBlobNVPairs); - nCustomBlobNVPairs = 0; } break; -case 720: -#line 1801 "asmparse.y" -{ yyval.binstr = PASM->EncodeSecAttr(yypvt[-4].string,yypvt[-1].binstr,nCustomBlobNVPairs); - nCustomBlobNVPairs = 0; } break; -case 721: -#line 1805 "asmparse.y" -{ yyval.secAct = yypvt[-2].secAct; bParsingByteArray = TRUE; } break; -case 722: -#line 1807 "asmparse.y" -{ yyval.secAct = yypvt[-2].secAct; bParsingByteArray = TRUE; } break; -case 723: -#line 1810 "asmparse.y" -{ yyval.pair = yypvt[-0].pair; } break; -case 724: -#line 1811 "asmparse.y" -{ yyval.pair = yypvt[-2].pair->Concat(yypvt[-0].pair); } break; -case 725: -#line 1814 "asmparse.y" -{ yypvt[-2].binstr->appendInt8(0); yyval.pair = new NVPair(yypvt[-2].binstr, yypvt[-0].binstr); } break; -case 726: -#line 1817 "asmparse.y" -{ yyval.int32 = 1; } break; -case 727: -#line 1818 "asmparse.y" -{ yyval.int32 = 0; } break; -case 728: -#line 1821 "asmparse.y" -{ yyval.binstr = new BinStr(); - yyval.binstr->appendInt8(SERIALIZATION_TYPE_BOOLEAN); - yyval.binstr->appendInt8(yypvt[-0].int32); } break; -case 729: -#line 1824 "asmparse.y" -{ yyval.binstr = new BinStr(); - yyval.binstr->appendInt8(SERIALIZATION_TYPE_I4); - yyval.binstr->appendInt32(yypvt[-0].int32); } break; -case 730: -#line 1827 "asmparse.y" -{ yyval.binstr = new BinStr(); - yyval.binstr->appendInt8(SERIALIZATION_TYPE_I4); - yyval.binstr->appendInt32(yypvt[-1].int32); } break; -case 731: -#line 1830 "asmparse.y" -{ yyval.binstr = new BinStr(); - yyval.binstr->appendInt8(SERIALIZATION_TYPE_STRING); - yyval.binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; - yyval.binstr->appendInt8(0); } break; -case 732: -#line 1834 "asmparse.y" -{ yyval.binstr = new BinStr(); - yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); - char* sz = PASM->ReflectionNotation(yypvt[-5].token); - strcpy_s((char *)yyval.binstr->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); - yyval.binstr->appendInt8(1); - yyval.binstr->appendInt32(yypvt[-1].int32); } break; -case 733: -#line 1840 "asmparse.y" -{ yyval.binstr = new BinStr(); - yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); - char* sz = PASM->ReflectionNotation(yypvt[-5].token); - strcpy_s((char *)yyval.binstr->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); - yyval.binstr->appendInt8(2); - yyval.binstr->appendInt32(yypvt[-1].int32); } break; -case 734: -#line 1846 "asmparse.y" -{ yyval.binstr = new BinStr(); - yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); - char* sz = PASM->ReflectionNotation(yypvt[-5].token); - strcpy_s((char *)yyval.binstr->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); - yyval.binstr->appendInt8(4); - yyval.binstr->appendInt32(yypvt[-1].int32); } break; -case 735: -#line 1852 "asmparse.y" -{ yyval.binstr = new BinStr(); - yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); - char* sz = PASM->ReflectionNotation(yypvt[-3].token); - strcpy_s((char *)yyval.binstr->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); - yyval.binstr->appendInt8(4); - yyval.binstr->appendInt32(yypvt[-1].int32); } break; -case 736: -#line 1860 "asmparse.y" -{ yyval.secAct = dclRequest; } break; -case 737: -#line 1861 "asmparse.y" -{ yyval.secAct = dclDemand; } break; -case 738: -#line 1862 "asmparse.y" -{ yyval.secAct = dclAssert; } break; -case 739: -#line 1863 "asmparse.y" -{ yyval.secAct = dclDeny; } break; -case 740: -#line 1864 "asmparse.y" -{ yyval.secAct = dclPermitOnly; } break; -case 741: -#line 1865 "asmparse.y" -{ yyval.secAct = dclLinktimeCheck; } break; -case 742: -#line 1866 "asmparse.y" -{ yyval.secAct = dclInheritanceCheck; } break; -case 743: -#line 1867 "asmparse.y" -{ yyval.secAct = dclRequestMinimum; } break; -case 744: -#line 1868 "asmparse.y" -{ yyval.secAct = dclRequestOptional; } break; -case 745: -#line 1869 "asmparse.y" -{ yyval.secAct = dclRequestRefuse; } break; -case 746: -#line 1870 "asmparse.y" -{ yyval.secAct = dclPrejitGrant; } break; -case 747: -#line 1871 "asmparse.y" -{ yyval.secAct = dclPrejitDenied; } break; -case 748: -#line 1872 "asmparse.y" -{ yyval.secAct = dclNonCasDemand; } break; -case 749: -#line 1873 "asmparse.y" -{ yyval.secAct = dclNonCasLinkDemand; } break; -case 750: -#line 1874 "asmparse.y" -{ yyval.secAct = dclNonCasInheritance; } break; -case 751: -#line 1878 "asmparse.y" -{ PASM->ResetLineNumbers(); nCurrPC = PASM->m_CurPC; PENV->bExternSource = TRUE; PENV->bExternSourceAutoincrement = FALSE; } break; -case 752: -#line 1879 "asmparse.y" -{ PASM->ResetLineNumbers(); nCurrPC = PASM->m_CurPC; PENV->bExternSource = TRUE; PENV->bExternSourceAutoincrement = TRUE; } break; -case 753: -#line 1882 "asmparse.y" -{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-1].int32; - PENV->nExtCol = 0; PENV->nExtColEnd = static_cast(-1); - PASM->SetSourceFileName(yypvt[-0].string);} break; -case 754: -#line 1885 "asmparse.y" -{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-0].int32; - PENV->nExtCol = 0; PENV->nExtColEnd = static_cast(-1); } break; -case 755: -#line 1887 "asmparse.y" -{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-3].int32; - PENV->nExtCol=yypvt[-1].int32; PENV->nExtColEnd = static_cast(-1); - PASM->SetSourceFileName(yypvt[-0].string);} break; -case 756: -#line 1890 "asmparse.y" -{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-2].int32; - PENV->nExtCol=yypvt[-0].int32; PENV->nExtColEnd = static_cast(-1);} break; -case 757: -#line 1893 "asmparse.y" -{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-5].int32; - PENV->nExtCol=yypvt[-3].int32; PENV->nExtColEnd = yypvt[-1].int32; - PASM->SetSourceFileName(yypvt[-0].string);} break; -case 758: -#line 1897 "asmparse.y" -{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-4].int32; - PENV->nExtCol=yypvt[-2].int32; PENV->nExtColEnd = yypvt[-0].int32; } break; -case 759: -#line 1900 "asmparse.y" -{ PENV->nExtLine = yypvt[-5].int32; PENV->nExtLineEnd = yypvt[-3].int32; - PENV->nExtCol=yypvt[-1].int32; PENV->nExtColEnd = static_cast(-1); - PASM->SetSourceFileName(yypvt[-0].string);} break; -case 760: -#line 1904 "asmparse.y" -{ PENV->nExtLine = yypvt[-4].int32; PENV->nExtLineEnd = yypvt[-2].int32; - PENV->nExtCol=yypvt[-0].int32; PENV->nExtColEnd = static_cast(-1); } break; -case 761: -#line 1907 "asmparse.y" -{ PENV->nExtLine = yypvt[-7].int32; PENV->nExtLineEnd = yypvt[-5].int32; - PENV->nExtCol=yypvt[-3].int32; PENV->nExtColEnd = yypvt[-1].int32; - PASM->SetSourceFileName(yypvt[-0].string);} break; -case 762: -#line 1911 "asmparse.y" -{ PENV->nExtLine = yypvt[-6].int32; PENV->nExtLineEnd = yypvt[-4].int32; - PENV->nExtCol=yypvt[-2].int32; PENV->nExtColEnd = yypvt[-0].int32; } break; -case 763: -#line 1913 "asmparse.y" -{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-1].int32 - 1; - PENV->nExtCol = 0; PENV->nExtColEnd = static_cast(-1); - PASM->SetSourceFileName(yypvt[-0].binstr);} break; -case 764: -#line 1920 "asmparse.y" -{ PASMM->AddFile(yypvt[-5].string, yypvt[-6].fileAttr|yypvt[-4].fileAttr|yypvt[-0].fileAttr, yypvt[-2].binstr); } break; -case 765: -#line 1921 "asmparse.y" -{ PASMM->AddFile(yypvt[-1].string, yypvt[-2].fileAttr|yypvt[-0].fileAttr, NULL); } break; -case 766: -#line 1924 "asmparse.y" -{ yyval.fileAttr = (CorFileFlags) 0; } break; -case 767: -#line 1925 "asmparse.y" -{ yyval.fileAttr = (CorFileFlags) (yypvt[-1].fileAttr | ffContainsNoMetaData); } break; -case 768: -#line 1928 "asmparse.y" -{ yyval.fileAttr = (CorFileFlags) 0; } break; -case 769: -#line 1929 "asmparse.y" -{ yyval.fileAttr = (CorFileFlags) 0x80000000; } break; -case 770: -#line 1932 "asmparse.y" -{ bParsingByteArray = TRUE; } break; -case 771: -#line 1935 "asmparse.y" -{ PASMM->StartAssembly(yypvt[-0].string, NULL, (DWORD)yypvt[-1].asmAttr, FALSE); } break; -case 772: -#line 1938 "asmparse.y" -{ yyval.asmAttr = (CorAssemblyFlags) 0; } break; -case 773: -#line 1939 "asmparse.y" -{ yyval.asmAttr = (CorAssemblyFlags) (yypvt[-1].asmAttr | afRetargetable); } break; -case 774: -#line 1940 "asmparse.y" -{ yyval.asmAttr = (CorAssemblyFlags) (yypvt[-1].asmAttr | afContentType_WindowsRuntime); } break; -case 775: -#line 1941 "asmparse.y" -{ yyval.asmAttr = (CorAssemblyFlags) (yypvt[-1].asmAttr | afPA_NoPlatform); } break; -case 776: -#line 1942 "asmparse.y" -{ yyval.asmAttr = yypvt[-2].asmAttr; } break; -case 777: -#line 1943 "asmparse.y" -{ SET_PA(yyval.asmAttr,yypvt[-1].asmAttr,afPA_MSIL); } break; -case 778: -#line 1944 "asmparse.y" -{ SET_PA(yyval.asmAttr,yypvt[-1].asmAttr,afPA_x86); } break; -case 779: -#line 1945 "asmparse.y" -{ SET_PA(yyval.asmAttr,yypvt[-1].asmAttr,afPA_IA64); } break; -case 780: -#line 1946 "asmparse.y" -{ SET_PA(yyval.asmAttr,yypvt[-1].asmAttr,afPA_AMD64); } break; -case 781: -#line 1947 "asmparse.y" -{ SET_PA(yyval.asmAttr,yypvt[-1].asmAttr,afPA_ARM); } break; -case 784: -#line 1954 "asmparse.y" -{ PASMM->SetAssemblyHashAlg(yypvt[-0].int32); } break; -case 787: -#line 1959 "asmparse.y" -{ yyval.int32 = yypvt[-0].int32; } break; -case 788: -#line 1960 "asmparse.y" -{ yyval.int32 = 0xFFFF; } break; -case 789: -#line 1963 "asmparse.y" -{ PASMM->SetAssemblyPublicKey(yypvt[-1].binstr); } break; -case 790: -#line 1965 "asmparse.y" -{ PASMM->SetAssemblyVer((USHORT)yypvt[-6].int32, (USHORT)yypvt[-4].int32, (USHORT)yypvt[-2].int32, (USHORT)yypvt[-0].int32); } break; -case 791: -#line 1966 "asmparse.y" -{ yypvt[-0].binstr->appendInt8(0); PASMM->SetAssemblyLocale(yypvt[-0].binstr,TRUE); } break; -case 792: -#line 1967 "asmparse.y" -{ PASMM->SetAssemblyLocale(yypvt[-1].binstr,FALSE); } break; -case 795: -#line 1972 "asmparse.y" -{ bParsingByteArray = TRUE; } break; -case 796: -#line 1975 "asmparse.y" -{ bParsingByteArray = TRUE; } break; -case 797: -#line 1978 "asmparse.y" -{ bParsingByteArray = TRUE; } break; -case 798: -#line 1982 "asmparse.y" -{ PASMM->StartAssembly(yypvt[-0].string, NULL, yypvt[-1].asmAttr, TRUE); } break; -case 799: -#line 1984 "asmparse.y" -{ PASMM->StartAssembly(yypvt[-2].string, yypvt[-0].string, yypvt[-3].asmAttr, TRUE); } break; -case 802: -#line 1991 "asmparse.y" -{ PASMM->SetAssemblyHashBlob(yypvt[-1].binstr); } break; -case 804: -#line 1993 "asmparse.y" -{ PASMM->SetAssemblyPublicKeyToken(yypvt[-1].binstr); } break; -case 805: -#line 1994 "asmparse.y" -{ PASMM->SetAssemblyAutodetect(); } break; -case 806: -#line 1997 "asmparse.y" -{ PASMM->StartComType(yypvt[-0].string, yypvt[-1].exptAttr);} break; -case 807: -#line 2000 "asmparse.y" -{ PASMM->StartComType(yypvt[-0].string, yypvt[-1].exptAttr); } break; -case 808: -#line 2003 "asmparse.y" -{ yyval.exptAttr = (CorTypeAttr) 0; } break; -case 809: -#line 2004 "asmparse.y" -{ yyval.exptAttr = (CorTypeAttr) (yypvt[-1].exptAttr | tdNotPublic); } break; -case 810: -#line 2005 "asmparse.y" -{ yyval.exptAttr = (CorTypeAttr) (yypvt[-1].exptAttr | tdPublic); } break; -case 811: -#line 2006 "asmparse.y" -{ yyval.exptAttr = (CorTypeAttr) (yypvt[-1].exptAttr | tdForwarder); } break; -case 812: -#line 2007 "asmparse.y" -{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedPublic); } break; -case 813: -#line 2008 "asmparse.y" -{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedPrivate); } break; -case 814: -#line 2009 "asmparse.y" -{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedFamily); } break; -case 815: -#line 2010 "asmparse.y" -{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedAssembly); } break; -case 816: -#line 2011 "asmparse.y" -{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedFamANDAssem); } break; -case 817: -#line 2012 "asmparse.y" -{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedFamORAssem); } break; -case 820: -#line 2019 "asmparse.y" -{ PASMM->SetComTypeFile(yypvt[-0].string); } break; -case 821: -#line 2020 "asmparse.y" -{ PASMM->SetComTypeComType(yypvt[-0].string); } break; -case 822: -#line 2021 "asmparse.y" -{ PASMM->SetComTypeAsmRef(yypvt[-0].string); } break; -case 823: -#line 2022 "asmparse.y" -{ if(!PASMM->SetComTypeImplementationTok(yypvt[-1].int32)) - PASM->report->error("Invalid implementation of exported type\n"); } break; -case 824: -#line 2024 "asmparse.y" -{ if(!PASMM->SetComTypeClassTok(yypvt[-0].int32)) - PASM->report->error("Invalid TypeDefID of exported type\n"); } break; -case 827: -#line 2030 "asmparse.y" -{ PASMM->StartManifestRes(yypvt[-0].string, yypvt[-0].string, yypvt[-1].manresAttr); } break; -case 828: -#line 2032 "asmparse.y" -{ PASMM->StartManifestRes(yypvt[-2].string, yypvt[-0].string, yypvt[-3].manresAttr); } break; -case 829: -#line 2035 "asmparse.y" -{ yyval.manresAttr = (CorManifestResourceFlags) 0; } break; -case 830: -#line 2036 "asmparse.y" -{ yyval.manresAttr = (CorManifestResourceFlags) (yypvt[-1].manresAttr | mrPublic); } break; -case 831: -#line 2037 "asmparse.y" -{ yyval.manresAttr = (CorManifestResourceFlags) (yypvt[-1].manresAttr | mrPrivate); } break; -case 834: -#line 2044 "asmparse.y" -{ PASMM->SetManifestResFile(yypvt[-2].string, (ULONG)yypvt[-0].int32); } break; -case 835: -#line 2045 "asmparse.y" -{ PASMM->SetManifestResAsmRef(yypvt[-0].string); } break;/* End of actions */ -#line 329 "D:\\ProjectK3\\src\\tools\\devdiv\\x86\\yypars.c" - } - } - goto yystack; /* stack new state and value */ - } -#pragma warning(default:102) - - -#ifdef YYDUMP -YYLOCAL void YYNEAR YYPASCAL yydumpinfo(void) -{ - short stackindex; - short valindex; - - //dump yys - printf("short yys[%d] {\n", YYMAXDEPTH); - for (stackindex = 0; stackindex < YYMAXDEPTH; stackindex++){ - if (stackindex) - printf(", %s", stackindex % 10 ? "\0" : "\n"); - printf("%6d", yys[stackindex]); - } - printf("\n};\n"); - - //dump yyv - printf("YYSTYPE yyv[%d] {\n", YYMAXDEPTH); - for (valindex = 0; valindex < YYMAXDEPTH; valindex++){ - if (valindex) - printf(", %s", valindex % 5 ? "\0" : "\n"); - printf("%#*x", 3+sizeof(YYSTYPE), yyv[valindex]); - } - printf("\n};\n"); - } -#endif diff --git a/src/ilasm/prebuilt/asmparse.cpp b/src/ilasm/prebuilt/asmparse.cpp new file mode 100644 index 0000000..50c6203 --- /dev/null +++ b/src/ilasm/prebuilt/asmparse.cpp @@ -0,0 +1,4907 @@ +/* + * Created by Microsoft VCBU Internal YACC from "asmparse.y" + */ + +#line 2 "asmparse.y" + + // 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. +// +// File asmparse.y +// +#include "ilasmpch.h" + +#include "grammar_before.cpp" + + +#line 16 "asmparse.y" + +#define UNION 1 +typedef union { + CorRegTypeAttr classAttr; + CorMethodAttr methAttr; + CorFieldAttr fieldAttr; + CorMethodImpl implAttr; + CorEventAttr eventAttr; + CorPropertyAttr propAttr; + CorPinvokeMap pinvAttr; + CorDeclSecurity secAct; + CorFileFlags fileAttr; + CorAssemblyFlags asmAttr; + CorAssemblyFlags asmRefAttr; + CorTypeAttr exptAttr; + CorManifestResourceFlags manresAttr; + double* float64; + __int64* int64; + __int32 int32; + char* string; + BinStr* binstr; + Labels* labels; + Instr* instr; // instruction opcode + NVPair* pair; + pTyParList typarlist; + mdToken token; + TypeDefDescr* tdd; + CustomDescr* cad; + unsigned short opcode; +} YYSTYPE; +# define ERROR_ 257 +# define BAD_COMMENT_ 258 +# define BAD_LITERAL_ 259 +# define ID 260 +# define DOTTEDNAME 261 +# define QSTRING 262 +# define SQSTRING 263 +# define INT32 264 +# define INT64 265 +# define FLOAT64 266 +# define HEXBYTE 267 +# define TYPEDEF_T 268 +# define TYPEDEF_M 269 +# define TYPEDEF_F 270 +# define TYPEDEF_TS 271 +# define TYPEDEF_MR 272 +# define TYPEDEF_CA 273 +# define DCOLON 274 +# define ELIPSIS 275 +# define VOID_ 276 +# define BOOL_ 277 +# define CHAR_ 278 +# define UNSIGNED_ 279 +# define INT_ 280 +# define INT8_ 281 +# define INT16_ 282 +# define INT32_ 283 +# define INT64_ 284 +# define FLOAT_ 285 +# define FLOAT32_ 286 +# define FLOAT64_ 287 +# define BYTEARRAY_ 288 +# define UINT_ 289 +# define UINT8_ 290 +# define UINT16_ 291 +# define UINT32_ 292 +# define UINT64_ 293 +# define FLAGS_ 294 +# define CALLCONV_ 295 +# define MDTOKEN_ 296 +# define OBJECT_ 297 +# define STRING_ 298 +# define NULLREF_ 299 +# define DEFAULT_ 300 +# define CDECL_ 301 +# define VARARG_ 302 +# define STDCALL_ 303 +# define THISCALL_ 304 +# define FASTCALL_ 305 +# define CLASS_ 306 +# define TYPEDREF_ 307 +# define UNMANAGED_ 308 +# define FINALLY_ 309 +# define HANDLER_ 310 +# define CATCH_ 311 +# define FILTER_ 312 +# define FAULT_ 313 +# define EXTENDS_ 314 +# define IMPLEMENTS_ 315 +# define TO_ 316 +# define AT_ 317 +# define TLS_ 318 +# define TRUE_ 319 +# define FALSE_ 320 +# define _INTERFACEIMPL 321 +# define VALUE_ 322 +# define VALUETYPE_ 323 +# define NATIVE_ 324 +# define INSTANCE_ 325 +# define SPECIALNAME_ 326 +# define FORWARDER_ 327 +# define STATIC_ 328 +# define PUBLIC_ 329 +# define PRIVATE_ 330 +# define FAMILY_ 331 +# define FINAL_ 332 +# define SYNCHRONIZED_ 333 +# define INTERFACE_ 334 +# define SEALED_ 335 +# define NESTED_ 336 +# define ABSTRACT_ 337 +# define AUTO_ 338 +# define SEQUENTIAL_ 339 +# define EXPLICIT_ 340 +# define ANSI_ 341 +# define UNICODE_ 342 +# define AUTOCHAR_ 343 +# define IMPORT_ 344 +# define ENUM_ 345 +# define VIRTUAL_ 346 +# define NOINLINING_ 347 +# define AGGRESSIVEINLINING_ 348 +# define NOOPTIMIZATION_ 349 +# define UNMANAGEDEXP_ 350 +# define BEFOREFIELDINIT_ 351 +# define STRICT_ 352 +# define RETARGETABLE_ 353 +# define WINDOWSRUNTIME_ 354 +# define NOPLATFORM_ 355 +# define METHOD_ 356 +# define FIELD_ 357 +# define PINNED_ 358 +# define MODREQ_ 359 +# define MODOPT_ 360 +# define SERIALIZABLE_ 361 +# define PROPERTY_ 362 +# define TYPE_ 363 +# define ASSEMBLY_ 364 +# define FAMANDASSEM_ 365 +# define FAMORASSEM_ 366 +# define PRIVATESCOPE_ 367 +# define HIDEBYSIG_ 368 +# define NEWSLOT_ 369 +# define RTSPECIALNAME_ 370 +# define PINVOKEIMPL_ 371 +# define _CTOR 372 +# define _CCTOR 373 +# define LITERAL_ 374 +# define NOTSERIALIZED_ 375 +# define INITONLY_ 376 +# define REQSECOBJ_ 377 +# define CIL_ 378 +# define OPTIL_ 379 +# define MANAGED_ 380 +# define FORWARDREF_ 381 +# define PRESERVESIG_ 382 +# define RUNTIME_ 383 +# define INTERNALCALL_ 384 +# define _IMPORT 385 +# define NOMANGLE_ 386 +# define LASTERR_ 387 +# define WINAPI_ 388 +# define AS_ 389 +# define BESTFIT_ 390 +# define ON_ 391 +# define OFF_ 392 +# define CHARMAPERROR_ 393 +# define INSTR_NONE 394 +# define INSTR_VAR 395 +# define INSTR_I 396 +# define INSTR_I8 397 +# define INSTR_R 398 +# define INSTR_BRTARGET 399 +# define INSTR_METHOD 400 +# define INSTR_FIELD 401 +# define INSTR_TYPE 402 +# define INSTR_STRING 403 +# define INSTR_SIG 404 +# define INSTR_TOK 405 +# define INSTR_SWITCH 406 +# define _CLASS 407 +# define _NAMESPACE 408 +# define _METHOD 409 +# define _FIELD 410 +# define _DATA 411 +# define _THIS 412 +# define _BASE 413 +# define _NESTER 414 +# define _EMITBYTE 415 +# define _TRY 416 +# define _MAXSTACK 417 +# define _LOCALS 418 +# define _ENTRYPOINT 419 +# define _ZEROINIT 420 +# define _EVENT 421 +# define _ADDON 422 +# define _REMOVEON 423 +# define _FIRE 424 +# define _OTHER 425 +# define _PROPERTY 426 +# define _SET 427 +# define _GET 428 +# define _PERMISSION 429 +# define _PERMISSIONSET 430 +# define REQUEST_ 431 +# define DEMAND_ 432 +# define ASSERT_ 433 +# define DENY_ 434 +# define PERMITONLY_ 435 +# define LINKCHECK_ 436 +# define INHERITCHECK_ 437 +# define REQMIN_ 438 +# define REQOPT_ 439 +# define REQREFUSE_ 440 +# define PREJITGRANT_ 441 +# define PREJITDENY_ 442 +# define NONCASDEMAND_ 443 +# define NONCASLINKDEMAND_ 444 +# define NONCASINHERITANCE_ 445 +# define _LINE 446 +# define P_LINE 447 +# define _LANGUAGE 448 +# define _CUSTOM 449 +# define INIT_ 450 +# define _SIZE 451 +# define _PACK 452 +# define _VTABLE 453 +# define _VTFIXUP 454 +# define FROMUNMANAGED_ 455 +# define CALLMOSTDERIVED_ 456 +# define _VTENTRY 457 +# define RETAINAPPDOMAIN_ 458 +# define _FILE 459 +# define NOMETADATA_ 460 +# define _HASH 461 +# define _ASSEMBLY 462 +# define _PUBLICKEY 463 +# define _PUBLICKEYTOKEN 464 +# define ALGORITHM_ 465 +# define _VER 466 +# define _LOCALE 467 +# define EXTERN_ 468 +# define _MRESOURCE 469 +# define _MODULE 470 +# define _EXPORT 471 +# define LEGACY_ 472 +# define LIBRARY_ 473 +# define X86_ 474 +# define IA64_ 475 +# define AMD64_ 476 +# define ARM_ 477 +# define MARSHAL_ 478 +# define CUSTOM_ 479 +# define SYSSTRING_ 480 +# define FIXED_ 481 +# define VARIANT_ 482 +# define CURRENCY_ 483 +# define SYSCHAR_ 484 +# define DECIMAL_ 485 +# define DATE_ 486 +# define BSTR_ 487 +# define TBSTR_ 488 +# define LPSTR_ 489 +# define LPWSTR_ 490 +# define LPTSTR_ 491 +# define OBJECTREF_ 492 +# define IUNKNOWN_ 493 +# define IDISPATCH_ 494 +# define STRUCT_ 495 +# define SAFEARRAY_ 496 +# define BYVALSTR_ 497 +# define LPVOID_ 498 +# define ANY_ 499 +# define ARRAY_ 500 +# define LPSTRUCT_ 501 +# define IIDPARAM_ 502 +# define IN_ 503 +# define OUT_ 504 +# define OPT_ 505 +# define PARAM_ 506 +# define _OVERRIDE 507 +# define WITH_ 508 +# define NULL_ 509 +# define HRESULT_ 510 +# define CARRAY_ 511 +# define USERDEFINED_ 512 +# define RECORD_ 513 +# define FILETIME_ 514 +# define BLOB_ 515 +# define STREAM_ 516 +# define STORAGE_ 517 +# define STREAMED_OBJECT_ 518 +# define STORED_OBJECT_ 519 +# define BLOB_OBJECT_ 520 +# define CF_ 521 +# define CLSID_ 522 +# define VECTOR_ 523 +# define _SUBSYSTEM 524 +# define _CORFLAGS 525 +# define ALIGNMENT_ 526 +# define _IMAGEBASE 527 +# define _STACKRESERVE 528 +# define _TYPEDEF 529 +# define _TEMPLATE 530 +# define _TYPELIST 531 +# define _MSCORLIB 532 +# define P_DEFINE 533 +# define P_UNDEF 534 +# define P_IFDEF 535 +# define P_IFNDEF 536 +# define P_ELSE 537 +# define P_ENDIF 538 +# define P_INCLUDE 539 +#define yyclearin yychar = -1 +#define yyerrok yyerrflag = 0 +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 150 +#endif +YYSTYPE yylval, yyval; +#ifndef YYFARDATA +#define YYFARDATA /*nothing*/ +#endif +#if ! defined YYSTATIC +#define YYSTATIC /*nothing*/ +#endif +#if ! defined YYCONST +#define YYCONST /*nothing*/ +#endif +#ifndef YYACT +#define YYACT yyact +#endif +#ifndef YYPACT +#define YYPACT yypact +#endif +#ifndef YYPGO +#define YYPGO yypgo +#endif +#ifndef YYR1 +#define YYR1 yyr1 +#endif +#ifndef YYR2 +#define YYR2 yyr2 +#endif +#ifndef YYCHK +#define YYCHK yychk +#endif +#ifndef YYDEF +#define YYDEF yydef +#endif +#ifndef YYV +#define YYV yyv +#endif +#ifndef YYS +#define YYS yys +#endif +#ifndef YYLOCAL +#define YYLOCAL +#endif +#ifndef YYR_T +#define YYR_T int +#endif +typedef YYR_T yyr_t; +#ifndef YYEXIND_T +#define YYEXIND_T unsigned int +#endif +typedef YYEXIND_T yyexind_t; +#ifndef YYOPTTIME +#define YYOPTTIME 0 +#endif +# define YYERRCODE 256 + +#line 2051 "asmparse.y" + + +#include "grammar_after.cpp" +YYSTATIC YYCONST short yyexca[] = { +#if !(YYOPTTIME) +-1, 1, +#endif + 0, -1, + -2, 0, +#if !(YYOPTTIME) +-1, 452, +#endif + 41, 532, + -2, 308, +#if !(YYOPTTIME) +-1, 621, +#endif + 274, 549, + 47, 549, + -2, 227, +#if !(YYOPTTIME) +-1, 642, +#endif + 40, 307, + 60, 307, + -2, 549, +#if !(YYOPTTIME) +-1, 663, +#endif + 41, 532, + -2, 308, +#if !(YYOPTTIME) +-1, 686, +#endif + 274, 549, + 47, 549, + -2, 510, +#if !(YYOPTTIME) +-1, 803, +#endif + 123, 232, + -2, 549, +#if !(YYOPTTIME) +-1, 828, +#endif + 41, 532, + -2, 308, +#if !(YYOPTTIME) +-1, 953, +#endif + 41, 532, + -2, 308, +#if !(YYOPTTIME) +-1, 986, +#endif + 41, 532, + -2, 308, +#if !(YYOPTTIME) +-1, 987, +#endif + 41, 532, + -2, 308, +#if !(YYOPTTIME) +-1, 1308, +#endif + 41, 532, + -2, 308, +#if !(YYOPTTIME) +-1, 1309, +#endif + 41, 532, + -2, 308, +#if !(YYOPTTIME) +-1, 1315, +#endif + 41, 532, + -2, 308, +#if !(YYOPTTIME) +-1, 1322, +#endif + 41, 532, + -2, 308, +#if !(YYOPTTIME) +-1, 1447, +#endif + 41, 532, + -2, 308, +#if !(YYOPTTIME) +-1, 1479, +#endif + 41, 532, + -2, 308, +#if !(YYOPTTIME) +-1, 1545, +#endif + 41, 532, + -2, 308, +#if !(YYOPTTIME) +-1, 1562, +#endif + 41, 532, + -2, 308, + +}; + +# define YYNPROD 838 +#if YYOPTTIME +YYSTATIC YYCONST yyexind_t yyexcaind[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 42, 46, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 50, 54, + 0, 0, 0, 0, 0, 58, 0, 0, 0, 0, + 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 78 +}; +#endif +# define YYLAST 3904 + +YYSTATIC YYCONST short YYFARDATA YYACT[] = { + 699, 1398, 1121, 1466, 658, 1467, 639, 1024, 1465, 878, + 1464, 963, 784, 753, 964, 221, 775, 26, 698, 725, + 73, 75, 275, 414, 624, 877, 966, 1399, 535, 191, + 477, 1503, 150, 788, 751, 756, 1134, 110, 1065, 107, + 690, 852, 273, 153, 219, 660, 24, 44, 776, 218, + 307, 10, 190, 176, 78, 81, 6, 86, 5, 598, + 673, 262, 204, 515, 3, 188, 217, 983, 17, 301, + 603, 136, 76, 1550, 1194, 1242, 214, 264, 7, 1238, + 1057, 1239, 1113, 1111, 85, 1112, 580, 74, 715, 88, + 87, 137, 89, 300, 115, 56, 139, 712, 672, 113, + 1058, 98, 112, 178, 179, 180, 181, 74, 272, 696, + 322, 519, 1015, 461, 220, 56, 18, 452, 536, 338, + 278, 88, 87, 1021, 89, 268, 216, 269, 1240, 225, + 56, 265, 277, 277, 1228, 1229, 106, 1226, 1227, 590, + 277, 343, 361, 360, 359, 358, 654, 368, 345, 653, + 68, 310, 312, 314, 316, 318, 185, 1554, 460, 1126, + 1127, 1414, 98, 931, 932, 327, 277, 348, 339, 1027, + 342, 778, 1026, 779, 373, 366, 154, 277, 695, 133, + 694, 991, 379, 271, 362, 84, 258, 364, 363, 376, + 614, 192, 387, 105, 1519, 662, 513, 930, 365, 1059, + 369, 202, 203, 371, 370, 1487, 374, 1264, 596, 450, + 661, 451, 763, 372, 416, 469, 186, 467, 471, 470, + 442, 26, 74, 376, 456, 417, 418, 346, 376, 1559, + 352, 472, 474, 599, 353, 305, 483, 388, 88, 87, + 596, 89, 410, 1263, 1478, 500, 492, 1314, 457, 441, + 24, 1200, 357, 491, 435, 10, 825, 797, 787, 56, + 486, 432, 490, 428, 475, 478, 479, 773, 476, 429, + 494, 434, 17, 192, 108, 666, 511, 511, 528, 534, + 375, 433, 7, 351, 267, 321, 480, 481, 473, 485, + 152, 710, 74, 484, 1234, 540, 1345, 116, 1496, 1391, + 56, 1540, 499, 80, 79, 498, 543, 493, 1417, 571, + 959, 268, 1351, 1544, 574, 348, 575, 154, 576, 436, + 18, 266, 548, 1335, 1116, 578, 579, 504, 541, 46, + 420, 544, 421, 422, 423, 933, 934, 570, 935, 88, + 572, 947, 89, 573, 46, 594, 854, 855, 856, 1128, + 640, 641, 600, 135, 198, 88, 87, 962, 89, 199, + 1541, 200, 568, 1510, 192, 487, 1341, 201, 612, 154, + 755, 482, 277, 674, 1543, 510, 510, 527, 533, 74, + 605, 744, 745, 746, 195, 808, 182, 623, 943, 611, + 599, 581, 582, 1141, 497, 1233, 700, 1252, 1142, 196, + 565, 367, 375, 620, 595, 258, 610, 88, 87, 518, + 89, 74, 606, 607, 608, 609, 747, 748, 749, 1542, + 643, 613, 599, 537, 340, 341, 634, 1489, 348, 807, + 459, 618, 619, 621, 780, 1130, 321, 876, 648, 649, + 638, 88, 87, 177, 89, 1231, 88, 87, 847, 89, + 152, 781, 702, 754, 347, 650, 664, 1502, 413, 88, + 87, 670, 946, 1488, 651, 88, 87, 155, 89, 681, + 642, 1518, 1126, 1127, 545, 743, 1118, 177, 993, 994, + 995, 996, 177, 587, 505, 859, 352, 1513, 667, 988, + 353, 678, 80, 79, 479, 177, 647, 692, 646, 1512, + 782, 1511, 61, 62, 47, 63, 536, 1508, 357, 645, + 685, 198, 741, 669, 480, 481, 199, 689, 200, 82, + 63, 74, 701, 479, 201, 711, 680, 453, 72, 679, + 88, 87, 519, 89, 512, 520, 74, 507, 508, 351, + 686, 195, 88, 480, 481, 89, 74, 723, 71, 70, + 354, 355, 356, 538, 691, 216, 196, 1141, 225, 1506, + 1241, 724, 1142, 675, 676, 677, 720, 657, 721, 49, + 50, 51, 52, 53, 54, 55, 671, 709, 74, 644, + 479, 730, 1504, 80, 79, 714, 80, 79, 348, 49, + 50, 51, 52, 53, 54, 55, 719, 74, 1141, 716, + 480, 481, 726, 1142, 49, 50, 51, 52, 53, 54, + 55, 156, 157, 158, 69, 758, 74, 542, 74, 88, + 87, 592, 89, 600, 67, 764, 765, 155, 88, 87, + 688, 89, 74, 783, 98, 638, 729, 1320, 1319, 1318, + 1317, 750, 74, 697, 325, 74, 703, 1172, 1171, 1170, + 1169, 542, 705, 348, 706, 177, 377, 1499, 324, 769, + 770, 771, 1337, 1338, 1339, 642, 815, 789, 813, 819, + 853, 88, 87, 816, 89, 822, 541, 1180, 801, 802, + 80, 79, 798, 823, 88, 812, 806, 89, 74, 66, + 818, 626, 627, 628, 74, 1117, 833, 834, 762, 1450, + 495, 826, 216, 786, 591, 225, 1439, 800, 793, 803, + 74, 809, 796, 636, 846, 824, 382, 383, 384, 385, + 817, 152, 74, 857, 74, 56, 629, 630, 631, 922, + 74, 740, 821, 49, 50, 51, 52, 53, 54, 55, + 1437, 850, 936, 937, 860, 1490, 516, 761, 88, 87, + 375, 89, 832, 1327, 844, 1247, 1243, 1244, 1245, 1246, + 1179, 1435, 769, 600, 949, 192, 845, 942, 1433, 848, + 276, 156, 157, 158, 49, 50, 51, 52, 53, 54, + 55, 97, 74, 924, 111, 925, 926, 927, 928, 929, + 952, 1001, 1416, 1407, 985, 152, 635, 938, 1406, 277, + 1013, 965, 362, 1326, 1011, 74, 354, 355, 356, 442, + 1000, 1009, 528, 605, 1404, 585, 954, 584, 583, 145, + 1390, 1012, 948, 1388, 586, 799, 960, 955, 277, 1017, + 958, 692, 692, 1032, 1378, 1376, 1237, 350, 441, 999, + 1008, 817, 1022, 435, 997, 1007, 851, 1374, 1037, 1014, + 432, 817, 428, 849, 1019, 1035, 1016, 1018, 429, 1039, + 434, 989, 326, 323, 88, 87, 94, 89, 74, 1372, + 433, 1033, 1034, 1045, 352, 772, 828, 277, 353, 1030, + 80, 79, 479, 1050, 277, 56, 1370, 1368, 691, 691, + 88, 87, 348, 89, 74, 954, 357, 337, 155, 348, + 1366, 1364, 480, 481, 668, 1362, 817, 1359, 436, 998, + 1006, 527, 1356, 1123, 1354, 1350, 56, 1334, 1312, 1055, + 152, 1196, 88, 87, 718, 89, 177, 351, 1044, 1053, + 193, 615, 1043, 194, 1051, 348, 1042, 352, 1041, 46, + 352, 353, 1122, 1023, 768, 820, 1067, 814, 1068, 1126, + 1127, 501, 733, 617, 616, 1124, 198, 177, 1132, 357, + 145, 199, 357, 200, 88, 87, 577, 89, 758, 201, + 564, 1300, 155, 1236, 308, 1119, 455, 109, 1054, 1140, + 1129, 92, 529, 1138, 1125, 1394, 195, 1298, 1115, 1185, + 351, 1183, 1184, 351, 88, 87, 1186, 89, 1178, 277, + 177, 196, 1296, 1491, 1064, 1060, 1061, 1062, 1063, 1025, + 1492, 1133, 145, 1182, 1415, 328, 329, 330, 1294, 1181, + 956, 96, 1301, 590, 104, 103, 102, 101, 1219, 99, + 100, 105, 56, 1, 1175, 1332, 1195, 1173, 1299, 1203, + 332, 941, 156, 157, 158, 1167, 1187, 1188, 1189, 1190, + 1230, 766, 1202, 1297, 1165, 1232, 1191, 1192, 1193, 80, + 79, 479, 588, 1131, 1223, 1225, 1224, 1222, 984, 1295, + 1235, 1197, 1400, 88, 87, 1163, 89, 1198, 1161, 1199, + 945, 480, 481, 589, 1218, 1176, 189, 708, 1174, 88, + 87, 1005, 89, 1003, 1004, 1159, 1168, 155, 1010, 46, + 707, 205, 152, 1157, 704, 1166, 633, 1412, 412, 187, + 625, 790, 61, 62, 47, 63, 156, 157, 158, 1248, + 1177, 192, 192, 192, 192, 177, 1164, 277, 1268, 1162, + 46, 192, 192, 192, 331, 1266, 333, 334, 335, 336, + 1155, 625, 1251, 192, 1411, 1265, 1160, 1269, 1410, 1271, + 1273, 1274, 1255, 1277, 1158, 1279, 1280, 1281, 1282, 1283, + 1284, 1285, 1270, 1287, 1288, 1289, 1290, 1291, 1292, 1293, + 1254, 1401, 1259, 56, 1302, 1303, 1153, 1305, 1304, 1151, + 1272, 1149, 1275, 1276, 1147, 1278, 1221, 1048, 1267, 1047, + 836, 1156, 1307, 1286, 354, 355, 356, 1145, 1143, 49, + 50, 51, 52, 53, 54, 55, 742, 1316, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 665, 1313, 352, 317, 1154, 454, 353, + 1152, 315, 1150, 313, 1328, 1148, 378, 1330, 1331, 521, + 1321, 156, 157, 158, 311, 45, 46, 357, 1146, 1144, + 1336, 1340, 309, 1333, 817, 41, 43, 354, 355, 356, + 354, 355, 356, 1135, 1342, 277, 277, 1140, 1552, 526, + 590, 88, 87, 306, 89, 63, 415, 308, 351, 155, + 1315, 1343, 308, 1257, 308, 56, 277, 503, 1452, 512, + 590, 1451, 507, 508, 140, 308, 1380, 1381, 1382, 1383, + 1384, 1385, 1386, 308, 944, 1347, 63, 177, 590, 1539, + 590, 1329, 1344, 1392, 1393, 193, 531, 1346, 194, 532, + 1397, 1396, 940, 831, 308, 138, 1379, 1402, 1403, 1031, + 1524, 590, 923, 1408, 590, 590, 1395, 830, 811, 767, + 760, 198, 177, 1405, 717, 566, 199, 349, 200, 258, + 303, 792, 1564, 117, 201, 97, 1555, 1553, 1140, 49, + 50, 51, 52, 53, 54, 55, 1546, 1523, 817, 1486, + 1485, 195, 1484, 1454, 1449, 1446, 1443, 1442, 1438, 56, + 524, 1436, 1434, 1432, 1419, 1413, 196, 46, 1409, 1389, + 49, 50, 51, 52, 53, 54, 55, 134, 1445, 1387, + 1377, 1375, 1373, 1371, 1369, 1367, 1365, 1363, 1361, 1360, + 526, 1455, 1456, 1457, 1358, 1357, 1355, 1453, 1353, 1444, + 1448, 1352, 63, 156, 157, 158, 1349, 1324, 1348, 1325, + 1458, 1323, 523, 1311, 1470, 525, 1310, 1471, 1469, 1468, + 1306, 1256, 1253, 258, 1476, 693, 1220, 88, 87, 1114, + 89, 1052, 1481, 1038, 1480, 1036, 1029, 1028, 1020, 961, + 951, 950, 56, 1498, 939, 1483, 1505, 1507, 1509, 858, + 1505, 1507, 1509, 530, 841, 840, 1495, 1507, 1516, 838, + 1520, 1517, 1515, 1514, 1522, 1521, 88, 835, 829, 89, + 827, 56, 810, 1497, 1500, 1501, 791, 774, 738, 46, + 737, 1538, 736, 1493, 735, 734, 49, 50, 51, 52, + 53, 54, 55, 732, 731, 1529, 1505, 1507, 1509, 684, + 637, 524, 569, 425, 424, 344, 258, 320, 206, 1562, + 1547, 1525, 817, 1545, 1479, 1475, 1474, 1473, 1472, 1447, + 1534, 1441, 1440, 1431, 1430, 354, 355, 356, 1551, 1429, + 1549, 1428, 1427, 1548, 1535, 1536, 1537, 449, 1426, 1425, + 1424, 1423, 1561, 63, 1422, 1421, 1560, 1563, 1420, 1418, + 1300, 1298, 1296, 523, 1294, 1322, 525, 1175, 1173, 1557, + 88, 1558, 1167, 89, 1556, 1526, 1527, 1528, 1530, 1531, + 1532, 1533, 1165, 46, 1163, 96, 1161, 1159, 104, 103, + 102, 101, 56, 99, 100, 105, 1157, 1155, 1153, 1151, + 1149, 1309, 1308, 817, 1250, 1249, 1066, 1056, 1049, 1040, + 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 987, 986, 953, 843, 59, 842, 839, + 837, 208, 259, 210, 228, 212, 213, 49, 50, 51, + 52, 53, 54, 55, 728, 41, 43, 727, 713, 687, + 683, 682, 663, 88, 632, 602, 89, 601, 593, 567, + 547, 546, 61, 62, 47, 63, 46, 496, 419, 411, + 874, 386, 319, 223, 304, 522, 514, 868, 517, 869, + 870, 871, 509, 506, 56, 502, 302, 222, 36, 184, + 93, 33, 468, 466, 465, 46, 464, 463, 244, 462, + 227, 243, 215, 209, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 863, 864, 865, + 95, 59, 226, 224, 207, 208, 259, 210, 228, 212, + 213, 211, 879, 31, 56, 1002, 992, 439, 795, 41, + 43, 431, 794, 430, 427, 539, 1046, 270, 83, 49, + 50, 51, 52, 53, 54, 55, 61, 62, 47, 63, + 29, 57, 862, 866, 867, 34, 872, 223, 25, 873, + 16, 263, 15, 14, 261, 13, 260, 12, 11, 9, + 8, 222, 1086, 4, 2, 234, 242, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, + 990, 241, 240, 239, 59, 238, 46, 237, 208, 259, + 210, 228, 212, 213, 236, 235, 226, 224, 233, 232, + 231, 230, 41, 43, 229, 114, 77, 42, 56, 38, + 30, 58, 32, 59, 752, 656, 655, 1482, 299, 61, + 62, 47, 63, 49, 50, 51, 52, 53, 54, 55, + 223, 41, 43, 90, 183, 861, 1139, 757, 785, 1258, + 957, 1137, 1136, 604, 222, 1461, 1460, 1459, 61, 62, + 47, 63, 1477, 1463, 1462, 60, 35, 1201, 1120, 597, + 659, 21, 777, 91, 37, 1069, 739, 65, 64, 197, + 875, 39, 40, 0, 426, 0, 0, 0, 0, 226, + 224, 0, 982, 981, 980, 0, 975, 974, 973, 972, + 0, 970, 971, 105, 0, 979, 978, 977, 976, 0, + 0, 0, 969, 967, 0, 0, 49, 50, 51, 52, + 53, 54, 55, 0, 0, 0, 0, 0, 0, 0, + 38, 30, 58, 32, 59, 0, 19, 20, 46, 22, + 23, 48, 0, 27, 28, 49, 50, 51, 52, 53, + 54, 55, 41, 43, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, + 62, 47, 63, 0, 0, 0, 60, 35, 968, 0, + 0, 0, 21, 0, 0, 37, 444, 1097, 0, 874, + 0, 0, 39, 40, 0, 0, 868, 0, 869, 870, + 871, 0, 0, 0, 0, 0, 1073, 1074, 0, 1081, + 1095, 1075, 1076, 1077, 1078, 0, 1079, 1080, 0, 1096, + 1082, 1083, 1084, 1085, 0, 0, 0, 0, 0, 0, + 0, 0, 46, 0, 0, 0, 863, 864, 865, 0, + 0, 0, 0, 0, 0, 0, 0, 19, 20, 0, + 22, 23, 48, 0, 27, 28, 49, 50, 51, 52, + 53, 54, 55, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 448, 0, 58, 32, 59, 0, 0, 0, + 444, 862, 866, 867, 0, 872, 445, 0, 873, 0, + 0, 446, 0, 0, 41, 43, 0, 146, 874, 0, + 0, 0, 0, 0, 0, 868, 0, 869, 870, 871, + 0, 61, 62, 47, 63, 0, 437, 438, 0, 921, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 447, 0, 0, 0, + 0, 0, 0, 0, 0, 863, 864, 865, 49, 50, + 51, 52, 53, 54, 55, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 448, 0, 58, 32, + 59, 443, 440, 0, 0, 0, 0, 0, 0, 0, + 445, 0, 0, 0, 0, 446, 0, 0, 41, 43, + 862, 866, 867, 0, 872, 0, 0, 873, 49, 50, + 51, 52, 53, 54, 55, 61, 62, 47, 63, 1494, + 437, 438, 1071, 1072, 0, 1087, 1088, 1089, 0, 1090, + 1091, 0, 0, 1092, 1093, 0, 1094, 0, 0, 0, + 447, 0, 0, 0, 0, 0, 0, 0, 0, 1070, + 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, + 1108, 1109, 1110, 893, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 443, 440, 920, 0, 0, + 0, 0, 885, 886, 0, 894, 911, 887, 888, 889, + 890, 0, 891, 892, 0, 912, 895, 896, 897, 898, + 893, 0, 49, 50, 51, 52, 53, 54, 55, 0, + 0, 0, 0, 0, 920, 146, 0, 0, 0, 885, + 886, 0, 894, 911, 887, 888, 889, 890, 0, 891, + 892, 0, 912, 895, 896, 897, 898, 0, 0, 0, + 909, 0, 913, 0, 0, 175, 0, 915, 0, 151, + 148, 163, 161, 170, 0, 164, 165, 166, 167, 0, + 168, 169, 917, 0, 171, 172, 173, 174, 563, 0, + 0, 142, 162, 152, 0, 0, 0, 909, 0, 913, + 141, 147, 0, 0, 915, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 918, 143, 144, 149, 917, + 555, 0, 549, 550, 551, 552, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 146, 0, 0, 0, 0, + 352, 0, 0, 0, 768, 0, 0, 0, 0, 0, + 160, 0, 918, 0, 0, 0, 0, 0, 557, 558, + 559, 560, 357, 0, 554, 0, 0, 0, 561, 562, + 553, 0, 0, 0, 0, 982, 981, 980, 0, 975, + 974, 973, 972, 0, 970, 971, 105, 0, 979, 978, + 977, 976, 0, 622, 0, 969, 967, 0, 0, 0, + 0, 0, 0, 0, 0, 880, 0, 881, 882, 883, + 884, 899, 900, 901, 916, 902, 903, 904, 905, 906, + 907, 908, 910, 914, 0, 0, 0, 919, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 880, 0, 881, 882, 883, 884, 899, 900, + 901, 916, 902, 903, 904, 905, 906, 907, 908, 910, + 914, 968, 88, 87, 919, 89, 0, 0, 0, 0, + 155, 0, 556, 175, 0, 0, 0, 151, 148, 163, + 161, 170, 0, 164, 165, 166, 167, 0, 168, 169, + 0, 0, 171, 172, 173, 174, 146, 0, 177, 142, + 162, 352, 0, 0, 0, 353, 0, 0, 141, 147, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 357, 143, 144, 149, 0, 0, 175, + 0, 0, 0, 0, 0, 163, 161, 170, 0, 164, + 165, 166, 167, 0, 168, 169, 0, 0, 171, 172, + 173, 174, 0, 0, 622, 1261, 162, 0, 160, 159, + 0, 0, 88, 87, 0, 89, 0, 0, 0, 0, + 155, 0, 0, 175, 0, 0, 0, 151, 148, 163, + 161, 170, 0, 164, 165, 166, 167, 0, 168, 169, + 0, 0, 171, 172, 173, 174, 0, 0, 177, 142, + 162, 0, 0, 1262, 0, 0, 0, 0, 141, 147, + 0, 0, 0, 0, 156, 157, 158, 0, 0, 0, + 0, 1260, 0, 0, 143, 144, 149, 0, 0, 0, + 0, 0, 0, 0, 297, 198, 146, 0, 0, 0, + 199, 352, 200, 0, 0, 353, 0, 0, 201, 0, + 0, 63, 0, 0, 0, 0, 0, 0, 160, 0, + 354, 355, 356, 357, 0, 195, 284, 0, 279, 280, + 281, 282, 283, 0, 640, 641, 0, 287, 0, 0, + 196, 0, 0, 0, 0, 0, 285, 0, 0, 0, + 295, 0, 286, 0, 622, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 288, 289, 290, 291, 292, 293, + 294, 298, 0, 0, 156, 157, 158, 296, 0, 0, + 0, 0, 0, 88, 87, 0, 89, 0, 0, 0, + 146, 155, 0, 0, 175, 0, 0, 0, 151, 148, + 163, 161, 170, 0, 164, 165, 166, 167, 0, 168, + 169, 0, 0, 171, 172, 173, 174, 0, 0, 177, + 142, 162, 0, 0, 0, 0, 0, 0, 0, 141, + 147, 0, 0, 0, 348, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 143, 144, 149, 274, 1217, + 1216, 1211, 0, 1210, 1209, 1208, 1207, 146, 1205, 1206, + 105, 0, 1215, 1214, 1213, 1212, 0, 0, 0, 0, + 0, 1204, 0, 0, 0, 0, 0, 0, 0, 160, + 0, 354, 355, 356, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 640, 641, 982, 981, 980, + 0, 975, 974, 973, 972, 0, 970, 971, 105, 0, + 979, 978, 977, 976, 0, 274, 0, 969, 967, 0, + 0, 0, 0, 88, 87, 0, 89, 0, 0, 0, + 0, 155, 0, 0, 175, 156, 157, 158, 151, 148, + 163, 161, 170, 0, 164, 165, 166, 167, 0, 168, + 169, 0, 0, 171, 172, 173, 174, 146, 0, 177, + 142, 162, 0, 0, 0, 0, 0, 0, 0, 141, + 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 968, 0, 143, 144, 149, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 274, 0, 88, 87, 160, + 89, 354, 355, 356, 146, 155, 0, 0, 175, 0, + 0, 0, 151, 148, 163, 161, 170, 0, 164, 165, + 166, 167, 0, 168, 169, 0, 0, 171, 172, 173, + 174, 0, 0, 177, 142, 162, 0, 0, 0, 0, + 0, 0, 0, 141, 147, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 156, 157, 158, 0, 143, + 144, 149, 274, 805, 88, 87, 0, 89, 0, 0, + 0, 0, 155, 0, 0, 175, 0, 0, 0, 151, + 148, 163, 161, 170, 0, 164, 165, 166, 167, 0, + 168, 169, 0, 160, 171, 172, 173, 174, 146, 0, + 177, 142, 162, 0, 0, 0, 0, 804, 0, 0, + 141, 147, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 143, 144, 149, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, + 157, 158, 0, 0, 0, 0, 274, 0, 0, 0, + 160, 159, 0, 0, 88, 87, 146, 89, 0, 0, + 0, 0, 155, 0, 0, 175, 0, 0, 0, 151, + 148, 163, 161, 170, 0, 164, 165, 166, 167, 0, + 168, 169, 0, 0, 171, 172, 173, 174, 0, 0, + 177, 142, 162, 0, 0, 0, 0, 0, 0, 0, + 141, 147, 0, 0, 0, 0, 156, 157, 158, 0, + 0, 0, 0, 0, 274, 0, 143, 144, 149, 0, + 0, 88, 87, 0, 89, 0, 0, 0, 0, 155, + 0, 0, 175, 0, 0, 0, 151, 148, 163, 161, + 170, 0, 164, 165, 166, 167, 0, 168, 169, 0, + 160, 171, 172, 173, 174, 0, 0, 177, 142, 162, + 0, 0, 0, 0, 0, 0, 0, 759, 147, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 143, 144, 149, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 146, 0, 0, 0, 0, 156, 157, 158, 0, + 0, 0, 0, 0, 0, 88, 87, 160, 89, 0, + 0, 0, 0, 155, 0, 0, 175, 0, 0, 0, + 151, 148, 163, 161, 170, 0, 164, 165, 166, 167, + 0, 168, 169, 0, 0, 171, 172, 173, 174, 0, + 0, 177, 142, 162, 0, 0, 146, 0, 0, 0, + 0, 141, 147, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 156, 157, 158, 0, 143, 144, 149, + 0, 0, 0, 88, 87, 0, 89, 0, 0, 0, + 0, 155, 0, 0, 175, 0, 0, 0, 151, 148, + 163, 161, 170, 0, 164, 165, 166, 167, 0, 168, + 169, 652, 146, 171, 172, 173, 174, 0, 0, 177, + 142, 162, 88, 87, 0, 89, 0, 0, 0, 141, + 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 143, 144, 149, 0, 0, + 0, 0, 0, 0, 0, 0, 409, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 146, 156, 157, 158, + 988, 0, 0, 0, 0, 0, 0, 0, 0, 458, + 0, 0, 0, 0, 391, 0, 0, 0, 407, 0, + 0, 389, 390, 0, 0, 0, 393, 394, 405, 395, + 396, 397, 398, 399, 400, 401, 402, 392, 0, 0, + 0, 0, 0, 406, 0, 0, 404, 0, 0, 0, + 146, 0, 0, 403, 722, 0, 0, 0, 0, 0, + 0, 0, 408, 0, 0, 156, 157, 158, 488, 175, + 489, 0, 0, 151, 148, 163, 161, 170, 0, 164, + 165, 166, 167, 0, 168, 169, 0, 0, 171, 172, + 173, 174, 0, 0, 177, 142, 162, 0, 0, 0, + 0, 0, 0, 0, 141, 147, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 143, 144, 149, 380, 175, 381, 0, 0, 151, 148, + 163, 161, 170, 0, 164, 165, 166, 167, 0, 168, + 169, 0, 0, 171, 172, 173, 174, 0, 0, 0, + 142, 162, 0, 0, 160, 0, 0, 0, 0, 141, + 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 143, 144, 149, 0, 0, + 175, 0, 0, 0, 151, 148, 163, 161, 170, 0, + 164, 165, 166, 167, 0, 168, 169, 0, 0, 171, + 172, 173, 174, 0, 0, 0, 142, 162, 0, 160, + 0, 0, 0, 0, 0, 141, 147, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 143, 144, 149, 175, 0, 0, 0, 151, 148, + 163, 161, 170, 0, 164, 165, 166, 167, 0, 168, + 169, 0, 0, 171, 172, 173, 174, 0, 0, 0, + 142, 162, 0, 0, 0, 160, 0, 0, 0, 141, + 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 143, 144, 149, 175, 0, + 0, 0, 151, 148, 163, 161, 170, 0, 164, 165, + 166, 167, 0, 168, 169, 0, 0, 171, 172, 173, + 174, 0, 0, 0, 142, 162, 0, 0, 0, 160, + 0, 0, 0, 141, 147, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, + 144, 149, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 160 +}; + +YYSTATIC YYCONST short YYFARDATA YYPACT[] = { +-1000, 1543,-1000, 566, 501,-1000,-1000,-1000,-1000,-1000, +-1000,-1000, 491, 426, 425, 405,-1000,-1000,-1000, 28, + 28, -454, 39, 39,-1000,-1000,-1000, 396,-1000, -129, + 411,-1000, 890, 743, 7, 886, 28, -366, -369,-1000, + -171, 777, 7, 777,-1000,-1000,-1000, 90, 2292, 411, + 411, 411, 411,-1000,-1000, 124,-1000,-1000,-1000, -162, + 1048,-1000,-1000, 1046, 7, 7,-1000,-1000, 1403,-1000, +-1000,-1000,-1000,-1000,-1000,-1000, 28, -139,-1000,-1000, +-1000,-1000, 359, -132, 2954, 1220,-1000,-1000,-1000,-1000, + 2430,-1000, 28,-1000, 1317,-1000, 1308, 1644, 7, 1233, + 1212, 1204, 1193, 1191, 1186, 1642, 1486, 18,-1000, 28, + 600, 662,-1000,-1000, 95, 1220, 411, 2954,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000, 1484, 166, 1303, 448, -244, -245, -246, + -247, 359,-1000, -118, 359, 661, 368,-1000,-1000, -76, +-1000, 3547, 186, 1189,-1000,-1000,-1000,-1000,-1000, 3383, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, + 435,-1000,-1000,-1000,-1000,-1000, 1220, 1641, 326, 1220, + 1220, 1220,-1000, 3222, 79,-1000,-1000, 1639, 1047, 2854, +-1000, 3547,-1000,-1000,-1000, 216, 216,-1000, 1638,-1000, +-1000, 29, 1483, 1482, 1779, 1432,-1000,-1000, 28,-1000, + 28, 77,-1000,-1000,-1000,-1000, 1170,-1000,-1000,-1000, +-1000,-1000, 885, 28, 3183,-1000, 67, -94,-1000,-1000, + 424, 28, 39, 228, 7, 424, 661, 3328, 2954, -95, + 216, 2854, 1637,-1000, 282,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, + 826, 71, 1114, 857,-1000, 87,-1000, 298, 359,-1000, +-1000, 2954,-1000,-1000, 181, 899, 216, 411,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000, 1631, 1630, 2084, + 877, 275, 1301, 1629, 79, 1481, 0,-1000, 28, 0, +-1000, 39,-1000, 28,-1000, 28,-1000, 28,-1000,-1000, +-1000,-1000, 873,-1000, 28, 28,-1000, 1220,-1000,-1000, +-1000, -387,-1000,-1000,-1000,-1000,-1000, 662, 488, 94, +-1000,-1000, 1220, 1022,-1000, 1292, 581, 1628,-1000, 82, + 411, 115,-1000,-1000,-1000, 1627, 1625, 3547, 411, 411, + 411, 411,-1000, 359,-1000,-1000, 3547, 604,-1000, 1220, +-1000, -90,-1000, 899, 838, 861, 860, 411, 411, 2693, +-1000,-1000,-1000,-1000,-1000,-1000, 28, 1292, 1081,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000, 362,-1000,-1000,-1000, 1624, + 1045,-1000, 673, 1479,-1000,-1000, 2553,-1000,-1000, 28, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, 386, + 375, 373,-1000,-1000,-1000,-1000,-1000, 28, 28, 332, + 3115,-1000,-1000, -214, -217,-1000,-1000,-1000,-1000,-1000, +-1000,-1000, -65, 1622,-1000, 28, 1165, 1, 216, 813, + 28,-1000, -94, 63, 63, 63, 63, 2954, 282,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, + 1621, 1620, 1478,-1000,-1000,-1000, 2693,-1000,-1000,-1000, +-1000, 1292, 1619, 7, 3547,-1000, 424, 1320,-1000, -136, + -138,-1000,-1000, -356,-1000,-1000, 7, 354, 391, 7, +-1000,-1000, 1043,-1000,-1000, 7,-1000, 7,-1000, 1039, + 1026,-1000,-1000, 411, -177, -371, 1618,-1000,-1000,-1000, +-1000, 411, -380,-1000,-1000, -350,-1000,-1000,-1000, 1300, +-1000, 831, 411, 3547, 1220, 3493, 28, 53, 1187,-1000, +-1000,-1000,-1000,-1000,-1000,-1000, 1617,-1000,-1000,-1000, +-1000,-1000,-1000, 1614,-1000,-1000, 1317, 53, 1473,-1000, + 1472, 859, 1464, 1463, 1461, 1459, 1457,-1000, 468, 1148, +-1000, 86, 1220,-1000,-1000,-1000, 52, 411, 53, 330, + 108, 3021,-1000,-1000, 1296, 1220,-1000, 654,-1000,-1000, + -63, 2954, 2954, 989, 1295, 899, 1220, 1220, 1220, 1220, +-1000, 2392,-1000, 1220,-1000, 411, 411, 411, 782, 1220, + -7, 1220, 147, 1456,-1000, 128,-1000,-1000,-1000,-1000, +-1000,-1000, 28,-1000, 1292,-1000,-1000, 661, -16, 1051, +-1000,-1000, 1220, 1455, 1226,-1000,-1000,-1000,-1000,-1000, +-1000, -17, 216, 734, 2954, 2787, 59, 488, 1451, 1294, +-1000,-1000, 3493, -65, 854, 28, -22, 3547, 28, 1220, + 852,-1000,-1000,-1000, 424,-1000,-1000,-1000,-1000,-1000, +-1000,-1000, 28, 39,-1000, -18, 1220, 53, 1449, 836, + 1447, 1293, 1279,-1000, 79, 28, 28, 1446, 1132,-1000, +-1000, 1292, 1600, 1438, 1599, 1434, 1433, 1598, 1596, 1220, + 411,-1000, 411, 28, 131, 411, 7, 2954, 411, 753, + 902, 192, -157, 1428, 96, 1824, 120, 2016, 28,-1000, + 1291,-1000, 883,-1000, 883, 883, 883, 883, 883, -120, +-1000, 28, 28, 411,-1000,-1000,-1000,-1000,-1000,-1000, + 1220, 1423, 1278, 980,-1000,-1000, 263, 1260, 1019, 199, + 78,-1000, -42, 28, 1420, 1419,-1000, 3547, 1595, 1189, + 1189, 1189, 411, 411,-1000, 958, 270, 128,-1000,-1000, +-1000,-1000,-1000, 1418, 232, 1635, 1007, -22, 1594, 1593, + 3439,-1000,-1000, 1685, 56, 666, 973, -22, 3547, 28, + 1220, -337, 411, 1220,-1000,-1000, 3547,-1000,-1000, 1220, +-1000, -65, 192, 1417, -266,-1000,-1000, 1220, 2693, 850, + 948, -144, -147, 1416, 1415, 411, 1288,-1000, -65,-1000, + 424, 424,-1000,-1000,-1000,-1000, 354,-1000,-1000,-1000, +-1000,-1000,-1000,-1000, 1189, 1220, 1414, 28, 1220, 1412, +-1000, 411, -22, 1579, 845, 843, 839, 835,-1000, 53, + 1715,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000, 1131, 1129, 1578, 948, 79, 1410, 887, 7, + 1577, -400, -78,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000, 724,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000, 1576, 1576,-1000, 1576, + 1750,-1000,-1000, -412,-1000, -402,-1000,-1000, -417,-1000, +-1000,-1000, 1408,-1000,-1000,-1000,-1000,-1000,-1000,-1000, + 79,-1000,-1000,-1000,-1000,-1000, 61, 432, 1220,-1000, + 53, 630, 224,-1000, 3021, 312, 1002,-1000,-1000,-1000, +-1000,-1000, 899, -65, 1189, 1220,-1000, 411, 1219, 2954, +-1000,-1000,-1000, 200,-1000,-1000,-1000, 1158, 1157, 1144, + 1141, 1139, 1136, 1100, 1063, 1055, 1038, 1035, 1014, 1005, + 366, 997, 994, 7, 637, 1051, -65, -65, 28, 934, +-1000,-1000,-1000, 661, 661, 661, 661,-1000,-1000,-1000, +-1000,-1000,-1000, 661, 661, 661,-1000,-1000,-1000,-1000, +-1000, -434, 2693, 828,-1000, 661, 1220, 1187,-1000, 79, +-1000, 79, -23,-1000,-1000, 2602, 79, 28,-1000,-1000, + 1220,-1000, 1405,-1000,-1000, 1128,-1000,-1000, -301, 1050, + 2016,-1000,-1000,-1000,-1000, 1292,-1000, -254, -257, 28, +-1000,-1000,-1000,-1000, 352, 169, 53, 882, 745,-1000, +-1000,-1000,-1000,-1000,-1000,-1000, -423,-1000,-1000, 37, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000, 475,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, 28,-1000, +-1000,-1000,-1000, 1575, 1292, 1574,-1000,-1000,-1000,-1000, +-1000, 274, 1401, 1219,-1000, 128, 1400, 1239,-1000, 2348, +-1000,-1000,-1000, -56, 28, 829, 28, 2650, 28, 314, + 28, 795, 28, 39, 28, 28, 28, 28, 28, 28, + 28, 39, 28, 28, 28, 28, 28, 28, 28, 978, + 962, 947, 931, 28, 28, -160, 28, 1399, 1292,-1000, +-1000, 1572, 1571, 1395, 1392, 825,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000, 216, -27,-1000, 1240,-1000,-1000, + -22,-1000,-1000, 1292,-1000, 1570, 1569, 1568, 1567, 1566, + 1557, 356, 1556, 1554, 1552, 1542, 1538, 1537,-1000,-1000, +-1000, 354,-1000, 1535, 1390, 1386,-1000,-1000,-1000,-1000, + 1388,-1000, 710, 28,-1000, 1267, 28, 28, 974, 53, + 824,-1000,-1000,-1000,-1000,-1000,-1000,-1000, 60, 28, + 381, 241,-1000,-1000,-1000,-1000,-1000, 2954, 205,-1000, +-1000,-1000, 1011, 1387, 1385, 822, 49, 1380, 1377, 821, + 1375, 819, 1374, 1373, 814, 1368, 1367, 812, 1366, 808, + 1365, 807, 1364, 794, 1363, 793, 1362, 776, 1361, 754, + 1360, 742, 1359, 741, 39, 28, 28, 28, 28, 28, + 28, 28, 1358, 730, 1348, 727,-1000, 174, -65, -65, +-1000,-1000, 923, 3547, -22, -65, 1012, 1534, 1532, 1531, + 1530, 1113, -65,-1000,-1000,-1000,-1000, 28, 721, 53, + 705, 700, 28, 1292,-1000,-1000, 1347, 1090, 1086, 1049, + 1344,-1000, 36,-1000, 953, 699, 45,-1000,-1000,-1000, + 1529, 1343,-1000,-1000, 1528,-1000, 1525,-1000,-1000, 1524, +-1000,-1000, 1521,-1000, 1520,-1000, 1519,-1000, 1518,-1000, + 1512,-1000, 1511,-1000, 1509,-1000, 1504,-1000, 1503, 1342, + 675, 1341, 668, 1340, 647, 1337, 613,-1000, 1502,-1000, + 1501,-1000, 1336, 1335,-1000, 2693, 1012, 1334, 1499,-1000, + 398, 354, 1333, 606,-1000, 1247,-1000, 2053, 1332,-1000, + 28, 28, 28,-1000,-1000, 2650,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000, 1498,-1000, 1497,-1000, 1496,-1000, 1495, +-1000,-1000,-1000,-1000, -30, 1494, 948, -65,-1000,-1000, +-1000, 53,-1000, 887,-1000, 1331, 1329, 1328,-1000, 164, + 704, 2188, 257, 616, 416, 541, 518, 466, 322, 460, + 458, 446,-1000,-1000,-1000,-1000, 430, 153, -22, -65, +-1000, 1326, 1207, 1265,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000, 38,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000, 319, 378, 333, 272,-1000,-1000, +-1000, 1493, 1325,-1000,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, 1490, 53, +-1000,-1000,-1000,-1000,-1000, -65, -435, 28, 1227, 1316, + -199, 1315,-1000,-1000, 216,-1000, 3547, 2693, -45, -22, + 1012, 1489, -65, 1311,-1000 +}; + +YYSTATIC YYCONST short YYFARDATA YYPGO[] = { + 0, 53, 57, 6, 1900, 43, 40, 29, 1899, 0, + 1898, 1897, 1896, 195, 50, 1895, 1893, 2, 1892, 48, + 38, 1, 27, 30, 31, 4, 1890, 45, 22, 59, + 1889, 136, 39, 9, 25, 7, 13, 1888, 41, 1887, + 14, 26, 1884, 1883, 5, 3, 8, 10, 1882, 1877, + 1876, 1875, 32, 33, 70, 1873, 1872, 1871, 1870, 12, + 1869, 1868, 11, 1867, 35, 1866, 18, 36, 16, 24, + 42, 23, 458, 65, 1276, 52, 127, 1864, 1863, 1848, + 1847, 1846, 1845, 19, 34, 1844, 1353, 1837, 1836, 28, + 784, 119, 1835, 47, 1245, 1834, 1831, 1830, 1829, 1828, + 1825, 1824, 1817, 1815, 1813, 1812, 1811, 1796, 1795, 1033, + 1794, 64, 62, 1793, 58, 150, 56, 76, 1790, 1789, + 49, 1788, 1787, 1786, 1785, 1784, 1783, 61, 1782, 1781, + 1780, 66, 114, 44, 1778, 15, 284, 1775, 1771, 1770, + 1758, 1757, 1755, 1754, 1753, 1752, 1751, 1748, 1747, 770, + 1746, 1745, 1743, 1742, 1741, 1734, 1713, 1712, 60, 1711, + 1710, 113, 1709, 1708, 1707, 98, 1706, 1704, 1703, 1702, + 1701, 1700, 1699, 69, 1696, 67, 1698, 63, 1695, 484, + 1693, 1692, 1688, 1686, 1685, 1473 +}; +YYSTATIC YYCONST yyr_t YYFARDATA YYR1[]={ + + 0, 109, 109, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 110, 110, 110, 136, + 136, 36, 36, 133, 133, 133, 2, 2, 1, 1, + 1, 9, 24, 24, 23, 23, 23, 134, 134, 134, + 134, 134, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 93, 93, 93, 93, 94, 94, 94, 94, 10, + 11, 73, 72, 72, 59, 61, 61, 61, 62, 62, + 62, 65, 65, 132, 132, 132, 60, 60, 60, 60, + 60, 60, 130, 130, 130, 119, 12, 12, 12, 12, + 12, 12, 118, 137, 113, 138, 139, 111, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 140, 140, 141, 141, 112, + 112, 142, 142, 56, 56, 57, 57, 69, 69, 18, + 18, 18, 18, 18, 19, 19, 68, 68, 67, 67, + 58, 21, 21, 22, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 116, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 4, 4, 35, 35, 16, 16, 75, 75, 75, 75, + 75, 75, 75, 7, 7, 7, 7, 8, 8, 8, + 8, 8, 8, 8, 76, 74, 74, 74, 74, 74, + 74, 144, 144, 81, 81, 81, 145, 145, 150, 150, + 150, 150, 150, 150, 150, 150, 146, 82, 82, 82, + 147, 147, 151, 151, 151, 151, 151, 151, 151, 152, + 38, 38, 34, 34, 153, 114, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 3, 3, 3, 13, 13, + 13, 13, 13, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 154, 115, + 115, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 155, 155, 155, 155, 155, 158, 159, 156, 161, 161, + 160, 160, 160, 163, 162, 162, 162, 162, 166, 166, + 166, 169, 164, 167, 168, 165, 165, 165, 117, 170, + 170, 172, 172, 172, 171, 171, 173, 173, 14, 14, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 175, 31, 31, 32, 32, 39, + 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 42, 42, + 42, 43, 43, 43, 47, 47, 46, 46, 45, 45, + 44, 44, 48, 48, 49, 49, 49, 50, 50, 50, + 50, 51, 51, 149, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 6, 6, 6, 6, 6, 53, 53, 54, 54, + 55, 55, 25, 25, 26, 26, 27, 27, 27, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 5, + 5, 71, 71, 71, 71, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 20, 20, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 30, 30, 29, 29, 29, 29, 29, + 131, 131, 131, 131, 131, 131, 64, 64, 64, 63, + 63, 87, 87, 84, 84, 85, 17, 17, 37, 37, + 37, 37, 37, 37, 37, 37, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 176, 176, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 121, 121, 88, 88, 89, 89, + 177, 122, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 123, 123, 178, 178, 178, 66, 66, 179, + 179, 179, 179, 179, 179, 180, 182, 181, 124, 124, + 125, 125, 183, 183, 183, 183, 126, 148, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 127, 127, + 184, 184, 184, 184, 184, 184, 184, 128, 128, 92, + 92, 92, 129, 129, 185, 185, 185, 185 }; +YYSTATIC YYCONST yyr_t YYFARDATA YYR2[]={ + + 0, 0, 2, 4, 4, 3, 1, 1, 1, 1, + 1, 1, 4, 4, 4, 4, 1, 1, 1, 2, + 2, 3, 2, 2, 1, 1, 1, 4, 1, 0, + 2, 1, 3, 2, 4, 6, 1, 1, 1, 1, + 3, 1, 1, 1, 1, 4, 4, 4, 4, 4, + 4, 4, 2, 3, 2, 2, 2, 1, 1, 2, + 1, 2, 4, 6, 3, 5, 7, 9, 3, 4, + 7, 1, 1, 1, 2, 0, 2, 2, 0, 6, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, + 2, 3, 1, 2, 3, 7, 0, 2, 2, 2, + 2, 2, 3, 3, 2, 1, 4, 3, 0, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, + 3, 2, 2, 2, 5, 0, 2, 0, 2, 0, + 2, 3, 1, 0, 1, 1, 3, 0, 3, 1, + 1, 1, 1, 1, 0, 2, 4, 3, 0, 2, + 3, 0, 1, 5, 3, 4, 4, 4, 1, 1, + 1, 1, 1, 2, 2, 4, 13, 22, 1, 1, + 5, 3, 4, 7, 0, 2, 2, 2, 2, 2, + 2, 2, 5, 2, 2, 2, 2, 2, 2, 5, + 0, 2, 0, 2, 0, 3, 9, 9, 7, 7, + 1, 1, 1, 2, 2, 1, 4, 0, 1, 1, + 2, 2, 2, 2, 4, 2, 5, 3, 2, 2, + 1, 4, 3, 0, 2, 2, 0, 2, 2, 2, + 2, 2, 1, 1, 1, 1, 9, 0, 2, 2, + 0, 2, 2, 2, 2, 1, 1, 1, 1, 1, + 0, 4, 1, 3, 1, 13, 0, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 5, 8, 6, 5, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 5, 1, 1, 1, 0, 4, + 4, 4, 4, 0, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 5, 1, 0, + 2, 2, 1, 2, 4, 5, 1, 1, 1, 1, + 2, 1, 1, 1, 1, 1, 4, 6, 4, 4, + 11, 1, 5, 3, 5, 3, 1, 2, 2, 1, + 2, 4, 4, 1, 2, 2, 2, 2, 2, 2, + 2, 1, 2, 1, 1, 1, 4, 4, 2, 4, + 2, 0, 1, 1, 3, 1, 3, 1, 0, 3, + 5, 4, 3, 5, 5, 5, 5, 5, 5, 2, + 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, + 4, 4, 4, 5, 5, 5, 5, 4, 4, 4, + 4, 4, 4, 3, 2, 0, 1, 1, 2, 1, + 1, 1, 1, 4, 4, 5, 4, 4, 4, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, + 8, 8, 8, 7, 7, 7, 7, 7, 0, 2, + 2, 0, 2, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 2, 0, 2, 3, + 2, 0, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, + 2, 2, 2, 2, 2, 3, 2, 2, 2, 5, + 3, 2, 2, 2, 2, 2, 5, 4, 6, 2, + 4, 0, 3, 3, 1, 1, 0, 3, 0, 1, + 1, 3, 0, 1, 1, 3, 1, 3, 4, 4, + 4, 4, 5, 1, 1, 1, 1, 1, 1, 1, + 3, 1, 3, 4, 1, 0, 10, 6, 5, 6, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, + 2, 3, 4, 6, 5, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 1, 2, 2, 4, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, + 0, 5, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, + 1, 1, 1, 3, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 3, 2, 3, 4, 2, 2, 2, + 5, 5, 7, 4, 3, 2, 3, 2, 1, 1, + 2, 3, 2, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, + 1, 1, 1, 1, 3, 0, 1, 1, 3, 2, + 6, 7, 3, 3, 3, 6, 0, 1, 3, 5, + 6, 4, 4, 1, 3, 3, 1, 1, 1, 1, + 4, 1, 6, 6, 6, 4, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 3, 2, 5, 4, 7, 6, 7, + 6, 9, 8, 3, 8, 4, 0, 2, 0, 1, + 3, 3, 0, 2, 2, 2, 3, 2, 2, 2, + 2, 2, 0, 2, 3, 1, 1, 1, 1, 3, + 8, 2, 3, 1, 1, 3, 3, 3, 4, 6, + 0, 2, 3, 1, 3, 1, 4, 3, 0, 2, + 2, 2, 3, 3, 3, 3, 3, 3, 0, 2, + 2, 3, 3, 4, 2, 1, 1, 3, 5, 0, + 2, 2, 0, 2, 4, 3, 1, 1 }; +YYSTATIC YYCONST short YYFARDATA YYCHK[]={ + +-1000,-109,-110,-111,-113,-114,-116,-117,-118,-119, +-120,-121,-122,-124,-126,-128,-130,-131,-132, 524, + 525, 459, 527, 528,-133,-134,-135, 531, 532,-139, + 408,-152, 410,-170,-137, 454,-176, 462, 407, 469, + 470, 429, -87, 430, -93, -94, 273, 448, 529, 533, + 534, 535, 536, 537, 538, 539, 59,-138, 409, 411, + 453, 446, 447, 449, -10, -11, 123, 123,-115, 123, + 123, 123, 123, -9, 264, -9, 526, -88, -24, 265, + 264, -24, 123,-140, 314, -1, -2, 261, 260, 263, + -78, -16, 91,-171, 123,-174, 278, 38,-175, 286, + 287, 284, 283, 282, 281, 288, -31, -32, 267, 91, + -9, -90, 468, 468, -92, -1, 468, -86, 431, 432, + 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, -31, -86, 263, -28, -70, -74, -93, + -94, 306, 297, 322, 323,-149, 33, 307, 276, 324, + -52, 275, 91, -5, -76, 268, 412, 413, 414, 357, + 356, 278, 298, 277, 281, 282, 283, 284, 286, 287, + 279, 290, 291, 292, 293, 271, -1, 296, -1, -1, + -1, -1, 262, -77,-172, 318, 378, 61, -73, 40, + -75, -7, -76, 269, 272, 325, 340, -8, 295, 300, + 302, 308, -31, -31,-112,-109, 125,-155, 415,-156, + 417,-154, 419, 420,-117,-157, -2,-131,-120,-133, +-132,-135, 471, 457, 507,-158, 506,-160, 418, -95, + -96, -97, -98, -99,-108,-100,-101,-102,-103,-104, +-105,-106,-107,-159,-163, 394, 395, 396, 397, 398, + 399, 400, 401, 402, 403, 404, 405, 406, 123, 416, +-123,-125,-127,-129, -9, -1, 460,-136, -70, -76, +-141, 315, -71, -70, 91, -28,-149, 46, -7, 328, + 329, 330, 331, 332, 326, 346, 352, 337, 364, 365, + 366, 367, 368, 369, 370, 350, 377, 294, 371, -79, + -9,-173,-174, 42, 40, -31, 40, -14, 91, 40, + -14, 40, -14, 40, -14, 40, -14, 40, -14, 40, + 41, 267, -9, 263, 58, 44, 262, -1, 353, 354, + 355, 472, 378, 474, 475, 476, 477, -90, -91, -1, + 329, 330, -1, -71, 41, -36, 61, 288, 262, 44, + 389, 91, 38, 42, 358, 359, 360, 60, 389, 389, + 389, 389, -70, 306, -70, -75, -7, 33, -9, -1, + 280, 279, 289, -28, -1, -76, 42, 470, 47, -28, + 270, 272, 281, 282, 283, 284, 40, -36, -1, 329, + 330, 322, 345, 334, 335, 337, 338, 339, 340, 341, + 342, 343, 344, 361, 354, 336, 351, 326, 370, 294, + -2, 40, 61, -72, -71, -74, -28, -7, -7, 40, + 301, 303, 304, 305, 41, 41, 125,-143,-114,-111, +-144,-146,-116,-117,-131,-120,-132, 451, 452,-148, + 507,-133,-135, 506, 321, 421, 426, 471, 407, 125, + -9, -9, 40, 450, 58, 91, -9, -71, 356, 363, + 91,-161,-162,-164,-166,-167,-168, 311,-169, 309, + 313, 312, -9, -2, -9, -24, 40, -23, -24, 266, + 286, 287, -31, -9, -2, -75, -28, -76, 270, 272, + -71, -36, 341,-175, -7, -72, 40,-115,-158, -2, + -9, 125,-178, 461,-131,-179,-180, 466, 467,-181, +-132,-135, 463, 125,-183,-177,-179,-182, 338, 461, + 464, 125,-184, 459, 407, 462, 296,-132,-135, 125, +-185, 459, 462,-132,-135, -89, 419, 125,-136,-142, + -71, -1, 470, -7, -1, -13, 40, 40, -28, 328, + 329, 330, 331, 376, 370, 326, 478, 364, 365, 366, + 367, 374, 375, 294, 93, 125, 44, 40, -2, 41, + -23, -9, -23, -24, -9, -9, -9, 93, -9, -9, + 473, -1, -1, 330, 329, 327, 336, 389, 40, 61, + 43, 123, 40, 40, 263, -1, 93, -30, -29, 275, + -9, 40, 40, -54, -55, -28, -1, -1, -1, -1, + -70, -28, -9, -1, 280, 93, 93, 93, -1, -1, + -71, -1, 91, -9, -69, 60, 329, 330, 331, 364, + 365, 366, 40, 61, -36, 123, 40, 41, -71, -3, + 372, 373, -1, -9,-115, 123, 123, 123, -9, -9, + 123, -71, 356, 363, 363, -81, -82, -91, -25, -26, + -27, 275, -13, 40, -9, 58, 274, -7, 91, -1, + -9,-161,-165,-158, 310,-165,-165,-165, -71,-158, + -2, -9, 40, 40, 41, -71, -1, 40, -31, -28, + -6, -2, -9, 125, 316, 316, 465, -31, -66, -9, + 42, -36, 61, -31, 61, -31, -31, 61, 61, -1, + 468, -9, 468, 40, -1, 468,-177, 44, 93, -1, + -28, -28, 91, -9, -36, -83, -1, 40, 40,-173, + -36, 41, 41, 93, 41, 41, 41, 41, 41, -12, + 263, 44, 58, 389, 329, 330, 331, 364, 365, 366, + -1, -84, -85, -36, 123, 262, -64, -63, -71, 306, + 44, 93, 44, 275, -71, -71, 62, 44, 42, -5, + -5, -5, 93, 274, 41, -68, -19, -18, 43, 45, + 306, 323, 372, -9, -59, -61, -73, 274, -53, -22, + 60, 41, 125,-112,-145,-147,-127, 274, -7, 91, + -1, -71, -71, -1, 370, 326, -7, 370, 326, -1, + 41, 44, -28, -25, 93, -9, -3, -1, -28, -9, + 93, -2, -9, -9, -24, 274, -36, 41, 40, 41, + 44, 44, -2, -9, -9, 41, 58, 40, 41, 40, + 41, 41, 40, 40, -5, -1, -9, 317, -1, -31, + -71, 93, -38, 478, 503, 504, 505, -9, 41, 389, + -83, 41, 386, 341, 342, 343, 387, 388, 301, 303, + 304, 305, 390, 393, 294, -4, 317, -34, -33,-153, + 479, 481, 482, 483, 484, 276, 277, 281, 282, 283, + 284, 286, 287, 257, 279, 290, 291, 292, 293, 485, + 486, 487, 489, 490, 491, 492, 493, 494, 495, 334, + 496, 280, 289, 336, 497, 341, 488, 356, 389, 501, + 271, 123, -9, 41, -14, -14, -14, -14, -14, -14, + 317, 283, 284, 455, 456, 458, -9, -9, -1, 41, + 44, 61, -59, 125, 44, 61, 263, 263, -29, -9, + 41, 41, -28, 40, -5, -1, 62, -58, -1, 40, + -19, 41, 125, -62, -40,-135, -41, 298, 363, 297, + 286, 287, 284, 283, 282, 281, 293, 292, 291, 290, + 279, 278, 277,-175, 61, -3, 40, 40, 91, -54, + 125, 125,-150, 422, 423, 424, 425,-120,-132,-133, +-135, 125,-151, 427, 428, 425,-132,-120,-133,-135, + 125, -3, -28, -9, -93, 449, -1, -28, -27, -38, + 41, 389, -71, 93, -35, 61, 316, 316, 41, 41, + -1, 41, -25, -6, -6, -66, 41, -9, 41, -3, + 40, 93, 93, 93, 93, -36, 41, 58, 58, 40, + -35, -2, 41, 42, 91, -32, 40, 480, 500, 277, + 281, 282, 283, 284, 280, -20, 40, -20, -20, -15, + 509, 482, 483, 276, 277, 281, 282, 283, 284, 286, + 287, 279, 290, 291, 292, 293, 42, 485, 486, 487, + 489, 490, 493, 494, 496, 280, 289, 257, 510, 511, + 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, + 522, 495, 487, 499, 41, -2, 263, 263, 44, -84, + -37, -17, -9, 283, -36, -70, 319, 320, 125, -64, + 123, 61, -25, -1, -67, 44, -56, -57, -71, -65, +-135, 357, 362, 40, 91, 40, 91, 40, 91, 40, + 91, 40, 91, 40, 91, 40, 91, 40, 91, 40, + 91, 40, 91, 40, 91, 40, 91, 40, 91, 284, + 283, 282, 281, 40, 91, 40, 91, -31, -36, 123, + 40, -53, -22, -25, -25, -9, 62, -75, -75, -75, + -75, -75, -75, -75, 508, -71, 93, -1, -2, -2, + 274, -39, -41, -36, 299, 286, 287, 284, 283, 282, + 281, 279, 293, 292, 291, 290, 278, 277, -2, -9, + 41, 58, -89, -69, -34, -83, 391, 392, 391, 392, + -9, 93, -9, 43, 125, -36, 91, 91, 502, 44, + 91, 523, 38, 281, 282, 283, 284, 280, -9, 40, + 40, -62, 123, 41, -67, -68, 41, 44, -60, -52, + 363, 297, 345, 299, 263, -9, 306, -70, 299, -9, + -40, -9, -23, -9, -9, -23, -24, -9, -24, -9, + -9, -9, -9, -9, -9, -9, -24, -9, -9, -9, + -9, -9, -9, -9, 40, 91, 40, 91, 40, 91, + 40, 91, -9, -9, -17, -9, 41, -59, 40, 40, + 41, 41, 93, -7, 274, 40, -3, 284, 283, 282, + 281, -66, 40, 41, 41, 41, 93, 43, -9, 44, + -9, -9, 61, -36, 93, 263, -9, 281, 282, 283, + -9, 125, -62, -71, -1, 91, 306, -70, 41, 41, + 93, 263, 41, 41, 93, 41, 93, 41, 41, 93, + 41, 41, 93, 41, 93, 41, 93, 41, 93, 41, + 93, 41, 93, 41, 93, 41, 93, 41, 93, -24, + -9, -9, -9, -9, -9, -9, -9, 41, 93, 41, + 93, 125, -25, -25, 62, -28, -3, -25, -21, -22, + 60, 58, -25, -9, 93, -36, 93, 93, -9, 41, + 58, 58, 58, 41, 125, 61, 93, 263, 40, 41, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 41, 93, 41, 93, 41, 93, 41, 93, + 40, 40, 41, 41, -71, -21, 41, 40, -66, 41, + 93, 44, 41, -33, 41, -9, -9, -9, -40, -49, + -50, -51, -42, -43, -47, -46, -45, -44, -47, -46, + -45, -44, 40, 40, 40, 40, -45, -48, 274, 40, + -35, -25, -80, -36, 41, 41, 41, 41, 299, 263, + 41, 299, 306, -70, 41, -40, 41, -23, -9, 41, + -23, -24, 41, -24, 41, -9, 41, -9, 41, -9, + 41, 41, 41, 41, -47, -46, -45, -44, 41, 41, + -17, -3, -25, 41, 123, 324, 378, 379, 380, 308, + 381, 382, 383, 384, 333, 347, 348, 349, 294, 44, + 263, 41, 41, 41, 41, 40, 41, 40, -36, -25, + 508, -9, 41, 41, 356, 41, -7, -28, -71, 274, + -3, -21, 40, -25, 41 }; +YYSTATIC YYCONST short YYFARDATA YYDEF[]={ + + 1, -2, 2, 0, 0, 329, 6, 7, 8, 9, + 10, 11, 0, 0, 0, 0, 16, 17, 18, 0, + 0, 766, 0, 0, 24, 25, 26, 0, 28, 135, + 0, 266, 204, 0, 425, 0, 0, 772, 105, 829, + 92, 0, 425, 0, 83, 84, 85, 0, 0, 0, + 0, 0, 0, 57, 58, 0, 60, 108, 259, 381, + 0, 751, 752, 217, 425, 425, 139, 1, 0, 782, + 800, 818, 832, 19, 41, 20, 0, 0, 22, 42, + 43, 23, 29, 137, 0, 104, 38, 39, 36, 37, + 217, 184, 0, 378, 0, 385, 0, 0, 425, 388, + 388, 388, 388, 388, 388, 0, 0, 426, 427, 0, + 754, 0, 772, 808, 0, 93, 0, 0, 736, 737, + 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, + 748, 749, 750, 0, 0, 33, 0, 0, 0, 0, + 0, 0, 662, 0, 0, 217, 0, 678, 679, 0, + 683, 0, 0, 543, 230, 545, 546, 547, 548, 0, + 483, 685, 686, 687, 688, 689, 690, 691, 692, 693, + 0, 698, 699, 700, 701, 702, 549, 0, 52, 54, + 55, 56, 59, 0, 380, 382, 383, 0, 61, 0, + 71, 0, 210, 211, 212, 217, 217, 215, 0, 218, + 219, 0, 0, 0, 0, 0, 5, 330, 0, 332, + 0, 0, 336, 337, 338, 339, 0, 341, 342, 343, + 344, 345, 0, 0, 0, 351, 0, 0, 328, 498, + 0, 0, 0, 0, 425, 0, 217, 0, 0, 0, + 217, 0, 0, 329, 0, 484, 485, 486, 487, 488, + 489, 490, 491, 492, 493, 494, 495, 496, 356, 363, + 0, 0, 0, 0, 21, 768, 767, 0, 29, 544, + 107, 0, 136, 551, 0, 554, 217, 0, 308, 267, + 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, + 278, 279, 280, 281, 282, 283, 284, 0, 0, 0, + 0, 0, 387, 0, 0, 0, 0, 399, 0, 0, + 400, 0, 401, 0, 402, 0, 403, 0, 404, 424, + 102, 428, 0, 753, 0, 0, 763, 771, 773, 774, + 775, 0, 777, 778, 779, 780, 781, 0, 0, 827, + 830, 831, 94, 712, 713, 714, 0, 0, 31, 0, + 0, 705, 667, 668, 669, 0, 0, 528, 0, 0, + 0, 0, 661, 0, 664, 225, 0, 0, 675, 677, + 680, 0, 682, 684, 0, 0, 0, 0, 0, 0, + 228, 229, 694, 695, 696, 697, 0, 53, 147, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 0, 131, 132, 133, 0, + 0, 103, 0, 0, 72, 73, 0, 213, 214, 0, + 220, 221, 222, 223, 64, 68, 3, 140, 329, 0, + 0, 0, 168, 169, 170, 171, 172, 0, 0, 0, + 0, 178, 179, 0, 0, 233, 247, 808, 105, 4, + 331, 333, -2, 0, 340, 0, 0, 0, 217, 0, + 0, 357, 359, 0, 0, 0, 0, 0, 0, 373, + 374, 371, 499, 500, 501, 502, 497, 503, 504, 44, + 0, 0, 0, 506, 507, 508, 0, 511, 512, 513, + 514, 515, 0, 425, 0, 519, 521, 0, 360, 0, + 0, 12, 783, 0, 785, 786, 425, 0, 0, 425, + 793, 794, 0, 13, 801, 425, 803, 425, 805, 0, + 0, 14, 819, 0, 0, 0, 0, 825, 826, 15, + 833, 0, 0, 836, 837, 765, 769, 27, 30, 138, + 142, 0, 0, 0, 40, 0, 0, 289, 0, 185, + 186, 187, 188, 189, 190, 191, 0, 193, 194, 195, + 196, 197, 198, 0, 205, 384, 0, 0, 0, 392, + 0, 0, 0, 0, 0, 0, 0, 96, 756, 0, + 776, 798, 806, 809, 810, 811, 0, 0, 0, 0, + 0, 716, 721, 722, 34, 47, 665, 0, 703, 706, + 707, 0, 0, 0, 529, 530, 48, 49, 50, 51, + 663, 0, 674, 676, 681, 0, 0, 0, 0, 550, + 0, -2, 705, 0, 106, 154, 125, 126, 127, 128, + 129, 130, 0, 379, 62, 75, 69, 217, 0, 526, + 305, 306, -2, 0, 0, 139, 236, 250, 173, 174, + 818, 0, 217, 0, 0, 0, 217, 0, 0, 533, + 534, 536, 0, -2, 0, 0, 0, 0, 0, 353, + 0, 358, 364, 375, 0, 365, 366, 367, 372, 368, + 369, 370, 0, 0, 505, 0, -2, 0, 0, 0, + 0, 524, 525, 355, 0, 0, 0, 0, 0, 787, + 788, 791, 0, 0, 0, 0, 0, 0, 0, 820, + 0, 824, 0, 0, 0, 0, 425, 0, 552, 0, + 0, 260, 0, 0, 289, 0, 200, 555, 0, 386, + 0, 391, 388, 389, 388, 388, 388, 388, 388, 0, + 755, 0, 0, 0, 812, 813, 814, 815, 816, 817, + 828, 0, 723, 0, 75, 32, 0, 717, 0, 0, + 0, 666, 705, 709, 0, 0, 673, 0, 668, 539, + 540, 541, 0, 0, 224, 0, 0, 154, 149, 150, + 151, 152, 153, 0, 0, 78, 65, 0, 0, 0, + 528, 216, 164, 0, 0, 0, 0, 0, 0, 0, + 181, 0, 0, -2, 234, 235, 0, 248, 249, 807, + 334, 308, 260, 0, 346, 348, 349, 307, 0, 0, + 202, 0, 0, 0, 0, 0, 0, 517, -2, 520, + 521, 521, 361, 362, 784, 789, 0, 797, 792, 795, + 802, 804, 770, 796, 821, 822, 0, 0, 835, 0, + 141, 553, 0, 0, 0, 0, 0, 0, 285, 0, + 0, 288, 290, 291, 292, 293, 294, 295, 296, 297, + 298, 299, 0, 0, 0, 202, 0, 0, 262, 0, + 0, 0, 560, 561, 562, 563, 564, 565, 566, 567, + 568, 569, 570, 571, 0, 576, 577, 578, 579, 585, + 586, 587, 588, 589, 590, 591, 610, 610, 594, 610, + 612, 598, 600, 0, 602, 0, 604, 606, 0, 608, + 609, 264, 0, 390, 393, 394, 395, 396, 397, 398, + 0, 97, 98, 99, 100, 101, 758, 760, 799, 710, + 0, 0, 0, 715, 716, 0, 37, 35, 704, 708, + 670, 671, 531, -2, 542, 226, 148, 0, 158, 143, + 155, 134, 63, 74, 76, 77, 432, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 425, 0, 526, -2, -2, 0, 0, + 165, 166, 237, 217, 217, 217, 217, 242, 243, 244, + 245, 167, 251, 217, 217, 217, 255, 256, 257, 258, + 175, 0, 0, 0, 182, 217, 231, 0, 535, 537, + 335, 0, 0, 352, 354, 0, 0, 0, 45, 46, + 509, 516, 0, 522, 523, 0, 823, 834, 768, 147, + 555, 309, 310, 311, 312, 289, 287, 0, 0, 0, + 183, 201, 192, 580, 0, 0, 0, 0, 0, 605, + 572, 573, 574, 575, 599, 592, 0, 593, 595, 596, + 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, + 623, 0, 628, 629, 630, 631, 632, 636, 637, 638, + 639, 640, 641, 642, 643, 644, 646, 647, 648, 649, + 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, + 660, 601, 603, 607, 199, 95, 757, 759, 0, 724, + 725, 728, 729, 0, 731, 0, 726, 727, 711, 718, + 78, 0, 0, 158, 157, 154, 0, 144, 145, 0, + 80, 81, 82, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 66, 75, + 70, 0, 0, 0, 0, 0, 527, 238, 239, 240, + 241, 252, 253, 254, 217, 0, 180, 0, 538, 347, + 0, 203, 429, 430, 431, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 376, 377, + 518, 0, 764, 0, 0, 0, 300, 301, 302, 303, + 0, 581, 0, 0, 263, 0, 0, 0, 0, 0, + 0, 634, 635, 624, 625, 626, 627, 645, 762, 0, + 0, 0, 78, 672, 156, 159, 160, 0, 0, 86, + 87, 88, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 423, 0, -2, -2, + 208, 209, 0, 0, 0, -2, 161, 0, 0, 0, + 0, 0, -2, 261, 286, 304, 582, 0, 0, 0, + 0, 0, 0, 597, 633, 761, 0, 0, 0, 0, + 0, 719, 0, 146, 0, 0, 0, 90, 433, 434, + 0, 0, 436, 437, 0, 438, 0, 405, 407, 0, + 406, 408, 0, 409, 0, 410, 0, 411, 0, 412, + 0, 417, 0, 418, 0, 419, 0, 420, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 421, 0, 422, + 0, 67, 0, 0, 163, 0, 161, 0, 0, 162, + 0, 0, 0, 0, 584, 0, 558, 555, 0, 730, + 0, 0, 0, 735, 720, 0, 91, 89, 474, 435, + 477, 481, 458, 461, 464, 466, 468, 470, 464, 466, + 468, 470, 413, 0, 414, 0, 415, 0, 416, 0, + 468, 472, 206, 207, 0, 0, 202, -2, 790, 313, + 583, 0, 557, 559, 611, 0, 0, 0, 79, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 464, 466, 468, 470, 0, 0, 0, -2, + 246, 0, 0, 0, 732, 733, 734, 455, 475, 476, + 456, 478, 0, 480, 457, 482, 439, 459, 460, 440, + 462, 463, 441, 465, 442, 467, 443, 469, 444, 471, + 445, 446, 447, 448, 0, 0, 0, 0, 453, 454, + 473, 0, 0, 350, 265, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 323, 324, 325, 326, 0, 0, + 479, 449, 450, 451, 452, -2, 0, 0, 0, 0, + 0, 0, 556, 176, 217, 327, 0, 0, 0, 0, + 161, 0, -2, 0, 177 }; +#ifdef YYRECOVER +YYSTATIC YYCONST short yyrecover[] = { +-1000 +}; +#endif + +/* SCCSWHAT( "@(#)yypars.c 3.1 88/11/16 22:00:49 " ) */ +#line 3 "D:\\ProjectK3\\src\\tools\\devdiv\\x86\\yypars.c" +#if ! defined(YYAPI_PACKAGE) +/* +** YYAPI_TOKENNAME : name used for return value of yylex +** YYAPI_TOKENTYPE : type of the token +** YYAPI_TOKENEME(t) : the value of the token that the parser should see +** YYAPI_TOKENNONE : the representation when there is no token +** YYAPI_VALUENAME : the name of the value of the token +** YYAPI_VALUETYPE : the type of the value of the token (if null, then the value is derivable from the token itself) +** YYAPI_VALUEOF(v) : how to get the value of the token. +*/ +#define YYAPI_TOKENNAME yychar +#define YYAPI_TOKENTYPE int +#define YYAPI_TOKENEME(t) (t) +#define YYAPI_TOKENNONE -1 +#define YYAPI_TOKENSTR(t) (sprintf_s(yytokbuf, _countof(yytokbuf), "%d", t), yytokbuf) +#define YYAPI_VALUENAME yylval +#define YYAPI_VALUETYPE YYSTYPE +#define YYAPI_VALUEOF(v) (v) +#endif +#if ! defined(YYAPI_CALLAFTERYYLEX) +#define YYAPI_CALLAFTERYYLEX +#endif + +# define YYFLAG -1000 +# define YYERROR goto yyerrlab +# define YYACCEPT return(0) +# define YYABORT return(1) + +#ifdef YYDEBUG /* RRR - 10/9/85 */ +char yytokbuf[20]; +# ifndef YYDBFLG +# define YYDBFLG (yydebug) +# endif +# define yyprintf(a, b, c, d) if (YYDBFLG) YYPRINT(a, b, c, d) +#else +# define yyprintf(a, b, c, d) +#endif + +#ifndef YYPRINT +#define YYPRINT printf +#endif + +/* parser for yacc output */ + +#ifdef YYDUMP +int yydump = 1; /* 1 for dumping */ +void yydumpinfo(void); +#endif +#ifdef YYDEBUG +YYSTATIC int yydebug = 0; /* 1 for debugging */ +#endif +YYSTATIC YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */ +YYSTATIC short yys[YYMAXDEPTH]; /* the parse stack */ + +#if ! defined(YYRECURSIVE) +YYSTATIC YYAPI_TOKENTYPE YYAPI_TOKENNAME = YYAPI_TOKENNONE; +#if defined(YYAPI_VALUETYPE) +// YYSTATIC YYAPI_VALUETYPE YYAPI_VALUENAME; FIX +#endif +YYSTATIC int yynerrs = 0; /* number of errors */ +YYSTATIC short yyerrflag = 0; /* error recovery flag */ +#endif + +#ifdef YYRECOVER +/* +** yyscpy : copy f onto t and return a ptr to the null terminator at the +** end of t. +*/ +YYSTATIC char *yyscpy(register char*t, register char*f) + { + while(*t = *f++) + t++; + return(t); /* ptr to the null char */ + } +#endif + +#ifndef YYNEAR +#define YYNEAR +#endif +#ifndef YYPASCAL +#define YYPASCAL +#endif +#ifndef YYLOCAL +#define YYLOCAL +#endif +#if ! defined YYPARSER +#define YYPARSER yyparse +#endif +#if ! defined YYLEX +#define YYLEX yylex +#endif + +#if defined(YYRECURSIVE) + + YYSTATIC YYAPI_TOKENTYPE YYAPI_TOKENNAME = YYAPI_TOKENNONE; + #if defined(YYAPI_VALUETYPE) + YYSTATIC YYAPI_VALUETYPE YYAPI_VALUENAME; + #endif + YYSTATIC int yynerrs = 0; /* number of errors */ + YYSTATIC short yyerrflag = 0; /* error recovery flag */ + + YYSTATIC short yyn; + YYSTATIC short yystate = 0; + YYSTATIC short *yyps= &yys[-1]; + YYSTATIC YYSTYPE *yypv= &yyv[-1]; + YYSTATIC short yyj; + YYSTATIC short yym; + +#endif + +#pragma warning(disable:102) +YYLOCAL YYNEAR YYPASCAL YYPARSER() +{ +#if ! defined(YYRECURSIVE) + + register short yyn; + short yystate, *yyps; + YYSTYPE *yypv; + short yyj, yym; + + YYAPI_TOKENNAME = YYAPI_TOKENNONE; + yystate = 0; + yyps= &yys[-1]; + yypv= &yyv[-1]; +#endif + +#ifdef YYDUMP + yydumpinfo(); +#endif + yystack: /* put a state and value onto the stack */ + +#ifdef YYDEBUG + if(YYAPI_TOKENNAME == YYAPI_TOKENNONE) { + yyprintf( "state %d, token # '%d'\n", yystate, -1, 0 ); + } + else { + yyprintf( "state %d, token # '%s'\n", yystate, YYAPI_TOKENSTR(YYAPI_TOKENNAME), 0 ); + } +#endif + if( ++yyps > &yys[YYMAXDEPTH] ) { + yyerror( "yacc stack overflow" ); + return(1); + } + *yyps = yystate; + ++yypv; + + *yypv = yyval; + +yynewstate: + + yyn = YYPACT[yystate]; + + if( yyn <= YYFLAG ) { /* simple state, no lookahead */ + goto yydefault; + } + if( YYAPI_TOKENNAME == YYAPI_TOKENNONE ) { /* need a lookahead */ + YYAPI_TOKENNAME = YYLEX(); + YYAPI_CALLAFTERYYLEX(YYAPI_TOKENNAME); + } + if( ((yyn += YYAPI_TOKENEME(YYAPI_TOKENNAME)) < 0) || (yyn >= YYLAST) ) { + goto yydefault; + } + if( YYCHK[ yyn = YYACT[ yyn ] ] == YYAPI_TOKENEME(YYAPI_TOKENNAME) ) { /* valid shift */ + yyval = YYAPI_VALUEOF(YYAPI_VALUENAME); + yystate = yyn; + yyprintf( "SHIFT: saw token '%s', now in state %4d\n", YYAPI_TOKENSTR(YYAPI_TOKENNAME), yystate, 0 ); + YYAPI_TOKENNAME = YYAPI_TOKENNONE; + if( yyerrflag > 0 ) { + --yyerrflag; + } + goto yystack; + } + + yydefault: + /* default state action */ + + if( (yyn = YYDEF[yystate]) == -2 ) { + register YYCONST short *yyxi; + + if( YYAPI_TOKENNAME == YYAPI_TOKENNONE ) { + YYAPI_TOKENNAME = YYLEX(); + YYAPI_CALLAFTERYYLEX(YYAPI_TOKENNAME); + yyprintf("LOOKAHEAD: token '%s'\n", YYAPI_TOKENSTR(YYAPI_TOKENNAME), 0, 0); + } +/* +** search exception table, we find a -1 followed by the current state. +** if we find one, we'll look through terminal,state pairs. if we find +** a terminal which matches the current one, we have a match. +** the exception table is when we have a reduce on a terminal. +*/ + +#if YYOPTTIME + yyxi = yyexca + yyexcaind[yystate]; + while(( *yyxi != YYAPI_TOKENEME(YYAPI_TOKENNAME) ) && ( *yyxi >= 0 )){ + yyxi += 2; + } +#else + for(yyxi = yyexca; + (*yyxi != (-1)) || (yyxi[1] != yystate); + yyxi += 2 + ) { + ; /* VOID */ + } + + while( *(yyxi += 2) >= 0 ){ + if( *yyxi == YYAPI_TOKENEME(YYAPI_TOKENNAME) ) { + break; + } + } +#endif + if( (yyn = yyxi[1]) < 0 ) { + return(0); /* accept */ + } + } + + if( yyn == 0 ){ /* error */ + /* error ... attempt to resume parsing */ + + switch( yyerrflag ){ + + case 0: /* brand new error */ +#ifdef YYRECOVER + { + register int i,j; + + for(i = 0; + (yyrecover[i] != -1000) && (yystate > yyrecover[i]); + i += 3 + ) { + ; + } + if(yystate == yyrecover[i]) { + yyprintf("recovered, from state %d to state %d on token # %d\n", + yystate,yyrecover[i+2],yyrecover[i+1] + ); + j = yyrecover[i + 1]; + if(j < 0) { + /* + ** here we have one of the injection set, so we're not quite + ** sure that the next valid thing will be a shift. so we'll + ** count it as an error and continue. + ** actually we're not absolutely sure that the next token + ** we were supposed to get is the one when j > 0. for example, + ** for(+) {;} error recovery with yyerrflag always set, stops + ** after inserting one ; before the +. at the point of the +, + ** we're pretty sure the guy wants a 'for' loop. without + ** setting the flag, when we're almost absolutely sure, we'll + ** give him one, since the only thing we can shift on this + ** error is after finding an expression followed by a + + */ + yyerrflag++; + j = -j; + } + if(yyerrflag <= 1) { /* only on first insertion */ + yyrecerr(YYAPI_TOKENNAME, j); /* what was, what should be first */ + } + yyval = yyeval(j); + yystate = yyrecover[i + 2]; + goto yystack; + } + } +#endif + yyerror("syntax error"); + + yyerrlab: + ++yynerrs; + + case 1: + case 2: /* incompletely recovered error ... try again */ + + yyerrflag = 3; + + /* find a state where "error" is a legal shift action */ + + while ( yyps >= yys ) { + yyn = YYPACT[*yyps] + YYERRCODE; + if( yyn>= 0 && yyn < YYLAST && YYCHK[YYACT[yyn]] == YYERRCODE ){ + yystate = YYACT[yyn]; /* simulate a shift of "error" */ + yyprintf( "SHIFT 'error': now in state %4d\n", yystate, 0, 0 ); + goto yystack; + } + yyn = YYPACT[*yyps]; + + /* the current yyps has no shift onn "error", pop stack */ + + yyprintf( "error recovery pops state %4d, uncovers %4d\n", *yyps, yyps[-1], 0 ); + --yyps; + --yypv; + } + + /* there is no state on the stack with an error shift ... abort */ + + yyabort: + return(1); + + + case 3: /* no shift yet; clobber input char */ + + yyprintf( "error recovery discards token '%s'\n", YYAPI_TOKENSTR(YYAPI_TOKENNAME), 0, 0 ); + + if( YYAPI_TOKENEME(YYAPI_TOKENNAME) == 0 ) goto yyabort; /* don't discard EOF, quit */ + YYAPI_TOKENNAME = YYAPI_TOKENNONE; + goto yynewstate; /* try again in the same state */ + } + } + + /* reduction by production yyn */ +yyreduce: + { + register YYSTYPE *yypvt; + yypvt = yypv; + yyps -= YYR2[yyn]; + yypv -= YYR2[yyn]; + yyval = yypv[1]; + yyprintf("REDUCE: rule %4d, popped %2d tokens, uncovered state %4d, ",yyn, YYR2[yyn], *yyps); + yym = yyn; + yyn = YYR1[yyn]; /* consult goto table to find next state */ + yyj = YYPGO[yyn] + *yyps + 1; + if( (yyj >= YYLAST) || (YYCHK[ yystate = YYACT[yyj] ] != -yyn) ) { + yystate = YYACT[YYPGO[yyn]]; + } + yyprintf("goto state %4d\n", yystate, 0, 0); +#ifdef YYDUMP + yydumpinfo(); +#endif + switch(yym){ + +case 3: +#line 189 "asmparse.y" +{ PASM->EndClass(); } break; +case 4: +#line 190 "asmparse.y" +{ PASM->EndNameSpace(); } break; +case 5: +#line 191 "asmparse.y" +{ if(PASM->m_pCurMethod->m_ulLines[1] ==0) + { PASM->m_pCurMethod->m_ulLines[1] = PASM->m_ulCurLine; + PASM->m_pCurMethod->m_ulColumns[1]=PASM->m_ulCurColumn;} + PASM->EndMethod(); } break; +case 12: +#line 201 "asmparse.y" +{ PASMM->EndAssembly(); } break; +case 13: +#line 202 "asmparse.y" +{ PASMM->EndAssembly(); } break; +case 14: +#line 203 "asmparse.y" +{ PASMM->EndComType(); } break; +case 15: +#line 204 "asmparse.y" +{ PASMM->EndManifestRes(); } break; +case 19: +#line 208 "asmparse.y" +{ +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:22011) // Suppress PREFast warning about integer overflow/underflow +#endif + PASM->m_dwSubsystem = yypvt[-0].int32; +#ifdef _PREFAST_ +#pragma warning(pop) +#endif + } break; +case 20: +#line 218 "asmparse.y" +{ PASM->m_dwComImageFlags = yypvt[-0].int32; } break; +case 21: +#line 219 "asmparse.y" +{ PASM->m_dwFileAlignment = yypvt[-0].int32; + if((yypvt[-0].int32 & (yypvt[-0].int32 - 1))||(yypvt[-0].int32 < 0x200)||(yypvt[-0].int32 > 0x10000)) + PASM->report->error("Invalid file alignment, must be power of 2 from 0x200 to 0x10000\n");} break; +case 22: +#line 222 "asmparse.y" +{ PASM->m_stBaseAddress = (ULONGLONG)(*(yypvt[-0].int64)); delete yypvt[-0].int64; + if(PASM->m_stBaseAddress & 0xFFFF) + PASM->report->error("Invalid image base, must be 0x10000-aligned\n");} break; +case 23: +#line 225 "asmparse.y" +{ PASM->m_stSizeOfStackReserve = (size_t)(*(yypvt[-0].int64)); delete yypvt[-0].int64; } break; +case 28: +#line 230 "asmparse.y" +{ PASM->m_fIsMscorlib = TRUE; } break; +case 31: +#line 237 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 32: +#line 238 "asmparse.y" +{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; } break; +case 33: +#line 241 "asmparse.y" +{ LPCSTRToGuid(yypvt[-0].string,&(PASM->m_guidLang)); } break; +case 34: +#line 242 "asmparse.y" +{ LPCSTRToGuid(yypvt[-2].string,&(PASM->m_guidLang)); + LPCSTRToGuid(yypvt[-0].string,&(PASM->m_guidLangVendor));} break; +case 35: +#line 244 "asmparse.y" +{ LPCSTRToGuid(yypvt[-4].string,&(PASM->m_guidLang)); + LPCSTRToGuid(yypvt[-2].string,&(PASM->m_guidLangVendor)); + LPCSTRToGuid(yypvt[-2].string,&(PASM->m_guidDoc));} break; +case 36: +#line 249 "asmparse.y" +{ yyval.string = yypvt[-0].string; } break; +case 37: +#line 250 "asmparse.y" +{ yyval.string = yypvt[-0].string; } break; +case 38: +#line 253 "asmparse.y" +{ yyval.string = yypvt[-0].string; } break; +case 39: +#line 254 "asmparse.y" +{ yyval.string = yypvt[-0].string; } break; +case 40: +#line 255 "asmparse.y" +{ yyval.string = newStringWDel(yypvt[-2].string, '.', yypvt[-0].string); } break; +case 41: +#line 258 "asmparse.y" +{ yyval.int32 = yypvt[-0].int32; } break; +case 42: +#line 261 "asmparse.y" +{ yyval.int64 = yypvt[-0].int64; } break; +case 43: +#line 262 "asmparse.y" +{ yyval.int64 = neg ? new __int64(yypvt[-0].int32) : new __int64((unsigned)yypvt[-0].int32); } break; +case 44: +#line 265 "asmparse.y" +{ yyval.float64 = yypvt[-0].float64; } break; +case 45: +#line 266 "asmparse.y" +{ float f; *((__int32*) (&f)) = yypvt[-1].int32; yyval.float64 = new double(f); } break; +case 46: +#line 267 "asmparse.y" +{ yyval.float64 = (double*) yypvt[-1].int64; } break; +case 47: +#line 271 "asmparse.y" +{ PASM->AddTypeDef(yypvt[-2].binstr,yypvt[-0].string); } break; +case 48: +#line 272 "asmparse.y" +{ PASM->AddTypeDef(yypvt[-2].token,yypvt[-0].string); } break; +case 49: +#line 273 "asmparse.y" +{ PASM->AddTypeDef(yypvt[-2].token,yypvt[-0].string); } break; +case 50: +#line 274 "asmparse.y" +{ yypvt[-2].cad->tkOwner = 0; PASM->AddTypeDef(yypvt[-2].cad,yypvt[-0].string); } break; +case 51: +#line 275 "asmparse.y" +{ PASM->AddTypeDef(yypvt[-2].cad,yypvt[-0].string); } break; +case 52: +#line 280 "asmparse.y" +{ DefineVar(yypvt[-0].string, NULL); } break; +case 53: +#line 281 "asmparse.y" +{ DefineVar(yypvt[-1].string, yypvt[-0].binstr); } break; +case 54: +#line 282 "asmparse.y" +{ UndefVar(yypvt[-0].string); } break; +case 55: +#line 283 "asmparse.y" +{ SkipToken = !IsVarDefined(yypvt[-0].string); + IfEndif++; + } break; +case 56: +#line 286 "asmparse.y" +{ SkipToken = IsVarDefined(yypvt[-0].string); + IfEndif++; + } break; +case 57: +#line 289 "asmparse.y" +{ if(IfEndif == 1) SkipToken = !SkipToken;} break; +case 58: +#line 290 "asmparse.y" +{ if(IfEndif == 0) + PASM->report->error("Unmatched #endif\n"); + else IfEndif--; + } break; +case 59: +#line 294 "asmparse.y" +{ _ASSERTE(!"yylex should have dealt with this"); } break; +case 60: +#line 295 "asmparse.y" +{ } break; +case 61: +#line 299 "asmparse.y" +{ yyval.cad = new CustomDescr(PASM->m_tkCurrentCVOwner, yypvt[-0].token, NULL); } break; +case 62: +#line 300 "asmparse.y" +{ yyval.cad = new CustomDescr(PASM->m_tkCurrentCVOwner, yypvt[-2].token, yypvt[-0].binstr); } break; +case 63: +#line 301 "asmparse.y" +{ yyval.cad = new CustomDescr(PASM->m_tkCurrentCVOwner, yypvt[-4].token, yypvt[-1].binstr); } break; +case 64: +#line 302 "asmparse.y" +{ yyval.cad = new CustomDescr(PASM->m_tkCurrentCVOwner, yypvt[-2].int32, yypvt[-1].binstr); } break; +case 65: +#line 305 "asmparse.y" +{ yyval.cad = new CustomDescr(yypvt[-2].token, yypvt[-0].token, NULL); } break; +case 66: +#line 306 "asmparse.y" +{ yyval.cad = new CustomDescr(yypvt[-4].token, yypvt[-2].token, yypvt[-0].binstr); } break; +case 67: +#line 308 "asmparse.y" +{ yyval.cad = new CustomDescr(yypvt[-6].token, yypvt[-4].token, yypvt[-1].binstr); } break; +case 68: +#line 309 "asmparse.y" +{ yyval.cad = new CustomDescr(PASM->m_tkCurrentCVOwner, yypvt[-2].int32, yypvt[-1].binstr); } break; +case 69: +#line 312 "asmparse.y" +{ yyval.int32 = yypvt[-2].token; bParsingByteArray = TRUE; } break; +case 70: +#line 316 "asmparse.y" +{ PASM->m_pCustomDescrList = NULL; + PASM->m_tkCurrentCVOwner = yypvt[-4].token; + yyval.int32 = yypvt[-2].token; bParsingByteArray = TRUE; } break; +case 71: +#line 321 "asmparse.y" +{ yyval.token = yypvt[-0].token; } break; +case 72: +#line 324 "asmparse.y" +{ yyval.token = yypvt[-0].token; } break; +case 73: +#line 325 "asmparse.y" +{ yyval.token = yypvt[-0].token; } break; +case 74: +#line 329 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; + yyval.binstr->appendInt16(nCustomBlobNVPairs); + yyval.binstr->append(yypvt[-0].binstr); + nCustomBlobNVPairs = 0; } break; +case 75: +#line 335 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt16(VAL16(0x0001)); } break; +case 76: +#line 336 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; + yyval.binstr->appendFrom(yypvt[-0].binstr, (*(yypvt[-0].binstr->ptr()) == ELEMENT_TYPE_SZARRAY) ? 2 : 1); } break; +case 77: +#line 338 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; } break; +case 78: +#line 341 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 79: +#line 343 "asmparse.y" +{ yyval.binstr = yypvt[-5].binstr; yyval.binstr->appendInt8(yypvt[-4].int32); + yyval.binstr->append(yypvt[-3].binstr); + AppendStringWithLength(yyval.binstr,yypvt[-2].string); + yyval.binstr->appendFrom(yypvt[-0].binstr, (*(yypvt[-0].binstr->ptr()) == ELEMENT_TYPE_SZARRAY) ? 2 : 1); + nCustomBlobNVPairs++; } break; +case 80: +#line 348 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; } break; +case 81: +#line 351 "asmparse.y" +{ yyval.int32 = SERIALIZATION_TYPE_FIELD; } break; +case 82: +#line 352 "asmparse.y" +{ yyval.int32 = SERIALIZATION_TYPE_PROPERTY; } break; +case 83: +#line 355 "asmparse.y" +{ if(yypvt[-0].cad->tkOwner && !yypvt[-0].cad->tkInterfacePair) + PASM->DefineCV(yypvt[-0].cad); + else if(PASM->m_pCustomDescrList) + PASM->m_pCustomDescrList->PUSH(yypvt[-0].cad); } break; +case 84: +#line 359 "asmparse.y" +{ PASM->DefineCV(yypvt[-0].cad); } break; +case 85: +#line 360 "asmparse.y" +{ CustomDescr* pNew = new CustomDescr(yypvt[-0].tdd->m_pCA); + if(pNew->tkOwner == 0) pNew->tkOwner = PASM->m_tkCurrentCVOwner; + if(pNew->tkOwner) + PASM->DefineCV(pNew); + else if(PASM->m_pCustomDescrList) + PASM->m_pCustomDescrList->PUSH(pNew); } break; +case 86: +#line 368 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 87: +#line 369 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_TYPE); } break; +case 88: +#line 370 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_TAGGED_OBJECT); } break; +case 89: +#line 371 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); + AppendStringWithLength(yyval.binstr,yypvt[-0].string); } break; +case 90: +#line 373 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); + AppendStringWithLength(yyval.binstr,PASM->ReflectionNotation(yypvt[-0].token)); } break; +case 91: +#line 375 "asmparse.y" +{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 92: +#line 380 "asmparse.y" +{ PASMM->SetModuleName(NULL); PASM->m_tkCurrentCVOwner=1; } break; +case 93: +#line 381 "asmparse.y" +{ PASMM->SetModuleName(yypvt[-0].string); PASM->m_tkCurrentCVOwner=1; } break; +case 94: +#line 382 "asmparse.y" +{ BinStr* pbs = new BinStr(); + unsigned L = (unsigned)strlen(yypvt[-0].string); + memcpy((char*)(pbs->getBuff(L)),yypvt[-0].string,L); + PASM->EmitImport(pbs); delete pbs;} break; +case 95: +#line 389 "asmparse.y" +{ /*PASM->SetDataSection(); PASM->EmitDataLabel($7);*/ + PASM->m_VTFList.PUSH(new VTFEntry((USHORT)yypvt[-4].int32, (USHORT)yypvt[-2].int32, yypvt[-0].string)); } break; +case 96: +#line 393 "asmparse.y" +{ yyval.int32 = 0; } break; +case 97: +#line 394 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32 | COR_VTABLE_32BIT; } break; +case 98: +#line 395 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32 | COR_VTABLE_64BIT; } break; +case 99: +#line 396 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32 | COR_VTABLE_FROM_UNMANAGED; } break; +case 100: +#line 397 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32 | COR_VTABLE_CALL_MOST_DERIVED; } break; +case 101: +#line 398 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32 | COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN; } break; +case 102: +#line 401 "asmparse.y" +{ PASM->m_pVTable = yypvt[-1].binstr; } break; +case 103: +#line 404 "asmparse.y" +{ bParsingByteArray = TRUE; } break; +case 104: +#line 408 "asmparse.y" +{ PASM->StartNameSpace(yypvt[-0].string); } break; +case 105: +#line 411 "asmparse.y" +{ newclass = TRUE; } break; +case 106: +#line 414 "asmparse.y" +{ if(yypvt[-0].typarlist) FixupConstraints(); + PASM->StartClass(yypvt[-1].string, yypvt[-2].classAttr, yypvt[-0].typarlist); + TyParFixupList.RESET(false); + newclass = FALSE; + } break; +case 107: +#line 420 "asmparse.y" +{ PASM->AddClass(); } break; +case 108: +#line 423 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) 0; } break; +case 109: +#line 424 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdVisibilityMask) | tdPublic); } break; +case 110: +#line 425 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdVisibilityMask) | tdNotPublic); } break; +case 111: +#line 426 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | 0x80000000 | tdSealed); } break; +case 112: +#line 427 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | 0x40000000); } break; +case 113: +#line 428 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdInterface | tdAbstract); } break; +case 114: +#line 429 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdSealed); } break; +case 115: +#line 430 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdAbstract); } break; +case 116: +#line 431 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdLayoutMask) | tdAutoLayout); } break; +case 117: +#line 432 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdLayoutMask) | tdSequentialLayout); } break; +case 118: +#line 433 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdLayoutMask) | tdExplicitLayout); } break; +case 119: +#line 434 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdStringFormatMask) | tdAnsiClass); } break; +case 120: +#line 435 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdStringFormatMask) | tdUnicodeClass); } break; +case 121: +#line 436 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-1].classAttr & ~tdStringFormatMask) | tdAutoClass); } break; +case 122: +#line 437 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdImport); } break; +case 123: +#line 438 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdSerializable); } break; +case 124: +#line 439 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdWindowsRuntime); } break; +case 125: +#line 440 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedPublic); } break; +case 126: +#line 441 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedPrivate); } break; +case 127: +#line 442 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedFamily); } break; +case 128: +#line 443 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedAssembly); } break; +case 129: +#line 444 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedFamANDAssem); } break; +case 130: +#line 445 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) ((yypvt[-2].classAttr & ~tdVisibilityMask) | tdNestedFamORAssem); } break; +case 131: +#line 446 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdBeforeFieldInit); } break; +case 132: +#line 447 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr | tdSpecialName); } break; +case 133: +#line 448 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].classAttr); } break; +case 134: +#line 449 "asmparse.y" +{ yyval.classAttr = (CorRegTypeAttr) (yypvt[-1].int32); } break; +case 136: +#line 453 "asmparse.y" +{ PASM->m_crExtends = yypvt[-0].token; } break; +case 141: +#line 464 "asmparse.y" +{ PASM->AddToImplList(yypvt[-0].token); } break; +case 142: +#line 465 "asmparse.y" +{ PASM->AddToImplList(yypvt[-0].token); } break; +case 143: +#line 469 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 144: +#line 470 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 145: +#line 473 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt32(yypvt[-0].token); } break; +case 146: +#line 474 "asmparse.y" +{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->appendInt32(yypvt[-0].token); } break; +case 147: +#line 477 "asmparse.y" +{ yyval.typarlist = NULL; PASM->m_TyParList = NULL;} break; +case 148: +#line 478 "asmparse.y" +{ yyval.typarlist = yypvt[-1].typarlist; PASM->m_TyParList = yypvt[-1].typarlist;} break; +case 149: +#line 481 "asmparse.y" +{ yyval.int32 = gpCovariant; } break; +case 150: +#line 482 "asmparse.y" +{ yyval.int32 = gpContravariant; } break; +case 151: +#line 483 "asmparse.y" +{ yyval.int32 = gpReferenceTypeConstraint; } break; +case 152: +#line 484 "asmparse.y" +{ yyval.int32 = gpNotNullableValueTypeConstraint; } break; +case 153: +#line 485 "asmparse.y" +{ yyval.int32 = gpDefaultConstructorConstraint; } break; +case 154: +#line 488 "asmparse.y" +{ yyval.int32 = 0; } break; +case 155: +#line 489 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32 | yypvt[-0].int32; } break; +case 156: +#line 492 "asmparse.y" +{yyval.typarlist = new TyParList(yypvt[-3].int32, yypvt[-2].binstr, yypvt[-1].string, yypvt[-0].typarlist);} break; +case 157: +#line 493 "asmparse.y" +{yyval.typarlist = new TyParList(yypvt[-2].int32, NULL, yypvt[-1].string, yypvt[-0].typarlist);} break; +case 158: +#line 496 "asmparse.y" +{ yyval.typarlist = NULL; } break; +case 159: +#line 497 "asmparse.y" +{ yyval.typarlist = yypvt[-0].typarlist; } break; +case 160: +#line 500 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; } break; +case 161: +#line 503 "asmparse.y" +{ yyval.int32= 0; } break; +case 162: +#line 504 "asmparse.y" +{ yyval.int32 = yypvt[-0].int32; } break; +case 163: +#line 507 "asmparse.y" +{ yyval.int32 = yypvt[-2].int32; } break; +case 164: +#line 511 "asmparse.y" +{ if(PASM->m_pCurMethod->m_ulLines[1] ==0) + { PASM->m_pCurMethod->m_ulLines[1] = PASM->m_ulCurLine; + PASM->m_pCurMethod->m_ulColumns[1]=PASM->m_ulCurColumn;} + PASM->EndMethod(); } break; +case 165: +#line 515 "asmparse.y" +{ PASM->EndClass(); } break; +case 166: +#line 516 "asmparse.y" +{ PASM->EndEvent(); } break; +case 167: +#line 517 "asmparse.y" +{ PASM->EndProp(); } break; +case 173: +#line 523 "asmparse.y" +{ PASM->m_pCurClass->m_ulSize = yypvt[-0].int32; } break; +case 174: +#line 524 "asmparse.y" +{ PASM->m_pCurClass->m_ulPack = yypvt[-0].int32; } break; +case 175: +#line 525 "asmparse.y" +{ PASMM->EndComType(); } break; +case 176: +#line 527 "asmparse.y" +{ BinStr *sig1 = parser->MakeSig(yypvt[-7].int32, yypvt[-6].binstr, yypvt[-1].binstr); + BinStr *sig2 = new BinStr(); sig2->append(sig1); + PASM->AddMethodImpl(yypvt[-11].token,yypvt[-9].string,sig1,yypvt[-5].token,yypvt[-3].string,sig2); + PASM->ResetArgNameList(); + } break; +case 177: +#line 533 "asmparse.y" +{ PASM->AddMethodImpl(yypvt[-17].token,yypvt[-15].string, + (yypvt[-14].int32==0 ? parser->MakeSig(yypvt[-19].int32,yypvt[-18].binstr,yypvt[-12].binstr) : + parser->MakeSig(yypvt[-19].int32| IMAGE_CEE_CS_CALLCONV_GENERIC,yypvt[-18].binstr,yypvt[-12].binstr,yypvt[-14].int32)), + yypvt[-6].token,yypvt[-4].string, + (yypvt[-3].int32==0 ? parser->MakeSig(yypvt[-8].int32,yypvt[-7].binstr,yypvt[-1].binstr) : + parser->MakeSig(yypvt[-8].int32| IMAGE_CEE_CS_CALLCONV_GENERIC,yypvt[-7].binstr,yypvt[-1].binstr,yypvt[-3].int32))); + PASM->ResetArgNameList(); + } break; +case 180: +#line 543 "asmparse.y" +{ if((yypvt[-1].int32 > 0) && (yypvt[-1].int32 <= (int)PASM->m_pCurClass->m_NumTyPars)) + PASM->m_pCustomDescrList = PASM->m_pCurClass->m_TyPars[yypvt[-1].int32-1].CAList(); + else + PASM->report->error("Type parameter index out of range\n"); + } break; +case 181: +#line 548 "asmparse.y" +{ int n = PASM->m_pCurClass->FindTyPar(yypvt[-0].string); + if(n >= 0) + PASM->m_pCustomDescrList = PASM->m_pCurClass->m_TyPars[n].CAList(); + else + PASM->report->error("Type parameter '%s' undefined\n",yypvt[-0].string); + } break; +case 182: +#line 554 "asmparse.y" +{ yypvt[-0].cad->tkInterfacePair = yypvt[-1].token; + if(PASM->m_pCustomDescrList) + PASM->m_pCustomDescrList->PUSH(yypvt[-0].cad); + } break; +case 183: +#line 562 "asmparse.y" +{ yypvt[-3].binstr->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + PASM->AddField(yypvt[-2].string, yypvt[-3].binstr, yypvt[-4].fieldAttr, yypvt[-1].string, yypvt[-0].binstr, yypvt[-5].int32); } break; +case 184: +#line 566 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) 0; } break; +case 185: +#line 567 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].fieldAttr | fdStatic); } break; +case 186: +#line 568 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdPublic); } break; +case 187: +#line 569 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdPrivate); } break; +case 188: +#line 570 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdFamily); } break; +case 189: +#line 571 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].fieldAttr | fdInitOnly); } break; +case 190: +#line 572 "asmparse.y" +{ yyval.fieldAttr = yypvt[-1].fieldAttr; } break; +case 191: +#line 573 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].fieldAttr | fdSpecialName); } break; +case 192: +#line 586 "asmparse.y" +{ PASM->m_pMarshal = yypvt[-1].binstr; } break; +case 193: +#line 587 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdAssembly); } break; +case 194: +#line 588 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdFamANDAssem); } break; +case 195: +#line 589 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdFamORAssem); } break; +case 196: +#line 590 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) ((yypvt[-1].fieldAttr & ~mdMemberAccessMask) | fdPrivateScope); } break; +case 197: +#line 591 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].fieldAttr | fdLiteral); } break; +case 198: +#line 592 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].fieldAttr | fdNotSerialized); } break; +case 199: +#line 593 "asmparse.y" +{ yyval.fieldAttr = (CorFieldAttr) (yypvt[-1].int32); } break; +case 200: +#line 596 "asmparse.y" +{ yyval.string = 0; } break; +case 201: +#line 597 "asmparse.y" +{ yyval.string = yypvt[-0].string; } break; +case 202: +#line 600 "asmparse.y" +{ yyval.binstr = NULL; } break; +case 203: +#line 601 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 204: +#line 604 "asmparse.y" +{ yyval.int32 = 0xFFFFFFFF; } break; +case 205: +#line 605 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32; } break; +case 206: +#line 610 "asmparse.y" +{ PASM->ResetArgNameList(); + if (yypvt[-3].binstr == NULL) + { + if((iCallConv)&&((yypvt[-8].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + yyval.token = PASM->MakeMemberRef(yypvt[-6].token, yypvt[-4].string, parser->MakeSig(yypvt[-8].int32|iCallConv, yypvt[-7].binstr, yypvt[-1].binstr)); + } + else + { + mdToken mr; + if((iCallConv)&&((yypvt[-8].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + mr = PASM->MakeMemberRef(yypvt[-6].token, yypvt[-4].string, + parser->MakeSig(yypvt[-8].int32 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, yypvt[-7].binstr, yypvt[-1].binstr, corCountArgs(yypvt[-3].binstr))); + yyval.token = PASM->MakeMethodSpec(mr, + parser->MakeSig(IMAGE_CEE_CS_CALLCONV_INSTANTIATION, 0, yypvt[-3].binstr)); + } + } break; +case 207: +#line 627 "asmparse.y" +{ PASM->ResetArgNameList(); + if((iCallConv)&&((yypvt[-8].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + yyval.token = PASM->MakeMemberRef(yypvt[-6].token, yypvt[-4].string, + parser->MakeSig(yypvt[-8].int32 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, yypvt[-7].binstr, yypvt[-1].binstr, yypvt[-3].int32)); + } break; +case 208: +#line 633 "asmparse.y" +{ PASM->ResetArgNameList(); + if (yypvt[-3].binstr == NULL) + { + if((iCallConv)&&((yypvt[-6].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + yyval.token = PASM->MakeMemberRef(mdTokenNil, yypvt[-4].string, parser->MakeSig(yypvt[-6].int32|iCallConv, yypvt[-5].binstr, yypvt[-1].binstr)); + } + else + { + mdToken mr; + if((iCallConv)&&((yypvt[-6].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + mr = PASM->MakeMemberRef(mdTokenNil, yypvt[-4].string, parser->MakeSig(yypvt[-6].int32 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, yypvt[-5].binstr, yypvt[-1].binstr, corCountArgs(yypvt[-3].binstr))); + yyval.token = PASM->MakeMethodSpec(mr, + parser->MakeSig(IMAGE_CEE_CS_CALLCONV_INSTANTIATION, 0, yypvt[-3].binstr)); + } + } break; +case 209: +#line 649 "asmparse.y" +{ PASM->ResetArgNameList(); + if((iCallConv)&&((yypvt[-6].int32 & iCallConv) != iCallConv)) parser->warn("'instance' added to method's calling convention\n"); + yyval.token = PASM->MakeMemberRef(mdTokenNil, yypvt[-4].string, parser->MakeSig(yypvt[-6].int32 | IMAGE_CEE_CS_CALLCONV_GENERIC|iCallConv, yypvt[-5].binstr, yypvt[-1].binstr, yypvt[-3].int32)); + } break; +case 210: +#line 653 "asmparse.y" +{ yyval.token = yypvt[-0].token; } break; +case 211: +#line 654 "asmparse.y" +{ yyval.token = yypvt[-0].tdd->m_tkTypeSpec; } break; +case 212: +#line 655 "asmparse.y" +{ yyval.token = yypvt[-0].tdd->m_tkTypeSpec; } break; +case 213: +#line 658 "asmparse.y" +{ yyval.int32 = (yypvt[-0].int32 | IMAGE_CEE_CS_CALLCONV_HASTHIS); } break; +case 214: +#line 659 "asmparse.y" +{ yyval.int32 = (yypvt[-0].int32 | IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS); } break; +case 215: +#line 660 "asmparse.y" +{ yyval.int32 = yypvt[-0].int32; } break; +case 216: +#line 661 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32; } break; +case 217: +#line 664 "asmparse.y" +{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_DEFAULT; } break; +case 218: +#line 665 "asmparse.y" +{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_DEFAULT; } break; +case 219: +#line 666 "asmparse.y" +{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_VARARG; } break; +case 220: +#line 667 "asmparse.y" +{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_C; } break; +case 221: +#line 668 "asmparse.y" +{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_STDCALL; } break; +case 222: +#line 669 "asmparse.y" +{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_THISCALL; } break; +case 223: +#line 670 "asmparse.y" +{ yyval.int32 = IMAGE_CEE_CS_CALLCONV_FASTCALL; } break; +case 224: +#line 673 "asmparse.y" +{ yyval.token = yypvt[-1].int32; } break; +case 225: +#line 676 "asmparse.y" +{ yyval.token = yypvt[-0].token; + PASM->delArgNameList(PASM->m_firstArgName); + PASM->m_firstArgName = parser->m_ANSFirst.POP(); + PASM->m_lastArgName = parser->m_ANSLast.POP(); + PASM->SetMemberRefFixup(yypvt[-0].token,iOpcodeLen); } break; +case 226: +#line 682 "asmparse.y" +{ yypvt[-3].binstr->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + yyval.token = PASM->MakeMemberRef(yypvt[-2].token, yypvt[-0].string, yypvt[-3].binstr); + PASM->SetMemberRefFixup(yyval.token,iOpcodeLen); } break; +case 227: +#line 686 "asmparse.y" +{ yypvt[-1].binstr->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + yyval.token = PASM->MakeMemberRef(NULL, yypvt[-0].string, yypvt[-1].binstr); + PASM->SetMemberRefFixup(yyval.token,iOpcodeLen); } break; +case 228: +#line 689 "asmparse.y" +{ yyval.token = yypvt[-0].tdd->m_tkTypeSpec; + PASM->SetMemberRefFixup(yyval.token,iOpcodeLen); } break; +case 229: +#line 691 "asmparse.y" +{ yyval.token = yypvt[-0].tdd->m_tkTypeSpec; + PASM->SetMemberRefFixup(yyval.token,iOpcodeLen); } break; +case 230: +#line 693 "asmparse.y" +{ yyval.token = yypvt[-0].token; + PASM->SetMemberRefFixup(yyval.token,iOpcodeLen); } break; +case 231: +#line 698 "asmparse.y" +{ PASM->ResetEvent(yypvt[-0].string, yypvt[-1].token, yypvt[-2].eventAttr); } break; +case 232: +#line 699 "asmparse.y" +{ PASM->ResetEvent(yypvt[-0].string, mdTypeRefNil, yypvt[-1].eventAttr); } break; +case 233: +#line 703 "asmparse.y" +{ yyval.eventAttr = (CorEventAttr) 0; } break; +case 234: +#line 704 "asmparse.y" +{ yyval.eventAttr = yypvt[-1].eventAttr; } break; +case 235: +#line 705 "asmparse.y" +{ yyval.eventAttr = (CorEventAttr) (yypvt[-1].eventAttr | evSpecialName); } break; +case 238: +#line 712 "asmparse.y" +{ PASM->SetEventMethod(0, yypvt[-0].token); } break; +case 239: +#line 713 "asmparse.y" +{ PASM->SetEventMethod(1, yypvt[-0].token); } break; +case 240: +#line 714 "asmparse.y" +{ PASM->SetEventMethod(2, yypvt[-0].token); } break; +case 241: +#line 715 "asmparse.y" +{ PASM->SetEventMethod(3, yypvt[-0].token); } break; +case 246: +#line 724 "asmparse.y" +{ PASM->ResetProp(yypvt[-4].string, + parser->MakeSig((IMAGE_CEE_CS_CALLCONV_PROPERTY | + (yypvt[-6].int32 & IMAGE_CEE_CS_CALLCONV_HASTHIS)),yypvt[-5].binstr,yypvt[-2].binstr), yypvt[-7].propAttr, yypvt[-0].binstr);} break; +case 247: +#line 729 "asmparse.y" +{ yyval.propAttr = (CorPropertyAttr) 0; } break; +case 248: +#line 730 "asmparse.y" +{ yyval.propAttr = yypvt[-1].propAttr; } break; +case 249: +#line 731 "asmparse.y" +{ yyval.propAttr = (CorPropertyAttr) (yypvt[-1].propAttr | prSpecialName); } break; +case 252: +#line 739 "asmparse.y" +{ PASM->SetPropMethod(0, yypvt[-0].token); } break; +case 253: +#line 740 "asmparse.y" +{ PASM->SetPropMethod(1, yypvt[-0].token); } break; +case 254: +#line 741 "asmparse.y" +{ PASM->SetPropMethod(2, yypvt[-0].token); } break; +case 259: +#line 749 "asmparse.y" +{ PASM->ResetForNextMethod(); + uMethodBeginLine = PASM->m_ulCurLine; + uMethodBeginColumn=PASM->m_ulCurColumn; + } break; +case 260: +#line 755 "asmparse.y" +{ yyval.binstr = NULL; } break; +case 261: +#line 756 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; } break; +case 262: +#line 759 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 263: +#line 760 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; } break; +case 264: +#line 763 "asmparse.y" +{ bParsingByteArray = TRUE; } break; +case 265: +#line 767 "asmparse.y" +{ BinStr* sig; + if (yypvt[-5].typarlist == NULL) sig = parser->MakeSig(yypvt[-10].int32, yypvt[-8].binstr, yypvt[-3].binstr); + else { + FixupTyPars(yypvt[-8].binstr); + sig = parser->MakeSig(yypvt[-10].int32 | IMAGE_CEE_CS_CALLCONV_GENERIC, yypvt[-8].binstr, yypvt[-3].binstr, yypvt[-5].typarlist->Count()); + FixupConstraints(); + } + PASM->StartMethod(yypvt[-6].string, sig, yypvt[-11].methAttr, yypvt[-7].binstr, yypvt[-9].int32, yypvt[-5].typarlist); + TyParFixupList.RESET(false); + PASM->SetImplAttr((USHORT)yypvt[-1].implAttr); + PASM->m_pCurMethod->m_ulLines[0] = uMethodBeginLine; + PASM->m_pCurMethod->m_ulColumns[0]=uMethodBeginColumn; + } break; +case 266: +#line 782 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) 0; } break; +case 267: +#line 783 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdStatic); } break; +case 268: +#line 784 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdPublic); } break; +case 269: +#line 785 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdPrivate); } break; +case 270: +#line 786 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdFamily); } break; +case 271: +#line 787 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdFinal); } break; +case 272: +#line 788 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdSpecialName); } break; +case 273: +#line 789 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdVirtual); } break; +case 274: +#line 790 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdCheckAccessOnOverride); } break; +case 275: +#line 791 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdAbstract); } break; +case 276: +#line 792 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdAssem); } break; +case 277: +#line 793 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdFamANDAssem); } break; +case 278: +#line 794 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdFamORAssem); } break; +case 279: +#line 795 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) ((yypvt[-1].methAttr & ~mdMemberAccessMask) | mdPrivateScope); } break; +case 280: +#line 796 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdHideBySig); } break; +case 281: +#line 797 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdNewSlot); } break; +case 282: +#line 798 "asmparse.y" +{ yyval.methAttr = yypvt[-1].methAttr; } break; +case 283: +#line 799 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdUnmanagedExport); } break; +case 284: +#line 800 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].methAttr | mdRequireSecObject); } break; +case 285: +#line 801 "asmparse.y" +{ yyval.methAttr = (CorMethodAttr) (yypvt[-1].int32); } break; +case 286: +#line 803 "asmparse.y" +{ PASM->SetPinvoke(yypvt[-4].binstr,0,yypvt[-2].binstr,yypvt[-1].pinvAttr); + yyval.methAttr = (CorMethodAttr) (yypvt[-7].methAttr | mdPinvokeImpl); } break; +case 287: +#line 806 "asmparse.y" +{ PASM->SetPinvoke(yypvt[-2].binstr,0,NULL,yypvt[-1].pinvAttr); + yyval.methAttr = (CorMethodAttr) (yypvt[-5].methAttr | mdPinvokeImpl); } break; +case 288: +#line 809 "asmparse.y" +{ PASM->SetPinvoke(new BinStr(),0,NULL,yypvt[-1].pinvAttr); + yyval.methAttr = (CorMethodAttr) (yypvt[-4].methAttr | mdPinvokeImpl); } break; +case 289: +#line 813 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) 0; } break; +case 290: +#line 814 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmNoMangle); } break; +case 291: +#line 815 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCharSetAnsi); } break; +case 292: +#line 816 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCharSetUnicode); } break; +case 293: +#line 817 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCharSetAuto); } break; +case 294: +#line 818 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmSupportsLastError); } break; +case 295: +#line 819 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCallConvWinapi); } break; +case 296: +#line 820 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCallConvCdecl); } break; +case 297: +#line 821 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCallConvStdcall); } break; +case 298: +#line 822 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCallConvThiscall); } break; +case 299: +#line 823 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].pinvAttr | pmCallConvFastcall); } break; +case 300: +#line 824 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-3].pinvAttr | pmBestFitEnabled); } break; +case 301: +#line 825 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-3].pinvAttr | pmBestFitDisabled); } break; +case 302: +#line 826 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-3].pinvAttr | pmThrowOnUnmappableCharEnabled); } break; +case 303: +#line 827 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-3].pinvAttr | pmThrowOnUnmappableCharDisabled); } break; +case 304: +#line 828 "asmparse.y" +{ yyval.pinvAttr = (CorPinvokeMap) (yypvt[-1].int32); } break; +case 305: +#line 831 "asmparse.y" +{ yyval.string = newString(COR_CTOR_METHOD_NAME); } break; +case 306: +#line 832 "asmparse.y" +{ yyval.string = newString(COR_CCTOR_METHOD_NAME); } break; +case 307: +#line 833 "asmparse.y" +{ yyval.string = yypvt[-0].string; } break; +case 308: +#line 836 "asmparse.y" +{ yyval.int32 = 0; } break; +case 309: +#line 837 "asmparse.y" +{ yyval.int32 = yypvt[-3].int32 | pdIn; } break; +case 310: +#line 838 "asmparse.y" +{ yyval.int32 = yypvt[-3].int32 | pdOut; } break; +case 311: +#line 839 "asmparse.y" +{ yyval.int32 = yypvt[-3].int32 | pdOptional; } break; +case 312: +#line 840 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32 + 1; } break; +case 313: +#line 843 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (miIL | miManaged); } break; +case 314: +#line 844 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) ((yypvt[-1].implAttr & 0xFFF4) | miNative); } break; +case 315: +#line 845 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) ((yypvt[-1].implAttr & 0xFFF4) | miIL); } break; +case 316: +#line 846 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) ((yypvt[-1].implAttr & 0xFFF4) | miOPTIL); } break; +case 317: +#line 847 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) ((yypvt[-1].implAttr & 0xFFFB) | miManaged); } break; +case 318: +#line 848 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) ((yypvt[-1].implAttr & 0xFFFB) | miUnmanaged); } break; +case 319: +#line 849 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miForwardRef); } break; +case 320: +#line 850 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miPreserveSig); } break; +case 321: +#line 851 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miRuntime); } break; +case 322: +#line 852 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miInternalCall); } break; +case 323: +#line 853 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miSynchronized); } break; +case 324: +#line 854 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miNoInlining); } break; +case 325: +#line 855 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miAggressiveInlining); } break; +case 326: +#line 856 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].implAttr | miNoOptimization); } break; +case 327: +#line 857 "asmparse.y" +{ yyval.implAttr = (CorMethodImpl) (yypvt[-1].int32); } break; +case 328: +#line 860 "asmparse.y" +{ PASM->delArgNameList(PASM->m_firstArgName); PASM->m_firstArgName = NULL;PASM->m_lastArgName = NULL; + } break; +case 331: +#line 868 "asmparse.y" +{ PASM->EmitByte(yypvt[-0].int32); } break; +case 332: +#line 869 "asmparse.y" +{ delete PASM->m_SEHD; PASM->m_SEHD = PASM->m_SEHDstack.POP(); } break; +case 333: +#line 870 "asmparse.y" +{ PASM->EmitMaxStack(yypvt[-0].int32); } break; +case 334: +#line 871 "asmparse.y" +{ PASM->EmitLocals(parser->MakeSig(IMAGE_CEE_CS_CALLCONV_LOCAL_SIG, 0, yypvt[-1].binstr)); + } break; +case 335: +#line 873 "asmparse.y" +{ PASM->EmitZeroInit(); + PASM->EmitLocals(parser->MakeSig(IMAGE_CEE_CS_CALLCONV_LOCAL_SIG, 0, yypvt[-1].binstr)); + } break; +case 336: +#line 876 "asmparse.y" +{ PASM->EmitEntryPoint(); } break; +case 337: +#line 877 "asmparse.y" +{ PASM->EmitZeroInit(); } break; +case 340: +#line 880 "asmparse.y" +{ PASM->AddLabel(PASM->m_CurPC,yypvt[-1].string); /*PASM->EmitLabel($1);*/ } break; +case 346: +#line 886 "asmparse.y" +{ if(PASM->m_pCurMethod->m_dwExportOrdinal == 0xFFFFFFFF) + { + PASM->m_pCurMethod->m_dwExportOrdinal = yypvt[-1].int32; + PASM->m_pCurMethod->m_szExportAlias = NULL; + if(PASM->m_pCurMethod->m_wVTEntry == 0) PASM->m_pCurMethod->m_wVTEntry = 1; + if(PASM->m_pCurMethod->m_wVTSlot == 0) PASM->m_pCurMethod->m_wVTSlot = yypvt[-1].int32 + 0x8000; + } + else + PASM->report->warn("Duplicate .export directive, ignored\n"); + } break; +case 347: +#line 896 "asmparse.y" +{ if(PASM->m_pCurMethod->m_dwExportOrdinal == 0xFFFFFFFF) + { + PASM->m_pCurMethod->m_dwExportOrdinal = yypvt[-3].int32; + PASM->m_pCurMethod->m_szExportAlias = yypvt[-0].string; + if(PASM->m_pCurMethod->m_wVTEntry == 0) PASM->m_pCurMethod->m_wVTEntry = 1; + if(PASM->m_pCurMethod->m_wVTSlot == 0) PASM->m_pCurMethod->m_wVTSlot = yypvt[-3].int32 + 0x8000; + } + else + PASM->report->warn("Duplicate .export directive, ignored\n"); + } break; +case 348: +#line 906 "asmparse.y" +{ PASM->m_pCurMethod->m_wVTEntry = (WORD)yypvt[-2].int32; + PASM->m_pCurMethod->m_wVTSlot = (WORD)yypvt[-0].int32; } break; +case 349: +#line 909 "asmparse.y" +{ PASM->AddMethodImpl(yypvt[-2].token,yypvt[-0].string,NULL,NULL,NULL,NULL); } break; +case 350: +#line 912 "asmparse.y" +{ PASM->AddMethodImpl(yypvt[-6].token,yypvt[-4].string, + (yypvt[-3].int32==0 ? parser->MakeSig(yypvt[-8].int32,yypvt[-7].binstr,yypvt[-1].binstr) : + parser->MakeSig(yypvt[-8].int32| IMAGE_CEE_CS_CALLCONV_GENERIC,yypvt[-7].binstr,yypvt[-1].binstr,yypvt[-3].int32)) + ,NULL,NULL,NULL); + PASM->ResetArgNameList(); + } break; +case 352: +#line 919 "asmparse.y" +{ if((yypvt[-1].int32 > 0) && (yypvt[-1].int32 <= (int)PASM->m_pCurMethod->m_NumTyPars)) + PASM->m_pCustomDescrList = PASM->m_pCurMethod->m_TyPars[yypvt[-1].int32-1].CAList(); + else + PASM->report->error("Type parameter index out of range\n"); + } break; +case 353: +#line 924 "asmparse.y" +{ int n = PASM->m_pCurMethod->FindTyPar(yypvt[-0].string); + if(n >= 0) + PASM->m_pCustomDescrList = PASM->m_pCurMethod->m_TyPars[n].CAList(); + else + PASM->report->error("Type parameter '%s' undefined\n",yypvt[-0].string); + } break; +case 354: +#line 931 "asmparse.y" +{ if( yypvt[-2].int32 ) { + ARG_NAME_LIST* pAN=PASM->findArg(PASM->m_pCurMethod->m_firstArgName, yypvt[-2].int32 - 1); + if(pAN) + { + PASM->m_pCustomDescrList = &(pAN->CustDList); + pAN->pValue = yypvt[-0].binstr; + } + else + { + PASM->m_pCustomDescrList = NULL; + if(yypvt[-0].binstr) delete yypvt[-0].binstr; + } + } else { + PASM->m_pCustomDescrList = &(PASM->m_pCurMethod->m_RetCustDList); + PASM->m_pCurMethod->m_pRetValue = yypvt[-0].binstr; + } + PASM->m_tkCurrentCVOwner = 0; + } break; +case 355: +#line 951 "asmparse.y" +{ PASM->m_pCurMethod->CloseScope(); } break; +case 356: +#line 954 "asmparse.y" +{ PASM->m_pCurMethod->OpenScope(); } break; +case 360: +#line 965 "asmparse.y" +{ PASM->m_SEHD->tryTo = PASM->m_CurPC; } break; +case 361: +#line 966 "asmparse.y" +{ PASM->SetTryLabels(yypvt[-2].string, yypvt[-0].string); } break; +case 362: +#line 967 "asmparse.y" +{ if(PASM->m_SEHD) {PASM->m_SEHD->tryFrom = yypvt[-2].int32; + PASM->m_SEHD->tryTo = yypvt[-0].int32;} } break; +case 363: +#line 971 "asmparse.y" +{ PASM->NewSEHDescriptor(); + PASM->m_SEHD->tryFrom = PASM->m_CurPC; } break; +case 364: +#line 976 "asmparse.y" +{ PASM->EmitTry(); } break; +case 365: +#line 977 "asmparse.y" +{ PASM->EmitTry(); } break; +case 366: +#line 978 "asmparse.y" +{ PASM->EmitTry(); } break; +case 367: +#line 979 "asmparse.y" +{ PASM->EmitTry(); } break; +case 368: +#line 983 "asmparse.y" +{ PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; +case 369: +#line 984 "asmparse.y" +{ PASM->SetFilterLabel(yypvt[-0].string); + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; +case 370: +#line 986 "asmparse.y" +{ PASM->m_SEHD->sehFilter = yypvt[-0].int32; + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; +case 371: +#line 990 "asmparse.y" +{ PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FILTER; + PASM->m_SEHD->sehFilter = PASM->m_CurPC; } break; +case 372: +#line 994 "asmparse.y" +{ PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_NONE; + PASM->SetCatchClass(yypvt[-0].token); + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; +case 373: +#line 999 "asmparse.y" +{ PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FINALLY; + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; +case 374: +#line 1003 "asmparse.y" +{ PASM->m_SEHD->sehClause = COR_ILEXCEPTION_CLAUSE_FAULT; + PASM->m_SEHD->sehHandler = PASM->m_CurPC; } break; +case 375: +#line 1007 "asmparse.y" +{ PASM->m_SEHD->sehHandlerTo = PASM->m_CurPC; } break; +case 376: +#line 1008 "asmparse.y" +{ PASM->SetHandlerLabels(yypvt[-2].string, yypvt[-0].string); } break; +case 377: +#line 1009 "asmparse.y" +{ PASM->m_SEHD->sehHandler = yypvt[-2].int32; + PASM->m_SEHD->sehHandlerTo = yypvt[-0].int32; } break; +case 379: +#line 1017 "asmparse.y" +{ PASM->EmitDataLabel(yypvt[-1].string); } break; +case 381: +#line 1021 "asmparse.y" +{ PASM->SetDataSection(); } break; +case 382: +#line 1022 "asmparse.y" +{ PASM->SetTLSSection(); } break; +case 383: +#line 1023 "asmparse.y" +{ PASM->SetILSection(); } break; +case 388: +#line 1034 "asmparse.y" +{ yyval.int32 = 1; } break; +case 389: +#line 1035 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32; + if(yypvt[-1].int32 <= 0) { PASM->report->error("Illegal item count: %d\n",yypvt[-1].int32); + if(!PASM->OnErrGo) yyval.int32 = 1; }} break; +case 390: +#line 1040 "asmparse.y" +{ PASM->EmitDataString(yypvt[-1].binstr); } break; +case 391: +#line 1041 "asmparse.y" +{ PASM->EmitDD(yypvt[-1].string); } break; +case 392: +#line 1042 "asmparse.y" +{ PASM->EmitData(yypvt[-1].binstr->ptr(),yypvt[-1].binstr->length()); } break; +case 393: +#line 1044 "asmparse.y" +{ float f = (float) (*yypvt[-2].float64); float* p = new (nothrow) float[yypvt[-0].int32]; + if(p != NULL) { + for(int i=0; i < yypvt[-0].int32; i++) p[i] = f; + PASM->EmitData(p, sizeof(float)*yypvt[-0].int32); delete yypvt[-2].float64; delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(float)*yypvt[-0].int32); } break; +case 394: +#line 1051 "asmparse.y" +{ double* p = new (nothrow) double[yypvt[-0].int32]; + if(p != NULL) { + for(int i=0; iEmitData(p, sizeof(double)*yypvt[-0].int32); delete yypvt[-2].float64; delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(double)*yypvt[-0].int32); } break; +case 395: +#line 1058 "asmparse.y" +{ __int64* p = new (nothrow) __int64[yypvt[-0].int32]; + if(p != NULL) { + for(int i=0; iEmitData(p, sizeof(__int64)*yypvt[-0].int32); delete yypvt[-2].int64; delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(__int64)*yypvt[-0].int32); } break; +case 396: +#line 1065 "asmparse.y" +{ __int32* p = new (nothrow) __int32[yypvt[-0].int32]; + if(p != NULL) { + for(int i=0; iEmitData(p, sizeof(__int32)*yypvt[-0].int32); delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(__int32)*yypvt[-0].int32); } break; +case 397: +#line 1072 "asmparse.y" +{ __int16 i = (__int16) yypvt[-2].int32; FAIL_UNLESS(i == yypvt[-2].int32, ("Value %d too big\n", yypvt[-2].int32)); + __int16* p = new (nothrow) __int16[yypvt[-0].int32]; + if(p != NULL) { + for(int j=0; jEmitData(p, sizeof(__int16)*yypvt[-0].int32); delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(__int16)*yypvt[-0].int32); } break; +case 398: +#line 1080 "asmparse.y" +{ __int8 i = (__int8) yypvt[-2].int32; FAIL_UNLESS(i == yypvt[-2].int32, ("Value %d too big\n", yypvt[-2].int32)); + __int8* p = new (nothrow) __int8[yypvt[-0].int32]; + if(p != NULL) { + for(int j=0; jEmitData(p, sizeof(__int8)*yypvt[-0].int32); delete [] p; + } else PASM->report->error("Out of memory emitting data block %d bytes\n", + sizeof(__int8)*yypvt[-0].int32); } break; +case 399: +#line 1087 "asmparse.y" +{ PASM->EmitData(NULL, sizeof(float)*yypvt[-0].int32); } break; +case 400: +#line 1088 "asmparse.y" +{ PASM->EmitData(NULL, sizeof(double)*yypvt[-0].int32); } break; +case 401: +#line 1089 "asmparse.y" +{ PASM->EmitData(NULL, sizeof(__int64)*yypvt[-0].int32); } break; +case 402: +#line 1090 "asmparse.y" +{ PASM->EmitData(NULL, sizeof(__int32)*yypvt[-0].int32); } break; +case 403: +#line 1091 "asmparse.y" +{ PASM->EmitData(NULL, sizeof(__int16)*yypvt[-0].int32); } break; +case 404: +#line 1092 "asmparse.y" +{ PASM->EmitData(NULL, sizeof(__int8)*yypvt[-0].int32); } break; +case 405: +#line 1096 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R4); + float f = (float)(*yypvt[-1].float64); + yyval.binstr->appendInt32(*((__int32*)&f)); delete yypvt[-1].float64; } break; +case 406: +#line 1099 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R8); + yyval.binstr->appendInt64((__int64 *)yypvt[-1].float64); delete yypvt[-1].float64; } break; +case 407: +#line 1101 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R4); + yyval.binstr->appendInt32(yypvt[-1].int32); } break; +case 408: +#line 1103 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R8); + yyval.binstr->appendInt64((__int64 *)yypvt[-1].int64); delete yypvt[-1].int64; } break; +case 409: +#line 1105 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I8); + yyval.binstr->appendInt64((__int64 *)yypvt[-1].int64); delete yypvt[-1].int64; } break; +case 410: +#line 1107 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I4); + yyval.binstr->appendInt32(yypvt[-1].int32); } break; +case 411: +#line 1109 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I2); + yyval.binstr->appendInt16(yypvt[-1].int32); } break; +case 412: +#line 1111 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I1); + yyval.binstr->appendInt8(yypvt[-1].int32); } break; +case 413: +#line 1113 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U8); + yyval.binstr->appendInt64((__int64 *)yypvt[-1].int64); delete yypvt[-1].int64; } break; +case 414: +#line 1115 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U4); + yyval.binstr->appendInt32(yypvt[-1].int32); } break; +case 415: +#line 1117 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U2); + yyval.binstr->appendInt16(yypvt[-1].int32); } break; +case 416: +#line 1119 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U1); + yyval.binstr->appendInt8(yypvt[-1].int32); } break; +case 417: +#line 1121 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U8); + yyval.binstr->appendInt64((__int64 *)yypvt[-1].int64); delete yypvt[-1].int64; } break; +case 418: +#line 1123 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U4); + yyval.binstr->appendInt32(yypvt[-1].int32); } break; +case 419: +#line 1125 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U2); + yyval.binstr->appendInt16(yypvt[-1].int32); } break; +case 420: +#line 1127 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U1); + yyval.binstr->appendInt8(yypvt[-1].int32); } break; +case 421: +#line 1129 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_CHAR); + yyval.binstr->appendInt16(yypvt[-1].int32); } break; +case 422: +#line 1131 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_BOOLEAN); + yyval.binstr->appendInt8(yypvt[-1].int32);} break; +case 423: +#line 1133 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_STRING); + yyval.binstr->append(yypvt[-1].binstr); delete yypvt[-1].binstr;} break; +case 424: +#line 1137 "asmparse.y" +{ bParsingByteArray = TRUE; } break; +case 425: +#line 1140 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 426: +#line 1141 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 427: +#line 1144 "asmparse.y" +{ __int8 i = (__int8) yypvt[-0].int32; yyval.binstr = new BinStr(); yyval.binstr->appendInt8(i); } break; +case 428: +#line 1145 "asmparse.y" +{ __int8 i = (__int8) yypvt[-0].int32; yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt8(i); } break; +case 429: +#line 1149 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 430: +#line 1150 "asmparse.y" +{ yyval.binstr = BinStrToUnicode(yypvt[-0].binstr,true); yyval.binstr->insertInt8(ELEMENT_TYPE_STRING);} break; +case 431: +#line 1151 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_CLASS); + yyval.binstr->appendInt32(0); } break; +case 432: +#line 1156 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 433: +#line 1157 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_STRING); yyval.binstr->appendInt8(0xFF); } break; +case 434: +#line 1158 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_STRING); + AppendStringWithLength(yyval.binstr,yypvt[-1].string); delete [] yypvt[-1].string;} break; +case 435: +#line 1160 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_TYPE); + AppendStringWithLength(yyval.binstr,yypvt[-1].string); delete [] yypvt[-1].string;} break; +case 436: +#line 1162 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_TYPE); + AppendStringWithLength(yyval.binstr,PASM->ReflectionNotation(yypvt[-1].token));} break; +case 437: +#line 1164 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(SERIALIZATION_TYPE_TYPE); yyval.binstr->appendInt8(0xFF); } break; +case 438: +#line 1165 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt8(SERIALIZATION_TYPE_TAGGED_OBJECT);} break; +case 439: +#line 1167 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_R4); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 440: +#line 1171 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_R8); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 441: +#line 1175 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_I8); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 442: +#line 1179 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_I4); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 443: +#line 1183 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_I2); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 444: +#line 1187 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_I1); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 445: +#line 1191 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_U8); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 446: +#line 1195 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_U4); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 447: +#line 1199 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_U2); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 448: +#line 1203 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_U1); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 449: +#line 1207 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_U8); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 450: +#line 1211 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_U4); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 451: +#line 1215 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_U2); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 452: +#line 1219 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_U1); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 453: +#line 1223 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_CHAR); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 454: +#line 1227 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_BOOLEAN); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 455: +#line 1231 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(ELEMENT_TYPE_STRING); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 456: +#line 1235 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(SERIALIZATION_TYPE_TYPE); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 457: +#line 1239 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt32(yypvt[-4].int32); + yyval.binstr->insertInt8(SERIALIZATION_TYPE_TAGGED_OBJECT); + yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 458: +#line 1245 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 459: +#line 1246 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; + float f = (float) (*yypvt[-0].float64); yyval.binstr->appendInt32(*((__int32*)&f)); delete yypvt[-0].float64; } break; +case 460: +#line 1248 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; + yyval.binstr->appendInt32(yypvt[-0].int32); } break; +case 461: +#line 1252 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 462: +#line 1253 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; + yyval.binstr->appendInt64((__int64 *)yypvt[-0].float64); delete yypvt[-0].float64; } break; +case 463: +#line 1255 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; + yyval.binstr->appendInt64((__int64 *)yypvt[-0].int64); delete yypvt[-0].int64; } break; +case 464: +#line 1259 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 465: +#line 1260 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; + yyval.binstr->appendInt64((__int64 *)yypvt[-0].int64); delete yypvt[-0].int64; } break; +case 466: +#line 1264 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 467: +#line 1265 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt32(yypvt[-0].int32);} break; +case 468: +#line 1268 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 469: +#line 1269 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt16(yypvt[-0].int32);} break; +case 470: +#line 1272 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 471: +#line 1273 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt8(yypvt[-0].int32); } break; +case 472: +#line 1276 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 473: +#line 1277 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; + yyval.binstr->appendInt8(yypvt[-0].int32);} break; +case 474: +#line 1281 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 475: +#line 1282 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt8(0xFF); } break; +case 476: +#line 1283 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; + AppendStringWithLength(yyval.binstr,yypvt[-0].string); delete [] yypvt[-0].string;} break; +case 477: +#line 1287 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 478: +#line 1288 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->appendInt8(0xFF); } break; +case 479: +#line 1289 "asmparse.y" +{ yyval.binstr = yypvt[-2].binstr; + AppendStringWithLength(yyval.binstr,yypvt[-0].string); delete [] yypvt[-0].string;} break; +case 480: +#line 1291 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; + AppendStringWithLength(yyval.binstr,PASM->ReflectionNotation(yypvt[-0].token));} break; +case 481: +#line 1295 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 482: +#line 1296 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; } break; +case 483: +#line 1300 "asmparse.y" +{ parser->m_ANSFirst.PUSH(PASM->m_firstArgName); + parser->m_ANSLast.PUSH(PASM->m_lastArgName); + PASM->m_firstArgName = NULL; + PASM->m_lastArgName = NULL; } break; +case 484: +#line 1306 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 485: +#line 1309 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 486: +#line 1312 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 487: +#line 1315 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 488: +#line 1318 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 489: +#line 1321 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 490: +#line 1324 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); + if((!PASM->OnErrGo)&& + ((yypvt[-0].opcode == CEE_NEWOBJ)|| + (yypvt[-0].opcode == CEE_CALLVIRT))) + iCallConv = IMAGE_CEE_CS_CALLCONV_HASTHIS; + } break; +case 491: +#line 1332 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 492: +#line 1335 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 493: +#line 1338 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 494: +#line 1341 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 495: +#line 1344 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); iOpcodeLen = PASM->OpcodeLen(yyval.instr); } break; +case 496: +#line 1347 "asmparse.y" +{ yyval.instr = SetupInstr(yypvt[-0].opcode); } break; +case 497: +#line 1350 "asmparse.y" +{ yyval.instr = yypvt[-1].instr; bParsingByteArray = TRUE; } break; +case 498: +#line 1354 "asmparse.y" +{ PASM->EmitOpcode(yypvt[-0].instr); } break; +case 499: +#line 1355 "asmparse.y" +{ PASM->EmitInstrVar(yypvt[-1].instr, yypvt[-0].int32); } break; +case 500: +#line 1356 "asmparse.y" +{ PASM->EmitInstrVarByName(yypvt[-1].instr, yypvt[-0].string); } break; +case 501: +#line 1357 "asmparse.y" +{ PASM->EmitInstrI(yypvt[-1].instr, yypvt[-0].int32); } break; +case 502: +#line 1358 "asmparse.y" +{ PASM->EmitInstrI8(yypvt[-1].instr, yypvt[-0].int64); } break; +case 503: +#line 1359 "asmparse.y" +{ PASM->EmitInstrR(yypvt[-1].instr, yypvt[-0].float64); delete (yypvt[-0].float64);} break; +case 504: +#line 1360 "asmparse.y" +{ double f = (double) (*yypvt[-0].int64); PASM->EmitInstrR(yypvt[-1].instr, &f); } break; +case 505: +#line 1361 "asmparse.y" +{ unsigned L = yypvt[-1].binstr->length(); + FAIL_UNLESS(L >= sizeof(float), ("%d hexbytes, must be at least %d\n", + L,sizeof(float))); + if(L < sizeof(float)) {YYERROR; } + else { + double f = (L >= sizeof(double)) ? *((double *)(yypvt[-1].binstr->ptr())) + : (double)(*(float *)(yypvt[-1].binstr->ptr())); + PASM->EmitInstrR(yypvt[-2].instr,&f); } + delete yypvt[-1].binstr; } break; +case 506: +#line 1370 "asmparse.y" +{ PASM->EmitInstrBrOffset(yypvt[-1].instr, yypvt[-0].int32); } break; +case 507: +#line 1371 "asmparse.y" +{ PASM->EmitInstrBrTarget(yypvt[-1].instr, yypvt[-0].string); } break; +case 508: +#line 1373 "asmparse.y" +{ PASM->SetMemberRefFixup(yypvt[-0].token,PASM->OpcodeLen(yypvt[-1].instr)); + PASM->EmitInstrI(yypvt[-1].instr,yypvt[-0].token); + PASM->m_tkCurrentCVOwner = yypvt[-0].token; + PASM->m_pCustomDescrList = NULL; + iCallConv = 0; + } break; +case 509: +#line 1380 "asmparse.y" +{ yypvt[-3].binstr->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + mdToken mr = PASM->MakeMemberRef(yypvt[-2].token, yypvt[-0].string, yypvt[-3].binstr); + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen(yypvt[-4].instr)); + PASM->EmitInstrI(yypvt[-4].instr,mr); + PASM->m_tkCurrentCVOwner = mr; + PASM->m_pCustomDescrList = NULL; + } break; +case 510: +#line 1388 "asmparse.y" +{ yypvt[-1].binstr->insertInt8(IMAGE_CEE_CS_CALLCONV_FIELD); + mdToken mr = PASM->MakeMemberRef(mdTokenNil, yypvt[-0].string, yypvt[-1].binstr); + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen(yypvt[-2].instr)); + PASM->EmitInstrI(yypvt[-2].instr,mr); + PASM->m_tkCurrentCVOwner = mr; + PASM->m_pCustomDescrList = NULL; + } break; +case 511: +#line 1395 "asmparse.y" +{ mdToken mr = yypvt[-0].token; + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen(yypvt[-1].instr)); + PASM->EmitInstrI(yypvt[-1].instr,mr); + PASM->m_tkCurrentCVOwner = mr; + PASM->m_pCustomDescrList = NULL; + } break; +case 512: +#line 1401 "asmparse.y" +{ mdToken mr = yypvt[-0].tdd->m_tkTypeSpec; + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen(yypvt[-1].instr)); + PASM->EmitInstrI(yypvt[-1].instr,mr); + PASM->m_tkCurrentCVOwner = mr; + PASM->m_pCustomDescrList = NULL; + } break; +case 513: +#line 1407 "asmparse.y" +{ mdToken mr = yypvt[-0].tdd->m_tkTypeSpec; + PASM->SetMemberRefFixup(mr, PASM->OpcodeLen(yypvt[-1].instr)); + PASM->EmitInstrI(yypvt[-1].instr,mr); + PASM->m_tkCurrentCVOwner = mr; + PASM->m_pCustomDescrList = NULL; + } break; +case 514: +#line 1413 "asmparse.y" +{ PASM->EmitInstrI(yypvt[-1].instr, yypvt[-0].token); + PASM->m_tkCurrentCVOwner = yypvt[-0].token; + PASM->m_pCustomDescrList = NULL; + } break; +case 515: +#line 1417 "asmparse.y" +{ PASM->EmitInstrStringLiteral(yypvt[-1].instr, yypvt[-0].binstr,TRUE); } break; +case 516: +#line 1419 "asmparse.y" +{ PASM->EmitInstrStringLiteral(yypvt[-4].instr, yypvt[-1].binstr,FALSE); } break; +case 517: +#line 1421 "asmparse.y" +{ PASM->EmitInstrStringLiteral(yypvt[-3].instr, yypvt[-1].binstr,FALSE,TRUE); } break; +case 518: +#line 1423 "asmparse.y" +{ PASM->EmitInstrSig(yypvt[-5].instr, parser->MakeSig(yypvt[-4].int32, yypvt[-3].binstr, yypvt[-1].binstr)); + PASM->ResetArgNameList(); + } break; +case 519: +#line 1427 "asmparse.y" +{ PASM->EmitInstrI(yypvt[-1].instr,yypvt[-0].token); + PASM->m_tkCurrentCVOwner = yypvt[-0].token; + PASM->m_pCustomDescrList = NULL; + iOpcodeLen = 0; + } break; +case 520: +#line 1432 "asmparse.y" +{ PASM->EmitInstrSwitch(yypvt[-3].instr, yypvt[-1].labels); } break; +case 521: +#line 1435 "asmparse.y" +{ yyval.labels = 0; } break; +case 522: +#line 1436 "asmparse.y" +{ yyval.labels = new Labels(yypvt[-2].string, yypvt[-0].labels, TRUE); } break; +case 523: +#line 1437 "asmparse.y" +{ yyval.labels = new Labels((char *)(UINT_PTR)yypvt[-2].int32, yypvt[-0].labels, FALSE); } break; +case 524: +#line 1438 "asmparse.y" +{ yyval.labels = new Labels(yypvt[-0].string, NULL, TRUE); } break; +case 525: +#line 1439 "asmparse.y" +{ yyval.labels = new Labels((char *)(UINT_PTR)yypvt[-0].int32, NULL, FALSE); } break; +case 526: +#line 1443 "asmparse.y" +{ yyval.binstr = NULL; } break; +case 527: +#line 1444 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; } break; +case 528: +#line 1447 "asmparse.y" +{ yyval.binstr = NULL; } break; +case 529: +#line 1448 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 530: +#line 1451 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 531: +#line 1452 "asmparse.y" +{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; } break; +case 532: +#line 1456 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 533: +#line 1457 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr;} break; +case 534: +#line 1460 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 535: +#line 1461 "asmparse.y" +{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; } break; +case 536: +#line 1464 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_SENTINEL); } break; +case 537: +#line 1465 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->append(yypvt[-1].binstr); PASM->addArgName(NULL, yypvt[-1].binstr, yypvt[-0].binstr, yypvt[-2].int32); } break; +case 538: +#line 1466 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->append(yypvt[-2].binstr); PASM->addArgName(yypvt[-0].string, yypvt[-2].binstr, yypvt[-1].binstr, yypvt[-3].int32);} break; +case 539: +#line 1470 "asmparse.y" +{ yyval.token = PASM->ResolveClassRef(PASM->GetAsmRef(yypvt[-2].string), yypvt[-0].string, NULL); delete[] yypvt[-2].string;} break; +case 540: +#line 1471 "asmparse.y" +{ yyval.token = PASM->ResolveClassRef(yypvt[-2].token, yypvt[-0].string, NULL); } break; +case 541: +#line 1472 "asmparse.y" +{ yyval.token = PASM->ResolveClassRef(mdTokenNil, yypvt[-0].string, NULL); } break; +case 542: +#line 1473 "asmparse.y" +{ yyval.token = PASM->ResolveClassRef(PASM->GetModRef(yypvt[-2].string),yypvt[-0].string, NULL); delete[] yypvt[-2].string;} break; +case 543: +#line 1474 "asmparse.y" +{ yyval.token = PASM->ResolveClassRef(1,yypvt[-0].string,NULL); } break; +case 544: +#line 1475 "asmparse.y" +{ yyval.token = yypvt[-0].token; } break; +case 545: +#line 1476 "asmparse.y" +{ yyval.token = yypvt[-0].tdd->m_tkTypeSpec; } break; +case 546: +#line 1477 "asmparse.y" +{ if(PASM->m_pCurClass != NULL) yyval.token = PASM->m_pCurClass->m_cl; + else { yyval.token = 0; PASM->report->error(".this outside class scope\n"); } + } break; +case 547: +#line 1480 "asmparse.y" +{ if(PASM->m_pCurClass != NULL) { + yyval.token = PASM->m_pCurClass->m_crExtends; + if(RidFromToken(yyval.token) == 0) + PASM->report->error(".base undefined\n"); + } else { yyval.token = 0; PASM->report->error(".base outside class scope\n"); } + } break; +case 548: +#line 1486 "asmparse.y" +{ if(PASM->m_pCurClass != NULL) { + if(PASM->m_pCurClass->m_pEncloser != NULL) yyval.token = PASM->m_pCurClass->m_pEncloser->m_cl; + else { yyval.token = 0; PASM->report->error(".nester undefined\n"); } + } else { yyval.token = 0; PASM->report->error(".nester outside class scope\n"); } + } break; +case 549: +#line 1493 "asmparse.y" +{ yyval.string = yypvt[-0].string; } break; +case 550: +#line 1494 "asmparse.y" +{ yyval.string = newStringWDel(yypvt[-2].string, NESTING_SEP, yypvt[-0].string); } break; +case 551: +#line 1497 "asmparse.y" +{ yyval.token = yypvt[-0].token;} break; +case 552: +#line 1498 "asmparse.y" +{ yyval.token = PASM->GetAsmRef(yypvt[-1].string); delete[] yypvt[-1].string;} break; +case 553: +#line 1499 "asmparse.y" +{ yyval.token = PASM->GetModRef(yypvt[-1].string); delete[] yypvt[-1].string;} break; +case 554: +#line 1500 "asmparse.y" +{ yyval.token = PASM->ResolveTypeSpec(yypvt[-0].binstr); } break; +case 555: +#line 1504 "asmparse.y" +{ yyval.binstr = new BinStr(); } break; +case 556: +#line 1506 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_CUSTOMMARSHALER); + corEmitInt(yyval.binstr,yypvt[-7].binstr->length()); yyval.binstr->append(yypvt[-7].binstr); + corEmitInt(yyval.binstr,yypvt[-5].binstr->length()); yyval.binstr->append(yypvt[-5].binstr); + corEmitInt(yyval.binstr,yypvt[-3].binstr->length()); yyval.binstr->append(yypvt[-3].binstr); + corEmitInt(yyval.binstr,yypvt[-1].binstr->length()); yyval.binstr->append(yypvt[-1].binstr); + PASM->report->warn("Deprecated 4-string form of custom marshaler, first two strings ignored\n");} break; +case 557: +#line 1513 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_CUSTOMMARSHALER); + corEmitInt(yyval.binstr,0); + corEmitInt(yyval.binstr,0); + corEmitInt(yyval.binstr,yypvt[-3].binstr->length()); yyval.binstr->append(yypvt[-3].binstr); + corEmitInt(yyval.binstr,yypvt[-1].binstr->length()); yyval.binstr->append(yypvt[-1].binstr); } break; +case 558: +#line 1518 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_FIXEDSYSSTRING); + corEmitInt(yyval.binstr,yypvt[-1].int32); } break; +case 559: +#line 1521 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_FIXEDARRAY); + corEmitInt(yyval.binstr,yypvt[-2].int32); yyval.binstr->append(yypvt[-0].binstr); } break; +case 560: +#line 1523 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_VARIANT); + PASM->report->warn("Deprecated native type 'variant'\n"); } break; +case 561: +#line 1525 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_CURRENCY); } break; +case 562: +#line 1526 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_SYSCHAR); + PASM->report->warn("Deprecated native type 'syschar'\n"); } break; +case 563: +#line 1528 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_VOID); + PASM->report->warn("Deprecated native type 'void'\n"); } break; +case 564: +#line 1530 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_BOOLEAN); } break; +case 565: +#line 1531 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_I1); } break; +case 566: +#line 1532 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_I2); } break; +case 567: +#line 1533 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_I4); } break; +case 568: +#line 1534 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_I8); } break; +case 569: +#line 1535 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_R4); } break; +case 570: +#line 1536 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_R8); } break; +case 571: +#line 1537 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_ERROR); } break; +case 572: +#line 1538 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U1); } break; +case 573: +#line 1539 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U2); } break; +case 574: +#line 1540 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U4); } break; +case 575: +#line 1541 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U8); } break; +case 576: +#line 1542 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U1); } break; +case 577: +#line 1543 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U2); } break; +case 578: +#line 1544 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U4); } break; +case 579: +#line 1545 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_U8); } break; +case 580: +#line 1546 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt8(NATIVE_TYPE_PTR); + PASM->report->warn("Deprecated native type '*'\n"); } break; +case 581: +#line 1548 "asmparse.y" +{ yyval.binstr = yypvt[-2].binstr; if(yyval.binstr->length()==0) yyval.binstr->appendInt8(NATIVE_TYPE_MAX); + yyval.binstr->insertInt8(NATIVE_TYPE_ARRAY); } break; +case 582: +#line 1550 "asmparse.y" +{ yyval.binstr = yypvt[-3].binstr; if(yyval.binstr->length()==0) yyval.binstr->appendInt8(NATIVE_TYPE_MAX); + yyval.binstr->insertInt8(NATIVE_TYPE_ARRAY); + corEmitInt(yyval.binstr,0); + corEmitInt(yyval.binstr,yypvt[-1].int32); + corEmitInt(yyval.binstr,0); } break; +case 583: +#line 1555 "asmparse.y" +{ yyval.binstr = yypvt[-5].binstr; if(yyval.binstr->length()==0) yyval.binstr->appendInt8(NATIVE_TYPE_MAX); + yyval.binstr->insertInt8(NATIVE_TYPE_ARRAY); + corEmitInt(yyval.binstr,yypvt[-1].int32); + corEmitInt(yyval.binstr,yypvt[-3].int32); + corEmitInt(yyval.binstr,ntaSizeParamIndexSpecified); } break; +case 584: +#line 1560 "asmparse.y" +{ yyval.binstr = yypvt[-4].binstr; if(yyval.binstr->length()==0) yyval.binstr->appendInt8(NATIVE_TYPE_MAX); + yyval.binstr->insertInt8(NATIVE_TYPE_ARRAY); + corEmitInt(yyval.binstr,yypvt[-1].int32); } break; +case 585: +#line 1563 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_DECIMAL); + PASM->report->warn("Deprecated native type 'decimal'\n"); } break; +case 586: +#line 1565 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_DATE); + PASM->report->warn("Deprecated native type 'date'\n"); } break; +case 587: +#line 1567 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_BSTR); } break; +case 588: +#line 1568 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_LPSTR); } break; +case 589: +#line 1569 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_LPWSTR); } break; +case 590: +#line 1570 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_LPTSTR); } break; +case 591: +#line 1571 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_OBJECTREF); + PASM->report->warn("Deprecated native type 'objectref'\n"); } break; +case 592: +#line 1573 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_IUNKNOWN); + if(yypvt[-0].int32 != -1) corEmitInt(yyval.binstr,yypvt[-0].int32); } break; +case 593: +#line 1575 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_IDISPATCH); + if(yypvt[-0].int32 != -1) corEmitInt(yyval.binstr,yypvt[-0].int32); } break; +case 594: +#line 1577 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_STRUCT); } break; +case 595: +#line 1578 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_INTF); + if(yypvt[-0].int32 != -1) corEmitInt(yyval.binstr,yypvt[-0].int32); } break; +case 596: +#line 1580 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_SAFEARRAY); + corEmitInt(yyval.binstr,yypvt[-0].int32); + corEmitInt(yyval.binstr,0);} break; +case 597: +#line 1583 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_SAFEARRAY); + corEmitInt(yyval.binstr,yypvt[-2].int32); + corEmitInt(yyval.binstr,yypvt[-0].binstr->length()); yyval.binstr->append(yypvt[-0].binstr); } break; +case 598: +#line 1587 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_INT); } break; +case 599: +#line 1588 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_UINT); } break; +case 600: +#line 1589 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_UINT); } break; +case 601: +#line 1590 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_NESTEDSTRUCT); + PASM->report->warn("Deprecated native type 'nested struct'\n"); } break; +case 602: +#line 1592 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_BYVALSTR); } break; +case 603: +#line 1593 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_ANSIBSTR); } break; +case 604: +#line 1594 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_TBSTR); } break; +case 605: +#line 1595 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_VARIANTBOOL); } break; +case 606: +#line 1596 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_FUNC); } break; +case 607: +#line 1597 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_ASANY); } break; +case 608: +#line 1598 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(NATIVE_TYPE_LPSTRUCT); } break; +case 609: +#line 1599 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->append(yypvt[-0].tdd->m_pbsTypeSpec); } break; +case 610: +#line 1602 "asmparse.y" +{ yyval.int32 = -1; } break; +case 611: +#line 1603 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32; } break; +case 612: +#line 1606 "asmparse.y" +{ yyval.int32 = VT_EMPTY; } break; +case 613: +#line 1607 "asmparse.y" +{ yyval.int32 = VT_NULL; } break; +case 614: +#line 1608 "asmparse.y" +{ yyval.int32 = VT_VARIANT; } break; +case 615: +#line 1609 "asmparse.y" +{ yyval.int32 = VT_CY; } break; +case 616: +#line 1610 "asmparse.y" +{ yyval.int32 = VT_VOID; } break; +case 617: +#line 1611 "asmparse.y" +{ yyval.int32 = VT_BOOL; } break; +case 618: +#line 1612 "asmparse.y" +{ yyval.int32 = VT_I1; } break; +case 619: +#line 1613 "asmparse.y" +{ yyval.int32 = VT_I2; } break; +case 620: +#line 1614 "asmparse.y" +{ yyval.int32 = VT_I4; } break; +case 621: +#line 1615 "asmparse.y" +{ yyval.int32 = VT_I8; } break; +case 622: +#line 1616 "asmparse.y" +{ yyval.int32 = VT_R4; } break; +case 623: +#line 1617 "asmparse.y" +{ yyval.int32 = VT_R8; } break; +case 624: +#line 1618 "asmparse.y" +{ yyval.int32 = VT_UI1; } break; +case 625: +#line 1619 "asmparse.y" +{ yyval.int32 = VT_UI2; } break; +case 626: +#line 1620 "asmparse.y" +{ yyval.int32 = VT_UI4; } break; +case 627: +#line 1621 "asmparse.y" +{ yyval.int32 = VT_UI8; } break; +case 628: +#line 1622 "asmparse.y" +{ yyval.int32 = VT_UI1; } break; +case 629: +#line 1623 "asmparse.y" +{ yyval.int32 = VT_UI2; } break; +case 630: +#line 1624 "asmparse.y" +{ yyval.int32 = VT_UI4; } break; +case 631: +#line 1625 "asmparse.y" +{ yyval.int32 = VT_UI8; } break; +case 632: +#line 1626 "asmparse.y" +{ yyval.int32 = VT_PTR; } break; +case 633: +#line 1627 "asmparse.y" +{ yyval.int32 = yypvt[-2].int32 | VT_ARRAY; } break; +case 634: +#line 1628 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32 | VT_VECTOR; } break; +case 635: +#line 1629 "asmparse.y" +{ yyval.int32 = yypvt[-1].int32 | VT_BYREF; } break; +case 636: +#line 1630 "asmparse.y" +{ yyval.int32 = VT_DECIMAL; } break; +case 637: +#line 1631 "asmparse.y" +{ yyval.int32 = VT_DATE; } break; +case 638: +#line 1632 "asmparse.y" +{ yyval.int32 = VT_BSTR; } break; +case 639: +#line 1633 "asmparse.y" +{ yyval.int32 = VT_LPSTR; } break; +case 640: +#line 1634 "asmparse.y" +{ yyval.int32 = VT_LPWSTR; } break; +case 641: +#line 1635 "asmparse.y" +{ yyval.int32 = VT_UNKNOWN; } break; +case 642: +#line 1636 "asmparse.y" +{ yyval.int32 = VT_DISPATCH; } break; +case 643: +#line 1637 "asmparse.y" +{ yyval.int32 = VT_SAFEARRAY; } break; +case 644: +#line 1638 "asmparse.y" +{ yyval.int32 = VT_INT; } break; +case 645: +#line 1639 "asmparse.y" +{ yyval.int32 = VT_UINT; } break; +case 646: +#line 1640 "asmparse.y" +{ yyval.int32 = VT_UINT; } break; +case 647: +#line 1641 "asmparse.y" +{ yyval.int32 = VT_ERROR; } break; +case 648: +#line 1642 "asmparse.y" +{ yyval.int32 = VT_HRESULT; } break; +case 649: +#line 1643 "asmparse.y" +{ yyval.int32 = VT_CARRAY; } break; +case 650: +#line 1644 "asmparse.y" +{ yyval.int32 = VT_USERDEFINED; } break; +case 651: +#line 1645 "asmparse.y" +{ yyval.int32 = VT_RECORD; } break; +case 652: +#line 1646 "asmparse.y" +{ yyval.int32 = VT_FILETIME; } break; +case 653: +#line 1647 "asmparse.y" +{ yyval.int32 = VT_BLOB; } break; +case 654: +#line 1648 "asmparse.y" +{ yyval.int32 = VT_STREAM; } break; +case 655: +#line 1649 "asmparse.y" +{ yyval.int32 = VT_STORAGE; } break; +case 656: +#line 1650 "asmparse.y" +{ yyval.int32 = VT_STREAMED_OBJECT; } break; +case 657: +#line 1651 "asmparse.y" +{ yyval.int32 = VT_STORED_OBJECT; } break; +case 658: +#line 1652 "asmparse.y" +{ yyval.int32 = VT_BLOB_OBJECT; } break; +case 659: +#line 1653 "asmparse.y" +{ yyval.int32 = VT_CF; } break; +case 660: +#line 1654 "asmparse.y" +{ yyval.int32 = VT_CLSID; } break; +case 661: +#line 1658 "asmparse.y" +{ if(yypvt[-0].token == PASM->m_tkSysString) + { yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_STRING); } + else if(yypvt[-0].token == PASM->m_tkSysObject) + { yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_OBJECT); } + else + yyval.binstr = parser->MakeTypeClass(ELEMENT_TYPE_CLASS, yypvt[-0].token); } break; +case 662: +#line 1664 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_OBJECT); } break; +case 663: +#line 1665 "asmparse.y" +{ yyval.binstr = parser->MakeTypeClass(ELEMENT_TYPE_VALUETYPE, yypvt[-0].token); } break; +case 664: +#line 1666 "asmparse.y" +{ yyval.binstr = parser->MakeTypeClass(ELEMENT_TYPE_VALUETYPE, yypvt[-0].token); } break; +case 665: +#line 1667 "asmparse.y" +{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_SZARRAY); } break; +case 666: +#line 1668 "asmparse.y" +{ yyval.binstr = parser->MakeTypeArray(ELEMENT_TYPE_ARRAY, yypvt[-3].binstr, yypvt[-1].binstr); } break; +case 667: +#line 1669 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_BYREF); } break; +case 668: +#line 1670 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_PTR); } break; +case 669: +#line 1671 "asmparse.y" +{ yyval.binstr = yypvt[-1].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_PINNED); } break; +case 670: +#line 1672 "asmparse.y" +{ yyval.binstr = parser->MakeTypeClass(ELEMENT_TYPE_CMOD_REQD, yypvt[-1].token); + yyval.binstr->append(yypvt[-4].binstr); } break; +case 671: +#line 1674 "asmparse.y" +{ yyval.binstr = parser->MakeTypeClass(ELEMENT_TYPE_CMOD_OPT, yypvt[-1].token); + yyval.binstr->append(yypvt[-4].binstr); } break; +case 672: +#line 1677 "asmparse.y" +{ yyval.binstr = parser->MakeSig(yypvt[-5].int32, yypvt[-4].binstr, yypvt[-1].binstr); + yyval.binstr->insertInt8(ELEMENT_TYPE_FNPTR); + PASM->delArgNameList(PASM->m_firstArgName); + PASM->m_firstArgName = parser->m_ANSFirst.POP(); + PASM->m_lastArgName = parser->m_ANSLast.POP(); + } break; +case 673: +#line 1683 "asmparse.y" +{ if(yypvt[-1].binstr == NULL) yyval.binstr = yypvt[-3].binstr; + else { + yyval.binstr = new BinStr(); + yyval.binstr->appendInt8(ELEMENT_TYPE_GENERICINST); + yyval.binstr->append(yypvt[-3].binstr); + corEmitInt(yyval.binstr, corCountArgs(yypvt[-1].binstr)); + yyval.binstr->append(yypvt[-1].binstr); delete yypvt[-3].binstr; delete yypvt[-1].binstr; }} break; +case 674: +#line 1690 "asmparse.y" +{ //if(PASM->m_pCurMethod) { + // if(($3 < 0)||((DWORD)$3 >= PASM->m_pCurMethod->m_NumTyPars)) + // PASM->report->error("Invalid method type parameter '%d'\n",$3); + yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_MVAR); corEmitInt(yyval.binstr, yypvt[-0].int32); + //} else PASM->report->error("Method type parameter '%d' outside method scope\n",$3); + } break; +case 675: +#line 1696 "asmparse.y" +{ //if(PASM->m_pCurClass) { + // if(($2 < 0)||((DWORD)$2 >= PASM->m_pCurClass->m_NumTyPars)) + // PASM->report->error("Invalid type parameter '%d'\n",$2); + yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_VAR); corEmitInt(yyval.binstr, yypvt[-0].int32); + //} else PASM->report->error("Type parameter '%d' outside class scope\n",$2); + } break; +case 676: +#line 1702 "asmparse.y" +{ int eltype = ELEMENT_TYPE_MVAR; + int n=-1; + if(PASM->m_pCurMethod) n = PASM->m_pCurMethod->FindTyPar(yypvt[-0].string); + else { + if(PASM->m_TyParList) n = PASM->m_TyParList->IndexOf(yypvt[-0].string); + if(n == -1) + { n = TyParFixupList.COUNT(); + TyParFixupList.PUSH(yypvt[-0].string); + eltype = ELEMENT_TYPE_MVARFIXUP; + } + } + if(n == -1) { PASM->report->error("Invalid method type parameter '%s'\n",yypvt[-0].string); + n = 0x1FFFFFFF; } + yyval.binstr = new BinStr(); yyval.binstr->appendInt8(eltype); corEmitInt(yyval.binstr,n); + } break; +case 677: +#line 1717 "asmparse.y" +{ int eltype = ELEMENT_TYPE_VAR; + int n=-1; + if(PASM->m_pCurClass && !newclass) n = PASM->m_pCurClass->FindTyPar(yypvt[-0].string); + else { + if(PASM->m_TyParList) n = PASM->m_TyParList->IndexOf(yypvt[-0].string); + if(n == -1) + { n = TyParFixupList.COUNT(); + TyParFixupList.PUSH(yypvt[-0].string); + eltype = ELEMENT_TYPE_VARFIXUP; + } + } + if(n == -1) { PASM->report->error("Invalid type parameter '%s'\n",yypvt[-0].string); + n = 0x1FFFFFFF; } + yyval.binstr = new BinStr(); yyval.binstr->appendInt8(eltype); corEmitInt(yyval.binstr,n); + } break; +case 678: +#line 1732 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_TYPEDBYREF); } break; +case 679: +#line 1733 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_VOID); } break; +case 680: +#line 1734 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I); } break; +case 681: +#line 1735 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U); } break; +case 682: +#line 1736 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U); } break; +case 683: +#line 1737 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 684: +#line 1738 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; yyval.binstr->insertInt8(ELEMENT_TYPE_SENTINEL); } break; +case 685: +#line 1741 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_CHAR); } break; +case 686: +#line 1742 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_STRING); } break; +case 687: +#line 1743 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_BOOLEAN); } break; +case 688: +#line 1744 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I1); } break; +case 689: +#line 1745 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I2); } break; +case 690: +#line 1746 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I4); } break; +case 691: +#line 1747 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_I8); } break; +case 692: +#line 1748 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R4); } break; +case 693: +#line 1749 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_R8); } break; +case 694: +#line 1750 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U1); } break; +case 695: +#line 1751 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U2); } break; +case 696: +#line 1752 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U4); } break; +case 697: +#line 1753 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U8); } break; +case 698: +#line 1754 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U1); } break; +case 699: +#line 1755 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U2); } break; +case 700: +#line 1756 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U4); } break; +case 701: +#line 1757 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt8(ELEMENT_TYPE_U8); } break; +case 702: +#line 1758 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->append(yypvt[-0].tdd->m_pbsTypeSpec); } break; +case 703: +#line 1761 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; } break; +case 704: +#line 1762 "asmparse.y" +{ yyval.binstr = yypvt[-2].binstr; yypvt[-2].binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; } break; +case 705: +#line 1765 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt32(0x7FFFFFFF); yyval.binstr->appendInt32(0x7FFFFFFF); } break; +case 706: +#line 1766 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt32(0x7FFFFFFF); yyval.binstr->appendInt32(0x7FFFFFFF); } break; +case 707: +#line 1767 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt32(0); yyval.binstr->appendInt32(yypvt[-0].int32); } break; +case 708: +#line 1768 "asmparse.y" +{ FAIL_UNLESS(yypvt[-2].int32 <= yypvt[-0].int32, ("lower bound %d must be <= upper bound %d\n", yypvt[-2].int32, yypvt[-0].int32)); + if (yypvt[-2].int32 > yypvt[-0].int32) { YYERROR; }; + yyval.binstr = new BinStr(); yyval.binstr->appendInt32(yypvt[-2].int32); yyval.binstr->appendInt32(yypvt[-0].int32-yypvt[-2].int32+1); } break; +case 709: +#line 1771 "asmparse.y" +{ yyval.binstr = new BinStr(); yyval.binstr->appendInt32(yypvt[-1].int32); yyval.binstr->appendInt32(0x7FFFFFFF); } break; +case 710: +#line 1776 "asmparse.y" +{ PASM->AddPermissionDecl(yypvt[-4].secAct, yypvt[-3].token, yypvt[-1].pair); } break; +case 711: +#line 1778 "asmparse.y" +{ PASM->AddPermissionDecl(yypvt[-5].secAct, yypvt[-4].token, yypvt[-1].binstr); } break; +case 712: +#line 1779 "asmparse.y" +{ PASM->AddPermissionDecl(yypvt[-1].secAct, yypvt[-0].token, (NVPair *)NULL); } break; +case 713: +#line 1780 "asmparse.y" +{ PASM->AddPermissionSetDecl(yypvt[-2].secAct, yypvt[-1].binstr); } break; +case 714: +#line 1782 "asmparse.y" +{ PASM->AddPermissionSetDecl(yypvt[-1].secAct,BinStrToUnicode(yypvt[-0].binstr,true));} break; +case 715: +#line 1784 "asmparse.y" +{ BinStr* ret = new BinStr(); + ret->insertInt8('.'); + corEmitInt(ret, nSecAttrBlobs); + ret->append(yypvt[-1].binstr); + PASM->AddPermissionSetDecl(yypvt[-4].secAct,ret); + nSecAttrBlobs = 0; } break; +case 716: +#line 1792 "asmparse.y" +{ yyval.binstr = new BinStr(); nSecAttrBlobs = 0;} break; +case 717: +#line 1793 "asmparse.y" +{ yyval.binstr = yypvt[-0].binstr; nSecAttrBlobs = 1; } break; +case 718: +#line 1794 "asmparse.y" +{ yyval.binstr = yypvt[-2].binstr; yyval.binstr->append(yypvt[-0].binstr); nSecAttrBlobs++; } break; +case 719: +#line 1798 "asmparse.y" +{ yyval.binstr = PASM->EncodeSecAttr(PASM->ReflectionNotation(yypvt[-4].token),yypvt[-1].binstr,nCustomBlobNVPairs); + nCustomBlobNVPairs = 0; } break; +case 720: +#line 1801 "asmparse.y" +{ yyval.binstr = PASM->EncodeSecAttr(yypvt[-4].string,yypvt[-1].binstr,nCustomBlobNVPairs); + nCustomBlobNVPairs = 0; } break; +case 721: +#line 1805 "asmparse.y" +{ yyval.secAct = yypvt[-2].secAct; bParsingByteArray = TRUE; } break; +case 722: +#line 1807 "asmparse.y" +{ yyval.secAct = yypvt[-2].secAct; bParsingByteArray = TRUE; } break; +case 723: +#line 1810 "asmparse.y" +{ yyval.pair = yypvt[-0].pair; } break; +case 724: +#line 1811 "asmparse.y" +{ yyval.pair = yypvt[-2].pair->Concat(yypvt[-0].pair); } break; +case 725: +#line 1814 "asmparse.y" +{ yypvt[-2].binstr->appendInt8(0); yyval.pair = new NVPair(yypvt[-2].binstr, yypvt[-0].binstr); } break; +case 726: +#line 1817 "asmparse.y" +{ yyval.int32 = 1; } break; +case 727: +#line 1818 "asmparse.y" +{ yyval.int32 = 0; } break; +case 728: +#line 1821 "asmparse.y" +{ yyval.binstr = new BinStr(); + yyval.binstr->appendInt8(SERIALIZATION_TYPE_BOOLEAN); + yyval.binstr->appendInt8(yypvt[-0].int32); } break; +case 729: +#line 1824 "asmparse.y" +{ yyval.binstr = new BinStr(); + yyval.binstr->appendInt8(SERIALIZATION_TYPE_I4); + yyval.binstr->appendInt32(yypvt[-0].int32); } break; +case 730: +#line 1827 "asmparse.y" +{ yyval.binstr = new BinStr(); + yyval.binstr->appendInt8(SERIALIZATION_TYPE_I4); + yyval.binstr->appendInt32(yypvt[-1].int32); } break; +case 731: +#line 1830 "asmparse.y" +{ yyval.binstr = new BinStr(); + yyval.binstr->appendInt8(SERIALIZATION_TYPE_STRING); + yyval.binstr->append(yypvt[-0].binstr); delete yypvt[-0].binstr; + yyval.binstr->appendInt8(0); } break; +case 732: +#line 1834 "asmparse.y" +{ yyval.binstr = new BinStr(); + yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); + char* sz = PASM->ReflectionNotation(yypvt[-5].token); + strcpy_s((char *)yyval.binstr->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); + yyval.binstr->appendInt8(1); + yyval.binstr->appendInt32(yypvt[-1].int32); } break; +case 733: +#line 1840 "asmparse.y" +{ yyval.binstr = new BinStr(); + yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); + char* sz = PASM->ReflectionNotation(yypvt[-5].token); + strcpy_s((char *)yyval.binstr->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); + yyval.binstr->appendInt8(2); + yyval.binstr->appendInt32(yypvt[-1].int32); } break; +case 734: +#line 1846 "asmparse.y" +{ yyval.binstr = new BinStr(); + yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); + char* sz = PASM->ReflectionNotation(yypvt[-5].token); + strcpy_s((char *)yyval.binstr->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); + yyval.binstr->appendInt8(4); + yyval.binstr->appendInt32(yypvt[-1].int32); } break; +case 735: +#line 1852 "asmparse.y" +{ yyval.binstr = new BinStr(); + yyval.binstr->appendInt8(SERIALIZATION_TYPE_ENUM); + char* sz = PASM->ReflectionNotation(yypvt[-3].token); + strcpy_s((char *)yyval.binstr->getBuff((unsigned)strlen(sz) + 1), strlen(sz) + 1,sz); + yyval.binstr->appendInt8(4); + yyval.binstr->appendInt32(yypvt[-1].int32); } break; +case 736: +#line 1860 "asmparse.y" +{ yyval.secAct = dclRequest; } break; +case 737: +#line 1861 "asmparse.y" +{ yyval.secAct = dclDemand; } break; +case 738: +#line 1862 "asmparse.y" +{ yyval.secAct = dclAssert; } break; +case 739: +#line 1863 "asmparse.y" +{ yyval.secAct = dclDeny; } break; +case 740: +#line 1864 "asmparse.y" +{ yyval.secAct = dclPermitOnly; } break; +case 741: +#line 1865 "asmparse.y" +{ yyval.secAct = dclLinktimeCheck; } break; +case 742: +#line 1866 "asmparse.y" +{ yyval.secAct = dclInheritanceCheck; } break; +case 743: +#line 1867 "asmparse.y" +{ yyval.secAct = dclRequestMinimum; } break; +case 744: +#line 1868 "asmparse.y" +{ yyval.secAct = dclRequestOptional; } break; +case 745: +#line 1869 "asmparse.y" +{ yyval.secAct = dclRequestRefuse; } break; +case 746: +#line 1870 "asmparse.y" +{ yyval.secAct = dclPrejitGrant; } break; +case 747: +#line 1871 "asmparse.y" +{ yyval.secAct = dclPrejitDenied; } break; +case 748: +#line 1872 "asmparse.y" +{ yyval.secAct = dclNonCasDemand; } break; +case 749: +#line 1873 "asmparse.y" +{ yyval.secAct = dclNonCasLinkDemand; } break; +case 750: +#line 1874 "asmparse.y" +{ yyval.secAct = dclNonCasInheritance; } break; +case 751: +#line 1878 "asmparse.y" +{ PASM->ResetLineNumbers(); nCurrPC = PASM->m_CurPC; PENV->bExternSource = TRUE; PENV->bExternSourceAutoincrement = FALSE; } break; +case 752: +#line 1879 "asmparse.y" +{ PASM->ResetLineNumbers(); nCurrPC = PASM->m_CurPC; PENV->bExternSource = TRUE; PENV->bExternSourceAutoincrement = TRUE; } break; +case 753: +#line 1882 "asmparse.y" +{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-1].int32; + PENV->nExtCol = 0; PENV->nExtColEnd = static_cast(-1); + PASM->SetSourceFileName(yypvt[-0].string);} break; +case 754: +#line 1885 "asmparse.y" +{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-0].int32; + PENV->nExtCol = 0; PENV->nExtColEnd = static_cast(-1); } break; +case 755: +#line 1887 "asmparse.y" +{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-3].int32; + PENV->nExtCol=yypvt[-1].int32; PENV->nExtColEnd = static_cast(-1); + PASM->SetSourceFileName(yypvt[-0].string);} break; +case 756: +#line 1890 "asmparse.y" +{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-2].int32; + PENV->nExtCol=yypvt[-0].int32; PENV->nExtColEnd = static_cast(-1);} break; +case 757: +#line 1893 "asmparse.y" +{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-5].int32; + PENV->nExtCol=yypvt[-3].int32; PENV->nExtColEnd = yypvt[-1].int32; + PASM->SetSourceFileName(yypvt[-0].string);} break; +case 758: +#line 1897 "asmparse.y" +{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-4].int32; + PENV->nExtCol=yypvt[-2].int32; PENV->nExtColEnd = yypvt[-0].int32; } break; +case 759: +#line 1900 "asmparse.y" +{ PENV->nExtLine = yypvt[-5].int32; PENV->nExtLineEnd = yypvt[-3].int32; + PENV->nExtCol=yypvt[-1].int32; PENV->nExtColEnd = static_cast(-1); + PASM->SetSourceFileName(yypvt[-0].string);} break; +case 760: +#line 1904 "asmparse.y" +{ PENV->nExtLine = yypvt[-4].int32; PENV->nExtLineEnd = yypvt[-2].int32; + PENV->nExtCol=yypvt[-0].int32; PENV->nExtColEnd = static_cast(-1); } break; +case 761: +#line 1907 "asmparse.y" +{ PENV->nExtLine = yypvt[-7].int32; PENV->nExtLineEnd = yypvt[-5].int32; + PENV->nExtCol=yypvt[-3].int32; PENV->nExtColEnd = yypvt[-1].int32; + PASM->SetSourceFileName(yypvt[-0].string);} break; +case 762: +#line 1911 "asmparse.y" +{ PENV->nExtLine = yypvt[-6].int32; PENV->nExtLineEnd = yypvt[-4].int32; + PENV->nExtCol=yypvt[-2].int32; PENV->nExtColEnd = yypvt[-0].int32; } break; +case 763: +#line 1913 "asmparse.y" +{ PENV->nExtLine = PENV->nExtLineEnd = yypvt[-1].int32 - 1; + PENV->nExtCol = 0; PENV->nExtColEnd = static_cast(-1); + PASM->SetSourceFileName(yypvt[-0].binstr);} break; +case 764: +#line 1920 "asmparse.y" +{ PASMM->AddFile(yypvt[-5].string, yypvt[-6].fileAttr|yypvt[-4].fileAttr|yypvt[-0].fileAttr, yypvt[-2].binstr); } break; +case 765: +#line 1921 "asmparse.y" +{ PASMM->AddFile(yypvt[-1].string, yypvt[-2].fileAttr|yypvt[-0].fileAttr, NULL); } break; +case 766: +#line 1924 "asmparse.y" +{ yyval.fileAttr = (CorFileFlags) 0; } break; +case 767: +#line 1925 "asmparse.y" +{ yyval.fileAttr = (CorFileFlags) (yypvt[-1].fileAttr | ffContainsNoMetaData); } break; +case 768: +#line 1928 "asmparse.y" +{ yyval.fileAttr = (CorFileFlags) 0; } break; +case 769: +#line 1929 "asmparse.y" +{ yyval.fileAttr = (CorFileFlags) 0x80000000; } break; +case 770: +#line 1932 "asmparse.y" +{ bParsingByteArray = TRUE; } break; +case 771: +#line 1935 "asmparse.y" +{ PASMM->StartAssembly(yypvt[-0].string, NULL, (DWORD)yypvt[-1].asmAttr, FALSE); } break; +case 772: +#line 1938 "asmparse.y" +{ yyval.asmAttr = (CorAssemblyFlags) 0; } break; +case 773: +#line 1939 "asmparse.y" +{ yyval.asmAttr = (CorAssemblyFlags) (yypvt[-1].asmAttr | afRetargetable); } break; +case 774: +#line 1940 "asmparse.y" +{ yyval.asmAttr = (CorAssemblyFlags) (yypvt[-1].asmAttr | afContentType_WindowsRuntime); } break; +case 775: +#line 1941 "asmparse.y" +{ yyval.asmAttr = (CorAssemblyFlags) (yypvt[-1].asmAttr | afPA_NoPlatform); } break; +case 776: +#line 1942 "asmparse.y" +{ yyval.asmAttr = yypvt[-2].asmAttr; } break; +case 777: +#line 1943 "asmparse.y" +{ SET_PA(yyval.asmAttr,yypvt[-1].asmAttr,afPA_MSIL); } break; +case 778: +#line 1944 "asmparse.y" +{ SET_PA(yyval.asmAttr,yypvt[-1].asmAttr,afPA_x86); } break; +case 779: +#line 1945 "asmparse.y" +{ SET_PA(yyval.asmAttr,yypvt[-1].asmAttr,afPA_IA64); } break; +case 780: +#line 1946 "asmparse.y" +{ SET_PA(yyval.asmAttr,yypvt[-1].asmAttr,afPA_AMD64); } break; +case 781: +#line 1947 "asmparse.y" +{ SET_PA(yyval.asmAttr,yypvt[-1].asmAttr,afPA_ARM); } break; +case 784: +#line 1954 "asmparse.y" +{ PASMM->SetAssemblyHashAlg(yypvt[-0].int32); } break; +case 787: +#line 1959 "asmparse.y" +{ yyval.int32 = yypvt[-0].int32; } break; +case 788: +#line 1960 "asmparse.y" +{ yyval.int32 = 0xFFFF; } break; +case 789: +#line 1963 "asmparse.y" +{ PASMM->SetAssemblyPublicKey(yypvt[-1].binstr); } break; +case 790: +#line 1965 "asmparse.y" +{ PASMM->SetAssemblyVer((USHORT)yypvt[-6].int32, (USHORT)yypvt[-4].int32, (USHORT)yypvt[-2].int32, (USHORT)yypvt[-0].int32); } break; +case 791: +#line 1966 "asmparse.y" +{ yypvt[-0].binstr->appendInt8(0); PASMM->SetAssemblyLocale(yypvt[-0].binstr,TRUE); } break; +case 792: +#line 1967 "asmparse.y" +{ PASMM->SetAssemblyLocale(yypvt[-1].binstr,FALSE); } break; +case 795: +#line 1972 "asmparse.y" +{ bParsingByteArray = TRUE; } break; +case 796: +#line 1975 "asmparse.y" +{ bParsingByteArray = TRUE; } break; +case 797: +#line 1978 "asmparse.y" +{ bParsingByteArray = TRUE; } break; +case 798: +#line 1982 "asmparse.y" +{ PASMM->StartAssembly(yypvt[-0].string, NULL, yypvt[-1].asmAttr, TRUE); } break; +case 799: +#line 1984 "asmparse.y" +{ PASMM->StartAssembly(yypvt[-2].string, yypvt[-0].string, yypvt[-3].asmAttr, TRUE); } break; +case 802: +#line 1991 "asmparse.y" +{ PASMM->SetAssemblyHashBlob(yypvt[-1].binstr); } break; +case 804: +#line 1993 "asmparse.y" +{ PASMM->SetAssemblyPublicKeyToken(yypvt[-1].binstr); } break; +case 805: +#line 1994 "asmparse.y" +{ PASMM->SetAssemblyAutodetect(); } break; +case 806: +#line 1997 "asmparse.y" +{ PASMM->StartComType(yypvt[-0].string, yypvt[-1].exptAttr);} break; +case 807: +#line 2000 "asmparse.y" +{ PASMM->StartComType(yypvt[-0].string, yypvt[-1].exptAttr); } break; +case 808: +#line 2003 "asmparse.y" +{ yyval.exptAttr = (CorTypeAttr) 0; } break; +case 809: +#line 2004 "asmparse.y" +{ yyval.exptAttr = (CorTypeAttr) (yypvt[-1].exptAttr | tdNotPublic); } break; +case 810: +#line 2005 "asmparse.y" +{ yyval.exptAttr = (CorTypeAttr) (yypvt[-1].exptAttr | tdPublic); } break; +case 811: +#line 2006 "asmparse.y" +{ yyval.exptAttr = (CorTypeAttr) (yypvt[-1].exptAttr | tdForwarder); } break; +case 812: +#line 2007 "asmparse.y" +{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedPublic); } break; +case 813: +#line 2008 "asmparse.y" +{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedPrivate); } break; +case 814: +#line 2009 "asmparse.y" +{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedFamily); } break; +case 815: +#line 2010 "asmparse.y" +{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedAssembly); } break; +case 816: +#line 2011 "asmparse.y" +{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedFamANDAssem); } break; +case 817: +#line 2012 "asmparse.y" +{ yyval.exptAttr = (CorTypeAttr) (yypvt[-2].exptAttr | tdNestedFamORAssem); } break; +case 820: +#line 2019 "asmparse.y" +{ PASMM->SetComTypeFile(yypvt[-0].string); } break; +case 821: +#line 2020 "asmparse.y" +{ PASMM->SetComTypeComType(yypvt[-0].string); } break; +case 822: +#line 2021 "asmparse.y" +{ PASMM->SetComTypeAsmRef(yypvt[-0].string); } break; +case 823: +#line 2022 "asmparse.y" +{ if(!PASMM->SetComTypeImplementationTok(yypvt[-1].int32)) + PASM->report->error("Invalid implementation of exported type\n"); } break; +case 824: +#line 2024 "asmparse.y" +{ if(!PASMM->SetComTypeClassTok(yypvt[-0].int32)) + PASM->report->error("Invalid TypeDefID of exported type\n"); } break; +case 827: +#line 2030 "asmparse.y" +{ PASMM->StartManifestRes(yypvt[-0].string, yypvt[-0].string, yypvt[-1].manresAttr); } break; +case 828: +#line 2032 "asmparse.y" +{ PASMM->StartManifestRes(yypvt[-2].string, yypvt[-0].string, yypvt[-3].manresAttr); } break; +case 829: +#line 2035 "asmparse.y" +{ yyval.manresAttr = (CorManifestResourceFlags) 0; } break; +case 830: +#line 2036 "asmparse.y" +{ yyval.manresAttr = (CorManifestResourceFlags) (yypvt[-1].manresAttr | mrPublic); } break; +case 831: +#line 2037 "asmparse.y" +{ yyval.manresAttr = (CorManifestResourceFlags) (yypvt[-1].manresAttr | mrPrivate); } break; +case 834: +#line 2044 "asmparse.y" +{ PASMM->SetManifestResFile(yypvt[-2].string, (ULONG)yypvt[-0].int32); } break; +case 835: +#line 2045 "asmparse.y" +{ PASMM->SetManifestResAsmRef(yypvt[-0].string); } break;/* End of actions */ +#line 329 "D:\\ProjectK3\\src\\tools\\devdiv\\x86\\yypars.c" + } + } + goto yystack; /* stack new state and value */ + } +#pragma warning(default:102) + + +#ifdef YYDUMP +YYLOCAL void YYNEAR YYPASCAL yydumpinfo(void) +{ + short stackindex; + short valindex; + + //dump yys + printf("short yys[%d] {\n", YYMAXDEPTH); + for (stackindex = 0; stackindex < YYMAXDEPTH; stackindex++){ + if (stackindex) + printf(", %s", stackindex % 10 ? "\0" : "\n"); + printf("%6d", yys[stackindex]); + } + printf("\n};\n"); + + //dump yyv + printf("YYSTYPE yyv[%d] {\n", YYMAXDEPTH); + for (valindex = 0; valindex < YYMAXDEPTH; valindex++){ + if (valindex) + printf(", %s", valindex % 5 ? "\0" : "\n"); + printf("%#*x", 3+sizeof(YYSTYPE), yyv[valindex]); + } + printf("\n};\n"); + } +#endif diff --git a/src/ildasm/dis.cpp b/src/ildasm/dis.cpp index ad5e5a7..371466f 100644 --- a/src/ildasm/dis.cpp +++ b/src/ildasm/dis.cpp @@ -475,7 +475,7 @@ void dumpOneEHInfo(DasmExceptionInfoClause* ehInfo, IMDInternalImport *pImport, /* if(ehInfo->GetFlags() & ERR_OUT_OF_CODE) { - sprintf(szString,"%s// WARNING: Boundary outside the method code",g_szAsmCodeIndent); + _snprintf_s(szString, _countof(szString), _TRUNCATE, "%s// WARNING: Boundary outside the method code",g_szAsmCodeIndent); printLine(GUICookie,szString); } */ @@ -863,8 +863,8 @@ BOOL SourceLinesHelper(void *GUICookie, LineCodeDescr* pLCD, __out_ecount(nSize) /* BOOL fHasEmbeddedSource=FALSE; ((ISymUnmanagedDocument*)(pParam->pLCD->FileToken))->HasEmbeddedSource(&fHasEmbeddedSource); - sprintf(szString,"%s// PDB has %sembedded source",g_szAsmCodeIndent, - fHasEmbeddedSource ? "" : "no "); + _snprintf_s(szString, _countof(szString), _TRUNCATE, "%s// PDB has %sembedded source",g_szAsmCodeIndent, + fHasEmbeddedSource ? "" : "no "); printLine(pParam->GUICookie,szString); */ } diff --git a/src/ildasm/dres.cpp b/src/ildasm/dres.cpp index 0f23fcc..53e1925 100644 --- a/src/ildasm/dres.cpp +++ b/src/ildasm/dres.cpp @@ -281,11 +281,11 @@ DWORD DumpResourceToFile(__in __nullterminated WCHAR* wzFileName) void* GUICookie = (void*)wzFileName; BYTE* pbData; printLine(GUICookie,""); - sprintf(szString,"// ========== Win32 Resource Entries (%d) ========",ulNumResNodes); + sprintf_s(szString, _countof(szString), "// ========== Win32 Resource Entries (%d) ========",ulNumResNodes); for(i=0; i < ulNumResNodes; i++) { printLine(GUICookie,""); - sprintf(szString,"// Res.# %d Type=0x%X Name=0x%X Lang=0x%X DataOffset=0x%X DataLength=%d", + sprintf_s(szString, _countof(szString), "// Res.# %d Type=0x%X Name=0x%X Lang=0x%X DataOffset=0x%X DataLength=%d", i+1, g_prResNodePtr[i]->ResHdr.dwTypeID, g_prResNodePtr[i]->ResHdr.dwNameID, diff --git a/src/ildasm/gui.cpp b/src/ildasm/gui.cpp index f5f141d..83501e6 100644 --- a/src/ildasm/gui.cpp +++ b/src/ildasm/gui.cpp @@ -2256,7 +2256,7 @@ void FindTextInListbox(HWND hwnd, FINDREPLACEW* lpfr) if(pos >= 0) { //char sz[32]; - //sprintf(sz,"%d:%d",strFind.chrg.cpMin,strFind.chrg.cpMax); + //sprintf_s(sz, _countof(sz), "%d:%d",strFind.chrg.cpMin,strFind.chrg.cpMax); //MessageBox(hwnd,sz,"Find",MB_OK); SendMessage(hwndLB,EM_SETSEL,(WPARAM)pos,(LPARAM)(pos+wcslen(lpfr->lpstrFindWhat))); } diff --git a/src/ildasm/windasm.cpp b/src/ildasm/windasm.cpp index d8a2881..57f779f 100644 --- a/src/ildasm/windasm.cpp +++ b/src/ildasm/windasm.cpp @@ -383,27 +383,29 @@ int ProcessOneArg(__in __nullterminated char* szArg, __out char** ppszObjFileNam } else if ((_stricmp(szOpt, "met") == 0)&&g_fTDC) { - if(g_fTDC) +#ifdef FEATURE_CORECLR + printf("Warning: 'METADATA' option is ignored for ildasm on CoreCLR.\n"); +#else + + char *pStr = EqualOrColon(szArg); + g_fDumpMetaInfo = TRUE; + if(pStr) { - char *pStr = EqualOrColon(szArg); - g_fDumpMetaInfo = TRUE; - if(pStr) - { - char szOptn[64]; - strncpy_s(szOptn, 64, pStr+1,10); - szOptn[3] = 0; // recognize metainfo specifier by first 3 chars - if (_stricmp(szOptn, "hex") == 0) g_ulMetaInfoFilter |= MDInfo::dumpMoreHex; - else if(_stricmp(szOptn, "csv") == 0) g_ulMetaInfoFilter |= MDInfo::dumpCSV; - else if(_stricmp(szOptn, "mdh") == 0) g_ulMetaInfoFilter |= MDInfo::dumpHeader; - else if(_stricmp(szOptn, "raw") == 0) g_ulMetaInfoFilter |= MDInfo::dumpRaw; - else if(_stricmp(szOptn, "hea") == 0) g_ulMetaInfoFilter |= MDInfo::dumpRawHeaps; - else if(_stricmp(szOptn, "sch") == 0) g_ulMetaInfoFilter |= MDInfo::dumpSchema; - else if(_stricmp(szOptn, "unr") == 0) g_ulMetaInfoFilter |= MDInfo::dumpUnsat; - else if(_stricmp(szOptn, "val") == 0) g_ulMetaInfoFilter |= MDInfo::dumpValidate; - else if(_stricmp(szOptn, "sta") == 0) g_ulMetaInfoFilter |= MDInfo::dumpStats; - else return -1; - } + char szOptn[64]; + strncpy_s(szOptn, 64, pStr+1,10); + szOptn[3] = 0; // recognize metainfo specifier by first 3 chars + if (_stricmp(szOptn, "hex") == 0) g_ulMetaInfoFilter |= MDInfo::dumpMoreHex; + else if(_stricmp(szOptn, "csv") == 0) g_ulMetaInfoFilter |= MDInfo::dumpCSV; + else if(_stricmp(szOptn, "mdh") == 0) g_ulMetaInfoFilter |= MDInfo::dumpHeader; + else if(_stricmp(szOptn, "raw") == 0) g_ulMetaInfoFilter |= MDInfo::dumpRaw; + else if(_stricmp(szOptn, "hea") == 0) g_ulMetaInfoFilter |= MDInfo::dumpRawHeaps; + else if(_stricmp(szOptn, "sch") == 0) g_ulMetaInfoFilter |= MDInfo::dumpSchema; + else if(_stricmp(szOptn, "unr") == 0) g_ulMetaInfoFilter |= MDInfo::dumpUnsat; + else if(_stricmp(szOptn, "val") == 0) g_ulMetaInfoFilter |= MDInfo::dumpValidate; + else if(_stricmp(szOptn, "sta") == 0) g_ulMetaInfoFilter |= MDInfo::dumpStats; + else return -1; } +#endif // FEATURE_CORECLR } else if (_stricmp(szOpt, "obj") == 0) { diff --git a/src/inc/CMakeLists.txt b/src/inc/CMakeLists.txt index 803ca3b..d38fa40 100644 --- a/src/inc/CMakeLists.txt +++ b/src/inc/CMakeLists.txt @@ -50,23 +50,22 @@ add_compile_options(/TC) else() -#The MIDL tool exists for Windows only, so for other systems, we have the prebuilt xxx_i.c files checked in +#The MIDL tool exists for Windows only, so for other systems, we have the prebuilt xxx_i.cpp files checked in # The prebuilt files contain extra '!_MIDL_USE_GUIDDEF_' after the #endif, but not in the comment. # In order to not to have to modify these prebuilt files, we disable the extra tokens warning. add_compile_options(-Wno-extra-tokens) - +add_compile_options(-D_MIDL_USE_GUIDDEF_) foreach(IDL_SOURCE IN LISTS CORGUIDS_IDL_SOURCES) get_filename_component(IDLNAME ${IDL_SOURCE} NAME_WE) - set(C_SOURCE ../pal/prebuilt/idl/${IDLNAME}_i.c) + set(C_SOURCE ../pal/prebuilt/idl/${IDLNAME}_i.cpp) list(APPEND CORGUIDS_SOURCES ${C_SOURCE}) endforeach(IDL_SOURCE) add_compile_options(-fPIC) - endif(WIN32) -# Compile *_i.c to lib +# Compile *_i.cpp to lib _add_library(corguids ${CORGUIDS_SOURCES}) # Binplace the inc files for packaging later. diff --git a/src/inc/bitposition.h b/src/inc/bitposition.h index 0f3831f..392d9a6 100644 --- a/src/inc/bitposition.h +++ b/src/inc/bitposition.h @@ -25,7 +25,11 @@ inline unsigned BitPosition(unsigned value) { _ASSERTE((value != 0) && ((value & (value-1)) == 0)); -#ifndef _TARGET_AMD64_ +#if defined(_TARGET_ARM_) && defined(__llvm__) + // use intrinsic functions for arm32 + // this is applied for LLVM only but it may work for some compilers + DWORD index = __builtin_clz(__builtin_arm_rbit(value)); +#elif !defined(_TARGET_AMD64_) const unsigned PRIME = 37; static const char hashTable[PRIME] = diff --git a/src/inc/clrconfigvalues.h b/src/inc/clrconfigvalues.h index d6a362e..a0183d2 100644 --- a/src/inc/clrconfigvalues.h +++ b/src/inc/clrconfigvalues.h @@ -477,6 +477,12 @@ RETAIL_CONFIG_DWORD_INFO(EXTERNAL_UseLegacyJit, W("useLegacyJit"), 0, "Set to 1 RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_DisableNativeImageLoadList, W("DisableNativeImageLoadList"), "Refuse to load native images corresponding to one of the assemblies on this semicolon-delimited list of assembly names.", CLRConfig::REGUTIL_default) #endif +#if defined(FEATURE_CORECLR) && defined(_TARGET_X86_) +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_UseWindowsX86CoreLegacyJit, W("UseWindowsX86CoreLegacyJit"), 0, "Set to 1 to do all JITing with compatjit.dll. Only applicable to Windows x86 .NET Core.") +#endif + +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_RequireLegacyJit, W("RequireLegacyJit"), 0, "Set to 1 to require the use of legacy JIT (via COMPlus_useLegacyJit=1 or COMPlus_UseWindowsX86CoreLegacyJit=1).") + CONFIG_STRING_INFO_EX(INTERNAL_JitValNumCSE, W("JitValNumCSE"), "Enables ValNum CSE for the specified methods", CLRConfig::REGUTIL_default) CONFIG_STRING_INFO_EX(INTERNAL_JitLexicalCSE, W("JitLexicalCSE"), "Enables Lexical CSE for the specified methods", CLRConfig::REGUTIL_default) CONFIG_DWORD_INFO_EX(INTERNAL_JitNoCSE, W("JitNoCSE"), 0, "", CLRConfig::REGUTIL_default) @@ -493,7 +499,7 @@ CONFIG_DWORD_INFO_EX(INTERNAL_JitNoStructPromotion, W("JitNoStructPromotion"), 0 CONFIG_DWORD_INFO_EX(INTERNAL_JitNoUnroll, W("JitNoUnroll"), 0, "", CLRConfig::REGUTIL_default) CONFIG_DWORD_INFO_EX(INTERNAL_JitNoMemoryBarriers, W("JitNoMemoryBarriers"), 0, "If 1, don't generate memory barriers", CLRConfig::REGUTIL_default) #ifdef FEATURE_ENABLE_NO_RANGE_CHECKS -RETAIL_CONFIG_DWORD_INFO(PRIVATE_JitNoRangeChks, W("JitNoRngChks"), 0, "If 1, don't generate range checks") +RETAIL_CONFIG_DWORD_INFO_EX(PRIVATE_JitNoRangeChks, W("JitNoRngChks"), 0, "If 1, don't generate range checks", CLRConfig::REGUTIL_default) #endif RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_JitOptimizeType, W("JitOptimizeType"), "") CONFIG_DWORD_INFO_EX(INTERNAL_JitOrder, W("JitOrder"), 0, "", CLRConfig::REGUTIL_default) @@ -551,7 +557,7 @@ CONFIG_DWORD_INFO_EX(INTERNAL_JitSplitFunctionSize, W("JitSplitFunctionSize"), 0 RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_JitRegisterFP, W("JitRegisterFP"), 3, "Control FP enregistration", CLRConfig::REGUTIL_default) RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitELTHookEnabled, W("JitELTHookEnabled"), 0, "On ARM, setting this will emit Enter/Leave/TailCall callbacks") CONFIG_DWORD_INFO_EX(INTERNAL_JitComponentUnitTests, W("JitComponentUnitTests"), 0, "Run JIT component unit tests", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO_EX(INTERNAL_JitMemStats, W("JitMemStats"), 0, "Display JIT memory usage statistics", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_JitMemStats, W("JitMemStats"), 0, "Display JIT memory usage statistics", CLRConfig::REGUTIL_default) CONFIG_DWORD_INFO_EX(INTERNAL_JitLoopHoistStats, W("JitLoopHoistStats"), 0, "Display JIT loop hoisting statistics", CLRConfig::REGUTIL_default) CONFIG_DWORD_INFO_EX(INTERNAL_JitDebugLogLoopCloning, W("JitDebugLogLoopCloning"), 0, "In debug builds log places where loop cloning optimizations are performed on the fast path.", CLRConfig::REGUTIL_default); CONFIG_DWORD_INFO_EX(INTERNAL_JitVNMapSelLimit, W("JitVNMapSelLimit"), 0, "If non-zero, assert if # of VNF_MapSelect applications considered reaches this", CLRConfig::REGUTIL_default) @@ -600,11 +606,11 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterDoLoopMethods, W("InterpreterDoLoop RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_InterpreterUseCaching, W("InterpreterUseCaching"), 1, "If non-zero, use the caching mechanism.", CLRConfig::REGUTIL_default) RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_InterpreterLooseRules, W("InterpreterLooseRules"), 1, "If non-zero, allow ECMA spec violations required by managed C++.", CLRConfig::REGUTIL_default) RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterPrintPostMortem, W("InterpreterPrintPostMortem"), 0, "Prints summary information about the execution to the console") -CONFIG_STRING_INFO_EX(INTERNAL_InterpreterLogFile, W("InterpreterLogFile"), "If non-null, append interpreter logging to this file, else use stdout", CLRConfig::REGUTIL_default) -CONFIG_DWORD_INFO(INTERNAL_DumpInterpreterStubs, W("DumpInterpreterStubs"), 0, "Prints all interpreter stubs that are created to the console") -CONFIG_DWORD_INFO(INTERNAL_TraceInterpreterEntries, W("TraceInterpreterEntries"), 0, "Logs entries to interpreted methods to the console") -CONFIG_DWORD_INFO(INTERNAL_TraceInterpreterIL, W("TraceInterpreterIL"), 0, "Logs individual instructions of interpreted methods to the console") -CONFIG_DWORD_INFO(INTERNAL_TraceInterpreterOstack, W("TraceInterpreterOstack"), 0, "Logs operand stack after each IL instruction of interpreted methods to the console") +RETAIL_CONFIG_STRING_INFO_EX(INTERNAL_InterpreterLogFile, W("InterpreterLogFile"), "If non-null, append interpreter logging to this file, else use stdout", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO(INTERNAL_DumpInterpreterStubs, W("DumpInterpreterStubs"), 0, "Prints all interpreter stubs that are created to the console") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TraceInterpreterEntries, W("TraceInterpreterEntries"), 0, "Logs entries to interpreted methods to the console") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TraceInterpreterIL, W("TraceInterpreterIL"), 0, "Logs individual instructions of interpreted methods to the console") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TraceInterpreterOstack, W("TraceInterpreterOstack"), 0, "Logs operand stack after each IL instruction of interpreted methods to the console") CONFIG_DWORD_INFO(INTERNAL_TraceInterpreterVerbose, W("TraceInterpreterVerbose"), 0, "Logs interpreter progress with detailed messages to the console") CONFIG_DWORD_INFO(INTERNAL_TraceInterpreterJITTransition, W("TraceInterpreterJITTransition"), 0, "Logs when the interpreter determines a method should be JITted") #endif @@ -1122,12 +1128,12 @@ CONFIG_DWORD_INFO_EX(INTERNAL_MscorsnLogging, W("MscorsnLogging"), 0, "Enables s RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_NativeImageRequire, W("NativeImageRequire"), 0, "", CLRConfig::REGUTIL_default) CONFIG_DWORD_INFO_EX(INTERNAL_NestedEhOom, W("NestedEhOom"), 0, "", CLRConfig::REGUTIL_default) RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_NO_SO_NOT_MAINLINE, W("NO_SO_NOT_MAINLINE"), 0, "", CLRConfig::REGUTIL_default) -#if defined(CROSSGEN_COMPILE) +#if defined(CROSSGEN_COMPILE) || defined(FEATURE_CORECLR) #define INTERNAL_NoGuiOnAssert_Default 1 #else #define INTERNAL_NoGuiOnAssert_Default 0 #endif -CONFIG_DWORD_INFO_EX(INTERNAL_NoGuiOnAssert, W("NoGuiOnAssert"), INTERNAL_NoGuiOnAssert_Default, "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_NoGuiOnAssert, W("NoGuiOnAssert"), INTERNAL_NoGuiOnAssert_Default, "", CLRConfig::REGUTIL_default) RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_NoProcedureSplitting, W("NoProcedureSplitting"), 0, "", CLRConfig::REGUTIL_default) CONFIG_DWORD_INFO_EX(INTERNAL_NoStringInterning, W("NoStringInterning"), 1, "Disallows string interning. I see no value in it anymore.", CLRConfig::REGUTIL_default) RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_NotifyBadAppCfg, W("NotifyBadAppCfg"), "Whether to show a message box for bad application config file.") diff --git a/src/inc/clrnt.h b/src/inc/clrnt.h index c15bd48..0e082c7 100644 --- a/src/inc/clrnt.h +++ b/src/inc/clrnt.h @@ -835,17 +835,17 @@ RtlVirtualUnwind_Unsafe( // X86 // -#if defined(_TARGET_X86_) - -#pragma warning(push) -#pragma warning (disable:4035) // disable 4035 (function must return something) -#define PcTeb 0x18 -#pragma warning(pop) +#ifdef _TARGET_X86_ +#ifndef FEATURE_PAL typedef struct _DISPATCHER_CONTEXT { _EXCEPTION_REGISTRATION_RECORD* RegistrationPointer; } DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; +#endif // !FEATURE_PAL + +#define RUNTIME_FUNCTION__BeginAddress(prf) (prf)->BeginAddress + #endif // _TARGET_X86_ #ifdef _TARGET_ARM_ diff --git a/src/inc/corcompile.h b/src/inc/corcompile.h index 70db9f1..3b517ae 100644 --- a/src/inc/corcompile.h +++ b/src/inc/corcompile.h @@ -72,6 +72,7 @@ typedef DPTR(struct CORCOMPILE_IMPORT_SECTION) PTR_CORCOMPILE_IMPORT_SECTION; #ifdef _TARGET_X86_ +#ifndef FEATURE_PAL // // x86 ABI does not define RUNTIME_FUNCTION. Define our own to allow unification between x86 and other platforms. // @@ -80,14 +81,15 @@ typedef struct _RUNTIME_FUNCTION { DWORD UnwindData; } RUNTIME_FUNCTION, *PRUNTIME_FUNCTION; +#endif // !FEATURE_PAL + typedef DPTR(RUNTIME_FUNCTION) PTR_RUNTIME_FUNCTION; -#define RUNTIME_FUNCTION__BeginAddress(prf) (prf)->BeginAddress // Chained unwind info. Used for cold methods. #define RUNTIME_FUNCTION_INDIRECT 0x80000000 -#endif +#endif // _TARGET_X86_ // The stride is choosen as maximum value that still gives good page locality of RUNTIME_FUNCTION table touches (only one page of // RUNTIME_FUNCTION table is going to be touched during most IP2MD lookups). @@ -1164,7 +1166,7 @@ enum CorCompileILRegion class ICorCompilePreloader { public: - typedef void (__stdcall *CORCOMPILE_CompileStubCallback)(LPVOID pContext, CORINFO_METHOD_HANDLE hStub, DWORD dwJitFlags); + typedef void (__stdcall *CORCOMPILE_CompileStubCallback)(LPVOID pContext, CORINFO_METHOD_HANDLE hStub, CORJIT_FLAGS jitFlags); // // Map methods are available after Serialize() is called @@ -1849,7 +1851,7 @@ class ICorCompileInfo // Get the compilation flags that are shared between JIT and NGen virtual HRESULT GetBaseJitFlags( IN CORINFO_METHOD_HANDLE hMethod, - OUT DWORD *pFlags) = 0; + OUT CORJIT_FLAGS *pFlags) = 0; // needed for stubs to obtain the number of bytes to copy into the native image // return the beginning of the stub and the size to copy (in bytes) @@ -1887,16 +1889,16 @@ class ICorCompileInfo /*****************************************************************************/ // This function determines the compile flags to use for a generic intatiation // since only the open instantiation can be verified. -// See the comment associated with CORJIT_FLG_SKIP_VERIFICATION for details. +// See the comment associated with CORJIT_FLAG_SKIP_VERIFICATION for details. // // On return: // if *raiseVerificationException=TRUE, the caller should raise a VerificationException. // if *unverifiableGenericCode=TRUE, the method is a generic instantiation with // unverifiable code -CorJitFlag GetCompileFlagsIfGenericInstantiation( +CORJIT_FLAGS GetCompileFlagsIfGenericInstantiation( CORINFO_METHOD_HANDLE method, - CorJitFlag compileFlags, + CORJIT_FLAGS compileFlags, ICorJitInfo * pCorJitInfo, BOOL * raiseVerificationException, BOOL * unverifiableGenericCode); diff --git a/src/inc/cordebug.idl b/src/inc/cordebug.idl index 49b8acc..093b893 100644 --- a/src/inc/cordebug.idl +++ b/src/inc/cordebug.idl @@ -177,6 +177,7 @@ interface ICorDebugTypeEnum; interface ICorDebugCodeEnum; interface ICorDebugFrameEnum; interface ICorDebugValueEnum; +interface ICorDebugVariableHomeEnum; interface ICorDebugAppDomainEnum; interface ICorDebugAssemblyEnum; interface ICorDebugBlockingObjectEnum; @@ -5594,6 +5595,23 @@ interface ICorDebugCode3 : IUnknown [out, size_is(bufferSize), length_is(*pFetched)] ULONG32 pOffsets[]); }; +[ + object, + local, + uuid(18221fa4-20cb-40fa-b19d-9f91c4fa8c14), + pointer_default(unique) +] +interface ICorDebugCode4 : IUnknown +{ + /* + * EnumerateVariableHomes - gives an enum for local variables and arguments + * in the function. + * This may include multiple ICorDebugVariableHomes for the same slot or + * argument index if they have different homes at different points in the + * function. + */ + HRESULT EnumerateVariableHomes([out] ICorDebugVariableHomeEnum **ppEnum); +} [ object, @@ -6488,8 +6506,79 @@ interface ICorDebugArrayValue : ICorDebugHeapValue [out] ICorDebugValue **ppValue); }; +[ + object, + local, + uuid(50847b8d-f43f-41b0-924c-6383a5f2278b), + pointer_default(unique) +] +interface ICorDebugVariableHome : IUnknown +{ + /* + * GetCode - gives the ICorDebugCode instance containing this + * ICorDebugVariableHome. + */ + HRESULT GetCode([out] ICorDebugCode **ppCode); + /* + * GetSlotIndex - gives the managed slot-index of a local variable. + * The slot-index can be used to retrieve the metadata for this local. + * Returns E_FAIL if the variable is a function argument. + */ + HRESULT GetSlotIndex([out] ULONG32 *pSlotIndex); + + /* + * GetArgumentIndex - gives the argument index of a function argument. + * The argument index can be used to retrieve the metadata for this + * argument. + * Returns E_FAIL if the variable is a local variable. + */ + HRESULT GetArgumentIndex([out] ULONG32* pArgumentIndex); -/* + /* + * GetLiveRange - gives the native range over which this variable is live. + * pStartOffset is the logical offset at which the variable is first live. + * pEndOffset is the logical offset immediately after that at which the + * variable is last live. + */ + HRESULT GetLiveRange([out] ULONG32* pStartOffset, + [out] ULONG32 *pEndOffset); + + typedef enum VariableLocationType + { + VLT_REGISTER, // variable is in a register + VLT_REGISTER_RELATIVE, // variable is in a register-relative memory + // location + VLT_INVALID + } VariableLocationType; + + /* + * GetLocationType - gives the type of native location. See + * VariableLocationType. + * Returns VLT_INVALID if the variable is not stored in a register or in a + * register-relative memory location. + */ + HRESULT GetLocationType([out] VariableLocationType *pLocationType); + + /* + * GetRegister - gives the register containing the variables with location + * type VLT_REGISTER, and the base register for variables with location + * type VLT_REGISTER_RELATIVE. + * Returns E_FAIL if the variable is not in a register or in a + * register-relative location. + */ + HRESULT GetRegister([out] CorDebugRegister *pRegister); + + /* + * GetOffset - gives the offset from the base register for a variable. + * Returns E_FAIL if the variable is not in a register-relative memory + * location. + */ + HRESULT GetOffset([out] LONG *pOffset); +} + + + +/* * ICorDebugHandleValue represents a reference value that the debugger has * explicitly created a GC handle to. It does not represent GC Handles in the debuggee process, @@ -6802,6 +6891,28 @@ interface ICorDebugValueEnum : ICorDebugEnum [ object, local, + uuid(e76b7a57-4f7a-4309-85a7-5d918c3deaf7), + pointer_default(unique) +] +interface ICorDebugVariableHomeEnum : ICorDebugEnum +{ + /* + * Next - gives the specified number of ICorDebugVariableHome instances from + * the enumeration, starting at the current position. + * celt is the number of requested instances. + * pceltFetched is the number of instances retrieved. + * returns S_FALSE if the actual number of instances retrieved is smaller + * than the number of instances requested. + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + ICorDebugVariableHome *homes[], + [out] ULONG *pceltFetched); +}; + +[ + object, + local, uuid(55E96461-9645-45e4-A2FF-0367877ABCDE), pointer_default(unique) ] @@ -6951,6 +7062,28 @@ interface ICorDebugType : IUnknown }; +[ + object, + local, + uuid(e6e91d79-693d-48bc-b417-8284b4f10fb5), + pointer_default(unique) +] +interface ICorDebugType2 : IUnknown +{ + /* + * GetTypeID - gives a COR_TYPEID for the ICorDebugType. This + * provides a mapping from the ICorDebugType, which represents a + * type that may or may not have been loaded into the runtime, to + * a COR_TYPEID, which serves as an opaque handle identifying a + * type loaded into the runtime. When the type that the + * ICorDebugType represents has not yet been loaded, this returns + * CORDBG_E_CLASS_NOT_LOADED. Returns CORDBG_E_UNSUPPORTED for + * unsupported types. + */ + HRESULT GetTypeID([out] COR_TYPEID *id); +}; + + /* ------------------------------------------------------------------------- * * DEPRECATED * diff --git a/src/inc/corinfo.h b/src/inc/corinfo.h index 6e41d8e..e899a23 100644 --- a/src/inc/corinfo.h +++ b/src/inc/corinfo.h @@ -231,11 +231,11 @@ TODO: Talk about initializing strutures before use #if COR_JIT_EE_VERSION > 460 // Update this one -SELECTANY const GUID JITEEVersionIdentifier = { /* 0b17dfeb-1ead-4e06-b025-d60d3a493b53 */ - 0x0b17dfeb, - 0x1ead, - 0x4e06, - { 0xb0, 0x25, 0xd6, 0x0d, 0x3a, 0x49, 0x3b, 0x53 } +SELECTANY const GUID JITEEVersionIdentifier = { /* 4bd06266-8ef7-4172-bec6-d3149fde7859 */ + 0x4bd06266, + 0x8ef7, + 0x4172, + {0xbe, 0xc6, 0xd3, 0x14, 0x9f, 0xde, 0x78, 0x59} }; #else @@ -642,6 +642,7 @@ enum CorInfoHelpFunc #if COR_JIT_EE_VERSION > 460 CORINFO_HELP_READYTORUN_GENERIC_HANDLE, CORINFO_HELP_READYTORUN_DELEGATE_CTOR, + CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE, #else #define CORINFO_HELP_READYTORUN_DELEGATE_CTOR CORINFO_HELP_EE_PRESTUB #endif // COR_JIT_EE_VERSION @@ -910,10 +911,12 @@ enum CORINFO_ACCESS_FLAGS // These are the flags set on an CORINFO_EH_CLAUSE enum CORINFO_EH_CLAUSE_FLAGS { - CORINFO_EH_CLAUSE_NONE = 0, - CORINFO_EH_CLAUSE_FILTER = 0x0001, // If this bit is on, then this EH entry is for a filter - CORINFO_EH_CLAUSE_FINALLY = 0x0002, // This clause is a finally clause - CORINFO_EH_CLAUSE_FAULT = 0x0004, // This clause is a fault clause + CORINFO_EH_CLAUSE_NONE = 0, + CORINFO_EH_CLAUSE_FILTER = 0x0001, // If this bit is on, then this EH entry is for a filter + CORINFO_EH_CLAUSE_FINALLY = 0x0002, // This clause is a finally clause + CORINFO_EH_CLAUSE_FAULT = 0x0004, // This clause is a fault clause + CORINFO_EH_CLAUSE_DUPLICATE = 0x0008, // Duplicated clause. This clause was duplicated to a funclet which was pulled out of line + CORINFO_EH_CLAUSE_SAMETRY = 0x0010, // This clause covers same try block as the previous one. (Used by CoreRT ABI.) }; // This enumeration is passed to InternalThrow @@ -1706,6 +1709,9 @@ enum CORINFO_FIELD_ACCESSOR CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER, // static field access using the "generic static" helper (argument is MethodTable *) CORINFO_FIELD_STATIC_ADDR_HELPER, // static field accessed using address-of helper (argument is FieldDesc *) CORINFO_FIELD_STATIC_TLS, // unmanaged TLS access +#if COR_JIT_EE_VERSION > 460 + CORINFO_FIELD_STATIC_READYTORUN_HELPER, // static field access using a runtime lookup helper +#endif CORINFO_FIELD_INTRINSIC_ZERO, // intrinsic zero (IntPtr.Zero, UIntPtr.Zero) CORINFO_FIELD_INTRINSIC_EMPTY_STRING, // intrinsic emptry string (String.Empty) @@ -2631,7 +2637,7 @@ public: // in the code are. The native compiler will ensure that these places // have a corresponding break point in native code. // - // Note that unless CORJIT_FLG_DEBUG_CODE is specified, this function will + // Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will // be used only as a hint and the native compiler should not change its // code generation. virtual void getBoundaries( @@ -2661,7 +2667,7 @@ public: // under debugging, the JIT needs to keep them live over their // entire scope so that they can be inspected. // - // Note that unless CORJIT_FLG_DEBUG_CODE is specified, this function will + // Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will // be used only as a hint and the native compiler should not change its // code generation. virtual void getVars( diff --git a/src/inc/corjit.h b/src/inc/corjit.h index e4deabd..6d01b9f 100644 --- a/src/inc/corjit.h +++ b/src/inc/corjit.h @@ -73,6 +73,8 @@ enum CorJitResult }; +#if COR_JIT_EE_VERSION <= 460 + /* values for flags in compileMethod */ enum CorJitFlag @@ -133,21 +135,11 @@ enum CorJitFlag CORJIT_FLG_ALIGN_LOOPS = 0x20000000, // add NOPs before loops to align them at 16 byte boundaries CORJIT_FLG_PUBLISH_SECRET_PARAM= 0x40000000, // JIT must place stub secret param into local 0. (used by IL stubs) CORJIT_FLG_GCPOLL_INLINE = 0x80000000, // JIT must inline calls to GCPoll when possible - -#if COR_JIT_EE_VERSION > 460 - CORJIT_FLG_CALL_GETJITFLAGS = 0xffffffff, // Indicates that the JIT should retrieve flags in the form of a - // pointer to a CORJIT_FLAGS value via ICorJitInfo::getJitFlags(). -#endif }; enum CorJitFlag2 { CORJIT_FLG2_SAMPLING_JIT_BACKGROUND = 0x00000001, // JIT is being invoked as a result of stack sampling for hot methods in the background -#if COR_JIT_EE_VERSION > 460 - CORJIT_FLG2_USE_PINVOKE_HELPERS = 0x00000002, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions - CORJIT_FLG2_REVERSE_PINVOKE = 0x00000004, // The JIT should insert REVERSE_PINVOKE_{ENTER,EXIT} helpers into method prolog/epilog - CORJIT_FLG2_DESKTOP_QUIRKS = 0x00000008, // The JIT should generate desktop-quirk-compatible code -#endif }; struct CORJIT_FLAGS @@ -156,11 +148,157 @@ struct CORJIT_FLAGS unsigned corJitFlags2; // Values are from CorJitFlag2 }; +#endif // COR_JIT_EE_VERSION <= 460 + +#if COR_JIT_EE_VERSION > 460 + +class CORJIT_FLAGS +{ +public: + + enum CorJitFlag + { + CORJIT_FLAG_CALL_GETJITFLAGS = 0xffffffff, // Indicates that the JIT should retrieve flags in the form of a + // pointer to a CORJIT_FLAGS value via ICorJitInfo::getJitFlags(). + CORJIT_FLAG_SPEED_OPT = 0, + CORJIT_FLAG_SIZE_OPT = 1, + CORJIT_FLAG_DEBUG_CODE = 2, // generate "debuggable" code (no code-mangling optimizations) + CORJIT_FLAG_DEBUG_EnC = 3, // We are in Edit-n-Continue mode + CORJIT_FLAG_DEBUG_INFO = 4, // generate line and local-var info + CORJIT_FLAG_MIN_OPT = 5, // disable all jit optimizations (not necesarily debuggable code) + CORJIT_FLAG_GCPOLL_CALLS = 6, // Emit calls to JIT_POLLGC for thread suspension. + CORJIT_FLAG_MCJIT_BACKGROUND = 7, // Calling from multicore JIT background thread, do not call JitComplete + + #if defined(_TARGET_X86_) + + CORJIT_FLAG_PINVOKE_RESTORE_ESP = 8, // Restore ESP after returning from inlined PInvoke + CORJIT_FLAG_TARGET_P4 = 9, + CORJIT_FLAG_USE_FCOMI = 10, // Generated code may use fcomi(p) instruction + CORJIT_FLAG_USE_CMOV = 11, // Generated code may use cmov instruction + CORJIT_FLAG_USE_SSE2 = 12, // Generated code may use SSE-2 instructions + + #else // !defined(_TARGET_X86_) + + CORJIT_FLAG_UNUSED1 = 8, + CORJIT_FLAG_UNUSED2 = 9, + CORJIT_FLAG_UNUSED3 = 10, + CORJIT_FLAG_UNUSED4 = 11, + CORJIT_FLAG_UNUSED5 = 12, + + #endif // !defined(_TARGET_X86_) + + #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) + + CORJIT_FLAG_USE_SSE3_4 = 13, + CORJIT_FLAG_USE_AVX = 14, + CORJIT_FLAG_USE_AVX2 = 15, + CORJIT_FLAG_USE_AVX_512 = 16, + CORJIT_FLAG_FEATURE_SIMD = 17, + + #else // !defined(_TARGET_X86_) && !defined(_TARGET_AMD64_) + + CORJIT_FLAG_UNUSED6 = 13, + CORJIT_FLAG_UNUSED7 = 14, + CORJIT_FLAG_UNUSED8 = 15, + CORJIT_FLAG_UNUSED9 = 16, + CORJIT_FLAG_UNUSED10 = 17, + + #endif // !defined(_TARGET_X86_) && !defined(_TARGET_AMD64_) + + CORJIT_FLAG_MAKEFINALCODE = 18, // Use the final code generator, i.e., not the interpreter. + CORJIT_FLAG_READYTORUN = 19, // Use version-resilient code generation + CORJIT_FLAG_PROF_ENTERLEAVE = 20, // Instrument prologues/epilogues + CORJIT_FLAG_PROF_REJIT_NOPS = 21, // Insert NOPs to ensure code is re-jitable + CORJIT_FLAG_PROF_NO_PINVOKE_INLINE = 22, // Disables PInvoke inlining + CORJIT_FLAG_SKIP_VERIFICATION = 23, // (lazy) skip verification - determined without doing a full resolve. See comment below + CORJIT_FLAG_PREJIT = 24, // jit or prejit is the execution engine. + CORJIT_FLAG_RELOC = 25, // Generate relocatable code + CORJIT_FLAG_IMPORT_ONLY = 26, // Only import the function + CORJIT_FLAG_IL_STUB = 27, // method is an IL stub + CORJIT_FLAG_PROCSPLIT = 28, // JIT should separate code into hot and cold sections + CORJIT_FLAG_BBINSTR = 29, // Collect basic block profile information + CORJIT_FLAG_BBOPT = 30, // Optimize method based on profile information + CORJIT_FLAG_FRAMED = 31, // All methods have an EBP frame + CORJIT_FLAG_ALIGN_LOOPS = 32, // add NOPs before loops to align them at 16 byte boundaries + CORJIT_FLAG_PUBLISH_SECRET_PARAM = 33, // JIT must place stub secret param into local 0. (used by IL stubs) + CORJIT_FLAG_GCPOLL_INLINE = 34, // JIT must inline calls to GCPoll when possible + CORJIT_FLAG_SAMPLING_JIT_BACKGROUND = 35, // JIT is being invoked as a result of stack sampling for hot methods in the background + CORJIT_FLAG_USE_PINVOKE_HELPERS = 36, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions + CORJIT_FLAG_REVERSE_PINVOKE = 37, // The JIT should insert REVERSE_PINVOKE_{ENTER,EXIT} helpers into method prolog/epilog + CORJIT_FLAG_DESKTOP_QUIRKS = 38, // The JIT should generate desktop-quirk-compatible code + }; + + CORJIT_FLAGS() + : corJitFlags(0) + { + // empty + } + + // Convenience constructor to set exactly one flag. + CORJIT_FLAGS(CorJitFlag flag) + : corJitFlags(0) + { + Set(flag); + } + + CORJIT_FLAGS(const CORJIT_FLAGS& other) + { + corJitFlags = other.corJitFlags; + } + + void Reset() + { + corJitFlags = 0; + } + + void Set(CorJitFlag flag) + { + corJitFlags |= 1ULL << (unsigned __int64)flag; + } + + void Clear(CorJitFlag flag) + { + corJitFlags &= ~(1ULL << (unsigned __int64)flag); + } + + bool IsSet(CorJitFlag flag) const + { + return (corJitFlags & (1ULL << (unsigned __int64)flag)) != 0; + } + + void Add(const CORJIT_FLAGS& other) + { + corJitFlags |= other.corJitFlags; + } + + void Remove(const CORJIT_FLAGS& other) + { + corJitFlags &= ~other.corJitFlags; + } + + bool IsEmpty() const + { + return corJitFlags == 0; + } + + // DO NOT USE THIS FUNCTION! (except in very restricted special cases) + unsigned __int64 GetFlagsRaw() + { + return corJitFlags; + } + +private: + + unsigned __int64 corJitFlags; +}; + +#endif // COR_JIT_EE_VERSION > 460 + /***************************************************************************** -Here is how CORJIT_FLG_SKIP_VERIFICATION should be interepreted. +Here is how CORJIT_FLAG_SKIP_VERIFICATION should be interepreted. Note that even if any method is inlined, it need not be verified. -if (CORJIT_FLG_SKIP_VERIFICATION is passed in to ICorJitCompiler::compileMethod()) +if (CORJIT_FLAG_SKIP_VERIFICATION is passed in to ICorJitCompiler::compileMethod()) { No verification needs to be done. Just compile the method, generating unverifiable code if necessary @@ -245,7 +383,7 @@ else case INSTVER_GENERIC_PASSED_VERIFICATION: { - This cannot ever happen because the VM would pass in CORJIT_FLG_SKIP_VERIFICATION. + This cannot ever happen because the VM would pass in CORJIT_FLAG_SKIP_VERIFICATION. } case INSTVER_GENERIC_FAILED_VERIFICATION: @@ -260,7 +398,7 @@ else case CORINFO_VERIFICATION_CAN_SKIP: { - This cannot ever happen because the CLR would pass in CORJIT_FLG_SKIP_VERIFICATION. + This cannot ever happen because the CLR would pass in CORJIT_FLAG_SKIP_VERIFICATION. } case CORINFO_VERIFICATION_RUNTIME_CHECK: @@ -377,7 +515,11 @@ public: // When the EE loads the System.Numerics.Vectors assembly, it asks the JIT what length (in bytes) of // SIMD vector it supports as an intrinsic type. Zero means that the JIT does not support SIMD // intrinsics, so the EE should use the default size (i.e. the size of the IL implementation). +#if COR_JIT_EE_VERSION > 460 + virtual unsigned getMaxIntrinsicSIMDVectorLength(CORJIT_FLAGS cpuCompileFlags) { return 0; } +#else virtual unsigned getMaxIntrinsicSIMDVectorLength(DWORD cpuCompileFlags) { return 0; } +#endif // IL obfuscators sometimes interpose on the EE-JIT interface. This function allows the VM to // tell the JIT to use a particular ICorJitCompiler to implement the methods of this interface, diff --git a/src/inc/corprof.idl b/src/inc/corprof.idl index 4288897..9af1cd9 100644 --- a/src/inc/corprof.idl +++ b/src/inc/corprof.idl @@ -60,6 +60,10 @@ cpp_quote("#endif") typedef const BYTE *LPCBYTE; typedef BYTE *LPBYTE; +typedef BYTE COR_SIGNATURE; +typedef COR_SIGNATURE* PCOR_SIGNATURE; +typedef const COR_SIGNATURE* PCCOR_SIGNATURE; + #endif @@ -2375,6 +2379,36 @@ interface ICorProfilerCallback7 : ICorProfilerCallback6 } +[ + object, + uuid(5BED9B15-C079-4D47-BFE2-215A140C07E0), + pointer_default(unique), + local +] +interface ICorProfilerCallback8 : ICorProfilerCallback7 +{ + // This event is triggered whenever a dynamic method is jit compiled. + // These include various IL Stubs and LCG Methods. + // The goal is to provide profiler writers with enough information to identify + // it to users as beyond unknown code addresses. + // Note: FunctionID's provided here cannot be used to resolve to their metadata + // tokens since dynamic methods have no metadata. + // + // Documentation Note: pILHeader is only valid during the callback + + HRESULT DynamicMethodJITCompilationStarted( + [in] FunctionID functionId, + [in] BOOL fIsSafeToBlock, + [in] LPCBYTE pILHeader, + [in] ULONG cbILHeader); + + HRESULT DynamicMethodJITCompilationFinished( + [in] FunctionID functionId, + [in] HRESULT hrStatus, + [in] BOOL fIsSafeToBlock); +} + + /* * COR_PRF_CODEGEN_FLAGS controls various flags and hooks for a specific * method. A combination of COR_PRF_CODEGEN_FLAGS is provided by the @@ -3781,6 +3815,59 @@ interface ICorProfilerInfo7 : ICorProfilerInfo6 }; +[ + object, + uuid(C5AC80A6-782E-4716-8044-39598C60CFBF), + pointer_default(unique), + local +] +interface ICorProfilerInfo8 : ICorProfilerInfo7 +{ + /* + * Determines if a function has associated metadata + * + * Certain methods like IL Stubs or LCG Methods do not have + * associated metadata that can be retrieved using the IMetaDataImport APIs. + * + * Such methods can be encountered by profilers through instruction pointers + * or by listening to ICorProfilerCallback::DynamicMethodJITCompilationStarted + * + * This API can be used to determine whether a FunctionID is dynamic. + */ + HRESULT IsFunctionDynamic( [in] FunctionID functionId, + [out] BOOL *isDynamic); + + /* + * Maps a managed code instruction pointer to a FunctionID. + * + * GetFunctionFromIP2 fails for dynamic methods, this method works for + * both dynamic and non-dynamic methods. It is a superset of GetFunctionFromIP2 + */ + HRESULT GetFunctionFromIP3([in] LPCBYTE ip, + [out] FunctionID *functionId, + [out] ReJITID * pReJitId); + + /* + * Retrieves informaiton about dynamic methods + * + * Certain methods like IL Stubs or LCG do not have + * associated metadata that can be retrieved using the IMetaDataImport APIs. + * + * Such methods can be encountered by profilers through instruction pointers + * or by listening to ICorProfilerCallback::DynamicMethodJITCompilationStarted + * + * This API can be used to retrieve information about dynamic methods + * including a friendly name if available. + */ + HRESULT GetDynamicFunctionInfo( [in] FunctionID functionId, + [out] ModuleID *moduleId, + [out] PCCOR_SIGNATURE *ppvSig, + [out] ULONG *pbSig, + [in] ULONG cchName, + [out] ULONG *pcchName, + [out] WCHAR wszName[]); +}; + /* * This interface lets you iterate over methods in the runtime. */ diff --git a/src/inc/daccess.h b/src/inc/daccess.h index b4c5044..6d9fb32 100644 --- a/src/inc/daccess.h +++ b/src/inc/daccess.h @@ -774,18 +774,18 @@ interface IMDInternalImport* DacGetMDImport(const ReflectionModule* reflectionMo int DacGetIlMethodSize(TADDR methAddr); struct COR_ILMETHOD* DacGetIlMethod(TADDR methAddr); -#if defined(WIN64EXCEPTIONS) +#ifdef WIN64EXCEPTIONS struct _UNWIND_INFO * DacGetUnwindInfo(TADDR taUnwindInfo); // virtually unwind a CONTEXT out-of-process struct _KNONVOLATILE_CONTEXT_POINTERS; BOOL DacUnwindStackFrame(T_CONTEXT * pContext, T_KNONVOLATILE_CONTEXT_POINTERS* pContextPointers); +#endif // WIN64EXCEPTIONS #if defined(FEATURE_PAL) // call back through data target to unwind out-of-process HRESULT DacVirtualUnwind(ULONG32 threadId, PCONTEXT context, PT_KNONVOLATILE_CONTEXT_POINTERS contextPointers); #endif // FEATURE_PAL -#endif // _WIN64 #ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS class SString; diff --git a/src/inc/dacprivate.h b/src/inc/dacprivate.h index 5a09abe..0db4aff 100644 --- a/src/inc/dacprivate.h +++ b/src/inc/dacprivate.h @@ -20,6 +20,29 @@ #include #endif // FEATURE_PAL +// +// Whenever a structure is marshalled between different platforms, we need to ensure the +// layout is the same in both cases. We tell GCC to use the MSVC-style packing with +// the following attribute. The main thing this appears to control is whether +// 8-byte values are aligned at 4-bytes (GCC default) or 8-bytes (MSVC default). +// This attribute affects only the immediate struct it is applied to, you must also apply +// it to any nested structs if you want their layout affected as well. You also must +// apply this to unions embedded in other structures, since it can influence the starting +// alignment. +// +// Note that there doesn't appear to be any disadvantage to applying this a little +// more agressively than necessary, so we generally use it on all classes / structures +// defined in a file that defines marshalled data types (eg. DacDbiStructures.h) +// The -mms-bitfields compiler option also does this for the whole file, but we don't +// want to go changing the layout of, for example, structures defined in OS header files +// so we explicitly opt-in with this attribute. +// +#ifdef __GNUC__ +#define MSLAYOUT __attribute__((__ms_struct__)) +#else +#define MSLAYOUT +#endif + //---------------------------------------------------------------------------- // // Utility class to allow for zero initialization of our Dacp- structs. @@ -58,7 +81,7 @@ enum }; enum DacpObjectType { OBJ_STRING=0,OBJ_FREE,OBJ_OBJECT,OBJ_ARRAY,OBJ_OTHER }; -struct DacpObjectData : ZeroInit +struct MSLAYOUT DacpObjectData : ZeroInit { CLRDATA_ADDRESS MethodTable; DacpObjectType ObjectType; @@ -81,7 +104,7 @@ struct DacpObjectData : ZeroInit } }; -struct DacpExceptionObjectData : ZeroInit +struct MSLAYOUT DacpExceptionObjectData : ZeroInit { CLRDATA_ADDRESS Message; CLRDATA_ADDRESS InnerException; @@ -105,7 +128,7 @@ struct DacpExceptionObjectData : ZeroInit } }; -struct DacpUsefulGlobalsData : ZeroInit +struct MSLAYOUT DacpUsefulGlobalsData : ZeroInit { CLRDATA_ADDRESS ArrayMethodTable; CLRDATA_ADDRESS StringMethodTable; @@ -114,7 +137,7 @@ struct DacpUsefulGlobalsData : ZeroInit CLRDATA_ADDRESS FreeMethodTable; }; -struct DacpFieldDescData : ZeroInit +struct MSLAYOUT DacpFieldDescData : ZeroInit { CorElementType Type; CorElementType sigType; // ELEMENT_TYPE_XXX from signature. We need this to disply pretty name for String in minidump's case @@ -137,7 +160,7 @@ struct DacpFieldDescData : ZeroInit } }; -struct DacpMethodTableFieldData : ZeroInit +struct MSLAYOUT DacpMethodTableFieldData : ZeroInit { WORD wNumInstanceFields; WORD wNumStaticFields; @@ -154,7 +177,7 @@ struct DacpMethodTableFieldData : ZeroInit } }; -struct DacpMethodTableTransparencyData : ZeroInit +struct MSLAYOUT DacpMethodTableTransparencyData : ZeroInit { BOOL bHasCriticalTransparentInfo; BOOL bIsCritical; @@ -166,7 +189,7 @@ struct DacpMethodTableTransparencyData : ZeroInit +struct MSLAYOUT DacpDomainLocalModuleData : ZeroInit { // These two parameters are used as input params when calling the // no-argument form of Request below. @@ -186,7 +209,7 @@ struct DacpDomainLocalModuleData : ZeroInit }; -struct DacpThreadLocalModuleData : ZeroInit +struct MSLAYOUT DacpThreadLocalModuleData : ZeroInit { // These two parameters are used as input params when calling the // no-argument form of Request below. @@ -200,7 +223,7 @@ struct DacpThreadLocalModuleData : ZeroInit }; -struct DacpModuleData : ZeroInit +struct MSLAYOUT DacpModuleData : ZeroInit { CLRDATA_ADDRESS Address; CLRDATA_ADDRESS File; // A PEFile addr @@ -243,7 +266,7 @@ private: void operator=(const DacpModuleData&); }; -struct DacpMethodTableData : ZeroInit +struct MSLAYOUT DacpMethodTableData : ZeroInit { BOOL bIsFree; // everything else is NULL if this is true. CLRDATA_ADDRESS Module; @@ -260,7 +283,7 @@ struct DacpMethodTableData : ZeroInit BOOL bIsShared; // flags & enum_flag_DomainNeutral BOOL bIsDynamic; BOOL bContainsPointers; - + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetMethodTableData(addr, this); @@ -279,7 +302,7 @@ struct DacpMethodTableData : ZeroInit #define CLRSECURITYHOSTED 0x80 #define CLRHOSTED 0x80000000 -struct DacpThreadStoreData : ZeroInit +struct MSLAYOUT DacpThreadStoreData : ZeroInit { LONG threadCount; LONG unstartedThreadCount; @@ -290,14 +313,14 @@ struct DacpThreadStoreData : ZeroInit CLRDATA_ADDRESS finalizerThread; CLRDATA_ADDRESS gcThread; DWORD fHostConfig; // Uses hosting flags defined above - + HRESULT Request(ISOSDacInterface *sos) { return sos->GetThreadStoreData(this); } }; -struct DacpAppDomainStoreData : ZeroInit +struct MSLAYOUT DacpAppDomainStoreData : ZeroInit { CLRDATA_ADDRESS sharedDomain; CLRDATA_ADDRESS systemDomain; @@ -309,14 +332,14 @@ struct DacpAppDomainStoreData : ZeroInit } }; -struct DacpCOMInterfacePointerData : ZeroInit +struct MSLAYOUT DacpCOMInterfacePointerData : ZeroInit { CLRDATA_ADDRESS methodTable; CLRDATA_ADDRESS interfacePtr; CLRDATA_ADDRESS comContext; }; -struct DacpRCWData : ZeroInit +struct MSLAYOUT DacpRCWData : ZeroInit { CLRDATA_ADDRESS identityPointer; CLRDATA_ADDRESS unknownPointer; @@ -355,7 +378,7 @@ struct DacpRCWData : ZeroInit } }; -struct DacpCCWData : ZeroInit +struct MSLAYOUT DacpCCWData : ZeroInit { CLRDATA_ADDRESS outerIUnknown; CLRDATA_ADDRESS managedObject; @@ -397,7 +420,7 @@ enum DacpAppDomainDataStage { // Information about a BaseDomain (AppDomain, SharedDomain or SystemDomain). // For types other than AppDomain, some fields (like dwID, DomainLocalBlock, etc.) will be 0/null. -struct DacpAppDomainData : ZeroInit +struct MSLAYOUT DacpAppDomainData : ZeroInit { // The pointer to the BaseDomain (not necessarily an AppDomain). // It's useful to keep this around in the structure @@ -420,7 +443,7 @@ struct DacpAppDomainData : ZeroInit } }; -struct DacpAssemblyData : ZeroInit +struct MSLAYOUT DacpAssemblyData : ZeroInit { CLRDATA_ADDRESS AssemblyPtr; //useful to have CLRDATA_ADDRESS ClassLoader; @@ -445,7 +468,7 @@ struct DacpAssemblyData : ZeroInit }; -struct DacpThreadData : ZeroInit +struct MSLAYOUT DacpThreadData : ZeroInit { DWORD corThreadId; DWORD osThreadId; @@ -470,7 +493,7 @@ struct DacpThreadData : ZeroInit }; -struct DacpReJitData : ZeroInit +struct MSLAYOUT DacpReJitData : ZeroInit { enum Flags { @@ -485,7 +508,7 @@ struct DacpReJitData : ZeroInit CLRDATA_ADDRESS NativeCodeAddr; }; -struct DacpMethodDescData : ZeroInit +struct MSLAYOUT DacpMethodDescData : ZeroInit { BOOL bHasNativeCode; BOOL bIsDynamic; @@ -529,7 +552,7 @@ struct DacpMethodDescData : ZeroInit } }; -struct DacpMethodDescTransparencyData : ZeroInit +struct MSLAYOUT DacpMethodDescTransparencyData : ZeroInit { BOOL bHasCriticalTransparentInfo; BOOL bIsCritical; @@ -544,7 +567,7 @@ struct DacpMethodDescTransparencyData : ZeroInit // for JITType enum JITTypes {TYPE_UNKNOWN=0,TYPE_JIT,TYPE_PJIT}; -struct DacpCodeHeaderData : ZeroInit +struct MSLAYOUT DacpCodeHeaderData : ZeroInit { CLRDATA_ADDRESS GCInfo; JITTypes JITType; @@ -561,7 +584,7 @@ struct DacpCodeHeaderData : ZeroInit } }; -struct DacpWorkRequestData : ZeroInit +struct MSLAYOUT DacpWorkRequestData : ZeroInit { CLRDATA_ADDRESS Function; CLRDATA_ADDRESS Context; @@ -573,7 +596,7 @@ struct DacpWorkRequestData : ZeroInit } }; -struct DacpHillClimbingLogEntry : ZeroInit +struct MSLAYOUT DacpHillClimbingLogEntry : ZeroInit { DWORD TickCount; int Transition; @@ -589,7 +612,7 @@ struct DacpHillClimbingLogEntry : ZeroInit // Used for CLR versions >= 4.0 -struct DacpThreadpoolData : ZeroInit +struct MSLAYOUT DacpThreadpoolData : ZeroInit { LONG cpuUtilization; int NumIdleWorkerThreads; @@ -623,7 +646,7 @@ struct DacpThreadpoolData : ZeroInit } }; -struct DacpGenerationData : ZeroInit +struct MSLAYOUT DacpGenerationData : ZeroInit { CLRDATA_ADDRESS start_segment; CLRDATA_ADDRESS allocation_start; @@ -636,18 +659,18 @@ struct DacpGenerationData : ZeroInit #define DAC_NUMBERGENERATIONS 4 -struct DacpAllocData : ZeroInit +struct MSLAYOUT DacpAllocData : ZeroInit { CLRDATA_ADDRESS allocBytes; CLRDATA_ADDRESS allocBytesLoh; }; -struct DacpGenerationAllocData : ZeroInit +struct MSLAYOUT DacpGenerationAllocData : ZeroInit { DacpAllocData allocData[DAC_NUMBERGENERATIONS]; }; -struct DacpGcHeapDetails : ZeroInit +struct MSLAYOUT DacpGcHeapDetails : ZeroInit { CLRDATA_ADDRESS heapAddr; // Only filled in in server mode, otherwise NULL CLRDATA_ADDRESS alloc_allocated; @@ -681,7 +704,7 @@ struct DacpGcHeapDetails : ZeroInit } }; -struct DacpGcHeapData +struct MSLAYOUT DacpGcHeapData : ZeroInit { BOOL bServerMode; @@ -695,7 +718,7 @@ struct DacpGcHeapData } }; -struct DacpHeapSegmentData +struct MSLAYOUT DacpHeapSegmentData : ZeroInit { CLRDATA_ADDRESS segmentAddr; @@ -730,7 +753,7 @@ struct DacpHeapSegmentData } }; -struct DacpOomData : ZeroInit +struct MSLAYOUT DacpOomData : ZeroInit { int reason; ULONG64 alloc_size; @@ -761,7 +784,7 @@ struct DacpOomData : ZeroInit #define MAX_GC_MECHANISM_BITS_COUNT 2 // This is from ndp\clr\src\vm\common.h #define MAX_GLOBAL_GC_MECHANISMS_COUNT 6 -struct DacpGCInterestingInfoData : ZeroInit +struct MSLAYOUT DacpGCInterestingInfoData : ZeroInit { size_t interestingDataPoints[NUM_GC_DATA_POINTS]; size_t compactReasons[MAX_COMPACT_REASONS_COUNT]; @@ -808,7 +831,7 @@ struct DacpGCInterestingInfoData : ZeroInit } }; -struct DacpGcHeapAnalyzeData +struct MSLAYOUT DacpGcHeapAnalyzeData : ZeroInit { CLRDATA_ADDRESS heapAddr; // Only filled in in server mode, otherwise NULL @@ -836,7 +859,7 @@ struct DacpGcHeapAnalyzeData #define SYNCBLOCKDATA_COMFLAGS_RCW 2 #define SYNCBLOCKDATA_COMFLAGS_CF 4 -struct DacpSyncBlockData : ZeroInit +struct MSLAYOUT DacpSyncBlockData : ZeroInit { CLRDATA_ADDRESS Object; BOOL bFree; // if set, no other fields are useful @@ -863,7 +886,7 @@ struct DacpSyncBlockData : ZeroInit } }; -struct DacpSyncBlockCleanupData : ZeroInit +struct MSLAYOUT DacpSyncBlockCleanupData : ZeroInit { CLRDATA_ADDRESS SyncBlockPointer; @@ -883,7 +906,7 @@ struct DacpSyncBlockCleanupData : ZeroInit enum EHClauseType {EHFault, EHFinally, EHFilter, EHTyped, EHUnknown}; -struct DACEHInfo : ZeroInit +struct MSLAYOUT DACEHInfo : ZeroInit { EHClauseType clauseType; CLRDATA_ADDRESS tryStartOffset; @@ -898,7 +921,7 @@ struct DACEHInfo : ZeroInit mdToken tokCatch; // the type token of the TYPED clause type }; -struct DacpGetModuleAddress : ZeroInit +struct MSLAYOUT DacpGetModuleAddress : ZeroInit { CLRDATA_ADDRESS ModulePtr; HRESULT Request(IXCLRDataModule* pDataModule) @@ -907,7 +930,7 @@ struct DacpGetModuleAddress : ZeroInit } }; -struct DacpGetModuleData : ZeroInit +struct MSLAYOUT DacpGetModuleData : ZeroInit { BOOL IsDynamic; BOOL IsInMemory; @@ -924,7 +947,7 @@ struct DacpGetModuleData : ZeroInit } }; -struct DacpFrameData : ZeroInit +struct MSLAYOUT DacpFrameData : ZeroInit { CLRDATA_ADDRESS frameAddr; @@ -937,7 +960,7 @@ struct DacpFrameData : ZeroInit } }; -struct DacpJitManagerInfo : ZeroInit +struct MSLAYOUT DacpJitManagerInfo : ZeroInit { CLRDATA_ADDRESS managerAddr; DWORD codeType; // for union below @@ -946,14 +969,14 @@ struct DacpJitManagerInfo : ZeroInit enum CodeHeapType {CODEHEAP_LOADER=0,CODEHEAP_HOST,CODEHEAP_UNKNOWN}; -struct DacpJitCodeHeapInfo : ZeroInit +struct MSLAYOUT DacpJitCodeHeapInfo : ZeroInit { DWORD codeHeapType; // for union below union { CLRDATA_ADDRESS LoaderHeap; // if CODEHEAP_LOADER - struct + struct MSLAYOUT { CLRDATA_ADDRESS baseAddr; // if CODEHEAP_HOST CLRDATA_ADDRESS currentAddr; diff --git a/src/inc/dacvars.h b/src/inc/dacvars.h index fb052b3..0a60684 100644 --- a/src/inc/dacvars.h +++ b/src/inc/dacvars.h @@ -125,9 +125,10 @@ DEFINE_DACVAR(ULONG, PTR_Thread, dac__g_pFinalizerThread, ::g_pFinalizerThread) DEFINE_DACVAR(ULONG, PTR_Thread, dac__g_pSuspensionThread, ::g_pSuspensionThread) #ifdef FEATURE_SVR_GC -DEFINE_DACVAR(ULONG, DWORD, GCHeap__gcHeapType, GCHeap::gcHeapType) +DEFINE_DACVAR(ULONG, DWORD, IGCHeap__gcHeapType, IGCHeap::gcHeapType) #endif // FEATURE_SVR_GC +DEFINE_DACVAR(ULONG, DWORD, IGCHeap__maxGeneration, IGCHeap::maxGeneration) DEFINE_DACVAR(ULONG, PTR_BYTE, WKS__gc_heap__alloc_allocated, WKS::gc_heap::alloc_allocated) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE /*PTR_heap_segment*/, WKS__gc_heap__ephemeral_heap_segment, WKS::gc_heap::ephemeral_heap_segment) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE /*PTR_CFinalize*/, WKS__gc_heap__finalize_queue, WKS::gc_heap::finalize_queue) @@ -198,7 +199,7 @@ DEFINE_DACVAR(ULONG, PTR_DWORD, dac__g_card_table, ::g_card_table) DEFINE_DACVAR(ULONG, PTR_BYTE, dac__g_lowest_address, ::g_lowest_address) DEFINE_DACVAR(ULONG, PTR_BYTE, dac__g_highest_address, ::g_highest_address) -DEFINE_DACVAR(ULONG, GCHeap, dac__g_pGCHeap, ::g_pGCHeap) +DEFINE_DACVAR(ULONG, IGCHeap, dac__g_pGCHeap, ::g_pGCHeap) #ifdef GC_CONFIG_DRIVEN DEFINE_DACVAR_NO_DUMP(ULONG, SIZE_T, dac__interesting_data_per_heap, WKS::interesting_data_per_heap) @@ -217,6 +218,9 @@ DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pStringClass, ::g_pStringClass DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pArrayClass, ::g_pArrayClass) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pSZArrayHelperClass, ::g_pSZArrayHelperClass) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pNullableClass, ::g_pNullableClass) +#ifdef FEATURE_SPAN_OF_T +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pByReferenceClass, ::g_pByReferenceClass) +#endif DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pExceptionClass, ::g_pExceptionClass) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pThreadAbortExceptionClass, ::g_pThreadAbortExceptionClass) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pOutOfMemoryExceptionClass, ::g_pOutOfMemoryExceptionClass) @@ -229,8 +233,12 @@ DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pOverlappedDataClass, ::g_pOve DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pValueTypeClass, ::g_pValueTypeClass) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pEnumClass, ::g_pEnumClass) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pThreadClass, ::g_pThreadClass) +#ifdef FEATURE_CER DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pCriticalFinalizerObjectClass, ::g_pCriticalFinalizerObjectClass) +#endif +#ifndef FEATURE_CORECLR DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pAsyncFileStream_AsyncResultClass, ::g_pAsyncFileStream_AsyncResultClass) +#endif // !FEATURE_CORECLR DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pPredefinedArrayTypes, ::g_pPredefinedArrayTypes) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_TypedReferenceMT, ::g_TypedReferenceMT) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pByteArrayMT, ::g_pByteArrayMT) @@ -244,7 +252,9 @@ DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pBaseRuntimeClass, ::g_pBaseRu DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pICastableInterface, ::g_pICastableInterface) #endif // FEATURE_ICASTABLE +#ifdef FEATURE_CER DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pPrepareConstrainedRegionsMethod, ::g_pPrepareConstrainedRegionsMethod) +#endif DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pExecuteBackoutCodeHelperMethod, ::g_pExecuteBackoutCodeHelperMethod) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pObjectCtorMD, ::g_pObjectCtorMD) diff --git a/src/inc/debugreturn.h b/src/inc/debugreturn.h index dbcbd2b..e5013cc 100644 --- a/src/inc/debugreturn.h +++ b/src/inc/debugreturn.h @@ -27,9 +27,11 @@ #else // !_PREFAST_ -// This is disabled in VS2015 Update 3 and earlier because only C++11 constexpr is supported, -// which doesn't allow the use of 'if' statements within the body of a constexpr function. -#if defined(_DEBUG) && (!defined(_MSC_FULL_VER) || _MSC_FULL_VER > 190024210) +// This is disabled in build 190024315 (a pre-release build after VS 2015 Update 3) and +// earlier because those builds only support C++11 constexpr, which doesn't allow the +// use of 'if' statements within the body of a constexpr function. Later builds support +// C++14 constexpr. +#if defined(_DEBUG) && (!defined(_MSC_FULL_VER) || _MSC_FULL_VER > 190024315) // Code to generate a compile-time error if return statements appear where they // shouldn't. @@ -110,7 +112,7 @@ typedef __SafeToReturn __ReturnOK; #define DEBUG_OK_TO_RETURN_BEGIN(arg) { typedef __SafeToReturn __ReturnOK; if (0 && __ReturnOK::used()) { } else { #define DEBUG_OK_TO_RETURN_END(arg) } } -#else // defined(_DEBUG) && (!defined(_MSC_FULL_VER) || _MSC_FULL_VER > 190024210) +#else // defined(_DEBUG) && (!defined(_MSC_FULL_VER) || _MSC_FULL_VER > 190024315) #define DEBUG_ASSURE_SAFE_TO_RETURN TRUE @@ -120,7 +122,7 @@ typedef __SafeToReturn __ReturnOK; #define DEBUG_OK_TO_RETURN_BEGIN(arg) { #define DEBUG_OK_TO_RETURN_END(arg) } -#endif // defined(_DEBUG) && (!defined(_MSC_FULL_VER) || _MSC_FULL_VER > 190024210) +#endif // defined(_DEBUG) && (!defined(_MSC_FULL_VER) || _MSC_FULL_VER > 190024315) #endif // !_PREFAST_ diff --git a/src/inc/eetwain.h b/src/inc/eetwain.h index 6e183c5..502d181 100644 --- a/src/inc/eetwain.h +++ b/src/inc/eetwain.h @@ -278,16 +278,16 @@ virtual void * GetGSCookieAddr(PREGDISPLAY pContext, Returns true if the given IP is in the given method's prolog or an epilog. */ virtual bool IsInPrologOrEpilog(DWORD relPCOffset, - PTR_VOID methodInfoPtr, + GCInfoToken gcInfoToken, size_t* prologSize) = 0; /* Returns true if the given IP is in the synchronized region of the method (valid for synchronized methods only) */ virtual bool IsInSynchronizedRegion( - DWORD relOffset, - PTR_VOID methodInfoPtr, - unsigned flags) = 0; + DWORD relOffset, + GCInfoToken gcInfoToken, + unsigned flags) = 0; /* Returns the size of a given function as reported in the GC info (does @@ -297,9 +297,15 @@ virtual bool IsInSynchronizedRegion( virtual size_t GetFunctionSize(GCInfoToken gcInfoToken) = 0; /* +Returns the ReturnKind of a given function as reported in the GC info. +*/ + +virtual ReturnKind GetReturnKind(GCInfoToken gcInfotoken) = 0; + +/* Returns the size of the frame (barring localloc) */ -virtual unsigned int GetFrameSize(PTR_VOID methodInfoPtr) = 0; +virtual unsigned int GetFrameSize(GCInfoToken gcInfoToken) = 0; #ifndef DACCESS_COMPILE @@ -307,16 +313,16 @@ virtual unsigned int GetFrameSize(PTR_VOID methodInfoPtr) = 0; virtual const BYTE* GetFinallyReturnAddr(PREGDISPLAY pReg)=0; -virtual BOOL IsInFilter(void *methodInfoPtr, +virtual BOOL IsInFilter(GCInfoToken gcInfoToken, unsigned offset, PCONTEXT pCtx, DWORD curNestLevel) = 0; -virtual BOOL LeaveFinally(void *methodInfoPtr, +virtual BOOL LeaveFinally(GCInfoToken gcInfoToken, unsigned offset, PCONTEXT pCtx) = 0; -virtual void LeaveCatch(void *methodInfoPtr, +virtual void LeaveCatch(GCInfoToken gcInfoToken, unsigned offset, PCONTEXT pCtx)=0; @@ -535,18 +541,18 @@ void * GetGSCookieAddr(PREGDISPLAY pContext, */ virtual bool IsInPrologOrEpilog( - DWORD relOffset, - PTR_VOID methodInfoPtr, - size_t* prologSize); + DWORD relOffset, + GCInfoToken gcInfoToken, + size_t* prologSize); /* Returns true if the given IP is in the synchronized region of the method (valid for synchronized functions only) */ virtual bool IsInSynchronizedRegion( - DWORD relOffset, - PTR_VOID methodInfoPtr, - unsigned flags); + DWORD relOffset, + GCInfoToken gcInfoToken, + unsigned flags); /* Returns the size of a given function. @@ -555,23 +561,27 @@ virtual size_t GetFunctionSize(GCInfoToken gcInfoToken); /* +Returns the ReturnKind of a given function. +*/ +virtual ReturnKind GetReturnKind(GCInfoToken gcInfotoken); + +/* Returns the size of the frame (barring localloc) */ virtual -unsigned int GetFrameSize( - PTR_VOID methodInfoPtr); +unsigned int GetFrameSize(GCInfoToken gcInfoToken); #ifndef DACCESS_COMPILE virtual const BYTE* GetFinallyReturnAddr(PREGDISPLAY pReg); -virtual BOOL LeaveFinally(void *methodInfoPtr, +virtual BOOL LeaveFinally(GCInfoToken gcInfoToken, unsigned offset, PCONTEXT pCtx); -virtual BOOL IsInFilter(void *methodInfoPtr, +virtual BOOL IsInFilter(GCInfoToken gcInfoToken, unsigned offset, PCONTEXT pCtx, DWORD curNestLevel); -virtual void LeaveCatch(void *methodInfoPtr, +virtual void LeaveCatch(GCInfoToken gcInfoToken, unsigned offset, PCONTEXT pCtx); @@ -646,8 +656,9 @@ struct hdrInfo { unsigned int methodSize; // native code bytes unsigned int argSize; // in bytes - unsigned int stackSize; /* including callee saved registers */ - unsigned int rawStkSize; /* excluding callee saved registers */ + unsigned int stackSize; // including callee saved registers + unsigned int rawStkSize; // excluding callee saved registers + ReturnKind returnKind; // The ReturnKind for this method. unsigned int prologSize; @@ -689,6 +700,7 @@ struct hdrInfo unsigned int syncStartOffset; // start/end code offset of the protected region in synchronized methods. unsigned int syncEndOffset; // INVALID_SYNC_OFFSET if there not synchronized method unsigned int syncEpilogStart; // The start of the epilog. Synchronized methods are guaranteed to have no more than one epilog. + unsigned int revPInvokeOffset; // INVALID_REV_PINVOKE_OFFSET if there is no Reverse PInvoke frame enum { NOT_IN_PROLOG = -1, NOT_IN_EPILOG = -1 }; diff --git a/src/inc/eventtrace.h b/src/inc/eventtrace.h index 67d9b79..765249e 100644 --- a/src/inc/eventtrace.h +++ b/src/inc/eventtrace.h @@ -34,7 +34,29 @@ #define _VMEVENTTRACE_H_ #include "eventtracebase.h" +#include "gcinterface.h" +#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) +struct ProfilingScanContext : ScanContext +{ + BOOL fProfilerPinned; + void * pvEtwContext; + void *pHeapId; + + ProfilingScanContext(BOOL fProfilerPinnedParam) : ScanContext() + { + LIMITED_METHOD_CONTRACT; + + pHeapId = NULL; + fProfilerPinned = fProfilerPinnedParam; + pvEtwContext = NULL; +#ifdef FEATURE_CONSERVATIVE_GC + // To not confuse GCScan::GcScanRoots + promotion = g_pConfig->GetGCConservative(); +#endif + } +}; +#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) #ifndef FEATURE_REDHAWK diff --git a/src/inc/fstring.h b/src/inc/fstring.h index 68c9098..9245885 100644 --- a/src/inc/fstring.h +++ b/src/inc/fstring.h @@ -21,6 +21,9 @@ namespace FString { + // Note: All "length" parameters do not count the space for the null terminator. + // Caller of Unicode_Utf8 and Utf8_Unicode must pass in a buffer of size at least length + 1. + // Scan for ASCII only string, calculate result UTF8 string length HRESULT Unicode_Utf8_Length(__in_z LPCWSTR pString, __out bool * pAllAscii, __out DWORD * pLength); diff --git a/src/inc/gcdecoder.cpp b/src/inc/gcdecoder.cpp index d337fae..a2a2e8c 100644 --- a/src/inc/gcdecoder.cpp +++ b/src/inc/gcdecoder.cpp @@ -86,19 +86,19 @@ size_t FASTCALL decodeSigned(PTR_CBYTE src, int* val) #pragma optimize("tgy", on) #endif -PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, InfoHdr* header) +PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, UINT32 version, InfoHdr* header) { LIMITED_METHOD_DAC_CONTRACT; - BYTE byte = *table++; - BYTE encoding = byte & 0x7f; - + BYTE nextByte = *table++; + BYTE encoding = nextByte & 0x7f; GetInfoHdr(encoding, header); - - while (byte & 0x80) + while (nextByte & MORE_BYTES_TO_FOLLOW) { - byte = *table++; - encoding = byte & 0x7f; + nextByte = *table++; + encoding = nextByte & ADJ_ENCODING_MAX; + // encoding here always corresponds to codes in InfoHdrAdjust set + if (encoding < NEXT_FOUR_START) { if (encoding < SET_ARGCOUNT) @@ -126,6 +126,7 @@ PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, InfoHdr* header) else if (encoding < FIRST_FLIP) { header->untrackedCnt = encoding - SET_UNTRACKED; + _ASSERTE(header->untrackedCnt != HAS_UNTRACKED); } else switch (encoding) { @@ -145,22 +146,22 @@ PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, InfoHdr* header) header->ebpSaved ^= 1; break; case FLIP_EBP_FRAME: - header->ebpFrame ^= 1; + header->ebpFrame ^= 1; break; case FLIP_INTERRUPTIBLE: - header->interruptible ^= 1; + header->interruptible ^= 1; break; case FLIP_DOUBLE_ALIGN: - header->doubleAlign ^= 1; + header->doubleAlign ^= 1; break; case FLIP_SECURITY: - header->security ^= 1; + header->security ^= 1; break; case FLIP_HANDLERS: - header->handlers ^= 1; + header->handlers ^= 1; break; case FLIP_LOCALLOC: - header->localloc ^= 1; + header->localloc ^= 1; break; case FLIP_EDITnCONTINUE: header->editNcontinue ^= 1; @@ -172,10 +173,10 @@ PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, InfoHdr* header) header->untrackedCnt = HAS_UNTRACKED; break; case FLIP_VARARGS: - header->varargs ^= 1; + header->varargs ^= 1; break; case FLIP_PROF_CALLBACKS: - header->profCallbacks ^= 1; + header->profCallbacks ^= 1; break; case FLIP_HAS_GENERICS_CONTEXT: header->genericsContext ^= 1; @@ -189,6 +190,27 @@ PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, InfoHdr* header) case FLIP_SYNC: header->syncStartOffset ^= HAS_SYNC_OFFSET; break; + case FLIP_REV_PINVOKE_FRAME: + _ASSERTE(GCInfoEncodesRevPInvokeFrame(version)); + header->revPInvokeOffset ^= HAS_REV_PINVOKE_FRAME_OFFSET; + break; + + case NEXT_OPCODE: + _ASSERTE((nextByte & MORE_BYTES_TO_FOLLOW) && "Must have another code"); + nextByte = *table++; + encoding = nextByte & ADJ_ENCODING_MAX; + // encoding here always corresponds to codes in InfoHdrAdjust2 set + + if (encoding < SET_RET_KIND_MAX) + { + _ASSERTE(GCInfoEncodesReturnKind(version)); + header->returnKind = (ReturnKind)encoding; + } + else + { + assert(!"Unexpected encoding"); + } + break; } } else @@ -202,14 +224,14 @@ PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, InfoHdr* header) case 5: assert(NEXT_FOUR_FRAMESIZE == 0x50); lowBits = encoding & 0xf; - header->frameSize <<= 4; - header->frameSize += lowBits; + header->frameSize <<= 4; + header->frameSize += lowBits; break; case 6: assert(NEXT_FOUR_ARGCOUNT == 0x60); lowBits = encoding & 0xf; - header->argCount <<= 4; - header->argCount += lowBits; + header->argCount <<= 4; + header->argCount += lowBits; break; case 7: if ((encoding & 0x8) == 0) @@ -217,14 +239,14 @@ PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, InfoHdr* header) assert(NEXT_THREE_PROLOGSIZE == 0x70); lowBits = encoding & 0x7; header->prologSize <<= 3; - header->prologSize += lowBits; + header->prologSize += lowBits; } else { assert(NEXT_THREE_EPILOGSIZE == 0x78); lowBits = encoding & 0x7; header->epilogSize <<= 3; - header->epilogSize += lowBits; + header->epilogSize += lowBits; } break; } @@ -293,154 +315,155 @@ const InfoHdrSmall infoHdrShortcut[128] = { // | | | | | | | | | | | | | | | | | // | | | | | | | | | | | | | | | | | genericsContext // | | | | | | | | | | | | | | | | | | -// | | | | | | | | | | | | | | | | | | genericsContextIsMethodDesc -// | | | | | | | | | | | | | | | | | | | -// | | | | | | | | | | | | | | | | | | | Arg count -// | | | | | | | | | | | | | | | | | | | | Counted occurances -// | | | | | | | | | | | | | | | | | | | | Frame size | -// | | | | | | | | | | | | | | | | | | | | | | -// | | | | | | | | | | | | | | | | | | | | | untrackedCnt | Header encoding -// | | | | | | | | | | | | | | | | | | | | | | | | -// | | | | | | | | | | | | | | | | | | | | | | varPtrTable | | -// | | | | | | | | | | | | | | | | | | | | | | | | | -// | | | | | | | | | | | | | | | | | | | | | | | gsCookieOffs | | -// | | | | | | | | | | | | | | | | | | | | | | | | | | -// | | | | | | | | | | | | | | | | | | | | | | | | syncOffs | | -// | | | | | | | | | | | | | | | | | | | | | | | | | | | | -// | | | | | | | | | | | | | | | | | | | | | | | | | | | | -// | | | | | | | | | | | | | | | | | | | | | | | | | | | | -// v v v v v v v v v v v v v v v v v v v v v v v v v v v v - { 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1139 00 - { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 128738 01 - { 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3696 02 - { 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 402 03 - { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 4259 04 - { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 3379 05 - { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 2058 06 - { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0 }, // 728 07 - { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0 }, // 984 08 - { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0 }, // 606 09 - { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0 }, // 1110 0a - { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 0 }, // 414 0b - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 1553 0c - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, YES }, // 584 0d - { 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 2182 0e - { 1, 2, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3445 0f - { 1, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1369 10 - { 1, 2, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 515 11 - { 1, 2, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 21127 12 - { 1, 2, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3517 13 - { 1, 2, 3, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 750 14 - { 1, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1876 15 - { 1, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 1665 16 - { 1, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 729 17 - { 1, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0 }, // 484 18 - { 1, 4, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 331 19 - { 2, 3, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 361 1a - { 2, 3, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 964 1b - { 2, 3, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3713 1c - { 2, 3, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 466 1d - { 2, 3, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1325 1e - { 2, 3, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 712 1f - { 2, 3, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 588 20 - { 2, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 20542 21 - { 2, 3, 2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3802 22 - { 2, 3, 3, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 798 23 - { 2, 5, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1900 24 - { 2, 5, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 385 25 - { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1617 26 - { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 1743 27 - { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 909 28 - { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0 }, // 602 29 - { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0 }, // 352 2a - { 2, 6, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 657 2b - { 2, 7, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, YES }, // 1283 2c - { 2, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 1286 2d - { 3, 4, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1495 2e - { 3, 4, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1989 2f - { 3, 4, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1154 30 - { 3, 4, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 9300 31 - { 3, 4, 2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 392 32 - { 3, 4, 2, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1720 33 - { 3, 6, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1246 34 - { 3, 6, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 800 35 - { 3, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1179 36 - { 3, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 1368 37 - { 3, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 349 38 - { 3, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0 }, // 505 39 - { 3, 6, 2, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 629 3a - { 3, 8, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 2, YES }, // 365 3b - { 4, 5, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 487 3c - { 4, 5, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1752 3d - { 4, 5, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1959 3e - { 4, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 2436 3f - { 4, 5, 2, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 861 40 - { 4, 7, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1459 41 - { 4, 7, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 950 42 - { 4, 7, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1491 43 - { 4, 7, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 879 44 - { 4, 7, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 408 45 - { 5, 4, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 4870 46 - { 5, 6, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 359 47 - { 5, 6, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 915 48 - { 5, 6, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0 }, // 412 49 - { 5, 6, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1288 4a - { 5, 6, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 1591 4b - { 5, 6, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, YES }, // 361 4c - { 5, 6, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0 }, // 623 4d - { 5, 8, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 }, // 1239 4e - { 6, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 457 4f - { 6, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 606 50 - { 6, 4, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, YES }, // 1073 51 - { 6, 4, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, YES }, // 508 52 - { 6, 6, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 330 53 - { 6, 6, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1709 54 - { 6, 7, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 1164 55 - { 7, 4, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 556 56 - { 7, 5, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, YES }, // 529 57 - { 7, 5, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, YES }, // 1423 58 - { 7, 8, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, YES }, // 2455 59 - { 7, 8, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 956 5a - { 7, 8, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, YES }, // 1399 5b - { 7, 8, 2, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, YES }, // 587 5c - { 7, 10, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 1, YES }, // 743 5d - { 7, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0 }, // 1004 5e - { 7, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, YES }, // 487 5f - { 7, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0 }, // 337 60 - { 7, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, YES }, // 361 61 - { 8, 3, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, // 560 62 - { 8, 6, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 1377 63 - { 9, 4, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, // 877 64 - { 9, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 3041 65 - { 9, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, YES }, // 349 66 - { 10, 5, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 }, // 2061 67 - { 10, 5, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, // 577 68 - { 11, 6, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 }, // 1195 69 - { 12, 5, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 491 6a - { 13, 8, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, YES }, // 627 6b - { 13, 8, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0 }, // 1099 6c - { 13, 10, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 1, YES }, // 488 6d - { 14, 7, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 574 6e - { 16, 7, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, YES }, // 1281 6f - { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, YES }, // 1881 70 - { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 339 71 - { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 }, // 2594 72 - { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0 }, // 339 73 - { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, YES }, // 2107 74 - { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, 0, YES }, // 2372 75 - { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 6, 0, YES }, // 1078 76 - { 16, 7, 2, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, YES }, // 384 77 - { 16, 9, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 4, 1, YES }, // 1541 78 - { 16, 9, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 4, 1, YES }, // 975 79 - { 19, 7, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, 0, YES }, // 546 7a - { 24, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, 0, YES }, // 675 7b - { 45, 9, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 902 7c - { 51, 7, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, YES }, // 432 7d - { 51, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 361 7e - { 51, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0 }, // 703 7f +// | | | | | | | | | | | | | | | | | | genericsContextIsMethodDesc +// | | | | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | | | | | | returnKind +// | | | | | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | | | | | | | Arg count +// | | | | | | | | | | | | | | | | | | | | | Counted occurences +// | | | | | | | | | | | | | | | | | | | | | Frame size | +// | | | | | | | | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | | | | | | | | | untrackedCnt | Header encoding +// | | | | | | | | | | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | | | | | | | | | | varPtrTable | | +// | | | | | | | | | | | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | | | | | | | | | | | gsCookieOffs | | +// | | | | | | | | | | | | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | | | | | | | | | | | | syncOffs | | +// | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +// v v v v v v v v v v v v v v v v v v v v v v v v v v v v v + { 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1139 00 + { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 128738 01 + { 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3696 02 + { 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 402 03 + { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 4259 04 + { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 3379 05 + { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 2058 06 + { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0 }, // 728 07 + { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0 }, // 984 08 + { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0 }, // 606 09 + { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0 }, // 1110 0a + { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 0 }, // 414 0b + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 1553 0c + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, YES }, // 584 0d + { 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 2182 0e + { 1, 2, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3445 0f + { 1, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1369 10 + { 1, 2, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 515 11 + { 1, 2, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 21127 12 + { 1, 2, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3517 13 + { 1, 2, 3, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 750 14 + { 1, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1876 15 + { 1, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 1665 16 + { 1, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 729 17 + { 1, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0 }, // 484 18 + { 1, 4, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 331 19 + { 2, 3, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 361 1a + { 2, 3, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 964 1b + { 2, 3, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3713 1c + { 2, 3, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 466 1d + { 2, 3, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1325 1e + { 2, 3, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 712 1f + { 2, 3, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 588 20 + { 2, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 20542 21 + { 2, 3, 2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3802 22 + { 2, 3, 3, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 798 23 + { 2, 5, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1900 24 + { 2, 5, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 385 25 + { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1617 26 + { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 1743 27 + { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 909 28 + { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0 }, // 602 29 + { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0 }, // 352 2a + { 2, 6, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 657 2b + { 2, 7, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, YES }, // 1283 2c + { 2, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 1286 2d + { 3, 4, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1495 2e + { 3, 4, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1989 2f + { 3, 4, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1154 30 + { 3, 4, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 9300 31 + { 3, 4, 2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 392 32 + { 3, 4, 2, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1720 33 + { 3, 6, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1246 34 + { 3, 6, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 800 35 + { 3, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1179 36 + { 3, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 1368 37 + { 3, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 349 38 + { 3, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0 }, // 505 39 + { 3, 6, 2, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 629 3a + { 3, 8, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 2, YES }, // 365 3b + { 4, 5, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 487 3c + { 4, 5, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1752 3d + { 4, 5, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1959 3e + { 4, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 2436 3f + { 4, 5, 2, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 861 40 + { 4, 7, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1459 41 + { 4, 7, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 950 42 + { 4, 7, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1491 43 + { 4, 7, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 879 44 + { 4, 7, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 408 45 + { 5, 4, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 4870 46 + { 5, 6, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 359 47 + { 5, 6, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 915 48 + { 5, 6, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0 }, // 412 49 + { 5, 6, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1288 4a + { 5, 6, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 1591 4b + { 5, 6, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, YES }, // 361 4c + { 5, 6, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0 }, // 623 4d + { 5, 8, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 }, // 1239 4e + { 6, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 457 4f + { 6, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 606 50 + { 6, 4, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, YES }, // 1073 51 + { 6, 4, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, YES }, // 508 52 + { 6, 6, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 330 53 + { 6, 6, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1709 54 + { 6, 7, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 1164 55 + { 7, 4, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 556 56 + { 7, 5, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, YES }, // 529 57 + { 7, 5, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, YES }, // 1423 58 + { 7, 8, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, YES }, // 2455 59 + { 7, 8, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 956 5a + { 7, 8, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, YES }, // 1399 5b + { 7, 8, 2, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, YES }, // 587 5c + { 7, 10, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 1, YES }, // 743 5d + { 7, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0 }, // 1004 5e + { 7, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, YES }, // 487 5f + { 7, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0 }, // 337 60 + { 7, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, YES }, // 361 61 + { 8, 3, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, // 560 62 + { 8, 6, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 1377 63 + { 9, 4, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, // 877 64 + { 9, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 3041 65 + { 9, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, YES }, // 349 66 + { 10, 5, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 }, // 2061 67 + { 10, 5, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, // 577 68 + { 11, 6, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 }, // 1195 69 + { 12, 5, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 491 6a + { 13, 8, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, YES }, // 627 6b + { 13, 8, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0 }, // 1099 6c + { 13, 10, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 1, YES }, // 488 6d + { 14, 7, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 574 6e + { 16, 7, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, YES }, // 1281 6f + { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, YES }, // 1881 70 + { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 339 71 + { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 }, // 2594 72 + { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0 }, // 339 73 + { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, YES }, // 2107 74 + { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, YES }, // 2372 75 + { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, YES }, // 1078 76 + { 16, 7, 2, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, YES }, // 384 77 + { 16, 9, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 4, 1, YES }, // 1541 78 + { 16, 9, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 4, 1, YES }, // 975 79 + { 19, 7, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, YES }, // 546 7a + { 24, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, YES }, // 675 7b + { 45, 9, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 902 7c + { 51, 7, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, YES }, // 432 7d + { 51, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 361 7e + { 51, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0 }, // 703 7f }; - bool InfoHdrSmall::isHeaderMatch(const InfoHdr& target) const { #ifdef _ASSERTE @@ -448,7 +471,8 @@ bool InfoHdrSmall::isHeaderMatch(const InfoHdr& target) const _ASSERTE(target.untrackedCnt != HAS_UNTRACKED && target.varPtrTableSize != HAS_VARPTR && target.gsCookieOffset != HAS_GS_COOKIE_OFFSET && - target.syncStartOffset != HAS_SYNC_OFFSET); + target.syncStartOffset != HAS_SYNC_OFFSET && + target.revPInvokeOffset != HAS_REV_PINVOKE_FRAME_OFFSET); #endif // compare two InfoHdr's up to but not including the untrackCnt field @@ -470,7 +494,13 @@ bool InfoHdrSmall::isHeaderMatch(const InfoHdr& target) const if (target.gsCookieOffset != INVALID_GS_COOKIE_OFFSET) return false; - return target.syncStartOffset == INVALID_SYNC_OFFSET; + if (target.syncStartOffset != INVALID_SYNC_OFFSET) + return false; + + if (target.revPInvokeOffset!= INVALID_REV_PINVOKE_OFFSET) + return false; + + return true; } @@ -503,7 +533,7 @@ const unsigned callCommonDelta[4] = { 6,8,10,12 }; * EDI = 0x1, ESI = 0x2, EBX = 0x4, EBP = 0x8 * */ -const unsigned callPatternTable[80] = { // # of occurances +const unsigned callPatternTable[80] = { // # of occurences 0x0a000200, // 30109 0x0c000200, // 22970 0x0c000201, // 19005 diff --git a/src/inc/gcdump.h b/src/inc/gcdump.h index cd73940..3271ca1 100644 --- a/src/inc/gcdump.h +++ b/src/inc/gcdump.h @@ -45,7 +45,7 @@ public: * Return value : Size in bytes of the header encoding */ - unsigned FASTCALL DumpInfoHdr (PTR_CBYTE gcInfoBlock, + unsigned FASTCALL DumpInfoHdr (PTR_CBYTE gcInfoBlock, InfoHdr * header, /* OUT */ unsigned * methodSize, /* OUT */ bool verifyGCTables = false); @@ -53,7 +53,7 @@ public: /*------------------------------------------------------------------------- * Dumps the GC tables to 'stdout' - * table : The GCInfoToken + * gcInfoBlock : Start of the GC info block * verifyGCTables : If the JIT has been compiled with VERIFY_GC_TABLES * Return value : Size in bytes of the GC table encodings */ @@ -70,10 +70,10 @@ public: * verifyGCTables : If the JIT has been compiled with VERIFY_GC_TABLES */ - void FASTCALL DumpPtrsInFrame(PTR_CBYTE infoBlock, - PTR_CBYTE codeBlock, - unsigned offs, - bool verifyGCTables = false); + void FASTCALL DumpPtrsInFrame(PTR_CBYTE gcInfoBlock, + PTR_CBYTE codeBlock, + unsigned offs, + bool verifyGCTables = false); public: diff --git a/src/inc/gcinfo.h b/src/inc/gcinfo.h index 8d249a3..e5537e0 100644 --- a/src/inc/gcinfo.h +++ b/src/inc/gcinfo.h @@ -32,15 +32,21 @@ const unsigned this_OFFSET_FLAG = 0x2; // the offset is "this" // The current GCInfo Version //----------------------------------------------------------------------------- -#ifdef _TARGET_X86_ -// X86 GcInfo encoding is yet to be changed. -#define GCINFO_VERSION 1 -#else #define GCINFO_VERSION 2 -#endif // _TARGET_X86_ #define MIN_GCINFO_VERSION_WITH_RETURN_KIND 2 #define MIN_GCINFO_VERSION_WITH_REV_PINVOKE_FRAME 2 + +inline BOOL GCInfoEncodesReturnKind(UINT32 version=GCINFO_VERSION) +{ + return version >= MIN_GCINFO_VERSION_WITH_RETURN_KIND; +} + +inline BOOL GCInfoEncodesRevPInvokeFrame(UINT32 version=GCINFO_VERSION) +{ + return version >= MIN_GCINFO_VERSION_WITH_REV_PINVOKE_FRAME; +} + //----------------------------------------------------------------------------- // GCInfoToken: A wrapper that contains the GcInfo data and version number. // @@ -62,11 +68,11 @@ struct GCInfoToken BOOL IsReturnKindAvailable() { - return (Version >= MIN_GCINFO_VERSION_WITH_RETURN_KIND); + return GCInfoEncodesReturnKind(Version); } BOOL IsReversePInvokeFrameAvailable() { - return (Version >= MIN_GCINFO_VERSION_WITH_REV_PINVOKE_FRAME); + return GCInfoEncodesRevPInvokeFrame(Version); } static UINT32 ReadyToRunVersionToGcInfoVersion(UINT32 readyToRunMajorVersion) diff --git a/src/inc/gcinfodecoder.h b/src/inc/gcinfodecoder.h index c77c359..6d4850a 100644 --- a/src/inc/gcinfodecoder.h +++ b/src/inc/gcinfodecoder.h @@ -11,16 +11,47 @@ #ifndef _GC_INFO_DECODER_ #define _GC_INFO_DECODER_ -#include "gcinfotypes.h" - #define _max(a, b) (((a) > (b)) ? (a) : (b)) #define _min(a, b) (((a) < (b)) ? (a) : (b)) -#ifndef GCINFODECODER_NO_EE +#if !defined(_TARGET_X86_) +#define USE_GC_INFO_DECODER +#endif + +#if !defined(GCINFODECODER_NO_EE) #include "eetwain.h" -#else // GCINFODECODER_NO_EE +#else + +#ifdef FEATURE_REDHAWK + +typedef ArrayDPTR(const uint8_t) PTR_CBYTE; + +#define LIMITED_METHOD_CONTRACT +#define SUPPORTS_DAC + +#define LOG(x) +#define LOG_PIPTR(pObjRef, gcFlags, hCallBack) +#define DAC_ARG(x) + +#define VALIDATE_ROOT(isInterior, hCallBack, pObjRef) + +#define _ASSERTE(x) assert(x) + +#define UINT32 UInt32 +#define INT32 Int32 +#define UINT16 UInt16 +#define UINT UInt32 +#define SIZE_T UIntNative +#define SSIZE_T IntNative +#define LPVOID void* + +typedef void * OBJECTREF; + +#define GET_CALLER_SP(pREGDISPLAY) ((TADDR)0) + +#else // FEATURE_REDHAWK // Stuff from cgencpu.h: @@ -112,11 +143,17 @@ inline BOOL IS_ALIGNED( void* val, size_t alignment ) #ifndef _EETWAIN_H typedef void (*GCEnumCallback)( - LPVOID hCallback, // callback data + void * hCallback, // callback data OBJECTREF* pObject, // address of obect-reference we are reporting uint32_t flags // is this a pinned and/or interior pointer ); +#endif // !_EETWAIN_H + +#include "regdisp.h" + +#endif // FEATURE_REDHAWK + #ifndef _strike_h enum ICodeManagerFlags @@ -135,16 +172,9 @@ enum ICodeManagerFlags #endif // !_strike_h -#if !defined(_TARGET_X86_) -#define USE_GC_INFO_DECODER -#endif - -#include "regdisp.h" - -#endif // !_EETWAIN_H - #endif // GCINFODECODER_NO_EE + #include "gcinfotypes.h" #ifdef _DEBUG @@ -153,10 +183,6 @@ enum ICodeManagerFlags #define MAX_PREDECODED_SLOTS 64 #endif -#if defined(FEATURE_PAL) && !defined(STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY) -#define STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY -#endif - enum GcInfoDecoderFlags @@ -286,8 +312,6 @@ public: __forceinline void SetCurrentPos( size_t pos ) { - STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; // note: this will set only the host instance, not the target instance - size_t adjPos = pos + m_InitialRelPos; m_pCurrent = m_pBuffer + adjPos / BITS_PER_SIZE_T; m_RelPos = (int)(adjPos % BITS_PER_SIZE_T); @@ -431,7 +455,7 @@ class GcInfoDecoder { public: - // If you are not insterested in interruptibility or gc lifetime information, pass 0 as instructionOffset + // If you are not interested in interruptibility or gc lifetime information, pass 0 as instructionOffset GcInfoDecoder( GCInfoToken gcInfoToken, GcInfoDecoderFlags flags = DECODE_EVERYTHING, @@ -448,16 +472,16 @@ public: // This is used for gccoverage bool IsSafePoint(UINT32 codeOffset); - typedef void EnumerateSafePointsCallback (UINT32 offset, LPVOID hCallback); - void EnumerateSafePoints(EnumerateSafePointsCallback *pCallback, LPVOID hCallback); + typedef void EnumerateSafePointsCallback (UINT32 offset, void * hCallback); + void EnumerateSafePoints(EnumerateSafePointsCallback * pCallback, void * hCallback); #endif // Returns true to stop enumerating. - typedef bool EnumerateInterruptibleRangesCallback (UINT32 startOffset, UINT32 stopOffset, LPVOID hCallback); + typedef bool EnumerateInterruptibleRangesCallback (UINT32 startOffset, UINT32 stopOffset, void * hCallback); void EnumerateInterruptibleRanges ( EnumerateInterruptibleRangesCallback *pCallback, - LPVOID hCallback); + void * hCallback); //------------------------------------------------------------------------ // GC lifetime information @@ -468,7 +492,7 @@ public: bool reportScratchSlots, unsigned flags, GCEnumCallback pCallBack, - LPVOID hCallBack + void * hCallBack ); // Public for the gc info dumper @@ -476,7 +500,7 @@ public: PREGDISPLAY pRD, unsigned flags, GCEnumCallback pCallBack, - LPVOID hCallBack + void * hCallBack ); //------------------------------------------------------------------------ @@ -490,7 +514,7 @@ public: UINT32 GetPrologSize(); INT32 GetPSPSymStackSlot(); INT32 GetGenericsInstContextStackSlot(); - INT32 GetReversePInvokeStackSlot(); + INT32 GetReversePInvokeFrameStackSlot(); bool HasMethodDescGenericsInstContext(); bool HasMethodTableGenericsInstContext(); bool GetIsVarArg(); @@ -518,7 +542,7 @@ private: bool m_WantsReportOnlyLeaf; INT32 m_SecurityObjectStackSlot; INT32 m_GSCookieStackSlot; - INT32 m_ReversePInvokeStackSlot; + INT32 m_ReversePInvokeFrameStackSlot; UINT32 m_ValidRangeStart; UINT32 m_ValidRangeEnd; INT32 m_PSPSymStackSlot; @@ -526,7 +550,6 @@ private: UINT32 m_CodeLength; UINT32 m_StackBaseRegister; UINT32 m_SizeOfEditAndContinuePreservedArea; - INT32 m_ReversePInvokeFrameSlot; ReturnKind m_ReturnKind; #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED UINT32 m_NumSafePoints; @@ -545,7 +568,7 @@ private: #endif UINT32 m_Version; - static bool SetIsInterruptibleCB (UINT32 startOffset, UINT32 stopOffset, LPVOID hCallback); + static bool SetIsInterruptibleCB (UINT32 startOffset, UINT32 stopOffset, void * hCallback); OBJECTREF* GetRegisterSlot( int regNum, @@ -577,7 +600,7 @@ private: PREGDISPLAY pRD, unsigned flags, GCEnumCallback pCallBack, - LPVOID hCallBack + void * hCallBack ); void ReportRegisterToGC( @@ -586,7 +609,7 @@ private: PREGDISPLAY pRD, unsigned flags, GCEnumCallback pCallBack, - LPVOID hCallBack + void * hCallBack ); void ReportStackSlotToGC( @@ -596,7 +619,7 @@ private: PREGDISPLAY pRD, unsigned flags, GCEnumCallback pCallBack, - LPVOID hCallBack + void * hCallBack ); @@ -607,7 +630,7 @@ private: bool reportScratchSlots, unsigned inputFlags, GCEnumCallback pCallBack, - LPVOID hCallBack + void * hCallBack ) { _ASSERTE(slotIndex < slotDecoder.GetNumSlots()); diff --git a/src/inc/gcinfoencoder.h b/src/inc/gcinfoencoder.h index 838f1ba..d09f430 100644 --- a/src/inc/gcinfoencoder.h +++ b/src/inc/gcinfoencoder.h @@ -100,6 +100,11 @@ #include "gcinfotypes.h" +// As stated in issue #6008, GcInfoSize should be incorporated into debug builds. +#ifdef _DEBUG +#define MEASURE_GCINFO +#endif + #ifdef MEASURE_GCINFO struct GcInfoSize { @@ -110,10 +115,13 @@ struct GcInfoSize size_t NumRanges; size_t NumRegs; size_t NumStack; - size_t NumEh; + size_t NumUntracked; size_t NumTransitions; size_t SizeOfCode; + size_t EncPreservedSlots; + size_t UntrackedSlotSize; + size_t NumUntrackedSize; size_t FlagsSize; size_t RetKindSize; size_t CodeLengthSize; @@ -134,7 +142,6 @@ struct GcInfoSize size_t RegSlotSize; size_t StackSlotSize; size_t CallSiteStateSize; - size_t NumEhSize; size_t EhPosSize; size_t EhStateSize; size_t ChunkPtrSize; diff --git a/src/inc/gcinfotypes.h b/src/inc/gcinfotypes.h index cd19759..c802d97 100644 --- a/src/inc/gcinfotypes.h +++ b/src/inc/gcinfotypes.h @@ -6,49 +6,15 @@ #ifndef __GCINFOTYPES_H__ #define __GCINFOTYPES_H__ +#ifndef FEATURE_REDHAWK #include "gcinfo.h" +#endif -// This file is included when building an "alt jit". In that case, we are doing a cross-compile: -// we may be building the ARM jit on x86, for example. We generally make that work by conditionalizing on -// a _TARGET_XXX_ variable that we explicitly set in the build, rather than the _XXX_ variable implicitly -// set by the compiler. But this file is *also* included by the runtime, and needs in that case to be -// conditionalized by the actual platform we're compiling for. We solve this by: -// 1) conditionalizing on _TARGET_XXX_ in this file, -// 2) having a _TARGET_SET_ variable so we know whether we're in a compilation for JIT in which some -// _TARGET_XXX_ has already been set, and -// 3) if _TARGET_SET_ is not set, set the _TARGET_XXX_ variable appropriate for the current _XXX_. -// -#ifndef _TARGET_SET_ - -//#ifdef _X86_ -//#define _TARGET_X86_ -//#endif - -//#ifdef _AMD64_ -//#define _TARGET_AMD64_ -//#endif - -//#ifdef _ARM_ -//#define _TARGET_ARM_ -//#endif - -#endif // _TARGET_SET_ -#if defined(_TARGET_AMD64_) || defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) #define PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED -#endif - -#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED -// -// The EH vector mechanism is not completely worked out, -// so it's temporarily disabled. We rely on fully-interruptible instead. -// -#define DISABLE_EH_VECTORS -#endif -#if defined(_TARGET_AMD64_) || defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) #define FIXED_STACK_PARAMETER_SCRATCH_AREA -#endif + #define BITS_PER_SIZE_T ((int)sizeof(size_t)*8) @@ -376,12 +342,17 @@ enum infoHdrAdjustConstants { SET_PROLOGSIZE_MAX = 16, SET_EPILOGSIZE_MAX = 10, // Change to 6 SET_EPILOGCNT_MAX = 4, - SET_UNTRACKED_MAX = 3 + SET_UNTRACKED_MAX = 3, + SET_RET_KIND_MAX = 4, // 2 bits for ReturnKind + ADJ_ENCODING_MAX = 0x7f, // Maximum valid encoding in a byte + // Also used to mask off next bit from each encoding byte. + MORE_BYTES_TO_FOLLOW = 0x80 // If the High-bit of a header or adjustment byte + // is set, then there are more adjustments to follow. }; // -// Enum to define the 128 codes that are used to incrementally adjust the InfoHdr structure -// +// Enum to define codes that are used to incrementally adjust the InfoHdr structure. +// First set of opcodes enum infoHdrAdjust { SET_FRAMESIZE = 0, // 0x00 @@ -412,18 +383,25 @@ enum infoHdrAdjust { FLIP_SYNC, // 0x4B FLIP_HAS_GENERICS_CONTEXT,// 0x4C FLIP_GENERICS_CONTEXT_IS_METHODDESC,// 0x4D + FLIP_REV_PINVOKE_FRAME, // 0x4E + NEXT_OPCODE, // 0x4F -- see next Adjustment enumeration + NEXT_FOUR_START = 0x50, + NEXT_FOUR_FRAMESIZE = 0x50, + NEXT_FOUR_ARGCOUNT = 0x60, + NEXT_THREE_PROLOGSIZE = 0x70, + NEXT_THREE_EPILOGSIZE = 0x78 +}; - // 0x4E .. 0x4f unused - - NEXT_FOUR_START = 0x50, - NEXT_FOUR_FRAMESIZE = 0x50, - NEXT_FOUR_ARGCOUNT = 0x60, - NEXT_THREE_PROLOGSIZE = 0x70, - NEXT_THREE_EPILOGSIZE = 0x78 +// Second set of opcodes, when first code is 0x4F +enum infoHdrAdjust2 { + SET_RETURNKIND = 0, // 0x00-SET_RET_KIND_MAX Set ReturnKind to value }; #define HAS_UNTRACKED ((unsigned int) -1) #define HAS_VARPTR ((unsigned int) -1) + +#define INVALID_REV_PINVOKE_OFFSET 0 +#define HAS_REV_PINVOKE_FRAME_OFFSET ((unsigned int) -1) // 0 is not a valid offset for EBP-frames as all locals are at a negative offset // For ESP frames, the cookie is above (at a higher address than) the buffers, // and so cannot be at offset 0. @@ -463,6 +441,7 @@ struct InfoHdrSmall { unsigned char profCallbacks : 1; // 4 [0] unsigned char genericsContext : 1;//4 [1] function reports a generics context parameter is present unsigned char genericsContextIsMethodDesc : 1;//4[2] + unsigned char returnKind : 2; // 4 [4] Available GcInfo v2 onwards, previously undefined unsigned short argCount; // 5,6 in bytes unsigned int frameSize; // 7,8,9,10 in bytes unsigned int untrackedCnt; // 11,12,13,14 @@ -483,8 +462,8 @@ struct InfoHdr : public InfoHdrSmall { unsigned int gsCookieOffset; // 19,20,21,22 unsigned int syncStartOffset; // 23,24,25,26 unsigned int syncEndOffset; // 27,28,29,30 - - // 31 bytes total + unsigned int revPInvokeOffset; // 31,32,33,34 Available GcInfo v2 onwards, previously undefined + // 35 bytes total // Checks whether "this" is compatible with "target". // It is not an exact bit match as "this" could have some @@ -498,7 +477,8 @@ struct InfoHdr : public InfoHdrSmall { _ASSERTE(target.untrackedCnt != HAS_UNTRACKED && target.varPtrTableSize != HAS_VARPTR && target.gsCookieOffset != HAS_GS_COOKIE_OFFSET && - target.syncStartOffset != HAS_SYNC_OFFSET); + target.syncStartOffset != HAS_SYNC_OFFSET && + target.revPInvokeOffset != HAS_REV_PINVOKE_FRAME_OFFSET); #endif // compare two InfoHdr's up to but not including the untrackCnt field @@ -525,6 +505,10 @@ struct InfoHdr : public InfoHdrSmall { (target.syncStartOffset == INVALID_SYNC_OFFSET)) return false; + if ((revPInvokeOffset == INVALID_REV_PINVOKE_OFFSET) != + (target.revPInvokeOffset == INVALID_REV_PINVOKE_OFFSET)) + return false; + return true; } }; @@ -551,15 +535,16 @@ inline void GetInfoHdr(int index, InfoHdr * header) { *((InfoHdrSmall *)header) = infoHdrShortcut[index]; - header->gsCookieOffset = 0; - header->syncStartOffset = 0; - header->syncEndOffset = 0; + header->gsCookieOffset = INVALID_GS_COOKIE_OFFSET; + header->syncStartOffset = INVALID_SYNC_OFFSET; + header->syncEndOffset = INVALID_SYNC_OFFSET; + header->revPInvokeOffset = INVALID_REV_PINVOKE_OFFSET; } -PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, InfoHdr* header); +PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, UINT32 version, InfoHdr* header); BYTE FASTCALL encodeHeaderFirst(const InfoHdr& header, InfoHdr* state, int* more, int *pCached); -BYTE FASTCALL encodeHeaderNext(const InfoHdr& header, InfoHdr* state); +BYTE FASTCALL encodeHeaderNext(const InfoHdr& header, InfoHdr* state, BYTE &codeSet); size_t FASTCALL decodeUnsigned(PTR_CBYTE src, unsigned* value); size_t FASTCALL decodeUDelta(PTR_CBYTE src, unsigned* value, unsigned lastValue); diff --git a/src/inc/jithelpers.h b/src/inc/jithelpers.h index 8a71992..f84db91 100644 --- a/src/inc/jithelpers.h +++ b/src/inc/jithelpers.h @@ -302,15 +302,16 @@ JITHELPER(CORINFO_HELP_VIRTUAL_FUNC_PTR, JIT_VirtualFunctionPointer, CORINFO_HELP_SIG_4_STACK) //JITHELPER(CORINFO_HELP_VIRTUAL_FUNC_PTR_LOG,JIT_VirtualFunctionPointerLogging) - JITHELPER(CORINFO_HELP_READYTORUN_NEW, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) - JITHELPER(CORINFO_HELP_READYTORUN_NEWARR_1, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) - JITHELPER(CORINFO_HELP_READYTORUN_ISINSTANCEOF, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) - JITHELPER(CORINFO_HELP_READYTORUN_CHKCAST, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) - JITHELPER(CORINFO_HELP_READYTORUN_STATIC_BASE, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) - JITHELPER(CORINFO_HELP_READYTORUN_VIRTUAL_FUNC_PTR, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_READYTORUN_NEW, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_READYTORUN_NEWARR_1, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_READYTORUN_ISINSTANCEOF, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_READYTORUN_CHKCAST, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_READYTORUN_STATIC_BASE, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_READYTORUN_VIRTUAL_FUNC_PTR, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) #if COR_JIT_EE_VERSION > 460 - JITHELPER(CORINFO_HELP_READYTORUN_GENERIC_HANDLE, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) - JITHELPER(CORINFO_HELP_READYTORUN_DELEGATE_CTOR, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_READYTORUN_GENERIC_HANDLE, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_READYTORUN_DELEGATE_CTOR, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) #endif // COR_JIT_EE_VERSION JITHELPER(CORINFO_HELP_EE_PRESTUB, ThePreStub, CORINFO_HELP_SIG_NO_ALIGN_STUB) diff --git a/src/inc/livedatatarget.h b/src/inc/livedatatarget.h index 7282dd4..1ffbca7 100644 --- a/src/inc/livedatatarget.h +++ b/src/inc/livedatatarget.h @@ -14,6 +14,7 @@ // Does not include IXClrData definitions. #include +#ifndef FEATURE_PAL //--------------------------------------------------------------------------------------- // @@ -100,6 +101,7 @@ private: CLRDATA_ADDRESS m_baseAddressOfEngine; }; +#endif // FEATURE_PAL #endif // _LIVEPROC_DATATARGET_H_ diff --git a/src/inc/longfilepathwrappers.h b/src/inc/longfilepathwrappers.h index a847988..a0ffe38 100644 --- a/src/inc/longfilepathwrappers.h +++ b/src/inc/longfilepathwrappers.h @@ -124,18 +124,18 @@ GetLongPathNameWrapper( SString& lpszLongPath ); -UINT GetTempFileNameWrapper( +UINT WINAPI GetTempFileNameWrapper( _In_ LPCTSTR lpPathName, _In_ LPCTSTR lpPrefixString, _In_ UINT uUnique, SString& lpTempFileName ); -DWORD GetTempPathWrapper( +DWORD WINAPI GetTempPathWrapper( SString& lpBuffer ); -DWORD GetCurrentDirectoryWrapper( +DWORD WINAPI GetCurrentDirectoryWrapper( SString& lpBuffer ); @@ -145,7 +145,7 @@ GetModuleFileNameWrapper( SString& buffer ); -DWORD GetEnvironmentVariableWrapper( +DWORD WINAPI GetEnvironmentVariableWrapper( _In_opt_ LPCTSTR lpName, _Out_opt_ SString& lpBuffer ); diff --git a/src/inc/shash.inl b/src/inc/shash.inl index 72affb4..f48899a 100644 --- a/src/inc/shash.inl +++ b/src/inc/shash.inl @@ -22,8 +22,8 @@ SHash::SHash() LIMITED_METHOD_CONTRACT; #ifndef __GNUC__ // these crash GCC - static_assert_no_msg(s_growth_factor_numerator > s_growth_factor_denominator); - static_assert_no_msg(s_density_factor_numerator < s_density_factor_denominator); + static_assert_no_msg(SHash::s_growth_factor_numerator > SHash::s_growth_factor_denominator); + static_assert_no_msg(SHash::s_density_factor_numerator < SHash::s_density_factor_denominator); #endif } diff --git a/src/inc/sortversioning.h b/src/inc/sortversioning.h index 7bc01c6..fe3e878 100644 --- a/src/inc/sortversioning.h +++ b/src/inc/sortversioning.h @@ -107,7 +107,7 @@ namespace SortVersioning PSORTHANDLE GetSortHandle(__in LPCWSTR lpLocaleName, __in_opt CONST NLSVERSIONINFO * pVersion); - int SortCompareString(__in LPCWSTR lpLocaleName, + int WINAPI SortCompareString(__in LPCWSTR lpLocaleName, __in DWORD dwCmpFlags, __in_ecount(cchCount1) LPCWSTR lpString1, __in int cchCount1, @@ -137,7 +137,7 @@ namespace SortVersioning __reserved LPVOID lpReserved, __reserved LPARAM lParam ); - __success(return != 0) int SortDllChangeCase( + __success(return != 0) int WINAPI SortDllChangeCase( __in PSORTHANDLE pSort, __in DWORD dwFlags, __in_ecount(cchSrc) LPCWSTR pSrc, @@ -147,7 +147,7 @@ namespace SortVersioning __in_opt LPVOID lpReserved, __in_opt LPARAM lParam ); - __success(return != 0) int SortDllGetSortKey( + __success(return != 0) int WINAPI SortDllGetSortKey( __in PSORTHANDLE pSort, __in DWORD dwFlags, __in_ecount(cchSrc) LPCWSTR pSrc, @@ -157,7 +157,7 @@ namespace SortVersioning __in_opt LPVOID lpReserved, __in_opt LPARAM lParam ); - int SortFindString(__in LPCWSTR lpLocaleName, + int WINAPI SortFindString(__in LPCWSTR lpLocaleName, __in DWORD dwFindNLSStringFlags, __in_ecount(cchSource) LPCWSTR lpStringSource, __in int cchSource, @@ -168,7 +168,7 @@ namespace SortVersioning __reserved LPVOID lpReserved, __reserved LPARAM lParam); - __success(return != 0) int SortDllFindString( + __success(return != 0) int WINAPI SortDllFindString( __in PSORTHANDLE pSort, __in DWORD dwFindNLSStringFlags, __in_ecount(cchSource) LPCWSTR lpStringSource, @@ -179,7 +179,7 @@ namespace SortVersioning __in_opt LPVOID lpReserved, __in_opt LPARAM lParam); - BOOL SortIsDefinedString(__in NLS_FUNCTION Function, + BOOL WINAPI SortIsDefinedString(__in NLS_FUNCTION Function, __in DWORD dwFlags, __in_opt CONST NLSVERSIONINFOEX * lpVersionInfo, __in LPCWSTR lpString, diff --git a/src/inc/stacktrace.h b/src/inc/stacktrace.h index 83646c8..49e9517 100644 --- a/src/inc/stacktrace.h +++ b/src/inc/stacktrace.h @@ -74,7 +74,7 @@ void GetStringFromStackLevels(UINT ifrStart, UINT cfrTotal, __out_ecount(cchMaxA ******************************************************************** robch */ void GetStringFromAddr(DWORD_PTR dwAddr, __out_ecount(cchMaxAssertStackLevelStringLen) LPSTR szString); -#if defined(_TARGET_X86_) && defined(FEATURE_CORECLR) +#if defined(_TARGET_X86_) && defined(FEATURE_CORECLR) && !defined(FEATURE_PAL) /**************************************************************************** * ClrCaptureContext * *-------------------* @@ -83,9 +83,9 @@ void GetStringFromAddr(DWORD_PTR dwAddr, __out_ecount(cchMaxAssertStackLevelStri * support this, so we need it for CoreCLR 4, if we require Win2K support ****************************************************************************/ extern "C" void __stdcall ClrCaptureContext(__out PCONTEXT ctx); -#else // _TARGET_X86_ && FEATURE_CORECLR +#else // _TARGET_X86_ && FEATURE_CORECLR && !FEATURE_PAL #define ClrCaptureContext RtlCaptureContext -#endif // _X86 && FEATURE_CORECLR else +#endif // _TARGET_X86_ && FEATURE_CORECLR && !FEATURE_PAL #endif diff --git a/src/inc/stresslog.h b/src/inc/stresslog.h index 86dee13..55fb27a 100644 --- a/src/inc/stresslog.h +++ b/src/inc/stresslog.h @@ -683,7 +683,7 @@ public: static const char* gcRootPromoteMsg() { STATIC_CONTRACT_LEAF; - return " GCHeap::Promote: Promote GC Root *%p = %p MT = %pT\n"; + return " IGCHeap::Promote: Promote GC Root *%p = %p MT = %pT\n"; } static const char* gcPlugMoveMsg() diff --git a/src/inc/utilcode.h b/src/inc/utilcode.h index c519e8b..a1a0836 100644 --- a/src/inc/utilcode.h +++ b/src/inc/utilcode.h @@ -134,6 +134,17 @@ inline TADDR PCODEToPINSTR(PCODE pc) #endif } +// Convert from a PINSTR to the corresponding PCODE. On many architectures this will be the identity function; +// on ARM, this will raise the THUMB bit. +inline PCODE PINSTRToPCODE(TADDR addr) +{ +#ifdef _TARGET_ARM_ + return DataPointerToThumbCode(addr); +#else + return dac_cast(addr); +#endif +} + typedef LPCSTR LPCUTF8; typedef LPSTR LPUTF8; @@ -3389,7 +3400,7 @@ public: m_iSize = iBuckets + 7; } - ~CClosedHashBase() + virtual ~CClosedHashBase() { WRAPPER_NO_CONTRACT; Clear(); @@ -5170,6 +5181,11 @@ template void DeleteExecutable(T *p) INDEBUG(BOOL DbgIsExecutable(LPVOID lpMem, SIZE_T length);) +BOOL NoGuiOnAssert(); +#ifdef _DEBUG +VOID TerminateOnAssert(); +#endif // _DEBUG + class HighCharHelper { public: static inline BOOL IsHighChar(int c) { @@ -5750,4 +5766,6 @@ extern SpinConstants g_SpinConstants; // ====================================================================================== +void* __stdcall GetCLRFunction(LPCSTR FunctionName); + #endif // __UtilCode_h__ diff --git a/src/inc/winwrap.h b/src/inc/winwrap.h index 91a71b7..4a012d3 100644 --- a/src/inc/winwrap.h +++ b/src/inc/winwrap.h @@ -86,8 +86,6 @@ #undef lstrcmp #undef lstrcmpi #undef lstrcpyn -#undef lstrcpy -#undef lstrcat #undef lstrlen #undef CreateMutex #undef OpenMutex @@ -222,7 +220,6 @@ // winuser.h #undef MAKEINTRESOURCE #undef wvsprintf -#undef wsprintf #undef LoadKeyboardLayout #undef GetKeyboardLayoutName #undef CreateDesktop @@ -395,8 +392,6 @@ #define WszQueryRecoveryAgents QueryRecoveryAgentsW #define Wszlstrcmp lstrcmpW #define Wszlstrcmpi lstrcmpiW -#define Wszlstrcpy lstrcpyW -#define Wszlstrcat lstrcatW #define WszCreateMutex CreateMutexW #define WszOpenMutex OpenMutexW #define WszCreateEvent CreateEventW @@ -684,8 +679,6 @@ // on win98 and higher #define Wszlstrlen lstrlenW -#define Wszlstrcpy lstrcpyW -#define Wszlstrcat lstrcatW //File and Directory Functions which need special handling for LongFile Names //Note only the functions which are currently used are defined diff --git a/src/inc/xmlparser_i.c b/src/inc/xmlparser_i.cpp similarity index 100% rename from src/inc/xmlparser_i.c rename to src/inc/xmlparser_i.cpp diff --git a/src/inc/zapper.h b/src/inc/zapper.h index 2fa9437..1018505 100644 --- a/src/inc/zapper.h +++ b/src/inc/zapper.h @@ -540,7 +540,7 @@ class ZapperOptions bool m_fNGenLastRetry; // This is retry of the compilation - unsigned m_compilerFlags; + CORJIT_FLAGS m_compilerFlags; bool m_legacyMode; // true if the zapper was invoked using legacy mode diff --git a/src/ipcman/ipcshared.h b/src/ipcman/ipcshared.h index d40b0ba..865509d 100644 --- a/src/ipcman/ipcshared.h +++ b/src/ipcman/ipcshared.h @@ -75,8 +75,8 @@ public: HANDLE & pPrivateNamespace, PSID* pSID, BOOL bCreate); - static HRESULT IPCShared::FreeHandles(HANDLE & hDescriptor, PSID & pSID); - static HRESULT IPCShared::FreeHandles(HANDLE & hBoundaryDescriptor, PSID & pSID, HANDLE & hPrivateNamespace); + static HRESULT FreeHandles(HANDLE & hDescriptor, PSID & pSID); + static HRESULT FreeHandles(HANDLE & hBoundaryDescriptor, PSID & pSID, HANDLE & hPrivateNamespace); static HRESULT CreateWinNTDescriptor(DWORD pid, BOOL bRestrictiveACL, SECURITY_ATTRIBUTES **ppSA, KernelObject whatObject); static HRESULT CreateWinNTDescriptor(DWORD pid, BOOL bRestrictiveACL, SECURITY_ATTRIBUTES **ppSA, KernelObject whatObject, EDescriptorType descType); static void DestroySecurityAttributes(SECURITY_ATTRIBUTES *pSA); diff --git a/src/jit/CMakeLists.txt b/src/jit/CMakeLists.txt index 6372e37..96b8c49 100644 --- a/src/jit/CMakeLists.txt +++ b/src/jit/CMakeLists.txt @@ -7,9 +7,9 @@ include_directories("../inc") # Enable the following for UNIX altjit on Windows # add_definitions(-DALT_JIT) -if (CLR_CMAKE_TARGET_ARCH_AMD64) - add_definitions(-DFEATURE_SIMD) - add_definitions(-DFEATURE_AVX_SUPPORT) +if (CLR_CMAKE_TARGET_ARCH_AMD64 OR (CLR_CMAKE_TARGET_ARCH_I386 AND NOT CLR_CMAKE_PLATFORM_UNIX)) + add_definitions(-DFEATURE_SIMD) + add_definitions(-DFEATURE_AVX_SUPPORT) endif () @@ -23,6 +23,7 @@ set( JIT_SOURCES bitset.cpp block.cpp codegencommon.cpp + codegenlinear.cpp compiler.cpp copyprop.cpp disasm.cpp @@ -194,19 +195,17 @@ endif() add_custom_target(jit_exports DEPENDS ${JIT_EXPORTS_FILE}) -set(JIT_BASE_NAME clrjit) -if (CLR_BUILD_JIT32) - set(JIT_BASE_NAME ryujit) -endif() - -if(WIN32) - add_definitions(-DFX_VER_INTERNALNAME_STR=${JIT_BASE_NAME}.dll) -endif(WIN32) - add_subdirectory(dll) add_subdirectory(crossgen) add_subdirectory(standalone) -if (CLR_CMAKE_PLATFORM_ARCH_I386 OR CLR_CMAKE_PLATFORM_ARCH_ARM) +if (CLR_CMAKE_PLATFORM_ARCH_ARM) add_subdirectory(protojit) -endif (CLR_CMAKE_PLATFORM_ARCH_I386 OR CLR_CMAKE_PLATFORM_ARCH_ARM) +endif (CLR_CMAKE_PLATFORM_ARCH_ARM) + +if (CLR_CMAKE_PLATFORM_ARCH_I386) + add_subdirectory(legacyjit) + if (NOT CLR_BUILD_JIT32) + add_subdirectory(compatjit) + endif () +endif (CLR_CMAKE_PLATFORM_ARCH_I386) diff --git a/src/jit/ICorJitInfo_API_names.h b/src/jit/ICorJitInfo_API_names.h new file mode 100644 index 0000000..601afbd --- /dev/null +++ b/src/jit/ICorJitInfo_API_names.h @@ -0,0 +1,171 @@ +// 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. + +DEF_CLR_API(getMethodAttribs) +DEF_CLR_API(setMethodAttribs) +DEF_CLR_API(getMethodSig) +DEF_CLR_API(getMethodInfo) +DEF_CLR_API(canInline) +DEF_CLR_API(reportInliningDecision) +DEF_CLR_API(canTailCall) +DEF_CLR_API(reportTailCallDecision) +DEF_CLR_API(getEHinfo) +DEF_CLR_API(getMethodClass) +DEF_CLR_API(getMethodModule) +DEF_CLR_API(getMethodVTableOffset) +DEF_CLR_API(getIntrinsicID) +DEF_CLR_API(isInSIMDModule) +DEF_CLR_API(getUnmanagedCallConv) +DEF_CLR_API(pInvokeMarshalingRequired) +DEF_CLR_API(satisfiesMethodConstraints) +DEF_CLR_API(isCompatibleDelegate) +DEF_CLR_API(isDelegateCreationAllowed) +DEF_CLR_API(isInstantiationOfVerifiedGeneric) +DEF_CLR_API(initConstraintsForVerification) +DEF_CLR_API(canSkipMethodVerification) +DEF_CLR_API(methodMustBeLoadedBeforeCodeIsRun) +DEF_CLR_API(mapMethodDeclToMethodImpl) +DEF_CLR_API(getGSCookie) +DEF_CLR_API(resolveToken) +DEF_CLR_API(tryResolveToken) +DEF_CLR_API(findSig) +DEF_CLR_API(findCallSiteSig) +DEF_CLR_API(getTokenTypeAsHandle) +DEF_CLR_API(canSkipVerification) +DEF_CLR_API(isValidToken) +DEF_CLR_API(isValidStringRef) +DEF_CLR_API(shouldEnforceCallvirtRestriction) +DEF_CLR_API(asCorInfoType) +DEF_CLR_API(getClassName) +DEF_CLR_API(appendClassName) +DEF_CLR_API(isValueClass) +DEF_CLR_API(canInlineTypeCheckWithObjectVTable) +DEF_CLR_API(getClassAttribs) +DEF_CLR_API(isStructRequiringStackAllocRetBuf) +DEF_CLR_API(getClassModule) +DEF_CLR_API(getModuleAssembly) +DEF_CLR_API(getAssemblyName) +DEF_CLR_API(LongLifetimeMalloc) +DEF_CLR_API(LongLifetimeFree) +DEF_CLR_API(getClassModuleIdForStatics) +DEF_CLR_API(getClassSize) +DEF_CLR_API(getClassAlignmentRequirement) +DEF_CLR_API(getClassGClayout) +DEF_CLR_API(getClassNumInstanceFields) +DEF_CLR_API(getFieldInClass) +DEF_CLR_API(checkMethodModifier) +DEF_CLR_API(getNewHelper) +DEF_CLR_API(getNewArrHelper) +DEF_CLR_API(getCastingHelper) +DEF_CLR_API(getSharedCCtorHelper) +DEF_CLR_API(getSecurityPrologHelper) +DEF_CLR_API(getTypeForBox) +DEF_CLR_API(getBoxHelper) +DEF_CLR_API(getUnBoxHelper) +DEF_CLR_API(getReadyToRunHelper) +DEF_CLR_API(getReadyToRunDelegateCtorHelper) +DEF_CLR_API(getHelperName) +DEF_CLR_API(initClass) +DEF_CLR_API(classMustBeLoadedBeforeCodeIsRun) +DEF_CLR_API(getBuiltinClass) +DEF_CLR_API(getTypeForPrimitiveValueClass) +DEF_CLR_API(canCast) +DEF_CLR_API(areTypesEquivalent) +DEF_CLR_API(mergeClasses) +DEF_CLR_API(getParentType) +DEF_CLR_API(getChildType) +DEF_CLR_API(satisfiesClassConstraints) +DEF_CLR_API(isSDArray) +DEF_CLR_API(getArrayRank) +DEF_CLR_API(getArrayInitializationData) +DEF_CLR_API(canAccessClass) +DEF_CLR_API(getFieldName) +DEF_CLR_API(getFieldClass) +DEF_CLR_API(getFieldType) +DEF_CLR_API(getFieldOffset) +DEF_CLR_API(isWriteBarrierHelperRequired) +DEF_CLR_API(getFieldInfo) +DEF_CLR_API(isFieldStatic) +DEF_CLR_API(getBoundaries) +DEF_CLR_API(setBoundaries) +DEF_CLR_API(getVars) +DEF_CLR_API(setVars) +DEF_CLR_API(allocateArray) +DEF_CLR_API(freeArray) +DEF_CLR_API(getArgNext) +DEF_CLR_API(getArgType) +DEF_CLR_API(getArgClass) +DEF_CLR_API(getHFAType) +DEF_CLR_API(GetErrorHRESULT) +DEF_CLR_API(GetErrorMessage) +DEF_CLR_API(FilterException) +DEF_CLR_API(HandleException) +DEF_CLR_API(ThrowExceptionForJitResult) +DEF_CLR_API(ThrowExceptionForHelper) +DEF_CLR_API(getEEInfo) +DEF_CLR_API(getJitTimeLogFilename) +DEF_CLR_API(getMethodDefFromMethod) +DEF_CLR_API(getMethodName) +DEF_CLR_API(getMethodHash) +DEF_CLR_API(findNameOfToken) +DEF_CLR_API(getSystemVAmd64PassStructInRegisterDescriptor) +DEF_CLR_API(getThreadTLSIndex) +DEF_CLR_API(getInlinedCallFrameVptr) +DEF_CLR_API(getAddrOfCaptureThreadGlobal) +DEF_CLR_API(getAddrModuleDomainID) +DEF_CLR_API(getHelperFtn) +DEF_CLR_API(getFunctionEntryPoint) +DEF_CLR_API(getFunctionFixedEntryPoint) +DEF_CLR_API(getMethodSync) +DEF_CLR_API(getLazyStringLiteralHelper) +DEF_CLR_API(embedModuleHandle) +DEF_CLR_API(embedClassHandle) +DEF_CLR_API(embedMethodHandle) +DEF_CLR_API(embedFieldHandle) +DEF_CLR_API(embedGenericHandle) +DEF_CLR_API(getLocationOfThisType) +DEF_CLR_API(getPInvokeUnmanagedTarget) +DEF_CLR_API(getAddressOfPInvokeFixup) +DEF_CLR_API(getAddressOfPInvokeTarget) +DEF_CLR_API(GetCookieForPInvokeCalliSig) +DEF_CLR_API(canGetCookieForPInvokeCalliSig) +DEF_CLR_API(getJustMyCodeHandle) +DEF_CLR_API(GetProfilingHandle) +DEF_CLR_API(getCallInfo) +DEF_CLR_API(canAccessFamily) +DEF_CLR_API(isRIDClassDomainID) +DEF_CLR_API(getClassDomainID) +DEF_CLR_API(getFieldAddress) +DEF_CLR_API(getVarArgsHandle) +DEF_CLR_API(canGetVarArgsHandle) +DEF_CLR_API(constructStringLiteral) +DEF_CLR_API(emptyStringLiteral) +DEF_CLR_API(getFieldThreadLocalStoreID) +DEF_CLR_API(setOverride) +DEF_CLR_API(addActiveDependency) +DEF_CLR_API(GetDelegateCtor) +DEF_CLR_API(MethodCompileComplete) +DEF_CLR_API(getTailCallCopyArgsThunk) +DEF_CLR_API(getJitFlags) +DEF_CLR_API(runWithErrorTrap) +DEF_CLR_API(getMemoryManager) +DEF_CLR_API(allocMem) +DEF_CLR_API(reserveUnwindInfo) +DEF_CLR_API(allocUnwindInfo) +DEF_CLR_API(allocGCInfo) +DEF_CLR_API(yieldExecution) +DEF_CLR_API(setEHcount) +DEF_CLR_API(setEHinfo) +DEF_CLR_API(logMsg) +DEF_CLR_API(doAssert) +DEF_CLR_API(reportFatalError) +DEF_CLR_API(allocBBProfileBuffer) +DEF_CLR_API(getBBProfileData) +DEF_CLR_API(recordCallSite) +DEF_CLR_API(recordRelocation) +DEF_CLR_API(getRelocTypeHint) +DEF_CLR_API(getModuleNativeEntryPointRange) +DEF_CLR_API(getExpectedTargetArchitecture) + +#undef DEF_CLR_API diff --git a/src/jit/ICorJitInfo_API_wrapper.hpp b/src/jit/ICorJitInfo_API_wrapper.hpp new file mode 100644 index 0000000..4272b27 --- /dev/null +++ b/src/jit/ICorJitInfo_API_wrapper.hpp @@ -0,0 +1,1666 @@ +// 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. + +#define API_ENTER(name) wrapComp->CLR_API_Enter(API_##name); +#define API_LEAVE(name) wrapComp->CLR_API_Leave(API_##name); + +/**********************************************************************************/ +// clang-format off +/**********************************************************************************/ +// +// ICorMethodInfo +// + +DWORD WrapICorJitInfo::getMethodAttribs(CORINFO_METHOD_HANDLE ftn /* IN */) +{ + API_ENTER(getMethodAttribs) + DWORD temp = wrapHnd->getMethodAttribs(ftn); + API_LEAVE(getMethodAttribs) + return temp; +} + +void WrapICorJitInfo::setMethodAttribs(CORINFO_METHOD_HANDLE ftn,/* IN */ + CorInfoMethodRuntimeFlags attribs/* IN */) +{ + API_ENTER(setMethodAttribs); + wrapHnd->setMethodAttribs(ftn, attribs); + API_LEAVE(setMethodAttribs); +} + +void WrapICorJitInfo::getMethodSig(CORINFO_METHOD_HANDLE ftn, /* IN */ + CORINFO_SIG_INFO *sig, /* OUT */ + CORINFO_CLASS_HANDLE memberParent/* IN */) +{ + API_ENTER(getMethodSig); + wrapHnd->getMethodSig(ftn, sig, memberParent); + API_LEAVE(getMethodSig); +} + +bool WrapICorJitInfo::getMethodInfo( + CORINFO_METHOD_HANDLE ftn, /* IN */ + CORINFO_METHOD_INFO* info /* OUT */) +{ + API_ENTER(getMethodInfo); + bool temp = wrapHnd->getMethodInfo(ftn, info); + API_LEAVE(getMethodInfo); + return temp; +} + +CorInfoInline WrapICorJitInfo::canInline( + CORINFO_METHOD_HANDLE callerHnd, /* IN */ + CORINFO_METHOD_HANDLE calleeHnd, /* IN */ + DWORD* pRestrictions /* OUT */) +{ + API_ENTER(canInline); + CorInfoInline temp = wrapHnd->canInline(callerHnd, calleeHnd, pRestrictions); + API_LEAVE(canInline); + return temp; +} + +void WrapICorJitInfo::reportInliningDecision(CORINFO_METHOD_HANDLE inlinerHnd, + CORINFO_METHOD_HANDLE inlineeHnd, + CorInfoInline inlineResult, + const char * reason) +{ + API_ENTER(reportInliningDecision); + wrapHnd->reportInliningDecision(inlinerHnd, inlineeHnd, inlineResult, reason); + API_LEAVE(reportInliningDecision); +} + +bool WrapICorJitInfo::canTailCall( + CORINFO_METHOD_HANDLE callerHnd, /* IN */ + CORINFO_METHOD_HANDLE declaredCalleeHnd, /* IN */ + CORINFO_METHOD_HANDLE exactCalleeHnd, /* IN */ + bool fIsTailPrefix /* IN */) +{ + API_ENTER(canTailCall); + bool temp = wrapHnd->canTailCall(callerHnd, declaredCalleeHnd, exactCalleeHnd, fIsTailPrefix); + API_LEAVE(canTailCall); + return temp; +} + +void WrapICorJitInfo::reportTailCallDecision(CORINFO_METHOD_HANDLE callerHnd, + CORINFO_METHOD_HANDLE calleeHnd, + bool fIsTailPrefix, + CorInfoTailCall tailCallResult, + const char * reason) +{ + API_ENTER(reportTailCallDecision); + wrapHnd->reportTailCallDecision(callerHnd, calleeHnd, fIsTailPrefix, tailCallResult, reason); + API_LEAVE(reportTailCallDecision); +} + +void WrapICorJitInfo::getEHinfo( + CORINFO_METHOD_HANDLE ftn, /* IN */ + unsigned EHnumber, /* IN */ + CORINFO_EH_CLAUSE* clause /* OUT */) +{ + API_ENTER(getEHinfo); + wrapHnd->getEHinfo(ftn, EHnumber, clause); + API_LEAVE(getEHinfo); +} + +CORINFO_CLASS_HANDLE WrapICorJitInfo::getMethodClass( + CORINFO_METHOD_HANDLE method) +{ + API_ENTER(getMethodClass); + CORINFO_CLASS_HANDLE temp = wrapHnd->getMethodClass(method); + API_LEAVE(getMethodClass); + return temp; +} + +CORINFO_MODULE_HANDLE WrapICorJitInfo::getMethodModule( + CORINFO_METHOD_HANDLE method) +{ + API_ENTER(getMethodModule); + CORINFO_MODULE_HANDLE temp = wrapHnd->getMethodModule(method); + API_LEAVE(getMethodModule); + return temp; +} + +void WrapICorJitInfo::getMethodVTableOffset( + CORINFO_METHOD_HANDLE method, /* IN */ + unsigned* offsetOfIndirection, /* OUT */ + unsigned* offsetAfterIndirection /* OUT */) +{ + API_ENTER(getMethodVTableOffset); + wrapHnd->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection); + API_LEAVE(getMethodVTableOffset); +} + +#if COR_JIT_EE_VERSION > 460 + +CorInfoIntrinsics WrapICorJitInfo::getIntrinsicID( + CORINFO_METHOD_HANDLE method, + bool* pMustExpand /* OUT */) +{ + API_ENTER(getIntrinsicID); + CorInfoIntrinsics temp = wrapHnd->getIntrinsicID(method, pMustExpand); + API_LEAVE(getIntrinsicID); + return temp; +} + +#else + +CorInfoIntrinsics WrapICorJitInfo::getIntrinsicID(CORINFO_METHOD_HANDLE method) +{ + API_ENTER(getIntrinsicID); + CorInfoIntrinsics temp = wrapHnd->getIntrinsicID(method); + API_LEAVE(getIntrinsicID); + return temp; +} + +#endif + +bool WrapICorJitInfo::isInSIMDModule(CORINFO_CLASS_HANDLE classHnd) +{ + API_ENTER(isInSIMDModule); + bool temp = wrapHnd->isInSIMDModule(classHnd); + API_LEAVE(isInSIMDModule); + return temp; +} + +CorInfoUnmanagedCallConv WrapICorJitInfo::getUnmanagedCallConv( + CORINFO_METHOD_HANDLE method) +{ + API_ENTER(getUnmanagedCallConv); + CorInfoUnmanagedCallConv temp = wrapHnd->getUnmanagedCallConv(method); + API_LEAVE(getUnmanagedCallConv); + return temp; +} + +BOOL WrapICorJitInfo::pInvokeMarshalingRequired( + CORINFO_METHOD_HANDLE method, + CORINFO_SIG_INFO* callSiteSig) +{ + API_ENTER(pInvokeMarshalingRequired); + BOOL temp = wrapHnd->pInvokeMarshalingRequired(method, callSiteSig); + API_LEAVE(pInvokeMarshalingRequired); + return temp; +} + +BOOL WrapICorJitInfo::satisfiesMethodConstraints( + CORINFO_CLASS_HANDLE parent, // the exact parent of the method + CORINFO_METHOD_HANDLE method) +{ + API_ENTER(satisfiesMethodConstraints); + BOOL temp = wrapHnd->satisfiesMethodConstraints(parent, method); + API_LEAVE(satisfiesMethodConstraints); + return temp; +} + +BOOL WrapICorJitInfo::isCompatibleDelegate( + CORINFO_CLASS_HANDLE objCls, + CORINFO_CLASS_HANDLE methodParentCls, + CORINFO_METHOD_HANDLE method, + CORINFO_CLASS_HANDLE delegateCls, + BOOL *pfIsOpenDelegate) +{ + API_ENTER(isCompatibleDelegate); + BOOL temp = wrapHnd->isCompatibleDelegate(objCls, methodParentCls, method, delegateCls, pfIsOpenDelegate); + API_LEAVE(isCompatibleDelegate); + return temp; +} + +BOOL WrapICorJitInfo::isDelegateCreationAllowed( + CORINFO_CLASS_HANDLE delegateHnd, + CORINFO_METHOD_HANDLE calleeHnd) +{ + API_ENTER(isDelegateCreationAllowed); + BOOL temp = wrapHnd->isDelegateCreationAllowed(delegateHnd, calleeHnd); + API_LEAVE(isDelegateCreationAllowed); + return temp; +} + + +CorInfoInstantiationVerification WrapICorJitInfo::isInstantiationOfVerifiedGeneric( + CORINFO_METHOD_HANDLE method /* IN */) +{ + API_ENTER(isInstantiationOfVerifiedGeneric); + CorInfoInstantiationVerification temp = wrapHnd->isInstantiationOfVerifiedGeneric(method); + API_LEAVE(isInstantiationOfVerifiedGeneric); + return temp; +} + +void WrapICorJitInfo::initConstraintsForVerification( + CORINFO_METHOD_HANDLE method, /* IN */ + BOOL *pfHasCircularClassConstraints, /* OUT */ + BOOL *pfHasCircularMethodConstraint /* OUT */) +{ + API_ENTER(initConstraintsForVerification); + wrapHnd->initConstraintsForVerification(method, pfHasCircularClassConstraints, pfHasCircularMethodConstraint); + API_LEAVE(initConstraintsForVerification); +} + +CorInfoCanSkipVerificationResult WrapICorJitInfo::canSkipMethodVerification( + CORINFO_METHOD_HANDLE ftnHandle) +{ + API_ENTER(canSkipMethodVerification); + CorInfoCanSkipVerificationResult temp = wrapHnd->canSkipMethodVerification(ftnHandle); + API_LEAVE(canSkipMethodVerification); + return temp; +} + +void WrapICorJitInfo::methodMustBeLoadedBeforeCodeIsRun( + CORINFO_METHOD_HANDLE method) +{ + API_ENTER(methodMustBeLoadedBeforeCodeIsRun); + wrapHnd->methodMustBeLoadedBeforeCodeIsRun(method); + API_LEAVE(methodMustBeLoadedBeforeCodeIsRun); +} + +CORINFO_METHOD_HANDLE WrapICorJitInfo::mapMethodDeclToMethodImpl( + CORINFO_METHOD_HANDLE method) +{ + API_ENTER(mapMethodDeclToMethodImpl); + CORINFO_METHOD_HANDLE temp = wrapHnd->mapMethodDeclToMethodImpl(method); + API_LEAVE(mapMethodDeclToMethodImpl); + return temp; +} + +void WrapICorJitInfo::getGSCookie( + GSCookie * pCookieVal, + GSCookie ** ppCookieVal ) +{ + API_ENTER(getGSCookie); + wrapHnd->getGSCookie(pCookieVal, ppCookieVal); + API_LEAVE(getGSCookie); +} + +/**********************************************************************************/ +// +// ICorModuleInfo +// +/**********************************************************************************/ + +void WrapICorJitInfo::resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken) +{ + API_ENTER(resolveToken); + wrapHnd->resolveToken(pResolvedToken); + API_LEAVE(resolveToken); +} + +#if COR_JIT_EE_VERSION > 460 + +bool WrapICorJitInfo::tryResolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken) +{ + API_ENTER(tryResolveToken); + bool success = wrapHnd->tryResolveToken(pResolvedToken); + API_LEAVE(tryResolveToken); + return success; +} + +#endif + +void WrapICorJitInfo::findSig( + CORINFO_MODULE_HANDLE module, + unsigned sigTOK, + CORINFO_CONTEXT_HANDLE context, + CORINFO_SIG_INFO *sig ) +{ + API_ENTER(findSig); + wrapHnd->findSig(module, sigTOK, context, sig); + API_LEAVE(findSig); +} + +void WrapICorJitInfo::findCallSiteSig( + CORINFO_MODULE_HANDLE module, /* IN */ + unsigned methTOK, /* IN */ + CORINFO_CONTEXT_HANDLE context, /* IN */ + CORINFO_SIG_INFO *sig /* OUT */) +{ + API_ENTER(findCallSiteSig); + wrapHnd->findCallSiteSig(module, methTOK, context, sig); + API_LEAVE(findCallSiteSig); +} + +CORINFO_CLASS_HANDLE WrapICorJitInfo::getTokenTypeAsHandle( + CORINFO_RESOLVED_TOKEN * pResolvedToken /* IN */) +{ + API_ENTER(getTokenTypeAsHandle); + CORINFO_CLASS_HANDLE temp = wrapHnd->getTokenTypeAsHandle(pResolvedToken); + API_LEAVE(getTokenTypeAsHandle); + return temp; +} + +CorInfoCanSkipVerificationResult WrapICorJitInfo::canSkipVerification( + CORINFO_MODULE_HANDLE module /* IN */) +{ + API_ENTER(canSkipVerification); + CorInfoCanSkipVerificationResult temp = wrapHnd->canSkipVerification(module); + API_LEAVE(canSkipVerification); + return temp; +} + +BOOL WrapICorJitInfo::isValidToken( + CORINFO_MODULE_HANDLE module, /* IN */ + unsigned metaTOK /* IN */) +{ + API_ENTER(isValidToken); + BOOL result = wrapHnd->isValidToken(module, metaTOK); + API_LEAVE(isValidToken); + return result; +} + +BOOL WrapICorJitInfo::isValidStringRef( + CORINFO_MODULE_HANDLE module, /* IN */ + unsigned metaTOK /* IN */) +{ + API_ENTER(isValidStringRef); + BOOL temp = wrapHnd->isValidStringRef(module, metaTOK); + API_LEAVE(isValidStringRef); + return temp; +} + +BOOL WrapICorJitInfo::shouldEnforceCallvirtRestriction( + CORINFO_MODULE_HANDLE scope) +{ + API_ENTER(shouldEnforceCallvirtRestriction); + BOOL temp = wrapHnd->shouldEnforceCallvirtRestriction(scope); + API_LEAVE(shouldEnforceCallvirtRestriction); + return temp; +} + +/**********************************************************************************/ +// +// ICorClassInfo +// +/**********************************************************************************/ + +CorInfoType WrapICorJitInfo::asCorInfoType(CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(asCorInfoType); + CorInfoType temp = wrapHnd->asCorInfoType(cls); + API_LEAVE(asCorInfoType); + return temp; +} + +const char* WrapICorJitInfo::getClassName(CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(getClassName); + const char* result = wrapHnd->getClassName(cls); + API_LEAVE(getClassName); + return result; +} + +int WrapICorJitInfo::appendClassName( + __deref_inout_ecount(*pnBufLen) WCHAR** ppBuf, + int* pnBufLen, + CORINFO_CLASS_HANDLE cls, + BOOL fNamespace, + BOOL fFullInst, + BOOL fAssembly) +{ + API_ENTER(appendClassName); + WCHAR* pBuf = *ppBuf; + int nLen = wrapHnd->appendClassName(ppBuf, pnBufLen, cls, fNamespace, fFullInst, fAssembly); + API_LEAVE(appendClassName); + return nLen; +} + +BOOL WrapICorJitInfo::isValueClass(CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(isValueClass); + BOOL temp = wrapHnd->isValueClass(cls); + API_LEAVE(isValueClass); + return temp; +} + +BOOL WrapICorJitInfo::canInlineTypeCheckWithObjectVTable(CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(canInlineTypeCheckWithObjectVTable); + BOOL temp = wrapHnd->canInlineTypeCheckWithObjectVTable(cls); + API_LEAVE(canInlineTypeCheckWithObjectVTable); + return temp; +} + +DWORD WrapICorJitInfo::getClassAttribs( + CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(getClassAttribs); + DWORD temp = wrapHnd->getClassAttribs(cls); + API_LEAVE(getClassAttribs); + return temp; +} + +BOOL WrapICorJitInfo::isStructRequiringStackAllocRetBuf(CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(isStructRequiringStackAllocRetBuf); + BOOL temp = wrapHnd->isStructRequiringStackAllocRetBuf(cls); + API_LEAVE(isStructRequiringStackAllocRetBuf); + return temp; +} + +CORINFO_MODULE_HANDLE WrapICorJitInfo::getClassModule( + CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(getClassModule); + CORINFO_MODULE_HANDLE result = wrapHnd->getClassModule(cls); + API_LEAVE(getClassModule); + return result; +} + +CORINFO_ASSEMBLY_HANDLE WrapICorJitInfo::getModuleAssembly( + CORINFO_MODULE_HANDLE mod) +{ + API_ENTER(getModuleAssembly); + CORINFO_ASSEMBLY_HANDLE result = wrapHnd->getModuleAssembly(mod); + API_LEAVE(getModuleAssembly); + return result; +} + +const char* WrapICorJitInfo::getAssemblyName( + CORINFO_ASSEMBLY_HANDLE assem) +{ + API_ENTER(getAssemblyName); + const char* result = wrapHnd->getAssemblyName(assem); + API_LEAVE(getAssemblyName); + return result; +} + +void* WrapICorJitInfo::LongLifetimeMalloc(size_t sz) +{ + API_ENTER(LongLifetimeMalloc); + void* result = wrapHnd->LongLifetimeMalloc(sz); + API_LEAVE(LongLifetimeMalloc); + return result; +} + +void WrapICorJitInfo::LongLifetimeFree(void* obj) +{ + API_ENTER(LongLifetimeFree); + wrapHnd->LongLifetimeFree(obj); + API_LEAVE(LongLifetimeFree); +} + +size_t WrapICorJitInfo::getClassModuleIdForStatics( + CORINFO_CLASS_HANDLE cls, + CORINFO_MODULE_HANDLE *pModule, + void **ppIndirection) +{ + API_ENTER(getClassModuleIdForStatics); + size_t temp = wrapHnd->getClassModuleIdForStatics(cls, pModule, ppIndirection); + API_LEAVE(getClassModuleIdForStatics); + return temp; +} + +unsigned WrapICorJitInfo::getClassSize(CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(getClassSize); + unsigned temp = wrapHnd->getClassSize(cls); + API_LEAVE(getClassSize); + return temp; +} + +unsigned WrapICorJitInfo::getClassAlignmentRequirement( + CORINFO_CLASS_HANDLE cls, + BOOL fDoubleAlignHint) +{ + API_ENTER(getClassAlignmentRequirement); + unsigned temp = wrapHnd->getClassAlignmentRequirement(cls, fDoubleAlignHint); + API_LEAVE(getClassAlignmentRequirement); + return temp; +} + +unsigned WrapICorJitInfo::getClassGClayout( + CORINFO_CLASS_HANDLE cls, /* IN */ + BYTE *gcPtrs /* OUT */) +{ + API_ENTER(getClassGClayout); + unsigned temp = wrapHnd->getClassGClayout(cls, gcPtrs); + API_LEAVE(getClassGClayout); + return temp; +} + +unsigned WrapICorJitInfo::getClassNumInstanceFields( + CORINFO_CLASS_HANDLE cls /* IN */) +{ + API_ENTER(getClassNumInstanceFields); + unsigned temp = wrapHnd->getClassNumInstanceFields(cls); + API_LEAVE(getClassNumInstanceFields); + return temp; +} + +CORINFO_FIELD_HANDLE WrapICorJitInfo::getFieldInClass( + CORINFO_CLASS_HANDLE clsHnd, + INT num) +{ + API_ENTER(getFieldInClass); + CORINFO_FIELD_HANDLE temp = wrapHnd->getFieldInClass(clsHnd, num); + API_LEAVE(getFieldInClass); + return temp; +} + +BOOL WrapICorJitInfo::checkMethodModifier( + CORINFO_METHOD_HANDLE hMethod, + LPCSTR modifier, + BOOL fOptional) +{ + API_ENTER(checkMethodModifier); + BOOL result = wrapHnd->checkMethodModifier(hMethod, modifier, fOptional); + API_LEAVE(checkMethodModifier); + return result; +} + +CorInfoHelpFunc WrapICorJitInfo::getNewHelper( + CORINFO_RESOLVED_TOKEN * pResolvedToken, + CORINFO_METHOD_HANDLE callerHandle) +{ + API_ENTER(getNewHelper); + CorInfoHelpFunc temp = wrapHnd->getNewHelper(pResolvedToken, callerHandle); + API_LEAVE(getNewHelper); + return temp; +} + +CorInfoHelpFunc WrapICorJitInfo::getNewArrHelper( + CORINFO_CLASS_HANDLE arrayCls) +{ + API_ENTER(getNewArrHelper); + CorInfoHelpFunc temp = wrapHnd->getNewArrHelper(arrayCls); + API_LEAVE(getNewArrHelper); + return temp; +} + +CorInfoHelpFunc WrapICorJitInfo::getCastingHelper( + CORINFO_RESOLVED_TOKEN * pResolvedToken, + bool fThrowing) +{ + API_ENTER(getCastingHelper); + CorInfoHelpFunc temp = wrapHnd->getCastingHelper(pResolvedToken, fThrowing); + API_LEAVE(getCastingHelper); + return temp; +} + +CorInfoHelpFunc WrapICorJitInfo::getSharedCCtorHelper( + CORINFO_CLASS_HANDLE clsHnd) +{ + API_ENTER(getSharedCCtorHelper); + CorInfoHelpFunc temp = wrapHnd->getSharedCCtorHelper(clsHnd); + API_LEAVE(getSharedCCtorHelper); + return temp; +} + +CorInfoHelpFunc WrapICorJitInfo::getSecurityPrologHelper( + CORINFO_METHOD_HANDLE ftn) +{ + API_ENTER(getSecurityPrologHelper); + CorInfoHelpFunc temp = wrapHnd->getSecurityPrologHelper(ftn); + API_LEAVE(getSecurityPrologHelper); + return temp; +} + +CORINFO_CLASS_HANDLE WrapICorJitInfo::getTypeForBox( + CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(getTypeForBox); + CORINFO_CLASS_HANDLE temp = wrapHnd->getTypeForBox(cls); + API_LEAVE(getTypeForBox); + return temp; +} + +CorInfoHelpFunc WrapICorJitInfo::getBoxHelper( + CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(getBoxHelper); + CorInfoHelpFunc temp = wrapHnd->getBoxHelper(cls); + API_LEAVE(getBoxHelper); + return temp; +} + +CorInfoHelpFunc WrapICorJitInfo::getUnBoxHelper( + CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(getUnBoxHelper); + CorInfoHelpFunc temp = wrapHnd->getUnBoxHelper(cls); + API_LEAVE(getUnBoxHelper); + return temp; +} + +#if COR_JIT_EE_VERSION > 460 + +bool WrapICorJitInfo::getReadyToRunHelper( + CORINFO_RESOLVED_TOKEN * pResolvedToken, + CORINFO_LOOKUP_KIND * pGenericLookupKind, + CorInfoHelpFunc id, + CORINFO_CONST_LOOKUP * pLookup) +{ + API_ENTER(getReadyToRunHelper); + bool result = wrapHnd->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, id, pLookup); + API_LEAVE(getReadyToRunHelper); + return result; +} + +void WrapICorJitInfo::getReadyToRunDelegateCtorHelper( + CORINFO_RESOLVED_TOKEN * pTargetMethod, + CORINFO_CLASS_HANDLE delegateType, + CORINFO_CONST_LOOKUP * pLookup) +{ + API_ENTER(getReadyToRunDelegateCtorHelper); + wrapHnd->getReadyToRunDelegateCtorHelper(pTargetMethod, delegateType, pLookup); + API_LEAVE(getReadyToRunDelegateCtorHelper); +} + +#else + +void WrapICorJitInfo::getReadyToRunHelper( + CORINFO_RESOLVED_TOKEN * pResolvedToken, + CorInfoHelpFunc id, + CORINFO_CONST_LOOKUP * pLookup) +{ + API_ENTER(getReadyToRunHelper); + wrapHnd->getReadyToRunHelper(pResolvedToken, id, pLookup); + API_LEAVE(getReadyToRunHelper); +} + +#endif + +const char* WrapICorJitInfo::getHelperName( + CorInfoHelpFunc funcNum) +{ + API_ENTER(getHelperName); + const char* temp = wrapHnd->getHelperName(funcNum); + API_LEAVE(getHelperName); + return temp; +} + +CorInfoInitClassResult WrapICorJitInfo::initClass( + CORINFO_FIELD_HANDLE field, + + CORINFO_METHOD_HANDLE method, + CORINFO_CONTEXT_HANDLE context, + BOOL speculative) +{ + API_ENTER(initClass); + CorInfoInitClassResult temp = wrapHnd->initClass(field, method, context, speculative); + API_LEAVE(initClass); + return temp; +} + +void WrapICorJitInfo::classMustBeLoadedBeforeCodeIsRun( + CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(classMustBeLoadedBeforeCodeIsRun); + wrapHnd->classMustBeLoadedBeforeCodeIsRun(cls); + API_LEAVE(classMustBeLoadedBeforeCodeIsRun); +} + +CORINFO_CLASS_HANDLE WrapICorJitInfo::getBuiltinClass( + CorInfoClassId classId) +{ + API_ENTER(getBuiltinClass); + CORINFO_CLASS_HANDLE temp = wrapHnd->getBuiltinClass(classId); + API_LEAVE(getBuiltinClass); + return temp; +} + +CorInfoType WrapICorJitInfo::getTypeForPrimitiveValueClass( + CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(getTypeForPrimitiveValueClass); + CorInfoType temp = wrapHnd->getTypeForPrimitiveValueClass(cls); + API_LEAVE(getTypeForPrimitiveValueClass); + return temp; +} + +BOOL WrapICorJitInfo::canCast( + CORINFO_CLASS_HANDLE child, + CORINFO_CLASS_HANDLE parent ) +{ + API_ENTER(canCast); + BOOL temp = wrapHnd->canCast(child, parent); + API_LEAVE(canCast); + return temp; +} + +BOOL WrapICorJitInfo::areTypesEquivalent( + CORINFO_CLASS_HANDLE cls1, + CORINFO_CLASS_HANDLE cls2) +{ + API_ENTER(areTypesEquivalent); + BOOL temp = wrapHnd->areTypesEquivalent(cls1, cls2); + API_LEAVE(areTypesEquivalent); + return temp; +} + +CORINFO_CLASS_HANDLE WrapICorJitInfo::mergeClasses( + CORINFO_CLASS_HANDLE cls1, + CORINFO_CLASS_HANDLE cls2) +{ + API_ENTER(mergeClasses); + CORINFO_CLASS_HANDLE temp = wrapHnd->mergeClasses(cls1, cls2); + API_LEAVE(mergeClasses); + return temp; +} + +CORINFO_CLASS_HANDLE WrapICorJitInfo::getParentType( + CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(getParentType); + CORINFO_CLASS_HANDLE temp = wrapHnd->getParentType(cls); + API_LEAVE(getParentType); + return temp; +} + +CorInfoType WrapICorJitInfo::getChildType( + CORINFO_CLASS_HANDLE clsHnd, + CORINFO_CLASS_HANDLE *clsRet) +{ + API_ENTER(getChildType); + CorInfoType temp = wrapHnd->getChildType(clsHnd, clsRet); + API_LEAVE(getChildType); + return temp; +} + +BOOL WrapICorJitInfo::satisfiesClassConstraints( + CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(satisfiesClassConstraints); + BOOL temp = wrapHnd->satisfiesClassConstraints(cls); + API_LEAVE(satisfiesClassConstraints); + return temp; + +} + +BOOL WrapICorJitInfo::isSDArray( + CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(isSDArray); + BOOL temp = wrapHnd->isSDArray(cls); + API_LEAVE(isSDArray); + return temp; +} + +unsigned WrapICorJitInfo::getArrayRank( + CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(getArrayRank); + unsigned result = wrapHnd->getArrayRank(cls); + API_LEAVE(getArrayRank); + return result; +} + +void * WrapICorJitInfo::getArrayInitializationData( + CORINFO_FIELD_HANDLE field, + DWORD size) +{ + API_ENTER(getArrayInitializationData); + void *temp = wrapHnd->getArrayInitializationData(field, size); + API_LEAVE(getArrayInitializationData); + return temp; +} + +CorInfoIsAccessAllowedResult WrapICorJitInfo::canAccessClass( + CORINFO_RESOLVED_TOKEN * pResolvedToken, + CORINFO_METHOD_HANDLE callerHandle, + CORINFO_HELPER_DESC *pAccessHelper) +{ + API_ENTER(canAccessClass); + CorInfoIsAccessAllowedResult temp = wrapHnd->canAccessClass(pResolvedToken, callerHandle, pAccessHelper); + API_LEAVE(canAccessClass); + return temp; +} + +/**********************************************************************************/ +// +// ICorFieldInfo +// +/**********************************************************************************/ + +const char* WrapICorJitInfo::getFieldName( + CORINFO_FIELD_HANDLE ftn, /* IN */ + const char **moduleName /* OUT */) +{ + API_ENTER(getFieldName); + const char* temp = wrapHnd->getFieldName(ftn, moduleName); + API_LEAVE(getFieldName); + return temp; +} + +CORINFO_CLASS_HANDLE WrapICorJitInfo::getFieldClass( + CORINFO_FIELD_HANDLE field) +{ + API_ENTER(getFieldClass); + CORINFO_CLASS_HANDLE temp = wrapHnd->getFieldClass(field); + API_LEAVE(getFieldClass); + return temp; +} + +CorInfoType WrapICorJitInfo::getFieldType( + CORINFO_FIELD_HANDLE field, + CORINFO_CLASS_HANDLE *structType, + CORINFO_CLASS_HANDLE memberParent/* IN */) +{ + API_ENTER(getFieldType); + CorInfoType temp = wrapHnd->getFieldType(field, structType, memberParent); + API_LEAVE(getFieldType); + return temp; +} + +unsigned WrapICorJitInfo::getFieldOffset( + CORINFO_FIELD_HANDLE field) +{ + API_ENTER(getFieldOffset); + unsigned temp = wrapHnd->getFieldOffset(field); + API_LEAVE(getFieldOffset); + return temp; +} + +bool WrapICorJitInfo::isWriteBarrierHelperRequired( + CORINFO_FIELD_HANDLE field) +{ + API_ENTER(isWriteBarrierHelperRequired); + bool result = wrapHnd->isWriteBarrierHelperRequired(field); + API_LEAVE(isWriteBarrierHelperRequired); + return result; +} + +void WrapICorJitInfo::getFieldInfo(CORINFO_RESOLVED_TOKEN * pResolvedToken, + CORINFO_METHOD_HANDLE callerHandle, + CORINFO_ACCESS_FLAGS flags, + CORINFO_FIELD_INFO *pResult) +{ + API_ENTER(getFieldInfo); + wrapHnd->getFieldInfo(pResolvedToken, callerHandle, flags, pResult); + API_LEAVE(getFieldInfo); +} + +bool WrapICorJitInfo::isFieldStatic(CORINFO_FIELD_HANDLE fldHnd) +{ + API_ENTER(isFieldStatic); + bool result = wrapHnd->isFieldStatic(fldHnd); + API_LEAVE(isFieldStatic); + return result; +} + +/*********************************************************************************/ +// +// ICorDebugInfo +// +/*********************************************************************************/ + +void WrapICorJitInfo::getBoundaries( + CORINFO_METHOD_HANDLE ftn, + unsigned int *cILOffsets, + DWORD **pILOffsets, + + ICorDebugInfo::BoundaryTypes *implictBoundaries) +{ + API_ENTER(getBoundaries); + wrapHnd->getBoundaries(ftn, cILOffsets, pILOffsets, implictBoundaries); + API_LEAVE(getBoundaries); +} + +void WrapICorJitInfo::setBoundaries( + CORINFO_METHOD_HANDLE ftn, + ULONG32 cMap, + ICorDebugInfo::OffsetMapping *pMap) +{ + API_ENTER(setBoundaries); + wrapHnd->setBoundaries(ftn, cMap, pMap); + API_LEAVE(setBoundaries); +} + +void WrapICorJitInfo::getVars( + CORINFO_METHOD_HANDLE ftn, + ULONG32 *cVars, + ICorDebugInfo::ILVarInfo **vars, + bool *extendOthers) + +{ + API_ENTER(getVars); + wrapHnd->getVars(ftn, cVars, vars, extendOthers); + API_LEAVE(getVars); +} + +void WrapICorJitInfo::setVars( + CORINFO_METHOD_HANDLE ftn, + ULONG32 cVars, + ICorDebugInfo::NativeVarInfo *vars) + +{ + API_ENTER(setVars); + wrapHnd->setVars(ftn, cVars, vars); + API_LEAVE(setVars); +} + +void * WrapICorJitInfo::allocateArray( + ULONG cBytes) +{ + API_ENTER(allocateArray); + void *temp = wrapHnd->allocateArray(cBytes); + API_LEAVE(allocateArray); + return temp; +} + +void WrapICorJitInfo::freeArray( + void *array) +{ + API_ENTER(freeArray); + wrapHnd->freeArray(array); + API_LEAVE(freeArray); +} + +/*********************************************************************************/ +// +// ICorArgInfo +// +/*********************************************************************************/ + +CORINFO_ARG_LIST_HANDLE WrapICorJitInfo::getArgNext( + CORINFO_ARG_LIST_HANDLE args /* IN */) +{ + API_ENTER(getArgNext); + CORINFO_ARG_LIST_HANDLE temp = wrapHnd->getArgNext(args); + API_LEAVE(getArgNext); + return temp; +} + +CorInfoTypeWithMod WrapICorJitInfo::getArgType( + CORINFO_SIG_INFO* sig, /* IN */ + CORINFO_ARG_LIST_HANDLE args, /* IN */ + CORINFO_CLASS_HANDLE *vcTypeRet /* OUT */) +{ + API_ENTER(getArgType); + CorInfoTypeWithMod temp = wrapHnd->getArgType(sig, args, vcTypeRet); + API_LEAVE(getArgType); + return temp; +} + +CORINFO_CLASS_HANDLE WrapICorJitInfo::getArgClass( + CORINFO_SIG_INFO* sig, /* IN */ + CORINFO_ARG_LIST_HANDLE args /* IN */) +{ + API_ENTER(getArgClass); + CORINFO_CLASS_HANDLE temp = wrapHnd->getArgClass(sig, args); + API_LEAVE(getArgClass); + return temp; +} + +CorInfoType WrapICorJitInfo::getHFAType( + CORINFO_CLASS_HANDLE hClass) +{ + API_ENTER(getHFAType); + CorInfoType temp = wrapHnd->getHFAType(hClass); + API_LEAVE(getHFAType); + return temp; +} + +HRESULT WrapICorJitInfo::GetErrorHRESULT( + struct _EXCEPTION_POINTERS *pExceptionPointers) +{ + API_ENTER(GetErrorHRESULT); + HRESULT temp = wrapHnd->GetErrorHRESULT(pExceptionPointers); + API_LEAVE(GetErrorHRESULT); + return temp; +} + +ULONG WrapICorJitInfo::GetErrorMessage( + __inout_ecount(bufferLength) LPWSTR buffer, + ULONG bufferLength) +{ + API_ENTER(GetErrorMessage); + ULONG temp = wrapHnd->GetErrorMessage(buffer, bufferLength); + API_LEAVE(GetErrorMessage); + return temp; +} + +int WrapICorJitInfo::FilterException( + struct _EXCEPTION_POINTERS *pExceptionPointers) +{ + API_ENTER(FilterException); + int temp = wrapHnd->FilterException(pExceptionPointers); + API_LEAVE(FilterException); + return temp; +} + +void WrapICorJitInfo::HandleException( + struct _EXCEPTION_POINTERS *pExceptionPointers) +{ + API_ENTER(HandleException); + wrapHnd->HandleException(pExceptionPointers); + API_LEAVE(HandleException); +} + +void WrapICorJitInfo::ThrowExceptionForJitResult( + HRESULT result) +{ + API_ENTER(ThrowExceptionForJitResult); + wrapHnd->ThrowExceptionForJitResult(result); + API_LEAVE(ThrowExceptionForJitResult); +} + +void WrapICorJitInfo::ThrowExceptionForHelper( + const CORINFO_HELPER_DESC * throwHelper) +{ + API_ENTER(ThrowExceptionForHelper); + wrapHnd->ThrowExceptionForHelper(throwHelper); + API_LEAVE(ThrowExceptionForHelper); +} + +void WrapICorJitInfo::getEEInfo( + CORINFO_EE_INFO *pEEInfoOut) +{ + API_ENTER(getEEInfo); + wrapHnd->getEEInfo(pEEInfoOut); + API_LEAVE(getEEInfo); +} + +LPCWSTR WrapICorJitInfo::getJitTimeLogFilename() +{ + API_ENTER(getJitTimeLogFilename); + LPCWSTR temp = wrapHnd->getJitTimeLogFilename(); + API_LEAVE(getJitTimeLogFilename); + return temp; +} + +mdMethodDef WrapICorJitInfo::getMethodDefFromMethod( + CORINFO_METHOD_HANDLE hMethod) +{ + API_ENTER(getMethodDefFromMethod); + mdMethodDef result = wrapHnd->getMethodDefFromMethod(hMethod); + API_LEAVE(getMethodDefFromMethod); + return result; +} + +const char* WrapICorJitInfo::getMethodName( + CORINFO_METHOD_HANDLE ftn, /* IN */ + const char **moduleName /* OUT */) +{ + API_ENTER(getMethodName); + const char* temp = wrapHnd->getMethodName(ftn, moduleName); + API_LEAVE(getMethodName); + return temp; +} + +unsigned WrapICorJitInfo::getMethodHash( + CORINFO_METHOD_HANDLE ftn /* IN */) +{ + API_ENTER(getMethodHash); + unsigned temp = wrapHnd->getMethodHash(ftn); + API_LEAVE(getMethodHash); + return temp; +} + +size_t WrapICorJitInfo::findNameOfToken( + CORINFO_MODULE_HANDLE module, /* IN */ + mdToken metaTOK, /* IN */ + __out_ecount(FQNameCapacity) char * szFQName, /* OUT */ + size_t FQNameCapacity /* IN */) +{ + API_ENTER(findNameOfToken); + size_t result = wrapHnd->findNameOfToken(module, metaTOK, szFQName, FQNameCapacity); + API_LEAVE(findNameOfToken); + return result; +} + +#if COR_JIT_EE_VERSION > 460 + +bool WrapICorJitInfo::getSystemVAmd64PassStructInRegisterDescriptor( + /* IN */ CORINFO_CLASS_HANDLE structHnd, + /* OUT */ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr) +{ + API_ENTER(getSystemVAmd64PassStructInRegisterDescriptor); + bool result = wrapHnd->getSystemVAmd64PassStructInRegisterDescriptor(structHnd, structPassInRegDescPtr); + API_LEAVE(getSystemVAmd64PassStructInRegisterDescriptor); + return result; +} + +#endif + +DWORD WrapICorJitInfo::getThreadTLSIndex( + void **ppIndirection) +{ + API_ENTER(getThreadTLSIndex); + DWORD temp = wrapHnd->getThreadTLSIndex(ppIndirection); + API_LEAVE(getThreadTLSIndex); + return temp; +} + +const void * WrapICorJitInfo::getInlinedCallFrameVptr( + void **ppIndirection) +{ + API_ENTER(getInlinedCallFrameVptr); + const void* temp = wrapHnd->getInlinedCallFrameVptr(ppIndirection); + API_LEAVE(getInlinedCallFrameVptr); + return temp; +} + +LONG * WrapICorJitInfo::getAddrOfCaptureThreadGlobal( + void **ppIndirection) +{ + API_ENTER(getAddrOfCaptureThreadGlobal); + LONG * temp = wrapHnd->getAddrOfCaptureThreadGlobal(ppIndirection); + API_LEAVE(getAddrOfCaptureThreadGlobal); + return temp; +} + +SIZE_T* WrapICorJitInfo::getAddrModuleDomainID(CORINFO_MODULE_HANDLE module) +{ + API_ENTER(getAddrModuleDomainID); + SIZE_T* result = wrapHnd->getAddrModuleDomainID(module); + API_LEAVE(getAddrModuleDomainID); + return result; +} + +void* WrapICorJitInfo::getHelperFtn( + CorInfoHelpFunc ftnNum, + void **ppIndirection) +{ + API_ENTER(getHelperFtn); + void *temp = wrapHnd->getHelperFtn(ftnNum, ppIndirection); + API_LEAVE(getHelperFtn); + return temp; +} + +void WrapICorJitInfo::getFunctionEntryPoint( + CORINFO_METHOD_HANDLE ftn, /* IN */ + CORINFO_CONST_LOOKUP * pResult, /* OUT */ + CORINFO_ACCESS_FLAGS accessFlags) +{ + API_ENTER(getFunctionEntryPoint); + wrapHnd->getFunctionEntryPoint(ftn, pResult, accessFlags); + API_LEAVE(getFunctionEntryPoint); +} + +void WrapICorJitInfo::getFunctionFixedEntryPoint( + CORINFO_METHOD_HANDLE ftn, + CORINFO_CONST_LOOKUP * pResult) +{ + API_ENTER(getFunctionFixedEntryPoint); + wrapHnd->getFunctionFixedEntryPoint(ftn, pResult); + API_LEAVE(getFunctionFixedEntryPoint); +} + +void* WrapICorJitInfo::getMethodSync( + CORINFO_METHOD_HANDLE ftn, + void **ppIndirection) +{ + API_ENTER(getMethodSync); + void *temp = wrapHnd->getMethodSync(ftn, ppIndirection); + API_LEAVE(getMethodSync); + return temp; +} + + +CorInfoHelpFunc WrapICorJitInfo::getLazyStringLiteralHelper( + CORINFO_MODULE_HANDLE handle) +{ + API_ENTER(getLazyStringLiteralHelper); + CorInfoHelpFunc temp = wrapHnd->getLazyStringLiteralHelper(handle); + API_LEAVE(getLazyStringLiteralHelper); + return temp; +} + +CORINFO_MODULE_HANDLE WrapICorJitInfo::embedModuleHandle( + CORINFO_MODULE_HANDLE handle, + void **ppIndirection) +{ + API_ENTER(embedModuleHandle); + CORINFO_MODULE_HANDLE temp = wrapHnd->embedModuleHandle(handle, ppIndirection); + API_LEAVE(embedModuleHandle); + return temp; +} + +CORINFO_CLASS_HANDLE WrapICorJitInfo::embedClassHandle( + CORINFO_CLASS_HANDLE handle, + void **ppIndirection) +{ + API_ENTER(embedClassHandle); + CORINFO_CLASS_HANDLE temp = wrapHnd->embedClassHandle(handle, ppIndirection); + API_LEAVE(embedClassHandle); + return temp; +} + +CORINFO_METHOD_HANDLE WrapICorJitInfo::embedMethodHandle( + CORINFO_METHOD_HANDLE handle, + void **ppIndirection) +{ + API_ENTER(embedMethodHandle); + CORINFO_METHOD_HANDLE temp = wrapHnd->embedMethodHandle(handle, ppIndirection); + API_LEAVE(embedMethodHandle); + return temp; +} + +CORINFO_FIELD_HANDLE WrapICorJitInfo::embedFieldHandle( + CORINFO_FIELD_HANDLE handle, + void **ppIndirection) +{ + API_ENTER(embedFieldHandle); + CORINFO_FIELD_HANDLE temp = wrapHnd->embedFieldHandle(handle, ppIndirection); + API_LEAVE(embedFieldHandle); + return temp; +} + +void WrapICorJitInfo::embedGenericHandle( + CORINFO_RESOLVED_TOKEN * pResolvedToken, + BOOL fEmbedParent, + CORINFO_GENERICHANDLE_RESULT * pResult) +{ + API_ENTER(embedGenericHandle); + wrapHnd->embedGenericHandle(pResolvedToken, fEmbedParent, pResult); + API_LEAVE(embedGenericHandle); +} + +CORINFO_LOOKUP_KIND WrapICorJitInfo::getLocationOfThisType( + CORINFO_METHOD_HANDLE context) +{ + API_ENTER(getLocationOfThisType); + CORINFO_LOOKUP_KIND temp = wrapHnd->getLocationOfThisType(context); + API_LEAVE(getLocationOfThisType); + return temp; +} + +void* WrapICorJitInfo::getPInvokeUnmanagedTarget( + CORINFO_METHOD_HANDLE method, + void **ppIndirection) +{ + API_ENTER(getPInvokeUnmanagedTarget); + void *result = wrapHnd->getPInvokeUnmanagedTarget(method, ppIndirection); + API_LEAVE(getPInvokeUnmanagedTarget); + return result; +} + +void* WrapICorJitInfo::getAddressOfPInvokeFixup( + CORINFO_METHOD_HANDLE method, + void **ppIndirection) +{ + API_ENTER(getAddressOfPInvokeFixup); + void *temp = wrapHnd->getAddressOfPInvokeFixup(method, ppIndirection); + API_LEAVE(getAddressOfPInvokeFixup); + return temp; +} + +#if COR_JIT_EE_VERSION > 460 + +void WrapICorJitInfo::getAddressOfPInvokeTarget( + CORINFO_METHOD_HANDLE method, + CORINFO_CONST_LOOKUP *pLookup) +{ + API_ENTER(getAddressOfPInvokeTarget); + wrapHnd->getAddressOfPInvokeTarget(method, pLookup); + API_LEAVE(getAddressOfPInvokeTarget); +} + +#endif + +LPVOID WrapICorJitInfo::GetCookieForPInvokeCalliSig( + CORINFO_SIG_INFO* szMetaSig, + void ** ppIndirection) +{ + API_ENTER(GetCookieForPInvokeCalliSig); + LPVOID temp = wrapHnd->GetCookieForPInvokeCalliSig(szMetaSig, ppIndirection); + API_LEAVE(GetCookieForPInvokeCalliSig); + return temp; +} + +bool WrapICorJitInfo::canGetCookieForPInvokeCalliSig( + CORINFO_SIG_INFO* szMetaSig) +{ + API_ENTER(canGetCookieForPInvokeCalliSig); + bool temp = wrapHnd->canGetCookieForPInvokeCalliSig(szMetaSig); + API_LEAVE(canGetCookieForPInvokeCalliSig); + return temp; +} + +CORINFO_JUST_MY_CODE_HANDLE WrapICorJitInfo::getJustMyCodeHandle( + CORINFO_METHOD_HANDLE method, + CORINFO_JUST_MY_CODE_HANDLE**ppIndirection) +{ + API_ENTER(getJustMyCodeHandle); + CORINFO_JUST_MY_CODE_HANDLE temp = wrapHnd->getJustMyCodeHandle(method, ppIndirection); + API_LEAVE(getJustMyCodeHandle); + return temp; +} + +void WrapICorJitInfo::GetProfilingHandle( + BOOL *pbHookFunction, + void **pProfilerHandle, + BOOL *pbIndirectedHandles) +{ + API_ENTER(GetProfilingHandle); + wrapHnd->GetProfilingHandle(pbHookFunction, pProfilerHandle, pbIndirectedHandles); + API_LEAVE(GetProfilingHandle); +} + +void WrapICorJitInfo::getCallInfo( + CORINFO_RESOLVED_TOKEN * pResolvedToken, + CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken, + CORINFO_METHOD_HANDLE callerHandle, + CORINFO_CALLINFO_FLAGS flags, + CORINFO_CALL_INFO *pResult) +{ + API_ENTER(getCallInfo); + wrapHnd->getCallInfo(pResolvedToken, pConstrainedResolvedToken, callerHandle, flags, pResult); + API_LEAVE(getCallInfo); +} + +BOOL WrapICorJitInfo::canAccessFamily(CORINFO_METHOD_HANDLE hCaller, + CORINFO_CLASS_HANDLE hInstanceType) +{ + API_ENTER(canAccessFamily); + BOOL temp = wrapHnd->canAccessFamily(hCaller, hInstanceType); + API_LEAVE(canAccessFamily); + return temp; +} + +BOOL WrapICorJitInfo::isRIDClassDomainID(CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(isRIDClassDomainID); + BOOL result = wrapHnd->isRIDClassDomainID(cls); + API_LEAVE(isRIDClassDomainID); + return result; +} + +unsigned WrapICorJitInfo::getClassDomainID( + CORINFO_CLASS_HANDLE cls, + void **ppIndirection) +{ + API_ENTER(getClassDomainID); + unsigned temp = wrapHnd->getClassDomainID(cls, ppIndirection); + API_LEAVE(getClassDomainID); + return temp; +} + +void* WrapICorJitInfo::getFieldAddress( + CORINFO_FIELD_HANDLE field, + void **ppIndirection) +{ + API_ENTER(getFieldAddress); + void *temp = wrapHnd->getFieldAddress(field, ppIndirection); + API_LEAVE(getFieldAddress); + return temp; +} + +CORINFO_VARARGS_HANDLE WrapICorJitInfo::getVarArgsHandle( + CORINFO_SIG_INFO *pSig, + void **ppIndirection) +{ + API_ENTER(getVarArgsHandle); + CORINFO_VARARGS_HANDLE temp = wrapHnd->getVarArgsHandle(pSig, ppIndirection); + API_LEAVE(getVarArgsHandle); + return temp; +} + +bool WrapICorJitInfo::canGetVarArgsHandle( + CORINFO_SIG_INFO *pSig) +{ + API_ENTER(canGetVarArgsHandle); + bool temp = wrapHnd->canGetVarArgsHandle(pSig); + API_LEAVE(canGetVarArgsHandle); + return temp; +} + +InfoAccessType WrapICorJitInfo::constructStringLiteral( + CORINFO_MODULE_HANDLE module, + mdToken metaTok, + void **ppValue) +{ + API_ENTER(constructStringLiteral); + InfoAccessType temp = wrapHnd->constructStringLiteral(module, metaTok, ppValue); + API_LEAVE(constructStringLiteral); + return temp; +} + +InfoAccessType WrapICorJitInfo::emptyStringLiteral(void **ppValue) +{ + API_ENTER(emptyStringLiteral); + InfoAccessType temp = wrapHnd->emptyStringLiteral(ppValue); + API_LEAVE(emptyStringLiteral); + return temp; +} + +DWORD WrapICorJitInfo::getFieldThreadLocalStoreID( + CORINFO_FIELD_HANDLE field, + void **ppIndirection) +{ + API_ENTER(getFieldThreadLocalStoreID); + DWORD temp = wrapHnd->getFieldThreadLocalStoreID(field, ppIndirection); + API_LEAVE(getFieldThreadLocalStoreID); + return temp; +} + +void WrapICorJitInfo::setOverride( + ICorDynamicInfo *pOverride, + CORINFO_METHOD_HANDLE currentMethod) +{ + API_ENTER(setOverride); + wrapHnd->setOverride(pOverride, currentMethod); + API_LEAVE(setOverride); +} + +void WrapICorJitInfo::addActiveDependency( + CORINFO_MODULE_HANDLE moduleFrom, + CORINFO_MODULE_HANDLE moduleTo) +{ + API_ENTER(addActiveDependency); + wrapHnd->addActiveDependency(moduleFrom, moduleTo); + API_LEAVE(addActiveDependency); +} + +CORINFO_METHOD_HANDLE WrapICorJitInfo::GetDelegateCtor( + CORINFO_METHOD_HANDLE methHnd, + CORINFO_CLASS_HANDLE clsHnd, + CORINFO_METHOD_HANDLE targetMethodHnd, + DelegateCtorArgs * pCtorData) +{ + API_ENTER(GetDelegateCtor); + CORINFO_METHOD_HANDLE temp = wrapHnd->GetDelegateCtor(methHnd, clsHnd, targetMethodHnd, pCtorData); + API_LEAVE(GetDelegateCtor); + return temp; +} + +void WrapICorJitInfo::MethodCompileComplete( + CORINFO_METHOD_HANDLE methHnd) +{ + API_ENTER(MethodCompileComplete); + wrapHnd->MethodCompileComplete(methHnd); + API_LEAVE(MethodCompileComplete); +} + +void* WrapICorJitInfo::getTailCallCopyArgsThunk( + CORINFO_SIG_INFO *pSig, + CorInfoHelperTailCallSpecialHandling flags) +{ + API_ENTER(getTailCallCopyArgsThunk); + void *result = wrapHnd->getTailCallCopyArgsThunk(pSig, flags); + API_LEAVE(getTailCallCopyArgsThunk); + return result; +} + +/*********************************************************************************/ +// +// ICorJitInfo +// +/*********************************************************************************/ + +#if COR_JIT_EE_VERSION > 460 + +DWORD WrapICorJitInfo::getJitFlags(CORJIT_FLAGS *jitFlags, DWORD sizeInBytes) +{ + API_ENTER(getJitFlags); + DWORD result = wrapHnd->getJitFlags(jitFlags, sizeInBytes); + API_LEAVE(getJitFlags); + return result; +} + +bool WrapICorJitInfo::runWithErrorTrap(void(*function)(void*), void *param) +{ + return wrapHnd->runWithErrorTrap(function, param); +} + +#endif + +IEEMemoryManager* WrapICorJitInfo::getMemoryManager() +{ + API_ENTER(getMemoryManager); + IEEMemoryManager * temp = wrapHnd->getMemoryManager(); + API_LEAVE(getMemoryManager); + return temp; +} + +void WrapICorJitInfo::allocMem( + ULONG hotCodeSize, /* IN */ + ULONG coldCodeSize, /* IN */ + ULONG roDataSize, /* IN */ + ULONG xcptnsCount, /* IN */ + CorJitAllocMemFlag flag, /* IN */ + void ** hotCodeBlock, /* OUT */ + void ** coldCodeBlock, /* OUT */ + void ** roDataBlock /* OUT */) +{ + API_ENTER(allocMem); + wrapHnd->allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, coldCodeBlock, roDataBlock); + API_LEAVE(allocMem); +} + +void WrapICorJitInfo::reserveUnwindInfo( + BOOL isFunclet, /* IN */ + BOOL isColdCode, /* IN */ + ULONG unwindSize /* IN */) +{ + API_ENTER(reserveUnwindInfo); + wrapHnd->reserveUnwindInfo(isFunclet, isColdCode, unwindSize); + API_LEAVE(reserveUnwindInfo); +} + +void WrapICorJitInfo::allocUnwindInfo( + BYTE * pHotCode, /* IN */ + BYTE * pColdCode, /* IN */ + ULONG startOffset, /* IN */ + ULONG endOffset, /* IN */ + ULONG unwindSize, /* IN */ + BYTE * pUnwindBlock, /* IN */ + CorJitFuncKind funcKind /* IN */) +{ + API_ENTER(allocUnwindInfo); + wrapHnd->allocUnwindInfo(pHotCode, pColdCode, startOffset, endOffset, unwindSize, pUnwindBlock, funcKind); + API_LEAVE(allocUnwindInfo); +} + +void *WrapICorJitInfo::allocGCInfo(size_t size /* IN */) +{ + API_ENTER(allocGCInfo); + void *temp = wrapHnd->allocGCInfo(size); + API_LEAVE(allocGCInfo); + return temp; +} + +void WrapICorJitInfo::yieldExecution() +{ + API_ENTER(yieldExecution); //Nothing to record + wrapHnd->yieldExecution(); + API_LEAVE(yieldExecution); //Nothing to recor) +} + +void WrapICorJitInfo::setEHcount(unsigned cEH /* IN */) +{ + API_ENTER(setEHcount); + wrapHnd->setEHcount(cEH); + API_LEAVE(setEHcount); +} + +void WrapICorJitInfo::setEHinfo( + unsigned EHnumber, /* IN */ + const CORINFO_EH_CLAUSE *clause /* IN */) +{ + API_ENTER(setEHinfo); + wrapHnd->setEHinfo(EHnumber, clause); + API_LEAVE(setEHinfo); +} + +BOOL WrapICorJitInfo::logMsg(unsigned level, const char* fmt, va_list args) +{ + API_ENTER(logMsg); + BOOL result = wrapHnd->logMsg(level, fmt, args); + API_LEAVE(logMsg); + return result; +} + +int WrapICorJitInfo::doAssert(const char* szFile, int iLine, const char* szExpr) +{ + API_ENTER(doAssert); + int result = wrapHnd->doAssert(szFile, iLine, szExpr); + API_LEAVE(doAssert); + return result; +} + +void WrapICorJitInfo::reportFatalError(CorJitResult result) +{ + API_ENTER(reportFatalError); + wrapHnd->reportFatalError(result); + API_LEAVE(reportFatalError); +} + +HRESULT WrapICorJitInfo::allocBBProfileBuffer( + ULONG count, + ProfileBuffer **profileBuffer) +{ + API_ENTER(allocBBProfileBuffer); + HRESULT result = wrapHnd->allocBBProfileBuffer(count, profileBuffer); + API_LEAVE(allocBBProfileBuffer); + return result; +} + +HRESULT WrapICorJitInfo::getBBProfileData( + CORINFO_METHOD_HANDLE ftnHnd, + ULONG *count, + ProfileBuffer **profileBuffer, + ULONG *numRuns) +{ + API_ENTER(getBBProfileData); + HRESULT temp = wrapHnd->getBBProfileData(ftnHnd, count, profileBuffer, numRuns); + API_LEAVE(getBBProfileData); + return temp; +} + +void WrapICorJitInfo::recordCallSite( + ULONG instrOffset, /* IN */ + CORINFO_SIG_INFO * callSig, /* IN */ + CORINFO_METHOD_HANDLE methodHandle /* IN */) +{ + API_ENTER(recordCallSite); + wrapHnd->recordCallSite(instrOffset, callSig, methodHandle); + API_LEAVE(recordCallSite); +} + +void WrapICorJitInfo::recordRelocation( + void *location, /* IN */ + void *target, /* IN */ + WORD fRelocType, /* IN */ + WORD slotNum, /* IN */ + INT32 addlDelta /* IN */) +{ + API_ENTER(recordRelocation); + wrapHnd->recordRelocation(location, target, fRelocType, slotNum, addlDelta); + API_LEAVE(recordRelocation); +} + +WORD WrapICorJitInfo::getRelocTypeHint(void *target) +{ + API_ENTER(getRelocTypeHint); + WORD result = wrapHnd->getRelocTypeHint(target); + API_LEAVE(getRelocTypeHint); + return result; +} + +void WrapICorJitInfo::getModuleNativeEntryPointRange( + void **pStart, /* OUT */ + void **pEnd /* OUT */) +{ + API_ENTER(getModuleNativeEntryPointRange); + wrapHnd->getModuleNativeEntryPointRange(pStart, pEnd); + API_LEAVE(getModuleNativeEntryPointRange); +} + +DWORD WrapICorJitInfo::getExpectedTargetArchitecture() +{ + API_ENTER(getExpectedTargetArchitecture); + DWORD result = wrapHnd->getExpectedTargetArchitecture(); + API_LEAVE(getExpectedTargetArchitecture); + return result; +} + +/**********************************************************************************/ +// clang-format on +/**********************************************************************************/ diff --git a/src/jit/assertionprop.cpp b/src/jit/assertionprop.cpp index fe35c3b..cb0832f 100644 --- a/src/jit/assertionprop.cpp +++ b/src/jit/assertionprop.cpp @@ -1100,11 +1100,6 @@ Compiler::AssertionIndex Compiler::optCreateAssertion(GenTreePtr op1, CNS_COMMON: { - // TODO-1stClassStructs: handle constant propagation to struct types. - if (varTypeIsStruct(lclVar)) - { - goto DONE_ASSERTION; - } // // Must either be an OAK_EQUAL or an OAK_NOT_EQUAL assertion // @@ -2034,12 +2029,7 @@ void Compiler::optAssertionGen(GenTreePtr tree) { case GT_ASG: // VN takes care of non local assertions for assignments and data flow. - // TODO-1stClassStructs: Enable assertion prop for struct types. - if (varTypeIsStruct(tree)) - { - // Do nothing. - } - else if (optLocalAssertionProp) + if (optLocalAssertionProp) { assertionIndex = optCreateAssertion(tree->gtOp.gtOp1, tree->gtOp.gtOp2, OAK_EQUAL); } @@ -2052,26 +2042,15 @@ void Compiler::optAssertionGen(GenTreePtr tree) case GT_OBJ: case GT_BLK: case GT_DYN_BLK: - // TODO-1stClassStructs: These should always be considered to create a non-null - // assertion, but previously, when these indirections were implicit due to a block - // copy or init, they were not being considered to do so. - break; case GT_IND: - // TODO-1stClassStructs: All indirections should be considered to create a non-null - // assertion, but previously, when these indirections were implicit due to a block - // copy or init, they were not being considered to do so. - if (tree->gtType == TYP_STRUCT) - { - GenTree* parent = tree->gtGetParent(nullptr); - if ((parent != nullptr) && (parent->gtOper == GT_ASG)) - { - break; - } - } case GT_NULLCHECK: + // All indirections create non-null assertions + assertionIndex = optCreateAssertion(tree->AsIndir()->Addr(), nullptr, OAK_NOT_EQUAL); + break; + case GT_ARR_LENGTH: - // An array length can create a non-null assertion - assertionIndex = optCreateAssertion(tree->gtOp.gtOp1, nullptr, OAK_NOT_EQUAL); + // An array length is an indirection (but doesn't derive from GenTreeIndir). + assertionIndex = optCreateAssertion(tree->AsArrLen()->ArrRef(), nullptr, OAK_NOT_EQUAL); break; case GT_ARR_BOUNDS_CHECK: @@ -2629,9 +2608,29 @@ GenTreePtr Compiler::optConstantAssertionProp(AssertionDsc* curAssertion, else { bool isArrIndex = ((tree->gtFlags & GTF_VAR_ARR_INDEX) != 0); - newTree->ChangeOperConst(GT_CNS_INT); - newTree->gtIntCon.gtIconVal = curAssertion->op2.u1.iconVal; - newTree->ClearIconHandleMask(); + // If we have done constant propagation of a struct type, it is only valid for zero-init, + // and we have to ensure that we have the right zero for the type. + if (varTypeIsStruct(tree)) + { + assert(curAssertion->op2.u1.iconVal == 0); + } +#ifdef FEATURE_SIMD + if (varTypeIsSIMD(tree)) + { + var_types simdType = tree->TypeGet(); + tree->ChangeOperConst(GT_CNS_DBL); + GenTree* initVal = tree; + initVal->gtType = TYP_FLOAT; + newTree = + gtNewSIMDNode(simdType, initVal, nullptr, SIMDIntrinsicInit, TYP_FLOAT, genTypeSize(simdType)); + } + else +#endif // FEATURE_SIMD + { + newTree->ChangeOperConst(GT_CNS_INT); + newTree->gtIntCon.gtIconVal = curAssertion->op2.u1.iconVal; + newTree->ClearIconHandleMask(); + } // If we're doing an array index address, assume any constant propagated contributes to the index. if (isArrIndex) { @@ -3421,32 +3420,13 @@ GenTreePtr Compiler::optAssertionProp_Ind(ASSERT_VALARG_TP assertions, const Gen { assert(tree->OperIsIndir()); - // TODO-1stClassStructs: All indirections should be handled here, but - // previously, when these indirections were GT_OBJ, or implicit due to a block - // copy or init, they were not being handled. - if (tree->TypeGet() == TYP_STRUCT) - { - if (tree->OperIsBlk()) - { - return nullptr; - } - else - { - GenTree* parent = tree->gtGetParent(nullptr); - if ((parent != nullptr) && parent->OperIsBlkOp()) - { - return nullptr; - } - } - } - if (!(tree->gtFlags & GTF_EXCEPT)) { return nullptr; } // Check for add of a constant. - GenTreePtr op1 = tree->gtOp.gtOp1; + GenTreePtr op1 = tree->AsIndir()->Addr(); if ((op1->gtOper == GT_ADD) && (op1->gtOp.gtOp2->gtOper == GT_CNS_INT)) { op1 = op1->gtOp.gtOp1; @@ -3700,6 +3680,21 @@ GenTreePtr Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, const assert(tree->gtOper == GT_ARR_BOUNDS_CHECK); +#ifdef FEATURE_ENABLE_NO_RANGE_CHECKS + if (JitConfig.JitNoRangeChks()) + { +#ifdef DEBUG + if (verbose) + { + printf("\nFlagging check redundant due to JitNoRangeChks in BB%02u:\n", compCurBB->bbNum); + gtDispTree(tree, nullptr, nullptr, true); + } +#endif // DEBUG + tree->gtFlags |= GTF_ARR_BOUND_INBND; + return nullptr; + } +#endif // FEATURE_ENABLE_NO_RANGE_CHECKS + BitVecOps::Iter iter(apTraits, assertions); unsigned index = 0; while (iter.NextElem(apTraits, &index)) @@ -4688,9 +4683,8 @@ GenTreePtr Compiler::optVNConstantPropOnJTrue(BasicBlock* block, GenTreePtr stmt newStmt = fgInsertStmtNearEnd(block, sideEffList); sideEffList = nullptr; } - fgMorphBlockStmt(block, newStmt DEBUGARG(__FUNCTION__)); - gtSetStmtInfo(newStmt); - fgSetStmtSeq(newStmt); + + fgMorphBlockStmt(block, newStmt->AsStmt() DEBUGARG(__FUNCTION__)); } // Transform the relop's operands to be both zeroes. @@ -4748,7 +4742,6 @@ Compiler::fgWalkResult Compiler::optVNConstantPropCurStmt(BasicBlock* block, Gen case GT_MOD: case GT_UDIV: case GT_UMOD: - case GT_MULHI: case GT_EQ: case GT_NE: case GT_LT: @@ -4767,6 +4760,10 @@ Compiler::fgWalkResult Compiler::optVNConstantPropCurStmt(BasicBlock* block, Gen case GT_INTRINSIC: break; + case GT_MULHI: + assert(false && "Unexpected GT_MULHI node encountered before lowering"); + break; + case GT_JTRUE: break; @@ -4911,9 +4908,7 @@ GenTreePtr Compiler::optVNAssertionPropCurStmt(BasicBlock* block, GenTreePtr stm if (optAssertionPropagatedCurrentStmt) { - fgMorphBlockStmt(block, stmt DEBUGARG("optVNAssertionPropCurStmt")); - gtSetStmtInfo(stmt); - fgSetStmtSeq(stmt); + fgMorphBlockStmt(block, stmt->AsStmt() DEBUGARG("optVNAssertionPropCurStmt")); } // Check if propagation removed statements starting from current stmt. @@ -5110,13 +5105,7 @@ void Compiler::optAssertionPropMain() } #endif // Re-morph the statement. - fgMorphBlockStmt(block, stmt DEBUGARG("optAssertionPropMain")); - - // Recalculate the gtCostSz, etc... - gtSetStmtInfo(stmt); - - // Re-thread the nodes - fgSetStmtSeq(stmt); + fgMorphBlockStmt(block, stmt->AsStmt() DEBUGARG("optAssertionPropMain")); } // Check if propagation removed statements starting from current stmt. diff --git a/src/jit/bitsetasuint64.h b/src/jit/bitsetasuint64.h index 150f7e9..243e9e3 100644 --- a/src/jit/bitsetasuint64.h +++ b/src/jit/bitsetasuint64.h @@ -167,7 +167,7 @@ public: { IAllocator* alloc = BitSetTraits::GetDebugOnlyAllocator(env); const int CharsForUINT64 = sizeof(UINT64) * 2; - char* res = NULL; + char* res = nullptr; const int AllocSize = CharsForUINT64 + 4; res = (char*)alloc->Alloc(AllocSize); UINT64 bits = bs; diff --git a/src/jit/block.cpp b/src/jit/block.cpp index 2d37754..47f1052 100644 --- a/src/jit/block.cpp +++ b/src/jit/block.cpp @@ -554,7 +554,9 @@ void BasicBlock::dspBlockHeader(Compiler* compiler, } if (showFlags) { - printf(" flags=0x%08x: ", bbFlags); + const unsigned lowFlags = (unsigned)bbFlags; + const unsigned highFlags = (unsigned)(bbFlags >> 32); + printf(" flags=0x%08x.%08x: ", highFlags, lowFlags); dspFlags(); } printf("\n"); @@ -568,7 +570,25 @@ void* BasicBlock::HeapPhiArg::operator new(size_t sz, Compiler* comp) return comp->compGetMem(sz, CMK_HeapPhiArg); } -void BasicBlock::CloneBlockState(Compiler* compiler, BasicBlock* to, const BasicBlock* from) +//------------------------------------------------------------------------ +// CloneBlockState: Try to populate `to` block with a copy of `from` block's statements, replacing +// uses of local `varNum` with IntCns `varVal`. +// +// Arguments: +// compiler - Jit compiler instance +// to - New/empty block to copy statements into +// from - Block to copy statements from +// varNum - lclVar uses with lclNum `varNum` will be replaced; can be ~0 to indicate no replacement. +// varVal - If replacing uses of `varNum`, replace them with int constants with value `varVal`. +// +// Return Value: +// Cloning may fail because this routine uses `gtCloneExpr` for cloning and it can't handle all +// IR nodes. If cloning of any statement fails, `false` will be returned and block `to` may be +// partially populated. If cloning of all statements succeeds, `true` will be returned and +// block `to` will be fully populated. + +bool BasicBlock::CloneBlockState( + Compiler* compiler, BasicBlock* to, const BasicBlock* from, unsigned varNum, int varVal) { assert(to->bbTreeList == nullptr); @@ -595,9 +615,17 @@ void BasicBlock::CloneBlockState(Compiler* compiler, BasicBlock* to, const Basic for (GenTreePtr fromStmt = from->bbTreeList; fromStmt != nullptr; fromStmt = fromStmt->gtNext) { - compiler->fgInsertStmtAtEnd(to, - compiler->fgNewStmtFromTree(compiler->gtCloneExpr(fromStmt->gtStmt.gtStmtExpr))); + auto newExpr = compiler->gtCloneExpr(fromStmt->gtStmt.gtStmtExpr, 0, varNum, varVal); + if (!newExpr) + { + // gtCloneExpr doesn't handle all opcodes, so may fail to clone a statement. + // When that happens, it returns nullptr; abandon the rest of this block and + // return `false` to the caller to indicate that cloning was unsuccessful. + return false; + } + compiler->fgInsertStmtAtEnd(to, compiler->fgNewStmtFromTree(newExpr)); } + return true; } // LIR helpers @@ -667,7 +695,6 @@ GenTreeStmt* BasicBlock::lastStmt() return result->AsStmt(); } - //------------------------------------------------------------------------ // BasicBlock::firstNode: Returns the first node in the block. // diff --git a/src/jit/block.h b/src/jit/block.h index ecfbb62..99c0efc 100644 --- a/src/jit/block.h +++ b/src/jit/block.h @@ -30,17 +30,13 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #include "simplerhash.h" /*****************************************************************************/ - +typedef BitVec EXPSET_TP; #if LARGE_EXPSET -typedef unsigned __int64 EXPSET_TP; #define EXPSET_SZ 64 #else -typedef unsigned int EXPSET_TP; #define EXPSET_SZ 32 #endif -#define EXPSET_ALL ((EXPSET_TP)0 - 1) - typedef BitVec ASSERT_TP; typedef BitVec_ValArg_T ASSERT_VALARG_TP; typedef BitVec_ValRet_T ASSERT_VALRET_TP; @@ -291,14 +287,14 @@ struct BasicBlock : private LIR::Range } } + unsigned __int64 bbFlags; // see BBF_xxxx below + unsigned bbNum; // the block's number unsigned bbPostOrderNum; // the block's post order number in the graph. unsigned bbRefs; // number of blocks that can reach here, either by fall-through or a branch. If this falls to zero, // the block is unreachable. - unsigned bbFlags; // see BBF_xxxx below - #define BBF_VISITED 0x00000001 // BB visited during optimizations #define BBF_MARKED 0x00000002 // BB marked during optimizations #define BBF_CHANGED 0x00000004 // input/output of this block has changed @@ -357,6 +353,10 @@ struct BasicBlock : private LIR::Range // BBJ_CALLFINALLY block, as well as, on x86, the final step block out of a // finally. +// Flags that relate blocks to loop structure. + +#define BBF_LOOP_FLAGS (BBF_LOOP_PREHEADER | BBF_LOOP_HEAD | BBF_LOOP_CALL0 | BBF_LOOP_CALL1) + bool isRunRarely() { return ((bbFlags & BBF_RUN_RARELY) != 0); @@ -860,9 +860,7 @@ struct BasicBlock : private LIR::Range unsigned bbHeapSsaNumIn; // The SSA # of "Heap" on entry to the block. unsigned bbHeapSsaNumOut; // The SSA # of "Heap" on exit from the block. -#ifdef DEBUGGING_SUPPORT VARSET_TP bbScope; // variables in scope over the block -#endif void InitVarSets(class Compiler* comp); @@ -1094,9 +1092,11 @@ public: return AllSuccs(comp, this); } - // Clone block state and statements from 'from' block to 'to' block. - // Assumes that "to" is an empty block. - static void CloneBlockState(Compiler* compiler, BasicBlock* to, const BasicBlock* from); + // Try to clone block state and statements from `from` block to `to` block (which must be new/empty), + // optionally replacing uses of local `varNum` with IntCns `varVal`. Return true if all statements + // in the block are cloned successfully, false (with partially-populated `to` block) if one fails. + static bool CloneBlockState( + Compiler* compiler, BasicBlock* to, const BasicBlock* from, unsigned varNum = (unsigned)-1, int varVal = 0); void MakeLIR(GenTree* firstNode, GenTree* lastNode); bool IsLIR(); diff --git a/src/jit/codegen.h b/src/jit/codegen.h index 0c4a311..c6e38ab 100755 --- a/src/jit/codegen.h +++ b/src/jit/codegen.h @@ -48,7 +48,6 @@ public: unsigned* cnsPtr, bool nogen = false); - private: #if defined(_TARGET_XARCH_) && !FEATURE_STACK_FP_X87 // Bit masks used in negating a float or double number. @@ -123,7 +122,7 @@ private: void genRangeCheck(GenTree* node); - void genLockedInstructions(GenTree* node); + void genLockedInstructions(GenTreeOp* node); //------------------------------------------------------------------------- // Register-related methods @@ -251,6 +250,8 @@ protected: void genAdjustSP(ssize_t delta); + void genAdjustStackLevel(BasicBlock* block); + void genExitCode(BasicBlock* block); //------------------------------------------------------------------------- @@ -488,15 +489,26 @@ protected: void genAmd64EmitterUnitTests(); #endif -//------------------------------------------------------------------------- -// -// End prolog/epilog generation -// -//------------------------------------------------------------------------- + //------------------------------------------------------------------------- + // + // End prolog/epilog generation + // + //------------------------------------------------------------------------- -/*****************************************************************************/ -#ifdef DEBUGGING_SUPPORT -/*****************************************************************************/ + void genSinglePush(); + void genSinglePop(); + regMaskTP genPushRegs(regMaskTP regs, regMaskTP* byrefRegs, regMaskTP* noRefRegs); + void genPopRegs(regMaskTP regs, regMaskTP byrefRegs, regMaskTP noRefRegs); + +/* +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XX XX +XX Debugging Support XX +XX XX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +*/ #ifdef DEBUG void genIPmappingDisp(unsigned mappingNum, Compiler::IPmappingDsc* ipMapping); @@ -730,10 +742,6 @@ protected: unsigned genTrnslLocalVarCount; #endif -/*****************************************************************************/ -#endif // DEBUGGING_SUPPORT -/*****************************************************************************/ - #ifndef LEGACY_BACKEND #include "codegenlinear.h" #else // LEGACY_BACKEND diff --git a/src/jit/codegenarm.cpp b/src/jit/codegenarm.cpp index 4ce8230..73e51f2 100644 --- a/src/jit/codegenarm.cpp +++ b/src/jit/codegenarm.cpp @@ -27,102 +27,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #include "gcinfoencoder.h" #endif -// Get the register assigned to the given node - -regNumber CodeGenInterface::genGetAssignedReg(GenTreePtr tree) -{ - return tree->gtRegNum; -} - -//------------------------------------------------------------------------ -// genSpillVar: Spill a local variable -// -// Arguments: -// tree - the lclVar node for the variable being spilled -// -// Return Value: -// None. -// -// Assumptions: -// The lclVar must be a register candidate (lvRegCandidate) - -void CodeGen::genSpillVar(GenTreePtr tree) -{ - regMaskTP regMask; - unsigned varNum = tree->gtLclVarCommon.gtLclNum; - LclVarDsc* varDsc = &(compiler->lvaTable[varNum]); - - // We don't actually need to spill if it is already living in memory - bool needsSpill = ((tree->gtFlags & GTF_VAR_DEF) == 0 && varDsc->lvIsInReg()); - if (needsSpill) - { - bool restoreRegVar = false; - if (tree->gtOper == GT_REG_VAR) - { - tree->SetOper(GT_LCL_VAR); - restoreRegVar = true; - } - - // mask off the flag to generate the right spill code, then bring it back - tree->gtFlags &= ~GTF_REG_VAL; - - instruction storeIns = ins_Store(tree->TypeGet()); - - if (varTypeIsMultiReg(tree)) - { - assert(varDsc->lvRegNum == genRegPairLo(tree->gtRegPair)); - assert(varDsc->lvOtherReg == genRegPairHi(tree->gtRegPair)); - regNumber regLo = genRegPairLo(tree->gtRegPair); - regNumber regHi = genRegPairHi(tree->gtRegPair); - inst_TT_RV(storeIns, tree, regLo); - inst_TT_RV(storeIns, tree, regHi, 4); - } - else - { - assert(varDsc->lvRegNum == tree->gtRegNum); - inst_TT_RV(storeIns, tree, tree->gtRegNum); - } - tree->gtFlags |= GTF_REG_VAL; - - if (restoreRegVar) - { - tree->SetOper(GT_REG_VAR); - } - - genUpdateRegLife(varDsc, /*isBorn*/ false, /*isDying*/ true DEBUGARG(tree)); - gcInfo.gcMarkRegSetNpt(varDsc->lvRegMask()); - - if (VarSetOps::IsMember(compiler, gcInfo.gcTrkStkPtrLcls, varDsc->lvVarIndex)) - { -#ifdef DEBUG - if (!VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex)) - { - JITDUMP("\t\t\t\t\t\t\tVar V%02u becoming live\n", varNum); - } - else - { - JITDUMP("\t\t\t\t\t\t\tVar V%02u continuing live\n", varNum); - } -#endif - VarSetOps::AddElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex); - } - } - - tree->gtFlags &= ~GTF_SPILL; - varDsc->lvRegNum = REG_STK; - if (varTypeIsMultiReg(tree)) - { - varDsc->lvOtherReg = REG_STK; - } -} - -// inline -void CodeGenInterface::genUpdateVarReg(LclVarDsc* varDsc, GenTreePtr tree) -{ - assert(tree->OperIsScalarLocal() || (tree->gtOper == GT_COPY)); - varDsc->lvRegNum = tree->gtRegNum; -} - /***************************************************************************** * * Generate code that will set the given register to the integer constant. @@ -157,735 +61,22 @@ void CodeGen::genSetRegToIcon(regNumber reg, ssize_t val, var_types type, insFla */ void CodeGen::genEmitGSCookieCheck(bool pushReg) { - NYI("ARM genEmitGSCookieCheck is not yet implemented for protojit"); + NYI("ARM genEmitGSCookieCheck"); } -/***************************************************************************** - * - * Generate code for all the basic blocks in the function. - */ - -void CodeGen::genCodeForBBlist() +BasicBlock* CodeGen::genCallFinally(BasicBlock* block, BasicBlock* lblk) { - unsigned varNum; - LclVarDsc* varDsc; - - unsigned savedStkLvl; - -#ifdef DEBUG - genInterruptibleUsed = true; - - // You have to be careful if you create basic blocks from now on - compiler->fgSafeBasicBlockCreation = false; - - // This stress mode is not comptible with fully interruptible GC - if (genInterruptible && compiler->opts.compStackCheckOnCall) - { - compiler->opts.compStackCheckOnCall = false; - } - - // This stress mode is not comptible with fully interruptible GC - if (genInterruptible && compiler->opts.compStackCheckOnRet) - { - compiler->opts.compStackCheckOnRet = false; - } -#endif - - // Prepare the blocks for exception handling codegen: mark the blocks that needs labels. - genPrepForEHCodegen(); - - assert(!compiler->fgFirstBBScratch || - compiler->fgFirstBB == compiler->fgFirstBBScratch); // compiler->fgFirstBBScratch has to be first. - - /* Initialize the spill tracking logic */ - - regSet.rsSpillBeg(); - -#ifdef DEBUGGING_SUPPORT - /* Initialize the line# tracking logic */ - - if (compiler->opts.compScopeInfo) - { - siInit(); - } -#endif - - if (compiler->opts.compDbgEnC) - { - noway_assert(isFramePointerUsed()); - regSet.rsSetRegsModified(RBM_INT_CALLEE_SAVED & ~RBM_FPBASE); - } - - /* If we have any pinvoke calls, we might potentially trash everything */ - if (compiler->info.compCallUnmanaged) - { - noway_assert(isFramePointerUsed()); // Setup of Pinvoke frame currently requires an EBP style frame - regSet.rsSetRegsModified(RBM_INT_CALLEE_SAVED & ~RBM_FPBASE); - } - - genPendingCallLabel = nullptr; - - /* Initialize the pointer tracking code */ - - gcInfo.gcRegPtrSetInit(); - gcInfo.gcVarPtrSetInit(); - - /* If any arguments live in registers, mark those regs as such */ - - for (varNum = 0, varDsc = compiler->lvaTable; varNum < compiler->lvaCount; varNum++, varDsc++) - { - /* Is this variable a parameter assigned to a register? */ - - if (!varDsc->lvIsParam || !varDsc->lvRegister) - continue; - - /* Is the argument live on entry to the method? */ - - if (!VarSetOps::IsMember(compiler, compiler->fgFirstBB->bbLiveIn, varDsc->lvVarIndex)) - continue; - - /* Is this a floating-point argument? */ - - if (varDsc->IsFloatRegType()) - continue; - - noway_assert(!varTypeIsFloating(varDsc->TypeGet())); - - /* Mark the register as holding the variable */ - - regTracker.rsTrackRegLclVar(varDsc->lvRegNum, varNum); - } - - unsigned finallyNesting = 0; - - // Make sure a set is allocated for compiler->compCurLife (in the long case), so we can set it to empty without - // allocation at the start of each basic block. - VarSetOps::AssignNoCopy(compiler, compiler->compCurLife, VarSetOps::MakeEmpty(compiler)); - - /*------------------------------------------------------------------------- - * - * Walk the basic blocks and generate code for each one - * - */ - - BasicBlock* block; - BasicBlock* lblk; /* previous block */ - - for (lblk = NULL, block = compiler->fgFirstBB; block != NULL; lblk = block, block = block->bbNext) - { -#ifdef DEBUG - if (compiler->verbose) - { - printf("\n=============== Generating "); - block->dspBlockHeader(compiler, true, true); - compiler->fgDispBBLiveness(block); - } -#endif // DEBUG - - /* Figure out which registers hold variables on entry to this block */ - - regSet.ClearMaskVars(); - gcInfo.gcRegGCrefSetCur = RBM_NONE; - gcInfo.gcRegByrefSetCur = RBM_NONE; - - compiler->m_pLinearScan->recordVarLocationsAtStartOfBB(block); - - genUpdateLife(block->bbLiveIn); - - // Even if liveness didn't change, we need to update the registers containing GC references. - // genUpdateLife will update the registers live due to liveness changes. But what about registers that didn't - // change? We cleared them out above. Maybe we should just not clear them out, but update the ones that change - // here. That would require handling the changes in recordVarLocationsAtStartOfBB(). - - regMaskTP newLiveRegSet = RBM_NONE; - regMaskTP newRegGCrefSet = RBM_NONE; - regMaskTP newRegByrefSet = RBM_NONE; - VARSET_ITER_INIT(compiler, iter, block->bbLiveIn, varIndex); - while (iter.NextElem(compiler, &varIndex)) - { - unsigned varNum = compiler->lvaTrackedToVarNum[varIndex]; - LclVarDsc* varDsc = &(compiler->lvaTable[varNum]); - - if (varDsc->lvIsInReg()) - { - newLiveRegSet |= varDsc->lvRegMask(); - if (varDsc->lvType == TYP_REF) - { - newRegGCrefSet |= varDsc->lvRegMask(); - } - else if (varDsc->lvType == TYP_BYREF) - { - newRegByrefSet |= varDsc->lvRegMask(); - } - } - else if (varDsc->lvType == TYP_REF || varDsc->lvType == TYP_BYREF) - { - VarSetOps::AddElemD(compiler, gcInfo.gcVarPtrSetCur, varIndex); - } - } - - regSet.rsMaskVars = newLiveRegSet; - gcInfo.gcMarkRegSetGCref(newRegGCrefSet DEBUGARG(true)); - gcInfo.gcMarkRegSetByref(newRegByrefSet DEBUGARG(true)); - - /* Blocks with handlerGetsXcptnObj()==true use GT_CATCH_ARG to - represent the exception object (TYP_REF). - We mark REG_EXCEPTION_OBJECT as holding a GC object on entry - to the block, it will be the first thing evaluated - (thanks to GTF_ORDER_SIDEEFF). - */ - - if (handlerGetsXcptnObj(block->bbCatchTyp)) - { - for (GenTree* node : LIR::AsRange(block)) - { - if (node->OperGet() == GT_CATCH_ARG) - { - gcInfo.gcMarkRegSetGCref(RBM_EXCEPTION_OBJECT); - break; - } - } - } - - /* Start a new code output block */ - CLANG_FORMAT_COMMENT_ANCHOR; - -#if FEATURE_EH_FUNCLETS -#if defined(_TARGET_ARM_) - // If this block is the target of a finally return, we need to add a preceding NOP, in the same EH region, - // so the unwinder doesn't get confused by our "movw lr, xxx; movt lr, xxx; b Lyyy" calling convention that - // calls the funclet during non-exceptional control flow. - if (block->bbFlags & BBF_FINALLY_TARGET) - { - assert(block->bbFlags & BBF_JMP_TARGET); - -#ifdef DEBUG - if (compiler->verbose) - { - printf("\nEmitting finally target NOP predecessor for BB%02u\n", block->bbNum); - } -#endif - // Create a label that we'll use for computing the start of an EH region, if this block is - // at the beginning of such a region. If we used the existing bbEmitCookie as is for - // determining the EH regions, then this NOP would end up outside of the region, if this - // block starts an EH region. If we pointed the existing bbEmitCookie here, then the NOP - // would be executed, which we would prefer not to do. - - block->bbUnwindNopEmitCookie = - getEmitter()->emitAddLabel(gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, gcInfo.gcRegByrefSetCur); - - instGen(INS_nop); - } -#endif // defined(_TARGET_ARM_) - - genUpdateCurrentFunclet(block); -#endif // FEATURE_EH_FUNCLETS - -#ifdef _TARGET_XARCH_ - if (genAlignLoops && block->bbFlags & BBF_LOOP_HEAD) - { - getEmitter()->emitLoopAlign(); - } -#endif - -#ifdef DEBUG - if (compiler->opts.dspCode) - printf("\n L_M%03u_BB%02u:\n", Compiler::s_compMethodsCount, block->bbNum); -#endif - - block->bbEmitCookie = NULL; - - if (block->bbFlags & (BBF_JMP_TARGET | BBF_HAS_LABEL)) - { - /* Mark a label and update the current set of live GC refs */ - - block->bbEmitCookie = - getEmitter()->emitAddLabel(gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, gcInfo.gcRegByrefSetCur, - /*isFinally*/ block->bbFlags & BBF_FINALLY_TARGET); - } - - if (block == compiler->fgFirstColdBlock) - { -#ifdef DEBUG - if (compiler->verbose) - { - printf("\nThis is the start of the cold region of the method\n"); - } -#endif - // We should never have a block that falls through into the Cold section - noway_assert(!lblk->bbFallsThrough()); - - // We require the block that starts the Cold section to have a label - noway_assert(block->bbEmitCookie); - getEmitter()->emitSetFirstColdIGCookie(block->bbEmitCookie); - } - - /* Both stacks are always empty on entry to a basic block */ - - genStackLevel = 0; - -#if !FEATURE_FIXED_OUT_ARGS - /* Check for inserted throw blocks and adjust genStackLevel */ - - if (!isFramePointerUsed() && compiler->fgIsThrowHlpBlk(block)) - { - noway_assert(block->bbFlags & BBF_JMP_TARGET); - - genStackLevel = compiler->fgThrowHlpBlkStkLevel(block) * sizeof(int); - - if (genStackLevel) - { - NYI("Need emitMarkStackLvl()"); - } - } -#endif // !FEATURE_FIXED_OUT_ARGS - - savedStkLvl = genStackLevel; - - /* Tell everyone which basic block we're working on */ - - compiler->compCurBB = block; - -#ifdef DEBUGGING_SUPPORT - siBeginBlock(block); - - // BBF_INTERNAL blocks don't correspond to any single IL instruction. - if (compiler->opts.compDbgInfo && (block->bbFlags & BBF_INTERNAL) && block != compiler->fgFirstBB) - genIPmappingAdd((IL_OFFSETX)ICorDebugInfo::NO_MAPPING, true); - - bool firstMapping = true; -#endif // DEBUGGING_SUPPORT - - /*--------------------------------------------------------------------- - * - * Generate code for each statement-tree in the block - * - */ - CLANG_FORMAT_COMMENT_ANCHOR; - -#if FEATURE_EH_FUNCLETS - if (block->bbFlags & BBF_FUNCLET_BEG) - { - genReserveFuncletProlog(block); - } -#endif // FEATURE_EH_FUNCLETS - - // Clear compCurStmt and compCurLifeTree. - compiler->compCurStmt = nullptr; - compiler->compCurLifeTree = nullptr; - -#ifdef DEBUG - bool pastProfileUpdate = false; -#endif - -// Traverse the block in linear order, generating code for each node as we -// as we encounter it. -#ifdef DEBUGGING_SUPPORT - IL_OFFSETX currentILOffset = BAD_IL_OFFSET; -#endif - for (GenTree* node : LIR::AsRange(block)) - { -#ifdef DEBUGGING_SUPPORT - // Do we have a new IL offset? - if (node->OperGet() == GT_IL_OFFSET) - { - genEnsureCodeEmitted(currentILOffset); - - currentILOffset = node->gtStmt.gtStmtILoffsx; - - genIPmappingAdd(currentILOffset, firstMapping); - firstMapping = false; - } -#endif // DEBUGGING_SUPPORT - -#ifdef DEBUG - if (node->OperGet() == GT_IL_OFFSET) - { - noway_assert(node->gtStmt.gtStmtLastILoffs <= compiler->info.compILCodeSize || - node->gtStmt.gtStmtLastILoffs == BAD_IL_OFFSET); - - if (compiler->opts.dspCode && compiler->opts.dspInstrs && - node->gtStmt.gtStmtLastILoffs != BAD_IL_OFFSET) - { - while (genCurDispOffset <= node->gtStmt.gtStmtLastILoffs) - { - genCurDispOffset += dumpSingleInstr(compiler->info.compCode, genCurDispOffset, "> "); - } - } - } -#endif // DEBUG - - genCodeForTreeNode(node); - if (node->gtHasReg() && node->gtLsraInfo.isLocalDefUse) - { - genConsumeReg(node); - } - -#ifdef DEBUG - regSet.rsSpillChk(); - - assert((node->gtFlags & GTF_SPILL) == 0); - - /* Make sure we didn't bungle pointer register tracking */ - - regMaskTP ptrRegs = (gcInfo.gcRegGCrefSetCur | gcInfo.gcRegByrefSetCur); - regMaskTP nonVarPtrRegs = ptrRegs & ~regSet.rsMaskVars; - - // If return is a GC-type, clear it. Note that if a common - // epilog is generated (genReturnBB) it has a void return - // even though we might return a ref. We can't use the compRetType - // as the determiner because something we are tracking as a byref - // might be used as a return value of a int function (which is legal) - if (node->gtOper == GT_RETURN && (varTypeIsGC(compiler->info.compRetType) || - (node->gtOp.gtOp1 != 0 && varTypeIsGC(node->gtOp.gtOp1->TypeGet())))) - { - nonVarPtrRegs &= ~RBM_INTRET; - } - - // When profiling, the first few nodes in a catch block will be an update of - // the profile count (does not interfere with the exception object). - if (((compiler->opts.eeFlags & CORJIT_FLG_BBINSTR) != 0) && handlerGetsXcptnObj(block->bbCatchTyp)) - { - pastProfileUpdate = pastProfileUpdate || node->OperGet() == GT_CATCH_ARG; - if (!pastProfileUpdate) - { - nonVarPtrRegs &= ~RBM_EXCEPTION_OBJECT; - } - } - - if (nonVarPtrRegs) - { - printf("Regset after node="); - Compiler::printTreeID(node); - printf(" BB%02u gcr=", block->bbNum); - printRegMaskInt(gcInfo.gcRegGCrefSetCur & ~regSet.rsMaskVars); - compiler->getEmitter()->emitDispRegSet(gcInfo.gcRegGCrefSetCur & ~regSet.rsMaskVars); - printf(", byr="); - printRegMaskInt(gcInfo.gcRegByrefSetCur & ~regSet.rsMaskVars); - compiler->getEmitter()->emitDispRegSet(gcInfo.gcRegByrefSetCur & ~regSet.rsMaskVars); - printf(", regVars="); - printRegMaskInt(regSet.rsMaskVars); - compiler->getEmitter()->emitDispRegSet(regSet.rsMaskVars); - printf("\n"); - } - - noway_assert(nonVarPtrRegs == 0); -#endif // DEBUG - } - -#ifdef DEBUGGING_SUPPORT - // It is possible to reach the end of the block without generating code for the current IL offset. - // For example, if the following IR ends the current block, no code will have been generated for - // offset 21: - // - // ( 0, 0) [000040] ------------ il_offset void IL offset: 21 - // - // N001 ( 0, 0) [000039] ------------ nop void - // - // This can lead to problems when debugging the generated code. To prevent these issues, make sure - // we've generated code for the last IL offset we saw in the block. - genEnsureCodeEmitted(currentILOffset); - - if (compiler->opts.compScopeInfo && (compiler->info.compVarScopesCount > 0)) - { - siEndBlock(block); - - /* Is this the last block, and are there any open scopes left ? */ - - bool isLastBlockProcessed = (block->bbNext == NULL); - if (block->isBBCallAlwaysPair()) - { - isLastBlockProcessed = (block->bbNext->bbNext == NULL); - } - - if (isLastBlockProcessed && siOpenScopeList.scNext) - { - /* This assert no longer holds, because we may insert a throw - block to demarcate the end of a try or finally region when they - are at the end of the method. It would be nice if we could fix - our code so that this throw block will no longer be necessary. */ - - // noway_assert(block->bbCodeOffsEnd != compiler->info.compILCodeSize); - - siCloseAllOpenScopes(); - } - } - -#endif // DEBUGGING_SUPPORT - - genStackLevel -= savedStkLvl; - -#ifdef DEBUG - // compCurLife should be equal to the liveOut set, except that we don't keep - // it up to date for vars that are not register candidates - // (it would be nice to have a xor set function) - - VARSET_TP VARSET_INIT_NOCOPY(extraLiveVars, VarSetOps::Diff(compiler, block->bbLiveOut, compiler->compCurLife)); - VarSetOps::UnionD(compiler, extraLiveVars, VarSetOps::Diff(compiler, compiler->compCurLife, block->bbLiveOut)); - VARSET_ITER_INIT(compiler, extraLiveVarIter, extraLiveVars, extraLiveVarIndex); - while (extraLiveVarIter.NextElem(compiler, &extraLiveVarIndex)) - { - unsigned varNum = compiler->lvaTrackedToVarNum[extraLiveVarIndex]; - LclVarDsc* varDsc = compiler->lvaTable + varNum; - assert(!varDsc->lvIsRegCandidate()); - } -#endif - - /* Both stacks should always be empty on exit from a basic block */ - - noway_assert(genStackLevel == 0); - -#ifdef _TARGET_AMD64_ - // On AMD64, we need to generate a NOP after a call that is the last instruction of the block, in several - // situations, to support proper exception handling semantics. This is mostly to ensure that when the stack - // walker computes an instruction pointer for a frame, that instruction pointer is in the correct EH region. - // The document "X64 and ARM ABIs.docx" has more details. The situations: - // 1. If the call instruction is in a different EH region as the instruction that follows it. - // 2. If the call immediately precedes an OS epilog. (Note that what the JIT or VM consider an epilog might - // be slightly different from what the OS considers an epilog, and it is the OS-reported epilog that matters - // here.) - // We handle case #1 here, and case #2 in the emitter. - if (getEmitter()->emitIsLastInsCall()) - { - // Ok, the last instruction generated is a call instruction. Do any of the other conditions hold? - // Note: we may be generating a few too many NOPs for the case of call preceding an epilog. Technically, - // if the next block is a BBJ_RETURN, an epilog will be generated, but there may be some instructions - // generated before the OS epilog starts, such as a GS cookie check. - if ((block->bbNext == nullptr) || !BasicBlock::sameEHRegion(block, block->bbNext)) - { - // We only need the NOP if we're not going to generate any more code as part of the block end. - - switch (block->bbJumpKind) - { - case BBJ_ALWAYS: - case BBJ_THROW: - case BBJ_CALLFINALLY: - case BBJ_EHCATCHRET: - // We're going to generate more code below anyway, so no need for the NOP. - - case BBJ_RETURN: - case BBJ_EHFINALLYRET: - case BBJ_EHFILTERRET: - // These are the "epilog follows" case, handled in the emitter. - - break; - - case BBJ_NONE: - if (block->bbNext == nullptr) - { - // Call immediately before the end of the code; we should never get here . - instGen(INS_BREAKPOINT); // This should never get executed - } - else - { - // We need the NOP - instGen(INS_nop); - } - break; - - case BBJ_COND: - case BBJ_SWITCH: - // These can't have a call as the last instruction! - - default: - noway_assert(!"Unexpected bbJumpKind"); - break; - } - } - } -#endif //_TARGET_AMD64_ - - /* Do we need to generate a jump or return? */ - - switch (block->bbJumpKind) - { - case BBJ_ALWAYS: - inst_JMP(EJ_jmp, block->bbJumpDest); - break; - - case BBJ_RETURN: - genExitCode(block); - break; - - case BBJ_THROW: - // If we have a throw at the end of a function or funclet, we need to emit another instruction - // afterwards to help the OS unwinder determine the correct context during unwind. - // We insert an unexecuted breakpoint instruction in several situations - // following a throw instruction: - // 1. If the throw is the last instruction of the function or funclet. This helps - // the OS unwinder determine the correct context during an unwind from the - // thrown exception. - // 2. If this is this is the last block of the hot section. - // 3. If the subsequent block is a special throw block. - // 4. On AMD64, if the next block is in a different EH region. - if ((block->bbNext == NULL) -#if FEATURE_EH_FUNCLETS - || (block->bbNext->bbFlags & BBF_FUNCLET_BEG) -#endif // FEATURE_EH_FUNCLETS -#ifdef _TARGET_AMD64_ - || !BasicBlock::sameEHRegion(block, block->bbNext) -#endif // _TARGET_AMD64_ - || (!isFramePointerUsed() && compiler->fgIsThrowHlpBlk(block->bbNext)) || - block->bbNext == compiler->fgFirstColdBlock) - { - instGen(INS_BREAKPOINT); // This should never get executed - } - - break; - - case BBJ_CALLFINALLY: - - // Now set REG_LR to the address of where the finally funclet should - // return to directly. - - BasicBlock* bbFinallyRet; - bbFinallyRet = NULL; - - // We don't have retless calls, since we use the BBJ_ALWAYS to point at a NOP pad where - // we would have otherwise created retless calls. - assert(block->isBBCallAlwaysPair()); - - assert(block->bbNext != NULL); - assert(block->bbNext->bbJumpKind == BBJ_ALWAYS); - assert(block->bbNext->bbJumpDest != NULL); - assert(block->bbNext->bbJumpDest->bbFlags & BBF_FINALLY_TARGET); - - bbFinallyRet = block->bbNext->bbJumpDest; - bbFinallyRet->bbFlags |= BBF_JMP_TARGET; - -#if 0 - // TODO-ARM-CQ: - // We don't know the address of finally funclet yet. But adr requires the offset - // to finally funclet from current IP is within 4095 bytes. So this code is disabled - // for now. - getEmitter()->emitIns_J_R (INS_adr, - EA_4BYTE, - bbFinallyRet, - REG_LR); -#else // !0 - // Load the address where the finally funclet should return into LR. - // The funclet prolog/epilog will do "push {lr}" / "pop {pc}" to do - // the return. - getEmitter()->emitIns_R_L(INS_movw, EA_4BYTE_DSP_RELOC, bbFinallyRet, REG_LR); - getEmitter()->emitIns_R_L(INS_movt, EA_4BYTE_DSP_RELOC, bbFinallyRet, REG_LR); -#endif // !0 - - // Jump to the finally BB - inst_JMP(EJ_jmp, block->bbJumpDest); - - // The BBJ_ALWAYS is used because the BBJ_CALLFINALLY can't point to the - // jump target using bbJumpDest - that is already used to point - // to the finally block. So just skip past the BBJ_ALWAYS unless the - // block is RETLESS. - if (!(block->bbFlags & BBF_RETLESS_CALL)) - { - assert(block->isBBCallAlwaysPair()); - - lblk = block; - block = block->bbNext; - } - break; - -#ifdef _TARGET_ARM_ - - case BBJ_EHCATCHRET: - // set r0 to the address the VM should return to after the catch - getEmitter()->emitIns_R_L(INS_movw, EA_4BYTE_DSP_RELOC, block->bbJumpDest, REG_R0); - getEmitter()->emitIns_R_L(INS_movt, EA_4BYTE_DSP_RELOC, block->bbJumpDest, REG_R0); - - __fallthrough; - - case BBJ_EHFINALLYRET: - case BBJ_EHFILTERRET: - genReserveFuncletEpilog(block); - break; - -#elif defined(_TARGET_AMD64_) - - case BBJ_EHCATCHRET: - // Set EAX to the address the VM should return to after the catch. - // Generate a RIP-relative - // lea reg, [rip + disp32] ; the RIP is implicit - // which will be position-indepenent. - // TODO-ARM-Bug?: For ngen, we need to generate a reloc for the displacement (maybe EA_PTR_DSP_RELOC). - getEmitter()->emitIns_R_L(INS_lea, EA_PTRSIZE, block->bbJumpDest, REG_INTRET); - __fallthrough; - - case BBJ_EHFINALLYRET: - case BBJ_EHFILTERRET: - genReserveFuncletEpilog(block); - break; - -#endif // _TARGET_AMD64_ - - case BBJ_NONE: - case BBJ_COND: - case BBJ_SWITCH: - break; - - default: - noway_assert(!"Unexpected bbJumpKind"); - break; - } - -#ifdef DEBUG - compiler->compCurBB = 0; -#endif - - } //------------------ END-FOR each block of the method ------------------- - - /* Nothing is live at this point */ - genUpdateLife(VarSetOps::MakeEmpty(compiler)); - - /* Finalize the spill tracking logic */ - - regSet.rsSpillEnd(); - - /* Finalize the temp tracking logic */ - - compiler->tmpEnd(); - -#ifdef DEBUG - if (compiler->verbose) - { - printf("\n# "); - printf("compCycleEstimate = %6d, compSizeEstimate = %5d ", compiler->compCycleEstimate, compiler->compSizeEstimate); - printf("%s\n", compiler->info.compFullName); - } -#endif + NYI("ARM genCallFinally"); + return block; } -// return the child that has the same reg as the dst (if any) -// other child returned (out param) in 'other' -GenTree* sameRegAsDst(GenTree* tree, GenTree*& other /*out*/) -{ - if (tree->gtRegNum == REG_NA) - { - other = nullptr; - return NULL; - } +// move an immediate value into an integer register - GenTreePtr op1 = tree->gtOp.gtOp1->gtEffectiveVal(); - GenTreePtr op2 = tree->gtOp.gtOp2->gtEffectiveVal(); - if (op1->gtRegNum == tree->gtRegNum) - { - other = op2; - return op1; - } - if (op2->gtRegNum == tree->gtRegNum) - { - other = op1; - return op2; - } - else - { - other = nullptr; - return NULL; - } +void CodeGen::genEHCatchRet(BasicBlock* block) +{ + NYI("ARM genEHCatchRet"); } -// move an immediate value into an integer register - void CodeGen::instGen_Set_Reg_To_Imm(emitAttr size, regNumber reg, ssize_t imm, insFlags flags) { // reg cannot be a FP register @@ -902,16 +93,7 @@ void CodeGen::instGen_Set_Reg_To_Imm(emitAttr size, regNumber reg, ssize_t imm, } else { -#ifdef _TARGET_AMD64_ - if (AddrShouldUsePCRel(imm)) - { - getEmitter()->emitIns_R_AI(INS_lea, EA_PTR_DSP_RELOC, reg, imm); - } - else -#endif // _TARGET_AMD64_ - { - getEmitter()->emitIns_R_I(INS_mov, size, reg, imm); - } + getEmitter()->emitIns_R_I(INS_mov, size, reg, imm); } regTracker.rsTrackRegIntCns(reg, imm); } @@ -1423,6 +605,7 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) break; case GT_LIST: + case GT_FIELD_LIST: case GT_ARGPLACE: // Nothing to do break; @@ -1479,7 +662,7 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) case GT_LOCKADD: case GT_XCHG: case GT_XADD: - genLockedInstructions(treeNode); + genLockedInstructions(treeNode->AsOp()); break; case GT_CMPXCHG: @@ -1554,7 +737,8 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) { #ifdef DEBUG char message[256]; - sprintf(message, "NYI: Unimplemented node type %s\n", GenTree::NodeName(treeNode->OperGet())); + _snprintf_s(message, _countof(message), _TRUNCATE, "NYI: Unimplemented node type %s\n", + GenTree::NodeName(treeNode->OperGet())); notYetImplemented(message, __FILE__, __LINE__); #else NYI("unimplemented node"); @@ -1566,7 +750,7 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) // generate code for the locked operations: // GT_LOCKADD, GT_XCHG, GT_XADD -void CodeGen::genLockedInstructions(GenTree* treeNode) +void CodeGen::genLockedInstructions(GenTreeOp* treeNode) { NYI("genLockedInstructions"); } @@ -1697,188 +881,9 @@ void CodeGen::genCodeForShift(GenTreePtr tree) NYI("genCodeForShift"); } -void CodeGen::genUnspillRegIfNeeded(GenTree* tree) -{ - regNumber dstReg = tree->gtRegNum; - - GenTree* unspillTree = tree; - if (tree->gtOper == GT_RELOAD) - { - unspillTree = tree->gtOp.gtOp1; - } - if (unspillTree->gtFlags & GTF_SPILLED) - { - if (genIsRegCandidateLocal(unspillTree)) - { - // Reset spilled flag, since we are going to load a local variable from its home location. - unspillTree->gtFlags &= ~GTF_SPILLED; - - // Load local variable from its home location. - inst_RV_TT(ins_Load(unspillTree->gtType), dstReg, unspillTree); - - unspillTree->SetInReg(); - - GenTreeLclVarCommon* lcl = unspillTree->AsLclVarCommon(); - LclVarDsc* varDsc = &compiler->lvaTable[lcl->gtLclNum]; - - // TODO-Review: We would like to call: - // genUpdateRegLife(varDsc, /*isBorn*/ true, /*isDying*/ false DEBUGARG(tree)); - // instead of the following code, but this ends up hitting this assert: - // assert((regSet.rsMaskVars & regMask) == 0); - // due to issues with LSRA resolution moves. - // So, just force it for now. This probably indicates a condition that creates a GC hole! - // - // Extra note: I think we really want to call something like gcInfo.gcUpdateForRegVarMove, - // because the variable is not really going live or dead, but that method is somewhat poorly - // factored because it, in turn, updates rsMaskVars which is part of RegSet not GCInfo. - // TODO-Cleanup: This code exists in other CodeGen*.cpp files, and should be moved to CodeGenCommon.cpp. - - genUpdateVarReg(varDsc, tree); -#ifdef DEBUG - if (VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex)) - { - JITDUMP("\t\t\t\t\t\t\tRemoving V%02u from gcVarPtrSetCur\n", lcl->gtLclNum); - } -#endif // DEBUG - VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex); - -#ifdef DEBUG - if (compiler->verbose) - { - printf("\t\t\t\t\t\t\tV%02u in reg ", lcl->gtLclNum); - varDsc->PrintVarReg(); - printf(" is becoming live "); - Compiler::printTreeID(unspillTree); - printf("\n"); - } -#endif // DEBUG - - regSet.AddMaskVars(genGetRegMask(varDsc)); - } - else - { - TempDsc* t = regSet.rsUnspillInPlace(unspillTree, unspillTree->gtRegNum); - compiler->tmpRlsTemp(t); - getEmitter()->emitIns_R_S(ins_Load(unspillTree->gtType), emitActualTypeSize(unspillTree->gtType), dstReg, - t->tdTempNum(), 0); - - unspillTree->SetInReg(); - } - - gcInfo.gcMarkRegPtrVal(dstReg, unspillTree->TypeGet()); - } -} - -// do liveness update for a subnode that is being consumed by codegen -regNumber CodeGen::genConsumeReg(GenTree* tree) -{ - genUnspillRegIfNeeded(tree); - - // genUpdateLife() will also spill local var if marked as GTF_SPILL by calling CodeGen::genSpillVar - genUpdateLife(tree); - assert(tree->gtRegNum != REG_NA); - - // there are three cases where consuming a reg means clearing the bit in the live mask - // 1. it was not produced by a local - // 2. it was produced by a local that is going dead - // 3. it was produced by a local that does not live in that reg (like one allocated on the stack) - - if (genIsRegCandidateLocal(tree)) - { - GenTreeLclVarCommon* lcl = tree->AsLclVarCommon(); - LclVarDsc* varDsc = &compiler->lvaTable[lcl->GetLclNum()]; - - if (varDsc->lvRegNum == tree->gtRegNum && ((tree->gtFlags & GTF_VAR_DEATH) != 0)) - { - gcInfo.gcMarkRegSetNpt(genRegMask(tree->gtRegNum)); - } - else if (!varDsc->lvLRACandidate) - { - gcInfo.gcMarkRegSetNpt(genRegMask(tree->gtRegNum)); - } - } - else - { - gcInfo.gcMarkRegSetNpt(genRegMask(tree->gtRegNum)); - } - - return tree->gtRegNum; -} - -// Do liveness update for an address tree: one of GT_LEA, GT_LCL_VAR, or GT_CNS_INT (for call indirect). -void CodeGen::genConsumeAddress(GenTree* addr) -{ - if (addr->OperGet() == GT_LEA) - { - genConsumeAddrMode(addr->AsAddrMode()); - } - else - { - assert(!addr->isContained()); - genConsumeReg(addr); - } -} - -// do liveness update for a subnode that is being consumed by codegen -void CodeGen::genConsumeAddrMode(GenTreeAddrMode* addr) +void CodeGen::genRegCopy(GenTree* treeNode) { - if (addr->Base()) - genConsumeReg(addr->Base()); - if (addr->Index()) - genConsumeReg(addr->Index()); -} - -// do liveness update for register produced by the current node in codegen -void CodeGen::genProduceReg(GenTree* tree) -{ - if (tree->gtFlags & GTF_SPILL) - { - if (genIsRegCandidateLocal(tree)) - { - // Store local variable to its home location. - tree->gtFlags &= ~GTF_REG_VAL; - inst_TT_RV(ins_Store(tree->gtType), tree, tree->gtRegNum); - } - else - { - tree->SetInReg(); - regSet.rsSpillTree(tree->gtRegNum, tree); - tree->gtFlags |= GTF_SPILLED; - tree->gtFlags &= ~GTF_SPILL; - gcInfo.gcMarkRegSetNpt(genRegMask(tree->gtRegNum)); - return; - } - } - - genUpdateLife(tree); - - // If we've produced a register, mark it as a pointer, as needed. - // Except in the case of a dead definition of a lclVar. - if (tree->gtHasReg() && (!tree->IsLocal() || (tree->gtFlags & GTF_VAR_DEATH) == 0)) - { - gcInfo.gcMarkRegPtrVal(tree->gtRegNum, tree->TypeGet()); - } - tree->SetInReg(); -} - -// transfer gc/byref status of src reg to dst reg -void CodeGen::genTransferRegGCState(regNumber dst, regNumber src) -{ - regMaskTP srcMask = genRegMask(src); - regMaskTP dstMask = genRegMask(dst); - - if (gcInfo.gcRegGCrefSetCur & srcMask) - { - gcInfo.gcMarkRegSetGCref(dstMask); - } - else if (gcInfo.gcRegByrefSetCur & srcMask) - { - gcInfo.gcMarkRegSetByref(dstMask); - } - else - { - gcInfo.gcMarkRegSetNpt(dstMask); - } + NYI("genRegCopy"); } // Produce code for a GT_CALL node @@ -2050,57 +1055,6 @@ void CodeGen::genEmitHelperCall(unsigned helper, NYI("Helper call"); } -/*****************************************************************************/ -#ifdef DEBUGGING_SUPPORT -/***************************************************************************** - * genSetScopeInfo - * - * Called for every scope info piece to record by the main genSetScopeInfo() - */ - -void CodeGen::genSetScopeInfo(unsigned which, - UNATIVE_OFFSET startOffs, - UNATIVE_OFFSET length, - unsigned varNum, - unsigned LVnum, - bool avail, - Compiler::siVarLoc& varLoc) -{ - /* We need to do some mapping while reporting back these variables */ - - unsigned ilVarNum = compiler->compMap2ILvarNum(varNum); - noway_assert((int)ilVarNum != ICorDebugInfo::UNKNOWN_ILNUM); - - VarName name = nullptr; - -#ifdef DEBUG - - for (unsigned scopeNum = 0; scopeNum < compiler->info.compVarScopesCount; scopeNum++) - { - if (LVnum == compiler->info.compVarScopes[scopeNum].vsdLVnum) - { - name = compiler->info.compVarScopes[scopeNum].vsdName; - } - } - - // Hang on to this compiler->info. - - TrnslLocalVarInfo& tlvi = genTrnslLocalVarInfo[which]; - - tlvi.tlviVarNum = ilVarNum; - tlvi.tlviLVnum = LVnum; - tlvi.tlviName = name; - tlvi.tlviStartPC = startOffs; - tlvi.tlviLength = length; - tlvi.tlviAvailable = avail; - tlvi.tlviVarLoc = varLoc; - -#endif // DEBUG - - compiler->eeSetLVinfo(which, startOffs, length, ilVarNum, LVnum, name, avail, varLoc); -} -#endif // DEBUGGING_SUPPORT - #endif // _TARGET_ARM_ #endif // !LEGACY_BACKEND diff --git a/src/jit/codegenarm64.cpp b/src/jit/codegenarm64.cpp index ca0df53..cc7c5dc 100644 --- a/src/jit/codegenarm64.cpp +++ b/src/jit/codegenarm64.cpp @@ -747,7 +747,7 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * +=======================+ <---- Caller's SP * |Callee saved registers | // multiple of 8 bytes * |-----------------------| - * | PSP slot | // 8 bytes + * | PSP slot | // 8 bytes (omitted in CoreRT ABI) * |-----------------------| * ~ alignment padding ~ // To make the whole frame 16 byte aligned. * |-----------------------| @@ -773,7 +773,7 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * +=======================+ <---- Caller's SP * |Callee saved registers | // multiple of 8 bytes * |-----------------------| - * | PSP slot | // 8 bytes + * | PSP slot | // 8 bytes (omitted in CoreRT ABI) * |-----------------------| * ~ alignment padding ~ // To make the whole frame 16 byte aligned. * |-----------------------| @@ -801,7 +801,7 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * +=======================+ <---- Caller's SP * |Callee saved registers | // multiple of 8 bytes * |-----------------------| - * | PSP slot | // 8 bytes + * | PSP slot | // 8 bytes (omitted in CoreRT ABI) * |-----------------------| * ~ alignment padding ~ // To make the first SP subtraction 16 byte aligned * |-----------------------| @@ -883,7 +883,7 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * +=======================+ <---- Caller's SP * |Callee saved registers | // multiple of 8 bytes * |-----------------------| - * | PSP slot | // 8 bytes + * | PSP slot | // 8 bytes (omitted in CoreRT ABI) * |-----------------------| * | Saved FP, LR | // 16 bytes * |-----------------------| @@ -988,6 +988,12 @@ void CodeGen::genFuncletProlog(BasicBlock* block) // This is the end of the OS-reported prolog for purposes of unwinding compiler->unwindEndProlog(); + // If there is no PSPSym (CoreRT ABI), we are done. + if (compiler->lvaPSPSym == BAD_VAR_NUM) + { + return; + } + if (isFilter) { // This is the first block of a filter @@ -1134,8 +1140,10 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() assert((rsMaskSaveRegs & RBM_LR) != 0); assert((rsMaskSaveRegs & RBM_FP) != 0); + unsigned PSPSize = (compiler->lvaPSPSym != BAD_VAR_NUM) ? REGSIZE_BYTES : 0; + unsigned saveRegsCount = genCountBits(rsMaskSaveRegs); - unsigned saveRegsPlusPSPSize = saveRegsCount * REGSIZE_BYTES + /* PSPSym */ REGSIZE_BYTES; + unsigned saveRegsPlusPSPSize = saveRegsCount * REGSIZE_BYTES + PSPSize; if (compiler->info.compIsVarArgs) { // For varargs we always save all of the integer register arguments @@ -1222,22 +1230,29 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() printf(" SP delta 1: %d\n", genFuncletInfo.fiSpDelta1); printf(" SP delta 2: %d\n", genFuncletInfo.fiSpDelta2); - if (CallerSP_to_PSP_slot_delta != compiler->lvaGetCallerSPRelativeOffset(compiler->lvaPSPSym)) // for debugging + if (compiler->lvaPSPSym != BAD_VAR_NUM) { - printf("lvaGetCallerSPRelativeOffset(lvaPSPSym): %d\n", - compiler->lvaGetCallerSPRelativeOffset(compiler->lvaPSPSym)); + if (CallerSP_to_PSP_slot_delta != + compiler->lvaGetCallerSPRelativeOffset(compiler->lvaPSPSym)) // for debugging + { + printf("lvaGetCallerSPRelativeOffset(lvaPSPSym): %d\n", + compiler->lvaGetCallerSPRelativeOffset(compiler->lvaPSPSym)); + } } } -#endif // DEBUG assert(genFuncletInfo.fiSP_to_FPLR_save_delta >= 0); assert(genFuncletInfo.fiSP_to_PSP_slot_delta >= 0); assert(genFuncletInfo.fiSP_to_CalleeSave_delta >= 0); assert(genFuncletInfo.fiCallerSP_to_PSP_slot_delta <= 0); - assert(compiler->lvaPSPSym != BAD_VAR_NUM); - assert(genFuncletInfo.fiCallerSP_to_PSP_slot_delta == - compiler->lvaGetCallerSPRelativeOffset(compiler->lvaPSPSym)); // same offset used in main function and - // funclet! + + if (compiler->lvaPSPSym != BAD_VAR_NUM) + { + assert(genFuncletInfo.fiCallerSP_to_PSP_slot_delta == + compiler->lvaGetCallerSPRelativeOffset(compiler->lvaPSPSym)); // same offset used in main function and + // funclet! + } +#endif // DEBUG } /* @@ -1250,100 +1265,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ -// Get the register assigned to the given node - -regNumber CodeGenInterface::genGetAssignedReg(GenTreePtr tree) -{ - return tree->gtRegNum; -} - -//------------------------------------------------------------------------ -// genSpillVar: Spill a local variable -// -// Arguments: -// tree - the lclVar node for the variable being spilled -// -// Return Value: -// None. -// -// Assumptions: -// The lclVar must be a register candidate (lvRegCandidate) - -void CodeGen::genSpillVar(GenTreePtr tree) -{ - unsigned varNum = tree->gtLclVarCommon.gtLclNum; - LclVarDsc* varDsc = &(compiler->lvaTable[varNum]); - - assert(varDsc->lvIsRegCandidate()); - - // We don't actually need to spill if it is already living in memory - bool needsSpill = ((tree->gtFlags & GTF_VAR_DEF) == 0 && varDsc->lvIsInReg()); - if (needsSpill) - { - var_types lclTyp = varDsc->TypeGet(); - if (varDsc->lvNormalizeOnStore()) - lclTyp = genActualType(lclTyp); - emitAttr size = emitTypeSize(lclTyp); - - bool restoreRegVar = false; - if (tree->gtOper == GT_REG_VAR) - { - tree->SetOper(GT_LCL_VAR); - restoreRegVar = true; - } - - // mask off the flag to generate the right spill code, then bring it back - tree->gtFlags &= ~GTF_REG_VAL; - - instruction storeIns = ins_Store(tree->TypeGet(), compiler->isSIMDTypeLocalAligned(varNum)); - - assert(varDsc->lvRegNum == tree->gtRegNum); - inst_TT_RV(storeIns, tree, tree->gtRegNum, 0, size); - - tree->gtFlags |= GTF_REG_VAL; - - if (restoreRegVar) - { - tree->SetOper(GT_REG_VAR); - } - - genUpdateRegLife(varDsc, /*isBorn*/ false, /*isDying*/ true DEBUGARG(tree)); - gcInfo.gcMarkRegSetNpt(varDsc->lvRegMask()); - - if (VarSetOps::IsMember(compiler, gcInfo.gcTrkStkPtrLcls, varDsc->lvVarIndex)) - { -#ifdef DEBUG - if (!VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex)) - { - JITDUMP("\t\t\t\t\t\t\tVar V%02u becoming live\n", varNum); - } - else - { - JITDUMP("\t\t\t\t\t\t\tVar V%02u continuing live\n", varNum); - } -#endif - VarSetOps::AddElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex); - } - } - - tree->gtFlags &= ~GTF_SPILL; - varDsc->lvRegNum = REG_STK; - if (varTypeIsMultiReg(tree)) - { - varDsc->lvOtherReg = REG_STK; - } -} - -// inline -void CodeGenInterface::genUpdateVarReg(LclVarDsc* varDsc, GenTreePtr tree) -{ - assert(tree->OperIsScalarLocal() || (tree->gtOper == GT_COPY)); - varDsc->lvRegNum = tree->gtRegNum; -} - -/*****************************************************************************/ -/*****************************************************************************/ - /***************************************************************************** * * Generate code that will set the given register to the integer constant. @@ -1405,702 +1326,79 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) genDefineTempLabel(gsCheckBlk); } -/***************************************************************************** - * - * Generate code for all the basic blocks in the function. - */ - -void CodeGen::genCodeForBBlist() -{ - unsigned varNum; - LclVarDsc* varDsc; - - unsigned savedStkLvl; - -#ifdef DEBUG - genInterruptibleUsed = true; - - // You have to be careful if you create basic blocks from now on - compiler->fgSafeBasicBlockCreation = false; - - // This stress mode is not comptible with fully interruptible GC - if (genInterruptible && compiler->opts.compStackCheckOnCall) - { - compiler->opts.compStackCheckOnCall = false; - } - - // This stress mode is not comptible with fully interruptible GC - if (genInterruptible && compiler->opts.compStackCheckOnRet) - { - compiler->opts.compStackCheckOnRet = false; - } -#endif // DEBUG - - // Prepare the blocks for exception handling codegen: mark the blocks that needs labels. - genPrepForEHCodegen(); - - assert(!compiler->fgFirstBBScratch || - compiler->fgFirstBB == compiler->fgFirstBBScratch); // compiler->fgFirstBBScratch has to be first. - - /* Initialize the spill tracking logic */ - - regSet.rsSpillBeg(); - -#ifdef DEBUGGING_SUPPORT - /* Initialize the line# tracking logic */ - - if (compiler->opts.compScopeInfo) - { - siInit(); - } -#endif - - // The current implementation of switch tables requires the first block to have a label so it - // can generate offsets to the switch label targets. - // TODO-ARM64-CQ: remove this when switches have been re-implemented to not use this. - if (compiler->fgHasSwitch) - { - compiler->fgFirstBB->bbFlags |= BBF_JMP_TARGET; - } - - genPendingCallLabel = nullptr; - - /* Initialize the pointer tracking code */ - - gcInfo.gcRegPtrSetInit(); - gcInfo.gcVarPtrSetInit(); - - /* If any arguments live in registers, mark those regs as such */ - - for (varNum = 0, varDsc = compiler->lvaTable; varNum < compiler->lvaCount; varNum++, varDsc++) - { - /* Is this variable a parameter assigned to a register? */ - - if (!varDsc->lvIsParam || !varDsc->lvRegister) - continue; - - /* Is the argument live on entry to the method? */ - - if (!VarSetOps::IsMember(compiler, compiler->fgFirstBB->bbLiveIn, varDsc->lvVarIndex)) - continue; - - /* Is this a floating-point argument? */ - - if (varDsc->IsFloatRegType()) - continue; - - noway_assert(!varTypeIsFloating(varDsc->TypeGet())); - - /* Mark the register as holding the variable */ - - regTracker.rsTrackRegLclVar(varDsc->lvRegNum, varNum); - } - - unsigned finallyNesting = 0; - - // Make sure a set is allocated for compiler->compCurLife (in the long case), so we can set it to empty without - // allocation at the start of each basic block. - VarSetOps::AssignNoCopy(compiler, compiler->compCurLife, VarSetOps::MakeEmpty(compiler)); - - /*------------------------------------------------------------------------- - * - * Walk the basic blocks and generate code for each one - * - */ - - BasicBlock* block; - BasicBlock* lblk; /* previous block */ - - for (lblk = NULL, block = compiler->fgFirstBB; block != NULL; lblk = block, block = block->bbNext) - { -#ifdef DEBUG - if (compiler->verbose) - { - printf("\n=============== Generating "); - block->dspBlockHeader(compiler, true, true); - compiler->fgDispBBLiveness(block); - } -#endif // DEBUG - - /* Figure out which registers hold variables on entry to this block */ - - regSet.ClearMaskVars(); - gcInfo.gcRegGCrefSetCur = RBM_NONE; - gcInfo.gcRegByrefSetCur = RBM_NONE; - - compiler->m_pLinearScan->recordVarLocationsAtStartOfBB(block); - - genUpdateLife(block->bbLiveIn); - - // Even if liveness didn't change, we need to update the registers containing GC references. - // genUpdateLife will update the registers live due to liveness changes. But what about registers that didn't - // change? We cleared them out above. Maybe we should just not clear them out, but update the ones that change - // here. That would require handling the changes in recordVarLocationsAtStartOfBB(). - - regMaskTP newLiveRegSet = RBM_NONE; - regMaskTP newRegGCrefSet = RBM_NONE; - regMaskTP newRegByrefSet = RBM_NONE; -#ifdef DEBUG - VARSET_TP VARSET_INIT_NOCOPY(removedGCVars, VarSetOps::MakeEmpty(compiler)); - VARSET_TP VARSET_INIT_NOCOPY(addedGCVars, VarSetOps::MakeEmpty(compiler)); -#endif - VARSET_ITER_INIT(compiler, iter, block->bbLiveIn, varIndex); - while (iter.NextElem(compiler, &varIndex)) - { - unsigned varNum = compiler->lvaTrackedToVarNum[varIndex]; - LclVarDsc* varDsc = &(compiler->lvaTable[varNum]); - - if (varDsc->lvIsInReg()) - { - newLiveRegSet |= varDsc->lvRegMask(); - if (varDsc->lvType == TYP_REF) - { - newRegGCrefSet |= varDsc->lvRegMask(); - } - else if (varDsc->lvType == TYP_BYREF) - { - newRegByrefSet |= varDsc->lvRegMask(); - } -#ifdef DEBUG - if (verbose && VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varIndex)) - { - VarSetOps::AddElemD(compiler, removedGCVars, varIndex); - } -#endif // DEBUG - VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varIndex); - } - else if (compiler->lvaIsGCTracked(varDsc)) - { -#ifdef DEBUG - if (verbose && !VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varIndex)) - { - VarSetOps::AddElemD(compiler, addedGCVars, varIndex); - } -#endif // DEBUG - VarSetOps::AddElemD(compiler, gcInfo.gcVarPtrSetCur, varIndex); - } - } - - regSet.rsMaskVars = newLiveRegSet; - -#ifdef DEBUG - if (compiler->verbose) - { - if (!VarSetOps::IsEmpty(compiler, addedGCVars)) - { - printf("\t\t\t\t\t\t\tAdded GCVars: "); - dumpConvertedVarSet(compiler, addedGCVars); - printf("\n"); - } - if (!VarSetOps::IsEmpty(compiler, removedGCVars)) - { - printf("\t\t\t\t\t\t\tRemoved GCVars: "); - dumpConvertedVarSet(compiler, removedGCVars); - printf("\n"); - } - } -#endif // DEBUG - - gcInfo.gcMarkRegSetGCref(newRegGCrefSet DEBUGARG(true)); - gcInfo.gcMarkRegSetByref(newRegByrefSet DEBUGARG(true)); - - /* Blocks with handlerGetsXcptnObj()==true use GT_CATCH_ARG to - represent the exception object (TYP_REF). - We mark REG_EXCEPTION_OBJECT as holding a GC object on entry - to the block, it will be the first thing evaluated - (thanks to GTF_ORDER_SIDEEFF). - */ - - if (handlerGetsXcptnObj(block->bbCatchTyp)) - { - for (GenTree* node : LIR::AsRange(block)) - { - if (node->OperGet() == GT_CATCH_ARG) - { - gcInfo.gcMarkRegSetGCref(RBM_EXCEPTION_OBJECT); - break; - } - } - } - - /* Start a new code output block */ - - genUpdateCurrentFunclet(block); - -#ifdef _TARGET_XARCH_ - if (genAlignLoops && block->bbFlags & BBF_LOOP_HEAD) - { - getEmitter()->emitLoopAlign(); - } -#endif - -#ifdef DEBUG - if (compiler->opts.dspCode) - printf("\n L_M%03u_BB%02u:\n", Compiler::s_compMethodsCount, block->bbNum); -#endif - - block->bbEmitCookie = NULL; - - if (block->bbFlags & (BBF_JMP_TARGET | BBF_HAS_LABEL)) - { - /* Mark a label and update the current set of live GC refs */ - - block->bbEmitCookie = getEmitter()->emitAddLabel(gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, - gcInfo.gcRegByrefSetCur, FALSE); - } - - if (block == compiler->fgFirstColdBlock) - { -#ifdef DEBUG - if (compiler->verbose) - { - printf("\nThis is the start of the cold region of the method\n"); - } -#endif - // We should never have a block that falls through into the Cold section - noway_assert(!lblk->bbFallsThrough()); - - // We require the block that starts the Cold section to have a label - noway_assert(block->bbEmitCookie); - getEmitter()->emitSetFirstColdIGCookie(block->bbEmitCookie); - } - - /* Both stacks are always empty on entry to a basic block */ - - genStackLevel = 0; - - savedStkLvl = genStackLevel; - - /* Tell everyone which basic block we're working on */ - - compiler->compCurBB = block; - -#ifdef DEBUGGING_SUPPORT - siBeginBlock(block); - - // BBF_INTERNAL blocks don't correspond to any single IL instruction. - if (compiler->opts.compDbgInfo && (block->bbFlags & BBF_INTERNAL) && - !compiler->fgBBisScratch(block)) // If the block is the distinguished first scratch block, then no need to - // emit a NO_MAPPING entry, immediately after the prolog. - { - genIPmappingAdd((IL_OFFSETX)ICorDebugInfo::NO_MAPPING, true); - } - - bool firstMapping = true; -#endif // DEBUGGING_SUPPORT - - /*--------------------------------------------------------------------- - * - * Generate code for each statement-tree in the block - * - */ - - if (block->bbFlags & BBF_FUNCLET_BEG) - { - genReserveFuncletProlog(block); - } - - // Clear compCurStmt and compCurLifeTree. - compiler->compCurStmt = nullptr; - compiler->compCurLifeTree = nullptr; - - // Traverse the block in linear order, generating code for each node as we - // as we encounter it. - CLANG_FORMAT_COMMENT_ANCHOR; - -#ifdef DEBUGGING_SUPPORT - IL_OFFSETX currentILOffset = BAD_IL_OFFSET; -#endif - for (GenTree* node : LIR::AsRange(block).NonPhiNodes()) - { -#ifdef DEBUGGING_SUPPORT - // Do we have a new IL offset? - if (node->OperGet() == GT_IL_OFFSET) - { - genEnsureCodeEmitted(currentILOffset); - currentILOffset = node->gtStmt.gtStmtILoffsx; - genIPmappingAdd(currentILOffset, firstMapping); - firstMapping = false; - } -#endif // DEBUGGING_SUPPORT - -#ifdef DEBUG - if (node->OperGet() == GT_IL_OFFSET) - { - noway_assert(node->gtStmt.gtStmtLastILoffs <= compiler->info.compILCodeSize || - node->gtStmt.gtStmtLastILoffs == BAD_IL_OFFSET); - - if (compiler->opts.dspCode && compiler->opts.dspInstrs && - node->gtStmt.gtStmtLastILoffs != BAD_IL_OFFSET) - { - while (genCurDispOffset <= node->gtStmt.gtStmtLastILoffs) - { - genCurDispOffset += dumpSingleInstr(compiler->info.compCode, genCurDispOffset, "> "); - } - } - } -#endif // DEBUG - - genCodeForTreeNode(node); - if (node->gtHasReg() && node->gtLsraInfo.isLocalDefUse) - { - genConsumeReg(node); - } - } // end for each node in block - -#ifdef DEBUG - // The following set of register spill checks and GC pointer tracking checks used to be - // performed at statement boundaries. Now, with LIR, there are no statements, so they are - // performed at the end of each block. - // TODO: could these checks be performed more frequently? E.g., at each location where - // the register allocator says there are no live non-variable registers. Perhaps this could - // be done by (a) keeping a running count of live non-variable registers by using - // gtLsraInfo.srcCount and gtLsraInfo.dstCount to decrement and increment the count, respectively, - // and running the checks when the count is zero. Or, (b) use the map maintained by LSRA - // (operandToLocationInfoMap) to mark a node somehow when, after the execution of that node, - // there will be no live non-variable registers. - - regSet.rsSpillChk(); - - /* Make sure we didn't bungle pointer register tracking */ - - regMaskTP ptrRegs = gcInfo.gcRegGCrefSetCur | gcInfo.gcRegByrefSetCur; - regMaskTP nonVarPtrRegs = ptrRegs & ~regSet.rsMaskVars; - - // If return is a GC-type, clear it. Note that if a common - // epilog is generated (genReturnBB) it has a void return - // even though we might return a ref. We can't use the compRetType - // as the determiner because something we are tracking as a byref - // might be used as a return value of a int function (which is legal) - GenTree* blockLastNode = block->lastNode(); - if ((blockLastNode != nullptr) && (blockLastNode->gtOper == GT_RETURN) && - (varTypeIsGC(compiler->info.compRetType) || - (blockLastNode->gtOp.gtOp1 != nullptr && varTypeIsGC(blockLastNode->gtOp.gtOp1->TypeGet())))) - { - nonVarPtrRegs &= ~RBM_INTRET; - } - - if (nonVarPtrRegs) - { - printf("Regset after BB%02u gcr=", block->bbNum); - printRegMaskInt(gcInfo.gcRegGCrefSetCur & ~regSet.rsMaskVars); - compiler->getEmitter()->emitDispRegSet(gcInfo.gcRegGCrefSetCur & ~regSet.rsMaskVars); - printf(", byr="); - printRegMaskInt(gcInfo.gcRegByrefSetCur & ~regSet.rsMaskVars); - compiler->getEmitter()->emitDispRegSet(gcInfo.gcRegByrefSetCur & ~regSet.rsMaskVars); - printf(", regVars="); - printRegMaskInt(regSet.rsMaskVars); - compiler->getEmitter()->emitDispRegSet(regSet.rsMaskVars); - printf("\n"); - } - - noway_assert(nonVarPtrRegs == RBM_NONE); -#endif // DEBUG - -#if defined(DEBUG) && defined(_TARGET_ARM64_) - if (block->bbNext == nullptr) - { - // Unit testing of the ARM64 emitter: generate a bunch of instructions into the last block - // (it's as good as any, but better than the prolog, which can only be a single instruction - // group) then use COMPlus_JitLateDisasm=* to see if the late disassembler - // thinks the instructions are the same as we do. - genArm64EmitterUnitTests(); - } -#endif // defined(DEBUG) && defined(_TARGET_ARM64_) - -#ifdef DEBUGGING_SUPPORT - // It is possible to reach the end of the block without generating code for the current IL offset. - // For example, if the following IR ends the current block, no code will have been generated for - // offset 21: - // - // ( 0, 0) [000040] ------------ il_offset void IL offset: 21 - // - // N001 ( 0, 0) [000039] ------------ nop void - // - // This can lead to problems when debugging the generated code. To prevent these issues, make sure - // we've generated code for the last IL offset we saw in the block. - genEnsureCodeEmitted(currentILOffset); - - if (compiler->opts.compScopeInfo && (compiler->info.compVarScopesCount > 0)) - { - siEndBlock(block); - - /* Is this the last block, and are there any open scopes left ? */ - - bool isLastBlockProcessed = (block->bbNext == NULL); - if (block->isBBCallAlwaysPair()) - { - isLastBlockProcessed = (block->bbNext->bbNext == NULL); - } - - if (isLastBlockProcessed && siOpenScopeList.scNext) - { - /* This assert no longer holds, because we may insert a throw - block to demarcate the end of a try or finally region when they - are at the end of the method. It would be nice if we could fix - our code so that this throw block will no longer be necessary. */ - - // noway_assert(block->bbCodeOffsEnd != compiler->info.compILCodeSize); - - siCloseAllOpenScopes(); - } - } - -#endif // DEBUGGING_SUPPORT - - genStackLevel -= savedStkLvl; - -#ifdef DEBUG - // compCurLife should be equal to the liveOut set, except that we don't keep - // it up to date for vars that are not register candidates - // (it would be nice to have a xor set function) - - VARSET_TP VARSET_INIT_NOCOPY(extraLiveVars, VarSetOps::Diff(compiler, block->bbLiveOut, compiler->compCurLife)); - VarSetOps::UnionD(compiler, extraLiveVars, VarSetOps::Diff(compiler, compiler->compCurLife, block->bbLiveOut)); - VARSET_ITER_INIT(compiler, extraLiveVarIter, extraLiveVars, extraLiveVarIndex); - while (extraLiveVarIter.NextElem(compiler, &extraLiveVarIndex)) - { - unsigned varNum = compiler->lvaTrackedToVarNum[extraLiveVarIndex]; - LclVarDsc* varDsc = compiler->lvaTable + varNum; - assert(!varDsc->lvIsRegCandidate()); - } -#endif - - /* Both stacks should always be empty on exit from a basic block */ - - noway_assert(genStackLevel == 0); - -#if 0 - // On AMD64, we need to generate a NOP after a call that is the last instruction of the block, in several - // situations, to support proper exception handling semantics. This is mostly to ensure that when the stack - // walker computes an instruction pointer for a frame, that instruction pointer is in the correct EH region. - // The document "X64 and ARM ABIs.docx" has more details. The situations: - // 1. If the call instruction is in a different EH region as the instruction that follows it. - // 2. If the call immediately precedes an OS epilog. (Note that what the JIT or VM consider an epilog might - // be slightly different from what the OS considers an epilog, and it is the OS-reported epilog that matters here.) - // We handle case #1 here, and case #2 in the emitter. - if (getEmitter()->emitIsLastInsCall()) - { - // Ok, the last instruction generated is a call instruction. Do any of the other conditions hold? - // Note: we may be generating a few too many NOPs for the case of call preceding an epilog. Technically, - // if the next block is a BBJ_RETURN, an epilog will be generated, but there may be some instructions - // generated before the OS epilog starts, such as a GS cookie check. - if ((block->bbNext == nullptr) || - !BasicBlock::sameEHRegion(block, block->bbNext)) - { - // We only need the NOP if we're not going to generate any more code as part of the block end. - - switch (block->bbJumpKind) - { - case BBJ_ALWAYS: - case BBJ_THROW: - case BBJ_CALLFINALLY: - case BBJ_EHCATCHRET: - // We're going to generate more code below anyway, so no need for the NOP. - - case BBJ_RETURN: - case BBJ_EHFINALLYRET: - case BBJ_EHFILTERRET: - // These are the "epilog follows" case, handled in the emitter. - - break; - - case BBJ_NONE: - if (block->bbNext == nullptr) - { - // Call immediately before the end of the code; we should never get here . - instGen(INS_BREAKPOINT); // This should never get executed - } - else - { - // We need the NOP - instGen(INS_nop); - } - break; - - case BBJ_COND: - case BBJ_SWITCH: - // These can't have a call as the last instruction! - - default: - noway_assert(!"Unexpected bbJumpKind"); - break; - } - } - } -#endif // 0 - - /* Do we need to generate a jump or return? */ - - switch (block->bbJumpKind) - { - case BBJ_ALWAYS: - inst_JMP(EJ_jmp, block->bbJumpDest); - break; - - case BBJ_RETURN: - genExitCode(block); - break; - - case BBJ_THROW: - // If we have a throw at the end of a function or funclet, we need to emit another instruction - // afterwards to help the OS unwinder determine the correct context during unwind. - // We insert an unexecuted breakpoint instruction in several situations - // following a throw instruction: - // 1. If the throw is the last instruction of the function or funclet. This helps - // the OS unwinder determine the correct context during an unwind from the - // thrown exception. - // 2. If this is this is the last block of the hot section. - // 3. If the subsequent block is a special throw block. - // 4. On AMD64, if the next block is in a different EH region. - if ((block->bbNext == NULL) || (block->bbNext->bbFlags & BBF_FUNCLET_BEG) || - !BasicBlock::sameEHRegion(block, block->bbNext) || - (!isFramePointerUsed() && compiler->fgIsThrowHlpBlk(block->bbNext)) || - block->bbNext == compiler->fgFirstColdBlock) - { - instGen(INS_BREAKPOINT); // This should never get executed - } - - break; - - case BBJ_CALLFINALLY: - - // Generate a call to the finally, like this: - // mov x0,qword ptr [fp + 10H] // Load x0 with PSPSym - // bl finally-funclet - // b finally-return // Only for non-retless finally calls - // The 'b' can be a NOP if we're going to the next block. - - getEmitter()->emitIns_R_S(ins_Load(TYP_I_IMPL), EA_PTRSIZE, REG_R0, compiler->lvaPSPSym, 0); - getEmitter()->emitIns_J(INS_bl_local, block->bbJumpDest); - - if (block->bbFlags & BBF_RETLESS_CALL) - { - // We have a retless call, and the last instruction generated was a call. - // If the next block is in a different EH region (or is the end of the code - // block), then we need to generate a breakpoint here (since it will never - // get executed) to get proper unwind behavior. - - if ((block->bbNext == nullptr) || !BasicBlock::sameEHRegion(block, block->bbNext)) - { - instGen(INS_BREAKPOINT); // This should never get executed - } - } - else - { - // Because of the way the flowgraph is connected, the liveness info for this one instruction - // after the call is not (can not be) correct in cases where a variable has a last use in the - // handler. So turn off GC reporting for this single instruction. - getEmitter()->emitDisableGC(); - - // Now go to where the finally funclet needs to return to. - if (block->bbNext->bbJumpDest == block->bbNext->bbNext) - { - // Fall-through. - // TODO-ARM64-CQ: Can we get rid of this instruction, and just have the call return directly - // to the next instruction? This would depend on stack walking from within the finally - // handler working without this instruction being in this special EH region. - instGen(INS_nop); - } - else - { - inst_JMP(EJ_jmp, block->bbNext->bbJumpDest); - } - - getEmitter()->emitEnableGC(); - } - - // The BBJ_ALWAYS is used because the BBJ_CALLFINALLY can't point to the - // jump target using bbJumpDest - that is already used to point - // to the finally block. So just skip past the BBJ_ALWAYS unless the - // block is RETLESS. - if (!(block->bbFlags & BBF_RETLESS_CALL)) - { - assert(block->isBBCallAlwaysPair()); - - lblk = block; - block = block->bbNext; - } - break; - - case BBJ_EHCATCHRET: - // For long address (default): `adrp + add` will be emitted. - // For short address (proven later): `adr` will be emitted. - getEmitter()->emitIns_R_L(INS_adr, EA_PTRSIZE, block->bbJumpDest, REG_INTRET); - - __fallthrough; - - case BBJ_EHFINALLYRET: - case BBJ_EHFILTERRET: - genReserveFuncletEpilog(block); - break; - - case BBJ_NONE: - case BBJ_COND: - case BBJ_SWITCH: - break; - - default: - noway_assert(!"Unexpected bbJumpKind"); - break; - } - -#ifdef DEBUG - compiler->compCurBB = 0; -#endif - - } //------------------ END-FOR each block of the method ------------------- - - /* Nothing is live at this point */ - genUpdateLife(VarSetOps::MakeEmpty(compiler)); - - /* Finalize the spill tracking logic */ - - regSet.rsSpillEnd(); - - /* Finalize the temp tracking logic */ - - compiler->tmpEnd(); - -#ifdef DEBUG - if (compiler->verbose) - { - printf("\n# "); - printf("compCycleEstimate = %6d, compSizeEstimate = %5d ", compiler->compCycleEstimate, - compiler->compSizeEstimate); - printf("%s\n", compiler->info.compFullName); - } -#endif -} - -// return the child that has the same reg as the dst (if any) -// other child returned (out param) in 'other' -// TODO-Cleanup: move to CodeGenCommon.cpp -GenTree* sameRegAsDst(GenTree* tree, GenTree*& other /*out*/) +BasicBlock* CodeGen::genCallFinally(BasicBlock* block, BasicBlock* lblk) { - if (tree->gtRegNum == REG_NA) + // Generate a call to the finally, like this: + // mov x0,qword ptr [fp + 10H] / sp // Load x0 with PSPSym, or sp if PSPSym is not used + // bl finally-funclet + // b finally-return // Only for non-retless finally calls + // The 'b' can be a NOP if we're going to the next block. + + if (compiler->lvaPSPSym != BAD_VAR_NUM) { - other = nullptr; - return NULL; + getEmitter()->emitIns_R_S(ins_Load(TYP_I_IMPL), EA_PTRSIZE, REG_R0, compiler->lvaPSPSym, 0); } - - GenTreePtr op1 = tree->gtOp.gtOp1; - GenTreePtr op2 = tree->gtOp.gtOp2; - if (op1->gtRegNum == tree->gtRegNum) + else { - other = op2; - return op1; + getEmitter()->emitIns_R_R(INS_mov, EA_PTRSIZE, REG_R0, REG_SPBASE); } - if (op2->gtRegNum == tree->gtRegNum) + getEmitter()->emitIns_J(INS_bl_local, block->bbJumpDest); + + if (block->bbFlags & BBF_RETLESS_CALL) { - other = op1; - return op2; + // We have a retless call, and the last instruction generated was a call. + // If the next block is in a different EH region (or is the end of the code + // block), then we need to generate a breakpoint here (since it will never + // get executed) to get proper unwind behavior. + + if ((block->bbNext == nullptr) || !BasicBlock::sameEHRegion(block, block->bbNext)) + { + instGen(INS_BREAKPOINT); // This should never get executed + } } else { - other = nullptr; - return NULL; + // Because of the way the flowgraph is connected, the liveness info for this one instruction + // after the call is not (can not be) correct in cases where a variable has a last use in the + // handler. So turn off GC reporting for this single instruction. + getEmitter()->emitDisableGC(); + + // Now go to where the finally funclet needs to return to. + if (block->bbNext->bbJumpDest == block->bbNext->bbNext) + { + // Fall-through. + // TODO-ARM64-CQ: Can we get rid of this instruction, and just have the call return directly + // to the next instruction? This would depend on stack walking from within the finally + // handler working without this instruction being in this special EH region. + instGen(INS_nop); + } + else + { + inst_JMP(EJ_jmp, block->bbNext->bbJumpDest); + } + + getEmitter()->emitEnableGC(); + } + + // The BBJ_ALWAYS is used because the BBJ_CALLFINALLY can't point to the + // jump target using bbJumpDest - that is already used to point + // to the finally block. So just skip past the BBJ_ALWAYS unless the + // block is RETLESS. + if (!(block->bbFlags & BBF_RETLESS_CALL)) + { + assert(block->isBBCallAlwaysPair()); + + lblk = block; + block = block->bbNext; } + return block; +} + +void CodeGen::genEHCatchRet(BasicBlock* block) +{ + // For long address (default): `adrp + add` will be emitted. + // For short address (proven later): `adr` will be emitted. + getEmitter()->emitIns_R_L(INS_adr, EA_PTRSIZE, block->bbJumpDest, REG_INTRET); } // move an immediate value into an integer register @@ -3397,12 +2695,13 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) break; case GT_LIST: + case GT_FIELD_LIST: case GT_ARGPLACE: // Nothing to do break; case GT_PUTARG_STK: - genPutArgStk(treeNode); + genPutArgStk(treeNode->AsPutArgStk()); break; case GT_PUTARG_REG: @@ -3432,7 +2731,7 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) case GT_LOCKADD: case GT_XCHG: case GT_XADD: - genLockedInstructions(treeNode); + genLockedInstructions(treeNode->AsOp()); break; case GT_MEMORYBARRIER: @@ -3597,7 +2896,8 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) { #ifdef DEBUG char message[256]; - sprintf(message, "Unimplemented node type %s\n", GenTree::NodeName(treeNode->OperGet())); + _snprintf_s(message, _countof(message), _TRUNCATE, "Unimplemented node type %s\n", + GenTree::NodeName(treeNode->OperGet())); #endif assert(!"Unknown node in codegen"); } @@ -3998,9 +3298,11 @@ BAILOUT: if (endLabel != nullptr) genDefineTempLabel(endLabel); - // Write the lvaShadowSPfirst stack frame slot - noway_assert(compiler->lvaLocAllocSPvar != BAD_VAR_NUM); - getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, targetReg, compiler->lvaLocAllocSPvar, 0); + // Write the lvaLocAllocSPvar stack frame slot + if (compiler->lvaLocAllocSPvar != BAD_VAR_NUM) + { + getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, targetReg, compiler->lvaLocAllocSPvar, 0); + } #if STACK_PROBES if (compiler->opts.compNeedStackProbes) @@ -4034,6 +3336,10 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* initBlkNode) unsigned size = initBlkNode->Size(); GenTreePtr dstAddr = initBlkNode->Addr(); GenTreePtr initVal = initBlkNode->Data(); + if (initVal->OperIsInitVal()) + { + initVal = initVal->gtGetOp1(); + } assert(!dstAddr->isContained()); assert(!initVal->isContained()); @@ -4043,8 +3349,7 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* initBlkNode) emitter *emit = getEmitter(); - genConsumeReg(initVal); - genConsumeReg(dstAddr); + genConsumeOperands(initBlkNode); // If the initVal was moved, or spilled and reloaded to a different register, // get the original initVal from below the GT_RELOAD, but only after capturing the valReg, @@ -4066,27 +3371,25 @@ void CodeGen::genCodeForInitBlk(GenTreeBlk* initBlkNode) unsigned size = initBlkNode->Size(); GenTreePtr dstAddr = initBlkNode->Addr(); GenTreePtr initVal = initBlkNode->Data(); + if (initVal->OperIsInitVal()) + { + initVal = initVal->gtGetOp1(); + } assert(!dstAddr->isContained()); assert(!initVal->isContained()); assert(initBlkNode->gtRsvdRegs == RBM_ARG_2); - if (size == 0) - { - noway_assert(initBlkNode->gtOper == GT_DYN_BLK); - genConsumeRegAndCopy(initBlkNode->AsDynBlk()->gtDynamicSize, REG_ARG_2); - } - else - { // TODO-ARM64-CQ: When initblk loop unrolling is implemented // put this assert back on. #if 0 - assert(size >= INITBLK_UNROLL_LIMIT); -#endif // 0 - genSetRegToIcon(REG_ARG_2, size); + if (size != 0) + { + assert(blockSize >= INITBLK_UNROLL_LIMIT); } - genConsumeRegAndCopy(initVal, REG_ARG_1); - genConsumeRegAndCopy(dstAddr, REG_ARG_0); +#endif // 0 + + genConsumeBlockOp(initBlkNode, REG_ARG_0, REG_ARG_1, REG_ARG_2); genEmitHelperCall(CORINFO_HELP_MEMSET, 0, EA_UNKNOWN); } @@ -4238,29 +3541,38 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* cpBlkNode) // str tempReg, [R14, #8] void CodeGen::genCodeForCpObj(GenTreeObj* cpObjNode) { - // Make sure we got the arguments of the cpobj operation in the right registers - GenTreePtr dstAddr = cpObjNode->Addr(); - GenTreePtr source = cpObjNode->Data(); - noway_assert(source->gtOper == GT_IND); - GenTreePtr srcAddr = source->gtGetOp1(); + GenTreePtr dstAddr = cpObjNode->Addr(); + GenTreePtr source = cpObjNode->Data(); + var_types srcAddrType = TYP_BYREF; + bool sourceIsLocal = false; + + assert(source->isContained()); + if (source->gtOper == GT_IND) + { + GenTree* srcAddr = source->gtGetOp1(); + assert(!srcAddr->isContained()); + srcAddrType = srcAddr->TypeGet(); + } + else + { + noway_assert(source->IsLocal()); + sourceIsLocal = true; + } bool dstOnStack = dstAddr->OperIsLocalAddr(); #ifdef DEBUG assert(!dstAddr->isContained()); - assert(!srcAddr->isContained()); // This GenTree node has data about GC pointers, this means we're dealing // with CpObj. assert(cpObjNode->gtGcPtrCount > 0); #endif // DEBUG - // Consume these registers. + // Consume the operands and get them into the right registers. // They may now contain gc pointers (depending on their type; gcMarkRegPtrVal will "do the right thing"). - genConsumeRegAndCopy(srcAddr, REG_WRITE_BARRIER_SRC_BYREF); - gcInfo.gcMarkRegPtrVal(REG_WRITE_BARRIER_SRC_BYREF, srcAddr->TypeGet()); - - genConsumeRegAndCopy(dstAddr, REG_WRITE_BARRIER_DST_BYREF); + genConsumeBlockOp(cpObjNode, REG_WRITE_BARRIER_DST_BYREF, REG_WRITE_BARRIER_SRC_BYREF, REG_NA); + gcInfo.gcMarkRegPtrVal(REG_WRITE_BARRIER_SRC_BYREF, srcAddrType); gcInfo.gcMarkRegPtrVal(REG_WRITE_BARRIER_DST_BYREF, dstAddr->TypeGet()); // Temp register used to perform the sequence of loads and stores. @@ -4332,31 +3644,17 @@ void CodeGen::genCodeForCpBlk(GenTreeBlk* cpBlkNode) // Make sure we got the arguments of the cpblk operation in the right registers unsigned blockSize = cpBlkNode->Size(); GenTreePtr dstAddr = cpBlkNode->Addr(); - GenTreePtr source = cpBlkNode->Data(); - noway_assert(source->gtOper == GT_IND); - GenTreePtr srcAddr = source->gtGetOp1(); - assert(!dstAddr->isContained()); - assert(!srcAddr->isContained()); - assert(cpBlkNode->gtRsvdRegs == RBM_ARG_2); - if (blockSize != 0) - { + genConsumeBlockOp(cpBlkNode, REG_ARG_0, REG_ARG_1, REG_ARG_2); + #if 0 // Enable this when we support cpblk loop unrolling. - - assert(blockSize->gtIntCon.gtIconVal >= CPBLK_UNROLL_LIMIT); - -#endif // 0 - genSetRegToIcon(REG_ARG_2, blockSize); - } - else + if (blockSize != 0) { - noway_assert(cpBlkNode->gtOper == GT_DYN_BLK); - genConsumeRegAndCopy(cpBlkNode->AsDynBlk()->gtDynamicSize, REG_ARG_2); + assert(blockSize->gtIntCon.gtIconVal >= CPBLK_UNROLL_LIMIT); } - genConsumeRegAndCopy(srcAddr, REG_ARG_1); - genConsumeRegAndCopy(dstAddr, REG_ARG_0); +#endif // 0 genEmitHelperCall(CORINFO_HELP_MEMCPY, 0, EA_UNKNOWN); } @@ -4421,7 +3719,7 @@ void CodeGen::genJumpTable(GenTree* treeNode) // generate code for the locked operations: // GT_LOCKADD, GT_XCHG, GT_XADD -void CodeGen::genLockedInstructions(GenTree* treeNode) +void CodeGen::genLockedInstructions(GenTreeOp* treeNode) { #if 0 GenTree* data = treeNode->gtOp.gtOp2; @@ -4839,154 +4137,6 @@ void CodeGen::genCodeForShift(GenTreePtr tree) genProduceReg(tree); } -// TODO-Cleanup: move to CodeGenCommon.cpp -void CodeGen::genUnspillRegIfNeeded(GenTree* tree) -{ - regNumber dstReg = tree->gtRegNum; - - GenTree* unspillTree = tree; - if (tree->gtOper == GT_RELOAD) - { - unspillTree = tree->gtOp.gtOp1; - } - - if (unspillTree->gtFlags & GTF_SPILLED) - { - if (genIsRegCandidateLocal(unspillTree)) - { - // Reset spilled flag, since we are going to load a local variable from its home location. - unspillTree->gtFlags &= ~GTF_SPILLED; - - GenTreeLclVarCommon* lcl = unspillTree->AsLclVarCommon(); - LclVarDsc* varDsc = &compiler->lvaTable[lcl->gtLclNum]; - - var_types targetType = unspillTree->gtType; - instruction ins = ins_Load(targetType, compiler->isSIMDTypeLocalAligned(lcl->gtLclNum)); - emitAttr attr = emitTypeSize(targetType); - emitter* emit = getEmitter(); - - // Fixes Issue #3326 - attr = emit->emitInsAdjustLoadStoreAttr(ins, attr); - - // Load local variable from its home location. - inst_RV_TT(ins, dstReg, unspillTree, 0, attr); - - unspillTree->SetInReg(); - - // TODO-Review: We would like to call: - // genUpdateRegLife(varDsc, /*isBorn*/ true, /*isDying*/ false DEBUGARG(tree)); - // instead of the following code, but this ends up hitting this assert: - // assert((regSet.rsMaskVars & regMask) == 0); - // due to issues with LSRA resolution moves. - // So, just force it for now. This probably indicates a condition that creates a GC hole! - // - // Extra note: I think we really want to call something like gcInfo.gcUpdateForRegVarMove, - // because the variable is not really going live or dead, but that method is somewhat poorly - // factored because it, in turn, updates rsMaskVars which is part of RegSet not GCInfo. - // This code exists in other CodeGen*.cpp files. - - // Don't update the variable's location if we are just re-spilling it again. - - if ((unspillTree->gtFlags & GTF_SPILL) == 0) - { - genUpdateVarReg(varDsc, tree); -#ifdef DEBUG - if (VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex)) - { - JITDUMP("\t\t\t\t\t\t\tRemoving V%02u from gcVarPtrSetCur\n", lcl->gtLclNum); - } -#endif // DEBUG - VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex); - -#ifdef DEBUG - if (compiler->verbose) - { - printf("\t\t\t\t\t\t\tV%02u in reg ", lcl->gtLclNum); - varDsc->PrintVarReg(); - printf(" is becoming live "); - compiler->printTreeID(unspillTree); - printf("\n"); - } -#endif // DEBUG - - regSet.AddMaskVars(genGetRegMask(varDsc)); - } - - gcInfo.gcMarkRegPtrVal(dstReg, unspillTree->TypeGet()); - } - else if (unspillTree->IsMultiRegCall()) - { - GenTreeCall* call = unspillTree->AsCall(); - ReturnTypeDesc* pRetTypeDesc = call->GetReturnTypeDesc(); - unsigned regCount = pRetTypeDesc->GetReturnRegCount(); - GenTreeCopyOrReload* reloadTree = nullptr; - if (tree->OperGet() == GT_RELOAD) - { - reloadTree = tree->AsCopyOrReload(); - } - - // In case of multi-reg call node, GTF_SPILLED flag on it indicates that - // one or more of its result regs are spilled. Call node needs to be - // queried to know which specific result regs to be unspilled. - for (unsigned i = 0; i < regCount; ++i) - { - unsigned flags = call->GetRegSpillFlagByIdx(i); - if ((flags & GTF_SPILLED) != 0) - { - var_types dstType = pRetTypeDesc->GetReturnRegType(i); - regNumber unspillTreeReg = call->GetRegNumByIdx(i); - - if (reloadTree != nullptr) - { - dstReg = reloadTree->GetRegNumByIdx(i); - if (dstReg == REG_NA) - { - dstReg = unspillTreeReg; - } - } - else - { - dstReg = unspillTreeReg; - } - - TempDsc* t = regSet.rsUnspillInPlace(call, unspillTreeReg, i); - getEmitter()->emitIns_R_S(ins_Load(dstType), emitActualTypeSize(dstType), dstReg, t->tdTempNum(), - 0); - compiler->tmpRlsTemp(t); - gcInfo.gcMarkRegPtrVal(dstReg, dstType); - } - } - - unspillTree->gtFlags &= ~GTF_SPILLED; - unspillTree->SetInReg(); - } - else - { - TempDsc* t = regSet.rsUnspillInPlace(unspillTree, unspillTree->gtRegNum); - getEmitter()->emitIns_R_S(ins_Load(unspillTree->gtType), emitActualTypeSize(unspillTree->TypeGet()), dstReg, - t->tdTempNum(), 0); - compiler->tmpRlsTemp(t); - - unspillTree->gtFlags &= ~GTF_SPILLED; - unspillTree->SetInReg(); - gcInfo.gcMarkRegPtrVal(dstReg, unspillTree->TypeGet()); - } - } -} - -// Do Liveness update for a subnodes that is being consumed by codegen -// including the logic for reload in case is needed and also takes care -// of locating the value on the desired register. -void CodeGen::genConsumeRegAndCopy(GenTree* tree, regNumber needReg) -{ - regNumber treeReg = genConsumeReg(tree); - if (treeReg != needReg) - { - var_types targetType = tree->TypeGet(); - inst_RV_RV(ins_Copy(targetType), needReg, treeReg, targetType); - } -} - void CodeGen::genRegCopy(GenTree* treeNode) { assert(treeNode->OperGet() == GT_COPY); @@ -5049,261 +4199,6 @@ void CodeGen::genRegCopy(GenTree* treeNode) genProduceReg(treeNode); } -// Do liveness update for a subnode that is being consumed by codegen. -// TODO-Cleanup: move to CodeGenCommon.cpp -regNumber CodeGen::genConsumeReg(GenTree* tree) -{ - if (tree->OperGet() == GT_COPY) - { - genRegCopy(tree); - } - // Handle the case where we have a lclVar that needs to be copied before use (i.e. because it - // interferes with one of the other sources (or the target, if it's a "delayed use" register)). - // TODO-Cleanup: This is a special copyReg case in LSRA - consider eliminating these and - // always using GT_COPY to make the lclVar location explicit. - // Note that we have to do this before calling genUpdateLife because otherwise if we spill it - // the lvRegNum will be set to REG_STK and we will lose track of what register currently holds - // the lclVar (normally when a lclVar is spilled it is then used from its former register - // location, which matches the gtRegNum on the node). - // (Note that it doesn't matter if we call this before or after genUnspillRegIfNeeded - // because if it's on the stack it will always get reloaded into tree->gtRegNum). - if (genIsRegCandidateLocal(tree)) - { - GenTreeLclVarCommon* lcl = tree->AsLclVarCommon(); - LclVarDsc* varDsc = &compiler->lvaTable[lcl->GetLclNum()]; - if ((varDsc->lvRegNum != REG_STK) && (varDsc->lvRegNum != tree->gtRegNum)) - { - inst_RV_RV(ins_Copy(tree->TypeGet()), tree->gtRegNum, varDsc->lvRegNum); - } - } - - genUnspillRegIfNeeded(tree); - - // genUpdateLife() will also spill local var if marked as GTF_SPILL by calling CodeGen::genSpillVar - genUpdateLife(tree); - assert(tree->gtRegNum != REG_NA); - - // there are three cases where consuming a reg means clearing the bit in the live mask - // 1. it was not produced by a local - // 2. it was produced by a local that is going dead - // 3. it was produced by a local that does not live in that reg (like one allocated on the stack) - - if (genIsRegCandidateLocal(tree)) - { - GenTreeLclVarCommon* lcl = tree->AsLclVarCommon(); - LclVarDsc* varDsc = &compiler->lvaTable[lcl->GetLclNum()]; - assert(varDsc->lvLRACandidate); - - if ((tree->gtFlags & GTF_VAR_DEATH) != 0) - { - gcInfo.gcMarkRegSetNpt(genRegMask(varDsc->lvRegNum)); - } - else if (varDsc->lvRegNum == REG_STK) - { - // We have loaded this into a register only temporarily - gcInfo.gcMarkRegSetNpt(genRegMask(tree->gtRegNum)); - } - } - else - { - gcInfo.gcMarkRegSetNpt(genRegMask(tree->gtRegNum)); - } - - return tree->gtRegNum; -} - -// Do liveness update for an address tree: one of GT_LEA, GT_LCL_VAR, or GT_CNS_INT (for call indirect). -// TODO-Cleanup: move to CodeGenCommon.cpp -void CodeGen::genConsumeAddress(GenTree* addr) -{ - if (addr->OperGet() == GT_LEA) - { - genConsumeAddrMode(addr->AsAddrMode()); - } - else if (!addr->isContained()) - { - genConsumeReg(addr); - } -} - -// do liveness update for a subnode that is being consumed by codegen -// TODO-Cleanup: move to CodeGenCommon.cpp -void CodeGen::genConsumeAddrMode(GenTreeAddrMode* addr) -{ - if (addr->Base()) - genConsumeReg(addr->Base()); - if (addr->Index()) - genConsumeReg(addr->Index()); -} - -// TODO-Cleanup: move to CodeGenCommon.cpp -void CodeGen::genConsumeRegs(GenTree* tree) -{ - if (tree->isContained()) - { - if (tree->isIndir()) - { - genConsumeAddress(tree->AsIndir()->Addr()); - } - else if (tree->OperGet() == GT_AND) - { - // This is the special contained GT_AND that we created in Lowering::LowerCmp() - // Now we need to consume the operands of the GT_AND node. - genConsumeOperands(tree->AsOp()); - } - else - { - assert(tree->OperIsLeaf()); - } - } - else - { - genConsumeReg(tree); - } -} - -//------------------------------------------------------------------------ -// genConsumeOperands: Do liveness update for the operands of a unary or binary tree -// -// Arguments: -// tree - the GenTreeOp whose operands will have their liveness updated. -// -// Return Value: -// None. -// -// Notes: -// Note that this logic is localized here because we must do the liveness update in -// the correct execution order. This is important because we may have two operands -// that involve the same lclVar, and if one is marked "lastUse" we must handle it -// after the first. -// TODO-Cleanup: move to CodeGenCommon.cpp - -void CodeGen::genConsumeOperands(GenTreeOp* tree) -{ - GenTree* firstOp = tree->gtOp1; - GenTree* secondOp = tree->gtOp2; - if ((tree->gtFlags & GTF_REVERSE_OPS) != 0) - { - assert(secondOp != nullptr); - firstOp = secondOp; - secondOp = tree->gtOp1; - } - if (firstOp != nullptr) - { - genConsumeRegs(firstOp); - } - if (secondOp != nullptr) - { - genConsumeRegs(secondOp); - } -} - -// do liveness update for register produced by the current node in codegen -// TODO-Cleanup: move to CodeGenCommon.cpp -void CodeGen::genProduceReg(GenTree* tree) -{ - if (tree->gtFlags & GTF_SPILL) - { - if (genIsRegCandidateLocal(tree)) - { - // Store local variable to its home location. - tree->gtFlags &= ~GTF_REG_VAL; - inst_TT_RV(ins_Store(tree->gtType, compiler->isSIMDTypeLocalAligned(tree->gtLclVarCommon.gtLclNum)), tree, - tree->gtRegNum); - } - else - { - tree->SetInReg(); - regSet.rsSpillTree(tree->gtRegNum, tree); - tree->gtFlags |= GTF_SPILLED; - tree->gtFlags &= ~GTF_SPILL; - gcInfo.gcMarkRegSetNpt(genRegMask(tree->gtRegNum)); - return; - } - } - - genUpdateLife(tree); - - // If we've produced a register, mark it as a pointer, as needed. - if (tree->gtHasReg()) - { - // We only mark the register in the following cases: - // 1. It is not a register candidate local. In this case, we're producing a - // register from a local, but the local is not a register candidate. Thus, - // we must be loading it as a temp register, and any "last use" flag on - // the register wouldn't be relevant. - // 2. The register candidate local is going dead. There's no point to mark - // the register as live, with a GC pointer, if the variable is dead. - if (!genIsRegCandidateLocal(tree) || ((tree->gtFlags & GTF_VAR_DEATH) == 0)) - { - gcInfo.gcMarkRegPtrVal(tree->gtRegNum, tree->TypeGet()); - } - } - tree->SetInReg(); -} - -// transfer gc/byref status of src reg to dst reg -// TODO-Cleanup: move to CodeGenCommon.cpp -void CodeGen::genTransferRegGCState(regNumber dst, regNumber src) -{ - regMaskTP srcMask = genRegMask(src); - regMaskTP dstMask = genRegMask(dst); - - if (gcInfo.gcRegGCrefSetCur & srcMask) - { - gcInfo.gcMarkRegSetGCref(dstMask); - } - else if (gcInfo.gcRegByrefSetCur & srcMask) - { - gcInfo.gcMarkRegSetByref(dstMask); - } - else - { - gcInfo.gcMarkRegSetNpt(dstMask); - } -} - -// generates an ip-relative call or indirect call via reg ('call reg') -// pass in 'addr' for a relative call or 'base' for a indirect register call -// methHnd - optional, only used for pretty printing -// retSize - emitter type of return for GC purposes, should be EA_BYREF, EA_GCREF, or EA_PTRSIZE(not GC) -// TODO-Cleanup: move to CodeGenCommon.cpp -void CodeGen::genEmitCall(int callType, - CORINFO_METHOD_HANDLE methHnd, - INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) void* addr, - emitAttr retSize, - emitAttr secondRetSize, - IL_OFFSETX ilOffset, - regNumber base, - bool isJump, - bool isNoGC) -{ - - getEmitter()->emitIns_Call(emitter::EmitCallType(callType), methHnd, INDEBUG_LDISASM_COMMA(sigInfo) addr, 0, - retSize, secondRetSize, gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, - gcInfo.gcRegByrefSetCur, ilOffset, base, REG_NA, 0, 0, isJump, - emitter::emitNoGChelper(compiler->eeGetHelperNum(methHnd))); -} - -// generates an indirect call via addressing mode (call []) given an indir node -// methHnd - optional, only used for pretty printing -// retSize - emitter type of return for GC purposes, should be EA_BYREF, EA_GCREF, or EA_PTRSIZE(not GC) -// TODO-Cleanup: move to CodeGenCommon.cpp -void CodeGen::genEmitCall(int callType, - CORINFO_METHOD_HANDLE methHnd, - INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) GenTreeIndir* indir, - emitAttr retSize, - emitAttr secondRetSize, - IL_OFFSETX ilOffset) -{ - genConsumeAddress(indir->Addr()); - - getEmitter()->emitIns_Call(emitter::EmitCallType(callType), methHnd, INDEBUG_LDISASM_COMMA(sigInfo) nullptr, 0, - retSize, secondRetSize, gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, - gcInfo.gcRegByrefSetCur, ilOffset, indir->Base() ? indir->Base()->gtRegNum : REG_NA, - indir->Index() ? indir->Index()->gtRegNum : REG_NA, indir->Scale(), indir->Offset()); -} - // Produce code for a GT_CALL node void CodeGen::genCallInstruction(GenTreePtr node) { @@ -5321,7 +4216,7 @@ void CodeGen::genCallInstruction(GenTreePtr node) // Consume all the arg regs for (GenTreePtr list = call->gtCallLateArgs; list; list = list->MoveNext()) { - assert(list->IsList()); + assert(list->OperIsList()); GenTreePtr argNode = list->Current(); @@ -5332,7 +4227,7 @@ void CodeGen::genCallInstruction(GenTreePtr node) continue; // Deal with multi register passed struct args. - if (argNode->OperGet() == GT_LIST) + if (argNode->OperGet() == GT_FIELD_LIST) { GenTreeArgList* argListPtr = argNode->AsArgList(); unsigned iterationNum = 0; @@ -5457,7 +4352,6 @@ void CodeGen::genCallInstruction(GenTreePtr node) } } -#ifdef DEBUGGING_SUPPORT // We need to propagate the IL offset information to the call instruction, so we can emit // an IL to native mapping record for the call, to support managed return value debugging. // We don't want tail call helper calls that were converted from normal calls to get a record, @@ -5466,7 +4360,6 @@ void CodeGen::genCallInstruction(GenTreePtr node) { (void)compiler->genCallSite2ILOffsetMap->Lookup(call, &ilOffset); } -#endif // DEBUGGING_SUPPORT if (target != nullptr) { @@ -6703,7 +5596,7 @@ void CodeGen::genIntrinsic(GenTreePtr treeNode) // Return value: // None // -void CodeGen::genPutArgStk(GenTreePtr treeNode) +void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) { assert(treeNode->OperGet() == GT_PUTARG_STK); var_types targetType = treeNode->TypeGet(); @@ -6759,7 +5652,7 @@ void CodeGen::genPutArgStk(GenTreePtr treeNode) varNumOut = compiler->lvaOutgoingArgSpaceVar; argOffsetMax = compiler->lvaOutgoingArgSpaceSize; } - bool isStruct = (targetType == TYP_STRUCT) || (source->OperGet() == GT_LIST); + bool isStruct = (targetType == TYP_STRUCT) || (source->OperGet() == GT_FIELD_LIST); if (!isStruct) // a normal non-Struct argument { @@ -6785,24 +5678,24 @@ void CodeGen::genPutArgStk(GenTreePtr treeNode) { assert(source->isContained()); // We expect that this node was marked as contained in LowerArm64 - if (source->OperGet() == GT_LIST) + if (source->OperGet() == GT_FIELD_LIST) { // Deal with the multi register passed struct args. - GenTreeArgList* argListPtr = source->AsArgList(); + GenTreeFieldList* fieldListPtr = source->AsFieldList(); - // Evaluate each of the GT_LIST items into their register + // Evaluate each of the GT_FIELD_LIST items into their register // and store their register into the outgoing argument area - for (; argListPtr != nullptr; argListPtr = argListPtr->Rest()) + for (; fieldListPtr != nullptr; fieldListPtr = fieldListPtr->Rest()) { - GenTreePtr nextArgNode = argListPtr->gtOp.gtOp1; + GenTreePtr nextArgNode = fieldListPtr->gtOp.gtOp1; genConsumeReg(nextArgNode); regNumber reg = nextArgNode->gtRegNum; var_types type = nextArgNode->TypeGet(); emitAttr attr = emitTypeSize(type); - // Emit store instructions to store the registers produced by the GT_LIST into the outgoing argument - // area + // Emit store instructions to store the registers produced by the GT_FIELD_LIST into the outgoing + // argument area emit->emitIns_S_R(ins_Store(type), attr, reg, varNumOut, argOffsetOut); argOffsetOut += EA_SIZE_IN_BYTES(attr); assert(argOffsetOut <= argOffsetMax); // We can't write beyound the outgoing area area @@ -7159,7 +6052,6 @@ void CodeGen::genCreateAndStoreGCInfoX64(unsigned codeSize, unsigned prologSize // Now we can actually use those slot ID's to declare live ranges. gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_DO_WORK); -#if defined(DEBUGGING_SUPPORT) if (compiler->opts.compDbgEnC) { // what we have to preserve is called the "frame header" (see comments in VM\eetwain.cpp) @@ -7183,7 +6075,6 @@ void CodeGen::genCreateAndStoreGCInfoX64(unsigned codeSize, unsigned prologSize // frame gcInfoEncoder->SetSizeOfEditAndContinuePreservedArea(preservedAreaSize); } -#endif gcInfoEncoder->Build(); @@ -7249,58 +6140,6 @@ void CodeGen::genEmitHelperCall(unsigned helper, int argSize, emitAttr retSize, regTracker.rsTrashRegsForGCInterruptability(); } -/*****************************************************************************/ -#ifdef DEBUGGING_SUPPORT -/***************************************************************************** - * genSetScopeInfo - * - * Called for every scope info piece to record by the main genSetScopeInfo() - */ - -// TODO-Cleanup: move to CodeGenCommon.cpp -void CodeGen::genSetScopeInfo(unsigned which, - UNATIVE_OFFSET startOffs, - UNATIVE_OFFSET length, - unsigned varNum, - unsigned LVnum, - bool avail, - Compiler::siVarLoc& varLoc) -{ - /* We need to do some mapping while reporting back these variables */ - - unsigned ilVarNum = compiler->compMap2ILvarNum(varNum); - noway_assert((int)ilVarNum != ICorDebugInfo::UNKNOWN_ILNUM); - - VarName name = nullptr; - -#ifdef DEBUG - - for (unsigned scopeNum = 0; scopeNum < compiler->info.compVarScopesCount; scopeNum++) - { - if (LVnum == compiler->info.compVarScopes[scopeNum].vsdLVnum) - { - name = compiler->info.compVarScopes[scopeNum].vsdName; - } - } - - // Hang on to this compiler->info. - - TrnslLocalVarInfo& tlvi = genTrnslLocalVarInfo[which]; - - tlvi.tlviVarNum = ilVarNum; - tlvi.tlviLVnum = LVnum; - tlvi.tlviName = name; - tlvi.tlviStartPC = startOffs; - tlvi.tlviLength = length; - tlvi.tlviAvailable = avail; - tlvi.tlviVarLoc = varLoc; - -#endif // DEBUG - - compiler->eeSetLVinfo(which, startOffs, length, ilVarNum, LVnum, name, avail, varLoc); -} -#endif // DEBUGGING_SUPPORT - /***************************************************************************** * Unit testing of the ARM64 emitter: generate a bunch of instructions into the prolog * (it's as good a place as any), then use COMPlus_JitLateDisasm=* to see if the late diff --git a/src/jit/codegenclassic.h b/src/jit/codegenclassic.h index 81b7b34..3a88c83 100644 --- a/src/jit/codegenclassic.h +++ b/src/jit/codegenclassic.h @@ -63,10 +63,6 @@ void genPInvokeCallEpilog(LclVarDsc* varDsc, regMaskTP retVal); regNumber genLclHeap(GenTreePtr size); -void genSinglePush(); - -void genSinglePop(); - void genDyingVars(VARSET_VALARG_TP beforeSet, VARSET_VALARG_TP afterSet); bool genContainsVarDeath(GenTreePtr from, GenTreePtr to, unsigned varNum); @@ -287,9 +283,6 @@ void genCodeForJumpTable(GenTreePtr tree); void genCodeForSwitchTable(GenTreePtr tree); void genCodeForSwitch(GenTreePtr tree); -regMaskTP genPushRegs(regMaskTP regs, regMaskTP* byrefRegs, regMaskTP* noRefRegs); -void genPopRegs(regMaskTP regs, regMaskTP byrefRegs, regMaskTP noRefRegs); - size_t genPushArgList(GenTreePtr call); #ifdef _TARGET_ARM_ diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp old mode 100755 new mode 100644 index 2710447..2409115 --- a/src/jit/codegencommon.cpp +++ b/src/jit/codegencommon.cpp @@ -103,6 +103,10 @@ CodeGen::CodeGen(Compiler* theCompiler) : CodeGenInterface(theCompiler) u8ToDblBitmask = nullptr; #endif // defined(_TARGET_XARCH_) && !FEATURE_STACK_FP_X87 +#if defined(FEATURE_PUT_STRUCT_ARG_STK) && !defined(_TARGET_X86_) + m_stkArgVarNum = BAD_VAR_NUM; +#endif + regTracker.rsTrackInit(compiler, ®Set); gcInfo.regSet = ®Set; m_cgEmitter = new (compiler->getAllocator()) emitter(); @@ -163,12 +167,10 @@ CodeGen::CodeGen(Compiler* theCompiler) : CodeGenInterface(theCompiler) genFlagsEqualToNone(); #endif // LEGACY_BACKEND -#ifdef DEBUGGING_SUPPORT // Initialize the IP-mapping logic. compiler->genIPmappingList = nullptr; compiler->genIPmappingLast = nullptr; compiler->genCallSite2ILOffsetMap = nullptr; -#endif /* Assume that we not fully interruptible */ @@ -359,7 +361,7 @@ void CodeGen::genPrepForCompiler() { VarSetOps::AddElemD(compiler, compiler->raRegVarsMask, varDsc->lvVarIndex); } - else if (compiler->lvaIsGCTracked(varDsc) && (!varDsc->lvIsParam || varDsc->lvIsRegArg)) + else if (compiler->lvaIsGCTracked(varDsc)) { VarSetOps::AddElemD(compiler, gcInfo.gcTrkStkPtrLcls, varDsc->lvVarIndex); } @@ -646,23 +648,32 @@ regMaskTP Compiler::compHelperCallKillSet(CorInfoHelpFunc helper) return RBM_RSI | RBM_RDI | RBM_CALLEE_TRASH; #elif defined(_TARGET_ARM64_) return RBM_CALLEE_TRASH_NOGC; +#elif defined(_TARGET_X86_) + return RBM_ESI | RBM_EDI | RBM_ECX; #else NYI("Model kill set for CORINFO_HELP_ASSIGN_BYREF on target arch"); return RBM_CALLEE_TRASH; #endif case CORINFO_HELP_PROF_FCN_ENTER: -#ifdef _TARGET_AMD64_ +#ifdef RBM_PROFILER_ENTER_TRASH return RBM_PROFILER_ENTER_TRASH; #else - unreached(); + NYI("Model kill set for CORINFO_HELP_PROF_FCN_ENTER on target arch"); #endif + case CORINFO_HELP_PROF_FCN_LEAVE: - case CORINFO_HELP_PROF_FCN_TAILCALL: -#ifdef _TARGET_AMD64_ +#ifdef RBM_PROFILER_LEAVE_TRASH return RBM_PROFILER_LEAVE_TRASH; #else - unreached(); + NYI("Model kill set for CORINFO_HELP_PROF_FCN_LEAVE on target arch"); +#endif + + case CORINFO_HELP_PROF_FCN_TAILCALL: +#ifdef RBM_PROFILER_TAILCALL_TRASH + return RBM_PROFILER_TAILCALL_TRASH; +#else + NYI("Model kill set for CORINFO_HELP_PROF_FCN_TAILCALL on target arch"); #endif case CORINFO_HELP_STOP_FOR_GC: @@ -685,26 +696,34 @@ regMaskTP Compiler::compHelperCallKillSet(CorInfoHelpFunc helper) regMaskTP Compiler::compNoGCHelperCallKillSet(CorInfoHelpFunc helper) { assert(emitter::emitNoGChelper(helper)); -#ifdef _TARGET_AMD64_ + switch (helper) { +#if defined(_TARGET_AMD64_) || defined(_TARGET_X86_) case CORINFO_HELP_PROF_FCN_ENTER: return RBM_PROFILER_ENTER_TRASH; case CORINFO_HELP_PROF_FCN_LEAVE: - case CORINFO_HELP_PROF_FCN_TAILCALL: return RBM_PROFILER_LEAVE_TRASH; + case CORINFO_HELP_PROF_FCN_TAILCALL: + return RBM_PROFILER_TAILCALL_TRASH; +#endif // defined(_TARGET_AMD64_) || defined(_TARGET_X86_) + case CORINFO_HELP_ASSIGN_BYREF: +#if defined(_TARGET_AMD64_) // this helper doesn't trash RSI and RDI return RBM_CALLEE_TRASH_NOGC & ~(RBM_RSI | RBM_RDI); +#elif defined(_TARGET_X86_) + // This helper only trashes ECX. + return RBM_ECX; +#else + return RBM_CALLEE_TRASH_NOGC; +#endif // defined(_TARGET_AMD64_) default: return RBM_CALLEE_TRASH_NOGC; } -#else - return RBM_CALLEE_TRASH_NOGC; -#endif } // Update liveness (always var liveness, i.e., compCurLife, and also, if "ForCodeGen" is true, reg liveness, i.e., @@ -1004,9 +1023,7 @@ void Compiler::compUpdateLifeVar(GenTreePtr tree, VARSET_TP* pLastUseVars) #endif // LEGACY_BACKEND -#ifdef DEBUGGING_SUPPORT codeGen->siUpdate(); -#endif } } @@ -1172,9 +1189,7 @@ void Compiler::compChangeLife(VARSET_VALARG_TP newLife DEBUGARG(GenTreePtr tree) #endif // !LEGACY_BACKEND } -#ifdef DEBUGGING_SUPPORT codeGen->siUpdate(); -#endif } // Need an explicit instantiation. @@ -1626,6 +1641,44 @@ void CodeGen::genAdjustSP(ssize_t delta) inst_RV_IV(INS_add, REG_SPBASE, delta, EA_PTRSIZE); } +//------------------------------------------------------------------------ +// genAdjustStackLevel: Adjust the stack level, if required, for a throw helper block +// +// Arguments: +// block - The BasicBlock for which we are about to generate code. +// +// Assumptions: +// Must be called just prior to generating code for 'block'. +// +// Notes: +// This only makes an adjustment if !FEATURE_FIXED_OUT_ARGS, if there is no frame pointer, +// and if 'block' is a throw helper block with a non-zero stack level. + +void CodeGen::genAdjustStackLevel(BasicBlock* block) +{ +#if !FEATURE_FIXED_OUT_ARGS + // Check for inserted throw blocks and adjust genStackLevel. + + if (!isFramePointerUsed() && compiler->fgIsThrowHlpBlk(block)) + { + noway_assert(block->bbFlags & BBF_JMP_TARGET); + + genStackLevel = compiler->fgThrowHlpBlkStkLevel(block) * sizeof(int); + + if (genStackLevel != 0) + { +#ifdef _TARGET_X86_ + getEmitter()->emitMarkStackLvl(genStackLevel); + inst_RV_IV(INS_add, REG_SPBASE, genStackLevel, EA_PTRSIZE); + genStackLevel = 0; +#else // _TARGET_X86_ + NYI("Need emitMarkStackLvl()"); +#endif // _TARGET_X86_ + } + } +#endif // !FEATURE_FIXED_OUT_ARGS +} + #ifdef _TARGET_ARM_ // return size // alignmentWB is out param @@ -2539,14 +2592,12 @@ emitJumpKind CodeGen::genJumpKindForOper(genTreeOps cmp, CompareKind compareKind void CodeGen::genExitCode(BasicBlock* block) { -#ifdef DEBUGGING_SUPPORT /* Just wrote the first instruction of the epilog - inform debugger Note that this may result in a duplicate IPmapping entry, and that this is ok */ // For non-optimized debuggable code, there is only one epilog. genIPmappingAdd((IL_OFFSETX)ICorDebugInfo::EPILOG, true); -#endif // DEBUGGING_SUPPORT bool jmpEpilog = ((block->bbFlags & BBF_HAS_JMP) != 0); if (compiler->getNeedsGSSecurityCookie()) @@ -2968,7 +3019,7 @@ void CodeGen::genGenerateCode(void** codePtr, ULONG* nativeSizeOfCode) #if defined(DEBUG) , (compiler->compCodeOpt() != Compiler::SMALL_CODE) && - !(compiler->opts.eeFlags & CORJIT_FLG_PREJIT) + !compiler->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT) #endif #ifdef LEGACY_BACKEND , @@ -3095,7 +3146,8 @@ void CodeGen::genGenerateCode(void** codePtr, ULONG* nativeSizeOfCode) We need to relax the assert as our estimation won't include code-gen stack changes (which we know don't affect fgAddCodeRef()) */ noway_assert(getEmitter()->emitMaxStackDepth <= - (compiler->fgPtrArgCntMax + compiler->compHndBBtabCount + // Return address for locally-called finallys + (compiler->fgPtrArgCntMax + // Max number of pointer-sized stack arguments. + compiler->compHndBBtabCount + // Return address for locally-called finallys genTypeStSz(TYP_LONG) + // longs/doubles may be transferred via stack, etc (compiler->compTailCallUsed ? 4 : 0))); // CORINFO_HELP_TAILCALL args #endif @@ -3116,8 +3168,6 @@ void CodeGen::genGenerateCode(void** codePtr, ULONG* nativeSizeOfCode) compiler->unwindEmit(*codePtr, coldCodePtr); -#ifdef DEBUGGING_SUPPORT - /* Finalize the line # tracking logic after we know the exact block sizes/offsets */ genIPmappingGen(); @@ -3126,8 +3176,6 @@ void CodeGen::genGenerateCode(void** codePtr, ULONG* nativeSizeOfCode) genSetScopeInfo(); -#endif // DEBUGGING_SUPPORT - #ifdef LATE_DISASM unsigned finalHotCodeSize; unsigned finalColdCodeSize; @@ -3272,6 +3320,8 @@ void CodeGen::genReportEH() EHblkDsc* HBtab; EHblkDsc* HBtabEnd; + bool isCoreRTABI = compiler->IsTargetAbi(CORINFO_CORERT_ABI); + unsigned EHCount = compiler->compHndBBtabCount; #if FEATURE_EH_FUNCLETS @@ -3279,46 +3329,55 @@ void CodeGen::genReportEH() // VM. unsigned duplicateClauseCount = 0; unsigned enclosingTryIndex; - for (XTnum = 0; XTnum < compiler->compHndBBtabCount; XTnum++) + + // Duplicate clauses are not used by CoreRT ABI + if (!isCoreRTABI) { - for (enclosingTryIndex = compiler->ehTrueEnclosingTryIndexIL(XTnum); // find the true enclosing try index, - // ignoring 'mutual protect' trys - enclosingTryIndex != EHblkDsc::NO_ENCLOSING_INDEX; - enclosingTryIndex = compiler->ehGetEnclosingTryIndex(enclosingTryIndex)) + for (XTnum = 0; XTnum < compiler->compHndBBtabCount; XTnum++) { - ++duplicateClauseCount; + for (enclosingTryIndex = compiler->ehTrueEnclosingTryIndexIL(XTnum); // find the true enclosing try index, + // ignoring 'mutual protect' trys + enclosingTryIndex != EHblkDsc::NO_ENCLOSING_INDEX; + enclosingTryIndex = compiler->ehGetEnclosingTryIndex(enclosingTryIndex)) + { + ++duplicateClauseCount; + } } + EHCount += duplicateClauseCount; } - EHCount += duplicateClauseCount; #if FEATURE_EH_CALLFINALLY_THUNKS unsigned clonedFinallyCount = 0; - // We don't keep track of how many cloned finally there are. So, go through and count. - // We do a quick pass first through the EH table to see if there are any try/finally - // clauses. If there aren't, we don't need to look for BBJ_CALLFINALLY. - - bool anyFinallys = false; - for (HBtab = compiler->compHndBBtab, HBtabEnd = compiler->compHndBBtab + compiler->compHndBBtabCount; - HBtab < HBtabEnd; HBtab++) + // Duplicate clauses are not used by CoreRT ABI + if (!isCoreRTABI) { - if (HBtab->HasFinallyHandler()) + // We don't keep track of how many cloned finally there are. So, go through and count. + // We do a quick pass first through the EH table to see if there are any try/finally + // clauses. If there aren't, we don't need to look for BBJ_CALLFINALLY. + + bool anyFinallys = false; + for (HBtab = compiler->compHndBBtab, HBtabEnd = compiler->compHndBBtab + compiler->compHndBBtabCount; + HBtab < HBtabEnd; HBtab++) { - anyFinallys = true; - break; + if (HBtab->HasFinallyHandler()) + { + anyFinallys = true; + break; + } } - } - if (anyFinallys) - { - for (BasicBlock* block = compiler->fgFirstBB; block != nullptr; block = block->bbNext) + if (anyFinallys) { - if (block->bbJumpKind == BBJ_CALLFINALLY) + for (BasicBlock* block = compiler->fgFirstBB; block != nullptr; block = block->bbNext) { - ++clonedFinallyCount; + if (block->bbJumpKind == BBJ_CALLFINALLY) + { + ++clonedFinallyCount; + } } - } - EHCount += clonedFinallyCount; + EHCount += clonedFinallyCount; + } } #endif // FEATURE_EH_CALLFINALLY_THUNKS @@ -3373,6 +3432,23 @@ void CodeGen::genReportEH() CORINFO_EH_CLAUSE_FLAGS flags = ToCORINFO_EH_CLAUSE_FLAGS(HBtab->ebdHandlerType); + if (isCoreRTABI && (XTnum > 0)) + { + // For CoreRT, CORINFO_EH_CLAUSE_SAMETRY flag means that the current clause covers same + // try block as the previous one. The runtime cannot reliably infer this information from + // native code offsets because of different try blocks can have same offsets. Alternative + // solution to this problem would be inserting extra nops to ensure that different try + // blocks have different offsets. + if (EHblkDsc::ebdIsSameTry(HBtab, HBtab - 1)) + { + // The SAMETRY bit should only be set on catch clauses. This is ensured in IL, where only 'catch' is + // allowed to be mutually-protect. E.g., the C# "try {} catch {} catch {} finally {}" actually exists in + // IL as "try { try {} catch {} catch {} } finally {}". + assert(HBtab->HasCatchHandler()); + flags = (CORINFO_EH_CLAUSE_FLAGS)(flags | CORINFO_EH_CLAUSE_SAMETRY); + } + } + // Note that we reuse the CORINFO_EH_CLAUSE type, even though the names of // the fields aren't accurate. @@ -3578,9 +3654,7 @@ void CodeGen::genReportEH() CORINFO_EH_CLAUSE_FLAGS flags = ToCORINFO_EH_CLAUSE_FLAGS(encTab->ebdHandlerType); // Tell the VM this is an extra clause caused by moving funclets out of line. - // It seems weird this is from the CorExceptionFlag enum in corhdr.h, - // not the CORINFO_EH_CLAUSE_FLAGS enum in corinfo.h. - flags = (CORINFO_EH_CLAUSE_FLAGS)(flags | COR_ILEXCEPTION_CLAUSE_DUPLICATED); + flags = (CORINFO_EH_CLAUSE_FLAGS)(flags | CORINFO_EH_CLAUSE_DUPLICATE); // Note that the JIT-EE interface reuses the CORINFO_EH_CLAUSE type, even though the names of // the fields aren't really accurate. For example, we set "TryLength" to the offset of the @@ -3617,7 +3691,7 @@ void CodeGen::genReportEH() } // if (duplicateClauseCount > 0) #if FEATURE_EH_CALLFINALLY_THUNKS - if (anyFinallys) + if (clonedFinallyCount > 0) { unsigned reportedClonedFinallyCount = 0; for (BasicBlock* block = compiler->fgFirstBB; block != nullptr; block = block->bbNext) @@ -3647,9 +3721,9 @@ void CodeGen::genReportEH() CORINFO_EH_CLAUSE clause; clause.ClassToken = 0; // unused - clause.Flags = (CORINFO_EH_CLAUSE_FLAGS)(CORINFO_EH_CLAUSE_FINALLY | COR_ILEXCEPTION_CLAUSE_DUPLICATED); - clause.TryOffset = hndBeg; - clause.TryLength = hndBeg; + clause.Flags = (CORINFO_EH_CLAUSE_FLAGS)(CORINFO_EH_CLAUSE_FINALLY | CORINFO_EH_CLAUSE_DUPLICATE); + clause.TryOffset = hndBeg; + clause.TryLength = hndBeg; clause.HandlerOffset = hndBeg; clause.HandlerLength = hndEnd; @@ -3671,7 +3745,7 @@ void CodeGen::genReportEH() } // for each block assert(clonedFinallyCount == reportedClonedFinallyCount); - } // if (anyFinallys) + } // if (clonedFinallyCount > 0) #endif // FEATURE_EH_CALLFINALLY_THUNKS #endif // FEATURE_EH_FUNCLETS @@ -6995,12 +7069,12 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, noway_assert(varTypeIsGC(varDsc->TypeGet()) || (varDsc->TypeGet() == TYP_STRUCT) || compiler->info.compInitMem || compiler->opts.compDbgCode); -#ifdef _TARGET_64BIT_ +#ifndef LEGACY_BACKEND if (!varDsc->lvOnFrame) { continue; } -#else // !_TARGET_64BIT_ +#else // LEGACY_BACKEND if (varDsc->lvRegister) { if (varDsc->lvOnFrame) @@ -7016,7 +7090,7 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, } continue; } -#endif // !_TARGET_64BIT_ +#endif // LEGACY_BACKEND if ((varDsc->TypeGet() == TYP_STRUCT) && !compiler->info.compInitMem && (varDsc->lvExactSize >= TARGET_POINTER_SIZE)) @@ -7221,11 +7295,31 @@ void CodeGen::genSetGSSecurityCookie(regNumber initReg, bool* pInitRegZeroed) #ifdef PROFILING_SUPPORTED -/*----------------------------------------------------------------------------- - * - * Generate the profiling function enter callback. - */ - +//----------------------------------------------------------------------------------- +// genProfilingEnterCallback: Generate the profiling function enter callback. +// +// Arguments: +// initReg - register to use as scratch register +// pInitRegZeroed - OUT parameter. *pInitRegZeroed set to 'false' if 'initReg' is +// not zero after this call. +// +// Return Value: +// None +// +// Notes: +// The x86 profile enter helper has the following requirements (see ProfileEnterNaked in +// VM\i386\asmhelpers.asm for details): +// 1. The calling sequence for calling the helper is: +// push FunctionIDOrClientID +// call ProfileEnterHelper +// 2. The calling function has an EBP frame. +// 3. EBP points to the saved ESP which is the first thing saved in the function. Thus, +// the following prolog is assumed: +// push ESP +// mov EBP, ESP +// 4. All registers are preserved. +// 5. The helper pops the FunctionIDOrClientID argument from the stack. +// void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed) { assert(compiler->compGeneratingProlog); @@ -7236,7 +7330,6 @@ void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed) return; } -#ifndef LEGACY_BACKEND #if defined(_TARGET_AMD64_) && !defined(UNIX_AMD64_ABI) // No profiling for System V systems yet. unsigned varNum; LclVarDsc* varDsc; @@ -7280,7 +7373,7 @@ void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed) else { // No need to record relocations, if we are generating ELT hooks under the influence - // of complus_JitELtHookEnabled=1 + // of COMPlus_JitELTHookEnabled=1 if (compiler->opts.compJitELTHookEnabled) { genSetRegToIcon(REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd, TYP_I_IMPL); @@ -7346,11 +7439,7 @@ void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed) *pInitRegZeroed = false; } -#else //!_TARGET_AMD64_ - NYI("RyuJIT: Emit Profiler Enter callback"); -#endif - -#else // LEGACY_BACKEND +#elif defined(_TARGET_X86_) || (defined(_TARGET_ARM_) && defined(LEGACY_BACKEND)) unsigned saveStackLvl2 = genStackLevel; @@ -7423,17 +7512,41 @@ void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed) /* Restore the stack level */ genStackLevel = saveStackLvl2; -#endif // LEGACY_BACKEND -} -/***************************************************************************** - * - * Generates Leave profiler hook. - * Technically, this is not part of the epilog; it is called when we are generating code for a GT_RETURN node. - */ +#else // target + NYI("Emit Profiler Enter callback"); +#endif // target +} +//----------------------------------------------------------------------------------- +// genProfilingLeaveCallback: Generate the profiling function leave or tailcall callback. +// Technically, this is not part of the epilog; it is called when we are generating code for a GT_RETURN node. +// +// Arguments: +// helper - which helper to call. Either CORINFO_HELP_PROF_FCN_LEAVE or CORINFO_HELP_PROF_FCN_TAILCALL +// +// Return Value: +// None +// +// Notes: +// The x86 profile leave/tailcall helper has the following requirements (see ProfileLeaveNaked and +// ProfileTailcallNaked in VM\i386\asmhelpers.asm for details): +// 1. The calling sequence for calling the helper is: +// push FunctionIDOrClientID +// call ProfileLeaveHelper or ProfileTailcallHelper +// 2. The calling function has an EBP frame. +// 3. EBP points to the saved ESP which is the first thing saved in the function. Thus, +// the following prolog is assumed: +// push ESP +// mov EBP, ESP +// 4. helper == CORINFO_HELP_PROF_FCN_LEAVE: All registers are preserved. +// helper == CORINFO_HELP_PROF_FCN_TAILCALL: Only argument registers are preserved. +// 5. The helper pops the FunctionIDOrClientID argument from the stack. +// void CodeGen::genProfilingLeaveCallback(unsigned helper /*= CORINFO_HELP_PROF_FCN_LEAVE*/) { + assert((helper == CORINFO_HELP_PROF_FCN_LEAVE) || (helper == CORINFO_HELP_PROF_FCN_TAILCALL)); + // Only hook if profiler says it's okay. if (!compiler->compIsProfilerHookNeeded()) { @@ -7442,12 +7555,11 @@ void CodeGen::genProfilingLeaveCallback(unsigned helper /*= CORINFO_HELP_PROF_FC compiler->info.compProfilerCallback = true; - // Need to save on to the stack level, since the callee will pop the argument + // Need to save on to the stack level, since the helper call will pop the argument unsigned saveStackLvl2 = genStackLevel; -#ifndef LEGACY_BACKEND - #if defined(_TARGET_AMD64_) && !defined(UNIX_AMD64_ABI) // No profiling for System V systems yet. + // Since the method needs to make a profiler callback, it should have out-going arg space allocated. noway_assert(compiler->lvaOutgoingArgSpaceVar != BAD_VAR_NUM); noway_assert(compiler->lvaOutgoingArgSpaceSize >= (4 * REGSIZE_BYTES)); @@ -7477,7 +7589,7 @@ void CodeGen::genProfilingLeaveCallback(unsigned helper /*= CORINFO_HELP_PROF_FC else { // Don't record relocations, if we are generating ELT hooks under the influence - // of complus_JitELtHookEnabled=1 + // of COMPlus_JitELTHookEnabled=1 if (compiler->opts.compJitELTHookEnabled) { genSetRegToIcon(REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd, TYP_I_IMPL); @@ -7517,13 +7629,8 @@ void CodeGen::genProfilingLeaveCallback(unsigned helper /*= CORINFO_HELP_PROF_FC // "mov r8, helper addr; call r8" genEmitHelperCall(helper, 0, EA_UNKNOWN, REG_ARG_2); -#else //!_TARGET_AMD64_ - NYI("RyuJIT: Emit Profiler Leave callback"); -#endif // _TARGET_* - -#else // LEGACY_BACKEND +#elif defined(_TARGET_X86_) -#if defined(_TARGET_X86_) // // Push the profilerHandle // @@ -7538,7 +7645,7 @@ void CodeGen::genProfilingLeaveCallback(unsigned helper /*= CORINFO_HELP_PROF_FC } genSinglePush(); - genEmitHelperCall(CORINFO_HELP_PROF_FCN_LEAVE, + genEmitHelperCall(helper, sizeof(int) * 1, // argSize EA_UNKNOWN); // retSize @@ -7549,7 +7656,9 @@ void CodeGen::genProfilingLeaveCallback(unsigned helper /*= CORINFO_HELP_PROF_FC { compiler->fgPtrArgCntMax = 1; } -#elif defined(_TARGET_ARM_) + +#elif defined(LEGACY_BACKEND) && defined(_TARGET_ARM_) + // // Push the profilerHandle // @@ -7571,9 +7680,9 @@ void CodeGen::genProfilingLeaveCallback(unsigned helper /*= CORINFO_HELP_PROF_FC bool r0Trashed; emitAttr attr = EA_UNKNOWN; - if (compiler->info.compRetType == TYP_VOID || - (!compiler->info.compIsVarArgs && !compiler->opts.compUseSoftFP && (varTypeIsFloating(compiler->info.compRetType) || - compiler->IsHfa(compiler->info.compMethodInfo->args.retTypeClass)))) + if (compiler->info.compRetType == TYP_VOID || (!compiler->info.compIsVarArgs && !compiler->opts.compUseSoftFP && + (varTypeIsFloating(compiler->info.compRetType) || + compiler->IsHfa(compiler->info.compMethodInfo->args.retTypeClass)))) { r0Trashed = false; } @@ -7625,11 +7734,10 @@ void CodeGen::genProfilingLeaveCallback(unsigned helper /*= CORINFO_HELP_PROF_FC } regSet.rsUnlockReg(RBM_PROFILER_RET_USED); -#else // _TARGET_* - NYI("Pushing the profilerHandle & caller's sp for the profiler callout and locking them"); -#endif // _TARGET_* -#endif // LEGACY_BACKEND +#else // target + NYI("Emit Profiler Leave callback"); +#endif // target /* Restore the stack level */ genStackLevel = saveStackLvl2; @@ -7741,7 +7849,7 @@ void CodeGen::genPrologPadForReJit() assert(compiler->compGeneratingProlog); #ifdef _TARGET_XARCH_ - if (!(compiler->opts.eeFlags & CORJIT_FLG_PROF_REJIT_NOPS)) + if (!compiler->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PROF_REJIT_NOPS)) { return; } @@ -8165,11 +8273,9 @@ void CodeGen::genFnProlog() getEmitter()->emitBegProlog(); compiler->unwindBegProlog(); -#ifdef DEBUGGING_SUPPORT // Do this so we can put the prolog instruction group ahead of // other instruction groups genIPmappingAddToFront((IL_OFFSETX)ICorDebugInfo::PROLOG); -#endif // DEBUGGING_SUPPORT #ifdef DEBUG if (compiler->opts.dspCode) @@ -8178,13 +8284,11 @@ void CodeGen::genFnProlog() } #endif -#ifdef DEBUGGING_SUPPORT if (compiler->opts.compScopeInfo && (compiler->info.compVarScopesCount > 0)) { // Create new scopes for the method-parameters for the prolog-block. psiBegProlog(); } -#endif #ifdef DEBUG @@ -8664,12 +8768,6 @@ void CodeGen::genFnProlog() // when compInitMem is true the genZeroInitFrame will zero out the shadow SP slots if (compiler->ehNeedsShadowSPslots() && !compiler->info.compInitMem) { - /* - // size/speed option? - getEmitter()->emitIns_I_ARR(INS_mov, EA_PTRSIZE, 0, - REG_EBP, REG_NA, -compiler->lvaShadowSPfirstOffs); - */ - // The last slot is reserved for ICodeManager::FixContext(ppEndRegion) unsigned filterEndOffsetSlotOffs = compiler->lvaLclSize(compiler->lvaShadowSPslotsVar) - (sizeof(void*)); @@ -8707,9 +8805,8 @@ void CodeGen::genFnProlog() // Initialize any "hidden" slots/locals - if (compiler->compLocallocUsed) + if (compiler->lvaLocAllocSPvar != BAD_VAR_NUM) { - noway_assert(compiler->lvaLocAllocSPvar != BAD_VAR_NUM); #ifdef _TARGET_ARM64_ getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_FPBASE, compiler->lvaLocAllocSPvar, 0); #else @@ -8870,12 +8967,10 @@ void CodeGen::genFnProlog() getEmitter()->emitMarkPrologEnd(); } -#ifdef DEBUGGING_SUPPORT if (compiler->opts.compScopeInfo && (compiler->info.compVarScopesCount > 0)) { psiEndProlog(); } -#endif if (hasGCRef) { @@ -8927,7 +9022,7 @@ void CodeGen::genFnProlog() // LEA EAX, & + EAX getEmitter()->emitIns_R_ARR(INS_lea, EA_PTRSIZE, REG_EAX, genFramePointerReg(), REG_EAX, offset); - if (varDsc->lvRegister) + if (varDsc->lvIsInReg()) { if (varDsc->lvRegNum != REG_EAX) { @@ -9637,7 +9732,7 @@ void CodeGen::genFnEpilog(BasicBlock* block) * |Pre-spill regs space | // This is only necessary to keep the PSP slot at the same offset * | | // in function and funclet * |-----------------------| - * | PSP slot | + * | PSP slot | // Omitted in CoreRT ABI * |-----------------------| * ~ possible 4 byte pad ~ * ~ for alignment ~ @@ -9936,7 +10031,7 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() * ~ possible 8 byte pad ~ * ~ for alignment ~ * |-----------------------| - * | PSP slot | + * | PSP slot | // Omitted in CoreRT ABI * |-----------------------| * | Outgoing arg space | // this only exists if the function makes a call * |-----------------------| <---- Initial SP @@ -10007,6 +10102,12 @@ void CodeGen::genFuncletProlog(BasicBlock* block) // This is the end of the OS-reported prolog for purposes of unwinding compiler->unwindEndProlog(); + // If there is no PSPSym (CoreRT ABI), we are done. + if (compiler->lvaPSPSym == BAD_VAR_NUM) + { + return; + } + getEmitter()->emitIns_R_AR(INS_mov, EA_PTRSIZE, REG_FPBASE, REG_ARG_0, genFuncletInfo.fiPSP_slot_InitialSP_offset); regTracker.rsTrackRegTrash(REG_FPBASE); @@ -10100,10 +10201,12 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() unsigned calleeFPRegsSavedSize = genCountBits(compiler->compCalleeFPRegsSavedMask) * XMM_REGSIZE_BYTES; unsigned FPRegsPad = (calleeFPRegsSavedSize > 0) ? AlignmentPad(totalFrameSize, XMM_REGSIZE_BYTES) : 0; + unsigned PSPSymSize = (compiler->lvaPSPSym != BAD_VAR_NUM) ? REGSIZE_BYTES : 0; + totalFrameSize += FPRegsPad // Padding before pushing entire xmm regs + calleeFPRegsSavedSize // pushed callee-saved float regs // below calculated 'pad' will go here - + REGSIZE_BYTES // PSPSym + + PSPSymSize // PSPSym + compiler->lvaOutgoingArgSpaceSize // outgoing arg space ; @@ -10111,7 +10214,7 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() genFuncletInfo.fiSpDelta = FPRegsPad // Padding to align SP on XMM_REGSIZE_BYTES boundary + calleeFPRegsSavedSize // Callee saved xmm regs - + pad + REGSIZE_BYTES // PSPSym + + pad + PSPSymSize // PSPSym + compiler->lvaOutgoingArgSpaceSize // outgoing arg space ; @@ -10124,12 +10227,14 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() printf(" SP delta: %d\n", genFuncletInfo.fiSpDelta); printf(" PSP slot Initial SP offset: %d\n", genFuncletInfo.fiPSP_slot_InitialSP_offset); } -#endif // DEBUG - assert(compiler->lvaPSPSym != BAD_VAR_NUM); - assert(genFuncletInfo.fiPSP_slot_InitialSP_offset == - compiler->lvaGetInitialSPRelativeOffset(compiler->lvaPSPSym)); // same offset used in main function and - // funclet! + if (compiler->lvaPSPSym != BAD_VAR_NUM) + { + assert(genFuncletInfo.fiPSP_slot_InitialSP_offset == + compiler->lvaGetInitialSPRelativeOffset(compiler->lvaPSPSym)); // same offset used in main function and + // funclet! + } +#endif // DEBUG } #elif defined(_TARGET_ARM64_) @@ -10249,13 +10354,12 @@ void CodeGen::genSetPSPSym(regNumber initReg, bool* pInitRegZeroed) { assert(compiler->compGeneratingProlog); - if (!compiler->ehNeedsPSPSym()) + if (compiler->lvaPSPSym == BAD_VAR_NUM) { return; } - noway_assert(isFramePointerUsed()); // We need an explicit frame pointer - assert(compiler->lvaPSPSym != BAD_VAR_NUM); // We should have created the PSPSym variable + noway_assert(isFramePointerUsed()); // We need an explicit frame pointer #if defined(_TARGET_ARM_) @@ -10851,8 +10955,162 @@ unsigned CodeGen::getFirstArgWithStackSlot() #endif // !LEGACY_BACKEND && (_TARGET_XARCH_ || _TARGET_ARM64_) -/*****************************************************************************/ -#ifdef DEBUGGING_SUPPORT +//------------------------------------------------------------------------ +// genSinglePush: Report a change in stack level caused by a single word-sized push instruction +// +void CodeGen::genSinglePush() +{ + genStackLevel += sizeof(void*); +} + +//------------------------------------------------------------------------ +// genSinglePop: Report a change in stack level caused by a single word-sized pop instruction +// +void CodeGen::genSinglePop() +{ + genStackLevel -= sizeof(void*); +} + +//------------------------------------------------------------------------ +// genPushRegs: Push the given registers. +// +// Arguments: +// regs - mask or registers to push +// byrefRegs - OUT arg. Set to byref registers that were pushed. +// noRefRegs - OUT arg. Set to non-GC ref registers that were pushed. +// +// Return Value: +// Mask of registers pushed. +// +// Notes: +// This function does not check if the register is marked as used, etc. +// +regMaskTP CodeGen::genPushRegs(regMaskTP regs, regMaskTP* byrefRegs, regMaskTP* noRefRegs) +{ + *byrefRegs = RBM_NONE; + *noRefRegs = RBM_NONE; + + if (regs == RBM_NONE) + { + return RBM_NONE; + } + +#if FEATURE_FIXED_OUT_ARGS + + NYI("Don't call genPushRegs with real regs!"); + return RBM_NONE; + +#else // FEATURE_FIXED_OUT_ARGS + + noway_assert(genTypeStSz(TYP_REF) == genTypeStSz(TYP_I_IMPL)); + noway_assert(genTypeStSz(TYP_BYREF) == genTypeStSz(TYP_I_IMPL)); + + regMaskTP pushedRegs = regs; + + for (regNumber reg = REG_INT_FIRST; regs != RBM_NONE; reg = REG_NEXT(reg)) + { + regMaskTP regBit = regMaskTP(1) << reg; + + if ((regBit & regs) == RBM_NONE) + continue; + + var_types type; + if (regBit & gcInfo.gcRegGCrefSetCur) + { + type = TYP_REF; + } + else if (regBit & gcInfo.gcRegByrefSetCur) + { + *byrefRegs |= regBit; + type = TYP_BYREF; + } + else if (noRefRegs != NULL) + { + *noRefRegs |= regBit; + type = TYP_I_IMPL; + } + else + { + continue; + } + + inst_RV(INS_push, reg, type); + + genSinglePush(); + gcInfo.gcMarkRegSetNpt(regBit); + + regs &= ~regBit; + } + + return pushedRegs; + +#endif // FEATURE_FIXED_OUT_ARGS +} + +//------------------------------------------------------------------------ +// genPopRegs: Pop the registers that were pushed by genPushRegs(). +// +// Arguments: +// regs - mask of registers to pop +// byrefRegs - The byref registers that were pushed by genPushRegs(). +// noRefRegs - The non-GC ref registers that were pushed by genPushRegs(). +// +// Return Value: +// None +// +void CodeGen::genPopRegs(regMaskTP regs, regMaskTP byrefRegs, regMaskTP noRefRegs) +{ + if (regs == RBM_NONE) + { + return; + } + +#if FEATURE_FIXED_OUT_ARGS + + NYI("Don't call genPopRegs with real regs!"); + +#else // FEATURE_FIXED_OUT_ARGS + + noway_assert((regs & byrefRegs) == byrefRegs); + noway_assert((regs & noRefRegs) == noRefRegs); + noway_assert((regs & (gcInfo.gcRegGCrefSetCur | gcInfo.gcRegByrefSetCur)) == RBM_NONE); + + noway_assert(genTypeStSz(TYP_REF) == genTypeStSz(TYP_INT)); + noway_assert(genTypeStSz(TYP_BYREF) == genTypeStSz(TYP_INT)); + + // Walk the registers in the reverse order as genPushRegs() + for (regNumber reg = REG_INT_LAST; regs != RBM_NONE; reg = REG_PREV(reg)) + { + regMaskTP regBit = regMaskTP(1) << reg; + + if ((regBit & regs) == RBM_NONE) + continue; + + var_types type; + if (regBit & byrefRegs) + { + type = TYP_BYREF; + } + else if (regBit & noRefRegs) + { + type = TYP_INT; + } + else + { + type = TYP_REF; + } + + inst_RV(INS_pop, reg, type); + genSinglePop(); + + if (type != TYP_INT) + gcInfo.gcMarkRegPtrVal(reg, type); + + regs &= ~regBit; + } + +#endif // FEATURE_FIXED_OUT_ARGS +} /***************************************************************************** * genSetScopeInfo @@ -11151,6 +11409,103 @@ void CodeGen::genSetScopeInfo() compiler->eeSetLVdone(); } +//------------------------------------------------------------------------ +// genSetScopeInfo: Record scope information for debug info +// +// Arguments: +// which +// startOffs - the starting offset for this scope +// length - the length of this scope +// varNum - the lclVar for this scope info +// LVnum +// avail +// varLoc +// +// Notes: +// Called for every scope info piece to record by the main genSetScopeInfo() + +void CodeGen::genSetScopeInfo(unsigned which, + UNATIVE_OFFSET startOffs, + UNATIVE_OFFSET length, + unsigned varNum, + unsigned LVnum, + bool avail, + Compiler::siVarLoc& varLoc) +{ + // We need to do some mapping while reporting back these variables. + + unsigned ilVarNum = compiler->compMap2ILvarNum(varNum); + noway_assert((int)ilVarNum != ICorDebugInfo::UNKNOWN_ILNUM); + +#ifdef _TARGET_X86_ + // Non-x86 platforms are allowed to access all arguments directly + // so we don't need this code. + + // Is this a varargs function? + + if (compiler->info.compIsVarArgs && varNum != compiler->lvaVarargsHandleArg && + varNum < compiler->info.compArgsCount && !compiler->lvaTable[varNum].lvIsRegArg) + { + noway_assert(varLoc.vlType == Compiler::VLT_STK || varLoc.vlType == Compiler::VLT_STK2); + + // All stack arguments (except the varargs handle) have to be + // accessed via the varargs cookie. Discard generated info, + // and just find its position relative to the varargs handle + + PREFIX_ASSUME(compiler->lvaVarargsHandleArg < compiler->info.compArgsCount); + if (!compiler->lvaTable[compiler->lvaVarargsHandleArg].lvOnFrame) + { + noway_assert(!compiler->opts.compDbgCode); + return; + } + + // Can't check compiler->lvaTable[varNum].lvOnFrame as we don't set it for + // arguments of vararg functions to avoid reporting them to GC. + noway_assert(!compiler->lvaTable[varNum].lvRegister); + unsigned cookieOffset = compiler->lvaTable[compiler->lvaVarargsHandleArg].lvStkOffs; + unsigned varOffset = compiler->lvaTable[varNum].lvStkOffs; + + noway_assert(cookieOffset < varOffset); + unsigned offset = varOffset - cookieOffset; + unsigned stkArgSize = compiler->compArgSize - intRegState.rsCalleeRegArgCount * sizeof(void*); + noway_assert(offset < stkArgSize); + offset = stkArgSize - offset; + + varLoc.vlType = Compiler::VLT_FIXED_VA; + varLoc.vlFixedVarArg.vlfvOffset = offset; + } + +#endif // _TARGET_X86_ + + VarName name = nullptr; + +#ifdef DEBUG + + for (unsigned scopeNum = 0; scopeNum < compiler->info.compVarScopesCount; scopeNum++) + { + if (LVnum == compiler->info.compVarScopes[scopeNum].vsdLVnum) + { + name = compiler->info.compVarScopes[scopeNum].vsdName; + } + } + + // Hang on to this compiler->info. + + TrnslLocalVarInfo& tlvi = genTrnslLocalVarInfo[which]; + + tlvi.tlviVarNum = ilVarNum; + tlvi.tlviLVnum = LVnum; + tlvi.tlviName = name; + tlvi.tlviStartPC = startOffs; + tlvi.tlviLength = length; + tlvi.tlviAvailable = avail; + tlvi.tlviVarLoc = varLoc; + +#endif // DEBUG + + compiler->eeSetLVinfo(which, startOffs, length, ilVarNum, LVnum, name, avail, varLoc); +} + /*****************************************************************************/ #ifdef LATE_DISASM #if defined(DEBUG) @@ -11747,19 +12102,16 @@ void CodeGen::genIPmappingGen() compiler->eeSetLIdone(); } -#endif // DEBUGGING_SUPPORT - /*============================================================================ * * These are empty stubs to help the late dis-assembler to compile - * if DEBUGGING_SUPPORT is not enabled, or the late disassembler is being - * built into a non-DEBUG build. + * if the late disassembler is being built into a non-DEBUG build. * *============================================================================ */ #if defined(LATE_DISASM) -#if !defined(DEBUGGING_SUPPORT) || !defined(DEBUG) +#if !defined(DEBUG) /* virtual */ const char* CodeGen::siRegVarName(size_t offs, size_t size, unsigned reg) @@ -11774,6 +12126,6 @@ const char* CodeGen::siStackVarName(size_t offs, size_t size, unsigned reg, unsi } /*****************************************************************************/ -#endif // !defined(DEBUGGING_SUPPORT) || !defined(DEBUG) +#endif // !defined(DEBUG) #endif // defined(LATE_DISASM) /*****************************************************************************/ diff --git a/src/jit/codegeninterface.h b/src/jit/codegeninterface.h index e9abbe6..3950673 100644 --- a/src/jit/codegeninterface.h +++ b/src/jit/codegeninterface.h @@ -253,12 +253,14 @@ public: private: bool m_cgDoubleAlign; -#else // !DOUBLE_ALIGN +#else // !DOUBLE_ALIGN + public: bool doubleAlignOrFramePointerUsed() const { return isFramePointerUsed(); } + #endif // !DOUBLE_ALIGN #ifdef DEBUG @@ -424,10 +426,8 @@ public: private: bool m_cgFullPtrRegMap; -#ifdef DEBUGGING_SUPPORT public: virtual void siUpdate() = 0; -#endif // DEBUGGING_SUPPORT #ifdef LATE_DISASM public: diff --git a/src/jit/codegenlegacy.cpp b/src/jit/codegenlegacy.cpp index ea40eb2..667b9d4 100644 --- a/src/jit/codegenlegacy.cpp +++ b/src/jit/codegenlegacy.cpp @@ -243,18 +243,6 @@ GenTreePtr CodeGen::genGetAddrModeBase(GenTreePtr tree) return NULL; } -// inline -void CodeGen::genSinglePush() -{ - genStackLevel += sizeof(void*); -} - -// inline -void CodeGen::genSinglePop() -{ - genStackLevel -= sizeof(void*); -} - #if FEATURE_STACK_FP_X87 // inline void CodeGenInterface::genResetFPstkLevel(unsigned newValue /* = 0 */) @@ -497,9 +485,10 @@ void CodeGen::genIncRegBy(regNumber reg, ssize_t ival, GenTreePtr tree, var_type } } #endif - - insFlags flags = setFlags ? INS_FLAGS_SET : INS_FLAGS_DONT_CARE; - inst_RV_IV(INS_add, reg, ival, emitActualTypeSize(dstType), flags); + { + insFlags flags = setFlags ? INS_FLAGS_SET : INS_FLAGS_DONT_CARE; + inst_RV_IV(INS_add, reg, ival, emitActualTypeSize(dstType), flags); + } #ifdef _TARGET_XARCH_ UPDATE_LIVENESS: @@ -4328,8 +4317,6 @@ emitJumpKind CodeGen::genCondSetFlags(GenTreePtr cond) addrReg1 = genMakeRvalueAddressable(op1, RBM_NONE, RegSet::KEEP_REG, false, smallOk); } - // #if defined(DEBUGGING_SUPPORT) - /* Special case: comparison of two constants */ // Needed if Importer doesn't call gtFoldExpr() @@ -4347,8 +4334,6 @@ emitJumpKind CodeGen::genCondSetFlags(GenTreePtr cond) addrReg1 = genRegMask(op1->gtRegNum); } - // #endif - /* Compare the operand against the constant */ if (op2->IsIconHandle()) @@ -7087,84 +7072,87 @@ void CodeGen::genCodeForTreeSmpBinArithLogOp(GenTreePtr tree, regMaskTP destReg, regTracker.rsTrackRegTrash(reg); - bool op2Released = false; + { + bool op2Released = false; - // For overflow instructions, tree->gtType is the accurate type, - // and gives us the size for the operands. + // For overflow instructions, tree->gtType is the accurate type, + // and gives us the size for the operands. - emitAttr opSize = emitTypeSize(treeType); + emitAttr opSize = emitTypeSize(treeType); - /* Compute the new value */ + /* Compute the new value */ - if (isArith && !op2->InReg() && (op2->OperKind() & GTK_CONST) + if (isArith && !op2->InReg() && (op2->OperKind() & GTK_CONST) #if !CPU_HAS_FP_SUPPORT - && (treeType == TYP_INT || treeType == TYP_I_IMPL) + && (treeType == TYP_INT || treeType == TYP_I_IMPL) #endif - ) - { - ssize_t ival = op2->gtIntCon.gtIconVal; - - if (oper == GT_ADD) - { - genIncRegBy(reg, ival, tree, treeType, ovfl); - } - else if (oper == GT_SUB) - { - if (ovfl && ((tree->gtFlags & GTF_UNSIGNED) || - (ival == ((treeType == TYP_INT) ? INT32_MIN : SSIZE_T_MIN))) // -0x80000000 == 0x80000000. - // Therefore we can't use -ival. ) - { - /* For unsigned overflow, we have to use INS_sub to set - the flags correctly */ + { + ssize_t ival = op2->gtIntCon.gtIconVal; - genDecRegBy(reg, ival, tree); + if (oper == GT_ADD) + { + genIncRegBy(reg, ival, tree, treeType, ovfl); } - else + else if (oper == GT_SUB) { - /* Else, we simply add the negative of the value */ + if (ovfl && ((tree->gtFlags & GTF_UNSIGNED) || + (ival == ((treeType == TYP_INT) ? INT32_MIN : SSIZE_T_MIN))) // -0x80000000 == 0x80000000. + // Therefore we can't use -ival. + ) + { + /* For unsigned overflow, we have to use INS_sub to set + the flags correctly */ - genIncRegBy(reg, -ival, tree, treeType, ovfl); + genDecRegBy(reg, ival, tree); + } + else + { + /* Else, we simply add the negative of the value */ + + genIncRegBy(reg, -ival, tree, treeType, ovfl); + } + } + else if (oper == GT_MUL) + { + genMulRegBy(reg, ival, tree, treeType, ovfl); } } - else if (oper == GT_MUL) - { - genMulRegBy(reg, ival, tree, treeType, ovfl); - } - } - else - { - // op2 could be a GT_COMMA (i.e. an assignment for a CSE def) - op2 = op2->gtEffectiveVal(); - if (varTypeIsByte(treeType) && op2->InReg()) + else { - noway_assert(genRegMask(reg) & RBM_BYTE_REGS); + // op2 could be a GT_COMMA (i.e. an assignment for a CSE def) + op2 = op2->gtEffectiveVal(); + if (varTypeIsByte(treeType) && op2->InReg()) + { + noway_assert(genRegMask(reg) & RBM_BYTE_REGS); - regNumber op2reg = op2->gtRegNum; - regMaskTP op2regMask = genRegMask(op2reg); + regNumber op2reg = op2->gtRegNum; + regMaskTP op2regMask = genRegMask(op2reg); - if (!(op2regMask & RBM_BYTE_REGS)) - { - regNumber byteReg = regSet.rsGrabReg(RBM_BYTE_REGS); + if (!(op2regMask & RBM_BYTE_REGS)) + { + regNumber byteReg = regSet.rsGrabReg(RBM_BYTE_REGS); - inst_RV_RV(INS_mov, byteReg, op2reg); - regTracker.rsTrackRegTrash(byteReg); + inst_RV_RV(INS_mov, byteReg, op2reg); + regTracker.rsTrackRegTrash(byteReg); - genDoneAddressable(op2, addrReg, RegSet::KEEP_REG); - op2Released = true; + genDoneAddressable(op2, addrReg, RegSet::KEEP_REG); + op2Released = true; - op2->gtRegNum = byteReg; + op2->gtRegNum = byteReg; + } } - } - inst_RV_TT(ins, reg, op2, 0, opSize, flags); - } + inst_RV_TT(ins, reg, op2, 0, opSize, flags); + } - /* Free up anything that was tied up by the operand */ - - if (!op2Released) - genDoneAddressable(op2, addrReg, RegSet::KEEP_REG); + /* Free up anything that was tied up by the operand */ + if (!op2Released) + { + genDoneAddressable(op2, addrReg, RegSet::KEEP_REG); + } + } /* The result will be where the first operand is sitting */ /* We must use RegSet::KEEP_REG since op1 can have a GC pointer here */ @@ -9721,7 +9709,7 @@ void CodeGen::genCodeForTreeSmpOp(GenTreePtr tree, regMaskTP destReg, regMaskTP switch (oper) { case GT_ASG: - if (tree->OperIsBlkOp()) + if (tree->OperIsBlkOp() && op1->gtOper != GT_LCL_VAR) { genCodeForBlkOp(tree, destReg); } @@ -10184,6 +10172,9 @@ void CodeGen::genCodeForTreeSmpOp(GenTreePtr tree, regMaskTP destReg, regMaskTP if (op1 == NULL) return; #endif + __fallthrough; + + case GT_INIT_VAL: /* Generate the operand into some register */ @@ -11293,10 +11284,8 @@ void CodeGen::genCodeForTreeSmpOpAsg(GenTreePtr tree) bool volat = false; // Is this a volatile store regMaskTP regGC; instruction ins; -#ifdef DEBUGGING_SUPPORT - unsigned lclVarNum = compiler->lvaCount; - unsigned lclILoffs = DUMMY_INIT(0); -#endif + unsigned lclVarNum = compiler->lvaCount; + unsigned lclILoffs = DUMMY_INIT(0); #ifdef _TARGET_ARM_ if (tree->gtType == TYP_STRUCT) @@ -11335,7 +11324,6 @@ void CodeGen::genCodeForTreeSmpOpAsg(GenTreePtr tree) noway_assert(varNum < compiler->lvaCount); varDsc = compiler->lvaTable + varNum; -#ifdef DEBUGGING_SUPPORT /* For non-debuggable code, every definition of a lcl-var has * to be checked to see if we need to open a new scope for it. * Remember the local var info to call siCheckVarScope @@ -11346,7 +11334,6 @@ void CodeGen::genCodeForTreeSmpOpAsg(GenTreePtr tree) lclVarNum = varNum; lclILoffs = op1->gtLclVar.gtLclILoffs; } -#endif /* Check against dead store ? (with min opts we may have dead stores) */ @@ -11999,13 +11986,11 @@ void CodeGen::genCodeForTreeSmpOpAsg(GenTreePtr tree) genCodeForTreeSmpOpAsg_DONE_ASSG(tree, addrReg, REG_NA, ovfl); LExit: -#ifdef DEBUGGING_SUPPORT /* For non-debuggable code, every definition of a lcl-var has * to be checked to see if we need to open a new scope for it. */ if (lclVarNum < compiler->lvaCount) siCheckVarScope(lclVarNum, lclILoffs); -#endif } #ifdef _PREFAST_ #pragma warning(pop) @@ -12436,14 +12421,12 @@ void CodeGen::genCodeForBBlist() regSet.rsSpillBeg(); -#ifdef DEBUGGING_SUPPORT /* Initialize the line# tracking logic */ if (compiler->opts.compScopeInfo) { siInit(); } -#endif #ifdef _TARGET_X86_ if (compiler->compTailCallUsed) @@ -12774,27 +12757,7 @@ void CodeGen::genCodeForBBlist() genResetFPstkLevel(); #endif // FEATURE_STACK_FP_X87 -#if !FEATURE_FIXED_OUT_ARGS - /* Check for inserted throw blocks and adjust genStackLevel */ - - if (!isFramePointerUsed() && compiler->fgIsThrowHlpBlk(block)) - { - noway_assert(block->bbFlags & BBF_JMP_TARGET); - - genStackLevel = compiler->fgThrowHlpBlkStkLevel(block) * sizeof(int); - - if (genStackLevel) - { -#ifdef _TARGET_X86_ - getEmitter()->emitMarkStackLvl(genStackLevel); - inst_RV_IV(INS_add, REG_SPBASE, genStackLevel, EA_PTRSIZE); - genStackLevel = 0; -#else // _TARGET_X86_ - NYI("Need emitMarkStackLvl()"); -#endif // _TARGET_X86_ - } - } -#endif // !FEATURE_FIXED_OUT_ARGS + genAdjustStackLevel(block); savedStkLvl = genStackLevel; @@ -12802,7 +12765,6 @@ void CodeGen::genCodeForBBlist() compiler->compCurBB = block; -#ifdef DEBUGGING_SUPPORT siBeginBlock(block); // BBF_INTERNAL blocks don't correspond to any single IL instruction. @@ -12810,7 +12772,6 @@ void CodeGen::genCodeForBBlist() genIPmappingAdd((IL_OFFSETX)ICorDebugInfo::NO_MAPPING, true); bool firstMapping = true; -#endif // DEBUGGING_SUPPORT /*--------------------------------------------------------------------- * @@ -12830,8 +12791,6 @@ void CodeGen::genCodeForBBlist() { noway_assert(stmt->gtOper == GT_STMT); -#if defined(DEBUGGING_SUPPORT) - /* Do we have a new IL-offset ? */ if (stmt->gtStmt.gtStmtILoffsx != BAD_IL_OFFSET) @@ -12841,8 +12800,6 @@ void CodeGen::genCodeForBBlist() firstMapping = false; } -#endif // DEBUGGING_SUPPORT - #ifdef DEBUG if (stmt->gtStmt.gtStmtLastILoffs != BAD_IL_OFFSET) { @@ -12945,7 +12902,7 @@ void CodeGen::genCodeForBBlist() // harmless "inc" instruction (does not interfere with the exception // object). - if ((compiler->opts.eeFlags & CORJIT_FLG_BBINSTR) && (stmt == block->bbTreeList) && + if (compiler->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_BBINSTR) && (stmt == block->bbTreeList) && (block->bbCatchTyp && handlerGetsXcptnObj(block->bbCatchTyp))) { nonVarPtrRegs &= ~RBM_EXCEPTION_OBJECT; @@ -12972,14 +12929,10 @@ void CodeGen::genCodeForBBlist() noway_assert(stmt->gtOper == GT_STMT); -#ifdef DEBUGGING_SUPPORT genEnsureCodeEmitted(stmt->gtStmt.gtStmtILoffsx); -#endif } //-------- END-FOR each statement-tree of the current block --------- -#ifdef DEBUGGING_SUPPORT - if (compiler->opts.compScopeInfo && (compiler->info.compVarScopesCount > 0)) { siEndBlock(block); @@ -13005,8 +12958,6 @@ void CodeGen::genCodeForBBlist() } } -#endif // DEBUGGING_SUPPORT - genStackLevel -= savedStkLvl; gcInfo.gcMarkRegSetNpt(gcrefRegs | byrefRegs); @@ -13449,10 +13400,8 @@ void CodeGen::genCodeForTreeLng(GenTreePtr tree, regMaskTP needReg, regMaskTP av { case GT_ASG: { -#ifdef DEBUGGING_SUPPORT unsigned lclVarNum = compiler->lvaCount; unsigned lclVarILoffs = DUMMY_INIT(0); -#endif /* Is the target a local ? */ @@ -13467,7 +13416,6 @@ void CodeGen::genCodeForTreeLng(GenTreePtr tree, regMaskTP needReg, regMaskTP av // No dead stores, (with min opts we may have dead stores) noway_assert(!varDsc->lvTracked || compiler->opts.MinOpts() || !(op1->gtFlags & GTF_VAR_DEATH)); -#ifdef DEBUGGING_SUPPORT /* For non-debuggable code, every definition of a lcl-var has * to be checked to see if we need to open a new scope for it. * Remember the local var info to call siCheckVarScope @@ -13479,7 +13427,6 @@ void CodeGen::genCodeForTreeLng(GenTreePtr tree, regMaskTP needReg, regMaskTP av lclVarNum = varNum; lclVarILoffs = op1->gtLclVar.gtLclILoffs; } -#endif /* Has the variable been assigned to a register (pair) ? */ @@ -13767,13 +13714,11 @@ void CodeGen::genCodeForTreeLng(GenTreePtr tree, regMaskTP needReg, regMaskTP av genUpdateLife(op1); genUpdateLife(tree); -#ifdef DEBUGGING_SUPPORT /* For non-debuggable code, every definition of a lcl-var has * to be checked to see if we need to open a new scope for it. */ if (lclVarNum < compiler->lvaCount) siCheckVarScope(lclVarNum, lclVarILoffs); -#endif } return; @@ -15792,132 +15737,6 @@ void CodeGen::genEmitHelperCall(unsigned helper, int argSize, emitAttr retSize) /***************************************************************************** * - * Push the given registers. - * This function does not check if the register is marked as used, etc. - */ - -regMaskTP CodeGen::genPushRegs(regMaskTP regs, regMaskTP* byrefRegs, regMaskTP* noRefRegs) -{ - *byrefRegs = RBM_NONE; - *noRefRegs = RBM_NONE; - - // noway_assert((regs & regSet.rsRegMaskFree()) == regs); // Don't care. Caller is responsible for all this - - if (regs == RBM_NONE) - return RBM_NONE; - -#if FEATURE_FIXED_OUT_ARGS - - NYI("Don't call genPushRegs with real regs!"); - return RBM_NONE; - -#else // FEATURE_FIXED_OUT_ARGS - - noway_assert(genTypeStSz(TYP_REF) == genTypeStSz(TYP_I_IMPL)); - noway_assert(genTypeStSz(TYP_BYREF) == genTypeStSz(TYP_I_IMPL)); - - regMaskTP pushedRegs = regs; - - for (regNumber reg = REG_INT_FIRST; regs != RBM_NONE; reg = REG_NEXT(reg)) - { - regMaskTP regBit = regMaskTP(1) << reg; - - if ((regBit & regs) == RBM_NONE) - continue; - - var_types type; - if (regBit & gcInfo.gcRegGCrefSetCur) - { - type = TYP_REF; - } - else if (regBit & gcInfo.gcRegByrefSetCur) - { - *byrefRegs |= regBit; - type = TYP_BYREF; - } - else if (noRefRegs != NULL) - { - *noRefRegs |= regBit; - type = TYP_I_IMPL; - } - else - { - continue; - } - - inst_RV(INS_push, reg, type); - - genSinglePush(); - gcInfo.gcMarkRegSetNpt(regBit); - - regs &= ~regBit; - } - - return pushedRegs; - -#endif // FEATURE_FIXED_OUT_ARGS -} - -/***************************************************************************** - * - * Pop the registers pushed by genPushRegs() - */ - -void CodeGen::genPopRegs(regMaskTP regs, regMaskTP byrefRegs, regMaskTP noRefRegs) -{ - if (regs == RBM_NONE) - return; - -#if FEATURE_FIXED_OUT_ARGS - - NYI("Don't call genPopRegs with real regs!"); - -#else // FEATURE_FIXED_OUT_ARGS - - noway_assert((regs & byrefRegs) == byrefRegs); - noway_assert((regs & noRefRegs) == noRefRegs); - // noway_assert((regs & regSet.rsRegMaskFree()) == regs); // Don't care. Caller is responsible for all this - noway_assert((regs & (gcInfo.gcRegGCrefSetCur | gcInfo.gcRegByrefSetCur)) == RBM_NONE); - - noway_assert(genTypeStSz(TYP_REF) == genTypeStSz(TYP_INT)); - noway_assert(genTypeStSz(TYP_BYREF) == genTypeStSz(TYP_INT)); - - // Walk the registers in the reverse order as genPushRegs() - for (regNumber reg = REG_INT_LAST; regs != RBM_NONE; reg = REG_PREV(reg)) - { - regMaskTP regBit = regMaskTP(1) << reg; - - if ((regBit & regs) == RBM_NONE) - continue; - - var_types type; - if (regBit & byrefRegs) - { - type = TYP_BYREF; - } - else if (regBit & noRefRegs) - { - type = TYP_INT; - } - else - { - type = TYP_REF; - } - - inst_RV(INS_pop, reg, type); - genSinglePop(); - - if (type != TYP_INT) - gcInfo.gcMarkRegPtrVal(reg, type); - - regs &= ~regBit; - } - -#endif // FEATURE_FIXED_OUT_ARGS -} - -/***************************************************************************** - * * Push the given argument list, right to left; returns the total amount of * stuff pushed. */ @@ -18519,12 +18338,10 @@ regMaskTP CodeGen::genCodeForCall(GenTreePtr call, bool valUsed) CORINFO_SIG_INFO* sigInfo = nullptr; -#ifdef DEBUGGING_SUPPORT if (compiler->opts.compDbgInfo && compiler->genCallSite2ILOffsetMap != NULL) { (void)compiler->genCallSite2ILOffsetMap->Lookup(call, &ilOffset); } -#endif /* Make some sanity checks on the call node */ @@ -19600,6 +19417,7 @@ regMaskTP CodeGen::genCodeForCall(GenTreePtr call, bool valUsed) regNumber indCallReg; case IAT_VALUE: + { //------------------------------------------------------ // Non-virtual direct calls to known addressess // @@ -19607,7 +19425,24 @@ regMaskTP CodeGen::genCodeForCall(GenTreePtr call, bool valUsed) // it be nice if they all did! CLANG_FORMAT_COMMENT_ANCHOR; #ifdef _TARGET_ARM_ - if (!arm_Valid_Imm_For_BL((ssize_t)addr)) + // We may use direct call for some of recursive calls + // as we can safely estimate the distance from the call site to the top of the method + const int codeOffset = MAX_PROLOG_SIZE_BYTES + // prolog size + getEmitter()->emitCurCodeOffset + // offset of the current IG + getEmitter()->emitCurIGsize + // size of the current IG + 4; // size of the jump instruction + // that we are now emitting + if (compiler->gtIsRecursiveCall(call->AsCall()) && codeOffset <= -CALL_DIST_MAX_NEG) + { + getEmitter()->emitIns_Call(emitter::EC_FUNC_TOKEN, methHnd, + INDEBUG_LDISASM_COMMA(sigInfo) NULL, // addr + args, retSize, gcInfo.gcVarPtrSetCur, + gcInfo.gcRegGCrefSetCur, gcInfo.gcRegByrefSetCur, ilOffset, + REG_NA, REG_NA, 0, 0, // ireg, xreg, xmul, disp + false, // isJump + emitter::emitNoGChelper(helperNum)); + } + else if (!arm_Valid_Imm_For_BL((ssize_t)addr)) { // Load the address into a register and call through a register indCallReg = regSet.rsGrabReg(RBM_ALLINT); // Grab an available register to use for the @@ -19634,7 +19469,8 @@ regMaskTP CodeGen::genCodeForCall(GenTreePtr call, bool valUsed) false, /* isJump */ emitter::emitNoGChelper(helperNum)); } - break; + } + break; case IAT_PVALUE: //------------------------------------------------------ @@ -20046,7 +19882,7 @@ regMaskTP CodeGen::genCodeForCall(GenTreePtr call, bool valUsed) #if defined(_TARGET_X86_) if (call->gtFlags & GTF_CALL_UNMANAGED) { - if ((compiler->opts.eeFlags & CORJIT_FLG_PINVOKE_RESTORE_ESP) || + if (compiler->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PINVOKE_RESTORE_ESP) || compiler->compStressCompile(Compiler::STRESS_PINVOKE_RESTORE_ESP, 50)) { // P/Invoke signature mismatch resilience - restore ESP to pre-call value. We would ideally @@ -20756,9 +20592,11 @@ DONE: } #endif - /* Write the lvaShadowSPfirst stack frame slot */ - noway_assert(compiler->lvaLocAllocSPvar != BAD_VAR_NUM); - getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SPBASE, compiler->lvaLocAllocSPvar, 0); + /* Write the lvaLocAllocSPvar stack frame slot */ + if (compiler->lvaLocAllocSPvar != BAD_VAR_NUM) + { + getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SPBASE, compiler->lvaLocAllocSPvar, 0); + } #if STACK_PROBES // Don't think it is worth it the codegen complexity to embed this @@ -20783,98 +20621,6 @@ DONE: return regCnt; } -/*****************************************************************************/ -#ifdef DEBUGGING_SUPPORT -/***************************************************************************** - * genSetScopeInfo - * - * Called for every scope info piece to record by the main genSetScopeInfo() - */ - -void CodeGen::genSetScopeInfo(unsigned which, - UNATIVE_OFFSET startOffs, - UNATIVE_OFFSET length, - unsigned varNum, - unsigned LVnum, - bool avail, - Compiler::siVarLoc& varLoc) -{ - /* We need to do some mapping while reporting back these variables */ - - unsigned ilVarNum = compiler->compMap2ILvarNum(varNum); - noway_assert((int)ilVarNum != ICorDebugInfo::UNKNOWN_ILNUM); - -#ifdef _TARGET_X86_ - // Non-x86 platforms are allowed to access all arguments directly - // so we don't need this code. - - // Is this a varargs function? - - if (compiler->info.compIsVarArgs && varNum != compiler->lvaVarargsHandleArg && - varNum < compiler->info.compArgsCount && !compiler->lvaTable[varNum].lvIsRegArg) - { - noway_assert(varLoc.vlType == Compiler::VLT_STK || varLoc.vlType == Compiler::VLT_STK2); - - // All stack arguments (except the varargs handle) have to be - // accessed via the varargs cookie. Discard generated info, - // and just find its position relative to the varargs handle - - PREFIX_ASSUME(compiler->lvaVarargsHandleArg < compiler->info.compArgsCount); - if (!compiler->lvaTable[compiler->lvaVarargsHandleArg].lvOnFrame) - { - noway_assert(!compiler->opts.compDbgCode); - return; - } - - // Can't check compiler->lvaTable[varNum].lvOnFrame as we don't set it for - // arguments of vararg functions to avoid reporting them to GC. - noway_assert(!compiler->lvaTable[varNum].lvRegister); - unsigned cookieOffset = compiler->lvaTable[compiler->lvaVarargsHandleArg].lvStkOffs; - unsigned varOffset = compiler->lvaTable[varNum].lvStkOffs; - - noway_assert(cookieOffset < varOffset); - unsigned offset = varOffset - cookieOffset; - unsigned stkArgSize = compiler->compArgSize - intRegState.rsCalleeRegArgCount * sizeof(void*); - noway_assert(offset < stkArgSize); - offset = stkArgSize - offset; - - varLoc.vlType = Compiler::VLT_FIXED_VA; - varLoc.vlFixedVarArg.vlfvOffset = offset; - } - -#endif // _TARGET_X86_ - - VarName name = NULL; - -#ifdef DEBUG - - for (unsigned scopeNum = 0; scopeNum < compiler->info.compVarScopesCount; scopeNum++) - { - if (LVnum == compiler->info.compVarScopes[scopeNum].vsdLVnum) - { - name = compiler->info.compVarScopes[scopeNum].vsdName; - } - } - - // Hang on to this compiler->info. - - TrnslLocalVarInfo& tlvi = genTrnslLocalVarInfo[which]; - - tlvi.tlviVarNum = ilVarNum; - tlvi.tlviLVnum = LVnum; - tlvi.tlviName = name; - tlvi.tlviStartPC = startOffs; - tlvi.tlviLength = length; - tlvi.tlviAvailable = avail; - tlvi.tlviVarLoc = varLoc; - -#endif // DEBUG - - compiler->eeSetLVinfo(which, startOffs, length, ilVarNum, LVnum, name, avail, varLoc); -} - -#endif // DEBUGGING_SUPPORT - /***************************************************************************** * * Return non-zero if the given register is free after the given tree is diff --git a/src/jit/codegenlinear.cpp b/src/jit/codegenlinear.cpp new file mode 100644 index 0000000..9713288 --- /dev/null +++ b/src/jit/codegenlinear.cpp @@ -0,0 +1,1773 @@ +// 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. + +/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XX XX +XX Code Generation Support Methods for Linear Codegen XX +XX XX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +*/ +#include "jitpch.h" +#ifdef _MSC_VER +#pragma hdrstop +#endif + +#ifndef LEGACY_BACKEND // This file is ONLY used for the RyuJIT backend that uses the linear scan register allocator. +#include "emit.h" +#include "codegen.h" + +//------------------------------------------------------------------------ +// genCodeForBBlist: Generate code for all the blocks in a method +// +// Arguments: +// None +// +// Notes: +// This is the main method for linear codegen. It calls genCodeForTreeNode +// to generate the code for each node in each BasicBlock, and handles BasicBlock +// boundaries and branches. +// +void CodeGen::genCodeForBBlist() +{ + unsigned varNum; + LclVarDsc* varDsc; + + unsigned savedStkLvl; + +#ifdef DEBUG + genInterruptibleUsed = true; + + // You have to be careful if you create basic blocks from now on + compiler->fgSafeBasicBlockCreation = false; + + // This stress mode is not comptible with fully interruptible GC + if (genInterruptible && compiler->opts.compStackCheckOnCall) + { + compiler->opts.compStackCheckOnCall = false; + } + + // This stress mode is not comptible with fully interruptible GC + if (genInterruptible && compiler->opts.compStackCheckOnRet) + { + compiler->opts.compStackCheckOnRet = false; + } +#endif // DEBUG + + // Prepare the blocks for exception handling codegen: mark the blocks that needs labels. + genPrepForEHCodegen(); + + assert(!compiler->fgFirstBBScratch || + compiler->fgFirstBB == compiler->fgFirstBBScratch); // compiler->fgFirstBBScratch has to be first. + + /* Initialize the spill tracking logic */ + + regSet.rsSpillBeg(); + + /* Initialize the line# tracking logic */ + + if (compiler->opts.compScopeInfo) + { + siInit(); + } + + // The current implementation of switch tables requires the first block to have a label so it + // can generate offsets to the switch label targets. + // TODO-CQ: remove this when switches have been re-implemented to not use this. + if (compiler->fgHasSwitch) + { + compiler->fgFirstBB->bbFlags |= BBF_JMP_TARGET; + } + + genPendingCallLabel = nullptr; + + /* Initialize the pointer tracking code */ + + gcInfo.gcRegPtrSetInit(); + gcInfo.gcVarPtrSetInit(); + + /* If any arguments live in registers, mark those regs as such */ + + for (varNum = 0, varDsc = compiler->lvaTable; varNum < compiler->lvaCount; varNum++, varDsc++) + { + /* Is this variable a parameter assigned to a register? */ + + if (!varDsc->lvIsParam || !varDsc->lvRegister) + { + continue; + } + + /* Is the argument live on entry to the method? */ + + if (!VarSetOps::IsMember(compiler, compiler->fgFirstBB->bbLiveIn, varDsc->lvVarIndex)) + { + continue; + } + + /* Is this a floating-point argument? */ + + if (varDsc->IsFloatRegType()) + { + continue; + } + + noway_assert(!varTypeIsFloating(varDsc->TypeGet())); + + /* Mark the register as holding the variable */ + + regTracker.rsTrackRegLclVar(varDsc->lvRegNum, varNum); + } + + unsigned finallyNesting = 0; + + // Make sure a set is allocated for compiler->compCurLife (in the long case), so we can set it to empty without + // allocation at the start of each basic block. + VarSetOps::AssignNoCopy(compiler, compiler->compCurLife, VarSetOps::MakeEmpty(compiler)); + + /*------------------------------------------------------------------------- + * + * Walk the basic blocks and generate code for each one + * + */ + + BasicBlock* block; + BasicBlock* lblk; /* previous block */ + + for (lblk = nullptr, block = compiler->fgFirstBB; block != nullptr; lblk = block, block = block->bbNext) + { +#ifdef DEBUG + if (compiler->verbose) + { + printf("\n=============== Generating "); + block->dspBlockHeader(compiler, true, true); + compiler->fgDispBBLiveness(block); + } +#endif // DEBUG + + // Figure out which registers hold variables on entry to this block + + regSet.ClearMaskVars(); + gcInfo.gcRegGCrefSetCur = RBM_NONE; + gcInfo.gcRegByrefSetCur = RBM_NONE; + + compiler->m_pLinearScan->recordVarLocationsAtStartOfBB(block); + + genUpdateLife(block->bbLiveIn); + + // Even if liveness didn't change, we need to update the registers containing GC references. + // genUpdateLife will update the registers live due to liveness changes. But what about registers that didn't + // change? We cleared them out above. Maybe we should just not clear them out, but update the ones that change + // here. That would require handling the changes in recordVarLocationsAtStartOfBB(). + + regMaskTP newLiveRegSet = RBM_NONE; + regMaskTP newRegGCrefSet = RBM_NONE; + regMaskTP newRegByrefSet = RBM_NONE; +#ifdef DEBUG + VARSET_TP VARSET_INIT_NOCOPY(removedGCVars, VarSetOps::MakeEmpty(compiler)); + VARSET_TP VARSET_INIT_NOCOPY(addedGCVars, VarSetOps::MakeEmpty(compiler)); +#endif + VARSET_ITER_INIT(compiler, iter, block->bbLiveIn, varIndex); + while (iter.NextElem(compiler, &varIndex)) + { + unsigned varNum = compiler->lvaTrackedToVarNum[varIndex]; + LclVarDsc* varDsc = &(compiler->lvaTable[varNum]); + + if (varDsc->lvIsInReg()) + { + newLiveRegSet |= varDsc->lvRegMask(); + if (varDsc->lvType == TYP_REF) + { + newRegGCrefSet |= varDsc->lvRegMask(); + } + else if (varDsc->lvType == TYP_BYREF) + { + newRegByrefSet |= varDsc->lvRegMask(); + } +#ifdef DEBUG + if (verbose && VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varIndex)) + { + VarSetOps::AddElemD(compiler, removedGCVars, varIndex); + } +#endif // DEBUG + VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varIndex); + } + else if (compiler->lvaIsGCTracked(varDsc)) + { +#ifdef DEBUG + if (verbose && !VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varIndex)) + { + VarSetOps::AddElemD(compiler, addedGCVars, varIndex); + } +#endif // DEBUG + VarSetOps::AddElemD(compiler, gcInfo.gcVarPtrSetCur, varIndex); + } + } + + regSet.rsMaskVars = newLiveRegSet; + +#ifdef DEBUG + if (compiler->verbose) + { + if (!VarSetOps::IsEmpty(compiler, addedGCVars)) + { + printf("\t\t\t\t\t\t\tAdded GCVars: "); + dumpConvertedVarSet(compiler, addedGCVars); + printf("\n"); + } + if (!VarSetOps::IsEmpty(compiler, removedGCVars)) + { + printf("\t\t\t\t\t\t\tRemoved GCVars: "); + dumpConvertedVarSet(compiler, removedGCVars); + printf("\n"); + } + } +#endif // DEBUG + + gcInfo.gcMarkRegSetGCref(newRegGCrefSet DEBUGARG(true)); + gcInfo.gcMarkRegSetByref(newRegByrefSet DEBUGARG(true)); + + /* Blocks with handlerGetsXcptnObj()==true use GT_CATCH_ARG to + represent the exception object (TYP_REF). + We mark REG_EXCEPTION_OBJECT as holding a GC object on entry + to the block, it will be the first thing evaluated + (thanks to GTF_ORDER_SIDEEFF). + */ + + if (handlerGetsXcptnObj(block->bbCatchTyp)) + { + for (GenTree* node : LIR::AsRange(block)) + { + if (node->OperGet() == GT_CATCH_ARG) + { + gcInfo.gcMarkRegSetGCref(RBM_EXCEPTION_OBJECT); + break; + } + } + } + + /* Start a new code output block */ + + genUpdateCurrentFunclet(block); + +#ifdef _TARGET_XARCH_ + if (genAlignLoops && block->bbFlags & BBF_LOOP_HEAD) + { + getEmitter()->emitLoopAlign(); + } +#endif + +#ifdef DEBUG + if (compiler->opts.dspCode) + { + printf("\n L_M%03u_BB%02u:\n", Compiler::s_compMethodsCount, block->bbNum); + } +#endif + + block->bbEmitCookie = nullptr; + + if (block->bbFlags & (BBF_JMP_TARGET | BBF_HAS_LABEL)) + { + /* Mark a label and update the current set of live GC refs */ + + block->bbEmitCookie = getEmitter()->emitAddLabel(gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, + gcInfo.gcRegByrefSetCur, FALSE); + } + + if (block == compiler->fgFirstColdBlock) + { +#ifdef DEBUG + if (compiler->verbose) + { + printf("\nThis is the start of the cold region of the method\n"); + } +#endif + // We should never have a block that falls through into the Cold section + noway_assert(!lblk->bbFallsThrough()); + + // We require the block that starts the Cold section to have a label + noway_assert(block->bbEmitCookie); + getEmitter()->emitSetFirstColdIGCookie(block->bbEmitCookie); + } + + /* Both stacks are always empty on entry to a basic block */ + + genStackLevel = 0; + genAdjustStackLevel(block); + savedStkLvl = genStackLevel; + + /* Tell everyone which basic block we're working on */ + + compiler->compCurBB = block; + + siBeginBlock(block); + + // BBF_INTERNAL blocks don't correspond to any single IL instruction. + if (compiler->opts.compDbgInfo && (block->bbFlags & BBF_INTERNAL) && + !compiler->fgBBisScratch(block)) // If the block is the distinguished first scratch block, then no need to + // emit a NO_MAPPING entry, immediately after the prolog. + { + genIPmappingAdd((IL_OFFSETX)ICorDebugInfo::NO_MAPPING, true); + } + + bool firstMapping = true; + +#if FEATURE_EH_FUNCLETS + if (block->bbFlags & BBF_FUNCLET_BEG) + { + genReserveFuncletProlog(block); + } +#endif // FEATURE_EH_FUNCLETS + + // Clear compCurStmt and compCurLifeTree. + compiler->compCurStmt = nullptr; + compiler->compCurLifeTree = nullptr; + + // Traverse the block in linear order, generating code for each node as we + // as we encounter it. + CLANG_FORMAT_COMMENT_ANCHOR; + +#ifdef DEBUG + // Set the use-order numbers for each node. + { + int useNum = 0; + for (GenTree* node : LIR::AsRange(block).NonPhiNodes()) + { + assert((node->gtDebugFlags & GTF_DEBUG_NODE_CG_CONSUMED) == 0); + + node->gtUseNum = -1; + if (node->isContained() || node->IsCopyOrReload()) + { + continue; + } + + for (GenTree* operand : node->Operands()) + { + genNumberOperandUse(operand, useNum); + } + } + } +#endif // DEBUG + + IL_OFFSETX currentILOffset = BAD_IL_OFFSET; + for (GenTree* node : LIR::AsRange(block).NonPhiNodes()) + { + // Do we have a new IL offset? + if (node->OperGet() == GT_IL_OFFSET) + { + genEnsureCodeEmitted(currentILOffset); + currentILOffset = node->gtStmt.gtStmtILoffsx; + genIPmappingAdd(currentILOffset, firstMapping); + firstMapping = false; + } + +#ifdef DEBUG + if (node->OperGet() == GT_IL_OFFSET) + { + noway_assert(node->gtStmt.gtStmtLastILoffs <= compiler->info.compILCodeSize || + node->gtStmt.gtStmtLastILoffs == BAD_IL_OFFSET); + + if (compiler->opts.dspCode && compiler->opts.dspInstrs && + node->gtStmt.gtStmtLastILoffs != BAD_IL_OFFSET) + { + while (genCurDispOffset <= node->gtStmt.gtStmtLastILoffs) + { + genCurDispOffset += dumpSingleInstr(compiler->info.compCode, genCurDispOffset, "> "); + } + } + } +#endif // DEBUG + + genCodeForTreeNode(node); + if (node->gtHasReg() && node->gtLsraInfo.isLocalDefUse) + { + genConsumeReg(node); + } + } // end for each node in block + +#ifdef DEBUG + // The following set of register spill checks and GC pointer tracking checks used to be + // performed at statement boundaries. Now, with LIR, there are no statements, so they are + // performed at the end of each block. + // TODO: could these checks be performed more frequently? E.g., at each location where + // the register allocator says there are no live non-variable registers. Perhaps this could + // be done by (a) keeping a running count of live non-variable registers by using + // gtLsraInfo.srcCount and gtLsraInfo.dstCount to decrement and increment the count, respectively, + // and running the checks when the count is zero. Or, (b) use the map maintained by LSRA + // (operandToLocationInfoMap) to mark a node somehow when, after the execution of that node, + // there will be no live non-variable registers. + + regSet.rsSpillChk(); + + /* Make sure we didn't bungle pointer register tracking */ + + regMaskTP ptrRegs = gcInfo.gcRegGCrefSetCur | gcInfo.gcRegByrefSetCur; + regMaskTP nonVarPtrRegs = ptrRegs & ~regSet.rsMaskVars; + + // If return is a GC-type, clear it. Note that if a common + // epilog is generated (genReturnBB) it has a void return + // even though we might return a ref. We can't use the compRetType + // as the determiner because something we are tracking as a byref + // might be used as a return value of a int function (which is legal) + GenTree* blockLastNode = block->lastNode(); + if ((blockLastNode != nullptr) && (blockLastNode->gtOper == GT_RETURN) && + (varTypeIsGC(compiler->info.compRetType) || + (blockLastNode->gtOp.gtOp1 != nullptr && varTypeIsGC(blockLastNode->gtOp.gtOp1->TypeGet())))) + { + nonVarPtrRegs &= ~RBM_INTRET; + } + + if (nonVarPtrRegs) + { + printf("Regset after BB%02u gcr=", block->bbNum); + printRegMaskInt(gcInfo.gcRegGCrefSetCur & ~regSet.rsMaskVars); + compiler->getEmitter()->emitDispRegSet(gcInfo.gcRegGCrefSetCur & ~regSet.rsMaskVars); + printf(", byr="); + printRegMaskInt(gcInfo.gcRegByrefSetCur & ~regSet.rsMaskVars); + compiler->getEmitter()->emitDispRegSet(gcInfo.gcRegByrefSetCur & ~regSet.rsMaskVars); + printf(", regVars="); + printRegMaskInt(regSet.rsMaskVars); + compiler->getEmitter()->emitDispRegSet(regSet.rsMaskVars); + printf("\n"); + } + + noway_assert(nonVarPtrRegs == RBM_NONE); +#endif // DEBUG + +#if defined(DEBUG) + if (block->bbNext == nullptr) + { +// Unit testing of the emitter: generate a bunch of instructions into the last block +// (it's as good as any, but better than the prolog, which can only be a single instruction +// group) then use COMPlus_JitLateDisasm=* to see if the late disassembler +// thinks the instructions are the same as we do. +#if defined(_TARGET_AMD64_) && defined(LATE_DISASM) + genAmd64EmitterUnitTests(); +#elif defined(_TARGET_ARM64_) + genArm64EmitterUnitTests(); +#endif // _TARGET_ARM64_ + } +#endif // defined(DEBUG) + + // It is possible to reach the end of the block without generating code for the current IL offset. + // For example, if the following IR ends the current block, no code will have been generated for + // offset 21: + // + // ( 0, 0) [000040] ------------ il_offset void IL offset: 21 + // + // N001 ( 0, 0) [000039] ------------ nop void + // + // This can lead to problems when debugging the generated code. To prevent these issues, make sure + // we've generated code for the last IL offset we saw in the block. + genEnsureCodeEmitted(currentILOffset); + + if (compiler->opts.compScopeInfo && (compiler->info.compVarScopesCount > 0)) + { + siEndBlock(block); + + /* Is this the last block, and are there any open scopes left ? */ + + bool isLastBlockProcessed = (block->bbNext == nullptr); + if (block->isBBCallAlwaysPair()) + { + isLastBlockProcessed = (block->bbNext->bbNext == nullptr); + } + + if (isLastBlockProcessed && siOpenScopeList.scNext) + { + /* This assert no longer holds, because we may insert a throw + block to demarcate the end of a try or finally region when they + are at the end of the method. It would be nice if we could fix + our code so that this throw block will no longer be necessary. */ + + // noway_assert(block->bbCodeOffsEnd != compiler->info.compILCodeSize); + + siCloseAllOpenScopes(); + } + } + + genStackLevel -= savedStkLvl; + +#ifdef DEBUG + // compCurLife should be equal to the liveOut set, except that we don't keep + // it up to date for vars that are not register candidates + // (it would be nice to have a xor set function) + + VARSET_TP VARSET_INIT_NOCOPY(extraLiveVars, VarSetOps::Diff(compiler, block->bbLiveOut, compiler->compCurLife)); + VarSetOps::UnionD(compiler, extraLiveVars, VarSetOps::Diff(compiler, compiler->compCurLife, block->bbLiveOut)); + VARSET_ITER_INIT(compiler, extraLiveVarIter, extraLiveVars, extraLiveVarIndex); + while (extraLiveVarIter.NextElem(compiler, &extraLiveVarIndex)) + { + unsigned varNum = compiler->lvaTrackedToVarNum[extraLiveVarIndex]; + LclVarDsc* varDsc = compiler->lvaTable + varNum; + assert(!varDsc->lvIsRegCandidate()); + } +#endif + + /* Both stacks should always be empty on exit from a basic block */ + noway_assert(genStackLevel == 0); + +#ifdef _TARGET_AMD64_ + // On AMD64, we need to generate a NOP after a call that is the last instruction of the block, in several + // situations, to support proper exception handling semantics. This is mostly to ensure that when the stack + // walker computes an instruction pointer for a frame, that instruction pointer is in the correct EH region. + // The document "X64 and ARM ABIs.docx" has more details. The situations: + // 1. If the call instruction is in a different EH region as the instruction that follows it. + // 2. If the call immediately precedes an OS epilog. (Note that what the JIT or VM consider an epilog might + // be slightly different from what the OS considers an epilog, and it is the OS-reported epilog that matters + // here.) + // We handle case #1 here, and case #2 in the emitter. + if (getEmitter()->emitIsLastInsCall()) + { + // Ok, the last instruction generated is a call instruction. Do any of the other conditions hold? + // Note: we may be generating a few too many NOPs for the case of call preceding an epilog. Technically, + // if the next block is a BBJ_RETURN, an epilog will be generated, but there may be some instructions + // generated before the OS epilog starts, such as a GS cookie check. + if ((block->bbNext == nullptr) || !BasicBlock::sameEHRegion(block, block->bbNext)) + { + // We only need the NOP if we're not going to generate any more code as part of the block end. + + switch (block->bbJumpKind) + { + case BBJ_ALWAYS: + case BBJ_THROW: + case BBJ_CALLFINALLY: + case BBJ_EHCATCHRET: + // We're going to generate more code below anyway, so no need for the NOP. + + case BBJ_RETURN: + case BBJ_EHFINALLYRET: + case BBJ_EHFILTERRET: + // These are the "epilog follows" case, handled in the emitter. + + break; + + case BBJ_NONE: + if (block->bbNext == nullptr) + { + // Call immediately before the end of the code; we should never get here . + instGen(INS_BREAKPOINT); // This should never get executed + } + else + { + // We need the NOP + instGen(INS_nop); + } + break; + + case BBJ_COND: + case BBJ_SWITCH: + // These can't have a call as the last instruction! + + default: + noway_assert(!"Unexpected bbJumpKind"); + break; + } + } + } +#endif // _TARGET_AMD64_ + + /* Do we need to generate a jump or return? */ + + switch (block->bbJumpKind) + { + case BBJ_ALWAYS: + inst_JMP(EJ_jmp, block->bbJumpDest); + break; + + case BBJ_RETURN: + genExitCode(block); + break; + + case BBJ_THROW: + // If we have a throw at the end of a function or funclet, we need to emit another instruction + // afterwards to help the OS unwinder determine the correct context during unwind. + // We insert an unexecuted breakpoint instruction in several situations + // following a throw instruction: + // 1. If the throw is the last instruction of the function or funclet. This helps + // the OS unwinder determine the correct context during an unwind from the + // thrown exception. + // 2. If this is this is the last block of the hot section. + // 3. If the subsequent block is a special throw block. + // 4. On AMD64, if the next block is in a different EH region. + if ((block->bbNext == nullptr) || (block->bbNext->bbFlags & BBF_FUNCLET_BEG) || + !BasicBlock::sameEHRegion(block, block->bbNext) || + (!isFramePointerUsed() && compiler->fgIsThrowHlpBlk(block->bbNext)) || + block->bbNext == compiler->fgFirstColdBlock) + { + instGen(INS_BREAKPOINT); // This should never get executed + } + + break; + + case BBJ_CALLFINALLY: + block = genCallFinally(block, lblk); + break; + +#if FEATURE_EH_FUNCLETS + + case BBJ_EHCATCHRET: + genEHCatchRet(block); + __fallthrough; + + case BBJ_EHFINALLYRET: + case BBJ_EHFILTERRET: + genReserveFuncletEpilog(block); + break; + +#else // !FEATURE_EH_FUNCLETS + + case BBJ_EHCATCHRET: + noway_assert(!"Unexpected BBJ_EHCATCHRET"); // not used on x86 + + case BBJ_EHFINALLYRET: + case BBJ_EHFILTERRET: + genEHFinallyOrFilterRet(block); + break; + +#endif // !FEATURE_EH_FUNCLETS + + case BBJ_NONE: + case BBJ_COND: + case BBJ_SWITCH: + break; + + default: + noway_assert(!"Unexpected bbJumpKind"); + break; + } + +#ifdef DEBUG + compiler->compCurBB = nullptr; +#endif + + } //------------------ END-FOR each block of the method ------------------- + + /* Nothing is live at this point */ + genUpdateLife(VarSetOps::MakeEmpty(compiler)); + + /* Finalize the spill tracking logic */ + + regSet.rsSpillEnd(); + + /* Finalize the temp tracking logic */ + + compiler->tmpEnd(); + +#ifdef DEBUG + if (compiler->verbose) + { + printf("\n# "); + printf("compCycleEstimate = %6d, compSizeEstimate = %5d ", compiler->compCycleEstimate, + compiler->compSizeEstimate); + printf("%s\n", compiler->info.compFullName); + } +#endif +} + +/* +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XX XX +XX Register Management XX +XX XX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +*/ +// + +//------------------------------------------------------------------------ +// genGetAssignedReg: Get the register assigned to the given node +// +// Arguments: +// tree - the lclVar node whose assigned register we want +// +// Return Value: +// The assigned regNumber +// +regNumber CodeGenInterface::genGetAssignedReg(GenTreePtr tree) +{ + return tree->gtRegNum; +} + +//------------------------------------------------------------------------ +// genSpillVar: Spill a local variable +// +// Arguments: +// tree - the lclVar node for the variable being spilled +// +// Return Value: +// None. +// +// Assumptions: +// The lclVar must be a register candidate (lvRegCandidate) + +void CodeGen::genSpillVar(GenTreePtr tree) +{ + unsigned varNum = tree->gtLclVarCommon.gtLclNum; + LclVarDsc* varDsc = &(compiler->lvaTable[varNum]); + + assert(varDsc->lvIsRegCandidate()); + + // We don't actually need to spill if it is already living in memory + bool needsSpill = ((tree->gtFlags & GTF_VAR_DEF) == 0 && varDsc->lvIsInReg()); + if (needsSpill) + { + // In order for a lclVar to have been allocated to a register, it must not have been aliasable, and can + // therefore be store-normalized (rather than load-normalized). In fact, not performing store normalization + // can lead to problems on architectures where a lclVar may be allocated to a register that is not + // addressable at the granularity of the lclVar's defined type (e.g. x86). + var_types lclTyp = genActualType(varDsc->TypeGet()); + emitAttr size = emitTypeSize(lclTyp); + + bool restoreRegVar = false; + if (tree->gtOper == GT_REG_VAR) + { + tree->SetOper(GT_LCL_VAR); + restoreRegVar = true; + } + + // mask off the flag to generate the right spill code, then bring it back + tree->gtFlags &= ~GTF_REG_VAL; + + instruction storeIns = ins_Store(tree->TypeGet(), compiler->isSIMDTypeLocalAligned(varNum)); +#if CPU_LONG_USES_REGPAIR + if (varTypeIsMultiReg(tree)) + { + assert(varDsc->lvRegNum == genRegPairLo(tree->gtRegPair)); + assert(varDsc->lvOtherReg == genRegPairHi(tree->gtRegPair)); + regNumber regLo = genRegPairLo(tree->gtRegPair); + regNumber regHi = genRegPairHi(tree->gtRegPair); + inst_TT_RV(storeIns, tree, regLo); + inst_TT_RV(storeIns, tree, regHi, 4); + } + else +#endif + { + assert(varDsc->lvRegNum == tree->gtRegNum); + inst_TT_RV(storeIns, tree, tree->gtRegNum, 0, size); + } + tree->gtFlags |= GTF_REG_VAL; + + if (restoreRegVar) + { + tree->SetOper(GT_REG_VAR); + } + + genUpdateRegLife(varDsc, /*isBorn*/ false, /*isDying*/ true DEBUGARG(tree)); + gcInfo.gcMarkRegSetNpt(varDsc->lvRegMask()); + + if (VarSetOps::IsMember(compiler, gcInfo.gcTrkStkPtrLcls, varDsc->lvVarIndex)) + { +#ifdef DEBUG + if (!VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex)) + { + JITDUMP("\t\t\t\t\t\t\tVar V%02u becoming live\n", varNum); + } + else + { + JITDUMP("\t\t\t\t\t\t\tVar V%02u continuing live\n", varNum); + } +#endif + VarSetOps::AddElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex); + } + } + + tree->gtFlags &= ~GTF_SPILL; + varDsc->lvRegNum = REG_STK; + if (varTypeIsMultiReg(tree)) + { + varDsc->lvOtherReg = REG_STK; + } +} + +//------------------------------------------------------------------------ +// genUpdateVarReg: Update the current register location for a lclVar +// +// Arguments: +// varDsc - the LclVarDsc for the lclVar +// tree - the lclVar node +// +// inline +void CodeGenInterface::genUpdateVarReg(LclVarDsc* varDsc, GenTreePtr tree) +{ + assert(tree->OperIsScalarLocal() || (tree->gtOper == GT_COPY)); + varDsc->lvRegNum = tree->gtRegNum; +} + +//------------------------------------------------------------------------ +// sameRegAsDst: Return the child that has the same reg as the dst (if any) +// +// Arguments: +// tree - the node of interest +// other - an out parameter to return the other child +// +// Notes: +// If 'tree' has a child with the same assigned register as its target reg, +// that child will be returned, and 'other' will contain the non-matching child. +// Otherwise, both other and the return value will be nullptr. +// +GenTree* sameRegAsDst(GenTree* tree, GenTree*& other /*out*/) +{ + if (tree->gtRegNum == REG_NA) + { + other = nullptr; + return nullptr; + } + + GenTreePtr op1 = tree->gtOp.gtOp1; + GenTreePtr op2 = tree->gtOp.gtOp2; + if (op1->gtRegNum == tree->gtRegNum) + { + other = op2; + return op1; + } + if (op2->gtRegNum == tree->gtRegNum) + { + other = op1; + return op2; + } + else + { + other = nullptr; + return nullptr; + } +} + +//------------------------------------------------------------------------ +// genUnspillRegIfNeeded: Reload the value into a register, if needed +// +// Arguments: +// tree - the node of interest. +// +// Notes: +// In the normal case, the value will be reloaded into the register it +// was originally computed into. However, if that register is not available, +// the register allocator will have allocated a different register, and +// inserted a GT_RELOAD to indicate the register into which it should be +// reloaded. +// +void CodeGen::genUnspillRegIfNeeded(GenTree* tree) +{ + regNumber dstReg = tree->gtRegNum; + GenTree* unspillTree = tree; + + if (tree->gtOper == GT_RELOAD) + { + unspillTree = tree->gtOp.gtOp1; + } + + if ((unspillTree->gtFlags & GTF_SPILLED) != 0) + { + if (genIsRegCandidateLocal(unspillTree)) + { + // Reset spilled flag, since we are going to load a local variable from its home location. + unspillTree->gtFlags &= ~GTF_SPILLED; + + GenTreeLclVarCommon* lcl = unspillTree->AsLclVarCommon(); + LclVarDsc* varDsc = &compiler->lvaTable[lcl->gtLclNum]; + +// TODO-Cleanup: The following code could probably be further merged and cleaned up. +#ifdef _TARGET_XARCH_ + // Load local variable from its home location. + // In most cases the tree type will indicate the correct type to use for the load. + // However, if it is NOT a normalizeOnLoad lclVar (i.e. NOT a small int that always gets + // widened when loaded into a register), and its size is not the same as genActualType of + // the type of the lclVar, then we need to change the type of the tree node when loading. + // This situation happens due to "optimizations" that avoid a cast and + // simply retype the node when using long type lclVar as an int. + // While loading the int in that case would work for this use of the lclVar, if it is + // later used as a long, we will have incorrectly truncated the long. + // In the normalizeOnLoad case ins_Load will return an appropriate sign- or zero- + // extending load. + + var_types treeType = unspillTree->TypeGet(); + if (treeType != genActualType(varDsc->lvType) && !varTypeIsGC(treeType) && !varDsc->lvNormalizeOnLoad()) + { + assert(!varTypeIsGC(varDsc)); + var_types spillType = genActualType(varDsc->lvType); + unspillTree->gtType = spillType; + inst_RV_TT(ins_Load(spillType, compiler->isSIMDTypeLocalAligned(lcl->gtLclNum)), dstReg, unspillTree); + unspillTree->gtType = treeType; + } + else + { + inst_RV_TT(ins_Load(treeType, compiler->isSIMDTypeLocalAligned(lcl->gtLclNum)), dstReg, unspillTree); + } +#elif defined(_TARGET_ARM64_) + var_types targetType = unspillTree->gtType; + instruction ins = ins_Load(targetType, compiler->isSIMDTypeLocalAligned(lcl->gtLclNum)); + emitAttr attr = emitTypeSize(targetType); + emitter* emit = getEmitter(); + + // Fixes Issue #3326 + attr = emit->emitInsAdjustLoadStoreAttr(ins, attr); + + // Load local variable from its home location. + inst_RV_TT(ins, dstReg, unspillTree, 0, attr); +#else + NYI("Unspilling not implemented for this target architecture."); +#endif + unspillTree->SetInReg(); + + // TODO-Review: We would like to call: + // genUpdateRegLife(varDsc, /*isBorn*/ true, /*isDying*/ false DEBUGARG(tree)); + // instead of the following code, but this ends up hitting this assert: + // assert((regSet.rsMaskVars & regMask) == 0); + // due to issues with LSRA resolution moves. + // So, just force it for now. This probably indicates a condition that creates a GC hole! + // + // Extra note: I think we really want to call something like gcInfo.gcUpdateForRegVarMove, + // because the variable is not really going live or dead, but that method is somewhat poorly + // factored because it, in turn, updates rsMaskVars which is part of RegSet not GCInfo. + // TODO-Cleanup: This code exists in other CodeGen*.cpp files, and should be moved to CodeGenCommon.cpp. + + // Don't update the variable's location if we are just re-spilling it again. + + if ((unspillTree->gtFlags & GTF_SPILL) == 0) + { + genUpdateVarReg(varDsc, tree); +#ifdef DEBUG + if (VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex)) + { + JITDUMP("\t\t\t\t\t\t\tRemoving V%02u from gcVarPtrSetCur\n", lcl->gtLclNum); + } +#endif // DEBUG + VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex); + +#ifdef DEBUG + if (compiler->verbose) + { + printf("\t\t\t\t\t\t\tV%02u in reg ", lcl->gtLclNum); + varDsc->PrintVarReg(); + printf(" is becoming live "); + compiler->printTreeID(unspillTree); + printf("\n"); + } +#endif // DEBUG + + regSet.AddMaskVars(genGetRegMask(varDsc)); + } + + gcInfo.gcMarkRegPtrVal(dstReg, unspillTree->TypeGet()); + } + else if (unspillTree->IsMultiRegCall()) + { + GenTreeCall* call = unspillTree->AsCall(); + ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); + unsigned regCount = retTypeDesc->GetReturnRegCount(); + GenTreeCopyOrReload* reloadTree = nullptr; + if (tree->OperGet() == GT_RELOAD) + { + reloadTree = tree->AsCopyOrReload(); + } + + // In case of multi-reg call node, GTF_SPILLED flag on it indicates that + // one or more of its result regs are spilled. Call node needs to be + // queried to know which specific result regs to be unspilled. + for (unsigned i = 0; i < regCount; ++i) + { + unsigned flags = call->GetRegSpillFlagByIdx(i); + if ((flags & GTF_SPILLED) != 0) + { + var_types dstType = retTypeDesc->GetReturnRegType(i); + regNumber unspillTreeReg = call->GetRegNumByIdx(i); + + if (reloadTree != nullptr) + { + dstReg = reloadTree->GetRegNumByIdx(i); + if (dstReg == REG_NA) + { + dstReg = unspillTreeReg; + } + } + else + { + dstReg = unspillTreeReg; + } + + TempDsc* t = regSet.rsUnspillInPlace(call, unspillTreeReg, i); + getEmitter()->emitIns_R_S(ins_Load(dstType), emitActualTypeSize(dstType), dstReg, t->tdTempNum(), + 0); + compiler->tmpRlsTemp(t); + gcInfo.gcMarkRegPtrVal(dstReg, dstType); + } + } + + unspillTree->gtFlags &= ~GTF_SPILLED; + unspillTree->SetInReg(); + } + else + { + TempDsc* t = regSet.rsUnspillInPlace(unspillTree, unspillTree->gtRegNum); + getEmitter()->emitIns_R_S(ins_Load(unspillTree->gtType), emitActualTypeSize(unspillTree->TypeGet()), dstReg, + t->tdTempNum(), 0); + compiler->tmpRlsTemp(t); + + unspillTree->gtFlags &= ~GTF_SPILLED; + unspillTree->SetInReg(); + gcInfo.gcMarkRegPtrVal(dstReg, unspillTree->TypeGet()); + } + } +} + +//------------------------------------------------------------------------ +// genCopyRegIfNeeded: Copy the given node into the specified register +// +// Arguments: +// node - The node that has been evaluated (consumed). +// needReg - The register in which its value is needed. +// +// Notes: +// This must be a node that has a register. +// +void CodeGen::genCopyRegIfNeeded(GenTree* node, regNumber needReg) +{ + assert((node->gtRegNum != REG_NA) && (needReg != REG_NA)); + if (node->gtRegNum != needReg) + { + inst_RV_RV(INS_mov, needReg, node->gtRegNum, node->TypeGet()); + } +} + +// Do Liveness update for a subnodes that is being consumed by codegen +// including the logic for reload in case is needed and also takes care +// of locating the value on the desired register. +void CodeGen::genConsumeRegAndCopy(GenTree* node, regNumber needReg) +{ + if (needReg == REG_NA) + { + return; + } + regNumber treeReg = genConsumeReg(node); + genCopyRegIfNeeded(node, needReg); +} + +// Check that registers are consumed in the right order for the current node being generated. +#ifdef DEBUG +void CodeGen::genNumberOperandUse(GenTree* const operand, int& useNum) const +{ + assert(operand != nullptr); + assert(operand->gtUseNum == -1); + + // Ignore argument placeholders. + if (operand->OperGet() == GT_ARGPLACE) + { + return; + } + + if (!operand->isContained() && !operand->IsCopyOrReload()) + { + operand->gtUseNum = useNum; + useNum++; + } + else + { + for (GenTree* operand : operand->Operands()) + { + genNumberOperandUse(operand, useNum); + } + } +} + +void CodeGen::genCheckConsumeNode(GenTree* const node) +{ + assert(node != nullptr); + + if (verbose) + { + if ((node->gtDebugFlags & GTF_DEBUG_NODE_CG_CONSUMED) != 0) + { + printf("Node was consumed twice:\n"); + compiler->gtDispTree(node, nullptr, nullptr, true); + } + else if ((lastConsumedNode != nullptr) && (node->gtUseNum < lastConsumedNode->gtUseNum)) + { + printf("Nodes were consumed out-of-order:\n"); + compiler->gtDispTree(lastConsumedNode, nullptr, nullptr, true); + compiler->gtDispTree(node, nullptr, nullptr, true); + } + } + + assert((node->OperGet() == GT_CATCH_ARG) || ((node->gtDebugFlags & GTF_DEBUG_NODE_CG_CONSUMED) == 0)); + assert((lastConsumedNode == nullptr) || (node->gtUseNum == -1) || (node->gtUseNum > lastConsumedNode->gtUseNum)); + + node->gtDebugFlags |= GTF_DEBUG_NODE_CG_CONSUMED; + lastConsumedNode = node; +} +#endif // DEBUG + +//-------------------------------------------------------------------- +// genConsumeReg: Do liveness update for a subnode that is being +// consumed by codegen. +// +// Arguments: +// tree - GenTree node +// +// Return Value: +// Returns the reg number of tree. +// In case of multi-reg call node returns the first reg number +// of the multi-reg return. +regNumber CodeGen::genConsumeReg(GenTree* tree) +{ + if (tree->OperGet() == GT_COPY) + { + genRegCopy(tree); + } + + // Handle the case where we have a lclVar that needs to be copied before use (i.e. because it + // interferes with one of the other sources (or the target, if it's a "delayed use" register)). + // TODO-Cleanup: This is a special copyReg case in LSRA - consider eliminating these and + // always using GT_COPY to make the lclVar location explicit. + // Note that we have to do this before calling genUpdateLife because otherwise if we spill it + // the lvRegNum will be set to REG_STK and we will lose track of what register currently holds + // the lclVar (normally when a lclVar is spilled it is then used from its former register + // location, which matches the gtRegNum on the node). + // (Note that it doesn't matter if we call this before or after genUnspillRegIfNeeded + // because if it's on the stack it will always get reloaded into tree->gtRegNum). + if (genIsRegCandidateLocal(tree)) + { + GenTreeLclVarCommon* lcl = tree->AsLclVarCommon(); + LclVarDsc* varDsc = &compiler->lvaTable[lcl->GetLclNum()]; + if (varDsc->lvRegNum != REG_STK && varDsc->lvRegNum != tree->gtRegNum) + { + inst_RV_RV(ins_Copy(tree->TypeGet()), tree->gtRegNum, varDsc->lvRegNum); + } + } + + genUnspillRegIfNeeded(tree); + + // genUpdateLife() will also spill local var if marked as GTF_SPILL by calling CodeGen::genSpillVar + genUpdateLife(tree); + + assert(tree->gtHasReg()); + + // there are three cases where consuming a reg means clearing the bit in the live mask + // 1. it was not produced by a local + // 2. it was produced by a local that is going dead + // 3. it was produced by a local that does not live in that reg (like one allocated on the stack) + + if (genIsRegCandidateLocal(tree)) + { + GenTreeLclVarCommon* lcl = tree->AsLclVarCommon(); + LclVarDsc* varDsc = &compiler->lvaTable[lcl->GetLclNum()]; + assert(varDsc->lvLRACandidate); + + if ((tree->gtFlags & GTF_VAR_DEATH) != 0) + { + gcInfo.gcMarkRegSetNpt(genRegMask(varDsc->lvRegNum)); + } + else if (varDsc->lvRegNum == REG_STK) + { + // We have loaded this into a register only temporarily + gcInfo.gcMarkRegSetNpt(genRegMask(tree->gtRegNum)); + } + } + else + { + gcInfo.gcMarkRegSetNpt(tree->gtGetRegMask()); + } + + genCheckConsumeNode(tree); + return tree->gtRegNum; +} + +// Do liveness update for an address tree: one of GT_LEA, GT_LCL_VAR, or GT_CNS_INT (for call indirect). +void CodeGen::genConsumeAddress(GenTree* addr) +{ + if (!addr->isContained()) + { + genConsumeReg(addr); + } + else if (addr->OperGet() == GT_LEA) + { + genConsumeAddrMode(addr->AsAddrMode()); + } +} + +// do liveness update for a subnode that is being consumed by codegen +void CodeGen::genConsumeAddrMode(GenTreeAddrMode* addr) +{ + genConsumeOperands(addr); +} + +void CodeGen::genConsumeRegs(GenTree* tree) +{ +#if !defined(_TARGET_64BIT_) + if (tree->OperGet() == GT_LONG) + { + genConsumeRegs(tree->gtGetOp1()); + genConsumeRegs(tree->gtGetOp2()); + return; + } +#endif // !defined(_TARGET_64BIT_) + + if (tree->isContained()) + { + if (tree->isContainedSpillTemp()) + { + // spill temps are un-tracked and hence no need to update life + } + else if (tree->isIndir()) + { + genConsumeAddress(tree->AsIndir()->Addr()); + } + else if (tree->OperGet() == GT_AND) + { + // This is the special contained GT_AND that we created in Lowering::TreeNodeInfoInitCmp() + // Now we need to consume the operands of the GT_AND node. + genConsumeOperands(tree->AsOp()); + } +#ifdef _TARGET_XARCH_ + else if (tree->OperGet() == GT_LCL_VAR) + { + // A contained lcl var must be living on stack and marked as reg optional, or not be a + // register candidate. + unsigned varNum = tree->AsLclVarCommon()->GetLclNum(); + LclVarDsc* varDsc = compiler->lvaTable + varNum; + + noway_assert(varDsc->lvRegNum == REG_STK); + noway_assert(tree->IsRegOptional() || !varDsc->lvLRACandidate); + + // Update the life of the lcl var. + genUpdateLife(tree); + } +#endif // _TARGET_XARCH_ + else if (tree->OperIsInitVal()) + { + genConsumeReg(tree->gtGetOp1()); + } + else + { +#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->IsIntegralConstVector(0)); +#else + assert(tree->OperIsLeaf()); +#endif + } + } + else + { + genConsumeReg(tree); + } +} + +//------------------------------------------------------------------------ +// genConsumeOperands: Do liveness update for the operands of a unary or binary tree +// +// Arguments: +// tree - the GenTreeOp whose operands will have their liveness updated. +// +// Return Value: +// None. +// +// Notes: +// Note that this logic is localized here because we must do the liveness update in +// the correct execution order. This is important because we may have two operands +// that involve the same lclVar, and if one is marked "lastUse" we must handle it +// after the first. + +void CodeGen::genConsumeOperands(GenTreeOp* tree) +{ + GenTree* firstOp = tree->gtOp1; + GenTree* secondOp = tree->gtOp2; + if ((tree->gtFlags & GTF_REVERSE_OPS) != 0) + { + assert(secondOp != nullptr); + firstOp = secondOp; + secondOp = tree->gtOp1; + } + if (firstOp != nullptr) + { + genConsumeRegs(firstOp); + } + if (secondOp != nullptr) + { + genConsumeRegs(secondOp); + } +} + +#if FEATURE_PUT_STRUCT_ARG_STK +//------------------------------------------------------------------------ +// genConsumePutStructArgStk: Do liveness update for the operands of a PutArgStk node. +// Also loads in the right register the addresses of the +// src/dst for rep mov operation. +// +// Arguments: +// putArgNode - the PUTARG_STK tree. +// dstReg - the dstReg for the rep move operation. +// srcReg - the srcReg for the rep move operation. +// sizeReg - the sizeReg for the rep move operation. +// +// Return Value: +// None. +// +// Notes: +// sizeReg can be REG_NA when this function is used to consume the dstReg and srcReg +// for copying on the stack a struct with references. +// The source address/offset is determined from the address on the GT_OBJ node, while +// the destination address is the address contained in 'm_stkArgVarNum' plus the offset +// provided in the 'putArgNode'. +// m_stkArgVarNum must be set to the varnum for the local used for placing the "by-value" args on the stack. + +void CodeGen::genConsumePutStructArgStk(GenTreePutArgStk* putArgNode, + regNumber dstReg, + regNumber srcReg, + regNumber sizeReg) +{ + assert(varTypeIsStruct(putArgNode)); + + // The putArgNode children are always contained. We should not consume any registers. + assert(putArgNode->gtGetOp1()->isContained()); + + GenTree* dstAddr = putArgNode; + + // Get the source address. + GenTree* src = putArgNode->gtGetOp1(); + assert((src->gtOper == GT_OBJ) || ((src->gtOper == GT_IND && varTypeIsSIMD(src)))); + GenTree* srcAddr = src->gtGetOp1(); + + size_t size = putArgNode->getArgSize(); + + assert(dstReg != REG_NA); + assert(srcReg != REG_NA); + + // Consume the registers only if they are not contained or set to REG_NA. + if (srcAddr->gtRegNum != REG_NA) + { + genConsumeReg(srcAddr); + } + + // If the op1 is already in the dstReg - nothing to do. + // Otherwise load the op1 (GT_ADDR) into the dstReg to copy the struct on the stack by value. + CLANG_FORMAT_COMMENT_ANCHOR; + +#ifdef _TARGET_X86_ + assert(dstReg != REG_SPBASE); + inst_RV_RV(INS_mov, dstReg, REG_SPBASE); +#else // !_TARGET_X86_ + if (dstAddr->gtRegNum != dstReg) + { + // Generate LEA instruction to load the stack of the outgoing var + SlotNum offset (or the incoming arg area + // for tail calls) in RDI. + // Destination is always local (on the stack) - use EA_PTRSIZE. + assert(m_stkArgVarNum != BAD_VAR_NUM); + getEmitter()->emitIns_R_S(INS_lea, EA_PTRSIZE, dstReg, m_stkArgVarNum, putArgNode->getArgOffset()); + } +#endif // !_TARGET_X86_ + + if (srcAddr->gtRegNum != srcReg) + { + if (srcAddr->OperIsLocalAddr()) + { + // The OperLocalAddr is always contained. + assert(srcAddr->isContained()); + GenTreeLclVarCommon* lclNode = srcAddr->AsLclVarCommon(); + + // Generate LEA instruction to load the LclVar address in RSI. + // Source is known to be on the stack. Use EA_PTRSIZE. + unsigned int offset = 0; + if (srcAddr->OperGet() == GT_LCL_FLD_ADDR) + { + offset = srcAddr->AsLclFld()->gtLclOffs; + } + getEmitter()->emitIns_R_S(INS_lea, EA_PTRSIZE, srcReg, lclNode->gtLclNum, offset); + } + else + { + assert(srcAddr->gtRegNum != REG_NA); + // Source is not known to be on the stack. Use EA_BYREF. + getEmitter()->emitIns_R_R(INS_mov, EA_BYREF, srcReg, srcAddr->gtRegNum); + } + } + + if (sizeReg != REG_NA) + { + inst_RV_IV(INS_mov, sizeReg, size, EA_PTRSIZE); + } +} +#endif // FEATURE_PUT_STRUCT_ARG_STK + +//------------------------------------------------------------------------ +// genSetBlockSize: Ensure that the block size is in the given register +// +// Arguments: +// blkNode - The block node +// sizeReg - The register into which the block's size should go +// + +void CodeGen::genSetBlockSize(GenTreeBlk* blkNode, regNumber sizeReg) +{ + if (sizeReg != REG_NA) + { + unsigned blockSize = blkNode->Size(); + if (blockSize != 0) + { + assert((blkNode->gtRsvdRegs & genRegMask(sizeReg)) != 0); + genSetRegToIcon(sizeReg, blockSize); + } + else + { + noway_assert(blkNode->gtOper == GT_STORE_DYN_BLK); + GenTree* sizeNode = blkNode->AsDynBlk()->gtDynamicSize; + if (sizeNode->gtRegNum != sizeReg) + { + inst_RV_RV(INS_mov, sizeReg, sizeNode->gtRegNum, sizeNode->TypeGet()); + } + } + } +} + +//------------------------------------------------------------------------ +// genConsumeBlockSrc: Consume the source address register of a block node, if any. +// +// Arguments: +// blkNode - The block node + +void CodeGen::genConsumeBlockSrc(GenTreeBlk* blkNode) +{ + GenTree* src = blkNode->Data(); + if (blkNode->OperIsCopyBlkOp()) + { + // For a CopyBlk we need the address of the source. + if (src->OperGet() == GT_IND) + { + src = src->gtOp.gtOp1; + } + else + { + // This must be a local. + // For this case, there is no source address register, as it is a + // stack-based address. + assert(src->OperIsLocal()); + return; + } + } + else + { + if (src->OperIsInitVal()) + { + src = src->gtGetOp1(); + } + } + genConsumeReg(src); +} + +//------------------------------------------------------------------------ +// genSetBlockSrc: Ensure that the block source is in its allocated register. +// +// Arguments: +// blkNode - The block node +// srcReg - The register in which to set the source (address or init val). +// +void CodeGen::genSetBlockSrc(GenTreeBlk* blkNode, regNumber srcReg) +{ + GenTree* src = blkNode->Data(); + if (blkNode->OperIsCopyBlkOp()) + { + // For a CopyBlk we need the address of the source. + if (src->OperGet() == GT_IND) + { + src = src->gtOp.gtOp1; + } + else + { + // This must be a local struct. + // Load its address into srcReg. + inst_RV_TT(INS_lea, srcReg, src, 0, EA_BYREF); + return; + } + } + else + { + if (src->OperIsInitVal()) + { + src = src->gtGetOp1(); + } + } + genCopyRegIfNeeded(src, srcReg); +} + +//------------------------------------------------------------------------ +// genConsumeBlockOp: Ensure that the block's operands are enregistered +// as needed. +// Arguments: +// blkNode - The block node +// +// Notes: +// This ensures that the operands are consumed in the proper order to +// obey liveness modeling. + +void CodeGen::genConsumeBlockOp(GenTreeBlk* blkNode, regNumber dstReg, regNumber srcReg, regNumber sizeReg) +{ + // We have to consume the registers, and perform any copies, in the actual execution order. + // The nominal order is: dst, src, size. However this may have been changed + // with reverse flags on the blkNode and the setting of gtEvalSizeFirst in the case of a dynamic + // block size. + // Note that the register allocator ensures that the registers ON THE NODES will not interfere + // with one another if consumed (i.e. reloaded or moved to their ASSIGNED reg) in execution order. + // Further, it ensures that they will not interfere with one another if they are then copied + // to the REQUIRED register (if a fixed register requirement) in execution order. This requires, + // then, that we first consume all the operands, then do any necessary moves. + + GenTree* dstAddr = blkNode->Addr(); + GenTree* src = nullptr; + unsigned blockSize = blkNode->Size(); + GenTree* size = nullptr; + bool evalSizeFirst = true; + + // First, consume all the sources in order + if (blkNode->OperGet() == GT_STORE_DYN_BLK) + { + size = blkNode->AsDynBlk()->gtDynamicSize; + if (blkNode->AsDynBlk()->gtEvalSizeFirst) + { + genConsumeReg(size); + } + else + { + evalSizeFirst = false; + } + } + if (blkNode->IsReverseOp()) + { + + genConsumeBlockSrc(blkNode); + genConsumeReg(dstAddr); + } + else + { + genConsumeReg(dstAddr); + genConsumeBlockSrc(blkNode); + } + if (!evalSizeFirst) + { + noway_assert(size != nullptr); + genConsumeReg(size); + } + + // Next, perform any necessary moves. + if (evalSizeFirst) + { + genSetBlockSize(blkNode, sizeReg); + } + if (blkNode->IsReverseOp()) + { + genSetBlockSrc(blkNode, srcReg); + genCopyRegIfNeeded(dstAddr, dstReg); + } + else + { + genCopyRegIfNeeded(dstAddr, dstReg); + genSetBlockSrc(blkNode, srcReg); + } + if (!evalSizeFirst) + { + genSetBlockSize(blkNode, sizeReg); + } +} + +//------------------------------------------------------------------------- +// genProduceReg: do liveness update for register produced by the current +// node in codegen. +// +// Arguments: +// tree - Gentree node +// +// Return Value: +// None. +void CodeGen::genProduceReg(GenTree* tree) +{ +#ifdef DEBUG + assert((tree->gtDebugFlags & GTF_DEBUG_NODE_CG_PRODUCED) == 0); + tree->gtDebugFlags |= GTF_DEBUG_NODE_CG_PRODUCED; +#endif + + if (tree->gtFlags & GTF_SPILL) + { + // Code for GT_COPY node gets generated as part of consuming regs by its parent. + // A GT_COPY node in turn produces reg result and it should never be marked to + // spill. + // + // Similarly GT_RELOAD node gets generated as part of consuming regs by its + // parent and should never be marked for spilling. + noway_assert(!tree->IsCopyOrReload()); + + if (genIsRegCandidateLocal(tree)) + { + // Store local variable to its home location. + tree->gtFlags &= ~GTF_REG_VAL; + // Ensure that lclVar stores are typed correctly. + unsigned varNum = tree->gtLclVarCommon.gtLclNum; + assert(!compiler->lvaTable[varNum].lvNormalizeOnStore() || + (tree->TypeGet() == genActualType(compiler->lvaTable[varNum].TypeGet()))); + inst_TT_RV(ins_Store(tree->gtType, compiler->isSIMDTypeLocalAligned(varNum)), tree, tree->gtRegNum); + } + else + { + // In case of multi-reg call node, spill flag on call node + // indicates that one or more of its allocated regs need to + // be spilled. Call node needs to be further queried to + // know which of its result regs needs to be spilled. + if (tree->IsMultiRegCall()) + { + GenTreeCall* call = tree->AsCall(); + ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); + unsigned regCount = retTypeDesc->GetReturnRegCount(); + + for (unsigned i = 0; i < regCount; ++i) + { + unsigned flags = call->GetRegSpillFlagByIdx(i); + if ((flags & GTF_SPILL) != 0) + { + regNumber reg = call->GetRegNumByIdx(i); + call->SetInReg(); + regSet.rsSpillTree(reg, call, i); + gcInfo.gcMarkRegSetNpt(genRegMask(reg)); + } + } + } + else + { + tree->SetInReg(); + regSet.rsSpillTree(tree->gtRegNum, tree); + gcInfo.gcMarkRegSetNpt(genRegMask(tree->gtRegNum)); + } + + tree->gtFlags |= GTF_SPILLED; + tree->gtFlags &= ~GTF_SPILL; + + return; + } + } + + genUpdateLife(tree); + + // If we've produced a register, mark it as a pointer, as needed. + if (tree->gtHasReg()) + { + // We only mark the register in the following cases: + // 1. It is not a register candidate local. In this case, we're producing a + // register from a local, but the local is not a register candidate. Thus, + // we must be loading it as a temp register, and any "last use" flag on + // the register wouldn't be relevant. + // 2. The register candidate local is going dead. There's no point to mark + // the register as live, with a GC pointer, if the variable is dead. + if (!genIsRegCandidateLocal(tree) || ((tree->gtFlags & GTF_VAR_DEATH) == 0)) + { + // Multi-reg call node will produce more than one register result. + // Mark all the regs produced by call node. + if (tree->IsMultiRegCall()) + { + GenTreeCall* call = tree->AsCall(); + ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); + unsigned regCount = retTypeDesc->GetReturnRegCount(); + + for (unsigned i = 0; i < regCount; ++i) + { + regNumber reg = call->GetRegNumByIdx(i); + var_types type = retTypeDesc->GetReturnRegType(i); + gcInfo.gcMarkRegPtrVal(reg, type); + } + } + else if (tree->IsCopyOrReloadOfMultiRegCall()) + { + // we should never see reload of multi-reg call here + // because GT_RELOAD gets generated in reg consuming path. + noway_assert(tree->OperGet() == GT_COPY); + + // A multi-reg GT_COPY node produces those regs to which + // copy has taken place. + GenTreeCopyOrReload* copy = tree->AsCopyOrReload(); + GenTreeCall* call = copy->gtGetOp1()->AsCall(); + ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); + unsigned regCount = retTypeDesc->GetReturnRegCount(); + + for (unsigned i = 0; i < regCount; ++i) + { + var_types type = retTypeDesc->GetReturnRegType(i); + regNumber fromReg = call->GetRegNumByIdx(i); + regNumber toReg = copy->GetRegNumByIdx(i); + + if (toReg != REG_NA) + { + gcInfo.gcMarkRegPtrVal(toReg, type); + } + } + } + else + { + gcInfo.gcMarkRegPtrVal(tree->gtRegNum, tree->TypeGet()); + } + } + } + tree->SetInReg(); +} + +// transfer gc/byref status of src reg to dst reg +void CodeGen::genTransferRegGCState(regNumber dst, regNumber src) +{ + regMaskTP srcMask = genRegMask(src); + regMaskTP dstMask = genRegMask(dst); + + if (gcInfo.gcRegGCrefSetCur & srcMask) + { + gcInfo.gcMarkRegSetGCref(dstMask); + } + else if (gcInfo.gcRegByrefSetCur & srcMask) + { + gcInfo.gcMarkRegSetByref(dstMask); + } + else + { + gcInfo.gcMarkRegSetNpt(dstMask); + } +} + +// generates an ip-relative call or indirect call via reg ('call reg') +// pass in 'addr' for a relative call or 'base' for a indirect register call +// methHnd - optional, only used for pretty printing +// retSize - emitter type of return for GC purposes, should be EA_BYREF, EA_GCREF, or EA_PTRSIZE(not GC) +void CodeGen::genEmitCall(int callType, + CORINFO_METHOD_HANDLE methHnd, + INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) void* addr X86_ARG(ssize_t argSize), + emitAttr retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize), + IL_OFFSETX ilOffset, + regNumber base, + bool isJump, + bool isNoGC) +{ +#if !defined(_TARGET_X86_) + ssize_t argSize = 0; +#endif // !defined(_TARGET_X86_) + getEmitter()->emitIns_Call(emitter::EmitCallType(callType), methHnd, INDEBUG_LDISASM_COMMA(sigInfo) addr, argSize, + retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize), gcInfo.gcVarPtrSetCur, + gcInfo.gcRegGCrefSetCur, gcInfo.gcRegByrefSetCur, ilOffset, base, REG_NA, 0, 0, isJump, + emitter::emitNoGChelper(compiler->eeGetHelperNum(methHnd))); +} + +// generates an indirect call via addressing mode (call []) given an indir node +// methHnd - optional, only used for pretty printing +// retSize - emitter type of return for GC purposes, should be EA_BYREF, EA_GCREF, or EA_PTRSIZE(not GC) +void CodeGen::genEmitCall(int callType, + CORINFO_METHOD_HANDLE methHnd, + INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) GenTreeIndir* indir X86_ARG(ssize_t argSize), + emitAttr retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize), + IL_OFFSETX ilOffset) +{ +#if !defined(_TARGET_X86_) + ssize_t argSize = 0; +#endif // !defined(_TARGET_X86_) + genConsumeAddress(indir->Addr()); + + getEmitter()->emitIns_Call(emitter::EmitCallType(callType), methHnd, INDEBUG_LDISASM_COMMA(sigInfo) nullptr, + argSize, retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize), + gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, gcInfo.gcRegByrefSetCur, ilOffset, + indir->Base() ? indir->Base()->gtRegNum : REG_NA, + indir->Index() ? indir->Index()->gtRegNum : REG_NA, indir->Scale(), indir->Offset()); +} + +#endif // !LEGACY_BACKEND diff --git a/src/jit/codegenlinear.h b/src/jit/codegenlinear.h index fb0d6ea..406ab77 100644 --- a/src/jit/codegenlinear.h +++ b/src/jit/codegenlinear.h @@ -16,6 +16,10 @@ void genCodeForTreeNode(GenTreePtr treeNode); void genCodeForBinary(GenTreePtr treeNode); +#if defined(_TARGET_X86_) +void genCodeForLongUMod(GenTreeOp* node); +#endif // _TARGET_X86_ + void genCodeForDivMod(GenTreeOp* treeNode); void genCodeForMulHi(GenTreeOp* treeNode); @@ -24,6 +28,10 @@ void genLeaInstruction(GenTreeAddrMode* lea); void genSetRegToCond(regNumber dstReg, GenTreePtr tree); +#if !defined(_TARGET_64BIT_) +void genLongToIntCast(GenTreePtr treeNode); +#endif + void genIntToIntCast(GenTreePtr treeNode); void genFloatToFloatCast(GenTreePtr treeNode); @@ -36,7 +44,7 @@ void genCkfinite(GenTreePtr treeNode); void genIntrinsic(GenTreePtr treeNode); -void genPutArgStk(GenTreePtr treeNode); +void genPutArgStk(GenTreePutArgStk* treeNode); unsigned getBaseVarForPutArgStk(GenTreePtr treeNode); #if defined(_TARGET_XARCH_) || defined(_TARGET_ARM64_) @@ -49,7 +57,6 @@ void genCompareInt(GenTreePtr treeNode); #if !defined(_TARGET_64BIT_) void genCompareLong(GenTreePtr treeNode); -void genJTrueLong(GenTreePtr treeNode); #endif #ifdef FEATURE_SIMD @@ -61,7 +68,8 @@ enum SIMDScalarMoveType }; instruction getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_types baseType, unsigned* ival = nullptr); -void genSIMDScalarMove(var_types type, regNumber target, regNumber src, SIMDScalarMoveType moveType); +void genSIMDScalarMove( + var_types targetType, var_types type, regNumber target, regNumber src, SIMDScalarMoveType moveType); void genSIMDZero(var_types targetType, var_types baseType, regNumber targetReg); void genSIMDIntrinsicInit(GenTreeSIMD* simdNode); void genSIMDIntrinsicInitN(GenTreeSIMD* simdNode); @@ -87,7 +95,10 @@ void genSIMDCheck(GenTree* treeNode); void genStoreIndTypeSIMD12(GenTree* treeNode); void genStoreLclFldTypeSIMD12(GenTree* treeNode); void genLoadIndTypeSIMD12(GenTree* treeNode); -void genLoadLclFldTypeSIMD12(GenTree* treeNode); +void genLoadLclTypeSIMD12(GenTree* treeNode); +#ifdef _TARGET_X86_ +void genPutArgStkSIMD12(GenTree* treeNode); +#endif // _TARGET_X86_ #endif // FEATURE_SIMD #if !defined(_TARGET_64BIT_) @@ -104,6 +115,7 @@ void genUnspillRegIfNeeded(GenTree* tree); regNumber genConsumeReg(GenTree* tree); +void genCopyRegIfNeeded(GenTree* tree, regNumber needReg); void genConsumeRegAndCopy(GenTree* tree, regNumber needReg); void genConsumeIfReg(GenTreePtr tree) @@ -122,15 +134,14 @@ void genConsumeAddress(GenTree* addr); void genConsumeAddrMode(GenTreeAddrMode* mode); -void genConsumeBlockSize(GenTreeBlk* blkNode, regNumber sizeReg); -void genConsumeBlockDst(GenTreeBlk* blkNode); -GenTree* genConsumeBlockSrc(GenTreeBlk* blkNode); +void genSetBlockSize(GenTreeBlk* blkNode, regNumber sizeReg); +void genConsumeBlockSrc(GenTreeBlk* blkNode); +void genSetBlockSrc(GenTreeBlk* blkNode, regNumber srcReg); void genConsumeBlockOp(GenTreeBlk* blkNode, regNumber dstReg, regNumber srcReg, regNumber sizeReg); -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING -void genConsumePutStructArgStk( - GenTreePutArgStk* putArgStkNode, regNumber dstReg, regNumber srcReg, regNumber sizeReg, unsigned baseVarNum); -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING +#ifdef FEATURE_PUT_STRUCT_ARG_STK +void genConsumePutStructArgStk(GenTreePutArgStk* putArgStkNode, regNumber dstReg, regNumber srcReg, regNumber sizeReg); +#endif // FEATURE_PUT_STRUCT_ARG_STK void genConsumeRegs(GenTree* tree); @@ -142,6 +153,10 @@ void genSetRegToIcon(regNumber reg, ssize_t val, var_types type = TYP_INT, insFl void genCodeForShift(GenTreePtr tree); +#if defined(_TARGET_X86_) +void genCodeForShiftLong(GenTreePtr tree); +#endif + #ifdef _TARGET_XARCH_ void genCodeForShiftRMW(GenTreeStoreInd* storeInd); #endif // _TARGET_XARCH_ @@ -154,12 +169,23 @@ void genCodeForCpBlkRepMovs(GenTreeBlk* cpBlkNode); void genCodeForCpBlkUnroll(GenTreeBlk* cpBlkNode); -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING -void genPutStructArgStk(GenTreePtr treeNode, unsigned baseVarNum); +#ifdef FEATURE_PUT_STRUCT_ARG_STK +#ifdef _TARGET_X86_ +bool genAdjustStackForPutArgStk(GenTreePutArgStk* putArgStk); +void genPushReg(var_types type, regNumber srcReg); +void genPutArgStkFieldList(GenTreePutArgStk* putArgStk); +#endif // _TARGET_X86_ + +void genPutStructArgStk(GenTreePutArgStk* treeNode); -void genStructPutArgRepMovs(GenTreePutArgStk* putArgStkNode, unsigned baseVarNum); -void genStructPutArgUnroll(GenTreePutArgStk* putArgStkNode, unsigned baseVarNum); -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING +int genMove8IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset); +int genMove4IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset); +int genMove2IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset); +int genMove1IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset); +void genStructPutArgRepMovs(GenTreePutArgStk* putArgStkNode); +void genStructPutArgUnroll(GenTreePutArgStk* putArgStkNode); +void genStoreRegToStackArg(var_types type, regNumber reg, int offset); +#endif // FEATURE_PUT_STRUCT_ARG_STK void genCodeForLoadOffset(instruction ins, emitAttr size, regNumber dst, GenTree* base, unsigned offset); @@ -191,6 +217,14 @@ void genCallInstruction(GenTreePtr call); void genJmpMethod(GenTreePtr jmp); +BasicBlock* genCallFinally(BasicBlock* block, BasicBlock* lblk); + +#if FEATURE_EH_FUNCLETS +void genEHCatchRet(BasicBlock* block); +#else // !FEATURE_EH_FUNCLETS +void genEHFinallyOrFilterRet(BasicBlock* block); +#endif // !FEATURE_EH_FUNCLETS + void genMultiRegCallStoreToLocal(GenTreePtr treeNode); // Deals with codegen for muti-register struct returns. @@ -212,9 +246,19 @@ bool genIsRegCandidateLocal(GenTreePtr tree) return (varDsc->lvIsRegCandidate()); } +#ifdef FEATURE_PUT_STRUCT_ARG_STK +#ifdef _TARGET_X86_ +bool m_pushStkArg; +#else // !_TARGET_X86_ +unsigned m_stkArgVarNum; +unsigned m_stkArgOffset; +#endif // !_TARGET_X86_ +#endif // !FEATURE_PUT_STRUCT_ARG_STK + #ifdef DEBUG GenTree* lastConsumedNode; -void genCheckConsumeNode(GenTree* treeNode); +void genNumberOperandUse(GenTree* const operand, int& useNum) const; +void genCheckConsumeNode(GenTree* const node); #else // !DEBUG inline void genCheckConsumeNode(GenTree* treeNode) { diff --git a/src/jit/codegenxarch.cpp b/src/jit/codegenxarch.cpp index a41c286..8e0af48 100644 --- a/src/jit/codegenxarch.cpp +++ b/src/jit/codegenxarch.cpp @@ -24,114 +24,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #include "gcinfo.h" #include "gcinfoencoder.h" -// Get the register assigned to the given node - -regNumber CodeGenInterface::genGetAssignedReg(GenTreePtr tree) -{ - return tree->gtRegNum; -} - -//------------------------------------------------------------------------ -// genSpillVar: Spill a local variable -// -// Arguments: -// tree - the lclVar node for the variable being spilled -// -// Return Value: -// None. -// -// Assumptions: -// The lclVar must be a register candidate (lvRegCandidate) - -void CodeGen::genSpillVar(GenTreePtr tree) -{ - unsigned varNum = tree->gtLclVarCommon.gtLclNum; - LclVarDsc* varDsc = &(compiler->lvaTable[varNum]); - - assert(varDsc->lvIsRegCandidate()); - - // We don't actually need to spill if it is already living in memory - bool needsSpill = ((tree->gtFlags & GTF_VAR_DEF) == 0 && varDsc->lvIsInReg()); - if (needsSpill) - { - var_types lclTyp = varDsc->TypeGet(); - if (varDsc->lvNormalizeOnStore()) - { - lclTyp = genActualType(lclTyp); - } - emitAttr size = emitTypeSize(lclTyp); - - bool restoreRegVar = false; - if (tree->gtOper == GT_REG_VAR) - { - tree->SetOper(GT_LCL_VAR); - restoreRegVar = true; - } - - // mask off the flag to generate the right spill code, then bring it back - tree->gtFlags &= ~GTF_REG_VAL; - - instruction storeIns = ins_Store(tree->TypeGet(), compiler->isSIMDTypeLocalAligned(varNum)); -#if CPU_LONG_USES_REGPAIR - if (varTypeIsMultiReg(tree)) - { - assert(varDsc->lvRegNum == genRegPairLo(tree->gtRegPair)); - assert(varDsc->lvOtherReg == genRegPairHi(tree->gtRegPair)); - regNumber regLo = genRegPairLo(tree->gtRegPair); - regNumber regHi = genRegPairHi(tree->gtRegPair); - inst_TT_RV(storeIns, tree, regLo); - inst_TT_RV(storeIns, tree, regHi, 4); - } - else -#endif - { - assert(varDsc->lvRegNum == tree->gtRegNum); - inst_TT_RV(storeIns, tree, tree->gtRegNum, 0, size); - } - tree->gtFlags |= GTF_REG_VAL; - - if (restoreRegVar) - { - tree->SetOper(GT_REG_VAR); - } - - genUpdateRegLife(varDsc, /*isBorn*/ false, /*isDying*/ true DEBUGARG(tree)); - gcInfo.gcMarkRegSetNpt(varDsc->lvRegMask()); - - if (VarSetOps::IsMember(compiler, gcInfo.gcTrkStkPtrLcls, varDsc->lvVarIndex)) - { -#ifdef DEBUG - if (!VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex)) - { - JITDUMP("\t\t\t\t\t\t\tVar V%02u becoming live\n", varNum); - } - else - { - JITDUMP("\t\t\t\t\t\t\tVar V%02u continuing live\n", varNum); - } -#endif - VarSetOps::AddElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex); - } - } - - tree->gtFlags &= ~GTF_SPILL; - varDsc->lvRegNum = REG_STK; - if (varTypeIsMultiReg(tree)) - { - varDsc->lvOtherReg = REG_STK; - } -} - -// inline -void CodeGenInterface::genUpdateVarReg(LclVarDsc* varDsc, GenTreePtr tree) -{ - assert(tree->OperIsScalarLocal() || (tree->gtOper == GT_COPY)); - varDsc->lvRegNum = tree->gtRegNum; -} - -/*****************************************************************************/ -/*****************************************************************************/ - /***************************************************************************** * * Generate code that will set the given register to the integer constant. @@ -231,6 +123,8 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) } regNumber regGSCheck; + regMaskTP regMaskGSCheck = RBM_NONE; + if (!pushReg) { // Non-tail call: we can use any callee trash register that is not @@ -251,8 +145,11 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) else { #ifdef _TARGET_X86_ - NYI_X86("Tail calls from methods that need GS check"); - regGSCheck = REG_NA; + // It doesn't matter which register we pick, since we're going to save and restore it + // around the check. + // TODO-CQ: Can we optimize the choice of register to avoid doing the push/pop sometimes? + regGSCheck = REG_EAX; + regMaskGSCheck = RBM_EAX; #else // !_TARGET_X86_ // Tail calls from methods that need GS check: We need to preserve registers while // emitting GS cookie check for a tail prefixed call or a jmp. To emit GS cookie @@ -287,8 +184,13 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) #endif // !_TARGET_X86_ } + regMaskTP byrefPushedRegs = RBM_NONE; + regMaskTP norefPushedRegs = RBM_NONE; + regMaskTP pushedRegs = RBM_NONE; + if (compiler->gsGlobalSecurityCookieAddr == nullptr) { +#if defined(_TARGET_AMD64_) // If GS cookie value fits within 32-bits we can use 'cmp mem64, imm32'. // Otherwise, load the value into a reg and use 'cmp mem64, reg64'. if ((int)compiler->gsGlobalSecurityCookieVal != (ssize_t)compiler->gsGlobalSecurityCookieVal) @@ -297,7 +199,9 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) getEmitter()->emitIns_S_R(INS_cmp, EA_PTRSIZE, regGSCheck, compiler->lvaGSSecurityCookie, 0); } else +#endif // defined(_TARGET_AMD64_) { + assert((int)compiler->gsGlobalSecurityCookieVal == (ssize_t)compiler->gsGlobalSecurityCookieVal); getEmitter()->emitIns_S_I(INS_cmp, EA_PTRSIZE, compiler->lvaGSSecurityCookie, 0, (int)compiler->gsGlobalSecurityCookieVal); } @@ -305,6 +209,9 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) else { // Ngen case - GS cookie value needs to be accessed through an indirection. + + pushedRegs = genPushRegs(regMaskGSCheck, &byrefPushedRegs, &norefPushedRegs); + instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, regGSCheck, (ssize_t)compiler->gsGlobalSecurityCookieAddr); getEmitter()->emitIns_R_AR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, regGSCheck, regGSCheck, 0); getEmitter()->emitIns_S_R(INS_cmp, EA_PTRSIZE, regGSCheck, compiler->lvaGSSecurityCookie, 0); @@ -315,1612 +222,1078 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) inst_JMP(jmpEqual, gsCheckBlk); genEmitHelperCall(CORINFO_HELP_FAIL_FAST, 0, EA_UNKNOWN); genDefineTempLabel(gsCheckBlk); -} -/***************************************************************************** - * - * Generate code for all the basic blocks in the function. - */ + genPopRegs(pushedRegs, byrefPushedRegs, norefPushedRegs); +} -void CodeGen::genCodeForBBlist() +BasicBlock* CodeGen::genCallFinally(BasicBlock* block, BasicBlock* lblk) { - unsigned varNum; - LclVarDsc* varDsc; - - unsigned savedStkLvl; - -#ifdef DEBUG - genInterruptibleUsed = true; - - // You have to be careful if you create basic blocks from now on - compiler->fgSafeBasicBlockCreation = false; +#if FEATURE_EH_FUNCLETS + // Generate a call to the finally, like this: + // mov rcx,qword ptr [rbp + 20H] // Load rcx with PSPSym + // call finally-funclet + // jmp finally-return // Only for non-retless finally calls + // The jmp can be a NOP if we're going to the next block. + // If we're generating code for the main function (not a funclet), and there is no localloc, + // then RSP at this point is the same value as that stored in the PSPSym. So just copy RSP + // instead of loading the PSPSym in this case, or if PSPSym is not used (CoreRT ABI). - // This stress mode is not comptible with fully interruptible GC - if (genInterruptible && compiler->opts.compStackCheckOnCall) + if ((compiler->lvaPSPSym == BAD_VAR_NUM) || + (!compiler->compLocallocUsed && (compiler->funCurrentFunc()->funKind == FUNC_ROOT))) + { + inst_RV_RV(INS_mov, REG_ARG_0, REG_SPBASE, TYP_I_IMPL); + } + else { - compiler->opts.compStackCheckOnCall = false; + getEmitter()->emitIns_R_S(ins_Load(TYP_I_IMPL), EA_PTRSIZE, REG_ARG_0, compiler->lvaPSPSym, 0); } + getEmitter()->emitIns_J(INS_call, block->bbJumpDest); + + if (block->bbFlags & BBF_RETLESS_CALL) + { + // We have a retless call, and the last instruction generated was a call. + // If the next block is in a different EH region (or is the end of the code + // block), then we need to generate a breakpoint here (since it will never + // get executed) to get proper unwind behavior. - // This stress mode is not comptible with fully interruptible GC - if (genInterruptible && compiler->opts.compStackCheckOnRet) + if ((block->bbNext == nullptr) || !BasicBlock::sameEHRegion(block, block->bbNext)) + { + instGen(INS_BREAKPOINT); // This should never get executed + } + } + else { - compiler->opts.compStackCheckOnRet = false; + // Because of the way the flowgraph is connected, the liveness info for this one instruction + // after the call is not (can not be) correct in cases where a variable has a last use in the + // handler. So turn off GC reporting for this single instruction. + getEmitter()->emitDisableGC(); + + // Now go to where the finally funclet needs to return to. + if (block->bbNext->bbJumpDest == block->bbNext->bbNext) + { + // Fall-through. + // TODO-XArch-CQ: Can we get rid of this instruction, and just have the call return directly + // to the next instruction? This would depend on stack walking from within the finally + // handler working without this instruction being in this special EH region. + instGen(INS_nop); + } + else + { + inst_JMP(EJ_jmp, block->bbNext->bbJumpDest); + } + + getEmitter()->emitEnableGC(); } -#endif // DEBUG - // Prepare the blocks for exception handling codegen: mark the blocks that needs labels. - genPrepForEHCodegen(); +#else // !FEATURE_EH_FUNCLETS - assert(!compiler->fgFirstBBScratch || - compiler->fgFirstBB == compiler->fgFirstBBScratch); // compiler->fgFirstBBScratch has to be first. + // If we are about to invoke a finally locally from a try block, we have to set the ShadowSP slot + // corresponding to the finally's nesting level. When invoked in response to an exception, the + // EE does this. + // + // We have a BBJ_CALLFINALLY followed by a BBJ_ALWAYS. + // + // We will emit : + // mov [ebp - (n + 1)], 0 + // mov [ebp - n ], 0xFC + // push &step + // jmp finallyBlock + // ... + // step: + // mov [ebp - n ], 0 + // jmp leaveTarget + // ... + // leaveTarget: + + noway_assert(isFramePointerUsed()); + + // Get the nesting level which contains the finally + unsigned finallyNesting = 0; + compiler->fgGetNestingLevel(block, &finallyNesting); - /* Initialize the spill tracking logic */ + // The last slot is reserved for ICodeManager::FixContext(ppEndRegion) + unsigned filterEndOffsetSlotOffs; + filterEndOffsetSlotOffs = (unsigned)(compiler->lvaLclSize(compiler->lvaShadowSPslotsVar) - TARGET_POINTER_SIZE); - regSet.rsSpillBeg(); + unsigned curNestingSlotOffs; + curNestingSlotOffs = (unsigned)(filterEndOffsetSlotOffs - ((finallyNesting + 1) * TARGET_POINTER_SIZE)); -#ifdef DEBUGGING_SUPPORT - /* Initialize the line# tracking logic */ + // Zero out the slot for the next nesting level + instGen_Store_Imm_Into_Lcl(TYP_I_IMPL, EA_PTRSIZE, 0, compiler->lvaShadowSPslotsVar, + curNestingSlotOffs - TARGET_POINTER_SIZE); + instGen_Store_Imm_Into_Lcl(TYP_I_IMPL, EA_PTRSIZE, LCL_FINALLY_MARK, compiler->lvaShadowSPslotsVar, + curNestingSlotOffs); - if (compiler->opts.compScopeInfo) + // Now push the address where the finally funclet should return to directly. + if (!(block->bbFlags & BBF_RETLESS_CALL)) { - siInit(); + assert(block->isBBCallAlwaysPair()); + getEmitter()->emitIns_J(INS_push_hide, block->bbNext->bbJumpDest); } -#endif - - // The current implementation of switch tables requires the first block to have a label so it - // can generate offsets to the switch label targets. - // TODO-XArch-CQ: remove this when switches have been re-implemented to not use this. - if (compiler->fgHasSwitch) + else { - compiler->fgFirstBB->bbFlags |= BBF_JMP_TARGET; + // EE expects a DWORD, so we give him 0 + inst_IV(INS_push_hide, 0); } - genPendingCallLabel = nullptr; - - /* Initialize the pointer tracking code */ + // Jump to the finally BB + inst_JMP(EJ_jmp, block->bbJumpDest); - gcInfo.gcRegPtrSetInit(); - gcInfo.gcVarPtrSetInit(); - - /* If any arguments live in registers, mark those regs as such */ +#endif // !FEATURE_EH_FUNCLETS - for (varNum = 0, varDsc = compiler->lvaTable; varNum < compiler->lvaCount; varNum++, varDsc++) + // The BBJ_ALWAYS is used because the BBJ_CALLFINALLY can't point to the + // jump target using bbJumpDest - that is already used to point + // to the finally block. So just skip past the BBJ_ALWAYS unless the + // block is RETLESS. + if (!(block->bbFlags & BBF_RETLESS_CALL)) { - /* Is this variable a parameter assigned to a register? */ + assert(block->isBBCallAlwaysPair()); - if (!varDsc->lvIsParam || !varDsc->lvRegister) - { - continue; - } + lblk = block; + block = block->bbNext; + } + return block; +} - /* Is the argument live on entry to the method? */ +#if FEATURE_EH_FUNCLETS +void CodeGen::genEHCatchRet(BasicBlock* block) +{ + // Set RAX to the address the VM should return to after the catch. + // Generate a RIP-relative + // lea reg, [rip + disp32] ; the RIP is implicit + // which will be position-indepenent. + getEmitter()->emitIns_R_L(INS_lea, EA_PTR_DSP_RELOC, block->bbJumpDest, REG_INTRET); +} - if (!VarSetOps::IsMember(compiler, compiler->fgFirstBB->bbLiveIn, varDsc->lvVarIndex)) - { - continue; - } +#else // !FEATURE_EH_FUNCLETS - /* Is this a floating-point argument? */ +void CodeGen::genEHFinallyOrFilterRet(BasicBlock* block) +{ + // The last statement of the block must be a GT_RETFILT, which has already been generated. + assert(block->lastNode() != nullptr); + assert(block->lastNode()->OperGet() == GT_RETFILT); - if (varDsc->IsFloatRegType()) - { - continue; - } + if (block->bbJumpKind == BBJ_EHFINALLYRET) + { + assert(block->lastNode()->gtOp.gtOp1 == nullptr); // op1 == nullptr means endfinally - noway_assert(!varTypeIsFloating(varDsc->TypeGet())); + // Return using a pop-jmp sequence. As the "try" block calls + // the finally with a jmp, this leaves the x86 call-ret stack + // balanced in the normal flow of path. - /* Mark the register as holding the variable */ + noway_assert(isFramePointerRequired()); + inst_RV(INS_pop_hide, REG_EAX, TYP_I_IMPL); + inst_RV(INS_i_jmp, REG_EAX, TYP_I_IMPL); + } + else + { + assert(block->bbJumpKind == BBJ_EHFILTERRET); - regTracker.rsTrackRegLclVar(varDsc->lvRegNum, varNum); + // The return value has already been computed. + instGen_Return(0); } +} - unsigned finallyNesting = 0; +#endif // !FEATURE_EH_FUNCLETS - // Make sure a set is allocated for compiler->compCurLife (in the long case), so we can set it to empty without - // allocation at the start of each basic block. - VarSetOps::AssignNoCopy(compiler, compiler->compCurLife, VarSetOps::MakeEmpty(compiler)); +// Move an immediate value into an integer register - /*------------------------------------------------------------------------- - * - * Walk the basic blocks and generate code for each one - * - */ +void CodeGen::instGen_Set_Reg_To_Imm(emitAttr size, regNumber reg, ssize_t imm, insFlags flags) +{ + // reg cannot be a FP register + assert(!genIsValidFloatReg(reg)); - BasicBlock* block; - BasicBlock* lblk; /* previous block */ + if (!compiler->opts.compReloc) + { + size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs + } - for (lblk = nullptr, block = compiler->fgFirstBB; block != nullptr; lblk = block, block = block->bbNext) + if ((imm == 0) && !EA_IS_RELOC(size)) { -#ifdef DEBUG - if (compiler->verbose) + instGen_Set_Reg_To_Zero(size, reg, flags); + } + else + { + if (genDataIndirAddrCanBeEncodedAsPCRelOffset(imm)) + { + getEmitter()->emitIns_R_AI(INS_lea, EA_PTR_DSP_RELOC, reg, imm); + } + else { - printf("\n=============== Generating "); - block->dspBlockHeader(compiler, true, true); - compiler->fgDispBBLiveness(block); + getEmitter()->emitIns_R_I(INS_mov, size, reg, imm); } -#endif // DEBUG - - // Figure out which registers hold variables on entry to this block - - regSet.ClearMaskVars(); - gcInfo.gcRegGCrefSetCur = RBM_NONE; - gcInfo.gcRegByrefSetCur = RBM_NONE; - - compiler->m_pLinearScan->recordVarLocationsAtStartOfBB(block); - - genUpdateLife(block->bbLiveIn); + } + regTracker.rsTrackRegIntCns(reg, imm); +} - // Even if liveness didn't change, we need to update the registers containing GC references. - // genUpdateLife will update the registers live due to liveness changes. But what about registers that didn't - // change? We cleared them out above. Maybe we should just not clear them out, but update the ones that change - // here. That would require handling the changes in recordVarLocationsAtStartOfBB(). +/*********************************************************************************** + * + * Generate code to set a register 'targetReg' of type 'targetType' to the constant + * specified by the constant (GT_CNS_INT or GT_CNS_DBL) in 'tree'. This does not call + * genProduceReg() on the target register. + */ +void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTreePtr tree) +{ - regMaskTP newLiveRegSet = RBM_NONE; - regMaskTP newRegGCrefSet = RBM_NONE; - regMaskTP newRegByrefSet = RBM_NONE; -#ifdef DEBUG - VARSET_TP VARSET_INIT_NOCOPY(removedGCVars, VarSetOps::MakeEmpty(compiler)); - VARSET_TP VARSET_INIT_NOCOPY(addedGCVars, VarSetOps::MakeEmpty(compiler)); -#endif - VARSET_ITER_INIT(compiler, iter, block->bbLiveIn, varIndex); - while (iter.NextElem(compiler, &varIndex)) + switch (tree->gtOper) + { + case GT_CNS_INT: { - unsigned varNum = compiler->lvaTrackedToVarNum[varIndex]; - LclVarDsc* varDsc = &(compiler->lvaTable[varNum]); + // relocatable values tend to come down as a CNS_INT of native int type + // so the line between these two opcodes is kind of blurry + GenTreeIntConCommon* con = tree->AsIntConCommon(); + ssize_t cnsVal = con->IconValue(); - if (varDsc->lvIsInReg()) + if (con->ImmedValNeedsReloc(compiler)) { - newLiveRegSet |= varDsc->lvRegMask(); - if (varDsc->lvType == TYP_REF) - { - newRegGCrefSet |= varDsc->lvRegMask(); - } - else if (varDsc->lvType == TYP_BYREF) - { - newRegByrefSet |= varDsc->lvRegMask(); - } -#ifdef DEBUG - if (verbose && VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varIndex)) - { - VarSetOps::AddElemD(compiler, removedGCVars, varIndex); - } -#endif // DEBUG - VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varIndex); + instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, targetReg, cnsVal); + regTracker.rsTrackRegTrash(targetReg); } - else if (compiler->lvaIsGCTracked(varDsc)) + else { -#ifdef DEBUG - if (verbose && !VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varIndex)) - { - VarSetOps::AddElemD(compiler, addedGCVars, varIndex); - } -#endif // DEBUG - VarSetOps::AddElemD(compiler, gcInfo.gcVarPtrSetCur, varIndex); + genSetRegToIcon(targetReg, cnsVal, targetType); } } + break; - regSet.rsMaskVars = newLiveRegSet; - -#ifdef DEBUG - if (compiler->verbose) + case GT_CNS_DBL: { - if (!VarSetOps::IsEmpty(compiler, addedGCVars)) - { - printf("\t\t\t\t\t\t\tAdded GCVars: "); - dumpConvertedVarSet(compiler, addedGCVars); - printf("\n"); - } - if (!VarSetOps::IsEmpty(compiler, removedGCVars)) + double constValue = tree->gtDblCon.gtDconVal; + + // Make sure we use "xorpd reg, reg" only for +ve zero constant (0.0) and not for -ve zero (-0.0) + if (*(__int64*)&constValue == 0) { - printf("\t\t\t\t\t\t\tRemoved GCVars: "); - dumpConvertedVarSet(compiler, removedGCVars); - printf("\n"); + // A faster/smaller way to generate 0 + instruction ins = genGetInsForOper(GT_XOR, targetType); + inst_RV_RV(ins, targetReg, targetReg, targetType); } - } -#endif // DEBUG - - gcInfo.gcMarkRegSetGCref(newRegGCrefSet DEBUGARG(true)); - gcInfo.gcMarkRegSetByref(newRegByrefSet DEBUGARG(true)); - - /* Blocks with handlerGetsXcptnObj()==true use GT_CATCH_ARG to - represent the exception object (TYP_REF). - We mark REG_EXCEPTION_OBJECT as holding a GC object on entry - to the block, it will be the first thing evaluated - (thanks to GTF_ORDER_SIDEEFF). - */ - - if (handlerGetsXcptnObj(block->bbCatchTyp)) - { - for (GenTree* node : LIR::AsRange(block)) + else { - if (node->OperGet() == GT_CATCH_ARG) + GenTreePtr cns; + if (targetType == TYP_FLOAT) { - gcInfo.gcMarkRegSetGCref(RBM_EXCEPTION_OBJECT); - break; + float f = forceCastToFloat(constValue); + cns = genMakeConst(&f, targetType, tree, false); + } + else + { + cns = genMakeConst(&constValue, targetType, tree, true); } + + inst_RV_TT(ins_Load(targetType), targetReg, cns); } } + break; - /* Start a new code output block */ - - genUpdateCurrentFunclet(block); + default: + unreached(); + } +} - if (genAlignLoops && block->bbFlags & BBF_LOOP_HEAD) - { - getEmitter()->emitLoopAlign(); - } +// Generate code to get the high N bits of a N*N=2N bit multiplication result +void CodeGen::genCodeForMulHi(GenTreeOp* treeNode) +{ + if (treeNode->OperGet() == GT_MULHI) + { + assert(!(treeNode->gtFlags & GTF_UNSIGNED)); + } + assert(!treeNode->gtOverflowEx()); -#ifdef DEBUG - if (compiler->opts.dspCode) - { - printf("\n L_M%03u_BB%02u:\n", Compiler::s_compMethodsCount, block->bbNum); - } -#endif + regNumber targetReg = treeNode->gtRegNum; + var_types targetType = treeNode->TypeGet(); + emitter* emit = getEmitter(); + emitAttr size = emitTypeSize(treeNode); + GenTree* op1 = treeNode->gtOp.gtOp1; + GenTree* op2 = treeNode->gtOp.gtOp2; - block->bbEmitCookie = nullptr; + // to get the high bits of the multiply, we are constrained to using the + // 1-op form: RDX:RAX = RAX * rm + // The 3-op form (Rx=Ry*Rz) does not support it. - if (block->bbFlags & (BBF_JMP_TARGET | BBF_HAS_LABEL)) - { - /* Mark a label and update the current set of live GC refs */ + genConsumeOperands(treeNode->AsOp()); - block->bbEmitCookie = getEmitter()->emitAddLabel(gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, - gcInfo.gcRegByrefSetCur, FALSE); - } + GenTree* regOp = op1; + GenTree* rmOp = op2; - if (block == compiler->fgFirstColdBlock) - { -#ifdef DEBUG - if (compiler->verbose) - { - printf("\nThis is the start of the cold region of the method\n"); - } -#endif - // We should never have a block that falls through into the Cold section - noway_assert(!lblk->bbFallsThrough()); - - // We require the block that starts the Cold section to have a label - noway_assert(block->bbEmitCookie); - getEmitter()->emitSetFirstColdIGCookie(block->bbEmitCookie); - } - - /* Both stacks are always empty on entry to a basic block */ + // Set rmOp to the contained memory operand (if any) + if (op1->isContained() || (!op2->isContained() && (op2->gtRegNum == REG_RAX))) + { + regOp = op2; + rmOp = op1; + } + assert(!regOp->isContained()); - genStackLevel = 0; + // Setup targetReg when neither of the source operands was a matching register + if (regOp->gtRegNum != REG_RAX) + { + inst_RV_RV(ins_Copy(targetType), REG_RAX, regOp->gtRegNum, targetType); + } - savedStkLvl = genStackLevel; + instruction ins; + if ((treeNode->gtFlags & GTF_UNSIGNED) == 0) + { + ins = INS_imulEAX; + } + else + { + ins = INS_mulEAX; + } + emit->emitInsBinary(ins, size, treeNode, rmOp); - /* Tell everyone which basic block we're working on */ + // Move the result to the desired register, if necessary + if (treeNode->OperGet() == GT_MULHI && targetReg != REG_RDX) + { + inst_RV_RV(INS_mov, targetReg, REG_RDX, targetType); + } +} - compiler->compCurBB = block; +#ifdef _TARGET_X86_ +//------------------------------------------------------------------------ +// genCodeForLongUMod: Generate code for a tree of the form +// `(umod (gt_long x y) (const int))` +// +// Arguments: +// node - the node for which to generate code +// +void CodeGen::genCodeForLongUMod(GenTreeOp* node) +{ + assert(node != nullptr); + assert(node->OperGet() == GT_UMOD); + assert(node->TypeGet() == TYP_INT); -#ifdef DEBUGGING_SUPPORT - siBeginBlock(block); + GenTreeOp* const dividend = node->gtOp1->AsOp(); + assert(dividend->OperGet() == GT_LONG); + assert(varTypeIsLong(dividend)); - // BBF_INTERNAL blocks don't correspond to any single IL instruction. - if (compiler->opts.compDbgInfo && (block->bbFlags & BBF_INTERNAL) && - !compiler->fgBBisScratch(block)) // If the block is the distinguished first scratch block, then no need to - // emit a NO_MAPPING entry, immediately after the prolog. - { - genIPmappingAdd((IL_OFFSETX)ICorDebugInfo::NO_MAPPING, true); - } + genConsumeOperands(node); - bool firstMapping = true; -#endif // DEBUGGING_SUPPORT + GenTree* const dividendLo = dividend->gtOp1; + GenTree* const dividendHi = dividend->gtOp2; + assert(!dividendLo->isContained()); + assert(!dividendHi->isContained()); - /*--------------------------------------------------------------------- - * - * Generate code for each statement-tree in the block - * - */ - CLANG_FORMAT_COMMENT_ANCHOR; + GenTree* const divisor = node->gtOp2; + assert(divisor->gtSkipReloadOrCopy()->OperGet() == GT_CNS_INT); + assert(!divisor->gtSkipReloadOrCopy()->isContained()); + assert(divisor->gtSkipReloadOrCopy()->AsIntCon()->gtIconVal >= 2); + assert(divisor->gtSkipReloadOrCopy()->AsIntCon()->gtIconVal <= 0x3fffffff); -#if FEATURE_EH_FUNCLETS - if (block->bbFlags & BBF_FUNCLET_BEG) - { - genReserveFuncletProlog(block); - } -#endif // FEATURE_EH_FUNCLETS + // dividendLo must be in RAX; dividendHi must be in RDX + genCopyRegIfNeeded(dividendLo, REG_EAX); + genCopyRegIfNeeded(dividendHi, REG_EDX); - // Clear compCurStmt and compCurLifeTree. - compiler->compCurStmt = nullptr; - compiler->compCurLifeTree = nullptr; + // At this point, EAX:EDX contains the 64bit dividend and op2->gtRegNum + // contains the 32bit divisor. We want to generate the following code: + // + // cmp edx, divisor->gtRegNum + // jb noOverflow + // + // mov temp, eax + // mov eax, edx + // xor edx, edx + // div divisor->gtRegNum + // mov eax, temp + // + // noOverflow: + // div divisor->gtRegNum + // + // This works because (a * 2^32 + b) % c = ((a % c) * 2^32 + b) % c. + + BasicBlock* const noOverflow = genCreateTempLabel(); + + // cmp edx, divisor->gtRegNum + // jb noOverflow + inst_RV_RV(INS_cmp, REG_EDX, divisor->gtRegNum); + inst_JMP(EJ_jb, noOverflow); + + // mov temp, eax + // mov eax, edx + // xor edx, edx + // div divisor->gtRegNum + // mov eax, temp + const regNumber tempReg = genRegNumFromMask(node->gtRsvdRegs); + inst_RV_RV(INS_mov, tempReg, REG_EAX, TYP_INT); + inst_RV_RV(INS_mov, REG_EAX, REG_EDX, TYP_INT); + instGen_Set_Reg_To_Zero(EA_PTRSIZE, REG_EDX); + inst_RV(INS_div, divisor->gtRegNum, TYP_INT); + inst_RV_RV(INS_mov, REG_EAX, tempReg, TYP_INT); + + // noOverflow: + // div divisor->gtRegNum + genDefineTempLabel(noOverflow); + inst_RV(INS_div, divisor->gtRegNum, TYP_INT); + + const regNumber targetReg = node->gtRegNum; + if (targetReg != REG_EDX) + { + inst_RV_RV(INS_mov, targetReg, REG_RDX, TYP_INT); + } + genProduceReg(node); +} +#endif // _TARGET_X86_ - // Traverse the block in linear order, generating code for each node as we - // as we encounter it. - CLANG_FORMAT_COMMENT_ANCHOR; +//------------------------------------------------------------------------ +// genCodeForDivMod: Generate code for a DIV or MOD operation. +// +// Arguments: +// treeNode - the node to generate the code for +// +void CodeGen::genCodeForDivMod(GenTreeOp* treeNode) +{ + GenTree* dividend = treeNode->gtOp1; +#ifdef _TARGET_X86_ + if (varTypeIsLong(dividend->TypeGet())) + { + genCodeForLongUMod(treeNode); + return; + } +#endif // _TARGET_X86_ -#ifdef DEBUGGING_SUPPORT - IL_OFFSETX currentILOffset = BAD_IL_OFFSET; -#endif - for (GenTree* node : LIR::AsRange(block).NonPhiNodes()) - { -#ifdef DEBUGGING_SUPPORT - // Do we have a new IL offset? - if (node->OperGet() == GT_IL_OFFSET) - { - genEnsureCodeEmitted(currentILOffset); - currentILOffset = node->gtStmt.gtStmtILoffsx; - genIPmappingAdd(currentILOffset, firstMapping); - firstMapping = false; - } -#endif // DEBUGGING_SUPPORT + GenTree* divisor = treeNode->gtOp2; + genTreeOps oper = treeNode->OperGet(); + emitAttr size = emitTypeSize(treeNode); + regNumber targetReg = treeNode->gtRegNum; + var_types targetType = treeNode->TypeGet(); + emitter* emit = getEmitter(); -#ifdef DEBUG - if (node->OperGet() == GT_IL_OFFSET) - { - noway_assert(node->gtStmt.gtStmtLastILoffs <= compiler->info.compILCodeSize || - node->gtStmt.gtStmtLastILoffs == BAD_IL_OFFSET); + // dividend is not contained. + assert(!dividend->isContained()); - if (compiler->opts.dspCode && compiler->opts.dspInstrs && - node->gtStmt.gtStmtLastILoffs != BAD_IL_OFFSET) - { - while (genCurDispOffset <= node->gtStmt.gtStmtLastILoffs) - { - genCurDispOffset += dumpSingleInstr(compiler->info.compCode, genCurDispOffset, "> "); - } - } - } -#endif // DEBUG + genConsumeOperands(treeNode->AsOp()); + if (varTypeIsFloating(targetType)) + { + // divisor is not contained or if contained is a memory op. + // Note that a reg optional operand is a treated as a memory op + // if no register is allocated to it. + assert(!divisor->isContained() || divisor->isMemoryOp() || divisor->IsCnsFltOrDbl() || + divisor->IsRegOptional()); - genCodeForTreeNode(node); - if (node->gtHasReg() && node->gtLsraInfo.isLocalDefUse) - { - genConsumeReg(node); - } - } // end for each node in block + // Floating point div/rem operation + assert(oper == GT_DIV || oper == GT_MOD); -#ifdef DEBUG - // The following set of register spill checks and GC pointer tracking checks used to be - // performed at statement boundaries. Now, with LIR, there are no statements, so they are - // performed at the end of each block. - // TODO: could these checks be performed more frequently? E.g., at each location where - // the register allocator says there are no live non-variable registers. Perhaps this could - // be done by (a) keeping a running count of live non-variable registers by using - // gtLsraInfo.srcCount and gtLsraInfo.dstCount to decrement and increment the count, respectively, - // and running the checks when the count is zero. Or, (b) use the map maintained by LSRA - // (operandToLocationInfoMap) to mark a node somehow when, after the execution of that node, - // there will be no live non-variable registers. - - regSet.rsSpillChk(); - - /* Make sure we didn't bungle pointer register tracking */ - - regMaskTP ptrRegs = gcInfo.gcRegGCrefSetCur | gcInfo.gcRegByrefSetCur; - regMaskTP nonVarPtrRegs = ptrRegs & ~regSet.rsMaskVars; - - // If return is a GC-type, clear it. Note that if a common - // epilog is generated (genReturnBB) it has a void return - // even though we might return a ref. We can't use the compRetType - // as the determiner because something we are tracking as a byref - // might be used as a return value of a int function (which is legal) - GenTree* blockLastNode = block->lastNode(); - if ((blockLastNode != nullptr) && (blockLastNode->gtOper == GT_RETURN) && - (varTypeIsGC(compiler->info.compRetType) || - (blockLastNode->gtOp.gtOp1 != nullptr && varTypeIsGC(blockLastNode->gtOp.gtOp1->TypeGet())))) - { - nonVarPtrRegs &= ~RBM_INTRET; - } - - if (nonVarPtrRegs) - { - printf("Regset after BB%02u gcr=", block->bbNum); - printRegMaskInt(gcInfo.gcRegGCrefSetCur & ~regSet.rsMaskVars); - compiler->getEmitter()->emitDispRegSet(gcInfo.gcRegGCrefSetCur & ~regSet.rsMaskVars); - printf(", byr="); - printRegMaskInt(gcInfo.gcRegByrefSetCur & ~regSet.rsMaskVars); - compiler->getEmitter()->emitDispRegSet(gcInfo.gcRegByrefSetCur & ~regSet.rsMaskVars); - printf(", regVars="); - printRegMaskInt(regSet.rsMaskVars); - compiler->getEmitter()->emitDispRegSet(regSet.rsMaskVars); - printf("\n"); + if (dividend->gtRegNum == targetReg) + { + emit->emitInsBinary(genGetInsForOper(treeNode->gtOper, targetType), size, treeNode, divisor); } - - noway_assert(nonVarPtrRegs == RBM_NONE); -#endif // DEBUG - -#if defined(DEBUG) && defined(LATE_DISASM) && defined(_TARGET_AMD64_) - if (block->bbNext == nullptr) + else if (!divisor->isContained() && divisor->gtRegNum == targetReg) + { + // It is not possible to generate 2-operand divss or divsd where reg2 = reg1 / reg2 + // because divss/divsd reg1, reg2 will over-write reg1. Therefore, in case of AMD64 + // LSRA has to make sure that such a register assignment is not generated for floating + // point div/rem operations. + noway_assert( + !"GT_DIV/GT_MOD (float): case of reg2 = reg1 / reg2, LSRA should never generate such a reg assignment"); + } + else { - // Unit testing of the AMD64 emitter: generate a bunch of instructions into the last block - // (it's as good as any, but better than the prolog, which can only be a single instruction - // group) then use COMPlus_JitLateDisasm=* to see if the late disassembler - // thinks the instructions are the same as we do. - genAmd64EmitterUnitTests(); + inst_RV_RV(ins_Copy(targetType), targetReg, dividend->gtRegNum, targetType); + emit->emitInsBinary(genGetInsForOper(treeNode->gtOper, targetType), size, treeNode, divisor); } -#endif // defined(DEBUG) && defined(LATE_DISASM) && defined(_TARGET_ARM64_) + } + else + { + // dividend must be in RAX + genCopyRegIfNeeded(dividend, REG_RAX); -#ifdef DEBUGGING_SUPPORT - // It is possible to reach the end of the block without generating code for the current IL offset. - // For example, if the following IR ends the current block, no code will have been generated for - // offset 21: - // - // ( 0, 0) [000040] ------------ il_offset void IL offset: 21 - // - // N001 ( 0, 0) [000039] ------------ nop void - // - // This can lead to problems when debugging the generated code. To prevent these issues, make sure - // we've generated code for the last IL offset we saw in the block. - genEnsureCodeEmitted(currentILOffset); + // zero or sign extend rax to rdx + if (oper == GT_UMOD || oper == GT_UDIV) + { + instGen_Set_Reg_To_Zero(EA_PTRSIZE, REG_EDX); + } + else + { + emit->emitIns(INS_cdq, size); + // the cdq instruction writes RDX, So clear the gcInfo for RDX + gcInfo.gcMarkRegSetNpt(RBM_RDX); + } - if (compiler->opts.compScopeInfo && (compiler->info.compVarScopesCount > 0)) + // Perform the 'targetType' (64-bit or 32-bit) divide instruction + instruction ins; + if (oper == GT_UMOD || oper == GT_UDIV) + { + ins = INS_div; + } + else { - siEndBlock(block); + ins = INS_idiv; + } - /* Is this the last block, and are there any open scopes left ? */ + emit->emitInsBinary(ins, size, treeNode, divisor); - bool isLastBlockProcessed = (block->bbNext == nullptr); - if (block->isBBCallAlwaysPair()) + // DIV/IDIV instructions always store the quotient in RAX and the remainder in RDX. + // Move the result to the desired register, if necessary + if (oper == GT_DIV || oper == GT_UDIV) + { + if (targetReg != REG_RAX) { - isLastBlockProcessed = (block->bbNext->bbNext == nullptr); + inst_RV_RV(INS_mov, targetReg, REG_RAX, targetType); } - - if (isLastBlockProcessed && siOpenScopeList.scNext) + } + else + { + assert((oper == GT_MOD) || (oper == GT_UMOD)); + if (targetReg != REG_RDX) { - /* This assert no longer holds, because we may insert a throw - block to demarcate the end of a try or finally region when they - are at the end of the method. It would be nice if we could fix - our code so that this throw block will no longer be necessary. */ - - // noway_assert(block->bbCodeOffsEnd != compiler->info.compILCodeSize); - - siCloseAllOpenScopes(); + inst_RV_RV(INS_mov, targetReg, REG_RDX, targetType); } } + } + genProduceReg(treeNode); +} -#endif // DEBUGGING_SUPPORT +//------------------------------------------------------------------------ +// genCodeForBinary: Generate code for many binary arithmetic operators +// This method is expected to have called genConsumeOperands() before calling it. +// +// Arguments: +// treeNode - The binary operation for which we are generating code. +// +// Return Value: +// None. +// +// Notes: +// Mul and div variants have special constraints on x64 so are not handled here. +// See teh assert below for the operators that are handled. - genStackLevel -= savedStkLvl; +void CodeGen::genCodeForBinary(GenTree* treeNode) +{ + const genTreeOps oper = treeNode->OperGet(); + regNumber targetReg = treeNode->gtRegNum; + var_types targetType = treeNode->TypeGet(); + emitter* emit = getEmitter(); -#ifdef DEBUG - // compCurLife should be equal to the liveOut set, except that we don't keep - // it up to date for vars that are not register candidates - // (it would be nice to have a xor set function) +#if defined(_TARGET_64BIT_) + assert(oper == GT_OR || oper == GT_XOR || oper == GT_AND || oper == GT_ADD || oper == GT_SUB); +#else // !defined(_TARGET_64BIT_) + assert(oper == GT_OR || oper == GT_XOR || oper == GT_AND || oper == GT_ADD_LO || oper == GT_ADD_HI || + oper == GT_SUB_LO || oper == GT_SUB_HI || oper == GT_MUL_LONG || oper == GT_DIV_HI || oper == GT_MOD_HI || + oper == GT_ADD || oper == GT_SUB); +#endif // !defined(_TARGET_64BIT_) - VARSET_TP VARSET_INIT_NOCOPY(extraLiveVars, VarSetOps::Diff(compiler, block->bbLiveOut, compiler->compCurLife)); - VarSetOps::UnionD(compiler, extraLiveVars, VarSetOps::Diff(compiler, compiler->compCurLife, block->bbLiveOut)); - VARSET_ITER_INIT(compiler, extraLiveVarIter, extraLiveVars, extraLiveVarIndex); - while (extraLiveVarIter.NextElem(compiler, &extraLiveVarIndex)) - { - unsigned varNum = compiler->lvaTrackedToVarNum[extraLiveVarIndex]; - LclVarDsc* varDsc = compiler->lvaTable + varNum; - assert(!varDsc->lvIsRegCandidate()); - } -#endif + GenTreePtr op1 = treeNode->gtGetOp1(); + GenTreePtr op2 = treeNode->gtGetOp2(); - /* Both stacks should always be empty on exit from a basic block */ - noway_assert(genStackLevel == 0); + // Commutative operations can mark op1 as contained to generate "op reg, memop/immed" + if (op1->isContained()) + { + assert(treeNode->OperIsCommutative()); + assert(op1->isMemoryOp() || op1->IsCnsNonZeroFltOrDbl() || op1->IsIntCnsFitsInI32() || op1->IsRegOptional()); -#ifdef _TARGET_AMD64_ - // On AMD64, we need to generate a NOP after a call that is the last instruction of the block, in several - // situations, to support proper exception handling semantics. This is mostly to ensure that when the stack - // walker computes an instruction pointer for a frame, that instruction pointer is in the correct EH region. - // The document "X64 and ARM ABIs.docx" has more details. The situations: - // 1. If the call instruction is in a different EH region as the instruction that follows it. - // 2. If the call immediately precedes an OS epilog. (Note that what the JIT or VM consider an epilog might - // be slightly different from what the OS considers an epilog, and it is the OS-reported epilog that matters - // here.) - // We handle case #1 here, and case #2 in the emitter. - if (getEmitter()->emitIsLastInsCall()) - { - // Ok, the last instruction generated is a call instruction. Do any of the other conditions hold? - // Note: we may be generating a few too many NOPs for the case of call preceding an epilog. Technically, - // if the next block is a BBJ_RETURN, an epilog will be generated, but there may be some instructions - // generated before the OS epilog starts, such as a GS cookie check. - if ((block->bbNext == nullptr) || !BasicBlock::sameEHRegion(block, block->bbNext)) - { - // We only need the NOP if we're not going to generate any more code as part of the block end. - - switch (block->bbJumpKind) - { - case BBJ_ALWAYS: - case BBJ_THROW: - case BBJ_CALLFINALLY: - case BBJ_EHCATCHRET: - // We're going to generate more code below anyway, so no need for the NOP. + op1 = treeNode->gtGetOp2(); + op2 = treeNode->gtGetOp1(); + } - case BBJ_RETURN: - case BBJ_EHFINALLYRET: - case BBJ_EHFILTERRET: - // These are the "epilog follows" case, handled in the emitter. + instruction ins = genGetInsForOper(treeNode->OperGet(), targetType); - break; + // The arithmetic node must be sitting in a register (since it's not contained) + noway_assert(targetReg != REG_NA); - case BBJ_NONE: - if (block->bbNext == nullptr) - { - // Call immediately before the end of the code; we should never get here . - instGen(INS_BREAKPOINT); // This should never get executed - } - else - { - // We need the NOP - instGen(INS_nop); - } - break; + regNumber op1reg = op1->isContained() ? REG_NA : op1->gtRegNum; + regNumber op2reg = op2->isContained() ? REG_NA : op2->gtRegNum; - case BBJ_COND: - case BBJ_SWITCH: - // These can't have a call as the last instruction! + GenTreePtr dst; + GenTreePtr src; - default: - noway_assert(!"Unexpected bbJumpKind"); - break; - } - } + // This is the case of reg1 = reg1 op reg2 + // We're ready to emit the instruction without any moves + if (op1reg == targetReg) + { + dst = op1; + src = op2; + } + // We have reg1 = reg2 op reg1 + // In order for this operation to be correct + // we need that op is a commutative operation so + // we can convert it into reg1 = reg1 op reg2 and emit + // the same code as above + else if (op2reg == targetReg) + { + noway_assert(GenTree::OperIsCommutative(oper)); + dst = op2; + src = op1; + } + // now we know there are 3 different operands so attempt to use LEA + else if (oper == GT_ADD && !varTypeIsFloating(treeNode) && !treeNode->gtOverflowEx() // LEA does not set flags + && (op2->isContainedIntOrIImmed() || !op2->isContained()) && !treeNode->gtSetFlags()) + { + if (op2->isContainedIntOrIImmed()) + { + emit->emitIns_R_AR(INS_lea, emitTypeSize(treeNode), targetReg, op1reg, + (int)op2->AsIntConCommon()->IconValue()); } -#endif // _TARGET_AMD64_ - - /* Do we need to generate a jump or return? */ - - switch (block->bbJumpKind) + else { - case BBJ_ALWAYS: - inst_JMP(EJ_jmp, block->bbJumpDest); - break; - - case BBJ_RETURN: - genExitCode(block); - break; - - case BBJ_THROW: - // If we have a throw at the end of a function or funclet, we need to emit another instruction - // afterwards to help the OS unwinder determine the correct context during unwind. - // We insert an unexecuted breakpoint instruction in several situations - // following a throw instruction: - // 1. If the throw is the last instruction of the function or funclet. This helps - // the OS unwinder determine the correct context during an unwind from the - // thrown exception. - // 2. If this is this is the last block of the hot section. - // 3. If the subsequent block is a special throw block. - // 4. On AMD64, if the next block is in a different EH region. - if ((block->bbNext == nullptr) || (block->bbNext->bbFlags & BBF_FUNCLET_BEG) || - !BasicBlock::sameEHRegion(block, block->bbNext) || - (!isFramePointerUsed() && compiler->fgIsThrowHlpBlk(block->bbNext)) || - block->bbNext == compiler->fgFirstColdBlock) - { - instGen(INS_BREAKPOINT); // This should never get executed - } - - break; - - case BBJ_CALLFINALLY: - -#if FEATURE_EH_FUNCLETS - - // Generate a call to the finally, like this: - // mov rcx,qword ptr [rbp + 20H] // Load rcx with PSPSym - // call finally-funclet - // jmp finally-return // Only for non-retless finally calls - // The jmp can be a NOP if we're going to the next block. - // If we're generating code for the main function (not a funclet), and there is no localloc, - // then RSP at this point is the same value as that stored in the PSPsym. So just copy RSP - // instead of loading the PSPSym in this case. - - if (!compiler->compLocallocUsed && (compiler->funCurrentFunc()->funKind == FUNC_ROOT)) - { - inst_RV_RV(INS_mov, REG_ARG_0, REG_SPBASE, TYP_I_IMPL); - } - else - { - getEmitter()->emitIns_R_S(ins_Load(TYP_I_IMPL), EA_PTRSIZE, REG_ARG_0, compiler->lvaPSPSym, 0); - } - getEmitter()->emitIns_J(INS_call, block->bbJumpDest); - - if (block->bbFlags & BBF_RETLESS_CALL) - { - // We have a retless call, and the last instruction generated was a call. - // If the next block is in a different EH region (or is the end of the code - // block), then we need to generate a breakpoint here (since it will never - // get executed) to get proper unwind behavior. - - if ((block->bbNext == nullptr) || !BasicBlock::sameEHRegion(block, block->bbNext)) - { - instGen(INS_BREAKPOINT); // This should never get executed - } - } - else - { - // Because of the way the flowgraph is connected, the liveness info for this one instruction - // after the call is not (can not be) correct in cases where a variable has a last use in the - // handler. So turn off GC reporting for this single instruction. - getEmitter()->emitDisableGC(); - - // Now go to where the finally funclet needs to return to. - if (block->bbNext->bbJumpDest == block->bbNext->bbNext) - { - // Fall-through. - // TODO-XArch-CQ: Can we get rid of this instruction, and just have the call return directly - // to the next instruction? This would depend on stack walking from within the finally - // handler working without this instruction being in this special EH region. - instGen(INS_nop); - } - else - { - inst_JMP(EJ_jmp, block->bbNext->bbJumpDest); - } - - getEmitter()->emitEnableGC(); - } - -#else // !FEATURE_EH_FUNCLETS - - // If we are about to invoke a finally locally from a try block, we have to set the ShadowSP slot - // corresponding to the finally's nesting level. When invoked in response to an exception, the - // EE does this. - // - // We have a BBJ_CALLFINALLY followed by a BBJ_ALWAYS. - // - // We will emit : - // mov [ebp - (n + 1)], 0 - // mov [ebp - n ], 0xFC - // push &step - // jmp finallyBlock - // ... - // step: - // mov [ebp - n ], 0 - // jmp leaveTarget - // ... - // leaveTarget: - - noway_assert(isFramePointerUsed()); - - // Get the nesting level which contains the finally - compiler->fgGetNestingLevel(block, &finallyNesting); - - // The last slot is reserved for ICodeManager::FixContext(ppEndRegion) - unsigned filterEndOffsetSlotOffs; - filterEndOffsetSlotOffs = - (unsigned)(compiler->lvaLclSize(compiler->lvaShadowSPslotsVar) - TARGET_POINTER_SIZE); - - unsigned curNestingSlotOffs; - curNestingSlotOffs = (unsigned)(filterEndOffsetSlotOffs - ((finallyNesting + 1) * TARGET_POINTER_SIZE)); - - // Zero out the slot for the next nesting level - instGen_Store_Imm_Into_Lcl(TYP_I_IMPL, EA_PTRSIZE, 0, compiler->lvaShadowSPslotsVar, - curNestingSlotOffs - TARGET_POINTER_SIZE); - instGen_Store_Imm_Into_Lcl(TYP_I_IMPL, EA_PTRSIZE, LCL_FINALLY_MARK, compiler->lvaShadowSPslotsVar, - curNestingSlotOffs); - - // Now push the address where the finally funclet should return to directly. - if (!(block->bbFlags & BBF_RETLESS_CALL)) - { - assert(block->isBBCallAlwaysPair()); - getEmitter()->emitIns_J(INS_push_hide, block->bbNext->bbJumpDest); - } - else - { - // EE expects a DWORD, so we give him 0 - inst_IV(INS_push_hide, 0); - } - - // Jump to the finally BB - inst_JMP(EJ_jmp, block->bbJumpDest); - -#endif // !FEATURE_EH_FUNCLETS - - // The BBJ_ALWAYS is used because the BBJ_CALLFINALLY can't point to the - // jump target using bbJumpDest - that is already used to point - // to the finally block. So just skip past the BBJ_ALWAYS unless the - // block is RETLESS. - if (!(block->bbFlags & BBF_RETLESS_CALL)) - { - assert(block->isBBCallAlwaysPair()); - - lblk = block; - block = block->bbNext; - } - - break; - -#if FEATURE_EH_FUNCLETS - - case BBJ_EHCATCHRET: - // Set RAX to the address the VM should return to after the catch. - // Generate a RIP-relative - // lea reg, [rip + disp32] ; the RIP is implicit - // which will be position-indepenent. - getEmitter()->emitIns_R_L(INS_lea, EA_PTR_DSP_RELOC, block->bbJumpDest, REG_INTRET); - __fallthrough; - - case BBJ_EHFINALLYRET: - case BBJ_EHFILTERRET: - genReserveFuncletEpilog(block); - break; - -#else // !FEATURE_EH_FUNCLETS - - case BBJ_EHCATCHRET: - noway_assert(!"Unexpected BBJ_EHCATCHRET"); // not used on x86 - - case BBJ_EHFINALLYRET: - case BBJ_EHFILTERRET: - { - // The last statement of the block must be a GT_RETFILT, which has already been generated. - assert(block->lastNode() != nullptr); - assert(block->lastNode()->OperGet() == GT_RETFILT); - - if (block->bbJumpKind == BBJ_EHFINALLYRET) - { - assert(block->lastNode()->gtOp.gtOp1 == nullptr); // op1 == nullptr means endfinally - - // Return using a pop-jmp sequence. As the "try" block calls - // the finally with a jmp, this leaves the x86 call-ret stack - // balanced in the normal flow of path. - - noway_assert(isFramePointerRequired()); - inst_RV(INS_pop_hide, REG_EAX, TYP_I_IMPL); - inst_RV(INS_i_jmp, REG_EAX, TYP_I_IMPL); - } - else - { - assert(block->bbJumpKind == BBJ_EHFILTERRET); - - // The return value has already been computed. - instGen_Return(0); - } - } - break; - -#endif // !FEATURE_EH_FUNCLETS - - case BBJ_NONE: - case BBJ_COND: - case BBJ_SWITCH: - break; - - default: - noway_assert(!"Unexpected bbJumpKind"); - break; + assert(op2reg != REG_NA); + emit->emitIns_R_ARX(INS_lea, emitTypeSize(treeNode), targetReg, op1reg, op2reg, 1, 0); } - -#ifdef DEBUG - compiler->compCurBB = nullptr; -#endif - - } //------------------ END-FOR each block of the method ------------------- - - /* Nothing is live at this point */ - genUpdateLife(VarSetOps::MakeEmpty(compiler)); - - /* Finalize the spill tracking logic */ - - regSet.rsSpillEnd(); - - /* Finalize the temp tracking logic */ - - compiler->tmpEnd(); - -#ifdef DEBUG - if (compiler->verbose) - { - printf("\n# "); - printf("compCycleEstimate = %6d, compSizeEstimate = %5d ", compiler->compCycleEstimate, - compiler->compSizeEstimate); - printf("%s\n", compiler->info.compFullName); + genProduceReg(treeNode); + return; } -#endif -} - -// return the child that has the same reg as the dst (if any) -// other child returned (out param) in 'other' -GenTree* sameRegAsDst(GenTree* tree, GenTree*& other /*out*/) -{ - if (tree->gtRegNum == REG_NA) + // dest, op1 and op2 registers are different: + // reg3 = reg1 op reg2 + // We can implement this by issuing a mov: + // reg3 = reg1 + // reg3 = reg3 op reg2 + else { - other = nullptr; - return nullptr; + inst_RV_RV(ins_Copy(targetType), targetReg, op1reg, targetType); + regTracker.rsTrackRegCopy(targetReg, op1reg); + gcInfo.gcMarkRegPtrVal(targetReg, targetType); + dst = treeNode; + src = op2; } - GenTreePtr op1 = tree->gtOp.gtOp1; - GenTreePtr op2 = tree->gtOp.gtOp2; - if (op1->gtRegNum == tree->gtRegNum) - { - other = op2; - return op1; - } - if (op2->gtRegNum == tree->gtRegNum) + // try to use an inc or dec + if (oper == GT_ADD && !varTypeIsFloating(treeNode) && src->isContainedIntOrIImmed() && !treeNode->gtOverflowEx()) { - other = op1; - return op2; + if (src->IsIntegralConst(1)) + { + emit->emitIns_R(INS_inc, emitTypeSize(treeNode), targetReg); + genProduceReg(treeNode); + return; + } + else if (src->IsIntegralConst(-1)) + { + emit->emitIns_R(INS_dec, emitTypeSize(treeNode), targetReg); + genProduceReg(treeNode); + return; + } } - else + regNumber r = emit->emitInsBinary(ins, emitTypeSize(treeNode), dst, src); + noway_assert(r == targetReg); + + if (treeNode->gtOverflowEx()) { - other = nullptr; - return nullptr; +#if !defined(_TARGET_64BIT_) + assert(oper == GT_ADD || oper == GT_SUB || oper == GT_ADD_HI || oper == GT_SUB_HI); +#else + assert(oper == GT_ADD || oper == GT_SUB); +#endif + genCheckOverflow(treeNode); } + genProduceReg(treeNode); } -// Move an immediate value into an integer register - -void CodeGen::instGen_Set_Reg_To_Imm(emitAttr size, regNumber reg, ssize_t imm, insFlags flags) +//------------------------------------------------------------------------ +// isStructReturn: Returns whether the 'treeNode' is returning a struct. +// +// Arguments: +// treeNode - The tree node to evaluate whether is a struct return. +// +// Return Value: +// For AMD64 *nix: returns true if the 'treeNode" is a GT_RETURN node, of type struct. +// Otherwise returns false. +// For other platforms always returns false. +// +bool CodeGen::isStructReturn(GenTreePtr treeNode) { - // reg cannot be a FP register - assert(!genIsValidFloatReg(reg)); - - if (!compiler->opts.compReloc) + // This method could be called for 'treeNode' of GT_RET_FILT or GT_RETURN. + // For the GT_RET_FILT, the return is always + // a bool or a void, for the end of a finally block. + noway_assert(treeNode->OperGet() == GT_RETURN || treeNode->OperGet() == GT_RETFILT); + if (treeNode->OperGet() != GT_RETURN) { - size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs + return false; } - if ((imm == 0) && !EA_IS_RELOC(size)) - { - instGen_Set_Reg_To_Zero(size, reg, flags); - } - else - { - if (genDataIndirAddrCanBeEncodedAsPCRelOffset(imm)) - { - getEmitter()->emitIns_R_AI(INS_lea, EA_PTR_DSP_RELOC, reg, imm); - } - else - { - getEmitter()->emitIns_R_I(INS_mov, size, reg, imm); - } - } - regTracker.rsTrackRegIntCns(reg, imm); +#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING + return varTypeIsStruct(treeNode); +#else // !FEATURE_UNIX_AMD64_STRUCT_PASSING + assert(!varTypeIsStruct(treeNode)); + return false; +#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING } -/*********************************************************************************** - * - * Generate code to set a register 'targetReg' of type 'targetType' to the constant - * specified by the constant (GT_CNS_INT or GT_CNS_DBL) in 'tree'. This does not call - * genProduceReg() on the target register. - */ -void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTreePtr tree) +//------------------------------------------------------------------------ +// genStructReturn: Generates code for returning a struct. +// +// Arguments: +// treeNode - The GT_RETURN tree node. +// +// Return Value: +// None +// +// Assumption: +// op1 of GT_RETURN node is either GT_LCL_VAR or multi-reg GT_CALL +void CodeGen::genStructReturn(GenTreePtr treeNode) { + assert(treeNode->OperGet() == GT_RETURN); + GenTreePtr op1 = treeNode->gtGetOp1(); - switch (tree->gtOper) +#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING + if (op1->OperGet() == GT_LCL_VAR) { - case GT_CNS_INT: + GenTreeLclVarCommon* lclVar = op1->AsLclVarCommon(); + LclVarDsc* varDsc = &(compiler->lvaTable[lclVar->gtLclNum]); + assert(varDsc->lvIsMultiRegRet); + + ReturnTypeDesc retTypeDesc; + retTypeDesc.InitializeStructReturnType(compiler, varDsc->lvVerTypeInfo.GetClassHandle()); + unsigned regCount = retTypeDesc.GetReturnRegCount(); + assert(regCount == MAX_RET_REG_COUNT); + + if (varTypeIsEnregisterableStruct(op1)) { - // relocatable values tend to come down as a CNS_INT of native int type - // so the line between these two opcodes is kind of blurry - GenTreeIntConCommon* con = tree->AsIntConCommon(); - ssize_t cnsVal = con->IconValue(); + // Right now the only enregistrable structs supported are SIMD vector types. + assert(varTypeIsSIMD(op1)); + assert(!op1->isContained()); - if (con->ImmedValNeedsReloc(compiler)) + // This is a case of operand is in a single reg and needs to be + // returned in multiple ABI return registers. + regNumber opReg = genConsumeReg(op1); + regNumber reg0 = retTypeDesc.GetABIReturnReg(0); + regNumber reg1 = retTypeDesc.GetABIReturnReg(1); + + if (opReg != reg0 && opReg != reg1) { - instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, targetReg, cnsVal); - regTracker.rsTrackRegTrash(targetReg); + // Operand reg is different from return regs. + // Copy opReg to reg0 and let it to be handled by one of the + // two cases below. + inst_RV_RV(ins_Copy(TYP_DOUBLE), reg0, opReg, TYP_DOUBLE); + opReg = reg0; + } + + if (opReg == reg0) + { + assert(opReg != reg1); + + // reg0 - already has required 8-byte in bit position [63:0]. + // reg1 = opReg. + // swap upper and lower 8-bytes of reg1 so that desired 8-byte is in bit position [63:0]. + inst_RV_RV(ins_Copy(TYP_DOUBLE), reg1, opReg, TYP_DOUBLE); } else { - genSetRegToIcon(targetReg, cnsVal, targetType); + assert(opReg == reg1); + + // reg0 = opReg. + // swap upper and lower 8-bytes of reg1 so that desired 8-byte is in bit position [63:0]. + inst_RV_RV(ins_Copy(TYP_DOUBLE), reg0, opReg, TYP_DOUBLE); } + inst_RV_RV_IV(INS_shufpd, EA_16BYTE, reg1, reg1, 0x01); } - break; - - case GT_CNS_DBL: + else { - double constValue = tree->gtDblCon.gtDconVal; + assert(op1->isContained()); - // Make sure we use "xorpd reg, reg" only for +ve zero constant (0.0) and not for -ve zero (-0.0) - if (*(__int64*)&constValue == 0) - { - // A faster/smaller way to generate 0 - instruction ins = genGetInsForOper(GT_XOR, targetType); - inst_RV_RV(ins, targetReg, targetReg, targetType); - } - else + // Copy var on stack into ABI return registers + int offset = 0; + for (unsigned i = 0; i < regCount; ++i) { - GenTreePtr cns; - if (targetType == TYP_FLOAT) - { - float f = forceCastToFloat(constValue); - cns = genMakeConst(&f, targetType, tree, false); - } - else - { - cns = genMakeConst(&constValue, targetType, tree, true); - } - - inst_RV_TT(ins_Load(targetType), targetReg, cns); + var_types type = retTypeDesc.GetReturnRegType(i); + regNumber reg = retTypeDesc.GetABIReturnReg(i); + getEmitter()->emitIns_R_S(ins_Load(type), emitTypeSize(type), reg, lclVar->gtLclNum, offset); + offset += genTypeSize(type); } } - break; - - default: - unreached(); - } -} - -// Generate code to get the high N bits of a N*N=2N bit multiplication result -void CodeGen::genCodeForMulHi(GenTreeOp* treeNode) -{ - assert(!(treeNode->gtFlags & GTF_UNSIGNED)); - assert(!treeNode->gtOverflowEx()); - - regNumber targetReg = treeNode->gtRegNum; - var_types targetType = treeNode->TypeGet(); - emitter* emit = getEmitter(); - emitAttr size = emitTypeSize(treeNode); - GenTree* op1 = treeNode->gtOp.gtOp1; - GenTree* op2 = treeNode->gtOp.gtOp2; - - // to get the high bits of the multiply, we are constrained to using the - // 1-op form: RDX:RAX = RAX * rm - // The 3-op form (Rx=Ry*Rz) does not support it. - - genConsumeOperands(treeNode->AsOp()); - - GenTree* regOp = op1; - GenTree* rmOp = op2; - - // Set rmOp to the contained memory operand (if any) - // - if (op1->isContained() || (!op2->isContained() && (op2->gtRegNum == targetReg))) - { - regOp = op2; - rmOp = op1; - } - assert(!regOp->isContained()); - - // Setup targetReg when neither of the source operands was a matching register - if (regOp->gtRegNum != targetReg) - { - inst_RV_RV(ins_Copy(targetType), targetReg, regOp->gtRegNum, targetType); } - - emit->emitInsBinary(INS_imulEAX, size, treeNode, rmOp); - - // Move the result to the desired register, if necessary - if (targetReg != REG_RDX) + else { - inst_RV_RV(INS_mov, targetReg, REG_RDX, targetType); - } -} + assert(op1->IsMultiRegCall() || op1->IsCopyOrReloadOfMultiRegCall()); -// generate code for a DIV or MOD operation -// -void CodeGen::genCodeForDivMod(GenTreeOp* treeNode) -{ - GenTree* dividend = treeNode->gtOp1; - GenTree* divisor = treeNode->gtOp2; - genTreeOps oper = treeNode->OperGet(); - emitAttr size = emitTypeSize(treeNode); - regNumber targetReg = treeNode->gtRegNum; - var_types targetType = treeNode->TypeGet(); - emitter* emit = getEmitter(); + genConsumeRegs(op1); - // dividend is not contained. - assert(!dividend->isContained()); + GenTree* actualOp1 = op1->gtSkipReloadOrCopy(); + GenTreeCall* call = actualOp1->AsCall(); + ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); + unsigned regCount = retTypeDesc->GetReturnRegCount(); + assert(regCount == MAX_RET_REG_COUNT); - genConsumeOperands(treeNode->AsOp()); - if (varTypeIsFloating(targetType)) - { - // divisor is not contained or if contained is a memory op. - // Note that a reg optional operand is a treated as a memory op - // if no register is allocated to it. - assert(!divisor->isContained() || divisor->isMemoryOp() || divisor->IsCnsFltOrDbl() || - divisor->IsRegOptional()); + // Handle circular dependency between call allocated regs and ABI return regs. + // + // It is possible under LSRA stress that originally allocated regs of call node, + // say rax and rdx, are spilled and reloaded to rdx and rax respectively. But + // GT_RETURN needs to move values as follows: rdx->rax, rax->rdx. Similar kind + // kind of circular dependency could arise between xmm0 and xmm1 return regs. + // Codegen is expected to handle such circular dependency. + // + var_types regType0 = retTypeDesc->GetReturnRegType(0); + regNumber returnReg0 = retTypeDesc->GetABIReturnReg(0); + regNumber allocatedReg0 = call->GetRegNumByIdx(0); - // Floating point div/rem operation - assert(oper == GT_DIV || oper == GT_MOD); + var_types regType1 = retTypeDesc->GetReturnRegType(1); + regNumber returnReg1 = retTypeDesc->GetABIReturnReg(1); + regNumber allocatedReg1 = call->GetRegNumByIdx(1); - if (dividend->gtRegNum == targetReg) - { - emit->emitInsBinary(genGetInsForOper(treeNode->gtOper, targetType), size, treeNode, divisor); - } - else if (!divisor->isContained() && divisor->gtRegNum == targetReg) - { - // It is not possible to generate 2-operand divss or divsd where reg2 = reg1 / reg2 - // because divss/divsd reg1, reg2 will over-write reg1. Therefore, in case of AMD64 - // LSRA has to make sure that such a register assignment is not generated for floating - // point div/rem operations. - noway_assert( - !"GT_DIV/GT_MOD (float): case of reg2 = reg1 / reg2, LSRA should never generate such a reg assignment"); - } - else - { - inst_RV_RV(ins_Copy(targetType), targetReg, dividend->gtRegNum, targetType); - emit->emitInsBinary(genGetInsForOper(treeNode->gtOper, targetType), size, treeNode, divisor); - } - } - else - { - // dividend must be in RAX - if (dividend->gtRegNum != REG_RAX) + if (op1->IsCopyOrReload()) { - inst_RV_RV(INS_mov, REG_RAX, dividend->gtRegNum, targetType); - } + // GT_COPY/GT_RELOAD will have valid reg for those positions + // that need to be copied or reloaded. + regNumber reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(0); + if (reloadReg != REG_NA) + { + allocatedReg0 = reloadReg; + } - // zero or sign extend rax to rdx - if (oper == GT_UMOD || oper == GT_UDIV) - { - instGen_Set_Reg_To_Zero(EA_PTRSIZE, REG_EDX); - } - else - { - emit->emitIns(INS_cdq, size); - // the cdq instruction writes RDX, So clear the gcInfo for RDX - gcInfo.gcMarkRegSetNpt(RBM_RDX); + reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(1); + if (reloadReg != REG_NA) + { + allocatedReg1 = reloadReg; + } } - // Perform the 'targetType' (64-bit or 32-bit) divide instruction - instruction ins; - if (oper == GT_UMOD || oper == GT_UDIV) + if (allocatedReg0 == returnReg1 && allocatedReg1 == returnReg0) { - ins = INS_div; + // Circular dependency - swap allocatedReg0 and allocatedReg1 + if (varTypeIsFloating(regType0)) + { + assert(varTypeIsFloating(regType1)); + + // The fastest way to swap two XMM regs is using PXOR + inst_RV_RV(INS_pxor, allocatedReg0, allocatedReg1, TYP_DOUBLE); + inst_RV_RV(INS_pxor, allocatedReg1, allocatedReg0, TYP_DOUBLE); + inst_RV_RV(INS_pxor, allocatedReg0, allocatedReg1, TYP_DOUBLE); + } + else + { + assert(varTypeIsIntegral(regType0)); + assert(varTypeIsIntegral(regType1)); + inst_RV_RV(INS_xchg, allocatedReg1, allocatedReg0, TYP_I_IMPL); + } } - else + else if (allocatedReg1 == returnReg0) { - ins = INS_idiv; - } - - emit->emitInsBinary(ins, size, treeNode, divisor); + // Change the order of moves to correctly handle dependency. + if (allocatedReg1 != returnReg1) + { + inst_RV_RV(ins_Copy(regType1), returnReg1, allocatedReg1, regType1); + } - // DIV/IDIV instructions always store the quotient in RAX and the remainder in RDX. - // Move the result to the desired register, if necessary - if (oper == GT_DIV || oper == GT_UDIV) - { - if (targetReg != REG_RAX) + if (allocatedReg0 != returnReg0) { - inst_RV_RV(INS_mov, targetReg, REG_RAX, targetType); + inst_RV_RV(ins_Copy(regType0), returnReg0, allocatedReg0, regType0); } } else { - assert((oper == GT_MOD) || (oper == GT_UMOD)); - if (targetReg != REG_RDX) + // No circular dependency case. + if (allocatedReg0 != returnReg0) { - inst_RV_RV(INS_mov, targetReg, REG_RDX, targetType); + inst_RV_RV(ins_Copy(regType0), returnReg0, allocatedReg0, regType0); + } + + if (allocatedReg1 != returnReg1) + { + inst_RV_RV(ins_Copy(regType1), returnReg1, allocatedReg1, regType1); } } } - genProduceReg(treeNode); +#else + unreached(); +#endif } //------------------------------------------------------------------------ -// genCodeForBinary: Generate code for many binary arithmetic operators -// This method is expected to have called genConsumeOperands() before calling it. +// genReturn: Generates code for return statement. +// In case of struct return, delegates to the genStructReturn method. // // Arguments: -// treeNode - The binary operation for which we are generating code. +// treeNode - The GT_RETURN or GT_RETFILT tree node. // // Return Value: -// None. +// None // -// Notes: -// Mul and div variants have special constraints on x64 so are not handled here. -// See teh assert below for the operators that are handled. - -void CodeGen::genCodeForBinary(GenTree* treeNode) +void CodeGen::genReturn(GenTreePtr treeNode) { - const genTreeOps oper = treeNode->OperGet(); - regNumber targetReg = treeNode->gtRegNum; - var_types targetType = treeNode->TypeGet(); - emitter* emit = getEmitter(); - -#if defined(_TARGET_64BIT_) - assert(oper == GT_OR || oper == GT_XOR || oper == GT_AND || oper == GT_ADD || oper == GT_SUB); -#else // !defined(_TARGET_64BIT_) - assert(oper == GT_OR || oper == GT_XOR || oper == GT_AND || oper == GT_ADD_LO || oper == GT_ADD_HI || - oper == GT_SUB_LO || oper == GT_SUB_HI || oper == GT_MUL_HI || oper == GT_DIV_HI || oper == GT_MOD_HI || - oper == GT_ADD || oper == GT_SUB); -#endif // !defined(_TARGET_64BIT_) - - GenTreePtr op1 = treeNode->gtGetOp1(); - GenTreePtr op2 = treeNode->gtGetOp2(); + assert(treeNode->OperGet() == GT_RETURN || treeNode->OperGet() == GT_RETFILT); + GenTreePtr op1 = treeNode->gtGetOp1(); + var_types targetType = treeNode->TypeGet(); - // Commutative operations can mark op1 as contained to generate "op reg, memop/immed" - if (op1->isContained()) +#ifdef DEBUG + if (targetType == TYP_VOID) { - assert(treeNode->OperIsCommutative()); - assert(op1->isMemoryOp() || op1->IsCnsNonZeroFltOrDbl() || op1->IsIntCnsFitsInI32() || op1->IsRegOptional()); - - op1 = treeNode->gtGetOp2(); - op2 = treeNode->gtGetOp1(); + assert(op1 == nullptr); } +#endif - instruction ins = genGetInsForOper(treeNode->OperGet(), targetType); - - // The arithmetic node must be sitting in a register (since it's not contained) - noway_assert(targetReg != REG_NA); - - regNumber op1reg = op1->isContained() ? REG_NA : op1->gtRegNum; - regNumber op2reg = op2->isContained() ? REG_NA : op2->gtRegNum; - - GenTreePtr dst; - GenTreePtr src; - - // This is the case of reg1 = reg1 op reg2 - // We're ready to emit the instruction without any moves - if (op1reg == targetReg) - { - dst = op1; - src = op2; - } - // We have reg1 = reg2 op reg1 - // In order for this operation to be correct - // we need that op is a commutative operation so - // we can convert it into reg1 = reg1 op reg2 and emit - // the same code as above - else if (op2reg == targetReg) - { - noway_assert(GenTree::OperIsCommutative(oper)); - dst = op2; - src = op1; - } - // now we know there are 3 different operands so attempt to use LEA - else if (oper == GT_ADD && !varTypeIsFloating(treeNode) && !treeNode->gtOverflowEx() // LEA does not set flags - && (op2->isContainedIntOrIImmed() || !op2->isContained())) +#ifdef _TARGET_X86_ + if (treeNode->TypeGet() == TYP_LONG) { - if (op2->isContainedIntOrIImmed()) + assert(op1 != nullptr); + noway_assert(op1->OperGet() == GT_LONG); + GenTree* loRetVal = op1->gtGetOp1(); + GenTree* hiRetVal = op1->gtGetOp2(); + noway_assert((loRetVal->gtRegNum != REG_NA) && (hiRetVal->gtRegNum != REG_NA)); + + genConsumeReg(loRetVal); + genConsumeReg(hiRetVal); + if (loRetVal->gtRegNum != REG_LNGRET_LO) { - emit->emitIns_R_AR(INS_lea, emitTypeSize(treeNode), targetReg, op1reg, - (int)op2->AsIntConCommon()->IconValue()); + inst_RV_RV(ins_Copy(targetType), REG_LNGRET_LO, loRetVal->gtRegNum, TYP_INT); } - else + if (hiRetVal->gtRegNum != REG_LNGRET_HI) { - assert(op2reg != REG_NA); - emit->emitIns_R_ARX(INS_lea, emitTypeSize(treeNode), targetReg, op1reg, op2reg, 1, 0); + inst_RV_RV(ins_Copy(targetType), REG_LNGRET_HI, hiRetVal->gtRegNum, TYP_INT); } - genProduceReg(treeNode); - return; } - // dest, op1 and op2 registers are different: - // reg3 = reg1 op reg2 - // We can implement this by issuing a mov: - // reg3 = reg1 - // reg3 = reg3 op reg2 else +#endif // !defined(_TARGET_X86_) { - inst_RV_RV(ins_Copy(targetType), targetReg, op1reg, targetType); - regTracker.rsTrackRegCopy(targetReg, op1reg); - gcInfo.gcMarkRegPtrVal(targetReg, targetType); - dst = treeNode; - src = op2; + if (isStructReturn(treeNode)) + { + genStructReturn(treeNode); + } + else if (targetType != TYP_VOID) + { + assert(op1 != nullptr); + noway_assert(op1->gtRegNum != REG_NA); + + // !! NOTE !! genConsumeReg will clear op1 as GC ref after it has + // consumed a reg for the operand. This is because the variable + // is dead after return. But we are issuing more instructions + // like "profiler leave callback" after this consumption. So + // if you are issuing more instructions after this point, + // remember to keep the variable live up until the new method + // exit point where it is actually dead. + genConsumeReg(op1); + + regNumber retReg = varTypeIsFloating(treeNode) ? REG_FLOATRET : REG_INTRET; +#ifdef _TARGET_X86_ + if (varTypeIsFloating(treeNode)) + { + // Spill the return value register from an XMM register to the stack, then load it on the x87 stack. + // If it already has a home location, use that. Otherwise, we need a temp. + if (genIsRegCandidateLocal(op1) && compiler->lvaTable[op1->gtLclVarCommon.gtLclNum].lvOnFrame) + { + // Store local variable to its home location, if necessary. + if ((op1->gtFlags & GTF_REG_VAL) != 0) + { + op1->gtFlags &= ~GTF_REG_VAL; + inst_TT_RV(ins_Store(op1->gtType, + compiler->isSIMDTypeLocalAligned(op1->gtLclVarCommon.gtLclNum)), + op1, op1->gtRegNum); + } + // Now, load it to the fp stack. + getEmitter()->emitIns_S(INS_fld, emitTypeSize(op1), op1->AsLclVarCommon()->gtLclNum, 0); + } + else + { + // Spill the value, which should be in a register, then load it to the fp stack. + // TODO-X86-CQ: Deal with things that are already in memory (don't call genConsumeReg yet). + op1->gtFlags |= GTF_SPILL; + regSet.rsSpillTree(op1->gtRegNum, op1); + op1->gtFlags |= GTF_SPILLED; + op1->gtFlags &= ~GTF_SPILL; + + TempDsc* t = regSet.rsUnspillInPlace(op1, op1->gtRegNum); + inst_FS_ST(INS_fld, emitActualTypeSize(op1->gtType), t, 0); + op1->gtFlags &= ~GTF_SPILLED; + compiler->tmpRlsTemp(t); + } + } + else +#endif // _TARGET_X86_ + { + if (op1->gtRegNum != retReg) + { + inst_RV_RV(ins_Copy(targetType), retReg, op1->gtRegNum, targetType); + } + } + } } - // try to use an inc or dec - if (oper == GT_ADD && !varTypeIsFloating(treeNode) && src->isContainedIntOrIImmed() && !treeNode->gtOverflowEx()) +#ifdef PROFILING_SUPPORTED + // !! Note !! + // TODO-AMD64-Unix: If the profiler hook is implemented on *nix, make sure for 2 register returned structs + // the RAX and RDX needs to be kept alive. Make the necessary changes in lowerxarch.cpp + // in the handling of the GT_RETURN statement. + // Such structs containing GC pointers need to be handled by calling gcInfo.gcMarkRegSetNpt + // for the return registers containing GC refs. + + // There will be a single return block while generating profiler ELT callbacks. + // + // Reason for not materializing Leave callback as a GT_PROF_HOOK node after GT_RETURN: + // In flowgraph and other places assert that the last node of a block marked as + // BBJ_RETURN is either a GT_RETURN or GT_JMP or a tail call. It would be nice to + // maintain such an invariant irrespective of whether profiler hook needed or not. + // Also, there is not much to be gained by materializing it as an explicit node. + if (compiler->compCurBB == compiler->genReturnBB) { - if (src->IsIntegralConst(1)) + // !! NOTE !! + // Since we are invalidating the assumption that we would slip into the epilog + // right after the "return", we need to preserve the return reg's GC state + // across the call until actual method return. + if (varTypeIsGC(compiler->info.compRetType)) { - emit->emitIns_R(INS_inc, emitTypeSize(treeNode), targetReg); - genProduceReg(treeNode); - return; + gcInfo.gcMarkRegPtrVal(REG_INTRET, compiler->info.compRetType); } - else if (src->IsIntegralConst(-1)) + + genProfilingLeaveCallback(); + + if (varTypeIsGC(compiler->info.compRetType)) { - emit->emitIns_R(INS_dec, emitTypeSize(treeNode), targetReg); - genProduceReg(treeNode); - return; + gcInfo.gcMarkRegSetNpt(REG_INTRET); } } - regNumber r = emit->emitInsBinary(ins, emitTypeSize(treeNode), dst, src); - noway_assert(r == targetReg); - - if (treeNode->gtOverflowEx()) - { -#if !defined(_TARGET_64BIT_) - assert(oper == GT_ADD || oper == GT_SUB || oper == GT_ADD_HI || oper == GT_SUB_HI); -#else - assert(oper == GT_ADD || oper == GT_SUB); #endif - genCheckOverflow(treeNode); - } - genProduceReg(treeNode); } -//------------------------------------------------------------------------ -// isStructReturn: Returns whether the 'treeNode' is returning a struct. -// -// Arguments: -// treeNode - The tree node to evaluate whether is a struct return. -// -// Return Value: -// For AMD64 *nix: returns true if the 'treeNode" is a GT_RETURN node, of type struct. -// Otherwise returns false. -// For other platforms always returns false. -// -bool CodeGen::isStructReturn(GenTreePtr treeNode) +/***************************************************************************** + * + * Generate code for a single node in the tree. + * Preconditions: All operands have been evaluated + * + */ +void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) { - // This method could be called for 'treeNode' of GT_RET_FILT or GT_RETURN. - // For the GT_RET_FILT, the return is always - // a bool or a void, for the end of a finally block. - noway_assert(treeNode->OperGet() == GT_RETURN || treeNode->OperGet() == GT_RETFILT); - if (treeNode->OperGet() != GT_RETURN) + regNumber targetReg; +#if !defined(_TARGET_64BIT_) + if (treeNode->TypeGet() == TYP_LONG) { - return false; + // All long enregistered nodes will have been decomposed into their + // constituent lo and hi nodes. + targetReg = REG_NA; } - -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING - return varTypeIsStruct(treeNode); -#else // !FEATURE_UNIX_AMD64_STRUCT_PASSING - assert(!varTypeIsStruct(treeNode)); - return false; -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING -} - -//------------------------------------------------------------------------ -// genStructReturn: Generates code for returning a struct. -// -// Arguments: -// treeNode - The GT_RETURN tree node. -// -// Return Value: -// None -// -// Assumption: -// op1 of GT_RETURN node is either GT_LCL_VAR or multi-reg GT_CALL -void CodeGen::genStructReturn(GenTreePtr treeNode) -{ - assert(treeNode->OperGet() == GT_RETURN); - GenTreePtr op1 = treeNode->gtGetOp1(); - -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING - if (op1->OperGet() == GT_LCL_VAR) + else +#endif // !defined(_TARGET_64BIT_) { - GenTreeLclVarCommon* lclVar = op1->AsLclVarCommon(); - LclVarDsc* varDsc = &(compiler->lvaTable[lclVar->gtLclNum]); - assert(varDsc->lvIsMultiRegRet); + targetReg = treeNode->gtRegNum; + } + var_types targetType = treeNode->TypeGet(); + emitter* emit = getEmitter(); - ReturnTypeDesc retTypeDesc; - retTypeDesc.InitializeStructReturnType(compiler, varDsc->lvVerTypeInfo.GetClassHandle()); - unsigned regCount = retTypeDesc.GetReturnRegCount(); - assert(regCount == MAX_RET_REG_COUNT); +#ifdef DEBUG + // Validate that all the operands for the current node are consumed in order. + // This is important because LSRA ensures that any necessary copies will be + // handled correctly. + lastConsumedNode = nullptr; + if (compiler->verbose) + { + unsigned seqNum = treeNode->gtSeqNum; // Useful for setting a conditional break in Visual Studio + printf("Generating: "); + compiler->gtDispTree(treeNode, nullptr, nullptr, true); + } +#endif // DEBUG - if (varTypeIsEnregisterableStruct(op1)) - { - // Right now the only enregistrable structs supported are SIMD vector types. - assert(varTypeIsSIMD(op1)); - assert(!op1->isContained()); - - // This is a case of operand is in a single reg and needs to be - // returned in multiple ABI return registers. - regNumber opReg = genConsumeReg(op1); - regNumber reg0 = retTypeDesc.GetABIReturnReg(0); - regNumber reg1 = retTypeDesc.GetABIReturnReg(1); - - if (opReg != reg0 && opReg != reg1) - { - // Operand reg is different from return regs. - // Copy opReg to reg0 and let it to be handled by one of the - // two cases below. - inst_RV_RV(ins_Copy(TYP_DOUBLE), reg0, opReg, TYP_DOUBLE); - opReg = reg0; - } - - if (opReg == reg0) - { - assert(opReg != reg1); - - // reg0 - already has required 8-byte in bit position [63:0]. - // reg1 = opReg. - // swap upper and lower 8-bytes of reg1 so that desired 8-byte is in bit position [63:0]. - inst_RV_RV(ins_Copy(TYP_DOUBLE), reg1, opReg, TYP_DOUBLE); - } - else - { - assert(opReg == reg1); - - // reg0 = opReg. - // swap upper and lower 8-bytes of reg1 so that desired 8-byte is in bit position [63:0]. - inst_RV_RV(ins_Copy(TYP_DOUBLE), reg0, opReg, TYP_DOUBLE); - } - inst_RV_RV_IV(INS_shufpd, EA_16BYTE, reg1, reg1, 0x01); - } - else - { - assert(op1->isContained()); - - // Copy var on stack into ABI return registers - int offset = 0; - for (unsigned i = 0; i < regCount; ++i) - { - var_types type = retTypeDesc.GetReturnRegType(i); - regNumber reg = retTypeDesc.GetABIReturnReg(i); - getEmitter()->emitIns_R_S(ins_Load(type), emitTypeSize(type), reg, lclVar->gtLclNum, offset); - offset += genTypeSize(type); - } - } - } - else + // Is this a node whose value is already in a register? LSRA denotes this by + // setting the GTF_REUSE_REG_VAL flag. + if (treeNode->IsReuseRegVal()) { - assert(op1->IsMultiRegCall() || op1->IsCopyOrReloadOfMultiRegCall()); - - genConsumeRegs(op1); - - GenTree* actualOp1 = op1->gtSkipReloadOrCopy(); - GenTreeCall* call = actualOp1->AsCall(); - ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); - unsigned regCount = retTypeDesc->GetReturnRegCount(); - assert(regCount == MAX_RET_REG_COUNT); - - // Handle circular dependency between call allocated regs and ABI return regs. - // - // It is possible under LSRA stress that originally allocated regs of call node, - // say rax and rdx, are spilled and reloaded to rdx and rax respectively. But - // GT_RETURN needs to move values as follows: rdx->rax, rax->rdx. Similar kind - // kind of circular dependency could arise between xmm0 and xmm1 return regs. - // Codegen is expected to handle such circular dependency. - // - var_types regType0 = retTypeDesc->GetReturnRegType(0); - regNumber returnReg0 = retTypeDesc->GetABIReturnReg(0); - regNumber allocatedReg0 = call->GetRegNumByIdx(0); - - var_types regType1 = retTypeDesc->GetReturnRegType(1); - regNumber returnReg1 = retTypeDesc->GetABIReturnReg(1); - regNumber allocatedReg1 = call->GetRegNumByIdx(1); - - if (op1->IsCopyOrReload()) - { - // GT_COPY/GT_RELOAD will have valid reg for those positions - // that need to be copied or reloaded. - regNumber reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(0); - if (reloadReg != REG_NA) - { - allocatedReg0 = reloadReg; - } - - reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(1); - if (reloadReg != REG_NA) - { - allocatedReg1 = reloadReg; - } - } - - if (allocatedReg0 == returnReg1 && allocatedReg1 == returnReg0) - { - // Circular dependency - swap allocatedReg0 and allocatedReg1 - if (varTypeIsFloating(regType0)) - { - assert(varTypeIsFloating(regType1)); - - // The fastest way to swap two XMM regs is using PXOR - inst_RV_RV(INS_pxor, allocatedReg0, allocatedReg1, TYP_DOUBLE); - inst_RV_RV(INS_pxor, allocatedReg1, allocatedReg0, TYP_DOUBLE); - inst_RV_RV(INS_pxor, allocatedReg0, allocatedReg1, TYP_DOUBLE); - } - else - { - assert(varTypeIsIntegral(regType0)); - assert(varTypeIsIntegral(regType1)); - inst_RV_RV(INS_xchg, allocatedReg1, allocatedReg0, TYP_I_IMPL); - } - } - else if (allocatedReg1 == returnReg0) - { - // Change the order of moves to correctly handle dependency. - if (allocatedReg1 != returnReg1) - { - inst_RV_RV(ins_Copy(regType1), returnReg1, allocatedReg1, regType1); - } - - if (allocatedReg0 != returnReg0) - { - inst_RV_RV(ins_Copy(regType0), returnReg0, allocatedReg0, regType0); - } - } - else - { - // No circular dependency case. - if (allocatedReg0 != returnReg0) - { - inst_RV_RV(ins_Copy(regType0), returnReg0, allocatedReg0, regType0); - } - - if (allocatedReg1 != returnReg1) - { - inst_RV_RV(ins_Copy(regType1), returnReg1, allocatedReg1, regType1); - } - } + // For now, this is only used for constant nodes. + assert((treeNode->OperIsConst())); + JITDUMP(" TreeNode is marked ReuseReg\n"); + return; } -#else - unreached(); -#endif -} - -//------------------------------------------------------------------------ -// genReturn: Generates code for return statement. -// In case of struct return, delegates to the genStructReturn method. -// -// Arguments: -// treeNode - The GT_RETURN or GT_RETFILT tree node. -// -// Return Value: -// None -// -void CodeGen::genReturn(GenTreePtr treeNode) -{ - assert(treeNode->OperGet() == GT_RETURN || treeNode->OperGet() == GT_RETFILT); - GenTreePtr op1 = treeNode->gtGetOp1(); - var_types targetType = treeNode->TypeGet(); -#ifdef DEBUG - if (targetType == TYP_VOID) + // contained nodes are part of their parents for codegen purposes + // ex : immediates, most LEAs + if (treeNode->isContained()) { - assert(op1 == nullptr); + return; } -#endif - -#ifdef _TARGET_X86_ - if (treeNode->TypeGet() == TYP_LONG) - { - assert(op1 != nullptr); - noway_assert(op1->OperGet() == GT_LONG); - GenTree* loRetVal = op1->gtGetOp1(); - GenTree* hiRetVal = op1->gtGetOp2(); - noway_assert((loRetVal->gtRegNum != REG_NA) && (hiRetVal->gtRegNum != REG_NA)); - genConsumeReg(loRetVal); - genConsumeReg(hiRetVal); - if (loRetVal->gtRegNum != REG_LNGRET_LO) - { - inst_RV_RV(ins_Copy(targetType), REG_LNGRET_LO, loRetVal->gtRegNum, TYP_INT); - } - if (hiRetVal->gtRegNum != REG_LNGRET_HI) - { - inst_RV_RV(ins_Copy(targetType), REG_LNGRET_HI, hiRetVal->gtRegNum, TYP_INT); - } - } - else -#endif // !defined(_TARGET_X86_) + switch (treeNode->gtOper) { - if (isStructReturn(treeNode)) - { - genStructReturn(treeNode); - } - else if (targetType != TYP_VOID) - { - assert(op1 != nullptr); - noway_assert(op1->gtRegNum != REG_NA); - - // !! NOTE !! genConsumeReg will clear op1 as GC ref after it has - // consumed a reg for the operand. This is because the variable - // is dead after return. But we are issuing more instructions - // like "profiler leave callback" after this consumption. So - // if you are issuing more instructions after this point, - // remember to keep the variable live up until the new method - // exit point where it is actually dead. - genConsumeReg(op1); +#ifndef JIT32_GCENCODER + case GT_START_NONGC: + getEmitter()->emitDisableGC(); + break; +#endif // !defined(JIT32_GCENCODER) - regNumber retReg = varTypeIsFloating(treeNode) ? REG_FLOATRET : REG_INTRET; -#ifdef _TARGET_X86_ - if (varTypeIsFloating(treeNode)) - { - // Spill the return value register from an XMM register to the stack, then load it on the x87 stack. - // If it already has a home location, use that. Otherwise, we need a temp. - if (genIsRegCandidateLocal(op1) && compiler->lvaTable[op1->gtLclVarCommon.gtLclNum].lvOnFrame) - { - // Store local variable to its home location, if necessary. - if ((op1->gtFlags & GTF_REG_VAL) != 0) - { - op1->gtFlags &= ~GTF_REG_VAL; - inst_TT_RV(ins_Store(op1->gtType, - compiler->isSIMDTypeLocalAligned(op1->gtLclVarCommon.gtLclNum)), - op1, op1->gtRegNum); - } - // Now, load it to the fp stack. - getEmitter()->emitIns_S(INS_fld, emitTypeSize(op1), op1->AsLclVarCommon()->gtLclNum, 0); - } - else - { - // Spill the value, which should be in a register, then load it to the fp stack. - // TODO-X86-CQ: Deal with things that are already in memory (don't call genConsumeReg yet). - op1->gtFlags |= GTF_SPILL; - regSet.rsSpillTree(op1->gtRegNum, op1); - op1->gtFlags |= GTF_SPILLED; - op1->gtFlags &= ~GTF_SPILL; - - TempDsc* t = regSet.rsUnspillInPlace(op1, op1->gtRegNum); - inst_FS_ST(INS_fld, emitActualTypeSize(op1->gtType), t, 0); - op1->gtFlags &= ~GTF_SPILLED; - compiler->tmpRlsTemp(t); - } - } - else -#endif // _TARGET_X86_ - { - if (op1->gtRegNum != retReg) - { - inst_RV_RV(ins_Copy(targetType), retReg, op1->gtRegNum, targetType); - } - } - } - } - -#ifdef PROFILING_SUPPORTED - // !! Note !! - // TODO-AMD64-Unix: If the profiler hook is implemented on *nix, make sure for 2 register returned structs - // the RAX and RDX needs to be kept alive. Make the necessary changes in lowerxarch.cpp - // in the handling of the GT_RETURN statement. - // Such structs containing GC pointers need to be handled by calling gcInfo.gcMarkRegSetNpt - // for the return registers containing GC refs. - - // There will be a single return block while generating profiler ELT callbacks. - // - // Reason for not materializing Leave callback as a GT_PROF_HOOK node after GT_RETURN: - // In flowgraph and other places assert that the last node of a block marked as - // GT_RETURN is either a GT_RETURN or GT_JMP or a tail call. It would be nice to - // maintain such an invariant irrespective of whether profiler hook needed or not. - // Also, there is not much to be gained by materializing it as an explicit node. - if (compiler->compCurBB == compiler->genReturnBB) - { - // !! NOTE !! - // Since we are invalidating the assumption that we would slip into the epilog - // right after the "return", we need to preserve the return reg's GC state - // across the call until actual method return. - if (varTypeIsGC(compiler->info.compRetType)) - { - gcInfo.gcMarkRegPtrVal(REG_INTRET, compiler->info.compRetType); - } - - genProfilingLeaveCallback(); - - if (varTypeIsGC(compiler->info.compRetType)) - { - gcInfo.gcMarkRegSetNpt(REG_INTRET); - } - } -#endif -} - -/***************************************************************************** - * - * Generate code for a single node in the tree. - * Preconditions: All operands have been evaluated - * - */ -void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) -{ - regNumber targetReg; -#if !defined(_TARGET_64BIT_) - if (treeNode->TypeGet() == TYP_LONG) - { - // All long enregistered nodes will have been decomposed into their - // constituent lo and hi nodes. - targetReg = REG_NA; - } - else -#endif // !defined(_TARGET_64BIT_) - { - targetReg = treeNode->gtRegNum; - } - var_types targetType = treeNode->TypeGet(); - emitter* emit = getEmitter(); - -#ifdef DEBUG - // Validate that all the operands for the current node are consumed in order. - // This is important because LSRA ensures that any necessary copies will be - // handled correctly. - lastConsumedNode = nullptr; - if (compiler->verbose) - { - unsigned seqNum = treeNode->gtSeqNum; // Useful for setting a conditional break in Visual Studio - printf("Generating: "); - compiler->gtDispTree(treeNode, nullptr, nullptr, true); - } -#endif // DEBUG - - // Is this a node whose value is already in a register? LSRA denotes this by - // setting the GTF_REUSE_REG_VAL flag. - if (treeNode->IsReuseRegVal()) - { - // For now, this is only used for constant nodes. - assert((treeNode->OperIsConst())); - JITDUMP(" TreeNode is marked ReuseReg\n"); - return; - } - - // contained nodes are part of their parents for codegen purposes - // ex : immediates, most LEAs - if (treeNode->isContained()) - { - return; - } - - switch (treeNode->gtOper) - { - case GT_START_NONGC: - getEmitter()->emitDisableGC(); - break; - - case GT_PROF_HOOK: -#ifdef PROFILING_SUPPORTED - // We should be seeing this only if profiler hook is needed - noway_assert(compiler->compIsProfilerHookNeeded()); + case GT_PROF_HOOK: +#ifdef PROFILING_SUPPORTED + // We should be seeing this only if profiler hook is needed + noway_assert(compiler->compIsProfilerHookNeeded()); // Right now this node is used only for tail calls. In future if // we intend to use it for Enter or Leave hooks, add a data member @@ -1930,3752 +1303,3180 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) #endif // PROFILING_SUPPORTED break; - case GT_LCLHEAP: - genLclHeap(treeNode); - break; - - case GT_CNS_INT: -#ifdef _TARGET_X86_ - NYI_IF(treeNode->IsIconHandle(GTF_ICON_TLS_HDL), "TLS constants"); -#endif // _TARGET_X86_ - __fallthrough; - - case GT_CNS_DBL: - genSetRegToConst(targetReg, targetType, treeNode); - genProduceReg(treeNode); - break; - - case GT_NEG: - case GT_NOT: - if (varTypeIsFloating(targetType)) - { - assert(treeNode->gtOper == GT_NEG); - genSSE2BitwiseOp(treeNode); - } - else - { - GenTreePtr operand = treeNode->gtGetOp1(); - assert(!operand->isContained()); - regNumber operandReg = genConsumeReg(operand); - - if (operandReg != targetReg) - { - inst_RV_RV(INS_mov, targetReg, operandReg, targetType); - } - - instruction ins = genGetInsForOper(treeNode->OperGet(), targetType); - inst_RV(ins, targetReg, targetType); - } - genProduceReg(treeNode); - break; - - case GT_OR: - case GT_XOR: - case GT_AND: - assert(varTypeIsIntegralOrI(treeNode)); - __fallthrough; - -#if !defined(_TARGET_64BIT_) - case GT_ADD_LO: - case GT_ADD_HI: - case GT_SUB_LO: - case GT_SUB_HI: -#endif // !defined(_TARGET_64BIT_) - case GT_ADD: - case GT_SUB: - genConsumeOperands(treeNode->AsOp()); - genCodeForBinary(treeNode); - break; - - case GT_LSH: - case GT_RSH: - case GT_RSZ: - case GT_ROL: - case GT_ROR: - genCodeForShift(treeNode); - // genCodeForShift() calls genProduceReg() - break; - - case GT_CAST: -#if !defined(_TARGET_64BIT_) - // We will NYI in DecomposeNode() if we are cast TO a long type, but we do not - // yet support casting FROM a long type either, and that's simpler to catch - // here. - NYI_IF(varTypeIsLong(treeNode->gtOp.gtOp1), "Casts from TYP_LONG"); -#endif // !defined(_TARGET_64BIT_) - - if (varTypeIsFloating(targetType) && varTypeIsFloating(treeNode->gtOp.gtOp1)) - { - // Casts float/double <--> double/float - genFloatToFloatCast(treeNode); - } - else if (varTypeIsFloating(treeNode->gtOp.gtOp1)) - { - // Casts float/double --> int32/int64 - genFloatToIntCast(treeNode); - } - else if (varTypeIsFloating(targetType)) - { - // Casts int32/uint32/int64/uint64 --> float/double - genIntToFloatCast(treeNode); - } - else - { - // Casts int <--> int - genIntToIntCast(treeNode); - } - // The per-case functions call genProduceReg() - break; - - case GT_LCL_VAR: - { - // lcl_vars are not defs - assert((treeNode->gtFlags & GTF_VAR_DEF) == 0); - - GenTreeLclVarCommon* lcl = treeNode->AsLclVarCommon(); - bool isRegCandidate = compiler->lvaTable[lcl->gtLclNum].lvIsRegCandidate(); - - if (isRegCandidate && !(treeNode->gtFlags & GTF_VAR_DEATH)) - { - assert((treeNode->InReg()) || (treeNode->gtFlags & GTF_SPILLED)); - } - - // If this is a register candidate that has been spilled, genConsumeReg() will - // reload it at the point of use. Otherwise, if it's not in a register, we load it here. - - if (!treeNode->InReg() && !(treeNode->gtFlags & GTF_SPILLED)) - { - assert(!isRegCandidate); - - emit->emitIns_R_S(ins_Load(treeNode->TypeGet(), compiler->isSIMDTypeLocalAligned(lcl->gtLclNum)), - emitTypeSize(treeNode), treeNode->gtRegNum, lcl->gtLclNum, 0); - genProduceReg(treeNode); - } - } - break; - - case GT_LCL_FLD_ADDR: - case GT_LCL_VAR_ADDR: - // Address of a local var. This by itself should never be allocated a register. - // If it is worth storing the address in a register then it should be cse'ed into - // a temp and that would be allocated a register. - noway_assert(targetType == TYP_BYREF); - noway_assert(!treeNode->InReg()); - - inst_RV_TT(INS_lea, targetReg, treeNode, 0, EA_BYREF); - genProduceReg(treeNode); - break; - - case GT_LCL_FLD: - { - noway_assert(targetType != TYP_STRUCT); - noway_assert(treeNode->gtRegNum != REG_NA); - -#ifdef FEATURE_SIMD - // Loading of TYP_SIMD12 (i.e. Vector3) field - if (treeNode->TypeGet() == TYP_SIMD12) - { - genLoadLclFldTypeSIMD12(treeNode); - break; - } -#endif - - emitAttr size = emitTypeSize(targetType); - unsigned offs = treeNode->gtLclFld.gtLclOffs; - unsigned varNum = treeNode->gtLclVarCommon.gtLclNum; - assert(varNum < compiler->lvaCount); - - emit->emitIns_R_S(ins_Move_Extend(targetType, treeNode->InReg()), size, targetReg, varNum, offs); - } - genProduceReg(treeNode); - break; - - case GT_STORE_LCL_FLD: - { - noway_assert(targetType != TYP_STRUCT); - noway_assert(!treeNode->InReg()); - assert(!varTypeIsFloating(targetType) || (targetType == treeNode->gtGetOp1()->TypeGet())); - -#ifdef FEATURE_SIMD - // storing of TYP_SIMD12 (i.e. Vector3) field - if (treeNode->TypeGet() == TYP_SIMD12) - { - genStoreLclFldTypeSIMD12(treeNode); - break; - } -#endif - GenTreePtr op1 = treeNode->gtGetOp1(); - genConsumeRegs(op1); - emit->emitInsBinary(ins_Store(targetType), emitTypeSize(treeNode), treeNode, op1); - } - break; - - case GT_STORE_LCL_VAR: - { - GenTreePtr op1 = treeNode->gtGetOp1(); - - // var = call, where call returns a multi-reg return value - // case is handled separately. - if (op1->gtSkipReloadOrCopy()->IsMultiRegCall()) - { - genMultiRegCallStoreToLocal(treeNode); - } - else - { - noway_assert(targetType != TYP_STRUCT); - assert(!varTypeIsFloating(targetType) || (targetType == treeNode->gtGetOp1()->TypeGet())); - - unsigned lclNum = treeNode->AsLclVarCommon()->gtLclNum; - LclVarDsc* varDsc = &(compiler->lvaTable[lclNum]); - - // Ensure that lclVar nodes are typed correctly. - assert(!varDsc->lvNormalizeOnStore() || treeNode->TypeGet() == genActualType(varDsc->TypeGet())); - -#if !defined(_TARGET_64BIT_) - if (treeNode->TypeGet() == TYP_LONG) - { - genStoreLongLclVar(treeNode); - break; - } -#endif // !defined(_TARGET_64BIT_) - -#ifdef FEATURE_SIMD - if (varTypeIsSIMD(targetType) && (targetReg != REG_NA) && op1->IsCnsIntOrI()) - { - // This is only possible for a zero-init. - noway_assert(op1->IsIntegralConst(0)); - genSIMDZero(targetType, varDsc->lvBaseType, targetReg); - genProduceReg(treeNode); - break; - } -#endif // FEATURE_SIMD - - genConsumeRegs(op1); - - if (treeNode->gtRegNum == REG_NA) - { - // stack store - emit->emitInsMov(ins_Store(targetType, compiler->isSIMDTypeLocalAligned(lclNum)), - emitTypeSize(targetType), treeNode); - varDsc->lvRegNum = REG_STK; - } - else - { - bool containedOp1 = op1->isContained(); - // Look for the case where we have a constant zero which we've marked for reuse, - // but which isn't actually in the register we want. In that case, it's better to create - // zero in the target register, because an xor is smaller than a copy. Note that we could - // potentially handle this in the register allocator, but we can't always catch it there - // because the target may not have a register allocated for it yet. - if (!containedOp1 && (op1->gtRegNum != treeNode->gtRegNum) && - (op1->IsIntegralConst(0) || op1->IsFPZero())) - { - op1->gtRegNum = REG_NA; - op1->ResetReuseRegVal(); - containedOp1 = true; - } - - if (containedOp1) - { - // Currently, we assume that the contained source of a GT_STORE_LCL_VAR writing to a register - // must be a constant. However, in the future we might want to support a contained memory op. - // This is a bit tricky because we have to decide it's contained before register allocation, - // and this would be a case where, once that's done, we need to mark that node as always - // requiring a register - which we always assume now anyway, but once we "optimize" that - // we'll have to take cases like this into account. - assert((op1->gtRegNum == REG_NA) && op1->OperIsConst()); - genSetRegToConst(treeNode->gtRegNum, targetType, op1); - } - else if (op1->gtRegNum != treeNode->gtRegNum) - { - assert(op1->gtRegNum != REG_NA); - emit->emitInsBinary(ins_Move_Extend(targetType, true), emitTypeSize(treeNode), treeNode, op1); - } - } - } - - if (treeNode->gtRegNum != REG_NA) - { - genProduceReg(treeNode); - } - } - break; - - case GT_RETFILT: - // A void GT_RETFILT is the end of a finally. For non-void filter returns we need to load the result in - // the return register, if it's not already there. The processing is the same as GT_RETURN. - if (targetType != TYP_VOID) - { - // For filters, the IL spec says the result is type int32. Further, the only specified legal values - // are 0 or 1, with the use of other values "undefined". - assert(targetType == TYP_INT); - } - - __fallthrough; - - case GT_RETURN: - genReturn(treeNode); - break; - - case GT_LEA: - { - // if we are here, it is the case where there is an LEA that cannot - // be folded into a parent instruction - GenTreeAddrMode* lea = treeNode->AsAddrMode(); - genLeaInstruction(lea); - } - // genLeaInstruction calls genProduceReg() - break; - - case GT_IND: -#ifdef FEATURE_SIMD - // Handling of Vector3 type values loaded through indirection. - if (treeNode->TypeGet() == TYP_SIMD12) - { - genLoadIndTypeSIMD12(treeNode); - break; - } -#endif // FEATURE_SIMD - - genConsumeAddress(treeNode->AsIndir()->Addr()); - emit->emitInsMov(ins_Load(treeNode->TypeGet()), emitTypeSize(treeNode), treeNode); - genProduceReg(treeNode); - break; - - case GT_MULHI: - genCodeForMulHi(treeNode->AsOp()); - genProduceReg(treeNode); - break; - - case GT_MUL: - { - instruction ins; - emitAttr size = emitTypeSize(treeNode); - bool isUnsignedMultiply = ((treeNode->gtFlags & GTF_UNSIGNED) != 0); - bool requiresOverflowCheck = treeNode->gtOverflowEx(); - - GenTree* op1 = treeNode->gtGetOp1(); - GenTree* op2 = treeNode->gtGetOp2(); - - // there are 3 forms of x64 multiply: - // 1-op form with 128 result: RDX:RAX = RAX * rm - // 2-op form: reg *= rm - // 3-op form: reg = rm * imm - - genConsumeOperands(treeNode->AsOp()); - - // This matches the 'mul' lowering in Lowering::SetMulOpCounts() - // - // immOp :: Only one operand can be an immediate - // rmOp :: Only one operand can be a memory op. - // regOp :: A register op (especially the operand that matches 'targetReg') - // (can be nullptr when we have both a memory op and an immediate op) - - GenTree* immOp = nullptr; - GenTree* rmOp = op1; - GenTree* regOp; - - if (op2->isContainedIntOrIImmed()) - { - immOp = op2; - } - else if (op1->isContainedIntOrIImmed()) - { - immOp = op1; - rmOp = op2; - } - - if (immOp != nullptr) - { - // This must be a non-floating point operation. - assert(!varTypeIsFloating(treeNode)); - - // CQ: When possible use LEA for mul by imm 3, 5 or 9 - ssize_t imm = immOp->AsIntConCommon()->IconValue(); - - if (!requiresOverflowCheck && !rmOp->isContained() && ((imm == 3) || (imm == 5) || (imm == 9))) - { - // We will use the LEA instruction to perform this multiply - // Note that an LEA with base=x, index=x and scale=(imm-1) computes x*imm when imm=3,5 or 9. - unsigned int scale = (unsigned int)(imm - 1); - getEmitter()->emitIns_R_ARX(INS_lea, size, targetReg, rmOp->gtRegNum, rmOp->gtRegNum, scale, 0); - } - else - { - // use the 3-op form with immediate - ins = getEmitter()->inst3opImulForReg(targetReg); - emit->emitInsBinary(ins, size, rmOp, immOp); - } - } - else // we have no contained immediate operand - { - regOp = op1; - rmOp = op2; - - regNumber mulTargetReg = targetReg; - if (isUnsignedMultiply && requiresOverflowCheck) - { - ins = INS_mulEAX; - mulTargetReg = REG_RAX; - } - else - { - ins = genGetInsForOper(GT_MUL, targetType); - } + case GT_LCLHEAP: + genLclHeap(treeNode); + break; - // Set rmOp to the contain memory operand (if any) - // or set regOp to the op2 when it has the matching target register for our multiply op - // - if (op1->isContained() || (!op2->isContained() && (op2->gtRegNum == mulTargetReg))) - { - regOp = op2; - rmOp = op1; - } - assert(!regOp->isContained()); + case GT_CNS_INT: +#ifdef _TARGET_X86_ + NYI_IF(treeNode->IsIconHandle(GTF_ICON_TLS_HDL), "TLS constants"); +#endif // _TARGET_X86_ + __fallthrough; - // Setup targetReg when neither of the source operands was a matching register - if (regOp->gtRegNum != mulTargetReg) - { - inst_RV_RV(ins_Copy(targetType), mulTargetReg, regOp->gtRegNum, targetType); - } + case GT_CNS_DBL: + genSetRegToConst(targetReg, targetType, treeNode); + genProduceReg(treeNode); + break; - emit->emitInsBinary(ins, size, treeNode, rmOp); + case GT_NEG: + case GT_NOT: + if (varTypeIsFloating(targetType)) + { + assert(treeNode->gtOper == GT_NEG); + genSSE2BitwiseOp(treeNode); + } + else + { + GenTreePtr operand = treeNode->gtGetOp1(); + assert(!operand->isContained()); + regNumber operandReg = genConsumeReg(operand); - // Move the result to the desired register, if necessary - if ((ins == INS_mulEAX) && (targetReg != REG_RAX)) + if (operandReg != targetReg) { - inst_RV_RV(INS_mov, targetReg, REG_RAX, targetType); + inst_RV_RV(INS_mov, targetReg, operandReg, targetType); } - } - - if (requiresOverflowCheck) - { - // Overflow checking is only used for non-floating point types - noway_assert(!varTypeIsFloating(treeNode)); - genCheckOverflow(treeNode); + instruction ins = genGetInsForOper(treeNode->OperGet(), targetType); + inst_RV(ins, targetReg, targetType); } - } genProduceReg(treeNode); break; - case GT_MOD: - case GT_UDIV: - case GT_UMOD: - // We shouldn't be seeing GT_MOD on float/double args as it should get morphed into a - // helper call by front-end. Similarly we shouldn't be seeing GT_UDIV and GT_UMOD - // on float/double args. - noway_assert(!varTypeIsFloating(treeNode)); + case GT_OR: + case GT_XOR: + case GT_AND: + assert(varTypeIsIntegralOrI(treeNode)); __fallthrough; - case GT_DIV: - genCodeForDivMod(treeNode->AsOp()); - break; - - case GT_INTRINSIC: - genIntrinsic(treeNode); +#if !defined(_TARGET_64BIT_) + case GT_ADD_LO: + case GT_ADD_HI: + case GT_SUB_LO: + case GT_SUB_HI: +#endif // !defined(_TARGET_64BIT_) + case GT_ADD: + case GT_SUB: + genConsumeOperands(treeNode->AsOp()); + genCodeForBinary(treeNode); break; -#ifdef FEATURE_SIMD - case GT_SIMD: - genSIMDIntrinsic(treeNode->AsSIMD()); + case GT_LSH: + case GT_RSH: + case GT_RSZ: + case GT_ROL: + case GT_ROR: + genCodeForShift(treeNode); + // genCodeForShift() calls genProduceReg() break; -#endif // FEATURE_SIMD - case GT_CKFINITE: - genCkfinite(treeNode); +#if !defined(_TARGET_64BIT_) + case GT_LSH_HI: + case GT_RSH_LO: + // TODO-X86-CQ: This only handles the case where the operand being shifted is in a register. We don't + // need sourceHi to be always in reg in case of GT_LSH_HI (because it could be moved from memory to + // targetReg if sourceHi is a contained mem-op). Similarly for GT_RSH_LO, sourceLo could be marked as + // contained memory-op. Even if not a memory-op, we could mark it as reg-optional. + genCodeForShiftLong(treeNode); break; +#endif - case GT_EQ: - case GT_NE: - case GT_LT: - case GT_LE: - case GT_GE: - case GT_GT: - { - // TODO-XArch-CQ: Check if we can use the currently set flags. - // TODO-XArch-CQ: Check for the case where we can simply transfer the carry bit to a register - // (signed < or >= where targetReg != REG_NA) - - GenTreePtr op1 = treeNode->gtGetOp1(); - var_types op1Type = op1->TypeGet(); - - if (varTypeIsFloating(op1Type)) + case GT_CAST: + if (varTypeIsFloating(targetType) && varTypeIsFloating(treeNode->gtOp.gtOp1)) { - genCompareFloat(treeNode); + // Casts float/double <--> double/float + genFloatToFloatCast(treeNode); } -#if !defined(_TARGET_64BIT_) - // X86 Long comparison - else if (varTypeIsLong(op1Type)) + else if (varTypeIsFloating(treeNode->gtOp.gtOp1)) { - // When not materializing the result in a register, the compare logic is generated - // when we generate the GT_JTRUE. - if (treeNode->gtRegNum != REG_NA) - { - genCompareLong(treeNode); - } - else - { - // We generate the compare when we generate the GT_JTRUE, but we need to consume - // the operands now. - genConsumeOperands(treeNode->AsOp()); - } + // Casts float/double --> int32/int64 + genFloatToIntCast(treeNode); + } + else if (varTypeIsFloating(targetType)) + { + // Casts int32/uint32/int64/uint64 --> float/double + genIntToFloatCast(treeNode); } -#endif // !defined(_TARGET_64BIT_) else { - genCompareInt(treeNode); + // Casts int <--> int + genIntToIntCast(treeNode); } - } - break; + // The per-case functions call genProduceReg() + break; - case GT_JTRUE: + case GT_LCL_VAR: { - GenTree* cmp = treeNode->gtOp.gtOp1; + // lcl_vars are not defs + assert((treeNode->gtFlags & GTF_VAR_DEF) == 0); - assert(cmp->OperIsCompare()); - assert(compiler->compCurBB->bbJumpKind == BBJ_COND); + GenTreeLclVarCommon* lcl = treeNode->AsLclVarCommon(); + bool isRegCandidate = compiler->lvaTable[lcl->gtLclNum].lvIsRegCandidate(); -#if !defined(_TARGET_64BIT_) - // For long compares, we emit special logic - if (varTypeIsLong(cmp->gtGetOp1())) + if (isRegCandidate && !(treeNode->gtFlags & GTF_VAR_DEATH)) { - genJTrueLong(cmp); + assert(treeNode->InReg() || (treeNode->gtFlags & GTF_SPILLED)); } - else -#endif - { - // Get the "kind" and type of the comparison. Note that whether it is an unsigned cmp - // is governed by a flag NOT by the inherent type of the node - // TODO-XArch-CQ: Check if we can use the currently set flags. - emitJumpKind jumpKind[2]; - bool branchToTrueLabel[2]; - genJumpKindsForTree(cmp, jumpKind, branchToTrueLabel); - BasicBlock* skipLabel = nullptr; - if (jumpKind[0] != EJ_NONE) - { - BasicBlock* jmpTarget; - if (branchToTrueLabel[0]) - { - jmpTarget = compiler->compCurBB->bbJumpDest; - } - else - { - // This case arises only for ordered GT_EQ right now - assert((cmp->gtOper == GT_EQ) && ((cmp->gtFlags & GTF_RELOP_NAN_UN) == 0)); - skipLabel = genCreateTempLabel(); - jmpTarget = skipLabel; - } + // If this is a register candidate that has been spilled, genConsumeReg() will + // reload it at the point of use. Otherwise, if it's not in a register, we load it here. - inst_JMP(jumpKind[0], jmpTarget); - } + if (!treeNode->InReg() && !(treeNode->gtFlags & GTF_SPILLED)) + { + assert(!isRegCandidate); - if (jumpKind[1] != EJ_NONE) +#if defined(FEATURE_SIMD) && defined(_TARGET_X86_) + // Loading of TYP_SIMD12 (i.e. Vector3) variable + if (treeNode->TypeGet() == TYP_SIMD12) { - // the second conditional branch always has to be to the true label - assert(branchToTrueLabel[1]); - inst_JMP(jumpKind[1], compiler->compCurBB->bbJumpDest); + genLoadLclTypeSIMD12(treeNode); + break; } +#endif // defined(FEATURE_SIMD) && defined(_TARGET_X86_) - if (skipLabel != nullptr) - { - genDefineTempLabel(skipLabel); - } + emit->emitIns_R_S(ins_Load(treeNode->TypeGet(), compiler->isSIMDTypeLocalAligned(lcl->gtLclNum)), + emitTypeSize(treeNode), treeNode->gtRegNum, lcl->gtLclNum, 0); + genProduceReg(treeNode); } } break; - case GT_RETURNTRAP: - { - // this is nothing but a conditional call to CORINFO_HELP_STOP_FOR_GC - // based on the contents of 'data' - - GenTree* data = treeNode->gtOp.gtOp1; - genConsumeRegs(data); - GenTreeIntCon cns = intForm(TYP_INT, 0); - emit->emitInsBinary(INS_cmp, emitTypeSize(TYP_INT), data, &cns); - - BasicBlock* skipLabel = genCreateTempLabel(); - - emitJumpKind jmpEqual = genJumpKindForOper(GT_EQ, CK_SIGNED); - inst_JMP(jmpEqual, skipLabel); - - // emit the call to the EE-helper that stops for GC (or other reasons) - assert(treeNode->gtRsvdRegs != RBM_NONE); - assert(genCountBits(treeNode->gtRsvdRegs) == 1); - regNumber tmpReg = genRegNumFromMask(treeNode->gtRsvdRegs); - assert(genIsValidIntReg(tmpReg)); - - genEmitHelperCall(CORINFO_HELP_STOP_FOR_GC, 0, EA_UNKNOWN, tmpReg); - genDefineTempLabel(skipLabel); - } - break; - - case GT_STOREIND: - genStoreInd(treeNode); - break; + case GT_LCL_FLD_ADDR: + case GT_LCL_VAR_ADDR: + // Address of a local var. This by itself should never be allocated a register. + // If it is worth storing the address in a register then it should be cse'ed into + // a temp and that would be allocated a register. + noway_assert(targetType == TYP_BYREF); + noway_assert(!treeNode->InReg()); - case GT_COPY: - // This is handled at the time we call genConsumeReg() on the GT_COPY + inst_RV_TT(INS_lea, targetReg, treeNode, 0, EA_BYREF); + genProduceReg(treeNode); break; - case GT_SWAP: + case GT_LCL_FLD: { - // Swap is only supported for lclVar operands that are enregistered - // We do not consume or produce any registers. Both operands remain enregistered. - // However, the gc-ness may change. - assert(genIsRegCandidateLocal(treeNode->gtOp.gtOp1) && genIsRegCandidateLocal(treeNode->gtOp.gtOp2)); - - GenTreeLclVarCommon* lcl1 = treeNode->gtOp.gtOp1->AsLclVarCommon(); - LclVarDsc* varDsc1 = &(compiler->lvaTable[lcl1->gtLclNum]); - var_types type1 = varDsc1->TypeGet(); - GenTreeLclVarCommon* lcl2 = treeNode->gtOp.gtOp2->AsLclVarCommon(); - LclVarDsc* varDsc2 = &(compiler->lvaTable[lcl2->gtLclNum]); - var_types type2 = varDsc2->TypeGet(); - - // We must have both int or both fp regs - assert(!varTypeIsFloating(type1) || varTypeIsFloating(type2)); - - // FP swap is not yet implemented (and should have NYI'd in LSRA) - assert(!varTypeIsFloating(type1)); - - regNumber oldOp1Reg = lcl1->gtRegNum; - regMaskTP oldOp1RegMask = genRegMask(oldOp1Reg); - regNumber oldOp2Reg = lcl2->gtRegNum; - regMaskTP oldOp2RegMask = genRegMask(oldOp2Reg); - - // We don't call genUpdateVarReg because we don't have a tree node with the new register. - varDsc1->lvRegNum = oldOp2Reg; - varDsc2->lvRegNum = oldOp1Reg; - - // Do the xchg - emitAttr size = EA_PTRSIZE; - if (varTypeGCtype(type1) != varTypeGCtype(type2)) + noway_assert(targetType != TYP_STRUCT); + noway_assert(treeNode->gtRegNum != REG_NA); + +#ifdef FEATURE_SIMD + // Loading of TYP_SIMD12 (i.e. Vector3) field + if (treeNode->TypeGet() == TYP_SIMD12) { - // If the type specified to the emitter is a GC type, it will swap the GC-ness of the registers. - // Otherwise it will leave them alone, which is correct if they have the same GC-ness. - size = EA_GCREF; + genLoadLclTypeSIMD12(treeNode); + break; } - inst_RV_RV(INS_xchg, oldOp1Reg, oldOp2Reg, TYP_I_IMPL, size); +#endif - // Update the gcInfo. - // Manually remove these regs for the gc sets (mostly to avoid confusing duplicative dump output) - gcInfo.gcRegByrefSetCur &= ~(oldOp1RegMask | oldOp2RegMask); - gcInfo.gcRegGCrefSetCur &= ~(oldOp1RegMask | oldOp2RegMask); + emitAttr size = emitTypeSize(targetType); + unsigned offs = treeNode->gtLclFld.gtLclOffs; + unsigned varNum = treeNode->gtLclVarCommon.gtLclNum; + assert(varNum < compiler->lvaCount); - // gcMarkRegPtrVal will do the appropriate thing for non-gc types. - // It will also dump the updates. - gcInfo.gcMarkRegPtrVal(oldOp2Reg, type1); - gcInfo.gcMarkRegPtrVal(oldOp1Reg, type2); + emit->emitIns_R_S(ins_Move_Extend(targetType, treeNode->InReg()), size, targetReg, varNum, offs); } - break; - - case GT_LIST: - case GT_ARGPLACE: - // Nothing to do - break; - - case GT_PUTARG_STK: - genPutArgStk(treeNode); + genProduceReg(treeNode); break; - case GT_PUTARG_REG: + case GT_STORE_LCL_FLD: { -#ifndef FEATURE_UNIX_AMD64_STRUCT_PASSING noway_assert(targetType != TYP_STRUCT); -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING - // commas show up here commonly, as part of a nullchk operation - GenTree* op1 = treeNode->gtOp.gtOp1; - // If child node is not already in the register we need, move it - genConsumeReg(op1); - if (treeNode->gtRegNum != op1->gtRegNum) + noway_assert(!treeNode->InReg()); + assert(!varTypeIsFloating(targetType) || (targetType == treeNode->gtGetOp1()->TypeGet())); + +#ifdef FEATURE_SIMD + // storing of TYP_SIMD12 (i.e. Vector3) field + if (treeNode->TypeGet() == TYP_SIMD12) { - inst_RV_RV(ins_Copy(targetType), treeNode->gtRegNum, op1->gtRegNum, targetType); + genStoreLclFldTypeSIMD12(treeNode); + break; } - genProduceReg(treeNode); +#endif + GenTreePtr op1 = treeNode->gtGetOp1(); + genConsumeRegs(op1); + emit->emitInsBinary(ins_Store(targetType), emitTypeSize(treeNode), treeNode, op1); } break; - case GT_CALL: - genCallInstruction(treeNode); - break; + case GT_STORE_LCL_VAR: + { + GenTreePtr op1 = treeNode->gtGetOp1(); - case GT_JMP: - genJmpMethod(treeNode); - break; + // var = call, where call returns a multi-reg return value + // case is handled separately. + if (op1->gtSkipReloadOrCopy()->IsMultiRegCall()) + { + genMultiRegCallStoreToLocal(treeNode); + } + else + { + noway_assert(targetType != TYP_STRUCT); + assert(!varTypeIsFloating(targetType) || (targetType == treeNode->gtGetOp1()->TypeGet())); - case GT_LOCKADD: - case GT_XCHG: - case GT_XADD: - genLockedInstructions(treeNode); - break; + unsigned lclNum = treeNode->AsLclVarCommon()->gtLclNum; + LclVarDsc* varDsc = &(compiler->lvaTable[lclNum]); - case GT_MEMORYBARRIER: - instGen_MemoryBarrier(); - break; + // Ensure that lclVar nodes are typed correctly. + assert(!varDsc->lvNormalizeOnStore() || treeNode->TypeGet() == genActualType(varDsc->TypeGet())); - case GT_CMPXCHG: - { - GenTreePtr location = treeNode->gtCmpXchg.gtOpLocation; // arg1 - GenTreePtr value = treeNode->gtCmpXchg.gtOpValue; // arg2 - GenTreePtr comparand = treeNode->gtCmpXchg.gtOpComparand; // arg3 +#if !defined(_TARGET_64BIT_) + if (treeNode->TypeGet() == TYP_LONG) + { + genStoreLongLclVar(treeNode); + break; + } +#endif // !defined(_TARGET_64BIT_) - assert(location->gtRegNum != REG_NA && location->gtRegNum != REG_RAX); - assert(value->gtRegNum != REG_NA && value->gtRegNum != REG_RAX); +#ifdef FEATURE_SIMD + if (varTypeIsSIMD(targetType) && (targetReg != REG_NA) && op1->IsCnsIntOrI()) + { + // This is only possible for a zero-init. + noway_assert(op1->IsIntegralConst(0)); + genSIMDZero(targetType, varDsc->lvBaseType, targetReg); + genProduceReg(treeNode); + break; + } +#endif // FEATURE_SIMD - genConsumeReg(location); - genConsumeReg(value); - genConsumeReg(comparand); - // comparand goes to RAX; - // Note that we must issue this move after the genConsumeRegs(), in case any of the above - // have a GT_COPY from RAX. - if (comparand->gtRegNum != REG_RAX) - { - inst_RV_RV(ins_Copy(comparand->TypeGet()), REG_RAX, comparand->gtRegNum, comparand->TypeGet()); - } + genConsumeRegs(op1); - // location is Rm - instGen(INS_lock); + if (treeNode->gtRegNum == REG_NA) + { + // stack store + emit->emitInsMov(ins_Store(targetType, compiler->isSIMDTypeLocalAligned(lclNum)), + emitTypeSize(targetType), treeNode); + varDsc->lvRegNum = REG_STK; + } + else + { + bool containedOp1 = op1->isContained(); + // Look for the case where we have a constant zero which we've marked for reuse, + // but which isn't actually in the register we want. In that case, it's better to create + // zero in the target register, because an xor is smaller than a copy. Note that we could + // potentially handle this in the register allocator, but we can't always catch it there + // because the target may not have a register allocated for it yet. + if (!containedOp1 && (op1->gtRegNum != treeNode->gtRegNum) && + (op1->IsIntegralConst(0) || op1->IsFPZero())) + { + op1->gtRegNum = REG_NA; + op1->ResetReuseRegVal(); + containedOp1 = true; + } - emit->emitIns_AR_R(INS_cmpxchg, emitTypeSize(targetType), value->gtRegNum, location->gtRegNum, 0); + if (containedOp1) + { + // Currently, we assume that the contained source of a GT_STORE_LCL_VAR writing to a register + // must be a constant. However, in the future we might want to support a contained memory op. + // This is a bit tricky because we have to decide it's contained before register allocation, + // and this would be a case where, once that's done, we need to mark that node as always + // requiring a register - which we always assume now anyway, but once we "optimize" that + // we'll have to take cases like this into account. + assert((op1->gtRegNum == REG_NA) && op1->OperIsConst()); + genSetRegToConst(treeNode->gtRegNum, targetType, op1); + } + else if (op1->gtRegNum != treeNode->gtRegNum) + { + assert(op1->gtRegNum != REG_NA); + emit->emitInsBinary(ins_Move_Extend(targetType, true), emitTypeSize(treeNode), treeNode, op1); + } + } + } - // Result is in RAX - if (targetReg != REG_RAX) + if (treeNode->gtRegNum != REG_NA) { - inst_RV_RV(ins_Copy(targetType), targetReg, REG_RAX, targetType); + genProduceReg(treeNode); } } - genProduceReg(treeNode); - break; - - case GT_RELOAD: - // do nothing - reload is just a marker. - // The parent node will call genConsumeReg on this which will trigger the unspill of this node's child - // into the register specified in this node. - break; - - case GT_NOP: - break; + break; - case GT_NO_OP: - if (treeNode->gtFlags & GTF_NO_OP_NO) - { - noway_assert(!"GTF_NO_OP_NO should not be set"); - } - else + case GT_RETFILT: + // A void GT_RETFILT is the end of a finally. For non-void filter returns we need to load the result in + // the return register, if it's not already there. The processing is the same as GT_RETURN. + if (targetType != TYP_VOID) { - getEmitter()->emitIns_Nop(1); + // For filters, the IL spec says the result is type int32. Further, the only specified legal values + // are 0 or 1, with the use of other values "undefined". + assert(targetType == TYP_INT); } - break; - case GT_ARR_BOUNDS_CHECK: -#ifdef FEATURE_SIMD - case GT_SIMD_CHK: -#endif // FEATURE_SIMD - genRangeCheck(treeNode); + __fallthrough; + + case GT_RETURN: + genReturn(treeNode); break; - case GT_PHYSREG: - if (treeNode->gtRegNum != treeNode->AsPhysReg()->gtSrcReg) - { - inst_RV_RV(INS_mov, treeNode->gtRegNum, treeNode->AsPhysReg()->gtSrcReg, targetType); + case GT_LEA: + { + // if we are here, it is the case where there is an LEA that cannot + // be folded into a parent instruction + GenTreeAddrMode* lea = treeNode->AsAddrMode(); + genLeaInstruction(lea); + } + // genLeaInstruction calls genProduceReg() + break; - genTransferRegGCState(treeNode->gtRegNum, treeNode->AsPhysReg()->gtSrcReg); + case GT_IND: +#ifdef FEATURE_SIMD + // Handling of Vector3 type values loaded through indirection. + if (treeNode->TypeGet() == TYP_SIMD12) + { + genLoadIndTypeSIMD12(treeNode); + break; } +#endif // FEATURE_SIMD + + genConsumeAddress(treeNode->AsIndir()->Addr()); + emit->emitInsMov(ins_Load(treeNode->TypeGet()), emitTypeSize(treeNode), treeNode); genProduceReg(treeNode); break; - case GT_PHYSREGDST: + case GT_MULHI: +#ifdef _TARGET_X86_ + case GT_MUL_LONG: +#endif + genCodeForMulHi(treeNode->AsOp()); + genProduceReg(treeNode); break; - case GT_NULLCHECK: + case GT_MUL: { - assert(!treeNode->gtOp.gtOp1->isContained()); - regNumber reg = genConsumeReg(treeNode->gtOp.gtOp1); - emit->emitIns_AR_R(INS_cmp, EA_4BYTE, reg, reg, 0); - } - break; + instruction ins; + emitAttr size = emitTypeSize(treeNode); + bool isUnsignedMultiply = ((treeNode->gtFlags & GTF_UNSIGNED) != 0); + bool requiresOverflowCheck = treeNode->gtOverflowEx(); - case GT_CATCH_ARG: + GenTree* op1 = treeNode->gtGetOp1(); + GenTree* op2 = treeNode->gtGetOp2(); - noway_assert(handlerGetsXcptnObj(compiler->compCurBB->bbCatchTyp)); + // there are 3 forms of x64 multiply: + // 1-op form with 128 result: RDX:RAX = RAX * rm + // 2-op form: reg *= rm + // 3-op form: reg = rm * imm + + genConsumeOperands(treeNode->AsOp()); - /* Catch arguments get passed in a register. genCodeForBBlist() - would have marked it as holding a GC object, but not used. */ + // This matches the 'mul' lowering in Lowering::SetMulOpCounts() + // + // immOp :: Only one operand can be an immediate + // rmOp :: Only one operand can be a memory op. + // regOp :: A register op (especially the operand that matches 'targetReg') + // (can be nullptr when we have both a memory op and an immediate op) - noway_assert(gcInfo.gcRegGCrefSetCur & RBM_EXCEPTION_OBJECT); - genConsumeReg(treeNode); - break; + GenTree* immOp = nullptr; + GenTree* rmOp = op1; + GenTree* regOp; -#if !FEATURE_EH_FUNCLETS - case GT_END_LFIN: + if (op2->isContainedIntOrIImmed()) + { + immOp = op2; + } + else if (op1->isContainedIntOrIImmed()) + { + immOp = op1; + rmOp = op2; + } - // Have to clear the ShadowSP of the nesting level which encloses the finally. Generates: - // mov dword ptr [ebp-0xC], 0 // for some slot of the ShadowSP local var + if (immOp != nullptr) + { + // This must be a non-floating point operation. + assert(!varTypeIsFloating(treeNode)); - unsigned finallyNesting; - finallyNesting = treeNode->gtVal.gtVal1; - noway_assert(treeNode->gtVal.gtVal1 < compiler->compHndBBtabCount); - noway_assert(finallyNesting < compiler->compHndBBtabCount); + // CQ: When possible use LEA for mul by imm 3, 5 or 9 + ssize_t imm = immOp->AsIntConCommon()->IconValue(); - // The last slot is reserved for ICodeManager::FixContext(ppEndRegion) - unsigned filterEndOffsetSlotOffs; - PREFIX_ASSUME(compiler->lvaLclSize(compiler->lvaShadowSPslotsVar) > - TARGET_POINTER_SIZE); // below doesn't underflow. - filterEndOffsetSlotOffs = - (unsigned)(compiler->lvaLclSize(compiler->lvaShadowSPslotsVar) - TARGET_POINTER_SIZE); + if (!requiresOverflowCheck && !rmOp->isContained() && ((imm == 3) || (imm == 5) || (imm == 9))) + { + // We will use the LEA instruction to perform this multiply + // Note that an LEA with base=x, index=x and scale=(imm-1) computes x*imm when imm=3,5 or 9. + unsigned int scale = (unsigned int)(imm - 1); + getEmitter()->emitIns_R_ARX(INS_lea, size, targetReg, rmOp->gtRegNum, rmOp->gtRegNum, scale, 0); + } + else + { + // use the 3-op form with immediate + ins = getEmitter()->inst3opImulForReg(targetReg); + emit->emitInsBinary(ins, size, rmOp, immOp); + } + } + else // we have no contained immediate operand + { + regOp = op1; + rmOp = op2; - unsigned curNestingSlotOffs; - curNestingSlotOffs = filterEndOffsetSlotOffs - ((finallyNesting + 1) * TARGET_POINTER_SIZE); - instGen_Store_Imm_Into_Lcl(TYP_I_IMPL, EA_PTRSIZE, 0, compiler->lvaShadowSPslotsVar, curNestingSlotOffs); - break; -#endif // !FEATURE_EH_FUNCLETS + regNumber mulTargetReg = targetReg; + if (isUnsignedMultiply && requiresOverflowCheck) + { + ins = INS_mulEAX; + mulTargetReg = REG_RAX; + } + else + { + ins = genGetInsForOper(GT_MUL, targetType); + } - case GT_PINVOKE_PROLOG: - noway_assert(((gcInfo.gcRegGCrefSetCur | gcInfo.gcRegByrefSetCur) & ~fullIntArgRegMask()) == 0); + // Set rmOp to the contain memory operand (if any) + // or set regOp to the op2 when it has the matching target register for our multiply op + // + if (op1->isContained() || (!op2->isContained() && (op2->gtRegNum == mulTargetReg))) + { + regOp = op2; + rmOp = op1; + } + assert(!regOp->isContained()); - // the runtime side requires the codegen here to be consistent - emit->emitDisableRandomNops(); - break; + // Setup targetReg when neither of the source operands was a matching register + if (regOp->gtRegNum != mulTargetReg) + { + inst_RV_RV(ins_Copy(targetType), mulTargetReg, regOp->gtRegNum, targetType); + } - case GT_LABEL: - genPendingCallLabel = genCreateTempLabel(); - treeNode->gtLabel.gtLabBB = genPendingCallLabel; - emit->emitIns_R_L(INS_lea, EA_PTR_DSP_RELOC, genPendingCallLabel, treeNode->gtRegNum); - break; + emit->emitInsBinary(ins, size, treeNode, rmOp); - case GT_STORE_OBJ: - if (treeNode->OperIsCopyBlkOp() && !treeNode->AsBlk()->gtBlkOpGcUnsafe) - { - assert(treeNode->AsObj()->gtGcPtrCount != 0); - genCodeForCpObj(treeNode->AsObj()); - break; + // Move the result to the desired register, if necessary + if ((ins == INS_mulEAX) && (targetReg != REG_RAX)) + { + inst_RV_RV(INS_mov, targetReg, REG_RAX, targetType); + } } - __fallthrough; - - case GT_STORE_DYN_BLK: - case GT_STORE_BLK: - genCodeForStoreBlk(treeNode->AsBlk()); - break; - case GT_JMPTABLE: - genJumpTable(treeNode); - break; + if (requiresOverflowCheck) + { + // Overflow checking is only used for non-floating point types + noway_assert(!varTypeIsFloating(treeNode)); - case GT_SWITCH_TABLE: - genTableBasedSwitch(treeNode); + genCheckOverflow(treeNode); + } + } + genProduceReg(treeNode); break; - case GT_ARR_INDEX: - genCodeForArrIndex(treeNode->AsArrIndex()); - break; + case GT_MOD: + case GT_UDIV: + case GT_UMOD: + // We shouldn't be seeing GT_MOD on float/double args as it should get morphed into a + // helper call by front-end. Similarly we shouldn't be seeing GT_UDIV and GT_UMOD + // on float/double args. + noway_assert(!varTypeIsFloating(treeNode)); + __fallthrough; - case GT_ARR_OFFSET: - genCodeForArrOffset(treeNode->AsArrOffs()); + case GT_DIV: + genCodeForDivMod(treeNode->AsOp()); break; - case GT_CLS_VAR_ADDR: - getEmitter()->emitIns_R_C(INS_lea, EA_PTRSIZE, targetReg, treeNode->gtClsVar.gtClsVarHnd, 0); - genProduceReg(treeNode); + case GT_INTRINSIC: + genIntrinsic(treeNode); break; -#if !defined(_TARGET_64BIT_) - case GT_LONG: - assert(!treeNode->isContained()); - genConsumeRegs(treeNode); +#ifdef FEATURE_SIMD + case GT_SIMD: + genSIMDIntrinsic(treeNode->AsSIMD()); break; -#endif +#endif // FEATURE_SIMD - case GT_IL_OFFSET: - // Do nothing; these nodes are simply markers for debug info. + case GT_CKFINITE: + genCkfinite(treeNode); break; - default: + case GT_EQ: + case GT_NE: + case GT_LT: + case GT_LE: + case GT_GE: + case GT_GT: { -#ifdef DEBUG - char message[256]; - sprintf(message, "Unimplemented node type %s\n", GenTree::NodeName(treeNode->OperGet())); -#endif - assert(!"Unknown node in codegen"); - } - break; - } -} - -//---------------------------------------------------------------------------------- -// genMultiRegCallStoreToLocal: store multi-reg return value of a call node to a local -// -// Arguments: -// treeNode - Gentree of GT_STORE_LCL_VAR -// -// Return Value: -// None -// -// Assumption: -// The child of store is a multi-reg call node. -// genProduceReg() on treeNode is made by caller of this routine. -// -void CodeGen::genMultiRegCallStoreToLocal(GenTreePtr treeNode) -{ - assert(treeNode->OperGet() == GT_STORE_LCL_VAR); - -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING - // Structs of size >=9 and <=16 are returned in two return registers on x64 Unix. - assert(varTypeIsStruct(treeNode)); - - // Assumption: current x64 Unix implementation requires that a multi-reg struct - // var in 'var = call' is flagged as lvIsMultiRegRet to prevent it from - // being struct promoted. - unsigned lclNum = treeNode->AsLclVarCommon()->gtLclNum; - LclVarDsc* varDsc = &(compiler->lvaTable[lclNum]); - noway_assert(varDsc->lvIsMultiRegRet); - - GenTree* op1 = treeNode->gtGetOp1(); - GenTree* actualOp1 = op1->gtSkipReloadOrCopy(); - GenTreeCall* call = actualOp1->AsCall(); - assert(call->HasMultiRegRetVal()); - - genConsumeRegs(op1); - - ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); - assert(retTypeDesc->GetReturnRegCount() == MAX_RET_REG_COUNT); - unsigned regCount = retTypeDesc->GetReturnRegCount(); - - if (treeNode->gtRegNum != REG_NA) - { - // Right now the only enregistrable structs supported are SIMD types. - assert(varTypeIsSIMD(treeNode)); - assert(varTypeIsFloating(retTypeDesc->GetReturnRegType(0))); - assert(varTypeIsFloating(retTypeDesc->GetReturnRegType(1))); + // TODO-XArch-CQ: Check if we can use the currently set flags. + // TODO-XArch-CQ: Check for the case where we can simply transfer the carry bit to a register + // (signed < or >= where targetReg != REG_NA) - // This is a case of two 8-bytes that comprise the operand is in - // two different xmm registers and needs to assembled into a single - // xmm register. - regNumber targetReg = treeNode->gtRegNum; - regNumber reg0 = call->GetRegNumByIdx(0); - regNumber reg1 = call->GetRegNumByIdx(1); + GenTreePtr op1 = treeNode->gtGetOp1(); + var_types op1Type = op1->TypeGet(); - if (op1->IsCopyOrReload()) - { - // GT_COPY/GT_RELOAD will have valid reg for those positions - // that need to be copied or reloaded. - regNumber reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(0); - if (reloadReg != REG_NA) + if (varTypeIsFloating(op1Type)) { - reg0 = reloadReg; + genCompareFloat(treeNode); } +#if !defined(_TARGET_64BIT_) + // X86 Long comparison + else if (varTypeIsLong(op1Type)) + { +#ifdef DEBUG + // The result of an unlowered long compare on a 32-bit target must either be + // a) materialized into a register, or + // b) unused. + // + // A long compare that has a result that is used but not materialized into a register should + // have been handled by Lowering::LowerCompare. - reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(1); - if (reloadReg != REG_NA) + LIR::Use use; + assert((treeNode->gtRegNum != REG_NA) || !LIR::AsRange(compiler->compCurBB).TryGetUse(treeNode, &use)); +#endif + genCompareLong(treeNode); + } +#endif // !defined(_TARGET_64BIT_) + else { - reg1 = reloadReg; + genCompareInt(treeNode); } } + break; - if (targetReg != reg0 && targetReg != reg1) + case GT_JTRUE: { - // Copy reg0 into targetReg and let it to be handled by one - // of the cases below. - inst_RV_RV(ins_Copy(TYP_DOUBLE), targetReg, reg0, TYP_DOUBLE); - targetReg = reg0; - } + GenTree* cmp = treeNode->gtOp.gtOp1; - if (targetReg == reg0) - { - // targeReg[63:0] = targetReg[63:0] - // targetReg[127:64] = reg1[127:64] - inst_RV_RV_IV(INS_shufpd, EA_16BYTE, targetReg, reg1, 0x00); - } - else - { - assert(targetReg == reg1); + assert(cmp->OperIsCompare()); + assert(compiler->compCurBB->bbJumpKind == BBJ_COND); - // We need two shuffles to achieve this - // First: - // targeReg[63:0] = targetReg[63:0] - // targetReg[127:64] = reg0[63:0] - // - // Second: - // targeReg[63:0] = targetReg[127:64] - // targetReg[127:64] = targetReg[63:0] - // - // Essentially copy low 8-bytes from reg0 to high 8-bytes of targetReg - // and next swap low and high 8-bytes of targetReg to have them - // rearranged in the right order. - inst_RV_RV_IV(INS_shufpd, EA_16BYTE, targetReg, reg0, 0x00); - inst_RV_RV_IV(INS_shufpd, EA_16BYTE, targetReg, targetReg, 0x01); - } - } - else - { - // Stack store - int offset = 0; - for (unsigned i = 0; i < regCount; ++i) - { - var_types type = retTypeDesc->GetReturnRegType(i); - regNumber reg = call->GetRegNumByIdx(i); - if (op1->IsCopyOrReload()) +#if !defined(_TARGET_64BIT_) + // Long-typed compares should have been handled by Lowering::LowerCompare. + assert(!varTypeIsLong(cmp->gtGetOp1())); +#endif + + // Get the "kind" and type of the comparison. Note that whether it is an unsigned cmp + // is governed by a flag NOT by the inherent type of the node + // TODO-XArch-CQ: Check if we can use the currently set flags. + emitJumpKind jumpKind[2]; + bool branchToTrueLabel[2]; + genJumpKindsForTree(cmp, jumpKind, branchToTrueLabel); + + BasicBlock* skipLabel = nullptr; + if (jumpKind[0] != EJ_NONE) { - // GT_COPY/GT_RELOAD will have valid reg for those positions - // that need to be copied or reloaded. - regNumber reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(i); - if (reloadReg != REG_NA) + BasicBlock* jmpTarget; + if (branchToTrueLabel[0]) { - reg = reloadReg; + jmpTarget = compiler->compCurBB->bbJumpDest; + } + else + { + // This case arises only for ordered GT_EQ right now + assert((cmp->gtOper == GT_EQ) && ((cmp->gtFlags & GTF_RELOP_NAN_UN) == 0)); + skipLabel = genCreateTempLabel(); + jmpTarget = skipLabel; } - } - - assert(reg != REG_NA); - getEmitter()->emitIns_S_R(ins_Store(type), emitTypeSize(type), reg, lclNum, offset); - offset += genTypeSize(type); - } - - varDsc->lvRegNum = REG_STK; - } -#elif defined(_TARGET_X86_) - // Longs are returned in two return registers on x86. - assert(varTypeIsLong(treeNode)); - - // Assumption: current x86 implementation requires that a multi-reg long - // var in 'var = call' is flagged as lvIsMultiRegRet to prevent it from - // being promoted. - unsigned lclNum = treeNode->AsLclVarCommon()->gtLclNum; - LclVarDsc* varDsc = &(compiler->lvaTable[lclNum]); - noway_assert(varDsc->lvIsMultiRegRet); - - GenTree* op1 = treeNode->gtGetOp1(); - GenTree* actualOp1 = op1->gtSkipReloadOrCopy(); - GenTreeCall* call = actualOp1->AsCall(); - assert(call->HasMultiRegRetVal()); - genConsumeRegs(op1); + inst_JMP(jumpKind[0], jmpTarget); + } - ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); - unsigned regCount = retTypeDesc->GetReturnRegCount(); - assert(regCount == MAX_RET_REG_COUNT); + if (jumpKind[1] != EJ_NONE) + { + // the second conditional branch always has to be to the true label + assert(branchToTrueLabel[1]); + inst_JMP(jumpKind[1], compiler->compCurBB->bbJumpDest); + } - // Stack store - int offset = 0; - for (unsigned i = 0; i < regCount; ++i) - { - var_types type = retTypeDesc->GetReturnRegType(i); - regNumber reg = call->GetRegNumByIdx(i); - if (op1->IsCopyOrReload()) - { - // GT_COPY/GT_RELOAD will have valid reg for those positions - // that need to be copied or reloaded. - regNumber reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(i); - if (reloadReg != REG_NA) + if (skipLabel != nullptr) { - reg = reloadReg; + genDefineTempLabel(skipLabel); } } + break; - assert(reg != REG_NA); - getEmitter()->emitIns_S_R(ins_Store(type), emitTypeSize(type), reg, lclNum, offset); - offset += genTypeSize(type); - } - - varDsc->lvRegNum = REG_STK; -#else // !FEATURE_UNIX_AMD64_STRUCT_PASSING && !_TARGET_X86_ - assert(!"Unreached"); -#endif // !FEATURE_UNIX_AMD64_STRUCT_PASSING && !_TARGET_X86_ -} + case GT_JCC: + { + GenTreeJumpCC* jcc = treeNode->AsJumpCC(); -//------------------------------------------------------------------------ -// genLclHeap: Generate code for localloc. -// -// Arguments: -// tree - the localloc tree to generate. -// -// Notes: -// Note that for x86, we don't track ESP movements while generating the localloc code. -// The ESP tracking is used to report stack pointer-relative GC info, which is not -// interesting while doing the localloc construction. Also, for functions with localloc, -// we have EBP frames, and EBP-relative locals, and ESP-relative accesses only for function -// call arguments. We store the ESP after the localloc is complete in the LocAllocSP -// variable. This variable is implicitly reported to the VM in the GC info (its position -// is defined by convention relative to other items), and is used by the GC to find the -// "base" stack pointer in functions with localloc. -// -void CodeGen::genLclHeap(GenTreePtr tree) -{ - assert(tree->OperGet() == GT_LCLHEAP); - assert(compiler->compLocallocUsed); + assert(compiler->compCurBB->bbJumpKind == BBJ_COND); - GenTreePtr size = tree->gtOp.gtOp1; - noway_assert((genActualType(size->gtType) == TYP_INT) || (genActualType(size->gtType) == TYP_I_IMPL)); + CompareKind compareKind = ((jcc->gtFlags & GTF_UNSIGNED) != 0) ? CK_UNSIGNED : CK_SIGNED; + emitJumpKind jumpKind = genJumpKindForOper(jcc->gtCondition, compareKind); - regNumber targetReg = tree->gtRegNum; - regMaskTP tmpRegsMask = tree->gtRsvdRegs; - regNumber regCnt = REG_NA; - var_types type = genActualType(size->gtType); - emitAttr easz = emitTypeSize(type); - BasicBlock* endLabel = nullptr; + inst_JMP(jumpKind, compiler->compCurBB->bbJumpDest); + } + break; -#ifdef DEBUG - // Verify ESP - if (compiler->opts.compStackCheckOnRet) - { - noway_assert(compiler->lvaReturnEspCheck != 0xCCCCCCCC && - compiler->lvaTable[compiler->lvaReturnEspCheck].lvDoNotEnregister && - compiler->lvaTable[compiler->lvaReturnEspCheck].lvOnFrame); - getEmitter()->emitIns_S_R(INS_cmp, EA_PTRSIZE, REG_SPBASE, compiler->lvaReturnEspCheck, 0); + case GT_RETURNTRAP: + { + // this is nothing but a conditional call to CORINFO_HELP_STOP_FOR_GC + // based on the contents of 'data' - BasicBlock* esp_check = genCreateTempLabel(); - emitJumpKind jmpEqual = genJumpKindForOper(GT_EQ, CK_SIGNED); - inst_JMP(jmpEqual, esp_check); - getEmitter()->emitIns(INS_BREAKPOINT); - genDefineTempLabel(esp_check); - } -#endif + GenTree* data = treeNode->gtOp.gtOp1; + genConsumeRegs(data); + GenTreeIntCon cns = intForm(TYP_INT, 0); + emit->emitInsBinary(INS_cmp, emitTypeSize(TYP_INT), data, &cns); - noway_assert(isFramePointerUsed()); // localloc requires Frame Pointer to be established since SP changes - noway_assert(genStackLevel == 0); // Can't have anything on the stack + BasicBlock* skipLabel = genCreateTempLabel(); - unsigned stackAdjustment = 0; - BasicBlock* loop = nullptr; + emitJumpKind jmpEqual = genJumpKindForOper(GT_EQ, CK_SIGNED); + inst_JMP(jmpEqual, skipLabel); - // compute the amount of memory to allocate to properly STACK_ALIGN. - size_t amount = 0; - if (size->IsCnsIntOrI()) - { - // If size is a constant, then it must be contained. - assert(size->isContained()); + // emit the call to the EE-helper that stops for GC (or other reasons) + assert(treeNode->gtRsvdRegs != RBM_NONE); + assert(genCountBits(treeNode->gtRsvdRegs) == 1); + regNumber tmpReg = genRegNumFromMask(treeNode->gtRsvdRegs); + assert(genIsValidIntReg(tmpReg)); - // If amount is zero then return null in targetReg - amount = size->gtIntCon.gtIconVal; - if (amount == 0) - { - instGen_Set_Reg_To_Zero(EA_PTRSIZE, targetReg); - goto BAILOUT; + genEmitHelperCall(CORINFO_HELP_STOP_FOR_GC, 0, EA_UNKNOWN, tmpReg); + genDefineTempLabel(skipLabel); } + break; - // 'amount' is the total number of bytes to localloc to properly STACK_ALIGN - amount = AlignUp(amount, STACK_ALIGN); - } - else - { - // The localloc requested memory size is non-constant. + case GT_STOREIND: + genStoreInd(treeNode); + break; - // Put the size value in targetReg. If it is zero, bail out by returning null in targetReg. - genConsumeRegAndCopy(size, targetReg); - endLabel = genCreateTempLabel(); - getEmitter()->emitIns_R_R(INS_test, easz, targetReg, targetReg); - inst_JMP(EJ_je, endLabel); + case GT_COPY: + // This is handled at the time we call genConsumeReg() on the GT_COPY + break; - // Compute the size of the block to allocate and perform alignment. - // If compInitMem=true, we can reuse targetReg as regcnt, - // since we don't need any internal registers. - if (compiler->info.compInitMem) - { - assert(genCountBits(tmpRegsMask) == 0); - regCnt = targetReg; - } - else + case GT_SWAP: { - assert(genCountBits(tmpRegsMask) >= 1); - regMaskTP regCntMask = genFindLowestBit(tmpRegsMask); - tmpRegsMask &= ~regCntMask; - regCnt = genRegNumFromMask(regCntMask); - if (regCnt != targetReg) - { - // Above, we put the size in targetReg. Now, copy it to our new temp register if necessary. - inst_RV_RV(INS_mov, regCnt, targetReg, size->TypeGet()); - } - } - - // Round up the number of bytes to allocate to a STACK_ALIGN boundary. This is done - // by code like: - // add reg, 15 - // and reg, -16 - // However, in the initialized memory case, we need the count of STACK_ALIGN-sized - // elements, not a byte count, after the alignment. So instead of the "and", which - // becomes unnecessary, generate a shift, e.g.: - // add reg, 15 - // shr reg, 4 + // Swap is only supported for lclVar operands that are enregistered + // We do not consume or produce any registers. Both operands remain enregistered. + // However, the gc-ness may change. + assert(genIsRegCandidateLocal(treeNode->gtOp.gtOp1) && genIsRegCandidateLocal(treeNode->gtOp.gtOp2)); - inst_RV_IV(INS_add, regCnt, STACK_ALIGN - 1, emitActualTypeSize(type)); + GenTreeLclVarCommon* lcl1 = treeNode->gtOp.gtOp1->AsLclVarCommon(); + LclVarDsc* varDsc1 = &(compiler->lvaTable[lcl1->gtLclNum]); + var_types type1 = varDsc1->TypeGet(); + GenTreeLclVarCommon* lcl2 = treeNode->gtOp.gtOp2->AsLclVarCommon(); + LclVarDsc* varDsc2 = &(compiler->lvaTable[lcl2->gtLclNum]); + var_types type2 = varDsc2->TypeGet(); - if (compiler->info.compInitMem) - { - // Convert the count from a count of bytes to a loop count. We will loop once per - // stack alignment size, so each loop will zero 4 bytes on x86 and 16 bytes on x64. - // Note that we zero a single reg-size word per iteration on x86, and 2 reg-size - // words per iteration on x64. We will shift off all the stack alignment bits - // added above, so there is no need for an 'and' instruction. + // We must have both int or both fp regs + assert(!varTypeIsFloating(type1) || varTypeIsFloating(type2)); - // --- shr regCnt, 2 (or 4) --- - inst_RV_SH(INS_SHIFT_RIGHT_LOGICAL, EA_PTRSIZE, regCnt, STACK_ALIGN_SHIFT_ALL); - } - else - { - // Otherwise, mask off the low bits to align the byte count. - inst_RV_IV(INS_AND, regCnt, ~(STACK_ALIGN - 1), emitActualTypeSize(type)); - } - } + // FP swap is not yet implemented (and should have NYI'd in LSRA) + assert(!varTypeIsFloating(type1)); -#if FEATURE_FIXED_OUT_ARGS - // If we have an outgoing arg area then we must adjust the SP by popping off the - // outgoing arg area. We will restore it right before we return from this method. - // - // Localloc returns stack space that aligned to STACK_ALIGN bytes. The following - // are the cases that need to be handled: - // i) Method has out-going arg area. - // It is guaranteed that size of out-going arg area is STACK_ALIGN'ed (see fgMorphArgs). - // Therefore, we will pop off the out-going arg area from RSP before allocating the localloc space. - // ii) Method has no out-going arg area. - // Nothing to pop off from the stack. - if (compiler->lvaOutgoingArgSpaceSize > 0) - { - assert((compiler->lvaOutgoingArgSpaceSize % STACK_ALIGN) == 0); // This must be true for the stack to remain - // aligned - inst_RV_IV(INS_add, REG_SPBASE, compiler->lvaOutgoingArgSpaceSize, EA_PTRSIZE); - stackAdjustment += compiler->lvaOutgoingArgSpaceSize; - } -#endif + regNumber oldOp1Reg = lcl1->gtRegNum; + regMaskTP oldOp1RegMask = genRegMask(oldOp1Reg); + regNumber oldOp2Reg = lcl2->gtRegNum; + regMaskTP oldOp2RegMask = genRegMask(oldOp2Reg); - if (size->IsCnsIntOrI()) - { - // We should reach here only for non-zero, constant size allocations. - assert(amount > 0); - assert((amount % STACK_ALIGN) == 0); - assert((amount % REGSIZE_BYTES) == 0); + // We don't call genUpdateVarReg because we don't have a tree node with the new register. + varDsc1->lvRegNum = oldOp2Reg; + varDsc2->lvRegNum = oldOp1Reg; - // For small allocations we will generate up to six push 0 inline - size_t cntRegSizedWords = amount / REGSIZE_BYTES; - if (cntRegSizedWords <= 6) - { - for (; cntRegSizedWords != 0; cntRegSizedWords--) + // Do the xchg + emitAttr size = EA_PTRSIZE; + if (varTypeGCtype(type1) != varTypeGCtype(type2)) { - inst_IV(INS_push_hide, 0); // push_hide means don't track the stack + // If the type specified to the emitter is a GC type, it will swap the GC-ness of the registers. + // Otherwise it will leave them alone, which is correct if they have the same GC-ness. + size = EA_GCREF; } - goto ALLOC_DONE; + inst_RV_RV(INS_xchg, oldOp1Reg, oldOp2Reg, TYP_I_IMPL, size); + + // Update the gcInfo. + // Manually remove these regs for the gc sets (mostly to avoid confusing duplicative dump output) + gcInfo.gcRegByrefSetCur &= ~(oldOp1RegMask | oldOp2RegMask); + gcInfo.gcRegGCrefSetCur &= ~(oldOp1RegMask | oldOp2RegMask); + + // gcMarkRegPtrVal will do the appropriate thing for non-gc types. + // It will also dump the updates. + gcInfo.gcMarkRegPtrVal(oldOp2Reg, type1); + gcInfo.gcMarkRegPtrVal(oldOp1Reg, type2); } + break; - bool doNoInitLessThanOnePageAlloc = - !compiler->info.compInitMem && (amount < compiler->eeGetPageSize()); // must be < not <= + case GT_LIST: + case GT_FIELD_LIST: + case GT_ARGPLACE: + // Nothing to do + break; -#ifdef _TARGET_X86_ - bool needRegCntRegister = true; -#else // !_TARGET_X86_ - bool needRegCntRegister = !doNoInitLessThanOnePageAlloc; -#endif // !_TARGET_X86_ + case GT_PUTARG_STK: + genPutArgStk(treeNode->AsPutArgStk()); + break; - if (needRegCntRegister) + case GT_PUTARG_REG: { - // If compInitMem=true, we can reuse targetReg as regcnt. - // Since size is a constant, regCnt is not yet initialized. - assert(regCnt == REG_NA); - if (compiler->info.compInitMem) - { - assert(genCountBits(tmpRegsMask) == 0); - regCnt = targetReg; - } - else +#ifndef FEATURE_UNIX_AMD64_STRUCT_PASSING + noway_assert(targetType != TYP_STRUCT); +#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING + // commas show up here commonly, as part of a nullchk operation + GenTree* op1 = treeNode->gtOp.gtOp1; + // If child node is not already in the register we need, move it + genConsumeReg(op1); + if (treeNode->gtRegNum != op1->gtRegNum) { - assert(genCountBits(tmpRegsMask) >= 1); - regMaskTP regCntMask = genFindLowestBit(tmpRegsMask); - tmpRegsMask &= ~regCntMask; - regCnt = genRegNumFromMask(regCntMask); + inst_RV_RV(ins_Copy(targetType), treeNode->gtRegNum, op1->gtRegNum, targetType); } + genProduceReg(treeNode); } + break; - if (doNoInitLessThanOnePageAlloc) - { - // Since the size is less than a page, simply adjust ESP. - // ESP might already be in the guard page, so we must touch it BEFORE - // the alloc, not after. - CLANG_FORMAT_COMMENT_ANCHOR; + case GT_CALL: + genCallInstruction(treeNode); + break; -#ifdef _TARGET_X86_ - // For x86, we don't want to use "sub ESP" because we don't want the emitter to track the adjustment - // to ESP. So do the work in the count register. - // TODO-CQ: manipulate ESP directly, to share code, reduce #ifdefs, and improve CQ. This would require - // creating a way to temporarily turn off the emitter's tracking of ESP, maybe marking instrDescs as "don't - // track". - inst_RV_RV(INS_mov, regCnt, REG_SPBASE, TYP_I_IMPL); - getEmitter()->emitIns_AR_R(INS_TEST, EA_4BYTE, REG_SPBASE, REG_SPBASE, 0); - inst_RV_IV(INS_sub, regCnt, amount, EA_PTRSIZE); - inst_RV_RV(INS_mov, REG_SPBASE, regCnt, TYP_I_IMPL); -#else // !_TARGET_X86_ - getEmitter()->emitIns_AR_R(INS_TEST, EA_4BYTE, REG_SPBASE, REG_SPBASE, 0); - inst_RV_IV(INS_sub, REG_SPBASE, amount, EA_PTRSIZE); -#endif // !_TARGET_X86_ + case GT_JMP: + genJmpMethod(treeNode); + break; - goto ALLOC_DONE; - } + case GT_LOCKADD: + case GT_XCHG: + case GT_XADD: + genLockedInstructions(treeNode->AsOp()); + break; - // else, "mov regCnt, amount" + case GT_MEMORYBARRIER: + instGen_MemoryBarrier(); + break; - if (compiler->info.compInitMem) + case GT_CMPXCHG: { - // When initializing memory, we want 'amount' to be the loop count. - assert((amount % STACK_ALIGN) == 0); - amount /= STACK_ALIGN; - } + GenTreePtr location = treeNode->gtCmpXchg.gtOpLocation; // arg1 + GenTreePtr value = treeNode->gtCmpXchg.gtOpValue; // arg2 + GenTreePtr comparand = treeNode->gtCmpXchg.gtOpComparand; // arg3 - genSetRegToIcon(regCnt, amount, ((int)amount == amount) ? TYP_INT : TYP_LONG); - } + assert(location->gtRegNum != REG_NA && location->gtRegNum != REG_RAX); + assert(value->gtRegNum != REG_NA && value->gtRegNum != REG_RAX); - loop = genCreateTempLabel(); - if (compiler->info.compInitMem) - { - // At this point 'regCnt' is set to the number of loop iterations for this loop, if each - // iteration zeros (and subtracts from the stack pointer) STACK_ALIGN bytes. - // Since we have to zero out the allocated memory AND ensure that RSP is always valid - // by tickling the pages, we will just push 0's on the stack. + genConsumeReg(location); + genConsumeReg(value); + genConsumeReg(comparand); + // comparand goes to RAX; + // Note that we must issue this move after the genConsumeRegs(), in case any of the above + // have a GT_COPY from RAX. + if (comparand->gtRegNum != REG_RAX) + { + inst_RV_RV(ins_Copy(comparand->TypeGet()), REG_RAX, comparand->gtRegNum, comparand->TypeGet()); + } - assert(genIsValidIntReg(regCnt)); + // location is Rm + instGen(INS_lock); - // Loop: - genDefineTempLabel(loop); + emit->emitIns_AR_R(INS_cmpxchg, emitTypeSize(targetType), value->gtRegNum, location->gtRegNum, 0); -#if defined(_TARGET_AMD64_) - // Push two 8-byte zeros. This matches the 16-byte STACK_ALIGN value. - static_assert_no_msg(STACK_ALIGN == (REGSIZE_BYTES * 2)); - inst_IV(INS_push_hide, 0); // --- push 8-byte 0 - inst_IV(INS_push_hide, 0); // --- push 8-byte 0 -#elif defined(_TARGET_X86_) - // Push a single 4-byte zero. This matches the 4-byte STACK_ALIGN value. - static_assert_no_msg(STACK_ALIGN == REGSIZE_BYTES); - inst_IV(INS_push_hide, 0); // --- push 4-byte 0 -#endif // _TARGET_X86_ + // Result is in RAX + if (targetReg != REG_RAX) + { + inst_RV_RV(ins_Copy(targetType), targetReg, REG_RAX, targetType); + } + } + genProduceReg(treeNode); + break; - // Decrement the loop counter and loop if not done. - inst_RV(INS_dec, regCnt, TYP_I_IMPL); - inst_JMP(EJ_jne, loop); - } - else - { - // At this point 'regCnt' is set to the total number of bytes to localloc. - // - // We don't need to zero out the allocated memory. However, we do have - // to tickle the pages to ensure that ESP is always valid and is - // in sync with the "stack guard page". Note that in the worst - // case ESP is on the last byte of the guard page. Thus you must - // touch ESP+0 first not ESP+x01000. - // - // Another subtlety is that you don't want ESP to be exactly on the - // boundary of the guard page because PUSH is predecrement, thus - // call setup would not touch the guard page but just beyond it - // - // Note that we go through a few hoops so that ESP never points to - // illegal pages at any time during the tickling process - // - // neg REGCNT - // add REGCNT, ESP // reg now holds ultimate ESP - // jb loop // result is smaller than orignial ESP (no wrap around) - // xor REGCNT, REGCNT, // Overflow, pick lowest possible number - // loop: - // test ESP, [ESP+0] // tickle the page - // mov REGTMP, ESP - // sub REGTMP, PAGE_SIZE - // mov ESP, REGTMP - // cmp ESP, REGCNT - // jae loop - // - // mov ESP, REG - // end: - inst_RV(INS_NEG, regCnt, TYP_I_IMPL); - inst_RV_RV(INS_add, regCnt, REG_SPBASE, TYP_I_IMPL); - inst_JMP(EJ_jb, loop); + case GT_RELOAD: + // do nothing - reload is just a marker. + // The parent node will call genConsumeReg on this which will trigger the unspill of this node's child + // into the register specified in this node. + break; + + case GT_NOP: + break; + + case GT_NO_OP: + if (treeNode->gtFlags & GTF_NO_OP_NO) + { + noway_assert(!"GTF_NO_OP_NO should not be set"); + } + else + { + getEmitter()->emitIns_Nop(1); + } + break; - instGen_Set_Reg_To_Zero(EA_PTRSIZE, regCnt); + case GT_ARR_BOUNDS_CHECK: +#ifdef FEATURE_SIMD + case GT_SIMD_CHK: +#endif // FEATURE_SIMD + genRangeCheck(treeNode); + break; - genDefineTempLabel(loop); + case GT_PHYSREG: + if (treeNode->gtRegNum != treeNode->AsPhysReg()->gtSrcReg) + { + inst_RV_RV(INS_mov, treeNode->gtRegNum, treeNode->AsPhysReg()->gtSrcReg, targetType); - // Tickle the decremented value, and move back to ESP, - // note that it has to be done BEFORE the update of ESP since - // ESP might already be on the guard page. It is OK to leave - // the final value of ESP on the guard page - getEmitter()->emitIns_AR_R(INS_TEST, EA_4BYTE, REG_SPBASE, REG_SPBASE, 0); + genTransferRegGCState(treeNode->gtRegNum, treeNode->AsPhysReg()->gtSrcReg); + } + genProduceReg(treeNode); + break; - // This is a harmless trick to avoid the emitter trying to track the - // decrement of the ESP - we do the subtraction in another reg instead - // of adjusting ESP directly. - assert(tmpRegsMask != RBM_NONE); - assert(genCountBits(tmpRegsMask) == 1); - regNumber regTmp = genRegNumFromMask(tmpRegsMask); + case GT_PHYSREGDST: + break; - inst_RV_RV(INS_mov, regTmp, REG_SPBASE, TYP_I_IMPL); - inst_RV_IV(INS_sub, regTmp, compiler->eeGetPageSize(), EA_PTRSIZE); - inst_RV_RV(INS_mov, REG_SPBASE, regTmp, TYP_I_IMPL); + case GT_NULLCHECK: + { + assert(!treeNode->gtOp.gtOp1->isContained()); + regNumber reg = genConsumeReg(treeNode->gtOp.gtOp1); + emit->emitIns_AR_R(INS_cmp, EA_4BYTE, reg, reg, 0); + } + break; - inst_RV_RV(INS_cmp, REG_SPBASE, regCnt, TYP_I_IMPL); - inst_JMP(EJ_jae, loop); + case GT_CATCH_ARG: - // Move the final value to ESP - inst_RV_RV(INS_mov, REG_SPBASE, regCnt); - } + noway_assert(handlerGetsXcptnObj(compiler->compCurBB->bbCatchTyp)); -ALLOC_DONE: - // Re-adjust SP to allocate out-going arg area - if (stackAdjustment > 0) - { - assert((stackAdjustment % STACK_ALIGN) == 0); // This must be true for the stack to remain aligned - inst_RV_IV(INS_sub, REG_SPBASE, stackAdjustment, EA_PTRSIZE); - } + /* Catch arguments get passed in a register. genCodeForBBlist() + would have marked it as holding a GC object, but not used. */ - // Return the stackalloc'ed address in result register. - // TargetReg = RSP + stackAdjustment. - getEmitter()->emitIns_R_AR(INS_lea, EA_PTRSIZE, targetReg, REG_SPBASE, stackAdjustment); + noway_assert(gcInfo.gcRegGCrefSetCur & RBM_EXCEPTION_OBJECT); + genConsumeReg(treeNode); + break; - if (endLabel != nullptr) - { - genDefineTempLabel(endLabel); - } +#if !FEATURE_EH_FUNCLETS + case GT_END_LFIN: -BAILOUT: + // Have to clear the ShadowSP of the nesting level which encloses the finally. Generates: + // mov dword ptr [ebp-0xC], 0 // for some slot of the ShadowSP local var - // Write the lvaLocAllocSPvar stack frame slot - noway_assert(compiler->lvaLocAllocSPvar != BAD_VAR_NUM); - getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SPBASE, compiler->lvaLocAllocSPvar, 0); + unsigned finallyNesting; + finallyNesting = treeNode->gtVal.gtVal1; + noway_assert(treeNode->gtVal.gtVal1 < compiler->compHndBBtabCount); + noway_assert(finallyNesting < compiler->compHndBBtabCount); -#if STACK_PROBES - if (compiler->opts.compNeedStackProbes) - { - genGenerateStackProbe(); - } -#endif + // The last slot is reserved for ICodeManager::FixContext(ppEndRegion) + unsigned filterEndOffsetSlotOffs; + PREFIX_ASSUME(compiler->lvaLclSize(compiler->lvaShadowSPslotsVar) > + TARGET_POINTER_SIZE); // below doesn't underflow. + filterEndOffsetSlotOffs = + (unsigned)(compiler->lvaLclSize(compiler->lvaShadowSPslotsVar) - TARGET_POINTER_SIZE); -#ifdef DEBUG - // Update new ESP - if (compiler->opts.compStackCheckOnRet) - { - noway_assert(compiler->lvaReturnEspCheck != 0xCCCCCCCC && - compiler->lvaTable[compiler->lvaReturnEspCheck].lvDoNotEnregister && - compiler->lvaTable[compiler->lvaReturnEspCheck].lvOnFrame); - getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SPBASE, compiler->lvaReturnEspCheck, 0); - } -#endif + unsigned curNestingSlotOffs; + curNestingSlotOffs = filterEndOffsetSlotOffs - ((finallyNesting + 1) * TARGET_POINTER_SIZE); + instGen_Store_Imm_Into_Lcl(TYP_I_IMPL, EA_PTRSIZE, 0, compiler->lvaShadowSPslotsVar, curNestingSlotOffs); + break; +#endif // !FEATURE_EH_FUNCLETS - genProduceReg(tree); -} + case GT_PINVOKE_PROLOG: + noway_assert(((gcInfo.gcRegGCrefSetCur | gcInfo.gcRegByrefSetCur) & ~fullIntArgRegMask()) == 0); -void CodeGen::genCodeForStoreBlk(GenTreeBlk* storeBlkNode) -{ - if (storeBlkNode->gtBlkOpGcUnsafe) - { - getEmitter()->emitDisableGC(); - } - bool isCopyBlk = storeBlkNode->OperIsCopyBlkOp(); + // the runtime side requires the codegen here to be consistent + emit->emitDisableRandomNops(); + break; - switch (storeBlkNode->gtBlkOpKind) - { -#ifdef _TARGET_AMD64_ - case GenTreeBlk::BlkOpKindHelper: - if (isCopyBlk) - { - genCodeForCpBlk(storeBlkNode); - } - else - { - genCodeForInitBlk(storeBlkNode); - } + case GT_LABEL: + genPendingCallLabel = genCreateTempLabel(); + treeNode->gtLabel.gtLabBB = genPendingCallLabel; + emit->emitIns_R_L(INS_lea, EA_PTR_DSP_RELOC, genPendingCallLabel, treeNode->gtRegNum); break; -#endif // _TARGET_AMD64_ - case GenTreeBlk::BlkOpKindRepInstr: - if (isCopyBlk) - { - genCodeForCpBlkRepMovs(storeBlkNode); - } - else + + case GT_STORE_OBJ: + if (treeNode->OperIsCopyBlkOp() && !treeNode->AsBlk()->gtBlkOpGcUnsafe) { - genCodeForInitBlkRepStos(storeBlkNode); + assert(treeNode->AsObj()->gtGcPtrCount != 0); + genCodeForCpObj(treeNode->AsObj()); + break; } + __fallthrough; + + case GT_STORE_DYN_BLK: + case GT_STORE_BLK: + genCodeForStoreBlk(treeNode->AsBlk()); break; - case GenTreeBlk::BlkOpKindUnroll: - if (isCopyBlk) - { - genCodeForCpBlkUnroll(storeBlkNode); - } - else - { - genCodeForInitBlkUnroll(storeBlkNode); - } + + case GT_JMPTABLE: + genJumpTable(treeNode); break; - default: - unreached(); - } - if (storeBlkNode->gtBlkOpGcUnsafe) - { - getEmitter()->emitEnableGC(); - } -} -// Generate code for InitBlk using rep stos. -// Preconditions: -// The size of the buffers must be a constant and also less than INITBLK_STOS_LIMIT bytes. -// Any value larger than that, we'll use the helper even if both the -// fill byte and the size are integer constants. -void CodeGen::genCodeForInitBlkRepStos(GenTreeBlk* initBlkNode) -{ - // Make sure we got the arguments of the initblk/initobj operation in the right registers - unsigned size = initBlkNode->Size(); - GenTreePtr dstAddr = initBlkNode->Addr(); - GenTreePtr initVal = initBlkNode->Data(); + case GT_SWITCH_TABLE: + genTableBasedSwitch(treeNode); + break; -#ifdef DEBUG - assert(!dstAddr->isContained()); - assert(!initVal->isContained()); -#ifdef _TARGET_AMD64_ - assert(size != 0); -#endif - if (initVal->IsCnsIntOrI()) - { -#ifdef _TARGET_AMD64_ - assert(size > CPBLK_UNROLL_LIMIT && size < CPBLK_MOVS_LIMIT); -#else - assert(size > CPBLK_UNROLL_LIMIT); + case GT_ARR_INDEX: + genCodeForArrIndex(treeNode->AsArrIndex()); + break; + + case GT_ARR_OFFSET: + genCodeForArrOffset(treeNode->AsArrOffs()); + break; + + case GT_CLS_VAR_ADDR: + getEmitter()->emitIns_R_C(INS_lea, EA_PTRSIZE, targetReg, treeNode->gtClsVar.gtClsVarHnd, 0); + genProduceReg(treeNode); + break; + +#if !defined(_TARGET_64BIT_) + case GT_LONG: + assert(!treeNode->isContained()); + genConsumeRegs(treeNode); + break; #endif - } -#endif // DEBUG + case GT_IL_OFFSET: + // Do nothing; these nodes are simply markers for debug info. + break; - genConsumeBlockOp(initBlkNode, REG_RDI, REG_RAX, REG_RCX); - instGen(INS_r_stosb); + default: + { +#ifdef DEBUG + char message[256]; + _snprintf_s(message, _countof(message), _TRUNCATE, "Unimplemented node type %s\n", + GenTree::NodeName(treeNode->OperGet())); +#endif + assert(!"Unknown node in codegen"); + } + break; + } } -// Generate code for InitBlk by performing a loop unroll -// Preconditions: -// a) Both the size and fill byte value are integer constants. -// b) The size of the struct to initialize is smaller than INITBLK_UNROLL_LIMIT bytes. +//---------------------------------------------------------------------------------- +// genMultiRegCallStoreToLocal: store multi-reg return value of a call node to a local // -void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* initBlkNode) -{ - // Make sure we got the arguments of the initblk/initobj operation in the right registers - unsigned size = initBlkNode->Size(); - GenTreePtr dstAddr = initBlkNode->Addr(); - GenTreePtr initVal = initBlkNode->Data(); +// Arguments: +// treeNode - Gentree of GT_STORE_LCL_VAR +// +// Return Value: +// None +// +// Assumption: +// The child of store is a multi-reg call node. +// genProduceReg() on treeNode is made by caller of this routine. +// +void CodeGen::genMultiRegCallStoreToLocal(GenTreePtr treeNode) +{ + assert(treeNode->OperGet() == GT_STORE_LCL_VAR); - assert(!dstAddr->isContained()); - assert(!initVal->isContained()); - assert(size != 0); - assert(size <= INITBLK_UNROLL_LIMIT); - assert(initVal->gtSkipReloadOrCopy()->IsCnsIntOrI()); +#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING + // Structs of size >=9 and <=16 are returned in two return registers on x64 Unix. + assert(varTypeIsStruct(treeNode)); - emitter* emit = getEmitter(); + // Assumption: current x64 Unix implementation requires that a multi-reg struct + // var in 'var = call' is flagged as lvIsMultiRegRet to prevent it from + // being struct promoted. + unsigned lclNum = treeNode->AsLclVarCommon()->gtLclNum; + LclVarDsc* varDsc = &(compiler->lvaTable[lclNum]); + noway_assert(varDsc->lvIsMultiRegRet); - genConsumeOperands(initBlkNode); + GenTree* op1 = treeNode->gtGetOp1(); + GenTree* actualOp1 = op1->gtSkipReloadOrCopy(); + GenTreeCall* call = actualOp1->AsCall(); + assert(call->HasMultiRegRetVal()); - // If the initVal was moved, or spilled and reloaded to a different register, - // get the original initVal from below the GT_RELOAD, but only after capturing the valReg, - // which needs to be the new register. - regNumber valReg = initVal->gtRegNum; - initVal = initVal->gtSkipReloadOrCopy(); + genConsumeRegs(op1); - unsigned offset = 0; + ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); + assert(retTypeDesc->GetReturnRegCount() == MAX_RET_REG_COUNT); + unsigned regCount = retTypeDesc->GetReturnRegCount(); - // Perform an unroll using SSE2 loads and stores. - if (size >= XMM_REGSIZE_BYTES) + if (treeNode->gtRegNum != REG_NA) { - regNumber tmpReg = genRegNumFromMask(initBlkNode->gtRsvdRegs); + // Right now the only enregistrable structs supported are SIMD types. + assert(varTypeIsSIMD(treeNode)); + assert(varTypeIsFloating(retTypeDesc->GetReturnRegType(0))); + assert(varTypeIsFloating(retTypeDesc->GetReturnRegType(1))); -#ifdef DEBUG - assert(initBlkNode->gtRsvdRegs != RBM_NONE); - assert(genCountBits(initBlkNode->gtRsvdRegs) == 1); - assert(genIsValidFloatReg(tmpReg)); -#endif // DEBUG + // This is a case of two 8-bytes that comprise the operand is in + // two different xmm registers and needs to assembled into a single + // xmm register. + regNumber targetReg = treeNode->gtRegNum; + regNumber reg0 = call->GetRegNumByIdx(0); + regNumber reg1 = call->GetRegNumByIdx(1); - if (initVal->gtIntCon.gtIconVal != 0) + if (op1->IsCopyOrReload()) { - emit->emitIns_R_R(INS_mov_i2xmm, EA_PTRSIZE, tmpReg, valReg); - emit->emitIns_R_R(INS_punpckldq, EA_8BYTE, tmpReg, tmpReg); -#ifdef _TARGET_X86_ - // For x86, we need one more to convert it from 8 bytes to 16 bytes. - emit->emitIns_R_R(INS_punpckldq, EA_8BYTE, tmpReg, tmpReg); -#endif // _TARGET_X86_ + // GT_COPY/GT_RELOAD will have valid reg for those positions + // that need to be copied or reloaded. + regNumber reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(0); + if (reloadReg != REG_NA) + { + reg0 = reloadReg; + } + + reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(1); + if (reloadReg != REG_NA) + { + reg1 = reloadReg; + } } - else + + if (targetReg != reg0 && targetReg != reg1) { - emit->emitIns_R_R(INS_xorpd, EA_8BYTE, tmpReg, tmpReg); + // Copy reg0 into targetReg and let it to be handled by one + // of the cases below. + inst_RV_RV(ins_Copy(TYP_DOUBLE), targetReg, reg0, TYP_DOUBLE); + targetReg = reg0; } - // Determine how many 16 byte slots we're going to fill using SSE movs. - size_t slots = size / XMM_REGSIZE_BYTES; - - while (slots-- > 0) + if (targetReg == reg0) { - emit->emitIns_AR_R(INS_movdqu, EA_8BYTE, tmpReg, dstAddr->gtRegNum, offset); - offset += XMM_REGSIZE_BYTES; + // targeReg[63:0] = targetReg[63:0] + // targetReg[127:64] = reg1[127:64] + inst_RV_RV_IV(INS_shufpd, EA_16BYTE, targetReg, reg1, 0x00); } - } + else + { + assert(targetReg == reg1); - // Fill the remainder (or a < 16 byte sized struct) - if ((size & 8) != 0) - { -#ifdef _TARGET_X86_ - // TODO-X86-CQ: [1091735] Revisit block ops codegen. One example: use movq for 8 byte movs. - emit->emitIns_AR_R(INS_mov, EA_4BYTE, valReg, dstAddr->gtRegNum, offset); - offset += 4; - emit->emitIns_AR_R(INS_mov, EA_4BYTE, valReg, dstAddr->gtRegNum, offset); - offset += 4; -#else // !_TARGET_X86_ - emit->emitIns_AR_R(INS_mov, EA_8BYTE, valReg, dstAddr->gtRegNum, offset); - offset += 8; -#endif // !_TARGET_X86_ - } - if ((size & 4) != 0) - { - emit->emitIns_AR_R(INS_mov, EA_4BYTE, valReg, dstAddr->gtRegNum, offset); - offset += 4; - } - if ((size & 2) != 0) - { - emit->emitIns_AR_R(INS_mov, EA_2BYTE, valReg, dstAddr->gtRegNum, offset); - offset += 2; + // We need two shuffles to achieve this + // First: + // targeReg[63:0] = targetReg[63:0] + // targetReg[127:64] = reg0[63:0] + // + // Second: + // targeReg[63:0] = targetReg[127:64] + // targetReg[127:64] = targetReg[63:0] + // + // Essentially copy low 8-bytes from reg0 to high 8-bytes of targetReg + // and next swap low and high 8-bytes of targetReg to have them + // rearranged in the right order. + inst_RV_RV_IV(INS_shufpd, EA_16BYTE, targetReg, reg0, 0x00); + inst_RV_RV_IV(INS_shufpd, EA_16BYTE, targetReg, targetReg, 0x01); + } } - if ((size & 1) != 0) + else { - emit->emitIns_AR_R(INS_mov, EA_1BYTE, valReg, dstAddr->gtRegNum, offset); - } -} - -// Generates code for InitBlk by calling the VM memset helper function. -// Preconditions: -// a) The size argument of the InitBlk is not an integer constant. -// b) The size argument of the InitBlk is >= INITBLK_STOS_LIMIT bytes. -void CodeGen::genCodeForInitBlk(GenTreeBlk* initBlkNode) -{ -#ifdef _TARGET_AMD64_ - // Make sure we got the arguments of the initblk operation in the right registers - unsigned blockSize = initBlkNode->Size(); - GenTreePtr dstAddr = initBlkNode->Addr(); - GenTreePtr initVal = initBlkNode->Data(); + // Stack store + int offset = 0; + for (unsigned i = 0; i < regCount; ++i) + { + var_types type = retTypeDesc->GetReturnRegType(i); + regNumber reg = call->GetRegNumByIdx(i); + if (op1->IsCopyOrReload()) + { + // GT_COPY/GT_RELOAD will have valid reg for those positions + // that need to be copied or reloaded. + regNumber reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(i); + if (reloadReg != REG_NA) + { + reg = reloadReg; + } + } - assert(!dstAddr->isContained()); - assert(!initVal->isContained()); + assert(reg != REG_NA); + getEmitter()->emitIns_S_R(ins_Store(type), emitTypeSize(type), reg, lclNum, offset); + offset += genTypeSize(type); + } - if (blockSize != 0) - { - assert(blockSize >= CPBLK_MOVS_LIMIT); + varDsc->lvRegNum = REG_STK; } +#elif defined(_TARGET_X86_) + // Longs are returned in two return registers on x86. + assert(varTypeIsLong(treeNode)); - genConsumeBlockOp(initBlkNode, REG_ARG_0, REG_ARG_1, REG_ARG_2); + // Assumption: current x86 implementation requires that a multi-reg long + // var in 'var = call' is flagged as lvIsMultiRegRet to prevent it from + // being promoted. + unsigned lclNum = treeNode->AsLclVarCommon()->gtLclNum; + LclVarDsc* varDsc = &(compiler->lvaTable[lclNum]); + noway_assert(varDsc->lvIsMultiRegRet); - genEmitHelperCall(CORINFO_HELP_MEMSET, 0, EA_UNKNOWN); -#else // !_TARGET_AMD64_ - NYI_X86("Helper call for InitBlk"); -#endif // !_TARGET_AMD64_ -} + GenTree* op1 = treeNode->gtGetOp1(); + GenTree* actualOp1 = op1->gtSkipReloadOrCopy(); + GenTreeCall* call = actualOp1->AsCall(); + assert(call->HasMultiRegRetVal()); -// Generate code for a load from some address + offset -// baseNode: tree node which can be either a local address or arbitrary node -// offset: distance from the baseNode from which to load -void CodeGen::genCodeForLoadOffset(instruction ins, emitAttr size, regNumber dst, GenTree* baseNode, unsigned offset) -{ - emitter* emit = getEmitter(); + genConsumeRegs(op1); - if (baseNode->OperIsLocalAddr()) + ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); + unsigned regCount = retTypeDesc->GetReturnRegCount(); + assert(regCount == MAX_RET_REG_COUNT); + + // Stack store + int offset = 0; + for (unsigned i = 0; i < regCount; ++i) { - if (baseNode->gtOper == GT_LCL_FLD_ADDR) + var_types type = retTypeDesc->GetReturnRegType(i); + regNumber reg = call->GetRegNumByIdx(i); + if (op1->IsCopyOrReload()) { - offset += baseNode->gtLclFld.gtLclOffs; + // GT_COPY/GT_RELOAD will have valid reg for those positions + // that need to be copied or reloaded. + regNumber reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(i); + if (reloadReg != REG_NA) + { + reg = reloadReg; + } } - emit->emitIns_R_S(ins, size, dst, baseNode->gtLclVarCommon.gtLclNum, offset); - } - else - { - emit->emitIns_R_AR(ins, size, dst, baseNode->gtRegNum, offset); + + assert(reg != REG_NA); + getEmitter()->emitIns_S_R(ins_Store(type), emitTypeSize(type), reg, lclNum, offset); + offset += genTypeSize(type); } + + varDsc->lvRegNum = REG_STK; +#else // !FEATURE_UNIX_AMD64_STRUCT_PASSING && !_TARGET_X86_ + assert(!"Unreached"); +#endif // !FEATURE_UNIX_AMD64_STRUCT_PASSING && !_TARGET_X86_ } //------------------------------------------------------------------------ -// genCodeForStoreOffset: Generate code to store a reg to [base + offset]. +// genLclHeap: Generate code for localloc. // // Arguments: -// ins - the instruction to generate. -// size - the size that needs to be stored. -// src - the register which needs to be stored. -// baseNode - the base, relative to which to store the src register. -// offset - the offset that is added to the baseNode to calculate the address to store into. +// tree - the localloc tree to generate. // -void CodeGen::genCodeForStoreOffset(instruction ins, emitAttr size, regNumber src, GenTree* baseNode, unsigned offset) +// Notes: +// Note that for x86, we don't track ESP movements while generating the localloc code. +// The ESP tracking is used to report stack pointer-relative GC info, which is not +// interesting while doing the localloc construction. Also, for functions with localloc, +// we have EBP frames, and EBP-relative locals, and ESP-relative accesses only for function +// call arguments. We store the ESP after the localloc is complete in the LocAllocSP +// variable. This variable is implicitly reported to the VM in the GC info (its position +// is defined by convention relative to other items), and is used by the GC to find the +// "base" stack pointer in functions with localloc. +// +void CodeGen::genLclHeap(GenTreePtr tree) { - emitter* emit = getEmitter(); + assert(tree->OperGet() == GT_LCLHEAP); + assert(compiler->compLocallocUsed); - if (baseNode->OperIsLocalAddr()) - { - if (baseNode->gtOper == GT_LCL_FLD_ADDR) - { - offset += baseNode->gtLclFld.gtLclOffs; - } + GenTreePtr size = tree->gtOp.gtOp1; + noway_assert((genActualType(size->gtType) == TYP_INT) || (genActualType(size->gtType) == TYP_I_IMPL)); - emit->emitIns_S_R(ins, size, src, baseNode->AsLclVarCommon()->GetLclNum(), offset); - } - else + regNumber targetReg = tree->gtRegNum; + regMaskTP tmpRegsMask = tree->gtRsvdRegs; + regNumber regCnt = REG_NA; + var_types type = genActualType(size->gtType); + emitAttr easz = emitTypeSize(type); + BasicBlock* endLabel = nullptr; + +#ifdef DEBUG + // Verify ESP + if (compiler->opts.compStackCheckOnRet) { - emit->emitIns_AR_R(ins, size, src, baseNode->gtRegNum, offset); + noway_assert(compiler->lvaReturnEspCheck != 0xCCCCCCCC && + compiler->lvaTable[compiler->lvaReturnEspCheck].lvDoNotEnregister && + compiler->lvaTable[compiler->lvaReturnEspCheck].lvOnFrame); + getEmitter()->emitIns_S_R(INS_cmp, EA_PTRSIZE, REG_SPBASE, compiler->lvaReturnEspCheck, 0); + + BasicBlock* esp_check = genCreateTempLabel(); + emitJumpKind jmpEqual = genJumpKindForOper(GT_EQ, CK_SIGNED); + inst_JMP(jmpEqual, esp_check); + getEmitter()->emitIns(INS_BREAKPOINT); + genDefineTempLabel(esp_check); } -} +#endif -// Generates CpBlk code by performing a loop unroll -// Preconditions: -// The size argument of the CpBlk node is a constant and <= 64 bytes. -// This may seem small but covers >95% of the cases in several framework assemblies. -// -void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* cpBlkNode) -{ - // Make sure we got the arguments of the cpblk operation in the right registers - unsigned size = cpBlkNode->Size(); - GenTreePtr dstAddr = cpBlkNode->Addr(); - GenTreePtr source = cpBlkNode->Data(); - GenTreePtr srcAddr = nullptr; - assert(size <= CPBLK_UNROLL_LIMIT); + noway_assert(isFramePointerUsed()); // localloc requires Frame Pointer to be established since SP changes + noway_assert(genStackLevel == 0); // Can't have anything on the stack - emitter* emit = getEmitter(); + unsigned stackAdjustment = 0; + BasicBlock* loop = nullptr; - if (source->gtOper == GT_IND) + // compute the amount of memory to allocate to properly STACK_ALIGN. + size_t amount = 0; + if (size->IsCnsIntOrI()) { - srcAddr = source->gtGetOp1(); - if (!srcAddr->isContained()) + // If size is a constant, then it must be contained. + assert(size->isContained()); + + // If amount is zero then return null in targetReg + amount = size->gtIntCon.gtIconVal; + if (amount == 0) { - genConsumeReg(srcAddr); + instGen_Set_Reg_To_Zero(EA_PTRSIZE, targetReg); + goto BAILOUT; } + + // 'amount' is the total number of bytes to localloc to properly STACK_ALIGN + amount = AlignUp(amount, STACK_ALIGN); } else { - noway_assert(source->IsLocal()); - // TODO-Cleanup: Consider making the addrForm() method in Rationalize public, e.g. in GenTree. - // OR: transform source to GT_IND(GT_LCL_VAR_ADDR) - if (source->OperGet() == GT_LCL_VAR) + // The localloc requested memory size is non-constant. + + // Put the size value in targetReg. If it is zero, bail out by returning null in targetReg. + genConsumeRegAndCopy(size, targetReg); + endLabel = genCreateTempLabel(); + getEmitter()->emitIns_R_R(INS_test, easz, targetReg, targetReg); + inst_JMP(EJ_je, endLabel); + + // Compute the size of the block to allocate and perform alignment. + // If compInitMem=true, we can reuse targetReg as regcnt, + // since we don't need any internal registers. + if (compiler->info.compInitMem) { - source->SetOper(GT_LCL_VAR_ADDR); + assert(genCountBits(tmpRegsMask) == 0); + regCnt = targetReg; } else { - assert(source->OperGet() == GT_LCL_FLD); - source->SetOper(GT_LCL_FLD_ADDR); + assert(genCountBits(tmpRegsMask) >= 1); + regMaskTP regCntMask = genFindLowestBit(tmpRegsMask); + tmpRegsMask &= ~regCntMask; + regCnt = genRegNumFromMask(regCntMask); + if (regCnt != targetReg) + { + // Above, we put the size in targetReg. Now, copy it to our new temp register if necessary. + inst_RV_RV(INS_mov, regCnt, targetReg, size->TypeGet()); + } } - srcAddr = source; - } - - if (!dstAddr->isContained()) - { - genConsumeReg(dstAddr); - } - unsigned offset = 0; + // Round up the number of bytes to allocate to a STACK_ALIGN boundary. This is done + // by code like: + // add reg, 15 + // and reg, -16 + // However, in the initialized memory case, we need the count of STACK_ALIGN-sized + // elements, not a byte count, after the alignment. So instead of the "and", which + // becomes unnecessary, generate a shift, e.g.: + // add reg, 15 + // shr reg, 4 - // If the size of this struct is larger than 16 bytes - // let's use SSE2 to be able to do 16 byte at a time - // loads and stores. + inst_RV_IV(INS_add, regCnt, STACK_ALIGN - 1, emitActualTypeSize(type)); - if (size >= XMM_REGSIZE_BYTES) - { - assert(cpBlkNode->gtRsvdRegs != RBM_NONE); - regNumber xmmReg = genRegNumFromMask(cpBlkNode->gtRsvdRegs & RBM_ALLFLOAT); - assert(genIsValidFloatReg(xmmReg)); - size_t slots = size / XMM_REGSIZE_BYTES; + if (compiler->info.compInitMem) + { + // Convert the count from a count of bytes to a loop count. We will loop once per + // stack alignment size, so each loop will zero 4 bytes on x86 and 16 bytes on x64. + // Note that we zero a single reg-size word per iteration on x86, and 2 reg-size + // words per iteration on x64. We will shift off all the stack alignment bits + // added above, so there is no need for an 'and' instruction. - // TODO: In the below code the load and store instructions are for 16 bytes, but the - // type is EA_8BYTE. The movdqa/u are 16 byte instructions, so it works, but - // this probably needs to be changed. - while (slots-- > 0) + // --- shr regCnt, 2 (or 4) --- + inst_RV_SH(INS_SHIFT_RIGHT_LOGICAL, EA_PTRSIZE, regCnt, STACK_ALIGN_SHIFT_ALL); + } + else { - // Load - genCodeForLoadOffset(INS_movdqu, EA_8BYTE, xmmReg, srcAddr, offset); - // Store - genCodeForStoreOffset(INS_movdqu, EA_8BYTE, xmmReg, dstAddr, offset); - offset += XMM_REGSIZE_BYTES; + // Otherwise, mask off the low bits to align the byte count. + inst_RV_IV(INS_AND, regCnt, ~(STACK_ALIGN - 1), emitActualTypeSize(type)); } } - // Fill the remainder (15 bytes or less) if there's one. - if ((size & 0xf) != 0) +#if FEATURE_FIXED_OUT_ARGS + // If we have an outgoing arg area then we must adjust the SP by popping off the + // outgoing arg area. We will restore it right before we return from this method. + // + // Localloc returns stack space that aligned to STACK_ALIGN bytes. The following + // are the cases that need to be handled: + // i) Method has out-going arg area. + // It is guaranteed that size of out-going arg area is STACK_ALIGN'ed (see fgMorphArgs). + // Therefore, we will pop off the out-going arg area from RSP before allocating the localloc space. + // ii) Method has no out-going arg area. + // Nothing to pop off from the stack. + if (compiler->lvaOutgoingArgSpaceSize > 0) { - // Grab the integer temp register to emit the remaining loads and stores. - regNumber tmpReg = genRegNumFromMask(cpBlkNode->gtRsvdRegs & RBM_ALLINT); + assert((compiler->lvaOutgoingArgSpaceSize % STACK_ALIGN) == 0); // This must be true for the stack to remain + // aligned + inst_RV_IV(INS_add, REG_SPBASE, compiler->lvaOutgoingArgSpaceSize, EA_PTRSIZE); + stackAdjustment += compiler->lvaOutgoingArgSpaceSize; + } +#endif - if ((size & 8) != 0) + if (size->IsCnsIntOrI()) + { + // We should reach here only for non-zero, constant size allocations. + assert(amount > 0); + assert((amount % STACK_ALIGN) == 0); + assert((amount % REGSIZE_BYTES) == 0); + + // For small allocations we will generate up to six push 0 inline + size_t cntRegSizedWords = amount / REGSIZE_BYTES; + if (cntRegSizedWords <= 6) { -#ifdef _TARGET_X86_ - // TODO-X86-CQ: [1091735] Revisit block ops codegen. One example: use movq for 8 byte movs. - for (unsigned savedOffs = offset; offset < savedOffs + 8; offset += 4) + for (; cntRegSizedWords != 0; cntRegSizedWords--) { - genCodeForLoadOffset(INS_mov, EA_4BYTE, tmpReg, srcAddr, offset); - genCodeForStoreOffset(INS_mov, EA_4BYTE, tmpReg, dstAddr, offset); + inst_IV(INS_push_hide, 0); // push_hide means don't track the stack } + goto ALLOC_DONE; + } + + bool doNoInitLessThanOnePageAlloc = + !compiler->info.compInitMem && (amount < compiler->eeGetPageSize()); // must be < not <= + +#ifdef _TARGET_X86_ + bool needRegCntRegister = true; #else // !_TARGET_X86_ - genCodeForLoadOffset(INS_mov, EA_8BYTE, tmpReg, srcAddr, offset); - genCodeForStoreOffset(INS_mov, EA_8BYTE, tmpReg, dstAddr, offset); - offset += 8; + bool needRegCntRegister = !doNoInitLessThanOnePageAlloc; #endif // !_TARGET_X86_ - } - if ((size & 4) != 0) + + if (needRegCntRegister) { - genCodeForLoadOffset(INS_mov, EA_4BYTE, tmpReg, srcAddr, offset); - genCodeForStoreOffset(INS_mov, EA_4BYTE, tmpReg, dstAddr, offset); - offset += 4; + // If compInitMem=true, we can reuse targetReg as regcnt. + // Since size is a constant, regCnt is not yet initialized. + assert(regCnt == REG_NA); + if (compiler->info.compInitMem) + { + assert(genCountBits(tmpRegsMask) == 0); + regCnt = targetReg; + } + else + { + assert(genCountBits(tmpRegsMask) >= 1); + regMaskTP regCntMask = genFindLowestBit(tmpRegsMask); + tmpRegsMask &= ~regCntMask; + regCnt = genRegNumFromMask(regCntMask); + } } - if ((size & 2) != 0) + + if (doNoInitLessThanOnePageAlloc) { - genCodeForLoadOffset(INS_mov, EA_2BYTE, tmpReg, srcAddr, offset); - genCodeForStoreOffset(INS_mov, EA_2BYTE, tmpReg, dstAddr, offset); - offset += 2; + // Since the size is less than a page, simply adjust ESP. + // ESP might already be in the guard page, so we must touch it BEFORE + // the alloc, not after. + CLANG_FORMAT_COMMENT_ANCHOR; + +#ifdef _TARGET_X86_ + // For x86, we don't want to use "sub ESP" because we don't want the emitter to track the adjustment + // to ESP. So do the work in the count register. + // TODO-CQ: manipulate ESP directly, to share code, reduce #ifdefs, and improve CQ. This would require + // creating a way to temporarily turn off the emitter's tracking of ESP, maybe marking instrDescs as "don't + // track". + inst_RV_RV(INS_mov, regCnt, REG_SPBASE, TYP_I_IMPL); + getEmitter()->emitIns_AR_R(INS_TEST, EA_4BYTE, REG_SPBASE, REG_SPBASE, 0); + inst_RV_IV(INS_sub, regCnt, amount, EA_PTRSIZE); + inst_RV_RV(INS_mov, REG_SPBASE, regCnt, TYP_I_IMPL); +#else // !_TARGET_X86_ + getEmitter()->emitIns_AR_R(INS_TEST, EA_4BYTE, REG_SPBASE, REG_SPBASE, 0); + inst_RV_IV(INS_sub, REG_SPBASE, amount, EA_PTRSIZE); +#endif // !_TARGET_X86_ + + goto ALLOC_DONE; } - if ((size & 1) != 0) + + // else, "mov regCnt, amount" + + if (compiler->info.compInitMem) { - genCodeForLoadOffset(INS_mov, EA_1BYTE, tmpReg, srcAddr, offset); - genCodeForStoreOffset(INS_mov, EA_1BYTE, tmpReg, dstAddr, offset); + // When initializing memory, we want 'amount' to be the loop count. + assert((amount % STACK_ALIGN) == 0); + amount /= STACK_ALIGN; } + + genSetRegToIcon(regCnt, amount, ((int)amount == amount) ? TYP_INT : TYP_LONG); } -} -// Generate code for CpBlk by using rep movs -// Preconditions: -// The size argument of the CpBlk is a constant and is between -// CPBLK_UNROLL_LIMIT and CPBLK_MOVS_LIMIT bytes. -void CodeGen::genCodeForCpBlkRepMovs(GenTreeBlk* cpBlkNode) -{ - // Make sure we got the arguments of the cpblk operation in the right registers - unsigned size = cpBlkNode->Size(); - GenTreePtr dstAddr = cpBlkNode->Addr(); - GenTreePtr source = cpBlkNode->Data(); - GenTreePtr srcAddr = nullptr; + loop = genCreateTempLabel(); + if (compiler->info.compInitMem) + { + // At this point 'regCnt' is set to the number of loop iterations for this loop, if each + // iteration zeros (and subtracts from the stack pointer) STACK_ALIGN bytes. + // Since we have to zero out the allocated memory AND ensure that RSP is always valid + // by tickling the pages, we will just push 0's on the stack. -#ifdef DEBUG - assert(!dstAddr->isContained()); - assert(source->isContained()); + assert(genIsValidIntReg(regCnt)); -#ifdef _TARGET_X86_ - if (size == 0) - { - noway_assert(cpBlkNode->OperGet() == GT_STORE_DYN_BLK); + // Loop: + genDefineTempLabel(loop); + +#if defined(_TARGET_AMD64_) + // Push two 8-byte zeros. This matches the 16-byte STACK_ALIGN value. + static_assert_no_msg(STACK_ALIGN == (REGSIZE_BYTES * 2)); + inst_IV(INS_push_hide, 0); // --- push 8-byte 0 + inst_IV(INS_push_hide, 0); // --- push 8-byte 0 +#elif defined(_TARGET_X86_) + // Push a single 4-byte zero. This matches the 4-byte STACK_ALIGN value. + static_assert_no_msg(STACK_ALIGN == REGSIZE_BYTES); + inst_IV(INS_push_hide, 0); // --- push 4-byte 0 +#endif // _TARGET_X86_ + + // Decrement the loop counter and loop if not done. + inst_RV(INS_dec, regCnt, TYP_I_IMPL); + inst_JMP(EJ_jne, loop); } else -#endif { -#ifdef _TARGET_X64_ - assert(size > CPBLK_UNROLL_LIMIT && size < CPBLK_MOVS_LIMIT); -#else - assert(size > CPBLK_UNROLL_LIMIT); -#endif - } -#endif // DEBUG - - genConsumeBlockOp(cpBlkNode, REG_RDI, REG_RSI, REG_RCX); - instGen(INS_r_movsb); -} + // At this point 'regCnt' is set to the total number of bytes to localloc. + // + // We don't need to zero out the allocated memory. However, we do have + // to tickle the pages to ensure that ESP is always valid and is + // in sync with the "stack guard page". Note that in the worst + // case ESP is on the last byte of the guard page. Thus you must + // touch ESP+0 first not ESP+x01000. + // + // Another subtlety is that you don't want ESP to be exactly on the + // boundary of the guard page because PUSH is predecrement, thus + // call setup would not touch the guard page but just beyond it + // + // Note that we go through a few hoops so that ESP never points to + // illegal pages at any time during the tickling process + // + // neg REGCNT + // add REGCNT, ESP // reg now holds ultimate ESP + // jb loop // result is smaller than orignial ESP (no wrap around) + // xor REGCNT, REGCNT, // Overflow, pick lowest possible number + // loop: + // test ESP, [ESP+0] // tickle the page + // mov REGTMP, ESP + // sub REGTMP, PAGE_SIZE + // mov ESP, REGTMP + // cmp ESP, REGCNT + // jae loop + // + // mov ESP, REG + // end: + inst_RV(INS_NEG, regCnt, TYP_I_IMPL); + inst_RV_RV(INS_add, regCnt, REG_SPBASE, TYP_I_IMPL); + inst_JMP(EJ_jb, loop); -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING + instGen_Set_Reg_To_Zero(EA_PTRSIZE, regCnt); -//---------------------------------------------------------------------------------------------------------------// -// genStructPutArgUnroll: Generates code for passing a struct arg on stack by value using loop unrolling. -// -// Arguments: -// putArgNode - the PutArgStk tree. -// baseVarNum - the base var number, relative to which the by-val struct will be copied on the stack. -// -// TODO-Amd64-Unix: Try to share code with copyblk. -// Need refactoring of copyblk before it could be used for putarg_stk. -// The difference for now is that a putarg_stk contains its children, while cpyblk does not. -// This creates differences in code. After some significant refactoring it could be reused. -// -void CodeGen::genStructPutArgUnroll(GenTreePutArgStk* putArgNode, unsigned baseVarNum) -{ - // We will never call this method for SIMD types, which are stored directly - // in genPutStructArgStk(). - noway_assert(putArgNode->TypeGet() == TYP_STRUCT); + genDefineTempLabel(loop); - // Make sure we got the arguments of the cpblk operation in the right registers - GenTreePtr dstAddr = putArgNode; - GenTreePtr src = putArgNode->gtOp.gtOp1; + // Tickle the decremented value, and move back to ESP, + // note that it has to be done BEFORE the update of ESP since + // ESP might already be on the guard page. It is OK to leave + // the final value of ESP on the guard page + getEmitter()->emitIns_AR_R(INS_TEST, EA_4BYTE, REG_SPBASE, REG_SPBASE, 0); - size_t size = putArgNode->getArgSize(); - assert(size <= CPBLK_UNROLL_LIMIT); + // This is a harmless trick to avoid the emitter trying to track the + // decrement of the ESP - we do the subtraction in another reg instead + // of adjusting ESP directly. + assert(tmpRegsMask != RBM_NONE); + assert(genCountBits(tmpRegsMask) == 1); + regNumber regTmp = genRegNumFromMask(tmpRegsMask); - emitter* emit = getEmitter(); - unsigned putArgOffset = putArgNode->getArgOffset(); + inst_RV_RV(INS_mov, regTmp, REG_SPBASE, TYP_I_IMPL); + inst_RV_IV(INS_sub, regTmp, compiler->eeGetPageSize(), EA_PTRSIZE); + inst_RV_RV(INS_mov, REG_SPBASE, regTmp, TYP_I_IMPL); - assert(src->isContained()); + inst_RV_RV(INS_cmp, REG_SPBASE, regCnt, TYP_I_IMPL); + inst_JMP(EJ_jae, loop); - assert(src->gtOper == GT_OBJ); + // Move the final value to ESP + inst_RV_RV(INS_mov, REG_SPBASE, regCnt); + } - if (!src->gtOp.gtOp1->isContained()) +ALLOC_DONE: + // Re-adjust SP to allocate out-going arg area + if (stackAdjustment > 0) { - genConsumeReg(src->gtOp.gtOp1); + assert((stackAdjustment % STACK_ALIGN) == 0); // This must be true for the stack to remain aligned + inst_RV_IV(INS_sub, REG_SPBASE, stackAdjustment, EA_PTRSIZE); } - unsigned offset = 0; + // Return the stackalloc'ed address in result register. + // TargetReg = RSP + stackAdjustment. + getEmitter()->emitIns_R_AR(INS_lea, EA_PTRSIZE, targetReg, REG_SPBASE, stackAdjustment); - // If the size of this struct is larger than 16 bytes - // let's use SSE2 to be able to do 16 byte at a time - // loads and stores. - if (size >= XMM_REGSIZE_BYTES) + if (endLabel != nullptr) { - assert(putArgNode->gtRsvdRegs != RBM_NONE); - regNumber xmmReg = genRegNumFromMask(putArgNode->gtRsvdRegs & RBM_ALLFLOAT); - assert(genIsValidFloatReg(xmmReg)); - size_t slots = size / XMM_REGSIZE_BYTES; - - assert(putArgNode->gtGetOp1()->isContained()); - assert(putArgNode->gtGetOp1()->gtOp.gtOper == GT_OBJ); - - // TODO: In the below code the load and store instructions are for 16 bytes, but the - // type is EA_8BYTE. The movdqa/u are 16 byte instructions, so it works, but - // this probably needs to be changed. - while (slots-- > 0) - { - // Load - genCodeForLoadOffset(INS_movdqu, EA_8BYTE, xmmReg, src->gtGetOp1(), - offset); // Load the address of the child of the Obj node. + genDefineTempLabel(endLabel); + } - // Store - emit->emitIns_S_R(INS_movdqu, EA_8BYTE, xmmReg, baseVarNum, putArgOffset + offset); +BAILOUT: - offset += XMM_REGSIZE_BYTES; - } + // Write the lvaLocAllocSPvar stack frame slot + if (compiler->lvaLocAllocSPvar != BAD_VAR_NUM) + { + getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SPBASE, compiler->lvaLocAllocSPvar, 0); } - // Fill the remainder (15 bytes or less) if there's one. - if ((size & 0xf) != 0) +#if STACK_PROBES + if (compiler->opts.compNeedStackProbes) { - // Grab the integer temp register to emit the remaining loads and stores. - regNumber tmpReg = genRegNumFromMask(putArgNode->gtRsvdRegs & RBM_ALLINT); - assert(genIsValidIntReg(tmpReg)); - - if ((size & 8) != 0) - { - genCodeForLoadOffset(INS_mov, EA_8BYTE, tmpReg, src->gtOp.gtOp1, offset); - - emit->emitIns_S_R(INS_mov, EA_8BYTE, tmpReg, baseVarNum, putArgOffset + offset); - - offset += 8; - } - - if ((size & 4) != 0) - { - genCodeForLoadOffset(INS_mov, EA_4BYTE, tmpReg, src->gtOp.gtOp1, offset); + genGenerateStackProbe(); + } +#endif - emit->emitIns_S_R(INS_mov, EA_4BYTE, tmpReg, baseVarNum, putArgOffset + offset); +#ifdef DEBUG + // Update new ESP + if (compiler->opts.compStackCheckOnRet) + { + noway_assert(compiler->lvaReturnEspCheck != 0xCCCCCCCC && + compiler->lvaTable[compiler->lvaReturnEspCheck].lvDoNotEnregister && + compiler->lvaTable[compiler->lvaReturnEspCheck].lvOnFrame); + getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SPBASE, compiler->lvaReturnEspCheck, 0); + } +#endif - offset += 4; - } + genProduceReg(tree); +} - if ((size & 2) != 0) - { - genCodeForLoadOffset(INS_mov, EA_2BYTE, tmpReg, src->gtOp.gtOp1, offset); +void CodeGen::genCodeForStoreBlk(GenTreeBlk* storeBlkNode) +{ +#ifdef JIT32_GCENCODER + assert(!storeBlkNode->gtBlkOpGcUnsafe); +#else + if (storeBlkNode->gtBlkOpGcUnsafe) + { + getEmitter()->emitDisableGC(); + } +#endif // JIT32_GCENCODER - emit->emitIns_S_R(INS_mov, EA_2BYTE, tmpReg, baseVarNum, putArgOffset + offset); + bool isCopyBlk = storeBlkNode->OperIsCopyBlkOp(); - offset += 2; - } + switch (storeBlkNode->gtBlkOpKind) + { +#ifdef _TARGET_AMD64_ + case GenTreeBlk::BlkOpKindHelper: + if (isCopyBlk) + { + genCodeForCpBlk(storeBlkNode); + } + else + { + genCodeForInitBlk(storeBlkNode); + } + break; +#endif // _TARGET_AMD64_ + case GenTreeBlk::BlkOpKindRepInstr: + if (isCopyBlk) + { + genCodeForCpBlkRepMovs(storeBlkNode); + } + else + { + genCodeForInitBlkRepStos(storeBlkNode); + } + break; + case GenTreeBlk::BlkOpKindUnroll: + if (isCopyBlk) + { + genCodeForCpBlkUnroll(storeBlkNode); + } + else + { + genCodeForInitBlkUnroll(storeBlkNode); + } + break; + default: + unreached(); + } - if ((size & 1) != 0) - { - genCodeForLoadOffset(INS_mov, EA_1BYTE, tmpReg, src->gtOp.gtOp1, offset); - emit->emitIns_S_R(INS_mov, EA_1BYTE, tmpReg, baseVarNum, putArgOffset + offset); - } +#ifndef JIT32_GCENCODER + if (storeBlkNode->gtBlkOpGcUnsafe) + { + getEmitter()->emitEnableGC(); } +#endif // !defined(JIT32_GCENCODER) } +// //------------------------------------------------------------------------ -// genStructPutArgRepMovs: Generates code for passing a struct arg by value on stack using Rep Movs. +// genCodeForInitBlkRepStos: Generate code for InitBlk using rep stos. // // Arguments: -// putArgNode - the PutArgStk tree. -// baseVarNum - the base var number, relative to which the by-val struct bits will go. +// initBlkNode - The Block store for which we are generating code. // // Preconditions: -// The size argument of the PutArgStk (for structs) is a constant and is between -// CPBLK_UNROLL_LIMIT and CPBLK_MOVS_LIMIT bytes. +// On x64: +// The size of the buffers must be a constant and also less than INITBLK_STOS_LIMIT bytes. +// Any value larger than that, we'll use the helper even if both the fill byte and the +// size are integer constants. +// On x86: +// The size must either be a non-constant or less than INITBLK_STOS_LIMIT bytes. // -void CodeGen::genStructPutArgRepMovs(GenTreePutArgStk* putArgNode, unsigned baseVarNum) +void CodeGen::genCodeForInitBlkRepStos(GenTreeBlk* initBlkNode) { - assert(putArgNode->TypeGet() == TYP_STRUCT); - assert(putArgNode->getArgSize() > CPBLK_UNROLL_LIMIT); - assert(baseVarNum != BAD_VAR_NUM); - - // Make sure we got the arguments of the cpblk operation in the right registers - GenTreePtr dstAddr = putArgNode; - GenTreePtr srcAddr = putArgNode->gtGetOp1(); - - // Validate state. - assert(putArgNode->gtRsvdRegs == (RBM_RDI | RBM_RCX | RBM_RSI)); - assert(srcAddr->isContained()); - - genConsumePutStructArgStk(putArgNode, REG_RDI, REG_RSI, REG_RCX, baseVarNum); - instGen(INS_r_movsb); -} + // Make sure we got the arguments of the initblk/initobj operation in the right registers. + unsigned size = initBlkNode->Size(); + GenTreePtr dstAddr = initBlkNode->Addr(); + GenTreePtr initVal = initBlkNode->Data(); + if (initVal->OperIsInitVal()) + { + initVal = initVal->gtGetOp1(); + } -//------------------------------------------------------------------------ -// If any Vector3 args are on stack and they are not pass-by-ref, the upper 32bits -// must be cleared to zeroes. The native compiler doesn't clear the upper bits -// and there is no way to know if the caller is native or not. So, the upper -// 32 bits of Vector argument on stack are always cleared to zero. -#ifdef FEATURE_SIMD -void CodeGen::genClearStackVec3ArgUpperBits() -{ #ifdef DEBUG - if (verbose) - printf("*************** In genClearStackVec3ArgUpperBits()\n"); + assert(!dstAddr->isContained()); + assert(!initVal->isContained()); +#ifdef _TARGET_AMD64_ + assert(size != 0); #endif - - assert(compiler->compGeneratingProlog); - - unsigned varNum = 0; - - for (unsigned varNum = 0; varNum < compiler->info.compArgsCount; varNum++) + if (initVal->IsCnsIntOrI()) { - LclVarDsc* varDsc = &(compiler->lvaTable[varNum]); - assert(varDsc->lvIsParam); - - // Does var has simd12 type? - if (varDsc->lvType != TYP_SIMD12) - { - continue; - } +#ifdef _TARGET_AMD64_ + assert(size > CPBLK_UNROLL_LIMIT && size < CPBLK_MOVS_LIMIT); +#else + // Note that a size of zero means a non-constant size. + assert((size == 0) || (size > CPBLK_UNROLL_LIMIT)); +#endif + } - if (!varDsc->lvIsRegArg) - { - // Clear the upper 32 bits by mov dword ptr [V_ARG_BASE+0xC], 0 - getEmitter()->emitIns_S_I(ins_Store(TYP_INT), EA_4BYTE, varNum, genTypeSize(TYP_FLOAT) * 3, 0); - } - else - { - // Assume that for x64 linux, an argument is fully in registers - // or fully on stack. - regNumber argReg = varDsc->GetOtherArgReg(); +#endif // DEBUG - // Clear the upper 32 bits by two shift instructions. - // argReg = argReg << 96 - getEmitter()->emitIns_R_I(INS_pslldq, emitActualTypeSize(TYP_SIMD12), argReg, 12); - // argReg = argReg >> 96 - getEmitter()->emitIns_R_I(INS_psrldq, emitActualTypeSize(TYP_SIMD12), argReg, 12); - } - } + genConsumeBlockOp(initBlkNode, REG_RDI, REG_RAX, REG_RCX); + instGen(INS_r_stosb); } -#endif // FEATURE_SIMD -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING -// Generate code for CpObj nodes wich copy structs that have interleaved -// GC pointers. -// This will generate a sequence of movsq instructions for the cases of non-gc members -// and calls to the BY_REF_ASSIGN helper otherwise. -void CodeGen::genCodeForCpObj(GenTreeObj* cpObjNode) +// Generate code for InitBlk by performing a loop unroll +// Preconditions: +// a) Both the size and fill byte value are integer constants. +// b) The size of the struct to initialize is smaller than INITBLK_UNROLL_LIMIT bytes. +// +void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* initBlkNode) { - // Make sure we got the arguments of the cpobj operation in the right registers - GenTreePtr dstAddr = cpObjNode->Addr(); - GenTreePtr source = cpObjNode->Data(); - GenTreePtr srcAddr = nullptr; - bool sourceIsLocal = false; - - assert(source->isContained()); - if (source->gtOper == GT_IND) - { - srcAddr = source->gtGetOp1(); - assert(!srcAddr->isContained()); - } - else + // Make sure we got the arguments of the initblk/initobj operation in the right registers + unsigned size = initBlkNode->Size(); + GenTreePtr dstAddr = initBlkNode->Addr(); + GenTreePtr initVal = initBlkNode->Data(); + if (initVal->OperIsInitVal()) { - noway_assert(source->IsLocal()); - sourceIsLocal = true; - // TODO: Consider making the addrForm() method in Rationalize public, e.g. in GenTree. - // OR: transform source to GT_IND(GT_LCL_VAR_ADDR) - if (source->OperGet() == GT_LCL_VAR) - { - source->SetOper(GT_LCL_VAR_ADDR); - } - else - { - assert(source->OperGet() == GT_LCL_FLD); - source->SetOper(GT_LCL_FLD_ADDR); - } - srcAddr = source; + initVal = initVal->gtGetOp1(); } - bool dstOnStack = dstAddr->OperIsLocalAddr(); - -#ifdef DEBUG - bool isRepMovsqUsed = false; - assert(!dstAddr->isContained()); + assert(!initVal->isContained() || (initVal->IsIntegralConst(0) && ((size & 0xf) == 0))); + assert(size != 0); + assert(size <= INITBLK_UNROLL_LIMIT); + assert(initVal->gtSkipReloadOrCopy()->IsCnsIntOrI()); - // If the GenTree node has data about GC pointers, this means we're dealing - // with CpObj, so this requires special logic. - assert(cpObjNode->gtGcPtrCount > 0); + emitter* emit = getEmitter(); - // MovSq instruction is used for copying non-gcref fields and it needs - // src = RSI and dst = RDI. - // Either these registers must not contain lclVars, or they must be dying or marked for spill. - // This is because these registers are incremented as we go through the struct. - GenTree* actualSrcAddr = srcAddr->gtSkipReloadOrCopy(); - GenTree* actualDstAddr = dstAddr->gtSkipReloadOrCopy(); - unsigned srcLclVarNum = BAD_VAR_NUM; - unsigned dstLclVarNum = BAD_VAR_NUM; - bool isSrcAddrLiveOut = false; - bool isDstAddrLiveOut = false; - if (genIsRegCandidateLocal(actualSrcAddr)) - { - srcLclVarNum = actualSrcAddr->AsLclVarCommon()->gtLclNum; - isSrcAddrLiveOut = ((actualSrcAddr->gtFlags & (GTF_VAR_DEATH | GTF_SPILL)) == 0); - } - if (genIsRegCandidateLocal(actualDstAddr)) - { - dstLclVarNum = actualDstAddr->AsLclVarCommon()->gtLclNum; - isDstAddrLiveOut = ((actualDstAddr->gtFlags & (GTF_VAR_DEATH | GTF_SPILL)) == 0); - } - assert((actualSrcAddr->gtRegNum != REG_RSI) || !isSrcAddrLiveOut || - ((srcLclVarNum == dstLclVarNum) && !isDstAddrLiveOut)); - assert((actualDstAddr->gtRegNum != REG_RDI) || !isDstAddrLiveOut || - ((srcLclVarNum == dstLclVarNum) && !isSrcAddrLiveOut)); -#endif // DEBUG + genConsumeOperands(initBlkNode); - // Consume these registers. - // They may now contain gc pointers (depending on their type; gcMarkRegPtrVal will "do the right thing"). - if (sourceIsLocal) - { - inst_RV_TT(INS_lea, REG_RSI, source, 0, EA_BYREF); - genConsumeBlockOp(cpObjNode, REG_RDI, REG_NA, REG_NA); - } - else - { - genConsumeBlockOp(cpObjNode, REG_RDI, REG_RSI, REG_NA); - } - gcInfo.gcMarkRegPtrVal(REG_RSI, srcAddr->TypeGet()); - gcInfo.gcMarkRegPtrVal(REG_RDI, dstAddr->TypeGet()); + // If the initVal was moved, or spilled and reloaded to a different register, + // get the original initVal from below the GT_RELOAD, but only after capturing the valReg, + // which needs to be the new register. + regNumber valReg = initVal->gtRegNum; + initVal = initVal->gtSkipReloadOrCopy(); - unsigned slots = cpObjNode->gtSlots; + unsigned offset = 0; - // If we can prove it's on the stack we don't need to use the write barrier. - if (dstOnStack) + // Perform an unroll using SSE2 loads and stores. + if (size >= XMM_REGSIZE_BYTES) { - if (slots >= CPOBJ_NONGC_SLOTS_LIMIT) - { + regNumber tmpReg = genRegNumFromMask(initBlkNode->gtRsvdRegs); + #ifdef DEBUG - // If the destination of the CpObj is on the stack - // make sure we allocated RCX to emit rep movsq. - regNumber tmpReg = genRegNumFromMask(cpObjNode->gtRsvdRegs & RBM_ALLINT); - assert(tmpReg == REG_RCX); - isRepMovsqUsed = true; + assert(initBlkNode->gtRsvdRegs != RBM_NONE); + assert(genCountBits(initBlkNode->gtRsvdRegs) == 1); + assert(genIsValidFloatReg(tmpReg)); #endif // DEBUG - getEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, REG_RCX, slots); - instGen(INS_r_movsq); + if (initVal->gtIntCon.gtIconVal != 0) + { + emit->emitIns_R_R(INS_mov_i2xmm, EA_PTRSIZE, tmpReg, valReg); + emit->emitIns_R_R(INS_punpckldq, EA_8BYTE, tmpReg, tmpReg); +#ifdef _TARGET_X86_ + // For x86, we need one more to convert it from 8 bytes to 16 bytes. + emit->emitIns_R_R(INS_punpckldq, EA_8BYTE, tmpReg, tmpReg); +#endif // _TARGET_X86_ } else { - // For small structs, it's better to emit a sequence of movsq than to - // emit a rep movsq instruction. - while (slots > 0) - { - instGen(INS_movsq); - slots--; - } + emit->emitIns_R_R(INS_xorpd, EA_8BYTE, tmpReg, tmpReg); } - } - else - { - BYTE* gcPtrs = cpObjNode->gtGcPtrs; - unsigned gcPtrCount = cpObjNode->gtGcPtrCount; - unsigned i = 0; - while (i < slots) + // Determine how many 16 byte slots we're going to fill using SSE movs. + size_t slots = size / XMM_REGSIZE_BYTES; + + while (slots-- > 0) { - switch (gcPtrs[i]) - { - case TYPE_GC_NONE: - // Let's see if we can use rep movsq instead of a sequence of movsq instructions - // to save cycles and code size. - { - unsigned nonGcSlotCount = 0; + emit->emitIns_AR_R(INS_movdqu, EA_8BYTE, tmpReg, dstAddr->gtRegNum, offset); + offset += XMM_REGSIZE_BYTES; + } + } - do - { - nonGcSlotCount++; - i++; - } while (i < slots && gcPtrs[i] == TYPE_GC_NONE); + // Fill the remainder (or a < 16 byte sized struct) + if ((size & 8) != 0) + { +#ifdef _TARGET_X86_ + // TODO-X86-CQ: [1091735] Revisit block ops codegen. One example: use movq for 8 byte movs. + emit->emitIns_AR_R(INS_mov, EA_4BYTE, valReg, dstAddr->gtRegNum, offset); + offset += 4; + emit->emitIns_AR_R(INS_mov, EA_4BYTE, valReg, dstAddr->gtRegNum, offset); + offset += 4; +#else // !_TARGET_X86_ - // If we have a very small contiguous non-gc region, it's better just to - // emit a sequence of movsq instructions - if (nonGcSlotCount < CPOBJ_NONGC_SLOTS_LIMIT) - { - while (nonGcSlotCount > 0) - { - instGen(INS_movsq); - nonGcSlotCount--; - } - } - else - { -#ifdef DEBUG - // Otherwise, we can save code-size and improve CQ by emitting - // rep movsq - regNumber tmpReg = genRegNumFromMask(cpObjNode->gtRsvdRegs & RBM_ALLINT); - assert(tmpReg == REG_RCX); - isRepMovsqUsed = true; -#endif // DEBUG - getEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, REG_RCX, nonGcSlotCount); - instGen(INS_r_movsq); - } - } - break; - default: - // We have a GC pointer, call the memory barrier. - genEmitHelperCall(CORINFO_HELP_ASSIGN_BYREF, 0, EA_PTRSIZE); - gcPtrCount--; - i++; - } - } + emit->emitIns_AR_R(INS_mov, EA_8BYTE, valReg, dstAddr->gtRegNum, offset); + offset += 8; - assert(gcPtrCount == 0); +#endif // !_TARGET_X86_ + } + if ((size & 4) != 0) + { + emit->emitIns_AR_R(INS_mov, EA_4BYTE, valReg, dstAddr->gtRegNum, offset); + offset += 4; + } + if ((size & 2) != 0) + { + emit->emitIns_AR_R(INS_mov, EA_2BYTE, valReg, dstAddr->gtRegNum, offset); + offset += 2; + } + if ((size & 1) != 0) + { + emit->emitIns_AR_R(INS_mov, EA_1BYTE, valReg, dstAddr->gtRegNum, offset); } - - // Clear the gcInfo for RSI and RDI. - // While we normally update GC info prior to the last instruction that uses them, - // these actually live into the helper call. - gcInfo.gcMarkRegSetNpt(RBM_RSI); - gcInfo.gcMarkRegSetNpt(RBM_RDI); } -// Generate code for a CpBlk node by the means of the VM memcpy helper call +// Generates code for InitBlk by calling the VM memset helper function. // Preconditions: -// a) The size argument of the CpBlk is not an integer constant -// b) The size argument is a constant but is larger than CPBLK_MOVS_LIMIT bytes. -void CodeGen::genCodeForCpBlk(GenTreeBlk* cpBlkNode) +// a) The size argument of the InitBlk is not an integer constant. +// b) The size argument of the InitBlk is >= INITBLK_STOS_LIMIT bytes. +void CodeGen::genCodeForInitBlk(GenTreeBlk* initBlkNode) { #ifdef _TARGET_AMD64_ - // Make sure we got the arguments of the cpblk operation in the right registers - unsigned blockSize = cpBlkNode->Size(); - GenTreePtr dstAddr = cpBlkNode->Addr(); - GenTreePtr source = cpBlkNode->Data(); - GenTreePtr srcAddr = nullptr; - - // Size goes in arg2 - if (blockSize != 0) - { - assert(blockSize >= CPBLK_MOVS_LIMIT); - assert((cpBlkNode->gtRsvdRegs & RBM_ARG_2) != 0); - } - else + // Make sure we got the arguments of the initblk operation in the right registers + unsigned blockSize = initBlkNode->Size(); + GenTreePtr dstAddr = initBlkNode->Addr(); + GenTreePtr initVal = initBlkNode->Data(); + if (initVal->OperIsInitVal()) { - noway_assert(cpBlkNode->gtOper == GT_STORE_DYN_BLK); + initVal = initVal->gtGetOp1(); } - // Source address goes in arg1 - if (source->gtOper == GT_IND) - { - srcAddr = source->gtGetOp1(); - assert(!srcAddr->isContained()); - } - else + assert(!dstAddr->isContained()); + assert(!initVal->isContained()); + + if (blockSize != 0) { - noway_assert(source->IsLocal()); - assert((cpBlkNode->gtRsvdRegs & RBM_ARG_1) != 0); - inst_RV_TT(INS_lea, REG_ARG_1, source, 0, EA_BYREF); + assert(blockSize >= CPBLK_MOVS_LIMIT); } - genConsumeBlockOp(cpBlkNode, REG_ARG_0, REG_ARG_1, REG_ARG_2); + genConsumeBlockOp(initBlkNode, REG_ARG_0, REG_ARG_1, REG_ARG_2); - genEmitHelperCall(CORINFO_HELP_MEMCPY, 0, EA_UNKNOWN); + genEmitHelperCall(CORINFO_HELP_MEMSET, 0, EA_UNKNOWN); #else // !_TARGET_AMD64_ - noway_assert(false && "Helper call for CpBlk is not needed."); + NYI_X86("Helper call for InitBlk"); #endif // !_TARGET_AMD64_ } -// generate code do a switch statement based on a table of ip-relative offsets -void CodeGen::genTableBasedSwitch(GenTree* treeNode) +// Generate code for a load from some address + offset +// baseNode: tree node which can be either a local address or arbitrary node +// offset: distance from the baseNode from which to load +void CodeGen::genCodeForLoadOffset(instruction ins, emitAttr size, regNumber dst, GenTree* baseNode, unsigned offset) { - genConsumeOperands(treeNode->AsOp()); - regNumber idxReg = treeNode->gtOp.gtOp1->gtRegNum; - regNumber baseReg = treeNode->gtOp.gtOp2->gtRegNum; - - regNumber tmpReg = genRegNumFromMask(treeNode->gtRsvdRegs); - - // load the ip-relative offset (which is relative to start of fgFirstBB) - getEmitter()->emitIns_R_ARX(INS_mov, EA_4BYTE, baseReg, baseReg, idxReg, 4, 0); + emitter* emit = getEmitter(); - // add it to the absolute address of fgFirstBB - compiler->fgFirstBB->bbFlags |= BBF_JMP_TARGET; - getEmitter()->emitIns_R_L(INS_lea, EA_PTR_DSP_RELOC, compiler->fgFirstBB, tmpReg); - getEmitter()->emitIns_R_R(INS_add, EA_PTRSIZE, baseReg, tmpReg); - // jmp baseReg - getEmitter()->emitIns_R(INS_i_jmp, emitTypeSize(TYP_I_IMPL), baseReg); + if (baseNode->OperIsLocalAddr()) + { + if (baseNode->gtOper == GT_LCL_FLD_ADDR) + { + offset += baseNode->gtLclFld.gtLclOffs; + } + emit->emitIns_R_S(ins, size, dst, baseNode->gtLclVarCommon.gtLclNum, offset); + } + else + { + emit->emitIns_R_AR(ins, size, dst, baseNode->gtRegNum, offset); + } } -// emits the table and an instruction to get the address of the first element -void CodeGen::genJumpTable(GenTree* treeNode) +//------------------------------------------------------------------------ +// genCodeForStoreOffset: Generate code to store a reg to [base + offset]. +// +// Arguments: +// ins - the instruction to generate. +// size - the size that needs to be stored. +// src - the register which needs to be stored. +// baseNode - the base, relative to which to store the src register. +// offset - the offset that is added to the baseNode to calculate the address to store into. +// +void CodeGen::genCodeForStoreOffset(instruction ins, emitAttr size, regNumber src, GenTree* baseNode, unsigned offset) { - noway_assert(compiler->compCurBB->bbJumpKind == BBJ_SWITCH); - assert(treeNode->OperGet() == GT_JMPTABLE); - - unsigned jumpCount = compiler->compCurBB->bbJumpSwt->bbsCount; - BasicBlock** jumpTable = compiler->compCurBB->bbJumpSwt->bbsDstTab; - unsigned jmpTabOffs; - unsigned jmpTabBase; - - jmpTabBase = getEmitter()->emitBBTableDataGenBeg(jumpCount, true); - - jmpTabOffs = 0; - - JITDUMP("\n J_M%03u_DS%02u LABEL DWORD\n", Compiler::s_compMethodsCount, jmpTabBase); + emitter* emit = getEmitter(); - for (unsigned i = 0; i < jumpCount; i++) + if (baseNode->OperIsLocalAddr()) { - BasicBlock* target = *jumpTable++; - noway_assert(target->bbFlags & BBF_JMP_TARGET); - - JITDUMP(" DD L_M%03u_BB%02u\n", Compiler::s_compMethodsCount, target->bbNum); - - getEmitter()->emitDataGenData(i, target); - }; - - getEmitter()->emitDataGenEnd(); + if (baseNode->gtOper == GT_LCL_FLD_ADDR) + { + offset += baseNode->gtLclFld.gtLclOffs; + } - // Access to inline data is 'abstracted' by a special type of static member - // (produced by eeFindJitDataOffs) which the emitter recognizes as being a reference - // to constant data, not a real static field. - getEmitter()->emitIns_R_C(INS_lea, emitTypeSize(TYP_I_IMPL), treeNode->gtRegNum, - compiler->eeFindJitDataOffs(jmpTabBase), 0); - genProduceReg(treeNode); + emit->emitIns_S_R(ins, size, src, baseNode->AsLclVarCommon()->GetLclNum(), offset); + } + else + { + emit->emitIns_AR_R(ins, size, src, baseNode->gtRegNum, offset); + } } -// generate code for the locked operations: -// GT_LOCKADD, GT_XCHG, GT_XADD -void CodeGen::genLockedInstructions(GenTree* treeNode) +// Generates CpBlk code by performing a loop unroll +// Preconditions: +// The size argument of the CpBlk node is a constant and <= 64 bytes. +// This may seem small but covers >95% of the cases in several framework assemblies. +// +void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* cpBlkNode) { - GenTree* data = treeNode->gtOp.gtOp2; - GenTree* addr = treeNode->gtOp.gtOp1; - regNumber targetReg = treeNode->gtRegNum; - regNumber dataReg = data->gtRegNum; - regNumber addrReg = addr->gtRegNum; - instruction ins; - - // all of these nodes implicitly do an indirection on op1 - // so create a temporary node to feed into the pattern matching - GenTreeIndir i = indirForm(data->TypeGet(), addr); - genConsumeReg(addr); - - // The register allocator should have extended the lifetime of the address - // so that it is not used as the target. - noway_assert(addrReg != targetReg); + // Make sure we got the arguments of the cpblk operation in the right registers + unsigned size = cpBlkNode->Size(); + GenTreePtr dstAddr = cpBlkNode->Addr(); + GenTreePtr source = cpBlkNode->Data(); + GenTreePtr srcAddr = nullptr; + assert(size <= CPBLK_UNROLL_LIMIT); - // If data is a lclVar that's not a last use, we'd better have allocated a register - // for the result (except in the case of GT_LOCKADD which does not produce a register result). - assert(targetReg != REG_NA || treeNode->OperGet() == GT_LOCKADD || !genIsRegCandidateLocal(data) || - (data->gtFlags & GTF_VAR_DEATH) != 0); + emitter* emit = getEmitter(); - genConsumeIfReg(data); - if (targetReg != REG_NA && dataReg != REG_NA && dataReg != targetReg) + if (source->gtOper == GT_IND) { - inst_RV_RV(ins_Copy(data->TypeGet()), targetReg, dataReg); - data->gtRegNum = targetReg; + srcAddr = source->gtGetOp1(); + if (!srcAddr->isContained()) + { + genConsumeReg(srcAddr); + } + } + else + { + noway_assert(source->IsLocal()); + // TODO-Cleanup: Consider making the addrForm() method in Rationalize public, e.g. in GenTree. + // OR: transform source to GT_IND(GT_LCL_VAR_ADDR) + if (source->OperGet() == GT_LCL_VAR) + { + source->SetOper(GT_LCL_VAR_ADDR); + } + else + { + assert(source->OperGet() == GT_LCL_FLD); + source->SetOper(GT_LCL_FLD_ADDR); + } + srcAddr = source; + } - // TODO-XArch-Cleanup: Consider whether it is worth it, for debugging purposes, to restore the - // original gtRegNum on data, after calling emitInsBinary below. + if (!dstAddr->isContained()) + { + genConsumeReg(dstAddr); } - switch (treeNode->OperGet()) + + unsigned offset = 0; + + // If the size of this struct is larger than 16 bytes + // let's use SSE2 to be able to do 16 byte at a time + // loads and stores. + + if (size >= XMM_REGSIZE_BYTES) { - case GT_LOCKADD: - instGen(INS_lock); - ins = INS_add; - break; - case GT_XCHG: - // lock is implied by xchg - ins = INS_xchg; - break; - case GT_XADD: - instGen(INS_lock); - ins = INS_xadd; - break; - default: - unreached(); + assert(cpBlkNode->gtRsvdRegs != RBM_NONE); + regNumber xmmReg = genRegNumFromMask(cpBlkNode->gtRsvdRegs & RBM_ALLFLOAT); + assert(genIsValidFloatReg(xmmReg)); + size_t slots = size / XMM_REGSIZE_BYTES; + + // TODO: In the below code the load and store instructions are for 16 bytes, but the + // type is EA_8BYTE. The movdqa/u are 16 byte instructions, so it works, but + // this probably needs to be changed. + while (slots-- > 0) + { + // Load + genCodeForLoadOffset(INS_movdqu, EA_8BYTE, xmmReg, srcAddr, offset); + // Store + genCodeForStoreOffset(INS_movdqu, EA_8BYTE, xmmReg, dstAddr, offset); + offset += XMM_REGSIZE_BYTES; + } } - getEmitter()->emitInsBinary(ins, emitTypeSize(data), &i, data); - if (treeNode->gtRegNum != REG_NA) + // Fill the remainder (15 bytes or less) if there's one. + if ((size & 0xf) != 0) { - genProduceReg(treeNode); + // Grab the integer temp register to emit the remaining loads and stores. + regNumber tmpReg = genRegNumFromMask(cpBlkNode->gtRsvdRegs & RBM_ALLINT); + + if ((size & 8) != 0) + { +#ifdef _TARGET_X86_ + // TODO-X86-CQ: [1091735] Revisit block ops codegen. One example: use movq for 8 byte movs. + for (unsigned savedOffs = offset; offset < savedOffs + 8; offset += 4) + { + genCodeForLoadOffset(INS_mov, EA_4BYTE, tmpReg, srcAddr, offset); + genCodeForStoreOffset(INS_mov, EA_4BYTE, tmpReg, dstAddr, offset); + } +#else // !_TARGET_X86_ + genCodeForLoadOffset(INS_mov, EA_8BYTE, tmpReg, srcAddr, offset); + genCodeForStoreOffset(INS_mov, EA_8BYTE, tmpReg, dstAddr, offset); + offset += 8; +#endif // !_TARGET_X86_ + } + if ((size & 4) != 0) + { + genCodeForLoadOffset(INS_mov, EA_4BYTE, tmpReg, srcAddr, offset); + genCodeForStoreOffset(INS_mov, EA_4BYTE, tmpReg, dstAddr, offset); + offset += 4; + } + if ((size & 2) != 0) + { + genCodeForLoadOffset(INS_mov, EA_2BYTE, tmpReg, srcAddr, offset); + genCodeForStoreOffset(INS_mov, EA_2BYTE, tmpReg, dstAddr, offset); + offset += 2; + } + if ((size & 1) != 0) + { + genCodeForLoadOffset(INS_mov, EA_1BYTE, tmpReg, srcAddr, offset); + genCodeForStoreOffset(INS_mov, EA_1BYTE, tmpReg, dstAddr, offset); + } } } -// generate code for BoundsCheck nodes -void CodeGen::genRangeCheck(GenTreePtr oper) +// Generate code for CpBlk by using rep movs +// Preconditions: +// The size argument of the CpBlk is a constant and is between +// CPBLK_UNROLL_LIMIT and CPBLK_MOVS_LIMIT bytes. +void CodeGen::genCodeForCpBlkRepMovs(GenTreeBlk* cpBlkNode) { -#ifdef FEATURE_SIMD - noway_assert(oper->OperGet() == GT_ARR_BOUNDS_CHECK || oper->OperGet() == GT_SIMD_CHK); -#else // !FEATURE_SIMD - noway_assert(oper->OperGet() == GT_ARR_BOUNDS_CHECK); -#endif // !FEATURE_SIMD - - GenTreeBoundsChk* bndsChk = oper->AsBoundsChk(); - - GenTreePtr arrLen = bndsChk->gtArrLen; - GenTreePtr arrIndex = bndsChk->gtIndex; - GenTreePtr arrRef = nullptr; - int lenOffset = 0; - - GenTree * src1, *src2; - emitJumpKind jmpKind; + // Make sure we got the arguments of the cpblk operation in the right registers + unsigned size = cpBlkNode->Size(); + GenTreePtr dstAddr = cpBlkNode->Addr(); + GenTreePtr source = cpBlkNode->Data(); + GenTreePtr srcAddr = nullptr; - genConsumeRegs(arrLen); - genConsumeRegs(arrIndex); +#ifdef DEBUG + assert(!dstAddr->isContained()); + assert(source->isContained()); - if (arrIndex->isContainedIntOrIImmed()) +#ifdef _TARGET_X86_ + if (size == 0) { - // arrIndex is a contained constant. In this case - // we will generate one of the following - // cmp [mem], immed (if arrLen is a memory op) - // cmp reg, immed (if arrLen is in a reg) - // - // That is arrLen cannot be a contained immed. - assert(!arrLen->isContainedIntOrIImmed()); - - src1 = arrLen; - src2 = arrIndex; - jmpKind = EJ_jbe; + noway_assert(cpBlkNode->OperGet() == GT_STORE_DYN_BLK); } else +#endif { - // arrIndex could either be a contained memory op or a reg - // In this case we will generate one of the following - // cmp [mem], immed (if arrLen is a constant) - // cmp [mem], reg (if arrLen is in a reg) - // cmp reg, immed (if arrIndex is in a reg) - // cmp reg1, reg2 (if arraIndex is in reg1) - // cmp reg, [mem] (if arrLen is a memory op) - // - // That is only one of arrIndex or arrLen can be a memory op. - assert(!arrIndex->isContainedMemoryOp() || !arrLen->isContainedMemoryOp()); - - src1 = arrIndex; - src2 = arrLen; - jmpKind = EJ_jae; +#ifdef _TARGET_X64_ + assert(size > CPBLK_UNROLL_LIMIT && size < CPBLK_MOVS_LIMIT); +#else + assert(size > CPBLK_UNROLL_LIMIT); +#endif } - - var_types bndsChkType = src2->TypeGet(); -#if DEBUG - // Bounds checks can only be 32 or 64 bit sized comparisons. - assert(bndsChkType == TYP_INT || bndsChkType == TYP_LONG); - - // The type of the bounds check should always wide enough to compare against the index. - assert(emitTypeSize(bndsChkType) >= emitTypeSize(src1->TypeGet())); #endif // DEBUG - getEmitter()->emitInsBinary(INS_cmp, emitTypeSize(bndsChkType), src1, src2); - genJumpToThrowHlpBlk(jmpKind, bndsChk->gtThrowKind, bndsChk->gtIndRngFailBB); + genConsumeBlockOp(cpBlkNode, REG_RDI, REG_RSI, REG_RCX); + instGen(INS_r_movsb); } +#ifdef FEATURE_PUT_STRUCT_ARG_STK //------------------------------------------------------------------------ -// genOffsetOfMDArrayLowerBound: Returns the offset from the Array object to the -// lower bound for the given dimension. +// CodeGen::genMove8IfNeeded: Conditionally move 8 bytes of a struct to the argument area // // Arguments: -// elemType - the element type of the array -// rank - the rank of the array -// dimension - the dimension for which the lower bound offset will be returned. +// size - The size of bytes remaining to be moved +// longTmpReg - The tmp register to be used for the long value +// srcAddr - The address of the source struct +// offset - The current offset being copied // // Return Value: -// The offset. - -unsigned CodeGen::genOffsetOfMDArrayLowerBound(var_types elemType, unsigned rank, unsigned dimension) +// Returns the number of bytes moved (8 or 0). +// +// Notes: +// This is used in the PutArgStkKindUnroll case, to move any bytes that are +// not an even multiple of 16. +// On x86, longTmpReg must be an xmm reg; on x64 it must be an integer register. +// This is checked by genStoreRegToStackArg. +// +int CodeGen::genMove8IfNeeded(unsigned size, regNumber longTmpReg, GenTree* srcAddr, unsigned offset) { - // Note that the lower bound and length fields of the Array object are always TYP_INT, even on 64-bit targets. - return compiler->eeGetArrayDataOffset(elemType) + genTypeSize(TYP_INT) * (dimension + rank); +#ifdef _TARGET_X86_ + instruction longMovIns = INS_movq; +#else // !_TARGET_X86_ + instruction longMovIns = INS_mov; +#endif // !_TARGET_X86_ + if ((size & 8) != 0) + { + genCodeForLoadOffset(longMovIns, EA_8BYTE, longTmpReg, srcAddr, offset); + genStoreRegToStackArg(TYP_LONG, longTmpReg, offset); + return 8; + } + return 0; } //------------------------------------------------------------------------ -// genOffsetOfMDArrayLength: Returns the offset from the Array object to the -// size for the given dimension. +// CodeGen::genMove4IfNeeded: Conditionally move 4 bytes of a struct to the argument area // // Arguments: -// elemType - the element type of the array -// rank - the rank of the array -// dimension - the dimension for which the lower bound offset will be returned. +// size - The size of bytes remaining to be moved +// intTmpReg - The tmp register to be used for the long value +// srcAddr - The address of the source struct +// offset - The current offset being copied // // Return Value: -// The offset. - -unsigned CodeGen::genOffsetOfMDArrayDimensionSize(var_types elemType, unsigned rank, unsigned dimension) +// Returns the number of bytes moved (4 or 0). +// +// Notes: +// This is used in the PutArgStkKindUnroll case, to move any bytes that are +// not an even multiple of 16. +// intTmpReg must be an integer register. +// This is checked by genStoreRegToStackArg. +// +int CodeGen::genMove4IfNeeded(unsigned size, regNumber intTmpReg, GenTree* srcAddr, unsigned offset) { - // Note that the lower bound and length fields of the Array object are always TYP_INT, even on 64-bit targets. - return compiler->eeGetArrayDataOffset(elemType) + genTypeSize(TYP_INT) * dimension; + if ((size & 4) != 0) + { + genCodeForLoadOffset(INS_mov, EA_4BYTE, intTmpReg, srcAddr, offset); + genStoreRegToStackArg(TYP_INT, intTmpReg, offset); + return 4; + } + return 0; } //------------------------------------------------------------------------ -// genCodeForArrIndex: Generates code to bounds check the index for one dimension of an array reference, -// producing the effective index by subtracting the lower bound. +// CodeGen::genMove2IfNeeded: Conditionally move 2 bytes of a struct to the argument area // // Arguments: -// arrIndex - the node for which we're generating code +// size - The size of bytes remaining to be moved +// intTmpReg - The tmp register to be used for the long value +// srcAddr - The address of the source struct +// offset - The current offset being copied // // Return Value: -// None. +// Returns the number of bytes moved (2 or 0). // - -void CodeGen::genCodeForArrIndex(GenTreeArrIndex* arrIndex) +// Notes: +// This is used in the PutArgStkKindUnroll case, to move any bytes that are +// not an even multiple of 16. +// intTmpReg must be an integer register. +// This is checked by genStoreRegToStackArg. +// +int CodeGen::genMove2IfNeeded(unsigned size, regNumber intTmpReg, GenTree* srcAddr, unsigned offset) { - GenTreePtr arrObj = arrIndex->ArrObj(); - GenTreePtr indexNode = arrIndex->IndexExpr(); - - regNumber arrReg = genConsumeReg(arrObj); - regNumber indexReg = genConsumeReg(indexNode); - regNumber tgtReg = arrIndex->gtRegNum; - - unsigned dim = arrIndex->gtCurrDim; - unsigned rank = arrIndex->gtArrRank; - var_types elemType = arrIndex->gtArrElemType; - - noway_assert(tgtReg != REG_NA); - - // Subtract the lower bound for this dimension. - // TODO-XArch-CQ: make this contained if it's an immediate that fits. - if (tgtReg != indexReg) + if ((size & 2) != 0) { - inst_RV_RV(INS_mov, tgtReg, indexReg, indexNode->TypeGet()); + genCodeForLoadOffset(INS_mov, EA_2BYTE, intTmpReg, srcAddr, offset); + genStoreRegToStackArg(TYP_SHORT, intTmpReg, offset); + return 2; } - getEmitter()->emitIns_R_AR(INS_sub, emitActualTypeSize(TYP_INT), tgtReg, arrReg, - genOffsetOfMDArrayLowerBound(elemType, rank, dim)); - getEmitter()->emitIns_R_AR(INS_cmp, emitActualTypeSize(TYP_INT), tgtReg, arrReg, - genOffsetOfMDArrayDimensionSize(elemType, rank, dim)); - genJumpToThrowHlpBlk(EJ_jae, SCK_RNGCHK_FAIL); - - genProduceReg(arrIndex); + return 0; } //------------------------------------------------------------------------ -// genCodeForArrOffset: Generates code to compute the flattened array offset for -// one dimension of an array reference: -// result = (prevDimOffset * dimSize) + effectiveIndex -// where dimSize is obtained from the arrObj operand +// CodeGen::genMove1IfNeeded: Conditionally move 1 byte of a struct to the argument area // // Arguments: -// arrOffset - the node for which we're generating code +// size - The size of bytes remaining to be moved +// intTmpReg - The tmp register to be used for the long value +// srcAddr - The address of the source struct +// offset - The current offset being copied // // Return Value: -// None. +// Returns the number of bytes moved (1 or 0). // // Notes: -// dimSize and effectiveIndex are always non-negative, the former by design, -// and the latter because it has been normalized to be zero-based. +// This is used in the PutArgStkKindUnroll case, to move any bytes that are +// not an even multiple of 16. +// intTmpReg must be an integer register. +// This is checked by genStoreRegToStackArg. +// +int CodeGen::genMove1IfNeeded(unsigned size, regNumber intTmpReg, GenTree* srcAddr, unsigned offset) +{ -void CodeGen::genCodeForArrOffset(GenTreeArrOffs* arrOffset) + if ((size & 1) != 0) + { + genCodeForLoadOffset(INS_mov, EA_1BYTE, intTmpReg, srcAddr, offset); + genStoreRegToStackArg(TYP_BYTE, intTmpReg, offset); + return 1; + } + return 0; +} + +//---------------------------------------------------------------------------------------------------------------// +// genStructPutArgUnroll: Generates code for passing a struct arg on stack by value using loop unrolling. +// +// Arguments: +// putArgNode - the PutArgStk tree. +// +// Notes: +// m_stkArgVarNum must be set to the base var number, relative to which the by-val struct will be copied to the +// stack. +// +// TODO-Amd64-Unix: Try to share code with copyblk. +// Need refactoring of copyblk before it could be used for putarg_stk. +// The difference for now is that a putarg_stk contains its children, while cpyblk does not. +// This creates differences in code. After some significant refactoring it could be reused. +// +void CodeGen::genStructPutArgUnroll(GenTreePutArgStk* putArgNode) { - GenTreePtr offsetNode = arrOffset->gtOffset; - GenTreePtr indexNode = arrOffset->gtIndex; - GenTreePtr arrObj = arrOffset->gtArrObj; + // We will never call this method for SIMD types, which are stored directly + // in genPutStructArgStk(). + noway_assert(putArgNode->TypeGet() == TYP_STRUCT); - regNumber tgtReg = arrOffset->gtRegNum; + // Make sure we got the arguments of the cpblk operation in the right registers + GenTreePtr dstAddr = putArgNode; + GenTreePtr src = putArgNode->gtOp.gtOp1; - noway_assert(tgtReg != REG_NA); + size_t size = putArgNode->getArgSize(); + assert(size <= CPBLK_UNROLL_LIMIT); - unsigned dim = arrOffset->gtCurrDim; - unsigned rank = arrOffset->gtArrRank; - var_types elemType = arrOffset->gtArrElemType; + emitter* emit = getEmitter(); + unsigned putArgOffset = putArgNode->getArgOffset(); - // We will use a temp register for the offset*scale+effectiveIndex computation. - regMaskTP tmpRegMask = arrOffset->gtRsvdRegs; - regNumber tmpReg = genRegNumFromMask(tmpRegMask); + assert(src->isContained()); - // First, consume the operands in the correct order. - regNumber offsetReg = REG_NA; - if (!offsetNode->IsIntegralConst(0)) + assert(src->gtOper == GT_OBJ); + + if (!src->gtOp.gtOp1->isContained()) { - offsetReg = genConsumeReg(offsetNode); + genConsumeReg(src->gtOp.gtOp1); } - else + + unsigned offset = 0; + + regNumber xmmTmpReg = REG_NA; + regNumber intTmpReg = REG_NA; + regNumber longTmpReg = REG_NA; +#ifdef _TARGET_X86_ + // On x86 we use an XMM register for both 16 and 8-byte chunks, but if it's + // less than 16 bytes, we will just be using pushes + if (size >= 8) { - assert(offsetNode->isContained()); + xmmTmpReg = genRegNumFromMask(putArgNode->gtRsvdRegs & RBM_ALLFLOAT); + longTmpReg = xmmTmpReg; } - regNumber indexReg = genConsumeReg(indexNode); - // Although arrReg may not be used in the constant-index case, if we have generated - // the value into a register, we must consume it, otherwise we will fail to end the - // live range of the gc ptr. - // TODO-CQ: Currently arrObj will always have a register allocated to it. - // We could avoid allocating a register for it, which would be of value if the arrObj - // is an on-stack lclVar. - regNumber arrReg = REG_NA; - if (arrObj->gtHasReg()) + if ((size & 0x7) != 0) + { + intTmpReg = genRegNumFromMask(putArgNode->gtRsvdRegs & RBM_ALLINT); + } +#else // !_TARGET_X86_ + // On x64 we use an XMM register only for 16-byte chunks. + if (size >= XMM_REGSIZE_BYTES) { - arrReg = genConsumeReg(arrObj); + xmmTmpReg = genRegNumFromMask(putArgNode->gtRsvdRegs & RBM_ALLFLOAT); + } + if ((size & 0xf) != 0) + { + intTmpReg = genRegNumFromMask(putArgNode->gtRsvdRegs & RBM_ALLINT); + longTmpReg = intTmpReg; } +#endif // !_TARGET_X86_ - if (!offsetNode->IsIntegralConst(0)) + // If the size of this struct is larger than 16 bytes + // let's use SSE2 to be able to do 16 byte at a time + // loads and stores. + if (size >= XMM_REGSIZE_BYTES) { - // Evaluate tgtReg = offsetReg*dim_size + indexReg. - // tmpReg is used to load dim_size and the result of the multiplication. - // Note that dim_size will never be negative. +#ifdef _TARGET_X86_ + assert(!m_pushStkArg); +#endif // _TARGET_X86_ + assert(putArgNode->gtRsvdRegs != RBM_NONE); + size_t slots = size / XMM_REGSIZE_BYTES; - getEmitter()->emitIns_R_AR(INS_mov, emitActualTypeSize(TYP_INT), tmpReg, arrReg, - genOffsetOfMDArrayDimensionSize(elemType, rank, dim)); - inst_RV_RV(INS_imul, tmpReg, offsetReg); + assert(putArgNode->gtGetOp1()->isContained()); + assert(putArgNode->gtGetOp1()->gtOp.gtOper == GT_OBJ); - if (tmpReg == tgtReg) - { - inst_RV_RV(INS_add, tmpReg, indexReg); - } - else + // TODO: In the below code the load and store instructions are for 16 bytes, but the + // type is EA_8BYTE. The movdqa/u are 16 byte instructions, so it works, but + // this probably needs to be changed. + while (slots-- > 0) { - if (indexReg != tgtReg) - { - inst_RV_RV(INS_mov, tgtReg, indexReg, TYP_I_IMPL); - } - inst_RV_RV(INS_add, tgtReg, tmpReg); + // Load + genCodeForLoadOffset(INS_movdqu, EA_8BYTE, xmmTmpReg, src->gtGetOp1(), offset); + + // Store + genStoreRegToStackArg(TYP_STRUCT, xmmTmpReg, offset); + + offset += XMM_REGSIZE_BYTES; } } - else + + // Fill the remainder (15 bytes or less) if there's one. + if ((size & 0xf) != 0) { - if (indexReg != tgtReg) +#ifdef _TARGET_X86_ + if (m_pushStkArg) + { + // This case is currently supported only for the case where the total size is + // less than XMM_REGSIZE_BYTES. We need to push the remaining chunks in reverse + // order. However, morph has ensured that we have a struct that is an even + // multiple of TARGET_POINTER_SIZE, so we don't need to worry about alignment. + assert(((size & 0xc) == size) && (offset == 0)); + // If we have a 4 byte chunk, load it from either offset 0 or 8, depending on + // whether we've got an 8 byte chunk, and then push it on the stack. + unsigned pushedBytes = genMove4IfNeeded(size, intTmpReg, src->gtOp.gtOp1, size & 0x8); + // Now if we have an 8 byte chunk, load it from offset 0 (it's the first chunk) + // and push it on the stack. + pushedBytes += genMove8IfNeeded(size, longTmpReg, src->gtOp.gtOp1, 0); + } + else +#endif // _TARGET_X86_ { - inst_RV_RV(INS_mov, tgtReg, indexReg, TYP_INT); + offset += genMove8IfNeeded(size, longTmpReg, src->gtOp.gtOp1, offset); + offset += genMove4IfNeeded(size, intTmpReg, src->gtOp.gtOp1, offset); + offset += genMove2IfNeeded(size, intTmpReg, src->gtOp.gtOp1, offset); + offset += genMove1IfNeeded(size, intTmpReg, src->gtOp.gtOp1, offset); + assert(offset == size); } } - genProduceReg(arrOffset); } -// make a temporary indir we can feed to pattern matching routines -// in cases where we don't want to instantiate all the indirs that happen +//------------------------------------------------------------------------ +// genStructPutArgRepMovs: Generates code for passing a struct arg by value on stack using Rep Movs. // -GenTreeIndir CodeGen::indirForm(var_types type, GenTree* base) -{ - GenTreeIndir i(GT_IND, type, base, nullptr); - i.gtRegNum = REG_NA; - // has to be nonnull (because contained nodes can't be the last in block) - // but don't want it to be a valid pointer - i.gtNext = (GenTree*)(-1); - return i; -} - -// make a temporary int we can feed to pattern matching routines -// in cases where we don't want to instantiate +// Arguments: +// putArgNode - the PutArgStk tree. // -GenTreeIntCon CodeGen::intForm(var_types type, ssize_t value) +// Preconditions: +// The size argument of the PutArgStk (for structs) is a constant and is between +// CPBLK_UNROLL_LIMIT and CPBLK_MOVS_LIMIT bytes. +// m_stkArgVarNum must be set to the base var number, relative to which the by-val struct bits will go. +// +void CodeGen::genStructPutArgRepMovs(GenTreePutArgStk* putArgNode) { - GenTreeIntCon i(type, value); - i.gtRegNum = REG_NA; - // has to be nonnull (because contained nodes can't be the last in block) - // but don't want it to be a valid pointer - i.gtNext = (GenTree*)(-1); - return i; + assert(putArgNode->TypeGet() == TYP_STRUCT); + assert(putArgNode->getArgSize() > CPBLK_UNROLL_LIMIT); + + // Make sure we got the arguments of the cpblk operation in the right registers + GenTreePtr dstAddr = putArgNode; + GenTreePtr srcAddr = putArgNode->gtGetOp1(); + + // Validate state. + assert(putArgNode->gtRsvdRegs == (RBM_RDI | RBM_RCX | RBM_RSI)); + assert(srcAddr->isContained()); + + genConsumePutStructArgStk(putArgNode, REG_RDI, REG_RSI, REG_RCX); + instGen(INS_r_movsb); } -instruction CodeGen::genGetInsForOper(genTreeOps oper, var_types type) +//------------------------------------------------------------------------ +// If any Vector3 args are on stack and they are not pass-by-ref, the upper 32bits +// must be cleared to zeroes. The native compiler doesn't clear the upper bits +// and there is no way to know if the caller is native or not. So, the upper +// 32 bits of Vector argument on stack are always cleared to zero. +#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) && defined(FEATURE_SIMD) +void CodeGen::genClearStackVec3ArgUpperBits() { - instruction ins; - - // Operations on SIMD vectors shouldn't come this path - assert(!varTypeIsSIMD(type)); - if (varTypeIsFloating(type)) +#ifdef DEBUG + if (verbose) { - return ins_MathOp(oper, type); + printf("*************** In genClearStackVec3ArgUpperBits()\n"); } +#endif - switch (oper) + assert(compiler->compGeneratingProlog); + + unsigned varNum = 0; + + for (unsigned varNum = 0; varNum < compiler->info.compArgsCount; varNum++) { - case GT_ADD: - ins = INS_add; - break; - case GT_AND: - ins = INS_and; - break; - case GT_LSH: - ins = INS_shl; - break; - case GT_MUL: - ins = INS_imul; - break; - case GT_NEG: - ins = INS_neg; - break; - case GT_NOT: - ins = INS_not; - break; - case GT_OR: - ins = INS_or; - break; - case GT_ROL: - ins = INS_rol; - break; - case GT_ROR: - ins = INS_ror; - break; - case GT_RSH: - ins = INS_sar; - break; - case GT_RSZ: - ins = INS_shr; - break; - case GT_SUB: - ins = INS_sub; - break; - case GT_XOR: - ins = INS_xor; - break; -#if !defined(_TARGET_64BIT_) - case GT_ADD_LO: - ins = INS_add; - break; - case GT_ADD_HI: - ins = INS_adc; - break; - case GT_SUB_LO: - ins = INS_sub; - break; - case GT_SUB_HI: - ins = INS_sbb; - break; -#endif // !defined(_TARGET_64BIT_) - default: - unreached(); - break; + LclVarDsc* varDsc = &(compiler->lvaTable[varNum]); + assert(varDsc->lvIsParam); + + // Does var has simd12 type? + if (varDsc->lvType != TYP_SIMD12) + { + continue; + } + + if (!varDsc->lvIsRegArg) + { + // Clear the upper 32 bits by mov dword ptr [V_ARG_BASE+0xC], 0 + getEmitter()->emitIns_S_I(ins_Store(TYP_INT), EA_4BYTE, varNum, genTypeSize(TYP_FLOAT) * 3, 0); + } + else + { + // Assume that for x64 linux, an argument is fully in registers + // or fully on stack. + regNumber argReg = varDsc->GetOtherArgReg(); + + // Clear the upper 32 bits by two shift instructions. + // argReg = argReg << 96 + getEmitter()->emitIns_R_I(INS_pslldq, emitActualTypeSize(TYP_SIMD12), argReg, 12); + // argReg = argReg >> 96 + getEmitter()->emitIns_R_I(INS_psrldq, emitActualTypeSize(TYP_SIMD12), argReg, 12); + } } - return ins; } +#endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) && defined(FEATURE_SIMD) +#endif // FEATURE_PUT_STRUCT_ARG_STK -//------------------------------------------------------------------------ -// genCodeForShift: Generates the code sequence for a GenTree node that -// represents a bit shift or rotate operation (<<, >>, >>>, rol, ror). -// -// Arguments: -// tree - the bit shift node (that specifies the type of bit shift to perform). -// -// Assumptions: -// a) All GenTrees are register allocated. -// b) The shift-by-amount in tree->gtOp.gtOp2 is either a contained constant or -// it's a register-allocated expression. If it is in a register that is -// not RCX, it will be moved to RCX (so RCX better not be in use!). -// -void CodeGen::genCodeForShift(GenTreePtr tree) +// Generate code for CpObj nodes wich copy structs that have interleaved +// GC pointers. +// This will generate a sequence of movsp instructions for the cases of non-gc members. +// Note that movsp is an alias for movsd on x86 and movsq on x64. +// and calls to the BY_REF_ASSIGN helper otherwise. +void CodeGen::genCodeForCpObj(GenTreeObj* cpObjNode) { - // Only the non-RMW case here. - assert(tree->OperIsShiftOrRotate()); - assert(!tree->gtOp.gtOp1->isContained()); - assert(tree->gtRegNum != REG_NA); + // Make sure we got the arguments of the cpobj operation in the right registers + GenTreePtr dstAddr = cpObjNode->Addr(); + GenTreePtr source = cpObjNode->Data(); + GenTreePtr srcAddr = nullptr; + var_types srcAddrType = TYP_BYREF; + bool sourceIsLocal = false; - genConsumeOperands(tree->AsOp()); + assert(source->isContained()); + if (source->gtOper == GT_IND) + { + srcAddr = source->gtGetOp1(); + assert(!srcAddr->isContained()); + } + else + { + noway_assert(source->IsLocal()); + sourceIsLocal = true; + } - var_types targetType = tree->TypeGet(); - instruction ins = genGetInsForOper(tree->OperGet(), targetType); + bool dstOnStack = dstAddr->OperIsLocalAddr(); - GenTreePtr operand = tree->gtGetOp1(); - regNumber operandReg = operand->gtRegNum; +#ifdef DEBUG + bool isRepMovspUsed = false; - GenTreePtr shiftBy = tree->gtGetOp2(); - if (shiftBy->isContainedIntOrIImmed()) - { - // First, move the operand to the destination register and - // later on perform the shift in-place. - // (LSRA will try to avoid this situation through preferencing.) - if (tree->gtRegNum != operandReg) - { - inst_RV_RV(INS_mov, tree->gtRegNum, operandReg, targetType); - } + assert(!dstAddr->isContained()); - int shiftByValue = (int)shiftBy->AsIntConCommon()->IconValue(); - inst_RV_SH(ins, emitTypeSize(tree), tree->gtRegNum, shiftByValue); - } - else + // If the GenTree node has data about GC pointers, this means we're dealing + // with CpObj, so this requires special logic. + assert(cpObjNode->gtGcPtrCount > 0); + + // MovSp (alias for movsq on x64 and movsd on x86) instruction is used for copying non-gcref fields + // and it needs src = RSI and dst = RDI. + // Either these registers must not contain lclVars, or they must be dying or marked for spill. + // This is because these registers are incremented as we go through the struct. + if (!sourceIsLocal) { - // We must have the number of bits to shift stored in ECX, since we constrained this node to - // sit in ECX. In case this didn't happen, LSRA expects the code generator to move it since it's a single - // register destination requirement. - regNumber shiftReg = shiftBy->gtRegNum; - if (shiftReg != REG_RCX) + GenTree* actualSrcAddr = srcAddr->gtSkipReloadOrCopy(); + GenTree* actualDstAddr = dstAddr->gtSkipReloadOrCopy(); + unsigned srcLclVarNum = BAD_VAR_NUM; + unsigned dstLclVarNum = BAD_VAR_NUM; + bool isSrcAddrLiveOut = false; + bool isDstAddrLiveOut = false; + if (genIsRegCandidateLocal(actualSrcAddr)) { - // Issue the mov to RCX: - inst_RV_RV(INS_mov, REG_RCX, shiftReg, shiftBy->TypeGet()); + srcLclVarNum = actualSrcAddr->AsLclVarCommon()->gtLclNum; + isSrcAddrLiveOut = ((actualSrcAddr->gtFlags & (GTF_VAR_DEATH | GTF_SPILL)) == 0); } - - // The operand to be shifted must not be in ECX - noway_assert(operandReg != REG_RCX); - - if (tree->gtRegNum != operandReg) + if (genIsRegCandidateLocal(actualDstAddr)) { - inst_RV_RV(INS_mov, tree->gtRegNum, operandReg, targetType); + dstLclVarNum = actualDstAddr->AsLclVarCommon()->gtLclNum; + isDstAddrLiveOut = ((actualDstAddr->gtFlags & (GTF_VAR_DEATH | GTF_SPILL)) == 0); } - inst_RV_CL(ins, tree->gtRegNum, targetType); + assert((actualSrcAddr->gtRegNum != REG_RSI) || !isSrcAddrLiveOut || + ((srcLclVarNum == dstLclVarNum) && !isDstAddrLiveOut)); + assert((actualDstAddr->gtRegNum != REG_RDI) || !isDstAddrLiveOut || + ((srcLclVarNum == dstLclVarNum) && !isSrcAddrLiveOut)); + srcAddrType = srcAddr->TypeGet(); } +#endif // DEBUG - genProduceReg(tree); -} - -//------------------------------------------------------------------------ -// genCodeForShiftRMW: Generates the code sequence for a GT_STOREIND GenTree node that -// represents a RMW bit shift or rotate operation (<<, >>, >>>, rol, ror), for example: -// GT_STOREIND( AddressTree, GT_SHL( Ind ( AddressTree ), Operand ) ) -// -// Arguments: -// storeIndNode: the GT_STOREIND node. -// -void CodeGen::genCodeForShiftRMW(GenTreeStoreInd* storeInd) -{ - GenTree* data = storeInd->Data(); - GenTree* addr = storeInd->Addr(); - - assert(data->OperIsShiftOrRotate()); - - // This function only handles the RMW case. - assert(data->gtOp.gtOp1->isContained()); - assert(data->gtOp.gtOp1->isIndir()); - assert(Lowering::IndirsAreEquivalent(data->gtOp.gtOp1, storeInd)); - assert(data->gtRegNum == REG_NA); + // Consume the operands and get them into the right registers. + // They may now contain gc pointers (depending on their type; gcMarkRegPtrVal will "do the right thing"). + genConsumeBlockOp(cpObjNode, REG_RDI, REG_RSI, REG_NA); + gcInfo.gcMarkRegPtrVal(REG_RSI, srcAddrType); + gcInfo.gcMarkRegPtrVal(REG_RDI, dstAddr->TypeGet()); - var_types targetType = data->TypeGet(); - genTreeOps oper = data->OperGet(); - instruction ins = genGetInsForOper(oper, targetType); - emitAttr attr = EA_ATTR(genTypeSize(targetType)); + unsigned slots = cpObjNode->gtSlots; - GenTree* shiftBy = data->gtOp.gtOp2; - if (shiftBy->isContainedIntOrIImmed()) + // If we can prove it's on the stack we don't need to use the write barrier. + if (dstOnStack) { - int shiftByValue = (int)shiftBy->AsIntConCommon()->IconValue(); - ins = genMapShiftInsToShiftByConstantIns(ins, shiftByValue); - if (shiftByValue == 1) + if (slots >= CPOBJ_NONGC_SLOTS_LIMIT) { - // There is no source in this case, as the shift by count is embedded in the instruction opcode itself. - getEmitter()->emitInsRMW(ins, attr, storeInd); +#ifdef DEBUG + // If the destination of the CpObj is on the stack, make sure we allocated + // RCX to emit the movsp (alias for movsd or movsq for 32 and 64 bits respectively). + assert((cpObjNode->gtRsvdRegs & RBM_RCX) != 0); + regNumber tmpReg = REG_RCX; + isRepMovspUsed = true; +#endif // DEBUG + + getEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, REG_RCX, slots); + instGen(INS_r_movsp); } else { - getEmitter()->emitInsRMW(ins, attr, storeInd, shiftBy); + // For small structs, it's better to emit a sequence of movsp than to + // emit a rep movsp instruction. + while (slots > 0) + { + instGen(INS_movsp); + slots--; + } } } else { - // We must have the number of bits to shift stored in ECX, since we constrained this node to - // sit in ECX. In case this didn't happen, LSRA expects the code generator to move it since it's a single - // register destination requirement. - regNumber shiftReg = shiftBy->gtRegNum; - if (shiftReg != REG_RCX) + BYTE* gcPtrs = cpObjNode->gtGcPtrs; + unsigned gcPtrCount = cpObjNode->gtGcPtrCount; + + unsigned i = 0; + while (i < slots) { - // Issue the mov to RCX: - inst_RV_RV(INS_mov, REG_RCX, shiftReg, shiftBy->TypeGet()); + switch (gcPtrs[i]) + { + case TYPE_GC_NONE: + // Let's see if we can use rep movsp instead of a sequence of movsp instructions + // to save cycles and code size. + { + unsigned nonGcSlotCount = 0; + + do + { + nonGcSlotCount++; + i++; + } while (i < slots && gcPtrs[i] == TYPE_GC_NONE); + + // If we have a very small contiguous non-gc region, it's better just to + // emit a sequence of movsp instructions + if (nonGcSlotCount < CPOBJ_NONGC_SLOTS_LIMIT) + { + while (nonGcSlotCount > 0) + { + instGen(INS_movsp); + nonGcSlotCount--; + } + } + else + { +#ifdef DEBUG + // Otherwise, we can save code-size and improve CQ by emitting + // rep movsp (alias for movsd/movsq for x86/x64) + assert((cpObjNode->gtRsvdRegs & RBM_RCX) != 0); + regNumber tmpReg = REG_RCX; + isRepMovspUsed = true; +#endif // DEBUG + getEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, REG_RCX, nonGcSlotCount); + instGen(INS_r_movsp); + } + } + break; + default: + // We have a GC pointer, call the memory barrier. + genEmitHelperCall(CORINFO_HELP_ASSIGN_BYREF, 0, EA_PTRSIZE); + gcPtrCount--; + i++; + } } - // The shiftBy operand is implicit, so call the unary version of emitInsRMW. - getEmitter()->emitInsRMW(ins, attr, storeInd); + assert(gcPtrCount == 0); } + + // Clear the gcInfo for RSI and RDI. + // While we normally update GC info prior to the last instruction that uses them, + // these actually live into the helper call. + gcInfo.gcMarkRegSetNpt(RBM_RSI); + gcInfo.gcMarkRegSetNpt(RBM_RDI); } -void CodeGen::genUnspillRegIfNeeded(GenTree* tree) +// Generate code for a CpBlk node by the means of the VM memcpy helper call +// Preconditions: +// a) The size argument of the CpBlk is not an integer constant +// b) The size argument is a constant but is larger than CPBLK_MOVS_LIMIT bytes. +void CodeGen::genCodeForCpBlk(GenTreeBlk* cpBlkNode) { - regNumber dstReg = tree->gtRegNum; - GenTree* unspillTree = tree; +#ifdef _TARGET_AMD64_ + // Make sure we got the arguments of the cpblk operation in the right registers + unsigned blockSize = cpBlkNode->Size(); + GenTreePtr dstAddr = cpBlkNode->Addr(); + GenTreePtr source = cpBlkNode->Data(); + GenTreePtr srcAddr = nullptr; - if (tree->gtOper == GT_RELOAD) + // Size goes in arg2 + if (blockSize != 0) + { + assert(blockSize >= CPBLK_MOVS_LIMIT); + assert((cpBlkNode->gtRsvdRegs & RBM_ARG_2) != 0); + } + else { - unspillTree = tree->gtOp.gtOp1; + noway_assert(cpBlkNode->gtOper == GT_STORE_DYN_BLK); } - if ((unspillTree->gtFlags & GTF_SPILLED) != 0) + // Source address goes in arg1 + if (source->gtOper == GT_IND) { - if (genIsRegCandidateLocal(unspillTree)) - { - // Reset spilled flag, since we are going to load a local variable from its home location. - unspillTree->gtFlags &= ~GTF_SPILLED; + srcAddr = source->gtGetOp1(); + assert(!srcAddr->isContained()); + } + else + { + noway_assert(source->IsLocal()); + assert((cpBlkNode->gtRsvdRegs & RBM_ARG_1) != 0); + inst_RV_TT(INS_lea, REG_ARG_1, source, 0, EA_BYREF); + } - GenTreeLclVarCommon* lcl = unspillTree->AsLclVarCommon(); - LclVarDsc* varDsc = &compiler->lvaTable[lcl->gtLclNum]; + genConsumeBlockOp(cpBlkNode, REG_ARG_0, REG_ARG_1, REG_ARG_2); - // Load local variable from its home location. - // In most cases the tree type will indicate the correct type to use for the load. - // However, if it is NOT a normalizeOnLoad lclVar (i.e. NOT a small int that always gets - // widened when loaded into a register), and its size is not the same as genActualType of - // the type of the lclVar, then we need to change the type of the tree node when loading. - // This situation happens due to "optimizations" that avoid a cast and - // simply retype the node when using long type lclVar as an int. - // While loading the int in that case would work for this use of the lclVar, if it is - // later used as a long, we will have incorrectly truncated the long. - // In the normalizeOnLoad case ins_Load will return an appropriate sign- or zero- - // extending load. + genEmitHelperCall(CORINFO_HELP_MEMCPY, 0, EA_UNKNOWN); +#else // !_TARGET_AMD64_ + noway_assert(false && "Helper call for CpBlk is not needed."); +#endif // !_TARGET_AMD64_ +} - var_types treeType = unspillTree->TypeGet(); - if (treeType != genActualType(varDsc->lvType) && !varTypeIsGC(treeType) && !varDsc->lvNormalizeOnLoad()) - { - assert(!varTypeIsGC(varDsc)); - var_types spillType = genActualType(varDsc->lvType); - unspillTree->gtType = spillType; - inst_RV_TT(ins_Load(spillType, compiler->isSIMDTypeLocalAligned(lcl->gtLclNum)), dstReg, unspillTree); - unspillTree->gtType = treeType; - } - else - { - inst_RV_TT(ins_Load(treeType, compiler->isSIMDTypeLocalAligned(lcl->gtLclNum)), dstReg, unspillTree); - } +// generate code do a switch statement based on a table of ip-relative offsets +void CodeGen::genTableBasedSwitch(GenTree* treeNode) +{ + genConsumeOperands(treeNode->AsOp()); + regNumber idxReg = treeNode->gtOp.gtOp1->gtRegNum; + regNumber baseReg = treeNode->gtOp.gtOp2->gtRegNum; - unspillTree->SetInReg(); + regNumber tmpReg = genRegNumFromMask(treeNode->gtRsvdRegs); - // TODO-Review: We would like to call: - // genUpdateRegLife(varDsc, /*isBorn*/ true, /*isDying*/ false DEBUGARG(tree)); - // instead of the following code, but this ends up hitting this assert: - // assert((regSet.rsMaskVars & regMask) == 0); - // due to issues with LSRA resolution moves. - // So, just force it for now. This probably indicates a condition that creates a GC hole! - // - // Extra note: I think we really want to call something like gcInfo.gcUpdateForRegVarMove, - // because the variable is not really going live or dead, but that method is somewhat poorly - // factored because it, in turn, updates rsMaskVars which is part of RegSet not GCInfo. - // TODO-Cleanup: This code exists in other CodeGen*.cpp files, and should be moved to CodeGenCommon.cpp. + // load the ip-relative offset (which is relative to start of fgFirstBB) + getEmitter()->emitIns_R_ARX(INS_mov, EA_4BYTE, baseReg, baseReg, idxReg, 4, 0); - // Don't update the variable's location if we are just re-spilling it again. + // add it to the absolute address of fgFirstBB + compiler->fgFirstBB->bbFlags |= BBF_JMP_TARGET; + getEmitter()->emitIns_R_L(INS_lea, EA_PTR_DSP_RELOC, compiler->fgFirstBB, tmpReg); + getEmitter()->emitIns_R_R(INS_add, EA_PTRSIZE, baseReg, tmpReg); + // jmp baseReg + getEmitter()->emitIns_R(INS_i_jmp, emitTypeSize(TYP_I_IMPL), baseReg); +} - if ((unspillTree->gtFlags & GTF_SPILL) == 0) - { - genUpdateVarReg(varDsc, tree); -#ifdef DEBUG - if (VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex)) - { - JITDUMP("\t\t\t\t\t\t\tRemoving V%02u from gcVarPtrSetCur\n", lcl->gtLclNum); - } -#endif // DEBUG - VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex); +// emits the table and an instruction to get the address of the first element +void CodeGen::genJumpTable(GenTree* treeNode) +{ + noway_assert(compiler->compCurBB->bbJumpKind == BBJ_SWITCH); + assert(treeNode->OperGet() == GT_JMPTABLE); -#ifdef DEBUG - if (compiler->verbose) - { - printf("\t\t\t\t\t\t\tV%02u in reg ", lcl->gtLclNum); - varDsc->PrintVarReg(); - printf(" is becoming live "); - compiler->printTreeID(unspillTree); - printf("\n"); - } -#endif // DEBUG + unsigned jumpCount = compiler->compCurBB->bbJumpSwt->bbsCount; + BasicBlock** jumpTable = compiler->compCurBB->bbJumpSwt->bbsDstTab; + unsigned jmpTabOffs; + unsigned jmpTabBase; - regSet.AddMaskVars(genGetRegMask(varDsc)); - } + jmpTabBase = getEmitter()->emitBBTableDataGenBeg(jumpCount, true); - gcInfo.gcMarkRegPtrVal(dstReg, unspillTree->TypeGet()); - } - else if (unspillTree->IsMultiRegCall()) - { - GenTreeCall* call = unspillTree->AsCall(); - ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); - unsigned regCount = retTypeDesc->GetReturnRegCount(); - GenTreeCopyOrReload* reloadTree = nullptr; - if (tree->OperGet() == GT_RELOAD) - { - reloadTree = tree->AsCopyOrReload(); - } + jmpTabOffs = 0; - // In case of multi-reg call node, GTF_SPILLED flag on it indicates that - // one or more of its result regs are spilled. Call node needs to be - // queried to know which specific result regs to be unspilled. - for (unsigned i = 0; i < regCount; ++i) - { - unsigned flags = call->GetRegSpillFlagByIdx(i); - if ((flags & GTF_SPILLED) != 0) - { - var_types dstType = retTypeDesc->GetReturnRegType(i); - regNumber unspillTreeReg = call->GetRegNumByIdx(i); + JITDUMP("\n J_M%03u_DS%02u LABEL DWORD\n", Compiler::s_compMethodsCount, jmpTabBase); - if (reloadTree != nullptr) - { - dstReg = reloadTree->GetRegNumByIdx(i); - if (dstReg == REG_NA) - { - dstReg = unspillTreeReg; - } - } - else - { - dstReg = unspillTreeReg; - } + for (unsigned i = 0; i < jumpCount; i++) + { + BasicBlock* target = *jumpTable++; + noway_assert(target->bbFlags & BBF_JMP_TARGET); - TempDsc* t = regSet.rsUnspillInPlace(call, unspillTreeReg, i); - getEmitter()->emitIns_R_S(ins_Load(dstType), emitActualTypeSize(dstType), dstReg, t->tdTempNum(), - 0); - compiler->tmpRlsTemp(t); - gcInfo.gcMarkRegPtrVal(dstReg, dstType); - } - } + JITDUMP(" DD L_M%03u_BB%02u\n", Compiler::s_compMethodsCount, target->bbNum); + + getEmitter()->emitDataGenData(i, target); + }; + + getEmitter()->emitDataGenEnd(); + + // Access to inline data is 'abstracted' by a special type of static member + // (produced by eeFindJitDataOffs) which the emitter recognizes as being a reference + // to constant data, not a real static field. + getEmitter()->emitIns_R_C(INS_lea, emitTypeSize(TYP_I_IMPL), treeNode->gtRegNum, + compiler->eeFindJitDataOffs(jmpTabBase), 0); + genProduceReg(treeNode); +} + +// generate code for the locked operations: +// GT_LOCKADD, GT_XCHG, GT_XADD +void CodeGen::genLockedInstructions(GenTreeOp* treeNode) +{ + GenTree* data = treeNode->gtOp.gtOp2; + GenTree* addr = treeNode->gtOp.gtOp1; + regNumber targetReg = treeNode->gtRegNum; + regNumber dataReg = data->gtRegNum; + regNumber addrReg = addr->gtRegNum; + instruction ins; + + // The register allocator should have extended the lifetime of the address + // so that it is not used as the target. + noway_assert(addrReg != targetReg); - unspillTree->gtFlags &= ~GTF_SPILLED; - unspillTree->SetInReg(); - } - else - { - TempDsc* t = regSet.rsUnspillInPlace(unspillTree, unspillTree->gtRegNum); - getEmitter()->emitIns_R_S(ins_Load(unspillTree->gtType), emitActualTypeSize(unspillTree->TypeGet()), dstReg, - t->tdTempNum(), 0); - compiler->tmpRlsTemp(t); + // If data is a lclVar that's not a last use, we'd better have allocated a register + // for the result (except in the case of GT_LOCKADD which does not produce a register result). + assert(targetReg != REG_NA || treeNode->OperGet() == GT_LOCKADD || !genIsRegCandidateLocal(data) || + (data->gtFlags & GTF_VAR_DEATH) != 0); - unspillTree->gtFlags &= ~GTF_SPILLED; - unspillTree->SetInReg(); - gcInfo.gcMarkRegPtrVal(dstReg, unspillTree->TypeGet()); - } - } -} + genConsumeOperands(treeNode); + if (targetReg != REG_NA && dataReg != REG_NA && dataReg != targetReg) + { + inst_RV_RV(ins_Copy(data->TypeGet()), targetReg, dataReg); + data->gtRegNum = targetReg; -// Do Liveness update for a subnodes that is being consumed by codegen -// including the logic for reload in case is needed and also takes care -// of locating the value on the desired register. -void CodeGen::genConsumeRegAndCopy(GenTree* tree, regNumber needReg) -{ - if (needReg == REG_NA) + // TODO-XArch-Cleanup: Consider whether it is worth it, for debugging purposes, to restore the + // original gtRegNum on data, after calling emitInsBinary below. + } + switch (treeNode->OperGet()) { - return; + case GT_LOCKADD: + instGen(INS_lock); + ins = INS_add; + break; + case GT_XCHG: + // lock is implied by xchg + ins = INS_xchg; + break; + case GT_XADD: + instGen(INS_lock); + ins = INS_xadd; + break; + default: + unreached(); } - regNumber treeReg = genConsumeReg(tree); - if (treeReg != needReg) + + // all of these nodes implicitly do an indirection on op1 + // so create a temporary node to feed into the pattern matching + GenTreeIndir i = indirForm(data->TypeGet(), addr); + getEmitter()->emitInsBinary(ins, emitTypeSize(data), &i, data); + + if (treeNode->gtRegNum != REG_NA) { - inst_RV_RV(INS_mov, needReg, treeReg, tree->TypeGet()); + genProduceReg(treeNode); } } -void CodeGen::genRegCopy(GenTree* treeNode) +// generate code for BoundsCheck nodes +void CodeGen::genRangeCheck(GenTreePtr oper) { - assert(treeNode->OperGet() == GT_COPY); - GenTree* op1 = treeNode->gtOp.gtOp1; +#ifdef FEATURE_SIMD + noway_assert(oper->OperGet() == GT_ARR_BOUNDS_CHECK || oper->OperGet() == GT_SIMD_CHK); +#else // !FEATURE_SIMD + noway_assert(oper->OperGet() == GT_ARR_BOUNDS_CHECK); +#endif // !FEATURE_SIMD - if (op1->IsMultiRegCall()) - { - genConsumeReg(op1); + GenTreeBoundsChk* bndsChk = oper->AsBoundsChk(); - GenTreeCopyOrReload* copyTree = treeNode->AsCopyOrReload(); - GenTreeCall* call = op1->AsCall(); - ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); - unsigned regCount = retTypeDesc->GetReturnRegCount(); + GenTreePtr arrLen = bndsChk->gtArrLen; + GenTreePtr arrIndex = bndsChk->gtIndex; + GenTreePtr arrRef = nullptr; + int lenOffset = 0; - for (unsigned i = 0; i < regCount; ++i) - { - var_types type = retTypeDesc->GetReturnRegType(i); - regNumber fromReg = call->GetRegNumByIdx(i); - regNumber toReg = copyTree->GetRegNumByIdx(i); + GenTree * src1, *src2; + emitJumpKind jmpKind; - // A Multi-reg GT_COPY node will have valid reg only for those - // positions that corresponding result reg of call node needs - // to be copied. - if (toReg != REG_NA) - { - assert(toReg != fromReg); - inst_RV_RV(ins_Copy(type), toReg, fromReg, type); - } - } + genConsumeRegs(arrLen); + genConsumeRegs(arrIndex); + + if (arrIndex->isContainedIntOrIImmed()) + { + // arrIndex is a contained constant. In this case + // we will generate one of the following + // cmp [mem], immed (if arrLen is a memory op) + // cmp reg, immed (if arrLen is in a reg) + // + // That is arrLen cannot be a contained immed. + assert(!arrLen->isContainedIntOrIImmed()); + + src1 = arrLen; + src2 = arrIndex; + jmpKind = EJ_jbe; } else { - var_types targetType = treeNode->TypeGet(); - regNumber targetReg = treeNode->gtRegNum; - assert(targetReg != REG_NA); - - // Check whether this node and the node from which we're copying the value have - // different register types. This can happen if (currently iff) we have a SIMD - // vector type that fits in an integer register, in which case it is passed as - // an argument, or returned from a call, in an integer register and must be - // copied if it's in an xmm register. - - bool srcFltReg = (varTypeIsFloating(op1) || varTypeIsSIMD(op1)); - bool tgtFltReg = (varTypeIsFloating(treeNode) || varTypeIsSIMD(treeNode)); - if (srcFltReg != tgtFltReg) - { - instruction ins; - regNumber fpReg; - regNumber intReg; - if (tgtFltReg) - { - ins = ins_CopyIntToFloat(op1->TypeGet(), treeNode->TypeGet()); - fpReg = targetReg; - intReg = op1->gtRegNum; - } - else - { - ins = ins_CopyFloatToInt(op1->TypeGet(), treeNode->TypeGet()); - intReg = targetReg; - fpReg = op1->gtRegNum; - } - inst_RV_RV(ins, fpReg, intReg, targetType); - } - else - { - inst_RV_RV(ins_Copy(targetType), targetReg, genConsumeReg(op1), targetType); - } + // arrIndex could either be a contained memory op or a reg + // In this case we will generate one of the following + // cmp [mem], immed (if arrLen is a constant) + // cmp [mem], reg (if arrLen is in a reg) + // cmp reg, immed (if arrIndex is in a reg) + // cmp reg1, reg2 (if arraIndex is in reg1) + // cmp reg, [mem] (if arrLen is a memory op) + // + // That is only one of arrIndex or arrLen can be a memory op. + assert(!arrIndex->isContainedMemoryOp() || !arrLen->isContainedMemoryOp()); - if (op1->IsLocal()) - { - // The lclVar will never be a def. - // If it is a last use, the lclVar will be killed by genConsumeReg(), as usual, and genProduceReg will - // appropriately set the gcInfo for the copied value. - // If not, there are two cases we need to handle: - // - If this is a TEMPORARY copy (indicated by the GTF_VAR_DEATH flag) the variable - // will remain live in its original register. - // genProduceReg() will appropriately set the gcInfo for the copied value, - // and genConsumeReg will reset it. - // - Otherwise, we need to update register info for the lclVar. + src1 = arrIndex; + src2 = arrLen; + jmpKind = EJ_jae; + } - GenTreeLclVarCommon* lcl = op1->AsLclVarCommon(); - assert((lcl->gtFlags & GTF_VAR_DEF) == 0); + var_types bndsChkType = src2->TypeGet(); +#if DEBUG + // Bounds checks can only be 32 or 64 bit sized comparisons. + assert(bndsChkType == TYP_INT || bndsChkType == TYP_LONG); - if ((lcl->gtFlags & GTF_VAR_DEATH) == 0 && (treeNode->gtFlags & GTF_VAR_DEATH) == 0) - { - LclVarDsc* varDsc = &compiler->lvaTable[lcl->gtLclNum]; + // The type of the bounds check should always wide enough to compare against the index. + assert(emitTypeSize(bndsChkType) >= emitTypeSize(src1->TypeGet())); +#endif // DEBUG - // If we didn't just spill it (in genConsumeReg, above), then update the register info - if (varDsc->lvRegNum != REG_STK) - { - // The old location is dying - genUpdateRegLife(varDsc, /*isBorn*/ false, /*isDying*/ true DEBUGARG(op1)); + getEmitter()->emitInsBinary(INS_cmp, emitTypeSize(bndsChkType), src1, src2); + genJumpToThrowHlpBlk(jmpKind, bndsChk->gtThrowKind, bndsChk->gtIndRngFailBB); +} - gcInfo.gcMarkRegSetNpt(genRegMask(op1->gtRegNum)); +//------------------------------------------------------------------------ +// genOffsetOfMDArrayLowerBound: Returns the offset from the Array object to the +// lower bound for the given dimension. +// +// Arguments: +// elemType - the element type of the array +// rank - the rank of the array +// dimension - the dimension for which the lower bound offset will be returned. +// +// Return Value: +// The offset. - genUpdateVarReg(varDsc, treeNode); +unsigned CodeGen::genOffsetOfMDArrayLowerBound(var_types elemType, unsigned rank, unsigned dimension) +{ + // Note that the lower bound and length fields of the Array object are always TYP_INT, even on 64-bit targets. + return compiler->eeGetArrayDataOffset(elemType) + genTypeSize(TYP_INT) * (dimension + rank); +} - // The new location is going live - genUpdateRegLife(varDsc, /*isBorn*/ true, /*isDying*/ false DEBUGARG(treeNode)); - } - } - } - } +//------------------------------------------------------------------------ +// genOffsetOfMDArrayLength: Returns the offset from the Array object to the +// size for the given dimension. +// +// Arguments: +// elemType - the element type of the array +// rank - the rank of the array +// dimension - the dimension for which the lower bound offset will be returned. +// +// Return Value: +// The offset. - genProduceReg(treeNode); +unsigned CodeGen::genOffsetOfMDArrayDimensionSize(var_types elemType, unsigned rank, unsigned dimension) +{ + // Note that the lower bound and length fields of the Array object are always TYP_INT, even on 64-bit targets. + return compiler->eeGetArrayDataOffset(elemType) + genTypeSize(TYP_INT) * dimension; } -// Check that registers are consumed in the right order for the current node being generated. -#ifdef DEBUG -void CodeGen::genCheckConsumeNode(GenTree* treeNode) +//------------------------------------------------------------------------ +// genCodeForArrIndex: Generates code to bounds check the index for one dimension of an array reference, +// producing the effective index by subtracting the lower bound. +// +// Arguments: +// arrIndex - the node for which we're generating code +// +// Return Value: +// None. +// + +void CodeGen::genCodeForArrIndex(GenTreeArrIndex* arrIndex) { - // GT_PUTARG_REG is consumed out of order. - if (treeNode->gtSeqNum != 0 && treeNode->OperGet() != GT_PUTARG_REG) - { - if (lastConsumedNode != nullptr) - { - if (treeNode == lastConsumedNode) - { - if (verbose) - { - printf("Node was consumed twice:\n "); - compiler->gtDispTree(treeNode, nullptr, nullptr, true); - } - } - else - { - if (verbose && (lastConsumedNode->gtSeqNum > treeNode->gtSeqNum)) - { - printf("Nodes were consumed out-of-order:\n"); - compiler->gtDispTree(lastConsumedNode, nullptr, nullptr, true); - compiler->gtDispTree(treeNode, nullptr, nullptr, true); - } - // assert(lastConsumedNode->gtSeqNum < treeNode->gtSeqNum); - } - } - lastConsumedNode = treeNode; + GenTreePtr arrObj = arrIndex->ArrObj(); + GenTreePtr indexNode = arrIndex->IndexExpr(); + + regNumber arrReg = genConsumeReg(arrObj); + regNumber indexReg = genConsumeReg(indexNode); + regNumber tgtReg = arrIndex->gtRegNum; + + unsigned dim = arrIndex->gtCurrDim; + unsigned rank = arrIndex->gtArrRank; + var_types elemType = arrIndex->gtArrElemType; + + noway_assert(tgtReg != REG_NA); + + // Subtract the lower bound for this dimension. + // TODO-XArch-CQ: make this contained if it's an immediate that fits. + if (tgtReg != indexReg) + { + inst_RV_RV(INS_mov, tgtReg, indexReg, indexNode->TypeGet()); } + getEmitter()->emitIns_R_AR(INS_sub, emitActualTypeSize(TYP_INT), tgtReg, arrReg, + genOffsetOfMDArrayLowerBound(elemType, rank, dim)); + getEmitter()->emitIns_R_AR(INS_cmp, emitActualTypeSize(TYP_INT), tgtReg, arrReg, + genOffsetOfMDArrayDimensionSize(elemType, rank, dim)); + genJumpToThrowHlpBlk(EJ_jae, SCK_RNGCHK_FAIL); + + genProduceReg(arrIndex); } -#endif // DEBUG -//-------------------------------------------------------------------- -// genConsumeReg: Do liveness update for a subnode that is being -// consumed by codegen. +//------------------------------------------------------------------------ +// genCodeForArrOffset: Generates code to compute the flattened array offset for +// one dimension of an array reference: +// result = (prevDimOffset * dimSize) + effectiveIndex +// where dimSize is obtained from the arrObj operand // // Arguments: -// tree - GenTree node +// arrOffset - the node for which we're generating code // // Return Value: -// Returns the reg number of tree. -// In case of multi-reg call node returns the first reg number -// of the multi-reg return. -regNumber CodeGen::genConsumeReg(GenTree* tree) +// None. +// +// Notes: +// dimSize and effectiveIndex are always non-negative, the former by design, +// and the latter because it has been normalized to be zero-based. + +void CodeGen::genCodeForArrOffset(GenTreeArrOffs* arrOffset) { - if (tree->OperGet() == GT_COPY) + GenTreePtr offsetNode = arrOffset->gtOffset; + GenTreePtr indexNode = arrOffset->gtIndex; + GenTreePtr arrObj = arrOffset->gtArrObj; + + regNumber tgtReg = arrOffset->gtRegNum; + assert(tgtReg != REG_NA); + + unsigned dim = arrOffset->gtCurrDim; + unsigned rank = arrOffset->gtArrRank; + var_types elemType = arrOffset->gtArrElemType; + + // First, consume the operands in the correct order. + regNumber offsetReg = REG_NA; + regNumber tmpReg = REG_NA; + if (!offsetNode->IsIntegralConst(0)) { - genRegCopy(tree); - } + offsetReg = genConsumeReg(offsetNode); - // Handle the case where we have a lclVar that needs to be copied before use (i.e. because it - // interferes with one of the other sources (or the target, if it's a "delayed use" register)). - // TODO-Cleanup: This is a special copyReg case in LSRA - consider eliminating these and - // always using GT_COPY to make the lclVar location explicit. - // Note that we have to do this before calling genUpdateLife because otherwise if we spill it - // the lvRegNum will be set to REG_STK and we will lose track of what register currently holds - // the lclVar (normally when a lclVar is spilled it is then used from its former register - // location, which matches the gtRegNum on the node). - // (Note that it doesn't matter if we call this before or after genUnspillRegIfNeeded - // because if it's on the stack it will always get reloaded into tree->gtRegNum). - if (genIsRegCandidateLocal(tree)) + // We will use a temp register for the offset*scale+effectiveIndex computation. + regMaskTP tmpRegMask = arrOffset->gtRsvdRegs; + tmpReg = genRegNumFromMask(tmpRegMask); + } + else { - GenTreeLclVarCommon* lcl = tree->AsLclVarCommon(); - LclVarDsc* varDsc = &compiler->lvaTable[lcl->GetLclNum()]; - if (varDsc->lvRegNum != REG_STK && varDsc->lvRegNum != tree->gtRegNum) - { - inst_RV_RV(INS_mov, tree->gtRegNum, varDsc->lvRegNum); - } + assert(offsetNode->isContained()); + } + regNumber indexReg = genConsumeReg(indexNode); + // Although arrReg may not be used in the constant-index case, if we have generated + // the value into a register, we must consume it, otherwise we will fail to end the + // live range of the gc ptr. + // TODO-CQ: Currently arrObj will always have a register allocated to it. + // We could avoid allocating a register for it, which would be of value if the arrObj + // is an on-stack lclVar. + regNumber arrReg = REG_NA; + if (arrObj->gtHasReg()) + { + arrReg = genConsumeReg(arrObj); } - genUnspillRegIfNeeded(tree); - - // genUpdateLife() will also spill local var if marked as GTF_SPILL by calling CodeGen::genSpillVar - genUpdateLife(tree); - - assert(tree->gtHasReg()); + if (!offsetNode->IsIntegralConst(0)) + { + assert(tmpReg != REG_NA); + assert(arrReg != REG_NA); - // there are three cases where consuming a reg means clearing the bit in the live mask - // 1. it was not produced by a local - // 2. it was produced by a local that is going dead - // 3. it was produced by a local that does not live in that reg (like one allocated on the stack) + // Evaluate tgtReg = offsetReg*dim_size + indexReg. + // tmpReg is used to load dim_size and the result of the multiplication. + // Note that dim_size will never be negative. - if (genIsRegCandidateLocal(tree)) - { - GenTreeLclVarCommon* lcl = tree->AsLclVarCommon(); - LclVarDsc* varDsc = &compiler->lvaTable[lcl->GetLclNum()]; - assert(varDsc->lvLRACandidate); + getEmitter()->emitIns_R_AR(INS_mov, emitActualTypeSize(TYP_INT), tmpReg, arrReg, + genOffsetOfMDArrayDimensionSize(elemType, rank, dim)); + inst_RV_RV(INS_imul, tmpReg, offsetReg); - if ((tree->gtFlags & GTF_VAR_DEATH) != 0) + if (tmpReg == tgtReg) { - gcInfo.gcMarkRegSetNpt(genRegMask(varDsc->lvRegNum)); + inst_RV_RV(INS_add, tmpReg, indexReg); } - else if (varDsc->lvRegNum == REG_STK) + else { - // We have loaded this into a register only temporarily - gcInfo.gcMarkRegSetNpt(genRegMask(tree->gtRegNum)); + if (indexReg != tgtReg) + { + inst_RV_RV(INS_mov, tgtReg, indexReg, TYP_I_IMPL); + } + inst_RV_RV(INS_add, tgtReg, tmpReg); } } else { - gcInfo.gcMarkRegSetNpt(tree->gtGetRegMask()); + if (indexReg != tgtReg) + { + inst_RV_RV(INS_mov, tgtReg, indexReg, TYP_INT); + } } - - genCheckConsumeNode(tree); - return tree->gtRegNum; + genProduceReg(arrOffset); } -// Do liveness update for an address tree: one of GT_LEA, GT_LCL_VAR, or GT_CNS_INT (for call indirect). -void CodeGen::genConsumeAddress(GenTree* addr) +// make a temporary indir we can feed to pattern matching routines +// in cases where we don't want to instantiate all the indirs that happen +// +GenTreeIndir CodeGen::indirForm(var_types type, GenTree* base) { - if (!addr->isContained()) - { - genConsumeReg(addr); - } - else if (addr->OperGet() == GT_LEA) - { - genConsumeAddrMode(addr->AsAddrMode()); - } + GenTreeIndir i(GT_IND, type, base, nullptr); + i.gtRegNum = REG_NA; + // has to be nonnull (because contained nodes can't be the last in block) + // but don't want it to be a valid pointer + i.gtNext = (GenTree*)(-1); + return i; } -// do liveness update for a subnode that is being consumed by codegen -void CodeGen::genConsumeAddrMode(GenTreeAddrMode* addr) +// make a temporary int we can feed to pattern matching routines +// in cases where we don't want to instantiate +// +GenTreeIntCon CodeGen::intForm(var_types type, ssize_t value) { - genConsumeOperands(addr); + GenTreeIntCon i(type, value); + i.gtRegNum = REG_NA; + // has to be nonnull (because contained nodes can't be the last in block) + // but don't want it to be a valid pointer + i.gtNext = (GenTree*)(-1); + return i; } -void CodeGen::genConsumeRegs(GenTree* tree) +instruction CodeGen::genGetInsForOper(genTreeOps oper, var_types type) { -#if !defined(_TARGET_64BIT_) - if (tree->OperGet() == GT_LONG) - { - genConsumeRegs(tree->gtGetOp1()); - genConsumeRegs(tree->gtGetOp2()); - return; - } -#endif // !defined(_TARGET_64BIT_) + instruction ins; - if (tree->isContained()) + // Operations on SIMD vectors shouldn't come this path + assert(!varTypeIsSIMD(type)); + if (varTypeIsFloating(type)) { - if (tree->isContainedSpillTemp()) - { - // spill temps are un-tracked and hence no need to update life - } - else if (tree->isIndir()) - { - genConsumeAddress(tree->AsIndir()->Addr()); - } - else if (tree->OperGet() == GT_AND) - { - // This is the special contained GT_AND that we created in Lowering::LowerCmp() - // Now we need to consume the operands of the GT_AND node. - genConsumeOperands(tree->AsOp()); - } - else if (tree->OperGet() == GT_LCL_VAR) - { - // A contained lcl var must be living on stack and marked as reg optional. - unsigned varNum = tree->AsLclVarCommon()->GetLclNum(); - LclVarDsc* varDsc = compiler->lvaTable + varNum; - - noway_assert(varDsc->lvRegNum == REG_STK); - noway_assert(tree->IsRegOptional()); - - // Update the life of reg optional lcl var. - genUpdateLife(tree); - } - else - { - assert(tree->OperIsLeaf()); - } + return ins_MathOp(oper, type); } - else + + switch (oper) { - genConsumeReg(tree); + case GT_ADD: + ins = INS_add; + break; + case GT_AND: + ins = INS_and; + break; + case GT_LSH: + ins = INS_shl; + break; + case GT_MUL: + ins = INS_imul; + break; + case GT_NEG: + ins = INS_neg; + break; + case GT_NOT: + ins = INS_not; + break; + case GT_OR: + ins = INS_or; + break; + case GT_ROL: + ins = INS_rol; + break; + case GT_ROR: + ins = INS_ror; + break; + case GT_RSH: + ins = INS_sar; + break; + case GT_RSZ: + ins = INS_shr; + break; + case GT_SUB: + ins = INS_sub; + break; + case GT_XOR: + ins = INS_xor; + break; +#if !defined(_TARGET_64BIT_) + case GT_ADD_LO: + ins = INS_add; + break; + case GT_ADD_HI: + ins = INS_adc; + break; + case GT_SUB_LO: + ins = INS_sub; + break; + case GT_SUB_HI: + ins = INS_sbb; + break; + case GT_LSH_HI: + ins = INS_shld; + break; + case GT_RSH_LO: + ins = INS_shrd; + break; +#endif // !defined(_TARGET_64BIT_) + default: + unreached(); + break; } + return ins; } //------------------------------------------------------------------------ -// genConsumeOperands: Do liveness update for the operands of a unary or binary tree +// genCodeForShift: Generates the code sequence for a GenTree node that +// represents a bit shift or rotate operation (<<, >>, >>>, rol, ror). // // Arguments: -// tree - the GenTreeOp whose operands will have their liveness updated. +// tree - the bit shift node (that specifies the type of bit shift to perform). // -// Return Value: -// None. +// Assumptions: +// a) All GenTrees are register allocated. +// b) The shift-by-amount in tree->gtOp.gtOp2 is either a contained constant or +// it's a register-allocated expression. If it is in a register that is +// not RCX, it will be moved to RCX (so RCX better not be in use!). // -// Notes: -// Note that this logic is localized here because we must do the liveness update in -// the correct execution order. This is important because we may have two operands -// that involve the same lclVar, and if one is marked "lastUse" we must handle it -// after the first. - -void CodeGen::genConsumeOperands(GenTreeOp* tree) +void CodeGen::genCodeForShift(GenTreePtr tree) { - GenTree* firstOp = tree->gtOp1; - GenTree* secondOp = tree->gtOp2; - if ((tree->gtFlags & GTF_REVERSE_OPS) != 0) - { - assert(secondOp != nullptr); - firstOp = secondOp; - secondOp = tree->gtOp1; - } - if (firstOp != nullptr) + // Only the non-RMW case here. + assert(tree->OperIsShiftOrRotate()); + assert(!tree->gtOp.gtOp1->isContained()); + assert(tree->gtRegNum != REG_NA); + + genConsumeOperands(tree->AsOp()); + + var_types targetType = tree->TypeGet(); + instruction ins = genGetInsForOper(tree->OperGet(), targetType); + + GenTreePtr operand = tree->gtGetOp1(); + regNumber operandReg = operand->gtRegNum; + + GenTreePtr shiftBy = tree->gtGetOp2(); + + if (shiftBy->isContainedIntOrIImmed()) { - genConsumeRegs(firstOp); + // First, move the operand to the destination register and + // later on perform the shift in-place. + // (LSRA will try to avoid this situation through preferencing.) + if (tree->gtRegNum != operandReg) + { + inst_RV_RV(INS_mov, tree->gtRegNum, operandReg, targetType); + } + + int shiftByValue = (int)shiftBy->AsIntConCommon()->IconValue(); + inst_RV_SH(ins, emitTypeSize(tree), tree->gtRegNum, shiftByValue); } - if (secondOp != nullptr) + else { - genConsumeRegs(secondOp); + // We must have the number of bits to shift stored in ECX, since we constrained this node to + // sit in ECX. In case this didn't happen, LSRA expects the code generator to move it since it's a single + // register destination requirement. + genCopyRegIfNeeded(shiftBy, REG_RCX); + + // The operand to be shifted must not be in ECX + noway_assert(operandReg != REG_RCX); + + if (tree->gtRegNum != operandReg) + { + inst_RV_RV(INS_mov, tree->gtRegNum, operandReg, targetType); + } + inst_RV_CL(ins, tree->gtRegNum, targetType); } + + genProduceReg(tree); } -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING +#ifdef _TARGET_X86_ //------------------------------------------------------------------------ -// genConsumePutStructArgStk: Do liveness update for the operands of a PutArgStk node. -// Also loads in the right register the addresses of the -// src/dst for rep mov operation. +// genCodeForShiftLong: Generates the code sequence for a GenTree node that +// represents a three operand bit shift or rotate operation (<>Lo). // // Arguments: -// putArgNode - the PUTARG_STK tree. -// dstReg - the dstReg for the rep move operation. -// srcReg - the srcReg for the rep move operation. -// sizeReg - the sizeReg for the rep move operation. -// baseVarNum - the varnum for the local used for placing the "by-value" args on the stack. +// tree - the bit shift node (that specifies the type of bit shift to perform). // -// Return Value: -// None. +// Assumptions: +// a) All GenTrees are register allocated. +// b) The shift-by-amount in tree->gtOp.gtOp2 is a contained constant // -// Note: sizeReg can be REG_NA when this function is used to consume the dstReg and srcReg -// for copying on the stack a struct with references. -// The source address/offset is determined from the address on the GT_OBJ node, while -// the destination address is the address contained in 'baseVarNum' plus the offset -// provided in the 'putArgNode'. - -void CodeGen::genConsumePutStructArgStk( - GenTreePutArgStk* putArgNode, regNumber dstReg, regNumber srcReg, regNumber sizeReg, unsigned baseVarNum) +void CodeGen::genCodeForShiftLong(GenTreePtr tree) { - assert(varTypeIsStruct(putArgNode)); - assert(baseVarNum != BAD_VAR_NUM); + // Only the non-RMW case here. + genTreeOps oper = tree->OperGet(); + assert(oper == GT_LSH_HI || oper == GT_RSH_LO); - // The putArgNode children are always contained. We should not consume any registers. - assert(putArgNode->gtGetOp1()->isContained()); + GenTree* operand = tree->gtOp.gtOp1; + assert(operand->OperGet() == GT_LONG); + assert(!operand->gtOp.gtOp1->isContained()); + assert(!operand->gtOp.gtOp2->isContained()); - GenTree* dstAddr = putArgNode; + GenTree* operandLo = operand->gtGetOp1(); + GenTree* operandHi = operand->gtGetOp2(); - // Get the source address. - GenTree* src = putArgNode->gtGetOp1(); - assert((src->gtOper == GT_OBJ) || ((src->gtOper == GT_IND && varTypeIsSIMD(src)))); - GenTree* srcAddr = src->gtGetOp1(); + regNumber regLo = operandLo->gtRegNum; + regNumber regHi = operandHi->gtRegNum; - size_t size = putArgNode->getArgSize(); + genConsumeOperands(tree->AsOp()); - assert(dstReg != REG_NA); - assert(srcReg != REG_NA); + var_types targetType = tree->TypeGet(); + instruction ins = genGetInsForOper(oper, targetType); - // Consume the registers only if they are not contained or set to REG_NA. - if (srcAddr->gtRegNum != REG_NA) - { - genConsumeReg(srcAddr); - } + GenTreePtr shiftBy = tree->gtGetOp2(); + + assert(shiftBy->isContainedIntOrIImmed()); + + unsigned int count = shiftBy->AsIntConCommon()->IconValue(); - // If the op1 is already in the dstReg - nothing to do. - // Otherwise load the op1 (GT_ADDR) into the dstReg to copy the struct on the stack by value. - if (dstAddr->gtRegNum != dstReg) + regNumber regResult = (oper == GT_LSH_HI) ? regHi : regLo; + + if (regResult != tree->gtRegNum) { - // Generate LEA instruction to load the stack of the outgoing var + SlotNum offset (or the incoming arg area - // for tail calls) in RDI. - // Destination is always local (on the stack) - use EA_PTRSIZE. - getEmitter()->emitIns_R_S(INS_lea, EA_PTRSIZE, dstReg, baseVarNum, putArgNode->getArgOffset()); + inst_RV_RV(INS_mov, tree->gtRegNum, regResult, targetType); } - if (srcAddr->gtRegNum != srcReg) + if (oper == GT_LSH_HI) { - if (srcAddr->OperIsLocalAddr()) - { - // The OperLocalAddr is always contained. - assert(srcAddr->isContained()); - GenTreeLclVarCommon* lclNode = srcAddr->AsLclVarCommon(); - - // Generate LEA instruction to load the LclVar address in RSI. - // Source is known to be on the stack. Use EA_PTRSIZE. - unsigned int offset = 0; - if (srcAddr->OperGet() == GT_LCL_FLD_ADDR) - { - offset = srcAddr->AsLclFld()->gtLclOffs; - } - getEmitter()->emitIns_R_S(INS_lea, EA_PTRSIZE, srcReg, lclNode->gtLclNum, offset); - } - else - { - assert(srcAddr->gtRegNum != REG_NA); - // Source is not known to be on the stack. Use EA_BYREF. - getEmitter()->emitIns_R_R(INS_mov, EA_BYREF, srcReg, srcAddr->gtRegNum); - } + inst_RV_RV_IV(ins, emitTypeSize(targetType), tree->gtRegNum, regLo, count); } - - if (sizeReg != REG_NA) + else { - inst_RV_IV(INS_mov, sizeReg, size, EA_8BYTE); + assert(oper == GT_RSH_LO); + inst_RV_RV_IV(ins, emitTypeSize(targetType), tree->gtRegNum, regHi, count); } + + genProduceReg(tree); } -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING +#endif //------------------------------------------------------------------------ -// genConsumeBlockSize: Ensure that the block size is in the given register +// genCodeForShiftRMW: Generates the code sequence for a GT_STOREIND GenTree node that +// represents a RMW bit shift or rotate operation (<<, >>, >>>, rol, ror), for example: +// GT_STOREIND( AddressTree, GT_SHL( Ind ( AddressTree ), Operand ) ) // // Arguments: -// blkNode - The block node -// sizeReg - The register into which the block's size should go +// storeIndNode: the GT_STOREIND node. // - -void CodeGen::genConsumeBlockSize(GenTreeBlk* blkNode, regNumber sizeReg) +void CodeGen::genCodeForShiftRMW(GenTreeStoreInd* storeInd) { - if (sizeReg != REG_NA) - { - unsigned blockSize = blkNode->Size(); - if (blockSize != 0) - { - assert(blkNode->gtRsvdRegs == genRegMask(sizeReg)); - genSetRegToIcon(sizeReg, blockSize); - } - else - { - noway_assert(blkNode->gtOper == GT_STORE_DYN_BLK); - genConsumeReg(blkNode->AsDynBlk()->gtDynamicSize); - } - } -} + GenTree* data = storeInd->Data(); + GenTree* addr = storeInd->Addr(); -//------------------------------------------------------------------------ -// genConsumeBlockDst: Ensure that the block destination address is in its -// allocated register. -// Arguments: -// blkNode - The block node -// + assert(data->OperIsShiftOrRotate()); -void CodeGen::genConsumeBlockDst(GenTreeBlk* blkNode) -{ - GenTree* dstAddr = blkNode->Addr(); - genConsumeReg(dstAddr); -} + // This function only handles the RMW case. + assert(data->gtOp.gtOp1->isContained()); + assert(data->gtOp.gtOp1->isIndir()); + assert(Lowering::IndirsAreEquivalent(data->gtOp.gtOp1, storeInd)); + assert(data->gtRegNum == REG_NA); -//------------------------------------------------------------------------ -// genConsumeBlockSrc: Ensure that the block source address is in its -// allocated register if it is non-local. -// Arguments: -// blkNode - The block node -// -// Return Value: -// Returns the source address node, if it is non-local, -// and nullptr otherwise. + var_types targetType = data->TypeGet(); + genTreeOps oper = data->OperGet(); + instruction ins = genGetInsForOper(oper, targetType); + emitAttr attr = EA_ATTR(genTypeSize(targetType)); -GenTree* CodeGen::genConsumeBlockSrc(GenTreeBlk* blkNode) -{ - GenTree* src = blkNode->Data(); - if (blkNode->OperIsCopyBlkOp()) + GenTree* shiftBy = data->gtOp.gtOp2; + if (shiftBy->isContainedIntOrIImmed()) { - // For a CopyBlk we need the address of the source. - if (src->OperGet() == GT_IND) + int shiftByValue = (int)shiftBy->AsIntConCommon()->IconValue(); + ins = genMapShiftInsToShiftByConstantIns(ins, shiftByValue); + if (shiftByValue == 1) { - src = src->gtOp.gtOp1; + // There is no source in this case, as the shift by count is embedded in the instruction opcode itself. + getEmitter()->emitInsRMW(ins, attr, storeInd); } else { - // This must be a local. - // For this case, there is no source address register, as it is a - // stack-based address. - assert(src->OperIsLocal()); - return nullptr; + getEmitter()->emitInsRMW(ins, attr, storeInd, shiftBy); } } - genConsumeReg(src); - return src; -} + else + { + // We must have the number of bits to shift stored in ECX, since we constrained this node to + // sit in ECX. In case this didn't happen, LSRA expects the code generator to move it since it's a single + // register destination requirement. + regNumber shiftReg = shiftBy->gtRegNum; + genCopyRegIfNeeded(shiftBy, REG_RCX); -//------------------------------------------------------------------------ -// genConsumeBlockOp: Ensure that the block's operands are enregistered -// as needed. -// Arguments: -// blkNode - The block node -// -// Notes: -// This ensures that the operands are consumed in the proper order to -// obey liveness modeling. + // The shiftBy operand is implicit, so call the unary version of emitInsRMW. + getEmitter()->emitInsRMW(ins, attr, storeInd); + } +} -void CodeGen::genConsumeBlockOp(GenTreeBlk* blkNode, regNumber dstReg, regNumber srcReg, regNumber sizeReg) +void CodeGen::genRegCopy(GenTree* treeNode) { - // We have to consume the registers, and perform any copies, in the actual execution order. - // The nominal order is: dst, src, size. However this may have been changed - // with reverse flags on the blkNode and the setting of gtEvalSizeFirst in the case of a dynamic - // block size. - // Note that the register allocator ensures that the registers ON THE NODES will not interfere - // with one another if consumed (i.e. reloaded or moved to their ASSIGNED reg) in execution order. - // Further, it ensures that they will not interfere with one another if they are then copied - // to the REQUIRED register (if a fixed register requirement) in execution order. This requires, - // then, that we first consume all the operands, then do any necessary moves. - - GenTree* dstAddr = blkNode->Addr(); - GenTree* src = nullptr; - unsigned blockSize = blkNode->Size(); - GenTree* size = nullptr; - bool evalSizeFirst = true; + assert(treeNode->OperGet() == GT_COPY); + GenTree* op1 = treeNode->gtOp.gtOp1; - if (blkNode->OperGet() == GT_STORE_DYN_BLK) + if (op1->IsMultiRegCall()) { - evalSizeFirst = blkNode->AsDynBlk()->gtEvalSizeFirst; - size = blkNode->AsDynBlk()->gtDynamicSize; - } + genConsumeReg(op1); - // First, consusme all the sources in order - if (evalSizeFirst) - { - genConsumeBlockSize(blkNode, sizeReg); - } - if (blkNode->IsReverseOp()) - { - src = genConsumeBlockSrc(blkNode); - genConsumeBlockDst(blkNode); - } - else - { - genConsumeBlockDst(blkNode); - src = genConsumeBlockSrc(blkNode); - } - if (!evalSizeFirst) - { - genConsumeBlockSize(blkNode, sizeReg); - } - // Next, perform any necessary moves. - if (evalSizeFirst && (size != nullptr) && (size->gtRegNum != sizeReg)) - { - inst_RV_RV(INS_mov, sizeReg, size->gtRegNum, size->TypeGet()); - } - if (blkNode->IsReverseOp()) - { - if ((src != nullptr) && (src->gtRegNum != srcReg)) - { - inst_RV_RV(INS_mov, srcReg, src->gtRegNum, src->TypeGet()); - } - if (dstAddr->gtRegNum != dstReg) + GenTreeCopyOrReload* copyTree = treeNode->AsCopyOrReload(); + GenTreeCall* call = op1->AsCall(); + ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); + unsigned regCount = retTypeDesc->GetReturnRegCount(); + + for (unsigned i = 0; i < regCount; ++i) { - inst_RV_RV(INS_mov, dstReg, dstAddr->gtRegNum, dstAddr->TypeGet()); + var_types type = retTypeDesc->GetReturnRegType(i); + regNumber fromReg = call->GetRegNumByIdx(i); + regNumber toReg = copyTree->GetRegNumByIdx(i); + + // A Multi-reg GT_COPY node will have valid reg only for those + // positions that corresponding result reg of call node needs + // to be copied. + if (toReg != REG_NA) + { + assert(toReg != fromReg); + inst_RV_RV(ins_Copy(type), toReg, fromReg, type); + } } } else { - if (dstAddr->gtRegNum != dstReg) - { - inst_RV_RV(INS_mov, dstReg, dstAddr->gtRegNum, dstAddr->TypeGet()); - } - if ((src != nullptr) && (src->gtRegNum != srcReg)) - { - inst_RV_RV(INS_mov, srcReg, src->gtRegNum, src->TypeGet()); - } - } - if (!evalSizeFirst && size != nullptr && (size->gtRegNum != sizeReg)) - { - inst_RV_RV(INS_mov, sizeReg, size->gtRegNum, size->TypeGet()); - } -} + var_types targetType = treeNode->TypeGet(); + regNumber targetReg = treeNode->gtRegNum; + assert(targetReg != REG_NA); -//------------------------------------------------------------------------- -// genProduceReg: do liveness update for register produced by the current -// node in codegen. -// -// Arguments: -// tree - Gentree node -// -// Return Value: -// None. -void CodeGen::genProduceReg(GenTree* tree) -{ - if (tree->gtFlags & GTF_SPILL) - { - // Code for GT_COPY node gets generated as part of consuming regs by its parent. - // A GT_COPY node in turn produces reg result and it should never be marked to - // spill. - // - // Similarly GT_RELOAD node gets generated as part of consuming regs by its - // parent and should never be marked for spilling. - noway_assert(!tree->IsCopyOrReload()); + // Check whether this node and the node from which we're copying the value have + // different register types. This can happen if (currently iff) we have a SIMD + // vector type that fits in an integer register, in which case it is passed as + // an argument, or returned from a call, in an integer register and must be + // copied if it's in an xmm register. - if (genIsRegCandidateLocal(tree)) - { - // Store local variable to its home location. - tree->gtFlags &= ~GTF_REG_VAL; - // Ensure that lclVar stores are typed correctly. - unsigned varNum = tree->gtLclVarCommon.gtLclNum; - assert(!compiler->lvaTable[varNum].lvNormalizeOnStore() || - (tree->TypeGet() == genActualType(compiler->lvaTable[varNum].TypeGet()))); - inst_TT_RV(ins_Store(tree->gtType, compiler->isSIMDTypeLocalAligned(varNum)), tree, tree->gtRegNum); - } - else + bool srcFltReg = (varTypeIsFloating(op1) || varTypeIsSIMD(op1)); + bool tgtFltReg = (varTypeIsFloating(treeNode) || varTypeIsSIMD(treeNode)); + if (srcFltReg != tgtFltReg) { - // In case of multi-reg call node, spill flag on call node - // indicates that one or more of its allocated regs need to - // be spilled. Call node needs to be further queried to - // know which of its result regs needs to be spilled. - if (tree->IsMultiRegCall()) + instruction ins; + regNumber fpReg; + regNumber intReg; + if (tgtFltReg) { - GenTreeCall* call = tree->AsCall(); - ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); - unsigned regCount = retTypeDesc->GetReturnRegCount(); - - for (unsigned i = 0; i < regCount; ++i) - { - unsigned flags = call->GetRegSpillFlagByIdx(i); - if ((flags & GTF_SPILL) != 0) - { - regNumber reg = call->GetRegNumByIdx(i); - call->SetInReg(); - regSet.rsSpillTree(reg, call, i); - gcInfo.gcMarkRegSetNpt(genRegMask(reg)); - } - } + ins = ins_CopyIntToFloat(op1->TypeGet(), treeNode->TypeGet()); + fpReg = targetReg; + intReg = op1->gtRegNum; } else { - tree->SetInReg(); - regSet.rsSpillTree(tree->gtRegNum, tree); - gcInfo.gcMarkRegSetNpt(genRegMask(tree->gtRegNum)); + ins = ins_CopyFloatToInt(op1->TypeGet(), treeNode->TypeGet()); + intReg = targetReg; + fpReg = op1->gtRegNum; } - - tree->gtFlags |= GTF_SPILLED; - tree->gtFlags &= ~GTF_SPILL; - - return; + inst_RV_RV(ins, fpReg, intReg, targetType); + } + else + { + inst_RV_RV(ins_Copy(targetType), targetReg, genConsumeReg(op1), targetType); } - } - - genUpdateLife(tree); - // If we've produced a register, mark it as a pointer, as needed. - if (tree->gtHasReg()) - { - // We only mark the register in the following cases: - // 1. It is not a register candidate local. In this case, we're producing a - // register from a local, but the local is not a register candidate. Thus, - // we must be loading it as a temp register, and any "last use" flag on - // the register wouldn't be relevant. - // 2. The register candidate local is going dead. There's no point to mark - // the register as live, with a GC pointer, if the variable is dead. - if (!genIsRegCandidateLocal(tree) || ((tree->gtFlags & GTF_VAR_DEATH) == 0)) + if (op1->IsLocal()) { - // Multi-reg call node will produce more than one register result. - // Mark all the regs produced by call node. - if (tree->IsMultiRegCall()) + // The lclVar will never be a def. + // If it is a last use, the lclVar will be killed by genConsumeReg(), as usual, and genProduceReg will + // appropriately set the gcInfo for the copied value. + // If not, there are two cases we need to handle: + // - If this is a TEMPORARY copy (indicated by the GTF_VAR_DEATH flag) the variable + // will remain live in its original register. + // genProduceReg() will appropriately set the gcInfo for the copied value, + // and genConsumeReg will reset it. + // - Otherwise, we need to update register info for the lclVar. + + GenTreeLclVarCommon* lcl = op1->AsLclVarCommon(); + assert((lcl->gtFlags & GTF_VAR_DEF) == 0); + + if ((lcl->gtFlags & GTF_VAR_DEATH) == 0 && (treeNode->gtFlags & GTF_VAR_DEATH) == 0) { - GenTreeCall* call = tree->AsCall(); - ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); - unsigned regCount = retTypeDesc->GetReturnRegCount(); + LclVarDsc* varDsc = &compiler->lvaTable[lcl->gtLclNum]; - for (unsigned i = 0; i < regCount; ++i) + // If we didn't just spill it (in genConsumeReg, above), then update the register info + if (varDsc->lvRegNum != REG_STK) { - regNumber reg = call->GetRegNumByIdx(i); - var_types type = retTypeDesc->GetReturnRegType(i); - gcInfo.gcMarkRegPtrVal(reg, type); - } - } - else if (tree->IsCopyOrReloadOfMultiRegCall()) - { - // we should never see reload of multi-reg call here - // because GT_RELOAD gets generated in reg consuming path. - noway_assert(tree->OperGet() == GT_COPY); + // The old location is dying + genUpdateRegLife(varDsc, /*isBorn*/ false, /*isDying*/ true DEBUGARG(op1)); - // A multi-reg GT_COPY node produces those regs to which - // copy has taken place. - GenTreeCopyOrReload* copy = tree->AsCopyOrReload(); - GenTreeCall* call = copy->gtGetOp1()->AsCall(); - ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc(); - unsigned regCount = retTypeDesc->GetReturnRegCount(); + gcInfo.gcMarkRegSetNpt(genRegMask(op1->gtRegNum)); - for (unsigned i = 0; i < regCount; ++i) - { - var_types type = retTypeDesc->GetReturnRegType(i); - regNumber fromReg = call->GetRegNumByIdx(i); - regNumber toReg = copy->GetRegNumByIdx(i); + genUpdateVarReg(varDsc, treeNode); - if (toReg != REG_NA) - { - gcInfo.gcMarkRegPtrVal(toReg, type); - } + // The new location is going live + genUpdateRegLife(varDsc, /*isBorn*/ true, /*isDying*/ false DEBUGARG(treeNode)); } } - else - { - gcInfo.gcMarkRegPtrVal(tree->gtRegNum, tree->TypeGet()); - } } } - tree->SetInReg(); -} - -// transfer gc/byref status of src reg to dst reg -void CodeGen::genTransferRegGCState(regNumber dst, regNumber src) -{ - regMaskTP srcMask = genRegMask(src); - regMaskTP dstMask = genRegMask(dst); - - if (gcInfo.gcRegGCrefSetCur & srcMask) - { - gcInfo.gcMarkRegSetGCref(dstMask); - } - else if (gcInfo.gcRegByrefSetCur & srcMask) - { - gcInfo.gcMarkRegSetByref(dstMask); - } - else - { - gcInfo.gcMarkRegSetNpt(dstMask); - } -} - -// generates an ip-relative call or indirect call via reg ('call reg') -// pass in 'addr' for a relative call or 'base' for a indirect register call -// methHnd - optional, only used for pretty printing -// retSize - emitter type of return for GC purposes, should be EA_BYREF, EA_GCREF, or EA_PTRSIZE(not GC) -void CodeGen::genEmitCall(int callType, - CORINFO_METHOD_HANDLE methHnd, - INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) void* addr X86_ARG(ssize_t argSize), - emitAttr retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize), - IL_OFFSETX ilOffset, - regNumber base, - bool isJump, - bool isNoGC) -{ -#if !defined(_TARGET_X86_) - ssize_t argSize = 0; -#endif // !defined(_TARGET_X86_) - getEmitter()->emitIns_Call(emitter::EmitCallType(callType), methHnd, INDEBUG_LDISASM_COMMA(sigInfo) addr, argSize, - retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize), gcInfo.gcVarPtrSetCur, - gcInfo.gcRegGCrefSetCur, gcInfo.gcRegByrefSetCur, ilOffset, base, REG_NA, 0, 0, isJump, - emitter::emitNoGChelper(compiler->eeGetHelperNum(methHnd))); -} - -// generates an indirect call via addressing mode (call []) given an indir node -// methHnd - optional, only used for pretty printing -// retSize - emitter type of return for GC purposes, should be EA_BYREF, EA_GCREF, or EA_PTRSIZE(not GC) -void CodeGen::genEmitCall(int callType, - CORINFO_METHOD_HANDLE methHnd, - INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) GenTreeIndir* indir X86_ARG(ssize_t argSize), - emitAttr retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize), - IL_OFFSETX ilOffset) -{ -#if !defined(_TARGET_X86_) - ssize_t argSize = 0; -#endif // !defined(_TARGET_X86_) - genConsumeAddress(indir->Addr()); - getEmitter()->emitIns_Call(emitter::EmitCallType(callType), methHnd, INDEBUG_LDISASM_COMMA(sigInfo) nullptr, - argSize, retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize), - gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, gcInfo.gcRegByrefSetCur, ilOffset, - indir->Base() ? indir->Base()->gtRegNum : REG_NA, - indir->Index() ? indir->Index()->gtRegNum : REG_NA, indir->Scale(), indir->Offset()); + genProduceReg(treeNode); } //------------------------------------------------------------------------ @@ -5724,16 +4525,10 @@ void CodeGen::genStoreInd(GenTreePtr node) noway_assert(data->gtRegNum != REG_ARG_0); // addr goes in REG_ARG_0 - if (addr->gtRegNum != REG_ARG_0) - { - inst_RV_RV(INS_mov, REG_ARG_0, addr->gtRegNum, addr->TypeGet()); - } + genCopyRegIfNeeded(addr, REG_ARG_0); // data goes in REG_ARG_1 - if (data->gtRegNum != REG_ARG_1) - { - inst_RV_RV(INS_mov, REG_ARG_1, data->gtRegNum, data->TypeGet()); - } + genCopyRegIfNeeded(data, REG_ARG_1); genGCWriteBarrier(storeInd, writeBarrierForm); } @@ -5821,6 +4616,23 @@ void CodeGen::genStoreInd(GenTreePtr node) assert(rmwSrc == data->gtGetOp2()); genCodeForShiftRMW(storeInd); } + else if (!compiler->opts.compDbgCode && data->OperGet() == GT_ADD && + (rmwSrc->IsIntegralConst(1) || rmwSrc->IsIntegralConst(-1))) + { + // Generate "inc/dec [mem]" instead of "add/sub [mem], 1". + // + // Notes: + // 1) Global morph transforms GT_SUB(x, +/-1) into GT_ADD(x, -/+1). + // 2) TODO-AMD64: Debugger routine NativeWalker::Decode() runs into + // an assert while decoding ModR/M byte of "inc dword ptr [rax]". + // It is not clear whether Decode() can handle all possible + // addr modes with inc/dec. For this reason, inc/dec [mem] + // is not generated while generating debuggable code. Update + // the above if condition once Decode() routine is fixed. + assert(rmwSrc->isContainedIntOrIImmed()); + instruction ins = rmwSrc->IsIntegralConst(1) ? INS_inc : INS_dec; + getEmitter()->emitInsRMW(ins, emitTypeSize(storeInd), storeInd); + } else { // generate code for remaining binary RMW memory ops like add/sub/and/or/xor @@ -5905,10 +4717,7 @@ bool CodeGen::genEmitOptimizedGCWriteBarrier(GCInfo::WriteBarrierForm writeBarri // call write_barrier_helper_reg // addr goes in REG_ARG_0 - if (addr->gtRegNum != REG_WRITE_BARRIER) // REVIEW: can it ever not already by in this register? - { - inst_RV_RV(INS_mov, REG_WRITE_BARRIER, addr->gtRegNum, addr->TypeGet()); - } + genCopyRegIfNeeded(addr, REG_WRITE_BARRIER); unsigned tgtAnywhere = 0; if (writeBarrierForm != GCInfo::WBF_BarrierUnchecked) @@ -5943,10 +4752,28 @@ void CodeGen::genCallInstruction(GenTreePtr node) // all virtuals should have been expanded into a control expression assert(!call->IsVirtual() || call->gtControlExpr || call->gtCallAddr); + // Insert a GS check if necessary + if (call->IsTailCallViaHelper()) + { + if (compiler->getNeedsGSSecurityCookie()) + { +#if FEATURE_FIXED_OUT_ARGS + // If either of the conditions below is true, we will need a temporary register in order to perform the GS + // cookie check. When FEATURE_FIXED_OUT_ARGS is disabled, we save and restore the temporary register using + // push/pop. When FEATURE_FIXED_OUT_ARGS is enabled, however, we need an alternative solution. For now, + // though, the tail prefix is ignored on all platforms that use fixed out args, so we should never hit this + // case. + assert(compiler->gsGlobalSecurityCookieAddr == nullptr); + assert((int)compiler->gsGlobalSecurityCookieVal == (ssize_t)compiler->gsGlobalSecurityCookieVal); +#endif + genEmitGSCookieCheck(true); + } + } + // Consume all the arg regs for (GenTreePtr list = call->gtCallLateArgs; list; list = list->MoveNext()) { - assert(list->IsList()); + assert(list->OperIsList()); GenTreePtr argNode = list->Current(); @@ -5960,13 +4787,13 @@ void CodeGen::genCallInstruction(GenTreePtr node) #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING // Deal with multi register passed struct args. - if (argNode->OperGet() == GT_LIST) + if (argNode->OperGet() == GT_FIELD_LIST) { - GenTreeArgList* argListPtr = argNode->AsArgList(); - unsigned iterationNum = 0; - for (; argListPtr != nullptr; argListPtr = argListPtr->Rest(), iterationNum++) + GenTreeFieldList* fieldListPtr = argNode->AsFieldList(); + unsigned iterationNum = 0; + for (; fieldListPtr != nullptr; fieldListPtr = fieldListPtr->Rest(), iterationNum++) { - GenTreePtr putArgRegNode = argListPtr->gtOp.gtOp1; + GenTreePtr putArgRegNode = fieldListPtr->gtOp.gtOp1; assert(putArgRegNode->gtOper == GT_PUTARG_REG); regNumber argReg = REG_NA; @@ -6036,20 +4863,34 @@ void CodeGen::genCallInstruction(GenTreePtr node) { assert((arg->gtGetOp1()->OperGet() == GT_PUTARG_STK) && (arg->gtGetOp2()->OperGet() == GT_PUTARG_STK)); } + if ((arg->OperGet() == GT_PUTARG_STK) && (arg->gtGetOp1()->OperGet() == GT_FIELD_LIST)) + { + fgArgTabEntryPtr curArgTabEntry = compiler->gtArgEntryByNode(call, arg); + assert(curArgTabEntry); + stackArgBytes += curArgTabEntry->numSlots * TARGET_POINTER_SIZE; + } + else #endif // defined(_TARGET_X86_) -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING - if (genActualType(arg->TypeGet()) == TYP_STRUCT) +#ifdef FEATURE_PUT_STRUCT_ARG_STK + if (genActualType(arg->TypeGet()) == TYP_STRUCT) { assert(arg->OperGet() == GT_PUTARG_STK); - GenTreeObj* obj = arg->gtGetOp1()->AsObj(); - stackArgBytes = compiler->info.compCompHnd->getClassSize(obj->gtClass); + GenTreeObj* obj = arg->gtGetOp1()->AsObj(); + unsigned argBytes = (unsigned)roundUp(obj->gtBlkSize, TARGET_POINTER_SIZE); +#ifdef DEBUG + fgArgTabEntryPtr curArgTabEntry = compiler->gtArgEntryByNode(call, arg); + assert((curArgTabEntry->numSlots * TARGET_POINTER_SIZE) == argBytes); +#endif // DEBUG + stackArgBytes += argBytes; } else -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING + { +#endif // FEATURE_PUT_STRUCT_ARG_STK stackArgBytes += genTypeSize(genActualType(arg->TypeGet())); + } } args = args->gtOp.gtOp2; } @@ -6098,10 +4939,7 @@ void CodeGen::genCallInstruction(GenTreePtr node) assert(target != nullptr); genConsumeReg(target); - if (target->gtRegNum != REG_RAX) - { - inst_RV_RV(INS_mov, REG_RAX, target->gtRegNum); - } + genCopyRegIfNeeded(target, REG_RAX); return; } @@ -6141,7 +4979,6 @@ void CodeGen::genCallInstruction(GenTreePtr node) bool fPossibleSyncHelperCall = false; CorInfoHelpFunc helperNum = CORINFO_HELP_UNDEF; -#ifdef DEBUGGING_SUPPORT // We need to propagate the IL offset information to the call instruction, so we can emit // an IL to native mapping record for the call, to support managed return value debugging. // We don't want tail call helper calls that were converted from normal calls to get a record, @@ -6150,7 +4987,6 @@ void CodeGen::genCallInstruction(GenTreePtr node) { (void)compiler->genCallSite2ILOffsetMap->Lookup(call, &ilOffset); } -#endif // DEBUGGING_SUPPORT #if defined(_TARGET_X86_) // If the callee pops the arguments, we pass a positive value as the argSize, and the emitter will @@ -6167,7 +5003,38 @@ void CodeGen::genCallInstruction(GenTreePtr node) if (target != nullptr) { - if (target->isContainedIndir()) +#ifdef _TARGET_X86_ + if (call->IsVirtualStub() && (call->gtCallType == CT_INDIRECT)) + { + // On x86, we need to generate a very specific pattern for indirect VSD calls: + // + // 3-byte nop + // call dword ptr [eax] + // + // Where EAX is also used as an argument to the stub dispatch helper. Make + // sure that the call target address is computed into EAX in this case. + + assert(REG_VIRTUAL_STUB_PARAM == REG_VIRTUAL_STUB_TARGET); + + assert(target->isContainedIndir()); + assert(target->OperGet() == GT_IND); + + GenTree* addr = target->AsIndir()->Addr(); + assert(!addr->isContained()); + + genConsumeReg(addr); + genCopyRegIfNeeded(addr, REG_VIRTUAL_STUB_TARGET); + + getEmitter()->emitIns_Nop(3); + getEmitter()->emitIns_Call(emitter::EmitCallType(emitter::EC_INDIR_ARD), methHnd, + INDEBUG_LDISASM_COMMA(sigInfo) nullptr, argSizeForEmitter, + retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize), + gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, gcInfo.gcRegByrefSetCur, + ilOffset, REG_VIRTUAL_STUB_TARGET, REG_NA, 1, 0); + } + else +#endif + if (target->isContainedIndir()) { if (target->AsIndir()->HasBase() && target->AsIndir()->Base()->isContainedIntOrIImmed()) { @@ -6977,8 +5844,6 @@ void CodeGen::genCompareLong(GenTreePtr treeNode) genConsumeOperands(tree); - assert(targetReg != REG_NA); - GenTreePtr loOp1 = op1->gtGetOp1(); GenTreePtr hiOp1 = op1->gtGetOp2(); GenTreePtr loOp2 = op2->gtGetOp1(); @@ -6992,6 +5857,12 @@ void CodeGen::genCompareLong(GenTreePtr treeNode) // Emit the compare instruction getEmitter()->emitInsBinary(ins, cmpAttr, hiOp1, hiOp2); + // If the result is not being materialized in a register, we're done. + if (targetReg == REG_NA) + { + return; + } + // Generate the first jump for the high compare CompareKind compareKind = ((tree->gtFlags & GTF_UNSIGNED) != 0) ? CK_UNSIGNED : CK_SIGNED; @@ -7015,10 +5886,6 @@ void CodeGen::genCompareLong(GenTreePtr treeNode) emitJumpKind jumpKindLo = genJumpKindForOper(tree->gtOper, CK_UNSIGNED); inst_SET(jumpKindLo, targetReg); - // Set the higher bytes to 0 - inst_RV_RV(ins_Move_Extend(TYP_UBYTE, true), targetReg, targetReg, TYP_UBYTE, emitTypeSize(TYP_UBYTE)); - genProduceReg(tree); - inst_JMP(EJ_jmp, labelFinal); // Define the label for hi jump target here. If we have jumped here, we want to set @@ -7027,11 +5894,10 @@ void CodeGen::genCompareLong(GenTreePtr treeNode) genDefineTempLabel(labelHi); inst_SET(genJumpKindForOper(tree->gtOper, compareKind), targetReg); + genDefineTempLabel(labelFinal); // Set the higher bytes to 0 inst_RV_RV(ins_Move_Extend(TYP_UBYTE, true), targetReg, targetReg, TYP_UBYTE, emitTypeSize(TYP_UBYTE)); genProduceReg(tree); - - genDefineTempLabel(labelFinal); } else { @@ -7062,152 +5928,6 @@ void CodeGen::genCompareLong(GenTreePtr treeNode) genProduceReg(tree); } } - -//------------------------------------------------------------------------ -// genJTrueLong: Generate code for comparing two longs on x86 for the case where the result -// is not manifested in a register. -// -// Arguments: -// treeNode - the compare tree -// -// Return Value: -// None. -// Comments: -// For long compares, we need to compare the high parts of operands first, then the low parts. -// We only have to do the low compare if the high parts of the operands are equal. -// -// In the case where the result of a rel-op is not realized in a register, we generate: -// -// Opcode x86 equivalent Comment -// ------ -------------- ------- -// -// GT_LT; unsigned cmp hiOp1,hiOp2 -// jb trueLabel -// ja falseLabel -// cmp loOp1,loOp2 -// jb trueLabel -// falseLabel: -// -// GT_LE; unsigned cmp hiOp1,hiOp2 -// jb trueLabel -// ja falseLabel -// cmp loOp1,loOp2 -// jbe trueLabel -// falseLabel: -// -// GT_GT; unsigned cmp hiOp1,hiOp2 -// ja trueLabel -// jb falseLabel -// cmp loOp1,loOp2 -// ja trueLabel -// falseLabel: -// -// GT_GE; unsigned cmp hiOp1,hiOp2 -// ja trueLabel -// jb falseLabel -// cmp loOp1,loOp2 -// jae trueLabel -// falseLabel: -// -// GT_LT; signed cmp hiOp1,hiOp2 -// jl trueLabel -// jg falseLabel -// cmp loOp1,loOp2 -// jb trueLabel -// falseLabel: -// -// GT_LE; signed cmp hiOp1,hiOp2 -// jl trueLabel -// jg falseLabel -// cmp loOp1,loOp2 -// jbe trueLabel -// falseLabel: -// -// GT_GT; signed cmp hiOp1,hiOp2 -// jg trueLabel -// jl falseLabel -// cmp loOp1,loOp2 -// ja trueLabel -// falseLabel: -// -// GT_GE; signed cmp hiOp1,hiOp2 -// jg trueLabel -// jl falseLabel -// cmp loOp1,loOp2 -// jae trueLabel -// falseLabel: -// -// GT_EQ; cmp hiOp1,hiOp2 -// jne falseLabel -// cmp loOp1,loOp2 -// je trueLabel -// falseLabel: -// -// GT_NE; cmp hiOp1,hiOp2 -// jne labelTrue -// cmp loOp1,loOp2 -// jne trueLabel -// falseLabel: -// -// TODO-X86-CQ: Check if hi or lo parts of op2 are 0 and change the compare to a test. -void CodeGen::genJTrueLong(GenTreePtr treeNode) -{ - assert(treeNode->OperIsCompare()); - - GenTreeOp* tree = treeNode->AsOp(); - GenTreePtr op1 = tree->gtOp1; - GenTreePtr op2 = tree->gtOp2; - - assert(varTypeIsLong(op1->TypeGet())); - assert(varTypeIsLong(op2->TypeGet())); - - regNumber targetReg = treeNode->gtRegNum; - - assert(targetReg == REG_NA); - - GenTreePtr loOp1 = op1->gtGetOp1(); - GenTreePtr hiOp1 = op1->gtGetOp2(); - GenTreePtr loOp2 = op2->gtGetOp1(); - GenTreePtr hiOp2 = op2->gtGetOp2(); - - // Emit the compare instruction - getEmitter()->emitInsBinary(INS_cmp, EA_4BYTE, hiOp1, hiOp2); - - // Generate the first jump for the high compare - CompareKind compareKind = ((tree->gtFlags & GTF_UNSIGNED) != 0) ? CK_UNSIGNED : CK_SIGNED; - - // TODO-X86-CQ: If the next block is a BBJ_ALWAYS, we can set falseLabel = compiler->compCurBB->bbNext->bbJumpDest. - BasicBlock* falseLabel = genCreateTempLabel(); - - emitJumpKind jumpKindHi[2]; - - // Generate the jumps for the high compare - genJumpKindsForTreeLongHi(tree, jumpKindHi); - - BasicBlock* trueLabel = compiler->compCurBB->bbJumpDest; - - if (jumpKindHi[0] != EJ_NONE) - { - inst_JMP(jumpKindHi[0], trueLabel); - } - - if (jumpKindHi[1] != EJ_NONE) - { - inst_JMP(jumpKindHi[1], falseLabel); - } - - // The low jump must be unsigned - emitJumpKind jumpKindLo = genJumpKindForOper(tree->gtOper, CK_UNSIGNED); - - // Emit the comparison and the jump to the trueLabel - getEmitter()->emitInsBinary(INS_cmp, EA_4BYTE, loOp1, loOp2); - - inst_JMP(jumpKindLo, trueLabel); - - // Generate falseLabel, which is the false path. We will jump here if the high compare is false - // or fall through if the low compare is false. - genDefineTempLabel(falseLabel); -} #endif //! defined(_TARGET_64BIT_) //------------------------------------------------------------------------ @@ -7339,19 +6059,77 @@ void CodeGen::genCompareInt(GenTreePtr treeNode) { assert(treeNode->OperIsCompare()); - GenTreeOp* tree = treeNode->AsOp(); - GenTreePtr op1 = tree->gtOp1; - GenTreePtr op2 = tree->gtOp2; - var_types op1Type = op1->TypeGet(); - var_types op2Type = op2->TypeGet(); + GenTreeOp* tree = treeNode->AsOp(); + GenTreePtr op1 = tree->gtOp1; + GenTreePtr op2 = tree->gtOp2; + var_types op1Type = op1->TypeGet(); + var_types op2Type = op2->TypeGet(); + regNumber targetReg = treeNode->gtRegNum; + + // Case of op1 == 0 or op1 != 0: + // Optimize generation of 'test' instruction if op1 sets flags. + // + // Note that if LSRA has inserted any GT_RELOAD/GT_COPY before + // op1, it will not modify the flags set by codegen of op1. + // Similarly op1 could also be reg-optional at its use and + // it was spilled after producing its result in a register. + // Spill code too will not modify the flags set by op1. + GenTree* realOp1 = op1->gtSkipReloadOrCopy(); + if (realOp1->gtSetFlags()) + { + // op1 must set ZF and SF flags + assert(realOp1->gtSetZSFlags()); + + // Must be (in)equality against zero. + assert(tree->OperGet() == GT_EQ || tree->OperGet() == GT_NE); + assert(op2->IsIntegralConst(0)); + assert(op2->isContained()); + + // Just consume the operands + genConsumeOperands(tree); + + // No need to generate test instruction since + // op1 sets flags + + // Are we evaluating this into a register? + if (targetReg != REG_NA) + { + genSetRegToCond(targetReg, tree); + genProduceReg(tree); + } + + return; + } + +#ifdef FEATURE_SIMD + // If we have GT_JTRUE(GT_EQ/NE(GT_SIMD((in)Equality, v1, v2), true/false)), + // then we don't need to generate code for GT_EQ/GT_NE, since SIMD (in)Equality intrinsic + // would set or clear Zero flag. + if ((targetReg == REG_NA) && (tree->OperGet() == GT_EQ || tree->OperGet() == GT_NE)) + { + // Is it a SIMD (in)Equality that doesn't need to materialize result into a register? + if ((op1->gtRegNum == REG_NA) && op1->IsSIMDEqualityOrInequality()) + { + // Must be comparing against true or false. + assert(op2->IsIntegralConst(0) || op2->IsIntegralConst(1)); + assert(op2->isContainedIntOrIImmed()); + + // In this case SIMD (in)Equality will set or clear + // Zero flag, based on which GT_JTRUE would generate + // the right conditional jump. + return; + } + } +#endif // FEATURE_SIMD genConsumeOperands(tree); instruction ins; emitAttr cmpAttr; - regNumber targetReg = treeNode->gtRegNum; - assert(!op1->isContainedIntOrIImmed()); // We no longer support swapping op1 and op2 to generate cmp reg, imm + // TODO-CQ: We should be able to support swapping op1 and op2 to generate cmp reg, imm. + // https://github.com/dotnet/coreclr/issues/7270 + assert(!op1->isContainedIntOrIImmed()); // We no longer support assert(!varTypeIsFloating(op2Type)); #ifdef _TARGET_X86_ @@ -7387,7 +6165,7 @@ void CodeGen::genCompareInt(GenTreePtr treeNode) { // Do we have a short compare against a constant in op2? // - // We checked for this case in LowerCmp() and if we can perform a small + // We checked for this case in TreeNodeInfoInitCmp() and if we can perform a small // compare immediate we labeled this compare with a GTF_RELOP_SMALL // and for unsigned small non-equality compares the GTF_UNSIGNED flag. // @@ -7442,12 +6220,11 @@ void CodeGen::genCompareInt(GenTreePtr treeNode) if (op1->isContained()) { // op1 can be a contained memory op - // or the special contained GT_AND that we created in Lowering::LowerCmp() + // or the special contained GT_AND that we created in Lowering::TreeNodeInfoInitCmp() // - if ((op1->OperGet() == GT_AND)) + if ((op1->OperGet() == GT_AND) && op1->gtGetOp2()->isContainedIntOrIImmed() && + ((tree->OperGet() == GT_EQ) || (tree->OperGet() == GT_NE))) { - noway_assert(op1->gtOp.gtOp2->isContainedIntOrIImmed()); - ins = INS_test; // we will generate "test andOp1, andOp2CnsVal" op2 = op1->gtOp.gtOp2; // must assign op2 before we overwrite op1 op1 = op1->gtOp.gtOp1; // overwrite op1 @@ -7561,6 +6338,93 @@ void CodeGen::genSetRegToCond(regNumber dstReg, GenTreePtr tree) } } +#if !defined(_TARGET_64BIT_) +//------------------------------------------------------------------------ +// genIntToIntCast: Generate code for long to int casts on x86. +// +// Arguments: +// cast - The GT_CAST node +// +// Return Value: +// None. +// +// Assumptions: +// The cast node and its sources (via GT_LONG) must have been assigned registers. +// The destination cannot be a floating point type or a small integer type. +// +void CodeGen::genLongToIntCast(GenTree* cast) +{ + assert(cast->OperGet() == GT_CAST); + + GenTree* src = cast->gtGetOp1(); + noway_assert(src->OperGet() == GT_LONG); + + genConsumeRegs(src); + + var_types srcType = ((cast->gtFlags & GTF_UNSIGNED) != 0) ? TYP_ULONG : TYP_LONG; + var_types dstType = cast->CastToType(); + regNumber loSrcReg = src->gtGetOp1()->gtRegNum; + regNumber hiSrcReg = src->gtGetOp2()->gtRegNum; + regNumber dstReg = cast->gtRegNum; + + assert((dstType == TYP_INT) || (dstType == TYP_UINT)); + assert(genIsValidIntReg(loSrcReg)); + assert(genIsValidIntReg(hiSrcReg)); + assert(genIsValidIntReg(dstReg)); + + if (cast->gtOverflow()) + { + // + // Generate an overflow check for [u]long to [u]int casts: + // + // long -> int - check if the upper 33 bits are all 0 or all 1 + // + // ulong -> int - check if the upper 33 bits are all 0 + // + // long -> uint - check if the upper 32 bits are all 0 + // ulong -> uint - check if the upper 32 bits are all 0 + // + + if ((srcType == TYP_LONG) && (dstType == TYP_INT)) + { + BasicBlock* allOne = genCreateTempLabel(); + BasicBlock* success = genCreateTempLabel(); + + inst_RV_RV(INS_test, loSrcReg, loSrcReg, TYP_INT, EA_4BYTE); + inst_JMP(EJ_js, allOne); + + inst_RV_RV(INS_test, hiSrcReg, hiSrcReg, TYP_INT, EA_4BYTE); + genJumpToThrowHlpBlk(EJ_jne, SCK_OVERFLOW); + inst_JMP(EJ_jmp, success); + + genDefineTempLabel(allOne); + inst_RV_IV(INS_cmp, hiSrcReg, -1, EA_4BYTE); + genJumpToThrowHlpBlk(EJ_jne, SCK_OVERFLOW); + + genDefineTempLabel(success); + } + else + { + if ((srcType == TYP_ULONG) && (dstType == TYP_INT)) + { + inst_RV_RV(INS_test, loSrcReg, loSrcReg, TYP_INT, EA_4BYTE); + genJumpToThrowHlpBlk(EJ_js, SCK_OVERFLOW); + } + + inst_RV_RV(INS_test, hiSrcReg, hiSrcReg, TYP_INT, EA_4BYTE); + genJumpToThrowHlpBlk(EJ_jne, SCK_OVERFLOW); + } + } + + if (dstReg != loSrcReg) + { + inst_RV_RV(INS_mov, dstReg, loSrcReg, TYP_INT, EA_4BYTE); + } + + genProduceReg(cast); +} +#endif + //------------------------------------------------------------------------ // genIntToIntCast: Generate code for an integer cast // This method handles integer overflow checking casts @@ -7584,13 +6448,22 @@ void CodeGen::genIntToIntCast(GenTreePtr treeNode) { assert(treeNode->OperGet() == GT_CAST); - GenTreePtr castOp = treeNode->gtCast.CastOp(); - regNumber targetReg = treeNode->gtRegNum; - regNumber sourceReg = castOp->gtRegNum; - var_types dstType = treeNode->CastToType(); - bool isUnsignedDst = varTypeIsUnsigned(dstType); - var_types srcType = genActualType(castOp->TypeGet()); - bool isUnsignedSrc = varTypeIsUnsigned(srcType); + GenTreePtr castOp = treeNode->gtCast.CastOp(); + var_types srcType = genActualType(castOp->TypeGet()); + +#if !defined(_TARGET_64BIT_) + if (varTypeIsLong(srcType)) + { + genLongToIntCast(treeNode); + return; + } +#endif // !defined(_TARGET_64BIT_) + + regNumber targetReg = treeNode->gtRegNum; + regNumber sourceReg = castOp->gtRegNum; + var_types dstType = treeNode->CastToType(); + bool isUnsignedDst = varTypeIsUnsigned(dstType); + bool isUnsignedSrc = varTypeIsUnsigned(srcType); // if necessary, force the srcType to unsigned when the GT_UNSIGNED flag is set if (!isUnsignedSrc && (treeNode->gtFlags & GTF_UNSIGNED) != 0) @@ -7948,7 +6821,7 @@ void CodeGen::genFloatToFloatCast(GenTreePtr treeNode) assert(varTypeIsFloating(srcType) && varTypeIsFloating(dstType)); genConsumeOperands(treeNode->AsOp()); - if (srcType == dstType && targetReg == op1->gtRegNum) + if (srcType == dstType && (!op1->isContained() && (targetReg == op1->gtRegNum))) { // source and destinations types are the same and also reside in the same register. // we just need to consume and produce the reg in this case. @@ -7999,7 +6872,8 @@ void CodeGen::genIntToFloatCast(GenTreePtr treeNode) assert(!varTypeIsFloating(srcType) && varTypeIsFloating(dstType)); #if !defined(_TARGET_64BIT_) - NYI_IF(varTypeIsLong(srcType), "Conversion from long to float"); + // We expect morph to replace long to float/double casts with helper calls + noway_assert(!varTypeIsLong(srcType)); #endif // !defined(_TARGET_64BIT_) // Since xarch emitter doesn't handle reporting gc-info correctly while casting away gc-ness we @@ -8225,27 +7099,27 @@ void CodeGen::genCkfinite(GenTreePtr treeNode) // // For TYP_DOUBLE, we'll generate (for targetReg != op1->gtRegNum): // movaps targetReg, op1->gtRegNum - // shufps targetReg, targetReg, 0xB1 // WZYX => ZWXY - // mov_xmm2i tmpReg, targetReg // tmpReg <= Y + // shufps targetReg, targetReg, 0xB1 // WZYX => ZWXY + // mov_xmm2i tmpReg, targetReg // tmpReg <= Y // and tmpReg, // cmp tmpReg, // je // movaps targetReg, op1->gtRegNum // copy the value again, instead of un-shuffling it // // For TYP_DOUBLE with (targetReg == op1->gtRegNum): - // shufps targetReg, targetReg, 0xB1 // WZYX => ZWXY - // mov_xmm2i tmpReg, targetReg // tmpReg <= Y + // shufps targetReg, targetReg, 0xB1 // WZYX => ZWXY + // mov_xmm2i tmpReg, targetReg // tmpReg <= Y // and tmpReg, // cmp tmpReg, // je - // shufps targetReg, targetReg, 0xB1 // ZWXY => WZYX + // shufps targetReg, targetReg, 0xB1 // ZWXY => WZYX // // For TYP_FLOAT, it's the same as _TARGET_64BIT_: - // mov_xmm2i tmpReg, targetReg // tmpReg <= low 32 bits + // mov_xmm2i tmpReg, targetReg // tmpReg <= low 32 bits // and tmpReg, // cmp tmpReg, // je - // movaps targetReg, op1->gtRegNum // only if targetReg != op1->gtRegNum + // movaps targetReg, op1->gtRegNum // only if targetReg != op1->gtRegNum regNumber copyToTmpSrcReg; // The register we'll copy to the integer temp. @@ -8600,29 +7474,280 @@ unsigned CodeGen::getBaseVarForPutArgStk(GenTreePtr treeNode) LclVarDsc* varDsc = &(compiler->lvaTable[baseVarNum]); assert(varDsc != nullptr); -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING - assert(!varDsc->lvIsRegArg && varDsc->lvArgReg == REG_STK); -#else // !FEATURE_UNIX_AMD64_STRUCT_PASSING - // On Windows this assert is always true. The first argument will always be in REG_ARG_0 or REG_FLTARG_0. - assert(varDsc->lvIsRegArg && (varDsc->lvArgReg == REG_ARG_0 || varDsc->lvArgReg == REG_FLTARG_0)); -#endif // !FEATURE_UNIX_AMD64_STRUCT_PASSING -#endif // !DEBUG +#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING + assert(!varDsc->lvIsRegArg && varDsc->lvArgReg == REG_STK); +#else // !FEATURE_UNIX_AMD64_STRUCT_PASSING + // On Windows this assert is always true. The first argument will always be in REG_ARG_0 or REG_FLTARG_0. + assert(varDsc->lvIsRegArg && (varDsc->lvArgReg == REG_ARG_0 || varDsc->lvArgReg == REG_FLTARG_0)); +#endif // !FEATURE_UNIX_AMD64_STRUCT_PASSING +#endif // !DEBUG + } + else + { +#if FEATURE_FIXED_OUT_ARGS + baseVarNum = compiler->lvaOutgoingArgSpaceVar; +#else // !FEATURE_FIXED_OUT_ARGS + assert(!"No BaseVarForPutArgStk on x86"); + baseVarNum = BAD_VAR_NUM; +#endif // !FEATURE_FIXED_OUT_ARGS + } + + return baseVarNum; +} + +#ifdef _TARGET_X86_ +//--------------------------------------------------------------------- +// adjustStackForPutArgStk: +// adjust the stack pointer for a putArgStk node if necessary. +// +// Arguments: +// putArgStk - the putArgStk node. +// +// Returns: true if the stack pointer was adjusted; false otherwise. +// +bool CodeGen::genAdjustStackForPutArgStk(GenTreePutArgStk* putArgStk) +{ +#ifdef FEATURE_SIMD + if (varTypeIsSIMD(putArgStk)) + { + const unsigned argSize = genTypeSize(putArgStk); + inst_RV_IV(INS_sub, REG_SPBASE, argSize, EA_PTRSIZE); + genStackLevel += argSize; + m_pushStkArg = false; + return true; + } +#endif // FEATURE_SIMD + + const unsigned argSize = putArgStk->getArgSize(); + + // If the gtPutArgStkKind is one of the push types, we do not pre-adjust the stack. + // This is set in Lowering, and is true if and only if: + // - This argument contains any GC pointers OR + // - It is a GT_FIELD_LIST OR + // - It is less than 16 bytes in size. + CLANG_FORMAT_COMMENT_ANCHOR; + +#ifdef DEBUG + switch (putArgStk->gtPutArgStkKind) + { + case GenTreePutArgStk::Kind::RepInstr: + case GenTreePutArgStk::Kind::Unroll: + assert((putArgStk->gtNumberReferenceSlots == 0) && (putArgStk->gtGetOp1()->OperGet() != GT_FIELD_LIST) && + (argSize >= 16)); + break; + case GenTreePutArgStk::Kind::Push: + case GenTreePutArgStk::Kind::PushAllSlots: + assert((putArgStk->gtNumberReferenceSlots != 0) || (putArgStk->gtGetOp1()->OperGet() == GT_FIELD_LIST) || + (argSize < 16)); + break; + case GenTreePutArgStk::Kind::Invalid: + default: + assert(!"Uninitialized GenTreePutArgStk::Kind"); + break; + } +#endif // DEBUG + + if (putArgStk->isPushKind()) + { + m_pushStkArg = true; + return false; + } + else + { + m_pushStkArg = false; + inst_RV_IV(INS_sub, REG_SPBASE, argSize, EA_PTRSIZE); + genStackLevel += argSize; + return true; + } +} + +//--------------------------------------------------------------------- +// genPutArgStkFieldList - generate code for passing an arg on the stack. +// +// Arguments +// treeNode - the GT_PUTARG_STK node +// targetType - the type of the treeNode +// +// Return value: +// None +// +void CodeGen::genPutArgStkFieldList(GenTreePutArgStk* putArgStk) +{ + GenTreeFieldList* const fieldList = putArgStk->gtOp1->AsFieldList(); + assert(fieldList != nullptr); + + // Set m_pushStkArg and pre-adjust the stack if necessary. + const bool preAdjustedStack = genAdjustStackForPutArgStk(putArgStk); + // For now, we only support the "push" case; we will push a full slot for the first field of each slot + // within the struct. + assert((putArgStk->isPushKind()) && !preAdjustedStack && m_pushStkArg); + + // If we have pre-adjusted the stack and are simply storing the fields in order) set the offset to 0. + // (Note that this mode is not currently being used.) + // If we are pushing the arguments (i.e. we have not pre-adjusted the stack), then we are pushing them + // in reverse order, so we start with the current field offset at the size of the struct arg (which must be + // a multiple of the target pointer size). + unsigned currentOffset = (preAdjustedStack) ? 0 : putArgStk->getArgSize(); + unsigned prevFieldOffset = currentOffset; + regNumber tmpReg = REG_NA; + if (putArgStk->gtRsvdRegs != RBM_NONE) + { + assert(genCountBits(putArgStk->gtRsvdRegs) == 1); + tmpReg = genRegNumFromMask(putArgStk->gtRsvdRegs); + assert(genIsValidIntReg(tmpReg)); + } + for (GenTreeFieldList* current = fieldList; current != nullptr; current = current->Rest()) + { + GenTree* const fieldNode = current->Current(); + const unsigned fieldOffset = current->gtFieldOffset; + var_types fieldType = current->gtFieldType; + + // Long-typed nodes should have been handled by the decomposition pass, and lowering should have sorted the + // field list in descending order by offset. + assert(!varTypeIsLong(fieldType)); + assert(fieldOffset <= prevFieldOffset); + + // Consume the register, if any, for this field. Note that genConsumeRegs() will appropriately + // update the liveness info for a lclVar that has been marked RegOptional, which hasn't been + // assigned a register, and which is therefore contained. + // Unlike genConsumeReg(), it handles the case where no registers are being consumed. + genConsumeRegs(fieldNode); + regNumber argReg = fieldNode->isContainedSpillTemp() ? REG_NA : fieldNode->gtRegNum; + + // If the field is slot-like, we can use a push instruction to store the entire register no matter the type. + // + // The GC encoder requires that the stack remain 4-byte aligned at all times. Round the adjustment up + // to the next multiple of 4. If we are going to generate a `push` instruction, the adjustment must + // not require rounding. + // NOTE: if the field is of GC type, we must use a push instruction, since the emitter is not otherwise + // able to detect stores into the outgoing argument area of the stack on x86. + const bool fieldIsSlot = ((fieldOffset % 4) == 0) && ((prevFieldOffset - fieldOffset) >= 4); + int adjustment = roundUp(currentOffset - fieldOffset, 4); + if (fieldIsSlot) + { + fieldType = genActualType(fieldType); + unsigned pushSize = genTypeSize(fieldType); + assert((pushSize % 4) == 0); + adjustment -= pushSize; + while (adjustment != 0) + { + inst_IV(INS_push, 0); + currentOffset -= pushSize; + genStackLevel += pushSize; + adjustment -= pushSize; + } + m_pushStkArg = true; + } + else + { + m_pushStkArg = false; + // We always "push" floating point fields (i.e. they are full slot values that don't + // require special handling). + assert(varTypeIsIntegralOrI(fieldNode)); + // If we can't push this field, it needs to be in a register so that we can store + // it to the stack location. + assert(tmpReg != REG_NA); + if (adjustment != 0) + { + // This moves the stack pointer to fieldOffset. + // For this case, we must adjust the stack and generate stack-relative stores rather than pushes. + // Adjust the stack pointer to the next slot boundary. + inst_RV_IV(INS_sub, REG_SPBASE, adjustment, EA_PTRSIZE); + currentOffset -= adjustment; + genStackLevel += adjustment; + } + + // Does it need to be in a byte register? + // If so, we'll use tmpReg, which must have been allocated as a byte register. + // If it's already in a register, but not a byteable one, then move it. + if (varTypeIsByte(fieldType) && ((argReg == REG_NA) || ((genRegMask(argReg) & RBM_BYTE_REGS) == 0))) + { + noway_assert((genRegMask(tmpReg) & RBM_BYTE_REGS) != 0); + if (argReg != REG_NA) + { + inst_RV_RV(INS_mov, tmpReg, argReg, fieldType); + argReg = tmpReg; + } + } + } + + if (argReg == REG_NA) + { + if (m_pushStkArg) + { + if (fieldNode->isContainedSpillTemp()) + { + assert(fieldNode->IsRegOptional()); + TempDsc* tmp = getSpillTempDsc(fieldNode); + getEmitter()->emitIns_S(INS_push, emitActualTypeSize(fieldNode->TypeGet()), tmp->tdTempNum(), 0); + compiler->tmpRlsTemp(tmp); + } + else + { + assert(varTypeIsIntegralOrI(fieldNode)); + switch (fieldNode->OperGet()) + { + case GT_LCL_VAR: + inst_TT(INS_push, fieldNode, 0, 0, emitActualTypeSize(fieldNode->TypeGet())); + break; + case GT_CNS_INT: + if (fieldNode->IsIconHandle()) + { + inst_IV_handle(INS_push, fieldNode->gtIntCon.gtIconVal); + } + else + { + inst_IV(INS_push, fieldNode->gtIntCon.gtIconVal); + } + break; + default: + unreached(); + } + } + currentOffset -= TARGET_POINTER_SIZE; + genStackLevel += TARGET_POINTER_SIZE; + } + else + { + // The stack has been adjusted and we will load the field to tmpReg and then store it on the stack. + assert(varTypeIsIntegralOrI(fieldNode)); + switch (fieldNode->OperGet()) + { + case GT_LCL_VAR: + inst_RV_TT(INS_mov, tmpReg, fieldNode); + break; + case GT_CNS_INT: + genSetRegToConst(tmpReg, fieldNode->TypeGet(), fieldNode); + break; + default: + unreached(); + } + genStoreRegToStackArg(fieldType, tmpReg, fieldOffset - currentOffset); + } + } + else + { + genStoreRegToStackArg(fieldType, argReg, fieldOffset - currentOffset); + if (m_pushStkArg) + { + // We always push a slot-rounded size + currentOffset -= genTypeSize(fieldType); + } + } + + prevFieldOffset = fieldOffset; } - else + if (currentOffset != 0) { -#if FEATURE_FIXED_OUT_ARGS - baseVarNum = compiler->lvaOutgoingArgSpaceVar; -#else // !FEATURE_FIXED_OUT_ARGS - NYI_X86("Stack args for x86/RyuJIT"); - baseVarNum = BAD_VAR_NUM; -#endif // !FEATURE_FIXED_OUT_ARGS + // We don't expect padding at the beginning of a struct, but it could happen with explicit layout. + inst_RV_IV(INS_sub, REG_SPBASE, currentOffset, EA_PTRSIZE); + genStackLevel += currentOffset; } - - return baseVarNum; } +#endif // _TARGET_X86_ -//--------------------------------------------------------------------- // -// genPutStructArgStk - generate code for passing an arg on the stack. +//--------------------------------------------------------------------- +// genPutArgStk - generate code for passing an arg on the stack. // // Arguments // treeNode - the GT_PUTARG_STK node @@ -8631,25 +7756,39 @@ unsigned CodeGen::getBaseVarForPutArgStk(GenTreePtr treeNode) // Return value: // None // -void CodeGen::genPutArgStk(GenTreePtr treeNode) +void CodeGen::genPutArgStk(GenTreePutArgStk* putArgStk) { - var_types targetType = treeNode->TypeGet(); + var_types targetType = putArgStk->TypeGet(); + #ifdef _TARGET_X86_ - noway_assert(targetType != TYP_STRUCT); + +#ifdef FEATURE_SIMD + if (targetType == TYP_SIMD12) + { + genPutArgStkSIMD12(putArgStk); + return; + } +#endif // FEATURE_SIMD + + if (varTypeIsStruct(targetType)) + { + (void)genAdjustStackForPutArgStk(putArgStk); + genPutStructArgStk(putArgStk); + return; + } // The following logic is applicable for x86 arch. - assert(!varTypeIsFloating(targetType) || (targetType == treeNode->gtGetOp1()->TypeGet())); + assert(!varTypeIsFloating(targetType) || (targetType == putArgStk->gtOp1->TypeGet())); - GenTreePtr data = treeNode->gtOp.gtOp1; + GenTreePtr data = putArgStk->gtOp1; // On a 32-bit target, all of the long arguments have been decomposed into // a separate putarg_stk for each of the upper and lower halves. noway_assert(targetType != TYP_LONG); - int argSize = genTypeSize(genActualType(targetType)); - genStackLevel += argSize; + const unsigned argSize = putArgStk->getArgSize(); + assert((argSize % TARGET_POINTER_SIZE) == 0); - // TODO-Cleanup: Handle this in emitInsMov() in emitXArch.cpp? if (data->isContainedIntOrIImmed()) { if (data->IsIconHandle()) @@ -8660,53 +7799,50 @@ void CodeGen::genPutArgStk(GenTreePtr treeNode) { inst_IV(INS_push, data->gtIntCon.gtIconVal); } + genStackLevel += argSize; } - else if (data->isContained()) + else if (data->OperGet() == GT_FIELD_LIST) { - NYI_X86("Contained putarg_stk of non-constant"); + genPutArgStkFieldList(putArgStk); } else { + // We should not see any contained nodes that are not immediates. + assert(!data->isContained()); genConsumeReg(data); - if (varTypeIsIntegralOrI(targetType)) - { - inst_RV(INS_push, data->gtRegNum, targetType); - } - else - { - // Decrement SP. - inst_RV_IV(INS_sub, REG_SPBASE, argSize, emitActualTypeSize(TYP_I_IMPL)); - getEmitter()->emitIns_AR_R(ins_Store(targetType), emitTypeSize(targetType), data->gtRegNum, REG_SPBASE, 0); - } + genPushReg(targetType, data->gtRegNum); } #else // !_TARGET_X86_ { - unsigned baseVarNum = getBaseVarForPutArgStk(treeNode); + unsigned baseVarNum = getBaseVarForPutArgStk(putArgStk); #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING if (varTypeIsStruct(targetType)) { - genPutStructArgStk(treeNode, baseVarNum); + m_stkArgVarNum = baseVarNum; + m_stkArgOffset = putArgStk->getArgOffset(); + genPutStructArgStk(putArgStk); + m_stkArgVarNum = BAD_VAR_NUM; return; } #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING noway_assert(targetType != TYP_STRUCT); - assert(!varTypeIsFloating(targetType) || (targetType == treeNode->gtGetOp1()->TypeGet())); + assert(!varTypeIsFloating(targetType) || (targetType == putArgStk->gtOp1->TypeGet())); // Get argument offset on stack. // Here we cross check that argument offset hasn't changed from lowering to codegen since // we are storing arg slot number in GT_PUTARG_STK node in lowering phase. - int argOffset = treeNode->AsPutArgStk()->getArgOffset(); + int argOffset = putArgStk->getArgOffset(); #ifdef DEBUG - fgArgTabEntryPtr curArgTabEntry = compiler->gtArgEntryByNode(treeNode->AsPutArgStk()->gtCall, treeNode); + fgArgTabEntryPtr curArgTabEntry = compiler->gtArgEntryByNode(putArgStk->gtCall, putArgStk); assert(curArgTabEntry); assert(argOffset == (int)curArgTabEntry->slotNum * TARGET_POINTER_SIZE); #endif - GenTreePtr data = treeNode->gtGetOp1(); + GenTreePtr data = putArgStk->gtOp1; if (data->isContained()) { @@ -8723,7 +7859,125 @@ void CodeGen::genPutArgStk(GenTreePtr treeNode) #endif // !_TARGET_X86_ } -#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) +#ifdef _TARGET_X86_ +// genPushReg: Push a register value onto the stack and adjust the stack level +// +// Arguments: +// type - the type of value to be stored +// reg - the register containing the value +// +// Notes: +// For TYP_LONG, the srcReg must be a floating point register. +// Otherwise, the register type must be consistent with the given type. +// +void CodeGen::genPushReg(var_types type, regNumber srcReg) +{ + unsigned size = genTypeSize(type); + if (varTypeIsIntegralOrI(type) && type != TYP_LONG) + { + assert(genIsValidIntReg(srcReg)); + inst_RV(INS_push, srcReg, type); + } + else + { + instruction ins; + emitAttr attr = emitTypeSize(type); + if (type == TYP_LONG) + { + // On x86, the only way we can push a TYP_LONG from a register is if it is in an xmm reg. + // This is only used when we are pushing a struct from memory to memory, and basically is + // handling an 8-byte "chunk", as opposed to strictly a long type. + ins = INS_movq; + } + else + { + ins = ins_Store(type); + } + assert(genIsValidFloatReg(srcReg)); + inst_RV_IV(INS_sub, REG_SPBASE, size, EA_PTRSIZE); + getEmitter()->emitIns_AR_R(ins, attr, srcReg, REG_SPBASE, 0); + } + genStackLevel += size; +} +#endif // _TARGET_X86_ + +#if defined(FEATURE_PUT_STRUCT_ARG_STK) +// genStoreRegToStackArg: Store a register value into the stack argument area +// +// Arguments: +// type - the type of value to be stored +// reg - the register containing the value +// offset - the offset from the base (see Assumptions below) +// +// Notes: +// A type of TYP_STRUCT instructs this method to store a 16-byte chunk +// at the given offset (i.e. not the full struct). +// +// Assumptions: +// The caller must set the context appropriately before calling this method: +// - On x64, m_stkArgVarNum must be set according to whether this is a regular or tail call. +// - On x86, the caller must set m_pushStkArg if this method should push the argument. +// Otherwise, the argument is stored at the given offset from sp. +// +// TODO: In the below code the load and store instructions are for 16 bytes, but the +// type is EA_8BYTE. The movdqa/u are 16 byte instructions, so it works, but +// this probably needs to be changed. +// +void CodeGen::genStoreRegToStackArg(var_types type, regNumber srcReg, int offset) +{ + assert(srcReg != REG_NA); + instruction ins; + emitAttr attr; + unsigned size; + + if (type == TYP_STRUCT) + { + ins = INS_movdqu; + // This should be changed! + attr = EA_8BYTE; + size = 16; + } + else + { +#ifdef FEATURE_SIMD + if (varTypeIsSIMD(type)) + { + assert(genIsValidFloatReg(srcReg)); + ins = ins_Store(type); // TODO-CQ: pass 'aligned' correctly + } + else +#endif // FEATURE_SIMD +#ifdef _TARGET_X86_ + if (type == TYP_LONG) + { + assert(genIsValidFloatReg(srcReg)); + ins = INS_movq; + } + else +#endif // _TARGET_X86_ + { + assert((varTypeIsFloating(type) && genIsValidFloatReg(srcReg)) || + (varTypeIsIntegralOrI(type) && genIsValidIntReg(srcReg))); + ins = ins_Store(type); + } + attr = emitTypeSize(type); + size = genTypeSize(type); + } + +#ifdef _TARGET_X86_ + if (m_pushStkArg) + { + genPushReg(type, srcReg); + } + else + { + getEmitter()->emitIns_AR_R(ins, attr, srcReg, REG_SPBASE, offset); + } +#else // !_TARGET_X86_ + assert(m_stkArgVarNum != BAD_VAR_NUM); + getEmitter()->emitIns_S_R(ins, attr, srcReg, m_stkArgVarNum, m_stkArgOffset + offset); +#endif // !_TARGET_X86_ +} //--------------------------------------------------------------------- // genPutStructArgStk - generate code for copying a struct arg on the stack by value. @@ -8731,42 +7985,39 @@ void CodeGen::genPutArgStk(GenTreePtr treeNode) // it generates the gcinfo as well. // // Arguments -// treeNode - the GT_PUTARG_STK node -// baseVarNum - the variable number relative to which to put the argument on the stack. -// For tail calls this is the baseVarNum = 0. -// For non tail calls this is the outgoingArgSpace. +// putArgStk - the GT_PUTARG_STK node // -// Return value: -// None -// -void CodeGen::genPutStructArgStk(GenTreePtr treeNode, unsigned baseVarNum) +// Notes: +// In the case of fixed out args, the caller must have set m_stkArgVarNum to the variable number +// corresponding to the argument area (where we will put the argument on the stack). +// For tail calls this is the baseVarNum = 0. +// For non tail calls this is the outgoingArgSpace. +void CodeGen::genPutStructArgStk(GenTreePutArgStk* putArgStk) { - assert(treeNode->OperGet() == GT_PUTARG_STK); - assert(baseVarNum != BAD_VAR_NUM); - - var_types targetType = treeNode->TypeGet(); + var_types targetType = putArgStk->TypeGet(); if (varTypeIsSIMD(targetType)) { - regNumber srcReg = genConsumeReg(treeNode->gtGetOp1()); + regNumber srcReg = genConsumeReg(putArgStk->gtGetOp1()); assert((srcReg != REG_NA) && (genIsValidFloatReg(srcReg))); - getEmitter()->emitIns_S_R(ins_Store(targetType), emitTypeSize(targetType), srcReg, baseVarNum, - treeNode->AsPutArgStk()->getArgOffset()); + genStoreRegToStackArg(targetType, srcReg, 0); return; } assert(targetType == TYP_STRUCT); - GenTreePutArgStk* putArgStk = treeNode->AsPutArgStk(); if (putArgStk->gtNumberReferenceSlots == 0) { switch (putArgStk->gtPutArgStkKind) { - case GenTreePutArgStk::PutArgStkKindRepInstr: - genStructPutArgRepMovs(putArgStk, baseVarNum); + case GenTreePutArgStk::Kind::RepInstr: + genStructPutArgRepMovs(putArgStk); + break; + case GenTreePutArgStk::Kind::Unroll: + genStructPutArgUnroll(putArgStk); break; - case GenTreePutArgStk::PutArgStkKindUnroll: - genStructPutArgUnroll(putArgStk, baseVarNum); + case GenTreePutArgStk::Kind::Push: + genStructPutArgUnroll(putArgStk); break; default: unreached(); @@ -8775,108 +8026,150 @@ void CodeGen::genPutStructArgStk(GenTreePtr treeNode, unsigned baseVarNum) else { // No need to disable GC the way COPYOBJ does. Here the refs are copied in atomic operations always. + CLANG_FORMAT_COMMENT_ANCHOR; - // Consume these registers. - // They may now contain gc pointers (depending on their type; gcMarkRegPtrVal will "do the right thing"). - genConsumePutStructArgStk(putArgStk, REG_RDI, REG_RSI, REG_NA, baseVarNum); - GenTreePtr dstAddr = putArgStk; - GenTreePtr src = putArgStk->gtOp.gtOp1; - assert(src->OperGet() == GT_OBJ); - GenTreePtr srcAddr = src->gtGetOp1(); +#ifdef _TARGET_X86_ + // On x86, any struct that has contains GC references must be stored to the stack using `push` instructions so + // that the emitter properly detects the need to update the method's GC information. + // + // Strictly speaking, it is only necessary to use `push` to store the GC references themselves, so for structs + // with large numbers of consecutive non-GC-ref-typed fields, we may be able to improve the code size in the + // future. + assert(m_pushStkArg); - unsigned slots = putArgStk->gtNumSlots; + GenTree* srcAddr = putArgStk->gtGetOp1()->gtGetOp1(); + BYTE* gcPtrs = putArgStk->gtGcPtrs; + const unsigned numSlots = putArgStk->gtNumSlots; - // We are always on the stack we don't need to use the write barrier. - BYTE* gcPtrs = putArgStk->gtGcPtrs; - unsigned gcPtrCount = putArgStk->gtNumberReferenceSlots; + regNumber srcRegNum = srcAddr->gtRegNum; + const bool srcAddrInReg = srcRegNum != REG_NA; - unsigned i = 0; - unsigned copiedSlots = 0; - while (i < slots) + unsigned srcLclNum = 0; + unsigned srcLclOffset = 0; + if (srcAddrInReg) { - switch (gcPtrs[i]) + genConsumeReg(srcAddr); + } + else + { + assert(srcAddr->OperIsLocalAddr()); + + srcLclNum = srcAddr->AsLclVarCommon()->gtLclNum; + if (srcAddr->OperGet() == GT_LCL_FLD_ADDR) { - case TYPE_GC_NONE: - // Let's see if we can use rep movsq instead of a sequence of movsq instructions - // to save cycles and code size. - { - unsigned nonGcSlotCount = 0; + srcLclOffset = srcAddr->AsLclFld()->gtLclOffs; + } + } - do - { - nonGcSlotCount++; - i++; - } while (i < slots && gcPtrs[i] == TYPE_GC_NONE); + for (int i = numSlots - 1; i >= 0; --i) + { + emitAttr slotAttr; + if (gcPtrs[i] == TYPE_GC_NONE) + { + slotAttr = EA_4BYTE; + } + else if (gcPtrs[i] == TYPE_GC_REF) + { + slotAttr = EA_GCREF; + } + else + { + assert(gcPtrs[i] == TYPE_GC_BYREF); + slotAttr = EA_BYREF; + } - // If we have a very small contiguous non-gc region, it's better just to - // emit a sequence of movsq instructions - if (nonGcSlotCount < CPOBJ_NONGC_SLOTS_LIMIT) - { - copiedSlots += nonGcSlotCount; - while (nonGcSlotCount > 0) - { - instGen(INS_movsq); - nonGcSlotCount--; - } - } - else - { - getEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, REG_RCX, nonGcSlotCount); - copiedSlots += nonGcSlotCount; - instGen(INS_r_movsq); - } - } - break; + const unsigned offset = i * 4; + if (srcAddrInReg) + { + getEmitter()->emitIns_AR_R(INS_push, slotAttr, REG_NA, srcRegNum, offset); + } + else + { + getEmitter()->emitIns_S(INS_push, slotAttr, srcLclNum, srcLclOffset + offset); + } + genStackLevel += 4; + } +#else // !defined(_TARGET_X86_) + + // Consume these registers. + // They may now contain gc pointers (depending on their type; gcMarkRegPtrVal will "do the right thing"). + genConsumePutStructArgStk(putArgStk, REG_RDI, REG_RSI, REG_NA); + + const bool srcIsLocal = putArgStk->gtOp1->AsObj()->gtOp1->OperIsLocalAddr(); + const emitAttr srcAddrAttr = srcIsLocal ? EA_PTRSIZE : EA_BYREF; - case TYPE_GC_REF: // Is an object ref - case TYPE_GC_BYREF: // Is an interior pointer - promote it but don't scan it +#if DEBUG + unsigned numGCSlotsCopied = 0; +#endif // DEBUG + + BYTE* gcPtrs = putArgStk->gtGcPtrs; + const unsigned numSlots = putArgStk->gtNumSlots; + for (unsigned i = 0; i < numSlots;) + { + if (gcPtrs[i] == TYPE_GC_NONE) + { + // Let's see if we can use rep movsp (alias for movsd or movsq for 32 and 64 bits respectively) + // instead of a sequence of movsp instructions to save cycles and code size. + unsigned adjacentNonGCSlotCount = 0; + do { - // We have a GC (byref or ref) pointer - // TODO-Amd64-Unix: Here a better solution (for code size and CQ) would be to use movsq instruction, - // but the logic for emitting a GC info record is not available (it is internal for the emitter - // only.) See emitGCVarLiveUpd function. If we could call it separately, we could do - // instGen(INS_movsq); and emission of gc info. - - var_types memType; - if (gcPtrs[i] == TYPE_GC_REF) - { - memType = TYP_REF; - } - else + adjacentNonGCSlotCount++; + i++; + } while ((i < numSlots) && (gcPtrs[i] == TYPE_GC_NONE)); + + // If we have a very small contiguous non-ref region, it's better just to + // emit a sequence of movsp instructions + if (adjacentNonGCSlotCount < CPOBJ_NONGC_SLOTS_LIMIT) + { + for (; adjacentNonGCSlotCount > 0; adjacentNonGCSlotCount--) { - assert(gcPtrs[i] == TYPE_GC_BYREF); - memType = TYP_BYREF; + instGen(INS_movsp); } + } + else + { + getEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, REG_RCX, adjacentNonGCSlotCount); + instGen(INS_r_movsp); + } + } + else + { + assert((gcPtrs[i] == TYPE_GC_REF) || (gcPtrs[i] == TYPE_GC_BYREF)); + + // We have a GC (byref or ref) pointer + // TODO-Amd64-Unix: Here a better solution (for code size and CQ) would be to use movsp instruction, + // but the logic for emitting a GC info record is not available (it is internal for the emitter + // only.) See emitGCVarLiveUpd function. If we could call it separately, we could do + // instGen(INS_movsp); and emission of gc info. + + var_types memType = (gcPtrs[i] == TYPE_GC_REF) ? TYP_REF : TYP_BYREF; + getEmitter()->emitIns_R_AR(ins_Load(memType), emitTypeSize(memType), REG_RCX, REG_RSI, 0); + genStoreRegToStackArg(memType, REG_RCX, i * TARGET_POINTER_SIZE); - getEmitter()->emitIns_R_AR(ins_Load(memType), emitTypeSize(memType), REG_RCX, REG_RSI, 0); - getEmitter()->emitIns_S_R(ins_Store(memType), emitTypeSize(memType), REG_RCX, baseVarNum, - ((copiedSlots + putArgStk->gtSlotNum) * TARGET_POINTER_SIZE)); +#ifdef DEBUG + numGCSlotsCopied++; +#endif // DEBUG + i++; + if (i < numSlots) + { // Source for the copy operation. // If a LocalAddr, use EA_PTRSIZE - copy from stack. // If not a LocalAddr, use EA_BYREF - the source location is not on the stack. - getEmitter()->emitIns_R_I(INS_add, ((src->OperIsLocalAddr()) ? EA_PTRSIZE : EA_BYREF), REG_RSI, - TARGET_POINTER_SIZE); + getEmitter()->emitIns_R_I(INS_add, srcAddrAttr, REG_RSI, TARGET_POINTER_SIZE); // Always copying to the stack - outgoing arg area // (or the outgoing arg area of the caller for a tail call) - use EA_PTRSIZE. getEmitter()->emitIns_R_I(INS_add, EA_PTRSIZE, REG_RDI, TARGET_POINTER_SIZE); - copiedSlots++; - gcPtrCount--; - i++; } - break; - - default: - unreached(); - break; } } - assert(gcPtrCount == 0); + assert(numGCSlotsCopied == putArgStk->gtNumberReferenceSlots); +#endif // _TARGET_X86_ } } -#endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) +#endif // defined(FEATURE_PUT_STRUCT_ARG_STK) /***************************************************************************** * @@ -9043,7 +8336,7 @@ void* CodeGen::genCreateAndStoreGCInfoJIT32(unsigned codeSize, return infoPtr; } -#else // !JIT32_GCENCODER +#else // !JIT32_GCENCODER void CodeGen::genCreateAndStoreGCInfoX64(unsigned codeSize, unsigned prologSize DEBUGARG(void* codePtr)) { IAllocator* allowZeroAlloc = new (compiler, CMK_GC) AllowZeroAllocator(compiler->getAllocatorGC()); @@ -9061,7 +8354,6 @@ void CodeGen::genCreateAndStoreGCInfoX64(unsigned codeSize, unsigned prologSize // Now we can actually use those slot ID's to declare live ranges. gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_DO_WORK); -#if defined(DEBUGGING_SUPPORT) if (compiler->opts.compDbgEnC) { // what we have to preserve is called the "frame header" (see comments in VM\eetwain.cpp) @@ -9088,7 +8380,6 @@ void CodeGen::genCreateAndStoreGCInfoX64(unsigned codeSize, unsigned prologSize // frame gcInfoEncoder->SetSizeOfEditAndContinuePreservedArea(preservedAreaSize); } -#endif gcInfoEncoder->Build(); @@ -9203,18 +8494,33 @@ void CodeGen::genStoreLongLclVar(GenTree* treeNode) assert(varDsc->TypeGet() == TYP_LONG); assert(!varDsc->lvPromoted); GenTreePtr op1 = treeNode->gtOp.gtOp1; - noway_assert(op1->OperGet() == GT_LONG); + noway_assert(op1->OperGet() == GT_LONG || op1->OperGet() == GT_MUL_LONG); genConsumeRegs(op1); - // Definitions of register candidates will have been lowered to 2 int lclVars. - assert(!treeNode->InReg()); + if (op1->OperGet() == GT_LONG) + { + // Definitions of register candidates will have been lowered to 2 int lclVars. + assert(!treeNode->InReg()); + + GenTreePtr loVal = op1->gtGetOp1(); + GenTreePtr hiVal = op1->gtGetOp2(); + + // NYI: Contained immediates. + NYI_IF((loVal->gtRegNum == REG_NA) || (hiVal->gtRegNum == REG_NA), + "Store of long lclVar with contained immediate"); + + emit->emitIns_S_R(ins_Store(TYP_INT), EA_4BYTE, loVal->gtRegNum, lclNum, 0); + emit->emitIns_S_R(ins_Store(TYP_INT), EA_4BYTE, hiVal->gtRegNum, lclNum, genTypeSize(TYP_INT)); + } + else if (op1->OperGet() == GT_MUL_LONG) + { + assert((op1->gtFlags & GTF_MUL_64RSLT) != 0); - GenTreePtr loVal = op1->gtGetOp1(); - GenTreePtr hiVal = op1->gtGetOp2(); - // NYI: Contained immediates. - NYI_IF((loVal->gtRegNum == REG_NA) || (hiVal->gtRegNum == REG_NA), "Store of long lclVar with contained immediate"); - emit->emitIns_R_S(ins_Store(TYP_INT), EA_4BYTE, loVal->gtRegNum, lclNum, 0); - emit->emitIns_R_S(ins_Store(TYP_INT), EA_4BYTE, hiVal->gtRegNum, lclNum, genTypeSize(TYP_INT)); + // Stack store + getEmitter()->emitIns_S_R(ins_Store(TYP_INT), emitTypeSize(TYP_INT), REG_LNGRET_LO, lclNum, 0); + getEmitter()->emitIns_S_R(ins_Store(TYP_INT), emitTypeSize(TYP_INT), REG_LNGRET_HI, lclNum, + genTypeSize(TYP_INT)); + } } #endif // !defined(_TARGET_64BIT_) @@ -9332,57 +8638,6 @@ void CodeGen::genAmd64EmitterUnitTests() #endif // defined(DEBUG) && defined(LATE_DISASM) && defined(_TARGET_AMD64_) -/*****************************************************************************/ -#ifdef DEBUGGING_SUPPORT -/***************************************************************************** - * genSetScopeInfo - * - * Called for every scope info piece to record by the main genSetScopeInfo() - */ - -void CodeGen::genSetScopeInfo(unsigned which, - UNATIVE_OFFSET startOffs, - UNATIVE_OFFSET length, - unsigned varNum, - unsigned LVnum, - bool avail, - Compiler::siVarLoc& varLoc) -{ - /* We need to do some mapping while reporting back these variables */ - - unsigned ilVarNum = compiler->compMap2ILvarNum(varNum); - noway_assert((int)ilVarNum != ICorDebugInfo::UNKNOWN_ILNUM); - - VarName name = nullptr; - -#ifdef DEBUG - - for (unsigned scopeNum = 0; scopeNum < compiler->info.compVarScopesCount; scopeNum++) - { - if (LVnum == compiler->info.compVarScopes[scopeNum].vsdLVnum) - { - name = compiler->info.compVarScopes[scopeNum].vsdName; - } - } - - // Hang on to this compiler->info. - - TrnslLocalVarInfo& tlvi = genTrnslLocalVarInfo[which]; - - tlvi.tlviVarNum = ilVarNum; - tlvi.tlviLVnum = LVnum; - tlvi.tlviName = name; - tlvi.tlviStartPC = startOffs; - tlvi.tlviLength = length; - tlvi.tlviAvailable = avail; - tlvi.tlviVarLoc = varLoc; - -#endif // DEBUG - - compiler->eeSetLVinfo(which, startOffs, length, ilVarNum, LVnum, name, avail, varLoc); -} -#endif // DEBUGGING_SUPPORT - #endif // _TARGET_AMD64_ #endif // !LEGACY_BACKEND diff --git a/src/ToolBox/.gitmirror b/src/jit/compatjit/.gitmirror similarity index 100% rename from src/ToolBox/.gitmirror rename to src/jit/compatjit/.gitmirror diff --git a/src/jit/compatjit/CMakeLists.txt b/src/jit/compatjit/CMakeLists.txt new file mode 100644 index 0000000..1e0615e --- /dev/null +++ b/src/jit/compatjit/CMakeLists.txt @@ -0,0 +1,66 @@ +project(compatjit) + +# This compatjit.dll is only built if we are not building JIT32 as compatjit.dll. +# It is the same build as legacyjit.dll, just with a different name, and not +# built as an altjit. + +add_definitions(-DLEGACY_BACKEND) + +add_definitions(-DFEATURE_NO_HOST) +add_definitions(-DSELF_NO_HOST) +add_definitions(-DFEATURE_READYTORUN_COMPILER) +remove_definitions(-DFEATURE_MERGE_JIT_AND_ENGINE) + +# No SIMD in legacy back-end. +remove_definitions(-DFEATURE_SIMD) +remove_definitions(-DFEATURE_AVX_SUPPORT) + +if(WIN32) + add_definitions(-DFX_VER_INTERNALNAME_STR=compatjit.dll) +endif(WIN32) + +add_library_clr(compatjit + SHARED + ${SHARED_LIB_SOURCES} +) + +add_dependencies(compatjit jit_exports) + +set_property(TARGET compatjit APPEND_STRING PROPERTY LINK_FLAGS ${JIT_EXPORTS_LINKER_OPTION}) +set_property(TARGET compatjit APPEND_STRING PROPERTY LINK_DEPENDS ${JIT_EXPORTS_FILE}) + +set(RYUJIT_LINK_LIBRARIES + utilcodestaticnohost + gcinfo +) + +if(CLR_CMAKE_PLATFORM_UNIX) + list(APPEND RYUJIT_LINK_LIBRARIES + mscorrc_debug + coreclrpal + palrt + ) +else() + list(APPEND RYUJIT_LINK_LIBRARIES + ${STATIC_MT_CRT_LIB} + ${STATIC_MT_VCRT_LIB} + kernel32.lib + advapi32.lib + ole32.lib + oleaut32.lib + uuid.lib + user32.lib + version.lib + shlwapi.lib + bcrypt.lib + crypt32.lib + RuntimeObject.lib + ) +endif(CLR_CMAKE_PLATFORM_UNIX) + +target_link_libraries(compatjit + ${RYUJIT_LINK_LIBRARIES} +) + +# add the install targets +install_clr(compatjit) diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp index afbecdf..114847c 100644 --- a/src/jit/compiler.cpp +++ b/src/jit/compiler.cpp @@ -48,6 +48,60 @@ bool Compiler::s_pAltJitExcludeAssembliesListInitialized = false; AssemblyNamesList2* Compiler::s_pAltJitExcludeAssembliesList = nullptr; #endif // ALT_JIT +/***************************************************************************** + * + * Little helpers to grab the current cycle counter value; this is done + * differently based on target architecture, host toolchain, etc. The + * main thing is to keep the overhead absolutely minimal; in fact, on + * x86/x64 we use RDTSC even though it's not thread-safe; GetThreadCycles + * (which is monotonous) is just too expensive. + */ +#ifdef FEATURE_JIT_METHOD_PERF + +#if defined(_HOST_X86_) || defined(_HOST_AMD64_) + +#if defined(_MSC_VER) + +#include +inline bool _our_GetThreadCycles(unsigned __int64* cycleOut) +{ + *cycleOut = __rdtsc(); + return true; +} + +#elif defined(__clang__) + +inline bool _our_GetThreadCycles(unsigned __int64* cycleOut) +{ + uint64_t cycles; + asm volatile("rdtsc" : "=A"(cycles)); + *cycleOut = cycles; + return true; +} + +#else // neither _MSC_VER nor __clang__ + +// The following *might* work - might as well try. +#define _our_GetThreadCycles(cp) GetThreadCycles(cp) + +#endif + +#elif defined(_HOST_ARM_) || defined(_HOST_ARM64_) + +// If this doesn't work please see ../gc/gc.cpp for additional ARM +// info (and possible solutions). +#define _our_GetThreadCycles(cp) GetThreadCycles(cp) + +#else // not x86/x64 and not ARM + +// Don't know what this target is, but let's give it a try; if +// someone really wants to make this work, please add the right +// code here. +#define _our_GetThreadCycles(cp) GetThreadCycles(cp) + +#endif // which host OS + +#endif // FEATURE_JIT_METHOD_PERF /*****************************************************************************/ inline unsigned getCurTime() { @@ -147,8 +201,6 @@ void Compiler::compDspSrcLinesByLineNum(unsigned line, bool seek) void Compiler::compDspSrcLinesByNativeIP(UNATIVE_OFFSET curIP) { -#ifdef DEBUGGING_SUPPORT - static IPmappingDsc* nextMappingDsc; static unsigned lastLine; @@ -203,8 +255,6 @@ void Compiler::compDspSrcLinesByNativeIP(UNATIVE_OFFSET curIP) nextMappingDsc = nextMappingDsc->ipmdNext; } } - -#endif } /*****************************************************************************/ @@ -232,6 +282,15 @@ unsigned genTreeNsizHistBuckets[] = {1000, 5000, 10000, 50000, 100000, 500000, Histogram genTreeNsizHist(HostAllocator::getHostAllocator(), genTreeNsizHistBuckets); #endif // MEASURE_NODE_SIZE +/*****************************************************************************/ +#if MEASURE_MEM_ALLOC + +unsigned memSizeHistBuckets[] = {20, 50, 75, 100, 150, 250, 500, 1000, 5000, 0}; +Histogram memAllocHist(HostAllocator::getHostAllocator(), memSizeHistBuckets); +Histogram memUsedHist(HostAllocator::getHostAllocator(), memSizeHistBuckets); + +#endif // MEASURE_MEM_ALLOC + /***************************************************************************** * * Variables to keep track of total code amounts. @@ -475,7 +534,7 @@ bool Compiler::isSingleFloat32Struct(CORINFO_CLASS_HANDLE clsHnd) for (;;) { // all of class chain must be of value type and must have only one field - if (!info.compCompHnd->isValueClass(clsHnd) && info.compCompHnd->getClassNumInstanceFields(clsHnd) != 1) + if (!info.compCompHnd->isValueClass(clsHnd) || info.compCompHnd->getClassNumInstanceFields(clsHnd) != 1) { return false; } @@ -1101,14 +1160,11 @@ size_t genFlowNodeCnt; #ifdef DEBUG /* static */ unsigned Compiler::s_compMethodsCount = 0; // to produce unique label names - -/* static */ -bool Compiler::s_dspMemStats = false; #endif -#ifndef DEBUGGING_SUPPORT +#if MEASURE_MEM_ALLOC /* static */ -const bool Compiler::Options::compDbgCode = false; +bool Compiler::s_dspMemStats = false; #endif #ifndef PROFILING_SUPPORTED @@ -1184,18 +1240,22 @@ void Compiler::compShutdown() } #endif +#if NODEBASH_STATS + GenTree::ReportOperBashing(jitstdout); +#endif + // Where should we write our statistics output? FILE* fout = jitstdout; #ifdef FEATURE_JIT_METHOD_PERF - if (compJitTimeLogFilename != NULL) + if (compJitTimeLogFilename != nullptr) { - // I assume that this will return NULL if it fails for some reason, and - // that... FILE* jitTimeLogFile = _wfopen(compJitTimeLogFilename, W("a")); - // ...Print will return silently with a NULL argument. - CompTimeSummaryInfo::s_compTimeSummary.Print(jitTimeLogFile); - fclose(jitTimeLogFile); + if (jitTimeLogFile != nullptr) + { + CompTimeSummaryInfo::s_compTimeSummary.Print(jitTimeLogFile); + fclose(jitTimeLogFile); + } } #endif // FEATURE_JIT_METHOD_PERF @@ -1214,6 +1274,63 @@ void Compiler::compShutdown() } #endif // COUNT_RANGECHECKS +#if COUNT_AST_OPERS + + // Add up all the counts so that we can show percentages of total + unsigned gtc = 0; + for (unsigned op = 0; op < GT_COUNT; op++) + gtc += GenTree::s_gtNodeCounts[op]; + + if (gtc > 0) + { + unsigned rem_total = gtc; + unsigned rem_large = 0; + unsigned rem_small = 0; + + unsigned tot_large = 0; + unsigned tot_small = 0; + + fprintf(fout, "\nGenTree operator counts (approximate):\n\n"); + + for (unsigned op = 0; op < GT_COUNT; op++) + { + unsigned siz = GenTree::s_gtTrueSizes[op]; + unsigned cnt = GenTree::s_gtNodeCounts[op]; + double pct = 100.0 * cnt / gtc; + + if (siz > TREE_NODE_SZ_SMALL) + tot_large += cnt; + else + tot_small += cnt; + + // Let's not show anything below a threshold + if (pct >= 0.5) + { + fprintf(fout, " GT_%-17s %7u (%4.1lf%%) %3u bytes each\n", GenTree::OpName((genTreeOps)op), cnt, + pct, siz); + rem_total -= cnt; + } + else + { + if (siz > TREE_NODE_SZ_SMALL) + rem_large += cnt; + else + rem_small += cnt; + } + } + if (rem_total > 0) + { + fprintf(fout, " All other GT_xxx ... %7u (%4.1lf%%) ... %4.1lf%% small + %4.1lf%% large\n", rem_total, + 100.0 * rem_total / gtc, 100.0 * rem_small / gtc, 100.0 * rem_large / gtc); + } + fprintf(fout, " -----------------------------------------------------\n"); + fprintf(fout, " Total ....... %11u --ALL-- ... %4.1lf%% small + %4.1lf%% large\n", gtc, + 100.0 * tot_small / gtc, 100.0 * tot_large / gtc); + fprintf(fout, "\n"); + } + +#endif // COUNT_AST_OPERS + #if DISPLAY_SIZES if (grossVMsize && grossNCsize) @@ -1367,17 +1484,23 @@ void Compiler::compShutdown() #if MEASURE_MEM_ALLOC -#ifdef DEBUG - // Under debug, we only dump memory stats when the COMPlus_* variable is defined. - // Under non-debug, we don't have the COMPlus_* variable, and we always dump it. if (s_dspMemStats) -#endif { fprintf(fout, "\nAll allocations:\n"); s_aggMemStats.Print(jitstdout); fprintf(fout, "\nLargest method:\n"); s_maxCompMemStats.Print(jitstdout); + + fprintf(fout, "\n"); + fprintf(fout, "---------------------------------------------------\n"); + fprintf(fout, "Distribution of total memory allocated per method (in KB):\n"); + memAllocHist.dump(fout); + + fprintf(fout, "\n"); + fprintf(fout, "---------------------------------------------------\n"); + fprintf(fout, "Distribution of total memory used per method (in KB):\n"); + memUsedHist.dump(fout); } #endif // MEASURE_MEM_ALLOC @@ -1452,100 +1575,8 @@ void Compiler::compDisplayStaticSizes(FILE* fout) { #if MEASURE_NODE_SIZE - /* - IMPORTANT: Use the following code to check the alignment of - GenTree members (in a retail build, of course). - */ - - GenTree* gtDummy = nullptr; - - fprintf(fout, "\n"); - fprintf(fout, "Offset / size of gtOper = %2u / %2u\n", offsetof(GenTree, gtOper), sizeof(gtDummy->gtOper)); - fprintf(fout, "Offset / size of gtType = %2u / %2u\n", offsetof(GenTree, gtType), sizeof(gtDummy->gtType)); -#if FEATURE_ANYCSE - fprintf(fout, "Offset / size of gtCSEnum = %2u / %2u\n", offsetof(GenTree, gtCSEnum), - sizeof(gtDummy->gtCSEnum)); -#endif // FEATURE_ANYCSE -#if ASSERTION_PROP - fprintf(fout, "Offset / size of gtAssertionNum = %2u / %2u\n", offsetof(GenTree, gtAssertionNum), - sizeof(gtDummy->gtAssertionNum)); -#endif // ASSERTION_PROP -#if FEATURE_STACK_FP_X87 - fprintf(fout, "Offset / size of gtFPlvl = %2u / %2u\n", offsetof(GenTree, gtFPlvl), - sizeof(gtDummy->gtFPlvl)); -#endif // FEATURE_STACK_FP_X87 - // TODO: The section that report GenTree sizes should be made into a public static member function of the GenTree - // class (see https://github.com/dotnet/coreclr/pull/493) - // fprintf(fout, "Offset / size of gtCostEx = %2u / %2u\n", offsetof(GenTree, _gtCostEx ), - // sizeof(gtDummy->_gtCostEx )); - // fprintf(fout, "Offset / size of gtCostSz = %2u / %2u\n", offsetof(GenTree, _gtCostSz ), - // sizeof(gtDummy->_gtCostSz )); - fprintf(fout, "Offset / size of gtFlags = %2u / %2u\n", offsetof(GenTree, gtFlags), - sizeof(gtDummy->gtFlags)); - fprintf(fout, "Offset / size of gtVNPair = %2u / %2u\n", offsetof(GenTree, gtVNPair), - sizeof(gtDummy->gtVNPair)); - fprintf(fout, "Offset / size of gtRsvdRegs = %2u / %2u\n", offsetof(GenTree, gtRsvdRegs), - sizeof(gtDummy->gtRsvdRegs)); -#ifdef LEGACY_BACKEND - fprintf(fout, "Offset / size of gtUsedRegs = %2u / %2u\n", offsetof(GenTree, gtUsedRegs), - sizeof(gtDummy->gtUsedRegs)); -#endif // LEGACY_BACKEND -#ifndef LEGACY_BACKEND - fprintf(fout, "Offset / size of gtLsraInfo = %2u / %2u\n", offsetof(GenTree, gtLsraInfo), - sizeof(gtDummy->gtLsraInfo)); -#endif // !LEGACY_BACKEND - fprintf(fout, "Offset / size of gtNext = %2u / %2u\n", offsetof(GenTree, gtNext), sizeof(gtDummy->gtNext)); - fprintf(fout, "Offset / size of gtPrev = %2u / %2u\n", offsetof(GenTree, gtPrev), sizeof(gtDummy->gtPrev)); - fprintf(fout, "\n"); - -#if SMALL_TREE_NODES - fprintf(fout, "Small tree node size = %3u\n", TREE_NODE_SZ_SMALL); -#endif // SMALL_TREE_NODES - fprintf(fout, "Large tree node size = %3u\n", TREE_NODE_SZ_LARGE); - fprintf(fout, "Size of GenTree = %3u\n", sizeof(GenTree)); - fprintf(fout, "Size of GenTreeUnOp = %3u\n", sizeof(GenTreeUnOp)); - fprintf(fout, "Size of GenTreeOp = %3u\n", sizeof(GenTreeOp)); - fprintf(fout, "Size of GenTreeVal = %3u\n", sizeof(GenTreeVal)); - fprintf(fout, "Size of GenTreeIntConCommon = %3u\n", sizeof(GenTreeIntConCommon)); - fprintf(fout, "Size of GenTreePhysReg = %3u\n", sizeof(GenTreePhysReg)); -#ifndef LEGACY_BACKEND - fprintf(fout, "Size of GenTreeJumpTable = %3u\n", sizeof(GenTreeJumpTable)); -#endif // !LEGACY_BACKEND - fprintf(fout, "Size of GenTreeIntCon = %3u\n", sizeof(GenTreeIntCon)); - fprintf(fout, "Size of GenTreeLngCon = %3u\n", sizeof(GenTreeLngCon)); - fprintf(fout, "Size of GenTreeDblCon = %3u\n", sizeof(GenTreeDblCon)); - fprintf(fout, "Size of GenTreeStrCon = %3u\n", sizeof(GenTreeStrCon)); - fprintf(fout, "Size of GenTreeLclVarCommon = %3u\n", sizeof(GenTreeLclVarCommon)); - fprintf(fout, "Size of GenTreeLclVar = %3u\n", sizeof(GenTreeLclVar)); - fprintf(fout, "Size of GenTreeLclFld = %3u\n", sizeof(GenTreeLclFld)); - fprintf(fout, "Size of GenTreeRegVar = %3u\n", sizeof(GenTreeRegVar)); - fprintf(fout, "Size of GenTreeCast = %3u\n", sizeof(GenTreeCast)); - fprintf(fout, "Size of GenTreeBox = %3u\n", sizeof(GenTreeBox)); - fprintf(fout, "Size of GenTreeField = %3u\n", sizeof(GenTreeField)); - fprintf(fout, "Size of GenTreeArgList = %3u\n", sizeof(GenTreeArgList)); - fprintf(fout, "Size of GenTreeColon = %3u\n", sizeof(GenTreeColon)); - fprintf(fout, "Size of GenTreeCall = %3u\n", sizeof(GenTreeCall)); - fprintf(fout, "Size of GenTreeCmpXchg = %3u\n", sizeof(GenTreeCmpXchg)); - fprintf(fout, "Size of GenTreeFptrVal = %3u\n", sizeof(GenTreeFptrVal)); - fprintf(fout, "Size of GenTreeQmark = %3u\n", sizeof(GenTreeQmark)); - fprintf(fout, "Size of GenTreeIntrinsic = %3u\n", sizeof(GenTreeIntrinsic)); - fprintf(fout, "Size of GenTreeIndex = %3u\n", sizeof(GenTreeIndex)); - fprintf(fout, "Size of GenTreeArrLen = %3u\n", sizeof(GenTreeArrLen)); - fprintf(fout, "Size of GenTreeBoundsChk = %3u\n", sizeof(GenTreeBoundsChk)); - fprintf(fout, "Size of GenTreeArrElem = %3u\n", sizeof(GenTreeArrElem)); - fprintf(fout, "Size of GenTreeAddrMode = %3u\n", sizeof(GenTreeAddrMode)); - fprintf(fout, "Size of GenTreeIndir = %3u\n", sizeof(GenTreeIndir)); - fprintf(fout, "Size of GenTreeStoreInd = %3u\n", sizeof(GenTreeStoreInd)); - fprintf(fout, "Size of GenTreeRetExpr = %3u\n", sizeof(GenTreeRetExpr)); - fprintf(fout, "Size of GenTreeStmt = %3u\n", sizeof(GenTreeStmt)); - fprintf(fout, "Size of GenTreeObj = %3u\n", sizeof(GenTreeObj)); - fprintf(fout, "Size of GenTreeClsVar = %3u\n", sizeof(GenTreeClsVar)); - fprintf(fout, "Size of GenTreeArgPlace = %3u\n", sizeof(GenTreeArgPlace)); - fprintf(fout, "Size of GenTreeLabel = %3u\n", sizeof(GenTreeLabel)); - fprintf(fout, "Size of GenTreePhiArg = %3u\n", sizeof(GenTreePhiArg)); - fprintf(fout, "Size of GenTreePutArgStk = %3u\n", sizeof(GenTreePutArgStk)); - fprintf(fout, "\n"); -#endif // MEASURE_NODE_SIZE + GenTree::DumpNodeSizes(fout); +#endif #if MEASURE_BLOCK_SIZE @@ -1572,8 +1603,6 @@ void Compiler::compDisplayStaticSizes(FILE* fout) sizeof(bbDummy->bbJumpDest)); fprintf(fout, "Offset / size of bbJumpSwt = %3u / %3u\n", offsetof(BasicBlock, bbJumpSwt), sizeof(bbDummy->bbJumpSwt)); - fprintf(fout, "Offset / size of bbTreeList = %3u / %3u\n", offsetof(BasicBlock, bbTreeList), - sizeof(bbDummy->bbTreeList)); fprintf(fout, "Offset / size of bbEntryState = %3u / %3u\n", offsetof(BasicBlock, bbEntryState), sizeof(bbDummy->bbEntryState)); fprintf(fout, "Offset / size of bbStkTempsIn = %3u / %3u\n", offsetof(BasicBlock, bbStkTempsIn), @@ -1618,12 +1647,8 @@ void Compiler::compDisplayStaticSizes(FILE* fout) sizeof(bbDummy->bbHeapSsaNumIn)); fprintf(fout, "Offset / size of bbHeapSsaNumOut = %3u / %3u\n", offsetof(BasicBlock, bbHeapSsaNumOut), sizeof(bbDummy->bbHeapSsaNumOut)); - -#ifdef DEBUGGING_SUPPORT fprintf(fout, "Offset / size of bbScope = %3u / %3u\n", offsetof(BasicBlock, bbScope), sizeof(bbDummy->bbScope)); -#endif // DEBUGGING_SUPPORT - fprintf(fout, "Offset / size of bbCseGen = %3u / %3u\n", offsetof(BasicBlock, bbCseGen), sizeof(bbDummy->bbCseGen)); fprintf(fout, "Offset / size of bbCseIn = %3u / %3u\n", offsetof(BasicBlock, bbCseIn), @@ -1888,10 +1913,6 @@ void Compiler::compInit(ArenaAllocator* pAlloc, InlineInfo* inlineInfo) SIMDVectorHandle = nullptr; #endif -#ifdef DEBUG - inlRNG = nullptr; -#endif - compUsesThrowHelper = false; } @@ -2244,14 +2265,14 @@ const char* Compiler::compLocalVarName(unsigned varNum, unsigned offs) void Compiler::compSetProcessor() { - unsigned compileFlags = opts.eeFlags; + const JitFlags& jitFlags = *opts.jitFlags; #if defined(_TARGET_ARM_) info.genCPU = CPU_ARM; #elif defined(_TARGET_AMD64_) - info.genCPU = CPU_X64; + info.genCPU = CPU_X64; #elif defined(_TARGET_X86_) - if (compileFlags & CORJIT_FLG_TARGET_P4) + if (jitFlags.IsSet(JitFlags::JIT_FLAG_TARGET_P4)) info.genCPU = CPU_X86_PENTIUM_4; else info.genCPU = CPU_X86; @@ -2262,33 +2283,66 @@ void Compiler::compSetProcessor() // CLANG_FORMAT_COMMENT_ANCHOR; -#ifdef _TARGET_AMD64_ - opts.compUseFCOMI = false; - opts.compUseCMOV = true; - opts.compCanUseSSE2 = true; +#ifdef _TARGET_XARCH_ + opts.compCanUseSSE3_4 = false; + if (!jitFlags.IsSet(JitFlags::JIT_FLAG_PREJIT) && jitFlags.IsSet(JitFlags::JIT_FLAG_USE_SSE3_4)) + { + if (JitConfig.EnableSSE3_4() != 0) + { + opts.compCanUseSSE3_4 = true; + } + } #ifdef FEATURE_AVX_SUPPORT // COMPlus_EnableAVX can be used to disable using AVX if available on a target machine. // Note that FEATURE_AVX_SUPPORT is not enabled for ctpjit opts.compCanUseAVX = false; - if (((compileFlags & CORJIT_FLG_PREJIT) == 0) && ((compileFlags & CORJIT_FLG_USE_AVX2) != 0)) + if (!jitFlags.IsSet(JitFlags::JIT_FLAG_PREJIT) && jitFlags.IsSet(JitFlags::JIT_FLAG_USE_AVX2)) { if (JitConfig.EnableAVX() != 0) { opts.compCanUseAVX = true; - if (!compIsForInlining()) - { - codeGen->getEmitter()->SetUseAVX(true); - } } } -#endif -#endif //_TARGET_AMD64_ +#endif // FEATURE_AVX_SUPPORT -#ifdef _TARGET_X86_ - opts.compUseFCOMI = ((opts.eeFlags & CORJIT_FLG_USE_FCOMI) != 0); - opts.compUseCMOV = ((opts.eeFlags & CORJIT_FLG_USE_CMOV) != 0); - opts.compCanUseSSE2 = ((opts.eeFlags & CORJIT_FLG_USE_SSE2) != 0); + if (!compIsForInlining()) + { +#ifdef FEATURE_AVX_SUPPORT + if (opts.compCanUseAVX) + { + codeGen->getEmitter()->SetUseAVX(true); + } + else +#endif // FEATURE_AVX_SUPPORT + if (opts.compCanUseSSE3_4) + { + codeGen->getEmitter()->SetUseSSE3_4(true); + } + } +#endif // _TARGET_XARCH_ + +#ifdef _TARGET_AMD64_ + opts.compUseFCOMI = false; + opts.compUseCMOV = true; + opts.compCanUseSSE2 = true; +#elif defined(_TARGET_X86_) + opts.compUseFCOMI = jitFlags.IsSet(JitFlags::JIT_FLAG_USE_FCOMI); + opts.compUseCMOV = jitFlags.IsSet(JitFlags::JIT_FLAG_USE_CMOV); + opts.compCanUseSSE2 = jitFlags.IsSet(JitFlags::JIT_FLAG_USE_SSE2); + +#if !defined(LEGACY_BACKEND) && !defined(FEATURE_CORECLR) + // RyuJIT/x86 requires SSE2 to be available: there is no support for generating floating-point + // code with x87 instructions. On .NET Core, the VM always tells us that SSE2 is available. + // However, on desktop, under ngen, (and presumably in the unlikely case you're actually + // running on a machine without SSE2), the VM does not set the SSE2 flag. We ignore this and + // go ahead and generate SSE2 code anyway. + if (!opts.compCanUseSSE2) + { + JITDUMP("VM didn't set CORJIT_FLG_USE_SSE2! Ignoring, and generating SSE2 code anyway.\n"); + opts.compCanUseSSE2 = true; + } +#endif // !defined(LEGACY_BACKEND) && !defined(FEATURE_CORECLR) #ifdef DEBUG if (opts.compUseFCOMI) @@ -2296,7 +2350,9 @@ void Compiler::compSetProcessor() if (opts.compUseCMOV) opts.compUseCMOV = !compStressCompile(STRESS_USE_CMOV, 50); - // Should we override the SSE2 setting +#ifdef LEGACY_BACKEND + + // Should we override the SSE2 setting? enum { SSE2_FORCE_DISABLE = 0, @@ -2310,7 +2366,17 @@ void Compiler::compSetProcessor() opts.compCanUseSSE2 = true; else if (opts.compCanUseSSE2) opts.compCanUseSSE2 = !compStressCompile(STRESS_GENERIC_VARN, 50); + +#else // !LEGACY_BACKEND + + // RyuJIT/x86 requires SSE2 to be available and hence + // don't turn off compCanUseSSE2 under stress. + assert(opts.compCanUseSSE2); + +#endif // !LEGACY_BACKEND + #endif // DEBUG + #endif // _TARGET_X86_ } @@ -2378,31 +2444,36 @@ unsigned ReinterpretHexAsDecimal(unsigned in) return result; } -void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) +void Compiler::compInitOptions(JitFlags* jitFlags) { #ifdef UNIX_AMD64_ABI opts.compNeedToAlignFrame = false; #endif // UNIX_AMD64_ABI memset(&opts, 0, sizeof(opts)); - unsigned compileFlags = jitFlags->corJitFlags; - if (compIsForInlining()) { - assert((compileFlags & CORJIT_FLG_LOST_WHEN_INLINING) == 0); - assert(compileFlags & CORJIT_FLG_SKIP_VERIFICATION); + // The following flags are lost when inlining. (They are removed in + // Compiler::fgInvokeInlineeCompiler().) + assert(!jitFlags->IsSet(JitFlags::JIT_FLAG_BBOPT)); + assert(!jitFlags->IsSet(JitFlags::JIT_FLAG_BBINSTR)); + assert(!jitFlags->IsSet(JitFlags::JIT_FLAG_PROF_ENTERLEAVE)); + assert(!jitFlags->IsSet(JitFlags::JIT_FLAG_DEBUG_EnC)); + assert(!jitFlags->IsSet(JitFlags::JIT_FLAG_DEBUG_INFO)); + + assert(jitFlags->IsSet(JitFlags::JIT_FLAG_SKIP_VERIFICATION)); } opts.jitFlags = jitFlags; - opts.eeFlags = compileFlags; opts.compFlags = CLFLG_MAXOPT; // Default value is for full optimization - if (opts.eeFlags & (CORJIT_FLG_DEBUG_CODE | CORJIT_FLG_MIN_OPT)) + if (jitFlags->IsSet(JitFlags::JIT_FLAG_DEBUG_CODE) || jitFlags->IsSet(JitFlags::JIT_FLAG_MIN_OPT)) { opts.compFlags = CLFLG_MINOPT; } // Don't optimize .cctors (except prejit) or if we're an inlinee - else if (!(opts.eeFlags & CORJIT_FLG_PREJIT) && ((info.compFlags & FLG_CCTOR) == FLG_CCTOR) && !compIsForInlining()) + else if (!jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT) && ((info.compFlags & FLG_CCTOR) == FLG_CCTOR) && + !compIsForInlining()) { opts.compFlags = CLFLG_MINOPT; } @@ -2414,32 +2485,31 @@ void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) // If the EE sets SIZE_OPT or if we are compiling a Class constructor // we will optimize for code size at the expense of speed // - if ((opts.eeFlags & CORJIT_FLG_SIZE_OPT) || ((info.compFlags & FLG_CCTOR) == FLG_CCTOR)) + if (jitFlags->IsSet(JitFlags::JIT_FLAG_SIZE_OPT) || ((info.compFlags & FLG_CCTOR) == FLG_CCTOR)) { opts.compCodeOpt = SMALL_CODE; } // // If the EE sets SPEED_OPT we will optimize for speed at the expense of code size // - else if (opts.eeFlags & CORJIT_FLG_SPEED_OPT) + else if (jitFlags->IsSet(JitFlags::JIT_FLAG_SPEED_OPT)) { opts.compCodeOpt = FAST_CODE; - assert((opts.eeFlags & CORJIT_FLG_SIZE_OPT) == 0); + assert(!jitFlags->IsSet(JitFlags::JIT_FLAG_SIZE_OPT)); } -//------------------------------------------------------------------------- + //------------------------------------------------------------------------- + + opts.compDbgCode = jitFlags->IsSet(JitFlags::JIT_FLAG_DEBUG_CODE); + opts.compDbgInfo = jitFlags->IsSet(JitFlags::JIT_FLAG_DEBUG_INFO); + opts.compDbgEnC = jitFlags->IsSet(JitFlags::JIT_FLAG_DEBUG_EnC); -#ifdef DEBUGGING_SUPPORT - opts.compDbgCode = (opts.eeFlags & CORJIT_FLG_DEBUG_CODE) != 0; - opts.compDbgInfo = (opts.eeFlags & CORJIT_FLG_DEBUG_INFO) != 0; - opts.compDbgEnC = (opts.eeFlags & CORJIT_FLG_DEBUG_EnC) != 0; #if REGEN_SHORTCUTS || REGEN_CALLPAT // We never want to have debugging enabled when regenerating GC encoding patterns opts.compDbgCode = false; opts.compDbgInfo = false; opts.compDbgEnC = false; #endif -#endif compSetProcessor(); @@ -2473,7 +2543,7 @@ void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) #ifdef DEBUG const JitConfigValues::MethodSet* pfAltJit; - if (opts.eeFlags & CORJIT_FLG_PREJIT) + if (jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT)) { pfAltJit = &JitConfig.AltJitNgen(); } @@ -2498,7 +2568,7 @@ void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) #else // !DEBUG const char* altJitVal; - if (opts.eeFlags & CORJIT_FLG_PREJIT) + if (jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT)) { altJitVal = JitConfig.AltJitNgen().list(); } @@ -2602,7 +2672,7 @@ void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) // if (!compIsForInlining()) { - if (opts.eeFlags & CORJIT_FLG_PREJIT) + if (jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT)) { if (JitConfig.NgenDump().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args)) { @@ -2952,10 +3022,8 @@ void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) #endif // DEBUG #ifdef FEATURE_SIMD -#ifdef _TARGET_AMD64_ - // Minimum bar for availing SIMD benefits is SSE2 on AMD64. - featureSIMD = ((opts.eeFlags & CORJIT_FLG_FEATURE_SIMD) != 0); -#endif // _TARGET_AMD64_ + // Minimum bar for availing SIMD benefits is SSE2 on AMD64/x86. + featureSIMD = jitFlags->IsSet(JitFlags::JIT_FLAG_FEATURE_SIMD); #endif // FEATURE_SIMD if (compIsForInlining() || compIsForImportOnly()) @@ -2978,23 +3046,26 @@ void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) opts.compTailCallLoopOpt = true; #endif -#ifdef DEBUG - opts.dspInstrs = false; - opts.dspEmit = false; - opts.dspLines = false; - opts.varNames = false; - opts.dmpHex = false; - opts.disAsm = false; - opts.disAsmSpilled = false; - opts.disDiffable = false; - opts.dspCode = false; - opts.dspEHTable = false; - opts.dspGCtbls = false; - opts.disAsm2 = false; - opts.dspUnwind = false; - s_dspMemStats = false; - opts.compLongAddress = false; +#ifdef PROFILING_SUPPORTED opts.compJitELTHookEnabled = false; +#endif // PROFILING_SUPPORTED + +#ifdef DEBUG + opts.dspInstrs = false; + opts.dspEmit = false; + opts.dspLines = false; + opts.varNames = false; + opts.dmpHex = false; + opts.disAsm = false; + opts.disAsmSpilled = false; + opts.disDiffable = false; + opts.dspCode = false; + opts.dspEHTable = false; + opts.dspGCtbls = false; + opts.disAsm2 = false; + opts.dspUnwind = false; + opts.compLongAddress = false; + opts.optRepeat = false; #ifdef LATE_DISASM opts.doLateDisasm = false; @@ -3007,7 +3078,7 @@ void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) // if (!altJitConfig || opts.altJit) { - if (opts.eeFlags & CORJIT_FLG_PREJIT) + if (jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT)) { if ((JitConfig.NgenOrder() & 1) == 1) { @@ -3084,14 +3155,14 @@ void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) opts.dspDiffable = true; } - if (JitConfig.DisplayMemStats() != 0) + if (JitConfig.JitLongAddress() != 0) { - s_dspMemStats = true; + opts.compLongAddress = true; } - if (JitConfig.JitLongAddress() != 0) + if (JitConfig.JitOptRepeat().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args)) { - opts.compLongAddress = true; + opts.optRepeat = true; } } @@ -3152,7 +3223,6 @@ void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) //------------------------------------------------------------------------- -#ifdef DEBUGGING_SUPPORT #ifdef DEBUG assert(!codeGen->isGCTypeFixed()); opts.compGcChecks = (JitConfig.JitGCChecks() != 0) || compStressCompile(STRESS_GENERIC_VARN, 5); @@ -3173,11 +3243,15 @@ void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) opts.compStackCheckOnCall = (dwJitStackChecks & DWORD(STACK_CHECK_ON_CALL)) != 0; #endif +#if MEASURE_MEM_ALLOC + s_dspMemStats = (JitConfig.DisplayMemStats() != 0); +#endif + #ifdef PROFILING_SUPPORTED - opts.compNoPInvokeInlineCB = (opts.eeFlags & CORJIT_FLG_PROF_NO_PINVOKE_INLINE) ? true : false; + opts.compNoPInvokeInlineCB = jitFlags->IsSet(JitFlags::JIT_FLAG_PROF_NO_PINVOKE_INLINE); // Cache the profiler handle - if (opts.eeFlags & CORJIT_FLG_PROF_ENTERLEAVE) + if (jitFlags->IsSet(JitFlags::JIT_FLAG_PROF_ENTERLEAVE)) { BOOL hookNeeded; BOOL indirected; @@ -3192,11 +3266,8 @@ void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) compProfilerMethHndIndirected = false; } -#if defined(_TARGET_ARM_) || defined(_TARGET_AMD64_) - // Right now this ELT hook option is enabled only for arm and amd64 - - // Honour complus_JitELTHookEnabled only if VM has not asked us to generate profiler - // hooks in the first place. That is, Override VM only if it hasn't asked for a + // Honour COMPlus_JitELTHookEnabled only if VM has not asked us to generate profiler + // hooks in the first place. That is, override VM only if it hasn't asked for a // profiler callback for this method. if (!compProfilerHookNeeded && (JitConfig.JitELTHookEnabled() != 0)) { @@ -3209,7 +3280,6 @@ void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) compProfilerMethHnd = (void*)DummyProfilerELTStub; compProfilerMethHndIndirected = false; } -#endif // _TARGET_ARM_ || _TARGET_AMD64_ #endif // PROFILING_SUPPORTED @@ -3226,10 +3296,9 @@ void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) } #endif - opts.compMustInlinePInvokeCalli = (opts.eeFlags & CORJIT_FLG_IL_STUB) ? true : false; + opts.compMustInlinePInvokeCalli = jitFlags->IsSet(JitFlags::JIT_FLAG_IL_STUB); opts.compScopeInfo = opts.compDbgInfo; -#endif // DEBUGGING_SUPPORT #ifdef LATE_DISASM codeGen->getDisAssembler().disOpenForLateDisAsm(info.compMethodName, info.compClassName, @@ -3239,7 +3308,7 @@ void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) //------------------------------------------------------------------------- #if RELOC_SUPPORT - opts.compReloc = (opts.eeFlags & CORJIT_FLG_RELOC) ? true : false; + opts.compReloc = jitFlags->IsSet(JitFlags::JIT_FLAG_RELOC); #endif #ifdef DEBUG @@ -3249,7 +3318,7 @@ void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) #endif #endif // DEBUG - opts.compProcedureSplitting = (opts.eeFlags & CORJIT_FLG_PROCSPLIT) ? true : false; + opts.compProcedureSplitting = jitFlags->IsSet(JitFlags::JIT_FLAG_PROCSPLIT); #ifdef _TARGET_ARM64_ // TODO-ARM64-NYI: enable hot/cold splitting @@ -3294,7 +3363,7 @@ void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) fgProfileBuffer = nullptr; fgProfileData_ILSizeMismatch = false; fgNumProfileRuns = 0; - if (opts.eeFlags & CORJIT_FLG_BBOPT) + if (jitFlags->IsSet(JitFlags::JIT_FLAG_BBOPT)) { assert(!compIsForInlining()); HRESULT hr; @@ -3365,7 +3434,7 @@ void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) printf("OPTIONS: compProcedureSplitting = %s\n", dspBool(opts.compProcedureSplitting)); printf("OPTIONS: compProcedureSplittingEH = %s\n", dspBool(opts.compProcedureSplittingEH)); - if ((opts.eeFlags & CORJIT_FLG_BBOPT) && fgHaveProfileData()) + if (jitFlags->IsSet(JitFlags::JIT_FLAG_BBOPT) && fgHaveProfileData()) { printf("OPTIONS: using real profile data\n"); } @@ -3375,7 +3444,7 @@ void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) printf("OPTIONS: discarded IBC profile data due to mismatch in ILSize\n"); } - if (opts.eeFlags & CORJIT_FLG_PREJIT) + if (jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT)) { printf("OPTIONS: Jit invoked for ngen\n"); } @@ -3384,11 +3453,11 @@ void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) #endif opts.compGCPollType = GCPOLL_NONE; - if (opts.eeFlags & CORJIT_FLG_GCPOLL_CALLS) + if (jitFlags->IsSet(JitFlags::JIT_FLAG_GCPOLL_CALLS)) { opts.compGCPollType = GCPOLL_CALL; } - else if (opts.eeFlags & CORJIT_FLG_GCPOLL_INLINE) + else if (jitFlags->IsSet(JitFlags::JIT_FLAG_GCPOLL_INLINE)) { // make sure that the EE didn't set both flags. assert(opts.compGCPollType == GCPOLL_NONE); @@ -3568,14 +3637,11 @@ void Compiler::compInitDebuggingInfo() info.compVarScopesCount = 0; -#ifdef DEBUGGING_SUPPORT if (opts.compScopeInfo) -#endif { eeGetVars(); } -#ifdef DEBUGGING_SUPPORT compInitVarScopeMap(); if (opts.compScopeInfo || opts.compDbgCode) @@ -3598,7 +3664,6 @@ void Compiler::compInitDebuggingInfo() JITDUMP("Debuggable code - Add new BB%02u to perform initialization of variables [%08X]\n", fgFirstBB->bbNum, dspPtr(fgFirstBB)); } -#endif // DEBUGGING_SUPPORT /*------------------------------------------------------------------------- * @@ -3617,9 +3682,7 @@ void Compiler::compInitDebuggingInfo() info.compStmtOffsetsCount = 0; -#ifdef DEBUGGING_SUPPORT if (opts.compDbgInfo) -#endif { /* Get hold of the line# records, if there are any */ @@ -3661,12 +3724,9 @@ void Compiler::compInitDebuggingInfo() void Compiler::compSetOptimizationLevel() { - unsigned compileFlags; bool theMinOptsValue; unsigned jitMinOpts; - compileFlags = opts.eeFlags; - if (compIsForInlining()) { theMinOptsValue = impInlineInfo->InlinerCompiler->opts.MinOpts(); @@ -3757,13 +3817,40 @@ void Compiler::compSetOptimizationLevel() } } +#if 0 + // The code in this #if can be used to debug optimization issues according to method hash. + // To use, uncomment, rebuild and set environment variables minoptshashlo and minoptshashhi. +#ifdef DEBUG + unsigned methHash = info.compMethodHash(); + char* lostr = getenv("minoptshashlo"); + unsigned methHashLo = 0; + if (lostr != nullptr) + { + sscanf_s(lostr, "%x", &methHashLo); + char* histr = getenv("minoptshashhi"); + unsigned methHashHi = UINT32_MAX; + if (histr != nullptr) + { + sscanf_s(histr, "%x", &methHashHi); + if (methHash >= methHashLo && methHash <= methHashHi) + { + printf("MinOpts for method %s, hash = 0x%x.\n", + info.compFullName, info.compMethodHash()); + printf(""); // in our logic this causes a flush + theMinOptsValue = true; + } + } + } +#endif +#endif + if (compStressCompile(STRESS_MIN_OPTS, 5)) { theMinOptsValue = true; } // For PREJIT we never drop down to MinOpts // unless unless CLFLG_MINOPT is set - else if (!(compileFlags & CORJIT_FLG_PREJIT)) + else if (!opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT)) { if ((unsigned)JitConfig.JitMinOptsCodeSize() < info.compILCodeSize) { @@ -3805,7 +3892,7 @@ void Compiler::compSetOptimizationLevel() // Retail check if we should force Minopts due to the complexity of the method // For PREJIT we never drop down to MinOpts // unless unless CLFLG_MINOPT is set - if (!theMinOptsValue && !(compileFlags & CORJIT_FLG_PREJIT) && + if (!theMinOptsValue && !opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT) && ((DEFAULT_MIN_OPTS_CODE_SIZE < info.compILCodeSize) || (DEFAULT_MIN_OPTS_INSTR_COUNT < opts.instrCount) || (DEFAULT_MIN_OPTS_BB_COUNT < fgBBcount) || (DEFAULT_MIN_OPTS_LV_NUM_COUNT < lvaCount) || (DEFAULT_MIN_OPTS_LV_REF_COUNT < opts.lvRefCount))) @@ -3828,14 +3915,14 @@ void Compiler::compSetOptimizationLevel() unsigned methHash = info.compMethodHash(); char* lostr = getenv("opthashlo"); unsigned methHashLo = 0; - if (lostr != NULL) + if (lostr != NULL) { sscanf_s(lostr, "%x", &methHashLo); // methHashLo = (unsigned(atoi(lostr)) << 2); // So we don't have to use negative numbers. } char* histr = getenv("opthashhi"); unsigned methHashHi = UINT32_MAX; - if (histr != NULL) + if (histr != NULL) { sscanf_s(histr, "%x", &methHashHi); // methHashHi = (unsigned(atoi(histr)) << 2); // So we don't have to use negative numbers. @@ -3883,27 +3970,27 @@ _SetMinOpts: } #if !defined(_TARGET_AMD64_) - // The VM sets CORJIT_FLG_FRAMED for two reasons: (1) the COMPlus_JitFramed variable is set, or + // The VM sets JitFlags::JIT_FLAG_FRAMED for two reasons: (1) the COMPlus_JitFramed variable is set, or // (2) the function is marked "noinline". The reason for #2 is that people mark functions // noinline to ensure the show up on in a stack walk. But for AMD64, we don't need a frame // pointer for the frame to show up in stack walk. - if (compileFlags & CORJIT_FLG_FRAMED) + if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_FRAMED)) codeGen->setFrameRequired(true); #endif - if (compileFlags & CORJIT_FLG_RELOC) + if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_RELOC)) { codeGen->genAlignLoops = false; // loop alignment not supported for prejitted code - // The zapper doesn't set CORJIT_FLG_ALIGN_LOOPS, and there is + // The zapper doesn't set JitFlags::JIT_FLAG_ALIGN_LOOPS, and there is // no reason for it to set it as the JIT doesn't currently support loop alignment // for prejitted images. (The JIT doesn't know the final address of the code, hence // it can't align code based on unknown addresses.) - assert((compileFlags & CORJIT_FLG_ALIGN_LOOPS) == 0); + assert(!opts.jitFlags->IsSet(JitFlags::JIT_FLAG_ALIGN_LOOPS)); } else { - codeGen->genAlignLoops = (compileFlags & CORJIT_FLG_ALIGN_LOOPS) != 0; + codeGen->genAlignLoops = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_ALIGN_LOOPS); } } @@ -4075,7 +4162,7 @@ void Compiler::compFunctionTraceEnd(void* methodCodePtr, ULONG methodCodeSize, b // For an overview of the structure of the JIT, see: // https://github.com/dotnet/coreclr/blob/master/Documentation/botr/ryujit-overview.md // -void Compiler::compCompile(void** methodCodePtr, ULONG* methodCodeSize, CORJIT_FLAGS* compileFlags) +void Compiler::compCompile(void** methodCodePtr, ULONG* methodCodeSize, JitFlags* compileFlags) { if (compIsForInlining()) { @@ -4112,26 +4199,36 @@ void Compiler::compCompile(void** methodCodePtr, ULONG* methodCodeSize, CORJIT_F fgRemovePreds(); } + EndPhase(PHASE_IMPORTATION); + if (compIsForInlining()) { /* Quit inlining if fgImport() failed for any reason. */ - if (compDonotInline()) + if (!compDonotInline()) { - return; + /* Filter out unimported BBs */ + + fgRemoveEmptyBlocks(); } - /* Filter out unimported BBs */ + EndPhase(PHASE_POST_IMPORT); - fgRemoveEmptyBlocks(); +#ifdef FEATURE_JIT_METHOD_PERF + if (pCompJitTimer != nullptr) + { +#if MEASURE_CLRAPI_CALLS + EndPhase(PHASE_CLR_API); +#endif + pCompJitTimer->Terminate(this, CompTimeSummaryInfo::s_compTimeSummary, false); + } +#endif return; } assert(!compDonotInline()); - EndPhase(PHASE_IMPORTATION); - // Maybe the caller was not interested in generating code if (compIsForImportOnly()) { @@ -4145,7 +4242,7 @@ void Compiler::compCompile(void** methodCodePtr, ULONG* methodCodeSize, CORJIT_F fgRemoveEH(); #endif // !FEATURE_EH - if (compileFlags->corJitFlags & CORJIT_FLG_BBINSTR) + if (compileFlags->IsSet(JitFlags::JIT_FLAG_BBINSTR)) { fgInstrumentMethod(); } @@ -4180,7 +4277,7 @@ void Compiler::compCompile(void** methodCodePtr, ULONG* methodCodeSize, CORJIT_F /* Massage the trees so that we can generate code out of them */ fgMorph(); - EndPhase(PHASE_MORPH); + EndPhase(PHASE_MORPH_END); /* GS security checks for unsafe buffers */ if (getNeedsGSSecurityCookie()) @@ -4336,6 +4433,7 @@ void Compiler::compCompile(void** methodCodePtr, ULONG* methodCodeSize, CORJIT_F bool doCopyProp = true; bool doAssertionProp = true; bool doRangeAnalysis = true; + int iterations = 1; #ifdef DEBUG doSsa = (JitConfig.JitDoSsa() != 0); @@ -4345,72 +4443,88 @@ void Compiler::compCompile(void** methodCodePtr, ULONG* methodCodeSize, CORJIT_F doCopyProp = doValueNum && (JitConfig.JitDoCopyProp() != 0); doAssertionProp = doValueNum && (JitConfig.JitDoAssertionProp() != 0); doRangeAnalysis = doAssertionProp && (JitConfig.JitDoRangeAnalysis() != 0); -#endif - if (doSsa) + if (opts.optRepeat) { - fgSsaBuild(); - EndPhase(PHASE_BUILD_SSA); + iterations = JitConfig.JitOptRepeatCount(); } +#endif - if (doEarlyProp) + while (iterations > 0) { - /* Propagate array length and rewrite getType() method call */ - optEarlyProp(); - EndPhase(PHASE_EARLY_PROP); - } + if (doSsa) + { + fgSsaBuild(); + EndPhase(PHASE_BUILD_SSA); + } - if (doValueNum) - { - fgValueNumber(); - EndPhase(PHASE_VALUE_NUMBER); - } + if (doEarlyProp) + { + /* Propagate array length and rewrite getType() method call */ + optEarlyProp(); + EndPhase(PHASE_EARLY_PROP); + } - if (doLoopHoisting) - { - /* Hoist invariant code out of loops */ - optHoistLoopCode(); - EndPhase(PHASE_HOIST_LOOP_CODE); - } + if (doValueNum) + { + fgValueNumber(); + EndPhase(PHASE_VALUE_NUMBER); + } - if (doCopyProp) - { - /* Perform VN based copy propagation */ - optVnCopyProp(); - EndPhase(PHASE_VN_COPY_PROP); - } + if (doLoopHoisting) + { + /* Hoist invariant code out of loops */ + optHoistLoopCode(); + EndPhase(PHASE_HOIST_LOOP_CODE); + } + + if (doCopyProp) + { + /* Perform VN based copy propagation */ + optVnCopyProp(); + EndPhase(PHASE_VN_COPY_PROP); + } #if FEATURE_ANYCSE - /* Remove common sub-expressions */ - optOptimizeCSEs(); + /* Remove common sub-expressions */ + optOptimizeCSEs(); #endif // FEATURE_ANYCSE #if ASSERTION_PROP - if (doAssertionProp) - { - /* Assertion propagation */ - optAssertionPropMain(); - EndPhase(PHASE_ASSERTION_PROP_MAIN); - } + if (doAssertionProp) + { + /* Assertion propagation */ + optAssertionPropMain(); + EndPhase(PHASE_ASSERTION_PROP_MAIN); + } - if (doRangeAnalysis) - { - /* Optimize array index range checks */ - RangeCheck rc(this); - rc.OptimizeRangeChecks(); - EndPhase(PHASE_OPTIMIZE_INDEX_CHECKS); - } + if (doRangeAnalysis) + { + /* Optimize array index range checks */ + RangeCheck rc(this); + rc.OptimizeRangeChecks(); + EndPhase(PHASE_OPTIMIZE_INDEX_CHECKS); + } #endif // ASSERTION_PROP - /* update the flowgraph if we modified it during the optimization phase*/ - if (fgModified) - { - fgUpdateFlowGraph(); - EndPhase(PHASE_UPDATE_FLOW_GRAPH); + /* update the flowgraph if we modified it during the optimization phase*/ + if (fgModified) + { + fgUpdateFlowGraph(); + EndPhase(PHASE_UPDATE_FLOW_GRAPH); + + // Recompute the edge weight if we have modified the flow graph + fgComputeEdgeWeights(); + EndPhase(PHASE_COMPUTE_EDGE_WEIGHTS2); + } - // Recompute the edge weight if we have modified the flow graph - fgComputeEdgeWeights(); - EndPhase(PHASE_COMPUTE_EDGE_WEIGHTS2); + // Iterate if requested, resetting annotations first. + if (--iterations == 0) + { + break; + } + ResetOptAnnotations(); + RecomputeLoopInfo(); } } @@ -4540,7 +4654,12 @@ void Compiler::compCompile(void** methodCodePtr, ULONG* methodCodeSize, CORJIT_F #ifdef FEATURE_JIT_METHOD_PERF if (pCompJitTimer) - pCompJitTimer->Terminate(this, CompTimeSummaryInfo::s_compTimeSummary); + { +#if MEASURE_CLRAPI_CALLS + EndPhase(PHASE_CLR_API); +#endif + pCompJitTimer->Terminate(this, CompTimeSummaryInfo::s_compTimeSummary, true); + } #endif RecordStateAtEndOfCompilation(); @@ -4569,6 +4688,82 @@ void Compiler::compCompile(void** methodCodePtr, ULONG* methodCodeSize, CORJIT_F #endif // FUNC_INFO_LOGGING } +//------------------------------------------------------------------------ +// ResetOptAnnotations: Clear annotations produced during global optimizations. +// +// Notes: +// The intent of this method is to clear any information typically assumed +// to be set only once; it is used between iterations when JitOptRepeat is +// in effect. + +void Compiler::ResetOptAnnotations() +{ + assert(opts.optRepeat); + assert(JitConfig.JitOptRepeatCount() > 0); + fgResetForSsa(); + vnStore = nullptr; + m_opAsgnVarDefSsaNums = nullptr; + m_blockToEHPreds = nullptr; + fgSsaPassesCompleted = 0; + fgVNPassesCompleted = 0; + + for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext) + { + for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) + { + stmt->gtFlags &= ~GTF_STMT_HAS_CSE; + + for (GenTreePtr tree = stmt->gtStmt.gtStmtList; tree != nullptr; tree = tree->gtNext) + { + tree->ClearVN(); + tree->ClearAssertion(); + tree->gtCSEnum = NO_CSE; + + // Clear any *_ASG_LHS flags -- these are set during SSA construction, + // and the heap live-in calculation depends on them being unset coming + // into SSA construction (without clearing them, a block that has a + // heap def via one of these before any heap use is treated as not having + // an upwards-exposed heap use, even though subsequent heap uses may not + // be killed by the store; this seems to be a bug, worked around here). + if (tree->OperIsIndir()) + { + tree->gtFlags &= ~GTF_IND_ASG_LHS; + } + else if (tree->OperGet() == GT_CLS_VAR) + { + tree->gtFlags &= ~GTF_CLS_VAR_ASG_LHS; + } + } + } + } +} + +//------------------------------------------------------------------------ +// RecomputeLoopInfo: Recompute loop annotations between opt-repeat iterations. +// +// Notes: +// The intent of this method is to update loop structure annotations, and those +// they depend on; these annotations may have become stale during optimization, +// and need to be up-to-date before running another iteration of optimizations. + +void Compiler::RecomputeLoopInfo() +{ + assert(opts.optRepeat); + assert(JitConfig.JitOptRepeatCount() > 0); + // Recompute reachability sets, dominators, and loops. + optLoopCount = 0; + fgDomsComputed = false; + for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext) + { + block->bbFlags &= ~BBF_LOOP_FLAGS; + } + fgComputeReachability(); + // Rebuild the loop tree annotations themselves. Since this is performed as + // part of 'optOptimizeLoops', this will also re-perform loop rotation, but + // not other optimizations, as the others are not part of 'optOptimizeLoops'. + optOptimizeLoops(); +} + /*****************************************************************************/ void Compiler::ProcessShutdownWork(ICorStaticInfo* statInfo) { @@ -4696,11 +4891,13 @@ int Compiler::compCompile(CORINFO_METHOD_HANDLE methodHnd, CORINFO_METHOD_INFO* methodInfo, void** methodCodePtr, ULONG* methodCodeSize, - CORJIT_FLAGS* compileFlags) + JitFlags* compileFlags) { #ifdef FEATURE_JIT_METHOD_PERF static bool checkedForJitTimeLog = false; + pCompJitTimer = nullptr; + if (!checkedForJitTimeLog) { // Call into VM to get the config strings. FEATURE_JIT_METHOD_PERF is enabled for @@ -4713,14 +4910,10 @@ int Compiler::compCompile(CORINFO_METHOD_HANDLE methodHnd, checkedForJitTimeLog = true; } - if ((Compiler::compJitTimeLogFilename != NULL) || (JitTimeLogCsv() != NULL)) + if ((Compiler::compJitTimeLogFilename != nullptr) || (JitTimeLogCsv() != nullptr)) { pCompJitTimer = JitTimer::Create(this, methodInfo->ILCodeSize); } - else - { - pCompJitTimer = NULL; - } #endif // FEATURE_JIT_METHOD_PERF #ifdef DEBUG @@ -4862,7 +5055,7 @@ int Compiler::compCompile(CORINFO_METHOD_HANDLE methodHnd, // Set this before the first 'BADCODE' // Skip verification where possible - tiVerificationNeeded = (compileFlags->corJitFlags & CORJIT_FLG_SKIP_VERIFICATION) == 0; + tiVerificationNeeded = !compileFlags->IsSet(JitFlags::JIT_FLAG_SKIP_VERIFICATION); assert(!compIsForInlining() || !tiVerificationNeeded); // Inlinees must have been verified. @@ -4893,8 +5086,8 @@ int Compiler::compCompile(CORINFO_METHOD_HANDLE methodHnd, case CORINFO_VERIFICATION_CAN_SKIP: // The VM should first verify the open instantiation. If unverifiable code - // is detected, it should pass in CORJIT_FLG_SKIP_VERIFICATION. - assert(!"The VM should have used CORJIT_FLG_SKIP_VERIFICATION"); + // is detected, it should pass in JitFlags::JIT_FLAG_SKIP_VERIFICATION. + assert(!"The VM should have used JitFlags::JIT_FLAG_SKIP_VERIFICATION"); tiVerificationNeeded = false; break; @@ -4933,7 +5126,7 @@ int Compiler::compCompile(CORINFO_METHOD_HANDLE methodHnd, CORINFO_METHOD_INFO* methodInfo; void** methodCodePtr; ULONG* methodCodeSize; - CORJIT_FLAGS* compileFlags; + JitFlags* compileFlags; CorInfoInstantiationVerification instVerInfo; int result; @@ -5000,6 +5193,8 @@ void Compiler::compCompileFinish() // Make the updates. genMemStats.nraTotalSizeAlloc = compGetAllocator()->getTotalBytesAllocated(); genMemStats.nraTotalSizeUsed = compGetAllocator()->getTotalBytesUsed(); + memAllocHist.record((unsigned)((genMemStats.nraTotalSizeAlloc + 1023) / 1024)); + memUsedHist.record((unsigned)((genMemStats.nraTotalSizeUsed + 1023) / 1024)); s_aggMemStats.Add(genMemStats); if (genMemStats.allocSz > s_maxCompMemStats.allocSz) { @@ -5038,6 +5233,7 @@ void Compiler::compCompileFinish() // the prolog which requires memory (info.compLocalsCount <= 32) && (!opts.MinOpts()) && // We may have too many local variables, etc (getJitStressLevel() == 0) && // We need extra memory for stress + !opts.optRepeat && // We need extra memory to repeat opts !compAllocator->bypassHostAllocator() && // ArenaAllocator::getDefaultPageSize() is artificially low for // DirectAlloc (compAllocator->getTotalBytesAllocated() > (2 * ArenaAllocator::getDefaultPageSize())) && @@ -5071,7 +5267,7 @@ void Compiler::compCompileFinish() mdMethodDef currentMethodToken = info.compCompHnd->getMethodDefFromMethod(info.compMethodHnd); unsigned profCallCount = 0; - if (((opts.eeFlags & CORJIT_FLG_BBOPT) != 0) && fgHaveProfileData()) + if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_BBOPT) && fgHaveProfileData()) { assert(fgProfileBuffer[0].ILOffset == 0); profCallCount = fgProfileBuffer[0].ExecutionCount; @@ -5208,7 +5404,7 @@ void Compiler::compCompileFinish() // For ngen the int3 or breakpoint instruction will be right at the // start of the ngen method and we will stop when we execute it. // - if ((opts.eeFlags & CORJIT_FLG_PREJIT) == 0) + if (!opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT)) { if (compJitHaltMethod()) { @@ -5296,7 +5492,7 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, CORINFO_METHOD_INFO* methodInfo, void** methodCodePtr, ULONG* methodCodeSize, - CORJIT_FLAGS* compileFlags, + JitFlags* compileFlags, CorInfoInstantiationVerification instVerInfo) { CORINFO_METHOD_HANDLE methodHnd = info.compMethodHnd; @@ -5438,7 +5634,7 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, info.compIsContextful = (info.compClassAttr & CORINFO_FLG_CONTEXTFUL) != 0; - info.compPublishStubParam = (opts.eeFlags & CORJIT_FLG_PUBLISH_SECRET_PARAM) != 0; + info.compPublishStubParam = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM); switch (methodInfo->args.getCallConv()) { @@ -5476,7 +5672,7 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, const bool forceInline = !!(info.compFlags & CORINFO_FLG_FORCEINLINE); - if (!compIsForInlining() && (opts.eeFlags & CORJIT_FLG_PREJIT)) + if (!compIsForInlining() && opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT)) { // We're prejitting the root method. We also will analyze it as // a potential inline candidate. @@ -5644,10 +5840,6 @@ _Next: return CORJIT_OK; } -/*****************************************************************************/ -#ifdef DEBUGGING_SUPPORT -/*****************************************************************************/ - //------------------------------------------------------------------------ // compFindLocalVarLinear: Linear search for variable's scope containing offset. // @@ -5992,11 +6184,7 @@ void Compiler::compProcessScopesUntil(unsigned offset, } while (foundExit || foundEnter); } -/*****************************************************************************/ -#endif // DEBUGGING_SUPPORT -/*****************************************************************************/ - -#if defined(DEBUGGING_SUPPORT) && defined(DEBUG) +#if defined(DEBUG) void Compiler::compDispScopeLists() { @@ -6044,10 +6232,6 @@ void Compiler::compDispScopeLists() } } -#endif - -#if defined(DEBUG) - void Compiler::compDispLocalVars() { printf("info.compVarScopesCount = %d\n", info.compVarScopesCount); @@ -6066,7 +6250,66 @@ void Compiler::compDispLocalVars() } } -#endif +#endif // DEBUG + +/*****************************************************************************/ + +#if MEASURE_CLRAPI_CALLS + +struct WrapICorJitInfo : public ICorJitInfo +{ + //------------------------------------------------------------------------ + // WrapICorJitInfo::makeOne: allocate an instance of WrapICorJitInfo + // + // Arguments: + // alloc - the allocator to get memory from for the instance + // compile - the compiler instance + // compHndRef - the ICorJitInfo handle from the EE; the caller's + // copy may be replaced with a "wrapper" instance + // + // Return Value: + // If the config flags indicate that ICorJitInfo should be wrapped, + // we return the "wrapper" instance; otherwise we return "nullptr". + + static WrapICorJitInfo* makeOne(ArenaAllocator* alloc, Compiler* compiler, COMP_HANDLE& compHndRef /* INOUT */) + { + WrapICorJitInfo* wrap = nullptr; + + if (JitConfig.JitEECallTimingInfo() != 0) + { + // It's too early to use the default allocator, so we do this + // in two steps to be safe (the constructor doesn't need to do + // anything except fill in the vtable pointer, so we let the + // compiler do it). + void* inst = alloc->allocateMemory(roundUp(sizeof(WrapICorJitInfo))); + if (inst != nullptr) + { + // If you get a build error here due to 'WrapICorJitInfo' being + // an abstract class, it's very likely that the wrapper bodies + // in ICorJitInfo_API_wrapper.hpp are no longer in sync with + // the EE interface; please be kind and update the header file. + wrap = new (inst, jitstd::placement_t()) WrapICorJitInfo(); + + wrap->wrapComp = compiler; + + // Save the real handle and replace it with our wrapped version. + wrap->wrapHnd = compHndRef; + compHndRef = wrap; + } + } + + return wrap; + } + +private: + Compiler* wrapComp; + COMP_HANDLE wrapHnd; // the "real thing" + +public: +#include "ICorJitInfo_API_wrapper.hpp" +}; + +#endif // MEASURE_CLRAPI_CALLS /*****************************************************************************/ @@ -6078,7 +6321,7 @@ int jitNativeCode(CORINFO_METHOD_HANDLE methodHnd, CORINFO_METHOD_INFO* methodInfo, void** methodCodePtr, ULONG* methodCodeSize, - CORJIT_FLAGS* compileFlags, + JitFlags* compileFlags, void* inlineInfoPtr) { // @@ -6093,6 +6336,10 @@ START: ArenaAllocator* pAlloc = nullptr; ArenaAllocator alloc; +#if MEASURE_CLRAPI_CALLS + WrapICorJitInfo* wrapCLR = nullptr; +#endif + if (inlineInfo) { // Use inliner's memory allocator when compiling the inlinee. @@ -6128,8 +6375,11 @@ START: CORINFO_METHOD_INFO* methodInfo; void** methodCodePtr; ULONG* methodCodeSize; - CORJIT_FLAGS* compileFlags; + JitFlags* compileFlags; InlineInfo* inlineInfo; +#if MEASURE_CLRAPI_CALLS + WrapICorJitInfo* wrapCLR; +#endif int result; } param; @@ -6145,7 +6395,10 @@ START: param.methodCodeSize = methodCodeSize; param.compileFlags = compileFlags; param.inlineInfo = inlineInfo; - param.result = result; +#if MEASURE_CLRAPI_CALLS + param.wrapCLR = nullptr; +#endif + param.result = result; setErrorTrap(compHnd, Param*, pParamOuter, ¶m) { @@ -6172,6 +6425,10 @@ START: pParam->pComp = (Compiler*)pParam->pAlloc->allocateMemory(roundUp(sizeof(*pParam->pComp))); } +#if MEASURE_CLRAPI_CALLS + pParam->wrapCLR = WrapICorJitInfo::makeOne(pParam->pAlloc, pParam->pComp, pParam->compHnd); +#endif + // push this compiler on the stack (TLS) pParam->pComp->prevCompiler = JitTls::GetCompiler(); JitTls::SetCompiler(pParam->pComp); @@ -6238,8 +6495,9 @@ START: jitFallbackCompile = true; // Update the flags for 'safer' code generation. - compileFlags->corJitFlags |= CORJIT_FLG_MIN_OPT; - compileFlags->corJitFlags &= ~(CORJIT_FLG_SIZE_OPT | CORJIT_FLG_SPEED_OPT); + compileFlags->Set(JitFlags::JIT_FLAG_MIN_OPT); + compileFlags->Clear(JitFlags::JIT_FLAG_SIZE_OPT); + compileFlags->Clear(JitFlags::JIT_FLAG_SPEED_OPT); goto START; } @@ -6952,9 +7210,12 @@ void Compiler::compDispCallArgStats(FILE* fout) // Static variables CritSecObject CompTimeSummaryInfo::s_compTimeSummaryLock; CompTimeSummaryInfo CompTimeSummaryInfo::s_compTimeSummary; +#if MEASURE_CLRAPI_CALLS +double JitTimer::s_cyclesPerSec = CycleTimer::CyclesPerSecond(); +#endif #endif // FEATURE_JIT_METHOD_PERF -#if defined(FEATURE_JIT_METHOD_PERF) || DUMP_FLOWGRAPHS +#if defined(FEATURE_JIT_METHOD_PERF) || DUMP_FLOWGRAPHS || defined(FEATURE_TRACELOGGING) const char* PhaseNames[] = { #define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent) string_nm, #include "compphases.h" @@ -6983,13 +7244,36 @@ int PhaseParent[] = { }; CompTimeInfo::CompTimeInfo(unsigned byteCodeBytes) - : m_byteCodeBytes(byteCodeBytes), m_totalCycles(0), m_parentPhaseEndSlop(0), m_timerFailure(false) + : m_byteCodeBytes(byteCodeBytes) + , m_totalCycles(0) + , m_parentPhaseEndSlop(0) + , m_timerFailure(false) +#if MEASURE_CLRAPI_CALLS + , m_allClrAPIcalls(0) + , m_allClrAPIcycles(0) +#endif { for (int i = 0; i < PHASE_NUMBER_OF; i++) { m_invokesByPhase[i] = 0; m_cyclesByPhase[i] = 0; +#if MEASURE_CLRAPI_CALLS + m_CLRinvokesByPhase[i] = 0; + m_CLRcyclesByPhase[i] = 0; +#endif } + +#if MEASURE_CLRAPI_CALLS + assert(ARRAYSIZE(m_perClrAPIcalls) == API_ICorJitInfo_Names::API_COUNT); + assert(ARRAYSIZE(m_perClrAPIcycles) == API_ICorJitInfo_Names::API_COUNT); + assert(ARRAYSIZE(m_maxClrAPIcycles) == API_ICorJitInfo_Names::API_COUNT); + for (int i = 0; i < API_ICorJitInfo_Names::API_COUNT; i++) + { + m_perClrAPIcalls[i] = 0; + m_perClrAPIcycles[i] = 0; + m_maxClrAPIcycles[i] = 0; + } +#endif } bool CompTimeSummaryInfo::IncludedInFilteredData(CompTimeInfo& info) @@ -6997,52 +7281,125 @@ bool CompTimeSummaryInfo::IncludedInFilteredData(CompTimeInfo& info) return false; // info.m_byteCodeBytes < 10; } -void CompTimeSummaryInfo::AddInfo(CompTimeInfo& info) +//------------------------------------------------------------------------ +// CompTimeSummaryInfo::AddInfo: Record timing info from one compile. +// +// Arguments: +// info - The timing information to record. +// includePhases - If "true", the per-phase info in "info" is valid, +// which means that a "normal" compile has ended; if +// the value is "false" we are recording the results +// of a partial compile (typically an import-only run +// on behalf of the inliner) in which case the phase +// info is not valid and so we only record EE call +// overhead. +void CompTimeSummaryInfo::AddInfo(CompTimeInfo& info, bool includePhases) { if (info.m_timerFailure) + { return; // Don't update if there was a failure. + } CritSecHolder timeLock(s_compTimeSummaryLock); - m_numMethods++; - bool includeInFiltered = IncludedInFilteredData(info); + if (includePhases) + { + bool includeInFiltered = IncludedInFilteredData(info); - // Update the totals and maxima. - m_total.m_byteCodeBytes += info.m_byteCodeBytes; - m_maximum.m_byteCodeBytes = max(m_maximum.m_byteCodeBytes, info.m_byteCodeBytes); - m_total.m_totalCycles += info.m_totalCycles; - m_maximum.m_totalCycles = max(m_maximum.m_totalCycles, info.m_totalCycles); + m_numMethods++; - if (includeInFiltered) - { - m_numFilteredMethods++; - m_filtered.m_byteCodeBytes += info.m_byteCodeBytes; - m_filtered.m_totalCycles += info.m_totalCycles; - m_filtered.m_parentPhaseEndSlop += info.m_parentPhaseEndSlop; - } + // Update the totals and maxima. + m_total.m_byteCodeBytes += info.m_byteCodeBytes; + m_maximum.m_byteCodeBytes = max(m_maximum.m_byteCodeBytes, info.m_byteCodeBytes); + m_total.m_totalCycles += info.m_totalCycles; + m_maximum.m_totalCycles = max(m_maximum.m_totalCycles, info.m_totalCycles); + +#if MEASURE_CLRAPI_CALLS + // Update the CLR-API values. + m_total.m_allClrAPIcalls += info.m_allClrAPIcalls; + m_maximum.m_allClrAPIcalls = max(m_maximum.m_allClrAPIcalls, info.m_allClrAPIcalls); + m_total.m_allClrAPIcycles += info.m_allClrAPIcycles; + m_maximum.m_allClrAPIcycles = max(m_maximum.m_allClrAPIcycles, info.m_allClrAPIcycles); +#endif - for (int i = 0; i < PHASE_NUMBER_OF; i++) - { - m_total.m_invokesByPhase[i] += info.m_invokesByPhase[i]; - m_total.m_cyclesByPhase[i] += info.m_cyclesByPhase[i]; if (includeInFiltered) { - m_filtered.m_invokesByPhase[i] += info.m_invokesByPhase[i]; - m_filtered.m_cyclesByPhase[i] += info.m_cyclesByPhase[i]; + m_numFilteredMethods++; + m_filtered.m_byteCodeBytes += info.m_byteCodeBytes; + m_filtered.m_totalCycles += info.m_totalCycles; + m_filtered.m_parentPhaseEndSlop += info.m_parentPhaseEndSlop; + } + + for (int i = 0; i < PHASE_NUMBER_OF; i++) + { + m_total.m_invokesByPhase[i] += info.m_invokesByPhase[i]; + m_total.m_cyclesByPhase[i] += info.m_cyclesByPhase[i]; + +#if MEASURE_CLRAPI_CALLS + m_total.m_CLRinvokesByPhase[i] += info.m_CLRinvokesByPhase[i]; + m_total.m_CLRcyclesByPhase[i] += info.m_CLRcyclesByPhase[i]; +#endif + + if (includeInFiltered) + { + m_filtered.m_invokesByPhase[i] += info.m_invokesByPhase[i]; + m_filtered.m_cyclesByPhase[i] += info.m_cyclesByPhase[i]; +#if MEASURE_CLRAPI_CALLS + m_filtered.m_CLRinvokesByPhase[i] += info.m_CLRinvokesByPhase[i]; + m_filtered.m_CLRcyclesByPhase[i] += info.m_CLRcyclesByPhase[i]; +#endif + } + m_maximum.m_cyclesByPhase[i] = max(m_maximum.m_cyclesByPhase[i], info.m_cyclesByPhase[i]); + +#if MEASURE_CLRAPI_CALLS + m_maximum.m_CLRcyclesByPhase[i] = max(m_maximum.m_CLRcyclesByPhase[i], info.m_CLRcyclesByPhase[i]); +#endif } - m_maximum.m_cyclesByPhase[i] = max(m_maximum.m_cyclesByPhase[i], info.m_cyclesByPhase[i]); + m_total.m_parentPhaseEndSlop += info.m_parentPhaseEndSlop; + m_maximum.m_parentPhaseEndSlop = max(m_maximum.m_parentPhaseEndSlop, info.m_parentPhaseEndSlop); + } +#if MEASURE_CLRAPI_CALLS + else + { + m_totMethods++; + + // Update the "global" CLR-API values. + m_total.m_allClrAPIcalls += info.m_allClrAPIcalls; + m_maximum.m_allClrAPIcalls = max(m_maximum.m_allClrAPIcalls, info.m_allClrAPIcalls); + m_total.m_allClrAPIcycles += info.m_allClrAPIcycles; + m_maximum.m_allClrAPIcycles = max(m_maximum.m_allClrAPIcycles, info.m_allClrAPIcycles); + + // Update the per-phase CLR-API values. + m_total.m_invokesByPhase[PHASE_CLR_API] += info.m_allClrAPIcalls; + m_maximum.m_invokesByPhase[PHASE_CLR_API] = + max(m_maximum.m_perClrAPIcalls[PHASE_CLR_API], info.m_allClrAPIcalls); + m_total.m_cyclesByPhase[PHASE_CLR_API] += info.m_allClrAPIcycles; + m_maximum.m_cyclesByPhase[PHASE_CLR_API] = + max(m_maximum.m_cyclesByPhase[PHASE_CLR_API], info.m_allClrAPIcycles); + } + + for (int i = 0; i < API_ICorJitInfo_Names::API_COUNT; i++) + { + m_total.m_perClrAPIcalls[i] += info.m_perClrAPIcalls[i]; + m_maximum.m_perClrAPIcalls[i] = max(m_maximum.m_perClrAPIcalls[i], info.m_perClrAPIcalls[i]); + + m_total.m_perClrAPIcycles[i] += info.m_perClrAPIcycles[i]; + m_maximum.m_perClrAPIcycles[i] = max(m_maximum.m_perClrAPIcycles[i], info.m_perClrAPIcycles[i]); + + m_maximum.m_maxClrAPIcycles[i] = max(m_maximum.m_maxClrAPIcycles[i], info.m_maxClrAPIcycles[i]); } - m_total.m_parentPhaseEndSlop += info.m_parentPhaseEndSlop; - m_maximum.m_parentPhaseEndSlop = max(m_maximum.m_parentPhaseEndSlop, info.m_parentPhaseEndSlop); +#endif } // Static -LPCWSTR Compiler::compJitTimeLogFilename = NULL; +LPCWSTR Compiler::compJitTimeLogFilename = nullptr; void CompTimeSummaryInfo::Print(FILE* f) { - if (f == NULL) + if (f == nullptr) + { return; + } // Otherwise... double countsPerSec = CycleTimer::CyclesPerSecond(); if (countsPerSec == 0.0) @@ -7051,13 +7408,16 @@ void CompTimeSummaryInfo::Print(FILE* f) return; } + bool extraInfo = (JitConfig.JitEECallTimingInfo() != 0); + double totTime_ms = 0.0; + fprintf(f, "JIT Compilation time report:\n"); fprintf(f, " Compiled %d methods.\n", m_numMethods); if (m_numMethods != 0) { fprintf(f, " Compiled %d bytecodes total (%d max, %8.2f avg).\n", m_total.m_byteCodeBytes, m_maximum.m_byteCodeBytes, (double)m_total.m_byteCodeBytes / (double)m_numMethods); - double totTime_ms = ((double)m_total.m_totalCycles / countsPerSec) * 1000.0; + totTime_ms = ((double)m_total.m_totalCycles / countsPerSec) * 1000.0; fprintf(f, " Time: total: %10.3f Mcycles/%10.3f ms\n", ((double)m_total.m_totalCycles / 1000000.0), totTime_ms); fprintf(f, " max: %10.3f Mcycles/%10.3f ms\n", ((double)m_maximum.m_totalCycles) / 1000000.0, @@ -7065,15 +7425,36 @@ void CompTimeSummaryInfo::Print(FILE* f) fprintf(f, " avg: %10.3f Mcycles/%10.3f ms\n", ((double)m_total.m_totalCycles) / 1000000.0 / (double)m_numMethods, totTime_ms / (double)m_numMethods); - fprintf(f, " Total time by phases:\n"); - fprintf(f, " PHASE inv/meth Mcycles time (ms) %% of total max (ms)\n"); - fprintf(f, " --------------------------------------------------------------------------------------\n"); + const char* extraHdr1 = ""; + const char* extraHdr2 = ""; +#if MEASURE_CLRAPI_CALLS + if (extraInfo) + { + extraHdr1 = " CLRs/meth % in CLR"; + extraHdr2 = "-----------------------"; + } +#endif + + fprintf(f, "\n Total time by phases:\n"); + fprintf(f, " PHASE inv/meth Mcycles time (ms) %% of total max (ms)%s\n", + extraHdr1); + fprintf(f, " ---------------------------------------------------------------------------------------%s\n", + extraHdr2); + // Ensure that at least the names array and the Phases enum have the same number of entries: assert(sizeof(PhaseNames) / sizeof(const char*) == PHASE_NUMBER_OF); for (int i = 0; i < PHASE_NUMBER_OF; i++) { - double phase_tot_ms = (((double)m_total.m_cyclesByPhase[i]) / countsPerSec) * 1000.0; - double phase_max_ms = (((double)m_maximum.m_cyclesByPhase[i]) / countsPerSec) * 1000.0; + double phase_tot_ms = (((double)m_total.m_cyclesByPhase[i]) / countsPerSec) * 1000.0; + double phase_max_ms = (((double)m_maximum.m_cyclesByPhase[i]) / countsPerSec) * 1000.0; + double phase_tot_pct = 100.0 * phase_tot_ms / totTime_ms; + +#if MEASURE_CLRAPI_CALLS + // Skip showing CLR API call info if we didn't collect any + if (i == PHASE_CLR_API && !extraInfo) + continue; +#endif + // Indent nested phases, according to depth. int ancPhase = PhaseParent[i]; while (ancPhase != -1) @@ -7081,13 +7462,33 @@ void CompTimeSummaryInfo::Print(FILE* f) fprintf(f, " "); ancPhase = PhaseParent[ancPhase]; } - fprintf(f, " %-30s %5.2f %10.2f %9.3f %8.2f%% %8.3f\n", PhaseNames[i], + fprintf(f, " %-30s %6.2f %10.2f %9.3f %8.2f%% %8.3f", PhaseNames[i], ((double)m_total.m_invokesByPhase[i]) / ((double)m_numMethods), ((double)m_total.m_cyclesByPhase[i]) / 1000000.0, phase_tot_ms, (phase_tot_ms * 100.0 / totTime_ms), phase_max_ms); + +#if MEASURE_CLRAPI_CALLS + if (extraInfo && i != PHASE_CLR_API) + { + double nest_tot_ms = (((double)m_total.m_CLRcyclesByPhase[i]) / countsPerSec) * 1000.0; + double nest_percent = nest_tot_ms * 100.0 / totTime_ms; + double calls_per_fn = ((double)m_total.m_CLRinvokesByPhase[i]) / ((double)m_numMethods); + + if (nest_percent > 0.1 || calls_per_fn > 10) + fprintf(f, " %5.1f %8.2f%%", calls_per_fn, nest_percent); + } +#endif + fprintf(f, "\n"); + } + + // Show slop if it's over a certain percentage of the total + double pslop_pct = 100.0 * m_total.m_parentPhaseEndSlop * 1000.0 / countsPerSec / totTime_ms; + if (pslop_pct >= 1.0) + { + fprintf(f, "\n 'End phase slop' should be very small (if not, there's unattributed time): %9.3f Mcycles = " + "%3.1f%% of total.\n\n", + m_total.m_parentPhaseEndSlop / 1000000.0, pslop_pct); } - fprintf(f, "\n 'End phase slop' should be very small (if not, there's unattributed time): %9.3f Mcycles.\n", - m_total.m_parentPhaseEndSlop); } if (m_numFilteredMethods > 0) { @@ -7121,19 +7522,125 @@ void CompTimeSummaryInfo::Print(FILE* f) ((double)m_filtered.m_cyclesByPhase[i]) / 1000000.0, phase_tot_ms, (phase_tot_ms * 100.0 / totTime_ms)); } - fprintf(f, "\n 'End phase slop' should be very small (if not, there's unattributed time): %9.3f Mcycles.\n", - m_filtered.m_parentPhaseEndSlop); + + double fslop_ms = m_filtered.m_parentPhaseEndSlop * 1000.0 / countsPerSec; + if (fslop_ms > 1.0) + { + fprintf(f, + "\n 'End phase slop' should be very small (if not, there's unattributed time): %9.3f Mcycles.\n", + m_filtered.m_parentPhaseEndSlop); + } } + +#if MEASURE_CLRAPI_CALLS + if (m_total.m_allClrAPIcalls > 0 && m_total.m_allClrAPIcycles > 0) + { + fprintf(f, "\n"); + if (m_totMethods > 0) + fprintf(f, " Imported %u methods.\n\n", m_numMethods + m_totMethods); + + fprintf(f, " CLR API # calls total time max time avg time %% " + "of total\n"); + fprintf(f, " -------------------------------------------------------------------------------"); + fprintf(f, "---------------------\n"); + + static const char* APInames[] = { +#define DEF_CLR_API(name) #name, +#include "ICorJitInfo_API_names.h" + }; + + unsigned shownCalls = 0; + double shownMillis = 0.0; +#ifdef DEBUG + unsigned checkedCalls = 0; + double checkedMillis = 0.0; +#endif + + for (unsigned pass = 0; pass < 2; pass++) + { + for (unsigned i = 0; i < API_ICorJitInfo_Names::API_COUNT; i++) + { + unsigned calls = m_total.m_perClrAPIcalls[i]; + if (calls == 0) + continue; + + unsigned __int64 cycles = m_total.m_perClrAPIcycles[i]; + double millis = 1000.0 * cycles / countsPerSec; + + // Don't show the small fry to keep the results manageable + if (millis < 0.5) + { + // We always show the following API because it is always called + // exactly once for each method and its body is the simplest one + // possible (it just returns an integer constant), and therefore + // it can be used to measure the overhead of adding the CLR API + // timing code. Roughly speaking, on a 3GHz x64 box the overhead + // per call should be around 40 ns when using RDTSC, compared to + // about 140 ns when using GetThreadCycles() under Windows. + if (i != API_ICorJitInfo_Names::API_getExpectedTargetArchitecture) + continue; + } + + // In the first pass we just compute the totals. + if (pass == 0) + { + shownCalls += m_total.m_perClrAPIcalls[i]; + shownMillis += millis; + continue; + } + + unsigned __int32 maxcyc = m_maximum.m_maxClrAPIcycles[i]; + double max_ms = 1000.0 * maxcyc / countsPerSec; + + fprintf(f, " %-40s", APInames[i]); // API name + fprintf(f, " %8u %9.1f ms", calls, millis); // #calls, total time + fprintf(f, " %8.1f ms %8.1f ns", max_ms, 1000000.0 * millis / calls); // max, avg time + fprintf(f, " %5.1f%%\n", 100.0 * millis / shownMillis); // % of total + +#ifdef DEBUG + checkedCalls += m_total.m_perClrAPIcalls[i]; + checkedMillis += millis; +#endif + } + } + +#ifdef DEBUG + assert(checkedCalls == shownCalls); + assert(checkedMillis == shownMillis); +#endif + + if (shownCalls > 0 || shownMillis > 0) + { + fprintf(f, " -------------------------"); + fprintf(f, "---------------------------------------------------------------------------\n"); + fprintf(f, " Total for calls shown above %8u %10.1f ms", shownCalls, shownMillis); + if (totTime_ms > 0.0) + fprintf(f, " (%4.1lf%% of overall JIT time)", shownMillis * 100.0 / totTime_ms); + fprintf(f, "\n"); + } + fprintf(f, "\n"); + } +#endif + + fprintf(f, "\n"); } JitTimer::JitTimer(unsigned byteCodeSize) : m_info(byteCodeSize) { +#if MEASURE_CLRAPI_CALLS + m_CLRcallInvokes = 0; + m_CLRcallCycles = 0; +#endif + #ifdef DEBUG m_lastPhase = (Phases)-1; +#if MEASURE_CLRAPI_CALLS + m_CLRcallAPInum = -1; +#endif #endif unsigned __int64 threadCurCycles; - if (GetThreadCycles(&threadCurCycles)) + if (_our_GetThreadCycles(&threadCurCycles)) { m_start = threadCurCycles; m_curPhaseStart = threadCurCycles; @@ -7147,9 +7654,10 @@ void JitTimer::EndPhase(Phases phase) // assert((int)phase > (int)m_lastPhase); // We should end phases in increasing order. unsigned __int64 threadCurCycles; - if (GetThreadCycles(&threadCurCycles)) + if (_our_GetThreadCycles(&threadCurCycles)) { unsigned __int64 phaseCycles = (threadCurCycles - m_curPhaseStart); + // If this is not a leaf phase, the assumption is that the last subphase must have just recently ended. // Credit the duration to "slop", the total of which should be very small. if (PhaseHasChildren[phase]) @@ -7161,6 +7669,13 @@ void JitTimer::EndPhase(Phases phase) // It is a leaf phase. Credit duration to it. m_info.m_invokesByPhase[phase]++; m_info.m_cyclesByPhase[phase] += phaseCycles; + +#if MEASURE_CLRAPI_CALLS + // Record the CLR API timing info as well. + m_info.m_CLRinvokesByPhase[phase] += m_CLRcallInvokes; + m_info.m_CLRcyclesByPhase[phase] += m_CLRcallCycles; +#endif + // Credit the phase's ancestors, if any. int ancPhase = PhaseParent[phase]; while (ancPhase != -1) @@ -7168,8 +7683,13 @@ void JitTimer::EndPhase(Phases phase) m_info.m_cyclesByPhase[ancPhase] += phaseCycles; ancPhase = PhaseParent[ancPhase]; } - // Did we just end the last phase? - if (phase + 1 == PHASE_NUMBER_OF) + +#if MEASURE_CLRAPI_CALLS + const Phases lastPhase = PHASE_CLR_API; +#else + const Phases lastPhase = PHASE_NUMBER_OF; +#endif + if (phase + 1 == lastPhase) { m_info.m_totalCycles = (threadCurCycles - m_start); } @@ -7179,11 +7699,92 @@ void JitTimer::EndPhase(Phases phase) } } } + #ifdef DEBUG m_lastPhase = phase; #endif +#if MEASURE_CLRAPI_CALLS + m_CLRcallInvokes = 0; + m_CLRcallCycles = 0; +#endif +} + +#if MEASURE_CLRAPI_CALLS + +//------------------------------------------------------------------------ +// JitTimer::CLRApiCallEnter: Start the stopwatch for an EE call. +// +// Arguments: +// apix - The API index - an "enum API_ICorJitInfo_Names" value. +// + +void JitTimer::CLRApiCallEnter(unsigned apix) +{ + assert(m_CLRcallAPInum == -1); // Nested calls not allowed + m_CLRcallAPInum = apix; + + // If we can't get the cycles, we'll just ignore this call + if (!_our_GetThreadCycles(&m_CLRcallStart)) + m_CLRcallStart = 0; +} + +//------------------------------------------------------------------------ +// JitTimer::CLRApiCallLeave: compute / record time spent in an EE call. +// +// Arguments: +// apix - The API's "enum API_ICorJitInfo_Names" value; this value +// should match the value passed to the most recent call to +// "CLRApiCallEnter" (i.e. these must come as matched pairs), +// and they also may not nest. +// + +void JitTimer::CLRApiCallLeave(unsigned apix) +{ + // Make sure we're actually inside a measured CLR call. + assert(m_CLRcallAPInum != -1); + m_CLRcallAPInum = -1; + + // Ignore this one if we don't have a valid starting counter. + if (m_CLRcallStart != 0) + { + if (JitConfig.JitEECallTimingInfo() != 0) + { + unsigned __int64 threadCurCycles; + if (_our_GetThreadCycles(&threadCurCycles)) + { + // Compute the cycles spent in the call. + threadCurCycles -= m_CLRcallStart; + + // Add the cycles to the 'phase' and bump its use count. + m_info.m_cyclesByPhase[PHASE_CLR_API] += threadCurCycles; + m_info.m_invokesByPhase[PHASE_CLR_API] += 1; + + // Add the values to the "per API" info. + m_info.m_allClrAPIcycles += threadCurCycles; + m_info.m_allClrAPIcalls += 1; + + m_info.m_perClrAPIcalls[apix] += 1; + m_info.m_perClrAPIcycles[apix] += threadCurCycles; + m_info.m_maxClrAPIcycles[apix] = max(m_info.m_maxClrAPIcycles[apix], (unsigned __int32)threadCurCycles); + + // Subtract the cycles from the enclosing phase by bumping its start time + m_curPhaseStart += threadCurCycles; + + // Update the running totals. + m_CLRcallInvokes += 1; + m_CLRcallCycles += threadCurCycles; + } + } + + m_CLRcallStart = 0; + } + + assert(m_CLRcallAPInum != -1); // No longer in this API call. + m_CLRcallAPInum = -1; } +#endif // MEASURE_CLRAPI_CALLS + CritSecObject JitTimer::s_csvLock; LPCWSTR Compiler::JitTimeLogCsv() @@ -7195,39 +7796,38 @@ LPCWSTR Compiler::JitTimeLogCsv() void JitTimer::PrintCsvHeader() { LPCWSTR jitTimeLogCsv = Compiler::JitTimeLogCsv(); - if (jitTimeLogCsv == NULL) + if (jitTimeLogCsv == nullptr) { return; } CritSecHolder csvLock(s_csvLock); - FILE* fp = _wfopen(jitTimeLogCsv, W("r")); - if (fp == nullptr) + FILE* fp = _wfopen(jitTimeLogCsv, W("a")); + if (fp != nullptr) { - // File doesn't exist, so create it and write the header - - // Use write mode, so we rewrite the file, and retain only the last compiled process/dll. - // Ex: ngen install mscorlib won't print stats for "ngen" but for "mscorsvw" - FILE* fp = _wfopen(jitTimeLogCsv, W("w")); - fprintf(fp, "\"Method Name\","); - fprintf(fp, "\"Method Index\","); - fprintf(fp, "\"IL Bytes\","); - fprintf(fp, "\"Basic Blocks\","); - fprintf(fp, "\"Opt Level\","); - fprintf(fp, "\"Loops Cloned\","); - - for (int i = 0; i < PHASE_NUMBER_OF; i++) + // Write the header if the file is empty + if (ftell(fp) == 0) { - fprintf(fp, "\"%s\",", PhaseNames[i]); - } + fprintf(fp, "\"Method Name\","); + fprintf(fp, "\"Method Index\","); + fprintf(fp, "\"IL Bytes\","); + fprintf(fp, "\"Basic Blocks\","); + fprintf(fp, "\"Opt Level\","); + fprintf(fp, "\"Loops Cloned\","); - InlineStrategy::DumpCsvHeader(fp); + for (int i = 0; i < PHASE_NUMBER_OF; i++) + { + fprintf(fp, "\"%s\",", PhaseNames[i]); + } - fprintf(fp, "\"Total Cycles\","); - fprintf(fp, "\"CPS\"\n"); + InlineStrategy::DumpCsvHeader(fp); + + fprintf(fp, "\"Total Cycles\","); + fprintf(fp, "\"CPS\"\n"); + } + fclose(fp); } - fclose(fp); } extern ICorJitHost* g_jitHost; @@ -7235,7 +7835,7 @@ extern ICorJitHost* g_jitHost; void JitTimer::PrintCsvMethodStats(Compiler* comp) { LPCWSTR jitTimeLogCsv = Compiler::JitTimeLogCsv(); - if (jitTimeLogCsv == NULL) + if (jitTimeLogCsv == nullptr) { return; } @@ -7265,7 +7865,9 @@ void JitTimer::PrintCsvMethodStats(Compiler* comp) for (int i = 0; i < PHASE_NUMBER_OF; i++) { if (!PhaseHasChildren[i]) + { totCycles += m_info.m_cyclesByPhase[i]; + } fprintf(fp, "%I64u,", m_info.m_cyclesByPhase[i]); } @@ -7277,23 +7879,14 @@ void JitTimer::PrintCsvMethodStats(Compiler* comp) } // Completes the timing of the current method, and adds it to "sum". -void JitTimer::Terminate(Compiler* comp, CompTimeSummaryInfo& sum) +void JitTimer::Terminate(Compiler* comp, CompTimeSummaryInfo& sum, bool includePhases) { -#ifdef DEBUG - unsigned __int64 totCycles2 = 0; - for (int i = 0; i < PHASE_NUMBER_OF; i++) + if (includePhases) { - if (!PhaseHasChildren[i]) - totCycles2 += m_info.m_cyclesByPhase[i]; + PrintCsvMethodStats(comp); } - // We include m_parentPhaseEndSlop in the next phase's time also (we probably shouldn't) - // totCycles2 += m_info.m_parentPhaseEndSlop; - assert(totCycles2 == m_info.m_totalCycles); -#endif - - PrintCsvMethodStats(comp); - sum.AddInfo(m_info); + sum.AddInfo(m_info, includePhases); } #endif // FEATURE_JIT_METHOD_PERF @@ -7331,6 +7924,10 @@ void Compiler::MemStats::PrintByKind(FILE* f) void Compiler::AggregateMemStats::Print(FILE* f) { fprintf(f, "For %9u methods:\n", nMethods); + if (nMethods == 0) + { + return; + } fprintf(f, " count: %12u (avg %7u per method)\n", allocCnt, allocCnt / nMethods); fprintf(f, " alloc size : %12llu (avg %7llu per method)\n", allocSz, allocSz / nMethods); fprintf(f, " max alloc : %12llu\n", allocSzMax); @@ -8520,6 +9117,9 @@ int cTreeFlagsIR(Compiler* comp, GenTree* tree) break; case GT_MUL: +#if defined(_TARGET_X86_) && !defined(LEGACY_BACKEND) + case GT_MUL_LONG: +#endif if (tree->gtFlags & GTF_MUL_64RSLT) { @@ -10124,11 +10724,6 @@ void cNodeIR(Compiler* comp, GenTree* tree) } break; - case GT_STORE_CLS_VAR: - - chars += printf(" ???"); - break; - case GT_LEA: GenTreeAddrMode* lea = tree->AsAddrMode(); diff --git a/src/jit/compiler.h b/src/jit/compiler.h index 05047c5..d8cd491 100644 --- a/src/jit/compiler.h +++ b/src/jit/compiler.h @@ -691,12 +691,21 @@ public: // is now TYP_INT in the local variable table. It's not really unused, because it's in the tree. assert(varTypeIsStruct(lvType) || (lvType == TYP_BLK) || (lvPromoted && lvUnusedStruct)); + +#if defined(FEATURE_SIMD) && !defined(_TARGET_64BIT_) + // For 32-bit architectures, we make local variable SIMD12 types 16 bytes instead of just 12. We can't do + // this for arguments, which must be passed according the defined ABI. + if ((lvType == TYP_SIMD12) && !lvIsParam) + { + assert(lvExactSize == 12); + return 16; + } +#endif // defined(FEATURE_SIMD) && !defined(_TARGET_64BIT_) + return (unsigned)(roundUp(lvExactSize, TARGET_POINTER_SIZE)); } -#if defined(DEBUGGING_SUPPORT) || defined(DEBUG) unsigned lvSlotNum; // original slot # (if remapped) -#endif typeInfo lvVerTypeInfo; // type info needed for verification @@ -926,6 +935,14 @@ extern const char* PhaseNames[]; extern const char* PhaseEnums[]; extern const LPCWSTR PhaseShortNames[]; +// The following enum provides a simple 1:1 mapping to CLR API's +enum API_ICorJitInfo_Names +{ +#define DEF_CLR_API(name) API_##name, +#include "ICorJitInfo_API_names.h" + API_COUNT +}; + //--------------------------------------------------------------- // Compilation time. // @@ -949,6 +966,10 @@ struct CompTimeInfo unsigned __int64 m_totalCycles; unsigned __int64 m_invokesByPhase[PHASE_NUMBER_OF]; unsigned __int64 m_cyclesByPhase[PHASE_NUMBER_OF]; +#if MEASURE_CLRAPI_CALLS + unsigned __int64 m_CLRinvokesByPhase[PHASE_NUMBER_OF]; + unsigned __int64 m_CLRcyclesByPhase[PHASE_NUMBER_OF]; +#endif // For better documentation, we call EndPhase on // non-leaf phases. We should also call EndPhase on the // last leaf subphase; obviously, the elapsed cycles between the EndPhase @@ -960,12 +981,25 @@ struct CompTimeInfo unsigned __int64 m_parentPhaseEndSlop; bool m_timerFailure; +#if MEASURE_CLRAPI_CALLS + // The following measures the time spent inside each individual CLR API call. + unsigned m_allClrAPIcalls; + unsigned m_perClrAPIcalls[API_ICorJitInfo_Names::API_COUNT]; + unsigned __int64 m_allClrAPIcycles; + unsigned __int64 m_perClrAPIcycles[API_ICorJitInfo_Names::API_COUNT]; + unsigned __int32 m_maxClrAPIcycles[API_ICorJitInfo_Names::API_COUNT]; +#endif // MEASURE_CLRAPI_CALLS + CompTimeInfo(unsigned byteCodeBytes); #endif }; #ifdef FEATURE_JIT_METHOD_PERF +#if MEASURE_CLRAPI_CALLS +struct WrapICorJitInfo; +#endif + // This class summarizes the JIT time information over the course of a run: the number of methods compiled, // and the total and maximum timings. (These are instances of the "CompTimeInfo" type described above). // The operation of adding a single method's timing to the summary may be performed concurrently by several @@ -977,6 +1011,7 @@ class CompTimeSummaryInfo static CritSecObject s_compTimeSummaryLock; int m_numMethods; + int m_totMethods; CompTimeInfo m_total; CompTimeInfo m_maximum; @@ -996,13 +1031,14 @@ public: // This is the unique CompTimeSummaryInfo object for this instance of the runtime. static CompTimeSummaryInfo s_compTimeSummary; - CompTimeSummaryInfo() : m_numMethods(0), m_total(0), m_maximum(0), m_numFilteredMethods(0), m_filtered(0) + CompTimeSummaryInfo() + : m_numMethods(0), m_totMethods(0), m_total(0), m_maximum(0), m_numFilteredMethods(0), m_filtered(0) { } // Assumes that "info" is a completed CompTimeInfo for a compilation; adds it to the summary. // This is thread safe. - void AddInfo(CompTimeInfo& info); + void AddInfo(CompTimeInfo& info, bool includePhases); // Print the summary information to "f". // This is not thread-safe; assumed to be called by only one thread. @@ -1017,6 +1053,13 @@ class JitTimer { unsigned __int64 m_start; // Start of the compilation. unsigned __int64 m_curPhaseStart; // Start of the current phase. +#if MEASURE_CLRAPI_CALLS + unsigned __int64 m_CLRcallStart; // Start of the current CLR API call (if any). + unsigned __int64 m_CLRcallInvokes; // CLR API invokes under current outer so far + unsigned __int64 m_CLRcallCycles; // CLR API cycles under current outer so far. + int m_CLRcallAPInum; // The enum/index of the current CLR API call (or -1). + static double s_cyclesPerSec; // Cached for speedier measurements +#endif #ifdef DEBUG Phases m_lastPhase; // The last phase that was completed (or (Phases)-1 to start). #endif @@ -1045,9 +1088,15 @@ public: // Ends the current phase (argument is for a redundant check). void EndPhase(Phases phase); +#if MEASURE_CLRAPI_CALLS + // Start and end a timed CLR API call. + void CLRApiCallEnter(unsigned apix); + void CLRApiCallLeave(unsigned apix); +#endif // MEASURE_CLRAPI_CALLS + // Completes the timing of the current method, which is assumed to have "byteCodeBytes" bytes of bytecode, // and adds it to "sum". - void Terminate(Compiler* comp, CompTimeSummaryInfo& sum); + void Terminate(Compiler* comp, CompTimeSummaryInfo& sum, bool includePhases); // Attempts to query the cycle counter of the current thread. If successful, returns "true" and sets // *cycles to the cycle counter value. Otherwise, returns false and sets the "m_timerFailure" flag of @@ -1164,7 +1213,13 @@ struct fgArgTabEntry regNumber otherRegNum; // The (second) register to use when passing this argument. SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR structDesc; -#endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) +#elif defined(_TARGET_X86_) + __declspec(property(get = getIsStruct)) bool isStruct; + bool getIsStruct() + { + return varTypeIsStruct(node); + } +#endif // _TARGET_X86_ #ifdef _TARGET_ARM_ void SetIsHfaRegArg(bool hfaRegArg) @@ -1293,6 +1348,10 @@ public: { return hasStackArgs; } + bool AreArgsComplete() const + { + return argsComplete; + } }; #ifdef DEBUG @@ -1939,8 +1998,6 @@ public: GenTreeArgList* gtNewArgList(GenTreePtr op1, GenTreePtr op2); GenTreeArgList* gtNewArgList(GenTreePtr op1, GenTreePtr op2, GenTreePtr op3); - GenTreeArgList* gtNewAggregate(GenTree* element); - static fgArgTabEntryPtr gtArgEntryByArgNum(GenTreePtr call, unsigned argNum); static fgArgTabEntryPtr gtArgEntryByNode(GenTreePtr call, GenTreePtr node); fgArgTabEntryPtr gtArgEntryByLateArgIndex(GenTreePtr call, unsigned lateArgInx); @@ -1975,7 +2032,18 @@ public: GenTreePtr gtClone(GenTree* tree, bool complexOK = false); - GenTreePtr gtCloneExpr(GenTree* tree, unsigned addFlags = 0, unsigned varNum = (unsigned)-1, int varVal = 0); + // If `tree` is a lclVar with lclNum `varNum`, return an IntCns with value `varVal`; otherwise, + // create a copy of `tree`, adding specified flags, replacing uses of lclVar `deepVarNum` with + // IntCnses with value `deepVarVal`. + GenTreePtr gtCloneExpr( + GenTree* tree, unsigned addFlags, unsigned varNum, int varVal, unsigned deepVarNum, int deepVarVal); + + // Create a copy of `tree`, optionally adding specifed flags, and optionally mapping uses of local + // `varNum` to int constants with value `varVal`. + GenTreePtr gtCloneExpr(GenTree* tree, unsigned addFlags = 0, unsigned varNum = (unsigned)-1, int varVal = 0) + { + return gtCloneExpr(tree, addFlags, varNum, varVal, varNum, varVal); + } GenTreePtr gtReplaceTree(GenTreePtr stmt, GenTreePtr tree, GenTreePtr replacementTree); @@ -1997,7 +2065,7 @@ public: unsigned gtHashValue(GenTree* tree); - unsigned gtSetListOrder(GenTree* list, bool regs); + unsigned gtSetListOrder(GenTree* list, bool regs, bool isListCallArgs); void gtWalkOp(GenTree** op1, GenTree** op2, GenTree* adr, bool constOnly); @@ -2277,7 +2345,8 @@ public: DNER_VMNeedsStackAddr, DNER_LiveInOutOfHandler, DNER_LiveAcrossUnmanagedCall, - DNER_BlockOp, // Is read or written via a block operation that explicitly takes the address. + DNER_BlockOp, // Is read or written via a block operation that explicitly takes the address. + DNER_IsStructArg, // Is a struct passed as an argument in a way that requires a stack location. #ifdef JIT32_GCENCODER DNER_PinningRef, #endif @@ -2439,7 +2508,6 @@ public: void lvaInit(); - unsigned lvaArgSize(const void* argTok); unsigned lvaLclSize(unsigned varNum); unsigned lvaLclExactSize(unsigned varNum); @@ -2712,9 +2780,10 @@ protected: void impImportNewObjArray(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_CALL_INFO* pCallInfo); - bool impCanPInvokeInline(var_types callRetTyp); - bool impCanPInvokeInlineCallSite(var_types callRetTyp); - void impCheckForPInvokeCall(GenTreePtr call, CORINFO_METHOD_HANDLE methHnd, CORINFO_SIG_INFO* sig, unsigned mflags); + bool impCanPInvokeInline(BasicBlock* block); + bool impCanPInvokeInlineCallSite(BasicBlock* block); + void impCheckForPInvokeCall( + GenTreePtr call, CORINFO_METHOD_HANDLE methHnd, CORINFO_SIG_INFO* sig, unsigned mflags, BasicBlock* block); GenTreePtr impImportIndirectCall(CORINFO_SIG_INFO* sig, IL_OFFSETX ilOffset = BAD_IL_OFFSET); void impPopArgsForUnmanagedCall(GenTreePtr call, CORINFO_SIG_INFO* sig); @@ -2739,8 +2808,6 @@ protected: GenTreePtr impFixupCallStructReturn(GenTreePtr call, CORINFO_CLASS_HANDLE retClsHnd); - GenTreePtr impInitCallLongReturn(GenTreePtr call); - GenTreePtr impFixupStructReturnType(GenTreePtr op, CORINFO_CLASS_HANDLE retClsHnd); #ifdef DEBUG @@ -2764,7 +2831,6 @@ protected: void impImportLeave(BasicBlock* block); void impResetLeaveBlock(BasicBlock* block, unsigned jmpAddr); - BOOL impLocAllocOnStack(); GenTreePtr impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig, @@ -2868,6 +2934,8 @@ public: unsigned flags, void* compileTimeHandle); + GenTreePtr getRuntimeContextTree(CORINFO_RUNTIME_LOOKUP_KIND kind); + GenTreePtr impRuntimeLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP* pLookup, void* compileTimeHandle); @@ -3148,8 +3216,6 @@ private: static LONG jitNestingLevel; #endif // DEBUG - bool seenConditionalJump; - static BOOL impIsAddressInLocal(GenTreePtr tree, GenTreePtr* lclVarTreeOut); void impMakeDiscretionaryInlineObservations(InlineInfo* pInlineInfo, InlineResult* inlineResult); @@ -3455,8 +3521,9 @@ public: void fgMorphStmts(BasicBlock* block, bool* mult, bool* lnot, bool* loadw); void fgMorphBlocks(); - bool fgMorphBlockStmt(BasicBlock* block, GenTreePtr stmt DEBUGARG(const char* msg)); + bool fgMorphBlockStmt(BasicBlock* block, GenTreeStmt* stmt DEBUGARG(const char* msg)); + void fgCheckArgCnt(); void fgSetOptions(); #ifdef DEBUG @@ -3845,7 +3912,7 @@ public: // var_types getReturnTypeForStruct(CORINFO_CLASS_HANDLE clsHnd, structPassingKind* wbPassStruct = nullptr, - unsigned structSize = 0); + unsigned structSize = 0); #ifdef DEBUG // Print a representation of "vnp" or "vn" on standard output. @@ -4072,7 +4139,7 @@ public: void fgUnreachableBlock(BasicBlock* block); - void fgRemoveJTrue(BasicBlock* block); + void fgRemoveConditionalJump(BasicBlock* block); BasicBlock* fgLastBBInMainFunction(); @@ -4204,6 +4271,7 @@ public: void fgDebugCheckLinks(bool morphTrees = false); void fgDebugCheckNodeLinks(BasicBlock* block, GenTreePtr stmt); void fgDebugCheckFlags(GenTreePtr tree); + void fgDebugCheckFlagsHelper(GenTreePtr tree, unsigned treeFlags, unsigned chkFlags); #endif #ifdef LEGACY_BACKEND @@ -4305,7 +4373,7 @@ protected: void fgLinkBasicBlocks(); - void fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* jumpTarget); + unsigned fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* jumpTarget); void fgCheckBasicBlockControlFlow(); @@ -4380,13 +4448,6 @@ private: GenTree* fgInsertCommaFormTemp(GenTree** ppTree, CORINFO_CLASS_HANDLE structType = nullptr); GenTree* fgMakeMultiUse(GenTree** ppTree); - // After replacing oldChild with newChild, fixup the fgArgTabEntryPtr - // if it happens to be an argument to a call. - void fgFixupIfCallArg(ArrayStack* parentStack, GenTree* oldChild, GenTree* newChild); - -public: - void fgFixupArgTabEntryPtr(GenTreePtr parentCall, GenTreePtr oldArg, GenTreePtr newArg); - private: // Recognize a bitwise rotation pattern and convert into a GT_ROL or a GT_ROR node. GenTreePtr fgRecognizeAndMorphBitwiseRotation(GenTreePtr tree); @@ -4440,16 +4501,11 @@ private: // for sufficiently small offsets, we can rely on OS page protection to implicitly null-check addresses that we // know will be dereferenced. To know that reliance on implicit null checking is sound, we must further know that // all offsets between the top-level indirection and the bottom are constant, and that their sum is sufficiently - // small; hence the other fields of MorphAddrContext. Finally, the odd structure of GT_COPYBLK, in which the second - // argument is a GT_LIST, requires us to "tell" that List node that its parent is a GT_COPYBLK, so it "knows" that - // each of its arguments should be evaluated in MACK_Ind contexts. (This would not be true for GT_LIST nodes - // representing method call argument lists.) + // small; hence the other fields of MorphAddrContext. enum MorphAddrContextKind { MACK_Ind, MACK_Addr, - MACK_CopyBlock, // This is necessary so we know we have to start a new "Ind" context for each of the - // addresses in the arg list. }; struct MorphAddrContext { @@ -4513,7 +4569,7 @@ private: void fgMorphCallInline(GenTreeCall* call, InlineResult* result); void fgMorphCallInlineHelper(GenTreeCall* call, InlineResult* result); #if DEBUG - void fgNoteNonInlineCandidate(GenTreePtr tree, GenTreeCall* call); + void fgNoteNonInlineCandidate(GenTreeStmt* stmt, GenTreeCall* call); static fgWalkPreFn fgFindNonInlineCandidate; #endif GenTreePtr fgOptimizeDelegateConstructor(GenTreePtr call, CORINFO_CONTEXT_HANDLE* ExactContextHnd); @@ -4525,16 +4581,14 @@ private: GenTreePtr fgMorphGetStructAddr(GenTreePtr* pTree, CORINFO_CLASS_HANDLE clsHnd, bool isRValue = false); GenTreePtr fgMorphBlkNode(GenTreePtr tree, bool isDest); GenTreePtr fgMorphBlockOperand(GenTreePtr tree, var_types asgType, unsigned blockWidth, bool isDest); + void fgMorphUnsafeBlk(GenTreeObj* obj); GenTreePtr fgMorphCopyBlock(GenTreePtr tree); GenTreePtr fgMorphForRegisterFP(GenTreePtr tree); GenTreePtr fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac = nullptr); GenTreePtr fgMorphSmpOpPre(GenTreePtr tree); - GenTreePtr fgMorphDivByConst(GenTreeOp* tree); - GenTreePtr fgMorphModByConst(GenTreeOp* tree); GenTreePtr fgMorphModToSubMulDiv(GenTreeOp* tree); GenTreePtr fgMorphSmpOpOptional(GenTreeOp* tree); GenTreePtr fgMorphRecognizeBoxNullable(GenTree* compare); - bool fgShouldUseMagicNumberDivide(GenTreeOp* tree); GenTreePtr fgMorphToEmulatedFP(GenTreePtr tree); GenTreePtr fgMorphConst(GenTreePtr tree); @@ -4544,11 +4598,12 @@ public: private: #if LOCAL_ASSERTION_PROP + void fgKillDependentAssertionsSingle(unsigned lclNum DEBUGARG(GenTreePtr tree)); void fgKillDependentAssertions(unsigned lclNum DEBUGARG(GenTreePtr tree)); #endif void fgMorphTreeDone(GenTreePtr tree, GenTreePtr oldTree = nullptr DEBUGARG(int morphNum = 0)); - GenTreePtr fgMorphStmt; + GenTreeStmt* fgMorphStmt; unsigned fgGetBigOffsetMorphingTemp(var_types type); // We cache one temp per type to be // used when morphing big offset. @@ -4564,7 +4619,6 @@ private: void fgMarkUseDef(GenTreeLclVarCommon* tree, GenTree* asgdLclVar = nullptr); -#ifdef DEBUGGING_SUPPORT void fgBeginScopeLife(VARSET_TP* inScope, VarScopeDsc* var); void fgEndScopeLife(VARSET_TP* inScope, VarScopeDsc* var); @@ -4578,8 +4632,6 @@ private: void fgDispDebugScopes(); #endif // DEBUG -#endif // DEBUGGING_SUPPORT - //------------------------------------------------------------------------- // // The following keeps track of any code we've added for things like array @@ -4622,6 +4674,7 @@ private: void fgInvokeInlineeCompiler(GenTreeCall* call, InlineResult* result); void fgInsertInlineeBlocks(InlineInfo* pInlineInfo); GenTreePtr fgInlinePrependStatements(InlineInfo* inlineInfo); + void fgInlineAppendStatements(InlineInfo* inlineInfo, BasicBlock* block, GenTreePtr stmt); #if FEATURE_MULTIREG_RET GenTreePtr fgGetStructAsStructPtr(GenTreePtr tree); @@ -4905,6 +4958,7 @@ public: #define LPFLG_VAR_LIMIT 0x0100 // iterator is compared with a local var (var # found in lpVarLimit) #define LPFLG_CONST_LIMIT 0x0200 // iterator is compared with a constant (found in lpConstLimit) #define LPFLG_ARRLEN_LIMIT 0x0400 // iterator is compared with a.len or a[i].len (found in lpArrLenLimit) +#define LPFLG_SIMD_LIMIT 0x0080 // iterator is compared with Vector.Count (found in lpConstLimit) #define LPFLG_HAS_PREHEAD 0x0800 // lpHead is known to be a preHead for this loop #define LPFLG_REMOVED 0x1000 // has been removed from the loop table (unrolled or optimized away) @@ -5205,6 +5259,11 @@ protected: static const int MIN_CSE_COST = 2; + // Keeps tracked cse indices + BitVecTraits* cseTraits; + EXPSET_TP cseFull; + EXPSET_TP cseEmpty; + /* Generic list of nodes - used by the CSE logic */ struct treeLst @@ -6237,7 +6296,7 @@ public: BOOL eeIsValueClass(CORINFO_CLASS_HANDLE clsHnd); -#if defined(DEBUG) || defined(FEATURE_JIT_METHOD_PERF) || defined(FEATURE_SIMD) +#if defined(DEBUG) || defined(FEATURE_JIT_METHOD_PERF) || defined(FEATURE_SIMD) || defined(TRACK_LSRA_STATS) bool IsSuperPMIException(unsigned code) { @@ -6334,10 +6393,19 @@ public: #endif } + inline bool IsTargetAbi(CORINFO_RUNTIME_ABI abi) + { +#if COR_JIT_EE_VERSION > 460 + return eeGetEEInfo()->targetAbi == abi; +#else + return CORINFO_DESKTOP_ABI == abi; +#endif + } + inline bool generateCFIUnwindCodes() { -#if COR_JIT_EE_VERSION > 460 && defined(UNIX_AMD64_ABI) - return eeGetEEInfo()->targetAbi == CORINFO_CORERT_ABI; +#ifdef UNIX_AMD64_ABI + return IsTargetAbi(CORINFO_CORERT_ABI); #else return false; #endif @@ -6522,8 +6590,6 @@ private: public: CodeGenInterface* codeGen; -#ifdef DEBUGGING_SUPPORT - // The following holds information about instr offsets in terms of generated code. struct IPmappingDsc @@ -6553,7 +6619,6 @@ public: typedef SimplerHashTable, IL_OFFSETX, JitSimplerHashBehavior> CallSiteILOffsetTable; CallSiteILOffsetTable* genCallSite2ILOffsetMap; -#endif // DEBUGGING_SUPPORT unsigned genReturnLocal; // Local number for the return value when applicable. BasicBlock* genReturnBB; // jumped to when not optimizing for speed. @@ -6588,8 +6653,14 @@ public: { return codeGen->doDoubleAlign(); } - DWORD getCanDoubleAlign(); // Defined & used only by RegAlloc -#endif // DOUBLE_ALIGN + DWORD getCanDoubleAlign(); + bool shouldDoubleAlign(unsigned refCntStk, + unsigned refCntReg, + unsigned refCntWtdReg, + unsigned refCntStkParam, + unsigned refCntWtdStkDbl); +#endif // DOUBLE_ALIGN + __declspec(property(get = getFullPtrRegMap, put = setFullPtrRegMap)) bool genFullPtrRegMap; bool getFullPtrRegMap() { @@ -6829,6 +6900,11 @@ private: return InstructionSet_AVX; } + if (CanUseSSE3_4()) + { + return InstructionSet_SSE3_4; + } + // min bar is SSE2 assert(canUseSSE2()); return InstructionSet_SSE2; @@ -7072,7 +7148,7 @@ private: // and small int base type vectors. SIMDIntrinsicID impSIMDIntegralRelOpGreaterThanOrEqual( CORINFO_CLASS_HANDLE typeHnd, unsigned simdVectorSize, var_types baseType, GenTree** op1, GenTree** op2); -#endif // defined(_TARGET_AMD64_) && !defined(LEGACY_BACKEND) +#endif // defined(_TARGET_XARCH_) && !defined(LEGACY_BACKEND) void setLclRelatedToSIMDIntrinsic(GenTreePtr tree); bool areFieldsContiguous(GenTreePtr op1, GenTreePtr op2); @@ -7261,6 +7337,16 @@ private: // Returns true if the TYP_SIMD locals on stack are aligned at their // preferred byte boundary specified by getSIMDTypeAlignment(). + // + // As per the Intel manual, the preferred alignment for AVX vectors is 32-bytes. On Amd64, + // RSP/EBP is aligned at 16-bytes, therefore to align SIMD types at 32-bytes we need even + // RSP/EBP to be 32-byte aligned. It is not clear whether additional stack space used in + // aligning stack is worth the benefit and for now will use 16-byte alignment for AVX + // 256-bit vectors with unaligned load/stores to/from memory. On x86, the stack frame + // is aligned to 4 bytes. We need to extend existing support for double (8-byte) alignment + // to 16 or 32 byte alignment for frames with local SIMD vars, if that is determined to be + // profitable. + // bool isSIMDTypeLocalAligned(unsigned varNum) { #if defined(FEATURE_SIMD) && ALIGN_SIMD_TYPES @@ -7270,8 +7356,7 @@ private: int off = lvaFrameAddress(varNum, &ebpBased); // TODO-Cleanup: Can't this use the lvExactSize on the varDsc? int alignment = getSIMDTypeAlignment(lvaTable[varNum].lvType); - bool isAligned = ((off % alignment) == 0); - noway_assert(isAligned || lvaTable[varNum].lvIsParam); + bool isAligned = (alignment <= STACK_ALIGN) && ((off % alignment) == 0); return isAligned; } #endif // FEATURE_SIMD @@ -7289,6 +7374,16 @@ private: #endif } + // Whether SSE3, SSE3, SSE4.1 and SSE4.2 is available + bool CanUseSSE3_4() const + { +#ifdef _TARGET_XARCH_ + return opts.compCanUseSSE3_4; +#else + return false; +#endif + } + bool canUseAVX() const { #ifdef FEATURE_AVX_SUPPORT @@ -7393,21 +7488,21 @@ public: struct Options { - CORJIT_FLAGS* jitFlags; // all flags passed from the EE - unsigned eeFlags; // CorJitFlag flags passed from the EE - unsigned compFlags; // method attributes + JitFlags* jitFlags; // all flags passed from the EE + unsigned compFlags; // method attributes codeOptimize compCodeOpt; // what type of code optimizations bool compUseFCOMI; bool compUseCMOV; #ifdef _TARGET_XARCH_ - bool compCanUseSSE2; // Allow CodeGen to use "movq XMM" instructions + bool compCanUseSSE2; // Allow CodeGen to use "movq XMM" instructions + bool compCanUseSSE3_4; // Allow CodeGen to use SSE3, SSSE3, SSE4.1 and SSE4.2 instructions #ifdef FEATURE_AVX_SUPPORT bool compCanUseAVX; // Allow CodeGen to use AVX 256-bit vectors for SIMD operations -#endif -#endif +#endif // FEATURE_AVX_SUPPORT +#endif // _TARGET_XARCH_ // optimize maximally and/or favor speed over size? @@ -7464,7 +7559,7 @@ public: #ifdef FEATURE_READYTORUN_COMPILER inline bool IsReadyToRun() { - return (eeFlags & CORJIT_FLG_READYTORUN) != 0; + return jitFlags->IsSet(JitFlags::JIT_FLAG_READYTORUN); } #else inline bool IsReadyToRun() @@ -7478,7 +7573,7 @@ public: inline bool ShouldUsePInvokeHelpers() { #if COR_JIT_EE_VERSION > 460 - return (jitFlags->corJitFlags2 & CORJIT_FLG2_USE_PINVOKE_HELPERS) != 0; + return jitFlags->IsSet(JitFlags::JIT_FLAG_USE_PINVOKE_HELPERS); #else return false; #endif @@ -7489,7 +7584,7 @@ public: inline bool IsReversePInvoke() { #if COR_JIT_EE_VERSION > 460 - return (jitFlags->corJitFlags2 & CORJIT_FLG2_REVERSE_PINVOKE) != 0; + return jitFlags->IsSet(JitFlags::JIT_FLAG_REVERSE_PINVOKE); #else return false; #endif @@ -7499,7 +7594,7 @@ public: inline bool IsJit32Compat() { #if defined(_TARGET_X86_) && COR_JIT_EE_VERSION > 460 - return (jitFlags->corJitFlags2 & CORJIT_FLG2_DESKTOP_QUIRKS) != 0; + return jitFlags->IsSet(JitFlags::JIT_FLAG_DESKTOP_QUIRKS); #else return false; #endif @@ -7509,7 +7604,7 @@ public: inline bool IsJit64Compat() { #if defined(_TARGET_AMD64_) && COR_JIT_EE_VERSION > 460 - return (jitFlags->corJitFlags2 & CORJIT_FLG2_DESKTOP_QUIRKS) != 0; + return jitFlags->IsSet(JitFlags::JIT_FLAG_DESKTOP_QUIRKS); #elif defined(_TARGET_AMD64_) && !defined(FEATURE_CORECLR) return true; #else @@ -7517,14 +7612,10 @@ public: #endif } -#ifdef DEBUGGING_SUPPORT bool compScopeInfo; // Generate the LocalVar info ? bool compDbgCode; // Generate debugger-friendly code? bool compDbgInfo; // Gather debugging info? bool compDbgEnC; -#else - static const bool compDbgCode; -#endif #ifdef PROFILING_SUPPORTED bool compNoPInvokeInlineCB; @@ -7584,6 +7675,7 @@ public: bool altJit; // True if we are an altjit and are compiling this method #ifdef DEBUG + bool optRepeat; // Repeat optimizer phases k times bool compProcedureSplittingEH; // Separate cold code from hot code for functions with EH bool dspCode; // Display native code generated bool dspEHTable; // Display the EH table reported to the VM @@ -7623,9 +7715,11 @@ public: // for any call. We have a plan for not needing for stubs though bool compNeedStackProbes; - // Whether to emit Enter/Leave/TailCall hooks using a dummy stub (DummyProfilerELTStub()) - // This options helps one to make JIT behave as if it is under profiler. +#ifdef PROFILING_SUPPORTED + // Whether to emit Enter/Leave/TailCall hooks using a dummy stub (DummyProfilerELTStub()). + // This option helps make the JIT behave as if it is running under a profiler. bool compJitELTHookEnabled; +#endif // PROFILING_SUPPORTED #if FEATURE_TAILCALL_OPT // Whether opportunistic or implicit tail call optimization is enabled. @@ -7650,8 +7744,6 @@ public: #ifdef DEBUG - static bool s_dspMemStats; // Display per-phase memory statistics for every function - template T dspPtr(T p) { @@ -7759,8 +7851,8 @@ public: codeOptimize compCodeOpt() { #if 0 - // Switching between size & speed has measurable throughput impact - // (3.5% on NGen mscorlib when measured). It used to be enabled for + // Switching between size & speed has measurable throughput impact + // (3.5% on NGen mscorlib when measured). It used to be enabled for // DEBUG, but should generate identical code between CHK & RET builds, // so that's not acceptable. // TODO-Throughput: Figure out what to do about size vs. speed & throughput. @@ -7772,10 +7864,6 @@ public: #endif } -#ifdef DEBUG - CLRRandom* inlRNG; -#endif - //--------------------- Info about the procedure -------------------------- struct Info @@ -7855,8 +7943,6 @@ public: // and the VM expects that, or the JIT is a "self-host" compiler // (e.g., x86 hosted targeting x86) and the VM expects that. -#if defined(DEBUGGING_SUPPORT) || defined(DEBUG) - /* The following holds IL scope information about local variables. */ @@ -7871,8 +7957,6 @@ public: unsigned compStmtOffsetsCount; ICorDebugInfo::BoundaryTypes compStmtOffsetsImplicit; -#endif // DEBUGGING_SUPPORT || DEBUG - #define CPU_X86 0x0100 // The generic X86 CPU #define CPU_X86_PENTIUM_4 0x0110 @@ -7937,9 +8021,12 @@ public: // Such method's compRetNativeType is TYP_STRUCT without a hidden RetBufArg return varTypeIsStruct(info.compRetNativeType) && (info.compRetBuffArg == BAD_VAR_NUM); #endif // TARGET_XXX + #else // not FEATURE_MULTIREG_RET + // For this architecture there are no multireg returns return false; + #endif // FEATURE_MULTIREG_RET } @@ -7960,7 +8047,7 @@ public: void compDispLocalVars(); -#endif // DEBUGGING_SUPPORT || DEBUG +#endif // DEBUG //-------------------------- Global Compiler Data ------------------------------------ @@ -8059,19 +8146,22 @@ public: CORINFO_METHOD_INFO* methodInfo, void** methodCodePtr, ULONG* methodCodeSize, - CORJIT_FLAGS* compileFlags); + JitFlags* compileFlags); void compCompileFinish(); int compCompileHelper(CORINFO_MODULE_HANDLE classPtr, COMP_HANDLE compHnd, CORINFO_METHOD_INFO* methodInfo, void** methodCodePtr, ULONG* methodCodeSize, - CORJIT_FLAGS* compileFlags, + JitFlags* compileFlags, CorInfoInstantiationVerification instVerInfo); ArenaAllocator* compGetAllocator(); #if MEASURE_MEM_ALLOC + + static bool s_dspMemStats; // Display per-phase memory statistics for every function + struct MemStats { unsigned allocCnt; // # of allocs @@ -8195,9 +8285,8 @@ public: void compDspSrcLinesByLineNum(unsigned line, bool seek = false); #endif // DEBUG -//------------------------------------------------------------------------- + //------------------------------------------------------------------------- -#ifdef DEBUGGING_SUPPORT typedef ListNode VarScopeListNode; struct VarScopeMapInfo @@ -8255,8 +8344,6 @@ public: void compDispScopeLists(); #endif // DEBUG -#endif // DEBUGGING_SUPPORT - bool compIsProfilerHookNeeded(); //------------------------------------------------------------------------- @@ -8299,7 +8386,7 @@ public: protected: size_t compMaxUncheckedOffsetForNullObject; - void compInitOptions(CORJIT_FLAGS* compileFlags); + void compInitOptions(JitFlags* compileFlags); void compSetProcessor(); void compInitDebuggingInfo(); @@ -8307,16 +8394,22 @@ protected: #ifdef _TARGET_ARMARCH_ bool compRsvdRegCheck(FrameLayoutState curState); #endif - void compCompile(void** methodCodePtr, ULONG* methodCodeSize, CORJIT_FLAGS* compileFlags); + void compCompile(void** methodCodePtr, ULONG* methodCodeSize, JitFlags* compileFlags); - // Data required for generating profiler Enter/Leave/TailCall hooks - CLANG_FORMAT_COMMENT_ANCHOR; + // Clear annotations produced during optimizations; to be used between iterations when repeating opts. + void ResetOptAnnotations(); + + // Regenerate loop descriptors; to be used between iterations when repeating opts. + void RecomputeLoopInfo(); #ifdef PROFILING_SUPPORTED + // Data required for generating profiler Enter/Leave/TailCall hooks + bool compProfilerHookNeeded; // Whether profiler Enter/Leave/TailCall hook needs to be generated for the method void* compProfilerMethHnd; // Profiler handle of the method being compiled. Passed as param to ELT callbacks bool compProfilerMethHndIndirected; // Whether compProfilerHandle is pointer to the handle or is an actual handle #endif + #ifdef _TARGET_AMD64_ bool compQuirkForPPP(); // Check if this method should be Quirked for the PPP issue #endif @@ -8692,6 +8785,18 @@ private: #endif inline void EndPhase(Phases phase); // Indicate the end of the given phase. +#if MEASURE_CLRAPI_CALLS + // Thin wrappers that call into JitTimer (if present). + inline void CLRApiCallEnter(unsigned apix); + inline void CLRApiCallLeave(unsigned apix); + +public: + inline void CLR_API_Enter(API_ICorJitInfo_Names ename); + inline void CLR_API_Leave(API_ICorJitInfo_Names ename); + +private: +#endif + #if defined(DEBUG) || defined(INLINE_DATA) || defined(FEATURE_CLRSQM) // These variables are associated with maintaining SQM data about compile time. unsigned __int64 m_compCyclesAtEndOfInlining; // The thread-virtualized cycle count at the end of the inlining phase diff --git a/src/jit/compiler.hpp b/src/jit/compiler.hpp index eb8eb19..e8358fd 100644 --- a/src/jit/compiler.hpp +++ b/src/jit/compiler.hpp @@ -473,10 +473,17 @@ inline unsigned Compiler::funGetFuncIdx(BasicBlock* block) #endif // !FEATURE_EH_FUNCLETS -/***************************************************************************** - * - * Map a register mask to a register number - */ +//------------------------------------------------------------------------------ +// genRegNumFromMask : Maps a single register mask to a register number. +// +// Arguments: +// mask - the register mask +// +// Return Value: +// The number of the register contained in the mask. +// +// Assumptions: +// The mask contains one and only one register. inline regNumber genRegNumFromMask(regMaskTP mask) { @@ -768,7 +775,8 @@ inline double getR8LittleEndian(const BYTE* ptr) /***************************************************************************** * - * Return the bitmask to use in the EXPSET_TP for the CSE with the given CSE index. + * Return the normalized index to use in the EXPSET_TP for the CSE with + * the given CSE index. * Each GenTree has the following field: * signed char gtCSEnum; // 0 or the CSE index (negated if def) * So zero is reserved to mean this node is not a CSE @@ -777,15 +785,15 @@ inline double getR8LittleEndian(const BYTE* ptr) * This precondition is checked by the assert on the first line of this method. */ -inline EXPSET_TP genCSEnum2bit(unsigned index) +inline unsigned int genCSEnum2bit(unsigned index) { assert((index > 0) && (index <= EXPSET_SZ)); - return ((EXPSET_TP)1 << (index - 1)); + return (index - 1); } #ifdef DEBUG -const char* genES2str(EXPSET_TP set); +const char* genES2str(BitVecTraits* traits, EXPSET_TP set); const char* refCntWtd2str(unsigned refCntWtd); #endif @@ -870,6 +878,10 @@ inline GenTree::GenTree(genTreeOps oper, var_types type DEBUGARG(bool largeNode) #endif #endif +#if COUNT_AST_OPERS + InterlockedIncrement(&s_gtNodeCounts[oper]); +#endif + #ifdef DEBUG gtSeqNum = 0; gtTreeID = JitTls::GetCompiler()->compGenTreeID++; @@ -1285,11 +1297,11 @@ inline void GenTree::SetOper(genTreeOps oper, ValueNumberUpdate vnUpdate) assert(GenTree::s_gtNodeSizes[gtOper] == TREE_NODE_SZ_SMALL || GenTree::s_gtNodeSizes[gtOper] == TREE_NODE_SZ_LARGE); - assert(GenTree::s_gtNodeSizes[oper] == TREE_NODE_SZ_SMALL || GenTree::s_gtNodeSizes[oper] == TREE_NODE_SZ_LARGE); + assert(GenTree::s_gtNodeSizes[oper] == TREE_NODE_SZ_SMALL || GenTree::s_gtNodeSizes[oper] == TREE_NODE_SZ_LARGE); assert(GenTree::s_gtNodeSizes[oper] == TREE_NODE_SZ_SMALL || (gtDebugFlags & GTF_DEBUG_NODE_LARGE)); - gtOper = oper; + SetOperRaw(oper); #ifdef DEBUG // Maintain the invariant that unary operators always have NULL gtOp2. @@ -1327,6 +1339,9 @@ inline void GenTree::CopyFrom(const GenTree* src, Compiler* comp) assert((gtDebugFlags & GTF_DEBUG_NODE_LARGE) || GenTree::s_gtNodeSizes[src->gtOper] == TREE_NODE_SZ_SMALL); GenTreePtr prev = gtPrev; GenTreePtr next = gtNext; + + RecordOperBashing(OperGet(), src->OperGet()); // nop unless NODEBASH_STATS is enabled + // The VTable pointer is copied intentionally here memcpy((void*)this, (void*)src, src->GetNodeSize()); this->gtPrev = prev; @@ -1373,7 +1388,7 @@ inline void GenTree::InitNodeSize() inline void GenTree::SetOper(genTreeOps oper, ValueNumberUpdate vnUpdate) { - gtOper = oper; + SetOperRaw(oper); if (vnUpdate == CLEAR_VN) { @@ -1384,6 +1399,7 @@ inline void GenTree::SetOper(genTreeOps oper, ValueNumberUpdate vnUpdate) inline void GenTree::CopyFrom(GenTreePtr src) { + RecordOperBashing(OperGet(), src->OperGet()); // nop unless NODEBASH_STATS is enabled *this = *src; #ifdef DEBUG gtSeqNum = 0; @@ -1405,6 +1421,16 @@ inline GenTreePtr Compiler::gtNewCastNodeL(var_types typ, GenTreePtr op1, var_ty #endif // SMALL_TREE_NODES /*****************************************************************************/ +/*****************************************************************************/ + +inline void GenTree::SetOperRaw(genTreeOps oper) +{ + // Please do not do anything here other than assign to gtOper (debug-only + // code is OK, but should be kept to a minimum). + RecordOperBashing(OperGet(), oper); // nop unless NODEBASH_STATS is enabled + gtOper = oper; +} + inline void GenTree::SetOperResetFlags(genTreeOps oper) { SetOper(oper); @@ -1446,7 +1472,7 @@ inline void GenTree::ChangeOper(genTreeOps oper, ValueNumberUpdate vnUpdate) inline void GenTree::ChangeOperUnchecked(genTreeOps oper) { - gtOper = oper; // Trust the caller and don't use SetOper() + SetOperRaw(oper); // Trust the caller and don't use SetOper() gtFlags &= GTF_COMMON_MASK; } @@ -1579,7 +1605,7 @@ inline unsigned Compiler::lvaGrabTemp(bool shortLifetime DEBUGARG(const char* re #if 0 // TODO-Cleanup: Enable this and test. -#ifdef DEBUG +#ifdef DEBUG // Fill the old table with junks. So to detect the un-intended use. memset(lvaTable, fDefaultFill2.val_DontUse_(CLRConfig::INTERNAL_JitDefaultFill, 0xFF), lvaCount * sizeof(*lvaTable)); #endif @@ -1655,7 +1681,7 @@ inline unsigned Compiler::lvaGrabTemps(unsigned cnt DEBUGARG(const char* reason) } #if 0 -#ifdef DEBUG +#ifdef DEBUG // TODO-Cleanup: Enable this and test. // Fill the old table with junks. So to detect the un-intended use. memset(lvaTable, fDefaultFill2.val_DontUse_(CLRConfig::INTERNAL_JitDefaultFill, 0xFF), lvaCount * sizeof(*lvaTable)); @@ -3909,7 +3935,7 @@ inline bool Compiler::IsSharedStaticHelper(GenTreePtr tree) helper == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS || helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS || #ifdef FEATURE_READYTORUN_COMPILER - helper == CORINFO_HELP_READYTORUN_STATIC_BASE || + helper == CORINFO_HELP_READYTORUN_STATIC_BASE || helper == CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE || #endif helper == CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS; #if 0 @@ -3944,7 +3970,7 @@ inline bool jitStaticFldIsGlobAddr(CORINFO_FIELD_HANDLE fldHnd) return (fldHnd == FLD_GLOBAL_DS || fldHnd == FLD_GLOBAL_FS); } -#if defined(DEBUG) || defined(FEATURE_JIT_METHOD_PERF) || defined(FEATURE_SIMD) +#if defined(DEBUG) || defined(FEATURE_JIT_METHOD_PERF) || defined(FEATURE_SIMD) || defined(FEATURE_TRACELOGGING) inline bool Compiler::eeIsNativeMethod(CORINFO_METHOD_HANDLE method) { @@ -4087,16 +4113,12 @@ inline bool Compiler::compIsProfilerHookNeeded() { #ifdef PROFILING_SUPPORTED return compProfilerHookNeeded - -#if defined(_TARGET_ARM_) || defined(_TARGET_AMD64_) // IL stubs are excluded by VM and we need to do the same even running // under a complus env hook to generate profiler hooks - || (opts.compJitELTHookEnabled && !(opts.eeFlags & CORJIT_FLG_IL_STUB)) -#endif - ; -#else // PROFILING_SUPPORTED + || (opts.compJitELTHookEnabled && !opts.jitFlags->IsSet(JitFlags::JIT_FLAG_IL_STUB)); +#else // !PROFILING_SUPPORTED return false; -#endif +#endif // !PROFILING_SUPPORTED } /***************************************************************************** @@ -4185,7 +4207,7 @@ inline bool Compiler::impIsDUP_LDVIRTFTN_TOKEN(const BYTE* delegateCreateStart, inline bool Compiler::compIsForImportOnly() { - return ((opts.eeFlags & CORJIT_FLG_IMPORT_ONLY) != 0); + return opts.jitFlags->IsSet(JitFlags::JIT_FLAG_IMPORT_ONLY); } /***************************************************************************** @@ -4352,10 +4374,12 @@ inline bool Compiler::lvaIsGCTracked(const LclVarDsc* varDsc) { if (varDsc->lvTracked && (varDsc->lvType == TYP_REF || varDsc->lvType == TYP_BYREF)) { + // Stack parameters are always untracked w.r.t. GC reportings + const bool isStackParam = varDsc->lvIsParam && !varDsc->lvIsRegArg; #ifdef _TARGET_AMD64_ - return !lvaIsFieldOfDependentlyPromotedStruct(varDsc); + return !isStackParam && !lvaIsFieldOfDependentlyPromotedStruct(varDsc); #else // !_TARGET_AMD64_ - return true; + return !isStackParam; #endif // !_TARGET_AMD64_ } else @@ -4367,8 +4391,10 @@ inline bool Compiler::lvaIsGCTracked(const LclVarDsc* varDsc) inline void Compiler::EndPhase(Phases phase) { #if defined(FEATURE_JIT_METHOD_PERF) - if (pCompJitTimer != NULL) + if (pCompJitTimer != nullptr) + { pCompJitTimer->EndPhase(phase); + } #endif #if DUMP_FLOWGRAPHS fgDumpFlowGraph(phase); @@ -4405,6 +4431,36 @@ inline void Compiler::EndPhase(Phases phase) } /*****************************************************************************/ +#if MEASURE_CLRAPI_CALLS + +inline void Compiler::CLRApiCallEnter(unsigned apix) +{ + if (pCompJitTimer != nullptr) + { + pCompJitTimer->CLRApiCallEnter(apix); + } +} +inline void Compiler::CLRApiCallLeave(unsigned apix) +{ + if (pCompJitTimer != nullptr) + { + pCompJitTimer->CLRApiCallLeave(apix); + } +} + +inline void Compiler::CLR_API_Enter(API_ICorJitInfo_Names ename) +{ + CLRApiCallEnter(ename); +} + +inline void Compiler::CLR_API_Leave(API_ICorJitInfo_Names ename) +{ + CLRApiCallLeave(ename); +} + +#endif // MEASURE_CLRAPI_CALLS + +/*****************************************************************************/ bool Compiler::fgExcludeFromSsa(unsigned lclNum) { if (opts.MinOpts()) diff --git a/src/jit/compphases.h b/src/jit/compphases.h index f193d04..ac1bb63 100644 --- a/src/jit/compphases.h +++ b/src/jit/compphases.h @@ -22,7 +22,12 @@ CompPhaseNameMacro(PHASE_PRE_IMPORT, "Pre-import", "PRE-IMP", false, -1) CompPhaseNameMacro(PHASE_IMPORTATION, "Importation", "IMPORT", false, -1) CompPhaseNameMacro(PHASE_POST_IMPORT, "Post-import", "POST-IMP", false, -1) -CompPhaseNameMacro(PHASE_MORPH, "Morph", "MORPH", false, -1) +CompPhaseNameMacro(PHASE_MORPH_INIT, "Morph - Init", "MOR-INIT" ,false, -1) +CompPhaseNameMacro(PHASE_MORPH_INLINE, "Morph - Inlining", "MOR-INL", false, -1) +CompPhaseNameMacro(PHASE_MORPH_IMPBYREF, "Morph - ByRefs", "MOR-BYREF",false, -1) +CompPhaseNameMacro(PHASE_STR_ADRLCL, "Morph - Structs/AddrExp", "MOR-STRAL",false, -1) +CompPhaseNameMacro(PHASE_MORPH_GLOBAL, "Morph - Global", "MOR-GLOB", false, -1) +CompPhaseNameMacro(PHASE_MORPH_END, "Morph - Finish", "MOR-END", false, -1) CompPhaseNameMacro(PHASE_GS_COOKIE, "GS Cookie", "GS-COOK", false, -1) CompPhaseNameMacro(PHASE_COMPUTE_PREDS, "Compute preds", "PREDS", false, -1) CompPhaseNameMacro(PHASE_MARK_GC_POLL_BLOCKS, "Mark GC poll blocks", "GC-POLL", false, -1) @@ -55,7 +60,7 @@ CompPhaseNameMacro(PHASE_OPTIMIZE_INDEX_CHECKS, "Optimize index checks", #if FEATURE_VALNUM_CSE CompPhaseNameMacro(PHASE_OPTIMIZE_VALNUM_CSES, "Optimize Valnum CSEs", "OPT-CSE", false, -1) -#endif +#endif CompPhaseNameMacro(PHASE_VN_COPY_PROP, "VN based copy prop", "CP-PROP", false, -1) #if ASSERTION_PROP @@ -86,6 +91,12 @@ CompPhaseNameMacro(PHASE_LINEAR_SCAN_RESOLVE, "LSRA resolve", CompPhaseNameMacro(PHASE_GENERATE_CODE, "Generate code", "CODEGEN", false, -1) CompPhaseNameMacro(PHASE_EMIT_CODE, "Emit code", "EMIT", false, -1) CompPhaseNameMacro(PHASE_EMIT_GCEH, "Emit GC+EH tables", "EMT-GCEH", false, -1) + +#if MEASURE_CLRAPI_CALLS +// The following is a "pseudo-phase" - it aggregates timing info +// for calls through ICorJitInfo across all "real" phases. +CompPhaseNameMacro(PHASE_CLR_API, "CLR API calls", "CLR-API", false, -1) +#endif // clang-format on #undef CompPhaseNameMacro diff --git a/src/jit/crossgen/CMakeLists.txt b/src/jit/crossgen/CMakeLists.txt index f79d9e7..6440e91 100644 --- a/src/jit/crossgen/CMakeLists.txt +++ b/src/jit/crossgen/CMakeLists.txt @@ -1,7 +1,7 @@ include(${CLR_DIR}/crossgen.cmake) -if(CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_ARM) +if(CLR_CMAKE_TARGET_ARCH_ARM) add_definitions(-DLEGACY_BACKEND) endif() -add_library_clr(${JIT_BASE_NAME}_crossgen ${SOURCES}) +add_library_clr(clrjit_crossgen ${SOURCES}) diff --git a/src/jit/decomposelongs.cpp b/src/jit/decomposelongs.cpp index cf66487..98b8b08 100644 --- a/src/jit/decomposelongs.cpp +++ b/src/jit/decomposelongs.cpp @@ -65,7 +65,7 @@ void DecomposeLongs::DecomposeBlock(BasicBlock* block) assert(block->isEmpty() || block->IsLIR()); m_blockWeight = block->getBBWeight(m_compiler); - m_range = &LIR::AsRange(block); + m_range = &LIR::AsRange(block); DecomposeRangeHelper(); } @@ -90,7 +90,7 @@ void DecomposeLongs::DecomposeRange(Compiler* compiler, unsigned blockWeight, LI DecomposeLongs decomposer(compiler); decomposer.m_blockWeight = blockWeight; - decomposer.m_range = ⦥ + decomposer.m_range = ⦥ decomposer.DecomposeRangeHelper(); } @@ -111,13 +111,7 @@ void DecomposeLongs::DecomposeRangeHelper() GenTree* node = Range().FirstNonPhiNode(); while (node != nullptr) { - LIR::Use use; - if (!Range().TryGetUse(node, &use)) - { - use = LIR::Use::GetDummyUse(Range(), node); - } - - node = DecomposeNode(use); + node = DecomposeNode(node); } assert(Range().CheckLIR(m_compiler)); @@ -132,10 +126,8 @@ void DecomposeLongs::DecomposeRangeHelper() // Return Value: // The next node to process. // -GenTree* DecomposeLongs::DecomposeNode(LIR::Use& use) +GenTree* DecomposeLongs::DecomposeNode(GenTree* tree) { - GenTree* tree = use.Def(); - // Handle the case where we are implicitly using the lower half of a long lclVar. if ((tree->TypeGet() == TYP_INT) && tree->OperIsLocal()) { @@ -171,14 +163,15 @@ GenTree* DecomposeLongs::DecomposeNode(LIR::Use& use) } #endif // DEBUG + LIR::Use use; + if (!Range().TryGetUse(tree, &use)) + { + use = LIR::Use::GetDummyUse(Range(), tree); + } + GenTree* nextNode = nullptr; switch (tree->OperGet()) { - case GT_PHI: - case GT_PHI_ARG: - nextNode = tree->gtNext; - break; - case GT_LCL_VAR: nextNode = DecomposeLclVar(use); break; @@ -212,8 +205,7 @@ GenTree* DecomposeLongs::DecomposeNode(LIR::Use& use) break; case GT_STORE_LCL_FLD: - assert(tree->gtOp.gtOp1->OperGet() == GT_LONG); - NYI("st.lclFld of of TYP_LONG"); + nextNode = DecomposeStoreLclFld(use); break; case GT_IND: @@ -239,23 +231,11 @@ GenTree* DecomposeLongs::DecomposeNode(LIR::Use& use) break; case GT_MUL: - NYI("Arithmetic binary operators on TYP_LONG - GT_MUL"); - break; - - case GT_DIV: - NYI("Arithmetic binary operators on TYP_LONG - GT_DIV"); - break; - - case GT_MOD: - NYI("Arithmetic binary operators on TYP_LONG - GT_MOD"); - break; - - case GT_UDIV: - NYI("Arithmetic binary operators on TYP_LONG - GT_UDIV"); + nextNode = DecomposeMul(use); break; case GT_UMOD: - NYI("Arithmetic binary operators on TYP_LONG - GT_UMOD"); + nextNode = DecomposeUMod(use); break; case GT_LSH: @@ -266,11 +246,7 @@ GenTree* DecomposeLongs::DecomposeNode(LIR::Use& use) case GT_ROL: case GT_ROR: - NYI("Arithmetic binary operators on TYP_LONG - ROTATE"); - break; - - case GT_MULHI: - NYI("Arithmetic binary operators on TYP_LONG - MULHI"); + nextNode = DecomposeRotate(use); break; case GT_LOCKADD: @@ -288,6 +264,37 @@ GenTree* DecomposeLongs::DecomposeNode(LIR::Use& use) } } + // If we replaced the argument to a GT_FIELD_LIST element with a GT_LONG node, split that field list + // element into two elements: one for each half of the GT_LONG. + if ((use.Def()->OperGet() == GT_LONG) && !use.IsDummyUse() && (use.User()->OperGet() == GT_FIELD_LIST)) + { + GenTreeOp* value = use.Def()->AsOp(); + Range().Remove(value); + + // The node returned by `use.User()` is the head of the field list. We need to find the actual node that uses + // the `GT_LONG` so that we can split it. + GenTreeFieldList* listNode = use.User()->AsFieldList(); + for (; listNode != nullptr; listNode = listNode->Rest()) + { + if (listNode->Current() == value) + { + break; + } + } + + assert(listNode != nullptr); + GenTree* rest = listNode->gtOp2; + + GenTreeFieldList* loNode = listNode; + loNode->gtOp1 = value->gtOp1; + loNode->gtFieldType = TYP_INT; + + GenTreeFieldList* hiNode = + new (m_compiler, GT_FIELD_LIST) GenTreeFieldList(value->gtOp2, loNode->gtFieldOffset + 4, TYP_INT, loNode); + + hiNode->gtOp2 = rest; + } + #ifdef DEBUG if (m_compiler->verbose) { @@ -308,23 +315,25 @@ GenTree* DecomposeLongs::DecomposeNode(LIR::Use& use) // Arguments: // use - the LIR::Use object for the def that needs to be decomposed. // loResult - the decomposed low part -// hiResult - the decomposed high part. This must follow loResult in the linear order, -// as the new GT_LONG node will be inserted immediately after it. +// hiResult - the decomposed high part +// insertResultAfter - the node that the GT_LONG should be inserted after // // Return Value: // The next node to process. // -GenTree* DecomposeLongs::FinalizeDecomposition(LIR::Use& use, GenTree* loResult, GenTree* hiResult) +GenTree* DecomposeLongs::FinalizeDecomposition(LIR::Use& use, + GenTree* loResult, + GenTree* hiResult, + GenTree* insertResultAfter) { assert(use.IsInitialized()); assert(loResult != nullptr); assert(hiResult != nullptr); assert(Range().Contains(loResult)); assert(Range().Contains(hiResult)); - assert(loResult->Precedes(hiResult)); GenTree* gtLong = new (m_compiler, GT_LONG) GenTreeOp(GT_LONG, TYP_LONG, loResult, hiResult); - Range().InsertAfter(hiResult, gtLong); + Range().InsertAfter(insertResultAfter, gtLong); use.ReplaceWith(m_compiler, gtLong); @@ -366,8 +375,6 @@ GenTree* DecomposeLongs::DecomposeLclVar(LIR::Use& use) } else { - noway_assert(varDsc->lvLRACandidate == false); - loResult->SetOper(GT_LCL_FLD); loResult->AsLclFld()->gtLclOffs = 0; loResult->AsLclFld()->gtFieldSeq = FieldSeqStore::NotAField(); @@ -380,7 +387,7 @@ GenTree* DecomposeLongs::DecomposeLclVar(LIR::Use& use) m_compiler->lvaIncRefCnts(loResult); m_compiler->lvaIncRefCnts(hiResult); - return FinalizeDecomposition(use, loResult, hiResult); + return FinalizeDecomposition(use, loResult, hiResult, hiResult); } //------------------------------------------------------------------------ @@ -404,7 +411,7 @@ GenTree* DecomposeLongs::DecomposeLclFld(LIR::Use& use) GenTree* hiResult = m_compiler->gtNewLclFldNode(loResult->gtLclNum, TYP_INT, loResult->gtLclOffs + 4); Range().InsertAfter(loResult, hiResult); - return FinalizeDecomposition(use, loResult, hiResult); + return FinalizeDecomposition(use, loResult, hiResult, hiResult); } //------------------------------------------------------------------------ @@ -423,59 +430,118 @@ GenTree* DecomposeLongs::DecomposeStoreLclVar(LIR::Use& use) GenTree* tree = use.Def(); GenTree* rhs = tree->gtGetOp1(); - if ((rhs->OperGet() == GT_PHI) || (rhs->OperGet() == GT_CALL)) + if ((rhs->OperGet() == GT_PHI) || (rhs->OperGet() == GT_CALL) || + ((rhs->OperGet() == GT_MUL_LONG) && (rhs->gtFlags & GTF_MUL_64RSLT) != 0)) { // GT_CALLs are not decomposed, so will not be converted to GT_LONG // GT_STORE_LCL_VAR = GT_CALL are handled in genMultiRegCallStoreToLocal + // GT_MULs are not decomposed, so will not be converted to GT_LONG return tree->gtNext; } noway_assert(rhs->OperGet() == GT_LONG); + unsigned varNum = tree->AsLclVarCommon()->gtLclNum; LclVarDsc* varDsc = m_compiler->lvaTable + varNum; + if (!varDsc->lvPromoted) + { + // We cannot decompose a st.lclVar that is not promoted because doing so + // changes its liveness semantics. For example, consider the following + // decomposition of a st.lclVar into two st.lclFlds: + // + // Before: + // + // /--* t0 int + // +--* t1 int + // t2 = * gt_long long + // + // /--* t2 long + // * st.lclVar long V0 + // + // After: + // /--* t0 int + // * st.lclFld int V0 [+0] + // + // /--* t1 int + // * st.lclFld int V0 [+4] + // + // Before decomposition, the `st.lclVar` is a simple def of `V0`. After + // decomposition, each `st.lclFld` is a partial def of `V0`. This partial + // def is treated as both a use and a def of the appropriate lclVar. This + // difference will affect any situation in which the liveness of a variable + // at a def matters (e.g. dead store elimination, live-in sets, etc.). As + // a result, we leave these stores as-is and generate the decomposed store + // in the code generator. + // + // NOTE: this does extend the lifetime of the low half of the `GT_LONG` + // node as compared to the decomposed form. If we start doing more code + // motion in the backend, this may cause some CQ issues and some sort of + // decomposition could be beneficial. + return tree->gtNext; + } + + assert(varDsc->lvFieldCnt == 2); m_compiler->lvaDecRefCnts(tree); - GenTree* loRhs = rhs->gtGetOp1(); - GenTree* hiRhs = rhs->gtGetOp2(); - GenTree* hiStore = m_compiler->gtNewLclLNode(varNum, TYP_INT); + GenTreeOp* value = rhs->AsOp(); + Range().Remove(value); - if (varDsc->lvPromoted) - { - assert(varDsc->lvFieldCnt == 2); + const unsigned loVarNum = varDsc->lvFieldLclStart; + GenTree* loStore = tree; + loStore->AsLclVarCommon()->SetLclNum(loVarNum); + loStore->gtOp.gtOp1 = value->gtOp1; + loStore->gtType = TYP_INT; - unsigned loVarNum = varDsc->lvFieldLclStart; - unsigned hiVarNum = loVarNum + 1; - tree->AsLclVarCommon()->SetLclNum(loVarNum); - hiStore->SetOper(GT_STORE_LCL_VAR); - hiStore->AsLclVarCommon()->SetLclNum(hiVarNum); - } - else - { - noway_assert(varDsc->lvLRACandidate == false); + const unsigned hiVarNum = loVarNum + 1; + GenTree* hiStore = m_compiler->gtNewLclLNode(hiVarNum, TYP_INT); + hiStore->SetOper(GT_STORE_LCL_VAR); + hiStore->gtOp.gtOp1 = value->gtOp2; + hiStore->gtFlags |= GTF_VAR_DEF; - tree->SetOper(GT_STORE_LCL_FLD); - tree->AsLclFld()->gtLclOffs = 0; - tree->AsLclFld()->gtFieldSeq = FieldSeqStore::NotAField(); + m_compiler->lvaIncRefCnts(loStore); + m_compiler->lvaIncRefCnts(hiStore); - hiStore->SetOper(GT_STORE_LCL_FLD); - hiStore->AsLclFld()->gtLclOffs = 4; - hiStore->AsLclFld()->gtFieldSeq = FieldSeqStore::NotAField(); - } + Range().InsertAfter(tree, hiStore); - // 'tree' is going to steal the loRhs node for itself, so we need to remove the - // GT_LONG node from the threading. - Range().Remove(rhs); + return hiStore->gtNext; +} - tree->gtOp.gtOp1 = loRhs; - tree->gtType = TYP_INT; +//------------------------------------------------------------------------ +// DecomposeStoreLclFld: Decompose GT_STORE_LCL_FLD. +// +// Arguments: +// use - the LIR::Use object for the def that needs to be decomposed. +// +// Return Value: +// The next node to process. +// +GenTree* DecomposeLongs::DecomposeStoreLclFld(LIR::Use& use) +{ + assert(use.IsInitialized()); + assert(use.Def()->OperGet() == GT_STORE_LCL_FLD); - hiStore->gtOp.gtOp1 = hiRhs; - hiStore->gtFlags |= GTF_VAR_DEF; + GenTreeLclFld* store = use.Def()->AsLclFld(); + + GenTreeOp* value = store->gtOp1->AsOp(); + assert(value->OperGet() == GT_LONG); + Range().Remove(value); + + // The original store node will be repurposed to store the low half of the GT_LONG. + GenTreeLclFld* loStore = store; + loStore->gtOp1 = value->gtOp1; + loStore->gtType = TYP_INT; + loStore->gtFlags |= GTF_VAR_USEASG; - m_compiler->lvaIncRefCnts(tree); + // Create the store for the upper half of the GT_LONG and insert it after the low store. + GenTreeLclFld* hiStore = m_compiler->gtNewLclFldNode(loStore->gtLclNum, TYP_INT, loStore->gtLclOffs + 4); + hiStore->SetOper(GT_STORE_LCL_FLD); + hiStore->gtOp1 = value->gtOp2; + hiStore->gtFlags |= (GTF_VAR_DEF | GTF_VAR_USEASG); + + // Bump the ref count for the destination. m_compiler->lvaIncRefCnts(hiStore); - Range().InsertAfter(tree, hiStore); + Range().InsertAfter(loStore, hiStore); return hiStore->gtNext; } @@ -494,35 +560,103 @@ GenTree* DecomposeLongs::DecomposeCast(LIR::Use& use) assert(use.IsInitialized()); assert(use.Def()->OperGet() == GT_CAST); - GenTree* tree = use.Def(); + GenTree* cast = use.Def()->AsCast(); GenTree* loResult = nullptr; GenTree* hiResult = nullptr; - assert(tree->gtPrev == tree->gtGetOp1()); - NYI_IF(tree->gtOverflow(), "TYP_LONG cast with overflow"); - switch (tree->AsCast()->CastFromType()) + var_types srcType = cast->CastFromType(); + var_types dstType = cast->CastToType(); + + if ((cast->gtFlags & GTF_UNSIGNED) != 0) + { + srcType = genUnsignedType(srcType); + } + + if (varTypeIsLong(srcType)) + { + if (cast->gtOverflow() && (varTypeIsUnsigned(srcType) != varTypeIsUnsigned(dstType))) + { + GenTree* srcOp = cast->gtGetOp1(); + noway_assert(srcOp->OperGet() == GT_LONG); + GenTree* loSrcOp = srcOp->gtGetOp1(); + GenTree* hiSrcOp = srcOp->gtGetOp2(); + + // + // When casting between long types an overflow check is needed only if the types + // have different signedness. In both cases (long->ulong and ulong->long) we only + // need to check if the high part is negative or not. Use the existing cast node + // to perform a int->uint cast of the high part to take advantage of the overflow + // check provided by codegen. + // + + loResult = loSrcOp; + + hiResult = cast; + hiResult->gtType = TYP_INT; + hiResult->AsCast()->gtCastType = TYP_UINT; + hiResult->gtFlags &= ~GTF_UNSIGNED; + hiResult->gtOp.gtOp1 = hiSrcOp; + + Range().Remove(cast); + Range().Remove(srcOp); + Range().InsertAfter(hiSrcOp, hiResult); + } + else + { + NYI("Unimplemented long->long no-op cast decomposition"); + } + } + else if (varTypeIsIntegralOrI(srcType)) { - case TYP_INT: - if (tree->gtFlags & GTF_UNSIGNED) + if (cast->gtOverflow() && !varTypeIsUnsigned(srcType) && varTypeIsUnsigned(dstType)) + { + // + // An overflow check is needed only when casting from a signed type to ulong. + // Change the cast type to uint to take advantage of the overflow check provided + // by codegen and then zero extend the resulting uint to ulong. + // + + loResult = cast; + loResult->AsCast()->gtCastType = TYP_UINT; + loResult->gtType = TYP_INT; + + hiResult = m_compiler->gtNewZeroConNode(TYP_INT); + + Range().InsertAfter(loResult, hiResult); + } + else + { + if (varTypeIsUnsigned(srcType)) { - loResult = tree->gtGetOp1(); - Range().Remove(tree); + loResult = cast->gtGetOp1(); + hiResult = m_compiler->gtNewZeroConNode(TYP_INT); - hiResult = new (m_compiler, GT_CNS_INT) GenTreeIntCon(TYP_INT, 0); + Range().Remove(cast); Range().InsertAfter(loResult, hiResult); } else { - NYI("Lowering of signed cast TYP_INT->TYP_LONG"); - } - break; + LIR::Use src(Range(), &(cast->gtOp.gtOp1), cast); + unsigned lclNum = src.ReplaceWithLclVar(m_compiler, m_blockWeight); - default: - NYI("Unimplemented type for Lowering of cast to TYP_LONG"); - break; + loResult = src.Def(); + + GenTree* loCopy = m_compiler->gtNewLclvNode(lclNum, TYP_INT); + GenTree* shiftBy = m_compiler->gtNewIconNode(31, TYP_INT); + hiResult = m_compiler->gtNewOperNode(GT_RSH, TYP_INT, loCopy, shiftBy); + + Range().Remove(cast); + Range().InsertAfter(loResult, loCopy, shiftBy, hiResult); + m_compiler->lvaIncRefCnts(loCopy); + } + } + } + else + { + NYI("Unimplemented cast decomposition"); } - return FinalizeDecomposition(use, loResult, hiResult); + return FinalizeDecomposition(use, loResult, hiResult, hiResult); } //------------------------------------------------------------------------ @@ -549,7 +683,7 @@ GenTree* DecomposeLongs::DecomposeCnsLng(LIR::Use& use) GenTree* hiResult = new (m_compiler, GT_CNS_INT) GenTreeIntCon(TYP_INT, hiVal); Range().InsertAfter(loResult, hiResult); - return FinalizeDecomposition(use, loResult, hiResult); + return FinalizeDecomposition(use, loResult, hiResult, hiResult); } //------------------------------------------------------------------------ @@ -567,35 +701,7 @@ GenTree* DecomposeLongs::DecomposeCall(LIR::Use& use) assert(use.Def()->OperGet() == GT_CALL); // We only need to force var = call() if the call's result is used. - if (use.IsDummyUse()) - return use.Def()->gtNext; - - GenTree* user = use.User(); - if (user->OperGet() == GT_STORE_LCL_VAR) - { - // If parent is already a STORE_LCL_VAR, we can skip it if - // it is already marked as lvIsMultiRegRet. - unsigned varNum = user->AsLclVarCommon()->gtLclNum; - if (m_compiler->lvaTable[varNum].lvIsMultiRegRet) - { - return use.Def()->gtNext; - } - else if (!m_compiler->lvaTable[varNum].lvPromoted) - { - // If var wasn't promoted, we can just set lvIsMultiRegRet. - m_compiler->lvaTable[varNum].lvIsMultiRegRet = true; - return use.Def()->gtNext; - } - } - - GenTree* originalNode = use.Def(); - - // Otherwise, we need to force var = call() - unsigned varNum = use.ReplaceWithLclVar(m_compiler, m_blockWeight); - m_compiler->lvaTable[varNum].lvIsMultiRegRet = true; - - // Decompose the new LclVar use - return DecomposeLclVar(use); + return StoreNodeToVar(use); } //------------------------------------------------------------------------ @@ -627,7 +733,7 @@ GenTree* DecomposeLongs::DecomposeStoreInd(LIR::Use& use) // + --* t155 long // * storeIndir long - GenTree* gtLong = tree->gtOp.gtOp2; + GenTree* gtLong = tree->gtOp.gtOp2; // Save address to a temp. It is used in storeIndLow and storeIndHigh trees. LIR::Use address(Range(), &tree->gtOp.gtOp1, tree); @@ -721,12 +827,13 @@ GenTree* DecomposeLongs::DecomposeInd(LIR::Use& use) GenTreePtr addrHigh = new (m_compiler, GT_LEA) GenTreeAddrMode(TYP_REF, addrBaseHigh, nullptr, 0, genTypeSize(TYP_INT)); GenTreePtr indHigh = new (m_compiler, GT_IND) GenTreeIndir(GT_IND, TYP_INT, addrHigh, nullptr); + indHigh->gtFlags |= (indLow->gtFlags & (GTF_GLOB_REF | GTF_EXCEPT | GTF_IND_FLAGS)); m_compiler->lvaIncRefCnts(addrBaseHigh); Range().InsertAfter(indLow, addrBaseHigh, addrHigh, indHigh); - return FinalizeDecomposition(use, indLow, indHigh); + return FinalizeDecomposition(use, indLow, indHigh, indHigh); } //------------------------------------------------------------------------ @@ -758,7 +865,7 @@ GenTree* DecomposeLongs::DecomposeNot(LIR::Use& use) GenTree* hiResult = new (m_compiler, GT_NOT) GenTreeOp(GT_NOT, TYP_INT, hiOp1, nullptr); Range().InsertAfter(loResult, hiResult); - return FinalizeDecomposition(use, loResult, hiResult); + return FinalizeDecomposition(use, loResult, hiResult, hiResult); } //------------------------------------------------------------------------ @@ -779,14 +886,6 @@ GenTree* DecomposeLongs::DecomposeNeg(LIR::Use& use) GenTree* gtLong = tree->gtGetOp1(); noway_assert(gtLong->OperGet() == GT_LONG); - LIR::Use op1(Range(), >Long->gtOp.gtOp1, gtLong); - op1.ReplaceWithLclVar(m_compiler, m_blockWeight); - - LIR::Use op2(Range(), >Long->gtOp.gtOp2, gtLong); - op2.ReplaceWithLclVar(m_compiler, m_blockWeight); - - // Neither GT_NEG nor the introduced temporaries have side effects. - tree->gtFlags &= ~GTF_ALL_EFFECT; GenTree* loOp1 = gtLong->gtGetOp1(); GenTree* hiOp1 = gtLong->gtGetOp2(); @@ -799,11 +898,10 @@ GenTree* DecomposeLongs::DecomposeNeg(LIR::Use& use) GenTree* zero = m_compiler->gtNewZeroConNode(TYP_INT); GenTree* hiAdjust = m_compiler->gtNewOperNode(GT_ADD_HI, TYP_INT, hiOp1, zero); GenTree* hiResult = m_compiler->gtNewOperNode(GT_NEG, TYP_INT, hiAdjust); - hiResult->gtFlags = tree->gtFlags; Range().InsertAfter(loResult, zero, hiAdjust, hiResult); - return FinalizeDecomposition(use, loResult, hiResult); + return FinalizeDecomposition(use, loResult, hiResult, hiResult); } //------------------------------------------------------------------------ @@ -864,14 +962,19 @@ GenTree* DecomposeLongs::DecomposeArith(LIR::Use& use) } } - return FinalizeDecomposition(use, loResult, hiResult); + return FinalizeDecomposition(use, loResult, hiResult, hiResult); } //------------------------------------------------------------------------ -// DecomposeShift: Decompose GT_LSH, GT_RSH, GT_RSZ. For shift nodes, we need to use -// the shift helper functions, so we here convert the shift into a helper call by -// pulling its arguments out of linear order and making them the args to a call, then -// replacing the original node with the new call. +// DecomposeShift: Decompose GT_LSH, GT_RSH, GT_RSZ. For shift nodes being shifted +// by a constant int, we can inspect the shift amount and decompose to the appropriate +// node types, generating a shl/shld pattern for GT_LSH, a shrd/shr pattern for GT_RSZ, +// and a shrd/sar pattern for GT_SHR for most shift amounts. Shifting by 0, >= 32 and +// >= 64 are special cased to produce better code patterns. +// +// For all other shift nodes, we need to use the shift helper functions, so we here convert +// the shift into a helper call by pulling its arguments out of linear order and making +// them the args to a call, then replacing the original node with the new call. // // Arguments: // use - the LIR::Use object for the def that needs to be decomposed. @@ -883,66 +986,646 @@ GenTree* DecomposeLongs::DecomposeShift(LIR::Use& use) { assert(use.IsInitialized()); - GenTree* tree = use.Def(); - GenTree* gtLong = tree->gtGetOp1(); - genTreeOps oper = tree->OperGet(); + GenTree* tree = use.Def(); + GenTree* gtLong = tree->gtGetOp1(); + GenTree* loOp1 = gtLong->gtGetOp1(); + GenTree* hiOp1 = gtLong->gtGetOp2(); + GenTree* shiftByOp = tree->gtGetOp2(); + + genTreeOps oper = tree->OperGet(); + genTreeOps shiftByOper = shiftByOp->OperGet(); assert((oper == GT_LSH) || (oper == GT_RSH) || (oper == GT_RSZ)); - LIR::Use loOp1Use(Range(), >Long->gtOp.gtOp1, gtLong); - loOp1Use.ReplaceWithLclVar(m_compiler, m_blockWeight); + // If we are shifting by a constant int, we do not want to use a helper, instead, we decompose. + if (shiftByOper == GT_CNS_INT) + { + unsigned int count = shiftByOp->gtIntCon.gtIconVal; + Range().Remove(shiftByOp); - LIR::Use hiOp1Use(Range(), >Long->gtOp.gtOp2, gtLong); - hiOp1Use.ReplaceWithLclVar(m_compiler, m_blockWeight); + if (count == 0) + { + GenTree* next = tree->gtNext; + // Remove tree and don't do anything else. + Range().Remove(tree); + use.ReplaceWith(m_compiler, gtLong); + return next; + } - LIR::Use shiftWidthUse(Range(), &tree->gtOp.gtOp2, tree); - shiftWidthUse.ReplaceWithLclVar(m_compiler, m_blockWeight); + GenTree* loResult; + GenTree* hiResult; - GenTree* loOp1 = gtLong->gtGetOp1(); - GenTree* hiOp1 = gtLong->gtGetOp2(); + GenTree* insertAfter; - GenTree* shiftWidthOp = tree->gtGetOp2(); + switch (oper) + { + case GT_LSH: + { + Range().Remove(hiOp1); + if (count < 32) + { + // Hi is a GT_LSH_HI, lo is a GT_LSH. Will produce: + // reg1 = lo + // shl lo, shift + // shld hi, reg1, shift + + Range().Remove(gtLong); + loOp1 = RepresentOpAsLocalVar(loOp1, gtLong, >Long->gtOp.gtOp1); + unsigned loOp1LclNum = loOp1->AsLclVarCommon()->gtLclNum; + Range().Remove(loOp1); + + GenTree* shiftByHi = m_compiler->gtNewIconNode(count, TYP_INT); + GenTree* shiftByLo = m_compiler->gtNewIconNode(count, TYP_INT); + + loResult = m_compiler->gtNewOperNode(GT_LSH, TYP_INT, loOp1, shiftByLo); + + // Create a GT_LONG that contains loCopy and hiOp1. This will be used in codegen to + // generate the shld instruction + GenTree* loCopy = m_compiler->gtNewLclvNode(loOp1LclNum, TYP_INT); + GenTree* hiOp = new (m_compiler, GT_LONG) GenTreeOp(GT_LONG, TYP_LONG, loCopy, hiOp1); + hiResult = m_compiler->gtNewOperNode(GT_LSH_HI, TYP_INT, hiOp, shiftByHi); + + m_compiler->lvaIncRefCnts(loCopy); + + Range().InsertBefore(tree, loCopy, hiOp1, hiOp); + Range().InsertBefore(tree, shiftByHi, hiResult); + Range().InsertBefore(tree, loOp1, shiftByLo, loResult); + + insertAfter = loResult; + } + else + { + assert(count >= 32); + + if (count < 64) + { + if (count == 32) + { + // Move loOp1 into hiResult (shift of 32 bits is just a mov of lo to hi) + // We need to make sure that we save lo to a temp variable so that we don't overwrite lo + // before saving it to hi in the case that we are doing an inplace shift. I.e.: + // x = x << 32 + + LIR::Use loOp1Use(Range(), >Long->gtOp.gtOp1, gtLong); + loOp1Use.ReplaceWithLclVar(m_compiler, m_blockWeight); + + hiResult = loOp1Use.Def(); + Range().Remove(gtLong); + } + else + { + Range().Remove(gtLong); + Range().Remove(loOp1); + assert(count > 32 && count < 64); + + // Move loOp1 into hiResult, do a GT_LSH with count - 32. + // We will compute hiResult before loResult in this case, so we don't need to store lo to a + // temp + GenTree* shiftBy = m_compiler->gtNewIconNode(count - 32, TYP_INT); + hiResult = m_compiler->gtNewOperNode(oper, TYP_INT, loOp1, shiftBy); + Range().InsertBefore(tree, loOp1, shiftBy, hiResult); + } + } + else + { + Range().Remove(gtLong); + Range().Remove(loOp1); + assert(count >= 64); + + // Zero out hi (shift of >= 64 bits moves all the bits out of the two registers) + hiResult = m_compiler->gtNewZeroConNode(TYP_INT); + Range().InsertBefore(tree, hiResult); + } + + // Zero out loResult (shift of >= 32 bits shifts all lo bits to hiResult) + loResult = m_compiler->gtNewZeroConNode(TYP_INT); + Range().InsertBefore(tree, loResult); + + insertAfter = loResult; + } + } + break; + case GT_RSZ: + { + Range().Remove(gtLong); + + if (count < 32) + { + // Hi is a GT_RSZ, lo is a GT_RSH_LO. Will produce: + // reg1 = hi + // shrd lo, reg1, shift + // shr hi, shift + + hiOp1 = RepresentOpAsLocalVar(hiOp1, gtLong, >Long->gtOp.gtOp2); + unsigned hiOp1LclNum = hiOp1->AsLclVarCommon()->gtLclNum; + GenTree* hiCopy = m_compiler->gtNewLclvNode(hiOp1LclNum, TYP_INT); + + GenTree* shiftByHi = m_compiler->gtNewIconNode(count, TYP_INT); + GenTree* shiftByLo = m_compiler->gtNewIconNode(count, TYP_INT); + + m_compiler->lvaIncRefCnts(hiCopy); + + hiResult = m_compiler->gtNewOperNode(GT_RSZ, TYP_INT, hiOp1, shiftByHi); + + // Create a GT_LONG that contains loOp1 and hiCopy. This will be used in codegen to + // generate the shrd instruction + GenTree* loOp = new (m_compiler, GT_LONG) GenTreeOp(GT_LONG, TYP_LONG, loOp1, hiCopy); + loResult = m_compiler->gtNewOperNode(GT_RSH_LO, TYP_INT, loOp, shiftByLo); + + Range().InsertBefore(tree, hiCopy, loOp); + Range().InsertBefore(tree, shiftByLo, loResult); + Range().InsertBefore(tree, shiftByHi, hiResult); + } + else + { + Range().Remove(loOp1); + Range().Remove(hiOp1); + assert(count >= 32); + if (count < 64) + { + if (count == 32) + { + // Move hiOp1 into loResult. + loResult = hiOp1; + Range().InsertBefore(tree, loResult); + } + else + { + assert(count > 32 && count < 64); + + // Move hiOp1 into loResult, do a GT_RSZ with count - 32. + GenTree* shiftBy = m_compiler->gtNewIconNode(count - 32, TYP_INT); + loResult = m_compiler->gtNewOperNode(oper, TYP_INT, hiOp1, shiftBy); + Range().InsertBefore(tree, hiOp1, shiftBy, loResult); + } + } + else + { + assert(count >= 64); + + // Zero out lo + loResult = m_compiler->gtNewZeroConNode(TYP_INT); + Range().InsertBefore(tree, loResult); + } + + // Zero out hi + hiResult = m_compiler->gtNewZeroConNode(TYP_INT); + Range().InsertBefore(tree, hiResult); + } + + insertAfter = hiResult; + } + break; + case GT_RSH: + { + Range().Remove(gtLong); + Range().Remove(loOp1); + + hiOp1 = RepresentOpAsLocalVar(hiOp1, gtLong, >Long->gtOp.gtOp2); + unsigned hiOp1LclNum = hiOp1->AsLclVarCommon()->gtLclNum; + GenTree* hiCopy = m_compiler->gtNewLclvNode(hiOp1LclNum, TYP_INT); + Range().Remove(hiOp1); + + if (count < 32) + { + // Hi is a GT_RSH, lo is a GT_RSH_LO. Will produce: + // reg1 = hi + // shrd lo, reg1, shift + // sar hi, shift + + GenTree* shiftByHi = m_compiler->gtNewIconNode(count, TYP_INT); + GenTree* shiftByLo = m_compiler->gtNewIconNode(count, TYP_INT); + m_compiler->lvaIncRefCnts(hiCopy); + + hiResult = m_compiler->gtNewOperNode(GT_RSH, TYP_INT, hiOp1, shiftByHi); + + // Create a GT_LONG that contains loOp1 and hiCopy. This will be used in codegen to + // generate the shrd instruction + GenTree* loOp = new (m_compiler, GT_LONG) GenTreeOp(GT_LONG, TYP_LONG, loOp1, hiCopy); + loResult = m_compiler->gtNewOperNode(GT_RSH_LO, TYP_INT, loOp, shiftByLo); + + Range().InsertBefore(tree, loOp1, hiCopy, loOp); + Range().InsertBefore(tree, shiftByLo, loResult); + Range().InsertBefore(tree, shiftByHi, hiOp1, hiResult); + } + else + { + assert(count >= 32); + if (count < 64) + { + if (count == 32) + { + // Move hiOp1 into loResult. + loResult = hiOp1; + Range().InsertBefore(tree, loResult); + } + else + { + assert(count > 32 && count < 64); + + // Move hiOp1 into loResult, do a GT_RSH with count - 32. + GenTree* shiftBy = m_compiler->gtNewIconNode(count - 32, TYP_INT); + loResult = m_compiler->gtNewOperNode(oper, TYP_INT, hiOp1, shiftBy); + Range().InsertBefore(tree, hiOp1, shiftBy, loResult); + } + + // Propagate sign bit in hiResult + GenTree* shiftBy = m_compiler->gtNewIconNode(31, TYP_INT); + hiResult = m_compiler->gtNewOperNode(GT_RSH, TYP_INT, hiCopy, shiftBy); + Range().InsertBefore(tree, shiftBy, hiCopy, hiResult); + + m_compiler->lvaIncRefCnts(hiCopy); + } + else + { + assert(count >= 64); + + // Propagate sign bit in loResult + GenTree* loShiftBy = m_compiler->gtNewIconNode(31, TYP_INT); + loResult = m_compiler->gtNewOperNode(GT_RSH, TYP_INT, hiCopy, loShiftBy); + Range().InsertBefore(tree, hiCopy, loShiftBy, loResult); + + // Propagate sign bit in hiResult + GenTree* shiftBy = m_compiler->gtNewIconNode(31, TYP_INT); + hiResult = m_compiler->gtNewOperNode(GT_RSH, TYP_INT, hiOp1, shiftBy); + Range().InsertBefore(tree, shiftBy, hiOp1, hiResult); + + m_compiler->lvaIncRefCnts(hiCopy); + } + } + + insertAfter = hiResult; + } + break; + default: + unreached(); + } - Range().Remove(gtLong); - Range().Remove(loOp1); - Range().Remove(hiOp1); + // Remove tree from Range + Range().Remove(tree); - Range().Remove(shiftWidthOp); + return FinalizeDecomposition(use, loResult, hiResult, insertAfter); + } + else + { + // arguments are single used, but LIR call can work only with local vars. + shiftByOp = RepresentOpAsLocalVar(shiftByOp, tree, &tree->gtOp.gtOp2); + loOp1 = RepresentOpAsLocalVar(loOp1, gtLong, >Long->gtOp.gtOp1); + hiOp1 = RepresentOpAsLocalVar(hiOp1, gtLong, >Long->gtOp.gtOp2); - // TODO-X86-CQ: If the shift operand is a GT_CNS_INT, we should pipe the instructions through to codegen - // and generate the shift instructions ourselves there, rather than replacing it with a helper call. + Range().Remove(shiftByOp); + Range().Remove(gtLong); + Range().Remove(loOp1); + Range().Remove(hiOp1); - unsigned helper; + unsigned helper; - switch (oper) + switch (oper) + { + case GT_LSH: + helper = CORINFO_HELP_LLSH; + break; + case GT_RSH: + helper = CORINFO_HELP_LRSH; + break; + case GT_RSZ: + helper = CORINFO_HELP_LRSZ; + break; + default: + unreached(); + } + + GenTreeArgList* argList = m_compiler->gtNewArgList(loOp1, hiOp1, shiftByOp); + + GenTree* call = m_compiler->gtNewHelperCallNode(helper, TYP_LONG, 0, argList); + call->gtFlags |= tree->gtFlags & GTF_ALL_EFFECT; + + GenTreeCall* callNode = call->AsCall(); + ReturnTypeDesc* retTypeDesc = callNode->GetReturnTypeDesc(); + retTypeDesc->InitializeLongReturnType(m_compiler); + + call = m_compiler->fgMorphArgs(callNode); + Range().InsertAfter(tree, LIR::SeqTree(m_compiler, call)); + + Range().Remove(tree); + use.ReplaceWith(m_compiler, call); + return call; + } +} + +//------------------------------------------------------------------------ +// DecomposeRotate: Decompose GT_ROL and GT_ROR with constant shift amounts. We can +// inspect the rotate amount and decompose to the appropriate node types, generating +// a shld/shld pattern for GT_ROL, a shrd/shrd pattern for GT_ROR, for most rotate +// amounts. +// +// Arguments: +// use - the LIR::Use object for the def that needs to be decomposed. +// +// Return Value: +// The next node to process. +// +GenTree* DecomposeLongs::DecomposeRotate(LIR::Use& use) +{ + GenTree* tree = use.Def(); + GenTree* gtLong = tree->gtGetOp1(); + GenTree* rotateByOp = tree->gtGetOp2(); + + genTreeOps oper = tree->OperGet(); + + assert((oper == GT_ROL) || (oper == GT_ROR)); + assert(rotateByOp->IsCnsIntOrI()); + + // For longs, we need to change rols into two GT_LSH_HIs and rors into two GT_RSH_LOs + // so we will get: + // + // shld lo, hi, rotateAmount + // shld hi, loCopy, rotateAmount + // + // or: + // + // shrd lo, hi, rotateAmount + // shrd hi, loCopy, rotateAmount + + if (oper == GT_ROL) { - case GT_LSH: - helper = CORINFO_HELP_LLSH; - break; - case GT_RSH: - helper = CORINFO_HELP_LRSH; - break; - case GT_RSZ: - helper = CORINFO_HELP_LRSZ; - break; - default: - unreached(); + oper = GT_LSH_HI; + } + else + { + oper = GT_RSH_LO; } - GenTreeArgList* argList = m_compiler->gtNewArgList(loOp1, hiOp1, shiftWidthOp); + unsigned int count = rotateByOp->gtIntCon.gtIconVal; + Range().Remove(rotateByOp); + + // Make sure the rotate amount is between 0 and 63. + assert((count < 64) && (count != 0)); + + GenTree* loResult; + GenTree* hiResult; + + if (count == 32) + { + // If the rotate amount is 32, then swap hi and lo + LIR::Use loOp1Use(Range(), >Long->gtOp.gtOp1, gtLong); + loOp1Use.ReplaceWithLclVar(m_compiler, m_blockWeight); + + LIR::Use hiOp1Use(Range(), >Long->gtOp.gtOp2, gtLong); + hiOp1Use.ReplaceWithLclVar(m_compiler, m_blockWeight); + + hiResult = loOp1Use.Def(); + loResult = hiOp1Use.Def(); + gtLong->gtOp.gtOp1 = loResult; + gtLong->gtOp.gtOp2 = hiResult; + + GenTree* next = tree->gtNext; + // Remove tree and don't do anything else. + Range().Remove(tree); + use.ReplaceWith(m_compiler, gtLong); + return next; + } + else + { + GenTree* loOp1; + GenTree* hiOp1; + + if (count > 32) + { + // If count > 32, we swap hi and lo, and subtract 32 from count + hiOp1 = gtLong->gtGetOp1(); + loOp1 = gtLong->gtGetOp2(); + + Range().Remove(gtLong); + loOp1 = RepresentOpAsLocalVar(loOp1, gtLong, >Long->gtOp.gtOp2); + hiOp1 = RepresentOpAsLocalVar(hiOp1, gtLong, >Long->gtOp.gtOp1); + + count -= 32; + } + else + { + loOp1 = gtLong->gtGetOp1(); + hiOp1 = gtLong->gtGetOp2(); + + Range().Remove(gtLong); + loOp1 = RepresentOpAsLocalVar(loOp1, gtLong, >Long->gtOp.gtOp1); + hiOp1 = RepresentOpAsLocalVar(hiOp1, gtLong, >Long->gtOp.gtOp2); + } + + unsigned loOp1LclNum = loOp1->AsLclVarCommon()->gtLclNum; + unsigned hiOp1LclNum = hiOp1->AsLclVarCommon()->gtLclNum; + + Range().Remove(loOp1); + Range().Remove(hiOp1); + + GenTree* rotateByHi = m_compiler->gtNewIconNode(count, TYP_INT); + GenTree* rotateByLo = m_compiler->gtNewIconNode(count, TYP_INT); + + // Create a GT_LONG that contains loOp1 and hiCopy. This will be used in codegen to + // generate the shld instruction + GenTree* hiCopy = m_compiler->gtNewLclvNode(hiOp1LclNum, TYP_INT); + GenTree* loOp = new (m_compiler, GT_LONG) GenTreeOp(GT_LONG, TYP_LONG, hiCopy, loOp1); + loResult = m_compiler->gtNewOperNode(oper, TYP_INT, loOp, rotateByLo); + + // Create a GT_LONG that contains loCopy and hiOp1. This will be used in codegen to + // generate the shld instruction + GenTree* loCopy = m_compiler->gtNewLclvNode(loOp1LclNum, TYP_INT); + GenTree* hiOp = new (m_compiler, GT_LONG) GenTreeOp(GT_LONG, TYP_LONG, loCopy, hiOp1); + hiResult = m_compiler->gtNewOperNode(oper, TYP_INT, hiOp, rotateByHi); + + m_compiler->lvaIncRefCnts(loCopy); + m_compiler->lvaIncRefCnts(hiCopy); + + Range().InsertBefore(tree, hiCopy, loOp1, loOp); + Range().InsertBefore(tree, rotateByLo, loResult); + Range().InsertBefore(tree, loCopy, hiOp1, hiOp); + Range().InsertBefore(tree, rotateByHi, hiResult); + + Range().Remove(tree); + + return FinalizeDecomposition(use, loResult, hiResult, hiResult); + } +} + +//------------------------------------------------------------------------ +// DecomposeMul: Decompose GT_MUL. The only GT_MULs that make it to decompose are +// those with the GTF_MUL_64RSLT flag set. These muls result in a mul instruction that +// returns its result in two registers like GT_CALLs do. Additionally, these muls are +// guaranteed to be in the form long = (long)int * (long)int. Therefore, to decompose +// these nodes, we convert them into GT_MUL_LONGs, undo the cast from int to long by +// stripping out the lo ops, and force them into the form var = mul, as we do for +// GT_CALLs. In codegen, we then produce a mul instruction that produces the result +// in edx:eax, and store those registers on the stack in genStoreLongLclVar. +// +// All other GT_MULs have been converted to helper calls in morph.cpp +// +// Arguments: +// use - the LIR::Use object for the def that needs to be decomposed. +// +// Return Value: +// The next node to process. +// +GenTree* DecomposeLongs::DecomposeMul(LIR::Use& use) +{ + assert(use.IsInitialized()); + + GenTree* tree = use.Def(); + genTreeOps oper = tree->OperGet(); + + assert(oper == GT_MUL); + assert((tree->gtFlags & GTF_MUL_64RSLT) != 0); + + GenTree* op1 = tree->gtGetOp1(); + GenTree* op2 = tree->gtGetOp2(); + + GenTree* loOp1 = op1->gtGetOp1(); + GenTree* hiOp1 = op1->gtGetOp2(); + GenTree* loOp2 = op2->gtGetOp1(); + GenTree* hiOp2 = op2->gtGetOp2(); + + Range().Remove(hiOp1); + Range().Remove(hiOp2); + Range().Remove(op1); + Range().Remove(op2); + + // Get rid of the hi ops. We don't need them. + tree->gtOp.gtOp1 = loOp1; + tree->gtOp.gtOp2 = loOp2; + tree->SetOperRaw(GT_MUL_LONG); + + return StoreNodeToVar(use); +} + +//------------------------------------------------------------------------ +// DecomposeUMod: Decompose GT_UMOD. The only GT_UMODs that make it to decompose +// are guaranteed to be an unsigned long mod with op2 which is a cast to long from +// a constant int whose value is between 2 and 0x3fffffff. All other GT_UMODs are +// morphed into helper calls. These GT_UMODs will actually return an int value in +// RDX. In decompose, we make the lo operation a TYP_INT GT_UMOD, with op2 as the +// original lo half and op1 as a GT_LONG. We make the hi part 0, so we end up with: +// +// GT_UMOD[TYP_INT] ( GT_LONG [TYP_LONG] (loOp1, hiOp1), loOp2 [TYP_INT] ) +// +// With the expectation that we will generate: +// +// EDX = hiOp1 +// EAX = loOp1 +// reg = loOp2 +// idiv reg +// EDX is the remainder, and result of GT_UMOD +// mov hiReg = 0 +// +// Arguments: +// use - the LIR::Use object for the def that needs to be decomposed. +// +// Return Value: +// The next node to process. +// +GenTree* DecomposeLongs::DecomposeUMod(LIR::Use& use) +{ + assert(use.IsInitialized()); + + GenTree* tree = use.Def(); + genTreeOps oper = tree->OperGet(); + + assert(oper == GT_UMOD); + + GenTree* op1 = tree->gtGetOp1(); + GenTree* op2 = tree->gtGetOp2(); + assert(op1->OperGet() == GT_LONG); + assert(op2->OperGet() == GT_LONG); + + GenTree* loOp2 = op2->gtGetOp1(); + GenTree* hiOp2 = op2->gtGetOp2(); + + assert(loOp2->OperGet() == GT_CNS_INT); + assert(hiOp2->OperGet() == GT_CNS_INT); + assert((loOp2->gtIntCon.gtIconVal >= 2) && (loOp2->gtIntCon.gtIconVal <= 0x3fffffff)); + assert(hiOp2->gtIntCon.gtIconVal == 0); + + // Get rid of op2's hi part. We don't need it. + Range().Remove(hiOp2); + Range().Remove(op2); + + // Lo part is the GT_UMOD + GenTree* loResult = tree; + loResult->gtOp.gtOp2 = loOp2; + loResult->gtType = TYP_INT; - GenTree* call = m_compiler->gtNewHelperCallNode(helper, TYP_LONG, 0, argList); + // Set the high part to 0 + GenTree* hiResult = m_compiler->gtNewZeroConNode(TYP_INT); - GenTreeCall* callNode = call->AsCall(); - ReturnTypeDesc* retTypeDesc = callNode->GetReturnTypeDesc(); - retTypeDesc->InitializeLongReturnType(m_compiler); + Range().InsertAfter(loResult, hiResult); - call = m_compiler->fgMorphArgs(callNode); - Range().InsertAfter(tree, LIR::SeqTree(m_compiler, call)); - - Range().Remove(tree); - use.ReplaceWith(m_compiler, call); - return call; + return FinalizeDecomposition(use, loResult, hiResult, hiResult); +} + +//------------------------------------------------------------------------ +// StoreNodeToVar: Check if the user is a STORE_LCL_VAR, and if it isn't, +// store the node to a var. Then decompose the new LclVar. +// +// Arguments: +// use - the LIR::Use object for the def that needs to be decomposed. +// +// Return Value: +// The next node to process. +// +GenTree* DecomposeLongs::StoreNodeToVar(LIR::Use& use) +{ + if (use.IsDummyUse()) + return use.Def()->gtNext; + + GenTree* tree = use.Def(); + GenTree* user = use.User(); + + if (user->OperGet() == GT_STORE_LCL_VAR) + { + // If parent is already a STORE_LCL_VAR, we can skip it if + // it is already marked as lvIsMultiRegRet. + unsigned varNum = user->AsLclVarCommon()->gtLclNum; + if (m_compiler->lvaTable[varNum].lvIsMultiRegRet) + { + return tree->gtNext; + } + else if (!m_compiler->lvaTable[varNum].lvPromoted) + { + // If var wasn't promoted, we can just set lvIsMultiRegRet. + m_compiler->lvaTable[varNum].lvIsMultiRegRet = true; + return tree->gtNext; + } + } + + // Otherwise, we need to force var = call() + unsigned varNum = use.ReplaceWithLclVar(m_compiler, m_blockWeight); + m_compiler->lvaTable[varNum].lvIsMultiRegRet = true; + + // Decompose the new LclVar use + return DecomposeLclVar(use); +} + +//------------------------------------------------------------------------ +// Check is op already local var, if not store it to local. +// +// Arguments: +// op - GenTree* to represent as local variable +// user - user of op +// edge - edge from user to op +// +// Return Value: +// op represented as local var +// +GenTree* DecomposeLongs::RepresentOpAsLocalVar(GenTree* op, GenTree* user, GenTree** edge) +{ + if (op->OperGet() == GT_LCL_VAR) + { + return op; + } + else + { + LIR::Use opUse(Range(), edge, user); + opUse.ReplaceWithLclVar(m_compiler, m_blockWeight); + return *edge; + } } //------------------------------------------------------------------------ @@ -965,9 +1648,6 @@ genTreeOps DecomposeLongs::GetHiOper(genTreeOps oper) case GT_SUB: return GT_SUB_HI; break; - case GT_MUL: - return GT_MUL_HI; - break; case GT_DIV: return GT_DIV_HI; break; diff --git a/src/jit/decomposelongs.h b/src/jit/decomposelongs.h index af9b342..8965a0b 100644 --- a/src/jit/decomposelongs.h +++ b/src/jit/decomposelongs.h @@ -35,13 +35,14 @@ private: } // Driver functions - void DecomposeRangeHelper(); - GenTree* DecomposeNode(LIR::Use& use); + void DecomposeRangeHelper(); + GenTree* DecomposeNode(GenTree* tree); // Per-node type decompose cases GenTree* DecomposeLclVar(LIR::Use& use); GenTree* DecomposeLclFld(LIR::Use& use); GenTree* DecomposeStoreLclVar(LIR::Use& use); + GenTree* DecomposeStoreLclFld(LIR::Use& use); GenTree* DecomposeCast(LIR::Use& use); GenTree* DecomposeCnsLng(LIR::Use& use); GenTree* DecomposeCall(LIR::Use& use); @@ -51,10 +52,15 @@ private: GenTree* DecomposeNeg(LIR::Use& use); GenTree* DecomposeArith(LIR::Use& use); GenTree* DecomposeShift(LIR::Use& use); + GenTree* DecomposeRotate(LIR::Use& use); + GenTree* DecomposeMul(LIR::Use& use); + GenTree* DecomposeUMod(LIR::Use& use); // Helper functions - GenTree* FinalizeDecomposition(LIR::Use& use, GenTree* loResult, GenTree* hiResult); + GenTree* FinalizeDecomposition(LIR::Use& use, GenTree* loResult, GenTree* hiResult, GenTree* insertResultAfter); + GenTree* RepresentOpAsLocalVar(GenTree* op, GenTree* user, GenTree** edge); + GenTree* StoreNodeToVar(LIR::Use& use); static genTreeOps GetHiOper(genTreeOps oper); static genTreeOps GetLoOper(genTreeOps oper); diff --git a/src/jit/dll/CMakeLists.txt b/src/jit/dll/CMakeLists.txt index 01e58db..43ed07e 100644 --- a/src/jit/dll/CMakeLists.txt +++ b/src/jit/dll/CMakeLists.txt @@ -1,20 +1,20 @@ project(ClrJit) -if(CLR_CMAKE_PLATFORM_ARCH_I386 OR CLR_CMAKE_PLATFORM_ARCH_ARM) +if(CLR_CMAKE_TARGET_ARCH_ARM) add_definitions(-DLEGACY_BACKEND) -endif(CLR_CMAKE_PLATFORM_ARCH_I386 OR CLR_CMAKE_PLATFORM_ARCH_ARM) +endif(CLR_CMAKE_TARGET_ARCH_ARM) # Disable the following for UNIX altjit on Windows if(CLR_CMAKE_PLATFORM_UNIX) add_compile_options(-fPIC) - add_library_clr(${JIT_BASE_NAME}_static + add_library_clr(clrjit_static STATIC ${SHARED_LIB_SOURCES} ) - add_dependencies(${JIT_BASE_NAME}_static coreclrpal gcinfo) + add_dependencies(clrjit_static coreclrpal gcinfo) else() - add_library_clr(${JIT_BASE_NAME}_static + add_library_clr(clrjit_static ${SOURCES} ) # Disable up to here (see above) the following for UNIX altjit on Windows diff --git a/src/jit/dll/jit.nativeproj b/src/jit/dll/jit.nativeproj index 97981e7..7505f5e 100644 --- a/src/jit/dll/jit.nativeproj +++ b/src/jit/dll/jit.nativeproj @@ -37,9 +37,9 @@ - false - true - true + false + true + true $(Win32DllLibs);$(CrtLibPath)\pgort.lib $(Win32DllLibs);$(CrtLibPath)\pgort.lib;$(SdkLibPath)\ntdll.lib $(_BuildArch)\CLR\Base diff --git a/src/jit/earlyprop.cpp b/src/jit/earlyprop.cpp index 70d1012..51de631 100644 --- a/src/jit/earlyprop.cpp +++ b/src/jit/earlyprop.cpp @@ -189,8 +189,7 @@ void Compiler::optEarlyProp() // Walk the stmt tree in linear order to rewrite any array length reference with a // constant array length. - bool isRewritten = false; - bool bbHasNullCheck = (block->bbFlags & BBF_HAS_NULLCHECK) != 0; + bool isRewritten = false; for (GenTreePtr tree = stmt->gtStmt.gtStmtList; tree != nullptr; tree = tree->gtNext) { if (optEarlyPropRewriteTree(tree)) @@ -238,12 +237,8 @@ bool Compiler::optEarlyPropRewriteTree(GenTreePtr tree) objectRefPtr = tree->gtOp.gtOp1; propKind = optPropKind::OPK_ARRAYLEN; } - else if ((tree->OperGet() == GT_IND) && !varTypeIsStruct(tree)) + else if (tree->OperIsIndir()) { - // TODO-1stClassStructs: The above condition should apply equally to all indirections, - // but previously the implicit indirections due to a struct assignment were not - // considered, so we are currently limiting it to non-structs to preserve existing - // behavior. // optFoldNullCheck takes care of updating statement info if a null check is removed. optFoldNullCheck(tree); @@ -259,7 +254,7 @@ bool Compiler::optEarlyPropRewriteTree(GenTreePtr tree) return false; } - objectRefPtr = tree->gtOp.gtOp1; + objectRefPtr = tree->AsIndir()->Addr(); propKind = optPropKind::OPK_OBJ_GETTYPE; } else @@ -511,15 +506,23 @@ void Compiler::optFoldNullCheck(GenTreePtr tree) // | // x - assert(tree->OperGet() == GT_IND); - if (tree->gtGetOp1()->OperGet() == GT_LCL_VAR) + if ((compCurBB->bbFlags & BBF_HAS_NULLCHECK) == 0) + { + return; + } + + assert(tree->OperIsIndir()); + + GenTree* const addr = tree->AsIndir()->Addr(); + if (addr->OperGet() == GT_LCL_VAR) { // Check if we have the pattern above and find the nullcheck node if we do. // Find the definition of the indirected local (x in the picture) - GenTreePtr indLocalTree = tree->gtGetOp1(); - unsigned lclNum = indLocalTree->AsLclVarCommon()->GetLclNum(); - unsigned ssaNum = indLocalTree->AsLclVarCommon()->GetSsaNum(); + GenTreeLclVarCommon* const lclVarNode = addr->AsLclVarCommon(); + + const unsigned lclNum = lclVarNode->GetLclNum(); + const unsigned ssaNum = lclVarNode->GetSsaNum(); if (ssaNum != SsaConfig::RESERVED_SSA_NUM) { @@ -557,7 +560,7 @@ void Compiler::optFoldNullCheck(GenTreePtr tree) { // Walk from the use to the def in reverse execution order to see // if any nodes have unsafe side effects. - GenTreePtr currentTree = indLocalTree->gtPrev; + GenTreePtr currentTree = lclVarNode->gtPrev; bool isInsideTry = compCurBB->hasTryIndex(); bool canRemoveNullCheck = true; const unsigned maxNodesWalked = 25; @@ -612,13 +615,8 @@ void Compiler::optFoldNullCheck(GenTreePtr tree) additionNode->gtFlags & (GTF_EXCEPT | GTF_DONT_CSE); // Re-morph the statement. - fgMorphBlockStmt(compCurBB, curStmt DEBUGARG("optFoldNullCheck")); - - // Recalculate the gtCostSz, etc... - gtSetStmtInfo(curStmt); - - // Re-thread the nodes - fgSetStmtSeq(curStmt); + fgMorphBlockStmt(compCurBB, + curStmt->AsStmt() DEBUGARG("optFoldNullCheck")); } } } @@ -668,4 +666,4 @@ bool Compiler::optCanMoveNullCheckPastTree(GenTreePtr tree, bool isInsideTry) } } return result; -} \ No newline at end of file +} diff --git a/src/jit/ee_il_dll.cpp b/src/jit/ee_il_dll.cpp old mode 100755 new mode 100644 index 5272442..dcadaa9 --- a/src/jit/ee_il_dll.cpp +++ b/src/jit/ee_il_dll.cpp @@ -284,21 +284,17 @@ CorJitResult CILJit::compileMethod( return g_realJitCompiler->compileMethod(compHnd, methodInfo, flags, entryAddress, nativeSizeOfCode); } - CORJIT_FLAGS jitFlags = {0}; + JitFlags jitFlags; - DWORD jitFlagsSize = 0; #if COR_JIT_EE_VERSION > 460 - if (flags == CORJIT_FLG_CALL_GETJITFLAGS) - { - jitFlagsSize = compHnd->getJitFlags(&jitFlags, sizeof(jitFlags)); - } -#endif - - assert(jitFlagsSize <= sizeof(jitFlags)); - if (jitFlagsSize == 0) - { - jitFlags.corJitFlags = flags; - } + assert(flags == CORJIT_FLAGS::CORJIT_FLAG_CALL_GETJITFLAGS); + CORJIT_FLAGS corJitFlags; + DWORD jitFlagsSize = compHnd->getJitFlags(&corJitFlags, sizeof(corJitFlags)); + assert(jitFlagsSize == sizeof(corJitFlags)); + jitFlags.SetFromFlags(corJitFlags); +#else // COR_JIT_EE_VERSION <= 460 + jitFlags.SetFromOldFlags(flags, 0); +#endif // COR_JIT_EE_VERSION <= 460 int result; void* methodCodePtr = nullptr; @@ -385,17 +381,31 @@ void CILJit::getVersionIdentifier(GUID* versionIdentifier) /***************************************************************************** * Determine the maximum length of SIMD vector supported by this JIT. */ + +#if COR_JIT_EE_VERSION > 460 +unsigned CILJit::getMaxIntrinsicSIMDVectorLength(CORJIT_FLAGS cpuCompileFlags) +#else unsigned CILJit::getMaxIntrinsicSIMDVectorLength(DWORD cpuCompileFlags) +#endif { if (g_realJitCompiler != nullptr) { return g_realJitCompiler->getMaxIntrinsicSIMDVectorLength(cpuCompileFlags); } -#ifdef _TARGET_AMD64_ + JitFlags jitFlags; + +#if COR_JIT_EE_VERSION > 460 + jitFlags.SetFromFlags(cpuCompileFlags); +#else // COR_JIT_EE_VERSION <= 460 + jitFlags.SetFromOldFlags(cpuCompileFlags, 0); +#endif // COR_JIT_EE_VERSION <= 460 + +#ifdef FEATURE_SIMD +#ifdef _TARGET_XARCH_ #ifdef FEATURE_AVX_SUPPORT - if (((cpuCompileFlags & CORJIT_FLG_PREJIT) == 0) && ((cpuCompileFlags & CORJIT_FLG_FEATURE_SIMD) != 0) && - ((cpuCompileFlags & CORJIT_FLG_USE_AVX2) != 0)) + if (!jitFlags.IsSet(JitFlags::JIT_FLAG_PREJIT) && jitFlags.IsSet(JitFlags::JIT_FLAG_FEATURE_SIMD) && + jitFlags.IsSet(JitFlags::JIT_FLAG_USE_AVX2)) { if (JitConfig.EnableAVX() != 0) { @@ -404,9 +414,10 @@ unsigned CILJit::getMaxIntrinsicSIMDVectorLength(DWORD cpuCompileFlags) } #endif // FEATURE_AVX_SUPPORT return 16; -#else // !_TARGET_AMD64_ +#endif // _TARGET_XARCH_ +#else // !FEATURE_SIMD return 0; -#endif // !_TARGET_AMD64_ +#endif // !FEATURE_SIMD } void CILJit::setRealJit(ICorJitCompiler* realJitCompiler) @@ -1378,7 +1389,7 @@ bool Compiler::eeRunWithErrorTrapImp(void (*function)(void*), void* param) * Utility functions */ -#if defined(DEBUG) || defined(FEATURE_JIT_METHOD_PERF) || defined(FEATURE_SIMD) +#if defined(DEBUG) || defined(FEATURE_JIT_METHOD_PERF) || defined(FEATURE_SIMD) || defined(FEATURE_TRACELOGGING) /*****************************************************************************/ @@ -1526,6 +1537,9 @@ const char* Compiler::eeGetClassName(CORINFO_CLASS_HANDLE clsHnd) const wchar_t* Compiler::eeGetCPString(size_t strHandle) { +#ifdef FEATURE_PAL + return nullptr; +#else char buff[512 + sizeof(CORINFO_String)]; // make this bulletproof, so it works even if we are wrong. @@ -1547,6 +1561,7 @@ const wchar_t* Compiler::eeGetCPString(size_t strHandle) } return (asString->chars); +#endif // FEATURE_PAL } #endif // DEBUG diff --git a/src/jit/ee_il_dll.hpp b/src/jit/ee_il_dll.hpp index d9bf95f..3899d92 100644 --- a/src/jit/ee_il_dll.hpp +++ b/src/jit/ee_il_dll.hpp @@ -21,7 +21,11 @@ class CILJit : public ICorJitCompiler void getVersionIdentifier(GUID* versionIdentifier /* OUT */ ); +#if COR_JIT_EE_VERSION > 460 + unsigned getMaxIntrinsicSIMDVectorLength(CORJIT_FLAGS cpuCompileFlags); +#else unsigned getMaxIntrinsicSIMDVectorLength(DWORD cpuCompileFlags); +#endif void setRealJit(ICorJitCompiler* realJitCompiler); }; diff --git a/src/jit/emit.cpp b/src/jit/emit.cpp index 5c991dd..0929b73 100644 --- a/src/jit/emit.cpp +++ b/src/jit/emit.cpp @@ -1264,9 +1264,9 @@ void* emitter::emitAllocInstr(size_t sz, emitAttr opsz) // ARM - This is currently broken on _TARGET_ARM_ // When nopSize is odd we misalign emitCurIGsize // - if (!(emitComp->opts.eeFlags & CORJIT_FLG_PREJIT) && !emitInInstrumentation && - !emitIGisInProlog(emitCurIG) // don't do this in prolog or epilog - && !emitIGisInEpilog(emitCurIG) && + if (!emitComp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT) && !emitInInstrumentation && + !emitIGisInProlog(emitCurIG) && // don't do this in prolog or epilog + !emitIGisInEpilog(emitCurIG) && emitRandomNops // sometimes we turn off where exact codegen is needed (pinvoke inline) ) { @@ -1670,13 +1670,9 @@ void emitter::emitCreatePlaceholderIG(insGroupPlaceholderType igType, emitCurIGsize += MAX_PLACEHOLDER_IG_SIZE; emitCurCodeOffset += emitCurIGsize; -#ifdef DEBUGGING_SUPPORT - #if FEATURE_EH_FUNCLETS // Add the appropriate IP mapping debugging record for this placeholder - // group. - - // genExitCode() adds the mapping for main function epilogs + // group. genExitCode() adds the mapping for main function epilogs. if (emitComp->opts.compDbgInfo) { if (igType == IGPT_FUNCLET_PROLOG) @@ -1690,8 +1686,6 @@ void emitter::emitCreatePlaceholderIG(insGroupPlaceholderType igType, } #endif // FEATURE_EH_FUNCLETS -#endif // DEBUGGING_SUPPORT - /* Start a new IG if more code follows */ if (last) @@ -2320,7 +2314,7 @@ bool emitter::emitNoGChelper(unsigned IHX) case CORINFO_HELP_PROF_FCN_LEAVE: case CORINFO_HELP_PROF_FCN_ENTER: -#ifdef _TARGET_AMD64_ +#if defined(_TARGET_AMD64_) || (defined(_TARGET_X86_) && !defined(LEGACY_BACKEND)) case CORINFO_HELP_PROF_FCN_TAILCALL: #endif case CORINFO_HELP_LLSH: @@ -3414,8 +3408,6 @@ size_t emitter::emitIssue1Instr(insGroup* ig, instrDesc* id, BYTE** dp) #endif -#if defined(DEBUGGING_SUPPORT) || defined(DEBUG) - /* Did the size of the instruction match our expectations? */ UNATIVE_OFFSET csz = (UNATIVE_OFFSET)(*dp - curInsAdr); @@ -3447,8 +3439,6 @@ size_t emitter::emitIssue1Instr(insGroup* ig, instrDesc* id, BYTE** dp) #endif } -#endif - #ifdef DEBUG /* Make sure the instruction descriptor size also matches our expectations */ if (is != emitSizeOfInsDsc(id)) @@ -6048,7 +6038,7 @@ unsigned char emitter::emitOutputLong(BYTE* dst, ssize_t val) #ifdef DEBUG if (emitComp->opts.dspEmit) { - printf("; emit_long 0%08XH\n", val); + printf("; emit_long 0%08XH\n", (int)val); } #ifdef _TARGET_AMD64_ // if we're emitting code bytes, ensure that we've already emitted the rex prefix! @@ -6072,9 +6062,9 @@ unsigned char emitter::emitOutputSizeT(BYTE* dst, ssize_t val) if (emitComp->opts.dspEmit) { #ifdef _TARGET_AMD64_ - printf("; emit_size_t 0%016llXH\n", (size_t)val); + printf("; emit_size_t 0%016llXH\n", val); #else // _TARGET_AMD64_ - printf("; emit_size_t 0%08XH\n", (size_t)val); + printf("; emit_size_t 0%08XH\n", val); #endif // _TARGET_AMD64_ } #endif // DEBUG @@ -6082,6 +6072,60 @@ unsigned char emitter::emitOutputSizeT(BYTE* dst, ssize_t val) return sizeof(size_t); } +//------------------------------------------------------------------------ +// Wrappers to emitOutputByte, emitOutputWord, emitOutputLong, emitOutputSizeT +// that take unsigned __int64 or size_t type instead of ssize_t. Used on RyuJIT/x86. +// +// Arguments: +// dst - passed through +// val - passed through +// +// Return Value: +// Same as wrapped function. +// + +#if !defined(LEGACY_BACKEND) && defined(_TARGET_X86_) +unsigned char emitter::emitOutputByte(BYTE* dst, size_t val) +{ + return emitOutputByte(dst, (ssize_t)val); +} + +unsigned char emitter::emitOutputWord(BYTE* dst, size_t val) +{ + return emitOutputWord(dst, (ssize_t)val); +} + +unsigned char emitter::emitOutputLong(BYTE* dst, size_t val) +{ + return emitOutputLong(dst, (ssize_t)val); +} + +unsigned char emitter::emitOutputSizeT(BYTE* dst, size_t val) +{ + return emitOutputSizeT(dst, (ssize_t)val); +} + +unsigned char emitter::emitOutputByte(BYTE* dst, unsigned __int64 val) +{ + return emitOutputByte(dst, (ssize_t)val); +} + +unsigned char emitter::emitOutputWord(BYTE* dst, unsigned __int64 val) +{ + return emitOutputWord(dst, (ssize_t)val); +} + +unsigned char emitter::emitOutputLong(BYTE* dst, unsigned __int64 val) +{ + return emitOutputLong(dst, (ssize_t)val); +} + +unsigned char emitter::emitOutputSizeT(BYTE* dst, unsigned __int64 val) +{ + return emitOutputSizeT(dst, (ssize_t)val); +} +#endif // !defined(LEGACY_BACKEND) && defined(_TARGET_X86_) + /***************************************************************************** * * Given a block cookie and a code position, return the actual code offset; diff --git a/src/jit/emit.h b/src/jit/emit.h index 8fb24bc..5b1a395 100644 --- a/src/jit/emit.h +++ b/src/jit/emit.h @@ -427,6 +427,11 @@ public: // There seem to be some cases where this is used without being initialized via CodeGen::inst_set_SV_var(). emitVarRefOffs = 0; #endif // DEBUG + +#ifdef _TARGET_XARCH_ + SetUseSSE3_4(false); +#endif // _TARGET_XARCH_ + #ifdef FEATURE_AVX_SUPPORT SetUseAVX(false); #endif // FEATURE_AVX_SUPPORT @@ -1659,6 +1664,18 @@ private: unsigned char emitOutputLong(BYTE* dst, ssize_t val); unsigned char emitOutputSizeT(BYTE* dst, ssize_t val); +#if !defined(LEGACY_BACKEND) && defined(_TARGET_X86_) + unsigned char emitOutputByte(BYTE* dst, size_t val); + unsigned char emitOutputWord(BYTE* dst, size_t val); + unsigned char emitOutputLong(BYTE* dst, size_t val); + unsigned char emitOutputSizeT(BYTE* dst, size_t val); + + unsigned char emitOutputByte(BYTE* dst, unsigned __int64 val); + unsigned char emitOutputWord(BYTE* dst, unsigned __int64 val); + unsigned char emitOutputLong(BYTE* dst, unsigned __int64 val); + unsigned char emitOutputSizeT(BYTE* dst, unsigned __int64 val); +#endif // !defined(LEGACY_BACKEND) && defined(_TARGET_X86_) + size_t emitIssue1Instr(insGroup* ig, instrDesc* id, BYTE** dp); size_t emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp); @@ -1742,8 +1759,8 @@ private: BYTE* emitCurIGfreeEndp; // one byte past the last available byte in buffer BYTE* emitCurIGfreeBase; // first byte address - unsigned emitCurIGinsCnt; // # of collected instr's in buffer - unsigned emitCurIGsize; // estimated code size of current group in bytes + unsigned emitCurIGinsCnt; // # of collected instr's in buffer + unsigned emitCurIGsize; // estimated code size of current group in bytes UNATIVE_OFFSET emitCurCodeOffset; // current code offset within group UNATIVE_OFFSET emitTotalCodeSize; // bytes of code in entire method @@ -1822,8 +1839,12 @@ private: void emitInsertIGAfter(insGroup* insertAfterIG, insGroup* ig); void emitNewIG(); + +#if !defined(JIT32_GCENCODER) void emitDisableGC(); void emitEnableGC(); +#endif // !defined(JIT32_GCENCODER) + void emitGenIG(insGroup* ig); insGroup* emitSavIG(bool emitAdd = false); void emitNxtIG(bool emitAdd = false); @@ -2707,6 +2728,7 @@ inline void emitter::emitNewIG() emitGenIG(ig); } +#if !defined(JIT32_GCENCODER) // Start a new instruction group that is not interruptable inline void emitter::emitDisableGC() { @@ -2736,6 +2758,7 @@ inline void emitter::emitEnableGC() // instruction groups. emitForceNewIG = true; } +#endif // !defined(JIT32_GCENCODER) /*****************************************************************************/ #endif // _EMIT_H_ diff --git a/src/jit/emitarm.cpp b/src/jit/emitarm.cpp index 1f57048..45928ca 100644 --- a/src/jit/emitarm.cpp +++ b/src/jit/emitarm.cpp @@ -4368,6 +4368,7 @@ void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNu * * EC_FUNC_TOKEN : addr is the method address * EC_FUNC_ADDR : addr is the absolute address of the function + * if addr is NULL, it is a recursive call * * If callType is one of these emitCallTypes, addr has to be NULL. * EC_INDIR_R : "call ireg". @@ -4463,13 +4464,11 @@ void emitter::emitIns_Call(EmitCallType callType, assert(argSize % (int)sizeof(void*) == 0); argCnt = argSize / (int)sizeof(void*); -#ifdef DEBUGGING_SUPPORT /* Managed RetVal: emit sequence point for the call */ if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET) { codeGen->genIPmappingAdd(ilOffset, false); } -#endif /* We need to allocate the appropriate instruction descriptor based @@ -4555,8 +4554,8 @@ void emitter::emitIns_Call(EmitCallType callType, assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR); - assert(addr != NULL); - assert(codeGen->validImmForBL((ssize_t)addr)); + // if addr is nullptr then this call is treated as a recursive call. + assert(addr == nullptr || codeGen->arm_Valid_Imm_For_BL((ssize_t)addr)); if (isJump) { @@ -5266,8 +5265,8 @@ BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i) else #endif { - assert(distVal >= -16777216); - assert(distVal <= 16777214); + assert(distVal >= CALL_DIST_MAX_NEG); + assert(distVal <= CALL_DIST_MAX_POS); if (distVal < 0) code |= 1 << 26; @@ -6211,7 +6210,14 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) sz = sizeof(instrDesc); } - addr = id->idAddr()->iiaAddr; + if (id->idAddr()->iiaAddr == NULL) /* a recursive call */ + { + addr = emitCodeBlock; + } + else + { + addr = id->idAddr()->iiaAddr; + } code = emitInsCode(ins, fmt); #ifdef RELOC_SUPPORT diff --git a/src/jit/emitarm64.cpp b/src/jit/emitarm64.cpp index a632ec1..12c4087 100644 --- a/src/jit/emitarm64.cpp +++ b/src/jit/emitarm64.cpp @@ -6738,13 +6738,11 @@ void emitter::emitIns_Call(EmitCallType callType, assert(argSize % REGSIZE_BYTES == 0); argCnt = (int)(argSize / (int)sizeof(void*)); -#ifdef DEBUGGING_SUPPORT /* Managed RetVal: emit sequence point for the call */ if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET) { codeGen->genIPmappingAdd(ilOffset, false); } -#endif /* We need to allocate the appropriate instruction descriptor based diff --git a/src/jit/emitxarch.cpp b/src/jit/emitxarch.cpp index d43f766..b6bacfa 100644 --- a/src/jit/emitxarch.cpp +++ b/src/jit/emitxarch.cpp @@ -30,6 +30,15 @@ bool IsSSE2Instruction(instruction ins) return (ins >= INS_FIRST_SSE2_INSTRUCTION && ins <= INS_LAST_SSE2_INSTRUCTION); } +bool IsSSE4Instruction(instruction ins) +{ +#ifdef LEGACY_BACKEND + return false; +#else + return (ins >= INS_FIRST_SSE4_INSTRUCTION && ins <= INS_LAST_SSE4_INSTRUCTION); +#endif +} + bool IsSSEOrAVXInstruction(instruction ins) { #ifdef FEATURE_AVX_SUPPORT @@ -48,7 +57,9 @@ bool emitter::IsAVXInstruction(instruction ins) #endif } +#ifdef _TARGET_AMD64_ #define REX_PREFIX_MASK 0xFF00000000LL +#endif // _TARGET_AMD64_ #ifdef FEATURE_AVX_SUPPORT // Returns true if the AVX instruction is a binary operator that requires 3 operands. @@ -75,10 +86,8 @@ bool emitter::IsThreeOperandBinaryAVXInstruction(instruction ins) ins == INS_maxss || ins == INS_maxsd || ins == INS_andnps || ins == INS_andnpd || ins == INS_paddb || ins == INS_paddw || ins == INS_paddd || ins == INS_paddq || ins == INS_psubb || ins == INS_psubw || ins == INS_psubd || ins == INS_psubq || ins == INS_pmuludq || ins == INS_pxor || ins == INS_pmaxub || - ins == INS_pminub || ins == INS_pmaxsw || ins == INS_pminsw || ins == INS_insertps || ins == INS_vinsertf128 || - ins == INS_punpckldq - - ); + ins == INS_pminub || ins == INS_pmaxsw || ins == INS_pminsw || ins == INS_insertps || + ins == INS_vinsertf128 || ins == INS_punpckldq || ins == INS_phaddd); } // Returns true if the AVX instruction is a move operator that requires 3 operands. @@ -92,22 +101,45 @@ bool emitter::IsThreeOperandMoveAVXInstruction(instruction ins) return IsAVXInstruction(ins) && (ins == INS_movlpd || ins == INS_movlps || ins == INS_movhpd || ins == INS_movhps || ins == INS_movss); } -#endif // FEATURE_AVX_SUPPORT -// Returns true if the AVX instruction is a 4-byte opcode. +// ------------------------------------------------------------------------------ +// Is4ByteAVXInstruction: Returns true if the AVX instruction is a 4-byte opcode. +// +// Arguments: +// ins - instructions +// // Note that this should be true for any of the instructions in instrsXArch.h // that use the SSE38 or SSE3A macro. +// // TODO-XArch-Cleanup: This is a temporary solution for now. Eventually this // needs to be addressed by expanding instruction encodings. -bool Is4ByteAVXInstruction(instruction ins) +bool emitter::Is4ByteAVXInstruction(instruction ins) { -#ifdef FEATURE_AVX_SUPPORT - return (ins == INS_dpps || ins == INS_dppd || ins == INS_insertps || ins == INS_pcmpeqq || ins == INS_pcmpgtq || + return UseAVX() && + (ins == INS_dpps || ins == INS_dppd || ins == INS_insertps || ins == INS_pcmpeqq || ins == INS_pcmpgtq || ins == INS_vbroadcastss || ins == INS_vbroadcastsd || ins == INS_vpbroadcastb || ins == INS_vpbroadcastw || ins == INS_vpbroadcastd || ins == INS_vpbroadcastq || ins == INS_vextractf128 || ins == INS_vinsertf128 || - ins == INS_pmulld); -#else + ins == INS_pmulld || ins == INS_ptest || ins == INS_phaddd); +} +#endif // FEATURE_AVX_SUPPORT + +// ------------------------------------------------------------------- +// Is4ByteSSE4Instruction: Returns true if the SSE4 instruction +// is a 4-byte opcode. +// +// Arguments: +// ins - instruction +// +// Note that this should be true for any of the instructions in instrsXArch.h +// that use the SSE38 or SSE3A macro. +bool emitter::Is4ByteSSE4Instruction(instruction ins) +{ +#ifdef LEGACY_BACKEND + // On legacy backend SSE3_4 is not enabled. return false; +#else + return UseSSE3_4() && (ins == INS_dpps || ins == INS_dppd || ins == INS_insertps || ins == INS_pcmpeqq || + ins == INS_pcmpgtq || ins == INS_pmulld || ins == INS_ptest || ins == INS_phaddd); #endif } @@ -150,8 +182,9 @@ bool emitter::TakesVexPrefix(instruction ins) // prefix. Based on 'attr' param we could add 2-byte VEX prefix in case of scalar // and AVX-128 bit operations. #define DEFAULT_3BYTE_VEX_PREFIX 0xC4E07800000000ULL -#define LBIT_IN_3BYTE_VEX_PREFIX 0X00000400000000ULL -size_t emitter::AddVexPrefix(instruction ins, size_t code, emitAttr attr) +#define DEFAULT_3BYTE_VEX_PREFIX_MASK 0xFFFFFF00000000ULL +#define LBIT_IN_3BYTE_VEX_PREFIX 0x00000400000000ULL +emitter::code_t emitter::AddVexPrefix(instruction ins, code_t code, emitAttr attr) { // Only AVX instructions require VEX prefix assert(IsAVXInstruction(ins)); @@ -160,6 +193,7 @@ size_t emitter::AddVexPrefix(instruction ins, size_t code, emitAttr attr) assert(!hasVexPrefix(code)); // Set L bit to 1 in case of instructions that operate on 256-bits. + assert((code & DEFAULT_3BYTE_VEX_PREFIX_MASK) == 0); code |= DEFAULT_3BYTE_VEX_PREFIX; if (attr == EA_32BYTE) { @@ -296,25 +330,25 @@ bool IsXMMReg(regNumber reg) } // Returns bits to be encoded in instruction for the given register. -regNumber RegEncoding(regNumber reg) +unsigned RegEncoding(regNumber reg) { #ifndef LEGACY_BACKEND // XMM registers do not share the same reg numbers as integer registers. // But register encoding of integer and XMM registers is the same. // Therefore, subtract XMMBASE from regNumber to get the register encoding // in case of XMM registers. - return (regNumber)((IsXMMReg(reg) ? reg - XMMBASE : reg) & 0x7); + return (unsigned)((IsXMMReg(reg) ? reg - XMMBASE : reg) & 0x7); #else // LEGACY_BACKEND // Legacy X86: XMM registers share the same reg numbers as integer registers and // hence nothing to do to get reg encoding. - return (regNumber)(reg & 0x7); + return (unsigned)(reg & 0x7); #endif // LEGACY_BACKEND } // Utility routines that abstract the logic of adding REX.W, REX.R, REX.X, REX.B and REX prefixes // SSE2: separate 1-byte prefix gets added before opcode. // AVX: specific bits within VEX prefix need to be set in bit-inverted form. -size_t emitter::AddRexWPrefix(instruction ins, size_t code) +emitter::code_t emitter::AddRexWPrefix(instruction ins, code_t code) { #ifdef _TARGET_AMD64_ if (UseAVX() && IsAVXInstruction(ins)) @@ -335,7 +369,7 @@ size_t emitter::AddRexWPrefix(instruction ins, size_t code) #ifdef _TARGET_AMD64_ -size_t emitter::AddRexRPrefix(instruction ins, size_t code) +emitter::code_t emitter::AddRexRPrefix(instruction ins, code_t code) { if (UseAVX() && IsAVXInstruction(ins)) { @@ -349,7 +383,7 @@ size_t emitter::AddRexRPrefix(instruction ins, size_t code) return code | 0x4400000000ULL; } -size_t emitter::AddRexXPrefix(instruction ins, size_t code) +emitter::code_t emitter::AddRexXPrefix(instruction ins, code_t code) { if (UseAVX() && IsAVXInstruction(ins)) { @@ -363,7 +397,7 @@ size_t emitter::AddRexXPrefix(instruction ins, size_t code) return code | 0x4200000000ULL; } -size_t emitter::AddRexBPrefix(instruction ins, size_t code) +emitter::code_t emitter::AddRexBPrefix(instruction ins, code_t code) { if (UseAVX() && IsAVXInstruction(ins)) { @@ -378,12 +412,14 @@ size_t emitter::AddRexBPrefix(instruction ins, size_t code) } // Adds REX prefix (0x40) without W, R, X or B bits set -size_t emitter::AddRexPrefix(instruction ins, size_t code) +emitter::code_t emitter::AddRexPrefix(instruction ins, code_t code) { assert(!UseAVX() || !IsAVXInstruction(ins)); return code | 0x4000000000ULL; } +#endif //_TARGET_AMD64_ + bool isPrefix(BYTE b) { assert(b != 0); // Caller should check this @@ -401,17 +437,15 @@ bool isPrefix(BYTE b) return ((b == 0xF2) || (b == 0xF3) || (b == 0x66)); } -#endif //_TARGET_AMD64_ - // Outputs VEX prefix (in case of AVX instructions) and REX.R/X/W/B otherwise. -unsigned emitter::emitOutputRexOrVexPrefixIfNeeded(instruction ins, BYTE* dst, size_t& code) +unsigned emitter::emitOutputRexOrVexPrefixIfNeeded(instruction ins, BYTE* dst, code_t& code) { -#ifdef _TARGET_AMD64_ // TODO-x86: This needs to be enabled for AVX support on x86. +#ifdef FEATURE_AVX_SUPPORT if (hasVexPrefix(code)) { // Only AVX instructions should have a VEX prefix assert(UseAVX() && IsAVXInstruction(ins)); - size_t vexPrefix = (code >> 32) & 0x00FFFFFF; + code_t vexPrefix = (code >> 32) & 0x00FFFFFF; code &= 0x00000000FFFFFFFFLL; WORD leadingBytes = 0; @@ -504,7 +538,10 @@ unsigned emitter::emitOutputRexOrVexPrefixIfNeeded(instruction ins, BYTE* dst, s emitOutputByte(dst + 2, vexPrefix & 0xFF); return 3; } - else if (code > 0x00FFFFFFFFLL) +#endif // FEATURE_AVX_SUPPORT + +#ifdef _TARGET_AMD64_ + if (code > 0x00FFFFFFFFLL) { BYTE prefix = (code >> 32) & 0xFF; noway_assert(prefix >= 0x40 && prefix <= 0x4F); @@ -543,13 +580,13 @@ unsigned emitter::emitOutputRexOrVexPrefixIfNeeded(instruction ins, BYTE* dst, s { // 3 prefixes were rex = rr, check = c1, check2 = c2 encoded as 0xrrc1c2XXXX // Change to c2rrc1XXXX, and emit check2 now - code = (((size_t)prefix << 24) | ((size_t)check << 16) | (code & 0x0000FFFFLL)); + code = (((code_t)prefix << 24) | ((code_t)check << 16) | (code & 0x0000FFFFLL)); } else { // 2 prefixes were rex = rr, check2 = c2 encoded as 0xrrXXc2XXXX, (check is part of the opcode) // Change to c2XXrrXXXX, and emit check2 now - code = (((size_t)check << 24) | ((size_t)prefix << 16) | (code & 0x0000FFFFLL)); + code = (((code_t)check << 24) | ((code_t)prefix << 16) | (code & 0x0000FFFFLL)); } return emitOutputByte(dst, check2); } @@ -593,7 +630,6 @@ void emitter::emitOutputPreEpilogNOP() // Size of rex prefix in bytes unsigned emitter::emitGetRexPrefixSize(instruction ins) { - // In case of AVX instructions, REX prefixes are part of VEX prefix. // And hence requires no additional byte to encode REX prefixes. if (IsAVXInstruction(ins)) @@ -630,7 +666,7 @@ unsigned emitter::emitGetVexPrefixSize(instruction ins, emitAttr attr) //=(opcodeSize - ExtrabytesSize) + vexPrefixSize //=opcodeSize + (vexPrefixSize - ExtrabytesSize) //=opcodeSize + vexPrefixAdjustedSize -unsigned emitter::emitGetVexPrefixAdjustedSize(instruction ins, emitAttr attr, size_t code) +unsigned emitter::emitGetVexPrefixAdjustedSize(instruction ins, emitAttr attr, code_t code) { #ifdef FEATURE_AVX_SUPPORT if (IsAVXInstruction(ins)) @@ -674,19 +710,19 @@ unsigned emitter::emitGetVexPrefixAdjustedSize(instruction ins, emitAttr attr, s } // Get size of rex or vex prefix emitted in code -unsigned emitter::emitGetPrefixSize(size_t code) +unsigned emitter::emitGetPrefixSize(code_t code) { -#ifdef FEATURE_AVX_SUPPORT - if (code & VEX_PREFIX_MASK_3BYTE) + if (hasVexPrefix(code)) { return 3; } - else -#endif - if (code & REX_PREFIX_MASK) + +#ifdef _TARGET_AMD64_ + if (code & REX_PREFIX_MASK) { return 1; } +#endif // _TARGET_AMD64_ return 0; } @@ -1058,7 +1094,7 @@ size_t insCodesMR[] = // clang-format on // Returns true iff the give CPU instruction has an MR encoding. -inline size_t hasCodeMR(instruction ins) +inline bool hasCodeMR(instruction ins) { assert((unsigned)ins < sizeof(insCodesMR) / sizeof(insCodesMR[0])); return ((insCodesMR[ins] != BAD_CODE)); @@ -1083,7 +1119,7 @@ inline size_t insCodeMR(instruction ins) * part of an opcode. */ -inline unsigned emitter::insEncodeReg012(instruction ins, regNumber reg, emitAttr size, size_t* code) +inline unsigned emitter::insEncodeReg012(instruction ins, regNumber reg, emitAttr size, code_t* code) { assert(reg < REG_STK); @@ -1106,16 +1142,16 @@ inline unsigned emitter::insEncodeReg012(instruction ins, regNumber reg, emitAtt } #endif // _TARGET_AMD64_ - reg = RegEncoding(reg); - assert(reg < 8); - return reg; + unsigned regBits = RegEncoding(reg); #else // LEGACY_BACKEND - assert(reg < 8); - return reg; + unsigned regBits = reg; #endif // LEGACY_BACKEND + + assert(regBits < 8); + return regBits; } /***************************************************************************** @@ -1124,7 +1160,7 @@ inline unsigned emitter::insEncodeReg012(instruction ins, regNumber reg, emitAtt * part of an opcode. */ -inline unsigned emitter::insEncodeReg345(instruction ins, regNumber reg, emitAttr size, size_t* code) +inline unsigned emitter::insEncodeReg345(instruction ins, regNumber reg, emitAttr size, code_t* code) { assert(reg < REG_STK); @@ -1147,14 +1183,16 @@ inline unsigned emitter::insEncodeReg345(instruction ins, regNumber reg, emitAtt } #endif // _TARGET_AMD64_ - reg = RegEncoding(reg); - assert(reg < 8); - return (reg << 3); + unsigned regBits = RegEncoding(reg); + +#else // LEGACY_BACKEND + + unsigned regBits = reg; -#else // LEGACY_BACKEND - assert(reg < 8); - return (reg << 3); #endif // LEGACY_BACKEND + + assert(regBits < 8); + return (regBits << 3); } /*********************************************************************************** @@ -1162,7 +1200,7 @@ inline unsigned emitter::insEncodeReg345(instruction ins, regNumber reg, emitAtt * Returns modified AVX opcode with the specified register encoded in bits 3-6 of * byte 2 of VEX prefix. */ -inline size_t emitter::insEncodeReg3456(instruction ins, regNumber reg, emitAttr size, size_t code) +inline emitter::code_t emitter::insEncodeReg3456(instruction ins, regNumber reg, emitAttr size, code_t code) { #ifdef FEATURE_AVX_SUPPORT assert(reg < REG_STK); @@ -1172,7 +1210,7 @@ inline size_t emitter::insEncodeReg3456(instruction ins, regNumber reg, emitAttr // Get 4-bit register encoding // RegEncoding() gives lower 3 bits // IsExtendedReg() gives MSB. - size_t regBits = RegEncoding(reg); + code_t regBits = RegEncoding(reg); if (IsExtendedReg(reg)) { regBits |= 0x08; @@ -1196,7 +1234,7 @@ inline size_t emitter::insEncodeReg3456(instruction ins, regNumber reg, emitAttr * Used exclusively to generate the REX.X bit and truncate the register. */ -inline unsigned emitter::insEncodeRegSIB(instruction ins, regNumber reg, size_t* code) +inline unsigned emitter::insEncodeRegSIB(instruction ins, regNumber reg, code_t* code) { assert(reg < REG_STK); @@ -1210,11 +1248,13 @@ inline unsigned emitter::insEncodeRegSIB(instruction ins, regNumber reg, size_t* { *code = AddRexXPrefix(ins, *code); // REX.X } - reg = RegEncoding(reg); -#endif + unsigned regBits = RegEncoding(reg); +#else // !_TARGET_AMD64_ + unsigned regBits = reg; +#endif // !_TARGET_AMD64_ - assert(reg < 8); - return reg; + assert(regBits < 8); + return regBits; } /***************************************************************************** @@ -1222,7 +1262,7 @@ inline unsigned emitter::insEncodeRegSIB(instruction ins, regNumber reg, size_t* * Returns the "[r/m]" opcode with the mod/RM field set to register. */ -inline size_t emitter::insEncodeMRreg(instruction ins, size_t code) +inline emitter::code_t emitter::insEncodeMRreg(instruction ins, code_t code) { // If Byte 4 (which is 0xFF00) is 0, that's where the RM encoding goes. // Otherwise, it will be placed after the 4 byte encoding. @@ -1237,22 +1277,10 @@ inline size_t emitter::insEncodeMRreg(instruction ins, size_t code) /***************************************************************************** * - * Returns the "[r/m], icon" opcode with the mod/RM field set to register. - */ - -inline size_t insEncodeMIreg(instruction ins, size_t code) -{ - assert((code & 0xC000) == 0); - code |= 0xC000; - return code; -} - -/***************************************************************************** - * * Returns the given "[r/m]" opcode with the mod/RM field set to register. */ -inline size_t insEncodeRMreg(instruction ins, size_t code) +inline emitter::code_t emitter::insEncodeRMreg(instruction ins, code_t code) { // If Byte 4 (which is 0xFF00) is 0, that's where the RM encoding goes. // Otherwise, it will be placed after the 4 byte encoding. @@ -1270,7 +1298,7 @@ inline size_t insEncodeRMreg(instruction ins, size_t code) * the given register. */ -inline size_t emitter::insEncodeMRreg(instruction ins, regNumber reg, emitAttr size, size_t code) +inline emitter::code_t emitter::insEncodeMRreg(instruction ins, regNumber reg, emitAttr size, code_t code) { assert((code & 0xC000) == 0); code |= 0xC000; @@ -1285,7 +1313,7 @@ inline size_t emitter::insEncodeMRreg(instruction ins, regNumber reg, emitAttr s * the given register. */ -inline size_t emitter::insEncodeMIreg(instruction ins, regNumber reg, emitAttr size, size_t code) +inline emitter::code_t emitter::insEncodeMIreg(instruction ins, regNumber reg, emitAttr size, code_t code) { assert((code & 0xC000) == 0); code |= 0xC000; @@ -1310,12 +1338,12 @@ inline bool insNeedsRRIb(instruction ins) * Returns the "reg,reg,imm8" opcode with both the reg's set to the * the given register. */ -inline size_t emitter::insEncodeRRIb(instruction ins, regNumber reg, emitAttr size) +inline emitter::code_t emitter::insEncodeRRIb(instruction ins, regNumber reg, emitAttr size) { assert(size == EA_4BYTE); // All we handle for now. assert(insNeedsRRIb(ins)); // If this list gets longer, use a switch, or a table lookup. - size_t code = 0x69c0; + code_t code = 0x69c0; unsigned regcode = insEncodeReg012(ins, reg, size, &code); // We use the same register as source and destination. (Could have another version that does both regs...) code |= regcode; @@ -1329,9 +1357,9 @@ inline size_t emitter::insEncodeRRIb(instruction ins, regNumber reg, emitAttr si * nibble of the opcode */ -inline size_t emitter::insEncodeOpreg(instruction ins, regNumber reg, emitAttr size) +inline emitter::code_t emitter::insEncodeOpreg(instruction ins, regNumber reg, emitAttr size) { - size_t code = insCodeRR(ins); + code_t code = insCodeRR(ins); unsigned regcode = insEncodeReg012(ins, reg, size, &code); code |= regcode; return code; @@ -1342,7 +1370,7 @@ inline size_t emitter::insEncodeOpreg(instruction ins, regNumber reg, emitAttr s * Return the 'SS' field value for the given index scale factor. */ -inline unsigned insSSval(unsigned scale) +inline unsigned emitter::insSSval(unsigned scale) { assert(scale == 1 || scale == 2 || scale == 4 || scale == 8); @@ -1447,7 +1475,7 @@ bool emitter::emitVerifyEncodable(instruction ins, emitAttr size, regNumber reg1 * Estimate the size (in bytes of generated code) of the given instruction. */ -inline UNATIVE_OFFSET emitter::emitInsSize(size_t code) +inline UNATIVE_OFFSET emitter::emitInsSize(code_t code) { UNATIVE_OFFSET size = (code & 0xFF000000) ? 4 : (code & 0x00FF0000) ? 3 : 2; #ifdef _TARGET_AMD64_ @@ -1466,18 +1494,17 @@ inline UNATIVE_OFFSET emitter::emitInsSizeRR(instruction ins, regNumber reg1, re emitAttr size = EA_SIZE(attr); UNATIVE_OFFSET sz; -#ifdef _TARGET_AMD64_ - // If Byte 4 (which is 0xFF00) is non-zero, that's where the RM encoding goes. + + // If Byte 4 (which is 0xFF00) is zero, that's where the RM encoding goes. // Otherwise, it will be placed after the 4 byte encoding, making the total 5 bytes. // This would probably be better expressed as a different format or something? - if (insCodeRM(ins) & 0xFF00) + if ((insCodeRM(ins) & 0xFF00) != 0) { sz = 5; } else -#endif // _TARGET_AMD64_ { - size_t code = insCodeRM(ins); + code_t code = insCodeRM(ins); sz = emitInsSize(insEncodeRMreg(ins, code)); } @@ -1502,7 +1529,7 @@ inline UNATIVE_OFFSET emitter::emitInsSizeRR(instruction ins, regNumber reg1, re /*****************************************************************************/ -inline UNATIVE_OFFSET emitter::emitInsSizeSV(size_t code, int var, int dsp) +inline UNATIVE_OFFSET emitter::emitInsSizeSV(code_t code, int var, int dsp) { UNATIVE_OFFSET size = emitInsSize(code); UNATIVE_OFFSET offs; @@ -1777,7 +1804,7 @@ static bool baseRegisterRequiresDisplacement(regNumber base) #endif } -UNATIVE_OFFSET emitter::emitInsSizeAM(instrDesc* id, size_t code) +UNATIVE_OFFSET emitter::emitInsSizeAM(instrDesc* id, code_t code) { emitAttr attrSize = id->idOpSize(); instruction ins = id->idIns(); @@ -1994,7 +2021,7 @@ UNATIVE_OFFSET emitter::emitInsSizeAM(instrDesc* id, size_t code) return size; } -inline UNATIVE_OFFSET emitter::emitInsSizeAM(instrDesc* id, size_t code, int val) +inline UNATIVE_OFFSET emitter::emitInsSizeAM(instrDesc* id, code_t code, int val) { instruction ins = id->idIns(); UNATIVE_OFFSET valSize = EA_SIZE_IN_BYTES(id->idOpSize()); @@ -2027,7 +2054,7 @@ inline UNATIVE_OFFSET emitter::emitInsSizeAM(instrDesc* id, size_t code, int val return valSize + emitInsSizeAM(id, code); } -inline UNATIVE_OFFSET emitter::emitInsSizeCV(instrDesc* id, size_t code) +inline UNATIVE_OFFSET emitter::emitInsSizeCV(instrDesc* id, code_t code) { instruction ins = id->idIns(); @@ -2047,7 +2074,7 @@ inline UNATIVE_OFFSET emitter::emitInsSizeCV(instrDesc* id, size_t code) return size + emitInsSize(code); } -inline UNATIVE_OFFSET emitter::emitInsSizeCV(instrDesc* id, size_t code, int val) +inline UNATIVE_OFFSET emitter::emitInsSizeCV(instrDesc* id, code_t code, int val) { instruction ins = id->idIns(); UNATIVE_OFFSET valSize = EA_SIZE_IN_BYTES(id->idOpSize()); @@ -2252,7 +2279,7 @@ void emitter::emitIns(instruction ins) { UNATIVE_OFFSET sz; instrDesc* id = emitNewInstr(); - size_t code = insCodeMR(ins); + code_t code = insCodeMR(ins); #ifdef DEBUG #if FEATURE_STACK_FP_X87 @@ -2328,7 +2355,7 @@ void emitter::emitIns(instruction ins, emitAttr attr) { UNATIVE_OFFSET sz; instrDesc* id = emitNewInstr(attr); - size_t code = insCodeMR(ins); + code_t code = insCodeMR(ins); assert(ins == INS_cdq); assert((code & 0xFFFFFF00) == 0); sz = 1; @@ -2499,8 +2526,9 @@ void emitter::emitHandleMemOp(GenTreeIndir* indir, instrDesc* id, insFormat fmt, // Absolute addresses marked as contained should fit within the base of addr mode. assert(memBase->AsIntConCommon()->FitsInAddrBase(emitComp)); - // Either not generating relocatable code or addr must be an icon handle - assert(!emitComp->opts.compReloc || memBase->IsIconHandle()); + // Either not generating relocatable code, or addr must be an icon handle, or the + // constant is zero (which we won't generate a relocation for). + assert(!emitComp->opts.compReloc || memBase->IsIconHandle() || memBase->IsIntegralConst(0)); if (memBase->AsIntConCommon()->AddrNeedsReloc(emitComp)) { @@ -2904,6 +2932,19 @@ regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, G varNum = tmpDsc->tdTempNum(); offset = 0; } + else + { + // At this point we must have a memory operand that is a contained indir: if we do not, we should have handled + // this instruction above in the reg/imm or reg/reg case. + assert(mem != nullptr); + assert(memBase != nullptr); + + if (memBase->OperGet() == GT_LCL_VAR_ADDR) + { + varNum = memBase->AsLclVarCommon()->GetLclNum(); + offset = 0; + } + } // Spill temp numbers are negative and start with -1 // which also happens to be BAD_VAR_NUM. For this reason @@ -2911,7 +2952,7 @@ regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, G if (varNum != BAD_VAR_NUM || tmpDsc != nullptr) { // Is the memory op in the source position? - if (src->isContainedLclField() || src->isContainedLclVar() || src->isContainedSpillTemp()) + if (src->isContainedMemoryOp()) { if (instrHasImplicitRegPairDest(ins)) { @@ -3351,22 +3392,7 @@ void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg) dispIns(id); emitCurIGsize += sz; -#if !FEATURE_FIXED_OUT_ARGS - - if (ins == INS_push) - { - emitCurStackLvl += emitCntStackDepth; - - if (emitMaxStackDepth < emitCurStackLvl) - emitMaxStackDepth = emitCurStackLvl; - } - else if (ins == INS_pop) - { - emitCurStackLvl -= emitCntStackDepth; - assert((int)emitCurStackLvl >= 0); - } - -#endif // !FEATURE_FIXED_OUT_ARGS + emitAdjustStackDepthPushPop(ins); } /***************************************************************************** @@ -3484,7 +3510,7 @@ void emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t sz += emitGetRexPrefixSize(ins); } -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && defined(LEGACY_BACKEND) assert(reg < 8); #endif @@ -3504,34 +3530,10 @@ void emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t dispIns(id); emitCurIGsize += sz; -#if !FEATURE_FIXED_OUT_ARGS - if (reg == REG_ESP) { - if (emitCntStackDepth) - { - if (ins == INS_sub) - { - S_UINT32 newStackLvl(emitCurStackLvl); - newStackLvl += S_UINT32(val); - noway_assert(!newStackLvl.IsOverflow()); - - emitCurStackLvl = newStackLvl.Value(); - - if (emitMaxStackDepth < emitCurStackLvl) - emitMaxStackDepth = emitCurStackLvl; - } - else if (ins == INS_add) - { - S_UINT32 newStackLvl = S_UINT32(emitCurStackLvl) - S_UINT32(val); - noway_assert(!newStackLvl.IsOverflow()); - - emitCurStackLvl = newStackLvl.Value(); - } - } + emitAdjustStackDepth(ins, val); } - -#endif // !FEATURE_FIXED_OUT_ARGS } /***************************************************************************** @@ -3584,17 +3586,7 @@ void emitter::emitIns_I(instruction ins, emitAttr attr, int val) dispIns(id); emitCurIGsize += sz; -#if !FEATURE_FIXED_OUT_ARGS - - if (ins == INS_push) - { - emitCurStackLvl += emitCntStackDepth; - - if (emitMaxStackDepth < emitCurStackLvl) - emitMaxStackDepth = emitCurStackLvl; - } - -#endif // !FEATURE_FIXED_OUT_ARGS + emitAdjustStackDepthPushPop(ins); } /***************************************************************************** @@ -3693,22 +3685,7 @@ void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fld dispIns(id); emitCurIGsize += sz; -#if !FEATURE_FIXED_OUT_ARGS - - if (ins == INS_push) - { - emitCurStackLvl += emitCntStackDepth; - - if (emitMaxStackDepth < emitCurStackLvl) - emitMaxStackDepth = emitCurStackLvl; - } - else if (ins == INS_pop) - { - emitCurStackLvl -= emitCntStackDepth; - assert((int)emitCurStackLvl >= 0); - } - -#endif // !FEATURE_FIXED_OUT_ARGS + emitAdjustStackDepthPushPop(ins); } /***************************************************************************** @@ -3757,11 +3734,14 @@ void emitter::emitIns_R_R(instruction ins, emitAttr attr, regNumber reg1, regNum void emitter::emitIns_R_R_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int ival) { - // SSE2 version requires 5 bytes and AVX version 6 bytes + // SSE2 version requires 5 bytes and SSE4/AVX version 6 bytes UNATIVE_OFFSET sz = 4; if (IsSSEOrAVXInstruction(ins)) { - sz = UseAVX() ? 6 : 5; + // AVX: 3 byte VEX prefix + 1 byte opcode + 1 byte ModR/M + 1 byte immediate + // SSE4: 4 byte opcode + 1 byte ModR/M + 1 byte immediate + // SSE2: 3 byte opcode + 1 byte ModR/M + 1 byte immediate + sz = (UseAVX() || UseSSE3_4()) ? 6 : 5; } #ifdef _TARGET_AMD64_ @@ -4014,7 +3994,7 @@ void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE f id->idIns(ins); id->idInsFmt(fmt); - size_t code = insCodeMI(ins); + code_t code = insCodeMI(ins); UNATIVE_OFFSET sz = emitInsSizeCV(id, code, val); #ifdef _TARGET_AMD64_ @@ -4387,22 +4367,7 @@ void emitter::emitIns_AR_R( dispIns(id); emitCurIGsize += sz; -#if !FEATURE_FIXED_OUT_ARGS - - if (ins == INS_push) - { - emitCurStackLvl += emitCntStackDepth; - - if (emitMaxStackDepth < emitCurStackLvl) - emitMaxStackDepth = emitCurStackLvl; - } - else if (ins == INS_pop) - { - emitCurStackLvl -= emitCntStackDepth; - assert((int)emitCurStackLvl >= 0); - } - -#endif // !FEATURE_FIXED_OUT_ARGS + emitAdjustStackDepthPushPop(ins); } void emitter::emitIns_AI_R(instruction ins, emitAttr attr, regNumber ireg, ssize_t disp) @@ -4443,22 +4408,7 @@ void emitter::emitIns_AI_R(instruction ins, emitAttr attr, regNumber ireg, ssize dispIns(id); emitCurIGsize += sz; -#if !FEATURE_FIXED_OUT_ARGS - - if (ins == INS_push) - { - emitCurStackLvl += emitCntStackDepth; - - if (emitMaxStackDepth < emitCurStackLvl) - emitMaxStackDepth = emitCurStackLvl; - } - else if (ins == INS_pop) - { - emitCurStackLvl -= emitCntStackDepth; - assert((int)emitCurStackLvl >= 0); - } - -#endif // !FEATURE_FIXED_OUT_ARGS + emitAdjustStackDepthPushPop(ins); } void emitter::emitIns_I_ARR(instruction ins, emitAttr attr, int val, regNumber reg, regNumber rg2, int disp) @@ -4575,22 +4525,7 @@ void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regN dispIns(id); emitCurIGsize += sz; -#if !FEATURE_FIXED_OUT_ARGS - - if (ins == INS_push) - { - emitCurStackLvl += emitCntStackDepth; - - if (emitMaxStackDepth < emitCurStackLvl) - emitMaxStackDepth = emitCurStackLvl; - } - else if (ins == INS_pop) - { - emitCurStackLvl -= emitCntStackDepth; - assert((int)emitCurStackLvl >= 0); - } - -#endif // !FEATURE_FIXED_OUT_ARGS + emitAdjustStackDepthPushPop(ins); } void emitter::emitIns_I_ARX( @@ -4711,22 +4646,7 @@ void emitter::emitIns_ARX_R( dispIns(id); emitCurIGsize += sz; -#if !FEATURE_FIXED_OUT_ARGS - - if (ins == INS_push) - { - emitCurStackLvl += emitCntStackDepth; - - if (emitMaxStackDepth < emitCurStackLvl) - emitMaxStackDepth = emitCurStackLvl; - } - else if (ins == INS_pop) - { - emitCurStackLvl -= emitCntStackDepth; - assert((int)emitCurStackLvl >= 0); - } - -#endif // !FEATURE_FIXED_OUT_ARGS + emitAdjustStackDepthPushPop(ins); } void emitter::emitIns_I_AX(instruction ins, emitAttr attr, int val, regNumber reg, unsigned mul, int disp) @@ -4842,22 +4762,7 @@ void emitter::emitIns_AX_R(instruction ins, emitAttr attr, regNumber ireg, regNu dispIns(id); emitCurIGsize += sz; -#if !FEATURE_FIXED_OUT_ARGS - - if (ins == INS_push) - { - emitCurStackLvl += emitCntStackDepth; - - if (emitMaxStackDepth < emitCurStackLvl) - emitMaxStackDepth = emitCurStackLvl; - } - else if (ins == INS_pop) - { - emitCurStackLvl -= emitCntStackDepth; - assert((int)emitCurStackLvl >= 0); - } - -#endif // !FEATURE_FIXED_OUT_ARGS + emitAdjustStackDepthPushPop(ins); } /***************************************************************************** @@ -4901,22 +4806,7 @@ void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs) dispIns(id); emitCurIGsize += sz; -#if !FEATURE_FIXED_OUT_ARGS - - if (ins == INS_push) - { - emitCurStackLvl += emitCntStackDepth; - - if (emitMaxStackDepth < emitCurStackLvl) - emitMaxStackDepth = emitCurStackLvl; - } - else if (ins == INS_pop) - { - emitCurStackLvl -= emitCntStackDepth; - assert((int)emitCurStackLvl >= 0); - } - -#endif // !FEATURE_FIXED_OUT_ARGS + emitAdjustStackDepthPushPop(ins); } void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber ireg, int varx, int offs) @@ -5197,8 +5087,23 @@ void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount /* = 0 dispIns(id); emitCurIGsize += sz; + emitAdjustStackDepthPushPop(ins); +} + #if !FEATURE_FIXED_OUT_ARGS +//------------------------------------------------------------------------ +// emitAdjustStackDepthPushPop: Adjust the current and maximum stack depth. +// +// Arguments: +// ins - the instruction. Only INS_push and INS_pop adjust the stack depth. +// +// Notes: +// 1. Alters emitCurStackLvl and possibly emitMaxStackDepth. +// 2. emitCntStackDepth must be set (0 in prolog/epilog, one DWORD elsewhere) +// +void emitter::emitAdjustStackDepthPushPop(instruction ins) +{ if (ins == INS_push) { emitCurStackLvl += emitCntStackDepth; @@ -5206,10 +5111,53 @@ void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount /* = 0 if (emitMaxStackDepth < emitCurStackLvl) emitMaxStackDepth = emitCurStackLvl; } + else if (ins == INS_pop) + { + emitCurStackLvl -= emitCntStackDepth; + assert((int)emitCurStackLvl >= 0); + } +} -#endif // !FEATURE_FIXED_OUT_ARGS +//------------------------------------------------------------------------ +// emitAdjustStackDepth: Adjust the current and maximum stack depth. +// +// Arguments: +// ins - the instruction. Only INS_add and INS_sub adjust the stack depth. +// It is assumed that the add/sub is on the stack pointer. +// val - the number of bytes to add to or subtract from the stack pointer. +// +// Notes: +// 1. Alters emitCurStackLvl and possibly emitMaxStackDepth. +// 2. emitCntStackDepth must be set (0 in prolog/epilog, one DWORD elsewhere) +// +void emitter::emitAdjustStackDepth(instruction ins, ssize_t val) +{ + // If we're in the prolog or epilog, or otherwise not tracking the stack depth, just return. + if (emitCntStackDepth == 0) + return; + + if (ins == INS_sub) + { + S_UINT32 newStackLvl(emitCurStackLvl); + newStackLvl += S_UINT32(val); + noway_assert(!newStackLvl.IsOverflow()); + + emitCurStackLvl = newStackLvl.Value(); + + if (emitMaxStackDepth < emitCurStackLvl) + emitMaxStackDepth = emitCurStackLvl; + } + else if (ins == INS_add) + { + S_UINT32 newStackLvl = S_UINT32(emitCurStackLvl) - S_UINT32(val); + noway_assert(!newStackLvl.IsOverflow()); + + emitCurStackLvl = newStackLvl.Value(); + } } +#endif // EMIT_TRACK_STACK_DEPTH + /***************************************************************************** * * Add a call instruction (direct or indirect). @@ -5393,13 +5341,11 @@ void emitter::emitIns_Call(EmitCallType callType, assert(argSize % sizeof(void*) == 0); argCnt = (int)(argSize / (ssize_t)sizeof(void*)); // we need a signed-divide -#ifdef DEBUGGING_SUPPORT /* Managed RetVal: emit sequence point for the call */ if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET) { codeGen->genIPmappingAdd(ilOffset, false); } -#endif /* We need to allocate the appropriate instruction descriptor based @@ -5793,9 +5739,18 @@ const char* emitter::emitRegName(regNumber reg, emitAttr attr, bool varName) return emitXMMregName(reg); case EA_8BYTE: + if ((REG_XMM0 <= reg) && (reg <= REG_XMM15)) + { + return emitXMMregName(reg); + } break; case EA_4BYTE: + if ((REG_XMM0 <= reg) && (reg <= REG_XMM15)) + { + return emitXMMregName(reg); + } + if (reg > REG_R15) { break; @@ -5880,10 +5835,24 @@ const char* emitter::emitRegName(regNumber reg, emitAttr attr, bool varName) case EA_16BYTE: return emitXMMregName(reg); -#endif // LEGACY_BACKEND + case EA_8BYTE: + if ((REG_XMM0 <= reg) && (reg <= REG_XMM7)) + { + return emitXMMregName(reg); + } + break; + + case EA_4BYTE: + if ((REG_XMM0 <= reg) && (reg <= REG_XMM7)) + { + return emitXMMregName(reg); + } + break; +#else // LEGACY_BACKEND case EA_4BYTE: break; +#endif // LEGACY_BACKEND case EA_2BYTE: rn++; @@ -6661,9 +6630,9 @@ void emitter::emitDispIns( printf(" %-9s", sstr); } #ifndef FEATURE_PAL - if (strnlen_s(sstr, 10) > 8) + if (strnlen_s(sstr, 10) >= 8) #else // FEATURE_PAL - if (strnlen(sstr, 10) > 8) + if (strnlen(sstr, 10) >= 8) #endif // FEATURE_PAL { printf(" "); @@ -6808,17 +6777,8 @@ void emitter::emitDispIns( case IF_RRD_ARD: case IF_RWR_ARD: case IF_RRW_ARD: - if (IsAVXInstruction(ins)) - { - printf("%s, %s", emitYMMregName((unsigned)id->idReg1()), sstr); - } - else if (IsSSE2Instruction(ins)) - { - printf("%s, %s", emitXMMregName((unsigned)id->idReg1()), sstr); - } - else #ifdef _TARGET_AMD64_ - if (ins == INS_movsxd) + if (ins == INS_movsxd) { printf("%s, %s", emitRegName(id->idReg1(), EA_8BYTE), sstr); } @@ -6841,18 +6801,7 @@ void emitter::emitDispIns( printf("%s", sstr); emitDispAddrMode(id); - if (IsAVXInstruction(ins)) - { - printf(", %s", emitYMMregName((unsigned)id->idReg1())); - } - else if (IsSSE2Instruction(ins)) - { - printf(", %s", emitXMMregName((unsigned)id->idReg1())); - } - else - { - printf(", %s", emitRegName(id->idReg1(), attr)); - } + printf(", %s", emitRegName(id->idReg1(), attr)); break; case IF_ARD_CNS: @@ -6930,18 +6879,7 @@ void emitter::emitDispIns( emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(), id->idDebugOnlyInfo()->idVarRefOffs, asmfm); - if (IsAVXInstruction(ins)) - { - printf(", %s", emitYMMregName((unsigned)id->idReg1())); - } - else if (IsSSE2Instruction(ins)) - { - printf(", %s", emitXMMregName((unsigned)id->idReg1())); - } - else - { - printf(", %s", emitRegName(id->idReg1(), attr)); - } + printf(", %s", emitRegName(id->idReg1(), attr)); break; case IF_SRD_CNS: @@ -6983,17 +6921,8 @@ void emitter::emitDispIns( case IF_RRD_SRD: case IF_RWR_SRD: case IF_RRW_SRD: - if (IsAVXInstruction(ins)) - { - printf("%s, %s", emitYMMregName((unsigned)id->idReg1()), sstr); - } - else if (IsSSE2Instruction(ins)) - { - printf("%s, %s", emitXMMregName((unsigned)id->idReg1()), sstr); - } - else #ifdef _TARGET_AMD64_ - if (ins == INS_movsxd) + if (ins == INS_movsxd) { printf("%s, %s", emitRegName(id->idReg1(), EA_8BYTE), sstr); } @@ -7016,36 +6945,31 @@ void emitter::emitDispIns( case IF_RRD_RRD: case IF_RWR_RRD: case IF_RRW_RRD: - if (ins == INS_mov_i2xmm) { - printf("%s, %s", emitXMMregName((unsigned)id->idReg1()), emitRegName(id->idReg2(), attr)); + printf("%s, %s", emitRegName(id->idReg1(), EA_16BYTE), emitRegName(id->idReg2(), attr)); } else if (ins == INS_mov_xmm2i) { - printf("%s, %s", emitRegName(id->idReg2(), attr), emitXMMregName((unsigned)id->idReg1())); + printf("%s, %s", emitRegName(id->idReg2(), attr), emitRegName(id->idReg1(), EA_16BYTE)); + } + else if (ins == INS_pmovmskb) + { + printf("%s, %s", emitRegName(id->idReg1(), EA_4BYTE), emitRegName(id->idReg2(), attr)); } #ifndef LEGACY_BACKEND else if ((ins == INS_cvtsi2ss) || (ins == INS_cvtsi2sd)) { - printf(" %s, %s", emitXMMregName((unsigned)id->idReg1()), emitRegName(id->idReg2(), attr)); + printf(" %s, %s", emitRegName(id->idReg1(), EA_16BYTE), emitRegName(id->idReg2(), attr)); } #endif else if ((ins == INS_cvttsd2si) #ifndef LEGACY_BACKEND || (ins == INS_cvtss2si) || (ins == INS_cvtsd2si) || (ins == INS_cvttss2si) #endif - ) - { - printf(" %s, %s", emitRegName(id->idReg1(), attr), emitXMMregName((unsigned)id->idReg2())); - } - else if (IsAVXInstruction(ins)) - { - printf("%s, %s", emitYMMregName((unsigned)id->idReg1()), emitYMMregName((unsigned)id->idReg2())); - } - else if (IsSSE2Instruction(ins)) + || 0) { - printf("%s, %s", emitXMMregName((unsigned)id->idReg1()), emitXMMregName((unsigned)id->idReg2())); + printf(" %s, %s", emitRegName(id->idReg1(), attr), emitRegName(id->idReg2(), EA_16BYTE)); } #ifdef _TARGET_AMD64_ else if (ins == INS_movsxd) @@ -7079,16 +7003,8 @@ void emitter::emitDispIns( break; #endif case IF_RRW_RRW_CNS: - if (IsAVXInstruction(ins)) - { - printf("%s,", emitYMMregName((unsigned)id->idReg1()), attr); - printf(" %s", emitYMMregName((unsigned)id->idReg2()), attr); - } - else - { - printf("%s,", emitRegName(id->idReg1(), attr)); - printf(" %s", emitRegName(id->idReg2(), attr)); - } + printf("%s,", emitRegName(id->idReg1(), attr)); + printf(" %s", emitRegName(id->idReg2(), attr)); val = emitGetInsSC(id); #ifdef _TARGET_AMD64_ // no 8-byte immediates allowed here! @@ -7133,18 +7049,7 @@ void emitter::emitDispIns( attr = EA_PTRSIZE; } #endif - if (IsAVXInstruction(ins)) - { - printf("%s, %s", emitYMMregName((unsigned)id->idReg1()), sstr); - } - else if (IsSSE2Instruction(ins)) - { - printf("%s, %s", emitXMMregName((unsigned)id->idReg1()), sstr); - } - else - { - printf("%s, %s", emitRegName(id->idReg1(), attr), sstr); - } + printf("%s, %s", emitRegName(id->idReg1(), attr), sstr); offs = emitGetInsDsp(id); emitDispClsVar(id->idAddr()->iiaFieldHnd, offs, ID_INFO_DSP_RELOC); break; @@ -7521,7 +7426,7 @@ static BYTE* emitOutputNOP(BYTE* dst, size_t nBytes) * Output an instruction involving an address mode. */ -BYTE* emitter::emitOutputAM(BYTE* dst, instrDesc* id, size_t code, CnsVal* addc) +BYTE* emitter::emitOutputAM(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc) { regNumber reg; regNumber rgx; @@ -7543,7 +7448,7 @@ BYTE* emitter::emitOutputAM(BYTE* dst, instrDesc* id, size_t code, CnsVal* addc) // Special case: call via a register if (id->idIsCallRegPtr()) { - size_t opcode = insEncodeMRreg(INS_call, reg, EA_PTRSIZE, insCodeMR(INS_call)); + code_t opcode = insEncodeMRreg(INS_call, reg, EA_PTRSIZE, insCodeMR(INS_call)); dst += emitOutputRexOrVexPrefixIfNeeded(ins, dst, opcode); dst += emitOutputWord(dst, opcode); @@ -7559,13 +7464,15 @@ BYTE* emitter::emitOutputAM(BYTE* dst, instrDesc* id, size_t code, CnsVal* addc) if (IsExtendedReg(reg, EA_PTRSIZE)) { insEncodeReg012(ins, reg, EA_PTRSIZE, &code); - reg = RegEncoding(reg); + // TODO-Cleanup: stop casting RegEncoding() back to a regNumber. + reg = (regNumber)RegEncoding(reg); } if (IsExtendedReg(rgx, EA_PTRSIZE)) { insEncodeRegSIB(ins, rgx, &code); - rgx = RegEncoding(rgx); + // TODO-Cleanup: stop casting RegEncoding() back to a regNumber. + rgx = (regNumber)RegEncoding(rgx); } // And emit the REX prefix @@ -7605,7 +7512,7 @@ BYTE* emitter::emitOutputAM(BYTE* dst, instrDesc* id, size_t code, CnsVal* addc) // For this format, moves do not support a third operand, so we only need to handle the binary ops. if (IsThreeOperandBinaryAVXInstruction(ins)) { - // Encode source operand reg in 'vvvv' bits in 1's compliement form + // Encode source operand reg in 'vvvv' bits in 1's complement form // The order of operands are reversed, therefore use reg2 as the source. code = insEncodeReg3456(ins, id->idReg1(), size, code); } @@ -7619,13 +7526,15 @@ BYTE* emitter::emitOutputAM(BYTE* dst, instrDesc* id, size_t code, CnsVal* addc) if (IsExtendedReg(reg, EA_PTRSIZE)) { insEncodeReg012(ins, reg, EA_PTRSIZE, &code); - reg = RegEncoding(reg); + // TODO-Cleanup: stop casting RegEncoding() back to a regNumber. + reg = (regNumber)RegEncoding(reg); } if (IsExtendedReg(rgx, EA_PTRSIZE)) { insEncodeRegSIB(ins, rgx, &code); - rgx = RegEncoding(rgx); + // TODO-Cleanup: stop casting RegEncoding() back to a regNumber. + rgx = (regNumber)RegEncoding(rgx); } // Is this a 'big' opcode? @@ -8185,7 +8094,7 @@ DONE: * Output an instruction involving a stack frame value. */ -BYTE* emitter::emitOutputSV(BYTE* dst, instrDesc* id, size_t code, CnsVal* addc) +BYTE* emitter::emitOutputSV(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc) { int adr; int dsp; @@ -8234,7 +8143,7 @@ BYTE* emitter::emitOutputSV(BYTE* dst, instrDesc* id, size_t code, CnsVal* addc) // Special case emitting AVX instructions if (Is4ByteAVXInstruction(ins)) { - size_t regcode = insEncodeReg345(ins, id->idReg1(), size, &code); + unsigned regcode = insEncodeReg345(ins, id->idReg1(), size, &code); dst += emitOutputRexOrVexPrefixIfNeeded(ins, dst, code); // Emit last opcode byte @@ -8581,7 +8490,7 @@ BYTE* emitter::emitOutputSV(BYTE* dst, instrDesc* id, size_t code, CnsVal* addc) * Output an instruction with a static data member (class variable). */ -BYTE* emitter::emitOutputCV(BYTE* dst, instrDesc* id, size_t code, CnsVal* addc) +BYTE* emitter::emitOutputCV(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc) { BYTE* addr; CORINFO_FIELD_HANDLE fldh; @@ -8646,20 +8555,18 @@ BYTE* emitter::emitOutputCV(BYTE* dst, instrDesc* id, size_t code, CnsVal* addc) { case IF_RWR_MRD: - assert((unsigned)code == - (insCodeRM(ins) | (insEncodeReg345(ins, REG_EAX, EA_PTRSIZE, NULL) << 8) | 0x0500)); + assert(code == (insCodeRM(ins) | (insEncodeReg345(ins, REG_EAX, EA_PTRSIZE, NULL) << 8) | 0x0500)); - code &= ~((size_t)0xFFFFFFFF); + code &= ~((code_t)0xFFFFFFFF); code |= 0xA0; isMoffset = true; break; case IF_MWR_RRD: - assert((unsigned)code == - (insCodeMR(ins) | (insEncodeReg345(ins, REG_EAX, EA_PTRSIZE, NULL) << 8) | 0x0500)); + assert(code == (insCodeMR(ins) | (insEncodeReg345(ins, REG_EAX, EA_PTRSIZE, NULL) << 8) | 0x0500)); - code &= ~((size_t)0xFFFFFFFF); + code &= ~((code_t)0xFFFFFFFF); code |= 0xA2; isMoffset = true; break; @@ -8674,7 +8581,7 @@ BYTE* emitter::emitOutputCV(BYTE* dst, instrDesc* id, size_t code, CnsVal* addc) // Special case emitting AVX instructions if (Is4ByteAVXInstruction(ins)) { - size_t regcode = insEncodeReg345(ins, id->idReg1(), size, &code); + unsigned regcode = insEncodeReg345(ins, id->idReg1(), size, &code); dst += emitOutputRexOrVexPrefixIfNeeded(ins, dst, code); // Emit last opcode byte @@ -9017,7 +8924,7 @@ BYTE* emitter::emitOutputCV(BYTE* dst, instrDesc* id, size_t code, CnsVal* addc) BYTE* emitter::emitOutputR(BYTE* dst, instrDesc* id) { - size_t code; + code_t code; instruction ins = id->idIns(); regNumber reg = id->idReg1(); @@ -9228,7 +9135,7 @@ BYTE* emitter::emitOutputR(BYTE* dst, instrDesc* id) BYTE* emitter::emitOutputRR(BYTE* dst, instrDesc* id) { - size_t code; + code_t code; instruction ins = id->idIns(); regNumber reg1 = id->idReg1(); @@ -9238,7 +9145,7 @@ BYTE* emitter::emitOutputRR(BYTE* dst, instrDesc* id) // Get the 'base' opcode code = insCodeRM(ins); code = AddVexPrefixIfNeeded(ins, code, size); - if (IsSSE2Instruction(ins) || IsAVXInstruction(ins)) + if (IsSSEOrAVXInstruction(ins)) { code = insEncodeRMreg(ins, code); @@ -9322,12 +9229,12 @@ BYTE* emitter::emitOutputRR(BYTE* dst, instrDesc* id) // now we use the single source as source1 and source2. if (IsThreeOperandBinaryAVXInstruction(ins)) { - // encode source/dest operand reg in 'vvvv' bits in 1's compliement form + // encode source/dest operand reg in 'vvvv' bits in 1's complement form code = insEncodeReg3456(ins, reg1, size, code); } else if (IsThreeOperandMoveAVXInstruction(ins)) { - // encode source operand reg in 'vvvv' bits in 1's compliement form + // encode source operand reg in 'vvvv' bits in 1's complement form code = insEncodeReg3456(ins, reg2, size, code); } @@ -9340,6 +9247,13 @@ BYTE* emitter::emitOutputRR(BYTE* dst, instrDesc* id) // Output the highest word of the opcode dst += emitOutputWord(dst, code >> 16); code &= 0x0000FFFF; + + if (Is4ByteSSE4Instruction(ins)) + { + // Output 3rd byte of the opcode + dst += emitOutputByte(dst, code); + code &= 0xFF00; + } } else if (code & 0x00FF0000) { @@ -9349,13 +9263,13 @@ BYTE* emitter::emitOutputRR(BYTE* dst, instrDesc* id) // If byte 4 is 0xC0, then it contains the Mod/RM encoding for a 3-byte // encoding. Otherwise, this is an instruction with a 4-byte encoding, - // and the MOd/RM encoding needs to go in the 5th byte. + // and the Mod/RM encoding needs to go in the 5th byte. // TODO-XArch-CQ: Currently, this will only support registers in the 5th byte. // We probably need a different mechanism to identify the 4-byte encodings. if ((code & 0xFF) == 0x00) { - // This case happens for AVX instructions only - assert(IsAVXInstruction(ins)); + // This case happens for SSE4/AVX instructions only + assert(IsAVXInstruction(ins) || IsSSE4Instruction(ins)); if ((code & 0xFF00) == 0xC000) { dst += emitOutputByte(dst, (0xC0 | regCode)); @@ -9560,7 +9474,7 @@ BYTE* emitter::emitOutputRR(BYTE* dst, instrDesc* id) #ifdef FEATURE_AVX_SUPPORT BYTE* emitter::emitOutputRRR(BYTE* dst, instrDesc* id) { - size_t code; + code_t code; instruction ins = id->idIns(); assert(IsAVXInstruction(ins)); @@ -9642,7 +9556,7 @@ BYTE* emitter::emitOutputRRR(BYTE* dst, instrDesc* id) BYTE* emitter::emitOutputRI(BYTE* dst, instrDesc* id) { - size_t code; + code_t code; emitAttr size = id->idOpSize(); instruction ins = id->idIns(); regNumber reg = id->idReg1(); @@ -10004,7 +9918,7 @@ DONE: BYTE* emitter::emitOutputIV(BYTE* dst, instrDesc* id) { - size_t code; + code_t code; instruction ins = id->idIns(); emitAttr size = id->idOpSize(); ssize_t val = emitGetInsSC(id); @@ -10286,27 +10200,29 @@ BYTE* emitter::emitOutputLJ(BYTE* dst, instrDesc* i) } else { - size_t code; + code_t code; // Long jump if (jmp) { + // clang-format off assert(INS_jmp + (INS_l_jmp - INS_jmp) == INS_l_jmp); - assert(INS_jo + (INS_l_jmp - INS_jmp) == INS_l_jo); - assert(INS_jb + (INS_l_jmp - INS_jmp) == INS_l_jb); + assert(INS_jo + (INS_l_jmp - INS_jmp) == INS_l_jo); + assert(INS_jb + (INS_l_jmp - INS_jmp) == INS_l_jb); assert(INS_jae + (INS_l_jmp - INS_jmp) == INS_l_jae); - assert(INS_je + (INS_l_jmp - INS_jmp) == INS_l_je); + assert(INS_je + (INS_l_jmp - INS_jmp) == INS_l_je); assert(INS_jne + (INS_l_jmp - INS_jmp) == INS_l_jne); assert(INS_jbe + (INS_l_jmp - INS_jmp) == INS_l_jbe); - assert(INS_ja + (INS_l_jmp - INS_jmp) == INS_l_ja); - assert(INS_js + (INS_l_jmp - INS_jmp) == INS_l_js); + assert(INS_ja + (INS_l_jmp - INS_jmp) == INS_l_ja); + assert(INS_js + (INS_l_jmp - INS_jmp) == INS_l_js); assert(INS_jns + (INS_l_jmp - INS_jmp) == INS_l_jns); assert(INS_jpe + (INS_l_jmp - INS_jmp) == INS_l_jpe); assert(INS_jpo + (INS_l_jmp - INS_jmp) == INS_l_jpo); - assert(INS_jl + (INS_l_jmp - INS_jmp) == INS_l_jl); + assert(INS_jl + (INS_l_jmp - INS_jmp) == INS_l_jl); assert(INS_jge + (INS_l_jmp - INS_jmp) == INS_l_jge); assert(INS_jle + (INS_l_jmp - INS_jmp) == INS_l_jle); - assert(INS_jg + (INS_l_jmp - INS_jmp) == INS_l_jg); + assert(INS_jg + (INS_l_jmp - INS_jmp) == INS_l_jg); + // clang-format on code = insCode((instruction)(ins + (INS_l_jmp - INS_jmp))); } @@ -10452,10 +10368,10 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) // What instruction format have we got? switch (id->idInsFmt()) { - size_t code; - size_t regcode; - int args; - CnsVal cnsVal; + code_t code; + unsigned regcode; + int args; + CnsVal cnsVal; BYTE* addr; bool recCall; @@ -10792,6 +10708,10 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) dst += emitOutputWord(dst, code); dst += emitOutputByte(dst, emitGetInsSC(id)); sz = emitSizeOfInsDsc(id); + + // Update GC info. + assert(!id->idGCref()); + emitGCregDeadUpd(id->idReg1(), dst); break; case IF_RRD_RRD: @@ -10871,7 +10791,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) // Output the REX prefix dst += emitOutputRexOrVexPrefixIfNeeded(ins, dst, code); - if (UseAVX() && Is4ByteAVXInstruction(ins)) + if (Is4ByteAVXInstruction(ins)) { // We just need to output the last byte of the opcode. assert((code & 0xFF) == 0); @@ -10883,6 +10803,12 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) { dst += emitOutputWord(dst, code >> 16); code &= 0x0000FFFF; + + if (Is4ByteSSE4Instruction(ins)) + { + dst += emitOutputWord(dst, code); + code = 0; + } } else if (code & 0x00FF0000) { @@ -10898,9 +10824,9 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) } else { - // This case occurs for AVX instructions. + // This case occurs for SSE4/AVX instructions. // Note that regcode is left shifted by 8-bits. - assert(Is4ByteAVXInstruction(ins)); + assert(Is4ByteAVXInstruction(ins) || Is4ByteSSE4Instruction(ins)); dst += emitOutputByte(dst, 0xC0 | (regcode >> 8)); } diff --git a/src/jit/emitxarch.h b/src/jit/emitxarch.h index dfd7e6e..98256cd 100644 --- a/src/jit/emitxarch.h +++ b/src/jit/emitxarch.h @@ -28,6 +28,15 @@ inline static bool isDoubleReg(regNumber reg) /* Routines that compute the size of / encode instructions */ /************************************************************************/ +// code_t is a type used to accumulate bits of opcode + prefixes. On amd64, it must be 64 bits +// to support the REX prefixes. On both x86 and amd64, it must be 64 bits to support AVX, with +// its 3-byte VEX prefix. For legacy backend (which doesn't support AVX), leave it as size_t. +#if defined(LEGACY_BACKEND) +typedef size_t code_t; +#else // !defined(LEGACY_BACKEND) +typedef unsigned __int64 code_t; +#endif // !defined(LEGACY_BACKEND) + struct CnsVal { ssize_t cnsVal; @@ -36,19 +45,19 @@ struct CnsVal #endif }; -UNATIVE_OFFSET emitInsSize(size_t code); +UNATIVE_OFFSET emitInsSize(code_t code); UNATIVE_OFFSET emitInsSizeRM(instruction ins); -UNATIVE_OFFSET emitInsSizeSV(size_t code, int var, int dsp); +UNATIVE_OFFSET emitInsSizeSV(code_t code, int var, int dsp); UNATIVE_OFFSET emitInsSizeSV(instrDesc* id, int var, int dsp, int val); UNATIVE_OFFSET emitInsSizeRR(instruction ins, regNumber reg1, regNumber reg2, emitAttr attr); -UNATIVE_OFFSET emitInsSizeAM(instrDesc* id, size_t code); -UNATIVE_OFFSET emitInsSizeAM(instrDesc* id, size_t code, int val); -UNATIVE_OFFSET emitInsSizeCV(instrDesc* id, size_t code); -UNATIVE_OFFSET emitInsSizeCV(instrDesc* id, size_t code, int val); +UNATIVE_OFFSET emitInsSizeAM(instrDesc* id, code_t code); +UNATIVE_OFFSET emitInsSizeAM(instrDesc* id, code_t code, int val); +UNATIVE_OFFSET emitInsSizeCV(instrDesc* id, code_t code); +UNATIVE_OFFSET emitInsSizeCV(instrDesc* id, code_t code, int val); -BYTE* emitOutputAM(BYTE* dst, instrDesc* id, size_t code, CnsVal* addc = nullptr); -BYTE* emitOutputSV(BYTE* dst, instrDesc* id, size_t code, CnsVal* addc = nullptr); -BYTE* emitOutputCV(BYTE* dst, instrDesc* id, size_t code, CnsVal* addc = nullptr); +BYTE* emitOutputAM(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc = nullptr); +BYTE* emitOutputSV(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc = nullptr); +BYTE* emitOutputCV(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc = nullptr); BYTE* emitOutputR(BYTE* dst, instrDesc* id); BYTE* emitOutputRI(BYTE* dst, instrDesc* id); @@ -61,42 +70,60 @@ BYTE* emitOutputRRR(BYTE* dst, instrDesc* id); BYTE* emitOutputLJ(BYTE* dst, instrDesc* id); -unsigned emitOutputRexOrVexPrefixIfNeeded(instruction ins, BYTE* dst, size_t& code); +unsigned emitOutputRexOrVexPrefixIfNeeded(instruction ins, BYTE* dst, code_t& code); unsigned emitGetRexPrefixSize(instruction ins); unsigned emitGetVexPrefixSize(instruction ins, emitAttr attr); -unsigned emitGetPrefixSize(size_t code); -unsigned emitGetVexPrefixAdjustedSize(instruction ins, emitAttr attr, size_t code); +unsigned emitGetPrefixSize(code_t code); +unsigned emitGetVexPrefixAdjustedSize(instruction ins, emitAttr attr, code_t code); + +unsigned insEncodeReg012(instruction ins, regNumber reg, emitAttr size, code_t* code); +unsigned insEncodeReg345(instruction ins, regNumber reg, emitAttr size, code_t* code); +code_t insEncodeReg3456(instruction ins, regNumber reg, emitAttr size, code_t code); +unsigned insEncodeRegSIB(instruction ins, regNumber reg, code_t* code); -unsigned insEncodeReg345(instruction ins, regNumber reg, emitAttr size, size_t* code); -unsigned insEncodeReg012(instruction ins, regNumber reg, emitAttr size, size_t* code); -size_t insEncodeReg3456(instruction ins, regNumber reg, emitAttr size, size_t code); -unsigned insEncodeRegSIB(instruction ins, regNumber reg, size_t* code); +code_t insEncodeMRreg(instruction ins, code_t code); +code_t insEncodeRMreg(instruction ins, code_t code); +code_t insEncodeMRreg(instruction ins, regNumber reg, emitAttr size, code_t code); +code_t insEncodeRRIb(instruction ins, regNumber reg, emitAttr size); +code_t insEncodeOpreg(instruction ins, regNumber reg, emitAttr size); -size_t insEncodeMRreg(instruction ins, size_t code); -size_t insEncodeMRreg(instruction ins, regNumber reg, emitAttr size, size_t code); -size_t insEncodeRRIb(instruction ins, regNumber reg, emitAttr size); -size_t insEncodeOpreg(instruction ins, regNumber reg, emitAttr size); +unsigned insSSval(unsigned scale); bool IsAVXInstruction(instruction ins); -size_t insEncodeMIreg(instruction ins, regNumber reg, emitAttr size, size_t code); +code_t insEncodeMIreg(instruction ins, regNumber reg, emitAttr size, code_t code); -size_t AddRexWPrefix(instruction ins, size_t code); -size_t AddRexRPrefix(instruction ins, size_t code); -size_t AddRexXPrefix(instruction ins, size_t code); -size_t AddRexBPrefix(instruction ins, size_t code); -size_t AddRexPrefix(instruction ins, size_t code); +code_t AddRexWPrefix(instruction ins, code_t code); +code_t AddRexRPrefix(instruction ins, code_t code); +code_t AddRexXPrefix(instruction ins, code_t code); +code_t AddRexBPrefix(instruction ins, code_t code); +code_t AddRexPrefix(instruction ins, code_t code); + +bool useSSE3_4Encodings; +bool UseSSE3_4() +{ + return useSSE3_4Encodings; +} +void SetUseSSE3_4(bool value) +{ + useSSE3_4Encodings = value; +} +bool Is4ByteSSE4Instruction(instruction ins); #ifdef FEATURE_AVX_SUPPORT + // 3-byte VEX prefix starts with byte 0xC4 -#define VEX_PREFIX_MASK_3BYTE 0xC4000000000000LL +#define VEX_PREFIX_MASK_3BYTE 0xFF000000000000ULL +#define VEX_PREFIX_CODE_3BYTE 0xC4000000000000ULL + bool TakesVexPrefix(instruction ins); + // Returns true if the instruction encoding already contains VEX prefix -bool hasVexPrefix(size_t code) +bool hasVexPrefix(code_t code) { - return (code & VEX_PREFIX_MASK_3BYTE) != 0; + return (code & VEX_PREFIX_MASK_3BYTE) == VEX_PREFIX_CODE_3BYTE; } -size_t AddVexPrefix(instruction ins, size_t code, emitAttr attr); -size_t AddVexPrefixIfNeeded(instruction ins, size_t code, emitAttr size) +code_t AddVexPrefix(instruction ins, code_t code, emitAttr attr); +code_t AddVexPrefixIfNeeded(instruction ins, code_t code, emitAttr size) { if (TakesVexPrefix(ins)) { @@ -104,7 +131,7 @@ size_t AddVexPrefixIfNeeded(instruction ins, size_t code, emitAttr size) } return code; } -size_t AddVexPrefixIfNeededAndNotPresent(instruction ins, size_t code, emitAttr size) +code_t AddVexPrefixIfNeededAndNotPresent(instruction ins, code_t code, emitAttr size) { if (TakesVexPrefix(ins) && !hasVexPrefix(code)) { @@ -112,6 +139,7 @@ size_t AddVexPrefixIfNeededAndNotPresent(instruction ins, size_t code, emitAttr } return code; } + bool useAVXEncodings; bool UseAVX() { @@ -121,18 +149,20 @@ void SetUseAVX(bool value) { useAVXEncodings = value; } + bool IsThreeOperandBinaryAVXInstruction(instruction ins); bool IsThreeOperandMoveAVXInstruction(instruction ins); bool IsThreeOperandAVXInstruction(instruction ins) { return (IsThreeOperandBinaryAVXInstruction(ins) || IsThreeOperandMoveAVXInstruction(ins)); } +bool Is4ByteAVXInstruction(instruction ins); #else // !FEATURE_AVX_SUPPORT -bool UseAVX() +bool UseAVX() { return false; } -bool hasVexPrefix(size_t code) +bool hasVexPrefix(code_t code) { return false; } @@ -148,15 +178,19 @@ bool IsThreeOperandAVXInstruction(instruction ins) { return false; } +bool Is4ByteAVXInstruction(instruction ins) +{ + return false; +} bool TakesVexPrefix(instruction ins) { return false; } -size_t AddVexPrefixIfNeeded(instruction ins, size_t code, emitAttr attr) +code_t AddVexPrefixIfNeeded(instruction ins, code_t code, emitAttr attr) { return code; } -size_t AddVexPrefixIfNeededAndNotPresent(instruction ins, size_t code, emitAttr size) +code_t AddVexPrefixIfNeededAndNotPresent(instruction ins, code_t code, emitAttr size) { return code; } @@ -226,6 +260,18 @@ bool emitVerifyEncodable(instruction ins, emitAttr size, regNumber reg1, regNumb bool emitInsCanOnlyWriteSSE2OrAVXReg(instrDesc* id); +#if FEATURE_FIXED_OUT_ARGS +void emitAdjustStackDepthPushPop(instruction ins) +{ +} +void emitAdjustStackDepth(instruction ins, ssize_t val) +{ +} +#else // !FEATURE_FIXED_OUT_ARGS +void emitAdjustStackDepthPushPop(instruction ins); +void emitAdjustStackDepth(instruction ins, ssize_t val); +#endif // !FEATURE_FIXED_OUT_ARGS + /***************************************************************************** * * Convert between an index scale in bytes to a smaller encoding used for diff --git a/src/jit/error.cpp b/src/jit/error.cpp index 71c3301..f42dcef 100644 --- a/src/jit/error.cpp +++ b/src/jit/error.cpp @@ -129,7 +129,7 @@ void noWayAssertBodyConditional( } } -#if !defined(_TARGET_X86_) || !defined(LEGACY_BACKEND) +#if defined(ALT_JIT) && (!defined(_TARGET_X86_) || !defined(LEGACY_BACKEND)) /*****************************************************************************/ void notYetImplemented(const char* msg, const char* filename, unsigned line) @@ -193,7 +193,7 @@ void notYetImplemented(const char* msg, const char* filename, unsigned line) } } -#endif // #if !defined(_TARGET_X86_) || !defined(LEGACY_BACKEND) +#endif // #if defined(ALT_JIT) && (!defined(_TARGET_X86_) || !defined(LEGACY_BACKEND)) /*****************************************************************************/ LONG __JITfilter(PEXCEPTION_POINTERS pExceptionPointers, LPVOID lpvParam) diff --git a/src/jit/error.h b/src/jit/error.h index c56971a..0535601 100644 --- a/src/jit/error.h +++ b/src/jit/error.h @@ -58,10 +58,11 @@ extern LONG __JITfilter(PEXCEPTION_POINTERS pExceptionPointers, LPVOID lpvParam) /*****************************************************************************/ +// clang-format off + extern void debugError(const char* msg, const char* file, unsigned line); extern void DECLSPEC_NORETURN badCode(); -extern void DECLSPEC_NORETURN -badCode3(const char* msg, const char* msg2, int arg, __in_z const char* file, unsigned line); +extern void DECLSPEC_NORETURN badCode3(const char* msg, const char* msg2, int arg, __in_z const char* file, unsigned line); extern void DECLSPEC_NORETURN noWay(); extern void DECLSPEC_NORETURN NOMEM(); extern void DECLSPEC_NORETURN fatal(int errCode); @@ -79,120 +80,6 @@ extern void noWayAssertBodyConditional( ); extern void noWayAssertBodyConditional(const char* cond, const char* file, unsigned line); -#if !defined(_TARGET_X86_) || !defined(LEGACY_BACKEND) - -// This guy can return based on Config flag/Debugger -extern void notYetImplemented(const char* msg, const char* file, unsigned line); -#define NYI(msg) notYetImplemented("NYI: " #msg, __FILE__, __LINE__) -#define NYI_IF(cond, msg) \ - if (cond) \ - notYetImplemented("NYI: " #msg, __FILE__, __LINE__) - -#ifdef _TARGET_AMD64_ - -#define NYI_AMD64(msg) notYetImplemented("NYI_AMD64: " #msg, __FILE__, __LINE__) -#define NYI_X86(msg) \ - do \ - { \ - } while (0) -#define NYI_ARM(msg) \ - do \ - { \ - } while (0) -#define NYI_ARM64(msg) \ - do \ - { \ - } while (0) - -#elif defined(_TARGET_X86_) - -#define NYI_AMD64(msg) \ - do \ - { \ - } while (0) -#define NYI_X86(msg) notYetImplemented("NYI_X86: " #msg, __FILE__, __LINE__) -#define NYI_ARM(msg) \ - do \ - { \ - } while (0) -#define NYI_ARM64(msg) \ - do \ - { \ - } while (0) - -#elif defined(_TARGET_ARM_) - -#define NYI_AMD64(msg) \ - do \ - { \ - } while (0) -#define NYI_X86(msg) \ - do \ - { \ - } while (0) -#define NYI_ARM(msg) notYetImplemented("NYI_ARM: " #msg, __FILE__, __LINE__) -#define NYI_ARM64(msg) \ - do \ - { \ - } while (0) - -#elif defined(_TARGET_ARM64_) - -#define NYI_AMD64(msg) \ - do \ - { \ - } while (0) -#define NYI_X86(msg) \ - do \ - { \ - } while (0) -#define NYI_ARM(msg) \ - do \ - { \ - } while (0) -#define NYI_ARM64(msg) notYetImplemented("NYI_ARM64: " #msg, __FILE__, __LINE__) - -#else - -#error "Unknown platform, not x86, ARM, or AMD64?" - -#endif - -#else // defined(_TARGET_X86_) && defined(LEGACY_BACKEND) - -#define NYI(msg) assert(!msg) -#define NYI_AMD64(msg) \ - do \ - { \ - } while (0) -#define NYI_ARM(msg) \ - do \ - { \ - } while (0) -#define NYI_ARM64(msg) \ - do \ - { \ - } while (0) - -#endif // _TARGET_X86_ - -#if !defined(_TARGET_X86_) && !defined(FEATURE_STACK_FP_X87) -#define NYI_FLAT_FP_X87(msg) notYetImplemented("NYI: " #msg, __FILE__, __LINE__) -#define NYI_FLAT_FP_X87_NC(msg) notYetImplemented("NYI: " #msg, __FILE__, __LINE__) - -#else - -#define NYI_FLAT_FP_X87(msg) \ - do \ - { \ - } while (0) -#define NYI_FLAT_FP_X87_NC(msg) \ - do \ - { \ - } while (0) - -#endif // !_TARGET_X86_ && !FEATURE_STACK_FP_X87 - #ifdef DEBUG #define NO_WAY(msg) (debugError(msg, __FILE__, __LINE__), noWay()) // Used for fallback stress mode @@ -210,6 +97,8 @@ extern void notYetImplemented(const char* msg, const char* file, unsigned line); } while (0) #define unreached() noWayAssertBody("unreached", __FILE__, __LINE__) +#define NOWAY_MSG(msg) noWayAssertBodyConditional(msg, __FILE__, __LINE__) + #else #define NO_WAY(msg) noWay() @@ -232,6 +121,8 @@ extern void notYetImplemented(const char* msg, const char* file, unsigned line); } while (0) #define unreached() noWayAssertBody() +#define NOWAY_MSG(msg) noWayAssertBodyConditional(NOWAY_ASSERT_BODY_ARGUMENTS) + #endif // IMPL_LIMITATION is called when we encounter valid IL that is not @@ -239,7 +130,81 @@ extern void notYetImplemented(const char* msg, const char* file, unsigned line); // limitations (that could be removed in the future) #define IMPL_LIMITATION(msg) NO_WAY(msg) -#if defined(_HOST_X86_) +#if !defined(_TARGET_X86_) || !defined(LEGACY_BACKEND) + +#if defined(ALT_JIT) + +// This guy can return based on Config flag/Debugger +extern void notYetImplemented(const char* msg, const char* file, unsigned line); +#define NYIRAW(msg) notYetImplemented(msg, __FILE__, __LINE__) + +#else // !defined(ALT_JIT) + +#define NYIRAW(msg) NOWAY_MSG(msg) + +#endif // !defined(ALT_JIT) + +#define NYI(msg) NYIRAW("NYI: " msg) +#define NYI_IF(cond, msg) if (cond) NYIRAW("NYI: " msg) + +#ifdef _TARGET_AMD64_ + +#define NYI_AMD64(msg) NYIRAW("NYI_AMD64: " msg) +#define NYI_X86(msg) do { } while (0) +#define NYI_ARM(msg) do { } while (0) +#define NYI_ARM64(msg) do { } while (0) + +#elif defined(_TARGET_X86_) + +#define NYI_AMD64(msg) do { } while (0) +#define NYI_X86(msg) NYIRAW("NYI_X86: " msg) +#define NYI_ARM(msg) do { } while (0) +#define NYI_ARM64(msg) do { } while (0) + +#elif defined(_TARGET_ARM_) + +#define NYI_AMD64(msg) do { } while (0) +#define NYI_X86(msg) do { } while (0) +#define NYI_ARM(msg) NYIRAW("NYI_ARM: " msg) +#define NYI_ARM64(msg) do { } while (0) + +#elif defined(_TARGET_ARM64_) + +#define NYI_AMD64(msg) do { } while (0) +#define NYI_X86(msg) do { } while (0) +#define NYI_ARM(msg) do { } while (0) +#define NYI_ARM64(msg) NYIRAW("NYI_ARM64: " msg) + +#else + +#error "Unknown platform, not x86, ARM, or AMD64?" + +#endif + +#else // NYI not available; make it an assert. + +#define NYI(msg) assert(!msg) +#define NYI_AMD64(msg) do { } while (0) +#define NYI_ARM(msg) do { } while (0) +#define NYI_ARM64(msg) do { } while (0) + +#endif // NYI not available + +#if !defined(_TARGET_X86_) && !defined(FEATURE_STACK_FP_X87) + +#define NYI_FLAT_FP_X87(msg) NYI(msg) +#define NYI_FLAT_FP_X87_NC(msg) NYI(msg) + +#else + +#define NYI_FLAT_FP_X87(msg) do { } while (0) +#define NYI_FLAT_FP_X87_NC(msg) do { } while (0) + +#endif // !_TARGET_X86_ && !FEATURE_STACK_FP_X87 + +// clang-format on + +#if defined(_HOST_X86_) && !defined(FEATURE_PAL) // While debugging in an Debugger, the "int 3" will cause the program to break // Outside, the exception handler will just filter out the "int 3". diff --git a/src/jit/flowgraph.cpp b/src/jit/flowgraph.cpp index 1c68bfd..441569c 100644 --- a/src/jit/flowgraph.cpp +++ b/src/jit/flowgraph.cpp @@ -2985,8 +2985,8 @@ void Compiler::fgRemovePreds() { C_ASSERT(offsetof(BasicBlock, bbPreds) == offsetof(BasicBlock, bbCheapPreds)); // bbPreds and bbCheapPreds are at the same place in a union, - C_ASSERT(sizeof(((BasicBlock*)0)->bbPreds) == - sizeof(((BasicBlock*)0)->bbCheapPreds)); // and are the same size. So, this function removes both. + C_ASSERT(sizeof(((BasicBlock*)nullptr)->bbPreds) == + sizeof(((BasicBlock*)nullptr)->bbCheapPreds)); // and are the same size. So, this function removes both. for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext) { @@ -3890,8 +3890,7 @@ bool Compiler::fgCreateGCPoll(GCPollType pollType, BasicBlock* block) BBjumpKinds oldJumpKind = top->bbJumpKind; // Update block flags - unsigned originalFlags; - originalFlags = top->bbFlags | BBF_GC_SAFE_POINT; + const unsigned __int64 originalFlags = top->bbFlags | BBF_GC_SAFE_POINT; // Unlike Fei's inliner from puclr, I'm allowed to split loops. // And we keep a few other flags... @@ -4269,6 +4268,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* const bool isForceInline = (info.compFlags & CORINFO_FLG_FORCEINLINE) != 0; const bool makeInlineObservations = (compInlineResult != nullptr); const bool isInlining = compIsForInlining(); + unsigned retBlocks = 0; if (makeInlineObservations) { @@ -4638,6 +4638,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* break; case CEE_JMP: + retBlocks++; #if !defined(_TARGET_X86_) && !defined(_TARGET_ARM_) if (!isInlining) @@ -4730,6 +4731,8 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* fgObserveInlineConstants(opcode, pushedStack, isInlining); } break; + case CEE_RET: + retBlocks++; default: break; @@ -4758,6 +4761,27 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* { compInlineResult->Note(InlineObservation::CALLEE_END_OPCODE_SCAN); + if (!compInlineResult->UsesLegacyPolicy()) + { + // If there are no return blocks we know it does not return, however if there + // return blocks we don't know it returns as it may be counting unreachable code. + // However we will still make the CALLEE_DOES_NOT_RETURN observation. + + compInlineResult->NoteBool(InlineObservation::CALLEE_DOES_NOT_RETURN, retBlocks == 0); + + if (retBlocks == 0 && isInlining) + { + // Mark the call node as "no return" as it can impact caller's code quality. + impInlineInfo->iciCall->gtCallMoreFlags |= GTF_CALL_M_DOES_NOT_RETURN; + } + } + + // Determine if call site is within a try. + if (isInlining && impInlineInfo->iciBlock->hasTryIndex()) + { + compInlineResult->Note(InlineObservation::CALLSITE_IN_TRY_REGION); + } + // If the inline is viable and discretionary, do the // profitability screening. if (compInlineResult->IsDiscretionaryCandidate()) @@ -5062,22 +5086,23 @@ void Compiler::fgLinkBasicBlocks() /***************************************************************************** * - * Walk the instrs to create the basic blocks. + * Walk the instrs to create the basic blocks. Returns the number of BBJ_RETURN in method */ -void Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* jumpTarget) +unsigned Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* jumpTarget) { + unsigned retBlocks; const BYTE* codeBegp = codeAddr; const BYTE* codeEndp = codeAddr + codeSize; bool tailCall = false; unsigned curBBoffs; BasicBlock* curBBdesc; + retBlocks = 0; /* Clear the beginning offset for the first BB */ curBBoffs = 0; -#ifdef DEBUGGING_SUPPORT if (opts.compDbgCode && (info.compVarScopesCount > 0)) { compResetScopeLists(); @@ -5090,7 +5115,6 @@ void Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* { /* do nothing */ } } -#endif BBjumpKinds jmpKind; @@ -5280,7 +5304,8 @@ void Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* // TODO-CQ: We can inline some callees with explicit tail calls if we can guarantee that the calls // can be dispatched as tail calls from the caller. compInlineResult->NoteFatal(InlineObservation::CALLEE_EXPLICIT_TAIL_PREFIX); - return; + retBlocks++; + return retBlocks; } __fallthrough; @@ -5391,6 +5416,7 @@ void Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* But instead of directly returning to the caller we jump and execute something else in between */ case CEE_RET: + retBlocks++; jmpKind = BBJ_RETURN; break; @@ -5473,8 +5499,6 @@ void Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* nxtBBoffs = (IL_OFFSET)(codeAddr - codeBegp); -#ifdef DEBUGGING_SUPPORT - bool foundScope = false; if (opts.compDbgCode && (info.compVarScopesCount > 0)) @@ -5488,7 +5512,6 @@ void Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* foundScope = true; } } -#endif /* Do we have a jump? */ @@ -5505,7 +5528,6 @@ void Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* bool makeBlock = (jumpTarget[nxtBBoffs] != JT_NONE); -#ifdef DEBUGGING_SUPPORT if (!makeBlock && foundScope) { makeBlock = true; @@ -5516,7 +5538,6 @@ void Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* } #endif // DEBUG } -#endif // DEBUGGING_SUPPORT if (!makeBlock) { @@ -5581,6 +5602,8 @@ void Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE* /* Finally link up the bbJumpDest of the blocks together */ fgLinkBasicBlocks(); + + return retBlocks; } /***************************************************************************** @@ -5726,44 +5749,23 @@ void Compiler::fgFindBasicBlocks() /* Now create the basic blocks */ - fgMakeBasicBlocks(info.compCode, info.compILCodeSize, jumpTarget); + unsigned retBlocks = fgMakeBasicBlocks(info.compCode, info.compILCodeSize, jumpTarget); if (compIsForInlining()) { - if (compInlineResult->IsFailure()) - { - return; - } - - bool hasReturnBlocks = false; - bool hasMoreThanOneReturnBlock = false; - - for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext) - { - if (block->bbJumpKind == BBJ_RETURN) - { - if (hasReturnBlocks) - { - hasMoreThanOneReturnBlock = true; - break; - } - - hasReturnBlocks = true; - } - } - if (!hasReturnBlocks && !compInlineResult->UsesLegacyPolicy()) +#ifdef DEBUG + // If fgFindJumpTargets marked the call as "no return" there + // really should be no BBJ_RETURN blocks in the method. + // + // Note LegacyPolicy does not mark calls as no return, so if + // it's active, skip the check. + if (!compInlineResult->UsesLegacyPolicy()) { - // - // Mark the call node as "no return". The inliner might ignore CALLEE_DOES_NOT_RETURN and - // fail inline for a different reasons. In that case we still want to make the "no return" - // information available to the caller as it can impact caller's code quality. - // - - impInlineInfo->iciCall->gtCallMoreFlags |= GTF_CALL_M_DOES_NOT_RETURN; + bool markedNoReturn = (impInlineInfo->iciCall->gtCallMoreFlags & GTF_CALL_M_DOES_NOT_RETURN) != 0; + assert((markedNoReturn && (retBlocks == 0)) || (!markedNoReturn && (retBlocks >= 1))); } - - compInlineResult->NoteBool(InlineObservation::CALLEE_DOES_NOT_RETURN, !hasReturnBlocks); +#endif // DEBUG if (compInlineResult->IsFailure()) { @@ -5777,12 +5779,14 @@ void Compiler::fgFindBasicBlocks() compHndBBtabCount = impInlineInfo->InlinerCompiler->compHndBBtabCount; info.compXcptnsCount = impInlineInfo->InlinerCompiler->info.compXcptnsCount; - if (info.compRetNativeType != TYP_VOID && hasMoreThanOneReturnBlock) + // Use a spill temp for the return value if there are multiple return blocks. + if ((info.compRetNativeType != TYP_VOID) && (retBlocks > 1)) { // The lifetime of this var might expand multiple BBs. So it is a long lifetime compiler temp. lvaInlineeReturnSpillTemp = lvaGrabTemp(false DEBUGARG("Inline candidate multiple BBJ_RETURN spill temp")); lvaTable[lvaInlineeReturnSpillTemp].lvType = info.compRetNativeType; } + return; } @@ -6666,7 +6670,7 @@ void Compiler::fgImport() impImport(fgFirstBB); - if (!(opts.eeFlags & CORJIT_FLG_SKIP_VERIFICATION)) + if (!opts.jitFlags->IsSet(JitFlags::JIT_FLAG_SKIP_VERIFICATION)) { CorInfoMethodRuntimeFlags verFlag; verFlag = tiIsVerifiableCode ? CORINFO_FLG_VERIFIABLE : CORINFO_FLG_UNVERIFIABLE; @@ -6936,7 +6940,7 @@ GenTreePtr Compiler::fgGetSharedCCtor(CORINFO_CLASS_HANDLE cls) if (opts.IsReadyToRun()) { CORINFO_RESOLVED_TOKEN resolvedToken; - ZeroMemory(&resolvedToken, sizeof(resolvedToken)); + memset(&resolvedToken, 0, sizeof(resolvedToken)); resolvedToken.hClass = cls; return impReadyToRunHelperToTree(&resolvedToken, CORINFO_HELP_READYTORUN_STATIC_BASE, TYP_BYREF); @@ -8248,8 +8252,8 @@ void Compiler::fgAddInternal() if (!varTypeIsFloating(info.compRetType)) { lvaTable[genReturnLocal].setPrefReg(REG_INTRET, this); -#ifdef REG_FLOATRET } +#ifdef REG_FLOATRET else { lvaTable[genReturnLocal].setPrefReg(REG_FLOATRET, this); @@ -8301,7 +8305,7 @@ void Compiler::fgAddInternal() CORINFO_JUST_MY_CODE_HANDLE* pDbgHandle = nullptr; CORINFO_JUST_MY_CODE_HANDLE dbgHandle = nullptr; - if (opts.compDbgCode && !(opts.eeFlags & CORJIT_FLG_IL_STUB)) + if (opts.compDbgCode && !opts.jitFlags->IsSet(JitFlags::JIT_FLAG_IL_STUB)) { dbgHandle = info.compCompHnd->getJustMyCodeHandle(info.compMethodHnd, &pDbgHandle); } @@ -8589,17 +8593,12 @@ GenTreeStmt* Compiler::fgNewStmtFromTree(GenTreePtr tree, IL_OFFSETX offs) // The first good IL offset of a statement in the block, or BAD_IL_OFFSET if such an IL offset // cannot be found. // -// If we are not built with DEBUGGING_SUPPORT or DEBUG, then always report BAD_IL_OFFSET, -// since in that case statements don't contain an IL offset. The effect will be that split -// blocks will lose their IL offset information. - IL_OFFSET Compiler::fgFindBlockILOffset(BasicBlock* block) { // This function searches for IL offsets in statement nodes, so it can't be used in LIR. We // could have a similar function for LIR that searches for GT_IL_OFFSET nodes. assert(!block->IsLIR()); -#if defined(DEBUGGING_SUPPORT) || defined(DEBUG) for (GenTree* stmt = block->bbTreeList; stmt != nullptr; stmt = stmt->gtNext) { assert(stmt->IsStatement()); @@ -8608,7 +8607,6 @@ IL_OFFSET Compiler::fgFindBlockILOffset(BasicBlock* block) return jitGetILoffs(stmt->gtStmt.gtStmtILoffsx); } } -#endif // defined(DEBUGGING_SUPPORT) || defined(DEBUG) return BAD_IL_OFFSET; } @@ -8949,10 +8947,10 @@ void Compiler::fgSimpleLowering() for (GenTreePtr tree = stmt->gtStmtList; tree; tree = tree->gtNext) { #else - LIR::Range& range = LIR::AsRange(block); - for (GenTree* tree : range) + LIR::Range& range = LIR::AsRange(block); + for (GenTree* tree : range) + { { - { #endif if (tree->gtOper == GT_ARR_LENGTH) { @@ -9000,7 +8998,7 @@ void Compiler::fgSimpleLowering() add->gtNext = tree; tree->gtPrev = add; #else - range.InsertAfter(arr, con, add); + range.InsertAfter(arr, con, add); #endif } @@ -9339,6 +9337,7 @@ inline bool OperIsControlFlow(genTreeOps oper) switch (oper) { case GT_JTRUE: + case GT_JCC: case GT_SWITCH: case GT_LABEL: @@ -10019,10 +10018,10 @@ void Compiler::fgUnreachableBlock(BasicBlock* block) /***************************************************************************************************** * - * Function called to remove or morph a GT_JTRUE statement when we jump to the same + * Function called to remove or morph a jump when we jump to the same * block when both the condition is true or false. */ -void Compiler::fgRemoveJTrue(BasicBlock* block) +void Compiler::fgRemoveConditionalJump(BasicBlock* block) { noway_assert(block->bbJumpKind == BBJ_COND && block->bbJumpDest == block->bbNext); assert(compRationalIRForm == block->IsLIR()); @@ -10053,7 +10052,7 @@ void Compiler::fgRemoveJTrue(BasicBlock* block) LIR::Range& blockRange = LIR::AsRange(block); GenTree* test = blockRange.LastNode(); - assert(test->OperGet() == GT_JTRUE); + assert(test->OperIsConditionalJump()); bool isClosed; unsigned sideEffects; @@ -10109,7 +10108,7 @@ void Compiler::fgRemoveJTrue(BasicBlock* block) { test->gtStmtExpr = sideEffList; - fgMorphBlockStmt(block, test DEBUGARG("fgRemoveJTrue")); + fgMorphBlockStmt(block, test DEBUGARG("fgRemoveConditionalJump")); } } } @@ -10545,7 +10544,7 @@ void Compiler::fgRemoveBlock(BasicBlock* block, bool unreachable) // Make sure we are replacing "block" with "succBlock" in predBlock->bbJumpDest. noway_assert(predBlock->bbJumpDest == block); predBlock->bbJumpDest = succBlock; - fgRemoveJTrue(predBlock); + fgRemoveConditionalJump(predBlock); break; } @@ -10605,7 +10604,7 @@ void Compiler::fgRemoveBlock(BasicBlock* block, bool unreachable) /* Check for branch to next block */ if (bPrev->bbJumpDest == bPrev->bbNext) { - fgRemoveJTrue(bPrev); + fgRemoveConditionalJump(bPrev); } break; @@ -11031,10 +11030,10 @@ bool Compiler::fgExpandRarelyRunBlocks() noway_assert(tmpbb->isBBCallAlwaysPair()); bPrevPrev = tmpbb; #else - if (tmpbb->bbJumpKind == BBJ_CALLFINALLY) - { - bPrevPrev = tmpbb; - } + if (tmpbb->bbJumpKind == BBJ_CALLFINALLY) + { + bPrevPrev = tmpbb; + } #endif } @@ -11566,60 +11565,60 @@ BasicBlock* Compiler::fgRelocateEHRange(unsigned regionIndex, FG_RELOCATE_TYPE r #else // FEATURE_EH_FUNCLETS - for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++) + for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++) + { + if (XTnum == regionIndex) { - if (XTnum == regionIndex) - { - // Don't update our handler's Last info - continue; - } + // Don't update our handler's Last info + continue; + } - if (HBtab->ebdTryLast == bLast) + if (HBtab->ebdTryLast == bLast) + { + // If we moved a set of blocks that were at the end of + // a different try region then we may need to update ebdTryLast + for (block = HBtab->ebdTryBeg; block != NULL; block = block->bbNext) { - // If we moved a set of blocks that were at the end of - // a different try region then we may need to update ebdTryLast - for (block = HBtab->ebdTryBeg; block != NULL; block = block->bbNext) + if (block == bPrev) { - if (block == bPrev) - { - fgSetTryEnd(HBtab, bPrev); - break; - } - else if (block == HBtab->ebdTryLast->bbNext) - { - // bPrev does not come after the TryBeg - break; - } + fgSetTryEnd(HBtab, bPrev); + break; + } + else if (block == HBtab->ebdTryLast->bbNext) + { + // bPrev does not come after the TryBeg + break; } } - if (HBtab->ebdHndLast == bLast) + } + if (HBtab->ebdHndLast == bLast) + { + // If we moved a set of blocks that were at the end of + // a different handler region then we must update ebdHndLast + for (block = HBtab->ebdHndBeg; block != NULL; block = block->bbNext) { - // If we moved a set of blocks that were at the end of - // a different handler region then we must update ebdHndLast - for (block = HBtab->ebdHndBeg; block != NULL; block = block->bbNext) + if (block == bPrev) { - if (block == bPrev) - { - fgSetHndEnd(HBtab, bPrev); - break; - } - else if (block == HBtab->ebdHndLast->bbNext) - { - // bPrev does not come after the HndBeg - break; - } + fgSetHndEnd(HBtab, bPrev); + break; + } + else if (block == HBtab->ebdHndLast->bbNext) + { + // bPrev does not come after the HndBeg + break; } } - } // end exception table iteration + } + } // end exception table iteration - // We have decided to insert the block(s) after fgLastBlock - fgMoveBlocksAfter(bStart, bLast, insertAfterBlk); + // We have decided to insert the block(s) after fgLastBlock + fgMoveBlocksAfter(bStart, bLast, insertAfterBlk); - // If bPrev falls through, we will insert a jump to block - fgConnectFallThrough(bPrev, bStart); + // If bPrev falls through, we will insert a jump to block + fgConnectFallThrough(bPrev, bStart); - // If bLast falls through, we will insert a jump to bNext - fgConnectFallThrough(bLast, bNext); + // If bLast falls through, we will insert a jump to bNext + fgConnectFallThrough(bLast, bNext); #endif // FEATURE_EH_FUNCLETS @@ -12060,70 +12059,70 @@ void Compiler::fgCreateFunclets() #else // !FEATURE_EH_FUNCLETS - /***************************************************************************** - * - * Function called to relocate any and all EH regions. - * Only entire consecutive EH regions will be moved and they will be kept together. - * Except for the first block, the range can not have any blocks that jump into or out of the region. - */ +/***************************************************************************** + * + * Function called to relocate any and all EH regions. + * Only entire consecutive EH regions will be moved and they will be kept together. + * Except for the first block, the range can not have any blocks that jump into or out of the region. + */ - bool Compiler::fgRelocateEHRegions() - { - bool result = false; // Our return value +bool Compiler::fgRelocateEHRegions() +{ + bool result = false; // Our return value #ifdef DEBUG - if (verbose) - printf("*************** In fgRelocateEHRegions()\n"); + if (verbose) + printf("*************** In fgRelocateEHRegions()\n"); #endif - if (fgCanRelocateEHRegions) - { - unsigned XTnum; - EHblkDsc* HBtab; + if (fgCanRelocateEHRegions) + { + unsigned XTnum; + EHblkDsc* HBtab; - for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++) + for (XTnum = 0, HBtab = compHndBBtab; XTnum < compHndBBtabCount; XTnum++, HBtab++) + { + // Nested EH regions cannot be moved. + // Also we don't want to relocate an EH region that has a filter + if ((HBtab->ebdHandlerNestingLevel == 0) && !HBtab->HasFilter()) { - // Nested EH regions cannot be moved. - // Also we don't want to relocate an EH region that has a filter - if ((HBtab->ebdHandlerNestingLevel == 0) && !HBtab->HasFilter()) - { - bool movedTry = false; + bool movedTry = false; #if DEBUG - bool movedHnd = false; + bool movedHnd = false; #endif // DEBUG - // Only try to move the outermost try region - if (HBtab->ebdEnclosingTryIndex == EHblkDsc::NO_ENCLOSING_INDEX) + // Only try to move the outermost try region + if (HBtab->ebdEnclosingTryIndex == EHblkDsc::NO_ENCLOSING_INDEX) + { + // Move the entire try region if it can be moved + if (HBtab->ebdTryBeg->isRunRarely()) { - // Move the entire try region if it can be moved - if (HBtab->ebdTryBeg->isRunRarely()) + BasicBlock* bTryLastBB = fgRelocateEHRange(XTnum, FG_RELOCATE_TRY); + if (bTryLastBB != NULL) { - BasicBlock* bTryLastBB = fgRelocateEHRange(XTnum, FG_RELOCATE_TRY); - if (bTryLastBB != NULL) - { - result = true; - movedTry = true; - } + result = true; + movedTry = true; } + } #if DEBUG - if (verbose && movedTry) - { - printf("\nAfter relocating an EH try region"); - fgDispBasicBlocks(); - fgDispHandlerTab(); + if (verbose && movedTry) + { + printf("\nAfter relocating an EH try region"); + fgDispBasicBlocks(); + fgDispHandlerTab(); - // Make sure that the predecessor lists are accurate - if (expensiveDebugCheckLevel >= 2) - { - fgDebugCheckBBlist(); - } + // Make sure that the predecessor lists are accurate + if (expensiveDebugCheckLevel >= 2) + { + fgDebugCheckBBlist(); } -#endif // DEBUG } +#endif // DEBUG + } - // Currently it is not good to move the rarely run handler regions to the end of the method - // because fgDetermineFirstColdBlock() must put the start of any handler region in the hot section. - CLANG_FORMAT_COMMENT_ANCHOR; + // Currently it is not good to move the rarely run handler regions to the end of the method + // because fgDetermineFirstColdBlock() must put the start of any handler region in the hot section. + CLANG_FORMAT_COMMENT_ANCHOR; #if 0 // Now try to move the entire handler region if it can be moved. @@ -12142,38 +12141,38 @@ void Compiler::fgCreateFunclets() #endif // 0 #if DEBUG - if (verbose && movedHnd) - { - printf("\nAfter relocating an EH handler region"); - fgDispBasicBlocks(); - fgDispHandlerTab(); + if (verbose && movedHnd) + { + printf("\nAfter relocating an EH handler region"); + fgDispBasicBlocks(); + fgDispHandlerTab(); - // Make sure that the predecessor lists are accurate - if (expensiveDebugCheckLevel >= 2) - { - fgDebugCheckBBlist(); - } + // Make sure that the predecessor lists are accurate + if (expensiveDebugCheckLevel >= 2) + { + fgDebugCheckBBlist(); } -#endif // DEBUG } +#endif // DEBUG } } + } #if DEBUG - fgVerifyHandlerTab(); + fgVerifyHandlerTab(); - if (verbose && result) - { - printf("\nAfter fgRelocateEHRegions()"); - fgDispBasicBlocks(); - fgDispHandlerTab(); - // Make sure that the predecessor lists are accurate - fgDebugCheckBBlist(); - } + if (verbose && result) + { + printf("\nAfter fgRelocateEHRegions()"); + fgDispBasicBlocks(); + fgDispHandlerTab(); + // Make sure that the predecessor lists are accurate + fgDebugCheckBBlist(); + } #endif // DEBUG - return result; - } + return result; +} #endif // !FEATURE_EH_FUNCLETS @@ -13489,6 +13488,7 @@ bool Compiler::fgOptimizeSwitchBranches(BasicBlock* block) GenTree* switchVal = switchTree->gtOp.gtOp1; noway_assert(genActualTypeIsIntOrI(switchVal->TypeGet())); +#ifndef LEGACY_BACKEND // If we are in LIR, remove the jump table from the block. if (block->IsLIR()) { @@ -13496,6 +13496,7 @@ bool Compiler::fgOptimizeSwitchBranches(BasicBlock* block) assert(jumpTable->OperGet() == GT_JMPTABLE); blockRange->Remove(jumpTable); } +#endif // Change the GT_SWITCH(switchVal) into GT_JTRUE(GT_EQ(switchVal==0)). // Also mark the node as GTF_DONT_CSE as further down JIT is not capable of handling it. @@ -13793,7 +13794,7 @@ bool Compiler::fgOptimizeBranchToNext(BasicBlock* block, BasicBlock* bNext, Basi { LIR::Range& blockRange = LIR::AsRange(block); GenTree* jmp = blockRange.LastNode(); - assert(jmp->OperGet() == GT_JTRUE); + assert(jmp->OperIsConditionalJump()); bool isClosed; unsigned sideEffects; @@ -14034,7 +14035,7 @@ bool Compiler::fgOptimizeBranch(BasicBlock* bJump) // we are willing to have more code expansion since we // won't be running code from this page // - if (opts.eeFlags & CORJIT_FLG_PREJIT) + if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT)) { if (rareJump) { @@ -14169,16 +14170,16 @@ bool Compiler::fgOptimizeBranch(BasicBlock* bJump) // gtReverseCond(condTree); + // We need to update the following flags of the bJump block if they were set in the bDest block + bJump->bbFlags |= + (bDest->bbFlags & (BBF_HAS_NEWOBJ | BBF_HAS_NEWARRAY | BBF_HAS_NULLCHECK | BBF_HAS_IDX_LEN | BBF_HAS_VTABREF)); + bJump->bbJumpKind = BBJ_COND; bJump->bbJumpDest = bDest->bbNext; /* Mark the jump dest block as being a jump target */ bJump->bbJumpDest->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL; - // We need to update the following flags of the bJump block if they were set in the bbJumpDest block - bJump->bbFlags |= (bJump->bbJumpDest->bbFlags & - (BBF_HAS_NEWOBJ | BBF_HAS_NEWARRAY | BBF_HAS_NULLCHECK | BBF_HAS_IDX_LEN | BBF_HAS_VTABREF)); - /* Update bbRefs and bbPreds */ // bJump now falls through into the next block @@ -15879,11 +15880,18 @@ bool Compiler::fgUpdateFlowGraph(bool doTailDuplication) /* Reverse the jump condition */ GenTree* test = block->lastNode(); - noway_assert(test->gtOper == GT_JTRUE); + noway_assert(test->OperIsConditionalJump()); - GenTree* cond = gtReverseCond(test->gtOp.gtOp1); - assert(cond == test->gtOp.gtOp1); // Ensure `gtReverseCond` did not create a new node. - test->gtOp.gtOp1 = cond; + if (test->OperGet() == GT_JTRUE) + { + GenTree* cond = gtReverseCond(test->gtOp.gtOp1); + assert(cond == test->gtOp.gtOp1); // Ensure `gtReverseCond` did not create a new node. + test->gtOp.gtOp1 = cond; + } + else + { + gtReverseCond(test); + } // Optimize the Conditional JUMP to go to the new target block->bbJumpDest = bNext->bbJumpDest; @@ -18020,9 +18028,13 @@ void Compiler::fgSetTreeSeqFinish(GenTreePtr tree, bool isLIR) { // If we are sequencing a node that does not appear in LIR, // do not add it to the list. - if (isLIR && (((tree->OperGet() == GT_LIST) && !tree->AsArgList()->IsAggregate()) || tree->OperGet() == GT_ARGPLACE)) + if (isLIR) { - return; + if ((tree->OperGet() == GT_LIST) || (tree->OperGet() == GT_ARGPLACE) || + (tree->OperGet() == GT_FIELD_LIST && !tree->AsFieldList()->IsFieldListHead())) + { + return; + } } /* Append to the node list */ @@ -18359,7 +18371,7 @@ void Compiler::fgSetBlockOrder(BasicBlock* block) // // For the (usual) case of GT_BLK or GT_OBJ, the size is always "evaluated" (i.e. // instantiated into a register) last. In those cases, the GTF_REVERSE_OPS flag -// on the assignment works as usual. +// on the assignment works as usual. // In order to preserve previous possible orderings, the order for evaluating // the size of a GT_DYN_BLK node is controlled by its gtEvalSizeFirst flag. If // that is set, the size is evaluated first, and then the src and dst are evaluated @@ -18549,20 +18561,20 @@ static escapeMapping_t s_EscapeMapping[] = {'"', """}, {0, nullptr} }; -// clang-formt on +// clang-format on -const char* Compiler::fgProcessEscapes(const char* nameIn, escapeMapping_t* map) +const char* Compiler::fgProcessEscapes(const char* nameIn, escapeMapping_t* map) { - const char* nameOut = nameIn; - unsigned lengthOut; - unsigned index; - bool match; - bool subsitutionRequired; - const char* pChar; - - lengthOut = 1; + const char* nameOut = nameIn; + unsigned lengthOut; + unsigned index; + bool match; + bool subsitutionRequired; + const char* pChar; + + lengthOut = 1; subsitutionRequired = false; - pChar = nameIn; + pChar = nameIn; while (*pChar != '\0') { match = false; @@ -18590,8 +18602,8 @@ const char* Compiler::fgProcessEscapes(const char* nameIn, escapeMapping_t* ma if (subsitutionRequired) { - char* newName = (char*) compGetMemA(lengthOut, CMK_DebugOnly); - char* pDest; + char* newName = (char*)compGetMemA(lengthOut, CMK_DebugOnly); + char* pDest; pDest = newName; pChar = nameIn; while (*pChar != '\0') @@ -18619,7 +18631,7 @@ const char* Compiler::fgProcessEscapes(const char* nameIn, escapeMapping_t* ma pChar++; } *pDest++ = '\0'; - nameOut = (const char*) newName; + nameOut = (const char*)newName; } return nameOut; @@ -18655,44 +18667,47 @@ static void fprintfDouble(FILE* fgxFile, double value) // Opens a file to which a flowgraph can be dumped, whose name is based on the current // config vales. -FILE* Compiler::fgOpenFlowGraphFile(bool* wbDontClose, Phases phase, LPCWSTR type) +FILE* Compiler::fgOpenFlowGraphFile(bool* wbDontClose, Phases phase, LPCWSTR type) { - FILE* fgxFile; - LPCWSTR pattern = nullptr; - LPCWSTR filename = nullptr; - LPCWSTR pathname = nullptr; - const char* escapedString; - bool createDuplicateFgxFiles = true; + FILE* fgxFile; + LPCWSTR pattern = nullptr; + LPCWSTR filename = nullptr; + LPCWSTR pathname = nullptr; + const char* escapedString; + bool createDuplicateFgxFiles = true; #ifdef DEBUG - if (opts.eeFlags & CORJIT_FLG_PREJIT) + if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT)) { - pattern = JitConfig.NgenDumpFg(); + pattern = JitConfig.NgenDumpFg(); filename = JitConfig.NgenDumpFgFile(); pathname = JitConfig.NgenDumpFgDir(); } else { - pattern = JitConfig.JitDumpFg(); + pattern = JitConfig.JitDumpFg(); filename = JitConfig.JitDumpFgFile(); pathname = JitConfig.JitDumpFgDir(); } #endif // DEBUG - if (fgBBcount <= 1) { + if (fgBBcount <= 1) + { return nullptr; -} + } - if (pattern == nullptr) { + if (pattern == nullptr) + { return nullptr; -} + } - if (wcslen(pattern) == 0) { + if (wcslen(pattern) == 0) + { return nullptr; -} + } LPCWSTR phasePattern = JitConfig.JitDumpFgPhase(); - LPCWSTR phaseName = PhaseShortNames[phase]; + LPCWSTR phaseName = PhaseShortNames[phase]; if (phasePattern == nullptr) { if (phase != PHASE_DETERMINE_FIRST_COLD_BLOCK) @@ -18723,9 +18738,10 @@ FILE* Compiler::fgOpenFlowGraphFile(bool* wbDontClose, Phases phas { while ((*pattern != W(':')) && (*pattern != W('*'))) { - if (*pattern != *className) { + if (*pattern != *className) + { return nullptr; -} + } pattern++; className++; @@ -18736,12 +18752,14 @@ FILE* Compiler::fgOpenFlowGraphFile(bool* wbDontClose, Phases phas } else { - if (*className != 0) { + if (*className != 0) + { return nullptr; -} - } + } } - if (*pattern != W(':')) { + } + if (*pattern != W(':')) + { return nullptr; } @@ -18757,9 +18775,10 @@ FILE* Compiler::fgOpenFlowGraphFile(bool* wbDontClose, Phases phas { while ((*pattern != 0) && (*pattern != W('*'))) { - if (*pattern != *methodName) { + if (*pattern != *methodName) + { return nullptr; -} + } pattern++; methodName++; @@ -18770,12 +18789,14 @@ FILE* Compiler::fgOpenFlowGraphFile(bool* wbDontClose, Phases phas } else { - if (*methodName != 0) { + if (*methodName != 0) + { return nullptr; -} - } + } } - if (*pattern != 0) { + } + if (*pattern != 0) + { return nullptr; } } @@ -18838,15 +18859,15 @@ FILE* Compiler::fgOpenFlowGraphFile(bool* wbDontClose, Phases phas { createDuplicateFgxFiles = true; -ONE_FILE_PER_METHOD:; + ONE_FILE_PER_METHOD:; - escapedString = fgProcessEscapes(info.compFullName, s_EscapeFileMapping); + escapedString = fgProcessEscapes(info.compFullName, s_EscapeFileMapping); size_t wCharCount = strlen(escapedString) + wcslen(phaseName) + 1 + strlen("~999") + wcslen(type) + 1; if (pathname != nullptr) { wCharCount += wcslen(pathname) + 1; } - filename = (LPCWSTR) alloca(wCharCount * sizeof(WCHAR)); + filename = (LPCWSTR)alloca(wCharCount * sizeof(WCHAR)); if (pathname != nullptr) { swprintf_s((LPWSTR)filename, wCharCount, W("%s\\%S-%s.%s"), pathname, escapedString, phaseName, type); @@ -18855,7 +18876,7 @@ ONE_FILE_PER_METHOD:; { swprintf_s((LPWSTR)filename, wCharCount, W("%S.%s"), escapedString, type); } - fgxFile = _wfopen(filename, W("r")); // Check if this file already exists + fgxFile = _wfopen(filename, W("r")); // Check if this file already exists if (fgxFile != nullptr) { // For Generic methods we will have both hot and cold versions @@ -18876,10 +18897,11 @@ ONE_FILE_PER_METHOD:; { swprintf_s((LPWSTR)filename, wCharCount, W("%S~%d.%s"), escapedString, i, type); } - fgxFile = _wfopen(filename, W("r")); // Check if this file exists - if (fgxFile == nullptr) { + fgxFile = _wfopen(filename, W("r")); // Check if this file exists + if (fgxFile == nullptr) + { break; - } + } } // If we have already created 1000 files with this name then just fail if (fgxFile != nullptr) @@ -18888,28 +18910,28 @@ ONE_FILE_PER_METHOD:; return nullptr; } } - fgxFile = _wfopen(filename, W("a+")); + fgxFile = _wfopen(filename, W("a+")); *wbDontClose = false; } else if (wcscmp(filename, W("stdout")) == 0) { - fgxFile = jitstdout; + fgxFile = jitstdout; *wbDontClose = true; } else if (wcscmp(filename, W("stderr")) == 0) { - fgxFile = stderr; + fgxFile = stderr; *wbDontClose = true; } else { LPCWSTR origFilename = filename; - size_t wCharCount = wcslen(origFilename) + wcslen(type) + 2; + size_t wCharCount = wcslen(origFilename) + wcslen(type) + 2; if (pathname != nullptr) { wCharCount += wcslen(pathname) + 1; } - filename = (LPCWSTR) alloca(wCharCount * sizeof(WCHAR)); + filename = (LPCWSTR)alloca(wCharCount * sizeof(WCHAR)); if (pathname != nullptr) { swprintf_s((LPWSTR)filename, wCharCount, W("%s\\%s.%s"), pathname, origFilename, type); @@ -18918,7 +18940,7 @@ ONE_FILE_PER_METHOD:; { swprintf_s((LPWSTR)filename, wCharCount, W("%s.%s"), origFilename, type); } - fgxFile = _wfopen(filename, W("a+")); + fgxFile = _wfopen(filename, W("a+")); *wbDontClose = false; } @@ -18959,39 +18981,39 @@ ONE_FILE_PER_METHOD:; // phases. // COMPlus_JitDumpFgDot Set to non-zero to emit Dot instead of Xml Flowgraph dump. (Default is xml format.) -bool Compiler::fgDumpFlowGraph(Phases phase) +bool Compiler::fgDumpFlowGraph(Phases phase) { - bool result = false; - bool dontClose = false; - bool createDotFile = false; + bool result = false; + bool dontClose = false; + bool createDotFile = false; if (JitConfig.JitDumpFgDot()) { createDotFile = true; } - - FILE* fgxFile = fgOpenFlowGraphFile(&dontClose, phase, createDotFile ? W("dot") : W("fgx")); + + FILE* fgxFile = fgOpenFlowGraphFile(&dontClose, phase, createDotFile ? W("dot") : W("fgx")); if (fgxFile == nullptr) { return false; } - bool validWeights = fgHaveValidEdgeWeights; - unsigned calledCount = max(fgCalledWeight, BB_UNITY_WEIGHT) / BB_UNITY_WEIGHT; - double weightDivisor = (double) (calledCount * BB_UNITY_WEIGHT); - const char* escapedString; - const char* regionString = "NONE"; + bool validWeights = fgHaveValidEdgeWeights; + unsigned calledCount = max(fgCalledWeight, BB_UNITY_WEIGHT) / BB_UNITY_WEIGHT; + double weightDivisor = (double)(calledCount * BB_UNITY_WEIGHT); + const char* escapedString; + const char* regionString = "NONE"; - if (info.compMethodInfo->regionKind == CORINFO_REGION_HOT) + if (info.compMethodInfo->regionKind == CORINFO_REGION_HOT) { - regionString="HOT"; + regionString = "HOT"; } else if (info.compMethodInfo->regionKind == CORINFO_REGION_COLD) { - regionString="COLD"; + regionString = "COLD"; } else if (info.compMethodInfo->regionKind == CORINFO_REGION_JIT) { - regionString="JIT"; + regionString = "JIT"; } if (createDotFile) @@ -19001,7 +19023,7 @@ bool Compiler::fgDumpFlowGraph(Phases phase) } else { - fprintf(fgxFile, "bbNum); } - fprintf(fgxFile, ">"); + fprintf(fgxFile, ">"); fprintf(fgxFile, "\n "); + fprintf(fgxFile, ">"); } - static const char* kindImage[] = { "EHFINALLYRET", "EHFILTERRET", "EHCATCHRET", - "THROW", "RETURN", "NONE", "ALWAYS", "LEAVE", - "CALLFINALLY", "COND", "SWITCH" }; + static const char* kindImage[] = {"EHFINALLYRET", "EHFILTERRET", "EHCATCHRET", "THROW", "RETURN", "NONE", + "ALWAYS", "LEAVE", "CALLFINALLY", "COND", "SWITCH"}; BasicBlock* block; unsigned blockOrdinal; - for (block = fgFirstBB , blockOrdinal = 1; - block != nullptr; - block = block->bbNext, blockOrdinal++) + for (block = fgFirstBB, blockOrdinal = 1; block != nullptr; block = block->bbNext, blockOrdinal++) { if (createDotFile) { // Add constraint edges to try to keep nodes ordered. // It seems to work best if these edges are all created first. - switch(block->bbJumpKind) + switch (block->bbJumpKind) { - case BBJ_COND: - case BBJ_NONE: - assert(block->bbNext != nullptr); - fprintf(fgxFile, " BB%02u -> BB%02u\n", block->bbNum, block->bbNext->bbNum); - break; - default: - // These may or may not have an edge to the next block. - // Add a transparent edge to keep nodes ordered. - if (block->bbNext != nullptr) - { - fprintf(fgxFile, " BB%02u -> BB%02u [arrowtail=none,color=transparent]\n", block->bbNum, block->bbNext->bbNum); - } + case BBJ_COND: + case BBJ_NONE: + assert(block->bbNext != nullptr); + fprintf(fgxFile, " BB%02u -> BB%02u\n", block->bbNum, block->bbNext->bbNum); + break; + default: + // These may or may not have an edge to the next block. + // Add a transparent edge to keep nodes ordered. + if (block->bbNext != nullptr) + { + fprintf(fgxFile, " BB%02u -> BB%02u [arrowtail=none,color=transparent]\n", block->bbNum, + block->bbNext->bbNum); + } } } else { - fprintf(fgxFile,"\n bbNum); - fprintf(fgxFile,"\n ordinal=\"%d\"", blockOrdinal); - fprintf(fgxFile,"\n jumpKind=\"%s\"", kindImage[block->bbJumpKind]); + fprintf(fgxFile, "\n bbNum); + fprintf(fgxFile, "\n ordinal=\"%d\"", blockOrdinal); + fprintf(fgxFile, "\n jumpKind=\"%s\"", kindImage[block->bbJumpKind]); if (block->hasTryIndex()) { - fprintf(fgxFile,"\n inTry=\"%s\"", "true"); + fprintf(fgxFile, "\n inTry=\"%s\"", "true"); } if (block->hasHndIndex()) { - fprintf(fgxFile,"\n inHandler=\"%s\"", "true"); + fprintf(fgxFile, "\n inHandler=\"%s\"", "true"); } - if (((fgFirstBB->bbFlags & BBF_PROF_WEIGHT) != 0) && - ((block->bbFlags & BBF_COLD) == 0) ) + if (((fgFirstBB->bbFlags & BBF_PROF_WEIGHT) != 0) && ((block->bbFlags & BBF_COLD) == 0)) { - fprintf(fgxFile,"\n hot=\"true\""); + fprintf(fgxFile, "\n hot=\"true\""); } if (block->bbFlags & (BBF_HAS_NEWOBJ | BBF_HAS_NEWARRAY)) { - fprintf(fgxFile,"\n callsNew=\"true\""); + fprintf(fgxFile, "\n callsNew=\"true\""); } if (block->bbFlags & BBF_LOOP_HEAD) { - fprintf(fgxFile,"\n loopHead=\"true\""); + fprintf(fgxFile, "\n loopHead=\"true\""); } - fprintf(fgxFile,"\n weight="); - fprintfDouble(fgxFile, ((double) block->bbWeight) / weightDivisor); - fprintf(fgxFile,"\n codeEstimate=\"%d\"", fgGetCodeEstimate(block)); - fprintf(fgxFile,"\n startOffset=\"%d\"", block->bbCodeOffs); - fprintf(fgxFile,"\n endOffset=\"%d\"", block->bbCodeOffsEnd); - fprintf(fgxFile, ">"); - fprintf(fgxFile,"\n "); + fprintf(fgxFile, "\n weight="); + fprintfDouble(fgxFile, ((double)block->bbWeight) / weightDivisor); + fprintf(fgxFile, "\n codeEstimate=\"%d\"", fgGetCodeEstimate(block)); + fprintf(fgxFile, "\n startOffset=\"%d\"", block->bbCodeOffs); + fprintf(fgxFile, "\n endOffset=\"%d\"", block->bbCodeOffsEnd); + fprintf(fgxFile, ">"); + fprintf(fgxFile, "\n "); } } @@ -19122,10 +19141,10 @@ bool Compiler::fgDumpFlowGraph(Phases phase) fprintf(fgxFile, "\n "); + fprintf(fgxFile, ">"); } - unsigned edgeNum = 1; + unsigned edgeNum = 1; BasicBlock* bTarget; for (bTarget = fgFirstBB; bTarget != nullptr; bTarget = bTarget->bbNext) { @@ -19136,21 +19155,21 @@ bool Compiler::fgDumpFlowGraph(Phases phase) } else { - targetWeightDivisor = (double) bTarget->bbWeight; + targetWeightDivisor = (double)bTarget->bbWeight; } flowList* edge; for (edge = bTarget->bbPreds; edge != nullptr; edge = edge->flNext, edgeNum++) { - BasicBlock* bSource = edge->flBlock; - double sourceWeightDivisor; + BasicBlock* bSource = edge->flBlock; + double sourceWeightDivisor; if (bSource->bbWeight == BB_ZERO_WEIGHT) { sourceWeightDivisor = 1.0; } else { - sourceWeightDivisor = (double) bSource->bbWeight; + sourceWeightDivisor = (double)bSource->bbWeight; } if (createDotFile) { @@ -19172,54 +19191,54 @@ bool Compiler::fgDumpFlowGraph(Phases phase) } else { - fprintf(fgxFile,"\n bbNum); - fprintf(fgxFile,"\n target=\"%d\"", bTarget->bbNum); + fprintf(fgxFile, "\n bbNum); + fprintf(fgxFile, "\n target=\"%d\"", bTarget->bbNum); if (bSource->bbJumpKind == BBJ_SWITCH) { if (edge->flDupCount >= 2) { - fprintf(fgxFile,"\n switchCases=\"%d\"", edge->flDupCount); + fprintf(fgxFile, "\n switchCases=\"%d\"", edge->flDupCount); } if (bSource->bbJumpSwt->getDefault() == bTarget) { - fprintf(fgxFile,"\n switchDefault=\"true\""); + fprintf(fgxFile, "\n switchDefault=\"true\""); } } if (validWeights) { unsigned edgeWeight = (edge->flEdgeWeightMin + edge->flEdgeWeightMax) / 2; - fprintf(fgxFile,"\n weight="); - fprintfDouble(fgxFile, ((double) edgeWeight) / weightDivisor); + fprintf(fgxFile, "\n weight="); + fprintfDouble(fgxFile, ((double)edgeWeight) / weightDivisor); if (edge->flEdgeWeightMin != edge->flEdgeWeightMax) { - fprintf(fgxFile,"\n minWeight="); - fprintfDouble(fgxFile, ((double) edge->flEdgeWeightMin) / weightDivisor); - fprintf(fgxFile,"\n maxWeight="); - fprintfDouble(fgxFile, ((double) edge->flEdgeWeightMax) / weightDivisor); + fprintf(fgxFile, "\n minWeight="); + fprintfDouble(fgxFile, ((double)edge->flEdgeWeightMin) / weightDivisor); + fprintf(fgxFile, "\n maxWeight="); + fprintfDouble(fgxFile, ((double)edge->flEdgeWeightMax) / weightDivisor); } if (edgeWeight > 0) { if (edgeWeight < bSource->bbWeight) { - fprintf(fgxFile,"\n out="); - fprintfDouble(fgxFile, ((double) edgeWeight) / sourceWeightDivisor ); + fprintf(fgxFile, "\n out="); + fprintfDouble(fgxFile, ((double)edgeWeight) / sourceWeightDivisor); } if (edgeWeight < bTarget->bbWeight) { - fprintf(fgxFile,"\n in="); - fprintfDouble(fgxFile, ((double) edgeWeight) / targetWeightDivisor); + fprintf(fgxFile, "\n in="); + fprintfDouble(fgxFile, ((double)edgeWeight) / targetWeightDivisor); } } } } if (!createDotFile) { - fprintf(fgxFile, ">"); - fprintf(fgxFile,"\n "); + fprintf(fgxFile, ">"); + fprintf(fgxFile, "\n "); } } } @@ -19251,7 +19270,7 @@ bool Compiler::fgDumpFlowGraph(Phases phase) /*****************************************************************************/ #ifdef DEBUG -void Compiler::fgDispReach() +void Compiler::fgDispReach() { printf("------------------------------------------------\n"); printf("BBnum Reachable by \n"); @@ -19269,7 +19288,7 @@ void Compiler::fgDispReach() } } -void Compiler::fgDispDoms() +void Compiler::fgDispDoms() { // Don't bother printing this when we have a large number of BasicBlocks in the method if (fgBBcount > 256) @@ -19296,23 +19315,17 @@ void Compiler::fgDispDoms() /*****************************************************************************/ -void Compiler::fgTableDispBasicBlock(BasicBlock* block, - int ibcColWidth /* = 0 */) +void Compiler::fgTableDispBasicBlock(BasicBlock* block, int ibcColWidth /* = 0 */) { - unsigned flags = block->bbFlags; + const unsigned __int64 flags = block->bbFlags; + unsigned bbNumMax = compIsForInlining() ? impInlineInfo->InlinerCompiler->fgBBNumMax : fgBBNumMax; + int maxBlockNumWidth = CountDigits(bbNumMax); + maxBlockNumWidth = max(maxBlockNumWidth, 2); + int blockNumWidth = CountDigits(block->bbNum); + blockNumWidth = max(blockNumWidth, 2); + int blockNumPadding = maxBlockNumWidth - blockNumWidth; - unsigned bbNumMax = compIsForInlining() ? impInlineInfo->InlinerCompiler->fgBBNumMax : fgBBNumMax; - int maxBlockNumWidth = CountDigits(bbNumMax); - maxBlockNumWidth = max(maxBlockNumWidth, 2); - int blockNumWidth = CountDigits(block->bbNum); - blockNumWidth = max(blockNumWidth, 2); - int blockNumPadding = maxBlockNumWidth - blockNumWidth; - - printf("BB%02u%*s [%08p] %2u", - block->bbNum, - blockNumPadding, "", - dspPtr(block), - block->bbRefs); + printf("BB%02u%*s [%08p] %2u", block->bbNum, blockNumPadding, "", dspPtr(block), block->bbRefs); // // Display EH 'try' region index @@ -19406,86 +19419,89 @@ void Compiler::fgTableDispBasicBlock(BasicBlock* block, // Display block branch target // - if (flags & BBF_REMOVED) + if (flags & BBF_REMOVED) { - printf( "[removed] "); + printf("[removed] "); } else { switch (block->bbJumpKind) { - case BBJ_COND: - printf("-> BB%02u%*s ( cond )", block->bbJumpDest->bbNum, maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), ""); - break; - - case BBJ_CALLFINALLY: - printf("-> BB%02u%*s (callf )", block->bbJumpDest->bbNum, maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), ""); - break; + case BBJ_COND: + printf("-> BB%02u%*s ( cond )", block->bbJumpDest->bbNum, + maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), ""); + break; - case BBJ_ALWAYS: - if (flags & BBF_KEEP_BBJ_ALWAYS) - { - printf("-> BB%02u%*s (ALWAYS)", block->bbJumpDest->bbNum, maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), ""); - } - else - { - printf("-> BB%02u%*s (always)", block->bbJumpDest->bbNum, maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), ""); - } - break; + case BBJ_CALLFINALLY: + printf("-> BB%02u%*s (callf )", block->bbJumpDest->bbNum, + maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), ""); + break; - case BBJ_LEAVE: - printf("-> BB%02u%*s (leave )", block->bbJumpDest->bbNum, maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), ""); - break; + case BBJ_ALWAYS: + if (flags & BBF_KEEP_BBJ_ALWAYS) + { + printf("-> BB%02u%*s (ALWAYS)", block->bbJumpDest->bbNum, + maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), ""); + } + else + { + printf("-> BB%02u%*s (always)", block->bbJumpDest->bbNum, + maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), ""); + } + break; - case BBJ_EHFINALLYRET: - printf( "%*s (finret)", maxBlockNumWidth - 2, ""); - break; + case BBJ_LEAVE: + printf("-> BB%02u%*s (leave )", block->bbJumpDest->bbNum, + maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), ""); + break; - case BBJ_EHFILTERRET: - printf( "%*s (fltret)", maxBlockNumWidth - 2, ""); - break; + case BBJ_EHFINALLYRET: + printf("%*s (finret)", maxBlockNumWidth - 2, ""); + break; - case BBJ_EHCATCHRET: - printf("-> BB%02u%*s ( cret )", block->bbJumpDest->bbNum, maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), ""); - break; + case BBJ_EHFILTERRET: + printf("%*s (fltret)", maxBlockNumWidth - 2, ""); + break; - case BBJ_THROW: - printf( "%*s (throw )", maxBlockNumWidth - 2, ""); - break; + case BBJ_EHCATCHRET: + printf("-> BB%02u%*s ( cret )", block->bbJumpDest->bbNum, + maxBlockNumWidth - max(CountDigits(block->bbJumpDest->bbNum), 2), ""); + break; - case BBJ_RETURN: - printf( "%*s (return)", maxBlockNumWidth - 2, ""); - break; + case BBJ_THROW: + printf("%*s (throw )", maxBlockNumWidth - 2, ""); + break; - default: - printf( "%*s ", maxBlockNumWidth - 2, ""); - break; + case BBJ_RETURN: + printf("%*s (return)", maxBlockNumWidth - 2, ""); + break; - case BBJ_SWITCH: - printf("->"); - - unsigned jumpCnt; - jumpCnt = block->bbJumpSwt->bbsCount; - BasicBlock** jumpTab; - jumpTab = block->bbJumpSwt->bbsDstTab; - int switchWidth; - switchWidth = 0; - do - { - printf("%cBB%02u", - (jumpTab == block->bbJumpSwt->bbsDstTab) ? ' ' : ',', - (*jumpTab)->bbNum); - switchWidth += 1 /* space/comma */ + 2 /* BB */ + max(CountDigits((*jumpTab)->bbNum), 2); - } - while (++jumpTab, --jumpCnt); + default: + printf("%*s ", maxBlockNumWidth - 2, ""); + break; - if (switchWidth < 7) - { - printf("%*s", 8 - switchWidth, ""); - } + case BBJ_SWITCH: + printf("->"); - printf(" (switch)"); - break; + unsigned jumpCnt; + jumpCnt = block->bbJumpSwt->bbsCount; + BasicBlock** jumpTab; + jumpTab = block->bbJumpSwt->bbsDstTab; + int switchWidth; + switchWidth = 0; + do + { + printf("%cBB%02u", (jumpTab == block->bbJumpSwt->bbsDstTab) ? ' ' : ',', (*jumpTab)->bbNum); + switchWidth += 1 /* space/comma */ + 2 /* BB */ + max(CountDigits((*jumpTab)->bbNum), 2); + } while (++jumpTab, --jumpCnt); + + if (switchWidth < 7) + { + printf("%*s", 8 - switchWidth, ""); + } + + printf(" (switch)"); + break; } } @@ -19526,12 +19542,28 @@ void Compiler::fgTableDispBasicBlock(BasicBlock* block, switch (block->bbCatchTyp) { - case BBCT_NONE: break; - case BBCT_FAULT: printf("fault "); cnt += 6; break; - case BBCT_FINALLY: printf("finally "); cnt += 8; break; - case BBCT_FILTER: printf("filter "); cnt += 7; break; - case BBCT_FILTER_HANDLER: printf("filtHnd "); cnt += 8; break; - default: printf("catch "); cnt += 6; break; + case BBCT_NONE: + break; + case BBCT_FAULT: + printf("fault "); + cnt += 6; + break; + case BBCT_FINALLY: + printf("finally "); + cnt += 8; + break; + case BBCT_FILTER: + printf("filter "); + cnt += 7; + break; + case BBCT_FILTER_HANDLER: + printf("filtHnd "); + cnt += 8; + break; + default: + printf("catch "); + cnt += 6; + break; } if (block->bbCatchTyp != BBCT_NONE) @@ -19548,9 +19580,7 @@ void Compiler::fgTableDispBasicBlock(BasicBlock* block, EHblkDsc* HBtab; EHblkDsc* HBtabEnd; - for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; - HBtab < HBtabEnd; - HBtab++) + for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++) { if (HBtab->ebdTryBeg == block) { @@ -19564,9 +19594,7 @@ void Compiler::fgTableDispBasicBlock(BasicBlock* block, EHblkDsc* HBtab; EHblkDsc* HBtabEnd; - for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; - HBtab < HBtabEnd; - HBtab++) + for (HBtab = compHndBBtab, HBtabEnd = compHndBBtab + compHndBBtabCount; HBtab < HBtabEnd; HBtab++) { if (HBtab->ebdTryLast == block) { @@ -19607,9 +19635,7 @@ void Compiler::fgTableDispBasicBlock(BasicBlock* block, Dump blocks from firstBlock to lastBlock. */ -void Compiler::fgDispBasicBlocks(BasicBlock* firstBlock, - BasicBlock* lastBlock, - bool dumpTrees) +void Compiler::fgDispBasicBlocks(BasicBlock* firstBlock, BasicBlock* lastBlock, bool dumpTrees) { BasicBlock* block; @@ -19627,24 +19653,27 @@ void Compiler::fgDispBasicBlocks(BasicBlock* firstBlock, if (block->bbFlags & BBF_PROF_WEIGHT) { int thisIbcWidth = CountDigits(block->bbWeight); - ibcColWidth = max(ibcColWidth, thisIbcWidth); + ibcColWidth = max(ibcColWidth, thisIbcWidth); } - if (block == lastBlock) { + if (block == lastBlock) + { break; - } + } } if (ibcColWidth > 0) { ibcColWidth = max(ibcColWidth, 3) + 1; // + 1 for the leading space } - unsigned bbNumMax = compIsForInlining() ? impInlineInfo->InlinerCompiler->fgBBNumMax : fgBBNumMax; - int maxBlockNumWidth = CountDigits(bbNumMax); - maxBlockNumWidth = max(maxBlockNumWidth, 2); + unsigned bbNumMax = compIsForInlining() ? impInlineInfo->InlinerCompiler->fgBBNumMax : fgBBNumMax; + int maxBlockNumWidth = CountDigits(bbNumMax); + maxBlockNumWidth = max(maxBlockNumWidth, 2); padWidth += maxBlockNumWidth - 2; // Account for functions with a large number of blocks. + // clang-format off + printf("\n"); printf("------%*s------------------------------------%*s-----------------------%*s----------------------------------------\n", padWidth, "------------", @@ -19665,9 +19694,9 @@ void Compiler::fgDispBasicBlocks(BasicBlock* firstBlock, ibcColWidth, "------------", maxBlockNumWidth, "----"); - for (block = firstBlock; - block; - block = block->bbNext) + // clang-format on + + for (block = firstBlock; block; block = block->bbNext) { // First, do some checking on the bbPrev links if (block->bbPrev) @@ -19681,36 +19710,34 @@ void Compiler::fgDispBasicBlocks(BasicBlock* firstBlock, { printf("bad prev link!\n"); } - + if (block == fgFirstColdBlock) { - printf("~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n", - padWidth, "~~~~~~~~~~~~", - ibcColWidth, "~~~~~~~~~~~~", - maxBlockNumWidth, "~~~~"); + printf("~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~~" + "~~~~~~~~~~~~~~~\n", + padWidth, "~~~~~~~~~~~~", ibcColWidth, "~~~~~~~~~~~~", maxBlockNumWidth, "~~~~"); } #if FEATURE_EH_FUNCLETS if (block == fgFirstFuncletBB) { - printf("++++++%*s++++++++++++++++++++++++++++++++++++%*s+++++++++++++++++++++++%*s++++++++++++++++++++++++++++++++++++++++ funclets follow\n", - padWidth, "++++++++++++", - ibcColWidth, "++++++++++++", - maxBlockNumWidth, "++++"); + printf("++++++%*s++++++++++++++++++++++++++++++++++++%*s+++++++++++++++++++++++%*s+++++++++++++++++++++++++" + "+++++++++++++++ funclets follow\n", + padWidth, "++++++++++++", ibcColWidth, "++++++++++++", maxBlockNumWidth, "++++"); } #endif // FEATURE_EH_FUNCLETS fgTableDispBasicBlock(block, ibcColWidth); - if (block == lastBlock) { + if (block == lastBlock) + { break; - } + } } - printf("------%*s------------------------------------%*s-----------------------%*s----------------------------------------\n", - padWidth, "------------", - ibcColWidth, "------------", - maxBlockNumWidth, "----"); + printf("------%*s------------------------------------%*s-----------------------%*s---------------------------------" + "-------\n", + padWidth, "------------", ibcColWidth, "------------", maxBlockNumWidth, "----"); if (dumpTrees) { @@ -19720,7 +19747,7 @@ void Compiler::fgDispBasicBlocks(BasicBlock* firstBlock, /*****************************************************************************/ -void Compiler::fgDispBasicBlocks(bool dumpTrees) +void Compiler::fgDispBasicBlocks(bool dumpTrees) { fgDispBasicBlocks(fgFirstBB, nullptr, dumpTrees); } @@ -19728,9 +19755,9 @@ void Compiler::fgDispBasicBlocks(bool dumpTrees) /*****************************************************************************/ // Increment the stmtNum and dump the tree using gtDispTree // -void Compiler::fgDumpStmtTree(GenTreePtr stmt, unsigned blkNum) +void Compiler::fgDumpStmtTree(GenTreePtr stmt, unsigned blkNum) { - compCurStmtNum++; // Increment the current stmtNum + compCurStmtNum++; // Increment the current stmtNum printf("\n***** BB%02u, stmt %d\n", blkNum, compCurStmtNum); @@ -19750,7 +19777,7 @@ void Compiler::fgDumpStmtTree(GenTreePtr stmt, unsigned blkNum) // Arguments: // block - The block to dump. // -void Compiler::fgDumpBlock(BasicBlock* block) +void Compiler::fgDumpBlock(BasicBlock* block) { printf("\n------------ "); block->dspBlockHeader(this); @@ -19762,7 +19789,7 @@ void Compiler::fgDumpBlock(BasicBlock* block) fgDumpStmtTree(stmt, block->bbNum); if (stmt == block->bbTreeList) { - block->bbStmtNum = compCurStmtNum; // Set the block->bbStmtNum + block->bbStmtNum = compCurStmtNum; // Set the block->bbStmtNum } } } @@ -19775,63 +19802,81 @@ void Compiler::fgDumpBlock(BasicBlock* block) /*****************************************************************************/ // Walk the BasicBlock list calling fgDumpTree once per Stmt // -void Compiler::fgDumpTrees(BasicBlock* firstBlock, - BasicBlock* lastBlock) +void Compiler::fgDumpTrees(BasicBlock* firstBlock, BasicBlock* lastBlock) { - compCurStmtNum = 0; // Reset the current stmtNum + compCurStmtNum = 0; // Reset the current stmtNum /* Walk the basic blocks */ - // Note that typically we have already called fgDispBasicBlocks() + // Note that typically we have already called fgDispBasicBlocks() // so we don't need to print the preds and succs again here // for (BasicBlock* block = firstBlock; block; block = block->bbNext) { fgDumpBlock(block); - if (block == lastBlock) { + if (block == lastBlock) + { break; + } } - } - printf("\n-------------------------------------------------------------------------------------------------------------------\n"); + printf("\n---------------------------------------------------------------------------------------------------------" + "----------\n"); } - /***************************************************************************** * Try to create as many candidates for GTF_MUL_64RSLT as possible. * We convert 'intOp1*intOp2' into 'int(long(nop(intOp1))*long(intOp2))'. */ /* static */ -Compiler::fgWalkResult Compiler::fgStress64RsltMulCB(GenTreePtr* pTree, fgWalkData* data) +Compiler::fgWalkResult Compiler::fgStress64RsltMulCB(GenTreePtr* pTree, fgWalkData* data) { - GenTreePtr tree = *pTree; + GenTreePtr tree = *pTree; Compiler* pComp = data->compiler; - - if (tree->gtOper != GT_MUL || tree->gtType != TYP_INT || (tree->gtOverflow())) { + + if (tree->gtOper != GT_MUL || tree->gtType != TYP_INT || (tree->gtOverflow())) + { return WALK_CONTINUE; -} + } + +#ifdef DEBUG + if (pComp->verbose) + { + printf("STRESS_64RSLT_MUL before:\n"); + pComp->gtDispTree(tree); + } +#endif // DEBUG // To ensure optNarrowTree() doesn't fold back to the original tree. - tree->gtOp.gtOp1 = pComp->gtNewOperNode(GT_NOP, TYP_LONG, tree->gtOp.gtOp1); tree->gtOp.gtOp1 = pComp->gtNewCastNode(TYP_LONG, tree->gtOp.gtOp1, TYP_LONG); - tree->gtOp.gtOp2 = pComp->gtNewCastNode(TYP_LONG, tree->gtOp.gtOp2, TYP_LONG); - tree->gtType = TYP_LONG; - *pTree = pComp->gtNewCastNode(TYP_INT, tree, TYP_INT); + tree->gtOp.gtOp1 = pComp->gtNewOperNode(GT_NOP, TYP_LONG, tree->gtOp.gtOp1); + tree->gtOp.gtOp1 = pComp->gtNewCastNode(TYP_LONG, tree->gtOp.gtOp1, TYP_LONG); + tree->gtOp.gtOp2 = pComp->gtNewCastNode(TYP_LONG, tree->gtOp.gtOp2, TYP_LONG); + tree->gtType = TYP_LONG; + *pTree = pComp->gtNewCastNode(TYP_INT, tree, TYP_INT); + +#ifdef DEBUG + if (pComp->verbose) + { + printf("STRESS_64RSLT_MUL after:\n"); + pComp->gtDispTree(*pTree); + } +#endif // DEBUG return WALK_SKIP_SUBTREES; } -void Compiler::fgStress64RsltMul() +void Compiler::fgStress64RsltMul() { - if (!compStressCompile(STRESS_64RSLT_MUL, 20)) { + if (!compStressCompile(STRESS_64RSLT_MUL, 20)) + { return; -} + } fgWalkAllTreesPre(fgStress64RsltMulCB, (void*)this); } - // This variable is used to generate "traversal labels": one-time constants with which // we label basic blocks that are members of the basic block list, in order to have a // fast, high-probability test for membership in that list. Type is "volatile" because @@ -19847,8 +19892,7 @@ static volatile int bbTraverseLabel = 1; * *****************************************************************************/ -void Compiler::fgDebugCheckBBlist(bool checkBBNum /* = false */, - bool checkBBRefs /* = true */) +void Compiler::fgDebugCheckBBlist(bool checkBBNum /* = false */, bool checkBBRefs /* = true */) { #ifdef DEBUG if (verbose) @@ -19858,7 +19902,7 @@ void Compiler::fgDebugCheckBBlist(bool checkBBNum /* = false */, #endif // DEBUG fgDebugCheckBlockLinks(); - + if (fgBBcount > 10000 && expensiveDebugCheckLevel < 1) { // The basic block checks are too expensive if there are too many blocks, @@ -19875,7 +19919,7 @@ void Compiler::fgDebugCheckBBlist(bool checkBBNum /* = false */, unsigned blockRefs; #if FEATURE_EH_FUNCLETS - bool reachedFirstFunclet = false; + bool reachedFirstFunclet = false; if (fgFuncletsCreated) { // @@ -19898,15 +19942,13 @@ void Compiler::fgDebugCheckBBlist(bool checkBBNum /* = false */, block->bbTraversalStamp = curTraversalStamp; } - for (prevBlock = nullptr, block = fgFirstBB; - block; - prevBlock = block, block = block->bbNext) + for (prevBlock = nullptr, block = fgFirstBB; block; prevBlock = block, block = block->bbNext) { blockRefs = 0; /* First basic block has countOfInEdges() >= 1 */ - if (block == fgFirstBB) + if (block == fgFirstBB) { noway_assert(block->countOfInEdges() >= 1); blockRefs = 1; @@ -19920,27 +19962,24 @@ void Compiler::fgDebugCheckBBlist(bool checkBBNum /* = false */, // If the block is a BBJ_COND, a BBJ_SWITCH or a // lowered GT_SWITCH_TABLE node then make sure it - // ends with a GT_JTRUE or a GT_SWITCH + // ends with a conditional jump or a GT_SWITCH if (block->bbJumpKind == BBJ_COND) { - noway_assert(block->lastNode()->gtNext == nullptr && block->lastNode()->gtOper == GT_JTRUE); + noway_assert(block->lastNode()->gtNext == nullptr && block->lastNode()->OperIsConditionalJump()); } else if (block->bbJumpKind == BBJ_SWITCH) { #ifndef LEGACY_BACKEND noway_assert(block->lastNode()->gtNext == nullptr && - (block->lastNode()->gtOper == GT_SWITCH || - block->lastNode()->gtOper == GT_SWITCH_TABLE)); -#else // LEGACY_BACKEND - noway_assert(block->lastStmt()->gtNext == NULL && - block->lastStmt()->gtStmtExpr->gtOper == GT_SWITCH); + (block->lastNode()->gtOper == GT_SWITCH || block->lastNode()->gtOper == GT_SWITCH_TABLE)); +#else // LEGACY_BACKEND + noway_assert(block->lastStmt()->gtNext == NULL && block->lastStmt()->gtStmtExpr->gtOper == GT_SWITCH); #endif // LEGACY_BACKEND } - else if (!( block->bbJumpKind == BBJ_ALWAYS - || block->bbJumpKind == BBJ_RETURN)) + else if (!(block->bbJumpKind == BBJ_ALWAYS || block->bbJumpKind == BBJ_RETURN)) { - //this block cannot have a poll + // this block cannot have a poll noway_assert(!(block->bbFlags & BBF_NEEDS_GCPOLL)); } @@ -19981,7 +20020,8 @@ void Compiler::fgDebugCheckBBlist(bool checkBBNum /* = false */, #endif // FEATURE_EH_FUNCLETS // Don't check cheap preds. - for (pred = (fgCheapPredsValid ? nullptr : block->bbPreds); pred != nullptr; blockRefs += pred->flDupCount, pred = pred->flNext) + for (pred = (fgCheapPredsValid ? nullptr : block->bbPreds); pred != nullptr; + blockRefs += pred->flDupCount, pred = pred->flNext) { assert(fgComputePredsDone); // If this isn't set, why do we have a preds list? @@ -19994,95 +20034,101 @@ void Compiler::fgDebugCheckBBlist(bool checkBBNum /* = false */, if (ehTryDsc != nullptr) { // You can jump to the start of a try - if (ehTryDsc->ebdTryBeg == block) { + if (ehTryDsc->ebdTryBeg == block) + { goto CHECK_HND; -} + } // You can jump within the same try region - if (bbInTryRegions(block->getTryIndex(), blockPred)) { + if (bbInTryRegions(block->getTryIndex(), blockPred)) + { goto CHECK_HND; -} + } // The catch block can jump back into the middle of the try - if (bbInCatchHandlerRegions(block, blockPred)) { + if (bbInCatchHandlerRegions(block, blockPred)) + { goto CHECK_HND; -} + } // The end of a finally region is a BBJ_EHFINALLYRET block (during importing, BBJ_LEAVE) which // is marked as "returning" to the BBJ_ALWAYS block following the BBJ_CALLFINALLY // block that does a local call to the finally. This BBJ_ALWAYS is within // the try region protected by the finally (for x86, ARM), but that's ok. - if (prevBlock->bbJumpKind == BBJ_CALLFINALLY && - block->bbJumpKind == BBJ_ALWAYS && - blockPred->bbJumpKind == BBJ_EHFINALLYRET) { + if (prevBlock->bbJumpKind == BBJ_CALLFINALLY && block->bbJumpKind == BBJ_ALWAYS && + blockPred->bbJumpKind == BBJ_EHFINALLYRET) + { goto CHECK_HND; -} + } - printf("Jump into the middle of try region: BB%02u branches to BB%02u\n", blockPred->bbNum, block->bbNum); + printf("Jump into the middle of try region: BB%02u branches to BB%02u\n", blockPred->bbNum, + block->bbNum); noway_assert(!"Jump into middle of try region"); } -CHECK_HND:; + CHECK_HND:; EHblkDsc* ehHndDsc = ehGetBlockHndDsc(block); if (ehHndDsc != nullptr) { // You can do a BBJ_EHFINALLYRET or BBJ_EHFILTERRET into a handler region - if ( (blockPred->bbJumpKind == BBJ_EHFINALLYRET) - || (blockPred->bbJumpKind == BBJ_EHFILTERRET)) { + if ((blockPred->bbJumpKind == BBJ_EHFINALLYRET) || (blockPred->bbJumpKind == BBJ_EHFILTERRET)) + { goto CHECK_JUMP; -} + } // Our try block can call our finally block - if ((block->bbCatchTyp == BBCT_FINALLY) && - (blockPred->bbJumpKind == BBJ_CALLFINALLY) && + if ((block->bbCatchTyp == BBCT_FINALLY) && (blockPred->bbJumpKind == BBJ_CALLFINALLY) && ehCallFinallyInCorrectRegion(blockPred, block->getHndIndex())) { goto CHECK_JUMP; } // You can jump within the same handler region - if (bbInHandlerRegions(block->getHndIndex(), blockPred)) { + if (bbInHandlerRegions(block->getHndIndex(), blockPred)) + { goto CHECK_JUMP; -} + } // A filter can jump to the start of the filter handler - if (ehHndDsc->HasFilter()) { + if (ehHndDsc->HasFilter()) + { goto CHECK_JUMP; -} + } - printf("Jump into the middle of handler region: BB%02u branches to BB%02u\n", blockPred->bbNum, block->bbNum); + printf("Jump into the middle of handler region: BB%02u branches to BB%02u\n", blockPred->bbNum, + block->bbNum); noway_assert(!"Jump into the middle of handler region"); } -CHECK_JUMP:; + CHECK_JUMP:; switch (blockPred->bbJumpKind) { - case BBJ_COND: - noway_assert(blockPred->bbNext == block || blockPred->bbJumpDest == block); - break; + case BBJ_COND: + noway_assert(blockPred->bbNext == block || blockPred->bbJumpDest == block); + break; - case BBJ_NONE: - noway_assert(blockPred->bbNext == block); - break; + case BBJ_NONE: + noway_assert(blockPred->bbNext == block); + break; - case BBJ_CALLFINALLY: - case BBJ_ALWAYS: - case BBJ_EHCATCHRET: - case BBJ_EHFILTERRET: - noway_assert(blockPred->bbJumpDest == block); - break; + case BBJ_CALLFINALLY: + case BBJ_ALWAYS: + case BBJ_EHCATCHRET: + case BBJ_EHFILTERRET: + noway_assert(blockPred->bbJumpDest == block); + break; - case BBJ_EHFINALLYRET: + case BBJ_EHFINALLYRET: { // If the current block is a successor to a BBJ_EHFINALLYRET (return from finally), // then the lexically previous block should be a call to the same finally. // Verify all of that. - unsigned hndIndex = blockPred->getHndIndex(); - EHblkDsc* ehDsc = ehGetDsc(hndIndex); - BasicBlock* finBeg = ehDsc->ebdHndBeg; + unsigned hndIndex = blockPred->getHndIndex(); + EHblkDsc* ehDsc = ehGetDsc(hndIndex); + BasicBlock* finBeg = ehDsc->ebdHndBeg; // Because there is no bbPrev, we have to search for the lexically previous // block. We can shorten the search by only looking in places where it is legal @@ -20094,13 +20140,15 @@ CHECK_JUMP:; for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext) { - if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg) { + if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg) + { continue; -} + } - if (block == bcall->bbNext) { + if (block == bcall->bbNext) + { goto PRED_OK; - } + } } #if FEATURE_EH_FUNCLETS @@ -20114,19 +20162,22 @@ CHECK_JUMP:; for (BasicBlock* bcall = fgFirstFuncletBB; bcall; bcall = bcall->bbNext) { - if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg) { + if (bcall->bbJumpKind != BBJ_CALLFINALLY || bcall->bbJumpDest != finBeg) + { continue; -} + } - if (block != bcall->bbNext) { + if (block != bcall->bbNext) + { continue; -} + } - if (ehCallFinallyInCorrectRegion(bcall, hndIndex)) { + if (ehCallFinallyInCorrectRegion(bcall, hndIndex)) + { goto PRED_OK; + } } } - } #endif // FEATURE_EH_FUNCLETS @@ -20134,34 +20185,34 @@ CHECK_JUMP:; } break; - case BBJ_THROW: - case BBJ_RETURN: - noway_assert(!"THROW and RETURN block cannot be in the predecessor list!"); - break; + case BBJ_THROW: + case BBJ_RETURN: + noway_assert(!"THROW and RETURN block cannot be in the predecessor list!"); + break; - case BBJ_SWITCH: - unsigned jumpCnt; jumpCnt = blockPred->bbJumpSwt->bbsCount; - BasicBlock** jumpTab; jumpTab = blockPred->bbJumpSwt->bbsDstTab; + case BBJ_SWITCH: + unsigned jumpCnt; + jumpCnt = blockPred->bbJumpSwt->bbsCount; + BasicBlock** jumpTab; + jumpTab = blockPred->bbJumpSwt->bbsDstTab; - do - { - if (block == *jumpTab) + do { - goto PRED_OK; - } - } - while (++jumpTab, --jumpCnt); + if (block == *jumpTab) + { + goto PRED_OK; + } + } while (++jumpTab, --jumpCnt); - noway_assert(!"SWITCH in the predecessor list with no jump label to BLOCK!"); - break; + noway_assert(!"SWITCH in the predecessor list with no jump label to BLOCK!"); + break; - default: - noway_assert(!"Unexpected bbJumpKind"); - break; + default: + noway_assert(!"Unexpected bbJumpKind"); + break; } -PRED_OK:; - + PRED_OK:; } /* Check the bbRefs */ @@ -20200,7 +20251,7 @@ PRED_OK:; copiedForGenericsCtxt = ((info.compMethodInfo->options & CORINFO_GENERICS_CTXT_FROM_THIS) != 0); #else // JIT32_GCENCODER copiedForGenericsCtxt = FALSE; -#endif // JIT32_GCENCODER +#endif // JIT32_GCENCODER // This if only in support of the noway_asserts it contains. if (info.compIsStatic) @@ -20213,16 +20264,18 @@ PRED_OK:; // For instance method: assert(info.compThisArg != BAD_VAR_NUM); bool compThisArgAddrExposedOK = !lvaTable[info.compThisArg].lvAddrExposed; + #ifndef JIT32_GCENCODER compThisArgAddrExposedOK = compThisArgAddrExposedOK || copiedForGenericsCtxt; -#endif // !JIT32_GCENCODER - noway_assert(compThisArgAddrExposedOK && // should never expose the address of arg 0 or - !lvaTable[info.compThisArg].lvArgWrite && // write to arg 0. - ( // In addition, - lvaArg0Var == info.compThisArg || // lvArg0Var should remain 0 if arg0 is not written to or address-exposed. - lvaArg0Var != info.compThisArg && - (lvaTable[lvaArg0Var].lvAddrExposed || lvaTable[lvaArg0Var].lvArgWrite || copiedForGenericsCtxt) - )); +#endif // !JIT32_GCENCODER + + // Should never expose the address of arg 0 or write to arg 0. + // In addition, lvArg0Var should remain 0 if arg0 is not + // written to or address-exposed. + noway_assert(compThisArgAddrExposedOK && !lvaTable[info.compThisArg].lvArgWrite && + (lvaArg0Var == info.compThisArg || + lvaArg0Var != info.compThisArg && (lvaTable[lvaArg0Var].lvAddrExposed || + lvaTable[lvaArg0Var].lvArgWrite || copiedForGenericsCtxt))); } } @@ -20232,40 +20285,40 @@ PRED_OK:; * ****************************************************************************/ -void Compiler::fgDebugCheckFlags(GenTreePtr tree) +void Compiler::fgDebugCheckFlags(GenTreePtr tree) { noway_assert(tree->gtOper != GT_STMT); - genTreeOps oper = tree->OperGet(); - unsigned kind = tree->OperKind(); - unsigned treeFlags = tree->gtFlags & GTF_ALL_EFFECT; - unsigned chkFlags = 0; + genTreeOps oper = tree->OperGet(); + unsigned kind = tree->OperKind(); + unsigned treeFlags = tree->gtFlags & GTF_ALL_EFFECT; + unsigned chkFlags = 0; /* Is this a leaf node? */ - if (kind & GTK_LEAF) + if (kind & GTK_LEAF) { switch (oper) { - case GT_CLS_VAR: - chkFlags |= GTF_GLOB_REF; - break; + case GT_CLS_VAR: + chkFlags |= GTF_GLOB_REF; + break; - case GT_CATCH_ARG: - chkFlags |= GTF_ORDER_SIDEEFF; - break; + case GT_CATCH_ARG: + chkFlags |= GTF_ORDER_SIDEEFF; + break; - default: - break; + default: + break; } } /* Is it a 'simple' unary/binary operator? */ - else if (kind & GTK_SMPOP) + else if (kind & GTK_SMPOP) { - GenTreePtr op1 = tree->gtOp.gtOp1; - GenTreePtr op2 = tree->gtGetOp2(); + GenTreePtr op1 = tree->gtOp.gtOp1; + GenTreePtr op2 = tree->gtGetOp2(); // During GS work, we make shadow copies for params. // In gsParamsToShadows(), we create a shadow var of TYP_INT for every small type param. @@ -20275,48 +20328,88 @@ void Compiler::fgDebugCheckFlags(GenTreePtr tree) // TYP_INT up to the GT_ASG tree is only correct if we don't need to propagate the TYP_INT back up. // The following checks will ensure this. - // Is the left child of "tree" a GT_ASG?, + // Is the left child of "tree" a GT_ASG? + // + // If parent is a TYP_VOID, we don't no need to propagate TYP_INT up. We are fine. + // (or) If GT_ASG is the left child of a GT_COMMA, the type of the GT_COMMA node will + // be determined by its right child. So we don't need to propagate TYP_INT up either. We are fine. if (op1 && op1->gtOper == GT_ASG) { - assert(tree->gtType == TYP_VOID || // If parent is a TYP_VOID, we don't no need to propagate TYP_INT up. We are fine. - tree->gtOper == GT_COMMA); // (or) If GT_ASG is the left child of a GT_COMMA, the type of the GT_COMMA node will - } // be determined by its right child. So we don't need to propagate TYP_INT up either. We are fine. + assert(tree->gtType == TYP_VOID || tree->gtOper == GT_COMMA); + } - // Is the right child of "tree" a GT_ASG?, + // Is the right child of "tree" a GT_ASG? + // + // If parent is a TYP_VOID, we don't no need to propagate TYP_INT up. We are fine. if (op2 && op2->gtOper == GT_ASG) { - assert(tree->gtType == TYP_VOID); // If parent is a TYP_VOID, we don't no need to propagate TYP_INT up. We are fine. + assert(tree->gtType == TYP_VOID); } switch (oper) { - case GT_QMARK: - if (op1->OperIsCompare()) - { - noway_assert(op1->gtFlags & GTF_DONT_CSE); - } - else - { - noway_assert( (op1->gtOper == GT_CNS_INT) && - ((op1->gtIntCon.gtIconVal == 0) || (op1->gtIntCon.gtIconVal == 1)) ); - } - break; + case GT_QMARK: + if (op1->OperIsCompare()) + { + noway_assert(op1->gtFlags & GTF_DONT_CSE); + } + else + { + noway_assert((op1->gtOper == GT_CNS_INT) && + ((op1->gtIntCon.gtIconVal == 0) || (op1->gtIntCon.gtIconVal == 1))); + } + break; - default: - break; + case GT_LIST: + case GT_FIELD_LIST: + if ((op2 != nullptr) && op2->OperIsAnyList()) + { + ArrayStack stack(this); + while ((tree->gtGetOp2() != nullptr) && tree->gtGetOp2()->OperIsAnyList()) + { + stack.Push(tree); + tree = tree->gtGetOp2(); + } + + fgDebugCheckFlags(tree); + + while (stack.Height() > 0) + { + tree = stack.Pop(); + assert((tree->gtFlags & GTF_REVERSE_OPS) == 0); + fgDebugCheckFlags(tree->gtOp.gtOp1); + chkFlags |= (tree->gtOp.gtOp1->gtFlags & GTF_ALL_EFFECT); + chkFlags |= (tree->gtGetOp2()->gtFlags & GTF_ALL_EFFECT); + fgDebugCheckFlagsHelper(tree, (tree->gtFlags & GTF_ALL_EFFECT), chkFlags); + } + + return; + } + break; + + default: + break; } /* Recursively check the subtrees */ - if (op1) { fgDebugCheckFlags(op1); -} - if (op2) { fgDebugCheckFlags(op2); -} + if (op1) + { + fgDebugCheckFlags(op1); + } + if (op2) + { + fgDebugCheckFlags(op2); + } - if (op1) { chkFlags |= (op1->gtFlags & GTF_ALL_EFFECT); -} - if (op2) { chkFlags |= (op2->gtFlags & GTF_ALL_EFFECT); -} + if (op1) + { + chkFlags |= (op1->gtFlags & GTF_ALL_EFFECT); + } + if (op2) + { + chkFlags |= (op2->gtFlags & GTF_ALL_EFFECT); + } // We reuse the value of GTF_REVERSE_OPS for a GT_IND-specific flag, // so exempt that (unary) operator. @@ -20331,7 +20424,7 @@ void Compiler::fgDebugCheckFlags(GenTreePtr tree) was set and thus GTF_ASG cannot be considered here. */ /* For a GT_ASG(GT_IND(x), y) we are interested in the side effects of x */ - GenTreePtr op1p; + GenTreePtr op1p; if ((kind & GTK_ASGOP) && (op1->gtOper == GT_IND)) { op1p = op1->gtOp.gtOp1; @@ -20355,20 +20448,18 @@ void Compiler::fgDebugCheckFlags(GenTreePtr tree) if (kind & GTK_ASGOP) { - chkFlags |= GTF_ASG; + chkFlags |= GTF_ASG; } /* Note that it is OK for treeFlags not to have a GTF_EXCEPT, AssertionProp's non-Null may have cleared it */ if (tree->OperMayThrow()) { - chkFlags |= (treeFlags & GTF_EXCEPT); + chkFlags |= (treeFlags & GTF_EXCEPT); } - if (oper == GT_ADDR && - (op1->OperIsLocal() || - op1->gtOper == GT_CLS_VAR || - (op1->gtOper == GT_IND && op1->gtOp.gtOp1->gtOper == GT_CLS_VAR_ADDR))) + if (oper == GT_ADDR && (op1->OperIsLocal() || op1->gtOper == GT_CLS_VAR || + (op1->gtOper == GT_IND && op1->gtOp.gtOp1->gtOper == GT_CLS_VAR_ADDR))) { /* &aliasedVar doesn't need GTF_GLOB_REF, though alisasedVar does. Similarly for clsVar */ @@ -20378,131 +20469,149 @@ void Compiler::fgDebugCheckFlags(GenTreePtr tree) /* See what kind of a special operator we have here */ - else { switch (tree->OperGet()) + else { - case GT_CALL: + switch (tree->OperGet()) + { + case GT_CALL: - GenTreePtr args; - GenTreePtr argx; - GenTreeCall* call; - - call = tree->AsCall(); + GenTreePtr args; + GenTreePtr argx; + GenTreeCall* call; - chkFlags |= GTF_CALL; + call = tree->AsCall(); - if ((treeFlags & GTF_EXCEPT) && !(chkFlags & GTF_EXCEPT)) - { - switch (eeGetHelperNum(tree->gtCall.gtCallMethHnd)) - { - // Is this a helper call that can throw an exception ? - case CORINFO_HELP_LDIV: - case CORINFO_HELP_LMOD: - case CORINFO_HELP_METHOD_ACCESS_CHECK: - case CORINFO_HELP_FIELD_ACCESS_CHECK: - case CORINFO_HELP_CLASS_ACCESS_CHECK: - case CORINFO_HELP_DELEGATE_SECURITY_CHECK: - chkFlags |= GTF_EXCEPT; - break; - default: - break; - } - } + chkFlags |= GTF_CALL; - if (call->gtCallObjp) - { - fgDebugCheckFlags(call->gtCallObjp); - chkFlags |= (call->gtCallObjp->gtFlags & GTF_SIDE_EFFECT); + if ((treeFlags & GTF_EXCEPT) && !(chkFlags & GTF_EXCEPT)) + { + switch (eeGetHelperNum(tree->gtCall.gtCallMethHnd)) + { + // Is this a helper call that can throw an exception ? + case CORINFO_HELP_LDIV: + case CORINFO_HELP_LMOD: + case CORINFO_HELP_METHOD_ACCESS_CHECK: + case CORINFO_HELP_FIELD_ACCESS_CHECK: + case CORINFO_HELP_CLASS_ACCESS_CHECK: + case CORINFO_HELP_DELEGATE_SECURITY_CHECK: + chkFlags |= GTF_EXCEPT; + break; + default: + break; + } + } - if (call->gtCallObjp->gtFlags & GTF_ASG) - { - treeFlags |= GTF_ASG; - } - } + if (call->gtCallObjp) + { + fgDebugCheckFlags(call->gtCallObjp); + chkFlags |= (call->gtCallObjp->gtFlags & GTF_SIDE_EFFECT); - for (args = call->gtCallArgs; args; args = args->gtOp.gtOp2) - { - argx = args->gtOp.gtOp1; - fgDebugCheckFlags(argx); + if (call->gtCallObjp->gtFlags & GTF_ASG) + { + treeFlags |= GTF_ASG; + } + } - chkFlags |= (argx->gtFlags & GTF_SIDE_EFFECT); + for (args = call->gtCallArgs; args; args = args->gtOp.gtOp2) + { + argx = args->gtOp.gtOp1; + fgDebugCheckFlags(argx); - if (argx->gtFlags & GTF_ASG) - { - treeFlags |= GTF_ASG; - } - } + chkFlags |= (argx->gtFlags & GTF_SIDE_EFFECT); - for (args = call->gtCallLateArgs; args; args = args->gtOp.gtOp2) - { - argx = args->gtOp.gtOp1; - fgDebugCheckFlags(argx); + if (argx->gtFlags & GTF_ASG) + { + treeFlags |= GTF_ASG; + } + } - chkFlags |= (argx->gtFlags & GTF_SIDE_EFFECT); + for (args = call->gtCallLateArgs; args; args = args->gtOp.gtOp2) + { + argx = args->gtOp.gtOp1; + fgDebugCheckFlags(argx); - if (argx->gtFlags & GTF_ASG) - { - treeFlags |= GTF_ASG; - } - } + chkFlags |= (argx->gtFlags & GTF_SIDE_EFFECT); - if ((call->gtCallType == CT_INDIRECT) && (call->gtCallCookie != nullptr)) - { - fgDebugCheckFlags(call->gtCallCookie); - chkFlags |= (call->gtCallCookie->gtFlags & GTF_SIDE_EFFECT); - } + if (argx->gtFlags & GTF_ASG) + { + treeFlags |= GTF_ASG; + } + } - if (call->gtCallType == CT_INDIRECT) - { - fgDebugCheckFlags(call->gtCallAddr); - chkFlags |= (call->gtCallAddr->gtFlags & GTF_SIDE_EFFECT); - } + if ((call->gtCallType == CT_INDIRECT) && (call->gtCallCookie != nullptr)) + { + fgDebugCheckFlags(call->gtCallCookie); + chkFlags |= (call->gtCallCookie->gtFlags & GTF_SIDE_EFFECT); + } - if (call->IsUnmanaged() && - (call->gtCallMoreFlags & GTF_CALL_M_UNMGD_THISCALL)) - { - if (call->gtCallArgs->gtOp.gtOp1->OperGet() == GT_NOP) - { - noway_assert(call->gtCallLateArgs->gtOp.gtOp1->TypeGet() == TYP_I_IMPL || - call->gtCallLateArgs->gtOp.gtOp1->TypeGet() == TYP_BYREF); - } - else - { - noway_assert(call->gtCallArgs->gtOp.gtOp1->TypeGet() == TYP_I_IMPL || - call->gtCallArgs->gtOp.gtOp1->TypeGet() == TYP_BYREF); - } - } - break; + if (call->gtCallType == CT_INDIRECT) + { + fgDebugCheckFlags(call->gtCallAddr); + chkFlags |= (call->gtCallAddr->gtFlags & GTF_SIDE_EFFECT); + } - case GT_ARR_ELEM: + if (call->IsUnmanaged() && (call->gtCallMoreFlags & GTF_CALL_M_UNMGD_THISCALL)) + { + if (call->gtCallArgs->gtOp.gtOp1->OperGet() == GT_NOP) + { + noway_assert(call->gtCallLateArgs->gtOp.gtOp1->TypeGet() == TYP_I_IMPL || + call->gtCallLateArgs->gtOp.gtOp1->TypeGet() == TYP_BYREF); + } + else + { + noway_assert(call->gtCallArgs->gtOp.gtOp1->TypeGet() == TYP_I_IMPL || + call->gtCallArgs->gtOp.gtOp1->TypeGet() == TYP_BYREF); + } + } + break; - GenTreePtr arrObj; - unsigned dim; + case GT_ARR_ELEM: - arrObj = tree->gtArrElem.gtArrObj; - fgDebugCheckFlags(arrObj); - chkFlags |= (arrObj->gtFlags & GTF_ALL_EFFECT); + GenTreePtr arrObj; + unsigned dim; - for (dim = 0; dim < tree->gtArrElem.gtArrRank; dim++) - { - fgDebugCheckFlags(tree->gtArrElem.gtArrInds[dim]); - chkFlags |= tree->gtArrElem.gtArrInds[dim]->gtFlags & GTF_ALL_EFFECT; - } - break; + arrObj = tree->gtArrElem.gtArrObj; + fgDebugCheckFlags(arrObj); + chkFlags |= (arrObj->gtFlags & GTF_ALL_EFFECT); - case GT_ARR_OFFSET: - fgDebugCheckFlags(tree->gtArrOffs.gtOffset); - chkFlags |= (tree->gtArrOffs.gtOffset->gtFlags & GTF_ALL_EFFECT); - fgDebugCheckFlags(tree->gtArrOffs.gtIndex); - chkFlags |= (tree->gtArrOffs.gtIndex->gtFlags & GTF_ALL_EFFECT); - fgDebugCheckFlags(tree->gtArrOffs.gtArrObj); - chkFlags |= (tree->gtArrOffs.gtArrObj->gtFlags & GTF_ALL_EFFECT); - break; + for (dim = 0; dim < tree->gtArrElem.gtArrRank; dim++) + { + fgDebugCheckFlags(tree->gtArrElem.gtArrInds[dim]); + chkFlags |= tree->gtArrElem.gtArrInds[dim]->gtFlags & GTF_ALL_EFFECT; + } + break; - default: - break; + case GT_ARR_OFFSET: + fgDebugCheckFlags(tree->gtArrOffs.gtOffset); + chkFlags |= (tree->gtArrOffs.gtOffset->gtFlags & GTF_ALL_EFFECT); + fgDebugCheckFlags(tree->gtArrOffs.gtIndex); + chkFlags |= (tree->gtArrOffs.gtIndex->gtFlags & GTF_ALL_EFFECT); + fgDebugCheckFlags(tree->gtArrOffs.gtArrObj); + chkFlags |= (tree->gtArrOffs.gtArrObj->gtFlags & GTF_ALL_EFFECT); + break; + + default: + break; + } } + + fgDebugCheckFlagsHelper(tree, treeFlags, chkFlags); } +//------------------------------------------------------------------------------ +// fgDebugCheckFlagsHelper : Check if all bits that are set in chkFlags are also set in treeFlags. +// +// +// Arguments: +// tree - Tree whose flags are being checked +// treeFlags - Actual flags on the tree +// chkFlags - Expected flags +// +// Note: +// Checking that all bits that are set in treeFlags are also set in chkFlags is currently disabled. + +void Compiler::fgDebugCheckFlagsHelper(GenTreePtr tree, unsigned treeFlags, unsigned chkFlags) +{ if (chkFlags & ~treeFlags) { // Print the tree so we can see it in the log. @@ -20524,12 +20633,12 @@ void Compiler::fgDebugCheckFlags(GenTreePtr tree) #if 0 // TODO-Cleanup: /* The tree has extra flags set. However, this will happen if we - replace a subtree with something, but don't clear the flags up - the tree. Can't flag this unless we start clearing flags above. + replace a subtree with something, but don't clear the flags up + the tree. Can't flag this unless we start clearing flags above. - Note: we need this working for GTF_CALL and CSEs, so I'm enabling - it for calls. - */ + Note: we need this working for GTF_CALL and CSEs, so I'm enabling + it for calls. + */ if (tree->OperGet() != GT_CALL && (treeFlags & GTF_CALL) && !(chkFlags & GTF_CALL)) { // Print the tree so we can see it in the log. @@ -20545,7 +20654,7 @@ void Compiler::fgDebugCheckFlags(GenTreePtr tree) GenTree::gtDispFlags(treeFlags & ~chkFlags, GTF_DEBUG_NONE); printf("\n"); gtDispTree(tree); - } + } #endif // 0 } } @@ -20569,14 +20678,13 @@ void Compiler::fgDebugCheckNodeLinks(BasicBlock* block, GenTree* node) noway_assert(stmt->gtStmtList); // The first node's gtPrev must be nullptr (the gtPrev list is not circular). - // The last node's gtNext must be nullptr (the gtNext list is not circular). This is tested if the loop below terminates. + // The last node's gtNext must be nullptr (the gtNext list is not circular). This is tested if the loop below + // terminates. assert(stmt->gtStmtList->gtPrev == nullptr); - for (GenTreePtr tree = stmt->gtStmtList; - tree != nullptr; - tree = tree->gtNext) + for (GenTreePtr tree = stmt->gtStmtList; tree != nullptr; tree = tree->gtNext) { - if (tree->gtPrev) + if (tree->gtPrev) { noway_assert(tree->gtPrev->gtNext == tree); } @@ -20585,7 +20693,7 @@ void Compiler::fgDebugCheckNodeLinks(BasicBlock* block, GenTree* node) noway_assert(tree == stmt->gtStmtList); } - if (tree->gtNext) + if (tree->gtNext) { noway_assert(tree->gtNext->gtPrev == tree); } @@ -20621,40 +20729,40 @@ void Compiler::fgDebugCheckNodeLinks(BasicBlock* block, GenTree* node) { switch (tree->gtOper) { - case GT_QMARK: - expectedPrevTree = tree->gtOp.gtOp2->AsColon()->ThenNode(); // "then" operand of the GT_COLON (generated second). - break; + case GT_QMARK: + expectedPrevTree = + tree->gtOp.gtOp2->AsColon()->ThenNode(); // "then" operand of the GT_COLON (generated second). + break; - case GT_COLON: - expectedPrevTree = tree->AsColon()->ElseNode(); // "else" branch result (generated first). - break; + case GT_COLON: + expectedPrevTree = tree->AsColon()->ElseNode(); // "else" branch result (generated first). + break; - default: - if (tree->gtOp.gtOp2) - { - if (tree->gtFlags & GTF_REVERSE_OPS) + default: + if (tree->gtOp.gtOp2) { - expectedPrevTree = tree->gtOp.gtOp1; + if (tree->gtFlags & GTF_REVERSE_OPS) + { + expectedPrevTree = tree->gtOp.gtOp1; + } + else + { + expectedPrevTree = tree->gtOp.gtOp2; + } } else { - expectedPrevTree = tree->gtOp.gtOp2; + expectedPrevTree = tree->gtOp.gtOp1; } - } - else - { - expectedPrevTree = tree->gtOp.gtOp1; - } - break; + break; } } - noway_assert(expectedPrevTree == nullptr || // No expectations about the prev node - tree->gtPrev == expectedPrevTree); // The "normal" case + noway_assert(expectedPrevTree == nullptr || // No expectations about the prev node + tree->gtPrev == expectedPrevTree); // The "normal" case } } - /***************************************************************************** * * A DEBUG routine to check the correctness of the links between GT_STMT nodes @@ -20662,15 +20770,14 @@ void Compiler::fgDebugCheckNodeLinks(BasicBlock* block, GenTree* node) * ****************************************************************************/ -void Compiler::fgDebugCheckLinks(bool morphTrees) +void Compiler::fgDebugCheckLinks(bool morphTrees) { // This used to be only on for stress, and there was a comment stating that // it was "quite an expensive operation" but I did not find that to be true. // Set DO_SANITY_DEBUG_CHECKS to false to revert to that behavior. const bool DO_SANITY_DEBUG_CHECKS = true; - if (!DO_SANITY_DEBUG_CHECKS && - !compStressCompile(STRESS_CHK_FLOW_UPDATE, 30)) + if (!DO_SANITY_DEBUG_CHECKS && !compStressCompile(STRESS_CHK_FLOW_UPDATE, 30)) { return; } @@ -20680,7 +20787,7 @@ void Compiler::fgDebugCheckLinks(bool morphTrees) /* For each basic block check the bbTreeList links */ for (BasicBlock* block = fgFirstBB; block; block = block->bbNext) { -PROCESS_BLOCK_AGAIN:; + PROCESS_BLOCK_AGAIN:; if (block->IsLIR()) { LIR::AsRange(block).CheckLIR(this); @@ -20690,11 +20797,12 @@ PROCESS_BLOCK_AGAIN:; for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt) { /* Verify that bbTreeList is threaded correctly */ - /* Note that for the GT_STMT list, the gtPrev list is circular. The gtNext list is not: gtNext of the last GT_STMT in a block is nullptr. */ + /* Note that for the GT_STMT list, the gtPrev list is circular. The gtNext list is not: gtNext of the + * last GT_STMT in a block is nullptr. */ noway_assert(stmt->gtPrev); - if (stmt == block->bbTreeList) + if (stmt == block->bbTreeList) { noway_assert(stmt->gtPrev->gtNext == nullptr); } @@ -20703,7 +20811,7 @@ PROCESS_BLOCK_AGAIN:; noway_assert(stmt->gtPrev->gtNext == stmt); } - if (stmt->gtNext) + if (stmt->gtNext) { noway_assert(stmt->gtNext->gtPrev == stmt); } @@ -20782,9 +20890,9 @@ void Compiler::fgDebugCheckBlockLinks() // Create a set with all the successors. Don't use BlockSet, so we don't need to worry // about the BlockSet epoch. BitVecTraits bitVecTraits(fgBBNumMax + 1, this); - BitVec BITVEC_INIT_NOCOPY(succBlocks, BitVecOps::MakeEmpty(&bitVecTraits)); + BitVec BITVEC_INIT_NOCOPY(succBlocks, BitVecOps::MakeEmpty(&bitVecTraits)); BasicBlock** jumpTable = block->bbJumpSwt->bbsDstTab; - unsigned jumpCount = block->bbJumpSwt->bbsCount; + unsigned jumpCount = block->bbJumpSwt->bbsCount; for (unsigned i = 0; i < jumpCount; i++) { BitVecOps::AddElemD(&bitVecTraits, succBlocks, jumpTable[i]->bbNum); @@ -20822,10 +20930,10 @@ void Compiler::fgDebugCheckBlockLinks() // Likewise the depth limit is a policy consideration, and serves mostly // as a safeguard to prevent runaway inlining of small methods. -unsigned Compiler::fgCheckInlineDepthAndRecursion(InlineInfo* inlineInfo) +unsigned Compiler::fgCheckInlineDepthAndRecursion(InlineInfo* inlineInfo) { BYTE* candidateCode = inlineInfo->inlineCandidateInfo->methInfo.ILCode; - InlineContext* inlineContext = inlineInfo->iciStmt->gtStmt.gtInlineContext; + InlineContext* inlineContext = inlineInfo->iciStmt->gtInlineContext; InlineResult* inlineResult = inlineInfo->inlineResult; // There should be a context for all candidates. @@ -20860,17 +20968,18 @@ unsigned Compiler::fgCheckInlineDepthAndRecursion(InlineInfo* inlineInfo) * Inlining phase */ - -void Compiler::fgInline() +void Compiler::fgInline() { - if (!opts.OptEnabled(CLFLG_INLINING)) { + if (!opts.OptEnabled(CLFLG_INLINING)) + { return; -} + } #ifdef DEBUG - if (verbose) { + if (verbose) + { printf("*************** In fgInline()\n"); -} + } #endif // DEBUG BasicBlock* block = fgFirstBB; @@ -20881,9 +20990,7 @@ void Compiler::fgInline() for (; block != nullptr; block = block->bbNext) { - for (GenTreeStmt* stmt = block->firstStmt(); - stmt; - stmt = stmt->gtNextStmt) + for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt) { stmt->gtInlineContext = rootContext; } @@ -20901,9 +21008,7 @@ void Compiler::fgInline() GenTreeStmt* stmt; GenTreePtr expr; - for (stmt = block->firstStmt(); - stmt != nullptr; - stmt = stmt->gtNextStmt) + for (stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt) { expr = stmt->gtStmtExpr; @@ -20932,14 +21037,11 @@ void Compiler::fgInline() } // See if we need to replace the return value place holder. - fgWalkTreePre(&stmt->gtStmtExpr, - fgUpdateInlineReturnExpressionPlaceHolder, - (void *) this); + fgWalkTreePre(&stmt->gtStmtExpr, fgUpdateInlineReturnExpressionPlaceHolder, (void*)this); // See if stmt is of the form GT_COMMA(call, nop) - // If yes, we can get rid of GT_COMMA. - if (expr->OperGet() == GT_COMMA && - expr->gtOp.gtOp1->OperGet() == GT_CALL && + // If yes, we can get rid of GT_COMMA. + if (expr->OperGet() == GT_COMMA && expr->gtOp.gtOp1->OperGet() == GT_CALL && expr->gtOp.gtOp2->OperGet() == GT_NOP) { stmt->gtStmtExpr = expr->gtOp.gtOp1; @@ -20961,9 +21063,7 @@ void Compiler::fgInline() { GenTreeStmt* stmt; - for (stmt = block->firstStmt(); - stmt; - stmt = stmt->gtNextStmt) + for (stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt) { // Call Compiler::fgDebugCheckInlineCandidates on each node fgWalkTreePre(&stmt->gtStmtExpr, fgDebugCheckInlineCandidates); @@ -20975,17 +21075,17 @@ void Compiler::fgInline() fgVerifyHandlerTab(); - if (verbose) + if (verbose) { printf("*************** After fgInline()\n"); fgDispBasicBlocks(true); fgDispHandlerTab(); } - if (verbose || fgPrintInlinedMethods) + if (verbose || fgPrintInlinedMethods) { - printf("**************** Inline Tree\n"); - m_inlineStrategy->Dump(); + printf("**************** Inline Tree\n"); + m_inlineStrategy->Dump(); } #endif // DEBUG @@ -21007,14 +21107,13 @@ void Compiler::fgInline() // Note: // Invokes fgNoteNonInlineCandidate on the nodes it finds. -Compiler::fgWalkResult Compiler::fgFindNonInlineCandidate(GenTreePtr* pTree, - fgWalkData* data) +Compiler::fgWalkResult Compiler::fgFindNonInlineCandidate(GenTreePtr* pTree, fgWalkData* data) { GenTreePtr tree = *pTree; if (tree->gtOper == GT_CALL) { Compiler* compiler = data->compiler; - GenTreePtr stmt = (GenTreePtr) data->pCallbackData; + GenTreeStmt* stmt = (GenTreeStmt*)data->pCallbackData; GenTreeCall* call = tree->AsCall(); compiler->fgNoteNonInlineCandidate(stmt, call); @@ -21027,17 +21126,16 @@ Compiler::fgWalkResult Compiler::fgFindNonInlineCandidate(GenTreePtr* pTree // not marked as inline candidates. // // Arguments: -// tree - statement containing the call +// stmt - statement containing the call // call - the call itself // // Notes: // Used in debug only to try and place descriptions of inline failures // into the proper context in the inline tree. -void Compiler::fgNoteNonInlineCandidate(GenTreePtr tree, - GenTreeCall* call) +void Compiler::fgNoteNonInlineCandidate(GenTreeStmt* stmt, GenTreeCall* call) { - InlineResult inlineResult(this, call, nullptr, "fgNotInlineCandidate"); + InlineResult inlineResult(this, call, nullptr, "fgNotInlineCandidate"); InlineObservation currentObservation = InlineObservation::CALLSITE_NOT_CANDIDATE; // Try and recover the reason left behind when the jit decided @@ -21070,7 +21168,7 @@ void Compiler::fgNoteNonInlineCandidate(GenTreePtr tree, if (call->gtCallType == CT_USER_FUNC) { // Create InlineContext for the failure - m_inlineStrategy->NewFailure(tree, &inlineResult); + m_inlineStrategy->NewFailure(stmt, &inlineResult); } } @@ -21088,12 +21186,8 @@ void Compiler::fgNoteNonInlineCandidate(GenTreePtr tree, */ GenTreePtr Compiler::fgGetStructAsStructPtr(GenTreePtr tree) { - noway_assert((tree->gtOper == GT_LCL_VAR) || - (tree->gtOper == GT_FIELD) || - (tree->gtOper == GT_IND) || - (tree->gtOper == GT_BLK) || - (tree->gtOper == GT_OBJ) || - tree->OperIsSIMD() || + noway_assert((tree->gtOper == GT_LCL_VAR) || (tree->gtOper == GT_FIELD) || (tree->gtOper == GT_IND) || + (tree->gtOper == GT_BLK) || (tree->gtOper == GT_OBJ) || tree->OperIsSIMD() || // tree->gtOper == GT_CALL || cannot get address of call. // tree->gtOper == GT_MKREFANY || inlining should've been aborted due to mkrefany opcode. // tree->gtOper == GT_RET_EXPR || cannot happen after fgUpdateInlineReturnExpressionPlaceHolder @@ -21101,18 +21195,18 @@ GenTreePtr Compiler::fgGetStructAsStructPtr(GenTreePtr tree) switch (tree->OperGet()) { - case GT_BLK: - case GT_OBJ: - case GT_IND: - return tree->gtOp.gtOp1; + case GT_BLK: + case GT_OBJ: + case GT_IND: + return tree->gtOp.gtOp1; - case GT_COMMA: - tree->gtOp.gtOp2 = fgGetStructAsStructPtr(tree->gtOp.gtOp2); - tree->gtType = TYP_BYREF; - return tree; + case GT_COMMA: + tree->gtOp.gtOp2 = fgGetStructAsStructPtr(tree->gtOp.gtOp2); + tree->gtType = TYP_BYREF; + return tree; - default: - return gtNewOperNode(GT_ADDR, TYP_BYREF, tree); + default: + return gtNewOperNode(GT_ADDR, TYP_BYREF, tree); } } @@ -21137,15 +21231,15 @@ GenTreePtr Compiler::fgAssignStructInlineeToVar(GenTreePtr child, CORINFO_CLASS_ // we have a ", , , call()" -- this is very defensive as we may never get // an inlinee that is made of commas. If the inlinee is not a call, then // we use a copy block to do the assignment. - GenTreePtr src = child; - GenTreePtr lastComma = NULL; + GenTreePtr src = child; + GenTreePtr lastComma = nullptr; while (src->gtOper == GT_COMMA) { lastComma = src; - src = src->gtOp.gtOp2; + src = src->gtOp.gtOp2; } - GenTreePtr newInlinee = NULL; + GenTreePtr newInlinee = nullptr; if (src->gtOper == GT_CALL) { // If inlinee was just a call, new inlinee is v05 = call() @@ -21162,16 +21256,16 @@ GenTreePtr Compiler::fgAssignStructInlineeToVar(GenTreePtr child, CORINFO_CLASS_ if (child->gtOper == GT_COMMA) { lastComma->gtOp.gtOp2 = newInlinee; - newInlinee = child; + newInlinee = child; } } else { // Inlinee is not a call, so just create a copy block to the tmp. - src = child; + src = child; GenTreePtr dstAddr = fgGetStructAsStructPtr(dst); GenTreePtr srcAddr = fgGetStructAsStructPtr(src); - newInlinee = gtNewCpObjNode(dstAddr, srcAddr, retClsHnd, false); + newInlinee = gtNewCpObjNode(dstAddr, srcAddr, retClsHnd, false); } GenTreePtr production = gtNewLclvNode(tmpNum, structType); @@ -21197,15 +21291,17 @@ void Compiler::fgAttachStructInlineeToAsg(GenTreePtr tree, GenTreePtr child, COR assert(tree->gtOper == GT_ASG); // We have an assignment, we codegen only V05 = call(). - if (child->gtOper == GT_CALL && tree->gtOp.gtOp1->gtOper == GT_LCL_VAR) + // However, if it is a multireg return on x64/ux we want to assign it to a temp. + if (child->gtOper == GT_CALL && tree->gtOp.gtOp1->gtOper == GT_LCL_VAR && !child->AsCall()->HasMultiRegRetVal()) { return; } GenTreePtr dstAddr = fgGetStructAsStructPtr(tree->gtOp.gtOp1); - GenTreePtr srcAddr = fgGetStructAsStructPtr((child->gtOper == GT_CALL) - ? fgAssignStructInlineeToVar(child, retClsHnd) // Assign to a variable if it is a call. - : child); // Just get the address, if not a call. + GenTreePtr srcAddr = fgGetStructAsStructPtr( + (child->gtOper == GT_CALL) + ? fgAssignStructInlineeToVar(child, retClsHnd) // Assign to a variable if it is a call. + : child); // Just get the address, if not a call. tree->CopyFrom(gtNewCpObjNode(dstAddr, srcAddr, retClsHnd, false), this); } @@ -21217,16 +21313,15 @@ void Compiler::fgAttachStructInlineeToAsg(GenTreePtr tree, GenTreePtr child, COR */ /* static */ -Compiler::fgWalkResult Compiler::fgUpdateInlineReturnExpressionPlaceHolder(GenTreePtr* pTree, - fgWalkData* data) +Compiler::fgWalkResult Compiler::fgUpdateInlineReturnExpressionPlaceHolder(GenTreePtr* pTree, fgWalkData* data) { - GenTreePtr tree = *pTree; - Compiler* comp = data->compiler; + GenTreePtr tree = *pTree; + Compiler* comp = data->compiler; CORINFO_CLASS_HANDLE retClsHnd = NO_CLASS_HANDLE; if (tree->gtOper == GT_RET_EXPR) { - // We are going to copy the tree from the inlinee, + // We are going to copy the tree from the inlinee, // so record the handle now. // if (varTypeIsStruct(tree)) @@ -21242,7 +21337,7 @@ Compiler::fgWalkResult Compiler::fgUpdateInlineReturnExpressionPlaceHolder( #ifdef DEBUG if (comp->verbose) { - printf("\nReplacing the return expression placeholder "); + printf("\nReplacing the return expression placeholder "); printTreeID(tree); printf(" with "); printTreeID(inlineCandidate); @@ -21252,7 +21347,7 @@ Compiler::fgWalkResult Compiler::fgUpdateInlineReturnExpressionPlaceHolder( } #endif // DEBUG - tree->CopyFrom(inlineCandidate, comp); + tree->CopyFrom(inlineCandidate, comp); #ifdef DEBUG if (comp->verbose) @@ -21262,8 +21357,7 @@ Compiler::fgWalkResult Compiler::fgUpdateInlineReturnExpressionPlaceHolder( printf("\n"); } #endif // DEBUG - } - while (tree->gtOper == GT_RET_EXPR); + } while (tree->gtOper == GT_RET_EXPR); } #if FEATURE_MULTIREG_RET @@ -21305,15 +21399,12 @@ Compiler::fgWalkResult Compiler::fgUpdateInlineReturnExpressionPlaceHolder( if ((tree->gtOper == GT_ASG) && (tree->gtOp.gtOp2->gtOper == GT_COMMA)) { GenTreePtr comma; - for (comma = tree->gtOp.gtOp2; - comma->gtOper == GT_COMMA; - comma = comma->gtOp.gtOp2) + for (comma = tree->gtOp.gtOp2; comma->gtOper == GT_COMMA; comma = comma->gtOp.gtOp2) { // empty } - noway_assert(!varTypeIsStruct(comma) || - comma->gtOper != GT_RET_EXPR || + noway_assert(!varTypeIsStruct(comma) || comma->gtOper != GT_RET_EXPR || !comp->IsMultiRegReturnedType(comma->gtRetExpr.gtRetClsHnd)); } @@ -21330,8 +21421,7 @@ Compiler::fgWalkResult Compiler::fgUpdateInlineReturnExpressionPlaceHolder( */ /* static */ -Compiler::fgWalkResult Compiler::fgDebugCheckInlineCandidates(GenTreePtr* pTree, - fgWalkData* data) +Compiler::fgWalkResult Compiler::fgDebugCheckInlineCandidates(GenTreePtr* pTree, fgWalkData* data) { GenTreePtr tree = *pTree; if (tree->gtOper == GT_CALL) @@ -21348,9 +21438,7 @@ Compiler::fgWalkResult Compiler::fgDebugCheckInlineCandidates(GenTreePtr* p #endif // DEBUG - -void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call, - InlineResult* inlineResult) +void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call, InlineResult* inlineResult) { noway_assert(call->gtOper == GT_CALL); noway_assert((call->gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0); @@ -21393,92 +21481,95 @@ void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call, // Set the trap to catch all errors (including recoverable ones from the EE) struct Param { - Compiler* pThis; - GenTree* call; + Compiler* pThis; + GenTree* call; CORINFO_METHOD_HANDLE fncHandle; - InlineCandidateInfo* inlineCandidateInfo; - InlineInfo* inlineInfo; + InlineCandidateInfo* inlineCandidateInfo; + InlineInfo* inlineInfo; } param = {nullptr}; - param.pThis = this; - param.call = call; - param.fncHandle = fncHandle; + param.pThis = this; + param.call = call; + param.fncHandle = fncHandle; param.inlineCandidateInfo = inlineCandidateInfo; - param.inlineInfo = &inlineInfo; - bool success = eeRunWithErrorTrap([](Param* pParam) - { - // Init the local var info of the inlinee - pParam->pThis->impInlineInitVars(pParam->inlineInfo); + param.inlineInfo = &inlineInfo; + bool success = eeRunWithErrorTrap( + [](Param* pParam) { + // Init the local var info of the inlinee + pParam->pThis->impInlineInitVars(pParam->inlineInfo); - if (pParam->inlineInfo->inlineResult->IsCandidate()) - { - /* Clear the temp table */ - memset(pParam->inlineInfo->lclTmpNum, -1, sizeof(pParam->inlineInfo->lclTmpNum)); + if (pParam->inlineInfo->inlineResult->IsCandidate()) + { + /* Clear the temp table */ + memset(pParam->inlineInfo->lclTmpNum, -1, sizeof(pParam->inlineInfo->lclTmpNum)); - // - // Prepare the call to jitNativeCode - // + // + // Prepare the call to jitNativeCode + // - pParam->inlineInfo->InlinerCompiler = pParam->pThis; - if (pParam->pThis->impInlineInfo == nullptr) - { - pParam->inlineInfo->InlineRoot = pParam->pThis; - } - else - { - pParam->inlineInfo->InlineRoot = pParam->pThis->impInlineInfo->InlineRoot; - } - pParam->inlineInfo->argCnt = pParam->inlineCandidateInfo->methInfo.args.totalILArgs(); - pParam->inlineInfo->tokenLookupContextHandle = pParam->inlineCandidateInfo->exactContextHnd; + pParam->inlineInfo->InlinerCompiler = pParam->pThis; + if (pParam->pThis->impInlineInfo == nullptr) + { + pParam->inlineInfo->InlineRoot = pParam->pThis; + } + else + { + pParam->inlineInfo->InlineRoot = pParam->pThis->impInlineInfo->InlineRoot; + } + pParam->inlineInfo->argCnt = pParam->inlineCandidateInfo->methInfo.args.totalILArgs(); + pParam->inlineInfo->tokenLookupContextHandle = pParam->inlineCandidateInfo->exactContextHnd; + + JITLOG_THIS(pParam->pThis, + (LL_INFO100000, "INLINER: inlineInfo.tokenLookupContextHandle for %s set to 0x%p:\n", + pParam->pThis->eeGetMethodFullName(pParam->fncHandle), + pParam->pThis->dspPtr(pParam->inlineInfo->tokenLookupContextHandle))); - JITLOG_THIS(pParam->pThis, - (LL_INFO100000, - "INLINER: inlineInfo.tokenLookupContextHandle for %s set to 0x%p:\n", - pParam->pThis->eeGetMethodFullName(pParam->fncHandle), - pParam->pThis->dspPtr(pParam->inlineInfo->tokenLookupContextHandle))); + JitFlags compileFlagsForInlinee = *pParam->pThis->opts.jitFlags; - CORJIT_FLAGS compileFlagsForInlinee; - memcpy(&compileFlagsForInlinee, pParam->pThis->opts.jitFlags, sizeof(compileFlagsForInlinee)); - compileFlagsForInlinee.corJitFlags &= ~CORJIT_FLG_LOST_WHEN_INLINING; - compileFlagsForInlinee.corJitFlags |= CORJIT_FLG_SKIP_VERIFICATION; + // The following flags are lost when inlining. + // (This is checked in Compiler::compInitOptions().) + compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_BBOPT); + compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_BBINSTR); + compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_PROF_ENTERLEAVE); + compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_DEBUG_EnC); + compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_DEBUG_INFO); + + compileFlagsForInlinee.Set(JitFlags::JIT_FLAG_SKIP_VERIFICATION); #ifdef DEBUG - if (pParam->pThis->verbose) - { - printf("\nInvoking compiler for the inlinee method %s :\n", - pParam->pThis->eeGetMethodFullName(pParam->fncHandle)); - } + if (pParam->pThis->verbose) + { + printf("\nInvoking compiler for the inlinee method %s :\n", + pParam->pThis->eeGetMethodFullName(pParam->fncHandle)); + } #endif // DEBUG - int result = jitNativeCode(pParam->fncHandle, - pParam->inlineCandidateInfo->methInfo.scope, - pParam->pThis->info.compCompHnd, - &pParam->inlineCandidateInfo->methInfo, - (void**)pParam->inlineInfo, - nullptr, - &compileFlagsForInlinee, - pParam->inlineInfo); - - if (result != CORJIT_OK) - { - // If we haven't yet determined why this inline fails, use - // a catch-all something bad happened observation. - InlineResult* innerInlineResult = pParam->inlineInfo->inlineResult; + int result = + jitNativeCode(pParam->fncHandle, pParam->inlineCandidateInfo->methInfo.scope, + pParam->pThis->info.compCompHnd, &pParam->inlineCandidateInfo->methInfo, + (void**)pParam->inlineInfo, nullptr, &compileFlagsForInlinee, pParam->inlineInfo); - if (!innerInlineResult->IsFailure()) + if (result != CORJIT_OK) { - innerInlineResult->NoteFatal(InlineObservation::CALLSITE_COMPILATION_FAILURE); + // If we haven't yet determined why this inline fails, use + // a catch-all something bad happened observation. + InlineResult* innerInlineResult = pParam->inlineInfo->inlineResult; + + if (!innerInlineResult->IsFailure()) + { + innerInlineResult->NoteFatal(InlineObservation::CALLSITE_COMPILATION_FAILURE); + } } } - } - }, ¶m); + }, + ¶m); if (!success) { #ifdef DEBUG if (verbose) { - printf("\nInlining failed due to an exception during invoking the compiler for the inlinee method %s.\n", - eeGetMethodFullName(fncHandle)); + printf("\nInlining failed due to an exception during invoking the compiler for the inlinee method %s.\n", + eeGetMethodFullName(fncHandle)); } #endif // DEBUG @@ -21498,8 +21589,7 @@ void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call, #ifdef DEBUG if (0 && verbose) { - printf("\nDone invoking compiler for the inlinee method %s\n", - eeGetMethodFullName(fncHandle)); + printf("\nDone invoking compiler for the inlinee method %s\n", eeGetMethodFullName(fncHandle)); } #endif // DEBUG @@ -21514,7 +21604,7 @@ void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call, if (verbose) { printf("\nInlining failed because pInlineInfo->retExpr is not set in the inlinee method %s.\n", - eeGetMethodFullName(fncHandle)); + eeGetMethodFullName(fncHandle)); } #endif // DEBUG inlineResult->NoteFatal(InlineObservation::CALLEE_LACKS_RETURN); @@ -21526,7 +21616,8 @@ void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call, // we defer the call to initClass() until inlining is completed in case it fails. If inlining succeeds, // we will call initClass(). if (!(info.compCompHnd->initClass(nullptr /* field */, fncHandle /* method */, - inlineCandidateInfo->exactContextHnd /* context */) & CORINFO_INITCLASS_INITIALIZED)) + inlineCandidateInfo->exactContextHnd /* context */) & + CORINFO_INITCLASS_INITIALIZED)) { inlineResult->NoteFatal(InlineObservation::CALLEE_CLASS_INIT_FAILURE); return; @@ -21545,11 +21636,8 @@ void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call, if (verbose || fgPrintInlinedMethods) { - printf("Successfully inlined %s (%d IL bytes) (depth %d) [%s]\n", - eeGetMethodFullName(fncHandle), - inlineCandidateInfo->methInfo.ILCodeSize, - inlineDepth, - inlineResult->ReasonString()); + printf("Successfully inlined %s (%d IL bytes) (depth %d) [%s]\n", eeGetMethodFullName(fncHandle), + inlineCandidateInfo->methInfo.ILCodeSize, inlineDepth, inlineResult->ReasonString()); } if (verbose) @@ -21566,20 +21654,39 @@ void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call, inlineResult->NoteSuccess(); } -// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -// The inlining attempt cannot be failed starting from this point. -// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +//------------------------------------------------------------------------ +// fgInsertInlineeBlocks: incorporate statements for an inline into the +// root method. +// +// Arguments: +// inlineInfo -- info for the inline +// +// Notes: +// The inlining attempt cannot be failed once this method is called. +// +// Adds all inlinee statements, plus any glue statements needed +// either before or after the inlined call. +// +// Updates flow graph and assigns weights to inlinee +// blocks. Currently does not attempt to read IBC data for the +// inlinee. +// +// Updates relevant root method status flags (eg optMethodFlags) to +// include information from the inlinee. +// +// Marks newly added statements with an appropriate inline context. + void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) { - GenTreePtr iciCall = pInlineInfo->iciCall; - GenTreePtr iciStmt = pInlineInfo->iciStmt; - BasicBlock* iciBlock = pInlineInfo->iciBlock; + GenTreeCall* iciCall = pInlineInfo->iciCall; + GenTreeStmt* iciStmt = pInlineInfo->iciStmt; + BasicBlock* iciBlock = pInlineInfo->iciBlock; BasicBlock* block; // We can write better assert here. For example, we can check that // iciBlock contains iciStmt, which in turn contains iciCall. noway_assert(iciBlock->bbTreeList != nullptr); - noway_assert(iciStmt->gtStmt.gtStmtExpr != nullptr); + noway_assert(iciStmt->gtStmtExpr != nullptr); noway_assert(iciCall->gtOper == GT_CALL); #ifdef DEBUG @@ -21591,33 +21698,23 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) printf("\n\n----------- Statements (and blocks) added due to the inlining of call "); printTreeID(iciCall); printf(" -----------\n"); - // gtDispTree(iciStmt); } #endif // DEBUG - // // Create a new inline context and mark the inlined statements with it - // InlineContext* calleeContext = m_inlineStrategy->NewSuccess(pInlineInfo); - for (block = InlineeCompiler->fgFirstBB; - block != nullptr; - block = block->bbNext) + for (block = InlineeCompiler->fgFirstBB; block != nullptr; block = block->bbNext) { - for (GenTreeStmt* stmt = block->firstStmt(); - stmt; - stmt = stmt->gtNextStmt) + for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt) { stmt->gtInlineContext = calleeContext; } } - // - // Prepend statements. - // - GenTreePtr stmtAfter; - stmtAfter = fgInlinePrependStatements(pInlineInfo); + // Prepend statements + GenTreePtr stmtAfter = fgInlinePrependStatements(pInlineInfo); #ifdef DEBUG if (verbose) @@ -21627,6 +21724,9 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) } #endif // DEBUG + BasicBlock* topBlock = iciBlock; + BasicBlock* bottomBlock = nullptr; + if (InlineeCompiler->fgBBcount == 1) { // When fgBBCount is 1 we will always have a non-NULL fgFirstBB @@ -21641,22 +21741,21 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) // Inlinee contains just one BB. So just insert its statement list to topBlock. if (InlineeCompiler->fgFirstBB->bbTreeList) { - stmtAfter = fgInsertStmtListAfter(iciBlock, - stmtAfter, - InlineeCompiler->fgFirstBB->bbTreeList); + stmtAfter = fgInsertStmtListAfter(iciBlock, stmtAfter, InlineeCompiler->fgFirstBB->bbTreeList); // Copy inlinee bbFlags to caller bbFlags. - const unsigned int inlineeBlockFlags = InlineeCompiler->fgFirstBB->bbFlags; + const unsigned __int64 inlineeBlockFlags = InlineeCompiler->fgFirstBB->bbFlags; noway_assert((inlineeBlockFlags & BBF_HAS_JMP) == 0); noway_assert((inlineeBlockFlags & BBF_KEEP_BBJ_ALWAYS) == 0); iciBlock->bbFlags |= inlineeBlockFlags; } + #ifdef DEBUG if (verbose) { noway_assert(currentDumpStmt); - if (currentDumpStmt != stmtAfter) + if (currentDumpStmt != stmtAfter) { do { @@ -21669,10 +21768,14 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) gtDispTree(currentDumpStmt); printf("\n"); - } while (currentDumpStmt != stmtAfter); + } while (currentDumpStmt != stmtAfter); } } #endif // DEBUG + + // Append statements to unpin, if necessary. + fgInlineAppendStatements(pInlineInfo, iciBlock, stmtAfter); + goto _Done; } } @@ -21681,24 +21784,20 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) // ======= Inserting inlinee's basic blocks =============== // - BasicBlock* topBlock; - BasicBlock* bottomBlock; - - topBlock = iciBlock; - - bottomBlock = fgNewBBafter(topBlock->bbJumpKind, topBlock, true); - bottomBlock->bbRefs = 1; + bottomBlock = fgNewBBafter(topBlock->bbJumpKind, topBlock, true); + bottomBlock->bbRefs = 1; bottomBlock->bbJumpDest = topBlock->bbJumpDest; bottomBlock->inheritWeight(topBlock); topBlock->bbJumpKind = BBJ_NONE; // Update block flags - unsigned originalFlags; - originalFlags = topBlock->bbFlags; - noway_assert((originalFlags & BBF_SPLIT_NONEXIST) == 0); - topBlock->bbFlags &= ~(BBF_SPLIT_LOST); - bottomBlock->bbFlags |= originalFlags & BBF_SPLIT_GAINED; + { + const unsigned __int64 originalFlags = topBlock->bbFlags; + noway_assert((originalFlags & BBF_SPLIT_NONEXIST) == 0); + topBlock->bbFlags &= ~(BBF_SPLIT_LOST); + bottomBlock->bbFlags |= originalFlags & BBF_SPLIT_GAINED; + } // // Split statements between topBlock and bottomBlock @@ -21708,10 +21807,10 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) GenTreePtr bottomBlock_Begin; GenTreePtr bottomBlock_End; - topBlock_Begin = nullptr; - topBlock_End = nullptr; + topBlock_Begin = nullptr; + topBlock_End = nullptr; bottomBlock_Begin = nullptr; - bottomBlock_End = nullptr; + bottomBlock_End = nullptr; // // First figure out bottomBlock_Begin @@ -21724,7 +21823,7 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) // topBlock is empty before the split. // In this case, both topBlock and bottomBlock should be empty noway_assert(bottomBlock_Begin == nullptr); - topBlock->bbTreeList = nullptr; + topBlock->bbTreeList = nullptr; bottomBlock->bbTreeList = nullptr; } else if (topBlock->bbTreeList == bottomBlock_Begin) @@ -21735,7 +21834,7 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) // And the split is before the first statement. // In this case, topBlock should be empty, and everything else should be moved to the bottonBlock. bottomBlock->bbTreeList = topBlock->bbTreeList; - topBlock->bbTreeList = nullptr; + topBlock->bbTreeList = nullptr; } else if (bottomBlock_Begin == nullptr) { @@ -21753,9 +21852,9 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) noway_assert(bottomBlock_Begin); // This is the normal case where both blocks should contain at least one statement. - topBlock_Begin = topBlock->bbTreeList; + topBlock_Begin = topBlock->bbTreeList; noway_assert(topBlock_Begin); - topBlock_End = bottomBlock_Begin->gtPrev; + topBlock_End = bottomBlock_Begin->gtPrev; noway_assert(topBlock_End); bottomBlock_End = topBlock->lastStmt(); noway_assert(bottomBlock_End); @@ -21778,25 +21877,23 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) bool inheritWeight; inheritWeight = true; // The firstBB does inherit the weight from the iciBlock - for (block = InlineeCompiler->fgFirstBB; - block != nullptr; - block = block->bbNext) + for (block = InlineeCompiler->fgFirstBB; block != nullptr; block = block->bbNext) { noway_assert(!block->hasTryIndex()); noway_assert(!block->hasHndIndex()); block->copyEHRegion(iciBlock); - block->bbFlags |= iciBlock->bbFlags & BBF_BACKWARD_JUMP; + block->bbFlags |= iciBlock->bbFlags & BBF_BACKWARD_JUMP; - if (iciStmt->gtStmt.gtStmtILoffsx != BAD_IL_OFFSET) + if (iciStmt->gtStmtILoffsx != BAD_IL_OFFSET) { - block->bbCodeOffs = jitGetILoffs(iciStmt->gtStmt.gtStmtILoffsx); - block->bbCodeOffsEnd = block->bbCodeOffs + 1; // TODO: is code size of 1 some magic number for inlining? + block->bbCodeOffs = jitGetILoffs(iciStmt->gtStmtILoffsx); + block->bbCodeOffsEnd = block->bbCodeOffs + 1; // TODO: is code size of 1 some magic number for inlining? } else { - block->bbCodeOffs = 0; // TODO: why not BAD_IL_OFFSET? - block->bbCodeOffsEnd = 0; - block->bbFlags |= BBF_INTERNAL; + block->bbCodeOffs = 0; // TODO: why not BAD_IL_OFFSET? + block->bbCodeOffsEnd = 0; + block->bbFlags |= BBF_INTERNAL; } if (block->bbJumpKind == BBJ_RETURN) @@ -21810,8 +21907,8 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) #ifdef DEBUG if (verbose) { - printf("\nConvert bbJumpKind of BB%02u to BBJ_ALWAYS to bottomBlock BB%02u\n", - block->bbNum, bottomBlock->bbNum); + printf("\nConvert bbJumpKind of BB%02u to BBJ_ALWAYS to bottomBlock BB%02u\n", block->bbNum, + bottomBlock->bbNum); } #endif // DEBUG } @@ -21846,6 +21943,9 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo) // fgBBcount += InlineeCompiler->fgBBcount; + // Append statements to unpin if necessary. + fgInlineAppendStatements(pInlineInfo, bottomBlock, nullptr); + #ifdef DEBUG if (verbose) { @@ -21862,15 +21962,18 @@ _Done: // // Copy out some flags // - compLongUsed |= InlineeCompiler->compLongUsed; - compFloatingPointUsed |= InlineeCompiler->compFloatingPointUsed; - compLocallocUsed |= InlineeCompiler->compLocallocUsed; - compQmarkUsed |= InlineeCompiler->compQmarkUsed; - compUnsafeCastUsed |= InlineeCompiler->compUnsafeCastUsed; + compLongUsed |= InlineeCompiler->compLongUsed; + compFloatingPointUsed |= InlineeCompiler->compFloatingPointUsed; + compLocallocUsed |= InlineeCompiler->compLocallocUsed; + compQmarkUsed |= InlineeCompiler->compQmarkUsed; + compUnsafeCastUsed |= InlineeCompiler->compUnsafeCastUsed; compNeedsGSSecurityCookie |= InlineeCompiler->compNeedsGSSecurityCookie; - compGSReorderStackLayout |= InlineeCompiler->compGSReorderStackLayout; + compGSReorderStackLayout |= InlineeCompiler->compGSReorderStackLayout; - // Update optMethodFlags + // Update unmanaged call count + info.compCallUnmanaged += InlineeCompiler->info.compCallUnmanaged; + +// Update optMethodFlags #ifdef DEBUG unsigned optMethodFlagsBefore = optMethodFlags; @@ -21881,8 +21984,8 @@ _Done: #ifdef DEBUG if (optMethodFlags != optMethodFlagsBefore) { - JITDUMP("INLINER: Updating optMethodFlags -- root:%0x callee:%0x new:%0x\n", - optMethodFlagsBefore, InlineeCompiler->optMethodFlags, optMethodFlags); + JITDUMP("INLINER: Updating optMethodFlags -- root:%0x callee:%0x new:%0x\n", optMethodFlagsBefore, + InlineeCompiler->optMethodFlags, optMethodFlags); } #endif @@ -21908,24 +22011,41 @@ _Done: // Detach the GT_CALL node from the original statement by hanging a "nothing" node under it, // so that fgMorphStmts can remove the statement once we return from here. // - iciStmt->gtStmt.gtStmtExpr = gtNewNothingNode(); + iciStmt->gtStmtExpr = gtNewNothingNode(); } -// Prepend the statements that are needed before the inlined call. -// Return the last statement that is prepended. +//------------------------------------------------------------------------ +// fgInlinePrependStatements: prepend statements needed to match up +// caller and inlined callee +// +// Arguments: +// inlineInfo -- info for the inline +// +// Return Value: +// The last statement that was added, or the original call if no +// statements were added. +// +// Notes: +// Statements prepended may include the following: +// * This pointer null check +// * Class initialization +// * Zeroing of must-init locals in the callee +// * Passing of call arguments via temps +// +// Newly added statements are placed just after the original call +// and are are given the same inline context as the call any calls +// added here will appear to have been part of the immediate caller. -GenTreePtr Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) +GenTreePtr Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) { - BasicBlock* block = inlineInfo->iciBlock; + BasicBlock* block = inlineInfo->iciBlock; + GenTreeStmt* callStmt = inlineInfo->iciStmt; + IL_OFFSETX callILOffset = callStmt->gtStmtILoffsx; + GenTreeStmt* postStmt = callStmt->gtNextStmt; + GenTreePtr afterStmt = callStmt; // afterStmt is the place where the new statements should be inserted after. + GenTreePtr newStmt = nullptr; + GenTreePtr call = inlineInfo->iciCall; - GenTreePtr callStmt = inlineInfo->iciStmt; - noway_assert(callStmt->gtOper == GT_STMT); - IL_OFFSETX callILOffset = callStmt->gtStmt.gtStmtILoffsx; - - GenTreePtr afterStmt = callStmt; // afterStmt is the place where the new statements should be inserted after. - GenTreePtr newStmt; - - GenTreePtr call = inlineInfo->iciCall; noway_assert(call->gtOper == GT_CALL); #ifdef DEBUG @@ -21939,12 +22059,13 @@ GenTreePtr Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) // Prepend statements for any initialization / side effects - InlArgInfo* inlArgInfo = inlineInfo->inlArgInfo; - InlLclVarInfo* lclVarInfo = inlineInfo->lclVarInfo; + InlArgInfo* inlArgInfo = inlineInfo->inlArgInfo; + InlLclVarInfo* lclVarInfo = inlineInfo->lclVarInfo; GenTreePtr tree; - // Create the null check statement (but not appending it to the statement list yet) for the 'this' pointer if necessary. + // Create the null check statement (but not appending it to the statement list yet) for the 'this' pointer if + // necessary. // The NULL check should be done after "argument setup statements". // The only reason we move it here is for calling "impInlineFetchArg(0,..." to reserve a temp // for the "this" pointer. @@ -21956,8 +22077,7 @@ GenTreePtr Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) if (call->gtFlags & GTF_CALL_NULLCHECK && !inlineInfo->thisDereferencedFirst) { // Call impInlineFetchArg to "reserve" a temp for the "this" pointer. - nullcheck = gtNewOperNode(GT_IND, TYP_INT, - impInlineFetchArg(0, inlArgInfo, lclVarInfo)); + nullcheck = gtNewOperNode(GT_IND, TYP_INT, impInlineFetchArg(0, inlArgInfo, lclVarInfo)); nullcheck->gtFlags |= GTF_EXCEPT; // The NULL-check statement will be inserted to the statement list after those statements @@ -21995,10 +22115,8 @@ GenTreePtr Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) GenTreePtr argSingleUseNode = inlArgInfo[argNum].argBashTmpNode; - if (argSingleUseNode && - !(argSingleUseNode->gtFlags & GTF_VAR_CLONED) && - !inlArgInfo[argNum].argHasLdargaOp && - !inlArgInfo[argNum].argHasStargOp) + if (argSingleUseNode && !(argSingleUseNode->gtFlags & GTF_VAR_CLONED) && + !inlArgInfo[argNum].argHasLdargaOp && !inlArgInfo[argNum].argHasStargOp) { // Change the temp in-place to the actual argument. // We currently do not support this for struct arguments, so it must not be a GT_OBJ. @@ -22019,15 +22137,12 @@ GenTreePtr Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) noway_assert(structHnd != NO_CLASS_HANDLE); } - // Unsafe value cls check is not needed for argTmpNum here since in-linee compiler instance would have - // iterated over these and marked them accordingly. - impAssignTempGen(inlArgInfo[argNum].argTmpNum, - inlArgInfo[argNum].argNode, - structHnd, - (unsigned)CHECK_SPILL_NONE, - & afterStmt, - callILOffset, - block); + // Unsafe value cls check is not needed for + // argTmpNum here since in-linee compiler instance + // would have iterated over these and marked them + // accordingly. + impAssignTempGen(inlArgInfo[argNum].argTmpNum, inlArgInfo[argNum].argNode, structHnd, + (unsigned)CHECK_SPILL_NONE, &afterStmt, callILOffset, block); #ifdef DEBUG if (verbose) @@ -22035,7 +22150,6 @@ GenTreePtr Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) gtDispTree(afterStmt); } #endif // DEBUG - } } else if (inlArgInfo[argNum].argIsByRefToStructLocal) @@ -22046,19 +22160,18 @@ GenTreePtr Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) { /* The argument is either not used or a const or lcl var */ - noway_assert(!inlArgInfo[argNum].argIsUsed || - inlArgInfo[argNum].argIsInvariant || - inlArgInfo[argNum].argIsLclVar ); + noway_assert(!inlArgInfo[argNum].argIsUsed || inlArgInfo[argNum].argIsInvariant || + inlArgInfo[argNum].argIsLclVar); /* Make sure we didnt change argNode's along the way, or else subsequent uses of the arg would have worked with the bashed value */ if (inlArgInfo[argNum].argIsInvariant) { - assert(inlArgInfo[argNum].argNode->OperIsConst() || - inlArgInfo[argNum].argNode->gtOper == GT_ADDR); + assert(inlArgInfo[argNum].argNode->OperIsConst() || inlArgInfo[argNum].argNode->gtOper == GT_ADDR); } noway_assert((inlArgInfo[argNum].argIsLclVar == 0) == - (inlArgInfo[argNum].argNode->gtOper != GT_LCL_VAR || (inlArgInfo[argNum].argNode->gtFlags & GTF_GLOB_REF))); + (inlArgInfo[argNum].argNode->gtOper != GT_LCL_VAR || + (inlArgInfo[argNum].argNode->gtFlags & GTF_GLOB_REF))); /* If the argument has side effects, append it */ @@ -22086,7 +22199,6 @@ GenTreePtr Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) gtDispTree(afterStmt); } #endif // DEBUG - } } } @@ -22101,7 +22213,7 @@ GenTreePtr Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) if (inlineInfo->inlineCandidateInfo->initClassResult & CORINFO_INITCLASS_USE_HELPER) { CORINFO_CONTEXT_HANDLE exactContext = inlineInfo->inlineCandidateInfo->exactContextHnd; - CORINFO_CLASS_HANDLE exactClass; + CORINFO_CLASS_HANDLE exactClass; if (((SIZE_T)exactContext & CORINFO_CONTEXTFLAGS_MASK) == CORINFO_CONTEXTFLAGS_CLASS) { @@ -22109,18 +22221,19 @@ GenTreePtr Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) } else { - exactClass = info.compCompHnd->getMethodClass(CORINFO_METHOD_HANDLE((SIZE_T)exactContext & ~CORINFO_CONTEXTFLAGS_MASK)); + exactClass = info.compCompHnd->getMethodClass( + CORINFO_METHOD_HANDLE((SIZE_T)exactContext & ~CORINFO_CONTEXTFLAGS_MASK)); } - tree = fgGetSharedCCtor(exactClass); - newStmt = gtNewStmt(tree, callILOffset); + tree = fgGetSharedCCtor(exactClass); + newStmt = gtNewStmt(tree, callILOffset); afterStmt = fgInsertStmtAfter(block, afterStmt, newStmt); } // Insert the nullcheck statement now. if (nullcheck) { - newStmt = gtNewStmt(nullcheck, callILOffset); + newStmt = gtNewStmt(nullcheck, callILOffset); afterStmt = fgInsertStmtAfter(block, afterStmt, newStmt); } @@ -22133,8 +22246,7 @@ GenTreePtr Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) unsigned lclCnt = InlineeMethodInfo->locals.numArgs; // Does callee contain any zero-init local? - if ((lclCnt != 0) && - (InlineeMethodInfo->options & CORINFO_OPT_INIT_LOCALS) != 0) + if ((lclCnt != 0) && (InlineeMethodInfo->options & CORINFO_OPT_INIT_LOCALS) != 0) { #ifdef DEBUG @@ -22146,7 +22258,7 @@ GenTreePtr Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) for (unsigned lclNum = 0; lclNum < lclCnt; lclNum++) { - unsigned tmpNum = inlineInfo->lclTmpNum[lclNum]; + unsigned tmpNum = inlineInfo->lclTmpNum[lclNum]; // Is the local used at all? if (tmpNum != BAD_VAR_NUM) @@ -22158,25 +22270,21 @@ GenTreePtr Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) { // Unsafe value cls check is not needed here since in-linee compiler instance would have // iterated over locals and marked accordingly. - impAssignTempGen(tmpNum, - gtNewZeroConNode(genActualType(lclTyp)), - NO_CLASS_HANDLE, - (unsigned)CHECK_SPILL_NONE, - & afterStmt, - callILOffset, - block); + impAssignTempGen(tmpNum, gtNewZeroConNode(genActualType(lclTyp)), NO_CLASS_HANDLE, + (unsigned)CHECK_SPILL_NONE, &afterStmt, callILOffset, block); } else { - CORINFO_CLASS_HANDLE structType = lclVarInfo[lclNum + inlineInfo->argCnt].lclVerTypeInfo.GetClassHandle(); + CORINFO_CLASS_HANDLE structType = + lclVarInfo[lclNum + inlineInfo->argCnt].lclVerTypeInfo.GetClassHandle(); - tree = gtNewBlkOpNode(gtNewLclvNode(tmpNum, lclTyp), // Dest - gtNewIconNode(0), // Value + tree = gtNewBlkOpNode(gtNewLclvNode(tmpNum, lclTyp), // Dest + gtNewIconNode(0), // Value info.compCompHnd->getClassSize(structType), // Size - false, // isVolatile - false); // not copyBlock + false, // isVolatile + false); // not copyBlock - newStmt = gtNewStmt(tree, callILOffset); + newStmt = gtNewStmt(tree, callILOffset); afterStmt = fgInsertStmtAfter(block, afterStmt, newStmt); } @@ -22190,14 +22298,102 @@ GenTreePtr Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) } } + // Update any newly added statements with the appropriate context. + InlineContext* context = callStmt->gtInlineContext; + assert(context != nullptr); + for (GenTreeStmt* addedStmt = callStmt->gtNextStmt; addedStmt != postStmt; addedStmt = addedStmt->gtNextStmt) + { + assert(addedStmt->gtInlineContext == nullptr); + addedStmt->gtInlineContext = context; + } + return afterStmt; } +//------------------------------------------------------------------------ +// fgInlineAppendStatements: Append statements that are needed +// after the inlined call. +// +// Arguments: +// inlineInfo - information about the inline +// block - basic block for the new statements +// stmtAfter - (optional) insertion point for mid-block cases + +void Compiler::fgInlineAppendStatements(InlineInfo* inlineInfo, BasicBlock* block, GenTreePtr stmtAfter) +{ + // Null out any inline pinned locals + if (!inlineInfo->hasPinnedLocals) + { + // No pins, nothing to do + return; + } + + JITDUMP("Unpin inlinee locals:\n"); + + GenTreePtr callStmt = inlineInfo->iciStmt; + IL_OFFSETX callILOffset = callStmt->gtStmt.gtStmtILoffsx; + CORINFO_METHOD_INFO* InlineeMethodInfo = InlineeCompiler->info.compMethodInfo; + unsigned lclCnt = InlineeMethodInfo->locals.numArgs; + InlLclVarInfo* lclVarInfo = inlineInfo->lclVarInfo; + + noway_assert(callStmt->gtOper == GT_STMT); + + for (unsigned lclNum = 0; lclNum < lclCnt; lclNum++) + { + unsigned tmpNum = inlineInfo->lclTmpNum[lclNum]; + + // Is the local used at all? + if (tmpNum == BAD_VAR_NUM) + { + // Nope, nothing to unpin. + continue; + } + + // Is the local pinned? + if (!lvaTable[tmpNum].lvPinned) + { + // Nope, nothing to unpin. + continue; + } + + // Does the local we're about to unpin appear in the return + // expression? If so we somehow messed up and didn't properly + // spill the return value. See impInlineFetchLocal. + GenTreePtr retExpr = inlineInfo->retExpr; + if (retExpr != nullptr) + { + const bool interferesWithReturn = gtHasRef(inlineInfo->retExpr, tmpNum, false); + noway_assert(!interferesWithReturn); + } + + // Emit the unpin, by assigning null to the local. + var_types lclTyp = (var_types)lvaTable[tmpNum].lvType; + noway_assert(lclTyp == lclVarInfo[lclNum + inlineInfo->argCnt].lclTypeInfo); + noway_assert(!varTypeIsStruct(lclTyp)); + GenTreePtr unpinExpr = gtNewTempAssign(tmpNum, gtNewZeroConNode(genActualType(lclTyp))); + GenTreePtr unpinStmt = gtNewStmt(unpinExpr, callILOffset); + + if (stmtAfter == nullptr) + { + stmtAfter = fgInsertStmtAtBeg(block, unpinStmt); + } + else + { + stmtAfter = fgInsertStmtAfter(block, stmtAfter, unpinStmt); + } + +#ifdef DEBUG + if (verbose) + { + gtDispTree(unpinStmt); + } +#endif // DEBUG + } +} /*****************************************************************************/ /*static*/ -Compiler::fgWalkResult Compiler::fgChkThrowCB(GenTreePtr* pTree, - fgWalkData* data) +Compiler::fgWalkResult Compiler::fgChkThrowCB(GenTreePtr* pTree, fgWalkData* data) { GenTreePtr tree = *pTree; @@ -22210,28 +22406,30 @@ Compiler::fgWalkResult Compiler::fgChkThrowCB(GenTreePtr* pTree, switch (tree->gtOper) { - case GT_MUL: - case GT_ADD: - case GT_SUB: - case GT_ASG_ADD: - case GT_ASG_SUB: - case GT_CAST: - if (tree->gtOverflow()) { - return Compiler::WALK_ABORT; -} - break; + case GT_MUL: + case GT_ADD: + case GT_SUB: + case GT_ASG_ADD: + case GT_ASG_SUB: + case GT_CAST: + if (tree->gtOverflow()) + { + return Compiler::WALK_ABORT; + } + break; - case GT_INDEX: - if (tree->gtFlags & GTF_INX_RNGCHK) { - return Compiler::WALK_ABORT; -} - break; + case GT_INDEX: + if (tree->gtFlags & GTF_INX_RNGCHK) + { + return Compiler::WALK_ABORT; + } + break; - case GT_ARR_BOUNDS_CHECK: - return Compiler::WALK_ABORT; + case GT_ARR_BOUNDS_CHECK: + return Compiler::WALK_ABORT; - default: - break; + default: + break; } return Compiler::WALK_CONTINUE; @@ -22239,33 +22437,32 @@ Compiler::fgWalkResult Compiler::fgChkThrowCB(GenTreePtr* pTree, /*****************************************************************************/ /*static*/ -Compiler::fgWalkResult Compiler::fgChkLocAllocCB(GenTreePtr* pTree, - fgWalkData* data) +Compiler::fgWalkResult Compiler::fgChkLocAllocCB(GenTreePtr* pTree, fgWalkData* data) { GenTreePtr tree = *pTree; - if (tree->gtOper == GT_LCLHEAP) { + if (tree->gtOper == GT_LCLHEAP) + { return Compiler::WALK_ABORT; -} + } return Compiler::WALK_CONTINUE; } /*****************************************************************************/ /*static*/ -Compiler::fgWalkResult Compiler::fgChkQmarkCB(GenTreePtr* pTree, - fgWalkData* data) +Compiler::fgWalkResult Compiler::fgChkQmarkCB(GenTreePtr* pTree, fgWalkData* data) { GenTreePtr tree = *pTree; - if (tree->gtOper == GT_QMARK) { + if (tree->gtOper == GT_QMARK) + { return Compiler::WALK_ABORT; -} + } return Compiler::WALK_CONTINUE; } - void Compiler::fgLclFldAssign(unsigned lclNum) { assert(varTypeIsStruct(lvaTable[lclNum].lvType)); diff --git a/src/jit/gcencode.cpp b/src/jit/gcencode.cpp index f20183b..128fc4a 100644 --- a/src/jit/gcencode.cpp +++ b/src/jit/gcencode.cpp @@ -23,6 +23,89 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #include "gcinfotypes.h" +ReturnKind GCTypeToReturnKind(CorInfoGCType gcType) +{ + switch (gcType) + { + case TYPE_GC_NONE: + return RT_Scalar; + case TYPE_GC_REF: + return RT_Object; + case TYPE_GC_BYREF: + return RT_ByRef; + default: + _ASSERTE(!"TYP_GC_OTHER is unexpected"); + return RT_Illegal; + } +} + +ReturnKind GCInfo::getReturnKind() +{ + switch (compiler->info.compRetType) + { + case TYP_REF: + case TYP_ARRAY: + return RT_Object; + case TYP_BYREF: + return RT_ByRef; + case TYP_STRUCT: + { + CORINFO_CLASS_HANDLE structType = compiler->info.compMethodInfo->args.retTypeClass; + var_types retType = compiler->getReturnTypeForStruct(structType); + + switch (retType) + { + case TYP_ARRAY: + _ASSERTE(false && "TYP_ARRAY unexpected from getReturnTypeForStruct()"); + // fall through + case TYP_REF: + return RT_Object; + + case TYP_BYREF: + return RT_ByRef; + + case TYP_STRUCT: + if (compiler->IsHfa(structType)) + { +#ifdef _TARGET_X86_ + _ASSERTE(false && "HFAs not expected for X86"); +#endif // _TARGET_X86_ + + return RT_Scalar; + } + else + { + // Multi-reg return + BYTE gcPtrs[2] = {TYPE_GC_NONE, TYPE_GC_NONE}; + compiler->info.compCompHnd->getClassGClayout(structType, gcPtrs); + + ReturnKind first = GCTypeToReturnKind((CorInfoGCType)gcPtrs[0]); + ReturnKind second = GCTypeToReturnKind((CorInfoGCType)gcPtrs[1]); + + return GetStructReturnKind(first, second); + } + +#ifdef _TARGET_X86_ + case TYP_FLOAT: + case TYP_DOUBLE: + return RT_Float; +#endif // _TARGET_X86_ + default: + return RT_Scalar; + } + } + +#ifdef _TARGET_X86_ + case TYP_FLOAT: + case TYP_DOUBLE: + return RT_Float; +#endif // _TARGET_X86_ + + default: + return RT_Scalar; + } +} + #ifdef JIT32_GCENCODER #include "emit.h" @@ -104,18 +187,21 @@ static void regenLog(unsigned encoding, InfoHdr* header, InfoHdr* state) fprintf(logFile, "InfoHdr( %2d, %2d, %1d, %1d, %1d," " %1d, %1d, %1d, %1d, %1d," - " %1d, %1d, %1d, %1d, %1d," - " %1d, %2d, %2d, %2d, %2d," - " %2d, %2d), \n", + " %1d, %1d, %1d, %1d, %1d, %1d," + " %1d, %1d, %1d," + " %1d, %2d, %2d," + " %2d, %2d, %2d, %2d, %2d, %2d), \n", state->prologSize, state->epilogSize, state->epilogCount, state->epilogAtEnd, state->ediSaved, state->esiSaved, state->ebxSaved, state->ebpSaved, state->ebpFrame, state->interruptible, state->doubleAlign, state->security, state->handlers, state->localloc, state->editNcontinue, state->varargs, - state->profCallbacks, state->argCount, state->frameSize, + state->profCallbacks, state->genericsContext, state->genericsContextIsMethodDesc, state->returnKind, + state->argCount, state->frameSize, (state->untrackedCnt <= SET_UNTRACKED_MAX) ? state->untrackedCnt : HAS_UNTRACKED, (state->varPtrTableSize == 0) ? 0 : HAS_VARPTR, (state->gsCookieOffset == INVALID_GS_COOKIE_OFFSET) ? 0 : HAS_GS_COOKIE_OFFSET, (state->syncStartOffset == INVALID_SYNC_OFFSET) ? 0 : HAS_SYNC_OFFSET, - (state->syncStartOffset == INVALID_SYNC_OFFSET) ? 0 : HAS_SYNC_OFFSET); + (state->syncStartOffset == INVALID_SYNC_OFFSET) ? 0 : HAS_SYNC_OFFSET, + (state->revPInvokeOffset == INVALID_REV_PINVOKE_OFFSET) ? 0 : HAS_REV_PINVOKE_FRAME_OFFSET); fflush(logFile); @@ -265,9 +351,11 @@ static int bigEncoding4(unsigned cur, unsigned tgt, unsigned max) return cnt; } -BYTE FASTCALL encodeHeaderNext(const InfoHdr& header, InfoHdr* state) +BYTE FASTCALL encodeHeaderNext(const InfoHdr& header, InfoHdr* state, BYTE& codeSet) { BYTE encoding = 0xff; + codeSet = 1; // codeSet is 1 or 2, depending on whether the returned encoding + // corresponds to InfoHdrAdjust, or InfoHdrAdjust2 enumerations. if (state->argCount != header.argCount) { @@ -547,6 +635,15 @@ BYTE FASTCALL encodeHeaderNext(const InfoHdr& header, InfoHdr* state) goto DO_RETURN; } + if (GCInfoEncodesReturnKind() && (state->returnKind != header.returnKind)) + { + state->returnKind = header.returnKind; + codeSet = 2; // Two byte encoding + encoding = header.returnKind; + _ASSERTE(encoding < SET_RET_KIND_MAX); + goto DO_RETURN; + } + if (state->gsCookieOffset != header.gsCookieOffset) { assert(state->gsCookieOffset == INVALID_GS_COOKIE_OFFSET || state->gsCookieOffset == HAS_GS_COOKIE_OFFSET); @@ -587,10 +684,31 @@ BYTE FASTCALL encodeHeaderNext(const InfoHdr& header, InfoHdr* state) } } + if (GCInfoEncodesRevPInvokeFrame() && (state->revPInvokeOffset != header.revPInvokeOffset)) + { + assert(state->revPInvokeOffset == INVALID_REV_PINVOKE_OFFSET || + state->revPInvokeOffset == HAS_REV_PINVOKE_FRAME_OFFSET); + + if (state->revPInvokeOffset == INVALID_REV_PINVOKE_OFFSET) + { + // header.revPInvokeOffset is non-zero. + state->revPInvokeOffset = HAS_REV_PINVOKE_FRAME_OFFSET; + encoding = FLIP_REV_PINVOKE_FRAME; + goto DO_RETURN; + } + else if (header.revPInvokeOffset == INVALID_REV_PINVOKE_OFFSET) + { + state->revPInvokeOffset = INVALID_REV_PINVOKE_OFFSET; + encoding = FLIP_REV_PINVOKE_FRAME; + goto DO_RETURN; + } + } + DO_RETURN: - assert(encoding < 0x80); + _ASSERTE(encoding < MORE_BYTES_TO_FOLLOW); if (!state->isHeaderMatch(header)) - encoding |= 0x80; + encoding |= MORE_BYTES_TO_FOLLOW; + return encoding; } @@ -806,6 +924,14 @@ static int measureDistance(const InfoHdr& header, const InfoHdrSmall* p, int clo return distance; } + if (p->returnKind != header.returnKind) + { + // Setting the ReturnKind requires two bytes of encoding. + distance += 2; + if (distance >= closeness) + return distance; + } + if (header.gsCookieOffset != INVALID_GS_COOKIE_OFFSET) { distance += 1; @@ -820,6 +946,13 @@ static int measureDistance(const InfoHdr& header, const InfoHdrSmall* p, int clo return distance; } + if (header.revPInvokeOffset != INVALID_REV_PINVOKE_OFFSET) + { + distance += 1; + if (distance >= closeness) + return distance; + } + return distance; } @@ -1164,6 +1297,16 @@ size_t GCInfo::gcInfoBlockHdrSave( header->genericsContext = compiler->lvaReportParamTypeArg(); header->genericsContextIsMethodDesc = header->genericsContext && (compiler->info.compMethodInfo->options & (CORINFO_GENERICS_CTXT_FROM_METHODDESC)); + + if (GCInfoEncodesReturnKind()) + { + ReturnKind returnKind = getReturnKind(); + _ASSERTE(IsValidReturnKind(returnKind) && "Return Kind must be valid"); + _ASSERTE(!IsStructReturnKind(returnKind) && "Struct Return Kinds Unexpected for JIT32"); + _ASSERTE(((int)returnKind < (int)SET_RET_KIND_MAX) && "ReturnKind has no legal encoding"); + header->returnKind = returnKind; + } + header->gsCookieOffset = INVALID_GS_COOKIE_OFFSET; if (compiler->getNeedsGSSecurityCookie()) { @@ -1190,6 +1333,8 @@ size_t GCInfo::gcInfoBlockHdrSave( assert(header->epilogCount <= 1); } + header->revPInvokeOffset = INVALID_REV_PINVOKE_OFFSET; + assert((compiler->compArgSize & 0x3) == 0); size_t argCount = @@ -1224,12 +1369,21 @@ size_t GCInfo::gcInfoBlockHdrSave( *dest++ = headerEncoding; BYTE encoding = headerEncoding; - while (encoding & 0x80) + BYTE codeSet = 1; + while (encoding & MORE_BYTES_TO_FOLLOW) { - encoding = encodeHeaderNext(*header, &state); + encoding = encodeHeaderNext(*header, &state, codeSet); + #if REGEN_SHORTCUTS regenLog(headerEncoding, header, &state); #endif + _ASSERTE(codeSet == 1 || codeSet == 2 && "Encoding must correspond to InfoHdrAdjust or InfoHdrAdjust2"); + if (codeSet == 2) + { + *dest++ = NEXT_OPCODE | MORE_BYTES_TO_FOLLOW; + ++size; + } + *dest++ = encoding; ++size; } @@ -1771,12 +1925,12 @@ size_t GCInfo::gcMakeRegPtrTable(BYTE* dest, int mask, const InfoHdr& header, un } else { - /* Stack-passed arguments which are not enregistered - * are always reported in this "untracked stack - * pointers" section of the GC info even if lvTracked==true - */ +/* Stack-passed arguments which are not enregistered + * are always reported in this "untracked stack + * pointers" section of the GC info even if lvTracked==true + */ - /* Has this argument been enregistered? */ +/* Has this argument been enregistered? */ #ifndef LEGACY_BACKEND if (!varDsc->lvOnFrame) #else // LEGACY_BACKEND @@ -3277,7 +3431,7 @@ void GCInfo::gcFindPtrsInFrame(const void* infoBlock, const void* codeBlock, uns GCDump gcDump(GCINFO_VERSION); gcDump.gcPrintf = gcDump_logf; // use my printf (which logs to VM) - gcDump.DumpPtrsInFrame((const BYTE*)infoBlock, (const BYTE*)codeBlock, offs, verifyGCTables); + gcDump.DumpPtrsInFrame((PTR_CBYTE)infoBlock, (const BYTE*)codeBlock, offs, verifyGCTables); } #endif // DUMP_GC_TABLES @@ -3504,23 +3658,6 @@ public: #endif // DEBUG -ReturnKind GCTypeToReturnKind(CorInfoGCType gcType) -{ - - switch (gcType) - { - case TYPE_GC_NONE: - return RT_Scalar; - case TYPE_GC_REF: - return RT_Object; - case TYPE_GC_BYREF: - return RT_ByRef; - default: - _ASSERTE(!"TYP_GC_OTHER is unexpected"); - return RT_Illegal; - } -} - void GCInfo::gcInfoBlockHdrSave(GcInfoEncoder* gcInfoEncoder, unsigned methodSize, unsigned prologSize) { #ifdef DEBUG @@ -3536,65 +3673,7 @@ void GCInfo::gcInfoBlockHdrSave(GcInfoEncoder* gcInfoEncoder, unsigned methodSiz gcInfoEncoderWithLog->SetCodeLength(methodSize); - ReturnKind returnKind = RT_Illegal; - - switch (compiler->info.compRetType) - { - case TYP_REF: - case TYP_ARRAY: - returnKind = RT_Object; - break; - case TYP_BYREF: - returnKind = RT_ByRef; - break; - case TYP_STRUCT: - { - CORINFO_CLASS_HANDLE structType = compiler->info.compMethodInfo->args.retTypeClass; - var_types retType = compiler->getReturnTypeForStruct(structType); - - switch (retType) - { - case TYP_ARRAY: - _ASSERTE(false && "TYP_ARRAY unexpected from getReturnTypeForStruct()"); - - case TYP_REF: - returnKind = RT_Object; - break; - - case TYP_BYREF: - returnKind = RT_ByRef; - break; - - case TYP_STRUCT: - if (compiler->IsHfa(structType)) - { - returnKind = RT_Scalar; - } - else - { - // Multi-reg return - BYTE gcPtrs[2] = { TYPE_GC_NONE, TYPE_GC_NONE }; - compiler->info.compCompHnd->getClassGClayout(structType, gcPtrs); - - ReturnKind first = GCTypeToReturnKind((CorInfoGCType)gcPtrs[0]); - ReturnKind second = GCTypeToReturnKind((CorInfoGCType)gcPtrs[1]); - - returnKind = GetStructReturnKind(first, second); - } - break; - - default: - returnKind = RT_Scalar; - break; - } - break; - } - default: - returnKind = RT_Scalar; - } - - _ASSERTE(returnKind != RT_Illegal); - gcInfoEncoderWithLog->SetReturnKind(returnKind); + gcInfoEncoderWithLog->SetReturnKind(getReturnKind()); if (compiler->isFramePointerUsed()) { @@ -3682,10 +3761,8 @@ void GCInfo::gcInfoBlockHdrSave(GcInfoEncoder* gcInfoEncoder, unsigned methodSiz } #if FEATURE_EH_FUNCLETS - if (compiler->ehNeedsPSPSym()) + if (compiler->lvaPSPSym != BAD_VAR_NUM) { - assert(compiler->lvaPSPSym != BAD_VAR_NUM); - #ifdef _TARGET_AMD64_ // The PSPSym is relative to InitialSP on X64 and CallerSP on other platforms. gcInfoEncoderWithLog->SetPSPSymStackSlot(compiler->lvaGetInitialSPRelativeOffset(compiler->lvaPSPSym)); diff --git a/src/jit/gentree.cpp b/src/jit/gentree.cpp index 67474e1..4a6cc74 100644 --- a/src/jit/gentree.cpp +++ b/src/jit/gentree.cpp @@ -21,7 +21,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX /*****************************************************************************/ const unsigned short GenTree::gtOperKindTable[] = { -#define GTNODE(en, sn, cm, ok) ok + GTK_COMMUTE *cm, +#define GTNODE(en, sn, st, cm, ok) ok + GTK_COMMUTE *cm, #include "gtlist.h" }; @@ -209,7 +209,7 @@ static void printIndent(IndentStack* indentStack) } static const char* nodeNames[] = { -#define GTNODE(en, sn, cm, ok) sn, +#define GTNODE(en, sn, st, cm, ok) sn, #include "gtlist.h" }; @@ -220,8 +220,12 @@ const char* GenTree::NodeName(genTreeOps op) return nodeNames[op]; } +#endif + +#if defined(DEBUG) || NODEBASH_STATS || MEASURE_NODE_SIZE || COUNT_AST_OPERS + static const char* opNames[] = { -#define GTNODE(en, sn, cm, ok) #en, +#define GTNODE(en, sn, st, cm, ok) #en, #include "gtlist.h" }; @@ -234,12 +238,27 @@ const char* GenTree::OpName(genTreeOps op) #endif +#if MEASURE_NODE_SIZE && SMALL_TREE_NODES + +static const char* opStructNames[] = { +#define GTNODE(en, sn, st, cm, ok) #st, +#include "gtlist.h" +}; + +const char* GenTree::OpStructName(genTreeOps op) +{ + assert((unsigned)op < sizeof(opStructNames) / sizeof(opStructNames[0])); + + return opStructNames[op]; +} + +#endif + /***************************************************************************** * * When 'SMALL_TREE_NODES' is enabled, we allocate tree nodes in 2 different - * sizes: 'GTF_DEBUG_NODE_SMALL' for most nodes and 'GTF_DEBUG_NODE_LARGE' for - * the few nodes (such as calls and statement list nodes) that have more fields - * and take up a lot more space. + * sizes: 'TREE_NODE_SZ_SMALL' for most nodes and 'TREE_NODE_SZ_LARGE' for the + * few nodes (such as calls) that have more fields and take up a lot more space. */ #if SMALL_TREE_NODES @@ -248,6 +267,19 @@ const char* GenTree::OpName(genTreeOps op) /* static */ unsigned char GenTree::s_gtNodeSizes[GT_COUNT + 1]; +#if NODEBASH_STATS || MEASURE_NODE_SIZE || COUNT_AST_OPERS + +unsigned char GenTree::s_gtTrueSizes[GT_COUNT + 1]{ +#define GTNODE(en, sn, st, cm, ok) sizeof(st), +#include "gtlist.h" +}; + +#endif // NODEBASH_STATS || MEASURE_NODE_SIZE || COUNT_AST_OPERS + +#if COUNT_AST_OPERS +LONG GenTree::s_gtNodeCounts[GT_COUNT + 1] = {0}; +#endif // COUNT_AST_OPERS + /* static */ void GenTree::InitNodeSize() { @@ -265,12 +297,13 @@ void GenTree::InitNodeSize() // Now set all of the appropriate entries to 'large' CLANG_FORMAT_COMMENT_ANCHOR; +// clang-format off #if defined(FEATURE_HFA) || defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) // On ARM32, ARM64 and System V for struct returning // there is code that does GT_ASG-tree.CopyObj call. // CopyObj is a large node and the GT_ASG is small, which triggers an exception. - GenTree::s_gtNodeSizes[GT_ASG] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_RETURN] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_ASG] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_RETURN] = TREE_NODE_SZ_LARGE; #endif // defined(FEATURE_HFA) || defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) GenTree::s_gtNodeSizes[GT_CALL] = TREE_NODE_SZ_LARGE; @@ -282,30 +315,32 @@ void GenTree::InitNodeSize() #ifdef FEATURE_SIMD GenTree::s_gtNodeSizes[GT_SIMD_CHK] = TREE_NODE_SZ_LARGE; #endif // FEATURE_SIMD - GenTree::s_gtNodeSizes[GT_ARR_ELEM] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_ARR_INDEX] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_ARR_OFFSET] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_RET_EXPR] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_OBJ] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_FIELD] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_STMT] = 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_LEA] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_STORE_OBJ] = 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; + GenTree::s_gtNodeSizes[GT_ARR_ELEM] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_ARR_INDEX] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_ARR_OFFSET] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_RET_EXPR] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_OBJ] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_FIELD] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_STMT] = 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_LEA] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_STORE_OBJ] = 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; #if USE_HELPERS_FOR_INT_DIV - GenTree::s_gtNodeSizes[GT_DIV] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_UDIV] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_MOD] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_UMOD] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_DIV] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_UDIV] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_MOD] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_UMOD] = TREE_NODE_SZ_LARGE; #endif -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING - GenTree::s_gtNodeSizes[GT_PUTARG_STK] = TREE_NODE_SZ_LARGE; -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING +#ifdef FEATURE_PUT_STRUCT_ARG_STK + // TODO-Throughput: This should not need to be a large node. The object info should be + // obtained from the child node. + GenTree::s_gtNodeSizes[GT_PUTARG_STK] = TREE_NODE_SZ_LARGE; +#endif // FEATURE_PUT_STRUCT_ARG_STK assert(GenTree::s_gtNodeSizes[GT_RETURN] == GenTree::s_gtNodeSizes[GT_ASG]); @@ -314,60 +349,65 @@ void GenTree::InitNodeSize() assert(sizeof(GenTreeLclFld) <= GenTree::s_gtNodeSizes[GT_LCL_FLD]); assert(sizeof(GenTreeLclVar) <= GenTree::s_gtNodeSizes[GT_LCL_VAR]); - static_assert_no_msg(sizeof(GenTree) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeUnOp) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeOp) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeVal) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTree) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeUnOp) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeOp) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeVal) <= TREE_NODE_SZ_SMALL); static_assert_no_msg(sizeof(GenTreeIntConCommon) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreePhysReg) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreePhysReg) <= TREE_NODE_SZ_SMALL); #ifndef LEGACY_BACKEND - static_assert_no_msg(sizeof(GenTreeJumpTable) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeJumpTable) <= TREE_NODE_SZ_SMALL); #endif // !LEGACY_BACKEND - static_assert_no_msg(sizeof(GenTreeIntCon) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeLngCon) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeDblCon) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeStrCon) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeIntCon) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeLngCon) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeDblCon) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeStrCon) <= TREE_NODE_SZ_SMALL); static_assert_no_msg(sizeof(GenTreeLclVarCommon) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeLclVar) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeLclFld) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeRegVar) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeCast) <= TREE_NODE_SZ_LARGE); // *** large node - static_assert_no_msg(sizeof(GenTreeBox) <= TREE_NODE_SZ_LARGE); // *** large node - static_assert_no_msg(sizeof(GenTreeField) <= TREE_NODE_SZ_LARGE); // *** large node - static_assert_no_msg(sizeof(GenTreeArgList) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeColon) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeCall) <= TREE_NODE_SZ_LARGE); // *** large node - static_assert_no_msg(sizeof(GenTreeCmpXchg) <= TREE_NODE_SZ_LARGE); // *** large node - static_assert_no_msg(sizeof(GenTreeFptrVal) <= TREE_NODE_SZ_LARGE); // *** large node - static_assert_no_msg(sizeof(GenTreeQmark) <= TREE_NODE_SZ_LARGE); // *** large node - static_assert_no_msg(sizeof(GenTreeIntrinsic) <= TREE_NODE_SZ_LARGE); // *** large node - static_assert_no_msg(sizeof(GenTreeIndex) <= TREE_NODE_SZ_LARGE); // *** large node - static_assert_no_msg(sizeof(GenTreeArrLen) <= TREE_NODE_SZ_LARGE); // *** large node - static_assert_no_msg(sizeof(GenTreeBoundsChk) <= TREE_NODE_SZ_LARGE); // *** large node - static_assert_no_msg(sizeof(GenTreeArrElem) <= TREE_NODE_SZ_LARGE); // *** large node - static_assert_no_msg(sizeof(GenTreeArrIndex) <= TREE_NODE_SZ_LARGE); // *** large node - static_assert_no_msg(sizeof(GenTreeArrOffs) <= TREE_NODE_SZ_LARGE); // *** large node - static_assert_no_msg(sizeof(GenTreeIndir) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeStoreInd) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeAddrMode) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeObj) <= TREE_NODE_SZ_LARGE); // *** large node - static_assert_no_msg(sizeof(GenTreeBlk) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeRetExpr) <= TREE_NODE_SZ_LARGE); // *** large node - static_assert_no_msg(sizeof(GenTreeStmt) <= TREE_NODE_SZ_LARGE); // *** large node - static_assert_no_msg(sizeof(GenTreeClsVar) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeArgPlace) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeLabel) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreePhiArg) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeAllocObj) <= TREE_NODE_SZ_LARGE); // *** large node -#ifndef FEATURE_UNIX_AMD64_STRUCT_PASSING - static_assert_no_msg(sizeof(GenTreePutArgStk) <= TREE_NODE_SZ_SMALL); -#else // FEATURE_UNIX_AMD64_STRUCT_PASSING - static_assert_no_msg(sizeof(GenTreePutArgStk) <= TREE_NODE_SZ_LARGE); -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING + static_assert_no_msg(sizeof(GenTreeLclVar) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeLclFld) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeRegVar) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeJumpCC) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeCast) <= TREE_NODE_SZ_LARGE); // *** large node + static_assert_no_msg(sizeof(GenTreeBox) <= TREE_NODE_SZ_LARGE); // *** large node + static_assert_no_msg(sizeof(GenTreeField) <= TREE_NODE_SZ_LARGE); // *** large node + static_assert_no_msg(sizeof(GenTreeArgList) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeFieldList) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeColon) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeCall) <= TREE_NODE_SZ_LARGE); // *** large node + static_assert_no_msg(sizeof(GenTreeCmpXchg) <= TREE_NODE_SZ_LARGE); // *** large node + static_assert_no_msg(sizeof(GenTreeFptrVal) <= TREE_NODE_SZ_LARGE); // *** large node + static_assert_no_msg(sizeof(GenTreeQmark) <= TREE_NODE_SZ_LARGE); // *** large node + static_assert_no_msg(sizeof(GenTreeIntrinsic) <= TREE_NODE_SZ_LARGE); // *** large node + static_assert_no_msg(sizeof(GenTreeIndex) <= TREE_NODE_SZ_LARGE); // *** large node + static_assert_no_msg(sizeof(GenTreeArrLen) <= TREE_NODE_SZ_LARGE); // *** large node + static_assert_no_msg(sizeof(GenTreeBoundsChk) <= TREE_NODE_SZ_LARGE); // *** large node + static_assert_no_msg(sizeof(GenTreeArrElem) <= TREE_NODE_SZ_LARGE); // *** large node + static_assert_no_msg(sizeof(GenTreeArrIndex) <= TREE_NODE_SZ_LARGE); // *** large node + static_assert_no_msg(sizeof(GenTreeArrOffs) <= TREE_NODE_SZ_LARGE); // *** large node + static_assert_no_msg(sizeof(GenTreeIndir) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeStoreInd) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeAddrMode) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeObj) <= TREE_NODE_SZ_LARGE); // *** large node + static_assert_no_msg(sizeof(GenTreeBlk) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeRetExpr) <= TREE_NODE_SZ_LARGE); // *** large node + static_assert_no_msg(sizeof(GenTreeStmt) <= TREE_NODE_SZ_LARGE); // *** large node + static_assert_no_msg(sizeof(GenTreeClsVar) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeArgPlace) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeLabel) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreePhiArg) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeAllocObj) <= TREE_NODE_SZ_LARGE); // *** large node +#ifndef FEATURE_PUT_STRUCT_ARG_STK + static_assert_no_msg(sizeof(GenTreePutArgStk) <= TREE_NODE_SZ_SMALL); +#else // FEATURE_PUT_STRUCT_ARG_STK + // TODO-Throughput: This should not need to be a large node. The object info should be + // obtained from the child node. + static_assert_no_msg(sizeof(GenTreePutArgStk) <= TREE_NODE_SZ_LARGE); +#endif // FEATURE_PUT_STRUCT_ARG_STK #ifdef FEATURE_SIMD - static_assert_no_msg(sizeof(GenTreeSIMD) <= TREE_NODE_SZ_SMALL); + static_assert_no_msg(sizeof(GenTreeSIMD) <= TREE_NODE_SZ_SMALL); #endif // FEATURE_SIMD + // clang-format on } size_t GenTree::GetNodeSize() const @@ -394,6 +434,88 @@ bool GenTree::IsNodeProperlySized() const } #endif +/***************************************************************************** + * + * When 'NODEBASH_STATS' is enabled in "jit.h" we record all instances of + * an existing GenTree node having its operator changed. This can be useful + * for two (related) things - to see what is being bashed (and what isn't), + * and to verify that the existing choices for what nodes are marked 'large' + * are reasonable (to minimize "wasted" space). + * + * And yes, the hash function / logic is simplistic, but it is conflict-free + * and transparent for what we need. + */ + +#if NODEBASH_STATS + +#define BASH_HASH_SIZE 211 + +inline hashme(genTreeOps op1, genTreeOps op2) +{ + return ((op1 * 104729) ^ (op2 * 56569)) % BASH_HASH_SIZE; +} + +struct BashHashDsc +{ + unsigned __int32 bhFullHash; // the hash value (unique for all old->new pairs) + unsigned __int32 bhCount; // the same old->new bashings seen so far + unsigned __int8 bhOperOld; // original gtOper + unsigned __int8 bhOperNew; // new gtOper +}; + +static BashHashDsc BashHash[BASH_HASH_SIZE]; + +void GenTree::RecordOperBashing(genTreeOps operOld, genTreeOps operNew) +{ + unsigned hash = hashme(operOld, operNew); + BashHashDsc* desc = BashHash + hash; + + if (desc->bhFullHash != hash) + { + noway_assert(desc->bhCount == 0); // if this ever fires, need fix the hash fn + desc->bhFullHash = hash; + } + + desc->bhCount += 1; + desc->bhOperOld = operOld; + desc->bhOperNew = operNew; +} + +void GenTree::ReportOperBashing(FILE* f) +{ + unsigned total = 0; + + fflush(f); + + fprintf(f, "\n"); + fprintf(f, "Bashed gtOper stats:\n"); + fprintf(f, "\n"); + fprintf(f, " Old operator New operator #bytes old->new Count\n"); + fprintf(f, " ---------------------------------------------------------------\n"); + + for (unsigned h = 0; h < BASH_HASH_SIZE; h++) + { + unsigned count = BashHash[h].bhCount; + if (count == 0) + continue; + + unsigned opOld = BashHash[h].bhOperOld; + unsigned opNew = BashHash[h].bhOperNew; + + fprintf(f, " GT_%-13s -> GT_%-13s [size: %3u->%3u] %c %7u\n", OpName((genTreeOps)opOld), + OpName((genTreeOps)opNew), s_gtTrueSizes[opOld], s_gtTrueSizes[opNew], + (s_gtTrueSizes[opOld] < s_gtTrueSizes[opNew]) ? 'X' : ' ', count); + total += count; + } + fprintf(f, "\n"); + fprintf(f, "Total bashings: %u\n", total); + fprintf(f, "\n"); + + fflush(f); +} + +#endif // NODEBASH_STATS + #else // SMALL_TREE_NODES #ifdef DEBUG @@ -407,6 +529,71 @@ bool GenTree::IsNodeProperlySized() const /*****************************************************************************/ +#if MEASURE_NODE_SIZE + +void GenTree::DumpNodeSizes(FILE* fp) +{ +// Dump the sizes of the various GenTree flavors + +#if SMALL_TREE_NODES + fprintf(fp, "Small tree node size = %3u bytes\n", TREE_NODE_SZ_SMALL); +#endif + fprintf(fp, "Large tree node size = %3u bytes\n", TREE_NODE_SZ_LARGE); + fprintf(fp, "\n"); + +#if SMALL_TREE_NODES + + // Verify that node sizes are set kosherly and dump sizes + for (unsigned op = GT_NONE + 1; op < GT_COUNT; op++) + { + unsigned needSize = s_gtTrueSizes[op]; + unsigned nodeSize = s_gtNodeSizes[op]; + + const char* structNm = OpStructName((genTreeOps)op); + const char* operName = OpName((genTreeOps)op); + + bool repeated = false; + + // Have we seen this struct flavor before? + for (unsigned mop = GT_NONE + 1; mop < op; mop++) + { + if (strcmp(structNm, OpStructName((genTreeOps)mop)) == 0) + { + repeated = true; + break; + } + } + + // Don't repeat the same GenTree flavor unless we have an error + if (!repeated || needSize > nodeSize) + { + unsigned sizeChar = '?'; + + if (nodeSize == TREE_NODE_SZ_SMALL) + sizeChar = 'S'; + else if (nodeSize == TREE_NODE_SZ_LARGE) + sizeChar = 'L'; + + fprintf(fp, "GT_%-16s ... %-19s = %3u bytes (%c)", operName, structNm, needSize, sizeChar); + if (needSize > nodeSize) + { + fprintf(fp, " -- ERROR -- allocation is only %u bytes!", nodeSize); + } + else if (needSize <= TREE_NODE_SZ_SMALL && nodeSize == TREE_NODE_SZ_LARGE) + { + fprintf(fp, " ... could be small"); + } + + fprintf(fp, "\n"); + } + } + +#endif +} + +#endif // MEASURE_NODE_SIZE +/*****************************************************************************/ + // make sure these get instantiated, because it's not in a header file // (emulating the c++ 'export' keyword here) // VC appears to be somewhat unpredictable about whether they end up in the .obj file without this @@ -965,11 +1152,12 @@ Compiler::fgWalkResult Compiler::fgWalkTreePostRec(GenTreePtr* pTree, fgWalkData } break; - case GT_LIST: + case GT_FIELD_LIST: { - GenTreeArgList* list = tree->AsArgList(); - if (list->IsAggregate()) + GenTreeFieldList* list = tree->AsFieldList(); + if (list->IsFieldListHead()) { + GenTreeFieldList* list = tree->AsFieldList(); for (; list != nullptr; list = list->Rest()) { result = fgWalkTreePostRec(&list->gtOp1, fgWalkData); @@ -978,12 +1166,8 @@ Compiler::fgWalkResult Compiler::fgWalkTreePostRec(GenTreePtr* pTree, fgWalkData return result; } } - break; } - - // GT_LIST nodes that do not represent aggregate arguments intentionally fall through to the - // default node processing below. - __fallthrough; + break; } default: @@ -1765,6 +1949,66 @@ bool GenTreeCall::IsHelperCall(Compiler* compiler, unsigned helper) const return IsHelperCall(compiler->eeFindHelper(helper)); } +//------------------------------------------------------------------------ +// GenTreeCall::ReplaceCallOperand: +// Replaces a given operand to a call node and updates the call +// argument table if necessary. +// +// Arguments: +// useEdge - the use edge that points to the operand to be replaced. +// replacement - the replacement node. +// +void GenTreeCall::ReplaceCallOperand(GenTree** useEdge, GenTree* replacement) +{ + assert(useEdge != nullptr); + assert(replacement != nullptr); + assert(TryGetUse(*useEdge, &useEdge)); + + GenTree* originalOperand = *useEdge; + *useEdge = replacement; + + const bool isArgument = + (replacement != gtControlExpr) && + ((gtCallType != CT_INDIRECT) || ((replacement != gtCallCookie) && (replacement != gtCallAddr))); + + if (isArgument) + { + if ((originalOperand->gtFlags & GTF_LATE_ARG) != 0) + { + replacement->gtFlags |= GTF_LATE_ARG; + } + else + { + assert((replacement->gtFlags & GTF_LATE_ARG) == 0); + + fgArgTabEntryPtr fp = Compiler::gtArgEntryByNode(this, originalOperand); + assert(fp->node == originalOperand); + fp->node = replacement; + } + } +} + +//------------------------------------------------------------------------- +// AreArgsComplete: Determine if this GT_CALL node's arguments have been processed. +// +// Return Value: +// Returns true if fgMorphArgs has processed the arguments. +// +bool GenTreeCall::AreArgsComplete() const +{ + if (fgArgInfo == nullptr) + { + return false; + } + if (fgArgInfo->AreArgsComplete()) + { + assert((gtCallLateArgs != nullptr) || !fgArgInfo->HasRegArgs()); + return true; + } + assert(gtCallArgs == nullptr); + return false; +} + /***************************************************************************** * * Returns non-zero if the two trees are identical. @@ -2071,7 +2315,9 @@ AGAIN: #ifdef FEATURE_READYTORUN_COMPILER if (op1->gtCall.gtEntryPoint.addr != op2->gtCall.gtEntryPoint.addr) + { return false; + } #endif } else @@ -2560,8 +2806,8 @@ AGAIN: hash = genTreeHashAdd(hash, tree->gtAllocObj.gtNewHelper); break; case GT_OBJ: - hash = genTreeHashAdd(hash, static_cast( - reinterpret_cast(tree->gtObj.gtClass))); + hash = + genTreeHashAdd(hash, static_cast(reinterpret_cast(tree->gtObj.gtClass))); break; // For the ones below no extra argument matters for comparison. @@ -3196,6 +3442,11 @@ GenTreePtr Compiler::gtReverseCond(GenTree* tree) tree->gtFlags ^= GTF_RELOP_NAN_UN; } } + else if (tree->OperGet() == GT_JCC) + { + GenTreeJumpCC* jcc = tree->AsJumpCC(); + jcc->gtCondition = GenTree::ReverseRelop(jcc->gtCondition); + } else { tree = gtNewOperNode(GT_NOT, TYP_INT, tree); @@ -3257,77 +3508,136 @@ bool GenTree::gtIsValid64RsltMul() #endif // DEBUG -/***************************************************************************** - * - * Figure out the evaluation order for a list of values. - */ +//------------------------------------------------------------------------------ +// gtSetListOrder : Figure out the evaluation order for a list of values. +// +// +// Arguments: +// list - List to figure out the evaluation order for +// isListCallArgs - True iff the list is a list of call arguments +// callArgsInRegs - True iff the list is a list of call arguments and they are passed in registers +// +// Return Value: +// True if the operation can be a root of a bitwise rotation tree; false otherwise. -unsigned Compiler::gtSetListOrder(GenTree* list, bool regs) +unsigned Compiler::gtSetListOrder(GenTree* list, bool isListCallArgs, bool callArgsInRegs) { - assert(list && list->IsList()); + assert((list != nullptr) && list->OperIsAnyList()); + assert(!callArgsInRegs || isListCallArgs); - unsigned level = 0; - unsigned ftreg = 0; - unsigned costSz = 0; - unsigned costEx = 0; + ArrayStack listNodes(this); + do + { + listNodes.Push(list); + list = list->gtOp.gtOp2; + } while ((list != nullptr) && (list->OperIsAnyList())); + + unsigned nxtlvl = (list == nullptr) ? 0 : gtSetEvalOrder(list); + while (listNodes.Height() > 0) + { #if FEATURE_STACK_FP_X87 - /* Save the current FP stack level since an argument list - * will implicitly pop the FP stack when pushing the argument */ - unsigned FPlvlSave = codeGen->genGetFPstkLevel(); + /* Save the current FP stack level since an argument list + * will implicitly pop the FP stack when pushing the argument */ + unsigned FPlvlSave = codeGen->genGetFPstkLevel(); #endif // FEATURE_STACK_FP_X87 - GenTreePtr next = list->gtOp.gtOp2; + list = listNodes.Pop(); + assert(list && list->OperIsAnyList()); + GenTreePtr next = list->gtOp.gtOp2; - if (next) - { - unsigned nxtlvl = gtSetListOrder(next, regs); + unsigned level = 0; + unsigned ftreg = 0; - ftreg |= next->gtRsvdRegs; + // TODO: Do we have to compute costs differently for argument lists and + // all other lists? + // https://github.com/dotnet/coreclr/issues/7095 + unsigned costSz = (isListCallArgs || (next == nullptr)) ? 0 : 1; + unsigned costEx = (isListCallArgs || (next == nullptr)) ? 0 : 1; - if (level < nxtlvl) + if (next != nullptr) { - level = nxtlvl; + ftreg |= next->gtRsvdRegs; + if (isListCallArgs) + { + if (level < nxtlvl) + { + level = nxtlvl; + } + } + costEx += next->gtCostEx; + costSz += next->gtCostSz; } - costEx += next->gtCostEx; - costSz += next->gtCostSz; - } - GenTreePtr op1 = list->gtOp.gtOp1; - unsigned lvl = gtSetEvalOrder(op1); + GenTreePtr op1 = list->gtOp.gtOp1; + unsigned lvl = gtSetEvalOrder(op1); #if FEATURE_STACK_FP_X87 - /* restore the FP level */ - codeGen->genResetFPstkLevel(FPlvlSave); + // restore the FP level + codeGen->genResetFPstkLevel(FPlvlSave); #endif // FEATURE_STACK_FP_X87 - list->gtRsvdRegs = (regMaskSmall)(ftreg | op1->gtRsvdRegs); + list->gtRsvdRegs = (regMaskSmall)(ftreg | op1->gtRsvdRegs); - if (level < lvl) - { - level = lvl; - } + // Swap the level counts + if (list->gtFlags & GTF_REVERSE_OPS) + { + unsigned tmpl; - if (op1->gtCostEx != 0) - { - costEx += op1->gtCostEx; - costEx += regs ? 0 : IND_COST_EX; - } + tmpl = lvl; + lvl = nxtlvl; + nxtlvl = tmpl; + } - if (op1->gtCostSz != 0) - { - costSz += op1->gtCostSz; + // TODO: Do we have to compute levels differently for argument lists and + // all other lists? + // https://github.com/dotnet/coreclr/issues/7095 + if (isListCallArgs) + { + if (level < lvl) + { + level = lvl; + } + } + else + { + if (lvl < 1) + { + level = nxtlvl; + } + else if (lvl == nxtlvl) + { + level = lvl + 1; + } + else + { + level = lvl; + } + } + + if (op1->gtCostEx != 0) + { + costEx += op1->gtCostEx; + costEx += (callArgsInRegs || !isListCallArgs) ? 0 : IND_COST_EX; + } + + if (op1->gtCostSz != 0) + { + costSz += op1->gtCostSz; #ifdef _TARGET_XARCH_ - if (regs) // push is smaller than mov to reg + if (callArgsInRegs) // push is smaller than mov to reg #endif - { - costSz += 1; + { + costSz += 1; + } } - } - list->SetCosts(costEx, costSz); + list->SetCosts(costEx, costSz); - return level; + nxtlvl = level; + } + + return nxtlvl; } /***************************************************************************** @@ -3363,17 +3673,8 @@ void Compiler::gtWalkOp(GenTree** op1WB, GenTree** op2WB, GenTree* adr, bool con { GenTreePtr op1 = *op1WB; GenTreePtr op2 = *op2WB; - GenTreePtr op1EffectiveVal; - if (op1->gtOper == GT_COMMA) - { - op1EffectiveVal = op1->gtEffectiveVal(); - if ((op1EffectiveVal->gtOper == GT_ADD) && (!op1EffectiveVal->gtOverflow()) && - (!constOnly || (op1EffectiveVal->gtOp.gtOp2->IsCnsIntOrI()))) - { - op1 = op1EffectiveVal; - } - } + op1 = op1->gtEffectiveVal(); // Now we look for op1's with non-overflow GT_ADDs [of constants] while ((op1->gtOper == GT_ADD) && (!op1->gtOverflow()) && (!constOnly || (op1->gtOp.gtOp2->IsCnsIntOrI()))) @@ -3398,20 +3699,12 @@ void Compiler::gtWalkOp(GenTree** op1WB, GenTree** op2WB, GenTree* adr, bool con op2 = tmp; } - if (op1->gtOper == GT_COMMA) - { - op1EffectiveVal = op1->gtEffectiveVal(); - if ((op1EffectiveVal->gtOper == GT_ADD) && (!op1EffectiveVal->gtOverflow()) && - (!constOnly || (op1EffectiveVal->gtOp.gtOp2->IsCnsIntOrI()))) - { - op1 = op1EffectiveVal; - } - } - if (!constOnly && ((op2 == adr) || (!op2->IsCnsIntOrI()))) { break; } + + op1 = op1->gtEffectiveVal(); } *op1WB = op1; @@ -3445,15 +3738,7 @@ GenTreePtr Compiler::gtWalkOpEffectiveVal(GenTreePtr op) { for (;;) { - if (op->gtOper == GT_COMMA) - { - GenTreePtr opEffectiveVal = op->gtEffectiveVal(); - if ((opEffectiveVal->gtOper == GT_ADD) && (!opEffectiveVal->gtOverflow()) && - (opEffectiveVal->gtOp.gtOp2->IsCnsIntOrI())) - { - op = opEffectiveVal; - } - } + op = op->gtEffectiveVal(); if ((op->gtOper != GT_ADD) || op->gtOverflow() || !op->gtOp.gtOp2->IsCnsIntOrI()) { @@ -3980,6 +4265,7 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) break; case GT_LIST: + case GT_FIELD_LIST: case GT_NOP: costEx = 0; costSz = 0; @@ -4671,6 +4957,14 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) goto DONE; + case GT_LIST: + case GT_FIELD_LIST: + { + const bool isListCallArgs = false; + const bool callArgsInRegs = false; + return gtSetListOrder(tree, isListCallArgs, callArgsInRegs); + } + default: break; } @@ -5025,6 +5319,7 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) break; case GT_LIST: + case GT_FIELD_LIST: break; case GT_SUB: @@ -5123,7 +5418,9 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) #if FEATURE_STACK_FP_X87 FPlvlSave = codeGen->genGetFPstkLevel(); #endif // FEATURE_STACK_FP_X87 - lvl2 = gtSetListOrder(tree->gtCall.gtCallArgs, false); + const bool isListCallArgs = true; + const bool callArgsInRegs = false; + lvl2 = gtSetListOrder(tree->gtCall.gtCallArgs, isListCallArgs, callArgsInRegs); if (level < lvl2) { level = lvl2; @@ -5145,7 +5442,9 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) #if FEATURE_STACK_FP_X87 FPlvlSave = codeGen->genGetFPstkLevel(); #endif // FEATURE_STACK_FP_X87 - lvl2 = gtSetListOrder(tree->gtCall.gtCallLateArgs, true); + const bool isListCallArgs = true; + const bool callArgsInRegs = true; + lvl2 = gtSetListOrder(tree->gtCall.gtCallLateArgs, isListCallArgs, callArgsInRegs); if (level < lvl2) { level = lvl2; @@ -5189,7 +5488,7 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) costSz += 2; } } - else if ((opts.eeFlags & CORJIT_FLG_PREJIT) == 0) + else if (!opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT)) { costEx += 2; costSz += 6; @@ -5789,11 +6088,11 @@ bool GenTree::IsAddWithI32Const(GenTreePtr* addr, int* offset) // 'parent' must be non-null // // Notes: -// When FEATURE_MULTIREG_ARGS is defined we can get here with GT_LDOBJ tree. +// When FEATURE_MULTIREG_ARGS is defined we can get here with GT_OBJ tree. // This happens when we have a struct that is passed in multiple registers. // // Also note that when FEATURE_UNIX_AMD64_STRUCT_PASSING is defined the GT_LDOBJ -// later gets converted to a GT_LIST with two GT_LCL_FLDs in Lower/LowerXArch. +// later gets converted to a GT_FIELD_LIST with two GT_LCL_FLDs in Lower/LowerXArch. // GenTreePtr* GenTree::gtGetChildPointer(GenTreePtr parent) @@ -5952,6 +6251,9 @@ GenTreePtr* GenTree::gtGetChildPointer(GenTreePtr parent) bool GenTree::TryGetUse(GenTree* def, GenTree*** use) { + assert(def != nullptr); + assert(use != nullptr); + for (GenTree** useEdge : UseEdges()) { if (*useEdge == def) @@ -5965,6 +6267,32 @@ bool GenTree::TryGetUse(GenTree* def, GenTree*** use) } //------------------------------------------------------------------------ +// GenTree::ReplaceOperand: +// Replace a given operand to this node with a new operand. If the +// current node is a call node, this will also udpate the call +// argument table if necessary. +// +// Arguments: +// useEdge - the use edge that points to the operand to be replaced. +// replacement - the replacement node. +// +void GenTree::ReplaceOperand(GenTree** useEdge, GenTree* replacement) +{ + assert(useEdge != nullptr); + assert(replacement != nullptr); + assert(TryGetUse(*useEdge, &useEdge)); + + if (OperGet() == GT_CALL) + { + AsCall()->ReplaceCallOperand(useEdge, replacement); + } + else + { + *useEdge = replacement; + } +} + +//------------------------------------------------------------------------ // gtGetParent: Get the parent of this node, and optionally capture the // pointer to the child so that it can be modified. // @@ -6500,16 +6828,15 @@ GenTreeCall* Compiler::gtNewCallNode( #endif // LEGACY_BACKEND #ifdef FEATURE_READYTORUN_COMPILER - node->gtCall.gtEntryPoint.addr = nullptr; + node->gtEntryPoint.addr = nullptr; #endif #if defined(DEBUG) || defined(INLINE_DATA) // These get updated after call node is built. - node->gtCall.gtInlineObservation = InlineObservation::CALLEE_UNUSED_INITIAL; - node->gtCall.gtRawILOffset = BAD_IL_OFFSET; + node->gtInlineObservation = InlineObservation::CALLEE_UNUSED_INITIAL; + node->gtRawILOffset = BAD_IL_OFFSET; #endif -#ifdef DEBUGGING_SUPPORT // Spec: Managed Retval sequence points needs to be generated while generating debug info for debuggable code. // // Implementation note: if not generating MRV info genCallSite2ILOffsetMap will be NULL and @@ -6537,7 +6864,6 @@ GenTreeCall* Compiler::gtNewCallNode( assert(!genCallSite2ILOffsetMap->Lookup(node, &value)); genCallSite2ILOffsetMap->Set(node, ilOffset); } -#endif // Initialize gtOtherRegs node->ClearOtherRegs(); @@ -6545,6 +6871,22 @@ GenTreeCall* Compiler::gtNewCallNode( // Initialize spill flags of gtOtherRegs node->ClearOtherRegFlags(); +#if defined(_TARGET_X86_) && !defined(LEGACY_BACKEND) + // Initialize the multi-reg long return info if necessary + if (varTypeIsLong(node)) + { + // The return type will remain as the incoming long type + node->gtReturnType = node->gtType; + + // Initialize Return type descriptor of call node + ReturnTypeDesc* retTypeDesc = node->GetReturnTypeDesc(); + retTypeDesc->InitializeLongReturnType(this); + + // must be a long returned in two registers + assert(retTypeDesc->GetReturnRegCount() == 2); + } +#endif // defined(_TARGET_X86_) && !defined(_LEGACY_BACKEND_) + return node; } @@ -6648,29 +6990,6 @@ GenTreeArgList* Compiler::gtNewArgList(GenTreePtr arg1, GenTreePtr arg2) return new (this, GT_LIST) GenTreeArgList(arg1, gtNewArgList(arg2)); } -//------------------------------------------------------------------------ -// Compiler::gtNewAggregate: -// Creates a new aggregate argument node. These nodes are used to -// represent arguments that are composed of multiple values (e.g. -// the lclVars that represent the fields of a promoted struct). -// -// Note that aggregate arguments are currently represented by GT_LIST -// nodes that are marked with the GTF_LIST_AGGREGATE flag. This -// representation may be changed in the future to instead use its own -// node type (e.g. GT_AGGREGATE). -// -// Arguments: -// firstElement - The first element in the aggregate's list of values. -// -// Returns: -// The newly-created aggregate node. -GenTreeArgList* Compiler::gtNewAggregate(GenTree* firstElement) -{ - GenTreeArgList* agg = gtNewArgList(firstElement); - agg->gtFlags |= GTF_LIST_AGGREGATE; - return agg; -} - /***************************************************************************** * * Create a list out of the three values. @@ -6741,7 +7060,7 @@ fgArgTabEntryPtr Compiler::gtArgEntryByNode(GenTreePtr call, GenTreePtr node) #endif // PROTO_JIT else if (curArgTabEntry->parent != nullptr) { - assert(curArgTabEntry->parent->IsList()); + assert(curArgTabEntry->parent->OperIsList()); if (curArgTabEntry->parent->Current() == node) { return curArgTabEntry; @@ -6956,17 +7275,32 @@ GenTree* Compiler::gtNewBlockVal(GenTreePtr addr, unsigned size) { // By default we treat this as an opaque struct type with known size. var_types blkType = TYP_STRUCT; -#if FEATURE_SIMD if ((addr->gtOper == GT_ADDR) && (addr->gtGetOp1()->OperGet() == GT_LCL_VAR)) { GenTree* val = addr->gtGetOp1(); - if (varTypeIsSIMD(val) && (genTypeSize(val->TypeGet()) == size)) +#if FEATURE_SIMD + if (varTypeIsSIMD(val)) { - blkType = val->TypeGet(); - return addr->gtGetOp1(); + if (genTypeSize(val->TypeGet()) == size) + { + blkType = val->TypeGet(); + return addr->gtGetOp1(); + } } - } + else #endif // FEATURE_SIMD +#ifndef LEGACY_BACKEND + if (val->TypeGet() == TYP_STRUCT) + { + GenTreeLclVarCommon* lcl = addr->gtGetOp1()->AsLclVarCommon(); + LclVarDsc* varDsc = &(lvaTable[lcl->gtLclNum]); + if ((varDsc->TypeGet() == TYP_STRUCT) && (varDsc->lvExactSize == size)) + { + return addr->gtGetOp1(); + } + } +#endif // !LEGACY_BACKEND + } return new (this, GT_BLK) GenTreeBlk(GT_BLK, blkType, addr, size); } @@ -6979,7 +7313,10 @@ GenTree* Compiler::gtNewBlockVal(GenTreePtr addr, unsigned size) // if FEATURE_SIMD is enabled and the source has a SIMD type. // isVolatile - Is this marked as volatile memory? -GenTree* Compiler::gtNewCpObjNode(GenTreePtr dstAddr, GenTreePtr srcAddr, CORINFO_CLASS_HANDLE structHnd, bool isVolatile) +GenTree* Compiler::gtNewCpObjNode(GenTreePtr dstAddr, + GenTreePtr srcAddr, + CORINFO_CLASS_HANDLE structHnd, + bool isVolatile) { GenTreePtr lhs = gtNewStructVal(structHnd, dstAddr); GenTree* src = nullptr; @@ -7046,10 +7383,10 @@ void GenTreeIntCon::FixupInitBlkValue(var_types asgType) } #endif // _TARGET_64BIT_ - // Make the type used in the GT_IND node match for evaluation types. + // Make the type match for evaluation types. gtType = asgType; - // if we are using an GT_INITBLK on a GC type the value being assigned has to be zero (null). + // if we are initializing a GC type the value being assigned must be zero (null). assert(!varTypeIsGC(asgType) || (cns == 0)); } @@ -7057,7 +7394,7 @@ void GenTreeIntCon::FixupInitBlkValue(var_types asgType) } } -// +// //------------------------------------------------------------------------ // gtBlockOpInit: Initializes a BlkOp GenTree // @@ -7066,7 +7403,7 @@ void GenTreeIntCon::FixupInitBlkValue(var_types asgType) // dst - the target (destination) we want to either initialize or copy to. // src - the init value for InitBlk or the source struct for CpBlk/CpObj. // isVolatile - specifies whether this node is a volatile memory operation. -// +// // Assumptions: // 'result' is an assignment that is newly constructed. // If 'dst' is TYP_STRUCT, then it must be a block node or lclVar. @@ -7156,9 +7493,6 @@ void Compiler::gtBlockOpInit(GenTreePtr result, GenTreePtr dst, GenTreePtr srcOr result->gtFlags |= dst->gtFlags & GTF_ALL_EFFECT; result->gtFlags |= result->gtOp.gtOp2->gtFlags & GTF_ALL_EFFECT; - // TODO-1stClassStructs: This should be done only if the destination is non-local. - result->gtFlags |= (GTF_GLOB_REF | GTF_ASG); - // REVERSE_OPS is necessary because the use must occur before the def result->gtFlags |= GTF_REVERSE_OPS; @@ -7229,12 +7563,20 @@ GenTree* Compiler::gtNewBlkOpNode( srcOrFillVal = srcOrFillVal->gtGetOp1()->gtGetOp1(); } } - - GenTree* result = gtNewAssignNode(dst, srcOrFillVal); - if (!isCopyBlock) + else { - result->gtFlags |= GTF_BLK_INIT; + // InitBlk + assert(varTypeIsIntegral(srcOrFillVal)); + if (varTypeIsStruct(dst)) + { + if (!srcOrFillVal->IsIntegralConst(0)) + { + srcOrFillVal = gtNewOperNode(GT_INIT_VAL, TYP_INT, srcOrFillVal); + } + } } + + GenTree* result = gtNewAssignNode(dst, srcOrFillVal); gtBlockOpInit(result, dst, srcOrFillVal, isVolatile); return result; } @@ -7376,17 +7718,30 @@ GenTreePtr Compiler::gtClone(GenTree* tree, bool complexOK) return copy; } -/***************************************************************************** - * - * Clones the given tree value and returns a copy of the given tree. Any - * references to local variable varNum will be replaced with the integer - * constant varVal. - */ +//------------------------------------------------------------------------ +// gtCloneExpr: Create a copy of `tree`, adding flags `addFlags`, mapping +// local `varNum` to int constant `varVal` if it appears at +// the root, and mapping uses of local `deepVarNum` to constant +// `deepVarVal` if they occur beyond the root. +// +// Arguments: +// tree - GenTree to create a copy of +// addFlags - GTF_* flags to add to the copied tree nodes +// varNum - lclNum to replace at the root, or ~0 for no root replacement +// varVal - If replacing at root, replace local `varNum` with IntCns `varVal` +// deepVarNum - lclNum to replace uses of beyond the root, or ~0 for no replacement +// deepVarVal - If replacing beyond root, replace `deepVarNum` with IntCns `deepVarVal` +// +// Return Value: +// A copy of the given tree with the replacements and added flags specified. +// +// Notes: +// Top-level callers should generally call the overload that doesn't have +// the explicit `deepVarNum` and `deepVarVal` parameters; those are used in +// recursive invocations to avoid replacing defs. -GenTreePtr Compiler::gtCloneExpr(GenTree* tree, - unsigned addFlags, - unsigned varNum, // = (unsigned)-1 - int varVal) +GenTreePtr Compiler::gtCloneExpr( + GenTree* tree, unsigned addFlags, unsigned varNum, int varVal, unsigned deepVarNum, int deepVarVal) { if (tree == nullptr) { @@ -7442,6 +7797,10 @@ GenTreePtr Compiler::gtCloneExpr(GenTree* tree, if (tree->gtLclVarCommon.gtLclNum == varNum) { copy = gtNewIconNode(varVal, tree->gtType); + if (tree->gtFlags & GTF_VAR_ARR_INDEX) + { + copy->LabelIndex(this); + } } else { @@ -7572,16 +7931,16 @@ GenTreePtr Compiler::gtCloneExpr(GenTree* tree, // The nodes below this are not bashed, so they can be allocated at their individual sizes. case GT_LIST: - // This is ridiculous, but would go away if we made a stronger distinction between argument lists, whose - // second argument *must* be an arglist*, and the uses of LIST in copyblk and initblk. - if (tree->gtOp.gtOp2 != nullptr && tree->gtOp.gtOp2->OperGet() == GT_LIST) - { - copy = new (this, GT_LIST) GenTreeArgList(tree->gtOp.gtOp1, tree->gtOp.gtOp2->AsArgList()); - } - else - { - copy = new (this, GT_LIST) GenTreeOp(GT_LIST, TYP_VOID, tree->gtOp.gtOp1, tree->gtOp.gtOp2); - } + assert((tree->gtOp.gtOp2 == nullptr) || tree->gtOp.gtOp2->OperIsList()); + copy = new (this, GT_LIST) GenTreeArgList(tree->gtOp.gtOp1); + copy->gtOp.gtOp2 = tree->gtOp.gtOp2; + break; + + case GT_FIELD_LIST: + copy = new (this, GT_FIELD_LIST) GenTreeFieldList(tree->gtOp.gtOp1, tree->AsFieldList()->gtFieldOffset, + tree->AsFieldList()->gtFieldType, nullptr); + copy->gtOp.gtOp2 = tree->gtOp.gtOp2; + copy->gtFlags = (copy->gtFlags & ~GTF_FIELD_LIST_HEAD) | (tree->gtFlags & GTF_FIELD_LIST_HEAD); break; case GT_INDEX: @@ -7608,8 +7967,9 @@ GenTreePtr Compiler::gtCloneExpr(GenTree* tree, case GT_ARR_INDEX: copy = new (this, GT_ARR_INDEX) - GenTreeArrIndex(tree->TypeGet(), gtCloneExpr(tree->gtArrIndex.ArrObj(), addFlags, varNum, varVal), - gtCloneExpr(tree->gtArrIndex.IndexExpr(), addFlags, varNum, varVal), + GenTreeArrIndex(tree->TypeGet(), + gtCloneExpr(tree->gtArrIndex.ArrObj(), addFlags, deepVarNum, deepVarVal), + gtCloneExpr(tree->gtArrIndex.IndexExpr(), addFlags, deepVarNum, deepVarVal), tree->gtArrIndex.gtCurrDim, tree->gtArrIndex.gtArrRank, tree->gtArrIndex.gtArrElemType); break; @@ -7708,12 +8068,20 @@ GenTreePtr Compiler::gtCloneExpr(GenTree* tree, if (tree->gtOp.gtOp1) { - copy->gtOp.gtOp1 = gtCloneExpr(tree->gtOp.gtOp1, addFlags, varNum, varVal); + if (tree->gtOper == GT_ASG) + { + // Don't replace varNum if it appears as the LHS of an assign. + copy->gtOp.gtOp1 = gtCloneExpr(tree->gtOp.gtOp1, addFlags, -1, 0, deepVarNum, deepVarVal); + } + else + { + copy->gtOp.gtOp1 = gtCloneExpr(tree->gtOp.gtOp1, addFlags, deepVarNum, deepVarVal); + } } if (tree->gtGetOp2()) { - copy->gtOp.gtOp2 = gtCloneExpr(tree->gtOp.gtOp2, addFlags, varNum, varVal); + copy->gtOp.gtOp2 = gtCloneExpr(tree->gtOp.gtOp2, addFlags, deepVarNum, deepVarVal); } /* Flags */ @@ -7775,18 +8143,6 @@ GenTreePtr Compiler::gtCloneExpr(GenTree* tree, copy->CopyReg(tree); } - // We can call gtCloneExpr() before we have called fgMorph when we expand a GT_INDEX node in fgMorphArrayIndex() - // The method gtFoldExpr() expects to be run after fgMorph so it will set the GTF_DEBUG_NODE_MORPHED - // flag on nodes that it adds/modifies. Then when we call fgMorph we will assert. - // We really only will need to fold when this method is used to replace references to - // local variable with an integer. - // - if (varNum != (unsigned)-1) - { - /* Try to do some folding */ - copy = gtFoldExpr(copy); - } - goto DONE; } @@ -7795,7 +8151,7 @@ GenTreePtr Compiler::gtCloneExpr(GenTree* tree, switch (oper) { case GT_STMT: - copy = gtCloneExpr(tree->gtStmt.gtStmtExpr, addFlags, varNum, varVal); + copy = gtCloneExpr(tree->gtStmt.gtStmtExpr, addFlags, deepVarNum, deepVarVal); copy = gtNewStmt(copy, tree->gtStmt.gtStmtILoffsx); goto DONE; @@ -7803,15 +8159,17 @@ GenTreePtr Compiler::gtCloneExpr(GenTree* tree, copy = new (this, GT_CALL) GenTreeCall(tree->TypeGet()); - copy->gtCall.gtCallObjp = - tree->gtCall.gtCallObjp ? gtCloneExpr(tree->gtCall.gtCallObjp, addFlags, varNum, varVal) : nullptr; - copy->gtCall.gtCallArgs = tree->gtCall.gtCallArgs - ? gtCloneExpr(tree->gtCall.gtCallArgs, addFlags, varNum, varVal)->AsArgList() + copy->gtCall.gtCallObjp = tree->gtCall.gtCallObjp + ? gtCloneExpr(tree->gtCall.gtCallObjp, addFlags, deepVarNum, deepVarVal) : nullptr; + copy->gtCall.gtCallArgs = + tree->gtCall.gtCallArgs + ? gtCloneExpr(tree->gtCall.gtCallArgs, addFlags, deepVarNum, deepVarVal)->AsArgList() + : nullptr; copy->gtCall.gtCallMoreFlags = tree->gtCall.gtCallMoreFlags; copy->gtCall.gtCallLateArgs = tree->gtCall.gtCallLateArgs - ? gtCloneExpr(tree->gtCall.gtCallLateArgs, addFlags, varNum, varVal)->AsArgList() + ? gtCloneExpr(tree->gtCall.gtCallLateArgs, addFlags, deepVarNum, deepVarVal)->AsArgList() : nullptr; #if !FEATURE_FIXED_OUT_ARGS @@ -7832,11 +8190,12 @@ GenTreePtr Compiler::gtCloneExpr(GenTree* tree, /* Copy the union */ if (tree->gtCall.gtCallType == CT_INDIRECT) { - copy->gtCall.gtCallCookie = tree->gtCall.gtCallCookie - ? gtCloneExpr(tree->gtCall.gtCallCookie, addFlags, varNum, varVal) - : nullptr; - copy->gtCall.gtCallAddr = - tree->gtCall.gtCallAddr ? gtCloneExpr(tree->gtCall.gtCallAddr, addFlags, varNum, varVal) : nullptr; + copy->gtCall.gtCallCookie = + tree->gtCall.gtCallCookie ? gtCloneExpr(tree->gtCall.gtCallCookie, addFlags, deepVarNum, deepVarVal) + : nullptr; + copy->gtCall.gtCallAddr = tree->gtCall.gtCallAddr + ? gtCloneExpr(tree->gtCall.gtCallAddr, addFlags, deepVarNum, deepVarVal) + : nullptr; } else if (tree->gtFlags & GTF_CALL_VIRT_STUB) { @@ -7883,8 +8242,9 @@ GenTreePtr Compiler::gtCloneExpr(GenTree* tree, copy = gtNewFieldRef(tree->TypeGet(), tree->gtField.gtFldHnd, nullptr, tree->gtField.gtFldOffset); - copy->gtField.gtFldObj = - tree->gtField.gtFldObj ? gtCloneExpr(tree->gtField.gtFldObj, addFlags, varNum, varVal) : nullptr; + copy->gtField.gtFldObj = tree->gtField.gtFldObj + ? gtCloneExpr(tree->gtField.gtFldObj, addFlags, deepVarNum, deepVarVal) + : nullptr; copy->gtField.gtFldMayOverlap = tree->gtField.gtFldMayOverlap; #ifdef FEATURE_READYTORUN_COMPILER copy->gtField.gtFieldLookup = tree->gtField.gtFieldLookup; @@ -7897,10 +8257,10 @@ GenTreePtr Compiler::gtCloneExpr(GenTree* tree, GenTreePtr inds[GT_ARR_MAX_RANK]; for (unsigned dim = 0; dim < tree->gtArrElem.gtArrRank; dim++) { - inds[dim] = gtCloneExpr(tree->gtArrElem.gtArrInds[dim], addFlags, varNum, varVal); + inds[dim] = gtCloneExpr(tree->gtArrElem.gtArrInds[dim], addFlags, deepVarNum, deepVarVal); } copy = new (this, GT_ARR_ELEM) - GenTreeArrElem(tree->TypeGet(), gtCloneExpr(tree->gtArrElem.gtArrObj, addFlags, varNum, varVal), + GenTreeArrElem(tree->TypeGet(), gtCloneExpr(tree->gtArrElem.gtArrObj, addFlags, deepVarNum, deepVarVal), tree->gtArrElem.gtArrRank, tree->gtArrElem.gtArrElemSize, tree->gtArrElem.gtArrElemType, &inds[0]); } @@ -7909,34 +8269,37 @@ GenTreePtr Compiler::gtCloneExpr(GenTree* tree, case GT_ARR_OFFSET: { copy = new (this, GT_ARR_OFFSET) - GenTreeArrOffs(tree->TypeGet(), gtCloneExpr(tree->gtArrOffs.gtOffset, addFlags, varNum, varVal), - gtCloneExpr(tree->gtArrOffs.gtIndex, addFlags, varNum, varVal), - gtCloneExpr(tree->gtArrOffs.gtArrObj, addFlags, varNum, varVal), + GenTreeArrOffs(tree->TypeGet(), gtCloneExpr(tree->gtArrOffs.gtOffset, addFlags, deepVarNum, deepVarVal), + gtCloneExpr(tree->gtArrOffs.gtIndex, addFlags, deepVarNum, deepVarVal), + gtCloneExpr(tree->gtArrOffs.gtArrObj, addFlags, deepVarNum, deepVarVal), tree->gtArrOffs.gtCurrDim, tree->gtArrOffs.gtArrRank, tree->gtArrOffs.gtArrElemType); } break; case GT_CMPXCHG: copy = new (this, GT_CMPXCHG) - GenTreeCmpXchg(tree->TypeGet(), gtCloneExpr(tree->gtCmpXchg.gtOpLocation, addFlags, varNum, varVal), - gtCloneExpr(tree->gtCmpXchg.gtOpValue, addFlags, varNum, varVal), - gtCloneExpr(tree->gtCmpXchg.gtOpComparand, addFlags, varNum, varVal)); + GenTreeCmpXchg(tree->TypeGet(), + gtCloneExpr(tree->gtCmpXchg.gtOpLocation, addFlags, deepVarNum, deepVarVal), + gtCloneExpr(tree->gtCmpXchg.gtOpValue, addFlags, deepVarNum, deepVarVal), + gtCloneExpr(tree->gtCmpXchg.gtOpComparand, addFlags, deepVarNum, deepVarVal)); break; case GT_ARR_BOUNDS_CHECK: #ifdef FEATURE_SIMD case GT_SIMD_CHK: #endif // FEATURE_SIMD - copy = new (this, oper) GenTreeBoundsChk(oper, tree->TypeGet(), - gtCloneExpr(tree->gtBoundsChk.gtArrLen, addFlags, varNum, varVal), - gtCloneExpr(tree->gtBoundsChk.gtIndex, addFlags, varNum, varVal), - tree->gtBoundsChk.gtThrowKind); + copy = new (this, oper) + GenTreeBoundsChk(oper, tree->TypeGet(), + gtCloneExpr(tree->gtBoundsChk.gtArrLen, addFlags, deepVarNum, deepVarVal), + gtCloneExpr(tree->gtBoundsChk.gtIndex, addFlags, deepVarNum, deepVarVal), + tree->gtBoundsChk.gtThrowKind); break; case GT_STORE_DYN_BLK: case GT_DYN_BLK: - copy = new (this, oper) GenTreeDynBlk(gtCloneExpr(tree->gtDynBlk.Addr(), addFlags, varNum, varVal), - gtCloneExpr(tree->gtDynBlk.gtDynamicSize, addFlags, varNum, varVal)); + copy = new (this, oper) + GenTreeDynBlk(gtCloneExpr(tree->gtDynBlk.Addr(), addFlags, deepVarNum, deepVarVal), + gtCloneExpr(tree->gtDynBlk.gtDynamicSize, addFlags, deepVarNum, deepVarVal)); break; default: @@ -8050,12 +8413,31 @@ GenTreePtr Compiler::gtReplaceTree(GenTreePtr stmt, GenTreePtr tree, GenTreePtr { assert(treeParent != nullptr); + // Check to see if the node to be replaced is a call argument and if so, + // set `treeParent` to the call node. + GenTree* cursor = treeParent; + while ((cursor != nullptr) && (cursor->OperGet() == GT_LIST)) + { + cursor = cursor->gtNext; + } + + if ((cursor != nullptr) && (cursor->OperGet() == GT_CALL)) + { + treeParent = cursor; + } + +#ifdef DEBUG + GenTree** useEdge; + assert(treeParent->TryGetUse(tree, &useEdge)); + assert(useEdge == treePtr); +#endif // DEBUG + GenTreePtr treeFirstNode = fgGetFirstNode(tree); GenTreePtr treeLastNode = tree; GenTreePtr treePrevNode = treeFirstNode->gtPrev; GenTreePtr treeNextNode = treeLastNode->gtNext; - *treePtr = replacementTree; + treeParent->ReplaceOperand(treePtr, replacementTree); // Build the linear order for "replacementTree". fgSetTreeSeq(replacementTree, treePrevNode); @@ -8082,48 +8464,6 @@ GenTreePtr Compiler::gtReplaceTree(GenTreePtr stmt, GenTreePtr tree, GenTreePtr treeNextNode->gtPrev = treeLastNode; } - bool needFixupCallArg = false; - GenTreePtr node = treeParent; - - // If we have replaced an arg, then update pointers in argtable. - do - { - // Look for the first enclosing callsite - switch (node->OperGet()) - { - case GT_LIST: - case GT_ARGPLACE: - // "tree" is likely an argument of a call. - needFixupCallArg = true; - break; - - case GT_CALL: - if (needFixupCallArg) - { - // We have replaced an arg, so update pointers in argtable. - fgFixupArgTabEntryPtr(node, tree, replacementTree); - needFixupCallArg = false; - } - break; - - default: - // "tree" is unlikely an argument of a call. - needFixupCallArg = false; - break; - } - - if (needFixupCallArg) - { - // Keep tracking to update the first enclosing call. - node = node->gtGetParent(nullptr); - } - else - { - // Stop tracking. - node = nullptr; - } - } while (node != nullptr); - // Propagate side-effect flags of "replacementTree" to its parents if needed. gtUpdateSideEffects(treeParent, tree->gtFlags, replacementTree->gtFlags); } @@ -8304,14 +8644,13 @@ bool GenTree::gtSetFlags() const // // Precondition we have a GTK_SMPOP // - assert(OperIsSimple()); - if (!varTypeIsIntegralOrI(TypeGet())) { return false; } #if FEATURE_SET_FLAGS + assert(OperIsSimple()); if ((gtFlags & GTF_SET_FLAGS) && gtOper != GT_IND) { @@ -8325,6 +8664,7 @@ bool GenTree::gtSetFlags() const #else // !FEATURE_SET_FLAGS +#ifdef LEGACY_BACKEND #ifdef _TARGET_XARCH_ // Return true if/when the codegen for this node will set the flags // @@ -8346,6 +8686,22 @@ bool GenTree::gtSetFlags() const return false; #endif +#else // !LEGACY_BACKEND +#ifdef _TARGET_XARCH_ + if (((gtFlags & GTF_SET_FLAGS) != 0) && (gtOper != GT_IND)) + { + // GTF_SET_FLAGS is not valid on GT_IND and is overlaid with GTF_NONFAULTING_IND + return true; + } + else + { + return false; + } +#else + unreached(); +#endif +#endif // !LEGACY_BACKEND + #endif // !FEATURE_SET_FLAGS } @@ -8399,7 +8755,8 @@ bool GenTree::gtRequestSetFlags() /*****************************************************************************/ void GenTree::CopyTo(class Compiler* comp, const GenTree& gt) { - gtOper = gt.gtOper; + SetOperRaw(gt.OperGet()); + gtType = gt.gtType; gtAssertionNum = gt.gtAssertionNum; @@ -8772,19 +9129,12 @@ GenTreePtr GenTree::GetChild(unsigned childNum) } } -GenTreeUseEdgeIterator::GenTreeUseEdgeIterator() - : m_node(nullptr) - , m_edge(nullptr) - , m_argList(nullptr) - , m_state(-1) +GenTreeUseEdgeIterator::GenTreeUseEdgeIterator() : m_node(nullptr), m_edge(nullptr), m_argList(nullptr), m_state(-1) { } GenTreeUseEdgeIterator::GenTreeUseEdgeIterator(GenTree* node) - : m_node(node) - , m_edge(nullptr) - , m_argList(nullptr) - , m_state(0) + : m_node(node), m_edge(nullptr), m_argList(nullptr), m_state(0) { assert(m_node != nullptr); @@ -8894,30 +9244,53 @@ GenTree** GenTreeUseEdgeIterator::GetNextUseEdge() const } case GT_DYN_BLK: + { + GenTreeDynBlk* const dynBlock = m_node->AsDynBlk(); switch (m_state) { case 0: - return &(m_node->AsDynBlk()->gtOp1); + return dynBlock->gtEvalSizeFirst ? &dynBlock->gtDynamicSize : &dynBlock->gtOp1; case 1: - return &(m_node->AsDynBlk()->gtDynamicSize); + return dynBlock->gtEvalSizeFirst ? &dynBlock->gtOp1 : &dynBlock->gtDynamicSize; default: return nullptr; } - break; + } + break; case GT_STORE_DYN_BLK: - switch (m_state) + { + GenTreeDynBlk* const dynBlock = m_node->AsDynBlk(); + if (dynBlock->gtEvalSizeFirst) { - case 0: - return &(m_node->AsDynBlk()->gtOp1); - case 1: - return &(m_node->AsDynBlk()->gtOp2); - case 2: - return &(m_node->AsDynBlk()->gtDynamicSize); - default: - return nullptr; + switch (m_state) + { + case 0: + return &dynBlock->gtDynamicSize; + case 1: + return dynBlock->IsReverseOp() ? &dynBlock->gtOp2 : &dynBlock->gtOp1; + case 2: + return dynBlock->IsReverseOp() ? &dynBlock->gtOp1 : &dynBlock->gtOp2; + default: + return nullptr; + } } - break; + else + { + switch (m_state) + { + case 0: + return dynBlock->IsReverseOp() ? &dynBlock->gtOp2 : &dynBlock->gtOp1; + case 1: + return dynBlock->IsReverseOp() ? &dynBlock->gtOp1 : &dynBlock->gtOp2; + case 2: + return &dynBlock->gtDynamicSize; + default: + return nullptr; + } + } + } + break; case GT_LEA: { @@ -8942,13 +9315,9 @@ GenTree** GenTreeUseEdgeIterator::GetNextUseEdge() const } break; - case GT_LIST: - if (m_node->AsArgList()->IsAggregate()) - { - // List nodes that represent aggregates are handled by MoveNextAggregateUseEdge. - break; - } - __fallthrough; + case GT_FIELD_LIST: + // Field List nodes are handled by MoveToNextFieldUseEdge. + break; default: if (m_node->OperIsConst() || m_node->OperIsLeaf()) @@ -8988,13 +9357,13 @@ void GenTreeUseEdgeIterator::MoveToNextCallUseEdge() { enum { - CALL_INSTANCE = 0, - CALL_ARGS = 1, - CALL_LATE_ARGS = 2, + CALL_INSTANCE = 0, + CALL_ARGS = 1, + CALL_LATE_ARGS = 2, CALL_CONTROL_EXPR = 3, - CALL_COOKIE = 4, - CALL_ADDRESS = 5, - CALL_TERMINAL = 6, + CALL_COOKIE = 4, + CALL_ADDRESS = 5, + CALL_TERMINAL = 6, }; GenTreeCall* call = m_node->AsCall(); @@ -9197,10 +9566,9 @@ void GenTreeUseEdgeIterator::MoveToNextSIMDUseEdge() } #endif // FEATURE_SIMD -void GenTreeUseEdgeIterator::MoveToNextAggregateUseEdge() +void GenTreeUseEdgeIterator::MoveToNextFieldUseEdge() { - assert(m_node->OperGet() == GT_LIST); - assert(m_node->AsArgList()->IsAggregate()); + assert(m_node->OperGet() == GT_FIELD_LIST); for (;;) { @@ -9218,9 +9586,9 @@ void GenTreeUseEdgeIterator::MoveToNextAggregateUseEdge() } else { - GenTreeArgList* aggNode = m_argList->AsArgList(); - m_edge = &aggNode->gtOp1; - m_argList = aggNode->Rest(); + GenTreeArgList* listNode = m_argList->AsArgList(); + m_edge = &listNode->gtOp1; + m_argList = listNode->Rest(); return; } break; @@ -9266,9 +9634,9 @@ GenTreeUseEdgeIterator& GenTreeUseEdgeIterator::operator++() MoveToNextSIMDUseEdge(); } #endif - else if ((op == GT_LIST) && (m_node->AsArgList()->IsAggregate())) + else if (op == GT_FIELD_LIST) { - MoveToNextAggregateUseEdge(); + MoveToNextFieldUseEdge(); } else { @@ -9529,7 +9897,7 @@ void Compiler::gtDispNodeName(GenTree* tree) { sprintf_s(bufp, sizeof(buf), " %s_ovfl%c", name, 0); } - else if (tree->OperIsBlk() && (tree->AsBlk()->gtBlkSize != 0)) + else if (tree->OperIsBlk() && !tree->OperIsDynBlk()) { sprintf_s(bufp, sizeof(buf), " %s(%d)", name, tree->AsBlk()->gtBlkSize); } @@ -9775,6 +10143,9 @@ void Compiler::gtDispNode(GenTreePtr tree, IndentStack* indentStack, __in __in_z goto DASH; case GT_MUL: +#if defined(_TARGET_X86_) && !defined(LEGACY_BACKEND) + case GT_MUL_LONG: +#endif if (tree->gtFlags & GTF_MUL_64RSLT) { printf("L"); @@ -10409,6 +10780,13 @@ void Compiler::gtDispConst(GenTree* tree) printf(" field offset"); } +#ifdef FEATURE_SIMD + if ((tree->gtFlags & GTF_ICON_SIMD_COUNT) != 0) + { + printf(" Vector.Count"); + } +#endif + if ((tree->IsReuseRegVal()) != 0) { printf(" reuse reg val"); @@ -10714,6 +11092,10 @@ void Compiler::gtDispLeaf(GenTree* tree, IndentStack* indentStack) } break; + case GT_JCC: + printf(" cond=%s", GenTree::NodeName(tree->AsJumpCC()->gtCondition)); + break; + default: assert(!"don't know how to display tree leaf node"); } @@ -10928,14 +11310,62 @@ void Compiler::gtDispTree(GenTreePtr tree, { printf(" (last use)"); } - if (tree->OperIsCopyBlkOp()) + if (tree->OperIsBlkOp()) + { + if (tree->OperIsCopyBlkOp()) + { + printf(" (copy)"); + } + else if (tree->OperIsInitBlkOp()) + { + printf(" (init)"); + } + if (tree->OperIsStoreBlk() && (tree->AsBlk()->gtBlkOpKind != GenTreeBlk::BlkOpKindInvalid)) + { + switch (tree->AsBlk()->gtBlkOpKind) + { + case GenTreeBlk::BlkOpKindRepInstr: + printf(" (RepInstr)"); + break; + case GenTreeBlk::BlkOpKindUnroll: + printf(" (Unroll)"); + break; + case GenTreeBlk::BlkOpKindHelper: + printf(" (Helper)"); + break; + default: + unreached(); + } + } + } + else if (tree->OperIsFieldList()) { - printf(" (copy)"); + printf(" %s at offset %d", varTypeName(tree->AsFieldList()->gtFieldType), + tree->AsFieldList()->gtFieldOffset); } - else if (tree->OperIsInitBlkOp()) +#if FEATURE_PUT_STRUCT_ARG_STK + else if ((tree->OperGet() == GT_PUTARG_STK) && + (tree->AsPutArgStk()->gtPutArgStkKind != GenTreePutArgStk::Kind::Invalid)) { - printf(" (init)"); + switch (tree->AsPutArgStk()->gtPutArgStkKind) + { + case GenTreePutArgStk::Kind::RepInstr: + printf(" (RepInstr)"); + break; + case GenTreePutArgStk::Kind::Unroll: + printf(" (Unroll)"); + break; + case GenTreePutArgStk::Kind::Push: + printf(" (Push)"); + break; + case GenTreePutArgStk::Kind::PushAllSlots: + printf(" (PushAllSlots)"); + break; + default: + unreached(); + } } +#endif // FEATURE_PUT_STRUCT_ARG_STK IndirectAssignmentAnnotation* pIndirAnnote; if (tree->gtOper == GT_ASG && GetIndirAssignMap()->Lookup(tree, &pIndirAnnote)) @@ -11282,7 +11712,7 @@ void Compiler::gtDispTree(GenTreePtr tree, // call - The call for which 'arg' is an argument // arg - The argument for which a message should be constructed // argNum - The ordinal number of the arg in the argument list -// listCount - When printing in LIR form this is the count for a multireg GT_LIST +// listCount - When printing in LIR form this is the count for a GT_FIELD_LIST // or -1 if we are not printing in LIR form // bufp - A pointer to the buffer into which the message is written // bufLength - The length of the buffer pointed to by bufp @@ -11338,7 +11768,7 @@ void Compiler::gtGetArgMsg( // call - The call for which 'arg' is an argument // argx - The argument for which a message should be constructed // lateArgIndex - The ordinal number of the arg in the lastArg list -// listCount - When printing in LIR form this is the count for a multireg GT_LIST +// listCount - When printing in LIR form this is the count for a multireg GT_FIELD_LIST // or -1 if we are not printing in LIR form // bufp - A pointer to the buffer into which the message is written // bufLength - The length of the buffer pointed to by bufp @@ -11542,22 +11972,8 @@ void Compiler::gtDispLIRNode(GenTree* node) const bool nodeIsCall = node->IsCall(); - int numCallEarlyArgs = 0; - if (nodeIsCall) - { - GenTreeCall* call = node->AsCall(); - for (GenTreeArgList* args = call->gtCallArgs; args != nullptr; args = args->Rest()) - { - if (!args->Current()->IsArgPlaceHolderNode() && args->Current()->IsValue()) - { - numCallEarlyArgs++; - } - } - } - // Visit operands - IndentInfo operandArc = IIArcTop; - int callArgNumber = 0; + IndentInfo operandArc = IIArcTop; for (GenTree* operand : node->Operands()) { if (operand->IsArgPlaceHolderNode() || !operand->IsValue()) @@ -11588,20 +12004,22 @@ void Compiler::gtDispLIRNode(GenTree* node) } else { - int callLateArgNumber = callArgNumber - numCallEarlyArgs; + fgArgTabEntryPtr curArgTabEntry = gtArgEntryByNode(call, operand); + assert(curArgTabEntry); + if (operand->OperGet() == GT_LIST) { int listIndex = 0; for (GenTreeArgList* element = operand->AsArgList(); element != nullptr; element = element->Rest()) { operand = element->Current(); - if (callLateArgNumber < 0) + if (curArgTabEntry->lateArgInx == (unsigned)-1) { - gtGetArgMsg(call, operand, callArgNumber, listIndex, buf, sizeof(buf)); + gtGetArgMsg(call, operand, curArgTabEntry->argNum, listIndex, buf, sizeof(buf)); } else { - gtGetLateArgMsg(call, operand, callLateArgNumber, listIndex, buf, sizeof(buf)); + gtGetLateArgMsg(call, operand, curArgTabEntry->lateArgInx, listIndex, buf, sizeof(buf)); } displayOperand(operand, buf, operandArc, indentStack); @@ -11610,19 +12028,17 @@ void Compiler::gtDispLIRNode(GenTree* node) } else { - if (callLateArgNumber < 0) + if (curArgTabEntry->lateArgInx == (unsigned)-1) { - gtGetArgMsg(call, operand, callArgNumber, -1, buf, sizeof(buf)); + gtGetArgMsg(call, operand, curArgTabEntry->argNum, -1, buf, sizeof(buf)); } else { - gtGetLateArgMsg(call, operand, callLateArgNumber, -1, buf, sizeof(buf)); + gtGetLateArgMsg(call, operand, curArgTabEntry->lateArgInx, -1, buf, sizeof(buf)); } displayOperand(operand, buf, operandArc, indentStack); } - - callArgNumber++; } } else if (node->OperIsDynBlkOp()) @@ -12315,9 +12731,6 @@ GenTreePtr Compiler::gtFoldExprConst(GenTreePtr tree) case TYP_ULONG: if (!(tree->gtFlags & GTF_UNSIGNED) && tree->gtOverflow() && i1 < 0) { - op1->ChangeOperConst(GT_CNS_NATIVELONG); // need type of oper to be same as tree - op1->gtType = TYP_LONG; - // We don't care about the value as we are throwing an exception goto LNG_OVF; } lval1 = UINT64(UINT32(i1)); @@ -12516,47 +12929,19 @@ GenTreePtr Compiler::gtFoldExprConst(GenTreePtr tree) // constants in a target-specific function. CLANG_FORMAT_COMMENT_ANCHOR; -#ifdef _TARGET_XARCH_ - // Don't fold conversions of +inf/-inf to integral value as the value returned by JIT helper - // doesn't match with the C compiler's cast result. + // Don't fold conversions of +inf/-inf to integral value on all platforms + // as the value returned by JIT helper doesn't match with the C compiler's cast result. + // We want the behavior to be same with or without folding. return tree; -#else //!_TARGET_XARCH_ + } - switch (tree->CastToType()) - { - case TYP_BYTE: - i1 = ssize_t(INT8(d1)); - goto CNS_INT; - case TYP_UBYTE: - i1 = ssize_t(UINT8(d1)); - goto CNS_INT; - case TYP_SHORT: - i1 = ssize_t(INT16(d1)); - goto CNS_INT; - case TYP_CHAR: - i1 = ssize_t(UINT16(d1)); - goto CNS_INT; - case TYP_INT: - i1 = ssize_t(INT32(d1)); - goto CNS_INT; - case TYP_UINT: - i1 = ssize_t(UINT32(d1)); - goto CNS_INT; - case TYP_LONG: - lval1 = INT64(d1); - goto CNS_LONG; - case TYP_ULONG: - lval1 = UINT64(d1); - goto CNS_LONG; - case TYP_FLOAT: - case TYP_DOUBLE: - if (op1->gtType == TYP_FLOAT) - d1 = forceCastToFloat(d1); // it's only !_finite() after this conversion - goto CNS_DOUBLE; - default: - unreached(); - } -#endif //!_TARGET_XARCH_ + if (d1 <= -1.0 && varTypeIsUnsigned(tree->CastToType())) + { + // Don't fold conversions of these cases becasue the result is unspecified per ECMA spec + // and the native math doing the fold doesn't match the run-time computation on all + // platforms. + // We want the behavior to be same with or without folding. + return tree; } switch (tree->CastToType()) @@ -12633,7 +13018,7 @@ GenTreePtr Compiler::gtFoldExprConst(GenTreePtr tree) return op2; } - if (tree->gtOper == GT_LIST) + if (tree->OperIsAnyList()) { return tree; } @@ -13621,8 +14006,8 @@ GenTreePtr Compiler::gtNewTempAssign(unsigned tmp, GenTreePtr val) var_types valTyp = val->TypeGet(); if (val->OperGet() == GT_LCL_VAR && lvaTable[val->gtLclVar.gtLclNum].lvNormalizeOnLoad()) { - valTyp = lvaGetRealType(val->gtLclVar.gtLclNum); - val = gtNewLclvNode(val->gtLclVar.gtLclNum, valTyp, val->gtLclVar.gtLclILoffs); + valTyp = lvaGetRealType(val->gtLclVar.gtLclNum); + val->gtType = valTyp; } var_types dstTyp = varDsc->TypeGet(); @@ -14108,7 +14493,7 @@ void Compiler::gtExtractSideEffList(GenTreePtr expr, // effect of this instruction, change it into a GT_LOCKADD node (the add only) if (oper == GT_XADD) { - expr->gtOper = GT_LOCKADD; + expr->SetOperRaw(GT_LOCKADD); expr->gtType = TYP_VOID; } @@ -14188,12 +14573,12 @@ void Compiler::gtExtractSideEffList(GenTreePtr expr, GenTreePtr args; for (args = expr->gtCall.gtCallArgs; args; args = args->gtOp.gtOp2) { - assert(args->IsList()); + assert(args->OperIsList()); gtExtractSideEffList(args->Current(), pList, flags); } for (args = expr->gtCall.gtCallLateArgs; args; args = args->gtOp.gtOp2) { - assert(args->IsList()); + assert(args->OperIsList()); gtExtractSideEffList(args->Current(), pList, flags); } } @@ -15356,11 +15741,18 @@ bool GenTree::isContained() const return false; } + // these either produce a result in register or set flags reg. + if (IsSIMDEqualityOrInequality()) + { + return false; + } + // TODO-Cleanup : this is not clean, would be nice to have some way of marking this. switch (OperGet()) { case GT_STOREIND: case GT_JTRUE: + case GT_JCC: case GT_RETURN: case GT_RETFILT: case GT_STORE_LCL_FLD: @@ -15381,7 +15773,9 @@ bool GenTree::isContained() const case GT_STORE_OBJ: case GT_STORE_DYN_BLK: case GT_SWITCH: +#ifndef LEGACY_BACKEND case GT_JMPTABLE: +#endif case GT_SWITCH_TABLE: case GT_SWAP: case GT_LCLHEAP: @@ -15928,6 +16322,17 @@ void GenTree::ParseArrayAddress( // TODO-Review: A NotAField here indicates a failure to properly maintain the field sequence // See test case self_host_tests_x86\jit\regression\CLR-x86-JIT\v1-m12-beta2\ b70992\ b70992.exe // Safest thing to do here is to drop back to MinOpts + CLANG_FORMAT_COMMENT_ANCHOR; + +#ifdef DEBUG + if (comp->opts.optRepeat) + { + // We don't guarantee preserving these annotations through the entire optimizer, so + // just conservatively return null if under optRepeat. + *pArr = nullptr; + return; + } +#endif // DEBUG noway_assert(!"fldSeqIter is NotAField() in ParseArrayAddress"); } @@ -16446,24 +16851,6 @@ bool GenTree::isCommutativeSIMDIntrinsic() #endif // FEATURE_SIMD //--------------------------------------------------------------------------------------- -// GenTreeArgList::Prepend: -// Prepends an element to a GT_LIST. -// -// Arguments: -// compiler - The compiler context. -// element - The element to prepend. -// -// Returns: -// The new head of the list. -GenTreeArgList* GenTreeArgList::Prepend(Compiler* compiler, GenTree* element) -{ - GenTreeArgList* head = compiler->gtNewListNode(element, this); - head->gtFlags |= (gtFlags & GTF_LIST_AGGREGATE); - gtFlags &= ~GTF_LIST_AGGREGATE; - return head; -} - -//--------------------------------------------------------------------------------------- // InitializeStructReturnType: // Initialize the Return Type Descriptor for a method that returns a struct type // diff --git a/src/jit/gentree.h b/src/jit/gentree.h index 4efeeae..4611d35 100644 --- a/src/jit/gentree.h +++ b/src/jit/gentree.h @@ -68,7 +68,7 @@ enum SpecialCodeKind DECLARE_TYPED_ENUM(genTreeOps, BYTE) { -#define GTNODE(en, sn, cm, ok) GT_##en, +#define GTNODE(en, sn, st, cm, ok) GT_##en, #include "gtlist.h" GT_COUNT, @@ -429,13 +429,15 @@ struct GenTree noway_assert(FitsIn(level)); gtFPlvl = (unsigned char)level; } -#else // FEATURE_STACK_FP_X87 +#else // FEATURE_STACK_FP_X87 + void gtCopyFPlvl(GenTree* other) { } void gtSetFPlvl(unsigned level) { } + #endif // FEATURE_STACK_FP_X87 // @@ -564,7 +566,7 @@ public: bool isContainedIntOrIImmed() const { - return isContained() && IsCnsIntOrI(); + return isContained() && IsCnsIntOrI() && !isContainedSpillTemp(); } bool isContainedFltOrDblImmed() const @@ -766,15 +768,15 @@ public: #ifdef LEGACY_BACKEND #define GTF_SPILLED_OPER 0x00000100 // op1 has been spilled #define GTF_SPILLED_OP2 0x00000200 // op2 has been spilled -#else +#else // !LEGACY_BACKEND #define GTF_NOREG_AT_USE 0x00000100 // tree node is in memory at the point of use -#endif // LEGACY_BACKEND +#endif // !LEGACY_BACKEND #define GTF_ZSF_SET 0x00000400 // the zero(ZF) and sign(SF) flags set to the operand -#if FEATURE_SET_FLAGS + #define GTF_SET_FLAGS 0x00000800 // Requires that codegen for this node set the flags // Use gtSetFlags() to check this flags -#endif + #define GTF_IND_NONFAULTING 0x00000800 // An indir that cannot fault. GTF_SET_FLAGS is not used on indirs #define GTF_MAKE_CSE 0x00002000 // Hoisted Expression: try hard to make this into CSE (see optPerformHoistExpr) @@ -865,12 +867,18 @@ public: #define GTF_IND_TLS_REF 0x08000000 // GT_IND -- the target is accessed via TLS #define GTF_IND_ASG_LHS 0x04000000 // GT_IND -- this GT_IND node is (the effective val) of the LHS of an // assignment; don't evaluate it independently. -#define GTF_IND_UNALIGNED 0x02000000 // GT_IND -- the load or store is unaligned (we assume worst case - // alignment of 1 byte) -#define GTF_IND_INVARIANT 0x01000000 // GT_IND -- the target is invariant (a prejit indirection) -#define GTF_IND_ARR_LEN 0x80000000 // GT_IND -- the indirection represents an array length (of the REF - // contribution to its argument). -#define GTF_IND_ARR_INDEX 0x00800000 // GT_IND -- the indirection represents an (SZ) array index +#define GTF_IND_REQ_ADDR_IN_REG GTF_IND_ASG_LHS // GT_IND -- requires its addr operand to be evaluated + // into a register. This flag is useful in cases where it + // is required to generate register indirect addressing mode. + // One such case is virtual stub calls on xarch. This is only + // valid in the backend, where GTF_IND_ASG_LHS is not necessary + // (all such indirections will be lowered to GT_STOREIND). +#define GTF_IND_UNALIGNED 0x02000000 // GT_IND -- the load or store is unaligned (we assume worst case + // alignment of 1 byte) +#define GTF_IND_INVARIANT 0x01000000 // GT_IND -- the target is invariant (a prejit indirection) +#define GTF_IND_ARR_LEN 0x80000000 // GT_IND -- the indirection represents an array length (of the REF + // contribution to its argument). +#define GTF_IND_ARR_INDEX 0x00800000 // GT_IND -- the indirection represents an (SZ) array index #define GTF_IND_FLAGS \ (GTF_IND_VOLATILE | GTF_IND_REFARR_LAYOUT | GTF_IND_TGTANYWHERE | GTF_IND_NONFAULTING | GTF_IND_TLS_REF | \ @@ -925,11 +933,12 @@ public: #define GTF_ICON_FIELD_OFF 0x08000000 // GT_CNS_INT -- constant is a field offset +#define GTF_ICON_SIMD_COUNT 0x04000000 // GT_CNS_INT -- constant is Vector.Count + #define GTF_BLK_VOLATILE 0x40000000 // GT_ASG, GT_STORE_BLK, GT_STORE_OBJ, GT_STORE_DYNBLK // -- is a volatile block operation #define GTF_BLK_UNALIGNED 0x02000000 // GT_ASG, GT_STORE_BLK, GT_STORE_OBJ, GT_STORE_DYNBLK // -- is an unaligned block operation -#define GTF_BLK_INIT 0x01000000 // GT_ASG, GT_STORE_BLK, GT_STORE_OBJ, GT_STORE_DYNBLK -- is an init block operation #define GTF_OVERFLOW 0x10000000 // GT_ADD, GT_SUB, GT_MUL, - Need overflow check // GT_ASG_ADD, GT_ASG_SUB, @@ -942,10 +951,13 @@ public: #define GTF_ARRLEN_ARR_IDX 0x80000000 // GT_ARR_LENGTH -- Length which feeds into an array index expression -#define GTF_LIST_AGGREGATE 0x80000000 // GT_LIST -- Indicates that this list should be treated as an - // anonymous aggregate value (e.g. a multi-value argument). +#define GTF_FIELD_LIST_HEAD 0x80000000 // GT_FIELD_LIST -- Indicates that this is the first field in a list of + // struct fields constituting a single call argument. //---------------------------------------------------------------- +#define GTF_SIMD12_OP 0x80000000 // GT_SIMD -- Indicates that the operands need to be handled as SIMD12 + // even if they have been retyped as SIMD16. +//---------------------------------------------------------------- #define GTF_STMT_CMPADD 0x80000000 // GT_STMT -- added by compiler #define GTF_STMT_HAS_CSE 0x40000000 // GT_STMT -- CSE def or use was subsituted @@ -958,8 +970,10 @@ public: #define GTF_DEBUG_NODE_MORPHED 0x00000001 // the node has been morphed (in the global morphing phase) #define GTF_DEBUG_NODE_SMALL 0x00000002 #define GTF_DEBUG_NODE_LARGE 0x00000004 +#define GTF_DEBUG_NODE_CG_PRODUCED 0x00000008 // genProduceReg has been called on this node +#define GTF_DEBUG_NODE_CG_CONSUMED 0x00000010 // genConsumeReg has been called on this node -#define GTF_DEBUG_NODE_MASK 0x00000007 // These flags are all node (rather than operation) properties. +#define GTF_DEBUG_NODE_MASK 0x0000001F // These flags are all node (rather than operation) properties. #define GTF_DEBUG_VAR_CSE_REF 0x00800000 // GT_LCL_VAR -- This is a CSE LCL_VAR node #endif // defined(DEBUG) @@ -970,6 +984,8 @@ public: #ifdef DEBUG unsigned gtTreeID; unsigned gtSeqNum; // liveness traversal order within the current statement + + int gtUseNum; // use-ordered traversal within the function #endif static const unsigned short gtOperKindTable[]; @@ -1011,9 +1027,9 @@ public: return gtType != TYP_VOID; } - if (gtOper == GT_LIST) + if (gtOper == GT_FIELD_LIST) { - return (gtFlags & GTF_LIST_AGGREGATE) != 0; + return (gtFlags & GTF_FIELD_LIST_HEAD) != 0; } return true; @@ -1033,14 +1049,14 @@ public: return IsNothingNode(); case GT_ARGPLACE: - // ARGPLACE nodes may not be present in a block's LIR sequence, but they may + case GT_LIST: + // ARGPLACE and LIST nodes may not be present in a block's LIR sequence, but they may // be present as children of an LIR node. return (gtNext == nullptr) && (gtPrev == nullptr); - case GT_LIST: - // LIST nodes may only be present in an LIR sequence if they represent aggregates. - // They are always allowed, however, as children of an LIR node. - return ((gtFlags & GTF_LIST_AGGREGATE) != 0) || ((gtNext == nullptr) && (gtPrev == nullptr)); + case GT_FIELD_LIST: + // Only the head of the FIELD_LIST is present in the block's LIR sequence. + return (((gtFlags & GTF_FIELD_LIST_HEAD) != 0) || ((gtNext == nullptr) && (gtPrev == nullptr))); case GT_ADDR: { @@ -1130,6 +1146,21 @@ public: return (gtOper == GT_LEA); } + static bool OperIsInitVal(genTreeOps gtOper) + { + return (gtOper == GT_INIT_VAL); + } + + bool OperIsInitVal() const + { + return OperIsInitVal(OperGet()); + } + + bool IsConstInitVal() + { + return (gtOper == GT_CNS_INT) || (OperIsInitVal() && (gtGetOp1()->gtOper == GT_CNS_INT)); + } + bool OperIsBlkOp(); bool OperIsCopyBlkOp(); bool OperIsInitBlkOp(); @@ -1146,6 +1177,16 @@ public: 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)); @@ -1206,7 +1247,7 @@ public: return OperIsLocalRead(OperGet()); } - bool OperIsCompare() + bool OperIsCompare() const { return (OperKind(gtOper) & GTK_RELOP) != 0; } @@ -1270,7 +1311,6 @@ public: { case GT_ADD_HI: case GT_SUB_HI: - case GT_MUL_HI: case GT_DIV_HI: case GT_MOD_HI: return true; @@ -1396,8 +1436,7 @@ public: static bool OperIsStore(genTreeOps gtOper) { return (gtOper == GT_STOREIND || gtOper == GT_STORE_LCL_VAR || gtOper == GT_STORE_LCL_FLD || - gtOper == GT_STORE_CLS_VAR || gtOper == GT_STORE_BLK || gtOper == GT_STORE_OBJ || - gtOper == GT_STORE_DYN_BLK); + gtOper == GT_STORE_BLK || gtOper == GT_STORE_OBJ || gtOper == GT_STORE_DYN_BLK); } static bool OperIsAtomicOp(genTreeOps gtOper) @@ -1425,9 +1464,34 @@ public: return OperIsSIMD(gtOper); } - bool OperIsAggregate() + bool OperIsFieldListHead() + { + return (gtOper == GT_FIELD_LIST) && ((gtFlags & GTF_FIELD_LIST_HEAD) != 0); + } + + bool OperIsConditionalJump() const + { + return (gtOper == GT_JTRUE) || (gtOper == GT_JCC); + } + + static bool OperIsBoundsCheck(genTreeOps op) + { + if (op == GT_ARR_BOUNDS_CHECK) + { + return true; + } +#ifdef FEATURE_SIMD + if (op == GT_SIMD_CHK) + { + return true; + } +#endif // FEATURE_SIMD + return false; + } + + bool OperIsBoundsCheck() const { - return (gtOper == GT_LIST) && ((gtFlags & GTF_LIST_AGGREGATE) != 0); + return OperIsBoundsCheck(OperGet()); } // Requires that "op" is an op= operator. Returns @@ -1462,6 +1526,7 @@ public: switch (gtOper) { case GT_LIST: + case GT_FIELD_LIST: case GT_INTRINSIC: case GT_LEA: #ifdef FEATURE_SIMD @@ -1474,19 +1539,47 @@ public: } static inline bool RequiresNonNullOp2(genTreeOps oper); - bool IsListForMultiRegArg(); + bool IsValidCallArgument(); #endif // DEBUG inline bool IsFPZero(); inline bool IsIntegralConst(ssize_t constVal); + inline bool IsIntegralConstVector(ssize_t constVal); inline bool IsBoxedValue(); - bool IsList() const + inline bool IsSIMDEqualityOrInequality() const; + + static bool OperIsList(genTreeOps gtOper) { return gtOper == GT_LIST; } + bool OperIsList() const + { + return OperIsList(gtOper); + } + + static bool OperIsFieldList(genTreeOps gtOper) + { + return gtOper == GT_FIELD_LIST; + } + + bool OperIsFieldList() const + { + return OperIsFieldList(gtOper); + } + + static bool OperIsAnyList(genTreeOps gtOper) + { + return OperIsList(gtOper) || OperIsFieldList(gtOper); + } + + bool OperIsAnyList() const + { + return OperIsAnyList(gtOper); + } + inline GenTreePtr MoveNext(); inline GenTreePtr Current(); @@ -1508,6 +1601,8 @@ public: // Get the parent of this node, and optionally capture the pointer to the child so that it can be modified. GenTreePtr gtGetParent(GenTreePtr** parentChildPtrPtr); + void ReplaceOperand(GenTree** useEdge, GenTree* replacement); + inline GenTreePtr gtEffectiveVal(bool commaOnly = false); // Return the child of this node if it is a GT_RELOAD or GT_COPY; otherwise simply return the node itself @@ -1536,7 +1631,13 @@ public: public: #if SMALL_TREE_NODES static unsigned char s_gtNodeSizes[]; +#if NODEBASH_STATS || MEASURE_NODE_SIZE || COUNT_AST_OPERS + static unsigned char s_gtTrueSizes[]; +#endif +#if COUNT_AST_OPERS + static LONG s_gtNodeCounts[]; #endif +#endif // SMALL_TREE_NODES static void InitNodeSize(); @@ -1555,15 +1656,19 @@ public: static bool Compare(GenTreePtr op1, GenTreePtr op2, bool swapOK = false); //--------------------------------------------------------------------- -#ifdef DEBUG - //--------------------------------------------------------------------- +#if defined(DEBUG) static const char* NodeName(genTreeOps op); +#endif +#if defined(DEBUG) || NODEBASH_STATS || MEASURE_NODE_SIZE || COUNT_AST_OPERS static const char* OpName(genTreeOps op); +#endif -//--------------------------------------------------------------------- +#if MEASURE_NODE_SIZE && SMALL_TREE_NODES + static const char* OpStructName(genTreeOps op); #endif + //--------------------------------------------------------------------- bool IsNothingNode() const; @@ -1583,6 +1688,7 @@ public: // set gtOper and only keep GTF_COMMON_MASK flags void ChangeOper(genTreeOps oper, ValueNumberUpdate vnUpdate = CLEAR_VN); void ChangeOperUnchecked(genTreeOps oper); + void SetOperRaw(genTreeOps oper); void ChangeType(var_types newType) { @@ -1597,6 +1703,20 @@ public: } } +#if SMALL_TREE_NODES +#if NODEBASH_STATS + static void RecordOperBashing(genTreeOps operOld, genTreeOps operNew); + static void ReportOperBashing(FILE* fp); +#else + static void RecordOperBashing(genTreeOps operOld, genTreeOps operNew) + { /* do nothing */ + } + static void ReportOperBashing(FILE* fp) + { /* do nothing */ + } +#endif +#endif + bool IsLocal() const { return OperIsLocal(OperGet()); @@ -1777,6 +1897,14 @@ public: bool gtOverflowEx() const; bool gtSetFlags() const; bool gtRequestSetFlags(); + + // Returns true if the codegen of this tree node + // sets ZF and SF flags. + bool gtSetZSFlags() const + { + return (gtFlags & GTF_ZSF_SET) != 0; + } + #ifdef DEBUG bool gtIsValid64RsltMul(); static int gtDispFlags(unsigned flags, unsigned debugFlags); @@ -1827,10 +1955,10 @@ public: // Returns an iterator that will produce the use edge to each operand of this node. Differs // from the sequence of nodes produced by a loop over `GetChild` in its handling of call, phi, // and block op nodes. - GenTreeUseEdgeIterator GenTree::UseEdgesBegin(); - GenTreeUseEdgeIterator GenTree::UseEdgesEnd(); + GenTreeUseEdgeIterator UseEdgesBegin(); + GenTreeUseEdgeIterator UseEdgesEnd(); - IteratorPair GenTree::UseEdges(); + IteratorPair UseEdges(); // Returns an iterator that will produce each operand of this node. Differs from the sequence // of nodes produced by a loop over `GetChild` in its handling of call, phi, and block op @@ -1866,6 +1994,10 @@ public: gtFlags &= ~GTF_REUSE_REG_VAL; } +#if MEASURE_NODE_SIZE + static void DumpNodeSizes(FILE* fp); +#endif + #ifdef DEBUG private: @@ -1931,7 +2063,7 @@ class GenTreeUseEdgeIterator final #ifdef FEATURE_SIMD void MoveToNextSIMDUseEdge(); #endif - void MoveToNextAggregateUseEdge(); + void MoveToNextFieldUseEdge(); public: GenTreeUseEdgeIterator(); @@ -2128,7 +2260,7 @@ struct GenTreeIntConCommon : public GenTree } bool ImmedValNeedsReloc(Compiler* comp); - bool GenTreeIntConCommon::ImmedValCanBeFolded(Compiler* comp, genTreeOps op); + bool ImmedValCanBeFolded(Compiler* comp, genTreeOps op); #ifdef _TARGET_XARCH_ bool FitsInAddrBase(Compiler* comp); @@ -2629,18 +2761,13 @@ struct GenTreeField : public GenTree // method names for the arguments. struct GenTreeArgList : public GenTreeOp { - bool IsAggregate() const - { - return (gtFlags & GTF_LIST_AGGREGATE) != 0; - } - GenTreePtr& Current() { return gtOp1; } GenTreeArgList*& Rest() { - assert(gtOp2 == nullptr || gtOp2->OperGet() == GT_LIST); + assert(gtOp2 == nullptr || gtOp2->OperIsAnyList()); return *reinterpret_cast(>Op2); } @@ -2654,20 +2781,68 @@ struct GenTreeArgList : public GenTreeOp { } - GenTreeArgList(GenTreePtr arg, GenTreeArgList* rest) : GenTreeOp(GT_LIST, TYP_VOID, arg, rest) + GenTreeArgList(GenTreePtr arg, GenTreeArgList* rest) : GenTreeArgList(GT_LIST, arg, rest) { - // With structs passed in multiple args we could have an arg - // GT_LIST containing a list of LCL_FLDs, see IsListForMultiRegArg() - // - assert((arg != nullptr) && ((!arg->IsList()) || (arg->IsListForMultiRegArg()))); + } + + GenTreeArgList(genTreeOps oper, GenTreePtr arg, GenTreeArgList* rest) : GenTreeOp(oper, TYP_VOID, arg, rest) + { + assert(OperIsAnyList(oper)); + assert((arg != nullptr) && arg->IsValidCallArgument()); gtFlags |= arg->gtFlags & GTF_ALL_EFFECT; if (rest != nullptr) { gtFlags |= rest->gtFlags & GTF_ALL_EFFECT; } } +}; + +// Represents a list of fields constituting a struct, when it is passed as an argument. +// The first field of the struct is marked with the GTF_FIELD_LIST_HEAD flag, and +// in LIR form it is the only member of the list that is threaded into the execution +// order. +// It differs from the GenTreeArgList in a couple of ways: +// - The entire list represents a single argument. +// - It contains additional fields to provide the offset and type of the field. +// +struct GenTreeFieldList : public GenTreeArgList +{ + unsigned gtFieldOffset; + var_types gtFieldType; + + bool IsFieldListHead() const + { + return (gtFlags & GTF_FIELD_LIST_HEAD) != 0; + } - GenTreeArgList* Prepend(Compiler* compiler, GenTree* element); +#if DEBUGGABLE_GENTREE + GenTreeFieldList() : GenTreeArgList() + { + } +#endif + + GenTreeFieldList*& Rest() + { + assert(gtOp2 == nullptr || gtOp2->OperGet() == GT_FIELD_LIST); + return *reinterpret_cast(>Op2); + } + + GenTreeFieldList(GenTreePtr arg, unsigned fieldOffset, var_types fieldType, GenTreeFieldList* prevList) + : GenTreeArgList(GT_FIELD_LIST, arg, nullptr) + { + // While GT_FIELD_LIST can be in a GT_LIST, GT_FIELD_LISTs cannot be nested or have GT_LISTs. + assert(!arg->OperIsAnyList()); + gtFieldOffset = fieldOffset; + gtFieldType = fieldType; + if (prevList == nullptr) + { + gtFlags |= GTF_FIELD_LIST_HEAD; + } + else + { + prevList->gtOp2 = this; + } + } }; // There was quite a bit of confusion in the code base about which of gtOp1 and gtOp2 was the @@ -3360,8 +3535,13 @@ struct GenTreeCall final : public GenTree bool IsHelperCall(Compiler* compiler, unsigned helper) const; + void ReplaceCallOperand(GenTree** operandUseEdge, GenTree* replacement); + + bool AreArgsComplete() const; + GenTreeCall(var_types type) : GenTree(GT_CALL, type) { + fgArgInfo = nullptr; } #if DEBUGGABLE_GENTREE GenTreeCall() : GenTree() @@ -4017,6 +4197,19 @@ struct GenTreeObj : public GenTreeBlk // Let's assert it just to be safe. noway_assert(roundUp(gtBlkSize, REGSIZE_BYTES) == gtBlkSize); } + else + { + genTreeOps newOper = GT_BLK; + if (gtOper == GT_STORE_OBJ) + { + newOper = GT_STORE_BLK; + } + else + { + assert(gtOper == GT_OBJ); + } + SetOper(newOper); + } } void CopyGCInfo(GenTreeObj* srcObj) @@ -4068,6 +4261,8 @@ public: GenTreeDynBlk(GenTreePtr addr, GenTreePtr dynamicSize) : GenTreeBlk(GT_DYN_BLK, TYP_STRUCT, addr, 0), gtDynamicSize(dynamicSize), gtEvalSizeFirst(false) { + // Conservatively the 'addr' could be null or point into the global heap. + gtFlags |= GTF_EXCEPT | GTF_GLOB_REF; gtFlags |= (dynamicSize->gtFlags & GTF_ALL_EFFECT); } @@ -4198,10 +4393,7 @@ struct GenTreeStmt : public GenTree GenTreePtr gtStmtExpr; // root of the expression tree GenTreePtr gtStmtList; // first node (for forward walks) InlineContext* gtInlineContext; // The inline context for this statement. - -#if defined(DEBUGGING_SUPPORT) || defined(DEBUG) - IL_OFFSETX gtStmtILoffsx; // instr offset (if available) -#endif + IL_OFFSETX gtStmtILoffsx; // instr offset (if available) #ifdef DEBUG IL_OFFSET gtStmtLastILoffs; // instr offset at end of stmt @@ -4240,9 +4432,7 @@ struct GenTreeStmt : public GenTree , gtStmtExpr(expr) , gtStmtList(nullptr) , gtInlineContext(nullptr) -#if defined(DEBUGGING_SUPPORT) || defined(DEBUG) , gtStmtILoffsx(offset) -#endif #ifdef DEBUG , gtStmtLastILoffs(BAD_IL_OFFSET) #endif @@ -4350,20 +4540,19 @@ struct GenTreePutArgStk : public GenTreeUnOp GenTreePutArgStk(genTreeOps oper, var_types type, - unsigned slotNum FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(unsigned numSlots) - FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(bool isStruct), + unsigned slotNum PUT_STRUCT_ARG_STK_ONLY_ARG(unsigned numSlots) + PUT_STRUCT_ARG_STK_ONLY_ARG(bool isStruct), bool _putInIncomingArgArea = false DEBUGARG(GenTreePtr callNode = nullptr) DEBUGARG(bool largeNode = false)) : GenTreeUnOp(oper, type DEBUGARG(largeNode)) , gtSlotNum(slotNum) , putInIncomingArgArea(_putInIncomingArgArea) -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING - , gtPutArgStkKind(PutArgStkKindInvalid) +#ifdef FEATURE_PUT_STRUCT_ARG_STK + , gtPutArgStkKind(Kind::Invalid) , gtNumSlots(numSlots) - , gtIsStruct(isStruct) , gtNumberReferenceSlots(0) , gtGcPtrs(nullptr) -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING +#endif // FEATURE_PUT_STRUCT_ARG_STK { #ifdef DEBUG gtCall = callNode; @@ -4373,20 +4562,18 @@ struct GenTreePutArgStk : public GenTreeUnOp GenTreePutArgStk(genTreeOps oper, var_types type, GenTreePtr op1, - unsigned slotNum FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(unsigned numSlots) - FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(bool isStruct), + unsigned slotNum PUT_STRUCT_ARG_STK_ONLY_ARG(unsigned numSlots), bool _putInIncomingArgArea = false DEBUGARG(GenTreePtr callNode = nullptr) DEBUGARG(bool largeNode = false)) : GenTreeUnOp(oper, type, op1 DEBUGARG(largeNode)) , gtSlotNum(slotNum) , putInIncomingArgArea(_putInIncomingArgArea) -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING - , gtPutArgStkKind(PutArgStkKindInvalid) +#ifdef FEATURE_PUT_STRUCT_ARG_STK + , gtPutArgStkKind(Kind::Invalid) , gtNumSlots(numSlots) - , gtIsStruct(isStruct) , gtNumberReferenceSlots(0) , gtGcPtrs(nullptr) -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING +#endif // FEATURE_PUT_STRUCT_ARG_STK { #ifdef DEBUG gtCall = callNode; @@ -4397,18 +4584,16 @@ struct GenTreePutArgStk : public GenTreeUnOp GenTreePutArgStk(genTreeOps oper, var_types type, - unsigned slotNum FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(unsigned numSlots) - FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(bool isStruct) DEBUGARG(GenTreePtr callNode = NULL) - DEBUGARG(bool largeNode = false)) + unsigned slotNum PUT_STRUCT_ARG_STK_ONLY_ARG(unsigned numSlots) + DEBUGARG(GenTreePtr callNode = NULL) DEBUGARG(bool largeNode = false)) : GenTreeUnOp(oper, type DEBUGARG(largeNode)) , gtSlotNum(slotNum) -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING - , gtPutArgStkKind(PutArgStkKindInvalid) +#ifdef FEATURE_PUT_STRUCT_ARG_STK + , gtPutArgStkKind(Kind::Invalid) , gtNumSlots(numSlots) - , gtIsStruct(isStruct) , gtNumberReferenceSlots(0) , gtGcPtrs(nullptr) -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING +#endif // FEATURE_PUT_STRUCT_ARG_STK { #ifdef DEBUG gtCall = callNode; @@ -4418,18 +4603,16 @@ struct GenTreePutArgStk : public GenTreeUnOp GenTreePutArgStk(genTreeOps oper, var_types type, GenTreePtr op1, - unsigned slotNum FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(unsigned numSlots) - FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(bool isStruct) DEBUGARG(GenTreePtr callNode = NULL) - DEBUGARG(bool largeNode = false)) + unsigned slotNum PUT_STRUCT_ARG_STK_ONLY_ARG(unsigned numSlots) + DEBUGARG(GenTreePtr callNode = NULL) DEBUGARG(bool largeNode = false)) : GenTreeUnOp(oper, type, op1 DEBUGARG(largeNode)) , gtSlotNum(slotNum) -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING - , gtPutArgStkKind(PutArgStkKindInvalid) +#ifdef FEATURE_PUT_STRUCT_ARG_STK + , gtPutArgStkKind(Kind::Invalid) , gtNumSlots(numSlots) - , gtIsStruct(isStruct) , gtNumberReferenceSlots(0) , gtGcPtrs(nullptr) -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING +#endif // FEATURE_PUT_STRUCT_ARG_STK { #ifdef DEBUG gtCall = callNode; @@ -4442,14 +4625,14 @@ struct GenTreePutArgStk : public GenTreeUnOp return gtSlotNum * TARGET_POINTER_SIZE; } -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING +#ifdef FEATURE_PUT_STRUCT_ARG_STK unsigned getArgSize() { return gtNumSlots * TARGET_POINTER_SIZE; } -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING +#endif // FEATURE_PUT_STRUCT_ARG_STK -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING +#ifdef FEATURE_PUT_STRUCT_ARG_STK //------------------------------------------------------------------------ // setGcPointers: Sets the number of references and the layout of the struct object returned by the VM. // @@ -4471,27 +4654,32 @@ struct GenTreePutArgStk : public GenTreeUnOp gtNumberReferenceSlots = numPointers; gtGcPtrs = pointers; } -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING +#endif // FEATURE_PUT_STRUCT_ARG_STK #ifdef DEBUG GenTreePtr gtCall; // the call node to which this argument belongs #endif -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING +#ifdef FEATURE_PUT_STRUCT_ARG_STK // Instruction selection: during codegen time, what code sequence we will be using // to encode this operation. + // TODO-Throughput: The following information should be obtained from the child + // block node. - enum PutArgStkKind : __int8{ - PutArgStkKindInvalid, PutArgStkKindRepInstr, PutArgStkKindUnroll, + enum class Kind : __int8{ + Invalid, RepInstr, Unroll, Push, PushAllSlots, }; - PutArgStkKind gtPutArgStkKind; + Kind gtPutArgStkKind; + bool isPushKind() + { + return (gtPutArgStkKind == Kind::Push) || (gtPutArgStkKind == Kind::PushAllSlots); + } unsigned gtNumSlots; // Number of slots for the argument to be passed on stack - bool gtIsStruct; // This stack arg is a struct. unsigned gtNumberReferenceSlots; // Number of reference slots. BYTE* gtGcPtrs; // gcPointers -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING +#endif // FEATURE_PUT_STRUCT_ARG_STK #if DEBUGGABLE_GENTREE GenTreePutArgStk() : GenTreeUnOp() @@ -4644,6 +4832,23 @@ struct GenTreeAllocObj final : public GenTreeUnOp #endif }; +struct GenTreeJumpCC final : public GenTree +{ + genTreeOps gtCondition; // any relop + + GenTreeJumpCC(genTreeOps condition) + : GenTree(GT_JCC, TYP_VOID DEBUGARG(/*largeNode*/ FALSE)), gtCondition(condition) + { + assert(OperIsCompare(condition)); + } + +#if DEBUGGABLE_GENTREE + GenTreeJumpCC() : GenTree() + { + } +#endif // DEBUGGABLE_GENTREE +}; + //------------------------------------------------------------------------ // Deferred inline functions of GenTree -- these need the subtypes above to // be defined already. @@ -4673,34 +4878,31 @@ inline bool GenTree::OperIsDynBlkOp() return false; } -inline bool GenTree::OperIsCopyBlkOp() +inline bool GenTree::OperIsInitBlkOp() { - if (gtOper == GT_ASG) + if (!OperIsBlkOp()) { - return (varTypeIsStruct(gtGetOp1()) && ((gtFlags & GTF_BLK_INIT) == 0)); + return false; } #ifndef LEGACY_BACKEND - else if (OperIsStoreBlk()) - { - return ((gtFlags & GTF_BLK_INIT) == 0); - } -#endif - return false; -} - -inline bool GenTree::OperIsInitBlkOp() -{ + GenTree* src; if (gtOper == GT_ASG) { - return (varTypeIsStruct(gtGetOp1()) && ((gtFlags & GTF_BLK_INIT) != 0)); + src = gtGetOp2(); } -#ifndef LEGACY_BACKEND - else if (OperIsStoreBlk()) + else { - return ((gtFlags & GTF_BLK_INIT) != 0); + src = AsBlk()->Data()->gtSkipReloadOrCopy(); } -#endif - return false; +#else // LEGACY_BACKEND + GenTree* src = gtGetOp2(); +#endif // LEGACY_BACKEND + return src->OperIsInitVal() || src->OperIsConst(); +} + +inline bool GenTree::OperIsCopyBlkOp() +{ + return OperIsBlkOp() && !OperIsInitBlkOp(); } //------------------------------------------------------------------------ @@ -4748,34 +4950,63 @@ inline bool GenTree::IsIntegralConst(ssize_t constVal) return false; } +//------------------------------------------------------------------- +// IsIntegralConstVector: returns true if this this is a SIMD vector +// with all its elements equal to an integral constant. +// +// Arguments: +// constVal - const value of vector element +// +// Returns: +// True if this represents an integral const SIMD vector. +// +inline bool GenTree::IsIntegralConstVector(ssize_t constVal) +{ +#ifdef FEATURE_SIMD + // SIMDIntrinsicInit intrinsic with a const value as initializer + // represents a const vector. + if ((gtOper == GT_SIMD) && (gtSIMD.gtSIMDIntrinsicID == SIMDIntrinsicInit) && gtGetOp1()->IsIntegralConst(constVal)) + { + assert(varTypeIsIntegral(gtSIMD.gtSIMDBaseType)); + assert(gtGetOp2() == nullptr); + return true; + } +#endif + + return false; +} + inline bool GenTree::IsBoxedValue() { assert(gtOper != GT_BOX || gtBox.BoxOp() != nullptr); return (gtOper == GT_BOX) && (gtFlags & GTF_BOX_VALUE); } +inline bool GenTree::IsSIMDEqualityOrInequality() const +{ +#ifdef FEATURE_SIMD + if (gtOper == GT_SIMD) + { + // Has to cast away const-ness since AsSIMD() method is non-const. + GenTreeSIMD* simdNode = const_cast(this)->AsSIMD(); + return (simdNode->gtSIMDIntrinsicID == SIMDIntrinsicOpEquality || + simdNode->gtSIMDIntrinsicID == SIMDIntrinsicOpInEquality); + } +#endif + + return false; +} + inline GenTreePtr GenTree::MoveNext() { - assert(IsList()); + assert(OperIsAnyList()); return gtOp.gtOp2; } #ifdef DEBUG //------------------------------------------------------------------------ -// IsListForMultiRegArg: Given an GenTree node that represents an argument -// enforce (or don't enforce) the following invariant. -// -// For LEGACY_BACKEND or architectures that don't support MultiReg args -// we don't allow a GT_LIST at all. -// -// Currently for AMD64 UNIX we allow a limited case where a GT_LIST is -// allowed but every element must be a GT_LCL_FLD. -// -// For the future targets that allow for Multireg args (and this includes -// the current ARM64 target) we allow a GT_LIST of arbitrary nodes, these -// would typically start out as GT_LCL_VARs or GT_LCL_FLDS or GT_INDs, -// but could be changed into constants or GT_COMMA trees by the later -// optimization phases. +// IsValidCallArgument: Given an GenTree node that represents an argument +// enforce (or don't enforce) the following invariant. // // Arguments: // instance method for a GenTree node @@ -4784,33 +5015,46 @@ inline GenTreePtr GenTree::MoveNext() // true: the GenTree node is accepted as a valid argument // false: the GenTree node is not accepted as a valid argumeny // -inline bool GenTree::IsListForMultiRegArg() +// Notes: +// For targets that don't support arguments as a list of fields, we do not support GT_FIELD_LIST. +// +// Currently for AMD64 UNIX we allow a limited case where a GT_FIELD_LIST is +// allowed but every element must be a GT_LCL_FLD. +// +// For the future targets that allow for Multireg args (and this includes the current ARM64 target), +// or that allow for passing promoted structs, we allow a GT_FIELD_LIST of arbitrary nodes. +// These would typically start out as GT_LCL_VARs or GT_LCL_FLDS or GT_INDs, +// but could be changed into constants or GT_COMMA trees by the later +// optimization phases. + +inline bool GenTree::IsValidCallArgument() { - if (!IsList()) + if (OperIsList()) { - // We don't have a GT_LIST, so just return true. - return true; + // GT_FIELD_LIST is the only list allowed. + return false; } - else // We do have a GT_LIST + if (OperIsFieldList()) { -#if defined(LEGACY_BACKEND) || !FEATURE_MULTIREG_ARGS - - // Not allowed to have a GT_LIST for an argument - // unless we have a RyuJIT backend and FEATURE_MULTIREG_ARGS +#if defined(LEGACY_BACKEND) || (!FEATURE_MULTIREG_ARGS && !FEATURE_PUT_STRUCT_ARG_STK) + // Not allowed to have a GT_FIELD_LIST for an argument + // unless we have a RyuJIT backend and FEATURE_MULTIREG_ARGS or FEATURE_PUT_STRUCT_ARG_STK return false; -#else // we have RyuJIT backend and FEATURE_MULTIREG_ARGS +#else // we have RyuJIT backend and FEATURE_MULTIREG_ARGS or FEATURE_PUT_STRUCT_ARG_STK #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING - // For UNIX ABI we currently only allow a GT_LIST of GT_LCL_FLDs nodes + // For UNIX ABI we currently only allow a GT_FIELD_LIST of GT_LCL_FLDs nodes GenTree* gtListPtr = this; while (gtListPtr != nullptr) { // ToDo: fix UNIX_AMD64 so that we do not generate this kind of a List // Note the list as currently created is malformed, as the last entry is a nullptr if (gtListPtr->Current() == nullptr) + { break; + } // Only a list of GT_LCL_FLDs is allowed if (gtListPtr->Current()->OperGet() != GT_LCL_FLD) @@ -4821,25 +5065,27 @@ inline bool GenTree::IsListForMultiRegArg() } #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING - // Note that for non-UNIX ABI the GT_LIST may contain any node + // Note that for non-UNIX ABI the GT_FIELD_LIST may contain any node // - // We allow this GT_LIST as an argument + // We allow this GT_FIELD_LIST as an argument return true; -#endif // RyuJIT backend and FEATURE_MULTIREG_ARGS +#endif // FEATURE_MULTIREG_ARGS } + // We don't have either kind of list, so it satisfies the invariant. + return true; } #endif // DEBUG inline GenTreePtr GenTree::Current() { - assert(IsList()); + assert(OperIsAnyList()); return gtOp.gtOp1; } inline GenTreePtr* GenTree::pCurrent() { - assert(IsList()); + assert(OperIsAnyList()); return &(gtOp.gtOp1); } @@ -4917,23 +5163,22 @@ inline GenTreePtr GenTree::gtGetOp2() inline GenTreePtr GenTree::gtEffectiveVal(bool commaOnly) { - switch (gtOper) + GenTree* effectiveVal = this; + for (;;) { - case GT_COMMA: - return gtOp.gtOp2->gtEffectiveVal(commaOnly); - - case GT_NOP: - if (!commaOnly && gtOp.gtOp1 != nullptr) - { - return gtOp.gtOp1->gtEffectiveVal(); - } - break; - - default: - break; + if (effectiveVal->gtOper == GT_COMMA) + { + effectiveVal = effectiveVal->gtOp.gtOp2; + } + else if (!commaOnly && (effectiveVal->gtOper == GT_NOP) && (effectiveVal->gtOp.gtOp1 != nullptr)) + { + effectiveVal = effectiveVal->gtOp.gtOp1; + } + else + { + return effectiveVal; + } } - - return this; } inline GenTree* GenTree::gtSkipReloadOrCopy() diff --git a/src/jit/gschecks.cpp b/src/jit/gschecks.cpp index 43cbb89..9255d8f 100644 --- a/src/jit/gschecks.cpp +++ b/src/jit/gschecks.cpp @@ -40,9 +40,9 @@ const unsigned NO_SHADOW_COPY = UINT_MAX; * The current function has an unsafe buffer on the stack. Search for vulnerable * parameters which could be used to modify a code address and take over the process * in the case of a buffer overrun. Create a safe local copy for each vulnerable parameter, - * which will be allocated bellow the unsafe buffer. Change uses of the param to the + * which will be allocated bellow the unsafe buffer. Change uses of the param to the * shadow copy. - * + * * A pointer under indirection is considered vulnerable. A malicious user could read from * protected memory or write to it. If a parameter is assigned/computed into another variable, * and is a pointer (i.e., under indirection), then we consider the variable to be part of the @@ -58,7 +58,7 @@ void Compiler::gsCopyShadowParams() // Allocate array for shadow param info gsShadowVarInfo = new (this, CMK_Unknown) ShadowParamVarInfo[lvaCount](); - // Find groups of variables assigned to each other, and also + // Find groups of variables assigned to each other, and also // tracks variables which are dereferenced and marks them as ptrs. // Look for assignments to *p, and ptrs passed to functions if (gsFindVulnerableParams()) @@ -83,7 +83,7 @@ struct MarkPtrsInfo { printf( "[MarkPtrsInfo] = {comp = %p, lvAssignDef = %d, isAssignSrc = %d, isUnderIndir = %d, skipNextNode = %d}\n", - comp, lvAssignDef, isAssignSrc, isUnderIndir, skipNextNode); + comp, lvAssignDef, isAssignSrc, isUnderIndir, skipNextNode); } #endif }; @@ -129,7 +129,7 @@ Compiler::fgWalkResult Compiler::gsMarkPtrsAndAssignGroups(GenTreePtr* pTree, fg newState.isUnderIndir = true; { newState.skipNextNode = true; // Don't have to worry about which kind of node we're dealing with - comp->fgWalkTreePre(&tree, comp->gsMarkPtrsAndAssignGroups, (void *)&newState); + comp->fgWalkTreePre(&tree, comp->gsMarkPtrsAndAssignGroups, (void*)&newState); } return WALK_SKIP_SUBTREES; @@ -160,50 +160,50 @@ Compiler::fgWalkResult Compiler::gsMarkPtrsAndAssignGroups(GenTreePtr* pTree, fg { shadowVarInfo[pState->lvAssignDef].assignGroup->bitVectSet(lclNum); } - + // Point both to the same bit vector shadowVarInfo[lclNum].assignGroup = shadowVarInfo[pState->lvAssignDef].assignGroup; } else if (shadowVarInfo[lclNum].assignGroup) { shadowVarInfo[lclNum].assignGroup->bitVectSet(pState->lvAssignDef); - + // Point both to the same bit vector shadowVarInfo[pState->lvAssignDef].assignGroup = shadowVarInfo[lclNum].assignGroup; } else { - FixedBitVect* bv = FixedBitVect::bitVectInit(pState->comp->lvaCount, pState->comp); + FixedBitVect* bv = FixedBitVect::bitVectInit(pState->comp->lvaCount, pState->comp); // (shadowVarInfo[pState->lvAssignDef] == NULL && shadowVarInfo[lclNew] == NULL); // Neither of them has an assign group yet. Make a new one. shadowVarInfo[pState->lvAssignDef].assignGroup = bv; - shadowVarInfo[lclNum].assignGroup = bv; + shadowVarInfo[lclNum].assignGroup = bv; bv->bitVectSet(pState->lvAssignDef); bv->bitVectSet(lclNum); } } return WALK_CONTINUE; - + // Calls - Mark arg variables case GT_CALL: newState.isUnderIndir = false; - newState.isAssignSrc = false; + newState.isAssignSrc = false; { if (tree->gtCall.gtCallObjp) { newState.isUnderIndir = true; - comp->fgWalkTreePre(&tree->gtCall.gtCallObjp, gsMarkPtrsAndAssignGroups, (void*)&newState); + comp->fgWalkTreePre(&tree->gtCall.gtCallObjp, gsMarkPtrsAndAssignGroups, (void*)&newState); } for (GenTreeArgList* args = tree->gtCall.gtCallArgs; args; args = args->Rest()) { - comp->fgWalkTreePre(&args->Current(), gsMarkPtrsAndAssignGroups, (void*)&newState); + comp->fgWalkTreePre(&args->Current(), gsMarkPtrsAndAssignGroups, (void*)&newState); } for (GenTreeArgList* args = tree->gtCall.gtCallLateArgs; args; args = args->Rest()) { - comp->fgWalkTreePre(&args->Current(), gsMarkPtrsAndAssignGroups, (void*)&newState); + comp->fgWalkTreePre(&args->Current(), gsMarkPtrsAndAssignGroups, (void*)&newState); } if (tree->gtCall.gtCallType == CT_INDIRECT) @@ -213,7 +213,7 @@ Compiler::fgWalkResult Compiler::gsMarkPtrsAndAssignGroups(GenTreePtr* pTree, fg // A function pointer is treated like a write-through pointer since // it controls what code gets executed, and so indirectly can cause // a write to memory. - comp->fgWalkTreePre(&tree->gtCall.gtCallAddr, gsMarkPtrsAndAssignGroups, (void*)&newState); + comp->fgWalkTreePre(&tree->gtCall.gtCallAddr, gsMarkPtrsAndAssignGroups, (void*)&newState); } } return WALK_SKIP_SUBTREES; @@ -223,7 +223,7 @@ Compiler::fgWalkResult Compiler::gsMarkPtrsAndAssignGroups(GenTreePtr* pTree, fg // We'll assume p in "**p = " can be vulnerable because by changing 'p', someone // could control where **p stores to. { - comp->fgWalkTreePre(&tree->gtOp.gtOp1, comp->gsMarkPtrsAndAssignGroups, (void*)&newState); + comp->fgWalkTreePre(&tree->gtOp.gtOp1, comp->gsMarkPtrsAndAssignGroups, (void*)&newState); } return WALK_SKIP_SUBTREES; @@ -251,7 +251,7 @@ Compiler::fgWalkResult Compiler::gsMarkPtrsAndAssignGroups(GenTreePtr* pTree, fg { // Walk dst side comp->fgWalkTreePre(&tree->gtOp.gtOp1, comp->gsMarkPtrsAndAssignGroups, (void*)&newState); - + // Now handle src side isLocVar = tree->gtOp.gtOp1->OperGet() == GT_LCL_VAR; isLocFld = tree->gtOp.gtOp1->OperGet() == GT_LCL_FLD; @@ -262,7 +262,7 @@ Compiler::fgWalkResult Compiler::gsMarkPtrsAndAssignGroups(GenTreePtr* pTree, fg newState.lvAssignDef = lclNum; newState.isAssignSrc = true; } - + comp->fgWalkTreePre(&tree->gtOp.gtOp2, comp->gsMarkPtrsAndAssignGroups, (void*)&newState); } @@ -377,7 +377,7 @@ bool Compiler::gsFindVulnerableParams() */ void Compiler::gsParamsToShadows() { - // Cache old count since we'll add new variables, and + // Cache old count since we'll add new variables, and // gsShadowVarInfo will not grow to accomodate the new ones. UINT lvaOldCount = lvaCount; @@ -513,7 +513,7 @@ void Compiler::gsParamsToShadows() GenTreePtr src = gtNewLclvNode(shadowVar, lvaTable[shadowVar].TypeGet()); GenTreePtr dst = gtNewLclvNode(lclNum, varDsc->TypeGet()); - + src->gtFlags |= GTF_DONT_CSE; dst->gtFlags |= GTF_DONT_CSE; @@ -530,7 +530,7 @@ void Compiler::gsParamsToShadows() { opAssign = gtNewAssignNode(dst, src); } - + (void)fgInsertStmtNearEnd(block, fgMorphTree(opAssign)); } } @@ -552,8 +552,8 @@ Compiler::fgWalkResult Compiler::gsReplaceShadowParams(GenTreePtr* pTree, fgWalk { asg = tree; // "asg" is the assignment tree. tree = tree->gtOp.gtOp1; // "tree" is the local var tree at the left-hand size of the assignment. - } - + } + if (tree->gtOper == GT_LCL_VAR || tree->gtOper == GT_LCL_FLD) { UINT paramNum = tree->gtLclVarCommon.gtLclNum; @@ -571,7 +571,7 @@ Compiler::fgWalkResult Compiler::gsReplaceShadowParams(GenTreePtr* pTree, fgWalk if (varTypeIsSmall(comp->lvaTable[paramNum].TypeGet())) { tree->gtType = TYP_INT; - if (asg) + if (asg) { // If this is an assignment tree, propagate the type to it as well. asg->gtType = TYP_INT; diff --git a/src/jit/gtlist.h b/src/jit/gtlist.h index a03bcfe..92265a7 100644 --- a/src/jit/gtlist.h +++ b/src/jit/gtlist.h @@ -9,245 +9,270 @@ #endif /*****************************************************************************/ // -// Node enum -// , "Node name" -// ,commutative -// ,operKind +// Node enum +// ,"Node name" +// ,GenTree struct flavor +// ,commutative +// ,operKind -GTNODE(NONE , "" ,0,GTK_SPECIAL) +GTNODE(NONE , "" ,char ,0,GTK_SPECIAL) //----------------------------------------------------------------------------- // Leaf nodes (i.e. these nodes have no sub-operands): //----------------------------------------------------------------------------- -GTNODE(LCL_VAR , "lclVar" ,0,GTK_LEAF|GTK_LOCAL) // local variable -GTNODE(LCL_FLD , "lclFld" ,0,GTK_LEAF|GTK_LOCAL) // field in a non-primitive variable -GTNODE(LCL_VAR_ADDR , "&lclVar" ,0,GTK_LEAF) // address of local variable -GTNODE(LCL_FLD_ADDR , "&lclFld" ,0,GTK_LEAF) // address of field in a non-primitive variable -GTNODE(STORE_LCL_VAR , "st.lclVar" ,0,GTK_UNOP|GTK_LOCAL|GTK_NOVALUE) // store to local variable -GTNODE(STORE_LCL_FLD , "st.lclFld" ,0,GTK_UNOP|GTK_LOCAL|GTK_NOVALUE) // store to field in a non-primitive variable -GTNODE(CATCH_ARG , "catchArg" ,0,GTK_LEAF) // Exception object in a catch block -GTNODE(LABEL , "codeLabel" ,0,GTK_LEAF) // Jump-target -GTNODE(FTN_ADDR , "ftnAddr" ,0,GTK_LEAF) // Address of a function -GTNODE(RET_EXPR , "retExpr" ,0,GTK_LEAF) // Place holder for the return expression from an inline candidate +GTNODE(LCL_VAR , "lclVar" ,GenTreeLclVar ,0,GTK_LEAF|GTK_LOCAL) // local variable +GTNODE(LCL_FLD , "lclFld" ,GenTreeLclFld ,0,GTK_LEAF|GTK_LOCAL) // field in a non-primitive variable +GTNODE(LCL_VAR_ADDR , "&lclVar" ,GenTreeLclVar ,0,GTK_LEAF) // address of local variable +GTNODE(LCL_FLD_ADDR , "&lclFld" ,GenTreeLclFld ,0,GTK_LEAF) // address of field in a non-primitive variable +GTNODE(STORE_LCL_VAR , "st.lclVar" ,GenTreeLclVar ,0,GTK_UNOP|GTK_LOCAL|GTK_NOVALUE) // store to local variable +GTNODE(STORE_LCL_FLD , "st.lclFld" ,GenTreeLclFld ,0,GTK_UNOP|GTK_LOCAL|GTK_NOVALUE) // store to field in a non-primitive variable +GTNODE(CATCH_ARG , "catchArg" ,GenTree ,0,GTK_LEAF) // Exception object in a catch block +GTNODE(LABEL , "codeLabel" ,GenTreeLabel ,0,GTK_LEAF) // Jump-target +GTNODE(FTN_ADDR , "ftnAddr" ,GenTreeFptrVal ,0,GTK_LEAF) // Address of a function +GTNODE(RET_EXPR , "retExpr" ,GenTreeRetExpr ,0,GTK_LEAF) // Place holder for the return expression from an inline candidate //----------------------------------------------------------------------------- // Constant nodes: //----------------------------------------------------------------------------- -GTNODE(CNS_INT , "const" ,0,GTK_LEAF|GTK_CONST) -GTNODE(CNS_LNG , "lconst" ,0,GTK_LEAF|GTK_CONST) -GTNODE(CNS_DBL , "dconst" ,0,GTK_LEAF|GTK_CONST) -GTNODE(CNS_STR , "sconst" ,0,GTK_LEAF|GTK_CONST) +GTNODE(CNS_INT , "const" ,GenTreeIntCon ,0,GTK_LEAF|GTK_CONST) +GTNODE(CNS_LNG , "lconst" ,GenTreeLngCon ,0,GTK_LEAF|GTK_CONST) +GTNODE(CNS_DBL , "dconst" ,GenTreeDblCon ,0,GTK_LEAF|GTK_CONST) +GTNODE(CNS_STR , "sconst" ,GenTreeStrCon ,0,GTK_LEAF|GTK_CONST) //----------------------------------------------------------------------------- // Unary operators (1 operand): //----------------------------------------------------------------------------- -GTNODE(NOT , "~" ,0,GTK_UNOP) -GTNODE(NOP , "nop" ,0,GTK_UNOP) -GTNODE(NEG , "unary -" ,0,GTK_UNOP) -GTNODE(COPY , "copy" ,0,GTK_UNOP) // Copies a variable from its current location to a register that satisfies - // code generation constraints. The child is the actual lclVar node. -GTNODE(RELOAD , "reload" ,0,GTK_UNOP) -GTNODE(CHS , "flipsign" ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) // GT_CHS is actually unary -- op2 is ignored. - // Changing to unary presently causes problems, though -- take a little work to fix. - -GTNODE(ARR_LENGTH , "arrLen" ,0,GTK_UNOP|GTK_EXOP) // array-length - -GTNODE(INTRINSIC , "intrinsic" ,0,GTK_BINOP|GTK_EXOP) // intrinsics - -GTNODE(LOCKADD , "lockAdd" ,0,GTK_BINOP|GTK_NOVALUE) -GTNODE(XADD , "XAdd" ,0,GTK_BINOP) -GTNODE(XCHG , "Xchg" ,0,GTK_BINOP) -GTNODE(CMPXCHG , "cmpxchg" ,0,GTK_SPECIAL) -GTNODE(MEMORYBARRIER , "memoryBarrier" ,0,GTK_LEAF|GTK_NOVALUE) - -GTNODE(CAST , "cast" ,0,GTK_UNOP|GTK_EXOP) // conversion to another type -GTNODE(CKFINITE , "ckfinite" ,0,GTK_UNOP) // Check for NaN -GTNODE(LCLHEAP , "lclHeap" ,0,GTK_UNOP) // alloca() -GTNODE(JMP , "jump" ,0,GTK_LEAF|GTK_NOVALUE) // Jump to another function - - -GTNODE(ADDR , "addr" ,0,GTK_UNOP) // address of -GTNODE(IND , "indir" ,0,GTK_UNOP) // load indirection -GTNODE(STOREIND , "storeIndir" ,0,GTK_BINOP|GTK_NOVALUE) // store indirection - - // TODO-Cleanup: GT_ARR_BOUNDS_CHECK should be made a GTK_BINOP now that it has only two child nodes -GTNODE(ARR_BOUNDS_CHECK , "arrBndsChk" ,0,GTK_SPECIAL|GTK_NOVALUE) // array bounds check -GTNODE(OBJ , "obj" ,0,GTK_UNOP|GTK_EXOP) // Object that MAY have gc pointers, and thus includes the relevant gc layout info. -GTNODE(STORE_OBJ , "storeObj" ,0,GTK_BINOP|GTK_EXOP|GTK_NOVALUE) // Object that MAY have gc pointers, and thus includes the relevant gc layout info. -GTNODE(BLK , "blk" ,0,GTK_UNOP) // Block/object with no gc pointers, and with a known size (e.g. a struct with no gc fields) -GTNODE(STORE_BLK , "storeBlk" ,0,GTK_BINOP|GTK_NOVALUE) // Block/object with no gc pointers, and with a known size (e.g. a struct with no gc fields) -GTNODE(DYN_BLK , "DynBlk" ,0,GTK_SPECIAL) // Dynamically sized block object -GTNODE(STORE_DYN_BLK , "storeDynBlk" ,0,GTK_SPECIAL|GTK_NOVALUE) // Dynamically sized block object -GTNODE(BOX , "box" ,0,GTK_UNOP|GTK_EXOP|GTK_NOTLIR) +GTNODE(NOT , "~" ,GenTreeOp ,0,GTK_UNOP) +GTNODE(NOP , "nop" ,GenTree ,0,GTK_UNOP) +GTNODE(NEG , "unary -" ,GenTreeOp ,0,GTK_UNOP) +GTNODE(COPY , "copy" ,GenTreeCopyOrReload,0,GTK_UNOP) // Copies a variable from its current location to a register that satisfies + // code generation constraints. The child is the actual lclVar node. +GTNODE(RELOAD , "reload" ,GenTreeCopyOrReload,0,GTK_UNOP) +GTNODE(CHS , "flipsign" ,GenTreeOp ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) // GT_CHS is actually unary -- op2 is ignored. + // Changing to unary presently causes problems, though -- take a little work to fix. + +GTNODE(ARR_LENGTH , "arrLen" ,GenTreeArrLen ,0,GTK_UNOP|GTK_EXOP) // array-length + +GTNODE(INTRINSIC , "intrinsic" ,GenTreeIntrinsic ,0,GTK_BINOP|GTK_EXOP) // intrinsics + +GTNODE(LOCKADD , "lockAdd" ,GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE) +GTNODE(XADD , "XAdd" ,GenTreeOp ,0,GTK_BINOP) +GTNODE(XCHG , "Xchg" ,GenTreeOp ,0,GTK_BINOP) +GTNODE(CMPXCHG , "cmpxchg" ,GenTreeCmpXchg ,0,GTK_SPECIAL) +GTNODE(MEMORYBARRIER , "memoryBarrier",GenTree ,0,GTK_LEAF|GTK_NOVALUE) + +GTNODE(CAST , "cast" ,GenTreeCast ,0,GTK_UNOP|GTK_EXOP) // conversion to another type +GTNODE(CKFINITE , "ckfinite" ,GenTreeOp ,0,GTK_UNOP) // Check for NaN +GTNODE(LCLHEAP , "lclHeap" ,GenTreeOp ,0,GTK_UNOP) // alloca() +GTNODE(JMP , "jump" ,GenTreeVal ,0,GTK_LEAF|GTK_NOVALUE) // Jump to another function + +GTNODE(ADDR , "addr" ,GenTreeOp ,0,GTK_UNOP) // address of +GTNODE(IND , "indir" ,GenTreeOp ,0,GTK_UNOP) // load indirection +GTNODE(STOREIND , "storeIndir" ,GenTreeStoreInd ,0,GTK_BINOP|GTK_NOVALUE) // store indirection + + // TODO-Cleanup: GT_ARR_BOUNDS_CHECK should be made a GTK_BINOP now that it has only two child nodes +GTNODE(ARR_BOUNDS_CHECK , "arrBndsChk" ,GenTreeBoundsChk ,0,GTK_SPECIAL|GTK_NOVALUE)// array bounds check +GTNODE(OBJ , "obj" ,GenTreeObj ,0,GTK_UNOP|GTK_EXOP) // Object that MAY have gc pointers, and thus includes the relevant gc layout info. +GTNODE(STORE_OBJ , "storeObj" ,GenTreeBlk ,0,GTK_BINOP|GTK_EXOP|GTK_NOVALUE) // Object that MAY have gc pointers, and thus includes the relevant gc layout info. +GTNODE(BLK , "blk" ,GenTreeBlk ,0,GTK_UNOP) // Block/object with no gc pointers, and with a known size (e.g. a struct with no gc fields) +GTNODE(STORE_BLK , "storeBlk" ,GenTreeBlk ,0,GTK_BINOP|GTK_NOVALUE) // Block/object with no gc pointers, and with a known size (e.g. a struct with no gc fields) +GTNODE(DYN_BLK , "DynBlk" ,GenTreeBlk ,0,GTK_SPECIAL) // Dynamically sized block object +GTNODE(STORE_DYN_BLK , "storeDynBlk" ,GenTreeBlk ,0,GTK_SPECIAL|GTK_NOVALUE)// Dynamically sized block object +GTNODE(BOX , "box" ,GenTreeBox ,0,GTK_UNOP|GTK_EXOP|GTK_NOTLIR) #ifdef FEATURE_SIMD -GTNODE(SIMD_CHK , "simdChk" ,0,GTK_SPECIAL|GTK_NOVALUE) // Compare whether an index is less than the given SIMD vector length, and call CORINFO_HELP_RNGCHKFAIL if not. - // TODO-CQ: In future may want to add a field that specifies different exceptions but we'll - // need VM assistance for that. - // TODO-CQ: It would actually be very nice to make this an unconditional throw, and expose the control flow that - // does the compare, so that it can be more easily optimized. But that involves generating qmarks at import time... +GTNODE(SIMD_CHK , "simdChk" ,GenTreeBoundsChk ,0,GTK_SPECIAL|GTK_NOVALUE)// Compare whether an index is less than the given SIMD vector length, and call CORINFO_HELP_RNGCHKFAIL if not. + // TODO-CQ: In future may want to add a field that specifies different exceptions but we'll + // need VM assistance for that. + // TODO-CQ: It would actually be very nice to make this an unconditional throw, and expose the control flow that + // does the compare, so that it can be more easily optimized. But that involves generating qmarks at import time... #endif // FEATURE_SIMD -GTNODE(ALLOCOBJ , "allocObj" ,0,GTK_UNOP|GTK_EXOP) // object allocator +GTNODE(ALLOCOBJ , "allocObj" ,GenTreeAllocObj ,0,GTK_UNOP|GTK_EXOP) // object allocator + +GTNODE(INIT_VAL , "initVal" ,GenTreeOp ,0,GTK_UNOP) // Initialization value for an initBlk //----------------------------------------------------------------------------- // Binary operators (2 operands): //----------------------------------------------------------------------------- -GTNODE(ADD , "+" ,1,GTK_BINOP) -GTNODE(SUB , "-" ,0,GTK_BINOP) -GTNODE(MUL , "*" ,1,GTK_BINOP) -GTNODE(DIV , "/" ,0,GTK_BINOP) -GTNODE(MOD , "%" ,0,GTK_BINOP) +GTNODE(ADD , "+" ,GenTreeOp ,1,GTK_BINOP) +GTNODE(SUB , "-" ,GenTreeOp ,0,GTK_BINOP) +GTNODE(MUL , "*" ,GenTreeOp ,1,GTK_BINOP) +GTNODE(DIV , "/" ,GenTreeOp ,0,GTK_BINOP) +GTNODE(MOD , "%" ,GenTreeOp ,0,GTK_BINOP) -GTNODE(UDIV , "un-/" ,0,GTK_BINOP) -GTNODE(UMOD , "un-%" ,0,GTK_BINOP) +GTNODE(UDIV , "un-/" ,GenTreeOp ,0,GTK_BINOP) +GTNODE(UMOD , "un-%" ,GenTreeOp ,0,GTK_BINOP) -GTNODE(OR , "|" ,1,GTK_BINOP|GTK_LOGOP) -GTNODE(XOR , "^" ,1,GTK_BINOP|GTK_LOGOP) -GTNODE(AND , "&" ,1,GTK_BINOP|GTK_LOGOP) +GTNODE(OR , "|" ,GenTreeOp ,1,GTK_BINOP|GTK_LOGOP) +GTNODE(XOR , "^" ,GenTreeOp ,1,GTK_BINOP|GTK_LOGOP) +GTNODE(AND , "&" ,GenTreeOp ,1,GTK_BINOP|GTK_LOGOP) -GTNODE(LSH , "<<" ,0,GTK_BINOP) -GTNODE(RSH , ">>" ,0,GTK_BINOP) -GTNODE(RSZ , ">>>" ,0,GTK_BINOP) -GTNODE(ROL , "rol" ,0,GTK_BINOP) -GTNODE(ROR , "ror" ,0,GTK_BINOP) -GTNODE(MULHI , "mulhi" ,1,GTK_BINOP) // returns high bits (top N bits of the 2N bit result of an NxN multiply) +GTNODE(LSH , "<<" ,GenTreeOp ,0,GTK_BINOP) +GTNODE(RSH , ">>" ,GenTreeOp ,0,GTK_BINOP) +GTNODE(RSZ , ">>>" ,GenTreeOp ,0,GTK_BINOP) +GTNODE(ROL , "rol" ,GenTreeOp ,0,GTK_BINOP) +GTNODE(ROR , "ror" ,GenTreeOp ,0,GTK_BINOP) +GTNODE(MULHI , "mulhi" ,GenTreeOp ,1,GTK_BINOP) // returns high bits (top N bits of the 2N bit result of an NxN multiply) + // GT_MULHI is used in division by a constant (fgMorphDivByConst). We turn + // the div into a MULHI + some adjustments. In codegen, we only use the + // results of the high register, and we drop the low results. -GTNODE(ASG , "=" ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) -GTNODE(ASG_ADD , "+=" ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) -GTNODE(ASG_SUB , "-=" ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) -GTNODE(ASG_MUL , "*=" ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) -GTNODE(ASG_DIV , "/=" ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) -GTNODE(ASG_MOD , "%=" ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) +GTNODE(ASG , "=" ,GenTreeOp ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) +GTNODE(ASG_ADD , "+=" ,GenTreeOp ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) +GTNODE(ASG_SUB , "-=" ,GenTreeOp ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) +GTNODE(ASG_MUL , "*=" ,GenTreeOp ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) +GTNODE(ASG_DIV , "/=" ,GenTreeOp ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) +GTNODE(ASG_MOD , "%=" ,GenTreeOp ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) -GTNODE(ASG_UDIV , "/=" ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) -GTNODE(ASG_UMOD , "%=" ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) +GTNODE(ASG_UDIV , "/=" ,GenTreeOp ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) +GTNODE(ASG_UMOD , "%=" ,GenTreeOp ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) -GTNODE(ASG_OR , "|=" ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) -GTNODE(ASG_XOR , "^=" ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) -GTNODE(ASG_AND , "&=" ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) -GTNODE(ASG_LSH , "<<=" ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) -GTNODE(ASG_RSH , ">>=" ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) -GTNODE(ASG_RSZ , ">>>=" ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) +GTNODE(ASG_OR , "|=" ,GenTreeOp ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) +GTNODE(ASG_XOR , "^=" ,GenTreeOp ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) +GTNODE(ASG_AND , "&=" ,GenTreeOp ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) +GTNODE(ASG_LSH , "<<=" ,GenTreeOp ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) +GTNODE(ASG_RSH , ">>=" ,GenTreeOp ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) +GTNODE(ASG_RSZ , ">>>=" ,GenTreeOp ,0,GTK_BINOP|GTK_ASGOP|GTK_NOTLIR) -GTNODE(EQ , "==" ,0,GTK_BINOP|GTK_RELOP) -GTNODE(NE , "!=" ,0,GTK_BINOP|GTK_RELOP) -GTNODE(LT , "<" ,0,GTK_BINOP|GTK_RELOP) -GTNODE(LE , "<=" ,0,GTK_BINOP|GTK_RELOP) -GTNODE(GE , ">=" ,0,GTK_BINOP|GTK_RELOP) -GTNODE(GT , ">" ,0,GTK_BINOP|GTK_RELOP) +GTNODE(EQ , "==" ,GenTreeOp ,0,GTK_BINOP|GTK_RELOP) +GTNODE(NE , "!=" ,GenTreeOp ,0,GTK_BINOP|GTK_RELOP) +GTNODE(LT , "<" ,GenTreeOp ,0,GTK_BINOP|GTK_RELOP) +GTNODE(LE , "<=" ,GenTreeOp ,0,GTK_BINOP|GTK_RELOP) +GTNODE(GE , ">=" ,GenTreeOp ,0,GTK_BINOP|GTK_RELOP) +GTNODE(GT , ">" ,GenTreeOp ,0,GTK_BINOP|GTK_RELOP) -GTNODE(COMMA , "comma" ,0,GTK_BINOP|GTK_NOTLIR) +GTNODE(COMMA , "comma" ,GenTreeOp ,0,GTK_BINOP|GTK_NOTLIR) -GTNODE(QMARK , "qmark" ,0,GTK_BINOP|GTK_EXOP|GTK_NOTLIR) -GTNODE(COLON , "colon" ,0,GTK_BINOP|GTK_NOTLIR) +GTNODE(QMARK , "qmark" ,GenTreeQmark ,0,GTK_BINOP|GTK_EXOP|GTK_NOTLIR) +GTNODE(COLON , "colon" ,GenTreeColon ,0,GTK_BINOP|GTK_NOTLIR) -GTNODE(INDEX , "[]" ,0,GTK_BINOP|GTK_EXOP|GTK_NOTLIR) // SZ-array-element +GTNODE(INDEX , "[]" ,GenTreeIndex ,0,GTK_BINOP|GTK_EXOP|GTK_NOTLIR) // SZ-array-element -GTNODE(MKREFANY , "mkrefany" ,0,GTK_BINOP) +GTNODE(MKREFANY , "mkrefany" ,GenTreeOp ,0,GTK_BINOP) -GTNODE(LEA , "lea" ,0,GTK_BINOP|GTK_EXOP) +GTNODE(LEA , "lea" ,GenTreeAddrMode ,0,GTK_BINOP|GTK_EXOP) #if !defined(LEGACY_BACKEND) && !defined(_TARGET_64BIT_) // A GT_LONG node simply represents the long value produced by the concatenation // of its two (lower and upper half) operands. Some GT_LONG nodes are transient, // during the decomposing of longs; others are handled by codegen as operands of // nodes such as calls, returns and stores of long lclVars. -GTNODE(LONG , "gt_long" ,0,GTK_BINOP) - -// The following are nodes representing the upper half of a 64-bit operation -// that requires a carry/borrow. However, they are all named GT_XXX_HI for -// consistency. -GTNODE(ADD_LO , "+Lo" ,1,GTK_BINOP) -GTNODE(ADD_HI , "+Hi" ,1,GTK_BINOP) -GTNODE(SUB_LO , "-Lo" ,0,GTK_BINOP) -GTNODE(SUB_HI , "-Hi" ,0,GTK_BINOP) -GTNODE(MUL_HI , "*Hi" ,1,GTK_BINOP) -GTNODE(DIV_HI , "/Hi" ,0,GTK_BINOP) -GTNODE(MOD_HI , "%Hi" ,0,GTK_BINOP) +GTNODE(LONG , "gt_long" ,GenTreeOp ,0,GTK_BINOP) + +// The following are nodes representing x86 specific long operators, including +// high operators of a 64-bit operations that requires a carry/borrow, which are +// named GT_XXX_HI for consistency, low operators of 64-bit operations that need +// to not be modified in phases post-decompose, and operators that return 64-bit +// results in one instruction. +GTNODE(ADD_LO , "+Lo" ,GenTreeOp ,1,GTK_BINOP) +GTNODE(ADD_HI , "+Hi" ,GenTreeOp ,1,GTK_BINOP) +GTNODE(SUB_LO , "-Lo" ,GenTreeOp ,0,GTK_BINOP) +GTNODE(SUB_HI , "-Hi" ,GenTreeOp ,0,GTK_BINOP) +GTNODE(DIV_HI , "/Hi" ,GenTreeOp ,0,GTK_BINOP) +GTNODE(MOD_HI , "%Hi" ,GenTreeOp ,0,GTK_BINOP) +GTNODE(MUL_LONG , "*long" ,GenTreeOp ,1,GTK_BINOP) // A mul that returns the 2N bit result of an NxN multiply. This op + // is used for x86 multiplies that take two ints and return a long + // result. All other multiplies with long results are morphed into + // helper calls. It is similar to GT_MULHI, the difference being that + // GT_MULHI drops the lo part of the result, whereas GT_MUL_LONG keeps + // both parts of the result. + +// The following are nodes that specify shifts that take a GT_LONG op1. The GT_LONG +// contains the hi and lo parts of three operand shift form where one op will be +// shifted into the other op as part of the operation (LSH_HI will shift +// the high bits of the lo operand into the high operand as it shifts left. RSH_LO +// will shift the lo bits of the high operand into the lo operand). LSH_HI +// represents the high operation of a 64-bit left shift by a constant int, and +// RSH_LO represents the lo operation of a 64-bit right shift by a constant int. +GTNODE(LSH_HI , "<>Lo" ,GenTreeOp ,0,GTK_BINOP) #endif // !defined(LEGACY_BACKEND) && !defined(_TARGET_64BIT_) #ifdef FEATURE_SIMD -GTNODE(SIMD , "simd" ,0,GTK_BINOP|GTK_EXOP) // SIMD functions/operators/intrinsics +GTNODE(SIMD , "simd" ,GenTreeSIMD ,0,GTK_BINOP|GTK_EXOP) // SIMD functions/operators/intrinsics #endif // FEATURE_SIMD //----------------------------------------------------------------------------- // Other nodes that look like unary/binary operators: //----------------------------------------------------------------------------- -GTNODE(JTRUE , "jmpTrue" ,0,GTK_UNOP|GTK_NOVALUE) +GTNODE(JTRUE , "jmpTrue" ,GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE) +GTNODE(JCC , "jcc" ,GenTreeJumpCC ,0,GTK_LEAF|GTK_NOVALUE) -GTNODE(LIST , "" ,0,GTK_BINOP) +GTNODE(LIST , "" ,GenTreeArgList ,0,GTK_BINOP|GTK_NOVALUE) +GTNODE(FIELD_LIST , "" ,GenTreeFieldList ,0,GTK_BINOP) // List of fields of a struct, when passed as an argument //----------------------------------------------------------------------------- // Other nodes that have special structure: //----------------------------------------------------------------------------- -GTNODE(FIELD , "field" ,0,GTK_SPECIAL) // Member-field -GTNODE(ARR_ELEM , "arrMD&" ,0,GTK_SPECIAL) // Multi-dimensional array-element address -GTNODE(ARR_INDEX , "arrMDIdx" ,0,GTK_BINOP|GTK_EXOP) // Effective, bounds-checked index for one dimension of a multi-dimensional array element -GTNODE(ARR_OFFSET , "arrMDOffs" ,0,GTK_SPECIAL) // Flattened offset of multi-dimensional array element -GTNODE(CALL , "call()" ,0,GTK_SPECIAL) +GTNODE(FIELD , "field" ,GenTreeField ,0,GTK_SPECIAL) // Member-field +GTNODE(ARR_ELEM , "arrMD&" ,GenTreeArrElem ,0,GTK_SPECIAL) // Multi-dimensional array-element address +GTNODE(ARR_INDEX , "arrMDIdx" ,GenTreeArrIndex ,0,GTK_BINOP|GTK_EXOP) // Effective, bounds-checked index for one dimension of a multi-dimensional array element +GTNODE(ARR_OFFSET , "arrMDOffs" ,GenTreeArrOffs ,0,GTK_SPECIAL) // Flattened offset of multi-dimensional array element +GTNODE(CALL , "call()" ,GenTreeCall ,0,GTK_SPECIAL) //----------------------------------------------------------------------------- // Statement operator nodes: //----------------------------------------------------------------------------- -GTNODE(BEG_STMTS , "begStmts" ,0,GTK_SPECIAL|GTK_NOVALUE) // used only temporarily in importer by impBegin/EndTreeList() -GTNODE(STMT , "stmtExpr" ,0,GTK_SPECIAL|GTK_NOVALUE) // top-level list nodes in bbTreeList +GTNODE(BEG_STMTS , "begStmts" ,GenTree ,0,GTK_SPECIAL|GTK_NOVALUE)// used only temporarily in importer by impBegin/EndTreeList() +GTNODE(STMT , "stmtExpr" ,GenTreeStmt ,0,GTK_SPECIAL|GTK_NOVALUE)// top-level list nodes in bbTreeList -GTNODE(RETURN , "return" ,0,GTK_UNOP|GTK_NOVALUE) // return from current function -GTNODE(SWITCH , "switch" ,0,GTK_UNOP|GTK_NOVALUE) // switch +GTNODE(RETURN , "return" ,GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE) // return from current function +GTNODE(SWITCH , "switch" ,GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE) // switch -GTNODE(NO_OP , "no_op" ,0,GTK_LEAF|GTK_NOVALUE) // nop! +GTNODE(NO_OP , "no_op" ,GenTree ,0,GTK_LEAF|GTK_NOVALUE) // nop! -GTNODE(START_NONGC, "start_nongc",0,GTK_LEAF|GTK_NOVALUE) // starts a new instruction group that will be non-gc interruptible +GTNODE(START_NONGC , "start_nongc" ,GenTree ,0,GTK_LEAF|GTK_NOVALUE) // starts a new instruction group that will be non-gc interruptible -GTNODE(PROF_HOOK , "prof_hook" ,0,GTK_LEAF|GTK_NOVALUE) // profiler Enter/Leave/TailCall hook +GTNODE(PROF_HOOK , "prof_hook" ,GenTree ,0,GTK_LEAF|GTK_NOVALUE) // profiler Enter/Leave/TailCall hook -GTNODE(RETFILT , "retfilt", 0,GTK_UNOP|GTK_NOVALUE) // end filter with TYP_I_IMPL return value +GTNODE(RETFILT , "retfilt" ,GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE) // end filter with TYP_I_IMPL return value #if !FEATURE_EH_FUNCLETS -GTNODE(END_LFIN , "endLFin" ,0,GTK_LEAF|GTK_NOVALUE) // end locally-invoked finally +GTNODE(END_LFIN , "endLFin" ,GenTreeVal ,0,GTK_LEAF|GTK_NOVALUE) // end locally-invoked finally #endif // !FEATURE_EH_FUNCLETS //----------------------------------------------------------------------------- // Nodes used for optimizations. //----------------------------------------------------------------------------- -GTNODE(PHI , "phi" ,0,GTK_UNOP) // phi node for ssa. -GTNODE(PHI_ARG , "phiArg" ,0,GTK_LEAF|GTK_LOCAL) // phi(phiarg, phiarg, phiarg) +GTNODE(PHI , "phi" ,GenTreeOp ,0,GTK_UNOP) // phi node for ssa. +GTNODE(PHI_ARG , "phiArg" ,GenTreePhiArg ,0,GTK_LEAF|GTK_LOCAL) // phi(phiarg, phiarg, phiarg) //----------------------------------------------------------------------------- // Nodes used by Lower to generate a closer CPU representation of other nodes //----------------------------------------------------------------------------- -GTNODE(JMPTABLE , "jumpTable" , 0, GTK_LEAF) // Generates the jump table for switches -GTNODE(SWITCH_TABLE, "tableSwitch", 0, GTK_BINOP|GTK_NOVALUE) // Jump Table based switch construct +#ifndef LEGACY_BACKEND +GTNODE(JMPTABLE , "jumpTable" ,GenTreeJumpTable ,0, GTK_LEAF) // Generates the jump table for switches +#endif +GTNODE(SWITCH_TABLE , "tableSwitch" ,GenTreeOp ,0, GTK_BINOP|GTK_NOVALUE) // Jump Table based switch construct //----------------------------------------------------------------------------- // Nodes used only within the code generator: //----------------------------------------------------------------------------- -GTNODE(REG_VAR , "regVar" ,0,GTK_LEAF|GTK_LOCAL) // register variable -GTNODE(CLS_VAR , "clsVar" ,0,GTK_LEAF) // static data member -GTNODE(CLS_VAR_ADDR , "&clsVar" ,0,GTK_LEAF) // static data member address -GTNODE(STORE_CLS_VAR, "st.clsVar" ,0,GTK_LEAF|GTK_NOVALUE) // store to static data member -GTNODE(ARGPLACE , "argPlace" ,0,GTK_LEAF) // placeholder for a register arg -GTNODE(NULLCHECK , "nullcheck" ,0,GTK_UNOP|GTK_NOVALUE) // null checks the source -GTNODE(PHYSREG , "physregSrc" ,0,GTK_LEAF) // read from a physical register -GTNODE(PHYSREGDST , "physregDst" ,0,GTK_UNOP|GTK_NOVALUE) // write to a physical register -GTNODE(EMITNOP , "emitnop" ,0,GTK_LEAF|GTK_NOVALUE) // emitter-placed nop -GTNODE(PINVOKE_PROLOG,"pinvoke_prolog",0,GTK_LEAF|GTK_NOVALUE) // pinvoke prolog seq -GTNODE(PINVOKE_EPILOG,"pinvoke_epilog",0,GTK_LEAF|GTK_NOVALUE) // pinvoke epilog seq -GTNODE(PUTARG_REG , "putarg_reg" ,0,GTK_UNOP) // operator that places outgoing arg in register -GTNODE(PUTARG_STK , "putarg_stk" ,0,GTK_UNOP) // operator that places outgoing arg in stack -GTNODE(RETURNTRAP , "returnTrap" ,0,GTK_UNOP|GTK_NOVALUE) // a conditional call to wait on gc -GTNODE(SWAP , "swap" ,0,GTK_BINOP|GTK_NOVALUE) // op1 and op2 swap (registers) -GTNODE(IL_OFFSET , "il_offset" ,0,GTK_LEAF|GTK_NOVALUE) // marks an IL offset for debugging purposes +GTNODE(REG_VAR , "regVar" ,GenTreeLclVar ,0,GTK_LEAF|GTK_LOCAL) // register variable +GTNODE(CLS_VAR , "clsVar" ,GenTreeClsVar ,0,GTK_LEAF) // static data member +GTNODE(CLS_VAR_ADDR , "&clsVar" ,GenTreeClsVar ,0,GTK_LEAF) // static data member address +GTNODE(ARGPLACE , "argPlace" ,GenTreeArgPlace ,0,GTK_LEAF) // placeholder for a register arg +GTNODE(NULLCHECK , "nullcheck" ,GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE) // null checks the source +GTNODE(PHYSREG , "physregSrc" ,GenTreePhysReg ,0,GTK_LEAF) // read from a physical register +GTNODE(PHYSREGDST , "physregDst" ,GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE) // write to a physical register +GTNODE(EMITNOP , "emitnop" ,GenTree ,0,GTK_LEAF|GTK_NOVALUE) // emitter-placed nop +GTNODE(PINVOKE_PROLOG ,"pinvoke_prolog",GenTree ,0,GTK_LEAF|GTK_NOVALUE) // pinvoke prolog seq +GTNODE(PINVOKE_EPILOG ,"pinvoke_epilog",GenTree ,0,GTK_LEAF|GTK_NOVALUE) // pinvoke epilog seq +GTNODE(PUTARG_REG , "putarg_reg" ,GenTreeOp ,0,GTK_UNOP) // operator that places outgoing arg in register +GTNODE(PUTARG_STK , "putarg_stk" ,GenTreePutArgStk ,0,GTK_UNOP) // operator that places outgoing arg in stack +GTNODE(RETURNTRAP , "returnTrap" ,GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE) // a conditional call to wait on gc +GTNODE(SWAP , "swap" ,GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE) // op1 and op2 swap (registers) +GTNODE(IL_OFFSET , "il_offset" ,GenTreeStmt ,0,GTK_LEAF|GTK_NOVALUE) // marks an IL offset for debugging purposes /*****************************************************************************/ #undef GTNODE diff --git a/src/jit/gtstructs.h b/src/jit/gtstructs.h index 895d3b6..ac91240 100644 --- a/src/jit/gtstructs.h +++ b/src/jit/gtstructs.h @@ -65,7 +65,8 @@ GTSTRUCT_1(Cast , GT_CAST) GTSTRUCT_1(Box , GT_BOX) GTSTRUCT_1(Field , GT_FIELD) GTSTRUCT_1(Call , GT_CALL) -GTSTRUCT_1(ArgList , GT_LIST) +GTSTRUCT_2(ArgList , GT_LIST, GT_FIELD_LIST) +GTSTRUCT_1(FieldList , GT_FIELD_LIST) GTSTRUCT_1(Colon , GT_COLON) GTSTRUCT_1(FptrVal , GT_FTN_ADDR) GTSTRUCT_1(Intrinsic , GT_INTRINSIC) @@ -100,6 +101,7 @@ GTSTRUCT_1(PhysReg , GT_PHYSREG) GTSTRUCT_1(SIMD , GT_SIMD) #endif // FEATURE_SIMD GTSTRUCT_1(AllocObj , GT_ALLOCOBJ) +GTSTRUCT_1(JumpCC , GT_JCC) /*****************************************************************************/ #undef GTSTRUCT_0 #undef GTSTRUCT_1 diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp index d04ded7..cb09ff8 100644 --- a/src/jit/importer.cpp +++ b/src/jit/importer.cpp @@ -63,15 +63,12 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX void Compiler::impInit() { -#ifdef DEBUG - impTreeList = impTreeLast = nullptr; -#endif -#if defined(DEBUG) +#ifdef DEBUG + impTreeList = nullptr; + impTreeLast = nullptr; impInlinedCodeSize = 0; #endif - - seenConditionalJump = false; } /***************************************************************************** @@ -600,13 +597,9 @@ inline void Compiler::impAppendStmt(GenTreePtr stmt, unsigned chkLevel) // Assignment to (unaliased) locals don't count as a side-effect as // we handle them specially using impSpillLclRefs(). Temp locals should // be fine too. - // TODO-1stClassStructs: The check below should apply equally to struct assignments, - // but previously the block ops were always being marked GTF_GLOB_REF, even if - // the operands could not be global refs. if ((expr->gtOper == GT_ASG) && (expr->gtOp.gtOp1->gtOper == GT_LCL_VAR) && - !(expr->gtOp.gtOp1->gtFlags & GTF_GLOB_REF) && !gtHasLocalsWithAddrOp(expr->gtOp.gtOp2) && - !varTypeIsStruct(expr->gtOp.gtOp1)) + !(expr->gtOp.gtOp1->gtFlags & GTF_GLOB_REF) && !gtHasLocalsWithAddrOp(expr->gtOp.gtOp2)) { unsigned op2Flags = expr->gtOp.gtOp2->gtFlags & GTF_GLOB_EFFECT; assert(flags == (op2Flags | GTF_ASG)); @@ -673,8 +666,6 @@ inline void Compiler::impAppendStmt(GenTreePtr stmt, unsigned chkLevel) impMarkContiguousSIMDFieldAssignments(stmt); #endif -#ifdef DEBUGGING_SUPPORT - /* Once we set impCurStmtOffs in an appended tree, we are ready to report the following offsets. So reset impCurStmtOffs */ @@ -683,8 +674,6 @@ inline void Compiler::impAppendStmt(GenTreePtr stmt, unsigned chkLevel) impCurStmtOffsSet(BAD_IL_OFFSET); } -#endif - #ifdef DEBUG if (impLastILoffsStmt == nullptr) { @@ -1143,9 +1132,13 @@ GenTreePtr Compiler::impAssignStructPtr(GenTreePtr destAddr, if (destAddr->OperGet() == GT_ADDR) { GenTree* destNode = destAddr->gtGetOp1(); - // If the actual destination is already a block node, or is a node that + // If the actual destination is a local (for non-LEGACY_BACKEND), or already a block node, or is a node that // will be morphed, don't insert an OBJ(ADDR). - if (destNode->gtOper == GT_INDEX || destNode->OperIsBlk()) + if (destNode->gtOper == GT_INDEX || destNode->OperIsBlk() +#ifndef LEGACY_BACKEND + || ((destNode->OperGet() == GT_LCL_VAR) && (destNode->TypeGet() == src->TypeGet())) +#endif // !LEGACY_BACKEND + ) { dest = destNode; } @@ -1194,6 +1187,9 @@ GenTreePtr Compiler::impAssignStructPtr(GenTreePtr destAddr, { // Mark the struct LclVar as used in a MultiReg return context // which currently makes it non promotable. + // TODO-1stClassStructs: Eliminate this pessimization when we can more generally + // handle multireg returns. + lcl->gtFlags |= GTF_DONT_CSE; lvaTable[lcl->gtLclVarCommon.gtLclNum].lvIsMultiRegRet = true; } else // The call result is not a multireg return @@ -1208,12 +1204,20 @@ GenTreePtr Compiler::impAssignStructPtr(GenTreePtr destAddr, dest = lcl; #if defined(_TARGET_ARM_) + // TODO-Cleanup: This should have been taken care of in the above HasMultiRegRetVal() case, + // but that method has not been updadted to include ARM. impMarkLclDstNotPromotable(lcl->gtLclVarCommon.gtLclNum, src, structHnd); + lcl->gtFlags |= GTF_DONT_CSE; #elif defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) // Not allowed for FEATURE_CORCLR which is the only SKU available for System V OSs. assert(!src->gtCall.IsVarargs() && "varargs not allowed for System V OSs."); // Make the struct non promotable. The eightbytes could contain multiple fields. + // TODO-1stClassStructs: Eliminate this pessimization when we can more generally + // handle multireg returns. + // TODO-Cleanup: Why is this needed here? This seems that it will set this even for + // non-multireg returns. + lcl->gtFlags |= GTF_DONT_CSE; lvaTable[lcl->gtLclVarCommon.gtLclNum].lvIsMultiRegRet = true; #endif } @@ -1255,10 +1259,11 @@ GenTreePtr Compiler::impAssignStructPtr(GenTreePtr destAddr, src->gtType = genActualType(returnType); call->gtType = src->gtType; - // 1stClassStructToDo: We shouldn't necessarily need this. - if (dest != nullptr) + // If we've changed the type, and it no longer matches a local destination, + // we must use an indirection. + if ((dest != nullptr) && (dest->OperGet() == GT_LCL_VAR) && (dest->TypeGet() != asgType)) { - dest = gtNewOperNode(GT_IND, returnType, gtNewOperNode(GT_ADDR, TYP_BYREF, dest)); + dest = nullptr; } // !!! The destination could be on stack. !!! @@ -1329,21 +1334,19 @@ GenTreePtr Compiler::impAssignStructPtr(GenTreePtr destAddr, } else if (src->IsLocal()) { - // TODO-1stClassStructs: Eliminate this; it is only here to minimize diffs in the - // initial implementation. Previously the source would have been under a GT_ADDR, which - // would cause it to be marked GTF_DONT_CSE. asgType = src->TypeGet(); - src->gtFlags |= GTF_DONT_CSE; - if (asgType == TYP_STRUCT) - { - GenTree* srcAddr = gtNewOperNode(GT_ADDR, TYP_BYREF, src); - src = gtNewOperNode(GT_IND, TYP_STRUCT, srcAddr); - } } else if (asgType == TYP_STRUCT) { asgType = impNormStructType(structHnd); src->gtType = asgType; +#ifdef LEGACY_BACKEND + if (asgType == TYP_STRUCT) + { + GenTree* srcAddr = gtNewOperNode(GT_ADDR, TYP_BYREF, src); + src = gtNewOperNode(GT_IND, TYP_STRUCT, srcAddr); + } +#endif } if (dest == nullptr) { @@ -1459,6 +1462,8 @@ GenTreePtr Compiler::impGetStructAddr(GenTreePtr structVal, // into which the gcLayout will be written. // pNumGCVars - (optional, default nullptr) - if non-null, a pointer to an unsigned, // which will be set to the number of GC fields in the struct. +// pSimdBaseType - (optional, default nullptr) - if non-null, and the struct is a SIMD +// type, set to the SIMD base type // // Return Value: // The JIT type for the struct (e.g. TYP_STRUCT, or TYP_SIMD*). @@ -1480,53 +1485,69 @@ var_types Compiler::impNormStructType(CORINFO_CLASS_HANDLE structHnd, var_types* pSimdBaseType) { assert(structHnd != NO_CLASS_HANDLE); - unsigned originalSize = info.compCompHnd->getClassSize(structHnd); - unsigned numGCVars = 0; - var_types structType = TYP_STRUCT; - var_types simdBaseType = TYP_UNKNOWN; - bool definitelyHasGCPtrs = false; -#ifdef FEATURE_SIMD - // We don't want to consider this as a possible SIMD type if it has GC pointers. - // (Saves querying about the SIMD assembly.) - BYTE gcBytes[maxPossibleSIMDStructBytes / TARGET_POINTER_SIZE]; - if ((gcLayout == nullptr) && (originalSize >= minSIMDStructBytes()) && (originalSize <= maxSIMDStructBytes())) - { - gcLayout = gcBytes; - } -#endif // FEATURE_SIMD + const DWORD structFlags = info.compCompHnd->getClassAttribs(structHnd); + var_types structType = TYP_STRUCT; + +#ifdef FEATURE_CORECLR + const bool hasGCPtrs = (structFlags & CORINFO_FLG_CONTAINS_GC_PTR) != 0; +#else + // Desktop CLR won't report FLG_CONTAINS_GC_PTR for RefAnyClass - need to check explicitly. + const bool isRefAny = (structHnd == impGetRefAnyClass()); + const bool hasGCPtrs = isRefAny || ((structFlags & CORINFO_FLG_CONTAINS_GC_PTR) != 0); +#endif - if (gcLayout != nullptr) - { - numGCVars = info.compCompHnd->getClassGClayout(structHnd, gcLayout); - definitelyHasGCPtrs = (numGCVars != 0); - } #ifdef FEATURE_SIMD // Check to see if this is a SIMD type. - if (featureSIMD && (originalSize <= getSIMDVectorRegisterByteLength()) && (originalSize >= TARGET_POINTER_SIZE) && - !definitelyHasGCPtrs) + if (featureSIMD && !hasGCPtrs) { - unsigned int sizeBytes; - simdBaseType = getBaseTypeAndSizeOfSIMDType(structHnd, &sizeBytes); - if (simdBaseType != TYP_UNKNOWN) + unsigned originalSize = info.compCompHnd->getClassSize(structHnd); + + if ((originalSize >= minSIMDStructBytes()) && (originalSize <= maxSIMDStructBytes())) { - assert(sizeBytes == originalSize); - structType = getSIMDTypeForSize(sizeBytes); - if (pSimdBaseType != nullptr) + unsigned int sizeBytes; + var_types simdBaseType = getBaseTypeAndSizeOfSIMDType(structHnd, &sizeBytes); + if (simdBaseType != TYP_UNKNOWN) { - *pSimdBaseType = simdBaseType; - } + assert(sizeBytes == originalSize); + structType = getSIMDTypeForSize(sizeBytes); + if (pSimdBaseType != nullptr) + { + *pSimdBaseType = simdBaseType; + } #ifdef _TARGET_AMD64_ - // Amd64: also indicate that we use floating point registers - compFloatingPointUsed = true; + // Amd64: also indicate that we use floating point registers + compFloatingPointUsed = true; #endif + } } } #endif // FEATURE_SIMD - if (pNumGCVars != nullptr) + + // Fetch GC layout info if requested + if (gcLayout != nullptr) + { + unsigned numGCVars = info.compCompHnd->getClassGClayout(structHnd, gcLayout); + + // Verify that the quick test up above via the class attributes gave a + // safe view of the type's GCness. + // + // Note there are cases where hasGCPtrs is true but getClassGClayout + // does not report any gc fields. + assert(hasGCPtrs || (numGCVars == 0)); + + if (pNumGCVars != nullptr) + { + *pNumGCVars = numGCVars; + } + } + else { - *pNumGCVars = numGCVars; + // Can't safely ask for number of GC pointers without also + // asking for layout. + assert(pNumGCVars == nullptr); } + return structType; } @@ -1777,15 +1798,19 @@ GenTreePtr Compiler::impReadyToRunLookupToTree(CORINFO_CONST_LOOKUP* pLookup, unsigned handleFlags, void* compileTimeHandle) { - CORINFO_GENERIC_HANDLE handle = 0; - void* pIndirection = 0; + CORINFO_GENERIC_HANDLE handle = nullptr; + void* pIndirection = nullptr; assert(pLookup->accessType != IAT_PPVALUE); if (pLookup->accessType == IAT_VALUE) + { handle = pLookup->handle; + } else if (pLookup->accessType == IAT_PVALUE) + { pIndirection = pLookup->addr; - return gtNewIconEmbHndNode(handle, pIndirection, handleFlags, 0, 0, compileTimeHandle); + } + return gtNewIconEmbHndNode(handle, pIndirection, handleFlags, 0, nullptr, compileTimeHandle); } GenTreePtr Compiler::impReadyToRunHelperToTree( @@ -1798,7 +1823,9 @@ GenTreePtr Compiler::impReadyToRunHelperToTree( CORINFO_CONST_LOOKUP lookup; #if COR_JIT_EE_VERSION > 460 if (!info.compCompHnd->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, helper, &lookup)) - return NULL; + { + return nullptr; + } #else info.compCompHnd->getReadyToRunHelper(pResolvedToken, helper, &lookup); #endif @@ -1828,7 +1855,9 @@ GenTreePtr Compiler::impMethodPointer(CORINFO_RESOLVED_TOKEN* pResolvedToken, CO *op1->gtFptrVal.gtLdftnResolvedToken = *pResolvedToken; } else + { op1->gtFptrVal.gtEntryPoint.addr = nullptr; + } #endif break; @@ -1852,6 +1881,46 @@ GenTreePtr Compiler::impMethodPointer(CORINFO_RESOLVED_TOKEN* pResolvedToken, CO return op1; } +//------------------------------------------------------------------------ +// getRuntimeContextTree: find pointer to context for runtime lookup. +// +// Arguments: +// kind - lookup kind. +// +// Return Value: +// Return GenTree pointer to generic shared context. +// +// Notes: +// Reports about generic context using. + +GenTreePtr Compiler::getRuntimeContextTree(CORINFO_RUNTIME_LOOKUP_KIND kind) +{ + GenTreePtr ctxTree = nullptr; + + // Collectible types requires that for shared generic code, if we use the generic context parameter + // that we report it. (This is a conservative approach, we could detect some cases particularly when the + // context parameter is this that we don't need the eager reporting logic.) + lvaGenericsContextUsed = true; + + if (kind == CORINFO_LOOKUP_THISOBJ) + { + // this Object + ctxTree = gtNewLclvNode(info.compThisArg, TYP_REF); + + // Vtable pointer of this object + ctxTree = gtNewOperNode(GT_IND, TYP_I_IMPL, ctxTree); + ctxTree->gtFlags |= GTF_EXCEPT; // Null-pointer exception + ctxTree->gtFlags |= GTF_IND_INVARIANT; + } + else + { + assert(kind == CORINFO_LOOKUP_METHODPARAM || kind == CORINFO_LOOKUP_CLASSPARAM); + + ctxTree = gtNewLclvNode(info.compTypeCtxtArg, TYP_I_IMPL); // Exact method descriptor as passed in as last arg + } + return ctxTree; +} + /*****************************************************************************/ /* Import a dictionary lookup to access a handle in code shared between generic instantiations. @@ -1874,36 +1943,12 @@ GenTreePtr Compiler::impRuntimeLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedTok CORINFO_LOOKUP* pLookup, void* compileTimeHandle) { - CORINFO_RUNTIME_LOOKUP_KIND kind = pLookup->lookupKind.runtimeLookupKind; - CORINFO_RUNTIME_LOOKUP* pRuntimeLookup = &pLookup->runtimeLookup; // This method can only be called from the importer instance of the Compiler. // In other word, it cannot be called by the instance of the Compiler for the inlinee. assert(!compIsForInlining()); - GenTreePtr ctxTree; - - // Collectible types requires that for shared generic code, if we use the generic context parameter - // that we report it. (This is a conservative approach, we could detect some cases particularly when the - // context parameter is this that we don't need the eager reporting logic.) - lvaGenericsContextUsed = true; - - if (kind == CORINFO_LOOKUP_THISOBJ) - { - // this Object - ctxTree = gtNewLclvNode(info.compThisArg, TYP_REF); - - // Vtable pointer of this object - ctxTree = gtNewOperNode(GT_IND, TYP_I_IMPL, ctxTree); - ctxTree->gtFlags |= GTF_EXCEPT; // Null-pointer exception - ctxTree->gtFlags |= GTF_IND_INVARIANT; - } - else - { - assert(kind == CORINFO_LOOKUP_METHODPARAM || kind == CORINFO_LOOKUP_CLASSPARAM); - - ctxTree = gtNewLclvNode(info.compTypeCtxtArg, TYP_I_IMPL); // Exact method descriptor as passed in as last arg - } + GenTreePtr ctxTree = getRuntimeContextTree(pLookup->lookupKind.runtimeLookupKind); #ifdef FEATURE_READYTORUN_COMPILER if (opts.IsReadyToRun()) @@ -1913,6 +1958,7 @@ GenTreePtr Compiler::impRuntimeLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedTok } #endif + CORINFO_RUNTIME_LOOKUP* pRuntimeLookup = &pLookup->runtimeLookup; // It's available only via the run-time helper function if (pRuntimeLookup->indirections == CORINFO_USEHELPER) { @@ -2083,8 +2129,6 @@ bool Compiler::impSpillStackEntry(unsigned level, guard.Init(&impNestedStackSpill, bAssertOnRecursion); #endif - assert(!fgGlobalMorph); // use impInlineSpillStackEntry() during inlining - GenTreePtr tree = verCurrentState.esStack[level].val; /* Allocate a temp if we haven't been asked to use a particular one */ @@ -2179,8 +2223,6 @@ void Compiler::impSpillStackEnsure(bool spillLeaves) void Compiler::impSpillEvalStack() { - assert(!fgGlobalMorph); // use impInlineSpillEvalStack() during inlining - for (unsigned level = 0; level < verCurrentState.esStackDepth; level++) { impSpillStackEntry(level, BAD_VAR_NUM DEBUGARG(false) DEBUGARG("impSpillEvalStack")); @@ -2318,8 +2360,6 @@ Compiler::fgWalkResult Compiler::impFindValueClasses(GenTreePtr* pTree, fgWalkDa void Compiler::impSpillLclRefs(ssize_t lclNum) { - assert(!fgGlobalMorph); // use impInlineSpillLclRefs() during inlining - /* Before we make any appends to the tree list we must spill the * "special" side effects (GTF_ORDER_SIDEEFF) - GT_CATCH_ARG */ @@ -2676,7 +2716,6 @@ static inline bool impOpcodeIsCallOpcode(OPCODE opcode) } /*****************************************************************************/ -#ifdef DEBUGGING_SUPPORT static inline bool impOpcodeIsCallSiteBoundary(OPCODE opcode) { @@ -2695,8 +2734,6 @@ static inline bool impOpcodeIsCallSiteBoundary(OPCODE opcode) } } -#endif // DEBUGGING_SUPPORT - /*****************************************************************************/ // One might think it is worth caching these values, but results indicate @@ -2816,27 +2853,6 @@ GenTreePtr Compiler::impImplicitR4orR8Cast(GenTreePtr tree, var_types dstTyp) return tree; } -/*****************************************************************************/ -BOOL Compiler::impLocAllocOnStack() -{ - if (!compLocallocUsed) - { - return (FALSE); - } - - // Returns true if a GT_LCLHEAP node is encountered in any of the trees - // that have been pushed on the importer evaluatuion stack. - // - for (unsigned i = 0; i < verCurrentState.esStackDepth; i++) - { - if (fgWalkTreePre(&verCurrentState.esStack[i].val, Compiler::fgChkLocAllocCB) == WALK_ABORT) - { - return (TRUE); - } - } - return (FALSE); -} - //------------------------------------------------------------------------ // impInitializeArrayIntrinsic: Attempts to replace a call to InitializeArray // with a GT_COPYBLK node. @@ -3236,7 +3252,7 @@ GenTreePtr Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, #if COR_JIT_EE_VERSION > 460 CorInfoIntrinsics intrinsicID = info.compCompHnd->getIntrinsicID(method, &mustExpand); #else - CorInfoIntrinsics intrinsicID = info.compCompHnd->getIntrinsicID(method); + CorInfoIntrinsics intrinsicID = info.compCompHnd->getIntrinsicID(method); #endif *pIntrinsicID = intrinsicID; @@ -3307,9 +3323,9 @@ GenTreePtr Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, op1 = nullptr; -#ifdef LEGACY_BACKEND +#if defined(LEGACY_BACKEND) if (IsTargetIntrinsic(intrinsicID)) -#else +#elif !defined(_TARGET_X86_) // Intrinsics that are not implemented directly by target instructions will // be re-materialized as users calls in rationalizer. For prefixed tail calls, // don't do this optimization, because @@ -3317,6 +3333,11 @@ GenTreePtr Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, // b) It will be non-trivial task or too late to re-materialize a surviving // tail prefixed GT_INTRINSIC as tail call in rationalizer. if (!IsIntrinsicImplementedByUserCall(intrinsicID) || !tailCall) +#else + // On x86 RyuJIT, importing intrinsics that are implemented as user calls can cause incorrect calculation + // of the depth of the stack if these intrinsics are used as arguments to another call. This causes bad + // code generation for certain EH constructs. + if (!IsIntrinsicImplementedByUserCall(intrinsicID)) #endif { switch (sig->numArgs) @@ -3534,7 +3555,7 @@ GenTreePtr Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, // Get native TypeHandle argument to old helper op1 = op1->gtCall.gtCallArgs; - assert(op1->IsList()); + assert(op1->OperIsList()); assert(op1->gtOp.gtOp2 == nullptr); op1 = op1->gtOp.gtOp1; retNode = op1; @@ -3886,7 +3907,7 @@ void Compiler::verHandleVerificationFailure(BasicBlock* block DEBUGARG(bool logM #endif // DEBUG // Add the non verifiable flag to the compiler - if ((opts.eeFlags & CORJIT_FLG_IMPORT_ONLY) != 0) + if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_IMPORT_ONLY)) { tiIsVerifiableCode = FALSE; } @@ -4913,14 +4934,26 @@ GenTreePtr Compiler::impImportLdvirtftn(GenTreePtr thisPtr, } #ifdef FEATURE_READYTORUN_COMPILER - if (opts.IsReadyToRun() && !pCallInfo->exactContextNeedsRuntimeLookup) + if (opts.IsReadyToRun()) { - GenTreeCall* call = gtNewHelperCallNode(CORINFO_HELP_READYTORUN_VIRTUAL_FUNC_PTR, TYP_I_IMPL, GTF_EXCEPT, - gtNewArgList(thisPtr)); + if (!pCallInfo->exactContextNeedsRuntimeLookup) + { + GenTreeCall* call = gtNewHelperCallNode(CORINFO_HELP_READYTORUN_VIRTUAL_FUNC_PTR, TYP_I_IMPL, GTF_EXCEPT, + gtNewArgList(thisPtr)); - call->setEntryPoint(pCallInfo->codePointerLookup.constLookup); + call->setEntryPoint(pCallInfo->codePointerLookup.constLookup); - return call; + return call; + } + + // We need a runtime lookup. CoreRT has a ReadyToRun helper for that too. + if (IsTargetAbi(CORINFO_CORERT_ABI)) + { + GenTreePtr ctxTree = getRuntimeContextTree(pCallInfo->codePointerLookup.lookupKind.runtimeLookupKind); + + return impReadyToRunHelperToTree(pResolvedToken, CORINFO_HELP_READYTORUN_GENERIC_HANDLE, TYP_I_IMPL, + gtNewArgList(ctxTree), &pCallInfo->codePointerLookup.lookupKind); + } } #endif @@ -5001,7 +5034,7 @@ void Compiler::impImportAndPushBox(CORINFO_RESOLVED_TOKEN* pResolvedToken) if (opts.IsReadyToRun()) { op1 = impReadyToRunHelperToTree(pResolvedToken, CORINFO_HELP_READYTORUN_NEW, TYP_REF); - usingReadyToRunHelper = (op1 != NULL); + usingReadyToRunHelper = (op1 != nullptr); } if (!usingReadyToRunHelper) @@ -5150,7 +5183,7 @@ void Compiler::impImportNewObjArray(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORI CLANG_FORMAT_COMMENT_ANCHOR; #if COR_JIT_EE_VERSION > 460 - if (!opts.IsReadyToRun() || (eeGetEEInfo()->targetAbi == CORINFO_CORERT_ABI)) + if (!opts.IsReadyToRun() || IsTargetAbi(CORINFO_CORERT_ABI)) { LclVarDsc* newObjArrayArgsVar; @@ -5325,61 +5358,110 @@ GenTreePtr Compiler::impTransformThis(GenTreePtr thisPtr, } } -bool Compiler::impCanPInvokeInline(var_types callRetTyp) +//------------------------------------------------------------------------ +// impCanPInvokeInline: examine information from a call to see if the call +// qualifies as an inline pinvoke. +// +// Arguments: +// block - block contaning the call, or for inlinees, block +// containing the call being inlined +// +// Return Value: +// true if this call qualifies as an inline pinvoke, false otherwise +// +// Notes: +// Checks basic legality and then a number of ambient conditions +// where we could pinvoke but choose not to + +bool Compiler::impCanPInvokeInline(BasicBlock* block) { - return impCanPInvokeInlineCallSite(callRetTyp) && getInlinePInvokeEnabled() && (!opts.compDbgCode) && + return impCanPInvokeInlineCallSite(block) && getInlinePInvokeEnabled() && (!opts.compDbgCode) && (compCodeOpt() != SMALL_CODE) && (!opts.compNoPInvokeInlineCB) // profiler is preventing inline pinvoke ; } -// Returns false only if the callsite really cannot be inlined. Ignores global variables -// like debugger, profiler etc. -bool Compiler::impCanPInvokeInlineCallSite(var_types callRetTyp) +//------------------------------------------------------------------------ +// impCanPInvokeInlineSallSite: basic legality checks using information +// from a call to see if the call qualifies as an inline pinvoke. +// +// Arguments: +// block - block contaning the call, or for inlinees, block +// containing the call being inlined +// +// Return Value: +// true if this call can legally qualify as an inline pinvoke, false otherwise +// +// Notes: +// For runtimes that support exception handling interop there are +// restrictions on using inline pinvoke in handler regions. +// +// * We have to disable pinvoke inlining inside of filters because +// in case the main execution (i.e. in the try block) is inside +// unmanaged code, we cannot reuse the inlined stub (we still need +// the original state until we are in the catch handler) +// +// * We disable pinvoke inlining inside handlers since the GSCookie +// is in the inlined Frame (see +// CORINFO_EE_INFO::InlinedCallFrameInfo::offsetOfGSCookie), but +// this would not protect framelets/return-address of handlers. +// +// These restrictions are currently also in place for CoreCLR but +// can be relaxed when coreclr/#8459 is addressed. + +bool Compiler::impCanPInvokeInlineCallSite(BasicBlock* block) { - return - // We have to disable pinvoke inlining inside of filters - // because in case the main execution (i.e. in the try block) is inside - // unmanaged code, we cannot reuse the inlined stub (we still need the - // original state until we are in the catch handler) - (!bbInFilterILRange(compCurBB)) && - // We disable pinvoke inlining inside handlers since the GSCookie is - // in the inlined Frame (see CORINFO_EE_INFO::InlinedCallFrameInfo::offsetOfGSCookie), - // but this would not protect framelets/return-address of handlers. - !compCurBB->hasHndIndex() && #ifdef _TARGET_AMD64_ - // Turns out JIT64 doesn't perform PInvoke inlining inside try regions, here's an excerpt of - // the comment from JIT64 explaining why: - // - //// [VSWhidbey: 611015] - because the jitted code links in the Frame (instead - //// of the stub) we rely on the Frame not being 'active' until inside the - //// stub. This normally happens by the stub setting the return address - //// pointer in the Frame object inside the stub. On a normal return, the - //// return address pointer is zeroed out so the Frame can be safely re-used, - //// but if an exception occurs, nobody zeros out the return address pointer. - //// Thus if we re-used the Frame object, it would go 'active' as soon as we - //// link it into the Frame chain. - //// - //// Technically we only need to disable PInvoke inlining if we're in a - //// handler or if we're - //// in a try body with a catch or filter/except where other non-handler code - //// in this method might run and try to re-use the dirty Frame object. - // - // Now, because of this, the VM actually assumes that in 64 bit we never PInvoke - // inline calls on any EH construct, you can verify that on VM\ExceptionHandling.cpp:203 - // The method responsible for resuming execution is UpdateObjectRefInResumeContextCallback - // you can see how it aligns with JIT64 policy of not inlining PInvoke calls almost right - // at the beginning of the body of the method. - !compCurBB->hasTryIndex() && -#endif - (!impLocAllocOnStack()) && (callRetTyp != TYP_STRUCT); + // On x64, we disable pinvoke inlining inside of try regions. + // Here is the comment from JIT64 explaining why: + // + // [VSWhidbey: 611015] - because the jitted code links in the + // Frame (instead of the stub) we rely on the Frame not being + // 'active' until inside the stub. This normally happens by the + // stub setting the return address pointer in the Frame object + // inside the stub. On a normal return, the return address + // pointer is zeroed out so the Frame can be safely re-used, but + // if an exception occurs, nobody zeros out the return address + // pointer. Thus if we re-used the Frame object, it would go + // 'active' as soon as we link it into the Frame chain. + // + // Technically we only need to disable PInvoke inlining if we're + // in a handler or if we're in a try body with a catch or + // filter/except where other non-handler code in this method + // might run and try to re-use the dirty Frame object. + // + // A desktop test case where this seems to matter is + // jit\jit64\ebvts\mcpp\sources2\ijw\__clrcall\vector_ctor_dtor.02\deldtor_clr.exe + const bool inX64Try = block->hasTryIndex(); +#else + const bool inX64Try = false; +#endif // _TARGET_AMD64_ + + return !inX64Try && !block->hasHndIndex(); } -void Compiler::impCheckForPInvokeCall(GenTreePtr call, - CORINFO_METHOD_HANDLE methHnd, - CORINFO_SIG_INFO* sig, - unsigned mflags) +//------------------------------------------------------------------------ +// impCheckForPInvokeCall examine call to see if it is a pinvoke and if so +// if it can be expressed as an inline pinvoke. +// +// Arguments: +// call - tree for the call +// methHnd - handle for the method being called (may be null) +// sig - signature of the method being called +// mflags - method flags for the method being called +// block - block contaning the call, or for inlinees, block +// containing the call being inlined +// +// Notes: +// Sets GTF_CALL_M_PINVOKE on the call for pinvokes. +// +// Also sets GTF_CALL_UNMANAGED on call for inline pinvokes if the +// call passes a combination of legality and profitabilty checks. +// +// If GTF_CALL_UNMANAGED is set, increments info.compCallUnmanaged + +void Compiler::impCheckForPInvokeCall( + GenTreePtr call, CORINFO_METHOD_HANDLE methHnd, CORINFO_SIG_INFO* sig, unsigned mflags, BasicBlock* block) { - var_types callRetTyp = JITtype2varType(sig->retType); CorInfoUnmanagedCallConv unmanagedCallConv; // If VM flagged it as Pinvoke, flag the call node accordingly @@ -5422,15 +5504,12 @@ void Compiler::impCheckForPInvokeCall(GenTreePtr call, if (opts.compMustInlinePInvokeCalli && methHnd == nullptr) { -#ifdef _TARGET_X86_ - // CALLI in IL stubs must be inlined - assert(impCanPInvokeInlineCallSite(callRetTyp)); - assert(!info.compCompHnd->pInvokeMarshalingRequired(methHnd, sig)); -#endif // _TARGET_X86_ + // Always inline pinvoke. } else { - if (!impCanPInvokeInline(callRetTyp)) + // Check legality and profitability. + if (!impCanPInvokeInline(block)) { return; } @@ -5439,6 +5518,14 @@ void Compiler::impCheckForPInvokeCall(GenTreePtr call, { return; } + + // Size-speed tradeoff: don't use inline pinvoke at rarely + // executed call sites. The non-inline version is more + // compact. + if (block->isRunRarely()) + { + return; + } } JITLOG((LL_INFO1000000, "\nInline a CALLI PINVOKE call from method %s", info.compFullName)); @@ -5446,8 +5533,6 @@ void Compiler::impCheckForPInvokeCall(GenTreePtr call, call->gtFlags |= GTF_CALL_UNMANAGED; info.compCallUnmanaged++; - assert(!compIsForInlining()); - // AMD64 convention is same for native and managed if (unmanagedCallConv == CORINFO_UNMANAGED_CALLCONV_C) { @@ -5736,6 +5821,7 @@ GenTreePtr Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolve break; case CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER: + { #ifdef FEATURE_READYTORUN_COMPILER if (opts.IsReadyToRun()) { @@ -5762,8 +5848,39 @@ GenTreePtr Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolve new (this, GT_CNS_INT) GenTreeIntCon(TYP_INT, pFieldInfo->offset, fs)); } break; + } +#if COR_JIT_EE_VERSION > 460 + case CORINFO_FIELD_STATIC_READYTORUN_HELPER: + { +#ifdef FEATURE_READYTORUN_COMPILER + noway_assert(opts.IsReadyToRun()); + CORINFO_LOOKUP_KIND kind = info.compCompHnd->getLocationOfThisType(info.compMethodHnd); + assert(kind.needsRuntimeLookup); + + GenTreePtr ctxTree = getRuntimeContextTree(kind.runtimeLookupKind); + GenTreeArgList* args = gtNewArgList(ctxTree); + + unsigned callFlags = 0; + + if (info.compCompHnd->getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_BEFOREFIELDINIT) + { + callFlags |= GTF_CALL_HOISTABLE; + } + var_types type = TYP_BYREF; + op1 = gtNewHelperCallNode(CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE, type, callFlags, args); + op1->gtCall.setEntryPoint(pFieldInfo->fieldLookup); + FieldSeqNode* fs = GetFieldSeqStore()->CreateSingleton(pResolvedToken->hField); + op1 = gtNewOperNode(GT_ADD, type, op1, + new (this, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, pFieldInfo->offset, fs)); +#else + unreached(); +#endif // FEATURE_READYTORUN_COMPILER + } + break; +#endif // COR_JIT_EE_VERSION > 460 default: + { if (!(access & CORINFO_ACCESS_ADDRESS)) { // In future, it may be better to just create the right tree here instead of folding it later. @@ -5820,6 +5937,7 @@ GenTreePtr Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolve } } break; + } } if (pFieldInfo->fieldFlags & CORINFO_FLG_FIELD_STATIC_IN_HEAP) @@ -6071,7 +6189,7 @@ bool Compiler::impIsTailCallILPattern(bool tailPrefixed, ((nextOpcode == CEE_NOP) || ((nextOpcode == CEE_POP) && (++cntPop == 1)))); // Next opcode = nop or exactly // one pop seen so far. #else - nextOpcode = (OPCODE)getU1LittleEndian(codeAddrOfNextOpcode); + nextOpcode = (OPCODE)getU1LittleEndian(codeAddrOfNextOpcode); #endif if (isCallPopAndRet) @@ -6845,9 +6963,15 @@ var_types Compiler::impImportCall(OPCODE opcode, //--------------------------- Inline NDirect ------------------------------ - if (!compIsForInlining()) + // For inline cases we technically should look at both the current + // block and the call site block (or just the latter if we've + // fused the EH trees). However the block-related checks pertain to + // EH and we currently won't inline a method with EH. So for + // inlinees, just checking the call site block is sufficient. { - impCheckForPInvokeCall(call, methHnd, sig, mflags); + // New lexical block here to avoid compilation errors because of GOTOs. + BasicBlock* block = compIsForInlining() ? impInlineInfo->iciBlock : compCurBB; + impCheckForPInvokeCall(call, methHnd, sig, mflags, block); } if (call->gtFlags & GTF_CALL_UNMANAGED) @@ -7035,7 +7159,7 @@ var_types Compiler::impImportCall(OPCODE opcode, { instParam = impReadyToRunLookupToTree(&callInfo->instParamLookup, GTF_ICON_CLASS_HDL, exactClassHandle); - if (instParam == NULL) + if (instParam == nullptr) { return callRetTyp; } @@ -7452,10 +7576,6 @@ DONE_CALL: { call = impFixupCallStructReturn(call, sig->retTypeClass); } - else if (varTypeIsLong(callRetTyp)) - { - call = impInitCallLongReturn(call); - } if ((call->gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0) { @@ -7467,6 +7587,13 @@ DONE_CALL: // TODO: Still using the widened type. call = gtNewInlineCandidateReturnExpr(call, genActualType(callRetTyp)); } + else + { + // For non-candidates we must also spill, since we + // might have locals live on the eval stack that this + // call can modify. + impSpillSideEffects(true, CHECK_SPILL_ALL DEBUGARG("non-inline candidate call")); + } } if (!bIntrinsicImported) @@ -7738,42 +7865,6 @@ GenTreePtr Compiler::impFixupCallStructReturn(GenTreePtr call, CORINFO_CLASS_HAN return call; } -//------------------------------------------------------------------------------------- -// impInitCallLongReturn: -// Initialize the ReturnTypDesc for a call that returns a TYP_LONG -// -// Arguments: -// call - GT_CALL GenTree node -// -// Return Value: -// Returns new GenTree node after initializing the ReturnTypeDesc of call node -// -GenTreePtr Compiler::impInitCallLongReturn(GenTreePtr call) -{ - assert(call->gtOper == GT_CALL); - -#if defined(_TARGET_X86_) && !defined(LEGACY_BACKEND) - // LEGACY_BACKEND does not use multi reg returns for calls with long return types - - if (varTypeIsLong(call)) - { - GenTreeCall* callNode = call->AsCall(); - - // The return type will remain as the incoming long type - callNode->gtReturnType = call->gtType; - - // Initialize Return type descriptor of call node - ReturnTypeDesc* retTypeDesc = callNode->GetReturnTypeDesc(); - retTypeDesc->InitializeLongReturnType(this); - - // must be a long returned in two registers - assert(retTypeDesc->GetReturnRegCount() == 2); - } -#endif // _TARGET_X86_ && !LEGACY_BACKEND - - return call; -} - /***************************************************************************** For struct return values, re-type the operand in the case where the ABI does not use a struct return buffer @@ -7804,6 +7895,9 @@ GenTreePtr Compiler::impFixupStructReturnType(GenTreePtr op, CORINFO_CLASS_HANDL unsigned lclNum = op->gtLclVarCommon.gtLclNum; lvaTable[lclNum].lvIsMultiRegRet = true; + // TODO-1stClassStructs: Handle constant propagation and CSE-ing of multireg returns. + op->gtFlags |= GTF_DONT_CSE; + return op; } @@ -7828,6 +7922,10 @@ GenTreePtr Compiler::impFixupStructReturnType(GenTreePtr op, CORINFO_CLASS_HANDL unsigned lclNum = op->gtLclVarCommon.gtLclNum; // Make sure this struct type stays as struct so that we can return it as an HFA lvaTable[lclNum].lvIsMultiRegRet = true; + + // TODO-1stClassStructs: Handle constant propagation and CSE-ing of multireg returns. + op->gtFlags |= GTF_DONT_CSE; + return op; } @@ -7860,6 +7958,10 @@ GenTreePtr Compiler::impFixupStructReturnType(GenTreePtr op, CORINFO_CLASS_HANDL // Make sure this struct type is not struct promoted lvaTable[lclNum].lvIsMultiRegRet = true; + + // TODO-1stClassStructs: Handle constant propagation and CSE-ing of multireg returns. + op->gtFlags |= GTF_DONT_CSE; + return op; } @@ -9311,8 +9413,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) opcodeOffs = (IL_OFFSET)(codeAddr - info.compCode); -#if defined(DEBUGGING_SUPPORT) || defined(DEBUG) - #ifndef DEBUG if (opts.compDbgInfo) #endif @@ -9424,8 +9524,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) } } -#endif // defined(DEBUGGING_SUPPORT) || defined(DEBUG) - CORINFO_CLASS_HANDLE clsHnd = DUMMY_INIT(NULL); CORINFO_CLASS_HANDLE ldelemClsHnd = DUMMY_INIT(NULL); CORINFO_CLASS_HANDLE stelemClsHnd = DUMMY_INIT(NULL); @@ -9515,6 +9613,14 @@ void Compiler::impImportBlockCode(BasicBlock* block) SPILL_APPEND: + // We need to call impSpillLclRefs() for a struct type lclVar. + // This is done for non-block assignments in the handling of stloc. + if ((op1->OperGet() == GT_ASG) && varTypeIsStruct(op1->gtOp.gtOp1) && + (op1->gtOp.gtOp1->gtOper == GT_LCL_VAR)) + { + impSpillLclRefs(op1->gtOp.gtOp1->AsLclVarCommon()->gtLclNum); + } + /* Append 'op1' to the list of statements */ impAppendTree(op1, (unsigned)CHECK_SPILL_ALL, impCurStmtOffs); goto DONE_APPEND; @@ -11087,8 +11193,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) COND_JUMP: - seenConditionalJump = true; - /* Fold comparison if we can */ op1 = gtFoldExpr(op1); @@ -12328,14 +12432,12 @@ void Compiler::impImportBlockCode(BasicBlock* block) // At present this can only be String else if (clsFlags & CORINFO_FLG_VAROBJSIZE) { -#if COR_JIT_EE_VERSION > 460 - if (eeGetEEInfo()->targetAbi == CORINFO_CORERT_ABI) + if (IsTargetAbi(CORINFO_CORERT_ABI)) { // The dummy argument does not exist in CoreRT newObjThisPtr = nullptr; } else -#endif { // This is the case for variable-sized objects that are not // arrays. In this case, call the constructor with a null 'this' @@ -12368,6 +12470,33 @@ void Compiler::impImportBlockCode(BasicBlock* block) // The lookup of the code pointer will be handled by CALL in this case if (clsFlags & CORINFO_FLG_VALUECLASS) { + if (compIsForInlining()) + { + // If value class has GC fields, inform the inliner. It may choose to + // bail out on the inline. + DWORD typeFlags = info.compCompHnd->getClassAttribs(resolvedToken.hClass); + if ((typeFlags & CORINFO_FLG_CONTAINS_GC_PTR) != 0) + { + compInlineResult->Note(InlineObservation::CALLEE_HAS_GC_STRUCT); + if (compInlineResult->IsFailure()) + { + return; + } + + // Do further notification in the case where the call site is rare; + // some policies do not track the relative hotness of call sites for + // "always" inline cases. + if (impInlineInfo->iciBlock->isRunRarely()) + { + compInlineResult->Note(InlineObservation::CALLSITE_RARE_GC_STRUCT); + if (compInlineResult->IsFailure()) + { + return; + } + } + } + } + CorInfoType jitTyp = info.compCompHnd->asCorInfoType(resolvedToken.hClass); unsigned size = info.compCompHnd->getClassSize(resolvedToken.hClass); @@ -12403,7 +12532,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) if (opts.IsReadyToRun()) { op1 = impReadyToRunHelperToTree(&resolvedToken, CORINFO_HELP_READYTORUN_NEW, TYP_REF); - usingReadyToRunHelper = (op1 != NULL); + usingReadyToRunHelper = (op1 != nullptr); } if (!usingReadyToRunHelper) @@ -12503,6 +12632,10 @@ void Compiler::impImportBlockCode(BasicBlock* block) if (compIsForInlining()) { + if (compDonotInline()) + { + return; + } // We rule out inlinees with explicit tail calls in fgMakeBasicBlocks. assert((prefixFlags & PREFIX_TAILCALL_EXPLICIT) == 0); } @@ -12696,7 +12829,9 @@ void Compiler::impImportBlockCode(BasicBlock* block) return; case CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER: - +#if COR_JIT_EE_VERSION > 460 + case CORINFO_FIELD_STATIC_READYTORUN_HELPER: +#endif /* We may be able to inline the field accessors in specific instantiations of generic * methods */ compInlineResult->NoteFatal(InlineObservation::CALLSITE_LDFLD_NEEDS_HELPER); @@ -12828,7 +12963,9 @@ void Compiler::impImportBlockCode(BasicBlock* block) #ifdef FEATURE_READYTORUN_COMPILER if (fieldInfo.fieldAccessor == CORINFO_FIELD_INSTANCE_WITH_BASE) + { op1->gtField.gtFieldLookup = fieldInfo.fieldLookup; + } #endif op1->gtFlags |= (obj->gtFlags & GTF_GLOB_EFFECT); @@ -12925,6 +13062,9 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CORINFO_FIELD_STATIC_RVA_ADDRESS: case CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER: case CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER: +#if COR_JIT_EE_VERSION > 460 + case CORINFO_FIELD_STATIC_READYTORUN_HELPER: +#endif op1 = impImportStaticFieldAccess(&resolvedToken, (CORINFO_ACCESS_FLAGS)aflags, &fieldInfo, lclTyp); break; @@ -13068,6 +13208,9 @@ void Compiler::impImportBlockCode(BasicBlock* block) return; case CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER: +#if COR_JIT_EE_VERSION > 460 + case CORINFO_FIELD_STATIC_READYTORUN_HELPER: +#endif /* We may be able to inline the field accessors in specific instantiations of generic * methods */ @@ -13134,7 +13277,9 @@ void Compiler::impImportBlockCode(BasicBlock* block) #ifdef FEATURE_READYTORUN_COMPILER if (fieldInfo.fieldAccessor == CORINFO_FIELD_INSTANCE_WITH_BASE) + { op1->gtField.gtFieldLookup = fieldInfo.fieldLookup; + } #endif op1->gtFlags |= (obj->gtFlags & GTF_GLOB_EFFECT); @@ -13185,6 +13330,9 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CORINFO_FIELD_STATIC_RVA_ADDRESS: case CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER: case CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER: +#if COR_JIT_EE_VERSION > 460 + case CORINFO_FIELD_STATIC_READYTORUN_HELPER: +#endif op1 = impImportStaticFieldAccess(&resolvedToken, (CORINFO_ACCESS_FLAGS)aflags, &fieldInfo, lclTyp); break; @@ -13376,7 +13524,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) { op1 = impReadyToRunHelperToTree(&resolvedToken, CORINFO_HELP_READYTORUN_NEWARR_1, TYP_REF, gtNewArgList(op2)); - usingReadyToRunHelper = (op1 != NULL); + usingReadyToRunHelper = (op1 != nullptr); if (!usingReadyToRunHelper) { @@ -13388,9 +13536,11 @@ void Compiler::impImportBlockCode(BasicBlock* block) // Reason: performance (today, we'll always use the slow helper for the R2R generics case) // Need to restore array classes before creating array objects on the heap - op1 = impTokenToHandle(&resolvedToken, NULL, TRUE /*mustRestoreHandle*/); - if (op1 == NULL) // compDonotInline() + op1 = impTokenToHandle(&resolvedToken, nullptr, TRUE /*mustRestoreHandle*/); + if (op1 == nullptr) + { // compDonotInline() return; + } } } @@ -13498,7 +13648,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) GenTreePtr opLookup = impReadyToRunHelperToTree(&resolvedToken, CORINFO_HELP_READYTORUN_ISINSTANCEOF, TYP_REF, gtNewArgList(op1)); - usingReadyToRunHelper = (opLookup != NULL); + usingReadyToRunHelper = (opLookup != nullptr); op1 = (usingReadyToRunHelper ? opLookup : op1); if (!usingReadyToRunHelper) @@ -13510,9 +13660,11 @@ void Compiler::impImportBlockCode(BasicBlock* block) // 3) Perform the 'is instance' check on the input object // Reason: performance (today, we'll always use the slow helper for the R2R generics case) - op2 = impTokenToHandle(&resolvedToken, NULL, FALSE); - if (op2 == NULL) // compDonotInline() + op2 = impTokenToHandle(&resolvedToken, nullptr, FALSE); + if (op2 == nullptr) + { // compDonotInline() return; + } } } @@ -14026,7 +14178,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) { GenTreePtr opLookup = impReadyToRunHelperToTree(&resolvedToken, CORINFO_HELP_READYTORUN_CHKCAST, TYP_REF, gtNewArgList(op1)); - usingReadyToRunHelper = (opLookup != NULL); + usingReadyToRunHelper = (opLookup != nullptr); op1 = (usingReadyToRunHelper ? opLookup : op1); if (!usingReadyToRunHelper) @@ -14038,9 +14190,11 @@ void Compiler::impImportBlockCode(BasicBlock* block) // 3) Check the object on the stack for the type-cast // Reason: performance (today, we'll always use the slow helper for the R2R generics case) - op2 = impTokenToHandle(&resolvedToken, NULL, FALSE); - if (op2 == NULL) // compDonotInline() + op2 = impTokenToHandle(&resolvedToken, nullptr, FALSE); + if (op2 == nullptr) + { // compDonotInline() return; + } } } @@ -14075,20 +14229,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) compInlineResult->NoteFatal(InlineObservation::CALLEE_THROW_WITH_INVALID_STACK); return; } - - /* Don't inline non-void conditionals that have a throw in one of the branches */ - - /* NOTE: If we do allow this, note that we can't simply do a - checkLiveness() to match the liveness at the end of the "then" - and "else" branches of the GT_COLON. The branch with the throw - will keep nothing live, so we should use the liveness at the - end of the non-throw branch. */ - - if (seenConditionalJump && (impInlineInfo->inlineCandidateInfo->fncRetType != TYP_VOID)) - { - compInlineResult->NoteFatal(InlineObservation::CALLSITE_CONDITIONAL_THROW); - return; - } } if (tiVerificationNeeded) @@ -14714,6 +14854,10 @@ GenTreePtr Compiler::impAssignMultiRegTypeToVar(GenTreePtr op, CORINFO_CLASS_HAN unsigned tmpNum = lvaGrabTemp(true DEBUGARG("Return value temp for multireg return.")); impAssignTempGen(tmpNum, op, hClass, (unsigned)CHECK_SPILL_NONE); GenTreePtr ret = gtNewLclvNode(tmpNum, op->gtType); + + // TODO-1stClassStructs: Handle constant propagation and CSE-ing of multireg returns. + ret->gtFlags |= GTF_DONT_CSE; + assert(IsMultiRegReturnedType(hClass)); // Mark the var so that fields are not promoted and stay together. @@ -14852,7 +14996,8 @@ bool Compiler::impReturnInstruction(BasicBlock* block, int prefixFlags, OPCODE& if (lvaInlineeReturnSpillTemp != BAD_VAR_NUM) { - assert(info.compRetNativeType != TYP_VOID && fgMoreThanOneReturnBlock()); + assert(info.compRetNativeType != TYP_VOID && + (fgMoreThanOneReturnBlock() || impInlineInfo->hasPinnedLocals)); // This is a bit of a workaround... // If we are inlining a call that returns a struct, where the actual "native" return type is @@ -14943,7 +15088,7 @@ bool Compiler::impReturnInstruction(BasicBlock* block, int prefixFlags, OPCODE& // in this case we have to insert multiple struct copies to the temp // and the retexpr is just the temp. assert(info.compRetNativeType != TYP_VOID); - assert(fgMoreThanOneReturnBlock()); + assert(fgMoreThanOneReturnBlock() || impInlineInfo->hasPinnedLocals); impAssignTempGen(lvaInlineeReturnSpillTemp, op2, se.seTypeInfo.GetClassHandle(), (unsigned)CHECK_SPILL_ALL); @@ -16469,7 +16614,7 @@ void Compiler::impImport(BasicBlock* method) // 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.eeFlags & CORJIT_FLG_IMPORT_ONLY) != 0) + if (tiVerificationNeeded && opts.jitFlags->IsSet(JitFlags::JIT_FLAG_IMPORT_ONLY)) { BADCODE("Basic block marked as not verifiable"); } @@ -16989,18 +17134,10 @@ void Compiler::impInlineRecordArgInfo(InlineInfo* pInlineInfo, #endif // FEATURE_SIMD } - if (curArgVal->gtFlags & GTF_ORDER_SIDEEFF) - { - // Right now impInlineSpillLclRefs and impInlineSpillGlobEffects don't take - // into account special side effects, so we disallow them during inlining. - inlineResult->NoteFatal(InlineObservation::CALLSITE_ARG_HAS_SIDE_EFFECT); - return; - } - - if (curArgVal->gtFlags & GTF_GLOB_EFFECT) + if (curArgVal->gtFlags & GTF_ALL_EFFECT) { inlCurArgInfo->argHasGlobRef = (curArgVal->gtFlags & GTF_GLOB_REF) != 0; - inlCurArgInfo->argHasSideEff = (curArgVal->gtFlags & GTF_SIDE_EFFECT) != 0; + inlCurArgInfo->argHasSideEff = (curArgVal->gtFlags & (GTF_ALL_EFFECT & ~GTF_GLOB_REF)) != 0; } if (curArgVal->gtOper == GT_LCL_VAR) @@ -17251,6 +17388,7 @@ void Compiler::impInlineInitVars(InlineInfo* pInlineInfo) var_types sigType = (var_types)eeGetArgType(argLst, &methInfo->args); lclVarInfo[i].lclVerTypeInfo = verParseArgSigToTypeInfo(&methInfo->args, argLst); + #ifdef FEATURE_SIMD if ((!foundSIMDType || (sigType == TYP_STRUCT)) && isSIMDClass(&(lclVarInfo[i].lclVerTypeInfo))) { @@ -17377,16 +17515,49 @@ void Compiler::impInlineInitVars(InlineInfo* pInlineInfo) var_types type = (var_types)eeGetArgType(localsSig, &methInfo->locals, &isPinned); lclVarInfo[i + argCnt].lclHasLdlocaOp = false; + lclVarInfo[i + argCnt].lclIsPinned = isPinned; lclVarInfo[i + argCnt].lclTypeInfo = type; if (isPinned) { - inlineResult->NoteFatal(InlineObservation::CALLEE_HAS_PINNED_LOCALS); - return; + // Pinned locals may cause inlines to fail. + inlineResult->Note(InlineObservation::CALLEE_HAS_PINNED_LOCALS); + if (inlineResult->IsFailure()) + { + return; + } } lclVarInfo[i + argCnt].lclVerTypeInfo = verParseArgSigToTypeInfo(&methInfo->locals, localsSig); + // If this local is a struct type with GC fields, inform the inliner. It may choose to bail + // out on the inline. + if (type == TYP_STRUCT) + { + CORINFO_CLASS_HANDLE lclHandle = lclVarInfo[i + argCnt].lclVerTypeInfo.GetClassHandle(); + DWORD typeFlags = info.compCompHnd->getClassAttribs(lclHandle); + if ((typeFlags & CORINFO_FLG_CONTAINS_GC_PTR) != 0) + { + inlineResult->Note(InlineObservation::CALLEE_HAS_GC_STRUCT); + if (inlineResult->IsFailure()) + { + return; + } + + // Do further notification in the case where the call site is rare; some policies do + // not track the relative hotness of call sites for "always" inline cases. + if (pInlineInfo->iciBlock->isRunRarely()) + { + inlineResult->Note(InlineObservation::CALLSITE_RARE_GC_STRUCT); + if (inlineResult->IsFailure()) + { + + return; + } + } + } + } + localsSig = info.compCompHnd->getArgNext(localsSig); #ifdef FEATURE_SIMD @@ -17431,6 +17602,28 @@ unsigned Compiler::impInlineFetchLocal(unsigned lclNum DEBUGARG(const char* reas lvaTable[tmpNum].lvHasLdAddrOp = 1; } + if (impInlineInfo->lclVarInfo[lclNum + impInlineInfo->argCnt].lclIsPinned) + { + lvaTable[tmpNum].lvPinned = 1; + + if (!impInlineInfo->hasPinnedLocals) + { + // If the inlinee returns a value, use a spill temp + // for the return value to ensure that even in case + // where the return expression refers to one of the + // pinned locals, we can unpin the local right after + // the inlined method body. + if ((info.compRetNativeType != TYP_VOID) && (lvaInlineeReturnSpillTemp == BAD_VAR_NUM)) + { + lvaInlineeReturnSpillTemp = + lvaGrabTemp(false DEBUGARG("Inline candidate pinned local return spill temp")); + lvaTable[lvaInlineeReturnSpillTemp].lvType = info.compRetNativeType; + } + } + + impInlineInfo->hasPinnedLocals = true; + } + if (impInlineInfo->lclVarInfo[lclNum + impInlineInfo->argCnt].lclVerTypeInfo.IsStruct()) { if (varTypeIsStruct(lclTyp)) @@ -17895,10 +18088,17 @@ void Compiler::impMarkInlineCandidate(GenTreePtr callNode, bool Compiler::IsTargetIntrinsic(CorInfoIntrinsics intrinsicId) { -#if defined(_TARGET_AMD64_) +#if defined(_TARGET_AMD64_) || (defined(_TARGET_X86_) && !defined(LEGACY_BACKEND)) switch (intrinsicId) { // Amd64 only has SSE2 instruction to directly compute sqrt/abs. + // + // TODO: Because the x86 backend only targets SSE for floating-point code, + // it does not treat Sine, Cosine, or Round as intrinsics (JIT32 + // implemented those intrinsics as x87 instructions). If this poses + // a CQ problem, it may be necessary to change the implementation of + // the helper calls to decrease call overhead or switch back to the + // x87 instructions. This is tracked by #7097. case CORINFO_INTRINSIC_Sqrt: case CORINFO_INTRINSIC_Abs: return true; diff --git a/src/jit/inline.cpp b/src/jit/inline.cpp index deccc0e..05fcf1c 100644 --- a/src/jit/inline.cpp +++ b/src/jit/inline.cpp @@ -447,7 +447,7 @@ void InlineContext::DumpData(unsigned indent) else if (m_Success) { const char* inlineReason = InlGetObservationString(m_Observation); - printf("%*s%u,\"%s\",\"%s\"", indent, "", m_Ordinal, inlineReason, calleeName); + printf("%*s%u,\"%s\",\"%s\",", indent, "", m_Ordinal, inlineReason, calleeName); m_Policy->DumpData(jitstdout); printf("\n"); } @@ -500,14 +500,25 @@ void InlineContext::DumpXml(FILE* file, unsigned indent) fprintf(file, "%*s%u\n", indent + 2, "", offset); fprintf(file, "%*s%s\n", indent + 2, "", inlineReason); - // Optionally, dump data about the last inline - if ((JitConfig.JitInlineDumpData() != 0) && (this == m_InlineStrategy->GetLastContext())) + // Optionally, dump data about the inline + const int dumpDataSetting = JitConfig.JitInlineDumpData(); + + // JitInlineDumpData=1 -- dump data plus deltas for last inline only + if ((dumpDataSetting == 1) && (this == m_InlineStrategy->GetLastContext())) { fprintf(file, "%*s", indent + 2, ""); m_InlineStrategy->DumpDataContents(file); fprintf(file, "\n"); } + // JitInlineDumpData=2 -- dump data for all inlines, no deltas + if ((dumpDataSetting == 2) && (m_Policy != nullptr)) + { + fprintf(file, "%*s", indent + 2, ""); + m_Policy->DumpData(file); + fprintf(file, "\n"); + } + newIndent = indent + 2; } @@ -646,10 +657,11 @@ void InlineResult::Report() m_Reported = true; #ifdef DEBUG - const char* callee = nullptr; + const char* callee = nullptr; + const bool showInlines = (JitConfig.JitPrintInlinedMethods() == 1); // Optionally dump the result - if (VERBOSE) + if (VERBOSE || showInlines) { const char* format = "INLINER: during '%s' result '%s' reason '%s' for '%s' calling '%s'\n"; const char* caller = (m_Caller == nullptr) ? "n/a" : m_RootCompiler->eeGetMethodFullName(m_Caller); @@ -689,12 +701,18 @@ void InlineResult::Report() #ifdef DEBUG + const char* obsString = InlGetObservationString(obs); + if (VERBOSE) { - const char* obsString = InlGetObservationString(obs); JITDUMP("\nINLINER: Marking %s as NOINLINE because of %s\n", callee, obsString); } + if (showInlines) + { + printf("Marking %s as NOINLINE because of %s\n", callee, obsString); + } + #endif // DEBUG COMP_HANDLE comp = m_RootCompiler->info.compCompHnd; @@ -740,6 +758,7 @@ InlineStrategy::InlineStrategy(Compiler* compiler) , m_HasForceViaDiscretionary(false) #if defined(DEBUG) || defined(INLINE_DATA) , m_MethodXmlFilePosition(0) + , m_Random(nullptr) #endif // defined(DEBUG) || defined(INLINE_DATA) { @@ -1155,10 +1174,10 @@ InlineContext* InlineStrategy::NewRoot() InlineContext* InlineStrategy::NewSuccess(InlineInfo* inlineInfo) { InlineContext* calleeContext = new (m_Compiler, CMK_Inlining) InlineContext(this); - GenTree* stmt = inlineInfo->iciStmt; + GenTreeStmt* stmt = inlineInfo->iciStmt; BYTE* calleeIL = inlineInfo->inlineCandidateInfo->methInfo.ILCode; unsigned calleeILSize = inlineInfo->inlineCandidateInfo->methInfo.ILCodeSize; - InlineContext* parentContext = stmt->gtStmt.gtInlineContext; + InlineContext* parentContext = stmt->gtInlineContext; noway_assert(parentContext != nullptr); @@ -1213,35 +1232,22 @@ InlineContext* InlineStrategy::NewSuccess(InlineInfo* inlineInfo) // A new InlineContext for diagnostic purposes, or nullptr if // the desired context could not be created. -InlineContext* InlineStrategy::NewFailure(GenTree* stmt, InlineResult* inlineResult) +InlineContext* InlineStrategy::NewFailure(GenTreeStmt* stmt, InlineResult* inlineResult) { - // Check for a parent context first. We may insert new statements - // between the caller and callee that do not pick up either's - // context, and these statements may have calls that we later - // examine and fail to inline. - // - // See fgInlinePrependStatements for examples. - - InlineContext* parentContext = stmt->gtStmt.gtInlineContext; - - if (parentContext == nullptr) - { - // Assume for now this is a failure to inline a call in a - // statement inserted between caller and callee. Just ignore - // it for the time being. - - return nullptr; - } - + // Check for a parent context first. We should now have a parent + // context for all statements. + InlineContext* parentContext = stmt->gtInlineContext; + assert(parentContext != nullptr); InlineContext* failedContext = new (m_Compiler, CMK_Inlining) InlineContext(this); - failedContext->m_Parent = parentContext; - // Push on front here will put siblings in reverse lexical - // order which we undo in the dumper + // Pushing the new context on the front of the parent child list + // will put siblings in reverse lexical order which we undo in the + // dumper. + failedContext->m_Parent = parentContext; failedContext->m_Sibling = parentContext->m_Child; parentContext->m_Child = failedContext; failedContext->m_Child = nullptr; - failedContext->m_Offset = stmt->AsStmt()->gtStmtILoffsx; + failedContext->m_Offset = stmt->gtStmtILoffsx; failedContext->m_Observation = inlineResult->GetObservation(); failedContext->m_Callee = inlineResult->GetCallee(); failedContext->m_Success = false; @@ -1354,7 +1360,7 @@ void InlineStrategy::DumpDataEnsurePolicyIsSet() // successful policy, so fake one up. if (m_LastSuccessfulPolicy == nullptr) { - const bool isPrejitRoot = (opts.eeFlags & CORJIT_FLG_PREJIT) != 0; + const bool isPrejitRoot = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT); m_LastSuccessfulPolicy = InlinePolicy::GetPolicy(m_Compiler, isPrejitRoot); // Add in a bit of data.... @@ -1388,7 +1394,7 @@ void InlineStrategy::DumpDataHeader(FILE* file) void InlineStrategy::DumpDataSchema(FILE* file) { DumpDataEnsurePolicyIsSet(); - fprintf(file, "Method,Version,HotSize,ColdSize,JitTime,SizeEstimate,TimeEstimate"); + fprintf(file, "Method,Version,HotSize,ColdSize,JitTime,SizeEstimate,TimeEstimate,"); m_LastSuccessfulPolicy->DumpSchema(file); } @@ -1424,7 +1430,7 @@ void InlineStrategy::DumpDataContents(FILE* file) microsecondsSpentJitting = (unsigned)((counts / countsPerSec) * 1000 * 1000); } - fprintf(file, "%08X,%u,%u,%u,%u,%d,%d", currentMethodToken, m_InlineCount, info.compTotalHotCodeSize, + fprintf(file, "%08X,%u,%u,%u,%u,%d,%d,", currentMethodToken, m_InlineCount, info.compTotalHotCodeSize, info.compTotalColdCodeSize, microsecondsSpentJitting, m_CurrentSizeEstimate / 10, m_CurrentTimeEstimate); m_LastSuccessfulPolicy->DumpData(file); } @@ -1461,10 +1467,22 @@ void InlineStrategy::DumpXml(FILE* file, unsigned indent) fprintf(file, "\n"); fprintf(file, "%s\n", m_LastSuccessfulPolicy->GetName()); - if (JitConfig.JitInlineDumpData() != 0) + const int dumpDataSetting = JitConfig.JitInlineDumpData(); + if (dumpDataSetting != 0) { fprintf(file, ""); - DumpDataSchema(file); + + if (dumpDataSetting == 1) + { + // JitInlineDumpData=1 -- dump schema for data plus deltas + DumpDataSchema(file); + } + else if (dumpDataSetting == 2) + { + // JitInlineDumpData=2 -- dump schema for data only + m_LastSuccessfulPolicy->DumpSchema(file); + } + fprintf(file, "\n"); } @@ -1484,7 +1502,7 @@ void InlineStrategy::DumpXml(FILE* file, unsigned indent) const Compiler::Info& info = m_Compiler->info; const Compiler::Options& opts = m_Compiler->opts; - const bool isPrejitRoot = (opts.eeFlags & CORJIT_FLG_PREJIT) != 0; + const bool isPrejitRoot = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT); const bool isForceInline = (info.compFlags & CORINFO_FLG_FORCEINLINE) != 0; // We'd really like the method identifier to be unique and @@ -1589,6 +1607,52 @@ void InlineStrategy::FinalizeXml(FILE* file) ReplayPolicy::FinalizeXml(); } +//------------------------------------------------------------------------ +// GetRandom: setup or access random state +// +// Return Value: +// New or pre-existing random state. +// +// Notes: +// Random state is kept per jit compilation request. Seed is partially +// specified externally (via stress or policy setting) and partially +// specified internally via method hash. + +CLRRandom* InlineStrategy::GetRandom() +{ + if (m_Random == nullptr) + { + int externalSeed = 0; + +#ifdef DEBUG + + if (m_Compiler->compRandomInlineStress()) + { + externalSeed = getJitStressLevel(); + } + +#endif // DEBUG + + int randomPolicyFlag = JitConfig.JitInlinePolicyRandom(); + if (randomPolicyFlag != 0) + { + externalSeed = randomPolicyFlag; + } + + int internalSeed = m_Compiler->info.compMethodHash(); + + assert(externalSeed != 0); + assert(internalSeed != 0); + + int seed = externalSeed ^ internalSeed; + + m_Random = new (m_Compiler, CMK_Inlining) CLRRandom(); + m_Random->Init(seed); + } + + return m_Random; +} + #endif // defined(DEBUG) || defined(INLINE_DATA) //------------------------------------------------------------------------ diff --git a/src/jit/inline.def b/src/jit/inline.def index 2c933fb..ff0b211 100644 --- a/src/jit/inline.def +++ b/src/jit/inline.def @@ -40,7 +40,6 @@ INLINE_OBSERVATION(HAS_MANAGED_VARARGS, bool, "managed varargs", INLINE_OBSERVATION(HAS_NATIVE_VARARGS, bool, "native varargs", FATAL, CALLEE) INLINE_OBSERVATION(HAS_NO_BODY, bool, "has no body", FATAL, CALLEE) INLINE_OBSERVATION(HAS_NULL_FOR_LDELEM, bool, "has null pointer for ldelem", FATAL, CALLEE) -INLINE_OBSERVATION(HAS_PINNED_LOCALS, bool, "has pinned locals", FATAL, CALLEE) INLINE_OBSERVATION(IS_ARRAY_METHOD, bool, "is array method", FATAL, CALLEE) INLINE_OBSERVATION(IS_GENERIC_VIRTUAL, bool, "generic virtual", FATAL, CALLEE) INLINE_OBSERVATION(IS_JIT_NOINLINE, bool, "noinline per JitNoinline", FATAL, CALLEE) @@ -78,6 +77,8 @@ INLINE_OBSERVATION(BELOW_ALWAYS_INLINE_SIZE, bool, "below ALWAYS_INLINE size" INLINE_OBSERVATION(CLASS_PROMOTABLE, bool, "promotable value class", INFORMATION, CALLEE) INLINE_OBSERVATION(DOES_NOT_RETURN, bool, "does not return", INFORMATION, CALLEE) INLINE_OBSERVATION(END_OPCODE_SCAN, bool, "done looking at opcodes", INFORMATION, CALLEE) +INLINE_OBSERVATION(HAS_GC_STRUCT, bool, "has gc field in struct local", INFORMATION, CALLEE) +INLINE_OBSERVATION(HAS_PINNED_LOCALS, bool, "has pinned locals", INFORMATION, CALLEE) INLINE_OBSERVATION(HAS_SIMD, bool, "has SIMD arg, local, or ret", INFORMATION, CALLEE) INLINE_OBSERVATION(HAS_SWITCH, bool, "has switch", INFORMATION, CALLEE) INLINE_OBSERVATION(IL_CODE_SIZE, int, "number of bytes of IL", INFORMATION, CALLEE) @@ -112,7 +113,6 @@ INLINE_OBSERVATION(HAS_NEWOBJ, bool, "has newobj", // ------ Call Site Correctness ------- INLINE_OBSERVATION(ARG_HAS_NULL_THIS, bool, "this pointer argument is null", FATAL, CALLSITE) -INLINE_OBSERVATION(ARG_HAS_SIDE_EFFECT, bool, "argument has side effect", FATAL, CALLSITE) INLINE_OBSERVATION(ARG_IS_MKREFANY, bool, "argument is mkrefany", FATAL, CALLSITE) INLINE_OBSERVATION(ARG_NO_BASH_TO_INT, bool, "argument can't bash to int", FATAL, CALLSITE) INLINE_OBSERVATION(ARG_NO_BASH_TO_REF, bool, "argument can't bash to ref", FATAL, CALLSITE) @@ -122,7 +122,6 @@ INLINE_OBSERVATION(CANT_EMBED_VARARGS_COOKIE, bool, "can't embed varargs cooki INLINE_OBSERVATION(CLASS_INIT_FAILURE_SPEC, bool, "speculative class init failed", FATAL, CALLSITE) INLINE_OBSERVATION(COMPILATION_ERROR, bool, "compilation error", FATAL, CALLSITE) INLINE_OBSERVATION(COMPILATION_FAILURE, bool, "failed to compile", FATAL, CALLSITE) -INLINE_OBSERVATION(CONDITIONAL_THROW, bool, "conditional throw", FATAL, CALLSITE) INLINE_OBSERVATION(CROSS_BOUNDARY_CALLI, bool, "cross-boundary calli", FATAL, CALLSITE) INLINE_OBSERVATION(CROSS_BOUNDARY_SECURITY, bool, "cross-boundary security check", FATAL, CALLSITE) INLINE_OBSERVATION(EXCEEDS_THRESHOLD, bool, "exceeds profit threshold", FATAL, CALLSITE) @@ -140,7 +139,7 @@ INLINE_OBSERVATION(IS_TOO_DEEP, bool, "too deep", INLINE_OBSERVATION(IS_VIRTUAL, bool, "virtual", FATAL, CALLSITE) INLINE_OBSERVATION(IS_VM_NOINLINE, bool, "noinline per VM", FATAL, CALLSITE) INLINE_OBSERVATION(IS_WITHIN_CATCH, bool, "within catch region", FATAL, CALLSITE) -INLINE_OBSERVATION(IS_WITHIN_FILTER, bool, "within filterregion", FATAL, CALLSITE) +INLINE_OBSERVATION(IS_WITHIN_FILTER, bool, "within filter region", FATAL, CALLSITE) INLINE_OBSERVATION(LDARGA_NOT_LOCAL_VAR, bool, "ldarga not on local var", FATAL, CALLSITE) INLINE_OBSERVATION(LDFLD_NEEDS_HELPER, bool, "ldfld needs helper", FATAL, CALLSITE) INLINE_OBSERVATION(LDVIRTFN_ON_NON_VIRTUAL, bool, "ldvirtfn on non-virtual", FATAL, CALLSITE) @@ -149,6 +148,7 @@ INLINE_OBSERVATION(NOT_CANDIDATE, bool, "not inline candidate", INLINE_OBSERVATION(NOT_PROFITABLE_INLINE, bool, "unprofitable inline", FATAL, CALLSITE) INLINE_OBSERVATION(OVER_BUDGET, bool, "inline exceeds budget", FATAL, CALLSITE) INLINE_OBSERVATION(OVER_INLINE_LIMIT, bool, "limited by JitInlineLimit", FATAL, CALLSITE) +INLINE_OBSERVATION(PIN_IN_TRY_REGION, bool, "within try region, pinned", FATAL, CALLSITE) INLINE_OBSERVATION(RANDOM_REJECT, bool, "random reject", FATAL, CALLSITE) INLINE_OBSERVATION(REQUIRES_SAME_THIS, bool, "requires same this", FATAL, CALLSITE) INLINE_OBSERVATION(RETURN_TYPE_MISMATCH, bool, "return type mismatch", FATAL, CALLSITE) @@ -157,12 +157,14 @@ INLINE_OBSERVATION(TOO_MANY_LOCALS, bool, "too many locals", // ------ Call Site Performance ------- +INLINE_OBSERVATION(RARE_GC_STRUCT, bool, "rarely called, has gc struct", INFORMATION, CALLSITE) // ------ Call Site Information ------- INLINE_OBSERVATION(CONSTANT_ARG_FEEDS_TEST, bool, "constant argument feeds test", INFORMATION, CALLSITE) INLINE_OBSERVATION(DEPTH, int, "depth", INFORMATION, CALLSITE) INLINE_OBSERVATION(FREQUENCY, int, "rough call site frequency", INFORMATION, CALLSITE) +INLINE_OBSERVATION(IN_TRY_REGION, bool, "call site in try region", INFORMATION, CALLSITE) INLINE_OBSERVATION(IS_PROFITABLE_INLINE, bool, "profitable inline", INFORMATION, CALLSITE) INLINE_OBSERVATION(IS_SAME_THIS, bool, "same this as root caller", INFORMATION, CALLSITE) INLINE_OBSERVATION(IS_SIZE_DECREASING_INLINE, bool, "size decreasing inline", INFORMATION, CALLSITE) diff --git a/src/jit/inline.h b/src/jit/inline.h index e3d5750..2634ebe 100644 --- a/src/jit/inline.h +++ b/src/jit/inline.h @@ -85,11 +85,6 @@ const unsigned int MAX_INL_ARGS = 10; // does not include obj pointer const unsigned int MAX_INL_LCLS = 8; #endif // LEGACY_BACKEND -// Flags lost during inlining. - -#define CORJIT_FLG_LOST_WHEN_INLINING \ - (CORJIT_FLG_BBOPT | CORJIT_FLG_BBINSTR | CORJIT_FLG_PROF_ENTERLEAVE | CORJIT_FLG_DEBUG_EnC | CORJIT_FLG_DEBUG_INFO) - // Forward declarations class InlineStrategy; @@ -542,6 +537,7 @@ struct InlLclVarInfo var_types lclTypeInfo; typeInfo lclVerTypeInfo; bool lclHasLdlocaOp; // Is there LDLOCA(s) operation on this argument? + bool lclIsPinned; }; // InlineInfo provides detailed information about a particular inline candidate. @@ -568,12 +564,13 @@ struct InlineInfo InlLclVarInfo lclVarInfo[MAX_INL_LCLS + MAX_INL_ARGS + 1]; // type information from local sig bool thisDereferencedFirst; + bool hasPinnedLocals; #ifdef FEATURE_SIMD bool hasSIMDTypeArgLocalOrReturn; #endif // FEATURE_SIMD GenTreeCall* iciCall; // The GT_CALL node to be inlined. - GenTree* iciStmt; // The statement iciCall is in. + GenTreeStmt* iciStmt; // The statement iciCall is in. BasicBlock* iciBlock; // The basic block iciStmt is in. }; @@ -706,7 +703,7 @@ public: InlineContext* NewSuccess(InlineInfo* inlineInfo); // Create context for a failing inline. - InlineContext* NewFailure(GenTree* stmt, InlineResult* inlineResult); + InlineContext* NewFailure(GenTreeStmt* stmt, InlineResult* inlineResult); // Compiler associated with this strategy Compiler* GetCompiler() const @@ -823,6 +820,9 @@ public: m_MethodXmlFilePosition = val; } + // Set up or access random state (for use by RandomPolicy) + CLRRandom* GetRandom(); + #endif // defined(DEBUG) || defined(INLINE_DATA) // Some inline limit values @@ -887,7 +887,8 @@ private: bool m_HasForceViaDiscretionary; #if defined(DEBUG) || defined(INLINE_DATA) - long m_MethodXmlFilePosition; + long m_MethodXmlFilePosition; + CLRRandom* m_Random; #endif // defined(DEBUG) || defined(INLINE_DATA) }; diff --git a/src/jit/inlinepolicy.cpp b/src/jit/inlinepolicy.cpp index f80f3a5..61e70c3 100644 --- a/src/jit/inlinepolicy.cpp +++ b/src/jit/inlinepolicy.cpp @@ -27,22 +27,22 @@ InlinePolicy* InlinePolicy::GetPolicy(Compiler* compiler, bool isPrejitRoot) { -#ifdef DEBUG +#if defined(DEBUG) || defined(INLINE_DATA) - // Optionally install the RandomPolicy. - bool useRandomPolicy = compiler->compRandomInlineStress(); +#if defined(DEBUG) + const bool useRandomPolicyForStress = compiler->compRandomInlineStress(); +#else + const bool useRandomPolicyForStress = false; +#endif // defined(DEBUG) + + const bool useRandomPolicy = (JitConfig.JitInlinePolicyRandom() != 0); - if (useRandomPolicy) + // Optionally install the RandomPolicy. + if (useRandomPolicyForStress || useRandomPolicy) { - unsigned seed = getJitStressLevel(); - assert(seed != 0); - return new (compiler, CMK_Inlining) RandomPolicy(compiler, isPrejitRoot, seed); + return new (compiler, CMK_Inlining) RandomPolicy(compiler, isPrejitRoot); } -#endif // DEBUG - -#if defined(DEBUG) || defined(INLINE_DATA) - // Optionally install the ReplayPolicy. bool useReplayPolicy = JitConfig.JitInlinePolicyReplay() != 0; @@ -106,7 +106,7 @@ InlinePolicy* InlinePolicy::GetPolicy(Compiler* compiler, bool isPrejitRoot) void LegalPolicy::NoteFatal(InlineObservation obs) { // As a safeguard, all fatal impact must be - // reported via noteFatal. + // reported via NoteFatal. assert(InlGetImpact(obs) == InlineImpact::FATAL); NoteInternal(obs); assert(InlDecisionIsFailure(m_Decision)); @@ -243,7 +243,7 @@ void LegacyPolicy::NoteBool(InlineObservation obs, bool value) InlineImpact impact = InlGetImpact(obs); // As a safeguard, all fatal impact must be - // reported via noteFatal. + // reported via NoteFatal. assert(impact != InlineImpact::FATAL); // Handle most information here @@ -383,6 +383,12 @@ void LegacyPolicy::NoteBool(InlineObservation obs, bool value) break; } + case InlineObservation::CALLEE_HAS_PINNED_LOCALS: + // The legacy policy is to never inline methods with + // pinned locals. + SetNever(obs); + break; + default: // Ignore the remainder for now break; @@ -443,16 +449,16 @@ void LegacyPolicy::NoteInt(InlineObservation obs, int value) // Now that we know size and forceinline state, // update candidacy. - if (m_CodeSize <= InlineStrategy::ALWAYS_INLINE_SIZE) - { - // Candidate based on small size - SetCandidate(InlineObservation::CALLEE_BELOW_ALWAYS_INLINE_SIZE); - } - else if (m_IsForceInline) + if (m_IsForceInline) { // Candidate based on force inline SetCandidate(InlineObservation::CALLEE_IS_FORCE_INLINE); } + else if (m_CodeSize <= InlineStrategy::ALWAYS_INLINE_SIZE) + { + // Candidate based on small size + SetCandidate(InlineObservation::CALLEE_BELOW_ALWAYS_INLINE_SIZE); + } else if (m_CodeSize <= m_RootCompiler->m_inlineStrategy->GetMaxInlineILSize()) { // Candidate, pending profitability evaluation @@ -842,11 +848,21 @@ int LegacyPolicy::CodeSizeEstimate() // NoteBool: handle a boolean observation with non-fatal impact // // Arguments: -// obs - the current obsevation +// obs - the current observation // value - the value of the observation void EnhancedLegacyPolicy::NoteBool(InlineObservation obs, bool value) { + +#ifdef DEBUG + // Check the impact + InlineImpact impact = InlGetImpact(obs); + + // As a safeguard, all fatal impact must be + // reported via NoteFatal. + assert(impact != InlineImpact::FATAL); +#endif // DEBUG + switch (obs) { case InlineObservation::CALLEE_DOES_NOT_RETURN: @@ -854,6 +870,36 @@ void EnhancedLegacyPolicy::NoteBool(InlineObservation obs, bool value) m_IsNoReturnKnown = true; break; + case InlineObservation::CALLSITE_RARE_GC_STRUCT: + // If this is a discretionary or always inline candidate + // with a gc struct, we may change our mind about inlining + // if the call site is rare, to avoid costs associated with + // zeroing the GC struct up in the root prolog. + if (m_Observation == InlineObservation::CALLEE_BELOW_ALWAYS_INLINE_SIZE) + { + assert(m_CallsiteFrequency == InlineCallsiteFrequency::UNUSED); + SetFailure(obs); + return; + } + else if (m_Observation == InlineObservation::CALLEE_IS_DISCRETIONARY_INLINE) + { + assert(m_CallsiteFrequency == InlineCallsiteFrequency::RARE); + SetFailure(obs); + return; + } + break; + + case InlineObservation::CALLEE_HAS_PINNED_LOCALS: + if (m_CallsiteIsInTryRegion) + { + // Inlining a method with pinned locals in a try + // region requires wrapping the inline body in a + // try/finally to ensure unpinning. Bail instead. + SetFailure(InlineObservation::CALLSITE_PIN_IN_TRY_REGION); + return; + } + break; + default: // Pass all other information to the legacy policy LegacyPolicy::NoteBool(obs, value); @@ -928,7 +974,7 @@ bool EnhancedLegacyPolicy::PropagateNeverToRuntime() const return propagate; } -#ifdef DEBUG +#if defined(DEBUG) || defined(INLINE_DATA) //------------------------------------------------------------------------ // RandomPolicy: construct a new RandomPolicy @@ -936,89 +982,10 @@ bool EnhancedLegacyPolicy::PropagateNeverToRuntime() const // Arguments: // compiler -- compiler instance doing the inlining (root compiler) // isPrejitRoot -- true if this compiler is prejitting the root method -// seed -- seed value for the random number generator - -RandomPolicy::RandomPolicy(Compiler* compiler, bool isPrejitRoot, unsigned seed) - : LegalPolicy(isPrejitRoot) - , m_RootCompiler(compiler) - , m_Random(nullptr) - , m_CodeSize(0) - , m_IsForceInline(false) - , m_IsForceInlineKnown(false) -{ - // If necessary, setup and seed the random state. - if (compiler->inlRNG == nullptr) - { - compiler->inlRNG = new (compiler, CMK_Inlining) CLRRandom(); - unsigned hash = m_RootCompiler->info.compMethodHash(); - assert(hash != 0); - assert(seed != 0); - int hashSeed = static_cast(hash ^ seed); - compiler->inlRNG->Init(hashSeed); - } - - m_Random = compiler->inlRNG; -} - -//------------------------------------------------------------------------ -// NoteSuccess: handle finishing all the inlining checks successfully - -void RandomPolicy::NoteSuccess() +RandomPolicy::RandomPolicy(Compiler* compiler, bool isPrejitRoot) : DiscretionaryPolicy(compiler, isPrejitRoot) { - assert(InlDecisionIsCandidate(m_Decision)); - m_Decision = InlineDecision::SUCCESS; -} - -//------------------------------------------------------------------------ -// NoteBool: handle a boolean observation with non-fatal impact -// -// Arguments: -// obs - the current obsevation -// value - the value of the observation -void RandomPolicy::NoteBool(InlineObservation obs, bool value) -{ - // Check the impact - InlineImpact impact = InlGetImpact(obs); - - // As a safeguard, all fatal impact must be - // reported via noteFatal. - assert(impact != InlineImpact::FATAL); - - // Handle most information here - bool isInformation = (impact == InlineImpact::INFORMATION); - bool propagate = !isInformation; - - if (isInformation) - { - switch (obs) - { - case InlineObservation::CALLEE_IS_FORCE_INLINE: - // The RandomPolicy still honors force inlines. - // - // We may make the force-inline observation more than - // once. All observations should agree. - assert(!m_IsForceInlineKnown || (m_IsForceInline == value)); - m_IsForceInline = value; - m_IsForceInlineKnown = true; - break; - - case InlineObservation::CALLEE_HAS_SWITCH: - case InlineObservation::CALLEE_UNSUPPORTED_OPCODE: - // Pass these on, they should cause inlining to fail. - propagate = true; - break; - - default: - // Ignore the remainder for now - break; - } - } - - if (propagate) - { - NoteInternal(obs); - } + m_Random = compiler->m_inlineStrategy->GetRandom(); } //------------------------------------------------------------------------ @@ -1032,7 +999,6 @@ void RandomPolicy::NoteInt(InlineObservation obs, int value) { switch (obs) { - case InlineObservation::CALLEE_IL_CODE_SIZE: { assert(m_IsForceInlineKnown); @@ -1054,7 +1020,8 @@ void RandomPolicy::NoteInt(InlineObservation obs, int value) } default: - // Ignore all other information + // Defer to superclass for all other information + DiscretionaryPolicy::NoteInt(obs, value); break; } } @@ -1087,6 +1054,16 @@ void RandomPolicy::DetermineProfitability(CORINFO_METHOD_INFO* methodInfo) } } + // If we're also dumping inline data, make additional observations + // based on the method info, and estimate code size and perf + // impact, so that the reports have the necessary data. + if (JitConfig.JitInlineDumpData() != 0) + { + MethodInfoObservations(methodInfo); + EstimateCodeSize(); + EstimatePerformanceImpact(); + } + // Use a probability curve that roughly matches the observed // behavior of the LegacyPolicy. That way we're inlining // differently but not creating enormous methods. @@ -1165,7 +1142,7 @@ void RandomPolicy::DetermineProfitability(CORINFO_METHOD_INFO* methodInfo) } } -#endif // DEBUG +#endif // defined(DEBUG) || defined(INLINE_DATA) #ifdef _MSC_VER // Disable warning about new array member initialization behavior @@ -1181,7 +1158,7 @@ void RandomPolicy::DetermineProfitability(CORINFO_METHOD_INFO* methodInfo) // clang-format off DiscretionaryPolicy::DiscretionaryPolicy(Compiler* compiler, bool isPrejitRoot) - : LegacyPolicy(compiler, isPrejitRoot) + : EnhancedLegacyPolicy(compiler, isPrejitRoot) , m_Depth(0) , m_BlockCount(0) , m_Maxstack(0) @@ -1227,6 +1204,7 @@ DiscretionaryPolicy::DiscretionaryPolicy(Compiler* compiler, bool isPrejitRoot) , m_IsSameThis(false) , m_CallerHasNewArray(false) , m_CallerHasNewObj(false) + , m_CalleeHasGCStruct(false) { // Empty } @@ -1278,8 +1256,17 @@ void DiscretionaryPolicy::NoteBool(InlineObservation obs, bool value) m_CallerHasNewObj = value; break; + case InlineObservation::CALLEE_HAS_GC_STRUCT: + m_CalleeHasGCStruct = value; + break; + + case InlineObservation::CALLSITE_RARE_GC_STRUCT: + // This is redundant since this policy tracks call site + // hotness for all candidates. So ignore. + break; + default: - LegacyPolicy::NoteBool(obs, value); + EnhancedLegacyPolicy::NoteBool(obs, value); break; } } @@ -1295,7 +1282,6 @@ void DiscretionaryPolicy::NoteInt(InlineObservation obs, int value) { switch (obs) { - case InlineObservation::CALLEE_IL_CODE_SIZE: // Override how code size is handled { @@ -1323,7 +1309,7 @@ void DiscretionaryPolicy::NoteInt(InlineObservation obs, int value) // on similarity of impact on codegen. OPCODE opcode = static_cast(value); ComputeOpcodeBin(opcode); - LegacyPolicy::NoteInt(obs, value); + EnhancedLegacyPolicy::NoteInt(obs, value); break; } @@ -1344,8 +1330,8 @@ void DiscretionaryPolicy::NoteInt(InlineObservation obs, int value) break; default: - // Delegate remainder to the LegacyPolicy. - LegacyPolicy::NoteInt(obs, value); + // Delegate remainder to the super class. + EnhancedLegacyPolicy::NoteInt(obs, value); break; } } @@ -1660,8 +1646,8 @@ void DiscretionaryPolicy::DetermineProfitability(CORINFO_METHOD_INFO* methodInfo // model for actual inlining. EstimatePerformanceImpact(); - // Delegate to LegacyPolicy for the rest - LegacyPolicy::DetermineProfitability(methodInfo); + // Delegate to super class for the rest + EnhancedLegacyPolicy::DetermineProfitability(methodInfo); } //------------------------------------------------------------------------ @@ -1869,7 +1855,7 @@ int DiscretionaryPolicy::CodeSizeEstimate() void DiscretionaryPolicy::DumpSchema(FILE* file) const { - fprintf(file, ",ILSize"); + fprintf(file, "ILSize"); fprintf(file, ",CallsiteFrequency"); fprintf(file, ",InstructionCount"); fprintf(file, ",LoadStoreCount"); @@ -1938,6 +1924,8 @@ void DiscretionaryPolicy::DumpSchema(FILE* file) const fprintf(file, ",IsSameThis"); fprintf(file, ",CallerHasNewArray"); fprintf(file, ",CallerHasNewObj"); + fprintf(file, ",CalleeDoesNotReturn"); + fprintf(file, ",CalleeHasGCStruct"); } //------------------------------------------------------------------------ @@ -1949,7 +1937,7 @@ void DiscretionaryPolicy::DumpSchema(FILE* file) const void DiscretionaryPolicy::DumpData(FILE* file) const { - fprintf(file, ",%u", m_CodeSize); + fprintf(file, "%u", m_CodeSize); fprintf(file, ",%u", m_CallsiteFrequency); fprintf(file, ",%u", m_InstructionCount); fprintf(file, ",%u", m_LoadStoreCount); @@ -2018,6 +2006,8 @@ void DiscretionaryPolicy::DumpData(FILE* file) const fprintf(file, ",%u", m_IsSameThis ? 1 : 0); fprintf(file, ",%u", m_CallerHasNewArray ? 1 : 0); fprintf(file, ",%u", m_CallerHasNewObj ? 1 : 0); + fprintf(file, ",%u", m_IsNoReturn ? 1 : 0); + fprintf(file, ",%u", m_CalleeHasGCStruct ? 1 : 0); } #endif // defined(DEBUG) || defined(INLINE_DATA) @@ -2473,7 +2463,7 @@ bool ReplayPolicy::FindMethod() // See if token matches unsigned token = 0; - int count = sscanf(buffer, " %u ", &token); + int count = sscanf_s(buffer, " %u ", &token); if ((count != 1) || (token != methodToken)) { continue; @@ -2487,7 +2477,7 @@ bool ReplayPolicy::FindMethod() // See if hash matches unsigned hash = 0; - count = sscanf(buffer, " %u ", &hash); + count = sscanf_s(buffer, " %u ", &hash); if ((count != 1) || (hash != methodHash)) { continue; @@ -2646,7 +2636,7 @@ bool ReplayPolicy::FindInline(unsigned token, unsigned hash, unsigned offset) // Match token unsigned inlineToken = 0; - int count = sscanf(buffer, " %u ", &inlineToken); + int count = sscanf_s(buffer, " %u ", &inlineToken); if ((count != 1) || (inlineToken != token)) { @@ -2661,7 +2651,7 @@ bool ReplayPolicy::FindInline(unsigned token, unsigned hash, unsigned offset) // Match hash unsigned inlineHash = 0; - count = sscanf(buffer, " %u ", &inlineHash); + count = sscanf_s(buffer, " %u ", &inlineHash); if ((count != 1) || (inlineHash != hash)) { @@ -2676,7 +2666,7 @@ bool ReplayPolicy::FindInline(unsigned token, unsigned hash, unsigned offset) // Match offset unsigned inlineOffset = 0; - count = sscanf(buffer, " %u ", &inlineOffset); + count = sscanf_s(buffer, " %u ", &inlineOffset); if ((count != 1) || (inlineOffset != offset)) { continue; @@ -2695,7 +2685,7 @@ bool ReplayPolicy::FindInline(unsigned token, unsigned hash, unsigned offset) if (fgets(buffer, sizeof(buffer), s_ReplayFile) != nullptr) { unsigned collectData = 0; - count = sscanf(buffer, " %u ", &collectData); + count = sscanf_s(buffer, " %u ", &collectData); if (count == 1) { diff --git a/src/jit/inlinepolicy.h b/src/jit/inlinepolicy.h index 62031c8..3239dcb 100644 --- a/src/jit/inlinepolicy.h +++ b/src/jit/inlinepolicy.h @@ -98,6 +98,7 @@ public: , m_HasSimd(false) , m_LooksLikeWrapperMethod(false) , m_MethodIsMostlyLoadStore(false) + , m_CallsiteIsInTryRegion(false) { // empty } @@ -165,6 +166,7 @@ protected: bool m_HasSimd : 1; bool m_LooksLikeWrapperMethod : 1; bool m_MethodIsMostlyLoadStore : 1; + bool m_CallsiteIsInTryRegion : 1; }; // EnhancedLegacyPolicy extends the legacy policy by rejecting @@ -196,65 +198,15 @@ protected: bool m_IsNoReturnKnown : 1; }; -#ifdef DEBUG - -// RandomPolicy implements a policy that inlines at random. -// It is mostly useful for stress testing. - -class RandomPolicy : public LegalPolicy -{ -public: - // Construct a RandomPolicy - RandomPolicy(Compiler* compiler, bool isPrejitRoot, unsigned seed); - - // Policy observations - void NoteSuccess() override; - void NoteBool(InlineObservation obs, bool value) override; - void NoteInt(InlineObservation obs, int value) override; - - // Policy determinations - void DetermineProfitability(CORINFO_METHOD_INFO* methodInfo) override; - - // Policy policies - bool PropagateNeverToRuntime() const override - { - return true; - } - bool IsLegacyPolicy() const override - { - return false; - } - - // Policy estimates - int CodeSizeEstimate() override - { - return 0; - } - - const char* GetName() const override - { - return "RandomPolicy"; - } - -private: - // Data members - Compiler* m_RootCompiler; - CLRRandom* m_Random; - unsigned m_CodeSize; - bool m_IsForceInline : 1; - bool m_IsForceInlineKnown : 1; -}; - -#endif // DEBUG - -// DiscretionaryPolicy is a variant of the legacy policy. It differs -// in that there is no ALWAYS_INLINE class, there is no IL size limit, -// it does not try and maintain legacy compatabilty, and in prejit mode, -// discretionary failures do not set the "NEVER" inline bit. +// DiscretionaryPolicy is a variant of the enhanced legacy policy. It +// differs in that there is no ALWAYS_INLINE class, there is no IL +// size limit, it does not try and maintain legacy compatabilty, and +// in prejit mode, discretionary failures do not set the "NEVER" +// inline bit. // // It is useful for gathering data about inline costs. -class DiscretionaryPolicy : public LegacyPolicy +class DiscretionaryPolicy : public EnhancedLegacyPolicy { public: // Construct a DiscretionaryPolicy @@ -266,10 +218,6 @@ public: // Policy policies bool PropagateNeverToRuntime() const override; - bool IsLegacyPolicy() const override - { - return false; - } // Policy determinations void DetermineProfitability(CORINFO_METHOD_INFO* methodInfo) override; @@ -346,6 +294,7 @@ protected: bool m_IsSameThis; bool m_CallerHasNewArray; bool m_CallerHasNewObj; + bool m_CalleeHasGCStruct; }; // ModelPolicy is an experimental policy that uses the results @@ -382,6 +331,35 @@ public: #if defined(DEBUG) || defined(INLINE_DATA) +// RandomPolicy implements a policy that inlines at random. +// It is mostly useful for stress testing. + +class RandomPolicy : public DiscretionaryPolicy +{ +public: + // Construct a RandomPolicy + RandomPolicy(Compiler* compiler, bool isPrejitRoot); + + // Policy observations + void NoteInt(InlineObservation obs, int value) override; + + // Policy determinations + void DetermineProfitability(CORINFO_METHOD_INFO* methodInfo) override; + + const char* GetName() const override + { + return "RandomPolicy"; + } + +private: + // Data members + CLRRandom* m_Random; +}; + +#endif // defined(DEBUG) || defined(INLINE_DATA) + +#if defined(DEBUG) || defined(INLINE_DATA) + // FullPolicy is an experimental policy that will always inline if // possible, subject to externally settable depth and size limits. // diff --git a/src/jit/instr.cpp b/src/jit/instr.cpp index d516e0d..edc4483 100644 --- a/src/jit/instr.cpp +++ b/src/jit/instr.cpp @@ -149,8 +149,6 @@ const char* CodeGen::genSizeStr(emitAttr attr) nullptr, "xmmword ptr ", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "ymmword ptr" }; @@ -3054,7 +3052,7 @@ bool CodeGenInterface::validImmForBL(ssize_t addr) return // If we are running the altjit for NGEN, then assume we can use the "BL" instruction. // This matches the usual behavior for NGEN, since we normally do generate "BL". - (!compiler->info.compMatchedVM && (compiler->opts.eeFlags & CORJIT_FLG_PREJIT)) || + (!compiler->info.compMatchedVM && compiler->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT)) || (compiler->eeGetRelocTypeHint((void*)addr) == IMAGE_REL_BASED_THUMB_BRANCH24); } bool CodeGen::arm_Valid_Imm_For_BL(ssize_t addr) @@ -3240,7 +3238,7 @@ instruction CodeGen::ins_Move_Extend(var_types srcType, bool srcInReg) * * Parameters * srcType - source type - * aligned - whether source is 16-byte aligned if srcType is a SIMD type + * aligned - whether source is properly aligned if srcType is a SIMD type */ instruction CodeGenInterface::ins_Load(var_types srcType, bool aligned /*=false*/) { @@ -3258,8 +3256,7 @@ instruction CodeGenInterface::ins_Load(var_types srcType, bool aligned /*=false* #endif // FEATURE_SIMD if (compiler->canUseAVX()) { - // TODO-CQ: consider alignment of AVX vectors. - return INS_movupd; + return (aligned) ? INS_movapd : INS_movupd; } else { @@ -3404,7 +3401,7 @@ instruction CodeGen::ins_Copy(var_types dstType) * * Parameters * dstType - destination type - * aligned - whether destination is 16-byte aligned if dstType is a SIMD type + * aligned - whether destination is properly aligned if dstType is a SIMD type */ instruction CodeGenInterface::ins_Store(var_types dstType, bool aligned /*=false*/) { @@ -3422,8 +3419,7 @@ instruction CodeGenInterface::ins_Store(var_types dstType, bool aligned /*=false #endif // FEATURE_SIMD if (compiler->canUseAVX()) { - // TODO-CQ: consider alignment of AVX vectors. - return INS_movupd; + return (aligned) ? INS_movapd : INS_movupd; } else { diff --git a/src/jit/instr.h b/src/jit/instr.h index c38f8d2..2d50234 100644 --- a/src/jit/instr.h +++ b/src/jit/instr.h @@ -284,15 +284,19 @@ END_DECLARE_TYPED_ENUM(emitAttr,unsigned) #define EmitSize(x) (EA_ATTR(genTypeSize(TypeGet(x)))) // Enum specifying the instruction set for generating floating point or SIMD code. +// These enums are ordered such that each one is inclusive of previous instruction sets +// and the VM ensures this as well when setting the CONFIG flags. enum InstructionSet { #ifdef _TARGET_XARCH_ - InstructionSet_SSE2, - InstructionSet_AVX, + InstructionSet_SSE2, // SSE2 Instruction set + InstructionSet_SSE3_4, // SSE3, SSSE3, SSE4.1 and SSE4.2 instruction set + InstructionSet_AVX, // AVX2 instruction set + // TODO-Cleaup - This should be named as InstructionSet_AVX2 #elif defined(_TARGET_ARM_) InstructionSet_NEON, #endif - InstructionSet_NONE + InstructionSet_NONE // No instruction set is available indicating an invalid value }; // clang-format on diff --git a/src/jit/instrsxarch.h b/src/jit/instrsxarch.h index 436563b..4317334 100644 --- a/src/jit/instrsxarch.h +++ b/src/jit/instrsxarch.h @@ -178,6 +178,7 @@ INST3(FIRST_SSE2_INSTRUCTION, "FIRST_SSE2_INSTRUCTION", 0, IUM_WR, 0, 0, BAD_CO // These are the SSE instructions used on x86 INST3( mov_i2xmm, "movd" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, PCKDBL(0x6E)) // Move int reg to a xmm reg. reg1=xmm reg, reg2=int reg INST3( mov_xmm2i, "movd" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, PCKDBL(0x7E)) // Move xmm reg to an int reg. reg1=xmm reg, reg2=int reg +INST3( pmovmskb, "pmovmskb" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, PCKDBL(0xD7)) // Move the MSB bits of all bytes in a xmm reg to an int reg INST3( movq, "movq" , 0, IUM_WR, 0, 0, PCKDBL(0xD6), BAD_CODE, SSEFLT(0x7E)) INST3( movsdsse2, "movsd" , 0, IUM_WR, 0, 0, SSEDBL(0x11), BAD_CODE, SSEDBL(0x10)) @@ -317,6 +318,8 @@ INST3( insertps, "insertps" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SS INST3( pcmpeqq, "pcmpeqq" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE38(0x29)) // Packed compare 64-bit integers for equality INST3( pcmpgtq, "pcmpgtq" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE38(0x37)) // Packed compare 64-bit integers for equality INST3( pmulld, "pmulld" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE38(0x40)) // Packed multiply 32 bit unsigned integers and store lower 32 bits of each result +INST3( ptest, "ptest" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE38(0x17)) // Packed logical compare +INST3( phaddd, "phaddd" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE38(0x02)) // Packed horizontal add INST3(LAST_SSE4_INSTRUCTION, "LAST_SSE4_INSTRUCTION", 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, BAD_CODE) INST3(FIRST_AVX_INSTRUCTION, "FIRST_AVX_INSTRUCTION", 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, BAD_CODE) @@ -367,25 +370,25 @@ INST2(sar_N , "sar" , 0, IUM_RW, 0, 1, 0x0038C0, 0x0038C0) INST1(r_movsb, "rep movsb" , 0, IUM_RD, 0, 0, 0x00A4F3) INST1(r_movsd, "rep movsd" , 0, IUM_RD, 0, 0, 0x00A5F3) -#ifndef LEGACY_BACKEND +#if !defined(LEGACY_BACKEND) && defined(_TARGET_AMD64_) INST1(r_movsq, "rep movsq" , 0, IUM_RD, 0, 0, 0xF3A548) -#endif // !LEGACY_BACKEND +#endif // !LEGACY_BACKEND || !defined(_TARGET_AMD64_) INST1(movsb , "movsb" , 0, IUM_RD, 0, 0, 0x0000A4) INST1(movsd , "movsd" , 0, IUM_RD, 0, 0, 0x0000A5) -#ifndef LEGACY_BACKEND +#if !defined(LEGACY_BACKEND) && defined(_TARGET_AMD64_) INST1(movsq, "movsq" , 0, IUM_RD, 0, 0, 0x00A548) -#endif // !LEGACY_BACKEND +#endif // !LEGACY_BACKEND || !defined(_TARGET_AMD64_) INST1(r_stosb, "rep stosb" , 0, IUM_RD, 0, 0, 0x00AAF3) INST1(r_stosd, "rep stosd" , 0, IUM_RD, 0, 0, 0x00ABF3) -#ifndef LEGACY_BACKEND +#if !defined(LEGACY_BACKEND) && defined(_TARGET_AMD64_) INST1(r_stosq, "rep stosq" , 0, IUM_RD, 0, 0, 0xF3AB48) -#endif // !LEGACY_BACKEND +#endif // !LEGACY_BACKEND || !defined(_TARGET_AMD64_) INST1(stosb, "stosb" , 0, IUM_RD, 0, 0, 0x0000AA) INST1(stosd, "stosd" , 0, IUM_RD, 0, 0, 0x0000AB) -#ifndef LEGACY_BACKEND +#if !defined(LEGACY_BACKEND) && defined(_TARGET_AMD64_) INST1(stosq, "stosq" , 0, IUM_RD, 0, 0, 0x00AB48) -#endif // !LEGACY_BACKEND +#endif // !LEGACY_BACKEND || !defined(_TARGET_AMD64_) INST1(int3 , "int3" , 0, IUM_RD, 0, 0, 0x0000CC) INST1(nop , "nop" , 0, IUM_RD, 0, 0, 0x000090) diff --git a/src/jit/jit.h b/src/jit/jit.h index 7bf5cd4..220294f 100644 --- a/src/jit/jit.h +++ b/src/jit/jit.h @@ -28,6 +28,7 @@ #ifdef _MSC_VER // These don't seem useful, so turning them off is no big deal +#pragma warning(disable : 4065) // "switch statement contains 'default' but no 'case' labels" (happens due to #ifdefs) #pragma warning(disable : 4510) // can't generate default constructor #pragma warning(disable : 4511) // can't generate copy constructor #pragma warning(disable : 4512) // can't generate assignment constructor @@ -209,6 +210,7 @@ #include "corhdr.h" #include "corjit.h" +#include "jitee.h" #define __OPERATOR_NEW_INLINE 1 // indicate that I will define these #define __PLACEMENT_NEW_INLINE // don't bring in the global placement new, it is easy to make a mistake @@ -259,6 +261,15 @@ struct CLRConfig #define FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY(x) #endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) +#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) || (defined(_TARGET_X86_) && !defined(LEGACY_BACKEND)) +#define FEATURE_PUT_STRUCT_ARG_STK 1 +#define PUT_STRUCT_ARG_STK_ONLY_ARG(x) , x +#define PUT_STRUCT_ARG_STK_ONLY(x) x +#else // !(defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)|| (defined(_TARGET_X86_) && !defined(LEGACY_BACKEND))) +#define PUT_STRUCT_ARG_STK_ONLY_ARG(x) +#define PUT_STRUCT_ARG_STK_ONLY(x) +#endif // !(defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)|| (defined(_TARGET_X86_) && !defined(LEGACY_BACKEND))) + #if defined(UNIX_AMD64_ABI) #define UNIX_AMD64_ABI_ONLY_ARG(x) , x #define UNIX_AMD64_ABI_ONLY(x) x @@ -377,17 +388,6 @@ typedef ptrdiff_t ssize_t; /*****************************************************************************/ -// Debugging support is ON by default. Can be turned OFF by -// adding /DDEBUGGING_SUPPORT=0 on the command line. - -#ifndef DEBUGGING_SUPPORT -#define DEBUGGING_SUPPORT -#elif !DEBUGGING_SUPPORT -#undef DEBUGGING_SUPPORT -#endif - -/*****************************************************************************/ - // Late disassembly is OFF by default. Can be turned ON by // adding /DLATE_DISASM=1 on the command line. // Always OFF in the non-debug version @@ -465,6 +465,8 @@ typedef ptrdiff_t ssize_t; #define MEASURE_NODE_SIZE 0 // Collect stats about GenTree node allocations. #define MEASURE_PTRTAB_SIZE 0 // Collect stats about GC pointer table allocations. #define EMITTER_STATS 0 // Collect stats on the emitter. +#define NODEBASH_STATS 0 // Collect stats on changed gtOper values in GenTree's. +#define COUNT_AST_OPERS 0 // Display use counts for GenTree operators. #define VERBOSE_SIZES 0 // Always display GC info sizes. If set, DISPLAY_SIZES must also be set. #define VERBOSE_VERIFY 0 // Dump additional information when verifying code. Useful to debug verification bugs. @@ -472,9 +474,30 @@ typedef ptrdiff_t ssize_t; #ifdef DEBUG #define MEASURE_MEM_ALLOC 1 // Collect memory allocation stats. #define LOOP_HOIST_STATS 1 // Collect loop hoisting stats. +#define TRACK_LSRA_STATS 1 // Collect LSRA stats #else #define MEASURE_MEM_ALLOC 0 // You can set this to 1 to get memory stats in retail, as well #define LOOP_HOIST_STATS 0 // You can set this to 1 to get loop hoist stats in retail, as well +#define TRACK_LSRA_STATS 0 // You can set this to 1 to get LSRA stats in retail, as well +#endif + +// Timing calls to clr.dll is only available under certain conditions. +#ifndef FEATURE_JIT_METHOD_PERF +#define MEASURE_CLRAPI_CALLS 0 // Can't time these calls without METHOD_PERF. +#endif +#ifdef DEBUG +#define MEASURE_CLRAPI_CALLS 0 // No point in measuring DEBUG code. +#endif +#if !defined(_HOST_X86_) && !defined(_HOST_AMD64_) +#define MEASURE_CLRAPI_CALLS 0 // Cycle counters only hooked up on x86/x64. +#endif +#if !defined(_MSC_VER) && !defined(__clang__) +#define MEASURE_CLRAPI_CALLS 0 // Only know how to do this with VC and Clang. +#endif + +// If none of the above set the flag to 0, it's available. +#ifndef MEASURE_CLRAPI_CALLS +#define MEASURE_CLRAPI_CALLS 0 // Set to 1 to measure time in ICorJitInfo calls. #endif /*****************************************************************************/ @@ -686,7 +709,7 @@ inline size_t unsigned_abs(ssize_t x) /*****************************************************************************/ -#if CALL_ARG_STATS || COUNT_BASIC_BLOCKS || COUNT_LOOPS || EMITTER_STATS || MEASURE_NODE_SIZE +#if CALL_ARG_STATS || COUNT_BASIC_BLOCKS || COUNT_LOOPS || EMITTER_STATS || MEASURE_NODE_SIZE || MEASURE_MEM_ALLOC class Histogram { @@ -807,7 +830,7 @@ extern int jitNativeCode(CORINFO_METHOD_HANDLE methodHnd, CORINFO_METHOD_INFO* methodInfo, void** methodCodePtr, ULONG* methodCodeSize, - CORJIT_FLAGS* compileFlags, + JitFlags* compileFlags, void* inlineInfoPtr); #ifdef _HOST_64BIT_ diff --git a/src/jit/jit.settings.targets b/src/jit/jit.settings.targets index 9dbc225..6c0474a 100644 --- a/src/jit/jit.settings.targets +++ b/src/jit/jit.settings.targets @@ -86,10 +86,11 @@ - + + diff --git a/src/jit/jitconfig.h b/src/jit/jitconfig.h index d5b4e30..9186e12 100644 --- a/src/jit/jitconfig.h +++ b/src/jit/jitconfig.h @@ -5,6 +5,8 @@ #ifndef _JITCONFIG_H_ #define _JITCONFIG_H_ +#include "switches.h" + struct CORINFO_SIG_INFO; class ICorJitHost; diff --git a/src/jit/jitconfigvalues.h b/src/jit/jitconfigvalues.h index 6579817..39a2505 100644 --- a/src/jit/jitconfigvalues.h +++ b/src/jit/jitconfigvalues.h @@ -17,10 +17,10 @@ CONFIG_INTEGER(DebugBreakOnVerificationFailure, W("DebugBreakOnVerificationFailu // verification failure CONFIG_INTEGER(DiffableDasm, W("JitDiffableDasm"), 0) // Make the disassembly diff-able CONFIG_INTEGER(DisplayLoopHoistStats, W("JitLoopHoistStats"), 0) // Display JIT loop hoisting statistics -CONFIG_INTEGER(DisplayMemStats, W("JitMemStats"), 0) // Display JIT memory usage statistics -CONFIG_INTEGER(DumpJittedMethods, W("DumpJittedMethods"), 0) // Prints all jitted methods to the console -CONFIG_INTEGER(EnablePCRelAddr, W("JitEnablePCRelAddr"), 1) // Whether absolute addr be encoded as PC-rel offset by - // RyuJIT where possible +CONFIG_INTEGER(DisplayLsraStats, W("JitLsraStats"), 0) // Display JIT Linear Scan Register Allocator statistics +CONFIG_INTEGER(DumpJittedMethods, W("DumpJittedMethods"), 0) // Prints all jitted methods to the console +CONFIG_INTEGER(EnablePCRelAddr, W("JitEnablePCRelAddr"), 1) // Whether absolute addr be encoded as PC-rel offset by + // RyuJIT where possible CONFIG_INTEGER(InterpreterFallback, W("InterpreterFallback"), 0) // Fallback to the interpreter when the JIT compiler // fails CONFIG_INTEGER(JitAssertOnMaxRAPasses, W("JitAssertOnMaxRAPasses"), 0) @@ -154,10 +154,12 @@ CONFIG_METHODSET(JitNoProcedureSplittingEH, W("JitNoProcedureSplittingEH")) // D // exception handling CONFIG_METHODSET(JitStressOnly, W("JitStressOnly")) // Internal Jit stress mode: stress only the specified method(s) CONFIG_METHODSET(JitUnwindDump, W("JitUnwindDump")) // Dump the unwind codes for the method -CONFIG_METHODSET(NgenDisasm, W("NgenDisasm")) // Same as JitDisasm, but for ngen -CONFIG_METHODSET(NgenDump, W("NgenDump")) // Same as JitDump, but for ngen -CONFIG_METHODSET(NgenDumpIR, W("NgenDumpIR")) // Same as JitDumpIR, but for ngen -CONFIG_METHODSET(NgenEHDump, W("NgenEHDump")) // Dump the EH table for the method, as reported to the VM +CONFIG_METHODSET(JitOptRepeat, W("JitOptRepeat")) // Runs optimizer multiple times on the method +CONFIG_INTEGER(JitOptRepeatCount, W("JitOptRepeatCount"), 2) // Number of times to repeat opts when repeating +CONFIG_METHODSET(NgenDisasm, W("NgenDisasm")) // Same as JitDisasm, but for ngen +CONFIG_METHODSET(NgenDump, W("NgenDump")) // Same as JitDump, but for ngen +CONFIG_METHODSET(NgenDumpIR, W("NgenDumpIR")) // Same as JitDumpIR, but for ngen +CONFIG_METHODSET(NgenEHDump, W("NgenEHDump")) // Dump the EH table for the method, as reported to the VM CONFIG_METHODSET(NgenGCDump, W("NgenGCDump")) CONFIG_METHODSET(NgenUnwindDump, W("NgenUnwindDump")) // Dump the unwind codes for the method CONFIG_STRING(JitDumpFg, W("JitDumpFg")) // Dumps Xml/Dot Flowgraph for specified method @@ -186,6 +188,10 @@ CONFIG_STRING(NgenDumpIRFormat, W("NgenDumpIRFormat")) // Same as JitD CONFIG_STRING(NgenDumpIRPhase, W("NgenDumpIRPhase")) // Same as JitDumpIRPhase, but for ngen #endif // defined(DEBUG) +#ifdef FEATURE_ENABLE_NO_RANGE_CHECKS +CONFIG_INTEGER(JitNoRangeChks, W("JitNoRngChks"), 0) // If 1, don't generate range checks +#endif + // AltJitAssertOnNYI should be 0 on targets where JIT is under developement or bring up stage, so as to facilitate // fallback to main JIT on hitting a NYI. #if defined(_TARGET_ARM64_) || defined(_TARGET_X86_) @@ -194,11 +200,17 @@ CONFIG_INTEGER(AltJitAssertOnNYI, W("AltJitAssertOnNYI"), 0) // Controls the Alt CONFIG_INTEGER(AltJitAssertOnNYI, W("AltJitAssertOnNYI"), 1) // Controls the AltJit behavior of NYI stuff #endif // defined(_TARGET_ARM64_) || defined(_TARGET_X86_) +#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) +CONFIG_INTEGER(EnableSSE3_4, W("EnableSSE3_4"), 1) // Enable SSE3, SSSE3, SSE 4.1 and 4.2 instruction set as default +#endif + #if defined(_TARGET_AMD64_) -CONFIG_INTEGER(EnableAVX, W("EnableAVX"), 1) // Enable AVX instruction set for wide operations as default -#else // !defined(_TARGET_AMD64_) +CONFIG_INTEGER(EnableAVX, W("EnableAVX"), 1) // Enable AVX instruction set for wide operations as default. +// When both AVX and SSE3_4 are set, we will use the most capable instruction set available +// which will prefer AVX over SSE3/4. +#else // !defined(_TARGET_AMD64_) CONFIG_INTEGER(EnableAVX, W("EnableAVX"), 0) // Enable AVX instruction set for wide operations as default -#endif // defined(_TARGET_AMD64_) +#endif // defined(_TARGET_AMD64_) #if !defined(DEBUG) && !defined(_DEBUG) CONFIG_INTEGER(JitEnableNoWayAssert, W("JitEnableNoWayAssert"), 0) @@ -206,9 +218,17 @@ CONFIG_INTEGER(JitEnableNoWayAssert, W("JitEnableNoWayAssert"), 0) CONFIG_INTEGER(JitEnableNoWayAssert, W("JitEnableNoWayAssert"), 1) #endif // !defined(DEBUG) && !defined(_DEBUG) +// The following should be wrapped inside "#if MEASURE_MEM_ALLOC / #endif", but +// some files include this one without bringing in the definitions from "jit.h" +// so we don't always know what the "true" value of that flag should be. For now +// we take the easy way out and always include the flag, even in release builds +// (normally MEASURE_MEM_ALLOC is off for release builds but if it's toggled on +// for release in "jit.h" the flag would be missing for some includers). +// TODO-Cleanup: need to make 'MEASURE_MEM_ALLOC' well-defined here at all times. +CONFIG_INTEGER(DisplayMemStats, W("JitMemStats"), 0) // Display JIT memory usage statistics + CONFIG_INTEGER(JitAggressiveInlining, W("JitAggressiveInlining"), 0) // Aggressive inlining of all methods -CONFIG_INTEGER(JitELTHookEnabled, W("JitELTHookEnabled"), 0) // On ARM, setting this will emit Enter/Leave/TailCall - // callbacks +CONFIG_INTEGER(JitELTHookEnabled, W("JitELTHookEnabled"), 0) // If 1, emit Enter/Leave/TailCall callbacks CONFIG_INTEGER(JitInlineSIMDMultiplier, W("JitInlineSIMDMultiplier"), 3) #if defined(FEATURE_ENABLE_NO_RANGE_CHECKS) @@ -242,6 +262,8 @@ CONFIG_INTEGER(JitInlineLimit, W("JitInlineLimit"), -1) CONFIG_INTEGER(JitInlinePolicyDiscretionary, W("JitInlinePolicyDiscretionary"), 0) CONFIG_INTEGER(JitInlinePolicyFull, W("JitInlinePolicyFull"), 0) CONFIG_INTEGER(JitInlinePolicySize, W("JitInlinePolicySize"), 0) +CONFIG_INTEGER(JitInlinePolicyRandom, W("JitInlinePolicyRandom"), 0) // nozero enables; value is the external random + // seed CONFIG_INTEGER(JitInlinePolicyReplay, W("JitInlinePolicyReplay"), 0) CONFIG_STRING(JitNoInlineRange, W("JitNoInlineRange")) CONFIG_STRING(JitInlineReplayFile, W("JitInlineReplayFile")) @@ -250,6 +272,8 @@ CONFIG_STRING(JitInlineReplayFile, W("JitInlineReplayFile")) CONFIG_INTEGER(JitInlinePolicyLegacy, W("JitInlinePolicyLegacy"), 0) CONFIG_INTEGER(JitInlinePolicyModel, W("JitInlinePolicyModel"), 0) +CONFIG_INTEGER(JitEECallTimingInfo, W("JitEECallTimingInfo"), 0) + #undef CONFIG_INTEGER #undef CONFIG_STRING #undef CONFIG_METHODSET diff --git a/src/jit/jitee.h b/src/jit/jitee.h new file mode 100644 index 0000000..f9bd83f --- /dev/null +++ b/src/jit/jitee.h @@ -0,0 +1,264 @@ +// 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. + +// This class wraps the CORJIT_FLAGS type in the JIT-EE interface (in corjit.h) such that the JIT can +// build with either the old flags (COR_JIT_EE_VERSION <= 460) or the new flags (COR_JIT_EE_VERSION > 460). +// It actually is exactly the same as the new definition, and must be kept up-to-date with the new definition. +// When built against an old JIT-EE interface, the old flags are converted into this structure. +class JitFlags +{ +public: + // clang-format off + enum JitFlag + { + JIT_FLAG_SPEED_OPT = 0, + JIT_FLAG_SIZE_OPT = 1, + JIT_FLAG_DEBUG_CODE = 2, // generate "debuggable" code (no code-mangling optimizations) + JIT_FLAG_DEBUG_EnC = 3, // We are in Edit-n-Continue mode + JIT_FLAG_DEBUG_INFO = 4, // generate line and local-var info + JIT_FLAG_MIN_OPT = 5, // disable all jit optimizations (not necesarily debuggable code) + JIT_FLAG_GCPOLL_CALLS = 6, // Emit calls to JIT_POLLGC for thread suspension. + JIT_FLAG_MCJIT_BACKGROUND = 7, // Calling from multicore JIT background thread, do not call JitComplete + + #if defined(_TARGET_X86_) + + JIT_FLAG_PINVOKE_RESTORE_ESP = 8, // Restore ESP after returning from inlined PInvoke + JIT_FLAG_TARGET_P4 = 9, + JIT_FLAG_USE_FCOMI = 10, // Generated code may use fcomi(p) instruction + JIT_FLAG_USE_CMOV = 11, // Generated code may use cmov instruction + JIT_FLAG_USE_SSE2 = 12, // Generated code may use SSE-2 instructions + + #else // !defined(_TARGET_X86_) + + JIT_FLAG_UNUSED1 = 8, + JIT_FLAG_UNUSED2 = 9, + JIT_FLAG_UNUSED3 = 10, + JIT_FLAG_UNUSED4 = 11, + JIT_FLAG_UNUSED5 = 12, + + #endif // !defined(_TARGET_X86_) + + #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) + + JIT_FLAG_USE_SSE3_4 = 13, + JIT_FLAG_USE_AVX = 14, + JIT_FLAG_USE_AVX2 = 15, + JIT_FLAG_USE_AVX_512 = 16, + JIT_FLAG_FEATURE_SIMD = 17, + + #else // !defined(_TARGET_X86_) && !defined(_TARGET_AMD64_) + + JIT_FLAG_UNUSED6 = 13, + JIT_FLAG_UNUSED7 = 14, + JIT_FLAG_UNUSED8 = 15, + JIT_FLAG_UNUSED9 = 16, + JIT_FLAG_UNUSED10 = 17, + + #endif // !defined(_TARGET_X86_) && !defined(_TARGET_AMD64_) + + JIT_FLAG_MAKEFINALCODE = 18, // Use the final code generator, i.e., not the interpreter. + JIT_FLAG_READYTORUN = 19, // Use version-resilient code generation + JIT_FLAG_PROF_ENTERLEAVE = 20, // Instrument prologues/epilogues + JIT_FLAG_PROF_REJIT_NOPS = 21, // Insert NOPs to ensure code is re-jitable + JIT_FLAG_PROF_NO_PINVOKE_INLINE = 22, // Disables PInvoke inlining + JIT_FLAG_SKIP_VERIFICATION = 23, // (lazy) skip verification - determined without doing a full resolve. See comment below + JIT_FLAG_PREJIT = 24, // jit or prejit is the execution engine. + JIT_FLAG_RELOC = 25, // Generate relocatable code + JIT_FLAG_IMPORT_ONLY = 26, // Only import the function + JIT_FLAG_IL_STUB = 27, // method is an IL stub + JIT_FLAG_PROCSPLIT = 28, // JIT should separate code into hot and cold sections + JIT_FLAG_BBINSTR = 29, // Collect basic block profile information + JIT_FLAG_BBOPT = 30, // Optimize method based on profile information + JIT_FLAG_FRAMED = 31, // All methods have an EBP frame + JIT_FLAG_ALIGN_LOOPS = 32, // add NOPs before loops to align them at 16 byte boundaries + JIT_FLAG_PUBLISH_SECRET_PARAM = 33, // JIT must place stub secret param into local 0. (used by IL stubs) + JIT_FLAG_GCPOLL_INLINE = 34, // JIT must inline calls to GCPoll when possible + JIT_FLAG_SAMPLING_JIT_BACKGROUND = 35, // JIT is being invoked as a result of stack sampling for hot methods in the background + JIT_FLAG_USE_PINVOKE_HELPERS = 36, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions + JIT_FLAG_REVERSE_PINVOKE = 37, // The JIT should insert REVERSE_PINVOKE_{ENTER,EXIT} helpers into method prolog/epilog + JIT_FLAG_DESKTOP_QUIRKS = 38, // The JIT should generate desktop-quirk-compatible code + }; + // clang-format on + + JitFlags() : m_jitFlags(0) + { + // empty + } + + // Convenience constructor to set exactly one flags. + JitFlags(JitFlag flag) : m_jitFlags(0) + { + Set(flag); + } + + void Reset() + { + m_jitFlags = 0; + } + + void Set(JitFlag flag) + { + m_jitFlags |= 1ULL << (unsigned __int64)flag; + } + + void Clear(JitFlag flag) + { + m_jitFlags &= ~(1ULL << (unsigned __int64)flag); + } + + bool IsSet(JitFlag flag) const + { + return (m_jitFlags & (1ULL << (unsigned __int64)flag)) != 0; + } + + void Add(const JitFlags& other) + { + m_jitFlags |= other.m_jitFlags; + } + + void Remove(const JitFlags& other) + { + m_jitFlags &= ~other.m_jitFlags; + } + + bool IsEmpty() const + { + return m_jitFlags == 0; + } + +#if COR_JIT_EE_VERSION <= 460 + + void SetFromOldFlags(unsigned corJitFlags, unsigned corJitFlags2) + { + Reset(); + +#define CONVERT_OLD_FLAG(oldf, newf) \ + if ((corJitFlags & (oldf)) != 0) \ + this->Set(JitFlags::newf); +#define CONVERT_OLD_FLAG2(oldf, newf) \ + if ((corJitFlags2 & (oldf)) != 0) \ + this->Set(JitFlags::newf); + + CONVERT_OLD_FLAG(CORJIT_FLG_SPEED_OPT, JIT_FLAG_SPEED_OPT) + CONVERT_OLD_FLAG(CORJIT_FLG_SIZE_OPT, JIT_FLAG_SIZE_OPT) + CONVERT_OLD_FLAG(CORJIT_FLG_DEBUG_CODE, JIT_FLAG_DEBUG_CODE) + CONVERT_OLD_FLAG(CORJIT_FLG_DEBUG_EnC, JIT_FLAG_DEBUG_EnC) + CONVERT_OLD_FLAG(CORJIT_FLG_DEBUG_INFO, JIT_FLAG_DEBUG_INFO) + CONVERT_OLD_FLAG(CORJIT_FLG_MIN_OPT, JIT_FLAG_MIN_OPT) + CONVERT_OLD_FLAG(CORJIT_FLG_GCPOLL_CALLS, JIT_FLAG_GCPOLL_CALLS) + CONVERT_OLD_FLAG(CORJIT_FLG_MCJIT_BACKGROUND, JIT_FLAG_MCJIT_BACKGROUND) + +#if defined(_TARGET_X86_) + + CONVERT_OLD_FLAG(CORJIT_FLG_PINVOKE_RESTORE_ESP, JIT_FLAG_PINVOKE_RESTORE_ESP) + CONVERT_OLD_FLAG(CORJIT_FLG_TARGET_P4, JIT_FLAG_TARGET_P4) + CONVERT_OLD_FLAG(CORJIT_FLG_USE_FCOMI, JIT_FLAG_USE_FCOMI) + CONVERT_OLD_FLAG(CORJIT_FLG_USE_CMOV, JIT_FLAG_USE_CMOV) + CONVERT_OLD_FLAG(CORJIT_FLG_USE_SSE2, JIT_FLAG_USE_SSE2) + +#elif defined(_TARGET_AMD64_) + + CONVERT_OLD_FLAG(CORJIT_FLG_USE_SSE3_4, JIT_FLAG_USE_SSE3_4) + CONVERT_OLD_FLAG(CORJIT_FLG_USE_AVX, JIT_FLAG_USE_AVX) + CONVERT_OLD_FLAG(CORJIT_FLG_USE_AVX2, JIT_FLAG_USE_AVX2) + CONVERT_OLD_FLAG(CORJIT_FLG_USE_AVX_512, JIT_FLAG_USE_AVX_512) + CONVERT_OLD_FLAG(CORJIT_FLG_FEATURE_SIMD, JIT_FLAG_FEATURE_SIMD) + +#endif // !defined(_TARGET_X86_) && !defined(_TARGET_AMD64_) + + CONVERT_OLD_FLAG(CORJIT_FLG_MAKEFINALCODE, JIT_FLAG_MAKEFINALCODE) + CONVERT_OLD_FLAG(CORJIT_FLG_READYTORUN, JIT_FLAG_READYTORUN) + CONVERT_OLD_FLAG(CORJIT_FLG_PROF_ENTERLEAVE, JIT_FLAG_PROF_ENTERLEAVE) + CONVERT_OLD_FLAG(CORJIT_FLG_PROF_REJIT_NOPS, JIT_FLAG_PROF_REJIT_NOPS) + CONVERT_OLD_FLAG(CORJIT_FLG_PROF_NO_PINVOKE_INLINE, JIT_FLAG_PROF_NO_PINVOKE_INLINE) + CONVERT_OLD_FLAG(CORJIT_FLG_SKIP_VERIFICATION, JIT_FLAG_SKIP_VERIFICATION) + CONVERT_OLD_FLAG(CORJIT_FLG_PREJIT, JIT_FLAG_PREJIT) + CONVERT_OLD_FLAG(CORJIT_FLG_RELOC, JIT_FLAG_RELOC) + CONVERT_OLD_FLAG(CORJIT_FLG_IMPORT_ONLY, JIT_FLAG_IMPORT_ONLY) + CONVERT_OLD_FLAG(CORJIT_FLG_IL_STUB, JIT_FLAG_IL_STUB) + CONVERT_OLD_FLAG(CORJIT_FLG_PROCSPLIT, JIT_FLAG_PROCSPLIT) + CONVERT_OLD_FLAG(CORJIT_FLG_BBINSTR, JIT_FLAG_BBINSTR) + CONVERT_OLD_FLAG(CORJIT_FLG_BBOPT, JIT_FLAG_BBOPT) + CONVERT_OLD_FLAG(CORJIT_FLG_FRAMED, JIT_FLAG_FRAMED) + CONVERT_OLD_FLAG(CORJIT_FLG_ALIGN_LOOPS, JIT_FLAG_ALIGN_LOOPS) + CONVERT_OLD_FLAG(CORJIT_FLG_PUBLISH_SECRET_PARAM, JIT_FLAG_PUBLISH_SECRET_PARAM) + CONVERT_OLD_FLAG(CORJIT_FLG_GCPOLL_INLINE, JIT_FLAG_GCPOLL_INLINE) + + CONVERT_OLD_FLAG2(CORJIT_FLG2_SAMPLING_JIT_BACKGROUND, JIT_FLAG_SAMPLING_JIT_BACKGROUND) + +#undef CONVERT_OLD_FLAG +#undef CONVERT_OLD_FLAG2 + } + +#else // COR_JIT_EE_VERSION > 460 + + void SetFromFlags(CORJIT_FLAGS flags) + { + // We don't want to have to check every one, so we assume it is exactly the same values as the JitFlag + // values defined in this type. + m_jitFlags = flags.GetFlagsRaw(); + + C_ASSERT(sizeof(m_jitFlags) == sizeof(CORJIT_FLAGS)); + +#define FLAGS_EQUAL(a, b) C_ASSERT((unsigned)(a) == (unsigned)(b)) + + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_SPEED_OPT, JIT_FLAG_SPEED_OPT); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_SIZE_OPT, JIT_FLAG_SIZE_OPT); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE, JIT_FLAG_DEBUG_CODE); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_EnC, JIT_FLAG_DEBUG_EnC); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO, JIT_FLAG_DEBUG_INFO); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_MIN_OPT, JIT_FLAG_MIN_OPT); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_GCPOLL_CALLS, JIT_FLAG_GCPOLL_CALLS); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_MCJIT_BACKGROUND, JIT_FLAG_MCJIT_BACKGROUND); + +#if defined(_TARGET_X86_) + + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_PINVOKE_RESTORE_ESP, JIT_FLAG_PINVOKE_RESTORE_ESP); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_TARGET_P4, JIT_FLAG_TARGET_P4); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_FCOMI, JIT_FLAG_USE_FCOMI); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_CMOV, JIT_FLAG_USE_CMOV); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_SSE2, JIT_FLAG_USE_SSE2); + +#endif + +#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) + + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_SSE3_4, JIT_FLAG_USE_SSE3_4); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_AVX, JIT_FLAG_USE_AVX); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_AVX2, JIT_FLAG_USE_AVX2); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_AVX_512, JIT_FLAG_USE_AVX_512); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_FEATURE_SIMD, JIT_FLAG_FEATURE_SIMD); + +#endif + + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_MAKEFINALCODE, JIT_FLAG_MAKEFINALCODE); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_READYTORUN, JIT_FLAG_READYTORUN); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE, JIT_FLAG_PROF_ENTERLEAVE); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_PROF_REJIT_NOPS, JIT_FLAG_PROF_REJIT_NOPS); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_PROF_NO_PINVOKE_INLINE, JIT_FLAG_PROF_NO_PINVOKE_INLINE); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION, JIT_FLAG_SKIP_VERIFICATION); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_PREJIT, JIT_FLAG_PREJIT); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_RELOC, JIT_FLAG_RELOC); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY, JIT_FLAG_IMPORT_ONLY); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB, JIT_FLAG_IL_STUB); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT, JIT_FLAG_PROCSPLIT); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR, JIT_FLAG_BBINSTR); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_BBOPT, JIT_FLAG_BBOPT); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_FRAMED, JIT_FLAG_FRAMED); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_ALIGN_LOOPS, JIT_FLAG_ALIGN_LOOPS); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_PUBLISH_SECRET_PARAM, JIT_FLAG_PUBLISH_SECRET_PARAM); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_GCPOLL_INLINE, JIT_FLAG_GCPOLL_INLINE); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_SAMPLING_JIT_BACKGROUND, JIT_FLAG_SAMPLING_JIT_BACKGROUND); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_PINVOKE_HELPERS, JIT_FLAG_USE_PINVOKE_HELPERS); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_REVERSE_PINVOKE, JIT_FLAG_REVERSE_PINVOKE); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_DESKTOP_QUIRKS, JIT_FLAG_DESKTOP_QUIRKS); + +#undef FLAGS_EQUAL + } + +#endif // COR_JIT_EE_VERSION > 460 + +private: + unsigned __int64 m_jitFlags; +}; diff --git a/src/jit/jiteh.cpp b/src/jit/jiteh.cpp index b20c2f8..4b3ceae 100644 --- a/src/jit/jiteh.cpp +++ b/src/jit/jiteh.cpp @@ -2979,7 +2979,7 @@ void Compiler::dispOutgoingEHClause(unsigned num, const CORINFO_EH_CLAUSE& claus // Note: the flags field is kind of weird. It should be compared for equality // to determine the type of clause, even though it looks like a bitfield. In // Particular, CORINFO_EH_CLAUSE_NONE is zero, so you can "&" to check it. - // You do need to mask off the bits, though, because COR_ILEXCEPTION_CLAUSE_DUPLICATED + // You do need to mask off the bits, though, because CORINFO_EH_CLAUSE_DUPLICATE // is and'ed in. const DWORD CORINFO_EH_CLAUSE_TYPE_MASK = 0x7; switch (clause.Flags & CORINFO_EH_CLAUSE_TYPE_MASK) @@ -3013,15 +3013,19 @@ void Compiler::dispOutgoingEHClause(unsigned num, const CORINFO_EH_CLAUSE& claus } if ((clause.TryOffset == clause.TryLength) && (clause.TryOffset == clause.HandlerOffset) && - ((clause.Flags & (COR_ILEXCEPTION_CLAUSE_DUPLICATED | COR_ILEXCEPTION_CLAUSE_FINALLY)) == - (COR_ILEXCEPTION_CLAUSE_DUPLICATED | COR_ILEXCEPTION_CLAUSE_FINALLY))) + ((clause.Flags & (CORINFO_EH_CLAUSE_DUPLICATE | CORINFO_EH_CLAUSE_FINALLY)) == + (CORINFO_EH_CLAUSE_DUPLICATE | CORINFO_EH_CLAUSE_FINALLY))) { printf(" cloned finally"); } - else if (clause.Flags & COR_ILEXCEPTION_CLAUSE_DUPLICATED) + else if (clause.Flags & CORINFO_EH_CLAUSE_DUPLICATE) { printf(" duplicated"); } + else if (clause.Flags & CORINFO_EH_CLAUSE_SAMETRY) + { + printf(" same try"); + } printf("\n"); } diff --git a/src/jit/jitgcinfo.h b/src/jit/jitgcinfo.h index b93ac33..3f8d8af 100644 --- a/src/jit/jitgcinfo.h +++ b/src/jit/jitgcinfo.h @@ -380,6 +380,9 @@ private: public: void gcUpdateForRegVarMove(regMaskTP srcMask, regMaskTP dstMask, LclVarDsc* varDsc); #endif // !LEGACY_BACKEND + +private: + ReturnKind getReturnKind(); }; inline unsigned char encodeUnsigned(BYTE* dest, unsigned value) diff --git a/src/jit/lclvars.cpp b/src/jit/lclvars.cpp index 369c963..ea9c573 100644 --- a/src/jit/lclvars.cpp +++ b/src/jit/lclvars.cpp @@ -385,8 +385,9 @@ void Compiler::lvaInitThisPtr(InitVarDscInfo* varDscInfo) if (simdBaseType != TYP_UNKNOWN) { assert(varTypeIsSIMD(type)); - varDsc->lvSIMDType = true; - varDsc->lvBaseType = simdBaseType; + varDsc->lvSIMDType = true; + varDsc->lvBaseType = simdBaseType; + varDsc->lvExactSize = genTypeSize(type); } } #endif // FEATURE_SIMD @@ -1448,12 +1449,16 @@ void Compiler::lvaCanPromoteStructType(CORINFO_CLASS_HANDLE typeHnd, #if 1 // TODO-Cleanup: Consider removing this entire #if block in the future - // This method has two callers. The one in Importer.cpp passes sortFields == false - // and the other passes sortFields == true. - // This is a workaround that leave the inlining behavior the same and before while still - // performing extra struct promotions when compiling the method. - // +// This method has two callers. The one in Importer.cpp passes sortFields == false +// and the other passes sortFields == true. +// This is a workaround that leaves the inlining behavior the same as before while still +// performing extra struct promotions when compiling the method. +// +// The x86 legacy back-end can't handle the more general RyuJIT struct promotion (notably structs +// with holes), in genPushArgList(), so in that case always check for custom layout. +#if FEATURE_FIXED_OUT_ARGS || !defined(LEGACY_BACKEND) if (!sortFields) // the condition "!sortFields" really means "we are inlining" +#endif { treatAsOverlapping = StructHasCustomLayout(typeFlags); } @@ -1736,7 +1741,7 @@ void Compiler::lvaPromoteStructVar(unsigned lclNum, lvaStructPromotionInfo* Stru } } -#if !defined(_TARGET_64BIT_) +#if !defined(LEGACY_BACKEND) && !defined(_TARGET_64BIT_) //------------------------------------------------------------------------ // lvaPromoteLongVars: "Struct promote" all register candidate longs as if they are structs of two ints. // @@ -1752,29 +1757,18 @@ void Compiler::lvaPromoteLongVars() { return; } + // The lvaTable might grow as we grab temps. Make a local copy here. unsigned startLvaCount = lvaCount; for (unsigned lclNum = 0; lclNum < startLvaCount; lclNum++) { LclVarDsc* varDsc = &lvaTable[lclNum]; if (!varTypeIsLong(varDsc) || varDsc->lvDoNotEnregister || varDsc->lvIsMultiRegArgOrRet() || - (varDsc->lvRefCnt == 0)) + (varDsc->lvRefCnt == 0) || varDsc->lvIsStructField || (fgNoStructPromotion && varDsc->lvIsParam)) { continue; } - // Will this work ??? - // We can't have nested promoted structs. - if (varDsc->lvIsStructField) - { - if (lvaGetPromotionType(varDsc->lvParentLcl) != PROMOTION_TYPE_INDEPENDENT) - { - continue; - } - varDsc->lvIsStructField = false; - varDsc->lvTracked = false; - } - varDsc->lvFieldCnt = 2; varDsc->lvFieldLclStart = lvaCount; varDsc->lvPromoted = true; @@ -1823,7 +1817,7 @@ void Compiler::lvaPromoteLongVars() } #endif // DEBUG } -#endif // !_TARGET_64BIT_ +#endif // !defined(LEGACY_BACKEND) && !defined(_TARGET_64BIT_) /***************************************************************************** * Given a fldOffset in a promoted struct var, return the index of the local @@ -1904,6 +1898,10 @@ void Compiler::lvaSetVarDoNotEnregister(unsigned varNum DEBUGARG(DoNotEnregister JITDUMP("it is a struct\n"); assert(varTypeIsStruct(varDsc)); break; + case DNER_IsStructArg: + JITDUMP("it is a struct arg\n"); + assert(varTypeIsStruct(varDsc)); + break; case DNER_BlockOp: JITDUMP("written in a block op\n"); varDsc->lvLclBlockOpAddr = 1; @@ -2038,7 +2036,7 @@ void Compiler::lvaSetStruct(unsigned varNum, CORINFO_CLASS_HANDLE typeHnd, bool } #ifndef _TARGET_64BIT_ - bool fDoubleAlignHint = FALSE; + BOOL fDoubleAlignHint = FALSE; #ifdef _TARGET_X86_ fDoubleAlignHint = TRUE; #endif @@ -2697,6 +2695,10 @@ void Compiler::lvaSortByRefCount() lvaTrackedCount = 0; lvaTrackedCountInSizeTUnits = 0; +#ifdef DEBUG + VarSetOps::AssignNoCopy(this, lvaTrackedVars, VarSetOps::MakeEmpty(this)); +#endif + if (lvaCount == 0) { return; @@ -3386,26 +3388,30 @@ void Compiler::lvaMarkLocalVars() #endif // !FEATURE_EH_FUNCLETS -#if FEATURE_EH_FUNCLETS - if (ehNeedsPSPSym()) + // PSPSym and LocAllocSPvar are not used by the CoreRT ABI + if (!IsTargetAbi(CORINFO_CORERT_ABI)) { - lvaPSPSym = lvaGrabTempWithImplicitUse(false DEBUGARG("PSPSym")); - LclVarDsc* lclPSPSym = &lvaTable[lvaPSPSym]; - lclPSPSym->lvType = TYP_I_IMPL; - } +#if FEATURE_EH_FUNCLETS + if (ehNeedsPSPSym()) + { + lvaPSPSym = lvaGrabTempWithImplicitUse(false DEBUGARG("PSPSym")); + LclVarDsc* lclPSPSym = &lvaTable[lvaPSPSym]; + lclPSPSym->lvType = TYP_I_IMPL; + } #endif // FEATURE_EH_FUNCLETS - if (compLocallocUsed) - { - lvaLocAllocSPvar = lvaGrabTempWithImplicitUse(false DEBUGARG("LocAllocSPvar")); - LclVarDsc* locAllocSPvar = &lvaTable[lvaLocAllocSPvar]; - locAllocSPvar->lvType = TYP_I_IMPL; + // TODO: LocAllocSPvar should be only required by the implicit frame layout expected by the VM on x86. + // It should be removed on other platforms once we check there are no other implicit dependencies. + if (compLocallocUsed) + { + lvaLocAllocSPvar = lvaGrabTempWithImplicitUse(false DEBUGARG("LocAllocSPvar")); + LclVarDsc* locAllocSPvar = &lvaTable[lvaLocAllocSPvar]; + locAllocSPvar->lvType = TYP_I_IMPL; + } } BasicBlock* block; -#if defined(DEBUGGING_SUPPORT) || defined(DEBUG) - #ifndef DEBUG // Assign slot numbers to all variables. // If compiler generated local variables, slot numbers will be @@ -3428,8 +3434,6 @@ void Compiler::lvaMarkLocalVars() } } -#endif // defined(DEBUGGING_SUPPORT) || defined(DEBUG) - /* Mark all local variable references */ lvaRefCountingStarted = true; @@ -4062,12 +4066,11 @@ void Compiler::lvaFixVirtualFrameOffsets() LclVarDsc* varDsc; #if FEATURE_EH_FUNCLETS && defined(_TARGET_AMD64_) - if (ehNeedsPSPSym()) + if (lvaPSPSym != BAD_VAR_NUM) { // We need to fix the offset of the PSPSym so there is no padding between it and the outgoing argument space. // Without this code, lvaAlignFrame might have put the padding lower than the PSPSym, which would be between // the PSPSym and the outgoing argument space. - assert(lvaPSPSym != BAD_VAR_NUM); varDsc = &lvaTable[lvaPSPSym]; assert(varDsc->lvFramePointerBased); // We always access it RBP-relative. assert(!varDsc->lvMustInit); // It is never "must init". @@ -4453,7 +4456,9 @@ int Compiler::lvaAssignVirtualFrameOffsetToArg(unsigned lclNum, noway_assert(argSize); if (Target::g_tgtArgOrder == Target::ARG_ORDER_L2R) + { argOffs -= argSize; + } unsigned fieldVarNum = BAD_VAR_NUM; @@ -4543,7 +4548,9 @@ int Compiler::lvaAssignVirtualFrameOffsetToArg(unsigned lclNum, } if (Target::g_tgtArgOrder == Target::ARG_ORDER_R2L && !varDsc->lvIsRegArg) + { argOffs += argSize; + } return argOffs; } @@ -4973,13 +4980,12 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals() #endif //_TARGET_AMD64_ #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARMARCH_) - if (ehNeedsPSPSym()) + if (lvaPSPSym != BAD_VAR_NUM) { // On ARM/ARM64, if we need a PSPSym, allocate it first, before anything else, including // padding (so we can avoid computing the same padding in the funclet // frame). Note that there is no special padding requirement for the PSPSym. noway_assert(codeGen->isFramePointerUsed()); // We need an explicit frame pointer - assert(lvaPSPSym != BAD_VAR_NUM); // We should have created the PSPSym variable stkOffs = lvaAllocLocalAndSetVirtualOffset(lvaPSPSym, TARGET_POINTER_SIZE, stkOffs); } #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARMARCH_) @@ -5033,7 +5039,7 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals() stkOffs = lvaAllocLocalAndSetVirtualOffset(lvaSecurityObject, TARGET_POINTER_SIZE, stkOffs); } - if (compLocallocUsed) + if (lvaLocAllocSPvar != BAD_VAR_NUM) { #ifdef JIT32_GCENCODER noway_assert(codeGen->isFramePointerUsed()); // else offsets of locals of frameless methods will be incorrect @@ -5278,7 +5284,9 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals() // a local variable which will need stack frame space. // if (!varDsc->lvIsRegArg) + { continue; + } #ifdef _TARGET_ARM64_ if (info.compIsVarArgs) @@ -5477,13 +5485,12 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals() } #if FEATURE_EH_FUNCLETS && defined(_TARGET_AMD64_) - if (ehNeedsPSPSym()) + if (lvaPSPSym != BAD_VAR_NUM) { // On AMD64, if we need a PSPSym, allocate it last, immediately above the outgoing argument // space. Any padding will be higher on the stack than this // (including the padding added by lvaAlignFrame()). noway_assert(codeGen->isFramePointerUsed()); // We need an explicit frame pointer - assert(lvaPSPSym != BAD_VAR_NUM); // We should have created the PSPSym variable stkOffs = lvaAllocLocalAndSetVirtualOffset(lvaPSPSym, TARGET_POINTER_SIZE, stkOffs); } #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_AMD64_) diff --git a/src/.gitmirror b/src/jit/legacyjit/.gitmirror similarity index 100% rename from src/.gitmirror rename to src/jit/legacyjit/.gitmirror diff --git a/src/jit/legacyjit/CMakeLists.txt b/src/jit/legacyjit/CMakeLists.txt new file mode 100644 index 0000000..73a4600 --- /dev/null +++ b/src/jit/legacyjit/CMakeLists.txt @@ -0,0 +1,62 @@ +project(legacyjit) + +add_definitions(-DLEGACY_BACKEND) +add_definitions(-DALT_JIT) +add_definitions(-DFEATURE_NO_HOST) +add_definitions(-DSELF_NO_HOST) +add_definitions(-DFEATURE_READYTORUN_COMPILER) +remove_definitions(-DFEATURE_MERGE_JIT_AND_ENGINE) + +# No SIMD in legacy back-end. +remove_definitions(-DFEATURE_SIMD) +remove_definitions(-DFEATURE_AVX_SUPPORT) + +if(WIN32) + add_definitions(-DFX_VER_INTERNALNAME_STR=legacyjit.dll) +endif(WIN32) + +add_library_clr(legacyjit + SHARED + ${SHARED_LIB_SOURCES} +) + +add_dependencies(legacyjit jit_exports) + +set_property(TARGET legacyjit APPEND_STRING PROPERTY LINK_FLAGS ${JIT_EXPORTS_LINKER_OPTION}) +set_property(TARGET legacyjit APPEND_STRING PROPERTY LINK_DEPENDS ${JIT_EXPORTS_FILE}) + +set(RYUJIT_LINK_LIBRARIES + utilcodestaticnohost + gcinfo +) + +if(CLR_CMAKE_PLATFORM_UNIX) + list(APPEND RYUJIT_LINK_LIBRARIES + mscorrc_debug + coreclrpal + palrt + ) +else() + list(APPEND RYUJIT_LINK_LIBRARIES + ${STATIC_MT_CRT_LIB} + ${STATIC_MT_VCRT_LIB} + kernel32.lib + advapi32.lib + ole32.lib + oleaut32.lib + uuid.lib + user32.lib + version.lib + shlwapi.lib + bcrypt.lib + crypt32.lib + RuntimeObject.lib + ) +endif(CLR_CMAKE_PLATFORM_UNIX) + +target_link_libraries(legacyjit + ${RYUJIT_LINK_LIBRARIES} +) + +# add the install targets +install_clr(legacyjit) diff --git a/src/jit/lir.cpp b/src/jit/lir.cpp index 94206de..35dd181 100644 --- a/src/jit/lir.cpp +++ b/src/jit/lir.cpp @@ -190,12 +190,13 @@ void LIR::Use::ReplaceWith(Compiler* compiler, GenTree* replacement) assert(IsDummyUse() || m_range->Contains(m_user)); assert(m_range->Contains(replacement)); - GenTree* replacedNode = *m_edge; - - *m_edge = replacement; - if (!IsDummyUse() && m_user->IsCall()) + if (!IsDummyUse()) + { + m_user->ReplaceOperand(m_edge, replacement); + } + else { - compiler->fgFixupArgTabEntryPtr(m_user, replacedNode, replacement); + *m_edge = replacement; } } @@ -256,7 +257,7 @@ unsigned LIR::Use::ReplaceWithLclVar(Compiler* compiler, unsigned blockWeight, u assert(m_range->Contains(m_user)); assert(m_range->Contains(*m_edge)); - GenTree* node = *m_edge; + GenTree* const node = *m_edge; if (lclNum == BAD_VAR_NUM) { @@ -267,9 +268,11 @@ unsigned LIR::Use::ReplaceWithLclVar(Compiler* compiler, unsigned blockWeight, u compiler->lvaTable[lclNum].incRefCnts(blockWeight, compiler); compiler->lvaTable[lclNum].incRefCnts(blockWeight, compiler); - GenTreeLclVar* store = compiler->gtNewTempAssign(lclNum, node)->AsLclVar(); + GenTreeLclVar* const store = compiler->gtNewTempAssign(lclNum, node)->AsLclVar(); + assert(store != nullptr); + assert(store->gtOp1 == node); - GenTree* load = + GenTree* const load = new (compiler, GT_LCL_VAR) GenTreeLclVar(store->TypeGet(), store->AsLclVarCommon()->GetLclNum(), BAD_IL_OFFSET); m_range->InsertAfter(node, store, load); @@ -678,7 +681,7 @@ void LIR::Range::FinishInsertBefore(GenTree* insertionPoint, GenTree* first, Gen assert(m_lastNode != nullptr); assert(m_lastNode->gtNext == nullptr); m_lastNode->gtNext = first; - first->gtPrev = m_lastNode; + first->gtPrev = m_lastNode; } m_lastNode = last; } @@ -866,7 +869,7 @@ void LIR::Range::FinishInsertAfter(GenTree* insertionPoint, GenTree* first, GenT assert(m_firstNode != nullptr); assert(m_firstNode->gtPrev == nullptr); m_firstNode->gtPrev = last; - last->gtNext = m_firstNode; + last->gtNext = m_firstNode; } m_firstNode = first; } @@ -1157,7 +1160,6 @@ void LIR::Range::Delete(Compiler* compiler, BasicBlock* block, ReadOnlyRange&& r Delete(compiler, block, range.m_firstNode, range.m_lastNode); } - //------------------------------------------------------------------------ // LIR::Range::TryGetUse: Try to find the use for a given node. // @@ -1616,22 +1618,21 @@ void LIR::InsertBeforeTerminator(BasicBlock* block, LIR::Range&& range) #if DEBUG switch (block->bbJumpKind) { - case BBJ_COND: - assert(insertionPoint->OperGet() == GT_JTRUE); - break; + case BBJ_COND: + assert(insertionPoint->OperIsConditionalJump()); + break; - case BBJ_SWITCH: - assert((insertionPoint->OperGet() == GT_SWITCH) || (insertionPoint->OperGet() == GT_SWITCH_TABLE)); - break; + case BBJ_SWITCH: + assert((insertionPoint->OperGet() == GT_SWITCH) || (insertionPoint->OperGet() == GT_SWITCH_TABLE)); + break; - case BBJ_RETURN: - assert((insertionPoint->OperGet() == GT_RETURN) || - (insertionPoint->OperGet() == GT_JMP) || - (insertionPoint->OperGet() == GT_CALL)); - break; + case BBJ_RETURN: + assert((insertionPoint->OperGet() == GT_RETURN) || (insertionPoint->OperGet() == GT_JMP) || + (insertionPoint->OperGet() == GT_CALL)); + break; - default: - unreached(); + default: + unreached(); } #endif } diff --git a/src/jit/liveness.cpp b/src/jit/liveness.cpp index 19d3263..423d72b 100644 --- a/src/jit/liveness.cpp +++ b/src/jit/liveness.cpp @@ -76,7 +76,6 @@ void Compiler::fgMarkUseDef(GenTreeLclVarCommon* tree, GenTree* asgdLclVar) if ((lhsLclNum == lclNum) && ((tree->gtFlags & GTF_VAR_DEF) == 0) && (tree != asgdLclVar)) { /* bingo - we have an x = f(x) case */ - noway_assert(lvaTable[lhsLclNum].lvType != TYP_STRUCT); asgdLclVar->gtFlags |= GTF_VAR_USEDEF; rhsUSEDEF = true; } @@ -699,10 +698,6 @@ void Compiler::fgPerBlockLocalVarLiveness() } } -/*****************************************************************************/ -#ifdef DEBUGGING_SUPPORT -/*****************************************************************************/ - // Helper functions to mark variables live over their entire scope void Compiler::fgBeginScopeLife(VARSET_TP* inScope, VarScopeDsc* var) @@ -1113,7 +1108,7 @@ void Compiler::fgExtendDbgLifetimes() // Create initialization node if (!block->IsLIR()) { - GenTree* varNode = gtNewLclvNode(varNum, type); + GenTree* varNode = gtNewLclvNode(varNum, type); GenTree* initNode = gtNewAssignNode(varNode, zero); // Create a statement for the initializer, sequence it, and append it to the current BB. @@ -1124,7 +1119,8 @@ void Compiler::fgExtendDbgLifetimes() } else { - GenTree* store = new (this, GT_STORE_LCL_VAR) GenTreeLclVar(GT_STORE_LCL_VAR, type, varNum, BAD_IL_OFFSET); + GenTree* store = + new (this, GT_STORE_LCL_VAR) GenTreeLclVar(GT_STORE_LCL_VAR, type, varNum, BAD_IL_OFFSET); store->gtOp.gtOp1 = zero; store->gtFlags |= (GTF_VAR_DEF | GTF_ASG); @@ -1133,7 +1129,7 @@ void Compiler::fgExtendDbgLifetimes() #if !defined(_TARGET_64BIT_) && !defined(LEGACY_BACKEND) DecomposeLongs::DecomposeRange(this, blockWeight, initRange); -#endif +#endif // !defined(_TARGET_64BIT_) && !defined(LEGACY_BACKEND) // Naively inserting the initializer at the end of the block may add code after the block's // terminator, in which case the inserted code will never be executed (and the IR for the @@ -1184,10 +1180,6 @@ void Compiler::fgExtendDbgLifetimes() #endif // DEBUG } -/*****************************************************************************/ -#endif // DEBUGGING_SUPPORT -/*****************************************************************************/ - VARSET_VALRET_TP Compiler::fgGetHandlerLiveVars(BasicBlock* block) { noway_assert(block); @@ -1905,9 +1897,7 @@ VARSET_VALRET_TP Compiler::fgComputeLife(VARSET_VALARG_TP lifeArg, VARSET_TP VARSET_INIT(this, life, lifeArg); // lifeArg is const ref; copy to allow modification. VARSET_TP VARSET_INIT(this, keepAliveVars, volatileVars); -#ifdef DEBUGGING_SUPPORT VarSetOps::UnionD(this, keepAliveVars, compCurBB->bbScope); // Don't kill vars in scope -#endif noway_assert(VarSetOps::Equal(this, VarSetOps::Intersection(this, keepAliveVars, life), keepAliveVars)); noway_assert(compCurStmt->gtOper == GT_STMT); @@ -1955,9 +1945,7 @@ VARSET_VALRET_TP Compiler::fgComputeLifeLIR(VARSET_VALARG_TP lifeArg, BasicBlock VARSET_TP VARSET_INIT(this, life, lifeArg); // lifeArg is const ref; copy to allow modification. VARSET_TP VARSET_INIT(this, keepAliveVars, volatileVars); -#ifdef DEBUGGING_SUPPORT VarSetOps::UnionD(this, keepAliveVars, block->bbScope); // Don't kill vars in scope -#endif noway_assert(VarSetOps::Equal(this, VarSetOps::Intersection(this, keepAliveVars, life), keepAliveVars)); @@ -1980,9 +1968,9 @@ VARSET_VALRET_TP Compiler::fgComputeLifeLIR(VARSET_VALARG_TP lifeArg, BasicBlock else if (node->OperIsNonPhiLocal() || node->OperIsLocalAddr()) { bool isDeadStore = fgComputeLifeLocal(life, keepAliveVars, node, node); - if (isDeadStore) + if (isDeadStore && fgTryRemoveDeadLIRStore(blockRange, node, &next)) { - fgTryRemoveDeadLIRStore(blockRange, node, &next); + fgStmtRemoved = true; } } } @@ -2018,9 +2006,8 @@ VARSET_VALRET_TP Compiler::fgComputeLife(VARSET_VALARG_TP lifeArg, GenTreePtr gtColon = NULL; VARSET_TP VARSET_INIT(this, keepAliveVars, volatileVars); -#ifdef DEBUGGING_SUPPORT VarSetOps::UnionD(this, keepAliveVars, compCurBB->bbScope); /* Dont kill vars in scope */ -#endif + noway_assert(VarSetOps::Equal(this, VarSetOps::Intersection(this, keepAliveVars, life), keepAliveVars)); noway_assert(compCurStmt->gtOper == GT_STMT); noway_assert(endNode || (startNode == compCurStmt->gtStmt.gtStmtExpr)); @@ -2548,10 +2535,10 @@ bool Compiler::fgRemoveDeadStore( switch (asgNode->gtOper) { case GT_ASG_ADD: - asgNode->gtOper = GT_ADD; + asgNode->SetOperRaw(GT_ADD); break; case GT_ASG_SUB: - asgNode->gtOper = GT_SUB; + asgNode->SetOperRaw(GT_SUB); break; default: // Only add and sub allowed, we don't have ASG_MUL and ASG_DIV for ints, and @@ -2854,10 +2841,6 @@ void Compiler::fgInterBlockLocalVarLiveness() fgLiveVarAnalysis(); -//------------------------------------------------------------------------- - -#ifdef DEBUGGING_SUPPORT - /* For debuggable code, we mark vars as live over their entire * reported scope, so that it will be visible over the entire scope */ @@ -2867,8 +2850,6 @@ void Compiler::fgInterBlockLocalVarLiveness() fgExtendDbgLifetimes(); } -#endif // DEBUGGING_SUPPORT - /*------------------------------------------------------------------------- * Variables involved in exception-handlers and finally blocks need * to be specially marked diff --git a/src/jit/loopcloning.cpp b/src/jit/loopcloning.cpp index 8ce015e..a1ba142 100644 --- a/src/jit/loopcloning.cpp +++ b/src/jit/loopcloning.cpp @@ -698,7 +698,7 @@ void LoopCloneContext::CondToStmtInBlock(Compiler* comp, comp->fgInsertStmtAtEnd(block, stmt); // Remorph. - comp->fgMorphBlockStmt(block, stmt DEBUGARG("Loop cloning condition")); + comp->fgMorphBlockStmt(block, stmt->AsStmt() DEBUGARG("Loop cloning condition")); } //-------------------------------------------------------------------------------------------------- diff --git a/src/jit/lower.cpp b/src/jit/lower.cpp index 09eb914..a6e50b3 100644 --- a/src/jit/lower.cpp +++ b/src/jit/lower.cpp @@ -135,6 +135,15 @@ GenTree* Lowering::LowerNode(GenTree* node) LowerCall(node); break; + case GT_LT: + case GT_LE: + case GT_GT: + case GT_GE: + case GT_EQ: + case GT_NE: + LowerCompare(node); + break; + case GT_JMP: LowerJmpMethod(node); break; @@ -169,13 +178,33 @@ GenTree* Lowering::LowerNode(GenTree* node) // produces a TYP_SIMD16 result node->gtType = TYP_SIMD16; } + +#ifdef _TARGET_XARCH_ + if ((node->AsSIMD()->gtSIMDIntrinsicID == SIMDIntrinsicGetItem) && (node->gtGetOp1()->OperGet() == GT_IND)) + { + // If SIMD vector is already in memory, we force its + // addr to be evaluated into a reg. This would allow + // us to generate [regBase] or [regBase+offset] or + // [regBase+sizeOf(SIMD vector baseType)*regIndex] + // to access the required SIMD vector element directly + // from memory. + // + // TODO-CQ-XARCH: If addr of GT_IND is GT_LEA, we + // might be able update GT_LEA to fold the regIndex + // or offset in some cases. Instead with this + // approach we always evaluate GT_LEA into a reg. + // Ideally, we should be able to lower GetItem intrinsic + // into GT_IND(newAddr) where newAddr combines + // the addr of SIMD vector with the given index. + node->gtOp.gtOp1->gtFlags |= GTF_IND_REQ_ADDR_IN_REG; + } +#endif break; case GT_LCL_VAR: case GT_STORE_LCL_VAR: if (node->TypeGet() == TYP_SIMD12) { -#ifdef _TARGET_64BIT_ // Assumption 1: // RyuJit backend depends on the assumption that on 64-Bit targets Vector3 size is rounded off // to TARGET_POINTER_SIZE and hence Vector3 locals on stack can be treated as TYP_SIMD16 for @@ -198,10 +227,29 @@ GenTree* Lowering::LowerNode(GenTree* node) // Vector3 return values are returned two return registers and Caller assembles them into a // single xmm reg. Hence RyuJIT explicitly generates code to clears upper 4-bytes of Vector3 // type args in prolog and Vector3 type return value of a call + // + // RyuJIT x86 Windows: all non-param Vector3 local vars are allocated as 16 bytes. Vector3 arguments + // are pushed as 12 bytes. For return values, a 16-byte local is allocated and the address passed + // as a return buffer pointer. The callee doesn't write the high 4 bytes, and we don't need to clear + // it either. + + unsigned varNum = node->AsLclVarCommon()->GetLclNum(); + LclVarDsc* varDsc = &comp->lvaTable[varNum]; + +#if defined(_TARGET_64BIT_) + assert(varDsc->lvSize() == 16); node->gtType = TYP_SIMD16; -#else - NYI("Lowering of TYP_SIMD12 locals"); -#endif // _TARGET_64BIT_ +#else // !_TARGET_64BIT_ + if (varDsc->lvSize() == 16) + { + node->gtType = TYP_SIMD16; + } + else + { + // The following assert is guaranteed by lvSize(). + assert(varDsc->lvIsParam); + } +#endif // !_TARGET_64BIT_ } #endif // FEATURE_SIMD __fallthrough; @@ -215,7 +263,7 @@ GenTree* Lowering::LowerNode(GenTree* node) #if FEATURE_MULTIREG_RET GenTree* src = node->gtGetOp1(); assert((src->OperGet() == GT_CALL) && src->AsCall()->HasMultiRegRetVal()); -#else // !FEATURE_MULTIREG_RET +#else // !FEATURE_MULTIREG_RET assert(!"Unexpected struct local store in Lowering"); #endif // !FEATURE_MULTIREG_RET } @@ -680,7 +728,7 @@ void Lowering::ReplaceArgWithPutArgOrCopy(GenTree** argSlot, GenTree* putArgOrCo // Arguments: // call - the call whose arg is being rewritten. // arg - the arg being rewritten. -// info - the ArgTabEntry information for the argument. +// info - the fgArgTabEntry information for the argument. // type - the type of the argument. // // Return Value: @@ -692,11 +740,11 @@ void Lowering::ReplaceArgWithPutArgOrCopy(GenTree** argSlot, GenTree* putArgOrCo // // Notes: // For System V systems with native struct passing (i.e. FEATURE_UNIX_AMD64_STRUCT_PASSING defined) -// this method allocates a single GT_PUTARG_REG for 1 eightbyte structs and a GT_LIST of two GT_PUTARG_REGs +// this method allocates a single GT_PUTARG_REG for 1 eightbyte structs and a GT_FIELD_LIST of two GT_PUTARG_REGs // for two eightbyte structs. // // For STK passed structs the method generates GT_PUTARG_STK tree. For System V systems with native struct passing -// (i.e. FEATURE_UNIX_AMD64_STRUCT_PASSING defined) this method also sets the GP pointers count and the pointers +// (i.e. FEATURE_UNIX_AMD64_STRUCT_PASSING defined) this method also sets the GC pointers count and the pointers // layout object, so the codegen of the GT_PUTARG_STK could use this for optimizing copying to the stack by value. // (using block copy primitives for non GC pointers and a single TARGET_POINTER_SIZE copy with recording GC info.) // @@ -753,8 +801,8 @@ GenTreePtr Lowering::NewPutArg(GenTreeCall* call, GenTreePtr arg, fgArgTabEntryP // In this case a new tree is created that is GT_PUTARG_REG // with a op1 the original argument. // 2. The struct is contained in 2 eightbytes: - // in this case the arg comes as a GT_LIST of two GT_LCL_FLDs - the two eightbytes of the struct. - // The code creates a GT_PUTARG_REG node for each GT_LCL_FLD in the GT_LIST + // in this case the arg comes as a GT_FIELD_LIST of two GT_LCL_FLDs - the two eightbytes of the struct. + // The code creates a GT_PUTARG_REG node for each GT_LCL_FLD in the GT_FIELD_LIST // and splices it in the list with the corresponding original GT_LCL_FLD tree as op1. assert(info->structDesc.eightByteCount != 0); @@ -826,25 +874,25 @@ GenTreePtr Lowering::NewPutArg(GenTreeCall* call, GenTreePtr arg, fgArgTabEntryP // // clang-format on - assert(arg->OperGet() == GT_LIST); + assert(arg->OperGet() == GT_FIELD_LIST); - GenTreeArgList* argListPtr = arg->AsArgList(); - assert(argListPtr->IsAggregate()); + GenTreeFieldList* fieldListPtr = arg->AsFieldList(); + assert(fieldListPtr->IsFieldListHead()); - for (unsigned ctr = 0; argListPtr != nullptr; argListPtr = argListPtr->Rest(), ctr++) + for (unsigned ctr = 0; fieldListPtr != nullptr; fieldListPtr = fieldListPtr->Rest(), ctr++) { // Create a new GT_PUTARG_REG node with op1 the original GT_LCL_FLD. GenTreePtr newOper = comp->gtNewOperNode( GT_PUTARG_REG, comp->GetTypeFromClassificationAndSizes(info->structDesc.eightByteClassifications[ctr], info->structDesc.eightByteSizes[ctr]), - argListPtr->gtOp.gtOp1); + fieldListPtr->gtOp.gtOp1); - // Splice in the new GT_PUTARG_REG node in the GT_LIST - ReplaceArgWithPutArgOrCopy(&argListPtr->gtOp.gtOp1, newOper); + // Splice in the new GT_PUTARG_REG node in the GT_FIELD_LIST + ReplaceArgWithPutArgOrCopy(&fieldListPtr->gtOp.gtOp1, newOper); } - // Just return arg. The GT_LIST is not replaced. + // Just return arg. The GT_FIELD_LIST is not replaced. // Nothing more to do. return arg; } @@ -857,26 +905,26 @@ GenTreePtr Lowering::NewPutArg(GenTreeCall* call, GenTreePtr arg, fgArgTabEntryP else #else // not defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) #if FEATURE_MULTIREG_ARGS - if ((info->numRegs > 1) && (arg->OperGet() == GT_LIST)) + if ((info->numRegs > 1) && (arg->OperGet() == GT_FIELD_LIST)) { - assert(arg->OperGet() == GT_LIST); + assert(arg->OperGet() == GT_FIELD_LIST); - GenTreeArgList* argListPtr = arg->AsArgList(); - assert(argListPtr->IsAggregate()); + GenTreeFieldList* fieldListPtr = arg->AsFieldList(); + assert(fieldListPtr->IsFieldListHead()); - for (unsigned ctr = 0; argListPtr != nullptr; argListPtr = argListPtr->Rest(), ctr++) + for (unsigned ctr = 0; fieldListPtr != nullptr; fieldListPtr = fieldListPtr->Rest(), ctr++) { - GenTreePtr curOp = argListPtr->gtOp.gtOp1; + GenTreePtr curOp = fieldListPtr->gtOp.gtOp1; var_types curTyp = curOp->TypeGet(); // Create a new GT_PUTARG_REG node with op1 GenTreePtr newOper = comp->gtNewOperNode(GT_PUTARG_REG, curTyp, curOp); - // Splice in the new GT_PUTARG_REG node in the GT_LIST - ReplaceArgWithPutArgOrCopy(&argListPtr->gtOp.gtOp1, newOper); + // Splice in the new GT_PUTARG_REG node in the GT_FIELD_LIST + ReplaceArgWithPutArgOrCopy(&fieldListPtr->gtOp.gtOp1, newOper); } - // Just return arg. The GT_LIST is not replaced. + // Just return arg. The GT_FIELD_LIST is not replaced. // Nothing more to do. return arg; } @@ -893,23 +941,20 @@ GenTreePtr Lowering::NewPutArg(GenTreeCall* call, GenTreePtr arg, fgArgTabEntryP // This provides the info to put this argument in in-coming arg area slot // instead of in out-going arg area slot. - FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY(assert(info->isStruct == varTypeIsStruct(type))); // Make sure state is - // correct + PUT_STRUCT_ARG_STK_ONLY(assert(info->isStruct == varTypeIsStruct(type))); // Make sure state is + // correct #if FEATURE_FASTTAILCALL putArg = new (comp, GT_PUTARG_STK) - GenTreePutArgStk(GT_PUTARG_STK, type, arg, - info->slotNum FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(info->numSlots) - FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(info->isStruct), + GenTreePutArgStk(GT_PUTARG_STK, type, arg, info->slotNum PUT_STRUCT_ARG_STK_ONLY_ARG(info->numSlots), call->IsFastTailCall() DEBUGARG(call)); #else putArg = new (comp, GT_PUTARG_STK) GenTreePutArgStk(GT_PUTARG_STK, type, arg, - info->slotNum FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(info->numSlots) - FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(info->isStruct) DEBUGARG(call)); + info->slotNum PUT_STRUCT_ARG_STK_ONLY_ARG(info->numSlots) DEBUGARG(call)); #endif -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING +#ifdef FEATURE_PUT_STRUCT_ARG_STK // If the ArgTabEntry indicates that this arg is a struct // get and store the number of slots that are references. // This is later used in the codegen for PUT_ARG_STK implementation @@ -919,8 +964,6 @@ GenTreePtr Lowering::NewPutArg(GenTreeCall* call, GenTreePtr arg, fgArgTabEntryP // pair copying using XMM registers or rep mov instructions. if (info->isStruct) { - unsigned numRefs = 0; - BYTE* gcLayout = new (comp, CMK_Codegen) BYTE[info->numSlots]; // We use GT_OBJ for non-SIMD struct arguments. However, for // SIMD arguments the GT_OBJ has already been transformed. if (arg->gtOper != GT_OBJ) @@ -929,13 +972,14 @@ GenTreePtr Lowering::NewPutArg(GenTreeCall* call, GenTreePtr arg, fgArgTabEntryP } else { + unsigned numRefs = 0; + BYTE* gcLayout = new (comp, CMK_Codegen) BYTE[info->numSlots]; assert(!varTypeIsSIMD(arg)); numRefs = comp->info.compCompHnd->getClassGClayout(arg->gtObj.gtClass, gcLayout); + putArg->AsPutArgStk()->setGcPointers(numRefs, gcLayout); } - - putArg->AsPutArgStk()->setGcPointers(numRefs, gcLayout); } -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING +#endif // FEATURE_PUT_STRUCT_ARG_STK } if (arg->InReg()) @@ -1011,6 +1055,22 @@ void Lowering::LowerArg(GenTreeCall* call, GenTreePtr* ppArg) type = TYP_INT; } +#if defined(FEATURE_SIMD) && defined(_TARGET_X86_) + // Non-param TYP_SIMD12 local var nodes are massaged in Lower to TYP_SIMD16 to match their + // allocated size (see lvSize()). However, when passing the variables as arguments, and + // storing the variables to the outgoing argument area on the stack, we must use their + // actual TYP_SIMD12 type, so exactly 12 bytes is allocated and written. + if (type == TYP_SIMD16) + { + if ((arg->OperGet() == GT_LCL_VAR) || (arg->OperGet() == GT_STORE_LCL_VAR)) + { + unsigned varNum = arg->AsLclVarCommon()->GetLclNum(); + LclVarDsc* varDsc = &comp->lvaTable[varNum]; + type = varDsc->lvType; + } + } +#endif // defined(FEATURE_SIMD) && defined(_TARGET_X86_) + GenTreePtr putArg; // If we hit this we are probably double-lowering. @@ -1068,7 +1128,7 @@ void Lowering::LowerArg(GenTreeCall* call, GenTreePtr* ppArg) putArg = NewPutArg(call, arg, info, type); // In the case of register passable struct (in one or two registers) - // the NewPutArg returns a new node (GT_PUTARG_REG or a GT_LIST with two GT_PUTARG_REGs.) + // the NewPutArg returns a new node (GT_PUTARG_REG or a GT_FIELD_LIST with two GT_PUTARG_REGs.) // If an extra node is returned, splice it in the right place in the tree. if (arg != putArg) { @@ -1367,6 +1427,7 @@ void Lowering::CheckVSQuirkStackPaddingNeeded(GenTreeCall* call) // Inserts profiler hook, GT_PROF_HOOK for a tail call node. // +// AMD64: // We need to insert this after all nested calls, but before all the arguments to this call have been set up. // To do this, we look for the first GT_PUTARG_STK or GT_PUTARG_REG, and insert the hook immediately before // that. If there are no args, then it should be inserted before the call node. @@ -1391,16 +1452,30 @@ void Lowering::CheckVSQuirkStackPaddingNeeded(GenTreeCall* call) // In this case, the GT_PUTARG_REG src is a nested call. We need to put the instructions after that call // (as shown). We assume that of all the GT_PUTARG_*, only the first one can have a nested call. // +// X86: +// Insert the profiler hook immediately before the call. The profiler hook will preserve +// all argument registers (ECX, EDX), but nothing else. +// // Params: // callNode - tail call node -// insertionPoint - if caller has an insertion point; If null -// profiler hook is inserted before args are setup +// insertionPoint - if non-null, insert the profiler hook before this point. +// If null, insert the profiler hook before args are setup // but after all arg side effects are computed. +// void Lowering::InsertProfTailCallHook(GenTreeCall* call, GenTree* insertionPoint) { assert(call->IsTailCall()); assert(comp->compIsProfilerHookNeeded()); +#if defined(_TARGET_X86_) + + if (insertionPoint == nullptr) + { + insertionPoint = call; + } + +#else // !defined(_TARGET_X86_) + if (insertionPoint == nullptr) { GenTreePtr tmp = nullptr; @@ -1437,6 +1512,8 @@ void Lowering::InsertProfTailCallHook(GenTreeCall* call, GenTree* insertionPoint } } +#endif // !defined(_TARGET_X86_) + assert(insertionPoint != nullptr); GenTreePtr profHookNode = new (comp, GT_PROF_HOOK) GenTree(GT_PROF_HOOK, TYP_VOID); BlockRange().InsertBefore(insertionPoint, profHookNode); @@ -1705,7 +1782,10 @@ GenTree* Lowering::LowerTailCallViaHelper(GenTreeCall* call, GenTree* callTarget assert(!comp->opts.compNeedSecurityCheck); // tail call from methods that need security check assert(!call->IsUnmanaged()); // tail calls to unamanaged methods assert(!comp->compLocallocUsed); // tail call from methods that also do localloc - assert(!comp->getNeedsGSSecurityCookie()); // jit64 compat: tail calls from methods that need GS check + +#ifdef _TARGET_AMD64_ + assert(!comp->getNeedsGSSecurityCookie()); // jit64 compat: tail calls from methods that need GS check +#endif // _TARGET_AMD64_ // We expect to see a call that meets the following conditions assert(call->IsTailCallViaHelper()); @@ -1713,8 +1793,9 @@ GenTree* Lowering::LowerTailCallViaHelper(GenTreeCall* call, GenTree* callTarget // The TailCall helper call never returns to the caller and is not GC interruptible. // Therefore the block containing the tail call should be a GC safe point to avoid - // GC starvation. - assert(comp->compCurBB->bbFlags & BBF_GC_SAFE_POINT); + // GC starvation. It is legal for the block to be unmarked iff the entry block is a + // GC safe point, as the entry block trivially dominates every reachable block. + assert((comp->compCurBB->bbFlags & BBF_GC_SAFE_POINT) || (comp->fgFirstBB->bbFlags & BBF_GC_SAFE_POINT)); // If PInvokes are in-lined, we have to remember to execute PInvoke method epilog anywhere that // a method returns. This is a case of caller method has both PInvokes and tail calls. @@ -1839,16 +1920,268 @@ GenTree* Lowering::LowerTailCallViaHelper(GenTreeCall* call, GenTree* callTarget // Now add back tail call flags for identifying this node as tail call dispatched via helper. call->gtCallMoreFlags |= GTF_CALL_M_TAILCALL | GTF_CALL_M_TAILCALL_VIA_HELPER; +#ifdef PROFILING_SUPPORTED // Insert profiler tail call hook if needed. // Since we don't know the insertion point, pass null for second param. if (comp->compIsProfilerHookNeeded()) { InsertProfTailCallHook(call, nullptr); } +#endif // PROFILING_SUPPORTED + + assert(call->IsTailCallViaHelper()); return result; } +//------------------------------------------------------------------------ +// Lowering::LowerCompare: lowers a compare node. +// +// For 64-bit targets, this doesn't do much of anything: all comparisons +// that we support can be handled in code generation on such targets. +// +// For 32-bit targets, however, any comparison that feeds a `GT_JTRUE` +// node must be lowered such that the liveness of the operands to the +// comparison is properly visible to the rest of the backend. As such, +// a 64-bit comparison is lowered from something like this: +// +// ------------ BB02 [004..014) -> BB02 (cond), preds={BB02,BB01} succs={BB03,BB02} +// N001 ( 1, 1) [000006] ------------ t6 = lclVar int V02 loc0 u:5 $148 +// +// /--* t6 int +// N002 ( 2, 3) [000007] ---------U-- t7 = * cast long <- ulong <- uint $3c0 +// +// N003 ( 3, 10) [000009] ------------ t9 = lconst long 0x0000000000000003 $101 +// +// /--* t7 long +// +--* t9 long +// N004 ( 9, 17) [000010] N------N-U-- t10 = * < int $149 +// +// /--* t10 int +// N005 ( 11, 19) [000011] ------------ * jmpTrue void +// +// To something like this: +// +// ------------ BB02 [004..014) -> BB03 (cond), preds={BB06,BB07,BB01} succs={BB06,BB03} +// [000099] ------------ t99 = const int 0 +// +// [000101] ------------ t101 = const int 0 +// +// /--* t99 int +// +--* t101 int +// N004 ( 9, 17) [000010] N------N-U-- t10 = * > int $149 +// +// /--* t10 int +// N005 ( 11, 19) [000011] ------------ * jmpTrue void +// +// +// ------------ BB06 [???..???) -> BB02 (cond), preds={BB02} succs={BB07,BB02} +// [000105] -------N-U-- jcc void cond=< +// +// +// ------------ BB07 [???..???) -> BB02 (cond), preds={BB06} succs={BB03,BB02} +// N001 ( 1, 1) [000006] ------------ t6 = lclVar int V02 loc0 u:5 $148 +// +// N003 ( 3, 10) [000009] ------------ t9 = const int 3 +// +// /--* t6 int +// +--* t9 int +// [000106] N------N-U-- t106 = * < int +// +// /--* t106 int +// [000107] ------------ * jmpTrue void +// +// Which will eventually generate code similar to the following: +// +// 33DB xor ebx, ebx +// 85DB test ebx, ebx +// 7707 ja SHORT G_M50523_IG04 +// 72E7 jb SHORT G_M50523_IG03 +// 83F803 cmp eax, 3 +// 72E2 jb SHORT G_M50523_IG03 +// +void Lowering::LowerCompare(GenTree* cmp) +{ +#ifndef _TARGET_64BIT_ + if (cmp->gtGetOp1()->TypeGet() != TYP_LONG) + { + return; + } + + LIR::Use cmpUse; + + if (!BlockRange().TryGetUse(cmp, &cmpUse) || cmpUse.User()->OperGet() != GT_JTRUE) + { + return; + } + + GenTree* src1 = cmp->gtGetOp1(); + GenTree* src2 = cmp->gtGetOp2(); + unsigned weight = m_block->getBBWeight(comp); + + LIR::Use loSrc1(BlockRange(), &(src1->gtOp.gtOp1), src1); + LIR::Use loSrc2(BlockRange(), &(src2->gtOp.gtOp1), src2); + + if (loSrc1.Def()->OperGet() != GT_CNS_INT && loSrc1.Def()->OperGet() != GT_LCL_VAR) + { + loSrc1.ReplaceWithLclVar(comp, weight); + } + + if (loSrc2.Def()->OperGet() != GT_CNS_INT && loSrc2.Def()->OperGet() != GT_LCL_VAR) + { + loSrc2.ReplaceWithLclVar(comp, weight); + } + + BasicBlock* jumpDest = m_block->bbJumpDest; + BasicBlock* nextDest = m_block->bbNext; + BasicBlock* newBlock = comp->fgSplitBlockAtEnd(m_block); + + cmp->gtType = TYP_INT; + cmp->gtOp.gtOp1 = src1->gtOp.gtOp2; + cmp->gtOp.gtOp2 = src2->gtOp.gtOp2; + + if (cmp->OperGet() == GT_EQ || cmp->OperGet() == GT_NE) + { + // 64-bit equality comparisons (no matter the polarity) require two 32-bit comparisons: one for the upper 32 + // bits and one for the lower 32 bits. As such, we update the flow graph like so: + // + // Before: + // BB0: cond + // / \ + // false true + // | | + // BB1 BB2 + // + // After: + // BB0: cond(hi) + // / \ + // false true + // | | + // | BB3: cond(lo) + // | / \ + // | false true + // \ / | + // BB1 BB2 + // + + BlockRange().Remove(loSrc1.Def()); + BlockRange().Remove(loSrc2.Def()); + GenTree* loCmp = comp->gtNewOperNode(cmp->OperGet(), TYP_INT, loSrc1.Def(), loSrc2.Def()); + loCmp->gtFlags = cmp->gtFlags; + GenTree* loJtrue = comp->gtNewOperNode(GT_JTRUE, TYP_VOID, loCmp); + LIR::AsRange(newBlock).InsertAfter(nullptr, loSrc1.Def(), loSrc2.Def(), loCmp, loJtrue); + + m_block->bbJumpKind = BBJ_COND; + + if (cmp->OperGet() == GT_EQ) + { + cmp->gtOper = GT_NE; + m_block->bbJumpDest = nextDest; + nextDest->bbFlags |= BBF_JMP_TARGET; + comp->fgAddRefPred(nextDest, m_block); + } + else + { + m_block->bbJumpDest = jumpDest; + comp->fgAddRefPred(jumpDest, m_block); + } + + assert(newBlock->bbJumpKind == BBJ_COND); + assert(newBlock->bbJumpDest == jumpDest); + } + else + { + // 64-bit ordinal comparisons are more complicated: they require two comparisons for the upper 32 bits and one + // comparison for the lower 32 bits. We update the flowgraph as such: + // + // Before: + // BB0: cond + // / \ + // false true + // | | + // BB1 BB2 + // + // After: + // BB0: (!cond(hi) && !eq(hi)) + // / \ + // true false + // | | + // | BB3: (cond(hi) && !eq(hi)) + // | / \ + // | false true + // | | | + // | BB4: cond(lo) | + // | / \ | + // | false true | + // \ / \ / + // BB1 BB2 + // + // + // Note that the actual comparisons used to implement "(!cond(hi) && !eq(hi))" and "(cond(hi) && !eq(hi))" + // differ based on the original condition, and all consist of a single node. The switch statement below + // performs the necessary mapping. + // + + genTreeOps hiCmpOper; + genTreeOps loCmpOper; + + switch (cmp->OperGet()) + { + case GT_LT: + cmp->gtOper = GT_GT; + hiCmpOper = GT_LT; + loCmpOper = GT_LT; + break; + case GT_LE: + cmp->gtOper = GT_GT; + hiCmpOper = GT_LT; + loCmpOper = GT_LE; + break; + case GT_GT: + cmp->gtOper = GT_LT; + hiCmpOper = GT_GT; + loCmpOper = GT_GT; + break; + case GT_GE: + cmp->gtOper = GT_LT; + hiCmpOper = GT_GT; + loCmpOper = GT_GE; + break; + default: + unreached(); + } + + BasicBlock* newBlock2 = comp->fgSplitBlockAtEnd(newBlock); + + GenTree* hiJcc = new (comp, GT_JCC) GenTreeJumpCC(hiCmpOper); + hiJcc->gtFlags = cmp->gtFlags; + LIR::AsRange(newBlock).InsertAfter(nullptr, hiJcc); + + BlockRange().Remove(loSrc1.Def()); + BlockRange().Remove(loSrc2.Def()); + GenTree* loCmp = comp->gtNewOperNode(loCmpOper, TYP_INT, loSrc1.Def(), loSrc2.Def()); + loCmp->gtFlags = cmp->gtFlags | GTF_UNSIGNED; + GenTree* loJtrue = comp->gtNewOperNode(GT_JTRUE, TYP_VOID, loCmp); + LIR::AsRange(newBlock2).InsertAfter(nullptr, loSrc1.Def(), loSrc2.Def(), loCmp, loJtrue); + + m_block->bbJumpKind = BBJ_COND; + m_block->bbJumpDest = nextDest; + nextDest->bbFlags |= BBF_JMP_TARGET; + comp->fgAddRefPred(nextDest, m_block); + + newBlock->bbJumpKind = BBJ_COND; + newBlock->bbJumpDest = jumpDest; + comp->fgAddRefPred(jumpDest, newBlock); + + assert(newBlock2->bbJumpKind == BBJ_COND); + assert(newBlock2->bbJumpDest == jumpDest); + } + + BlockRange().Remove(src1); + BlockRange().Remove(src2); +#endif +} + // Lower "jmp " tail call to insert PInvoke method epilog if required. void Lowering::LowerJmpMethod(GenTree* jmp) { @@ -2334,8 +2667,12 @@ void Lowering::InsertPInvokeMethodProlog() DISPTREERANGE(firstBlockRange, storeFP); // -------------------------------------------------------- + // On 32-bit targets, CORINFO_HELP_INIT_PINVOKE_FRAME initializes the PInvoke frame and then pushes it onto + // the current thread's Frame stack. On 64-bit targets, it only initializes the PInvoke frame. + CLANG_FORMAT_COMMENT_ANCHOR; - if (comp->opts.eeFlags & CORJIT_FLG_IL_STUB) +#ifdef _TARGET_64BIT_ + if (comp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_IL_STUB)) { // Push a frame - if we are NOT in an IL stub, this is done right before the call // The init routine sets InlinedCallFrame's m_pNext, so we just set the thead's top-of-stack @@ -2343,6 +2680,7 @@ void Lowering::InsertPInvokeMethodProlog() firstBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, frameUpd)); DISPTREERANGE(firstBlockRange, frameUpd); } +#endif // _TARGET_64BIT_ } //------------------------------------------------------------------------ @@ -2405,9 +2743,14 @@ void Lowering::InsertPInvokeMethodEpilog(BasicBlock* returnBB DEBUGARG(GenTreePt GenTree* storeGCState = SetGCState(1); returnBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, storeGCState)); - if (comp->opts.eeFlags & CORJIT_FLG_IL_STUB) + // Pop the frame if necessary. This always happens in the epilog on 32-bit targets. For 64-bit targets, we only do + // this in the epilog for IL stubs; for non-IL stubs the frame is popped after every PInvoke call. + CLANG_FORMAT_COMMENT_ANCHOR; + +#ifdef _TARGET_64BIT_ + if (comp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_IL_STUB)) +#endif // _TARGET_64BIT_ { - // Pop the frame, in non-stubs we do this around each PInvoke call GenTree* frameUpd = CreateFrameLinkUpdate(PopFrame); returnBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, frameUpd)); } @@ -2454,6 +2797,7 @@ void Lowering::InsertPInvokeCallProlog(GenTreeCall* call) comp->fgMorphTree(helperCall); BlockRange().InsertBefore(insertBefore, LIR::SeqTree(comp, helperCall)); + LowerNode(helperCall); // helper call is inserted before current node and should be lowered here. return; } #endif @@ -2464,7 +2808,7 @@ void Lowering::InsertPInvokeCallProlog(GenTreeCall* call) // InlinedCallFrame.m_pCallSiteSP = SP // x86 only // InlinedCallFrame.m_pCallerReturnAddress = return address // Thread.gcState = 0 - // (non-stub) - update top Frame on TCB + // (non-stub) - update top Frame on TCB // 64-bit targets only // ---------------------------------------------------------------------------------- // Setup InlinedCallFrame.callSiteTarget (which is how the JIT refers to it). @@ -2474,11 +2818,19 @@ void Lowering::InsertPInvokeCallProlog(GenTreeCall* call) if (callType == CT_INDIRECT) { +#if !defined(_TARGET_64BIT_) + // On 32-bit targets, indirect calls need the size of the stack args in InlinedCallFrame.m_Datum. + const unsigned numStkArgBytes = call->fgArgInfo->GetNextSlotNum() * TARGET_POINTER_SIZE; + + src = comp->gtNewIconNode(numStkArgBytes, TYP_INT); +#else + // On 64-bit targets, indirect calls may need the stub parameter value in InlinedCallFrame.m_Datum. + // If the stub parameter value is not needed, m_Datum will be initialized by the VM. if (comp->info.compPublishStubParam) { - src = new (comp, GT_LCL_VAR) GenTreeLclVar(TYP_I_IMPL, comp->lvaStubArgumentVar, BAD_IL_OFFSET); + src = comp->gtNewLclvNode(comp->lvaStubArgumentVar, TYP_I_IMPL); } - // else { If we don't have secret parameter, m_Datum will be initialized by VM code } +#endif // !defined(_TARGET_64BIT_) } else { @@ -2542,7 +2894,12 @@ void Lowering::InsertPInvokeCallProlog(GenTreeCall* call) BlockRange().InsertBefore(insertBefore, LIR::SeqTree(comp, storeLab)); - if (!(comp->opts.eeFlags & CORJIT_FLG_IL_STUB)) + // Push the PInvoke frame if necessary. On 32-bit targets this only happens in the method prolog if a method + // contains PInvokes; on 64-bit targets this is necessary in non-stubs. + CLANG_FORMAT_COMMENT_ANCHOR; + +#ifdef _TARGET_64BIT_ + if (!comp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_IL_STUB)) { // Set the TCB's frame to be the one we just created. // Note the init routine for the InlinedCallFrame (CORINFO_HELP_INIT_PINVOKE_FRAME) @@ -2552,6 +2909,7 @@ void Lowering::InsertPInvokeCallProlog(GenTreeCall* call) GenTree* frameUpd = CreateFrameLinkUpdate(PushFrame); BlockRange().InsertBefore(insertBefore, LIR::SeqTree(comp, frameUpd)); } +#endif // _TARGET_64BIT_ // IMPORTANT **** This instruction must come last!!! **** // It changes the thread's state to Preemptive mode @@ -2583,7 +2941,7 @@ void Lowering::InsertPInvokeCallEpilog(GenTreeCall* call) // First argument is the address of the frame variable. GenTree* frameAddr = new (comp, GT_LCL_VAR) GenTreeLclVar(GT_LCL_VAR, TYP_BYREF, comp->lvaInlinedPInvokeFrameVar, BAD_IL_OFFSET); - frameAddr->gtOper = GT_LCL_VAR_ADDR; + frameAddr->SetOperRaw(GT_LCL_VAR_ADDR); // Insert call to CORINFO_HELP_JIT_PINVOKE_END GenTree* helperCall = @@ -2604,12 +2962,32 @@ void Lowering::InsertPInvokeCallEpilog(GenTreeCall* call) tree = CreateReturnTrapSeq(); BlockRange().InsertBefore(insertionPoint, LIR::SeqTree(comp, tree)); - // Pop the frame if necessasry - if (!(comp->opts.eeFlags & CORJIT_FLG_IL_STUB)) + // Pop the frame if necessary. On 32-bit targets this only happens in the method epilog; on 64-bit targets thi + // happens after every PInvoke call in non-stubs. 32-bit targets instead mark the frame as inactive. + CLANG_FORMAT_COMMENT_ANCHOR; + +#ifdef _TARGET_64BIT_ + if (!comp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_IL_STUB)) { tree = CreateFrameLinkUpdate(PopFrame); BlockRange().InsertBefore(insertionPoint, LIR::SeqTree(comp, tree)); } +#else + const CORINFO_EE_INFO::InlinedCallFrameInfo& callFrameInfo = comp->eeGetEEInfo()->inlinedCallFrameInfo; + + // ---------------------------------------------------------------------------------- + // InlinedCallFrame.m_pCallerReturnAddress = nullptr + + GenTreeLclFld* const storeCallSiteTracker = + new (comp, GT_STORE_LCL_FLD) GenTreeLclFld(GT_STORE_LCL_FLD, TYP_I_IMPL, comp->lvaInlinedPInvokeFrameVar, + callFrameInfo.offsetOfReturnAddress); + + GenTreeIntCon* const constantZero = new (comp, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, 0); + + storeCallSiteTracker->gtOp1 = constantZero; + + BlockRange().InsertBefore(insertionPoint, constantZero, storeCallSiteTracker); +#endif // _TARGET_64BIT_ } //------------------------------------------------------------------------ @@ -2624,7 +3002,7 @@ void Lowering::InsertPInvokeCallEpilog(GenTreeCall* call) GenTree* Lowering::LowerNonvirtPinvokeCall(GenTreeCall* call) { // PInvoke lowering varies depending on the flags passed in by the EE. By default, - // GC transitions are generated inline; if CORJIT_FLG2_USE_PINVOKE_HELPERS is specified, + // GC transitions are generated inline; if CORJIT_FLAG_USE_PINVOKE_HELPERS is specified, // GC transitions are instead performed using helper calls. Examples of each case are given // below. Note that the data structure that is used to store information about a call frame // containing any P/Invoke calls is initialized in the method prolog (see @@ -2697,7 +3075,7 @@ GenTree* Lowering::LowerNonvirtPinvokeCall(GenTreeCall* call) #if COR_JIT_EE_VERSION > 460 comp->info.compCompHnd->getAddressOfPInvokeTarget(methHnd, &lookup); #else - void* pIndirection; + void* pIndirection; lookup.accessType = IAT_PVALUE; lookup.addr = comp->info.compCompHnd->getAddressOfPInvokeFixup(methHnd, &pIndirection); if (lookup.addr == nullptr) @@ -2866,14 +3244,10 @@ GenTree* Lowering::LowerVirtualStubCall(GenTreeCall* call) } #endif - // TODO-Cleanup: Disable emitting random NOPs - // This is code to set up an indirect call to a stub address computed // via dictionary lookup. if (call->gtCallType == CT_INDIRECT) { - NYI_X86("Virtual Stub dispatched call lowering via dictionary lookup"); - // The importer decided we needed a stub call via a computed // stub dispatch address, i.e. an address which came from a dictionary lookup. // - The dictionary lookup produces an indirected address, suitable for call @@ -2886,6 +3260,8 @@ GenTree* Lowering::LowerVirtualStubCall(GenTreeCall* call) // All we have to do here is add an indirection to generate the actual call target. GenTree* ind = Ind(call->gtCallAddr); + ind->gtFlags |= GTF_IND_REQ_ADDR_IN_REG; + BlockRange().InsertAfter(call->gtCallAddr, ind); call->gtCallAddr = ind; } @@ -2923,8 +3299,10 @@ GenTree* Lowering::LowerVirtualStubCall(GenTreeCall* call) // So we don't use a register. #ifndef _TARGET_X86_ // on x64 we must materialize the target using specific registers. - addr->gtRegNum = REG_VIRTUAL_STUB_PARAM; + addr->gtRegNum = REG_VIRTUAL_STUB_PARAM; + indir->gtRegNum = REG_JUMP_THUNK_PARAM; + indir->gtFlags |= GTF_IND_REQ_ADDR_IN_REG; #endif result = indir; } @@ -3042,8 +3420,6 @@ bool Lowering::AreSourcesPossiblyModifiedLocals(GenTree* addr, GenTree* base, Ge return true; } } - - unreached(); } //------------------------------------------------------------------------ @@ -3082,9 +3458,9 @@ GenTree* Lowering::TryCreateAddrMode(LIR::Use&& use, bool isIndir) { // We can have an indirection on the rhs of a block copy (it is the source // object). This is not a "regular" indirection. - // (Note that the parent check could be costly.) - GenTree* parent = indir->gtGetParent(nullptr); - if ((parent != nullptr) && parent->OperIsIndir()) + // (Note that the user check could be costly.) + LIR::Use indirUse; + if (BlockRange().TryGetUse(indir, &indirUse) && indirUse.User()->OperIsIndir()) { isIndir = false; } @@ -3248,9 +3624,14 @@ void Lowering::LowerUnsignedDivOrMod(GenTree* node) { assert((node->OperGet() == GT_UDIV) || (node->OperGet() == GT_UMOD)); - GenTree* divisor = node->gtGetOp2(); + GenTree* divisor = node->gtGetOp2(); + GenTree* dividend = node->gtGetOp1(); - if (divisor->IsCnsIntOrI()) + if (divisor->IsCnsIntOrI() +#ifdef _TARGET_X86_ + && (dividend->OperGet() != GT_LONG) +#endif + ) { size_t divisorValue = static_cast(divisor->gtIntCon.IconValue()); @@ -3276,6 +3657,91 @@ void Lowering::LowerUnsignedDivOrMod(GenTree* node) } //------------------------------------------------------------------------ +// GetSignedMagicNumberForDivide: Generates a magic number and shift amount for +// the magic number division optimization. +// +// Arguments: +// denom - The denominator +// shift - Pointer to the shift value to be returned +// +// Returns: +// The magic number. +// +// Notes: +// This code is previously from UTC where it notes it was taken from +// _The_PowerPC_Compiler_Writer's_Guide_, pages 57-58. The paper is is based on +// is "Division by invariant integers using multiplication" by Torbjorn Granlund +// and Peter L. Montgomery in PLDI 94 + +template +T GetSignedMagicNumberForDivide(T denom, int* shift /*out*/) +{ + // static SMAG smag; + const int bits = sizeof(T) * 8; + const int bits_minus_1 = bits - 1; + + typedef typename jitstd::make_unsigned::type UT; + + const UT two_nminus1 = UT(1) << bits_minus_1; + + int p; + UT absDenom; + UT absNc; + UT delta; + UT q1; + UT r1; + UT r2; + UT q2; + UT t; + T result_magic; + int result_shift; + int iters = 0; + + absDenom = abs(denom); + t = two_nminus1 + ((unsigned int)denom >> 31); + absNc = t - 1 - (t % absDenom); // absolute value of nc + p = bits_minus_1; // initialize p + q1 = two_nminus1 / absNc; // initialize q1 = 2^p / abs(nc) + r1 = two_nminus1 - (q1 * absNc); // initialize r1 = rem(2^p, abs(nc)) + q2 = two_nminus1 / absDenom; // initialize q1 = 2^p / abs(denom) + r2 = two_nminus1 - (q2 * absDenom); // initialize r1 = rem(2^p, abs(denom)) + + do + { + iters++; + p++; + q1 *= 2; // update q1 = 2^p / abs(nc) + r1 *= 2; // update r1 = rem(2^p / abs(nc)) + + if (r1 >= absNc) + { // must be unsigned comparison + q1++; + r1 -= absNc; + } + + q2 *= 2; // update q2 = 2^p / abs(denom) + r2 *= 2; // update r2 = rem(2^p / abs(denom)) + + if (r2 >= absDenom) + { // must be unsigned comparison + q2++; + r2 -= absDenom; + } + + delta = absDenom - r2; + } while (q1 < delta || (q1 == delta && r1 == 0)); + + result_magic = q2 + 1; // resulting magic number + if (denom < 0) + { + result_magic = -result_magic; + } + *shift = p - bits; // resulting shift + + return result_magic; +} + +//------------------------------------------------------------------------ // LowerSignedDivOrMod: transform integer GT_DIV/GT_MOD nodes with a power of 2 // const divisor into equivalent but faster sequences. // @@ -3313,8 +3779,10 @@ GenTree* Lowering::LowerSignedDivOrMod(GenTreePtr node) ssize_t divisorValue = divisor->gtIntCon.IconValue(); - if (divisorValue == -1) + if (divisorValue == -1 || divisorValue == 0) { + // x / 0 and x % 0 can't be optimized because they are required to throw an exception. + // x / -1 can't be optimized because INT_MIN / -1 is required to throw an exception. // x % -1 is always 0 and the IL spec says that the rem instruction "can" throw an exception if x is @@ -3343,14 +3811,122 @@ GenTree* Lowering::LowerSignedDivOrMod(GenTreePtr node) if (!isPow2(absDivisorValue)) { +#ifdef _TARGET_XARCH_ + ssize_t magic; + int shift; + + if (type == TYP_INT) + { + magic = GetSignedMagicNumberForDivide(static_cast(divisorValue), &shift); + } + else + { +#ifdef _TARGET_64BIT_ + magic = GetSignedMagicNumberForDivide(static_cast(divisorValue), &shift); +#else + unreached(); +#endif + } + + divisor->gtIntConCommon.SetIconValue(magic); + + // Insert a new GT_MULHI node in front of the existing GT_DIV/GT_MOD node. + // The existing node will later be transformed into a GT_ADD/GT_SUB that + // computes the final result. This way don't need to find and change the + // use of the existing node. + GenTree* mulhi = comp->gtNewOperNode(GT_MULHI, type, divisor, dividend); + BlockRange().InsertBefore(divMod, mulhi); + + // mulhi was the easy part. Now we need to generate different code depending + // on the divisor value: + // For 3 we need: + // div = signbit(mulhi) + mulhi + // For 5 we need: + // div = signbit(mulhi) + sar(mulhi, 1) ; requires shift adjust + // For 7 we need: + // mulhi += dividend ; requires add adjust + // div = signbit(mulhi) + sar(mulhi, 2) ; requires shift adjust + // For -3 we need: + // mulhi -= dividend ; requires sub adjust + // div = signbit(mulhi) + sar(mulhi, 1) ; requires shift adjust + bool requiresAddSubAdjust = signum(divisorValue) != signum(magic); + bool requiresShiftAdjust = shift != 0; + bool requiresDividendMultiuse = requiresAddSubAdjust || !isDiv; + unsigned curBBWeight = comp->compCurBB->getBBWeight(comp); + unsigned dividendLclNum = BAD_VAR_NUM; + + if (requiresDividendMultiuse) + { + LIR::Use dividendUse(BlockRange(), &mulhi->gtOp.gtOp2, mulhi); + dividendLclNum = dividendUse.ReplaceWithLclVar(comp, curBBWeight); + } + + GenTree* adjusted; + + if (requiresAddSubAdjust) + { + dividend = comp->gtNewLclvNode(dividendLclNum, type); + comp->lvaTable[dividendLclNum].incRefCnts(curBBWeight, comp); + + adjusted = comp->gtNewOperNode(divisorValue > 0 ? GT_ADD : GT_SUB, type, mulhi, dividend); + BlockRange().InsertBefore(divMod, dividend, adjusted); + } + else + { + adjusted = mulhi; + } + + GenTree* shiftBy = comp->gtNewIconNode(genTypeSize(type) * 8 - 1, type); + GenTree* signBit = comp->gtNewOperNode(GT_RSZ, type, adjusted, shiftBy); + BlockRange().InsertBefore(divMod, shiftBy, signBit); + + LIR::Use adjustedUse(BlockRange(), &signBit->gtOp.gtOp1, signBit); + unsigned adjustedLclNum = adjustedUse.ReplaceWithLclVar(comp, curBBWeight); + adjusted = comp->gtNewLclvNode(adjustedLclNum, type); + comp->lvaTable[adjustedLclNum].incRefCnts(curBBWeight, comp); + BlockRange().InsertBefore(divMod, adjusted); + + if (requiresShiftAdjust) + { + shiftBy = comp->gtNewIconNode(shift, TYP_INT); + adjusted = comp->gtNewOperNode(GT_RSH, type, adjusted, shiftBy); + BlockRange().InsertBefore(divMod, shiftBy, adjusted); + } + + if (isDiv) + { + divMod->SetOperRaw(GT_ADD); + divMod->gtOp.gtOp1 = adjusted; + divMod->gtOp.gtOp2 = signBit; + } + else + { + GenTree* div = comp->gtNewOperNode(GT_ADD, type, adjusted, signBit); + + dividend = comp->gtNewLclvNode(dividendLclNum, type); + comp->lvaTable[dividendLclNum].incRefCnts(curBBWeight, comp); + + // divisor % dividend = dividend - divisor x div + GenTree* divisor = comp->gtNewIconNode(divisorValue, type); + GenTree* mul = comp->gtNewOperNode(GT_MUL, type, div, divisor); + BlockRange().InsertBefore(divMod, dividend, div, divisor, mul); + + divMod->SetOperRaw(GT_SUB); + divMod->gtOp.gtOp1 = dividend; + divMod->gtOp.gtOp2 = mul; + } + + return mulhi; +#else + // Currently there's no GT_MULHI for ARM32/64 return next; +#endif } - // We're committed to the conversion now. Go find the use. + // We're committed to the conversion now. Go find the use if any. LIR::Use use; if (!BlockRange().TryGetUse(node, &use)) { - assert(!"signed DIV/MOD node is unused"); return next; } @@ -3450,8 +4026,6 @@ void Lowering::LowerStoreInd(GenTree* node) void Lowering::LowerBlockStore(GenTreeBlk* blkNode) { GenTree* src = blkNode->Data(); - // TODO-1stClassStructs: Don't require this. - assert(blkNode->OperIsInitBlkOp() || !src->OperIsLocal()); TryCreateAddrMode(LIR::Use(BlockRange(), &blkNode->Addr(), blkNode), false); } @@ -3817,17 +4391,17 @@ void Lowering::CheckCallArg(GenTree* arg) break; #endif - case GT_LIST: - { - GenTreeArgList* list = arg->AsArgList(); - assert(list->IsAggregate()); + case GT_FIELD_LIST: + { + GenTreeFieldList* list = arg->AsFieldList(); + assert(list->IsFieldListHead()); - for (; list != nullptr; list = list->Rest()) - { - assert(list->Current()->OperIsPutArg()); - } + for (; list != nullptr; list = list->Rest()) + { + assert(list->Current()->OperIsPutArg()); } - break; + } + break; default: assert(arg->OperIsPutArg()); diff --git a/src/jit/lower.h b/src/jit/lower.h index 620636d..c1cafb4 100644 --- a/src/jit/lower.h +++ b/src/jit/lower.h @@ -65,6 +65,7 @@ private: // Call Lowering // ------------------------------ void LowerCall(GenTree* call); + void LowerCompare(GenTree* tree); void LowerJmpMethod(GenTree* jmp); void LowerRet(GenTree* ret); GenTree* LowerDelegateInvoke(GenTreeCall* call); @@ -127,8 +128,14 @@ private: // return true if this call target is within range of a pc-rel call on the machine bool IsCallTargetInRange(void* addr); +#ifdef _TARGET_X86_ + bool ExcludeNonByteableRegisters(GenTree* tree); +#endif + void TreeNodeInfoInit(GenTree* stmt); + void TreeNodeInfoInitCheckByteable(GenTree* tree); + #if defined(_TARGET_XARCH_) void TreeNodeInfoInitSimple(GenTree* tree); @@ -190,6 +197,7 @@ private: void TreeNodeInfoInitReturn(GenTree* tree); void TreeNodeInfoInitShiftRotate(GenTree* tree); void TreeNodeInfoInitCall(GenTreeCall* call); + void TreeNodeInfoInitCmp(GenTreePtr tree); void TreeNodeInfoInitStructArg(GenTreePtr structArg); void TreeNodeInfoInitBlockStore(GenTreeBlk* blkNode); void TreeNodeInfoInitLogicalOp(GenTree* tree); @@ -200,11 +208,11 @@ private: #endif // FEATURE_SIMD void TreeNodeInfoInitCast(GenTree* tree); #ifdef _TARGET_ARM64_ - void TreeNodeInfoInitPutArgStk(GenTree* argNode, fgArgTabEntryPtr info); + void TreeNodeInfoInitPutArgStk(GenTreePutArgStk* argNode, fgArgTabEntryPtr info); #endif // _TARGET_ARM64_ -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING - void TreeNodeInfoInitPutArgStk(GenTree* tree); -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING +#ifdef FEATURE_PUT_STRUCT_ARG_STK + void TreeNodeInfoInitPutArgStk(GenTreePutArgStk* tree); +#endif // FEATURE_PUT_STRUCT_ARG_STK void TreeNodeInfoInitLclHeap(GenTree* tree); void DumpNodeInfoMap(); @@ -226,8 +234,6 @@ private: void SetMulOpCounts(GenTreePtr tree); #endif // defined(_TARGET_XARCH_) - void LowerCmp(GenTreePtr tree); - #if !CPU_LOAD_STORE_ARCH bool IsRMWIndirCandidate(GenTree* operand, GenTree* storeInd); bool IsBinOpInRMWStoreInd(GenTreePtr tree); diff --git a/src/jit/lowerarm.cpp b/src/jit/lowerarm.cpp index 67cea2f..5bf23c4 100644 --- a/src/jit/lowerarm.cpp +++ b/src/jit/lowerarm.cpp @@ -32,10 +32,76 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #include "lower.h" #include "lsra.h" -/* Lowering of GT_CAST nodes */ +//------------------------------------------------------------------------ +// LowerCast: Lower GT_CAST(srcType, DstType) nodes. +// +// Arguments: +// tree - GT_CAST node to be lowered +// +// Return Value: +// None. +// +// Notes: +// Casts from small int type to float/double are transformed as follows: +// GT_CAST(byte, float/double) = GT_CAST(GT_CAST(byte, int32), float/double) +// GT_CAST(sbyte, float/double) = GT_CAST(GT_CAST(sbyte, int32), float/double) +// GT_CAST(int16, float/double) = GT_CAST(GT_CAST(int16, int32), float/double) +// GT_CAST(uint16, float/double) = GT_CAST(GT_CAST(uint16, int32), float/double) +// +// Similarly casts from float/double to a smaller int type are transformed as follows: +// GT_CAST(float/double, byte) = GT_CAST(GT_CAST(float/double, int32), byte) +// GT_CAST(float/double, sbyte) = GT_CAST(GT_CAST(float/double, int32), sbyte) +// GT_CAST(float/double, int16) = GT_CAST(GT_CAST(double/double, int32), int16) +// GT_CAST(float/double, uint16) = GT_CAST(GT_CAST(double/double, int32), uint16) +// +// Note that for the overflow conversions we still depend on helper calls and +// don't expect to see them here. +// i) GT_CAST(float/double, int type with overflow detection) + void Lowering::LowerCast(GenTree* tree) { - NYI_ARM("ARM Lowering for cast"); + assert(tree->OperGet() == GT_CAST); + + JITDUMP("LowerCast for: "); + DISPNODE(tree); + JITDUMP("\n"); + + GenTreePtr op1 = tree->gtOp.gtOp1; + var_types dstType = tree->CastToType(); + var_types srcType = op1->TypeGet(); + var_types tmpType = TYP_UNDEF; + + // TODO-ARM-Cleanup: Remove following NYI assertions. + if (varTypeIsFloating(srcType)) + { + NYI_ARM("Lowering for cast from float"); // Not tested yet. + noway_assert(!tree->gtOverflow()); + } + + // Case of src is a small type and dst is a floating point type. + if (varTypeIsSmall(srcType) && varTypeIsFloating(dstType)) + { + NYI_ARM("Lowering for cast from small type to float"); // Not tested yet. + // These conversions can never be overflow detecting ones. + noway_assert(!tree->gtOverflow()); + tmpType = TYP_INT; + } + // case of src is a floating point type and dst is a small type. + else if (varTypeIsFloating(srcType) && varTypeIsSmall(dstType)) + { + NYI_ARM("Lowering for cast from float to small type"); // Not tested yet. + tmpType = TYP_INT; + } + + if (tmpType != TYP_UNDEF) + { + GenTreePtr tmp = comp->gtNewCastNode(tmpType, op1, tmpType); + tmp->gtFlags |= (tree->gtFlags & (GTF_UNSIGNED | GTF_OVERFLOW | GTF_EXCEPT)); + + tree->gtFlags &= ~GTF_UNSIGNED; + tree->gtOp.gtOp1 = tmp; + BlockRange().InsertAfter(op1, tmp); + } } void Lowering::LowerRotate(GenTreePtr tree) @@ -62,7 +128,73 @@ bool Lowering::IsCallTargetInRange(void* addr) // return true if the immediate can be folded into an instruction, for example small enough and non-relocatable bool Lowering::IsContainableImmed(GenTree* parentNode, GenTree* childNode) { - NYI_ARM("ARM IsContainableImmed"); + if (varTypeIsFloating(parentNode->TypeGet())) + { + // TODO-ARM-Cleanup: not tested yet. + NYI_ARM("ARM IsContainableImmed for floating point type"); + + // We can contain a floating point 0.0 constant in a compare instruction + switch (parentNode->OperGet()) + { + default: + return false; + + case GT_EQ: + case GT_NE: + case GT_LT: + case GT_LE: + case GT_GE: + case GT_GT: + if (childNode->IsIntegralConst(0)) + return true; + break; + } + } + else + { + // Make sure we have an actual immediate + if (!childNode->IsCnsIntOrI()) + return false; + if (childNode->IsIconHandle() && comp->opts.compReloc) + return false; + + ssize_t immVal = childNode->gtIntCon.gtIconVal; + emitAttr attr = emitActualTypeSize(childNode->TypeGet()); + emitAttr size = EA_SIZE(attr); + + switch (parentNode->OperGet()) + { + default: + return false; + + case GT_ADD: + case GT_SUB: + if (emitter::emitIns_valid_imm_for_add(immVal, INS_FLAGS_DONT_CARE)) + return true; + break; + + case GT_EQ: + case GT_NE: + case GT_LT: + case GT_LE: + case GT_GE: + case GT_GT: + case GT_AND: + case GT_OR: + case GT_XOR: + if (emitter::emitIns_valid_imm_for_alu(immVal)) + return true; + break; + + case GT_STORE_LCL_VAR: + // TODO-ARM-Cleanup: not tested yet + NYI_ARM("ARM IsContainableImmed for GT_STORE_LCL_VAR"); + if (immVal == 0) + return true; + break; + } + } + return false; } diff --git a/src/jit/lowerarm64.cpp b/src/jit/lowerarm64.cpp index 1720c62..cc9e226 100644 --- a/src/jit/lowerarm64.cpp +++ b/src/jit/lowerarm64.cpp @@ -126,6 +126,10 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) TreeNodeInfo* info = &(tree->gtLsraInfo); RegisterType registerType = TypeGet(tree); + JITDUMP("TreeNodeInfoInit for: "); + DISPNODE(tree); + JITDUMP("\n"); + switch (tree->OperGet()) { GenTree* op1; @@ -202,6 +206,7 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) __fallthrough; case GT_LIST: + case GT_FIELD_LIST: case GT_ARGPLACE: case GT_NO_OP: case GT_START_NONGC: @@ -485,7 +490,7 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) case GT_LE: case GT_GE: case GT_GT: - LowerCmp(tree); + TreeNodeInfoInitCmp(tree); break; case GT_CKFINITE: @@ -524,12 +529,12 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) break; case GT_BLK: - case GT_OBJ: case GT_DYN_BLK: // These should all be eliminated prior to Lowering. assert(!"Non-store block node in Lowering"); info->srcCount = 0; info->dstCount = 0; + break; case GT_STORE_BLK: case GT_STORE_OBJ: @@ -537,6 +542,12 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) TreeNodeInfoInitBlockStore(tree->AsBlk()); break; + case GT_INIT_VAL: + // Always a passthrough of its child's value. + info->srcCount = 0; + info->dstCount = 0; + break; + case GT_LCLHEAP: { info->srcCount = 1; @@ -977,7 +988,7 @@ void Lowering::TreeNodeInfoInitCall(GenTreeCall* call) for (GenTreePtr list = call->gtCallLateArgs; list; list = list->MoveNext()) { - assert(list->IsList()); + assert(list->OperIsList()); GenTreePtr argNode = list->Current(); @@ -989,7 +1000,7 @@ void Lowering::TreeNodeInfoInitCall(GenTreeCall* call) // late arg that is not passed in a register assert(argNode->gtOper == GT_PUTARG_STK); - TreeNodeInfoInitPutArgStk(argNode, curArgTabEntry); + TreeNodeInfoInitPutArgStk(argNode->AsPutArgStk(), curArgTabEntry); continue; } @@ -1003,16 +1014,16 @@ void Lowering::TreeNodeInfoInitCall(GenTreeCall* call) argNode = argNode->gtEffectiveVal(); - // A GT_LIST has a TYP_VOID, but is used to represent a multireg struct - if (varTypeIsStruct(argNode) || (argNode->gtOper == GT_LIST)) + // A GT_FIELD_LIST has a TYP_VOID, but is used to represent a multireg struct + if (varTypeIsStruct(argNode) || (argNode->gtOper == GT_FIELD_LIST)) { GenTreePtr actualArgNode = argNode; unsigned originalSize = 0; - if (argNode->gtOper == GT_LIST) + if (argNode->gtOper == GT_FIELD_LIST) { // There could be up to 2-4 PUTARG_REGs in the list (3 or 4 can only occur for HFAs) - GenTreeArgList* argListPtr = argNode->AsArgList(); + GenTreeFieldList* fieldListPtr = argNode->AsFieldList(); // Initailize the first register and the first regmask in our list regNumber targetReg = argReg; @@ -1020,9 +1031,9 @@ void Lowering::TreeNodeInfoInitCall(GenTreeCall* call) unsigned iterationNum = 0; originalSize = 0; - for (; argListPtr; argListPtr = argListPtr->Rest()) + for (; fieldListPtr; fieldListPtr = fieldListPtr->Rest()) { - GenTreePtr putArgRegNode = argListPtr->gtOp.gtOp1; + GenTreePtr putArgRegNode = fieldListPtr->Current(); assert(putArgRegNode->gtOper == GT_PUTARG_REG); GenTreePtr putArgChild = putArgRegNode->gtOp.gtOp1; @@ -1115,7 +1126,7 @@ void Lowering::TreeNodeInfoInitCall(GenTreeCall* call) assert(curArgTabEntry->regNum == REG_STK); - TreeNodeInfoInitPutArgStk(arg, curArgTabEntry); + TreeNodeInfoInitPutArgStk(arg->AsPutArgStk(), curArgTabEntry); } else { @@ -1154,7 +1165,7 @@ void Lowering::TreeNodeInfoInitCall(GenTreeCall* call) // Notes: // Set the child node(s) to be contained when we have a multireg arg // -void Lowering::TreeNodeInfoInitPutArgStk(GenTree* argNode, fgArgTabEntryPtr info) +void Lowering::TreeNodeInfoInitPutArgStk(GenTreePutArgStk* argNode, fgArgTabEntryPtr info) { assert(argNode->gtOper == GT_PUTARG_STK); @@ -1166,14 +1177,14 @@ void Lowering::TreeNodeInfoInitPutArgStk(GenTree* argNode, fgArgTabEntryPtr info argNode->gtLsraInfo.srcCount = 1; argNode->gtLsraInfo.dstCount = 0; - // Do we have a TYP_STRUCT argument (or a GT_LIST), if so it must be a multireg pass-by-value struct - if ((putArgChild->TypeGet() == TYP_STRUCT) || (putArgChild->OperGet() == GT_LIST)) + // Do we have a TYP_STRUCT argument (or a GT_FIELD_LIST), if so it must be a multireg pass-by-value struct + if ((putArgChild->TypeGet() == TYP_STRUCT) || (putArgChild->OperGet() == GT_FIELD_LIST)) { // We will use store instructions that each write a register sized value - if (putArgChild->OperGet() == GT_LIST) + if (putArgChild->OperGet() == GT_FIELD_LIST) { - // We consume all of the items in the GT_LIST + // We consume all of the items in the GT_FIELD_LIST argNode->gtLsraInfo.srcCount = info->numSlots; } else @@ -1219,8 +1230,9 @@ void Lowering::TreeNodeInfoInitPutArgStk(GenTree* argNode, fgArgTabEntryPtr info void Lowering::TreeNodeInfoInitBlockStore(GenTreeBlk* blkNode) { - GenTree* dstAddr = blkNode->Addr(); - unsigned size; + GenTree* dstAddr = blkNode->Addr(); + unsigned size = blkNode->gtBlkSize; + GenTree* source = blkNode->Data(); LinearScan* l = m_lsra; Compiler* compiler = comp; @@ -1228,16 +1240,44 @@ void Lowering::TreeNodeInfoInitBlockStore(GenTreeBlk* blkNode) // We may require an additional source or temp register for the size. blkNode->gtLsraInfo.srcCount = 2; blkNode->gtLsraInfo.dstCount = 0; + GenTreePtr srcAddrOrFill = nullptr; + bool isInitBlk = blkNode->OperIsInitBlkOp(); - if ((blkNode->OperGet() == GT_STORE_OBJ) && (blkNode->AsObj()->gtGcPtrCount == 0)) + if (!isInitBlk) { - blkNode->SetOper(GT_STORE_BLK); + // CopyObj or CopyBlk + if ((blkNode->OperGet() == GT_STORE_OBJ) && ((blkNode->AsObj()->gtGcPtrCount == 0) || blkNode->gtBlkOpGcUnsafe)) + { + blkNode->SetOper(GT_STORE_BLK); + } + if (source->gtOper == GT_IND) + { + srcAddrOrFill = blkNode->Data()->gtGetOp1(); + // We're effectively setting source as contained, but can't call MakeSrcContained, because the + // "inheritance" of the srcCount is to a child not a parent - it would "just work" but could be misleading. + // If srcAddr is already non-contained, we don't need to change it. + if (srcAddrOrFill->gtLsraInfo.getDstCount() == 0) + { + srcAddrOrFill->gtLsraInfo.setDstCount(1); + srcAddrOrFill->gtLsraInfo.setSrcCount(source->gtLsraInfo.srcCount); + } + m_lsra->clearOperandCounts(source); + } + else if (!source->IsMultiRegCall() && !source->OperIsSIMD()) + { + assert(source->IsLocal()); + MakeSrcContained(blkNode, source); + } } - if (blkNode->OperIsInitBlkOp()) + if (isInitBlk) { - unsigned size = blkNode->gtBlkSize; - GenTreePtr initVal = blkNode->Data(); + GenTreePtr initVal = source; + if (initVal->OperIsInitVal()) + { + initVal = initVal->gtGetOp1(); + } + srcAddrOrFill = initVal; #if 0 // TODO-ARM64-CQ: Currently we generate a helper call for every @@ -1264,8 +1304,6 @@ void Lowering::TreeNodeInfoInitBlockStore(GenTreeBlk* blkNode) initVal->gtType = TYP_LONG; } - MakeSrcContained(tree, blockSize); - // In case we have a buffer >= 16 bytes // we can use SSE2 to do a 128-bit store in a single // instruction. @@ -1282,7 +1320,7 @@ void Lowering::TreeNodeInfoInitBlockStore(GenTreeBlk* blkNode) else #endif // 0 { - // The helper follows the regular AMD64 ABI. + // The helper follows the regular ABI. dstAddr->gtLsraInfo.setSrcCandidates(l, RBM_ARG_0); initVal->gtLsraInfo.setSrcCandidates(l, RBM_ARG_1); blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindHelper; @@ -1306,34 +1344,12 @@ void Lowering::TreeNodeInfoInitBlockStore(GenTreeBlk* blkNode) { // CopyObj or CopyBlk // Sources are src and dest and size if not constant. - unsigned size = blkNode->gtBlkSize; - GenTreePtr source = blkNode->Data(); - GenTree* srcAddr = nullptr; - if (source->gtOper == GT_IND) - { - srcAddr = blkNode->Data()->gtGetOp1(); - // We're effectively setting source as contained, but can't call MakeSrcContained, because the - // "inheritance" of the srcCount is to a child not a parent - it would "just work" but could be misleading. - // If srcAddr is already non-contained, we don't need to change it. - if (srcAddr->gtLsraInfo.getDstCount() == 0) - { - srcAddr->gtLsraInfo.setDstCount(1); - srcAddr->gtLsraInfo.setSrcCount(source->gtLsraInfo.srcCount); - } - m_lsra->clearOperandCounts(source); - } - else - { - assert(source->IsLocal()); - MakeSrcContained(blkNode, source); - } if (blkNode->OperGet() == GT_STORE_OBJ) { // CopyObj GenTreeObj* objNode = blkNode->AsObj(); - GenTreePtr source = objNode->Data(); unsigned slots = objNode->gtSlots; @@ -1362,16 +1378,19 @@ void Lowering::TreeNodeInfoInitBlockStore(GenTreeBlk* blkNode) blkNode->gtLsraInfo.internalIntCount = 1; dstAddr->gtLsraInfo.setSrcCandidates(l, RBM_WRITE_BARRIER_DST_BYREF); - srcAddr->gtLsraInfo.setSrcCandidates(l, RBM_WRITE_BARRIER_SRC_BYREF); + // If we have a source address we want it in REG_WRITE_BARRIER_SRC_BYREF. + // Otherwise, if it is a local, codegen will put its address in REG_WRITE_BARRIER_SRC_BYREF, + // which is killed by a StoreObj (and thus needn't be reserved). + if (srcAddrOrFill != nullptr) + { + srcAddrOrFill->gtLsraInfo.setSrcCandidates(l, RBM_WRITE_BARRIER_SRC_BYREF); + } } else { // CopyBlk - unsigned size = blkNode->gtBlkSize; - GenTreePtr dstAddr = blkNode->Addr(); - GenTreePtr srcAddr = blkNode->Data(); - short internalIntCount = 0; - regMaskTP internalIntCandidates = RBM_NONE; + short internalIntCount = 0; + regMaskTP internalIntCandidates = RBM_NONE; #if 0 // In case of a CpBlk with a constant size and less than CPBLK_UNROLL_LIMIT size @@ -1379,11 +1398,8 @@ void Lowering::TreeNodeInfoInitBlockStore(GenTreeBlk* blkNode) // TODO-ARM64-CQ: cpblk loop unrolling is currently not implemented. - if (blockSize->IsCnsIntOrI() && blockSize->gtIntCon.gtIconVal <= CPBLK_UNROLL_LIMIT) + if ((size != 0) && (size <= INITBLK_UNROLL_LIMIT)) { - assert(!blockSize->IsIconHandle()); - ssize_t size = blockSize->gtIntCon.gtIconVal; - // If we have a buffer between XMM_REGSIZE_BYTES and CPBLK_UNROLL_LIMIT bytes, we'll use SSE2. // Structs and buffer with sizes <= CPBLK_UNROLL_LIMIT bytes are occurring in more than 95% of // our framework assemblies, so this is the main code generation scheme we'll use. @@ -1404,9 +1420,9 @@ void Lowering::TreeNodeInfoInitBlockStore(GenTreeBlk* blkNode) // If src or dst are on stack, we don't have to generate the address into a register // because it's just some constant+SP - if (srcAddr->OperIsLocalAddr()) + if (srcAddr != nullptr && srcAddrOrFill->OperIsLocalAddr()) { - MakeSrcContained(blkNode, srcAddr); + MakeSrcContained(blkNode, srcAddrOrFill); } if (dstAddr->OperIsLocalAddr()) @@ -1425,15 +1441,9 @@ void Lowering::TreeNodeInfoInitBlockStore(GenTreeBlk* blkNode) dstAddr->gtLsraInfo.setSrcCandidates(l, RBM_ARG_0); // The srcAddr goes in arg1. - if (srcAddr != nullptr) + if (srcAddrOrFill != nullptr) { - srcAddr->gtLsraInfo.setSrcCandidates(l, RBM_ARG_1); - } - else - { - // This is a local; we'll use a temp register for its address. - internalIntCandidates |= RBM_ARG_1; - internalIntCount++; + srcAddrOrFill->gtLsraInfo.setSrcCandidates(l, RBM_ARG_1); } if (size != 0) { @@ -1447,7 +1457,6 @@ void Lowering::TreeNodeInfoInitBlockStore(GenTreeBlk* blkNode) noway_assert(blkNode->gtOper == GT_STORE_DYN_BLK); blkNode->gtLsraInfo.setSrcCount(3); GenTree* blockSize = blkNode->AsDynBlk()->gtDynamicSize; - assert(!blockSize->IsIconHandle()); blockSize->gtLsraInfo.setSrcCandidates(l, RBM_ARG_2); } blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindHelper; @@ -1860,7 +1869,7 @@ void Lowering::SetIndirAddrOpCounts(GenTreePtr indirTree) } } -void Lowering::LowerCmp(GenTreePtr tree) +void Lowering::TreeNodeInfoInitCmp(GenTreePtr tree) { TreeNodeInfo* info = &(tree->gtLsraInfo); diff --git a/src/jit/lowerxarch.cpp b/src/jit/lowerxarch.cpp index 6f98eb6..589cef4 100644 --- a/src/jit/lowerxarch.cpp +++ b/src/jit/lowerxarch.cpp @@ -77,7 +77,7 @@ void Lowering::LowerStoreLoc(GenTreeLclVarCommon* storeLoc) // InitBlk MakeSrcContained(storeLoc, op1); } - else if (storeLoc->TypeGet() == TYP_SIMD12) + else if ((storeLoc->TypeGet() == TYP_SIMD12) && (storeLoc->OperGet() == GT_STORE_LCL_FLD)) { // Need an additional register to extract upper 4 bytes of Vector3. info->internalFloatCount = 1; @@ -177,6 +177,7 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) break; case GT_LCL_FLD: + case GT_LCL_VAR: info->srcCount = 0; info->dstCount = 1; @@ -185,9 +186,9 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) if (tree->TypeGet() == TYP_SIMD12) { // We need an internal register different from targetReg in which 'tree' produces its result - // because both targetReg and internal reg will be in use at the same time. This is achieved - // by asking for two internal registers. - info->internalFloatCount = 2; + // because both targetReg and internal reg will be in use at the same time. + info->internalFloatCount = 1; + info->isInternalRegDelayFree = true; info->setInternalCandidates(m_lsra, m_lsra->allSIMDRegs()); } #endif @@ -195,7 +196,16 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) case GT_STORE_LCL_FLD: case GT_STORE_LCL_VAR: - info->srcCount = 1; +#ifdef _TARGET_X86_ + if (tree->gtGetOp1()->OperGet() == GT_LONG) + { + info->srcCount = 2; + } + else +#endif // _TARGET_X86_ + { + info->srcCount = 1; + } info->dstCount = 0; LowerStoreLoc(tree->AsLclVarCommon()); break; @@ -242,6 +252,7 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) break; case GT_LIST: + case GT_FIELD_LIST: case GT_ARGPLACE: case GT_NO_OP: case GT_START_NONGC: @@ -319,9 +330,87 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) break; case GT_JTRUE: + { + info->srcCount = 0; + info->dstCount = 0; + + GenTree* cmp = tree->gtGetOp1(); + l->clearDstCount(cmp); + +#ifdef FEATURE_SIMD + // Say we have the following IR + // simdCompareResult = GT_SIMD((In)Equality, v1, v2) + // integerCompareResult = GT_EQ/NE(simdCompareResult, true/false) + // GT_JTRUE(integerCompareResult) + // + // In this case we don't need to generate code for GT_EQ_/NE, since SIMD (In)Equality + // intrinsic would set or clear Zero flag. + + genTreeOps cmpOper = cmp->OperGet(); + if (cmpOper == GT_EQ || cmpOper == GT_NE) + { + GenTree* cmpOp1 = cmp->gtGetOp1(); + GenTree* cmpOp2 = cmp->gtGetOp2(); + + if (cmpOp1->IsSIMDEqualityOrInequality() && (cmpOp2->IsIntegralConst(0) || cmpOp2->IsIntegralConst(1))) + { + // clear dstCount on SIMD node to indicate that + // result doesn't need to be materialized into a register. + l->clearOperandCounts(cmp); + l->clearDstCount(cmpOp1); + l->clearOperandCounts(cmpOp2); + + // Codegen of SIMD (in)Equality uses target integer reg + // only for setting flags. Target reg is not needed on AVX + // when comparing against Vector Zero. In all other cases + // we need to reserve an int type internal register, since we + // have cleared dstCount. + if (compiler->canUseAVX() && cmpOp1->gtGetOp2()->IsIntegralConstVector(0)) + { + // We don't need an internal register,since we use vptest + // for setting flags. + } + else + { + ++(cmpOp1->gtLsraInfo.internalIntCount); + regMaskTP internalCandidates = cmpOp1->gtLsraInfo.getInternalCandidates(l); + internalCandidates |= l->allRegs(TYP_INT); + cmpOp1->gtLsraInfo.setInternalCandidates(l, internalCandidates); + } + + // We would have to reverse compare oper in the following cases: + // 1) SIMD Equality: Sets Zero flag on equal otherwise clears it. + // Therefore, if compare oper is == or != against false(0), we will + // be checking opposite of what is required. + // + // 2) SIMD inEquality: Clears Zero flag on true otherwise sets it. + // Therefore, if compare oper is == or != against true(1), we will + // be checking opposite of what is required. + GenTreeSIMD* simdNode = cmpOp1->AsSIMD(); + if (simdNode->gtSIMDIntrinsicID == SIMDIntrinsicOpEquality) + { + if (cmpOp2->IsIntegralConst(0)) + { + cmp->SetOper(GenTree::ReverseRelop(cmpOper)); + } + } + else + { + assert(simdNode->gtSIMDIntrinsicID == SIMDIntrinsicOpInEquality); + if (cmpOp2->IsIntegralConst(1)) + { + cmp->SetOper(GenTree::ReverseRelop(cmpOper)); + } + } + } + } +#endif // FEATURE_SIMD + } + break; + + case GT_JCC: info->srcCount = 0; info->dstCount = 0; - l->clearDstCount(tree->gtOp.gtOp1); break; case GT_JMP: @@ -436,6 +525,9 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) case GT_MUL: case GT_MULHI: +#if defined(_TARGET_X86_) && !defined(LEGACY_BACKEND) + case GT_MUL_LONG: +#endif SetMulOpCounts(tree); break; @@ -478,6 +570,11 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) info->internalFloatCount = 1; info->setInternalCandidates(l, l->internalFloatRegCandidates()); } + else + { + // Codegen of this tree node sets ZF and SF flags. + tree->gtFlags |= GTF_ZSF_SET; + } break; case GT_NOT: @@ -490,6 +587,10 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) case GT_RSZ: case GT_ROL: case GT_ROR: +#ifdef _TARGET_X86_ + case GT_LSH_HI: + case GT_RSH_LO: +#endif TreeNodeInfoInitShiftRotate(tree); break; @@ -499,7 +600,7 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) case GT_LE: case GT_GE: case GT_GT: - LowerCmp(tree); + TreeNodeInfoInitCmp(tree); break; case GT_CKFINITE: @@ -542,10 +643,7 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) } break; -#ifdef _TARGET_X86_ - case GT_OBJ: - NYI_X86("GT_OBJ"); -#elif !defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) +#if !defined(FEATURE_PUT_STRUCT_ARG_STK) case GT_OBJ: #endif case GT_BLK: @@ -556,11 +654,11 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) info->dstCount = 0; break; -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING +#ifdef FEATURE_PUT_STRUCT_ARG_STK case GT_PUTARG_STK: - TreeNodeInfoInitPutArgStk(tree); + TreeNodeInfoInitPutArgStk(tree->AsPutArgStk()); break; -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING +#endif // FEATURE_PUT_STRUCT_ARG_STK case GT_STORE_BLK: case GT_STORE_OBJ: @@ -568,6 +666,12 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) TreeNodeInfoInitBlockStore(tree->AsBlk()); break; + case GT_INIT_VAL: + // Always a passthrough of its child's value. + info->srcCount = 0; + info->dstCount = 0; + break; + case GT_LCLHEAP: TreeNodeInfoInitLclHeap(tree); break; @@ -634,14 +738,20 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) case GT_ARR_OFFSET: // This consumes the offset, if any, the arrObj and the effective index, // and produces the flattened offset for this dimension. - info->srcCount = 3; - info->dstCount = 1; - info->internalIntCount = 1; + info->srcCount = 3; + info->dstCount = 1; + // we don't want to generate code for this if (tree->gtArrOffs.gtOffset->IsIntegralConst(0)) { MakeSrcContained(tree, tree->gtArrOffs.gtOffset); } + else + { + // Here we simply need an internal register, which must be different + // from any of the operand's registers, but may be the same as targetReg. + info->internalIntCount = 1; + } break; case GT_LEA: @@ -725,15 +835,9 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) #endif case GT_CLS_VAR: - info->srcCount = 0; - // GT_CLS_VAR, by the time we reach the backend, must always - // be a pure use. - // It will produce a result of the type of the - // node, and use an internal register for the address. - - info->dstCount = 1; - assert((tree->gtFlags & (GTF_VAR_DEF | GTF_VAR_USEASG | GTF_VAR_USEDEF)) == 0); - info->internalIntCount = 1; + // These nodes are eliminated by rationalizer. + JITDUMP("Unexpected node %s in Lower.\n", GenTree::NodeName(tree->OperGet())); + unreached(); break; } // end switch (tree->OperGet()) @@ -813,27 +917,36 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) } } + TreeNodeInfoInitCheckByteable(tree); + + // We need to be sure that we've set info->srcCount and info->dstCount appropriately + assert((info->dstCount < 2) || (tree->IsMultiRegCall() && info->dstCount == MAX_RET_REG_COUNT)); +} + +//------------------------------------------------------------------------ +// TreeNodeInfoInitCheckByteable: Check the tree to see if "byte-able" registers are +// required, and set the tree node info accordingly. +// +// Arguments: +// tree - The node of interest +// +// Return Value: +// None. +// +void Lowering::TreeNodeInfoInitCheckByteable(GenTree* tree) +{ #ifdef _TARGET_X86_ + LinearScan* l = m_lsra; + TreeNodeInfo* info = &(tree->gtLsraInfo); + // Exclude RBM_NON_BYTE_REGS from dst candidates of tree node and src candidates of operands // if the tree node is a byte type. // - // Example1: GT_STOREIND(byte, addr, op2) - storeind of byte sized value from op2 into mem 'addr' - // Storeind itself will not produce any value and hence dstCount=0. But op2 could be TYP_INT - // value. In this case we need to exclude esi/edi from the src candidates of op2. - // - // Example2: GT_CAST(int <- bool <- int) - here type of GT_CAST node is int and castToType is bool. - // - // Example3: GT_EQ(int, op1 of type ubyte, op2 of type ubyte) - in this case codegen uses - // ubyte as the result of comparison and if the result needs to be materialized into a reg - // simply zero extend it to TYP_INT size. Here is an example of generated code: - // cmp dl, byte ptr[addr mode] - // movzx edx, dl - // // Though this looks conservative in theory, in practice we could not think of a case where // the below logic leads to conservative register specification. In future when or if we find // one such case, this logic needs to be fine tuned for that case(s). - if (varTypeIsByte(tree) || ((tree->OperGet() == GT_CAST) && varTypeIsByte(tree->CastToType())) || - (tree->OperIsCompare() && varTypeIsByte(tree->gtGetOp1()) && varTypeIsByte(tree->gtGetOp2()))) + + if (ExcludeNonByteableRegisters(tree)) { regMaskTP regMask; if (info->dstCount > 0) @@ -870,9 +983,6 @@ void Lowering::TreeNodeInfoInit(GenTree* tree) } } #endif //_TARGET_X86_ - - // We need to be sure that we've set info->srcCount and info->dstCount appropriately - assert((info->dstCount < 2) || (tree->IsMultiRegCall() && info->dstCount == MAX_RET_REG_COUNT)); } //------------------------------------------------------------------------ @@ -1028,6 +1138,31 @@ void Lowering::TreeNodeInfoInitShiftRotate(GenTree* tree) GenTreePtr shiftBy = tree->gtOp.gtOp2; GenTreePtr source = tree->gtOp.gtOp1; +#ifdef _TARGET_X86_ + // The first operand of a GT_LSH_HI and GT_RSH_LO oper is a GT_LONG so that + // we can have a three operand form. Increment the srcCount. + if (tree->OperGet() == GT_LSH_HI || tree->OperGet() == GT_RSH_LO) + { + assert(source->OperGet() == GT_LONG); + + info->srcCount++; + + if (tree->OperGet() == GT_LSH_HI) + { + GenTreePtr sourceLo = source->gtOp.gtOp1; + sourceLo->gtLsraInfo.isDelayFree = true; + } + else + { + GenTreePtr sourceHi = source->gtOp.gtOp2; + sourceHi->gtLsraInfo.isDelayFree = true; + } + + source->gtLsraInfo.hasDelayFreeSrc = true; + info->hasDelayFreeSrc = true; + } +#endif + // x64 can encode 8 bits of shift and it will use 5 or 6. (the others are masked off) // We will allow whatever can be encoded - hope you know what you are doing. if (!IsContainableImmed(tree, shiftBy) || (shiftBy->gtIntConCommon.IconValue() > 255) || @@ -1040,6 +1175,17 @@ void Lowering::TreeNodeInfoInitShiftRotate(GenTree* tree) else { MakeSrcContained(tree, shiftBy); + + // Note that Rotate Left/Right instructions don't set ZF and SF flags. + // + // If the operand being shifted is 32-bits then upper three bits are masked + // by hardware to get actual shift count. Similarly for 64-bit operands + // shift count is narrowed to [0..63]. If the resulting shift count is zero, + // then shift operation won't modify flags. + // + // TODO-CQ-XARCH: We can optimize generating 'test' instruction for GT_EQ/NE(shift, 0) + // if the shift count is known to be non-zero and in the range depending on the + // operand size. } } @@ -1088,6 +1234,12 @@ void Lowering::TreeNodeInfoInitCall(GenTreeCall* call) assert(ctrlExpr == nullptr); assert(call->gtCallAddr != nullptr); ctrlExpr = call->gtCallAddr; + +#ifdef _TARGET_X86_ + // Fast tail calls aren't currently supported on x86, but if they ever are, the code + // below that handles indirect VSD calls will need to be fixed. + assert(!call->IsFastTailCall() || !call->IsVirtualStub()); +#endif // _TARGET_X86_ } // set reg requirements on call target represented as control sequence. @@ -1103,7 +1255,24 @@ void Lowering::TreeNodeInfoInitCall(GenTreeCall* call) // computed into a register. if (!call->IsFastTailCall()) { - if (ctrlExpr->isIndir()) +#ifdef _TARGET_X86_ + // On x86, we need to generate a very specific pattern for indirect VSD calls: + // + // 3-byte nop + // call dword ptr [eax] + // + // Where EAX is also used as an argument to the stub dispatch helper. Make + // sure that the call target address is computed into EAX in this case. + if (call->IsVirtualStub() && (call->gtCallType == CT_INDIRECT)) + { + assert(ctrlExpr->isIndir()); + + ctrlExpr->gtGetOp1()->gtLsraInfo.setSrcCandidates(l, RBM_VIRTUAL_STUB_TARGET); + MakeSrcContained(call, ctrlExpr); + } + else +#endif // _TARGET_X86_ + if (ctrlExpr->isIndir()) { MakeSrcContained(call, ctrlExpr); } @@ -1191,7 +1360,7 @@ void Lowering::TreeNodeInfoInitCall(GenTreeCall* call) // First, count reg args for (GenTreePtr list = call->gtCallLateArgs; list; list = list->MoveNext()) { - assert(list->IsList()); + assert(list->OperIsList()); GenTreePtr argNode = list->Current(); @@ -1206,7 +1375,7 @@ void Lowering::TreeNodeInfoInitCall(GenTreeCall* call) argNode->gtLsraInfo.srcCount = 1; argNode->gtLsraInfo.dstCount = 0; -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING +#ifdef FEATURE_PUT_STRUCT_ARG_STK // If the node is TYP_STRUCT and it is put on stack with // putarg_stk operation, we consume and produce no registers. // In this case the embedded Obj node should not produce @@ -1218,7 +1387,7 @@ void Lowering::TreeNodeInfoInitCall(GenTreeCall* call) argNode->gtOp.gtOp1->gtLsraInfo.dstCount = 0; argNode->gtLsraInfo.srcCount = 0; } -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING +#endif // FEATURE_PUT_STRUCT_ARG_STK continue; } @@ -1248,7 +1417,7 @@ void Lowering::TreeNodeInfoInitCall(GenTreeCall* call) // If the struct arg is wrapped in CPYBLK the type of the param will be TYP_VOID. // Use the curArgTabEntry's isStruct to get whether the param is a struct. - if (varTypeIsStruct(argNode) FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY(|| curArgTabEntry->isStruct)) + if (varTypeIsStruct(argNode) PUT_STRUCT_ARG_STK_ONLY(|| curArgTabEntry->isStruct)) { unsigned originalSize = 0; LclVarDsc* varDsc = nullptr; @@ -1270,16 +1439,16 @@ void Lowering::TreeNodeInfoInitCall(GenTreeCall* call) { originalSize = genTypeSize(argNode->gtType); } - else if (argNode->gtOper == GT_LIST) + else if (argNode->gtOper == GT_FIELD_LIST) { originalSize = 0; // There could be up to 2 PUTARG_REGs in the list - GenTreeArgList* argListPtr = argNode->AsArgList(); - unsigned iterationNum = 0; - for (; argListPtr; argListPtr = argListPtr->Rest()) + GenTreeFieldList* fieldListPtr = argNode->AsFieldList(); + unsigned iterationNum = 0; + for (; fieldListPtr; fieldListPtr = fieldListPtr->Rest()) { - GenTreePtr putArgRegNode = argListPtr->gtOp.gtOp1; + GenTreePtr putArgRegNode = fieldListPtr->Current(); assert(putArgRegNode->gtOper == GT_PUTARG_REG); if (iterationNum == 0) @@ -1509,7 +1678,7 @@ void Lowering::TreeNodeInfoInitBlockStore(GenTreeBlk* blkNode) } m_lsra->clearOperandCounts(source); } - else if (!source->OperIsSIMD()) + else if (!source->IsMultiRegCall() && !source->OperIsSIMD()) { assert(source->IsLocal()); MakeSrcContained(blkNode, source); @@ -1519,7 +1688,11 @@ void Lowering::TreeNodeInfoInitBlockStore(GenTreeBlk* blkNode) if (isInitBlk) { GenTree* initVal = source; - srcAddrOrFill = source; + if (initVal->OperIsInitVal()) + { + initVal = initVal->gtGetOp1(); + } + srcAddrOrFill = initVal; // If we have an InitBlk with constant block size we can optimize several ways: // a) If the size is smaller than a small memory page but larger than INITBLK_UNROLL_LIMIT bytes // we use rep stosb since this reduces the register pressure in LSRA and we have @@ -1571,8 +1744,23 @@ void Lowering::TreeNodeInfoInitBlockStore(GenTreeBlk* blkNode) // a pack of 16 init value constants. blkNode->gtLsraInfo.internalFloatCount = 1; blkNode->gtLsraInfo.setInternalCandidates(l, l->internalFloatRegCandidates()); + if ((fill == 0) && ((size & 0xf) == 0)) + { + MakeSrcContained(blkNode, source); + } } blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindUnroll; + +#ifdef _TARGET_X86_ + if ((size & 1) != 0) + { + // On x86, you can't address the lower byte of ESI, EDI, ESP, or EBP when doing + // a "mov byte ptr [dest], val". If the fill size is odd, we will try to do this + // when unrolling, so only allow byteable registers as the source value. (We could + // consider just using BlkOpKindRepInstr instead.) + sourceRegMask = RBM_BYTE_REGS; + } +#endif // _TARGET_X86_ } else { @@ -1825,7 +2013,7 @@ void Lowering::TreeNodeInfoInitBlockStore(GenTreeBlk* blkNode) } } -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING +#ifdef FEATURE_PUT_STRUCT_ARG_STK //------------------------------------------------------------------------ // TreeNodeInfoInitPutArgStk: Set the NodeInfo for a GT_PUTARG_STK. // @@ -1835,44 +2023,219 @@ void Lowering::TreeNodeInfoInitBlockStore(GenTreeBlk* blkNode) // Return Value: // None. // -void Lowering::TreeNodeInfoInitPutArgStk(GenTree* tree) +void Lowering::TreeNodeInfoInitPutArgStk(GenTreePutArgStk* putArgStk) { - TreeNodeInfo* info = &(tree->gtLsraInfo); + TreeNodeInfo* info = &(putArgStk->gtLsraInfo); LinearScan* l = m_lsra; - if (tree->TypeGet() != TYP_STRUCT) +#ifdef _TARGET_X86_ + if (putArgStk->gtOp1->gtOper == GT_FIELD_LIST) + { + putArgStk->gtNumberReferenceSlots = 0; + putArgStk->gtPutArgStkKind = GenTreePutArgStk::Kind::Invalid; + + GenTreeFieldList* fieldList = putArgStk->gtOp1->AsFieldList(); + + // The code generator will push these fields in reverse order by offset. Reorder the list here s.t. the order + // of uses is visible to LSRA. + unsigned fieldCount = 0; + GenTreeFieldList* head = nullptr; + for (GenTreeFieldList *current = fieldList, *next; current != nullptr; current = next) + { + next = current->Rest(); + + // First, insert the field node into the sorted list. + GenTreeFieldList* prev = nullptr; + for (GenTreeFieldList* cursor = head;; cursor = cursor->Rest()) + { + // If the offset of the current list node is greater than the offset of the cursor or if we have + // reached the end of the list, insert the current node before the cursor and terminate. + if ((cursor == nullptr) || (current->gtFieldOffset > cursor->gtFieldOffset)) + { + if (prev == nullptr) + { + assert(cursor == head); + head = current; + } + else + { + prev->Rest() = current; + } + + current->Rest() = cursor; + break; + } + } + + fieldCount++; + } + + info->srcCount = fieldCount; + info->dstCount = 0; + + // In theory, the upper bound for the size of a field list is 8: these constructs only appear when passing the + // collection of lclVars that represent the fields of a promoted struct lclVar, and we do not promote struct + // lclVars with more than 4 fields. If each of these lclVars is of type long, decomposition will split the + // corresponding field list nodes in two, giving an upper bound of 8. + // + // The reason that this is important is that the algorithm we use above to sort the field list is O(N^2): if + // the maximum size of a field list grows significantly, we will need to reevaluate it. + assert(fieldCount <= 8); + + // The sort above may have changed which node is at the head of the list. Update the PUTARG_STK node if + // necessary. + if (head != fieldList) + { + head->gtFlags |= GTF_FIELD_LIST_HEAD; + fieldList->gtFlags &= ~GTF_FIELD_LIST_HEAD; + +#ifdef DEBUG + head->gtSeqNum = fieldList->gtSeqNum; +#endif // DEBUG + + head->gtLsraInfo = fieldList->gtLsraInfo; + head->gtClearReg(comp); + + BlockRange().InsertAfter(fieldList, head); + BlockRange().Remove(fieldList); + + fieldList = head; + putArgStk->gtOp1 = fieldList; + } + + // Now that the fields have been sorted, initialize the LSRA info. + bool allFieldsAreSlots = true; + bool needsByteTemp = false; + unsigned prevOffset = putArgStk->getArgSize(); + for (GenTreeFieldList* current = fieldList; current != nullptr; current = current->Rest()) + { + GenTree* const fieldNode = current->Current(); + const var_types fieldType = fieldNode->TypeGet(); + const unsigned fieldOffset = current->gtFieldOffset; + assert(fieldType != TYP_LONG); + + // For x86 we must mark all integral fields as contained or reg-optional, and handle them + // accordingly in code generation, since we may have up to 8 fields, which cannot all be in + // registers to be consumed atomically by the call. + if (varTypeIsIntegralOrI(fieldNode)) + { + if (fieldNode->OperGet() == GT_LCL_VAR) + { + LclVarDsc* varDsc = &(comp->lvaTable[fieldNode->AsLclVarCommon()->gtLclNum]); + if (varDsc->lvTracked && !varDsc->lvDoNotEnregister) + { + SetRegOptional(fieldNode); + } + else + { + MakeSrcContained(putArgStk, fieldNode); + } + } + else if (fieldNode->IsIntCnsFitsInI32()) + { + MakeSrcContained(putArgStk, fieldNode); + } + else + { + // For the case where we cannot directly push the value, if we run out of registers, + // it would be better to defer computation until we are pushing the arguments rather + // than spilling, but this situation is not all that common, as most cases of promoted + // structs do not have a large number of fields, and of those most are lclVars or + // copy-propagated constants. + SetRegOptional(fieldNode); + } + } + else + { + assert(varTypeIsFloating(fieldNode)); + } + + // We can treat as a slot any field that is stored at a slot boundary, where the previous + // field is not in the same slot. (Note that we store the fields in reverse order.) + const bool fieldIsSlot = ((fieldOffset % 4) == 0) && ((prevOffset - fieldOffset) >= 4); + if (!fieldIsSlot) + { + allFieldsAreSlots = false; + if (varTypeIsByte(fieldType)) + { + // If this field is a slot--i.e. it is an integer field that is 4-byte aligned and takes up 4 bytes + // (including padding)--we can store the whole value rather than just the byte. Otherwise, we will + // need a byte-addressable register for the store. We will enforce this requirement on an internal + // register, which we can use to copy multiple byte values. + needsByteTemp = true; + } + } + + if (varTypeIsGC(fieldType)) + { + putArgStk->gtNumberReferenceSlots++; + } + + prevOffset = fieldOffset; + } + + // Set the copy kind. + // TODO-X86-CQ: Even if we are using push, if there are contiguous floating point fields, we should + // adjust the stack once for those fields. The latter is really best done in code generation, but + // this tuning should probably be undertaken as a whole. + // Also, if there are floating point fields, it may be better to use the "Unroll" mode + // of copying the struct as a whole, if the fields are not register candidates. + if (allFieldsAreSlots) + { + putArgStk->gtPutArgStkKind = GenTreePutArgStk::Kind::PushAllSlots; + } + else + { + putArgStk->gtPutArgStkKind = GenTreePutArgStk::Kind::Push; + // If any of the fields cannot be stored with an actual push, we may need a temporary + // register to load the value before storing it to the stack location. + info->internalIntCount = 1; + regMaskTP regMask = l->allRegs(TYP_INT); + if (needsByteTemp) + { + regMask &= ~RBM_NON_BYTE_REGS; + } + info->setInternalCandidates(l, regMask); + } + return; + } +#endif // _TARGET_X86_ + +#if defined(FEATURE_SIMD) && defined(_TARGET_X86_) + // For PutArgStk of a TYP_SIMD12, we need an extra register. + if (putArgStk->TypeGet() == TYP_SIMD12) { - TreeNodeInfoInitSimple(tree); + info->srcCount = putArgStk->gtOp1->gtLsraInfo.dstCount; + info->dstCount = 0; + info->internalFloatCount = 1; + info->setInternalCandidates(l, l->allSIMDRegs()); return; } +#endif // defined(FEATURE_SIMD) && defined(_TARGET_X86_) - GenTreePutArgStk* putArgStkTree = tree->AsPutArgStk(); + if (putArgStk->TypeGet() != TYP_STRUCT) + { + TreeNodeInfoInitSimple(putArgStk); + return; + } - GenTreePtr dst = tree; - GenTreePtr src = tree->gtOp.gtOp1; + GenTreePtr dst = putArgStk; + GenTreePtr src = putArgStk->gtOp1; GenTreePtr srcAddr = nullptr; + bool haveLocalAddr = false; if ((src->OperGet() == GT_OBJ) || (src->OperGet() == GT_IND)) { srcAddr = src->gtOp.gtOp1; + assert(srcAddr != nullptr); + haveLocalAddr = srcAddr->OperIsLocalAddr(); } else { - assert(varTypeIsSIMD(tree)); - } - info->srcCount = src->gtLsraInfo.dstCount; - - // If this is a stack variable address, - // make the op1 contained, so this way - // there is no unnecessary copying between registers. - // To avoid assertion, increment the parent's source. - // It is recovered below. - bool haveLocalAddr = ((srcAddr != nullptr) && (srcAddr->OperIsLocalAddr())); - if (haveLocalAddr) - { - info->srcCount += 1; + assert(varTypeIsSIMD(putArgStk)); } + info->srcCount = src->gtLsraInfo.dstCount; info->dstCount = 0; // In case of a CpBlk we could use a helper call. In case of putarg_stk we @@ -1884,7 +2247,7 @@ void Lowering::TreeNodeInfoInitPutArgStk(GenTree* tree) // This threshold will decide from using the helper or let the JIT decide to inline // a code sequence of its choice. ssize_t helperThreshold = max(CPBLK_MOVS_LIMIT, CPBLK_UNROLL_LIMIT); - ssize_t size = putArgStkTree->gtNumSlots * TARGET_POINTER_SIZE; + ssize_t size = putArgStk->gtNumSlots * TARGET_POINTER_SIZE; // TODO-X86-CQ: The helper call either is not supported on x86 or required more work // (I don't know which). @@ -1892,7 +2255,7 @@ void Lowering::TreeNodeInfoInitPutArgStk(GenTree* tree) // If we have a buffer between XMM_REGSIZE_BYTES and CPBLK_UNROLL_LIMIT bytes, we'll use SSE2. // Structs and buffer with sizes <= CPBLK_UNROLL_LIMIT bytes are occurring in more than 95% of // our framework assemblies, so this is the main code generation scheme we'll use. - if (size <= CPBLK_UNROLL_LIMIT && putArgStkTree->gtNumberReferenceSlots == 0) + if (size <= CPBLK_UNROLL_LIMIT && putArgStk->gtNumberReferenceSlots == 0) { // If we have a remainder smaller than XMM_REGSIZE_BYTES, we need an integer temp reg. // @@ -1913,46 +2276,62 @@ void Lowering::TreeNodeInfoInitPutArgStk(GenTree* tree) info->setInternalCandidates(l, regMask); } +#ifdef _TARGET_X86_ + if (size >= 8) +#else // !_TARGET_X86_ if (size >= XMM_REGSIZE_BYTES) +#endif // !_TARGET_X86_ { - // If we have a buffer larger than XMM_REGSIZE_BYTES, - // reserve an XMM register to use it for a + // If we have a buffer larger than or equal to XMM_REGSIZE_BYTES on x64/ux, + // or larger than or equal to 8 bytes on x86, reserve an XMM register to use it for a // series of 16-byte loads and stores. info->internalFloatCount = 1; info->addInternalCandidates(l, l->internalFloatRegCandidates()); } - if (haveLocalAddr) +#ifdef _TARGET_X86_ + if (size < XMM_REGSIZE_BYTES) { - MakeSrcContained(putArgStkTree, srcAddr); + putArgStk->gtPutArgStkKind = GenTreePutArgStk::Kind::Push; } - - // If src or dst are on stack, we don't have to generate the address into a register - // because it's just some constant+SP - putArgStkTree->gtPutArgStkKind = GenTreePutArgStk::PutArgStkKindUnroll; + else +#endif // _TARGET_X86_ + { + putArgStk->gtPutArgStkKind = GenTreePutArgStk::Kind::Unroll; + } + } +#ifdef _TARGET_X86_ + else if (putArgStk->gtNumberReferenceSlots != 0) + { + // On x86, we must use `push` to store GC references to the stack in order for the emitter to properly update + // the function's GC info. These `putargstk` nodes will generate a sequence of `push` instructions. + putArgStk->gtPutArgStkKind = GenTreePutArgStk::Kind::Push; } +#endif // _TARGET_X86_ else { info->internalIntCount += 3; info->setInternalCandidates(l, (RBM_RDI | RBM_RCX | RBM_RSI)); - if (haveLocalAddr) - { - MakeSrcContained(putArgStkTree, srcAddr); - } - putArgStkTree->gtPutArgStkKind = GenTreePutArgStk::PutArgStkKindRepInstr; + putArgStk->gtPutArgStkKind = GenTreePutArgStk::Kind::RepInstr; } // Always mark the OBJ and ADDR as contained trees by the putarg_stk. The codegen will deal with this tree. - MakeSrcContained(putArgStkTree, src); + MakeSrcContained(putArgStk, src); - // Balance up the inc above. if (haveLocalAddr) { - info->srcCount -= 1; + // If the source address is the address of a lclVar, make the source address contained to avoid unnecessary + // copies. + // + // To avoid an assertion in MakeSrcContained, increment the parent's source count beforehand and decrement it + // afterwards. + info->srcCount++; + MakeSrcContained(putArgStk, srcAddr); + info->srcCount--; } } -#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING +#endif // FEATURE_PUT_STRUCT_ARG_STK //------------------------------------------------------------------------ // TreeNodeInfoInitLclHeap: Set the NodeInfo for a GT_LCLHEAP. @@ -1976,13 +2355,17 @@ void Lowering::TreeNodeInfoInitLclHeap(GenTree* tree) // Here '-' means don't care. // // Size? Init Memory? # temp regs - // 0 - 0 - // const and <=6 reg words - 0 - // const and >6 reg words Yes 0 + // 0 - 0 (returns 0) + // const and <=6 reg words - 0 (pushes '0') + // const and >6 reg words Yes 0 (pushes '0') // const and =PageSize No 2 - // Non-const Yes 0 - // Non-const No 2 + // (x86:tmpReg for sutracting from esp) + // const and >=PageSize No 2 (regCnt and tmpReg for subtracing from sp) + // Non-const Yes 0 (regCnt=targetReg and pushes '0') + // Non-const No 2 (regCnt and tmpReg for subtracting from sp) + // + // Note: Here we don't need internal register to be different from targetReg. + // Rather, require it to be different from operand's reg. GenTreePtr size = tree->gtOp.gtOp1; if (size->IsCnsIntOrI()) @@ -2121,6 +2504,9 @@ void Lowering::TreeNodeInfoInitLogicalOp(GenTree* tree) // as reg optional. SetRegOptionalForBinOp(tree); } + + // Codegen of this tree node sets ZF and SF flags. + tree->gtFlags |= GTF_ZSF_SET; } //------------------------------------------------------------------------ @@ -2189,15 +2575,40 @@ void Lowering::TreeNodeInfoInitModDiv(GenTree* tree) info->setDstCandidates(l, RBM_RAX); } - // If possible would like to have op1 in RAX to avoid a register move - op1->gtLsraInfo.setSrcCandidates(l, RBM_RAX); + bool op2CanBeRegOptional = true; +#ifdef _TARGET_X86_ + if (op1->OperGet() == GT_LONG) + { + // To avoid reg move would like to have op1's low part in RAX and high part in RDX. + GenTree* loVal = op1->gtGetOp1(); + GenTree* hiVal = op1->gtGetOp2(); + + // Src count is actually 3, so increment. + assert(op2->IsCnsIntOrI()); + assert(tree->OperGet() == GT_UMOD); + info->srcCount++; + op2CanBeRegOptional = false; + + // This situation also requires an internal register. + info->internalIntCount = 1; + info->setInternalCandidates(l, l->allRegs(TYP_INT)); + + loVal->gtLsraInfo.setSrcCandidates(l, RBM_EAX); + hiVal->gtLsraInfo.setSrcCandidates(l, RBM_EDX); + } + else +#endif + { + // If possible would like to have op1 in RAX to avoid a register move + op1->gtLsraInfo.setSrcCandidates(l, RBM_RAX); + } // divisor can be an r/m, but the memory indirection must be of the same size as the divide if (op2->isMemoryOp() && (op2->TypeGet() == tree->TypeGet())) { MakeSrcContained(tree, op2); } - else + else if (op2CanBeRegOptional) { op2->gtLsraInfo.setSrcCandidates(l, l->allRegs(TYP_INT) & ~(RBM_RAX | RBM_RDX)); @@ -2298,12 +2709,13 @@ void Lowering::TreeNodeInfoInitSIMD(GenTree* tree) info->dstCount = 1; switch (simdTree->gtSIMDIntrinsicID) { + GenTree* op1; GenTree* op2; case SIMDIntrinsicInit: { info->srcCount = 1; - GenTree* op1 = tree->gtOp.gtOp1; + op1 = tree->gtOp.gtOp1; // This sets all fields of a SIMD struct to the given value. // Mark op1 as contained if it is either zero or int constant of all 1's, @@ -2377,7 +2789,8 @@ void Lowering::TreeNodeInfoInitSIMD(GenTree* tree) info->srcCount = 2; // SSE2 32-bit integer multiplication requires two temp regs - if (simdTree->gtSIMDIntrinsicID == SIMDIntrinsicMul && simdTree->gtSIMDBaseType == TYP_INT) + if (simdTree->gtSIMDIntrinsicID == SIMDIntrinsicMul && simdTree->gtSIMDBaseType == TYP_INT && + comp->getSIMDInstructionSet() == InstructionSet_SSE2) { info->internalFloatCount = 2; info->setInternalCandidates(lsra, lsra->allSIMDRegs()); @@ -2406,38 +2819,78 @@ void Lowering::TreeNodeInfoInitSIMD(GenTree* tree) case SIMDIntrinsicOpEquality: case SIMDIntrinsicOpInEquality: - // Need two SIMD registers as scratch. - // See genSIMDIntrinsicRelOp() for details on code sequence generate and - // the need for two scratch registers. - info->srcCount = 2; - info->internalFloatCount = 2; - info->setInternalCandidates(lsra, lsra->allSIMDRegs()); + info->srcCount = 2; + + // On SSE4/AVX, we can generate optimal code for (in)equality + // against zero using ptest. We can safely do the this optimization + // for integral vectors but not for floating-point for the reason + // that we have +0.0 and -0.0 and +0.0 == -0.0 + op2 = tree->gtGetOp2(); + if ((comp->getSIMDInstructionSet() >= InstructionSet_SSE3_4) && op2->IsIntegralConstVector(0)) + { + MakeSrcContained(tree, op2); + } + else + { + + // Need one SIMD register as scratch. + // See genSIMDIntrinsicRelOp() for details on code sequence generated and + // the need for one scratch register. + // + // Note these intrinsics produce a BOOL result, hence internal float + // registers reserved are guaranteed to be different from target + // integer register without explicitly specifying. + info->internalFloatCount = 1; + info->setInternalCandidates(lsra, lsra->allSIMDRegs()); + } break; case SIMDIntrinsicDotProduct: - if ((comp->getSIMDInstructionSet() == InstructionSet_SSE2) || - (simdTree->gtOp.gtOp1->TypeGet() == TYP_SIMD32)) + // Float/Double vectors: + // For SSE, or AVX with 32-byte vectors, we also need an internal register + // as scratch. Further we need the targetReg and internal reg to be distinct + // registers. Note that if this is a TYP_SIMD16 or smaller on AVX, then we + // don't need a tmpReg. + // + // 32-byte integer vector on SSE4/AVX: + // will take advantage of phaddd, which operates only on 128-bit xmm reg. + // This will need 1 (in case of SSE4) or 2 (in case of AVX) internal + // registers since targetReg is an int type register. + // + // See genSIMDIntrinsicDotProduct() for details on code sequence generated + // and the need for scratch registers. + if (varTypeIsFloating(simdTree->gtSIMDBaseType)) { - // For SSE, or AVX with 32-byte vectors, we also need an internal register as scratch. - // Further we need the targetReg and internal reg to be distinct registers. - // This is achieved by requesting two internal registers; thus one of them - // will be different from targetReg. - // Note that if this is a TYP_SIMD16 or smaller on AVX, then we don't need a tmpReg. - // - // See genSIMDIntrinsicDotProduct() for details on code sequence generated and - // the need for scratch registers. - info->internalFloatCount = 2; + if ((comp->getSIMDInstructionSet() == InstructionSet_SSE2) || + (simdTree->gtOp.gtOp1->TypeGet() == TYP_SIMD32)) + { + info->internalFloatCount = 1; + info->isInternalRegDelayFree = true; + info->setInternalCandidates(lsra, lsra->allSIMDRegs()); + } + // else don't need scratch reg(s). + } + else + { + assert(simdTree->gtSIMDBaseType == TYP_INT && comp->getSIMDInstructionSet() >= InstructionSet_SSE3_4); + + // No need to set isInternalRegDelayFree since targetReg is a + // an int type reg and guaranteed to be different from xmm/ymm + // regs. + info->internalFloatCount = comp->canUseAVX() ? 2 : 1; info->setInternalCandidates(lsra, lsra->allSIMDRegs()); } info->srcCount = 2; break; case SIMDIntrinsicGetItem: + { // This implements get_Item method. The sources are: // - the source SIMD struct // - index (which element to get) // The result is baseType of SIMD struct. info->srcCount = 2; + op1 = tree->gtOp.gtOp1; op2 = tree->gtOp.gtOp2; // If the index is a constant, mark it as contained. @@ -2446,48 +2899,69 @@ void Lowering::TreeNodeInfoInitSIMD(GenTree* tree) info->srcCount = 1; } - // If the index is not a constant, we will use the SIMD temp location to store the vector. - // Otherwise, if the baseType is floating point, the targetReg will be a xmm reg and we - // can use that in the process of extracting the element. - // - // If the index is a constant and base type is a small int we can use pextrw, but on AVX - // we will need a temp if are indexing into the upper half of the AVX register. - // In all other cases with constant index, we need a temp xmm register to extract the - // element if index is other than zero. - - if (!op2->IsCnsIntOrI()) + if (op1->isMemoryOp()) { - (void)comp->getSIMDInitTempVarNum(); + MakeSrcContained(tree, op1); + + // Although GT_IND of TYP_SIMD12 reserves an internal float + // register for reading 4 and 8 bytes from memory and + // assembling them into target XMM reg, it is not required + // in this case. + op1->gtLsraInfo.internalIntCount = 0; + op1->gtLsraInfo.internalFloatCount = 0; } - else if (!varTypeIsFloating(simdTree->gtSIMDBaseType)) + else { - bool needFloatTemp; - if (varTypeIsSmallInt(simdTree->gtSIMDBaseType) && - (comp->getSIMDInstructionSet() == InstructionSet_AVX)) - { - int byteShiftCnt = (int)op2->AsIntCon()->gtIconVal * genTypeSize(simdTree->gtSIMDBaseType); - needFloatTemp = (byteShiftCnt >= 16); - } - else + // If the index is not a constant, we will use the SIMD temp location to store the vector. + // Otherwise, if the baseType is floating point, the targetReg will be a xmm reg and we + // can use that in the process of extracting the element. + // + // If the index is a constant and base type is a small int we can use pextrw, but on AVX + // we will need a temp if are indexing into the upper half of the AVX register. + // In all other cases with constant index, we need a temp xmm register to extract the + // element if index is other than zero. + + if (!op2->IsCnsIntOrI()) { - needFloatTemp = !op2->IsIntegralConst(0); + (void)comp->getSIMDInitTempVarNum(); } - if (needFloatTemp) + else if (!varTypeIsFloating(simdTree->gtSIMDBaseType)) { - info->internalFloatCount = 1; - info->setInternalCandidates(lsra, lsra->allSIMDRegs()); + bool needFloatTemp; + if (varTypeIsSmallInt(simdTree->gtSIMDBaseType) && + (comp->getSIMDInstructionSet() == InstructionSet_AVX)) + { + int byteShiftCnt = (int)op2->AsIntCon()->gtIconVal * genTypeSize(simdTree->gtSIMDBaseType); + needFloatTemp = (byteShiftCnt >= 16); + } + else + { + needFloatTemp = !op2->IsIntegralConst(0); + } + + if (needFloatTemp) + { + info->internalFloatCount = 1; + info->setInternalCandidates(lsra, lsra->allSIMDRegs()); + } } } - break; + } + break; case SIMDIntrinsicSetX: case SIMDIntrinsicSetY: case SIMDIntrinsicSetZ: case SIMDIntrinsicSetW: - // We need an internal integer register - info->srcCount = 2; - info->internalIntCount = 1; - info->setInternalCandidates(lsra, lsra->allRegs(TYP_INT)); + info->srcCount = 2; + + // We need an internal integer register for SSE2 codegen + if (comp->getSIMDInstructionSet() == InstructionSet_SSE2) + { + info->internalIntCount = 1; + info->setInternalCandidates(lsra, lsra->allRegs(TYP_INT)); + } + break; case SIMDIntrinsicCast: @@ -2592,6 +3066,8 @@ void Lowering::TreeNodeInfoInitCast(GenTree* tree) { if (genTypeSize(castOpType) == 8) { + // Here we don't need internal register to be different from targetReg, + // rather require it to be different from operand's reg. info->internalIntCount = 1; } } @@ -2693,7 +3169,6 @@ void Lowering::SetIndirAddrOpCounts(GenTreePtr indirTree) GenTreePtr index = nullptr; unsigned mul, cns; bool rev; - bool modifiedSources = false; #ifdef FEATURE_SIMD // If indirTree is of TYP_SIMD12, don't mark addr as contained @@ -2711,11 +3186,10 @@ void Lowering::SetIndirAddrOpCounts(GenTreePtr indirTree) info->internalFloatCount = 1; // In case of GT_IND we need an internal register different from targetReg and - // both of the registers are used at the same time. This achieved by reserving - // two internal registers + // both of the registers are used at the same time. if (indirTree->OperGet() == GT_IND) { - (info->internalFloatCount)++; + info->isInternalRegDelayFree = true; } info->setInternalCandidates(m_lsra, m_lsra->allSIMDRegs()); @@ -2724,16 +3198,21 @@ void Lowering::SetIndirAddrOpCounts(GenTreePtr indirTree) } #endif // FEATURE_SIMD - // These nodes go into an addr mode: - // - GT_CLS_VAR_ADDR turns into a constant. - // - GT_LCL_VAR_ADDR is a stack addr mode. - if ((addr->OperGet() == GT_CLS_VAR_ADDR) || (addr->OperGet() == GT_LCL_VAR_ADDR)) + if ((indirTree->gtFlags & GTF_IND_REQ_ADDR_IN_REG) != 0) { + // The address of an indirection that requires its address in a reg. + // Skip any further processing that might otherwise make it contained. + } + else if ((addr->OperGet() == GT_CLS_VAR_ADDR) || (addr->OperGet() == GT_LCL_VAR_ADDR)) + { + // These nodes go into an addr mode: + // - GT_CLS_VAR_ADDR turns into a constant. + // - GT_LCL_VAR_ADDR is a stack addr mode. + // make this contained, it turns into a constant that goes into an addr mode MakeSrcContained(indirTree, addr); } - else if (addr->IsCnsIntOrI() && addr->AsIntConCommon()->FitsInAddrBase(comp) && - addr->gtLsraInfo.getDstCandidates(m_lsra) != RBM_VIRTUAL_STUB_PARAM) + else if (addr->IsCnsIntOrI() && addr->AsIntConCommon()->FitsInAddrBase(comp)) { // Amd64: // We can mark any pc-relative 32-bit addr as containable, except for a direct VSD call address. @@ -2755,17 +3234,10 @@ void Lowering::SetIndirAddrOpCounts(GenTreePtr indirTree) } else if ((addr->OperGet() == GT_LEA) && IsSafeToContainMem(indirTree, addr)) { - GenTreeAddrMode* lea = addr->AsAddrMode(); - base = lea->Base(); - index = lea->Index(); - - m_lsra->clearOperandCounts(addr); - // The srcCount is decremented because addr is now "contained", - // then we account for the base and index below, if they are non-null. - info->srcCount--; + MakeSrcContained(indirTree, addr); } else if (comp->codeGen->genCreateAddrMode(addr, -1, true, 0, &rev, &base, &index, &mul, &cns, true /*nogen*/) && - !(modifiedSources = AreSourcesPossiblyModifiedLocals(indirTree, base, index))) + !AreSourcesPossiblyModifiedLocals(indirTree, base, index)) { // An addressing mode will be constructed that may cause some // nodes to not need a register, and cause others' lifetimes to be extended @@ -2774,7 +3246,16 @@ void Lowering::SetIndirAddrOpCounts(GenTreePtr indirTree) assert(base != addr); m_lsra->clearOperandCounts(addr); - GenTreePtr arrLength = nullptr; + const bool hasBase = base != nullptr; + const bool hasIndex = index != nullptr; + assert(hasBase || hasIndex); // At least one of a base or an index must be present. + + // If the addressing mode has both a base and an index, bump its source count by one. If it only has one or the + // other, its source count is already correct (due to the source for the address itself). + if (hasBase && hasIndex) + { + info->srcCount++; + } // Traverse the computation below GT_IND to find the operands // for the addressing mode, marking the various constants and @@ -2784,14 +3265,13 @@ void Lowering::SetIndirAddrOpCounts(GenTreePtr indirTree) // up of simple arithmetic operators, and the code generator // only traverses one leg of each node. - bool foundBase = (base == nullptr); - bool foundIndex = (index == nullptr); - GenTreePtr nextChild = nullptr; - for (GenTreePtr child = addr; child != nullptr && !child->OperIsLeaf(); child = nextChild) + bool foundBase = !hasBase; + bool foundIndex = !hasIndex; + for (GenTree *child = addr, *nextChild = nullptr; child != nullptr && !child->OperIsLeaf(); child = nextChild) { - nextChild = nullptr; - GenTreePtr op1 = child->gtOp.gtOp1; - GenTreePtr op2 = (child->OperIsBinary()) ? child->gtOp.gtOp2 : nullptr; + nextChild = nullptr; + GenTree* op1 = child->gtOp.gtOp1; + GenTree* op2 = (child->OperIsBinary()) ? child->gtOp.gtOp2 : nullptr; if (op1 == base) { @@ -2832,7 +3312,6 @@ void Lowering::SetIndirAddrOpCounts(GenTreePtr indirTree) } } assert(foundBase && foundIndex); - info->srcCount--; // it gets incremented below. } else if (addr->gtOper == GT_ARR_ELEM) { @@ -2845,32 +3324,23 @@ void Lowering::SetIndirAddrOpCounts(GenTreePtr indirTree) assert(addr->gtLsraInfo.srcCount >= 2); addr->gtLsraInfo.srcCount -= 1; } - else - { - // it is nothing but a plain indir - info->srcCount--; // base gets added in below - base = addr; - } - - if (base != nullptr) - { - info->srcCount++; - } - - if (index != nullptr && !modifiedSources) - { - info->srcCount++; - } } -void Lowering::LowerCmp(GenTreePtr tree) +void Lowering::TreeNodeInfoInitCmp(GenTreePtr tree) { + assert(tree->OperIsCompare()); + TreeNodeInfo* info = &(tree->gtLsraInfo); info->srcCount = 2; info->dstCount = 1; #ifdef _TARGET_X86_ + // If the compare is used by a jump, we just need to set the condition codes. If not, then we need + // to store the result into the low byte of a register, which requires the dst be a byteable register. + // We always set the dst candidates, though, because if this is compare is consumed by a jump, they + // won't be used. We might be able to use GTF_RELOP_JMP_USED to determine this case, but it's not clear + // that flag is maintained until this location (especially for decomposed long compares). info->setDstCandidates(m_lsra, RBM_BYTE_REGS); #endif // _TARGET_X86_ @@ -2894,9 +3364,9 @@ void Lowering::LowerCmp(GenTreePtr tree) #endif // !defined(_TARGET_64BIT_) // If either of op1 or op2 is floating point values, then we need to use - // ucomiss or ucomisd to compare, both of which support the following form - // ucomis[s|d] xmm, xmm/mem. That is only the second operand can be a memory - // op. + // ucomiss or ucomisd to compare, both of which support the following form: + // ucomis[s|d] xmm, xmm/mem + // That is only the second operand can be a memory op. // // Second operand is a memory Op: Note that depending on comparison operator, // the operands of ucomis[s|d] need to be reversed. Therefore, either op1 or @@ -2952,16 +3422,9 @@ void Lowering::LowerCmp(GenTreePtr tree) bool hasShortCast = false; if (CheckImmedAndMakeContained(tree, op2)) { - bool op1CanBeContained = (op1Type == op2Type); - if (!op1CanBeContained) - { - if (genTypeSize(op1Type) == genTypeSize(op2Type)) - { - // The constant is of the correct size, but we don't have an exact type match - // We can treat the isMemoryOp as "contained" - op1CanBeContained = true; - } - } + // If the types are the same, or if the constant is of the correct size, + // we can treat the isMemoryOp as contained. + bool op1CanBeContained = (genTypeSize(op1Type) == genTypeSize(op2Type)); // Do we have a short compare against a constant in op2 // @@ -3031,13 +3494,13 @@ void Lowering::LowerCmp(GenTreePtr tree) bool op1IsMadeContained = false; // When op1 is a GT_AND we can often generate a single "test" instruction - // instead of two instructions (an "and" instruction followed by a "cmp"/"test") + // instead of two instructions (an "and" instruction followed by a "cmp"/"test"). // - // This instruction can only be used for equality or inequality comparions. + // This instruction can only be used for equality or inequality comparisons. // and we must have a compare against zero. // // If we have a postive test for a single bit we can reverse the condition and - // make the compare be against zero + // make the compare be against zero. // // Example: // GT_EQ GT_NE @@ -3046,8 +3509,8 @@ void Lowering::LowerCmp(GenTreePtr tree) // / \ / \ // andOp1 GT_CNS (0x100) andOp1 GT_CNS (0x100) // - // We will mark the GT_AND node as contained if the tree is a equality compare with zero - // Additionally when we do this we also allow for a contained memory operand for "andOp1". + // We will mark the GT_AND node as contained if the tree is an equality compare with zero. + // Additionally, when we do this we also allow for a contained memory operand for "andOp1". // bool isEqualityCompare = (tree->gtOper == GT_EQ || tree->gtOper == GT_NE); @@ -3066,7 +3529,7 @@ void Lowering::LowerCmp(GenTreePtr tree) // so that we can generate a test instruction. // Reverse the equality comparison - tree->gtOper = (tree->gtOper == GT_EQ) ? GT_NE : GT_EQ; + tree->SetOperRaw((tree->gtOper == GT_EQ) ? GT_NE : GT_EQ); // Change the relOp2CnsVal to zero relOp2CnsVal = 0; @@ -3171,7 +3634,7 @@ void Lowering::LowerCmp(GenTreePtr tree) genTreeOps castOp1Oper = castOp1->OperGet(); bool safeOper = false; - // It is not always safe to change the gtType of 'castOp1' to TYP_UBYTE + // It is not always safe to change the gtType of 'castOp1' to TYP_UBYTE. // For example when 'castOp1Oper' is a GT_RSZ or GT_RSH then we are shifting // bits from the left into the lower bits. If we change the type to a TYP_UBYTE // we will instead generate a byte sized shift operation: shr al, 24 @@ -3196,22 +3659,24 @@ void Lowering::LowerCmp(GenTreePtr tree) // assert(!castOp1->gtOverflowEx()); // Must not be an overflow checking operation - GenTreePtr removeTreeNode = op1; - tree->gtOp.gtOp1 = castOp1; - op1 = castOp1; - castOp1->gtType = TYP_UBYTE; - - // trim down the value if castOp1 is an int constant since its type changed to UBYTE. - if (castOp1Oper == GT_CNS_INT) - { - castOp1->gtIntCon.gtIconVal = (UINT8)castOp1->gtIntCon.gtIconVal; - } - + // TODO-Cleanup: we're within "if (CheckImmedAndMakeContained(tree, op2))", so isn't + // the following condition always true? if (op2->isContainedIntOrIImmed()) { ssize_t val = (ssize_t)op2->AsIntConCommon()->IconValue(); if (val >= 0 && val <= 255) { + GenTreePtr removeTreeNode = op1; + tree->gtOp.gtOp1 = castOp1; + op1 = castOp1; + castOp1->gtType = TYP_UBYTE; + + // trim down the value if castOp1 is an int constant since its type changed to UBYTE. + if (castOp1Oper == GT_CNS_INT) + { + castOp1->gtIntCon.gtIconVal = (UINT8)castOp1->gtIntCon.gtIconVal; + } + op2->gtType = TYP_UBYTE; tree->gtFlags |= GTF_UNSIGNED; @@ -3222,18 +3687,26 @@ void Lowering::LowerCmp(GenTreePtr tree) MakeSrcContained(tree, op1); op1IsMadeContained = true; } - } - } - BlockRange().Remove(removeTreeNode); + BlockRange().Remove(removeTreeNode); + + // We've changed the type on op1 to TYP_UBYTE, but we already processed that node. + // We need to go back and mark it byteable. + // TODO-Cleanup: it might be better to move this out of the TreeNodeInfoInit pass to + // the earlier "lower" pass, in which case the byteable check would just fall out. + // But that is quite complex! + TreeNodeInfoInitCheckByteable(op1); + #ifdef DEBUG - if (comp->verbose) - { - printf("LowerCmp: Removing a GT_CAST to TYP_UBYTE and changing castOp1->gtType to " - "TYP_UBYTE\n"); - comp->gtDispTreeRange(BlockRange(), tree); - } + if (comp->verbose) + { + printf("TreeNodeInfoInitCmp: Removing a GT_CAST to TYP_UBYTE and changing " + "castOp1->gtType to TYP_UBYTE\n"); + comp->gtDispTreeRange(BlockRange(), tree); + } #endif + } + } } } @@ -3241,6 +3714,41 @@ void Lowering::LowerCmp(GenTreePtr tree) if (!op1IsMadeContained) { SetRegOptional(op1); + + // If op1 codegen sets ZF and SF flags and ==/!= against + // zero, we don't need to generate test instruction, + // provided we don't have another GenTree node between op1 + // and tree that could potentially modify flags. + // + // TODO-CQ: right now the below peep is inexpensive and + // gets the benefit in most of cases because in majority + // of cases op1, op2 and tree would be in that order in + // execution. In general we should be able to check that all + // the nodes that come after op1 in execution order do not + // modify the flags so that it is safe to avoid generating a + // test instruction. Such a check requires that on each + // GenTree node we need to set the info whether its codegen + // will modify flags. + // + // TODO-CQ: We can optimize compare against zero in the + // following cases by generating the branch as indicated + // against each case. + // 1) unsigned compare + // < 0 - always FALSE + // <= 0 - ZF=1 and jne + // > 0 - ZF=0 and je + // >= 0 - always TRUE + // + // 2) signed compare + // < 0 - SF=1 and js + // >= 0 - SF=0 and jns + if (isEqualityCompare && op1->gtSetZSFlags() && op2->IsIntegralConst(0) && (op1->gtNext == op2) && + (op2->gtNext == tree)) + { + // Require codegen of op1 to set the flags. + assert(!op1->gtSetFlags()); + op1->gtFlags |= GTF_SET_FLAGS; + } } } } @@ -3255,10 +3763,17 @@ void Lowering::LowerCmp(GenTreePtr tree) { MakeSrcContained(tree, op1); } + else if (op1->IsCnsIntOrI()) + { + // TODO-CQ: We should be able to support swapping op1 and op2 to generate cmp reg, imm, + // but there is currently an assert in CodeGen::genCompareInt(). + // https://github.com/dotnet/coreclr/issues/7270 + SetRegOptional(op2); + } else { // One of op1 or op2 could be marked as reg optional - // to indicate that codgen can still generate code + // to indicate that codegen can still generate code // if one of them is on stack. SetRegOptional(PreferredRegOptionalOperand(tree)); } @@ -3318,7 +3833,6 @@ void Lowering::LowerCast(GenTree* tree) var_types dstType = tree->CastToType(); var_types srcType = op1->TypeGet(); var_types tmpType = TYP_UNDEF; - bool srcUns = false; // force the srcType to unsigned if GT_UNSIGNED flag is set if (tree->gtFlags & GTF_UNSIGNED) @@ -3849,6 +4363,20 @@ bool Lowering::SetStoreIndOpCountsIfRMWMemOp(GenTreePtr storeInd) } m_lsra->clearOperandCounts(indirCandidateChild); +#ifdef _TARGET_X86_ + if (varTypeIsByte(storeInd)) + { + // If storeInd is of TYP_BYTE, set indirOpSources to byteable registers. + bool containedNode = indirOpSource->gtLsraInfo.dstCount == 0; + if (!containedNode) + { + regMaskTP regMask = indirOpSource->gtLsraInfo.getSrcCandidates(m_lsra); + assert(regMask != RBM_NONE); + indirOpSource->gtLsraInfo.setSrcCandidates(m_lsra, regMask & ~RBM_NON_BYTE_REGS); + } + } +#endif + return true; } @@ -3858,8 +4386,11 @@ bool Lowering::SetStoreIndOpCountsIfRMWMemOp(GenTreePtr storeInd) */ void Lowering::SetMulOpCounts(GenTreePtr tree) { +#if defined(_TARGET_X86_) + assert(tree->OperGet() == GT_MUL || tree->OperGet() == GT_MULHI || tree->OperGet() == GT_MUL_LONG); +#else assert(tree->OperGet() == GT_MUL || tree->OperGet() == GT_MULHI); - +#endif TreeNodeInfo* info = &(tree->gtLsraInfo); info->srcCount = 2; @@ -3900,13 +4431,18 @@ void Lowering::SetMulOpCounts(GenTreePtr tree) GenTreeIntConCommon* imm = nullptr; GenTreePtr other = nullptr; - // There are three forms of x86 multiply: - // one-op form: RDX:RAX = RAX * r/m - // two-op form: reg *= r/m - // three-op form: reg = r/m * imm +// There are three forms of x86 multiply: +// one-op form: RDX:RAX = RAX * r/m +// two-op form: reg *= r/m +// three-op form: reg = r/m * imm - // This special widening 32x32->64 MUL is not used on x64 - assert((tree->gtFlags & GTF_MUL_64RSLT) == 0); +// This special widening 32x32->64 MUL is not used on x64 +#if defined(_TARGET_X86_) + if (tree->OperGet() != GT_MUL_LONG) +#endif + { + assert((tree->gtFlags & GTF_MUL_64RSLT) == 0); + } // Multiply should never be using small types assert(!varTypeIsSmall(tree->TypeGet())); @@ -3924,12 +4460,21 @@ void Lowering::SetMulOpCounts(GenTreePtr tree) info->setDstCandidates(m_lsra, RBM_RAX); hasImpliedFirstOperand = true; } - else if (tree->gtOper == GT_MULHI) + else if (tree->OperGet() == GT_MULHI) + { + // Have to use the encoding:RDX:RAX = RAX * rm. Since we only care about the + // upper 32 bits of the result set the destination candidate to REG_RDX. + info->setDstCandidates(m_lsra, RBM_RDX); + hasImpliedFirstOperand = true; + } +#if defined(_TARGET_X86_) + else if (tree->OperGet() == GT_MUL_LONG) { // have to use the encoding:RDX:RAX = RAX * rm info->setDstCandidates(m_lsra, RBM_RAX); hasImpliedFirstOperand = true; } +#endif else if (IsContainableImmed(tree, op2) || IsContainableImmed(tree, op1)) { if (IsContainableImmed(tree, op2)) @@ -4187,6 +4732,71 @@ GenTree* Lowering::PreferredRegOptionalOperand(GenTree* tree) return preferredOp; } +#ifdef _TARGET_X86_ +//------------------------------------------------------------------------ +// ExcludeNonByteableRegisters: Determines if we need to exclude non-byteable registers for +// various reasons +// +// Arguments: +// tree - The node of interest +// +// Return Value: +// If we need to exclude non-byteable registers +// +bool Lowering::ExcludeNonByteableRegisters(GenTree* tree) +{ + // Example1: GT_STOREIND(byte, addr, op2) - storeind of byte sized value from op2 into mem 'addr' + // Storeind itself will not produce any value and hence dstCount=0. But op2 could be TYP_INT + // value. In this case we need to exclude esi/edi from the src candidates of op2. + if (varTypeIsByte(tree)) + { + return true; + } + // Example2: GT_CAST(int <- bool <- int) - here type of GT_CAST node is int and castToType is bool. + else if ((tree->OperGet() == GT_CAST) && varTypeIsByte(tree->CastToType())) + { + return true; + } + else if (tree->OperIsCompare()) + { + GenTree* op1 = tree->gtGetOp1(); + GenTree* op2 = tree->gtGetOp2(); + + // Example3: GT_EQ(int, op1 of type ubyte, op2 of type ubyte) - in this case codegen uses + // ubyte as the result of comparison and if the result needs to be materialized into a reg + // simply zero extend it to TYP_INT size. Here is an example of generated code: + // cmp dl, byte ptr[addr mode] + // movzx edx, dl + if (varTypeIsByte(op1) && varTypeIsByte(op2)) + { + return true; + } + // Example4: GT_EQ(int, op1 of type ubyte, op2 is GT_CNS_INT) - in this case codegen uses + // ubyte as the result of the comparison and if the result needs to be materialized into a reg + // simply zero extend it to TYP_INT size. + else if (varTypeIsByte(op1) && op2->IsCnsIntOrI()) + { + return true; + } + // Example4: GT_EQ(int, op1 is GT_CNS_INT, op2 of type ubyte) - in this case codegen uses + // ubyte as the result of the comparison and if the result needs to be materialized into a reg + // simply zero extend it to TYP_INT size. + else if (op1->IsCnsIntOrI() && varTypeIsByte(op2)) + { + return true; + } + else + { + return false; + } + } + else + { + return false; + } +} +#endif // _TARGET_X86_ + #endif // _TARGET_XARCH_ #endif // !LEGACY_BACKEND diff --git a/src/jit/lsra.cpp b/src/jit/lsra.cpp index 317b976..accfd6e 100644 --- a/src/jit/lsra.cpp +++ b/src/jit/lsra.cpp @@ -355,6 +355,33 @@ RegRecord* LinearScan::getRegisterRecord(regNumber regNum) } #ifdef DEBUG + +//---------------------------------------------------------------------------- +// getConstrainedRegMask: Returns new regMask which is the intersection of +// regMaskActual and regMaskConstraint if the new regMask has at least +// minRegCount registers, otherwise returns regMaskActual. +// +// Arguments: +// regMaskActual - regMask that needs to be constrained +// regMaskConstraint - regMask constraint that needs to be +// applied to regMaskActual +// minRegCount - Minimum number of regs that should be +// be present in new regMask. +// +// Return Value: +// New regMask that has minRegCount registers after instersection. +// Otherwise returns regMaskActual. +regMaskTP LinearScan::getConstrainedRegMask(regMaskTP regMaskActual, regMaskTP regMaskConstraint, unsigned minRegCount) +{ + regMaskTP newMask = regMaskActual & regMaskConstraint; + if (genCountBits(newMask) >= minRegCount) + { + return newMask; + } + + return regMaskActual; +} + //------------------------------------------------------------------------ // stressLimitRegs: Given a set of registers, expressed as a register mask, reduce // them based on the current stress options. @@ -373,38 +400,46 @@ regMaskTP LinearScan::stressLimitRegs(RefPosition* refPosition, regMaskTP mask) { if (getStressLimitRegs() != LSRA_LIMIT_NONE) { + // The refPosition could be null, for example when called + // by getTempRegForResolution(). + int minRegCount = (refPosition != nullptr) ? refPosition->minRegCandidateCount : 1; + switch (getStressLimitRegs()) { case LSRA_LIMIT_CALLEE: - if (!compiler->opts.compDbgEnC && (mask & RBM_CALLEE_SAVED) != RBM_NONE) + if (!compiler->opts.compDbgEnC) { - mask &= RBM_CALLEE_SAVED; + mask = getConstrainedRegMask(mask, RBM_CALLEE_SAVED, minRegCount); } break; + case LSRA_LIMIT_CALLER: - if ((mask & RBM_CALLEE_TRASH) != RBM_NONE) - { - mask &= RBM_CALLEE_TRASH; - } - break; + { + mask = getConstrainedRegMask(mask, RBM_CALLEE_TRASH, minRegCount); + } + break; + case LSRA_LIMIT_SMALL_SET: if ((mask & LsraLimitSmallIntSet) != RBM_NONE) { - mask &= LsraLimitSmallIntSet; + mask = getConstrainedRegMask(mask, LsraLimitSmallIntSet, minRegCount); } else if ((mask & LsraLimitSmallFPSet) != RBM_NONE) { - mask &= LsraLimitSmallFPSet; + mask = getConstrainedRegMask(mask, LsraLimitSmallFPSet, minRegCount); } break; + default: unreached(); } + if (refPosition != nullptr && refPosition->isFixedRegRef) { mask |= refPosition->registerAssignment; } } + return mask; } #endif // DEBUG @@ -658,16 +693,13 @@ void LinearScan::applyCalleeSaveHeuristics(RefPosition* rp) #endif // _TARGET_AMD64_ Interval* theInterval = rp->getInterval(); + #ifdef DEBUG regMaskTP calleeSaveMask = calleeSaveRegs(getRegisterType(theInterval, rp)); if (doReverseCallerCallee()) { - regMaskTP newAssignment = rp->registerAssignment; - newAssignment &= calleeSaveMask; - if (newAssignment != RBM_NONE) - { - rp->registerAssignment = newAssignment; - } + rp->registerAssignment = + getConstrainedRegMask(rp->registerAssignment, calleeSaveMask, rp->minRegCandidateCount); } else #endif // DEBUG @@ -777,6 +809,9 @@ RefPosition* LinearScan::newRefPosition( // mask - Set of valid registers for this RefPosition // multiRegIdx - register position if this RefPosition corresponds to a // multi-reg call node. +// minRegCount - Minimum number registers that needs to be ensured while +// constraining candidates for this ref position under +// LSRA stress. This is a DEBUG only arg. // // Return Value: // a new RefPosition @@ -786,7 +821,8 @@ RefPosition* LinearScan::newRefPosition(Interval* theInterval, RefType theRefType, GenTree* theTreeNode, regMaskTP mask, - unsigned multiRegIdx /* = 0 */) + unsigned multiRegIdx /* = 0 */ + DEBUGARG(unsigned minRegCandidateCount /* = 1 */)) { #ifdef DEBUG if (theInterval != nullptr && regType(theInterval->registerType) == FloatRegisterType) @@ -843,6 +879,10 @@ RefPosition* LinearScan::newRefPosition(Interval* theInterval, newRP->setMultiRegIdx(multiRegIdx); newRP->setAllocateIfProfitable(0); +#ifdef DEBUG + newRP->minRegCandidateCount = minRegCandidateCount; +#endif // DEBUG + associateRefPosWithInterval(newRP); DBEXEC(VERBOSE, newRP->dump()); @@ -1071,12 +1111,14 @@ LinearScan::LinearScan(Compiler* theCompiler) #endif dumpTerse = (JitConfig.JitDumpTerseLsra() != 0); - #endif // DEBUG + availableIntRegs = (RBM_ALLINT & ~compiler->codeGen->regSet.rsMaskResvd); + #if ETW_EBP_FRAMED availableIntRegs &= ~RBM_FPBASE; #endif // ETW_EBP_FRAMED + availableFloatRegs = RBM_ALLFLOAT; availableDoubleRegs = RBM_ALLDOUBLE; @@ -1272,6 +1314,7 @@ void LinearScan::setBlockSequence() bool addedInternalBlocks = false; verifiedAllBBs = false; + hasCriticalEdges = false; BasicBlock* nextBlock; for (BasicBlock* block = compiler->fgFirstBB; block != nullptr; block = nextBlock) { @@ -1288,6 +1331,13 @@ void LinearScan::setBlockSequence() blockInfo[block->bbNum].hasCriticalOutEdge = false; blockInfo[block->bbNum].weight = block->bbWeight; +#if TRACK_LSRA_STATS + blockInfo[block->bbNum].spillCount = 0; + blockInfo[block->bbNum].copyRegCount = 0; + blockInfo[block->bbNum].resolutionMovCount = 0; + blockInfo[block->bbNum].splitEdgeCount = 0; +#endif // TRACK_LSRA_STATS + if (block->GetUniquePred(compiler) == nullptr) { for (flowList* pred = block->bbPreds; pred != nullptr; pred = pred->flNext) @@ -1296,6 +1346,7 @@ void LinearScan::setBlockSequence() if (predBlock->NumSucc(compiler) > 1) { blockInfo[block->bbNum].hasCriticalInEdge = true; + hasCriticalEdges = true; break; } else if (predBlock->bbJumpKind == BBJ_SWITCH) @@ -1321,6 +1372,7 @@ void LinearScan::setBlockSequence() if (checkForCriticalOutEdge && succ->GetUniquePred(compiler) == nullptr) { blockInfo[block->bbNum].hasCriticalOutEdge = true; + hasCriticalEdges = true; // We can stop checking now. checkForCriticalOutEdge = false; } @@ -1666,11 +1718,6 @@ void LinearScan::doLinearScan() compiler->codeGen->regSet.rsClearRegsModified(); - // Figure out if we're going to use an RSP frame or an RBP frame. We need to do this - // before building the intervals and ref positions, because those objects will embed - // RBP in various register masks (like preferences) if RBP is allowed to be allocated. - setFrameType(); - initMaxSpill(); buildIntervals(); DBEXEC(VERBOSE, TupleStyleDump(LSRA_DUMP_REFPOS)); @@ -1685,6 +1732,17 @@ void LinearScan::doLinearScan() resolveRegisters(); compiler->EndPhase(PHASE_LINEAR_SCAN_RESOLVE); +#if TRACK_LSRA_STATS + if ((JitConfig.DisplayLsraStats() != 0) +#ifdef DEBUG + || VERBOSE +#endif + ) + { + dumpLsraStats(jitstdout); + } +#endif // TRACK_LSRA_STATS + DBEXEC(VERBOSE, TupleStyleDump(LSRA_DUMP_POST)); compiler->compLSRADone = true; @@ -1892,6 +1950,8 @@ void LinearScan::identifyCandidates() // for vectors on Arm64, though the actual value may differ. VarSetOps::AssignNoCopy(compiler, fpCalleeSaveCandidateVars, VarSetOps::MakeEmpty(compiler)); + VarSetOps::AssignNoCopy(compiler, resolutionCandidateVars, VarSetOps::MakeEmpty(compiler)); + VarSetOps::AssignNoCopy(compiler, splitOrSpilledVars, VarSetOps::MakeEmpty(compiler)); VARSET_TP VARSET_INIT_NOCOPY(fpMaybeCandidateVars, VarSetOps::MakeEmpty(compiler)); unsigned int floatVarCount = 0; unsigned int thresholdFPRefCntWtd = 4 * BB_UNITY_WEIGHT; @@ -1902,6 +1962,37 @@ void LinearScan::identifyCandidates() unsigned int largeVectorVarCount = 0; unsigned int thresholdLargeVectorRefCntWtd = 4 * BB_UNITY_WEIGHT; #endif // FEATURE_PARTIAL_SIMD_CALLEE_SAVE +#if DOUBLE_ALIGN + unsigned refCntStk = 0; + unsigned refCntReg = 0; + unsigned refCntWtdReg = 0; + unsigned refCntStkParam = 0; // sum of ref counts for all stack based parameters + unsigned refCntWtdStkDbl = 0; // sum of wtd ref counts for stack based doubles + doDoubleAlign = false; + bool checkDoubleAlign = true; + if (compiler->codeGen->isFramePointerRequired() || compiler->opts.MinOpts()) + { + checkDoubleAlign = false; + } + else + { + switch (compiler->getCanDoubleAlign()) + { + case MUST_DOUBLE_ALIGN: + doDoubleAlign = true; + checkDoubleAlign = false; + break; + case CAN_DOUBLE_ALIGN: + break; + case CANT_DOUBLE_ALIGN: + doDoubleAlign = false; + checkDoubleAlign = false; + break; + default: + unreached(); + } + } +#endif // DOUBLE_ALIGN for (lclNum = 0, varDsc = compiler->lvaTable; lclNum < compiler->lvaCount; lclNum++, varDsc++) { @@ -1911,6 +2002,32 @@ void LinearScan::identifyCandidates() Interval* newInt = newInterval(intervalType); newInt->setLocalNumber(lclNum, this); + +#if DOUBLE_ALIGN + if (checkDoubleAlign) + { + if (varDsc->lvIsParam && !varDsc->lvIsRegArg) + { + refCntStkParam += varDsc->lvRefCnt; + } + else if (!isRegCandidate(varDsc) || varDsc->lvDoNotEnregister) + { + refCntStk += varDsc->lvRefCnt; + if ((varDsc->lvType == TYP_DOUBLE) || + ((varTypeIsStruct(varDsc) && varDsc->lvStructDoubleAlign && + (compiler->lvaGetPromotionType(varDsc) != Compiler::PROMOTION_TYPE_INDEPENDENT)))) + { + refCntWtdStkDbl += varDsc->lvRefCntWtd; + } + } + else + { + refCntReg += varDsc->lvRefCnt; + refCntWtdReg += varDsc->lvRefCntWtd; + } + } +#endif // DOUBLE_ALIGN + if (varDsc->lvIsStructField) { newInt->isStructField = true; @@ -2095,6 +2212,24 @@ void LinearScan::identifyCandidates() } } +#if DOUBLE_ALIGN + if (checkDoubleAlign) + { + // TODO-CQ: Fine-tune this: + // In the legacy reg predictor, this runs after allocation, and then demotes any lclVars + // allocated to the frame pointer, which is probably the wrong order. + // However, because it runs after allocation, it can determine the impact of demoting + // the lclVars allocated to the frame pointer. + // => Here, estimate of the EBP refCnt and weighted refCnt is a wild guess. + // + unsigned refCntEBP = refCntReg / 8; + unsigned refCntWtdEBP = refCntWtdReg / 8; + + doDoubleAlign = + compiler->shouldDoubleAlign(refCntStk, refCntEBP, refCntWtdEBP, refCntStkParam, refCntWtdStkDbl); + } +#endif // DOUBLE_ALIGN + // The factors we consider to determine which set of fp vars to use as candidates for callee save // registers current include the number of fp vars, whether there are loops, and whether there are // multiple exits. These have been selected somewhat empirically, but there is probably room for @@ -2510,6 +2645,9 @@ regMaskTP LinearScan::getKillSetForNode(GenTree* tree) break; case GT_MULHI: +#if defined(_TARGET_X86_) && !defined(LEGACY_BACKEND) + case GT_MUL_LONG: +#endif killMask = RBM_RAX | RBM_RDX; break; @@ -2644,7 +2782,7 @@ regMaskTP LinearScan::getKillSetForNode(GenTree* tree) } break; -#if defined(PROFILING_SUPPORTED) && defined(_TARGET_AMD64_) +#if defined(PROFILING_SUPPORTED) // If this method requires profiler ELT hook then mark these nodes as killing // callee trash registers (excluding RAX and XMM0). The reason for this is that // profiler callback would trash these registers. See vm\amd64\asmhelpers.asm for @@ -2660,10 +2798,9 @@ regMaskTP LinearScan::getKillSetForNode(GenTree* tree) if (compiler->compIsProfilerHookNeeded()) { killMask = compiler->compHelperCallKillSet(CORINFO_HELP_PROF_FCN_TAILCALL); - ; } break; -#endif // PROFILING_SUPPORTED && _TARGET_AMD64_ +#endif // PROFILING_SUPPORTED default: // for all other 'tree->OperGet()' kinds, leave 'killMask' = RBM_NONE @@ -2769,19 +2906,46 @@ bool LinearScan::buildKillPositionsForNode(GenTree* tree, LsraLocation currentLo return false; } +//---------------------------------------------------------------------------- +// defineNewInternalTemp: Defines a ref position for an internal temp. +// +// Arguments: +// tree - Gentree node requiring an internal register +// regType - Register type +// currentLoc - Location of the temp Def position +// regMask - register mask of candidates for temp +// minRegCandidateCount - Minimum registers to be ensured in candidate +// set under LSRA stress mode. This is a +// DEBUG only arg. RefPosition* LinearScan::defineNewInternalTemp(GenTree* tree, RegisterType regType, LsraLocation currentLoc, - regMaskTP regMask) + regMaskTP regMask DEBUGARG(unsigned minRegCandidateCount)) { Interval* current = newInterval(regType); current->isInternal = true; - return newRefPosition(current, currentLoc, RefTypeDef, tree, regMask); + return newRefPosition(current, currentLoc, RefTypeDef, tree, regMask, 0 DEBUG_ARG(minRegCandidateCount)); } +//------------------------------------------------------------------------ +// buildInternalRegisterDefsForNode - build Def positions for internal +// registers required for tree node. +// +// Arguments: +// tree - Gentree node that needs internal registers +// currentLoc - Location at which Def positions need to be defined +// temps - in-out array which is populated with ref positions +// created for Def of internal registers +// minRegCandidateCount - Minimum registers to be ensured in candidate +// set of ref positions under LSRA stress. This is +// a DEBUG only arg. +// +// Returns: +// The total number of Def positions created for internal registers of tree node. int LinearScan::buildInternalRegisterDefsForNode(GenTree* tree, LsraLocation currentLoc, - RefPosition* temps[]) // populates + RefPosition* temps[] // populates + DEBUGARG(unsigned minRegCandidateCount)) { int count; int internalIntCount = tree->gtLsraInfo.internalIntCount; @@ -2805,14 +2969,16 @@ int LinearScan::buildInternalRegisterDefsForNode(GenTree* tree, internalIntCands = genFindLowestBit(internalIntCands); internalCands &= ~internalIntCands; } - temps[count] = defineNewInternalTemp(tree, IntRegisterType, currentLoc, internalIntCands); + temps[count] = + defineNewInternalTemp(tree, IntRegisterType, currentLoc, internalIntCands DEBUG_ARG(minRegCandidateCount)); } int internalFloatCount = tree->gtLsraInfo.internalFloatCount; for (int i = 0; i < internalFloatCount; i++) { regMaskTP internalFPCands = (internalCands & internalFloatRegCandidates()); - temps[count++] = defineNewInternalTemp(tree, FloatRegisterType, currentLoc, internalFPCands); + temps[count++] = + defineNewInternalTemp(tree, FloatRegisterType, currentLoc, internalFPCands DEBUG_ARG(minRegCandidateCount)); } noway_assert(count < MaxInternalRegisters); @@ -2820,10 +2986,26 @@ int LinearScan::buildInternalRegisterDefsForNode(GenTree* tree, return count; } +//------------------------------------------------------------------------ +// buildInternalRegisterUsesForNode - adds Use positions for internal +// registers required for tree node. +// +// Arguments: +// tree - Gentree node that needs internal registers +// currentLoc - Location at which Use positions need to be defined +// defs - int array containing Def positions of internal +// registers. +// total - Total number of Def positions in 'defs' array. +// minRegCandidateCount - Minimum registers to be ensured in candidate +// set of ref positions under LSRA stress. This is +// a DEBUG only arg. +// +// Returns: +// Void. void LinearScan::buildInternalRegisterUsesForNode(GenTree* tree, LsraLocation currentLoc, RefPosition* defs[], - int total) + int total DEBUGARG(unsigned minRegCandidateCount)) { assert(total < MaxInternalRegisters); @@ -2840,8 +3022,14 @@ void LinearScan::buildInternalRegisterUsesForNode(GenTree* tree, } else { - RefPosition* newest = newRefPosition(defs[i]->getInterval(), currentLoc, RefTypeUse, tree, mask); - newest->lastUse = true; + RefPosition* newest = newRefPosition(defs[i]->getInterval(), currentLoc, RefTypeUse, tree, mask, + 0 DEBUG_ARG(minRegCandidateCount)); + newest->lastUse = true; + + if (tree->gtLsraInfo.isInternalRegDelayFree) + { + newest->delayRegFree = true; + } } } } @@ -3196,10 +3384,10 @@ static int ComputeOperandDstCount(GenTree* operand) // If an operand has no destination registers but does have source registers, it must be a store // or a compare. assert(operand->OperIsStore() || operand->OperIsBlkOp() || operand->OperIsPutArgStk() || - operand->OperIsCompare()); + operand->OperIsCompare() || operand->IsSIMDEqualityOrInequality()); return 0; } - else if (!operand->OperIsAggregate() && (operand->OperIsStore() || operand->TypeGet() == TYP_VOID)) + else if (!operand->OperIsFieldListHead() && (operand->OperIsStore() || operand->TypeGet() == TYP_VOID)) { // Stores and void-typed operands may be encountered when processing call nodes, which contain // pointers to argument setup stores. @@ -3207,7 +3395,7 @@ static int ComputeOperandDstCount(GenTree* operand) } else { - // If an aggregate or non-void-typed operand is not an unsued value and does not have source registers, + // If a field list or non-void-typed operand is not an unused value and does not have source registers, // that argument is contained within its parent and produces `sum(operand_dst_count)` registers. int dstCount = 0; for (GenTree* op : operand->Operands()) @@ -3254,16 +3442,14 @@ void LinearScan::buildRefPositionsForNode(GenTree* tree, assert(!isRegPairType(tree->TypeGet())); #endif // _TARGET_ARM_ - // The LIR traversal doesn't visit non-aggregate GT_LIST or GT_ARGPLACE nodes + // The LIR traversal doesn't visit GT_LIST or GT_ARGPLACE nodes. + // GT_CLS_VAR nodes should have been eliminated by rationalizer. assert(tree->OperGet() != GT_ARGPLACE); - assert((tree->OperGet() != GT_LIST) || tree->AsArgList()->IsAggregate()); + assert(tree->OperGet() != GT_LIST); + assert(tree->OperGet() != GT_CLS_VAR); - // These nodes are eliminated by the Rationalizer. - if (tree->OperGet() == GT_CLS_VAR) - { - JITDUMP("Unexpected node %s in LSRA.\n", GenTree::NodeName(tree->OperGet())); - assert(!"Unexpected node in LSRA."); - } + // The LIR traversal visits only the first node in a GT_FIELD_LIST. + assert((tree->OperGet() != GT_FIELD_LIST) || tree->AsFieldList()->IsFieldListHead()); // The set of internal temporary registers used by this node are stored in the // gtRsvdRegs register mask. Clear it out. @@ -3409,7 +3595,7 @@ void LinearScan::buildRefPositionsForNode(GenTree* tree, { // Get the location info for the register defined by the first operand. LocationInfoList operandDefs; - bool found = operandToLocationInfoMap.TryGetValue(*(tree->OperandsBegin()), &operandDefs); + bool found = operandToLocationInfoMap.TryGetValue(*(tree->OperandsBegin()), &operandDefs); assert(found); // Since we only expect to consume one register, we should only have a single register to @@ -3503,7 +3689,51 @@ void LinearScan::buildRefPositionsForNode(GenTree* tree, // (i.e. the target is read-modify-write), preference the dst to op1. bool hasDelayFreeSrc = tree->gtLsraInfo.hasDelayFreeSrc; - if (tree->OperGet() == GT_PUTARG_REG && isCandidateLocalRef(tree->gtGetOp1()) && + +#if defined(DEBUG) && defined(_TARGET_X86_) + // On x86, `LSRA_LIMIT_CALLER` is too restrictive to allow the use of special put args: this stress mode + // leaves only three registers allocatable--eax, ecx, and edx--of which the latter two are also used for the + // first two integral arguments to a call. This can leave us with too few registers to succesfully allocate in + // situations like the following: + // + // t1026 = lclVar ref V52 tmp35 u:3 REG NA + // + // /--* t1026 ref + // t1352 = * putarg_reg ref REG NA + // + // t342 = lclVar int V14 loc6 u:4 REG NA $50c + // + // t343 = const int 1 REG NA $41 + // + // /--* t342 int + // +--* t343 int + // t344 = * + int REG NA $495 + // + // t345 = lclVar int V04 arg4 u:2 REG NA $100 + // + // /--* t344 int + // +--* t345 int + // t346 = * % int REG NA $496 + // + // /--* t346 int + // t1353 = * putarg_reg int REG NA + // + // t1354 = lclVar ref V52 tmp35 (last use) REG NA + // + // /--* t1354 ref + // t1355 = * lea(b+0) byref REG NA + // + // Here, the first `putarg_reg` would normally be considered a special put arg, which would remove `ecx` from the + // set of allocatable registers, leaving only `eax` and `edx`. The allocator will then fail to allocate a register + // for the def of `t345` if arg4 is not a register candidate: the corresponding ref position will be constrained to + // { `ecx`, `ebx`, `esi`, `edi` }, which `LSRA_LIMIT_CALLER` will further constrain to `ecx`, which will not be + // available due to the special put arg. + const bool supportsSpecialPutArg = getStressLimitRegs() != LSRA_LIMIT_CALLER; +#else + const bool supportsSpecialPutArg = true; +#endif + + if (supportsSpecialPutArg && tree->OperGet() == GT_PUTARG_REG && isCandidateLocalRef(tree->gtGetOp1()) && (tree->gtGetOp1()->gtFlags & GTF_VAR_DEATH) == 0) { // This is the case for a "pass-through" copy of a lclVar. In the case where it is a non-last-use, @@ -3525,9 +3755,17 @@ void LinearScan::buildRefPositionsForNode(GenTree* tree, RefPosition* internalRefs[MaxInternalRegisters]; +#ifdef DEBUG + // Number of registers required for tree node is the sum of + // consume + produce + internalCount. This is the minimum + // set of registers that needs to be ensured in candidate + // set of ref positions created. + unsigned minRegCount = consume + produce + info.internalIntCount + info.internalFloatCount; +#endif // DEBUG + // make intervals for all the 'internal' register requirements for this node // where internal means additional registers required temporarily - int internalCount = buildInternalRegisterDefsForNode(tree, currentLoc, internalRefs); + int internalCount = buildInternalRegisterDefsForNode(tree, currentLoc, internalRefs DEBUG_ARG(minRegCount)); // pop all ref'd tree temps GenTreeOperandIterator iterator = tree->OperandsBegin(); @@ -3632,6 +3870,37 @@ void LinearScan::buildRefPositionsForNode(GenTree* tree, candidates = fixedAssignment; } +#ifdef DEBUG + // If delayRegFree, then Use will interfere with the destination of + // the consuming node. Therefore, we also need add the kill set of + // consuming node to minRegCount. + // + // For example consider the following IR on x86, where v01 and v02 + // are method args coming in ecx and edx respectively. + // GT_DIV(v01, v02) + // + // For GT_DIV minRegCount will be 3 without adding kill set + // of GT_DIV node. + // + // Assume further JitStressRegs=2, which would constrain + // candidates to callee trashable regs { eax, ecx, edx } on + // use positions of v01 and v02. LSRA allocates ecx for v01. + // Use position of v02 cannot be allocated a regs since it + // is marked delay-reg free and {eax,edx} are getting killed + // before the def of GT_DIV. For this reason, minRegCount + // for Use position of v02 also needs to take into account + // of kill set of its consuming node. + unsigned minRegCountForUsePos = minRegCount; + if (delayRegFree) + { + regMaskTP killMask = getKillSetForNode(tree); + if (killMask != RBM_NONE) + { + minRegCountForUsePos += genCountBits(killMask); + } + } +#endif // DEBUG + RefPosition* pos; if ((candidates & allRegs(i->registerType)) == 0) { @@ -3645,13 +3914,16 @@ void LinearScan::buildRefPositionsForNode(GenTree* tree, regNumber physicalReg = genRegNumFromMask(fixedAssignment); RefPosition* pos = newRefPosition(physicalReg, currentLoc, RefTypeFixedReg, nullptr, fixedAssignment); } - pos = newRefPosition(i, currentLoc, RefTypeUse, useNode, allRegs(i->registerType), multiRegIdx); + pos = newRefPosition(i, currentLoc, RefTypeUse, useNode, allRegs(i->registerType), + multiRegIdx DEBUG_ARG(minRegCountForUsePos)); pos->registerAssignment = candidates; } else { - pos = newRefPosition(i, currentLoc, RefTypeUse, useNode, candidates, multiRegIdx); + pos = newRefPosition(i, currentLoc, RefTypeUse, useNode, candidates, + multiRegIdx DEBUG_ARG(minRegCountForUsePos)); } + if (delayRegFree) { hasDelayFreeSrc = true; @@ -3675,7 +3947,7 @@ void LinearScan::buildRefPositionsForNode(GenTree* tree, listNodePool.ReturnNodes(operandDefs); } - buildInternalRegisterUsesForNode(tree, currentLoc, internalRefs, internalCount); + buildInternalRegisterUsesForNode(tree, currentLoc, internalRefs, internalCount DEBUG_ARG(minRegCount)); RegisterType registerType = getDefType(tree); regMaskTP candidates = getDefCandidates(tree); @@ -3708,7 +3980,7 @@ void LinearScan::buildRefPositionsForNode(GenTree* tree, { // Build RefPositions for saving any live large vectors. // This must be done after the kills, so that we know which large vectors are still live. - VarSetOps::AssignNoCopy(compiler, liveLargeVectors, buildUpperVectorSaveRefPositions(tree, currentLoc)); + VarSetOps::AssignNoCopy(compiler, liveLargeVectors, buildUpperVectorSaveRefPositions(tree, currentLoc + 1)); } #endif // FEATURE_PARTIAL_SIMD_CALLEE_SAVE @@ -3779,7 +4051,8 @@ void LinearScan::buildRefPositionsForNode(GenTree* tree, locationInfoList.Append(listNodePool.GetNode(defLocation, interval, tree, (unsigned)i)); } - RefPosition* pos = newRefPosition(interval, defLocation, defRefType, defNode, currCandidates, (unsigned)i); + RefPosition* pos = newRefPosition(interval, defLocation, defRefType, defNode, currCandidates, + (unsigned)i DEBUG_ARG(minRegCount)); if (info.isLocalDefUse) { pos->isLocalDefUse = true; @@ -3791,11 +4064,12 @@ void LinearScan::buildRefPositionsForNode(GenTree* tree, } #if FEATURE_PARTIAL_SIMD_CALLEE_SAVE - buildUpperVectorRestoreRefPositions(tree, currentLoc, liveLargeVectors); + // SaveDef position must be at the same location as Def position of call node. + buildUpperVectorRestoreRefPositions(tree, defLocation, liveLargeVectors); #endif // FEATURE_PARTIAL_SIMD_CALLEE_SAVE - bool isContainedNode = - !noAdd && consume == 0 && produce == 0 && (tree->OperIsAggregate() || (tree->TypeGet() != TYP_VOID && !tree->OperIsStore())); + bool isContainedNode = !noAdd && consume == 0 && produce == 0 && + (tree->OperIsFieldListHead() || ((tree->TypeGet() != TYP_VOID) && !tree->OperIsStore())); if (isContainedNode) { // Contained nodes map to the concatenated lists of their operands. @@ -3852,6 +4126,22 @@ BasicBlock* getNonEmptyBlock(BasicBlock* block) return block; } +//------------------------------------------------------------------------ +// insertZeroInitRefPositions: Handle lclVars that are live-in to the first block +// +// Notes: +// For each lclVar that is live-in to the first block: +// - If it is a GC ref, or if compInitMem is set, a ZeroInit RefPosition will be created. +// - Otherwise, it will be marked as spilled, since it will not be assigned a register +// on entry and will be loaded from memory on the undefined path. +// Note that, when the compInitMem option is not set, we may encounter these on +// paths that are protected by the same condition as an earlier def. However, since +// we don't do the analysis to determine this - and couldn't rely on always identifying +// such cases even if we tried - we must conservatively treat the undefined path as +// being possible. This is a relatively rare case, so the introduced conservatism is +// not expected to warrant the analysis required to determine the best placement of +// an initialization. +// void LinearScan::insertZeroInitRefPositions() { // insert defs for this, then a block boundary @@ -3861,15 +4151,23 @@ void LinearScan::insertZeroInitRefPositions() { unsigned varNum = compiler->lvaTrackedToVarNum[varIndex]; LclVarDsc* varDsc = compiler->lvaTable + varNum; - if (!varDsc->lvIsParam && isCandidateVar(varDsc) && - (compiler->info.compInitMem || varTypeIsGC(varDsc->TypeGet()))) + if (!varDsc->lvIsParam && isCandidateVar(varDsc)) { - GenTree* firstNode = getNonEmptyBlock(compiler->fgFirstBB)->firstNode(); - JITDUMP("V%02u was live in\n", varNum); - Interval* interval = getIntervalForLocalVar(varNum); - RefPosition* pos = - newRefPosition(interval, MinLocation, RefTypeZeroInit, firstNode, allRegs(interval->registerType)); - varDsc->lvMustInit = true; + JITDUMP("V%02u was live in to first block:", varNum); + Interval* interval = getIntervalForLocalVar(varNum); + if (compiler->info.compInitMem || varTypeIsGC(varDsc->TypeGet())) + { + JITDUMP(" creating ZeroInit\n"); + GenTree* firstNode = getNonEmptyBlock(compiler->fgFirstBB)->firstNode(); + RefPosition* pos = + newRefPosition(interval, MinLocation, RefTypeZeroInit, firstNode, allRegs(interval->registerType)); + varDsc->lvMustInit = true; + } + else + { + setIntervalAsSpilled(interval); + JITDUMP(" marking as spilled\n"); + } } } } @@ -4131,8 +4429,20 @@ void LinearScan::buildIntervals() } #endif // DEBUG +#if DOUBLE_ALIGN + // We will determine whether we should double align the frame during + // identifyCandidates(), but we initially assume that we will not. + doDoubleAlign = false; +#endif + identifyCandidates(); + // Figure out if we're going to use a frame pointer. We need to do this before building + // the ref positions, because those objects will embed the frame register in various register masks + // if the frame pointer is not reserved. If we decide to have a frame pointer, setFrameType() will + // remove the frame pointer from the masks. + setFrameType(); + DBEXEC(VERBOSE, TupleStyleDump(LSRA_DUMP_PRE)); // second part: @@ -4263,6 +4573,9 @@ void LinearScan::buildIntervals() insertZeroInitRefPositions(); } + // Any lclVars live-in to a block are resolution candidates. + VarSetOps::UnionD(compiler, resolutionCandidateVars, block->bbLiveIn); + // Determine if we need any DummyDefs. // We need DummyDefs for cases where "predBlock" isn't really a predecessor. // Note that it's possible to have uses of unitialized variables, in which case even the first @@ -4274,8 +4587,8 @@ void LinearScan::buildIntervals() VARSET_TP VARSET_INIT(compiler, newLiveIn, block->bbLiveIn); if (predBlock) { - JITDUMP("\n\nSetting incoming variable registers of BB%02u to outVarToRegMap of BB%02u\n", block->bbNum, - predBlock->bbNum); + JITDUMP("\n\nSetting BB%02u as the predecessor for determining incoming variable registers of BB%02u\n", + block->bbNum, predBlock->bbNum); assert(predBlock->bbNum <= bbNumMaxBeforeResolution); blockInfo[block->bbNum].predBBNum = predBlock->bbNum; // Compute set difference: newLiveIn = block->bbLiveIn - predBlock->bbLiveOut @@ -4534,7 +4847,16 @@ void LinearScan::validateIntervals() void LinearScan::setFrameType() { FrameType frameType = FT_NOT_SET; - if (compiler->codeGen->isFramePointerRequired()) +#if DOUBLE_ALIGN + compiler->codeGen->setDoubleAlign(false); + if (doDoubleAlign) + { + frameType = FT_DOUBLE_ALIGN_FRAME; + compiler->codeGen->setDoubleAlign(true); + } + else +#endif // DOUBLE_ALIGN + if (compiler->codeGen->isFramePointerRequired()) { frameType = FT_EBP_FRAME; } @@ -4563,22 +4885,6 @@ void LinearScan::setFrameType() } } -#if DOUBLE_ALIGN - // The DOUBLE_ALIGN feature indicates whether the JIT will attempt to double-align the - // frame if needed. Note that this feature isn't on for amd64, because the stack is - // always double-aligned by default. - compiler->codeGen->setDoubleAlign(false); - - // TODO-CQ: Tune this (see regalloc.cpp, in which raCntWtdStkDblStackFP is used to - // determine whether to double-align). Note, though that there is at least one test - // (jit\opt\Perf\DoubleAlign\Locals.exe) that depends on double-alignment being set - // in certain situations. - if (!compiler->opts.MinOpts() && !compiler->codeGen->isFramePointerRequired() && compiler->compFloatingPointUsed) - { - frameType = FT_DOUBLE_ALIGN_FRAME; - } -#endif // DOUBLE_ALIGN - switch (frameType) { case FT_ESP_FRAME: @@ -4593,7 +4899,6 @@ void LinearScan::setFrameType() case FT_DOUBLE_ALIGN_FRAME: noway_assert(!compiler->codeGen->isFramePointerRequired()); compiler->codeGen->setFramePointerUsed(false); - compiler->codeGen->setDoubleAlign(true); break; #endif // DOUBLE_ALIGN default: @@ -4625,11 +4930,11 @@ void LinearScan::setFrameType() compiler->rpFrameType = frameType; } -// Is the copyReg given by this RefPosition still busy at the +// Is the copyReg/moveReg given by this RefPosition still busy at the // given location? -bool copyRegInUse(RefPosition* ref, LsraLocation loc) +bool copyOrMoveRegInUse(RefPosition* ref, LsraLocation loc) { - assert(ref->copyReg); + assert(ref->copyReg || ref->moveReg); if (ref->getRefEndLocation() >= loc) { return true; @@ -4689,14 +4994,15 @@ bool LinearScan::registerIsAvailable(RegRecord* physRegRecord, return false; } - // Is this a copyReg? It is if the register assignment doesn't match. - // (the recentReference may not be a copyReg, because we could have seen another - // reference since the copyReg) + // Is this a copyReg/moveReg? It is if the register assignment doesn't match. + // (the recentReference may not be a copyReg/moveReg, because we could have seen another + // reference since the copyReg/moveReg) if (!assignedInterval->isAssignedTo(physRegRecord->regNum)) { // Don't reassign it if it's still in use - if (recentReference->copyReg && copyRegInUse(recentReference, currentLoc)) + if ((recentReference->copyReg || recentReference->moveReg) && + copyOrMoveRegInUse(recentReference, currentLoc)) { return false; } @@ -5393,8 +5699,17 @@ regNumber LinearScan::allocateBusyReg(Interval* current, RefPosition* refPositio // to remain live until the use, we should set the candidates to allRegs(regType) // to avoid a spill - codegen can then insert the copy. assert(candidates == candidateBit); - physRegNextLocation = MaxLocation; - farthestRefPosWeight = BB_MAX_WEIGHT; + + // If a refPosition has a fixed reg as its candidate and is also marked + // as allocateIfProfitable, we should allocate fixed reg only if the + // weight of this ref position is greater than the weight of the ref + // position to which fixed reg is assigned. Such a case would arise + // on x86 under LSRA stress. + if (!allocateIfProfitable) + { + physRegNextLocation = MaxLocation; + farthestRefPosWeight = BB_MAX_WEIGHT; + } } else { @@ -5487,13 +5802,14 @@ regNumber LinearScan::allocateBusyReg(Interval* current, RefPosition* refPositio } } - LsraLocation nextLocation = assignedInterval->getNextRefLocation(); + RefPosition* nextRefPosition = assignedInterval->getNextRefPosition(); + LsraLocation nextLocation = assignedInterval->getNextRefLocation(); // We should never spill a register that's occupied by an Interval with its next use at the current location. // Normally this won't occur (unless we actually had more uses in a single node than there are registers), // because we'll always find something with a later nextLocation, but it can happen in stress when // we have LSRA_SELECT_NEAREST. - if ((nextLocation == refLocation) && !refPosition->isFixedRegRef) + if ((nextLocation == refLocation) && !refPosition->isFixedRegRef && nextRefPosition->RequiresRegister()) { continue; } @@ -5578,7 +5894,17 @@ regNumber LinearScan::allocateBusyReg(Interval* current, RefPosition* refPositio else { // Must have found a spill candidate. - assert((farthestRefPhysRegRecord != nullptr) && (farthestLocation > refLocation || refPosition->isFixedRegRef)); + assert(farthestRefPhysRegRecord != nullptr); + if ((farthestLocation == refLocation) && !refPosition->isFixedRegRef) + { + Interval* assignedInterval = farthestRefPhysRegRecord->assignedInterval; + RefPosition* nextRefPosition = assignedInterval->getNextRefPosition(); + assert(!nextRefPosition->RequiresRegister()); + } + else + { + assert(farthestLocation > refLocation || refPosition->isFixedRegRef); + } } #endif @@ -5699,6 +6025,70 @@ void LinearScan::assignPhysReg(RegRecord* regRec, Interval* interval) } //------------------------------------------------------------------------ +// setIntervalAsSplit: Set this Interval as being split +// +// Arguments: +// interval - The Interval which is being split +// +// Return Value: +// None. +// +// Notes: +// The given Interval will be marked as split, and it will be added to the +// set of splitOrSpilledVars. +// +// Assumptions: +// "interval" must be a lclVar interval, as tree temps are never split. +// This is asserted in the call to getVarIndex(). +// +void LinearScan::setIntervalAsSplit(Interval* interval) +{ + if (interval->isLocalVar) + { + unsigned varIndex = interval->getVarIndex(compiler); + if (!interval->isSplit) + { + VarSetOps::AddElemD(compiler, splitOrSpilledVars, varIndex); + } + else + { + assert(VarSetOps::IsMember(compiler, splitOrSpilledVars, varIndex)); + } + } + interval->isSplit = true; +} + +//------------------------------------------------------------------------ +// setIntervalAsSpilled: Set this Interval as being spilled +// +// Arguments: +// interval - The Interval which is being spilled +// +// Return Value: +// None. +// +// Notes: +// The given Interval will be marked as spilled, and it will be added +// to the set of splitOrSpilledVars. +// +void LinearScan::setIntervalAsSpilled(Interval* interval) +{ + if (interval->isLocalVar) + { + unsigned varIndex = interval->getVarIndex(compiler); + if (!interval->isSpilled) + { + VarSetOps::AddElemD(compiler, splitOrSpilledVars, varIndex); + } + else + { + assert(VarSetOps::IsMember(compiler, splitOrSpilledVars, varIndex)); + } + } + interval->isSpilled = true; +} + +//------------------------------------------------------------------------ // spill: Spill this Interval between "fromRefPosition" and "toRefPosition" // // Arguments: @@ -5739,8 +6129,10 @@ void LinearScan::spillInterval(Interval* interval, RefPosition* fromRefPosition, } #endif // DEBUG - interval->isActive = false; - interval->isSpilled = true; + INTRACK_STATS(updateLsraStat(LSRA_STAT_SPILL, fromRefPosition->bbNum)); + + interval->isActive = false; + setIntervalAsSpilled(interval); // If fromRefPosition occurs before the beginning of this block, mark this as living in the stack // on entry to this block. @@ -5923,7 +6315,7 @@ void LinearScan::unassignPhysReg(RegRecord* regRec, RefPosition* spillRefPositio setInVarRegForBB(curBBNum, assignedInterval->varNum, REG_STK); if (spillRefPosition->nextRefPosition != nullptr) { - assignedInterval->isSpilled = true; + setIntervalAsSpilled(assignedInterval); } } else @@ -5945,7 +6337,8 @@ void LinearScan::unassignPhysReg(RegRecord* regRec, RefPosition* spillRefPositio { assignedInterval->assignedReg = regRec; } - else if (regRec->previousInterval != nullptr && regRec->previousInterval->assignedReg == regRec && + else if (regRec->previousInterval != nullptr && regRec->previousInterval != assignedInterval && + regRec->previousInterval->assignedReg == regRec && regRec->previousInterval->getNextRefPosition() != nullptr) { regRec->assignedInterval = regRec->previousInterval; @@ -6128,7 +6521,14 @@ void LinearScan::processBlockStartLocations(BasicBlock* currentBlock, bool alloc if (allocationPass) { targetReg = predVarToRegMap[varIndex]; - INDEBUG(targetReg = rotateBlockStartLocation(interval, targetReg, (~liveRegs | inactiveRegs))); +#ifdef DEBUG + regNumber newTargetReg = rotateBlockStartLocation(interval, targetReg, (~liveRegs | inactiveRegs)); + if (newTargetReg != targetReg) + { + targetReg = newTargetReg; + setIntervalAsSplit(interval); + } +#endif // DEBUG inVarToRegMap[varIndex] = targetReg; } else // !allocationPass (i.e. resolution/write-back pass) @@ -6686,6 +7086,7 @@ void LinearScan::allocateRegisters() INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_NO_ENTRY_REG_ALLOCATED, currentInterval)); didDump = true; allocate = false; + setIntervalAsSpilled(currentInterval); } // If it has no actual references, mark it as "lastUse"; since they're not actually part // of any flow they won't have been marked during dataflow. Otherwise, if we allocate a @@ -6912,6 +7313,7 @@ void LinearScan::allocateRegisters() } currentRefPosition->moveReg = true; assignedRegister = REG_NA; + setIntervalAsSplit(currentInterval); INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_MOVE_REG, currentInterval, assignedRegister)); } else if ((genRegMask(assignedRegister) & currentRefPosition->registerAssignment) != 0) @@ -6936,65 +7338,47 @@ void LinearScan::allocateRegisters() } else { - // This must be a localVar or a single-reg fixed use or a tree temp with conflicting def & use. - - assert(currentInterval && (currentInterval->isLocalVar || currentRefPosition->isFixedRegRef || - currentInterval->hasConflictingDefUse)); + assert(currentInterval != nullptr); // It's already in a register, but not one we need. - // If it is a fixed use that is not marked "delayRegFree", there is already a FixedReg to ensure that - // the needed reg is not otherwise in use, so we can simply ignore it and codegen will do the copy. - // The reason we need special handling for the "delayRegFree" case is that we need to mark the - // fixed-reg as in-use and delayed (the FixedReg RefPosition doesn't handle the delay requirement). - // Otherwise, if this is a pure use localVar or tree temp, we assign a copyReg, but must free both regs - // if it is a last use. - if (!currentRefPosition->isFixedRegRef || currentRefPosition->delayRegFree) - { - if (!RefTypeIsDef(currentRefPosition->refType)) + if (!RefTypeIsDef(currentRefPosition->refType)) + { + regNumber copyReg = assignCopyReg(currentRefPosition); + assert(copyReg != REG_NA); + INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_COPY_REG, currentInterval, copyReg)); + lastAllocatedRefPosition = currentRefPosition; + if (currentRefPosition->lastUse) { - regNumber copyReg = assignCopyReg(currentRefPosition); - assert(copyReg != REG_NA); - INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_COPY_REG, currentInterval, copyReg)); - lastAllocatedRefPosition = currentRefPosition; - if (currentRefPosition->lastUse) + if (currentRefPosition->delayRegFree) { - if (currentRefPosition->delayRegFree) - { - INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_LAST_USE_DELAYED, currentInterval, - assignedRegister)); - delayRegsToFree |= - (genRegMask(assignedRegister) | currentRefPosition->registerAssignment); - } - else - { - INDEBUG( - dumpLsraAllocationEvent(LSRA_EVENT_LAST_USE, currentInterval, assignedRegister)); - regsToFree |= (genRegMask(assignedRegister) | currentRefPosition->registerAssignment); - } + INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_LAST_USE_DELAYED, currentInterval, + assignedRegister)); + delayRegsToFree |= (genRegMask(assignedRegister) | currentRefPosition->registerAssignment); } - // If this is a tree temp (non-localVar) interval, we will need an explicit move. - if (!currentInterval->isLocalVar) + else { - currentRefPosition->moveReg = true; - currentRefPosition->copyReg = false; + INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_LAST_USE, currentInterval, assignedRegister)); + regsToFree |= (genRegMask(assignedRegister) | currentRefPosition->registerAssignment); } - continue; } - else + // If this is a tree temp (non-localVar) interval, we will need an explicit move. + if (!currentInterval->isLocalVar) { - INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_NEEDS_NEW_REG, nullptr, assignedRegister)); - regsToFree |= genRegMask(assignedRegister); - // We want a new register, but we don't want this to be considered a spill. - assignedRegister = REG_NA; - if (physRegRecord->assignedInterval == currentInterval) - { - unassignPhysRegNoSpill(physRegRecord); - } + currentRefPosition->moveReg = true; + currentRefPosition->copyReg = false; } + continue; } else { - INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_KEPT_ALLOCATION, nullptr, assignedRegister)); + INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_NEEDS_NEW_REG, nullptr, assignedRegister)); + regsToFree |= genRegMask(assignedRegister); + // We want a new register, but we don't want this to be considered a spill. + assignedRegister = REG_NA; + if (physRegRecord->assignedInterval == currentInterval) + { + unassignPhysRegNoSpill(physRegRecord); + } } } } @@ -7031,23 +7415,39 @@ void LinearScan::allocateRegisters() // then find a register to spill if (assignedRegister == REG_NA) { -#ifdef FEATURE_SIMD +#if FEATURE_PARTIAL_SIMD_CALLEE_SAVE if (refType == RefTypeUpperVectorSaveDef) { // TODO-CQ: Determine whether copying to two integer callee-save registers would be profitable. - currentRefPosition->registerAssignment = (allRegs(TYP_FLOAT) & RBM_FLT_CALLEE_TRASH); - assignedRegister = tryAllocateFreeReg(currentInterval, currentRefPosition); + + // SaveDef position occurs after the Use of args and at the same location as Kill/Def + // positions of a call node. But SaveDef position cannot use any of the arg regs as + // they are needed for call node. + currentRefPosition->registerAssignment = + (allRegs(TYP_FLOAT) & RBM_FLT_CALLEE_TRASH & ~RBM_FLTARG_REGS); + assignedRegister = tryAllocateFreeReg(currentInterval, currentRefPosition); + // There MUST be caller-save registers available, because they have all just been killed. + // Amd64 Windows: xmm4-xmm5 are guaranteed to be available as xmm0-xmm3 are used for passing args. + // Amd64 Unix: xmm8-xmm15 are guaranteed to be avilable as xmm0-xmm7 are used for passing args. + // X86 RyuJIT Windows: xmm4-xmm7 are guanrateed to be available. assert(assignedRegister != REG_NA); + // Now, spill it. - // (These will look a bit backward in the dump, but it's a pain to dump the alloc before the spill). + // Note: + // i) The reason we have to spill is that SaveDef position is allocated after the Kill positions + // of the call node are processed. Since callee-trash registers are killed by call node + // we explicity spill and unassign the register. + // ii) These will look a bit backward in the dump, but it's a pain to dump the alloc before the + // spill). unassignPhysReg(getRegisterRecord(assignedRegister), currentRefPosition); INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_ALLOC_REG, currentInterval, assignedRegister)); + // Now set assignedRegister to REG_NA again so that we don't re-activate it. assignedRegister = REG_NA; } else -#endif // FEATURE_SIMD +#endif // FEATURE_PARTIAL_SIMD_CALLEE_SAVE if (currentRefPosition->RequiresRegister() || currentRefPosition->AllocateIfProfitable()) { if (allocateReg) @@ -7069,6 +7469,7 @@ void LinearScan::allocateRegisters() currentRefPosition->registerAssignment = RBM_NONE; currentRefPosition->reload = false; + setIntervalAsSpilled(currentInterval); INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_NO_REG_ALLOCATED, currentInterval)); } @@ -7078,6 +7479,7 @@ void LinearScan::allocateRegisters() INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_NO_REG_ALLOCATED, currentInterval)); currentRefPosition->registerAssignment = RBM_NONE; currentInterval->isActive = false; + setIntervalAsSpilled(currentInterval); } } #ifdef DEBUG @@ -7224,7 +7626,7 @@ void LinearScan::allocateRegisters() // - interval->physReg is set to the assigned register // (i.e. at the code location which is currently being handled by resolveRegisters()) // - interval->isActive is true iff the interval is live and occupying a register -// - interval->isSpilled is set to true if the interval is EVER spilled +// - interval->isSpilled should have already been set to true if the interval is EVER spilled // - interval->isSplit is set to true if the interval does not occupy the same // register throughout the method // - RegRecord->assignedInterval points to the interval which currently occupies @@ -7264,9 +7666,9 @@ void LinearScan::resolveLocalRef(BasicBlock* block, GenTreePtr treeNode, RefPosi if (currentRefPosition->registerAssignment == RBM_NONE) { assert(!currentRefPosition->RequiresRegister()); + assert(interval->isSpilled); - interval->isSpilled = true; - varDsc->lvRegNum = REG_STK; + varDsc->lvRegNum = REG_STK; if (interval->assignedReg != nullptr && interval->assignedReg->assignedInterval == interval) { interval->assignedReg->assignedInterval = nullptr; @@ -7314,8 +7716,10 @@ void LinearScan::resolveLocalRef(BasicBlock* block, GenTreePtr treeNode, RefPosi // In the reload case we simply do not set GTF_REG_VAL, and it gets // referenced from the variable's home location. // This is also true for a pure def which is spilled. - if (reload && currentRefPosition->refType != RefTypeDef) + if (reload) { + assert(currentRefPosition->refType != RefTypeDef); + assert(interval->isSpilled); varDsc->lvRegNum = REG_STK; if (!spillAfter) { @@ -7353,31 +7757,15 @@ void LinearScan::resolveLocalRef(BasicBlock* block, GenTreePtr treeNode, RefPosi { assert(currentRefPosition->refType == RefTypeExpUse); } - - // If we have an undefined use set it as non-reg - if (!interval->isSpilled) - { - if (varDsc->lvIsParam && !varDsc->lvIsRegArg && currentRefPosition == interval->firstRefPosition) - { - // Parameters are the only thing that can be used before defined - } - else - { - // if we see a use before def of something else, the zero init flag better not be set. - noway_assert(!compiler->info.compInitMem); - // if it is not set, then the behavior is undefined but we don't want to crash or assert - interval->isSpilled = true; - } - } } else if (spillAfter && !RefTypeIsUse(currentRefPosition->refType)) { // In the case of a pure def, don't bother spilling - just assign it to the // stack. However, we need to remember that it was spilled. - interval->isSpilled = true; - varDsc->lvRegNum = REG_STK; - interval->physReg = REG_NA; + assert(interval->isSpilled); + varDsc->lvRegNum = REG_STK; + interval->physReg = REG_NA; if (treeNode != nullptr) { treeNode->gtRegNum = REG_NA; @@ -7409,6 +7797,7 @@ void LinearScan::resolveLocalRef(BasicBlock* block, GenTreePtr treeNode, RefPosi } else { + assert(interval->isSplit); interval->physReg = assignedReg; } @@ -7426,13 +7815,11 @@ void LinearScan::resolveLocalRef(BasicBlock* block, GenTreePtr treeNode, RefPosi { if (varDsc->lvRegNum != REG_STK) { - // If the register assignments don't match, then this interval is spilt, - // but not spilled (yet) - // However, we don't have a single register assignment now + // If the register assignments don't match, then this interval is split. if (varDsc->lvRegNum != assignedReg) { - interval->isSplit = TRUE; - varDsc->lvRegNum = REG_STK; + setIntervalAsSplit(interval); + varDsc->lvRegNum = REG_STK; } } else @@ -7447,9 +7834,9 @@ void LinearScan::resolveLocalRef(BasicBlock* block, GenTreePtr treeNode, RefPosi { treeNode->gtFlags |= GTF_SPILL; } - interval->isSpilled = true; - interval->physReg = REG_NA; - varDsc->lvRegNum = REG_STK; + assert(interval->isSpilled); + interval->physReg = REG_NA; + varDsc->lvRegNum = REG_STK; } // This value is in a register, UNLESS we already saw this treeNode @@ -7489,6 +7876,7 @@ void LinearScan::writeRegisters(RefPosition* currentRefPosition, GenTree* tree) // than the one it was spilled from (GT_RELOAD). // // Arguments: +// block - basic block in which GT_COPY/GT_RELOAD is inserted. // tree - This is the node to copy or reload. // Insert copy or reload node between this node and its parent. // multiRegIdx - register position of tree node for which copy or reload is needed. @@ -7557,6 +7945,10 @@ void LinearScan::insertCopyOrReload(BasicBlock* block, GenTreePtr tree, unsigned else { oper = GT_COPY; + +#if TRACK_LSRA_STATS + updateLsraStat(LSRA_STAT_COPY_REG, block->bbNum); +#endif } // If the parent is a reload/copy node, then tree must be a multi-reg call node @@ -8100,7 +8492,7 @@ void LinearScan::resolveRegisters() { JITDUMP(" internal"); GenTreePtr indNode = nullptr; - if (treeNode->OperIsIndir()) + if (treeNode->OperGet() == GT_IND) { indNode = treeNode; JITDUMP(" allocated at GT_IND"); @@ -8223,6 +8615,11 @@ void LinearScan::resolveRegisters() printf("RESOLVING BB BOUNDARIES\n"); printf("-----------------------\n"); + printf("Resolution Candidates: "); + dumpConvertedVarSet(compiler, resolutionCandidateVars); + printf("\n"); + printf("Has %sCritical Edges\n\n", hasCriticalEdges ? "" : "No"); + printf("Prior to Resolution\n"); foreach_block(compiler, block) { @@ -8282,23 +8679,10 @@ void LinearScan::resolveRegisters() varDsc->lvArgInitReg = initialReg; JITDUMP(" Set V%02u argument initial register to %s\n", lclNum, getRegName(initialReg)); } - if (!varDsc->lvIsRegArg) - { - // stack arg - if (compiler->lvaIsFieldOfDependentlyPromotedStruct(varDsc)) - { - if (sourceReg != initialReg) - { - // The code generator won't initialize struct - // fields, so we have to do that if it's not already - // where it belongs. - assert(interval->isStructField); - JITDUMP(" Move struct field param V%02u from %s to %s\n", lclNum, getRegName(sourceReg), - getRegName(initialReg)); - insertMove(insertionBlock, insertionPoint, lclNum, sourceReg, initialReg); - } - } - } + + // Stack args that are part of dependently-promoted structs should never be register candidates (see + // LinearScan::isRegCandidate). + assert(varDsc->lvIsRegArg || !compiler->lvaIsFieldOfDependentlyPromotedStruct(varDsc)); } // If lvRegNum is REG_STK, that means that either no register @@ -8347,8 +8731,8 @@ void LinearScan::resolveRegisters() } if (firstRefPosition->registerAssignment == RBM_NONE || firstRefPosition->spillAfter) { - // Either this RefPosition is spilled, or it is not a "real" def or use - assert(firstRefPosition->spillAfter || + // Either this RefPosition is spilled, or regOptional or it is not a "real" def or use + assert(firstRefPosition->spillAfter || firstRefPosition->AllocateIfProfitable() || (firstRefPosition->refType != RefTypeDef && firstRefPosition->refType != RefTypeUse)); varDsc->lvRegNum = REG_STK; } @@ -8432,6 +8816,8 @@ void LinearScan::insertMove( BasicBlock* block, GenTreePtr insertionPoint, unsigned lclNum, regNumber fromReg, regNumber toReg) { LclVarDsc* varDsc = compiler->lvaTable + lclNum; + // the lclVar must be a register candidate + assert(isRegCandidate(varDsc)); // One or both MUST be a register assert(fromReg != REG_STK || toReg != REG_STK); // They must not be the same register. @@ -8440,20 +8826,22 @@ void LinearScan::insertMove( // This var can't be marked lvRegister now varDsc->lvRegNum = REG_STK; - var_types lclTyp = varDsc->TypeGet(); - if (varDsc->lvNormalizeOnStore()) - { - lclTyp = genActualType(lclTyp); - } - GenTreePtr src = compiler->gtNewLclvNode(lclNum, lclTyp); + GenTreePtr src = compiler->gtNewLclvNode(lclNum, varDsc->TypeGet()); src->gtLsraInfo.isLsraAdded = true; - GenTreePtr top; - // If we are moving from STK to reg, mark the lclVar nodes with GTF_SPILLED - // Otherwise, if we are moving from reg to stack, mark it as GTF_SPILL - // Finally, for a reg-to-reg move, generate a GT_COPY + // There are three cases we need to handle: + // - We are loading a lclVar from the stack. + // - We are storing a lclVar to the stack. + // - We are copying a lclVar between registers. + // + // In the first and second cases, the lclVar node will be marked with GTF_SPILLED and GTF_SPILL, respectively. + // It is up to the code generator to ensure that any necessary normalization is done when loading or storing the + // lclVar's value. + // + // In the third case, we generate GT_COPY(GT_LCL_VAR) and type each node with the normalized type of the lclVar. + // This is safe because a lclVar is always normalized once it is in a register. - top = src; + GenTree* dst = src; if (fromReg == REG_STK) { src->gtFlags |= GTF_SPILLED; @@ -8467,21 +8855,22 @@ void LinearScan::insertMove( } else { - top = new (compiler, GT_COPY) GenTreeCopyOrReload(GT_COPY, varDsc->TypeGet(), src); + var_types movType = genActualType(varDsc->TypeGet()); + src->gtType = movType; + + dst = new (compiler, GT_COPY) GenTreeCopyOrReload(GT_COPY, movType, src); // This is the new home of the lclVar - indicate that by clearing the GTF_VAR_DEATH flag. // Note that if src is itself a lastUse, this will have no effect. - top->gtFlags &= ~(GTF_VAR_DEATH); + dst->gtFlags &= ~(GTF_VAR_DEATH); src->gtRegNum = fromReg; src->SetInReg(); - top->gtRegNum = toReg; - src->gtNext = top; - top->gtPrev = src; + dst->gtRegNum = toReg; src->gtLsraInfo.isLocalDefUse = false; - top->gtLsraInfo.isLsraAdded = true; + dst->gtLsraInfo.isLsraAdded = true; } - top->gtLsraInfo.isLocalDefUse = true; + dst->gtLsraInfo.isLocalDefUse = true; - LIR::Range treeRange = LIR::SeqTree(compiler, top); + LIR::Range treeRange = LIR::SeqTree(compiler, dst); LIR::Range& blockRange = LIR::AsRange(block); if (insertionPoint != nullptr) @@ -8497,7 +8886,7 @@ void LinearScan::insertMove( noway_assert(!blockRange.IsEmpty()); GenTree* branch = blockRange.LastNode(); - assert(branch->OperGet() == GT_JTRUE || branch->OperGet() == GT_SWITCH_TABLE || + assert(branch->OperIsConditionalJump() || branch->OperGet() == GT_SWITCH_TABLE || branch->OperGet() == GT_SWITCH); blockRange.InsertBefore(branch, std::move(treeRange)); @@ -8568,7 +8957,7 @@ void LinearScan::insertSwap( noway_assert(!blockRange.IsEmpty()); GenTree* branch = blockRange.LastNode(); - assert(branch->OperGet() == GT_JTRUE || branch->OperGet() == GT_SWITCH_TABLE || + assert(branch->OperIsConditionalJump() || branch->OperGet() == GT_SWITCH_TABLE || branch->OperGet() == GT_SWITCH); blockRange.InsertBefore(branch, std::move(swapRange)); @@ -8682,12 +9071,15 @@ void LinearScan::addResolution( insertMove(block, insertionPoint, interval->varNum, fromReg, toReg); if (fromReg == REG_STK || toReg == REG_STK) { - interval->isSpilled = true; + assert(interval->isSpilled); } else { - interval->isSplit = true; + // We should have already marked this as spilled or split. + assert((interval->isSpilled) || (interval->isSplit)); } + + INTRACK_STATS(updateLsraStat(LSRA_STAT_RESOLUTION_MOV, block->bbNum)); } //------------------------------------------------------------------------ @@ -8706,6 +9098,12 @@ void LinearScan::addResolution( void LinearScan::handleOutgoingCriticalEdges(BasicBlock* block) { + VARSET_TP VARSET_INIT_NOCOPY(outResolutionSet, + VarSetOps::Intersection(compiler, block->bbLiveOut, resolutionCandidateVars)); + if (VarSetOps::IsEmpty(compiler, outResolutionSet)) + { + return; + } VARSET_TP VARSET_INIT_NOCOPY(sameResolutionSet, VarSetOps::MakeEmpty(compiler)); VARSET_TP VARSET_INIT_NOCOPY(sameLivePathsSet, VarSetOps::MakeEmpty(compiler)); VARSET_TP VARSET_INIT_NOCOPY(singleTargetSet, VarSetOps::MakeEmpty(compiler)); @@ -8720,6 +9118,8 @@ void LinearScan::handleOutgoingCriticalEdges(BasicBlock* block) // First, determine the live regs at the end of this block so that we know what regs are // available to copy into. + // Note that for this purpose we use the full live-out set, because we must ensure that + // even the registers that remain the same across the edge are preserved correctly. regMaskTP liveOutRegs = RBM_NONE; VARSET_ITER_INIT(compiler, iter1, block->bbLiveOut, varIndex1); while (iter1.NextElem(compiler, &varIndex1)) @@ -8755,7 +9155,7 @@ void LinearScan::handleOutgoingCriticalEdges(BasicBlock* block) regMaskTP sameWriteRegs = RBM_NONE; regMaskTP diffReadRegs = RBM_NONE; - // For each var, classify them as: + // For each var that may require resolution, classify them as: // - in the same register at the end of this block and at each target (no resolution needed) // - in different registers at different targets (resolve separately): // diffResolutionSet @@ -8764,7 +9164,7 @@ void LinearScan::handleOutgoingCriticalEdges(BasicBlock* block) // write to any registers that are read by those in the diffResolutionSet: // sameResolutionSet - VARSET_ITER_INIT(compiler, iter, block->bbLiveOut, varIndex); + VARSET_ITER_INIT(compiler, iter, outResolutionSet, varIndex); while (iter.NextElem(compiler, &varIndex)) { unsigned varNum = compiler->lvaTrackedToVarNum[varIndex]; @@ -8936,6 +9336,16 @@ void LinearScan::resolveEdges() { JITDUMP("RESOLVING EDGES\n"); + // The resolutionCandidateVars set was initialized with all the lclVars that are live-in to + // any block. We now intersect that set with any lclVars that ever spilled or split. + // If there are no candidates for resoultion, simply return. + + VarSetOps::IntersectionD(compiler, resolutionCandidateVars, splitOrSpilledVars); + if (VarSetOps::IsEmpty(compiler, resolutionCandidateVars)) + { + return; + } + BasicBlock *block, *prevBlock = nullptr; // Handle all the critical edges first. @@ -8944,18 +9354,21 @@ void LinearScan::resolveEdges() // remaining mismatches. We visit the out-edges, as that allows us to share the moves that are // common among allt he targets. - foreach_block(compiler, block) + if (hasCriticalEdges) { - if (block->bbNum > bbNumMaxBeforeResolution) - { - // This is a new block added during resolution - we don't need to visit these now. - continue; - } - if (blockInfo[block->bbNum].hasCriticalOutEdge) + foreach_block(compiler, block) { - handleOutgoingCriticalEdges(block); + if (block->bbNum > bbNumMaxBeforeResolution) + { + // This is a new block added during resolution - we don't need to visit these now. + continue; + } + if (blockInfo[block->bbNum].hasCriticalOutEdge) + { + handleOutgoingCriticalEdges(block); + } + prevBlock = block; } - prevBlock = block; } prevBlock = nullptr; @@ -8975,7 +9388,9 @@ void LinearScan::resolveEdges() // we may need resolution at the beginning of this block. // This may be true even if it's the block we used for starting locations, // if a variable was spilled. - if (!VarSetOps::IsEmpty(compiler, block->bbLiveIn)) + VARSET_TP VARSET_INIT_NOCOPY(inResolutionSet, + VarSetOps::Intersection(compiler, block->bbLiveIn, resolutionCandidateVars)); + if (!VarSetOps::IsEmpty(compiler, inResolutionSet)) { if (uniquePredBlock != nullptr) { @@ -8988,7 +9403,7 @@ void LinearScan::resolveEdges() uniquePredBlock = uniquePredBlock->GetUniquePred(compiler); noway_assert(uniquePredBlock != nullptr); } - resolveEdge(uniquePredBlock, block, ResolveSplit, block->bbLiveIn); + resolveEdge(uniquePredBlock, block, ResolveSplit, inResolutionSet); } } @@ -9003,7 +9418,12 @@ void LinearScan::resolveEdges() BasicBlock* succBlock = block->GetSucc(0, compiler); if (succBlock->GetUniquePred(compiler) == nullptr) { - resolveEdge(block, succBlock, ResolveJoin, succBlock->bbLiveIn); + VARSET_TP VARSET_INIT_NOCOPY(outResolutionSet, VarSetOps::Intersection(compiler, succBlock->bbLiveIn, + resolutionCandidateVars)); + if (!VarSetOps::IsEmpty(compiler, outResolutionSet)) + { + resolveEdge(block, succBlock, ResolveJoin, outResolutionSet); + } } } } @@ -9161,6 +9581,9 @@ void LinearScan::resolveEdge(BasicBlock* fromBlock, // in resolveEdges(), after all the edge resolution has been done (by calling this // method for each edge). block = compiler->fgSplitEdge(fromBlock, toBlock); + + // Split edges are counted against fromBlock. + INTRACK_STATS(updateLsraStat(LSRA_STAT_SPLIT_EDGE, fromBlock->bbNum)); break; default: unreached(); @@ -9347,11 +9770,13 @@ void LinearScan::resolveEdge(BasicBlock* fromBlock, { useSwap = true; } -#else // !_TARGET_XARCH_ +#else // !_TARGET_XARCH_ + else { tempReg = tempRegInt; } + #endif // !_TARGET_XARCH_ if (useSwap || tempReg == REG_NA) { @@ -9396,6 +9821,8 @@ void LinearScan::resolveEdge(BasicBlock* fromBlock, sourceIntervals[sourceReg]->varNum, fromReg); location[sourceReg] = REG_NA; location[source[otherTargetReg]] = (regNumberSmall)fromReg; + + INTRACK_STATS(updateLsraStat(LSRA_STAT_RESOLUTION_MOV, block->bbNum)); } else { @@ -9406,6 +9833,7 @@ void LinearScan::resolveEdge(BasicBlock* fromBlock, // First, spill "otherInterval" from targetReg to the stack. Interval* otherInterval = sourceIntervals[source[otherTargetReg]]; + setIntervalAsSpilled(otherInterval); addResolution(block, insertionPoint, otherInterval, REG_STK, targetReg); JITDUMP(" (%s)\n", resolveTypeName[resolveType]); location[source[otherTargetReg]] = REG_STK; @@ -9527,6 +9955,126 @@ void TreeNodeInfo::addInternalCandidates(LinearScan* lsra, regMaskTP mask) internalCandsIndex = (unsigned char)i; } +#if TRACK_LSRA_STATS +// ---------------------------------------------------------- +// updateLsraStat: Increment LSRA stat counter. +// +// Arguments: +// stat - LSRA stat enum +// bbNum - Basic block to which LSRA stat needs to be +// associated with. +// +void LinearScan::updateLsraStat(LsraStat stat, unsigned bbNum) +{ + if (bbNum > bbNumMaxBeforeResolution) + { + // This is a newly created basic block as part of resolution. + // These blocks contain resolution moves that are already accounted. + return; + } + + switch (stat) + { + case LSRA_STAT_SPILL: + ++(blockInfo[bbNum].spillCount); + break; + + case LSRA_STAT_COPY_REG: + ++(blockInfo[bbNum].copyRegCount); + break; + + case LSRA_STAT_RESOLUTION_MOV: + ++(blockInfo[bbNum].resolutionMovCount); + break; + + case LSRA_STAT_SPLIT_EDGE: + ++(blockInfo[bbNum].splitEdgeCount); + break; + + default: + break; + } +} + +// ----------------------------------------------------------- +// dumpLsraStats - dumps Lsra stats to given file. +// +// Arguments: +// file - file to which stats are to be written. +// +void LinearScan::dumpLsraStats(FILE* file) +{ + unsigned sumSpillCount = 0; + unsigned sumCopyRegCount = 0; + unsigned sumResolutionMovCount = 0; + unsigned sumSplitEdgeCount = 0; + UINT64 wtdSpillCount = 0; + UINT64 wtdCopyRegCount = 0; + UINT64 wtdResolutionMovCount = 0; + + fprintf(file, "----------\n"); + fprintf(file, "LSRA Stats"); +#ifdef DEBUG + if (!VERBOSE) + { + fprintf(file, " : %s\n", compiler->info.compFullName); + } + else + { + // In verbose mode no need to print full name + // while printing lsra stats. + fprintf(file, "\n"); + } +#else + fprintf(file, " : %s\n", compiler->eeGetMethodFullName(compiler->info.compCompHnd)); +#endif + + fprintf(file, "----------\n"); + + for (BasicBlock* block = compiler->fgFirstBB; block != nullptr; block = block->bbNext) + { + if (block->bbNum > bbNumMaxBeforeResolution) + { + continue; + } + + unsigned spillCount = blockInfo[block->bbNum].spillCount; + unsigned copyRegCount = blockInfo[block->bbNum].copyRegCount; + unsigned resolutionMovCount = blockInfo[block->bbNum].resolutionMovCount; + unsigned splitEdgeCount = blockInfo[block->bbNum].splitEdgeCount; + + if (spillCount != 0 || copyRegCount != 0 || resolutionMovCount != 0 || splitEdgeCount != 0) + { + fprintf(file, "BB%02u [%8d]: ", block->bbNum, block->bbWeight); + fprintf(file, "SpillCount = %d, ResolutionMovs = %d, SplitEdges = %d, CopyReg = %d\n", spillCount, + resolutionMovCount, splitEdgeCount, copyRegCount); + } + + sumSpillCount += spillCount; + sumCopyRegCount += copyRegCount; + sumResolutionMovCount += resolutionMovCount; + sumSplitEdgeCount += splitEdgeCount; + + wtdSpillCount += (UINT64)spillCount * block->bbWeight; + wtdCopyRegCount += (UINT64)copyRegCount * block->bbWeight; + wtdResolutionMovCount += (UINT64)resolutionMovCount * block->bbWeight; + } + + fprintf(file, "Total Spill Count: %d Weighted: %I64u\n", sumSpillCount, wtdSpillCount); + fprintf(file, "Total CopyReg Count: %d Weighted: %I64u\n", sumCopyRegCount, wtdCopyRegCount); + fprintf(file, "Total ResolutionMov Count: %d Weighted: %I64u\n", sumResolutionMovCount, wtdResolutionMovCount); + fprintf(file, "Total number of split edges: %d\n", sumSplitEdgeCount); + + // compute total number of spill temps created + unsigned numSpillTemps = 0; + for (int i = 0; i < TYP_COUNT; i++) + { + numSpillTemps += maxSpill[i]; + } + fprintf(file, "Total Number of spill temps created: %d\n\n", numSpillTemps); +} +#endif // TRACK_LSRA_STATS + #ifdef DEBUG void dumpRegMask(regMaskTP regs) { @@ -9645,6 +10193,11 @@ void RefPosition::dump() { printf(" outOfOrder"); } + + if (this->AllocateIfProfitable()) + { + printf(" regOptional"); + } printf(">\n"); } @@ -11329,9 +11882,18 @@ void LinearScan::verifyFinalAllocation() { if (VERBOSE) { + // If refPos is marked as copyReg, then the reg that is spilled + // is the homeReg of the interval not the reg currently assigned + // to refPos. + regNumber spillReg = regNum; + if (currentRefPosition->copyReg) + { + assert(interval != nullptr); + spillReg = interval->physReg; + } dumpRegRecords(); dumpEmptyRefPosition(); - printf("Spill %-4s ", getRegName(regNum)); + printf("Spill %-4s ", getRegName(spillReg)); } } else if (currentRefPosition->copyReg) @@ -11392,15 +11954,14 @@ void LinearScan::verifyFinalAllocation() interval->physReg = REG_NA; interval->assignedReg = nullptr; - // regRegcord could be null if RefPosition is to be allocated a - // reg only if profitable. + // regRegcord could be null if the RefPosition does not require a register. if (regRecord != nullptr) { regRecord->assignedInterval = nullptr; } else { - assert(currentRefPosition->AllocateIfProfitable()); + assert(!currentRefPosition->RequiresRegister()); } } } @@ -11506,6 +12067,8 @@ void LinearScan::verifyResolutionMove(GenTree* resolutionMove, LsraLocation curr assert(leftInterval->physReg == leftRegNum && rightInterval->physReg == rightRegNum); leftInterval->physReg = rightRegNum; rightInterval->physReg = leftRegNum; + leftInterval->assignedReg = &physRegs[rightRegNum]; + rightInterval->assignedReg = &physRegs[leftRegNum]; physRegs[rightRegNum].assignedInterval = leftInterval; physRegs[leftRegNum].assignedInterval = rightInterval; if (VERBOSE) diff --git a/src/jit/lsra.h b/src/jit/lsra.h index a3c41fe..c8a3fb4 100644 --- a/src/jit/lsra.h +++ b/src/jit/lsra.h @@ -73,6 +73,25 @@ struct LsraBlockInfo unsigned int predBBNum; bool hasCriticalInEdge; bool hasCriticalOutEdge; + +#if TRACK_LSRA_STATS + // Per block maintained LSRA statistics. + + // Number of spills of local vars or tree temps in this basic block. + unsigned spillCount; + + // Number of GT_COPY nodes inserted in this basic block while allocating regs. + // Note that GT_COPY nodes are also inserted as part of basic block boundary + // resolution, which are accounted against resolutionMovCount but not + // against copyRegCount. + unsigned copyRegCount; + + // Number of resolution moves inserted in this basic block. + unsigned resolutionMovCount; + + // Number of critical edges from this block that are split. + unsigned splitEdgeCount; +#endif // TRACK_LSRA_STATS }; // This is sort of a bit mask @@ -504,6 +523,8 @@ private: { return (LsraStressLimitRegs)(lsraStressMask & LSRA_LIMIT_MASK); } + + regMaskTP getConstrainedRegMask(regMaskTP regMaskActual, regMaskTP regMaskConstrain, unsigned minRegCount); regMaskTP stressLimitRegs(RefPosition* refPosition, regMaskTP mask); // This controls the heuristics used to select registers @@ -572,7 +593,7 @@ private: regNumber rotateBlockStartLocation(Interval* interval, regNumber targetReg, regMaskTP availableRegs); // This controls whether we always insert a GT_RELOAD instruction after a spill - // Note that this can be combined with LsraSpillAlways (or not) + // Note that this can be combined with LSRA_SPILL_ALWAYS (or not) enum LsraReload{LSRA_NO_RELOAD_IF_SAME = 0, LSRA_ALWAYS_INSERT_RELOAD = 0x400, LSRA_RELOAD_MASK = 0x400}; LsraReload getLsraReload() { @@ -769,11 +790,19 @@ private: regMaskTP getDefCandidates(GenTree* tree); var_types getDefType(GenTree* tree); - RefPosition* defineNewInternalTemp(GenTree* tree, RegisterType regType, LsraLocation currentLoc, regMaskTP regMask); + RefPosition* defineNewInternalTemp(GenTree* tree, + RegisterType regType, + LsraLocation currentLoc, + regMaskTP regMask DEBUGARG(unsigned minRegCandidateCount)); - int buildInternalRegisterDefsForNode(GenTree* tree, LsraLocation currentLoc, RefPosition* defs[]); + int buildInternalRegisterDefsForNode(GenTree* tree, + LsraLocation currentLoc, + RefPosition* defs[] DEBUGARG(unsigned minRegCandidateCount)); - void buildInternalRegisterUsesForNode(GenTree* tree, LsraLocation currentLoc, RefPosition* defs[], int total); + void buildInternalRegisterUsesForNode(GenTree* tree, + LsraLocation currentLoc, + RefPosition* defs[], + int total DEBUGARG(unsigned minRegCandidateCount)); void resolveLocalRef(BasicBlock* block, GenTreePtr treeNode, RefPosition* currentRefPosition); @@ -824,7 +853,7 @@ private: RefType theRefType, GenTree* theTreeNode, regMaskTP mask, - unsigned multiRegIdx = 0); + unsigned multiRegIdx = 0 DEBUGARG(unsigned minRegCandidateCount = 1)); RefPosition* newRefPosition( regNumber reg, LsraLocation theLocation, RefType theRefType, GenTree* theTreeNode, regMaskTP mask); @@ -864,6 +893,8 @@ private: unassignPhysReg(getRegisterRecord(reg), nullptr); } + void setIntervalAsSpilled(Interval* interval); + void setIntervalAsSplit(Interval* interval); void spillInterval(Interval* interval, RefPosition* fromRefPosition, RefPosition* toRefPosition); void spillGCRefs(RefPosition* killRefPosition); @@ -936,11 +967,8 @@ private: char* operandString, unsigned operandStringLength); void lsraDispNode(GenTreePtr tree, LsraTupleDumpMode mode, bool hasDest); - void DumpOperandDefs(GenTree* operand, - bool& first, - LsraTupleDumpMode mode, - char* operandString, - const unsigned operandStringLength); + void DumpOperandDefs( + GenTree* operand, bool& first, LsraTupleDumpMode mode, char* operandString, const unsigned operandStringLength); void TupleStyleDump(LsraTupleDumpMode mode); bool dumpTerse; @@ -1020,6 +1048,20 @@ private: void validateIntervals(); #endif // DEBUG +#if TRACK_LSRA_STATS + enum LsraStat{ + LSRA_STAT_SPILL, LSRA_STAT_COPY_REG, LSRA_STAT_RESOLUTION_MOV, LSRA_STAT_SPLIT_EDGE, + }; + + void updateLsraStat(LsraStat stat, unsigned currentBBNum); + + void dumpLsraStats(FILE* file); + +#define INTRACK_STATS(x) x +#else // !TRACK_LSRA_STATS +#define INTRACK_STATS(x) +#endif // !TRACK_LSRA_STATS + Compiler* compiler; private: @@ -1066,6 +1108,10 @@ private: return BlockSetOps::IsMember(compiler, bbVisitedSet, block->bbNum); } +#if DOUBLE_ALIGN + bool doDoubleAlign; +#endif + // A map from bbNum to the block information used during register allocation. LsraBlockInfo* blockInfo; BasicBlock* findPredBlockForLiveIn(BasicBlock* block, BasicBlock* prevBlock DEBUGARG(bool* pPredBlockIsAllocated)); @@ -1092,6 +1138,8 @@ private: unsigned int bbSeqCount; // The Location of the start of the current block. LsraLocation curBBStartLocation; + // True if the method contains any critical edges. + bool hasCriticalEdges; // Ordered list of RefPositions RefPositionList refPositions; @@ -1111,6 +1159,12 @@ private: // Current set of live tracked vars, used during building of RefPositions to determine whether // to preference to callee-save VARSET_TP currentLiveVars; + // Set of variables that may require resolution across an edge. + // This is first constructed during interval building, to contain all the lclVars that are live at BB edges. + // Then, any lclVar that is always in the same register is removed from the set. + VARSET_TP resolutionCandidateVars; + // This set contains all the lclVars that are ever spilled or split. + VARSET_TP splitOrSpilledVars; // Set of floating point variables to consider for callee-save registers. VARSET_TP fpCalleeSaveCandidateVars; #if FEATURE_PARTIAL_SIMD_CALLEE_SAVE @@ -1382,6 +1436,7 @@ public: , delayRegFree(false) , outOfOrder(false) #ifdef DEBUG + , minRegCandidateCount(1) , rpNum(0) #endif { @@ -1555,9 +1610,15 @@ public: } #ifdef DEBUG - unsigned rpNum; // The unique RefPosition number, equal to its index in the refPositions list. Only used for - // debugging dumps. -#endif // DEBUG + // Minimum number registers that needs to be ensured while + // constraining candidates for this ref position under + // LSRA stress. + unsigned minRegCandidateCount; + + // The unique RefPosition number, equal to its index in the + // refPositions list. Only used for debugging dumps. + unsigned rpNum; +#endif // DEBUG bool isIntervalRef() { diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp index 00df17b..678bb34 100644 --- a/src/jit/morph.cpp +++ b/src/jit/morph.cpp @@ -204,6 +204,9 @@ GenTreePtr Compiler::fgMorphCast(GenTreePtr tree) { case TYP_INT: #ifdef _TARGET_X86_ // there is no rounding convert to integer instruction on ARM or x64 so skip this +#ifdef LEGACY_BACKEND + // the RyuJIT backend does not use the x87 FPU and therefore + // does not support folding the cast conv.i4(round.d(d)) if ((oper->gtOper == GT_INTRINSIC) && (oper->gtIntrinsic.gtIntrinsicId == CORINFO_INTRINSIC_Round)) { @@ -212,7 +215,9 @@ GenTreePtr Compiler::fgMorphCast(GenTreePtr tree) return fgMorphTree(oper); } // if SSE2 is not enabled, we need the helper - else if (!opts.compCanUseSSE2) + else +#endif // LEGACY_BACKEND + if (!opts.compCanUseSSE2) { return fgMorphCastIntoHelper(tree, CORINFO_HELP_DBL2INT, oper); } @@ -360,8 +365,17 @@ GenTreePtr Compiler::fgMorphCast(GenTreePtr tree) oper = gtNewCastNode(TYP_LONG, oper, TYP_LONG); oper->gtFlags |= (tree->gtFlags & (GTF_OVERFLOW | GTF_EXCEPT | GTF_UNSIGNED)); tree->gtFlags &= ~GTF_UNSIGNED; +#ifndef LEGACY_BACKEND + return fgMorphCastIntoHelper(tree, CORINFO_HELP_LNG2DBL, oper); +#endif } } +#ifndef LEGACY_BACKEND + else if (((tree->gtFlags & GTF_UNSIGNED) == 0) && (srcType == TYP_LONG) && varTypeIsFloating(dstType)) + { + return fgMorphCastIntoHelper(tree, CORINFO_HELP_LNG2DBL, oper); + } +#endif #endif //_TARGET_XARCH_ else if (varTypeIsGC(srcType) != varTypeIsGC(dstType)) { @@ -1010,12 +1024,12 @@ fgArgInfo::fgArgInfo(GenTreePtr newCall, GenTreePtr oldCall) { /* Get hold of the next argument values for the oldCall and newCall */ - assert(newArgs->IsList()); + assert(newArgs->OperIsList()); newCurr = newArgs->Current(); newArgs = newArgs->Rest(); - assert(oldArgs->IsList()); + assert(oldArgs->OperIsList()); oldCurr = oldArgs->Current(); oldArgs = oldArgs->Rest(); @@ -1047,6 +1061,8 @@ fgArgInfo::fgArgInfo(GenTreePtr newCall, GenTreePtr oldCall) argCount = oldArgInfo->argCount; nextSlotNum = oldArgInfo->nextSlotNum; + hasRegArgs = oldArgInfo->hasRegArgs; + hasStackArgs = oldArgInfo->hasStackArgs; argsComplete = true; argsSorted = true; } @@ -1188,7 +1204,7 @@ fgArgTabEntry* fgArgInfo::RemorphRegArg( GenTreePtr argx; if (curArgTabEntry->parent != nullptr) { - assert(curArgTabEntry->parent->IsList()); + assert(curArgTabEntry->parent->OperIsList()); argx = curArgTabEntry->parent->Current(); isRegArg = (argx->gtFlags & GTF_LATE_ARG) != 0; } @@ -1255,7 +1271,7 @@ void fgArgInfo::RemorphStkArg( if (curArgTabEntry->parent != nullptr) { - assert(curArgTabEntry->parent->IsList()); + assert(curArgTabEntry->parent->OperIsList()); argx = curArgTabEntry->parent->Current(); isRegArg = (argx->gtFlags & GTF_LATE_ARG) != 0; } @@ -1283,7 +1299,7 @@ void fgArgInfo::RemorphStkArg( assert(curArgTabEntry->numSlots == numSlots); assert(curArgTabEntry->alignment == alignment); assert(curArgTabEntry->parent == parent); - assert(parent->IsList()); + assert(parent->OperIsList()); #if FEATURE_FIXED_OUT_ARGS if (curArgTabEntry->node != node) @@ -1512,7 +1528,7 @@ void fgArgInfo::ArgsComplete() #ifndef LEGACY_BACKEND #if FEATURE_MULTIREG_ARGS - // For RyuJIT backend we will expand a Multireg arg into a GT_LIST + // For RyuJIT backend we will expand a Multireg arg into a GT_FIELD_LIST // with multiple indirections, so here we consider spilling it into a tmp LclVar. // // Note that Arm32 is a LEGACY_BACKEND and it defines FEATURE_MULTIREG_ARGS @@ -2364,7 +2380,7 @@ void fgArgInfo::EvalArgsToTemps() { GenTreePtr parent = curArgTabEntry->parent; /* a normal argument from the list */ - noway_assert(parent->IsList()); + noway_assert(parent->OperIsList()); noway_assert(parent->gtOp.gtOp1 == argx); parent->gtOp.gtOp1 = setupArg; @@ -2387,7 +2403,7 @@ void fgArgInfo::EvalArgsToTemps() } else { - noway_assert(tmpRegArgNext->IsList()); + noway_assert(tmpRegArgNext->OperIsList()); noway_assert(tmpRegArgNext->Current()); tmpRegArgNext->gtOp.gtOp2 = compiler->gtNewArgList(defArg); tmpRegArgNext = tmpRegArgNext->Rest(); @@ -2603,7 +2619,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) unsigned argSlots = 0; unsigned nonRegPassedStructSlots = 0; - bool lateArgsComputed = (call->gtCallLateArgs != nullptr); + bool reMorphing = call->AreArgsComplete(); bool callHasRetBuffArg = call->HasRetBufArg(); #ifndef _TARGET_X86_ // i.e. _TARGET_AMD64_ or _TARGET_ARM_ @@ -2731,7 +2747,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) // Process the late arguments (which were determined by a previous caller). // Do this before resetting fgPtrArgCntCur as fgMorphTree(call->gtCallLateArgs) // may need to refer to it. - if (lateArgsComputed) + if (reMorphing) { // We need to reMorph the gtCallLateArgs early since that is what triggers // the expression folding and we need to have the final folded gtCallLateArgs @@ -2745,14 +2761,17 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) // // Since the late arguments are evaluated last we have pushed all of the // other arguments on the stack before we evaluate these late arguments, - // so we record the stack depth on the first morph call when lateArgsComputed + // so we record the stack depth on the first morph call when reMorphing // was false (via RecordStkLevel) and then retrieve that value here (via RetrieveStkLevel) // unsigned callStkLevel = call->fgArgInfo->RetrieveStkLevel(); - fgPtrArgCntCur += callStkLevel; - call->gtCallLateArgs = fgMorphTree(call->gtCallLateArgs)->AsArgList(); - flagsSummary |= call->gtCallLateArgs->gtFlags; - fgPtrArgCntCur -= callStkLevel; + if (call->gtCallLateArgs != nullptr) + { + fgPtrArgCntCur += callStkLevel; + call->gtCallLateArgs = fgMorphTree(call->gtCallLateArgs)->AsArgList(); + flagsSummary |= call->gtCallLateArgs->gtFlags; + fgPtrArgCntCur -= callStkLevel; + } assert(call->fgArgInfo != nullptr); call->fgArgInfo->RemorphReset(); @@ -2780,7 +2799,8 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) // *********** END NOTE ********* CLANG_FORMAT_COMMENT_ANCHOR; -#if !defined(LEGACY_BACKEND) && defined(_TARGET_X86_) +#if !defined(LEGACY_BACKEND) +#if defined(_TARGET_X86_) // The x86 CORINFO_HELP_INIT_PINVOKE_FRAME helper has a custom calling convention. Set the argument registers // correctly here. if (call->IsHelperCall(this, CORINFO_HELP_INIT_PINVOKE_FRAME)) @@ -2792,21 +2812,20 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) } // The x86 shift helpers have custom calling conventions and expect the lo part of the long to be in EAX and the // hi part to be in EDX. This sets the argument registers up correctly. - else if (call->IsHelperCall(this, CORINFO_HELP_LLSH) || call->IsHelperCall(this, CORINFO_HELP_LRSH) || call->IsHelperCall(this, CORINFO_HELP_LRSZ)) + else if (call->IsHelperCall(this, CORINFO_HELP_LLSH) || call->IsHelperCall(this, CORINFO_HELP_LRSH) || + call->IsHelperCall(this, CORINFO_HELP_LRSZ)) { GenTreeArgList* args = call->gtCallArgs; - GenTree* arg1 = args->Current(); + GenTree* arg1 = args->Current(); assert(arg1 != nullptr); nonStandardArgs.Add(arg1, REG_LNGARG_LO); - args = args->Rest(); + args = args->Rest(); GenTree* arg2 = args->Current(); assert(arg2 != nullptr); nonStandardArgs.Add(arg2, REG_LNGARG_HI); } -#endif // !defined(LEGACY_BACKEND) && defined(_TARGET_X86_) - -#if !defined(LEGACY_BACKEND) && !defined(_TARGET_X86_) +#else // !defined(_TARGET_X86_) // TODO-X86-CQ: Currently RyuJIT/x86 passes args on the stack, so this is not needed. // If/when we change that, the following code needs to be changed to correctly support the (TBD) managed calling // convention for x86/SSE. @@ -2817,7 +2836,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) { args = call->gtCallArgs; assert(args != nullptr); - assert(args->IsList()); + assert(args->OperIsList()); argx = call->gtCallArgs->Current(); @@ -2871,21 +2890,32 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) nonStandardArgs.Add(arg, REG_VIRTUAL_STUB_PARAM); } - else if (call->gtCallType == CT_INDIRECT && call->gtCallCookie) + else +#endif // defined(_TARGET_X86_) + if (call->gtCallType == CT_INDIRECT && (call->gtCallCookie != nullptr)) { assert(!call->IsUnmanaged()); - // put cookie into R11 GenTree* arg = call->gtCallCookie; noway_assert(arg != nullptr); call->gtCallCookie = nullptr; +#if defined(_TARGET_X86_) + // x86 passes the cookie on the stack as the final argument to the call. + GenTreeArgList** insertionPoint = &call->gtCallArgs; + for (; *insertionPoint != nullptr; insertionPoint = &(*insertionPoint)->Rest()) + { + } + *insertionPoint = gtNewListNode(arg, nullptr); +#else // !defined(_TARGET_X86_) + // All other architectures pass the cookie in a register. call->gtCallArgs = gtNewListNode(arg, call->gtCallArgs); - numArgs++; +#endif // defined(_TARGET_X86_) nonStandardArgs.Add(arg, REG_PINVOKE_COOKIE_PARAM); + numArgs++; - // put destination into R10 + // put destination into R10/EAX arg = gtClone(call->gtCallAddr, true); call->gtCallArgs = gtNewListNode(arg, call->gtCallArgs); numArgs++; @@ -2896,7 +2926,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) call->gtCallType = CT_HELPER; call->gtCallMethHnd = eeFindHelper(CORINFO_HELP_PINVOKE_CALLI); } -#endif // !defined(LEGACY_BACKEND) && !defined(_TARGET_X86_) +#endif // !defined(LEGACY_BACKEND) // Allocate the fgArgInfo for the call node; // @@ -2929,7 +2959,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) /* We must fill in or update the argInfo table */ - if (lateArgsComputed) + if (reMorphing) { /* this is a register argument - possibly update it in the table */ call->fgArgInfo->RemorphRegArg(argIndex, argx, nullptr, genMapIntRegArgNumToRegNum(intArgRegNum), 1, 1); @@ -3075,7 +3105,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) *parentArgx = argx; flagsSummary |= argx->gtFlags; - assert(args->IsList()); + assert(args->OperIsList()); assert(argx == args->Current()); #ifndef LEGACY_BACKEND @@ -3114,13 +3144,15 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) compFloatingPointUsed = true; } - unsigned size = 0; - CORINFO_CLASS_HANDLE copyBlkClass = nullptr; - bool isRegArg = false; + unsigned size = 0; + CORINFO_CLASS_HANDLE copyBlkClass = nullptr; + bool isRegArg = false; + bool isNonStandard = false; + regNumber nonStdRegNum = REG_NA; fgArgTabEntryPtr argEntry = nullptr; - if (lateArgsComputed) + if (reMorphing) { argEntry = gtArgEntryByArgNum(call, argIndex); } @@ -3128,7 +3160,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) #ifdef _TARGET_ARM_ bool passUsingIntRegs; - if (lateArgsComputed) + if (reMorphing) { passUsingFloatRegs = isValidFloatArgReg(argEntry->regNum); passUsingIntRegs = isValidIntArgReg(argEntry->regNum); @@ -3179,7 +3211,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) #elif defined(_TARGET_ARM64_) - if (lateArgsComputed) + if (reMorphing) { passUsingFloatRegs = isValidFloatArgReg(argEntry->regNum); } @@ -3189,8 +3221,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) } #elif defined(_TARGET_AMD64_) -#if defined(UNIX_AMD64_ABI) - if (lateArgsComputed) + if (reMorphing) { passUsingFloatRegs = isValidFloatArgReg(argEntry->regNum); } @@ -3198,9 +3229,6 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) { passUsingFloatRegs = varTypeIsFloating(argx); } -#else // WINDOWS_AMD64_ABI - passUsingFloatRegs = varTypeIsFloating(argx); -#endif // !UNIX_AMD64_ABI #elif defined(_TARGET_X86_) passUsingFloatRegs = false; @@ -3216,7 +3244,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) bool isStructArg = varTypeIsStruct(argx); - if (lateArgsComputed) + if (reMorphing) { #if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) // Get the struct description for the already completed struct argument. @@ -3260,7 +3288,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) // This size has now been computed assert(size != 0); } - else // !lateArgsComputed + else // !reMorphing { // // Figure out the size of the argument. This is either in number of registers, or number of @@ -3287,7 +3315,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) } } #else // !FEATURE_UNIX_AMD64_STRUCT_PASSING - size = 1; // On AMD64, all primitives fit in a single (64-bit) 'slot' + size = 1; // On AMD64, all primitives fit in a single (64-bit) 'slot' #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING #elif defined(_TARGET_ARM64_) if (isStructArg) @@ -3379,7 +3407,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) GenTreePtr argObj = argx; GenTreePtr* parentOfArgObj = parentArgx; - assert(args->IsList()); + assert(args->OperIsList()); assert(argx == args->Current()); /* The GT_OBJ may be be a child of a GT_COMMA */ @@ -3686,11 +3714,6 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) // the obj reading memory past the end of the valuetype CLANG_FORMAT_COMMENT_ANCHOR; -#if defined(_TARGET_X86_) && !defined(LEGACY_BACKEND) - // TODO-X86-CQ: [1091733] Revisit for small structs, we should use push instruction - copyBlkClass = objClass; - size = roundupSize / TARGET_POINTER_SIZE; // Normalize size to number of pointer sized items -#else // !defined(_TARGET_X86_) || defined(LEGACY_BACKEND) if (roundupSize > originalSize) { copyBlkClass = objClass; @@ -3705,7 +3728,6 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) } size = roundupSize / TARGET_POINTER_SIZE; // Normalize size to number of pointer sized items -#endif // !defined(_TARGET_X86_) || defined(LEGACY_BACKEND) } } } @@ -3841,7 +3863,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) } } #else // !defined(UNIX_AMD64_ABI) - isRegArg = (intArgRegNum + (size - 1)) < maxRegArgs; + isRegArg = (intArgRegNum + (size - 1)) < maxRegArgs; #endif // !defined(UNIX_AMD64_ABI) #endif // _TARGET_ARM_ } @@ -3850,8 +3872,19 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) isRegArg = false; } -#if defined(_TARGET_X86_) && !defined(LEGACY_BACKEND) - if (call->IsTailCallViaHelper()) +#ifndef LEGACY_BACKEND + // If there are nonstandard args (outside the calling convention) they were inserted above + // and noted them in a table so we can recognize them here and build their argInfo. + // + // They should not affect the placement of any other args or stack space required. + // Example: on AMD64 R10 and R11 are used for indirect VSD (generic interface) and cookie calls. + isNonStandard = nonStandardArgs.FindReg(argx, &nonStdRegNum); + if (isNonStandard && (nonStdRegNum == REG_STK)) + { + isRegArg = false; + } +#if defined(_TARGET_X86_) + else if (call->IsTailCallViaHelper()) { // We have already (before calling fgMorphArgs()) appended the 4 special args // required by the x86 tailcall helper. These args are required to go on the @@ -3862,9 +3895,9 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) isRegArg = false; } } -#endif // defined(_TARGET_X86_) && !defined(LEGACY_BACKEND) - - } // end !lateArgsComputed +#endif // defined(_TARGET_X86_) +#endif // !LEGACY_BACKEND + } // end !reMorphing // // Now we know if the argument goes in registers or not and how big it is, @@ -3943,23 +3976,17 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) #endif fgArgTabEntryPtr newArgEntry; - if (lateArgsComputed) + if (reMorphing) { // This is a register argument - possibly update it in the table newArgEntry = call->fgArgInfo->RemorphRegArg(argIndex, argx, args, nextRegNum, size, argAlign); } else { - bool isNonStandard = false; - -#ifndef LEGACY_BACKEND - // If there are nonstandard args (outside the calling convention) they were inserted above - // and noted them in a table so we can recognize them here and build their argInfo. - // - // They should not affect the placement of any other args or stack space required. - // Example: on AMD64 R10 and R11 are used for indirect VSD (generic interface) and cookie calls. - isNonStandard = nonStandardArgs.FindReg(argx, &nextRegNum); -#endif // !LEGACY_BACKEND + if (isNonStandard) + { + nextRegNum = nonStdRegNum; + } // This is a register argument - put it in the table newArgEntry = call->fgArgInfo->AddRegArg(argIndex, argx, args, nextRegNum, size, argAlign @@ -4053,7 +4080,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) // If the register arguments have not been determined then we must fill in the argInfo - if (lateArgsComputed) + if (reMorphing) { // This is a stack argument - possibly update it in the table call->fgArgInfo->RemorphStkArg(argIndex, argx, args, size, argAlign); @@ -4068,14 +4095,14 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) if (copyBlkClass != NO_CLASS_HANDLE) { - noway_assert(!lateArgsComputed); + noway_assert(!reMorphing); fgMakeOutgoingStructArgCopy(call, args, argIndex, copyBlkClass FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(&structDesc)); // This can cause a GTF_EXCEPT flag to be set. // TODO-CQ: Fix the cases where this happens. We shouldn't be adding any new flags. // This currently occurs in the case where we are re-morphing the args on x86/RyuJIT, and - // there are no register arguments. Then lateArgsComputed is never true, so we keep re-copying + // there are no register arguments. Then reMorphing is never true, so we keep re-copying // any struct arguments. // i.e. assert(((call->gtFlags & GTF_EXCEPT) != 0) || ((args->Current()->gtFlags & GTF_EXCEPT) == 0) flagsSummary |= (args->Current()->gtFlags & GTF_EXCEPT); @@ -4088,10 +4115,21 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) #ifndef LEGACY_BACKEND if (argx->gtOper == GT_MKREFANY) { - NYI_X86("MKREFANY"); - // 'Lower' the MKREFANY tree and insert it. - noway_assert(!lateArgsComputed); + noway_assert(!reMorphing); + +#ifdef _TARGET_X86_ + + // Build the mkrefany as a GT_FIELD_LIST + GenTreeFieldList* fieldList = new (this, GT_FIELD_LIST) + GenTreeFieldList(argx->gtOp.gtOp1, offsetof(CORINFO_RefAny, dataPtr), TYP_BYREF, nullptr); + (void)new (this, GT_FIELD_LIST) + GenTreeFieldList(argx->gtOp.gtOp2, offsetof(CORINFO_RefAny, type), TYP_I_IMPL, fieldList); + fgArgTabEntryPtr fp = Compiler::gtArgEntryByNode(call, argx); + fp->node = fieldList; + args->gtOp.gtOp1 = fieldList; + +#else // !_TARGET_X86_ // Get a new temp // Here we don't need unsafe value cls check since the addr of temp is used only in mkrefany @@ -4117,9 +4155,47 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) // EvalArgsToTemps will cause tmp to actually get loaded as the argument call->fgArgInfo->EvalToTmp(argIndex, tmp, asg); lvaSetVarAddrExposed(tmp); +#endif // !_TARGET_X86_ } #endif // !LEGACY_BACKEND +#if defined(_TARGET_X86_) && !defined(LEGACY_BACKEND) + if (isStructArg) + { + GenTree* lclNode = fgIsIndirOfAddrOfLocal(argx); + if ((lclNode != nullptr) && + (lvaGetPromotionType(lclNode->AsLclVarCommon()->gtLclNum) == Compiler::PROMOTION_TYPE_INDEPENDENT)) + { + // Make a GT_FIELD_LIST of the field lclVars. + GenTreeLclVarCommon* lcl = lclNode->AsLclVarCommon(); + LclVarDsc* varDsc = &(lvaTable[lcl->gtLclNum]); + GenTreeFieldList* fieldList = nullptr; + for (unsigned fieldLclNum = varDsc->lvFieldLclStart; + fieldLclNum < varDsc->lvFieldLclStart + varDsc->lvFieldCnt; ++fieldLclNum) + { + LclVarDsc* fieldVarDsc = &lvaTable[fieldLclNum]; + if (fieldList == nullptr) + { + lcl->SetLclNum(fieldLclNum); + lcl->ChangeOper(GT_LCL_VAR); + lcl->gtType = fieldVarDsc->lvType; + fieldList = new (this, GT_FIELD_LIST) + GenTreeFieldList(lcl, fieldVarDsc->lvFldOffset, fieldVarDsc->lvType, nullptr); + fgArgTabEntryPtr fp = Compiler::gtArgEntryByNode(call, argx); + fp->node = fieldList; + args->gtOp.gtOp1 = fieldList; + } + else + { + GenTree* fieldLcl = gtNewLclvNode(fieldLclNum, fieldVarDsc->lvType); + fieldList = new (this, GT_FIELD_LIST) + GenTreeFieldList(fieldLcl, fieldVarDsc->lvFldOffset, fieldVarDsc->lvType, fieldList); + } + } + } + } +#endif // defined (_TARGET_X86_) && !defined(LEGACY_BACKEND) + #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING if (isStructArg && !isRegArg) { @@ -4132,7 +4208,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) } } // end foreach argument loop - if (!lateArgsComputed) + if (!reMorphing) { call->fgArgInfo->ArgsComplete(); #ifdef LEGACY_BACKEND @@ -4240,11 +4316,11 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) // For UNIX_AMD64, the condition without hasStackArgCopy cannot catch // all cases of fgMakeOutgoingStructArgCopy() being called. hasStackArgCopy // is added to make sure to call EvalArgsToTemp. - if (!lateArgsComputed && (call->fgArgInfo->HasRegArgs() + if (!reMorphing && (call->fgArgInfo->HasRegArgs() #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING - || hasStackArgCopy + || hasStackArgCopy #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING - )) + )) { // This is the first time that we morph this call AND it has register arguments. // Follow into the code below and do the 'defer or eval to temp' analysis. @@ -4271,7 +4347,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) // In the future we can migrate UNIX_AMD64 to use this // method instead of fgMorphSystemVStructArgs - // We only build GT_LISTs for MultiReg structs for the RyuJIT backend + // We only build GT_FIELD_LISTs for MultiReg structs for the RyuJIT backend if (hasMultiregStructArgs) { fgMorphMultiregStructArgs(call); @@ -4334,7 +4410,7 @@ void Compiler::fgMorphSystemVStructArgs(GenTreeCall* call, bool hasStructArgumen { for (GenTreePtr list = call->gtCallLateArgs; list; list = list->MoveNext()) { - assert(list->IsList()); + assert(list->OperIsList()); GenTreePtr argNode = list->Current(); if (argx == argNode) @@ -4355,7 +4431,7 @@ void Compiler::fgMorphSystemVStructArgs(GenTreeCall* call, bool hasStructArgumen { var_types originalType = type; // If we have already processed the arg... - if (arg->OperGet() == GT_LIST && varTypeIsStruct(arg)) + if (arg->OperGet() == GT_FIELD_LIST && varTypeIsStruct(arg)) { continue; } @@ -4386,6 +4462,16 @@ void Compiler::fgMorphSystemVStructArgs(GenTreeCall* call, bool hasStructArgumen // Create LCL_FLD for each eightbyte. argListCreated = true; + // First eightbyte. + arg->AsLclFld()->gtFieldSeq = FieldSeqStore::NotAField(); + arg->gtType = + GetTypeFromClassificationAndSizes(fgEntryPtr->structDesc.eightByteClassifications[0], + fgEntryPtr->structDesc.eightByteSizes[0]); + GenTreeFieldList* fieldList = + new (this, GT_FIELD_LIST) GenTreeFieldList(arg, 0, originalType, nullptr); + fieldList->gtType = originalType; // Preserve the type. It is a special case. + arg = fieldList; + // Second eightbyte. GenTreeLclFld* newLclField = new (this, GT_LCL_FLD) GenTreeLclFld(GetTypeFromClassificationAndSizes(fgEntryPtr->structDesc @@ -4393,17 +4479,9 @@ void Compiler::fgMorphSystemVStructArgs(GenTreeCall* call, bool hasStructArgumen fgEntryPtr->structDesc.eightByteSizes[1]), lclCommon->gtLclNum, fgEntryPtr->structDesc.eightByteOffsets[1]); - GenTreeArgList* aggregate = gtNewAggregate(newLclField); - aggregate->gtType = originalType; // Preserve the type. It is a special case. - newLclField->gtFieldSeq = FieldSeqStore::NotAField(); - - // First field - arg->AsLclFld()->gtFieldSeq = FieldSeqStore::NotAField(); - arg->gtType = - GetTypeFromClassificationAndSizes(fgEntryPtr->structDesc.eightByteClassifications[0], - fgEntryPtr->structDesc.eightByteSizes[0]); - arg = aggregate->Prepend(this, arg); - arg->gtType = type; // Preserve the type. It is a special case. + fieldList = new (this, GT_FIELD_LIST) GenTreeFieldList(newLclField, 0, originalType, fieldList); + fieldList->gtType = originalType; // Preserve the type. It is a special case. + newLclField->gtFieldSeq = FieldSeqStore::NotAField(); } else { @@ -4450,7 +4528,7 @@ void Compiler::fgMorphSystemVStructArgs(GenTreeCall* call, bool hasStructArgumen { for (GenTreePtr list = call->gtCallLateArgs; list; list = list->MoveNext()) { - assert(list->IsList()); + assert(list->OperIsList()); GenTreePtr argNode = list->Current(); if (argx == argNode) @@ -4490,8 +4568,8 @@ void Compiler::fgMorphSystemVStructArgs(GenTreeCall* call, bool hasStructArgumen // // Notes: // We only call fgMorphMultiregStructArg for the register passed TYP_STRUCT arguments. -// The call to fgMorphMultiregStructArg will mutate the argument into the GT_LIST form -// whicj is only used for register arguments. +// The call to fgMorphMultiregStructArg will mutate the argument into the GT_FIELD_LIST form +// which is only used for struct arguments. // If this method fails to find any TYP_STRUCT arguments it will assert. // void Compiler::fgMorphMultiregStructArgs(GenTreeCall* call) @@ -4540,7 +4618,7 @@ void Compiler::fgMorphMultiregStructArgs(GenTreeCall* call) { for (GenTreePtr list = call->gtCallLateArgs; list; list = list->MoveNext()) { - assert(list->IsList()); + assert(list->OperIsList()); GenTreePtr argNode = list->Current(); if (argx == argNode) @@ -4588,7 +4666,7 @@ void Compiler::fgMorphMultiregStructArgs(GenTreeCall* call) //----------------------------------------------------------------------------- // fgMorphMultiregStructArg: Given a multireg TYP_STRUCT arg from a call argument list -// Morph the argument into a set of GT_LIST nodes. +// Morph the argument into a set of GT_FIELD_LIST nodes. // // Arguments: // arg - A GenTree node containing a TYP_STRUCT arg that @@ -4600,7 +4678,7 @@ void Compiler::fgMorphMultiregStructArgs(GenTreeCall* call) // for passing in multiple registers. // If arg is a LclVar we check if it is struct promoted and has the right number of fields // and if they are at the appropriate offsets we will use the struct promted fields -// in the GT_LIST nodes that we create. +// in the GT_FIELD_LIST nodes that we create. // If we have a GT_LCL_VAR that isn't struct promoted or doesn't meet the requirements // we will use a set of GT_LCL_FLDs nodes to access the various portions of the struct // this also forces the struct to be stack allocated into the local frame. @@ -4715,7 +4793,7 @@ GenTreePtr Compiler::fgMorphMultiregStructArg(GenTreePtr arg, fgArgTabEntryPtr f // We should still have a TYP_STRUCT assert(argValue->TypeGet() == TYP_STRUCT); - GenTreeArgList* newArg = nullptr; + GenTreeFieldList* newArg = nullptr; // Are we passing a struct LclVar? // @@ -4817,9 +4895,10 @@ GenTreePtr Compiler::fgMorphMultiregStructArg(GenTreePtr arg, fgArgTabEntryPtr f // Create a new tree for 'arg' // replace the existing LDOBJ(ADDR(LCLVAR)) - // with a LIST(LCLVAR-LO, LIST(LCLVAR-HI, nullptr)) + // with a FIELD_LIST(LCLVAR-LO, FIELD_LIST(LCLVAR-HI, nullptr)) // - newArg = gtNewAggregate(hiLclVar)->Prepend(this, loLclVar); + newArg = new (this, GT_FIELD_LIST) GenTreeFieldList(loLclVar, 0, loType, nullptr); + (void)new (this, GT_FIELD_LIST) GenTreeFieldList(hiLclVar, TARGET_POINTER_SIZE, hiType, newArg); } } } @@ -4885,27 +4964,22 @@ GenTreePtr Compiler::fgMorphMultiregStructArg(GenTreePtr arg, fgArgTabEntryPtr f // lvaSetVarDoNotEnregister(varNum DEBUG_ARG(DNER_LocalField)); - // Start building our list from the last element - unsigned offset = lastOffset; - unsigned inx = elemCount; - // Create a new tree for 'arg' // replace the existing LDOBJ(ADDR(LCLVAR)) - // with a LIST(LCLFLD-LO, LIST(LCLFLD-HI, nullptr) ...) + // with a FIELD_LIST(LCLFLD-LO, FIELD_LIST(LCLFLD-HI, nullptr) ...) // - while (inx > 0) + unsigned offset = 0; + GenTreeFieldList* listEntry = nullptr; + for (unsigned inx = 0; inx < elemCount; inx++) { - inx--; - offset -= elemSize; + elemSize = genTypeSize(type[inx]); GenTreePtr nextLclFld = gtNewLclFldNode(varNum, type[inx], offset); + listEntry = new (this, GT_FIELD_LIST) GenTreeFieldList(nextLclFld, offset, type[inx], listEntry); if (newArg == nullptr) { - newArg = gtNewAggregate(nextLclFld); - } - else - { - newArg = newArg->Prepend(this, nextLclFld); + newArg = listEntry; } + offset += elemSize; } } // Are we passing a GT_OBJ struct? @@ -4918,17 +4992,14 @@ GenTreePtr Compiler::fgMorphMultiregStructArg(GenTreePtr arg, fgArgTabEntryPtr f // Create a new tree for 'arg' // replace the existing LDOBJ(EXPR) - // with a LIST(IND(EXPR), LIST(IND(EXPR+8), nullptr) ...) + // with a FIELD_LIST(IND(EXPR), FIELD_LIST(IND(EXPR+8), nullptr) ...) // - // Start building our list from the last element - unsigned offset = structSize; - unsigned inx = elemCount; - while (inx > 0) + unsigned offset = 0; + GenTreeFieldList* listEntry = nullptr; + for (unsigned inx = 0; inx < elemCount; inx++) { - inx--; - elemSize = genTypeSize(type[inx]); - offset -= elemSize; + elemSize = genTypeSize(type[inx]); GenTreePtr curAddr = baseAddr; if (offset != 0) { @@ -4941,14 +5012,21 @@ GenTreePtr Compiler::fgMorphMultiregStructArg(GenTreePtr arg, fgArgTabEntryPtr f curAddr = baseAddr; } GenTreePtr curItem = gtNewOperNode(GT_IND, type[inx], curAddr); - if (newArg == nullptr) + + // For safety all GT_IND should have at least GT_GLOB_REF set. + curItem->gtFlags |= GTF_GLOB_REF; + if (fgAddrCouldBeNull(curItem)) { - newArg = gtNewAggregate(curItem); + // This indirection can cause a GPF if the address could be null. + curItem->gtFlags |= GTF_EXCEPT; } - else + + listEntry = new (this, GT_FIELD_LIST) GenTreeFieldList(curItem, offset, type[inx], listEntry); + if (newArg == nullptr) { - newArg = newArg->Prepend(this, curItem); + newArg = listEntry; } + offset += elemSize; } } } @@ -5674,7 +5752,7 @@ GenTreePtr Compiler::fgMorphArrayIndex(GenTreePtr tree) addr = gtNewOperNode(GT_ADD, TYP_BYREF, addr, cns); #if SMALL_TREE_NODES - assert(tree->gtDebugFlags & GTF_DEBUG_NODE_LARGE); + assert((tree->gtDebugFlags & GTF_DEBUG_NODE_LARGE) || GenTree::s_gtNodeSizes[GT_IND] == TREE_NODE_SZ_SMALL); #endif // Change the orginal GT_INDEX node into a GT_IND node @@ -5847,7 +5925,15 @@ GenTreePtr Compiler::fgMorphStackArgForVarArgs(unsigned lclNum, var_types varTyp lclOffs)); // Access the argument through the local - GenTreePtr tree = gtNewOperNode(GT_IND, varType, ptrArg); + GenTreePtr tree; + if (varType == TYP_STRUCT) + { + tree = gtNewBlockVal(ptrArg, varDsc->lvExactSize); + } + else + { + tree = gtNewOperNode(GT_IND, varType, ptrArg); + } tree->gtFlags |= GTF_IND_TGTANYWHERE; if (varDsc->lvAddrExposed) @@ -5884,8 +5970,14 @@ GenTreePtr Compiler::fgMorphLocalVar(GenTreePtr tree) if (info.compIsVarArgs) { GenTreePtr newTree = fgMorphStackArgForVarArgs(lclNum, varType, 0); - if (newTree != NULL) + if (newTree != nullptr) + { + if (newTree->OperIsBlk() && ((tree->gtFlags & GTF_VAR_DEF) == 0)) + { + fgMorphBlkToInd(newTree->AsBlk(), newTree->gtType); + } return newTree; + } } #endif // _TARGET_X86_ @@ -6205,7 +6297,9 @@ GenTreePtr Compiler::fgMorphField(GenTreePtr tree, MorphAddrContext* mac) GenTreePtr baseOffset = gtNewIconEmbHndNode(tree->gtField.gtFieldLookup.addr, nullptr, GTF_ICON_FIELD_HDL); if (tree->gtField.gtFieldLookup.accessType == IAT_PVALUE) + { baseOffset = gtNewOperNode(GT_IND, TYP_I_IMPL, baseOffset); + } addr = gtNewOperNode(GT_ADD, (var_types)(objRefType == TYP_I_IMPL ? TYP_I_IMPL : TYP_BYREF), addr, baseOffset); @@ -6483,8 +6577,8 @@ void Compiler::fgMorphCallInline(GenTreeCall* call, InlineResult* inlineResult) // hanging a "nothing" node to it. Later the "nothing" node will be removed // and the original GT_CALL tree will be picked up by the GT_RET_EXPR node. - noway_assert(fgMorphStmt->gtStmt.gtStmtExpr == call); - fgMorphStmt->gtStmt.gtStmtExpr = gtNewNothingNode(); + noway_assert(fgMorphStmt->gtStmtExpr == call); + fgMorphStmt->gtStmtExpr = gtNewNothingNode(); } // Clear the Inline Candidate flag so we can ensure later we tried @@ -6662,7 +6756,7 @@ bool Compiler::fgCanFastTailCall(GenTreeCall* callee) { nCalleeArgs++; - assert(args->IsList()); + assert(args->OperIsList()); GenTreePtr argx = args->gtOp.gtOp1; if (varTypeIsStruct(argx)) @@ -6980,7 +7074,14 @@ void Compiler::fgMorphTailCall(GenTreeCall* call) } #endif // _TARGET_X86_ +#if defined(_TARGET_X86_) + // When targeting x86, the runtime requires that we perforrm a null check on the `this` argument before tail + // calling to a virtual dispatch stub. This requirement is a consequence of limitations in the runtime's + // ability to map an AV to a NullReferenceException if the AV occurs in a dispatch stub. + if (call->NeedsNullCheck() || call->IsVirtualStub()) +#else if (call->NeedsNullCheck()) +#endif // defined(_TARGET_X86_) { // clone "this" if "this" has no side effects. if ((thisPtr == nullptr) && !(objp->gtFlags & GTF_SIDE_EFFECT)) @@ -7668,17 +7769,39 @@ GenTreePtr Compiler::fgMorphCall(GenTreeCall* call) } #endif - GenTreePtr stmtExpr = fgMorphStmt->gtStmt.gtStmtExpr; + GenTreePtr stmtExpr = fgMorphStmt->gtStmtExpr; #ifdef DEBUG // Tail call needs to be in one of the following IR forms // Either a call stmt or - // GT_RETURN(GT_CALL(..)) or - // var = call - noway_assert((stmtExpr->gtOper == GT_CALL && stmtExpr == call) || - (stmtExpr->gtOper == GT_RETURN && - (stmtExpr->gtOp.gtOp1 == call || stmtExpr->gtOp.gtOp1->gtOp.gtOp1 == call)) || - (stmtExpr->gtOper == GT_ASG && stmtExpr->gtOp.gtOp2 == call)); + // GT_RETURN(GT_CALL(..)) or GT_RETURN(GT_CAST(GT_CALL(..))) + // var = GT_CALL(..) or var = (GT_CAST(GT_CALL(..))) + genTreeOps stmtOper = stmtExpr->gtOper; + if (stmtOper == GT_CALL) + { + noway_assert(stmtExpr == call); + } + else + { + noway_assert(stmtOper == GT_RETURN || stmtOper == GT_ASG); + GenTreePtr treeWithCall; + if (stmtOper == GT_RETURN) + { + treeWithCall = stmtExpr->gtGetOp1(); + } + else + { + treeWithCall = stmtExpr->gtGetOp2(); + } + if (treeWithCall->gtOper == GT_CAST) + { + noway_assert(treeWithCall->gtGetOp1() == call && !treeWithCall->gtOverflow()); + } + else + { + noway_assert(treeWithCall == call); + } + } #endif // For void calls, we would have created a GT_CALL in the stmt list. @@ -7687,7 +7810,7 @@ GenTreePtr Compiler::fgMorphCall(GenTreeCall* call) // For debuggable code, it would be an assignment of the call to a temp // We want to get rid of any of this extra trees, and just leave // the call. - GenTreePtr nextMorphStmt = fgMorphStmt->gtNext; + GenTreeStmt* nextMorphStmt = fgMorphStmt->gtNextStmt; #ifdef _TARGET_AMD64_ // Legacy Jit64 Compat: @@ -7703,46 +7826,46 @@ GenTreePtr Compiler::fgMorphCall(GenTreeCall* call) if ((stmtExpr->gtOper == GT_CALL) || (stmtExpr->gtOper == GT_ASG)) { // First delete all GT_NOPs after the call - GenTreePtr morphStmtToRemove = nullptr; + GenTreeStmt* morphStmtToRemove = nullptr; while (nextMorphStmt != nullptr) { - GenTreePtr nextStmtExpr = nextMorphStmt->gtStmt.gtStmtExpr; + GenTreePtr nextStmtExpr = nextMorphStmt->gtStmtExpr; if (!nextStmtExpr->IsNothingNode()) { break; } morphStmtToRemove = nextMorphStmt; - nextMorphStmt = morphStmtToRemove->gtNext; + nextMorphStmt = morphStmtToRemove->gtNextStmt; fgRemoveStmt(compCurBB, morphStmtToRemove); } // Check to see if there is a pop. // Since tail call is honored, we can get rid of the stmt corresponding to pop. - if (nextMorphStmt != nullptr && nextMorphStmt->gtStmt.gtStmtExpr->gtOper != GT_RETURN) + if (nextMorphStmt != nullptr && nextMorphStmt->gtStmtExpr->gtOper != GT_RETURN) { // Note that pop opcode may or may not result in a new stmt (for details see // impImportBlockCode()). Hence, it is not possible to assert about the IR // form generated by pop but pop tree must be side-effect free so that we can // delete it safely. - GenTreePtr popStmt = nextMorphStmt; - nextMorphStmt = nextMorphStmt->gtNext; + GenTreeStmt* popStmt = nextMorphStmt; + nextMorphStmt = nextMorphStmt->gtNextStmt; - noway_assert((popStmt->gtStmt.gtStmtExpr->gtFlags & GTF_ALL_EFFECT) == 0); + noway_assert((popStmt->gtStmtExpr->gtFlags & GTF_ALL_EFFECT) == 0); fgRemoveStmt(compCurBB, popStmt); } // Next delete any GT_NOP nodes after pop while (nextMorphStmt != nullptr) { - GenTreePtr nextStmtExpr = nextMorphStmt->gtStmt.gtStmtExpr; + GenTreePtr nextStmtExpr = nextMorphStmt->gtStmtExpr; if (!nextStmtExpr->IsNothingNode()) { break; } morphStmtToRemove = nextMorphStmt; - nextMorphStmt = morphStmtToRemove->gtNext; + nextMorphStmt = morphStmtToRemove->gtNextStmt; fgRemoveStmt(compCurBB, morphStmtToRemove); } } @@ -7751,7 +7874,7 @@ GenTreePtr Compiler::fgMorphCall(GenTreeCall* call) // Delete GT_RETURN if any if (nextMorphStmt != nullptr) { - GenTreePtr retExpr = nextMorphStmt->gtStmt.gtStmtExpr; + GenTreePtr retExpr = nextMorphStmt->gtStmtExpr; noway_assert(retExpr->gtOper == GT_RETURN); // If var=call, then the next stmt must be a GT_RETURN(TYP_VOID) or GT_RETURN(var). @@ -7766,7 +7889,7 @@ GenTreePtr Compiler::fgMorphCall(GenTreeCall* call) fgRemoveStmt(compCurBB, nextMorphStmt); } - fgMorphStmt->gtStmt.gtStmtExpr = call; + fgMorphStmt->gtStmtExpr = call; // Tail call via helper: The VM can't use return address hijacking if we're // not going to return and the helper doesn't have enough info to safely poll, @@ -7855,7 +7978,7 @@ NO_TAIL_CALL: || call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_READYTORUN_VIRTUAL_FUNC_PTR) #endif ) && - (call == fgMorphStmt->gtStmt.gtStmtExpr)) + (call == fgMorphStmt->gtStmtExpr)) { // This is call to CORINFO_HELP_VIRTUAL_FUNC_PTR with ignored result. // Transform it into a null check. @@ -8008,31 +8131,72 @@ NO_TAIL_CALL: // This needs to be done after the arguments are morphed to ensure constant propagation has already taken place. if ((call->gtCallType == CT_HELPER) && (call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_ARRADDR_ST))) { - GenTreePtr value = gtArgEntryByArgNum(call, 2)->node; - + GenTree* value = gtArgEntryByArgNum(call, 2)->node; if (value->IsIntegralConst(0)) { assert(value->OperGet() == GT_CNS_INT); - GenTreePtr arr = gtArgEntryByArgNum(call, 0)->node; - GenTreePtr index = gtArgEntryByArgNum(call, 1)->node; - arr = gtClone(arr, true); - if (arr != nullptr) + GenTree* arr = gtArgEntryByArgNum(call, 0)->node; + GenTree* index = gtArgEntryByArgNum(call, 1)->node; + + // Either or both of the array and index arguments may have been spilled to temps by `fgMorphArgs`. Copy + // the spill trees as well if necessary. + GenTreeOp* argSetup = nullptr; + for (GenTreeArgList* earlyArgs = call->gtCallArgs; earlyArgs != nullptr; earlyArgs = earlyArgs->Rest()) { - index = gtClone(index, true); - if (index != nullptr) + GenTree* const arg = earlyArgs->Current(); + if (arg->OperGet() != GT_ASG) { - value = gtClone(value); - noway_assert(value != nullptr); + continue; + } + + assert(arg != arr); + assert(arg != index); - GenTreePtr nullCheckedArr = impCheckForNullPointer(arr); - GenTreePtr arrIndexNode = gtNewIndexRef(TYP_REF, nullCheckedArr, index); - GenTreePtr arrStore = gtNewAssignNode(arrIndexNode, value); - arrStore->gtFlags |= GTF_ASG; + arg->gtFlags &= ~GTF_LATE_ARG; - return fgMorphTree(arrStore); + GenTree* op1 = argSetup; + if (op1 == nullptr) + { + op1 = gtNewNothingNode(); +#if DEBUG + op1->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED; +#endif // DEBUG } + + argSetup = new (this, GT_COMMA) GenTreeOp(GT_COMMA, TYP_VOID, op1, arg); + +#if DEBUG + argSetup->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED; +#endif // DEBUG + } + +#ifdef DEBUG + auto resetMorphedFlag = [](GenTree** slot, fgWalkData* data) -> fgWalkResult { + (*slot)->gtDebugFlags &= ~GTF_DEBUG_NODE_MORPHED; + return WALK_CONTINUE; + }; + + fgWalkTreePost(&arr, resetMorphedFlag); + fgWalkTreePost(&index, resetMorphedFlag); + fgWalkTreePost(&value, resetMorphedFlag); +#endif // DEBUG + + GenTree* const nullCheckedArr = impCheckForNullPointer(arr); + GenTree* const arrIndexNode = gtNewIndexRef(TYP_REF, nullCheckedArr, index); + GenTree* const arrStore = gtNewAssignNode(arrIndexNode, value); + arrStore->gtFlags |= GTF_ASG; + + GenTree* result = fgMorphTree(arrStore); + if (argSetup != nullptr) + { + result = new (this, GT_COMMA) GenTreeOp(GT_COMMA, TYP_VOID, argSetup, result); +#if DEBUG + result->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED; +#endif // DEBUG } + + return result; } } @@ -8187,8 +8351,14 @@ GenTreePtr Compiler::fgMorphLeaf(GenTreePtr tree) { GenTreePtr newTree = fgMorphStackArgForVarArgs(tree->gtLclFld.gtLclNum, tree->gtType, tree->gtLclFld.gtLclOffs); - if (newTree != NULL) + if (newTree != nullptr) + { + if (newTree->OperIsBlk() && ((tree->gtFlags & GTF_VAR_DEF) == 0)) + { + fgMorphBlkToInd(newTree->AsBlk(), newTree->gtType); + } return newTree; + } } } #endif // _TARGET_X86_ @@ -8390,7 +8560,7 @@ GenTreePtr Compiler::fgMorphOneAsgBlockOp(GenTreePtr tree) // with the bits to create a single assigment. noway_assert(size <= REGSIZE_BYTES); - if (isInitBlock && (src->gtOper != GT_CNS_INT)) + if (isInitBlock && !src->IsConstInitVal()) { return nullptr; } @@ -8563,8 +8733,12 @@ GenTreePtr Compiler::fgMorphOneAsgBlockOp(GenTreePtr tree) } else #endif - if (src->IsCnsIntOrI()) { + if (src->OperIsInitVal()) + { + src = src->gtGetOp1(); + } + assert(src->IsCnsIntOrI()); // This will mutate the integer constant, in place, to be the correct // value for the type we are using in the assignment. src->AsIntCon()->FixupInitBlkValue(asgType); @@ -8632,7 +8806,8 @@ GenTreePtr Compiler::fgMorphOneAsgBlockOp(GenTreePtr tree) GenTreePtr Compiler::fgMorphInitBlock(GenTreePtr tree) { - noway_assert(tree->gtOper == GT_ASG && varTypeIsStruct(tree)); + // We must have the GT_ASG form of InitBlkOp. + noway_assert((tree->OperGet() == GT_ASG) && tree->OperIsInitBlkOp()); #ifdef DEBUG bool morphed = false; #endif // DEBUG @@ -8647,6 +8822,12 @@ GenTreePtr Compiler::fgMorphInitBlock(GenTreePtr tree) tree->gtOp.gtOp1 = dest; } tree->gtType = dest->TypeGet(); + // (Constant propagation may cause a TYP_STRUCT lclVar to be changed to GT_CNS_INT, and its + // type will be the type of the original lclVar, in which case we will change it to TYP_INT). + if ((src->OperGet() == GT_CNS_INT) && varTypeIsStruct(src)) + { + src->gtType = TYP_INT; + } JITDUMP("\nfgMorphInitBlock:"); GenTreePtr oneAsgTree = fgMorphOneAsgBlockOp(tree); @@ -8658,7 +8839,7 @@ GenTreePtr Compiler::fgMorphInitBlock(GenTreePtr tree) else { GenTree* destAddr = nullptr; - GenTree* initVal = src; + GenTree* initVal = src->OperIsInitVal() ? src->gtGetOp1() : src; GenTree* blockSize = nullptr; unsigned blockWidth = 0; FieldSeqNode* destFldSeq = nullptr; @@ -8727,6 +8908,7 @@ GenTreePtr Compiler::fgMorphInitBlock(GenTreePtr tree) if (destLclVar->lvPromoted && blockWidthIsConst) { + assert(initVal->OperGet() == GT_CNS_INT); noway_assert(varTypeIsStruct(destLclVar)); noway_assert(!opts.MinOpts()); if (destLclVar->lvAddrExposed & destLclVar->lvContainsHoles) @@ -8786,25 +8968,9 @@ GenTreePtr Compiler::fgMorphInitBlock(GenTreePtr tree) #if CPU_USES_BLOCK_MOVE compBlkOpUsed = true; #endif - if (!dest->OperIsBlk()) - { - GenTree* destAddr = gtNewOperNode(GT_ADDR, TYP_BYREF, dest); - CORINFO_CLASS_HANDLE clsHnd = gtGetStructHandleIfPresent(dest); - if (clsHnd == NO_CLASS_HANDLE) - { - dest = new (this, GT_BLK) GenTreeBlk(GT_BLK, dest->TypeGet(), destAddr, blockWidth); - } - else - { - GenTree* newDest = gtNewObjNode(clsHnd, destAddr); - if (newDest->OperGet() == GT_OBJ) - { - gtSetObjGcInfo(newDest->AsObj()); - } - dest = newDest; - } - tree->gtOp.gtOp1 = dest; - } + dest = fgMorphBlockOperand(dest, dest->TypeGet(), blockWidth, true); + tree->gtOp.gtOp1 = dest; + tree->gtFlags |= (dest->gtFlags & GTF_ALL_EFFECT); } else { @@ -9068,9 +9234,18 @@ GenTree* Compiler::fgMorphBlkNode(GenTreePtr tree, bool isDest) if (blkNode->AsDynBlk()->gtDynamicSize->IsCnsIntOrI()) { unsigned size = (unsigned)blkNode->AsDynBlk()->gtDynamicSize->AsIntConCommon()->IconValue(); - blkNode->AsDynBlk()->gtDynamicSize = nullptr; - blkNode->ChangeOper(GT_BLK); - blkNode->gtBlkSize = size; + // 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) + { + blkNode->AsDynBlk()->gtDynamicSize = nullptr; + blkNode->ChangeOper(GT_BLK); + blkNode->gtBlkSize = size; + } + else + { + return tree; + } } else { @@ -9104,7 +9279,7 @@ GenTree* Compiler::fgMorphBlkNode(GenTreePtr tree, bool isDest) // // Notes: // This does the following: -// - Ensures that a struct operand is a block node. +// - Ensures that a struct operand is a block node or (for non-LEGACY_BACKEND) lclVar. // - Ensures that any COMMAs are above ADDR nodes. // Although 'tree' WAS an operand of a block assignment, the assignment // may have been retyped to be a scalar assignment. @@ -9113,10 +9288,6 @@ GenTree* Compiler::fgMorphBlockOperand(GenTree* tree, var_types asgType, unsigne { GenTree* effectiveVal = tree->gtEffectiveVal(); - // TODO-1stClassStucts: We would like to transform non-TYP_STRUCT nodes to - // either plain lclVars or GT_INDs. However, for now we want to preserve most - // of the block nodes until the Rationalizer. - if (!varTypeIsStruct(asgType)) { if (effectiveVal->OperIsIndir()) @@ -9143,69 +9314,141 @@ GenTree* Compiler::fgMorphBlockOperand(GenTree* tree, var_types asgType, unsigne } else { + GenTreeIndir* indirTree = nullptr; + GenTreeLclVarCommon* lclNode = nullptr; + bool needsIndirection = true; + + if (effectiveVal->OperIsIndir()) + { + indirTree = effectiveVal->AsIndir(); + GenTree* addr = effectiveVal->AsIndir()->Addr(); + if ((addr->OperGet() == GT_ADDR) && (addr->gtGetOp1()->OperGet() == GT_LCL_VAR)) + { + lclNode = addr->gtGetOp1()->AsLclVarCommon(); + } + } + else if (effectiveVal->OperGet() == GT_LCL_VAR) + { + lclNode = effectiveVal->AsLclVarCommon(); + } #ifdef FEATURE_SIMD if (varTypeIsSIMD(asgType)) { - if (effectiveVal->OperIsIndir()) + if ((indirTree != nullptr) && (lclNode == nullptr) && (indirTree->Addr()->OperGet() == GT_ADDR) && + (indirTree->Addr()->gtGetOp1()->gtOper == GT_SIMD)) { - GenTree* addr = effectiveVal->AsIndir()->Addr(); - if (!isDest && (addr->OperGet() == GT_ADDR)) - { - if ((addr->gtGetOp1()->gtOper == GT_SIMD) || (addr->gtGetOp1()->OperGet() == GT_LCL_VAR)) - { - effectiveVal = addr->gtGetOp1(); - } - } - else if (isDest && !effectiveVal->OperIsBlk()) - { - effectiveVal = new (this, GT_BLK) GenTreeBlk(GT_BLK, asgType, addr, blockWidth); - } + assert(!isDest); + needsIndirection = false; + effectiveVal = indirTree->Addr()->gtGetOp1(); } - else if (!effectiveVal->OperIsSIMD() && (!effectiveVal->IsLocal() || isDest) && !effectiveVal->OperIsBlk()) + if (effectiveVal->OperIsSIMD()) { - GenTree* addr = gtNewOperNode(GT_ADDR, TYP_BYREF, effectiveVal); - effectiveVal = new (this, GT_BLK) GenTreeBlk(GT_BLK, asgType, addr, blockWidth); + needsIndirection = false; } } - else #endif // FEATURE_SIMD - if (!effectiveVal->OperIsBlk()) + if (lclNode != nullptr) + { + LclVarDsc* varDsc = &(lvaTable[lclNode->gtLclNum]); + if (varTypeIsStruct(varDsc) && (varDsc->lvExactSize == blockWidth)) + { +#ifndef LEGACY_BACKEND + effectiveVal = lclNode; + needsIndirection = false; +#endif // !LEGACY_BACKEND + } + else + { + // This may be a lclVar that was determined to be address-exposed. + effectiveVal->gtFlags |= (lclNode->gtFlags & GTF_ALL_EFFECT); + } + } + if (needsIndirection) { - GenTree* addr = gtNewOperNode(GT_ADDR, TYP_BYREF, effectiveVal); - CORINFO_CLASS_HANDLE clsHnd = gtGetStructHandleIfPresent(effectiveVal); - GenTree* newTree; - if (clsHnd == NO_CLASS_HANDLE) + if (indirTree != nullptr) { - newTree = new (this, GT_BLK) GenTreeBlk(GT_BLK, TYP_STRUCT, addr, blockWidth); + // We should never find a struct indirection on the lhs of an assignment. + assert(!isDest || indirTree->OperIsBlk()); + if (!isDest && indirTree->OperIsBlk()) + { + (void)fgMorphBlkToInd(effectiveVal->AsBlk(), asgType); + } } else { - newTree = gtNewObjNode(clsHnd, addr); - if (isDest && (newTree->OperGet() == GT_OBJ)) + GenTree* newTree; + GenTree* addr = gtNewOperNode(GT_ADDR, TYP_BYREF, effectiveVal); + if (isDest) { - gtSetObjGcInfo(newTree->AsObj()); + CORINFO_CLASS_HANDLE clsHnd = gtGetStructHandleIfPresent(effectiveVal); + if (clsHnd == NO_CLASS_HANDLE) + { + newTree = new (this, GT_BLK) GenTreeBlk(GT_BLK, TYP_STRUCT, addr, blockWidth); + } + else + { + newTree = gtNewObjNode(clsHnd, addr); + if (isDest && (newTree->OperGet() == GT_OBJ)) + { + gtSetObjGcInfo(newTree->AsObj()); + } + if (effectiveVal->IsLocal() && ((effectiveVal->gtFlags & GTF_GLOB_EFFECT) == 0)) + { + // This is not necessarily a global reference, though gtNewObjNode always assumes it is. + // TODO-1stClassStructs: This check should be done in the GenTreeObj constructor, + // where it currently sets GTF_GLOB_EFFECT unconditionally, but it is handled + // separately now to avoid excess diffs. + newTree->gtFlags &= ~(GTF_GLOB_EFFECT); + } + } } - if (effectiveVal->IsLocal() && ((effectiveVal->gtFlags & GTF_GLOB_EFFECT) == 0)) + else { - // This is not necessarily a global reference, though gtNewObjNode always assumes it is. - // TODO-1stClassStructs: This check should be done in the GenTreeObj constructor, - // where it currently sets GTF_GLOB_EFFECT unconditionally, but it is handled - // separately now to avoid excess diffs. - newTree->gtFlags &= ~(GTF_GLOB_EFFECT); + newTree = new (this, GT_IND) GenTreeIndir(GT_IND, asgType, addr, nullptr); } + effectiveVal = newTree; } - effectiveVal = newTree; } } - if (!isDest && effectiveVal->OperIsBlk()) - { - (void)fgMorphBlkToInd(effectiveVal->AsBlk(), asgType); - } tree = effectiveVal; return tree; } //------------------------------------------------------------------------ +// fgMorphUnsafeBlk: Convert a CopyObj with a dest on the stack to a GC Unsafe CopyBlk +// +// Arguments: +// dest - the GT_OBJ or GT_STORE_OBJ +// +// Assumptions: +// The destination must be known (by the caller) to be on the stack. +// +// Notes: +// If we have a CopyObj with a dest on the stack, and its size is small enouch +// to be completely unrolled (i.e. between [16..64] bytes), we will convert it into a +// GC Unsafe CopyBlk that is non-interruptible. +// This is not supported for the JIT32_GCENCODER, in which case this method is a no-op. +// +void Compiler::fgMorphUnsafeBlk(GenTreeObj* dest) +{ +#if defined(CPBLK_UNROLL_LIMIT) && !defined(JIT32_GCENCODER) + assert(dest->gtGcPtrCount != 0); + unsigned blockWidth = dest->AsBlk()->gtBlkSize; +#ifdef DEBUG + bool destOnStack = false; + GenTree* destAddr = dest->Addr(); + assert(destAddr->IsLocalAddrExpr() != nullptr); +#endif + if ((blockWidth >= (2 * TARGET_POINTER_SIZE)) && (blockWidth <= CPBLK_UNROLL_LIMIT)) + { + genTreeOps newOper = (dest->gtOper == GT_OBJ) ? GT_BLK : GT_STORE_BLK; + dest->SetOper(newOper); + dest->AsBlk()->gtBlkOpGcUnsafe = true; // Mark as a GC unsafe copy block + } +#endif // defined(CPBLK_UNROLL_LIMIT) && !defined(JIT32_GCENCODER) +} + +//------------------------------------------------------------------------ // fgMorphCopyBlock: Perform the Morphing of block copy // // Arguments: @@ -9444,6 +9687,14 @@ GenTreePtr Compiler::fgMorphCopyBlock(GenTreePtr tree) bool requiresCopyBlock = false; bool srcSingleLclVarAsg = false; + if ((destLclVar != nullptr) && (srcLclVar == destLclVar)) + { + // Beyond perf reasons, it is not prudent to have a copy of a struct to itself. + GenTree* nop = gtNewNothingNode(); + INDEBUG(nop->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED); + return nop; + } + // If either src or dest is a reg-sized non-field-addressed struct, keep the copyBlock. if ((destLclVar != nullptr && destLclVar->lvRegStruct) || (srcLclVar != nullptr && srcLclVar->lvRegStruct)) { @@ -9485,12 +9736,19 @@ GenTreePtr Compiler::fgMorphCopyBlock(GenTreePtr tree) // Are both dest and src promoted structs? if (destDoFldAsg && srcDoFldAsg) { - // Both structs should be of the same type, if not we will use a copy block + // Both structs should be of the same type, or each have a single field of the same type. + // If not we will use a copy block. if (lvaTable[destLclNum].lvVerTypeInfo.GetClassHandle() != lvaTable[srcLclNum].lvVerTypeInfo.GetClassHandle()) { - requiresCopyBlock = true; // Mismatched types, leave as a CopyBlock - JITDUMP(" with mismatched types"); + unsigned destFieldNum = lvaTable[destLclNum].lvFieldLclStart; + unsigned srcFieldNum = lvaTable[srcLclNum].lvFieldLclStart; + if ((lvaTable[destLclNum].lvFieldCnt != 1) || (lvaTable[srcLclNum].lvFieldCnt != 1) || + (lvaTable[destFieldNum].lvType != lvaTable[srcFieldNum].lvType)) + { + requiresCopyBlock = true; // Mismatched types, leave as a CopyBlock + JITDUMP(" with mismatched types"); + } } } // Are neither dest or src promoted structs? @@ -9584,34 +9842,24 @@ GenTreePtr Compiler::fgMorphCopyBlock(GenTreePtr tree) var_types asgType = dest->TypeGet(); dest = fgMorphBlockOperand(dest, asgType, blockWidth, true /*isDest*/); asg->gtOp.gtOp1 = dest; - hasGCPtrs = ((dest->OperGet() == GT_OBJ) && (dest->AsObj()->gtGcPtrCount != 0)); + asg->gtFlags |= (dest->gtFlags & GTF_ALL_EFFECT); -#ifdef CPBLK_UNROLL_LIMIT // Note that the unrolling of CopyBlk is only implemented on some platforms. - // Currently that includes x64 and Arm64 but not x64 or Arm32. + // Currently that includes x64 and ARM but not x86: the code generation for this + // construct requires the ability to mark certain regions of the generated code + // as non-interruptible, and the GC encoding for the latter platform does not + // have this capability. // If we have a CopyObj with a dest on the stack // we will convert it into an GC Unsafe CopyBlk that is non-interruptible - // when its size is small enouch to be completely unrolled (i.e. between [16..64] bytes) + // when its size is small enouch to be completely unrolled (i.e. between [16..64] bytes). + // (This is not supported for the JIT32_GCENCODER, for which fgMorphUnsafeBlk is a no-op.) // - if (hasGCPtrs && destOnStack && blockWidthIsConst && (blockWidth >= (2 * TARGET_POINTER_SIZE)) && - (blockWidth <= CPBLK_UNROLL_LIMIT)) + if (destOnStack && (dest->OperGet() == GT_OBJ)) { - if (dest->OperGet() == GT_OBJ) - { - dest->SetOper(GT_BLK); - dest->AsBlk()->gtBlkOpGcUnsafe = true; // Mark as a GC unsafe copy block - } - else - { - assert(dest->OperIsLocal()); - GenTree* destAddr = gtNewOperNode(GT_ADDR, TYP_BYREF, dest); - dest = new (this, GT_BLK) GenTreeBlk(GT_BLK, dest->TypeGet(), destAddr, blockWidth); - dest->AsBlk()->gtBlkOpGcUnsafe = true; // Mark as a GC unsafe copy block - tree->gtOp.gtOp1 = dest; - } + fgMorphUnsafeBlk(dest->AsObj()); } -#endif + // Eliminate the "OBJ or BLK" node on the rhs. rhs = fgMorphBlockOperand(rhs, asgType, blockWidth, false /*!isDest*/); asg->gtOp.gtOp2 = rhs; @@ -9659,8 +9907,6 @@ GenTreePtr Compiler::fgMorphCopyBlock(GenTreePtr tree) // To do fieldwise assignments for both sides, they'd better be the same struct type! // All of these conditions were checked above... assert(destLclNum != BAD_VAR_NUM && srcLclNum != BAD_VAR_NUM); - assert(lvaTable[destLclNum].lvVerTypeInfo.GetClassHandle() == - lvaTable[srcLclNum].lvVerTypeInfo.GetClassHandle()); assert(destLclVar != nullptr && srcLclVar != nullptr && destLclVar->lvFieldCnt == srcLclVar->lvFieldCnt); fieldCnt = destLclVar->lvFieldCnt; @@ -10354,23 +10600,12 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) /* fgDoNormalizeOnStore can change op2 */ noway_assert(op1 == tree->gtOp.gtOp1); op2 = tree->gtOp.gtOp2; - // TODO-1stClassStructs: this is here to match previous behavior, but results in some - // unnecessary pessimization in the handling of addresses in fgMorphCopyBlock(). - if (tree->OperIsBlkOp()) - { - op1->gtFlags |= GTF_DONT_CSE; - if (tree->OperIsCopyBlkOp() && - (op2->IsLocal() || (op2->OperIsIndir() && (op2->AsIndir()->Addr()->OperGet() == GT_ADDR)))) - { - op2->gtFlags |= GTF_DONT_CSE; - } - } #ifdef FEATURE_SIMD { // We should check whether op2 should be assigned to a SIMD field or not. // If it is, we should tranlate the tree to simd intrinsic. - assert((tree->gtDebugFlags & GTF_DEBUG_NODE_MORPHED) == 0); + assert(!fgGlobalMorph || ((tree->gtDebugFlags & GTF_DEBUG_NODE_MORPHED) == 0)); GenTreePtr newTree = fgMorphFieldAssignToSIMDIntrinsicSet(tree); typ = tree->TypeGet(); op1 = tree->gtGetOp1(); @@ -10451,8 +10686,8 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) case GT_COLON: #if LOCAL_ASSERTION_PROP if (optLocalAssertionProp) - { #endif + { isQmarkColon = true; } break; @@ -10608,13 +10843,6 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) { op2 = gtFoldExprConst(op2); } - - if (fgShouldUseMagicNumberDivide(tree->AsOp())) - { - tree = fgMorphDivByConst(tree->AsOp()); - op1 = tree->gtOp.gtOp1; - op2 = tree->gtOp.gtOp2; - } #endif // !LEGACY_BACKEND break; @@ -10673,44 +10901,44 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) // Note for _TARGET_ARMARCH_ we don't have a remainder instruction, so we don't do this optimization // #else // _TARGET_XARCH - /* If this is an unsigned long mod with op2 which is a cast to long from a - constant int, then don't morph to a call to the helper. This can be done - faster inline using idiv. - */ + /* If this is an unsigned long mod with op2 which is a cast to long from a + constant int, then don't morph to a call to the helper. This can be done + faster inline using idiv. + */ - noway_assert(op2); - if ((typ == TYP_LONG) && opts.OptEnabled(CLFLG_CONSTANTFOLD) && - ((tree->gtFlags & GTF_UNSIGNED) == (op1->gtFlags & GTF_UNSIGNED)) && - ((tree->gtFlags & GTF_UNSIGNED) == (op2->gtFlags & GTF_UNSIGNED))) - { - if (op2->gtOper == GT_CAST && op2->gtCast.CastOp()->gtOper == GT_CNS_INT && - op2->gtCast.CastOp()->gtIntCon.gtIconVal >= 2 && - op2->gtCast.CastOp()->gtIntCon.gtIconVal <= 0x3fffffff && - (tree->gtFlags & GTF_UNSIGNED) == (op2->gtCast.CastOp()->gtFlags & GTF_UNSIGNED)) - { - tree->gtOp.gtOp2 = op2 = fgMorphCast(op2); - noway_assert(op2->gtOper == GT_CNS_NATIVELONG); - } + noway_assert(op2); + if ((typ == TYP_LONG) && opts.OptEnabled(CLFLG_CONSTANTFOLD) && + ((tree->gtFlags & GTF_UNSIGNED) == (op1->gtFlags & GTF_UNSIGNED)) && + ((tree->gtFlags & GTF_UNSIGNED) == (op2->gtFlags & GTF_UNSIGNED))) + { + if (op2->gtOper == GT_CAST && op2->gtCast.CastOp()->gtOper == GT_CNS_INT && + op2->gtCast.CastOp()->gtIntCon.gtIconVal >= 2 && + op2->gtCast.CastOp()->gtIntCon.gtIconVal <= 0x3fffffff && + (tree->gtFlags & GTF_UNSIGNED) == (op2->gtCast.CastOp()->gtFlags & GTF_UNSIGNED)) + { + tree->gtOp.gtOp2 = op2 = fgMorphCast(op2); + noway_assert(op2->gtOper == GT_CNS_NATIVELONG); + } - if (op2->gtOper == GT_CNS_NATIVELONG && op2->gtIntConCommon.LngValue() >= 2 && - op2->gtIntConCommon.LngValue() <= 0x3fffffff) - { - tree->gtOp.gtOp1 = op1 = fgMorphTree(op1); - noway_assert(op1->TypeGet() == TYP_LONG); + if (op2->gtOper == GT_CNS_NATIVELONG && op2->gtIntConCommon.LngValue() >= 2 && + op2->gtIntConCommon.LngValue() <= 0x3fffffff) + { + tree->gtOp.gtOp1 = op1 = fgMorphTree(op1); + noway_assert(op1->TypeGet() == TYP_LONG); - // Update flags for op1 morph - tree->gtFlags &= ~GTF_ALL_EFFECT; + // Update flags for op1 morph + tree->gtFlags &= ~GTF_ALL_EFFECT; - tree->gtFlags |= (op1->gtFlags & GTF_ALL_EFFECT); // Only update with op1 as op2 is a constant + tree->gtFlags |= (op1->gtFlags & GTF_ALL_EFFECT); // Only update with op1 as op2 is a constant - // If op1 is a constant, then do constant folding of the division operator - if (op1->gtOper == GT_CNS_NATIVELONG) - { - tree = gtFoldExpr(tree); + // If op1 is a constant, then do constant folding of the division operator + if (op1->gtOper == GT_CNS_NATIVELONG) + { + tree = gtFoldExpr(tree); + } + return tree; } - return tree; } - } #endif // _TARGET_XARCH ASSIGN_HELPER_FOR_MOD: @@ -10773,16 +11001,28 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) tree = fgMorphModToSubMulDiv(tree->AsOp()); op1 = tree->gtOp.gtOp1; op2 = tree->gtOp.gtOp2; - -#else // !_TARGET_ARM64_ - - if (oper != GT_UMOD && fgShouldUseMagicNumberDivide(tree->AsOp())) - { - tree = fgMorphModByConst(tree->AsOp()); - op1 = tree->gtOp.gtOp1; - op2 = tree->gtOp.gtOp2; +#else //_TARGET_ARM64_ + // If b is not a power of 2 constant then lowering replaces a % b + // with a - (a / b) * b and applies magic division optimization to + // a / b. The code may already contain an a / b expression (e.g. + // x = a / 10; y = a % 10;) and then we end up with redundant code. + // If we convert % to / here we give CSE the opportunity to eliminate + // the redundant division. If there's no redundant division then + // nothing is lost, lowering would have done this transform anyway. + + if ((tree->OperGet() == GT_MOD) && op2->IsIntegralConst()) + { + ssize_t divisorValue = op2->AsIntCon()->IconValue(); + size_t absDivisorValue = (divisorValue == SSIZE_T_MIN) ? static_cast(divisorValue) + : static_cast(abs(divisorValue)); + + if (!isPow2(absDivisorValue)) + { + tree = fgMorphModToSubMulDiv(tree->AsOp()); + op1 = tree->gtOp.gtOp1; + op2 = tree->gtOp.gtOp2; + } } - #endif //_TARGET_ARM64_ #endif // !LEGACY_BACKEND break; @@ -10857,12 +11097,12 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) ((op2->gtCall.gtCallMoreFlags & GTF_CALL_M_SPECIAL_INTRINSIC) || (op2->gtCall.gtCallType == CT_HELPER))) #else - if ((((op1->gtOper == GT_INTRINSIC) && - (op1->gtIntrinsic.gtIntrinsicId == CORINFO_INTRINSIC_Object_GetType)) || - ((op1->gtOper == GT_CALL) && (op1->gtCall.gtCallType == CT_HELPER))) && - (((op2->gtOper == GT_INTRINSIC) && - (op2->gtIntrinsic.gtIntrinsicId == CORINFO_INTRINSIC_Object_GetType)) || - ((op2->gtOper == GT_CALL) && (op2->gtCall.gtCallType == CT_HELPER)))) + if ((((op1->gtOper == GT_INTRINSIC) && + (op1->gtIntrinsic.gtIntrinsicId == CORINFO_INTRINSIC_Object_GetType)) || + ((op1->gtOper == GT_CALL) && (op1->gtCall.gtCallType == CT_HELPER))) && + (((op2->gtOper == GT_INTRINSIC) && + (op2->gtIntrinsic.gtIntrinsicId == CORINFO_INTRINSIC_Object_GetType)) || + ((op2->gtOper == GT_CALL) && (op2->gtCall.gtCallType == CT_HELPER)))) #endif { GenTreePtr pGetClassFromHandle; @@ -10872,8 +11112,8 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) bool bOp1ClassFromHandle = gtIsTypeHandleToRuntimeTypeHelper(op1); bool bOp2ClassFromHandle = gtIsTypeHandleToRuntimeTypeHelper(op2); #else - bool bOp1ClassFromHandle = op1->gtOper == GT_CALL ? gtIsTypeHandleToRuntimeTypeHelper(op1) : false; - bool bOp2ClassFromHandle = op2->gtOper == GT_CALL ? gtIsTypeHandleToRuntimeTypeHelper(op2) : false; + bool bOp1ClassFromHandle = op1->gtOper == GT_CALL ? gtIsTypeHandleToRuntimeTypeHelper(op1) : false; + bool bOp2ClassFromHandle = op2->gtOper == GT_CALL ? gtIsTypeHandleToRuntimeTypeHelper(op2) : false; #endif // Optimize typeof(...) == typeof(...) @@ -10929,8 +11169,8 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) info.compCompHnd->getIntrinsicID(pGetType->gtCall.gtCallMethHnd) == CORINFO_INTRINSIC_Object_GetType && #else - if ((pGetType->gtOper == GT_INTRINSIC) && - (pGetType->gtIntrinsic.gtIntrinsicId == CORINFO_INTRINSIC_Object_GetType) && + if ((pGetType->gtOper == GT_INTRINSIC) && + (pGetType->gtIntrinsic.gtIntrinsicId == CORINFO_INTRINSIC_Object_GetType) && #endif pConstLiteral->gtOper == GT_CNS_INT && pConstLiteral->gtType == TYP_I_IMPL) { @@ -10944,7 +11184,7 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) #ifdef LEGACY_BACKEND GenTreePtr objMT = gtNewOperNode(GT_IND, TYP_I_IMPL, pGetType->gtCall.gtCallObjp); #else - GenTreePtr objMT = gtNewOperNode(GT_IND, TYP_I_IMPL, pGetType->gtUnOp.gtOp1); + GenTreePtr objMT = gtNewOperNode(GT_IND, TYP_I_IMPL, pGetType->gtUnOp.gtOp1); #endif objMT->gtFlags |= GTF_EXCEPT; // Null ref exception if object is null compCurBB->bbFlags |= BBF_HAS_VTABREF; @@ -11041,7 +11281,7 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) // Assume it's an Ind context to start. MorphAddrContext subIndMac1(MACK_Ind); MorphAddrContext* subMac1 = mac; - if (subMac1 == nullptr || subMac1->m_kind == MACK_Ind || subMac1->m_kind == MACK_CopyBlock) + if (subMac1 == nullptr || subMac1->m_kind == MACK_Ind) { switch (tree->gtOper) { @@ -11532,7 +11772,7 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) // // EQ/NE // / \ - // op1 CNS 0/1 + // op1 CNS 0/1 // ival2 = INT_MAX; // The value of INT_MAX for ival2 just means that the constant value is not 0 or 1 @@ -11557,11 +11797,11 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) // // EQ/NE Possible REVERSE(RELOP) // / \ / \ - // COMMA CNS 0/1 -> COMMA relop_op2 + // COMMA CNS 0/1 -> COMMA relop_op2 // / \ / \ - // x RELOP x relop_op1 + // x RELOP x relop_op1 // / \ - // relop_op1 relop_op2 + // relop_op1 relop_op2 // // // @@ -11600,13 +11840,13 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) // // EQ/NE EQ/NE // / \ / \ - // COMMA CNS 0/1 -> RELOP CNS 0/1 + // COMMA CNS 0/1 -> RELOP CNS 0/1 // / \ / \ - // ASG LCL_VAR + // ASG LCL_VAR // / \ - // LCL_VAR RELOP + // LCL_VAR RELOP // / \ - // + // GenTreePtr asg = op1->gtOp.gtOp1; GenTreePtr lcl = op1->gtOp.gtOp2; @@ -11689,9 +11929,9 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) // // EQ/NE -> RELOP/!RELOP // / \ / \ - // RELOP CNS 0/1 + // RELOP CNS 0/1 // / \ - // + // // Note that we will remove/destroy the EQ/NE node and move // the RELOP up into it's location. @@ -11721,11 +11961,11 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) // // EQ/NE EQ/NE // / \ / \ - // AND CNS 0/1 -> AND CNS 0 + // AND CNS 0/1 -> AND CNS 0 // / \ / \ - // RSZ/RSH CNS 1 x CNS (1 << y) + // RSZ/RSH CNS 1 x CNS (1 << y) // / \ - // x CNS_INT +y + // x CNS_INT +y if (op1->gtOper == GT_AND) { @@ -12121,38 +12361,42 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) goto CM_OVF_OP; } - /* Check for "op1 - cns2" , we change it to "op1 + (-cns2)" */ - - noway_assert(op2); - if (op2->IsCnsIntOrI()) + // TODO #4104: there are a lot of other places where + // this condition is not checked before transformations. + if (fgGlobalMorph) { - /* Negate the constant and change the node to be "+" */ + /* Check for "op1 - cns2" , we change it to "op1 + (-cns2)" */ - op2->gtIntConCommon.SetIconValue(-op2->gtIntConCommon.IconValue()); - oper = GT_ADD; - tree->ChangeOper(oper); - goto CM_ADD_OP; - } + noway_assert(op2); + if (op2->IsCnsIntOrI()) + { + /* Negate the constant and change the node to be "+" */ - /* Check for "cns1 - op2" , we change it to "(cns1 + (-op2))" */ + op2->gtIntConCommon.SetIconValue(-op2->gtIntConCommon.IconValue()); + oper = GT_ADD; + tree->ChangeOper(oper); + goto CM_ADD_OP; + } - noway_assert(op1); - if (op1->IsCnsIntOrI()) - { - noway_assert(varTypeIsIntOrI(tree)); + /* Check for "cns1 - op2" , we change it to "(cns1 + (-op2))" */ - tree->gtOp.gtOp2 = op2 = - gtNewOperNode(GT_NEG, tree->gtType, op2); // The type of the new GT_NEG node should be the same - // as the type of the tree, i.e. tree->gtType. - fgMorphTreeDone(op2); + noway_assert(op1); + if (op1->IsCnsIntOrI()) + { + noway_assert(varTypeIsIntOrI(tree)); - oper = GT_ADD; - tree->ChangeOper(oper); - goto CM_ADD_OP; - } + tree->gtOp.gtOp2 = op2 = gtNewOperNode(GT_NEG, tree->gtType, op2); // The type of the new GT_NEG + // node should be the same + // as the type of the tree, i.e. tree->gtType. + fgMorphTreeDone(op2); - /* No match - exit */ + oper = GT_ADD; + tree->ChangeOper(oper); + goto CM_ADD_OP; + } + /* No match - exit */ + } break; #ifdef _TARGET_ARM64_ @@ -12281,7 +12525,8 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) // Dereferencing the pointer in either case will have the // same effect. - if (!gtIsActiveCSE_Candidate(op1) && varTypeIsGC(op2->TypeGet())) + if (!optValnumCSE_phase && varTypeIsGC(op2->TypeGet()) && + ((op1->gtFlags & GTF_ALL_EFFECT) == 0)) { op2->gtType = tree->gtType; DEBUG_DESTROY_NODE(op1); @@ -12520,7 +12765,7 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) // Also make sure that the tree type matches the fieldVarType and that it's lvFldOffset // is zero - if (fieldVarDsc->TypeGet() == tree->TypeGet() && (fieldVarDsc->lvFldOffset == 0)) + if (fieldVarDsc->TypeGet() == typ && (fieldVarDsc->lvFldOffset == 0)) { // We can just use the existing promoted field LclNum temp->gtLclVarCommon.SetLclNum(lclNumFld); @@ -12538,8 +12783,8 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) else if (varTypeIsSmall(typ) && (genTypeSize(lvaTable[lclNum].lvType) == genTypeSize(typ)) && !lvaTable[lclNum].lvNormalizeOnLoad()) { - tree->gtType = temp->gtType; - foldAndReturnTemp = true; + tree->gtType = typ = temp->TypeGet(); + foldAndReturnTemp = true; } else { @@ -12554,7 +12799,7 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) // Append the field sequence, change the type. temp->AsLclFld()->gtFieldSeq = GetFieldSeqStore()->Append(temp->AsLclFld()->gtFieldSeq, fieldSeq); - temp->gtType = tree->TypeGet(); + temp->gtType = typ; foldAndReturnTemp = true; } @@ -12623,9 +12868,9 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) #ifdef _TARGET_ARM_ // Check for a LclVar TYP_STRUCT with misalignment on a Floating Point field // - if (varTypeIsFloating(tree->TypeGet())) + if (varTypeIsFloating(typ)) { - if ((ival1 % emitTypeSize(tree->TypeGet())) != 0) + if ((ival1 % emitTypeSize(typ)) != 0) { tree->gtFlags |= GTF_IND_UNALIGNED; break; @@ -12638,24 +12883,35 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) } } -#ifdef DEBUG - // If we have decided to fold, then temp cannot be nullptr - if (foldAndReturnTemp) - { - assert(temp != nullptr); - } -#endif - - if (temp != nullptr) - { - noway_assert(op1->gtOper == GT_ADD || op1->gtOper == GT_ADDR); - - // If we haven't already decided to fold this expression - // - if (!foldAndReturnTemp) + // At this point we may have a lclVar or lclFld that might be foldable with a bit of extra massaging: + // - We may have a load of a local where the load has a different type than the local + // - We may have a load of a local plus an offset + // + // In these cases, we will change the lclVar or lclFld into a lclFld of the appropriate type and + // offset if doing so is legal. The only cases in which this transformation is illegal are if the load + // begins before the local or if the load extends beyond the end of the local (i.e. if the load is + // out-of-bounds w.r.t. the local). + if ((temp != nullptr) && !foldAndReturnTemp) + { + assert(temp->OperIsLocal()); + + const unsigned lclNum = temp->AsLclVarCommon()->gtLclNum; + LclVarDsc* const varDsc = &lvaTable[lclNum]; + + const var_types tempTyp = temp->TypeGet(); + const bool useExactSize = + varTypeIsStruct(tempTyp) || (tempTyp == TYP_BLK) || (tempTyp == TYP_LCLBLK); + const unsigned varSize = useExactSize ? varDsc->lvExactSize : genTypeSize(temp); + + // If the size of the load is greater than the size of the lclVar, we cannot fold this access into + // a lclFld: the access represented by an lclFld node must begin at or after the start of the + // lclVar and must not extend beyond the end of the lclVar. + if ((ival1 < 0) || ((ival1 + genTypeSize(typ)) > varSize)) + { + lvaSetVarDoNotEnregister(lclNum DEBUGARG(DNER_LocalField)); + } + else { - noway_assert(temp->OperIsLocal()); - LclVarDsc* varDsc = &(lvaTable[temp->AsLclVarCommon()->gtLclNum]); // Make sure we don't separately promote the fields of this struct. if (varDsc->lvRegStruct) { @@ -12664,7 +12920,7 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) } else { - lvaSetVarDoNotEnregister(temp->gtLclVarCommon.gtLclNum DEBUGARG(DNER_LocalField)); + lvaSetVarDoNotEnregister(lclNum DEBUGARG(DNER_LocalField)); } // We will turn a GT_LCL_VAR into a GT_LCL_FLD with an gtLclOffs of 'ival' @@ -12689,19 +12945,19 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) temp->gtType = tree->gtType; foldAndReturnTemp = true; } + } - assert(foldAndReturnTemp == true); + if (foldAndReturnTemp) + { + assert(temp != nullptr); + assert(temp->TypeGet() == typ); + assert((op1->OperGet() == GT_ADD) || (op1->OperGet() == GT_ADDR)); - // Keep the DONT_CSE flag in sync - // (i.e keep the original value of this flag from tree) - // as it can be set for 'temp' because a GT_ADDR always marks it for it's op1 - // + // Copy the value of GTF_DONT_CSE from the original tree to `temp`: it can be set for + // 'temp' because a GT_ADDR always marks it for its operand. temp->gtFlags &= ~GTF_DONT_CSE; temp->gtFlags |= (tree->gtFlags & GTF_DONT_CSE); - noway_assert(op1->gtOper == GT_ADD || op1->gtOper == GT_ADDR); - noway_assert(temp->gtType == tree->gtType); - if (op1->OperGet() == GT_ADD) { DEBUG_DESTROY_NODE(op1->gtOp.gtOp1); // GT_ADDR @@ -12984,7 +13240,7 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) // If we are in the Valuenum CSE phase then don't morph away anything as these // nodes may have CSE defs/uses in them. // - if (!optValnumCSE_phase && (oper != GT_ASG) && (oper != GT_COLON) && !tree->IsList()) + if (!optValnumCSE_phase && (oper != GT_ASG) && (oper != GT_COLON) && !tree->OperIsAnyList()) { /* Check for op1 as a GT_COMMA with a unconditional throw node */ if (op1 && fgIsCommaThrow(op1, true)) @@ -13530,6 +13786,7 @@ GenTree* Compiler::fgMorphSmpOpOptional(GenTreeOp* tree) /* The target is used as well as being defined */ if (op1->OperIsLocal()) { + op1->gtFlags &= ~GTF_VAR_USEDEF; op1->gtFlags |= GTF_VAR_USEASG; } @@ -13666,7 +13923,7 @@ GenTree* Compiler::fgMorphSmpOpOptional(GenTreeOp* tree) /* Check for the case "(val + icon) << icon" */ - if (op2->IsCnsIntOrI() && op1->gtOper == GT_ADD && !op1->gtOverflow()) + if (!optValnumCSE_phase && op2->IsCnsIntOrI() && op1->gtOper == GT_ADD && !op1->gtOverflow()) { GenTreePtr cns = op1->gtOp.gtOp2; @@ -13731,192 +13988,45 @@ GenTree* Compiler::fgMorphSmpOpOptional(GenTreeOp* tree) break; + case GT_INIT_VAL: + // Initialization values for initBlk have special semantics - their lower + // byte is used to fill the struct. However, we allow 0 as a "bare" value, + // which enables them to get a VNForZero, and be propagated. + if (op1->IsIntegralConst(0)) + { + return op1; + } + break; + default: break; } return tree; } -// code to generate a magic number and shift amount for the magic number division -// optimization. This code is previously from UTC where it notes it was taken from -// _The_PowerPC_Compiler_Writer's_Guide_, pages 57-58. -// The paper it is based on is "Division by invariant integers using multiplication" -// by Torbjorn Granlund and Peter L. Montgomery in PLDI 94 - -template -T GetSignedMagicNumberForDivide(T denom, int* shift /*out*/) -{ - // static SMAG smag; - const int bits = sizeof(T) * 8; - const int bits_minus_1 = bits - 1; - - typedef typename jitstd::make_unsigned::type UT; - - const UT two_nminus1 = UT(1) << bits_minus_1; - - int p; - UT absDenom; - UT absNc; - UT delta; - UT q1; - UT r1; - UT r2; - UT q2; - UT t; - T result_magic; - int result_shift; - int iters = 0; - - absDenom = abs(denom); - t = two_nminus1 + ((unsigned int)denom >> 31); - absNc = t - 1 - (t % absDenom); // absolute value of nc - p = bits_minus_1; // initialize p - q1 = two_nminus1 / absNc; // initialize q1 = 2^p / abs(nc) - r1 = two_nminus1 - (q1 * absNc); // initialize r1 = rem(2^p, abs(nc)) - q2 = two_nminus1 / absDenom; // initialize q1 = 2^p / abs(denom) - r2 = two_nminus1 - (q2 * absDenom); // initialize r1 = rem(2^p, abs(denom)) - - do - { - iters++; - p++; - q1 *= 2; // update q1 = 2^p / abs(nc) - r1 *= 2; // update r1 = rem(2^p / abs(nc)) - - if (r1 >= absNc) - { // must be unsigned comparison - q1++; - r1 -= absNc; - } - - q2 *= 2; // update q2 = 2^p / abs(denom) - r2 *= 2; // update r2 = rem(2^p / abs(denom)) - - if (r2 >= absDenom) - { // must be unsigned comparison - q2++; - r2 -= absDenom; - } - - delta = absDenom - r2; - } while (q1 < delta || (q1 == delta && r1 == 0)); - - result_magic = q2 + 1; // resulting magic number - if (denom < 0) - { - result_magic = -result_magic; - } - *shift = p - bits; // resulting shift - - return result_magic; -} - -bool Compiler::fgShouldUseMagicNumberDivide(GenTreeOp* tree) -{ -#ifdef _TARGET_ARM64_ - // TODO-ARM64-NYI: We don't have a 'mulHi' implementation yet for ARM64 - return false; -#else - - // During the optOptimizeValnumCSEs phase we can call fgMorph and when we do, - // if this method returns true we will introduce a new LclVar and - // a couple of new GenTree nodes, including an assignment to the new LclVar. - // None of these new GenTree nodes will have valid ValueNumbers. - // That is an invalid state for a GenTree node during the optOptimizeValnumCSEs phase. - // - // Also during optAssertionProp when extracting side effects we can assert - // during gtBuildCommaList if we have one tree that has Value Numbers - // and another one that does not. - // - if (!fgGlobalMorph) - { - // We only perform the Magic Number Divide optimization during - // the initial global morph phase - return false; - } - - if (tree->gtFlags & GTF_OVERFLOW) - { - return false; - } - - if (tree->gtOp2->gtOper != GT_CNS_INT && tree->gtOp2->gtOper != GT_CNS_LNG) - { - return false; - } - - ssize_t cons = tree->gtOp2->gtIntConCommon.IconValue(); - - if (cons == 0 || cons == -1 || cons == 1) - { - return false; - } - - // codegen will expand these - if (cons == SSIZE_T_MIN || isPow2(abs(cons))) - { - return false; - } - - // someone else will fold this away, so don't make it complicated for them - if (tree->gtOp1->IsCnsIntOrI()) - { - return false; - } - - // There is no technical barrier to handling unsigned, however it is quite rare - // and more work to support and test - if (tree->gtFlags & GTF_UNSIGNED) - { - return false; - } - - return true; -#endif -} - -// transform x%c -> x-((x/c)*c) - -GenTree* Compiler::fgMorphModByConst(GenTreeOp* tree) -{ - assert(fgShouldUseMagicNumberDivide(tree)); - - var_types type = tree->gtType; - - GenTree* cns = tree->gtOp2; - - GenTree* numerator = fgMakeMultiUse(&tree->gtOp1); - - tree->SetOper(GT_DIV); - - GenTree* mul = gtNewOperNode(GT_MUL, type, tree, gtCloneExpr(cns)); - - GenTree* sub = gtNewOperNode(GT_SUB, type, numerator, mul); - -#ifdef DEBUG - sub->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED; -#endif - - return sub; -} - -// For ARM64 we don't have a remainder instruction, -// The architecture manual suggests the following transformation to -// generate code for such operator: +//------------------------------------------------------------------------ +// fgMorphModToSubMulDiv: Transform a % b into the equivalent a - (a / b) * b +// (see ECMA III 3.55 and III.3.56). // -// a % b = a - (a / b) * b; +// Arguments: +// tree - The GT_MOD/GT_UMOD tree to morph +// +// Returns: +// The morphed tree // -// This method will produce the above expression in 'a' and 'b' are -// leaf nodes, otherwise, if any of them is not a leaf it will spill -// its value into a temporary variable, an example: -// (x * 2 - 1) % (y + 1) -> t1 - (t2 * ( comma(t1 = x * 2 - 1, t1) / comma(t2 = y + 1, t2) ) ) +// Notes: +// For ARM64 we don't have a remainder instruction so this transform is +// always done. For XARCH this transform is done if we know that magic +// division will be used, in that case this transform allows CSE to +// eliminate the redundant div from code like "x = a / 3; y = a % 3;". +// +// This method will produce the above expression in 'a' and 'b' are +// leaf nodes, otherwise, if any of them is not a leaf it will spill +// its value into a temporary variable, an example: +// (x * 2 - 1) % (y + 1) -> t1 - (t2 * ( comma(t1 = x * 2 - 1, t1) / comma(t2 = y + 1, t2) ) ) // GenTree* Compiler::fgMorphModToSubMulDiv(GenTreeOp* tree) { -#ifndef _TARGET_ARM64_ - assert(!"This should only be called for ARM64"); -#endif - if (tree->OperGet() == GT_MOD) { tree->SetOper(GT_DIV); @@ -13944,8 +14054,16 @@ GenTree* Compiler::fgMorphModToSubMulDiv(GenTreeOp* tree) denominator = fgMakeMultiUse(&tree->gtOp2); } + // The numerator and denominator may have been assigned to temps, in which case + // their defining assignments are in the current tree. Therefore, we need to + // set the execuction order accordingly on the nodes we create. + // That is, the "mul" will be evaluated in "normal" order, and the "sub" must + // be set to be evaluated in reverse order. + // GenTree* mul = gtNewOperNode(GT_MUL, type, tree, gtCloneExpr(denominator)); + assert(!mul->IsReverseOp()); GenTree* sub = gtNewOperNode(GT_SUB, type, gtCloneExpr(numerator), mul); + sub->gtFlags |= GTF_REVERSE_OPS; #ifdef DEBUG sub->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED; @@ -13954,95 +14072,6 @@ GenTree* Compiler::fgMorphModToSubMulDiv(GenTreeOp* tree) return sub; } -// Turn a division by a constant into a multiplication by constant + some adjustments -// see comments on GetSignedMagicNumberForDivide for source of this algorithm. -// returns: the transformed tree - -GenTree* Compiler::fgMorphDivByConst(GenTreeOp* tree) -{ - assert(fgShouldUseMagicNumberDivide(tree)); - - JITDUMP("doing magic number divide optimization\n"); - - int64_t denominator = tree->gtOp2->gtIntConCommon.IconValue(); - int64_t magic; - int shift; - var_types type = tree->gtType; - - if (tree->gtType == TYP_INT) - { - magic = GetSignedMagicNumberForDivide((int32_t)denominator, &shift); - } - else - { - magic = GetSignedMagicNumberForDivide((int64_t)denominator, &shift); - } - - GenTree* numerator = nullptr; - - // If signs of the denominator and magic number don't match, - // we will need to use the numerator again. - if (signum(denominator) != signum(magic)) - { - numerator = fgMakeMultiUse(&tree->gtOp1); - tree->gtFlags |= GTF_ASG; - } - - if (type == TYP_LONG) - { - tree->gtOp2->gtIntConCommon.SetLngValue(magic); - } - else - { - tree->gtOp2->gtIntConCommon.SetIconValue((ssize_t)magic); - } - - tree->SetOper(GT_MULHI); - - GenTree* t = tree; - GenTree* mulresult = tree; - - JITDUMP("Multiply Result:\n"); - DISPTREE(mulresult); - - GenTree* adjusted = mulresult; - - if (denominator > 0 && magic < 0) - { - // add the numerator back in - adjusted = gtNewOperNode(GT_ADD, type, mulresult, numerator); - } - else if (denominator < 0 && magic > 0) - { - // subtract the numerator off - adjusted = gtNewOperNode(GT_SUB, type, mulresult, numerator); - } - else - { - adjusted = mulresult; - } - - GenTree* result1 = adjusted; - if (shift != 0) - { - result1 = gtNewOperNode(GT_RSH, type, adjusted, gtNewIconNode(shift, TYP_INT)); - } - - GenTree* secondClone = fgMakeMultiUse(&result1); - - GenTree* result2 = gtNewOperNode(GT_RSZ, type, secondClone, gtNewIconNode(genTypeSize(type) * 8 - 1, type)); - - GenTree* result = gtNewOperNode(GT_ADD, type, result1, result2); - JITDUMP("Final Magic Number divide:\n"); - DISPTREE(result); - -#ifdef DEBUG - result->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED; -#endif - - return result; -} - //------------------------------------------------------------------------------ // fgOperIsBitwiseRotationRoot : Check if the operation can be a root of a bitwise rotation tree. // @@ -14238,10 +14267,10 @@ GenTreePtr Compiler::fgRecognizeAndMorphBitwiseRotation(GenTreePtr tree) #ifndef _TARGET_64BIT_ if (!shiftIndexWithoutAdd->IsCnsIntOrI() && (rotatedValueBitSize == 64)) { - // TODO: we need to handle variable-sized long shifts specially on x86. + // 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. - NYI("Rotation of a long value by variable amount"); + return tree; } #endif @@ -14276,7 +14305,15 @@ GenTreePtr Compiler::fgRecognizeAndMorphBitwiseRotation(GenTreePtr tree) tree->gtOp.gtOp1 = rotatedValue; tree->gtOp.gtOp2 = rotateIndex; tree->ChangeOper(rotateOp); - noway_assert(inputTreeEffects == ((rotatedValue->gtFlags | rotateIndex->gtFlags) & GTF_ALL_EFFECT)); + + unsigned childFlags = 0; + for (GenTree* op : tree->Operands()) + { + childFlags |= (op->gtFlags & GTF_ALL_EFFECT); + } + + // The parent's flags should be a superset of its operands' flags + noway_assert((inputTreeEffects & childFlags) == childFlags); } else { @@ -14719,29 +14756,15 @@ DONE: } #if LOCAL_ASSERTION_PROP -/***************************************************************************** - * - * Kill all dependent assertions with regard to lclNum. - * - */ - -void Compiler::fgKillDependentAssertions(unsigned lclNum DEBUGARG(GenTreePtr tree)) +//------------------------------------------------------------------------ +// fgKillDependentAssertionsSingle: Kill all assertions specific to lclNum +// +// Arguments: +// lclNum - The varNum of the lclVar for which we're killing assertions. +// tree - (DEBUG only) the tree responsible for killing its assertions. +// +void Compiler::fgKillDependentAssertionsSingle(unsigned lclNum DEBUGARG(GenTreePtr tree)) { - LclVarDsc* varDsc = &lvaTable[lclNum]; - - if (varDsc->lvPromoted) - { - noway_assert(varTypeIsStruct(varDsc)); - - // Kill the field locals. - for (unsigned i = varDsc->lvFieldLclStart; i < varDsc->lvFieldLclStart + varDsc->lvFieldCnt; ++i) - { - fgKillDependentAssertions(i DEBUGARG(tree)); - } - - // Fall through to kill the struct local itself. - } - /* All dependent assertions are killed here */ ASSERT_TP killed = BitVecOps::MakeCopy(apTraits, GetAssertionDep(lclNum)); @@ -14778,6 +14801,48 @@ void Compiler::fgKillDependentAssertions(unsigned lclNum DEBUGARG(GenTreePtr tre noway_assert(BitVecOps::IsEmpty(apTraits, killed)); } } +//------------------------------------------------------------------------ +// fgKillDependentAssertions: Kill all dependent assertions with regard to lclNum. +// +// Arguments: +// lclNum - The varNum of the lclVar for which we're killing assertions. +// tree - (DEBUG only) the tree responsible for killing its assertions. +// +// Notes: +// For structs and struct fields, it will invalidate the children and parent +// respectively. +// Calls fgKillDependentAssertionsSingle to kill the assertions for a single lclVar. +// +void Compiler::fgKillDependentAssertions(unsigned lclNum DEBUGARG(GenTreePtr tree)) +{ + LclVarDsc* varDsc = &lvaTable[lclNum]; + + if (varDsc->lvPromoted) + { + noway_assert(varTypeIsStruct(varDsc)); + + // Kill the field locals. + for (unsigned i = varDsc->lvFieldLclStart; i < varDsc->lvFieldLclStart + varDsc->lvFieldCnt; ++i) + { + fgKillDependentAssertionsSingle(i DEBUGARG(tree)); + } + + // Kill the struct local itself. + fgKillDependentAssertionsSingle(lclNum DEBUGARG(tree)); + } + else if (varDsc->lvIsStructField) + { + // Kill the field local. + fgKillDependentAssertionsSingle(lclNum DEBUGARG(tree)); + + // Kill the parent struct. + fgKillDependentAssertionsSingle(varDsc->lvParentLcl DEBUGARG(tree)); + } + else + { + fgKillDependentAssertionsSingle(lclNum DEBUGARG(tree)); + } +} #endif // LOCAL_ASSERTION_PROP /***************************************************************************** @@ -14841,13 +14906,12 @@ void Compiler::fgMorphTreeDone(GenTreePtr tree, if (optAssertionCount > 0) { /* Is this an assignment to a local variable */ - - if ((tree->OperKind() & GTK_ASGOP) && - (tree->gtOp.gtOp1->gtOper == GT_LCL_VAR || tree->gtOp.gtOp1->gtOper == GT_LCL_FLD)) + GenTreeLclVarCommon* lclVarTree = nullptr; + if (tree->DefinesLocal(this, &lclVarTree)) { - unsigned op1LclNum = tree->gtOp.gtOp1->gtLclVarCommon.gtLclNum; - noway_assert(op1LclNum < lvaCount); - fgKillDependentAssertions(op1LclNum DEBUGARG(tree)); + unsigned lclNum = lclVarTree->gtLclNum; + noway_assert(lclNum < lvaCount); + fgKillDependentAssertions(lclNum DEBUGARG(tree)); } } @@ -15223,14 +15287,15 @@ bool Compiler::fgFoldConditional(BasicBlock* block) // Returns false if 'stmt' is still in the block (even if other statements were removed). // -bool Compiler::fgMorphBlockStmt(BasicBlock* block, GenTreePtr stmt DEBUGARG(const char* msg)) +bool Compiler::fgMorphBlockStmt(BasicBlock* block, GenTreeStmt* stmt DEBUGARG(const char* msg)) { - noway_assert(stmt->gtOper == GT_STMT); + assert(block != nullptr); + assert(stmt != nullptr); compCurBB = block; compCurStmt = stmt; - GenTreePtr morph = fgMorphTree(stmt->gtStmt.gtStmtExpr); + GenTree* morph = fgMorphTree(stmt->gtStmtExpr); // Bug 1106830 - During the CSE phase we can't just remove // morph->gtOp.gtOp2 as it could contain CSE expressions. @@ -15239,7 +15304,7 @@ bool Compiler::fgMorphBlockStmt(BasicBlock* block, GenTreePtr stmt DEBUGARG(cons // if (!optValnumCSE_phase) { - /* Check for morph as a GT_COMMA with an unconditional throw */ + // Check for morph as a GT_COMMA with an unconditional throw if (fgIsCommaThrow(morph, true)) { #ifdef DEBUG @@ -15251,12 +15316,12 @@ bool Compiler::fgMorphBlockStmt(BasicBlock* block, GenTreePtr stmt DEBUGARG(cons printf("\n"); } #endif - /* Use the call as the new stmt */ + // Use the call as the new stmt morph = morph->gtOp.gtOp1; noway_assert(morph->gtOper == GT_CALL); } - /* we can get a throw as a statement root*/ + // we can get a throw as a statement root if (fgIsThrow(morph)) { #ifdef DEBUG @@ -15271,15 +15336,19 @@ bool Compiler::fgMorphBlockStmt(BasicBlock* block, GenTreePtr stmt DEBUGARG(cons } } - stmt->gtStmt.gtStmtExpr = morph; + stmt->gtStmtExpr = morph; - /* Can the entire tree be removed ? */ + if (lvaLocalVarRefCounted) + { + // fgMorphTree may have introduced new lclVar references. Bump the ref counts if requested. + lvaRecursiveIncRefCounts(stmt->gtStmtExpr); + } + // Can the entire tree be removed? bool removedStmt = fgCheckRemoveStmt(block, stmt); - /* Or this is the last statement of a conditional branch that was just folded */ - - if ((!removedStmt) && (stmt->gtNext == nullptr) && !fgRemoveRestOfBlock) + // Or this is the last statement of a conditional branch that was just folded? + if (!removedStmt && (stmt->getNextStmt() == nullptr) && !fgRemoveRestOfBlock) { if (fgFoldConditional(block)) { @@ -15292,11 +15361,10 @@ bool Compiler::fgMorphBlockStmt(BasicBlock* block, GenTreePtr stmt DEBUGARG(cons if (!removedStmt) { - /* Have to re-do the evaluation order since for example - * some later code does not expect constants as op1 */ + // Have to re-do the evaluation order since for example some later code does not expect constants as op1 gtSetStmtInfo(stmt); - /* Have to re-link the nodes for this statement */ + // Have to re-link the nodes for this statement fgSetStmtSeq(stmt); } @@ -15311,18 +15379,13 @@ bool Compiler::fgMorphBlockStmt(BasicBlock* block, GenTreePtr stmt DEBUGARG(cons if (fgRemoveRestOfBlock) { - /* Remove the rest of the stmts in the block */ - - while (stmt->gtNext) + // Remove the rest of the stmts in the block + for (stmt = stmt->getNextStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) { - stmt = stmt->gtNext; - noway_assert(stmt->gtOper == GT_STMT); - fgRemoveStmt(block, stmt); } - // The rest of block has been removed - // and we will always throw an exception + // The rest of block has been removed and we will always throw an exception. // Update succesors of block fgRemoveBlockAsPred(block); @@ -15368,8 +15431,9 @@ void Compiler::fgMorphStmts(BasicBlock* block, bool* mult, bool* lnot, bool* loa fgCurrentlyInUseArgTemps = hashBv::Create(this); - GenTreePtr stmt, prev; - for (stmt = block->bbTreeList, prev = nullptr; stmt; prev = stmt->gtStmt.gtStmtExpr, stmt = stmt->gtNext) + GenTreeStmt* stmt = block->firstStmt(); + GenTreePtr prev = nullptr; + for (; stmt != nullptr; prev = stmt->gtStmtExpr, stmt = stmt->gtNextStmt) { noway_assert(stmt->gtOper == GT_STMT); @@ -15379,8 +15443,7 @@ void Compiler::fgMorphStmts(BasicBlock* block, bool* mult, bool* lnot, bool* loa continue; } #ifdef FEATURE_SIMD - if (!opts.MinOpts() && stmt->gtStmt.gtStmtExpr->TypeGet() == TYP_FLOAT && - stmt->gtStmt.gtStmtExpr->OperGet() == GT_ASG) + if (!opts.MinOpts() && stmt->gtStmtExpr->TypeGet() == TYP_FLOAT && stmt->gtStmtExpr->OperGet() == GT_ASG) { fgMorphCombineSIMDFieldAssignments(block, stmt); } @@ -15388,7 +15451,7 @@ void Compiler::fgMorphStmts(BasicBlock* block, bool* mult, bool* lnot, bool* loa fgMorphStmt = stmt; compCurStmt = stmt; - GenTreePtr tree = stmt->gtStmt.gtStmtExpr; + GenTreePtr tree = stmt->gtStmtExpr; #ifdef DEBUG compCurStmtNum++; @@ -15416,15 +15479,15 @@ void Compiler::fgMorphStmts(BasicBlock* block, bool* mult, bool* lnot, bool* loa // Has fgMorphStmt been sneakily changed ? - if (stmt->gtStmt.gtStmtExpr != tree) + if (stmt->gtStmtExpr != tree) { /* This must be tailcall. Ignore 'morph' and carry on with the tail-call node */ - morph = stmt->gtStmt.gtStmtExpr; + morph = stmt->gtStmtExpr; noway_assert(compTailCallUsed); noway_assert((morph->gtOper == GT_CALL) && morph->AsCall()->IsTailCall()); - noway_assert(stmt->gtNext == nullptr); + noway_assert(stmt->gtNextStmt == nullptr); GenTreeCall* call = morph->AsCall(); // Could either be @@ -15448,7 +15511,7 @@ void Compiler::fgMorphStmts(BasicBlock* block, bool* mult, bool* lnot, bool* loa noway_assert(compTailCallUsed); noway_assert((tree->gtOper == GT_CALL) && tree->AsCall()->IsTailCall()); - noway_assert(stmt->gtNext == nullptr); + noway_assert(stmt->gtNextStmt == nullptr); GenTreeCall* call = morph->AsCall(); @@ -15505,7 +15568,7 @@ void Compiler::fgMorphStmts(BasicBlock* block, bool* mult, bool* lnot, bool* loa fgRemoveRestOfBlock = true; } - stmt->gtStmt.gtStmtExpr = tree = morph; + stmt->gtStmtExpr = tree = morph; noway_assert(fgPtrArgCntCur == 0); @@ -15958,6 +16021,45 @@ void Compiler::fgMorphBlocks() #endif } +//------------------------------------------------------------------------ +// fgCheckArgCnt: Check whether the maximum arg size will change codegen requirements +// +// Notes: +// fpPtrArgCntMax records the maximum number of pushed arguments. +// Depending upon this value of the maximum number of pushed arguments +// we may need to use an EBP frame or be partially interuptible. +// This functionality has been factored out of fgSetOptions() because +// the Rationalizer can create new calls. +// +// Assumptions: +// This must be called before isFramePointerRequired() is called, because it is a +// phased variable (can only be written before it has been read). +// +void Compiler::fgCheckArgCnt() +{ + if (!compCanEncodePtrArgCntMax()) + { +#ifdef DEBUG + if (verbose) + { + printf("Too many pushed arguments for fully interruptible encoding, marking method as partially " + "interruptible\n"); + } +#endif + genInterruptible = false; + } + if (fgPtrArgCntMax >= sizeof(unsigned)) + { +#ifdef DEBUG + if (verbose) + { + printf("Too many pushed arguments for an ESP based encoding, forcing an EBP frame\n"); + } +#endif + codeGen->setFramePointerRequired(true); + } +} + /***************************************************************************** * * Make some decisions about the kind of code to generate. @@ -15974,13 +16076,11 @@ void Compiler::fgSetOptions() } #endif -#ifdef DEBUGGING_SUPPORT if (opts.compDbgCode) { assert(!codeGen->isGCTypeFixed()); genInterruptible = true; // debugging is easier this way ... } -#endif /* Assume we won't need an explicit stack frame if this is allowed */ @@ -16035,32 +16135,7 @@ void Compiler::fgSetOptions() #endif // _TARGET_X86_ - // fpPtrArgCntMax records the maximum number of pushed arguments - // Depending upon this value of the maximum number of pushed arguments - // we may need to use an EBP frame or be partially interuptible - // - - if (!compCanEncodePtrArgCntMax()) - { -#ifdef DEBUG - if (verbose) - { - printf("Too many pushed arguments for fully interruptible encoding, marking method as partially " - "interruptible\n"); - } -#endif - genInterruptible = false; - } - if (fgPtrArgCntMax >= sizeof(unsigned)) - { -#ifdef DEBUG - if (verbose) - { - printf("Too many pushed arguments for an ESP based encoding, forcing an EBP frame\n"); - } -#endif - codeGen->setFramePointerRequiredGCInfo(true); - } + fgCheckArgCnt(); if (info.compCallUnmanaged) { @@ -16121,6 +16196,23 @@ GenTreePtr Compiler::fgInitThisClass() } else { +#ifdef FEATURE_READYTORUN_COMPILER + // Only CoreRT understands CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE. Don't do this on CoreCLR. + if (opts.IsReadyToRun() && IsTargetAbi(CORINFO_CORERT_ABI)) + { + CORINFO_RESOLVED_TOKEN resolvedToken; + memset(&resolvedToken, 0, sizeof(resolvedToken)); + + GenTreePtr ctxTree = getRuntimeContextTree(kind.runtimeLookupKind); + + // CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE with a zeroed out resolvedToken means "get the static + // base of the class that owns the method being compiled". If we're in this method, it means we're not + // inlining and there's no ambiguity. + return impReadyToRunHelperToTree(&resolvedToken, CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE, TYP_BYREF, + gtNewArgList(ctxTree), &kind); + } +#endif + // Collectible types requires that for shared generic code, if we use the generic context paramter // that we report it. (This is a conservative approach, we could detect some cases particularly when the // context parameter is this that we don't need the eager reporting logic.) @@ -16774,19 +16866,13 @@ void Compiler::fgMorph() fgRemoveEmptyBlocks(); - /* Add any internal blocks/trees we may need */ - - fgAddInternal(); - -#if OPT_BOOL_OPS - fgMultipleNots = false; -#endif - #ifdef DEBUG /* Inliner could add basic blocks. Check that the flowgraph data is up-to-date */ fgDebugCheckBBlist(false, false); #endif // DEBUG + EndPhase(PHASE_MORPH_INIT); + /* Inline */ fgInline(); #if 0 @@ -16796,6 +16882,16 @@ void Compiler::fgMorph() RecordStateAtEndOfInlining(); // Record "start" values for post-inlining cycles and elapsed time. + EndPhase(PHASE_MORPH_INLINE); + + /* Add any internal blocks/trees we may need */ + + fgAddInternal(); + +#if OPT_BOOL_OPS + fgMultipleNots = false; +#endif + #ifdef DEBUG /* Inliner could add basic blocks. Check that the flowgraph data is up-to-date */ fgDebugCheckBBlist(false, false); @@ -16804,6 +16900,8 @@ void Compiler::fgMorph() /* For x64 and ARM64 we need to mark irregular parameters early so that they don't get promoted */ fgMarkImplicitByRefArgs(); + EndPhase(PHASE_MORPH_IMPBYREF); + /* Promote struct locals if necessary */ fgPromoteStructs(); @@ -16816,10 +16914,14 @@ void Compiler::fgMorph() fgStress64RsltMul(); #endif // DEBUG + EndPhase(PHASE_STR_ADRLCL); + /* Morph the trees in all the blocks of the method */ fgMorphBlocks(); + EndPhase(PHASE_MORPH_GLOBAL); + #if 0 JITDUMP("trees after fgMorphBlocks\n"); DBEXEC(VERBOSE, fgDispBasicBlocks(true)); @@ -17454,9 +17556,6 @@ enum AddrExposedContext AXC_AddrWide, // The address being computed will be dereferenced by a block operation that operates // on more bytes than the width of the storage location addressed. If this is a // field of a promoted struct local, declare the entire struct local address-taken. - AXC_InitBlk, // An GT_INITBLK is the immediate parent. The first argument is in an IND context. - AXC_CopyBlk, // An GT_COPYBLK is the immediate parent. The first argument is in a GT_LIST, whose - // args should be evaluated in an IND context. AXC_IndAdd, // A GT_ADD is the immediate parent, and it was evaluated in an IND contxt. // If one arg is a constant int, evaluate the other in an IND context. Otherwise, none. }; @@ -17572,14 +17671,8 @@ Compiler::fgWalkResult Compiler::fgMarkAddrTakenLocalsPreCB(GenTreePtr* pTree, f return WALK_CONTINUE; case GT_LIST: - if (axc == AXC_InitBlk || axc == AXC_CopyBlk) - { - axcStack->Push(axc); - } - else - { - axcStack->Push(AXC_None); - } + case GT_FIELD_LIST: + axcStack->Push(AXC_None); return WALK_CONTINUE; case GT_INDEX: @@ -18083,9 +18176,6 @@ bool Compiler::fgShouldCreateAssignOp(GenTreePtr tree, bool* bReverse) #endif // defined(LEGACY_BACKEND) } -// Static variables. -Compiler::MorphAddrContext Compiler::s_CopyBlockMAC(Compiler::MACK_CopyBlock); - #ifdef FEATURE_SIMD //----------------------------------------------------------------------------------- diff --git a/src/jit/nodeinfo.h b/src/jit/nodeinfo.h index a73033a..1937cc4 100644 --- a/src/jit/nodeinfo.h +++ b/src/jit/nodeinfo.h @@ -21,17 +21,18 @@ public: _internalIntCount = 0; _internalFloatCount = 0; - srcCandsIndex = 0; - dstCandsIndex = 0; - internalCandsIndex = 0; - isLocalDefUse = false; - isHelperCallWithKills = false; - isLsraAdded = false; - isDelayFree = false; - hasDelayFreeSrc = false; - isTgtPref = false; - regOptional = false; - definesAnyRegisters = false; + srcCandsIndex = 0; + dstCandsIndex = 0; + internalCandsIndex = 0; + isLocalDefUse = false; + isHelperCallWithKills = false; + isLsraAdded = false; + isDelayFree = false; + hasDelayFreeSrc = false; + isTgtPref = false; + regOptional = false; + definesAnyRegisters = false; + isInternalRegDelayFree = false; #ifdef DEBUG isInitialized = false; #endif @@ -99,42 +100,54 @@ public: LsraLocation loc; -private: - unsigned char _dstCount; - unsigned char _srcCount; - unsigned char _internalIntCount; - unsigned char _internalFloatCount; - public: unsigned char srcCandsIndex; unsigned char dstCandsIndex; unsigned char internalCandsIndex; +private: + unsigned char _srcCount : 5; + unsigned char _dstCount : 3; + unsigned char _internalIntCount : 3; + unsigned char _internalFloatCount : 3; + +public: // isLocalDefUse identifies trees that produce a value that is not consumed elsewhere. // Examples include stack arguments to a call (they are immediately stored), lhs of comma // nodes, or top-level nodes that are non-void. unsigned char isLocalDefUse : 1; + // isHelperCallWithKills is set when this is a helper call that kills more than just its in/out regs. unsigned char isHelperCallWithKills : 1; + // Is this node added by LSRA, e.g. as a resolution or copy/reload move. unsigned char isLsraAdded : 1; + // isDelayFree is set when the register defined by this node will interfere with the destination // of the consuming node, and therefore it must not be freed immediately after use. unsigned char isDelayFree : 1; + // hasDelayFreeSrc is set when this node has sources that are marked "isDelayFree". This is because, // we may eventually "contain" this node, in which case we don't want it's children (which have // already been marked "isDelayFree" to be handled that way when allocating. unsigned char hasDelayFreeSrc : 1; + // isTgtPref is set to true when we have a rmw op, where we would like the result to be allocated // in the same register as op1. unsigned char isTgtPref : 1; + // Whether a spilled second src can be treated as a contained operand unsigned char regOptional : 1; + // Whether or not a node defines any registers, whether directly (for nodes where dstCout is non-zero) // or indirectly (for contained nodes, which propagate the transitive closure of the registers // defined by their inputs). Used during buildRefPositionsForNode in order to avoid unnecessary work. unsigned char definesAnyRegisters : 1; + // Whether internal register needs to be different from targetReg + // in which result is produced. + unsigned char isInternalRegDelayFree : 1; + #ifdef DEBUG // isInitialized is set when the tree node is handled. unsigned char isInitialized : 1; diff --git a/src/jit/optcse.cpp b/src/jit/optcse.cpp index d23b4cd..3ff4cea 100644 --- a/src/jit/optcse.cpp +++ b/src/jit/optcse.cpp @@ -301,15 +301,15 @@ Compiler::fgWalkResult Compiler::optCSE_MaskHelper(GenTreePtr* pTree, fgWalkData if (IS_CSE_INDEX(tree->gtCSEnum)) { - unsigned cseIndex = GET_CSE_INDEX(tree->gtCSEnum); - EXPSET_TP cseBit = genCSEnum2bit(cseIndex); + unsigned cseIndex = GET_CSE_INDEX(tree->gtCSEnum); + unsigned cseBit = genCSEnum2bit(cseIndex); if (IS_CSE_DEF(tree->gtCSEnum)) { - pUserData->CSE_defMask |= cseBit; + BitVecOps::AddElemD(comp->cseTraits, pUserData->CSE_defMask, cseBit); } else { - pUserData->CSE_useMask |= cseBit; + BitVecOps::AddElemD(comp->cseTraits, pUserData->CSE_useMask, cseBit); } } @@ -321,8 +321,8 @@ Compiler::fgWalkResult Compiler::optCSE_MaskHelper(GenTreePtr* pTree, fgWalkData // void Compiler::optCSE_GetMaskData(GenTreePtr tree, optCSE_MaskData* pMaskData) { - pMaskData->CSE_defMask = 0; - pMaskData->CSE_useMask = 0; + pMaskData->CSE_defMask = BitVecOps::MakeCopy(cseTraits, cseEmpty); + pMaskData->CSE_useMask = BitVecOps::MakeCopy(cseTraits, cseEmpty); fgWalkTreePre(&tree, optCSE_MaskHelper, (void*)pMaskData); } @@ -355,14 +355,14 @@ bool Compiler::optCSE_canSwap(GenTree* op1, GenTree* op2) optCSE_GetMaskData(op2, &op2MaskData); // We cannot swap if op1 contains a CSE def that is used by op2 - if ((op1MaskData.CSE_defMask & op2MaskData.CSE_useMask) != 0) + if (!BitVecOps::IsEmptyIntersection(cseTraits, op1MaskData.CSE_defMask, op2MaskData.CSE_useMask)) { canSwap = false; } else { // We also cannot swap if op2 contains a CSE def that is used by op1. - if ((op2MaskData.CSE_defMask & op1MaskData.CSE_useMask) != 0) + if (!BitVecOps::IsEmptyIntersection(cseTraits, op2MaskData.CSE_defMask, op1MaskData.CSE_useMask)) { canSwap = false; } @@ -495,6 +495,14 @@ void Compiler::optValnumCSE_Init() optCSEtab = nullptr; #endif + // Init traits and full/empty bitvectors. This will be used to track the + // individual cse indexes. + cseTraits = new (getAllocator()) BitVecTraits(EXPSET_SZ, this); + cseFull = BitVecOps::UninitVal(); + cseEmpty = BitVecOps::UninitVal(); + BitVecOps::AssignNoCopy(cseTraits, cseFull, BitVecOps::MakeFull(cseTraits)); + BitVecOps::AssignNoCopy(cseTraits, cseEmpty, BitVecOps::MakeEmpty(cseTraits)); + /* Allocate and clear the hash bucket table */ optCSEhash = new (this, CMK_CSE) CSEdsc*[s_optCSEhashSize](); @@ -631,8 +639,8 @@ unsigned Compiler::optValnumCSE_Index(GenTreePtr tree, GenTreePtr stmt) C_ASSERT((signed char)MAX_CSE_CNT == MAX_CSE_CNT); - unsigned CSEindex = ++optCSECandidateCount; - EXPSET_TP CSEmask = genCSEnum2bit(CSEindex); + unsigned CSEindex = ++optCSECandidateCount; + // EXPSET_TP CSEmask = genCSEnum2bit(CSEindex); /* Record the new CSE index in the hashDsc */ hashDsc->csdIndex = CSEindex; @@ -649,10 +657,11 @@ unsigned Compiler::optValnumCSE_Index(GenTreePtr tree, GenTreePtr stmt) #ifdef DEBUG if (verbose) { + EXPSET_TP tempMask = BitVecOps::MakeSingleton(cseTraits, genCSEnum2bit(CSEindex)); printf("\nCSE candidate #%02u, vn=", CSEindex); vnPrint(vnlib, 0); - printf(" cseMask=%s in BB%02u, [cost=%2u, size=%2u]: \n", genES2str(genCSEnum2bit(CSEindex)), - compCurBB->bbNum, tree->gtCostEx, tree->gtCostSz); + printf(" cseMask=%s in BB%02u, [cost=%2u, size=%2u]: \n", genES2str(cseTraits, tempMask), compCurBB->bbNum, + tree->gtCostEx, tree->gtCostSz); gtDispTree(tree); } #endif // DEBUG @@ -773,19 +782,18 @@ void Compiler::optValnumCSE_InitDataFlow() if (init_to_zero) { /* Initialize to {ZERO} prior to dataflow */ - - block->bbCseIn = 0; + block->bbCseIn = BitVecOps::MakeCopy(cseTraits, cseEmpty); } else { /* Initialize to {ALL} prior to dataflow */ - - block->bbCseIn = EXPSET_ALL; + block->bbCseIn = BitVecOps::MakeCopy(cseTraits, cseFull); } - block->bbCseOut = EXPSET_ALL; + + block->bbCseOut = BitVecOps::MakeCopy(cseTraits, cseFull); /* Initialize to {ZERO} prior to locating the CSE candidates */ - block->bbCseGen = 0; + block->bbCseGen = BitVecOps::MakeCopy(cseTraits, cseEmpty); } // We walk the set of CSE candidates and set the bit corresponsing to the CSEindex @@ -801,7 +809,7 @@ void Compiler::optValnumCSE_InitDataFlow() while (lst != nullptr) { BasicBlock* block = lst->tslBlock; - block->bbCseGen |= genCSEnum2bit(CSEindex); + BitVecOps::AddElemD(cseTraits, block->bbCseGen, genCSEnum2bit(CSEindex)); lst = lst->tslNext; } } @@ -814,7 +822,7 @@ void Compiler::optValnumCSE_InitDataFlow() bool headerPrinted = false; for (BasicBlock* block = fgFirstBB; block; block = block->bbNext) { - if (block->bbCseGen != 0) + if (block->bbCseGen != nullptr) { if (!headerPrinted) { @@ -822,7 +830,7 @@ void Compiler::optValnumCSE_InitDataFlow() headerPrinted = true; } printf("BB%02u", block->bbNum); - printf(" cseGen = %s\n", genES2str(block->bbCseGen)); + printf(" cseGen = %s\n", genES2str(cseTraits, block->bbCseGen)); } } } @@ -857,21 +865,24 @@ public: // At the start of the merge function of the dataflow equations, initialize premerge state (to detect changes.) void StartMerge(BasicBlock* block) { - m_preMergeOut = block->bbCseOut; + m_preMergeOut = BitVecOps::MakeCopy(m_pCompiler->cseTraits, block->bbCseOut); } // During merge, perform the actual merging of the predecessor's (since this is a forward analysis) dataflow flags. void Merge(BasicBlock* block, BasicBlock* predBlock, flowList* preds) { - block->bbCseIn &= predBlock->bbCseOut; + BitVecOps::IntersectionD(m_pCompiler->cseTraits, block->bbCseIn, predBlock->bbCseOut); } // At the end of the merge store results of the dataflow equations, in a postmerge state. bool EndMerge(BasicBlock* block) { - EXPSET_TP mergeOut = block->bbCseOut & (block->bbCseIn | block->bbCseGen); - block->bbCseOut = mergeOut; - return (mergeOut != m_preMergeOut); + BitVecTraits* traits = m_pCompiler->cseTraits; + EXPSET_TP mergeOut = BitVecOps::MakeCopy(traits, block->bbCseIn); + BitVecOps::UnionD(traits, mergeOut, block->bbCseGen); + BitVecOps::IntersectionD(traits, mergeOut, block->bbCseOut); + BitVecOps::Assign(traits, block->bbCseOut, mergeOut); + return (!BitVecOps::Equal(traits, mergeOut, m_preMergeOut)); } }; @@ -905,8 +916,8 @@ void Compiler::optValnumCSE_DataFlow() for (BasicBlock* block = fgFirstBB; block; block = block->bbNext) { printf("BB%02u", block->bbNum); - printf(" cseIn = %s", genES2str(block->bbCseIn)); - printf(" cseOut = %s", genES2str(block->bbCseOut)); + printf(" cseIn = %s", genES2str(cseTraits, block->bbCseIn)); + printf(" cseOut = %s", genES2str(cseTraits, block->bbCseOut)); printf("\n"); } @@ -946,7 +957,7 @@ void Compiler::optValnumCSE_Availablity() compCurBB = block; - EXPSET_TP available_cses = block->bbCseIn; + EXPSET_TP available_cses = BitVecOps::MakeCopy(cseTraits, block->bbCseIn); optCSEweight = block->getBBWeight(this); @@ -961,13 +972,13 @@ void Compiler::optValnumCSE_Availablity() { if (IS_CSE_INDEX(tree->gtCSEnum)) { - EXPSET_TP mask = genCSEnum2bit(tree->gtCSEnum); - CSEdsc* desc = optCSEfindDsc(tree->gtCSEnum); - unsigned stmw = block->getBBWeight(this); + unsigned int cseBit = genCSEnum2bit(tree->gtCSEnum); + CSEdsc* desc = optCSEfindDsc(tree->gtCSEnum); + unsigned stmw = block->getBBWeight(this); /* Is this expression available here? */ - if (available_cses & mask) + if (BitVecOps::IsMember(cseTraits, available_cses, cseBit)) { /* This is a CSE use */ @@ -993,8 +1004,7 @@ void Compiler::optValnumCSE_Availablity() tree->gtCSEnum = TO_CSE_DEF(tree->gtCSEnum); /* This CSE will be available after this def */ - - available_cses |= mask; + BitVecOps::AddElemD(cseTraits, available_cses, cseBit); } #ifdef DEBUG if (verbose && IS_CSE_INDEX(tree->gtCSEnum)) @@ -1236,6 +1246,7 @@ public: { printf("\nSorted CSE candidates:\n"); /* Print out the CSE candidates */ + EXPSET_TP tempMask; for (unsigned cnt = 0; cnt < m_pCompiler->optCSECandidateCount; cnt++) { Compiler::CSEdsc* dsc = sortTab[cnt]; @@ -1255,8 +1266,9 @@ public: use = dsc->csdUseWtCnt; // weighted use count (excluding the implicit uses at defs) } + tempMask = BitVecOps::MakeSingleton(m_pCompiler->cseTraits, genCSEnum2bit(dsc->csdIndex)); printf("CSE #%02u,cseMask=%s,useCnt=%d: [def=%3u, use=%3u", dsc->csdIndex, - genES2str(genCSEnum2bit(dsc->csdIndex)), dsc->csdUseCount, def, use); + genES2str(m_pCompiler->cseTraits, tempMask), dsc->csdUseCount, def, use); printf("] :: "); m_pCompiler->gtDispTree(expr, nullptr, nullptr, true); } @@ -2038,7 +2050,7 @@ public: assert(m_pCompiler->fgRemoveRestOfBlock == false); /* re-morph the statement */ - m_pCompiler->fgMorphBlockStmt(blk, stm DEBUGARG("optValnumCSE")); + m_pCompiler->fgMorphBlockStmt(blk, stm->AsStmt() DEBUGARG("optValnumCSE")); } while (lst != nullptr); } @@ -2516,8 +2528,6 @@ void Compiler::optCleanupCSEs() // for (BasicBlock* block = fgFirstBB; block; block = block->bbNext) { - unsigned blkFlags = block->bbFlags; - // And clear all the "visited" bits on the block // block->bbFlags &= ~(BBF_VISITED | BBF_MARKED); diff --git a/src/jit/optimizer.cpp b/src/jit/optimizer.cpp index 0fbdb27..bd82f6a 100644 --- a/src/jit/optimizer.cpp +++ b/src/jit/optimizer.cpp @@ -822,6 +822,10 @@ bool Compiler::optCheckIterInLoopTest( if (limitOp->gtOper == GT_CNS_INT) { optLoopTable[loopInd].lpFlags |= LPFLG_CONST_LIMIT; + if ((limitOp->gtFlags & GTF_ICON_SIMD_COUNT) != 0) + { + optLoopTable[loopInd].lpFlags |= LPFLG_SIMD_LIMIT; + } } else if (limitOp->gtOper == GT_LCL_VAR && !optIsVarAssigned(from, to, nullptr, limitOp->gtLclVarCommon.gtLclNum)) { @@ -1081,9 +1085,24 @@ bool Compiler::optExtractInitTestIncr( // If it is a duplicated loop condition, skip it. if (init->gtFlags & GTF_STMT_CMPADD) { - // Must be a duplicated loop condition. - noway_assert(init->gtStmt.gtStmtExpr->gtOper == GT_JTRUE); - init = init->gtPrev; + bool doGetPrev = true; +#ifdef DEBUG + if (opts.optRepeat) + { + // Previous optimization passes may have inserted compiler-generated + // statements other than duplicated loop conditions. + doGetPrev = (init->gtPrev != nullptr); + } + else + { + // Must be a duplicated loop condition. + noway_assert(init->gtStmt.gtStmtExpr->gtOper == GT_JTRUE); + } +#endif // DEBUG + if (doGetPrev) + { + init = init->gtPrev; + } noway_assert(init != nullptr); } @@ -1217,10 +1236,14 @@ void Compiler::optRecordLoop(BasicBlock* head, } // Make sure the "iterVar" initialization is never skipped, - // i.e. HEAD dominates the ENTRY. - if (!fgDominate(head, entry)) + // i.e. every pred of ENTRY other than HEAD is in the loop. + for (flowList* predEdge = entry->bbPreds; predEdge; predEdge = predEdge->flNext) { - goto DONE_LOOP; + BasicBlock* predBlock = predEdge->flBlock; + if ((predBlock != head) && !optLoopTable[loopInd].lpContains(predBlock)) + { + goto DONE_LOOP; + } } if (!optPopulateInitInfo(loopInd, init, iterVar)) @@ -2798,11 +2821,6 @@ void Compiler::optUnrollLoops() } #endif - if (optCanCloneLoops()) - { - return; - } - #ifdef DEBUG if (verbose) { @@ -2811,276 +2829,266 @@ void Compiler::optUnrollLoops() #endif /* Look for loop unrolling candidates */ - /* Double loop so that after unrolling an inner loop we set change to true - * and we then go back over all of the loop candidates and try to unroll - * the next outer loop, until we don't unroll any loops, - * then change will be false and we are done. - */ - for (;;) - { - bool change = false; + bool change = false; + + // Visit loops from highest to lowest number to vist them in innermost + // to outermost order + for (unsigned lnum = optLoopCount - 1; lnum != ~0U; --lnum) + { + BasicBlock* block; + BasicBlock* head; + BasicBlock* bottom; + + GenTree* loop; + GenTree* test; + GenTree* incr; + GenTree* phdr; + GenTree* init; + + bool dupCond; + int lval; + int lbeg; // initial value for iterator + int llim; // limit value for iterator + unsigned lvar; // iterator lclVar # + int iterInc; // value to increment the iterator + genTreeOps iterOper; // type of iterator increment (i.e. ADD, SUB, etc.) + var_types iterOperType; // type result of the oper (for overflow instrs) + genTreeOps testOper; // type of loop test (i.e. GT_LE, GT_GE, etc.) + bool unsTest; // Is the comparison u/int + + unsigned loopRetCount; // number of BBJ_RETURN blocks in loop + unsigned totalIter; // total number of iterations in the constant loop + unsigned loopFlags; // actual lpFlags + unsigned requiredFlags; // required lpFlags + + static const int ITER_LIMIT[COUNT_OPT_CODE + 1] = { + 10, // BLENDED_CODE + 0, // SMALL_CODE + 20, // FAST_CODE + 0 // COUNT_OPT_CODE + }; + + noway_assert(ITER_LIMIT[SMALL_CODE] == 0); + noway_assert(ITER_LIMIT[COUNT_OPT_CODE] == 0); + + unsigned iterLimit = (unsigned)ITER_LIMIT[compCodeOpt()]; - for (unsigned lnum = 0; lnum < optLoopCount; lnum++) +#ifdef DEBUG + if (compStressCompile(STRESS_UNROLL_LOOPS, 50)) { - BasicBlock* block; - BasicBlock* head; - BasicBlock* bottom; - - GenTree* loop; - GenTree* test; - GenTree* incr; - GenTree* phdr; - GenTree* init; - - bool dupCond; - int lval; - int lbeg; // initial value for iterator - int llim; // limit value for iterator - unsigned lvar; // iterator lclVar # - int iterInc; // value to increment the iterator - genTreeOps iterOper; // type of iterator increment (i.e. ASG_ADD, ASG_SUB, etc.) - var_types iterOperType; // type result of the oper (for overflow instrs) - genTreeOps testOper; // type of loop test (i.e. GT_LE, GT_GE, etc.) - bool unsTest; // Is the comparison u/int - - unsigned totalIter; // total number of iterations in the constant loop - unsigned loopCostSz; // Cost is size of one iteration - unsigned loopFlags; // actual lpFlags - unsigned requiredFlags; // required lpFlags + iterLimit *= 10; + } +#endif - GenTree* loopList; // new stmt list of the unrolled loop - GenTree* loopLast; + static const int UNROLL_LIMIT_SZ[COUNT_OPT_CODE + 1] = { + 300, // BLENDED_CODE + 0, // SMALL_CODE + 600, // FAST_CODE + 0 // COUNT_OPT_CODE + }; - static const int ITER_LIMIT[COUNT_OPT_CODE + 1] = { - 10, // BLENDED_CODE - 0, // SMALL_CODE - 20, // FAST_CODE - 0 // COUNT_OPT_CODE - }; + noway_assert(UNROLL_LIMIT_SZ[SMALL_CODE] == 0); + noway_assert(UNROLL_LIMIT_SZ[COUNT_OPT_CODE] == 0); - noway_assert(ITER_LIMIT[SMALL_CODE] == 0); - noway_assert(ITER_LIMIT[COUNT_OPT_CODE] == 0); + int unrollLimitSz = (unsigned)UNROLL_LIMIT_SZ[compCodeOpt()]; - unsigned iterLimit = (unsigned)ITER_LIMIT[compCodeOpt()]; + loopFlags = optLoopTable[lnum].lpFlags; + // Check for required flags: + // LPFLG_DO_WHILE - required because this transform only handles loops of this form + // LPFLG_CONST - required because this transform only handles full unrolls + // LPFLG_SIMD_LIMIT - included here as a heuristic, not for correctness/structural reasons + requiredFlags = LPFLG_DO_WHILE | LPFLG_CONST | LPFLG_SIMD_LIMIT; #ifdef DEBUG - if (compStressCompile(STRESS_UNROLL_LOOPS, 50)) - { - iterLimit *= 10; - } -#endif - - static const int UNROLL_LIMIT_SZ[COUNT_OPT_CODE + 1] = { - 30, // BLENDED_CODE - 0, // SMALL_CODE - 60, // FAST_CODE - 0 // COUNT_OPT_CODE - }; - - noway_assert(UNROLL_LIMIT_SZ[SMALL_CODE] == 0); - noway_assert(UNROLL_LIMIT_SZ[COUNT_OPT_CODE] == 0); - - int unrollLimitSz = (unsigned)UNROLL_LIMIT_SZ[compCodeOpt()]; + if (compStressCompile(STRESS_UNROLL_LOOPS, 50)) + { + // In stress mode, quadruple the size limit, and drop + // the restriction that loop limit must be Vector.Count. -#ifdef DEBUG - if (compStressCompile(STRESS_UNROLL_LOOPS, 50)) - { - unrollLimitSz *= 10; - } + unrollLimitSz *= 4; + requiredFlags &= ~LPFLG_SIMD_LIMIT; + } #endif - loopFlags = optLoopTable[lnum].lpFlags; - requiredFlags = LPFLG_DO_WHILE | LPFLG_ONE_EXIT | LPFLG_CONST; + /* Ignore the loop if we don't have a do-while + that has a constant number of iterations */ - /* Ignore the loop if we don't have a do-while with a single exit - that has a constant number of iterations */ - - if ((loopFlags & requiredFlags) != requiredFlags) - { - continue; - } + if ((loopFlags & requiredFlags) != requiredFlags) + { + continue; + } - /* ignore if removed or marked as not unrollable */ + /* ignore if removed or marked as not unrollable */ - if (optLoopTable[lnum].lpFlags & (LPFLG_DONT_UNROLL | LPFLG_REMOVED)) - { - continue; - } + if (loopFlags & (LPFLG_DONT_UNROLL | LPFLG_REMOVED)) + { + continue; + } - head = optLoopTable[lnum].lpHead; - noway_assert(head); - bottom = optLoopTable[lnum].lpBottom; - noway_assert(bottom); + head = optLoopTable[lnum].lpHead; + noway_assert(head); + bottom = optLoopTable[lnum].lpBottom; + noway_assert(bottom); - /* The single exit must be at the bottom of the loop */ - noway_assert(optLoopTable[lnum].lpExit); - if (optLoopTable[lnum].lpExit != bottom) - { - continue; - } + /* Get the loop data: + - initial constant + - limit constant + - iterator + - iterator increment + - increment operation type (i.e. ADD, SUB, etc...) + - loop test type (i.e. GT_GE, GT_LT, etc...) + */ - /* Unrolling loops with jumps in them is not worth the headache - * Later we might consider unrolling loops after un-switching */ + lbeg = optLoopTable[lnum].lpConstInit; + llim = optLoopTable[lnum].lpConstLimit(); + testOper = optLoopTable[lnum].lpTestOper(); - block = head; - do - { - block = block->bbNext; - noway_assert(block); + lvar = optLoopTable[lnum].lpIterVar(); + iterInc = optLoopTable[lnum].lpIterConst(); + iterOper = optLoopTable[lnum].lpIterOper(); - if (block->bbJumpKind != BBJ_NONE) - { - if (block != bottom) - { - goto DONE_LOOP; - } - } - } while (block != bottom); + iterOperType = optLoopTable[lnum].lpIterOperType(); + unsTest = (optLoopTable[lnum].lpTestTree->gtFlags & GTF_UNSIGNED) != 0; - /* Get the loop data: - - initial constant - - limit constant - - iterator - - iterator increment - - increment operation type (i.e. ASG_ADD, ASG_SUB, etc...) - - loop test type (i.e. GT_GE, GT_LT, etc...) - */ + if (lvaTable[lvar].lvAddrExposed) + { // If the loop iteration variable is address-exposed then bail + continue; + } + if (lvaTable[lvar].lvIsStructField) + { // If the loop iteration variable is a promoted field from a struct then + // bail + continue; + } - lbeg = optLoopTable[lnum].lpConstInit; - llim = optLoopTable[lnum].lpConstLimit(); - testOper = optLoopTable[lnum].lpTestOper(); + /* Locate the pre-header and initialization and increment/test statements */ - lvar = optLoopTable[lnum].lpIterVar(); - iterInc = optLoopTable[lnum].lpIterConst(); - iterOper = optLoopTable[lnum].lpIterOper(); + phdr = head->bbTreeList; + noway_assert(phdr); + loop = bottom->bbTreeList; + noway_assert(loop); - iterOperType = optLoopTable[lnum].lpIterOperType(); - unsTest = (optLoopTable[lnum].lpTestTree->gtFlags & GTF_UNSIGNED) != 0; + init = head->lastStmt(); + noway_assert(init && (init->gtNext == nullptr)); + test = bottom->lastStmt(); + noway_assert(test && (test->gtNext == nullptr)); + incr = test->gtPrev; + noway_assert(incr); - if (lvaTable[lvar].lvAddrExposed) - { // If the loop iteration variable is address-exposed then bail - continue; - } - if (lvaTable[lvar].lvIsStructField) - { // If the loop iteration variable is a promoted field from a struct then - // bail - continue; - } + if (init->gtFlags & GTF_STMT_CMPADD) + { + /* Must be a duplicated loop condition */ + noway_assert(init->gtStmt.gtStmtExpr->gtOper == GT_JTRUE); - /* Locate the pre-header and initialization and increment/test statements */ + dupCond = true; + init = init->gtPrev; + noway_assert(init); + } + else + { + dupCond = false; + } - phdr = head->bbTreeList; - noway_assert(phdr); - loop = bottom->bbTreeList; - noway_assert(loop); + /* Find the number of iterations - the function returns false if not a constant number */ - init = head->lastStmt(); - noway_assert(init && (init->gtNext == nullptr)); - test = bottom->lastStmt(); - noway_assert(test && (test->gtNext == nullptr)); - incr = test->gtPrev; - noway_assert(incr); + if (!optComputeLoopRep(lbeg, llim, iterInc, iterOper, iterOperType, testOper, unsTest, dupCond, &totalIter)) + { + continue; + } - if (init->gtFlags & GTF_STMT_CMPADD) - { - /* Must be a duplicated loop condition */ - noway_assert(init->gtStmt.gtStmtExpr->gtOper == GT_JTRUE); + /* Forget it if there are too many repetitions or not a constant loop */ - dupCond = true; - init = init->gtPrev; - noway_assert(init); - } - else - { - dupCond = false; - } + if (totalIter > iterLimit) + { + continue; + } - /* Find the number of iterations - the function returns false if not a constant number */ + noway_assert(init->gtOper == GT_STMT); + init = init->gtStmt.gtStmtExpr; + noway_assert(test->gtOper == GT_STMT); + test = test->gtStmt.gtStmtExpr; + noway_assert(incr->gtOper == GT_STMT); + incr = incr->gtStmt.gtStmtExpr; - if (!optComputeLoopRep(lbeg, llim, iterInc, iterOper, iterOperType, testOper, unsTest, dupCond, &totalIter)) - { - continue; - } + // Don't unroll loops we don't understand. + if (incr->gtOper != GT_ASG) + { + continue; + } + incr = incr->gtOp.gtOp2; - /* Forget it if there are too many repetitions or not a constant loop */ + /* Make sure everything looks ok */ + if ((init->gtOper != GT_ASG) || (init->gtOp.gtOp1->gtOper != GT_LCL_VAR) || + (init->gtOp.gtOp1->gtLclVarCommon.gtLclNum != lvar) || (init->gtOp.gtOp2->gtOper != GT_CNS_INT) || + (init->gtOp.gtOp2->gtIntCon.gtIconVal != lbeg) || - if (totalIter > iterLimit) - { - continue; - } + !((incr->gtOper == GT_ADD) || (incr->gtOper == GT_SUB)) || (incr->gtOp.gtOp1->gtOper != GT_LCL_VAR) || + (incr->gtOp.gtOp1->gtLclVarCommon.gtLclNum != lvar) || (incr->gtOp.gtOp2->gtOper != GT_CNS_INT) || + (incr->gtOp.gtOp2->gtIntCon.gtIconVal != iterInc) || - noway_assert(init->gtOper == GT_STMT); - init = init->gtStmt.gtStmtExpr; - noway_assert(test->gtOper == GT_STMT); - test = test->gtStmt.gtStmtExpr; - noway_assert(incr->gtOper == GT_STMT); - incr = incr->gtStmt.gtStmtExpr; + (test->gtOper != GT_JTRUE)) + { + noway_assert(!"Bad precondition in Compiler::optUnrollLoops()"); + continue; + } - // Don't unroll loops we don't understand. - if (incr->gtOper == GT_ASG) - { - continue; - } + /* heuristic - Estimated cost in code size of the unrolled loop */ - /* Make sure everything looks ok */ - if ((init->gtOper != GT_ASG) || (init->gtOp.gtOp1->gtOper != GT_LCL_VAR) || - (init->gtOp.gtOp1->gtLclVarCommon.gtLclNum != lvar) || (init->gtOp.gtOp2->gtOper != GT_CNS_INT) || - (init->gtOp.gtOp2->gtIntCon.gtIconVal != lbeg) || + { + ClrSafeInt loopCostSz; // Cost is size of one iteration - !((incr->gtOper == GT_ASG_ADD) || (incr->gtOper == GT_ASG_SUB)) || - (incr->gtOp.gtOp1->gtOper != GT_LCL_VAR) || (incr->gtOp.gtOp1->gtLclVarCommon.gtLclNum != lvar) || - (incr->gtOp.gtOp2->gtOper != GT_CNS_INT) || (incr->gtOp.gtOp2->gtIntCon.gtIconVal != iterInc) || + block = head->bbNext; + auto tryIndex = block->bbTryIndex; - (test->gtOper != GT_JTRUE)) + loopRetCount = 0; + for (;; block = block->bbNext) { - noway_assert(!"Bad precondition in Compiler::optUnrollLoops()"); - continue; - } - - /* heuristic - Estimated cost in code size of the unrolled loop */ - - loopCostSz = 0; - - block = head; + if (block->bbTryIndex != tryIndex) + { + // Unrolling would require cloning EH regions + goto DONE_LOOP; + } - do - { - block = block->bbNext; + if (block->bbJumpKind == BBJ_RETURN) + { + ++loopRetCount; + } /* Visit all the statements in the block */ for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt) { - /* Get the expression and stop if end reached */ - - GenTreePtr expr = stmt->gtStmtExpr; - if (expr == incr) - { - break; - } - /* Calculate gtCostSz */ gtSetStmtInfo(stmt); /* Update loopCostSz */ loopCostSz += stmt->gtCostSz; } - } while (block != bottom); + + if (block == bottom) + { + break; + } + } + +#ifdef JIT32_GCENCODER + if (fgReturnCount + loopRetCount * (totalIter - 1) > SET_EPILOGCNT_MAX) + { + // Jit32 GC encoder can't report more than SET_EPILOGCNT_MAX epilogs. + goto DONE_LOOP; + } +#endif // !JIT32_GCENCODER /* Compute the estimated increase in code size for the unrolled loop */ - unsigned int fixedLoopCostSz; - fixedLoopCostSz = 8; + ClrSafeInt fixedLoopCostSz(8); - int unrollCostSz; - unrollCostSz = (loopCostSz * totalIter) - (loopCostSz + fixedLoopCostSz); + ClrSafeInt unrollCostSz = ClrSafeInt(loopCostSz * ClrSafeInt(totalIter)) - + ClrSafeInt(loopCostSz + fixedLoopCostSz); /* Don't unroll if too much code duplication would result. */ - if (unrollCostSz > unrollLimitSz) + if (unrollCostSz.IsOverflow() || (unrollCostSz.Value() > unrollLimitSz)) { - /* prevent this loop from being revisited */ - optLoopTable[lnum].lpFlags |= LPFLG_DONT_UNROLL; goto DONE_LOOP; } @@ -3100,76 +3108,81 @@ void Compiler::optUnrollLoops() printf("\n"); } #endif + } - /* Create the unrolled loop statement list */ - - loopList = loopLast = nullptr; + /* Create the unrolled loop statement list */ + { + BlockToBlockMap blockMap(getAllocator()); + BasicBlock* insertAfter = bottom; for (lval = lbeg; totalIter; totalIter--) { - block = head; - - do + for (block = head->bbNext;; block = block->bbNext) { - GenTreeStmt* stmt; - GenTree* expr; - - block = block->bbNext; - noway_assert(block); + BasicBlock* newBlock = insertAfter = + fgNewBBafter(block->bbJumpKind, insertAfter, /*extendRegion*/ true); + blockMap.Set(block, newBlock); - /* Visit all the statements in the block */ - - for (stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt) + if (!BasicBlock::CloneBlockState(this, newBlock, block, lvar, lval)) { - /* Stop if we've reached the end of the loop */ - - if (stmt->gtStmtExpr == incr) - { - break; - } - - /* Clone/substitute the expression */ - - expr = gtCloneExpr(stmt, 0, lvar, lval); - // cloneExpr doesn't handle everything + BasicBlock* oldBottomNext = insertAfter->bbNext; + bottom->bbNext = oldBottomNext; + oldBottomNext->bbPrev = bottom; + optLoopTable[lnum].lpFlags |= LPFLG_DONT_UNROLL; + goto DONE_LOOP; + } + // Block weight should no longer have the loop multiplier + newBlock->modifyBBWeight(newBlock->bbWeight / BB_LOOP_WEIGHT); + // Jump dests are set in a post-pass; make sure CloneBlockState hasn't tried to set them. + assert(newBlock->bbJumpDest == nullptr); - if (!expr) - { - optLoopTable[lnum].lpFlags |= LPFLG_DONT_UNROLL; - goto DONE_LOOP; - } - - /* Append the expression to our list */ - - if (loopList) + if (block == bottom) + { + // Remove the test; we're doing a full unroll. + + GenTreeStmt* testCopyStmt = newBlock->lastStmt(); + GenTreePtr testCopyExpr = testCopyStmt->gtStmt.gtStmtExpr; + assert(testCopyExpr->gtOper == GT_JTRUE); + GenTreePtr sideEffList = nullptr; + gtExtractSideEffList(testCopyExpr, &sideEffList, GTF_SIDE_EFFECT | GTF_ORDER_SIDEEFF); + if (sideEffList == nullptr) { - loopLast->gtNext = expr; + fgRemoveStmt(newBlock, testCopyStmt); } else { - loopList = expr; + testCopyStmt->gtStmt.gtStmtExpr = sideEffList; } + newBlock->bbJumpKind = BBJ_NONE; - expr->gtPrev = loopLast; - loopLast = expr; + // Exit this loop; we've walked all the blocks. + break; } - } while (block != bottom); + } + + // Now redirect any branches within the newly-cloned iteration + for (block = head->bbNext; block != bottom; block = block->bbNext) + { + BasicBlock* newBlock = blockMap[block]; + optCopyBlkDest(block, newBlock); + optRedirectBlock(newBlock, &blockMap); + } /* update the new value for the unrolled iterator */ switch (iterOper) { - case GT_ASG_ADD: + case GT_ADD: lval += iterInc; break; - case GT_ASG_SUB: + case GT_SUB: lval -= iterInc; break; - case GT_ASG_RSH: - case GT_ASG_LSH: + case GT_RSH: + case GT_LSH: noway_assert(!"Unrolling not implemented for this loop iterator"); goto DONE_LOOP; @@ -3179,46 +3192,22 @@ void Compiler::optUnrollLoops() } } - /* Finish the linked list */ - - if (loopList) + // Gut the old loop body + for (block = head->bbNext;; block = block->bbNext) { - loopList->gtPrev = loopLast; - loopLast->gtNext = nullptr; - } - - /* Replace the body with the unrolled one */ - - block = head; - - do - { - block = block->bbNext; - noway_assert(block); block->bbTreeList = nullptr; block->bbJumpKind = BBJ_NONE; - block->bbFlags &= ~BBF_NEEDS_GCPOLL; - } while (block != bottom); - - bottom->bbJumpKind = BBJ_NONE; - bottom->bbTreeList = loopList; - bottom->bbFlags &= ~BBF_NEEDS_GCPOLL; - bottom->modifyBBWeight(bottom->bbWeight / BB_LOOP_WEIGHT); - - bool dummy; - - fgMorphStmts(bottom, &dummy, &dummy, &dummy); - - /* Update bbRefs and bbPreds */ - /* Here head->bbNext is bottom !!! - Replace it */ - - fgRemoveRefPred(head->bbNext, bottom); - - /* Now change the initialization statement in the HEAD to "lvar = lval;" - * (the last value of the iterator in the loop) - * and drop the jump condition since the unrolled loop will always execute */ + block->bbFlags &= ~(BBF_NEEDS_GCPOLL | BBF_LOOP_HEAD); + if (block->bbJumpDest != nullptr) + { + block->bbJumpDest = nullptr; + } - init->gtOp.gtOp2->gtIntCon.gtIconVal = lval; + if (block == bottom) + { + break; + } + } /* if the HEAD is a BBJ_COND drop the condition (and make HEAD a BBJ_NONE block) */ @@ -3240,10 +3229,6 @@ void Compiler::optUnrollLoops() phdr->gtPrev = init; head->bbJumpKind = BBJ_NONE; head->bbFlags &= ~BBF_NEEDS_GCPOLL; - - /* Update bbRefs and bbPreds */ - - fgRemoveRefPred(head->bbJumpDest, head); } else { @@ -3256,18 +3241,9 @@ void Compiler::optUnrollLoops() { printf("Whole unrolled loop:\n"); - GenTreePtr s = loopList; - - while (s) - { - noway_assert(s->gtOper == GT_STMT); - gtDispTree(s); - s = s->gtNext; - } - printf("\n"); - gtDispTree(init); printf("\n"); + fgDumpTrees(head->bbNext, insertAfter); } #endif @@ -3278,22 +3254,25 @@ void Compiler::optUnrollLoops() /* Make sure to update loop table */ /* Use the LPFLG_REMOVED flag and update the bbLoopMask acordingly - * (also make head and bottom NULL - to hit an assert or GPF) */ + * (also make head and bottom NULL - to hit an assert or GPF) */ optLoopTable[lnum].lpFlags |= LPFLG_REMOVED; optLoopTable[lnum].lpHead = optLoopTable[lnum].lpBottom = nullptr; - DONE_LOOP:; + // Note if we created new BBJ_RETURNs + fgReturnCount += loopRetCount * (totalIter - 1); } - if (!change) - { - break; - } + DONE_LOOP:; + } + + if (change) + { + fgUpdateChangedFlowGraph(); } #ifdef DEBUG - fgDebugCheckBBlist(); + fgDebugCheckBBlist(true); #endif } #ifdef _PREFAST_ @@ -3639,12 +3618,10 @@ void Compiler::fgOptWhileLoop(BasicBlock* block) copyOfCondStmt->gtFlags |= GTF_STMT_CMPADD; -#ifdef DEBUGGING_SUPPORT if (opts.compDbgInfo) { copyOfCondStmt->gtStmt.gtStmtILoffsx = condStmt->gtStmt.gtStmtILoffsx; } -#endif // Flag the block that received the copy as potentially having an array/vtable // reference if the block copied from did; this is a conservative guess. @@ -4265,7 +4242,7 @@ void Compiler::optDebugLogLoopCloning(BasicBlock* block, GenTreePtr insertBefore GenTreePtr logCall = gtNewHelperCallNode(CORINFO_HELP_DEBUG_LOG_LOOP_CLONING, TYP_VOID); GenTreePtr stmt = fgNewStmtFromTree(logCall); fgInsertStmtBefore(block, insertBefore, stmt); - fgMorphBlockStmt(block, stmt DEBUGARG("Debug log loop cloning")); + fgMorphBlockStmt(block, stmt->AsStmt() DEBUGARG("Debug log loop cloning")); } #endif @@ -4394,14 +4371,18 @@ bool Compiler::optIsLoopClonable(unsigned loopInd) } // We've previously made a decision whether to have separate return epilogs, or branch to one. - // There's a GCInfo limitation in the x86 case, so that there can be no more than 4 separate epilogs. - // (I thought this was x86-specific, but it's not if-d. On other architectures, the decision should be made as a - // heuristic tradeoff; perhaps we're just choosing to live with 4 as the limit.) - if (fgReturnCount + loopRetCount > 4) + // There's a GCInfo limitation in the x86 case, so that there can be no more than SET_EPILOGCNT_MAX separate + // epilogs. Other architectures have a limit of 4 here for "historical reasons", but this should be revisited + // (or return blocks should not be considered part of the loop, rendering this issue moot). + unsigned epilogLimit = 4; +#ifdef JIT32_GCENCODER + epilogLimit = SET_EPILOGCNT_MAX; +#endif // JIT32_GCENCODER + if (fgReturnCount + loopRetCount > epilogLimit) { JITDUMP("Loop cloning: rejecting loop because it has %d returns; if added to previously-existing %d returns, " - "would exceed the limit of 4.\n", - loopRetCount, fgReturnCount); + "would exceed the limit of %d.\n", + loopRetCount, fgReturnCount, epilogLimit); return false; } @@ -4642,7 +4623,11 @@ void Compiler::optCloneLoop(unsigned loopInd, LoopCloneContext* context) BasicBlock* newBlk = fgNewBBafter(blk->bbJumpKind, newPred, /*extendRegion*/ true); - BasicBlock::CloneBlockState(this, newBlk, blk); + // Call CloneBlockState to make a copy of the block's statements (and attributes), and assert that it + // has a return value indicating success, because optCanOptimizeByLoopCloningVisitor has already + // checked them to guarantee they are clonable. + bool cloneOk = BasicBlock::CloneBlockState(this, newBlk, blk); + noway_assert(cloneOk); // TODO-Cleanup: The above clones the bbNatLoopNum, which is incorrect. Eventually, we should probably insert // the cloned loop in the loop table. For now, however, we'll just make these blocks be part of the surrounding // loop, if one exists -- the parent of the loop we're cloning. @@ -4716,6 +4701,12 @@ void Compiler::optCloneLoop(unsigned loopInd, LoopCloneContext* context) } assert(foundIt && e2 != nullptr); + // Don't unroll loops that we've cloned -- the unroller expects any loop it should unroll to + // initialize the loop counter immediately before entering the loop, but we've left a shared + // initialization of the loop counter up above the test that determines which version of the + // loop to take. + optLoopTable[loopInd].lpFlags |= LPFLG_DONT_UNROLL; + fgUpdateChangedFlowGraph(); } @@ -6226,9 +6217,28 @@ bool Compiler::optHoistLoopExprsForTree( // be hoisted so that they are evaluated in the same order as they would have been in the loop, // and therefore throw exceptions in the same order. (So we don't use GTF_GLOBALLY_VISIBLE_SIDE_EFFECTS // here, since that includes exceptions.) - if (tree->gtFlags & GTF_CALL) + if (tree->IsCall()) { - *pFirstBlockAndBeforeSideEffect = false; + // If it's a call, it must be a helper call that does not mutate the heap. + // Further, if it may run a cctor, it must be labeled as "Hoistable" + // (meaning it won't run a cctor because the class is not precise-init). + GenTreeCall* call = tree->AsCall(); + if (call->gtCallType != CT_HELPER) + { + *pFirstBlockAndBeforeSideEffect = false; + } + else + { + CorInfoHelpFunc helpFunc = eeGetHelperNum(call->gtCallMethHnd); + if (s_helperCallProperties.MutatesHeap(helpFunc)) + { + *pFirstBlockAndBeforeSideEffect = false; + } + else if (s_helperCallProperties.MayRunCctor(helpFunc) && (call->gtFlags & GTF_CALL_HOISTABLE) == 0) + { + *pFirstBlockAndBeforeSideEffect = false; + } + } } else if (tree->OperIsAssignment()) { @@ -6748,15 +6758,17 @@ void Compiler::fgCreateLoopPreHeader(unsigned lnum) bool Compiler::optBlockIsLoopEntry(BasicBlock* blk, unsigned* pLnum) { - unsigned lnum = blk->bbNatLoopNum; - while (lnum != BasicBlock::NOT_IN_LOOP) + for (unsigned lnum = blk->bbNatLoopNum; lnum != BasicBlock::NOT_IN_LOOP; lnum = optLoopTable[lnum].lpParent) { + if (optLoopTable[lnum].lpFlags & LPFLG_REMOVED) + { + continue; + } if (optLoopTable[lnum].lpEntry == blk) { *pLnum = lnum; return true; } - lnum = optLoopTable[lnum].lpParent; } return false; } @@ -7239,7 +7251,7 @@ void Compiler::optRemoveRangeCheck( noway_assert(stmt->gtOper == GT_STMT); noway_assert(tree->gtOper == GT_COMMA); - noway_assert(tree->gtOp.gtOp1->gtOper == GT_ARR_BOUNDS_CHECK); + noway_assert(tree->gtOp.gtOp1->OperIsBoundsCheck()); noway_assert(forceRemove || optIsRangeCheckRemovable(tree->gtOp.gtOp1)); GenTreeBoundsChk* bndsChk = tree->gtOp.gtOp1->AsBoundsChk(); diff --git a/src/jit/protojit/CMakeLists.txt b/src/jit/protojit/CMakeLists.txt index e3cc769..91c69e9 100644 --- a/src/jit/protojit/CMakeLists.txt +++ b/src/jit/protojit/CMakeLists.txt @@ -3,8 +3,13 @@ project(protojit) add_definitions(-DALT_JIT) add_definitions(-DFEATURE_NO_HOST) add_definitions(-DSELF_NO_HOST) +add_definitions(-DFEATURE_READYTORUN_COMPILER) remove_definitions(-DFEATURE_MERGE_JIT_AND_ENGINE) +if(WIN32) + add_definitions(-DFX_VER_INTERNALNAME_STR=protojit.dll) +endif(WIN32) + add_library_clr(protojit SHARED ${SHARED_LIB_SOURCES} @@ -28,7 +33,8 @@ if(CLR_CMAKE_PLATFORM_UNIX) ) else() list(APPEND RYUJIT_LINK_LIBRARIES - msvcrt.lib + ${STATIC_MT_CRT_LIB} + ${STATIC_MT_VCRT_LIB} kernel32.lib advapi32.lib ole32.lib diff --git a/src/jit/rangecheck.cpp b/src/jit/rangecheck.cpp index ae0c792..8d16cce 100644 --- a/src/jit/rangecheck.cpp +++ b/src/jit/rangecheck.cpp @@ -208,7 +208,7 @@ void RangeCheck::OptimizeRangeCheck(BasicBlock* block, GenTreePtr stmt, GenTreeP // If we are not looking at array bounds check, bail. GenTreePtr tree = treeParent->gtOp.gtOp1; - if (tree->gtOper != GT_ARR_BOUNDS_CHECK) + if (!tree->OperIsBoundsCheck()) { return; } @@ -233,6 +233,9 @@ void RangeCheck::OptimizeRangeCheck(BasicBlock* block, GenTreePtr stmt, GenTreeP } } else +#ifdef FEATURE_SIMD + if (tree->gtOper != GT_SIMD_CHK) +#endif // FEATURE_SIMD { arrSize = GetArrLength(arrLenVn); } diff --git a/src/jit/rationalize.cpp b/src/jit/rationalize.cpp index 03e0c9a..7f5a26f 100644 --- a/src/jit/rationalize.cpp +++ b/src/jit/rationalize.cpp @@ -16,44 +16,6 @@ struct SplitData Rationalizer* thisPhase; }; -//------------------------------------------------------------------------------ -// isNodeCallArg - given a context (stack of parent nodes), determine if the TOS is an arg to a call -//------------------------------------------------------------------------------ - -GenTree* isNodeCallArg(ArrayStack* parentStack) -{ - for (int i = 1; // 0 is current node, so start at 1 - i < parentStack->Height(); i++) - { - GenTree* node = parentStack->Index(i); - switch (node->OperGet()) - { - case GT_LIST: - case GT_ARGPLACE: - break; - case GT_NOP: - // Currently there's an issue when the rationalizer performs - // the fixup of a call argument: the case is when we remove an - // inserted NOP as a parent of a call introduced by fgMorph; - // when then the rationalizer removes it, the tree stack in the - // walk is not consistent with the node it was just deleted, so the - // solution is just to go 1 level deeper. - // TODO-Cleanup: This has to be fixed in a proper way: make the rationalizer - // correctly modify the evaluation stack when removing treenodes. - if (node->gtOp.gtOp1->gtOper == GT_CALL) - { - return node->gtOp.gtOp1; - } - break; - case GT_CALL: - return node; - default: - return nullptr; - } - } - return nullptr; -} - // return op that is the store equivalent of the given load opcode genTreeOps storeForm(genTreeOps loadForm) { @@ -109,54 +71,6 @@ void copyFlags(GenTree* dst, GenTree* src, unsigned mask) dst->gtFlags |= (src->gtFlags & mask); } -// call args have other pointers to them which must be fixed up if -// they are replaced -void Compiler::fgFixupIfCallArg(ArrayStack* parentStack, GenTree* oldChild, GenTree* newChild) -{ - GenTree* parentCall = isNodeCallArg(parentStack); - if (!parentCall) - { - return; - } - - // we have replaced an arg, so update pointers in argtable - fgFixupArgTabEntryPtr(parentCall, oldChild, newChild); -} - -//------------------------------------------------------------------------ -// fgFixupArgTabEntryPtr: Fixup the fgArgTabEntryPtr of parentCall after -// replacing oldArg with newArg -// -// Arguments: -// parentCall - a pointer to the parent call node -// oldArg - the original argument node -// newArg - the replacement argument node -// - -void Compiler::fgFixupArgTabEntryPtr(GenTreePtr parentCall, GenTreePtr oldArg, GenTreePtr newArg) -{ - assert(parentCall != nullptr); - assert(oldArg != nullptr); - assert(newArg != nullptr); - - JITDUMP("parent call was :\n"); - DISPNODE(parentCall); - - JITDUMP("old child was :\n"); - DISPNODE(oldArg); - - if (oldArg->gtFlags & GTF_LATE_ARG) - { - newArg->gtFlags |= GTF_LATE_ARG; - } - else - { - fgArgTabEntryPtr fp = Compiler::gtArgEntryByNode(parentCall, oldArg); - assert(fp->node == oldArg); - fp->node = newArg; - } -} - // Rewrite a SIMD indirection as GT_IND(GT_LEA(obj.op1)), or as a simple // lclVar if possible. // @@ -191,8 +105,8 @@ void Rationalizer::RewriteSIMDOperand(LIR::Use& use, bool keepBlk) return; } - // If the operand of is a GT_ADDR(GT_LCL_VAR) and LclVar is known to be of simdType, - // replace obj by GT_LCL_VAR. + // If we have GT_IND(GT_LCL_VAR_ADDR) and the GT_LCL_VAR_ADDR is TYP_BYREF/TYP_I_IMPL, + // and the var is a SIMD type, replace the expression by GT_LCL_VAR. GenTree* addr = tree->AsIndir()->Addr(); if (addr->OperIsLocalAddr() && comp->isAddrOfSIMDType(addr)) { @@ -202,6 +116,17 @@ void Rationalizer::RewriteSIMDOperand(LIR::Use& use, bool keepBlk) addr->gtType = simdType; use.ReplaceWith(comp, addr); } +#if defined(_TARGET_X86_) + // For x86, if we have GT_IND(GT_ADDR(GT_SIMD)), remove the GT_IND(GT_ADDR()), leaving just + // the GT_SIMD. + else if ((addr->OperGet() == GT_ADDR) && (addr->gtGetOp1()->OperGet() == GT_SIMD)) + { + BlockRange().Remove(tree); + BlockRange().Remove(addr); + + use.ReplaceWith(comp, addr->gtGetOp1()); + } +#endif // defined(_TARGET_X86_) else if (!keepBlk) { tree->SetOper(GT_IND); @@ -242,13 +167,32 @@ void Rationalizer::RewriteNodeAsCall(GenTree** use, // Create the call node GenTreeCall* call = comp->gtNewCallNode(CT_USER_FUNC, callHnd, tree->gtType, args); - call = comp->fgMorphArgs(call); + +#if DEBUG + CORINFO_SIG_INFO sig; + comp->eeGetMethodSig(callHnd, &sig); + assert(JITtype2varType(sig.retType) == tree->gtType); +#endif // DEBUG + + call = comp->fgMorphArgs(call); + // Determine if this call has changed any codegen requirements. + comp->fgCheckArgCnt(); + #ifdef FEATURE_READYTORUN_COMPILER call->gtCall.setEntryPoint(entryPoint); #endif // Replace "tree" with "call" - *use = call; + if (data->parentStack->Height() > 1) + { + data->parentStack->Index(1)->ReplaceOperand(use, call); + } + else + { + // If there's no parent, the tree being replaced is the root of the + // statement (and no special handling is necessary). + *use = call; + } // Rebuild the evaluation order. comp->gtSetStmtInfo(root); @@ -278,8 +222,6 @@ void Rationalizer::RewriteNodeAsCall(GenTree** use, treeNextNode->gtPrev = treeLastNode; } - comp->fgFixupIfCallArg(data->parentStack, tree, call); - // Propagate flags of "call" to its parents. // 0 is current node, so start at 1 for (int i = 1; i < data->parentStack->Height(); i++) @@ -510,33 +452,77 @@ void Rationalizer::RewriteAssignment(LIR::Use& use) genTreeOps locationOp = location->OperGet(); -#ifdef FEATURE_SIMD - if (varTypeIsSIMD(location) && assignment->OperIsInitBlkOp()) + if (assignment->OperIsBlkOp()) { - if (location->OperGet() == GT_LCL_VAR) +#ifdef FEATURE_SIMD + if (varTypeIsSIMD(location) && assignment->OperIsInitBlkOp()) { - var_types simdType = location->TypeGet(); - GenTree* initVal = assignment->gtOp.gtOp2; - var_types baseType = comp->getBaseTypeOfSIMDLocal(location); - if (baseType != TYP_UNKNOWN) + if (location->OperGet() == GT_LCL_VAR) { - GenTreeSIMD* simdTree = new (comp, GT_SIMD) - GenTreeSIMD(simdType, initVal, SIMDIntrinsicInit, baseType, genTypeSize(simdType)); - assignment->gtOp.gtOp2 = simdTree; - value = simdTree; - initVal->gtNext = simdTree; - simdTree->gtPrev = initVal; - - simdTree->gtNext = location; - location->gtPrev = simdTree; + var_types simdType = location->TypeGet(); + GenTree* initVal = assignment->gtOp.gtOp2; + var_types baseType = comp->getBaseTypeOfSIMDLocal(location); + if (baseType != TYP_UNKNOWN) + { + GenTreeSIMD* simdTree = new (comp, GT_SIMD) + GenTreeSIMD(simdType, initVal, SIMDIntrinsicInit, baseType, genTypeSize(simdType)); + assignment->gtOp.gtOp2 = simdTree; + value = simdTree; + initVal->gtNext = simdTree; + simdTree->gtPrev = initVal; + + simdTree->gtNext = location; + location->gtPrev = simdTree; + } } } - else +#endif // FEATURE_SIMD + if ((location->TypeGet() == TYP_STRUCT) && !assignment->IsPhiDefn() && !value->IsMultiRegCall()) { - assert(location->OperIsBlk()); + if ((location->OperGet() == GT_LCL_VAR)) + { + // We need to construct a block node for the location. + // Modify lcl to be the address form. + location->SetOper(addrForm(locationOp)); + LclVarDsc* varDsc = &(comp->lvaTable[location->AsLclVarCommon()->gtLclNum]); + location->gtType = TYP_BYREF; + GenTreeBlk* storeBlk = nullptr; + unsigned int size = varDsc->lvExactSize; + + if (varDsc->lvStructGcCount != 0) + { + CORINFO_CLASS_HANDLE structHnd = varDsc->lvVerTypeInfo.GetClassHandle(); + GenTreeObj* objNode = comp->gtNewObjNode(structHnd, location)->AsObj(); + unsigned int slots = (unsigned)(roundUp(size, TARGET_POINTER_SIZE) / TARGET_POINTER_SIZE); + + objNode->SetGCInfo(varDsc->lvGcLayout, varDsc->lvStructGcCount, slots); + objNode->ChangeOper(GT_STORE_OBJ); + objNode->SetData(value); + comp->fgMorphUnsafeBlk(objNode); + storeBlk = objNode; + } + else + { + storeBlk = new (comp, GT_STORE_BLK) GenTreeBlk(GT_STORE_BLK, TYP_STRUCT, location, value, size); + } + storeBlk->gtFlags |= (GTF_REVERSE_OPS | GTF_ASG); + storeBlk->gtFlags |= ((location->gtFlags | value->gtFlags) & GTF_ALL_EFFECT); + + GenTree* insertionPoint = location->gtNext; + BlockRange().InsertBefore(insertionPoint, storeBlk); + use.ReplaceWith(comp, storeBlk); + BlockRange().Remove(assignment); + JITDUMP("After transforming local struct assignment into a block op:\n"); + DISPTREERANGE(BlockRange(), use.Def()); + JITDUMP("\n"); + return; + } + else + { + assert(location->OperIsBlk()); + } } } -#endif // FEATURE_SIMD switch (locationOp) { @@ -605,10 +591,10 @@ void Rationalizer::RewriteAssignment(LIR::Use& use) } JITDUMP("Rewriting GT_ASG(%s(X), Y) to %s(X,Y):\n", GenTree::NodeName(location->gtOper), GenTree::NodeName(storeOper)); - storeBlk->gtOper = storeOper; + storeBlk->SetOperRaw(storeOper); storeBlk->gtFlags &= ~GTF_DONT_CSE; storeBlk->gtFlags |= (assignment->gtFlags & (GTF_ALL_EFFECT | GTF_REVERSE_OPS | GTF_BLK_VOLATILE | - GTF_BLK_UNALIGNED | GTF_BLK_INIT | GTF_DONT_CSE)); + GTF_BLK_UNALIGNED | GTF_DONT_CSE)); storeBlk->gtBlk.Data() = value; // Replace the assignment node with the store @@ -693,21 +679,20 @@ Compiler::fgWalkResult Rationalizer::RewriteNode(GenTree** useEdge, ArrayStackgtFlags & GTF_LATE_ARG) != 0; #endif - // First, remove any preceeding GT_LIST nodes, which are not otherwise visited by the tree walk. + // First, remove any preceeding list nodes, which are not otherwise visited by the tree walk. // - // NOTE: GT_LIST nodes that are used as aggregates, by block ops, and by phi nodes will in fact be visited. - for (GenTree* prev = node->gtPrev; - prev != nullptr && prev->OperGet() == GT_LIST && !(prev->AsArgList()->IsAggregate()); - prev = node->gtPrev) + // NOTE: GT_FIELD_LIST head nodes, and GT_LIST nodes used by phi nodes will in fact be visited. + for (GenTree* prev = node->gtPrev; prev != nullptr && prev->OperIsAnyList() && !(prev->OperIsFieldListHead()); + prev = node->gtPrev) { BlockRange().Remove(prev); } // In addition, remove the current node if it is a GT_LIST node that is not an aggregate. - if (node->OperGet() == GT_LIST) + if (node->OperIsAnyList()) { GenTreeArgList* list = node->AsArgList(); - if (!list->IsAggregate()) + if (!list->OperIsFieldListHead()) { BlockRange().Remove(list); } @@ -741,6 +726,11 @@ Compiler::fgWalkResult Rationalizer::RewriteNode(GenTree** useEdge, ArrayStackgtFlags &= ~GTF_IND_ASG_LHS; + break; + case GT_NOP: // fgMorph sometimes inserts NOP nodes between defs and uses // supposedly 'to prevent constant folding'. In this case, remove the @@ -931,19 +921,27 @@ Compiler::fgWalkResult Rationalizer::RewriteNode(GenTree** useEdge, ArrayStackOperGet() != GT_JCC); break; } // Do some extra processing on top-level nodes to remove unused local reads. - if (use.IsDummyUse() && node->OperIsLocalRead()) + if (node->OperIsLocalRead()) { - assert((node->gtFlags & GTF_ALL_EFFECT) == 0); - - comp->lvaDecRefCnts(node); - BlockRange().Remove(node); + if (use.IsDummyUse()) + { + comp->lvaDecRefCnts(node); + BlockRange().Remove(node); + } + else + { + // Local reads are side-effect-free; clear any flags leftover from frontend transformations. + node->gtFlags &= ~GTF_ALL_EFFECT; + } } - assert(isLateArg == ((node->gtFlags & GTF_LATE_ARG) != 0)); + assert(isLateArg == ((use.Def()->gtFlags & GTF_LATE_ARG) != 0)); return Compiler::WALK_CONTINUE; } diff --git a/src/jit/regalloc.cpp b/src/jit/regalloc.cpp index 9dd7299..8a7ad5a 100644 --- a/src/jit/regalloc.cpp +++ b/src/jit/regalloc.cpp @@ -53,8 +53,6 @@ regMaskTP Compiler::raConfigRestrictMaskFP() return result; } -#ifdef LEGACY_BACKEND // We don't use any of the old register allocator functions when LSRA is used instead. - #if DOUBLE_ALIGN DWORD Compiler::getCanDoubleAlign() { @@ -67,8 +65,84 @@ DWORD Compiler::getCanDoubleAlign() return DEFAULT_DOUBLE_ALIGN; #endif } + +//------------------------------------------------------------------------ +// shouldDoubleAlign: Determine whether to double-align the frame +// +// Arguments: +// refCntStk - sum of ref counts for all stack based variables +// refCntEBP - sum of ref counts for EBP enregistered variables +// refCntWtdEBP - sum of wtd ref counts for EBP enregistered variables +// refCntStkParam - sum of ref counts for all stack based parameters +// refCntWtdStkDbl - sum of wtd ref counts for stack based doubles (including structs +// with double fields). +// +// Return Value: +// Returns true if this method estimates that a double-aligned frame would be beneficial +// +// Notes: +// The impact of a double-aligned frame is computed as follows: +// - We save a byte of code for each parameter reference (they are frame-pointer relative) +// - We pay a byte of code for each non-parameter stack reference. +// - We save the misalignment penalty and possible cache-line crossing penalty. +// This is estimated as 0 for SMALL_CODE, 16 for FAST_CODE and 4 otherwise. +// - We pay 7 extra bytes for: +// MOV EBP,ESP, +// LEA ESP,[EBP-offset] +// AND ESP,-8 to double align ESP +// - We pay one extra memory reference for each variable that could have been enregistered in EBP (refCntWtdEBP). +// +// If the misalignment penalty is estimated to be less than the bytes used, we don't double align. +// Otherwise, we compare the weighted ref count of ebp-enregistered variables aginst double the +// ref count for double-aligned values. +// +bool Compiler::shouldDoubleAlign( + unsigned refCntStk, unsigned refCntEBP, unsigned refCntWtdEBP, unsigned refCntStkParam, unsigned refCntWtdStkDbl) +{ + bool doDoubleAlign = false; + const unsigned DBL_ALIGN_SETUP_SIZE = 7; + + unsigned bytesUsed = refCntStk + refCntEBP - refCntStkParam + DBL_ALIGN_SETUP_SIZE; + unsigned misaligned_weight = 4; + + if (compCodeOpt() == Compiler::SMALL_CODE) + misaligned_weight = 0; + + if (compCodeOpt() == Compiler::FAST_CODE) + misaligned_weight *= 4; + + JITDUMP("\nDouble alignment:\n"); + JITDUMP(" Bytes that could be saved by not using EBP frame: %i\n", bytesUsed); + JITDUMP(" Sum of weighted ref counts for EBP enregistered variables: %i\n", refCntWtdEBP); + JITDUMP(" Sum of weighted ref counts for weighted stack based doubles: %i\n", refCntWtdStkDbl); + + if (bytesUsed > ((refCntWtdStkDbl * misaligned_weight) / BB_UNITY_WEIGHT)) + { + JITDUMP(" Predicting not to double-align ESP to save %d bytes of code.\n", bytesUsed); + } + else if (refCntWtdEBP > refCntWtdStkDbl * 2) + { + // TODO-CQ: On P4 2 Proc XEON's, SciMark.FFT degrades if SciMark.FFT.transform_internal is + // not double aligned. + // Here are the numbers that make this not double-aligned. + // refCntWtdStkDbl = 0x164 + // refCntWtdEBP = 0x1a4 + // We think we do need to change the heuristic to be in favor of double-align. + + JITDUMP(" Predicting not to double-align ESP to allow EBP to be used to enregister variables.\n"); + } + else + { + // OK we passed all of the benefit tests, so we'll predict a double aligned frame. + JITDUMP(" Predicting to create a double-aligned frame\n"); + doDoubleAlign = true; + } + return doDoubleAlign; +} #endif // DOUBLE_ALIGN +#ifdef LEGACY_BACKEND // We don't use any of the old register allocator functions when LSRA is used instead. + void Compiler::raInit() { #if FEATURE_STACK_FP_X87 @@ -2415,12 +2489,6 @@ regMaskTP Compiler::rpPredictTreeRegUse(GenTreePtr tree, { case GT_ASG: - if (tree->OperIsBlkOp()) - { - interferingRegs |= rpPredictBlkAsgRegUse(tree, predictReg, lockedRegs, rsvdRegs); - regMask = 0; - goto RETURN_CHECK; - } /* Is the value being assigned into a LCL_VAR? */ if (op1->gtOper == GT_LCL_VAR) { @@ -2486,6 +2554,12 @@ regMaskTP Compiler::rpPredictTreeRegUse(GenTreePtr tree, } } } + else if (tree->OperIsBlkOp()) + { + interferingRegs |= rpPredictBlkAsgRegUse(tree, predictReg, lockedRegs, rsvdRegs); + regMask = 0; + goto RETURN_CHECK; + } __fallthrough; case GT_CHS: @@ -4384,6 +4458,13 @@ regMaskTP Compiler::rpPredictTreeRegUse(GenTreePtr tree, case GT_ARR_LENGTH: goto GENERIC_UNARY; + case GT_INIT_VAL: + // This unary operator simply passes through the value from its child (much like GT_NOP) + // and thus won't need a scratch register. + regMask = rpPredictTreeRegUse(op1, predictReg, lockedRegs, rsvdRegs); + tree->gtUsedRegs = op1->gtUsedRegs; + goto RETURN_CHECK; + default: #ifdef DEBUG gtDispTree(tree); @@ -4525,7 +4606,7 @@ regMaskTP Compiler::rpPredictTreeRegUse(GenTreePtr tree, curArgMask = RBM_NONE; // Set of argument registers that are going to be setup by this arg tmpMask = RBM_NONE; // Set of additional temp registers that are need only to setup the current arg - assert(list->IsList()); + assert(list->OperIsList()); args = list->Current(); list = list->Rest(); @@ -5840,114 +5921,14 @@ regMaskTP Compiler::rpPredictAssignRegVars(regMaskTP regAvail) if (getCanDoubleAlign() == CAN_DOUBLE_ALIGN && (refCntWtdStkDbl > 0)) { - /* OK, there may be some benefit to double-aligning the frame */ - /* But let us compare the benefits vs. the costs of this */ - - /* - One cost to consider is the benefit of smaller code - when using EBP as a frame pointer register - - Each stack variable reference is an extra byte of code - if we use a double-aligned frame, parameters are - accessed via EBP for a double-aligned frame so they - don't use an extra byte of code. - - We pay one byte of code for each refCntStk and we pay - one byte or more for each refCntEBP but we save one - byte for each refCntStkParam. - - Our savings are the elimination of a possible misaligned - access and a possible DCU spilt when an access crossed - a cache-line boundry. - - We use the loop weighted value of - refCntWtdStkDbl * misaligned_weight (0, 4, 16) - to represent this savings. - */ - - // We also pay 7 extra bytes for the MOV EBP,ESP, - // LEA ESP,[EBP-0x10] and the AND ESP,-8 to double align ESP - const unsigned DBL_ALIGN_SETUP_SIZE = 7; - - unsigned bytesUsed = refCntStk + refCntEBP - refCntStkParam + DBL_ALIGN_SETUP_SIZE; - unsigned misaligned_weight = 4; - - if (compCodeOpt() == SMALL_CODE) - misaligned_weight = 0; - - if (compCodeOpt() == FAST_CODE) - misaligned_weight *= 4; - -#ifdef DEBUG - if (verbose) - { - printf("; Double alignment:\n"); - printf("; Bytes that could be save by not using EBP frame: %i\n", bytesUsed); - printf("; Sum of weighted ref counts for EBP enregistered variables: %i\n", refCntWtdEBP); - printf("; Sum of weighted ref counts for weighted stack based doubles: %i\n", refCntWtdStkDbl); - } -#endif - - if (bytesUsed > ((refCntWtdStkDbl * misaligned_weight) / BB_UNITY_WEIGHT)) - { - /* It's probably better to use EBP as a frame pointer */ - CLANG_FORMAT_COMMENT_ANCHOR; - -#ifdef DEBUG - if (verbose) - printf("; Predicting not to double-align ESP to save %d bytes of code.\n", bytesUsed); -#endif - goto NO_DOUBLE_ALIGN; - } - - /* - Another cost to consider is the benefit of using EBP to enregister - one or more integer variables - - We pay one extra memory reference for each refCntWtdEBP - - Our savings are the elimination of a possible misaligned - access and a possible DCU spilt when an access crossed - a cache-line boundry. - - */ - - // - // VSW 346717: On P4 2 Proc XEON's, SciMark.FFT degrades if SciMark.FFT.transform_internal is - // not double aligned. - // Here are the numbers that make this not double-aligned. - // refCntWtdStkDbl = 0x164 - // refCntWtdEBP = 0x1a4 - // We think we do need to change the heuristic to be in favor of double-align. - // - - if (refCntWtdEBP > refCntWtdStkDbl * 2) + if (shouldDoubleAlign(refCntStk, refCntEBP, refCntWtdEBP, refCntStkParam, refCntWtdStkDbl)) { - /* It's probably better to use EBP to enregister integer variables */ - CLANG_FORMAT_COMMENT_ANCHOR; - -#ifdef DEBUG - if (verbose) - printf("; Predicting not to double-align ESP to allow EBP to be used to enregister variables\n"); -#endif - goto NO_DOUBLE_ALIGN; + rpFrameType = FT_DOUBLE_ALIGN_FRAME; + goto REVERSE_EBP_ENREG; } - -#ifdef DEBUG - if (verbose) - printf("; Predicting to create a double-aligned frame\n"); -#endif - /* - OK we passed all of the benefit tests - so we'll predict a double aligned frame - */ - - rpFrameType = FT_DOUBLE_ALIGN_FRAME; - goto REVERSE_EBP_ENREG; } } -NO_DOUBLE_ALIGN: #endif // DOUBLE_ALIGN if (!codeGen->isFramePointerRequired() && !codeGen->isFrameRequired()) @@ -6673,8 +6654,6 @@ void Compiler::raMarkStkVars() #endif // FEATURE_FIXED_OUT_ARGS -#ifdef DEBUGGING_SUPPORT - #ifdef DEBUG /* For debugging, note that we have to reserve space even for unused variables if they are ever in scope. However, this is not @@ -6709,7 +6688,6 @@ void Compiler::raMarkStkVars() varDsc->lvMustInit = true; } } -#endif // DEBUGGING_SUPPORT #ifndef LEGACY_BACKEND varDsc->lvOnFrame = needSlot; diff --git a/src/jit/regalloc.h b/src/jit/regalloc.h index 7e2d7c7..5054b45 100644 --- a/src/jit/regalloc.h +++ b/src/jit/regalloc.h @@ -17,6 +17,18 @@ enum FrameType #endif }; +#if DOUBLE_ALIGN +enum CanDoubleAlign +{ + CANT_DOUBLE_ALIGN, + CAN_DOUBLE_ALIGN, + MUST_DOUBLE_ALIGN, + COUNT_DOUBLE_ALIGN, + + DEFAULT_DOUBLE_ALIGN = CAN_DOUBLE_ALIGN +}; +#endif + #ifdef LEGACY_BACKEND #include "varset.h" @@ -94,18 +106,6 @@ enum rpPredictReg #endif // _TARGET_ }; -#if DOUBLE_ALIGN -enum CanDoubleAlign -{ - CANT_DOUBLE_ALIGN, - CAN_DOUBLE_ALIGN, - MUST_DOUBLE_ALIGN, - COUNT_DOUBLE_ALIGN, - - DEFAULT_DOUBLE_ALIGN = CAN_DOUBLE_ALIGN -}; -#endif - #endif // LEGACY_BACKEND #endif // REGALLOC_H_ diff --git a/src/jit/registerfp.cpp b/src/jit/registerfp.cpp index 997c223..3a3143e 100644 --- a/src/jit/registerfp.cpp +++ b/src/jit/registerfp.cpp @@ -326,10 +326,8 @@ void CodeGen::genFloatAssign(GenTree* tree) bool unaligned = false; // Is this an unaligned store regNumber op2reg = REG_NA; -#ifdef DEBUGGING_SUPPORT unsigned lclVarNum = compiler->lvaCount; unsigned lclILoffs = DUMMY_INIT(0); -#endif noway_assert(tree->OperGet() == GT_ASG); @@ -358,7 +356,6 @@ void CodeGen::genFloatAssign(GenTree* tree) noway_assert(varNum < compiler->lvaCount); varDsc = compiler->lvaTable + varNum; -#ifdef DEBUGGING_SUPPORT // For non-debuggable code, every definition of a lcl-var has // to be checked to see if we need to open a new scope for it. // Remember the local var info to call siCheckVarScope @@ -369,7 +366,6 @@ void CodeGen::genFloatAssign(GenTree* tree) lclVarNum = varNum; lclILoffs = op1->gtLclVar.gtLclILoffs; } -#endif // Dead Store assert (with min opts we may have dead stores) // @@ -607,13 +603,11 @@ DONE_ASG: genUpdateLife(tree); -#ifdef DEBUGGING_SUPPORT /* For non-debuggable code, every definition of a lcl-var has * to be checked to see if we need to open a new scope for it. */ if (lclVarNum < compiler->lvaCount) siCheckVarScope(lclVarNum, lclILoffs); -#endif } void CodeGen::genCodeForTreeFloat(GenTreePtr tree, RegSet::RegisterPreference* pref) diff --git a/src/jit/regset.cpp b/src/jit/regset.cpp index 2980f96..0d0ac3e 100644 --- a/src/jit/regset.cpp +++ b/src/jit/regset.cpp @@ -3175,6 +3175,16 @@ var_types Compiler::tmpNormalizeType(var_types type) type = genActualType(type); +#if defined(FEATURE_SIMD) && !defined(_TARGET_64BIT_) + // For SIMD on 32-bit platforms, we always spill SIMD12 to a 16-byte SIMD16 temp. + // This is because we don't have a single instruction to store 12 bytes. We also + // allocate non-argument locals as 16 bytes; see lvSize(). + if (type == TYP_SIMD12) + { + type = TYP_SIMD16; + } +#endif // defined(FEATURE_SIMD) && !defined(_TARGET_64BIT_) + #else // LEGACY_BACKEND if (!varTypeIsGC(type)) { diff --git a/src/jit/scopeinfo.cpp b/src/jit/scopeinfo.cpp index f2a7902..29c18f9 100644 --- a/src/jit/scopeinfo.cpp +++ b/src/jit/scopeinfo.cpp @@ -58,10 +58,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #include "emit.h" #include "codegen.h" -/*****************************************************************************/ -#ifdef DEBUGGING_SUPPORT -/*****************************************************************************/ - bool Compiler::siVarLoc::vlIsInReg(regNumber reg) { switch (vlType) @@ -1050,7 +1046,6 @@ void CodeGen::psiBegProlog() void CodeGen::psiAdjustStackLevel(unsigned size) { -#ifdef DEBUGGING_SUPPORT if (!compiler->opts.compScopeInfo || (compiler->info.compVarScopesCount == 0)) { return; @@ -1082,7 +1077,6 @@ void CodeGen::psiAdjustStackLevel(unsigned size) } #endif // ACCURATE_PROLOG_DEBUG_INFO -#endif // DEBUGGING_SUPPORT } /***************************************************************************** @@ -1094,7 +1088,6 @@ void CodeGen::psiAdjustStackLevel(unsigned size) void CodeGen::psiMoveESPtoEBP() { -#ifdef DEBUGGING_SUPPORT if (!compiler->opts.compScopeInfo || (compiler->info.compVarScopesCount == 0)) { return; @@ -1127,7 +1120,6 @@ void CodeGen::psiMoveESPtoEBP() } #endif // ACCURATE_PROLOG_DEBUG_INFO -#endif // DEBUGGING_SUPPORT } /***************************************************************************** @@ -1141,7 +1133,6 @@ void CodeGen::psiMoveESPtoEBP() void CodeGen::psiMoveToReg(unsigned varNum, regNumber reg, regNumber otherReg) { -#ifdef DEBUGGING_SUPPORT assert(compiler->compGeneratingProlog); if (!compiler->opts.compScopeInfo) @@ -1195,7 +1186,6 @@ void CodeGen::psiMoveToReg(unsigned varNum, regNumber reg, regNumber otherReg) !"Parameter scope not found (Assert doesnt always indicate error)"); #endif // ACCURATE_PROLOG_DEBUG_INFO -#endif // DEBUGGING_SUPPORT } /***************************************************************************** @@ -1207,7 +1197,6 @@ void CodeGen::psiMoveToReg(unsigned varNum, regNumber reg, regNumber otherReg) void CodeGen::psiMoveToStack(unsigned varNum) { -#ifdef DEBUGGING_SUPPORT if (!compiler->opts.compScopeInfo || (compiler->info.compVarScopesCount == 0)) { return; @@ -1248,7 +1237,6 @@ void CodeGen::psiMoveToStack(unsigned varNum) !"Parameter scope not found (Assert doesnt always indicate error)"); #endif // ACCURATE_PROLOG_DEBUG_INFO -#endif // DEBUGGING_SUPPORT } /***************************************************************************** @@ -1264,8 +1252,4 @@ void CodeGen::psiEndProlog() { psiEndPrologScope(scope); } -} - -/*****************************************************************************/ -#endif // DEBUGGING_SUPPORT -/*****************************************************************************/ +} \ No newline at end of file diff --git a/src/jit/sideeffects.h b/src/jit/sideeffects.h index 33fac16..e14b292 100644 --- a/src/jit/sideeffects.h +++ b/src/jit/sideeffects.h @@ -136,6 +136,12 @@ public: // SideEffectSet: // Represents a set of side effects for the purposes of analyzing code // motion. +// Note that for non-fixed-size frames without a frame pointer (currently +// x86-only), we don't track the modification of the stack level that occurs +// with a GT_PUTARG_STK as a side-effect. If we ever support general code +// reordering, that would have to be taken into account. As it happens, +// we currently do not reorder any other side-effecting nodes relative to +// these. // class SideEffectSet final { diff --git a/src/jit/simd.cpp b/src/jit/simd.cpp index 1f0c867..39664c4 100644 --- a/src/jit/simd.cpp +++ b/src/jit/simd.cpp @@ -77,10 +77,10 @@ int Compiler::getSIMDVectorLength(CORINFO_CLASS_HANDLE typeHnd) // int Compiler::getSIMDTypeAlignment(var_types simdType) { -#ifdef _TARGET_AMD64_ +#ifdef _TARGET_XARCH_ // Fixed length vectors have the following alignment preference - // Vector2/3 = 8 byte alignment - // Vector4 = 16-byte alignment + // Vector2 = 8 byte alignment + // Vector3/4 = 16-byte alignment unsigned size = genTypeSize(simdType); // preferred alignment for SSE2 128-bit vectors is 16-bytes @@ -88,13 +88,16 @@ int Compiler::getSIMDTypeAlignment(var_types simdType) { return 8; } - - // As per Intel manual, AVX vectors preferred alignment is 32-bytes but on Amd64 - // RSP/EBP is aligned at 16-bytes, therefore to align SIMD types at 32-bytes we need even - // RSP/EBP to be 32-byte aligned. It is not clear whether additional stack space used in - // aligning stack is worth the benefit and for now will use 16-byte alignment for AVX - // 256-bit vectors with unaligned load/stores to/from memory. - return 16; + else if (size <= 16) + { + assert((size == 12) || (size == 16)); + return 16; + } + else + { + assert(size == 32); + return 32; + } #else assert(!"getSIMDTypeAlignment() unimplemented on target arch"); unreached(); @@ -391,7 +394,6 @@ const SIMDIntrinsicInfo* Compiler::getSIMDIntrinsicInfo(CORINFO_CLASS_HANDLE* in CORINFO_CLASS_HANDLE typeHnd = *inOutTypeHnd; *baseType = getBaseTypeAndSizeOfSIMDType(typeHnd, sizeBytes); - bool isHWAcceleratedIntrinsic = false; if (typeHnd == SIMDVectorHandle) { // All of the supported intrinsics on this static class take a first argument that's a vector, @@ -424,6 +426,16 @@ const SIMDIntrinsicInfo* Compiler::getSIMDIntrinsicInfo(CORINFO_CLASS_HANDLE* in return nullptr; } +#ifdef _TARGET_X86_ + // NYI: support LONG type SIMD intrinsics. Need support in long decomposition. + // (Don't use NYI fallback mechanism; just call the function.) + if ((*baseType == TYP_LONG) || (*baseType == TYP_ULONG)) + { + JITDUMP("NYI: x86 long base type SIMD intrinsics\n"); + return nullptr; + } +#endif // _TARGET_X86_ + // account for implicit "this" arg *argCount = sig->numArgs; if (sig->hasThis()) @@ -525,7 +537,8 @@ const SIMDIntrinsicInfo* Compiler::getSIMDIntrinsicInfo(CORINFO_CLASS_HANDLE* in // We don't check anything in that case. if (!isThisPtr || !isNewObj) { - GenTreePtr arg = impStackTop(stackIndex).val; + GenTreePtr arg = impStackTop(stackIndex).val; + var_types argType = arg->TypeGet(); var_types expectedArgType; if (argIndex < fixedArgCnt) @@ -540,6 +553,7 @@ const SIMDIntrinsicInfo* Compiler::getSIMDIntrinsicInfo(CORINFO_CLASS_HANDLE* in { // The type of the argument will be genActualType(*baseType). expectedArgType = genActualType(*baseType); + argType = genActualType(argType); } } else @@ -547,7 +561,6 @@ const SIMDIntrinsicInfo* Compiler::getSIMDIntrinsicInfo(CORINFO_CLASS_HANDLE* in expectedArgType = *baseType; } - var_types argType = arg->TypeGet(); if (!isThisPtr && argType == TYP_I_IMPL) { // The reference implementation has a constructor that takes a pointer. @@ -715,7 +728,7 @@ GenTreeSIMD* Compiler::impSIMDGetFixed(var_types simdType, var_types baseType, u return simdTree; } -#ifdef _TARGET_AMD64_ +#ifdef _TARGET_XARCH_ // impSIMDLongRelOpEqual: transforms operands and returns the SIMD intrinsic to be applied on // transformed operands to obtain == comparison result. // @@ -741,7 +754,7 @@ SIMDIntrinsicID Compiler::impSIMDLongRelOpEqual(CORINFO_CLASS_HANDLE typeHnd, // // Equality(v1, v2): // tmp = (v1 == v2) i.e. compare for equality as if v1 and v2 are vector - // result = BitwiseAnd(t, shuffle(t, (2, 3, 1 0))) + // result = BitwiseAnd(t, shuffle(t, (2, 3, 0, 1))) // Shuffle is meant to swap the comparison results of low-32-bits and high 32-bits of respective long elements. // Compare vector as if they were vector and assign the result to a temp @@ -755,7 +768,7 @@ SIMDIntrinsicID Compiler::impSIMDLongRelOpEqual(CORINFO_CLASS_HANDLE typeHnd, // op2 = Shuffle(tmp, 0xB1) // IntrinsicId = BitwiseAnd *pOp1 = gtNewOperNode(GT_COMMA, simdType, asg, tmp); - *pOp2 = gtNewSIMDNode(simdType, gtNewLclvNode(lclNum, simdType), gtNewIconNode(SHUFFLE_ZWYX, TYP_INT), + *pOp2 = gtNewSIMDNode(simdType, gtNewLclvNode(lclNum, simdType), gtNewIconNode(SHUFFLE_ZWXY, TYP_INT), SIMDIntrinsicShuffleSSE2, TYP_INT, size); return SIMDIntrinsicBitwiseAnd; } @@ -971,7 +984,7 @@ SIMDIntrinsicID Compiler::impSIMDIntegralRelOpGreaterThanOrEqual( return SIMDIntrinsicBitwiseOr; } -#endif //_TARGET_AMD64_ +#endif // _TARGET_XARCH_ // Transforms operands and returns the SIMD intrinsic to be applied on // transformed operands to obtain given relop result. @@ -999,7 +1012,7 @@ SIMDIntrinsicID Compiler::impSIMDRelOp(SIMDIntrinsicID relOpIntrinsicId, assert(isRelOpSIMDIntrinsic(relOpIntrinsicId)); -#ifdef _TARGET_AMD64_ +#ifdef _TARGET_XARCH_ SIMDIntrinsicID intrinsicID = relOpIntrinsicId; var_types baseType = *inOutBaseType; @@ -1076,7 +1089,7 @@ SIMDIntrinsicID Compiler::impSIMDRelOp(SIMDIntrinsicID relOpIntrinsicId, // // We need to treat op1 and op2 as signed for comparison purpose after // the transformation. - ssize_t constVal = 0; + __int64 constVal = 0; switch (baseType) { case TYP_UBYTE: @@ -1105,9 +1118,19 @@ SIMDIntrinsicID Compiler::impSIMDRelOp(SIMDIntrinsicID relOpIntrinsicId, if (intrinsicID != SIMDIntrinsicEqual) { // For constructing const vector use either long or int base type. - var_types tempBaseType = (baseType == TYP_ULONG) ? TYP_LONG : TYP_INT; - GenTree* initVal = gtNewIconNode(constVal); - initVal->gtType = tempBaseType; + var_types tempBaseType; + GenTree* initVal; + if (baseType == TYP_ULONG) + { + tempBaseType = TYP_LONG; + initVal = gtNewLconNode(constVal); + } + else + { + tempBaseType = TYP_INT; + initVal = gtNewIconNode((ssize_t)constVal); + } + initVal->gtType = tempBaseType; GenTree* constVector = gtNewSIMDNode(simdType, initVal, nullptr, SIMDIntrinsicInit, tempBaseType, size); // Assign constVector to a temp, since we intend to use it more than once @@ -1127,10 +1150,10 @@ SIMDIntrinsicID Compiler::impSIMDRelOp(SIMDIntrinsicID relOpIntrinsicId, } return intrinsicID; -#else +#else // !_TARGET_XARCH_ assert(!"impSIMDRelOp() unimplemented on target arch"); unreached(); -#endif //_TARGET_AMD64_ +#endif // !_TARGET_XARCH_ } // Creates a GT_SIMD tree for Select operation @@ -1210,7 +1233,7 @@ GenTreePtr Compiler::impSIMDMinMax(SIMDIntrinsicID intrinsicId, var_types simdType = op1->TypeGet(); assert(op2->TypeGet() == simdType); -#ifdef _TARGET_AMD64_ +#ifdef _TARGET_XARCH_ // SSE2 has direct support for float/double/signed word/unsigned byte. // For other integer types we compute min/max as follows // @@ -1347,10 +1370,10 @@ GenTreePtr Compiler::impSIMDMinMax(SIMDIntrinsicID intrinsicId, assert(simdTree != nullptr); return simdTree; -#else +#else // !_TARGET_XARCH_ assert(!"impSIMDMinMax() unimplemented on target arch"); unreached(); -#endif //_TARGET_AMD64_ +#endif // !_TARGET_XARCH_ } //------------------------------------------------------------------------ @@ -1791,6 +1814,8 @@ GenTreePtr Compiler::impSIMDIntrinsic(OPCODE opcode, int length = getSIMDVectorLength(clsHnd); GenTreeIntCon* intConstTree = new (this, GT_CNS_INT) GenTreeIntCon(TYP_INT, length); retVal = intConstTree; + + intConstTree->gtFlags |= GTF_ICON_SIMD_COUNT; } break; @@ -2223,7 +2248,11 @@ GenTreePtr Compiler::impSIMDIntrinsic(OPCODE opcode, assert(op2->TypeGet() == simdType); simdTree = gtNewSIMDNode(genActualType(callType), op1, op2, SIMDIntrinsicOpEquality, baseType, size); - retVal = simdTree; + if (simdType == TYP_SIMD12) + { + simdTree->gtFlags |= GTF_SIMD12_OP; + } + retVal = simdTree; } break; @@ -2234,7 +2263,11 @@ GenTreePtr Compiler::impSIMDIntrinsic(OPCODE opcode, op2 = impSIMDPopStack(simdType); op1 = impSIMDPopStack(simdType, instMethod); simdTree = gtNewSIMDNode(genActualType(callType), op1, op2, SIMDIntrinsicOpInEquality, baseType, size); - retVal = simdTree; + if (simdType == TYP_SIMD12) + { + simdTree->gtFlags |= GTF_SIMD12_OP; + } + retVal = simdTree; } break; @@ -2262,7 +2295,7 @@ GenTreePtr Compiler::impSIMDIntrinsic(OPCODE opcode, case SIMDIntrinsicBitwiseOr: case SIMDIntrinsicBitwiseXor: { -#if defined(_TARGET_AMD64_) && defined(DEBUG) +#if defined(_TARGET_XARCH_) && defined(DEBUG) // check for the cases where we don't support intrinsics. // This check should be done before we make modifications to type stack. // Note that this is more of a double safety check for robustness since @@ -2290,7 +2323,7 @@ GenTreePtr Compiler::impSIMDIntrinsic(OPCODE opcode, return nullptr; } } -#endif //_TARGET_AMD64_ && DEBUG +#endif // _TARGET_XARCH_ && DEBUG // op1 is the first operand; if instance method, op1 is "this" arg // op2 is the second operand @@ -2331,9 +2364,9 @@ GenTreePtr Compiler::impSIMDIntrinsic(OPCODE opcode, { // op1 is a SIMD variable that is "this" arg // op2 is an index of TYP_INT - op2 = impSIMDPopStack(TYP_INT); - op1 = impSIMDPopStack(simdType, instMethod); - unsigned int vectorLength = getSIMDVectorLength(size, baseType); + op2 = impSIMDPopStack(TYP_INT); + op1 = impSIMDPopStack(simdType, instMethod); + int vectorLength = getSIMDVectorLength(size, baseType); if (!op2->IsCnsIntOrI() || op2->AsIntCon()->gtIconVal >= vectorLength) { // We need to bounds-check the length of the vector. @@ -2366,15 +2399,15 @@ GenTreePtr Compiler::impSIMDIntrinsic(OPCODE opcode, case SIMDIntrinsicDotProduct: { -#if defined(_TARGET_AMD64_) && defined(DEBUG) - // Right now dot product is supported only for float vectors. - // See SIMDIntrinsicList.h for supported base types for this intrinsic. - if (!varTypeIsFloating(baseType)) +#if defined(_TARGET_XARCH_) + // Right now dot product is supported only for float/double vectors and + // int vectors on SSE4/AVX. + if (!varTypeIsFloating(baseType) && + !(baseType == TYP_INT && getSIMDInstructionSet() >= InstructionSet_SSE3_4)) { - assert(!"Dot product on integer type vectors not supported"); return nullptr; } -#endif //_TARGET_AMD64_ && DEBUG +#endif // _TARGET_XARCH_ // op1 is a SIMD variable that is the first source and also "this" arg. // op2 is a SIMD variable which is the second source. @@ -2382,13 +2415,17 @@ GenTreePtr Compiler::impSIMDIntrinsic(OPCODE opcode, op1 = impSIMDPopStack(simdType, instMethod); simdTree = gtNewSIMDNode(baseType, op1, op2, simdIntrinsicID, baseType, size); - retVal = simdTree; + if (simdType == TYP_SIMD12) + { + simdTree->gtFlags |= GTF_SIMD12_OP; + } + retVal = simdTree; } break; case SIMDIntrinsicSqrt: { -#if defined(_TARGET_AMD64_) && defined(DEBUG) +#if defined(_TARGET_XARCH_) && defined(DEBUG) // SSE/AVX doesn't support sqrt on integer type vectors and hence // should never be seen as an intrinsic here. See SIMDIntrinsicList.h // for supported base types for this intrinsic. @@ -2397,7 +2434,7 @@ GenTreePtr Compiler::impSIMDIntrinsic(OPCODE opcode, assert(!"Sqrt not supported on integer vectors\n"); return nullptr; } -#endif // _TARGET_AMD64_ && DEBUG +#endif // _TARGET_XARCH_ && DEBUG op1 = impSIMDPopStack(simdType); @@ -2409,7 +2446,7 @@ GenTreePtr Compiler::impSIMDIntrinsic(OPCODE opcode, { op1 = impSIMDPopStack(simdType); -#ifdef _TARGET_AMD64_ +#ifdef _TARGET_XARCH_ if (varTypeIsFloating(baseType)) { // Abs(vf) = vf & new SIMDVector(0x7fffffff); @@ -2448,10 +2485,10 @@ GenTreePtr Compiler::impSIMDIntrinsic(OPCODE opcode, unreached(); } -#else //!_TARGET_AMD64_ - assert(!"Abs intrinsic on non-Amd64 target not implemented"); +#else // !_TARGET_XARCH_ + assert(!"Abs intrinsic on non-xarch target not implemented"); unreached(); -#endif //!_TARGET_AMD64_ +#endif // !_TARGET_XARCH_ } break; @@ -2524,15 +2561,15 @@ GenTreePtr Compiler::impSIMDIntrinsic(OPCODE opcode, return nullptr; } -#ifdef _TARGET_AMD64_ - // Amd64: also indicate that we use floating point registers. +#ifdef _TARGET_XARCH_ + // XArch: also indicate that we use floating point registers. // The need for setting this here is that a method may not have SIMD // type lclvars, but might be exercising SIMD intrinsics on fields of // SIMD type. // // e.g. public Vector ComplexVecFloat::sqabs() { return this.r * this.r + this.i * this.i; } compFloatingPointUsed = true; -#endif +#endif // _TARGET_XARCH_ // At this point, we have a tree that we are going to store into a destination. // TODO-1stClassStructs: This should be a simple store or assignment, and should not require diff --git a/src/jit/simd.h b/src/jit/simd.h index c68899e..c4a8866 100644 --- a/src/jit/simd.h +++ b/src/jit/simd.h @@ -29,13 +29,18 @@ struct SIMDIntrinsicInfo var_types supportedBaseTypes[SIMD_INTRINSIC_MAX_BASETYPE_COUNT]; }; -#ifdef _TARGET_AMD64_ +#ifdef _TARGET_XARCH_ // SSE2 Shuffle control byte to shuffle vector // These correspond to shuffle immediate byte in shufps SSE2 instruction. -#define SHUFFLE_XXXX 0x00 -#define SHUFFLE_ZWYX 0xB1 -#define SHUFFLE_WWYY 0xF5 -#define SHUFFLE_ZZXX 0xA0 +#define SHUFFLE_XXXX 0x00 // 00 00 00 00 +#define SHUFFLE_XXWW 0x0F // 00 00 11 11 +#define SHUFFLE_XYZW 0x1B // 00 01 10 11 +#define SHUFFLE_YXYX 0x44 // 01 00 01 00 +#define SHUFFLE_YYZZ 0x5A // 01 01 10 10 +#define SHUFFLE_ZXXY 0x81 // 10 00 00 01 +#define SHUFFLE_ZWXY 0xB1 // 10 11 00 01 +#define SHUFFLE_WWYY 0xF5 // 11 11 01 01 +#define SHUFFLE_ZZXX 0xA0 // 10 10 00 00 #endif #endif // FEATURE_SIMD diff --git a/src/jit/simdcodegenxarch.cpp b/src/jit/simdcodegenxarch.cpp index 702f967..ec933fd 100644 --- a/src/jit/simdcodegenxarch.cpp +++ b/src/jit/simdcodegenxarch.cpp @@ -17,7 +17,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #ifndef LEGACY_BACKEND // This file is ONLY used for the RyuJIT backend that uses the linear scan register allocator. -#ifdef _TARGET_AMD64_ +#ifdef _TARGET_XARCH_ #include "emit.h" #include "codegen.h" #include "sideeffects.h" @@ -62,7 +62,7 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type // AVX supports broadcast instructions to populate YMM reg with a single float/double value from memory. // AVX2 supports broadcast instructions to populate YMM reg with a single value from memory or mm reg. // If we decide to use AVX2 only, we can remove this assert. - if ((compiler->opts.eeFlags & CORJIT_FLG_USE_AVX2) == 0) + if (!compiler->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_USE_AVX2)) { assert(baseType == TYP_FLOAT || baseType == TYP_DOUBLE); } @@ -205,12 +205,9 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type { result = INS_pmullw; } - else if (compiler->canUseAVX()) + else if ((baseType == TYP_INT) && (compiler->getSIMDInstructionSet() >= InstructionSet_SSE3_4)) { - if (baseType == TYP_INT) - { - result = INS_pmulld; - } + result = INS_pmulld; } break; @@ -300,7 +297,8 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type { result = INS_pcmpeqb; } - else if (compiler->canUseAVX() && (baseType == TYP_ULONG || baseType == TYP_LONG)) + else if ((baseType == TYP_ULONG || baseType == TYP_LONG) && + (compiler->getSIMDInstructionSet() >= InstructionSet_SSE3_4)) { result = INS_pcmpeqq; } @@ -359,7 +357,7 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type { result = INS_pcmpgtb; } - else if (compiler->canUseAVX() && (baseType == TYP_LONG)) + else if ((baseType == TYP_LONG) && (compiler->getSIMDInstructionSet() >= InstructionSet_SSE3_4)) { result = INS_pcmpgtq; } @@ -464,7 +462,8 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type // to target mm reg, zeroing out the upper bits if and only if specified. // // Arguments: -// type the type of value to be moved +// targetType the target type +// baseType the base type of value to be moved // targetReg the target reg // srcReg the src reg // moveType action to be performed on target upper bits @@ -475,10 +474,10 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type // Notes: // This is currently only supported for floating point types. // -void CodeGen::genSIMDScalarMove(var_types type, regNumber targetReg, regNumber srcReg, SIMDScalarMoveType moveType) +void CodeGen::genSIMDScalarMove( + var_types targetType, var_types baseType, regNumber targetReg, regNumber srcReg, SIMDScalarMoveType moveType) { - var_types targetType = compiler->getSIMDVectorType(); - assert(varTypeIsFloating(type)); + assert(varTypeIsFloating(baseType)); #ifdef FEATURE_AVX_SUPPORT if (compiler->getSIMDInstructionSet() == InstructionSet_AVX) { @@ -487,17 +486,17 @@ void CodeGen::genSIMDScalarMove(var_types type, regNumber targetReg, regNumber s case SMT_PreserveUpper: if (srcReg != targetReg) { - instruction ins = ins_Store(type); + instruction ins = ins_Store(baseType); if (getEmitter()->IsThreeOperandMoveAVXInstruction(ins)) { // In general, when we use a three-operands move instruction, we want to merge the src with // itself. This is an exception in that we actually want the "merge" behavior, so we must // specify it with all 3 operands. - inst_RV_RV_RV(ins, targetReg, targetReg, srcReg, emitTypeSize(targetType)); + inst_RV_RV_RV(ins, targetReg, targetReg, srcReg, emitTypeSize(baseType)); } else { - inst_RV_RV(ins, targetReg, srcReg, targetType, emitTypeSize(targetType)); + inst_RV_RV(ins, targetReg, srcReg, baseType, emitTypeSize(baseType)); } } break; @@ -516,9 +515,9 @@ void CodeGen::genSIMDScalarMove(var_types type, regNumber targetReg, regNumber s case SMT_ZeroInitUpper_SrcHasUpperZeros: if (srcReg != targetReg) { - instruction ins = ins_Copy(type); + instruction ins = ins_Copy(baseType); assert(!getEmitter()->IsThreeOperandMoveAVXInstruction(ins)); - inst_RV_RV(ins, targetReg, srcReg, targetType, emitTypeSize(targetType)); + inst_RV_RV(ins, targetReg, srcReg, baseType, emitTypeSize(baseType)); } break; @@ -536,7 +535,7 @@ void CodeGen::genSIMDScalarMove(var_types type, regNumber targetReg, regNumber s case SMT_PreserveUpper: if (srcReg != targetReg) { - inst_RV_RV(ins_Store(type), targetReg, srcReg, targetType, emitTypeSize(targetType)); + inst_RV_RV(ins_Store(baseType), targetReg, srcReg, baseType, emitTypeSize(baseType)); } break; @@ -545,22 +544,22 @@ void CodeGen::genSIMDScalarMove(var_types type, regNumber targetReg, regNumber s { // There is no guarantee that upper bits of op1Reg are zero. // We achieve this by using left logical shift 12-bytes and right logical shift 12 bytes. - instruction ins = getOpForSIMDIntrinsic(SIMDIntrinsicShiftLeftInternal, type); + instruction ins = getOpForSIMDIntrinsic(SIMDIntrinsicShiftLeftInternal, baseType); getEmitter()->emitIns_R_I(ins, EA_16BYTE, srcReg, 12); - ins = getOpForSIMDIntrinsic(SIMDIntrinsicShiftRightInternal, type); + ins = getOpForSIMDIntrinsic(SIMDIntrinsicShiftRightInternal, baseType); getEmitter()->emitIns_R_I(ins, EA_16BYTE, srcReg, 12); } else { genSIMDZero(targetType, TYP_FLOAT, targetReg); - inst_RV_RV(ins_Store(type), targetReg, srcReg); + inst_RV_RV(ins_Store(baseType), targetReg, srcReg); } break; case SMT_ZeroInitUpper_SrcHasUpperZeros: if (srcReg != targetReg) { - inst_RV_RV(ins_Copy(type), targetReg, srcReg, targetType, emitTypeSize(targetType)); + inst_RV_RV(ins_Copy(baseType), targetReg, srcReg, baseType, emitTypeSize(baseType)); } break; @@ -676,7 +675,7 @@ void CodeGen::genSIMDIntrinsicInit(GenTreeSIMD* simdNode) SIMDScalarMoveType moveType = op1->IsCnsFltOrDbl() || op1->isMemoryOp() ? SMT_ZeroInitUpper_SrcHasUpperZeros : SMT_ZeroInitUpper; - genSIMDScalarMove(TYP_FLOAT, targetReg, op1Reg, moveType); + genSIMDScalarMove(targetType, TYP_FLOAT, targetReg, op1Reg, moveType); if (size == 8) { @@ -786,7 +785,7 @@ void CodeGen::genSIMDIntrinsicInitN(GenTreeSIMD* simdNode) { getEmitter()->emitIns_R_I(insLeftShift, EA_16BYTE, vectorReg, baseTypeSize); } - genSIMDScalarMove(baseType, vectorReg, operandReg, SMT_PreserveUpper); + genSIMDScalarMove(targetType, baseType, vectorReg, operandReg, SMT_PreserveUpper); offset += baseTypeSize; } @@ -1033,11 +1032,10 @@ void CodeGen::genSIMDIntrinsicBinOp(GenTreeSIMD* simdNode) // void CodeGen::genSIMDIntrinsicRelOp(GenTreeSIMD* simdNode) { - GenTree* op1 = simdNode->gtGetOp1(); - GenTree* op2 = simdNode->gtGetOp2(); - var_types baseType = simdNode->gtSIMDBaseType; - regNumber targetReg = simdNode->gtRegNum; - assert(targetReg != REG_NA); + GenTree* op1 = simdNode->gtGetOp1(); + GenTree* op2 = simdNode->gtGetOp2(); + var_types baseType = simdNode->gtSIMDBaseType; + regNumber targetReg = simdNode->gtRegNum; var_types targetType = simdNode->TypeGet(); InstructionSet iset = compiler->getSIMDInstructionSet(); @@ -1051,8 +1049,16 @@ void CodeGen::genSIMDIntrinsicRelOp(GenTreeSIMD* simdNode) case SIMDIntrinsicEqual: case SIMDIntrinsicGreaterThan: { - // SSE2: vector<(u)long> relation op should be implemented in terms of TYP_INT comparison operations - assert(((iset == InstructionSet_AVX) || (baseType != TYP_LONG)) && (baseType != TYP_ULONG)); + assert(targetReg != REG_NA); + +#ifdef DEBUG + // SSE2: vector<(u)long> relational op should be implemented in terms of + // TYP_INT comparison operations + if (baseType == TYP_LONG || baseType == TYP_ULONG) + { + assert(iset >= InstructionSet_SSE3_4); + } +#endif // Greater-than: Floating point vectors use "<" with swapped operands if (simdNode->gtSIMDIntrinsicID == SIMDIntrinsicGreaterThan) @@ -1093,6 +1099,8 @@ void CodeGen::genSIMDIntrinsicRelOp(GenTreeSIMD* simdNode) case SIMDIntrinsicLessThan: case SIMDIntrinsicLessThanOrEqual: { + assert(targetReg != REG_NA); + // Int vectors use ">" and ">=" with swapped operands assert(varTypeIsFloating(baseType)); @@ -1115,17 +1123,6 @@ void CodeGen::genSIMDIntrinsicRelOp(GenTreeSIMD* simdNode) case SIMDIntrinsicOpEquality: case SIMDIntrinsicOpInEquality: { - assert(genIsValidIntReg(targetReg)); - - // We need two additional XMM register as scratch - assert(simdNode->gtRsvdRegs != RBM_NONE); - assert(genCountBits(simdNode->gtRsvdRegs) == 2); - - regMaskTP tmpRegsMask = simdNode->gtRsvdRegs; - regMaskTP tmpReg1Mask = genFindLowestBit(tmpRegsMask); - tmpRegsMask &= ~tmpReg1Mask; - regNumber tmpReg1 = genRegNumFromMask(tmpReg1Mask); - regNumber tmpReg2 = genRegNumFromMask(tmpRegsMask); var_types simdType = op1->TypeGet(); // TODO-1stClassStructs: Temporary to minimize asmDiffs if (simdType == TYP_DOUBLE) @@ -1140,96 +1137,111 @@ void CodeGen::genSIMDIntrinsicRelOp(GenTreeSIMD* simdNode) simdType = TYP_SIMD16; } - // tmpReg1 = (op1Reg == op2Reg) - // Call this value of tmpReg1 as 'compResult' for further reference below. - regNumber otherReg = op2Reg; - if (tmpReg1 != op2Reg) + // On SSE4/AVX, we can generate optimal code for (in)equality against zero using ptest. + if ((compiler->getSIMDInstructionSet() >= InstructionSet_SSE3_4) && op2->IsIntegralConstVector(0)) { - if (tmpReg1 != op1Reg) - { - inst_RV_RV(ins_Copy(simdType), tmpReg1, op1Reg, simdType, emitActualTypeSize(simdType)); - } + assert(op2->isContained()); + inst_RV_RV(INS_ptest, op1->gtRegNum, op1->gtRegNum, simdType, emitActualTypeSize(simdType)); } else { - otherReg = op1Reg; - } + // We need one additional SIMD register to store the result of the SIMD compare. + regNumber tmpReg1 = genRegNumFromMask(simdNode->gtRsvdRegs & RBM_ALLFLOAT); - // For all integer types we can use TYP_INT comparison. - unsigned ival = 0; - instruction ins = - getOpForSIMDIntrinsic(SIMDIntrinsicEqual, varTypeIsFloating(baseType) ? baseType : TYP_INT, &ival); + // tmpReg1 = (op1Reg == op2Reg) + // Call this value of tmpReg1 as 'compResult' for further reference below. + regNumber otherReg = op2Reg; + if (tmpReg1 != op2Reg) + { + if (tmpReg1 != op1Reg) + { + inst_RV_RV(ins_Copy(simdType), tmpReg1, op1Reg, simdType, emitActualTypeSize(simdType)); + } + } + else + { + otherReg = op1Reg; + } - if (varTypeIsFloating(baseType)) - { - getEmitter()->emitIns_R_R_I(ins, emitActualTypeSize(simdType), tmpReg1, otherReg, ival); - } - else - { - inst_RV_RV(ins, tmpReg1, otherReg, simdType, emitActualTypeSize(simdType)); + // For all integer types we can use TYP_INT comparison. + unsigned ival = 0; + instruction ins = + getOpForSIMDIntrinsic(SIMDIntrinsicEqual, varTypeIsFloating(baseType) ? baseType : TYP_INT, &ival); + + if (varTypeIsFloating(baseType)) + { + getEmitter()->emitIns_R_R_I(ins, emitActualTypeSize(simdType), tmpReg1, otherReg, ival); + } + else + { + inst_RV_RV(ins, tmpReg1, otherReg, simdType, emitActualTypeSize(simdType)); + } + + regNumber intReg; + if (targetReg == REG_NA) + { + // If we are not materializing result into a register, + // we would have reserved an int type internal register. + intReg = genRegNumFromMask(simdNode->gtRsvdRegs & RBM_ALLINT); + } + else + { + // We can use targetReg for setting flags. + intReg = targetReg; + + // Must have not reserved any int type internal registers. + assert(genCountBits(simdNode->gtRsvdRegs & RBM_ALLINT) == 0); + } + + inst_RV_RV(INS_pmovmskb, intReg, tmpReg1, simdType, emitActualTypeSize(simdType)); + // There's no pmovmskw/pmovmskd/pmovmskq but they're not needed anyway. Vector compare + // instructions produce "all ones"/"all zeroes" components and pmovmskb extracts a + // subset of each component's ones/zeroes. In the end we need to know if the result is + // "all ones" where the number of ones is given by the vector byte size, not by the + // vector component count. So, for AVX registers we need to compare to 0xFFFFFFFF and + // for SSE registers we need to compare to 0x0000FFFF. + // The SIMD12 case is handled specially, because we can't rely on the upper bytes being + // zero, so we must compare only the lower 3 floats (hence the byte mask of 0xFFF). + // Note that -1 is used instead of 0xFFFFFFFF, on x64 emit doesn't correctly recognize + // that 0xFFFFFFFF can be encoded in a single byte and emits the longer 3DFFFFFFFF + // encoding instead of 83F8FF. + ssize_t mask; + if ((simdNode->gtFlags & GTF_SIMD12_OP) != 0) + { + mask = 0x00000FFF; + getEmitter()->emitIns_R_I(INS_and, EA_4BYTE, intReg, mask); + } + else if (emitActualTypeSize(simdType) == 32) + { + mask = -1; + } + else + { + mask = 0x0000FFFF; + } + getEmitter()->emitIns_R_I(INS_cmp, EA_4BYTE, intReg, mask); } - // If we have 32 bytes, start by anding the two 16-byte halves to get a 16-byte result. - if (compiler->canUseAVX() && (simdType == TYP_SIMD32)) + if (targetReg != REG_NA) { - // Reduce tmpReg1 from 256-bits to 128-bits bitwise-Anding the lower and uppper 128-bits + // If we need to materialize result into a register, targetReg needs to + // be set to 1 on true and zero on false. + // Equality: + // cmp targetReg, 0xFFFFFFFF or 0xFFFF + // sete targetReg + // movzx targetReg, targetReg // - // Generated code sequence - // - vextractf128 tmpReg2, tmpReg1, 0x01 - // tmpReg2[128..255] <- 0 - // tmpReg2[0..127] <- tmpReg1[128..255] - // - vandps tmpReg1, tempReg2 - // This will zero-out upper portion of tmpReg1 and - // lower portion of tmpReg1 is and of upper and lower 128-bit comparison result. - getEmitter()->emitIns_R_R_I(INS_vextractf128, EA_32BYTE, tmpReg2, tmpReg1, 0x01); - inst_RV_RV(INS_andps, tmpReg1, tmpReg2, simdType, emitActualTypeSize(simdType)); - } - // Next, if we have more than 8 bytes, and the two 8-byte halves to get a 8-byte result. - if (simdType != TYP_SIMD8) - { - // tmpReg2 = Shuffle(tmpReg1, (1,0,3,2)) - // Note: vpshufd is a 128-bit only instruction. Therefore, explicitly pass EA_16BYTE - getEmitter()->emitIns_R_R_I(INS_pshufd, EA_16BYTE, tmpReg2, tmpReg1, 0x4E); - - // tmpReg1 = BitwiseAnd(tmpReg1, tmpReg2) + // InEquality: + // cmp targetReg, 0xFFFFFFFF or 0xFFFF + // setne targetReg + // movzx targetReg, targetReg // - // Note that what we have computed is as follows at this point: - // tmpReg1[0] = compResult[0] & compResult[2] - // tmpReg1[1] = compResult[1] & compResult[3] - inst_RV_RV(INS_andps, tmpReg1, tmpReg2, simdType, emitActualTypeSize(simdType)); + assert(simdNode->TypeGet() == TYP_INT); + inst_RV((simdNode->gtSIMDIntrinsicID == SIMDIntrinsicOpEquality) ? INS_sete : INS_setne, targetReg, + TYP_INT, EA_1BYTE); + // Set the higher bytes to 0 + inst_RV_RV(ins_Move_Extend(TYP_UBYTE, true), targetReg, targetReg, TYP_UBYTE, emitTypeSize(TYP_UBYTE)); } - // At this point, we have either reduced the result to 8 bytes: tmpReg1[0] and tmpReg1[1], - // OR we have a Vector2 (TYP_SIMD8) in tmpReg1, which has only those two fields. - - // tmpReg2 = Shuffle(tmpReg1, (0,0,0,1)) - // tmpReg2[0] = compResult[1] & compResult[3] - getEmitter()->emitIns_R_R_I(INS_pshufd, EA_16BYTE, tmpReg2, tmpReg1, 0x1); - - // tmpReg1 = BitwiseAnd(tmpReg1, tmpReg2) - // That is tmpReg1[0] = compResult[0] & compResult[1] & compResult[2] & compResult[3] - inst_RV_RV(INS_pand, tmpReg1, tmpReg2, simdType, emitActualTypeSize(simdType)); // ??? INS_andps?? - - // targetReg = lower 32-bits of tmpReg1 = compResult[0] & compResult[1] & compResult[2] & compResult[3] - // (Note that for mov_xmm2i, the int register is always in the reg2 position. - inst_RV_RV(INS_mov_xmm2i, tmpReg1, targetReg, TYP_INT); - - // Since we need to compute a bool result, targetReg needs to be set to 1 on true and zero on false. - // Equality: - // cmp targetReg, 0xFFFFFFFF - // sete targetReg - // movzx targetReg, targetReg - // - // InEquality: - // cmp targetReg, 0xFFFFFFFF - // setne targetReg - // movzx targetReg, targetReg - // - getEmitter()->emitIns_R_I(INS_cmp, EA_4BYTE, targetReg, 0xFFFFFFFF); - inst_RV((simdNode->gtSIMDIntrinsicID == SIMDIntrinsicOpEquality) ? INS_sete : INS_setne, targetReg, TYP_INT, - EA_1BYTE); - assert(simdNode->TypeGet() == TYP_INT); - // Set the higher bytes to 0 - inst_RV_RV(ins_Move_Extend(TYP_UBYTE, true), targetReg, targetReg, TYP_UBYTE, emitTypeSize(TYP_UBYTE)); } break; @@ -1267,45 +1279,68 @@ void CodeGen::genSIMDIntrinsicDotProduct(GenTreeSIMD* simdNode) regNumber targetReg = simdNode->gtRegNum; assert(targetReg != REG_NA); - // DotProduct is only supported on floating point types. var_types targetType = simdNode->TypeGet(); assert(targetType == baseType); - assert(varTypeIsFloating(baseType)); genConsumeOperands(simdNode); - regNumber op1Reg = op1->gtRegNum; - regNumber op2Reg = op2->gtRegNum; + regNumber op1Reg = op1->gtRegNum; + regNumber op2Reg = op2->gtRegNum; + regNumber tmpReg1 = REG_NA; + regNumber tmpReg2 = REG_NA; - regNumber tmpReg = REG_NA; - // For SSE, or AVX with 32-byte vectors, we need an additional Xmm register as scratch. - // However, it must be distinct from targetReg, so we request two from the register allocator. - // Note that if this is a TYP_SIMD16 or smaller on AVX, then we don't need a tmpReg. - if ((compiler->getSIMDInstructionSet() == InstructionSet_SSE2) || (simdEvalType == TYP_SIMD32)) + InstructionSet iset = compiler->getSIMDInstructionSet(); + + // Dot product intrinsic is supported only on float/double vectors + // and 32-byte int vectors on AVX. + // + // Float/Double Vectors: + // For SSE, or AVX with 32-byte vectors, we need one additional Xmm register + // different from targetReg as scratch. Note that if this is a TYP_SIMD16 or + // smaller on AVX, then we don't need a tmpReg. + // + // 32-byte integer vector on AVX: we need two additional Xmm registers + // different from targetReg as scratch. + // + // 16-byte integer vector on SSE4: we need one additional Xmm register + // different from targetReg as scratch. + if (varTypeIsFloating(baseType)) { - assert(simdNode->gtRsvdRegs != RBM_NONE); - assert(genCountBits(simdNode->gtRsvdRegs) == 2); + if ((compiler->getSIMDInstructionSet() == InstructionSet_SSE2) || (simdEvalType == TYP_SIMD32)) + { + assert(simdNode->gtRsvdRegs != RBM_NONE); + assert(genCountBits(simdNode->gtRsvdRegs) == 1); - regMaskTP tmpRegsMask = simdNode->gtRsvdRegs; - regMaskTP tmpReg1Mask = genFindLowestBit(tmpRegsMask); - tmpRegsMask &= ~tmpReg1Mask; - regNumber tmpReg1 = genRegNumFromMask(tmpReg1Mask); - regNumber tmpReg2 = genRegNumFromMask(tmpRegsMask); + tmpReg1 = genRegNumFromMask(simdNode->gtRsvdRegs); + assert(tmpReg1 != REG_NA); + assert(tmpReg1 != targetReg); + } + else + { + assert(simdNode->gtRsvdRegs == RBM_NONE); + } + } + else + { + assert(baseType == TYP_INT); + assert(iset >= InstructionSet_SSE3_4); - // Choose any register different from targetReg as tmpReg - if (tmpReg1 != targetReg) + if (iset == InstructionSet_SSE3_4) { - tmpReg = tmpReg1; + // Must have reserved 1 scratch register. + assert(genCountBits(simdNode->gtRsvdRegs) == 1); + tmpReg1 = genRegNumFromMask(simdNode->gtRsvdRegs); } else { - assert(targetReg != tmpReg2); - tmpReg = tmpReg2; + // Must have reserved 2 scratch registers. + assert(genCountBits(simdNode->gtRsvdRegs) == 2); + regMaskTP tmpRegMask = genFindLowestBit(simdNode->gtRsvdRegs); + tmpReg1 = genRegNumFromMask(tmpRegMask); + tmpReg2 = genRegNumFromMask(simdNode->gtRsvdRegs & ~tmpRegMask); } - assert(tmpReg != REG_NA); - assert(tmpReg != targetReg); } - if (compiler->getSIMDInstructionSet() == InstructionSet_SSE2) + if (iset == InstructionSet_SSE2) { // We avoid reg move if either op1Reg == targetReg or op2Reg == targetReg if (op1Reg == targetReg) @@ -1323,96 +1358,187 @@ void CodeGen::genSIMDIntrinsicDotProduct(GenTreeSIMD* simdNode) } // DotProduct(v1, v2) - // Here v0 = targetReg, v1 = op1Reg, v2 = op2Reg and tmp = tmpReg - if (baseType == TYP_FLOAT) + // Here v0 = targetReg, v1 = op1Reg, v2 = op2Reg and tmp = tmpReg1 + if ((simdNode->gtFlags & GTF_SIMD12_OP) != 0) + { + assert(baseType == TYP_FLOAT); + // v0 = v1 * v2 + // tmp = v0 // v0 = (3, 2, 1, 0) - each element is given by its + // // position + // tmp = shuffle(tmp, tmp, SHUFFLE_ZXXY) // tmp = (2, 0, 0, 1) - don't really care what's in upper + // // bits + // v0 = v0 + tmp // v0 = (3+2, 0+2, 1+0, 0+1) + // tmp = shuffle(tmp, tmp, SHUFFLE_XXWW) // tmp = ( 1, 1, 2, 2) + // v0 = v0 + tmp // v0 = (1+2+3, 0+1+2, 0+1+2, 0+1+2) + // + inst_RV_RV(INS_mulps, targetReg, op2Reg); + inst_RV_RV(INS_movaps, tmpReg1, targetReg); + inst_RV_RV_IV(INS_shufps, EA_16BYTE, tmpReg1, tmpReg1, SHUFFLE_ZXXY); + inst_RV_RV(INS_addps, targetReg, tmpReg1); + inst_RV_RV_IV(INS_shufps, EA_16BYTE, tmpReg1, tmpReg1, SHUFFLE_XXWW); + inst_RV_RV(INS_addps, targetReg, tmpReg1); + } + else if (baseType == TYP_FLOAT) { // v0 = v1 * v2 // tmp = v0 // v0 = (3, 2, 1, 0) - each element is given by its // // position - // tmp = shuffle(tmp, tmp, Shuffle(2,3,0,1)) // tmp = (2, 3, 0, 1) + // tmp = shuffle(tmp, tmp, SHUFFLE_ZWXY) // tmp = (2, 3, 0, 1) // v0 = v0 + tmp // v0 = (3+2, 2+3, 1+0, 0+1) // tmp = v0 - // tmp = shuffle(tmp, tmp, Shuffle(0,1,2,3)) // tmp = (0+1, 1+0, 2+3, 3+2) + // tmp = shuffle(tmp, tmp, SHUFFLE_XYZW) // tmp = (0+1, 1+0, 2+3, 3+2) // v0 = v0 + tmp // v0 = (0+1+2+3, 0+1+2+3, 0+1+2+3, 0+1+2+3) // // Essentially horizontal addtion of all elements. // // We could achieve the same using SSEv3 instruction // // HADDPS. // inst_RV_RV(INS_mulps, targetReg, op2Reg); - inst_RV_RV(INS_movaps, tmpReg, targetReg); - inst_RV_RV_IV(INS_shufps, EA_16BYTE, tmpReg, tmpReg, 0xb1); - inst_RV_RV(INS_addps, targetReg, tmpReg); - inst_RV_RV(INS_movaps, tmpReg, targetReg); - inst_RV_RV_IV(INS_shufps, EA_16BYTE, tmpReg, tmpReg, 0x1b); - inst_RV_RV(INS_addps, targetReg, tmpReg); + inst_RV_RV(INS_movaps, tmpReg1, targetReg); + inst_RV_RV_IV(INS_shufps, EA_16BYTE, tmpReg1, tmpReg1, SHUFFLE_ZWXY); + inst_RV_RV(INS_addps, targetReg, tmpReg1); + inst_RV_RV(INS_movaps, tmpReg1, targetReg); + inst_RV_RV_IV(INS_shufps, EA_16BYTE, tmpReg1, tmpReg1, SHUFFLE_XYZW); + inst_RV_RV(INS_addps, targetReg, tmpReg1); } - else if (baseType == TYP_DOUBLE) + else { + assert(baseType == TYP_DOUBLE); + // v0 = v1 * v2 // tmp = v0 // v0 = (1, 0) - each element is given by its position // tmp = shuffle(tmp, tmp, Shuffle(0,1)) // tmp = (0, 1) // v0 = v0 + tmp // v0 = (1+0, 0+1) inst_RV_RV(INS_mulpd, targetReg, op2Reg); - inst_RV_RV(INS_movaps, tmpReg, targetReg); - inst_RV_RV_IV(INS_shufpd, EA_16BYTE, tmpReg, tmpReg, 0x01); - inst_RV_RV(INS_addpd, targetReg, tmpReg); - } - else - { - unreached(); + inst_RV_RV(INS_movaps, tmpReg1, targetReg); + inst_RV_RV_IV(INS_shufpd, EA_16BYTE, tmpReg1, tmpReg1, 0x01); + inst_RV_RV(INS_addpd, targetReg, tmpReg1); } } else { - // We avoid reg move if either op1Reg == targetReg or op2Reg == targetReg. - // Note that this is a duplicate of the code above for SSE, but in the AVX case we can eventually - // use the 3-op form, so that we can avoid these copies. - // TODO-CQ: Add inst_RV_RV_RV_IV(). - if (op1Reg == targetReg) - { - // Best case - // nothing to do, we have registers in the right place - } - else if (op2Reg == targetReg) + assert(iset >= InstructionSet_SSE3_4); + + if (varTypeIsFloating(baseType)) { - op2Reg = op1Reg; + // We avoid reg move if either op1Reg == targetReg or op2Reg == targetReg. + // Note that this is a duplicate of the code above for SSE, but in the AVX case we can eventually + // use the 3-op form, so that we can avoid these copies. + // TODO-CQ: Add inst_RV_RV_RV_IV(). + if (op1Reg == targetReg) + { + // Best case + // nothing to do, we have registers in the right place + } + else if (op2Reg == targetReg) + { + op2Reg = op1Reg; + } + else + { + inst_RV_RV(ins_Copy(simdType), targetReg, op1Reg, simdEvalType, emitActualTypeSize(simdType)); + } + + emitAttr emitSize = emitActualTypeSize(simdEvalType); + if (baseType == TYP_FLOAT) + { + // dpps computes the dot product of the upper & lower halves of the 32-byte register. + // Notice that if this is a TYP_SIMD16 or smaller on AVX, then we don't need a tmpReg. + unsigned mask = ((simdNode->gtFlags & GTF_SIMD12_OP) != 0) ? 0x71 : 0xf1; + inst_RV_RV_IV(INS_dpps, emitSize, targetReg, op2Reg, mask); + // dpps computes the dot product of the upper & lower halves of the 32-byte register. + // Notice that if this is a TYP_SIMD16 or smaller on AVX, then we don't need a tmpReg. + // If this is TYP_SIMD32, we need to combine the lower & upper results. + if (simdEvalType == TYP_SIMD32) + { + getEmitter()->emitIns_R_R_I(INS_vextractf128, EA_32BYTE, tmpReg1, targetReg, 0x01); + inst_RV_RV(INS_addps, targetReg, tmpReg1, targetType, emitTypeSize(targetType)); + } + } + else if (baseType == TYP_DOUBLE) + { + if (simdEvalType == TYP_SIMD32) + { + // targetReg = targetReg * op2Reg + // targetReg = vhaddpd(targetReg, targetReg) ; horizontal sum of lower & upper halves + // tmpReg = vextractf128(targetReg, 1) ; Moves the upper sum into tempReg + // targetReg = targetReg + tmpReg1 + inst_RV_RV(INS_mulpd, targetReg, op2Reg, simdEvalType, emitActualTypeSize(simdType)); + inst_RV_RV(INS_haddpd, targetReg, targetReg, simdEvalType, emitActualTypeSize(simdType)); + getEmitter()->emitIns_R_R_I(INS_vextractf128, EA_32BYTE, tmpReg1, targetReg, 0x01); + inst_RV_RV(INS_addpd, targetReg, tmpReg1, targetType, emitTypeSize(targetType)); + } + else + { + // On AVX, we have no 16-byte vectors of double. Note that, if we did, we could use + // dppd directly. + assert(iset == InstructionSet_SSE3_4); + inst_RV_RV_IV(INS_dppd, emitSize, targetReg, op2Reg, 0x31); + } + } } else { - inst_RV_RV(ins_Copy(simdType), targetReg, op1Reg, simdEvalType, emitActualTypeSize(simdType)); - } + // Dot product of 32-byte int vector on SSE4/AVX. + assert(baseType == TYP_INT); + assert(simdEvalType == TYP_SIMD16 || simdEvalType == TYP_SIMD32); + +#ifdef DEBUG + // SSE4: We need 1 scratch register. + // AVX2: We need 2 scratch registers. + if (simdEvalType == TYP_SIMD16) + { + assert(tmpReg1 != REG_NA); + } + else + { + assert(tmpReg1 != REG_NA); + assert(tmpReg2 != REG_NA); + } +#endif + + // tmpReg1 = op1 * op2 + if (iset == InstructionSet_AVX) + { + // On AVX take advantage 3 operand form of pmulld + inst_RV_RV_RV(INS_pmulld, tmpReg1, op1Reg, op2Reg, emitTypeSize(simdEvalType)); + } + else + { + inst_RV_RV(ins_Copy(simdEvalType), tmpReg1, op1Reg, simdEvalType); + inst_RV_RV(INS_pmulld, tmpReg1, op2Reg, simdEvalType); + } - emitAttr emitSize = emitActualTypeSize(simdEvalType); - if (baseType == TYP_FLOAT) - { - // dpps computes the dot product of the upper & lower halves of the 32-byte register. - // Notice that if this is a TYP_SIMD16 or smaller on AVX, then we don't need a tmpReg. - inst_RV_RV_IV(INS_dpps, emitSize, targetReg, op2Reg, 0xf1); - // If this is TYP_SIMD32, we need to combine the lower & upper results. if (simdEvalType == TYP_SIMD32) { - getEmitter()->emitIns_R_R_I(INS_vextractf128, EA_32BYTE, tmpReg, targetReg, 0x01); - inst_RV_RV(INS_addps, targetReg, tmpReg, targetType, emitTypeSize(targetType)); + // tmpReg2[127..0] = Upper 128-bits of tmpReg1 + getEmitter()->emitIns_R_R_I(INS_vextractf128, EA_32BYTE, tmpReg2, tmpReg1, 0x01); + + // tmpReg1[127..0] = tmpReg1[127..0] + tmpReg2[127..0] + // This will compute + // tmpReg1[0] = op1[0]*op2[0] + op1[4]*op2[4] + // tmpReg1[1] = op1[1]*op2[1] + op1[5]*op2[5] + // tmpReg1[2] = op1[2]*op2[2] + op1[6]*op2[6] + // tmpReg1[4] = op1[4]*op2[4] + op1[7]*op2[7] + inst_RV_RV(INS_paddd, tmpReg1, tmpReg2, TYP_SIMD16, EA_16BYTE); } - } - else if (baseType == TYP_DOUBLE) - { - // On AVX, we have no 16-byte vectors of double. Note that, if we did, we could use - // dppd directly. - assert(simdType == TYP_SIMD32); - - // targetReg = targetReg * op2Reg - // targetReg = vhaddpd(targetReg, targetReg) ; horizontal sum of lower & upper halves - // tmpReg = vextractf128(targetReg, 1) ; Moves the upper sum into tempReg - // targetReg = targetReg + tmpReg - inst_RV_RV(INS_mulpd, targetReg, op2Reg, simdEvalType, emitActualTypeSize(simdType)); - inst_RV_RV(INS_haddpd, targetReg, targetReg, simdEvalType, emitActualTypeSize(simdType)); - getEmitter()->emitIns_R_R_I(INS_vextractf128, EA_32BYTE, tmpReg, targetReg, 0x01); - inst_RV_RV(INS_addpd, targetReg, tmpReg, targetType, emitTypeSize(targetType)); - } - else - { - unreached(); + + // This horizontal add will compute + // + // TYP_SIMD16: + // tmpReg1[0] = tmpReg1[2] = op1[0]*op2[0] + op1[1]*op2[1] + // tmpReg1[1] = tmpReg1[3] = op1[2]*op2[2] + op1[4]*op2[4] + // + // TYP_SIMD32: + // tmpReg1[0] = tmpReg1[2] = op1[0]*op2[0] + op1[4]*op2[4] + op1[1]*op2[1] + op1[5]*op2[5] + // tmpReg1[1] = tmpReg1[3] = op1[2]*op2[2] + op1[6]*op2[6] + op1[4]*op2[4] + op1[7]*op2[7] + inst_RV_RV(INS_phaddd, tmpReg1, tmpReg1, TYP_SIMD16, EA_16BYTE); + + // DotProduct(op1, op2) = tmpReg1[0] = tmpReg1[0] + tmpReg1[1] + inst_RV_RV(INS_phaddd, tmpReg1, tmpReg1, TYP_SIMD16, EA_16BYTE); + + // TargetReg = integer result from tmpReg1 + // (Note that for mov_xmm2i, the int register is always in the reg2 position) + inst_RV_RV(INS_mov_xmm2i, tmpReg1, targetReg, TYP_INT); } } @@ -1456,6 +1582,59 @@ void CodeGen::genSIMDIntrinsicGetItem(GenTreeSIMD* simdNode) genConsumeOperands(simdNode); regNumber srcReg = op1->gtRegNum; + // Optimize the case of op1 is in memory and trying to access ith element. + if (op1->isMemoryOp()) + { + assert(op1->isContained()); + + regNumber baseReg; + regNumber indexReg; + int offset = 0; + + if (op1->OperGet() == GT_LCL_FLD) + { + // There are three parts to the total offset here: + // {offset of local} + {offset of SIMD Vector field} + {offset of element within SIMD vector}. + bool isEBPbased; + unsigned varNum = op1->gtLclVarCommon.gtLclNum; + offset += compiler->lvaFrameAddress(varNum, &isEBPbased); + offset += op1->gtLclFld.gtLclOffs; + + baseReg = (isEBPbased) ? REG_EBP : REG_ESP; + } + else + { + // Require GT_IND addr to be not contained. + assert(op1->OperGet() == GT_IND); + + GenTree* addr = op1->AsIndir()->Addr(); + assert(!addr->isContained()); + baseReg = addr->gtRegNum; + } + + if (op2->isContainedIntOrIImmed()) + { + indexReg = REG_NA; + offset += (int)op2->AsIntConCommon()->IconValue() * genTypeSize(baseType); + } + else + { + indexReg = op2->gtRegNum; + assert(genIsValidIntReg(indexReg)); + } + + // Now, load the desired element. + getEmitter()->emitIns_R_ARX(ins_Move_Extend(baseType, false), // Load + emitTypeSize(baseType), // Of the vector baseType + targetReg, // To targetReg + baseReg, // Base Reg + indexReg, // Indexed + genTypeSize(baseType), // by the size of the baseType + offset); + genProduceReg(simdNode); + return; + } + // SSE2 doesn't have an instruction to implement this intrinsic if the index is not a constant. // For the non-constant case, we will use the SIMD temp location to store the vector, and // the load the desired element. @@ -1839,26 +2018,9 @@ void CodeGen::genLoadIndTypeSIMD12(GenTree* treeNode) // Need an addtional Xmm register to read upper 4 bytes, which is different from targetReg assert(treeNode->gtRsvdRegs != RBM_NONE); - assert(genCountBits(treeNode->gtRsvdRegs) == 2); - - regNumber tmpReg = REG_NA; - regMaskTP tmpRegsMask = treeNode->gtRsvdRegs; - regMaskTP tmpReg1Mask = genFindLowestBit(tmpRegsMask); - tmpRegsMask &= ~tmpReg1Mask; - regNumber tmpReg1 = genRegNumFromMask(tmpReg1Mask); - regNumber tmpReg2 = genRegNumFromMask(tmpRegsMask); + assert(genCountBits(treeNode->gtRsvdRegs) == 1); - // Choose any register different from targetReg as tmpReg - if (tmpReg1 != targetReg) - { - tmpReg = tmpReg1; - } - else - { - assert(targetReg != tmpReg2); - tmpReg = tmpReg2; - } - assert(tmpReg != REG_NA); + regNumber tmpReg = genRegNumFromMask(treeNode->gtRsvdRegs); assert(tmpReg != targetReg); // Load upper 4 bytes in tmpReg @@ -1868,7 +2030,7 @@ void CodeGen::genLoadIndTypeSIMD12(GenTree* treeNode) getEmitter()->emitIns_R_AR(ins_Load(TYP_DOUBLE), EA_8BYTE, targetReg, operandReg, 0); // combine upper 4 bytes and lower 8 bytes in targetReg - getEmitter()->emitIns_R_R_I(INS_shufps, emitActualTypeSize(TYP_SIMD16), targetReg, tmpReg, 0x44); + getEmitter()->emitIns_R_R_I(INS_shufps, emitActualTypeSize(TYP_SIMD16), targetReg, tmpReg, SHUFFLE_YXYX); genProduceReg(treeNode); } @@ -1912,9 +2074,9 @@ void CodeGen::genStoreLclFldTypeSIMD12(GenTree* treeNode) } //----------------------------------------------------------------------------- -// genLoadLclFldTypeSIMD12: load a TYP_SIMD12 (i.e. Vector3) type field. -// Since Vector3 is not a hardware supported write size, it is performed -// as two reads: 8 byte followed by 4-byte. +// genLoadLclTypeSIMD12: load a TYP_SIMD12 (i.e. Vector3) type field. +// Since Vector3 is not a hardware supported read size, it is performed +// as two reads: 4 byte followed by 8 byte. // // Arguments: // treeNode - tree node that is attempting to load TYP_SIMD12 field @@ -1922,37 +2084,26 @@ void CodeGen::genStoreLclFldTypeSIMD12(GenTree* treeNode) // Return Value: // None. // -void CodeGen::genLoadLclFldTypeSIMD12(GenTree* treeNode) +void CodeGen::genLoadLclTypeSIMD12(GenTree* treeNode) { - assert(treeNode->OperGet() == GT_LCL_FLD); + assert((treeNode->OperGet() == GT_LCL_FLD) || (treeNode->OperGet() == GT_LCL_VAR)); regNumber targetReg = treeNode->gtRegNum; - unsigned offs = treeNode->gtLclFld.gtLclOffs; + unsigned offs = 0; unsigned varNum = treeNode->gtLclVarCommon.gtLclNum; assert(varNum < compiler->lvaCount); - // Need an addtional Xmm register to read upper 4 bytes - assert(treeNode->gtRsvdRegs != RBM_NONE); - assert(genCountBits(treeNode->gtRsvdRegs) == 2); - - regNumber tmpReg = REG_NA; - regMaskTP tmpRegsMask = treeNode->gtRsvdRegs; - regMaskTP tmpReg1Mask = genFindLowestBit(tmpRegsMask); - tmpRegsMask &= ~tmpReg1Mask; - regNumber tmpReg1 = genRegNumFromMask(tmpReg1Mask); - regNumber tmpReg2 = genRegNumFromMask(tmpRegsMask); - - // Choose any register different from targetReg as tmpReg - if (tmpReg1 != targetReg) + if (treeNode->OperGet() == GT_LCL_FLD) { - tmpReg = tmpReg1; + offs = treeNode->gtLclFld.gtLclOffs; } - else - { - assert(targetReg != tmpReg2); - tmpReg = tmpReg2; - } - assert(tmpReg != REG_NA); + + // Need an additional Xmm register that is different from + // targetReg to read upper 4 bytes. + assert(treeNode->gtRsvdRegs != RBM_NONE); + assert(genCountBits(treeNode->gtRsvdRegs) == 1); + + regNumber tmpReg = genRegNumFromMask(treeNode->gtRsvdRegs); assert(tmpReg != targetReg); // Read upper 4 bytes to tmpReg @@ -1962,11 +2113,54 @@ void CodeGen::genLoadLclFldTypeSIMD12(GenTree* treeNode) getEmitter()->emitIns_R_S(ins_Move_Extend(TYP_DOUBLE, false), EA_8BYTE, targetReg, varNum, offs); // combine upper 4 bytes and lower 8 bytes in targetReg - getEmitter()->emitIns_R_R_I(INS_shufps, emitActualTypeSize(TYP_SIMD16), targetReg, tmpReg, 0x44); + getEmitter()->emitIns_R_R_I(INS_shufps, emitActualTypeSize(TYP_SIMD16), targetReg, tmpReg, SHUFFLE_YXYX); genProduceReg(treeNode); } +#ifdef _TARGET_X86_ + +//----------------------------------------------------------------------------- +// genPutArgStkSIMD12: store a TYP_SIMD12 (i.e. Vector3) type field. +// Since Vector3 is not a hardware supported write size, it is performed +// as two stores: 8 byte followed by 4-byte. +// +// Arguments: +// treeNode - tree node that is attempting to store TYP_SIMD12 field +// +// Return Value: +// None. +// +void CodeGen::genPutArgStkSIMD12(GenTree* treeNode) +{ + assert(treeNode->OperGet() == GT_PUTARG_STK); + + GenTreePtr op1 = treeNode->gtOp.gtOp1; + assert(!op1->isContained()); + regNumber operandReg = genConsumeReg(op1); + + // Need an addtional Xmm register to extract upper 4 bytes from data. + assert(treeNode->gtRsvdRegs != RBM_NONE); + assert(genCountBits(treeNode->gtRsvdRegs) == 1); + regNumber tmpReg = genRegNumFromMask(treeNode->gtRsvdRegs); + + // Subtract from ESP; create space for argument. + // TODO-CQ: use 'push' instead? + inst_RV_IV(INS_sub, REG_SPBASE, 12, EA_PTRSIZE); + genStackLevel += 12; + + // 8-byte write + getEmitter()->emitIns_AR_R(ins_Store(TYP_DOUBLE), EA_8BYTE, operandReg, REG_SPBASE, 0); + + // Extract upper 4-bytes from data + getEmitter()->emitIns_R_R_I(INS_pshufd, emitActualTypeSize(TYP_SIMD16), tmpReg, operandReg, 0x02); + + // 4-byte write + getEmitter()->emitIns_AR_R(ins_Store(TYP_FLOAT), EA_4BYTE, tmpReg, REG_SPBASE, 8); +} + +#endif // _TARGET_X86_ + //----------------------------------------------------------------------------- // genSIMDIntrinsicUpperSave: save the upper half of a TYP_SIMD32 vector to // the given register, if any, or to memory. @@ -2139,5 +2333,5 @@ void CodeGen::genSIMDIntrinsic(GenTreeSIMD* simdNode) } #endif // FEATURE_SIMD -#endif //_TARGET_AMD64_ +#endif //_TARGET_XARCH_ #endif // !LEGACY_BACKEND diff --git a/src/jit/simdintrinsiclist.h b/src/jit/simdintrinsiclist.h index a44fb9d..c81f7b4 100644 --- a/src/jit/simdintrinsiclist.h +++ b/src/jit/simdintrinsiclist.h @@ -20,7 +20,7 @@ e) TODO-Cleanup: when we plumb TYP_SIMD through front-end, replace TYP_STRUCT with TYP_SIMD. */ -#ifdef _TARGET_AMD64_ +#ifdef _TARGET_XARCH_ // Max number of parameters that we model in the table for SIMD intrinsic methods. #define SIMD_INTRINSIC_MAX_MODELED_PARAM_COUNT 3 @@ -111,7 +111,8 @@ SIMD_INTRINSIC("op_BitwiseOr", false, BitwiseOr, SIMD_INTRINSIC("op_ExclusiveOr", false, BitwiseXor, "^", TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_CHAR, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) // Dot Product -SIMD_INTRINSIC("Dot", false, DotProduct, "Dot", TYP_UNKNOWN, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_FLOAT, TYP_DOUBLE, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) +// Is supported only on Vector on AVX. +SIMD_INTRINSIC("Dot", false, DotProduct, "Dot", TYP_UNKNOWN, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) // Select SIMD_INTRINSIC("ConditionalSelect", false, Select, "Select", TYP_STRUCT, 3, {TYP_STRUCT, TYP_STRUCT, TYP_STRUCT}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_CHAR, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) @@ -137,9 +138,9 @@ SIMD_INTRINSIC("UpperRestore", false, UpperRestore, SIMD_INTRINSIC(nullptr, false, Invalid, "Invalid", TYP_UNDEF, 0, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) #undef SIMD_INTRINSIC -#else //_TARGET_AMD64_ +#else //_TARGET_XARCH_ #error SIMD intrinsics not defined for target arch -#endif //!_TARGET_AMD64_ +#endif //!_TARGET_XARCH_ #endif //FEATURE_SIMD // clang-format on diff --git a/src/jit/ssabuilder.cpp b/src/jit/ssabuilder.cpp index 2da69024..f0ee461 100644 --- a/src/jit/ssabuilder.cpp +++ b/src/jit/ssabuilder.cpp @@ -27,87 +27,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX namespace { /** - * Visits basic blocks in the depth first order and arranges them in the order of - * their DFS finish time. - * - * @param block The fgFirstBB or entry block. - * @param comp A pointer to compiler. - * @param visited In pointer initialized to false and of size at least fgMaxBBNum. - * @param count Out pointer for count of all nodes reachable by DFS. - * @param postOrder Out poitner to arrange the blocks and of size at least fgMaxBBNum. - */ -static void TopologicalSortHelper(BasicBlock* block, Compiler* comp, bool* visited, int* count, BasicBlock** postOrder) -{ - visited[block->bbNum] = true; - - ArrayStack blocks(comp); - ArrayStack iterators(comp); - ArrayStack ends(comp); - - // there are three stacks used here and all should be same height - // the first is for blocks - // the second is the iterator to keep track of what succ of the block we are looking at - // and the third is the end marker iterator - blocks.Push(block); - iterators.Push(block->GetAllSuccs(comp).begin()); - ends.Push(block->GetAllSuccs(comp).end()); - - while (blocks.Height() > 0) - { - block = blocks.Top(); - -#ifdef DEBUG - if (comp->verboseSsa) - { - printf("[SsaBuilder::TopologicalSortHelper] Visiting BB%02u: ", block->bbNum); - printf("["); - unsigned numSucc = block->NumSucc(comp); - for (unsigned i = 0; i < numSucc; ++i) - { - printf("BB%02u, ", block->GetSucc(i, comp)->bbNum); - } - EHSuccessorIter end = block->GetEHSuccs(comp).end(); - for (EHSuccessorIter ehsi = block->GetEHSuccs(comp).begin(); ehsi != end; ++ehsi) - { - printf("[EH]BB%02u, ", (*ehsi)->bbNum); - } - printf("]\n"); - } -#endif - - if (iterators.TopRef() != ends.TopRef()) - { - // if the block on TOS still has unreached successors, visit them - AllSuccessorIter& iter = iterators.TopRef(); - BasicBlock* succ = *iter; - ++iter; - // push the child - - if (!visited[succ->bbNum]) - { - blocks.Push(succ); - iterators.Push(succ->GetAllSuccs(comp).begin()); - ends.Push(succ->GetAllSuccs(comp).end()); - visited[succ->bbNum] = true; - } - } - else - { - // all successors have been visited - blocks.Pop(); - iterators.Pop(); - ends.Pop(); - - postOrder[*count] = block; - block->bbPostOrderNum = *count; - *count += 1; - - DBG_SSA_JITDUMP("postOrder[%d] = [%p] and BB%02u\n", *count, dspPtr(block), block->bbNum); - } - } -} - -/** * Method that finds a common IDom parent, much like least common ancestor. * * @param finger1 A basic block that might share IDom ancestor with finger2. @@ -184,6 +103,8 @@ void Compiler::fgResetForSsa() { lvaTable[i].lvPerSsaData.Reset(); } + lvHeapPerSsaData.Reset(); + m_heapSsaMap = nullptr; for (BasicBlock* blk = fgFirstBB; blk != nullptr; blk = blk->bbNext) { // Eliminate phis. @@ -197,6 +118,32 @@ void Compiler::fgResetForSsa() blk->bbTreeList->gtPrev = last; } } + + // Clear post-order numbers and SSA numbers; SSA construction will overwrite these, + // but only for reachable code, so clear them to avoid analysis getting confused + // by stale annotations in unreachable code. + blk->bbPostOrderNum = 0; + for (GenTreeStmt* stmt = blk->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) + { + for (GenTreePtr tree = stmt->gtStmt.gtStmtList; tree != nullptr; tree = tree->gtNext) + { + if (tree->IsLocal()) + { + tree->gtLclVarCommon.SetSsaNum(SsaConfig::RESERVED_SSA_NUM); + continue; + } + + Compiler::IndirectAssignmentAnnotation* pIndirAssign = nullptr; + if ((tree->OperGet() != GT_ASG) || !GetIndirAssignMap()->Lookup(tree, &pIndirAssign) || + (pIndirAssign == nullptr)) + { + continue; + } + + pIndirAssign->m_defSsaNum = SsaConfig::RESERVED_SSA_NUM; + pIndirAssign->m_useSsaNum = SsaConfig::RESERVED_SSA_NUM; + } + } } } @@ -222,27 +169,97 @@ SsaBuilder::SsaBuilder(Compiler* pCompiler, IAllocator* pIAllocator) { } -/** - * Topologically sort the graph and return the number of nodes visited. - * - * @param postOrder The array in which the arranged basic blocks have to be returned. - * @param count The size of the postOrder array. - * - * @return The number of nodes visited while performing DFS on the graph. - */ +//------------------------------------------------------------------------ +// TopologicalSort: Topologically sort the graph and return the number of nodes visited. +// +// Arguments: +// postOrder - The array in which the arranged basic blocks have to be returned. +// count - The size of the postOrder array. +// +// Return Value: +// The number of nodes visited while performing DFS on the graph. + int SsaBuilder::TopologicalSort(BasicBlock** postOrder, int count) { - // Allocate and initialize visited flags. - bool* visited = (bool*)alloca(count * sizeof(bool)); - memset(visited, 0, count * sizeof(bool)); + Compiler* comp = m_pCompiler; + + BitVecTraits traits(comp->fgBBNumMax + 1, comp); + BitVec BITVEC_INIT_NOCOPY(visited, BitVecOps::MakeEmpty(&traits)); // Display basic blocks. - DBEXEC(VERBOSE, m_pCompiler->fgDispBasicBlocks()); - DBEXEC(VERBOSE, m_pCompiler->fgDispHandlerTab()); + DBEXEC(VERBOSE, comp->fgDispBasicBlocks()); + DBEXEC(VERBOSE, comp->fgDispHandlerTab()); - // Call the recursive helper. - int postIndex = 0; - TopologicalSortHelper(m_pCompiler->fgFirstBB, m_pCompiler, visited, &postIndex, postOrder); + // Compute order. + int postIndex = 0; + BasicBlock* block = comp->fgFirstBB; + BitVecOps::AddElemD(&traits, visited, block->bbNum); + + ArrayStack blocks(comp); + ArrayStack iterators(comp); + ArrayStack ends(comp); + + // there are three stacks used here and all should be same height + // the first is for blocks + // the second is the iterator to keep track of what succ of the block we are looking at + // and the third is the end marker iterator + blocks.Push(block); + iterators.Push(block->GetAllSuccs(comp).begin()); + ends.Push(block->GetAllSuccs(comp).end()); + + while (blocks.Height() > 0) + { + block = blocks.Top(); + +#ifdef DEBUG + if (comp->verboseSsa) + { + printf("[SsaBuilder::TopologicalSort] Visiting BB%02u: ", block->bbNum); + printf("["); + unsigned numSucc = block->NumSucc(comp); + for (unsigned i = 0; i < numSucc; ++i) + { + printf("BB%02u, ", block->GetSucc(i, comp)->bbNum); + } + EHSuccessorIter end = block->GetEHSuccs(comp).end(); + for (EHSuccessorIter ehsi = block->GetEHSuccs(comp).begin(); ehsi != end; ++ehsi) + { + printf("[EH]BB%02u, ", (*ehsi)->bbNum); + } + printf("]\n"); + } +#endif + + if (iterators.TopRef() != ends.TopRef()) + { + // if the block on TOS still has unreached successors, visit them + AllSuccessorIter& iter = iterators.TopRef(); + BasicBlock* succ = *iter; + ++iter; + + // push the children + if (!BitVecOps::IsMember(&traits, visited, succ->bbNum)) + { + blocks.Push(succ); + iterators.Push(succ->GetAllSuccs(comp).begin()); + ends.Push(succ->GetAllSuccs(comp).end()); + BitVecOps::AddElemD(&traits, visited, succ->bbNum); + } + } + else + { + // all successors have been visited + blocks.Pop(); + iterators.Pop(); + ends.Pop(); + + postOrder[postIndex] = block; + block->bbPostOrderNum = postIndex; + postIndex += 1; + + DBG_SSA_JITDUMP("postOrder[%d] = [%p] and BB%02u\n", postIndex, dspPtr(block), block->bbNum); + } + } // In the absence of EH (because catch/finally have no preds), this should be valid. // assert(postIndex == (count - 1)); @@ -1686,7 +1703,17 @@ void SsaBuilder::Build() JITDUMP("[SsaBuilder] Max block count is %d.\n", blockCount); // Allocate the postOrder array for the graph. - BasicBlock** postOrder = (BasicBlock**)alloca(blockCount * sizeof(BasicBlock*)); + + BasicBlock** postOrder; + + if (blockCount > DEFAULT_MIN_OPTS_BB_COUNT) + { + postOrder = new (m_pCompiler->getAllocator()) BasicBlock*[blockCount]; + } + else + { + postOrder = (BasicBlock**)alloca(blockCount * sizeof(BasicBlock*)); + } // Topologically sort the graph. int count = TopologicalSort(postOrder, blockCount); diff --git a/src/jit/stackfp.cpp b/src/jit/stackfp.cpp index f975822..43c4630 100644 --- a/src/jit/stackfp.cpp +++ b/src/jit/stackfp.cpp @@ -1406,8 +1406,6 @@ void CodeGen::genCodeForTreeStackFP_Asg(GenTreePtr tree) assert(!varDsc->lvTracked || compiler->opts.MinOpts() || !(op1NonCom->gtFlags & GTF_VAR_DEATH)); #endif -#ifdef DEBUGGING_SUPPORT - /* For non-debuggable code, every definition of a lcl-var has * to be checked to see if we need to open a new scope for it. */ @@ -1416,7 +1414,6 @@ void CodeGen::genCodeForTreeStackFP_Asg(GenTreePtr tree) { siCheckVarScope(op1NonCom->gtLclVarCommon.gtLclNum, op1NonCom->gtLclVar.gtLclILoffs); } -#endif } assert(op2); @@ -2827,7 +2824,7 @@ void CodeGen::genCondJumpFltStackFP(GenTreePtr cond, BasicBlock* jumpTrue, Basic BasicBlock* CodeGen::genTransitionBlockStackFP(FlatFPStateX87* pState, BasicBlock* pFrom, BasicBlock* pTarget) { // Fast paths where a transition block is not necessary - if (pTarget->bbFPStateX87 && FlatFPStateX87::AreEqual(pState, pTarget->bbFPStateX87) || pState->IsEmpty()) + if ((pTarget->bbFPStateX87 && FlatFPStateX87::AreEqual(pState, pTarget->bbFPStateX87)) || pState->IsEmpty()) { return pTarget; } @@ -4143,8 +4140,26 @@ void Compiler::raEnregisterVarsPostPassStackFP() { raSetRegLclBirthDeath(tree, lastlife, false); } + + // Model implicit use (& hence last use) of frame list root at pinvokes. + if (tree->gtOper == GT_CALL) + { + GenTreeCall* call = tree->AsCall(); + if (call->IsUnmanaged() && !opts.ShouldUsePInvokeHelpers()) + { + LclVarDsc* frameVarDsc = &lvaTable[info.compLvFrameListRoot]; + + if (frameVarDsc->lvTracked && ((call->gtCallMoreFlags & GTF_CALL_M_FRAME_VAR_DEATH) != 0)) + { + // Frame var dies here + unsigned varIndex = frameVarDsc->lvVarIndex; + VarSetOps::RemoveElemD(this, lastlife, varIndex); + } + } + } } } + assert(VarSetOps::Equal(this, lastlife, block->bbLiveOut)); } compCurBB = NULL; diff --git a/src/jit/standalone/CMakeLists.txt b/src/jit/standalone/CMakeLists.txt index 2e63170..f20d379 100644 --- a/src/jit/standalone/CMakeLists.txt +++ b/src/jit/standalone/CMakeLists.txt @@ -1,22 +1,27 @@ project(ryujit) + add_definitions(-DFEATURE_NO_HOST) add_definitions(-DSELF_NO_HOST) add_definitions(-DFEATURE_READYTORUN_COMPILER) remove_definitions(-DFEATURE_MERGE_JIT_AND_ENGINE) -if(CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_ARM) +if(CLR_CMAKE_TARGET_ARCH_ARM) add_definitions(-DLEGACY_BACKEND) endif() -add_library_clr(${JIT_BASE_NAME} +if(WIN32) + add_definitions(-DFX_VER_INTERNALNAME_STR=clrjit.dll) +endif(WIN32) + +add_library_clr(clrjit SHARED ${SHARED_LIB_SOURCES} ) -add_dependencies(${JIT_BASE_NAME} jit_exports) +add_dependencies(clrjit jit_exports) -set_property(TARGET ${JIT_BASE_NAME} APPEND_STRING PROPERTY LINK_FLAGS ${JIT_EXPORTS_LINKER_OPTION}) -set_property(TARGET ${JIT_BASE_NAME} APPEND_STRING PROPERTY LINK_DEPENDS ${JIT_EXPORTS_FILE}) +set_property(TARGET clrjit APPEND_STRING PROPERTY LINK_FLAGS ${JIT_EXPORTS_LINKER_OPTION}) +set_property(TARGET clrjit APPEND_STRING PROPERTY LINK_DEPENDS ${JIT_EXPORTS_FILE}) set(RYUJIT_LINK_LIBRARIES utilcodestaticnohost @@ -47,12 +52,12 @@ else() ) endif(CLR_CMAKE_PLATFORM_UNIX) -target_link_libraries(${JIT_BASE_NAME} +target_link_libraries(clrjit ${RYUJIT_LINK_LIBRARIES} ) # add the install targets -install_clr(${JIT_BASE_NAME}) +install_clr(clrjit) # Enable profile guided optimization -add_pgo(${JIT_BASE_NAME}) +add_pgo(clrjit) diff --git a/src/jit/target.h b/src/jit/target.h index fa0b18a..a726525 100644 --- a/src/jit/target.h +++ b/src/jit/target.h @@ -6,11 +6,6 @@ #ifndef _TARGET_H_ #define _TARGET_H_ -// Inform includers that we're in a context in which a target has been set. -#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) || defined(_TARGET_ARM_) -#define _TARGET_SET_ -#endif - // If the UNIX_AMD64_ABI is defined make sure that _TARGET_AMD64_ is also defined. #if defined(UNIX_AMD64_ABI) #if !defined(_TARGET_AMD64_) @@ -365,6 +360,9 @@ typedef unsigned short regPairNoSmall; // arm: need 12 bits #endif // !LEGACY_BACKEND +#ifdef FEATURE_SIMD + #define ALIGN_SIMD_TYPES 1 // whether SIMD type locals are to be aligned +#endif // FEATURE_SIMD #define FEATURE_WRITE_BARRIER 1 // Generate the proper WriteBarrier calls for GC #define FEATURE_FIXED_OUT_ARGS 0 // X86 uses push instructions to pass args @@ -585,7 +583,14 @@ typedef unsigned short regPairNoSmall; // arm: need 12 bits #define RBM_CALLEE_TRASH_NOGC RBM_EDX #endif // NOGC_WRITE_BARRIERS - // IL stub's secret parameter (CORJIT_FLG_PUBLISH_SECRET_PARAM) + // GenericPInvokeCalliHelper unmanaged target parameter + #define REG_PINVOKE_TARGET_PARAM REG_EAX + #define RBM_PINVOKE_TARGET_PARAM RBM_EAX + + // GenericPInvokeCalliHelper cookie parameter + #define REG_PINVOKE_COOKIE_PARAM REG_STK + + // IL stub's secret parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM) #define REG_SECRET_STUB_PARAM REG_EAX #define RBM_SECRET_STUB_PARAM RBM_EAX @@ -594,6 +599,10 @@ typedef unsigned short regPairNoSmall; // arm: need 12 bits #define RBM_VIRTUAL_STUB_PARAM RBM_EAX #define PREDICT_REG_VIRTUAL_STUB_PARAM PREDICT_REG_EAX + // VSD target address register + #define REG_VIRTUAL_STUB_TARGET REG_EAX + #define RBM_VIRTUAL_STUB_TARGET RBM_EAX + // Registers used by PInvoke frame setup #define REG_PINVOKE_FRAME REG_EDI // EDI is p/invoke "Frame" pointer argument to CORINFO_HELP_INIT_PINVOKE_FRAME helper #define RBM_PINVOKE_FRAME RBM_EDI @@ -670,6 +679,12 @@ typedef unsigned short regPairNoSmall; // arm: need 12 bits #define RBM_ARG_REGS (RBM_ARG_0|RBM_ARG_1) + // The registers trashed by profiler enter/leave/tailcall hook + // See vm\i386\asmhelpers.asm for more details. + #define RBM_PROFILER_ENTER_TRASH RBM_NONE + #define RBM_PROFILER_LEAVE_TRASH RBM_NONE + #define RBM_PROFILER_TAILCALL_TRASH (RBM_ALLINT & ~RBM_ARG_REGS) + // What sort of reloc do we use for [disp32] address mode #define IMAGE_REL_BASED_DISP32 IMAGE_REL_BASED_HIGHLOW @@ -968,7 +983,7 @@ typedef unsigned short regPairNoSmall; // arm: need 12 bits #define RBM_PINVOKE_TARGET_PARAM RBM_R10 #define PREDICT_REG_PINVOKE_TARGET_PARAM PREDICT_REG_R10 - // IL stub's secret MethodDesc parameter (CORJIT_FLG_PUBLISH_SECRET_PARAM) + // IL stub's secret MethodDesc parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM) #define REG_SECRET_STUB_PARAM REG_R10 #define RBM_SECRET_STUB_PARAM RBM_R10 @@ -1111,9 +1126,10 @@ typedef unsigned short regPairNoSmall; // arm: need 12 bits #endif // !UNIX_AMD64_ABI // The registers trashed by profiler enter/leave/tailcall hook - // See vm\amd64\amshelpers.asm for more details. - #define RBM_PROFILER_ENTER_TRASH RBM_CALLEE_TRASH - #define RBM_PROFILER_LEAVE_TRASH (RBM_CALLEE_TRASH & ~(RBM_FLOATRET | RBM_INTRET)) + // See vm\amd64\asmhelpers.asm for more details. + #define RBM_PROFILER_ENTER_TRASH RBM_CALLEE_TRASH + #define RBM_PROFILER_LEAVE_TRASH (RBM_CALLEE_TRASH & ~(RBM_FLOATRET | RBM_INTRET)) + #define RBM_PROFILER_TAILCALL_TRASH RBM_PROFILER_LEAVE_TRASH // The registers trashed by the CORINFO_HELP_STOP_FOR_GC helper. #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING @@ -1339,7 +1355,7 @@ typedef unsigned short regPairNoSmall; // arm: need 12 bits #define RBM_PINVOKE_TARGET_PARAM RBM_R12 #define PREDICT_REG_PINVOKE_TARGET_PARAM PREDICT_REG_R12 - // IL stub's secret MethodDesc parameter (CORJIT_FLG_PUBLISH_SECRET_PARAM) + // IL stub's secret MethodDesc parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM) #define REG_SECRET_STUB_PARAM REG_R12 #define RBM_SECRET_STUB_PARAM RBM_R12 @@ -1447,6 +1463,9 @@ typedef unsigned short regPairNoSmall; // arm: need 12 bits #define JMP_DIST_SMALL_MAX_NEG (-2048) #define JMP_DIST_SMALL_MAX_POS (+2046) + #define CALL_DIST_MAX_NEG (-16777216) + #define CALL_DIST_MAX_POS (+16777214) + #define JCC_DIST_SMALL_MAX_NEG (-256) #define JCC_DIST_SMALL_MAX_POS (+254) @@ -1617,7 +1636,7 @@ typedef unsigned short regPairNoSmall; // arm: need 12 bits #define RBM_PINVOKE_TARGET_PARAM RBM_R14 #define PREDICT_REG_PINVOKE_TARGET_PARAM PREDICT_REG_R14 - // IL stub's secret MethodDesc parameter (CORJIT_FLG_PUBLISH_SECRET_PARAM) + // IL stub's secret MethodDesc parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM) #define REG_SECRET_STUB_PARAM REG_R12 #define RBM_SECRET_STUB_PARAM RBM_R12 @@ -2277,6 +2296,9 @@ inline regNumber regNextOfType(regNumber reg, var_types type) inline bool isRegPairType(int /* s/b "var_types" */ type) { +#if !CPU_LONG_USES_REGPAIR + return false; +#else #ifdef _TARGET_64BIT_ return false; #elif CPU_HAS_FP_SUPPORT @@ -2284,6 +2306,7 @@ inline bool isRegPairType(int /* s/b "var_types" */ type) #else return type == TYP_LONG || type == TYP_DOUBLE; #endif +#endif // CPU_LONG_USES_REGPAIR } inline bool isFloatRegType(int /* s/b "var_types" */ type) diff --git a/src/jit/tinyarray.h b/src/jit/tinyarray.h index 17d7e04..bee59bd 100644 --- a/src/jit/tinyarray.h +++ b/src/jit/tinyarray.h @@ -71,7 +71,7 @@ public: // only use this for clearing it void operator=(void* rhs) { - assert(rhs == NULL); + assert(rhs == nullptr); data = 0; } }; diff --git a/src/jit/unwindamd64.cpp b/src/jit/unwindamd64.cpp index 89abdff..14eba8c 100644 --- a/src/jit/unwindamd64.cpp +++ b/src/jit/unwindamd64.cpp @@ -481,6 +481,13 @@ void Compiler::unwindSetFrameRegWindows(regNumber reg, unsigned offset) } #ifdef UNIX_AMD64_ABI +//------------------------------------------------------------------------ +// Compiler::unwindSetFrameRegCFI: Record a cfi info for a frame register set. +// +// Arguments: +// reg - The register being set as the frame register. +// offset - The offset from the current stack pointer that the frame pointer will point at. +// void Compiler::unwindSetFrameRegCFI(regNumber reg, unsigned offset) { assert(compGeneratingProlog); @@ -492,7 +499,13 @@ void Compiler::unwindSetFrameRegCFI(regNumber reg, unsigned offset) createCfiCode(func, cbProlog, CFI_DEF_CFA_REGISTER, mapRegNumToDwarfReg(reg)); if (offset != 0) { - createCfiCode(func, cbProlog, CFI_ADJUST_CFA_OFFSET, DWARF_REG_ILLEGAL, offset); + // before: cfa = rsp + old_cfa_offset; + // rbp = rsp + offset; + // after: cfa should be based on rbp, but points to the old address: + // rsp + old_cfa_offset == rbp + old_cfa_offset + adjust; + // adjust = -offset; + int adjust = -(int)offset; + createCfiCode(func, cbProlog, CFI_ADJUST_CFA_OFFSET, DWARF_REG_ILLEGAL, adjust); } } #endif // UNIX_AMD64_ABI diff --git a/src/jit/utils.cpp b/src/jit/utils.cpp index 9934416..3a45039 100644 --- a/src/jit/utils.cpp +++ b/src/jit/utils.cpp @@ -657,7 +657,7 @@ void dumpILRange(const BYTE* const codeAddr, unsigned codeSize) // in bytes for (IL_OFFSET offs = 0; offs < codeSize;) { char prefix[100]; - sprintf(prefix, "IL_%04x ", offs); + sprintf_s(prefix, _countof(prefix), "IL_%04x ", offs); unsigned codeBytesDumped = dumpSingleInstr(codeAddr, offs, prefix); offs += codeBytesDumped; } @@ -665,11 +665,9 @@ void dumpILRange(const BYTE* const codeAddr, unsigned codeSize) // in bytes /***************************************************************************** * - * Display a variable set (which may be a 32-bit or 64-bit number); only - * one or two of these can be used at once. + * Display a variable set. */ - -const char* genES2str(EXPSET_TP set) +const char* genES2str(BitVecTraits* traits, EXPSET_TP set) { const int bufSize = 17; static char num1[bufSize]; @@ -682,11 +680,7 @@ const char* genES2str(EXPSET_TP set) nump = (nump == num1) ? num2 : num1; -#if EXPSET_SZ == 32 - sprintf_s(temp, bufSize, "%08X", set); -#else - sprintf_s(temp, bufSize, "%08X%08X", (int)(set >> 32), (int)set); -#endif + sprintf_s(temp, bufSize, "%s", BitVecOps::ToString(traits, set)); return temp; } @@ -876,7 +870,7 @@ void ConfigMethodRange::InitRanges(const wchar_t* rangeStr, unsigned capacity) #endif // defined(DEBUG) || defined(INLINE_DATA) -#if CALL_ARG_STATS || COUNT_BASIC_BLOCKS || COUNT_LOOPS || EMITTER_STATS || MEASURE_NODE_SIZE +#if CALL_ARG_STATS || COUNT_BASIC_BLOCKS || COUNT_LOOPS || EMITTER_STATS || MEASURE_NODE_SIZE || MEASURE_MEM_ALLOC /***************************************************************************** * Histogram class. @@ -896,7 +890,10 @@ Histogram::Histogram(IAllocator* allocator, const unsigned* const sizeTable) Histogram::~Histogram() { - m_allocator->Free(m_counts); + if (m_counts != nullptr) + { + m_allocator->Free(m_counts); + } } // We need to lazy allocate the histogram data so static `Histogram` variables don't try to @@ -1414,6 +1411,9 @@ void HelperCallProperties::init() case CORINFO_HELP_GETGENERICS_GCSTATIC_BASE: case CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE: case CORINFO_HELP_READYTORUN_STATIC_BASE: +#if COR_JIT_EE_VERSION > 460 + case CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE: +#endif // COR_JIT_EE_VERSION > 460 // These may invoke static class constructors // These can throw InvalidProgram exception if the class can not be constructed diff --git a/src/jit/valuenum.cpp b/src/jit/valuenum.cpp index 5bc96ed..f7cc0c9 100644 --- a/src/jit/valuenum.cpp +++ b/src/jit/valuenum.cpp @@ -76,7 +76,6 @@ ValueNumStore::ValueNumStore(Compiler* comp, IAllocator* alloc) , m_VNFunc2Map(nullptr) , m_VNFunc3Map(nullptr) , m_VNFunc4Map(nullptr) - , m_uPtrToLocNotAFieldCount(1) { // We have no current allocation chunks. for (unsigned i = 0; i < TYP_COUNT; i++) @@ -604,6 +603,7 @@ ValueNumStore::Chunk::Chunk( switch (attribs) { case CEA_None: + case CEA_NotAField: break; // Nothing to do. case CEA_Const: switch (typ) @@ -911,6 +911,7 @@ class Object* ValueNumStore::s_specialRefConsts[] = {nullptr, nullptr, nullptr}; ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func) { assert(VNFuncArity(func) == 0); + assert(func != VNF_NotAField); ValueNum res; @@ -1029,9 +1030,9 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V { if (typ != TYP_BYREF) // We don't want/need to optimize a zero byref { - genTreeOps oper = genTreeOps(func); - ValueNum ZeroVN, OneVN; // We may need to create one of these in the switch below. - switch (oper) + ValueNum resultVN = NoVN; + ValueNum ZeroVN, OneVN; // We may need to create one of these in the switch below. + switch (genTreeOps(func)) { case GT_ADD: // This identity does not apply for floating point (when x == -0.0) @@ -1041,11 +1042,11 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V ZeroVN = VNZeroForType(typ); if (arg0VN == ZeroVN) { - return arg1VN; + resultVN = arg1VN; } else if (arg1VN == ZeroVN) { - return arg0VN; + resultVN = arg0VN; } } break; @@ -1055,7 +1056,7 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V ZeroVN = VNZeroForType(typ); if (arg1VN == ZeroVN) { - return arg0VN; + resultVN = arg0VN; } break; @@ -1066,11 +1067,11 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V { if (arg0VN == OneVN) { - return arg1VN; + resultVN = arg1VN; } else if (arg1VN == OneVN) { - return arg0VN; + resultVN = arg0VN; } } @@ -1080,11 +1081,11 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V ZeroVN = VNZeroForType(typ); if (arg0VN == ZeroVN) { - return ZeroVN; + resultVN = ZeroVN; } else if (arg1VN == ZeroVN) { - return ZeroVN; + resultVN = ZeroVN; } } break; @@ -1097,7 +1098,7 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V { if (arg1VN == OneVN) { - return arg0VN; + resultVN = arg0VN; } } break; @@ -1109,11 +1110,11 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V ZeroVN = VNZeroForType(typ); if (arg0VN == ZeroVN) { - return arg1VN; + resultVN = arg1VN; } else if (arg1VN == ZeroVN) { - return arg0VN; + resultVN = arg0VN; } break; @@ -1122,11 +1123,11 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V ZeroVN = VNZeroForType(typ); if (arg0VN == ZeroVN) { - return ZeroVN; + resultVN = ZeroVN; } else if (arg1VN == ZeroVN) { - return ZeroVN; + resultVN = ZeroVN; } break; @@ -1142,7 +1143,7 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V ZeroVN = VNZeroForType(typ); if (arg1VN == ZeroVN) { - return arg0VN; + resultVN = arg0VN; } break; @@ -1150,30 +1151,35 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V // (x == x) => true (unless x is NaN) if (!varTypeIsFloating(TypeOfVN(arg0VN)) && (arg0VN != NoVN) && (arg0VN == arg1VN)) { - return VNOneForType(typ); + resultVN = VNOneForType(typ); } if ((arg0VN == VNForNull() && IsKnownNonNull(arg1VN)) || (arg1VN == VNForNull() && IsKnownNonNull(arg0VN))) { - return VNZeroForType(typ); + resultVN = VNZeroForType(typ); } break; case GT_NE: // (x != x) => false (unless x is NaN) if (!varTypeIsFloating(TypeOfVN(arg0VN)) && (arg0VN != NoVN) && (arg0VN == arg1VN)) { - return VNZeroForType(typ); + resultVN = VNZeroForType(typ); } if ((arg0VN == VNForNull() && IsKnownNonNull(arg1VN)) || (arg1VN == VNForNull() && IsKnownNonNull(arg0VN))) { - return VNOneForType(typ); + resultVN = VNOneForType(typ); } break; default: break; } + + if ((resultVN != NoVN) && (TypeOfVN(resultVN) == typ)) + { + return resultVN; + } } } else // must be a VNF_ function @@ -2072,10 +2078,11 @@ bool ValueNumStore::CanEvalForConstantArgs(VNFunc vnf) case GT_MKREFANY: // We can't evaluate these. case GT_RETFILT: case GT_LIST: + case GT_FIELD_LIST: case GT_ARR_LENGTH: return false; case GT_MULHI: - // should be rare, not worth the complexity and risk of getting it wrong + assert(false && "Unexpected GT_MULHI node encountered before lowering"); return false; default: return true; @@ -2545,6 +2552,11 @@ ValueNumPair ValueNumStore::VNPairApplySelectors(ValueNumPair map, FieldSeqNode* return ValueNumPair(liberalVN, conservVN); } +bool ValueNumStore::IsVNNotAField(ValueNum vn) +{ + return m_chunks.GetNoExpand(GetChunkNum(vn))->m_attribs == CEA_NotAField; +} + ValueNum ValueNumStore::VNForFieldSeq(FieldSeqNode* fieldSeq) { if (fieldSeq == nullptr) @@ -2553,7 +2565,11 @@ ValueNum ValueNumStore::VNForFieldSeq(FieldSeqNode* fieldSeq) } else if (fieldSeq == FieldSeqStore::NotAField()) { - return VNForNotAField(); + // We always allocate a new, unique VN in this call. + Chunk* c = GetAllocChunk(TYP_REF, CEA_NotAField); + unsigned offsetWithinChunk = c->AllocVN(); + ValueNum result = c->m_baseVN + offsetWithinChunk; + return result; } else { @@ -2585,22 +2601,22 @@ FieldSeqNode* ValueNumStore::FieldSeqVNToFieldSeq(ValueNum vn) { return nullptr; } - else if (vn == VNForNotAField()) + + assert(IsVNFunc(vn)); + + VNFuncApp funcApp; + GetVNFunc(vn, &funcApp); + if (funcApp.m_func == VNF_NotAField) { return FieldSeqStore::NotAField(); } - else - { - assert(IsVNFunc(vn)); - VNFuncApp funcApp; - GetVNFunc(vn, &funcApp); - assert(funcApp.m_func == VNF_FieldSeq); - ssize_t fieldHndVal = ConstantValue(funcApp.m_args[0]); - FieldSeqNode* head = - m_pComp->GetFieldSeqStore()->CreateSingleton(reinterpret_cast(fieldHndVal)); - FieldSeqNode* tail = FieldSeqVNToFieldSeq(funcApp.m_args[1]); - return m_pComp->GetFieldSeqStore()->Append(head, tail); - } + + assert(funcApp.m_func == VNF_FieldSeq); + const ssize_t fieldHndVal = ConstantValue(funcApp.m_args[0]); + FieldSeqNode* head = + m_pComp->GetFieldSeqStore()->CreateSingleton(reinterpret_cast(fieldHndVal)); + FieldSeqNode* tail = FieldSeqVNToFieldSeq(funcApp.m_args[1]); + return m_pComp->GetFieldSeqStore()->Append(head, tail); } ValueNum ValueNumStore::FieldSeqVNAppend(ValueNum fsVN1, ValueNum fsVN2) @@ -2609,40 +2625,31 @@ ValueNum ValueNumStore::FieldSeqVNAppend(ValueNum fsVN1, ValueNum fsVN2) { return fsVN2; } - else if (fsVN1 == VNForNotAField() || fsVN2 == VNForNotAField()) - { - return VNForNotAField(); - } - else - { - assert(IsVNFunc(fsVN1)); - VNFuncApp funcApp1; - GetVNFunc(fsVN1, &funcApp1); - assert(funcApp1.m_func == VNF_FieldSeq); - ValueNum tailRes = FieldSeqVNAppend(funcApp1.m_args[1], fsVN2); - ValueNum fieldSeqVN = VNForFunc(TYP_REF, VNF_FieldSeq, funcApp1.m_args[0], tailRes); -#ifdef DEBUG - if (m_pComp->verbose) - { - printf(" fieldSeq " STR_VN "%x is ", fieldSeqVN); - vnDump(m_pComp, fieldSeqVN); - printf("\n"); - } -#endif + assert(IsVNFunc(fsVN1)); - return fieldSeqVN; + VNFuncApp funcApp1; + GetVNFunc(fsVN1, &funcApp1); + + if ((funcApp1.m_func == VNF_NotAField) || IsVNNotAField(fsVN2)) + { + return VNForFieldSeq(FieldSeqStore::NotAField()); } -} -ValueNum ValueNumStore::VNForPtrToLoc(var_types typ, ValueNum lclVarVN, ValueNum fieldSeqVN) -{ - if (fieldSeqVN == VNForNotAField()) + assert(funcApp1.m_func == VNF_FieldSeq); + ValueNum tailRes = FieldSeqVNAppend(funcApp1.m_args[1], fsVN2); + ValueNum fieldSeqVN = VNForFunc(TYP_REF, VNF_FieldSeq, funcApp1.m_args[0], tailRes); + +#ifdef DEBUG + if (m_pComp->verbose) { - // To distinguish two different not a fields, append a unique value. - return VNForFunc(typ, VNF_PtrToLoc, lclVarVN, fieldSeqVN, VNForIntCon(++m_uPtrToLocNotAFieldCount)); + printf(" fieldSeq " STR_VN "%x is ", fieldSeqVN); + vnDump(m_pComp, fieldSeqVN); + printf("\n"); } - return VNForFunc(typ, VNF_PtrToLoc, lclVarVN, fieldSeqVN, VNForIntCon(0)); +#endif + + return fieldSeqVN; } ValueNum ValueNumStore::ExtendPtrVN(GenTreePtr opA, GenTreePtr opB) @@ -2650,7 +2657,7 @@ ValueNum ValueNumStore::ExtendPtrVN(GenTreePtr opA, GenTreePtr opB) if (opB->OperGet() == GT_CNS_INT) { FieldSeqNode* fldSeq = opB->gtIntCon.gtFieldSeq; - if ((fldSeq != nullptr) && (fldSeq != FieldSeqStore::NotAField())) + if (fldSeq != nullptr) { return ExtendPtrVN(opA, opB->gtIntCon.gtFieldSeq); } @@ -2660,8 +2667,9 @@ ValueNum ValueNumStore::ExtendPtrVN(GenTreePtr opA, GenTreePtr opB) ValueNum ValueNumStore::ExtendPtrVN(GenTreePtr opA, FieldSeqNode* fldSeq) { + assert(fldSeq != nullptr); + ValueNum res = NoVN; - assert(fldSeq != FieldSeqStore::NotAField()); ValueNum opAvnWx = opA->gtVNPair.GetLiberal(); assert(VNIsValid(opAvnWx)); @@ -2684,7 +2692,7 @@ ValueNum ValueNumStore::ExtendPtrVN(GenTreePtr opA, FieldSeqNode* fldSeq) assert(GetVNFunc(VNNormVal(opA->GetVN(VNK_Conservative)), &consFuncApp) && consFuncApp.Equals(funcApp)); #endif ValueNum fldSeqVN = VNForFieldSeq(fldSeq); - res = VNForPtrToLoc(TYP_BYREF, funcApp.m_args[0], FieldSeqVNAppend(funcApp.m_args[1], fldSeqVN)); + res = VNForFunc(TYP_BYREF, VNF_PtrToLoc, funcApp.m_args[0], FieldSeqVNAppend(funcApp.m_args[1], fldSeqVN)); } else if (funcApp.m_func == VNF_PtrToStatic) { @@ -2917,6 +2925,11 @@ ValueNum Compiler::fgValueNumberArrIndexVal(GenTreePtr tree, var_types ValueNumStore::TypeOfVN(ValueNum vn) { + if (vn == NoVN) + { + return TYP_UNDEF; + } + Chunk* c = m_chunks.GetNoExpand(GetChunkNum(vn)); return c->m_typ; } @@ -2936,6 +2949,11 @@ var_types ValueNumStore::TypeOfVN(ValueNum vn) BasicBlock::loopNumber ValueNumStore::LoopOfVN(ValueNum vn) { + if (vn == NoVN) + { + return MAX_LOOP_NUM; + } + Chunk* c = m_chunks.GetNoExpand(GetChunkNum(vn)); return c->m_loopNum; } @@ -3388,6 +3406,7 @@ bool ValueNumStore::IsVNFunc(ValueNum vn) Chunk* c = m_chunks.GetNoExpand(GetChunkNum(vn)); switch (c->m_attribs) { + case CEA_NotAField: case CEA_Func0: case CEA_Func1: case CEA_Func2: @@ -3401,6 +3420,11 @@ bool ValueNumStore::IsVNFunc(ValueNum vn) bool ValueNumStore::GetVNFunc(ValueNum vn, VNFuncApp* funcApp) { + if (vn == NoVN) + { + return false; + } + Chunk* c = m_chunks.GetNoExpand(GetChunkNum(vn)); unsigned offset = ChunkOffset(vn); assert(offset < c->m_numUsed); @@ -3415,8 +3439,8 @@ bool ValueNumStore::GetVNFunc(ValueNum vn, VNFuncApp* funcApp) funcApp->m_args[1] = farg4->m_arg1; funcApp->m_args[2] = farg4->m_arg2; funcApp->m_args[3] = farg4->m_arg3; - } return true; + } case CEA_Func3: { VNDefFunc3Arg* farg3 = &reinterpret_cast(c->m_defs)[offset]; @@ -3425,8 +3449,8 @@ bool ValueNumStore::GetVNFunc(ValueNum vn, VNFuncApp* funcApp) funcApp->m_args[0] = farg3->m_arg0; funcApp->m_args[1] = farg3->m_arg1; funcApp->m_args[2] = farg3->m_arg2; - } return true; + } case CEA_Func2: { VNDefFunc2Arg* farg2 = &reinterpret_cast(c->m_defs)[offset]; @@ -3434,23 +3458,29 @@ bool ValueNumStore::GetVNFunc(ValueNum vn, VNFuncApp* funcApp) funcApp->m_arity = 2; funcApp->m_args[0] = farg2->m_arg0; funcApp->m_args[1] = farg2->m_arg1; - } return true; + } case CEA_Func1: { VNDefFunc1Arg* farg1 = &reinterpret_cast(c->m_defs)[offset]; funcApp->m_func = farg1->m_func; funcApp->m_arity = 1; funcApp->m_args[0] = farg1->m_arg0; - } return true; + } case CEA_Func0: { VNDefFunc0Arg* farg0 = &reinterpret_cast(c->m_defs)[offset]; funcApp->m_func = farg0->m_func; funcApp->m_arity = 0; + return true; } + case CEA_NotAField: + { + funcApp->m_func = VNF_NotAField; + funcApp->m_arity = 0; return true; + } default: return false; } @@ -3751,8 +3781,9 @@ static genTreeOps genTreeOpsIllegalAsVNFunc[] = {GT_IND, // When we do heap memo // These need special semantics: GT_COMMA, // == second argument (but with exception(s) from first). GT_ADDR, GT_ARR_BOUNDS_CHECK, - GT_OBJ, // May reference heap memory. - GT_BLK, // May reference heap memory. + GT_OBJ, // May reference heap memory. + GT_BLK, // May reference heap memory. + GT_INIT_VAL, // Not strictly a pass-through. // These control-flow operations need no values. GT_JTRUE, GT_RETURN, GT_SWITCH, GT_RETFILT, GT_CKFINITE}; @@ -3842,10 +3873,9 @@ static const char* s_reservedNameArr[] = { "$VN.No", // -1 NoVN "$VN.Null", // 0 VNForNull() "$VN.ZeroMap", // 1 VNForZeroMap() - "$VN.NotAField", // 2 VNForNotAField() - "$VN.ReadOnlyHeap", // 3 VNForROH() - "$VN.Void", // 4 VNForVoid() - "$VN.EmptyExcSet" // 5 VNForEmptyExcSet() + "$VN.ReadOnlyHeap", // 2 VNForROH() + "$VN.Void", // 3 VNForVoid() + "$VN.EmptyExcSet" // 4 VNForEmptyExcSet() }; // Returns the string name of "vn" when it is a reserved value number, nullptr otherwise @@ -4804,8 +4834,16 @@ void Compiler::fgValueNumberTreeConst(GenTreePtr tree) tree->gtVNPair.SetBoth(vnStore->VNForDoubleCon(tree->gtDblCon.gtDconVal)); break; case TYP_REF: - // Null is the only constant. (Except maybe for String?) - tree->gtVNPair.SetBoth(ValueNumStore::VNForNull()); + if (tree->gtIntConCommon.IconValue() == 0) + { + tree->gtVNPair.SetBoth(ValueNumStore::VNForNull()); + } + else + { + assert(tree->gtFlags == GTF_ICON_STR_HDL); // Constant object can be only frozen string. + tree->gtVNPair.SetBoth( + vnStore->VNForHandle(ssize_t(tree->gtIntConCommon.IconValue()), tree->GetIconHandleFlag())); + } break; case TYP_BYREF: @@ -4903,9 +4941,6 @@ void Compiler::fgValueNumberBlockAssignment(GenTreePtr tree, bool evalAsgLhsInd) } #endif // DEBUG } - // Initblock's are of type void. Give them the void "value" -- they may occur in argument lists, which we - // want to be able to give VN's to. - tree->gtVNPair.SetBoth(ValueNumStore::VNForVoid()); } else { @@ -4913,6 +4948,9 @@ void Compiler::fgValueNumberBlockAssignment(GenTreePtr tree, bool evalAsgLhsInd) // TODO-CQ: Why not be complete, and get this case right? fgMutateHeap(tree DEBUGARG("INITBLK - non local")); } + // Initblock's are of type void. Give them the void "value" -- they may occur in argument lists, which we + // want to be able to give VN's to. + tree->gtVNPair.SetBoth(ValueNumStore::VNForVoid()); } else { @@ -4953,17 +4991,21 @@ void Compiler::fgValueNumberBlockAssignment(GenTreePtr tree, bool evalAsgLhsInd) assert(lhs->OperGet() == GT_IND); lhsAddr = lhs->gtOp.gtOp1; } + // For addr-of-local expressions, lib/cons shouldn't matter. assert(lhsAddr->gtVNPair.BothEqual()); ValueNum lhsAddrVN = lhsAddr->GetVN(VNK_Liberal); // Unpack the PtrToLoc value number of the address. assert(vnStore->IsVNFunc(lhsAddrVN)); + VNFuncApp lhsAddrFuncApp; vnStore->GetVNFunc(lhsAddrVN, &lhsAddrFuncApp); + assert(lhsAddrFuncApp.m_func == VNF_PtrToLoc); assert(vnStore->IsVNConstant(lhsAddrFuncApp.m_args[0]) && vnStore->ConstantValue(lhsAddrFuncApp.m_args[0]) == lhsLclNum); + lhsFldSeq = vnStore->FieldSeqVNToFieldSeq(lhsAddrFuncApp.m_args[1]); } @@ -5598,10 +5640,9 @@ void Compiler::fgValueNumberTree(GenTreePtr tree, bool evalAsgLhsInd) // (we looked in a side table above for its "def" identity). Look up that value. ValueNumPair oldLhsVNPair = lvaTable[lclFld->GetLclNum()].GetPerSsaData(lclFld->GetSsaNum())->m_vnPair; - newLhsVNPair = - vnStore->VNPairApplySelectorsAssign(oldLhsVNPair, lclFld->gtFieldSeq, - rhsVNPair, // Pre-value. - lvaGetActualType(lclFld->gtLclNum), compCurBB); + newLhsVNPair = vnStore->VNPairApplySelectorsAssign(oldLhsVNPair, lclFld->gtFieldSeq, + rhsVNPair, // Pre-value. + lclFld->TypeGet(), compCurBB); } } lvaTable[lclFld->GetLclNum()].GetPerSsaData(lclDefSsaNum)->m_vnPair = newLhsVNPair; @@ -6034,8 +6075,9 @@ void Compiler::fgValueNumberTree(GenTreePtr tree, bool evalAsgLhsInd) if (newVN == ValueNumStore::NoVN) { assert(arg->gtLclVarCommon.GetSsaNum() != ValueNumStore::NoVN); - newVN = vnStore->VNForPtrToLoc(TYP_BYREF, vnStore->VNForIntCon(arg->gtLclVarCommon.GetLclNum()), - vnStore->VNForFieldSeq(fieldSeq)); + newVN = vnStore->VNForFunc(TYP_BYREF, VNF_PtrToLoc, + vnStore->VNForIntCon(arg->gtLclVarCommon.GetLclNum()), + vnStore->VNForFieldSeq(fieldSeq)); } tree->gtVNPair.SetBoth(newVN); } @@ -6240,17 +6282,12 @@ void Compiler::fgValueNumberTree(GenTreePtr tree, bool evalAsgLhsInd) } tree->gtVNPair = vnStore->VNPWithExc(tree->gtVNPair, addrXvnp); } - else if (!varTypeIsStruct(tree) && vnStore->GetVNFunc(addrNvnp.GetLiberal(), &funcApp) && - (funcApp.m_func == VNF_PtrToArrElem)) + else if (vnStore->GetVNFunc(addrNvnp.GetLiberal(), &funcApp) && (funcApp.m_func == VNF_PtrToArrElem)) { - // TODO-1stClassStructs: The above condition need not exclude struct types, but it is - // excluded for now to minimize diffs. fgValueNumberArrIndexVal(tree, &funcApp, addrXvnp.GetLiberal()); } - else if (!varTypeIsStruct(tree) && addr->IsFieldAddr(this, &obj, &staticOffset, &fldSeq2)) + else if (addr->IsFieldAddr(this, &obj, &staticOffset, &fldSeq2)) { - // TODO-1stClassStructs: The above condition need not exclude struct types, but it is - // excluded for now to minimize diffs. if (fldSeq2 == FieldSeqStore::NotAField()) { tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, tree->TypeGet())); @@ -6522,6 +6559,9 @@ void Compiler::fgValueNumberTree(GenTreePtr tree, bool evalAsgLhsInd) case GT_JTRUE: case GT_LIST: +#ifndef LEGACY_BACKEND + case GT_FIELD_LIST: +#endif // !LEGACY_BACKEND // These nodes never need to have a ValueNumber tree->gtVNPair.SetBoth(ValueNumStore::NoVN); break; @@ -6667,7 +6707,7 @@ void Compiler::fgValueNumberCastTree(GenTreePtr tree) bool srcIsUnsigned = ((tree->gtFlags & GTF_UNSIGNED) != 0); bool hasOverflowCheck = tree->gtOverflowEx(); - assert(genActualType(castToType) == tree->TypeGet()); // Insure that the resultType is correct + assert(genActualType(castToType) == genActualType(tree->TypeGet())); // Insure that the resultType is correct tree->gtVNPair = vnStore->VNPairForCast(srcVNPair, castToType, castFromType, srcIsUnsigned, hasOverflowCheck); } @@ -6816,6 +6856,7 @@ void Compiler::fgValueNumberHelperCallFunc(GenTreeCall* call, VNFunc vnf, ValueN break; case VNF_ReadyToRunStaticBase: + case VNF_ReadyToRunGenericStaticBase: case VNF_ReadyToRunIsInstanceOf: case VNF_ReadyToRunCastClass: { @@ -7061,11 +7102,11 @@ VNFunc Compiler::fgValueNumberHelperMethVNFunc(CorInfoHelpFunc helpFunc) vnf = VNFunc(GT_MOD); break; case CORINFO_HELP_ULDIV: - vnf = VNFunc(GT_DIV); - break; // Is this the right thing? + vnf = VNFunc(GT_UDIV); + break; case CORINFO_HELP_ULMOD: - vnf = VNFunc(GT_MOD); - break; // Is this the right thing? + vnf = VNFunc(GT_UMOD); + break; case CORINFO_HELP_LNG2DBL: vnf = VNF_Lng2Dbl; @@ -7155,6 +7196,11 @@ VNFunc Compiler::fgValueNumberHelperMethVNFunc(CorInfoHelpFunc helpFunc) case CORINFO_HELP_READYTORUN_STATIC_BASE: vnf = VNF_ReadyToRunStaticBase; break; +#if COR_JIT_EE_VERSION > 460 + case CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE: + vnf = VNF_ReadyToRunGenericStaticBase; + break; +#endif // COR_JIT_EE_VERSION > 460 case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS: vnf = VNF_GetsharedGcstaticBaseDynamicclass; break; diff --git a/src/jit/valuenum.h b/src/jit/valuenum.h index 17dacfb..c8a57ff 100644 --- a/src/jit/valuenum.h +++ b/src/jit/valuenum.h @@ -297,13 +297,6 @@ public: return ValueNum(SRC_ZeroMap); } - // The value number for the special "NotAField" field sequence. - static ValueNum VNForNotAField() - { - // We reserve Chunk 0 for "special" VNs. Let SRC_NotAField (== 2) be the "not a field seq". - return ValueNum(SRC_NotAField); - } - // The ROH map is the map for the "read-only heap". We assume that this is never mutated, and always // has the same value number. static ValueNum VNForROH() @@ -450,7 +443,7 @@ public: // Get a new, unique value number for an expression that we're not equating to some function, // which is the value of a tree in the given block. - ValueNum VNForExpr(BasicBlock *block, var_types typ = TYP_UNKNOWN); + ValueNum VNForExpr(BasicBlock* block, var_types typ = TYP_UNKNOWN); // This controls extra tracing of the "evaluation" of "VNF_MapSelect" functions. #define FEATURE_VN_TRACE_APPLY_SELECTORS 1 @@ -485,13 +478,11 @@ public: ValueNumPair VNPairApplySelectors(ValueNumPair map, FieldSeqNode* fieldSeq, var_types indType); - ValueNumPair VNPairApplySelectorsAssign(ValueNumPair map, - FieldSeqNode* fieldSeq, - ValueNumPair rhs, - var_types indType, - BasicBlock* block) + ValueNumPair VNPairApplySelectorsAssign( + ValueNumPair map, FieldSeqNode* fieldSeq, ValueNumPair rhs, var_types indType, BasicBlock* block) { - return ValueNumPair(VNApplySelectorsAssign(VNK_Liberal, map.GetLiberal(), fieldSeq, rhs.GetLiberal(), indType, block), + return ValueNumPair(VNApplySelectorsAssign(VNK_Liberal, map.GetLiberal(), fieldSeq, rhs.GetLiberal(), indType, + block), VNApplySelectorsAssign(VNK_Conservative, map.GetConservative(), fieldSeq, rhs.GetConservative(), indType, block)); } @@ -506,6 +497,9 @@ public: bool srcIsUnsigned = false, bool hasOverflowCheck = false); + // Returns true iff the VN represents an application of VNF_NotAField. + bool IsVNNotAField(ValueNum vn); + // PtrToLoc values need to express a field sequence as one of their arguments. VN for null represents // empty sequence, otherwise, "FieldSeq(VN(FieldHandle), restOfSeq)". ValueNum VNForFieldSeq(FieldSeqNode* fieldSeq); @@ -518,12 +512,6 @@ public: // concatenation "fsVN1 || fsVN2". ValueNum FieldSeqVNAppend(ValueNum fsVN1, ValueNum fsVN2); - // Requires "lclVarVN" be a value number for a GT_LCL_VAR pointer tree. - // Requires "fieldSeqVN" be a field sequence value number. - // Requires "typ" to be a TYP_REF/TYP_BYREF used for VNF_PtrToLoc. - // When "fieldSeqVN" is VNForNotAField, a unique VN is generated using m_uPtrToLocNotAFieldCount. - ValueNum VNForPtrToLoc(var_types typ, ValueNum lclVarVN, ValueNum fieldSeqVN); - // If "opA" has a PtrToLoc, PtrToArrElem, or PtrToStatic application as its value numbers, and "opB" is an integer // with a "fieldSeq", returns the VN for the pointer form extended with the field sequence; or else NoVN. ValueNum ExtendPtrVN(GenTreePtr opA, GenTreePtr opB); @@ -853,14 +841,15 @@ private: DECLARE_TYPED_ENUM(ChunkExtraAttribs, BYTE) { - CEA_None, // No extra attributes. - CEA_Const, // This chunk contains constant values. - CEA_Handle, // This chunk contains handle constants. - CEA_Func0, // Represents functions of arity 0. - CEA_Func1, // ...arity 1. - CEA_Func2, // ...arity 2. - CEA_Func3, // ...arity 3. - CEA_Func4, // ...arity 4. + CEA_None, // No extra attributes. + CEA_Const, // This chunk contains constant values. + CEA_Handle, // This chunk contains handle constants. + CEA_NotAField, // This chunk contains "not a field" values. + CEA_Func0, // Represents functions of arity 0. + CEA_Func1, // ...arity 1. + CEA_Func2, // ...arity 2. + CEA_Func3, // ...arity 3. + CEA_Func4, // ...arity 4. CEA_Count } END_DECLARE_TYPED_ENUM(ChunkExtraAttribs, BYTE); @@ -883,9 +872,14 @@ private: ChunkExtraAttribs m_attribs; BasicBlock::loopNumber m_loopNum; - // Initialize a chunk, starting at "*baseVN", for the given "typ", "attribs", and "loopNum" (using "alloc" for allocations). + // Initialize a chunk, starting at "*baseVN", for the given "typ", "attribs", and "loopNum" (using "alloc" for + // allocations). // (Increments "*baseVN" by ChunkSize.) - Chunk(IAllocator* alloc, ValueNum* baseVN, var_types typ, ChunkExtraAttribs attribs, BasicBlock::loopNumber loopNum); + Chunk(IAllocator* alloc, + ValueNum* baseVN, + var_types typ, + ChunkExtraAttribs attribs, + BasicBlock::loopNumber loopNum); // Requires that "m_numUsed < ChunkSize." Returns the offset of the allocated VN within the chunk; the // actual VN is this added to the "m_baseVN" of the chunk. @@ -1257,7 +1251,6 @@ private: { SRC_Null, SRC_ZeroMap, - SRC_NotAField, SRC_ReadOnlyHeap, SRC_Void, SRC_EmptyExcSet, @@ -1265,10 +1258,6 @@ private: SRC_NumSpecialRefConsts }; - // Counter to keep track of all the unique not a field sequences that have been assigned to - // PtrToLoc, because the ptr was added to an offset that was not a field. - unsigned m_uPtrToLocNotAFieldCount; - // The "values" of special ref consts will be all be "null" -- their differing meanings will // be carried by the distinct value numbers. static class Object* s_specialRefConsts[SRC_NumSpecialRefConsts]; diff --git a/src/jit/valuenumfuncs.h b/src/jit/valuenumfuncs.h index 064a337..eb17aed 100644 --- a/src/jit/valuenumfuncs.h +++ b/src/jit/valuenumfuncs.h @@ -11,9 +11,10 @@ ValueNumFuncDef(MapStore, 3, false, false, false) ValueNumFuncDef(MapSelect, 2, false, false, false) ValueNumFuncDef(FieldSeq, 2, false, false, false) // Sequence (VN of null == empty) of (VN's of) field handles. +ValueNumFuncDef(NotAField, 0, false, false, false) // Value number function for FieldSeqStore::NotAField. ValueNumFuncDef(ZeroMap, 0, false, false, false) // The "ZeroMap": indexing at any index yields "zero of the desired type". -ValueNumFuncDef(PtrToLoc, 3, false, false, false) // Pointer (byref) to a local variable. Args: VN's of: 0: var num, 1: FieldSeq, 2: Unique value for this PtrToLoc. +ValueNumFuncDef(PtrToLoc, 2, false, false, false) // Pointer (byref) to a local variable. Args: VN's of: 0: var num, 1: FieldSeq. ValueNumFuncDef(PtrToArrElem, 4, false, false, false) // Pointer (byref) to an array element. Args: 0: array elem type eq class var_types value, VN's of: 1: array, 2: index, 3: FieldSeq. ValueNumFuncDef(PtrToStatic, 1, false, false, false) // Pointer (byref) to a static variable (or possibly a field thereof, if the static variable is a struct). Args: 0: FieldSeq, first element // of which is the static var. @@ -99,6 +100,7 @@ ValueNumFuncDef(GetsharedNongcstaticBase, 2, false, true, true) ValueNumFuncDef(GetsharedGcstaticBaseNoctor, 1, false, true, true) ValueNumFuncDef(GetsharedNongcstaticBaseNoctor, 1, false, true, true) ValueNumFuncDef(ReadyToRunStaticBase, 1, false, true, true) +ValueNumFuncDef(ReadyToRunGenericStaticBase, 2, false, true, true) ValueNumFuncDef(GetsharedGcstaticBaseDynamicclass, 2, false, true, true) ValueNumFuncDef(GetsharedNongcstaticBaseDynamicclass, 2, false, true, true) ValueNumFuncDef(GetgenericsGcthreadstaticBase, 1, false, true, true) diff --git a/src/md/ceefilegen/cceegen.cpp b/src/md/ceefilegen/cceegen.cpp index 268093c..0cf0780 100644 --- a/src/md/ceefilegen/cceegen.cpp +++ b/src/md/ceefilegen/cceegen.cpp @@ -572,18 +572,20 @@ HRESULT CCeeGen::emitMetaData(IMetaDataEmit *emitter, CeeSection* section, DWORD _ASSERTE(metaDataLen <= buffLen); #ifdef ENC_DELTA_HACK - extern int __cdecl fclose(FILE *); - WCHAR szFileName[256]; - DWORD len = GetEnvironmentVariable(W("COMP_ENC_EMIT"), szFileName, ARRAYSIZE(szFileName)); - _ASSERTE(len < (ARRAYSIZE(szFileName) + 6)); // +6 for the .dmeta - if (len > 0 && len < (ARRAYSIZE(szFileName) + 6)) { - wcscat_s(szFileName, ARRAYSIZE(szFileName), W(".dmeta")); - FILE *pDelta; - int ec = _wfopen_s(&pDelta, szFileName, W("wb")); - if (FAILED(ec)) { return HRESULT_FROM_WIN32(ERROR_OPEN_FAILED); } - fwrite(buffer, 1, metaDataLen, pDelta); - fclose(pDelta); + extern int __cdecl fclose(FILE *); + WCHAR szFileName[256]; + DWORD len = GetEnvironmentVariable(W("COMP_ENC_EMIT"), szFileName, ARRAYSIZE(szFileName)); + _ASSERTE(len < (ARRAYSIZE(szFileName) + 6)); // +6 for the .dmeta + if (len > 0 && len < (ARRAYSIZE(szFileName) + 6)) + { + wcscat_s(szFileName, ARRAYSIZE(szFileName), W(".dmeta")); + FILE *pDelta; + int ec = _wfopen_s(&pDelta, szFileName, W("wb")); + if (FAILED(ec)) { return HRESULT_FROM_WIN32(ERROR_OPEN_FAILED); } + fwrite(buffer, 1, metaDataLen, pDelta); + fclose(pDelta); + } } #endif diff --git a/src/md/winmd/adapter.cpp b/src/md/winmd/adapter.cpp index 5b4d95c..2c9dd1b 100644 --- a/src/md/winmd/adapter.cpp +++ b/src/md/winmd/adapter.cpp @@ -88,6 +88,8 @@ HRESULT CheckIfWinMDAdapterNeeded(IMDCommon *pRawMDCommon) HRESULT hr; LPWSTR wszCorVersion = NULL; WinMDAdapter* pNewAdapter = NULL; + ULONG numAssemblyRefs = 0; + const char *szClrPortion = NULL; *ppAdapter = NULL; @@ -102,7 +104,7 @@ HRESULT CheckIfWinMDAdapterNeeded(IMDCommon *pRawMDCommon) //------------------------------------------------------------------------------------------------ LPCSTR szVersion; IfFailGo(pRawMDCommon->GetVersionString(&szVersion)); - const char *szClrPortion = strchr(szVersion, ';'); + szClrPortion = strchr(szVersion, ';'); if (szClrPortion) { pNewAdapter->m_scenario = kWinMDExp; @@ -148,7 +150,7 @@ HRESULT CheckIfWinMDAdapterNeeded(IMDCommon *pRawMDCommon) //------------------------------------------------------------------------------------------------ // Find an assemblyRef to mscorlib (required to exist in .winmd files precisely to make the adapter's job easier. //------------------------------------------------------------------------------------------------ - ULONG numAssemblyRefs = pNewAdapter->m_pRawMetaModelCommonRO->CommonGetRowCount(mdtAssemblyRef); + numAssemblyRefs = pNewAdapter->m_pRawMetaModelCommonRO->CommonGetRowCount(mdtAssemblyRef); pNewAdapter->m_assemblyRefMscorlib = 0; pNewAdapter->m_fReferencesMscorlibV4 = FALSE; for (ULONG rid = 1; rid <= numAssemblyRefs; rid++) @@ -860,10 +862,11 @@ WinMDAdapter::GetTypeRefProps( HRESULT hr; ULONG treatment; + ULONG treatmentClass; IfFailGo(GetTypeRefTreatment(tkTypeRef, &treatment)); _ASSERTE(treatment != kTrNotYetInitialized); - ULONG treatmentClass = treatment & kTrClassMask; + treatmentClass = treatment & kTrClassMask; if (treatmentClass == kTrClassWellKnownRedirected) { ULONG nRewritePairIndex = treatment & ~kTrClassMask; @@ -998,9 +1001,10 @@ WinMDAdapter::GetTypeRefRedirectedInfo( HRESULT hr; ULONG treatment; + ULONG treatmentClass; IfFailGo(GetTypeRefTreatment(tkTypeRef, &treatment)); - ULONG treatmentClass = treatment & kTrClassMask; + treatmentClass = treatment & kTrClassMask; if (treatmentClass == kTrClassWellKnownRedirected) { *pIndex = (RedirectedTypeIndex)(treatment & ~kTrClassMask); @@ -1278,11 +1282,14 @@ HRESULT WinMDAdapter::ModifyMethodProps(mdMethodDef tkMethodDef, /*[in, out]*/ D _ASSERTE(TypeFromToken(tkMethodDef) == mdtMethodDef); ULONG mdTreatment; + DWORD dwAttr; + DWORD dwImplFlags; + ULONG ulRVA; IfFailGo(GetMethodDefTreatment(tkMethodDef, &mdTreatment)); - DWORD dwAttr = pdwAttr ? *pdwAttr: 0; - DWORD dwImplFlags = pdwImplFlags ? *pdwImplFlags : 0; - ULONG ulRVA = pulRVA ? *pulRVA : 0; + dwAttr = pdwAttr ? *pdwAttr: 0; + dwImplFlags = pdwImplFlags ? *pdwImplFlags : 0; + ulRVA = pulRVA ? *pulRVA : 0; switch (mdTreatment & kMdTreatmentMask) { @@ -2400,9 +2407,12 @@ HRESULT WinMDAdapter::TranslateWinMDAttributeUsageAttribute(mdTypeDef tkTypeDefO { IfFailGo(COR_E_BADIMAGEFORMAT); } - DWORD wfTargetValue = *(DWORD*)(pbWFUsageBlob + 2); - *pClrTargetValue = ConvertToClrAttributeTarget(wfTargetValue); + { + DWORD wfTargetValue = *(DWORD*)(pbWFUsageBlob + 2); + *pClrTargetValue = ConvertToClrAttributeTarget(wfTargetValue); + } + // add AttributeTargets.Method, AttributeTargets.Constructor , AttributeTargets.Property, and AttributeTargets.Event if this is the VersionAttribute LPCSTR szNamespace; LPCSTR szName; diff --git a/src/md/winmd/inc/adapter.h b/src/md/winmd/inc/adapter.h index e69b620..e42992f 100644 --- a/src/md/winmd/inc/adapter.h +++ b/src/md/winmd/inc/adapter.h @@ -136,7 +136,7 @@ public: static BOOL ConvertWellKnownTypeNameFromClrToWinRT(LPCSTR *pszFullName); // Map a well-known CLR typename to WinRT typename - static BOOL WinMDAdapter::ConvertWellKnownTypeNameFromClrToWinRT(LPCSTR *pszNamespace, LPCSTR *pszName); + static BOOL ConvertWellKnownTypeNameFromClrToWinRT(LPCSTR *pszNamespace, LPCSTR *pszName); // Returns names of redirected type 'index'. static void GetRedirectedTypeInfo( diff --git a/src/md/winmd/winmdimport.cpp b/src/md/winmd/winmdimport.cpp index fe80bf0..cc983d2 100644 --- a/src/md/winmd/winmdimport.cpp +++ b/src/md/winmd/winmdimport.cpp @@ -588,13 +588,15 @@ class WinMDImport : public IMetaDataImport2 *pmb = mdMethodDefNil; - // check to see if this is a vararg signature - PCCOR_SIGNATURE pvSigTemp = pvSigBlob; - if (isCallConv(CorSigUncompressCallingConv(pvSigTemp), IMAGE_CEE_CS_CALLCONV_VARARG)) { - // Get the fixed part of VARARG signature - IfFailGo(_GetFixedSigOfVarArg(pvSigBlob, cbSigBlob, &qbSig, &cbSigBlob)); - pvSigBlob = (PCCOR_SIGNATURE) qbSig.Ptr(); + // check to see if this is a vararg signature + PCCOR_SIGNATURE pvSigTemp = pvSigBlob; + if (isCallConv(CorSigUncompressCallingConv(pvSigTemp), IMAGE_CEE_CS_CALLCONV_VARARG)) + { + // Get the fixed part of VARARG signature + IfFailGo(_GetFixedSigOfVarArg(pvSigBlob, cbSigBlob, &qbSig, &cbSigBlob)); + pvSigBlob = (PCCOR_SIGNATURE) qbSig.Ptr(); + } } // now iterate all methods in td and compare name and signature @@ -1654,15 +1656,17 @@ class WinMDImport : public IMetaDataImport2 // Step 1: Call EnumAssemblyRefs with an empty buffer to create the HENUMInternal IfFailGo(m_pRawAssemblyImport->EnumAssemblyRefs(phEnum, NULL, 0, NULL)); - // Step 2: Increment the cound to include the extra assembly refs - HENUMInternal *phInternalEnum = static_cast(*phEnum); + { + // Step 2: Increment the count to include the extra assembly refs + HENUMInternal *phInternalEnum = static_cast(*phEnum); - _ASSERTE(phInternalEnum->m_EnumType == MDSimpleEnum); + _ASSERTE(phInternalEnum->m_EnumType == MDSimpleEnum); - _ASSERTE( phInternalEnum->m_ulCount == m_pWinMDAdapter->GetRawAssemblyRefCount()); - int n = m_pWinMDAdapter->GetExtraAssemblyRefCount(); - phInternalEnum->m_ulCount += n; - phInternalEnum->u.m_ulEnd += n; + _ASSERTE( phInternalEnum->m_ulCount == m_pWinMDAdapter->GetRawAssemblyRefCount()); + int n = m_pWinMDAdapter->GetExtraAssemblyRefCount(); + phInternalEnum->m_ulCount += n; + phInternalEnum->u.m_ulEnd += n; + } // Step 3: Call EnumAssemblyRefs again and pass in the modifed HENUMInternal and the real buffer IfFailGo(m_pRawAssemblyImport->EnumAssemblyRefs(phEnum, rAssemblyRefs, cMax, pcTokens)); diff --git a/src/mscorlib/Common/PinnableBufferCache.cs b/src/mscorlib/Common/PinnableBufferCache.cs index fee3e46..fc6e13a 100644 --- a/src/mscorlib/Common/PinnableBufferCache.cs +++ b/src/mscorlib/Common/PinnableBufferCache.cs @@ -4,9 +4,6 @@ #define ENABLE #define MINBUFFERS using System; -#if !FEATURE_CORECLR -using System.Diagnostics.Tracing; -#endif using System.Runtime.InteropServices; using System.Runtime.ConstrainedExecution; using System.Collections.Generic; @@ -45,12 +42,6 @@ namespace System /// Create a PinnableBufferCache that works on any object (it is intended for OverlappedData) /// This is only used in mscorlib. /// -#if (ENABLE || MINBUFFERS) -#pragma warning disable 618 - [EnvironmentPermission(SecurityAction.Assert, Unrestricted = true)] -#pragma warning restore 618 - [System.Security.SecuritySafeCritical] -#endif internal PinnableBufferCache(string cacheName, Func factory) { m_NotGen2 = new List(DefaultNumberOfBuffers); @@ -103,7 +94,6 @@ namespace System /// /// Get a object from the buffer manager. If no buffers exist, allocate a new one. /// - [System.Security.SecuritySafeCritical] internal object Allocate() { #if ENABLE @@ -149,7 +139,6 @@ namespace System /// /// Return a buffer back to the buffer manager. /// - [System.Security.SecuritySafeCritical] internal void Free(object buffer) { #if ENABLE @@ -188,7 +177,6 @@ namespace System /// Called when we don't have any buffers in our free list to give out. /// /// - [System.Security.SecuritySafeCritical] private void Restock(out object returnBuffer) { lock (this) @@ -241,7 +229,6 @@ namespace System /// /// See if we can promote the buffers to the free list. Returns true if sucessful. /// - [System.Security.SecuritySafeCritical] private bool AgePendingBuffers() { if (m_gen1CountAtLastRestock < GC.CollectionCount(GC.MaxGeneration - 1)) @@ -317,7 +304,6 @@ namespace System /// otherwise, we root the cache to the Gen2GcCallback object, and leak the cache even when /// the application no longer needs it. /// - [System.Security.SecuritySafeCritical] private static bool Gen2GcCallbackFunc(object targetObj) { return ((PinnableBufferCache)(targetObj)).TrimFreeListIfNeeded(); @@ -328,7 +314,6 @@ namespace System /// NOTE: DO NOT CALL THIS DIRECTLY FROM THE GEN2GCCALLBACK. INSTEAD CALL IT VIA A STATIC FUNCTION (SEE ABOVE). /// If you register a non-static function as a callback, then this object will be leaked. /// - [System.Security.SecuritySafeCritical] private bool TrimFreeListIfNeeded() { int curMSec = Environment.TickCount; @@ -481,7 +466,6 @@ namespace System /// internal sealed class Gen2GcCallback : CriticalFinalizerObject { - [System.Security.SecuritySafeCritical] public Gen2GcCallback() : base() { @@ -506,14 +490,12 @@ namespace System private Func m_callback; private GCHandle m_weakTargetObj; - [System.Security.SecuritySafeCritical] private void Setup(Func callback, object targetObj) { m_callback = callback; m_weakTargetObj = GCHandle.Alloc(targetObj, GCHandleType.Weak); } - [System.Security.SecuritySafeCritical] ~Gen2GcCallback() { // Check to see if the target object is still alive. @@ -549,8 +531,6 @@ namespace System #endregion } - -#if FEATURE_CORECLR internal sealed class PinnableBufferCacheEventSource { public static readonly PinnableBufferCacheEventSource Log = new PinnableBufferCacheEventSource(); @@ -581,86 +561,9 @@ namespace System return 0; } - [System.Security.SecuritySafeCritical] static internal unsafe long AddressOfObject(byte[] array) { return 0; } } -#else - /// - /// PinnableBufferCacheEventSource is a private eventSource that we are using to - /// debug and monitor the effectiveness of PinnableBufferCache - /// -#if PINNABLEBUFFERCACHE_MSCORLIB - [EventSource(Name = "Microsoft-DotNETRuntime-PinnableBufferCache")] -#else - [EventSource(Name = "Microsoft-DotNETRuntime-PinnableBufferCache-System")] -#endif - internal sealed class PinnableBufferCacheEventSource : EventSource - { - public static readonly PinnableBufferCacheEventSource Log = new PinnableBufferCacheEventSource(); - - [Event(1, Level = EventLevel.Verbose)] - public void DebugMessage(string message) { if (IsEnabled()) WriteEvent(1, message); } - [Event(2, Level = EventLevel.Verbose)] - public void DebugMessage1(string message, long value) { if (IsEnabled()) WriteEvent(2, message, value); } - [Event(3, Level = EventLevel.Verbose)] - public void DebugMessage2(string message, long value1, long value2) { if (IsEnabled()) WriteEvent(3, message, value1, value2); } - [Event(18, Level = EventLevel.Verbose)] - public void DebugMessage3(string message, long value1, long value2, long value3) { if (IsEnabled()) WriteEvent(18, message, value1, value2, value3); } - - [Event(4)] - public void Create(string cacheName) { if (IsEnabled()) WriteEvent(4, cacheName); } - - [Event(5, Level = EventLevel.Verbose)] - public void AllocateBuffer(string cacheName, ulong objectId, int objectHash, int objectGen, int freeCountAfter) { if (IsEnabled()) WriteEvent(5, cacheName, objectId, objectHash, objectGen, freeCountAfter); } - [Event(6)] - public void AllocateBufferFromNotGen2(string cacheName, int notGen2CountAfter) { if (IsEnabled()) WriteEvent(6, cacheName, notGen2CountAfter); } - [Event(7)] - public void AllocateBufferCreatingNewBuffers(string cacheName, int totalBuffsBefore, int objectCount) { if (IsEnabled()) WriteEvent(7, cacheName, totalBuffsBefore, objectCount); } - [Event(8)] - public void AllocateBufferAged(string cacheName, int agedCount) { if (IsEnabled()) WriteEvent(8, cacheName, agedCount); } - [Event(9)] - public void AllocateBufferFreeListEmpty(string cacheName, int notGen2CountBefore) { if (IsEnabled()) WriteEvent(9, cacheName, notGen2CountBefore); } - - [Event(10, Level = EventLevel.Verbose)] - public void FreeBuffer(string cacheName, ulong objectId, int objectHash, int freeCountBefore) { if (IsEnabled()) WriteEvent(10, cacheName, objectId, objectHash, freeCountBefore); } - [Event(11)] - public void FreeBufferStillTooYoung(string cacheName, int notGen2CountBefore) { if (IsEnabled()) WriteEvent(11, cacheName, notGen2CountBefore); } - - [Event(13)] - public void TrimCheck(string cacheName, int totalBuffs, bool neededMoreThanFreeList, int deltaMSec) { if (IsEnabled()) WriteEvent(13, cacheName, totalBuffs, neededMoreThanFreeList, deltaMSec); } - [Event(14)] - public void TrimFree(string cacheName, int totalBuffs, int freeListCount, int toBeFreed) { if (IsEnabled()) WriteEvent(14, cacheName, totalBuffs, freeListCount, toBeFreed); } - [Event(15)] - public void TrimExperiment(string cacheName, int totalBuffs, int freeListCount, int numTrimTrial) { if (IsEnabled()) WriteEvent(15, cacheName, totalBuffs, freeListCount, numTrimTrial); } - [Event(16)] - public void TrimFreeSizeOK(string cacheName, int totalBuffs, int freeListCount) { if (IsEnabled()) WriteEvent(16, cacheName, totalBuffs, freeListCount); } - [Event(17)] - public void TrimFlush(string cacheName, int totalBuffs, int freeListCount, int notGen2CountBefore) { if (IsEnabled()) WriteEvent(17, cacheName, totalBuffs, freeListCount, notGen2CountBefore); } - [Event(20)] - public void AgePendingBuffersResults(string cacheName, int promotedToFreeListCount, int heldBackCount) { if (IsEnabled()) WriteEvent(20, cacheName, promotedToFreeListCount, heldBackCount); } - [Event(21)] - public void WalkFreeListResult(string cacheName, int freeListCount, int gen0BuffersInFreeList) { if (IsEnabled()) WriteEvent(21, cacheName, freeListCount, gen0BuffersInFreeList); } - - - static internal ulong AddressOf(object obj) - { - var asByteArray = obj as byte[]; - if (asByteArray != null) - return (ulong)AddressOfByteArray(asByteArray); - return 0; - } - - [System.Security.SecuritySafeCritical] - static internal unsafe long AddressOfByteArray(byte[] array) - { - if (array == null) - return 0; - fixed (byte* ptr = array) - return (long)(ptr - 2 * sizeof(void*)); - } - } -#endif } diff --git a/src/mscorlib/System.Private.CoreLib.csproj b/src/mscorlib/System.Private.CoreLib.csproj index c14ce42..f1f944a 100644 --- a/src/mscorlib/System.Private.CoreLib.csproj +++ b/src/mscorlib/System.Private.CoreLib.csproj @@ -1,5 +1,9 @@ + + + + diff --git a/src/mscorlib/System.Private.CoreLib.sln b/src/mscorlib/System.Private.CoreLib.sln index 4ab28af..60a2316 100644 --- a/src/mscorlib/System.Private.CoreLib.sln +++ b/src/mscorlib/System.Private.CoreLib.sln @@ -5,6 +5,11 @@ VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Private.CoreLib", "System.Private.CoreLib.csproj", "{3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E16B1C86-C275-495B-80D6-7CE8196A18B4}" + ProjectSection(SolutionItems) = preProject + model.xml = model.xml + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Checked|amd64 = Checked|amd64 diff --git a/src/mscorlib/corefx/Debug.cs b/src/mscorlib/corefx/Debug.cs new file mode 100644 index 0000000..3398c0e --- /dev/null +++ b/src/mscorlib/corefx/Debug.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. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; + +namespace System +{ + internal static class Debug + { + [Conditional("_DEBUG")] + static public void Assert(bool condition) + { + BCLDebug.Assert(condition); + } + + [Conditional("_DEBUG")] + static public void Assert(bool condition, string message) + { + BCLDebug.Assert(condition, message); + } + + [Conditional("_DEBUG")] + static public void Fail(string message) + { + BCLDebug.Assert(false, message); + } + } +} \ No newline at end of file diff --git a/src/mscorlib/corefx/Interop/Unix/Interop.Errors.cs b/src/mscorlib/corefx/Interop/Unix/Interop.Errors.cs new file mode 100644 index 0000000..4248434 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/Interop.Errors.cs @@ -0,0 +1,207 @@ +// 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.Runtime.InteropServices; + +internal static partial class Interop +{ + /// Common Unix errno error codes. + internal enum Error + { + // These values were defined in src/Native/System.Native/fxerrno.h + // + // They compare against values obtained via Interop.Sys.GetLastError() not Marshal.GetLastWin32Error() + // which obtains the raw errno that varies between unixes. The strong typing as an enum is meant to + // prevent confusing the two. Casting to or from int is suspect. Use GetLastErrorInfo() if you need to + // correlate these to the underlying platform values or obtain the corresponding error message. + // + + SUCCESS = 0, + + E2BIG = 0x10001, // Argument list too long. + EACCES = 0x10002, // Permission denied. + EADDRINUSE = 0x10003, // Address in use. + EADDRNOTAVAIL = 0x10004, // Address not available. + EAFNOSUPPORT = 0x10005, // Address family not supported. + EAGAIN = 0x10006, // Resource unavailable, try again (same value as EWOULDBLOCK), + EALREADY = 0x10007, // Connection already in progress. + EBADF = 0x10008, // Bad file descriptor. + EBADMSG = 0x10009, // Bad message. + EBUSY = 0x1000A, // Device or resource busy. + ECANCELED = 0x1000B, // Operation canceled. + ECHILD = 0x1000C, // No child processes. + ECONNABORTED = 0x1000D, // Connection aborted. + ECONNREFUSED = 0x1000E, // Connection refused. + ECONNRESET = 0x1000F, // Connection reset. + EDEADLK = 0x10010, // Resource deadlock would occur. + EDESTADDRREQ = 0x10011, // Destination address required. + EDOM = 0x10012, // Mathematics argument out of domain of function. + EDQUOT = 0x10013, // Reserved. + EEXIST = 0x10014, // File exists. + EFAULT = 0x10015, // Bad address. + EFBIG = 0x10016, // File too large. + EHOSTUNREACH = 0x10017, // Host is unreachable. + EIDRM = 0x10018, // Identifier removed. + EILSEQ = 0x10019, // Illegal byte sequence. + EINPROGRESS = 0x1001A, // Operation in progress. + EINTR = 0x1001B, // Interrupted function. + EINVAL = 0x1001C, // Invalid argument. + EIO = 0x1001D, // I/O error. + EISCONN = 0x1001E, // Socket is connected. + EISDIR = 0x1001F, // Is a directory. + ELOOP = 0x10020, // Too many levels of symbolic links. + EMFILE = 0x10021, // File descriptor value too large. + EMLINK = 0x10022, // Too many links. + EMSGSIZE = 0x10023, // Message too large. + EMULTIHOP = 0x10024, // Reserved. + ENAMETOOLONG = 0x10025, // Filename too long. + ENETDOWN = 0x10026, // Network is down. + ENETRESET = 0x10027, // Connection aborted by network. + ENETUNREACH = 0x10028, // Network unreachable. + ENFILE = 0x10029, // Too many files open in system. + ENOBUFS = 0x1002A, // No buffer space available. + ENODEV = 0x1002C, // No such device. + ENOENT = 0x1002D, // No such file or directory. + ENOEXEC = 0x1002E, // Executable file format error. + ENOLCK = 0x1002F, // No locks available. + ENOLINK = 0x10030, // Reserved. + ENOMEM = 0x10031, // Not enough space. + ENOMSG = 0x10032, // No message of the desired type. + ENOPROTOOPT = 0x10033, // Protocol not available. + ENOSPC = 0x10034, // No space left on device. + ENOSYS = 0x10037, // Function not supported. + ENOTCONN = 0x10038, // The socket is not connected. + ENOTDIR = 0x10039, // Not a directory or a symbolic link to a directory. + ENOTEMPTY = 0x1003A, // Directory not empty. + ENOTSOCK = 0x1003C, // Not a socket. + ENOTSUP = 0x1003D, // Not supported (same value as EOPNOTSUP). + ENOTTY = 0x1003E, // Inappropriate I/O control operation. + ENXIO = 0x1003F, // No such device or address. + EOVERFLOW = 0x10040, // Value too large to be stored in data type. + EPERM = 0x10042, // Operation not permitted. + EPIPE = 0x10043, // Broken pipe. + EPROTO = 0x10044, // Protocol error. + EPROTONOSUPPORT = 0x10045, // Protocol not supported. + EPROTOTYPE = 0x10046, // Protocol wrong type for socket. + ERANGE = 0x10047, // Result too large. + EROFS = 0x10048, // Read-only file system. + ESPIPE = 0x10049, // Invalid seek. + ESRCH = 0x1004A, // No such process. + ESTALE = 0x1004B, // Reserved. + ETIMEDOUT = 0x1004D, // Connection timed out. + ETXTBSY = 0x1004E, // Text file busy. + EXDEV = 0x1004F, // Cross-device link. + ESOCKTNOSUPPORT = 0x1005E, // Socket type not supported. + EPFNOSUPPORT = 0x10060, // Protocol family not supported. + ESHUTDOWN = 0x1006C, // Socket shutdown. + EHOSTDOWN = 0x10070, // Host is down. + ENODATA = 0x10071, // No data available. + + // POSIX permits these to have the same value and we make them always equal so + // that CoreFX cannot introduce a dependency on distinguishing between them that + // would not work on all platforms. + EOPNOTSUPP = ENOTSUP, // Operation not supported on socket. + EWOULDBLOCK = EAGAIN, // Operation would block. + } + + + // Represents a platform-agnostic Error and underlying platform-specific errno + internal struct ErrorInfo + { + private Error _error; + private int _rawErrno; + + internal ErrorInfo(int errno) + { + _error = Interop.Sys.ConvertErrorPlatformToPal(errno); + _rawErrno = errno; + } + + internal ErrorInfo(Error error) + { + _error = error; + _rawErrno = -1; + } + + internal Error Error + { + get { return _error; } + } + + internal int RawErrno + { + get { return _rawErrno == -1 ? (_rawErrno = Interop.Sys.ConvertErrorPalToPlatform(_error)) : _rawErrno; } + } + + internal string GetErrorMessage() + { + return Interop.Sys.StrError(RawErrno); + } + + public override string ToString() + { + return string.Format( + "RawErrno: {0} Error: {1} GetErrorMessage: {2}", // No localization required; text is member names used for debugging purposes + RawErrno, Error, GetErrorMessage()); + } + } + + internal partial class Sys + { + internal static Error GetLastError() + { + return ConvertErrorPlatformToPal(Marshal.GetLastWin32Error()); + } + + internal static ErrorInfo GetLastErrorInfo() + { + return new ErrorInfo(Marshal.GetLastWin32Error()); + } + + internal static unsafe string StrError(int platformErrno) + { + int maxBufferLength = 1024; // should be long enough for most any UNIX error + byte* buffer = stackalloc byte[maxBufferLength]; + byte* message = StrErrorR(platformErrno, buffer, maxBufferLength); + + if (message == null) + { + // This means the buffer was not large enough, but still contains + // as much of the error message as possible and is guaranteed to + // be null-terminated. We're not currently resizing/retrying because + // maxBufferLength is large enough in practice, but we could do + // so here in the future if necessary. + message = buffer; + } + + return Marshal.PtrToStringAnsi((IntPtr)message); + } + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ConvertErrorPlatformToPal")] + internal static extern Error ConvertErrorPlatformToPal(int platformErrno); + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ConvertErrorPalToPlatform")] + internal static extern int ConvertErrorPalToPlatform(Error error); + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_StrErrorR")] + private static unsafe extern byte* StrErrorR(int platformErrno, byte* buffer, int bufferSize); + } +} + +// NOTE: extension method can't be nested inside Interop class. +internal static class InteropErrorExtensions +{ + // Intended usage is e.g. Interop.Error.EFAIL.Info() for brevity + // vs. new Interop.ErrorInfo(Interop.Error.EFAIL) for synthesizing + // errors. Errors originated from the system should be obtained + // via GetLastErrorInfo(), not GetLastError().Info() as that will + // convert twice, which is not only inefficient but also lossy if + // we ever encounter a raw errno that no equivalent in the Error + // enum. + public static Interop.ErrorInfo Info(this Interop.Error error) + { + return new Interop.ErrorInfo(error); + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/Interop.IOErrors.cs b/src/mscorlib/corefx/Interop/Unix/Interop.IOErrors.cs new file mode 100644 index 0000000..e9d6ce6 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/Interop.IOErrors.cs @@ -0,0 +1,170 @@ +// 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.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + private static void ThrowExceptionForIoErrno(ErrorInfo errorInfo, string path, bool isDirectory, Func errorRewriter) + { + Debug.Assert(errorInfo.Error != Error.SUCCESS); + Debug.Assert(errorInfo.Error != Error.EINTR, "EINTR errors should be handled by the native shim and never bubble up to managed code"); + + if (errorRewriter != null) + { + errorInfo = errorRewriter(errorInfo); + } + + throw Interop.GetExceptionForIoErrno(errorInfo, path, isDirectory); + } + + internal static void CheckIo(Error error, string path = null, bool isDirectory = false, Func errorRewriter = null) + { + if (error != Interop.Error.SUCCESS) + { + ThrowExceptionForIoErrno(error.Info(), path, isDirectory, errorRewriter); + } + } + + /// + /// Validates the result of system call that returns greater than or equal to 0 on success + /// and less than 0 on failure, with errno set to the error code. + /// If the system call failed for any reason, an exception is thrown. Otherwise, the system call succeeded. + /// + /// The result of the system call. + /// The path with which this error is associated. This may be null. + /// true if the is known to be a directory; otherwise, false. + /// Optional function to change an error code prior to processing it. + /// + /// On success, returns the non-negative result long that was validated. + /// + internal static long CheckIo(long result, string path = null, bool isDirectory = false, Func errorRewriter = null) + { + if (result < 0) + { + ThrowExceptionForIoErrno(Sys.GetLastErrorInfo(), path, isDirectory, errorRewriter); + } + + return result; + } + + /// + /// Validates the result of system call that returns greater than or equal to 0 on success + /// and less than 0 on failure, with errno set to the error code. + /// If the system call failed for any reason, an exception is thrown. Otherwise, the system call succeeded. + /// + /// + /// On success, returns the non-negative result int that was validated. + /// + internal static int CheckIo(int result, string path = null, bool isDirectory = false, Func errorRewriter = null) + { + CheckIo((long)result, path, isDirectory, errorRewriter); + + return result; + } + + /// + /// Validates the result of system call that returns greater than or equal to 0 on success + /// and less than 0 on failure, with errno set to the error code. + /// If the system call failed for any reason, an exception is thrown. Otherwise, the system call succeeded. + /// + /// + /// On success, returns the non-negative result IntPtr that was validated. + /// + internal static IntPtr CheckIo(IntPtr result, string path = null, bool isDirectory = false, Func errorRewriter = null) + { + CheckIo((long)result, path, isDirectory, errorRewriter); + + return result; + } + + /// + /// Validates the result of system call that returns greater than or equal to 0 on success + /// and less than 0 on failure, with errno set to the error code. + /// If the system call failed for any reason, an exception is thrown. Otherwise, the system call succeeded. + /// + /// + /// On success, returns the valid SafeFileHandle that was validated. + /// + internal static TSafeHandle CheckIo(TSafeHandle handle, string path = null, bool isDirectory = false, Func errorRewriter = null) + where TSafeHandle : SafeHandle + { + if (handle.IsInvalid) + { + ThrowExceptionForIoErrno(Sys.GetLastErrorInfo(), path, isDirectory, errorRewriter); + } + + return handle; + } + + /// + /// Gets an Exception to represent the supplied error info. + /// + /// The error info + /// The path with which this error is associated. This may be null. + /// true if the is known to be a directory; otherwise, false. + /// + internal static Exception GetExceptionForIoErrno(ErrorInfo errorInfo, string path = null, bool isDirectory = false) + { + // Translate the errno into a known set of exception types. For cases where multiple errnos map + // to the same exception type, include an inner exception with the details. + switch (errorInfo.Error) + { + case Error.ENOENT: + if (isDirectory) + { + return !string.IsNullOrEmpty(path) ? + new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, path)) : + new DirectoryNotFoundException(SR.IO_PathNotFound_NoPathName); + } + else + { + return !string.IsNullOrEmpty(path) ? + new FileNotFoundException(SR.Format(SR.IO_FileNotFound_FileName, path), path) : + new FileNotFoundException(SR.IO_FileNotFound); + } + + case Error.EACCES: + case Error.EBADF: + case Error.EPERM: + Exception inner = GetIOException(errorInfo); + return !string.IsNullOrEmpty(path) ? + new UnauthorizedAccessException(SR.Format(SR.UnauthorizedAccess_IODenied_Path, path), inner) : + new UnauthorizedAccessException(SR.UnauthorizedAccess_IODenied_NoPathName, inner); + + case Error.ENAMETOOLONG: + return new PathTooLongException(SR.IO_PathTooLong); + + case Error.EWOULDBLOCK: + return !string.IsNullOrEmpty(path) ? + new IOException(SR.Format(SR.IO_SharingViolation_File, path), errorInfo.RawErrno) : + new IOException(SR.IO_SharingViolation_NoFileName, errorInfo.RawErrno); + + case Error.ECANCELED: + return new OperationCanceledException(); + + case Error.EFBIG: + return new ArgumentOutOfRangeException("value", SR.ArgumentOutOfRange_FileLengthTooBig); + + case Error.EEXIST: + if (!string.IsNullOrEmpty(path)) + { + return new IOException(SR.Format(SR.IO_FileExists_Name, path), errorInfo.RawErrno); + } + goto default; + + default: + return GetIOException(errorInfo); + } + } + + internal static Exception GetIOException(Interop.ErrorInfo errorInfo) + { + return new IOException(errorInfo.GetErrorMessage(), errorInfo.RawErrno); + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/Interop.Libraries.cs b/src/mscorlib/corefx/Interop/Unix/Interop.Libraries.cs index f8c5b26..a11a23c 100644 --- a/src/mscorlib/corefx/Interop/Unix/Interop.Libraries.cs +++ b/src/mscorlib/corefx/Interop/Unix/Interop.Libraries.cs @@ -7,5 +7,12 @@ internal static partial class Interop private static partial class Libraries { internal const string GlobalizationInterop = "System.Globalization.Native"; // CoreFX wrappers for ICU + // Shims + internal const string SystemNative = "System.Native"; + internal const string HttpNative = "System.Net.Http.Native"; + internal const string NetSecurityNative = "System.Net.Security.Native"; + internal const string CryptoNative = "System.Security.Cryptography.Native.OpenSsl"; + internal const string GlobalizationNative = "System.Globalization.Native"; + internal const string CompressionNative = "System.IO.Compression.Native"; } } diff --git a/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs index 6acf55e..eb9e074 100644 --- a/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs +++ b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs @@ -13,7 +13,7 @@ internal static partial class Interop { [SecurityCritical] [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetSortHandle")] - internal unsafe static extern SafeSortHandle GetSortHandle(byte[] localeName); + internal unsafe static extern ResultCode GetSortHandle(byte[] localeName, out SafeSortHandle sortHandle); [SecurityCritical] [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_CloseSortHandle")] @@ -53,6 +53,9 @@ internal static partial class Interop [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_CompareStringOrdinalIgnoreCase")] internal unsafe static extern int CompareStringOrdinalIgnoreCase(char* lpStr1, int cwStr1Len, char* lpStr2, int cwStr2Len); + [DllImport(Libraries.GlobalizationInterop, EntryPoint = "GlobalizationNative_GetSortVersion")] + internal static extern int GetSortVersion(); + [SecurityCritical] internal class SafeSortHandle : SafeHandle { diff --git a/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Idna.cs b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Idna.cs new file mode 100644 index 0000000..43c7228 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Idna.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class GlobalizationInterop + { + internal const int AllowUnassigned = 0x1; + internal const int UseStd3AsciiRules = 0x2; + + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_ToAscii")] + internal static unsafe extern int ToAscii(uint flags, char* src, int srcLen, char* dstBuffer, int dstBufferCapacity); + + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_ToUnicode")] + internal static unsafe extern int ToUnicode(uint flags, char* src, int srcLen, char* dstBuffer, int dstBufferCapacity); + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Locale.cs b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Locale.cs index 3912581..fcea708 100644 --- a/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Locale.cs +++ b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Locale.cs @@ -33,5 +33,8 @@ internal static partial class Interop [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetLocaleInfoGroupingSizes")] [return: MarshalAs(UnmanagedType.Bool)] internal unsafe static extern bool GetLocaleInfoGroupingSizes(string localeName, uint localeGroupingData, ref int primaryGroupSize, ref int secondaryGroupSize); + + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetLocales")] + internal unsafe static extern int GetLocales([Out] Char[] value, int valueLength); } } diff --git a/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Normalization.cs b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Normalization.cs new file mode 100644 index 0000000..c4cb9fb --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Normalization.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using System.Text; + +internal static partial class Interop +{ + internal static partial class GlobalizationInterop + { + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_IsNormalized")] + internal static extern int IsNormalized(NormalizationForm normalizationForm, string src, int srcLen); + + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_NormalizeString")] + internal static extern int NormalizeString(NormalizationForm normalizationForm, string src, int srcLen, [Out] char[] dstBuffer, int dstBufferCapacity); + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.ResultCode.cs b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.ResultCode.cs index 4621580..cca6ae4 100644 --- a/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.ResultCode.cs +++ b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.ResultCode.cs @@ -12,6 +12,7 @@ internal static partial class Interop Success = 0, UnknownError = 1, InsufficentBuffer = 2, + OutOfMemory = 3 } } } diff --git a/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Close.cs b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Close.cs new file mode 100644 index 0000000..8d19239 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Close.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Close", SetLastError = true)] + internal static extern int Close(IntPtr fd); + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.FLock.cs b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.FLock.cs new file mode 100644 index 0000000..22934a3 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.FLock.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Sys + { + internal enum LockOperations : int + { + LOCK_SH = 1, /* shared lock */ + LOCK_EX = 2, /* exclusive lock */ + LOCK_NB = 4, /* don't block when locking*/ + LOCK_UN = 8, /* unlock */ + } + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FLock", SetLastError = true)] + internal static extern int FLock(SafeFileHandle fd, LockOperations operation); + + /// + /// Exposing this for SafeFileHandle.ReleaseHandle() to call. + /// Normal callers should use FLock(SafeFileHandle fd). + /// + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FLock", SetLastError = true)] + internal static extern int FLock(IntPtr fd, LockOperations operation); + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.FSync.cs b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.FSync.cs new file mode 100644 index 0000000..e3ab970 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.FSync.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. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Sys + { + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FSync", SetLastError = true)] + internal static extern int FSync(SafeFileHandle fd); + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.FTruncate.cs b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.FTruncate.cs new file mode 100644 index 0000000..5dad650 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.FTruncate.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. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Sys + { + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FTruncate", SetLastError = true)] + internal static extern int FTruncate(SafeFileHandle fd, long length); + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Fcntl.cs b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Fcntl.cs new file mode 100644 index 0000000..23b48a4 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Fcntl.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + internal enum LockType : short + { + F_WRLCK = 1, // exclusive or write lock + F_UNLCK = 2 // unlock + } + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LockFileRegion", SetLastError=true)] + internal static extern int LockFileRegion(SafeHandle fd, long offset, long length, LockType lockType); + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.GetCwd.cs b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.GetCwd.cs new file mode 100644 index 0000000..724e342 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.GetCwd.cs @@ -0,0 +1,74 @@ +// 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.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetCwd", SetLastError = true)] + private static unsafe extern byte* GetCwd(byte* buffer, int bufferLength); + + internal static unsafe string GetCwd() + { + const int StackLimit = 256; + + // First try to get the path into a buffer on the stack + byte* stackBuf = stackalloc byte[StackLimit]; + string result = GetCwdHelper(stackBuf, StackLimit); + if (result != null) + { + return result; + } + + // If that was too small, try increasing large buffer sizes + // until we get one that works or until we hit MaxPath. + int maxPath = Interop.Sys.MaxPath; + if (StackLimit < maxPath) + { + int bufferSize = StackLimit; + do + { + checked { bufferSize *= 2; } + var buf = new byte[Math.Min(bufferSize, maxPath)]; + fixed (byte* ptr = buf) + { + result = GetCwdHelper(ptr, buf.Length); + if (result != null) + { + return result; + } + } + } + while (bufferSize < maxPath); + } + + // If we couldn't get the cwd with a MaxPath-sized buffer, something's wrong. + throw Interop.GetExceptionForIoErrno(new ErrorInfo(Interop.Error.ENAMETOOLONG)); + } + + private static unsafe string GetCwdHelper(byte* ptr, int bufferSize) + { + // Call the real getcwd + byte* result = GetCwd(ptr, bufferSize); + + // If it returned non-null, the null-terminated path is in the buffer + if (result != null) + { + return Marshal.PtrToStringAnsi((IntPtr)ptr); + } + + // Otherwise, if it failed due to the buffer being too small, return null; + // for anything else, throw. + ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo(); + if (errorInfo.Error == Interop.Error.ERANGE) + { + return null; + } + throw Interop.GetExceptionForIoErrno(errorInfo); + } + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.GetUnixName.cs b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.GetUnixName.cs new file mode 100644 index 0000000..33664c4 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.GetUnixName.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetUnixName")] + private static extern IntPtr GetUnixNamePrivate(); + + internal static string GetUnixName() + { + IntPtr ptr = GetUnixNamePrivate(); + return Marshal.PtrToStringAnsi(ptr); + } + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.LSeek.cs b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.LSeek.cs new file mode 100644 index 0000000..7f8df7c --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.LSeek.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. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Sys + { + internal enum SeekWhence + { + SEEK_SET = 0, + SEEK_CUR = 1, + SEEK_END = 2 + } + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LSeek", SetLastError = true)] + internal static extern long LSeek(SafeFileHandle fd, long offset, SeekWhence whence); + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.MksTemps.cs b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.MksTemps.cs new file mode 100644 index 0000000..b8694d9 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.MksTemps.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_MksTemps", SetLastError = true)] + internal static extern IntPtr MksTemps( + byte[] template, + int suffixlen); + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Open.cs b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Open.cs new file mode 100644 index 0000000..a9a994c --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Open.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. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Sys + { + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Open", SetLastError = true)] + internal static extern SafeFileHandle Open(string filename, OpenFlags flags, int mode); + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.OpenFlags.cs b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.OpenFlags.cs new file mode 100644 index 0000000..f9e54c3 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.OpenFlags.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. +// See the LICENSE file in the project root for more information. + +using System; + +internal static partial class Interop +{ + internal static partial class Sys + { + [Flags] + internal enum OpenFlags + { + // Access modes (mutually exclusive) + O_RDONLY = 0x0000, + O_WRONLY = 0x0001, + O_RDWR = 0x0002, + + // Flags (combinable) + O_CLOEXEC = 0x0010, + O_CREAT = 0x0020, + O_EXCL = 0x0040, + O_TRUNC = 0x0080, + O_SYNC = 0x0100, + } + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.PathConf.cs b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.PathConf.cs new file mode 100644 index 0000000..4a1fcf6 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.PathConf.cs @@ -0,0 +1,73 @@ +// 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.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + internal static int DEFAULT_PC_NAME_MAX = 255; + + internal enum PathConfName : int + { + PC_LINK_MAX = 1, + PC_MAX_CANON = 2, + PC_MAX_INPUT = 3, + PC_NAME_MAX = 4, + PC_PATH_MAX = 5, + PC_PIPE_BUF = 6, + PC_CHOWN_RESTRICTED = 7, + PC_NO_TRUNC = 8, + PC_VDISABLE = 9, + } + + /// The maximum path length for the system. -1 if it hasn't yet been initialized. + private static int s_maxPath = -1; + + /// The maximum name length for the system. -1 if it hasn't yet been initialized. + private static int s_maxName = -1; + + internal static int MaxPath + { + get + { + // Benign race condition on cached value + if (s_maxPath < 0) + { + // GetMaximumPath returns a long from PathConf + // but our callers expect an int so we need to convert. + long temp = GetMaximumPath(); + if (temp > int.MaxValue) + s_maxPath = int.MaxValue; + else + s_maxPath = Convert.ToInt32(temp); + } + return s_maxPath; + } + } + + internal static int MaxName + { + get + { + // Benign race condition on cached value + if (s_maxName < 0) + { + int result = PathConf("/", PathConfName.PC_NAME_MAX); + s_maxName = result >= 0 ? result : DEFAULT_PC_NAME_MAX; + } + + return s_maxName; + } + } + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_PathConf", SetLastError = true)] + private static extern int PathConf(string path, PathConfName name); + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetMaximumPath")] + private static extern long GetMaximumPath(); + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Permissions.cs b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Permissions.cs new file mode 100644 index 0000000..f1d1378 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Permissions.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. +// See the LICENSE file in the project root for more information. + +using System; + +internal static partial class Interop +{ + internal static partial class Sys + { + [Flags] + internal enum Permissions + { + Mask = S_IRWXU | S_IRWXG | S_IRWXO, + + S_IRWXU = S_IRUSR | S_IWUSR | S_IXUSR, + S_IRUSR = 0x100, + S_IWUSR = 0x80, + S_IXUSR = 0x40, + + S_IRWXG = S_IRGRP | S_IWGRP | S_IXGRP, + S_IRGRP = 0x20, + S_IWGRP = 0x10, + S_IXGRP = 0x8, + + S_IRWXO = S_IROTH | S_IWOTH | S_IXOTH, + S_IROTH = 0x4, + S_IWOTH = 0x2, + S_IXOTH = 0x1, + } + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.PosixFAdvise.cs b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.PosixFAdvise.cs new file mode 100644 index 0000000..69e39b3 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.PosixFAdvise.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. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Sys + { + internal enum FileAdvice : int + { + POSIX_FADV_NORMAL = 0, /* no special advice, the default value */ + POSIX_FADV_RANDOM = 1, /* random I/O access */ + POSIX_FADV_SEQUENTIAL = 2, /* sequential I/O access */ + POSIX_FADV_WILLNEED = 3, /* will need specified pages */ + POSIX_FADV_DONTNEED = 4, /* don't need the specified pages */ + POSIX_FADV_NOREUSE = 5, /* data will only be acessed once */ + } + + /// + /// Notifies the OS kernel that the specified file will be accessed in a particular way soon; this allows the kernel to + /// potentially optimize the access pattern of the file. + /// + /// The file descriptor of the file + /// The start of the region to advise about + /// The number of bytes of the region (until the end of the file if 0) + /// The type of advice to give the kernel about the specified region + /// + /// Returns 0 on success; otherwise, the error code is returned + /// + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_PosixFAdvise", SetLastError = false /* this is explicitly called out in the man page */)] + internal static extern int PosixFAdvise(SafeFileHandle fd, long offset, long length, FileAdvice advice); + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Read.cs b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Read.cs new file mode 100644 index 0000000..812ae34 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Read.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. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Sys + { + /// + /// Reads a number of bytes from an open file descriptor into a specified buffer. + /// + /// The open file descriptor to try to read from + /// The buffer to read info into + /// The size of the buffer + /// + /// Returns the number of bytes read on success; otherwise, -1 is returned + /// Note - on fail. the position of the stream may change depending on the platform; consult man 2 read for more info + /// + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Read", SetLastError = true)] + internal static unsafe extern int Read(SafeFileHandle fd, byte* buffer, int count); + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Stat.cs b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Stat.cs new file mode 100644 index 0000000..a8bc2ec --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Stat.cs @@ -0,0 +1,59 @@ +// 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.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Sys + { + // Even though csc will by default use a sequential layout, a CS0649 warning as error + // is produced for un-assigned fields when no StructLayout is specified. + // + // Explicitly saying Sequential disables that warning/error for consumers which only + // use Stat in debug builds. + [StructLayout(LayoutKind.Sequential)] + internal struct FileStatus + { + internal FileStatusFlags Flags; + internal int Mode; + internal uint Uid; + internal uint Gid; + internal long Size; + internal long ATime; + internal long MTime; + internal long CTime; + internal long BirthTime; + } + + internal static class FileTypes + { + internal const int S_IFMT = 0xF000; + internal const int S_IFIFO = 0x1000; + internal const int S_IFCHR = 0x2000; + internal const int S_IFDIR = 0x4000; + internal const int S_IFREG = 0x8000; + internal const int S_IFLNK = 0xA000; + internal const int S_IFSOCK = 0xC000; + } + + [Flags] + internal enum FileStatusFlags + { + None = 0, + HasBirthTime = 1, + } + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FStat", SetLastError = true)] + internal static extern int FStat(SafeFileHandle fd, out FileStatus output); + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Stat", SetLastError = true)] + internal static extern int Stat(string path, out FileStatus output); + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LStat", SetLastError = true)] + internal static extern int LStat(string path, out FileStatus output); + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Unlink.cs b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Unlink.cs new file mode 100644 index 0000000..829210f --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Unlink.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Unlink", SetLastError = true)] + internal static extern int Unlink(string pathname); + } +} diff --git a/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Write.cs b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Write.cs new file mode 100644 index 0000000..c14fc26 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Unix/System.Native/Interop.Write.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. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Sys + { + /// + /// Writes the specified buffer to the provided open file descriptor + /// + /// The file descriptor to try and write to + /// The data to attempt to write + /// The amount of data to write, in bytes + /// + /// Returns the number of bytes written on success; otherwise, returns -1 and sets errno + /// + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Write", SetLastError = true)] + internal static unsafe extern int Write(SafeFileHandle fd, byte* buffer, int bufferSize); + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Write", SetLastError = true)] + internal static unsafe extern int Write(int fd, byte* buffer, int bufferSize); + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/BCrypt/Interop.BCryptGenRandom.cs b/src/mscorlib/corefx/Interop/Windows/BCrypt/Interop.BCryptGenRandom.cs new file mode 100644 index 0000000..d2ce413 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/BCrypt/Interop.BCryptGenRandom.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class BCrypt + { + internal static unsafe NTSTATUS BCryptGenRandom(byte* pbBuffer, int count) + { + Debug.Assert(pbBuffer != null); + Debug.Assert(count >= 0); + + return BCryptGenRandom(IntPtr.Zero, pbBuffer, count, BCRYPT_USE_SYSTEM_PREFERRED_RNG); + } + + private const int BCRYPT_USE_SYSTEM_PREFERRED_RNG = 0x00000002; + + [DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] + private static unsafe extern NTSTATUS BCryptGenRandom(IntPtr hAlgorithm, byte* pbBuffer, int cbBuffer, int dwFlags); + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/BCrypt/Interop.NTSTATUS.cs b/src/mscorlib/corefx/Interop/Windows/BCrypt/Interop.NTSTATUS.cs new file mode 100644 index 0000000..49d674f --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/BCrypt/Interop.NTSTATUS.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. +// See the LICENSE file in the project root for more information. + +using System; + +internal partial class Interop +{ + internal partial class BCrypt + { + internal enum NTSTATUS : uint + { + STATUS_SUCCESS = 0x0, + STATUS_NOT_FOUND = 0xc0000225, + STATUS_INVALID_PARAMETER = 0xc000000d, + STATUS_NO_MEMORY = 0xc0000017, + } + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/Crypt32/Interop.CryptProtectMemory.cs b/src/mscorlib/corefx/Interop/Windows/Crypt32/Interop.CryptProtectMemory.cs new file mode 100644 index 0000000..b10cb6a --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/Crypt32/Interop.CryptProtectMemory.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using System.Security; + +internal partial class Interop +{ + internal partial class Crypt32 + { + internal const uint CRYPTPROTECTMEMORY_BLOCK_SIZE = 16; + internal const uint CRYPTPROTECTMEMORY_SAME_PROCESS = 0; + + [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern bool CryptProtectMemory(SafeBSTRHandle pData, uint cbData, uint dwFlags); + + [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern bool CryptUnprotectMemory(SafeBSTRHandle pData, uint cbData, uint dwFlags); + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/Interop.BOOL.cs b/src/mscorlib/corefx/Interop/Windows/Interop.BOOL.cs new file mode 100644 index 0000000..9f4dab8 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/Interop.BOOL.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +internal partial class Interop +{ + /// + /// Blittable version of Windows BOOL type. It is convenient in situations where + /// manual marshalling is required, or to avoid overhead of regular bool marshalling. + /// + /// + /// Some Windows APIs return arbitrary integer values although the return type is defined + /// as BOOL. It is best to never compare BOOL to TRUE. Always use bResult != BOOL.FALSE + /// or bResult == BOOL.FALSE . + /// + internal enum BOOL : int + { + FALSE = 0, + TRUE = 1, + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/Interop.Libraries.cs b/src/mscorlib/corefx/Interop/Windows/Interop.Libraries.cs new file mode 100644 index 0000000..1165a2d --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/Interop.Libraries.cs @@ -0,0 +1,82 @@ +// 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. + +internal static partial class Interop +{ + internal static class Libraries + { + internal const string Advapi32 = "advapi32.dll"; + internal const string BCrypt = "BCrypt.dll"; + internal const string Combase = "combase.dll"; + internal const string Console_L1 = "api-ms-win-core-console-l1-1-0.dll"; + internal const string Console_L2 = "api-ms-win-core-console-l2-1-0.dll"; + internal const string CoreFile_L1 = "api-ms-win-core-file-l1-1-0.dll"; + internal const string CoreFile_L1_2 = "api-ms-win-core-file-l1-2-0.dll"; + internal const string CoreFile_L2 = "api-ms-win-core-file-l2-1-0.dll"; + internal const string Crypt32 = "crypt32.dll"; + internal const string Debug = "api-ms-win-core-debug-l1-1-0.dll"; + internal const string Error_L1 = "api-ms-win-core-winrt-error-l1-1-0.dll"; + internal const string ErrorHandling = "api-ms-win-core-errorhandling-l1-1-0.dll"; + internal const string Eventing = "api-ms-win-eventing-provider-l1-1-0.dll"; + internal const string Handle = "api-ms-win-core-handle-l1-1-0.dll"; + internal const string Heap = "api-ms-win-core-heap-obsolete-l1-1-0.dll"; + internal const string Heap_L1 = "api-ms-win-core-heap-l1-1-0.dll"; + internal const string IO = "api-ms-win-core-io-l1-1-0.dll"; + internal const string IpHlpApi = "iphlpapi.dll"; + internal const string Kernel32 = "kernel32.dll"; + internal const string Kernel32_L1 = "api-ms-win-core-kernel32-legacy-l1-1-1.dll"; + internal const string Kernel32_L2 = "api-ms-win-core-kernel32-legacy-l1-1-0.dll"; + internal const string Keyboard = "ext-ms-win-ntuser-keyboard-l1-2-1.dll"; + internal const string LibraryLoader = "api-ms-win-core-libraryloader-l1-1-0.dll"; + internal const string Localization = "api-ms-win-core-localization-l1-2-0.dll"; + internal const string Memory_L1_0 = "api-ms-win-core-memory-l1-1-0.dll"; + internal const string Memory_L1_1 = "api-ms-win-core-memory-l1-1-1.dll"; + internal const string Memory_L1_2 = "api-ms-win-core-memory-l1-1-2.dll"; + internal const string Memory_L1_3 = "api-ms-win-core-memory-l1-1-3.dll"; + internal const string NCrypt = "ncrypt.dll"; + internal const string NtDll = "ntdll.dll"; + internal const string OleAut32 = "oleaut32.dll"; + internal const string Pipe = "api-ms-win-core-namedpipe-l1-1-0.dll"; + internal const string Pipe_L2 = "api-ms-win-core-namedpipe-l1-2-1.dll"; + internal const string ProcessEnvironment = "api-ms-win-core-processenvironment-l1-1-0.dll"; + internal const string ProcessThread_L1 = "api-ms-win-core-processthreads-l1-1-0.dll"; + internal const string ProcessThread_L1_1 = "api-ms-win-core-processthreads-l1-1-1.dll"; + internal const string ProcessThread_L1_2 = "api-ms-win-core-processthreads-l1-1-2.dll"; + internal const string ProcessTopology = "api-ms-win-core-processtopology-obsolete-l1-1-0.dll"; + internal const string Profile = "api-ms-win-core-profile-l1-1-0.dll"; + internal const string Psapi = "api-ms-win-core-psapi-l1-1-0.dll"; + internal const string Psapi_Obsolete = "api-ms-win-core-psapi-obsolete-l1-1-0.dll"; + internal const string Registry_L1 = "api-ms-win-core-registry-l1-1-0.dll"; + internal const string Registry_L2 = "api-ms-win-core-registry-l2-1-0.dll"; + internal const string RoBuffer = "api-ms-win-core-winrt-robuffer-l1-1-0.dll"; + internal const string SecurityBase = "api-ms-win-security-base-l1-1-0.dll"; + internal const string SecurityCpwl = "api-ms-win-security-cpwl-l1-1-0.dll"; + internal const string SecurityCryptoApi = "api-ms-win-security-cryptoapi-l1-1-0.dll"; + internal const string SecurityLsa = "api-ms-win-security-lsalookup-l2-1-0.dll"; + internal const string SecurityLsaPolicy = "api-ms-win-security-lsapolicy-l1-1-0.dll"; + internal const string SecurityProvider = "api-ms-win-security-provider-l1-1-0.dll"; + internal const string SecuritySddl = "api-ms-win-security-sddl-l1-1-0.dll"; + internal const string ServiceCore = "api-ms-win-service-core-l1-1-1.dll"; + internal const string ServiceMgmt_L1 = "api-ms-win-service-management-l1-1-0.dll"; + internal const string ServiceMgmt_L2 = "api-ms-win-service-management-l2-1-0.dll"; + internal const string ServiceWinSvc = "api-ms-win-service-winsvc-l1-1-0.dll"; + internal const string Shell = "shell32.dll"; + internal const string ShellFolders = "ext-ms-win-shell32-shellfolders-l1-1-0.dll"; + internal const string Sspi = "sspicli.dll"; + internal const string String_L1 = "api-ms-win-core-string-l1-1-0.dll"; + internal const string Synch = "api-ms-win-core-synch-l1-1-0.dll"; + internal const string SystemInfo_L1_1 = "api-ms-win-core-sysinfo-l1-1-0.dll"; + internal const string SystemInfo_L1_2 = "api-ms-win-core-sysinfo-l1-2-0.dll"; + internal const string SystemInfo_L2_1 = "api-ms-win-core-sysinfo-l2-1-0.dll"; + internal const string ThreadPool = "api-ms-win-core-threadpool-l1-2-0.dll"; + internal const string User32 = "user32.dll"; + internal const string Util = "api-ms-win-core-util-l1-1-0.dll"; + internal const string Version = "api-ms-win-core-version-l1-1-0.dll"; + internal const string WinHttp = "winhttp.dll"; + internal const string Winsock = "Ws2_32.dll"; + internal const string Wow64 = "api-ms-win-core-wow64-l1-1-0.dll"; + internal const string Ws2_32 = "ws2_32.dll"; + internal const string Zlib = "clrcompression.dll"; + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/NtDll/Interop.ZeroMemory.cs b/src/mscorlib/corefx/Interop/Windows/NtDll/Interop.ZeroMemory.cs new file mode 100644 index 0000000..caa0329 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/NtDll/Interop.ZeroMemory.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using System.Security; + +internal partial class Interop +{ + internal partial class NtDll + { + [DllImport(Libraries.NtDll, CharSet = CharSet.Unicode, EntryPoint = "RtlZeroMemory")] + internal static extern void ZeroMemory(SafeBSTRHandle address, uint length); + + [DllImport(Libraries.NtDll, CharSet = CharSet.Unicode, EntryPoint = "RtlZeroMemory")] + internal static extern void ZeroMemory(IntPtr address, UIntPtr length); + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.CancelIoEx.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.CancelIoEx.cs new file mode 100644 index 0000000..868d409 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.CancelIoEx.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. +// See the LICENSE file in the project root for more information. + +using Microsoft.Win32.SafeHandles; +using System.Runtime.InteropServices; +using System.Threading; + +internal partial class Interop +{ + internal partial class mincore + { + [DllImport(Libraries.IO, SetLastError = true)] + internal static unsafe extern bool CancelIoEx(SafeHandle handle, NativeOverlapped* lpOverlapped); + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.CloseHandle.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.CloseHandle.cs new file mode 100644 index 0000000..029937b --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.CloseHandle.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class mincore + { + [DllImport(Libraries.Handle, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool CloseHandle(IntPtr handle); + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.CreateFile.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.CreateFile.cs new file mode 100644 index 0000000..670037d --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.CreateFile.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. +// See the LICENSE file in the project root for more information. + +using Microsoft.Win32.SafeHandles; +using System; +using System.IO; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class mincore + { + /// + /// WARNING: This method does not implicitly handle long paths. Use CreateFile. + /// + [DllImport(Libraries.CoreFile_L1, EntryPoint = "CreateFileW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)] + private static extern SafeFileHandle CreateFilePrivate( + string lpFileName, + int dwDesiredAccess, + System.IO.FileShare dwShareMode, + [In] ref SECURITY_ATTRIBUTES securityAttrs, + System.IO.FileMode dwCreationDisposition, + int dwFlagsAndAttributes, + IntPtr hTemplateFile); + + internal static SafeFileHandle CreateFile( + string lpFileName, + int dwDesiredAccess, + System.IO.FileShare dwShareMode, + [In] ref SECURITY_ATTRIBUTES securityAttrs, + System.IO.FileMode dwCreationDisposition, + int dwFlagsAndAttributes, + IntPtr hTemplateFile) + { + lpFileName = PathInternal.EnsureExtendedPrefixOverMaxPath(lpFileName); + return CreateFilePrivate(lpFileName, dwDesiredAccess, dwShareMode, ref securityAttrs, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); + } + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.Errors.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.Errors.cs new file mode 100644 index 0000000..05b2250 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.Errors.cs @@ -0,0 +1,74 @@ +// 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. + +internal partial class Interop +{ + internal partial class mincore + { + internal partial class Errors + { + internal const int ERROR_SUCCESS = 0x0; + internal const int ERROR_INVALID_FUNCTION = 0x1; + internal const int ERROR_FILE_NOT_FOUND = 0x2; + internal const int ERROR_PATH_NOT_FOUND = 0x3; + internal const int ERROR_ACCESS_DENIED = 0x5; + internal const int ERROR_INVALID_HANDLE = 0x6; + internal const int ERROR_NOT_ENOUGH_MEMORY = 0x8; + internal const int ERROR_INVALID_DATA = 0xD; + internal const int ERROR_INVALID_DRIVE = 0xF; + internal const int ERROR_NO_MORE_FILES = 0x12; + internal const int ERROR_NOT_READY = 0x15; + internal const int ERROR_BAD_LENGTH = 0x18; + internal const int ERROR_SHARING_VIOLATION = 0x20; + internal const int ERROR_LOCK_VIOLATION = 0x21; + internal const int ERROR_HANDLE_EOF = 0x26; + internal const int ERROR_FILE_EXISTS = 0x50; + internal const int ERROR_INVALID_PARAMETER = 0x57; + internal const int ERROR_BROKEN_PIPE = 0x6D; + internal const int ERROR_INSUFFICIENT_BUFFER = 0x7A; + internal const int ERROR_INVALID_NAME = 0x7B; + internal const int ERROR_NEGATIVE_SEEK = 0x83; + internal const int ERROR_DIR_NOT_EMPTY = 0x91; + internal const int ERROR_BAD_PATHNAME = 0xA1; + internal const int ERROR_LOCK_FAILED = 0xA7; + internal const int ERROR_BUSY = 0xAA; + internal const int ERROR_ALREADY_EXISTS = 0xB7; + internal const int ERROR_BAD_EXE_FORMAT = 0xC1; + internal const int ERROR_ENVVAR_NOT_FOUND = 0xCB; + internal const int ERROR_FILENAME_EXCED_RANGE = 0xCE; + internal const int ERROR_EXE_MACHINE_TYPE_MISMATCH = 0xD8; + internal const int ERROR_PIPE_BUSY = 0xE7; + internal const int ERROR_NO_DATA = 0xE8; + internal const int ERROR_PIPE_NOT_CONNECTED = 0xE9; + internal const int ERROR_MORE_DATA = 0xEA; + internal const int ERROR_NO_MORE_ITEMS = 0x103; + internal const int ERROR_PARTIAL_COPY = 0x12B; + internal const int ERROR_ARITHMETIC_OVERFLOW = 0x216; + internal const int ERROR_PIPE_CONNECTED = 0x217; + internal const int ERROR_PIPE_LISTENING = 0x218; + internal const int ERROR_OPERATION_ABORTED = 0x3E3; + internal const int ERROR_IO_PENDING = 0x3E5; + internal const int ERROR_NO_TOKEN = 0x3f0; + internal const int ERROR_DLL_INIT_FAILED = 0x45A; + internal const int ERROR_NOT_FOUND = 0x490; + internal const int ERROR_NON_ACCOUNT_SID = 0x4E9; + internal const int ERROR_NOT_ALL_ASSIGNED = 0x514; + internal const int ERROR_UNKNOWN_REVISION = 0x519; + internal const int ERROR_INVALID_OWNER = 0x51B; + internal const int ERROR_INVALID_PRIMARY_GROUP = 0x51C; + internal const int ERROR_NO_SUCH_PRIVILEGE = 0x521; + internal const int ERROR_PRIVILEGE_NOT_HELD = 0x522; + internal const int ERROR_INVALID_ACL = 0x538; + internal const int ERROR_INVALID_SECURITY_DESCR = 0x53A; + internal const int ERROR_INVALID_SID = 0x539; + internal const int ERROR_BAD_IMPERSONATION_LEVEL = 0x542; + internal const int ERROR_CANT_OPEN_ANONYMOUS = 0x543; + internal const int ERROR_NO_SECURITY_ON_OBJECT = 0x546; + internal const int ERROR_TRUSTED_RELATIONSHIP_FAILURE = 0x6FD; + internal const int ERROR_RESOURCE_LANG_NOT_FOUND = 0x717; + internal const int EFail = unchecked((int)0x80004005); + internal const int E_FILENOTFOUND = unchecked((int)0x80070002); + } + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.FileOperations.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.FileOperations.cs new file mode 100644 index 0000000..4369760 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.FileOperations.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. +// See the LICENSE file in the project root for more information. + +internal partial class Interop +{ + internal partial class mincore + { + internal partial class IOReparseOptions + { + internal const uint IO_REPARSE_TAG_FILE_PLACEHOLDER = 0x80000015; + internal const uint IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003; + } + + internal partial class FileOperations + { + internal const int OPEN_EXISTING = 3; + internal const int COPY_FILE_FAIL_IF_EXISTS = 0x00000001; + + internal const int FILE_ACTION_ADDED = 1; + internal const int FILE_ACTION_REMOVED = 2; + internal const int FILE_ACTION_MODIFIED = 3; + internal const int FILE_ACTION_RENAMED_OLD_NAME = 4; + internal const int FILE_ACTION_RENAMED_NEW_NAME = 5; + + internal const int FILE_FLAG_BACKUP_SEMANTICS = 0x02000000; + internal const int FILE_FLAG_FIRST_PIPE_INSTANCE = 0x00080000; + internal const int FILE_FLAG_OVERLAPPED = 0x40000000; + + internal const int FILE_LIST_DIRECTORY = 0x0001; + } + + internal const uint SEM_FAILCRITICALERRORS = 1; + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.FileTypes.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.FileTypes.cs new file mode 100644 index 0000000..a24813e --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.FileTypes.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. +// See the LICENSE file in the project root for more information. + +internal partial class Interop +{ + internal partial class mincore + { + internal partial class FileTypes + { + internal const int FILE_TYPE_DISK = 0x0001; + internal const int FILE_TYPE_CHAR = 0x0002; + internal const int FILE_TYPE_PIPE = 0x0003; + } + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.FlushFileBuffers.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.FlushFileBuffers.cs new file mode 100644 index 0000000..69f4fe0 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.FlushFileBuffers.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. +// See the LICENSE file in the project root for more information. + +using Microsoft.Win32.SafeHandles; +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class mincore + { + [DllImport(Libraries.CoreFile_L1, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool FlushFileBuffers(SafeHandle hHandle); + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.FormatMessage.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.FormatMessage.cs new file mode 100644 index 0000000..02ecbb8 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.FormatMessage.cs @@ -0,0 +1,112 @@ +// 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.Text; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class mincore + { + private const int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200; + private const int FORMAT_MESSAGE_FROM_HMODULE = 0x00000800; + private const int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000; + private const int FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000; + + + private const int ERROR_INSUFFICIENT_BUFFER = 0x7A; + + [DllImport(Libraries.Localization, CharSet = CharSet.Unicode, EntryPoint = "FormatMessageW", SetLastError = true, BestFitMapping = true)] + private static extern int FormatMessage( + int dwFlags, + IntPtr lpSource, + uint dwMessageId, + int dwLanguageId, + [Out] StringBuilder lpBuffer, + int nSize, + IntPtr[] arguments); + + /// + /// Returns a string message for the specified Win32 error code. + /// + internal static string GetMessage(int errorCode) + { + return GetMessage(IntPtr.Zero, errorCode); + } + + internal static string GetMessage(IntPtr moduleHandle, int errorCode) + { + var sb = new StringBuilder(InitialBufferSize); + do + { + string errorMsg; + if (TryGetErrorMessage(moduleHandle, errorCode, sb, out errorMsg)) + { + return errorMsg; + } + else + { + // increase the capacity of the StringBuilder. + sb.Capacity *= BufferSizeIncreaseFactor; + } + } + while (sb.Capacity < MaxAllowedBufferSize); + + // If you come here then a size as large as 65K is also not sufficient and so we give the generic errorMsg. + return string.Format("Unknown error (0x{0:x})", errorCode); + } + + private static bool TryGetErrorMessage(IntPtr moduleHandle, int errorCode, StringBuilder sb, out string errorMsg) + { + errorMsg = ""; + + int flags = FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY; + if (moduleHandle != IntPtr.Zero) + { + flags |= FORMAT_MESSAGE_FROM_HMODULE; + } + + int result = FormatMessage(flags, moduleHandle, (uint)errorCode, 0, sb, sb.Capacity, null); + if (result != 0) + { + int i = sb.Length; + while (i > 0) + { + char ch = sb[i - 1]; + if (ch > 32 && ch != '.') break; + i--; + } + errorMsg = sb.ToString(0, i); + } + else if (Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER) + { + return false; + } + else + { + errorMsg = string.Format("Unknown error (0x{0:x})", errorCode); + } + + return true; + } + + // Windows API FormatMessage lets you format a message string given an errorcode. + // Unlike other APIs this API does not support a way to query it for the total message size. + // + // So the API can only be used in one of these two ways. + // a. You pass a buffer of appropriate size and get the resource. + // b. Windows creates a buffer and passes the address back and the onus of releasing the buffer lies on the caller. + // + // Since the error code is coming from the user, it is not possible to know the size in advance. + // Unfortunately we can't use option b. since the buffer can only be freed using LocalFree and it is a private API on onecore. + // Also, using option b is ugly for the managed code and could cause memory leak in situations where freeing is unsuccessful. + // + // As a result we use the following approach. + // We initially call the API with a buffer size of 256 and then gradually increase the size in case of failure until we reach the maximum allowed limit of 65K. + private const int InitialBufferSize = 256; + private const int BufferSizeIncreaseFactor = 4; + private const int MaxAllowedBufferSize = 65 * 1024; + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetFileInformationByHandleEx.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetFileInformationByHandleEx.cs new file mode 100644 index 0000000..c4739a5 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetFileInformationByHandleEx.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. +// See the LICENSE file in the project root for more information. + +using Microsoft.Win32.SafeHandles; +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class mincore + { + [DllImport(Libraries.CoreFile_L2, SetLastError = true)] + internal static extern bool GetFileInformationByHandleEx(SafeFileHandle hFile, FILE_INFO_BY_HANDLE_CLASS FileInformationClass, out FILE_STANDARD_INFO lpFileInformation, uint dwBufferSize); + + internal partial struct FILE_STANDARD_INFO + { + internal long AllocationSize; + internal long EndOfFile; + internal uint NumberOfLinks; + internal BOOL DeletePending; + internal BOOL Directory; + } + + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetFileType_SafeHandle.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetFileType_SafeHandle.cs new file mode 100644 index 0000000..3e2567b --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetFileType_SafeHandle.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. +// See the LICENSE file in the project root for more information. + +using Microsoft.Win32.SafeHandles; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class mincore + { + [DllImport(Libraries.CoreFile_L1, SetLastError = true)] + internal extern static int GetFileType(SafeHandle hFile); + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetFullPathNameW.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetFullPathNameW.cs new file mode 100644 index 0000000..a34cc33 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetFullPathNameW.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class mincore + { + /// + /// WARNING: This method does not implicitly handle long paths. Use GetFullPathName or PathHelper. + /// + [DllImport(Libraries.CoreFile_L1, SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)] + unsafe internal static extern uint GetFullPathNameW(char* path, uint numBufferChars, SafeHandle buffer, IntPtr mustBeZero); + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetLongPathNameW.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetLongPathNameW.cs new file mode 100644 index 0000000..d50db66 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetLongPathNameW.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +partial class Interop +{ + partial class mincore + { + /// + /// WARNING: This method does not implicitly handle long paths. Use GetFullPath/PathHelper. + /// + [DllImport(Libraries.CoreFile_L1, SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)] + internal static extern uint GetLongPathNameW(SafeHandle lpszShortPath, SafeHandle lpszLongPath, uint cchBuffer); + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetTempFileNameW.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetTempFileNameW.cs new file mode 100644 index 0000000..f06d11b --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetTempFileNameW.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text; +using System.Runtime.InteropServices; + +partial class Interop +{ + partial class mincore + { + [DllImport(Libraries.CoreFile_L1, CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false)] + internal static extern uint GetTempFileNameW(string tmpPath, string prefix, uint uniqueIdOrZero, [Out]StringBuilder tmpFileName); + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetTempPathW.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetTempPathW.cs new file mode 100644 index 0000000..0ccc27c --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.GetTempPathW.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. +// See the LICENSE file in the project root for more information. + +using System.IO; +using System.Text; +using System.Runtime.InteropServices; + +partial class Interop +{ + partial class mincore + { + [DllImport(Libraries.CoreFile_L1_2, CharSet = CharSet.Unicode, BestFitMapping = false)] + internal static extern uint GetTempPathW(int bufferLen, [Out]StringBuilder buffer); + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.Idna.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.Idna.cs new file mode 100644 index 0000000..e14f16b --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.Idna.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class mincore + { + // + // Idn APIs + // + + [DllImport("api-ms-win-core-localization-l1-2-0.dll", CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern int IdnToAscii( + uint dwFlags, + IntPtr lpUnicodeCharStr, + int cchUnicodeChar, + [System.Runtime.InteropServices.OutAttribute()] + IntPtr lpASCIICharStr, + int cchASCIIChar); + + [DllImport("api-ms-win-core-localization-l1-2-0.dll", CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern int IdnToUnicode( + uint dwFlags, + IntPtr lpASCIICharStr, + int cchASCIIChar, + [System.Runtime.InteropServices.OutAttribute()] + IntPtr lpUnicodeCharStr, + int cchUnicodeChar); + + internal const int IDN_ALLOW_UNASSIGNED = 0x1; + internal const int IDN_USE_STD3_ASCII_RULES = 0x2; + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.LockFile.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.LockFile.cs new file mode 100644 index 0000000..ee9a98e --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.LockFile.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. +// See the LICENSE file in the project root for more information. + +using Microsoft.Win32.SafeHandles; +using System; +using System.IO; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class mincore + { + [DllImport(Libraries.CoreFile_L1, SetLastError = true)] + internal static extern bool LockFile(SafeFileHandle handle, int offsetLow, int offsetHigh, int countLow, int countHigh); + + [DllImport(Libraries.CoreFile_L1, SetLastError = true)] + internal static extern bool UnlockFile(SafeFileHandle handle, int offsetLow, int offsetHigh, int countLow, int countHigh); + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.ReadFile_SafeHandle_IntPtr.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.ReadFile_SafeHandle_IntPtr.cs new file mode 100644 index 0000000..093a993 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.ReadFile_SafeHandle_IntPtr.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Win32.SafeHandles; +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class mincore + { + [DllImport(Libraries.CoreFile_L1, SetLastError = true)] + unsafe internal static extern int ReadFile( + SafeHandle handle, + byte* bytes, + int numBytesToRead, + out int numBytesRead, + IntPtr mustBeZero); + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.ReadFile_SafeHandle_NativeOverlapped.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.ReadFile_SafeHandle_NativeOverlapped.cs new file mode 100644 index 0000000..ac238cb --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.ReadFile_SafeHandle_NativeOverlapped.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. +// See the LICENSE file in the project root for more information. + +using Microsoft.Win32.SafeHandles; +using System; +using System.Runtime.InteropServices; +using System.Threading; + +internal partial class Interop +{ + internal partial class mincore + { + [DllImport(Libraries.CoreFile_L1, SetLastError = true)] + unsafe internal static extern int ReadFile( + SafeHandle handle, + byte* bytes, + int numBytesToRead, + IntPtr numBytesRead_mustBeZero, + NativeOverlapped* overlapped); + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SECURITY_ATTRIBUTES.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SECURITY_ATTRIBUTES.cs new file mode 100644 index 0000000..0f5c224 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SECURITY_ATTRIBUTES.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Win32.SafeHandles; +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class mincore + { + [StructLayout(LayoutKind.Sequential)] + internal struct SECURITY_ATTRIBUTES + { + internal uint nLength; + internal IntPtr lpSecurityDescriptor; + internal BOOL bInheritHandle; + } + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SafeCreateFile.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SafeCreateFile.cs new file mode 100644 index 0000000..edfc66d --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SafeCreateFile.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.IO; +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal partial class Interop +{ + internal partial class mincore + { + internal static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); // WinBase.h + + /// + /// Does not allow access to non-file devices. This disallows DOS devices like "con:", "com1:", + /// "lpt1:", etc. Use this to avoid security problems, like allowing a web client asking a server + /// for "http://server/com1.aspx" and then causing a worker process to hang. + /// + internal static SafeFileHandle SafeCreateFile( + String lpFileName, + int dwDesiredAccess, + System.IO.FileShare dwShareMode, + ref Interop.mincore.SECURITY_ATTRIBUTES securityAttrs, + FileMode dwCreationDisposition, + int dwFlagsAndAttributes, + IntPtr hTemplateFile) + { + SafeFileHandle handle = UnsafeCreateFile(lpFileName, dwDesiredAccess, dwShareMode, ref securityAttrs, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); + + if (!handle.IsInvalid) + { + int fileType = Interop.mincore.GetFileType(handle); + if (fileType != Interop.mincore.FileTypes.FILE_TYPE_DISK) + { + handle.Dispose(); + throw new NotSupportedException(SR.NotSupported_FileStreamOnNonFiles); + } + } + + return handle; + } + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SecurityOptions.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SecurityOptions.cs new file mode 100644 index 0000000..767d7f5 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SecurityOptions.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. +// See the LICENSE file in the project root for more information. + +internal partial class Interop +{ + internal partial class mincore + { + internal partial class SecurityOptions + { + internal const int SECURITY_SQOS_PRESENT = 0x00100000; + internal const int SECURITY_ANONYMOUS = 0 << 16; + internal const int SECURITY_IDENTIFICATION = 1 << 16; + internal const int SECURITY_IMPERSONATION = 2 << 16; + internal const int SECURITY_DELEGATION = 3 << 16; + } + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SetEndOfFile.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SetEndOfFile.cs new file mode 100644 index 0000000..ee0d3b4 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SetEndOfFile.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. +// See the LICENSE file in the project root for more information. + +using Microsoft.Win32.SafeHandles; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class mincore + { + [DllImport(Libraries.CoreFile_L1, SetLastError = true)] + internal static extern bool SetEndOfFile(SafeFileHandle hFile); + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SetErrorMode.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SetErrorMode.cs new file mode 100644 index 0000000..a845990 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SetErrorMode.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. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class mincore + { + [DllImport(Libraries.ErrorHandling, SetLastError = false, EntryPoint = "SetErrorMode", ExactSpelling = true)] + internal static extern uint SetErrorMode(uint newMode); + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SetFileInformationByHandle.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SetFileInformationByHandle.cs new file mode 100644 index 0000000..0519219 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SetFileInformationByHandle.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. +// See the LICENSE file in the project root for more information. + +using Microsoft.Win32.SafeHandles; +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class mincore + { + [DllImport(Libraries.CoreFile_L1, SetLastError = true)] + internal static extern bool SetFileInformationByHandle(SafeFileHandle hFile, FILE_INFO_BY_HANDLE_CLASS FileInformationClass, ref FILE_BASIC_INFO lpFileInformation, uint dwBufferSize); + + // Default values indicate "no change". Use defaults so that we don't force callsites to be aware of the default values + internal unsafe static bool SetFileTime( + SafeFileHandle hFile, + long creationTime = -1, + long lastAccessTime = -1, + long lastWriteTime = -1, + long changeTime = -1, + uint fileAttributes = 0) + { + FILE_BASIC_INFO basicInfo = new FILE_BASIC_INFO() + { + CreationTime = creationTime, + LastAccessTime = lastAccessTime, + LastWriteTime = lastWriteTime, + ChangeTime = changeTime, + FileAttributes = fileAttributes + }; + + return SetFileInformationByHandle(hFile, FILE_INFO_BY_HANDLE_CLASS.FileBasicInfo, ref basicInfo, (uint)Marshal.SizeOf()); + } + + internal struct FILE_BASIC_INFO + { + internal long CreationTime; + internal long LastAccessTime; + internal long LastWriteTime; + internal long ChangeTime; + internal uint FileAttributes; + } + + internal enum FILE_INFO_BY_HANDLE_CLASS : uint + { + FileBasicInfo = 0x0u, + FileStandardInfo = 0x1u, + FileNameInfo = 0x2u, + FileRenameInfo = 0x3u, + FileDispositionInfo = 0x4u, + FileAllocationInfo = 0x5u, + FileEndOfFileInfo = 0x6u, + FileStreamInfo = 0x7u, + FileCompressionInfo = 0x8u, + FileAttributeTagInfo = 0x9u, + FileIdBothDirectoryInfo = 0xAu, + FileIdBothDirectoryRestartInfo = 0xBu, + FileIoPriorityHintInfo = 0xCu, + FileRemoteProtocolInfo = 0xDu, + FileFullDirectoryInfo = 0xEu, + FileFullDirectoryRestartInfo = 0xFu, + FileStorageInfo = 0x10u, + FileAlignmentInfo = 0x11u, + FileIdInfo = 0x12u, + FileIdExtdDirectoryInfo = 0x13u, + FileIdExtdDirectoryRestartInfo = 0x14u, + MaximumFileInfoByHandleClass = 0x15u, + } + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SetFilePointerEx.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SetFilePointerEx.cs new file mode 100644 index 0000000..09f8e1f --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.SetFilePointerEx.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. +// See the LICENSE file in the project root for more information. + +using Microsoft.Win32.SafeHandles; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class mincore + { + [DllImport(Libraries.CoreFile_L1, SetLastError = true)] + internal static extern bool SetFilePointerEx(SafeFileHandle hFile, long liDistanceToMove, out long lpNewFilePointer, uint dwMoveMethod); + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.ThreadPoolIO.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.ThreadPoolIO.cs new file mode 100644 index 0000000..a0afed5 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.ThreadPoolIO.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class mincore + { + [DllImport(Libraries.ThreadPool, SetLastError = true)] + internal static unsafe extern SafeThreadPoolIOHandle CreateThreadpoolIo(SafeHandle fl, [MarshalAs(UnmanagedType.FunctionPtr)] NativeIoCompletionCallback pfnio, IntPtr context, IntPtr pcbe); + + [DllImport(Libraries.ThreadPool)] + internal static unsafe extern void CloseThreadpoolIo(IntPtr pio); + + [DllImport(Libraries.ThreadPool)] + internal static unsafe extern void StartThreadpoolIo(SafeThreadPoolIOHandle pio); + + [DllImport(Libraries.ThreadPool)] + internal static unsafe extern void CancelThreadpoolIo(SafeThreadPoolIOHandle pio); + } + + internal delegate void NativeIoCompletionCallback(IntPtr instance, IntPtr context, IntPtr overlapped, uint ioResult, UIntPtr numberOfBytesTransferred, IntPtr io); +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.UnsafeCreateFile.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.UnsafeCreateFile.cs new file mode 100644 index 0000000..e7e4f05 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.UnsafeCreateFile.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.IO; +using Microsoft.Win32.SafeHandles; + +internal partial class Interop +{ + internal partial class mincore + { + internal static SafeFileHandle UnsafeCreateFile( + string lpFileName, + int dwDesiredAccess, + FileShare dwShareMode, + ref Interop.mincore.SECURITY_ATTRIBUTES securityAttrs, + FileMode dwCreationDisposition, + int dwFlagsAndAttributes, + IntPtr hTemplateFile) + { + return CreateFile(lpFileName, dwDesiredAccess, dwShareMode, ref securityAttrs, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); + } + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.WideCharToMultiByte.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.WideCharToMultiByte.cs new file mode 100644 index 0000000..b1a2975 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.WideCharToMultiByte.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class mincore + { + [DllImport(Libraries.String_L1)] + internal static extern unsafe int WideCharToMultiByte( + uint CodePage, uint dwFlags, + char* lpWideCharStr, int cchWideChar, + byte* lpMultiByteStr, int cbMultiByte, + IntPtr lpDefaultChar, IntPtr lpUsedDefaultChar); + + internal const uint CP_ACP = 0; + internal const uint WC_NO_BEST_FIT_CHARS = 0x00000400; + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.WriteFile_SafeHandle_IntPtr.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.WriteFile_SafeHandle_IntPtr.cs new file mode 100644 index 0000000..052ba3c --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.WriteFile_SafeHandle_IntPtr.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. +// See the LICENSE file in the project root for more information. + +using Microsoft.Win32.SafeHandles; +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class mincore + { + // Note there are two different WriteFile prototypes - this is to use + // the type system to force you to not trip across a "feature" in + // Win32's async IO support. You can't do the following three things + // simultaneously: overlapped IO, free the memory for the overlapped + // struct in a callback (or an EndWrite method called by that callback), + // and pass in an address for the numBytesRead parameter. + + [DllImport(Libraries.CoreFile_L1, SetLastError = true)] + internal static unsafe extern int WriteFile(SafeHandle handle, byte* bytes, int numBytesToWrite, out int numBytesWritten, IntPtr mustBeZero); + + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/mincore/Interop.WriteFile_SafeHandle_NativeOverlapped.cs b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.WriteFile_SafeHandle_NativeOverlapped.cs new file mode 100644 index 0000000..e9d2953 --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/mincore/Interop.WriteFile_SafeHandle_NativeOverlapped.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. +// See the LICENSE file in the project root for more information. + +using Microsoft.Win32.SafeHandles; +using System; +using System.Runtime.InteropServices; +using System.Threading; +internal partial class Interop +{ + internal partial class mincore + { + // Note there are two different WriteFile prototypes - this is to use + // the type system to force you to not trip across a "feature" in + // Win32's async IO support. You can't do the following three things + // simultaneously: overlapped IO, free the memory for the overlapped + // struct in a callback (or an EndWrite method called by that callback), + // and pass in an address for the numBytesRead parameter. + [DllImport(Libraries.CoreFile_L1, SetLastError = true)] + internal static unsafe extern int WriteFile(SafeHandle handle, byte* bytes, int numBytesToWrite, IntPtr numBytesWritten_mustBeZero, NativeOverlapped* lpOverlapped); + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/oleaut32/Interop.SysAllocStringLen.cs b/src/mscorlib/corefx/Interop/Windows/oleaut32/Interop.SysAllocStringLen.cs new file mode 100644 index 0000000..65da4ea --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/oleaut32/Interop.SysAllocStringLen.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using System.Security; + +internal partial class Interop +{ + internal partial class OleAut32 + { + [DllImport(Libraries.OleAut32, CharSet = CharSet.Unicode)] + internal static extern SafeBSTRHandle SysAllocStringLen(IntPtr src, uint len); // BSTR + } +} diff --git a/src/mscorlib/corefx/Interop/Windows/oleaut32/Interop.SysStringLen.cs b/src/mscorlib/corefx/Interop/Windows/oleaut32/Interop.SysStringLen.cs new file mode 100644 index 0000000..027d8ee --- /dev/null +++ b/src/mscorlib/corefx/Interop/Windows/oleaut32/Interop.SysStringLen.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using System.Security; + +internal partial class Interop +{ + internal partial class OleAut32 + { + [DllImport(Libraries.OleAut32)] + internal static extern uint SysStringLen(SafeBSTRHandle bstr); + + [DllImport(Libraries.OleAut32)] + internal static extern uint SysStringLen(IntPtr bstr); + + [DllImport(Libraries.OleAut32)] + internal static extern void SysFreeString(IntPtr bstr); + } +} diff --git a/src/mscorlib/corefx/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs b/src/mscorlib/corefx/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs new file mode 100644 index 0000000..5ddb31a --- /dev/null +++ b/src/mscorlib/corefx/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs @@ -0,0 +1,122 @@ +// 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.Diagnostics; +using System.Runtime.InteropServices; + +namespace Microsoft.Win32.SafeHandles +{ + [System.Security.SecurityCritical] + public sealed class SafeFileHandle : SafeHandleZeroOrMinusOneIsInvalid + { + /// A handle value of -1. + private static readonly IntPtr s_invalidHandle = new IntPtr(-1); + + private SafeFileHandle() : this(ownsHandle: true) + { + } + + private SafeFileHandle(bool ownsHandle) + : base(ownsHandle) + { + SetHandle(s_invalidHandle); + } + + public SafeFileHandle(IntPtr preexistingHandle, bool ownsHandle) : this(ownsHandle) + { + SetHandle(preexistingHandle); + } + + internal bool? IsAsync { get; set; } + + /// Opens the specified file with the requested flags and mode. + /// The path to the file. + /// The flags with which to open the file. + /// The mode for opening the file. + /// A SafeFileHandle for the opened file. + internal static SafeFileHandle Open(string path, Interop.Sys.OpenFlags flags, int mode) + { + Debug.Assert(path != null); + + // If we fail to open the file due to a path not existing, we need to know whether to blame + // the file itself or its directory. If we're creating the file, then we blame the directory, + // otherwise we blame the file. + bool enoentDueToDirectory = (flags & Interop.Sys.OpenFlags.O_CREAT) != 0; + + // Open the file. + SafeFileHandle handle = Interop.CheckIo( + Interop.Sys.Open(path, flags, mode), + path, + isDirectory: enoentDueToDirectory, + errorRewriter: e => (e.Error == Interop.Error.EISDIR) ? Interop.Error.EACCES.Info() : e); + + // Make sure it's not a directory; we do this after opening it once we have a file descriptor + // to avoid race conditions. + Interop.Sys.FileStatus status; + if (Interop.Sys.FStat(handle, out status) != 0) + { + handle.Dispose(); + throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo(), path); + } + if ((status.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR) + { + handle.Dispose(); + throw Interop.GetExceptionForIoErrno(Interop.Error.EACCES.Info(), path, isDirectory: true); + } + + return handle; + } + + /// Opens a SafeFileHandle for a file descriptor created by a provided delegate. + /// + /// The function that creates the file descriptor. Returns the file descriptor on success, or an invalid + /// file descriptor on error with Marshal.GetLastWin32Error() set to the error code. + /// + /// The created SafeFileHandle. + internal static SafeFileHandle Open(Func fdFunc) + { + SafeFileHandle handle = Interop.CheckIo(fdFunc()); + + Debug.Assert(!handle.IsInvalid, "File descriptor is invalid"); + return handle; + } + + [System.Security.SecurityCritical] + protected override bool ReleaseHandle() + { + // When the SafeFileHandle was opened, we likely issued an flock on the created descriptor in order to add + // an advisory lock. This lock should be removed via closing the file descriptor, but close can be + // interrupted, and we don't retry closes. As such, we could end up leaving the file locked, + // which could prevent subsequent usage of the file until this process dies. To avoid that, we proactively + // try to release the lock before we close the handle. (If it's not locked, there's no behavioral + // problem trying to unlock it.) + Interop.Sys.FLock(handle, Interop.Sys.LockOperations.LOCK_UN); // ignore any errors + + // Close the descriptor. Although close is documented to potentially fail with EINTR, we never want + // to retry, as the descriptor could actually have been closed, been subsequently reassigned, and + // be in use elsewhere in the process. Instead, we simply check whether the call was successful. + int result = Interop.Sys.Close(handle); +#if DEBUG + if (result != 0) + { + Debug.Fail(string.Format( + "Close failed with result {0} and error {1}", + result, Interop.Sys.GetLastErrorInfo())); + } +#endif + return result == 0; + } + + public override bool IsInvalid + { + [System.Security.SecurityCritical] + get + { + long h = (long)handle; + return h < 0 || h > int.MaxValue; + } + } + } +} diff --git a/src/mscorlib/corefx/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs b/src/mscorlib/corefx/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs new file mode 100644 index 0000000..7d4dd44 --- /dev/null +++ b/src/mscorlib/corefx/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Security; +using System.Runtime.InteropServices; +using System.Threading; +using Microsoft.Win32; + +namespace Microsoft.Win32.SafeHandles +{ + public sealed class SafeFileHandle : SafeHandleZeroOrMinusOneIsInvalid + { + private bool? _isAsync; + + private SafeFileHandle() : base(true) + { + _isAsync = null; + } + + public SafeFileHandle(IntPtr preexistingHandle, bool ownsHandle) : base(ownsHandle) + { + SetHandle(preexistingHandle); + + _isAsync = null; + } + + internal bool? IsAsync + { + get + { + return _isAsync; + } + + set + { + _isAsync = value; + } + } + + internal ThreadPoolBoundHandle ThreadPoolBinding { get; set; } + + override protected bool ReleaseHandle() + { + return Interop.mincore.CloseHandle(handle); + } + } +} + diff --git a/src/mscorlib/corefx/Microsoft/Win32/SafeHandles/SafeThreadPoolIOHandle.cs b/src/mscorlib/corefx/Microsoft/Win32/SafeHandles/SafeThreadPoolIOHandle.cs new file mode 100644 index 0000000..3dbc2bb --- /dev/null +++ b/src/mscorlib/corefx/Microsoft/Win32/SafeHandles/SafeThreadPoolIOHandle.cs @@ -0,0 +1,28 @@ +// 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.Runtime.InteropServices; + +namespace Microsoft.Win32.SafeHandles +{ + internal class SafeThreadPoolIOHandle : SafeHandle + { + private SafeThreadPoolIOHandle() + : base(IntPtr.Zero, true) + { + } + + public override bool IsInvalid + { + get { return handle == IntPtr.Zero; } + } + + protected override bool ReleaseHandle() + { + Interop.mincore.CloseThreadpoolIo(handle); + return true; + } + } +} diff --git a/src/mscorlib/corefx/SR.cs b/src/mscorlib/corefx/SR.cs index 513bd9d..d820613 100644 --- a/src/mscorlib/corefx/SR.cs +++ b/src/mscorlib/corefx/SR.cs @@ -1,247 +1,588 @@ using System; +using System.Globalization; -namespace System.Globalization +// CoreFX creates SR in the System namespace. While putting the CoreCLR SR adapter in the root +// may be unconventional, it allows us to keep the shared code identical. + +internal static class SR { - internal static class SR - { - public static string Arg_HexStyleNotSupported - { - get { return Environment.GetResourceString("Arg_HexStyleNotSupported"); } - } - - public static string Arg_InvalidHexStyle - { - get { return Environment.GetResourceString("Arg_InvalidHexStyle"); } - } - - public static string ArgumentNull_Array - { - get { return Environment.GetResourceString("ArgumentNull_Array"); } - } - - public static string ArgumentNull_ArrayValue - { - get { return Environment.GetResourceString("ArgumentNull_ArrayValue"); } - } - - public static string ArgumentNull_Obj - { - get { return Environment.GetResourceString("ArgumentNull_Obj"); } - } - - public static string ArgumentNull_String - { - get { return Environment.GetResourceString("ArgumentNull_String"); } - } - - public static string ArgumentOutOfRange_AddValue - { - get { return Environment.GetResourceString("ArgumentOutOfRange_AddValue"); } - } - - public static string ArgumentOutOfRange_BadHourMinuteSecond - { - get { return Environment.GetResourceString("ArgumentOutOfRange_BadHourMinuteSecond"); } - } - - public static string ArgumentOutOfRange_BadYearMonthDay - { - get { return Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay"); } - } - - public static string ArgumentOutOfRange_Bounds_Lower_Upper - { - get { return Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper"); } - } - - public static string ArgumentOutOfRange_CalendarRange - { - get { return Environment.GetResourceString("ArgumentOutOfRange_CalendarRange"); } - } - - public static string ArgumentOutOfRange_Count - { - get { return Environment.GetResourceString("ArgumentOutOfRange_Count"); } - } - - public static string ArgumentOutOfRange_Day - { - get { return Environment.GetResourceString("ArgumentOutOfRange_Day"); } - } - - public static string ArgumentOutOfRange_Enum - { - get { return Environment.GetResourceString("ArgumentOutOfRange_Enum"); } - } - - public static string ArgumentOutOfRange_Era - { - get { return Environment.GetResourceString("ArgumentOutOfRange_Era"); } - } - - public static string ArgumentOutOfRange_Index - { - get { return Environment.GetResourceString("ArgumentOutOfRange_Index"); } - } - - public static string ArgumentOutOfRange_InvalidEraValue - { - get { return Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"); } - } - - public static string ArgumentOutOfRange_Month - { - get { return Environment.GetResourceString("ArgumentOutOfRange_Month"); } - } - - public static string ArgumentOutOfRange_NeedNonNegNum - { - get { return Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"); } - } - - public static string ArgumentOutOfRange_NeedPosNum - { - get { return Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"); } - } - - public static string ArgumentOutOfRange_OffsetLength - { - get { return Environment.GetResourceString("ArgumentOutOfRange_OffsetLength"); } - } - - public static string ArgumentOutOfRange_Range - { - get { return Environment.GetResourceString("ArgumentOutOfRange_Range"); } - } - - public static string Argument_CompareOptionOrdinal - { - get { return Environment.GetResourceString("Argument_CompareOptionOrdinal"); } - } - - public static string Argument_ConflictingDateTimeRoundtripStyles - { - get { return Environment.GetResourceString("Argument_ConflictingDateTimeRoundtripStyles"); } - } - - public static string Argument_ConflictingDateTimeStyles - { - get { return Environment.GetResourceString("Argument_ConflictingDateTimeStyles"); } - } - - public static string Argument_CultureInvalidIdentifier - { - get { return Environment.GetResourceString("Argument_CultureInvalidIdentifier"); } - } - - public static string Argument_CultureNotSupported - { - get { return Environment.GetResourceString("Argument_CultureNotSupported"); } - } + public static string Arg_ArrayZeroError + { + get { return Environment.GetResourceString("Arg_ArrayZeroError"); } + } + + public static string Arg_ExternalException + { + get { return Environment.GetResourceString("Arg_ExternalException"); } + } + + public static string Arg_HexStyleNotSupported + { + get { return Environment.GetResourceString("Arg_HexStyleNotSupported"); } + } + + public static string Arg_InvalidHexStyle + { + get { return Environment.GetResourceString("Arg_InvalidHexStyle"); } + } + + public static string ArgumentNull_Array + { + get { return Environment.GetResourceString("ArgumentNull_Array"); } + } + + public static string ArgumentNull_ArrayValue + { + get { return Environment.GetResourceString("ArgumentNull_ArrayValue"); } + } + + public static string ArgumentNull_Obj + { + get { return Environment.GetResourceString("ArgumentNull_Obj"); } + } + + public static string ArgumentNull_String + { + get { return Environment.GetResourceString("ArgumentNull_String"); } + } + + public static string ArgumentOutOfRange_AddValue + { + get { return Environment.GetResourceString("ArgumentOutOfRange_AddValue"); } + } + + public static string ArgumentOutOfRange_BadHourMinuteSecond + { + get { return Environment.GetResourceString("ArgumentOutOfRange_BadHourMinuteSecond"); } + } + + public static string ArgumentOutOfRange_BadYearMonthDay + { + get { return Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay"); } + } + + public static string ArgumentOutOfRange_Bounds_Lower_Upper + { + get { return Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper"); } + } + + public static string ArgumentOutOfRange_CalendarRange + { + get { return Environment.GetResourceString("ArgumentOutOfRange_CalendarRange"); } + } + + public static string ArgumentOutOfRange_Count + { + get { return Environment.GetResourceString("ArgumentOutOfRange_Count"); } + } + + public static string ArgumentOutOfRange_Day + { + get { return Environment.GetResourceString("ArgumentOutOfRange_Day"); } + } + + public static string ArgumentOutOfRange_Enum + { + get { return Environment.GetResourceString("ArgumentOutOfRange_Enum"); } + } + + public static string ArgumentOutOfRange_Era + { + get { return Environment.GetResourceString("ArgumentOutOfRange_Era"); } + } + + public static string ArgumentOutOfRange_Index + { + get { return Environment.GetResourceString("ArgumentOutOfRange_Index"); } + } + + public static string ArgumentOutOfRange_IndexCountBuffer + { + get { return Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"); } + } + + public static string ArgumentOutOfRange_InvalidEraValue + { + get { return Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"); } + } + + public static string ArgumentOutOfRange_Month + { + get { return Environment.GetResourceString("ArgumentOutOfRange_Month"); } + } + + public static string ArgumentOutOfRange_NeedNonNegNum + { + get { return Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"); } + } + + public static string ArgumentOutOfRange_NeedPosNum + { + get { return Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"); } + } + + public static string Arg_ArgumentOutOfRangeException + { + get { return Environment.GetResourceString("Arg_ArgumentOutOfRangeException"); } + } + + public static string ArgumentOutOfRange_OffsetLength + { + get { return Environment.GetResourceString("ArgumentOutOfRange_OffsetLength"); } + } + + public static string ArgumentOutOfRange_Range + { + get { return Environment.GetResourceString("ArgumentOutOfRange_Range"); } + } + + public static string Argument_CompareOptionOrdinal + { + get { return Environment.GetResourceString("Argument_CompareOptionOrdinal"); } + } + + public static string Argument_ConflictingDateTimeRoundtripStyles + { + get { return Environment.GetResourceString("Argument_ConflictingDateTimeRoundtripStyles"); } + } + + public static string Argument_ConflictingDateTimeStyles + { + get { return Environment.GetResourceString("Argument_ConflictingDateTimeStyles"); } + } + + public static string Argument_CultureIetfNotSupported + { + get { return Environment.GetResourceString("Argument_CultureIetfNotSupported"); } + } + + public static string Argument_CultureInvalidIdentifier + { + get { return Environment.GetResourceString("Argument_CultureInvalidIdentifier"); } + } + + public static string Argument_CultureNotSupported + { + get { return Environment.GetResourceString("Argument_CultureNotSupported"); } + } + + public static string Argument_CultureIsNeutral + { + get { return Environment.GetResourceString("Argument_CultureIsNeutral"); } + } + + public static string Argument_CustomCultureCannotBePassedByNumber + { + get { return Environment.GetResourceString("Argument_CustomCultureCannotBePassedByNumber"); } + } - public static string Argument_EmptyDecString - { - get { return Environment.GetResourceString("Argument_EmptyDecString"); } - } - - public static string Argument_InvalidArrayLength - { - get { return Environment.GetResourceString("Argument_InvalidArrayLength"); } - } - - public static string Argument_InvalidCalendar - { - get { return Environment.GetResourceString("Argument_InvalidCalendar"); } - } - - public static string Argument_InvalidCultureName - { - get { return Environment.GetResourceString("Argument_InvalidCultureName"); } - } - - public static string Argument_InvalidDateTimeStyles - { - get { return Environment.GetResourceString("Argument_InvalidDateTimeStyles"); } - } - - public static string Argument_InvalidFlag - { - get { return Environment.GetResourceString("Argument_InvalidFlag"); } - } - - public static string Argument_InvalidGroupSize - { - get { return Environment.GetResourceString("Argument_InvalidGroupSize"); } - } - - public static string Argument_InvalidNeutralRegionName - { - get { return Environment.GetResourceString("Argument_InvalidNeutralRegionName"); } - } - - public static string Argument_InvalidNumberStyles - { - get { return Environment.GetResourceString("Argument_InvalidNumberStyles"); } - } - - public static string Argument_InvalidResourceCultureName - { - get { return Environment.GetResourceString("Argument_InvalidResourceCultureName"); } - } - - public static string Argument_NoEra - { - get { return Environment.GetResourceString("Argument_NoEra"); } - } - - public static string Argument_NoRegionInvariantCulture - { - get { return Environment.GetResourceString("Argument_NoRegionInvariantCulture"); } - } - - public static string Argument_ResultCalendarRange - { - get { return Environment.GetResourceString("Argument_ResultCalendarRange"); } - } - - public static string Format_BadFormatSpecifier - { - get { return Environment.GetResourceString("Format_BadFormatSpecifier"); } - } - - public static string InvalidOperation_DateTimeParsing - { - get { return Environment.GetResourceString("InvalidOperation_DateTimeParsing"); } - } - - public static string InvalidOperation_EnumEnded - { - get { return Environment.GetResourceString("InvalidOperation_EnumEnded"); } - } - - public static string InvalidOperation_EnumNotStarted - { - get { return Environment.GetResourceString("InvalidOperation_EnumNotStarted"); } - } - - public static string InvalidOperation_ReadOnly - { - get { return Environment.GetResourceString("InvalidOperation_ReadOnly"); } - } - - public static string Overflow_TimeSpanTooLong - { - get { return Environment.GetResourceString("Overflow_TimeSpanTooLong"); } - } - - public static string Serialization_MemberOutOfRange - { - get { return Environment.GetResourceString("Serialization_MemberOutOfRange"); } - } - - public static string Format(string formatString, params object[] args) - { - return string.Format(CultureInfo.CurrentCulture, formatString, args); - } + public static string Argument_EmptyDecString + { + get { return Environment.GetResourceString("Argument_EmptyDecString"); } + } + + public static string Argument_IdnBadLabelSize + { + get { return Environment.GetResourceString("Argument_IdnBadLabelSize"); } + } + + public static string Argument_IdnBadPunycode + { + get { return Environment.GetResourceString("Argument_IdnBadPunycode"); } + } + + public static string Argument_IdnIllegalName + { + get { return Environment.GetResourceString("Argument_IdnIllegalName"); } + } + + public static string Argument_InvalidArrayLength + { + get { return Environment.GetResourceString("Argument_InvalidArrayLength"); } + } + + public static string Argument_InvalidCalendar + { + get { return Environment.GetResourceString("Argument_InvalidCalendar"); } + } + + public static string Argument_InvalidCharSequence + { + get { return Environment.GetResourceString("Argument_InvalidCharSequence"); } + } + + public static string Argument_InvalidCultureName + { + get { return Environment.GetResourceString("Argument_InvalidCultureName"); } + } + + public static string Argument_InvalidDateTimeStyles + { + get { return Environment.GetResourceString("Argument_InvalidDateTimeStyles"); } + } + + public static string Argument_InvalidDigitSubstitution + { + get { return Environment.GetResourceString("Argument_InvalidDigitSubstitution"); } + } + + public static string Argument_InvalidFlag + { + get { return Environment.GetResourceString("Argument_InvalidFlag"); } + } + + public static string Argument_InvalidGroupSize + { + get { return Environment.GetResourceString("Argument_InvalidGroupSize"); } + } + + public static string Argument_InvalidNativeDigitCount + { + get { return Environment.GetResourceString("Argument_InvalidNativeDigitCount"); } + } + + public static string Argument_InvalidNativeDigitValue + { + get { return Environment.GetResourceString("Argument_InvalidNativeDigitValue"); } + } + + public static string Argument_InvalidNeutralRegionName + { + get { return Environment.GetResourceString("Argument_InvalidNeutralRegionName"); } + } + + public static string Argument_InvalidNumberStyles + { + get { return Environment.GetResourceString("Argument_InvalidNumberStyles"); } + } + + public static string Argument_InvalidResourceCultureName + { + get { return Environment.GetResourceString("Argument_InvalidResourceCultureName"); } + } + + public static string Argument_NoEra + { + get { return Environment.GetResourceString("Argument_NoEra"); } + } + + public static string Argument_NoRegionInvariantCulture + { + get { return Environment.GetResourceString("Argument_NoRegionInvariantCulture"); } + } + + public static string Argument_OneOfCulturesNotSupported + { + get { return Environment.GetResourceString("Argument_OneOfCulturesNotSupported"); } + } + + public static string Argument_OnlyMscorlib + { + get { return Environment.GetResourceString("Argument_OnlyMscorlib"); } + } + + public static string Argument_ResultCalendarRange + { + get { return Environment.GetResourceString("Argument_ResultCalendarRange"); } + } + + public static string Format_BadFormatSpecifier + { + get { return Environment.GetResourceString("Format_BadFormatSpecifier"); } + } + + public static string InvalidOperation_DateTimeParsing + { + get { return Environment.GetResourceString("InvalidOperation_DateTimeParsing"); } + } + + public static string InvalidOperation_EnumEnded + { + get { return Environment.GetResourceString("InvalidOperation_EnumEnded"); } + } + + public static string InvalidOperation_EnumNotStarted + { + get { return Environment.GetResourceString("InvalidOperation_EnumNotStarted"); } + } + + public static string InvalidOperation_ReadOnly + { + get { return Environment.GetResourceString("InvalidOperation_ReadOnly"); } + } + + public static string Overflow_TimeSpanTooLong + { + get { return Environment.GetResourceString("Overflow_TimeSpanTooLong"); } + } + + public static string Serialization_MemberOutOfRange + { + get { return Environment.GetResourceString("Serialization_MemberOutOfRange"); } + } + + public static string Arg_InvalidHandle + { + get { return Environment.GetResourceString("Arg_InvalidHandle"); } + } + + public static string ObjectDisposed_FileClosed + { + get { return Environment.GetResourceString("ObjectDisposed_FileClosed"); } + } + + public static string Arg_HandleNotAsync + { + get { return Environment.GetResourceString("Arg_HandleNotAsync"); } + } + + public static string ArgumentNull_Path + { + get { return Environment.GetResourceString("ArgumentNull_Path"); } + } + + public static string Argument_EmptyPath + { + get { return Environment.GetResourceString("Argument_EmptyPath"); } + } + + public static string Argument_InvalidFileModeAndAccessCombo + { + get { return Environment.GetResourceString("Argument_InvalidFileMode&AccessCombo"); } + } + + public static string Argument_InvalidAppendMode + { + get { return Environment.GetResourceString("Argument_InvalidAppendMode"); } + } + + public static string ArgumentNull_Buffer + { + get { return Environment.GetResourceString("ArgumentNull_Buffer"); } + } + + public static string Argument_InvalidOffLen + { + get { return Environment.GetResourceString("Argument_InvalidOffLen"); } + } + + public static string IO_UnknownFileName + { + get { return Environment.GetResourceString("IO_UnknownFileName"); } + } + + public static string IO_FileStreamHandlePosition + { + get { return Environment.GetResourceString("IO.IO_FileStreamHandlePosition"); } + } + + public static string NotSupported_FileStreamOnNonFiles + { + get { return Environment.GetResourceString("NotSupported_FileStreamOnNonFiles"); } + } + + public static string IO_BindHandleFailed + { + get { return Environment.GetResourceString("IO.IO_BindHandleFailed"); } + } + + public static string Arg_HandleNotSync + { + get { return Environment.GetResourceString("Arg_HandleNotSync"); } + } + + public static string IO_SetLengthAppendTruncate + { + get { return Environment.GetResourceString("IO.IO_SetLengthAppendTruncate"); } + } + + public static string ArgumentOutOfRange_FileLengthTooBig + { + get { return Environment.GetResourceString("ArgumentOutOfRange_FileLengthTooBig"); } + } + + public static string Argument_InvalidSeekOrigin + { + get { return Environment.GetResourceString("Argument_InvalidSeekOrigin"); } + } + + public static string IO_SeekAppendOverwrite + { + get { return Environment.GetResourceString("IO.IO_SeekAppendOverwrite"); } + } + + public static string IO_FileTooLongOrHandleNotSync + { + get { return Environment.GetResourceString("IO_FileTooLongOrHandleNotSync"); } + } + + public static string IndexOutOfRange_IORaceCondition + { + get { return Environment.GetResourceString("IndexOutOfRange_IORaceCondition"); } + } + + public static string IO_FileNotFound + { + get { return Environment.GetResourceString("IO.FileNotFound"); } + } + + public static string IO_FileNotFound_FileName + { + get { return Environment.GetResourceString("IO.FileNotFound_FileName"); } + } + + public static string IO_PathNotFound_NoPathName + { + get { return Environment.GetResourceString("IO.PathNotFound_NoPathName"); } + } + + public static string IO_PathNotFound_Path + { + get { return Environment.GetResourceString("IO.PathNotFound_Path"); } + } + + public static string UnauthorizedAccess_IODenied_NoPathName + { + get { return Environment.GetResourceString("UnauthorizedAccess_IODenied_NoPathName"); } + } + + public static string UnauthorizedAccess_IODenied_Path + { + get { return Environment.GetResourceString("UnauthorizedAccess_IODenied_Path"); } + } + + public static string IO_AlreadyExists_Name + { + get { return Environment.GetResourceString("IO.IO_AlreadyExists_Name"); } + } + + public static string IO_PathTooLong + { + get { return Environment.GetResourceString("IO.PathTooLong"); } + } + + public static string IO_SharingViolation_NoFileName + { + get { return Environment.GetResourceString("IO.IO_SharingViolation_NoFileName"); } + } + + public static string IO_SharingViolation_File + { + get { return Environment.GetResourceString("IO.IO_SharingViolation_File"); } + } + + public static string IO_FileExists_Name + { + get { return Environment.GetResourceString("IO.IO_FileExists_Name"); } + } + + public static string NotSupported_UnwritableStream + { + get { return Environment.GetResourceString("NotSupported_UnwritableStream"); } + } + + public static string NotSupported_UnreadableStream + { + get { return Environment.GetResourceString("NotSupported_UnreadableStream"); } + } + + public static string NotSupported_UnseekableStream + { + get { return Environment.GetResourceString("NotSupported_UnseekableStream"); } + } + + public static string IO_EOF_ReadBeyondEOF + { + get { return Environment.GetResourceString("IO.EOF_ReadBeyondEOF"); } + } + + public static string Argument_InvalidHandle + { + get { return Environment.GetResourceString("Argument_InvalidHandle"); } + } + + public static string Argument_AlreadyBoundOrSyncHandle + { + get { return Environment.GetResourceString("Argument_AlreadyBoundOrSyncHandle"); } + } + + public static string Argument_PreAllocatedAlreadyAllocated + { + get { return Environment.GetResourceString("Argument_PreAllocatedAlreadyAllocated"); } + } + + public static string Argument_NativeOverlappedAlreadyFree + { + get { return Environment.GetResourceString("Argument_NativeOverlappedAlreadyFree"); } + } + + public static string Argument_NativeOverlappedWrongBoundHandle + { + get { return Environment.GetResourceString("Argument_NativeOverlappedWrongBoundHandle"); } + } + + public static string InvalidOperation_NativeOverlappedReused + { + get { return Environment.GetResourceString("InvalidOperation_NativeOverlappedReused"); } + } + + public static string ArgumentOutOfRange_Length + { + get { return Environment.GetResourceString("ArgumentOutOfRange_Length"); } + } + + public static string ArgumentOutOfRange_IndexString + { + get { return Environment.GetResourceString("ArgumentOutOfRange_IndexString"); } + } + + public static string ArgumentOutOfRange_Capacity + { + get { return Environment.GetResourceString("ArgumentOutOfRange_Capacity"); } + } + + public static string Arg_CryptographyException + { + get { return Environment.GetResourceString("Arg_CryptographyException"); } + } + + public static string ArgumentException_BufferNotFromPool + { + get { return Environment.GetResourceString("ArgumentException_BufferNotFromPool"); } + } + + public static string Argument_InvalidPathChars + { + get { return Environment.GetResourceString("Argument_InvalidPathChars"); } + } + + public static string Argument_PathFormatNotSupported + { + get { return Environment.GetResourceString("Argument_PathFormatNotSupported"); } + } + + public static string Arg_PathIllegal + { + get { return Environment.GetResourceString("Arg_PathIllegal"); } + } + + public static string Arg_PathIllegalUNC + { + get { return Environment.GetResourceString("Arg_PathIllegalUNC"); } + } + + public static string Arg_InvalidSearchPattern + { + get { return Environment.GetResourceString("Arg_InvalidSearchPattern"); } + } + + public static string InvalidOperation_Cryptography + { + get { return Environment.GetResourceString("InvalidOperation_Cryptography"); } + } + + public static string Format(string formatString, params object[] args) + { + return string.Format(CultureInfo.CurrentCulture, formatString, args); } } diff --git a/src/mscorlib/corefx/System/Buffers/ArrayPool.cs b/src/mscorlib/corefx/System/Buffers/ArrayPool.cs new file mode 100644 index 0000000..441e48d --- /dev/null +++ b/src/mscorlib/corefx/System/Buffers/ArrayPool.cs @@ -0,0 +1,113 @@ +// 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. + +namespace System.Buffers +{ + /// + /// Provides a resource pool that enables reusing instances of type . + /// + /// + /// + /// Renting and returning buffers with an can increase performance + /// in situations where arrays are created and destroyed frequently, resulting in significant + /// memory pressure on the garbage collector. + /// + /// + /// This class is thread-safe. All members may be used by multiple threads concurrently. + /// + /// + public abstract class ArrayPool + { + /// + /// Retrieves a shared instance. + /// + /// + /// The shared pool provides a default implementation of + /// that's intended for general applicability. It maintains arrays of multiple sizes, and + /// may hand back a larger array than was actually requested, but will never hand back a smaller + /// array than was requested. Renting a buffer from it with will result in an + /// existing buffer being taken from the pool if an appropriate buffer is available or in a new + /// buffer being allocated if one is not available. + /// + public static ArrayPool Shared => SharedPool.Value; + + /// Stores a cached pool instance for T[]. + /// + /// Separated out into a nested class to enable lazy-initialization of the pool provided by + /// the runtime, only forced when Shared is used (and not when Create is called or when + /// other non-Shared accesses happen). + /// + private static class SharedPool + { + /// Per-type cached pool. + /// + /// byte[] and char[] are the most commonly pooled array types. For these we use a special pool type + /// optimized for very fast access speeds, at the expense of more memory consumption. + /// + internal readonly static ArrayPool Value = + typeof(T) == typeof(byte) || typeof(T) == typeof(char) ? new TlsOverPerCoreLockedStacksArrayPool() : + Create(); + } + + /// + /// Creates a new instance using default configuration options. + /// + /// A new instance. + public static ArrayPool Create() => new ConfigurableArrayPool(); + + /// + /// Creates a new instance using custom configuration options. + /// + /// The maximum length of array instances that may be stored in the pool. + /// + /// The maximum number of array instances that may be stored in each bucket in the pool. The pool + /// groups arrays of similar lengths into buckets for faster access. + /// + /// A new instance with the specified configuration options. + /// + /// The created pool will group arrays into buckets, with no more than + /// in each bucket and with those arrays not exceeding in length. + /// + public static ArrayPool Create(int maxArrayLength, int maxArraysPerBucket) => + new ConfigurableArrayPool(maxArrayLength, maxArraysPerBucket); + + /// + /// Retrieves a buffer that is at least the requested length. + /// + /// The minimum length of the array needed. + /// + /// An that is at least in length. + /// + /// + /// This buffer is loaned to the caller and should be returned to the same pool via + /// so that it may be reused in subsequent usage of . + /// It is not a fatal error to not return a rented buffer, but failure to do so may lead to + /// decreased application performance, as the pool may need to create a new buffer to replace + /// the one lost. + /// + public abstract T[] Rent(int minimumLength); + + /// + /// Returns to the pool an array that was previously obtained via on the same + /// instance. + /// + /// + /// The buffer previously obtained from to return to the pool. + /// + /// + /// If true and if the pool will store the buffer to enable subsequent reuse, + /// will clear of its contents so that a subsequent consumer via + /// will not see the previous consumer's content. If false or if the pool will release the buffer, + /// the array's contents are left unchanged. + /// + /// + /// Once a buffer has been returned to the pool, the caller gives up all ownership of the buffer + /// and must not use it. The reference returned from a given call to must only be + /// returned via once. The default + /// may hold onto the returned buffer in order to rent it again, or it may release the returned buffer + /// if it's determined that the pool already has enough buffers stored. + /// + public abstract void Return(T[] array, bool clearArray = false); + } +} diff --git a/src/mscorlib/corefx/System/Buffers/ArrayPoolEventSource.cs b/src/mscorlib/corefx/System/Buffers/ArrayPoolEventSource.cs new file mode 100644 index 0000000..9482744 --- /dev/null +++ b/src/mscorlib/corefx/System/Buffers/ArrayPoolEventSource.cs @@ -0,0 +1,78 @@ +// 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.Diagnostics.Tracing; + +namespace System.Buffers +{ + [EventSource(Name = "System.Buffers.ArrayPoolEventSource")] + internal sealed class ArrayPoolEventSource : EventSource + { + internal readonly static ArrayPoolEventSource Log = new ArrayPoolEventSource(); + + /// The reason for a BufferAllocated event. + internal enum BufferAllocatedReason : int + { + /// The pool is allocating a buffer to be pooled in a bucket. + Pooled, + /// The requested buffer size was too large to be pooled. + OverMaximumSize, + /// The pool has already allocated for pooling as many buffers of a particular size as it's allowed. + PoolExhausted + } + + /// + /// Event for when a buffer is rented. This is invoked once for every successful call to Rent, + /// regardless of whether a buffer is allocated or a buffer is taken from the pool. In a + /// perfect situation where all rented buffers are returned, we expect to see the number + /// of BufferRented events exactly match the number of BuferReturned events, with the number + /// of BufferAllocated events being less than or equal to those numbers (ideally significantly + /// less than). + /// + [Event(1, Level = EventLevel.Verbose)] + internal unsafe void BufferRented(int bufferId, int bufferSize, int poolId, int bucketId) + { + EventData* payload = stackalloc EventData[4]; + payload[0].Size = sizeof(int); + payload[0].DataPointer = ((IntPtr)(&bufferId)); + payload[1].Size = sizeof(int); + payload[1].DataPointer = ((IntPtr)(&bufferSize)); + payload[2].Size = sizeof(int); + payload[2].DataPointer = ((IntPtr)(&poolId)); + payload[3].Size = sizeof(int); + payload[3].DataPointer = ((IntPtr)(&bucketId)); + WriteEventCore(1, 4, payload); + } + + /// + /// Event for when a buffer is allocated by the pool. In an ideal situation, the number + /// of BufferAllocated events is significantly smaller than the number of BufferRented and + /// BufferReturned events. + /// + [Event(2, Level = EventLevel.Informational)] + internal unsafe void BufferAllocated(int bufferId, int bufferSize, int poolId, int bucketId, BufferAllocatedReason reason) + { + EventData* payload = stackalloc EventData[5]; + payload[0].Size = sizeof(int); + payload[0].DataPointer = ((IntPtr)(&bufferId)); + payload[1].Size = sizeof(int); + payload[1].DataPointer = ((IntPtr)(&bufferSize)); + payload[2].Size = sizeof(int); + payload[2].DataPointer = ((IntPtr)(&poolId)); + payload[3].Size = sizeof(int); + payload[3].DataPointer = ((IntPtr)(&bucketId)); + payload[4].Size = sizeof(BufferAllocatedReason); + payload[4].DataPointer = ((IntPtr)(&reason)); + WriteEventCore(2, 5, payload); + } + + /// + /// Event raised when a buffer is returned to the pool. This event is raised regardless of whether + /// the returned buffer is stored or dropped. In an ideal situation, the number of BufferReturned + /// events exactly matches the number of BufferRented events. + /// + [Event(3, Level = EventLevel.Verbose)] + internal void BufferReturned(int bufferId, int bufferSize, int poolId) => WriteEvent(3, bufferId, bufferSize, poolId); + } +} diff --git a/src/mscorlib/corefx/System/Buffers/ConfigurableArrayPool.cs b/src/mscorlib/corefx/System/Buffers/ConfigurableArrayPool.cs new file mode 100644 index 0000000..1e0e769 --- /dev/null +++ b/src/mscorlib/corefx/System/Buffers/ConfigurableArrayPool.cs @@ -0,0 +1,265 @@ +// 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.Diagnostics; +using System.Threading; + +namespace System.Buffers +{ + internal sealed partial class ConfigurableArrayPool : ArrayPool + { + /// The default maximum length of each array in the pool (2^20). + private const int DefaultMaxArrayLength = 1024 * 1024; + /// The default maximum number of arrays per bucket that are available for rent. + private const int DefaultMaxNumberOfArraysPerBucket = 50; + + private readonly Bucket[] _buckets; + + internal ConfigurableArrayPool() : this(DefaultMaxArrayLength, DefaultMaxNumberOfArraysPerBucket) + { + } + + internal ConfigurableArrayPool(int maxArrayLength, int maxArraysPerBucket) + { + if (maxArrayLength <= 0) + { + throw new ArgumentOutOfRangeException(nameof(maxArrayLength)); + } + if (maxArraysPerBucket <= 0) + { + throw new ArgumentOutOfRangeException(nameof(maxArraysPerBucket)); + } + + // Our bucketing algorithm has a min length of 2^4 and a max length of 2^30. + // Constrain the actual max used to those values. + const int MinimumArrayLength = 0x10, MaximumArrayLength = 0x40000000; + if (maxArrayLength > MaximumArrayLength) + { + maxArrayLength = MaximumArrayLength; + } + else if (maxArrayLength < MinimumArrayLength) + { + maxArrayLength = MinimumArrayLength; + } + + // Create the buckets. + int poolId = Id; + int maxBuckets = Utilities.SelectBucketIndex(maxArrayLength); + var buckets = new Bucket[maxBuckets + 1]; + for (int i = 0; i < buckets.Length; i++) + { + buckets[i] = new Bucket(Utilities.GetMaxSizeForBucket(i), maxArraysPerBucket, poolId); + } + _buckets = buckets; + } + + /// Gets an ID for the pool to use with events. + private int Id => GetHashCode(); + + public override T[] Rent(int minimumLength) + { + // Arrays can't be smaller than zero. We allow requesting zero-length arrays (even though + // pooling such an array isn't valuable) as it's a valid length array, and we want the pool + // to be usable in general instead of using `new`, even for computed lengths. + if (minimumLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(minimumLength)); + } + else if (minimumLength == 0) + { + // No need for events with the empty array. Our pool is effectively infinite + // and we'll never allocate for rents and never store for returns. + return EmptyArray.Value; + } + + var log = ArrayPoolEventSource.Log; + T[] buffer = null; + + int index = Utilities.SelectBucketIndex(minimumLength); + if (index < _buckets.Length) + { + // Search for an array starting at the 'index' bucket. If the bucket is empty, bump up to the + // next higher bucket and try that one, but only try at most a few buckets. + const int MaxBucketsToTry = 2; + int i = index; + do + { + // Attempt to rent from the bucket. If we get a buffer from it, return it. + buffer = _buckets[i].Rent(); + if (buffer != null) + { + if (log.IsEnabled()) + { + log.BufferRented(buffer.GetHashCode(), buffer.Length, Id, _buckets[i].Id); + } + return buffer; + } + } + while (++i < _buckets.Length && i != index + MaxBucketsToTry); + + // The pool was exhausted for this buffer size. Allocate a new buffer with a size corresponding + // to the appropriate bucket. + buffer = new T[_buckets[index]._bufferLength]; + } + else + { + // The request was for a size too large for the pool. Allocate an array of exactly the requested length. + // When it's returned to the pool, we'll simply throw it away. + buffer = new T[minimumLength]; + } + + if (log.IsEnabled()) + { + int bufferId = buffer.GetHashCode(), bucketId = -1; // no bucket for an on-demand allocated buffer + log.BufferRented(bufferId, buffer.Length, Id, bucketId); + log.BufferAllocated(bufferId, buffer.Length, Id, bucketId, index >= _buckets.Length ? + ArrayPoolEventSource.BufferAllocatedReason.OverMaximumSize : ArrayPoolEventSource.BufferAllocatedReason.PoolExhausted); + } + + return buffer; + } + + public override void Return(T[] array, bool clearArray = false) + { + if (array == null) + { + throw new ArgumentNullException(nameof(array)); + } + else if (array.Length == 0) + { + // Ignore empty arrays. When a zero-length array is rented, we return a singleton + // rather than actually taking a buffer out of the lowest bucket. + return; + } + + // Determine with what bucket this array length is associated + int bucket = Utilities.SelectBucketIndex(array.Length); + + // If we can tell that the buffer was allocated, drop it. Otherwise, check if we have space in the pool + if (bucket < _buckets.Length) + { + // Clear the array if the user requests + if (clearArray) + { + Array.Clear(array, 0, array.Length); + } + + // Return the buffer to its bucket. In the future, we might consider having Return return false + // instead of dropping a bucket, in which case we could try to return to a lower-sized bucket, + // just as how in Rent we allow renting from a higher-sized bucket. + _buckets[bucket].Return(array); + } + + // Log that the buffer was returned + var log = ArrayPoolEventSource.Log; + if (log.IsEnabled()) + { + log.BufferReturned(array.GetHashCode(), array.Length, Id); + } + } + + /// Provides a thread-safe bucket containing buffers that can be Rent'd and Return'd. + private sealed class Bucket + { + internal readonly int _bufferLength; + private readonly T[][] _buffers; + private readonly int _poolId; + + private SpinLock _lock; // do not make this readonly; it's a mutable struct + private int _index; + + /// + /// Creates the pool with numberOfBuffers arrays where each buffer is of bufferLength length. + /// + internal Bucket(int bufferLength, int numberOfBuffers, int poolId) + { + _lock = new SpinLock(Debugger.IsAttached); // only enable thread tracking if debugger is attached; it adds non-trivial overheads to Enter/Exit + _buffers = new T[numberOfBuffers][]; + _bufferLength = bufferLength; + _poolId = poolId; + } + + /// Gets an ID for the bucket to use with events. + internal int Id => GetHashCode(); + + /// Takes an array from the bucket. If the bucket is empty, returns null. + internal T[] Rent() + { + T[][] buffers = _buffers; + T[] buffer = null; + + // While holding the lock, grab whatever is at the next available index and + // update the index. We do as little work as possible while holding the spin + // lock to minimize contention with other threads. The try/finally is + // necessary to properly handle thread aborts on platforms which have them. + bool lockTaken = false, allocateBuffer = false; + try + { + _lock.Enter(ref lockTaken); + + if (_index < buffers.Length) + { + buffer = buffers[_index]; + buffers[_index++] = null; + allocateBuffer = buffer == null; + } + } + finally + { + if (lockTaken) _lock.Exit(false); + } + + // While we were holding the lock, we grabbed whatever was at the next available index, if + // there was one. If we tried and if we got back null, that means we hadn't yet allocated + // for that slot, in which case we should do so now. + if (allocateBuffer) + { + buffer = new T[_bufferLength]; + + var log = ArrayPoolEventSource.Log; + if (log.IsEnabled()) + { + log.BufferAllocated(buffer.GetHashCode(), _bufferLength, _poolId, Id, + ArrayPoolEventSource.BufferAllocatedReason.Pooled); + } + } + + return buffer; + } + + /// + /// Attempts to return the buffer to the bucket. If successful, the buffer will be stored + /// in the bucket and true will be returned; otherwise, the buffer won't be stored, and false + /// will be returned. + /// + internal void Return(T[] array) + { + // Check to see if the buffer is the correct size for this bucket + if (array.Length != _bufferLength) + { + throw new ArgumentException(SR.ArgumentException_BufferNotFromPool, nameof(array)); + } + + // While holding the spin lock, if there's room available in the bucket, + // put the buffer into the next available slot. Otherwise, we just drop it. + // The try/finally is necessary to properly handle thread aborts on platforms + // which have them. + bool lockTaken = false; + try + { + _lock.Enter(ref lockTaken); + + if (_index != 0) + { + _buffers[--_index] = array; + } + } + finally + { + if (lockTaken) _lock.Exit(false); + } + } + } + } +} diff --git a/src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.Unix.cs b/src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.Unix.cs new file mode 100644 index 0000000..8a1d006 --- /dev/null +++ b/src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.Unix.cs @@ -0,0 +1,28 @@ +// 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 Microsoft.Win32; +using System.Runtime.CompilerServices; + +namespace System.Buffers +{ + internal sealed partial class TlsOverPerCoreLockedStacksArrayPool + { + /// Get an identifier for the current thread to use to index into the stacks. + private static int ExecutionId + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + // On Unix, CurrentProcessorNumber is implemented in terms of sched_getcpu, which + // doesn't exist on all platforms. On those it doesn't exist on, GetCurrentProcessorNumber + // returns -1. As a fallback in that case and to spread the threads across the buckets + // by default, we use the current managed thread ID as a proxy. + int id = CurrentProcessorNumber; + if (id < 0) id = Environment.CurrentManagedThreadId; + return id; + } + } + } +} diff --git a/src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.Windows.cs b/src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.Windows.cs new file mode 100644 index 0000000..d42242c --- /dev/null +++ b/src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.Windows.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. +// See the LICENSE file in the project root for more information. + +using Microsoft.Win32; +using System.Runtime.CompilerServices; +using System.Threading; + +namespace System.Buffers +{ + internal sealed partial class TlsOverPerCoreLockedStacksArrayPool : ArrayPool + { + /// Get an identifier for the current thread to use to index into the stacks. + private static int ExecutionId + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return CurrentProcessorNumber; } + } + } +} diff --git a/src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs b/src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs new file mode 100644 index 0000000..debc336 --- /dev/null +++ b/src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs @@ -0,0 +1,328 @@ +// 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 Microsoft.Win32; +using System.Runtime.CompilerServices; +using System.Threading; + +namespace System.Buffers +{ + /// + /// Provides an ArrayPool implementation meant to be used as the singleton returned from ArrayPool.Shared. + /// + /// + /// The implementation uses a tiered caching scheme, with a small per-thread cache for each array size, followed + /// by a cache per array size shared by all threads, split into per-core stacks meant to be used by threads + /// running on that core. Locks are used to protect each per-core stack, because a thread can migrate after + /// checking its processor number, because multiple threads could interleave on the same core, and because + /// a thread is allowed to check other core's buckets if its core's bucket is empty/full. + /// + internal sealed partial class TlsOverPerCoreLockedStacksArrayPool : ArrayPool + { + // TODO: #7747: "Investigate optimizing ArrayPool heuristics" + // - Explore caching in TLS more than one array per size per thread, and moving stale buffers to the global queue. + // - Explore dumping stale buffers from the global queue, similar to PinnableBufferCache (maybe merging them). + // - Explore changing the size of each per-core bucket, potentially dynamically or based on other factors like array size. + // - Explore changing number of buckets and what sizes of arrays are cached. + // - Investigate whether false sharing is causing any issues, in particular on LockedStack's count and the contents of its array. + // ... + + /// The number of buckets (array sizes) in the pool, one for each array length, starting from length 16. + private const int NumBuckets = 17; // Utilities.SelectBucketIndex(2*1024*1024) + /// Maximum number of per-core stacks to use per array size. + private const int MaxPerCorePerArraySizeStacks = 64; // selected to avoid needing to worry about processor groups + /// The maximum number of buffers to store in a bucket's global queue. + private const int MaxBuffersPerArraySizePerCore = 8; + + /// The length of arrays stored in the corresponding indices in and . + private readonly int[] _bucketArraySizes; + /// + /// An array of per-core array stacks. The slots are lazily initialized to avoid creating + /// lots of overhead for unused array sizes. + /// + private readonly PerCoreLockedStacks[] _buckets = new PerCoreLockedStacks[NumBuckets]; + /// A per-thread array of arrays, to cache one array per array size per thread. + [ThreadStatic] + private static T[][] t_tlsBuckets; + /// + /// Cached processor number used as a hint for which per-core stack to access. + /// + [ThreadStatic] + private static int? t_cachedProcessorNumber; + + /// Initialize the pool. + public TlsOverPerCoreLockedStacksArrayPool() + { + var sizes = new int[NumBuckets]; + for (int i = 0; i < sizes.Length; i++) + { + sizes[i] = Utilities.GetMaxSizeForBucket(i); + } + _bucketArraySizes = sizes; + } + + /// Allocate a new PerCoreLockedStacks and try to store it into the array. + private PerCoreLockedStacks CreatePerCoreLockedStacks(int bucketIndex) + { + var inst = new PerCoreLockedStacks(); + return Interlocked.CompareExchange(ref _buckets[bucketIndex], inst, null) ?? inst; + } + + /// Gets an ID for the pool to use with events. + private int Id => GetHashCode(); + + /// Gets the processor number associated with the current thread. + /// Uses a cached value if one exists on the current thread. + private static int CurrentProcessorNumber + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + int? num = t_cachedProcessorNumber; + if (!num.HasValue) + { + t_cachedProcessorNumber = num = Environment.CurrentProcessorNumber; + } + return num.GetValueOrDefault(); + } + } + + public override T[] Rent(int minimumLength) + { + // Arrays can't be smaller than zero. We allow requesting zero-length arrays (even though + // pooling such an array isn't valuable) as it's a valid length array, and we want the pool + // to be usable in general instead of using `new`, even for computed lengths. + if (minimumLength < 0) + { + throw new ArgumentOutOfRangeException(nameof(minimumLength)); + } + else if (minimumLength == 0) + { + // No need to log the empty array. Our pool is effectively infinite + // and we'll never allocate for rents and never store for returns. + return EmptyArray.Value; + } + + ArrayPoolEventSource log = ArrayPoolEventSource.Log; + T[] buffer; + + // Get the bucket number for the array length + int bucketIndex = Utilities.SelectBucketIndex(minimumLength); + + // If the array could come from a bucket... + if (bucketIndex < _buckets.Length) + { + // First try to get it from TLS if possible. + T[][] tlsBuckets = t_tlsBuckets; + if (tlsBuckets != null) + { + buffer = tlsBuckets[bucketIndex]; + if (buffer != null) + { + tlsBuckets[bucketIndex] = null; + if (log.IsEnabled()) + { + log.BufferRented(buffer.GetHashCode(), buffer.Length, Id, bucketIndex); + } + return buffer; + } + } + + // We couldn't get a buffer from TLS, so try the global stack. + PerCoreLockedStacks b = _buckets[bucketIndex]; + if (b != null) + { + buffer = b.TryPop(); + if (buffer != null) + { + if (log.IsEnabled()) + { + log.BufferRented(buffer.GetHashCode(), buffer.Length, Id, bucketIndex); + } + return buffer; + } + } + + // No buffer available. Allocate a new buffer with a size corresponding to the appropriate bucket. + buffer = new T[_bucketArraySizes[bucketIndex]]; + } + else + { + // The request was for a size too large for the pool. Allocate an array of exactly the requested length. + // When it's returned to the pool, we'll simply throw it away. + buffer = new T[minimumLength]; + } + + if (log.IsEnabled()) + { + int bufferId = buffer.GetHashCode(), bucketId = -1; // no bucket for an on-demand allocated buffer + log.BufferRented(bufferId, buffer.Length, Id, bucketId); + log.BufferAllocated(bufferId, buffer.Length, Id, bucketId, bucketIndex >= _buckets.Length ? + ArrayPoolEventSource.BufferAllocatedReason.OverMaximumSize : + ArrayPoolEventSource.BufferAllocatedReason.PoolExhausted); + } + + return buffer; + } + + public override void Return(T[] array, bool clearArray = false) + { + if (array == null) + { + throw new ArgumentNullException(nameof(array)); + } + + // Determine with what bucket this array length is associated + int bucketIndex = Utilities.SelectBucketIndex(array.Length); + + // If we can tell that the buffer was allocated (or empty), drop it. Otherwise, check if we have space in the pool. + if (bucketIndex < _buckets.Length) + { + // Clear the array if the user requests. + if (clearArray) + { + Array.Clear(array, 0, array.Length); + } + + // Check to see if the buffer is the correct size for this bucket + if (array.Length != _bucketArraySizes[bucketIndex]) + { + throw new ArgumentException(SR.ArgumentException_BufferNotFromPool, nameof(array)); + } + + // Write through the TLS bucket. If there weren't any buckets, create them + // and store this array into it. If there were, store this into it, and + // if there was a previous one there, push that to the global stack. This + // helps to keep LIFO access such that the most recently pushed stack will + // be in TLS and the first to be popped next. + T[][] tlsBuckets = t_tlsBuckets; + if (tlsBuckets == null) + { + t_tlsBuckets = tlsBuckets = new T[NumBuckets][]; + tlsBuckets[bucketIndex] = array; + } + else + { + T[] prev = tlsBuckets[bucketIndex]; + tlsBuckets[bucketIndex] = array; + if (prev != null) + { + PerCoreLockedStacks bucket = _buckets[bucketIndex] ?? CreatePerCoreLockedStacks(bucketIndex); + bucket.TryPush(prev); + } + } + } + + // Log that the buffer was returned + ArrayPoolEventSource log = ArrayPoolEventSource.Log; + if (log.IsEnabled()) + { + log.BufferReturned(array.GetHashCode(), array.Length, Id); + } + } + + /// + /// Stores a set of stacks of arrays, with one stack per core. + /// + private sealed class PerCoreLockedStacks + { + /// The stacks. + private readonly LockedStack[] _perCoreStacks; + + /// Initializes the stacks. + public PerCoreLockedStacks() + { + // Create the stacks. We create as many as there are processors, limited by our max. + var stacks = new LockedStack[Math.Min(Environment.ProcessorCount, MaxPerCorePerArraySizeStacks)]; + for (int i = 0; i < stacks.Length; i++) + { + stacks[i] = new LockedStack(); + } + _perCoreStacks = stacks; + } + + /// Try to push the array into the stacks. If each is full when it's tested, the array will be dropped. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void TryPush(T[] array) + { + // Try to push on to the associated stack first. If that fails, + // round-robin through the other stacks. + LockedStack[] stacks = _perCoreStacks; + int index = ExecutionId % stacks.Length; + for (int i = 0; i < stacks.Length; i++) + { + if (stacks[index].TryPush(array)) return; + if (++index == stacks.Length) index = 0; + } + } + + /// Try to get an array from the stacks. If each is empty when it's tested, null will be returned. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public T[] TryPop() + { + // Try to pop from the associated stack first. If that fails, + // round-robin through the other stacks. + T[] arr; + LockedStack[] stacks = _perCoreStacks; + int index = ExecutionId % stacks.Length; + for (int i = 0; i < stacks.Length; i++) + { + if ((arr = stacks[index].TryPop()) != null) return arr; + if (++index == stacks.Length) index = 0; + } + return null; + } + } + + /// Provides a simple stack of arrays, protected by a lock. + private sealed class LockedStack + { + private readonly T[][] _arrays = new T[MaxBuffersPerArraySizePerCore][]; + private int _count; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool TryPush(T[] array) + { + bool enqueued = false; + MonitorEnterWithProcNumberFlush(this); + if (_count < MaxBuffersPerArraySizePerCore) + { + _arrays[_count++] = array; + enqueued = true; + } + Monitor.Exit(this); + return enqueued; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public T[] TryPop() + { + T[] arr = null; + MonitorEnterWithProcNumberFlush(this); + if (_count > 0) + { + arr = _arrays[--_count]; + _arrays[_count] = null; + } + Monitor.Exit(this); + return arr; + } + + /// + /// Enters the monitor on the object. If there is any contention while trying + /// to acquire the monitor, it flushes the cached processor number so that subsequent + /// attempts to access the per-core stacks will use an updated processor number. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void MonitorEnterWithProcNumberFlush(object obj) + { + if (!Monitor.TryEnter(obj)) + { + t_cachedProcessorNumber = null; + Monitor.Enter(obj); + } + } + } + } +} diff --git a/src/mscorlib/corefx/System/Buffers/Utilities.cs b/src/mscorlib/corefx/System/Buffers/Utilities.cs new file mode 100644 index 0000000..823299f --- /dev/null +++ b/src/mscorlib/corefx/System/Buffers/Utilities.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. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace System.Buffers +{ + internal static class Utilities + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int SelectBucketIndex(int bufferSize) + { + uint bitsRemaining = ((uint)bufferSize - 1) >> 4; + + int poolIndex = 0; + if (bitsRemaining > 0xFFFF) { bitsRemaining >>= 16; poolIndex = 16; } + if (bitsRemaining > 0xFF) { bitsRemaining >>= 8; poolIndex += 8; } + if (bitsRemaining > 0xF) { bitsRemaining >>= 4; poolIndex += 4; } + if (bitsRemaining > 0x3) { bitsRemaining >>= 2; poolIndex += 2; } + if (bitsRemaining > 0x1) { bitsRemaining >>= 1; poolIndex += 1; } + + return poolIndex + (int)bitsRemaining; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int GetMaxSizeForBucket(int binIndex) + { + int maxSize = 16 << binIndex; + Debug.Assert(maxSize >= 0); + return maxSize; + } + } +} diff --git a/src/mscorlib/corefx/System/Globalization/Calendar.cs b/src/mscorlib/corefx/System/Globalization/Calendar.cs index 343682d..78e9f00 100644 --- a/src/mscorlib/corefx/System/Globalization/Calendar.cs +++ b/src/mscorlib/corefx/System/Globalization/Calendar.cs @@ -2,9 +2,7 @@ // 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.Runtime.CompilerServices; -using System.Globalization; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.Serialization; @@ -99,8 +97,14 @@ namespace System.Globalization } } - - + [System.Runtime.InteropServices.ComVisible(false)] + public virtual CalendarAlgorithmType AlgorithmType + { + get + { + return CalendarAlgorithmType.Unknown; + } + } protected Calendar() { @@ -164,9 +168,9 @@ namespace System.Globalization // //////////////////////////////////////////////////////////////////////// [System.Runtime.InteropServices.ComVisible(false)] - internal static Calendar ReadOnly(Calendar calendar) + public static Calendar ReadOnly(Calendar calendar) { - if (calendar == null) { throw new ArgumentNullException("calendar"); } + if (calendar == null) { throw new ArgumentNullException(nameof(calendar)); } Contract.EndContractBlock(); if (calendar.IsReadOnly) { return (calendar); } @@ -206,7 +210,7 @@ namespace System.Globalization // The following code assumes that the current era value can not be -1. if (_currentEraValue == -1) { - Contract.Assert(BaseCalendarID != CalendarId.UNINITIALIZED_VALUE, "[Calendar.CurrentEraValue] Expected a real calendar ID"); + Debug.Assert(BaseCalendarID != CalendarId.UNINITIALIZED_VALUE, "[Calendar.CurrentEraValue] Expected a real calendar ID"); _currentEraValue = CalendarData.GetCalendarData(BaseCalendarID).iCurrentEra; } return (_currentEraValue); @@ -242,7 +246,7 @@ namespace System.Globalization double tempMillis = (value * scale + (value >= 0 ? 0.5 : -0.5)); if (!((tempMillis > -(double)MaxMillis) && (tempMillis < (double)MaxMillis))) { - throw new ArgumentOutOfRangeException("value", SR.ArgumentOutOfRange_AddValue); + throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_AddValue); } long millis = (long)tempMillis; @@ -521,7 +525,7 @@ namespace System.Globalization // this value can be less than 0. It's fine since we are making it positive again in calculating offset. int dayForJan1 = (int)GetDayOfWeek(time) - (dayOfYear % 7); int offset = (dayForJan1 - firstDayOfWeek + 14) % 7; - Contract.Assert(offset >= 0, "Calendar.GetFirstDayWeekOfYear(): offset >= 0"); + Debug.Assert(offset >= 0, "Calendar.GetFirstDayWeekOfYear(): offset >= 0"); return ((dayOfYear + offset) / 7 + 1); } @@ -646,7 +650,7 @@ namespace System.Globalization if ((int)firstDayOfWeek < 0 || (int)firstDayOfWeek > 6) { throw new ArgumentOutOfRangeException( - "firstDayOfWeek", SR.Format(SR.ArgumentOutOfRange_Range, + nameof(firstDayOfWeek), SR.Format(SR.ArgumentOutOfRange_Range, DayOfWeek.Sunday, DayOfWeek.Saturday)); } Contract.EndContractBlock(); @@ -660,7 +664,7 @@ namespace System.Globalization return (GetWeekOfYearFullDays(time, (int)firstDayOfWeek, 4)); } throw new ArgumentOutOfRangeException( - "rule", SR.Format(SR.ArgumentOutOfRange_Range, + nameof(rule), SR.Format(SR.ArgumentOutOfRange_Range, CalendarWeekRule.FirstDay, CalendarWeekRule.FirstFourDayWeek)); } @@ -700,6 +704,16 @@ namespace System.Globalization public abstract bool IsLeapMonth(int year, int month, int era); + // Returns the leap month in a calendar year of the current era. This method returns 0 + // if this calendar does not have leap month, or this year is not a leap year. + // + + [System.Runtime.InteropServices.ComVisible(false)] + public virtual int GetLeapMonth(int year) + { + return (GetLeapMonth(year, CurrentEra)); + } + // Returns the leap month in a calendar year of the specified era. This method returns 0 // if this calendar does not have leap month, or this year is not a leap year. // @@ -808,7 +822,7 @@ namespace System.Globalization { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); @@ -830,7 +844,7 @@ namespace System.Globalization if (millisecond < 0 || millisecond >= MillisPerSecond) { throw new ArgumentOutOfRangeException( - "millisecond", + nameof(millisecond), String.Format( CultureInfo.InvariantCulture, SR.Format(SR.ArgumentOutOfRange_Range, 0, MillisPerSecond - 1))); diff --git a/src/mscorlib/corefx/System/Globalization/CalendarAlgorithmType.cs b/src/mscorlib/corefx/System/Globalization/CalendarAlgorithmType.cs new file mode 100644 index 0000000..159b0e6 --- /dev/null +++ b/src/mscorlib/corefx/System/Globalization/CalendarAlgorithmType.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. +// See the LICENSE file in the project root for more information. + +using System; + +namespace System.Globalization +{ + public enum CalendarAlgorithmType + { + Unknown = 0, // This is the default value to return in the Calendar base class. + SolarCalendar = 1, // Solar-base calendar, such as GregorianCalendar, jaoaneseCalendar, JulianCalendar, etc. + // Solar calendars are based on the solar year and seasons. + LunarCalendar = 2, // Lunar-based calendar, such as Hijri and UmAlQuraCalendar. + // Lunar calendars are based on the path of the moon. The seasons are not accurately represented. + LunisolarCalendar = 3 // Lunisolar-based calendar which use leap month rule, such as HebrewCalendar and Asian Lunisolar calendars. + // Lunisolar calendars are based on the cycle of the moon, but consider the seasons as a secondary consideration, + // so they align with the seasons as well as lunar events. + } +} diff --git a/src/mscorlib/corefx/System/Globalization/CalendarData.Unix.cs b/src/mscorlib/corefx/System/Globalization/CalendarData.Unix.cs index 6c6a18e..270d62f 100644 --- a/src/mscorlib/corefx/System/Globalization/CalendarData.Unix.cs +++ b/src/mscorlib/corefx/System/Globalization/CalendarData.Unix.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Security; @@ -200,7 +201,7 @@ namespace System.Globalization break; default: const string unsupportedDateFieldSymbols = "YuUrQqwWDFg"; - Contract.Assert(unsupportedDateFieldSymbols.IndexOf(input[index]) == -1, + Debug.Assert(unsupportedDateFieldSymbols.IndexOf(input[index]) == -1, string.Format(CultureInfo.InvariantCulture, "Encountered an unexpected date field symbol '{0}' from ICU which has no known corresponding .NET equivalent.", input[index])); diff --git a/src/mscorlib/corefx/System/Globalization/CalendarData.cs b/src/mscorlib/corefx/System/Globalization/CalendarData.cs index 2dbd1b8..d22bd67 100644 --- a/src/mscorlib/corefx/System/Globalization/CalendarData.cs +++ b/src/mscorlib/corefx/System/Globalization/CalendarData.cs @@ -2,11 +2,7 @@ // 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.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using System.Diagnostics.Contracts; -using System.Collections.Generic; +using System.Diagnostics; namespace System.Globalization { @@ -108,7 +104,7 @@ namespace System.Globalization if (!LoadCalendarDataFromSystem(localeName, calendarId)) { - Contract.Assert(false, "[CalendarData] LoadCalendarDataFromSystem call isn't expected to fail for calendar " + calendarId + " locale " + localeName); + Debug.Assert(false, "[CalendarData] LoadCalendarDataFromSystem call isn't expected to fail for calendar " + calendarId + " locale " + localeName); // Something failed, try invariant for missing parts // This is really not good, but we don't want the callers to crash. diff --git a/src/mscorlib/corefx/System/Globalization/CalendricalCalculationsHelper.cs b/src/mscorlib/corefx/System/Globalization/CalendricalCalculationsHelper.cs index ba7601b..149e63c 100644 --- a/src/mscorlib/corefx/System/Globalization/CalendricalCalculationsHelper.cs +++ b/src/mscorlib/corefx/System/Globalization/CalendricalCalculationsHelper.cs @@ -2,8 +2,7 @@ // 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.Diagnostics.Contracts; +using System.Diagnostics; namespace System.Globalization { @@ -126,7 +125,7 @@ namespace System.Globalization return longitude; } - static public double AsDayFraction(double longitude) + public static double AsDayFraction(double longitude) { return longitude / FullCircleOfArc; } @@ -153,7 +152,7 @@ namespace System.Globalization // the following formulas defines a polynomial function which gives us the amount that the earth is slowing down for specific year ranges private static double DefaultEphemerisCorrection(int gregorianYear) { - Contract.Assert(gregorianYear < 1620 || 2020 <= gregorianYear); + Debug.Assert(gregorianYear < 1620 || 2020 <= gregorianYear); long january1stOfYear = GetNumberOfDays(new DateTime(gregorianYear, 1, 1)); double daysSinceStartOf1810 = january1stOfYear - StartOf1810; double x = TwelveHours + daysSinceStartOf1810; @@ -162,34 +161,34 @@ namespace System.Globalization private static double EphemerisCorrection1988to2019(int gregorianYear) { - Contract.Assert(1988 <= gregorianYear && gregorianYear <= 2019); + Debug.Assert(1988 <= gregorianYear && gregorianYear <= 2019); return (double)(gregorianYear - 1933) / SecondsPerDay; } private static double EphemerisCorrection1900to1987(int gregorianYear) { - Contract.Assert(1900 <= gregorianYear && gregorianYear <= 1987); + Debug.Assert(1900 <= gregorianYear && gregorianYear <= 1987); double centuriesFrom1900 = CenturiesFrom1900(gregorianYear); return PolynomialSum(s_coefficients1900to1987, centuriesFrom1900); } private static double EphemerisCorrection1800to1899(int gregorianYear) { - Contract.Assert(1800 <= gregorianYear && gregorianYear <= 1899); + Debug.Assert(1800 <= gregorianYear && gregorianYear <= 1899); double centuriesFrom1900 = CenturiesFrom1900(gregorianYear); return PolynomialSum(s_coefficients1800to1899, centuriesFrom1900); } private static double EphemerisCorrection1700to1799(int gregorianYear) { - Contract.Assert(1700 <= gregorianYear && gregorianYear <= 1799); + Debug.Assert(1700 <= gregorianYear && gregorianYear <= 1799); double yearsSince1700 = gregorianYear - 1700; return PolynomialSum(s_coefficients1700to1799, yearsSince1700) / SecondsPerDay; } private static double EphemerisCorrection1620to1699(int gregorianYear) { - Contract.Assert(1620 <= gregorianYear && gregorianYear <= 1699); + Debug.Assert(1620 <= gregorianYear && gregorianYear <= 1699); double yearsSince1600 = gregorianYear - 1600; return PolynomialSum(s_coefficients1620to1699, yearsSince1600) / SecondsPerDay; } @@ -216,11 +215,11 @@ namespace System.Globalization } } - Contract.Assert(false, "Not expected to come here"); + Debug.Assert(false, "Not expected to come here"); return DefaultEphemerisCorrection(year); } - static public double JulianCenturies(double moment) + public static double JulianCenturies(double moment) { double dynamicalMoment = moment + EphemerisCorrection(moment); return (dynamicalMoment - Noon2000Jan01) / DaysInUniformLengthCentury; @@ -274,7 +273,7 @@ namespace System.Globalization } // midday - static public double Midday(double date, double longitude) + public static double Midday(double date, double longitude) { return AsLocalTime(date + TwelveHours, longitude) - AsDayFraction(longitude); } @@ -285,7 +284,7 @@ namespace System.Globalization } // midday-in-tehran - static public double MiddayAtPersianObservationSite(double date) + public static double MiddayAtPersianObservationSite(double date) { return Midday(date, InitLongitude(52.5)); // 52.5 degrees east - longitude of UTC+3:30 which defines Iranian Standard Time } @@ -362,7 +361,7 @@ namespace System.Globalization return (-0.004778 * SinOfDegree(a)) - (0.0003667 * SinOfDegree(b)); } - static public double Compute(double time) + public static double Compute(double time) { double julianCenturies = JulianCenturies(time); double lambda = 282.7771834 @@ -373,7 +372,7 @@ namespace System.Globalization return InitLongitude(longitude); } - static public double AsSeason(double longitude) + public static double AsSeason(double longitude) { return (longitude < 0) ? (longitude + FullCircleOfArc) : longitude; } @@ -405,7 +404,7 @@ namespace System.Globalization break; } } - Contract.Assert(day != upperBoundNewYearDay); + Debug.Assert(day != upperBoundNewYearDay); return day - 1; } diff --git a/src/mscorlib/corefx/System/Globalization/CharUnicodeInfo.cs b/src/mscorlib/corefx/System/Globalization/CharUnicodeInfo.cs index 4cb95fb..dc38ca4 100644 --- a/src/mscorlib/corefx/System/Globalization/CharUnicodeInfo.cs +++ b/src/mscorlib/corefx/System/Globalization/CharUnicodeInfo.cs @@ -12,12 +12,7 @@ // //////////////////////////////////////////////////////////////////////////// -using System; -using System.Threading; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using System.Reflection; -using System.Security; +using System.Diagnostics; using System.Diagnostics.Contracts; namespace System.Globalization @@ -59,8 +54,8 @@ namespace System.Globalization internal static int InternalConvertToUtf32(String s, int index) { - Contract.Assert(s != null, "s != null"); - Contract.Assert(index >= 0 && index < s.Length, "index < s.Length"); + Debug.Assert(s != null, "s != null"); + Debug.Assert(index >= 0 && index < s.Length, "index < s.Length"); if (index < s.Length - 1) { int temp1 = (int)s[index] - HIGH_SURROGATE_START; @@ -100,9 +95,9 @@ namespace System.Globalization internal static int InternalConvertToUtf32(String s, int index, out int charLength) { - Contract.Assert(s != null, "s != null"); - Contract.Assert(s.Length > 0, "s.Length > 0"); - Contract.Assert(index >= 0 && index < s.Length, "index >= 0 && index < s.Length"); + Debug.Assert(s != null, "s != null"); + Debug.Assert(s.Length > 0, "s.Length > 0"); + Debug.Assert(index >= 0 && index < s.Length, "index >= 0 && index < s.Length"); charLength = 1; if (index < s.Length - 1) { @@ -131,8 +126,8 @@ namespace System.Globalization internal static bool IsWhiteSpace(String s, int index) { - Contract.Assert(s != null, "s!=null"); - Contract.Assert(index >= 0 && index < s.Length, "index >= 0 && index < s.Length"); + Debug.Assert(s != null, "s!=null"); + Debug.Assert(index >= 0 && index < s.Length, "index >= 0 && index < s.Length"); UnicodeCategory uc = GetUnicodeCategory(s, index); // In Unicode 3.0, U+2028 is the only character which is under the category "LineSeparator". @@ -170,9 +165,9 @@ namespace System.Globalization // // Note that for ch in the range D800-DFFF we just treat it as any other non-numeric character // - internal unsafe static double InternalGetNumericValue(int ch) + internal static unsafe double InternalGetNumericValue(int ch) { - Contract.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range."); + Debug.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range."); // Get the level 2 item from the highest 12 bit (8 - 19) of ch. ushort index = s_pNumericLevel1Index[ch >> 8]; // Get the level 2 WORD offset from the 4 - 7 bit of ch. This provides the base offset of the level 3 table. @@ -191,6 +186,21 @@ namespace System.Globalization } } + internal static unsafe ushort InternalGetDigitValues(int ch) + { + Debug.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range."); + // Get the level 2 item from the highest 12 bit (8 - 19) of ch. + ushort index = s_pNumericLevel1Index[ch >> 8]; + // Get the level 2 WORD offset from the 4 - 7 bit of ch. This provides the base offset of the level 3 table. + // Note that & has the lower precedence than addition, so don't forget the parathesis. + index = s_pNumericLevel1Index[index + ((ch >> 4) & 0x000f)]; + + fixed (ushort* pUshortPtr = &(s_pNumericLevel1Index[index])) + { + byte* pBytePtr = (byte*)pUshortPtr; + return s_pDigitValues[pBytePtr[(ch & 0x000f)]]; + } + } //////////////////////////////////////////////////////////////////////// // @@ -218,16 +228,58 @@ namespace System.Globalization { if (s == null) { - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); } if (index < 0 || index >= s.Length) { - throw new ArgumentOutOfRangeException("index", SR.ArgumentOutOfRange_Index); + throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); } Contract.EndContractBlock(); return (InternalGetNumericValue(InternalConvertToUtf32(s, index))); } + public static int GetDecimalDigitValue(char ch) + { + return (sbyte) (InternalGetDigitValues(ch) >> 8); + } + + public static int GetDecimalDigitValue(String s, int index) + { + if (s == null) + { + throw new ArgumentNullException(nameof(s)); + } + + if (index < 0 || index >= s.Length) + { + throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); + } + Contract.EndContractBlock(); + + return (sbyte) (InternalGetDigitValues(InternalConvertToUtf32(s, index)) >> 8); + } + + public static int GetDigitValue(char ch) + { + return (sbyte) (InternalGetDigitValues(ch) & 0x00FF); + } + + public static int GetDigitValue(String s, int index) + { + if (s == null) + { + throw new ArgumentNullException(nameof(s)); + } + + if (index < 0 || index >= s.Length) + { + throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); + } + + Contract.EndContractBlock(); + return (sbyte) (InternalGetDigitValues(InternalConvertToUtf32(s, index)) & 0x00FF); + } + public static UnicodeCategory GetUnicodeCategory(char ch) { return (InternalGetUnicodeCategory(ch)); @@ -236,16 +288,16 @@ namespace System.Globalization public static UnicodeCategory GetUnicodeCategory(String s, int index) { if (s == null) - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); if (((uint)index) >= ((uint)s.Length)) { - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); } Contract.EndContractBlock(); return InternalGetUnicodeCategory(s, index); } - internal unsafe static UnicodeCategory InternalGetUnicodeCategory(int ch) + internal static unsafe UnicodeCategory InternalGetUnicodeCategory(int ch) { return ((UnicodeCategory)InternalGetCategoryValue(ch, UNICODE_CATEGORY_OFFSET)); } @@ -265,9 +317,9 @@ namespace System.Globalization // //////////////////////////////////////////////////////////////////////// - internal unsafe static byte InternalGetCategoryValue(int ch, int offset) + internal static unsafe byte InternalGetCategoryValue(int ch, int offset) { - Contract.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range."); + Debug.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range."); // Get the level 2 item from the highest 12 bit (8 - 19) of ch. ushort index = s_pCategoryLevel1Index[ch >> 8]; // Get the level 2 WORD offset from the 4 - 7 bit of ch. This provides the base offset of the level 3 table. @@ -284,7 +336,7 @@ namespace System.Globalization // Make sure that OtherNotAssigned is the last category in UnicodeCategory. // If that changes, change the following assertion as well. // - //Contract.Assert(uc >= 0 && uc <= UnicodeCategory.OtherNotAssigned, "Table returns incorrect Unicode category"); + //Debug.Assert(uc >= 0 && uc <= UnicodeCategory.OtherNotAssigned, "Table returns incorrect Unicode category"); return (uc); } } @@ -304,8 +356,8 @@ namespace System.Globalization internal static UnicodeCategory InternalGetUnicodeCategory(String value, int index) { - Contract.Assert(value != null, "value can not be null"); - Contract.Assert(index < value.Length, "index < value.Length"); + Debug.Assert(value != null, "value can not be null"); + Debug.Assert(index < value.Length, "index < value.Length"); return (InternalGetUnicodeCategory(InternalConvertToUtf32(value, index))); } @@ -319,16 +371,16 @@ namespace System.Globalization internal static UnicodeCategory InternalGetUnicodeCategory(String str, int index, out int charLength) { - Contract.Assert(str != null, "str can not be null"); - Contract.Assert(str.Length > 0, "str.Length > 0"); ; - Contract.Assert(index >= 0 && index < str.Length, "index >= 0 && index < str.Length"); + Debug.Assert(str != null, "str can not be null"); + Debug.Assert(str.Length > 0, "str.Length > 0"); ; + Debug.Assert(index >= 0 && index < str.Length, "index >= 0 && index < str.Length"); return (InternalGetUnicodeCategory(InternalConvertToUtf32(str, index, out charLength))); } internal static bool IsCombiningCategory(UnicodeCategory uc) { - Contract.Assert(uc >= 0, "uc >= 0"); + Debug.Assert(uc >= 0, "uc >= 0"); return ( uc == UnicodeCategory.NonSpacingMark || uc == UnicodeCategory.SpacingCombiningMark || diff --git a/src/mscorlib/corefx/System/Globalization/CharUnicodeInfoData.cs b/src/mscorlib/corefx/System/Globalization/CharUnicodeInfoData.cs index 7284cfd..b1bef81 100644 --- a/src/mscorlib/corefx/System/Globalization/CharUnicodeInfoData.cs +++ b/src/mscorlib/corefx/System/Globalization/CharUnicodeInfoData.cs @@ -1218,5 +1218,30 @@ namespace System.Globalization 0x00, 0x00, 0x00, 0x00, 0x80, 0x84, 0x2e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x84, 0xd7, 0x97, 0x41, 0x00, 0x00, 0x00, 0x20, 0x5f, 0xa0, 0x02, 0x42, 0x00, 0x00, 0x00, 0xa2, 0x94, 0x1a, 0x6d, 0x42 }; + + private static ushort[] s_pDigitValues = new ushort [] + { + 0xffff, 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, + 0x0707, 0x0808, 0x0909, 0xff02, 0xff03, 0xff01, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xff04, 0xff05, 0xff06, + 0xff07, 0xff08, 0xff09, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xff00, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000 + }; + } } diff --git a/src/mscorlib/corefx/System/Globalization/ChineseLunisolarCalendar.cs b/src/mscorlib/corefx/System/Globalization/ChineseLunisolarCalendar.cs index 48f6201..271d980 100644 --- a/src/mscorlib/corefx/System/Globalization/ChineseLunisolarCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/ChineseLunisolarCalendar.cs @@ -342,13 +342,13 @@ namespace System.Globalization { if (era != CurrentEra && era != ChineseEra) { - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } if (year < MIN_LUNISOLAR_YEAR || year > MAX_LUNISOLAR_YEAR) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR)); diff --git a/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs b/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs index 2aaf5a2..21c3c9f 100644 --- a/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs +++ b/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs @@ -2,6 +2,7 @@ // 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.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -17,7 +18,6 @@ namespace System.Globalization [NonSerialized] private bool _isAsciiEqualityOrdinal; - [SecuritySafeCritical] internal CompareInfo(CultureInfo culture) { _name = culture.m_name; @@ -27,14 +27,23 @@ namespace System.Globalization private void InitSort(CultureInfo culture) { _sortName = culture.SortName; - _sortHandle = Interop.GlobalizationInterop.GetSortHandle(GetNullTerminatedUtf8String(_sortName)); + Interop.GlobalizationInterop.ResultCode resultCode = Interop.GlobalizationInterop.GetSortHandle(GetNullTerminatedUtf8String(_sortName), out _sortHandle); + if (resultCode != Interop.GlobalizationInterop.ResultCode.Success) + { + _sortHandle.Dispose(); + + if (resultCode == Interop.GlobalizationInterop.ResultCode.OutOfMemory) + throw new OutOfMemoryException(); + + throw new ExternalException(SR.Arg_ExternalException); + } _isAsciiEqualityOrdinal = (_sortName == "en-US" || _sortName == ""); } internal static unsafe int IndexOfOrdinal(string source, string value, int startIndex, int count, bool ignoreCase) { - Contract.Assert(source != null); - Contract.Assert(value != null); + Debug.Assert(source != null); + Debug.Assert(value != null); if (value.Length == 0) { @@ -77,8 +86,8 @@ namespace System.Globalization internal static unsafe int LastIndexOfOrdinal(string source, string value, int startIndex, int count, bool ignoreCase) { - Contract.Assert(source != null); - Contract.Assert(value != null); + Debug.Assert(source != null); + Debug.Assert(value != null); if (value.Length == 0) { @@ -124,8 +133,8 @@ namespace System.Globalization private int GetHashCodeOfStringCore(string source, CompareOptions options) { - Contract.Assert(source != null); - Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); + Debug.Assert(source != null); + Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); return GetHashCodeOfStringCore(source, options, forceRandomizedHashing: false, additionalEntropy: 0); } @@ -137,9 +146,9 @@ namespace System.Globalization private unsafe int CompareString(string string1, int offset1, int length1, string string2, int offset2, int length2, CompareOptions options) { - Contract.Assert(string1 != null); - Contract.Assert(string2 != null); - Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); + Debug.Assert(string1 != null); + Debug.Assert(string2 != null); + Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); fixed (char* pString1 = string1) { @@ -152,9 +161,9 @@ namespace System.Globalization private unsafe int IndexOfCore(string source, string target, int startIndex, int count, CompareOptions options) { - Contract.Assert(!string.IsNullOrEmpty(source)); - Contract.Assert(target != null); - Contract.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0); + Debug.Assert(!string.IsNullOrEmpty(source)); + Debug.Assert(target != null); + Debug.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0); if (target.Length == 0) { @@ -181,9 +190,9 @@ namespace System.Globalization private unsafe int LastIndexOfCore(string source, string target, int startIndex, int count, CompareOptions options) { - Contract.Assert(!string.IsNullOrEmpty(source)); - Contract.Assert(target != null); - Contract.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0); + Debug.Assert(!string.IsNullOrEmpty(source)); + Debug.Assert(target != null); + Debug.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0); if (target.Length == 0) { @@ -212,12 +221,11 @@ namespace System.Globalization } } - [SecuritySafeCritical] private bool StartsWith(string source, string prefix, CompareOptions options) { - Contract.Assert(!string.IsNullOrEmpty(source)); - Contract.Assert(!string.IsNullOrEmpty(prefix)); - Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); + Debug.Assert(!string.IsNullOrEmpty(source)); + Debug.Assert(!string.IsNullOrEmpty(prefix)); + Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options) && source.IsFastSort() && prefix.IsFastSort()) { @@ -227,12 +235,11 @@ namespace System.Globalization return Interop.GlobalizationInterop.StartsWith(_sortHandle, prefix, prefix.Length, source, source.Length, options); } - [SecuritySafeCritical] private bool EndsWith(string source, string suffix, CompareOptions options) { - Contract.Assert(!string.IsNullOrEmpty(source)); - Contract.Assert(!string.IsNullOrEmpty(suffix)); - Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); + Debug.Assert(!string.IsNullOrEmpty(source)); + Debug.Assert(!string.IsNullOrEmpty(suffix)); + Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options) && source.IsFastSort() && suffix.IsFastSort()) { @@ -241,16 +248,81 @@ namespace System.Globalization return Interop.GlobalizationInterop.EndsWith(_sortHandle, suffix, suffix.Length, source, source.Length, options); } + + private unsafe SortKey CreateSortKey(String source, CompareOptions options) + { + if (source==null) { throw new ArgumentNullException(nameof(source)); } + Contract.EndContractBlock(); + + if ((options & ValidSortkeyCtorMaskOffFlags) != 0) + { + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); + } + + byte [] keyData; + if (source.Length == 0) + { + keyData = EmptyArray.Value; + } + else + { + int sortKeyLength = Interop.GlobalizationInterop.GetSortKey(_sortHandle, source, source.Length, null, 0, options); + keyData = new byte[sortKeyLength]; + + fixed (byte* pSortKey = keyData) + { + Interop.GlobalizationInterop.GetSortKey(_sortHandle, source, source.Length, pSortKey, sortKeyLength, options); + } + } + + return new SortKey(Name, source, options, keyData); + } + + private unsafe static bool IsSortable(char *text, int length) + { + int index = 0; + UnicodeCategory uc; + + while (index < length) + { + if (Char.IsHighSurrogate(text[index])) + { + if (index == length - 1 || !Char.IsLowSurrogate(text[index+1])) + return false; // unpaired surrogate + + uc = CharUnicodeInfo.InternalGetUnicodeCategory(Char.ConvertToUtf32(text[index], text[index+1])); + if (uc == UnicodeCategory.PrivateUse || uc == UnicodeCategory.OtherNotAssigned) + return false; + + index += 2; + continue; + } + + if (Char.IsLowSurrogate(text[index])) + { + return false; // unpaired surrogate + } + + uc = CharUnicodeInfo.GetUnicodeCategory(text[index]); + if (uc == UnicodeCategory.PrivateUse || uc == UnicodeCategory.OtherNotAssigned) + { + return false; + } + + index++; + } + + return true; + } // ----------------------------- // ---- PAL layer ends here ---- // ----------------------------- - [SecuritySafeCritical] internal unsafe int GetHashCodeOfStringCore(string source, CompareOptions options, bool forceRandomizedHashing, long additionalEntropy) { - Contract.Assert(source != null); - Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); + Debug.Assert(source != null); + Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); if (source.Length == 0) { @@ -307,9 +379,19 @@ namespace System.Globalization int bytesWritten = System.Text.Encoding.UTF8.GetBytes(s, 0, s.Length, buffer, 0); - Contract.Assert(bytesWritten == byteLen); + Debug.Assert(bytesWritten == byteLen); return buffer; } + + private SortVersion GetSortVersion() + { + int sortVersion = Interop.GlobalizationInterop.GetSortVersion(); + return new SortVersion(sortVersion, LCID, new Guid(sortVersion, 0, 0, 0, 0, 0, 0, + (byte) (LCID >> 24), + (byte) ((LCID & 0x00FF0000) >> 16), + (byte) ((LCID & 0x0000FF00) >> 8), + (byte) (LCID & 0xFF))); + } } } diff --git a/src/mscorlib/corefx/System/Globalization/CompareInfo.Windows.cs b/src/mscorlib/corefx/System/Globalization/CompareInfo.Windows.cs index 744a48b..4ebaf9c 100644 --- a/src/mscorlib/corefx/System/Globalization/CompareInfo.Windows.cs +++ b/src/mscorlib/corefx/System/Globalization/CompareInfo.Windows.cs @@ -2,6 +2,7 @@ // 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.Diagnostics; using System.Diagnostics.Contracts; namespace System.Globalization @@ -53,24 +54,24 @@ namespace System.Globalization internal static int IndexOfOrdinal(string source, string value, int startIndex, int count, bool ignoreCase) { - Contract.Assert(source != null); - Contract.Assert(value != null); + Debug.Assert(source != null); + Debug.Assert(value != null); return FindStringOrdinal(FIND_FROMSTART, source, startIndex, count, value, value.Length, ignoreCase); } internal static int LastIndexOfOrdinal(string source, string value, int startIndex, int count, bool ignoreCase) { - Contract.Assert(source != null); - Contract.Assert(value != null); + Debug.Assert(source != null); + Debug.Assert(value != null); return FindStringOrdinal(FIND_FROMEND, source, startIndex - count + 1, count, value, value.Length, ignoreCase); } private unsafe int GetHashCodeOfStringCore(string source, CompareOptions options) { - Contract.Assert(source != null); - Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); + Debug.Assert(source != null); + Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); if (source.Length == 0) { @@ -102,9 +103,9 @@ namespace System.Globalization private unsafe int CompareString(string string1, int offset1, int length1, string string2, int offset2, int length2, CompareOptions options) { - Contract.Assert(string1 != null); - Contract.Assert(string2 != null); - Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); + Debug.Assert(string1 != null); + Debug.Assert(string2 != null); + Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); string localeName = _sortHandle != IntPtr.Zero ? null : _sortName; @@ -167,9 +168,9 @@ namespace System.Globalization private int IndexOfCore(string source, string target, int startIndex, int count, CompareOptions options) { - Contract.Assert(!string.IsNullOrEmpty(source)); - Contract.Assert(target != null); - Contract.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0); + Debug.Assert(!string.IsNullOrEmpty(source)); + Debug.Assert(target != null); + Debug.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0); // TODO: Consider moving this up to the relevent APIs we need to ensure this behavior for // and add a precondition that target is not empty. @@ -200,9 +201,9 @@ namespace System.Globalization private int LastIndexOfCore(string source, string target, int startIndex, int count, CompareOptions options) { - Contract.Assert(!string.IsNullOrEmpty(source)); - Contract.Assert(target != null); - Contract.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0); + Debug.Assert(!string.IsNullOrEmpty(source)); + Debug.Assert(target != null); + Debug.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0); // TODO: Consider moving this up to the relevent APIs we need to ensure this behavior for // and add a precondition that target is not empty. @@ -234,9 +235,9 @@ namespace System.Globalization private bool StartsWith(string source, string prefix, CompareOptions options) { - Contract.Assert(!string.IsNullOrEmpty(source)); - Contract.Assert(!string.IsNullOrEmpty(prefix)); - Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); + Debug.Assert(!string.IsNullOrEmpty(source)); + Debug.Assert(!string.IsNullOrEmpty(prefix)); + Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); return FindString(FIND_STARTSWITH | (uint)GetNativeCompareFlags(options), source, @@ -249,9 +250,9 @@ namespace System.Globalization private bool EndsWith(string source, string suffix, CompareOptions options) { - Contract.Assert(!string.IsNullOrEmpty(source)); - Contract.Assert(!string.IsNullOrEmpty(suffix)); - Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); + Debug.Assert(!string.IsNullOrEmpty(source)); + Debug.Assert(!string.IsNullOrEmpty(suffix)); + Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); return FindString(FIND_ENDSWITH | (uint)GetNativeCompareFlags(options), source, @@ -280,14 +281,10 @@ namespace System.Globalization int sourceStartIndex = findLastIndex ? startIndex - sourceCount + 1 : startIndex; -#if !TEST_CODEGEN_OPTIMIZATION fixed (char* pSource = source, spTarget = target) { char* spSubSource = pSource + sourceStartIndex; -#else - String.StringPointer spSubSource = source.GetStringPointer(sourceStartIndex); - String.StringPointer spTarget = target.GetStringPointer(); -#endif + if (findLastIndex) { int startPattern = (sourceCount - 1) - targetCount + 1; @@ -347,11 +344,29 @@ namespace System.Globalization retValue += startIndex; } } -#if !TEST_CODEGEN_OPTIMIZATION } return retValue; -#endif // TEST_CODEGEN_OPTIMIZATION + } + + private unsafe SortKey CreateSortKey(String source, CompareOptions options) + { + if (source==null) { throw new ArgumentNullException(nameof(source)); } + Contract.EndContractBlock(); + + if ((options & ValidSortkeyCtorMaskOffFlags) != 0) + { + throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); + } + + throw new NotImplementedException(); + } + + private static unsafe bool IsSortable(char *text, int length) + { + // CompareInfo c = CultureInfo.InvariantCulture.CompareInfo; + // return (InternalIsSortable(c.m_dataHandle, c.m_handleOrigin, c.m_sortName, text, text.Length)); + throw new NotImplementedException(); } private const int COMPARE_OPTIONS_ORDINAL = 0x40000000; // Ordinal @@ -381,7 +396,7 @@ namespace System.Globalization // Suffix & Prefix shouldn't use this, make sure to turn off the NORM_LINGUISTIC_CASING flag if (options == CompareOptions.Ordinal) { nativeCompareFlags = COMPARE_OPTIONS_ORDINAL; } - Contract.Assert(((options & ~(CompareOptions.IgnoreCase | + Debug.Assert(((options & ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreKanaType | CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreSymbols | @@ -391,5 +406,10 @@ namespace System.Globalization return nativeCompareFlags; } + + private SortVersion GetSortVersion() + { + throw new NotImplementedException(); + } } } diff --git a/src/mscorlib/corefx/System/Globalization/CompareInfo.cs b/src/mscorlib/corefx/System/Globalization/CompareInfo.cs index 77778af..64dbfe8 100644 --- a/src/mscorlib/corefx/System/Globalization/CompareInfo.cs +++ b/src/mscorlib/corefx/System/Globalization/CompareInfo.cs @@ -12,20 +12,15 @@ // //////////////////////////////////////////////////////////////////////////// -using System; -using System.Collections; -using System.Collections.Generic; +using System.Reflection; +using System.Diagnostics; using System.Diagnostics.Contracts; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using System.Runtime.Serialization; -using System.Threading; namespace System.Globalization { [Flags] [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] public enum CompareOptions { None = 0x00000000, @@ -40,7 +35,6 @@ namespace System.Globalization } [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] public partial class CompareInfo : IDeserializationCallback { // Mask used to check if IndexOf()/LastIndexOf()/IsPrefix()/IsPostfix() has the right flags. @@ -58,6 +52,11 @@ namespace System.Globalization ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType); + // Mask used to check if we have the right flags. + private const CompareOptions ValidSortkeyCtorMaskOffFlags = + ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace | + CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType | CompareOptions.StringSort); + // // CompareInfos have an interesting identity. They are attached to the locale that created them, // ie: en-US would have an en-US sort. For haw-US (custom), then we serialize it as haw-US. @@ -69,6 +68,86 @@ namespace System.Globalization [NonSerialized] private String _sortName; // The name that defines our behavior + [OptionalField(VersionAdded = 3)] + private SortVersion _sortVersion; + + /*=================================GetCompareInfo========================== + **Action: Get the CompareInfo constructed from the data table in the specified assembly for the specified culture. + ** Warning: The assembly versioning mechanism is dead! + **Returns: The CompareInfo for the specified culture. + **Arguments: + ** culture the ID of the culture + ** assembly the assembly which contains the sorting table. + **Exceptions: + ** ArugmentNullException when the assembly is null + ** ArgumentException if culture is invalid. + ============================================================================*/ + // Assembly constructor should be deprecated, we don't act on the assembly information any more + public static CompareInfo GetCompareInfo(int culture, Assembly assembly) + { + // Parameter checking. + if (assembly == null) + { + throw new ArgumentNullException(nameof(assembly)); + } + if (assembly != typeof(Object).Module.Assembly) + { + throw new ArgumentException(SR.Argument_OnlyMscorlib); + } + Contract.EndContractBlock(); + + return GetCompareInfo(culture); + } + + /*=================================GetCompareInfo========================== + **Action: Get the CompareInfo constructed from the data table in the specified assembly for the specified culture. + ** The purpose of this method is to provide version for CompareInfo tables. + **Returns: The CompareInfo for the specified culture. + **Arguments: + ** name the name of the culture + ** assembly the assembly which contains the sorting table. + **Exceptions: + ** ArugmentNullException when the assembly is null + ** ArgumentException if name is invalid. + ============================================================================*/ + // Assembly constructor should be deprecated, we don't act on the assembly information any more + public static CompareInfo GetCompareInfo(String name, Assembly assembly) + { + if (name == null || assembly == null) + { + throw new ArgumentNullException(name == null ? nameof(name) : nameof(assembly)); + } + Contract.EndContractBlock(); + + if (assembly != typeof(Object).Module.Assembly) + { + throw new ArgumentException(SR.Argument_OnlyMscorlib); + } + + return GetCompareInfo(name); + } + + /*=================================GetCompareInfo========================== + **Action: Get the CompareInfo for the specified culture. + ** This method is provided for ease of integration with NLS-based software. + **Returns: The CompareInfo for the specified culture. + **Arguments: + ** culture the ID of the culture. + **Exceptions: + ** ArgumentException if culture is invalid. + ============================================================================*/ + // People really shouldn't be calling LCID versions, no custom support + public static CompareInfo GetCompareInfo(int culture) + { + if (CultureData.IsCustomCultureId(culture)) + { + // Customized culture cannot be created by the LCID. + throw new ArgumentException(SR.Argument_CustomCultureCannotBePassedByNumber, nameof(culture)); + } + + return CultureInfo.GetCultureInfo(culture).CompareInfo; + } + /*=================================GetCompareInfo========================== **Action: Get the CompareInfo for the specified culture. **Returns: The CompareInfo for the specified culture. @@ -82,13 +161,40 @@ namespace System.Globalization { if (name == null) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } Contract.EndContractBlock(); return CultureInfo.GetCultureInfo(name).CompareInfo; } + public static unsafe bool IsSortable(char ch) + { + char *pChar = &ch; + return IsSortable(pChar, 1); + } + + public static unsafe bool IsSortable(string text) + { + if (text == null) + { + // A null param is invalid here. + throw new ArgumentNullException(nameof(text)); + } + + if (0 == text.Length) + { + // A zero length string is not invalid, but it is also not sortable. + return (false); + } + + fixed (char *pChar = text) + { + return IsSortable(pChar, text.Length); + } + } + + [OnDeserializing] private void OnDeserializing(StreamingContext ctx) { @@ -130,12 +236,11 @@ namespace System.Globalization // //////////////////////////////////////////////////////////////////////// - [System.Runtime.InteropServices.ComVisible(false)] public virtual String Name { get { - Contract.Assert(_name != null, "CompareInfo.Name Expected _name to be set"); + Debug.Assert(_name != null, "CompareInfo.Name Expected _name to be set"); if (_name == "zh-CHT" || _name == "zh-CHS") { return _name; @@ -173,14 +278,14 @@ namespace System.Globalization { if (options != CompareOptions.Ordinal) { - throw new ArgumentException(SR.Argument_CompareOptionOrdinal, "options"); + throw new ArgumentException(SR.Argument_CompareOptionOrdinal, nameof(options)); } return String.CompareOrdinal(string1, string2); } if ((options & ValidCompareMaskOffFlags) != 0) { - throw new ArgumentException(SR.Argument_InvalidFlag, "options"); + throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); } //Our paradigm is that null sorts less than any other string and @@ -247,31 +352,31 @@ namespace System.Globalization // Verify inputs if (length1 < 0 || length2 < 0) { - throw new ArgumentOutOfRangeException((length1 < 0) ? "length1" : "length2", SR.ArgumentOutOfRange_NeedPosNum); + throw new ArgumentOutOfRangeException((length1 < 0) ? nameof(length1) : nameof(length2), SR.ArgumentOutOfRange_NeedPosNum); } if (offset1 < 0 || offset2 < 0) { - throw new ArgumentOutOfRangeException((offset1 < 0) ? "offset1" : "offset2", SR.ArgumentOutOfRange_NeedPosNum); + throw new ArgumentOutOfRangeException((offset1 < 0) ? nameof(offset1) : nameof(offset2), SR.ArgumentOutOfRange_NeedPosNum); } if (offset1 > (string1 == null ? 0 : string1.Length) - length1) { - throw new ArgumentOutOfRangeException("string1", SR.ArgumentOutOfRange_OffsetLength); + throw new ArgumentOutOfRangeException(nameof(string1), SR.ArgumentOutOfRange_OffsetLength); } if (offset2 > (string2 == null ? 0 : string2.Length) - length2) { - throw new ArgumentOutOfRangeException("string2", SR.ArgumentOutOfRange_OffsetLength); + throw new ArgumentOutOfRangeException(nameof(string2), SR.ArgumentOutOfRange_OffsetLength); } if ((options & CompareOptions.Ordinal) != 0) { if (options != CompareOptions.Ordinal) { throw new ArgumentException(SR.Argument_CompareOptionOrdinal, - "options"); + nameof(options)); } } else if ((options & ValidCompareMaskOffFlags) != 0) { - throw new ArgumentException(SR.Argument_InvalidFlag, "options"); + throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); } // @@ -318,8 +423,8 @@ namespace System.Globalization // internal static unsafe int CompareOrdinalIgnoreCase(string strA, int indexA, int lengthA, string strB, int indexB, int lengthB) { - Contract.Assert(indexA + lengthA <= strA.Length); - Contract.Assert(indexB + lengthB <= strB.Length); + Debug.Assert(indexA + lengthA <= strA.Length); + Debug.Assert(indexB + lengthB <= strB.Length); int length = Math.Min(lengthA, lengthB); int range = length; @@ -375,7 +480,7 @@ namespace System.Globalization { if (source == null || prefix == null) { - throw new ArgumentNullException((source == null ? "source" : "prefix"), + throw new ArgumentNullException((source == null ? nameof(source) : nameof(prefix)), SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -402,7 +507,7 @@ namespace System.Globalization if ((options & ValidIndexMaskOffFlags) != 0) { - throw new ArgumentException(SR.Argument_InvalidFlag, "options"); + throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); } return StartsWith(source, prefix, options); @@ -425,7 +530,7 @@ namespace System.Globalization { if (source == null || suffix == null) { - throw new ArgumentNullException((source == null ? "source" : "suffix"), + throw new ArgumentNullException((source == null ? nameof(source) : nameof(suffix)), SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -452,7 +557,7 @@ namespace System.Globalization if ((options & ValidIndexMaskOffFlags) != 0) { - throw new ArgumentException(SR.Argument_InvalidFlag, "options"); + throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); } return EndsWith(source, suffix, options); @@ -481,7 +586,7 @@ namespace System.Globalization public unsafe virtual int IndexOf(String source, char value) { if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); return IndexOf(source, value, 0, source.Length, CompareOptions.None); @@ -491,7 +596,7 @@ namespace System.Globalization public unsafe virtual int IndexOf(String source, String value) { if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); return IndexOf(source, value, 0, source.Length, CompareOptions.None); @@ -501,7 +606,7 @@ namespace System.Globalization public unsafe virtual int IndexOf(String source, char value, CompareOptions options) { if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); return IndexOf(source, value, 0, source.Length, options); @@ -511,17 +616,34 @@ namespace System.Globalization public unsafe virtual int IndexOf(String source, String value, CompareOptions options) { if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); return IndexOf(source, value, 0, source.Length, options); } + public unsafe virtual int IndexOf(String source, char value, int startIndex) + { + if (source == null) + throw new ArgumentNullException(nameof(source)); + Contract.EndContractBlock(); + + return IndexOf(source, value, startIndex, source.Length - startIndex, CompareOptions.None); + } + + public unsafe virtual int IndexOf(String source, String value, int startIndex) + { + if (source == null) + throw new ArgumentNullException(nameof(source)); + Contract.EndContractBlock(); + + return IndexOf(source, value, startIndex, source.Length - startIndex, CompareOptions.None); + } public unsafe virtual int IndexOf(String source, char value, int startIndex, CompareOptions options) { if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); return IndexOf(source, value, startIndex, source.Length - startIndex, options); @@ -531,7 +653,7 @@ namespace System.Globalization public unsafe virtual int IndexOf(String source, String value, int startIndex, CompareOptions options) { if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); return IndexOf(source, value, startIndex, source.Length - startIndex, options); @@ -553,13 +675,13 @@ namespace System.Globalization { // Validate inputs if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); if (startIndex < 0 || startIndex > source.Length) - throw new ArgumentOutOfRangeException("startIndex", SR.ArgumentOutOfRange_Index); + throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index); if (count < 0 || startIndex > source.Length - count) - throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_Count); + throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count); Contract.EndContractBlock(); if (options == CompareOptions.OrdinalIgnoreCase) @@ -570,7 +692,7 @@ namespace System.Globalization // Validate CompareOptions // Ordinal can't be selected with other flags if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal)) - throw new ArgumentException(SR.Argument_InvalidFlag, "options"); + throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); return IndexOfCore(source, new string(value, 1), startIndex, count, options); } @@ -580,13 +702,13 @@ namespace System.Globalization { // Validate inputs if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); if (startIndex > source.Length) { - throw new ArgumentOutOfRangeException("startIndex", SR.ArgumentOutOfRange_Index); + throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index); } Contract.EndContractBlock(); @@ -603,11 +725,11 @@ namespace System.Globalization if (startIndex < 0) { - throw new ArgumentOutOfRangeException("startIndex", SR.ArgumentOutOfRange_Index); + throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index); } if (count < 0 || startIndex > source.Length - count) - throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_Count); + throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count); if (options == CompareOptions.OrdinalIgnoreCase) { @@ -617,7 +739,7 @@ namespace System.Globalization // Validate CompareOptions // Ordinal can't be selected with other flags if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal)) - throw new ArgumentException(SR.Argument_InvalidFlag, "options"); + throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); return IndexOfCore(source, value, startIndex, count, options); } @@ -639,7 +761,7 @@ namespace System.Globalization public unsafe virtual int LastIndexOf(String source, char value) { if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); // Can't start at negative index, so make sure we check for the length == 0 case. @@ -651,7 +773,7 @@ namespace System.Globalization public virtual int LastIndexOf(String source, String value) { if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); // Can't start at negative index, so make sure we check for the length == 0 case. @@ -663,7 +785,7 @@ namespace System.Globalization public virtual int LastIndexOf(String source, char value, CompareOptions options) { if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); // Can't start at negative index, so make sure we check for the length == 0 case. @@ -674,7 +796,7 @@ namespace System.Globalization public unsafe virtual int LastIndexOf(String source, String value, CompareOptions options) { if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); // Can't start at negative index, so make sure we check for the length == 0 case. @@ -682,6 +804,16 @@ namespace System.Globalization source.Length, options); } + public unsafe virtual int LastIndexOf(String source, char value, int startIndex) + { + return LastIndexOf(source, value, startIndex, startIndex + 1, CompareOptions.None); + } + + + public unsafe virtual int LastIndexOf(String source, String value, int startIndex) + { + return LastIndexOf(source, value, startIndex, startIndex + 1, CompareOptions.None); + } public unsafe virtual int LastIndexOf(String source, char value, int startIndex, CompareOptions options) { @@ -711,7 +843,7 @@ namespace System.Globalization { // Verify Arguments if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); // Validate CompareOptions @@ -719,7 +851,7 @@ namespace System.Globalization if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal) && (options != CompareOptions.OrdinalIgnoreCase)) - throw new ArgumentException(SR.Argument_InvalidFlag, "options"); + throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); // Special case for 0 length input strings if (source.Length == 0 && (startIndex == -1 || startIndex == 0)) @@ -727,7 +859,7 @@ namespace System.Globalization // Make sure we're not out of range if (startIndex < 0 || startIndex > source.Length) - throw new ArgumentOutOfRangeException("startIndex", SR.ArgumentOutOfRange_Index); + throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index); // Make sure that we allow startIndex == source.Length if (startIndex == source.Length) @@ -739,7 +871,7 @@ namespace System.Globalization // 2nd have of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0. if (count < 0 || startIndex - count + 1 < 0) - throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_Count); + throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count); if (options == CompareOptions.OrdinalIgnoreCase) { @@ -754,9 +886,9 @@ namespace System.Globalization { // Verify Arguments if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); Contract.EndContractBlock(); // Validate CompareOptions @@ -764,7 +896,7 @@ namespace System.Globalization if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal) && (options != CompareOptions.OrdinalIgnoreCase)) - throw new ArgumentException(SR.Argument_InvalidFlag, "options"); + throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); // Special case for 0 length input strings if (source.Length == 0 && (startIndex == -1 || startIndex == 0)) @@ -772,7 +904,7 @@ namespace System.Globalization // Make sure we're not out of range if (startIndex < 0 || startIndex > source.Length) - throw new ArgumentOutOfRangeException("startIndex", SR.ArgumentOutOfRange_Index); + throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index); // Make sure that we allow startIndex == source.Length if (startIndex == source.Length) @@ -788,7 +920,7 @@ namespace System.Globalization // 2nd half of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0. if (count < 0 || startIndex - count + 1 < 0) - throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_Count); + throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count); if (options == CompareOptions.OrdinalIgnoreCase) { @@ -798,8 +930,24 @@ namespace System.Globalization return LastIndexOfCore(source, value, startIndex, count, options); } + //////////////////////////////////////////////////////////////////////// + // + // GetSortKey + // + // Gets the SortKey for the given string with the given options. + // + //////////////////////////////////////////////////////////////////////// + public unsafe virtual SortKey GetSortKey(String source, CompareOptions options) + { + return CreateSortKey(source, options); + } + public unsafe virtual SortKey GetSortKey(String source) + { + return CreateSortKey(source, CompareOptions.None); + } + //////////////////////////////////////////////////////////////////////// // // Equals @@ -872,12 +1020,12 @@ namespace System.Globalization // if (null == source) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if ((options & ValidHashCodeOfStringMaskOffFlags) != 0) { - throw new ArgumentException(SR.Argument_InvalidFlag, "options"); + throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); } Contract.EndContractBlock(); @@ -888,7 +1036,7 @@ namespace System.Globalization { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (options == CompareOptions.Ordinal) @@ -921,5 +1069,26 @@ namespace System.Globalization { return ("CompareInfo - " + this.Name); } + + public SortVersion Version + { + get + { + if (_sortVersion == null) + { + _sortVersion = GetSortVersion(); + } + + return _sortVersion; + } + } + + public int LCID + { + get + { + return CultureInfo.GetCultureInfo(Name).LCID; + } + } } } diff --git a/src/mscorlib/corefx/System/Globalization/CultureData.Unix.cs b/src/mscorlib/corefx/System/Globalization/CultureData.Unix.cs index 58aae2f..7f2f17d 100644 --- a/src/mscorlib/corefx/System/Globalization/CultureData.Unix.cs +++ b/src/mscorlib/corefx/System/Globalization/CultureData.Unix.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Security; @@ -17,7 +18,8 @@ namespace System.Globalization const int ICU_ULOC_KEYWORD_AND_VALUES_CAPACITY = 100; // max size of keyword or value const int ICU_ULOC_FULLNAME_CAPACITY = 157; // max size of locale name const string ICU_COLLATION_KEYWORD = "@collation="; - + + /// /// This method uses the sRealName field (which is initialized by the constructor before this is called) to /// initialize the rest of the state of CultureData based on the underlying OS globalization library. @@ -25,8 +27,8 @@ namespace System.Globalization [SecuritySafeCritical] private unsafe bool InitCultureData() { - Contract.Assert(_sRealName != null); - + Debug.Assert(_sRealName != null); + string alternateSortName = string.Empty; string realNameBuffer = _sRealName; @@ -66,23 +68,21 @@ namespace System.Globalization _sName = _sWindowsName; } _sRealName = _sName; - _sSpecificCulture = _sRealName; // we don't attempt to find a non-neutral locale if a neutral is passed in (unlike win32) _iLanguage = this.ILANGUAGE; if (_iLanguage == 0) { - _iLanguage = LOCALE_CUSTOM_UNSPECIFIED; + _iLanguage = CultureInfo.LOCALE_CUSTOM_UNSPECIFIED; } _bNeutral = (this.SISO3166CTRYNAME.Length == 0); - + + _sSpecificCulture = _bNeutral ? LocaleData.GetSpecificCultureName(_sRealName) : _sRealName; + // Remove the sort from sName unless custom culture - if (!_bNeutral) + if (index>0 && !_bNeutral && !IsCustomCultureId(_iLanguage)) { - if (!IsCustomCultureId(_iLanguage)) - { - _sName = _sWindowsName.Substring(0, index); - } + _sName = _sWindowsName.Substring(0, index); } return true; } @@ -120,10 +120,10 @@ namespace System.Globalization windowsName = StringBuilderCache.GetStringAndRelease(sb); // the name passed to subsequent ICU calls return true; } - + private string GetLocaleInfo(LocaleStringData type) { - Contract.Assert(_sWindowsName != null, "[CultureData.GetLocaleInfo] Expected _sWindowsName to be populated already"); + Debug.Assert(_sWindowsName != null, "[CultureData.GetLocaleInfo] Expected _sWindowsName to be populated already"); return GetLocaleInfo(_sWindowsName, type); } @@ -132,7 +132,7 @@ namespace System.Globalization [SecuritySafeCritical] private string GetLocaleInfo(string localeName, LocaleStringData type) { - Contract.Assert(localeName != null, "[CultureData.GetLocaleInfo] Expected localeName to be not be null"); + Debug.Assert(localeName != null, "[CultureData.GetLocaleInfo] Expected localeName to be not be null"); switch (type) { @@ -149,7 +149,7 @@ namespace System.Globalization { // Failed, just use empty string StringBuilderCache.Release(sb); - Contract.Assert(false, "[CultureData.GetLocaleInfo(LocaleStringData)] Failed"); + Debug.Assert(false, "[CultureData.GetLocaleInfo(LocaleStringData)] Failed"); return String.Empty; } return StringBuilderCache.GetStringAndRelease(sb); @@ -158,7 +158,7 @@ namespace System.Globalization [SecuritySafeCritical] private int GetLocaleInfo(LocaleNumberData type) { - Contract.Assert(_sWindowsName != null, "[CultureData.GetLocaleInfo(LocaleNumberData)] Expected _sWindowsName to be populated already"); + Debug.Assert(_sWindowsName != null, "[CultureData.GetLocaleInfo(LocaleNumberData)] Expected _sWindowsName to be populated already"); switch (type) { @@ -173,7 +173,7 @@ namespace System.Globalization if (!result) { // Failed, just use 0 - Contract.Assert(false, "[CultureData.GetLocaleInfo(LocaleNumberData)] failed"); + Debug.Assert(false, "[CultureData.GetLocaleInfo(LocaleNumberData)] failed"); } return value; @@ -182,14 +182,14 @@ namespace System.Globalization [SecuritySafeCritical] private int[] GetLocaleInfo(LocaleGroupingData type) { - Contract.Assert(_sWindowsName != null, "[CultureData.GetLocaleInfo(LocaleGroupingData)] Expected _sWindowsName to be populated already"); + Debug.Assert(_sWindowsName != null, "[CultureData.GetLocaleInfo(LocaleGroupingData)] Expected _sWindowsName to be populated already"); int primaryGroupingSize = 0; int secondaryGroupingSize = 0; bool result = Interop.GlobalizationInterop.GetLocaleInfoGroupingSizes(_sWindowsName, (uint)type, ref primaryGroupingSize, ref secondaryGroupingSize); if (!result) { - Contract.Assert(false, "[CultureData.GetLocaleInfo(LocaleGroupingData type)] failed"); + Debug.Assert(false, "[CultureData.GetLocaleInfo(LocaleGroupingData type)] failed"); } if (secondaryGroupingSize == 0) @@ -208,7 +208,7 @@ namespace System.Globalization [SecuritySafeCritical] private string GetTimeFormatString(bool shortFormat) { - Contract.Assert(_sWindowsName != null, "[CultureData.GetTimeFormatString(bool shortFormat)] Expected _sWindowsName to be populated already"); + Debug.Assert(_sWindowsName != null, "[CultureData.GetTimeFormatString(bool shortFormat)] Expected _sWindowsName to be populated already"); StringBuilder sb = StringBuilderCache.Acquire(ICU_ULOC_KEYWORD_AND_VALUES_CAPACITY); @@ -217,7 +217,7 @@ namespace System.Globalization { // Failed, just use empty string StringBuilderCache.Release(sb); - Contract.Assert(false, "[CultureData.GetTimeFormatString(bool shortFormat)] Failed"); + Debug.Assert(false, "[CultureData.GetTimeFormatString(bool shortFormat)] Failed"); return String.Empty; } @@ -300,5 +300,127 @@ namespace System.Globalization return StringBuilderCache.GetStringAndRelease(sb); } + + private static string LCIDToLocaleName(int culture) + { + return LocaleData.LCIDToLocaleName(culture); + } + + private static int LocaleNameToLCID(string cultureName) + { + int lcid = LocaleData.GetLocaleDataNumericPart(cultureName, LocaleDataParts.Lcid); + return lcid == -1 ? CultureInfo.LOCALE_CUSTOM_UNSPECIFIED : lcid; + } + + private static int GetAnsiCodePage(string cultureName) + { + int ansiCodePage = LocaleData.GetLocaleDataNumericPart(cultureName, LocaleDataParts.AnsiCodePage); + return ansiCodePage == -1 ? CultureData.Invariant.IDEFAULTANSICODEPAGE : ansiCodePage; + } + + private static int GetOemCodePage(string cultureName) + { + int oemCodePage = LocaleData.GetLocaleDataNumericPart(cultureName, LocaleDataParts.OemCodePage); + return oemCodePage == -1 ? CultureData.Invariant.IDEFAULTOEMCODEPAGE : oemCodePage; + } + + private static int GetMacCodePage(string cultureName) + { + int macCodePage = LocaleData.GetLocaleDataNumericPart(cultureName, LocaleDataParts.MacCodePage); + return macCodePage == -1 ? CultureData.Invariant.IDEFAULTMACCODEPAGE : macCodePage; + } + + private static int GetEbcdicCodePage(string cultureName) + { + int ebcdicCodePage = LocaleData.GetLocaleDataNumericPart(cultureName, LocaleDataParts.EbcdicCodePage); + return ebcdicCodePage == -1 ? CultureData.Invariant.IDEFAULTEBCDICCODEPAGE : ebcdicCodePage; + } + + private static int GetGeoId(string cultureName) + { + int geoId = LocaleData.GetLocaleDataNumericPart(cultureName, LocaleDataParts.GeoId); + return geoId == -1 ? CultureData.Invariant.IGEOID : geoId; + } + + private static int GetDigitSubstitution(string cultureName) + { + int digitSubstitution = LocaleData.GetLocaleDataNumericPart(cultureName, LocaleDataParts.DigitSubstitution); + return digitSubstitution == -1 ? (int) DigitShapes.None : digitSubstitution; + } + + private static string GetThreeLetterWindowsLanguageName(string cultureName) + { + string langName = LocaleData.GetThreeLetterWindowsLangageName(cultureName); + return langName == null ? "ZZZ" /* default lang name */ : langName; + } + + private static CultureInfo[] EnumCultures(CultureTypes types) + { + if ((types & (CultureTypes.NeutralCultures | CultureTypes.SpecificCultures)) == 0) + { + return Array.Empty(); + } + + int bufferLength = Interop.GlobalizationInterop.GetLocales(null, 0); + if (bufferLength <= 0) + { + return Array.Empty(); + } + + Char [] chars = new Char[bufferLength]; + + bufferLength = Interop.GlobalizationInterop.GetLocales(chars, bufferLength); + if (bufferLength <= 0) + { + return Array.Empty(); + } + + bool enumNeutrals = (types & CultureTypes.NeutralCultures) != 0; + bool enumSpecificss = (types & CultureTypes.SpecificCultures) != 0; + + List list = new List(); + if (enumNeutrals) + { + list.Add(CultureInfo.InvariantCulture); + } + + int index = 0; + while (index < bufferLength) + { + int length = (int) chars[index++]; + if (index + length <= bufferLength) + { + CultureInfo ci = CultureInfo.GetCultureInfo(new String(chars, index, length)); + if ((enumNeutrals && ci.IsNeutralCulture) || (enumSpecificss && !ci.IsNeutralCulture)) + { + list.Add(ci); + } + } + + index += length; + } + + return list.ToArray(); + } + + private static string GetConsoleFallbackName(string cultureName) + { + return LocaleData.GetConsoleUICulture(cultureName); + } + + internal bool IsFramework // not applicable on Linux based systems + { + get { return false; } + } + + internal bool IsWin32Installed // not applicable on Linux based systems + { + get { return false; } + } + + internal bool IsReplacementCulture // not applicable on Linux based systems + { + get { return false; } + } } } diff --git a/src/mscorlib/corefx/System/Globalization/CultureData.Windows.cs b/src/mscorlib/corefx/System/Globalization/CultureData.Windows.cs index 9969ecb..d1c99da 100644 --- a/src/mscorlib/corefx/System/Globalization/CultureData.Windows.cs +++ b/src/mscorlib/corefx/System/Globalization/CultureData.Windows.cs @@ -3,10 +3,13 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; -using System.Diagnostics.Contracts; +using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; + +#if ENABLE_WINRT using Internal.Runtime.Augments; +#endif namespace System.Globalization { @@ -158,7 +161,7 @@ namespace System.Globalization private string GetLocaleInfo(LocaleStringData type) { - Contract.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfo] Expected _sWindowsName to be populated by already"); + Debug.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfo] Expected _sWindowsName to be populated by already"); return GetLocaleInfo(_sWindowsName, type); } @@ -183,7 +186,7 @@ namespace System.Globalization // Ask OS for data, note that we presume it returns success, so we have to know that // sWindowsName is valid before calling. - Contract.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected _sWindowsName to be populated by already"); + Debug.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected _sWindowsName to be populated by already"); int result = Interop.mincore.GetLocaleInfoExInt(_sWindowsName, lctype); return result; @@ -203,7 +206,7 @@ namespace System.Globalization private int GetFirstDayOfWeek() { - Contract.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected _sWindowsName to be populated by already"); + Debug.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected _sWindowsName to be populated by already"); const uint LOCALE_IFIRSTDAYOFWEEK = 0x0000100C; @@ -216,7 +219,7 @@ namespace System.Globalization private String[] GetTimeFormats() { // Note that this gets overrides for us all the time - Contract.Assert(_sWindowsName != null, "[CultureData.DoEnumTimeFormats] Expected _sWindowsName to be populated by already"); + Debug.Assert(_sWindowsName != null, "[CultureData.DoEnumTimeFormats] Expected _sWindowsName to be populated by already"); String[] result = ReescapeWin32Strings(nativeEnumTimeFormats(_sWindowsName, 0, UseUserOverride)); return result; @@ -225,7 +228,7 @@ namespace System.Globalization private String[] GetShortTimeFormats() { // Note that this gets overrides for us all the time - Contract.Assert(_sWindowsName != null, "[CultureData.DoEnumShortTimeFormats] Expected _sWindowsName to be populated by already"); + Debug.Assert(_sWindowsName != null, "[CultureData.DoEnumShortTimeFormats] Expected _sWindowsName to be populated by already"); String[] result = ReescapeWin32Strings(nativeEnumTimeFormats(_sWindowsName, TIME_NOSECONDS, UseUserOverride)); return result; @@ -235,7 +238,7 @@ namespace System.Globalization // region name match the requested region name private static CultureData GetCultureDataFromRegionName(String regionName) { - Contract.Assert(regionName != null); + Debug.Assert(regionName != null); const uint LOCALE_SUPPLEMENTAL = 0x00000002; const uint LOCALE_SPECIFICDATA = 0x00000020; @@ -264,26 +267,64 @@ namespace System.Globalization return null; } - private static string GetLanguageDisplayName(string cultureName) + private string GetLanguageDisplayName(string cultureName) { +#if ENABLE_WINRT return WinRTInterop.Callbacks.GetLanguageDisplayName(cultureName); +#else + // Usually the UI culture shouldn't be different than what we got from WinRT except + // if DefaultThreadCurrentUICulture was set + CultureInfo ci; + + if (CultureInfo.DefaultThreadCurrentUICulture != null && + ((ci = GetUserDefaultCulture()) != null) && + !CultureInfo.DefaultThreadCurrentUICulture.Name.Equals(ci.Name)) + { + return SNATIVEDISPLAYNAME; + } + else + { + return GetLocaleInfo(cultureName, LocaleStringData.LocalizedDisplayName); + } +#endif // ENABLE_WINRT } - private static string GetRegionDisplayName(string isoCountryCode) + private string GetRegionDisplayName(string isoCountryCode) { +#if ENABLE_WINRT return WinRTInterop.Callbacks.GetRegionDisplayName(isoCountryCode); +#else + // Usually the UI culture shouldn't be different than what we got from WinRT except + // if DefaultThreadCurrentUICulture was set + CultureInfo ci; + + if (CultureInfo.DefaultThreadCurrentUICulture != null && + ((ci = GetUserDefaultCulture()) != null) && + !CultureInfo.DefaultThreadCurrentUICulture.Name.Equals(ci.Name)) + { + return SNATIVECOUNTRY; + } + else + { + return GetLocaleInfo(LocaleStringData.LocalizedCountryName); + } +#endif // ENABLE_WINRT } private static CultureInfo GetUserDefaultCulture() { +#if ENABLE_WINRT return (CultureInfo)WinRTInterop.Callbacks.GetUserDefaultCulture(); +#else + return CultureInfo.GetUserDefaultCulture(); +#endif // ENABLE_WINRT } // PAL methods end here. private static string GetLocaleInfoFromLCType(string localeName, uint lctype, bool useUserOveride) { - Contract.Assert(localeName != null, "[CultureData.GetLocaleInfoFromLCType] Expected localeName to be not be null"); + Debug.Assert(localeName != null, "[CultureData.GetLocaleInfoFromLCType] Expected localeName to be not be null"); // Fix lctype if we don't want overrides if (!useUserOveride) @@ -557,5 +598,76 @@ namespace System.Globalization return null; } + + private int LocaleNameToLCID(string cultureName) + { + return GetLocaleInfo(LocaleNumberData.LanguageId); + } + + private static string LCIDToLocaleName(int culture) + { + throw new NotImplementedException(); + } + + private int GetAnsiCodePage(string cultureName) + { + return GetLocaleInfo(LocaleNumberData.AnsiCodePage); + } + + private int GetOemCodePage(string cultureName) + { + return GetLocaleInfo(LocaleNumberData.OemCodePage); + } + + private int GetMacCodePage(string cultureName) + { + return GetLocaleInfo(LocaleNumberData.MacCodePage); + } + + private int GetEbcdicCodePage(string cultureName) + { + return GetLocaleInfo(LocaleNumberData.EbcdicCodePage); + } + + private int GetGeoId(string cultureName) + { + return GetLocaleInfo(LocaleNumberData.GeoId); + } + + private int GetDigitSubstitution(string cultureName) + { + return GetLocaleInfo(LocaleNumberData.DigitSubstitution); + } + + private string GetThreeLetterWindowsLanguageName(string cultureName) + { + return GetLocaleInfo(cultureName, LocaleStringData.AbbreviatedWindowsLanguageName); + } + + private static CultureInfo[] EnumCultures(CultureTypes types) + { + throw new NotImplementedException(); + } + + private string GetConsoleFallbackName(string cultureName) + { + return GetLocaleInfo(cultureName, LocaleStringData.ConsoleFallbackName); + } + + internal bool IsFramework + { + get { throw new NotImplementedException(); } + } + + internal bool IsWin32Installed + { + get { throw new NotImplementedException(); } + } + + internal bool IsReplacementCulture + { + get { throw new NotImplementedException(); } + } + } } diff --git a/src/mscorlib/corefx/System/Globalization/CultureData.cs b/src/mscorlib/corefx/System/Globalization/CultureData.cs index eb71318..c15a77c 100644 --- a/src/mscorlib/corefx/System/Globalization/CultureData.cs +++ b/src/mscorlib/corefx/System/Globalization/CultureData.cs @@ -2,25 +2,23 @@ // 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; using System.Collections.Generic; +using System.Diagnostics; using System.Text; using System.Threading; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Diagnostics.Contracts; namespace System.Globalization { #if INSIDE_CLR using StringStringDictionary = Dictionary; - using StringCultureDataDictionary = Dictionary; + using StringCultureDataDictionary = Dictionary; + using LcidToCultureNameDictionary = Dictionary; using Lock = Object; #else using StringStringDictionary = LowLevelDictionary; using StringCultureDataDictionary = LowLevelDictionary; + using LcidToCultureNameDictionary = LowLevelDictionary; #endif // @@ -57,8 +55,6 @@ namespace System.Globalization internal partial class CultureData { private const int undef = -1; - private const int LOCALE_CUSTOM_UNSPECIFIED = 0x1000; - private const int LOCALE_CUSTOM_DEFAULT = 0x0c00; // Override flag private String _sRealName; // Name you passed in (ie: en-US, en, or de-DE_phoneb) @@ -74,9 +70,13 @@ namespace System.Globalization // Language private String _sISO639Language; // ISO 639 Language Name + private String _sISO639Language2; // ISO 639 Language Name private String _sLocalizedLanguage; // Localized name for this language private String _sEnglishLanguage; // English name for this language private String _sNativeLanguage; // Native name of this language + private String _sAbbrevLang; // abbreviated language name (Windows Language Name) ex: ENU + private string _sConsoleFallbackName; // The culture name for the console fallback UI culture + private int _iInputLanguageHandle=undef;// input language handle // Region private String _sRegionName; // (RegionInfo) @@ -84,11 +84,12 @@ namespace System.Globalization private String _sEnglishCountry; // english country name (RegionInfo) private String _sNativeCountry; // native country name private String _sISO3166CountryName; // ISO 3166 (RegionInfo), ie: US + private String _sISO3166CountryName2; // 3 char ISO 3166 country name 2 2(RegionInfo) ex: USA (ISO) + private int _iGeoId = undef; // GeoId // Numbers private String _sPositiveSign; // (user can override) positive sign private String _sNegativeSign; // (user can override) negative sign - private String[] _saNativeDigits; // (user can override) native characters for digits 0-9 // (nfi populates these 5, don't have to be = undef) private int _iDigits; // (user can override) number of fractional digits private int _iNegativeNumber; // (user can override) negative number format @@ -108,6 +109,8 @@ namespace System.Globalization // Currency private String _sCurrency; // (user can override) local monetary symbol private String _sIntlMonetarySymbol; // international monetary symbol (RegionInfo) + private String _sEnglishCurrency; // English name for this currency + private String _sNativeCurrency; // Native name for this currency // (nfi populates these 4, don't have to be = undef) private int _iCurrencyDigits; // (user can override) # local monetary fractional digits private int _iCurrency; // (user can override) positive currency format @@ -145,6 +148,11 @@ namespace System.Globalization // CoreCLR depends on this even though its not exposed publicly. + private int _iDefaultAnsiCodePage = undef; // default ansi code page ID (ACP) + private int _iDefaultOemCodePage = undef; // default oem code page ID (OCP or OEM) + private int _iDefaultMacCodePage = undef; // default macintosh code page + private int _iDefaultEbcdicCodePage = undef; // default EBCDIC code page + private int _iLanguage; // locale ID (0409) - NO sort information private bool _bUseOverrides; // use user overrides? private bool _bNeutral; // Flags for the culture (ie: neutral or not right now) @@ -391,6 +399,42 @@ namespace System.Globalization return retVal; } + // Clear our internal caches + internal static void ClearCachedData() + { + s_cachedCultures = null; + s_cachedRegions = null; + } + + internal static CultureInfo[] GetCultures(CultureTypes types) + { + // Disable warning 618: System.Globalization.CultureTypes.FrameworkCultures' is obsolete +#pragma warning disable 618 + // Validate flags + if ((int)types <= 0 || ((int)types & (int)~(CultureTypes.NeutralCultures | CultureTypes.SpecificCultures | + CultureTypes.InstalledWin32Cultures | CultureTypes.UserCustomCulture | + CultureTypes.ReplacementCultures | CultureTypes.WindowsOnlyCultures | + CultureTypes.FrameworkCultures)) != 0) + { + throw new ArgumentOutOfRangeException(nameof(types), + SR.Format(SR.ArgumentOutOfRange_Range, CultureTypes.NeutralCultures, CultureTypes.FrameworkCultures)); + } + + // We have deprecated CultureTypes.FrameworkCultures. + // When this enum is used, we will enumerate Whidbey framework cultures (for compatibility). + // + + // We have deprecated CultureTypes.WindowsOnlyCultures. + // When this enum is used, we will return an empty array for this enum. + if ((types & CultureTypes.WindowsOnlyCultures) != 0) + { + // Remove the enum as it is an no-op. + types &= (~CultureTypes.WindowsOnlyCultures); + } + +#pragma warning restore 618 + return EnumCultures(types); + } ///////////////////////////////////////////////////////////////////////// // Build our invariant information @@ -422,20 +466,25 @@ namespace System.Globalization // Language invariant._sISO639Language = "iv"; // ISO 639 Language Name + invariant._sISO639Language2 = "ivl"; // 3 char ISO 639 lang name 2 invariant._sLocalizedLanguage = "Invariant Language"; // Display name for this Language invariant._sEnglishLanguage = "Invariant Language"; // English name for this language invariant._sNativeLanguage = "Invariant Language"; // Native name of this language + invariant._sAbbrevLang = "IVL"; // abbreviated language name (Windows Language Name) + invariant._sConsoleFallbackName = ""; // The culture name for the console fallback UI culture + invariant._iInputLanguageHandle = 0x07F; // input language handle // Region - invariant._sRegionName = "IV"; // (RegionInfo) - invariant._sEnglishCountry = "Invariant Country"; // english country name (RegionInfo) - invariant._sNativeCountry = "Invariant Country"; // native country name (Windows Only) - invariant._sISO3166CountryName = "IV"; // (RegionInfo), ie: US + invariant._sRegionName = "IV"; // (RegionInfo) + invariant._sEnglishCountry = "Invariant Country"; // english country name (RegionInfo) + invariant._sNativeCountry = "Invariant Country"; // native country name (Windows Only) + invariant._sISO3166CountryName = "IV"; // (RegionInfo), ie: US + invariant._sISO3166CountryName2 = "ivc"; // 3 char ISO 3166 country name 2 2(RegionInfo) + invariant._iGeoId = 244; // GeoId (Windows Only) // Numbers invariant._sPositiveSign = "+"; // positive sign invariant._sNegativeSign = "-"; // negative sign - invariant._saNativeDigits = new String[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; // native characters for digits 0-9 invariant._iDigits = 2; // number of fractional digits invariant._iNegativeNumber = 1; // negative number format invariant._waGrouping = new int[] { 3 }; // grouping of digits @@ -454,6 +503,8 @@ namespace System.Globalization // Currency invariant._sCurrency = "\x00a4"; // local monetary symbol: for international monetary symbol invariant._sIntlMonetarySymbol = "XDR"; // international monetary symbol (RegionInfo) + invariant._sEnglishCurrency = "International Monetary Fund"; // English name for this currency (Windows Only) + invariant._sNativeCurrency = "International Monetary Fund"; // Native name for this currency (Windows Only) invariant._iCurrencyDigits = 2; // # local monetary fractional digits invariant._iCurrency = 0; // positive currency format invariant._iNegativeCurrency = 0; // negative currency format @@ -487,7 +538,11 @@ namespace System.Globalization // These are desktop only, not coreclr - invariant._iLanguage = 0x007f; // locale ID (0409) - NO sort information + invariant._iLanguage = CultureInfo.LOCALE_INVARIANT; // locale ID (0409) - NO sort information + invariant._iDefaultAnsiCodePage = 1252; // default ansi code page ID (ACP) + invariant._iDefaultOemCodePage = 437; // default oem code page ID (OCP or OEM) + invariant._iDefaultMacCodePage = 10000; // default macintosh code page + invariant._iDefaultEbcdicCodePage = 037; // default EBCDIC code page // Remember it s_Invariant = invariant; } @@ -605,6 +660,33 @@ namespace System.Globalization return true; } + // We'd rather people use the named version since this doesn't allow custom locales + internal static CultureData GetCultureData(int culture, bool bUseUserOverride) + { + string localeName = null; + CultureData retVal = null; + + if (culture == CultureInfo.LOCALE_INVARIANT) + return Invariant; + + // Convert the lcid to a name, then use that + // Note that this'll return neutral names (unlike Vista native API) + localeName = LCIDToLocaleName(culture); + + if (!String.IsNullOrEmpty(localeName)) + { + // Valid name, use it + retVal = GetCultureData(localeName, bUseUserOverride); + } + + // If not successful, throw + if (retVal == null) + throw new CultureNotFoundException(nameof(culture), culture, SR.Argument_CultureNotSupported); + + // Return the one we found + return retVal; + } + //////////////////////////////////////////////////////////////////////// // // All the accessors @@ -622,7 +704,7 @@ namespace System.Globalization { get { - Contract.Assert(_sRealName != null, "[CultureData.CultureName] Expected _sRealName to be populated by already"); + Debug.Assert(_sRealName != null, "[CultureData.CultureName] Expected _sRealName to be populated by already"); // since windows doesn't know about zh-CHS and zh-CHT, // we leave sRealName == zh-Hanx but we still need to // pretend that it was zh-CHX. @@ -834,6 +916,17 @@ namespace System.Globalization } } + // The culture name to be used in CultureInfo.CreateSpecificCulture() + internal string SSPECIFICCULTURE + { + get + { + // This got populated during the culture initialization + Debug.Assert(_sSpecificCulture != null, "[CultureData.SSPECIFICCULTURE] Expected this.sSpecificCulture to be populated by culture data initialization already"); + return _sSpecificCulture; + } + } + ///////////// // Language // ///////////// @@ -845,12 +938,38 @@ namespace System.Globalization { if (_sISO639Language == null) { - _sISO639Language = GetLocaleInfo(LocaleStringData.Iso639LanguageName); + _sISO639Language = GetLocaleInfo(LocaleStringData.Iso639LanguageTwoLetterName); } return _sISO639Language; } } + // iso 639 language name, ie: eng + internal string SISO639LANGNAME2 + { + get + { + if (_sISO639Language2 == null) + { + _sISO639Language2 = GetLocaleInfo(LocaleStringData.Iso639LanguageThreeLetterName); + } + return _sISO639Language2; + } + } + + // abbreviated windows language name (ie: enu) (non-standard, avoid this) + internal string SABBREVLANGNAME + { + get + { + if (_sAbbrevLang == null) + { + _sAbbrevLang = GetThreeLetterWindowsLanguageName(_sRealName); + } + return _sAbbrevLang; + } + } + // Localized name for this language (Windows Only) ie: Inglis // This is only valid for Windows 8 and higher neutrals: internal String SLOCALIZEDLANGUAGE @@ -922,6 +1041,17 @@ namespace System.Globalization } } + internal int IGEOID + { + get + { + if (_iGeoId == undef) + { + _iGeoId = GetGeoId(_sRealName); + } + return _iGeoId; + } + } // localized name for the country internal string SLOCALIZEDCOUNTRY @@ -987,17 +1117,51 @@ namespace System.Globalization } } - ///////////// - // Numbers // - //////////// - - // internal String sPositiveSign ; // (user can override) positive sign - // internal String sNegativeSign ; // (user can override) negative sign - // internal String[] saNativeDigits ; // (user can override) native characters for digits 0-9 - // internal int iDigits ; // (user can override) number of fractional digits - // internal int iNegativeNumber ; // (user can override) negative number format + // 3 letter ISO 3166 country code + internal String SISO3166CTRYNAME2 + { + get + { + if (_sISO3166CountryName2 == null) + { + _sISO3166CountryName2 = GetLocaleInfo(LocaleStringData.Iso3166CountryName2); + } + return _sISO3166CountryName2; + } + } + internal int IINPUTLANGUAGEHANDLE + { + get + { + if (_iInputLanguageHandle == undef) + { + if (IsSupplementalCustomCulture) + { + _iInputLanguageHandle = 0x0409; + } + else + { + // Input Language is same as LCID for built-in cultures + _iInputLanguageHandle = this.ILANGUAGE; + } + } + return _iInputLanguageHandle; + } + } + // Console fallback name (ie: locale to use for console apps for unicode-only locales) + internal string SCONSOLEFALLBACKNAME + { + get + { + if (_sConsoleFallbackName == null) + { + _sConsoleFallbackName = GetConsoleFallbackName(_sRealName); + } + return _sConsoleFallbackName; + } + } // (user can override) grouping of digits internal int[] WAGROUPING @@ -1144,6 +1308,32 @@ namespace System.Globalization } } + // English name for this currency (RegionInfo), eg: US Dollar + internal String SENGLISHCURRENCY + { + get + { + if (_sEnglishCurrency == null) + { + _sEnglishCurrency = GetLocaleInfo(LocaleStringData.CurrencyEnglishName); + } + return _sEnglishCurrency; + } + } + + // Native name for this currency (RegionInfo), eg: Schweiz Frank + internal String SNATIVECURRENCY + { + get + { + if (_sNativeCurrency == null) + { + _sNativeCurrency = GetLocaleInfo(LocaleStringData.CurrencyNativeName); + } + return _sNativeCurrency; + } + } + // internal int iCurrencyDigits ; // (user can override) # local monetary fractional digits // internal int iCurrency ; // (user can override) positive currency format // internal int iNegativeCurrency ; // (user can override) negative currency format @@ -1522,7 +1712,7 @@ namespace System.Globalization // We then have to copy that list to a new array of the right size. // Default calendar should be first CalendarId[] calendars = new CalendarId[23]; - Contract.Assert(_sWindowsName != null, "[CultureData.CalendarIds] Expected _sWindowsName to be populated by already"); + Debug.Assert(_sWindowsName != null, "[CultureData.CalendarIds] Expected _sWindowsName to be populated by already"); int count = CalendarData.GetCalendars(_sWindowsName, _bUseOverrides, calendars); // See if we had a calendar to add. @@ -1585,9 +1775,16 @@ namespace System.Globalization } } + // Native calendar names. index of optional calendar - 1, empty if no optional calendar at that number + internal string CalendarName(CalendarId calendarId) + { + // Get the calendar + return GetCalendar(calendarId).sNativeName; + } + internal CalendarData GetCalendar(CalendarId calendarId) { - Contract.Assert(calendarId > 0 && calendarId <= CalendarId.LAST_CALENDAR, + Debug.Assert(calendarId > 0 && calendarId <= CalendarId.LAST_CALENDAR, "[CultureData.GetCalendar] Expect calendarId to be in a valid range"); // arrays are 0 based, calendarIds are 1 based @@ -1606,7 +1803,7 @@ namespace System.Globalization // Make sure that calendar has data if (calendarData == null) { - Contract.Assert(_sWindowsName != null, "[CultureData.GetCalendar] Expected _sWindowsName to be populated by already"); + Debug.Assert(_sWindowsName != null, "[CultureData.GetCalendar] Expected _sWindowsName to be populated by already"); calendarData = new CalendarData(_sWindowsName, calendarId, this.UseUserOverride); _calendars[calendarIndex] = calendarData; } @@ -1646,7 +1843,7 @@ namespace System.Globalization { if (_iReadingLayout == undef) { - Contract.Assert(_sRealName != null, "[CultureData.IsRightToLeft] Expected _sRealName to be populated by already"); + Debug.Assert(_sRealName != null, "[CultureData.IsRightToLeft] Expected _sRealName to be populated by already"); _iReadingLayout = GetLocaleInfo(LocaleNumberData.ReadingLayout); } @@ -1667,8 +1864,8 @@ namespace System.Globalization { // Note: Custom cultures might point at another culture's textinfo, however windows knows how // to redirect it to the desired textinfo culture, so this is OK. - Contract.Assert(_sWindowsName != null, "[CultureData.STEXTINFO] Expected _sWindowsName to be populated by already"); - return (_sWindowsName); + Debug.Assert(_sRealName != null, "[CultureData.STEXTINFO] Expected _sRealName to be populated by already"); + return (_sRealName); } } @@ -1677,8 +1874,8 @@ namespace System.Globalization { get { - Contract.Assert(_sWindowsName != null, "[CultureData.SCOMPAREINFO] Expected _sWindowsName to be populated by already"); - return (_sWindowsName); + Debug.Assert(_sRealName != null, "[CultureData.SCOMPAREINFO] Expected _sRealName to be populated by already"); + return (_sRealName); } } @@ -1690,10 +1887,63 @@ namespace System.Globalization } } + internal int IDEFAULTANSICODEPAGE // default ansi code page ID (ACP) + { + get + { + if (_iDefaultAnsiCodePage == undef) + { + _iDefaultAnsiCodePage = GetAnsiCodePage(_sRealName); + } + return _iDefaultAnsiCodePage; + } + } + + internal int IDEFAULTOEMCODEPAGE // default oem code page ID (OCP or OEM) + { + get + { + if (_iDefaultOemCodePage == undef) + { + _iDefaultOemCodePage = GetOemCodePage(_sRealName); + } + return _iDefaultOemCodePage; + } + } + + internal int IDEFAULTMACCODEPAGE // default macintosh code page + { + get + { + if (_iDefaultMacCodePage == undef) + { + _iDefaultMacCodePage = GetMacCodePage(_sRealName); + } + return _iDefaultMacCodePage; + } + } + + internal int IDEFAULTEBCDICCODEPAGE // default EBCDIC code page + { + get + { + if (_iDefaultEbcdicCodePage == undef) + { + _iDefaultEbcdicCodePage = GetEbcdicCodePage(_sRealName); + } + return _iDefaultEbcdicCodePage; + } + } + internal int ILANGUAGE { get { + if (_iLanguage == 0) + { + Debug.Assert(_sRealName != null, "[CultureData.ILANGUAGE] Expected this.sRealName to be populated by COMNlsInfo::nativeInitCultureData already"); + _iLanguage = LocaleNameToLCID(_sRealName); + } return _iLanguage; } } @@ -1734,21 +1984,21 @@ namespace System.Globalization // All of our era names internal String[] EraNames(CalendarId calendarId) { - Contract.Assert(calendarId > 0, "[CultureData.saEraNames] Expected Calendar.ID > 0"); + Debug.Assert(calendarId > 0, "[CultureData.saEraNames] Expected Calendar.ID > 0"); return this.GetCalendar(calendarId).saEraNames; } internal String[] AbbrevEraNames(CalendarId calendarId) { - Contract.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0"); + Debug.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0"); return this.GetCalendar(calendarId).saAbbrevEraNames; } internal String[] AbbreviatedEnglishEraNames(CalendarId calendarId) { - Contract.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0"); + Debug.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0"); return this.GetCalendar(calendarId).saAbbrevEnglishEraNames; } @@ -1808,9 +2058,9 @@ namespace System.Globalization //////////////////////////////////////////////////////////////////////////// private static String UnescapeNlsString(String str, int start, int end) { - Contract.Requires(str != null); - Contract.Requires(start >= 0); - Contract.Requires(end >= 0); + Debug.Assert(str != null); + Debug.Assert(start >= 0); + Debug.Assert(end >= 0); StringBuilder result = null; for (int i = start; i < str.Length && i <= end; i++) @@ -1908,8 +2158,8 @@ namespace System.Globalization private static int IndexOfTimePart(string format, int startIndex, string timeParts) { - Contract.Assert(startIndex >= 0, "startIndex cannot be negative"); - Contract.Assert(timeParts.IndexOfAny(new char[] { '\'', '\\' }) == -1, "timeParts cannot include quote characters"); + Debug.Assert(startIndex >= 0, "startIndex cannot be negative"); + Debug.Assert(timeParts.IndexOfAny(new char[] { '\'', '\\' }) == -1, "timeParts cannot include quote characters"); bool inQuote = false; for (int i = startIndex; i < format.Length; ++i) { @@ -1944,9 +2194,9 @@ namespace System.Globalization return -1; } - private static bool IsCustomCultureId(int cultureId) + internal static bool IsCustomCultureId(int cultureId) { - return (cultureId == LOCALE_CUSTOM_DEFAULT || cultureId == LOCALE_CUSTOM_UNSPECIFIED); + return (cultureId == CultureInfo.LOCALE_CUSTOM_DEFAULT || cultureId == CultureInfo.LOCALE_CUSTOM_UNSPECIFIED); } internal void GetNFIValues(NumberFormatInfo nfi) @@ -1954,7 +2204,6 @@ namespace System.Globalization if (this.IsInvariantCulture) { // FUTURE: NumberFormatInfo already has default values for many of these fields. Can we not do this? - // if we do need to do this, then why don't we set nfi.nativeDigits in this case? nfi.positiveSign = _sPositiveSign; nfi.negativeSign = _sNegativeSign; @@ -1972,7 +2221,7 @@ namespace System.Globalization } else { - Contract.Assert(_sWindowsName != null, "[CultureData.GetNFIValues] Expected _sWindowsName to be populated by already"); + Debug.Assert(_sWindowsName != null, "[CultureData.GetNFIValues] Expected _sWindowsName to be populated by already"); // String values nfi.positiveSign = GetLocaleInfo(LocaleStringData.PositiveSign); nfi.negativeSign = GetLocaleInfo(LocaleStringData.NegativeSign); @@ -1997,6 +2246,8 @@ namespace System.Globalization { nfi.nativeDigits[i] = new string(digits[i], 1); } + + nfi.digitSubstitution = GetDigitSubstitution(_sRealName); } // @@ -2043,9 +2294,26 @@ namespace System.Globalization // This is ONLY used for caching names and shouldn't be used for anything else internal static string AnsiToLower(string testString) { + int index = 0; + + while (index'Z' )) + { + index++; + } + if (index >= testString.Length) + { + return testString; // we didn't really change the string + } + StringBuilder sb = new StringBuilder(testString.Length); + for (int i=0; i= 'A' ? (char)(ch - 'A' + 'a') : ch); @@ -2072,10 +2340,14 @@ namespace System.Globalization EnglishLanguageName = 0x00001001, /// native name of language, eg "Deutsch" (coresponds to LOCALE_SNATIVELANGUAGENAME) NativeLanguageName = 0x00000004, + /// localized name of country, eg "Germany" in UI language (coresponds to LOCALE_SLOCALIZEDCOUNTRYNAME) + LocalizedCountryName = 0x00000006, /// English name of country, eg "Germany" (coresponds to LOCALE_SENGLISHCOUNTRYNAME) EnglishCountryName = 0x00001002, /// native name of country, eg "Deutschland" (coresponds to LOCALE_SNATIVECOUNTRYNAME) NativeCountryName = 0x00000008, + /// abbreviated language name (coresponds to LOCALE_SABBREVLANGNAME) + AbbreviatedWindowsLanguageName = 0x00000003, /// list item separator (coresponds to LOCALE_SLIST) ListSeparator = 0x0000000C, /// decimal separator (coresponds to LOCALE_SDECIMAL) @@ -2086,6 +2358,10 @@ namespace System.Globalization Digits = 0x00000013, /// local monetary symbol (coresponds to LOCALE_SCURRENCY) MonetarySymbol = 0x00000014, + /// English currency name (coresponds to LOCALE_SENGCURRNAME) + CurrencyEnglishName = 0x00001007, + /// Native currency name (coresponds to LOCALE_SNATIVECURRNAME) + CurrencyNativeName = 0x00001008, /// uintl monetary symbol (coresponds to LOCALE_SINTLSYMBOL) Iso4217MonetarySymbol = 0x00000015, /// monetary decimal separator (coresponds to LOCALE_SMONDECIMALSEP) @@ -2101,9 +2377,15 @@ namespace System.Globalization /// negative sign (coresponds to LOCALE_SNEGATIVESIGN) NegativeSign = 0x00000051, /// ISO abbreviated language name (coresponds to LOCALE_SISO639LANGNAME) + Iso639LanguageTwoLetterName = 0x00000059, + /// ISO abbreviated country name (coresponds to LOCALE_SISO639LANGNAME2) + Iso639LanguageThreeLetterName = 0x00000067, + /// ISO abbreviated language name (coresponds to LOCALE_SISO639LANGNAME) Iso639LanguageName = 0x00000059, /// ISO abbreviated country name (coresponds to LOCALE_SISO3166CTRYNAME) Iso3166CountryName = 0x0000005A, + /// 3 letter ISO country code (coresponds to LOCALE_SISO3166CTRYNAME2) + Iso3166CountryName2 = 0x00000068, // 3 character ISO country name /// Not a Number (coresponds to LOCALE_SNAN) NaNSymbol = 0x00000069, /// + Infinity (coresponds to LOCALE_SPOSINFINITY) @@ -2112,6 +2394,8 @@ namespace System.Globalization NegativeInfinitySymbol = 0x0000006b, /// Fallback name for resources (coresponds to LOCALE_SPARENT) ParentName = 0x0000006d, + /// Fallback name for within the console (coresponds to LOCALE_SCONSOLEFALLBACKNAME) + ConsoleFallbackName = 0x0000006e, /// Returns the percent symbol (coresponds to LOCALE_SPERCENT) PercentSymbol = 0x00000076, /// Returns the permille (U+2030) symbol (coresponds to LOCALE_SPERMILLE) @@ -2138,6 +2422,10 @@ namespace System.Globalization { /// language id (coresponds to LOCALE_ILANGUAGE) LanguageId = 0x00000001, + /// geographical location id, (coresponds to LOCALE_IGEOID) + GeoId = 0x00000008, + /// 0 = context, 1 = none, 2 = national (coresponds to LOCALE_IDIGITSUBSTITUTION) + DigitSubstitution = 0x00001014, /// 0 = metric, 1 = US (coresponds to LOCALE_IMEASURE) MeasurementSystem = 0x0000000D, /// number of fractional digits (coresponds to LOCALE_IDIGITS) @@ -2168,7 +2456,15 @@ namespace System.Globalization /// Returns 0-11 for the negative percent format (coresponds to LOCALE_INEGATIVEPERCENT) NegativePercentFormat = 0x00000074, /// Returns 0-3 for the positive percent format (coresponds to LOCALE_IPOSITIVEPERCENT) - PositivePercentFormat = 0x00000075 + PositivePercentFormat = 0x00000075, + /// default ansi code page (coresponds to LOCALE_IDEFAULTCODEPAGE) + OemCodePage = 0x0000000B, + /// default ansi code page (coresponds to LOCALE_IDEFAULTANSICODEPAGE) + AnsiCodePage = 0x00001004, + /// default mac code page (coresponds to LOCALE_IDEFAULTMACCODEPAGE) + MacCodePage = 0x00001011, + /// default ebcdic code page (coresponds to LOCALE_IDEFAULTEBCDICCODEPAGE) + EbcdicCodePage = 0x00001012, } } } diff --git a/src/mscorlib/corefx/System/Globalization/CultureInfo.Windows.cs b/src/mscorlib/corefx/System/Globalization/CultureInfo.Windows.cs index 16c8a06..c019eb2 100644 --- a/src/mscorlib/corefx/System/Globalization/CultureInfo.Windows.cs +++ b/src/mscorlib/corefx/System/Globalization/CultureInfo.Windows.cs @@ -2,7 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if ENABLE_WINRT using Internal.Runtime.Augments; +#endif namespace System.Globalization { @@ -16,16 +18,18 @@ namespace System.Globalization /// private static CultureInfo GetUserDefaultCultureCacheOverride() { +#if ENABLE_WINRT WinRTInteropCallbacks callbacks = WinRTInterop.UnsafeCallbacks; if (callbacks != null && callbacks.IsAppxModel()) { return (CultureInfo)callbacks.GetUserDefaultCulture(); } +#endif return null; } - private static CultureInfo GetUserDefaultCulture() + internal static CultureInfo GetUserDefaultCulture() { const uint LOCALE_SNAME = 0x0000005c; const string LOCALE_NAME_USER_DEFAULT = null; diff --git a/src/mscorlib/corefx/System/Globalization/CultureInfo.cs b/src/mscorlib/corefx/System/Globalization/CultureInfo.cs index f2b3742..da084d1 100644 --- a/src/mscorlib/corefx/System/Globalization/CultureInfo.cs +++ b/src/mscorlib/corefx/System/Globalization/CultureInfo.cs @@ -1,4 +1,4 @@ -// 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. // See the LICENSE file in the project root for more information. @@ -26,15 +26,10 @@ // //////////////////////////////////////////////////////////////////////////// -using System; -using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; -using System.Runtime; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using System.Runtime.Serialization; -using System.Security; using System.Threading; namespace System.Globalization @@ -42,9 +37,12 @@ namespace System.Globalization #if INSIDE_CLR using StringCultureInfoDictionary = Dictionary; + using StringLcidDictionary = Dictionary; + using Lock = Object; #else using StringCultureInfoDictionary = LowLevelDictionary; + using StringLcidDictionary = LowLevelDictionary; #endif [Serializable] @@ -79,6 +77,9 @@ namespace System.Globalization [NonSerialized] internal bool m_isInherited; + [NonSerialized] + private CultureInfo m_consoleFallbackCulture; + // Names are confusing. Here are 3 names we have: // // new CultureInfo() m_name m_nonSortName m_sortName @@ -106,7 +107,6 @@ namespace System.Globalization [NonSerialized] private string m_sortName; - //--------------------------------------------------------------------// // // Static data members @@ -139,11 +139,21 @@ namespace System.Globalization private static readonly Lock m_lock = new Lock(); private static volatile StringCultureInfoDictionary s_NameCachedCultures; + private static volatile StringLcidDictionary s_LcidCachedCultures; //The parent culture. [NonSerialized] private CultureInfo m_parent; + // LOCALE constants of interest to us internally and privately for LCID functions + // (ie: avoid using these and use names if possible) + internal const int LOCALE_NEUTRAL = 0x0000; + private const int LOCALE_USER_DEFAULT = 0x0400; + private const int LOCALE_SYSTEM_DEFAULT = 0x0800; + internal const int LOCALE_CUSTOM_UNSPECIFIED = 0x1000; + internal const int LOCALE_CUSTOM_DEFAULT = 0x0c00; + internal const int LOCALE_INVARIANT = 0x007F; + static AsyncLocal s_asyncLocalCurrentCulture; static AsyncLocal s_asyncLocalCurrentUICulture; @@ -189,17 +199,55 @@ namespace System.Globalization } - internal CultureInfo(String name, bool useUserOverride) + public CultureInfo(String name, bool useUserOverride) { if (name == null) { - throw new ArgumentNullException("name", + throw new ArgumentNullException(nameof(name), SR.ArgumentNull_String); } InitializeFromName(name, useUserOverride); } + public CultureInfo(int culture) : this(culture, true) + { + } + + public CultureInfo(int culture, bool useUserOverride) + { + // We don't check for other invalid LCIDS here... + if (culture < 0) + { + throw new ArgumentOutOfRangeException(nameof(culture), SR.ArgumentOutOfRange_NeedPosNum); + } + Contract.EndContractBlock(); + + InitializeFromCultureId(culture, useUserOverride); + } + + private void InitializeFromCultureId(int culture, bool useUserOverride) + { + switch (culture) + { + case LOCALE_CUSTOM_DEFAULT: + case LOCALE_SYSTEM_DEFAULT: + case LOCALE_NEUTRAL: + case LOCALE_USER_DEFAULT: + case LOCALE_CUSTOM_UNSPECIFIED: + // Can't support unknown custom cultures and we do not support neutral or + // non-custom user locales. + throw new CultureNotFoundException(nameof(culture), culture, SR.Argument_CultureNotSupported); + + default: + // Now see if this LCID is supported in the system default CultureData table. + m_cultureData = CultureData.GetCultureData(culture, useUserOverride); + break; + } + m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo)); + m_name = m_cultureData.CultureName; + } + private void InitializeFromName(string name, bool useUserOverride) { // Get our data providing record @@ -207,13 +255,38 @@ namespace System.Globalization if (this.m_cultureData == null) { - throw new CultureNotFoundException("name", name, SR.Argument_CultureNotSupported); + throw new CultureNotFoundException(nameof(name), name, SR.Argument_CultureNotSupported); } this.m_name = this.m_cultureData.CultureName; this.m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo)); } + // Constructor called by SQL Server's special munged culture - creates a culture with + // a TextInfo and CompareInfo that come from a supplied alternate source. This object + // is ALWAYS read-only. + // Note that we really cannot use an LCID version of this override as the cached + // name we create for it has to include both names, and the logic for this is in + // the GetCultureInfo override *only*. + internal CultureInfo(String cultureName, String textAndCompareCultureName) + { + if (cultureName == null) + { + throw new ArgumentNullException(nameof(cultureName),SR.ArgumentNull_String); + } + Contract.EndContractBlock(); + + m_cultureData = CultureData.GetCultureData(cultureName, false); + if (m_cultureData == null) + throw new CultureNotFoundException(nameof(cultureName), cultureName, SR.Argument_CultureNotSupported); + + m_name = m_cultureData.CultureName; + + CultureInfo altCulture = GetCultureInfo(textAndCompareCultureName); + compareInfo = altCulture.CompareInfo; + textInfo = altCulture.TextInfo; + } + // We do this to try to return the system UI language and the default user languages // This method will fallback if this fails (like Invariant) // @@ -239,6 +312,66 @@ namespace System.Globalization return ci; } + // + // Return a specific culture. A tad irrelevent now since we always return valid data + // for neutral locales. + // + // Note that there's interesting behavior that tries to find a smaller name, ala RFC4647, + // if we can't find a bigger name. That doesn't help with things like "zh" though, so + // the approach is of questionable value + // + public static CultureInfo CreateSpecificCulture(String name) + { + Contract.Ensures(Contract.Result() != null); + + CultureInfo culture; + + try + { + culture = new CultureInfo(name); + } + catch (ArgumentException) + { + // When CultureInfo throws this exception, it may be because someone passed the form + // like "az-az" because it came out of an http accept lang. We should try a little + // parsing to perhaps fall back to "az" here and use *it* to create the neutral. + + int idx; + + culture = null; + for (idx = 0; idx < name.Length; idx++) + { + if ('-' == name[idx]) + { + try + { + culture = new CultureInfo(name.Substring(0, idx)); + break; + } + catch (ArgumentException) + { + // throw the original exception so the name in the string will be right + throw; + } + } + } + + if (culture == null) + { + // nothing to save here; throw the original exception + throw; + } + } + + // In the most common case, they've given us a specific culture, so we'll just return that. + if (!(culture.IsNeutralCulture)) + { + return culture; + } + + return (new CultureInfo(culture.m_cultureData.SSPECIFICCULTURE)); + } + // // // // Return a specific culture. A tad irrelevent now since we always return valid data // // for neutral locales. @@ -296,7 +429,7 @@ namespace System.Globalization [OnDeserialized] private void OnDeserialized(StreamingContext ctx) { - Contract.Assert(m_name != null, "[CultureInfo.OnDeserialized] m_name != null"); + Debug.Assert(m_name != null, "[CultureInfo.OnDeserialized] m_name != null"); InitializeFromName(m_name, m_useUserOverride); } @@ -348,7 +481,7 @@ namespace System.Globalization Init(); } - Contract.Assert(s_userDefaultCulture != null); + Debug.Assert(s_userDefaultCulture != null); return s_userDefaultCulture; } @@ -356,7 +489,7 @@ namespace System.Globalization { if (value == null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } if (s_asyncLocalCurrentCulture == null) @@ -396,7 +529,7 @@ namespace System.Globalization Init(); } - Contract.Assert(s_userDefaultCulture != null); + Debug.Assert(s_userDefaultCulture != null); return s_userDefaultCulture; } @@ -404,7 +537,7 @@ namespace System.Globalization { if (value == null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } CultureInfo.VerifyCultureName(value, true); @@ -419,6 +552,20 @@ namespace System.Globalization } } + public static CultureInfo InstalledUICulture + { + get + { + Contract.Ensures(Contract.Result() != null); + if (s_userDefaultCulture == null) + { + Init(); + } + Debug.Assert(s_userDefaultCulture != null, "[CultureInfo.InstalledUICulture] s_userDefaultCulture != null"); + return s_userDefaultCulture; + } + } + public static CultureInfo DefaultThreadCurrentCulture { get { return s_DefaultThreadCurrentCulture; } @@ -513,6 +660,34 @@ namespace System.Globalization } } + public virtual int LCID + { + get + { + return (this.m_cultureData.ILANGUAGE); + } + } + + public virtual int KeyboardLayoutId + { + get + { + return m_cultureData.IINPUTLANGUAGEHANDLE; + } + } + + public static CultureInfo[] GetCultures(CultureTypes types) + { + Contract.Ensures(Contract.Result() != null); + // internally we treat UserCustomCultures as Supplementals but v2 + // treats as Supplementals and Replacements + if((types & CultureTypes.UserCustomCulture) == CultureTypes.UserCustomCulture) + { + types |= CultureTypes.ReplacementCultures; + } + return (CultureData.GetCultures(types)); + } + //////////////////////////////////////////////////////////////////////// // // Name @@ -552,6 +727,24 @@ namespace System.Globalization } } + public string IetfLanguageTag + { + get + { + Contract.Ensures(Contract.Result() != null); + + // special case the compatibility cultures + switch (this.Name) + { + case "zh-CHT": + return "zh-Hant"; + case "zh-CHS": + return "zh-Hans"; + default: + return this.Name; + } + } + } //////////////////////////////////////////////////////////////////////// // @@ -567,7 +760,7 @@ namespace System.Globalization get { Contract.Ensures(Contract.Result() != null); - Contract.Assert(m_name != null, "[CultureInfo.DisplayName] Always expect m_name to be set"); + Debug.Assert(m_name != null, "[CultureInfo.DisplayName] Always expect m_name to be set"); return m_cultureData.SLOCALIZEDDISPLAYNAME; } @@ -619,6 +812,32 @@ namespace System.Globalization } } + // ie: eng + public virtual String ThreeLetterISOLanguageName + { + get + { + Contract.Ensures(Contract.Result() != null); + return m_cultureData.SISO639LANGNAME2; + } + } + + //////////////////////////////////////////////////////////////////////// + // + // ThreeLetterWindowsLanguageName + // + // Returns the 3 letter windows language name for the current instance. eg: "ENU" + // The ISO names are much preferred + // + //////////////////////////////////////////////////////////////////////// + public virtual String ThreeLetterWindowsLanguageName + { + get + { + Contract.Ensures(Contract.Result() != null); + return m_cultureData.SABBREVLANGNAME; + } + } //////////////////////////////////////////////////////////////////////// // @@ -767,6 +986,31 @@ namespace System.Globalization } } + public CultureTypes CultureTypes + { + get + { + CultureTypes types = 0; + + if (m_cultureData.IsNeutralCulture) + types |= CultureTypes.NeutralCultures; + else + types |= CultureTypes.SpecificCultures; + + types |= m_cultureData.IsWin32Installed ? CultureTypes.InstalledWin32Cultures : 0; + +// Disable warning 618: System.Globalization.CultureTypes.FrameworkCultures' is obsolete +#pragma warning disable 618 + types |= m_cultureData.IsFramework ? CultureTypes.FrameworkCultures : 0; + +#pragma warning restore 618 + types |= m_cultureData.IsSupplementalCustomCulture ? CultureTypes.UserCustomCulture : 0; + types |= m_cultureData.IsReplacementCulture ? CultureTypes.ReplacementCultures | CultureTypes.UserCustomCulture : 0; + + return types; + } + } + public virtual NumberFormatInfo NumberFormat { get @@ -775,7 +1019,7 @@ namespace System.Globalization { NumberFormatInfo temp = new NumberFormatInfo(this.m_cultureData); temp.isReadOnly = m_isReadOnly; - numInfo = temp; + Interlocked.CompareExchange(ref numInfo, temp, null); } return (numInfo); } @@ -783,7 +1027,7 @@ namespace System.Globalization { if (value == null) { - throw new ArgumentNullException("value", SR.ArgumentNull_Obj); + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_Obj); } VerifyWritable(); numInfo = value; @@ -807,8 +1051,7 @@ namespace System.Globalization // Change the calendar of DTFI to the specified calendar of this CultureInfo. DateTimeFormatInfo temp = new DateTimeFormatInfo(this.m_cultureData, this.Calendar); temp._isReadOnly = m_isReadOnly; - System.Threading.Interlocked.MemoryBarrier(); - dateTimeInfo = temp; + Interlocked.CompareExchange(ref dateTimeInfo, temp, null); } return (dateTimeInfo); } @@ -817,13 +1060,28 @@ namespace System.Globalization { if (value == null) { - throw new ArgumentNullException("value", SR.ArgumentNull_Obj); + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_Obj); } VerifyWritable(); dateTimeInfo = value; } } + public void ClearCachedData() + { + s_userDefaultCulture = null; + + RegionInfo.s_currentRegionInfo = null; + #pragma warning disable 0618 // disable the obsolete warning + TimeZone.ResetTimeZone(); + #pragma warning restore 0618 + TimeZoneInfo.ClearCachedData(); + s_LcidCachedCultures = null; + s_NameCachedCultures = null; + + CultureData.ClearCachedData(); + } + /*=================================GetCalendarInstance========================== **Action: Map a Win32 CALID to an instance of supported calendar. **Returns: An instance of calendar. @@ -845,7 +1103,7 @@ namespace System.Globalization //calendars unless they're required. internal static Calendar GetCalendarInstanceRare(CalendarId calType) { - Contract.Assert(calType != CalendarId.GREGORIAN, "calType!=CalendarId.GREGORIAN"); + Debug.Assert(calType != CalendarId.GREGORIAN, "calType!=CalendarId.GREGORIAN"); switch (calType) { @@ -889,7 +1147,7 @@ namespace System.Globalization { if (calendar == null) { - Contract.Assert(this.m_cultureData.CalendarIds.Length > 0, "this.m_cultureData.CalendarIds.Length > 0"); + Debug.Assert(this.m_cultureData.CalendarIds.Length > 0, "this.m_cultureData.CalendarIds.Length > 0"); // Get the default calendar for this culture. Note that the value can be // from registry if this is a user default culture. Calendar newObj = this.m_cultureData.DefaultCalendar; @@ -929,13 +1187,26 @@ namespace System.Globalization } } - - private bool UseUserOverride + public bool UseUserOverride { get { - return (this.m_cultureData.UseUserOverride); + return m_cultureData.UseUserOverride; + } + } + + public CultureInfo GetConsoleFallbackUICulture() + { + Contract.Ensures(Contract.Result() != null); + + CultureInfo temp = m_consoleFallbackCulture; + if (temp == null) + { + temp = CreateSpecificCulture(m_cultureData.SCONSOLEFALLBACKNAME); + temp.m_isReadOnly = true; + m_consoleFallbackCulture = temp; } + return (temp); } public virtual Object Clone() @@ -979,7 +1250,7 @@ namespace System.Globalization { if (ci == null) { - throw new ArgumentNullException("ci"); + throw new ArgumentNullException(nameof(ci)); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -1054,26 +1325,25 @@ namespace System.Globalization get { return Name == CultureInfo.InvariantCulture.Name; } } - // Helper function both both overloads of GetCachedReadOnlyCulture. - internal static CultureInfo GetCultureInfoHelper(string name) + // Helper function both both overloads of GetCachedReadOnlyCulture. If lcid is 0, we use the name. + // If lcid is -1, use the altName and create one of those special SQL cultures. + internal static CultureInfo GetCultureInfoHelper(int lcid, string name, string altName) { - // There is a race condition in this code with the side effect that the second thread's value - // clobbers the first in the dictionary. This is an acceptable race since the CultureInfo objects - // are content equal (but not reference equal). Since we make no guarantees there, this race is - // acceptable. - // retval is our return value. CultureInfo retval; - if (name == null) - { - return null; - } - // Temporary hashtable for the names. StringCultureInfoDictionary tempNameHT = s_NameCachedCultures; - name = CultureData.AnsiToLower(name); + if (name != null) + { + name = CultureData.AnsiToLower(name); + } + + if (altName != null) + { + altName = CultureData.AnsiToLower(altName); + } // We expect the same result for both hashtables, but will test individually for added safety. if (tempNameHT == null) @@ -1082,20 +1352,66 @@ namespace System.Globalization } else { - bool ret; - lock (m_lock) + // If we are called by name, check if the object exists in the hashtable. If so, return it. + if (lcid == -1 || lcid == 0) { - ret = tempNameHT.TryGetValue(name, out retval); + bool ret; + lock (m_lock) + { + ret = tempNameHT.TryGetValue(lcid == 0 ? name : name + '\xfffd' + altName, out retval); + } + + if (ret && retval != null) + { + return retval; + } } + } - if (ret && retval != null) + // Next, the Lcid table. + StringLcidDictionary tempLcidHT = s_LcidCachedCultures; + + if (tempLcidHT == null) + { + // Case insensitive is not an issue here, save the constructor call. + tempLcidHT = new StringLcidDictionary(); + } + else + { + // If we were called by Lcid, check if the object exists in the table. If so, return it. + if (lcid > 0) { - return retval; + bool ret; + lock (m_lock) + { + ret = tempLcidHT.TryGetValue(lcid, out retval); + } + if (ret && retval != null) + { + return retval; + } } } + + // We now have two temporary hashtables and the desired object was not found. + // We'll construct it. We catch any exceptions from the constructor call and return null. try { - retval = new CultureInfo(name, false); + switch (lcid) + { + case -1: + // call the private constructor + retval = new CultureInfo(name, altName); + break; + + case 0: + retval = new CultureInfo(name, false); + break; + + default: + retval = new CultureInfo(lcid, false); + break; + } } catch (ArgumentException) { @@ -1105,14 +1421,42 @@ namespace System.Globalization // Set it to read-only retval.m_isReadOnly = true; - // Remember our name (as constructed). Do NOT use alternate sort name versions because - // we have internal state representing the sort. (So someone would get the wrong cached version) - string newName = CultureData.AnsiToLower(retval.m_name); + if (lcid == -1) + { + lock (m_lock) + { + // This new culture will be added only to the name hash table. + tempNameHT[name + '\xfffd' + altName] = retval; + } + // when lcid == -1 then TextInfo object is already get created and we need to set it as read only. + retval.TextInfo.SetReadOnlyState(true); + } + else if (lcid == 0) + { + // Remember our name (as constructed). Do NOT use alternate sort name versions because + // we have internal state representing the sort. (So someone would get the wrong cached version) + string newName = CultureData.AnsiToLower(retval.m_name); + + // We add this new culture info object to both tables. + lock (m_lock) + { + tempNameHT[newName] = retval; + } + } + else + { + lock (m_lock) + { + tempLcidHT[lcid] = retval; + } + } - // We add this new culture info object to both tables. - lock (m_lock) + // Copy the two hashtables to the corresponding member variables. This will potentially overwrite + // new tables simultaneously created by a new thread, but maximizes thread safety. + if (-1 != lcid) { - tempNameHT[newName] = retval; + // Only when we modify the lcid hash table, is there a need to overwrite. + s_LcidCachedCultures = tempLcidHT; } s_NameCachedCultures = tempNameHT; @@ -1122,23 +1466,93 @@ namespace System.Globalization } // Gets a cached copy of the specified culture from an internal hashtable (or creates it + // if not found). (LCID version)... use named version + public static CultureInfo GetCultureInfo(int culture) + { + // Must check for -1 now since the helper function uses the value to signal + // the altCulture code path for SQL Server. + // Also check for zero as this would fail trying to add as a key to the hash. + if (culture <= 0) + { + throw new ArgumentOutOfRangeException(nameof(culture), SR.ArgumentOutOfRange_NeedPosNum); + } + Contract.Ensures(Contract.Result() != null); + Contract.EndContractBlock(); + CultureInfo retval = GetCultureInfoHelper(culture, null, null); + if (null == retval) + { + throw new CultureNotFoundException(nameof(culture), culture, SR.Argument_CultureNotSupported); + } + return retval; + } + + // Gets a cached copy of the specified culture from an internal hashtable (or creates it // if not found). (Named version) - internal static CultureInfo GetCultureInfo(string name) + public static CultureInfo GetCultureInfo(string name) { // Make sure we have a valid, non-zero length string as name if (name == null) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } - CultureInfo retval = GetCultureInfoHelper(name); + CultureInfo retval = GetCultureInfoHelper(0, name, null); if (retval == null) { throw new CultureNotFoundException( - "name", name, SR.Argument_CultureNotSupported); + nameof(name), name, SR.Argument_CultureNotSupported); + } + return retval; + } + + // Gets a cached copy of the specified culture from an internal hashtable (or creates it + // if not found). + public static CultureInfo GetCultureInfo(string name, string altName) + { + // Make sure we have a valid, non-zero length string as name + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + + if (altName == null) + { + throw new ArgumentNullException(nameof(altName)); + } + + Contract.Ensures(Contract.Result() != null); + Contract.EndContractBlock(); + + CultureInfo retval = GetCultureInfoHelper(-1, name, altName); + if (retval == null) + { + throw new CultureNotFoundException("name or altName", + SR.Format(SR.Argument_OneOfCulturesNotSupported, name, altName)); } return retval; } + + // This function is deprecated, we don't like it + public static CultureInfo GetCultureInfoByIetfLanguageTag(string name) + { + Contract.Ensures(Contract.Result() != null); + + // Disallow old zh-CHT/zh-CHS names + if (name == "zh-CHT" || name == "zh-CHS") + { + throw new CultureNotFoundException(nameof(name), SR.Format(SR.Argument_CultureIetfNotSupported, name)); + } + + CultureInfo ci = GetCultureInfo(name); + + // Disallow alt sorts and es-es_TS + if (ci.LCID > 0xffff || ci.LCID == 0x040a) + { + throw new CultureNotFoundException(nameof(name), SR.Format(SR.Argument_CultureIetfNotSupported, name)); + } + + return ci; + } } } diff --git a/src/mscorlib/corefx/System/Globalization/CultureNotFoundException.cs b/src/mscorlib/corefx/System/Globalization/CultureNotFoundException.cs index 740063e..64782d2 100644 --- a/src/mscorlib/corefx/System/Globalization/CultureNotFoundException.cs +++ b/src/mscorlib/corefx/System/Globalization/CultureNotFoundException.cs @@ -13,6 +13,7 @@ namespace System.Globalization public partial class CultureNotFoundException : ArgumentException, ISerializable { private string _invalidCultureName; // unrecognized culture name + private int? _invalidCultureId; // unrecognized culture Lcid public CultureNotFoundException() : base(DefaultMessage) @@ -46,8 +47,22 @@ namespace System.Globalization _invalidCultureName = invalidCultureName; } - protected CultureNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) + public CultureNotFoundException(string message, int invalidCultureId, Exception innerException) + : base(message, innerException) + { + _invalidCultureId = invalidCultureId; + } + + public CultureNotFoundException(string paramName, int invalidCultureId, string message) + : base(message, paramName) + { + _invalidCultureId = invalidCultureId; + } + + protected CultureNotFoundException(SerializationInfo info, StreamingContext context) + : base(info, context) { + _invalidCultureId = (int?)info.GetValue("InvalidCultureId", typeof(int?)); _invalidCultureName = (string)info.GetValue("InvalidCultureName", typeof(string)); } @@ -56,13 +71,19 @@ namespace System.Globalization { if (info == null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } base.GetObjectData(info, context); + info.AddValue("InvalidCultureId", _invalidCultureId, typeof(int?)); info.AddValue("InvalidCultureName", _invalidCultureName, typeof(string)); } + public virtual Nullable InvalidCultureId + { + get { return _invalidCultureId; } + } + public virtual string InvalidCultureName { get { return _invalidCultureName; } @@ -80,7 +101,9 @@ namespace System.Globalization { get { - return InvalidCultureName; + return InvalidCultureId != null ? + String.Format(CultureInfo.InvariantCulture, "{0} (0x{0:x4})", (int)InvalidCultureId) : + InvalidCultureName; } } @@ -89,12 +112,14 @@ namespace System.Globalization get { String s = base.Message; - if ( - _invalidCultureName != null) + if (_invalidCultureId != null || _invalidCultureName != null) { String valueMessage = SR.Format(SR.Argument_CultureInvalidIdentifier, FormatedInvalidCultureId); if (s == null) + { return valueMessage; + } + return s + Environment.NewLine + valueMessage; } return s; diff --git a/src/mscorlib/corefx/System/Globalization/CultureTypes.cs b/src/mscorlib/corefx/System/Globalization/CultureTypes.cs new file mode 100644 index 0000000..80b588a --- /dev/null +++ b/src/mscorlib/corefx/System/Globalization/CultureTypes.cs @@ -0,0 +1,28 @@ +// 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. + +// The enumeration constants used in CultureInfo.GetCultures(). +// On Linux platforms, the only enum values used there is NeutralCultures and SpecificCultures +// the rest are obsolete or not valid on Linux + +namespace System.Globalization +{ + [Serializable] + [Flags] + public enum CultureTypes + { + NeutralCultures = 0x0001, // Neutral cultures are cultures like "en", "de", "zh", etc, for enumeration this includes ALL neutrals regardless of other flags + SpecificCultures = 0x0002, // Non-netural cultuers. Examples are "en-us", "zh-tw", etc., for enumeration this includes ALL specifics regardless of other flags + InstalledWin32Cultures = 0x0004, // Win32 installed cultures in the system and exists in the framework too., this is effectively all cultures + + AllCultures = NeutralCultures | SpecificCultures | InstalledWin32Cultures, + + UserCustomCulture = 0x0008, // User defined custom culture + ReplacementCultures = 0x0010, // User defined replacement custom culture. + [Obsolete("This value has been deprecated. Please use other values in CultureTypes.")] + WindowsOnlyCultures = 0x0020, // this will always return empty list. + [Obsolete("This value has been deprecated. Please use other values in CultureTypes.")] + FrameworkCultures = 0x0040, // will return only the v2 cultures marked as Framework culture. + } +} diff --git a/src/mscorlib/corefx/System/Globalization/DateTimeFormatInfo.cs b/src/mscorlib/corefx/System/Globalization/DateTimeFormatInfo.cs index da746ad..216fc60 100644 --- a/src/mscorlib/corefx/System/Globalization/DateTimeFormatInfo.cs +++ b/src/mscorlib/corefx/System/Globalization/DateTimeFormatInfo.cs @@ -2,15 +2,10 @@ // 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; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; -using System.Runtime.InteropServices; using System.Runtime.Serialization; -using System.Security; -using System.Text; -using System.Threading; namespace System.Globalization { @@ -55,8 +50,7 @@ namespace System.Globalization [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] - public sealed partial class DateTimeFormatInfo : IFormatProvider, ICloneable + public sealed class DateTimeFormatInfo : IFormatProvider, ICloneable { // cache for the invariant culture. // invariantInfo is constant irrespective of your current culture. @@ -228,7 +222,7 @@ namespace System.Globalization { // Get the abbreviated day names for our current calendar this.abbreviatedDayNames = _cultureData.AbbreviatedDayNames(Calendar.ID); - Contract.Assert(this.abbreviatedDayNames.Length == 7, "[DateTimeFormatInfo.GetAbbreviatedDayOfWeekNames] Expected 7 day names in a week"); + Debug.Assert(this.abbreviatedDayNames.Length == 7, "[DateTimeFormatInfo.GetAbbreviatedDayOfWeekNames] Expected 7 day names in a week"); } return (this.abbreviatedDayNames); } @@ -252,7 +246,7 @@ namespace System.Globalization { // Get the super short day names for our current calendar this.m_superShortDayNames = _cultureData.SuperShortDayNames(Calendar.ID); - Contract.Assert(this.m_superShortDayNames.Length == 7, "[DateTimeFormatInfo.internalGetSuperShortDayNames] Expected 7 day names in a week"); + Debug.Assert(this.m_superShortDayNames.Length == 7, "[DateTimeFormatInfo.internalGetSuperShortDayNames] Expected 7 day names in a week"); } return (this.m_superShortDayNames); } @@ -269,7 +263,7 @@ namespace System.Globalization { // Get the day names for our current calendar this.dayNames = _cultureData.DayNames(Calendar.ID); - Contract.Assert(this.dayNames.Length == 7, "[DateTimeFormatInfo.GetDayOfWeekNames] Expected 7 day names in a week"); + Debug.Assert(this.dayNames.Length == 7, "[DateTimeFormatInfo.GetDayOfWeekNames] Expected 7 day names in a week"); } return (this.dayNames); } @@ -286,7 +280,7 @@ namespace System.Globalization { // Get the month names for our current calendar this.abbreviatedMonthNames = _cultureData.AbbreviatedMonthNames(Calendar.ID); - Contract.Assert(this.abbreviatedMonthNames.Length == 12 || this.abbreviatedMonthNames.Length == 13, + Debug.Assert(this.abbreviatedMonthNames.Length == 12 || this.abbreviatedMonthNames.Length == 13, "[DateTimeFormatInfo.GetAbbreviatedMonthNames] Expected 12 or 13 month names in a year"); } return (this.abbreviatedMonthNames); @@ -305,7 +299,7 @@ namespace System.Globalization { // Get the month names for our current calendar this.monthNames = _cultureData.MonthNames(Calendar.ID); - Contract.Assert(this.monthNames.Length == 12 || this.monthNames.Length == 13, + Debug.Assert(this.monthNames.Length == 12 || this.monthNames.Length == 13, "[DateTimeFormatInfo.GetMonthNames] Expected 12 or 13 month names in a year"); } @@ -324,8 +318,8 @@ namespace System.Globalization internal DateTimeFormatInfo(CultureData cultureData, Calendar cal) { - Contract.Requires(cultureData != null); - Contract.Requires(cal != null); + Debug.Assert(cultureData != null); + Debug.Assert(cal != null); // Remember our culture _cultureData = cultureData; @@ -335,8 +329,8 @@ namespace System.Globalization private void InitializeOverridableProperties(CultureData cultureData, CalendarId calendarId) { - Contract.Requires(cultureData != null); - Contract.Assert(calendarId != CalendarId.UNINITIALIZED_VALUE, "[DateTimeFormatInfo.Populate] Expected initalized calendarId"); + Debug.Assert(cultureData != null); + Debug.Assert(calendarId != CalendarId.UNINITIALIZED_VALUE, "[DateTimeFormatInfo.Populate] Expected initalized calendarId"); if (this.firstDayOfWeek == -1) { this.firstDayOfWeek = cultureData.IFIRSTDAYOFWEEK; } if (this.calendarWeekRule == -1) { this.calendarWeekRule = cultureData.IFIRSTWEEKOFYEAR; } @@ -347,19 +341,19 @@ namespace System.Globalization if (this.dateSeparator == null) { this.dateSeparator = cultureData.DateSeparator(calendarId); } this.allLongTimePatterns = _cultureData.LongTimes; - Contract.Assert(this.allLongTimePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some long time patterns"); + Debug.Assert(this.allLongTimePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some long time patterns"); this.allShortTimePatterns = _cultureData.ShortTimes; - Contract.Assert(this.allShortTimePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some short time patterns"); + Debug.Assert(this.allShortTimePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some short time patterns"); this.allLongDatePatterns = cultureData.LongDates(calendarId); - Contract.Assert(this.allLongDatePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some long date patterns"); + Debug.Assert(this.allLongDatePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some long date patterns"); this.allShortDatePatterns = cultureData.ShortDates(calendarId); - Contract.Assert(this.allShortDatePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some short date patterns"); + Debug.Assert(this.allShortDatePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some short date patterns"); this.allYearMonthPatterns = cultureData.YearMonths(calendarId); - Contract.Assert(this.allYearMonthPatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some year month patterns"); + Debug.Assert(this.allYearMonthPatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some year month patterns"); } [OptionalField(VersionAdded = 1)] @@ -527,7 +521,7 @@ namespace System.Globalization { this.amDesignator = _cultureData.SAM1159; } - Contract.Assert(this.amDesignator != null, "DateTimeFormatInfo.AMDesignator, amDesignator != null"); + Debug.Assert(this.amDesignator != null, "DateTimeFormatInfo.AMDesignator, amDesignator != null"); return (this.amDesignator); } @@ -537,7 +531,7 @@ namespace System.Globalization throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -553,7 +547,7 @@ namespace System.Globalization { Contract.Ensures(Contract.Result() != null); - Contract.Assert(this.calendar != null, "DateTimeFormatInfo.Calendar: calendar != null"); + Debug.Assert(this.calendar != null, "DateTimeFormatInfo.Calendar: calendar != null"); return (this.calendar); } @@ -563,7 +557,7 @@ namespace System.Globalization throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { - throw new ArgumentNullException("value", SR.ArgumentNull_Obj); + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_Obj); } Contract.EndContractBlock(); if (value == calendar) @@ -641,7 +635,7 @@ namespace System.Globalization } // The assigned calendar is not a valid calendar for this culture, throw - throw new ArgumentOutOfRangeException("value", SR.Argument_InvalidCalendar); + throw new ArgumentOutOfRangeException(nameof(value), SR.Argument_InvalidCalendar); } } @@ -670,7 +664,7 @@ namespace System.Globalization { if (eraName == null) { - throw new ArgumentNullException("eraName", + throw new ArgumentNullException(nameof(eraName), SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -759,7 +753,7 @@ namespace System.Globalization { return (m_eraNames[era]); } - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } internal String[] AbbreviatedEraNames @@ -791,7 +785,7 @@ namespace System.Globalization { return (m_abbrevEraNames[era]); } - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } internal String[] AbbreviatedEnglishEraNames @@ -800,34 +794,41 @@ namespace System.Globalization { if (this.m_abbrevEnglishEraNames == null) { - Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.AbbreviatedEnglishEraNames] Expected Calendar.ID > 0"); + Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.AbbreviatedEnglishEraNames] Expected Calendar.ID > 0"); this.m_abbrevEnglishEraNames = _cultureData.AbbreviatedEnglishEraNames(Calendar.ID); } return (this.m_abbrevEnglishEraNames); } } - // Note that cultureData derives this from the short date format (unless someone's set this previously) // Note that this property is quite undesirable. - internal String DateSeparator + public string DateSeparator { get { - if (this.dateSeparator == null) + if (dateSeparator == null) { - this.dateSeparator = _cultureData.DateSeparator(Calendar.ID); + dateSeparator = _cultureData.DateSeparator(Calendar.ID); } - Contract.Assert(this.dateSeparator != null, "DateTimeFormatInfo.DateSeparator, dateSeparator != null"); - return (this.dateSeparator); + Debug.Assert(this.dateSeparator != null, "DateTimeFormatInfo.DateSeparator, dateSeparator != null"); + return dateSeparator; } set { - throw null; + if (IsReadOnly) + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); + + if (value == null) + { + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_String); + } + Contract.EndContractBlock(); + ClearTokenHashTable(); + dateSeparator = value; } } - public DayOfWeek FirstDayOfWeek { get @@ -836,7 +837,7 @@ namespace System.Globalization { this.firstDayOfWeek = _cultureData.IFIRSTDAYOFWEEK; } - Contract.Assert(this.firstDayOfWeek != -1, "DateTimeFormatInfo.FirstDayOfWeek, firstDayOfWeek != -1"); + Debug.Assert(this.firstDayOfWeek != -1, "DateTimeFormatInfo.FirstDayOfWeek, firstDayOfWeek != -1"); return ((DayOfWeek)this.firstDayOfWeek); } @@ -852,7 +853,7 @@ namespace System.Globalization else { throw new ArgumentOutOfRangeException( - "value", SR.Format(SR.ArgumentOutOfRange_Range, + nameof(value), SR.Format(SR.ArgumentOutOfRange_Range, DayOfWeek.Sunday, DayOfWeek.Saturday)); } } @@ -866,7 +867,7 @@ namespace System.Globalization { this.calendarWeekRule = _cultureData.IFIRSTWEEKOFYEAR; } - Contract.Assert(this.calendarWeekRule != -1, "DateTimeFormatInfo.CalendarWeekRule, calendarWeekRule != -1"); + Debug.Assert(this.calendarWeekRule != -1, "DateTimeFormatInfo.CalendarWeekRule, calendarWeekRule != -1"); return ((CalendarWeekRule)this.calendarWeekRule); } @@ -881,7 +882,7 @@ namespace System.Globalization else { throw new ArgumentOutOfRangeException( - "value", SR.Format(SR.ArgumentOutOfRange_Range, + nameof(value), SR.Format(SR.ArgumentOutOfRange_Range, CalendarWeekRule.FirstDay, CalendarWeekRule.FirstFourDayWeek)); } } @@ -904,7 +905,7 @@ namespace System.Globalization throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -938,7 +939,7 @@ namespace System.Globalization throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -979,7 +980,7 @@ namespace System.Globalization throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -1005,10 +1006,10 @@ namespace System.Globalization { if (this.monthDayPattern == null) { - Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.MonthDayPattern] Expected calID > 0"); + Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.MonthDayPattern] Expected calID > 0"); this.monthDayPattern = _cultureData.MonthDay(Calendar.ID); } - Contract.Assert(this.monthDayPattern != null, "DateTimeFormatInfo.MonthDayPattern, monthDayPattern != null"); + Debug.Assert(this.monthDayPattern != null, "DateTimeFormatInfo.MonthDayPattern, monthDayPattern != null"); return (this.monthDayPattern); } @@ -1018,7 +1019,7 @@ namespace System.Globalization throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -1037,7 +1038,7 @@ namespace System.Globalization { this.pmDesignator = _cultureData.SPM2359; } - Contract.Assert(this.pmDesignator != null, "DateTimeFormatInfo.PMDesignator, pmDesignator != null"); + Debug.Assert(this.pmDesignator != null, "DateTimeFormatInfo.PMDesignator, pmDesignator != null"); return (this.pmDesignator); } @@ -1047,7 +1048,7 @@ namespace System.Globalization throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -1090,7 +1091,7 @@ namespace System.Globalization if (IsReadOnly) throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_String); Contract.EndContractBlock(); @@ -1132,7 +1133,7 @@ namespace System.Globalization throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -1270,7 +1271,7 @@ namespace System.Globalization // Note that cultureData derives this from the long time format (unless someone's set this previously) // Note that this property is quite undesirable. - internal String TimeSeparator + public string TimeSeparator { get { @@ -1278,17 +1279,27 @@ namespace System.Globalization { timeSeparator = _cultureData.TimeSeparator; } - Contract.Assert(this.timeSeparator != null, "DateTimeFormatInfo.TimeSeparator, timeSeparator != null"); + Debug.Assert(this.timeSeparator != null, "DateTimeFormatInfo.TimeSeparator, timeSeparator != null"); return (timeSeparator); } set { - throw null; + if (IsReadOnly) + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); + + if (value == null) + { + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_String); + } + + Contract.EndContractBlock(); + ClearTokenHashTable(); + + timeSeparator = value; } } - public String UniversalSortableDateTimePattern { get @@ -1321,7 +1332,7 @@ namespace System.Globalization throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -1339,8 +1350,8 @@ namespace System.Globalization // private static void CheckNullValue(String[] values, int length) { - Contract.Requires(values != null, "value != null"); - Contract.Requires(values.Length >= length); + Debug.Assert(values != null, "value != null"); + Debug.Assert(values.Length >= length); for (int i = 0; i < length; i++) { if (values[i] == null) @@ -1365,12 +1376,12 @@ namespace System.Globalization throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_Array); } if (value.Length != 7) { - throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 7), "value"); + throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 7), nameof(value)); } Contract.EndContractBlock(); CheckNullValue(value, value.Length); @@ -1381,7 +1392,6 @@ namespace System.Globalization } // Returns the string array of the one-letter day of week names. - [System.Runtime.InteropServices.ComVisible(false)] public String[] ShortestDayNames { get @@ -1395,12 +1405,12 @@ namespace System.Globalization throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_Array); } if (value.Length != 7) { - throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 7), "value"); + throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 7), nameof(value)); } Contract.EndContractBlock(); CheckNullValue(value, value.Length); @@ -1422,12 +1432,12 @@ namespace System.Globalization throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_Array); } if (value.Length != 7) { - throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 7), "value"); + throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 7), nameof(value)); } Contract.EndContractBlock(); CheckNullValue(value, value.Length); @@ -1451,12 +1461,12 @@ namespace System.Globalization throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_Array); } if (value.Length != 13) { - throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 13), "value"); + throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 13), nameof(value)); } Contract.EndContractBlock(); CheckNullValue(value, value.Length - 1); @@ -1479,12 +1489,12 @@ namespace System.Globalization throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_Array); } if (value.Length != 13) { - throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 13), "value"); + throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 13), nameof(value)); } Contract.EndContractBlock(); CheckNullValue(value, value.Length - 1); @@ -1550,7 +1560,7 @@ namespace System.Globalization if ((month < 1) || (month > monthNamesArray.Length)) { throw new ArgumentOutOfRangeException( - "month", SR.Format(SR.ArgumentOutOfRange_Range, + nameof(month), SR.Format(SR.ArgumentOutOfRange_Range, 1, monthNamesArray.Length)); } return (monthNamesArray[month - 1]); @@ -1571,7 +1581,7 @@ namespace System.Globalization if (this.m_genitiveAbbreviatedMonthNames == null) { this.m_genitiveAbbreviatedMonthNames = _cultureData.AbbreviatedGenitiveMonthNames(this.Calendar.ID); - Contract.Assert(this.m_genitiveAbbreviatedMonthNames.Length == 13, + Debug.Assert(this.m_genitiveAbbreviatedMonthNames.Length == 13, "[DateTimeFormatInfo.GetGenitiveMonthNames] Expected 13 abbreviated genitive month names in a year"); } return (this.m_genitiveAbbreviatedMonthNames); @@ -1580,7 +1590,7 @@ namespace System.Globalization if (this.genitiveMonthNames == null) { this.genitiveMonthNames = _cultureData.GenitiveMonthNames(this.Calendar.ID); - Contract.Assert(this.genitiveMonthNames.Length == 13, + Debug.Assert(this.genitiveMonthNames.Length == 13, "[DateTimeFormatInfo.GetGenitiveMonthNames] Expected 13 genitive month names in a year"); } return (this.genitiveMonthNames); @@ -1597,9 +1607,9 @@ namespace System.Globalization { if (this.leapYearMonthNames == null) { - Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.internalGetLeapYearMonthNames] Expected Calendar.ID > 0"); + Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.internalGetLeapYearMonthNames] Expected Calendar.ID > 0"); this.leapYearMonthNames = _cultureData.LeapYearMonthNames(Calendar.ID); - Contract.Assert(this.leapYearMonthNames.Length == 13, + Debug.Assert(this.leapYearMonthNames.Length == 13, "[DateTimeFormatInfo.internalGetLeapYearMonthNames] Expepcted 13 leap year month names"); } return (leapYearMonthNames); @@ -1611,7 +1621,7 @@ namespace System.Globalization if ((int)dayofweek < 0 || (int)dayofweek > 6) { throw new ArgumentOutOfRangeException( - "dayofweek", SR.Format(SR.ArgumentOutOfRange_Range, + nameof(dayofweek), SR.Format(SR.ArgumentOutOfRange_Range, DayOfWeek.Sunday, DayOfWeek.Saturday)); } Contract.EndContractBlock(); @@ -1622,11 +1632,28 @@ namespace System.Globalization return (internalGetAbbreviatedDayOfWeekNames()[(int)dayofweek]); } + // Returns the super short day of week names for the specified day of week. + public string GetShortestDayName(DayOfWeek dayOfWeek) + { + if ((int)dayOfWeek < 0 || (int)dayOfWeek > 6) + { + throw new ArgumentOutOfRangeException( + nameof(dayOfWeek), SR.Format(SR.ArgumentOutOfRange_Range, + DayOfWeek.Sunday, DayOfWeek.Saturday)); + } + Contract.EndContractBlock(); + // + // Don't call the public property SuperShortDayNames here since a clone is needed in that + // property, so it will be slower. Instead, use internalGetSuperShortDayNames() directly. + // + return (internalGetSuperShortDayNames()[(int)dayOfWeek]); + } + // Get all possible combination of inputs private static String[] GetCombinedPatterns(String[] patterns1, String[] patterns2, String connectString) { - Contract.Requires(patterns1 != null); - Contract.Requires(patterns2 != null); + Debug.Assert(patterns1 != null); + Debug.Assert(patterns2 != null); // Get array size String[] result = new String[patterns1.Length * patterns2.Length]; @@ -1646,9 +1673,22 @@ namespace System.Globalization return (result); } + public string[] GetAllDateTimePatterns() + { + List results = new List(DEFAULT_ALL_DATETIMES_SIZE); + + for (int i = 0; i < DateTimeFormat.allStandardFormats.Length; i++) + { + String[] strings = GetAllDateTimePatterns(DateTimeFormat.allStandardFormats[i]); + for (int j = 0; j < strings.Length; j++) + { + results.Add(strings[j]); + } + } + return results.ToArray(); + } - // auto-generated - internal String[] GetAllDateTimePatterns(char format) + public string[] GetAllDateTimePatterns(char format) { Contract.Ensures(Contract.Result() != null); String[] result = null; @@ -1703,7 +1743,7 @@ namespace System.Globalization result = this.AllYearMonthPatterns; break; default: - throw new ArgumentException(SR.Format_BadFormatSpecifier, "format"); + throw new ArgumentException(SR.Format_BadFormatSpecifier, nameof(format)); } return (result); } @@ -1714,7 +1754,7 @@ namespace System.Globalization if ((int)dayofweek < 0 || (int)dayofweek > 6) { throw new ArgumentOutOfRangeException( - "dayofweek", SR.Format(SR.ArgumentOutOfRange_Range, + nameof(dayofweek), SR.Format(SR.ArgumentOutOfRange_Range, DayOfWeek.Sunday, DayOfWeek.Saturday)); } Contract.EndContractBlock(); @@ -1730,7 +1770,7 @@ namespace System.Globalization if (month < 1 || month > 13) { throw new ArgumentOutOfRangeException( - "month", SR.Format(SR.ArgumentOutOfRange_Range, + nameof(month), SR.Format(SR.ArgumentOutOfRange_Range, 1, 13)); } Contract.EndContractBlock(); @@ -1744,7 +1784,7 @@ namespace System.Globalization if (month < 1 || month > 13) { throw new ArgumentOutOfRangeException( - "month", SR.Format(SR.ArgumentOutOfRange_Range, + nameof(month), SR.Format(SR.ArgumentOutOfRange_Range, 1, 13)); } Contract.EndContractBlock(); @@ -1761,9 +1801,9 @@ namespace System.Globalization // The resulting [] can get returned to the calling app, so clone it. private static string[] GetMergedPatterns(string[] patterns, string defaultPattern) { - Contract.Assert(patterns != null && patterns.Length > 0, + Debug.Assert(patterns != null && patterns.Length > 0, "[DateTimeFormatInfo.GetMergedPatterns]Expected array of at least one pattern"); - Contract.Assert(defaultPattern != null, + Debug.Assert(defaultPattern != null, "[DateTimeFormatInfo.GetMergedPatterns]Expected non null default string"); // If the default happens to be the first in the list just return (a cloned) copy @@ -1864,9 +1904,9 @@ namespace System.Globalization { if (this.allYearMonthPatterns == null) { - Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedYearMonthPatterns] Expected Calendar.ID > 0"); + Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedYearMonthPatterns] Expected Calendar.ID > 0"); this.allYearMonthPatterns = _cultureData.YearMonths(this.Calendar.ID); - Contract.Assert(this.allYearMonthPatterns.Length > 0, + Debug.Assert(this.allYearMonthPatterns.Length > 0, "[DateTimeFormatInfo.UnclonedYearMonthPatterns] Expected some year month patterns"); } @@ -1883,9 +1923,9 @@ namespace System.Globalization { if (allShortDatePatterns == null) { - Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedShortDatePatterns] Expected Calendar.ID > 0"); + Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedShortDatePatterns] Expected Calendar.ID > 0"); this.allShortDatePatterns = _cultureData.ShortDates(this.Calendar.ID); - Contract.Assert(this.allShortDatePatterns.Length > 0, + Debug.Assert(this.allShortDatePatterns.Length > 0, "[DateTimeFormatInfo.UnclonedShortDatePatterns] Expected some short date patterns"); } @@ -1901,9 +1941,9 @@ namespace System.Globalization { if (allLongDatePatterns == null) { - Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedLongDatePatterns] Expected Calendar.ID > 0"); + Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedLongDatePatterns] Expected Calendar.ID > 0"); this.allLongDatePatterns = _cultureData.LongDates(this.Calendar.ID); - Contract.Assert(this.allLongDatePatterns.Length > 0, + Debug.Assert(this.allLongDatePatterns.Length > 0, "[DateTimeFormatInfo.UnclonedLongDatePatterns] Expected some long date patterns"); } @@ -1920,7 +1960,7 @@ namespace System.Globalization if (this.allShortTimePatterns == null) { this.allShortTimePatterns = _cultureData.ShortTimes; - Contract.Assert(this.allShortTimePatterns.Length > 0, + Debug.Assert(this.allShortTimePatterns.Length > 0, "[DateTimeFormatInfo.UnclonedShortTimePatterns] Expected some short time patterns"); } @@ -1937,7 +1977,7 @@ namespace System.Globalization if (this.allLongTimePatterns == null) { this.allLongTimePatterns = _cultureData.LongTimes; - Contract.Assert(this.allLongTimePatterns.Length > 0, + Debug.Assert(this.allLongTimePatterns.Length > 0, "[DateTimeFormatInfo.UnclonedLongTimePatterns] Expected some long time patterns"); } @@ -1949,7 +1989,7 @@ namespace System.Globalization { if (dtfi == null) { - throw new ArgumentNullException("dtfi", + throw new ArgumentNullException(nameof(dtfi), SR.ArgumentNull_Obj); } Contract.EndContractBlock(); @@ -1973,7 +2013,99 @@ namespace System.Globalization } } - [System.Runtime.InteropServices.ComVisible(false)] + // Return the native name for the calendar in DTFI.Calendar. The native name is referred to + // the culture used to create the DTFI. E.g. in the following example, the native language is Japanese. + // DateTimeFormatInfo dtfi = new CultureInfo("ja-JP", false).DateTimeFormat.Calendar = new JapaneseCalendar(); + // String nativeName = dtfi.NativeCalendarName; // Get the Japanese name for the Japanese calendar. + // DateTimeFormatInfo dtfi = new CultureInfo("ja-JP", false).DateTimeFormat.Calendar = new GregorianCalendar(GregorianCalendarTypes.Localized); + // String nativeName = dtfi.NativeCalendarName; // Get the Japanese name for the Gregorian calendar. + public string NativeCalendarName + { + get + { + return _cultureData.CalendarName(Calendar.ID); + } + } + + // + // Used by custom cultures and others to set the list of available formats. Note that none of them are + // explicitly used unless someone calls GetAllDateTimePatterns and subsequently uses one of the items + // from the list. + // + // Most of the format characters that can be used in GetAllDateTimePatterns are + // not really needed since they are one of the following: + // + // r/R/s/u locale-independent constants -- cannot be changed! + // m/M/y/Y fields with a single string in them -- that can be set through props directly + // f/F/g/G/U derived fields based on combinations of various of the below formats + // + // NOTE: No special validation is done here beyond what is done when the actual respective fields + // are used (what would be the point of disallowing here what we allow in the appropriate property?) + // + // WARNING: If more validation is ever done in one place, it should be done in the other. + // + public void SetAllDateTimePatterns(String[] patterns, char format) + { + if (IsReadOnly) + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); + + if (patterns == null) + { + throw new ArgumentNullException(nameof(patterns), SR.ArgumentNull_Array); + } + + if (patterns.Length == 0) + { + throw new ArgumentException(SR.Arg_ArrayZeroError, nameof(patterns)); + } + + Contract.EndContractBlock(); + + for (int i=0; i= TOKEN_HASH_SIZE) hashcode -= TOKEN_HASH_SIZE; } while (i < TOKEN_HASH_SIZE); - Contract.Assert(false, "The hashtable is full. This should not happen."); + Debug.Assert(false, "The hashtable is full. This should not happen."); } private bool CompareStringIgnoreCaseOptimized(string string1, int offset1, int length1, string string2, int offset2, int length2) diff --git a/src/mscorlib/corefx/System/Globalization/DayLightTime.cs b/src/mscorlib/corefx/System/Globalization/DayLightTime.cs index 2345fb5..6ec9d6a 100644 --- a/src/mscorlib/corefx/System/Globalization/DayLightTime.cs +++ b/src/mscorlib/corefx/System/Globalization/DayLightTime.cs @@ -9,11 +9,11 @@ namespace System.Globalization // This class represents a starting/ending time for a period of daylight saving time. [Serializable] - public partial class DaylightTime + public class DaylightTime { - internal DateTime m_start; - internal DateTime m_end; - internal TimeSpan m_delta; + private readonly DateTime _start; + private readonly DateTime _end; + private readonly TimeSpan _delta; private DaylightTime() { @@ -21,36 +21,33 @@ namespace System.Globalization public DaylightTime(DateTime start, DateTime end, TimeSpan delta) { - m_start = start; - m_end = end; - m_delta = delta; + _start = start; + _end = end; + _delta = delta; } // The start date of a daylight saving period. - public DateTime Start - { - get - { - return m_start; - } - } + public DateTime Start => _start; // The end date of a daylight saving period. - public DateTime End - { - get - { - return m_end; - } - } + public DateTime End => _end; // Delta to stardard offset in ticks. - public TimeSpan Delta + public TimeSpan Delta => _delta; + } + + // Value type version of DaylightTime + internal struct DaylightTimeStruct + { + public DaylightTimeStruct(DateTime start, DateTime end, TimeSpan delta) { - get - { - return m_delta; - } + Start = start; + End = end; + Delta = delta; } + + public readonly DateTime Start; + public readonly DateTime End; + public readonly TimeSpan Delta; } } diff --git a/src/mscorlib/corefx/System/Globalization/DigitShapes.cs b/src/mscorlib/corefx/System/Globalization/DigitShapes.cs new file mode 100644 index 0000000..7e40033 --- /dev/null +++ b/src/mscorlib/corefx/System/Globalization/DigitShapes.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. +// See the LICENSE file in the project root for more information. + +// +// The enumeration constants used in NumberFormatInfo.DigitSubstitution. +// +namespace System.Globalization +{ + [Serializable] + public enum DigitShapes : int + { + Context = 0x0000, // The shape depends on the previous text in the same output. + None = 0x0001, // Gives full Unicode compatibility. + NativeNational = 0x0002 // National shapes + } +} \ No newline at end of file diff --git a/src/mscorlib/corefx/System/Globalization/EastAsianLunisolarCalendar.cs b/src/mscorlib/corefx/System/Globalization/EastAsianLunisolarCalendar.cs index 8f2bbbc..84a44a9 100644 --- a/src/mscorlib/corefx/System/Globalization/EastAsianLunisolarCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/EastAsianLunisolarCalendar.cs @@ -38,14 +38,13 @@ namespace System.Globalization internal const int DatePartMonth = 2; internal const int DatePartDay = 3; - // Return the type of the East Asian Lunisolar calendars. - // - - //public override CalendarAlgorithmType AlgorithmType { - // get { - // return CalendarAlgorithmType.LunisolarCalendar; - // } - //} + public override CalendarAlgorithmType AlgorithmType + { + get + { + return CalendarAlgorithmType.LunisolarCalendar; + } + } // Return the year number in the 60-year cycle. // @@ -69,7 +68,7 @@ namespace System.Globalization if ((sexagenaryYear < 1) || (sexagenaryYear > 60)) { throw new ArgumentOutOfRangeException( - "sexagenaryYear", + nameof(sexagenaryYear), SR.Format(SR.ArgumentOutOfRange_Range, 1, 60)); } Contract.EndContractBlock(); @@ -86,7 +85,7 @@ namespace System.Globalization if ((sexagenaryYear < 1) || (sexagenaryYear > 60)) { throw new ArgumentOutOfRangeException( - "sexagenaryYear", + nameof(sexagenaryYear), SR.Format(SR.ArgumentOutOfRange_Range, 1, 60)); } Contract.EndContractBlock(); @@ -133,7 +132,7 @@ namespace System.Globalization return (mEraInfo[i].minEraYear); } } - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } internal int MaxEraCalendarYear(int era) @@ -162,7 +161,7 @@ namespace System.Globalization return (mEraInfo[i].maxEraYear); } } - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } internal EastAsianLunisolarCalendar() @@ -190,7 +189,7 @@ namespace System.Globalization if ((era < GetEra(MinDate)) || (era > GetEra(MaxDate))) { - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } } @@ -202,7 +201,7 @@ namespace System.Globalization if ((year < MinCalendarYear) || (year > MaxCalendarYear)) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), SR.Format(SR.ArgumentOutOfRange_Range, MinEraCalendarYear(era), MaxEraCalendarYear(era))); } return year; @@ -216,12 +215,12 @@ namespace System.Globalization { //Reject if there is no leap month this year if (GetYearInfo(year, LeapMonth) == 0) - throw new ArgumentOutOfRangeException("month", SR.ArgumentOutOfRange_Month); + throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); } if (month < 1 || month > 13) { - throw new ArgumentOutOfRangeException("month", SR.ArgumentOutOfRange_Month); + throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); } return year; } @@ -266,7 +265,7 @@ namespace System.Globalization if (day < 1 || day > daysInMonth) { throw new ArgumentOutOfRangeException( - "day", + nameof(day), SR.Format(SR.ArgumentOutOfRange_Day, daysInMonth, month)); } @@ -447,7 +446,7 @@ namespace System.Globalization if (months < -120000 || months > 120000) { throw new ArgumentOutOfRangeException( - "months", + nameof(months), SR.Format(SR.ArgumentOutOfRange_Range, -120000, 120000)); } Contract.EndContractBlock(); @@ -627,7 +626,7 @@ namespace System.Globalization if (day < 1 || day > daysInMonth) { throw new ArgumentOutOfRangeException( - "day", + nameof(day), SR.Format(SR.ArgumentOutOfRange_Day, daysInMonth, month)); } int m = GetYearInfo(year, LeapMonth); @@ -694,7 +693,7 @@ namespace System.Globalization if (value < 99 || value > MaxCalendarYear) { throw new ArgumentOutOfRangeException( - "value", + nameof(value), SR.Format(SR.ArgumentOutOfRange_Range, 99, MaxCalendarYear)); } twoDigitYearMax = value; @@ -706,7 +705,7 @@ namespace System.Globalization { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); diff --git a/src/mscorlib/corefx/System/Globalization/GregorianCalendar.cs b/src/mscorlib/corefx/System/Globalization/GregorianCalendar.cs index d0933a0..c2ed2e0 100644 --- a/src/mscorlib/corefx/System/Globalization/GregorianCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/GregorianCalendar.cs @@ -84,6 +84,15 @@ namespace System.Globalization } } + [System.Runtime.InteropServices.ComVisible(false)] + public override CalendarAlgorithmType AlgorithmType + { + get + { + return CalendarAlgorithmType.SolarCalendar; + } + } + /*=================================GetDefaultInstance========================== **Action: Internal method to provide a default intance of GregorianCalendar. Used by NLS+ implementation ** and other calendars. @@ -114,7 +123,7 @@ namespace System.Globalization if ((int)type < (int)GregorianCalendarTypes.Localized || (int)type > (int)GregorianCalendarTypes.TransliteratedFrench) { throw new ArgumentOutOfRangeException( - "type", + nameof(type), SR.Format(SR.ArgumentOutOfRange_Range, GregorianCalendarTypes.Localized, GregorianCalendarTypes.TransliteratedFrench)); } @@ -205,7 +214,7 @@ namespace System.Globalization int[] days = leapYear ? DaysToMonth366 : DaysToMonth365; // All months have less than 32 days, so n >> 5 is a good conservative // estimate for the month - int m = n >> 5 + 1; + int m = (n >> 5) + 1; // m = 1-based month number while (n >= days[m]) m++; // If month was requested, return it @@ -277,7 +286,7 @@ namespace System.Globalization if (months < -120000 || months > 120000) { throw new ArgumentOutOfRangeException( - "months", + nameof(months), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -366,17 +375,17 @@ namespace System.Globalization { if (year < 1 || year > MaxYear) { - throw new ArgumentOutOfRangeException("year", SR.Format(SR.ArgumentOutOfRange_Range, + throw new ArgumentOutOfRangeException(nameof(year), SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxYear)); } if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException("month", SR.ArgumentOutOfRange_Month); + throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); } int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365); return (days[month] - days[month - 1]); } - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } // Returns the number of days in the year given by the year argument for the current era. @@ -391,14 +400,14 @@ namespace System.Globalization return ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? 366 : 365); } throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, 1, MaxYear)); } - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } // Returns the era for the specified DateTime value. @@ -438,14 +447,14 @@ namespace System.Globalization return (12); } throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, 1, MaxYear)); } - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } // Returns the year part of the specified DateTime. The returned value is an @@ -465,25 +474,25 @@ namespace System.Globalization { if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException("month", SR.Format(SR.ArgumentOutOfRange_Range, + throw new ArgumentOutOfRangeException(nameof(month), SR.Format(SR.ArgumentOutOfRange_Range, 1, 12)); } Contract.EndContractBlock(); if (era != CurrentEra && era != ADEra) { - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } if (year < 1 || year > MaxYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxYear)); } if (day < 1 || day > GetDaysInMonth(year, month)) { - throw new ArgumentOutOfRangeException("day", SR.Format(SR.ArgumentOutOfRange_Range, + throw new ArgumentOutOfRangeException(nameof(day), SR.Format(SR.ArgumentOutOfRange_Range, 1, GetDaysInMonth(year, month))); } if (!IsLeapYear(year)) @@ -506,12 +515,12 @@ namespace System.Globalization { if (era != CurrentEra && era != ADEra) { - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } if (year < 1 || year > MaxYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, 1, MaxYear)); @@ -528,13 +537,13 @@ namespace System.Globalization { if (era != CurrentEra && era != ADEra) { - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } if (year < 1 || year > MaxYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, 1, MaxYear)); @@ -542,7 +551,7 @@ namespace System.Globalization if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException("month", SR.Format(SR.ArgumentOutOfRange_Range, + throw new ArgumentOutOfRangeException(nameof(month), SR.Format(SR.ArgumentOutOfRange_Range, 1, 12)); } Contract.EndContractBlock(); @@ -563,12 +572,12 @@ namespace System.Globalization } throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, 1, MaxYear)); } - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid. @@ -580,7 +589,7 @@ namespace System.Globalization { return new DateTime(year, month, day, hour, minute, second, millisecond); } - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } internal override Boolean TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result) @@ -643,7 +652,7 @@ namespace System.Globalization { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); @@ -651,7 +660,7 @@ namespace System.Globalization if (year > MaxYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, 1, MaxYear)); diff --git a/src/mscorlib/corefx/System/Globalization/GregorianCalendarHelper.cs b/src/mscorlib/corefx/System/Globalization/GregorianCalendarHelper.cs index f595e72..ee8ba13 100644 --- a/src/mscorlib/corefx/System/Globalization/GregorianCalendarHelper.cs +++ b/src/mscorlib/corefx/System/Globalization/GregorianCalendarHelper.cs @@ -148,7 +148,7 @@ namespace System.Globalization { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); @@ -165,7 +165,7 @@ namespace System.Globalization if (year < m_EraInfo[i].minEraYear || year > m_EraInfo[i].maxEraYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -175,7 +175,7 @@ namespace System.Globalization return (m_EraInfo[i].yearOffset + year); } } - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } internal bool IsValidYear(int year, int era) @@ -248,7 +248,7 @@ namespace System.Globalization int[] days = leapYear ? DaysToMonth366 : DaysToMonth365; // All months have less than 32 days, so n >> 5 is a good conservative // estimate for the month - int m = n >> 5 + 1; + int m = (n >> 5) + 1; // m = 1-based month number while (n >= days[m]) m++; // If month was requested, return it @@ -308,7 +308,7 @@ namespace System.Globalization if (millisecond < 0 || millisecond >= MillisPerSecond) { throw new ArgumentOutOfRangeException( - "millisecond", + nameof(millisecond), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -358,7 +358,7 @@ namespace System.Globalization if (months < -120000 || months > 120000) { throw new ArgumentOutOfRangeException( - "months", + nameof(months), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -446,7 +446,7 @@ namespace System.Globalization year = GetGregorianYear(year, era); if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException("month", SR.ArgumentOutOfRange_Month); + throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); } int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365); return (days[month] - days[month - 1]); @@ -476,7 +476,7 @@ namespace System.Globalization return (m_EraInfo[i].era); } } - throw new ArgumentOutOfRangeException("time", SR.ArgumentOutOfRange_Era); + throw new ArgumentOutOfRangeException(nameof(time), SR.ArgumentOutOfRange_Era); } @@ -558,7 +558,7 @@ namespace System.Globalization if (day < 1 || day > GetDaysInMonth(year, month, era)) { throw new ArgumentOutOfRangeException( - "day", + nameof(day), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -598,7 +598,7 @@ namespace System.Globalization if (month < 1 || month > 12) { throw new ArgumentOutOfRangeException( - "month", + nameof(month), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -640,7 +640,7 @@ namespace System.Globalization { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_NeedPosNum); } Contract.EndContractBlock(); @@ -654,7 +654,7 @@ namespace System.Globalization if (year < m_minYear || year > m_maxYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, m_minYear, m_maxYear)); diff --git a/src/mscorlib/corefx/System/Globalization/HebrewCalendar.cs b/src/mscorlib/corefx/System/Globalization/HebrewCalendar.cs index 5fbf2e0..7e63708 100644 --- a/src/mscorlib/corefx/System/Globalization/HebrewCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/HebrewCalendar.cs @@ -2,8 +2,7 @@ // 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.Text; +using System.Diagnostics; using System.Diagnostics.Contracts; namespace System.Globalization @@ -65,7 +64,7 @@ namespace System.Globalization [Serializable] [System.Runtime.InteropServices.ComVisible(true)] - public partial class HebrewCalendar : Calendar + public class HebrewCalendar : Calendar { public static readonly int HebrewEra = 1; @@ -317,6 +316,14 @@ namespace System.Globalization } } + public override CalendarAlgorithmType AlgorithmType + { + get + { + return CalendarAlgorithmType.LunisolarCalendar; + } + } + public HebrewCalendar() { } @@ -371,7 +378,7 @@ namespace System.Globalization if (month < 1 || month > monthsInYear) { throw new ArgumentOutOfRangeException( - "month", + nameof(month), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -397,7 +404,7 @@ namespace System.Globalization if (day < 1 || day > daysInMonth) { throw new ArgumentOutOfRangeException( - "day", + nameof(day), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -410,7 +417,7 @@ namespace System.Globalization { if (era != CurrentEra && era != HebrewEra) { - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } } @@ -470,7 +477,7 @@ namespace System.Globalization int index = gregorianYear - FirstGregorianTableYear; if (index < 0 || index > TABLESIZE) { - throw new ArgumentOutOfRangeException("gregorianYear"); + throw new ArgumentOutOfRangeException(nameof(gregorianYear)); } index *= 2; @@ -595,7 +602,7 @@ namespace System.Globalization // is true. // NumDays -= (long)(s_lunarMonthLen[hebrewYearType * MaxMonthPlusOne + lunarDate.month] - lunarDate.day); - Contract.Assert(NumDays >= 1, "NumDays >= 1"); + Debug.Assert(NumDays >= 1, "NumDays >= 1"); // If NumDays is 1, then we are done. Otherwise, find the correct Hebrew month // and day. @@ -705,7 +712,7 @@ namespace System.Globalization catch (ArgumentException) { throw new ArgumentOutOfRangeException( - "months", + nameof(months), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_AddValue)); @@ -728,7 +735,7 @@ namespace System.Globalization int d = GetDatePart(time.Ticks, DatePartDay); y += years; - CheckHebrewYearValue(y, Calendar.CurrentEra, "years"); + CheckHebrewYearValue(y, Calendar.CurrentEra, nameof(years)); int months = GetMonthsInYear(y, CurrentEra); if (m > months) @@ -771,7 +778,7 @@ namespace System.Globalization internal static int GetHebrewYearType(int year, int era) { - CheckHebrewYearValue(year, era, "year"); + CheckHebrewYearValue(year, era, nameof(year)); // The HebrewTable is indexed by Gregorian year and starts from FirstGregorianYear. // So we need to convert year (Hebrew year value) to Gregorian Year below. return (s_hebrewTable[(year - HebrewYearOf1AD - FirstGregorianTableYear) * 2 + 1]); @@ -819,12 +826,12 @@ namespace System.Globalization int hebrewYearType = GetHebrewYearType(year, era); CheckHebrewMonthValue(year, month, era); - Contract.Assert(hebrewYearType >= 1 && hebrewYearType <= 6, + Debug.Assert(hebrewYearType >= 1 && hebrewYearType <= 6, "hebrewYearType should be from 1 to 6, but now hebrewYearType = " + hebrewYearType + " for hebrew year " + year); int monthDays = s_lunarMonthLen[hebrewYearType * MaxMonthPlusOne + month]; if (monthDays == 0) { - throw new ArgumentOutOfRangeException("month", SR.ArgumentOutOfRange_Month); + throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); } return (monthDays); } @@ -956,7 +963,7 @@ namespace System.Globalization public override bool IsLeapYear(int year, int era) { - CheckHebrewYearValue(year, era, "year"); + CheckHebrewYearValue(year, era, nameof(year)); return (((7 * (long)year + 1) % 19) < 7); } @@ -1047,7 +1054,7 @@ namespace System.Globalization public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) { - CheckHebrewYearValue(year, era, "year"); + CheckHebrewYearValue(year, era, nameof(year)); CheckHebrewMonthValue(year, month, era); CheckHebrewDayValue(year, month, day, era); DateTime dt = HebrewToGregorian(year, month, day, hour, minute, second, millisecond); @@ -1078,7 +1085,7 @@ namespace System.Globalization } else { - CheckHebrewYearValue(value, HebrewEra, "value"); + CheckHebrewYearValue(value, HebrewEra, nameof(value)); } twoDigitYearMax = value; } @@ -1089,7 +1096,7 @@ namespace System.Globalization { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); @@ -1102,7 +1109,7 @@ namespace System.Globalization if (year > MaxHebrewYear || year < MinHebrewYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, diff --git a/src/mscorlib/corefx/System/Globalization/HebrewNumber.cs b/src/mscorlib/corefx/System/Globalization/HebrewNumber.cs index 8fc264b..01e251d 100644 --- a/src/mscorlib/corefx/System/Globalization/HebrewNumber.cs +++ b/src/mscorlib/corefx/System/Globalization/HebrewNumber.cs @@ -2,18 +2,11 @@ // 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.Text; using System.Diagnostics; -using System.Diagnostics.Contracts; namespace System.Globalization { - -#if INSIDE_CLR - using Debug = BCLDebug; -#endif - //////////////////////////////////////////////////////////////////////////// // // Used in HebrewNumber.ParseByChar to maintain the context information ( @@ -110,7 +103,7 @@ namespace System.Globalization Number -= 5000; } - Contract.Assert(Number > 0 && Number <= 999, "Number is out of range."); ; + Debug.Assert(Number > 0 && Number <= 999, "Number is out of range."); ; // // Get the Hundreds. @@ -335,7 +328,7 @@ namespace System.Globalization // // The state machine for Hebrew number pasing. // - private readonly static HS[] s_numberPasingState = + private static readonly HS[] s_numberPasingState = { // 400 300/200 100 90~10 8~1 6, 7, 9, ' " /* 0 */ diff --git a/src/mscorlib/corefx/System/Globalization/HijriCalendar.Win32.cs b/src/mscorlib/corefx/System/Globalization/HijriCalendar.Win32.cs new file mode 100644 index 0000000..5f46dce --- /dev/null +++ b/src/mscorlib/corefx/System/Globalization/HijriCalendar.Win32.cs @@ -0,0 +1,86 @@ +// 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 Microsoft.Win32; + +namespace System.Globalization +{ + public partial class HijriCalendar : Calendar + { + private static int GetHijriDateAdjustment() + { + if (_hijriAdvance == Int32.MinValue) { + // Never been set before. Use the system value from registry. + _hijriAdvance = GetAdvanceHijriDate(); + } + return (_hijriAdvance); + } + + private const String InternationalRegKey = "Control Panel\\International"; + private const String HijriAdvanceRegKeyEntry = "AddHijriDate"; + + /*=================================GetAdvanceHijriDate========================== + **Action: Gets the AddHijriDate value from the registry. + **Returns: + **Arguments: None. + **Exceptions: + **Note: + ** The HijriCalendar has a user-overidable calculation. That is, use can set a value from the control + ** panel, so that the calculation of the Hijri Calendar can move ahead or backwards from -2 to +2 days. + ** + ** The valid string values in the registry are: + ** "AddHijriDate-2" => Add -2 days to the current calculated Hijri date. + ** "AddHijriDate" => Add -1 day to the current calculated Hijri date. + ** "" => Add 0 day to the current calculated Hijri date. + ** "AddHijriDate+1" => Add +1 days to the current calculated Hijri date. + ** "AddHijriDate+2" => Add +2 days to the current calculated Hijri date. + ============================================================================*/ + private static int GetAdvanceHijriDate() { + int hijriAdvance = 0; + Microsoft.Win32.RegistryKey key = null; + + try { + // Open in read-only mode. + // Use InternalOpenSubKey so that we avoid the security check. + key = RegistryKey.GetBaseKey(RegistryKey.HKEY_CURRENT_USER).OpenSubKey(InternationalRegKey, false); + } + //If this fails for any reason, we'll just return 0. + catch (ObjectDisposedException) { return 0; } + catch (ArgumentException) { return 0; } + + if (key != null) { + try { + Object value = key.InternalGetValue(HijriAdvanceRegKeyEntry, null, false, false); + if (value == null) { + return (0); + } + String str = value.ToString(); + if (String.Compare(str, 0, HijriAdvanceRegKeyEntry, 0, HijriAdvanceRegKeyEntry.Length, StringComparison.OrdinalIgnoreCase) == 0) { + if (str.Length == HijriAdvanceRegKeyEntry.Length) + hijriAdvance = -1; + else { + str = str.Substring(HijriAdvanceRegKeyEntry.Length); + try { + int advance = Int32.Parse(str.ToString(), CultureInfo.InvariantCulture); + if ((advance >= MinAdvancedHijri) && (advance <= MaxAdvancedHijri)) { + hijriAdvance = advance; + } + } + // If we got garbage from registry just ignore it. + // hijriAdvance = 0 because of declaraction assignment up above. + catch (ArgumentException) { } + catch (FormatException) { } + catch (OverflowException) { } + } + } + } + finally { + key.Close(); + } + + } + return (hijriAdvance); + } + } +} diff --git a/src/mscorlib/corefx/System/Globalization/HijriCalendar.WinRT.cs b/src/mscorlib/corefx/System/Globalization/HijriCalendar.WinRT.cs new file mode 100644 index 0000000..fb91c27 --- /dev/null +++ b/src/mscorlib/corefx/System/Globalization/HijriCalendar.WinRT.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. +// See the LICENSE file in the project root for more information. + +using Internal.Runtime.Augments; + +namespace System.Globalization +{ + public partial class HijriCalendar : Calendar + { + private static int GetHijriDateAdjustment() + { + return WinRTInterop.Callbacks.GetHijriDateAdjustment(); + } + } +} diff --git a/src/mscorlib/corefx/System/Globalization/HijriCalendar.Windows.cs b/src/mscorlib/corefx/System/Globalization/HijriCalendar.Windows.cs deleted file mode 100644 index 185c518..0000000 --- a/src/mscorlib/corefx/System/Globalization/HijriCalendar.Windows.cs +++ /dev/null @@ -1,16 +0,0 @@ -// 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 Internal.Runtime.Augments; - -namespace System.Globalization -{ - public partial class HijriCalendar : Calendar - { - public static int GetHijriDateAdjustment() - { - return WinRTInterop.Callbacks.GetHijriDateAdjustment(); - } - } -} diff --git a/src/mscorlib/corefx/System/Globalization/HijriCalendar.cs b/src/mscorlib/corefx/System/Globalization/HijriCalendar.cs index 72d9ab3..156b210 100644 --- a/src/mscorlib/corefx/System/Globalization/HijriCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/HijriCalendar.cs @@ -48,7 +48,7 @@ namespace System.Globalization [System.Runtime.InteropServices.ComVisible(true)] public partial class HijriCalendar : Calendar { - internal static readonly int HijriEra = 1; + public static readonly int HijriEra = 1; internal const int DatePartYear = 0; internal const int DatePartDayOfYear = 1; @@ -91,6 +91,15 @@ namespace System.Globalization } } + [System.Runtime.InteropServices.ComVisible(false)] + public override CalendarAlgorithmType AlgorithmType + { + get + { + return CalendarAlgorithmType.LunarCalendar; + } + } + public HijriCalendar() { } @@ -221,7 +230,7 @@ namespace System.Globalization { if (era != CurrentEra && era != HijriEra) { - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } } @@ -231,7 +240,7 @@ namespace System.Globalization if (year < 1 || year > MaxCalendarYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -248,7 +257,7 @@ namespace System.Globalization if (month > MaxCalendarMonth) { throw new ArgumentOutOfRangeException( - "month", + nameof(month), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -259,7 +268,7 @@ namespace System.Globalization if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException("month", SR.ArgumentOutOfRange_Month); + throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); } } @@ -386,7 +395,7 @@ namespace System.Globalization if (months < -120000 || months > 120000) { throw new ArgumentOutOfRangeException( - "months", + nameof(months), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -542,7 +551,7 @@ namespace System.Globalization if (day < 1 || day > daysInMonth) { throw new ArgumentOutOfRangeException( - "day", + nameof(day), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Day, @@ -593,7 +602,7 @@ namespace System.Globalization if (day < 1 || day > daysInMonth) { throw new ArgumentOutOfRangeException( - "day", + nameof(day), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Day, @@ -633,7 +642,7 @@ namespace System.Globalization if (value < 99 || value > MaxCalendarYear) { throw new ArgumentOutOfRangeException( - "value", + nameof(value), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -649,7 +658,7 @@ namespace System.Globalization { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); @@ -662,7 +671,7 @@ namespace System.Globalization if (year > MaxCalendarYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, diff --git a/src/mscorlib/corefx/System/Globalization/IdnMapping.Unix.cs b/src/mscorlib/corefx/System/Globalization/IdnMapping.Unix.cs new file mode 100644 index 0000000..58f4cca --- /dev/null +++ b/src/mscorlib/corefx/System/Globalization/IdnMapping.Unix.cs @@ -0,0 +1,134 @@ +// 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. + +namespace System.Globalization +{ + sealed partial class IdnMapping + { + private unsafe string GetAsciiCore(char* unicode, int count) + { + uint flags = Flags; + CheckInvalidIdnCharacters(unicode, count, flags, nameof(unicode)); + + const int StackallocThreshold = 512; + // Each unicode character is represented by up to 3 ASCII chars + // and the whole string is prefixed by "xn--" (length 4) + int estimatedLength = (int)Math.Min(count * 3L + 4, StackallocThreshold); + int actualLength; + if (estimatedLength < StackallocThreshold) + { + char* outputStack = stackalloc char[estimatedLength]; + actualLength = Interop.GlobalizationInterop.ToAscii(flags, unicode, count, outputStack, estimatedLength); + if (actualLength > 0 && actualLength <= estimatedLength) + { + return new string(outputStack, 0, actualLength); + } + } + else + { + actualLength = Interop.GlobalizationInterop.ToAscii(flags, unicode, count, null, 0); + } + if (actualLength == 0) + { + throw new ArgumentException(SR.Argument_IdnIllegalName, nameof(unicode)); + } + + char[] outputHeap = new char[actualLength]; + fixed (char* pOutputHeap = outputHeap) + { + actualLength = Interop.GlobalizationInterop.ToAscii(flags, unicode, count, pOutputHeap, actualLength); + if (actualLength == 0 || actualLength > outputHeap.Length) + { + throw new ArgumentException(SR.Argument_IdnIllegalName, nameof(unicode)); + } + return new string(pOutputHeap, 0, actualLength); + } + } + + private unsafe string GetUnicodeCore(char* ascii, int count) + { + uint flags = Flags; + CheckInvalidIdnCharacters(ascii, count, flags, nameof(ascii)); + + const int StackAllocThreshold = 512; + if (count < StackAllocThreshold) + { + char* output = stackalloc char[count]; + return GetUnicodeCore(ascii, count, flags, output, count, reattempt: true); + } + else + { + char[] output = new char[count]; + fixed (char* pOutput = output) + { + return GetUnicodeCore(ascii, count, flags, pOutput, count, reattempt: true); + } + } + } + + private unsafe string GetUnicodeCore(char* ascii, int count, uint flags, char* output, int outputLength, bool reattempt) + { + int realLen = Interop.GlobalizationInterop.ToUnicode(flags, ascii, count, output, outputLength); + + if (realLen == 0) + { + throw new ArgumentException(SR.Argument_IdnIllegalName, nameof(ascii)); + } + else if (realLen <= outputLength) + { + return new string(output, 0, realLen); + } + else if (reattempt) + { + char[] newOutput = new char[realLen]; + fixed (char* pNewOutput = newOutput) + { + return GetUnicodeCore(ascii, count, flags, pNewOutput, realLen, reattempt: false); + } + } + + throw new ArgumentException(SR.Argument_IdnIllegalName, nameof(ascii)); + } + + // ----------------------------- + // ---- PAL layer ends here ---- + // ----------------------------- + + private uint Flags + { + get + { + int flags = + (AllowUnassigned ? Interop.GlobalizationInterop.AllowUnassigned : 0) | + (UseStd3AsciiRules ? Interop.GlobalizationInterop.UseStd3AsciiRules : 0); + return (uint)flags; + } + } + + /// + /// ICU doesn't check for invalid characters unless the STD3 rules option + /// is enabled. + /// + /// To match Windows behavior, we walk the string ourselves looking for these + /// bad characters so we can continue to throw ArgumentException in these cases. + /// + private static unsafe void CheckInvalidIdnCharacters(char* s, int count, uint flags, string paramName) + { + if ((flags & Interop.GlobalizationInterop.UseStd3AsciiRules) == 0) + { + for (int i = 0; i < count; i++) + { + char c = s[i]; + + // These characters are prohibited regardless of the UseStd3AsciiRules property. + // See https://msdn.microsoft.com/en-us/library/system.globalization.idnmapping.usestd3asciirules(v=vs.110).aspx + if (c <= 0x1F || c == 0x7F) + { + throw new ArgumentException(SR.Argument_IdnIllegalName, paramName); + } + } + } + } + } +} diff --git a/src/mscorlib/corefx/System/Globalization/IdnMapping.Windows.cs b/src/mscorlib/corefx/System/Globalization/IdnMapping.Windows.cs new file mode 100644 index 0000000..f39457b --- /dev/null +++ b/src/mscorlib/corefx/System/Globalization/IdnMapping.Windows.cs @@ -0,0 +1,113 @@ +// 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.Diagnostics; +using System.Runtime.InteropServices; + +namespace System.Globalization +{ + sealed partial class IdnMapping + { + private unsafe string GetAsciiCore(char* unicode, int count) + { + uint flags = Flags; + + // Determine the required length + int length = Interop.mincore.IdnToAscii(flags, new IntPtr(unicode), count, IntPtr.Zero, 0); + if (length == 0) + { + ThrowForZeroLength(nameof(unicode), SR.Argument_IdnIllegalName, SR.Argument_InvalidCharSequenceNoIndex); + } + + // Do the conversion + const int StackAllocThreshold = 512; // arbitrary limit to switch from stack to heap allocation + if (length < StackAllocThreshold) + { + char* output = stackalloc char[length]; + return GetAsciiCore(unicode, count, flags, output, length); + } + else + { + char[] output = new char[length]; + fixed (char* pOutput = output) + { + return GetAsciiCore(unicode, count, flags, pOutput, length); + } + } + } + + private unsafe string GetAsciiCore(char* unicode, int count, uint flags, char* output, int outputLength) + { + int length = Interop.mincore.IdnToAscii(flags, new IntPtr(unicode), count, new IntPtr(output), outputLength); + if (length == 0) + { + ThrowForZeroLength(nameof(unicode), SR.Argument_IdnIllegalName, SR.Argument_InvalidCharSequenceNoIndex); + } + Debug.Assert(length == outputLength); + return new string(output, 0, length); + } + + private unsafe string GetUnicodeCore(char* ascii, int count) + { + uint flags = Flags; + + // Determine the required length + int length = Interop.mincore.IdnToUnicode(flags, new IntPtr(ascii), count, IntPtr.Zero, 0); + if (length == 0) + { + ThrowForZeroLength(nameof(ascii), SR.Argument_IdnIllegalName, SR.Argument_IdnBadPunycode); + } + + // Do the conversion + const int StackAllocThreshold = 512; // arbitrary limit to switch from stack to heap allocation + if (length < StackAllocThreshold) + { + char* output = stackalloc char[length]; + return GetUnicodeCore(ascii, count, flags, output, length); + } + else + { + char[] output = new char[length]; + fixed (char* pOutput = output) + { + return GetUnicodeCore(ascii, count, flags, pOutput, length); + } + } + } + + private unsafe string GetUnicodeCore(char* ascii, int count, uint flags, char* output, int outputLength) + { + int length = Interop.mincore.IdnToUnicode(flags, new IntPtr(ascii), count, new IntPtr(output), outputLength); + if (length == 0) + { + ThrowForZeroLength(nameof(ascii), SR.Argument_IdnIllegalName, SR.Argument_IdnBadPunycode); + } + Debug.Assert(length == outputLength); + return new string(output, 0, length); + } + + // ----------------------------- + // ---- PAL layer ends here ---- + // ----------------------------- + + private uint Flags + { + get + { + int flags = + (AllowUnassigned ? Interop.mincore.IDN_ALLOW_UNASSIGNED : 0) | + (UseStd3AsciiRules ? Interop.mincore.IDN_USE_STD3_ASCII_RULES : 0); + return (uint)flags; + } + } + + private static void ThrowForZeroLength(string paramName, string invalidNameString, string otherString) + { + throw new ArgumentException( + Marshal.GetLastWin32Error() == Interop.ERROR_INVALID_NAME ? invalidNameString : otherString, + paramName); + } + } +} + diff --git a/src/mscorlib/corefx/System/Globalization/IdnMapping.cs b/src/mscorlib/corefx/System/Globalization/IdnMapping.cs new file mode 100644 index 0000000..8424472 --- /dev/null +++ b/src/mscorlib/corefx/System/Globalization/IdnMapping.cs @@ -0,0 +1,152 @@ +// 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. + +// This file contains the IDN functions and implementation. +// +// This allows encoding of non-ASCII domain names in a "punycode" form, +// for example: +// +// \u5B89\u5BA4\u5948\u7F8E\u6075-with-SUPER-MONKEYS +// +// is encoded as: +// +// xn---with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n +// +// Additional options are provided to allow unassigned IDN characters and +// to validate according to the Std3ASCII Rules (like DNS names). +// +// There are also rules regarding bidirectionality of text and the length +// of segments. +// +// For additional rules see also: +// RFC 3490 - Internationalizing Domain Names in Applications (IDNA) +// RFC 3491 - Nameprep: A Stringprep Profile for Internationalized Domain Names (IDN) +// RFC 3492 - Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA) + +using System.Diagnostics.Contracts; + +namespace System.Globalization +{ + // IdnMapping class used to map names to Punycode + public sealed partial class IdnMapping + { + private bool _allowUnassigned; + private bool _useStd3AsciiRules; + + public IdnMapping() + { + } + + public bool AllowUnassigned + { + get { return _allowUnassigned; } + set { _allowUnassigned = value; } + } + + public bool UseStd3AsciiRules + { + get { return _useStd3AsciiRules; } + set { _useStd3AsciiRules = value; } + } + + // Gets ASCII (Punycode) version of the string + public string GetAscii(string unicode) + { + return GetAscii(unicode, 0); + } + + public string GetAscii(string unicode, int index) + { + if (unicode == null) + throw new ArgumentNullException(nameof(unicode)); + Contract.EndContractBlock(); + return GetAscii(unicode, index, unicode.Length - index); + } + + public string GetAscii(string unicode, int index, int count) + { + if (unicode == null) + throw new ArgumentNullException(nameof(unicode)); + if (index < 0 || count < 0) + throw new ArgumentOutOfRangeException((index < 0) ? nameof(index) : nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum); + if (index > unicode.Length) + throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); + if (index > unicode.Length - count) + throw new ArgumentOutOfRangeException(nameof(unicode), SR.ArgumentOutOfRange_IndexCountBuffer); + Contract.EndContractBlock(); + + if (count == 0) + { + throw new ArgumentException(SR.Argument_IdnBadLabelSize, nameof(unicode)); + } + if (unicode[index + count - 1] == 0) + { + throw new ArgumentException(SR.Format(SR.Argument_InvalidCharSequence, index + count - 1), nameof(unicode)); + } + + unsafe + { + fixed (char* pUnicode = unicode) + { + return GetAsciiCore(pUnicode + index, count); + } + } + } + + // Gets Unicode version of the string. Normalized and limited to IDNA characters. + public string GetUnicode(string ascii) + { + return GetUnicode(ascii, 0); + } + + public string GetUnicode(string ascii, int index) + { + if (ascii == null) + throw new ArgumentNullException(nameof(ascii)); + Contract.EndContractBlock(); + return GetUnicode(ascii, index, ascii.Length - index); + } + + public string GetUnicode(string ascii, int index, int count) + { + if (ascii == null) + throw new ArgumentNullException(nameof(ascii)); + if (index < 0 || count < 0) + throw new ArgumentOutOfRangeException((index < 0) ? nameof(index) : nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum); + if (index > ascii.Length) + throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); + if (index > ascii.Length - count) + throw new ArgumentOutOfRangeException(nameof(ascii), SR.ArgumentOutOfRange_IndexCountBuffer); + + // This is a case (i.e. explicitly null-terminated input) where behavior in .NET and Win32 intentionally differ. + // The .NET APIs should (and did in v4.0 and earlier) throw an ArgumentException on input that includes a terminating null. + // The Win32 APIs fail on an embedded null, but not on a terminating null. + if (count > 0 && ascii[index + count - 1] == (char)0) + throw new ArgumentException(SR.Argument_IdnBadPunycode, nameof(ascii)); + Contract.EndContractBlock(); + + unsafe + { + fixed (char* pAscii = ascii) + { + return GetUnicodeCore(pAscii + index, count); + } + } + } + + public override bool Equals(object obj) + { + IdnMapping that = obj as IdnMapping; + return + that != null && + _allowUnassigned == that._allowUnassigned && + _useStd3AsciiRules == that._useStd3AsciiRules; + } + + public override int GetHashCode() + { + return (_allowUnassigned ? 100 : 200) + (_useStd3AsciiRules ? 1000 : 2000); + } + } +} diff --git a/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Unix.cs b/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Unix.cs index 12f430c..b9bd94a 100644 --- a/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Unix.cs +++ b/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Unix.cs @@ -3,13 +3,11 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; -using System.Security; namespace System.Globalization { public partial class JapaneseCalendar : Calendar { - [SecuritySafeCritical] private static EraInfo[] GetJapaneseEras() { string[] eraNames; @@ -66,7 +64,6 @@ namespace System.Globalization return eraNames[eraIndex].Substring(0, 1); } - [SecuritySafeCritical] private static bool GetJapaneseEraStartDate(int era, out DateTime dateTime) { dateTime = default(DateTime); diff --git a/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Win32.cs b/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Win32.cs new file mode 100644 index 0000000..bbde320 --- /dev/null +++ b/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Win32.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. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; + +using Microsoft.Win32; + +namespace System.Globalization +{ + public partial class JapaneseCalendar : Calendar + { + private const string c_japaneseErasHive = @"System\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras"; + private const string c_japaneseErasHivePermissionList = @"HKEY_LOCAL_MACHINE\" + c_japaneseErasHive; + + // We know about 4 built-in eras, however users may add additional era(s) from the + // registry, by adding values to HKLM\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras + // + // Registry values look like: + // yyyy.mm.dd=era_abbrev_english_englishabbrev + // + // Where yyyy.mm.dd is the registry value name, and also the date of the era start. + // yyyy, mm, and dd are the year, month & day the era begins (4, 2 & 2 digits long) + // era is the Japanese Era name + // abbrev is the Abbreviated Japanese Era Name + // english is the English name for the Era (unused) + // englishabbrev is the Abbreviated English name for the era. + // . is a delimiter, but the value of . doesn't matter. + // '_' marks the space between the japanese era name, japanese abbreviated era name + // english name, and abbreviated english names. + private static EraInfo[] GetJapaneseEras() + { + // Look in the registry key and see if we can find any ranges + int iFoundEras = 0; + EraInfo[] registryEraRanges = null; + + try + { + // Need to access registry + RegistryKey key = RegistryKey.GetBaseKey(RegistryKey.HKEY_LOCAL_MACHINE).OpenSubKey(c_japaneseErasHive, false); + + // Abort if we didn't find anything + if (key == null) return null; + + // Look up the values in our reg key + String[] valueNames = key.GetValueNames(); + if (valueNames != null && valueNames.Length > 0) + { + registryEraRanges = new EraInfo[valueNames.Length]; + + // Loop through the registry and read in all the values + for (int i = 0; i < valueNames.Length; i++) + { + // See if the era is a valid date + EraInfo era = GetEraFromValue(valueNames[i], key.GetValue(valueNames[i]).ToString()); + + // continue if not valid + if (era == null) continue; + + // Remember we found one. + registryEraRanges[iFoundEras] = era; + iFoundEras++; + } + } + } + catch (System.Security.SecurityException) + { + // If we weren't allowed to read, then just ignore the error + return null; + } + catch (System.IO.IOException) + { + // If key is being deleted just ignore the error + return null; + } + catch (System.UnauthorizedAccessException) + { + // Registry access rights permissions, just ignore the error + return null; + } + + // + // If we didn't have valid eras, then fail + // should have at least 4 eras + // + if (iFoundEras < 4) return null; + + // + // Now we have eras, clean them up. + // + // Clean up array length + Array.Resize(ref registryEraRanges, iFoundEras); + + // Sort them + Array.Sort(registryEraRanges, CompareEraRanges); + + // Clean up era information + for (int i = 0; i < registryEraRanges.Length; i++) + { + // eras count backwards from length to 1 (and are 1 based indexes into string arrays) + registryEraRanges[i].era = registryEraRanges.Length - i; + + // update max era year + if (i == 0) + { + // First range is 'til the end of the calendar + registryEraRanges[0].maxEraYear = GregorianCalendar.MaxYear - registryEraRanges[0].yearOffset; + } + else + { + // Rest are until the next era (remember most recent era is first in array) + registryEraRanges[i].maxEraYear = registryEraRanges[i-1].yearOffset + 1 - registryEraRanges[i].yearOffset; + } + } + + // Return our ranges + return registryEraRanges; + } + + // + // Compare two era ranges, eg just the ticks + // Remember the era array is supposed to be in reverse chronological order + // + private static int CompareEraRanges(EraInfo a, EraInfo b) + { + return b.ticks.CompareTo(a.ticks); + } + + // + // GetEraFromValue + // + // Parse the registry value name/data pair into an era + // + // Registry values look like: + // yyyy.mm.dd=era_abbrev_english_englishabbrev + // + // Where yyyy.mm.dd is the registry value name, and also the date of the era start. + // yyyy, mm, and dd are the year, month & day the era begins (4, 2 & 2 digits long) + // era is the Japanese Era name + // abbrev is the Abbreviated Japanese Era Name + // english is the English name for the Era (unused) + // englishabbrev is the Abbreviated English name for the era. + // . is a delimiter, but the value of . doesn't matter. + // '_' marks the space between the japanese era name, japanese abbreviated era name + // english name, and abbreviated english names. + private static EraInfo GetEraFromValue(String value, String data) + { + // Need inputs + if (value == null || data == null) return null; + + // + // Get Date + // + // Need exactly 10 characters in name for date + // yyyy.mm.dd although the . can be any character + if (value.Length != 10) return null; + + int year; + int month; + int day; + + if (!Int32.TryParse(value.Substring(0,4), NumberStyles.None, NumberFormatInfo.InvariantInfo, out year) || + !Int32.TryParse(value.Substring(5,2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out month) || + !Int32.TryParse(value.Substring(8,2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out day)) + { + // Couldn't convert integer, fail + return null; + } + + // + // Get Strings + // + // Needs to be a certain length e_a_E_A at least (7 chars, exactly 4 groups) + String[] names = data.Split(new char[] {'_'}); + + // Should have exactly 4 parts + // 0 - Era Name + // 1 - Abbreviated Era Name + // 2 - English Era Name + // 3 - Abbreviated English Era Name + if (names.Length != 4) return null; + + // Each part should have data in it + if (names[0].Length == 0 || + names[1].Length == 0 || + names[2].Length == 0 || + names[3].Length == 0) + return null; + + // + // Now we have an era we can build + // Note that the era # and max era year need cleaned up after sorting + // Don't use the full English Era Name (names[2]) + // + return new EraInfo( 0, year, month, day, year - 1, 1, 0, + names[0], names[1], names[3]); + } + + // PAL Layer ends here + + private static string[] JapaneseErasEnglishNames = new String[] { "M", "T", "S", "H" }; + + private static string GetJapaneseEnglishEraName(int era) + { + Debug.Assert(era > 0); + return era <= JapaneseErasEnglishNames.Length ? JapaneseErasEnglishNames[era - 1] : " "; + } + } +} diff --git a/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Windows.cs b/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.WinRT.cs similarity index 100% rename from src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Windows.cs rename to src/mscorlib/corefx/System/Globalization/JapaneseCalendar.WinRT.cs diff --git a/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.cs b/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.cs index 4130801..0b0fa77 100644 --- a/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.cs @@ -9,11 +9,6 @@ using System.Diagnostics.Contracts; namespace System.Globalization { - -#if INSIDE_CLR - using Debug = BCLDebug; -#endif - /*=================================JapaneseCalendar========================== ** ** JapaneseCalendar is based on Gregorian calendar. The month and day values are the same as @@ -68,6 +63,15 @@ namespace System.Globalization } } + [System.Runtime.InteropServices.ComVisible(false)] + public override CalendarAlgorithmType AlgorithmType + { + get + { + return CalendarAlgorithmType.SolarCalendar; + } + } + // // Using a field initializer rather than a static constructor so that the whole class can be lazy // init. @@ -302,7 +306,7 @@ namespace System.Globalization { if (year <= 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_NeedPosNum); } Contract.EndContractBlock(); @@ -310,7 +314,7 @@ namespace System.Globalization if (year > helper.MaxYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, diff --git a/src/mscorlib/corefx/System/Globalization/JulianCalendar.cs b/src/mscorlib/corefx/System/Globalization/JulianCalendar.cs index 6721899..a4277c6 100644 --- a/src/mscorlib/corefx/System/Globalization/JulianCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/JulianCalendar.cs @@ -67,17 +67,14 @@ namespace System.Globalization } } - // Return the type of the Julian calendar. - // - - //[System.Runtime.InteropServices.ComVisible(false)] - //public override CalendarAlgorithmType AlgorithmType - //{ - // get - // { - // return CalendarAlgorithmType.SolarCalendar; - // } - //} + [System.Runtime.InteropServices.ComVisible(false)] + public override CalendarAlgorithmType AlgorithmType + { + get + { + return CalendarAlgorithmType.SolarCalendar; + } + } public JulianCalendar() { @@ -97,7 +94,7 @@ namespace System.Globalization { if (era != CurrentEra && era != JulianEra) { - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } } @@ -107,7 +104,7 @@ namespace System.Globalization if (year <= 0 || year > MaxYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -120,7 +117,7 @@ namespace System.Globalization { if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException("month", SR.ArgumentOutOfRange_Month); + throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); } } @@ -151,7 +148,7 @@ namespace System.Globalization if (day < 1 || day > monthDays) { throw new ArgumentOutOfRangeException( - "day", + nameof(day), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -196,7 +193,7 @@ namespace System.Globalization int[] days = leapYear ? s_daysToMonth366 : s_daysToMonth365; // All months have less than 32 days, so n >> 5 is a good conservative // estimate for the month - int m = n >> 5 + 1; + int m = (n >> 5) + 1; // m = 1-based month number while (n >= days[m]) m++; // If month was requested, return it @@ -223,7 +220,7 @@ namespace System.Globalization if (months < -120000 || months > 120000) { throw new ArgumentOutOfRangeException( - "months", + nameof(months), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -383,7 +380,7 @@ namespace System.Globalization if (millisecond < 0 || millisecond >= MillisPerSecond) { throw new ArgumentOutOfRangeException( - "millisecond", + nameof(millisecond), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -431,7 +428,7 @@ namespace System.Globalization { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); @@ -439,7 +436,7 @@ namespace System.Globalization if (year > MaxYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Bounds_Lower_Upper, diff --git a/src/mscorlib/corefx/System/Globalization/KoreanCalendar.cs b/src/mscorlib/corefx/System/Globalization/KoreanCalendar.cs index 38a0b41..27d0aa8 100644 --- a/src/mscorlib/corefx/System/Globalization/KoreanCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/KoreanCalendar.cs @@ -69,6 +69,15 @@ namespace System.Globalization } } + [System.Runtime.InteropServices.ComVisible(false)] + public override CalendarAlgorithmType AlgorithmType + { + get + { + return CalendarAlgorithmType.SolarCalendar; + } + } + public KoreanCalendar() { try @@ -253,7 +262,7 @@ namespace System.Globalization { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); diff --git a/src/mscorlib/corefx/System/Globalization/KoreanLunisolarCalendar.cs b/src/mscorlib/corefx/System/Globalization/KoreanLunisolarCalendar.cs index 68c4fab..07d85a4 100644 --- a/src/mscorlib/corefx/System/Globalization/KoreanLunisolarCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/KoreanLunisolarCalendar.cs @@ -1275,12 +1275,12 @@ namespace System.Globalization internal override int GetGregorianYear(int year, int era) { if (era != CurrentEra && era != GregorianEra) - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); if (year < MIN_LUNISOLAR_YEAR || year > MAX_LUNISOLAR_YEAR) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR)); diff --git a/src/mscorlib/corefx/System/Globalization/LocaleData.Unix.cs b/src/mscorlib/corefx/System/Globalization/LocaleData.Unix.cs new file mode 100644 index 0000000..d4c58d8 --- /dev/null +++ b/src/mscorlib/corefx/System/Globalization/LocaleData.Unix.cs @@ -0,0 +1,4572 @@ +// 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.Diagnostics; +using System.Diagnostics.Contracts; + +// This file contains the handling of Windows OS specific culture features. + +namespace System.Globalization +{ + internal enum LocaleDataParts + { + Lcid = 0, + AnsiCodePage = 1, + OemCodePage = 2, + MacCodePage = 3, + EbcdicCodePage = 4, + GeoId = 5, + DigitSubstitution = 6, + SpecificLocaleIndex = 7, + ConsoleLocaleIndex = 8 + } + + internal partial class LocaleData + { + // this is done rather than using a large readonly array of strings to avoid + // generating a large amount of code in the static constructor. + // Using indices from s_localeNamesIndices, we binary search this string when mapping + // an culture name to Lcid. Note that these names are all lowercase and are + // sorted alphabetically (ordinal). + private const string c_localeNames = + // culture name Lcid + "aa" + // 01000 - 0 + "aa-dj" + // 01000 - 2 + "aa-er" + // 01000 - 7 + "aa-et" + // 01000 - 12 + "af" + // 00036 - 17 + "af-na" + // 01000 - 19 + "af-za" + // 00436 - 24 + "agq" + // 01000 - 29 + "agq-cm" + // 01000 - 32 + "ak" + // 01000 - 38 + "ak-gh" + // 01000 - 40 + "am" + // 0005e - 45 + "am-et" + // 0045e - 47 + "ar" + // 00001 - 52 + "ar-001" + // 01000 - 54 + "ar-ae" + // 03801 - 60 + "ar-bh" + // 03c01 - 65 + "ar-dj" + // 01000 - 70 + "ar-dz" + // 01401 - 75 + "ar-eg" + // 00c01 - 80 + "ar-er" + // 01000 - 85 + "ar-il" + // 01000 - 90 + "ar-iq" + // 00801 - 95 + "ar-jo" + // 02c01 - 100 + "ar-km" + // 01000 - 105 + "ar-kw" + // 03401 - 110 + "ar-lb" + // 03001 - 115 + "ar-ly" + // 01001 - 120 + "ar-ma" + // 01801 - 125 + "ar-mr" + // 01000 - 130 + "ar-om" + // 02001 - 135 + "ar-ps" + // 01000 - 140 + "ar-qa" + // 04001 - 145 + "ar-sa" + // 00401 - 150 + "ar-sd" + // 01000 - 155 + "ar-so" + // 01000 - 160 + "ar-ss" + // 01000 - 165 + "ar-sy" + // 02801 - 170 + "ar-td" + // 01000 - 175 + "ar-tn" + // 01c01 - 180 + "ar-ye" + // 02401 - 185 + "arn" + // 0007a - 190 + "arn-cl" + // 0047a - 193 + "as" + // 0004d - 199 + "as-in" + // 0044d - 201 + "asa" + // 01000 - 206 + "asa-tz" + // 01000 - 209 + "ast" + // 01000 - 215 + "ast-es" + // 01000 - 218 + "az" + // 0002c - 224 + "az-cyrl" + // 0742c - 226 + "az-cyrl-az" + // 0082c - 233 + "az-latn" + // 0782c - 243 + "az-latn-az" + // 0042c - 250 + "ba" + // 0006d - 260 + "ba-ru" + // 0046d - 262 + "bas" + // 01000 - 267 + "bas-cm" + // 01000 - 270 + "be" + // 00023 - 276 + "be-by" + // 00423 - 278 + "bem" + // 01000 - 283 + "bem-zm" + // 01000 - 286 + "bez" + // 01000 - 292 + "bez-tz" + // 01000 - 295 + "bg" + // 00002 - 301 + "bg-bg" + // 00402 - 303 + "bin" + // 00066 - 308 + "bin-ng" + // 00466 - 311 + "bm" + // 01000 - 317 + "bm-latn" + // 01000 - 319 + "bm-latn-ml" + // 01000 - 326 + "bn" + // 00045 - 336 + "bn-bd" + // 00845 - 338 + "bn-in" + // 00445 - 343 + "bo" + // 00051 - 348 + "bo-cn" + // 00451 - 350 + "bo-in" + // 01000 - 355 + "br" + // 0007e - 360 + "br-fr" + // 0047e - 362 + "brx" + // 01000 - 367 + "brx-in" + // 01000 - 370 + "bs" + // 0781a - 376 + "bs-cyrl" + // 0641a - 378 + "bs-cyrl-ba" + // 0201a - 385 + "bs-latn" + // 0681a - 395 + "bs-latn-ba" + // 0141a - 402 + "byn" + // 01000 - 412 + "byn-er" + // 01000 - 415 + "ca" + // 00003 - 421 + "ca-ad" + // 01000 - 423 + "ca-es" + // 00403 - 428 + "ca-es-valencia" + // 00803 - 433 + "ca-fr" + // 01000 - 447 + "ca-it" + // 01000 - 452 + "ce" + // 01000 - 457 + "ce-ru" + // 01000 - 459 + "cgg" + // 01000 - 464 + "cgg-ug" + // 01000 - 467 + "chr" + // 0005c - 473 + "chr-cher" + // 07c5c - 476 + "chr-cher-us" + // 0045c - 484 + "co" + // 00083 - 495 + "co-fr" + // 00483 - 497 + "cs" + // 00005 - 502 + "cs-cz" + // 00405 - 504 + "cu" + // 01000 - 509 + "cu-ru" + // 01000 - 511 + "cy" + // 00052 - 516 + "cy-gb" + // 00452 - 518 + "da" + // 00006 - 523 + "da-dk" + // 00406 - 525 + "da-gl" + // 01000 - 530 + "dav" + // 01000 - 535 + "dav-ke" + // 01000 - 538 + "de" + // 00007 - 544 + "de-at" + // 00c07 - 546 + "de-be" + // 01000 - 551 + "de-ch" + // 00807 - 556 + "de-de" + // 00407 - 561 + "de-de_phoneb" + // 10407 - 566 + "de-it" + // 01000 - 578 + "de-li" + // 01407 - 583 + "de-lu" + // 01007 - 588 + "dje" + // 01000 - 593 + "dje-ne" + // 01000 - 596 + "dsb" + // 07c2e - 602 + "dsb-de" + // 0082e - 605 + "dua" + // 01000 - 611 + "dua-cm" + // 01000 - 614 + "dv" + // 00065 - 620 + "dv-mv" + // 00465 - 622 + "dyo" + // 01000 - 627 + "dyo-sn" + // 01000 - 630 + "dz" + // 01000 - 636 + "dz-bt" + // 00c51 - 638 + "ebu" + // 01000 - 643 + "ebu-ke" + // 01000 - 646 + "ee" + // 01000 - 652 + "ee-gh" + // 01000 - 654 + "ee-tg" + // 01000 - 659 + "el" + // 00008 - 664 + "el-cy" + // 01000 - 666 + "el-gr" + // 00408 - 671 + "en" + // 00009 - 676 + "en-001" + // 01000 - 678 + "en-029" + // 02409 - 684 + "en-150" + // 01000 - 690 + "en-ag" + // 01000 - 696 + "en-ai" + // 01000 - 701 + "en-as" + // 01000 - 706 + "en-at" + // 01000 - 711 + "en-au" + // 00c09 - 716 + "en-bb" + // 01000 - 721 + "en-be" + // 01000 - 726 + "en-bi" + // 01000 - 731 + "en-bm" + // 01000 - 736 + "en-bs" + // 01000 - 741 + "en-bw" + // 01000 - 746 + "en-bz" + // 02809 - 751 + "en-ca" + // 01009 - 756 + "en-cc" + // 01000 - 761 + "en-ch" + // 01000 - 766 + "en-ck" + // 01000 - 771 + "en-cm" + // 01000 - 776 + "en-cx" + // 01000 - 781 + "en-cy" + // 01000 - 786 + "en-de" + // 01000 - 791 + "en-dk" + // 01000 - 796 + "en-dm" + // 01000 - 801 + "en-er" + // 01000 - 806 + "en-fi" + // 01000 - 811 + "en-fj" + // 01000 - 816 + "en-fk" + // 01000 - 821 + "en-fm" + // 01000 - 826 + "en-gb" + // 00809 - 831 + "en-gd" + // 01000 - 836 + "en-gg" + // 01000 - 841 + "en-gh" + // 01000 - 846 + "en-gi" + // 01000 - 851 + "en-gm" + // 01000 - 856 + "en-gu" + // 01000 - 861 + "en-gy" + // 01000 - 866 + "en-hk" + // 03c09 - 871 + "en-id" + // 03809 - 876 + "en-ie" + // 01809 - 881 + "en-il" + // 01000 - 886 + "en-im" + // 01000 - 891 + "en-in" + // 04009 - 896 + "en-io" + // 01000 - 901 + "en-je" + // 01000 - 906 + "en-jm" + // 02009 - 911 + "en-ke" + // 01000 - 916 + "en-ki" + // 01000 - 921 + "en-kn" + // 01000 - 926 + "en-ky" + // 01000 - 931 + "en-lc" + // 01000 - 936 + "en-lr" + // 01000 - 941 + "en-ls" + // 01000 - 946 + "en-mg" + // 01000 - 951 + "en-mh" + // 01000 - 956 + "en-mo" + // 01000 - 961 + "en-mp" + // 01000 - 966 + "en-ms" + // 01000 - 971 + "en-mt" + // 01000 - 976 + "en-mu" + // 01000 - 981 + "en-mw" + // 01000 - 986 + "en-my" + // 04409 - 991 + "en-na" + // 01000 - 996 + "en-nf" + // 01000 - 1001 + "en-ng" + // 01000 - 1006 + "en-nl" + // 01000 - 1011 + "en-nr" + // 01000 - 1016 + "en-nu" + // 01000 - 1021 + "en-nz" + // 01409 - 1026 + "en-pg" + // 01000 - 1031 + "en-ph" + // 03409 - 1036 + "en-pk" + // 01000 - 1041 + "en-pn" + // 01000 - 1046 + "en-pr" + // 01000 - 1051 + "en-pw" + // 01000 - 1056 + "en-rw" + // 01000 - 1061 + "en-sb" + // 01000 - 1066 + "en-sc" + // 01000 - 1071 + "en-sd" + // 01000 - 1076 + "en-se" + // 01000 - 1081 + "en-sg" + // 04809 - 1086 + "en-sh" + // 01000 - 1091 + "en-si" + // 01000 - 1096 + "en-sl" + // 01000 - 1101 + "en-ss" + // 01000 - 1106 + "en-sx" + // 01000 - 1111 + "en-sz" + // 01000 - 1116 + "en-tc" + // 01000 - 1121 + "en-tk" + // 01000 - 1126 + "en-to" + // 01000 - 1131 + "en-tt" + // 02c09 - 1136 + "en-tv" + // 01000 - 1141 + "en-tz" + // 01000 - 1146 + "en-ug" + // 01000 - 1151 + "en-um" + // 01000 - 1156 + "en-us" + // 00409 - 1161 + "en-vc" + // 01000 - 1166 + "en-vg" + // 01000 - 1171 + "en-vi" + // 01000 - 1176 + "en-vu" + // 01000 - 1181 + "en-ws" + // 01000 - 1186 + "en-za" + // 01c09 - 1191 + "en-zm" + // 01000 - 1196 + "en-zw" + // 03009 - 1201 + "eo" + // 01000 - 1206 + "eo-001" + // 01000 - 1208 + "es" + // 0000a - 1214 + "es-419" + // 0580a - 1216 + "es-ar" + // 02c0a - 1222 + "es-bo" + // 0400a - 1227 + "es-br" + // 01000 - 1232 + "es-cl" + // 0340a - 1237 + "es-co" + // 0240a - 1242 + "es-cr" + // 0140a - 1247 + "es-cu" + // 05c0a - 1252 + "es-do" + // 01c0a - 1257 + "es-ec" + // 0300a - 1262 + "es-es" + // 00c0a - 1267 + "es-es_tradnl" + // 0040a - 1272 + "es-gq" + // 01000 - 1284 + "es-gt" + // 0100a - 1289 + "es-hn" + // 0480a - 1294 + "es-mx" + // 0080a - 1299 + "es-ni" + // 04c0a - 1304 + "es-pa" + // 0180a - 1309 + "es-pe" + // 0280a - 1314 + "es-ph" + // 01000 - 1319 + "es-pr" + // 0500a - 1324 + "es-py" + // 03c0a - 1329 + "es-sv" + // 0440a - 1334 + "es-us" + // 0540a - 1339 + "es-uy" + // 0380a - 1344 + "es-ve" + // 0200a - 1349 + "et" + // 00025 - 1354 + "et-ee" + // 00425 - 1356 + "eu" + // 0002d - 1361 + "eu-es" + // 0042d - 1363 + "ewo" + // 01000 - 1368 + "ewo-cm" + // 01000 - 1371 + "fa" + // 00029 - 1377 + "fa-ir" + // 00429 - 1379 + "ff" + // 00067 - 1384 + "ff-cm" + // 01000 - 1386 + "ff-gn" + // 01000 - 1391 + "ff-latn" + // 07c67 - 1396 + "ff-latn-sn" + // 00867 - 1403 + "ff-mr" + // 01000 - 1413 + "ff-ng" + // 00467 - 1418 + "fi" + // 0000b - 1423 + "fi-fi" + // 0040b - 1425 + "fil" + // 00064 - 1430 + "fil-ph" + // 00464 - 1433 + "fo" + // 00038 - 1439 + "fo-dk" + // 01000 - 1441 + "fo-fo" + // 00438 - 1446 + "fr" + // 0000c - 1451 + "fr-029" + // 01c0c - 1453 + "fr-be" + // 0080c - 1459 + "fr-bf" + // 01000 - 1464 + "fr-bi" + // 01000 - 1469 + "fr-bj" + // 01000 - 1474 + "fr-bl" + // 01000 - 1479 + "fr-ca" + // 00c0c - 1484 + "fr-cd" + // 0240c - 1489 + "fr-cf" + // 01000 - 1494 + "fr-cg" + // 01000 - 1499 + "fr-ch" + // 0100c - 1504 + "fr-ci" + // 0300c - 1509 + "fr-cm" + // 02c0c - 1514 + "fr-dj" + // 01000 - 1519 + "fr-dz" + // 01000 - 1524 + "fr-fr" + // 0040c - 1529 + "fr-ga" + // 01000 - 1534 + "fr-gf" + // 01000 - 1539 + "fr-gn" + // 01000 - 1544 + "fr-gp" + // 01000 - 1549 + "fr-gq" + // 01000 - 1554 + "fr-ht" + // 03c0c - 1559 + "fr-km" + // 01000 - 1564 + "fr-lu" + // 0140c - 1569 + "fr-ma" + // 0380c - 1574 + "fr-mc" + // 0180c - 1579 + "fr-mf" + // 01000 - 1584 + "fr-mg" + // 01000 - 1589 + "fr-ml" + // 0340c - 1594 + "fr-mq" + // 01000 - 1599 + "fr-mr" + // 01000 - 1604 + "fr-mu" + // 01000 - 1609 + "fr-nc" + // 01000 - 1614 + "fr-ne" + // 01000 - 1619 + "fr-pf" + // 01000 - 1624 + "fr-pm" + // 01000 - 1629 + "fr-re" + // 0200c - 1634 + "fr-rw" + // 01000 - 1639 + "fr-sc" + // 01000 - 1644 + "fr-sn" + // 0280c - 1649 + "fr-sy" + // 01000 - 1654 + "fr-td" + // 01000 - 1659 + "fr-tg" + // 01000 - 1664 + "fr-tn" + // 01000 - 1669 + "fr-vu" + // 01000 - 1674 + "fr-wf" + // 01000 - 1679 + "fr-yt" + // 01000 - 1684 + "fur" + // 01000 - 1689 + "fur-it" + // 01000 - 1692 + "fy" + // 00062 - 1698 + "fy-nl" + // 00462 - 1700 + "ga" + // 0003c - 1705 + "ga-ie" + // 0083c - 1707 + "gd" + // 00091 - 1712 + "gd-gb" + // 00491 - 1714 + "gl" + // 00056 - 1719 + "gl-es" + // 00456 - 1721 + "gn" + // 00074 - 1726 + "gn-py" + // 00474 - 1728 + "gsw" + // 00084 - 1733 + "gsw-ch" + // 01000 - 1736 + "gsw-fr" + // 00484 - 1742 + "gsw-li" + // 01000 - 1748 + "gu" + // 00047 - 1754 + "gu-in" + // 00447 - 1756 + "guz" + // 01000 - 1761 + "guz-ke" + // 01000 - 1764 + "gv" + // 01000 - 1770 + "gv-im" + // 01000 - 1772 + "ha" + // 00068 - 1777 + "ha-latn" + // 07c68 - 1779 + "ha-latn-gh" + // 01000 - 1786 + "ha-latn-ne" + // 01000 - 1796 + "ha-latn-ng" + // 00468 - 1806 + "haw" + // 00075 - 1816 + "haw-us" + // 00475 - 1819 + "he" + // 0000d - 1825 + "he-il" + // 0040d - 1827 + "hi" + // 00039 - 1832 + "hi-in" + // 00439 - 1834 + "hr" + // 0001a - 1839 + "hr-ba" + // 0101a - 1841 + "hr-hr" + // 0041a - 1846 + "hsb" + // 0002e - 1851 + "hsb-de" + // 0042e - 1854 + "hu" + // 0000e - 1860 + "hu-hu" + // 0040e - 1862 + "hu-hu_technl" + // 1040e - 1867 + "hy" + // 0002b - 1879 + "hy-am" + // 0042b - 1881 + "ia" + // 01000 - 1886 + "ia-001" + // 01000 - 1888 + "ia-fr" + // 01000 - 1894 + "ibb" + // 00069 - 1899 + "ibb-ng" + // 00469 - 1902 + "id" + // 00021 - 1908 + "id-id" + // 00421 - 1910 + "ig" + // 00070 - 1915 + "ig-ng" + // 00470 - 1917 + "ii" + // 00078 - 1922 + "ii-cn" + // 00478 - 1924 + "is" + // 0000f - 1929 + "is-is" + // 0040f - 1931 + "it" + // 00010 - 1936 + "it-ch" + // 00810 - 1938 + "it-it" + // 00410 - 1943 + "it-sm" + // 01000 - 1948 + "iu" + // 0005d - 1953 + "iu-cans" + // 0785d - 1955 + "iu-cans-ca" + // 0045d - 1962 + "iu-latn" + // 07c5d - 1972 + "iu-latn-ca" + // 0085d - 1979 + "ja" + // 00011 - 1989 + "ja-jp" + // 00411 - 1991 + "ja-jp_radstr" + // 40411 - 1996 + "jgo" + // 01000 - 2008 + "jgo-cm" + // 01000 - 2011 + "jmc" + // 01000 - 2017 + "jmc-tz" + // 01000 - 2020 + "jv" + // 01000 - 2026 + "jv-java" + // 01000 - 2028 + "jv-java-id" + // 01000 - 2035 + "jv-latn" + // 01000 - 2045 + "jv-latn-id" + // 01000 - 2052 + "ka" + // 00037 - 2062 + "ka-ge" + // 00437 - 2064 + "ka-ge_modern" + // 10437 - 2069 + "kab" + // 01000 - 2081 + "kab-dz" + // 01000 - 2084 + "kam" + // 01000 - 2090 + "kam-ke" + // 01000 - 2093 + "kde" + // 01000 - 2099 + "kde-tz" + // 01000 - 2102 + "kea" + // 01000 - 2108 + "kea-cv" + // 01000 - 2111 + "khq" + // 01000 - 2117 + "khq-ml" + // 01000 - 2120 + "ki" + // 01000 - 2126 + "ki-ke" + // 01000 - 2128 + "kk" + // 0003f - 2133 + "kk-kz" + // 0043f - 2135 + "kkj" + // 01000 - 2140 + "kkj-cm" + // 01000 - 2143 + "kl" + // 0006f - 2149 + "kl-gl" + // 0046f - 2151 + "kln" + // 01000 - 2156 + "kln-ke" + // 01000 - 2159 + "km" + // 00053 - 2165 + "km-kh" + // 00453 - 2167 + "kn" + // 0004b - 2172 + "kn-in" + // 0044b - 2174 + "ko" + // 00012 - 2179 + "ko-kp" + // 01000 - 2181 + "ko-kr" + // 00412 - 2186 + "kok" + // 00057 - 2191 + "kok-in" + // 00457 - 2194 + "kr" + // 00071 - 2200 + "kr-ng" + // 00471 - 2202 + "ks" + // 00060 - 2207 + "ks-arab" + // 00460 - 2209 + "ks-arab-in" + // 01000 - 2216 + "ks-deva" + // 01000 - 2226 + "ks-deva-in" + // 00860 - 2233 + "ksb" + // 01000 - 2243 + "ksb-tz" + // 01000 - 2246 + "ksf" + // 01000 - 2252 + "ksf-cm" + // 01000 - 2255 + "ksh" + // 01000 - 2261 + "ksh-de" + // 01000 - 2264 + "ku" + // 00092 - 2270 + "ku-arab" + // 07c92 - 2272 + "ku-arab-iq" + // 00492 - 2279 + "ku-arab-ir" + // 01000 - 2289 + "kw" + // 01000 - 2299 + "kw-gb" + // 01000 - 2301 + "ky" + // 00040 - 2306 + "ky-kg" + // 00440 - 2308 + "la" + // 00076 - 2313 + "la-001" + // 00476 - 2315 + "lag" + // 01000 - 2321 + "lag-tz" + // 01000 - 2324 + "lb" + // 0006e - 2330 + "lb-lu" + // 0046e - 2332 + "lg" + // 01000 - 2337 + "lg-ug" + // 01000 - 2339 + "lkt" + // 01000 - 2344 + "lkt-us" + // 01000 - 2347 + "ln" + // 01000 - 2353 + "ln-ao" + // 01000 - 2355 + "ln-cd" + // 01000 - 2360 + "ln-cf" + // 01000 - 2365 + "ln-cg" + // 01000 - 2370 + "lo" + // 00054 - 2375 + "lo-la" + // 00454 - 2377 + "lrc" + // 01000 - 2382 + "lrc-iq" + // 01000 - 2385 + "lrc-ir" + // 01000 - 2391 + "lt" + // 00027 - 2397 + "lt-lt" + // 00427 - 2399 + "lu" + // 01000 - 2404 + "lu-cd" + // 01000 - 2406 + "luo" + // 01000 - 2411 + "luo-ke" + // 01000 - 2414 + "luy" + // 01000 - 2420 + "luy-ke" + // 01000 - 2423 + "lv" + // 00026 - 2429 + "lv-lv" + // 00426 - 2431 + "mas" + // 01000 - 2436 + "mas-ke" + // 01000 - 2439 + "mas-tz" + // 01000 - 2445 + "mer" + // 01000 - 2451 + "mer-ke" + // 01000 - 2454 + "mfe" + // 01000 - 2460 + "mfe-mu" + // 01000 - 2463 + "mg" + // 01000 - 2469 + "mg-mg" + // 01000 - 2471 + "mgh" + // 01000 - 2476 + "mgh-mz" + // 01000 - 2479 + "mgo" + // 01000 - 2485 + "mgo-cm" + // 01000 - 2488 + "mi" + // 00081 - 2494 + "mi-nz" + // 00481 - 2496 + "mk" + // 0002f - 2501 + "mk-mk" + // 0042f - 2503 + "ml" + // 0004c - 2508 + "ml-in" + // 0044c - 2510 + "mn" + // 00050 - 2515 + "mn-cyrl" + // 07850 - 2517 + "mn-mn" + // 00450 - 2524 + "mn-mong" + // 07c50 - 2529 + "mn-mong-cn" + // 00850 - 2536 + "mn-mong-mn" + // 00c50 - 2546 + "mni" + // 00058 - 2556 + "mni-in" + // 00458 - 2559 + "moh" + // 0007c - 2565 + "moh-ca" + // 0047c - 2568 + "mr" + // 0004e - 2574 + "mr-in" + // 0044e - 2576 + "ms" + // 0003e - 2581 + "ms-bn" + // 0083e - 2583 + "ms-my" + // 0043e - 2588 + "ms-sg" + // 01000 - 2593 + "mt" + // 0003a - 2598 + "mt-mt" + // 0043a - 2600 + "mua" + // 01000 - 2605 + "mua-cm" + // 01000 - 2608 + "my" + // 00055 - 2614 + "my-mm" + // 00455 - 2616 + "mzn" + // 01000 - 2621 + "mzn-ir" + // 01000 - 2624 + "naq" + // 01000 - 2630 + "naq-na" + // 01000 - 2633 + "nb" + // 07c14 - 2639 + "nb-no" + // 00414 - 2641 + "nb-sj" + // 01000 - 2646 + "nd" + // 01000 - 2651 + "nd-zw" + // 01000 - 2653 + "nds" + // 01000 - 2658 + "nds-de" + // 01000 - 2661 + "nds-nl" + // 01000 - 2667 + "ne" + // 00061 - 2673 + "ne-in" + // 00861 - 2675 + "ne-np" + // 00461 - 2680 + "nl" + // 00013 - 2685 + "nl-aw" + // 01000 - 2687 + "nl-be" + // 00813 - 2692 + "nl-bq" + // 01000 - 2697 + "nl-cw" + // 01000 - 2702 + "nl-nl" + // 00413 - 2707 + "nl-sr" + // 01000 - 2712 + "nl-sx" + // 01000 - 2717 + "nmg" + // 01000 - 2722 + "nmg-cm" + // 01000 - 2725 + "nn" + // 07814 - 2731 + "nn-no" + // 00814 - 2733 + "nnh" + // 01000 - 2738 + "nnh-cm" + // 01000 - 2741 + "no" + // 00014 - 2747 + "nqo" + // 01000 - 2749 + "nqo-gn" + // 01000 - 2752 + "nr" + // 01000 - 2758 + "nr-za" + // 01000 - 2760 + "nso" + // 0006c - 2765 + "nso-za" + // 0046c - 2768 + "nus" + // 01000 - 2774 + "nus-ss" + // 01000 - 2777 + "nyn" + // 01000 - 2783 + "nyn-ug" + // 01000 - 2786 + "oc" + // 00082 - 2792 + "oc-fr" + // 00482 - 2794 + "om" + // 00072 - 2799 + "om-et" + // 00472 - 2801 + "om-ke" + // 01000 - 2806 + "or" + // 00048 - 2811 + "or-in" + // 00448 - 2813 + "os" + // 01000 - 2818 + "os-ge" + // 01000 - 2820 + "os-ru" + // 01000 - 2825 + "pa" + // 00046 - 2830 + "pa-arab" + // 07c46 - 2832 + "pa-arab-pk" + // 00846 - 2839 + "pa-in" + // 00446 - 2849 + "pap" + // 00079 - 2854 + "pap-029" + // 00479 - 2857 + "pl" + // 00015 - 2864 + "pl-pl" + // 00415 - 2866 + "prg" + // 01000 - 2871 + "prg-001" + // 01000 - 2874 + "prs" + // 0008c - 2881 + "prs-af" + // 0048c - 2884 + "ps" + // 00063 - 2890 + "ps-af" + // 00463 - 2892 + "pt" + // 00016 - 2897 + "pt-ao" + // 01000 - 2899 + "pt-br" + // 00416 - 2904 + "pt-ch" + // 01000 - 2909 + "pt-cv" + // 01000 - 2914 + "pt-gq" + // 01000 - 2919 + "pt-gw" + // 01000 - 2924 + "pt-lu" + // 01000 - 2929 + "pt-mo" + // 01000 - 2934 + "pt-mz" + // 01000 - 2939 + "pt-pt" + // 00816 - 2944 + "pt-st" + // 01000 - 2949 + "pt-tl" + // 01000 - 2954 + "qps-latn-x-sh" + // 00901 - 2959 + "qps-ploc" + // 00501 - 2972 + "qps-ploca" + // 005fe - 2980 + "qps-plocm" + // 009ff - 2989 + "quc" + // 00086 - 2998 + "quc-latn" + // 07c86 - 3001 + "quc-latn-gt" + // 00486 - 3009 + "quz" + // 0006b - 3020 + "quz-bo" + // 0046b - 3023 + "quz-ec" + // 0086b - 3029 + "quz-pe" + // 00c6b - 3035 + "rm" + // 00017 - 3041 + "rm-ch" + // 00417 - 3043 + "rn" + // 01000 - 3048 + "rn-bi" + // 01000 - 3050 + "ro" + // 00018 - 3055 + "ro-md" + // 00818 - 3057 + "ro-ro" + // 00418 - 3062 + "rof" + // 01000 - 3067 + "rof-tz" + // 01000 - 3070 + "ru" + // 00019 - 3076 + "ru-by" + // 01000 - 3078 + "ru-kg" + // 01000 - 3083 + "ru-kz" + // 01000 - 3088 + "ru-md" + // 00819 - 3093 + "ru-ru" + // 00419 - 3098 + "ru-ua" + // 01000 - 3103 + "rw" + // 00087 - 3108 + "rw-rw" + // 00487 - 3110 + "rwk" + // 01000 - 3115 + "rwk-tz" + // 01000 - 3118 + "sa" + // 0004f - 3124 + "sa-in" + // 0044f - 3126 + "sah" + // 00085 - 3131 + "sah-ru" + // 00485 - 3134 + "saq" + // 01000 - 3140 + "saq-ke" + // 01000 - 3143 + "sbp" + // 01000 - 3149 + "sbp-tz" + // 01000 - 3152 + "sd" + // 00059 - 3158 + "sd-arab" + // 07c59 - 3160 + "sd-arab-pk" + // 00859 - 3167 + "sd-deva" + // 01000 - 3177 + "sd-deva-in" + // 00459 - 3184 + "se" + // 0003b - 3194 + "se-fi" + // 00c3b - 3196 + "se-no" + // 0043b - 3201 + "se-se" + // 0083b - 3206 + "seh" + // 01000 - 3211 + "seh-mz" + // 01000 - 3214 + "ses" + // 01000 - 3220 + "ses-ml" + // 01000 - 3223 + "sg" + // 01000 - 3229 + "sg-cf" + // 01000 - 3231 + "shi" + // 01000 - 3236 + "shi-latn" + // 01000 - 3239 + "shi-latn-ma" + // 01000 - 3247 + "shi-tfng" + // 01000 - 3258 + "shi-tfng-ma" + // 01000 - 3266 + "si" + // 0005b - 3277 + "si-lk" + // 0045b - 3279 + "sk" + // 0001b - 3284 + "sk-sk" + // 0041b - 3286 + "sl" + // 00024 - 3291 + "sl-si" + // 00424 - 3293 + "sma" + // 0783b - 3298 + "sma-no" + // 0183b - 3301 + "sma-se" + // 01c3b - 3307 + "smj" + // 07c3b - 3313 + "smj-no" + // 0103b - 3316 + "smj-se" + // 0143b - 3322 + "smn" + // 0703b - 3328 + "smn-fi" + // 0243b - 3331 + "sms" + // 0743b - 3337 + "sms-fi" + // 0203b - 3340 + "sn" + // 01000 - 3346 + "sn-latn" + // 01000 - 3348 + "sn-latn-zw" + // 01000 - 3355 + "so" + // 00077 - 3365 + "so-dj" + // 01000 - 3367 + "so-et" + // 01000 - 3372 + "so-ke" + // 01000 - 3377 + "so-so" + // 00477 - 3382 + "sq" + // 0001c - 3387 + "sq-al" + // 0041c - 3389 + "sq-mk" + // 01000 - 3394 + "sq-xk" + // 01000 - 3399 + "sr" + // 07c1a - 3404 + "sr-cyrl" + // 06c1a - 3406 + "sr-cyrl-ba" + // 01c1a - 3413 + "sr-cyrl-cs" + // 00c1a - 3423 + "sr-cyrl-me" + // 0301a - 3433 + "sr-cyrl-rs" + // 0281a - 3443 + "sr-cyrl-xk" + // 01000 - 3453 + "sr-latn" + // 0701a - 3463 + "sr-latn-ba" + // 0181a - 3470 + "sr-latn-cs" + // 0081a - 3480 + "sr-latn-me" + // 02c1a - 3490 + "sr-latn-rs" + // 0241a - 3500 + "sr-latn-xk" + // 01000 - 3510 + "ss" + // 01000 - 3520 + "ss-sz" + // 01000 - 3522 + "ss-za" + // 01000 - 3527 + "ssy" + // 01000 - 3532 + "ssy-er" + // 01000 - 3535 + "st" + // 00030 - 3541 + "st-ls" + // 01000 - 3543 + "st-za" + // 00430 - 3548 + "sv" + // 0001d - 3553 + "sv-ax" + // 01000 - 3555 + "sv-fi" + // 0081d - 3560 + "sv-se" + // 0041d - 3565 + "sw" + // 00041 - 3570 + "sw-cd" + // 01000 - 3572 + "sw-ke" + // 00441 - 3577 + "sw-tz" + // 01000 - 3582 + "sw-ug" + // 01000 - 3587 + "swc" + // 01000 - 3592 + "swc-cd" + // 01000 - 3595 + "syr" + // 0005a - 3601 + "syr-sy" + // 0045a - 3604 + "ta" + // 00049 - 3610 + "ta-in" + // 00449 - 3612 + "ta-lk" + // 00849 - 3617 + "ta-my" + // 01000 - 3622 + "ta-sg" + // 01000 - 3627 + "te" + // 0004a - 3632 + "te-in" + // 0044a - 3634 + "teo" + // 01000 - 3639 + "teo-ke" + // 01000 - 3642 + "teo-ug" + // 01000 - 3648 + "tg" + // 00028 - 3654 + "tg-cyrl" + // 07c28 - 3656 + "tg-cyrl-tj" + // 00428 - 3663 + "th" + // 0001e - 3673 + "th-th" + // 0041e - 3675 + "ti" + // 00073 - 3680 + "ti-er" + // 00873 - 3682 + "ti-et" + // 00473 - 3687 + "tig" + // 01000 - 3692 + "tig-er" + // 01000 - 3695 + "tk" + // 00042 - 3701 + "tk-tm" + // 00442 - 3703 + "tn" + // 00032 - 3708 + "tn-bw" + // 00832 - 3710 + "tn-za" + // 00432 - 3715 + "to" + // 01000 - 3720 + "to-to" + // 01000 - 3722 + "tr" + // 0001f - 3727 + "tr-cy" + // 01000 - 3729 + "tr-tr" + // 0041f - 3734 + "ts" + // 00031 - 3739 + "ts-za" + // 00431 - 3741 + "tt" + // 00044 - 3746 + "tt-ru" + // 00444 - 3748 + "twq" + // 01000 - 3753 + "twq-ne" + // 01000 - 3756 + "tzm" + // 0005f - 3762 + "tzm-arab" + // 01000 - 3765 + "tzm-arab-ma" + // 0045f - 3773 + "tzm-latn" + // 07c5f - 3784 + "tzm-latn-dz" + // 0085f - 3792 + "tzm-latn-ma" + // 01000 - 3803 + "tzm-tfng" + // 0785f - 3814 + "tzm-tfng-ma" + // 0105f - 3822 + "ug" + // 00080 - 3833 + "ug-cn" + // 00480 - 3835 + "uk" + // 00022 - 3840 + "uk-ua" + // 00422 - 3842 + "ur" + // 00020 - 3847 + "ur-in" + // 00820 - 3849 + "ur-pk" + // 00420 - 3854 + "uz" + // 00043 - 3859 + "uz-arab" + // 01000 - 3861 + "uz-arab-af" + // 01000 - 3868 + "uz-cyrl" + // 07843 - 3878 + "uz-cyrl-uz" + // 00843 - 3885 + "uz-latn" + // 07c43 - 3895 + "uz-latn-uz" + // 00443 - 3902 + "vai" + // 01000 - 3912 + "vai-latn" + // 01000 - 3915 + "vai-latn-lr" + // 01000 - 3923 + "vai-vaii" + // 01000 - 3934 + "vai-vaii-lr" + // 01000 - 3942 + "ve" + // 00033 - 3953 + "ve-za" + // 00433 - 3955 + "vi" + // 0002a - 3960 + "vi-vn" + // 0042a - 3962 + "vo" + // 01000 - 3967 + "vo-001" + // 01000 - 3969 + "vun" + // 01000 - 3975 + "vun-tz" + // 01000 - 3978 + "wae" + // 01000 - 3984 + "wae-ch" + // 01000 - 3987 + "wal" + // 01000 - 3993 + "wal-et" + // 01000 - 3996 + "wo" + // 00088 - 4002 + "wo-sn" + // 00488 - 4004 + "x-iv_mathan" + // 1007f - 4009 + "xh" + // 00034 - 4020 + "xh-za" + // 00434 - 4022 + "xog" + // 01000 - 4027 + "xog-ug" + // 01000 - 4030 + "yav" + // 01000 - 4036 + "yav-cm" + // 01000 - 4039 + "yi" + // 0003d - 4045 + "yi-001" + // 0043d - 4047 + "yo" + // 0006a - 4053 + "yo-bj" + // 01000 - 4055 + "yo-ng" + // 0046a - 4060 + "yue" + // 01000 - 4065 + "yue-hk" + // 01000 - 4068 + "zgh" + // 01000 - 4074 + "zgh-tfng" + // 01000 - 4077 + "zgh-tfng-ma" + // 01000 - 4085 + "zh" + // 07804 - 4096 + "zh-chs" + // 00004 - 4098 + "zh-cht" + // 07c04 - 4104 + "zh-cn" + // 00804 - 4110 + "zh-cn_phoneb" + // 50804 - 4115 + "zh-cn_stroke" + // 20804 - 4127 + "zh-hans" + // 00004 - 4139 + "zh-hans-hk" + // 01000 - 4146 + "zh-hans-mo" + // 01000 - 4156 + "zh-hant" + // 07c04 - 4166 + "zh-hk" + // 00c04 - 4173 + "zh-hk_radstr" + // 40c04 - 4178 + "zh-mo" + // 01404 - 4190 + "zh-mo_radstr" + // 41404 - 4195 + "zh-mo_stroke" + // 21404 - 4207 + "zh-sg" + // 01004 - 4219 + "zh-sg_phoneb" + // 51004 - 4224 + "zh-sg_stroke" + // 21004 - 4236 + "zh-tw" + // 00404 - 4248 + "zh-tw_pronun" + // 30404 - 4253 + "zh-tw_radstr" + // 40404 - 4265 + "zu" + // 00035 - 4277 + "zu-za"; // 00435 - 4279 + + // c_threeLetterWindowsLanguageName is string containing 3-letter Windows language names + // every 3-characters entry is matching locale name entry in c_localeNames + + private const string c_threeLetterWindowsLanguageName = + "ZZZ" + // aa + "ZZZ" + // aa-dj + "ZZZ" + // aa-er + "ZZZ" + // aa-et + "AFK" + // af + "ZZZ" + // af-na + "AFK" + // af-za + "ZZZ" + // agq + "ZZZ" + // agq-cm + "ZZZ" + // ak + "ZZZ" + // ak-gh + "AMH" + // am + "AMH" + // am-et + "ARA" + // ar + "ZZZ" + // ar-001 + "ARU" + // ar-ae + "ARH" + // ar-bh + "ZZZ" + // ar-dj + "ARG" + // ar-dz + "ARE" + // ar-eg + "ZZZ" + // ar-er + "ZZZ" + // ar-il + "ARI" + // ar-iq + "ARJ" + // ar-jo + "ZZZ" + // ar-km + "ARK" + // ar-kw + "ARB" + // ar-lb + "ARL" + // ar-ly + "ARM" + // ar-ma + "ZZZ" + // ar-mr + "ARO" + // ar-om + "ZZZ" + // ar-ps + "ARQ" + // ar-qa + "ARA" + // ar-sa + "ZZZ" + // ar-sd + "ZZZ" + // ar-so + "ZZZ" + // ar-ss + "ARS" + // ar-sy + "ZZZ" + // ar-td + "ART" + // ar-tn + "ARY" + // ar-ye + "MPD" + // arn + "MPD" + // arn-cl + "ASM" + // as + "ASM" + // as-in + "ZZZ" + // asa + "ZZZ" + // asa-tz + "ZZZ" + // ast + "ZZZ" + // ast-es + "AZE" + // az + "AZC" + // az-cyrl + "AZC" + // az-cyrl-az + "AZE" + // az-latn + "AZE" + // az-latn-az + "BAS" + // ba + "BAS" + // ba-ru + "ZZZ" + // bas + "ZZZ" + // bas-cm + "BEL" + // be + "BEL" + // be-by + "ZZZ" + // bem + "ZZZ" + // bem-zm + "ZZZ" + // bez + "ZZZ" + // bez-tz + "BGR" + // bg + "BGR" + // bg-bg + "ZZZ" + // bin + "ZZZ" + // bin-ng + "ZZZ" + // bm + "ZZZ" + // bm-latn + "ZZZ" + // bm-latn-ml + "BNB" + // bn + "BNB" + // bn-bd + "BNG" + // bn-in + "BOB" + // bo + "BOB" + // bo-cn + "ZZZ" + // bo-in + "BRE" + // br + "BRE" + // br-fr + "ZZZ" + // brx + "ZZZ" + // brx-in + "BSB" + // bs + "BSC" + // bs-cyrl + "BSC" + // bs-cyrl-ba + "BSB" + // bs-latn + "BSB" + // bs-latn-ba + "ZZZ" + // byn + "ZZZ" + // byn-er + "CAT" + // ca + "ZZZ" + // ca-ad + "CAT" + // ca-es + "VAL" + // ca-es-valencia + "ZZZ" + // ca-fr + "ZZZ" + // ca-it + "ZZZ" + // ce + "ZZZ" + // ce-ru + "ZZZ" + // cgg + "ZZZ" + // cgg-ug + "CRE" + // chr + "CRE" + // chr-cher + "CRE" + // chr-cher-us + "COS" + // co + "COS" + // co-fr + "CSY" + // cs + "CSY" + // cs-cz + "ZZZ" + // cu + "ZZZ" + // cu-ru + "CYM" + // cy + "CYM" + // cy-gb + "DAN" + // da + "DAN" + // da-dk + "ZZZ" + // da-gl + "ZZZ" + // dav + "ZZZ" + // dav-ke + "DEU" + // de + "DEA" + // de-at + "ZZZ" + // de-be + "DES" + // de-ch + "DEU" + // de-de + "DEU" + // de-de_phoneb + "ZZZ" + // de-it + "DEC" + // de-li + "DEL" + // de-lu + "ZZZ" + // dje + "ZZZ" + // dje-ne + "DSB" + // dsb + "DSB" + // dsb-de + "ZZZ" + // dua + "ZZZ" + // dua-cm + "DIV" + // dv + "DIV" + // dv-mv + "ZZZ" + // dyo + "ZZZ" + // dyo-sn + "ZZZ" + // dz + "ZZZ" + // dz-bt + "ZZZ" + // ebu + "ZZZ" + // ebu-ke + "ZZZ" + // ee + "ZZZ" + // ee-gh + "ZZZ" + // ee-tg + "ELL" + // el + "ZZZ" + // el-cy + "ELL" + // el-gr + "ENU" + // en + "ZZZ" + // en-001 + "ENB" + // en-029 + "ZZZ" + // en-150 + "ZZZ" + // en-ag + "ZZZ" + // en-ai + "ZZZ" + // en-as + "ZZZ" + // en-at + "ENA" + // en-au + "ZZZ" + // en-bb + "ZZZ" + // en-be + "ZZZ" + // en-bi + "ZZZ" + // en-bm + "ZZZ" + // en-bs + "ZZZ" + // en-bw + "ENL" + // en-bz + "ENC" + // en-ca + "ZZZ" + // en-cc + "ZZZ" + // en-ch + "ZZZ" + // en-ck + "ZZZ" + // en-cm + "ZZZ" + // en-cx + "ZZZ" + // en-cy + "ZZZ" + // en-de + "ZZZ" + // en-dk + "ZZZ" + // en-dm + "ZZZ" + // en-er + "ZZZ" + // en-fi + "ZZZ" + // en-fj + "ZZZ" + // en-fk + "ZZZ" + // en-fm + "ENG" + // en-gb + "ZZZ" + // en-gd + "ZZZ" + // en-gg + "ZZZ" + // en-gh + "ZZZ" + // en-gi + "ZZZ" + // en-gm + "ZZZ" + // en-gu + "ZZZ" + // en-gy + "ENH" + // en-hk + "ZZZ" + // en-id + "ENI" + // en-ie + "ZZZ" + // en-il + "ZZZ" + // en-im + "ENN" + // en-in + "ZZZ" + // en-io + "ZZZ" + // en-je + "ENJ" + // en-jm + "ZZZ" + // en-ke + "ZZZ" + // en-ki + "ZZZ" + // en-kn + "ZZZ" + // en-ky + "ZZZ" + // en-lc + "ZZZ" + // en-lr + "ZZZ" + // en-ls + "ZZZ" + // en-mg + "ZZZ" + // en-mh + "ZZZ" + // en-mo + "ZZZ" + // en-mp + "ZZZ" + // en-ms + "ZZZ" + // en-mt + "ZZZ" + // en-mu + "ZZZ" + // en-mw + "ENM" + // en-my + "ZZZ" + // en-na + "ZZZ" + // en-nf + "ZZZ" + // en-ng + "ZZZ" + // en-nl + "ZZZ" + // en-nr + "ZZZ" + // en-nu + "ENZ" + // en-nz + "ZZZ" + // en-pg + "ENP" + // en-ph + "ZZZ" + // en-pk + "ZZZ" + // en-pn + "ZZZ" + // en-pr + "ZZZ" + // en-pw + "ZZZ" + // en-rw + "ZZZ" + // en-sb + "ZZZ" + // en-sc + "ZZZ" + // en-sd + "ZZZ" + // en-se + "ENE" + // en-sg + "ZZZ" + // en-sh + "ZZZ" + // en-si + "ZZZ" + // en-sl + "ZZZ" + // en-ss + "ZZZ" + // en-sx + "ZZZ" + // en-sz + "ZZZ" + // en-tc + "ZZZ" + // en-tk + "ZZZ" + // en-to + "ENT" + // en-tt + "ZZZ" + // en-tv + "ZZZ" + // en-tz + "ZZZ" + // en-ug + "ZZZ" + // en-um + "ENU" + // en-us + "ZZZ" + // en-vc + "ZZZ" + // en-vg + "ZZZ" + // en-vi + "ZZZ" + // en-vu + "ZZZ" + // en-ws + "ENS" + // en-za + "ZZZ" + // en-zm + "ENW" + // en-zw + "ZZZ" + // eo + "ZZZ" + // eo-001 + "ESN" + // es + "ESJ" + // es-419 + "ESS" + // es-ar + "ESB" + // es-bo + "ZZZ" + // es-br + "ESL" + // es-cl + "ESO" + // es-co + "ESC" + // es-cr + "ESK" + // es-cu + "ESD" + // es-do + "ESF" + // es-ec + "ESN" + // es-es + "ESP" + // es-es_tradnl + "ZZZ" + // es-gq + "ESG" + // es-gt + "ESH" + // es-hn + "ESM" + // es-mx + "ESI" + // es-ni + "ESA" + // es-pa + "ESR" + // es-pe + "ZZZ" + // es-ph + "ESU" + // es-pr + "ESZ" + // es-py + "ESE" + // es-sv + "EST" + // es-us + "ESY" + // es-uy + "ESV" + // es-ve + "ETI" + // et + "ETI" + // et-ee + "EUQ" + // eu + "EUQ" + // eu-es + "ZZZ" + // ewo + "ZZZ" + // ewo-cm + "FAR" + // fa + "FAR" + // fa-ir + "FUL" + // ff + "ZZZ" + // ff-cm + "ZZZ" + // ff-gn + "FUL" + // ff-latn + "FUL" + // ff-latn-sn + "ZZZ" + // ff-mr + "ZZZ" + // ff-ng + "FIN" + // fi + "FIN" + // fi-fi + "FPO" + // fil + "FPO" + // fil-ph + "FOS" + // fo + "ZZZ" + // fo-dk + "FOS" + // fo-fo + "FRA" + // fr + "ZZZ" + // fr-029 + "FRB" + // fr-be + "ZZZ" + // fr-bf + "ZZZ" + // fr-bi + "ZZZ" + // fr-bj + "ZZZ" + // fr-bl + "FRC" + // fr-ca + "FRD" + // fr-cd + "ZZZ" + // fr-cf + "ZZZ" + // fr-cg + "FRS" + // fr-ch + "FRI" + // fr-ci + "FRE" + // fr-cm + "ZZZ" + // fr-dj + "ZZZ" + // fr-dz + "FRA" + // fr-fr + "ZZZ" + // fr-ga + "ZZZ" + // fr-gf + "ZZZ" + // fr-gn + "ZZZ" + // fr-gp + "ZZZ" + // fr-gq + "FRH" + // fr-ht + "ZZZ" + // fr-km + "FRL" + // fr-lu + "FRO" + // fr-ma + "FRM" + // fr-mc + "ZZZ" + // fr-mf + "ZZZ" + // fr-mg + "FRF" + // fr-ml + "ZZZ" + // fr-mq + "ZZZ" + // fr-mr + "ZZZ" + // fr-mu + "ZZZ" + // fr-nc + "ZZZ" + // fr-ne + "ZZZ" + // fr-pf + "ZZZ" + // fr-pm + "FRR" + // fr-re + "ZZZ" + // fr-rw + "ZZZ" + // fr-sc + "FRN" + // fr-sn + "ZZZ" + // fr-sy + "ZZZ" + // fr-td + "ZZZ" + // fr-tg + "ZZZ" + // fr-tn + "ZZZ" + // fr-vu + "ZZZ" + // fr-wf + "ZZZ" + // fr-yt + "ZZZ" + // fur + "ZZZ" + // fur-it + "FYN" + // fy + "FYN" + // fy-nl + "IRE" + // ga + "IRE" + // ga-ie + "GLA" + // gd + "GLA" + // gd-gb + "GLC" + // gl + "GLC" + // gl-es + "GRN" + // gn + "GRN" + // gn-py + "ZZZ" + // gsw + "ZZZ" + // gsw-ch + "GSW" + // gsw-fr + "ZZZ" + // gsw-li + "GUJ" + // gu + "GUJ" + // gu-in + "ZZZ" + // guz + "ZZZ" + // guz-ke + "ZZZ" + // gv + "ZZZ" + // gv-im + "HAU" + // ha + "HAU" + // ha-latn + "ZZZ" + // ha-latn-gh + "ZZZ" + // ha-latn-ne + "HAU" + // ha-latn-ng + "HAW" + // haw + "HAW" + // haw-us + "HEB" + // he + "HEB" + // he-il + "HIN" + // hi + "HIN" + // hi-in + "HRV" + // hr + "HRB" + // hr-ba + "HRV" + // hr-hr + "HSB" + // hsb + "HSB" + // hsb-de + "HUN" + // hu + "HUN" + // hu-hu + "HUN" + // hu-hu_technl + "HYE" + // hy + "HYE" + // hy-am + "ZZZ" + // ia + "ZZZ" + // ia-001 + "ZZZ" + // ia-fr + "ZZZ" + // ibb + "ZZZ" + // ibb-ng + "IND" + // id + "IND" + // id-id + "IBO" + // ig + "IBO" + // ig-ng + "III" + // ii + "III" + // ii-cn + "ISL" + // is + "ISL" + // is-is + "ITA" + // it + "ITS" + // it-ch + "ITA" + // it-it + "ZZZ" + // it-sm + "IUK" + // iu + "IUS" + // iu-cans + "IUS" + // iu-cans-ca + "IUK" + // iu-latn + "IUK" + // iu-latn-ca + "JPN" + // ja + "JPN" + // ja-jp + "JPN" + // ja-jp_radstr + "ZZZ" + // jgo + "ZZZ" + // jgo-cm + "ZZZ" + // jmc + "ZZZ" + // jmc-tz + "JAV" + // jv + "ZZZ" + // jv-java + "ZZZ" + // jv-java-id + "JAV" + // jv-latn + "JAV" + // jv-latn-id + "KAT" + // ka + "KAT" + // ka-ge + "KAT" + // ka-ge_modern + "ZZZ" + // kab + "ZZZ" + // kab-dz + "ZZZ" + // kam + "ZZZ" + // kam-ke + "ZZZ" + // kde + "ZZZ" + // kde-tz + "ZZZ" + // kea + "ZZZ" + // kea-cv + "ZZZ" + // khq + "ZZZ" + // khq-ml + "ZZZ" + // ki + "ZZZ" + // ki-ke + "KKZ" + // kk + "KKZ" + // kk-kz + "ZZZ" + // kkj + "ZZZ" + // kkj-cm + "KAL" + // kl + "KAL" + // kl-gl + "ZZZ" + // kln + "ZZZ" + // kln-ke + "KHM" + // km + "KHM" + // km-kh + "KDI" + // kn + "KDI" + // kn-in + "KOR" + // ko + "ZZZ" + // ko-kp + "KOR" + // ko-kr + "KNK" + // kok + "KNK" + // kok-in + "ZZZ" + // kr + "ZZZ" + // kr-ng + "ZZZ" + // ks + "ZZZ" + // ks-arab + "ZZZ" + // ks-arab-in + "ZZZ" + // ks-deva + "ZZZ" + // ks-deva-in + "ZZZ" + // ksb + "ZZZ" + // ksb-tz + "ZZZ" + // ksf + "ZZZ" + // ksf-cm + "ZZZ" + // ksh + "ZZZ" + // ksh-de + "KUR" + // ku + "KUR" + // ku-arab + "KUR" + // ku-arab-iq + "ZZZ" + // ku-arab-ir + "ZZZ" + // kw + "ZZZ" + // kw-gb + "KYR" + // ky + "KYR" + // ky-kg + "ZZZ" + // la + "ZZZ" + // la-001 + "ZZZ" + // lag + "ZZZ" + // lag-tz + "LBX" + // lb + "LBX" + // lb-lu + "ZZZ" + // lg + "ZZZ" + // lg-ug + "ZZZ" + // lkt + "ZZZ" + // lkt-us + "ZZZ" + // ln + "ZZZ" + // ln-ao + "ZZZ" + // ln-cd + "ZZZ" + // ln-cf + "ZZZ" + // ln-cg + "LAO" + // lo + "LAO" + // lo-la + "ZZZ" + // lrc + "ZZZ" + // lrc-iq + "ZZZ" + // lrc-ir + "LTH" + // lt + "LTH" + // lt-lt + "ZZZ" + // lu + "ZZZ" + // lu-cd + "ZZZ" + // luo + "ZZZ" + // luo-ke + "ZZZ" + // luy + "ZZZ" + // luy-ke + "LVI" + // lv + "LVI" + // lv-lv + "ZZZ" + // mas + "ZZZ" + // mas-ke + "ZZZ" + // mas-tz + "ZZZ" + // mer + "ZZZ" + // mer-ke + "ZZZ" + // mfe + "ZZZ" + // mfe-mu + "MLG" + // mg + "MLG" + // mg-mg + "ZZZ" + // mgh + "ZZZ" + // mgh-mz + "ZZZ" + // mgo + "ZZZ" + // mgo-cm + "MRI" + // mi + "MRI" + // mi-nz + "MKI" + // mk + "MKI" + // mk-mk + "MYM" + // ml + "MYM" + // ml-in + "MNN" + // mn + "MNN" + // mn-cyrl + "MNN" + // mn-mn + "MNG" + // mn-mong + "MNG" + // mn-mong-cn + "MNM" + // mn-mong-mn + "ZZZ" + // mni + "ZZZ" + // mni-in + "MWK" + // moh + "MWK" + // moh-ca + "MAR" + // mr + "MAR" + // mr-in + "MSL" + // ms + "MSB" + // ms-bn + "MSL" + // ms-my + "ZZZ" + // ms-sg + "MLT" + // mt + "MLT" + // mt-mt + "ZZZ" + // mua + "ZZZ" + // mua-cm + "MYA" + // my + "MYA" + // my-mm + "ZZZ" + // mzn + "ZZZ" + // mzn-ir + "ZZZ" + // naq + "ZZZ" + // naq-na + "NOR" + // nb + "NOR" + // nb-no + "ZZZ" + // nb-sj + "ZZZ" + // nd + "ZZZ" + // nd-zw + "ZZZ" + // nds + "ZZZ" + // nds-de + "ZZZ" + // nds-nl + "NEP" + // ne + "NEI" + // ne-in + "NEP" + // ne-np + "NLD" + // nl + "ZZZ" + // nl-aw + "NLB" + // nl-be + "ZZZ" + // nl-bq + "ZZZ" + // nl-cw + "NLD" + // nl-nl + "ZZZ" + // nl-sr + "ZZZ" + // nl-sx + "ZZZ" + // nmg + "ZZZ" + // nmg-cm + "NON" + // nn + "NON" + // nn-no + "ZZZ" + // nnh + "ZZZ" + // nnh-cm + "NOR" + // no + "NQO" + // nqo + "NQO" + // nqo-gn + "ZZZ" + // nr + "ZZZ" + // nr-za + "NSO" + // nso + "NSO" + // nso-za + "ZZZ" + // nus + "ZZZ" + // nus-ss + "ZZZ" + // nyn + "ZZZ" + // nyn-ug + "OCI" + // oc + "OCI" + // oc-fr + "ORM" + // om + "ORM" + // om-et + "ZZZ" + // om-ke + "ORI" + // or + "ORI" + // or-in + "ZZZ" + // os + "ZZZ" + // os-ge + "ZZZ" + // os-ru + "PAN" + // pa + "PAP" + // pa-arab + "PAP" + // pa-arab-pk + "PAN" + // pa-in + "ZZZ" + // pap + "ZZZ" + // pap-029 + "PLK" + // pl + "PLK" + // pl-pl + "ZZZ" + // prg + "ZZZ" + // prg-001 + "PRS" + // prs + "PRS" + // prs-af + "PAS" + // ps + "PAS" + // ps-af + "PTB" + // pt + "PTA" + // pt-ao + "PTB" + // pt-br + "ZZZ" + // pt-ch + "ZZZ" + // pt-cv + "ZZZ" + // pt-gq + "ZZZ" + // pt-gw + "ZZZ" + // pt-lu + "ZZZ" + // pt-mo + "ZZZ" + // pt-mz + "PTG" + // pt-pt + "ZZZ" + // pt-st + "ZZZ" + // pt-tl + "ENJ" + // qps-latn-x-sh + "ENU" + // qps-ploc + "JPN" + // qps-ploca + "ARA" + // qps-plocm + "QUT" + // quc + "QUT" + // quc-latn + "QUT" + // quc-latn-gt + "QUB" + // quz + "QUB" + // quz-bo + "QUE" + // quz-ec + "QUP" + // quz-pe + "RMC" + // rm + "RMC" + // rm-ch + "ZZZ" + // rn + "ZZZ" + // rn-bi + "ROM" + // ro + "ROD" + // ro-md + "ROM" + // ro-ro + "ZZZ" + // rof + "ZZZ" + // rof-tz + "RUS" + // ru + "ZZZ" + // ru-by + "ZZZ" + // ru-kg + "ZZZ" + // ru-kz + "RUM" + // ru-md + "RUS" + // ru-ru + "ZZZ" + // ru-ua + "KIN" + // rw + "KIN" + // rw-rw + "ZZZ" + // rwk + "ZZZ" + // rwk-tz + "SAN" + // sa + "SAN" + // sa-in + "SAH" + // sah + "SAH" + // sah-ru + "ZZZ" + // saq + "ZZZ" + // saq-ke + "ZZZ" + // sbp + "ZZZ" + // sbp-tz + "SIP" + // sd + "SIP" + // sd-arab + "SIP" + // sd-arab-pk + "ZZZ" + // sd-deva + "ZZZ" + // sd-deva-in + "SME" + // se + "SMG" + // se-fi + "SME" + // se-no + "SMF" + // se-se + "ZZZ" + // seh + "ZZZ" + // seh-mz + "ZZZ" + // ses + "ZZZ" + // ses-ml + "ZZZ" + // sg + "ZZZ" + // sg-cf + "ZZZ" + // shi + "ZZZ" + // shi-latn + "ZZZ" + // shi-latn-ma + "ZZZ" + // shi-tfng + "ZZZ" + // shi-tfng-ma + "SIN" + // si + "SIN" + // si-lk + "SKY" + // sk + "SKY" + // sk-sk + "SLV" + // sl + "SLV" + // sl-si + "SMB" + // sma + "SMA" + // sma-no + "SMB" + // sma-se + "SMK" + // smj + "SMJ" + // smj-no + "SMK" + // smj-se + "SMN" + // smn + "SMN" + // smn-fi + "SMS" + // sms + "SMS" + // sms-fi + "SNA" + // sn + "SNA" + // sn-latn + "SNA" + // sn-latn-zw + "SOM" + // so + "ZZZ" + // so-dj + "ZZZ" + // so-et + "ZZZ" + // so-ke + "SOM" + // so-so + "SQI" + // sq + "SQI" + // sq-al + "ZZZ" + // sq-mk + "ZZZ" + // sq-xk + "SRM" + // sr + "SRO" + // sr-cyrl + "SRN" + // sr-cyrl-ba + "SRB" + // sr-cyrl-cs + "SRQ" + // sr-cyrl-me + "SRO" + // sr-cyrl-rs + "ZZZ" + // sr-cyrl-xk + "SRM" + // sr-latn + "SRS" + // sr-latn-ba + "SRL" + // sr-latn-cs + "SRP" + // sr-latn-me + "SRM" + // sr-latn-rs + "ZZZ" + // sr-latn-xk + "ZZZ" + // ss + "ZZZ" + // ss-sz + "ZZZ" + // ss-za + "ZZZ" + // ssy + "ZZZ" + // ssy-er + "SOT" + // st + "ZZZ" + // st-ls + "SOT" + // st-za + "SVE" + // sv + "ZZZ" + // sv-ax + "SVF" + // sv-fi + "SVE" + // sv-se + "SWK" + // sw + "ZZZ" + // sw-cd + "SWK" + // sw-ke + "ZZZ" + // sw-tz + "ZZZ" + // sw-ug + "ZZZ" + // swc + "ZZZ" + // swc-cd + "SYR" + // syr + "SYR" + // syr-sy + "TAI" + // ta + "TAI" + // ta-in + "TAM" + // ta-lk + "ZZZ" + // ta-my + "ZZZ" + // ta-sg + "TEL" + // te + "TEL" + // te-in + "ZZZ" + // teo + "ZZZ" + // teo-ke + "ZZZ" + // teo-ug + "TAJ" + // tg + "TAJ" + // tg-cyrl + "TAJ" + // tg-cyrl-tj + "THA" + // th + "THA" + // th-th + "TIR" + // ti + "TIR" + // ti-er + "TIE" + // ti-et + "ZZZ" + // tig + "ZZZ" + // tig-er + "TUK" + // tk + "TUK" + // tk-tm + "TSN" + // tn + "TSB" + // tn-bw + "TSN" + // tn-za + "ZZZ" + // to + "ZZZ" + // to-to + "TRK" + // tr + "ZZZ" + // tr-cy + "TRK" + // tr-tr + "TSO" + // ts + "TSO" + // ts-za + "TTT" + // tt + "TTT" + // tt-ru + "ZZZ" + // twq + "ZZZ" + // twq-ne + "TZA" + // tzm + "ZZZ" + // tzm-arab + "ZZZ" + // tzm-arab-ma + "TZA" + // tzm-latn + "TZA" + // tzm-latn-dz + "ZZZ" + // tzm-latn-ma + "TZM" + // tzm-tfng + "TZM" + // tzm-tfng-ma + "UIG" + // ug + "UIG" + // ug-cn + "UKR" + // uk + "UKR" + // uk-ua + "URD" + // ur + "URI" + // ur-in + "URD" + // ur-pk + "UZB" + // uz + "ZZZ" + // uz-arab + "ZZZ" + // uz-arab-af + "UZC" + // uz-cyrl + "UZC" + // uz-cyrl-uz + "UZB" + // uz-latn + "UZB" + // uz-latn-uz + "ZZZ" + // vai + "ZZZ" + // vai-latn + "ZZZ" + // vai-latn-lr + "ZZZ" + // vai-vaii + "ZZZ" + // vai-vaii-lr + "ZZZ" + // ve + "ZZZ" + // ve-za + "VIT" + // vi + "VIT" + // vi-vn + "ZZZ" + // vo + "ZZZ" + // vo-001 + "ZZZ" + // vun + "ZZZ" + // vun-tz + "ZZZ" + // wae + "ZZZ" + // wae-ch + "ZZZ" + // wal + "ZZZ" + // wal-et + "WOL" + // wo + "WOL" + // wo-sn + "IVL" + // x-iv_mathan + "XHO" + // xh + "XHO" + // xh-za + "ZZZ" + // xog + "ZZZ" + // xog-ug + "ZZZ" + // yav + "ZZZ" + // yav-cm + "ZZZ" + // yi + "ZZZ" + // yi-001 + "YOR" + // yo + "ZZZ" + // yo-bj + "YOR" + // yo-ng + "ZZZ" + // yue + "ZZZ" + // yue-hk + "ZHG" + // zgh + "ZHG" + // zgh-tfng + "ZHG" + // zgh-tfng-ma + "CHS" + // zh + "CHS" + // zh-chs + "CHT" + // zh-cht + "CHS" + // zh-cn + "CHS" + // zh-cn_phoneb + "CHS" + // zh-cn_stroke + "CHS" + // zh-hans + "ZZZ" + // zh-hans-hk + "ZZZ" + // zh-hans-mo + "ZHH" + // zh-hant + "ZHH" + // zh-hk + "ZHH" + // zh-hk_radstr + "ZHM" + // zh-mo + "ZHM" + // zh-mo_radstr + "ZHM" + // zh-mo_stroke + "ZHI" + // zh-sg + "ZHI" + // zh-sg_phoneb + "ZHI" + // zh-sg_stroke + "CHT" + // zh-tw + "CHT" + // zh-tw_pronun + "CHT" + // zh-tw_radstr + "ZUL" + // zu + "ZUL"; // zu-za + + // s_localeNamesIndices contains the start index of every culture name in the string + // s_localeNames. We infer the length of each string by looking at the start index + // of the next string. + private static readonly int[] s_localeNamesIndices = new int[] + { + // c_localeNames index, // index to this array - culture name + 0 , // 0 - aa + 2 , // 1 - aa-dj + 7 , // 2 - aa-er + 12 , // 3 - aa-et + 17 , // 4 - af + 19 , // 5 - af-na + 24 , // 6 - af-za + 29 , // 7 - agq + 32 , // 8 - agq-cm + 38 , // 9 - ak + 40 , // 10 - ak-gh + 45 , // 11 - am + 47 , // 12 - am-et + 52 , // 13 - ar + 54 , // 14 - ar-001 + 60 , // 15 - ar-ae + 65 , // 16 - ar-bh + 70 , // 17 - ar-dj + 75 , // 18 - ar-dz + 80 , // 19 - ar-eg + 85 , // 20 - ar-er + 90 , // 21 - ar-il + 95 , // 22 - ar-iq + 100 , // 23 - ar-jo + 105 , // 24 - ar-km + 110 , // 25 - ar-kw + 115 , // 26 - ar-lb + 120 , // 27 - ar-ly + 125 , // 28 - ar-ma + 130 , // 29 - ar-mr + 135 , // 30 - ar-om + 140 , // 31 - ar-ps + 145 , // 32 - ar-qa + 150 , // 33 - ar-sa + 155 , // 34 - ar-sd + 160 , // 35 - ar-so + 165 , // 36 - ar-ss + 170 , // 37 - ar-sy + 175 , // 38 - ar-td + 180 , // 39 - ar-tn + 185 , // 40 - ar-ye + 190 , // 41 - arn + 193 , // 42 - arn-cl + 199 , // 43 - as + 201 , // 44 - as-in + 206 , // 45 - asa + 209 , // 46 - asa-tz + 215 , // 47 - ast + 218 , // 48 - ast-es + 224 , // 49 - az + 226 , // 50 - az-cyrl + 233 , // 51 - az-cyrl-az + 243 , // 52 - az-latn + 250 , // 53 - az-latn-az + 260 , // 54 - ba + 262 , // 55 - ba-ru + 267 , // 56 - bas + 270 , // 57 - bas-cm + 276 , // 58 - be + 278 , // 59 - be-by + 283 , // 60 - bem + 286 , // 61 - bem-zm + 292 , // 62 - bez + 295 , // 63 - bez-tz + 301 , // 64 - bg + 303 , // 65 - bg-bg + 308 , // 66 - bin + 311 , // 67 - bin-ng + 317 , // 68 - bm + 319 , // 69 - bm-latn + 326 , // 70 - bm-latn-ml + 336 , // 71 - bn + 338 , // 72 - bn-bd + 343 , // 73 - bn-in + 348 , // 74 - bo + 350 , // 75 - bo-cn + 355 , // 76 - bo-in + 360 , // 77 - br + 362 , // 78 - br-fr + 367 , // 79 - brx + 370 , // 80 - brx-in + 376 , // 81 - bs + 378 , // 82 - bs-cyrl + 385 , // 83 - bs-cyrl-ba + 395 , // 84 - bs-latn + 402 , // 85 - bs-latn-ba + 412 , // 86 - byn + 415 , // 87 - byn-er + 421 , // 88 - ca + 423 , // 89 - ca-ad + 428 , // 90 - ca-es + 433 , // 91 - ca-es-valencia + 447 , // 92 - ca-fr + 452 , // 93 - ca-it + 457 , // 94 - ce + 459 , // 95 - ce-ru + 464 , // 96 - cgg + 467 , // 97 - cgg-ug + 473 , // 98 - chr + 476 , // 99 - chr-cher + 484 , // 100 - chr-cher-us + 495 , // 101 - co + 497 , // 102 - co-fr + 502 , // 103 - cs + 504 , // 104 - cs-cz + 509 , // 105 - cu + 511 , // 106 - cu-ru + 516 , // 107 - cy + 518 , // 108 - cy-gb + 523 , // 109 - da + 525 , // 110 - da-dk + 530 , // 111 - da-gl + 535 , // 112 - dav + 538 , // 113 - dav-ke + 544 , // 114 - de + 546 , // 115 - de-at + 551 , // 116 - de-be + 556 , // 117 - de-ch + 561 , // 118 - de-de + 566 , // 119 - de-de_phoneb + 578 , // 120 - de-it + 583 , // 121 - de-li + 588 , // 122 - de-lu + 593 , // 123 - dje + 596 , // 124 - dje-ne + 602 , // 125 - dsb + 605 , // 126 - dsb-de + 611 , // 127 - dua + 614 , // 128 - dua-cm + 620 , // 129 - dv + 622 , // 130 - dv-mv + 627 , // 131 - dyo + 630 , // 132 - dyo-sn + 636 , // 133 - dz + 638 , // 134 - dz-bt + 643 , // 135 - ebu + 646 , // 136 - ebu-ke + 652 , // 137 - ee + 654 , // 138 - ee-gh + 659 , // 139 - ee-tg + 664 , // 140 - el + 666 , // 141 - el-cy + 671 , // 142 - el-gr + 676 , // 143 - en + 678 , // 144 - en-001 + 684 , // 145 - en-029 + 690 , // 146 - en-150 + 696 , // 147 - en-ag + 701 , // 148 - en-ai + 706 , // 149 - en-as + 711 , // 150 - en-at + 716 , // 151 - en-au + 721 , // 152 - en-bb + 726 , // 153 - en-be + 731 , // 154 - en-bi + 736 , // 155 - en-bm + 741 , // 156 - en-bs + 746 , // 157 - en-bw + 751 , // 158 - en-bz + 756 , // 159 - en-ca + 761 , // 160 - en-cc + 766 , // 161 - en-ch + 771 , // 162 - en-ck + 776 , // 163 - en-cm + 781 , // 164 - en-cx + 786 , // 165 - en-cy + 791 , // 166 - en-de + 796 , // 167 - en-dk + 801 , // 168 - en-dm + 806 , // 169 - en-er + 811 , // 170 - en-fi + 816 , // 171 - en-fj + 821 , // 172 - en-fk + 826 , // 173 - en-fm + 831 , // 174 - en-gb + 836 , // 175 - en-gd + 841 , // 176 - en-gg + 846 , // 177 - en-gh + 851 , // 178 - en-gi + 856 , // 179 - en-gm + 861 , // 180 - en-gu + 866 , // 181 - en-gy + 871 , // 182 - en-hk + 876 , // 183 - en-id + 881 , // 184 - en-ie + 886 , // 185 - en-il + 891 , // 186 - en-im + 896 , // 187 - en-in + 901 , // 188 - en-io + 906 , // 189 - en-je + 911 , // 190 - en-jm + 916 , // 191 - en-ke + 921 , // 192 - en-ki + 926 , // 193 - en-kn + 931 , // 194 - en-ky + 936 , // 195 - en-lc + 941 , // 196 - en-lr + 946 , // 197 - en-ls + 951 , // 198 - en-mg + 956 , // 199 - en-mh + 961 , // 200 - en-mo + 966 , // 201 - en-mp + 971 , // 202 - en-ms + 976 , // 203 - en-mt + 981 , // 204 - en-mu + 986 , // 205 - en-mw + 991 , // 206 - en-my + 996 , // 207 - en-na + 1001, // 208 - en-nf + 1006, // 209 - en-ng + 1011, // 210 - en-nl + 1016, // 211 - en-nr + 1021, // 212 - en-nu + 1026, // 213 - en-nz + 1031, // 214 - en-pg + 1036, // 215 - en-ph + 1041, // 216 - en-pk + 1046, // 217 - en-pn + 1051, // 218 - en-pr + 1056, // 219 - en-pw + 1061, // 220 - en-rw + 1066, // 221 - en-sb + 1071, // 222 - en-sc + 1076, // 223 - en-sd + 1081, // 224 - en-se + 1086, // 225 - en-sg + 1091, // 226 - en-sh + 1096, // 227 - en-si + 1101, // 228 - en-sl + 1106, // 229 - en-ss + 1111, // 230 - en-sx + 1116, // 231 - en-sz + 1121, // 232 - en-tc + 1126, // 233 - en-tk + 1131, // 234 - en-to + 1136, // 235 - en-tt + 1141, // 236 - en-tv + 1146, // 237 - en-tz + 1151, // 238 - en-ug + 1156, // 239 - en-um + 1161, // 240 - en-us + 1166, // 241 - en-vc + 1171, // 242 - en-vg + 1176, // 243 - en-vi + 1181, // 244 - en-vu + 1186, // 245 - en-ws + 1191, // 246 - en-za + 1196, // 247 - en-zm + 1201, // 248 - en-zw + 1206, // 249 - eo + 1208, // 250 - eo-001 + 1214, // 251 - es + 1216, // 252 - es-419 + 1222, // 253 - es-ar + 1227, // 254 - es-bo + 1232, // 255 - es-br + 1237, // 256 - es-cl + 1242, // 257 - es-co + 1247, // 258 - es-cr + 1252, // 259 - es-cu + 1257, // 260 - es-do + 1262, // 261 - es-ec + 1267, // 262 - es-es + 1272, // 263 - es-es_tradnl + 1284, // 264 - es-gq + 1289, // 265 - es-gt + 1294, // 266 - es-hn + 1299, // 267 - es-mx + 1304, // 268 - es-ni + 1309, // 269 - es-pa + 1314, // 270 - es-pe + 1319, // 271 - es-ph + 1324, // 272 - es-pr + 1329, // 273 - es-py + 1334, // 274 - es-sv + 1339, // 275 - es-us + 1344, // 276 - es-uy + 1349, // 277 - es-ve + 1354, // 278 - et + 1356, // 279 - et-ee + 1361, // 280 - eu + 1363, // 281 - eu-es + 1368, // 282 - ewo + 1371, // 283 - ewo-cm + 1377, // 284 - fa + 1379, // 285 - fa-ir + 1384, // 286 - ff + 1386, // 287 - ff-cm + 1391, // 288 - ff-gn + 1396, // 289 - ff-latn + 1403, // 290 - ff-latn-sn + 1413, // 291 - ff-mr + 1418, // 292 - ff-ng + 1423, // 293 - fi + 1425, // 294 - fi-fi + 1430, // 295 - fil + 1433, // 296 - fil-ph + 1439, // 297 - fo + 1441, // 298 - fo-dk + 1446, // 299 - fo-fo + 1451, // 300 - fr + 1453, // 301 - fr-029 + 1459, // 302 - fr-be + 1464, // 303 - fr-bf + 1469, // 304 - fr-bi + 1474, // 305 - fr-bj + 1479, // 306 - fr-bl + 1484, // 307 - fr-ca + 1489, // 308 - fr-cd + 1494, // 309 - fr-cf + 1499, // 310 - fr-cg + 1504, // 311 - fr-ch + 1509, // 312 - fr-ci + 1514, // 313 - fr-cm + 1519, // 314 - fr-dj + 1524, // 315 - fr-dz + 1529, // 316 - fr-fr + 1534, // 317 - fr-ga + 1539, // 318 - fr-gf + 1544, // 319 - fr-gn + 1549, // 320 - fr-gp + 1554, // 321 - fr-gq + 1559, // 322 - fr-ht + 1564, // 323 - fr-km + 1569, // 324 - fr-lu + 1574, // 325 - fr-ma + 1579, // 326 - fr-mc + 1584, // 327 - fr-mf + 1589, // 328 - fr-mg + 1594, // 329 - fr-ml + 1599, // 330 - fr-mq + 1604, // 331 - fr-mr + 1609, // 332 - fr-mu + 1614, // 333 - fr-nc + 1619, // 334 - fr-ne + 1624, // 335 - fr-pf + 1629, // 336 - fr-pm + 1634, // 337 - fr-re + 1639, // 338 - fr-rw + 1644, // 339 - fr-sc + 1649, // 340 - fr-sn + 1654, // 341 - fr-sy + 1659, // 342 - fr-td + 1664, // 343 - fr-tg + 1669, // 344 - fr-tn + 1674, // 345 - fr-vu + 1679, // 346 - fr-wf + 1684, // 347 - fr-yt + 1689, // 348 - fur + 1692, // 349 - fur-it + 1698, // 350 - fy + 1700, // 351 - fy-nl + 1705, // 352 - ga + 1707, // 353 - ga-ie + 1712, // 354 - gd + 1714, // 355 - gd-gb + 1719, // 356 - gl + 1721, // 357 - gl-es + 1726, // 358 - gn + 1728, // 359 - gn-py + 1733, // 360 - gsw + 1736, // 361 - gsw-ch + 1742, // 362 - gsw-fr + 1748, // 363 - gsw-li + 1754, // 364 - gu + 1756, // 365 - gu-in + 1761, // 366 - guz + 1764, // 367 - guz-ke + 1770, // 368 - gv + 1772, // 369 - gv-im + 1777, // 370 - ha + 1779, // 371 - ha-latn + 1786, // 372 - ha-latn-gh + 1796, // 373 - ha-latn-ne + 1806, // 374 - ha-latn-ng + 1816, // 375 - haw + 1819, // 376 - haw-us + 1825, // 377 - he + 1827, // 378 - he-il + 1832, // 379 - hi + 1834, // 380 - hi-in + 1839, // 381 - hr + 1841, // 382 - hr-ba + 1846, // 383 - hr-hr + 1851, // 384 - hsb + 1854, // 385 - hsb-de + 1860, // 386 - hu + 1862, // 387 - hu-hu + 1867, // 388 - hu-hu_technl + 1879, // 389 - hy + 1881, // 390 - hy-am + 1886, // 391 - ia + 1888, // 392 - ia-001 + 1894, // 393 - ia-fr + 1899, // 394 - ibb + 1902, // 395 - ibb-ng + 1908, // 396 - id + 1910, // 397 - id-id + 1915, // 398 - ig + 1917, // 399 - ig-ng + 1922, // 400 - ii + 1924, // 401 - ii-cn + 1929, // 402 - is + 1931, // 403 - is-is + 1936, // 404 - it + 1938, // 405 - it-ch + 1943, // 406 - it-it + 1948, // 407 - it-sm + 1953, // 408 - iu + 1955, // 409 - iu-cans + 1962, // 410 - iu-cans-ca + 1972, // 411 - iu-latn + 1979, // 412 - iu-latn-ca + 1989, // 413 - ja + 1991, // 414 - ja-jp + 1996, // 415 - ja-jp_radstr + 2008, // 416 - jgo + 2011, // 417 - jgo-cm + 2017, // 418 - jmc + 2020, // 419 - jmc-tz + 2026, // 420 - jv + 2028, // 421 - jv-java + 2035, // 422 - jv-java-id + 2045, // 423 - jv-latn + 2052, // 424 - jv-latn-id + 2062, // 425 - ka + 2064, // 426 - ka-ge + 2069, // 427 - ka-ge_modern + 2081, // 428 - kab + 2084, // 429 - kab-dz + 2090, // 430 - kam + 2093, // 431 - kam-ke + 2099, // 432 - kde + 2102, // 433 - kde-tz + 2108, // 434 - kea + 2111, // 435 - kea-cv + 2117, // 436 - khq + 2120, // 437 - khq-ml + 2126, // 438 - ki + 2128, // 439 - ki-ke + 2133, // 440 - kk + 2135, // 441 - kk-kz + 2140, // 442 - kkj + 2143, // 443 - kkj-cm + 2149, // 444 - kl + 2151, // 445 - kl-gl + 2156, // 446 - kln + 2159, // 447 - kln-ke + 2165, // 448 - km + 2167, // 449 - km-kh + 2172, // 450 - kn + 2174, // 451 - kn-in + 2179, // 452 - ko + 2181, // 453 - ko-kp + 2186, // 454 - ko-kr + 2191, // 455 - kok + 2194, // 456 - kok-in + 2200, // 457 - kr + 2202, // 458 - kr-ng + 2207, // 459 - ks + 2209, // 460 - ks-arab + 2216, // 461 - ks-arab-in + 2226, // 462 - ks-deva + 2233, // 463 - ks-deva-in + 2243, // 464 - ksb + 2246, // 465 - ksb-tz + 2252, // 466 - ksf + 2255, // 467 - ksf-cm + 2261, // 468 - ksh + 2264, // 469 - ksh-de + 2270, // 470 - ku + 2272, // 471 - ku-arab + 2279, // 472 - ku-arab-iq + 2289, // 473 - ku-arab-ir + 2299, // 474 - kw + 2301, // 475 - kw-gb + 2306, // 476 - ky + 2308, // 477 - ky-kg + 2313, // 478 - la + 2315, // 479 - la-001 + 2321, // 480 - lag + 2324, // 481 - lag-tz + 2330, // 482 - lb + 2332, // 483 - lb-lu + 2337, // 484 - lg + 2339, // 485 - lg-ug + 2344, // 486 - lkt + 2347, // 487 - lkt-us + 2353, // 488 - ln + 2355, // 489 - ln-ao + 2360, // 490 - ln-cd + 2365, // 491 - ln-cf + 2370, // 492 - ln-cg + 2375, // 493 - lo + 2377, // 494 - lo-la + 2382, // 495 - lrc + 2385, // 496 - lrc-iq + 2391, // 497 - lrc-ir + 2397, // 498 - lt + 2399, // 499 - lt-lt + 2404, // 500 - lu + 2406, // 501 - lu-cd + 2411, // 502 - luo + 2414, // 503 - luo-ke + 2420, // 504 - luy + 2423, // 505 - luy-ke + 2429, // 506 - lv + 2431, // 507 - lv-lv + 2436, // 508 - mas + 2439, // 509 - mas-ke + 2445, // 510 - mas-tz + 2451, // 511 - mer + 2454, // 512 - mer-ke + 2460, // 513 - mfe + 2463, // 514 - mfe-mu + 2469, // 515 - mg + 2471, // 516 - mg-mg + 2476, // 517 - mgh + 2479, // 518 - mgh-mz + 2485, // 519 - mgo + 2488, // 520 - mgo-cm + 2494, // 521 - mi + 2496, // 522 - mi-nz + 2501, // 523 - mk + 2503, // 524 - mk-mk + 2508, // 525 - ml + 2510, // 526 - ml-in + 2515, // 527 - mn + 2517, // 528 - mn-cyrl + 2524, // 529 - mn-mn + 2529, // 530 - mn-mong + 2536, // 531 - mn-mong-cn + 2546, // 532 - mn-mong-mn + 2556, // 533 - mni + 2559, // 534 - mni-in + 2565, // 535 - moh + 2568, // 536 - moh-ca + 2574, // 537 - mr + 2576, // 538 - mr-in + 2581, // 539 - ms + 2583, // 540 - ms-bn + 2588, // 541 - ms-my + 2593, // 542 - ms-sg + 2598, // 543 - mt + 2600, // 544 - mt-mt + 2605, // 545 - mua + 2608, // 546 - mua-cm + 2614, // 547 - my + 2616, // 548 - my-mm + 2621, // 549 - mzn + 2624, // 550 - mzn-ir + 2630, // 551 - naq + 2633, // 552 - naq-na + 2639, // 553 - nb + 2641, // 554 - nb-no + 2646, // 555 - nb-sj + 2651, // 556 - nd + 2653, // 557 - nd-zw + 2658, // 558 - nds + 2661, // 559 - nds-de + 2667, // 560 - nds-nl + 2673, // 561 - ne + 2675, // 562 - ne-in + 2680, // 563 - ne-np + 2685, // 564 - nl + 2687, // 565 - nl-aw + 2692, // 566 - nl-be + 2697, // 567 - nl-bq + 2702, // 568 - nl-cw + 2707, // 569 - nl-nl + 2712, // 570 - nl-sr + 2717, // 571 - nl-sx + 2722, // 572 - nmg + 2725, // 573 - nmg-cm + 2731, // 574 - nn + 2733, // 575 - nn-no + 2738, // 576 - nnh + 2741, // 577 - nnh-cm + 2747, // 578 - no + 2749, // 579 - nqo + 2752, // 580 - nqo-gn + 2758, // 581 - nr + 2760, // 582 - nr-za + 2765, // 583 - nso + 2768, // 584 - nso-za + 2774, // 585 - nus + 2777, // 586 - nus-ss + 2783, // 587 - nyn + 2786, // 588 - nyn-ug + 2792, // 589 - oc + 2794, // 590 - oc-fr + 2799, // 591 - om + 2801, // 592 - om-et + 2806, // 593 - om-ke + 2811, // 594 - or + 2813, // 595 - or-in + 2818, // 596 - os + 2820, // 597 - os-ge + 2825, // 598 - os-ru + 2830, // 599 - pa + 2832, // 600 - pa-arab + 2839, // 601 - pa-arab-pk + 2849, // 602 - pa-in + 2854, // 603 - pap + 2857, // 604 - pap-029 + 2864, // 605 - pl + 2866, // 606 - pl-pl + 2871, // 607 - prg + 2874, // 608 - prg-001 + 2881, // 609 - prs + 2884, // 610 - prs-af + 2890, // 611 - ps + 2892, // 612 - ps-af + 2897, // 613 - pt + 2899, // 614 - pt-ao + 2904, // 615 - pt-br + 2909, // 616 - pt-ch + 2914, // 617 - pt-cv + 2919, // 618 - pt-gq + 2924, // 619 - pt-gw + 2929, // 620 - pt-lu + 2934, // 621 - pt-mo + 2939, // 622 - pt-mz + 2944, // 623 - pt-pt + 2949, // 624 - pt-st + 2954, // 625 - pt-tl + 2959, // 626 - qps-latn-x-sh + 2972, // 627 - qps-ploc + 2980, // 628 - qps-ploca + 2989, // 629 - qps-plocm + 2998, // 630 - quc + 3001, // 631 - quc-latn + 3009, // 632 - quc-latn-gt + 3020, // 633 - quz + 3023, // 634 - quz-bo + 3029, // 635 - quz-ec + 3035, // 636 - quz-pe + 3041, // 637 - rm + 3043, // 638 - rm-ch + 3048, // 639 - rn + 3050, // 640 - rn-bi + 3055, // 641 - ro + 3057, // 642 - ro-md + 3062, // 643 - ro-ro + 3067, // 644 - rof + 3070, // 645 - rof-tz + 3076, // 646 - ru + 3078, // 647 - ru-by + 3083, // 648 - ru-kg + 3088, // 649 - ru-kz + 3093, // 650 - ru-md + 3098, // 651 - ru-ru + 3103, // 652 - ru-ua + 3108, // 653 - rw + 3110, // 654 - rw-rw + 3115, // 655 - rwk + 3118, // 656 - rwk-tz + 3124, // 657 - sa + 3126, // 658 - sa-in + 3131, // 659 - sah + 3134, // 660 - sah-ru + 3140, // 661 - saq + 3143, // 662 - saq-ke + 3149, // 663 - sbp + 3152, // 664 - sbp-tz + 3158, // 665 - sd + 3160, // 666 - sd-arab + 3167, // 667 - sd-arab-pk + 3177, // 668 - sd-deva + 3184, // 669 - sd-deva-in + 3194, // 670 - se + 3196, // 671 - se-fi + 3201, // 672 - se-no + 3206, // 673 - se-se + 3211, // 674 - seh + 3214, // 675 - seh-mz + 3220, // 676 - ses + 3223, // 677 - ses-ml + 3229, // 678 - sg + 3231, // 679 - sg-cf + 3236, // 680 - shi + 3239, // 681 - shi-latn + 3247, // 682 - shi-latn-ma + 3258, // 683 - shi-tfng + 3266, // 684 - shi-tfng-ma + 3277, // 685 - si + 3279, // 686 - si-lk + 3284, // 687 - sk + 3286, // 688 - sk-sk + 3291, // 689 - sl + 3293, // 690 - sl-si + 3298, // 691 - sma + 3301, // 692 - sma-no + 3307, // 693 - sma-se + 3313, // 694 - smj + 3316, // 695 - smj-no + 3322, // 696 - smj-se + 3328, // 697 - smn + 3331, // 698 - smn-fi + 3337, // 699 - sms + 3340, // 700 - sms-fi + 3346, // 701 - sn + 3348, // 702 - sn-latn + 3355, // 703 - sn-latn-zw + 3365, // 704 - so + 3367, // 705 - so-dj + 3372, // 706 - so-et + 3377, // 707 - so-ke + 3382, // 708 - so-so + 3387, // 709 - sq + 3389, // 710 - sq-al + 3394, // 711 - sq-mk + 3399, // 712 - sq-xk + 3404, // 713 - sr + 3406, // 714 - sr-cyrl + 3413, // 715 - sr-cyrl-ba + 3423, // 716 - sr-cyrl-cs + 3433, // 717 - sr-cyrl-me + 3443, // 718 - sr-cyrl-rs + 3453, // 719 - sr-cyrl-xk + 3463, // 720 - sr-latn + 3470, // 721 - sr-latn-ba + 3480, // 722 - sr-latn-cs + 3490, // 723 - sr-latn-me + 3500, // 724 - sr-latn-rs + 3510, // 725 - sr-latn-xk + 3520, // 726 - ss + 3522, // 727 - ss-sz + 3527, // 728 - ss-za + 3532, // 729 - ssy + 3535, // 730 - ssy-er + 3541, // 731 - st + 3543, // 732 - st-ls + 3548, // 733 - st-za + 3553, // 734 - sv + 3555, // 735 - sv-ax + 3560, // 736 - sv-fi + 3565, // 737 - sv-se + 3570, // 738 - sw + 3572, // 739 - sw-cd + 3577, // 740 - sw-ke + 3582, // 741 - sw-tz + 3587, // 742 - sw-ug + 3592, // 743 - swc + 3595, // 744 - swc-cd + 3601, // 745 - syr + 3604, // 746 - syr-sy + 3610, // 747 - ta + 3612, // 748 - ta-in + 3617, // 749 - ta-lk + 3622, // 750 - ta-my + 3627, // 751 - ta-sg + 3632, // 752 - te + 3634, // 753 - te-in + 3639, // 754 - teo + 3642, // 755 - teo-ke + 3648, // 756 - teo-ug + 3654, // 757 - tg + 3656, // 758 - tg-cyrl + 3663, // 759 - tg-cyrl-tj + 3673, // 760 - th + 3675, // 761 - th-th + 3680, // 762 - ti + 3682, // 763 - ti-er + 3687, // 764 - ti-et + 3692, // 765 - tig + 3695, // 766 - tig-er + 3701, // 767 - tk + 3703, // 768 - tk-tm + 3708, // 769 - tn + 3710, // 770 - tn-bw + 3715, // 771 - tn-za + 3720, // 772 - to + 3722, // 773 - to-to + 3727, // 774 - tr + 3729, // 775 - tr-cy + 3734, // 776 - tr-tr + 3739, // 777 - ts + 3741, // 778 - ts-za + 3746, // 779 - tt + 3748, // 780 - tt-ru + 3753, // 781 - twq + 3756, // 782 - twq-ne + 3762, // 783 - tzm + 3765, // 784 - tzm-arab + 3773, // 785 - tzm-arab-ma + 3784, // 786 - tzm-latn + 3792, // 787 - tzm-latn-dz + 3803, // 788 - tzm-latn-ma + 3814, // 789 - tzm-tfng + 3822, // 790 - tzm-tfng-ma + 3833, // 791 - ug + 3835, // 792 - ug-cn + 3840, // 793 - uk + 3842, // 794 - uk-ua + 3847, // 795 - ur + 3849, // 796 - ur-in + 3854, // 797 - ur-pk + 3859, // 798 - uz + 3861, // 799 - uz-arab + 3868, // 800 - uz-arab-af + 3878, // 801 - uz-cyrl + 3885, // 802 - uz-cyrl-uz + 3895, // 803 - uz-latn + 3902, // 804 - uz-latn-uz + 3912, // 805 - vai + 3915, // 806 - vai-latn + 3923, // 807 - vai-latn-lr + 3934, // 808 - vai-vaii + 3942, // 809 - vai-vaii-lr + 3953, // 810 - ve + 3955, // 811 - ve-za + 3960, // 812 - vi + 3962, // 813 - vi-vn + 3967, // 814 - vo + 3969, // 815 - vo-001 + 3975, // 816 - vun + 3978, // 817 - vun-tz + 3984, // 818 - wae + 3987, // 819 - wae-ch + 3993, // 820 - wal + 3996, // 821 - wal-et + 4002, // 822 - wo + 4004, // 823 - wo-sn + 4009, // 824 - x-iv_mathan + 4020, // 825 - xh + 4022, // 826 - xh-za + 4027, // 827 - xog + 4030, // 828 - xog-ug + 4036, // 829 - yav + 4039, // 830 - yav-cm + 4045, // 831 - yi + 4047, // 832 - yi-001 + 4053, // 833 - yo + 4055, // 834 - yo-bj + 4060, // 835 - yo-ng + 4065, // 836 - yue + 4068, // 837 - yue-hk + 4074, // 838 - zgh + 4077, // 839 - zgh-tfng + 4085, // 840 - zgh-tfng-ma + 4096, // 841 - zh + 4098, // 842 - zh-chs + 4104, // 843 - zh-cht + 4110, // 844 - zh-cn + 4115, // 845 - zh-cn_phoneb + 4127, // 846 - zh-cn_stroke + 4139, // 847 - zh-hans + 4146, // 848 - zh-hans-hk + 4156, // 849 - zh-hans-mo + 4166, // 850 - zh-hant + 4173, // 851 - zh-hk + 4178, // 852 - zh-hk_radstr + 4190, // 853 - zh-mo + 4195, // 854 - zh-mo_radstr + 4207, // 855 - zh-mo_stroke + 4219, // 856 - zh-sg + 4224, // 857 - zh-sg_phoneb + 4236, // 858 - zh-sg_stroke + 4248, // 859 - zh-tw + 4253, // 860 - zh-tw_pronun + 4265, // 861 - zh-tw_radstr + 4277, // 862 - zu + 4279, // 863 - zu-za + 4284 + }; + + private const int NUMERIC_LOCALE_DATA_COUNT_PER_ROW = 9; + // s_nameIndexToNumericData is mapping from index in s_localeNamesIndices to locale data. + // each row in the table will have the following data: + // Lcid, Ansi codepage, Oem codepage, MAC codepage, EBCDIC codepage, Geo Id, Digit Substitution, specific locale index, Console locale index + private static readonly int[] s_nameIndexToNumericData = new int[] + { + // Lcid, Ansi CP, Oem CP, MAC CP, EBCDIC CP, Geo Id, digit substitution, Specific culture index, keyboard Id, Console locale index // index - locale name + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 , 3 , 240 , // 0 - aa + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3e , 1 , 1 , 240 , // 1 - aa-dj + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x47 , 1 , 2 , 240 , // 2 - aa-er + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 , 3 , 240 , // 3 - aa-et + 0x36 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd1 , 1 , 6 , 6 , // 4 - af + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xfe , 1 , 5 , 240 , // 5 - af-na + 0x436 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd1 , 1 , 6 , 6 , // 6 - af-za + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 8 , 240 , // 7 - agq + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 8 , 240 , // 8 - agq-cm + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x59 , 1 , 10 , 240 , // 9 - ak + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x59 , 1 , 10 , 240 , // 10 - ak-gh + 0x5e , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 , 12 , 143 , // 11 - am + 0x45e , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 , 12 , 143 , // 12 - am-et + 0x1 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xcd , 0 , 33 , 143 , // 13 - ar + 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x989e, 0 , 14 , 240 , // 14 - ar-001 + 0x3801 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xe0 , 0 , 15 , 143 , // 15 - ar-ae + 0x3c01 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x11 , 0 , 16 , 143 , // 16 - ar-bh + 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x3e , 0 , 17 , 240 , // 17 - ar-dj + 0x1401 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x4 , 1 , 18 , 300 , // 18 - ar-dz + 0xc01 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x43 , 0 , 19 , 143 , // 19 - ar-eg + 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x47 , 0 , 20 , 240 , // 20 - ar-er + 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x75 , 0 , 21 , 240 , // 21 - ar-il + 0x801 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x79 , 0 , 22 , 143 , // 22 - ar-iq + 0x2c01 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x7e , 0 , 23 , 143 , // 23 - ar-jo + 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x32 , 0 , 24 , 240 , // 24 - ar-km + 0x3401 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x88 , 0 , 25 , 143 , // 25 - ar-kw + 0x3001 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x8b , 0 , 26 , 143 , // 26 - ar-lb + 0x1001 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x94 , 1 , 27 , 143 , // 27 - ar-ly + 0x1801 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x9f , 1 , 28 , 300 , // 28 - ar-ma + 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xa2 , 0 , 29 , 240 , // 29 - ar-mr + 0x2001 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xa4 , 0 , 30 , 143 , // 30 - ar-om + 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xb8 , 0 , 31 , 240 , // 31 - ar-ps + 0x4001 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xc5 , 0 , 32 , 143 , // 32 - ar-qa + 0x401 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xcd , 0 , 33 , 143 , // 33 - ar-sa + 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xdb , 0 , 34 , 240 , // 34 - ar-sd + 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xd8 , 0 , 35 , 240 , // 35 - ar-so + 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x114 , 0 , 36 , 240 , // 36 - ar-ss + 0x2801 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xde , 0 , 37 , 143 , // 37 - ar-sy + 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x29 , 0 , 38 , 240 , // 38 - ar-td + 0x1c01 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xea , 1 , 39 , 300 , // 39 - ar-tn + 0x2401 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x105 , 0 , 40 , 143 , // 40 - ar-ye + 0x7a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x2e , 1 , 42 , 42 , // 41 - arn + 0x47a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x2e , 1 , 42 , 42 , // 42 - arn-cl + 0x4d , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 44 , 143 , // 43 - as + 0x44d , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 44 , 143 , // 44 - as-in + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 46 , 240 , // 45 - asa + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 46 , 240 , // 46 - asa-tz + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd9 , 1 , 48 , 240 , // 47 - ast + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd9 , 1 , 48 , 240 , // 48 - ast-es + 0x2c , 0x4e6 , 0x359 , 0x2761, 0x51a9, 0x5 , 1 , 53 , 53 , // 49 - az + 0x742c , 0x4e3 , 0x362 , 0x2717, 0x5190, 0x5 , 1 , 51 , 51 , // 50 - az-cyrl + 0x82c , 0x4e3 , 0x362 , 0x2717, 0x5190, 0x5 , 1 , 51 , 51 , // 51 - az-cyrl-az + 0x782c , 0x4e6 , 0x359 , 0x2761, 0x51a9, 0x5 , 1 , 53 , 53 , // 52 - az-latn + 0x42c , 0x4e6 , 0x359 , 0x2761, 0x51a9, 0x5 , 1 , 53 , 53 , // 53 - az-latn-az + 0x6d , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xcb , 1 , 55 , 55 , // 54 - ba + 0x46d , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xcb , 1 , 55 , 55 , // 55 - ba-ru + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 57 , 240 , // 56 - bas + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 57 , 240 , // 57 - bas-cm + 0x23 , 0x4e3 , 0x362 , 0x2717, 0x1f4 , 0x1d , 1 , 59 , 59 , // 58 - be + 0x423 , 0x4e3 , 0x362 , 0x2717, 0x1f4 , 0x1d , 1 , 59 , 59 , // 59 - be-by + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x107 , 1 , 61 , 240 , // 60 - bem + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x107 , 1 , 61 , 240 , // 61 - bem-zm + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 63 , 240 , // 62 - bez + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 63 , 240 , // 63 - bez-tz + 0x2 , 0x4e3 , 0x362 , 0x2717, 0x5221, 0x23 , 1 , 65 , 65 , // 64 - bg + 0x402 , 0x4e3 , 0x362 , 0x2717, 0x5221, 0x23 , 1 , 65 , 65 , // 65 - bg-bg + 0x66 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xaf , 1 , 67 , 240 , // 66 - bin + 0x466 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xaf , 1 , 67 , 240 , // 67 - bin-ng + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9d , 1 , 70 , 240 , // 68 - bm + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9d , 1 , 70 , 240 , // 69 - bm-latn + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9d , 1 , 70 , 240 , // 70 - bm-latn-ml + 0x45 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x17 , 1 , 72 , 143 , // 71 - bn + 0x845 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x17 , 1 , 72 , 143 , // 72 - bn-bd + 0x445 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 73 , 143 , // 73 - bn-in + 0x51 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2d , 1 , 75 , 143 , // 74 - bo + 0x451 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2d , 1 , 75 , 143 , // 75 - bo-cn + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 76 , 240 , // 76 - bo-in + 0x7e , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x54 , 1 , 78 , 78 , // 77 - br + 0x47e , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x54 , 1 , 78 , 78 , // 78 - br-fr + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 80 , 240 , // 79 - brx + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 80 , 240 , // 80 - brx-in + 0x781a , 0x4e2 , 0x354 , 0x2762, 0x366 , 0x19 , 1 , 85 , 85 , // 81 - bs + 0x641a , 0x4e3 , 0x357 , 0x2762, 0x366 , 0x19 , 1 , 83 , 83 , // 82 - bs-cyrl + 0x201a , 0x4e3 , 0x357 , 0x2762, 0x366 , 0x19 , 1 , 83 , 83 , // 83 - bs-cyrl-ba + 0x681a , 0x4e2 , 0x354 , 0x2762, 0x366 , 0x19 , 1 , 85 , 85 , // 84 - bs-latn + 0x141a , 0x4e2 , 0x354 , 0x2762, 0x366 , 0x19 , 1 , 85 , 85 , // 85 - bs-latn-ba + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x47 , 1 , 87 , 240 , // 86 - byn + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x47 , 1 , 87 , 240 , // 87 - byn-er + 0x3 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd9 , 1 , 90 , 90 , // 88 - ca + 0x1000 , 0x4e4 , 0x352 , 0x2 , 0x1f4 , 0x8 , 1 , 89 , 240 , // 89 - ca-ad + 0x403 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd9 , 1 , 90 , 90 , // 90 - ca-es + 0x803 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd9 , 1 , 91 , 90 , // 91 - ca-es-valencia + 0x1000 , 0x4e4 , 0x352 , 0x2 , 0x1f4 , 0x54 , 1 , 92 , 240 , // 92 - ca-fr + 0x1000 , 0x4e4 , 0x352 , 0x2 , 0x1f4 , 0x76 , 1 , 93 , 240 , // 93 - ca-it + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xcb , 1 , 95 , 240 , // 94 - ce + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xcb , 1 , 95 , 240 , // 95 - ce-ru + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf0 , 1 , 97 , 240 , // 96 - cgg + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf0 , 1 , 97 , 240 , // 97 - cgg-ug + 0x5c , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf4 , 1 , 100 , 240 , // 98 - chr + 0x7c5c , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf4 , 1 , 100 , 240 , // 99 - chr-cher + 0x45c , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf4 , 1 , 100 , 240 , // 100 - chr-cher-us + 0x83 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x54 , 1 , 102 , 102 , // 101 - co + 0x483 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x54 , 1 , 102 , 102 , // 102 - co-fr + 0x5 , 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x4b , 1 , 104 , 104 , // 103 - cs + 0x405 , 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x4b , 1 , 104 , 104 , // 104 - cs-cz + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xcb , 1 , 106 , 240 , // 105 - cu + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xcb , 1 , 106 , 240 , // 106 - cu-ru + 0x52 , 0x4e4 , 0x352 , 0x2710, 0x4f3d, 0xf2 , 1 , 108 , 108 , // 107 - cy + 0x452 , 0x4e4 , 0x352 , 0x2710, 0x4f3d, 0xf2 , 1 , 108 , 108 , // 108 - cy-gb + 0x6 , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0x3d , 1 , 110 , 110 , // 109 - da + 0x406 , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0x3d , 1 , 110 , 110 , // 110 - da-dk + 0x1000 , 0x4e4 , 0x352 , 0x2 , 0x1f4 , 0x5d , 1 , 111 , 240 , // 111 - da-gl + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 113 , 240 , // 112 - dav + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 113 , 240 , // 113 - dav-ke + 0x7 , 0x4e4 , 0x352 , 0x2710, 0x4f31, 0x5e , 1 , 118 , 118 , // 114 - de + 0xc07 , 0x4e4 , 0x352 , 0x2710, 0x4f31, 0xe , 1 , 115 , 115 , // 115 - de-at + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f31, 0x15 , 1 , 116 , 240 , // 116 - de-be + 0x807 , 0x4e4 , 0x352 , 0x2710, 0x4f31, 0xdf , 1 , 117 , 117 , // 117 - de-ch + 0x407 , 0x4e4 , 0x352 , 0x2710, 0x4f31, 0x5e , 1 , 118 , 118 , // 118 - de-de + 0x10407, 0x4e4 , 0x352 , 0x2710, 0x4f31, 0x5e , 1 , 118 , 118 , // 119 - de-de_phoneb + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x76 , 1 , 120 , 240 , // 120 - de-it + 0x1407 , 0x4e4 , 0x352 , 0x2710, 0x4f31, 0x91 , 1 , 121 , 121 , // 121 - de-li + 0x1007 , 0x4e4 , 0x352 , 0x2710, 0x4f31, 0x93 , 1 , 122 , 122 , // 122 - de-lu + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xad , 1 , 124 , 240 , // 123 - dje + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xad , 1 , 124 , 240 , // 124 - dje-ne + 0x7c2e , 0x4e4 , 0x352 , 0x2710, 0x366 , 0x5e , 1 , 126 , 126 , // 125 - dsb + 0x82e , 0x4e4 , 0x352 , 0x2710, 0x366 , 0x5e , 1 , 126 , 126 , // 126 - dsb-de + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 128 , 240 , // 127 - dua + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 128 , 240 , // 128 - dua-cm + 0x65 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa5 , 1 , 130 , 143 , // 129 - dv + 0x465 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa5 , 1 , 130 , 143 , // 130 - dv-mv + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd2 , 1 , 132 , 240 , // 131 - dyo + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd2 , 1 , 132 , 240 , // 132 - dyo-sn + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x22 , 2 , 134 , 240 , // 133 - dz + 0xc51 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x22 , 2 , 134 , 240 , // 134 - dz-bt + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 136 , 240 , // 135 - ebu + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 136 , 240 , // 136 - ebu-ke + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x59 , 1 , 138 , 240 , // 137 - ee + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x59 , 1 , 138 , 240 , // 138 - ee-gh + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xe8 , 1 , 139 , 240 , // 139 - ee-tg + 0x8 , 0x4e5 , 0x2e1 , 0x2716, 0x4f31, 0x62 , 1 , 142 , 142 , // 140 - el + 0x1000 , 0x4e5 , 0x2e1 , 0x2716, 0x4f31, 0x3b , 1 , 141 , 240 , // 141 - el-cy + 0x408 , 0x4e5 , 0x2e1 , 0x2716, 0x4f31, 0x62 , 1 , 142 , 142 , // 142 - el-gr + 0x9 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xf4 , 1 , 240 , 240 , // 143 - en + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x989e, 1 , 144 , 240 , // 144 - en-001 + 0x2409 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x993248, 1 , 145 , 145 , // 145 - en-029 + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x292d, 1 , 146 , 240 , // 146 - en-150 + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x2 , 1 , 147 , 240 , // 147 - en-ag + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x12c , 1 , 148 , 240 , // 148 - en-ai + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xa , 1 , 149 , 240 , // 149 - en-as + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xe , 1 , 150 , 240 , // 150 - en-at + 0xc09 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xc , 1 , 151 , 151 , // 151 - en-au + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x12 , 1 , 152 , 240 , // 152 - en-bb + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x15 , 1 , 153 , 240 , // 153 - en-be + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x26 , 1 , 154 , 240 , // 154 - en-bi + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x14 , 1 , 155 , 240 , // 155 - en-bm + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x16 , 1 , 156 , 240 , // 156 - en-bs + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x13 , 1 , 157 , 240 , // 157 - en-bw + 0x2809 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x18 , 1 , 158 , 158 , // 158 - en-bz + 0x1009 , 0x4e4 , 0x352 , 0x2710, 0x25 , 0x27 , 1 , 159 , 159 , // 159 - en-ca + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x137 , 1 , 160 , 240 , // 160 - en-cc + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xdf , 1 , 161 , 240 , // 161 - en-ch + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x138 , 1 , 162 , 240 , // 162 - en-ck + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x31 , 1 , 163 , 240 , // 163 - en-cm + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x135 , 1 , 164 , 240 , // 164 - en-cx + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3b , 1 , 165 , 240 , // 165 - en-cy + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x5e , 1 , 166 , 240 , // 166 - en-de + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3d , 1 , 167 , 240 , // 167 - en-dk + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x3f , 1 , 168 , 240 , // 168 - en-dm + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x47 , 1 , 169 , 240 , // 169 - en-er + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x4d , 1 , 170 , 240 , // 170 - en-fi + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x4e , 1 , 171 , 240 , // 171 - en-fj + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x13b , 1 , 172 , 240 , // 172 - en-fk + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x50 , 1 , 173 , 240 , // 173 - en-fm + 0x809 , 0x4e4 , 0x352 , 0x2710, 0x4f3d, 0xf2 , 1 , 174 , 174 , // 174 - en-gb + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x5b , 1 , 175 , 240 , // 175 - en-gd + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x144 , 1 , 176 , 240 , // 176 - en-gg + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x59 , 1 , 177 , 240 , // 177 - en-gh + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x5a , 1 , 178 , 240 , // 178 - en-gi + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x56 , 1 , 179 , 240 , // 179 - en-gm + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x142 , 1 , 180 , 240 , // 180 - en-gu + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x65 , 1 , 181 , 240 , // 181 - en-gy + 0x3c09 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x68 , 1 , 182 , 240 , // 182 - en-hk + 0x3809 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x6f , 1 , 183 , 240 , // 183 - en-id + 0x1809 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x44 , 1 , 184 , 184 , // 184 - en-ie + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x75 , 1 , 185 , 240 , // 185 - en-il + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x3b16, 1 , 186 , 240 , // 186 - en-im + 0x4009 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0x71 , 1 , 187 , 187 , // 187 - en-in + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x72 , 1 , 188 , 240 , // 188 - en-io + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x148 , 1 , 189 , 240 , // 189 - en-je + 0x2009 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x7c , 1 , 190 , 190 , // 190 - en-jm + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x81 , 1 , 191 , 240 , // 191 - en-ke + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x85 , 1 , 192 , 240 , // 192 - en-ki + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xcf , 1 , 193 , 240 , // 193 - en-kn + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x133 , 1 , 194 , 240 , // 194 - en-ky + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xda , 1 , 195 , 240 , // 195 - en-lc + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x8e , 1 , 196 , 240 , // 196 - en-lr + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x92 , 1 , 197 , 240 , // 197 - en-ls + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x95 , 1 , 198 , 240 , // 198 - en-mg + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xc7 , 1 , 199 , 240 , // 199 - en-mh + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x97 , 1 , 200 , 240 , // 200 - en-mo + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x151 , 1 , 201 , 240 , // 201 - en-mp + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x14c , 1 , 202 , 240 , // 202 - en-ms + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xa3 , 1 , 203 , 240 , // 203 - en-mt + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xa0 , 1 , 204 , 240 , // 204 - en-mu + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x9c , 1 , 205 , 240 , // 205 - en-mw + 0x4409 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xa7 , 1 , 206 , 206 , // 206 - en-my + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xfe , 1 , 207 , 240 , // 207 - en-na + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x150 , 1 , 208 , 240 , // 208 - en-nf + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xaf , 1 , 209 , 240 , // 209 - en-ng + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xb0 , 1 , 210 , 240 , // 210 - en-nl + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xb4 , 1 , 211 , 240 , // 211 - en-nr + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x14f , 1 , 212 , 240 , // 212 - en-nu + 0x1409 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xb7 , 1 , 213 , 213 , // 213 - en-nz + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xc2 , 1 , 214 , 240 , // 214 - en-pg + 0x3409 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0xc9 , 1 , 215 , 215 , // 215 - en-ph + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xbe , 1 , 216 , 240 , // 216 - en-pk + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x153 , 1 , 217 , 240 , // 217 - en-pn + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xca , 1 , 218 , 240 , // 218 - en-pr + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xc3 , 1 , 219 , 240 , // 219 - en-pw + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xcc , 1 , 220 , 240 , // 220 - en-rw + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x1e , 1 , 221 , 240 , // 221 - en-sb + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd0 , 1 , 222 , 240 , // 222 - en-sc + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xdb , 1 , 223 , 240 , // 223 - en-sd + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xdd , 1 , 224 , 240 , // 224 - en-se + 0x4809 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xd7 , 1 , 225 , 225 , // 225 - en-sg + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x157 , 1 , 226 , 240 , // 226 - en-sh + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd4 , 1 , 227 , 240 , // 227 - en-si + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd5 , 1 , 228 , 240 , // 228 - en-sl + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x114 , 1 , 229 , 240 , // 229 - en-ss + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x78f7, 1 , 230 , 240 , // 230 - en-sx + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x104 , 1 , 231 , 240 , // 231 - en-sz + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x15d , 1 , 232 , 240 , // 232 - en-tc + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x15b , 1 , 233 , 240 , // 233 - en-tk + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xe7 , 1 , 234 , 240 , // 234 - en-to + 0x2c09 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xe1 , 1 , 235 , 235 , // 235 - en-tt + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xec , 1 , 236 , 240 , // 236 - en-tv + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xef , 1 , 237 , 240 , // 237 - en-tz + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xf0 , 1 , 238 , 240 , // 238 - en-ug + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x9a55d40, 1 , 239 , 240 , // 239 - en-um + 0x409 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xf4 , 1 , 240 , 240 , // 240 - en-us + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xf8 , 1 , 241 , 240 , // 241 - en-vc + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x15f , 1 , 242 , 240 , // 242 - en-vg + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xfc , 1 , 243 , 240 , // 243 - en-vi + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xae , 1 , 244 , 240 , // 244 - en-vu + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x103 , 1 , 245 , 240 , // 245 - en-ws + 0x1c09 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0xd1 , 1 , 246 , 246 , // 246 - en-za + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x107 , 1 , 247 , 240 , // 247 - en-zm + 0x3009 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0x108 , 1 , 248 , 248 , // 248 - en-zw + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x989e, 1 , 250 , 240 , // 249 - eo + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x989e, 1 , 250 , 240 , // 250 - eo-001 + 0xa , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xd9 , 1 , 262 , 262 , // 251 - es + 0x580a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x9a55d41, 1 , 252 , 240 , // 252 - es-419 + 0x2c0a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xb , 1 , 253 , 253 , // 253 - es-ar + 0x400a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x1a , 1 , 254 , 254 , // 254 - es-bo + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x20 , 1 , 255 , 240 , // 255 - es-br + 0x340a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x2e , 1 , 256 , 256 , // 256 - es-cl + 0x240a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x33 , 1 , 257 , 257 , // 257 - es-co + 0x140a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x36 , 1 , 258 , 258 , // 258 - es-cr + 0x5c0a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x38 , 1 , 259 , 240 , // 259 - es-cu + 0x1c0a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x41 , 1 , 260 , 260 , // 260 - es-do + 0x300a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x42 , 1 , 261 , 261 , // 261 - es-ec + 0xc0a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xd9 , 1 , 262 , 262 , // 262 - es-es + 0x40a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xd9 , 1 , 263 , 263 , // 263 - es-es_tradnl + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x45 , 1 , 264 , 240 , // 264 - es-gq + 0x100a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x63 , 1 , 265 , 265 , // 265 - es-gt + 0x480a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x6a , 1 , 266 , 266 , // 266 - es-hn + 0x80a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xa6 , 1 , 267 , 267 , // 267 - es-mx + 0x4c0a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xb6 , 1 , 268 , 268 , // 268 - es-ni + 0x180a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xc0 , 1 , 269 , 269 , // 269 - es-pa + 0x280a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xbb , 1 , 270 , 270 , // 270 - es-pe + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xc9 , 1 , 271 , 240 , // 271 - es-ph + 0x500a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xca , 1 , 272 , 272 , // 272 - es-pr + 0x3c0a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xb9 , 1 , 273 , 273 , // 273 - es-py + 0x440a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x48 , 1 , 274 , 274 , // 274 - es-sv + 0x540a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xf4 , 1 , 275 , 275 , // 275 - es-us + 0x380a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xf6 , 1 , 276 , 276 , // 276 - es-uy + 0x200a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xf9 , 1 , 277 , 277 , // 277 - es-ve + 0x25 , 0x4e9 , 0x307 , 0x272d, 0x1f4 , 0x46 , 1 , 279 , 279 , // 278 - et + 0x425 , 0x4e9 , 0x307 , 0x272d, 0x1f4 , 0x46 , 1 , 279 , 279 , // 279 - et-ee + 0x2d , 0x4e4 , 0x352 , 0x2 , 0x1f4 , 0xd9 , 1 , 281 , 240 , // 280 - eu + 0x42d , 0x4e4 , 0x352 , 0x2 , 0x1f4 , 0xd9 , 1 , 281 , 240 , // 281 - eu-es + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 283 , 240 , // 282 - ewo + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 283 , 240 , // 283 - ewo-cm + 0x29 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x74 , 0 , 285 , 143 , // 284 - fa + 0x429 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x74 , 0 , 285 , 143 , // 285 - fa-ir + 0x67 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xd2 , 1 , 290 , 290 , // 286 - ff + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x31 , 1 , 287 , 240 , // 287 - ff-cm + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x64 , 1 , 288 , 240 , // 288 - ff-gn + 0x7c67 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xd2 , 1 , 290 , 290 , // 289 - ff-latn + 0x867 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xd2 , 1 , 290 , 290 , // 290 - ff-latn-sn + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xa2 , 1 , 291 , 240 , // 291 - ff-mr + 0x467 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xaf , 1 , 292 , 240 , // 292 - ff-ng + 0xb , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0x4d , 1 , 294 , 294 , // 293 - fi + 0x40b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0x4d , 1 , 294 , 294 , // 294 - fi-fi + 0x64 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0xc9 , 1 , 296 , 296 , // 295 - fil + 0x464 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0xc9 , 1 , 296 , 296 , // 296 - fil-ph + 0x38 , 0x4e4 , 0x352 , 0x275f, 0x4f35, 0x51 , 1 , 299 , 299 , // 297 - fo + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3d , 1 , 298 , 240 , // 298 - fo-dk + 0x438 , 0x4e4 , 0x352 , 0x275f, 0x4f35, 0x51 , 1 , 299 , 299 , // 299 - fo-fo + 0xc , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x54 , 1 , 316 , 316 , // 300 - fr + 0x1c0c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x993248, 1 , 301 , 316 , // 301 - fr-029 + 0x80c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x15 , 1 , 302 , 302 , // 302 - fr-be + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xf5 , 1 , 303 , 240 , // 303 - fr-bf + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x26 , 1 , 304 , 240 , // 304 - fr-bi + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x1c , 1 , 305 , 240 , // 305 - fr-bj + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x9a55c4f, 1 , 306 , 240 , // 306 - fr-bl + 0xc0c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x27 , 1 , 307 , 307 , // 307 - fr-ca + 0x240c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x2c , 1 , 308 , 240 , // 308 - fr-cd + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x37 , 1 , 309 , 240 , // 309 - fr-cf + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x2b , 1 , 310 , 240 , // 310 - fr-cg + 0x100c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xdf , 1 , 311 , 311 , // 311 - fr-ch + 0x300c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x77 , 1 , 312 , 240 , // 312 - fr-ci + 0x2c0c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x31 , 1 , 313 , 240 , // 313 - fr-cm + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x3e , 1 , 314 , 240 , // 314 - fr-dj + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x4 , 1 , 315 , 240 , // 315 - fr-dz + 0x40c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x54 , 1 , 316 , 316 , // 316 - fr-fr + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x57 , 1 , 317 , 240 , // 317 - fr-ga + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x13d , 1 , 318 , 240 , // 318 - fr-gf + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x64 , 1 , 319 , 240 , // 319 - fr-gn + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x141 , 1 , 320 , 240 , // 320 - fr-gp + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x45 , 1 , 321 , 240 , // 321 - fr-gq + 0x3c0c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x67 , 1 , 322 , 240 , // 322 - fr-ht + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x32 , 1 , 323 , 240 , // 323 - fr-km + 0x140c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x93 , 1 , 324 , 324 , // 324 - fr-lu + 0x380c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x9f , 1 , 325 , 240 , // 325 - fr-ma + 0x180c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x9e , 1 , 326 , 326 , // 326 - fr-mc + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x7bda, 1 , 327 , 240 , // 327 - fr-mf + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x95 , 1 , 328 , 240 , // 328 - fr-mg + 0x340c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x9d , 1 , 329 , 240 , // 329 - fr-ml + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x14a , 1 , 330 , 240 , // 330 - fr-mq + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xa2 , 1 , 331 , 240 , // 331 - fr-mr + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xa0 , 1 , 332 , 240 , // 332 - fr-mu + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x14e , 1 , 333 , 240 , // 333 - fr-nc + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xad , 1 , 334 , 240 , // 334 - fr-ne + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x13e , 1 , 335 , 240 , // 335 - fr-pf + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xce , 1 , 336 , 240 , // 336 - fr-pm + 0x200c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xc6 , 1 , 337 , 240 , // 337 - fr-re + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xcc , 1 , 338 , 240 , // 338 - fr-rw + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xd0 , 1 , 339 , 240 , // 339 - fr-sc + 0x280c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xd2 , 1 , 340 , 240 , // 340 - fr-sn + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xde , 1 , 341 , 240 , // 341 - fr-sy + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x29 , 1 , 342 , 240 , // 342 - fr-td + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xe8 , 1 , 343 , 240 , // 343 - fr-tg + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xea , 1 , 344 , 240 , // 344 - fr-tn + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xae , 1 , 345 , 240 , // 345 - fr-vu + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x160 , 1 , 346 , 240 , // 346 - fr-wf + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x14b , 1 , 347 , 240 , // 347 - fr-yt + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x76 , 1 , 349 , 240 , // 348 - fur + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x76 , 1 , 349 , 240 , // 349 - fur-it + 0x62 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xb0 , 1 , 351 , 351 , // 350 - fy + 0x462 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xb0 , 1 , 351 , 351 , // 351 - fy-nl + 0x3c , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x44 , 1 , 353 , 353 , // 352 - ga + 0x83c , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x44 , 1 , 353 , 353 , // 353 - ga-ie + 0x91 , 0x4e4 , 0x352 , 0x2710, 0x4f3d, 0xf2 , 1 , 355 , 355 , // 354 - gd + 0x491 , 0x4e4 , 0x352 , 0x2710, 0x4f3d, 0xf2 , 1 , 355 , 355 , // 355 - gd-gb + 0x56 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd9 , 1 , 357 , 357 , // 356 - gl + 0x456 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd9 , 1 , 357 , 357 , // 357 - gl-es + 0x74 , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xb9 , 1 , 359 , 359 , // 358 - gn + 0x474 , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xb9 , 1 , 359 , 359 , // 359 - gn-py + 0x84 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xdf , 1 , 361 , 240 , // 360 - gsw + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xdf , 1 , 361 , 240 , // 361 - gsw-ch + 0x484 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x54 , 1 , 362 , 362 , // 362 - gsw-fr + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x91 , 1 , 363 , 240 , // 363 - gsw-li + 0x47 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 365 , 143 , // 364 - gu + 0x447 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 365 , 143 , // 365 - gu-in + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 367 , 240 , // 366 - guz + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 367 , 240 , // 367 - guz-ke + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3b16, 1 , 369 , 240 , // 368 - gv + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3b16, 1 , 369 , 240 , // 369 - gv-im + 0x68 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xaf , 1 , 374 , 374 , // 370 - ha + 0x7c68 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xaf , 1 , 374 , 374 , // 371 - ha-latn + 0x1000 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0x59 , 1 , 372 , 240 , // 372 - ha-latn-gh + 0x1000 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0xad , 1 , 373 , 240 , // 373 - ha-latn-ne + 0x468 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xaf , 1 , 374 , 374 , // 374 - ha-latn-ng + 0x75 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xf4 , 1 , 376 , 376 , // 375 - haw + 0x475 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xf4 , 1 , 376 , 376 , // 376 - haw-us + 0xd , 0x4e7 , 0x35e , 0x2715, 0x1f4 , 0x75 , 1 , 378 , 143 , // 377 - he + 0x40d , 0x4e7 , 0x35e , 0x2715, 0x1f4 , 0x75 , 1 , 378 , 143 , // 378 - he-il + 0x39 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 380 , 143 , // 379 - hi + 0x439 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 380 , 143 , // 380 - hi-in + 0x1a , 0x4e2 , 0x354 , 0x2762, 0x1f4 , 0x6c , 1 , 383 , 383 , // 381 - hr + 0x101a , 0x4e2 , 0x354 , 0x2762, 0x366 , 0x19 , 1 , 382 , 382 , // 382 - hr-ba + 0x41a , 0x4e2 , 0x354 , 0x2762, 0x1f4 , 0x6c , 1 , 383 , 383 , // 383 - hr-hr + 0x2e , 0x4e4 , 0x352 , 0x2710, 0x366 , 0x5e , 1 , 385 , 385 , // 384 - hsb + 0x42e , 0x4e4 , 0x352 , 0x2710, 0x366 , 0x5e , 1 , 385 , 385 , // 385 - hsb-de + 0xe , 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x6d , 1 , 387 , 387 , // 386 - hu + 0x40e , 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x6d , 1 , 387 , 387 , // 387 - hu-hu + 0x1040e, 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x6d , 1 , 387 , 387 , // 388 - hu-hu_technl + 0x2b , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x7 , 1 , 390 , 390 , // 389 - hy + 0x42b , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x7 , 1 , 390 , 390 , // 390 - hy-am + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x54 , 1 , 393 , 240 , // 391 - ia + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x989e, 1 , 392 , 240 , // 392 - ia-001 + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x54 , 1 , 393 , 240 , // 393 - ia-fr + 0x69 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xaf , 1 , 395 , 240 , // 394 - ibb + 0x469 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xaf , 1 , 395 , 240 , // 395 - ibb-ng + 0x21 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x6f , 1 , 397 , 397 , // 396 - id + 0x421 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x6f , 1 , 397 , 397 , // 397 - id-id + 0x70 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xaf , 1 , 399 , 399 , // 398 - ig + 0x470 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xaf , 1 , 399 , 399 , // 399 - ig-ng + 0x78 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2d , 1 , 401 , 143 , // 400 - ii + 0x478 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2d , 1 , 401 , 143 , // 401 - ii-cn + 0xf , 0x4e4 , 0x352 , 0x275f, 0x5187, 0x6e , 1 , 403 , 403 , // 402 - is + 0x40f , 0x4e4 , 0x352 , 0x275f, 0x5187, 0x6e , 1 , 403 , 403 , // 403 - is-is + 0x10 , 0x4e4 , 0x352 , 0x2710, 0x4f38, 0x76 , 1 , 406 , 406 , // 404 - it + 0x810 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xdf , 1 , 405 , 405 , // 405 - it-ch + 0x410 , 0x4e4 , 0x352 , 0x2710, 0x4f38, 0x76 , 1 , 406 , 406 , // 406 - it-it + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f38, 0xd6 , 1 , 407 , 240 , // 407 - it-sm + 0x5d , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0x27 , 1 , 412 , 412 , // 408 - iu + 0x785d , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x27 , 1 , 410 , 143 , // 409 - iu-cans + 0x45d , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x27 , 1 , 410 , 143 , // 410 - iu-cans-ca + 0x7c5d , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0x27 , 1 , 412 , 412 , // 411 - iu-latn + 0x85d , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0x27 , 1 , 412 , 412 , // 412 - iu-latn-ca + 0x11 , 0x3a4 , 0x3a4 , 0x2711, 0x4f42, 0x7a , 1 , 414 , 414 , // 413 - ja + 0x411 , 0x3a4 , 0x3a4 , 0x2711, 0x4f42, 0x7a , 1 , 414 , 414 , // 414 - ja-jp + 0x40411, 0x3a4 , 0x3a4 , 0x2711, 0x4f42, 0x7a , 1 , 414 , 414 , // 415 - ja-jp_radstr + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 417 , 240 , // 416 - jgo + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 417 , 240 , // 417 - jgo-cm + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 419 , 240 , // 418 - jmc + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 419 , 240 , // 419 - jmc-tz + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x6f , 1 , 424 , 424 , // 420 - jv + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x6f , 1 , 422 , 424 , // 421 - jv-java + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x6f , 1 , 422 , 424 , // 422 - jv-java-id + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x6f , 1 , 424 , 424 , // 423 - jv-latn + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x6f , 1 , 424 , 424 , // 424 - jv-latn-id + 0x37 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x58 , 1 , 426 , 426 , // 425 - ka + 0x437 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x58 , 1 , 426 , 426 , // 426 - ka-ge + 0x10437, 0x0 , 0x1 , 0x2 , 0x1f4 , 0x58 , 1 , 426 , 426 , // 427 - ka-ge_modern + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x4 , 1 , 429 , 240 , // 428 - kab + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x4 , 1 , 429 , 240 , // 429 - kab-dz + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 431 , 240 , // 430 - kam + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 431 , 240 , // 431 - kam-ke + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 433 , 240 , // 432 - kde + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 433 , 240 , // 433 - kde-tz + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x39 , 1 , 435 , 240 , // 434 - kea + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x39 , 1 , 435 , 240 , // 435 - kea-cv + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9d , 1 , 437 , 240 , // 436 - khq + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9d , 1 , 437 , 240 , // 437 - khq-ml + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 439 , 240 , // 438 - ki + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 439 , 240 , // 439 - ki-ke + 0x3f , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x89 , 1 , 441 , 441 , // 440 - kk + 0x43f , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x89 , 1 , 441 , 441 , // 441 - kk-kz + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 443 , 240 , // 442 - kkj + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 443 , 240 , // 443 - kkj-cm + 0x6f , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0x5d , 1 , 445 , 445 , // 444 - kl + 0x46f , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0x5d , 1 , 445 , 445 , // 445 - kl-gl + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 447 , 240 , // 446 - kln + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 447 , 240 , // 447 - kln-ke + 0x53 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x28 , 2 , 449 , 143 , // 448 - km + 0x453 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x28 , 2 , 449 , 143 , // 449 - km-kh + 0x4b , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 451 , 143 , // 450 - kn + 0x44b , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 451 , 143 , // 451 - kn-in + 0x12 , 0x3b5 , 0x3b5 , 0x2713, 0x5161, 0x86 , 1 , 454 , 454 , // 452 - ko + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x83 , 1 , 453 , 240 , // 453 - ko-kp + 0x412 , 0x3b5 , 0x3b5 , 0x2713, 0x5161, 0x86 , 1 , 454 , 454 , // 454 - ko-kr + 0x57 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 456 , 143 , // 455 - kok + 0x457 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 456 , 143 , // 456 - kok-in + 0x71 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xaf , 1 , 458 , 240 , // 457 - kr + 0x471 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xaf , 1 , 458 , 240 , // 458 - kr-ng + 0x60 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 2 , 461 , 240 , // 459 - ks + 0x460 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 2 , 461 , 240 , // 460 - ks-arab + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 2 , 461 , 240 , // 461 - ks-arab-in + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 463 , 187 , // 462 - ks-deva + 0x860 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 463 , 187 , // 463 - ks-deva-in + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 465 , 240 , // 464 - ksb + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 465 , 240 , // 465 - ksb-tz + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 467 , 240 , // 466 - ksf + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 467 , 240 , // 467 - ksf-cm + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x5e , 1 , 469 , 240 , // 468 - ksh + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x5e , 1 , 469 , 240 , // 469 - ksh-de + 0x92 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x79 , 0 , 472 , 143 , // 470 - ku + 0x7c92 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x79 , 0 , 472 , 143 , // 471 - ku-arab + 0x492 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x79 , 0 , 472 , 143 , // 472 - ku-arab-iq + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x74 , 0 , 473 , 240 , // 473 - ku-arab-ir + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf2 , 1 , 475 , 240 , // 474 - kw + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf2 , 1 , 475 , 240 , // 475 - kw-gb + 0x40 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0x82 , 1 , 477 , 477 , // 476 - ky + 0x440 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0x82 , 1 , 477 , 477 , // 477 - ky-kg + 0x76 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0x989e, 1 , 479 , 143 , // 478 - la + 0x476 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0x989e, 1 , 479 , 143 , // 479 - la-001 + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 481 , 240 , // 480 - lag + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 481 , 240 , // 481 - lag-tz + 0x6e , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x93 , 1 , 483 , 483 , // 482 - lb + 0x46e , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x93 , 1 , 483 , 483 , // 483 - lb-lu + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf0 , 1 , 485 , 240 , // 484 - lg + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf0 , 1 , 485 , 240 , // 485 - lg-ug + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf4 , 1 , 487 , 240 , // 486 - lkt + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf4 , 1 , 487 , 240 , // 487 - lkt-us + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2c , 1 , 490 , 240 , // 488 - ln + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9 , 1 , 489 , 240 , // 489 - ln-ao + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2c , 1 , 490 , 240 , // 490 - ln-cd + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x37 , 1 , 491 , 240 , // 491 - ln-cf + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2b , 1 , 492 , 240 , // 492 - ln-cg + 0x54 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x8a , 1 , 494 , 143 , // 493 - lo + 0x454 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x8a , 1 , 494 , 143 , // 494 - lo-la + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x74 , 2 , 497 , 240 , // 495 - lrc + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x79 , 2 , 496 , 240 , // 496 - lrc-iq + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x74 , 2 , 497 , 240 , // 497 - lrc-ir + 0x27 , 0x4e9 , 0x307 , 0x272d, 0x1f4 , 0x8d , 1 , 499 , 499 , // 498 - lt + 0x427 , 0x4e9 , 0x307 , 0x272d, 0x1f4 , 0x8d , 1 , 499 , 499 , // 499 - lt-lt + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2c , 1 , 501 , 240 , // 500 - lu + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2c , 1 , 501 , 240 , // 501 - lu-cd + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 503 , 240 , // 502 - luo + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 503 , 240 , // 503 - luo-ke + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 505 , 240 , // 504 - luy + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 505 , 240 , // 505 - luy-ke + 0x26 , 0x4e9 , 0x307 , 0x272d, 0x1f4 , 0x8c , 1 , 507 , 507 , // 506 - lv + 0x426 , 0x4e9 , 0x307 , 0x272d, 0x1f4 , 0x8c , 1 , 507 , 507 , // 507 - lv-lv + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 509 , 240 , // 508 - mas + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 509 , 240 , // 509 - mas-ke + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 510 , 240 , // 510 - mas-tz + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 512 , 240 , // 511 - mer + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 512 , 240 , // 512 - mer-ke + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa0 , 1 , 514 , 240 , // 513 - mfe + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa0 , 1 , 514 , 240 , // 514 - mfe-mu + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x95 , 1 , 516 , 240 , // 515 - mg + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x95 , 1 , 516 , 240 , // 516 - mg-mg + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa8 , 1 , 518 , 240 , // 517 - mgh + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa8 , 1 , 518 , 240 , // 518 - mgh-mz + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 520 , 240 , // 519 - mgo + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 520 , 240 , // 520 - mgo-cm + 0x81 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xb7 , 1 , 522 , 522 , // 521 - mi + 0x481 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xb7 , 1 , 522 , 522 , // 522 - mi-nz + 0x2f , 0x4e3 , 0x362 , 0x2717, 0x1f4 , 0x4ca2, 1 , 524 , 524 , // 523 - mk + 0x42f , 0x4e3 , 0x362 , 0x2717, 0x1f4 , 0x4ca2, 1 , 524 , 524 , // 524 - mk-mk + 0x4c , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 526 , 143 , // 525 - ml + 0x44c , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 526 , 143 , // 526 - ml-in + 0x50 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0x9a , 1 , 529 , 529 , // 527 - mn + 0x7850 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0x9a , 1 , 529 , 529 , // 528 - mn-cyrl + 0x450 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0x9a , 1 , 529 , 529 , // 529 - mn-mn + 0x7c50 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2d , 1 , 531 , 531 , // 530 - mn-mong + 0x850 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2d , 1 , 531 , 531 , // 531 - mn-mong-cn + 0xc50 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9a , 1 , 532 , 532 , // 532 - mn-mong-mn + 0x58 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 534 , 187 , // 533 - mni + 0x458 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 534 , 187 , // 534 - mni-in + 0x7c , 0x4e4 , 0x352 , 0x2710, 0x25 , 0x27 , 1 , 536 , 240 , // 535 - moh + 0x47c , 0x4e4 , 0x352 , 0x2710, 0x25 , 0x27 , 1 , 536 , 240 , // 536 - moh-ca + 0x4e , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 538 , 143 , // 537 - mr + 0x44e , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 538 , 143 , // 538 - mr-in + 0x3e , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xa7 , 1 , 541 , 541 , // 539 - ms + 0x83e , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x25 , 1 , 540 , 540 , // 540 - ms-bn + 0x43e , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xa7 , 1 , 541 , 541 , // 541 - ms-my + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd7 , 1 , 542 , 240 , // 542 - ms-sg + 0x3a , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa3 , 1 , 544 , 544 , // 543 - mt + 0x43a , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa3 , 1 , 544 , 544 , // 544 - mt-mt + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 546 , 240 , // 545 - mua + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 546 , 240 , // 546 - mua-cm + 0x55 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x1b , 2 , 548 , 240 , // 547 - my + 0x455 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x1b , 2 , 548 , 240 , // 548 - my-mm + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x74 , 2 , 550 , 240 , // 549 - mzn + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x74 , 2 , 550 , 240 , // 550 - mzn-ir + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xfe , 1 , 552 , 240 , // 551 - naq + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xfe , 1 , 552 , 240 , // 552 - naq-na + 0x7c14 , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0xb1 , 1 , 554 , 554 , // 553 - nb + 0x414 , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0xb1 , 1 , 554 , 554 , // 554 - nb-no + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0xdc , 1 , 555 , 240 , // 555 - nb-sj + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x108 , 1 , 557 , 240 , // 556 - nd + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x108 , 1 , 557 , 240 , // 557 - nd-zw + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x5e , 1 , 559 , 240 , // 558 - nds + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x5e , 1 , 559 , 240 , // 559 - nds-de + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xb0 , 1 , 560 , 240 , // 560 - nds-nl + 0x61 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xb2 , 1 , 563 , 143 , // 561 - ne + 0x861 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 2 , 562 , 240 , // 562 - ne-in + 0x461 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xb2 , 1 , 563 , 143 , // 563 - ne-np + 0x13 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xb0 , 1 , 569 , 569 , // 564 - nl + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x12e , 1 , 565 , 240 , // 565 - nl-aw + 0x813 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x15 , 1 , 566 , 566 , // 566 - nl-be + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x9a55d42, 1 , 567 , 240 , // 567 - nl-bq + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x111 , 1 , 568 , 240 , // 568 - nl-cw + 0x413 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xb0 , 1 , 569 , 569 , // 569 - nl-nl + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xb5 , 1 , 570 , 240 , // 570 - nl-sr + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x78f7, 1 , 571 , 240 , // 571 - nl-sx + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 573 , 240 , // 572 - nmg + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 573 , 240 , // 573 - nmg-cm + 0x7814 , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0xb1 , 1 , 575 , 575 , // 574 - nn + 0x814 , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0xb1 , 1 , 575 , 575 , // 575 - nn-no + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 577 , 240 , // 576 - nnh + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 577 , 240 , // 577 - nnh-cm + 0x14 , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0xb1 , 1 , 554 , 554 , // 578 - no + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x64 , 2 , 580 , 143 , // 579 - nqo + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x64 , 2 , 580 , 143 , // 580 - nqo-gn + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd1 , 1 , 582 , 240 , // 581 - nr + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd1 , 1 , 582 , 240 , // 582 - nr-za + 0x6c , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd1 , 1 , 584 , 584 , // 583 - nso + 0x46c , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd1 , 1 , 584 , 584 , // 584 - nso-za + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x114 , 1 , 586 , 240 , // 585 - nus + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x114 , 1 , 586 , 240 , // 586 - nus-ss + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf0 , 1 , 588 , 240 , // 587 - nyn + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf0 , 1 , 588 , 240 , // 588 - nyn-ug + 0x82 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x54 , 1 , 590 , 590 , // 589 - oc + 0x482 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x54 , 1 , 590 , 590 , // 590 - oc-fr + 0x72 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 , 592 , 240 , // 591 - om + 0x472 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 , 592 , 240 , // 592 - om-et + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 593 , 240 , // 593 - om-ke + 0x48 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 595 , 143 , // 594 - or + 0x448 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 595 , 143 , // 595 - or-in + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x58 , 1 , 597 , 240 , // 596 - os + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x58 , 1 , 597 , 240 , // 597 - os-ge + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xcb , 1 , 598 , 240 , // 598 - os-ru + 0x46 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 602 , 143 , // 599 - pa + 0x7c46 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xbe , 2 , 601 , 143 , // 600 - pa-arab + 0x846 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xbe , 2 , 601 , 143 , // 601 - pa-arab-pk + 0x446 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 602 , 143 , // 602 - pa-in + 0x79 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x993248, 1 , 604 , 145 , // 603 - pap + 0x479 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x993248, 1 , 604 , 145 , // 604 - pap-029 + 0x15 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0xbf , 1 , 606 , 606 , // 605 - pl + 0x415 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0xbf , 1 , 606 , 606 , // 606 - pl-pl + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x989e, 1 , 608 , 240 , // 607 - prg + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x989e, 1 , 608 , 240 , // 608 - prg-001 + 0x8c , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x3 , 2 , 610 , 143 , // 609 - prs + 0x48c , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x3 , 2 , 610 , 143 , // 610 - prs-af + 0x63 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3 , 2 , 612 , 143 , // 611 - ps + 0x463 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3 , 2 , 612 , 143 , // 612 - ps-af + 0x16 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x20 , 1 , 615 , 615 , // 613 - pt + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x9 , 1 , 614 , 240 , // 614 - pt-ao + 0x416 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x20 , 1 , 615 , 615 , // 615 - pt-br + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xdf , 1 , 616 , 240 , // 616 - pt-ch + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x39 , 1 , 617 , 240 , // 617 - pt-cv + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x45 , 1 , 618 , 240 , // 618 - pt-gq + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xc4 , 1 , 619 , 240 , // 619 - pt-gw + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x93 , 1 , 620 , 240 , // 620 - pt-lu + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x97 , 1 , 621 , 240 , // 621 - pt-mo + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xa8 , 1 , 622 , 240 , // 622 - pt-mz + 0x816 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xc1 , 1 , 623 , 623 , // 623 - pt-pt + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xe9 , 1 , 624 , 240 , // 624 - pt-st + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x6f60e7, 1 , 625 , 240 , // 625 - pt-tl + 0x901 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x7c , 1 , 626 , 190 , // 626 - qps-latn-x-sh + 0x501 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0xf4 , 1 , 627 , 627 , // 627 - qps-ploc + 0x5fe , 0x3a4 , 0x3a4 , 0x2711, 0x4f42, 0x7a , 1 , 628 , 628 , // 628 - qps-ploca + 0x9ff , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xcd , 0 , 629 , 143 , // 629 - qps-plocm + 0x86 , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x63 , 1 , 632 , 632 , // 630 - quc + 0x7c86 , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x63 , 1 , 632 , 632 , // 631 - quc-latn + 0x486 , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x63 , 1 , 632 , 632 , // 632 - quc-latn-gt + 0x6b , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x1a , 1 , 634 , 634 , // 633 - quz + 0x46b , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x1a , 1 , 634 , 634 , // 634 - quz-bo + 0x86b , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x42 , 1 , 635 , 635 , // 635 - quz-ec + 0xc6b , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xbb , 1 , 636 , 636 , // 636 - quz-pe + 0x17 , 0x4e4 , 0x352 , 0x2710, 0x4f31, 0xdf , 1 , 638 , 638 , // 637 - rm + 0x417 , 0x4e4 , 0x352 , 0x2710, 0x4f31, 0xdf , 1 , 638 , 638 , // 638 - rm-ch + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x26 , 1 , 640 , 240 , // 639 - rn + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x26 , 1 , 640 , 240 , // 640 - rn-bi + 0x18 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0xc8 , 1 , 643 , 643 , // 641 - ro + 0x818 , 0x4e2 , 0x354 , 0x2 , 0x1f4 , 0x98 , 1 , 642 , 240 , // 642 - ro-md + 0x418 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0xc8 , 1 , 643 , 643 , // 643 - ro-ro + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 645 , 240 , // 644 - rof + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 645 , 240 , // 645 - rof-tz + 0x19 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xcb , 1 , 651 , 651 , // 646 - ru + 0x1000 , 0x4e3 , 0x362 , 0x2 , 0x1f4 , 0x1d , 1 , 647 , 240 , // 647 - ru-by + 0x1000 , 0x4e3 , 0x362 , 0x2 , 0x1f4 , 0x82 , 1 , 648 , 240 , // 648 - ru-kg + 0x1000 , 0x4e3 , 0x362 , 0x2 , 0x1f4 , 0x89 , 1 , 649 , 240 , // 649 - ru-kz + 0x819 , 0x4e3 , 0x362 , 0x2 , 0x1f4 , 0x98 , 1 , 650 , 240 , // 650 - ru-md + 0x419 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xcb , 1 , 651 , 651 , // 651 - ru-ru + 0x1000 , 0x4e3 , 0x362 , 0x2 , 0x1f4 , 0xf1 , 1 , 652 , 240 , // 652 - ru-ua + 0x87 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xcc , 1 , 654 , 654 , // 653 - rw + 0x487 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xcc , 1 , 654 , 654 , // 654 - rw-rw + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 656 , 240 , // 655 - rwk + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 656 , 240 , // 656 - rwk-tz + 0x4f , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 658 , 143 , // 657 - sa + 0x44f , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 658 , 143 , // 658 - sa-in + 0x85 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xcb , 1 , 660 , 660 , // 659 - sah + 0x485 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xcb , 1 , 660 , 660 , // 660 - sah-ru + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 662 , 240 , // 661 - saq + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 662 , 240 , // 662 - saq-ke + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 664 , 240 , // 663 - sbp + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 664 , 240 , // 664 - sbp-tz + 0x59 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xbe , 2 , 667 , 143 , // 665 - sd + 0x7c59 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xbe , 2 , 667 , 143 , // 666 - sd-arab + 0x859 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xbe , 2 , 667 , 143 , // 667 - sd-arab-pk + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 669 , 187 , // 668 - sd-deva + 0x459 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 669 , 187 , // 669 - sd-deva-in + 0x3b , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0xb1 , 1 , 672 , 672 , // 670 - se + 0xc3b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0x4d , 1 , 671 , 671 , // 671 - se-fi + 0x43b , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0xb1 , 1 , 672 , 672 , // 672 - se-no + 0x83b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0xdd , 1 , 673 , 673 , // 673 - se-se + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa8 , 1 , 675 , 240 , // 674 - seh + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa8 , 1 , 675 , 240 , // 675 - seh-mz + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9d , 1 , 677 , 240 , // 676 - ses + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9d , 1 , 677 , 240 , // 677 - ses-ml + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x37 , 1 , 679 , 240 , // 678 - sg + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x37 , 1 , 679 , 240 , // 679 - sg-cf + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 684 , 240 , // 680 - shi + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 682 , 240 , // 681 - shi-latn + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 682 , 240 , // 682 - shi-latn-ma + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 684 , 240 , // 683 - shi-tfng + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 684 , 240 , // 684 - shi-tfng-ma + 0x5b , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2a , 1 , 686 , 143 , // 685 - si + 0x45b , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2a , 1 , 686 , 143 , // 686 - si-lk + 0x1b , 0x4e2 , 0x354 , 0x272d, 0x5190, 0x8f , 1 , 688 , 688 , // 687 - sk + 0x41b , 0x4e2 , 0x354 , 0x272d, 0x5190, 0x8f , 1 , 688 , 688 , // 688 - sk-sk + 0x24 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0xd4 , 1 , 690 , 690 , // 689 - sl + 0x424 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0xd4 , 1 , 690 , 690 , // 690 - sl-si + 0x783b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0xdd , 1 , 693 , 693 , // 691 - sma + 0x183b , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0xb1 , 1 , 692 , 692 , // 692 - sma-no + 0x1c3b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0xdd , 1 , 693 , 693 , // 693 - sma-se + 0x7c3b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0xdd , 1 , 696 , 696 , // 694 - smj + 0x103b , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0xb1 , 1 , 695 , 695 , // 695 - smj-no + 0x143b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0xdd , 1 , 696 , 696 , // 696 - smj-se + 0x703b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0x4d , 1 , 698 , 698 , // 697 - smn + 0x243b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0x4d , 1 , 698 , 698 , // 698 - smn-fi + 0x743b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0x4d , 1 , 700 , 700 , // 699 - sms + 0x203b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0x4d , 1 , 700 , 700 , // 700 - sms-fi + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x108 , 1 , 703 , 240 , // 701 - sn + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x108 , 1 , 703 , 240 , // 702 - sn-latn + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x108 , 1 , 703 , 240 , // 703 - sn-latn-zw + 0x77 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd8 , 1 , 708 , 240 , // 704 - so + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3e , 1 , 705 , 240 , // 705 - so-dj + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 , 706 , 240 , // 706 - so-et + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 707 , 240 , // 707 - so-ke + 0x477 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd8 , 1 , 708 , 240 , // 708 - so-so + 0x1c , 0x4e2 , 0x354 , 0x272d, 0x5190, 0x6 , 1 , 710 , 710 , // 709 - sq + 0x41c , 0x4e2 , 0x354 , 0x272d, 0x5190, 0x6 , 1 , 710 , 710 , // 710 - sq-al + 0x1000 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0x4ca2, 1 , 711 , 240 , // 711 - sq-mk + 0x1000 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0x974941, 1 , 712 , 240 , // 712 - sq-xk + 0x7c1a , 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x10f , 1 , 724 , 724 , // 713 - sr + 0x6c1a , 0x4e3 , 0x357 , 0x2717, 0x5221, 0x10f , 1 , 718 , 718 , // 714 - sr-cyrl + 0x1c1a , 0x4e3 , 0x357 , 0x2717, 0x5221, 0x19 , 1 , 715 , 715 , // 715 - sr-cyrl-ba + 0xc1a , 0x4e3 , 0x357 , 0x2717, 0x5221, 0x10d , 1 , 716 , 716 , // 716 - sr-cyrl-cs + 0x301a , 0x4e3 , 0x357 , 0x2717, 0x5221, 0x10e , 1 , 717 , 717 , // 717 - sr-cyrl-me + 0x281a , 0x4e3 , 0x357 , 0x2717, 0x5221, 0x10f , 1 , 718 , 718 , // 718 - sr-cyrl-rs + 0x1000 , 0x4e3 , 0x357 , 0x2717, 0x5221, 0x974941, 1 , 719 , 240 , // 719 - sr-cyrl-xk + 0x701a , 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x10f , 1 , 724 , 724 , // 720 - sr-latn + 0x181a , 0x4e2 , 0x354 , 0x2762, 0x366 , 0x19 , 1 , 721 , 721 , // 721 - sr-latn-ba + 0x81a , 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x10d , 1 , 722 , 722 , // 722 - sr-latn-cs + 0x2c1a , 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x10e , 1 , 723 , 723 , // 723 - sr-latn-me + 0x241a , 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x10f , 1 , 724 , 724 , // 724 - sr-latn-rs + 0x1000 , 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x974941, 1 , 725 , 240 , // 725 - sr-latn-xk + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd1 , 1 , 728 , 240 , // 726 - ss + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x104 , 1 , 727 , 240 , // 727 - ss-sz + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd1 , 1 , 728 , 240 , // 728 - ss-za + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x47 , 1 , 730 , 240 , // 729 - ssy + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x47 , 1 , 730 , 240 , // 730 - ssy-er + 0x30 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd1 , 1 , 733 , 240 , // 731 - st + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x92 , 1 , 732 , 240 , // 732 - st-ls + 0x430 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd1 , 1 , 733 , 240 , // 733 - st-za + 0x1d , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0xdd , 1 , 737 , 737 , // 734 - sv + 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0x9906f5, 1 , 735 , 240 , // 735 - sv-ax + 0x81d , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0x4d , 1 , 736 , 736 , // 736 - sv-fi + 0x41d , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0xdd , 1 , 737 , 737 , // 737 - sv-se + 0x41 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0x81 , 1 , 740 , 740 , // 738 - sw + 0x1000 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0x2c , 1 , 739 , 740 , // 739 - sw-cd + 0x441 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0x81 , 1 , 740 , 740 , // 740 - sw-ke + 0x1000 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0xef , 1 , 741 , 240 , // 741 - sw-tz + 0x1000 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0xf0 , 1 , 742 , 240 , // 742 - sw-ug + 0x1000 , 0x0 , 0x1 , 0x0 , 0x1f4 , 0x2c , 1 , 744 , 240 , // 743 - swc + 0x1000 , 0x0 , 0x1 , 0x0 , 0x1f4 , 0x2c , 1 , 744 , 240 , // 744 - swc-cd + 0x5a , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xde , 1 , 746 , 143 , // 745 - syr + 0x45a , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xde , 1 , 746 , 143 , // 746 - syr-sy + 0x49 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 748 , 143 , // 747 - ta + 0x449 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 748 , 143 , // 748 - ta-in + 0x849 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2a , 1 , 749 , 143 , // 749 - ta-lk + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa7 , 1 , 750 , 240 , // 750 - ta-my + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd7 , 1 , 751 , 240 , // 751 - ta-sg + 0x4a , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 753 , 143 , // 752 - te + 0x44a , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 753 , 143 , // 753 - te-in + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf0 , 1 , 756 , 240 , // 754 - teo + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 755 , 240 , // 755 - teo-ke + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf0 , 1 , 756 , 240 , // 756 - teo-ug + 0x28 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xe4 , 1 , 759 , 759 , // 757 - tg + 0x7c28 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xe4 , 1 , 759 , 759 , // 758 - tg-cyrl + 0x428 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xe4 , 1 , 759 , 759 , // 759 - tg-cyrl-tj + 0x1e , 0x36a , 0x36a , 0x2725, 0x5166, 0xe3 , 1 , 761 , 143 , // 760 - th + 0x41e , 0x36a , 0x36a , 0x2725, 0x5166, 0xe3 , 1 , 761 , 143 , // 761 - th-th + 0x73 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x47 , 1 , 763 , 143 , // 762 - ti + 0x873 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x47 , 1 , 763 , 143 , // 763 - ti-er + 0x473 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 , 764 , 143 , // 764 - ti-et + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x47 , 1 , 766 , 240 , // 765 - tig + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x47 , 1 , 766 , 240 , // 766 - tig-er + 0x42 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0xee , 1 , 768 , 768 , // 767 - tk + 0x442 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0xee , 1 , 768 , 768 , // 768 - tk-tm + 0x32 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd1 , 1 , 771 , 771 , // 769 - tn + 0x832 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x13 , 1 , 770 , 770 , // 770 - tn-bw + 0x432 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd1 , 1 , 771 , 771 , // 771 - tn-za + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xe7 , 1 , 773 , 240 , // 772 - to + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xe7 , 1 , 773 , 240 , // 773 - to-to + 0x1f , 0x4e6 , 0x359 , 0x2761, 0x51a9, 0xeb , 1 , 776 , 776 , // 774 - tr + 0x1000 , 0x4e6 , 0x359 , 0x2761, 0x51a9, 0x3b , 1 , 775 , 240 , // 775 - tr-cy + 0x41f , 0x4e6 , 0x359 , 0x2761, 0x51a9, 0xeb , 1 , 776 , 776 , // 776 - tr-tr + 0x31 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd1 , 1 , 778 , 240 , // 777 - ts + 0x431 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd1 , 1 , 778 , 240 , // 778 - ts-za + 0x44 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xcb , 1 , 780 , 780 , // 779 - tt + 0x444 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xcb , 1 , 780 , 780 , // 780 - tt-ru + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xad , 1 , 782 , 240 , // 781 - twq + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xad , 1 , 782 , 240 , // 782 - twq-ne + 0x5f , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x4 , 1 , 787 , 787 , // 783 - tzm + 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x9f , 1 , 785 , 240 , // 784 - tzm-arab + 0x45f , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x9f , 1 , 785 , 240 , // 785 - tzm-arab-ma + 0x7c5f , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x4 , 1 , 787 , 787 , // 786 - tzm-latn + 0x85f , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x4 , 1 , 787 , 787 , // 787 - tzm-latn-dz + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 788 , 240 , // 788 - tzm-latn-ma + 0x785f , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 790 , 316 , // 789 - tzm-tfng + 0x105f , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 790 , 316 , // 790 - tzm-tfng-ma + 0x80 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x2d , 1 , 792 , 143 , // 791 - ug + 0x480 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x2d , 1 , 792 , 143 , // 792 - ug-cn + 0x22 , 0x4e3 , 0x362 , 0x2721, 0x1f4 , 0xf1 , 1 , 794 , 794 , // 793 - uk + 0x422 , 0x4e3 , 0x362 , 0x2721, 0x1f4 , 0xf1 , 1 , 794 , 794 , // 794 - uk-ua + 0x20 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xbe , 1 , 797 , 143 , // 795 - ur + 0x820 , 0x4e8 , 0x2d0 , 0x2 , 0x1f4 , 0x71 , 2 , 796 , 240 , // 796 - ur-in + 0x420 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xbe , 1 , 797 , 143 , // 797 - ur-pk + 0x43 , 0x4e6 , 0x359 , 0x272d, 0x1f4 , 0xf7 , 1 , 804 , 804 , // 798 - uz + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3 , 2 , 800 , 240 , // 799 - uz-arab + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3 , 2 , 800 , 240 , // 800 - uz-arab-af + 0x7843 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xf7 , 1 , 802 , 802 , // 801 - uz-cyrl + 0x843 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xf7 , 1 , 802 , 802 , // 802 - uz-cyrl-uz + 0x7c43 , 0x4e6 , 0x359 , 0x272d, 0x1f4 , 0xf7 , 1 , 804 , 804 , // 803 - uz-latn + 0x443 , 0x4e6 , 0x359 , 0x272d, 0x1f4 , 0xf7 , 1 , 804 , 804 , // 804 - uz-latn-uz + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x8e , 1 , 809 , 240 , // 805 - vai + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x8e , 1 , 807 , 240 , // 806 - vai-latn + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x8e , 1 , 807 , 240 , // 807 - vai-latn-lr + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x8e , 1 , 809 , 240 , // 808 - vai-vaii + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x8e , 1 , 809 , 240 , // 809 - vai-vaii-lr + 0x33 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd1 , 1 , 811 , 240 , // 810 - ve + 0x433 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd1 , 1 , 811 , 240 , // 811 - ve-za + 0x2a , 0x4ea , 0x4ea , 0x2710, 0x1f4 , 0xfb , 1 , 813 , 143 , // 812 - vi + 0x42a , 0x4ea , 0x4ea , 0x2710, 0x1f4 , 0xfb , 1 , 813 , 143 , // 813 - vi-vn + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x989e, 1 , 815 , 240 , // 814 - vo + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x989e, 1 , 815 , 240 , // 815 - vo-001 + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 817 , 240 , // 816 - vun + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 817 , 240 , // 817 - vun-tz + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xdf , 1 , 819 , 240 , // 818 - wae + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xdf , 1 , 819 , 240 , // 819 - wae-ch + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 , 821 , 240 , // 820 - wal + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 , 821 , 240 , // 821 - wal-et + 0x88 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xd2 , 1 , 823 , 823 , // 822 - wo + 0x488 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xd2 , 1 , 823 , 823 , // 823 - wo-sn + 0x1007f, 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xf4 , 1 , -1 , -1 , // 824 - x-iv_mathan + 0x34 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd1 , 1 , 826 , 826 , // 825 - xh + 0x434 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd1 , 1 , 826 , 826 , // 826 - xh-za + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf0 , 1 , 828 , 240 , // 827 - xog + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf0 , 1 , 828 , 240 , // 828 - xog-ug + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 830 , 240 , // 829 - yav + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 830 , 240 , // 830 - yav-cm + 0x3d , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x989e, 1 , 832 , 240 , // 831 - yi + 0x43d , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x989e, 1 , 832 , 240 , // 832 - yi-001 + 0x6a , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xaf , 1 , 835 , 835 , // 833 - yo + 0x1000 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0x1c , 1 , 834 , 240 , // 834 - yo-bj + 0x46a , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xaf , 1 , 835 , 835 , // 835 - yo-ng + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x68 , 1 , 837 , 240 , // 836 - yue + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x68 , 1 , 837 , 240 , // 837 - yue-hk + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 840 , 316 , // 838 - zgh + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 840 , 316 , // 839 - zgh-tfng + 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 840 , 316 , // 840 - zgh-tfng-ma + 0x7804 , 0x3a8 , 0x3a8 , 0x2718, 0x1f4 , 0x2d , 1 , 844 , 844 , // 841 - zh + 0x4 , 0x3a8 , 0x3a8 , 0x0 , 0x1f4 , 0x2d , 1 , 844 , 844 , // 842 - zh-chs + 0x7c04 , 0x3b6 , 0x3b6 , 0x0 , 0x1f4 , 0x68 , 1 , 851 , 851 , // 843 - zh-cht + 0x804 , 0x3a8 , 0x3a8 , 0x2718, 0x1f4 , 0x2d , 1 , 844 , 844 , // 844 - zh-cn + 0x50804, 0x3a8 , 0x3a8 , 0x2718, 0x1f4 , 0x2d , 1 , 844 , 844 , // 845 - zh-cn_phoneb + 0x20804, 0x3a8 , 0x3a8 , 0x2718, 0x1f4 , 0x2d , 1 , 844 , 844 , // 846 - zh-cn_stroke + 0x4 , 0x3a8 , 0x3a8 , 0x2718, 0x1f4 , 0x2d , 1 , 844 , 844 , // 847 - zh-hans + 0x1000 , 0x3a8 , 0x3a8 , 0x2718, 0x1f4 , 0x68 , 1 , 848 , 240 , // 848 - zh-hans-hk + 0x1000 , 0x3a8 , 0x3a8 , 0x2718, 0x1f4 , 0x97 , 1 , 849 , 240 , // 849 - zh-hans-mo + 0x7c04 , 0x3b6 , 0x3b6 , 0x2712, 0x1f4 , 0x68 , 1 , 851 , 851 , // 850 - zh-hant + 0xc04 , 0x3b6 , 0x3b6 , 0x2712, 0x1f4 , 0x68 , 1 , 851 , 851 , // 851 - zh-hk + 0x40c04, 0x3b6 , 0x3b6 , 0x2712, 0x1f4 , 0x68 , 1 , 851 , 851 , // 852 - zh-hk_radstr + 0x1404 , 0x3b6 , 0x3b6 , 0x2712, 0x1f4 , 0x97 , 1 , 853 , 853 , // 853 - zh-mo + 0x41404, 0x3b6 , 0x3b6 , 0x2712, 0x1f4 , 0x97 , 1 , 853 , 853 , // 854 - zh-mo_radstr + 0x21404, 0x3b6 , 0x3b6 , 0x2712, 0x1f4 , 0x97 , 1 , 853 , 853 , // 855 - zh-mo_stroke + 0x1004 , 0x3a8 , 0x3a8 , 0x2718, 0x1f4 , 0xd7 , 1 , 856 , 856 , // 856 - zh-sg + 0x51004, 0x3a8 , 0x3a8 , 0x2718, 0x1f4 , 0xd7 , 1 , 856 , 856 , // 857 - zh-sg_phoneb + 0x21004, 0x3a8 , 0x3a8 , 0x2718, 0x1f4 , 0xd7 , 1 , 856 , 856 , // 858 - zh-sg_stroke + 0x404 , 0x3b6 , 0x3b6 , 0x2712, 0x1f4 , 0xed , 1 , 859 , 859 , // 859 - zh-tw + 0x30404, 0x3b6 , 0x3b6 , 0x2712, 0x1f4 , 0xed , 1 , 859 , 859 , // 860 - zh-tw_pronun + 0x40404, 0x3b6 , 0x3b6 , 0x2712, 0x1f4 , 0xed , 1 , 859 , 859 , // 861 - zh-tw_radstr + 0x35 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd1 , 1 , 863 , 863 , // 862 - zu + 0x435 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd1 , 1 , 863 , 863 , // 863 - zu-za + }; + + // s_lcids list all supported lcids. used to binary search and we use the index of the matched lcid to + // get the index in s_localeNamesIndices using s_lcidToCultureNameIndices + private static readonly int[] s_lcids = new int[] + { + // Lcid , index - index in c_localeNames + 0x1 , // 0 - 52 + 0x2 , // 1 - 301 + 0x3 , // 2 - 421 + 0x4 , // 3 - 4139 + 0x5 , // 4 - 502 + 0x6 , // 5 - 523 + 0x7 , // 6 - 544 + 0x8 , // 7 - 664 + 0x9 , // 8 - 676 + 0xa , // 9 - 1214 + 0xb , // 10 - 1423 + 0xc , // 11 - 1451 + 0xd , // 12 - 1825 + 0xe , // 13 - 1860 + 0xf , // 14 - 1929 + 0x10 , // 15 - 1936 + 0x11 , // 16 - 1989 + 0x12 , // 17 - 2179 + 0x13 , // 18 - 2685 + 0x14 , // 19 - 2747 + 0x15 , // 20 - 2864 + 0x16 , // 21 - 2897 + 0x17 , // 22 - 3041 + 0x18 , // 23 - 3055 + 0x19 , // 24 - 3076 + 0x1a , // 25 - 1839 + 0x1b , // 26 - 3284 + 0x1c , // 27 - 3387 + 0x1d , // 28 - 3553 + 0x1e , // 29 - 3673 + 0x1f , // 30 - 3727 + 0x20 , // 31 - 3847 + 0x21 , // 32 - 1908 + 0x22 , // 33 - 3840 + 0x23 , // 34 - 276 + 0x24 , // 35 - 3291 + 0x25 , // 36 - 1354 + 0x26 , // 37 - 2429 + 0x27 , // 38 - 2397 + 0x28 , // 39 - 3654 + 0x29 , // 40 - 1377 + 0x2a , // 41 - 3960 + 0x2b , // 42 - 1879 + 0x2c , // 43 - 224 + 0x2d , // 44 - 1361 + 0x2e , // 45 - 1851 + 0x2f , // 46 - 2501 + 0x30 , // 47 - 3541 + 0x31 , // 48 - 3739 + 0x32 , // 49 - 3708 + 0x33 , // 50 - 3953 + 0x34 , // 51 - 4020 + 0x35 , // 52 - 4277 + 0x36 , // 53 - 17 + 0x37 , // 54 - 2062 + 0x38 , // 55 - 1439 + 0x39 , // 56 - 1832 + 0x3a , // 57 - 2598 + 0x3b , // 58 - 3194 + 0x3c , // 59 - 1705 + 0x3d , // 60 - 4045 + 0x3e , // 61 - 2581 + 0x3f , // 62 - 2133 + 0x40 , // 63 - 2306 + 0x41 , // 64 - 3570 + 0x42 , // 65 - 3701 + 0x43 , // 66 - 3859 + 0x44 , // 67 - 3746 + 0x45 , // 68 - 336 + 0x46 , // 69 - 2830 + 0x47 , // 70 - 1754 + 0x48 , // 71 - 2811 + 0x49 , // 72 - 3610 + 0x4a , // 73 - 3632 + 0x4b , // 74 - 2172 + 0x4c , // 75 - 2508 + 0x4d , // 76 - 199 + 0x4e , // 77 - 2574 + 0x4f , // 78 - 3124 + 0x50 , // 79 - 2515 + 0x51 , // 80 - 348 + 0x52 , // 81 - 516 + 0x53 , // 82 - 2165 + 0x54 , // 83 - 2375 + 0x55 , // 84 - 2614 + 0x56 , // 85 - 1719 + 0x57 , // 86 - 2191 + 0x58 , // 87 - 2556 + 0x59 , // 88 - 3158 + 0x5a , // 89 - 3601 + 0x5b , // 90 - 3277 + 0x5c , // 91 - 473 + 0x5d , // 92 - 1953 + 0x5e , // 93 - 45 + 0x5f , // 94 - 3762 + 0x60 , // 95 - 2207 + 0x61 , // 96 - 2673 + 0x62 , // 97 - 1698 + 0x63 , // 98 - 2890 + 0x64 , // 99 - 1430 + 0x65 , // 100 - 620 + 0x66 , // 101 - 308 + 0x67 , // 102 - 1384 + 0x68 , // 103 - 1777 + 0x69 , // 104 - 1899 + 0x6a , // 105 - 4053 + 0x6b , // 106 - 3020 + 0x6c , // 107 - 2765 + 0x6d , // 108 - 260 + 0x6e , // 109 - 2330 + 0x6f , // 110 - 2149 + 0x70 , // 111 - 1915 + 0x71 , // 112 - 2200 + 0x72 , // 113 - 2799 + 0x73 , // 114 - 3680 + 0x74 , // 115 - 1726 + 0x75 , // 116 - 1816 + 0x76 , // 117 - 2313 + 0x77 , // 118 - 3365 + 0x78 , // 119 - 1922 + 0x79 , // 120 - 2854 + 0x7a , // 121 - 190 + 0x7c , // 122 - 2565 + 0x7e , // 123 - 360 + 0x80 , // 124 - 3833 + 0x81 , // 125 - 2494 + 0x82 , // 126 - 2792 + 0x83 , // 127 - 495 + 0x84 , // 128 - 1733 + 0x85 , // 129 - 3131 + 0x86 , // 130 - 2998 + 0x87 , // 131 - 3108 + 0x88 , // 132 - 4002 + 0x8c , // 133 - 2881 + 0x91 , // 134 - 1712 + 0x92 , // 135 - 2270 + 0x401 , // 136 - 150 + 0x402 , // 137 - 303 + 0x403 , // 138 - 428 + 0x404 , // 139 - 4248 + 0x405 , // 140 - 504 + 0x406 , // 141 - 525 + 0x407 , // 142 - 561 + 0x408 , // 143 - 671 + 0x409 , // 144 - 1161 + 0x40a , // 145 - 1272 + 0x40b , // 146 - 1425 + 0x40c , // 147 - 1529 + 0x40d , // 148 - 1827 + 0x40e , // 149 - 1862 + 0x40f , // 150 - 1931 + 0x410 , // 151 - 1943 + 0x411 , // 152 - 1991 + 0x412 , // 153 - 2186 + 0x413 , // 154 - 2707 + 0x414 , // 155 - 2641 + 0x415 , // 156 - 2866 + 0x416 , // 157 - 2904 + 0x417 , // 158 - 3043 + 0x418 , // 159 - 3062 + 0x419 , // 160 - 3098 + 0x41a , // 161 - 1846 + 0x41b , // 162 - 3286 + 0x41c , // 163 - 3389 + 0x41d , // 164 - 3565 + 0x41e , // 165 - 3675 + 0x41f , // 166 - 3734 + 0x420 , // 167 - 3854 + 0x421 , // 168 - 1910 + 0x422 , // 169 - 3842 + 0x423 , // 170 - 278 + 0x424 , // 171 - 3293 + 0x425 , // 172 - 1356 + 0x426 , // 173 - 2431 + 0x427 , // 174 - 2399 + 0x428 , // 175 - 3663 + 0x429 , // 176 - 1379 + 0x42a , // 177 - 3962 + 0x42b , // 178 - 1881 + 0x42c , // 179 - 250 + 0x42d , // 180 - 1363 + 0x42e , // 181 - 1854 + 0x42f , // 182 - 2503 + 0x430 , // 183 - 3548 + 0x431 , // 184 - 3741 + 0x432 , // 185 - 3715 + 0x433 , // 186 - 3955 + 0x434 , // 187 - 4022 + 0x435 , // 188 - 4279 + 0x436 , // 189 - 24 + 0x437 , // 190 - 2064 + 0x438 , // 191 - 1446 + 0x439 , // 192 - 1834 + 0x43a , // 193 - 2600 + 0x43b , // 194 - 3201 + 0x43d , // 195 - 4047 + 0x43e , // 196 - 2588 + 0x43f , // 197 - 2135 + 0x440 , // 198 - 2308 + 0x441 , // 199 - 3577 + 0x442 , // 200 - 3703 + 0x443 , // 201 - 3902 + 0x444 , // 202 - 3748 + 0x445 , // 203 - 343 + 0x446 , // 204 - 2849 + 0x447 , // 205 - 1756 + 0x448 , // 206 - 2813 + 0x449 , // 207 - 3612 + 0x44a , // 208 - 3634 + 0x44b , // 209 - 2174 + 0x44c , // 210 - 2510 + 0x44d , // 211 - 201 + 0x44e , // 212 - 2576 + 0x44f , // 213 - 3126 + 0x450 , // 214 - 2524 + 0x451 , // 215 - 350 + 0x452 , // 216 - 518 + 0x453 , // 217 - 2167 + 0x454 , // 218 - 2377 + 0x455 , // 219 - 2616 + 0x456 , // 220 - 1721 + 0x457 , // 221 - 2194 + 0x458 , // 222 - 2559 + 0x459 , // 223 - 3184 + 0x45a , // 224 - 3604 + 0x45b , // 225 - 3279 + 0x45c , // 226 - 484 + 0x45d , // 227 - 1962 + 0x45e , // 228 - 47 + 0x45f , // 229 - 3773 + 0x460 , // 230 - 2209 + 0x461 , // 231 - 2680 + 0x462 , // 232 - 1700 + 0x463 , // 233 - 2892 + 0x464 , // 234 - 1433 + 0x465 , // 235 - 622 + 0x466 , // 236 - 311 + 0x467 , // 237 - 1418 + 0x468 , // 238 - 1806 + 0x469 , // 239 - 1902 + 0x46a , // 240 - 4060 + 0x46b , // 241 - 3023 + 0x46c , // 242 - 2768 + 0x46d , // 243 - 262 + 0x46e , // 244 - 2332 + 0x46f , // 245 - 2151 + 0x470 , // 246 - 1917 + 0x471 , // 247 - 2202 + 0x472 , // 248 - 2801 + 0x473 , // 249 - 3687 + 0x474 , // 250 - 1728 + 0x475 , // 251 - 1819 + 0x476 , // 252 - 2315 + 0x477 , // 253 - 3382 + 0x478 , // 254 - 1924 + 0x479 , // 255 - 2857 + 0x47a , // 256 - 193 + 0x47c , // 257 - 2568 + 0x47e , // 258 - 362 + 0x480 , // 259 - 3835 + 0x481 , // 260 - 2496 + 0x482 , // 261 - 2794 + 0x483 , // 262 - 497 + 0x484 , // 263 - 1742 + 0x485 , // 264 - 3134 + 0x486 , // 265 - 3009 + 0x487 , // 266 - 3110 + 0x488 , // 267 - 4004 + 0x48c , // 268 - 2884 + 0x491 , // 269 - 1714 + 0x492 , // 270 - 2279 + 0x501 , // 271 - 2972 + 0x5fe , // 272 - 2980 + 0x801 , // 273 - 95 + 0x803 , // 274 - 433 + 0x804 , // 275 - 4110 + 0x807 , // 276 - 556 + 0x809 , // 277 - 831 + 0x80a , // 278 - 1299 + 0x80c , // 279 - 1459 + 0x810 , // 280 - 1938 + 0x813 , // 281 - 2692 + 0x814 , // 282 - 2733 + 0x816 , // 283 - 2944 + 0x818 , // 284 - 3057 + 0x819 , // 285 - 3093 + 0x81a , // 286 - 3480 + 0x81d , // 287 - 3560 + 0x820 , // 288 - 3849 + 0x82c , // 289 - 233 + 0x82e , // 290 - 605 + 0x832 , // 291 - 3710 + 0x83b , // 292 - 3206 + 0x83c , // 293 - 1707 + 0x83e , // 294 - 2583 + 0x843 , // 295 - 3885 + 0x845 , // 296 - 338 + 0x846 , // 297 - 2839 + 0x849 , // 298 - 3617 + 0x850 , // 299 - 2536 + 0x859 , // 300 - 3167 + 0x85d , // 301 - 1979 + 0x85f , // 302 - 3792 + 0x860 , // 303 - 2233 + 0x861 , // 304 - 2675 + 0x867 , // 305 - 1403 + 0x86b , // 306 - 3029 + 0x873 , // 307 - 3682 + 0x901 , // 308 - 2959 + 0x9ff , // 309 - 2989 + 0xc01 , // 310 - 80 + 0xc04 , // 311 - 4173 + 0xc07 , // 312 - 546 + 0xc09 , // 313 - 716 + 0xc0a , // 314 - 1267 + 0xc0c , // 315 - 1484 + 0xc1a , // 316 - 3423 + 0xc3b , // 317 - 3196 + 0xc50 , // 318 - 2546 + 0xc51 , // 319 - 638 + 0xc6b , // 320 - 3035 + 0x1001 , // 321 - 120 + 0x1004 , // 322 - 4219 + 0x1007 , // 323 - 588 + 0x1009 , // 324 - 756 + 0x100a , // 325 - 1289 + 0x100c , // 326 - 1504 + 0x101a , // 327 - 1841 + 0x103b , // 328 - 3316 + 0x105f , // 329 - 3822 + 0x1401 , // 330 - 75 + 0x1404 , // 331 - 4190 + 0x1407 , // 332 - 583 + 0x1409 , // 333 - 1026 + 0x140a , // 334 - 1247 + 0x140c , // 335 - 1569 + 0x141a , // 336 - 402 + 0x143b , // 337 - 3322 + 0x1801 , // 338 - 125 + 0x1809 , // 339 - 881 + 0x180a , // 340 - 1309 + 0x180c , // 341 - 1579 + 0x181a , // 342 - 3470 + 0x183b , // 343 - 3301 + 0x1c01 , // 344 - 180 + 0x1c09 , // 345 - 1191 + 0x1c0a , // 346 - 1257 + 0x1c0c , // 347 - 1453 + 0x1c1a , // 348 - 3413 + 0x1c3b , // 349 - 3307 + 0x2001 , // 350 - 135 + 0x2009 , // 351 - 911 + 0x200a , // 352 - 1349 + 0x200c , // 353 - 1634 + 0x201a , // 354 - 385 + 0x203b , // 355 - 3340 + 0x2401 , // 356 - 185 + 0x2409 , // 357 - 684 + 0x240a , // 358 - 1242 + 0x240c , // 359 - 1489 + 0x241a , // 360 - 3500 + 0x243b , // 361 - 3331 + 0x2801 , // 362 - 170 + 0x2809 , // 363 - 751 + 0x280a , // 364 - 1314 + 0x280c , // 365 - 1649 + 0x281a , // 366 - 3443 + 0x2c01 , // 367 - 100 + 0x2c09 , // 368 - 1136 + 0x2c0a , // 369 - 1222 + 0x2c0c , // 370 - 1514 + 0x2c1a , // 371 - 3490 + 0x3001 , // 372 - 115 + 0x3009 , // 373 - 1201 + 0x300a , // 374 - 1262 + 0x300c , // 375 - 1509 + 0x301a , // 376 - 3433 + 0x3401 , // 377 - 110 + 0x3409 , // 378 - 1036 + 0x340a , // 379 - 1237 + 0x340c , // 380 - 1594 + 0x3801 , // 381 - 60 + 0x3809 , // 382 - 876 + 0x380a , // 383 - 1344 + 0x380c , // 384 - 1574 + 0x3c01 , // 385 - 65 + 0x3c09 , // 386 - 871 + 0x3c0a , // 387 - 1329 + 0x3c0c , // 388 - 1559 + 0x4001 , // 389 - 145 + 0x4009 , // 390 - 896 + 0x400a , // 391 - 1227 + 0x4409 , // 392 - 991 + 0x440a , // 393 - 1334 + 0x4809 , // 394 - 1086 + 0x480a , // 395 - 1294 + 0x4c0a , // 396 - 1304 + 0x500a , // 397 - 1324 + 0x540a , // 398 - 1339 + 0x580a , // 399 - 1216 + 0x5c0a , // 400 - 1252 + 0x641a , // 401 - 378 + 0x681a , // 402 - 395 + 0x6c1a , // 403 - 3406 + 0x701a , // 404 - 3463 + 0x703b , // 405 - 3328 + 0x742c , // 406 - 226 + 0x743b , // 407 - 3337 + 0x7804 , // 408 - 4096 + 0x7814 , // 409 - 2731 + 0x781a , // 410 - 376 + 0x782c , // 411 - 243 + 0x783b , // 412 - 3298 + 0x7843 , // 413 - 3878 + 0x7850 , // 414 - 2517 + 0x785d , // 415 - 1955 + 0x785f , // 416 - 3814 + 0x7c04 , // 417 - 4166 + 0x7c14 , // 418 - 2639 + 0x7c1a , // 419 - 3404 + 0x7c28 , // 420 - 3656 + 0x7c2e , // 421 - 602 + 0x7c3b , // 422 - 3313 + 0x7c43 , // 423 - 3895 + 0x7c46 , // 424 - 2832 + 0x7c50 , // 425 - 2529 + 0x7c59 , // 426 - 3160 + 0x7c5c , // 427 - 476 + 0x7c5d , // 428 - 1972 + 0x7c5f , // 429 - 3784 + 0x7c67 , // 430 - 1396 + 0x7c68 , // 431 - 1779 + 0x7c86 , // 432 - 3001 + 0x7c92 , // 433 - 2272 + 0x1007f, // 434 - 4009 + 0x10407, // 435 - 566 + 0x1040e, // 436 - 1867 + 0x10437, // 437 - 2069 + 0x20804, // 438 - 4127 + 0x21004, // 439 - 4236 + 0x21404, // 440 - 4207 + 0x30404, // 441 - 4253 + 0x40404, // 442 - 4265 + 0x40411, // 443 - 1996 + 0x40c04, // 444 - 4178 + 0x41404, // 445 - 4195 + 0x50804, // 446 - 4115 + 0x51004 // 447 - 4224 + }; + // each element in s_lcidToCultureNameIndices is index to s_localeNamesIndices + private static readonly int[] s_lcidToCultureNameIndices = new int[] + { + // Index to s_localeNamesIndices, index to this array - lcid - index to the c_localeNames + 13 , // 0 - 1 - 52 + 64 , // 1 - 2 - 301 + 88 , // 2 - 3 - 421 + 847 , // 3 - 4 - 4139 + 103 , // 4 - 5 - 502 + 109 , // 5 - 6 - 523 + 114 , // 6 - 7 - 544 + 140 , // 7 - 8 - 664 + 143 , // 8 - 9 - 676 + 251 , // 9 - a - 1214 + 293 , // 10 - b - 1423 + 300 , // 11 - c - 1451 + 377 , // 12 - d - 1825 + 386 , // 13 - e - 1860 + 402 , // 14 - f - 1929 + 404 , // 15 - 10 - 1936 + 413 , // 16 - 11 - 1989 + 452 , // 17 - 12 - 2179 + 564 , // 18 - 13 - 2685 + 578 , // 19 - 14 - 2747 + 605 , // 20 - 15 - 2864 + 613 , // 21 - 16 - 2897 + 637 , // 22 - 17 - 3041 + 641 , // 23 - 18 - 3055 + 646 , // 24 - 19 - 3076 + 381 , // 25 - 1a - 1839 + 687 , // 26 - 1b - 3284 + 709 , // 27 - 1c - 3387 + 734 , // 28 - 1d - 3553 + 760 , // 29 - 1e - 3673 + 774 , // 30 - 1f - 3727 + 795 , // 31 - 20 - 3847 + 396 , // 32 - 21 - 1908 + 793 , // 33 - 22 - 3840 + 58 , // 34 - 23 - 276 + 689 , // 35 - 24 - 3291 + 278 , // 36 - 25 - 1354 + 506 , // 37 - 26 - 2429 + 498 , // 38 - 27 - 2397 + 757 , // 39 - 28 - 3654 + 284 , // 40 - 29 - 1377 + 812 , // 41 - 2a - 3960 + 389 , // 42 - 2b - 1879 + 49 , // 43 - 2c - 224 + 280 , // 44 - 2d - 1361 + 384 , // 45 - 2e - 1851 + 523 , // 46 - 2f - 2501 + 731 , // 47 - 30 - 3541 + 777 , // 48 - 31 - 3739 + 769 , // 49 - 32 - 3708 + 810 , // 50 - 33 - 3953 + 825 , // 51 - 34 - 4020 + 862 , // 52 - 35 - 4277 + 4 , // 53 - 36 - 17 + 425 , // 54 - 37 - 2062 + 297 , // 55 - 38 - 1439 + 379 , // 56 - 39 - 1832 + 543 , // 57 - 3a - 2598 + 670 , // 58 - 3b - 3194 + 352 , // 59 - 3c - 1705 + 831 , // 60 - 3d - 4045 + 539 , // 61 - 3e - 2581 + 440 , // 62 - 3f - 2133 + 476 , // 63 - 40 - 2306 + 738 , // 64 - 41 - 3570 + 767 , // 65 - 42 - 3701 + 798 , // 66 - 43 - 3859 + 779 , // 67 - 44 - 3746 + 71 , // 68 - 45 - 336 + 599 , // 69 - 46 - 2830 + 364 , // 70 - 47 - 1754 + 594 , // 71 - 48 - 2811 + 747 , // 72 - 49 - 3610 + 752 , // 73 - 4a - 3632 + 450 , // 74 - 4b - 2172 + 525 , // 75 - 4c - 2508 + 43 , // 76 - 4d - 199 + 537 , // 77 - 4e - 2574 + 657 , // 78 - 4f - 3124 + 527 , // 79 - 50 - 2515 + 74 , // 80 - 51 - 348 + 107 , // 81 - 52 - 516 + 448 , // 82 - 53 - 2165 + 493 , // 83 - 54 - 2375 + 547 , // 84 - 55 - 2614 + 356 , // 85 - 56 - 1719 + 455 , // 86 - 57 - 2191 + 533 , // 87 - 58 - 2556 + 665 , // 88 - 59 - 3158 + 745 , // 89 - 5a - 3601 + 685 , // 90 - 5b - 3277 + 98 , // 91 - 5c - 473 + 408 , // 92 - 5d - 1953 + 11 , // 93 - 5e - 45 + 783 , // 94 - 5f - 3762 + 459 , // 95 - 60 - 2207 + 561 , // 96 - 61 - 2673 + 350 , // 97 - 62 - 1698 + 611 , // 98 - 63 - 2890 + 295 , // 99 - 64 - 1430 + 129 , // 100 - 65 - 620 + 66 , // 101 - 66 - 308 + 286 , // 102 - 67 - 1384 + 370 , // 103 - 68 - 1777 + 394 , // 104 - 69 - 1899 + 833 , // 105 - 6a - 4053 + 633 , // 106 - 6b - 3020 + 583 , // 107 - 6c - 2765 + 54 , // 108 - 6d - 260 + 482 , // 109 - 6e - 2330 + 444 , // 110 - 6f - 2149 + 398 , // 111 - 70 - 1915 + 457 , // 112 - 71 - 2200 + 591 , // 113 - 72 - 2799 + 762 , // 114 - 73 - 3680 + 358 , // 115 - 74 - 1726 + 375 , // 116 - 75 - 1816 + 478 , // 117 - 76 - 2313 + 704 , // 118 - 77 - 3365 + 400 , // 119 - 78 - 1922 + 603 , // 120 - 79 - 2854 + 41 , // 121 - 7a - 190 + 535 , // 122 - 7c - 2565 + 77 , // 123 - 7e - 360 + 791 , // 124 - 80 - 3833 + 521 , // 125 - 81 - 2494 + 589 , // 126 - 82 - 2792 + 101 , // 127 - 83 - 495 + 360 , // 128 - 84 - 1733 + 659 , // 129 - 85 - 3131 + 630 , // 130 - 86 - 2998 + 653 , // 131 - 87 - 3108 + 822 , // 132 - 88 - 4002 + 609 , // 133 - 8c - 2881 + 354 , // 134 - 91 - 1712 + 470 , // 135 - 92 - 2270 + 33 , // 136 - 401 - 150 + 65 , // 137 - 402 - 303 + 90 , // 138 - 403 - 428 + 859 , // 139 - 404 - 4248 + 104 , // 140 - 405 - 504 + 110 , // 141 - 406 - 525 + 118 , // 142 - 407 - 561 + 142 , // 143 - 408 - 671 + 240 , // 144 - 409 - 1161 + 263 , // 145 - 40a - 1272 + 294 , // 146 - 40b - 1425 + 316 , // 147 - 40c - 1529 + 378 , // 148 - 40d - 1827 + 387 , // 149 - 40e - 1862 + 403 , // 150 - 40f - 1931 + 406 , // 151 - 410 - 1943 + 414 , // 152 - 411 - 1991 + 454 , // 153 - 412 - 2186 + 569 , // 154 - 413 - 2707 + 554 , // 155 - 414 - 2641 + 606 , // 156 - 415 - 2866 + 615 , // 157 - 416 - 2904 + 638 , // 158 - 417 - 3043 + 643 , // 159 - 418 - 3062 + 651 , // 160 - 419 - 3098 + 383 , // 161 - 41a - 1846 + 688 , // 162 - 41b - 3286 + 710 , // 163 - 41c - 3389 + 737 , // 164 - 41d - 3565 + 761 , // 165 - 41e - 3675 + 776 , // 166 - 41f - 3734 + 797 , // 167 - 420 - 3854 + 397 , // 168 - 421 - 1910 + 794 , // 169 - 422 - 3842 + 59 , // 170 - 423 - 278 + 690 , // 171 - 424 - 3293 + 279 , // 172 - 425 - 1356 + 507 , // 173 - 426 - 2431 + 499 , // 174 - 427 - 2399 + 759 , // 175 - 428 - 3663 + 285 , // 176 - 429 - 1379 + 813 , // 177 - 42a - 3962 + 390 , // 178 - 42b - 1881 + 53 , // 179 - 42c - 250 + 281 , // 180 - 42d - 1363 + 385 , // 181 - 42e - 1854 + 524 , // 182 - 42f - 2503 + 733 , // 183 - 430 - 3548 + 778 , // 184 - 431 - 3741 + 771 , // 185 - 432 - 3715 + 811 , // 186 - 433 - 3955 + 826 , // 187 - 434 - 4022 + 863 , // 188 - 435 - 4279 + 6 , // 189 - 436 - 24 + 426 , // 190 - 437 - 2064 + 299 , // 191 - 438 - 1446 + 380 , // 192 - 439 - 1834 + 544 , // 193 - 43a - 2600 + 672 , // 194 - 43b - 3201 + 832 , // 195 - 43d - 4047 + 541 , // 196 - 43e - 2588 + 441 , // 197 - 43f - 2135 + 477 , // 198 - 440 - 2308 + 740 , // 199 - 441 - 3577 + 768 , // 200 - 442 - 3703 + 804 , // 201 - 443 - 3902 + 780 , // 202 - 444 - 3748 + 73 , // 203 - 445 - 343 + 602 , // 204 - 446 - 2849 + 365 , // 205 - 447 - 1756 + 595 , // 206 - 448 - 2813 + 748 , // 207 - 449 - 3612 + 753 , // 208 - 44a - 3634 + 451 , // 209 - 44b - 2174 + 526 , // 210 - 44c - 2510 + 44 , // 211 - 44d - 201 + 538 , // 212 - 44e - 2576 + 658 , // 213 - 44f - 3126 + 529 , // 214 - 450 - 2524 + 75 , // 215 - 451 - 350 + 108 , // 216 - 452 - 518 + 449 , // 217 - 453 - 2167 + 494 , // 218 - 454 - 2377 + 548 , // 219 - 455 - 2616 + 357 , // 220 - 456 - 1721 + 456 , // 221 - 457 - 2194 + 534 , // 222 - 458 - 2559 + 669 , // 223 - 459 - 3184 + 746 , // 224 - 45a - 3604 + 686 , // 225 - 45b - 3279 + 100 , // 226 - 45c - 484 + 410 , // 227 - 45d - 1962 + 12 , // 228 - 45e - 47 + 785 , // 229 - 45f - 3773 + 460 , // 230 - 460 - 2209 + 563 , // 231 - 461 - 2680 + 351 , // 232 - 462 - 1700 + 612 , // 233 - 463 - 2892 + 296 , // 234 - 464 - 1433 + 130 , // 235 - 465 - 622 + 67 , // 236 - 466 - 311 + 292 , // 237 - 467 - 1418 + 374 , // 238 - 468 - 1806 + 395 , // 239 - 469 - 1902 + 835 , // 240 - 46a - 4060 + 634 , // 241 - 46b - 3023 + 584 , // 242 - 46c - 2768 + 55 , // 243 - 46d - 262 + 483 , // 244 - 46e - 2332 + 445 , // 245 - 46f - 2151 + 399 , // 246 - 470 - 1917 + 458 , // 247 - 471 - 2202 + 592 , // 248 - 472 - 2801 + 764 , // 249 - 473 - 3687 + 359 , // 250 - 474 - 1728 + 376 , // 251 - 475 - 1819 + 479 , // 252 - 476 - 2315 + 708 , // 253 - 477 - 3382 + 401 , // 254 - 478 - 1924 + 604 , // 255 - 479 - 2857 + 42 , // 256 - 47a - 193 + 536 , // 257 - 47c - 2568 + 78 , // 258 - 47e - 362 + 792 , // 259 - 480 - 3835 + 522 , // 260 - 481 - 2496 + 590 , // 261 - 482 - 2794 + 102 , // 262 - 483 - 497 + 362 , // 263 - 484 - 1742 + 660 , // 264 - 485 - 3134 + 632 , // 265 - 486 - 3009 + 654 , // 266 - 487 - 3110 + 823 , // 267 - 488 - 4004 + 610 , // 268 - 48c - 2884 + 355 , // 269 - 491 - 1714 + 472 , // 270 - 492 - 2279 + 627 , // 271 - 501 - 2972 + 628 , // 272 - 5fe - 2980 + 22 , // 273 - 801 - 95 + 91 , // 274 - 803 - 433 + 844 , // 275 - 804 - 4110 + 117 , // 276 - 807 - 556 + 174 , // 277 - 809 - 831 + 267 , // 278 - 80a - 1299 + 302 , // 279 - 80c - 1459 + 405 , // 280 - 810 - 1938 + 566 , // 281 - 813 - 2692 + 575 , // 282 - 814 - 2733 + 623 , // 283 - 816 - 2944 + 642 , // 284 - 818 - 3057 + 650 , // 285 - 819 - 3093 + 722 , // 286 - 81a - 3480 + 736 , // 287 - 81d - 3560 + 796 , // 288 - 820 - 3849 + 51 , // 289 - 82c - 233 + 126 , // 290 - 82e - 605 + 770 , // 291 - 832 - 3710 + 673 , // 292 - 83b - 3206 + 353 , // 293 - 83c - 1707 + 540 , // 294 - 83e - 2583 + 802 , // 295 - 843 - 3885 + 72 , // 296 - 845 - 338 + 601 , // 297 - 846 - 2839 + 749 , // 298 - 849 - 3617 + 531 , // 299 - 850 - 2536 + 667 , // 300 - 859 - 3167 + 412 , // 301 - 85d - 1979 + 787 , // 302 - 85f - 3792 + 463 , // 303 - 860 - 2233 + 562 , // 304 - 861 - 2675 + 290 , // 305 - 867 - 1403 + 635 , // 306 - 86b - 3029 + 763 , // 307 - 873 - 3682 + 626 , // 308 - 901 - 2959 + 629 , // 309 - 9ff - 2989 + 19 , // 310 - c01 - 80 + 851 , // 311 - c04 - 4173 + 115 , // 312 - c07 - 546 + 151 , // 313 - c09 - 716 + 262 , // 314 - c0a - 1267 + 307 , // 315 - c0c - 1484 + 716 , // 316 - c1a - 3423 + 671 , // 317 - c3b - 3196 + 532 , // 318 - c50 - 2546 + 134 , // 319 - c51 - 638 + 636 , // 320 - c6b - 3035 + 27 , // 321 - 1001 - 120 + 856 , // 322 - 1004 - 4219 + 122 , // 323 - 1007 - 588 + 159 , // 324 - 1009 - 756 + 265 , // 325 - 100a - 1289 + 311 , // 326 - 100c - 1504 + 382 , // 327 - 101a - 1841 + 695 , // 328 - 103b - 3316 + 790 , // 329 - 105f - 3822 + 18 , // 330 - 1401 - 75 + 853 , // 331 - 1404 - 4190 + 121 , // 332 - 1407 - 583 + 213 , // 333 - 1409 - 1026 + 258 , // 334 - 140a - 1247 + 324 , // 335 - 140c - 1569 + 85 , // 336 - 141a - 402 + 696 , // 337 - 143b - 3322 + 28 , // 338 - 1801 - 125 + 184 , // 339 - 1809 - 881 + 269 , // 340 - 180a - 1309 + 326 , // 341 - 180c - 1579 + 721 , // 342 - 181a - 3470 + 692 , // 343 - 183b - 3301 + 39 , // 344 - 1c01 - 180 + 246 , // 345 - 1c09 - 1191 + 260 , // 346 - 1c0a - 1257 + 301 , // 347 - 1c0c - 1453 + 715 , // 348 - 1c1a - 3413 + 693 , // 349 - 1c3b - 3307 + 30 , // 350 - 2001 - 135 + 190 , // 351 - 2009 - 911 + 277 , // 352 - 200a - 1349 + 337 , // 353 - 200c - 1634 + 83 , // 354 - 201a - 385 + 700 , // 355 - 203b - 3340 + 40 , // 356 - 2401 - 185 + 145 , // 357 - 2409 - 684 + 257 , // 358 - 240a - 1242 + 308 , // 359 - 240c - 1489 + 724 , // 360 - 241a - 3500 + 698 , // 361 - 243b - 3331 + 37 , // 362 - 2801 - 170 + 158 , // 363 - 2809 - 751 + 270 , // 364 - 280a - 1314 + 340 , // 365 - 280c - 1649 + 718 , // 366 - 281a - 3443 + 23 , // 367 - 2c01 - 100 + 235 , // 368 - 2c09 - 1136 + 253 , // 369 - 2c0a - 1222 + 313 , // 370 - 2c0c - 1514 + 723 , // 371 - 2c1a - 3490 + 26 , // 372 - 3001 - 115 + 248 , // 373 - 3009 - 1201 + 261 , // 374 - 300a - 1262 + 312 , // 375 - 300c - 1509 + 717 , // 376 - 301a - 3433 + 25 , // 377 - 3401 - 110 + 215 , // 378 - 3409 - 1036 + 256 , // 379 - 340a - 1237 + 329 , // 380 - 340c - 1594 + 15 , // 381 - 3801 - 60 + 183 , // 382 - 3809 - 876 + 276 , // 383 - 380a - 1344 + 325 , // 384 - 380c - 1574 + 16 , // 385 - 3c01 - 65 + 182 , // 386 - 3c09 - 871 + 273 , // 387 - 3c0a - 1329 + 322 , // 388 - 3c0c - 1559 + 32 , // 389 - 4001 - 145 + 187 , // 390 - 4009 - 896 + 254 , // 391 - 400a - 1227 + 206 , // 392 - 4409 - 991 + 274 , // 393 - 440a - 1334 + 225 , // 394 - 4809 - 1086 + 266 , // 395 - 480a - 1294 + 268 , // 396 - 4c0a - 1304 + 272 , // 397 - 500a - 1324 + 275 , // 398 - 540a - 1339 + 252 , // 399 - 580a - 1216 + 259 , // 400 - 5c0a - 1252 + 82 , // 401 - 641a - 378 + 84 , // 402 - 681a - 395 + 714 , // 403 - 6c1a - 3406 + 720 , // 404 - 701a - 3463 + 697 , // 405 - 703b - 3328 + 50 , // 406 - 742c - 226 + 699 , // 407 - 743b - 3337 + 841 , // 408 - 7804 - 4096 + 574 , // 409 - 7814 - 2731 + 81 , // 410 - 781a - 376 + 52 , // 411 - 782c - 243 + 691 , // 412 - 783b - 3298 + 801 , // 413 - 7843 - 3878 + 528 , // 414 - 7850 - 2517 + 409 , // 415 - 785d - 1955 + 789 , // 416 - 785f - 3814 + 850 , // 417 - 7c04 - 4166 + 553 , // 418 - 7c14 - 2639 + 713 , // 419 - 7c1a - 3404 + 758 , // 420 - 7c28 - 3656 + 125 , // 421 - 7c2e - 602 + 694 , // 422 - 7c3b - 3313 + 803 , // 423 - 7c43 - 3895 + 600 , // 424 - 7c46 - 2832 + 530 , // 425 - 7c50 - 2529 + 666 , // 426 - 7c59 - 3160 + 99 , // 427 - 7c5c - 476 + 411 , // 428 - 7c5d - 1972 + 786 , // 429 - 7c5f - 3784 + 289 , // 430 - 7c67 - 1396 + 371 , // 431 - 7c68 - 1779 + 631 , // 432 - 7c86 - 3001 + 471 , // 433 - 7c92 - 2272 + 824 , // 434 - 1007f - 4009 + 119 , // 435 - 10407 - 566 + 388 , // 436 - 1040e - 1867 + 427 , // 437 - 10437 - 2069 + 846 , // 438 - 20804 - 4127 + 858 , // 439 - 21004 - 4236 + 855 , // 440 - 21404 - 4207 + 860 , // 441 - 30404 - 4253 + 861 , // 442 - 40404 - 4265 + 415 , // 443 - 40411 - 1996 + 852 , // 444 - 40c04 - 4178 + 854 , // 445 - 41404 - 4195 + 845 , // 446 - 50804 - 4115 + 857 // 447 - 51004 - 4224 + }; + + internal static string LCIDToLocaleName(int culture) + { + int left = 0; + int right = s_lcids.Length - 1; + int index; + + Debug.Assert(s_lcids.Length == s_lcidToCultureNameIndices.Length); + + while (left <= right) + { + index = (right + left) / 2; + + if (culture == s_lcids[index]) + { + int indexToLocaleNamesIndices = s_lcidToCultureNameIndices[index]; + Debug.Assert(indexToLocaleNamesIndices < s_localeNamesIndices.Length - 1); + + return c_localeNames.Substring(s_localeNamesIndices[indexToLocaleNamesIndices], + s_localeNamesIndices[indexToLocaleNamesIndices + 1] - + s_localeNamesIndices[indexToLocaleNamesIndices]); + } + else if (culture < s_lcids[index]) + { + right = index - 1; + } + else + { + left = index + 1; + } + } + + return null; + } + + internal static int GetLocaleDataNumericPart(string cultureName, LocaleDataParts part) + { + int index = SearchCultureName(cultureName); + if (index < 0) + { + return -1; + } + + Debug.Assert((s_localeNamesIndices.Length-1 == (s_nameIndexToNumericData.Length/NUMERIC_LOCALE_DATA_COUNT_PER_ROW)) && + index < s_localeNamesIndices.Length); + + return s_nameIndexToNumericData[index * NUMERIC_LOCALE_DATA_COUNT_PER_ROW + (int) part]; + } + + internal static string GetThreeLetterWindowsLangageName(string cultureName) + { + int index = SearchCultureName(cultureName); + if (index < 0) + { + return null; + } + + Debug.Assert(s_localeNamesIndices.Length-1 == (c_threeLetterWindowsLanguageName.Length / 3)); + return c_threeLetterWindowsLanguageName.Substring(index * 3, 3); + } + + internal static string GetLocaleDataMappedCulture(string cultureName, LocaleDataParts part) + { + int indexToIndicesTable = GetLocaleDataNumericPart(cultureName, part); + if (indexToIndicesTable < 0) + { + return ""; // fallback to invariant + } + + Debug.Assert(indexToIndicesTable < s_localeNamesIndices.Length-1); + + return c_localeNames.Substring(s_localeNamesIndices[indexToIndicesTable], + s_localeNamesIndices[indexToIndicesTable+1] - s_localeNamesIndices[indexToIndicesTable]); + } + + internal static string GetSpecificCultureName(string cultureName) + { + return GetLocaleDataMappedCulture(cultureName, LocaleDataParts.SpecificLocaleIndex); + } + + internal static string GetConsoleUICulture(string cultureName) + { + return GetLocaleDataMappedCulture(cultureName, LocaleDataParts.ConsoleLocaleIndex); + } + + // SearchCultureName will binary search c_localeNames using s_localeNamesIndices. + // return index in s_localeNamesIndices, or -1 if it fail finding any match + private static int SearchCultureName(string name) + { + int left = 0; + int right = s_localeNamesIndices.Length - 2; + int index; + int result; + + Debug.Assert(s_localeNamesIndices[s_localeNamesIndices.Length - 1] == c_localeNames.Length); + + name = CultureData.AnsiToLower(name); + + // Binary search the array until we have only a couple of elements left and then + // just walk those elements. + while ((right - left) > 3) + { + index = ((right - left) / 2) + left; + + Debug.Assert(index < s_localeNamesIndices.Length - 1); + result = CompareOrdinal(name, c_localeNames, s_localeNamesIndices[index], s_localeNamesIndices[index + 1] - s_localeNamesIndices[index]); + if (result == 0) + { + return index; + } + else if (result < 0) + { + right = index; + } + else + { + left = index; + } + } + + // Walk the remaining elements (it'll be 3 or fewer). + for (; left <= right; left++) + { + Debug.Assert(left < s_localeNamesIndices.Length - 1); + if (CompareOrdinal(name, c_localeNames, s_localeNamesIndices[left], s_localeNamesIndices[left + 1] - s_localeNamesIndices[left]) == 0) + { + return (left); + } + } + + // couldn't find culture name + return -1; + } + + // optimized to avoid parameters checking + private static int CompareOrdinal(string s1, string s2, int index, int length) + { + int count = s1.Length; + if (count > length) + count = length; + + int i = 0; + while (i < count && s1[i] == s2[index + i]) + i++; + + if (i < count) + return (int)(s1[i] - s2[index + i]); + + return s1.Length - length; + } + } +} diff --git a/src/mscorlib/corefx/System/Globalization/NumberFormatInfo.cs b/src/mscorlib/corefx/System/Globalization/NumberFormatInfo.cs index 6a25eb2..813554f 100644 --- a/src/mscorlib/corefx/System/Globalization/NumberFormatInfo.cs +++ b/src/mscorlib/corefx/System/Globalization/NumberFormatInfo.cs @@ -42,8 +42,7 @@ namespace System.Globalization // [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] - sealed public partial class NumberFormatInfo : IFormatProvider, ICloneable + sealed public class NumberFormatInfo : IFormatProvider, ICloneable { // invariantInfo is constant irrespective of your current culture. private static volatile NumberFormatInfo s_invariantInfo; @@ -84,6 +83,8 @@ namespace System.Globalization internal int percentNegativePattern = 0; internal int percentDecimalDigits = 2; + [OptionalField(VersionAdded = 2)] + internal int digitSubstitution = (int) DigitShapes.None; internal bool isReadOnly = false; @@ -130,6 +131,64 @@ namespace System.Globalization Contract.EndContractBlock(); } + private static void VerifyNativeDigits(string [] nativeDig, string propertyName) + { + if (nativeDig == null) + { + throw new ArgumentNullException(propertyName, SR.ArgumentNull_Array); + } + + if (nativeDig.Length != 10) + { + throw new ArgumentException(SR.Argument_InvalidNativeDigitCount, propertyName); + } + Contract.EndContractBlock(); + + for (int i = 0; i < nativeDig.Length; i++) + { + if (nativeDig[i] == null) + { + throw new ArgumentNullException(propertyName, SR.ArgumentNull_ArrayValue); + } + + if (nativeDig[i].Length != 1) + { + if (nativeDig[i].Length != 2) + { + // Not 1 or 2 UTF-16 code points + throw new ArgumentException(SR.Argument_InvalidNativeDigitValue, propertyName); + } + else if (!char.IsSurrogatePair(nativeDig[i][0], nativeDig[i][1])) + { + // 2 UTF-6 code points, but not a surrogate pair + throw new ArgumentException(SR.Argument_InvalidNativeDigitValue, propertyName); + } + } + + if (CharUnicodeInfo.GetDecimalDigitValue(nativeDig[i], 0) != i && + CharUnicodeInfo.GetUnicodeCategory(nativeDig[i], 0) != UnicodeCategory.PrivateUse) + { + // Not the appropriate digit according to the Unicode data properties + // (Digit 0 must be a 0, etc.). + throw new ArgumentException(SR.Argument_InvalidNativeDigitValue, propertyName); + } + } + } + + private static void VerifyDigitSubstitution(DigitShapes digitSub, string propertyName) + { + switch (digitSub) + { + case DigitShapes.Context: + case DigitShapes.None: + case DigitShapes.NativeNational: + // Success. + break; + + default: + throw new ArgumentException(SR.Argument_InvalidDigitSubstitution, propertyName); + } + } internal NumberFormatInfo(CultureData cultureData) { @@ -748,6 +807,28 @@ namespace System.Globalization } } + public string [] NativeDigits + { + get { return (String[]) nativeDigits.Clone(); } + set + { + VerifyWritable(); + VerifyNativeDigits(value, "NativeDigits"); + nativeDigits = value; + } + } + + public DigitShapes DigitSubstitution + { + get { return (DigitShapes) digitSubstitution; } + set + { + VerifyWritable(); + VerifyDigitSubstitution(value, "DigitSubstitution"); + digitSubstitution = (int) value; + } + } + public Object GetFormat(Type formatType) { return formatType == typeof(NumberFormatInfo) ? this : null; @@ -757,7 +838,7 @@ namespace System.Globalization { if (nfi == null) { - throw new ArgumentNullException("nfi"); + throw new ArgumentNullException(nameof(nfi)); } Contract.EndContractBlock(); if (nfi.IsReadOnly) @@ -781,7 +862,7 @@ namespace System.Globalization // Check for undefined flags if ((style & InvalidNumberStyles) != 0) { - throw new ArgumentException(SR.Argument_InvalidNumberStyles, "style"); + throw new ArgumentException(SR.Argument_InvalidNumberStyles, nameof(style)); } Contract.EndContractBlock(); if ((style & NumberStyles.AllowHexSpecifier) != 0) @@ -798,7 +879,7 @@ namespace System.Globalization // Check for undefined flags if ((style & InvalidNumberStyles) != 0) { - throw new ArgumentException(SR.Argument_InvalidNumberStyles, "style"); + throw new ArgumentException(SR.Argument_InvalidNumberStyles, nameof(style)); } Contract.EndContractBlock(); if ((style & NumberStyles.AllowHexSpecifier) != 0) diff --git a/src/mscorlib/corefx/System/Globalization/PersianCalendar.cs b/src/mscorlib/corefx/System/Globalization/PersianCalendar.cs index 57bef7e..b8b3da6 100644 --- a/src/mscorlib/corefx/System/Globalization/PersianCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/PersianCalendar.cs @@ -2,7 +2,7 @@ // 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.Diagnostics; using System.Diagnostics.Contracts; namespace System.Globalization @@ -65,15 +65,13 @@ namespace System.Globalization } } - // Return the type of the Persian calendar. - // - - - //public override CalendarAlgorithmType AlgorithmType { - // get { - // return CalendarAlgorithmType.SolarCalendar; - // } - //} + public override CalendarAlgorithmType AlgorithmType + { + get + { + return CalendarAlgorithmType.SolarCalendar; + } + } // Construct an instance of Persian calendar. @@ -138,7 +136,7 @@ namespace System.Globalization { if (era != CurrentEra && era != PersianEra) { - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } } @@ -148,7 +146,7 @@ namespace System.Globalization if (year < 1 || year > MaxCalendarYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -165,7 +163,7 @@ namespace System.Globalization if (month > MaxCalendarMonth) { throw new ArgumentOutOfRangeException( - "month", + nameof(month), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -176,13 +174,13 @@ namespace System.Globalization if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException("month", SR.ArgumentOutOfRange_Month); + throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); } } private static int MonthFromOrdinalDay(int ordinalDay) { - Contract.Assert(ordinalDay <= 366); + Debug.Assert(ordinalDay <= 366); int index = 0; while (ordinalDay > DaysToMonth[index]) index++; @@ -192,7 +190,7 @@ namespace System.Globalization private static int DaysInPreviousMonths(int month) { - Contract.Assert(1 <= month && month <= 12); + Debug.Assert(1 <= month && month <= 12); --month; // months are one based but for calculations use 0 based return DaysToMonth[month]; } @@ -223,7 +221,7 @@ namespace System.Globalization long yearStart = CalendricalCalculationsHelper.PersianNewYearOnOrBefore(NumDays); int y = (int)(Math.Floor(((yearStart - PersianEpoch) / CalendricalCalculationsHelper.MeanTropicalYearInDays) + 0.5)) + 1; - Contract.Assert(y >= 1); + Debug.Assert(y >= 1); if (part == DatePartYear) { @@ -242,16 +240,16 @@ namespace System.Globalization } int m = MonthFromOrdinalDay(ordinalDay); - Contract.Assert(ordinalDay >= 1); - Contract.Assert(m >= 1 && m <= 12); + Debug.Assert(ordinalDay >= 1); + Debug.Assert(m >= 1 && m <= 12); if (part == DatePartMonth) { return m; } int d = ordinalDay - DaysInPreviousMonths(m); - Contract.Assert(1 <= d); - Contract.Assert(d <= 31); + Debug.Assert(1 <= d); + Debug.Assert(d <= 31); // // Calculate the Persian Day. @@ -290,7 +288,7 @@ namespace System.Globalization if (months < -120000 || months > 120000) { throw new ArgumentOutOfRangeException( - "months", + nameof(months), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -387,7 +385,7 @@ namespace System.Globalization int daysInMonth = DaysToMonth[month] - DaysToMonth[month - 1]; if ((month == MonthsPerYear) && !IsLeapYear(year)) { - Contract.Assert(daysInMonth == 30); + Debug.Assert(daysInMonth == 30); --daysInMonth; } return daysInMonth; @@ -471,7 +469,7 @@ namespace System.Globalization if (day < 1 || day > daysInMonth) { throw new ArgumentOutOfRangeException( - "day", + nameof(day), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Day, @@ -531,7 +529,7 @@ namespace System.Globalization { // BCLDebug.Log("year = " + year + ", month = " + month + ", day = " + day); throw new ArgumentOutOfRangeException( - "day", + nameof(day), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Day, @@ -570,7 +568,7 @@ namespace System.Globalization if (value < 99 || value > MaxCalendarYear) { throw new ArgumentOutOfRangeException( - "value", + nameof(value), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -587,7 +585,7 @@ namespace System.Globalization { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); @@ -600,7 +598,7 @@ namespace System.Globalization if (year > MaxCalendarYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, diff --git a/src/mscorlib/corefx/System/Globalization/RegionInfo.cs b/src/mscorlib/corefx/System/Globalization/RegionInfo.cs index 0669349..0645ded 100644 --- a/src/mscorlib/corefx/System/Globalization/RegionInfo.cs +++ b/src/mscorlib/corefx/System/Globalization/RegionInfo.cs @@ -14,15 +14,14 @@ // //////////////////////////////////////////////////////////////////////////// -using System; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.Serialization; namespace System.Globalization { [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] - public partial class RegionInfo + public class RegionInfo { //--------------------------------------------------------------------// // Internal Information // @@ -61,11 +60,11 @@ namespace System.Globalization public RegionInfo(String name) { if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); if (name.Length == 0) //The InvariantCulture has no matching region { - throw new ArgumentException(SR.Argument_NoRegionInvariantCulture, "name"); + throw new ArgumentException(SR.Argument_NoRegionInvariantCulture, nameof(name)); } Contract.EndContractBlock(); @@ -78,16 +77,46 @@ namespace System.Globalization throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, - SR.Argument_InvalidCultureName, name), "name"); + SR.Argument_InvalidCultureName, name), nameof(name)); // Not supposed to be neutral if (_cultureData.IsNeutralCulture) - throw new ArgumentException(SR.Format(SR.Argument_InvalidNeutralRegionName, name), "name"); + throw new ArgumentException(SR.Format(SR.Argument_InvalidNeutralRegionName, name), nameof(name)); SetName(name); } + [System.Security.SecuritySafeCritical] // auto-generated + public RegionInfo(int culture) + { + if (culture == CultureInfo.LOCALE_INVARIANT) //The InvariantCulture has no matching region + { + throw new ArgumentException(SR.Argument_NoRegionInvariantCulture); + } + + if (culture == CultureInfo.LOCALE_NEUTRAL) + { + // Not supposed to be neutral + throw new ArgumentException(SR.Format(SR.Argument_CultureIsNeutral, culture), nameof(culture)); + } + + if (culture == CultureInfo.LOCALE_CUSTOM_DEFAULT) + { + // Not supposed to be neutral + throw new ArgumentException(SR.Format(SR.Argument_CustomCultureCannotBePassedByNumber, culture), nameof(culture)); + } + + _cultureData = CultureData.GetCultureData(culture, true); + _name = _cultureData.SREGIONNAME; + + if (_cultureData.IsNeutralCulture) + { + // Not supposed to be neutral + throw new ArgumentException(SR.Format(SR.Argument_CultureIsNeutral, culture), nameof(culture)); + } + } + internal RegionInfo(CultureData cultureData) { _cultureData = cultureData; @@ -156,7 +185,7 @@ namespace System.Globalization { get { - Contract.Assert(_name != null, "Expected RegionInfo._name to be populated already"); + Debug.Assert(_name != null, "Expected RegionInfo._name to be populated already"); return (_name); } } @@ -202,7 +231,6 @@ namespace System.Globalization // WARNING: You need a full locale name for this to make sense. // //////////////////////////////////////////////////////////////////////// - [System.Runtime.InteropServices.ComVisible(false)] public virtual String NativeName { get @@ -228,6 +256,38 @@ namespace System.Globalization //////////////////////////////////////////////////////////////////////// // + // ThreeLetterISORegionName + // + // Returns the three letter ISO region name (ie: USA) + // + //////////////////////////////////////////////////////////////////////// + public virtual String ThreeLetterISORegionName + { + get + { + return (_cultureData.SISO3166CTRYNAME2); + } + } + + //////////////////////////////////////////////////////////////////////// + // + // ThreeLetterWindowsRegionName + // + // Returns the three letter windows region name (ie: USA) + // + //////////////////////////////////////////////////////////////////////// + public virtual String ThreeLetterWindowsRegionName + { + get + { + // ThreeLetterWindowsRegionName is really same as ThreeLetterISORegionName + return ThreeLetterISORegionName; + } + } + + + //////////////////////////////////////////////////////////////////////// + // // IsMetric // // Returns true if this region uses the metric measurement system @@ -242,6 +302,45 @@ namespace System.Globalization } } + public virtual int GeoId + { + get + { + return (_cultureData.IGEOID); + } + } + + //////////////////////////////////////////////////////////////////////// + // + // CurrencyEnglishName + // + // English name for this region's currency, ie: Swiss Franc + // + //////////////////////////////////////////////////////////////////////// + public virtual string CurrencyEnglishName + { + get + { + return (_cultureData.SENGLISHCURRENCY); + } + } + + //////////////////////////////////////////////////////////////////////// + // + // CurrencyNativeName + // + // Native name for this region's currency, ie: Schweizer Franken + // WARNING: You need a full locale name for this to make sense. + // + //////////////////////////////////////////////////////////////////////// + public virtual string CurrencyNativeName + { + get + { + return (_cultureData.SNATIVECURRENCY); + } + } + //////////////////////////////////////////////////////////////////////// // // CurrencySymbol diff --git a/src/mscorlib/corefx/System/Globalization/STUBS.cs b/src/mscorlib/corefx/System/Globalization/STUBS.cs deleted file mode 100644 index 8c85e83..0000000 --- a/src/mscorlib/corefx/System/Globalization/STUBS.cs +++ /dev/null @@ -1,180 +0,0 @@ -namespace System.Globalization -{ - public abstract partial class Calendar : System.ICloneable - { - [System.Runtime.InteropServices.ComVisibleAttribute(false)] - public virtual int GetLeapMonth(int year) { throw new NotImplementedException(); } - } - - [System.Runtime.InteropServices.ComVisible(true)] - public enum CalendarAlgorithmType - { - Unknown = 0, // This is the default value to return in the Calendar base class. - SolarCalendar = 1, // Solar-base calendar, such as GregorianCalendar, jaoaneseCalendar, JulianCalendar, etc. - // Solar calendars are based on the solar year and seasons. - LunarCalendar = 2, // Lunar-based calendar, such as Hijri and UmAlQuraCalendar. - // Lunar calendars are based on the path of the moon. The seasons are not accurately represented. - LunisolarCalendar = 3 // Lunisolar-based calendar which use leap month rule, such as HebrewCalendar and Asian Lunisolar calendars. - // Lunisolar calendars are based on the cycle of the moon, but consider the seasons as a secondary consideration, - // so they align with the seasons as well as lunar events. - } - - public static partial class CharUnicodeInfo - { - public static int GetDecimalDigitValue(char ch) { throw new NotImplementedException(); } - public static int GetDecimalDigitValue(string s, int index) { throw new NotImplementedException(); } - public static int GetDigitValue(char ch) { throw new NotImplementedException(); } - public static int GetDigitValue(string s, int index) { throw new NotImplementedException(); } - } - - public partial class CompareInfo : System.Runtime.Serialization.IDeserializationCallback - { - public int LCID { get { throw new NotImplementedException(); } } - public static System.Globalization.CompareInfo GetCompareInfo(int culture) { throw new NotImplementedException(); } - public static System.Globalization.CompareInfo GetCompareInfo(int culture, System.Reflection.Assembly assembly) { throw new NotImplementedException(); } - public static System.Globalization.CompareInfo GetCompareInfo(string name, System.Reflection.Assembly assembly) { throw new NotImplementedException(); } - public virtual System.Globalization.SortKey GetSortKey(string source) { throw new NotImplementedException(); } - public virtual System.Globalization.SortKey GetSortKey(string source, System.Globalization.CompareOptions options) { throw new NotImplementedException(); } - public virtual int IndexOf(string source, char value, int startIndex) { throw new NotImplementedException(); } - public virtual int IndexOf(string source, string value, int startIndex) { throw new NotImplementedException(); } - [System.Runtime.InteropServices.ComVisibleAttribute(false)] - public static bool IsSortable(char ch) { throw new NotImplementedException(); } - [System.Runtime.InteropServices.ComVisibleAttribute(false)] - [System.Security.SecuritySafeCriticalAttribute] - public static bool IsSortable(string text) { throw new NotImplementedException(); } - public virtual int LastIndexOf(string source, char value, int startIndex) { throw new NotImplementedException(); } - public virtual int LastIndexOf(string source, string value, int startIndex) { throw new NotImplementedException(); } - } - - public partial class CultureInfo : System.ICloneable, System.IFormatProvider - { - public CultureInfo(int culture) { throw new NotImplementedException(); } - public CultureInfo(int culture, bool useUserOverride) { throw new NotImplementedException(); } - public static System.Globalization.CultureInfo InstalledUICulture { get { throw new NotImplementedException(); } } - public virtual int LCID { get { throw new NotImplementedException(); } } - public virtual string ThreeLetterISOLanguageName { get { throw new NotImplementedException(); } } - public virtual string ThreeLetterWindowsLanguageName { get { throw new NotImplementedException(); } } - public void ClearCachedData() { throw new NotImplementedException(); } - public static System.Globalization.CultureInfo CreateSpecificCulture(string name) { throw new NotImplementedException(); } - public static System.Globalization.CultureInfo GetCultureInfo(int culture) { throw new NotImplementedException(); } - public static System.Globalization.CultureInfo GetCultureInfo(string name, string altName) { throw new NotImplementedException(); } - public static System.Globalization.CultureInfo GetCultureInfoByIetfLanguageTag(string name) { throw new NotImplementedException(); } - public static System.Globalization.CultureInfo[] GetCultures(System.Globalization.CultureTypes types) { throw new NotImplementedException(); } - } - - public partial class CultureNotFoundException : System.ArgumentException, System.Runtime.Serialization.ISerializable - { - public CultureNotFoundException(string message, int invalidCultureId, System.Exception innerException) { throw new NotImplementedException(); } - public CultureNotFoundException(string paramName, int invalidCultureId, string message) { throw new NotImplementedException(); } - public virtual System.Nullable InvalidCultureId { get { throw new NotImplementedException(); } } - } - - public enum CultureTypes - { - AllCultures = 7, - [System.ObsoleteAttribute("This value has been deprecated. Please use other values in CultureTypes.")] - FrameworkCultures = 64, - InstalledWin32Cultures = 4, - NeutralCultures = 1, - ReplacementCultures = 16, - SpecificCultures = 2, - UserCustomCulture = 8, - [System.ObsoleteAttribute("This value has been deprecated. Please use other values in CultureTypes.")] - WindowsOnlyCultures = 32, - } - - public sealed partial class DateTimeFormatInfo : System.ICloneable, System.IFormatProvider - { - // Can't do partial properties so add the setter for DateSeparator and TimeSeparator - [System.Runtime.InteropServices.ComVisibleAttribute(false)] - public string NativeCalendarName { get { throw new NotImplementedException(); } } - public string[] GetAllDateTimePatterns() { throw new NotImplementedException(); } - [System.Runtime.InteropServices.ComVisibleAttribute(false)] - public string GetShortestDayName(System.DayOfWeek dayOfWeek) { throw new NotImplementedException(); } - [System.Runtime.InteropServices.ComVisibleAttribute(false)] - public void SetAllDateTimePatterns(string[] patterns, char format) { throw new NotImplementedException(); } - } - - public enum DigitShapes - { - Context = 0, - NativeNational = 2, - None = 1, - } - - public sealed partial class IdnMapping - { - public IdnMapping() { } - public bool AllowUnassigned { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } - public bool UseStd3AsciiRules { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } - public override bool Equals(object obj) { throw new NotImplementedException(); } - public string GetAscii(string unicode) { throw new NotImplementedException(); } - public string GetAscii(string unicode, int index) { throw new NotImplementedException(); } - public string GetAscii(string unicode, int index, int count) { throw new NotImplementedException(); } - public override int GetHashCode() { throw new NotImplementedException(); } - public string GetUnicode(string ascii) { throw new NotImplementedException(); } - public string GetUnicode(string ascii, int index) { throw new NotImplementedException(); } - public string GetUnicode(string ascii, int index, int count) { throw new NotImplementedException(); } - } - - public sealed partial class NumberFormatInfo : System.ICloneable, System.IFormatProvider - { - [System.Runtime.InteropServices.ComVisibleAttribute(false)] - public System.Globalization.DigitShapes DigitSubstitution { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } - [System.Runtime.InteropServices.ComVisibleAttribute(false)] - public string[] NativeDigits { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } - } - - public partial class RegionInfo - { - public RegionInfo(int culture) { throw new NotImplementedException(); } - [System.Runtime.InteropServices.ComVisibleAttribute(false)] - public virtual string CurrencyEnglishName { get { throw new NotImplementedException(); } } - [System.Runtime.InteropServices.ComVisibleAttribute(false)] - public virtual string CurrencyNativeName { get { throw new NotImplementedException(); } } - [System.Runtime.InteropServices.ComVisibleAttribute(false)] - public virtual int GeoId { get { throw new NotImplementedException(); } } - public virtual string ThreeLetterISORegionName { get { throw new NotImplementedException(); } } - public virtual string ThreeLetterWindowsRegionName { get { throw new NotImplementedException(); } } - } - - public partial class SortKey - { - internal SortKey() { throw new NotImplementedException(); } - public virtual byte[] KeyData { get { throw new NotImplementedException(); } } - public virtual string OriginalString { get { throw new NotImplementedException(); } } - public static int Compare(System.Globalization.SortKey sortkey1, System.Globalization.SortKey sortkey2) { throw new NotImplementedException(); } - public override bool Equals(object value) { throw new NotImplementedException(); } - public override int GetHashCode() { throw new NotImplementedException(); } - public override string ToString() { throw new NotImplementedException(); } - } - - public sealed partial class SortVersion : System.IEquatable - { - public SortVersion(int fullVersion, System.Guid sortId) { throw new NotImplementedException(); } - public int FullVersion { get { throw new NotImplementedException(); } } - public System.Guid SortId { get { throw new NotImplementedException(); } } - public bool Equals(System.Globalization.SortVersion other) { throw new NotImplementedException(); } - public override bool Equals(object obj) { throw new NotImplementedException(); } - public override int GetHashCode() { throw new NotImplementedException(); } - public static bool operator ==(System.Globalization.SortVersion left, System.Globalization.SortVersion right) { throw new NotImplementedException(); } - public static bool operator !=(System.Globalization.SortVersion left, System.Globalization.SortVersion right) { throw new NotImplementedException(); } - } - - public partial class StringInfo - { - public string SubstringByTextElements(int startingTextElement) { throw new NotImplementedException(); } - public string SubstringByTextElements(int startingTextElement, int lengthInTextElements) { throw new NotImplementedException(); } - } - - public partial class TextInfo : System.ICloneable, System.Runtime.Serialization.IDeserializationCallback - { - public virtual int ANSICodePage { get { throw new NotImplementedException(); } } - public virtual int EBCDICCodePage { get { throw new NotImplementedException(); } } - [System.Runtime.InteropServices.ComVisibleAttribute(false)] - public int LCID { get { throw new NotImplementedException(); } } - public virtual int MacCodePage { get { throw new NotImplementedException(); } } - public virtual int OEMCodePage { get { throw new NotImplementedException(); } } - public string ToTitleCase(string str) { throw new NotImplementedException(); } - } -} \ No newline at end of file diff --git a/src/mscorlib/corefx/System/Globalization/SortKey.cs b/src/mscorlib/corefx/System/Globalization/SortKey.cs new file mode 100644 index 0000000..fc151fa --- /dev/null +++ b/src/mscorlib/corefx/System/Globalization/SortKey.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. +// See the LICENSE file in the project root for more information. + +//////////////////////////////////////////////////////////////////////////// +// +// +// Purpose: This class implements a set of methods for retrieving +// sort key information. +// +// +//////////////////////////////////////////////////////////////////////////// + +namespace System.Globalization { + + using System; + using System.Runtime.CompilerServices; + using System.Runtime.Serialization; + using System.Diagnostics; + using System.Diagnostics.Contracts; + + [System.Runtime.InteropServices.ComVisible(true)] + [Serializable] + public partial class SortKey + { + //--------------------------------------------------------------------// + // Internal Information // + //--------------------------------------------------------------------// + + // + // Variables. + // + + [OptionalField(VersionAdded = 3)] + internal string _localeName; // locale identifier + + [OptionalField(VersionAdded = 1)] // LCID field so serialization is Whidbey compatible though we don't officially support it + internal int _win32LCID; + // Whidbey serialization + + internal CompareOptions _options; // options + internal string _string; // original string + internal byte[] _keyData; // sortkey data + + // + // The following constructor is designed to be called from CompareInfo to get the + // the sort key of specific string for synthetic culture + // + internal SortKey(String localeName, String str, CompareOptions options, byte[] keyData) + { + _keyData = keyData; + _localeName = localeName; + _options = options; + _string = str; + } + + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + //set LCID to proper value for Whidbey serialization (no other use) + if (_win32LCID == 0) + { + _win32LCID = CultureInfo.GetCultureInfo(_localeName).LCID; + } + } + + [OnDeserialized] + private void OnDeserialized(StreamingContext context) + { + //set locale name to proper value after Whidbey deserialization + if (String.IsNullOrEmpty(_localeName) && _win32LCID != 0) + { + _localeName = CultureInfo.GetCultureInfo(_win32LCID).Name; + } + } + + //////////////////////////////////////////////////////////////////////// + // + // GetOriginalString + // + // Returns the original string used to create the current instance + // of SortKey. + // + //////////////////////////////////////////////////////////////////////// + public virtual String OriginalString + { + get + { + return (_string); + } + } + + //////////////////////////////////////////////////////////////////////// + // + // GetKeyData + // + // Returns a byte array representing the current instance of the + // sort key. + // + //////////////////////////////////////////////////////////////////////// + public virtual byte[] KeyData + { + get + { + return (byte[])(_keyData.Clone()); + } + } + + //////////////////////////////////////////////////////////////////////// + // + // Compare + // + // Compares the two sort keys. Returns 0 if the two sort keys are + // equal, a number less than 0 if sortkey1 is less than sortkey2, + // and a number greater than 0 if sortkey1 is greater than sortkey2. + // + //////////////////////////////////////////////////////////////////////// + public static int Compare(SortKey sortkey1, SortKey sortkey2) + { + if (sortkey1==null || sortkey2==null) + { + throw new ArgumentNullException((sortkey1 == null ? nameof(sortkey1) : nameof(sortkey2))); + } + Contract.EndContractBlock(); + + byte[] key1Data = sortkey1._keyData; + byte[] key2Data = sortkey2._keyData; + + Debug.Assert(key1Data != null, "key1Data != null"); + Debug.Assert(key2Data != null, "key2Data != null"); + + if (key1Data.Length == 0) + { + if (key2Data.Length == 0) + { + return (0); + } + return (-1); + } + if (key2Data.Length == 0) + { + return (1); + } + + int compLen = (key1Data.Lengthkey2Data[i]) + { + return (1); + } + if (key1Data[i] + { + private int _nlsVersion; + private Guid _sortId; + + public int FullVersion + { + get + { + return _nlsVersion; + } + } + + public Guid SortId + { + get + { + return _sortId; + } + } + + public SortVersion(int fullVersion, Guid sortId) + { + _sortId = sortId; + _nlsVersion = fullVersion; + } + + internal SortVersion(int nlsVersion, int effectiveId, Guid customVersion) + { + _nlsVersion = nlsVersion; + + if (customVersion == Guid.Empty) + { + byte b1 = (byte) (effectiveId >> 24); + byte b2 = (byte) ((effectiveId & 0x00FF0000) >> 16); + byte b3 = (byte) ((effectiveId & 0x0000FF00) >> 8); + byte b4 = (byte) (effectiveId & 0xFF); + customVersion = new Guid(0,0,0,0,0,0,0,b1,b2,b3,b4); + } + + _sortId = customVersion; + } + + public override bool Equals(object obj) + { + SortVersion n = obj as SortVersion; + if (n != null) + { + return this.Equals(n); + } + + return false; + } + + public bool Equals(SortVersion other) + { + if (other == null) + { + return false; + } + + return _nlsVersion == other._nlsVersion && _sortId == other._sortId; + } + + public override int GetHashCode() + { + return _nlsVersion * 7 | _sortId.GetHashCode(); + } + + public static bool operator ==(SortVersion left, SortVersion right) + { + if (((object) left) != null) + { + return left.Equals(right); + } + + if (((object) right) != null) + { + return right.Equals(left); + } + + // Both null. + return true; + } + + public static bool operator !=(SortVersion left, SortVersion right) + { + return !(left == right); + } + } +} \ No newline at end of file diff --git a/src/mscorlib/corefx/System/Globalization/StringInfo.cs b/src/mscorlib/corefx/System/Globalization/StringInfo.cs index 102f703..7558002 100644 --- a/src/mscorlib/corefx/System/Globalization/StringInfo.cs +++ b/src/mscorlib/corefx/System/Globalization/StringInfo.cs @@ -13,6 +13,7 @@ //////////////////////////////////////////////////////////////////////////// using System; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.Serialization; @@ -20,10 +21,10 @@ namespace System.Globalization { [Serializable] [System.Runtime.InteropServices.ComVisible(true)] - public partial class StringInfo + public class StringInfo { [OptionalField(VersionAdded = 2)] - private String _str; + private string _str; [NonSerialized] private int[] _indexes; @@ -32,7 +33,7 @@ namespace System.Globalization public StringInfo() : this("") { } // Primary, useful constructor - public StringInfo(String value) + public StringInfo(string value) { this.String = value; } @@ -85,7 +86,7 @@ namespace System.Globalization } } - public String String + public string String { get { @@ -119,7 +120,61 @@ namespace System.Globalization } } - public static String GetNextTextElement(String str) + public string SubstringByTextElements(int startingTextElement) + { + // If the string is empty, no sense going further. + if (null == this.Indexes) + { + // Just decide which error to give depending on the param they gave us.... + if (startingTextElement < 0) + { + throw new ArgumentOutOfRangeException(nameof(startingTextElement), SR.ArgumentOutOfRange_NeedPosNum); + } + else + { + throw new ArgumentOutOfRangeException(nameof(startingTextElement), SR.Arg_ArgumentOutOfRangeException); + } + } + return (SubstringByTextElements(startingTextElement, Indexes.Length - startingTextElement)); + } + + public string SubstringByTextElements(int startingTextElement, int lengthInTextElements) + { + if (startingTextElement < 0) + { + throw new ArgumentOutOfRangeException(nameof(startingTextElement), SR.ArgumentOutOfRange_NeedPosNum); + } + + if (this.String.Length == 0 || startingTextElement >= Indexes.Length) + { + throw new ArgumentOutOfRangeException(nameof(startingTextElement), SR.Arg_ArgumentOutOfRangeException); + } + + if (lengthInTextElements < 0) + { + throw new ArgumentOutOfRangeException(nameof(lengthInTextElements), SR.ArgumentOutOfRange_NeedPosNum); + } + + if (startingTextElement > Indexes.Length - lengthInTextElements) + { + throw new ArgumentOutOfRangeException(nameof(lengthInTextElements), SR.Arg_ArgumentOutOfRangeException); + } + + int start = Indexes[startingTextElement]; + + if (startingTextElement + lengthInTextElements == Indexes.Length) + { + // We are at the last text element in the string and because of that + // must handle the call differently. + return (this.String.Substring(start)); + } + else + { + return (this.String.Substring(start, (Indexes[lengthInTextElements + startingTextElement] - start))); + } + } + + public static string GetNextTextElement(string str) { return (GetNextTextElement(str, 0)); } @@ -157,10 +212,10 @@ namespace System.Globalization // //////////////////////////////////////////////////////////////////////// - internal static int GetCurrentTextElementLen(String str, int index, int len, ref UnicodeCategory ucCurrent, ref int currentCharCount) + internal static int GetCurrentTextElementLen(string str, int index, int len, ref UnicodeCategory ucCurrent, ref int currentCharCount) { - Contract.Assert(index >= 0 && len >= 0, "StringInfo.GetCurrentTextElementLen() : index = " + index + ", len = " + len); - Contract.Assert(index < len, "StringInfo.GetCurrentTextElementLen() : index = " + index + ", len = " + len); + Debug.Assert(index >= 0 && len >= 0, "StringInfo.GetCurrentTextElementLen() : index = " + index + ", len = " + len); + Debug.Assert(index < len, "StringInfo.GetCurrentTextElementLen() : index = " + index + ", len = " + len); if (index + currentCharCount == len) { // This is the last character/surrogate in the string. @@ -220,14 +275,14 @@ namespace System.Globalization // of str. It recognizes a base character plus one or more combining // characters or a properly formed surrogate pair as a text element. See also // the ParseCombiningCharacters() and the ParseSurrogates() methods. - public static String GetNextTextElement(String str, int index) + public static string GetNextTextElement(string str, int index) { // // Validate parameters. // if (str == null) { - throw new ArgumentNullException("str"); + throw new ArgumentNullException(nameof(str)); } Contract.EndContractBlock(); @@ -238,7 +293,7 @@ namespace System.Globalization { return (String.Empty); } - throw new ArgumentOutOfRangeException("index", SR.ArgumentOutOfRange_Index); + throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); } int charLen; @@ -246,26 +301,26 @@ namespace System.Globalization return (str.Substring(index, GetCurrentTextElementLen(str, index, len, ref uc, ref charLen))); } - public static TextElementEnumerator GetTextElementEnumerator(String str) + public static TextElementEnumerator GetTextElementEnumerator(string str) { return (GetTextElementEnumerator(str, 0)); } - public static TextElementEnumerator GetTextElementEnumerator(String str, int index) + public static TextElementEnumerator GetTextElementEnumerator(string str, int index) { // // Validate parameters. // if (str == null) { - throw new ArgumentNullException("str"); + throw new ArgumentNullException(nameof(str)); } Contract.EndContractBlock(); int len = str.Length; if (index < 0 || (index > len)) { - throw new ArgumentOutOfRangeException("index", SR.ArgumentOutOfRange_Index); + throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); } return (new TextElementEnumerator(str, index, len)); @@ -283,11 +338,11 @@ namespace System.Globalization * return the indices: 0, 2, 4. */ - public static int[] ParseCombiningCharacters(String str) + public static int[] ParseCombiningCharacters(string str) { if (str == null) { - throw new ArgumentNullException("str"); + throw new ArgumentNullException(nameof(str)); } Contract.EndContractBlock(); diff --git a/src/mscorlib/corefx/System/Globalization/TaiwanCalendar.cs b/src/mscorlib/corefx/System/Globalization/TaiwanCalendar.cs index 89b2e4a..36edd5b 100644 --- a/src/mscorlib/corefx/System/Globalization/TaiwanCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/TaiwanCalendar.cs @@ -83,6 +83,15 @@ namespace System.Globalization } } + [System.Runtime.InteropServices.ComVisible(false)] + public override CalendarAlgorithmType AlgorithmType + { + get + { + return CalendarAlgorithmType.SolarCalendar; + } + } + // Return the type of the Taiwan calendar. // @@ -260,7 +269,7 @@ namespace System.Globalization { if (year <= 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_NeedPosNum); } Contract.EndContractBlock(); @@ -268,7 +277,7 @@ namespace System.Globalization if (year > helper.MaxYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, diff --git a/src/mscorlib/corefx/System/Globalization/TextElementEnumerator.cs b/src/mscorlib/corefx/System/Globalization/TextElementEnumerator.cs index 487ef11..c0ffc65 100644 --- a/src/mscorlib/corefx/System/Globalization/TextElementEnumerator.cs +++ b/src/mscorlib/corefx/System/Globalization/TextElementEnumerator.cs @@ -11,7 +11,7 @@ //////////////////////////////////////////////////////////////////////////// using System.Collections; -using System.Diagnostics.Contracts; +using System.Diagnostics; using System.Runtime.Serialization; namespace System.Globalization @@ -42,9 +42,9 @@ namespace System.Globalization internal TextElementEnumerator(String str, int startIndex, int strLen) { - Contract.Assert(str != null, "TextElementEnumerator(): str != null"); - Contract.Assert(startIndex >= 0 && strLen >= 0, "TextElementEnumerator(): startIndex >= 0 && strLen >= 0"); - Contract.Assert(strLen >= startIndex, "TextElementEnumerator(): strLen >= startIndex"); + Debug.Assert(str != null, "TextElementEnumerator(): str != null"); + Debug.Assert(startIndex >= 0 && strLen >= 0, "TextElementEnumerator(): startIndex >= 0 && strLen >= 0"); + Debug.Assert(strLen >= startIndex, "TextElementEnumerator(): strLen >= startIndex"); _str = str; _startIndex = startIndex; _strLen = strLen; @@ -125,7 +125,7 @@ namespace System.Globalization } // - // Get the starting _index of the current text element. + // Get the starting index of the current text element. // public int ElementIndex diff --git a/src/mscorlib/corefx/System/Globalization/TextInfo.Unix.cs b/src/mscorlib/corefx/System/Globalization/TextInfo.Unix.cs index 8490057..3d9b777 100644 --- a/src/mscorlib/corefx/System/Globalization/TextInfo.Unix.cs +++ b/src/mscorlib/corefx/System/Globalization/TextInfo.Unix.cs @@ -2,6 +2,7 @@ // 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.Diagnostics; using System.Diagnostics.Contracts; using System.Security; using System.Text; @@ -35,7 +36,7 @@ namespace System.Globalization [SecuritySafeCritical] private unsafe string ChangeCase(string s, bool toUpper) { - Contract.Assert(s != null); + Debug.Assert(s != null); if (s.Length == 0) { @@ -93,7 +94,7 @@ namespace System.Globalization private bool NeedsTurkishCasing(string localeName) { - Contract.Assert(localeName != null); + Debug.Assert(localeName != null); return CultureInfo.GetCultureInfo(localeName).CompareInfo.Compare("\u0131", "I", CompareOptions.IgnoreCase) == 0; } diff --git a/src/mscorlib/corefx/System/Globalization/TextInfo.Windows.cs b/src/mscorlib/corefx/System/Globalization/TextInfo.Windows.cs index 238c512..b2f692e 100644 --- a/src/mscorlib/corefx/System/Globalization/TextInfo.Windows.cs +++ b/src/mscorlib/corefx/System/Globalization/TextInfo.Windows.cs @@ -2,7 +2,7 @@ // 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.Diagnostics.Contracts; +using System.Diagnostics; namespace System.Globalization { @@ -35,7 +35,7 @@ namespace System.Globalization private unsafe string ChangeCase(string s, bool toUpper) { - Contract.Assert(s != null); + Debug.Assert(s != null); // // Get the length of the string. @@ -80,7 +80,7 @@ namespace System.Globalization throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); } - Contract.Assert(ret == nLengthInput, "Expected getting the same length of the original string"); + Debug.Assert(ret == nLengthInput, "Expected getting the same length of the original string"); return result; } } diff --git a/src/mscorlib/corefx/System/Globalization/TextInfo.cs b/src/mscorlib/corefx/System/Globalization/TextInfo.cs index 6dadb58..5bb376f 100644 --- a/src/mscorlib/corefx/System/Globalization/TextInfo.cs +++ b/src/mscorlib/corefx/System/Globalization/TextInfo.cs @@ -12,15 +12,10 @@ // //////////////////////////////////////////////////////////////////////////// -using System; +using System.Diagnostics; using System.Diagnostics.Contracts; -using System.Runtime; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using System.Runtime.Serialization; -using System.Security; using System.Text; -using System.Threading; namespace System.Globalization { @@ -145,6 +140,64 @@ namespace System.Globalization return CompareInfo.LastIndexOfOrdinal(source, value, startIndex, count, ignoreCase: true); } + //////////////////////////////////////////////////////////////////////// + // + // CodePage + // + // Returns the number of the code page used by this writing system. + // The type parameter can be any of the following values: + // ANSICodePage + // OEMCodePage + // MACCodePage + // + //////////////////////////////////////////////////////////////////////// + + + public virtual int ANSICodePage + { + get + { + return (_cultureData.IDEFAULTANSICODEPAGE); + } + } + + + public virtual int OEMCodePage + { + get + { + return (_cultureData.IDEFAULTOEMCODEPAGE); + } + } + + + public virtual int MacCodePage + { + get + { + return (_cultureData.IDEFAULTMACCODEPAGE); + } + } + + + public virtual int EBCDICCodePage + { + get + { + return (_cultureData.IDEFAULTEBCDICCODEPAGE); + } + } + + [System.Runtime.InteropServices.ComVisible(false)] + public int LCID + { + get + { + // Just use the LCID from our text info name + return CultureInfo.GetCultureInfo(_textInfoName).LCID; + } + } + ////////////////////////////////////////////////////////////////////////// //// //// CultureName @@ -177,10 +230,10 @@ namespace System.Globalization //// //// Clone //// - //// Is the implementation of IColnable. + //// Is the implementation of ICloneable. //// ////////////////////////////////////////////////////////////////////////// - public virtual Object Clone() + public virtual object Clone() { object o = MemberwiseClone(); ((TextInfo)o).SetReadOnlyState(false); @@ -196,9 +249,9 @@ namespace System.Globalization // //////////////////////////////////////////////////////////////////////// [System.Runtime.InteropServices.ComVisible(false)] - internal static TextInfo ReadOnly(TextInfo textInfo) + public static TextInfo ReadOnly(TextInfo textInfo) { - if (textInfo == null) { throw new ArgumentNullException("textInfo"); } + if (textInfo == null) { throw new ArgumentNullException(nameof(textInfo)); } Contract.EndContractBlock(); if (textInfo.IsReadOnly) { return (textInfo); } @@ -244,7 +297,7 @@ namespace System.Globalization { if (value == null) { - throw new ArgumentNullException("value", SR.ArgumentNull_String); + throw new ArgumentNullException(nameof(value), SR.ArgumentNull_String); } VerifyWritable(); _listSeparator = value; @@ -270,7 +323,7 @@ namespace System.Globalization public unsafe virtual String ToLower(String str) { - if (str == null) { throw new ArgumentNullException("str"); } + if (str == null) { throw new ArgumentNullException(nameof(str)); } return ChangeCase(str, toUpper: false); } @@ -303,7 +356,7 @@ namespace System.Globalization public unsafe virtual String ToUpper(String str) { - if (str == null) { throw new ArgumentNullException("str"); } + if (str == null) { throw new ArgumentNullException(nameof(str)); } return ChangeCase(str, toUpper: true); } @@ -317,7 +370,7 @@ namespace System.Globalization return c; } - static private bool IsAscii(Char c) + private static bool IsAscii(Char c) { return c < 0x80; } @@ -396,6 +449,245 @@ namespace System.Globalization } // + // Titlecasing: + // ----------- + // Titlecasing refers to a casing practice wherein the first letter of a word is an uppercase letter + // and the rest of the letters are lowercase. The choice of which words to titlecase in headings + // and titles is dependent on language and local conventions. For example, "The Merry Wives of Windor" + // is the appropriate titlecasing of that play's name in English, with the word "of" not titlecased. + // In German, however, the title is "Die lustigen Weiber von Windsor," and both "lustigen" and "von" + // are not titlecased. In French even fewer words are titlecased: "Les joyeuses commeres de Windsor." + // + // Moreover, the determination of what actually constitutes a word is language dependent, and this can + // influence which letter or letters of a "word" are uppercased when titlecasing strings. For example + // "l'arbre" is considered two words in French, whereas "can't" is considered one word in English. + // + public unsafe String ToTitleCase(String str) + { + if (str == null) + { + throw new ArgumentNullException(nameof(str)); + } + Contract.EndContractBlock(); + if (str.Length == 0) + { + return (str); + } + + StringBuilder result = new StringBuilder(); + string lowercaseData = null; + + for (int i = 0; i < str.Length; i++) + { + UnicodeCategory charType; + int charLen; + + charType = CharUnicodeInfo.InternalGetUnicodeCategory(str, i, out charLen); + if (Char.CheckLetter(charType)) + { + // Do the titlecasing for the first character of the word. + i = AddTitlecaseLetter(ref result, ref str, i, charLen) + 1; + + // + // Convert the characters until the end of the this word + // to lowercase. + // + int lowercaseStart = i; + + // + // Use hasLowerCase flag to prevent from lowercasing acronyms (like "URT", "USA", etc) + // This is in line with Word 2000 behavior of titlecasing. + // + bool hasLowerCase = (charType == UnicodeCategory.LowercaseLetter); + // Use a loop to find all of the other letters following this letter. + while (i < str.Length) + { + charType = CharUnicodeInfo.InternalGetUnicodeCategory(str, i, out charLen); + if (IsLetterCategory(charType)) + { + if (charType == UnicodeCategory.LowercaseLetter) + { + hasLowerCase = true; + } + i += charLen; + } + else if (str[i] == '\'') + { + i++; + if (hasLowerCase) + { + if (lowercaseData == null) + { + lowercaseData = this.ToLower(str); + } + result.Append(lowercaseData, lowercaseStart, i - lowercaseStart); + } + else + { + result.Append(str, lowercaseStart, i - lowercaseStart); + } + lowercaseStart = i; + hasLowerCase = true; + } + else if (!IsWordSeparator(charType)) + { + // This category is considered to be part of the word. + // This is any category that is marked as false in wordSeprator array. + i+= charLen; + } + else + { + // A word separator. Break out of the loop. + break; + } + } + + int count = i - lowercaseStart; + + if (count > 0) + { + if (hasLowerCase) + { + if (lowercaseData == null) + { + lowercaseData = this.ToLower(str); + } + result.Append(lowercaseData, lowercaseStart, count); + } + else + { + result.Append(str, lowercaseStart, count); + } + } + + if (i < str.Length) + { + // not a letter, just append it + i = AddNonLetter(ref result, ref str, i, charLen); + } + } + else + { + // not a letter, just append it + i = AddNonLetter(ref result, ref str, i, charLen); + } + } + return (result.ToString()); + } + + private static int AddNonLetter(ref StringBuilder result, ref String input, int inputIndex, int charLen) + { + Debug.Assert(charLen == 1 || charLen == 2, "[TextInfo.AddNonLetter] CharUnicodeInfo.InternalGetUnicodeCategory returned an unexpected charLen!"); + if (charLen == 2) + { + // Surrogate pair + result.Append(input[inputIndex++]); + result.Append(input[inputIndex]); + } + else + { + result.Append(input[inputIndex]); + } + return inputIndex; + } + + private int AddTitlecaseLetter(ref StringBuilder result, ref String input, int inputIndex, int charLen) + { + Debug.Assert(charLen == 1 || charLen == 2, "[TextInfo.AddTitlecaseLetter] CharUnicodeInfo.InternalGetUnicodeCategory returned an unexpected charLen!"); + + // for surrogate pairs do a simple ToUpper operation on the substring + if (charLen == 2) + { + // Surrogate pair + result.Append(ToUpper(input.Substring(inputIndex, charLen))); + inputIndex++; + } + else + { + switch (input[inputIndex]) + { + // + // For AppCompat, the Titlecase Case Mapping data from NDP 2.0 is used below. + case (char) 0x01C4: // DZ with Caron -> Dz with Caron + case (char) 0x01C5: // Dz with Caron -> Dz with Caron + case (char) 0x01C6: // dz with Caron -> Dz with Caron + result.Append((char) 0x01C5); + break; + case (char) 0x01C7: // LJ -> Lj + case (char) 0x01C8: // Lj -> Lj + case (char) 0x01C9: // lj -> Lj + result.Append((char) 0x01C8); + break; + case (char) 0x01CA: // NJ -> Nj + case (char) 0x01CB: // Nj -> Nj + case (char) 0x01CC: // nj -> Nj + result.Append((char) 0x01CB); + break; + case (char) 0x01F1: // DZ -> Dz + case (char) 0x01F2: // Dz -> Dz + case (char) 0x01F3: // dz -> Dz + result.Append((char) 0x01F2); + break; + default: + result.Append(ToUpper(input[inputIndex])); + break; + } + } + return inputIndex; + } + + // + // Used in ToTitleCase(): + // When we find a starting letter, the following array decides if a category should be + // considered as word seprator or not. + // + private const int c_wordSeparatorMask = + /* false */ (0 << 0) | // UppercaseLetter = 0, + /* false */ (0 << 1) | // LowercaseLetter = 1, + /* false */ (0 << 2) | // TitlecaseLetter = 2, + /* false */ (0 << 3) | // ModifierLetter = 3, + /* false */ (0 << 4) | // OtherLetter = 4, + /* false */ (0 << 5) | // NonSpacingMark = 5, + /* false */ (0 << 6) | // SpacingCombiningMark = 6, + /* false */ (0 << 7) | // EnclosingMark = 7, + /* false */ (0 << 8) | // DecimalDigitNumber = 8, + /* false */ (0 << 9) | // LetterNumber = 9, + /* false */ (0 << 10) | // OtherNumber = 10, + /* true */ (1 << 11) | // SpaceSeparator = 11, + /* true */ (1 << 12) | // LineSeparator = 12, + /* true */ (1 << 13) | // ParagraphSeparator = 13, + /* true */ (1 << 14) | // Control = 14, + /* true */ (1 << 15) | // Format = 15, + /* false */ (0 << 16) | // Surrogate = 16, + /* false */ (0 << 17) | // PrivateUse = 17, + /* true */ (1 << 18) | // ConnectorPunctuation = 18, + /* true */ (1 << 19) | // DashPunctuation = 19, + /* true */ (1 << 20) | // OpenPunctuation = 20, + /* true */ (1 << 21) | // ClosePunctuation = 21, + /* true */ (1 << 22) | // InitialQuotePunctuation = 22, + /* true */ (1 << 23) | // FinalQuotePunctuation = 23, + /* true */ (1 << 24) | // OtherPunctuation = 24, + /* true */ (1 << 25) | // MathSymbol = 25, + /* true */ (1 << 26) | // CurrencySymbol = 26, + /* true */ (1 << 27) | // ModifierSymbol = 27, + /* true */ (1 << 28) | // OtherSymbol = 28, + /* false */ (0 << 29); // OtherNotAssigned = 29; + + private static bool IsWordSeparator(UnicodeCategory category) + { + return (c_wordSeparatorMask & (1 << (int) category)) != 0; + } + + private static bool IsLetterCategory(UnicodeCategory uc) + { + return (uc == UnicodeCategory.UppercaseLetter + || uc == UnicodeCategory.LowercaseLetter + || uc == UnicodeCategory.TitlecaseLetter + || uc == UnicodeCategory.ModifierLetter + || uc == UnicodeCategory.OtherLetter); + } + + // // Get case-insensitive hash code for the specified string. // internal unsafe int GetCaseInsensitiveHashCode(String str) @@ -403,7 +695,7 @@ namespace System.Globalization // Validate inputs if (str == null) { - throw new ArgumentNullException("str"); + throw new ArgumentNullException(nameof(str)); } // This code assumes that ASCII casing is safe for whatever context is passed in. @@ -438,7 +730,7 @@ namespace System.Globalization private unsafe int GetCaseInsensitiveHashCodeSlow(String str) { - Contract.Assert(str != null); + Debug.Assert(str != null); string upper = ToUpper(str); diff --git a/src/mscorlib/corefx/System/Globalization/ThaiBuddhistCalendar.cs b/src/mscorlib/corefx/System/Globalization/ThaiBuddhistCalendar.cs index b42af30..8ebbfa0 100644 --- a/src/mscorlib/corefx/System/Globalization/ThaiBuddhistCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/ThaiBuddhistCalendar.cs @@ -56,6 +56,15 @@ namespace System.Globalization } } + [System.Runtime.InteropServices.ComVisible(false)] + public override CalendarAlgorithmType AlgorithmType + { + get + { + return CalendarAlgorithmType.SolarCalendar; + } + } + public ThaiBuddhistCalendar() { helper = new GregorianCalendarHelper(this, thaiBuddhistEraInfo); @@ -221,7 +230,7 @@ namespace System.Globalization { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); diff --git a/src/mscorlib/corefx/System/Globalization/UmAlQuraCalendar.cs b/src/mscorlib/corefx/System/Globalization/UmAlQuraCalendar.cs index 1116722..997c5f2 100644 --- a/src/mscorlib/corefx/System/Globalization/UmAlQuraCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/UmAlQuraCalendar.cs @@ -2,7 +2,7 @@ // 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.Diagnostics; using System.Diagnostics.Contracts; namespace System.Globalization @@ -270,6 +270,14 @@ namespace System.Globalization } } + public override CalendarAlgorithmType AlgorithmType + { + get + { + return CalendarAlgorithmType.LunarCalendar; + } + } + public UmAlQuraCalendar() { } @@ -309,9 +317,9 @@ namespace System.Globalization =========================ConvertHijriToGregorian============================*/ private static void ConvertHijriToGregorian(int HijriYear, int HijriMonth, int HijriDay, ref int yg, ref int mg, ref int dg) { - Contract.Assert((HijriYear >= MinCalendarYear) && (HijriYear <= MaxCalendarYear), "Hijri year is out of range."); - Contract.Assert(HijriMonth >= 1, "Hijri month is out of range."); - Contract.Assert(HijriDay >= 1, "Hijri day is out of range."); + Debug.Assert((HijriYear >= MinCalendarYear) && (HijriYear <= MaxCalendarYear), "Hijri year is out of range."); + Debug.Assert(HijriMonth >= 1, "Hijri month is out of range."); + Debug.Assert(HijriDay >= 1, "Hijri day is out of range."); int index, b, nDays = HijriDay - 1; DateTime dt; @@ -368,7 +376,7 @@ namespace System.Globalization { if (era != CurrentEra && era != UmAlQuraEra) { - throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue); + throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue); } } @@ -378,7 +386,7 @@ namespace System.Globalization if (year < MinCalendarYear || year > MaxCalendarYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -392,7 +400,7 @@ namespace System.Globalization CheckYearRange(year, era); if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException("month", SR.ArgumentOutOfRange_Month); + throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month); } } @@ -409,7 +417,7 @@ namespace System.Globalization TimeSpan ts; int yh1 = 0, mh1 = 0, dh1 = 0; - Contract.Assert((time.Ticks >= minDate.Ticks) && (time.Ticks <= maxDate.Ticks), "Gregorian date is out of range."); + Debug.Assert((time.Ticks >= minDate.Ticks) && (time.Ticks <= maxDate.Ticks), "Gregorian date is out of range."); // Find the index where we should start our search by quessing the Hijri year that we will be in HijriYearInfo. // A Hijri year is 354 or 355 days. Use 355 days so that we will search from a lower index. @@ -510,7 +518,7 @@ namespace System.Globalization if (months < -120000 || months > 120000) { throw new ArgumentOutOfRangeException( - "months", + nameof(months), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -622,7 +630,7 @@ namespace System.Globalization { int days = 0, b; - Contract.Assert((year >= MinCalendarYear) && (year <= MaxCalendarYear), "Hijri year is out of range."); + Debug.Assert((year >= MinCalendarYear) && (year <= MaxCalendarYear), "Hijri year is out of range."); b = s_hijriYearInfo[year - MinCalendarYear].HijriMonthsLengthFlags; @@ -631,7 +639,7 @@ namespace System.Globalization days = days + 29 + (b & 1); /* Add the months lengths before mh */ b = b >> 1; } - Contract.Assert((days == 354) || (days == 355), "Hijri year has to be 354 or 355 days."); + Debug.Assert((days == 354) || (days == 355), "Hijri year has to be 354 or 355 days."); return days; } @@ -711,7 +719,7 @@ namespace System.Globalization if (day < 1 || day > daysInMonth) { throw new ArgumentOutOfRangeException( - "day", + nameof(day), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Day, @@ -775,7 +783,7 @@ namespace System.Globalization if (day < 1 || day > daysInMonth) { throw new ArgumentOutOfRangeException( - "day", + nameof(day), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Day, @@ -815,7 +823,7 @@ namespace System.Globalization if (value != 99 && (value < MinCalendarYear || value > MaxCalendarYear)) { throw new ArgumentOutOfRangeException( - "value", + nameof(value), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -835,7 +843,7 @@ namespace System.Globalization { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_NeedNonNegNum); } Contract.EndContractBlock(); @@ -848,7 +856,7 @@ namespace System.Globalization if ((year < MinCalendarYear) || (year > MaxCalendarYear)) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, diff --git a/src/mscorlib/corefx/System/HResults.cs b/src/mscorlib/corefx/System/HResults.cs new file mode 100644 index 0000000..fa0e24f --- /dev/null +++ b/src/mscorlib/corefx/System/HResults.cs @@ -0,0 +1,236 @@ +// 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. + +//============================================================================= +// +// +// Purpose: Define HResult constants. Every exception has one of these. +// +// +//===========================================================================*/ + +using System; + +namespace System +{ + // Note: FACILITY_URT is defined as 0x13 (0x8013xxxx). Within that + // range, 0x1yyy is for Runtime errors (used for Security, Metadata, etc). + // In that subrange, 0x15zz and 0x16zz have been allocated for classlib-type + // HResults. Also note that some of our HResults have to map to certain + // COM HR's, etc. + + // Another arbitrary decision... Feel free to change this, as long as you + // renumber the HResults yourself (and update rexcep.h). + // Reflection will use 0x1600 -> 0x161f. IO will use 0x1620 -> 0x163f. + // Security will use 0x1640 -> 0x165f + + // There are HResults files in the IO, Remoting, Reflection & + // Security/Util directories as well, so choose your HResults carefully. + internal static class HResults + { + internal const int APPMODEL_ERROR_NO_PACKAGE = unchecked((int)0x80073D54); + internal const int CLDB_E_FILE_CORRUPT = unchecked((int)0x8013110e); + internal const int CLDB_E_FILE_OLDVER = unchecked((int)0x80131107); + internal const int CLDB_E_INDEX_NOTFOUND = unchecked((int)0x80131124); + internal const int CLR_E_BIND_ASSEMBLY_NOT_FOUND = unchecked((int)0x80132004); + internal const int CLR_E_BIND_ASSEMBLY_PUBLIC_KEY_MISMATCH = unchecked((int)0x80132001); + internal const int CLR_E_BIND_ASSEMBLY_VERSION_TOO_LOW = unchecked((int)0x80132000); + internal const int CLR_E_BIND_TYPE_NOT_FOUND = unchecked((int)0x80132005); + internal const int CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT = unchecked((int)0x80132003); + internal const int COR_E_ABANDONEDMUTEX = unchecked((int)0x8013152D); + internal const int COR_E_AMBIGUOUSMATCH = unchecked((int)0x8000211D); + internal const int COR_E_APPDOMAINUNLOADED = unchecked((int)0x80131014); + internal const int COR_E_APPLICATION = unchecked((int)0x80131600); + internal const int COR_E_ARGUMENT = unchecked((int)0x80070057); + internal const int COR_E_ARGUMENTOUTOFRANGE = unchecked((int)0x80131502); + internal const int COR_E_ARITHMETIC = unchecked((int)0x80070216); + internal const int COR_E_ARRAYTYPEMISMATCH = unchecked((int)0x80131503); + internal const int COR_E_ASSEMBLYEXPECTED = unchecked((int)0x80131018); + internal const int COR_E_BADIMAGEFORMAT = unchecked((int)0x8007000B); + internal const int COR_E_CANNOTUNLOADAPPDOMAIN = unchecked((int)0x80131015); + internal const int COR_E_CODECONTRACTFAILED = unchecked((int)0x80131542); + internal const int COR_E_CONTEXTMARSHAL = unchecked((int)0x80131504); + internal const int COR_E_CUSTOMATTRIBUTEFORMAT = unchecked((int)0x80131605); + internal const int COR_E_DATAMISALIGNED = unchecked((int)0x80131541); + internal const int COR_E_DIVIDEBYZERO = unchecked((int)0x80020012); // DISP_E_DIVBYZERO + internal const int COR_E_DLLNOTFOUND = unchecked((int)0x80131524); + internal const int COR_E_DUPLICATEWAITOBJECT = unchecked((int)0x80131529); + internal const int COR_E_ENTRYPOINTNOTFOUND = unchecked((int)0x80131523); + internal const int COR_E_EXCEPTION = unchecked((int)0x80131500); + internal const int COR_E_EXECUTIONENGINE = unchecked((int)0x80131506); + internal const int COR_E_FIELDACCESS = unchecked((int)0x80131507); + internal const int COR_E_FIXUPSINEXE = unchecked((int)0x80131019); + internal const int COR_E_FORMAT = unchecked((int)0x80131537); + internal const int COR_E_INDEXOUTOFRANGE = unchecked((int)0x80131508); + internal const int COR_E_INSUFFICIENTEXECUTIONSTACK = unchecked((int)0x80131578); + internal const int COR_E_INVALIDCAST = unchecked((int)0x80004002); + internal const int COR_E_INVALIDCOMOBJECT = unchecked((int)0x80131527); + internal const int COR_E_INVALIDFILTERCRITERIA = unchecked((int)0x80131601); + internal const int COR_E_INVALIDOLEVARIANTTYPE = unchecked((int)0x80131531); + internal const int COR_E_INVALIDOPERATION = unchecked((int)0x80131509); + internal const int COR_E_INVALIDPROGRAM = unchecked((int)0x8013153a); + internal const int COR_E_KEYNOTFOUND = unchecked((int)0x80131577); + internal const int COR_E_LOADING_REFERENCE_ASSEMBLY = unchecked((int)0x80131058); + internal const int COR_E_MARSHALDIRECTIVE = unchecked((int)0x80131535); + internal const int COR_E_MEMBERACCESS = unchecked((int)0x8013151A); + internal const int COR_E_METHODACCESS = unchecked((int)0x80131510); + internal const int COR_E_MISSINGFIELD = unchecked((int)0x80131511); + internal const int COR_E_MISSINGMANIFESTRESOURCE = unchecked((int)0x80131532); + internal const int COR_E_MISSINGMEMBER = unchecked((int)0x80131512); + internal const int COR_E_MISSINGMETHOD = unchecked((int)0x80131513); + internal const int COR_E_MISSINGSATELLITEASSEMBLY = unchecked((int)0x80131536); + internal const int COR_E_MODULE_HASH_CHECK_FAILED = unchecked((int)0x80131039); + internal const int COR_E_MULTICASTNOTSUPPORTED = unchecked((int)0x80131514); + internal const int COR_E_NEWER_RUNTIME = unchecked((int)0x8013101b); + internal const int COR_E_NOTFINITENUMBER = unchecked((int)0x80131528); + internal const int COR_E_NOTSUPPORTED = unchecked((int)0x80131515); + internal const int COR_E_NULLREFERENCE = unchecked((int)0x80004003); + internal const int COR_E_OBJECTDISPOSED = unchecked((int)0x80131622); + internal const int COR_E_OPERATIONCANCELED = unchecked((int)0x8013153B); + internal const int COR_E_OUTOFMEMORY = unchecked((int)0x8007000E); + internal const int COR_E_OVERFLOW = unchecked((int)0x80131516); + internal const int COR_E_PLATFORMNOTSUPPORTED = unchecked((int)0x80131539); + internal const int COR_E_RANK = unchecked((int)0x80131517); + internal const int COR_E_REFLECTIONTYPELOAD = unchecked((int)0x80131602); + internal const int COR_E_REMOTING = unchecked((int)0x8013150b); + internal const int COR_E_RUNTIMEWRAPPED = unchecked((int)0x8013153e); + internal const int COR_E_SAFEARRAYRANKMISMATCH = unchecked((int)0x80131538); + internal const int COR_E_SAFEARRAYTYPEMISMATCH = unchecked((int)0x80131533); + internal const int COR_E_SECURITY = unchecked((int)0x8013150A); + internal const int COR_E_SERIALIZATION = unchecked((int)0x8013150C); + internal const int COR_E_SERVER = unchecked((int)0x8013150e); + internal const int COR_E_STACKOVERFLOW = unchecked((int)0x800703E9); + internal const int COR_E_SYNCHRONIZATIONLOCK = unchecked((int)0x80131518); + internal const int COR_E_SYSTEM = unchecked((int)0x80131501); + internal const int COR_E_TARGET = unchecked((int)0x80131603); + internal const int COR_E_TARGETINVOCATION = unchecked((int)0x80131604); + internal const int COR_E_TARGETPARAMCOUNT = unchecked((int)0x8002000e); + internal const int COR_E_THREADABORTED = unchecked((int)0x80131530); + internal const int COR_E_THREADINTERRUPTED = unchecked((int)0x80131519); + internal const int COR_E_THREADSTART = unchecked((int)0x80131525); + internal const int COR_E_THREADSTATE = unchecked((int)0x80131520); + internal const int COR_E_TIMEOUT = unchecked((int)0x80131505); + internal const int COR_E_TYPEACCESS = unchecked((int)0x80131543); + internal const int COR_E_TYPEINITIALIZATION = unchecked((int)0x80131534); + internal const int COR_E_TYPELOAD = unchecked((int)0x80131522); + internal const int COR_E_TYPEUNLOADED = unchecked((int)0x80131013); + internal const int COR_E_UNAUTHORIZEDACCESS = unchecked((int)0x80070005); + internal const int COR_E_VERIFICATION = unchecked((int)0x8013150D); + internal const int COR_E_WAITHANDLECANNOTBEOPENED = unchecked((int)0x8013152C); + internal const int CORSEC_E_CRYPTO = unchecked((int)0x80131430); + internal const int CORSEC_E_CRYPTO_UNEX_OPER = unchecked((int)0x80131431); + internal const int CORSEC_E_INVALID_IMAGE_FORMAT = unchecked((int)0x8013141d); + internal const int CORSEC_E_INVALID_PUBLICKEY = unchecked((int)0x8013141e); + internal const int CORSEC_E_INVALID_STRONGNAME = unchecked((int)0x8013141a); + internal const int CORSEC_E_MIN_GRANT_FAIL = unchecked((int)0x80131417); + internal const int CORSEC_E_MISSING_STRONGNAME = unchecked((int)0x8013141b); + internal const int CORSEC_E_NO_EXEC_PERM = unchecked((int)0x80131418); + internal const int CORSEC_E_POLICY_EXCEPTION = unchecked((int)0x80131416); + internal const int CORSEC_E_SIGNATURE_MISMATCH = unchecked((int)0x80131420); + internal const int CORSEC_E_XMLSYNTAX = unchecked((int)0x80131419); + internal const int CTL_E_DEVICEIOERROR = unchecked((int)0x800A0039); + internal const int CTL_E_DIVISIONBYZERO = unchecked((int)0x800A000B); + internal const int CTL_E_FILENOTFOUND = unchecked((int)0x800A0035); + internal const int CTL_E_OUTOFMEMORY = unchecked((int)0x800A0007); + internal const int CTL_E_OUTOFSTACKSPACE = unchecked((int)0x800A001C); + internal const int CTL_E_OVERFLOW = unchecked((int)0x800A0006); + internal const int CTL_E_PATHFILEACCESSERROR = unchecked((int)0x800A004B); + internal const int CTL_E_PATHNOTFOUND = unchecked((int)0x800A004C); + internal const int CTL_E_PERMISSIONDENIED = unchecked((int)0x800A0046); + internal const int E_ELEMENTNOTAVAILABLE = unchecked((int)0x802B001F); + internal const int E_ELEMENTNOTENABLED = unchecked((int)0x802B001E); + internal const int E_FAIL = unchecked((int)0x80004005); + internal const int E_HANDLE = unchecked((int)0x80070006); + internal const int E_ILLEGAL_DELEGATE_ASSIGNMENT = unchecked((int)0x80000018); + internal const int E_ILLEGAL_METHOD_CALL = unchecked((int)0x8000000E); + internal const int E_ILLEGAL_STATE_CHANGE = unchecked((int)0x8000000D); + internal const int E_INVALIDARG = unchecked((int)0x80070057); + internal const int E_LAYOUTCYCLE = unchecked((int)0x802B0014); + internal const int E_NOTIMPL = unchecked((int)0x80004001); + internal const int E_OUTOFMEMORY = unchecked((int)0x8007000E); + internal const int E_POINTER = unchecked((int)0x80004003L); + internal const int E_XAMLPARSEFAILED = unchecked((int)0x802B000A); + internal const int ERROR_BAD_EXE_FORMAT = unchecked((int)0x800700C1); + internal const int ERROR_BAD_NET_NAME = unchecked((int)0x80070043); + internal const int ERROR_BAD_NETPATH = unchecked((int)0x80070035); + internal const int ERROR_DISK_CORRUPT = unchecked((int)0x80070571); + internal const int ERROR_DLL_INIT_FAILED = unchecked((int)0x8007045A); + internal const int ERROR_DLL_NOT_FOUND = unchecked((int)0x80070485); + internal const int ERROR_EXE_MARKED_INVALID = unchecked((int)0x800700C0); + internal const int ERROR_FILE_CORRUPT = unchecked((int)0x80070570); + internal const int ERROR_FILE_INVALID = unchecked((int)0x800703EE); + internal const int ERROR_FILE_NOT_FOUND = unchecked((int)0x80070002); + internal const int ERROR_INVALID_DLL = unchecked((int)0x80070482); + internal const int ERROR_INVALID_NAME = unchecked((int)0x8007007B); + internal const int ERROR_INVALID_ORDINAL = unchecked((int)0x800700B6); + internal const int ERROR_INVALID_PARAMETER = unchecked((int)0x80070057); + internal const int ERROR_LOCK_VIOLATION = unchecked((int)0x80070021); + internal const int ERROR_MOD_NOT_FOUND = unchecked((int)0x8007007E); + internal const int ERROR_NO_UNICODE_TRANSLATION = unchecked((int)0x80070459); + internal const int ERROR_NOACCESS = unchecked((int)0x800703E6); + internal const int ERROR_NOT_READY = unchecked((int)0x80070015); + internal const int ERROR_OPEN_FAILED = unchecked((int)0x8007006E); + internal const int ERROR_PATH_NOT_FOUND = unchecked((int)0x80070003); + internal const int ERROR_SHARING_VIOLATION = unchecked((int)0x80070020); + internal const int ERROR_TOO_MANY_OPEN_FILES = unchecked((int)0x80070004); + internal const int ERROR_UNRECOGNIZED_VOLUME = unchecked((int)0x800703ED); + internal const int ERROR_WRONG_TARGET_NAME = unchecked((int)0x80070574); + internal const int FUSION_E_ASM_MODULE_MISSING = unchecked((int)0x80131042); + internal const int FUSION_E_CACHEFILE_FAILED = unchecked((int)0x80131052); + internal const int FUSION_E_CODE_DOWNLOAD_DISABLED = unchecked((int)0x80131048); + internal const int FUSION_E_HOST_GAC_ASM_MISMATCH = unchecked((int)0x80131050); + internal const int FUSION_E_INVALID_NAME = unchecked((int)0x80131047); + internal const int FUSION_E_INVALID_PRIVATE_ASM_LOCATION = unchecked((int)0x80131041); + internal const int FUSION_E_LOADFROM_BLOCKED = unchecked((int)0x80131051); + internal const int FUSION_E_PRIVATE_ASM_DISALLOWED = unchecked((int)0x80131044); + internal const int FUSION_E_REF_DEF_MISMATCH = unchecked((int)0x80131040); + internal const int FUSION_E_SIGNATURE_CHECK_FAILED = unchecked((int)0x80131045); + internal const int INET_E_CANNOT_CONNECT = unchecked((int)0x800C0004); + internal const int INET_E_CONNECTION_TIMEOUT = unchecked((int)0x800C000B); + internal const int INET_E_DATA_NOT_AVAILABLE = unchecked((int)0x800C0007); + internal const int INET_E_DOWNLOAD_FAILURE = unchecked((int)0x800C0008); + internal const int INET_E_OBJECT_NOT_FOUND = unchecked((int)0x800C0006); + internal const int INET_E_RESOURCE_NOT_FOUND = unchecked((int)0x800C0005); + internal const int INET_E_UNKNOWN_PROTOCOL = unchecked((int)0x800C000D); + internal const int ISS_E_ALLOC_TOO_LARGE = unchecked((int)0x80131484); + internal const int ISS_E_BLOCK_SIZE_TOO_SMALL = unchecked((int)0x80131483); + internal const int ISS_E_CALLER = unchecked((int)0x801314A1); + internal const int ISS_E_CORRUPTED_STORE_FILE = unchecked((int)0x80131480); + internal const int ISS_E_CREATE_DIR = unchecked((int)0x80131468); + internal const int ISS_E_CREATE_MUTEX = unchecked((int)0x80131464); + internal const int ISS_E_DEPRECATE = unchecked((int)0x801314A0); + internal const int ISS_E_FILE_NOT_MAPPED = unchecked((int)0x80131482); + internal const int ISS_E_FILE_WRITE = unchecked((int)0x80131466); + internal const int ISS_E_GET_FILE_SIZE = unchecked((int)0x80131463); + internal const int ISS_E_ISOSTORE = unchecked((int)0x80131450); + internal const int ISS_E_LOCK_FAILED = unchecked((int)0x80131465); + internal const int ISS_E_MACHINE = unchecked((int)0x801314A3); + internal const int ISS_E_MACHINE_DACL = unchecked((int)0x801314A4); + internal const int ISS_E_MAP_VIEW_OF_FILE = unchecked((int)0x80131462); + internal const int ISS_E_OPEN_FILE_MAPPING = unchecked((int)0x80131461); + internal const int ISS_E_OPEN_STORE_FILE = unchecked((int)0x80131460); + internal const int ISS_E_PATH_LENGTH = unchecked((int)0x801314A2); + internal const int ISS_E_SET_FILE_POINTER = unchecked((int)0x80131467); + internal const int ISS_E_STORE_NOT_OPEN = unchecked((int)0x80131469); + internal const int ISS_E_STORE_VERSION = unchecked((int)0x80131481); + internal const int ISS_E_TABLE_ROW_NOT_FOUND = unchecked((int)0x80131486); + internal const int ISS_E_USAGE_WILL_EXCEED_QUOTA = unchecked((int)0x80131485); + internal const int META_E_BAD_SIGNATURE = unchecked((int)0x80131192); + internal const int META_E_CA_FRIENDS_SN_REQUIRED = unchecked((int)0x801311e6); + internal const int MSEE_E_ASSEMBLYLOADINPROGRESS = unchecked((int)0x80131016); + internal const int RO_E_CLOSED = unchecked((int)0x80000013); + internal const int E_BOUNDS = unchecked((int)0x8000000B); + internal const int RO_E_METADATA_NAME_NOT_FOUND = unchecked((int)0x8000000F); + internal const int SECURITY_E_INCOMPATIBLE_EVIDENCE = unchecked((int)0x80131403); + internal const int SECURITY_E_INCOMPATIBLE_SHARE = unchecked((int)0x80131401); + internal const int SECURITY_E_UNVERIFIABLE = unchecked((int)0x80131402); + internal const int STG_E_PATHNOTFOUND = unchecked((int)0x80030003); + public const int COR_E_DIRECTORYNOTFOUND = unchecked((int)0x80070003); + public const int COR_E_ENDOFSTREAM = unchecked((int)0x80070026); // OS defined + public const int COR_E_FILELOAD = unchecked((int)0x80131621); + public const int COR_E_FILENOTFOUND = unchecked((int)0x80070002); + public const int COR_E_IO = unchecked((int)0x80131620); + public const int COR_E_PATHTOOLONG = unchecked((int)0x800700CE); + } +} diff --git a/src/mscorlib/corefx/System/IO/Error.cs b/src/mscorlib/corefx/System/IO/Error.cs new file mode 100644 index 0000000..c8434ff --- /dev/null +++ b/src/mscorlib/corefx/System/IO/Error.cs @@ -0,0 +1,44 @@ +// 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.Runtime.InteropServices; +using System.Text; +using System.Globalization; +using System.Diagnostics.Contracts; + +namespace System.IO +{ + /// + /// Provides centralized methods for creating exceptions for System.IO.FileSystem. + /// + [Pure] + internal static class Error + { + internal static Exception GetEndOfFile() + { + return new EndOfStreamException(SR.IO_EOF_ReadBeyondEOF); + } + + internal static Exception GetFileNotOpen() + { + return new ObjectDisposedException(null, SR.ObjectDisposed_FileClosed); + } + + internal static Exception GetReadNotSupported() + { + return new NotSupportedException(SR.NotSupported_UnreadableStream); + } + + internal static Exception GetSeekNotSupported() + { + return new NotSupportedException(SR.NotSupported_UnseekableStream); + } + + internal static Exception GetWriteNotSupported() + { + return new NotSupportedException(SR.NotSupported_UnwritableStream); + } + } +} diff --git a/src/mscorlib/corefx/System/IO/FileStream.NetStandard17.cs b/src/mscorlib/corefx/System/IO/FileStream.NetStandard17.cs new file mode 100644 index 0000000..dc1385f --- /dev/null +++ b/src/mscorlib/corefx/System/IO/FileStream.NetStandard17.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. +// See the LICENSE file in the project root for more information. + +using Microsoft.Win32.SafeHandles; +using System.Threading.Tasks; +using System.Diagnostics; +using System.Threading; + +namespace System.IO +{ + public partial class FileStream : Stream + { + public override IAsyncResult BeginRead(byte[] array, int offset, int numBytes, AsyncCallback callback, object state) + { + if (array == null) + throw new ArgumentNullException(nameof(array)); + if (offset < 0) + throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum); + if (numBytes < 0) + throw new ArgumentOutOfRangeException(nameof(numBytes), SR.ArgumentOutOfRange_NeedNonNegNum); + if (array.Length - offset < numBytes) + throw new ArgumentException(SR.Argument_InvalidOffLen); + + if (IsClosed) throw new ObjectDisposedException(SR.ObjectDisposed_FileClosed); + if (!CanRead) throw new NotSupportedException(SR.NotSupported_UnreadableStream); + + if (!IsAsync) + return base.BeginRead(array, offset, numBytes, callback, state); + else + return TaskToApm.Begin(ReadAsyncInternal(array, offset, numBytes, CancellationToken.None), callback, state); + } + + public override IAsyncResult BeginWrite(byte[] array, int offset, int numBytes, AsyncCallback callback, object state) + { + if (array == null) + throw new ArgumentNullException(nameof(array)); + if (offset < 0) + throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum); + if (numBytes < 0) + throw new ArgumentOutOfRangeException(nameof(numBytes), SR.ArgumentOutOfRange_NeedNonNegNum); + if (array.Length - offset < numBytes) + throw new ArgumentException(SR.Argument_InvalidOffLen); + + if (IsClosed) throw new ObjectDisposedException(SR.ObjectDisposed_FileClosed); + if (!CanWrite) throw new NotSupportedException(SR.NotSupported_UnwritableStream); + + if (!IsAsync) + return base.BeginWrite(array, offset, numBytes, callback, state); + else + return TaskToApm.Begin(WriteAsyncInternal(array, offset, numBytes, CancellationToken.None), callback, state); + } + + public override int EndRead(IAsyncResult asyncResult) + { + if (asyncResult == null) + throw new ArgumentNullException(nameof(asyncResult)); + + if (!IsAsync) + return base.EndRead(asyncResult); + else + return TaskToApm.End(asyncResult); + } + + public override void EndWrite(IAsyncResult asyncResult) + { + if (asyncResult == null) + throw new ArgumentNullException(nameof(asyncResult)); + + if (!IsAsync) + base.EndWrite(asyncResult); + else + TaskToApm.End(asyncResult); + } + } +} diff --git a/src/mscorlib/corefx/System/IO/FileStream.Unix.cs b/src/mscorlib/corefx/System/IO/FileStream.Unix.cs new file mode 100644 index 0000000..f83fc84 --- /dev/null +++ b/src/mscorlib/corefx/System/IO/FileStream.Unix.cs @@ -0,0 +1,934 @@ +// 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 Microsoft.Win32.SafeHandles; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; + +namespace System.IO +{ + /// Provides an implementation of a file stream for Unix files. + public partial class FileStream : Stream + { + /// File mode. + private FileMode _mode; + + /// Advanced options requested when opening the file. + private FileOptions _options; + + /// If the file was opened with FileMode.Append, the length of the file when opened; otherwise, -1. + private long _appendStart = -1; + + /// + /// Extra state used by the file stream when _useAsyncIO is true. This includes + /// the semaphore used to serialize all operation, the buffer/offset/count provided by the + /// caller for ReadAsync/WriteAsync operations, and the last successful task returned + /// synchronously from ReadAsync which can be reused if the count matches the next request. + /// Only initialized when is true. + /// + private AsyncState _asyncState; + + /// Lazily-initialized value for whether the file supports seeking. + private bool? _canSeek; + + private SafeFileHandle OpenHandle(FileMode mode, FileShare share, FileOptions options) + { + // FileStream performs most of the general argument validation. We can assume here that the arguments + // are all checked and consistent (e.g. non-null-or-empty path; valid enums in mode, access, share, and options; etc.) + // Store the arguments + _mode = mode; + _options = options; + + if (_useAsyncIO) + _asyncState = new AsyncState(); + + // Translate the arguments into arguments for an open call. + Interop.Sys.OpenFlags openFlags = PreOpenConfigurationFromOptions(mode, _access, options); // FileShare currently ignored + + // If the file gets created a new, we'll select the permissions for it. Most Unix utilities by default use 666 (read and + // write for all), so we do the same (even though this doesn't match Windows, where by default it's possible to write out + // a file and then execute it). No matter what we choose, it'll be subject to the umask applied by the system, such that the + // actual permissions will typically be less than what we select here. + const Interop.Sys.Permissions OpenPermissions = + Interop.Sys.Permissions.S_IRUSR | Interop.Sys.Permissions.S_IWUSR | + Interop.Sys.Permissions.S_IRGRP | Interop.Sys.Permissions.S_IWGRP | + Interop.Sys.Permissions.S_IROTH | Interop.Sys.Permissions.S_IWOTH; + + // Open the file and store the safe handle. + return SafeFileHandle.Open(_path, openFlags, (int)OpenPermissions); + } + + /// Initializes a stream for reading or writing a Unix file. + /// How the file should be opened. + /// What other access to the file should be allowed. This is currently ignored. + private void Init(FileMode mode, FileShare share) + { + _fileHandle.IsAsync = _useAsyncIO; + + // Lock the file if requested via FileShare. This is only advisory locking. FileShare.None implies an exclusive + // lock on the file and all other modes use a shared lock. While this is not as granular as Windows, not mandatory, + // and not atomic with file opening, it's better than nothing. + Interop.Sys.LockOperations lockOperation = (share == FileShare.None) ? Interop.Sys.LockOperations.LOCK_EX : Interop.Sys.LockOperations.LOCK_SH; + if (Interop.Sys.FLock(_fileHandle, lockOperation | Interop.Sys.LockOperations.LOCK_NB) < 0) + { + // The only error we care about is EWOULDBLOCK, which indicates that the file is currently locked by someone + // else and we would block trying to access it. Other errors, such as ENOTSUP (locking isn't supported) or + // EACCES (the file system doesn't allow us to lock), will only hamper FileStream's usage without providing value, + // given again that this is only advisory / best-effort. + Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo(); + if (errorInfo.Error == Interop.Error.EWOULDBLOCK) + { + throw Interop.GetExceptionForIoErrno(errorInfo, _path, isDirectory: false); + } + } + + // These provide hints around how the file will be accessed. Specifying both RandomAccess + // and Sequential together doesn't make sense as they are two competing options on the same spectrum, + // so if both are specified, we prefer RandomAccess (behavior on Windows is unspecified if both are provided). + Interop.Sys.FileAdvice fadv = + (_options & FileOptions.RandomAccess) != 0 ? Interop.Sys.FileAdvice.POSIX_FADV_RANDOM : + (_options & FileOptions.SequentialScan) != 0 ? Interop.Sys.FileAdvice.POSIX_FADV_SEQUENTIAL : + 0; + if (fadv != 0) + { + CheckFileCall(Interop.Sys.PosixFAdvise(_fileHandle, 0, 0, fadv), + ignoreNotSupported: true); // just a hint. + } + + // Jump to the end of the file if opened as Append. + if (_mode == FileMode.Append) + { + _appendStart = SeekCore(0, SeekOrigin.End); + } + } + + /// Initializes a stream from an already open file handle (file descriptor). + /// The handle to the file. + /// The size of the buffer to use when buffering. + /// Whether access to the stream is performed asynchronously. + private void InitFromHandle(SafeFileHandle handle) + { + if (_useAsyncIO) + _asyncState = new AsyncState(); + + if (CanSeekCore) // use non-virtual CanSeekCore rather than CanSeek to avoid making virtual call during ctor + SeekCore(0, SeekOrigin.Current); + } + + /// Translates the FileMode, FileAccess, and FileOptions values into flags to be passed when opening the file. + /// The FileMode provided to the stream's constructor. + /// The FileAccess provided to the stream's constructor + /// The FileOptions provided to the stream's constructor + /// The flags value to be passed to the open system call. + private static Interop.Sys.OpenFlags PreOpenConfigurationFromOptions(FileMode mode, FileAccess access, FileOptions options) + { + // Translate FileMode. Most of the values map cleanly to one or more options for open. + Interop.Sys.OpenFlags flags = default(Interop.Sys.OpenFlags); + switch (mode) + { + default: + case FileMode.Open: // Open maps to the default behavior for open(...). No flags needed. + break; + + case FileMode.Append: // Append is the same as OpenOrCreate, except that we'll also separately jump to the end later + case FileMode.OpenOrCreate: + flags |= Interop.Sys.OpenFlags.O_CREAT; + break; + + case FileMode.Create: + flags |= (Interop.Sys.OpenFlags.O_CREAT | Interop.Sys.OpenFlags.O_TRUNC); + break; + + case FileMode.CreateNew: + flags |= (Interop.Sys.OpenFlags.O_CREAT | Interop.Sys.OpenFlags.O_EXCL); + break; + + case FileMode.Truncate: + flags |= Interop.Sys.OpenFlags.O_TRUNC; + break; + } + + // Translate FileAccess. All possible values map cleanly to corresponding values for open. + switch (access) + { + case FileAccess.Read: + flags |= Interop.Sys.OpenFlags.O_RDONLY; + break; + + case FileAccess.ReadWrite: + flags |= Interop.Sys.OpenFlags.O_RDWR; + break; + + case FileAccess.Write: + flags |= Interop.Sys.OpenFlags.O_WRONLY; + break; + } + + // Translate some FileOptions; some just aren't supported, and others will be handled after calling open. + // - Asynchronous: Handled in ctor, setting _useAsync and SafeFileHandle.IsAsync to true + // - DeleteOnClose: Doesn't have a Unix equivalent, but we approximate it in Dispose + // - Encrypted: No equivalent on Unix and is ignored + // - RandomAccess: Implemented after open if posix_fadvise is available + // - SequentialScan: Implemented after open if posix_fadvise is available + // - WriteThrough: Handled here + if ((options & FileOptions.WriteThrough) != 0) + { + flags |= Interop.Sys.OpenFlags.O_SYNC; + } + + return flags; + } + + /// Gets a value indicating whether the current stream supports seeking. + public override bool CanSeek => CanSeekCore; + + /// Gets a value indicating whether the current stream supports seeking. + /// Separated out of CanSeek to enable making non-virtual call to this logic. + private bool CanSeekCore + { + get + { + if (_fileHandle.IsClosed) + { + return false; + } + + if (!_canSeek.HasValue) + { + // Lazily-initialize whether we're able to seek, tested by seeking to our current location. + _canSeek = Interop.Sys.LSeek(_fileHandle, 0, Interop.Sys.SeekWhence.SEEK_CUR) >= 0; + } + return _canSeek.Value; + } + } + + private long GetLengthInternal() + { + // Get the length of the file as reported by the OS + Interop.Sys.FileStatus status; + CheckFileCall(Interop.Sys.FStat(_fileHandle, out status)); + long length = status.Size; + + // But we may have buffered some data to be written that puts our length + // beyond what the OS is aware of. Update accordingly. + if (_writePos > 0 && _filePosition + _writePos > length) + { + length = _writePos + _filePosition; + } + + return length; + } + + /// Releases the unmanaged resources used by the stream. + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + protected override void Dispose(bool disposing) + { + try + { + if (_fileHandle != null && !_fileHandle.IsClosed) + { + // Flush any remaining data in the file + FlushWriteBuffer(); + + // If DeleteOnClose was requested when constructed, delete the file now. + // (Unix doesn't directly support DeleteOnClose, so we mimic it here.) + if (_path != null && (_options & FileOptions.DeleteOnClose) != 0) + { + // Since we still have the file open, this will end up deleting + // it (assuming we're the only link to it) once it's closed, but the + // name will be removed immediately. + Interop.Sys.Unlink(_path); // ignore errors; it's valid that the path may no longer exist + } + } + } + finally + { + if (_fileHandle != null && !_fileHandle.IsClosed) + { + _fileHandle.Dispose(); + } + base.Dispose(disposing); + } + } + + /// Flushes the OS buffer. This does not flush the internal read/write buffer. + private void FlushOSBuffer() + { + if (Interop.Sys.FSync(_fileHandle) < 0) + { + Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo(); + switch (errorInfo.Error) + { + case Interop.Error.EROFS: + case Interop.Error.EINVAL: + case Interop.Error.ENOTSUP: + // Ignore failures due to the FileStream being bound to a special file that + // doesn't support synchronization. In such cases there's nothing to flush. + break; + default: + throw Interop.GetExceptionForIoErrno(errorInfo, _path, isDirectory: false); + } + } + } + + /// Writes any data in the write buffer to the underlying stream and resets the buffer. + private void FlushWriteBuffer() + { + AssertBufferInvariants(); + if (_writePos > 0) + { + WriteNative(GetBuffer(), 0, _writePos); + _writePos = 0; + } + } + + /// Asynchronously clears all buffers for this stream, causing any buffered data to be written to the underlying device. + /// The token to monitor for cancellation requests. + /// A task that represents the asynchronous flush operation. + private Task FlushAsyncInternal(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return Task.FromCanceled(cancellationToken); + } + if (_fileHandle.IsClosed) + { + throw Error.GetFileNotOpen(); + } + + // As with Win32FileStream, flush the buffers synchronously to avoid race conditions. + try + { + FlushInternalBuffer(); + } + catch (Exception e) + { + return Task.FromException(e); + } + + // We then separately flush to disk asynchronously. This is only + // necessary if we support writing; otherwise, we're done. + if (CanWrite) + { + return Task.Factory.StartNew( + state => ((FileStream)state).FlushOSBuffer(), + this, + cancellationToken, + TaskCreationOptions.DenyChildAttach, + TaskScheduler.Default); + } + else + { + return Task.CompletedTask; + } + } + + /// Sets the length of this stream to the given value. + /// The new length of the stream. + private void SetLengthInternal(long value) + { + FlushInternalBuffer(); + + if (_appendStart != -1 && value < _appendStart) + { + throw new IOException(SR.IO_SetLengthAppendTruncate); + } + + long origPos = _filePosition; + + VerifyOSHandlePosition(); + + if (_filePosition != value) + { + SeekCore(value, SeekOrigin.Begin); + } + + CheckFileCall(Interop.Sys.FTruncate(_fileHandle, value)); + + // Return file pointer to where it was before setting length + if (origPos != value) + { + if (origPos < value) + { + SeekCore(origPos, SeekOrigin.Begin); + } + else + { + SeekCore(0, SeekOrigin.End); + } + } + } + + /// Reads a block of bytes from the stream and writes the data in a given buffer. + /// + /// When this method returns, contains the specified byte array with the values between offset and + /// (offset + count - 1) replaced by the bytes read from the current source. + /// + /// The byte offset in array at which the read bytes will be placed. + /// The maximum number of bytes to read. + /// + /// The total number of bytes read into the buffer. This might be less than the number of bytes requested + /// if that number of bytes are not currently available, or zero if the end of the stream is reached. + /// + public override int Read(byte[] array, int offset, int count) + { + ValidateReadWriteArgs(array, offset, count); + + if (_useAsyncIO) + { + _asyncState.Wait(); + try { return ReadCore(array, offset, count); } + finally { _asyncState.Release(); } + } + else + { + return ReadCore(array, offset, count); + } + } + + /// Reads a block of bytes from the stream and writes the data in a given buffer. + /// + /// When this method returns, contains the specified byte array with the values between offset and + /// (offset + count - 1) replaced by the bytes read from the current source. + /// + /// The byte offset in array at which the read bytes will be placed. + /// The maximum number of bytes to read. + /// + /// The total number of bytes read into the buffer. This might be less than the number of bytes requested + /// if that number of bytes are not currently available, or zero if the end of the stream is reached. + /// + private int ReadCore(byte[] array, int offset, int count) + { + PrepareForReading(); + + // Are there any bytes available in the read buffer? If yes, + // we can just return from the buffer. If the buffer is empty + // or has no more available data in it, we can either refill it + // (and then read from the buffer into the user's buffer) or + // we can just go directly into the user's buffer, if they asked + // for more data than we'd otherwise buffer. + int numBytesAvailable = _readLength - _readPos; + bool readFromOS = false; + if (numBytesAvailable == 0) + { + // If we're not able to seek, then we're not able to rewind the stream (i.e. flushing + // a read buffer), in which case we don't want to use a read buffer. Similarly, if + // the user has asked for more data than we can buffer, we also want to skip the buffer. + if (!CanSeek || (count >= _bufferLength)) + { + // Read directly into the user's buffer + _readPos = _readLength = 0; + return ReadNative(array, offset, count); + } + else + { + // Read into our buffer. + _readLength = numBytesAvailable = ReadNative(GetBuffer(), 0, _bufferLength); + _readPos = 0; + if (numBytesAvailable == 0) + { + return 0; + } + + // Note that we did an OS read as part of this Read, so that later + // we don't try to do one again if what's in the buffer doesn't + // meet the user's request. + readFromOS = true; + } + } + + // Now that we know there's data in the buffer, read from it into the user's buffer. + Debug.Assert(numBytesAvailable > 0, "Data must be in the buffer to be here"); + int bytesRead = Math.Min(numBytesAvailable, count); + Buffer.BlockCopy(GetBuffer(), _readPos, array, offset, bytesRead); + _readPos += bytesRead; + + // We may not have had enough data in the buffer to completely satisfy the user's request. + // While Read doesn't require that we return as much data as the user requested (any amount + // up to the requested count is fine), FileStream on Windows tries to do so by doing a + // subsequent read from the file if we tried to satisfy the request with what was in the + // buffer but the buffer contained less than the requested count. To be consistent with that + // behavior, we do the same thing here on Unix. Note that we may still get less the requested + // amount, as the OS may give us back fewer than we request, either due to reaching the end of + // file, or due to its own whims. + if (!readFromOS && bytesRead < count) + { + Debug.Assert(_readPos == _readLength, "bytesToRead should only be < count if numBytesAvailable < count"); + _readPos = _readLength = 0; // no data left in the read buffer + bytesRead += ReadNative(array, offset + bytesRead, count - bytesRead); + } + + return bytesRead; + } + + /// Unbuffered, reads a block of bytes from the stream and writes the data in a given buffer. + /// + /// When this method returns, contains the specified byte array with the values between offset and + /// (offset + count - 1) replaced by the bytes read from the current source. + /// + /// The byte offset in array at which the read bytes will be placed. + /// The maximum number of bytes to read. + /// + /// The total number of bytes read into the buffer. This might be less than the number of bytes requested + /// if that number of bytes are not currently available, or zero if the end of the stream is reached. + /// + private unsafe int ReadNative(byte[] array, int offset, int count) + { + FlushWriteBuffer(); // we're about to read; dump the write buffer + + VerifyOSHandlePosition(); + + int bytesRead; + fixed (byte* bufPtr = array) + { + bytesRead = CheckFileCall(Interop.Sys.Read(_fileHandle, bufPtr + offset, count)); + Debug.Assert(bytesRead <= count); + } + _filePosition += bytesRead; + return bytesRead; + } + + /// + /// Asynchronously reads a sequence of bytes from the current stream and advances + /// the position within the stream by the number of bytes read. + /// + /// The buffer to write the data into. + /// The byte offset in buffer at which to begin writing data from the stream. + /// The maximum number of bytes to read. + /// The token to monitor for cancellation requests. + /// A task that represents the asynchronous read operation. + private Task ReadAsyncInternal(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + if (_useAsyncIO) + { + if (!CanRead) // match Windows behavior; this gets thrown synchronously + { + throw Error.GetReadNotSupported(); + } + + // Serialize operations using the semaphore. + Task waitTask = _asyncState.WaitAsync(); + + // If we got ownership immediately, and if there's enough data in our buffer + // to satisfy the full request of the caller, hand back the buffered data. + // While it would be a legal implementation of the Read contract, we don't + // hand back here less than the amount requested so as to match the behavior + // in ReadCore that will make a native call to try to fulfill the remainder + // of the request. + if (waitTask.Status == TaskStatus.RanToCompletion) + { + int numBytesAvailable = _readLength - _readPos; + if (numBytesAvailable >= count) + { + try + { + PrepareForReading(); + + Buffer.BlockCopy(GetBuffer(), _readPos, buffer, offset, count); + _readPos += count; + + return _asyncState._lastSuccessfulReadTask != null && _asyncState._lastSuccessfulReadTask.Result == count ? + _asyncState._lastSuccessfulReadTask : + (_asyncState._lastSuccessfulReadTask = Task.FromResult(count)); + } + catch (Exception exc) + { + return Task.FromException(exc); + } + finally + { + _asyncState.Release(); + } + } + } + + // Otherwise, issue the whole request asynchronously. + _asyncState.Update(buffer, offset, count); + return waitTask.ContinueWith((t, s) => + { + // The options available on Unix for writing asynchronously to an arbitrary file + // handle typically amount to just using another thread to do the synchronous write, + // which is exactly what this implementation does. This does mean there are subtle + // differences in certain FileStream behaviors between Windows and Unix when multiple + // asynchronous operations are issued against the stream to execute concurrently; on + // Unix the operations will be serialized due to the usage of a semaphore, but the + // position /length information won't be updated until after the write has completed, + // whereas on Windows it may happen before the write has completed. + + Debug.Assert(t.Status == TaskStatus.RanToCompletion); + var thisRef = (FileStream)s; + try + { + byte[] b = thisRef._asyncState._buffer; + thisRef._asyncState._buffer = null; // remove reference to user's buffer + return thisRef.ReadCore(b, thisRef._asyncState._offset, thisRef._asyncState._count); + } + finally { thisRef._asyncState.Release(); } + }, this, CancellationToken.None, TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default); + } + else + { + return base.ReadAsync(buffer, offset, count, cancellationToken); + } + } + + /// + /// Reads a byte from the stream and advances the position within the stream + /// by one byte, or returns -1 if at the end of the stream. + /// + /// The unsigned byte cast to an Int32, or -1 if at the end of the stream. + public override int ReadByte() + { + if (_useAsyncIO) + { + _asyncState.Wait(); + try { return ReadByteCore(); } + finally { _asyncState.Release(); } + } + else + { + return ReadByteCore(); + } + } + + /// Writes a block of bytes to the file stream. + /// The buffer containing data to write to the stream. + /// The zero-based byte offset in array from which to begin copying bytes to the stream. + /// The maximum number of bytes to write. + public override void Write(byte[] array, int offset, int count) + { + ValidateReadWriteArgs(array, offset, count); + + if (_useAsyncIO) + { + _asyncState.Wait(); + try { WriteCore(array, offset, count); } + finally { _asyncState.Release(); } + } + else + { + WriteCore(array, offset, count); + } + } + + /// Writes a block of bytes to the file stream. + /// The buffer containing data to write to the stream. + /// The zero-based byte offset in array from which to begin copying bytes to the stream. + /// The maximum number of bytes to write. + private void WriteCore(byte[] array, int offset, int count) + { + PrepareForWriting(); + + // If no data is being written, nothing more to do. + if (count == 0) + { + return; + } + + // If there's already data in our write buffer, then we need to go through + // our buffer to ensure data isn't corrupted. + if (_writePos > 0) + { + // If there's space remaining in the buffer, then copy as much as + // we can from the user's buffer into ours. + int spaceRemaining = _bufferLength - _writePos; + if (spaceRemaining > 0) + { + int bytesToCopy = Math.Min(spaceRemaining, count); + Buffer.BlockCopy(array, offset, GetBuffer(), _writePos, bytesToCopy); + _writePos += bytesToCopy; + + // If we've successfully copied all of the user's data, we're done. + if (count == bytesToCopy) + { + return; + } + + // Otherwise, keep track of how much more data needs to be handled. + offset += bytesToCopy; + count -= bytesToCopy; + } + + // At this point, the buffer is full, so flush it out. + FlushWriteBuffer(); + } + + // Our buffer is now empty. If using the buffer would slow things down (because + // the user's looking to write more data than we can store in the buffer), + // skip the buffer. Otherwise, put the remaining data into the buffer. + Debug.Assert(_writePos == 0); + if (count >= _bufferLength) + { + WriteNative(array, offset, count); + } + else + { + Buffer.BlockCopy(array, offset, GetBuffer(), _writePos, count); + _writePos = count; + } + } + + /// Unbuffered, writes a block of bytes to the file stream. + /// The buffer containing data to write to the stream. + /// The zero-based byte offset in array from which to begin copying bytes to the stream. + /// The maximum number of bytes to write. + private unsafe void WriteNative(byte[] array, int offset, int count) + { + VerifyOSHandlePosition(); + + fixed (byte* bufPtr = array) + { + while (count > 0) + { + int bytesWritten = CheckFileCall(Interop.Sys.Write(_fileHandle, bufPtr + offset, count)); + Debug.Assert(bytesWritten <= count); + + _filePosition += bytesWritten; + count -= bytesWritten; + offset += bytesWritten; + } + } + } + + /// + /// Asynchronously writes a sequence of bytes to the current stream, advances + /// the current position within this stream by the number of bytes written, and + /// monitors cancellation requests. + /// + /// The buffer to write data from. + /// The zero-based byte offset in buffer from which to begin copying bytes to the stream. + /// The maximum number of bytes to write. + /// The token to monitor for cancellation requests. + /// A task that represents the asynchronous write operation. + private Task WriteAsyncInternal(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + return Task.FromCanceled(cancellationToken); + + if (_fileHandle.IsClosed) + throw Error.GetFileNotOpen(); + + if (_useAsyncIO) + { + if (!CanWrite) // match Windows behavior; this gets thrown synchronously + { + throw Error.GetWriteNotSupported(); + } + + // Serialize operations using the semaphore. + Task waitTask = _asyncState.WaitAsync(); + + // If we got ownership immediately, and if there's enough space in our buffer + // to buffer the entire write request, then do so and we're done. + if (waitTask.Status == TaskStatus.RanToCompletion) + { + int spaceRemaining = _bufferLength - _writePos; + if (spaceRemaining >= count) + { + try + { + PrepareForWriting(); + + Buffer.BlockCopy(buffer, offset, GetBuffer(), _writePos, count); + _writePos += count; + + return Task.CompletedTask; + } + catch (Exception exc) + { + return Task.FromException(exc); + } + finally + { + _asyncState.Release(); + } + } + } + + // Otherwise, issue the whole request asynchronously. + _asyncState.Update(buffer, offset, count); + return waitTask.ContinueWith((t, s) => + { + // The options available on Unix for writing asynchronously to an arbitrary file + // handle typically amount to just using another thread to do the synchronous write, + // which is exactly what this implementation does. This does mean there are subtle + // differences in certain FileStream behaviors between Windows and Unix when multiple + // asynchronous operations are issued against the stream to execute concurrently; on + // Unix the operations will be serialized due to the usage of a semaphore, but the + // position /length information won't be updated until after the write has completed, + // whereas on Windows it may happen before the write has completed. + + Debug.Assert(t.Status == TaskStatus.RanToCompletion); + var thisRef = (FileStream)s; + try + { + byte[] b = thisRef._asyncState._buffer; + thisRef._asyncState._buffer = null; // remove reference to user's buffer + thisRef.WriteCore(b, thisRef._asyncState._offset, thisRef._asyncState._count); + } + finally { thisRef._asyncState.Release(); } + }, this, CancellationToken.None, TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default); + } + else + { + return base.WriteAsync(buffer, offset, count, cancellationToken); + } + } + + /// + /// Writes a byte to the current position in the stream and advances the position + /// within the stream by one byte. + /// + /// The byte to write to the stream. + public override void WriteByte(byte value) // avoids an array allocation in the base implementation + { + if (_useAsyncIO) + { + _asyncState.Wait(); + try { WriteByteCore(value); } + finally { _asyncState.Release(); } + } + else + { + WriteByteCore(value); + } + } + + /// Prevents other processes from reading from or writing to the FileStream. + /// The beginning of the range to lock. + /// The range to be locked. + private void LockInternal(long position, long length) + { + CheckFileCall(Interop.Sys.LockFileRegion(_fileHandle, position, length, Interop.Sys.LockType.F_WRLCK)); + } + + /// Allows access by other processes to all or part of a file that was previously locked. + /// The beginning of the range to unlock. + /// The range to be unlocked. + private void UnlockInternal(long position, long length) + { + CheckFileCall(Interop.Sys.LockFileRegion(_fileHandle, position, length, Interop.Sys.LockType.F_UNLCK)); + } + + /// Sets the current position of this stream to the given value. + /// The point relative to origin from which to begin seeking. + /// + /// Specifies the beginning, the end, or the current position as a reference + /// point for offset, using a value of type SeekOrigin. + /// + /// The new position in the stream. + public override long Seek(long offset, SeekOrigin origin) + { + if (origin < SeekOrigin.Begin || origin > SeekOrigin.End) + { + throw new ArgumentException(SR.Argument_InvalidSeekOrigin, nameof(origin)); + } + if (_fileHandle.IsClosed) + { + throw Error.GetFileNotOpen(); + } + if (!CanSeek) + { + throw Error.GetSeekNotSupported(); + } + + VerifyOSHandlePosition(); + + // Flush our write/read buffer. FlushWrite will output any write buffer we have and reset _bufferWritePos. + // We don't call FlushRead, as that will do an unnecessary seek to rewind the read buffer, and since we're + // about to seek and update our position, we can simply update the offset as necessary and reset our read + // position and length to 0. (In the future, for some simple cases we could potentially add an optimization + // here to just move data around in the buffer for short jumps, to avoid re-reading the data from disk.) + FlushWriteBuffer(); + if (origin == SeekOrigin.Current) + { + offset -= (_readLength - _readPos); + } + _readPos = _readLength = 0; + + // Keep track of where we were, in case we're in append mode and need to verify + long oldPos = 0; + if (_appendStart >= 0) + { + oldPos = SeekCore(0, SeekOrigin.Current); + } + + // Jump to the new location + long pos = SeekCore(offset, origin); + + // Prevent users from overwriting data in a file that was opened in append mode. + if (_appendStart != -1 && pos < _appendStart) + { + SeekCore(oldPos, SeekOrigin.Begin); + throw new IOException(SR.IO_SeekAppendOverwrite); + } + + // Return the new position + return pos; + } + + /// Sets the current position of this stream to the given value. + /// The point relative to origin from which to begin seeking. + /// + /// Specifies the beginning, the end, or the current position as a reference + /// point for offset, using a value of type SeekOrigin. + /// + /// The new position in the stream. + private long SeekCore(long offset, SeekOrigin origin) + { + Debug.Assert(!_fileHandle.IsClosed && (GetType() != typeof(FileStream) || CanSeek)); // verify that we can seek, but only if CanSeek won't be a virtual call (which could happen in the ctor) + Debug.Assert(origin >= SeekOrigin.Begin && origin <= SeekOrigin.End); + + long pos = CheckFileCall(Interop.Sys.LSeek(_fileHandle, offset, (Interop.Sys.SeekWhence)(int)origin)); // SeekOrigin values are the same as Interop.libc.SeekWhence values + _filePosition = pos; + return pos; + } + + private long CheckFileCall(long result, bool ignoreNotSupported = false) + { + if (result < 0) + { + Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo(); + if (!(ignoreNotSupported && errorInfo.Error == Interop.Error.ENOTSUP)) + { + throw Interop.GetExceptionForIoErrno(errorInfo, _path, isDirectory: false); + } + } + + return result; + } + + private int CheckFileCall(int result, bool ignoreNotSupported = false) + { + CheckFileCall((long)result, ignoreNotSupported); + + return result; + } + + /// State used when the stream is in async mode. + private sealed class AsyncState : SemaphoreSlim + { + /// The caller's buffer currently being used by the active async operation. + internal byte[] _buffer; + /// The caller's offset currently being used by the active async operation. + internal int _offset; + /// The caller's count currently being used by the active async operation. + internal int _count; + /// The last task successfully, synchronously returned task from ReadAsync. + internal Task _lastSuccessfulReadTask; + + /// Initialize the AsyncState. + internal AsyncState() : base(initialCount: 1, maxCount: 1) { } + + /// Sets the active buffer, offset, and count. + internal void Update(byte[] buffer, int offset, int count) + { + _buffer = buffer; + _offset = offset; + _count = count; + } + } + } +} diff --git a/src/mscorlib/corefx/System/IO/FileStream.Win32.cs b/src/mscorlib/corefx/System/IO/FileStream.Win32.cs new file mode 100644 index 0000000..350d948 --- /dev/null +++ b/src/mscorlib/corefx/System/IO/FileStream.Win32.cs @@ -0,0 +1,1770 @@ +// 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.Buffers; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Win32.SafeHandles; +using System.Runtime.CompilerServices; + +/* + * Win32FileStream supports different modes of accessing the disk - async mode + * and sync mode. They are two completely different codepaths in the + * sync & async methods (i.e. Read/Write vs. ReadAsync/WriteAsync). File + * handles in NT can be opened in only sync or overlapped (async) mode, + * and we have to deal with this pain. Stream has implementations of + * the sync methods in terms of the async ones, so we'll + * call through to our base class to get those methods when necessary. + * + * Also buffering is added into Win32FileStream as well. Folded in the + * code from BufferedStream, so all the comments about it being mostly + * aggressive (and the possible perf improvement) apply to Win32FileStream as + * well. Also added some buffering to the async code paths. + * + * Class Invariants: + * The class has one buffer, shared for reading & writing. It can only be + * used for one or the other at any point in time - not both. The following + * should be true: + * 0 <= _readPos <= _readLen < _bufferSize + * 0 <= _writePos < _bufferSize + * _readPos == _readLen && _readPos > 0 implies the read buffer is valid, + * but we're at the end of the buffer. + * _readPos == _readLen == 0 means the read buffer contains garbage. + * Either _writePos can be greater than 0, or _readLen & _readPos can be + * greater than zero, but neither can be greater than zero at the same time. + * + */ + +namespace System.IO +{ + public partial class FileStream : Stream + { + private bool _canSeek; + private bool _isPipe; // Whether to disable async buffering code. + private long _appendStart; // When appending, prevent overwriting file. + + private static unsafe IOCompletionCallback s_ioCallback = FileStreamCompletionSource.IOCallback; + + private Task _lastSynchronouslyCompletedTask = null; // cached task for read ops that complete synchronously + private Task _activeBufferOperation = null; // tracks in-progress async ops using the buffer + private PreAllocatedOverlapped _preallocatedOverlapped; // optimization for async ops to avoid per-op allocations + private FileStreamCompletionSource _currentOverlappedOwner; // async op currently using the preallocated overlapped + + private SafeFileHandle OpenHandle(FileMode mode, FileShare share, FileOptions options) + { + Interop.mincore.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share); + + int fAccess = + ((_access & FileAccess.Read) == FileAccess.Read ? GENERIC_READ : 0) | + ((_access & FileAccess.Write) == FileAccess.Write ? GENERIC_WRITE : 0); + + // Our Inheritable bit was stolen from Windows, but should be set in + // the security attributes class. Don't leave this bit set. + share &= ~FileShare.Inheritable; + + // Must use a valid Win32 constant here... + if (mode == FileMode.Append) + mode = FileMode.OpenOrCreate; + + int flagsAndAttributes = (int)options; + + // For mitigating local elevation of privilege attack through named pipes + // make sure we always call CreateFile with SECURITY_ANONYMOUS so that the + // named pipe server can't impersonate a high privileged client security context + flagsAndAttributes |= (Interop.mincore.SecurityOptions.SECURITY_SQOS_PRESENT | Interop.mincore.SecurityOptions.SECURITY_ANONYMOUS); + + // Don't pop up a dialog for reading from an empty floppy drive + uint oldMode = Interop.mincore.SetErrorMode(Interop.mincore.SEM_FAILCRITICALERRORS); + try + { + SafeFileHandle fileHandle = Interop.mincore.SafeCreateFile(_path, fAccess, share, ref secAttrs, mode, flagsAndAttributes, IntPtr.Zero); + fileHandle.IsAsync = _useAsyncIO; + + if (fileHandle.IsInvalid) + { + // Return a meaningful exception with the full path. + + // NT5 oddity - when trying to open "C:\" as a Win32FileStream, + // we usually get ERROR_PATH_NOT_FOUND from the OS. We should + // probably be consistent w/ every other directory. + int errorCode = Marshal.GetLastWin32Error(); + + if (errorCode == Interop.mincore.Errors.ERROR_PATH_NOT_FOUND && _path.Equals(Directory.InternalGetDirectoryRoot(_path))) + errorCode = Interop.mincore.Errors.ERROR_ACCESS_DENIED; + + throw Win32Marshal.GetExceptionForWin32Error(errorCode, _path); + } + + return fileHandle; + } + finally + { + Interop.mincore.SetErrorMode(oldMode); + } + } + + private void Init(FileMode mode, FileShare share) + { + // Disallow access to all non-file devices from the Win32FileStream + // constructors that take a String. Everyone else can call + // CreateFile themselves then use the constructor that takes an + // IntPtr. Disallows "con:", "com1:", "lpt1:", etc. + int fileType = Interop.mincore.GetFileType(_fileHandle); + if (fileType != Interop.mincore.FileTypes.FILE_TYPE_DISK) + { + _fileHandle.Dispose(); + throw new NotSupportedException(SR.NotSupported_FileStreamOnNonFiles); + } + + // This is necessary for async IO using IO Completion ports via our + // managed Threadpool API's. This (theoretically) calls the OS's + // BindIoCompletionCallback method, and passes in a stub for the + // LPOVERLAPPED_COMPLETION_ROUTINE. This stub looks at the Overlapped + // struct for this request and gets a delegate to a managed callback + // from there, which it then calls on a threadpool thread. (We allocate + // our native OVERLAPPED structs 2 pointers too large and store EE state + // & GC handles there, one to an IAsyncResult, the other to a delegate.) + if (_useAsyncIO) + { + try + { + _fileHandle.ThreadPoolBinding = ThreadPoolBoundHandle.BindHandle(_fileHandle); + } + catch (ArgumentException ex) + { + throw new IOException(SR.IO_BindHandleFailed, ex); + } + finally + { + if (_fileHandle.ThreadPoolBinding == null) + { + // We should close the handle so that the handle is not open until SafeFileHandle GC + Debug.Assert(!_exposedHandle, "Are we closing handle that we exposed/not own, how?"); + _fileHandle.Dispose(); + } + } + } + + _canSeek = true; + + // For Append mode... + if (mode == FileMode.Append) + { + _appendStart = SeekCore(0, SeekOrigin.End); + } + else + { + _appendStart = -1; + } + } + + private void InitFromHandle(SafeFileHandle handle) + { + int handleType = Interop.mincore.GetFileType(_fileHandle); + Debug.Assert(handleType == Interop.mincore.FileTypes.FILE_TYPE_DISK || handleType == Interop.mincore.FileTypes.FILE_TYPE_PIPE || handleType == Interop.mincore.FileTypes.FILE_TYPE_CHAR, "FileStream was passed an unknown file type!"); + + _canSeek = handleType == Interop.mincore.FileTypes.FILE_TYPE_DISK; + _isPipe = handleType == Interop.mincore.FileTypes.FILE_TYPE_PIPE; + + // This is necessary for async IO using IO Completion ports via our + // managed Threadpool API's. This calls the OS's + // BindIoCompletionCallback method, and passes in a stub for the + // LPOVERLAPPED_COMPLETION_ROUTINE. This stub looks at the Overlapped + // struct for this request and gets a delegate to a managed callback + // from there, which it then calls on a threadpool thread. (We allocate + // our native OVERLAPPED structs 2 pointers too large and store EE + // state & a handle to a delegate there.) + // + // If, however, we've already bound this file handle to our completion port, + // don't try to bind it again because it will fail. A handle can only be + // bound to a single completion port at a time. + if (_useAsyncIO && !GetSuppressBindHandle(handle)) + { + try + { + _fileHandle.ThreadPoolBinding = ThreadPoolBoundHandle.BindHandle(_fileHandle); + } + catch (Exception ex) + { + // If you passed in a synchronous handle and told us to use + // it asynchronously, throw here. + throw new ArgumentException(SR.Arg_HandleNotAsync, nameof(handle), ex); + } + } + else if (!_useAsyncIO) + { + if (handleType != Interop.mincore.FileTypes.FILE_TYPE_PIPE) + VerifyHandleIsSync(); + } + + if (_canSeek) + SeekCore(0, SeekOrigin.Current); + else + _filePosition = 0; + } + + private static bool GetSuppressBindHandle(SafeFileHandle handle) + { + return handle.IsAsync.HasValue ? handle.IsAsync.Value : false; + } + + private unsafe static Interop.mincore.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share) + { + Interop.mincore.SECURITY_ATTRIBUTES secAttrs = default(Interop.mincore.SECURITY_ATTRIBUTES); + if ((share & FileShare.Inheritable) != 0) + { + secAttrs = new Interop.mincore.SECURITY_ATTRIBUTES(); + secAttrs.nLength = (uint)sizeof(Interop.mincore.SECURITY_ATTRIBUTES); + + secAttrs.bInheritHandle = Interop.BOOL.TRUE; + } + return secAttrs; + } + + // Verifies that this handle supports synchronous IO operations (unless you + // didn't open it for either reading or writing). + private unsafe void VerifyHandleIsSync() + { + Debug.Assert(!_useAsyncIO); + + // Do NOT use this method on pipes. Reading or writing to a pipe may + // cause an app to block incorrectly, introducing a deadlock (depending + // on whether a write will wake up an already-blocked thread or this + // Win32FileStream's thread). + Debug.Assert(Interop.mincore.GetFileType(_fileHandle) != Interop.mincore.FileTypes.FILE_TYPE_PIPE); + + byte* bytes = stackalloc byte[1]; + int numBytesReadWritten; + int r = -1; + + // If the handle is a pipe, ReadFile will block until there + // has been a write on the other end. We'll just have to deal with it, + // For the read end of a pipe, you can mess up and + // accidentally read synchronously from an async pipe. + if ((_access & FileAccess.Read) != 0) // don't use the virtual CanRead or CanWrite, as this may be used in the ctor + { + r = Interop.mincore.ReadFile(_fileHandle, bytes, 0, out numBytesReadWritten, IntPtr.Zero); + } + else if ((_access & FileAccess.Write) != 0) // don't use the virtual CanRead or CanWrite, as this may be used in the ctor + { + r = Interop.mincore.WriteFile(_fileHandle, bytes, 0, out numBytesReadWritten, IntPtr.Zero); + } + + if (r == 0) + { + int errorCode = GetLastWin32ErrorAndDisposeHandleIfInvalid(throwIfInvalidHandle: true); + if (errorCode == ERROR_INVALID_PARAMETER) + throw new ArgumentException(SR.Arg_HandleNotSync, "handle"); + } + } + + private bool HasActiveBufferOperation + { + get { return _activeBufferOperation != null && !_activeBufferOperation.IsCompleted; } + } + + public override bool CanSeek + { + get { return _canSeek; } + } + + private long GetLengthInternal() + { + Interop.mincore.FILE_STANDARD_INFO info = new Interop.mincore.FILE_STANDARD_INFO(); + + if (!Interop.mincore.GetFileInformationByHandleEx(_fileHandle, Interop.mincore.FILE_INFO_BY_HANDLE_CLASS.FileStandardInfo, out info, (uint)Marshal.SizeOf())) + throw Win32Marshal.GetExceptionForLastWin32Error(); + long len = info.EndOfFile; + // If we're writing near the end of the file, we must include our + // internal buffer in our Length calculation. Don't flush because + // we use the length of the file in our async write method. + if (_writePos > 0 && _filePosition + _writePos > len) + len = _writePos + _filePosition; + return len; + } + + protected override void Dispose(bool disposing) + { + // Nothing will be done differently based on whether we are + // disposing vs. finalizing. This is taking advantage of the + // weak ordering between normal finalizable objects & critical + // finalizable objects, which I included in the SafeHandle + // design for Win32FileStream, which would often "just work" when + // finalized. + try + { + if (_fileHandle != null && !_fileHandle.IsClosed) + { + // Flush data to disk iff we were writing. After + // thinking about this, we also don't need to flush + // our read position, regardless of whether the handle + // was exposed to the user. They probably would NOT + // want us to do this. + if (_writePos > 0) + { + FlushWriteBuffer(!disposing); + } + } + } + finally + { + if (_fileHandle != null && !_fileHandle.IsClosed) + { + if (_fileHandle.ThreadPoolBinding != null) + _fileHandle.ThreadPoolBinding.Dispose(); + + _fileHandle.Dispose(); + } + + if (_preallocatedOverlapped != null) + _preallocatedOverlapped.Dispose(); + + _canSeek = false; + + // Don't set the buffer to null, to avoid a NullReferenceException + // when users have a race condition in their code (i.e. they call + // Close when calling another method on Stream like Read). + //_buffer = null; + base.Dispose(disposing); + } + } + + private void FlushOSBuffer() + { + if (!Interop.mincore.FlushFileBuffers(_fileHandle)) + { + throw Win32Marshal.GetExceptionForLastWin32Error(); + } + } + + // Returns a task that flushes the internal write buffer + private Task FlushWriteAsync(CancellationToken cancellationToken) + { + Debug.Assert(_useAsyncIO); + Debug.Assert(_readPos == 0 && _readLength == 0, "FileStream: Read buffer must be empty in FlushWriteAsync!"); + + // If the buffer is already flushed, don't spin up the OS write + if (_writePos == 0) return Task.CompletedTask; + + Task flushTask = WriteInternalCoreAsync(GetBuffer(), 0, _writePos, cancellationToken); + _writePos = 0; + + // Update the active buffer operation + _activeBufferOperation = HasActiveBufferOperation ? + Task.WhenAll(_activeBufferOperation, flushTask) : + flushTask; + + return flushTask; + } + + // Writes are buffered. Anytime the buffer fills up + // (_writePos + delta > _bufferSize) or the buffer switches to reading + // and there is left over data (_writePos > 0), this function must be called. + private void FlushWriteBuffer(bool calledFromFinalizer = false) + { + if (_writePos == 0) return; + Debug.Assert(_readPos == 0 && _readLength == 0, "FileStream: Read buffer must be empty in FlushWrite!"); + + if (_useAsyncIO) + { + Task writeTask = FlushWriteAsync(CancellationToken.None); + // With our Whidbey async IO & overlapped support for AD unloads, + // we don't strictly need to block here to release resources + // since that support takes care of the pinning & freeing the + // overlapped struct. We need to do this when called from + // Close so that the handle is closed when Close returns, but + // we don't need to call EndWrite from the finalizer. + // Additionally, if we do call EndWrite, we block forever + // because AD unloads prevent us from running the managed + // callback from the IO completion port. Blocking here when + // called from the finalizer during AD unload is clearly wrong, + // but we can't use any sort of test for whether the AD is + // unloading because if we weren't unloading, an AD unload + // could happen on a separate thread before we call EndWrite. + if (!calledFromFinalizer) + { + writeTask.GetAwaiter().GetResult(); + } + } + else + { + WriteCore(GetBuffer(), 0, _writePos); + } + + _writePos = 0; + } + + private void SetLengthInternal(long value) + { + // Handle buffering updates. + if (_writePos > 0) + { + FlushWriteBuffer(); + } + else if (_readPos < _readLength) + { + FlushReadBuffer(); + } + _readPos = 0; + _readLength = 0; + + if (_appendStart != -1 && value < _appendStart) + throw new IOException(SR.IO_SetLengthAppendTruncate); + SetLengthCore(value); + } + + // We absolutely need this method broken out so that WriteInternalCoreAsync can call + // a method without having to go through buffering code that might call FlushWrite. + private void SetLengthCore(long value) + { + Debug.Assert(value >= 0, "value >= 0"); + long origPos = _filePosition; + + VerifyOSHandlePosition(); + if (_filePosition != value) + SeekCore(value, SeekOrigin.Begin); + if (!Interop.mincore.SetEndOfFile(_fileHandle)) + { + int errorCode = Marshal.GetLastWin32Error(); + if (errorCode == Interop.mincore.Errors.ERROR_INVALID_PARAMETER) + throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_FileLengthTooBig); + throw Win32Marshal.GetExceptionForWin32Error(errorCode); + } + // Return file pointer to where it was before setting length + if (origPos != value) + { + if (origPos < value) + SeekCore(origPos, SeekOrigin.Begin); + else + SeekCore(0, SeekOrigin.End); + } + } + + // Instance method to help code external to this MarshalByRefObject avoid + // accessing its fields by ref. This avoids a compiler warning. + private FileStreamCompletionSource CompareExchangeCurrentOverlappedOwner(FileStreamCompletionSource newSource, FileStreamCompletionSource existingSource) => Interlocked.CompareExchange(ref _currentOverlappedOwner, newSource, existingSource); + + public override int Read(byte[] array, int offset, int count) + { + ValidateReadWriteArgs(array, offset, count); + return ReadCore(array, offset, count); + } + + private int ReadCore(byte[] array, int offset, int count) + { + Debug.Assert((_readPos == 0 && _readLength == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLength), + "We're either reading or writing, but not both."); + + bool isBlocked = false; + int n = _readLength - _readPos; + // if the read buffer is empty, read into either user's array or our + // buffer, depending on number of bytes user asked for and buffer size. + if (n == 0) + { + if (!CanRead) throw Error.GetReadNotSupported(); + if (_writePos > 0) FlushWriteBuffer(); + if (!CanSeek || (count >= _bufferLength)) + { + n = ReadNative(array, offset, count); + // Throw away read buffer. + _readPos = 0; + _readLength = 0; + return n; + } + n = ReadNative(GetBuffer(), 0, _bufferLength); + if (n == 0) return 0; + isBlocked = n < _bufferLength; + _readPos = 0; + _readLength = n; + } + // Now copy min of count or numBytesAvailable (i.e. near EOF) to array. + if (n > count) n = count; + Buffer.BlockCopy(GetBuffer(), _readPos, array, offset, n); + _readPos += n; + + // We may have read less than the number of bytes the user asked + // for, but that is part of the Stream contract. Reading again for + // more data may cause us to block if we're using a device with + // no clear end of file, such as a serial port or pipe. If we + // blocked here & this code was used with redirected pipes for a + // process's standard output, this can lead to deadlocks involving + // two processes. But leave this here for files to avoid what would + // probably be a breaking change. -- + + // If we are reading from a device with no clear EOF like a + // serial port or a pipe, this will cause us to block incorrectly. + if (!_isPipe) + { + // If we hit the end of the buffer and didn't have enough bytes, we must + // read some more from the underlying stream. However, if we got + // fewer bytes from the underlying stream than we asked for (i.e. we're + // probably blocked), don't ask for more bytes. + if (n < count && !isBlocked) + { + Debug.Assert(_readPos == _readLength, "Read buffer should be empty!"); + int moreBytesRead = ReadNative(array, offset + n, count - n); + n += moreBytesRead; + // We've just made our buffer inconsistent with our position + // pointer. We must throw away the read buffer. + _readPos = 0; + _readLength = 0; + } + } + + return n; + } + + [Conditional("DEBUG")] + private void AssertCanRead(byte[] buffer, int offset, int count) + { + Debug.Assert(!_fileHandle.IsClosed, "!_fileHandle.IsClosed"); + Debug.Assert(CanRead, "CanRead"); + Debug.Assert(buffer != null, "buffer != null"); + Debug.Assert(_writePos == 0, "_writePos == 0"); + Debug.Assert(offset >= 0, "offset is negative"); + Debug.Assert(count >= 0, "count is negative"); + } + + private unsafe int ReadNative(byte[] buffer, int offset, int count) + { + AssertCanRead(buffer, offset, count); + + if (_useAsyncIO) + return ReadNativeAsync(buffer, offset, count, 0, CancellationToken.None).GetAwaiter().GetResult(); + + // Make sure we are reading from the right spot + VerifyOSHandlePosition(); + + int errorCode = 0; + int r = ReadFileNative(_fileHandle, buffer, offset, count, null, out errorCode); + + if (r == -1) + { + // For pipes, ERROR_BROKEN_PIPE is the normal end of the pipe. + if (errorCode == ERROR_BROKEN_PIPE) + { + r = 0; + } + else + { + if (errorCode == ERROR_INVALID_PARAMETER) + throw new ArgumentException(SR.Arg_HandleNotSync, "_fileHandle"); + + throw Win32Marshal.GetExceptionForWin32Error(errorCode); + } + } + Debug.Assert(r >= 0, "FileStream's ReadNative is likely broken."); + _filePosition += r; + + return r; + } + + public override long Seek(long offset, SeekOrigin origin) + { + if (origin < SeekOrigin.Begin || origin > SeekOrigin.End) + throw new ArgumentException(SR.Argument_InvalidSeekOrigin, nameof(origin)); + if (_fileHandle.IsClosed) throw Error.GetFileNotOpen(); + if (!CanSeek) throw Error.GetSeekNotSupported(); + + Debug.Assert((_readPos == 0 && _readLength == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLength), "We're either reading or writing, but not both."); + + // If we've got bytes in our buffer to write, write them out. + // If we've read in and consumed some bytes, we'll have to adjust + // our seek positions ONLY IF we're seeking relative to the current + // position in the stream. This simulates doing a seek to the new + // position, then a read for the number of bytes we have in our buffer. + if (_writePos > 0) + { + FlushWriteBuffer(); + } + else if (origin == SeekOrigin.Current) + { + // Don't call FlushRead here, which would have caused an infinite + // loop. Simply adjust the seek origin. This isn't necessary + // if we're seeking relative to the beginning or end of the stream. + offset -= (_readLength - _readPos); + } + _readPos = _readLength = 0; + + // Verify that internal position is in sync with the handle + VerifyOSHandlePosition(); + + long oldPos = _filePosition + (_readPos - _readLength); + long pos = SeekCore(offset, origin); + + // Prevent users from overwriting data in a file that was opened in + // append mode. + if (_appendStart != -1 && pos < _appendStart) + { + SeekCore(oldPos, SeekOrigin.Begin); + throw new IOException(SR.IO_SeekAppendOverwrite); + } + + // We now must update the read buffer. We can in some cases simply + // update _readPos within the buffer, copy around the buffer so our + // Position property is still correct, and avoid having to do more + // reads from the disk. Otherwise, discard the buffer's contents. + if (_readLength > 0) + { + // We can optimize the following condition: + // oldPos - _readPos <= pos < oldPos + _readLen - _readPos + if (oldPos == pos) + { + if (_readPos > 0) + { + //Console.WriteLine("Seek: seeked for 0, adjusting buffer back by: "+_readPos+" _readLen: "+_readLen); + Buffer.BlockCopy(GetBuffer(), _readPos, GetBuffer(), 0, _readLength - _readPos); + _readLength -= _readPos; + _readPos = 0; + } + // If we still have buffered data, we must update the stream's + // position so our Position property is correct. + if (_readLength > 0) + SeekCore(_readLength, SeekOrigin.Current); + } + else if (oldPos - _readPos < pos && pos < oldPos + _readLength - _readPos) + { + int diff = (int)(pos - oldPos); + //Console.WriteLine("Seek: diff was "+diff+", readpos was "+_readPos+" adjusting buffer - shrinking by "+ (_readPos + diff)); + Buffer.BlockCopy(GetBuffer(), _readPos + diff, GetBuffer(), 0, _readLength - (_readPos + diff)); + _readLength -= (_readPos + diff); + _readPos = 0; + if (_readLength > 0) + SeekCore(_readLength, SeekOrigin.Current); + } + else + { + // Lose the read buffer. + _readPos = 0; + _readLength = 0; + } + Debug.Assert(_readLength >= 0 && _readPos <= _readLength, "_readLen should be nonnegative, and _readPos should be less than or equal _readLen"); + Debug.Assert(pos == Position, "Seek optimization: pos != Position! Buffer math was mangled."); + } + return pos; + } + + // This doesn't do argument checking. Necessary for SetLength, which must + // set the file pointer beyond the end of the file. This will update the + // internal position + // This is called during construction so it should avoid any virtual + // calls + private long SeekCore(long offset, SeekOrigin origin) + { + Debug.Assert(!_fileHandle.IsClosed && _canSeek, "!_handle.IsClosed && _parent.CanSeek"); + Debug.Assert(origin >= SeekOrigin.Begin && origin <= SeekOrigin.End, "origin>=SeekOrigin.Begin && origin<=SeekOrigin.End"); + long ret = 0; + + if (!Interop.mincore.SetFilePointerEx(_fileHandle, offset, out ret, (uint)origin)) + { + int errorCode = GetLastWin32ErrorAndDisposeHandleIfInvalid(); + throw Win32Marshal.GetExceptionForWin32Error(errorCode); + } + + _filePosition = ret; + return ret; + } + + partial void OnBufferAllocated() + { + Debug.Assert(_buffer != null); + Debug.Assert(_preallocatedOverlapped == null); + + if (_useAsyncIO) + _preallocatedOverlapped = new PreAllocatedOverlapped(s_ioCallback, this, _buffer); + } + + public override void Write(byte[] array, int offset, int count) + { + ValidateReadWriteArgs(array, offset, count); + + if (_writePos == 0) + { + // Ensure we can write to the stream, and ready buffer for writing. + if (!CanWrite) throw Error.GetWriteNotSupported(); + if (_readPos < _readLength) FlushReadBuffer(); + _readPos = 0; + _readLength = 0; + } + + // If our buffer has data in it, copy data from the user's array into + // the buffer, and if we can fit it all there, return. Otherwise, write + // the buffer to disk and copy any remaining data into our buffer. + // The assumption here is memcpy is cheaper than disk (or net) IO. + // (10 milliseconds to disk vs. ~20-30 microseconds for a 4K memcpy) + // So the extra copying will reduce the total number of writes, in + // non-pathological cases (i.e. write 1 byte, then write for the buffer + // size repeatedly) + if (_writePos > 0) + { + int numBytes = _bufferLength - _writePos; // space left in buffer + if (numBytes > 0) + { + if (numBytes > count) + numBytes = count; + Buffer.BlockCopy(array, offset, GetBuffer(), _writePos, numBytes); + _writePos += numBytes; + if (count == numBytes) return; + offset += numBytes; + count -= numBytes; + } + // Reset our buffer. We essentially want to call FlushWrite + // without calling Flush on the underlying Stream. + + if (_useAsyncIO) + { + WriteInternalCoreAsync(GetBuffer(), 0, _writePos, CancellationToken.None).GetAwaiter().GetResult(); + } + else + { + WriteCore(GetBuffer(), 0, _writePos); + } + _writePos = 0; + } + // If the buffer would slow writes down, avoid buffer completely. + if (count >= _bufferLength) + { + Debug.Assert(_writePos == 0, "FileStream cannot have buffered data to write here! Your stream will be corrupted."); + WriteCore(array, offset, count); + return; + } + else if (count == 0) + { + return; // Don't allocate a buffer then call memcpy for 0 bytes. + } + + // Copy remaining bytes into buffer, to write at a later date. + Buffer.BlockCopy(array, offset, GetBuffer(), _writePos, count); + _writePos = count; + return; + } + + private unsafe void WriteCore(byte[] buffer, int offset, int count) + { + Debug.Assert(!_fileHandle.IsClosed, "!_handle.IsClosed"); + Debug.Assert(CanWrite, "_parent.CanWrite"); + + Debug.Assert(buffer != null, "buffer != null"); + Debug.Assert(_readPos == _readLength, "_readPos == _readLen"); + Debug.Assert(offset >= 0, "offset is negative"); + Debug.Assert(count >= 0, "count is negative"); + if (_useAsyncIO) + { + WriteInternalCoreAsync(buffer, offset, count, CancellationToken.None).GetAwaiter().GetResult(); + return; + } + + // Make sure we are writing to the position that we think we are + VerifyOSHandlePosition(); + + int errorCode = 0; + int r = WriteFileNative(_fileHandle, buffer, offset, count, null, out errorCode); + + if (r == -1) + { + // For pipes, ERROR_NO_DATA is not an error, but the pipe is closing. + if (errorCode == ERROR_NO_DATA) + { + r = 0; + } + else + { + // ERROR_INVALID_PARAMETER may be returned for writes + // where the position is too large (i.e. writing at Int64.MaxValue + // on Win9x) OR for synchronous writes to a handle opened + // asynchronously. + if (errorCode == ERROR_INVALID_PARAMETER) + throw new IOException(SR.IO_FileTooLongOrHandleNotSync); + throw Win32Marshal.GetExceptionForWin32Error(errorCode); + } + } + Debug.Assert(r >= 0, "FileStream's WriteCore is likely broken."); + _filePosition += r; + return; + } + + private Task ReadAsyncInternal(byte[] array, int offset, int numBytes, CancellationToken cancellationToken) + { + // If async IO is not supported on this platform or + // if this Win32FileStream was not opened with FileOptions.Asynchronous. + if (!_useAsyncIO) + { + return base.ReadAsync(array, offset, numBytes, cancellationToken); + } + + if (!CanRead) throw Error.GetReadNotSupported(); + + Debug.Assert((_readPos == 0 && _readLength == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLength), "We're either reading or writing, but not both."); + + if (_isPipe) + { + // Pipes are tricky, at least when you have 2 different pipes + // that you want to use simultaneously. When redirecting stdout + // & stderr with the Process class, it's easy to deadlock your + // parent & child processes when doing writes 4K at a time. The + // OS appears to use a 4K buffer internally. If you write to a + // pipe that is full, you will block until someone read from + // that pipe. If you try reading from an empty pipe and + // Win32FileStream's ReadAsync blocks waiting for data to fill it's + // internal buffer, you will be blocked. In a case where a child + // process writes to stdout & stderr while a parent process tries + // reading from both, you can easily get into a deadlock here. + // To avoid this deadlock, don't buffer when doing async IO on + // pipes. But don't completely ignore buffered data either. + if (_readPos < _readLength) + { + int n = _readLength - _readPos; + if (n > numBytes) n = numBytes; + Buffer.BlockCopy(GetBuffer(), _readPos, array, offset, n); + _readPos += n; + + // Return a completed task + return TaskFromResultOrCache(n); + } + else + { + Debug.Assert(_writePos == 0, "Win32FileStream must not have buffered write data here! Pipes should be unidirectional."); + return ReadNativeAsync(array, offset, numBytes, 0, cancellationToken); + } + } + + Debug.Assert(!_isPipe, "Should not be a pipe."); + + // Handle buffering. + if (_writePos > 0) FlushWriteBuffer(); + if (_readPos == _readLength) + { + // I can't see how to handle buffering of async requests when + // filling the buffer asynchronously, without a lot of complexity. + // The problems I see are issuing an async read, we do an async + // read to fill the buffer, then someone issues another read + // (either synchronously or asynchronously) before the first one + // returns. This would involve some sort of complex buffer locking + // that we probably don't want to get into, at least not in V1. + // If we did a sync read to fill the buffer, we could avoid the + // problem, and any async read less than 64K gets turned into a + // synchronous read by NT anyways... -- + + if (numBytes < _bufferLength) + { + Task readTask = ReadNativeAsync(GetBuffer(), 0, _bufferLength, 0, cancellationToken); + _readLength = readTask.GetAwaiter().GetResult(); + int n = _readLength; + if (n > numBytes) n = numBytes; + Buffer.BlockCopy(GetBuffer(), 0, array, offset, n); + _readPos = n; + + // Return a completed task (recycling the one above if possible) + return (_readLength == n ? readTask : TaskFromResultOrCache(n)); + } + else + { + // Here we're making our position pointer inconsistent + // with our read buffer. Throw away the read buffer's contents. + _readPos = 0; + _readLength = 0; + return ReadNativeAsync(array, offset, numBytes, 0, cancellationToken); + } + } + else + { + int n = _readLength - _readPos; + if (n > numBytes) n = numBytes; + Buffer.BlockCopy(GetBuffer(), _readPos, array, offset, n); + _readPos += n; + + if (n >= numBytes) + { + // Return a completed task + return TaskFromResultOrCache(n); + } + else + { + // For streams with no clear EOF like serial ports or pipes + // we cannot read more data without causing an app to block + // incorrectly. Pipes don't go down this path + // though. This code needs to be fixed. + // Throw away read buffer. + _readPos = 0; + _readLength = 0; + return ReadNativeAsync(array, offset + n, numBytes - n, n, cancellationToken); + } + } + } + + unsafe private Task ReadNativeAsync(byte[] bytes, int offset, int numBytes, int numBufferedBytesRead, CancellationToken cancellationToken) + { + AssertCanRead(bytes, offset, numBytes); + Debug.Assert(_useAsyncIO, "ReadNativeAsync doesn't work on synchronous file streams!"); + + // Create and store async stream class library specific data in the async result + + FileStreamCompletionSource completionSource = new FileStreamCompletionSource(this, numBufferedBytesRead, bytes, cancellationToken); + NativeOverlapped* intOverlapped = completionSource.Overlapped; + + // Calculate position in the file we should be at after the read is done + if (CanSeek) + { + long len = Length; + + // Make sure we are reading from the position that we think we are + VerifyOSHandlePosition(); + + if (_filePosition + numBytes > len) + { + if (_filePosition <= len) + numBytes = (int)(len - _filePosition); + else + numBytes = 0; + } + + // Now set the position to read from in the NativeOverlapped struct + // For pipes, we should leave the offset fields set to 0. + intOverlapped->OffsetLow = unchecked((int)_filePosition); + intOverlapped->OffsetHigh = (int)(_filePosition >> 32); + + // When using overlapped IO, the OS is not supposed to + // touch the file pointer location at all. We will adjust it + // ourselves. This isn't threadsafe. + + // WriteFile should not update the file pointer when writing + // in overlapped mode, according to MSDN. But it does update + // the file pointer when writing to a UNC path! + // So changed the code below to seek to an absolute + // location, not a relative one. ReadFile seems consistent though. + SeekCore(numBytes, SeekOrigin.Current); + } + + // queue an async ReadFile operation and pass in a packed overlapped + int errorCode = 0; + int r = ReadFileNative(_fileHandle, bytes, offset, numBytes, intOverlapped, out errorCode); + // ReadFile, the OS version, will return 0 on failure. But + // my ReadFileNative wrapper returns -1. My wrapper will return + // the following: + // On error, r==-1. + // On async requests that are still pending, r==-1 w/ errorCode==ERROR_IO_PENDING + // on async requests that completed sequentially, r==0 + // You will NEVER RELIABLY be able to get the number of bytes + // read back from this call when using overlapped structures! You must + // not pass in a non-null lpNumBytesRead to ReadFile when using + // overlapped structures! This is by design NT behavior. + if (r == -1 && numBytes != -1) + { + // For pipes, when they hit EOF, they will come here. + if (errorCode == ERROR_BROKEN_PIPE) + { + // Not an error, but EOF. AsyncFSCallback will NOT be + // called. Call the user callback here. + + // We clear the overlapped status bit for this special case. + // Failure to do so looks like we are freeing a pending overlapped later. + intOverlapped->InternalLow = IntPtr.Zero; + completionSource.SetCompletedSynchronously(0); + } + else if (errorCode != ERROR_IO_PENDING) + { + if (!_fileHandle.IsClosed && CanSeek) // Update Position - It could be anywhere. + { + SeekCore(0, SeekOrigin.Current); + } + + completionSource.ReleaseNativeResource(); + + if (errorCode == ERROR_HANDLE_EOF) + { + throw Error.GetEndOfFile(); + } + else + { + throw Win32Marshal.GetExceptionForWin32Error(errorCode); + } + } + else + { + // Only once the IO is pending do we register for cancellation + completionSource.RegisterForCancellation(); + } + } + else + { + // Due to a workaround for a race condition in NT's ReadFile & + // WriteFile routines, we will always be returning 0 from ReadFileNative + // when we do async IO instead of the number of bytes read, + // irregardless of whether the operation completed + // synchronously or asynchronously. We absolutely must not + // set asyncResult._numBytes here, since will never have correct + // results. + //Console.WriteLine("ReadFile returned: "+r+" (0x"+Int32.Format(r, "x")+") The IO completed synchronously, but the user callback was called on a separate thread"); + } + + return completionSource.Task; + } + + // Reads a byte from the file stream. Returns the byte cast to an int + // or -1 if reading from the end of the stream. + public override int ReadByte() + { + return ReadByteCore(); + } + + private Task WriteAsyncInternal(byte[] array, int offset, int numBytes, CancellationToken cancellationToken) + { + // If async IO is not supported on this platform or + // if this Win32FileStream was not opened with FileOptions.Asynchronous. + if (!_useAsyncIO) + { + return base.WriteAsync(array, offset, numBytes, cancellationToken); + } + + if (!CanWrite) throw Error.GetWriteNotSupported(); + + Debug.Assert((_readPos == 0 && _readLength == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLength), "We're either reading or writing, but not both."); + Debug.Assert(!_isPipe || (_readPos == 0 && _readLength == 0), "Win32FileStream must not have buffered data here! Pipes should be unidirectional."); + + bool writeDataStoredInBuffer = false; + if (!_isPipe) // avoid async buffering with pipes, as doing so can lead to deadlocks (see comments in ReadInternalAsyncCore) + { + // Ensure the buffer is clear for writing + if (_writePos == 0) + { + if (_readPos < _readLength) + { + FlushReadBuffer(); + } + _readPos = 0; + _readLength = 0; + } + + // Determine how much space remains in the buffer + int remainingBuffer = _bufferLength - _writePos; + Debug.Assert(remainingBuffer >= 0); + + // Simple/common case: + // - The write is smaller than our buffer, such that it's worth considering buffering it. + // - There's no active flush operation, such that we don't have to worry about the existing buffer being in use. + // - And the data we're trying to write fits in the buffer, meaning it wasn't already filled by previous writes. + // In that case, just store it in the buffer. + if (numBytes < _bufferLength && !HasActiveBufferOperation && numBytes <= remainingBuffer) + { + Buffer.BlockCopy(array, offset, GetBuffer(), _writePos, numBytes); + _writePos += numBytes; + writeDataStoredInBuffer = true; + + // There is one special-but-common case, common because devs often use + // byte[] sizes that are powers of 2 and thus fit nicely into our buffer, which is + // also a power of 2. If after our write the buffer still has remaining space, + // then we're done and can return a completed task now. But if we filled the buffer + // completely, we want to do the asynchronous flush/write as part of this operation + // rather than waiting until the next write that fills the buffer. + if (numBytes != remainingBuffer) + return Task.CompletedTask; + + Debug.Assert(_writePos == _bufferLength); + } + } + + // At this point, at least one of the following is true: + // 1. There was an active flush operation (it could have completed by now, though). + // 2. The data doesn't fit in the remaining buffer (or it's a pipe and we chose not to try). + // 3. We wrote all of the data to the buffer, filling it. + // + // If there's an active operation, we can't touch the current buffer because it's in use. + // That gives us a choice: we can either allocate a new buffer, or we can skip the buffer + // entirely (even if the data would otherwise fit in it). For now, for simplicity, we do + // the latter; it could also have performance wins due to OS-level optimizations, and we could + // potentially add support for PreAllocatedOverlapped due to having a single buffer. (We can + // switch to allocating a new buffer, potentially experimenting with buffer pooling, should + // performance data suggest it's appropriate.) + // + // If the data doesn't fit in the remaining buffer, it could be because it's so large + // it's greater than the entire buffer size, in which case we'd always skip the buffer, + // or it could be because there's more data than just the space remaining. For the latter + // case, we need to issue an asynchronous write to flush that data, which then turns this into + // the first case above with an active operation. + // + // If we already stored the data, then we have nothing additional to write beyond what + // we need to flush. + // + // In any of these cases, we have the same outcome: + // - If there's data in the buffer, flush it by writing it out asynchronously. + // - Then, if there's any data to be written, issue a write for it concurrently. + // We return a Task that represents one or both. + + // Flush the buffer asynchronously if there's anything to flush + Task flushTask = null; + if (_writePos > 0) + { + flushTask = FlushWriteAsync(cancellationToken); + + // If we already copied all of the data into the buffer, + // simply return the flush task here. Same goes for if the task has + // already completed and was unsuccessful. + if (writeDataStoredInBuffer || + flushTask.IsFaulted || + flushTask.IsCanceled) + { + return flushTask; + } + } + + Debug.Assert(!writeDataStoredInBuffer); + Debug.Assert(_writePos == 0); + + // Finally, issue the write asynchronously, and return a Task that logically + // represents the write operation, including any flushing done. + Task writeTask = WriteInternalCoreAsync(array, offset, numBytes, cancellationToken); + return + (flushTask == null || flushTask.Status == TaskStatus.RanToCompletion) ? writeTask : + (writeTask.Status == TaskStatus.RanToCompletion) ? flushTask : + Task.WhenAll(flushTask, writeTask); + } + + private unsafe Task WriteInternalCoreAsync(byte[] bytes, int offset, int numBytes, CancellationToken cancellationToken) + { + Debug.Assert(!_fileHandle.IsClosed, "!_handle.IsClosed"); + Debug.Assert(CanWrite, "_parent.CanWrite"); + Debug.Assert(bytes != null, "bytes != null"); + Debug.Assert(_readPos == _readLength, "_readPos == _readLen"); + Debug.Assert(_useAsyncIO, "WriteInternalCoreAsync doesn't work on synchronous file streams!"); + Debug.Assert(offset >= 0, "offset is negative"); + Debug.Assert(numBytes >= 0, "numBytes is negative"); + + // Create and store async stream class library specific data in the async result + FileStreamCompletionSource completionSource = new FileStreamCompletionSource(this, 0, bytes, cancellationToken); + NativeOverlapped* intOverlapped = completionSource.Overlapped; + + if (CanSeek) + { + // Make sure we set the length of the file appropriately. + long len = Length; + //Console.WriteLine("WriteInternalCoreAsync - Calculating end pos. pos: "+pos+" len: "+len+" numBytes: "+numBytes); + + // Make sure we are writing to the position that we think we are + VerifyOSHandlePosition(); + + if (_filePosition + numBytes > len) + { + //Console.WriteLine("WriteInternalCoreAsync - Setting length to: "+(pos + numBytes)); + SetLengthCore(_filePosition + numBytes); + } + + // Now set the position to read from in the NativeOverlapped struct + // For pipes, we should leave the offset fields set to 0. + intOverlapped->OffsetLow = (int)_filePosition; + intOverlapped->OffsetHigh = (int)(_filePosition >> 32); + + // When using overlapped IO, the OS is not supposed to + // touch the file pointer location at all. We will adjust it + // ourselves. This isn't threadsafe. + SeekCore(numBytes, SeekOrigin.Current); + } + + //Console.WriteLine("WriteInternalCoreAsync finishing. pos: "+pos+" numBytes: "+numBytes+" _pos: "+_pos+" Position: "+Position); + + int errorCode = 0; + // queue an async WriteFile operation and pass in a packed overlapped + int r = WriteFileNative(_fileHandle, bytes, offset, numBytes, intOverlapped, out errorCode); + + // WriteFile, the OS version, will return 0 on failure. But + // my WriteFileNative wrapper returns -1. My wrapper will return + // the following: + // On error, r==-1. + // On async requests that are still pending, r==-1 w/ errorCode==ERROR_IO_PENDING + // On async requests that completed sequentially, r==0 + // You will NEVER RELIABLY be able to get the number of bytes + // written back from this call when using overlapped IO! You must + // not pass in a non-null lpNumBytesWritten to WriteFile when using + // overlapped structures! This is ByDesign NT behavior. + if (r == -1 && numBytes != -1) + { + //Console.WriteLine("WriteFile returned 0; Write will complete asynchronously (if errorCode==3e5) errorCode: 0x{0:x}", errorCode); + + // For pipes, when they are closed on the other side, they will come here. + if (errorCode == ERROR_NO_DATA) + { + // Not an error, but EOF. AsyncFSCallback will NOT be called. + // Completing TCS and return cached task allowing the GC to collect TCS. + completionSource.SetCompletedSynchronously(0); + return Task.CompletedTask; + } + else if (errorCode != ERROR_IO_PENDING) + { + if (!_fileHandle.IsClosed && CanSeek) // Update Position - It could be anywhere. + { + SeekCore(0, SeekOrigin.Current); + } + + completionSource.ReleaseNativeResource(); + + if (errorCode == ERROR_HANDLE_EOF) + { + throw Error.GetEndOfFile(); + } + else + { + throw Win32Marshal.GetExceptionForWin32Error(errorCode); + } + } + else // ERROR_IO_PENDING + { + // Only once the IO is pending do we register for cancellation + completionSource.RegisterForCancellation(); + } + } + else + { + // Due to a workaround for a race condition in NT's ReadFile & + // WriteFile routines, we will always be returning 0 from WriteFileNative + // when we do async IO instead of the number of bytes written, + // irregardless of whether the operation completed + // synchronously or asynchronously. We absolutely must not + // set asyncResult._numBytes here, since will never have correct + // results. + //Console.WriteLine("WriteFile returned: "+r+" (0x"+Int32.Format(r, "x")+") The IO completed synchronously, but the user callback was called on another thread."); + } + + return completionSource.Task; + } + + public override void WriteByte(byte value) + { + WriteByteCore(value); + } + + // Windows API definitions, from winbase.h and others + + private const int FILE_ATTRIBUTE_NORMAL = 0x00000080; + private const int FILE_ATTRIBUTE_ENCRYPTED = 0x00004000; + private const int FILE_FLAG_OVERLAPPED = 0x40000000; + internal const int GENERIC_READ = unchecked((int)0x80000000); + private const int GENERIC_WRITE = 0x40000000; + + private const int FILE_BEGIN = 0; + private const int FILE_CURRENT = 1; + private const int FILE_END = 2; + + // Error codes (not HRESULTS), from winerror.h + internal const int ERROR_BROKEN_PIPE = 109; + internal const int ERROR_NO_DATA = 232; + private const int ERROR_HANDLE_EOF = 38; + private const int ERROR_INVALID_PARAMETER = 87; + private const int ERROR_IO_PENDING = 997; + + // __ConsoleStream also uses this code. + private unsafe int ReadFileNative(SafeFileHandle handle, byte[] bytes, int offset, int count, NativeOverlapped* overlapped, out int errorCode) + { + Debug.Assert(handle != null, "handle != null"); + Debug.Assert(offset >= 0, "offset >= 0"); + Debug.Assert(count >= 0, "count >= 0"); + Debug.Assert(bytes != null, "bytes != null"); + // Don't corrupt memory when multiple threads are erroneously writing + // to this stream simultaneously. + if (bytes.Length - offset < count) + throw new IndexOutOfRangeException(SR.IndexOutOfRange_IORaceCondition); + + Debug.Assert((_useAsyncIO && overlapped != null) || (!_useAsyncIO && overlapped == null), "Async IO and overlapped parameters inconsistent in call to ReadFileNative."); + + // You can't use the fixed statement on an array of length 0. + if (bytes.Length == 0) + { + errorCode = 0; + return 0; + } + + int r = 0; + int numBytesRead = 0; + + fixed (byte* p = bytes) + { + if (_useAsyncIO) + r = Interop.mincore.ReadFile(handle, p + offset, count, IntPtr.Zero, overlapped); + else + r = Interop.mincore.ReadFile(handle, p + offset, count, out numBytesRead, IntPtr.Zero); + } + + if (r == 0) + { + errorCode = GetLastWin32ErrorAndDisposeHandleIfInvalid(); + return -1; + } + else + { + errorCode = 0; + return numBytesRead; + } + } + + private unsafe int WriteFileNative(SafeFileHandle handle, byte[] bytes, int offset, int count, NativeOverlapped* overlapped, out int errorCode) + { + Debug.Assert(handle != null, "handle != null"); + Debug.Assert(offset >= 0, "offset >= 0"); + Debug.Assert(count >= 0, "count >= 0"); + Debug.Assert(bytes != null, "bytes != null"); + // Don't corrupt memory when multiple threads are erroneously writing + // to this stream simultaneously. (the OS is reading from + // the array we pass to WriteFile, but if we read beyond the end and + // that memory isn't allocated, we could get an AV.) + if (bytes.Length - offset < count) + throw new IndexOutOfRangeException(SR.IndexOutOfRange_IORaceCondition); + + Debug.Assert((_useAsyncIO && overlapped != null) || (!_useAsyncIO && overlapped == null), "Async IO and overlapped parameters inconsistent in call to WriteFileNative."); + + // You can't use the fixed statement on an array of length 0. + if (bytes.Length == 0) + { + errorCode = 0; + return 0; + } + + int numBytesWritten = 0; + int r = 0; + + fixed (byte* p = bytes) + { + if (_useAsyncIO) + r = Interop.mincore.WriteFile(handle, p + offset, count, IntPtr.Zero, overlapped); + else + r = Interop.mincore.WriteFile(handle, p + offset, count, out numBytesWritten, IntPtr.Zero); + } + + if (r == 0) + { + errorCode = GetLastWin32ErrorAndDisposeHandleIfInvalid(); + return -1; + } + else + { + errorCode = 0; + return numBytesWritten; + } + } + + private int GetLastWin32ErrorAndDisposeHandleIfInvalid(bool throwIfInvalidHandle = false) + { + int errorCode = Marshal.GetLastWin32Error(); + + // If ERROR_INVALID_HANDLE is returned, it doesn't suffice to set + // the handle as invalid; the handle must also be closed. + // + // Marking the handle as invalid but not closing the handle + // resulted in exceptions during finalization and locked column + // values (due to invalid but unclosed handle) in SQL Win32FileStream + // scenarios. + // + // A more mainstream scenario involves accessing a file on a + // network share. ERROR_INVALID_HANDLE may occur because the network + // connection was dropped and the server closed the handle. However, + // the client side handle is still open and even valid for certain + // operations. + // + // Note that _parent.Dispose doesn't throw so we don't need to special case. + // SetHandleAsInvalid only sets _closed field to true (without + // actually closing handle) so we don't need to call that as well. + if (errorCode == Interop.mincore.Errors.ERROR_INVALID_HANDLE) + { + _fileHandle.Dispose(); + + if (throwIfInvalidHandle) + throw Win32Marshal.GetExceptionForWin32Error(errorCode); + } + + return errorCode; + } + + public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) + { + // If we're in sync mode, just use the shared CopyToAsync implementation that does + // typical read/write looping. We also need to take this path if this is a derived + // instance from FileStream, as a derived type could have overridden ReadAsync, in which + // case our custom CopyToAsync implementation isn't necessarily correct. + if (!_useAsyncIO || GetType() != typeof(FileStream)) + { + return base.CopyToAsync(destination, bufferSize, cancellationToken); + } + + StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize); + + // Bail early for cancellation if cancellation has been requested + if (cancellationToken.IsCancellationRequested) + { + return Task.FromCanceled(cancellationToken); + } + + // Fail if the file was closed + if (_fileHandle.IsClosed) + { + throw Error.GetFileNotOpen(); + } + + // Do the async copy, with differing implementations based on whether the FileStream was opened as async or sync + Debug.Assert((_readPos == 0 && _readLength == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLength), "We're either reading or writing, but not both."); + return AsyncModeCopyToAsync(destination, bufferSize, cancellationToken); + } + + private async Task AsyncModeCopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) + { + Debug.Assert(_useAsyncIO, "This implementation is for async mode only"); + Debug.Assert(!_fileHandle.IsClosed, "!_handle.IsClosed"); + Debug.Assert(CanRead, "_parent.CanRead"); + + // Make sure any pending writes have been flushed before we do a read. + if (_writePos > 0) + { + await FlushWriteAsync(cancellationToken).ConfigureAwait(false); + } + + // Typically CopyToAsync would be invoked as the only "read" on the stream, but it's possible some reading is + // done and then the CopyToAsync is issued. For that case, see if we have any data available in the buffer. + if (GetBuffer() != null) + { + int bufferedBytes = _readLength - _readPos; + if (bufferedBytes > 0) + { + await destination.WriteAsync(GetBuffer(), _readPos, bufferedBytes, cancellationToken).ConfigureAwait(false); + _readPos = _readLength = 0; + } + } + + // For efficiency, we avoid creating a new task and associated state for each asynchronous read. + // Instead, we create a single reusable awaitable object that will be triggered when an await completes + // and reset before going again. + var readAwaitable = new AsyncCopyToAwaitable(this); + + // Make sure we are reading from the position that we think we are. + // Only set the position in the awaitable if we can seek (e.g. not for pipes). + bool canSeek = CanSeek; + if (canSeek) + { + VerifyOSHandlePosition(); + readAwaitable._position = _filePosition; + } + + // Get the buffer to use for the copy operation, as the base CopyToAsync does. We don't try to use + // _buffer here, even if it's not null, as concurrent operations are allowed, and another operation may + // actually be using the buffer already. Plus, it'll be rare for _buffer to be non-null, as typically + // CopyToAsync is used as the only operation performed on the stream, and the buffer is lazily initialized. + // Further, typically the CopyToAsync buffer size will be larger than that used by the FileStream, such that + // we'd likely be unable to use it anyway. Instead, we rent the buffer from a pool. + byte[] copyBuffer = ArrayPool.Shared.Rent(bufferSize); + bufferSize = 0; // repurpose bufferSize to be the high water mark for the buffer, to avoid an extra field in the state machine + + // Allocate an Overlapped we can use repeatedly for all operations + var awaitableOverlapped = new PreAllocatedOverlapped(AsyncCopyToAwaitable.s_callback, readAwaitable, copyBuffer); + var cancellationReg = default(CancellationTokenRegistration); + try + { + // Register for cancellation. We do this once for the whole copy operation, and just try to cancel + // whatever read operation may currently be in progress, if there is one. It's possible the cancellation + // request could come in between operations, in which case we flag that with explicit calls to ThrowIfCancellationRequested + // in the read/write copy loop. + if (cancellationToken.CanBeCanceled) + { + cancellationReg = cancellationToken.Register(s => + { + var innerAwaitable = (AsyncCopyToAwaitable)s; + unsafe + { + lock (innerAwaitable.CancellationLock) // synchronize with cleanup of the overlapped + { + if (innerAwaitable._nativeOverlapped != null) + { + // Try to cancel the I/O. We ignore the return value, as cancellation is opportunistic and we + // don't want to fail the operation because we couldn't cancel it. + Interop.mincore.CancelIoEx(innerAwaitable._fileStream._fileHandle, innerAwaitable._nativeOverlapped); + } + } + } + }, readAwaitable); + } + + // Repeatedly read from this FileStream and write the results to the destination stream. + while (true) + { + cancellationToken.ThrowIfCancellationRequested(); + readAwaitable.ResetForNextOperation(); + + try + { + bool synchronousSuccess; + int errorCode; + unsafe + { + // Allocate a native overlapped for our reusable overlapped, and set position to read based on the next + // desired address stored in the awaitable. (This position may be 0, if either we're at the beginning or + // if the stream isn't seekable.) + readAwaitable._nativeOverlapped = _fileHandle.ThreadPoolBinding.AllocateNativeOverlapped(awaitableOverlapped); + if (canSeek) + { + readAwaitable._nativeOverlapped->OffsetLow = unchecked((int)readAwaitable._position); + readAwaitable._nativeOverlapped->OffsetHigh = (int)(readAwaitable._position >> 32); + } + + // Kick off the read. + synchronousSuccess = ReadFileNative(_fileHandle, copyBuffer, 0, copyBuffer.Length, readAwaitable._nativeOverlapped, out errorCode) >= 0; + } + + // If the operation did not synchronously succeed, it either failed or initiated the asynchronous operation. + if (!synchronousSuccess) + { + switch (errorCode) + { + case ERROR_IO_PENDING: + // Async operation in progress. + break; + case ERROR_BROKEN_PIPE: + case ERROR_HANDLE_EOF: + // We're at or past the end of the file, and the overlapped callback + // won't be raised in these cases. Mark it as completed so that the await + // below will see it as such. + readAwaitable.MarkCompleted(); + break; + default: + // Everything else is an error (and there won't be a callback). + throw Win32Marshal.GetExceptionForWin32Error(errorCode); + } + } + + // Wait for the async operation (which may or may not have already completed), then throw if it failed. + await readAwaitable; + switch (readAwaitable._errorCode) + { + case 0: // success + Debug.Assert(readAwaitable._numBytes >= 0, $"Expected non-negative numBytes, got {readAwaitable._numBytes}"); + break; + case ERROR_BROKEN_PIPE: // logically success with 0 bytes read (write end of pipe closed) + case ERROR_HANDLE_EOF: // logically success with 0 bytes read (read at end of file) + Debug.Assert(readAwaitable._numBytes == 0, $"Expected 0 bytes read, got {readAwaitable._numBytes}"); + break; + case Interop.mincore.Errors.ERROR_OPERATION_ABORTED: // canceled + throw new OperationCanceledException(cancellationToken.IsCancellationRequested ? cancellationToken : new CancellationToken(true)); + default: // error + throw Win32Marshal.GetExceptionForWin32Error((int)readAwaitable._errorCode); + } + + // Successful operation. If we got zero bytes, we're done: exit the read/write loop. + int numBytesRead = (int)readAwaitable._numBytes; + if (numBytesRead == 0) + { + break; + } + + // Otherwise, update the read position for next time accordingly. + if (canSeek) + { + readAwaitable._position += numBytesRead; + } + + // (and keep track of the maximum number of bytes in the buffer we used, to avoid excessive and unnecessary + // clearing of the buffer before we return it to the pool) + if (numBytesRead > bufferSize) + { + bufferSize = numBytesRead; + } + } + finally + { + // Free the resources for this read operation + unsafe + { + NativeOverlapped* overlapped; + lock (readAwaitable.CancellationLock) // just an Exchange, but we need this to be synchronized with cancellation, so using the same lock + { + overlapped = readAwaitable._nativeOverlapped; + readAwaitable._nativeOverlapped = null; + } + if (overlapped != null) + { + _fileHandle.ThreadPoolBinding.FreeNativeOverlapped(overlapped); + } + } + } + + // Write out the read data. + await destination.WriteAsync(copyBuffer, 0, (int)readAwaitable._numBytes, cancellationToken).ConfigureAwait(false); + } + } + finally + { + // Cleanup from the whole copy operation + cancellationReg.Dispose(); + awaitableOverlapped.Dispose(); + + Array.Clear(copyBuffer, 0, bufferSize); + ArrayPool.Shared.Return(copyBuffer, clearArray: false); + + // Make sure the stream's current position reflects where we ended up + if (!_fileHandle.IsClosed && CanSeek) + { + SeekCore(0, SeekOrigin.End); + } + } + } + + /// Used by CopyToAsync to enable awaiting the result of an overlapped I/O operation with minimal overhead. + private sealed unsafe class AsyncCopyToAwaitable : ICriticalNotifyCompletion + { + /// Sentinel object used to indicate that the I/O operation has completed before being awaited. + private readonly static Action s_sentinel = () => { }; + /// Cached delegate to IOCallback. + internal static readonly IOCompletionCallback s_callback = IOCallback; + + /// The FileStream that owns this instance. + internal readonly FileStream _fileStream; + + /// Tracked position representing the next location from which to read. + internal long _position; + /// The current native overlapped pointer. This changes for each operation. + internal NativeOverlapped* _nativeOverlapped; + /// + /// null if the operation is still in progress, + /// s_sentinel if the I/O operation completed before the await, + /// s_callback if it completed after the await yielded. + /// + internal Action _continuation; + /// Last error code from completed operation. + internal uint _errorCode; + /// Last number of read bytes from completed operation. + internal uint _numBytes; + + /// Lock object used to protect cancellation-related access to _nativeOverlapped. + internal object CancellationLock => this; + + /// Initialize the awaitable. + internal unsafe AsyncCopyToAwaitable(FileStream fileStream) + { + _fileStream = fileStream; + } + + /// Reset state to prepare for the next read operation. + internal void ResetForNextOperation() + { + Debug.Assert(_position >= 0, $"Expected non-negative position, got {_position}"); + _continuation = null; + _errorCode = 0; + _numBytes = 0; + } + + /// Overlapped callback: store the results, then invoke the continuation delegate. + internal unsafe static void IOCallback(uint errorCode, uint numBytes, NativeOverlapped* pOVERLAP) + { + var awaitable = (AsyncCopyToAwaitable)ThreadPoolBoundHandle.GetNativeOverlappedState(pOVERLAP); + + Debug.Assert(awaitable._continuation != s_sentinel, "Sentinel must not have already been set as the continuation"); + awaitable._errorCode = errorCode; + awaitable._numBytes = numBytes; + + (awaitable._continuation ?? Interlocked.CompareExchange(ref awaitable._continuation, s_sentinel, null))?.Invoke(); + } + + /// + /// Called when it's known that the I/O callback for an operation will not be invoked but we'll + /// still be awaiting the awaitable. + /// + internal void MarkCompleted() + { + Debug.Assert(_continuation == null, "Expected null continuation"); + _continuation = s_sentinel; + } + + public AsyncCopyToAwaitable GetAwaiter() => this; + public bool IsCompleted => _continuation == s_sentinel; + public void GetResult() { } + public void OnCompleted(Action continuation) => UnsafeOnCompleted(continuation); + public void UnsafeOnCompleted(Action continuation) + { + if (_continuation == s_sentinel || + Interlocked.CompareExchange(ref _continuation, continuation, null) != null) + { + Debug.Assert(_continuation == s_sentinel, $"Expected continuation set to s_sentinel, got ${_continuation}"); + Task.Run(continuation); + } + } + } + + // Unlike Flush(), FlushAsync() always flushes to disk. This is intentional. + // Legend is that we chose not to flush the OS file buffers in Flush() in fear of + // perf problems with frequent, long running FlushFileBuffers() calls. But we don't + // have that problem with FlushAsync() because we will call FlushFileBuffers() in the background. + private Task FlushAsyncInternal(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + return Task.FromCanceled(cancellationToken); + + if (_fileHandle.IsClosed) + throw Error.GetFileNotOpen(); + + // The always synchronous data transfer between the OS and the internal buffer is intentional + // because this is needed to allow concurrent async IO requests. Concurrent data transfer + // between the OS and the internal buffer will result in race conditions. Since FlushWrite and + // FlushRead modify internal state of the stream and transfer data between the OS and the + // internal buffer, they cannot be truly async. We will, however, flush the OS file buffers + // asynchronously because it doesn't modify any internal state of the stream and is potentially + // a long running process. + try + { + FlushInternalBuffer(); + } + catch (Exception e) + { + return Task.FromException(e); + } + + if (CanWrite) + { + return Task.Factory.StartNew( + state => ((FileStream)state).FlushOSBuffer(), + this, + cancellationToken, + TaskCreationOptions.DenyChildAttach, + TaskScheduler.Default); + } + else + { + return Task.CompletedTask; + } + } + + private Task TaskFromResultOrCache(int result) + { + Task completedTask = _lastSynchronouslyCompletedTask; + Debug.Assert(completedTask == null || completedTask.Status == TaskStatus.RanToCompletion, "Cached task should have completed successfully"); + + if ((completedTask == null) || (completedTask.Result != result)) + { + completedTask = Task.FromResult(result); + _lastSynchronouslyCompletedTask = completedTask; + } + + return completedTask; + } + + private void LockInternal(long position, long length) + { + int positionLow = unchecked((int)(position)); + int positionHigh = unchecked((int)(position >> 32)); + int lengthLow = unchecked((int)(length)); + int lengthHigh = unchecked((int)(length >> 32)); + + if (!Interop.mincore.LockFile(_fileHandle, positionLow, positionHigh, lengthLow, lengthHigh)) + { + throw Win32Marshal.GetExceptionForLastWin32Error(); + } + } + + private void UnlockInternal(long position, long length) + { + int positionLow = unchecked((int)(position)); + int positionHigh = unchecked((int)(position >> 32)); + int lengthLow = unchecked((int)(length)); + int lengthHigh = unchecked((int)(length >> 32)); + + if (!Interop.mincore.UnlockFile(_fileHandle, positionLow, positionHigh, lengthLow, lengthHigh)) + { + throw Win32Marshal.GetExceptionForLastWin32Error(); + } + } + } +} diff --git a/src/mscorlib/corefx/System/IO/FileStream.cs b/src/mscorlib/corefx/System/IO/FileStream.cs new file mode 100644 index 0000000..398f5a6 --- /dev/null +++ b/src/mscorlib/corefx/System/IO/FileStream.cs @@ -0,0 +1,654 @@ +// 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.Threading; +using System.Threading.Tasks; +using Microsoft.Win32.SafeHandles; +using System.Diagnostics; + +namespace System.IO +{ + public partial class FileStream : Stream + { + private const FileShare DefaultShare = FileShare.Read; + private const bool DefaultIsAsync = false; + internal const int DefaultBufferSize = 4096; + + private byte[] _buffer; + private int _bufferLength; + private readonly SafeFileHandle _fileHandle; + + /// Whether the file is opened for reading, writing, or both. + private readonly FileAccess _access; + + /// The path to the opened file. + private readonly string _path; + + /// The next available byte to be read from the _buffer. + private int _readPos; + + /// The number of valid bytes in _buffer. + private int _readLength; + + /// The next location in which a write should occur to the buffer. + private int _writePos; + + /// + /// Whether asynchronous read/write/flush operations should be performed using async I/O. + /// On Windows FileOptions.Asynchronous controls how the file handle is configured, + /// and then as a result how operations are issued against that file handle. On Unix, + /// there isn't any distinction around how file descriptors are created for async vs + /// sync, but we still differentiate how the operations are issued in order to provide + /// similar behavioral semantics and performance characteristics as on Windows. On + /// Windows, if non-async, async read/write requests just delegate to the base stream, + /// and no attempt is made to synchronize between sync and async operations on the stream; + /// if async, then async read/write requests are implemented specially, and sync read/write + /// requests are coordinated with async ones by implementing the sync ones over the async + /// ones. On Unix, we do something similar. If non-async, async read/write requests just + /// delegate to the base stream, and no attempt is made to synchronize. If async, we use + /// a semaphore to coordinate both sync and async operations. + /// + private readonly bool _useAsyncIO; + + /// + /// Currently cached position in the stream. This should always mirror the underlying file's actual position, + /// and should only ever be out of sync if another stream with access to this same file manipulates it, at which + /// point we attempt to error out. + /// + private long _filePosition; + + /// Whether the file stream's handle has been exposed. + private bool _exposedHandle; + + [Obsolete("This constructor has been deprecated. Please use new FileStream(SafeFileHandle handle, FileAccess access) instead. http://go.microsoft.com/fwlink/?linkid=14202")] + public FileStream(IntPtr handle, FileAccess access) + : this(handle, access, true, DefaultBufferSize, false) + { + } + + [Obsolete("This constructor has been deprecated. Please use new FileStream(SafeFileHandle handle, FileAccess access) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")] + public FileStream(IntPtr handle, FileAccess access, bool ownsHandle) + : this(handle, access, ownsHandle, DefaultBufferSize, false) + { + } + + [Obsolete("This constructor has been deprecated. Please use new FileStream(SafeFileHandle handle, FileAccess access, int bufferSize) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")] + public FileStream(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize) + : this(handle, access, ownsHandle, bufferSize, false) + { + } + + [Obsolete("This constructor has been deprecated. Please use new FileStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")] + public FileStream(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize, bool isAsync) + : this(new SafeFileHandle(handle, ownsHandle), access, bufferSize, isAsync) + { + } + + public FileStream(SafeFileHandle handle, FileAccess access) + : this(handle, access, DefaultBufferSize) + { + } + + public FileStream(SafeFileHandle handle, FileAccess access, int bufferSize) + : this(handle, access, bufferSize, GetDefaultIsAsync(handle)) + { + } + + public FileStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) + { + if (handle.IsInvalid) + throw new ArgumentException(SR.Arg_InvalidHandle, nameof(handle)); + + if (access < FileAccess.Read || access > FileAccess.ReadWrite) + throw new ArgumentOutOfRangeException(nameof(access), SR.ArgumentOutOfRange_Enum); + if (bufferSize <= 0) + throw new ArgumentOutOfRangeException(nameof(bufferSize), SR.ArgumentOutOfRange_NeedPosNum); + + if (handle.IsClosed) + throw new ObjectDisposedException(SR.ObjectDisposed_FileClosed); + if (handle.IsAsync.HasValue && isAsync != handle.IsAsync.Value) + throw new ArgumentException(SR.Arg_HandleNotAsync, nameof(handle)); + + _access = access; + _useAsyncIO = isAsync; + _exposedHandle = true; + _bufferLength = bufferSize; + _fileHandle = handle; + + InitFromHandle(handle); + } + + public FileStream(string path, FileMode mode) : + this(path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), DefaultShare, DefaultBufferSize, DefaultIsAsync) + { } + + public FileStream(string path, FileMode mode, FileAccess access) : + this(path, mode, access, DefaultShare, DefaultBufferSize, DefaultIsAsync) + { } + + public FileStream(string path, FileMode mode, FileAccess access, FileShare share) : + this(path, mode, access, share, DefaultBufferSize, DefaultIsAsync) + { } + + public FileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize) : + this(path, mode, access, share, bufferSize, DefaultIsAsync) + { } + + public FileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync) : + this(path, mode, access, share, bufferSize, useAsync ? FileOptions.Asynchronous : FileOptions.None) + { } + + internal FileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, string msgPath, bool bFromProxy) + : this(path, mode, access, share, bufferSize, options, msgPath, bFromProxy, useLongPath: false) + { + } + + internal FileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, string msgPath, bool bFromProxy, bool useLongPath) + : this(path, mode, access, share, bufferSize, options) + { + // msgPath is the path that is handed back to untrusted code, CoreCLR is always full trust + // bFromProxy is also related to asserting rights for limited trust and also can be ignored + // useLongPath was used to get around the legacy MaxPath check, this is no longer applicable as everything supports long paths + // checkHost is also related to limited trust scenarios + } + + public FileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options) + { + if (path == null) + throw new ArgumentNullException(nameof(path), SR.ArgumentNull_Path); + if (path.Length == 0) + throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); + + // don't include inheritable in our bounds check for share + FileShare tempshare = share & ~FileShare.Inheritable; + string badArg = null; + + if (mode < FileMode.CreateNew || mode > FileMode.Append) + badArg = nameof(mode); + else if (access < FileAccess.Read || access > FileAccess.ReadWrite) + badArg = nameof(access); + else if (tempshare < FileShare.None || tempshare > (FileShare.ReadWrite | FileShare.Delete)) + badArg = nameof(share); + + if (badArg != null) + throw new ArgumentOutOfRangeException(badArg, SR.ArgumentOutOfRange_Enum); + + // NOTE: any change to FileOptions enum needs to be matched here in the error validation + if (options != FileOptions.None && (options & ~(FileOptions.WriteThrough | FileOptions.Asynchronous | FileOptions.RandomAccess | FileOptions.DeleteOnClose | FileOptions.SequentialScan | FileOptions.Encrypted | (FileOptions)0x20000000 /* NoBuffering */)) != 0) + throw new ArgumentOutOfRangeException(nameof(options), SR.ArgumentOutOfRange_Enum); + + if (bufferSize <= 0) + throw new ArgumentOutOfRangeException(nameof(bufferSize), SR.ArgumentOutOfRange_NeedPosNum); + + // Write access validation + if ((access & FileAccess.Write) == 0) + { + if (mode == FileMode.Truncate || mode == FileMode.CreateNew || mode == FileMode.Create || mode == FileMode.Append) + { + // No write access, mode and access disagree but flag access since mode comes first + throw new ArgumentException(SR.Format(SR.Argument_InvalidFileModeAndAccessCombo, mode, access), nameof(access)); + } + } + + if ((access & FileAccess.Read) != 0 && mode == FileMode.Append) + throw new ArgumentException(SR.Argument_InvalidAppendMode, nameof(access)); + + string fullPath = Path.GetFullPath(path); + + _path = fullPath; + _access = access; + _bufferLength = bufferSize; + + if ((options & FileOptions.Asynchronous) != 0) + _useAsyncIO = true; + + _fileHandle = OpenHandle(mode, share, options); + + try + { + Init(mode, share); + } + catch + { + // If anything goes wrong while setting up the stream, make sure we deterministically dispose + // of the opened handle. + _fileHandle.Dispose(); + _fileHandle = null; + throw; + } + } + + private static bool GetDefaultIsAsync(SafeFileHandle handle) + { + // This will eventually get more complicated as we can actually check the underlying handle type on Windows + return handle.IsAsync.HasValue ? handle.IsAsync.Value : false; + } + + // InternalOpen, InternalCreate, and InternalAppend: + // Factory methods for FileStream used by File, FileInfo, and ReadLinesIterator + // Specifies default access and sharing options for FileStreams created by those classes + internal static FileStream InternalOpen(string path, int bufferSize = DefaultBufferSize, bool useAsync = DefaultIsAsync) + { + return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, useAsync); + } + + internal static FileStream InternalCreate(string path, int bufferSize = DefaultBufferSize, bool useAsync = DefaultIsAsync) + { + return new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, bufferSize, useAsync); + } + + internal static FileStream InternalAppend(string path, int bufferSize = DefaultBufferSize, bool useAsync = DefaultIsAsync) + { + return new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.Read, bufferSize, useAsync); + } + + [Obsolete("This property has been deprecated. Please use FileStream's SafeFileHandle property instead. http://go.microsoft.com/fwlink/?linkid=14202")] + public virtual IntPtr Handle { get { return SafeFileHandle.DangerousGetHandle(); } } + + public virtual void Lock(long position, long length) + { + if (position < 0 || length < 0) + { + throw new ArgumentOutOfRangeException(position < 0 ? nameof(position) : nameof(length), SR.ArgumentOutOfRange_NeedNonNegNum); + } + + if (_fileHandle.IsClosed) + { + throw Error.GetFileNotOpen(); + } + + LockInternal(position, length); + } + + public virtual void Unlock(long position, long length) + { + if (position < 0 || length < 0) + { + throw new ArgumentOutOfRangeException(position < 0 ? nameof(position) : nameof(length), SR.ArgumentOutOfRange_NeedNonNegNum); + } + + if (_fileHandle.IsClosed) + { + throw Error.GetFileNotOpen(); + } + + UnlockInternal(position, length); + } + + public override Task FlushAsync(CancellationToken cancellationToken) + { + // If we have been inherited into a subclass, the following implementation could be incorrect + // since it does not call through to Flush() which a subclass might have overridden. To be safe + // we will only use this implementation in cases where we know it is safe to do so, + // and delegate to our base class (which will call into Flush) when we are not sure. + if (GetType() != typeof(FileStream)) + return base.FlushAsync(cancellationToken); + + return FlushAsyncInternal(cancellationToken); + } + + public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + if (buffer == null) + throw new ArgumentNullException(nameof(buffer), SR.ArgumentNull_Buffer); + if (offset < 0) + throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum); + if (count < 0) + throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum); + if (buffer.Length - offset < count) + throw new ArgumentException(SR.Argument_InvalidOffLen /*, no good single parameter name to pass*/); + + // If we have been inherited into a subclass, the following implementation could be incorrect + // since it does not call through to Read() or ReadAsync() which a subclass might have overridden. + // To be safe we will only use this implementation in cases where we know it is safe to do so, + // and delegate to our base class (which will call into Read/ReadAsync) when we are not sure. + if (GetType() != typeof(FileStream)) + return base.ReadAsync(buffer, offset, count, cancellationToken); + + if (cancellationToken.IsCancellationRequested) + return Task.FromCanceled(cancellationToken); + + if (IsClosed) + throw Error.GetFileNotOpen(); + + return ReadAsyncInternal(buffer, offset, count, cancellationToken); + } + + public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + if (buffer == null) + throw new ArgumentNullException(nameof(buffer), SR.ArgumentNull_Buffer); + if (offset < 0) + throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum); + if (count < 0) + throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum); + if (buffer.Length - offset < count) + throw new ArgumentException(SR.Argument_InvalidOffLen /*, no good single parameter name to pass*/); + + // If we have been inherited into a subclass, the following implementation could be incorrect + // since it does not call through to Write() or WriteAsync() which a subclass might have overridden. + // To be safe we will only use this implementation in cases where we know it is safe to do so, + // and delegate to our base class (which will call into Write/WriteAsync) when we are not sure. + if (GetType() != typeof(FileStream)) + return base.WriteAsync(buffer, offset, count, cancellationToken); + + if (cancellationToken.IsCancellationRequested) + return Task.FromCanceled(cancellationToken); + + if (IsClosed) + throw Error.GetFileNotOpen(); + + return WriteAsyncInternal(buffer, offset, count, cancellationToken); + } + + /// + /// Clears buffers for this stream and causes any buffered data to be written to the file. + /// + public override void Flush() + { + // Make sure that we call through the public virtual API + Flush(flushToDisk: false); + } + + /// + /// Clears buffers for this stream, and if is true, + /// causes any buffered data to be written to the file. + /// + public virtual void Flush(bool flushToDisk) + { + if (IsClosed) throw Error.GetFileNotOpen(); + + FlushInternalBuffer(); + + if (flushToDisk && CanWrite) + { + FlushOSBuffer(); + } + } + + /// Gets a value indicating whether the current stream supports reading. + public override bool CanRead + { + get { return !_fileHandle.IsClosed && (_access & FileAccess.Read) != 0; } + } + + /// Gets a value indicating whether the current stream supports writing. + public override bool CanWrite + { + get { return !_fileHandle.IsClosed && (_access & FileAccess.Write) != 0; } + } + + /// Validates arguments to Read and Write and throws resulting exceptions. + /// The buffer to read from or write to. + /// The zero-based offset into the array. + /// The maximum number of bytes to read or write. + private void ValidateReadWriteArgs(byte[] array, int offset, int count) + { + if (array == null) + throw new ArgumentNullException(nameof(array), SR.ArgumentNull_Buffer); + if (offset < 0) + throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum); + if (count < 0) + throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum); + if (array.Length - offset < count) + throw new ArgumentException(SR.Argument_InvalidOffLen /*, no good single parameter name to pass*/); + if (_fileHandle.IsClosed) + throw Error.GetFileNotOpen(); + } + + /// Sets the length of this stream to the given value. + /// The new length of the stream. + public override void SetLength(long value) + { + if (value < 0) + throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_NeedNonNegNum); + if (_fileHandle.IsClosed) + throw Error.GetFileNotOpen(); + if (!CanSeek) + throw Error.GetSeekNotSupported(); + if (!CanWrite) + throw Error.GetWriteNotSupported(); + + SetLengthInternal(value); + } + + public virtual SafeFileHandle SafeFileHandle + { + get + { + Flush(); + _exposedHandle = true; + return _fileHandle; + } + } + + /// Gets the path that was passed to the constructor. + public virtual string Name { get { return _path ?? SR.IO_UnknownFileName; } } + + /// Gets a value indicating whether the stream was opened for I/O to be performed synchronously or asynchronously. + public virtual bool IsAsync + { + get { return _useAsyncIO; } + } + + /// Gets the length of the stream in bytes. + public override long Length + { + get + { + if (_fileHandle.IsClosed) throw Error.GetFileNotOpen(); + if (!CanSeek) throw Error.GetSeekNotSupported(); + return GetLengthInternal(); + } + } + + /// + /// Verify that the actual position of the OS's handle equals what we expect it to. + /// This will fail if someone else moved the UnixFileStream's handle or if + /// our position updating code is incorrect. + /// + private void VerifyOSHandlePosition() + { + bool verifyPosition = _exposedHandle; // in release, only verify if we've given out the handle such that someone else could be manipulating it +#if DEBUG + verifyPosition = true; // in debug, always make sure our position matches what the OS says it should be +#endif + if (verifyPosition && CanSeek) + { + long oldPos = _filePosition; // SeekCore will override the current _position, so save it now + long curPos = SeekCore(0, SeekOrigin.Current); + if (oldPos != curPos) + { + // For reads, this is non-fatal but we still could have returned corrupted + // data in some cases, so discard the internal buffer. For writes, + // this is a problem; discard the buffer and error out. + _readPos = _readLength = 0; + if (_writePos > 0) + { + _writePos = 0; + throw new IOException(SR.IO_FileStreamHandlePosition); + } + } + } + } + + /// Verifies that state relating to the read/write buffer is consistent. + [Conditional("DEBUG")] + private void AssertBufferInvariants() + { + // Read buffer values must be in range: 0 <= _bufferReadPos <= _bufferReadLength <= _bufferLength + Debug.Assert(0 <= _readPos && _readPos <= _readLength && _readLength <= _bufferLength); + + // Write buffer values must be in range: 0 <= _bufferWritePos <= _bufferLength + Debug.Assert(0 <= _writePos && _writePos <= _bufferLength); + + // Read buffering and write buffering can't both be active + Debug.Assert((_readPos == 0 && _readLength == 0) || _writePos == 0); + } + + /// Validates that we're ready to read from the stream. + private void PrepareForReading() + { + if (_fileHandle.IsClosed) + throw Error.GetFileNotOpen(); + if (_readLength == 0 && !CanRead) + throw Error.GetReadNotSupported(); + + AssertBufferInvariants(); + } + + /// Gets or sets the position within the current stream + public override long Position + { + get + { + if (_fileHandle.IsClosed) + throw Error.GetFileNotOpen(); + + if (!CanSeek) + throw Error.GetSeekNotSupported(); + + AssertBufferInvariants(); + VerifyOSHandlePosition(); + + // We may have read data into our buffer from the handle, such that the handle position + // is artificially further along than the consumer's view of the stream's position. + // Thus, when reading, our position is really starting from the handle position negatively + // offset by the number of bytes in the buffer and positively offset by the number of + // bytes into that buffer we've read. When writing, both the read length and position + // must be zero, and our position is just the handle position offset positive by how many + // bytes we've written into the buffer. + return (_filePosition - _readLength) + _readPos + _writePos; + } + set + { + if (value < 0) + throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_NeedNonNegNum); + + Seek(value, SeekOrigin.Begin); + } + } + + internal virtual bool IsClosed => _fileHandle.IsClosed; + + /// + /// Gets the array used for buffering reading and writing. + /// If the array hasn't been allocated, this will lazily allocate it. + /// + /// The buffer. + private byte[] GetBuffer() + { + Debug.Assert(_buffer == null || _buffer.Length == _bufferLength); + if (_buffer == null) + { + _buffer = new byte[_bufferLength]; + OnBufferAllocated(); + } + + return _buffer; + } + + partial void OnBufferAllocated(); + + /// + /// Flushes the internal read/write buffer for this stream. If write data has been buffered, + /// that data is written out to the underlying file. Or if data has been buffered for + /// reading from the stream, the data is dumped and our position in the underlying file + /// is rewound as necessary. This does not flush the OS buffer. + /// + private void FlushInternalBuffer() + { + AssertBufferInvariants(); + if (_writePos > 0) + { + FlushWriteBuffer(); + } + else if (_readPos < _readLength && CanSeek) + { + FlushReadBuffer(); + } + } + + /// Dumps any read data in the buffer and rewinds our position in the stream, accordingly, as necessary. + private void FlushReadBuffer() + { + // Reading is done by blocks from the file, but someone could read + // 1 byte from the buffer then write. At that point, the OS's file + // pointer is out of sync with the stream's position. All write + // functions should call this function to preserve the position in the file. + + AssertBufferInvariants(); + Debug.Assert(_writePos == 0, "FileStream: Write buffer must be empty in FlushReadBuffer!"); + + int rewind = _readPos - _readLength; + if (rewind != 0) + { + Debug.Assert(CanSeek, "FileStream will lose buffered read data now."); + SeekCore(rewind, SeekOrigin.Current); + } + _readPos = _readLength = 0; + } + + private int ReadByteCore() + { + PrepareForReading(); + + byte[] buffer = GetBuffer(); + if (_readPos == _readLength) + { + FlushWriteBuffer(); + Debug.Assert(_bufferLength > 0, "_bufferSize > 0"); + + _readLength = ReadNative(buffer, 0, _bufferLength); + _readPos = 0; + if (_readLength == 0) + { + return -1; + } + } + + return buffer[_readPos++]; + } + + private void WriteByteCore(byte value) + { + PrepareForWriting(); + + // Flush the write buffer if it's full + if (_writePos == _bufferLength) + FlushWriteBuffer(); + + // We now have space in the buffer. Store the byte. + GetBuffer()[_writePos++] = value; + } + + /// + /// Validates that we're ready to write to the stream, + /// including flushing a read buffer if necessary. + /// + private void PrepareForWriting() + { + if (_fileHandle.IsClosed) + throw Error.GetFileNotOpen(); + + // Make sure we're good to write. We only need to do this if there's nothing already + // in our write buffer, since if there is something in the buffer, we've already done + // this checking and flushing. + if (_writePos == 0) + { + if (!CanWrite) throw Error.GetWriteNotSupported(); + FlushReadBuffer(); + Debug.Assert(_bufferLength > 0, "_bufferSize > 0"); + } + } + + ~FileStream() + { + // Preserved for compatibility since FileStream has defined a + // finalizer in past releases and derived classes may depend + // on Dispose(false) call. + Dispose(false); + } + } +} diff --git a/src/mscorlib/corefx/System/IO/FileStreamCompletionSource.Win32.cs b/src/mscorlib/corefx/System/IO/FileStreamCompletionSource.Win32.cs new file mode 100644 index 0000000..532dbb0 --- /dev/null +++ b/src/mscorlib/corefx/System/IO/FileStreamCompletionSource.Win32.cs @@ -0,0 +1,221 @@ +// 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.Security; +using System.Threading; +using System.Threading.Tasks; +using System.Runtime.InteropServices; +using System.Diagnostics; + +namespace System.IO +{ + public partial class FileStream : Stream + { + // This is an internal object extending TaskCompletionSource with fields + // for all of the relevant data necessary to complete the IO operation. + // This is used by IOCallback and all of the async methods. + unsafe private sealed class FileStreamCompletionSource : TaskCompletionSource + { + private const long NoResult = 0; + private const long ResultSuccess = (long)1 << 32; + private const long ResultError = (long)2 << 32; + private const long RegisteringCancellation = (long)4 << 32; + private const long CompletedCallback = (long)8 << 32; + private const ulong ResultMask = ((ulong)uint.MaxValue) << 32; + + private static Action s_cancelCallback; + + private readonly FileStream _stream; + private readonly int _numBufferedBytes; + private readonly CancellationToken _cancellationToken; + private CancellationTokenRegistration _cancellationRegistration; +#if DEBUG + private bool _cancellationHasBeenRegistered; +#endif + private NativeOverlapped* _overlapped; // Overlapped class responsible for operations in progress when an appdomain unload occurs + private long _result; // Using long since this needs to be used in Interlocked APIs + + // Using RunContinuationsAsynchronously for compat reasons (old API used Task.Factory.StartNew for continuations) + internal FileStreamCompletionSource(FileStream stream, int numBufferedBytes, byte[] bytes, CancellationToken cancellationToken) + : base(TaskCreationOptions.RunContinuationsAsynchronously) + { + _numBufferedBytes = numBufferedBytes; + _stream = stream; + _result = NoResult; + _cancellationToken = cancellationToken; + + // Create the native overlapped. We try to use the preallocated overlapped if possible: + // it's possible if the byte buffer is the same one that's associated with the preallocated overlapped + // and if no one else is currently using the preallocated overlapped. This is the fast-path for cases + // where the user-provided buffer is smaller than the FileStream's buffer (such that the FileStream's + // buffer is used) and where operations on the FileStream are not being performed concurrently. + _overlapped = ReferenceEquals(bytes, _stream._buffer) && _stream.CompareExchangeCurrentOverlappedOwner(this, null) == null ? + _stream._fileHandle.ThreadPoolBinding.AllocateNativeOverlapped(_stream._preallocatedOverlapped) : + _stream._fileHandle.ThreadPoolBinding.AllocateNativeOverlapped(s_ioCallback, this, bytes); + Debug.Assert(_overlapped != null, "AllocateNativeOverlapped returned null"); + } + + internal NativeOverlapped* Overlapped + { + get { return _overlapped; } + } + + public void SetCompletedSynchronously(int numBytes) + { + ReleaseNativeResource(); + TrySetResult(numBytes + _numBufferedBytes); + } + + public void RegisterForCancellation() + { +#if DEBUG + Debug.Assert(!_cancellationHasBeenRegistered, "Cannot register for cancellation twice"); + _cancellationHasBeenRegistered = true; +#endif + + // Quick check to make sure that the cancellation token supports cancellation, and that the IO hasn't completed + if ((_cancellationToken.CanBeCanceled) && (_overlapped != null)) + { + var cancelCallback = s_cancelCallback; + if (cancelCallback == null) s_cancelCallback = cancelCallback = Cancel; + + // Register the cancellation only if the IO hasn't completed + long packedResult = Interlocked.CompareExchange(ref _result, RegisteringCancellation, NoResult); + if (packedResult == NoResult) + { + _cancellationRegistration = _cancellationToken.Register(cancelCallback, this); + + // Switch the result, just in case IO completed while we were setting the registration + packedResult = Interlocked.Exchange(ref _result, NoResult); + } + else if (packedResult != CompletedCallback) + { + // Failed to set the result, IO is in the process of completing + // Attempt to take the packed result + packedResult = Interlocked.Exchange(ref _result, NoResult); + } + + // If we have a callback that needs to be completed + if ((packedResult != NoResult) && (packedResult != CompletedCallback) && (packedResult != RegisteringCancellation)) + { + CompleteCallback((ulong)packedResult); + } + } + } + + internal void ReleaseNativeResource() + { + // Ensure that cancellation has been completed and cleaned up. + _cancellationRegistration.Dispose(); + + // Free the overlapped. + // NOTE: The cancellation must *NOT* be running at this point, or it may observe freed memory + // (this is why we disposed the registration above). + if (_overlapped != null) + { + _stream._fileHandle.ThreadPoolBinding.FreeNativeOverlapped(_overlapped); + _overlapped = null; + } + + // Ensure we're no longer set as the current completion source (we may not have been to begin with). + // Only one operation at a time is eligible to use the preallocated overlapped, + _stream.CompareExchangeCurrentOverlappedOwner(null, this); + } + + // When doing IO asynchronously (i.e. _isAsync==true), this callback is + // called by a free thread in the threadpool when the IO operation + // completes. + internal static unsafe void IOCallback(uint errorCode, uint numBytes, NativeOverlapped* pOverlapped) + { + // Extract the completion source from the overlapped. The state in the overlapped + // will either be a Win32FileStream (in the case where the preallocated overlapped was used), + // in which case the operation being completed is its _currentOverlappedOwner, or it'll + // be directly the FileStreamCompletion that's completing (in the case where the preallocated + // overlapped was already in use by another operation). + object state = ThreadPoolBoundHandle.GetNativeOverlappedState(pOverlapped); + FileStream fs = state as FileStream; + FileStreamCompletionSource completionSource = fs != null ? + fs._currentOverlappedOwner : + (FileStreamCompletionSource)state; + Debug.Assert(completionSource._overlapped == pOverlapped, "Overlaps don't match"); + + // Handle reading from & writing to closed pipes. While I'm not sure + // this is entirely necessary anymore, maybe it's possible for + // an async read on a pipe to be issued and then the pipe is closed, + // returning this error. This may very well be necessary. + ulong packedResult; + if (errorCode != 0 && errorCode != ERROR_BROKEN_PIPE && errorCode != ERROR_NO_DATA) + { + packedResult = ((ulong)ResultError | errorCode); + } + else + { + packedResult = ((ulong)ResultSuccess | numBytes); + } + + // Stow the result so that other threads can observe it + // And, if no other thread is registering cancellation, continue + if (NoResult == Interlocked.Exchange(ref completionSource._result, (long)packedResult)) + { + // Successfully set the state, attempt to take back the callback + if (Interlocked.Exchange(ref completionSource._result, CompletedCallback) != NoResult) + { + // Successfully got the callback, finish the callback + completionSource.CompleteCallback(packedResult); + } + // else: Some other thread stole the result, so now it is responsible to finish the callback + } + // else: Some other thread is registering a cancellation, so it *must* finish the callback + } + + private void CompleteCallback(ulong packedResult) { + // Free up the native resource and cancellation registration + ReleaseNativeResource(); + + // Unpack the result and send it to the user + long result = (long)(packedResult & ResultMask); + if (result == ResultError) + { + int errorCode = unchecked((int)(packedResult & uint.MaxValue)); + if (errorCode == Interop.mincore.Errors.ERROR_OPERATION_ABORTED) + { + TrySetCanceled(_cancellationToken.IsCancellationRequested ? _cancellationToken : new CancellationToken(true)); + } + else + { + TrySetException(Win32Marshal.GetExceptionForWin32Error(errorCode)); + } + } + else + { + Debug.Assert(result == ResultSuccess, "Unknown result"); + TrySetResult((int)(packedResult & uint.MaxValue) + _numBufferedBytes); + } + } + + private static void Cancel(object state) + { + // WARNING: This may potentially be called under a lock (during cancellation registration) + + FileStreamCompletionSource completionSource = state as FileStreamCompletionSource; + Debug.Assert(completionSource != null, "Unknown state passed to cancellation"); + Debug.Assert(completionSource._overlapped != null && !completionSource.Task.IsCompleted, "IO should not have completed yet"); + + // If the handle is still valid, attempt to cancel the IO + if (!completionSource._stream._fileHandle.IsInvalid && + !Interop.mincore.CancelIoEx(completionSource._stream._fileHandle, completionSource._overlapped)) + { + int errorCode = Marshal.GetLastWin32Error(); + + // ERROR_NOT_FOUND is returned if CancelIoEx cannot find the request to cancel. + // This probably means that the IO operation has completed. + if (errorCode != Interop.mincore.Errors.ERROR_NOT_FOUND) + { + throw Win32Marshal.GetExceptionForWin32Error(errorCode); + } + } + } + } + } +} diff --git a/src/mscorlib/corefx/System/IO/Path.Unix.cs b/src/mscorlib/corefx/System/IO/Path.Unix.cs new file mode 100644 index 0000000..2dd1907 --- /dev/null +++ b/src/mscorlib/corefx/System/IO/Path.Unix.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. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Text; + +namespace System.IO +{ + public static partial class Path + { + public static readonly char DirectorySeparatorChar = '/'; + public static readonly char VolumeSeparatorChar = '/'; + public static readonly char PathSeparator = ':'; + + private const string DirectorySeparatorCharAsString = "/"; + + public static char[] GetInvalidFileNameChars() => new char[] { '\0', '/' }; + + internal static readonly int MaxPath = Interop.Sys.MaxPath; + private static readonly int MaxLongPath = MaxPath; + + private static readonly bool s_isMac = Interop.Sys.GetUnixName() == "OSX"; + + // 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_PathIllegal); + + PathInternal.CheckInvalidPathChars(path); + + // Expand with current directory if necessary + if (!IsPathRooted(path)) + { + path = Combine(Interop.Sys.GetCwd(), path); + } + + // We would ideally use realpath to do this, but it resolves symlinks, requires that the file actually exist, + // and turns it into a full path, which we only want if fullCheck is true. + string collapsedString = RemoveRelativeSegments(path); + + Debug.Assert(collapsedString.Length < path.Length || collapsedString.ToString() == path, + "Either we've removed characters, or the string should be unmodified from the input path."); + + if (collapsedString.Length > MaxPath) + { + throw new PathTooLongException(SR.IO_PathTooLong); + } + + string result = collapsedString.Length == 0 ? DirectorySeparatorCharAsString : collapsedString; + + return result; + } + + /// + /// Try to remove relative segments from the given path (without combining with a root). + /// + /// Skip the specified number of characters before evaluating. + private static string RemoveRelativeSegments(string path, int skip = 0) + { + bool flippedSeparator = false; + + // Remove "//", "/./", and "/../" from the path by copying each character to the output, + // except the ones we're removing, such that the builder contains the normalized path + // at the end. + var sb = StringBuilderCache.Acquire(path.Length); + if (skip > 0) + { + sb.Append(path, 0, skip); + } + + int componentCharCount = 0; + for (int i = skip; i < path.Length; i++) + { + char c = path[i]; + + if (PathInternal.IsDirectorySeparator(c) && i + 1 < path.Length) + { + componentCharCount = 0; + + // Skip this character if it's a directory separator and if the next character is, too, + // e.g. "parent//child" => "parent/child" + if (PathInternal.IsDirectorySeparator(path[i + 1])) + { + continue; + } + + // Skip this character and the next if it's referring to the current directory, + // e.g. "parent/./child" =? "parent/child" + if ((i + 2 == path.Length || PathInternal.IsDirectorySeparator(path[i + 2])) && + path[i + 1] == '.') + { + i++; + continue; + } + + // Skip this character and the next two if it's referring to the parent directory, + // e.g. "parent/child/../grandchild" => "parent/grandchild" + if (i + 2 < path.Length && + (i + 3 == path.Length || PathInternal.IsDirectorySeparator(path[i + 3])) && + path[i + 1] == '.' && path[i + 2] == '.') + { + // Unwind back to the last slash (and if there isn't one, clear out everything). + int s; + for (s = sb.Length - 1; s >= 0; s--) + { + if (PathInternal.IsDirectorySeparator(sb[s])) + { + sb.Length = s; + break; + } + } + if (s < 0) + { + sb.Length = 0; + } + + i += 2; + continue; + } + } + + if (++componentCharCount > PathInternal.MaxComponentLength) + { + throw new PathTooLongException(SR.IO_PathTooLong); + } + + // Normalize the directory separator if needed + if (c != Path.DirectorySeparatorChar && c == Path.AltDirectorySeparatorChar) + { + c = Path.DirectorySeparatorChar; + flippedSeparator = true; + } + + sb.Append(c); + } + + if (flippedSeparator || sb.Length != path.Length) + { + return StringBuilderCache.GetStringAndRelease(sb); + } + else + { + // We haven't changed the source path, return the original + StringBuilderCache.Release(sb); + return path; + } + } + + private static string RemoveLongPathPrefix(string path) + { + return path; // nop. There's nothing special about "long" paths on Unix. + } + + public static string GetTempPath() + { + const string TempEnvVar = "TMPDIR"; + const string DefaultTempPath = "/tmp/"; + + // Get the temp path from the TMPDIR environment variable. + // If it's not set, just return the default path. + // If it is, return it, ensuring it ends with a slash. + string path = Environment.GetEnvironmentVariable(TempEnvVar); + return + string.IsNullOrEmpty(path) ? DefaultTempPath : + PathInternal.IsDirectorySeparator(path[path.Length - 1]) ? path : + path + DirectorySeparatorChar; + } + + public static string GetTempFileName() + { + const string Suffix = ".tmp"; + const int SuffixByteLength = 4; + + // mkstemps takes a char* and overwrites the XXXXXX with six characters + // that'll result in a unique file name. + string template = GetTempPath() + "tmpXXXXXX" + Suffix + "\0"; + byte[] name = Encoding.UTF8.GetBytes(template); + + // Create, open, and close the temp file. + IntPtr fd = Interop.CheckIo(Interop.Sys.MksTemps(name, SuffixByteLength)); + Interop.Sys.Close(fd); // ignore any errors from close; nothing to do if cleanup isn't possible + + // 'name' is now the name of the file + Debug.Assert(name[name.Length - 1] == '\0'); + return Encoding.UTF8.GetString(name, 0, name.Length - 1); // trim off the trailing '\0' + } + + public static bool IsPathRooted(string path) + { + if (path == null) + return false; + + PathInternal.CheckInvalidPathChars(path); + return path.Length > 0 && path[0] == DirectorySeparatorChar; + } + + public static string GetPathRoot(string path) + { + if (path == null) return null; + return IsPathRooted(path) ? DirectorySeparatorCharAsString : String.Empty; + } + + private static unsafe void GetCryptoRandomBytes(byte* bytes, int byteCount) + { +#if FEATURE_CORECLR + // We want to avoid dependencies on the Crypto library when compiling in CoreCLR. This + // will use the existing PAL implementation. + byte[] buffer = new byte[KeyLength]; + Microsoft.Win32.Win32Native.Random(bStrong: true, buffer: buffer, length: KeyLength); + Runtime.InteropServices.Marshal.Copy(buffer, 0, (IntPtr)bytes, KeyLength); +#else + if (s_isMac) + { + GetCryptoRandomBytesApple(bytes, byteCount); + } + else + { + GetCryptoRandomBytesOpenSsl(bytes, byteCount); + } +#endif + } + +#if !FEATURE_CORECLR + private static unsafe void GetCryptoRandomBytesApple(byte* bytes, int byteCount) + { + Debug.Assert(bytes != null); + Debug.Assert(byteCount >= 0); + + if (Interop.CommonCrypto.CCRandomGenerateBytes(bytes, byteCount) != 0) + { + throw new InvalidOperationException(SR.InvalidOperation_Cryptography); + } + } + + private static unsafe void GetCryptoRandomBytesOpenSsl(byte* bytes, int byteCount) + { + Debug.Assert(bytes != null); + Debug.Assert(byteCount >= 0); + + if (!Interop.Crypto.GetRandomBytes(bytes, byteCount)) + { + throw new InvalidOperationException(SR.InvalidOperation_Cryptography); + } + } +#endif + + /// Gets whether the system is case-sensitive. + internal static bool IsCaseSensitive { get { return !s_isMac; } } + } +} diff --git a/src/mscorlib/corefx/System/IO/Path.Win32.cs b/src/mscorlib/corefx/System/IO/Path.Win32.cs new file mode 100644 index 0000000..8a9e62e --- /dev/null +++ b/src/mscorlib/corefx/System/IO/Path.Win32.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. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; + +namespace System.IO +{ + public static partial class Path + { + private static unsafe void GetCryptoRandomBytes(byte* bytes, int byteCount) + { + // We need to fill a byte array with cryptographically-strong random bytes, but we can't reference + // System.Security.Cryptography.RandomNumberGenerator.dll due to layering. Instead, we just + // call to BCryptGenRandom directly, which is all that RandomNumberGenerator does. + + Debug.Assert(bytes != null); + Debug.Assert(byteCount >= 0); + + Interop.BCrypt.NTSTATUS status = Interop.BCrypt.BCryptGenRandom(bytes, byteCount); + if (status == Interop.BCrypt.NTSTATUS.STATUS_SUCCESS) + { + return; + } + else if (status == Interop.BCrypt.NTSTATUS.STATUS_NO_MEMORY) + { + throw new OutOfMemoryException(); + } + else + { + Debug.Fail("BCryptGenRandom should only fail due to OOM or invalid args / handle inputs."); + throw new InvalidOperationException(); + } + } + } +} diff --git a/src/mscorlib/corefx/System/IO/Path.Windows.cs b/src/mscorlib/corefx/System/IO/Path.Windows.cs new file mode 100644 index 0000000..b597efc --- /dev/null +++ b/src/mscorlib/corefx/System/IO/Path.Windows.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. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using System.Text; + +namespace System.IO +{ + public static partial class Path + { + public static readonly char DirectorySeparatorChar = '\\'; + public static readonly char VolumeSeparatorChar = ':'; + public static readonly char PathSeparator = ';'; + + private const string DirectorySeparatorCharAsString = "\\"; + + public static char[] GetInvalidFileNameChars() => new char[] + { + '\"', '<', '>', '|', '\0', + (char)1, (char)2, (char)3, (char)4, (char)5, (char)6, (char)7, (char)8, (char)9, (char)10, + (char)11, (char)12, (char)13, (char)14, (char)15, (char)16, (char)17, (char)18, (char)19, (char)20, + (char)21, (char)22, (char)23, (char)24, (char)25, (char)26, (char)27, (char)28, (char)29, (char)30, + (char)31, ':', '*', '?', '\\', '/' + }; + + // The max total path is 260, and the max individual component length is 255. + // For example, D:\<256 char file name> isn't legal, even though it's under 260 chars. + internal static readonly int MaxPath = 260; + internal static readonly int MaxLongPath = short.MaxValue; + + // Expands the given path to a fully qualified path. + public static string GetFullPath(string path) + { + if (path == null) + throw new ArgumentNullException(nameof(path)); + + // Embedded null characters are the only invalid character case we want to check up front. + // This is because the nulls will signal the end of the string to Win32 and therefore have + // unpredictable results. Other invalid characters we give a chance to be normalized out. + if (path.IndexOf('\0') != -1) + throw new ArgumentException(SR.Argument_InvalidPathChars, nameof(path)); + + if (PathInternal.IsExtended(path)) + { + // We can't really know what is valid for all cases of extended paths. + // + // - object names can include other characters as well (':', '/', etc.) + // - even file objects have different rules (pipe names can contain most characters) + // + // As such we will do no further analysis of extended paths to avoid blocking known and unknown + // scenarios as well as minimizing compat breaks should we block now and need to unblock later. + return path; + } + + bool isDevice = PathInternal.IsDevice(path); + if (!isDevice) + { + // Toss out paths with colons that aren't a valid drive specifier. + // Cannot start with a colon and can only be of the form "C:". + // (Note that we used to explicitly check "http:" and "file:"- these are caught by this check now.) + int startIndex = PathInternal.PathStartSkip(path); + + // Move past the colon + startIndex += 2; + + if ((path.Length > 0 && path[0] == VolumeSeparatorChar) + || (path.Length >= startIndex && path[startIndex - 1] == VolumeSeparatorChar && !PathInternal.IsValidDriveChar(path[startIndex - 2])) + || (path.Length > startIndex && path.IndexOf(VolumeSeparatorChar, startIndex) != -1)) + { + throw new NotSupportedException(SR.Argument_PathFormatNotSupported); + } + } + + // Technically this doesn't matter but we used to throw for this case + if (string.IsNullOrWhiteSpace(path)) + throw new ArgumentException(SR.Arg_PathIllegal); + + // We don't want to check invalid characters for device format- see comments for extended above + string fullPath = PathHelper.Normalize(path, checkInvalidCharacters: !isDevice, expandShortPaths: true); + + if (!isDevice) + { + // Emulate FileIOPermissions checks, retained for compatibility (normal invalid characters have already been checked) + if (PathInternal.HasWildCardCharacters(fullPath)) + throw new ArgumentException(SR.Argument_InvalidPathChars, nameof(path)); + } + + return fullPath; + } + + public static string GetTempPath() + { + StringBuilder sb = StringBuilderCache.Acquire(MaxPath); + uint r = Interop.mincore.GetTempPathW(MaxPath, sb); + if (r == 0) + throw Win32Marshal.GetExceptionForLastWin32Error(); + return GetFullPath(StringBuilderCache.GetStringAndRelease(sb)); + } + + // Returns a unique temporary file name, and creates a 0-byte file by that + // name on disk. + public static string GetTempFileName() + { + string path = GetTempPath(); + + StringBuilder sb = StringBuilderCache.Acquire(MaxPath); + uint r = Interop.mincore.GetTempFileNameW(path, "tmp", 0, sb); + if (r == 0) + throw Win32Marshal.GetExceptionForLastWin32Error(); + return StringBuilderCache.GetStringAndRelease(sb); + } + + // Tests if the given path contains a root. A path is considered rooted + // if it starts with a backslash ("\") or a drive letter and a colon (":"). + public static bool IsPathRooted(string path) + { + if (path != null) + { + PathInternal.CheckInvalidPathChars(path); + + int length = path.Length; + if ((length >= 1 && PathInternal.IsDirectorySeparator(path[0])) || + (length >= 2 && path[1] == VolumeSeparatorChar)) + return true; + } + return false; + } + + // Returns the root portion of the given path. The resulting string + // consists of those rightmost characters of the path that constitute the + // root of the path. Possible patterns for the resulting string are: An + // empty string (a relative path on the current drive), "\" (an absolute + // path on the current drive), "X:" (a relative path on a given drive, + // where X is the drive letter), "X:\" (an absolute path on a given drive), + // and "\\server\share" (a UNC path for a given server and share name). + // The resulting string is null if path is null. + public static string GetPathRoot(string path) + { + if (path == null) return null; + PathInternal.CheckInvalidPathChars(path); + + // Need to return the normalized directory separator + path = PathInternal.NormalizeDirectorySeparators(path); + + int pathRoot = PathInternal.GetRootLength(path); + return pathRoot <= 0 ? string.Empty : path.Substring(0, pathRoot); + } + + /// Gets whether the system is case-sensitive. + internal static bool IsCaseSensitive { get { return false; } } + } +} diff --git a/src/mscorlib/corefx/System/IO/Path.cs b/src/mscorlib/corefx/System/IO/Path.cs new file mode 100644 index 0000000..3b1ba6b --- /dev/null +++ b/src/mscorlib/corefx/System/IO/Path.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. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using System.Diagnostics.Contracts; +using System.Text; + +namespace System.IO +{ + // Provides methods for processing file system strings in a cross-platform manner. + // Most of the methods don't do a complete parsing (such as examining a UNC hostname), + // but they will handle most string operations. + public static partial class Path + { + // Platform specific alternate directory separator character. + // There is only one directory separator char on Unix, which is the same + // as the alternate separator on Windows, so same definition is used for both. + public static readonly char AltDirectorySeparatorChar = '/'; + + // For generating random file names + // 8 random bytes provides 12 chars in our encoding for the 8.3 name. + const int KeyLength = 8; + + [Obsolete("Please use GetInvalidPathChars or GetInvalidFileNameChars instead.")] + public static readonly char[] InvalidPathChars = GetInvalidPathChars(); + + // Changes the extension of a file path. The path parameter + // specifies a file path, and the extension parameter + // specifies a file extension (with a leading period, such as + // ".exe" or ".cs"). + // + // The function returns a file path with the same root, directory, and base + // name parts as path, but with the file extension changed to + // the specified extension. If path is null, the function + // returns null. If path does not contain a file extension, + // the new file extension is appended to the path. If extension + // is null, any existing extension is removed from path. + public static string ChangeExtension(string path, string extension) + { + if (path != null) + { + PathInternal.CheckInvalidPathChars(path); + + string s = path; + for (int i = path.Length - 1; i >= 0; i--) + { + char ch = path[i]; + if (ch == '.') + { + s = path.Substring(0, i); + break; + } + if (PathInternal.IsDirectoryOrVolumeSeparator(ch)) break; + } + + if (extension != null && path.Length != 0) + { + s = (extension.Length == 0 || extension[0] != '.') ? + s + "." + extension : + s + extension; + } + + return s; + } + return null; + } + + // Returns the directory path of a file path. This method effectively + // removes the last element of the given file path, i.e. it returns a + // string consisting of all characters up to but not including the last + // backslash ("\") in the file path. The returned value is null if the file + // path is null or if the file path denotes a root (such as "\", "C:", or + // "\\server\share"). + public static string GetDirectoryName(string path) + { + if (path != null) + { + PathInternal.CheckInvalidPathChars(path); + path = PathInternal.NormalizeDirectorySeparators(path); + int root = PathInternal.GetRootLength(path); + + int i = path.Length; + if (i > root) + { + while (i > root && !PathInternal.IsDirectorySeparator(path[--i])) ; + return path.Substring(0, i); + } + } + return null; + } + + public static char[] GetInvalidPathChars() + { + return PathInternal.GetInvalidPathChars(); + } + + // Returns the extension of the given path. The returned value includes the + // period (".") character of the extension except when you have a terminal period when you get string.Empty, such as ".exe" or + // ".cpp". The returned value is null if the given path is + // null or if the given path does not include an extension. + [Pure] + public static string GetExtension(string path) + { + if (path == null) + return null; + + PathInternal.CheckInvalidPathChars(path); + int length = path.Length; + for (int i = length - 1; i >= 0; i--) + { + char ch = path[i]; + if (ch == '.') + { + if (i != length - 1) + return path.Substring(i, length - i); + else + return string.Empty; + } + if (PathInternal.IsDirectoryOrVolumeSeparator(ch)) + break; + } + return string.Empty; + } + + // Returns the name and extension parts of the given path. The resulting + // string contains the characters of path that follow the last + // separator in path. The resulting string is null if path is null. + [Pure] + public static string GetFileName(string path) + { + if (path == null) + return null; + + int offset = PathInternal.FindFileNameIndex(path); + int count = path.Length - offset; + return path.Substring(offset, count); + } + + [Pure] + public static string GetFileNameWithoutExtension(string path) + { + if (path == null) + return null; + + int length = path.Length; + int offset = PathInternal.FindFileNameIndex(path); + + int end = path.LastIndexOf('.', length - 1, length - offset); + return end == -1 ? + path.Substring(offset) : // No extension was found + path.Substring(offset, end - offset); + } + + // Returns a cryptographically strong random 8.3 string that can be + // used as either a folder name or a file name. + public static unsafe string GetRandomFileName() + { + + byte* pKey = stackalloc byte[KeyLength]; + GetCryptoRandomBytes(pKey, KeyLength); + + const int RandomFileNameLength = 12; + char* pRandomFileName = stackalloc char[RandomFileNameLength]; + Populate83FileNameFromRandomBytes(pKey, KeyLength, pRandomFileName, RandomFileNameLength); + return new string(pRandomFileName, 0, RandomFileNameLength); + } + + // Tests if a path includes a file extension. The result is + // true if the characters that follow the last directory + // separator ('\\' or '/') or volume separator (':') in the path include + // a period (".") other than a terminal period. The result is false otherwise. + [Pure] + public static bool HasExtension(string path) + { + if (path != null) + { + PathInternal.CheckInvalidPathChars(path); + + for (int i = path.Length - 1; i >= 0; i--) + { + char ch = path[i]; + if (ch == '.') + { + return i != path.Length - 1; + } + if (PathInternal.IsDirectoryOrVolumeSeparator(ch)) break; + } + } + return false; + } + + public static string Combine(string path1, string path2) + { + if (path1 == null || path2 == null) + throw new ArgumentNullException((path1 == null) ? nameof(path1): nameof(path2)); + Contract.EndContractBlock(); + + PathInternal.CheckInvalidPathChars(path1); + PathInternal.CheckInvalidPathChars(path2); + + return CombineNoChecks(path1, path2); + } + + public static string Combine(string path1, string path2, string path3) + { + if (path1 == null || path2 == null || path3 == null) + throw new ArgumentNullException((path1 == null) ? nameof(path1): (path2 == null) ? nameof(path2): nameof(path3)); + Contract.EndContractBlock(); + + PathInternal.CheckInvalidPathChars(path1); + PathInternal.CheckInvalidPathChars(path2); + PathInternal.CheckInvalidPathChars(path3); + + return CombineNoChecks(path1, path2, path3); + } + + public static string Combine(string path1, string path2, string path3, string path4) + { + if (path1 == null || path2 == null || path3 == null || path4 == null) + throw new ArgumentNullException((path1 == null) ? nameof(path1): (path2 == null) ? nameof(path2): (path3 == null) ? nameof(path3): nameof(path4)); + Contract.EndContractBlock(); + + PathInternal.CheckInvalidPathChars(path1); + PathInternal.CheckInvalidPathChars(path2); + PathInternal.CheckInvalidPathChars(path3); + PathInternal.CheckInvalidPathChars(path4); + + return CombineNoChecks(path1, path2, path3, path4); + } + + public static string Combine(params string[] paths) + { + if (paths == null) + { + throw new ArgumentNullException(nameof(paths)); + } + Contract.EndContractBlock(); + + int finalSize = 0; + int firstComponent = 0; + + // We have two passes, the first calculates how large a buffer to allocate and does some precondition + // checks on the paths passed in. The second actually does the combination. + + for (int i = 0; i < paths.Length; i++) + { + if (paths[i] == null) + { + throw new ArgumentNullException(nameof(paths)); + } + + if (paths[i].Length == 0) + { + continue; + } + + PathInternal.CheckInvalidPathChars(paths[i]); + + if (IsPathRooted(paths[i])) + { + firstComponent = i; + finalSize = paths[i].Length; + } + else + { + finalSize += paths[i].Length; + } + + char ch = paths[i][paths[i].Length - 1]; + if (!PathInternal.IsDirectoryOrVolumeSeparator(ch)) + finalSize++; + } + + StringBuilder finalPath = StringBuilderCache.Acquire(finalSize); + + for (int i = firstComponent; i < paths.Length; i++) + { + if (paths[i].Length == 0) + { + continue; + } + + if (finalPath.Length == 0) + { + finalPath.Append(paths[i]); + } + else + { + char ch = finalPath[finalPath.Length - 1]; + if (!PathInternal.IsDirectoryOrVolumeSeparator(ch)) + { + finalPath.Append(DirectorySeparatorChar); + } + + finalPath.Append(paths[i]); + } + } + + return StringBuilderCache.GetStringAndRelease(finalPath); + } + + private static string CombineNoChecks(string path1, string path2) + { + if (path2.Length == 0) + return path1; + + if (path1.Length == 0) + return path2; + + if (IsPathRooted(path2)) + return path2; + + char ch = path1[path1.Length - 1]; + return PathInternal.IsDirectoryOrVolumeSeparator(ch) ? + path1 + path2 : + path1 + DirectorySeparatorCharAsString + path2; + } + + private static string CombineNoChecks(string path1, string path2, string path3) + { + if (path1.Length == 0) + return CombineNoChecks(path2, path3); + if (path2.Length == 0) + return CombineNoChecks(path1, path3); + if (path3.Length == 0) + return CombineNoChecks(path1, path2); + + if (IsPathRooted(path3)) + return path3; + if (IsPathRooted(path2)) + return CombineNoChecks(path2, path3); + + bool hasSep1 = PathInternal.IsDirectoryOrVolumeSeparator(path1[path1.Length - 1]); + bool hasSep2 = PathInternal.IsDirectoryOrVolumeSeparator(path2[path2.Length - 1]); + + if (hasSep1 && hasSep2) + { + return path1 + path2 + path3; + } + else if (hasSep1) + { + return path1 + path2 + DirectorySeparatorCharAsString + path3; + } + else if (hasSep2) + { + return path1 + DirectorySeparatorCharAsString + path2 + path3; + } + else + { + // string.Concat only has string-based overloads up to four arguments; after that requires allocating + // a params string[]. Instead, try to use a cached StringBuilder. + StringBuilder sb = StringBuilderCache.Acquire(path1.Length + path2.Length + path3.Length + 2); + sb.Append(path1) + .Append(DirectorySeparatorChar) + .Append(path2) + .Append(DirectorySeparatorChar) + .Append(path3); + return StringBuilderCache.GetStringAndRelease(sb); + } + } + + private static string CombineNoChecks(string path1, string path2, string path3, string path4) + { + if (path1.Length == 0) + return CombineNoChecks(path2, path3, path4); + if (path2.Length == 0) + return CombineNoChecks(path1, path3, path4); + if (path3.Length == 0) + return CombineNoChecks(path1, path2, path4); + if (path4.Length == 0) + return CombineNoChecks(path1, path2, path3); + + if (IsPathRooted(path4)) + return path4; + if (IsPathRooted(path3)) + return CombineNoChecks(path3, path4); + if (IsPathRooted(path2)) + return CombineNoChecks(path2, path3, path4); + + bool hasSep1 = PathInternal.IsDirectoryOrVolumeSeparator(path1[path1.Length - 1]); + bool hasSep2 = PathInternal.IsDirectoryOrVolumeSeparator(path2[path2.Length - 1]); + bool hasSep3 = PathInternal.IsDirectoryOrVolumeSeparator(path3[path3.Length - 1]); + + if (hasSep1 && hasSep2 && hasSep3) + { + // Use string.Concat overload that takes four strings + return path1 + path2 + path3 + path4; + } + else + { + // string.Concat only has string-based overloads up to four arguments; after that requires allocating + // a params string[]. Instead, try to use a cached StringBuilder. + StringBuilder sb = StringBuilderCache.Acquire(path1.Length + path2.Length + path3.Length + path4.Length + 3); + + sb.Append(path1); + if (!hasSep1) + { + sb.Append(DirectorySeparatorChar); + } + + sb.Append(path2); + if (!hasSep2) + { + sb.Append(DirectorySeparatorChar); + } + + sb.Append(path3); + if (!hasSep3) + { + sb.Append(DirectorySeparatorChar); + } + + sb.Append(path4); + + return StringBuilderCache.GetStringAndRelease(sb); + } + } + + private static readonly char[] s_base32Char = { + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', + 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', + 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5'}; + + private static unsafe void Populate83FileNameFromRandomBytes(byte* bytes, int byteCount, char* chars, int charCount) + { + Debug.Assert(bytes != null); + Debug.Assert(chars != null); + + // This method requires bytes of length 8 and chars of length 12. + Debug.Assert(byteCount == 8, $"Unexpected {nameof(byteCount)}"); + Debug.Assert(charCount == 12, $"Unexpected {nameof(charCount)}"); + + byte b0 = bytes[0]; + byte b1 = bytes[1]; + byte b2 = bytes[2]; + byte b3 = bytes[3]; + byte b4 = bytes[4]; + + // Consume the 5 Least significant bits of the first 5 bytes + chars[0] = s_base32Char[b0 & 0x1F]; + chars[1] = s_base32Char[b1 & 0x1F]; + chars[2] = s_base32Char[b2 & 0x1F]; + chars[3] = s_base32Char[b3 & 0x1F]; + chars[4] = s_base32Char[b4 & 0x1F]; + + // Consume 3 MSB of b0, b1, MSB bits 6, 7 of b3, b4 + chars[5] = s_base32Char[( + ((b0 & 0xE0) >> 5) | + ((b3 & 0x60) >> 2))]; + + chars[6] = s_base32Char[( + ((b1 & 0xE0) >> 5) | + ((b4 & 0x60) >> 2))]; + + // Consume 3 MSB bits of b2, 1 MSB bit of b3, b4 + b2 >>= 5; + + Debug.Assert(((b2 & 0xF8) == 0), "Unexpected set bits"); + + if ((b3 & 0x80) != 0) + b2 |= 0x08; + if ((b4 & 0x80) != 0) + b2 |= 0x10; + + chars[7] = s_base32Char[b2]; + + // Set the file extension separator + chars[8] = '.'; + + // Consume the 5 Least significant bits of the remaining 3 bytes + chars[9] = s_base32Char[(bytes[5] & 0x1F)]; + chars[10] = s_base32Char[(bytes[6] & 0x1F)]; + chars[11] = s_base32Char[(bytes[7] & 0x1F)]; + } + + /// + /// Create a relative path from one path to another. Paths will be resolved before calculating the difference. + /// Default path comparison for the active platform will be used (OrdinalIgnoreCase for Windows or Mac, Ordinal for Unix). + /// + /// The source path the output should be relative to. This path is always considered to be a directory. + /// The destination path. + /// The relative path or if the paths don't share the same root. + /// Thrown if or is null or an empty string. + public static string GetRelativePath(string relativeTo, string path) + { + return GetRelativePath(relativeTo, path, StringComparison); + } + + private static string GetRelativePath(string relativeTo, string path, StringComparison comparisonType) + { + if (string.IsNullOrEmpty(relativeTo)) throw new ArgumentNullException(nameof(relativeTo)); + if (string.IsNullOrWhiteSpace(path)) throw new ArgumentNullException(nameof(path)); + Debug.Assert(comparisonType == StringComparison.Ordinal || comparisonType == StringComparison.OrdinalIgnoreCase); + + relativeTo = GetFullPath(relativeTo); + path = GetFullPath(path); + + // Need to check if the roots are different- if they are we need to return the "to" path. + if (!PathInternal.AreRootsEqual(relativeTo, path, comparisonType)) + return path; + + int commonLength = PathInternal.GetCommonPathLength(relativeTo, path, ignoreCase: comparisonType == StringComparison.OrdinalIgnoreCase); + + // If there is nothing in common they can't share the same root, return the "to" path as is. + if (commonLength == 0) + return path; + + // Trailing separators aren't significant for comparison + int relativeToLength = relativeTo.Length; + if (PathInternal.EndsInDirectorySeparator(relativeTo)) + relativeToLength--; + + bool pathEndsInSeparator = PathInternal.EndsInDirectorySeparator(path); + int pathLength = path.Length; + if (pathEndsInSeparator) + pathLength--; + + // If we have effectively the same path, return "." + if (relativeToLength == pathLength && commonLength >= relativeToLength) return "."; + + // We have the same root, we need to calculate the difference now using the + // common Length and Segment count past the length. + // + // Some examples: + // + // C:\Foo C:\Bar L3, S1 -> ..\Bar + // C:\Foo C:\Foo\Bar L6, S0 -> Bar + // C:\Foo\Bar C:\Bar\Bar L3, S2 -> ..\..\Bar\Bar + // C:\Foo\Foo C:\Foo\Bar L7, S1 -> ..\Bar + + StringBuilder sb = StringBuilderCache.Acquire(Math.Max(relativeTo.Length, path.Length)); + + // Add parent segments for segments past the common on the "from" path + if (commonLength < relativeToLength) + { + sb.Append(PathInternal.ParentDirectoryPrefix); + + for (int i = commonLength; i < relativeToLength; i++) + { + if (PathInternal.IsDirectorySeparator(relativeTo[i])) + { + sb.Append(PathInternal.ParentDirectoryPrefix); + } + } + } + else if (PathInternal.IsDirectorySeparator(path[commonLength])) + { + // No parent segments and we need to eat the initial separator + // (C:\Foo C:\Foo\Bar case) + commonLength++; + } + + // Now add the rest of the "to" path, adding back the trailing separator + int count = pathLength - commonLength; + if (pathEndsInSeparator) + count++; + + sb.Append(path, commonLength, count); + return StringBuilderCache.GetStringAndRelease(sb); + } + + // StringComparison and IsCaseSensitive are also available in PathInternal.CaseSensitivity but we are + // too low in System.Runtime.Extensions to use it (no FileStream, etc.) + + /// Returns a comparison that can be used to compare file and directory names for equality. + internal static StringComparison StringComparison + { + get + { + return IsCaseSensitive ? + StringComparison.Ordinal : + StringComparison.OrdinalIgnoreCase; + } + } + } +} diff --git a/src/mscorlib/corefx/System/IO/PathHelper.Windows.cs b/src/mscorlib/corefx/System/IO/PathHelper.Windows.cs new file mode 100644 index 0000000..4c2cdff --- /dev/null +++ b/src/mscorlib/corefx/System/IO/PathHelper.Windows.cs @@ -0,0 +1,389 @@ +// 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.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace System.IO +{ + /// + /// Wrapper to help with path normalization. + /// + unsafe internal class PathHelper + { + // Can't be over 8.3 and be a short name + private const int MaxShortName = 12; + + private const char LastAnsi = (char)255; + private const char Delete = (char)127; + + [ThreadStatic] + private static StringBuffer t_fullPathBuffer; + + /// + /// Normalize the given path. + /// + /// + /// Normalizes via Win32 GetFullPathName(). It will also trim all "typical" whitespace at the end of the path (see s_trimEndChars). Will also trim initial + /// spaces if the path is determined to be rooted. + /// + /// Note that invalid characters will be checked after the path is normalized, which could remove bad characters. (C:\|\..\a.txt -- C:\a.txt) + /// + /// Path to normalize + /// True to check for invalid characters + /// Attempt to expand short paths if true + /// Thrown if the path is an illegal UNC (does not contain a full server/share) or contains illegal characters. + /// Thrown if the path or a path segment exceeds the filesystem limits. + /// Thrown if Windows returns ERROR_FILE_NOT_FOUND. (See Win32Marshal.GetExceptionForWin32Error) + /// Thrown if Windows returns ERROR_PATH_NOT_FOUND. (See Win32Marshal.GetExceptionForWin32Error) + /// Thrown if Windows returns ERROR_ACCESS_DENIED. (See Win32Marshal.GetExceptionForWin32Error) + /// Thrown if Windows returns an error that doesn't map to the above. (See Win32Marshal.GetExceptionForWin32Error) + /// Normalized path + internal static string Normalize(string path, bool checkInvalidCharacters, bool expandShortPaths) + { + // Get the full path + StringBuffer fullPath = t_fullPathBuffer ?? (t_fullPathBuffer = new StringBuffer(PathInternal.MaxShortPath)); + try + { + GetFullPathName(path, fullPath); + + // Trim whitespace off the end of the string. Win32 normalization trims only U+0020. + fullPath.TrimEnd(PathInternal.s_trimEndChars); + + if (fullPath.Length >= PathInternal.MaxLongPath) + { + // Fullpath is genuinely too long + throw new PathTooLongException(SR.IO_PathTooLong); + } + + // Checking path validity used to happen before getting the full path name. To avoid additional input allocation + // (to trim trailing whitespace) we now do it after the Win32 call. This will allow legitimate paths through that + // used to get kicked back (notably segments with invalid characters might get removed via ".."). + // + // There is no way that GetLongPath can invalidate the path so we'll do this (cheaper) check before we attempt to + // expand short file names. + + // Scan the path for: + // + // - Illegal path characters. + // - Invalid UNC paths like \\, \\server, \\server\. + // - Segments that are too long (over MaxComponentLength) + + // As the path could be > 30K, we'll combine the validity scan. None of these checks are performed by the Win32 + // GetFullPathName() API. + + bool possibleShortPath = false; + bool foundTilde = false; + + // We can get UNCs as device paths through this code (e.g. \\.\UNC\), we won't validate them as there isn't + // an easy way to normalize without extensive cost (we'd have to hunt down the canonical name for any device + // path that contains UNC or to see if the path was doing something like \\.\GLOBALROOT\Device\Mup\, + // \\.\GLOBAL\UNC\, \\.\GLOBALROOT\GLOBAL??\UNC\, etc. + bool specialPath = fullPath.Length > 1 && fullPath[0] == '\\' && fullPath[1] == '\\'; + bool isDevice = PathInternal.IsDevice(fullPath); + bool possibleBadUnc = specialPath && !isDevice; + uint index = specialPath ? 2u : 0; + uint lastSeparator = specialPath ? 1u : 0; + uint segmentLength; + char* start = fullPath.CharPointer; + char current; + + while (index < fullPath.Length) + { + current = start[index]; + + // Try to skip deeper analysis. '?' and higher are valid/ignorable except for '\', '|', and '~' + if (current < '?' || current == '\\' || current == '|' || current == '~') + { + switch (current) + { + case '|': + case '>': + case '<': + case '\"': + if (checkInvalidCharacters) throw new ArgumentException(SR.Argument_InvalidPathChars); + foundTilde = false; + break; + case '~': + foundTilde = true; + break; + case '\\': + segmentLength = index - lastSeparator - 1; + if (segmentLength > (uint)PathInternal.MaxComponentLength) + throw new PathTooLongException(SR.IO_PathTooLong + fullPath.ToString()); + lastSeparator = index; + + if (foundTilde) + { + if (segmentLength <= MaxShortName) + { + // Possibly a short path. + possibleShortPath = true; + } + + foundTilde = false; + } + + if (possibleBadUnc) + { + // If we're at the end of the path and this is the first separator, we're missing the share. + // Otherwise we're good, so ignore UNC tracking from here. + if (index == fullPath.Length - 1) + throw new ArgumentException(SR.Arg_PathIllegalUNC); + else + possibleBadUnc = false; + } + + break; + + default: + if (checkInvalidCharacters && current < ' ') throw new ArgumentException(SR.Argument_InvalidPathChars, nameof(path)); + break; + } + } + + index++; + } + + if (possibleBadUnc) + throw new ArgumentException(SR.Arg_PathIllegalUNC); + + segmentLength = fullPath.Length - lastSeparator - 1; + if (segmentLength > (uint)PathInternal.MaxComponentLength) + throw new PathTooLongException(SR.IO_PathTooLong); + + if (foundTilde && segmentLength <= MaxShortName) + possibleShortPath = true; + + // Check for a short filename path and try and expand it. Technically you don't need to have a tilde for a short name, but + // this is how we've always done this. This expansion is costly so we'll continue to let other short paths slide. + if (expandShortPaths && possibleShortPath) + { + return TryExpandShortFileName(fullPath, originalPath: path); + } + else + { + if (fullPath.Length == (uint)path.Length && fullPath.StartsWith(path)) + { + // If we have the exact same string we were passed in, don't bother to allocate another string from the StringBuilder. + return path; + } + else + { + return fullPath.ToString(); + } + } + } + finally + { + // Clear the buffer + fullPath.Free(); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsDosUnc(StringBuffer buffer) + { + return !PathInternal.IsDevice(buffer) && buffer.Length > 1 && buffer[0] == '\\' && buffer[1] == '\\'; + } + + private static void GetFullPathName(string path, StringBuffer fullPath) + { + // If the string starts with an extended prefix we would need to remove it from the path before we call GetFullPathName as + // it doesn't root extended paths correctly. We don't currently resolve extended paths, so we'll just assert here. + Debug.Assert(PathInternal.IsPartiallyQualified(path) || !PathInternal.IsExtended(path)); + + // Historically we would skip leading spaces *only* if the path started with a drive " C:" or a UNC " \\" + int startIndex = PathInternal.PathStartSkip(path); + + fixed (char* pathStart = path) + { + uint result = 0; + while ((result = Interop.mincore.GetFullPathNameW(pathStart + startIndex, fullPath.CharCapacity, fullPath.GetHandle(), IntPtr.Zero)) > fullPath.CharCapacity) + { + // Reported size (which does not include the null) is greater than the buffer size. Increase the capacity. + fullPath.EnsureCharCapacity(result); + } + + if (result == 0) + { + // Failure, get the error and throw + int errorCode = Marshal.GetLastWin32Error(); + if (errorCode == 0) + errorCode = Interop.mincore.Errors.ERROR_BAD_PATHNAME; + throw Win32Marshal.GetExceptionForWin32Error(errorCode, path); + } + + fullPath.Length = result; + } + } + + private static uint GetInputBuffer(StringBuffer content, bool isDosUnc, out StringBuffer buffer) + { + uint length = content.Length; + + length += isDosUnc + ? (uint)PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength + : PathInternal.DevicePrefixLength; + + buffer = new StringBuffer(length); + + if (isDosUnc) + { + // Put the extended UNC prefix (\\?\UNC\) in front of the path + buffer.CopyFrom(bufferIndex: 0, source: PathInternal.UncExtendedPathPrefix); + + // Copy the source buffer over after the existing UNC prefix + content.CopyTo( + bufferIndex: PathInternal.UncPrefixLength, + destination: buffer, + destinationIndex: PathInternal.UncExtendedPrefixLength, + count: content.Length - PathInternal.UncPrefixLength); + + // Return the prefix difference + return (uint)PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength; + } + else + { + uint prefixSize = (uint)PathInternal.ExtendedPathPrefix.Length; + buffer.CopyFrom(bufferIndex: 0, source: PathInternal.ExtendedPathPrefix); + content.CopyTo(bufferIndex: 0, destination: buffer, destinationIndex: prefixSize, count: content.Length); + return prefixSize; + } + } + + private static string TryExpandShortFileName(StringBuffer outputBuffer, string originalPath) + { + // We guarantee we'll expand short names for paths that only partially exist. As such, we need to find the part of the path that actually does exist. To + // avoid allocating like crazy we'll create only one input array and modify the contents with embedded nulls. + + Debug.Assert(!PathInternal.IsPartiallyQualified(outputBuffer), "should have resolved by now"); + + // We'll have one of a few cases by now (the normalized path will have already: + // + // 1. Dos path (C:\) + // 2. Dos UNC (\\Server\Share) + // 3. Dos device path (\\.\C:\, \\?\C:\) + // + // We want to put the extended syntax on the front if it doesn't already have it, which may mean switching from \\.\. + // + // Note that we will never get \??\ here as GetFullPathName() does not recognize \??\ and will return it as C:\??\ (or whatever the current drive is). + + uint rootLength = PathInternal.GetRootLength(outputBuffer); + bool isDevice = PathInternal.IsDevice(outputBuffer); + + StringBuffer inputBuffer = null; + bool isDosUnc = false; + uint rootDifference = 0; + bool wasDotDevice = false; + + // Add the extended prefix before expanding to allow growth over MAX_PATH + if (isDevice) + { + // We have one of the following (\\?\ or \\.\) + inputBuffer = new StringBuffer(); + inputBuffer.Append(outputBuffer); + + if (outputBuffer[2] == '.') + { + wasDotDevice = true; + inputBuffer[2] = '?'; + } + } + else + { + isDosUnc = IsDosUnc(outputBuffer); + rootDifference = GetInputBuffer(outputBuffer, isDosUnc, out inputBuffer); + } + + rootLength += rootDifference; + uint inputLength = inputBuffer.Length; + + bool success = false; + uint foundIndex = inputBuffer.Length - 1; + + while (!success) + { + uint result = Interop.mincore.GetLongPathNameW(inputBuffer.GetHandle(), outputBuffer.GetHandle(), outputBuffer.CharCapacity); + + // Replace any temporary null we added + if (inputBuffer[foundIndex] == '\0') inputBuffer[foundIndex] = '\\'; + + if (result == 0) + { + // Look to see if we couldn't find the file + int error = Marshal.GetLastWin32Error(); + if (error != Interop.mincore.Errors.ERROR_FILE_NOT_FOUND && error != Interop.mincore.Errors.ERROR_PATH_NOT_FOUND) + { + // Some other failure, give up + break; + } + + // We couldn't find the path at the given index, start looking further back in the string. + foundIndex--; + + for (; foundIndex > rootLength && inputBuffer[foundIndex] != '\\'; foundIndex--) ; + if (foundIndex == rootLength) + { + // Can't trim the path back any further + break; + } + else + { + // Temporarily set a null in the string to get Windows to look further up the path + inputBuffer[foundIndex] = '\0'; + } + } + else if (result > outputBuffer.CharCapacity) + { + // Not enough space. The result count for this API does not include the null terminator. + outputBuffer.EnsureCharCapacity(result); + result = Interop.mincore.GetLongPathNameW(inputBuffer.GetHandle(), outputBuffer.GetHandle(), outputBuffer.CharCapacity); + } + else + { + // Found the path + success = true; + outputBuffer.Length = result; + if (foundIndex < inputLength - 1) + { + // It was a partial find, put the non-existent part of the path back + outputBuffer.Append(inputBuffer, foundIndex, inputBuffer.Length - foundIndex); + } + } + } + + // Strip out the prefix and return the string + StringBuffer bufferToUse = success ? outputBuffer : inputBuffer; + + // Switch back from \\?\ to \\.\ if necessary + if (wasDotDevice) + bufferToUse[2] = '.'; + + string returnValue = null; + + int newLength = (int)(bufferToUse.Length - rootDifference); + if (isDosUnc) + { + // Need to go from \\?\UNC\ to \\?\UN\\ + bufferToUse[PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength] = '\\'; + } + + // We now need to strip out any added characters at the front of the string + if (bufferToUse.SubstringEquals(originalPath, rootDifference, newLength)) + { + // Use the original path to avoid allocating + returnValue = originalPath; + } + else + { + returnValue = bufferToUse.Substring(rootDifference, newLength); + } + + inputBuffer.Dispose(); + return returnValue; + } + } +} diff --git a/src/mscorlib/corefx/System/IO/PathInternal.CaseSensitivity.cs b/src/mscorlib/corefx/System/IO/PathInternal.CaseSensitivity.cs new file mode 100644 index 0000000..bea2df9 --- /dev/null +++ b/src/mscorlib/corefx/System/IO/PathInternal.CaseSensitivity.cs @@ -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. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; + +namespace System.IO +{ + /// Contains internal path helpers that are shared between many projects. + internal static partial class PathInternal + { + private enum Tristate : byte + { + NotInitialized, + True, + False, + } + + private static Tristate s_isCaseSensitive = Tristate.NotInitialized; + + /// Returns a comparison that can be used to compare file and directory names for equality. + internal static StringComparison StringComparison + { + get + { + return IsCaseSensitive ? + StringComparison.Ordinal : + StringComparison.OrdinalIgnoreCase; + } + } + + /// Gets whether the system is case-sensitive. + internal static bool IsCaseSensitive + { + get + { + // This must be lazily initialized as there are dependencies on PathInternal's static constructor + // being fully initialized. (GetIsCaseSensitive() calls GetFullPath() which needs to use PathInternal) + if (s_isCaseSensitive == Tristate.NotInitialized) + s_isCaseSensitive = GetIsCaseSensitive() ? Tristate.True : Tristate.False; + + return s_isCaseSensitive == Tristate.True; + } + } + + /// + /// Determines whether the file system is case sensitive. + /// + /// + /// Ideally we'd use something like pathconf with _PC_CASE_SENSITIVE, but that is non-portable, + /// not supported on Windows or Linux, etc. For now, this function creates a tmp file with capital letters + /// and then tests for its existence with lower-case letters. This could return invalid results in corner + /// cases where, for example, different file systems are mounted with differing sensitivities. + /// + private static bool GetIsCaseSensitive() + { + try + { + string pathWithUpperCase = Path.Combine(Path.GetTempPath(), "CASESENSITIVETEST" + Guid.NewGuid().ToString("N")); + using (new FileStream(pathWithUpperCase, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None, 0x1000, FileOptions.DeleteOnClose)) + { + string lowerCased = pathWithUpperCase.ToLowerInvariant(); + return !File.Exists(lowerCased); + } + } + catch (Exception exc) + { + // In case something goes terribly wrong, we don't want to fail just because + // of a casing test, so we assume case-insensitive-but-preserving. + Debug.Fail("Casing test failed: " + exc); + return false; + } + } + } +} diff --git a/src/mscorlib/corefx/System/IO/PathInternal.Unix.cs b/src/mscorlib/corefx/System/IO/PathInternal.Unix.cs new file mode 100644 index 0000000..6c39f99 --- /dev/null +++ b/src/mscorlib/corefx/System/IO/PathInternal.Unix.cs @@ -0,0 +1,122 @@ +// 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.Diagnostics; +using System.Text; + +namespace System.IO +{ + /// Contains internal path helpers that are shared between many projects. + internal static partial class PathInternal + { + // There is only one invalid path character in Unix + private const char InvalidPathChar = '\0'; + internal static char[] GetInvalidPathChars() => new char[] { InvalidPathChar }; + + internal static readonly int MaxComponentLength = Interop.Sys.MaxName; + + internal const string ParentDirectoryPrefix = @"../"; + + /// Returns a value indicating if the given path contains invalid characters. + internal static bool HasIllegalCharacters(string path) + { + Debug.Assert(path != null); + return path.IndexOf(InvalidPathChar) >= 0; + } + + internal static int GetRootLength(string path) + { + return path.Length > 0 && IsDirectorySeparator(path[0]) ? 1 : 0; + } + + internal static bool IsDirectorySeparator(char c) + { + // The alternate directory separator char is the same as the directory separator, + // so we only need to check one. + Debug.Assert(Path.DirectorySeparatorChar == Path.AltDirectorySeparatorChar); + return c == Path.DirectorySeparatorChar; + } + + /// + /// Returns true if the path is too long + /// + internal static bool IsPathTooLong(string fullPath) + { + return fullPath.Length >= Interop.Sys.MaxPath; + } + + /// + /// Returns true if the directory is too long + /// + internal static bool IsDirectoryTooLong(string fullPath) + { + return fullPath.Length >= Interop.Sys.MaxPath; + } + + /// + /// Normalize separators in the given path. Compresses forward slash runs. + /// + internal static string NormalizeDirectorySeparators(string path) + { + if (string.IsNullOrEmpty(path)) return path; + + // Make a pass to see if we need to normalize so we can potentially skip allocating + bool normalized = true; + + for (int i = 0; i < path.Length; i++) + { + if (IsDirectorySeparator(path[i]) + && (i + 1 < path.Length && IsDirectorySeparator(path[i + 1]))) + { + normalized = false; + break; + } + } + + if (normalized) return path; + + StringBuilder builder = new StringBuilder(path.Length); + + for (int i = 0; i < path.Length; i++) + { + char current = path[i]; + + // Skip if we have another separator following + if (IsDirectorySeparator(current) + && (i + 1 < path.Length && IsDirectorySeparator(path[i + 1]))) + continue; + + builder.Append(current); + } + + return builder.ToString(); + } + + /// + /// Returns true if the character is a directory or volume separator. + /// + /// The character to test. + internal static bool IsDirectoryOrVolumeSeparator(char ch) + { + // The directory separator, volume separator, and the alternate directory + // separator should be the same on Unix, so we only need to check one. + Debug.Assert(Path.DirectorySeparatorChar == Path.AltDirectorySeparatorChar); + Debug.Assert(Path.DirectorySeparatorChar == Path.VolumeSeparatorChar); + return ch == Path.DirectorySeparatorChar; + } + + internal static bool HasInvalidVolumeSeparator(string path) + { + // This is only ever true for Windows + return false; + } + + internal static bool IsPartiallyQualified(string path) + { + // This is much simpler than Windows where paths can be rooted, but not fully qualified (such as Drive Relative) + // As long as the path is rooted in Unix it doesn't use the current directory and therefore is fully qualified. + return !Path.IsPathRooted(path); + } + } +} diff --git a/src/mscorlib/corefx/System/IO/PathInternal.Windows.StringBuffer.cs b/src/mscorlib/corefx/System/IO/PathInternal.Windows.StringBuffer.cs new file mode 100644 index 0000000..fec2218 --- /dev/null +++ b/src/mscorlib/corefx/System/IO/PathInternal.Windows.StringBuffer.cs @@ -0,0 +1,89 @@ +// 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.Diagnostics; +using System.Runtime.InteropServices; + +namespace System.IO +{ + /// Contains internal path helpers that are shared between many projects. + internal static partial class PathInternal + { + /// + /// Returns true if the path uses the extended syntax (\\?\) + /// + internal static bool IsExtended(StringBuffer path) + { + // While paths like "//?/C:/" will work, they're treated the same as "\\.\" paths. + // Skipping of normalization will *only* occur if back slashes ('\') are used. + return path.Length >= DevicePrefixLength + && path[0] == '\\' + && (path[1] == '\\' || path[1] == '?') + && path[2] == '?' + && path[3] == '\\'; + } + + /// + /// Gets the length of the root of the path (drive, share, etc.). + /// + internal unsafe static uint GetRootLength(StringBuffer path) + { + if (path.Length == 0) return 0; + return GetRootLength(path.CharPointer, path.Length); + } + + /// + /// Returns true if the path uses any of the DOS device path syntaxes. ("\\.\", "\\?\", or "\??\") + /// + internal static bool IsDevice(StringBuffer path) + { + // If the path begins with any two separators is will be recognized and normalized and prepped with + // "\??\" for internal usage correctly. "\??\" is recognized and handled, "/??/" is not. + return IsExtended(path) + || + ( + path.Length >= DevicePrefixLength + && IsDirectorySeparator(path[0]) + && IsDirectorySeparator(path[1]) + && (path[2] == '.' || path[2] == '?') + && IsDirectorySeparator(path[3]) + ); + } + + /// + /// Returns true if the path specified is relative to the current drive or working directory. + /// Returns false if the path is fixed to a specific drive or UNC path. This method does no + /// validation of the path (URIs will be returned as relative as a result). + /// + /// + /// Handles paths that use the alternate directory separator. It is a frequent mistake to + /// assume that rooted paths (Path.IsPathRooted) are not relative. This isn't the case. + /// "C:a" is drive relative- meaning that it will be resolved against the current directory + /// for C: (rooted, but relative). "C:\a" is rooted and not relative (the current directory + /// will not be used to modify the path). + /// + internal static bool IsPartiallyQualified(StringBuffer path) + { + if (path.Length < 2) + { + // It isn't fixed, it must be relative. There is no way to specify a fixed + // path with one character (or less). + return true; + } + + if (IsDirectorySeparator(path[0])) + { + // There is no valid way to specify a relative path with two initial slashes or + // \? as ? isn't valid for drive relative paths and \??\ is equivalent to \\?\ + return !(path[1] == '?' || IsDirectorySeparator(path[1])); + } + + // The only way to specify a fixed path that doesn't begin with two slashes + // is the drive, colon, slash format- i.e. C:\ + return !((path.Length >= 3) + && (path[1] == Path.VolumeSeparatorChar) + && IsDirectorySeparator(path[2])); + } + } +} diff --git a/src/mscorlib/corefx/System/IO/PathInternal.Windows.cs b/src/mscorlib/corefx/System/IO/PathInternal.Windows.cs new file mode 100644 index 0000000..bd7f1ea --- /dev/null +++ b/src/mscorlib/corefx/System/IO/PathInternal.Windows.cs @@ -0,0 +1,482 @@ +// 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.Diagnostics; +using System.Runtime.CompilerServices; +using System.Text; + +namespace System.IO +{ + /// Contains internal path helpers that are shared between many projects. + internal static partial class PathInternal + { + // All paths in Win32 ultimately end up becoming a path to a File object in the Windows object manager. Passed in paths get mapped through + // DosDevice symbolic links in the object tree to actual File objects under \Devices. To illustrate, this is what happens with a typical + // path "Foo" passed as a filename to any Win32 API: + // + // 1. "Foo" is recognized as a relative path and is appended to the current directory (say, "C:\" in our example) + // 2. "C:\Foo" is prepended with the DosDevice namespace "\??\" + // 3. CreateFile tries to create an object handle to the requested file "\??\C:\Foo" + // 4. The Object Manager recognizes the DosDevices prefix and looks + // a. First in the current session DosDevices ("\Sessions\1\DosDevices\" for example, mapped network drives go here) + // b. If not found in the session, it looks in the Global DosDevices ("\GLOBAL??\") + // 5. "C:" is found in DosDevices (in our case "\GLOBAL??\C:", which is a symbolic link to "\Device\HarddiskVolume6") + // 6. The full path is now "\Device\HarddiskVolume6\Foo", "\Device\HarddiskVolume6" is a File object and parsing is handed off + // to the registered parsing method for Files + // 7. The registered open method for File objects is invoked to create the file handle which is then returned + // + // There are multiple ways to directly specify a DosDevices path. The final format of "\??\" is one way. It can also be specified + // as "\\.\" (the most commonly documented way) and "\\?\". If the question mark syntax is used the path will skip normalization + // (essentially GetFullPathName()) and path length checks. + + // Windows Kernel-Mode Object Manager + // https://msdn.microsoft.com/en-us/library/windows/hardware/ff565763.aspx + // https://channel9.msdn.com/Shows/Going+Deep/Windows-NT-Object-Manager + // + // Introduction to MS-DOS Device Names + // https://msdn.microsoft.com/en-us/library/windows/hardware/ff548088.aspx + // + // Local and Global MS-DOS Device Names + // https://msdn.microsoft.com/en-us/library/windows/hardware/ff554302.aspx + + internal const string ExtendedPathPrefix = @"\\?\"; + internal const string UncPathPrefix = @"\\"; + internal const string UncExtendedPrefixToInsert = @"?\UNC\"; + internal const string UncExtendedPathPrefix = @"\\?\UNC\"; + internal const string DevicePathPrefix = @"\\.\"; + internal const string ParentDirectoryPrefix = @"..\"; + + internal const int MaxShortPath = 260; + internal const int MaxShortDirectoryPath = 248; + internal const int MaxLongPath = short.MaxValue; + // \\?\, \\.\, \??\ + internal const int DevicePrefixLength = 4; + // \\ + internal const int UncPrefixLength = 2; + // \\?\UNC\, \\.\UNC\ + internal const int UncExtendedPrefixLength = 8; + internal const int MaxComponentLength = 255; + + internal static char[] GetInvalidPathChars() => new char[] + { + '|', '\0', + (char)1, (char)2, (char)3, (char)4, (char)5, (char)6, (char)7, (char)8, (char)9, (char)10, + (char)11, (char)12, (char)13, (char)14, (char)15, (char)16, (char)17, (char)18, (char)19, (char)20, + (char)21, (char)22, (char)23, (char)24, (char)25, (char)26, (char)27, (char)28, (char)29, (char)30, + (char)31 + }; + + // [MS - FSA] 2.1.4.4 Algorithm for Determining if a FileName Is in an Expression + // https://msdn.microsoft.com/en-us/library/ff469270.aspx + private static readonly char[] s_wildcardChars = + { + '\"', '<', '>', '*', '?' + }; + + /// + /// Returns true if the given character is a valid drive letter + /// + internal static bool IsValidDriveChar(char value) + { + return ((value >= 'A' && value <= 'Z') || (value >= 'a' && value <= 'z')); + } + + /// + /// Returns true if the path is too long + /// + internal static bool IsPathTooLong(string fullPath) + { + // We'll never know precisely what will fail as paths get changed internally in Windows and + // may grow to exceed MaxLongPath. + return fullPath.Length >= MaxLongPath; + } + + /// + /// Returns true if the directory is too long + /// + internal static bool IsDirectoryTooLong(string fullPath) + { + return IsPathTooLong(fullPath); + } + + /// + /// Adds the extended path prefix (\\?\) if not already a device path, IF the path is not relative, + /// AND the path is more than 259 characters. (> MAX_PATH + null) + /// + internal static string EnsureExtendedPrefixOverMaxPath(string path) + { + if (path != null && path.Length >= MaxShortPath) + { + return EnsureExtendedPrefix(path); + } + else + { + return path; + } + } + + /// + /// Adds the extended path prefix (\\?\) if not relative or already a device path. + /// + internal static string EnsureExtendedPrefix(string path) + { + // Putting the extended prefix on the path changes the processing of the path. It won't get normalized, which + // means adding to relative paths will prevent them from getting the appropriate current directory inserted. + + // If it already has some variant of a device path (\??\, \\?\, \\.\, //./, etc.) we don't need to change it + // as it is either correct or we will be changing the behavior. When/if Windows supports long paths implicitly + // in the future we wouldn't want normalization to come back and break existing code. + + // In any case, all internal usages should be hitting normalize path (Path.GetFullPath) before they hit this + // shimming method. (Or making a change that doesn't impact normalization, such as adding a filename to a + // normalized base path.) + if (IsPartiallyQualified(path) || IsDevice(path)) + return path; + + // Given \\server\share in longpath becomes \\?\UNC\server\share + if (path.StartsWith(UncPathPrefix, StringComparison.OrdinalIgnoreCase)) + return path.Insert(2, UncExtendedPrefixToInsert); + + return ExtendedPathPrefix + path; + } + + /// + /// Returns true if the path uses any of the DOS device path syntaxes. ("\\.\", "\\?\", or "\??\") + /// + internal static bool IsDevice(string path) + { + // If the path begins with any two separators is will be recognized and normalized and prepped with + // "\??\" for internal usage correctly. "\??\" is recognized and handled, "/??/" is not. + return IsExtended(path) + || + ( + path.Length >= DevicePrefixLength + && IsDirectorySeparator(path[0]) + && IsDirectorySeparator(path[1]) + && (path[2] == '.' || path[2] == '?') + && IsDirectorySeparator(path[3]) + ); + } + + /// + /// Returns true if the path uses the canonical form of extended syntax ("\\?\" or "\??\"). If the + /// path matches exactly (cannot use alternate directory separators) Windows will skip normalization + /// and path length checks. + /// + internal static bool IsExtended(string path) + { + // While paths like "//?/C:/" will work, they're treated the same as "\\.\" paths. + // Skipping of normalization will *only* occur if back slashes ('\') are used. + return path.Length >= DevicePrefixLength + && path[0] == '\\' + && (path[1] == '\\' || path[1] == '?') + && path[2] == '?' + && path[3] == '\\'; + } + + /// + /// Returns a value indicating if the given path contains invalid characters (", <, >, | + /// NUL, or any ASCII char whose integer representation is in the range of 1 through 31). + /// Does not check for wild card characters ? and *. + /// + internal static bool HasIllegalCharacters(string path) + { + // This is equivalent to IndexOfAny(InvalidPathChars) >= 0, + // except faster since IndexOfAny grows slower as the input + // array grows larger. + // Since we know that some of the characters we're looking + // for are contiguous in the alphabet-- the path cannot contain + // characters 0-31-- we can optimize this for our specific use + // case and use simple comparison operations. + + for (int i = 0; i < path.Length; i++) + { + char c = path[i]; + + if (c <= '\u001f' || c == '|') + { + return true; + } + } + + return false; + } + + /// + /// Check for known wildcard characters. '*' and '?' are the most common ones. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal unsafe static bool HasWildCardCharacters(string path) + { + // Question mark is part of dos device syntax so we have to skip if we are + int startIndex = IsDevice(path) ? ExtendedPathPrefix.Length : 0; + + return path.IndexOfAny(s_wildcardChars, startIndex) >= 0; + } + + /// + /// Gets the length of the root of the path (drive, share, etc.). + /// + internal unsafe static int GetRootLength(string path) + { + fixed(char* value = path) + { + return (int)GetRootLength(value, (uint)path.Length); + } + } + + private unsafe static uint GetRootLength(char* path, uint pathLength) + { + uint i = 0; + uint volumeSeparatorLength = 2; // Length to the colon "C:" + uint uncRootLength = 2; // Length to the start of the server name "\\" + + bool extendedSyntax = StartsWithOrdinal(path, pathLength, ExtendedPathPrefix); + bool extendedUncSyntax = StartsWithOrdinal(path, pathLength, UncExtendedPathPrefix); + if (extendedSyntax) + { + // Shift the position we look for the root from to account for the extended prefix + if (extendedUncSyntax) + { + // "\\" -> "\\?\UNC\" + uncRootLength = (uint)UncExtendedPathPrefix.Length; + } + else + { + // "C:" -> "\\?\C:" + volumeSeparatorLength += (uint)ExtendedPathPrefix.Length; + } + } + + if ((!extendedSyntax || extendedUncSyntax) && pathLength > 0 && IsDirectorySeparator(path[0])) + { + // UNC or simple rooted path (e.g. "\foo", NOT "\\?\C:\foo") + + i = 1; // Drive rooted (\foo) is one character + if (extendedUncSyntax || (pathLength > 1 && IsDirectorySeparator(path[1]))) + { + // UNC (\\?\UNC\ or \\), scan past the next two directory separators at most + // (e.g. to \\?\UNC\Server\Share or \\Server\Share\) + i = uncRootLength; + int n = 2; // Maximum separators to skip + while (i < pathLength && (!IsDirectorySeparator(path[i]) || --n > 0)) i++; + } + } + else if (pathLength >= volumeSeparatorLength && path[volumeSeparatorLength - 1] == Path.VolumeSeparatorChar) + { + // Path is at least longer than where we expect a colon, and has a colon (\\?\A:, A:) + // If the colon is followed by a directory separator, move past it + i = volumeSeparatorLength; + if (pathLength >= volumeSeparatorLength + 1 && IsDirectorySeparator(path[volumeSeparatorLength])) i++; + } + return i; + } + + private unsafe static bool StartsWithOrdinal(char* source, uint sourceLength, string value) + { + if (sourceLength < (uint)value.Length) return false; + for (int i = 0; i < value.Length; i++) + { + if (value[i] != source[i]) return false; + } + return true; + } + + /// + /// Returns true if the path specified is relative to the current drive or working directory. + /// Returns false if the path is fixed to a specific drive or UNC path. This method does no + /// validation of the path (URIs will be returned as relative as a result). + /// + /// + /// Handles paths that use the alternate directory separator. It is a frequent mistake to + /// assume that rooted paths (Path.IsPathRooted) are not relative. This isn't the case. + /// "C:a" is drive relative- meaning that it will be resolved against the current directory + /// for C: (rooted, but relative). "C:\a" is rooted and not relative (the current directory + /// will not be used to modify the path). + /// + internal static bool IsPartiallyQualified(string path) + { + if (path.Length < 2) + { + // It isn't fixed, it must be relative. There is no way to specify a fixed + // path with one character (or less). + return true; + } + + if (IsDirectorySeparator(path[0])) + { + // There is no valid way to specify a relative path with two initial slashes or + // \? as ? isn't valid for drive relative paths and \??\ is equivalent to \\?\ + return !(path[1] == '?' || IsDirectorySeparator(path[1])); + } + + // The only way to specify a fixed path that doesn't begin with two slashes + // is the drive, colon, slash format- i.e. C:\ + return !((path.Length >= 3) + && (path[1] == Path.VolumeSeparatorChar) + && IsDirectorySeparator(path[2]) + // To match old behavior we'll check the drive character for validity as the path is technically + // not qualified if you don't have a valid drive. "=:\" is the "=" file's default data stream. + && IsValidDriveChar(path[0])); + } + + /// + /// Returns the characters to skip at the start of the path if it starts with space(s) and a drive or directory separator. + /// (examples are " C:", " \") + /// This is a legacy behavior of Path.GetFullPath(). + /// + /// + /// Note that this conflicts with IsPathRooted() which doesn't (and never did) such a skip. + /// + internal static int PathStartSkip(string path) + { + int startIndex = 0; + while (startIndex < path.Length && path[startIndex] == ' ') startIndex++; + + if (startIndex > 0 && (startIndex < path.Length && IsDirectorySeparator(path[startIndex])) + || (startIndex + 1 < path.Length && path[startIndex + 1] == ':' && IsValidDriveChar(path[startIndex]))) + { + // Go ahead and skip spaces as we're either " C:" or " \" + return startIndex; + } + + return 0; + } + + /// + /// True if the given character is a directory separator. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool IsDirectorySeparator(char c) + { + return c == Path.DirectorySeparatorChar || c == Path.AltDirectorySeparatorChar; + } + + /// + /// Normalize separators in the given path. Converts forward slashes into back slashes and compresses slash runs, keeping initial 2 if present. + /// Also trims initial whitespace in front of "rooted" paths (see PathStartSkip). + /// + /// This effectively replicates the behavior of the legacy NormalizePath when it was called with fullCheck=false and expandShortpaths=false. + /// The current NormalizePath gets directory separator normalization from Win32's GetFullPathName(), which will resolve relative paths and as + /// such can't be used here (and is overkill for our uses). + /// + /// Like the current NormalizePath this will not try and analyze periods/spaces within directory segments. + /// + /// + /// The only callers that used to use Path.Normalize(fullCheck=false) were Path.GetDirectoryName() and Path.GetPathRoot(). Both usages do + /// not need trimming of trailing whitespace here. + /// + /// GetPathRoot() could technically skip normalizing separators after the second segment- consider as a future optimization. + /// + /// For legacy desktop behavior with ExpandShortPaths: + /// - It has no impact on GetPathRoot() so doesn't need consideration. + /// - It could impact GetDirectoryName(), but only if the path isn't relative (C:\ or \\Server\Share). + /// + /// In the case of GetDirectoryName() the ExpandShortPaths behavior was undocumented and provided inconsistent results if the path was + /// fixed/relative. For example: "C:\PROGRA~1\A.TXT" would return "C:\Program Files" while ".\PROGRA~1\A.TXT" would return ".\PROGRA~1". If you + /// ultimately call GetFullPath() this doesn't matter, but if you don't or have any intermediate string handling could easily be tripped up by + /// this undocumented behavior. + /// + /// We won't match this old behavior because: + /// + /// 1. It was undocumented + /// 2. It was costly (extremely so if it actually contained '~') + /// 3. Doesn't play nice with string logic + /// 4. Isn't a cross-plat friendly concept/behavior + /// + internal static string NormalizeDirectorySeparators(string path) + { + if (string.IsNullOrEmpty(path)) return path; + + char current; + int start = PathStartSkip(path); + + if (start == 0) + { + // Make a pass to see if we need to normalize so we can potentially skip allocating + bool normalized = true; + + for (int i = 0; i < path.Length; i++) + { + current = path[i]; + if (IsDirectorySeparator(current) + && (current != Path.DirectorySeparatorChar + // Check for sequential separators past the first position (we need to keep initial two for UNC/extended) + || (i > 0 && i + 1 < path.Length && IsDirectorySeparator(path[i + 1])))) + { + normalized = false; + break; + } + } + + if (normalized) return path; + } + + StringBuilder builder = new StringBuilder(path.Length); + + if (IsDirectorySeparator(path[start])) + { + start++; + builder.Append(Path.DirectorySeparatorChar); + } + + for (int i = start; i < path.Length; i++) + { + current = path[i]; + + // If we have a separator + if (IsDirectorySeparator(current)) + { + // If the next is a separator, skip adding this + if (i + 1 < path.Length && IsDirectorySeparator(path[i + 1])) + { + continue; + } + + // Ensure it is the primary separator + current = Path.DirectorySeparatorChar; + } + + builder.Append(current); + } + + return builder.ToString(); + } + + /// + /// Returns true if the character is a directory or volume separator. + /// + /// The character to test. + internal static bool IsDirectoryOrVolumeSeparator(char ch) + { + return IsDirectorySeparator(ch) || Path.VolumeSeparatorChar == ch; + } + + /// + /// Validates volume separator only occurs as C: or \\?\C:. This logic is meant to filter out Alternate Data Streams. + /// + /// True if the path has an invalid volume separator. + internal static bool HasInvalidVolumeSeparator(string path) + { + // Toss out paths with colons that aren't a valid drive specifier. + // Cannot start with a colon and can only be of the form "C:" or "\\?\C:". + // (Note that we used to explicitly check "http:" and "file:"- these are caught by this check now.) + + // We don't care about skipping starting space for extended paths. Assume no knowledge of extended paths if we're forcing old path behavior. + int startIndex = IsExtended(path) ? ExtendedPathPrefix.Length : PathStartSkip(path); + + // If we start with a colon + if ((path.Length > startIndex && path[startIndex] == Path.VolumeSeparatorChar) + // Or have an invalid drive letter and colon + || (path.Length >= startIndex + 2 && path[startIndex + 1] == Path.VolumeSeparatorChar && !IsValidDriveChar(path[startIndex])) + // Or have any colons beyond the drive colon + || (path.Length > startIndex + 2 && path.IndexOf(Path.VolumeSeparatorChar, startIndex + 2) != -1)) + { + return true; + } + + return false; + } + } +} diff --git a/src/mscorlib/corefx/System/IO/PathInternal.cs b/src/mscorlib/corefx/System/IO/PathInternal.cs new file mode 100644 index 0000000..ee67680 --- /dev/null +++ b/src/mscorlib/corefx/System/IO/PathInternal.cs @@ -0,0 +1,230 @@ +// 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.Diagnostics; +using System.Text; + +namespace System.IO +{ + /// Contains internal path helpers that are shared between many projects. + internal static partial class PathInternal + { + // Trim trailing white spaces, tabs etc but don't be aggressive in removing everything that has UnicodeCategory of trailing space. + // string.WhitespaceChars will trim more aggressively than what the underlying FS does (for ex, NTFS, FAT). + // + // (This is for compatibility with old behavior.) + internal static readonly char[] s_trimEndChars = + { + (char)0x9, // Horizontal tab + (char)0xA, // Line feed + (char)0xB, // Vertical tab + (char)0xC, // Form feed + (char)0xD, // Carriage return + (char)0x20, // Space + (char)0x85, // Next line + (char)0xA0 // Non breaking space + }; + + /// + /// Checks for invalid path characters in the given path. + /// + /// Thrown if the path is null. + /// Thrown if the path has invalid characters. + /// The path to check for invalid characters. + internal static void CheckInvalidPathChars(string path) + { + if (path == null) + throw new ArgumentNullException(nameof(path)); + + if (HasIllegalCharacters(path)) + throw new ArgumentException(SR.Argument_InvalidPathChars, nameof(path)); + } + + + /// + /// Returns true if the given StringBuilder starts with the given value. + /// + /// The string to compare against the start of the StringBuilder. + internal static bool StartsWithOrdinal(this StringBuilder builder, string value) + { + if (value == null || builder.Length < value.Length) + return false; + + for (int i = 0; i < value.Length; i++) + { + if (builder[i] != value[i]) return false; + } + return true; + } + + /// + /// Returns true if the given string starts with the given value. + /// + /// The string to compare against the start of the source string. + internal static bool StartsWithOrdinal(this string source, string value) + { + if (value == null || source.Length < value.Length) + return false; + + return source.StartsWith(value, StringComparison.Ordinal); + } + + /// + /// Trims the specified characters from the end of the StringBuilder. + /// + internal static StringBuilder TrimEnd(this StringBuilder builder, params char[] trimChars) + { + if (trimChars == null || trimChars.Length == 0) + return builder; + + int end = builder.Length - 1; + + for (; end >= 0; end--) + { + int i = 0; + char ch = builder[end]; + for (; i < trimChars.Length; i++) + { + if (trimChars[i] == ch) break; + } + if (i == trimChars.Length) + { + // Not a trim char + break; + } + } + + builder.Length = end + 1; + return builder; + } + + /// + /// Returns the start index of the filename + /// in the given path, or 0 if no directory + /// or volume separator is found. + /// + /// The path in which to find the index of the filename. + /// + /// This method returns path.Length for + /// inputs like "/usr/foo/" on Unix. As such, + /// it is not safe for being used to index + /// the string without additional verification. + /// + internal static int FindFileNameIndex(string path) + { + Debug.Assert(path != null); + CheckInvalidPathChars(path); + + for (int i = path.Length - 1; i >= 0; i--) + { + char ch = path[i]; + if (IsDirectoryOrVolumeSeparator(ch)) + return i + 1; + } + + return 0; // the whole path is the filename + } + + /// + /// Returns true if the path ends in a directory separator. + /// + internal static bool EndsInDirectorySeparator(string path) => + !string.IsNullOrEmpty(path) && IsDirectorySeparator(path[path.Length - 1]); + + /// + /// Get the common path length from the start of the string. + /// + internal static int GetCommonPathLength(string first, string second, bool ignoreCase) + { + int commonChars = EqualStartingCharacterCount(first, second, ignoreCase: ignoreCase); + + // If nothing matches + if (commonChars == 0) + return commonChars; + + // Or we're a full string and equal length or match to a separator + if (commonChars == first.Length + && (commonChars == second.Length || IsDirectorySeparator(second[commonChars]))) + return commonChars; + + if (commonChars == second.Length && IsDirectorySeparator(first[commonChars])) + return commonChars; + + // It's possible we matched somewhere in the middle of a segment e.g. C:\Foodie and C:\Foobar. + while (commonChars > 0 && !IsDirectorySeparator(first[commonChars - 1])) + commonChars--; + + return commonChars; + } + + /// + /// Gets the count of common characters from the left optionally ignoring case + /// + unsafe internal static int EqualStartingCharacterCount(string first, string second, bool ignoreCase) + { + if (string.IsNullOrEmpty(first) || string.IsNullOrEmpty(second)) return 0; + + int commonChars = 0; + + fixed (char* f = first) + fixed (char* s = second) + { + char* l = f; + char* r = s; + char* leftEnd = l + first.Length; + char* rightEnd = r + second.Length; + + while (l != leftEnd && r != rightEnd + && (*l == *r || (ignoreCase && char.ToUpperInvariant((*l)) == char.ToUpperInvariant((*r))))) + { + commonChars++; + l++; + r++; + } + } + + return commonChars; + } + + /// + /// Returns true if the two paths have the same root + /// + internal static bool AreRootsEqual(string first, string second, StringComparison comparisonType) + { + int firstRootLength = GetRootLength(first); + int secondRootLength = GetRootLength(second); + + return firstRootLength == secondRootLength + && string.Compare( + strA: first, + indexA: 0, + strB: second, + indexB: 0, + length: firstRootLength, + comparisonType: comparisonType) == 0; + } + + /// + /// Returns false for ".." unless it is specified as a part of a valid File/Directory name. + /// (Used to avoid moving up directories.) + /// + /// Valid: a..b abc..d + /// Invalid: ..ab ab.. .. abc..d\abc.. + /// + internal static void CheckSearchPattern(string searchPattern) + { + int index; + while ((index = searchPattern.IndexOf("..", StringComparison.Ordinal)) != -1) + { + // Terminal ".." . Files names cannot end in ".." + if (index + 2 == searchPattern.Length + || IsDirectorySeparator(searchPattern[index + 2])) + throw new ArgumentException(SR.Arg_InvalidSearchPattern); + + searchPattern = searchPattern.Substring(index + 2); + } + + } + } +} diff --git a/src/mscorlib/corefx/System/IO/Win32Marshal.cs b/src/mscorlib/corefx/System/IO/Win32Marshal.cs new file mode 100644 index 0000000..b4dfa04 --- /dev/null +++ b/src/mscorlib/corefx/System/IO/Win32Marshal.cs @@ -0,0 +1,134 @@ +// 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.Diagnostics; +using System.Runtime.InteropServices; + +namespace System.IO +{ + /// + /// Provides static methods for converting from Win32 errors codes to exceptions, HRESULTS and error messages. + /// + internal static class Win32Marshal + { + /// + /// Converts, resetting it, the last Win32 error into a corresponding object. + /// + internal static Exception GetExceptionForLastWin32Error() + { + int errorCode = Marshal.GetLastWin32Error(); + return GetExceptionForWin32Error(errorCode, string.Empty); + } + + /// + /// Converts, resetting it, the last Win32 error into a corresponding object, optionally + /// including the specified path in the error message. + /// + internal static Exception GetExceptionForLastWin32Error(string path) + { + int errorCode = Marshal.GetLastWin32Error(); + return GetExceptionForWin32Error(errorCode, path); + } + + /// + /// Converts the specified Win32 error into a corresponding object. + /// + internal static Exception GetExceptionForWin32Error(int errorCode) + { + return GetExceptionForWin32Error(errorCode, string.Empty); + } + + /// + /// Converts the specified Win32 error into a corresponding object, optionally + /// including the specified path in the error message. + /// + internal static Exception GetExceptionForWin32Error(int errorCode, string path) + { + switch (errorCode) + { + case Interop.mincore.Errors.ERROR_FILE_NOT_FOUND: + if (path.Length == 0) + return new FileNotFoundException(SR.IO_FileNotFound); + else + return new FileNotFoundException(SR.Format(SR.IO_FileNotFound_FileName, path), path); + + case Interop.mincore.Errors.ERROR_PATH_NOT_FOUND: + if (path.Length == 0) + return new DirectoryNotFoundException(SR.IO_PathNotFound_NoPathName); + else + return new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, path)); + + case Interop.mincore.Errors.ERROR_ACCESS_DENIED: + if (path.Length == 0) + return new UnauthorizedAccessException(SR.UnauthorizedAccess_IODenied_NoPathName); + else + return new UnauthorizedAccessException(SR.Format(SR.UnauthorizedAccess_IODenied_Path, path)); + + case Interop.mincore.Errors.ERROR_ALREADY_EXISTS: + if (path.Length == 0) + goto default; + + return new IOException(SR.Format(SR.IO_AlreadyExists_Name, path), MakeHRFromErrorCode(errorCode)); + + case Interop.mincore.Errors.ERROR_FILENAME_EXCED_RANGE: + return new PathTooLongException(SR.IO_PathTooLong); + + case Interop.mincore.Errors.ERROR_INVALID_PARAMETER: + return new IOException(GetMessage(errorCode), MakeHRFromErrorCode(errorCode)); + + case Interop.mincore.Errors.ERROR_SHARING_VIOLATION: + if (path.Length == 0) + return new IOException(SR.IO_SharingViolation_NoFileName, MakeHRFromErrorCode(errorCode)); + else + return new IOException(SR.Format(SR.IO_SharingViolation_File, path), MakeHRFromErrorCode(errorCode)); + + case Interop.mincore.Errors.ERROR_FILE_EXISTS: + if (path.Length == 0) + goto default; + + return new IOException(SR.Format(SR.IO_FileExists_Name, path), MakeHRFromErrorCode(errorCode)); + + case Interop.mincore.Errors.ERROR_OPERATION_ABORTED: + return new OperationCanceledException(); + + default: + return new IOException(GetMessage(errorCode), MakeHRFromErrorCode(errorCode)); + } + } + + /// + /// Returns a HRESULT for the specified Win32 error code. + /// + internal static int MakeHRFromErrorCode(int errorCode) + { + Debug.Assert((0xFFFF0000 & errorCode) == 0, "This is an HRESULT, not an error code!"); + + return unchecked(((int)0x80070000) | errorCode); + } + + /// + /// Returns a Win32 error code for the specified HRESULT if it came from FACILITY_WIN32 + /// If not, returns the HRESULT unchanged + /// + internal static int TryMakeWin32ErrorCodeFromHR(int hr) + { + if ((0xFFFF0000 & hr) == 0x80070000) + { + // Win32 error, Win32Marshal.GetExceptionForWin32Error expects the Win32 format + hr &= 0x0000FFFF; + } + + return hr; + } + + /// + /// Returns a string message for the specified Win32 error code. + /// + internal static string GetMessage(int errorCode) + { + return Interop.mincore.GetMessage(errorCode); + } + } +} diff --git a/src/mscorlib/corefx/System/Runtime/InteropServices/NativeBuffer.cs b/src/mscorlib/corefx/System/Runtime/InteropServices/NativeBuffer.cs new file mode 100644 index 0000000..875009a --- /dev/null +++ b/src/mscorlib/corefx/System/Runtime/InteropServices/NativeBuffer.cs @@ -0,0 +1,157 @@ +// 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.Runtime.CompilerServices; + +namespace System.Runtime.InteropServices +{ + /// + /// Wrapper for access to the native heap. Dispose to free the memory. Try to use with using statements. + /// Does not allocate zero size buffers, and will free the existing native buffer if capacity is dropped to zero. + /// + /// NativeBuffer utilizes a cache of heap buffers. + /// + /// + /// Suggested use through P/Invoke: define DllImport arguments that take a byte buffer as SafeHandle. + /// + /// Using SafeHandle will ensure that the buffer will not get collected during a P/Invoke. + /// (Notably AddRef and ReleaseRef will be called by the interop layer.) + /// + /// This class is not threadsafe, changing the capacity or disposing on multiple threads risks duplicate heap + /// handles or worse. + /// + internal class NativeBuffer : IDisposable + { + private readonly static SafeHeapHandleCache s_handleCache = new SafeHeapHandleCache(); + private readonly static SafeHandle s_emptyHandle = new EmptySafeHandle(); + private SafeHeapHandle _handle; + private ulong _capacity; + + /// + /// Create a buffer with at least the specified initial capacity in bytes. + /// + public NativeBuffer(ulong initialMinCapacity = 0) + { + EnsureByteCapacity(initialMinCapacity); + } + + protected unsafe void* VoidPointer + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return _handle == null ? null : _handle.DangerousGetHandle().ToPointer(); + } + } + + protected unsafe byte* BytePointer + { + get + { + return (byte*)VoidPointer; + } + } + + /// + /// Get the handle for the buffer. + /// + public SafeHandle GetHandle() + { + // Marshalling code will throw on null for SafeHandle + return _handle ?? s_emptyHandle; + } + + /// + /// The capacity of the buffer in bytes. + /// + public ulong ByteCapacity + { + get { return _capacity; } + } + + /// + /// Ensure capacity in bytes is at least the given minimum. + /// + /// Thrown if unable to allocate memory when setting. + /// Thrown if attempting to set to a value that is larger than the maximum addressable memory. + public void EnsureByteCapacity(ulong minCapacity) + { + if (_capacity < minCapacity) + { + Resize(minCapacity); + _capacity = minCapacity; + } + } + + public unsafe byte this[ulong index] + { + get + { + if (index >= _capacity) throw new ArgumentOutOfRangeException(); + return BytePointer[index]; + } + set + { + if (index >= _capacity) throw new ArgumentOutOfRangeException(); + BytePointer[index] = value; + } + } + + private unsafe void Resize(ulong byteLength) + { + if (byteLength == 0) + { + ReleaseHandle(); + return; + } + + if (_handle == null) + { + _handle = s_handleCache.Acquire(byteLength); + } + else + { + _handle.Resize(byteLength); + } + } + + private void ReleaseHandle() + { + if (_handle != null) + { + s_handleCache.Release(_handle); + _capacity = 0; + _handle = null; + } + } + + /// + /// Release the backing buffer + /// + public virtual void Free() + { + ReleaseHandle(); + } + + public void Dispose() + { + Free(); + } + + private sealed class EmptySafeHandle : SafeHandle + { + public EmptySafeHandle() : base(IntPtr.Zero, true) { } + + public override bool IsInvalid + { + get { return true; } + } + + protected override bool ReleaseHandle() + { + return true; + } + } + } +} diff --git a/src/mscorlib/corefx/System/Runtime/InteropServices/SafeHeapHandle.cs b/src/mscorlib/corefx/System/Runtime/InteropServices/SafeHeapHandle.cs new file mode 100644 index 0000000..92b3d98 --- /dev/null +++ b/src/mscorlib/corefx/System/Runtime/InteropServices/SafeHeapHandle.cs @@ -0,0 +1,109 @@ +// 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. + +namespace System.Runtime.InteropServices +{ + /// + /// Handle for heap memory that allows tracking of capacity and reallocating. + /// + internal sealed class SafeHeapHandle : SafeBuffer + { + /// + /// Allocate a buffer of the given size if requested. + /// + /// Required size in bytes. Must be less than UInt32.MaxValue for 32 bit or UInt64.MaxValue for 64 bit. + /// Thrown if the requested memory size cannot be allocated. + /// Thrown if size is greater than the maximum memory size. + public SafeHeapHandle(ulong byteLength) : base(ownsHandle: true) + { + Resize(byteLength); + } + + public override bool IsInvalid + { + get { return handle == IntPtr.Zero; } + } + + /// + /// Resize the buffer to the given size if requested. + /// + /// Required size in bytes. Must be less than UInt32.MaxValue for 32 bit or UInt64.MaxValue for 64 bit. + /// Thrown if the requested memory size cannot be allocated. + /// Thrown if size is greater than the maximum memory size. + public void Resize(ulong byteLength) + { + if (IsClosed) throw new ObjectDisposedException(nameof(SafeHeapHandle)); + + ulong originalLength = 0; + if (handle == IntPtr.Zero) + { + handle = Marshal.AllocHGlobal((IntPtr)byteLength); + } + else + { + originalLength = ByteLength; + + // This may or may not be the same handle, may realloc in place. If the + // handle changes Windows will deal with the old handle, trying to free it will + // cause an error. + handle = Marshal.ReAllocHGlobal(pv: handle, cb: (IntPtr)byteLength); + } + + if (handle == IntPtr.Zero) + { + // Only real plausible answer + throw new OutOfMemoryException(); + } + + if (byteLength > originalLength) + { + // Add pressure + ulong addedBytes = byteLength - originalLength; + if (addedBytes > long.MaxValue) + { + GC.AddMemoryPressure(long.MaxValue); + GC.AddMemoryPressure((long)(addedBytes - long.MaxValue)); + } + else + { + GC.AddMemoryPressure((long)addedBytes); + } + } + else + { + // Shrank or did nothing, release pressure if needed + RemoveMemoryPressure(originalLength - byteLength); + } + + Initialize(byteLength); + } + + private void RemoveMemoryPressure(ulong removedBytes) + { + if (removedBytes == 0) return; + + if (removedBytes > long.MaxValue) + { + GC.RemoveMemoryPressure(long.MaxValue); + GC.RemoveMemoryPressure((long)(removedBytes - long.MaxValue)); + } + else + { + GC.RemoveMemoryPressure((long)removedBytes); + } + } + + protected override bool ReleaseHandle() + { + if (handle != IntPtr.Zero) + { + RemoveMemoryPressure(ByteLength); + Marshal.FreeHGlobal(handle); + } + + handle = IntPtr.Zero; + return true; + } + } +} diff --git a/src/mscorlib/corefx/System/Runtime/InteropServices/SafeHeapHandleCache.cs b/src/mscorlib/corefx/System/Runtime/InteropServices/SafeHeapHandleCache.cs new file mode 100644 index 0000000..725076e --- /dev/null +++ b/src/mscorlib/corefx/System/Runtime/InteropServices/SafeHeapHandleCache.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. +// See the LICENSE file in the project root for more information. + +using System.Threading; + +namespace System.Runtime.InteropServices +{ + /// + /// Allows limited thread safe reuse of heap buffers to limit memory pressure. + /// + /// This cache does not ensure that multiple copies of handles are not released back into the cache. + /// + internal sealed class SafeHeapHandleCache : IDisposable + { + private readonly ulong _minSize; + private readonly ulong _maxSize; + + // internal for testing + internal readonly SafeHeapHandle[] _handleCache; + + /// Smallest buffer size to allocate in bytes. + /// The largest buffer size to cache in bytes. + /// The maximum number of handles to cache. + public SafeHeapHandleCache(ulong minSize = 64, ulong maxSize = 1024 * 2, int maxHandles = 0) + { + _minSize = minSize; + _maxSize = maxSize; + _handleCache = new SafeHeapHandle[maxHandles > 0 ? maxHandles : Environment.ProcessorCount * 4]; + } + + /// + /// Get a HeapHandle + /// + public SafeHeapHandle Acquire(ulong minSize = 0) + { + if (minSize < _minSize) minSize = _minSize; + + SafeHeapHandle handle = null; + + for (int i = 0; i < _handleCache.Length; i++) + { + handle = Interlocked.Exchange(ref _handleCache[i], null); + if (handle != null) break; + } + + if (handle != null) + { + // One possible future consideration is to attempt cycling through to + // find one that might already have sufficient capacity + if (handle.ByteLength < minSize) + handle.Resize(minSize); + } + else + { + handle = new SafeHeapHandle(minSize); + } + + return handle; + } + + /// + /// Give a HeapHandle back for potential reuse + /// + public void Release(SafeHeapHandle handle) + { + if (handle.ByteLength <= _maxSize) + { + for (int i = 0; i < _handleCache.Length; i++) + { + // Push the handles down, walking the last one off the end to keep + // the top of the "stack" fresh + handle = Interlocked.Exchange(ref _handleCache[i], handle); + if (handle == null) return; + } + } + + handle.Dispose(); + } + + public void Dispose() + { + Dispose(disposing: true); + } + + private void Dispose(bool disposing) + { + if (disposing && _handleCache != null) + { + foreach (SafeHeapHandle handle in _handleCache) + { + if (handle != null) handle.Dispose(); + } + } + } + } +} diff --git a/src/mscorlib/corefx/System/Runtime/InteropServices/StringBuffer.cs b/src/mscorlib/corefx/System/Runtime/InteropServices/StringBuffer.cs new file mode 100644 index 0000000..29cef08 --- /dev/null +++ b/src/mscorlib/corefx/System/Runtime/InteropServices/StringBuffer.cs @@ -0,0 +1,354 @@ +// 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. + +namespace System.Runtime.InteropServices +{ + /// + /// Native buffer that deals in char size increments. Dispose to free memory. Allows buffers larger + /// than a maximum size string to enable working with very large string arrays. Always makes ordinal + /// comparisons. + /// + /// A more performant replacement for StringBuilder when performing native interop. + /// + /// + /// Suggested use through P/Invoke: define DllImport arguments that take a character buffer as SafeHandle and pass StringBuffer.GetHandle(). + /// + internal class StringBuffer : NativeBuffer + { + private uint _length; + + /// + /// Instantiate the buffer with capacity for at least the specified number of characters. Capacity + /// includes the trailing null character. + /// + public StringBuffer(uint initialCapacity = 0) + : base(initialCapacity * (ulong)sizeof(char)) + { + } + + /// + /// Get/set the character at the given index. + /// + /// Thrown if attempting to index outside of the buffer length. + public unsafe char this[uint index] + { + get + { + if (index >= _length) throw new ArgumentOutOfRangeException(nameof(index)); + return CharPointer[index]; + } + set + { + if (index >= _length) throw new ArgumentOutOfRangeException(nameof(index)); + CharPointer[index] = value; + } + } + + /// + /// Character capacity of the buffer. Includes the count for the trailing null character. + /// + public uint CharCapacity + { + get + { + ulong byteCapacity = ByteCapacity; + ulong charCapacity = byteCapacity == 0 ? 0 : byteCapacity / sizeof(char); + return charCapacity > uint.MaxValue ? uint.MaxValue : (uint)charCapacity; + } + } + + /// + /// Ensure capacity in characters is at least the given minimum. + /// + /// Thrown if unable to allocate memory when setting. + public void EnsureCharCapacity(uint minCapacity) + { + EnsureByteCapacity(minCapacity * (ulong)sizeof(char)); + } + + /// + /// The logical length of the buffer in characters. (Does not include the final null.) Will automatically attempt to increase capacity. + /// This is where the usable data ends. + /// + /// Thrown if unable to allocate memory when setting. + /// Thrown if the set size in bytes is uint.MaxValue (as space is implicitly reserved for the trailing null). + public unsafe uint Length + { + get { return _length; } + set + { + if (value == uint.MaxValue) throw new ArgumentOutOfRangeException(nameof(Length)); + + // Null terminate + EnsureCharCapacity(value + 1); + CharPointer[value] = '\0'; + + _length = value; + } + } + + /// + /// For use when the native api null terminates but doesn't return a length. + /// If no null is found, the length will not be changed. + /// + public unsafe void SetLengthToFirstNull() + { + char* buffer = CharPointer; + uint capacity = CharCapacity; + for (uint i = 0; i < capacity; i++) + { + if (buffer[i] == '\0') + { + _length = i; + break; + } + } + } + + internal unsafe char* CharPointer + { + get + { + return (char*)VoidPointer; + } + } + + /// + /// True if the buffer contains the given character. + /// + public unsafe bool Contains(char value) + { + char* start = CharPointer; + uint length = _length; + + for (uint i = 0; i < length; i++) + { + if (*start++ == value) return true; + } + + return false; + } + + /// + /// Returns true if the buffer starts with the given string. + /// + public bool StartsWith(string value) + { + if (value == null) throw new ArgumentNullException(nameof(value)); + if (_length < (uint)value.Length) return false; + return SubstringEquals(value, startIndex: 0, count: value.Length); + } + + /// + /// Returns true if the specified StringBuffer substring equals the given value. + /// + /// The value to compare against the specified substring. + /// Start index of the sub string. + /// Length of the substring, or -1 to check all remaining. + /// + /// Thrown if or are outside the range + /// of the buffer's length. + /// + public unsafe bool SubstringEquals(string value, uint startIndex = 0, int count = -1) + { + if (value == null) return false; + if (count < -1) throw new ArgumentOutOfRangeException(nameof(count)); + if (startIndex > _length) throw new ArgumentOutOfRangeException(nameof(startIndex)); + + uint realCount = count == -1 ? _length - startIndex : (uint)count; + if (checked(startIndex + realCount) > _length) throw new ArgumentOutOfRangeException(nameof(count)); + + int length = value.Length; + + // Check the substring length against the input length + if (realCount != (uint)length) return false; + + fixed (char* valueStart = value) + { + char* bufferStart = CharPointer + startIndex; + for (int i = 0; i < length; i++) + { + // Note that indexing in this case generates faster code than trying to copy the pointer and increment it + if (*bufferStart++ != valueStart[i]) return false; + } + } + + return true; + } + + /// + /// Append the given string. + /// + /// The string to append. + /// The index in the input string to start appending from. + /// The count of characters to copy from the input string, or -1 for all remaining. + /// Thrown if is null. + /// + /// Thrown if or are outside the range + /// of characters. + /// + public void Append(string value, int startIndex = 0, int count = -1) + { + CopyFrom( + bufferIndex: _length, + source: value, + sourceIndex: startIndex, + count: count); + } + + /// + /// Append the given buffer. + /// + /// The buffer to append. + /// The index in the input buffer to start appending from. + /// The count of characters to copy from the buffer string. + /// Thrown if is null. + /// + /// Thrown if or are outside the range + /// of characters. + /// + public void Append(StringBuffer value, uint startIndex = 0) + { + if (value == null) throw new ArgumentNullException(nameof(value)); + if (value.Length == 0) return; + + value.CopyTo( + bufferIndex: startIndex, + destination: this, + destinationIndex: _length, + count: value.Length); + } + + /// + /// Append the given buffer. + /// + /// The buffer to append. + /// The index in the input buffer to start appending from. + /// The count of characters to copy from the buffer string. + /// Thrown if is null. + /// + /// Thrown if or are outside the range + /// of characters. + /// + public void Append(StringBuffer value, uint startIndex, uint count) + { + if (value == null) throw new ArgumentNullException(nameof(value)); + if (count == 0) return; + + value.CopyTo( + bufferIndex: startIndex, + destination: this, + destinationIndex: _length, + count: count); + } + + /// + /// Copy contents to the specified buffer. Destination index must be within current destination length. + /// Will grow the destination buffer if needed. + /// + /// + /// Thrown if or or are outside the range + /// of characters. + /// + /// Thrown if is null. + public unsafe void CopyTo(uint bufferIndex, StringBuffer destination, uint destinationIndex, uint count) + { + if (destination == null) throw new ArgumentNullException(nameof(destination)); + if (destinationIndex > destination._length) throw new ArgumentOutOfRangeException(nameof(destinationIndex)); + if (bufferIndex >= _length) throw new ArgumentOutOfRangeException(nameof(bufferIndex)); + if (_length < checked(bufferIndex + count)) throw new ArgumentOutOfRangeException(nameof(count)); + + if (count == 0) return; + uint lastIndex = checked(destinationIndex + count); + if (destination._length < lastIndex) destination.Length = lastIndex; + + Buffer.MemoryCopy( + source: CharPointer + bufferIndex, + destination: destination.CharPointer + destinationIndex, + destinationSizeInBytes: checked((long)(destination.ByteCapacity - (destinationIndex * sizeof(char)))), + sourceBytesToCopy: checked((long)count * sizeof(char))); + } + + /// + /// Copy contents from the specified string into the buffer at the given index. Start index must be within the current length of + /// the buffer, will grow as necessary. + /// + public unsafe void CopyFrom(uint bufferIndex, string source, int sourceIndex = 0, int count = -1) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + if (bufferIndex > _length) throw new ArgumentOutOfRangeException(nameof(bufferIndex)); + if (sourceIndex < 0 || sourceIndex > source.Length) throw new ArgumentOutOfRangeException(nameof(sourceIndex)); + if (count == -1) count = source.Length - sourceIndex; + if (count < 0 || source.Length - count < sourceIndex) throw new ArgumentOutOfRangeException(nameof(count)); + + if (count == 0) return; + uint lastIndex = bufferIndex + (uint)count; + if (_length < lastIndex) Length = lastIndex; + + fixed (char* content = source) + { + Buffer.MemoryCopy( + source: content + sourceIndex, + destination: CharPointer + bufferIndex, + destinationSizeInBytes: checked((long)(ByteCapacity - (bufferIndex * sizeof(char)))), + sourceBytesToCopy: (long)count * sizeof(char)); + } + } + + /// + /// Trim the specified values from the end of the buffer. If nothing is specified, nothing is trimmed. + /// + public unsafe void TrimEnd(char[] values) + { + if (values == null || values.Length == 0 || _length == 0) return; + + char* end = CharPointer + _length - 1; + + while (_length > 0 && Array.IndexOf(values, *end) >= 0) + { + Length = _length - 1; + end--; + } + } + + /// + /// String representation of the entire buffer. If the buffer is larger than the maximum size string (int.MaxValue) this will throw. + /// + /// Thrown if the buffer is too big to fit into a string. + public unsafe override string ToString() + { + if (_length == 0) return string.Empty; + if (_length > int.MaxValue) throw new InvalidOperationException(); + return new string(CharPointer, startIndex: 0, length: (int)_length); + } + + /// + /// Get the given substring in the buffer. + /// + /// Count of characters to take, or remaining characters from if -1. + /// + /// Thrown if or are outside the range of the buffer's length + /// or count is greater than the maximum string size (int.MaxValue). + /// + public unsafe string Substring(uint startIndex, int count = -1) + { + if (startIndex > (_length == 0 ? 0 : _length - 1)) throw new ArgumentOutOfRangeException(nameof(startIndex)); + if (count < -1) throw new ArgumentOutOfRangeException(nameof(count)); + + uint realCount = count == -1 ? _length - startIndex : (uint)count; + if (realCount > int.MaxValue || checked(startIndex + realCount) > _length) throw new ArgumentOutOfRangeException(nameof(count)); + if (realCount == 0) return string.Empty; + + // The buffer could be bigger than will fit into a string, but the substring might fit. As the starting + // index might be bigger than int we need to index ourselves. + return new string(value: CharPointer + startIndex, startIndex: 0, length: (int)realCount); + } + + public override void Free() + { + base.Free(); + _length = 0; + } + } +} diff --git a/src/mscorlib/corefx/System/Security/CryptographicException.cs b/src/mscorlib/corefx/System/Security/CryptographicException.cs new file mode 100644 index 0000000..89cb658 --- /dev/null +++ b/src/mscorlib/corefx/System/Security/CryptographicException.cs @@ -0,0 +1,44 @@ +// 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.Globalization; +using System.Runtime.Serialization; + +namespace System.Security.Cryptography +{ + [Serializable] + public class CryptographicException : SystemException + { + public CryptographicException() + : base(SR.Arg_CryptographyException) + { + } + + public CryptographicException(int hr) + : base(SR.Arg_CryptographyException) + { + HResult = hr; + } + + public CryptographicException(string message) + : base(message) + { + } + + public CryptographicException(string message, Exception inner) + : base(message, inner) + { + } + + public CryptographicException(string format, string insert) + : base(string.Format(CultureInfo.CurrentCulture, format, insert)) + { + } + + protected CryptographicException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/src/mscorlib/corefx/System/Security/SafeBSTRHandle.cs b/src/mscorlib/corefx/System/Security/SafeBSTRHandle.cs new file mode 100644 index 0000000..19d63d4 --- /dev/null +++ b/src/mscorlib/corefx/System/Security/SafeBSTRHandle.cs @@ -0,0 +1,81 @@ +// 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.Diagnostics; +using System.Runtime.InteropServices; + +namespace System.Security +{ + internal sealed class SafeBSTRHandle : SafeBuffer + { + internal SafeBSTRHandle() : base(true) { } + + internal static SafeBSTRHandle Allocate(uint lenInChars) + { + uint lenInBytes = lenInChars * sizeof(char); + SafeBSTRHandle bstr = Interop.OleAut32.SysAllocStringLen(IntPtr.Zero, lenInChars); + if (bstr.IsInvalid) // SysAllocStringLen returns a NULL ptr when there's insufficient memory + { + throw new OutOfMemoryException(); + } + bstr.Initialize(lenInBytes); + return bstr; + } + + override protected bool ReleaseHandle() + { + Interop.NtDll.ZeroMemory(handle, (UIntPtr)(Interop.OleAut32.SysStringLen(handle) * sizeof(char))); + Interop.OleAut32.SysFreeString(handle); + return true; + } + + internal unsafe void ClearBuffer() + { + byte* bufferPtr = null; + try + { + AcquirePointer(ref bufferPtr); + Interop.NtDll.ZeroMemory((IntPtr)bufferPtr, (UIntPtr)(Interop.OleAut32.SysStringLen((IntPtr)bufferPtr) * sizeof(char))); + } + finally + { + if (bufferPtr != null) + { + ReleasePointer(); + } + } + } + + internal unsafe uint Length => Interop.OleAut32.SysStringLen(this); + + internal unsafe static void Copy(SafeBSTRHandle source, SafeBSTRHandle target, uint bytesToCopy) + { + if (bytesToCopy == 0) + { + return; + } + + byte* sourcePtr = null, targetPtr = null; + try + { + source.AcquirePointer(ref sourcePtr); + target.AcquirePointer(ref targetPtr); + + Debug.Assert(source.ByteLength >= bytesToCopy, "Source buffer is too small."); + Buffer.MemoryCopy(sourcePtr, targetPtr, target.ByteLength, bytesToCopy); + } + finally + { + if (targetPtr != null) + { + target.ReleasePointer(); + } + if (sourcePtr != null) + { + source.ReleasePointer(); + } + } + } + } +} diff --git a/src/mscorlib/corefx/System/Security/SecureString.Unix.cs b/src/mscorlib/corefx/System/Security/SecureString.Unix.cs new file mode 100644 index 0000000..0ef38e4 --- /dev/null +++ b/src/mscorlib/corefx/System/Security/SecureString.Unix.cs @@ -0,0 +1,295 @@ +// 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.Diagnostics; +using System.Runtime.InteropServices; +using System.Text; + +namespace System.Security +{ + // SecureString attempts to provide a defense-in-depth solution. + // + // On Windows, this is done with several mechanisms: + // 1. keeping the data in unmanaged memory so that copies of it aren't implicitly made by the GC moving it around + // 2. zero'ing out that unmanaged memory so that the string is reliably removed from memory when done with it + // 3. encrypting the data while it's not being used (it's unencrypted to manipulate and use it) + // + // On Unix, we do 1 and 2, but we don't do 3 as there's no CryptProtectData equivalent. + + public sealed partial class SecureString + { + private UnmanagedBuffer _buffer; + + internal SecureString(SecureString str) + { + // Allocate enough space to store the provided string + EnsureCapacity(str._decryptedLength); + _decryptedLength = str._decryptedLength; + + // Copy the string into the newly allocated space + if (_decryptedLength > 0) + { + UnmanagedBuffer.Copy(str._buffer, _buffer, (ulong)(str._decryptedLength * sizeof(char))); + } + } + + private unsafe void InitializeSecureString(char* value, int length) + { + // Allocate enough space to store the provided string + EnsureCapacity(length); + _decryptedLength = length; + if (length == 0) + { + return; + } + + // Copy the string into the newly allocated space + byte* ptr = null; + try + { + _buffer.AcquirePointer(ref ptr); + Buffer.MemoryCopy(value, ptr, _buffer.ByteLength, (ulong)(length * sizeof(char))); + } + finally + { + if (ptr != null) + { + _buffer.ReleasePointer(); + } + } + } + + private void DisposeCore() + { + if (_buffer != null && !_buffer.IsInvalid) + { + _buffer.Dispose(); + _buffer = null; + } + } + + private void EnsureNotDisposed() + { + if (_buffer == null) + { + throw new ObjectDisposedException(GetType().Name); + } + } + + private void ClearCore() + { + _decryptedLength = 0; + _buffer.Clear(); + } + + private unsafe void AppendCharCore(char c) + { + // Make sure we have enough space for the new character, then write it at the end. + EnsureCapacity(_decryptedLength + 1); + _buffer.Write((ulong)(_decryptedLength * sizeof(char)), c); + _decryptedLength++; + } + + private unsafe void InsertAtCore(int index, char c) + { + // Make sure we have enough space for the new character, then shift all of the characters above it and insert it. + EnsureCapacity(_decryptedLength + 1); + byte* ptr = null; + try + { + _buffer.AcquirePointer(ref ptr); + ptr += index * sizeof(char); + long bytesToShift = (_decryptedLength - index) * sizeof(char); + Buffer.MemoryCopy(ptr, ptr + sizeof(char), bytesToShift, bytesToShift); + *((char*)ptr) = c; + ++_decryptedLength; + } + finally + { + if (ptr != null) + { + _buffer.ReleasePointer(); + } + } + } + + private unsafe void RemoveAtCore(int index) + { + // Shift down all values above the specified index, then null out the empty space at the end. + byte* ptr = null; + try + { + _buffer.AcquirePointer(ref ptr); + ptr += index * sizeof(char); + long bytesToShift = (_decryptedLength - index - 1) * sizeof(char); + Buffer.MemoryCopy(ptr + sizeof(char), ptr, bytesToShift, bytesToShift); + *((char*)(ptr + bytesToShift)) = (char)0; + --_decryptedLength; + } + finally + { + if (ptr != null) + { + _buffer.ReleasePointer(); + } + } + } + + private void SetAtCore(int index, char c) + { + // Overwrite the character at the specified index + _buffer.Write((ulong)(index * sizeof(char)), c); + } + + internal unsafe IntPtr MarshalToStringCore(bool globalAlloc, bool unicode) + { + int length = _decryptedLength; + + byte* bufferPtr = null; + IntPtr stringPtr = IntPtr.Zero, result = IntPtr.Zero; + try + { + _buffer.AcquirePointer(ref bufferPtr); + if (unicode) + { + int resultLength = (length + 1) * sizeof(char); + stringPtr = globalAlloc ? Marshal.AllocHGlobal(resultLength) : Marshal.AllocCoTaskMem(resultLength); + Buffer.MemoryCopy( + source: bufferPtr, + destination: (byte*)stringPtr.ToPointer(), + destinationSizeInBytes: resultLength, + sourceBytesToCopy: length * sizeof(char)); + *(length + (char*)stringPtr) = '\0'; + } + else + { + int resultLength = Encoding.UTF8.GetByteCount((char*)bufferPtr, length) + 1; + stringPtr = globalAlloc ? Marshal.AllocHGlobal(resultLength) : Marshal.AllocCoTaskMem(resultLength); + int encodedLength = Encoding.UTF8.GetBytes((char*)bufferPtr, length, (byte*)stringPtr, resultLength); + Debug.Assert(encodedLength + 1 == resultLength, $"Expected encoded length to match result, got {encodedLength} != {resultLength}"); + *(resultLength - 1 + (byte*)stringPtr) = 0; + } + + result = stringPtr; + } + finally + { + // If there was a failure, such that result isn't initialized, + // release the string if we had one. + if (stringPtr != IntPtr.Zero && result == IntPtr.Zero) + { + UnmanagedBuffer.ZeroMemory((byte*)stringPtr, (ulong)(length * sizeof(char))); + MarshalFree(stringPtr, globalAlloc); + } + + if (bufferPtr != null) + { + _buffer.ReleasePointer(); + } + } + + return result; + } + + // ----------------------------- + // ---- PAL layer ends here ---- + // ----------------------------- + + private void EnsureCapacity(int capacity) + { + // Make sure the requested capacity doesn't exceed SecureString's defined limit + if (capacity > MaxLength) + { + throw new ArgumentOutOfRangeException(nameof(capacity), SR.ArgumentOutOfRange_Capacity); + } + + // If we already have enough space allocated, we're done + if (_buffer != null && (capacity * sizeof(char)) <= (int)_buffer.ByteLength) + { + return; + } + + // We need more space, so allocate a new buffer, copy all our data into it, + // and then swap the new for the old. + UnmanagedBuffer newBuffer = UnmanagedBuffer.Allocate(capacity * sizeof(char)); + if (_buffer != null) + { + UnmanagedBuffer.Copy(_buffer, newBuffer, _buffer.ByteLength); + _buffer.Dispose(); + } + _buffer = newBuffer; + } + + /// SafeBuffer for managing memory meant to be kept confidential. + private sealed class UnmanagedBuffer : SafeBuffer + { + internal UnmanagedBuffer() : base(true) { } + + internal static UnmanagedBuffer Allocate(int bytes) + { + Debug.Assert(bytes >= 0); + UnmanagedBuffer buffer = new UnmanagedBuffer(); + buffer.SetHandle(Marshal.AllocHGlobal(bytes)); + buffer.Initialize((ulong)bytes); + return buffer; + } + + internal unsafe void Clear() + { + byte* ptr = null; + try + { + AcquirePointer(ref ptr); + ZeroMemory(ptr, ByteLength); + } + finally + { + if (ptr != null) + { + ReleasePointer(); + } + } + } + + internal static unsafe void Copy(UnmanagedBuffer source, UnmanagedBuffer destination, ulong bytesLength) + { + if (bytesLength == 0) + { + return; + } + + byte* srcPtr = null, dstPtr = null; + try + { + source.AcquirePointer(ref srcPtr); + destination.AcquirePointer(ref dstPtr); + Buffer.MemoryCopy(srcPtr, dstPtr, destination.ByteLength, bytesLength); + } + finally + { + if (dstPtr != null) + { + destination.ReleasePointer(); + } + if (srcPtr != null) + { + source.ReleasePointer(); + } + } + } + + protected override unsafe bool ReleaseHandle() + { + Marshal.FreeHGlobal(handle); + return true; + } + + internal static unsafe void ZeroMemory(byte* ptr, ulong len) + { + for (ulong i = 0; i < len; i++) *ptr++ = 0; + } + } + + } +} diff --git a/src/mscorlib/corefx/System/Security/SecureString.Windows.cs b/src/mscorlib/corefx/System/Security/SecureString.Windows.cs new file mode 100644 index 0000000..5f56353 --- /dev/null +++ b/src/mscorlib/corefx/System/Security/SecureString.Windows.cs @@ -0,0 +1,310 @@ +// 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.Diagnostics; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using Microsoft.Win32; + +namespace System.Security +{ + public sealed partial class SecureString + { + internal SecureString(SecureString str) + { + Debug.Assert(str != null, "Expected non-null SecureString"); + Debug.Assert(str._buffer != null, "Expected other SecureString's buffer to be non-null"); + Debug.Assert(str._encrypted, "Expected to be used only on encrypted SecureStrings"); + + AllocateBuffer(str._buffer.Length); + SafeBSTRHandle.Copy(str._buffer, _buffer, str._buffer.Length * sizeof(char)); + + _decryptedLength = str._decryptedLength; + _encrypted = str._encrypted; + } + + private unsafe void InitializeSecureString(char* value, int length) + { + Debug.Assert(length >= 0, $"Expected non-negative length, got {length}"); + + AllocateBuffer((uint)length); + _decryptedLength = length; + + byte* bufferPtr = null; + try + { + _buffer.AcquirePointer(ref bufferPtr); + Buffer.MemoryCopy((byte*)value, bufferPtr, (long)_buffer.ByteLength, length * sizeof(char)); + } + finally + { + if (bufferPtr != null) + { + _buffer.ReleasePointer(); + } + } + + ProtectMemory(); + } + + private void AppendCharCore(char c) + { + UnprotectMemory(); + try + { + EnsureCapacity(_decryptedLength + 1); + _buffer.Write((uint)_decryptedLength * sizeof(char), c); + _decryptedLength++; + } + finally + { + ProtectMemory(); + } + } + + private void ClearCore() + { + _decryptedLength = 0; + _buffer.ClearBuffer(); + } + + private void DisposeCore() + { + if (_buffer != null) + { + _buffer.Dispose(); + _buffer = null; + } + } + + private unsafe void InsertAtCore(int index, char c) + { + byte* bufferPtr = null; + UnprotectMemory(); + try + { + EnsureCapacity(_decryptedLength + 1); + + _buffer.AcquirePointer(ref bufferPtr); + char* pBuffer = (char*)bufferPtr; + + for (int i = _decryptedLength; i > index; i--) + { + pBuffer[i] = pBuffer[i - 1]; + } + pBuffer[index] = c; + ++_decryptedLength; + } + finally + { + ProtectMemory(); + if (bufferPtr != null) + { + _buffer.ReleasePointer(); + } + } + } + + private unsafe void RemoveAtCore(int index) + { + byte* bufferPtr = null; + UnprotectMemory(); + try + { + _buffer.AcquirePointer(ref bufferPtr); + char* pBuffer = (char*)bufferPtr; + + for (int i = index; i < _decryptedLength - 1; i++) + { + pBuffer[i] = pBuffer[i + 1]; + } + pBuffer[--_decryptedLength] = (char)0; + } + finally + { + ProtectMemory(); + if (bufferPtr != null) + { + _buffer.ReleasePointer(); + } + } + } + + private void SetAtCore(int index, char c) + { + UnprotectMemory(); + try + { + _buffer.Write((uint)index * sizeof(char), c); + } + finally + { + ProtectMemory(); + } + } + + internal unsafe IntPtr MarshalToBSTR() + { + int length = _decryptedLength; + IntPtr ptr = IntPtr.Zero; + IntPtr result = IntPtr.Zero; + byte* bufferPtr = null; + + UnprotectMemory(); + try + { + _buffer.AcquirePointer(ref bufferPtr); + int resultByteLength = (length + 1) * sizeof(char); + + ptr = Win32Native.SysAllocStringLen(null, length); + if (ptr == IntPtr.Zero) { + throw new OutOfMemoryException(); + } + + Buffer.MemoryCopy(bufferPtr, (byte*)ptr, resultByteLength, length * sizeof(char)); + + result = ptr; + } + finally + { + ProtectMemory(); + + // If we failed for any reason, free the new buffer + if (result == IntPtr.Zero && ptr != IntPtr.Zero) + { + Interop.NtDll.ZeroMemory(ptr, (UIntPtr)(length * sizeof(char))); + Win32Native.SysFreeString(ptr); + } + + if (bufferPtr != null) + { + _buffer.ReleasePointer(); + } + } + return result; + } + + internal unsafe IntPtr MarshalToStringCore(bool globalAlloc, bool unicode) + { + int length = _decryptedLength; + IntPtr ptr = IntPtr.Zero; + IntPtr result = IntPtr.Zero; + byte* bufferPtr = null; + + UnprotectMemory(); + try + { + _buffer.AcquirePointer(ref bufferPtr); + if (unicode) + { + int resultByteLength = (length + 1) * sizeof(char); + ptr = globalAlloc ? Marshal.AllocHGlobal(resultByteLength) : Marshal.AllocCoTaskMem(resultByteLength); + Buffer.MemoryCopy(bufferPtr, (byte*)ptr, resultByteLength, length * sizeof(char)); + *(length + (char*)ptr) = '\0'; + } + else + { + uint defaultChar = '?'; + int resultByteLength = 1 + Interop.mincore.WideCharToMultiByte( + Interop.mincore.CP_ACP, Interop.mincore.WC_NO_BEST_FIT_CHARS, (char*)bufferPtr, length, null, 0, (IntPtr)(&defaultChar), IntPtr.Zero); + ptr = globalAlloc ? Marshal.AllocHGlobal(resultByteLength) : Marshal.AllocCoTaskMem(resultByteLength); + Interop.mincore.WideCharToMultiByte( + Interop.mincore.CP_ACP, Interop.mincore.WC_NO_BEST_FIT_CHARS, (char*)bufferPtr, length, (byte*)ptr, resultByteLength - 1, (IntPtr)(&defaultChar), IntPtr.Zero); + *(resultByteLength - 1 + (byte*)ptr) = 0; + } + result = ptr; + } + finally + { + ProtectMemory(); + + // If we failed for any reason, free the new buffer + if (result == IntPtr.Zero && ptr != IntPtr.Zero) + { + Interop.NtDll.ZeroMemory(ptr, (UIntPtr)(length * sizeof(char))); + MarshalFree(ptr, globalAlloc); + } + + if (bufferPtr != null) + { + _buffer.ReleasePointer(); + } + } + return result; + } + + private void EnsureNotDisposed() + { + if (_buffer == null) + { + throw new ObjectDisposedException(GetType().Name); + } + } + + // ----------------------------- + // ---- PAL layer ends here ---- + // ----------------------------- + + private const int BlockSize = (int)Interop.Crypt32.CRYPTPROTECTMEMORY_BLOCK_SIZE / sizeof(char); + private SafeBSTRHandle _buffer; + private bool _encrypted; + + private void AllocateBuffer(uint size) + { + _buffer = SafeBSTRHandle.Allocate(GetAlignedSize(size)); + } + + private static uint GetAlignedSize(uint size) => + size == 0 || size % BlockSize != 0 ? + BlockSize + ((size / BlockSize) * BlockSize) : + size; + + private void EnsureCapacity(int capacity) + { + if (capacity > MaxLength) + { + throw new ArgumentOutOfRangeException(nameof(capacity), SR.ArgumentOutOfRange_Capacity); + } + + if (((uint)capacity * sizeof(char)) <= _buffer.ByteLength) + { + return; + } + + var oldBuffer = _buffer; + SafeBSTRHandle newBuffer = SafeBSTRHandle.Allocate(GetAlignedSize((uint)capacity)); + SafeBSTRHandle.Copy(oldBuffer, newBuffer, (uint)_decryptedLength * sizeof(char)); + _buffer = newBuffer; + oldBuffer.Dispose(); + } + + private void ProtectMemory() + { + Debug.Assert(!_buffer.IsInvalid, "Invalid buffer!"); + + if (_decryptedLength != 0 && + !_encrypted && + !Interop.Crypt32.CryptProtectMemory(_buffer, _buffer.Length * sizeof(char), Interop.Crypt32.CRYPTPROTECTMEMORY_SAME_PROCESS)) + { + throw new CryptographicException(Marshal.GetLastWin32Error()); + } + + _encrypted = true; + } + + private void UnprotectMemory() + { + Debug.Assert(!_buffer.IsInvalid, "Invalid buffer!"); + + if (_decryptedLength != 0 && + _encrypted && + !Interop.Crypt32.CryptUnprotectMemory(_buffer, _buffer.Length * sizeof(char), Interop.Crypt32.CRYPTPROTECTMEMORY_SAME_PROCESS)) + { + throw new CryptographicException(Marshal.GetLastWin32Error()); + } + + _encrypted = false; + } + } +} diff --git a/src/mscorlib/corefx/System/Security/SecureString.cs b/src/mscorlib/corefx/System/Security/SecureString.cs new file mode 100644 index 0000000..9059f90 --- /dev/null +++ b/src/mscorlib/corefx/System/Security/SecureString.cs @@ -0,0 +1,189 @@ +// 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.Diagnostics; +using System.Runtime.InteropServices; + +namespace System.Security +{ + public sealed partial class SecureString : IDisposable + { + private const int MaxLength = 65536; + private readonly object _methodLock = new object(); + private bool _readOnly; + private int _decryptedLength; + + public unsafe SecureString() + { + InitializeSecureString(null, 0); + } + + [CLSCompliant(false)] + public unsafe SecureString(char* value, int length) + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NeedNonNegNum); + } + if (length > MaxLength) + { + throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_Length); + } + + InitializeSecureString(value, length); + } + + public int Length + { + get + { + lock (_methodLock) + { + EnsureNotDisposed(); + return _decryptedLength; + } + } + } + + public void AppendChar(char c) + { + lock (_methodLock) + { + EnsureNotDisposed(); + EnsureNotReadOnly(); + AppendCharCore(c); + } + } + + // clears the current contents. Only available if writable + public void Clear() + { + lock (_methodLock) + { + EnsureNotDisposed(); + EnsureNotReadOnly(); + ClearCore(); + } + } + + // Do a deep-copy of the SecureString + public SecureString Copy() + { + lock (_methodLock) + { + EnsureNotDisposed(); + return new SecureString(this); + } + } + + public void Dispose() + { + lock (_methodLock) + { + DisposeCore(); + } + } + + public void InsertAt(int index, char c) + { + lock (_methodLock) + { + if (index < 0 || index > _decryptedLength) + { + throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_IndexString); + } + + EnsureNotDisposed(); + EnsureNotReadOnly(); + + InsertAtCore(index, c); + } + } + + public bool IsReadOnly() + { + lock (_methodLock) + { + EnsureNotDisposed(); + return _readOnly; + } + } + + public void MakeReadOnly() + { + lock (_methodLock) + { + EnsureNotDisposed(); + _readOnly = true; + } + } + + public void RemoveAt(int index) + { + lock (_methodLock) + { + EnsureNotDisposed(); + EnsureNotReadOnly(); + + if (index < 0 || index >= _decryptedLength) + { + throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_IndexString); + } + + RemoveAtCore(index); + } + } + + public void SetAt(int index, char c) + { + lock (_methodLock) + { + if (index < 0 || index >= _decryptedLength) + { + throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_IndexString); + } + Debug.Assert(index <= Int32.MaxValue / sizeof(char)); + + EnsureNotDisposed(); + EnsureNotReadOnly(); + + SetAtCore(index, c); + } + } + + private void EnsureNotReadOnly() + { + if (_readOnly) + { + throw new InvalidOperationException(SR.InvalidOperation_ReadOnly); + } + } + + internal unsafe IntPtr MarshalToString(bool globalAlloc, bool unicode) + { + lock (_methodLock) + { + EnsureNotDisposed(); + return MarshalToStringCore(globalAlloc, unicode); + } + } + + private static void MarshalFree(IntPtr ptr, bool globalAlloc) + { + if (globalAlloc) + { + Marshal.FreeHGlobal(ptr); + } + else + { + Marshal.FreeCoTaskMem(ptr); + } + } + } +} diff --git a/src/mscorlib/corefx/System/Threading/ClrThreadPoolBoundHandle.cs b/src/mscorlib/corefx/System/Threading/ClrThreadPoolBoundHandle.cs new file mode 100644 index 0000000..d0cc5af --- /dev/null +++ b/src/mscorlib/corefx/System/Threading/ClrThreadPoolBoundHandle.cs @@ -0,0 +1,319 @@ +// 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.Diagnostics; +using System.Runtime.InteropServices; + +namespace System.Threading +{ + // + // Implementation of ThreadPoolBoundHandle that sits on top of the CLR's ThreadPool and Overlapped infrastructure + // + + /// + /// Represents an I/O handle that is bound to the system thread pool and enables low-level + /// components to receive notifications for asynchronous I/O operations. + /// + public sealed partial class ThreadPoolBoundHandle : IDisposable + { + private readonly SafeHandle _handle; + private bool _isDisposed; + + private ThreadPoolBoundHandle(SafeHandle handle) + { + _handle = handle; + } + + /// + /// Gets the bound operating system handle. + /// + /// + /// A object that holds the bound operating system handle. + /// + public SafeHandle Handle + { + get { return _handle; } + } + + /// + /// Returns a for the specific handle, + /// which is bound to the system thread pool. + /// + /// + /// A object that holds the operating system handle. The + /// handle must have been opened for overlapped I/O on the unmanaged side. + /// + /// + /// for , which + /// is bound to the system thread pool. + /// + /// + /// is . + /// + /// + /// has been disposed. + /// + /// -or- + /// + /// does not refer to a valid I/O handle. + /// + /// -or- + /// + /// refers to a handle that has not been opened + /// for overlapped I/O. + /// + /// -or- + /// + /// refers to a handle that has already been bound. + /// + /// + /// This method should be called once per handle. + /// + /// -or- + /// + /// does not take ownership of , + /// it remains the responsibility of the caller to call . + /// + public static ThreadPoolBoundHandle BindHandle(SafeHandle handle) + { + if (handle == null) + throw new ArgumentNullException(nameof(handle)); + + if (handle.IsClosed || handle.IsInvalid) + throw new ArgumentException(SR.Argument_InvalidHandle, nameof(handle)); + + try + { + // ThreadPool.BindHandle will always return true, otherwise, it throws. See the underlying FCall + // implementation in ThreadPoolNative::CorBindIoCompletionCallback to see the implementation. + bool succeeded = ThreadPool.BindHandle(handle); + Debug.Assert(succeeded); + } + catch (Exception ex) + { // BindHandle throws ApplicationException on full CLR and Exception on CoreCLR. + // We do not let either of these leak and convert them to ArgumentException to + // indicate that the specified handles are invalid. + + if (ex.HResult == System.HResults.E_HANDLE) // Bad handle + throw new ArgumentException(SR.Argument_InvalidHandle, nameof(handle)); + + if (ex.HResult == System.HResults.E_INVALIDARG) // Handle already bound or sync handle + throw new ArgumentException(SR.Argument_AlreadyBoundOrSyncHandle, nameof(handle)); + + throw; + } + + return new ThreadPoolBoundHandle(handle); + } + + /// + /// Returns an unmanaged pointer to a structure, specifying + /// a delegate that is invoked when the asynchronous I/O operation is complete, a user-provided + /// object providing context, and managed objects that serve as buffers. + /// + /// + /// An delegate that represents the callback method + /// invoked when the asynchronous I/O operation completes. + /// + /// + /// A user-provided object that distinguishes this from other + /// instances. Can be . + /// + /// + /// An object or array of objects representing the input or output buffer for the operation. Each + /// object represents a buffer, for example an array of bytes. Can be . + /// + /// + /// An unmanaged pointer to a structure. + /// + /// + /// + /// The unmanaged pointer returned by this method can be passed to the operating system in + /// overlapped I/O operations. The structure is fixed in + /// physical memory until is called. + /// + /// + /// The buffer or buffers specified in must be the same as those passed + /// to the unmanaged operating system function that performs the asynchronous I/O. + /// + /// + /// The buffers specified in are pinned for the duration of + /// the I/O operation. + /// + /// + /// + /// is . + /// + /// + /// This method was called after the was disposed. + /// + [CLSCompliant(false)] + public unsafe NativeOverlapped* AllocateNativeOverlapped(IOCompletionCallback callback, object state, object pinData) + { + if (callback == null) + throw new ArgumentNullException(nameof(callback)); + + EnsureNotDisposed(); + + ThreadPoolBoundHandleOverlapped overlapped = new ThreadPoolBoundHandleOverlapped(callback, state, pinData, preAllocated: null); + overlapped._boundHandle = this; + return overlapped._nativeOverlapped; + } + + /// + /// Returns an unmanaged pointer to a structure, using the callback, + /// state, and buffers associated with the specified object. + /// + /// + /// A object from which to create the NativeOverlapped pointer. + /// + /// + /// An unmanaged pointer to a structure. + /// + /// + /// + /// The unmanaged pointer returned by this method can be passed to the operating system in + /// overlapped I/O operations. The structure is fixed in + /// physical memory until is called. + /// + /// + /// + /// is . + /// + /// + /// is currently in use for another I/O operation. + /// + /// + /// This method was called after the was disposed, or + /// this method was called after was disposed. + /// + /// + [CLSCompliant(false)] + public unsafe NativeOverlapped* AllocateNativeOverlapped(PreAllocatedOverlapped preAllocated) + { + if (preAllocated == null) + throw new ArgumentNullException(nameof(preAllocated)); + + EnsureNotDisposed(); + + preAllocated.AddRef(); + try + { + ThreadPoolBoundHandleOverlapped overlapped = preAllocated._overlapped; + + if (overlapped._boundHandle != null) + throw new ArgumentException(SR.Argument_PreAllocatedAlreadyAllocated, nameof(preAllocated)); + + overlapped._boundHandle = this; + + return overlapped._nativeOverlapped; + } + catch + { + preAllocated.Release(); + throw; + } + } + + /// + /// Frees the unmanaged memory associated with a structure + /// allocated by the method. + /// + /// + /// An unmanaged pointer to the structure to be freed. + /// + /// + /// + /// You must call the method exactly once + /// on every unmanaged pointer allocated using the + /// method. + /// If you do not call the method, you will + /// leak memory. If you call the method more + /// than once on the same unmanaged pointer, memory will be corrupted. + /// + /// + /// + /// is . + /// + /// + /// This method was called after the was disposed. + /// + [CLSCompliant(false)] + public unsafe void FreeNativeOverlapped(NativeOverlapped* overlapped) + { + if (overlapped == null) + throw new ArgumentNullException(nameof(overlapped)); + + // Note: we explicitly allow FreeNativeOverlapped calls after the ThreadPoolBoundHandle has been Disposed. + + ThreadPoolBoundHandleOverlapped wrapper = GetOverlappedWrapper(overlapped, this); + + if (wrapper._boundHandle != this) + throw new ArgumentException(SR.Argument_NativeOverlappedWrongBoundHandle, nameof(overlapped)); + + if (wrapper._preAllocated != null) + wrapper._preAllocated.Release(); + else + Overlapped.Free(overlapped); + } + + /// + /// Returns the user-provided object specified when the instance was + /// allocated using the . + /// + /// + /// An unmanaged pointer to the structure from which to return the + /// asscociated user-provided object. + /// + /// + /// A user-provided object that distinguishes this + /// from other instances, otherwise, if one was + /// not specified when the instance was allocated using . + /// + /// + /// is . + /// + [CLSCompliant(false)] + public unsafe static object GetNativeOverlappedState(NativeOverlapped* overlapped) + { + if (overlapped == null) + throw new ArgumentNullException(nameof(overlapped)); + + ThreadPoolBoundHandleOverlapped wrapper = GetOverlappedWrapper(overlapped, null); + Debug.Assert(wrapper._boundHandle != null); + return wrapper._userState; + } + + private static unsafe ThreadPoolBoundHandleOverlapped GetOverlappedWrapper(NativeOverlapped* overlapped, ThreadPoolBoundHandle expectedBoundHandle) + { + ThreadPoolBoundHandleOverlapped wrapper; + try + { + wrapper = (ThreadPoolBoundHandleOverlapped)Overlapped.Unpack(overlapped); + } + catch (NullReferenceException ex) + { + throw new ArgumentException(SR.Argument_NativeOverlappedAlreadyFree, nameof(overlapped), ex); + } + + return wrapper; + } + + public void Dispose() + { + // .NET Native's version of ThreadPoolBoundHandle that wraps the Win32 ThreadPool holds onto + // native resources so it needs to be disposable. To match the contract, we are also disposable. + // We also implement a disposable state to mimic behavior between this implementation and + // .NET Native's version (code written against us, will also work against .NET Native's version). + _isDisposed = true; + } + + + private void EnsureNotDisposed() + { + if (_isDisposed) + throw new ObjectDisposedException(GetType().ToString()); + } + } +} diff --git a/src/mscorlib/corefx/System/Threading/ClrThreadPoolBoundHandleOverlapped.cs b/src/mscorlib/corefx/System/Threading/ClrThreadPoolBoundHandleOverlapped.cs new file mode 100644 index 0000000..1aea2a2 --- /dev/null +++ b/src/mscorlib/corefx/System/Threading/ClrThreadPoolBoundHandleOverlapped.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. +// See the LICENSE file in the project root for more information. + +namespace System.Threading +{ + /// + /// Overlapped subclass adding data needed by ThreadPoolBoundHandle. + /// + internal sealed class ThreadPoolBoundHandleOverlapped : Overlapped + { + private static readonly unsafe IOCompletionCallback s_completionCallback = CompletionCallback; + + private readonly IOCompletionCallback _userCallback; + internal readonly object _userState; + internal PreAllocatedOverlapped _preAllocated; + internal unsafe NativeOverlapped* _nativeOverlapped; + internal ThreadPoolBoundHandle _boundHandle; + internal bool _completed; + + public unsafe ThreadPoolBoundHandleOverlapped(IOCompletionCallback callback, object state, object pinData, PreAllocatedOverlapped preAllocated) + { + _userCallback = callback; + _userState = state; + _preAllocated = preAllocated; + + _nativeOverlapped = Pack(s_completionCallback, pinData); + _nativeOverlapped->OffsetLow = 0; // CLR reuses NativeOverlapped instances and does not reset these + _nativeOverlapped->OffsetHigh = 0; + } + + private unsafe static void CompletionCallback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped) + { + ThreadPoolBoundHandleOverlapped overlapped = (ThreadPoolBoundHandleOverlapped)Overlapped.Unpack(nativeOverlapped); + + // + // The Win32 thread pool implementation of ThreadPoolBoundHandle does not permit reuse of NativeOverlapped + // pointers without freeing them and allocating new a new one. We need to ensure that code using the CLR + // ThreadPool implementation follows those rules. + // + if (overlapped._completed) + throw new InvalidOperationException(SR.InvalidOperation_NativeOverlappedReused); + + overlapped._completed = true; + + if (overlapped._boundHandle == null) + throw new InvalidOperationException(SR.Argument_NativeOverlappedAlreadyFree); + + overlapped._userCallback(errorCode, numBytes, nativeOverlapped); + } + } +} diff --git a/src/mscorlib/corefx/System/Threading/ClrThreadPoolPreAllocatedOverlapped.cs b/src/mscorlib/corefx/System/Threading/ClrThreadPoolPreAllocatedOverlapped.cs new file mode 100644 index 0000000..a42e0c7 --- /dev/null +++ b/src/mscorlib/corefx/System/Threading/ClrThreadPoolPreAllocatedOverlapped.cs @@ -0,0 +1,105 @@ +// 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. + +namespace System.Threading +{ + /// + /// Represents pre-allocated state for native overlapped I/O operations. + /// + /// + public sealed class PreAllocatedOverlapped : IDisposable, IDeferredDisposable + { + internal readonly ThreadPoolBoundHandleOverlapped _overlapped; + private DeferredDisposableLifetime _lifetime; + + /// + /// Initializes a new instance of the class, specifying + /// a delegate that is invoked when each asynchronous I/O operation is complete, a user-provided + /// object providing context, and managed objects that serve as buffers. + /// + /// + /// An delegate that represents the callback method + /// invoked when each asynchronous I/O operation completes. + /// + /// + /// A user-provided object that distinguishes instance produced from this + /// object from other instances. Can be . + /// + /// + /// An object or array of objects representing the input or output buffer for the operations. Each + /// object represents a buffer, for example an array of bytes. Can be . + /// + /// + /// The new instance can be passed to + /// , to produce + /// a instance that can be passed to the operating system in overlapped + /// I/O operations. A single instance can only be used for + /// a single native I/O operation at a time. However, the state stored in the + /// instance can be reused for subsequent native operations. + /// + /// The buffers specified in are pinned until is called. + /// + /// + /// + /// is . + /// + /// + /// This method was called after the was disposed. + /// + [CLSCompliant(false)] + public unsafe PreAllocatedOverlapped(IOCompletionCallback callback, object state, object pinData) + { + if (callback == null) + throw new ArgumentNullException(nameof(callback)); + + _overlapped = new ThreadPoolBoundHandleOverlapped(callback, state, pinData, this); + } + + internal bool AddRef() + { + return _lifetime.AddRef(this); + } + + internal void Release() + { + _lifetime.Release(this); + } + + /// + /// Frees the resources associated with this instance. + /// + public unsafe void Dispose() + { + _lifetime.Dispose(this); + GC.SuppressFinalize(this); + } + + ~PreAllocatedOverlapped() + { + // + // During shutdown, don't automatically clean up, because this instance may still be + // reachable/usable by other code. + // + if (!Environment.HasShutdownStarted) + Dispose(); + } + + unsafe void IDeferredDisposable.OnFinalRelease(bool disposed) + { + if (_overlapped != null) + { + if (disposed) + { + Overlapped.Free(_overlapped._nativeOverlapped); + } + else + { + _overlapped._boundHandle = null; + _overlapped._completed = false; + *_overlapped._nativeOverlapped = default(NativeOverlapped); + } + } + } + } +} diff --git a/src/mscorlib/corefx/System/Threading/DeferredDisposableLifetime.cs b/src/mscorlib/corefx/System/Threading/DeferredDisposableLifetime.cs new file mode 100644 index 0000000..89380fe --- /dev/null +++ b/src/mscorlib/corefx/System/Threading/DeferredDisposableLifetime.cs @@ -0,0 +1,116 @@ +// 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.Diagnostics; + +namespace System.Threading +{ + /// + /// Provides callbacks to objects whose lifetime is managed by . + /// + internal interface IDeferredDisposable + { + /// + /// Called when the object's refcount reaches zero. + /// + /// + /// Indicates whether the object has been disposed. + /// + /// + /// If the refount reaches zero before the object is disposed, this method will be called with + /// set to false. If the object is then disposed, this method will be + /// called again, with set to true. If the refcount reaches zero + /// after the object has already been disposed, this will be called a single time, with + /// set to true. + /// + void OnFinalRelease(bool disposed); + } + + /// + /// Manages the lifetime of an object which implements IDisposable, but which must defer the actual + /// cleanup of state until all existing uses of the object are complete. + /// + /// The type of object whose lifetime will be managed. + /// + /// This type maintains a reference count, and tracks whether the object has been disposed. When + /// Callbacks are made to when the refcount + /// reaches zero. Objects that need to defer cleanup until they have been disposed *and* they have + /// no more references can do so in when + /// 'disposed' is true. + /// + internal struct DeferredDisposableLifetime where T : class, IDeferredDisposable + { + // + // _count is positive until Dispose is called, after which it's (-1 - refcount). + // + private int _count; + + public bool AddRef(T obj) + { + while (true) + { + int oldCount = Volatile.Read(ref _count); + + // Have we been disposed? + if (oldCount < 0) + throw new ObjectDisposedException(typeof(T).ToString()); + + int newCount = checked(oldCount + 1); + + if (Interlocked.CompareExchange(ref _count, newCount, oldCount) == oldCount) + return true; + } + } + + public void Release(T obj) + { + while (true) + { + int oldCount = Volatile.Read(ref _count); + if (oldCount > 0) + { + // We haven't been disposed. Decrement _count. + int newCount = oldCount - 1; + if (Interlocked.CompareExchange(ref _count, newCount, oldCount) == oldCount) + { + if (newCount == 0) + obj.OnFinalRelease(disposed: false); + return; + } + } + else + { + Debug.Assert(oldCount != 0 && oldCount != -1); + + // We've been disposed. Increment _count. + int newCount = oldCount + 1; + if (Interlocked.CompareExchange(ref _count, newCount, oldCount) == oldCount) + { + if (newCount == -1) + obj.OnFinalRelease(disposed: true); + return; + } + } + } + } + + public void Dispose(T obj) + { + while (true) + { + int oldCount = Volatile.Read(ref _count); + if (oldCount < 0) + return; // already disposed + + int newCount = -1 - oldCount; + if (Interlocked.CompareExchange(ref _count, newCount, oldCount) == oldCount) + { + if (newCount == -1) + obj.OnFinalRelease(disposed: true); + return; + } + } + } + } +} diff --git a/src/mscorlib/facade/TypeForwards.cs b/src/mscorlib/facade/TypeForwards.cs deleted file mode 100644 index ba78711..0000000 --- a/src/mscorlib/facade/TypeForwards.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Runtime.CompilerServices; - -#if WINDOWS_TYPEFORWARDS -[assembly: TypeForwardedTo(typeof(System.Threading.WinRTSynchronizationContextFactoryBase))] -[assembly: TypeForwardedTo(typeof(System.Resources.WindowsRuntimeResourceManagerBase))] -[assembly: TypeForwardedTo(typeof(System.Resources.PRIExceptionInfo))] -[assembly: TypeForwardedTo(typeof(System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeImportAttribute))] -[assembly: TypeForwardedTo(typeof(System.Runtime.InteropServices.WindowsRuntime.IRestrictedErrorInfo))] -[assembly: TypeForwardedTo(typeof(System.StubHelpers.EventArgsMarshaler))] -[assembly: TypeForwardedTo(typeof(System.StubHelpers.InterfaceMarshaler))] -#endif - -[assembly: TypeForwardedTo(typeof(System.Diagnostics.Tracing.FrameworkEventSource))] -[assembly: TypeForwardedTo(typeof(System.Globalization.CultureData))] -[assembly: TypeForwardedTo(typeof(System.Globalization.CalendarData))] -[assembly: TypeForwardedTo(typeof(System.IO.BufferedStream))] -[assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.JitHelpers))] -[assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.ObjectHandleOnStack))] -[assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.PinningHelper))] -[assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.StackCrawlMarkHandle))] -[assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.StringHandleOnStack))] -[assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.FriendAccessAllowedAttribute))] -[assembly: TypeForwardedTo(typeof(System.StubHelpers.StubHelpers))] -[assembly: TypeForwardedTo(typeof(System.StubHelpers.CleanupWorkList))] -[assembly: TypeForwardedTo(typeof(System.StubHelpers.CleanupWorkListElement))] -[assembly: TypeForwardedTo(typeof(System.Threading.StackCrawlMark))] -[assembly: TypeForwardedTo(typeof(System.Threading.Tasks.AsyncCausalityStatus))] -[assembly: TypeForwardedTo(typeof(System.Threading.Tasks.CausalityRelation))] -[assembly: TypeForwardedTo(typeof(System.Threading.Tasks.CausalitySynchronousWork))] -[assembly: TypeForwardedTo(typeof(System.Threading.Tasks.AsyncCausalityTracer))] -[assembly: TypeForwardedTo(typeof(System.Threading.Tasks.CausalityTraceLevel))] - - diff --git a/src/mscorlib/facade/mscorlib.csproj b/src/mscorlib/facade/mscorlib.csproj index c3a165d..7d0133a 100644 --- a/src/mscorlib/facade/mscorlib.csproj +++ b/src/mscorlib/facade/mscorlib.csproj @@ -48,20 +48,13 @@ none - - - $(DefineConstants);WINDOWS_TYPEFORWARDS - - $(RootBinDir)\obj - - $(BaseIntermediateOutputPath)\$(BuildOS).$(BuildArch).$(Configuration)\facade\\ + + $(BaseIntermediateOutputPath)\$(BuildOS).$(BuildArch).$(Configuration)\facade/ $(BinDir)\facade @@ -70,10 +63,6 @@ - - - - @@ -97,6 +86,24 @@ System.Console + + System.IO + + + System.IO + + + System.IO + + + System.IO + + + System.IO + + + System.IO + diff --git a/src/mscorlib/facade/project.json b/src/mscorlib/facade/project.json index 485086e..37f8c1b 100644 --- a/src/mscorlib/facade/project.json +++ b/src/mscorlib/facade/project.json @@ -1,6 +1,7 @@ { "dependencies": { "System.Console": "4.0.0", + "System.IO": "4.1.0", "System.Security.Cryptography.Primitives": "4.0.0", "System.Security.Claims": "4.0.0", }, diff --git a/src/mscorlib/model.xml b/src/mscorlib/model.xml index 67db0a0..c0e9746 100644 --- a/src/mscorlib/model.xml +++ b/src/mscorlib/model.xml @@ -143,14 +143,23 @@ + + + + + + - - - + + + + + - + + @@ -239,6 +248,8 @@ + + @@ -285,6 +296,8 @@ + + @@ -328,6 +341,7 @@ + @@ -335,6 +349,13 @@ + + + + + + + @@ -436,6 +457,7 @@ + @@ -448,6 +470,7 @@ + @@ -472,6 +495,7 @@ + @@ -497,6 +521,15 @@ + + + + + + + + + @@ -596,38 +629,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -639,6 +640,7 @@ + @@ -653,6 +655,8 @@ + + @@ -667,6 +671,8 @@ + + @@ -784,11 +790,15 @@ + + + + @@ -1055,27 +1065,25 @@ + + + + + + + + + + - - - - - - - - - - - - @@ -1830,6 +1838,7 @@ + @@ -1957,6 +1966,8 @@ + + @@ -1970,6 +1981,8 @@ + + @@ -2014,6 +2027,12 @@ + + + + + + @@ -2050,6 +2069,8 @@ + + @@ -2058,6 +2079,7 @@ + @@ -2166,6 +2188,7 @@ + @@ -2176,6 +2199,10 @@ + + + + @@ -2295,6 +2322,7 @@ + @@ -2340,6 +2368,7 @@ + @@ -2366,15 +2395,18 @@ + + + @@ -2386,6 +2418,7 @@ + @@ -2408,15 +2441,18 @@ + + + @@ -2591,7 +2627,7 @@ - + @@ -2627,7 +2663,7 @@ - + @@ -2740,7 +2776,7 @@ - + @@ -3480,11 +3516,6 @@ - - - - - @@ -3494,6 +3525,8 @@ + + @@ -3543,6 +3576,9 @@ + + + @@ -3572,6 +3608,17 @@ + + + + + + + + + + + @@ -3629,6 +3676,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3895,14 +3974,19 @@ + + + + + @@ -3913,6 +3997,9 @@ + + + @@ -3938,21 +4025,35 @@ + + + + + + + + + + + - + + + + @@ -4084,6 +4185,7 @@ + @@ -4092,6 +4194,8 @@ + + @@ -4102,17 +4206,20 @@ + + + @@ -4120,6 +4227,7 @@ + @@ -4588,6 +4696,7 @@ + @@ -5106,6 +5215,7 @@ + @@ -5120,6 +5230,7 @@ + @@ -5540,6 +5651,9 @@ + + + @@ -5673,6 +5787,9 @@ + + + @@ -5706,6 +5823,9 @@ + + + @@ -5912,6 +6032,7 @@ + @@ -6104,6 +6225,15 @@ + + + + + + + + + @@ -6112,6 +6242,19 @@ + + + + + + + + + + + + + @@ -6124,6 +6267,7 @@ + @@ -6140,9 +6284,12 @@ + + + @@ -6150,10 +6297,12 @@ + + @@ -6180,10 +6329,6 @@ - - - - @@ -6206,6 +6351,21 @@ + + + + + + + + + + + + + + + @@ -6247,18 +6407,6 @@ - - - - - - - - - - - - @@ -6267,22 +6415,7 @@ - - - - - - - - - - - - - - - - + @@ -6310,21 +6443,43 @@ + + + + - - + + + + + + + + + + + + + + + + + + + + @@ -6361,10 +6516,16 @@ + + + + + + @@ -6415,7 +6576,6 @@ - @@ -6527,6 +6687,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -6535,6 +6725,7 @@ + @@ -6572,9 +6763,26 @@ + + + + + + + + + + + + + + + + + @@ -6608,16 +6816,19 @@ - - - - + + + + + + + @@ -6635,13 +6846,18 @@ + + + + + @@ -6656,6 +6872,8 @@ + + @@ -6675,12 +6893,14 @@ + + @@ -6734,8 +6954,10 @@ + + @@ -6751,6 +6973,11 @@ + + + + + @@ -6767,12 +6994,24 @@ + + + + + + + + + + + + @@ -6782,8 +7021,17 @@ - - + + + + + + + + + + + @@ -6804,6 +7052,18 @@ + + + + + + + + + + + + @@ -6821,6 +7081,14 @@ + + + + + + + + @@ -6829,6 +7097,9 @@ + + + @@ -6899,16 +7170,6 @@ - - - - - - - - - - @@ -6949,12 +7210,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -7033,16 +7362,16 @@ + - - + @@ -7064,7 +7393,9 @@ + + @@ -7085,6 +7416,10 @@ + + + + @@ -7114,14 +7449,12 @@ - - @@ -7147,6 +7480,7 @@ + @@ -7161,7 +7495,7 @@ - + @@ -7169,6 +7503,7 @@ + @@ -7432,10 +7767,12 @@ + + @@ -7541,6 +7878,10 @@ + + + + @@ -7685,6 +8026,21 @@ + + + + + + + + + + + + + + + @@ -7784,7 +8140,9 @@ + + @@ -7797,14 +8155,18 @@ - - - - - - + + + + + + + + + + @@ -7821,14 +8183,8 @@ - - - - - - @@ -7838,39 +8194,77 @@ - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + - + + - - - - + + + + + + + + + + + + + + + @@ -7887,12 +8281,18 @@ + + + + + + @@ -7993,10 +8393,6 @@ - - - - @@ -8088,20 +8484,18 @@ + + + - @@ -8109,11 +8503,9 @@ - @@ -8386,6 +8778,9 @@ + + + @@ -8451,6 +8846,9 @@ + + + @@ -8459,6 +8857,7 @@ + @@ -8472,6 +8871,9 @@ + + + @@ -8813,6 +9215,9 @@ + + + @@ -8945,9 +9350,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -9000,15 +9460,18 @@ + - + + + @@ -9046,6 +9509,7 @@ + @@ -9061,6 +9525,7 @@ + @@ -9070,6 +9535,7 @@ + @@ -9083,185 +9549,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -9273,6 +9560,8 @@ + + @@ -9299,6 +9588,8 @@ + + @@ -9726,7 +10017,6 @@ - @@ -9831,12 +10121,22 @@ - + + + + + + + + + + + @@ -9849,8 +10149,14 @@ - + + + + + + + @@ -9865,7 +10171,13 @@ - + + + + + + + @@ -9875,7 +10187,7 @@ - + @@ -10278,25 +10590,11 @@ - - - - - - - - - - - - - - @@ -10397,6 +10695,14 @@ + + + + + + + + @@ -10450,6 +10756,15 @@ + + + + + + + + + @@ -10501,17 +10816,34 @@ - - - + + + + + + + + + + + + + + + + + - + + + + @@ -10555,7 +10887,10 @@ - + + + + @@ -11896,8 +12231,15 @@ + + + + + + + @@ -12080,5 +12422,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mscorlib/mscorlib.shared.sources.props b/src/mscorlib/mscorlib.shared.sources.props index fc5153f..3c4b1bc 100644 --- a/src/mscorlib/mscorlib.shared.sources.props +++ b/src/mscorlib/mscorlib.shared.sources.props @@ -2,7 +2,6 @@ - @@ -21,29 +20,15 @@ - - - - - - - - - - - - - + - - @@ -62,8 +47,6 @@ - - @@ -78,7 +61,6 @@ - @@ -123,7 +105,6 @@ - @@ -135,20 +116,23 @@ - - - + + + + + + + - @@ -338,8 +322,6 @@ - - @@ -389,6 +371,7 @@ + @@ -444,7 +427,6 @@ - @@ -455,9 +437,13 @@ + + + + @@ -613,7 +599,7 @@ - + @@ -631,10 +617,12 @@ - + - + + + @@ -644,6 +632,7 @@ + @@ -654,6 +643,7 @@ + @@ -663,6 +653,8 @@ + + @@ -676,12 +668,14 @@ + - + + @@ -689,8 +683,11 @@ + + + @@ -712,7 +709,7 @@ - + @@ -729,7 +726,6 @@ - @@ -765,18 +761,53 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + @@ -786,32 +817,24 @@ - - - - - + - - - - @@ -842,6 +865,7 @@ + @@ -932,6 +956,7 @@ + @@ -954,11 +979,9 @@ + - - - @@ -999,6 +1022,7 @@ + @@ -1130,7 +1154,6 @@ - @@ -1141,6 +1164,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1170,6 +1287,7 @@ + @@ -1190,6 +1308,10 @@ + + + + diff --git a/src/mscorlib/ref/mscorlib.cs b/src/mscorlib/ref/mscorlib.cs index e5211ff..da37877 100644 --- a/src/mscorlib/ref/mscorlib.cs +++ b/src/mscorlib/ref/mscorlib.cs @@ -15,10 +15,56 @@ namespace Internal.Runtime.Augments public static void FailFast(string message, System.Exception error) { } public static string[] GetCommandLineArgs() { throw null; } } + public partial class RuntimeThread : System.Runtime.ConstrainedExecution.CriticalFinalizerObject + { + public static Internal.Runtime.Augments.RuntimeThread CurrentThread { get { throw null; } } + public bool IsAlive { get { throw null; } } + public bool IsBackground { get { throw null; } set { } } + public bool IsThreadPoolThread { get { throw null; } } + public int ManagedThreadId { get { throw null; } } + public string Name { get { throw null; } set { } } + public System.Threading.ThreadPriority Priority { get { throw null; } set { } } + public System.Threading.ThreadState ThreadState { get { throw null; } } + ~RuntimeThread() { } + public static Internal.Runtime.Augments.RuntimeThread Create(System.Threading.ThreadStart start) { throw null; } + public static Internal.Runtime.Augments.RuntimeThread Create(System.Threading.ThreadStart start, int maxStackSize) { throw null; } + public static Internal.Runtime.Augments.RuntimeThread Create(System.Threading.ParameterizedThreadStart start) { throw null; } + public static Internal.Runtime.Augments.RuntimeThread Create(System.Threading.ParameterizedThreadStart start, int maxStackSize) { throw null; } + public System.Threading.ApartmentState GetApartmentState() { throw null; } + [System.Security.SecurityCriticalAttribute] + public void Interrupt() { } + public void Join() { } + public bool Join(int millisecondsTimeout) { throw null; } + public static void Sleep(int millisecondsTimeout) { } + public static void SpinWait(int iterations) { } + public void Start() { } + public void Start(object parameter) { } + public bool TrySetApartmentState(System.Threading.ApartmentState state) { throw null; } + } } namespace Microsoft.Win32.SafeHandles { [System.Security.SecurityCriticalAttribute] + public abstract partial class CriticalHandleMinusOneIsInvalid : System.Runtime.InteropServices.CriticalHandle + { + protected CriticalHandleMinusOneIsInvalid() : base(default(System.IntPtr)) { } + public override bool IsInvalid { [System.Security.SecurityCriticalAttribute]get { throw null; } } + } + [System.Security.SecurityCriticalAttribute] + public abstract partial class CriticalHandleZeroOrMinusOneIsInvalid : System.Runtime.InteropServices.CriticalHandle + { + protected CriticalHandleZeroOrMinusOneIsInvalid() : base(default(System.IntPtr)) { } + public override bool IsInvalid { [System.Security.SecurityCriticalAttribute]get { throw null; } } + } + [System.Security.SecurityCriticalAttribute] + public sealed partial class SafeFileHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid + { + public SafeFileHandle(System.IntPtr preexistingHandle, bool ownsHandle) : base(default(bool)) { } + public override bool IsInvalid { [System.Security.SecurityCriticalAttribute]get { throw null; } } + [System.Security.SecurityCriticalAttribute] + protected override bool ReleaseHandle() { throw null; } + } + [System.Security.SecurityCriticalAttribute] public abstract partial class SafeHandleMinusOneIsInvalid : System.Runtime.InteropServices.SafeHandle { protected SafeHandleMinusOneIsInvalid(bool ownsHandle) { } @@ -126,8 +172,13 @@ namespace System public static string TargetFrameworkName { get { throw null; } } [System.Security.SecuritySafeCriticalAttribute] public static object GetData(string name) { throw null; } + [System.Security.SecuritySafeCriticalAttribute] + public static void SetData(string name, object data) { } public static void SetSwitch(string switchName, bool isEnabled) { } public static bool TryGetSwitch(string switchName, out bool isEnabled) { isEnabled = default(bool); throw null; } + public static event UnhandledExceptionEventHandler UnhandledException { add { } remove { } } + public static event System.EventHandler FirstChanceException { add { } remove { } } + public static event System.EventHandler ProcessExit { add { } remove { } } } [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))] [System.Runtime.InteropServices.ComVisibleAttribute(true)] @@ -560,7 +611,11 @@ namespace System [System.CLSCompliantAttribute(false)] public static byte[] GetBytes(ulong value) { throw null; } [System.Security.SecuritySafeCriticalAttribute] + public static float Int32BitsToSingle(int value) { throw null; } + [System.Security.SecuritySafeCriticalAttribute] public static double Int64BitsToDouble(long value) { throw null; } + [System.Security.SecuritySafeCriticalAttribute] + public static int SingleToInt32Bits(float value) { throw null; } public static bool ToBoolean(byte[] value, int startIndex) { throw null; } public static char ToChar(byte[] value, int startIndex) { throw null; } [System.Security.SecuritySafeCriticalAttribute] @@ -782,29 +837,9 @@ namespace System public static partial class Console { [System.Security.SecuritySafeCriticalAttribute] - public static void Write(string s) { } + public static void Write(string value) { } public static void WriteLine() { } - public static void WriteLine(string s) { } - } - [System.Runtime.InteropServices.ComVisibleAttribute(true)] - public abstract partial class ContextBoundObject - { - protected ContextBoundObject() { } - } - [System.Runtime.InteropServices.ComVisibleAttribute(true)] - public partial class ContextMarshalException : System.SystemException - { - public ContextMarshalException() { } - public ContextMarshalException(string message) { } - public ContextMarshalException(string message, System.Exception inner) { } - protected ContextMarshalException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { } - } - [System.AttributeUsageAttribute((System.AttributeTargets)(256), Inherited=false)] - [System.ObsoleteAttribute("ContextStaticAttribute is not supported in this release. It has been left in so that legacy tools can be used with this release, but it cannot be used in your code.", true)] - [System.Runtime.InteropServices.ComVisibleAttribute(true)] - public partial class ContextStaticAttribute : System.Attribute - { - public ContextStaticAttribute() { } + public static void WriteLine(string value) { } } public static partial class Convert { @@ -1961,6 +1996,7 @@ namespace System public virtual string Source { [System.Security.SecurityCriticalAttribute]get { throw null; } [System.Security.SecurityCriticalAttribute]set { } } public virtual string StackTrace { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } } public System.Reflection.MethodBase TargetSite { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } } + protected event System.EventHandler SerializeObjectState { add { } remove { } } public virtual System.Exception GetBaseException() { throw null; } [System.Security.SecurityCriticalAttribute] public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } @@ -2473,6 +2509,10 @@ namespace System public abstract partial class MarshalByRefObject { protected MarshalByRefObject() { } + public object GetLifetimeService() { throw null; } + public virtual object InitializeLifetimeService() { throw null; } + protected System.MarshalByRefObject MemberwiseClone(bool cloneIdentity) { throw null; } + } public static partial class Math { @@ -2500,6 +2540,21 @@ namespace System public static decimal Ceiling(decimal d) { throw null; } [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] public static double Ceiling(double a) { throw null; } + public static byte Clamp(byte value, byte min, byte max) { throw null; } + public static decimal Clamp(decimal value, decimal min, decimal max) { throw null; } + public static double Clamp(double value, double min, double max) { throw null; } + public static short Clamp(short value, short min, short max) { throw null; } + public static int Clamp(int value, int min, int max) { throw null; } + public static long Clamp(long value, long min, long max) { throw null; } + [System.CLSCompliantAttribute(false)] + public static sbyte Clamp(sbyte value, sbyte min, sbyte max) { throw null; } + public static float Clamp(float value, float min, float max) { throw null; } + [System.CLSCompliantAttribute(false)] + public static ushort Clamp(ushort value, ushort min, ushort max) { throw null; } + [System.CLSCompliantAttribute(false)] + public static uint Clamp(uint value, uint min, uint max) { throw null; } + [System.CLSCompliantAttribute(false)] + public static ulong Clamp(ulong value, ulong min, ulong max) { throw null; } [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] public static double Cos(double d) { throw null; } [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] @@ -2579,6 +2634,58 @@ namespace System public static decimal Truncate(decimal d) { throw null; } public static double Truncate(double d) { throw null; } } + public static partial class MathF + { + public const float E = 2.71828183f; + public const float PI = 3.14159265f; + public static float Abs(float x) { throw null; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] + public static float Acos(float x) { throw null; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] + public static float Asin(float x) { throw null; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] + public static float Atan(float x) { throw null; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] + public static float Atan2(float y, float x) { throw null; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] + public static float Ceiling(float x) { throw null; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] + public static float Cos(float x) { throw null; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] + public static float Cosh(float x) { throw null; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] + public static float Exp(float x) { throw null; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] + public static float Floor(float x) { throw null; } + public static float IEEERemainder(float x, float y) { throw null; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] + public static float Log(float x) { throw null; } + public static float Log(float x, float y) { throw null; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] + public static float Log10(float x) { throw null; } + public static float Max(float x, float y) { throw null; } + public static float Min(float x, float y) { throw null; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] + public static float Pow(float x, float y) { throw null; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] + public static float Round(float x) { throw null; } + public static float Round(float x, int digits) { throw null; } + public static float Round(float x, int digits, System.MidpointRounding mode) { throw null; } + public static float Round(float x, System.MidpointRounding mode) { throw null; } + public static int Sign(float x) { return default(int); } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] + public static float Sin(float x) { throw null; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] + public static float Sinh(float x) { throw null; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)] + [System.Security.SecuritySafeCriticalAttribute] + public static float Sqrt(float x) { throw null; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] + public static float Tan(float x) { throw null; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] + public static float Tanh(float x) { throw null; } + public static float Truncate(float x) { throw null; } + } [System.Runtime.InteropServices.ComVisibleAttribute(true)] public partial class MemberAccessException : System.SystemException { @@ -3181,6 +3288,7 @@ namespace System public static System.String Format(System.String format, object arg0, object arg1) { throw null; } public static System.String Format(System.String format, object arg0, object arg1, object arg2) { throw null; } public static System.String Format(System.String format, params object[] args) { throw null; } + public System.CharEnumerator GetEnumerator() { throw null; } [System.Security.SecuritySafeCriticalAttribute] public override int GetHashCode() { throw null; } public System.TypeCode GetTypeCode() { throw null; } @@ -3253,6 +3361,10 @@ namespace System [System.Security.SecuritySafeCriticalAttribute] public System.String Replace(char oldChar, char newChar) { throw null; } public System.String Replace(System.String oldValue, System.String newValue) { throw null; } + [System.Runtime.InteropServices.ComVisibleAttribute(false)] + public string[] Split(char separator, int count, System.StringSplitOptions options = (System.StringSplitOptions)(0)) { throw null; } + [System.Runtime.InteropServices.ComVisibleAttribute(false)] + public string[] Split(char separator, System.StringSplitOptions options = (System.StringSplitOptions)(0)) { throw null; } public string[] Split(params char[] separator) { throw null; } public string[] Split(char[] separator, int count) { throw null; } [System.Runtime.InteropServices.ComVisibleAttribute(false)] @@ -3260,6 +3372,10 @@ namespace System [System.Runtime.InteropServices.ComVisibleAttribute(false)] public string[] Split(char[] separator, System.StringSplitOptions options) { throw null; } [System.Runtime.InteropServices.ComVisibleAttribute(false)] + public string[] Split(System.String separator, int count, System.StringSplitOptions options = (System.StringSplitOptions)(0)) { throw null; } + [System.Runtime.InteropServices.ComVisibleAttribute(false)] + public string[] Split(System.String separator, System.StringSplitOptions options = (System.StringSplitOptions)(0)) { throw null; } + [System.Runtime.InteropServices.ComVisibleAttribute(false)] public string[] Split(string[] separator, int count, System.StringSplitOptions options) { throw null; } [System.Runtime.InteropServices.ComVisibleAttribute(false)] public string[] Split(string[] separator, System.StringSplitOptions options) { throw null; } @@ -4228,32 +4344,6 @@ namespace System namespace System.Collections { [System.Runtime.InteropServices.ComVisibleAttribute(true)] - public sealed partial class BitArray : System.Collections.ICollection, System.Collections.IEnumerable, System.ICloneable - { - public BitArray(bool[] values) { } - public BitArray(byte[] bytes) { } - public BitArray(System.Collections.BitArray bits) { } - public BitArray(int length) { } - public BitArray(int length, bool defaultValue) { } - public BitArray(int[] values) { } - public int Count { get { throw null; } } - public bool IsReadOnly { get { throw null; } } - public bool IsSynchronized { get { throw null; } } - public bool this[int index] { get { throw null; } set { } } - public int Length { get { throw null; } set { } } - public object SyncRoot { get { throw null; } } - public System.Collections.BitArray And(System.Collections.BitArray value) { throw null; } - public object Clone() { throw null; } - public void CopyTo(System.Array array, int index) { } - public bool Get(int index) { throw null; } - public System.Collections.IEnumerator GetEnumerator() { throw null; } - public System.Collections.BitArray Not() { throw null; } - public System.Collections.BitArray Or(System.Collections.BitArray value) { throw null; } - public void Set(int index, bool value) { } - public void SetAll(bool value) { } - public System.Collections.BitArray Xor(System.Collections.BitArray value) { throw null; } - } - [System.Runtime.InteropServices.ComVisibleAttribute(true)] public abstract partial class CollectionBase : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { protected CollectionBase() { } @@ -4383,6 +4473,8 @@ namespace System.Collections.Generic public Dictionary() { } public Dictionary(System.Collections.Generic.IDictionary dictionary) { } public Dictionary(System.Collections.Generic.IDictionary dictionary, System.Collections.Generic.IEqualityComparer comparer) { } + public Dictionary(System.Collections.Generic.IEnumerable> collection) { } + public Dictionary(System.Collections.Generic.IEnumerable> collection, System.Collections.Generic.IEqualityComparer comparer) { } public Dictionary(System.Collections.Generic.IEqualityComparer comparer) { } public Dictionary(int capacity) { } public Dictionary(int capacity, System.Collections.Generic.IEqualityComparer comparer) { } @@ -4878,6 +4970,7 @@ namespace System.Diagnostics [System.Runtime.InteropServices.ComVisibleAttribute(true)] public sealed partial class Debugger { + public static readonly string DefaultCategory; [System.ObsoleteAttribute("Do not create instances of the Debugger class. Call the static methods directly on this type instead", true)] public Debugger() { } public static bool IsAttached { [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]get { throw null; } } @@ -5682,6 +5775,7 @@ namespace System.Globalization public virtual int LastIndexOf(string source, string value, int startIndex, int count, System.Globalization.CompareOptions options) { throw null; } void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) { } public override string ToString() { throw null; } + public SortVersion Version { get { throw null; } } } [System.FlagsAttribute] [System.Runtime.InteropServices.ComVisibleAttribute(true)] @@ -5706,6 +5800,7 @@ namespace System.Globalization public CultureInfo(string name, bool useUserOverride) { throw null; } public virtual System.Globalization.Calendar Calendar { get { throw null; } } public virtual System.Globalization.CompareInfo CompareInfo { get { throw null; } } + public System.Globalization.CultureTypes CultureTypes { get { throw null; } } public static System.Globalization.CultureInfo CurrentCulture { get { throw null; } set { } } public static System.Globalization.CultureInfo CurrentUICulture { get { throw null; } set { } } public virtual System.Globalization.DateTimeFormatInfo DateTimeFormat { get { throw null; } set { } } @@ -5713,10 +5808,12 @@ namespace System.Globalization public static System.Globalization.CultureInfo DefaultThreadCurrentUICulture { get { throw null; } [System.Security.SecuritySafeCriticalAttribute]set { } } public virtual string DisplayName { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } } public virtual string EnglishName { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } } + public string IetfLanguageTag { get { throw null; } } public static System.Globalization.CultureInfo InstalledUICulture { get { throw null; } } public static System.Globalization.CultureInfo InvariantCulture { get { throw null; } } public virtual bool IsNeutralCulture { get { throw null; } } public bool IsReadOnly { get { throw null; } } + public virtual int KeyboardLanguageId { get { throw null; } } public virtual int LCID { get { throw null; } } public virtual string Name { get { throw null; } } public virtual string NativeName { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } } @@ -5732,6 +5829,7 @@ namespace System.Globalization public virtual object Clone() { throw null; } public static System.Globalization.CultureInfo CreateSpecificCulture(string name) { throw null; } public override bool Equals(object value) { throw null; } + public System.Globalization.CultureInfo GetConsoleFallbackUICulture() { throw null; } public static System.Globalization.CultureInfo GetCultureInfo(int culture) { throw null; } public static System.Globalization.CultureInfo GetCultureInfo(string name) { throw null; } public static System.Globalization.CultureInfo GetCultureInfo(string name, string altName) { throw null; } @@ -6604,9 +6702,19 @@ namespace System.IO public FileLoadException(string message, string fileName, System.Exception inner) { } protected FileLoadException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { } public string FileName { get { throw null; } } + public string FusionLog { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } } public override string Message { get { throw null; } } public override string ToString() { throw null; } } + public enum FileMode + { + Append = 6, + Create = 2, + CreateNew = 1, + Open = 3, + OpenOrCreate = 4, + Truncate = 5, + } [System.Runtime.InteropServices.ComVisibleAttribute(true)] public partial class FileNotFoundException : System.IO.IOException { @@ -6617,9 +6725,72 @@ namespace System.IO public FileNotFoundException(string message, string fileName, System.Exception innerException) { } protected FileNotFoundException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { } public string FileName { get { throw null; } } + public string FusionLog { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } } public override string Message { get { throw null; } } public override string ToString() { throw null; } } + [System.FlagsAttribute] + public enum FileOptions + { + Asynchronous = 1073741824, + DeleteOnClose = 67108864, + Encrypted = 16384, + None = 0, + RandomAccess = 268435456, + SequentialScan = 134217728, + WriteThrough = -2147483648, + } + [System.FlagsAttribute] + public enum FileShare + { + Delete = 4, + Inheritable = 16, + None = 0, + Read = 1, + ReadWrite = 3, + Write = 2, + } + public partial class FileStream : System.IO.Stream + { + public FileStream(Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.IO.FileAccess access) { } + public FileStream(Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.IO.FileAccess access, int bufferSize) { } + public FileStream(Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.IO.FileAccess access, int bufferSize, bool isAsync) { } + public FileStream(string path, System.IO.FileMode mode) { } + public FileStream(string path, System.IO.FileMode mode, System.IO.FileAccess access) { } + public FileStream(string path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share) { } + public FileStream(string path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, int bufferSize) { } + public FileStream(string path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, int bufferSize, bool useAsync) { } + public FileStream(string path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, int bufferSize, System.IO.FileOptions options) { } + public override bool CanRead { get { throw null; } } + public override bool CanSeek { get { throw null; } } + public override bool CanWrite { get { throw null; } } + [Obsolete("This property has been deprecated. Please use FileStream's SafeFileHandle property instead. http://go.microsoft.com/fwlink/?linkid=14202")] + public virtual System.IntPtr Handle { get { throw null; } } + public virtual bool IsAsync { get { throw null; } } + public override long Length { get { throw null; } } + public string Name { get { throw null; } } + public override long Position { get { throw null; } set { } } + public virtual Microsoft.Win32.SafeHandles.SafeFileHandle SafeFileHandle { get { throw null; } } + protected override void Dispose(bool disposing) { } + ~FileStream() { } + public override void Flush() { } + public virtual void Flush(bool flushToDisk) { } + public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) { throw null; } + public override int Read(byte[] array, int offset, int count) { throw null; } + public override System.Threading.Tasks.Task ReadAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) { throw null; } + public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { throw null; } + public override int EndRead(IAsyncResult asyncResult) { throw null; } + public virtual void Lock(long position, long length) { } + public override int ReadByte() { throw null; } + public override long Seek(long offset, System.IO.SeekOrigin origin) { throw null; } + public override void SetLength(long value) { } + public override void Write(byte[] array, int offset, int count) { } + public override System.Threading.Tasks.Task WriteAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) { throw null; } + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { throw null; } + public override void EndWrite(IAsyncResult asyncResult) { } + public override void WriteByte(byte value) { } + public virtual void Unlock(long position, long length) { } + } [System.Runtime.InteropServices.ComVisibleAttribute(true)] public partial class IOException : System.SystemException { @@ -6736,6 +6907,8 @@ namespace System.IO public System.Threading.Tasks.Task CopyToAsync(System.IO.Stream destination, int bufferSize) { throw null; } [System.Runtime.InteropServices.ComVisibleAttribute(false)] public virtual System.Threading.Tasks.Task CopyToAsync(System.IO.Stream destination, int bufferSize, System.Threading.CancellationToken cancellationToken) { throw null; } + [System.ObsoleteAttribute("CreateWaitHandle will be removed eventually. Please use \"new ManualResetEvent(false)\" instead.")] + protected virtual System.Threading.WaitHandle CreateWaitHandle() { return default(System.Threading.WaitHandle); } public void Dispose() { } protected virtual void Dispose(bool disposing) { } public virtual int EndRead(System.IAsyncResult asyncResult) { throw null; } @@ -6745,6 +6918,8 @@ namespace System.IO public System.Threading.Tasks.Task FlushAsync() { throw null; } [System.Runtime.InteropServices.ComVisibleAttribute(false)] public virtual System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) { throw null; } + [System.ObsoleteAttribute("Do not call or override this method.")] + protected virtual void ObjectInvariant() { } public abstract int Read(byte[] buffer, int offset, int count); [System.Runtime.InteropServices.ComVisibleAttribute(false)] public System.Threading.Tasks.Task ReadAsync(byte[] buffer, int offset, int count) { throw null; } @@ -6753,6 +6928,7 @@ namespace System.IO public virtual int ReadByte() { throw null; } public abstract long Seek(long offset, System.IO.SeekOrigin origin); public abstract void SetLength(long value); + public static System.IO.Stream Synchronized(System.IO.Stream stream) { throw null; } public abstract void Write(byte[] buffer, int offset, int count); [System.Runtime.InteropServices.ComVisibleAttribute(false)] public System.Threading.Tasks.Task WriteAsync(byte[] buffer, int offset, int count) { throw null; } @@ -6910,6 +7086,7 @@ namespace System.IO [System.Diagnostics.DebuggerStepThroughAttribute] [System.Runtime.InteropServices.ComVisibleAttribute(false)] public virtual System.Threading.Tasks.Task ReadToEndAsync() { throw null; } + public static System.IO.TextReader Synchronized(System.IO.TextReader reader) { throw null; } } [System.Runtime.InteropServices.ComVisibleAttribute(true)] public abstract partial class TextWriter : System.IDisposable @@ -6927,6 +7104,7 @@ namespace System.IO public virtual void Flush() { } [System.Runtime.InteropServices.ComVisibleAttribute(false)] public virtual System.Threading.Tasks.Task FlushAsync() { throw null; } + public static System.IO.TextWriter Synchronized(System.IO.TextWriter writer) { throw null; } public virtual void Write(bool value) { } public virtual void Write(char value) { } public virtual void Write(char[] buffer) { } @@ -7001,6 +7179,10 @@ namespace System.IO [System.Security.SecuritySafeCriticalAttribute] [System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.Demand, Flags=(System.Security.Permissions.SecurityPermissionFlag)(2))] protected void Initialize(System.Runtime.InteropServices.SafeBuffer buffer, long offset, long capacity, System.IO.FileAccess access) { } + [System.Security.SecurityCriticalAttribute] + public void Read(long position, out T structure) where T : struct { structure = default(T); throw null; } + [System.Security.SecurityCriticalAttribute] + public int ReadArray(long position, T[] array, int offset, int count) where T : struct { throw null; } public bool ReadBoolean(long position) { throw null; } public byte ReadByte(long position) { throw null; } [System.Security.SecuritySafeCriticalAttribute] @@ -7057,6 +7239,10 @@ namespace System.IO [System.CLSCompliantAttribute(false)] [System.Security.SecuritySafeCriticalAttribute] public void Write(long position, ulong value) { } + [System.Security.SecurityCriticalAttribute] + public void Write(long position, ref T structure) where T : struct { } + [System.Security.SecurityCriticalAttribute] + public void WriteArray(long position, T[] array, int offset, int count) where T : struct { } } public partial class UnmanagedMemoryStream : System.IO.Stream { @@ -7125,11 +7311,15 @@ namespace System.Reflection public virtual System.Collections.Generic.IEnumerable CustomAttributes { get { throw null; } } public virtual System.Collections.Generic.IEnumerable DefinedTypes { get { throw null; } } public virtual System.Reflection.MethodInfo EntryPoint { get { throw null; } } + public virtual string EscapedCodeBase { [System.Security.SecurityCriticalAttribute]get { throw null; } } public virtual System.Collections.Generic.IEnumerable ExportedTypes { get { throw null; } } public virtual string FullName { get { throw null; } } + public virtual bool GlobalAssemblyCache { get { throw null; } } + public virtual Int64 HostContext { get { throw null; } } [System.Runtime.InteropServices.ComVisibleAttribute(false)] public virtual string ImageRuntimeVersion { get { throw null; } } public virtual bool IsDynamic { get { throw null; } } + public bool IsFullyTrusted { get { throw null; } } public virtual string Location { [System.Security.SecurityCriticalAttribute]get { throw null; } } [System.Runtime.InteropServices.ComVisibleAttribute(false)] public virtual System.Reflection.Module ManifestModule { get { throw null; } } @@ -7137,6 +7327,7 @@ namespace System.Reflection public virtual System.Collections.Generic.IEnumerable Modules { get { throw null; } } [System.Runtime.InteropServices.ComVisibleAttribute(false)] public virtual bool ReflectionOnly { get { throw null; } } + public virtual System.Security.SecurityRuleSet SecurityRuleSet { get { throw null; } } public object CreateInstance(string typeName) { throw null; } public object CreateInstance(string typeName, bool ignoreCase) { throw null; } public virtual object CreateInstance(String typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, System.Globalization.CultureInfo culture, Object[] activationAttributes) { throw null; } @@ -7155,6 +7346,9 @@ namespace System.Reflection [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute] public static System.Reflection.Assembly GetExecutingAssembly() { throw null; } public virtual System.Type[] GetExportedTypes() { throw null; } + public virtual System.IO.FileStream GetFile(string name) { throw null; } + public virtual System.IO.FileStream[] GetFiles() { throw null; } + public virtual System.IO.FileStream[] GetFiles(bool getResourceModules) { throw null; } public override int GetHashCode() { throw null; } public System.Reflection.Module[] GetLoadedModules() { throw null; } public virtual System.Reflection.Module[] GetLoadedModules(bool getResourceModules) { throw null; } @@ -7187,6 +7381,13 @@ namespace System.Reflection public static System.Reflection.Assembly Load(System.Reflection.AssemblyName assemblyRef) { throw null; } [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute] public static System.Reflection.Assembly Load(string assemblyString) { throw null; } + public static System.Reflection.Assembly LoadFile(String path) { throw null; } + public static System.Reflection.Assembly LoadFrom(String path) { throw null; } + public static Assembly LoadFrom(string assemblyFile, byte[] hashValue, System.Configuration.Assemblies.AssemblyHashAlgorithm hashAlgorithm) { throw null; } + public System.Reflection.Module LoadModule(String moduleName, byte[] rawModule) { throw null; } + public System.Reflection.Module LoadModule(String moduleName, byte[] rawModule, byte[] rawSymbolStore) { throw null; } + [ObsoleteAttribute("This method has been deprecated. Please use Assembly.Load() instead. http://go.microsoft.com/fwlink/?linkid=14202")] + public static Assembly LoadWithPartialName(string partialName) { throw null; } [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] public static Assembly ReflectionOnlyLoad(byte[] rawAssembly) { throw null; } [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] @@ -7194,6 +7395,7 @@ namespace System.Reflection [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] public static Assembly ReflectionOnlyLoadFrom(string assemblyFile) { throw null; } public override string ToString() { throw null; } + public static Assembly UnsafeLoadFrom(string assemblyFile) { throw null; } } [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)] [System.Runtime.InteropServices.ComVisibleAttribute(true)] @@ -7319,14 +7521,18 @@ namespace System.Reflection public System.Globalization.CultureInfo CultureInfo { get { throw null; } set { } } public string CultureName { [System.Security.SecurityCriticalAttribute]get { throw null; } [System.Security.SecurityCriticalAttribute]set { } } public string CodeBase { get { throw null; } set { } } + public string EscapedCodeBase { get { throw null; } } public System.Reflection.AssemblyNameFlags Flags { get { throw null; } set { } } public string FullName { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } } public System.Configuration.Assemblies.AssemblyHashAlgorithm HashAlgorithm { get { throw null; } set { } } + public System.Reflection.StrongNameKeyPair KeyPair { get { throw null; } set { } } public System.Configuration.Assemblies.AssemblyVersionCompatibility VersionCompatibility { get { throw null; } set { } } public string Name { get { throw null; } set { } } public System.Reflection.ProcessorArchitecture ProcessorArchitecture { get { throw null; } set { } } public System.Version Version { get { throw null; } set { } } public object Clone() { throw null; } + [System.Security.SecuritySafeCriticalAttribute] + public static System.Reflection.AssemblyName GetAssemblyName(System.String assemblyFile) { throw null; } public byte[] GetPublicKey() { throw null; } [System.Security.SecuritySafeCriticalAttribute] public byte[] GetPublicKeyToken() { throw null; } @@ -7336,6 +7542,8 @@ namespace System.Reflection [System.Security.SecurityCriticalAttribute] public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { throw null; } public void OnDeserialization(Object sender) { throw null; } + [System.Security.SecuritySafeCriticalAttribute] + public static bool ReferenceMatchesDefinition(System.Reflection.AssemblyName reference, System.Reflection.AssemblyName definition) { throw null; } } [System.FlagsAttribute] [System.Runtime.InteropServices.ComVisibleAttribute(true)] @@ -7723,7 +7931,7 @@ namespace System.Reflection public static System.Reflection.TypeInfo GetTypeInfo(this System.Type type) { throw null; } } [System.Runtime.InteropServices.ComVisibleAttribute(true)] - public partial class InvalidFilterCriteriaException : System.Exception + public partial class InvalidFilterCriteriaException : System.ApplicationException { public InvalidFilterCriteriaException() { } public InvalidFilterCriteriaException(string message) { } @@ -7858,6 +8066,8 @@ namespace System.Reflection public bool IsSpecialName { get { throw null; } } public bool IsStatic { get { throw null; } } public bool IsVirtual { get { throw null; } } + public virtual bool IsSecurityCritical { get { throw null; } } + public virtual bool IsSecurityTransparent { get { throw null; } } public abstract System.RuntimeMethodHandle MethodHandle { get; } public virtual System.Reflection.MethodImplAttributes MethodImplementationFlags { get { throw null; } } public override bool Equals(object obj) { throw null; } @@ -8217,7 +8427,7 @@ namespace System.Reflection public static System.Reflection.PropertyInfo GetRuntimeProperty(this System.Type type, string name) { throw null; } } [System.Runtime.InteropServices.ComVisibleAttribute(true)] - public partial class TargetException : System.Exception + public partial class TargetException : System.ApplicationException { public TargetException() { } public TargetException(string message) { } @@ -8225,13 +8435,13 @@ namespace System.Reflection protected TargetException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { } } [System.Runtime.InteropServices.ComVisibleAttribute(true)] - public sealed partial class TargetInvocationException : System.Exception + public sealed partial class TargetInvocationException : System.ApplicationException { public TargetInvocationException(System.Exception inner) { } public TargetInvocationException(string message, System.Exception inner) { } } [System.Runtime.InteropServices.ComVisibleAttribute(true)] - public sealed partial class TargetParameterCountException : System.Exception + public sealed partial class TargetParameterCountException : System.ApplicationException { public TargetParameterCountException() { } public TargetParameterCountException(string message) { } @@ -8354,6 +8564,16 @@ namespace System.Reflection public virtual bool IsAssignableFrom(System.Reflection.TypeInfo typeInfo) { throw null; } System.Reflection.TypeInfo System.Reflection.IReflectableType.GetTypeInfo() { throw null; } } + [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public partial class StrongNameKeyPair : System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable + { + public StrongNameKeyPair(byte[] keyPairArray) { } + protected StrongNameKeyPair(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } + public StrongNameKeyPair(string keyPairContainer) { } + public byte[] PublicKey { [System.Security.SecuritySafeCriticalAttribute]get { return default(byte[]); } } + void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) { } + void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } + } } namespace System.Reflection.Emit { @@ -8644,6 +8864,8 @@ namespace System.Reflection.Emit Cond_Branch = 3, Meta = 4, Next = 5, + [Obsolete("This API has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")] + Phi = 6, Return = 7, Throw = 8, } @@ -9206,6 +9428,8 @@ namespace System.Reflection.Emit [System.Runtime.InteropServices.ComVisibleAttribute(true)] public enum OpCodeType { + [Obsolete("This API has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")] + Annotation = 0, Macro = 1, Nternal = 2, Objmodel = 3, @@ -9221,6 +9445,8 @@ namespace System.Reflection.Emit InlineI8 = 3, InlineMethod = 4, InlineNone = 5, + [Obsolete("This API has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")] + InlinePhi = 6, InlineR = 7, InlineSig = 9, InlineString = 10, @@ -9591,15 +9817,26 @@ namespace System.Resources [System.Runtime.InteropServices.ComVisibleAttribute(true)] public partial interface IResourceReader : System.Collections.IEnumerable, System.IDisposable { + void Close(); new System.Collections.IDictionaryEnumerator GetEnumerator(); } [System.Runtime.InteropServices.ComVisibleAttribute(true)] public partial class MissingManifestResourceException : System.SystemException { public MissingManifestResourceException() { } + protected MissingManifestResourceException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } public MissingManifestResourceException(string message) { } public MissingManifestResourceException(string message, System.Exception inner) { } - protected MissingManifestResourceException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { } + } + [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public partial class MissingSatelliteAssemblyException : System.SystemException + { + public MissingSatelliteAssemblyException() { } + protected MissingSatelliteAssemblyException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } + public MissingSatelliteAssemblyException(string message) { } + public MissingSatelliteAssemblyException(string message, System.Exception inner) { } + public MissingSatelliteAssemblyException(string message, string cultureName) { } + public string CultureName { get { throw null; } } } [System.AttributeUsageAttribute((System.AttributeTargets)(1), AllowMultiple=false)] [System.Runtime.InteropServices.ComVisibleAttribute(true)] @@ -9622,8 +9859,10 @@ namespace System.Resources [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public ResourceManager(string baseName, System.Reflection.Assembly assembly, System.Type usingResourceSet) { } [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public ResourceManager(System.Type resourceSource) { } public virtual string BaseName { get { throw null; } } + protected System.Resources.UltimateResourceFallbackLocation FallbackLocation { get { throw null; } set { } } public virtual bool IgnoreCase { get { throw null; } set { } } public virtual System.Type ResourceSetType { get { throw null; } } + public static System.Resources.ResourceManager CreateFileBasedResourceManager(string baseName, string resourceDir, System.Type usingResourceSet) { throw null; } [System.Security.SecuritySafeCriticalAttribute] protected static System.Globalization.CultureInfo GetNeutralResourcesLanguage(System.Reflection.Assembly a) { throw null; } public virtual object GetObject(string name) { throw null; } @@ -9643,18 +9882,33 @@ namespace System.Resources public virtual void ReleaseAllResources() { } } [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public sealed partial class ResourceReader : System.Collections.IEnumerable, System.IDisposable, System.Resources.IResourceReader + { + [System.Security.SecurityCriticalAttribute] + public ResourceReader(System.IO.Stream stream) { } + [System.Security.SecurityCriticalAttribute] + public ResourceReader(string fileName) { } + public void Close() { } + public void Dispose() { } + public System.Collections.IDictionaryEnumerator GetEnumerator() { throw null; } + public void GetResourceData(string resourceName, out string resourceType, out byte[] resourceData) { resourceType = default(string); resourceData = default(byte[]); } + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } + } + [System.Runtime.InteropServices.ComVisibleAttribute(true)] public partial class ResourceSet : System.Collections.IEnumerable, System.IDisposable { protected System.Resources.IResourceReader Reader; protected ResourceSet() { } [System.Security.SecurityCriticalAttribute] public ResourceSet(System.IO.Stream stream) { } + public ResourceSet(System.Resources.IResourceReader reader) { } [System.Security.SecurityCriticalAttribute] public ResourceSet(string fileName) { } public virtual void Close() { } public void Dispose() { } protected virtual void Dispose(bool disposing) { } public virtual System.Type GetDefaultReader() { throw null; } + public virtual System.Type GetDefaultWriter() { throw null; } [System.Runtime.InteropServices.ComVisibleAttribute(false)] public virtual System.Collections.IDictionaryEnumerator GetEnumerator() { throw null; } public virtual object GetObject(string name) { throw null; } @@ -9699,6 +9953,15 @@ namespace System.Runtime public static System.Runtime.GCLargeObjectHeapCompactionMode LargeObjectHeapCompactionMode { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } [System.Security.SecurityCriticalAttribute]set { } } public static System.Runtime.GCLatencyMode LatencyMode { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } [System.Security.SecurityCriticalAttribute]set { } } } + + public sealed partial class MemoryFailPoint : System.Runtime.ConstrainedExecution.CriticalFinalizerObject, System.IDisposable + { + [System.Security.SecurityCriticalAttribute] + public MemoryFailPoint(int sizeInMegabytes) { } + [System.Security.SecuritySafeCriticalAttribute] + public void Dispose() { } + ~MemoryFailPoint() { } + } } namespace System.Runtime.CompilerServices { @@ -9757,26 +10020,6 @@ namespace System.Runtime.CompilerServices [System.Security.SecuritySafeCriticalAttribute] public void Start(ref TStateMachine stateMachine) where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { } } - [System.Runtime.InteropServices.ComVisibleAttribute(true)] - public partial class CallConvCdecl - { - internal CallConvCdecl() { } - } - [System.Runtime.InteropServices.ComVisibleAttribute(true)] - public partial class CallConvFastcall - { - internal CallConvFastcall() { } - } - [System.Runtime.InteropServices.ComVisibleAttribute(true)] - public partial class CallConvStdcall - { - internal CallConvStdcall() { } - } - [System.Runtime.InteropServices.ComVisibleAttribute(true)] - public partial class CallConvThiscall - { - internal CallConvThiscall() { } - } [System.AttributeUsageAttribute((System.AttributeTargets)(2048), Inherited=false)] public sealed partial class CallerFilePathAttribute : System.Attribute { @@ -9811,6 +10054,12 @@ namespace System.Runtime.CompilerServices { public CompilerGeneratedAttribute() { } } + [System.AttributeUsageAttribute((System.AttributeTargets)(4))] + [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public partial class CompilerGlobalScopeAttribute : System.Attribute + { + public CompilerGlobalScopeAttribute() { } + } public static partial class CompilerMarshalOverride { } @@ -9892,11 +10141,29 @@ namespace System.Runtime.CompilerServices public DecimalConstantAttribute(byte scale, byte sign, uint hi, uint mid, uint low) { } public decimal Value { get { throw null; } } } + [System.AttributeUsageAttribute((System.AttributeTargets)(1))] + public sealed partial class DefaultDependencyAttribute : System.Attribute + { + public DefaultDependencyAttribute(System.Runtime.CompilerServices.LoadHint loadHintArgument) { } + public System.Runtime.CompilerServices.LoadHint LoadHint { get { return default(System.Runtime.CompilerServices.LoadHint); } } + } + [System.AttributeUsageAttribute((System.AttributeTargets)(1), AllowMultiple=true)] + public sealed partial class DependencyAttribute : System.Attribute + { + public DependencyAttribute(string dependentAssemblyArgument, System.Runtime.CompilerServices.LoadHint loadHintArgument) { } + public string DependentAssembly { get { return default(string); } } + public System.Runtime.CompilerServices.LoadHint LoadHint { get { return default(System.Runtime.CompilerServices.LoadHint); } } + } [System.AttributeUsageAttribute((System.AttributeTargets)(1), AllowMultiple=false, Inherited=false)] public sealed partial class DisablePrivateReflectionAttribute : System.Attribute { public DisablePrivateReflectionAttribute() { } } + [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public partial class DiscardableAttribute : System.Attribute + { + public DiscardableAttribute() { } + } [System.AttributeUsageAttribute((System.AttributeTargets)(69))] public sealed partial class ExtensionAttribute : System.Attribute { @@ -9950,39 +10217,8 @@ namespace System.Runtime.CompilerServices public bool AllInternalsVisible { get { throw null; } set { } } public string AssemblyName { get { throw null; } } } - public static partial class IsBoxed - { - } - public static partial class IsByValue - { - } - public static partial class IsConst - { - } [System.Runtime.InteropServices.ComVisibleAttribute(true)] - public static partial class IsCopyConstructed - { - } - public static partial class IsExplicitlyDereferenced - { - } - public static partial class IsImplicitlyDereferenced - { - } - public static partial class IsJitIntrinsic - { - } - public static partial class IsLong - { - } - public static partial class IsSignUnspecifiedByte - { - } - public static partial class IsUdtReturn - { - } - [System.Runtime.InteropServices.ComVisibleAttribute(true)] - public static partial class IsVolatile + public static partial class IsVolatile { } [System.AttributeUsageAttribute((System.AttributeTargets)(64), Inherited=false, AllowMultiple=false)] @@ -9990,6 +10226,11 @@ namespace System.Runtime.CompilerServices { public IteratorStateMachineAttribute(System.Type stateMachineType) : base (default(System.Type)) { } } + public enum LoadHint { + Always = 1, + Default = 0, + Sometimes = 2, + } [System.Runtime.InteropServices.ComVisibleAttribute(true)] public enum MethodCodeType { @@ -10022,12 +10263,6 @@ namespace System.Runtime.CompilerServices Synchronized = 32, Unmanaged = 4, } - [System.AttributeUsageAttribute((System.AttributeTargets)(8), Inherited=true)] - [System.Runtime.InteropServices.ComVisibleAttribute(true)] - public sealed partial class NativeCppClassAttribute : System.Attribute - { - public NativeCppClassAttribute() { } - } [System.AttributeUsageAttribute((System.AttributeTargets)(1), AllowMultiple=false)] public sealed partial class ReferenceAssemblyAttribute : System.Attribute { @@ -10035,13 +10270,6 @@ namespace System.Runtime.CompilerServices public ReferenceAssemblyAttribute(string description) { } public string Description { get { throw null; } } } - [System.AttributeUsageAttribute((System.AttributeTargets)(1052), AllowMultiple=true, Inherited=false)] - [System.Runtime.InteropServices.ComVisibleAttribute(true)] - public sealed partial class RequiredAttributeAttribute : System.Attribute - { - public RequiredAttributeAttribute(System.Type requiredContract) { } - public System.Type RequiredContract { get { throw null; } } - } [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false, AllowMultiple=false)] public sealed partial class RuntimeCompatibilityAttribute : System.Attribute { @@ -10050,6 +10278,7 @@ namespace System.Runtime.CompilerServices } public static partial class RuntimeHelpers { + public static new bool Equals(object o1, object o2) { throw null; } public static int OffsetToStringData { get { throw null; } } [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] public static void EnsureSufficientExecutionStack() { } @@ -10061,12 +10290,48 @@ namespace System.Runtime.CompilerServices [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] public static void InitializeArray(System.Array array, System.RuntimeFieldHandle fldHandle) { } public static void RunClassConstructor(System.RuntimeTypeHandle type) { } + public static void RunModuleConstructor(System.ModuleHandle module) { } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute] + public static void ExecuteCodeWithGuaranteedCleanup(System.Runtime.CompilerServices.RuntimeHelpers.TryCode code, System.Runtime.CompilerServices.RuntimeHelpers.CleanupCode backoutCode, object userData) { } + [System.Security.SecurityCriticalAttribute] + public delegate void CleanupCode(object userData, bool exceptionThrown); + [System.Security.SecurityCriticalAttribute] + public delegate void TryCode(object userData); + [System.Runtime.ConstrainedExecution.ReliabilityContractAttribute((System.Runtime.ConstrainedExecution.Consistency)(3), (System.Runtime.ConstrainedExecution.Cer)(1))] + [System.Security.SecurityCriticalAttribute] + public static void PrepareConstrainedRegions() { } + [System.Runtime.ConstrainedExecution.ReliabilityContractAttribute((System.Runtime.ConstrainedExecution.Consistency)(3), (System.Runtime.ConstrainedExecution.Cer)(1))] + [System.Security.SecurityCriticalAttribute] + public static void PrepareConstrainedRegionsNoOP() { } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute] + public static void PrepareContractedDelegate(System.Delegate d) { } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute] + public static void PrepareDelegate(System.Delegate d) { } + [System.Security.SecurityCriticalAttribute] + public static void PrepareMethod(System.RuntimeMethodHandle method) { } + [System.Security.SecurityCriticalAttribute] + public static void PrepareMethod(System.RuntimeMethodHandle method, System.RuntimeTypeHandle[] instantiation) { } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Runtime.ConstrainedExecution.ReliabilityContractAttribute((System.Runtime.ConstrainedExecution.Consistency)(3), (System.Runtime.ConstrainedExecution.Cer)(1))] + [System.Security.SecurityCriticalAttribute] + public static void ProbeForSufficientStack() { } + } + public sealed partial class RuntimeWrappedException : System.Exception + { + internal RuntimeWrappedException() { } + public object WrappedException { get { return default(object); } } + [System.Security.SecurityCriticalAttribute] + public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } } [System.AttributeUsageAttribute((System.AttributeTargets)(972))] public sealed partial class SpecialNameAttribute : System.Attribute { public SpecialNameAttribute() { } } + [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)] + public sealed partial class StringFreezingAttribute : System.Attribute + { + public StringFreezingAttribute() { } + } [System.AttributeUsageAttribute((System.AttributeTargets)(64), Inherited=false, AllowMultiple=false)] public partial class StateMachineAttribute : System.Attribute { @@ -10140,6 +10405,27 @@ namespace System.Runtime.ConstrainedExecution protected CriticalFinalizerObject() { } ~CriticalFinalizerObject() { } } + + public enum Cer + { + MayFail = 1, + None = 0, + Success = 2, + } + public enum Consistency + { + MayCorruptAppDomain = 1, + MayCorruptInstance = 2, + MayCorruptProcess = 0, + WillNotCorruptState = 3, + } + [System.AttributeUsageAttribute((System.AttributeTargets)(1133), Inherited=false)] + public sealed partial class ReliabilityContractAttribute : System.Attribute + { + public ReliabilityContractAttribute(System.Runtime.ConstrainedExecution.Consistency consistencyGuarantee, System.Runtime.ConstrainedExecution.Cer cer) { } + public System.Runtime.ConstrainedExecution.Cer Cer { get { return default(System.Runtime.ConstrainedExecution.Cer); } } + public System.Runtime.ConstrainedExecution.Consistency ConsistencyGuarantee { get { return default(System.Runtime.ConstrainedExecution.Consistency); } } + } } namespace System.Runtime.ExceptionServices { @@ -10155,6 +10441,11 @@ namespace System.Runtime.ExceptionServices { public HandleProcessCorruptedStateExceptionsAttribute() { } } + public sealed partial class FirstChanceExceptionEventArgs : EventArgs + { + public FirstChanceExceptionEventArgs(Exception exception) { } + public Exception Exception { get { throw null; } } + } } namespace System.Runtime.InteropServices { @@ -10163,6 +10454,13 @@ namespace System.Runtime.InteropServices { public AllowReversePInvokeCallsAttribute() { } } + [System.AttributeUsageAttribute((System.AttributeTargets)(1029), Inherited=false)] + [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public sealed partial class AutomationProxyAttribute : System.Attribute + { + public AutomationProxyAttribute(bool val) { } + public bool Value { get { throw null; } } + } [System.Runtime.InteropServices.ComVisibleAttribute(true)] [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public partial struct ArrayWithOffset @@ -10235,6 +10533,29 @@ namespace System.Runtime.InteropServices public CoClassAttribute(System.Type coClass) { } public System.Type CoClass { get { throw null; } } } + [System.AttributeUsageAttribute((System.AttributeTargets)(10624), Inherited=false)] + [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public sealed partial class ComAliasNameAttribute : System.Attribute + { + public ComAliasNameAttribute(String val) { } + public String Value { get { throw null; } } + } + [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)] + [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public sealed partial class ComCompatibleVersionAttribute : System.Attribute + { + public ComCompatibleVersionAttribute(System.Int32 major, System.Int32 minor, System.Int32 build, System.Int32 revision) { } + public System.Int32 MajorVersion { get { throw null; } } + public System.Int32 MinorVersion { get { throw null; } } + public System.Int32 BuildNumber { get { throw null;} } + public System.Int32 RevisionNumber { get { throw null; } } + } + [System.AttributeUsageAttribute((System.AttributeTargets)(32767), Inherited=false)] + [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public sealed partial class ComConversionLossAttribute : Attribute + { + public ComConversionLossAttribute() { } + } [System.AttributeUsageAttribute((System.AttributeTargets)(4), Inherited=false)] [System.Runtime.InteropServices.ComVisibleAttribute(true)] public sealed partial class ComDefaultInterfaceAttribute : System.Attribute @@ -10289,6 +10610,12 @@ namespace System.Runtime.InteropServices PropGet = 1, PropSet = 2, } + [System.AttributeUsageAttribute((System.AttributeTargets)(64), Inherited=false)] + [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public sealed partial class ComRegisterFunctionAttribute : Attribute + { + public ComRegisterFunctionAttribute() { } + } [System.AttributeUsageAttribute((System.AttributeTargets)(4), Inherited=true)] [System.Runtime.InteropServices.ComVisibleAttribute(true)] public sealed partial class ComSourceInterfacesAttribute : System.Attribute @@ -10300,6 +10627,12 @@ namespace System.Runtime.InteropServices public ComSourceInterfacesAttribute(System.Type sourceInterface1, System.Type sourceInterface2, System.Type sourceInterface3, System.Type sourceInterface4) { } public string Value { get { throw null; } } } + [System.AttributeUsageAttribute((System.AttributeTargets)(64), Inherited=false)] + [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public sealed partial class ComUnregisterFunctionAttribute : Attribute + { + public ComUnregisterFunctionAttribute() { } + } [System.AttributeUsageAttribute((System.AttributeTargets)(5597), Inherited=false)] [System.Runtime.InteropServices.ComVisibleAttribute(true)] public sealed partial class ComVisibleAttribute : System.Attribute @@ -10418,6 +10751,7 @@ namespace System.Runtime.InteropServices public ExternalException(string message, System.Exception inner) { } public ExternalException(string message, int errorCode) { } public virtual int ErrorCode { get { throw null; } } + public override string ToString() { throw null; } } [System.AttributeUsageAttribute((System.AttributeTargets)(256), Inherited=false)] [System.Runtime.InteropServices.ComVisibleAttribute(true)] @@ -10466,17 +10800,48 @@ namespace System.Runtime.InteropServices public GuidAttribute(string guid) { } public string Value { get { throw null; } } } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public partial struct HandleRef + { + public HandleRef(object wrapper, System.IntPtr handle) { throw null;} + public System.IntPtr Handle { get { throw null; } } + public object Wrapper { get { throw null; } } + public static explicit operator System.IntPtr (System.Runtime.InteropServices.HandleRef value) { throw null; } + public static System.IntPtr ToIntPtr(System.Runtime.InteropServices.HandleRef value) { throw null; } + } [System.Runtime.InteropServices.ComVisibleAttribute(true)] public partial interface ICustomAdapter { object GetUnderlyingObject(); } + [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public partial interface ICustomFactory + { + MarshalByRefObject CreateInstance(Type serverType); + } + [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public partial interface ICustomMarshaler + { + object MarshalNativeToManaged(System.IntPtr pNativeData); + System.IntPtr MarshalManagedToNative(object ManagedObj); + void CleanUpNativeData(System.IntPtr pNativeData); + void CleanUpManagedData(object ManagedObj); + int GetNativeDataSize(); + } [System.Runtime.InteropServices.ComVisibleAttribute(false)] public partial interface ICustomQueryInterface { [System.Security.SecurityCriticalAttribute] System.Runtime.InteropServices.CustomQueryInterfaceResult GetInterface(ref System.Guid iid, out System.IntPtr ppv); } + [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)] + [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public sealed partial class ImportedFromTypeLibAttribute : System.Attribute + { + public ImportedFromTypeLibAttribute(String val) { } + public String Value { get { throw null; } } + } [System.AttributeUsageAttribute((System.AttributeTargets)(2048), Inherited=false)] [System.Runtime.InteropServices.ComVisibleAttribute(true)] public sealed partial class InAttribute : System.Attribute @@ -10514,6 +10879,13 @@ namespace System.Runtime.InteropServices Explicit = 2, Sequential = 0, } + [System.AttributeUsageAttribute((System.AttributeTargets)(64), Inherited=false)] + [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public sealed partial class LCIDConversionAttribute : System.Attribute + { + public LCIDConversionAttribute(System.Int32 val) { } + public System.Int32 Value { get { throw null; } } + } [System.Security.SecurityCriticalAttribute] public static partial class Marshal { @@ -10530,6 +10902,12 @@ namespace System.Runtime.InteropServices [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute] public static bool AreComObjectsAvailableForCleanup() { throw null; } [System.Security.SecurityCriticalAttribute] + public static object BindToMoniker(string monikerName) { throw null; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCritical] + public static void ChangeWrapperHandleStrength(object otp, bool fIsWeak) { throw null; } + [System.Security.SecurityCriticalAttribute] + public static void CleanupUnusedObjectsInCurrentContext() { throw null; } + [System.Security.SecurityCriticalAttribute] public static void Copy(byte[] source, int startIndex, System.IntPtr destination, int length) { } [System.Security.SecurityCriticalAttribute] public static void Copy(char[] source, int startIndex, System.IntPtr destination, int length) { } @@ -10583,11 +10961,17 @@ namespace System.Runtime.InteropServices [System.Security.SecurityCriticalAttribute] public static void FreeHGlobal(System.IntPtr hglobal) { } [System.Security.SecurityCriticalAttribute] + public static Guid GenerateGuidForType(System.Type type) { throw null; } + [System.Security.SecurityCritical] + public static string GenerateProgIdForType(System.Type type) { throw null; } + [System.Security.SecurityCriticalAttribute] public static System.IntPtr GetComInterfaceForObject(object o, System.Type T) { throw null; } [System.Security.SecurityCriticalAttribute] public static System.IntPtr GetComInterfaceForObject(object o, System.Type T, System.Runtime.InteropServices.CustomQueryInterfaceMode mode) { throw null; } [System.Security.SecurityCriticalAttribute] public static System.IntPtr GetComInterfaceForObject(T o) { throw null; } + [System.Security.SecurityCritical] + public static object GetComObjectData(object obj, object key) { throw null; } [System.Security.SecurityCriticalAttribute] public static System.Delegate GetDelegateForFunctionPointer(System.IntPtr ptr, System.Type t) { throw null; } [System.Security.SecurityCriticalAttribute] @@ -10602,10 +10986,14 @@ namespace System.Runtime.InteropServices public static System.IntPtr GetFunctionPointerForDelegate(System.Delegate d) { throw null; } [System.Security.SecurityCriticalAttribute] public static System.IntPtr GetFunctionPointerForDelegate(TDelegate d) { throw null; } + [System.Security.SecurityCritical] + public static System.IntPtr GetHINSTANCE(System.Reflection.Module m) { throw null; } [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute] public static int GetHRForException(System.Exception e) { throw null; } [System.Security.SecurityCriticalAttribute] public static int GetHRForLastWin32Error() { throw null; } + [System.Security.SecurityCritical] + public static System.IntPtr GetIDispatchForObject(object o) { throw null; } [System.Security.SecurityCriticalAttribute] public static System.IntPtr GetIUnknownForObject(object o) { throw null; } [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute] @@ -10626,6 +11014,8 @@ namespace System.Runtime.InteropServices public static T[] GetObjectsForNativeVariants(System.IntPtr aSrcNativeVariant, int cVars) { throw null; } [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute] public static int GetStartComSlot(System.Type t) { throw null; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCritical] + public static object GetTypedObjectForIUnknown(System.IntPtr pUnk, System.Type t) { throw null; } public static System.Type GetTypeFromCLSID(System.Guid clsid) { throw null; } [System.Security.SecurityCriticalAttribute] public static string GetTypeInfoName(System.Runtime.InteropServices.ComTypes.ITypeInfo typeInfo) { throw null; } @@ -10643,6 +11033,10 @@ namespace System.Runtime.InteropServices [System.Security.SecurityCriticalAttribute] public static string PtrToStringAnsi(System.IntPtr ptr, int len) { throw null; } [System.Security.SecurityCriticalAttribute] + public static string PtrToStringAuto(System.IntPtr ptr) { throw null; } + [System.Security.SecurityCriticalAttribute] + public static string PtrToStringAuto(System.IntPtr ptr, int len) { throw null; } + [System.Security.SecurityCriticalAttribute] public static string PtrToStringBSTR(System.IntPtr ptr) { throw null; } [System.Security.SecurityCriticalAttribute] public static string PtrToStringUni(System.IntPtr ptr) { throw null; } @@ -10702,6 +11096,8 @@ namespace System.Runtime.InteropServices public static int Release(System.IntPtr pUnk) { throw null; } [System.Security.SecurityCriticalAttribute] public static int ReleaseComObject(object o) { throw null; } + [System.Security.SecurityCritical] + public static bool SetComObjectData(object obj, object key, object data) { throw null; } [System.Runtime.InteropServices.ComVisibleAttribute(true)] public static int SizeOf(object structure) { throw null; } public static int SizeOf(System.Type t) { throw null; } @@ -10711,12 +11107,16 @@ namespace System.Runtime.InteropServices public static System.IntPtr StringToBSTR(string s) { throw null; } [System.Security.SecurityCriticalAttribute] public static System.IntPtr StringToCoTaskMemAnsi(string s) { throw null; } + [System.Security.SecurityCritical] + public static System.IntPtr StringToCoTaskMemAuto(string s) { throw null; } [System.Security.SecurityCriticalAttribute] public static System.IntPtr StringToCoTaskMemUni(string s) { throw null; } [System.Security.SecurityCriticalAttribute] public static System.IntPtr StringToCoTaskMemUTF8(string s) { throw null; } [System.Security.SecurityCriticalAttribute] public static System.IntPtr StringToHGlobalAnsi(string s) { throw null; } + [System.Security.SecurityCritical] + public static System.IntPtr StringToHGlobalAuto(string s) { throw null; } [System.Security.SecurityCriticalAttribute] public static System.IntPtr StringToHGlobalUni(string s) { throw null; } [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Runtime.InteropServices.ComVisibleAttribute(true)] @@ -10781,6 +11181,14 @@ namespace System.Runtime.InteropServices [System.Security.SecurityCriticalAttribute] public static void ZeroFreeGlobalAllocUnicode(System.IntPtr s) { } } + [System.AttributeUsageAttribute((System.AttributeTargets)(64), Inherited=false)] + [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public sealed partial class ManagedToNativeComInteropStubAttribute : System.Attribute + { + public ManagedToNativeComInteropStubAttribute(System.Type classType, System.String methodName) { } + public System.Type ClassType { get { throw null; } } + public System.String MethodName { get { throw null; } } + } [System.AttributeUsageAttribute((System.AttributeTargets)(10496), Inherited=false)] [System.Runtime.InteropServices.ComVisibleAttribute(true)] public sealed partial class MarshalAsAttribute : System.Attribute @@ -10833,12 +11241,21 @@ namespace System.Runtime.InteropServices { public PreserveSigAttribute() { } } + [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false, AllowMultiple = true)] [System.Runtime.InteropServices.ComVisibleAttribute(true)] - public static partial class RuntimeEnvironment + public sealed partial class PrimaryInteropAssemblyAttribute : System.Attribute { - [System.Security.SecuritySafeCriticalAttribute] - public static string GetRuntimeDirectory() { throw null; } + public PrimaryInteropAssemblyAttribute(System.Int32 major, System.Int32 minor) { } + public System.Int32 MajorVersion { get { throw null; } } + public System.Int32 MinorVersion { get { throw null; } } } + [System.AttributeUsageAttribute((System.AttributeTargets)(4), Inherited=false)] + [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public sealed partial class ProgIdAttribute : System.Attribute + { + public ProgIdAttribute(String val) { } + public String Value { get { throw null; } } + } [System.Runtime.InteropServices.ComVisibleAttribute(true)] public partial class SafeArrayRankMismatchException : System.SystemException { @@ -10933,6 +11350,21 @@ namespace System.Runtime.InteropServices public string Identifier { get { throw null; } } public string Scope { get { throw null; } } } + [System.AttributeUsageAttribute((System.AttributeTargets)(1024), Inherited=false)] + [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public sealed partial class TypeLibImportClassAttribute : System.Attribute + { + public TypeLibImportClassAttribute(System.Type val) { } + public String Value { get { throw null; } } + } + [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)] + [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public sealed partial class TypeLibVersionAttribute : System.Attribute + { + public TypeLibVersionAttribute(System.Int32 major, System.Int32 minor) { } + public System.Int32 MajorVersion { get { throw null; } } + public System.Int32 MinorVersion { get { throw null; } } + } [System.Runtime.InteropServices.ComVisibleAttribute(true)] public sealed partial class UnknownWrapper { @@ -11625,8 +12057,13 @@ namespace System.Runtime.Loader public static System.Runtime.Loader.AssemblyLoadContext Default { get { throw null; } } public event System.Func Resolving { add { } remove { } } public event System.Action Unloading { add { } remove { } } + public static event AssemblyLoadEventHandler AssemblyLoad { add { } remove { } } + public static event ResolveEventHandler AssemblyResolve { add { } remove { } } + public static event ResolveEventHandler TypeResolve { add { } remove { } } + public static event ResolveEventHandler ResourceResolve { add { } remove { } } public static System.Reflection.AssemblyName GetAssemblyName(string assemblyPath) { throw null; } public static System.Runtime.Loader.AssemblyLoadContext GetLoadContext(System.Reflection.Assembly assembly) { throw null; } + public static System.Reflection.Assembly[] GetLoadedAssemblies() { throw null; } protected abstract System.Reflection.Assembly Load(System.Reflection.AssemblyName assemblyName); public System.Reflection.Assembly LoadFromAssemblyName(System.Reflection.AssemblyName assemblyName) { throw null; } public System.Reflection.Assembly LoadFromAssemblyPath(string assemblyPath) { throw null; } @@ -11838,41 +12275,19 @@ namespace System.Runtime.Serialization Persistence = 8, Remoting = 16, } -} -namespace System.Runtime.Versioning -{ - [System.AttributeUsageAttribute((System.AttributeTargets)(5887), AllowMultiple=false, Inherited=false)] - public sealed partial class ComponentGuaranteesAttribute : System.Attribute - { - public ComponentGuaranteesAttribute(System.Runtime.Versioning.ComponentGuaranteesOptions guarantees) { } - public System.Runtime.Versioning.ComponentGuaranteesOptions Guarantees { get { throw null; } } - } - [System.FlagsAttribute] - public enum ComponentGuaranteesOptions - { - Exchange = 1, - None = 0, - SideBySide = 4, - Stable = 2, - } - [System.AttributeUsageAttribute((System.AttributeTargets)(480), Inherited=false)] - [System.Diagnostics.ConditionalAttribute("RESOURCE_ANNOTATION_WORK")] - public sealed partial class ResourceExposureAttribute : System.Attribute + public sealed partial class SafeSerializationEventArgs : System.EventArgs { - public ResourceExposureAttribute(System.Runtime.Versioning.ResourceScope exposureLevel) { } - public System.Runtime.Versioning.ResourceScope ResourceExposureLevel { get { throw null; } } + internal SafeSerializationEventArgs() { } + public System.Runtime.Serialization.StreamingContext StreamingContext { get { throw null; } } + public void AddSerializedState(System.Runtime.Serialization.ISafeSerializationData serializedState) { } } - [System.FlagsAttribute] - public enum ResourceScope + public partial interface ISafeSerializationData { - AppDomain = 4, - Assembly = 32, - Library = 8, - Machine = 1, - None = 0, - Private = 16, - Process = 2, + void CompleteDeserialization(object deserialized); } +} +namespace System.Runtime.Versioning +{ [System.AttributeUsageAttribute((System.AttributeTargets)(1), AllowMultiple=false, Inherited=false)] public sealed partial class TargetFrameworkAttribute : System.Attribute { @@ -11880,12 +12295,6 @@ namespace System.Runtime.Versioning public string FrameworkDisplayName { get { throw null; } set { } } public string FrameworkName { get { throw null; } } } - public static partial class VersioningHelper - { - public static string MakeVersionSafeName(string name, System.Runtime.Versioning.ResourceScope from, System.Runtime.Versioning.ResourceScope to) { throw null; } - [System.Security.SecuritySafeCriticalAttribute] - public static string MakeVersionSafeName(string name, System.Runtime.Versioning.ResourceScope from, System.Runtime.Versioning.ResourceScope to, System.Type type) { throw null; } - } } namespace System.Security { @@ -11894,23 +12303,64 @@ namespace System.Security public sealed partial class AllowPartiallyTrustedCallersAttribute : System.Attribute { public AllowPartiallyTrustedCallersAttribute() { } + public System.Security.PartialTrustVisibilityLevel PartialTrustVisibilityLevel { get { throw null; } set { } } + } + public enum PartialTrustVisibilityLevel + { + NotVisibleByDefault = 1, + VisibleToAllHosts = 0, } [System.AttributeUsageAttribute((System.AttributeTargets)(5501), AllowMultiple=false, Inherited=false)] public sealed partial class SecurityCriticalAttribute : System.Attribute { public SecurityCriticalAttribute() { } +#pragma warning disable 0618 + public SecurityCriticalAttribute(System.Security.SecurityCriticalScope scope) { } +#pragma warning restore 0618 + [System.ObsoleteAttribute("SecurityCriticalScope is only used for .NET 2.0 transparency compatibility.")] + public System.Security.SecurityCriticalScope Scope { get { throw null; } } + } + [System.ObsoleteAttribute("SecurityCriticalScope is only used for .NET 2.0 transparency compatibility.")] + public enum SecurityCriticalScope + { + Everything = 1, + Explicit = 0, } [System.Runtime.InteropServices.ComVisibleAttribute(true)] public partial class SecurityException : System.SystemException { public SecurityException() { } + protected SecurityException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } public SecurityException(string message) { } public SecurityException(string message, System.Exception inner) { } - protected SecurityException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { } - [System.Security.SecurityCriticalAttribute] + public SecurityException(string message, System.Type type) { } + public SecurityException(string message, System.Type type, string state) { } + public object Demanded { get { throw null; } set { } } + public object DenySetInstance { get { throw null; } set { } } + public System.Reflection.AssemblyName FailedAssemblyInfo { get { throw null; } set { } } + public string GrantedSet { get { throw null; } set { } } + public System.Reflection.MethodInfo Method { get { throw null; } set { } } + public string PermissionState { get { throw null; } set { } } + public System.Type PermissionType { get { throw null; } set { } } + public object PermitOnlySetInstance { get { throw null; } set { } } + public string RefusedSet { get { throw null; } set { } } + public string Url { get { throw null; } set { } } public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } public override string ToString() { throw null; } } + [System.AttributeUsageAttribute((System.AttributeTargets)(1), AllowMultiple=false)] + public sealed partial class SecurityRulesAttribute : System.Attribute + { + public SecurityRulesAttribute(System.Security.SecurityRuleSet ruleSet) { } + public System.Security.SecurityRuleSet RuleSet { get { throw null; } } + public bool SkipVerificationInFullTrust { get { throw null; } set { } } + } + public enum SecurityRuleSet : byte + { + Level1 = (byte)1, + Level2 = (byte)2, + None = (byte)0, + } [System.AttributeUsageAttribute((System.AttributeTargets)(5500), AllowMultiple=false, Inherited=false)] public sealed partial class SecuritySafeCriticalAttribute : System.Attribute { @@ -11929,6 +12379,17 @@ namespace System.Security { public SecurityTransparentAttribute() { } } + [System.AttributeUsageAttribute((System.AttributeTargets)(5501), AllowMultiple=false, Inherited=false)] + [System.ObsoleteAttribute("SecurityTreatAsSafe is only used for .NET 2.0 transparency compatibility. Please use the SecuritySafeCriticalAttribute instead.")] + public sealed partial class SecurityTreatAsSafeAttribute : System.Attribute + { + public SecurityTreatAsSafeAttribute() { } + } + [System.AttributeUsageAttribute((System.AttributeTargets)(5188), AllowMultiple=true, Inherited=false)] + public sealed partial class SuppressUnmanagedCodeSecurityAttribute : System.Attribute + { + public SuppressUnmanagedCodeSecurityAttribute() { } + } [System.AttributeUsageAttribute((System.AttributeTargets)(2), AllowMultiple=true, Inherited=false)] [System.Runtime.InteropServices.ComVisibleAttribute(true)] public sealed partial class UnverifiableCodeAttribute : System.Attribute @@ -12646,6 +13107,12 @@ namespace System.Threading public System.Threading.Mutex Mutex { get { throw null; } } public int MutexIndex { get { throw null; } } } + public enum ApartmentState + { + MTA = 1, + STA = 0, + Unknown = 2, + } public sealed partial class AsyncLocal { public AsyncLocal() { } @@ -12890,7 +13357,9 @@ namespace System.Threading public static void TryEnter(object obj, System.TimeSpan timeout, ref bool lockTaken) { } public static bool Wait(object obj) { throw null; } public static bool Wait(object obj, int millisecondsTimeout) { throw null; } + public static bool Wait(object obj, int millisecondsTimeout, bool exitContext) { throw null; } public static bool Wait(object obj, System.TimeSpan timeout) { throw null; } + public static bool Wait(object obj, System.TimeSpan timeout, bool exitContext) { throw null; } } [System.Runtime.InteropServices.ComVisibleAttribute(true)] public sealed partial class Mutex : System.Threading.WaitHandle @@ -13053,44 +13522,47 @@ namespace System.Threading } [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))] [System.Runtime.InteropServices.ComVisibleAttribute(true)] - public sealed partial class Thread : System.Runtime.ConstrainedExecution.CriticalFinalizerObject + public sealed partial class Thread : Internal.Runtime.Augments.RuntimeThread { [System.Security.SecuritySafeCriticalAttribute] public Thread(System.Threading.ParameterizedThreadStart start) { } [System.Security.SecuritySafeCriticalAttribute] public Thread(System.Threading.ThreadStart start) { } public System.Globalization.CultureInfo CurrentCulture { get { throw null; } [System.Security.SecuritySafeCriticalAttribute]set { } } - public static System.Threading.Thread CurrentThread { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } } + public static new System.Threading.Thread CurrentThread { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } } public System.Globalization.CultureInfo CurrentUICulture { get { throw null; } [System.Security.SecuritySafeCriticalAttribute]set { } } - public bool IsAlive { [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]get { throw null; } } - public bool IsBackground { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } [System.Security.SecuritySafeCriticalAttribute]set { } } - public int ManagedThreadId { [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]get { throw null; } } - public string Name { get { throw null; } [System.Security.SecuritySafeCriticalAttribute]set { } } - public System.Threading.ThreadState ThreadState { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } } + public new int ManagedThreadId { [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]get { throw null; } } + public new string Name { get { throw null; } [System.Security.SecuritySafeCriticalAttribute]set { } } ~Thread() { } [System.Security.SecuritySafeCriticalAttribute] public static System.AppDomain GetDomain() { throw null; } [System.Runtime.InteropServices.ComVisibleAttribute(false)] public override int GetHashCode() { throw null; } - [System.Security.SecuritySafeCriticalAttribute] - public void Join() { } - [System.Security.SecuritySafeCriticalAttribute] - public bool Join(int millisecondsTimeout) { throw null; } [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute] public static void MemoryBarrier() { } [System.Security.SecuritySafeCriticalAttribute] - public static void Sleep(int millisecondsTimeout) { } + public static new void Sleep(int millisecondsTimeout) { } public static void Sleep(System.TimeSpan timeout) { } [System.Security.SecuritySafeCriticalAttribute] - public static void SpinWait(int iterations) { } - [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public void Start() { } - [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public void Start(object parameter) { } + public static new void SpinWait(int iterations) { } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] + public new void Start() { } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] + public new void Start(object parameter) { } } [System.Runtime.InteropServices.ComVisibleAttribute(true)] public sealed partial class ThreadAbortException : System.SystemException { internal ThreadAbortException() { } } + [System.Runtime.InteropServices.ComVisibleAttribute(true)] + public partial class ThreadInterruptedException : System.SystemException + { + public ThreadInterruptedException() { } + public ThreadInterruptedException(string message) { } + public ThreadInterruptedException(string message, System.Exception innerException) { } + protected ThreadInterruptedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } + } [System.Diagnostics.DebuggerDisplayAttribute("IsValueCreated={IsValueCreated}, Value={ValueForDebugDisplay}, Count={ValuesCountForDebugDisplay}")] public partial class ThreadLocal : System.IDisposable { @@ -13136,6 +13608,14 @@ namespace System.Threading [System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.Demand, ControlThread=true)] public static bool SetMinThreads(int workerThreads, int completionPortThreads) { throw null; } } + public enum ThreadPriority + { + AboveNormal = 3, + BelowNormal = 1, + Highest = 4, + Lowest = 0, + Normal = 2, + } [System.Runtime.InteropServices.ComVisibleAttribute(true)] public delegate void ThreadStart(); public sealed partial class ThreadStartException : System.SystemException @@ -13276,20 +13756,13 @@ namespace System.Threading public virtual bool WaitOne(System.TimeSpan timeout, bool exitContext) { return default(bool); } } [System.Runtime.InteropServices.ComVisibleAttribute(false)] - public partial class WaitHandleCannotBeOpenedException : System.Exception + public partial class WaitHandleCannotBeOpenedException : System.ApplicationException { public WaitHandleCannotBeOpenedException() { } public WaitHandleCannotBeOpenedException(string message) { } public WaitHandleCannotBeOpenedException(string message, System.Exception innerException) { } protected WaitHandleCannotBeOpenedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { } } - public static partial class WaitHandleExtensions - { - [System.Security.SecurityCriticalAttribute] - public static Microsoft.Win32.SafeHandles.SafeWaitHandle GetSafeWaitHandle(this System.Threading.WaitHandle waitHandle) { throw null; } - [System.Security.SecurityCriticalAttribute] - public static void SetSafeWaitHandle(this System.Threading.WaitHandle waitHandle, Microsoft.Win32.SafeHandles.SafeWaitHandle value) { } - } [System.Runtime.InteropServices.ComVisibleAttribute(true)] public delegate void WaitOrTimerCallback(object state, bool timedOut); } diff --git a/src/mscorlib/src/Internal/Runtime/Augments/EnvironmentAugments.cs b/src/mscorlib/src/Internal/Runtime/Augments/EnvironmentAugments.cs index 2810468..b22310e 100644 --- a/src/mscorlib/src/Internal/Runtime/Augments/EnvironmentAugments.cs +++ b/src/mscorlib/src/Internal/Runtime/Augments/EnvironmentAugments.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections; namespace Internal.Runtime.Augments { @@ -17,5 +18,11 @@ namespace Internal.Runtime.Augments public static bool HasShutdownStarted => Environment.HasShutdownStarted; public static string StackTrace => Environment.StackTrace; public static int TickCount => Environment.TickCount; + public static string GetEnvironmentVariable(string variable) => Environment.GetEnvironmentVariable(variable); + public static string GetEnvironmentVariable(string variable, EnvironmentVariableTarget target) => Environment.GetEnvironmentVariable(variable, target); + public static IDictionary GetEnvironmentVariables() => Environment.GetEnvironmentVariables(); + public static IDictionary GetEnvironmentVariables(EnvironmentVariableTarget target) => Environment.GetEnvironmentVariables(target); + public static void SetEnvironmentVariable(string variable, string value) => Environment.SetEnvironmentVariable(variable, value); + public static void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target) => Environment.SetEnvironmentVariable(variable, value, target); } } diff --git a/src/mscorlib/src/Internal/Runtime/Augments/RuntimeThread.cs b/src/mscorlib/src/Internal/Runtime/Augments/RuntimeThread.cs new file mode 100644 index 0000000..3aafe01 --- /dev/null +++ b/src/mscorlib/src/Internal/Runtime/Augments/RuntimeThread.cs @@ -0,0 +1,198 @@ +// 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.Diagnostics; +using System.Diagnostics.Contracts; +using System.Runtime.CompilerServices; +using System.Runtime.ConstrainedExecution; +using System.Runtime.InteropServices; +using System.Security; +using System.Security.Permissions; +using System.Threading; + +namespace Internal.Runtime.Augments +{ + public class RuntimeThread : CriticalFinalizerObject + { + public static RuntimeThread Create(ThreadStart start) => new Thread(start); + public static RuntimeThread Create(ThreadStart start, int maxStackSize) => new Thread(start, maxStackSize); + public static RuntimeThread Create(ParameterizedThreadStart start) => new Thread(start); + public static RuntimeThread Create(ParameterizedThreadStart start, int maxStackSize) => new Thread(start, maxStackSize); + + private Thread AsThread() + { + Debug.Assert(this is Thread); + return (Thread)this; + } + + public static RuntimeThread CurrentThread => Thread.CurrentThread; + + /*========================================================================= + ** Returns true if the thread has been started and is not dead. + =========================================================================*/ + public extern bool IsAlive + { + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + + /*========================================================================= + ** Return whether or not this thread is a background thread. Background + ** threads do not affect when the Execution Engine shuts down. + ** + ** Exceptions: ThreadStateException if the thread is dead. + =========================================================================*/ + public bool IsBackground + { + get { return IsBackgroundNative(); } + set { SetBackgroundNative(value); } + } + + [MethodImpl(MethodImplOptions.InternalCall)] + private extern bool IsBackgroundNative(); + + [MethodImpl(MethodImplOptions.InternalCall)] + private extern void SetBackgroundNative(bool isBackground); + + /*========================================================================= + ** Returns true if the thread is a threadpool thread. + =========================================================================*/ + public extern bool IsThreadPoolThread + { + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + + public int ManagedThreadId => AsThread().ManagedThreadId; + public string Name { get { return AsThread().Name; } set { AsThread().Name = value; } } + + /*========================================================================= + ** Returns the priority of the thread. + ** + ** Exceptions: ThreadStateException if the thread is dead. + =========================================================================*/ + public ThreadPriority Priority + { + get { return (ThreadPriority)GetPriorityNative(); } + set { SetPriorityNative((int)value); } + } + + [MethodImpl(MethodImplOptions.InternalCall)] + private extern int GetPriorityNative(); + + [MethodImpl(MethodImplOptions.InternalCall)] + private extern void SetPriorityNative(int priority); + + /*========================================================================= + ** Return the thread state as a consistent set of bits. This is more + ** general then IsAlive or IsBackground. + =========================================================================*/ + public ThreadState ThreadState + { + get { return (ThreadState)GetThreadStateNative(); } + } + + [MethodImpl(MethodImplOptions.InternalCall)] + private extern int GetThreadStateNative(); + + public ApartmentState GetApartmentState() + { +#if FEATURE_COMINTEROP_APARTMENT_SUPPORT + return (ApartmentState)GetApartmentStateNative(); +#else // !FEATURE_COMINTEROP_APARTMENT_SUPPORT + Debug.Assert(false); // the Thread class in CoreFX should have handled this case + return ApartmentState.MTA; +#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT + } + + /*========================================================================= + ** An unstarted thread can be marked to indicate that it will host a + ** single-threaded or multi-threaded apartment. + =========================================================================*/ + public bool TrySetApartmentState(ApartmentState state) + { +#if FEATURE_COMINTEROP_APARTMENT_SUPPORT + return SetApartmentStateHelper(state, false); +#else // !FEATURE_COMINTEROP_APARTMENT_SUPPORT + Debug.Assert(false); // the Thread class in CoreFX should have handled this case + return false; +#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT + } + +#if FEATURE_COMINTEROP_APARTMENT_SUPPORT + internal bool SetApartmentStateHelper(ApartmentState state, bool fireMDAOnMismatch) + { + ApartmentState retState = (ApartmentState)SetApartmentStateNative((int)state, fireMDAOnMismatch); + + // Special case where we pass in Unknown and get back MTA. + // Once we CoUninitialize the thread, the OS will still + // report the thread as implicitly in the MTA if any + // other thread in the process is CoInitialized. + if ((state == System.Threading.ApartmentState.Unknown) && (retState == System.Threading.ApartmentState.MTA)) + return true; + + if (retState != state) + return false; + + return true; + } + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern int GetApartmentStateNative(); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern int SetApartmentStateNative(int state, bool fireMDAOnMismatch); +#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT + +#if FEATURE_COMINTEROP + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + [MethodImpl(MethodImplOptions.InternalCall)] + public extern void DisableComObjectEagerCleanup(); +#else // !FEATURE_COMINTEROP + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public void DisableComObjectEagerCleanup() + { + Debug.Assert(false); // the Thread class in CoreFX should have handled this case + } +#endif // FEATURE_COMINTEROP + + /*========================================================================= + ** Interrupts a thread that is inside a Wait(), Sleep() or Join(). If that + ** thread is not currently blocked in that manner, it will be interrupted + ** when it next begins to block. + =========================================================================*/ +#pragma warning disable 618 // obsolete types: SecurityPermissionAttribute, SecurityAction +#pragma warning restore 618 // obsolete types: SecurityPermissionAttribute, SecurityAction + public void Interrupt() => InterruptInternal(); + + // Internal helper (since we can't place security demands on + // ecalls/fcalls). + [MethodImpl(MethodImplOptions.InternalCall)] + private extern void InterruptInternal(); + + /*========================================================================= + ** Waits for the thread to die or for timeout milliseconds to elapse. + ** Returns true if the thread died, or false if the wait timed out. If + ** Timeout.Infinite is given as the parameter, no timeout will occur. + ** + ** Exceptions: ArgumentException if timeout < 0. + ** ThreadInterruptedException if the thread is interrupted while waiting. + ** ThreadStateException if the thread has not been started yet. + =========================================================================*/ + public void Join() => JoinInternal(Timeout.Infinite); + + public bool Join(int millisecondsTimeout) => JoinInternal(millisecondsTimeout); + + [MethodImpl(MethodImplOptions.InternalCall)] + private extern bool JoinInternal(int millisecondsTimeout); + + public static void Sleep(int millisecondsTimeout) => Thread.Sleep(millisecondsTimeout); + public static void SpinWait(int iterations) => Thread.SpinWait(iterations); + public static bool Yield() => Thread.Yield(); + + public void Start() => AsThread().Start(); + public void Start(object parameter) => AsThread().Start(parameter); + } +} diff --git a/src/mscorlib/src/Microsoft/Win32/OAVariantLib.cs b/src/mscorlib/src/Microsoft/Win32/OAVariantLib.cs index 118c69b..6c2c6e9 100644 --- a/src/mscorlib/src/Microsoft/Win32/OAVariantLib.cs +++ b/src/mscorlib/src/Microsoft/Win32/OAVariantLib.cs @@ -73,13 +73,12 @@ namespace Microsoft.Win32 { * Variant and the types that CLR supports explicitly in the * CLR Variant class. */ - [System.Security.SecurityCritical] // auto-generated internal static Variant ChangeType(Variant source, Type targetClass, short options, CultureInfo culture) { if (targetClass == null) - throw new ArgumentNullException("targetClass"); + throw new ArgumentNullException(nameof(targetClass)); if (culture == null) - throw new ArgumentNullException("culture"); + throw new ArgumentNullException(nameof(culture)); Variant result = new Variant (); ChangeTypeEx(ref result, ref source, #if FEATURE_USE_LCID @@ -125,7 +124,6 @@ namespace Microsoft.Win32 { #region Private FCalls - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void ChangeTypeEx(ref Variant result, ref Variant source, int lcid, IntPtr typeHandle, int cvType, short flags); diff --git a/src/mscorlib/src/Microsoft/Win32/Registry.cs b/src/mscorlib/src/Microsoft/Win32/Registry.cs index 4faf29d..3ee5f46 100644 --- a/src/mscorlib/src/Microsoft/Win32/Registry.cs +++ b/src/mscorlib/src/Microsoft/Win32/Registry.cs @@ -17,7 +17,6 @@ namespace Microsoft.Win32 { //This class contains only static members and does not need to be serializable. [ComVisible(true)] public static class Registry { - [System.Security.SecuritySafeCritical] // auto-generated static Registry() { } @@ -63,17 +62,6 @@ namespace Microsoft.Win32 { * This is where current configuration information is stored. */ public static readonly RegistryKey CurrentConfig = RegistryKey.GetBaseKey(RegistryKey.HKEY_CURRENT_CONFIG); - -#if !FEATURE_CORECLR - /** - * Dynamic Data Root Key. - * - * LEGACY: This is where dynamic performance data is stored on Win9X. - * This does not exist on NT. - */ - [Obsolete("The DynData registry key only works on Win9x, which is no longer supported by the CLR. On NT-based operating systems, use the PerformanceData registry key instead.")] - public static readonly RegistryKey DynData = RegistryKey.GetBaseKey(RegistryKey.HKEY_DYN_DATA); -#endif // // Following function will parse a keyName and returns the basekey for it. @@ -81,10 +69,9 @@ namespace Microsoft.Win32 { // If the keyName is not valid, we will throw ArgumentException. // The return value shouldn't be null. // - [System.Security.SecurityCritical] // auto-generated private static RegistryKey GetBaseKeyFromKeyName(string keyName, out string subKeyName) { if( keyName == null) { - throw new ArgumentNullException("keyName"); + throw new ArgumentNullException(nameof(keyName)); } string basekeyName; @@ -116,13 +103,8 @@ namespace Microsoft.Win32 { case "HKEY_CURRENT_CONFIG": basekey = Registry.CurrentConfig; break; -#if !FEATURE_CORECLR - case "HKEY_DYN_DATA": - basekey = RegistryKey.GetBaseKey(RegistryKey.HKEY_DYN_DATA); - break; -#endif default: - throw new ArgumentException(Environment.GetResourceString("Arg_RegInvalidKeyName", "keyName")); + throw new ArgumentException(Environment.GetResourceString("Arg_RegInvalidKeyName", nameof(keyName))); } if( i == -1 || i == keyName.Length) { subKeyName = string.Empty; @@ -133,7 +115,6 @@ namespace Microsoft.Win32 { return basekey; } - [System.Security.SecuritySafeCritical] // auto-generated public static object GetValue(string keyName, string valueName, object defaultValue ) { string subKeyName; RegistryKey basekey = GetBaseKeyFromKeyName(keyName, out subKeyName); @@ -154,7 +135,6 @@ namespace Microsoft.Win32 { SetValue(keyName, valueName, value, RegistryValueKind.Unknown); } - [System.Security.SecuritySafeCritical] // auto-generated public static void SetValue(string keyName, string valueName, object value, RegistryValueKind valueKind ) { string subKeyName; RegistryKey basekey = GetBaseKeyFromKeyName(keyName, out subKeyName); diff --git a/src/mscorlib/src/Microsoft/Win32/RegistryKey.cs b/src/mscorlib/src/Microsoft/Win32/RegistryKey.cs index dcf31dc..ff678f1 100644 --- a/src/mscorlib/src/Microsoft/Win32/RegistryKey.cs +++ b/src/mscorlib/src/Microsoft/Win32/RegistryKey.cs @@ -49,15 +49,12 @@ */ -namespace Microsoft.Win32 { - +namespace Microsoft.Win32 +{ using System; using System.Collections; using System.Collections.Generic; using System.Security; -#if FEATURE_MACL - using System.Security.AccessControl; -#endif using System.Security.Permissions; using System.Text; using System.Threading; @@ -74,7 +71,7 @@ namespace Microsoft.Win32 { * Registry hive values. Useful only for GetRemoteBaseKey */ [Serializable] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public enum RegistryHive { ClassesRoot = unchecked((int)0x80000000), @@ -83,9 +80,6 @@ namespace Microsoft.Win32 { Users = unchecked((int)0x80000003), PerformanceData = unchecked((int)0x80000004), CurrentConfig = unchecked((int)0x80000005), -#if !FEATURE_CORECLR - DynData = unchecked((int)0x80000006), -#endif } /** @@ -96,13 +90,8 @@ namespace Microsoft.Win32 { * @security(checkDllCalls=off) * @security(checkClassLinking=on) */ -#if FEATURE_REMOTING [ComVisible(true)] public sealed class RegistryKey : MarshalByRefObject, IDisposable -#else - [ComVisible(true)] - public sealed class RegistryKey : IDisposable -#endif { // We could use const here, if C# supported ELEMENT_TYPE_I fully. @@ -112,9 +101,6 @@ namespace Microsoft.Win32 { internal static readonly IntPtr HKEY_USERS = new IntPtr(unchecked((int)0x80000003)); internal static readonly IntPtr HKEY_PERFORMANCE_DATA = new IntPtr(unchecked((int)0x80000004)); internal static readonly IntPtr HKEY_CURRENT_CONFIG = new IntPtr(unchecked((int)0x80000005)); -#if !FEATURE_CORECLR - internal static readonly IntPtr HKEY_DYN_DATA = new IntPtr(unchecked((int)0x80000006)); -#endif // Dirty indicates that we have munged data that should be potentially // written to disk. @@ -142,9 +128,6 @@ namespace Microsoft.Win32 { "HKEY_USERS", "HKEY_PERFORMANCE_DATA", "HKEY_CURRENT_CONFIG", -#if !FEATURE_CORECLR - "HKEY_DYN_DATA" -#endif }; // MSDN defines the following limits for registry key names & values: @@ -154,7 +137,6 @@ namespace Microsoft.Win32 { private const int MaxKeyLength = 255; private const int MaxValueLength = 16383; - [System.Security.SecurityCritical] // auto-generated private volatile SafeRegistryHandle hkey = null; private volatile int state = 0; private volatile String keyName; @@ -188,7 +170,6 @@ namespace Microsoft.Win32 { * This key is bound to hkey, if writable is false then no write operations * will be allowed. */ - [System.Security.SecurityCritical] // auto-generated private RegistryKey(SafeRegistryHandle hkey, bool writable, RegistryView view) : this(hkey, writable, false, false, false, view) { } @@ -203,7 +184,6 @@ namespace Microsoft.Win32 { * The remoteKey flag when set to true indicates that we are dealing with registry entries * on a remote machine and requires the program making these calls to have full trust. */ - [System.Security.SecurityCritical] // auto-generated private RegistryKey(SafeRegistryHandle hkey, bool writable, bool systemkey, bool remoteKey, bool isPerfData, RegistryView view) { this.hkey = hkey; this.keyName = ""; @@ -227,7 +207,6 @@ namespace Microsoft.Win32 { Dispose(true); } - [System.Security.SecuritySafeCritical] // auto-generated private void Dispose(bool disposing) { if (hkey != null) { @@ -260,7 +239,6 @@ namespace Microsoft.Win32 { } } - [System.Security.SecuritySafeCritical] // auto-generated public void Flush() { if (hkey != null) { if (IsDirty()) { @@ -269,11 +247,7 @@ namespace Microsoft.Win32 { } } -#if FEATURE_CORECLR void IDisposable.Dispose() -#else - public void Dispose() -#endif { Dispose(true); } @@ -314,22 +288,6 @@ namespace Microsoft.Win32 { return CreateSubKeyInternal(subkey, writable ? RegistryKeyPermissionCheck.ReadWriteSubTree : RegistryKeyPermissionCheck.ReadSubTree, null, options); } - -#if FEATURE_MACL - [ComVisible(false)] - public unsafe RegistryKey CreateSubKey(String subkey, RegistryKeyPermissionCheck permissionCheck, RegistrySecurity registrySecurity) - { - return CreateSubKeyInternal(subkey, permissionCheck, registrySecurity, RegistryOptions.None); - } - - [ComVisible(false)] - public unsafe RegistryKey CreateSubKey(String subkey, RegistryKeyPermissionCheck permissionCheck, RegistryOptions registryOptions, RegistrySecurity registrySecurity) - { - return CreateSubKeyInternal(subkey, permissionCheck, registrySecurity, registryOptions); - } -#endif - - [System.Security.SecuritySafeCritical] // auto-generated [ComVisible(false)] private unsafe RegistryKey CreateSubKeyInternal(String subkey, RegistryKeyPermissionCheck permissionCheck, object registrySecurityObj, RegistryOptions registryOptions) { @@ -351,23 +309,9 @@ namespace Microsoft.Win32 { } CheckPermission(RegistryInternalCheck.CheckSubKeyCreatePermission, subkey, false, RegistryKeyPermissionCheck.Default); - + Win32Native.SECURITY_ATTRIBUTES secAttrs = null; -#if FEATURE_MACL - RegistrySecurity registrySecurity = (RegistrySecurity)registrySecurityObj; - // For ACL's, get the security descriptor from the RegistrySecurity. - if (registrySecurity != null) { - secAttrs = new Win32Native.SECURITY_ATTRIBUTES(); - secAttrs.nLength = (int)Marshal.SizeOf(secAttrs); - - byte[] sd = registrySecurity.GetSecurityDescriptorBinaryForm(); - // We allocate memory on the stack to improve the speed. - // So this part of code can't be refactored into a method. - byte* pSecDescriptor = stackalloc byte[sd.Length]; - Buffer.Memcpy(pSecDescriptor, 0, sd, 0, sd.Length); - secAttrs.pSecurityDescriptor = pSecDescriptor; - } -#endif + int disposition = 0; // By default, the new key will be writable. @@ -412,7 +356,6 @@ namespace Microsoft.Win32 { DeleteSubKey(subkey, true); } - [System.Security.SecuritySafeCritical] // auto-generated public void DeleteSubKey(String subkey, bool throwOnMissingSubKey) { ValidateKeyName(subkey); EnsureWriteable(); @@ -466,7 +409,6 @@ namespace Microsoft.Win32 { DeleteSubKeyTree(subkey, true /*throwOnMissingSubKey*/); } - [System.Security.SecuritySafeCritical] // auto-generated [ComVisible(false)] public void DeleteSubKeyTree(String subkey, Boolean throwOnMissingSubKey) { ValidateKeyName(subkey); @@ -514,7 +456,6 @@ namespace Microsoft.Win32 { // An internal version which does no security checks or argument checking. Skipping the // security checks should give us a slight perf gain on large trees. - [System.Security.SecurityCritical] // auto-generated private void DeleteSubKeyTreeInternal(string subkey) { RegistryKey key = InternalOpenSubKey(subkey, true); if (key != null) { @@ -541,7 +482,7 @@ namespace Microsoft.Win32 { if (ret!=0) Win32Error(ret, null); } else { - ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSubKeyAbsent); + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSubKeyAbsent); } } @@ -554,7 +495,6 @@ namespace Microsoft.Win32 { DeleteValue(name, true); } - [System.Security.SecuritySafeCritical] // auto-generated public void DeleteValue(String name, bool throwOnMissingValue) { EnsureWriteable(); CheckPermission(RegistryInternalCheck.CheckValueWritePermission, name, false, RegistryKeyPermissionCheck.Default); @@ -592,12 +532,10 @@ namespace Microsoft.Win32 { * * @return the RegistryKey requested. */ - [System.Security.SecurityCritical] // auto-generated internal static RegistryKey GetBaseKey(IntPtr hKey) { return GetBaseKey(hKey, RegistryView.Default); } - [System.Security.SecurityCritical] // auto-generated internal static RegistryKey GetBaseKey(IntPtr hKey, RegistryView view) { int index = ((int)hKey) & 0x0FFFFFFF; @@ -615,7 +553,6 @@ namespace Microsoft.Win32 { } - [System.Security.SecuritySafeCritical] // auto-generated [ComVisible(false)] public static RegistryKey OpenBaseKey(RegistryHive hKey, RegistryView view) { ValidateKeyView(view); @@ -645,11 +582,10 @@ namespace Microsoft.Win32 { return OpenRemoteBaseKey(hKey, machineName, RegistryView.Default); } - [System.Security.SecuritySafeCritical] // auto-generated [ComVisible(false)] public static RegistryKey OpenRemoteBaseKey(RegistryHive hKey, String machineName, RegistryView view) { if (machineName==null) - throw new ArgumentNullException("machineName"); + throw new ArgumentNullException(nameof(machineName)); int index = (int)hKey & 0x0FFFFFFF; if (index < 0 || index >= hkeyNames.Length || ((int)hKey & 0xFFFFFFF0) != 0x80000000) { throw new ArgumentException(Environment.GetResourceString("Arg_RegKeyOutOfRange")); @@ -687,11 +623,6 @@ namespace Microsoft.Win32 { * * @return the Subkey requested, or null if the operation failed. */ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif public RegistryKey OpenSubKey(string name, bool writable ) { ValidateKeyName(name); EnsureNotDisposed(); @@ -722,63 +653,8 @@ namespace Microsoft.Win32 { return null; } -#if FEATURE_MACL - - [System.Security.SecuritySafeCritical] // auto-generated - [ComVisible(false)] - public RegistryKey OpenSubKey(String name, RegistryKeyPermissionCheck permissionCheck) { - ValidateKeyMode(permissionCheck); - return InternalOpenSubKey(name, permissionCheck, GetRegistryKeyAccess(permissionCheck)); - } - - [System.Security.SecuritySafeCritical] - [ComVisible(false)] - public RegistryKey OpenSubKey(String name, RegistryRights rights) - { - return InternalOpenSubKey(name, this.checkMode, (int)rights); - } - - [System.Security.SecuritySafeCritical] // auto-generated - [ComVisible(false)] - public RegistryKey OpenSubKey(String name, RegistryKeyPermissionCheck permissionCheck, RegistryRights rights) { - return InternalOpenSubKey(name, permissionCheck, (int)rights); - } - - [System.Security.SecurityCritical] // auto-generated - private RegistryKey InternalOpenSubKey(String name, RegistryKeyPermissionCheck permissionCheck, int rights) { - ValidateKeyName(name); - ValidateKeyMode(permissionCheck); - - ValidateKeyRights(rights); - - EnsureNotDisposed(); - name = FixupName(name); // Fixup multiple slashes to a single slash - - CheckPermission(RegistryInternalCheck.CheckOpenSubKeyPermission, name, false, permissionCheck); - CheckPermission(RegistryInternalCheck.CheckSubTreePermission, name, false, permissionCheck); - SafeRegistryHandle result = null; - int ret = Win32Native.RegOpenKeyEx(hkey, name, 0, (rights | (int)regView), out result); - if (ret == 0 && !result.IsInvalid) { - RegistryKey key = new RegistryKey(result, (permissionCheck == RegistryKeyPermissionCheck.ReadWriteSubTree), false, remoteKey, false, regView); - key.keyName = keyName + "\\" + name; - key.checkMode = permissionCheck; - return key; - } - - // Return null if we didn't find the key. - if (ret == Win32Native.ERROR_ACCESS_DENIED || ret == Win32Native.ERROR_BAD_IMPERSONATION_LEVEL) { - // We need to throw SecurityException here for compatiblity reason, - // although UnauthorizedAccessException will make more sense. - ThrowHelper.ThrowSecurityException(ExceptionResource.Security_RegistryPermission); - } - - return null; - } -#endif - // This required no security checks. This is to get around the Deleting SubKeys which only require // write permission. They call OpenSubKey which required read. Now instead call this function w/o security checks - [System.Security.SecurityCritical] // auto-generated internal RegistryKey InternalOpenSubKey(String name, bool writable) { ValidateKeyName(name); EnsureNotDisposed(); @@ -805,9 +681,6 @@ namespace Microsoft.Win32 { * * @return the Subkey requested, or null if the operation failed. */ -#if FEATURE_CORECLR - [System.Security.SecurityCritical] -#endif public RegistryKey OpenSubKey(String name) { return OpenSubKey(name, false); } @@ -818,7 +691,6 @@ namespace Microsoft.Win32 { * @return a count of subkeys. */ public int SubKeyCount { - [System.Security.SecuritySafeCritical] // auto-generated get { CheckPermission(RegistryInternalCheck.CheckKeyReadPermission, null, false, RegistryKeyPermissionCheck.Default); return InternalSubKeyCount(); @@ -827,90 +699,12 @@ namespace Microsoft.Win32 { [ComVisible(false)] public RegistryView View { - [System.Security.SecuritySafeCritical] get { EnsureNotDisposed(); return regView; } } -#if !FEATURE_CORECLR - [ComVisible(false)] - public SafeRegistryHandle Handle { - [System.Security.SecurityCritical] - [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] - get { - EnsureNotDisposed(); - int ret = Win32Native.ERROR_INVALID_HANDLE; - if (IsSystemKey()) { - IntPtr baseKey = (IntPtr)0; - switch (keyName) { - case "HKEY_CLASSES_ROOT": - baseKey = HKEY_CLASSES_ROOT; - break; - case "HKEY_CURRENT_USER": - baseKey = HKEY_CURRENT_USER; - break; - case "HKEY_LOCAL_MACHINE": - baseKey = HKEY_LOCAL_MACHINE; - break; - case "HKEY_USERS": - baseKey = HKEY_USERS; - break; - case "HKEY_PERFORMANCE_DATA": - baseKey = HKEY_PERFORMANCE_DATA; - break; - case "HKEY_CURRENT_CONFIG": - baseKey = HKEY_CURRENT_CONFIG; - break; - case "HKEY_DYN_DATA": - baseKey = HKEY_DYN_DATA; - break; - default: - Win32Error(ret, null); - break; - } - // open the base key so that RegistryKey.Handle will return a valid handle - SafeRegistryHandle result; - ret = Win32Native.RegOpenKeyEx(baseKey, - null, - 0, - GetRegistryKeyAccess(IsWritable()) | (int)regView, - out result); - - if (ret == 0 && !result.IsInvalid) { - return result; - } - else { - Win32Error(ret, null); - } - } - else { - return hkey; - } - throw new IOException(Win32Native.GetMessage(ret), ret); - } - } - - [System.Security.SecurityCritical] - [ComVisible(false)] - [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] - public static RegistryKey FromHandle(SafeRegistryHandle handle) { - return FromHandle(handle, RegistryView.Default); - } - - [System.Security.SecurityCritical] - [ComVisible(false)] - [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] - public static RegistryKey FromHandle(SafeRegistryHandle handle, RegistryView view) { - if (handle == null) throw new ArgumentNullException("handle"); - ValidateKeyView(view); - - return new RegistryKey(handle, true /* isWritable */, view); - } -#endif - - [System.Security.SecurityCritical] // auto-generated internal int InternalSubKeyCount() { EnsureNotDisposed(); @@ -939,17 +733,11 @@ namespace Microsoft.Win32 { * * @return all subkey names. */ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif public String[] GetSubKeyNames() { CheckPermission(RegistryInternalCheck.CheckKeyReadPermission, null, false, RegistryKeyPermissionCheck.Default); return InternalGetSubKeyNames(); } - [System.Security.SecurityCritical] // auto-generated internal unsafe String[] InternalGetSubKeyNames() { EnsureNotDisposed(); int subkeys = InternalSubKeyCount(); @@ -988,14 +776,12 @@ namespace Microsoft.Win32 { * @return a count of values. */ public int ValueCount { - [System.Security.SecuritySafeCritical] // auto-generated get { CheckPermission(RegistryInternalCheck.CheckKeyReadPermission, null, false, RegistryKeyPermissionCheck.Default); return InternalValueCount(); } } - [System.Security.SecurityCritical] // auto-generated internal int InternalValueCount() { EnsureNotDisposed(); int values = 0; @@ -1022,7 +808,6 @@ namespace Microsoft.Win32 { * * @return all value names. */ - [System.Security.SecuritySafeCritical] // auto-generated public unsafe String[] GetValueNames() { CheckPermission(RegistryInternalCheck.CheckKeyReadPermission, null, false, RegistryKeyPermissionCheck.Default); EnsureNotDisposed(); @@ -1073,7 +858,6 @@ namespace Microsoft.Win32 { * * @return the data associated with the value. */ - [System.Security.SecuritySafeCritical] // auto-generated public Object GetValue(String name) { CheckPermission(RegistryInternalCheck.CheckValueReadPermission, name, false, RegistryKeyPermissionCheck.Default); return InternalGetValue(name, null, false, true); @@ -1094,32 +878,21 @@ namespace Microsoft.Win32 { * * @return the data associated with the value. */ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif public Object GetValue(String name, Object defaultValue) { CheckPermission(RegistryInternalCheck.CheckValueReadPermission, name, false, RegistryKeyPermissionCheck.Default); return InternalGetValue(name, defaultValue, false, true); } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif [ComVisible(false)] public Object GetValue(String name, Object defaultValue, RegistryValueOptions options) { if( options < RegistryValueOptions.None || options > RegistryValueOptions.DoNotExpandEnvironmentNames) { - throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)options), "options"); + throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)options), nameof(options)); } bool doNotExpand = (options == RegistryValueOptions.DoNotExpandEnvironmentNames); CheckPermission(RegistryInternalCheck.CheckValueReadPermission, name, false, RegistryKeyPermissionCheck.Default); return InternalGetValue(name, defaultValue, doNotExpand, true); } - [System.Security.SecurityCritical] // auto-generated internal Object InternalGetValue(String name, Object defaultValue, bool doNotExpand, bool checkSecurity) { if (checkSecurity) { // Name can be null! It's the most common use of RegQueryValueEx @@ -1338,7 +1111,6 @@ namespace Microsoft.Win32 { } - [System.Security.SecuritySafeCritical] // auto-generated [ComVisible(false)] public RegistryValueKind GetValueKind(string name) { CheckPermission(RegistryInternalCheck.CheckValueReadPermission, name, false, RegistryKeyPermissionCheck.Default); @@ -1382,7 +1154,6 @@ namespace Microsoft.Win32 { } public String Name { - [System.Security.SecuritySafeCritical] // auto-generated get { EnsureNotDisposed(); return keyName; @@ -1403,7 +1174,6 @@ namespace Microsoft.Win32 { SetValue(name, value, RegistryValueKind.Unknown); } - [System.Security.SecuritySafeCritical] //auto-generated [ComVisible(false)] public unsafe void SetValue(String name, Object value, RegistryValueKind valueKind) { if (value==null) @@ -1414,7 +1184,7 @@ namespace Microsoft.Win32 { } if (!Enum.IsDefined(typeof(RegistryValueKind), valueKind)) - throw new ArgumentException(Environment.GetResourceString("Arg_RegBadKeyKind"), "valueKind"); + throw new ArgumentException(Environment.GetResourceString("Arg_RegBadKeyKind"), nameof(valueKind)); EnsureWriteable(); @@ -1575,33 +1345,11 @@ namespace Microsoft.Win32 { * * @return a string representing the key. */ - [System.Security.SecuritySafeCritical] // auto-generated public override String ToString() { EnsureNotDisposed(); return keyName; } -#if FEATURE_MACL - public RegistrySecurity GetAccessControl() { - return GetAccessControl(AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public RegistrySecurity GetAccessControl(AccessControlSections includeSections) { - EnsureNotDisposed(); - return new RegistrySecurity(hkey, keyName, includeSections); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public void SetAccessControl(RegistrySecurity registrySecurity) { - EnsureWriteable(); - if (registrySecurity == null) - throw new ArgumentNullException("registrySecurity"); - - registrySecurity.Persist(hkey, keyName); - } -#endif - /** * After calling GetLastWin32Error(), it clears the last error field, * so you must save the HResult and pass it to this method. This method @@ -1609,7 +1357,6 @@ namespace Microsoft.Win32 { * error, and depending on the error, insert a string into the message * gotten from the ResourceManager. */ - [System.Security.SecuritySafeCritical] // auto-generated internal void Win32Error(int errorCode, String str) { switch (errorCode) { case Win32Native.ERROR_ACCESS_DENIED: @@ -1645,7 +1392,6 @@ namespace Microsoft.Win32 { } } - [SecuritySafeCritical] internal static void Win32ErrorStatic(int errorCode, String str) { switch (errorCode) { case Win32Native.ERROR_ACCESS_DENIED: @@ -1778,18 +1524,12 @@ namespace Microsoft.Win32 { path = keyName + "\\."; } - [System.Security.SecurityCritical] // auto-generated - private void CheckPermission(RegistryInternalCheck check, string item, bool subKeyWritable, RegistryKeyPermissionCheck subKeyCheck) { + private void CheckPermission(RegistryInternalCheck check, string item, bool subKeyWritable, RegistryKeyPermissionCheck subKeyCheck) + { bool demand = false; RegistryPermissionAccess access = RegistryPermissionAccess.NoAccess; string path = null; -#if !FEATURE_CORECLR - if (CodeAccessSecurityEngine.QuickCheckForAllDemands()) { - return; // full trust fast path - } -#endif // !FEATURE_CORECLR - switch (check) { // // Read/Write/Create SubKey Permission @@ -2020,14 +1760,12 @@ namespace Microsoft.Win32 { } } - [System.Security.SecurityCritical] // auto-generated static private void CheckUnmanagedCodePermission() { #pragma warning disable 618 new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); #pragma warning restore 618 } - [System.Security.SecurityCritical] // auto-generated private bool ContainsRegistryValue(string name) { int type = 0; int datasize = 0; @@ -2035,14 +1773,12 @@ namespace Microsoft.Win32 { return retval == 0; } - [System.Security.SecurityCritical] // auto-generated private void EnsureNotDisposed(){ if (hkey == null) { ThrowHelper.ThrowObjectDisposedException(keyName, ExceptionResource.ObjectDisposed_RegKeyClosed); } } - [System.Security.SecurityCritical] // auto-generated private void EnsureWriteable() { EnsureNotDisposed(); if (!IsWritable()) { @@ -2134,16 +1870,6 @@ namespace Microsoft.Win32 { } } - -#if FEATURE_MACL - static private void ValidateKeyRights(int rights) { - if(0 != (rights & ~((int)RegistryRights.FullControl))) { - // We need to throw SecurityException here for compatiblity reason, - // although UnauthorizedAccessException will make more sense. - ThrowHelper.ThrowSecurityException(ExceptionResource.Security_RegistryPermission); - } - } -#endif // Win32 constants for error handling private const int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200; private const int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000; diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.cs deleted file mode 100644 index ab06347..0000000 --- a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.cs +++ /dev/null @@ -1,43 +0,0 @@ -// 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. - -/*============================================================ -** -** -** -** A wrapper for file handles -** -** -===========================================================*/ - -using System; -using System.Security; -using System.Security.Permissions; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using System.Runtime.ConstrainedExecution; -using System.Runtime.Versioning; -using Microsoft.Win32; - -namespace Microsoft.Win32.SafeHandles { - - [System.Security.SecurityCritical] // auto-generated_required - public sealed class SafeFileHandle: SafeHandleZeroOrMinusOneIsInvalid { - - private SafeFileHandle() : base(true) - { - } - - public SafeFileHandle(IntPtr preexistingHandle, bool ownsHandle) : base(ownsHandle) { - SetHandle(preexistingHandle); - } - - [System.Security.SecurityCritical] - override protected bool ReleaseHandle() - { - return Win32Native.CloseHandle(handle); - } - } -} - diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileMappingHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileMappingHandle.cs index 5e1b510..cb915fe 100644 --- a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileMappingHandle.cs +++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileMappingHandle.cs @@ -20,20 +20,16 @@ using System.Runtime.Versioning; namespace Microsoft.Win32.SafeHandles { - [System.Security.SecurityCritical] // auto-generated internal sealed class SafeFileMappingHandle : SafeHandleZeroOrMinusOneIsInvalid { - [System.Security.SecurityCritical] // auto-generated_required internal SafeFileMappingHandle() : base(true) {} // 0 is an Invalid Handle - [System.Security.SecurityCritical] // auto-generated_required internal SafeFileMappingHandle(IntPtr handle, bool ownsHandle) : base (ownsHandle) { SetHandle(handle); } - [System.Security.SecurityCritical] override protected bool ReleaseHandle() { return Win32Native.CloseHandle(handle); diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFindHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFindHandle.cs index b24535f..219fb77 100644 --- a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFindHandle.cs +++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFindHandle.cs @@ -20,13 +20,10 @@ using System.Runtime.ConstrainedExecution; using Microsoft.Win32; namespace Microsoft.Win32.SafeHandles { - [System.Security.SecurityCritical] // auto-generated internal sealed class SafeFindHandle : SafeHandleZeroOrMinusOneIsInvalid { - [System.Security.SecurityCritical] // auto-generated_required internal SafeFindHandle() : base(true) {} - [System.Security.SecurityCritical] override protected bool ReleaseHandle() { return Win32Native.FindClose(handle); diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs index d2ea42b..2363198 100644 --- a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs +++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs @@ -3,24 +3,12 @@ // See the LICENSE file in the project root for more information. namespace Microsoft.Win32 { - using Microsoft.Win32; using Microsoft.Win32.SafeHandles; - using System; - using System.Runtime.CompilerServices; - using System.Runtime.ConstrainedExecution; - using System.Runtime.InteropServices; - using System.Runtime.Serialization; - using System.Runtime.Versioning; - using System.Security; using System.Security.Permissions; - using System.Text; - [System.Security.SecurityCritical] // auto-generated - [HostProtectionAttribute(MayLeakOnAbort = true)] sealed internal class SafeLibraryHandle : SafeHandleZeroOrMinusOneIsInvalid { internal SafeLibraryHandle() : base(true) {} - [System.Security.SecurityCritical] override protected bool ReleaseHandle() { return UnsafeNativeMethods.FreeLibrary(handle); diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLocalAllocHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLocalAllocHandle.cs index 3eea2b9..d6c1577 100644 --- a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLocalAllocHandle.cs +++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLocalAllocHandle.cs @@ -1,13 +1,14 @@ // 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. -namespace Microsoft.Win32.SafeHandles { + +namespace Microsoft.Win32.SafeHandles +{ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.ConstrainedExecution; - [System.Security.SecurityCritical] // auto-generated internal sealed class SafeLocalAllocHandle : SafeBuffer { private SafeLocalAllocHandle () : base(true) {} @@ -20,7 +21,6 @@ namespace Microsoft.Win32.SafeHandles { get { return new SafeLocalAllocHandle(IntPtr.Zero); } } - [System.Security.SecurityCritical] override protected bool ReleaseHandle() { return Win32Native.LocalFree(handle) == IntPtr.Zero; diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs index d0e3f04..4f96b81 100644 --- a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs +++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs @@ -17,17 +17,13 @@ namespace Microsoft.Win32.SafeHandles { using System.Runtime.ConstrainedExecution; using System.Runtime.Versioning; - [System.Security.SecurityCritical] public sealed class SafeRegistryHandle : SafeHandleZeroOrMinusOneIsInvalid { - [System.Security.SecurityCritical] internal SafeRegistryHandle() : base(true) {} - [System.Security.SecurityCritical] public SafeRegistryHandle(IntPtr preexistingHandle, bool ownsHandle) : base(ownsHandle) { SetHandle(preexistingHandle); } - [System.Security.SecurityCritical] override protected bool ReleaseHandle() { return (RegCloseKey(handle) == Win32Native.ERROR_SUCCESS); } diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeViewOfFileHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeViewOfFileHandle.cs index 01ec4d2..38a9323 100644 --- a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeViewOfFileHandle.cs +++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeViewOfFileHandle.cs @@ -22,19 +22,15 @@ using Microsoft.Win32.SafeHandles; namespace Microsoft.Win32.SafeHandles { - [System.Security.SecurityCritical] // auto-generated internal sealed class SafeViewOfFileHandle : SafeHandleZeroOrMinusOneIsInvalid { - [System.Security.SecurityCritical] // auto-generated_required internal SafeViewOfFileHandle() : base(true) {} // 0 is an Invalid Handle - [System.Security.SecurityCritical] // auto-generated_required internal SafeViewOfFileHandle(IntPtr handle, bool ownsHandle) : base (ownsHandle) { SetHandle(handle); } - [System.Security.SecurityCritical] override protected bool ReleaseHandle() { if (Win32Native.UnmapViewOfFile(handle)) diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs index fa24c96..0e57136 100644 --- a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs +++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs @@ -24,7 +24,6 @@ using System.Threading; namespace Microsoft.Win32.SafeHandles { - [System.Security.SecurityCritical] // auto-generated_required public sealed class SafeWaitHandle : SafeHandleZeroOrMinusOneIsInvalid { // Called by P/Invoke marshaler @@ -38,7 +37,6 @@ namespace Microsoft.Win32.SafeHandles { SetHandle(existingHandle); } - [System.Security.SecurityCritical] override protected bool ReleaseHandle() { return Win32Native.CloseHandle(handle); diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/Win32SafeHandles.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/Win32SafeHandles.cs index 58e0d7a..08ae095 100644 --- a/src/mscorlib/src/Microsoft/Win32/SafeHandles/Win32SafeHandles.cs +++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/Win32SafeHandles.cs @@ -22,10 +22,6 @@ namespace Microsoft.Win32.SafeHandles using System.Runtime.ConstrainedExecution; // Class of safe handle which uses 0 or -1 as an invalid handle. - [System.Security.SecurityCritical] // auto-generated_required -#if !FEATURE_CORECLR - [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)] -#endif public abstract class SafeHandleZeroOrMinusOneIsInvalid : SafeHandle { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] @@ -33,25 +29,18 @@ namespace Microsoft.Win32.SafeHandles { } -#if FEATURE_CORECLR // A default constructor is needed to satisfy CoreCLR inheritence rules. It should not be called at runtime protected SafeHandleZeroOrMinusOneIsInvalid() { throw new NotImplementedException(); } -#endif // FEATURE_CORECLR public override bool IsInvalid { - [System.Security.SecurityCritical] get { return handle.IsNull() || handle == new IntPtr(-1); } } } // Class of safe handle which uses only -1 as an invalid handle. - [System.Security.SecurityCritical] // auto-generated_required -#if !FEATURE_CORECLR - [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)] -#endif public abstract class SafeHandleMinusOneIsInvalid : SafeHandle { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] @@ -59,25 +48,18 @@ namespace Microsoft.Win32.SafeHandles { } -#if FEATURE_CORECLR // A default constructor is needed to satisfy CoreCLR inheritence rules. It should not be called at runtime protected SafeHandleMinusOneIsInvalid() { throw new NotImplementedException(); } -#endif // FEATURE_CORECLR public override bool IsInvalid { - [System.Security.SecurityCritical] get { return handle == new IntPtr(-1); } } } // Class of critical handle which uses 0 or -1 as an invalid handle. - [System.Security.SecurityCritical] // auto-generated_required -#if !FEATURE_CORECLR - [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)] -#endif public abstract class CriticalHandleZeroOrMinusOneIsInvalid : CriticalHandle { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] @@ -86,16 +68,11 @@ namespace Microsoft.Win32.SafeHandles } public override bool IsInvalid { - [System.Security.SecurityCritical] get { return handle.IsNull() || handle == new IntPtr(-1); } } } // Class of critical handle which uses only -1 as an invalid handle. - [System.Security.SecurityCritical] // auto-generated_required -#if !FEATURE_CORECLR - [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)] -#endif public abstract class CriticalHandleMinusOneIsInvalid : CriticalHandle { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] @@ -104,9 +81,7 @@ namespace Microsoft.Win32.SafeHandles } public override bool IsInvalid { - [System.Security.SecurityCritical] get { return handle == new IntPtr(-1); } } } - } diff --git a/src/mscorlib/src/Microsoft/Win32/UnsafeNativeMethods.cs b/src/mscorlib/src/Microsoft/Win32/UnsafeNativeMethods.cs index 9da9811..19d638d 100644 --- a/src/mscorlib/src/Microsoft/Win32/UnsafeNativeMethods.cs +++ b/src/mscorlib/src/Microsoft/Win32/UnsafeNativeMethods.cs @@ -16,7 +16,6 @@ namespace Microsoft.Win32 { using System.Text; using System.Diagnostics.Tracing; - [System.Security.SecurityCritical] // auto-generated [SuppressUnmanagedCodeSecurityAttribute()] internal static class UnsafeNativeMethods { @@ -64,7 +63,6 @@ namespace Microsoft.Win32 { internal static extern bool FreeLibrary(IntPtr hModule); - [SecurityCritical] [SuppressUnmanagedCodeSecurityAttribute()] internal static unsafe class ManifestEtw { @@ -96,7 +94,6 @@ namespace Microsoft.Win32 { // // Callback // - [SecurityCritical] internal unsafe delegate void EtwEnableCallback( [In] ref Guid sourceId, [In] int isEnabled, @@ -110,7 +107,6 @@ namespace Microsoft.Win32 { // // Registration APIs // - [SecurityCritical] [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventRegister", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] internal static extern unsafe uint EventRegister( [In] ref Guid providerId, @@ -120,7 +116,6 @@ namespace Microsoft.Win32 { ); // - [SecurityCritical] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")] [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventUnregister", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] internal static extern uint EventUnregister([In] long registrationHandle); @@ -129,7 +124,6 @@ namespace Microsoft.Win32 { // Writing (Publishing/Logging) APIs // // - [SecurityCritical] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")] [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventWrite", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] internal static extern unsafe int EventWrite( @@ -139,7 +133,6 @@ namespace Microsoft.Win32 { [In] EventProvider.EventData* userData ); - [SecurityCritical] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")] [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventWriteString", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] internal static extern unsafe int EventWriteString( @@ -270,7 +263,6 @@ namespace Microsoft.Win32 { } #if FEATURE_COMINTEROP - [SecurityCritical] [DllImport("combase.dll", PreserveSig = true)] internal static extern int RoGetActivationFactory( [MarshalAs(UnmanagedType.HString)] string activatableClassId, diff --git a/src/mscorlib/src/Microsoft/Win32/Win32Native.cs b/src/mscorlib/src/Microsoft/Win32/Win32Native.cs index ebe53f4..b5b808b 100644 --- a/src/mscorlib/src/Microsoft/Win32/Win32Native.cs +++ b/src/mscorlib/src/Microsoft/Win32/Win32Native.cs @@ -90,9 +90,6 @@ namespace Microsoft.Win32 { using System; using System.Security; -#if FEATURE_IMPERSONATION - using System.Security.Principal; -#endif using System.Text; using System.Configuration.Assemblies; using System.Runtime.Remoting; @@ -113,7 +110,6 @@ namespace Microsoft.Win32 { // Remove the default demands for all P/Invoke methods with this // global declaration on the class. - [System.Security.SecurityCritical] [SuppressUnmanagedCodeSecurityAttribute()] internal static class Win32Native { @@ -327,7 +323,7 @@ namespace Microsoft.Win32 { // } REG_TZI_FORMAT; // if (bytes == null || bytes.Length != 44) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidREG_TZI_FORMAT"), "bytes"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidREG_TZI_FORMAT"), nameof(bytes)); } Bias = BitConverter.ToInt32(bytes, 0); StandardBias = BitConverter.ToInt32(bytes, 4); @@ -454,7 +450,6 @@ namespace Microsoft.Win32 { internal int fileSizeHigh; internal int fileSizeLow; - [System.Security.SecurityCritical] internal void PopulateFrom(WIN32_FIND_DATA findData) { // Copy the information to data fileAttributes = findData.dwFileAttributes; @@ -516,7 +511,6 @@ namespace Microsoft.Win32 { /// strings created with this version of the constructor will be unsafe to use after the buffer /// has been freed. /// - [System.Security.SecurityCritical] // auto-generated internal UNICODE_INTPTR_STRING (int stringBytes, SafeLocalAllocHandle buffer) { BCLDebug.Assert(buffer == null || (stringBytes >= 0 && (ulong)stringBytes <= buffer.ByteLength), "buffer == null || (stringBytes >= 0 && stringBytes <= buffer.ByteLength)"); @@ -802,7 +796,6 @@ namespace Microsoft.Win32 { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] private static extern IntPtr GetModuleHandle(String moduleName); - [System.Security.SecurityCritical] // auto-generated internal static bool DoesWin32MethodExist(String moduleName, String methodName) { // GetModuleHandle does not increment the module's ref count, so we don't need to call FreeLibrary. @@ -910,56 +903,6 @@ namespace Microsoft.Win32 { [DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)] internal static extern uint GetLongPathNameW(string lpszShortPath, SafeHandle lpszLongPath, uint cchBuffer); - // Disallow access to all non-file devices from methods that take - // a String. This disallows DOS devices like "con:", "com1:", - // "lpt1:", etc. Use this to avoid security problems, like allowing - // a web client asking a server for "http://server/com1.aspx" and - // then causing a worker process to hang. - [System.Security.SecurityCritical] // auto-generated - internal static SafeFileHandle SafeCreateFile(String lpFileName, - int dwDesiredAccess, System.IO.FileShare dwShareMode, - SECURITY_ATTRIBUTES securityAttrs, System.IO.FileMode dwCreationDisposition, - int dwFlagsAndAttributes, IntPtr hTemplateFile) - { - SafeFileHandle handle = CreateFile( lpFileName, dwDesiredAccess, dwShareMode, - securityAttrs, dwCreationDisposition, - dwFlagsAndAttributes, hTemplateFile ); - - if (!handle.IsInvalid) - { - int fileType = Win32Native.GetFileType(handle); - if (fileType != Win32Native.FILE_TYPE_DISK) { - handle.Dispose(); - throw new NotSupportedException(Environment.GetResourceString("NotSupported_FileStreamOnNonFiles")); - } - } - - return handle; - } - - [System.Security.SecurityCritical] // auto-generated - internal static SafeFileHandle UnsafeCreateFile(String lpFileName, - int dwDesiredAccess, System.IO.FileShare dwShareMode, - SECURITY_ATTRIBUTES securityAttrs, System.IO.FileMode dwCreationDisposition, - int dwFlagsAndAttributes, IntPtr hTemplateFile) - { - SafeFileHandle handle = CreateFile( lpFileName, dwDesiredAccess, dwShareMode, - securityAttrs, dwCreationDisposition, - dwFlagsAndAttributes, hTemplateFile ); - - return handle; - } - - // Do not use these directly, use the safe or unsafe versions above. - // The safe version does not support devices (aka if will only open - // files on disk), while the unsafe version give you the full semantic - // of the native version. - [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)] - private static extern SafeFileHandle CreateFile(String lpFileName, - int dwDesiredAccess, System.IO.FileShare dwShareMode, - SECURITY_ATTRIBUTES securityAttrs, System.IO.FileMode dwCreationDisposition, - int dwFlagsAndAttributes, IntPtr hTemplateFile); - [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)] internal static extern SafeFileMappingHandle CreateFileMapping(SafeFileHandle hFile, IntPtr lpAttributes, uint fProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, String lpName); @@ -988,7 +931,6 @@ namespace Microsoft.Win32 { [DllImport(KERNEL32, SetLastError=true, EntryPoint="SetFilePointer")] private unsafe static extern int SetFilePointerWin32(SafeFileHandle handle, int lo, int * hi, int origin); - [System.Security.SecurityCritical] // auto-generated internal unsafe static long SetFilePointer(SafeFileHandle handle, long offset, System.IO.SeekOrigin origin, out int hr) { hr = 0; int lo = (int) offset; @@ -1070,7 +1012,6 @@ namespace Microsoft.Win32 { internal const int FIND_FROMSTART = 0x00400000; // look for value in source, starting at the beginning internal const int FIND_FROMEND = 0x00800000; // look for value in source, starting at the end -#if !FEATURE_CORECLR [StructLayout(LayoutKind.Sequential)] internal struct NlsVersionInfoEx { @@ -1080,7 +1021,6 @@ namespace Microsoft.Win32 { internal int dwEffectiveId; internal Guid guidCustomVersion; } -#endif [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)] internal static extern int GetWindowsDirectory([Out]StringBuilder sb, int length); @@ -1797,18 +1737,11 @@ namespace Microsoft.Win32 { [In] uint dwFlags); #endif // FEATURE_LEGACYSURFACE -#if FEATURE_CORECLR [DllImport(NTDLL, CharSet=CharSet.Unicode, SetLastError=true)] internal static extern int RtlNtStatusToDosError ( [In] int status); -#else - // identical to RtlNtStatusToDosError, but we are in ask mode for desktop CLR - [DllImport(ADVAPI32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern - int LsaNtStatusToWinError ( - [In] int status); -#endif + // Get the current FIPS policy setting on Vista and above [DllImport("bcrypt.dll")] internal static extern uint BCryptGetFipsAlgorithmMode( @@ -1930,28 +1863,6 @@ namespace Microsoft.Win32 { [In] bool bInheritHandle, [In] uint dwOptions); -#if FEATURE_IMPERSONATION - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - [DllImport(ADVAPI32, CharSet=CharSet.Auto, SetLastError=true)] - internal static extern - bool DuplicateTokenEx ( - [In] SafeAccessTokenHandle ExistingTokenHandle, - [In] TokenAccessLevels DesiredAccess, - [In] IntPtr TokenAttributes, - [In] SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, - [In] System.Security.Principal.TokenType TokenType, - [In,Out] ref SafeAccessTokenHandle DuplicateTokenHandle ); - - [DllImport(ADVAPI32, CharSet=CharSet.Auto, SetLastError=true)] - internal static extern - bool DuplicateTokenEx ( - [In] SafeAccessTokenHandle hExistingToken, - [In] uint dwDesiredAccess, - [In] IntPtr lpTokenAttributes, // LPSECURITY_ATTRIBUTES - [In] uint ImpersonationLevel, - [In] uint TokenType, - [In,Out] ref SafeAccessTokenHandle phNewToken); -#endif [DllImport( ADVAPI32, EntryPoint="EqualDomainSid", @@ -2345,15 +2256,6 @@ namespace Microsoft.Win32 { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal static extern int LsaFreeReturnBuffer(IntPtr handle); -#if FEATURE_IMPERSONATION - [DllImport (ADVAPI32, CharSet=CharSet.Unicode, SetLastError=true)] - internal static extern - bool OpenProcessToken ( - [In] IntPtr ProcessToken, - [In] TokenAccessLevels DesiredAccess, - [Out] out SafeAccessTokenHandle TokenHandle); -#endif - [DllImport( ADVAPI32, EntryPoint="SetNamedSecurityInfoW", @@ -2386,16 +2288,6 @@ namespace Microsoft.Win32 { byte[] dacl, byte[] sacl ); - // Fusion APIs -#if FEATURE_FUSION - [DllImport(MSCORWKS, CharSet=CharSet.Unicode)] - internal static extern int CreateAssemblyNameObject(out IAssemblyName ppEnum, String szAssemblyName, uint dwFlags, IntPtr pvReserved); - - [DllImport(MSCORWKS, CharSet=CharSet.Auto)] - internal static extern int CreateAssemblyEnum(out IAssemblyEnum ppEnum, IApplicationContext pAppCtx, IAssemblyName pName, uint dwFlags, IntPtr pvReserved); -#endif // FEATURE_FUSION - -#if FEATURE_CORECLR [DllImport(KERNEL32, CharSet=CharSet.Unicode)] [SuppressUnmanagedCodeSecurityAttribute()] internal unsafe static extern int WideCharToMultiByte( @@ -2417,13 +2309,11 @@ namespace Microsoft.Win32 { int cchMultiByte, char* lpWideCharStr, int cchWideChar); -#endif // FEATURE_CORECLR [DllImport(KERNEL32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal extern static bool QueryUnbiasedInterruptTime(out ulong UnbiasedTime); -#if FEATURE_CORECLR #if FEATURE_PAL [DllImport(KERNEL32, EntryPoint = "PAL_Random")] internal extern static bool Random(bool bStrong, @@ -2450,6 +2340,5 @@ namespace Microsoft.Win32 { } } #endif -#endif } } diff --git a/src/mscorlib/src/System.Private.CoreLib.txt b/src/mscorlib/src/System.Private.CoreLib.txt index 0369344..cf17dae 100644 --- a/src/mscorlib/src/System.Private.CoreLib.txt +++ b/src/mscorlib/src/System.Private.CoreLib.txt @@ -49,10 +49,6 @@ ArgumentOutOfRange_ActualValue = Actual value was {0}. NoDebugResources = [{0}]\r\nArguments: {1}\r\nDebugging resource strings are unavailable. Often the key and arguments provide sufficient information to diagnose the problem. See http://go.microsoft.com/fwlink/?linkid=106663&Version={2}&File={3}&Key={4} #endif // INCLUDE_RUNTIME -#if !FEATURE_CORECLR -UnknownError = Unknown error. -#endif // !FEATURE_CORECLR - #if INCLUDE_DEBUG ; For code contracts @@ -70,25 +66,6 @@ InvariantFailed = Invariant failed. InvariantFailed_Cnd = Invariant failed: {0} MustUseCCRewrite = An assembly (probably "{1}") must be rewritten using the code contracts binary rewriter (CCRewrite) because it is calling Contract.{0} and the CONTRACTS_FULL symbol is defined. Remove any explicit definitions of the CONTRACTS_FULL symbol from your project and rebuild. CCRewrite can be downloaded from http://go.microsoft.com/fwlink/?LinkID=169180. \r\nAfter the rewriter is installed, it can be enabled in Visual Studio from the project's Properties page on the Code Contracts pane. Ensure that "Perform Runtime Contract Checking" is enabled, which will define CONTRACTS_FULL. -; Access Control -#if FEATURE_MACL -AccessControl_MustSpecifyContainerAcl = The named parameter must be a container ACL. -AccessControl_MustSpecifyLeafObjectAcl = The named parameter must be a non-container ACL. -AccessControl_AclTooLong = Length of the access control list exceed the allowed maximum. -AccessControl_MustSpecifyDirectoryObjectAcl = The named parameter must be a directory-object ACL. -AccessControl_MustSpecifyNonDirectoryObjectAcl = The named parameter must be a non-directory-object ACL. -AccessControl_InvalidSecurityDescriptorRevision = Security descriptor with revision other than '1' are not legal. -AccessControl_InvalidSecurityDescriptorSelfRelativeForm = Security descriptor must be in the self-relative form. -AccessControl_NoAssociatedSecurity = Unable to perform a security operation on an object that has no associated security. This can happen when trying to get an ACL of an anonymous kernel object. -AccessControl_InvalidHandle = The supplied handle is invalid. This can happen when trying to set an ACL on an anonymous kernel object. -AccessControl_UnexpectedError = Method failed with unexpected error code {0}. -AccessControl_InvalidSidInSDDLString = The SDDL string contains an invalid sid or a sid that cannot be translated. -AccessControl_InvalidOwner = The security identifier is not allowed to be the owner of this object. -AccessControl_InvalidGroup = The security identifier is not allowed to be the primary group of this object. -AccessControl_InvalidAccessRuleType = The access rule is not the correct type. -AccessControl_InvalidAuditRuleType = The audit rule is not the correct type. -#endif // FEATURE_MACL - ; Identity Reference Library #if FEATURE_IDENTITY_REFERENCE IdentityReference_IdentityNotMapped = Some or all identity references could not be translated. @@ -121,9 +98,7 @@ Access_Void = Cannot create an instance of void. Arg_TypedReference_Null = The TypedReference must be initialized. Argument_AddingDuplicate__ = Item has already been added. Key in dictionary: '{0}' Key being added: '{1}' Argument_AddingDuplicate = An item with the same key has already been added. -#if FEATURE_CORECLR Argument_AddingDuplicateWithKey = An item with the same key has already been added. Key: {0} -#endif // FEATURE_CORECLR Argument_MethodDeclaringTypeGenericLcg = Method '{0}' has a generic declaring type '{1}'. Explicitly provide the declaring type to GetTokenFor. Argument_MethodDeclaringTypeGeneric = Cannot resolve method {0} because the declaring type of the method handle {1} is generic. Explicitly provide the declaring type to GetMethodFromHandle. Argument_FieldDeclaringTypeGeneric = Cannot resolve field {0} because the declaring type of the field handle {1} is generic. Explicitly provide the declaring type to GetFieldFromHandle. @@ -206,6 +181,7 @@ Arg_ArithmeticException = Overflow or underflow in the arithmetic operation. Arg_ArrayLengthsDiffer = Array lengths must be the same. Arg_ArrayPlusOffTooSmall = Destination array is not long enough to copy all the items in the collection. Check array index and length. Arg_ArrayTypeMismatchException = Attempted to access an element as a type incompatible with the array. +Arg_BadDecimal = Read an invalid decimal value from the buffer. Arg_BadImageFormatException = Format of the executable (.exe) or library (.dll) is invalid. Argument_BadImageFormatExceptionResolve = A BadImageFormatException has been thrown while parsing the signature. This is likely due to lack of a generic context. Ensure genericTypeArguments and genericMethodArguments are provided and contain enough context. Arg_BufferTooSmall = Not enough space available in the buffer. @@ -553,26 +529,6 @@ Argument_InvalidElementText = Invalid element text '{0}'. Argument_InvalidElementName = Invalid element name '{0}'. Argument_InvalidElementValue = Invalid element value '{0}'. Argument_AttributeNamesMustBeUnique = Attribute names must be unique. -#if FEATURE_CAS_POLICY -Argument_UninitializedCertificate = Uninitialized certificate object. -Argument_MembershipConditionElement = Element must be a element. -Argument_ReservedNPMS = Cannot remove or modify reserved permissions set '{0}'. -Argument_NPMSInUse = Permission set '{0}' was in use and could not be deleted. -Argument_StrongNameGetPublicKey = Unable to obtain public key for StrongNameKeyPair. -Argument_SiteCannotBeNull = Site name must be specified. -Argument_BlobCannotBeNull = Public key must be specified. -Argument_ZoneCannotBeNull = Zone must be specified. -Argument_UrlCannotBeNull = URL must be specified. -Argument_NoNPMS = Unable to find a permission set with the provided name. -Argument_FailedCodeGroup = Failed to create a code group of type '{0}'. -Argument_CodeGroupChildrenMustBeCodeGroups = All objects in the input list must have a parent type of 'CodeGroup'. -#endif // FEATURE_CAS_POLICY -#if FEATURE_IMPERSONATION -Argument_InvalidPrivilegeName = Privilege '{0}' is not valid on this system. -Argument_TokenZero = Token cannot be zero. -Argument_InvalidImpersonationToken = Invalid token for impersonation - it cannot be duplicated. -Argument_ImpersonateUser = Unable to impersonate user. -#endif // FEATURE_IMPERSONATION Argument_InvalidHexFormat = Improperly formatted hex string. Argument_InvalidSite = Invalid site. Argument_InterfaceMap = 'this' type cannot be an interface itself. @@ -630,6 +586,14 @@ Argument_UnmanagedMemAccessorWrapAround = The UnmanagedMemoryAccessor capacity a Argument_UnrecognizedLoaderOptimization = Unrecognized LOADER_OPTIMIZATION property value. Supported values may include "SingleDomain", "MultiDomain", "MultiDomainHost", and "NotSpecified". ArgumentException_NotAllCustomSortingFuncsDefined = Implementations of all the NLS functions must be provided. ArgumentException_MinSortingVersion = The runtime does not support a version of "{0}" less than {1}. +Argument_PreAllocatedAlreadyAllocated = 'preAllocated' is already in use. +Argument_NativeOverlappedWrongBoundHandle = 'overlapped' was not allocated by this ThreadPoolBoundHandle instance. +Argument_NativeOverlappedAlreadyFree = 'overlapped' has already been freed. +Argument_AlreadyBoundOrSyncHandle = 'handle' has already been bound to the thread pool, or was not opened for asynchronous I/O. +#if FEATURE_SPAN_OF_T +Argument_InvalidTypeWithPointersNotSupported = Cannot use type '{0}'. Only value types without pointers or references are supported. +Argument_DestinationTooShort = Destination is too short. +#endif // FEATURE_SPAN_OF_T ; ; ===================================================== @@ -1140,9 +1104,6 @@ InvalidOperation_EnumFailedVersion = Collection was modified; enumeration operat InvalidOperation_EnumNotStarted = Enumeration has not started. Call MoveNext. InvalidOperation_EnumOpCantHappen = Enumeration has either not started or has already finished. InvalidOperation_ModifyRONumFmtInfo = Unable to modify a read-only NumberFormatInfo object. -#if FEATURE_CAS_POLICY -InvalidOperation_ModifyROPermSet = ReadOnlyPermissionSet objects may not be modified. -#endif // FEATURE_CAS_POLICY InvalidOperation_MustBeSameThread = This operation must take place on the same thread on which the object was created. InvalidOperation_MustRevertPrivilege = Must revert the privilege prior to attempting this operation. InvalidOperation_ReadOnly = Instance is read-only. @@ -1157,6 +1118,7 @@ InvalidOperation_MethodBaked = Type definition of the method is complete. InvalidOperation_MethodHasBody = Method already has a body. InvalidOperation_ModificationOfNonCanonicalAcl = This access control list is not in canonical form and therefore cannot be modified. InvalidOperation_Method = This method is not supported by the current object. +InvalidOperation_NativeOverlappedReused = NativeOverlapped cannot be reused for multiple operations. InvalidOperation_NotADebugModule = Not a debug ModuleBuilder. InvalidOperation_NoMultiModuleAssembly = You cannot have more than one dynamic module in each dynamic assembly in this version of the runtime. InvalidOperation_OpenLocalVariableScope = Local variable scope was not properly closed. @@ -1242,7 +1204,7 @@ InvalidOperation_CannotUseAFCOtherThread = AsyncFlowControl object must be used InvalidOperation_CannotRestoreUnsupressedFlow = Cannot restore context flow when it is not suppressed. InvalidOperation_CannotSupressFlowMultipleTimes = Context flow is already suppressed. InvalidOperation_CannotUseAFCMultiple = AsyncFlowControl object can be used only once to call Undo(). -InvalidOperation_AsyncFlowCtrlCtxMismatch = AsyncFlowControl objects can be used to restore flow only on the Context that had its flow suppressed. +InvalidOperation_AsyncFlowCtrlCtxMismatch = AsyncFlowControl objects can be used to restore flow only on a Context that had its flow suppressed. InvalidOperation_TimeoutsNotSupported = Timeouts are not supported on this stream. InvalidOperation_Overlapped_Pack = Cannot pack a packed Overlapped again. InvalidOperation_OnlyValidForDS = Adding ACEs with Object Flags and Object GUIDs is only valid for directory-object ACLs. @@ -1405,6 +1367,7 @@ NotSupported_SignalAndWaitSTAThread = SignalAndWait on a STA thread is not suppo NotSupported_CreateInstanceWithTypeBuilder = CreateInstance cannot be used with an object of type TypeBuilder. NotSupported_NonUrlAttrOnMBR = UrlAttribute is the only attribute supported for MarshalByRefObject. NotSupported_ActivAttrOnNonMBR = Activation Attributes are not supported for types not deriving from MarshalByRefObject. +NotSupported_ActivAttr = Activation Attributes are not supported. NotSupported_ActivForCom = Activation Attributes not supported for COM Objects. NotSupported_NoCodepageData = No data is available for encoding {0}. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method. NotSupported_CodePage50229 = The ISO-2022-CN Encoding (Code page 50229) is not supported. @@ -1451,12 +1414,6 @@ NotSupported_NonBlittableTypes = Non-blittable parameter types are not supported NotSupported_UserDllImport = DllImport cannot be used on user-defined methods. NotSupported_UserCOM = COM Interop is not supported for user-defined types. #endif //FEATURE_WINDOWSPHONE -#if FEATURE_CAS_POLICY -NotSupported_RequiresCasPolicyExplicit = This method explicitly uses CAS policy, which has been obsoleted by the .NET Framework. In order to enable CAS policy for compatibility reasons, please use the NetFx40_LegacySecurityPolicy configuration switch. Please see http://go.microsoft.com/fwlink/?LinkID=155570 for more information. -NotSupported_RequiresCasPolicyImplicit = This method implicitly uses CAS policy, which has been obsoleted by the .NET Framework. In order to enable CAS policy for compatibility reasons, please use the NetFx40_LegacySecurityPolicy configuration switch. Please see http://go.microsoft.com/fwlink/?LinkID=155570 for more information. -NotSupported_CasDeny = The Deny stack modifier has been obsoleted by the .NET Framework. Please see http://go.microsoft.com/fwlink/?LinkId=155571 for more information. -NotSupported_SecurityContextSourceAppDomainInHeterogenous = SecurityContextSource.CurrentAppDomain is not supported in heterogenous AppDomains. -#endif // FEATURE_CAS_POLICY #if FEATURE_APPX NotSupported_AppX = {0} is not supported in AppX. LoadOfFxAssemblyNotSupported_AppX = {0} of .NET Framework assemblies is not supported in AppX. @@ -1466,9 +1423,6 @@ NotSupported_WinRT_PartialTrust = Windows Runtime is not supported in partial tr #endif // FEATURE_COMINTEROP ; ReflectionTypeLoadException ReflectionTypeLoad_LoadFailed = Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information. -#if !FEATURE_CORECLR -NotSupported_NoTypeInfo = Cannot resolve {0} to a TypeInfo object. -#endif #if FEATURE_COMINTEROP NotSupported_PIAInAppxProcess = A Primary Interop Assembly is not supported in AppX. #endif @@ -1476,7 +1430,12 @@ NotSupported_PIAInAppxProcess = A Primary Interop Assembly is not supported in A ; Not referring to "Windows Phone" in the messages, as FEATURE_WINDOWSPHONE is defined for .NET Core as well. NotSupported_WindowsPhone = {0} is not supported. NotSupported_AssemblyLoadCodeBase = Assembly.Load with a Codebase is not supported. +NotSupported_AssemblyLoadFromHash = Assembly.LoadFrom with hashValue is not supported. #endif +#if FEATURE_SPAN_OF_T +NotSupported_CannotCallEqualsOnSpan = Equals() on Span and ReadOnlySpan is not supported. Use operator== instead. +NotSupported_CannotCallGetHashCodeOnSpan = GetHashCode() on Span and ReadOnlySpan is not supported. +#endif // FEATURE_SPAN_OF_T ; TypeLoadException TypeLoad_ResolveType = Could not resolve type '{0}'. @@ -1536,81 +1495,12 @@ PlatformNotSupported_WinRT = Windows Runtime is not supported on this operating ; This still appears in bcl.small but should go away eventually Policy_Default = Error occurred while performing a policy operation. Policy_CannotLoadSemiTrustAssembliesDuringInit = All assemblies loaded as part of AppDomain initialization must be fully trusted. -#if FEATURE_IMPERSONATION -Policy_PrincipalTwice = Default principal object cannot be set twice. -#endif // FEATURE_IMPERSONATION -#if FEATURE_CAS_POLICY -Policy_PolicyAlreadySet = Policy for this domain cannot be set twice. -Policy_NoExecutionPermission = Execution permission cannot be acquired. -Policy_NoRequiredPermission = Required permissions cannot be acquired. -Policy_MultipleExclusive = More than one exclusive group is not allowed. -Policy_RecoverNotFileBased = PolicyLevel object not based on a file cannot be recovered. -Policy_RecoverNoConfigFile = No old configuration file exists to recover. -Policy_UnableToSave = Policy level '{0}' could not be saved: {1}. -Policy_BadXml = Policy configuration XML is invalid. The required tag '{0}' is missing. -Policy_NonFullTrustAssembly = Policy references an assembly not in the full trust assemblies list. -Policy_MissingActivationContextInAppEvidence = The application evidence does not contain a Fusion activation context. -Policy_NoTrustManager = A trust manager could not be loaded for this application. -Policy_GrantSetDoesNotMatchDomain = An assembly was provided an invalid grant set by runtime host '{0}'. In a homogenous AppDomain, the only valid grant sets are FullTrust and the AppDomain's sandbox grant set. -#endif // FEATURE_CAS_POLICY Policy_SaveNotFileBased = PolicyLevel object not based on a file cannot be saved. Policy_AppTrustMustGrantAppRequest = ApplicationTrust grant set does not contain ActivationContext's minimum request set. Error_SecurityPolicyFileParse = Error occurred while parsing the '{0}' policy level. The default policy level was used instead. Error_SecurityPolicyFileParseEx = Error '{1}' occurred while parsing the '{0}' policy level. The default policy level was used instead. -#if FEATURE_CAS_POLICY -Policy_EvidenceMustBeSerializable = Objects used as evidence must be serializable. -Policy_DuplicateEvidence = The evidence collection already contains evidence of type '{0}'. Multiple pieces of the same type of evidence are not allowed. -Policy_IncorrectHostEvidence = Runtime host '{0}' returned evidence of type '{1}' from a request for evidence of type '{2}'. -Policy_NullHostEvidence = Runtime host '{0}' returned null when asked for assembly evidence for assembly '{1}'. -Policy_NullHostGrantSet = Runtime host '{0}' returned a null grant set from ResolvePolicy. -#endif // FEATURE_CAS_POLICY - -; Policy codegroup and permission set names and descriptions -#if FEATURE_CAS_POLICY -Policy_AllCode_Name = All_Code -Policy_AllCode_DescriptionFullTrust = Code group grants all code full trust and forms the root of the code group tree. -Policy_AllCode_DescriptionNothing = Code group grants no permissions and forms the root of the code group tree. -Policy_MyComputer_Name = My_Computer_Zone -Policy_MyComputer_Description = Code group grants full trust to all code originating on the local computer -Policy_Intranet_Name = LocalIntranet_Zone -Policy_Intranet_Description = Code group grants the intranet permission set to code from the intranet zone. This permission set grants intranet code the right to use isolated storage, full UI access, some capability to do reflection, and limited access to environment variables. -Policy_IntranetNet_Name = Intranet_Same_Site_Access -Policy_IntranetNet_Description = All intranet code gets the right to connect back to the site of its origin. -Policy_IntranetFile_Name = Intranet_Same_Directory_Access -Policy_IntranetFile_Description = All intranet code gets the right to read from its install directory. -Policy_Internet_Name = Internet_Zone -Policy_Internet_Description = Code group grants code from the Internet zone the Internet permission set. This permission set grants Internet code the right to use isolated storage and limited UI access. -Policy_InternetNet_Name = Internet_Same_Site_Access -Policy_InternetNet_Description = All Internet code gets the right to connect back to the site of its origin. -Policy_Trusted_Name = Trusted_Zone -Policy_Trusted_Description = Code from a trusted zone is granted the Internet permission set. This permission set grants the right to use isolated storage and limited UI access. -Policy_TrustedNet_Name = Trusted_Same_Site_Access -Policy_TrustedNet_Description = All Trusted Code gets the right to connect back to the site of its origin. -Policy_Untrusted_Name = Restricted_Zone -Policy_Untrusted_Description = Code coming from a restricted zone does not receive any permissions. -Policy_Microsoft_Name = Microsoft_Strong_Name -Policy_Microsoft_Description = Code group grants full trust to code signed with the Microsoft strong name. -Policy_Ecma_Name = ECMA_Strong_Name -Policy_Ecma_Description = Code group grants full trust to code signed with the ECMA strong name. - -; Policy permission set descriptions -Policy_PS_FullTrust = Allows full access to all resources -Policy_PS_Everything = Allows unrestricted access to all resources covered by built-in permissions -Policy_PS_Nothing = Denies all resources, including the right to execute -Policy_PS_Execution = Permits execution -Policy_PS_SkipVerification = Grants right to bypass the verification -Policy_PS_Internet = Default rights given to Internet applications -Policy_PS_LocalIntranet = Default rights given to applications on the local intranet - -; default Policy level names -Policy_PL_Enterprise = Enterprise -Policy_PL_Machine = Machine -Policy_PL_User = User -Policy_PL_AppDomain = AppDomain -#endif // FEATURE_CAS_POLICY - ; RankException Rank_MultiDimNotSupported = Only single dimension arrays are supported here. Rank_MustMatch = The specified arrays must have the same number of dimensions. @@ -1658,125 +1548,6 @@ Remoting_Message_BadRetValOrOutArg = Bad return value or out-argument inside the Remoting_NonPublicOrStaticCantBeCalledRemotely = Permission denied: cannot call non-public or static methods remotely. Remoting_Proxy_ProxyTypeIsNotMBR = classToProxy argument must derive from MarshalByRef type. Remoting_TP_NonNull = The transparent proxy field of a real proxy must be null. -#if FEATURE_REMOTING -Remoting_Activation_BadAttribute = Activation attribute does not implement the IContextAttribute interface. -Remoting_Activation_BadObject = Proxy Attribute returned an incompatible object when constructing an instance of type {0}. -Remoting_Activation_MBR_ProxyAttribute = Proxy Attributes are supported on ContextBound types only. -Remoting_Activation_ConnectFailed = An attempt to connect to the remote activator failed with exception '{0}'. -Remoting_Activation_Failed = Activation failed due to an unknown reason. -Remoting_Activation_InconsistentState = Inconsistent state during activation; there may be two proxies for the same object. -Remoting_Activation_MissingRemoteAppEntry = Cannot find an entry for remote application '{0}'. -Remoting_Activation_NullReturnValue = Return value of construction call was null. -Remoting_Activation_NullFromInternalUnmarshal = InternalUnmarshal of returned ObjRef from activation call returned null. -Remoting_Activation_WellKnownCTOR = Cannot run a non-default constructor when connecting to well-known objects. -Remoting_Activation_PermissionDenied = Type '{0}' is not registered for activation. -Remoting_Activation_PropertyUnhappy = A context property did not approve the candidate context for activating the object. -Remoting_Activation_AsyncUnsupported = Async Activation not supported. -Remoting_AmbiguousCTOR = Cannot resolve the invocation to the correct constructor. -Remoting_AmbiguousMethod = Cannot resolve the invocation to the correct method. -Remoting_AppDomains_NYI = This feature is not yet supported for cross-application domain. -Remoting_AppDomainsCantBeCalledRemotely = Permission denied: cannot call methods on the AppDomain class remotely. -Remoting_AssemblyLoadFailed = Cannot load assembly '{0}'. -Remoting_Attribute_UseAttributeNotsettable = UseAttribute not allowed in SoapTypeAttribute. -Remoting_BadType = Cannot load type '{0}'. -Remoting_BadField = Remoting cannot find field '{0}' on type '{1}'. -Remoting_BadInternalState_ActivationFailure = Invalid internal state: Activation service failed to initialize. -Remoting_BadInternalState_ProxySameAppDomain = Invalid internal state: A marshal by ref object should not have a proxy in its own AppDomain. -Remoting_BadInternalState_FailEnvoySink = Invalid internal state: Failed to create an envoy sink for the object. -Remoting_CantDisconnectClientProxy = Cannot call disconnect on a proxy. -Remoting_CantInvokeIRemoteDispatch = Cannot invoke methods on IRemoteDispatch. -Remoting_ChannelNameAlreadyRegistered = The channel '{0}' is already registered. -Remoting_ChannelNotRegistered = The channel '{0}' is not registered with remoting services. -Remoting_Channel_PopOnEmptySinkStack = Tried to pop data from an empty channel sink stack. -Remoting_Channel_PopFromSinkStackWithoutPush = A channel sink tried to pop data from the stack without first pushing data onto the stack. -Remoting_Channel_StoreOnEmptySinkStack = A channel sink called the Store method when the sink stack was empty. -Remoting_Channel_StoreOnSinkStackWithoutPush = A channel sink called the Store method on the sink stack without first pushing data onto the stack. -Remoting_Channel_CantCallAPRWhenStackEmpty = Cannot call the AsyncProcessResponse method on the previous channel sink because the stack is empty. -Remoting_Channel_CantCallFRSWhenStackEmtpy = Called FlipRememberedStack() when stack was not null. -Remoting_Channel_CantCallGetResponseStreamWhenStackEmpty = Cannot call the GetResponseStream method on the previous channel sink because the stack is empty. -Remoting_Channel_DispatchSinkMessageMissing = No message was deserialized prior to calling the DispatchChannelSink. -Remoting_Channel_DispatchSinkWantsNullRequestStream = The request stream should be null when the DispatchChannelSink is called. -Remoting_Channel_CannotBeSecured = Channel {0} cannot be secured. Please consider using a channel that implements ISecurableChannel -Remoting_Config_ChannelMissingCtor = To be used from a .config file, the channel type '{0}' must have a constructor of the form '{1}' -Remoting_Config_SinkProviderMissingCtor = To be used from a .config file, the sink provider type '{0}' must have a constructor of the form '{1}' -Remoting_Config_SinkProviderNotFormatter = A sink provider of type '{0}' is incorrectly labeled as a 'formatter'. -Remoting_Config_ConfigurationFailure = Remoting configuration failed with the exception '{0}'. -Remoting_Config_InvalidTimeFormat = Invalid time format '{0}'. Examples of valid time formats include 7D, 10H, 5M, 30S, or 20MS. -Remoting_Config_AppNameSet = The remoting application name, '{0}', had already been set. -Remoting_Config_ErrorsModeSet = The remoting custom errors mode had already been set. -Remoting_Config_CantRedirectActivationOfWellKnownService = Attempt to redirect activation for type '{0}, {1}'. This is not allowed since either a well-known service type has already been registered with that type or that type has been registered has a activated service type. -Remoting_Config_CantUseRedirectedTypeForWellKnownService = Attempt to register a well-known or activated service type of type '{0}, {1}'. This is not allowed since the type has already been redirected to activate elsewhere. -Remoting_Config_InvalidChannelType = '{0}' does not implement IChannelReceiver or IChannelSender. All channels must implement one of these interfaces. -Remoting_Config_InvalidSinkProviderType = Unable to use '{0}' as a channel sink provider. It does not implement '{1}'. -Remoting_Config_MissingWellKnownModeAttribute = Well-known service entries must contain a 'mode' attribute with a value of 'Singleton' or 'SingleCall'. -Remoting_Config_MissingTypeAttribute = '{0}' entries must contain a '{1}' attribute of the form 'typeName, assemblyName'. -Remoting_Config_MissingXmlTypeAttribute = '{0}' entries must contain a '{1}' attribute of the form 'xmlTypeName, xmlTypeNamespace'. -Remoting_Config_NoAppName = Improper remoting configuration: missing ApplicationName property. -Remoting_Config_NonTemplateIdAttribute = Only '{0}' templates can have an 'id' attribute. -Remoting_Config_PreloadRequiresTypeOrAssembly = Preload entries require a type or assembly attribute. -Remoting_Config_ProviderNeedsElementName = Sink providers must have an element name of 'formatter' or 'provider'. -Remoting_Config_RequiredXmlAttribute = '{0}' entries require a '{1}' attribute. -Remoting_Config_ReadFailure = .Config file '{0}' cannot be read successfully due to exception '{1}'. -Remoting_Config_NodeMustBeUnique = There can be only one '{0}' node in the '{1}' section of a config file. -Remoting_Config_TemplateCannotReferenceTemplate = A '{0}' template cannot reference another '{0}' template. -Remoting_Config_TypeAlreadyRedirected = Attempt to redirect activation of type '{0}, {1}' which is already redirected. -Remoting_Config_UnknownValue = Unknown value {1} was found on the {0} node. -Remoting_Config_UnableToResolveTemplate = Cannot resolve '{0}' template reference: '{1}'. -Remoting_Config_VersionPresent = Version information is present in the assembly name '{0}' which is not allowed for '{1}' entries. -Remoting_Contexts_BadProperty = A property that contributed a bad sink to the chain was found. -Remoting_Contexts_NoProperty = A property with the name '{0}' was not found. -Remoting_Contexts_ContextNotFrozenForCallBack = Context should be frozen before calling the DoCallBack method. -Remoting_Default = Unknown remoting error. -Remoting_HandlerNotRegistered = The tracking handler of type '{0}' is not registered with Remoting Services. -Remoting_InvalidMsg = Invalid Message Object. -Remoting_InvalidCallingType = Attempted to call a method declared on type '{0}' on an object which exposes '{1}'. -Remoting_InvalidRequestedType = The server object type cannot be cast to the requested type '{0}'. -Remoting_InternalError = Server encountered an internal error. For more information, turn off customErrors in the server's .config file. -Remoting_Lifetime_ILeaseReturn = Expected a return object of type ILease, but received '{0}'. -Remoting_Lifetime_InitialStateInitialLeaseTime = InitialLeaseTime property can only be set when the lease is in initial state. The state is '{0}'. -Remoting_Lifetime_InitialStateRenewOnCall = RenewOnCallTime property can only be set when the lease is in initial state. The state is '{0}'. -Remoting_Lifetime_InitialStateSponsorshipTimeout = SponsorshipTimeout property can only be set when the lease is in initial state. State is '{0}'. -Remoting_Lifetime_SetOnce = '{0}' can only be set once within an AppDomain. -Remoting_Message_ArgMismatch = {2} arguments were passed to '{0}::{1}'. {3} arguments were expected by this method. -Remoting_Message_BadAsyncResult = The async result object is null or of an unexpected type. -Remoting_Message_BadType = The method was called with a Message of an unexpected type. -Remoting_Message_CoercionFailed = The argument type '{0}' cannot be converted into parameter type '{1}'. -Remoting_Message_MissingArgValue = Expecting an instance of type '{0}' at pos {1} in the args array. -Remoting_Message_BadSerialization = Invalid or malformed serialization information for the message object. -Remoting_NoIdentityEntry = No remoting information was found for this object. -Remoting_NotRemotableByReference = Trying to create a proxy to an unbound type. -Remoting_NullMessage = The method was called with a null message. -Remoting_Proxy_BadType = The proxy is of an unsupported type. -Remoting_ResetURI = Attempt to reset the URI for an object from '{0}' to '{1}'. -Remoting_ServerObjectNotFound = The server object for URI '{0}' is not registered with the remoting infrastructure (it may have been disconnected). -Remoting_SetObjectUriForMarshal__ObjectNeedsToBeLocal = SetObjectUriForMarshal method should only be called for MarshalByRefObjects that exist in the current AppDomain. -Remoting_SetObjectUriForMarshal__UriExists = SetObjectUriForMarshal method has already been called on this object or the object has already been marshaled. -Remoting_Proxy_BadReturnType = Return argument has an invalid type. -Remoting_Proxy_ReturnValueTypeCannotBeNull = ByRef value type parameter cannot be null. -Remoting_Proxy_BadReturnTypeForActivation = Bad return type for activation call via Invoke: must be of type IConstructionReturnMessage. -Remoting_Proxy_BadTypeForActivation = Type mismatch between proxy type '{0}' and activation type '{1}'. -Remoting_Proxy_ExpectedOriginalMessage = The message passed to Invoke should be passed to PropagateOutParameters. -Remoting_Proxy_InvalidCall = Trying to call proxy while constructor call is in progress. -Remoting_Proxy_InvalidState = Channel sink does not exist. Failed to dispatch async call. -Remoting_Proxy_NoChannelSink = This remoting proxy has no channel sink which means either the server has no registered server channels that are listening, or this application has no suitable client channel to talk to the server. -Remoting_Proxy_InvalidCallType = Only the synchronous call type is supported for messages that are not of type Message. -Remoting_Proxy_WrongContext = ExecuteMessage can be called only from the native context of the object. -Remoting_SOAPInteropxsdInvalid = Soap Parse error, xsd:type '{0}' invalid {1} -Remoting_SOAPQNameNamespace = SoapQName missing a Namespace value '{0}'. -Remoting_ThreadAffinity_InvalidFlag = The specified flag '{0}' does not have one of the valid values. -Remoting_TrackingHandlerAlreadyRegistered = The handler has already been registered with TrackingServices. -Remoting_URIClash = Found two different objects associated with the same URI, '{0}'. -Remoting_URIExists = The remoted object already has an associated URI. -Remoting_URIToProxy = Trying to associate the URI with a proxy. -Remoting_WellKnown_MustBeMBR = Attempted to create well-known object of type '{0}'. Well-known objects must derive from the MarshalByRefObject class. -Remoting_WellKnown_CtorCantMarshal = '{0}': A well-known object cannot marshal itself in its constructor, or perform any action that would cause it to be marshaled (such as passing the 'this' pointer as a parameter to a remote method). -Remoting_WellKnown_CantDirectlyConnect = Attempt to connect to a server using its object URI: '{0}'. A valid, complete URL must be used. -Remoting_Connect_CantCreateChannelSink = Cannot create channel sink to connect to URL '{0}'. An appropriate channel has probably not been registered. -Remoting_UnexpectedNullTP = Failed to create a transparent proxy. If a custom RealProxy is being used ensure it sets the proxy type. -; The following remoting exception messages appear in native resources too (mscorrc.rc) -Remoting_Disconnected = Object '{0}' has been disconnected or does not exist at the server. -Remoting_Message_MethodMissing = The method '{0}' was not found on the interface/type '{1}'. -#endif // FEATURE_REMOTING ; Resources exceptions ; @@ -1805,24 +1576,6 @@ Security_GenericNoType = Request failed. Security_NoAPTCA = That assembly does not allow partially trusted callers. Security_RegistryPermission = Requested registry access is not allowed. Security_MustRevertOverride = Stack walk modifier must be reverted before another modification of the same type can be performed. -#if FEATURE_CAS_POLICY -Security_CannotGenerateHash = Hash for the assembly cannot be generated. -Security_CannotGetRawData = Assembly bytes could not be retrieved. -Security_PrincipalPermission = Request for principal permission failed. -Security_Action = The action that failed was: -Security_TypeFirstPermThatFailed = The type of the first permission that failed was: -Security_FirstPermThatFailed = The first permission that failed was: -Security_Demanded = The demand was for: -Security_GrantedSet = The granted set of the failing assembly was: -Security_RefusedSet = The refused set of the failing assembly was: -Security_Denied = The denied permissions were: -Security_PermitOnly = The only permitted permissions were: -Security_Assembly = The assembly or AppDomain that failed was: -Security_Method = The method that caused the failure was: -Security_Zone = The Zone of the assembly that failed was: -Security_Url = The Url of the assembly that failed was: -Security_AnonymouslyHostedDynamicMethodCheckFailed = The demand failed due to the code access security information captured during the creation of an anonymously hosted dynamic method. In order for this operation to succeed, ensure that the demand would have succeeded at the time the method was created. See http://go.microsoft.com/fwlink/?LinkId=288746 for more information. -#endif // FEATURE_CAS_POLICY ; ; HostProtection exceptions @@ -1872,12 +1625,10 @@ IO.PathNotFound_Path = Could not find a part of the path '{0}'. IO.PathNotFound_NoPathName = Could not find a part of the path. ; PathTooLongException -IO.PathTooLong = The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters. +IO.PathTooLong = The specified file name or path is too long, or a component of the specified path is too long. -#if FEATURE_CORECLR ; SecurityException FileSecurityState_OperationNotPermitted = File operation not permitted. Access to path '{0}' is denied. -#endif ; PrivilegeNotHeldException PrivilegeNotHeld_Default = The process does not possess some privilege required for this operation. @@ -2275,14 +2026,6 @@ XMLSyntax_InvalidSyntaxSatAssemTag = Invalid XML in file "{0}" near element "{1} XMLSyntax_InvalidSyntaxSatAssemTagBadAttr = Invalid XML in file "{0}" near "{1}" and "{2}". In the section, the tag must have exactly 1 attribute called 'name', whose value is a fully-qualified assembly name. XMLSyntax_InvalidSyntaxSatAssemTagNoAttr = Invalid XML in file "{0}". In the section, the tag must have exactly 1 attribute called 'name', whose value is a fully-qualified assembly name. -; CodeGroup -#if FEATURE_CAS_POLICY -NetCodeGroup_PermissionSet = Same site Web -MergeLogic_Union = Union -MergeLogic_FirstMatch = First Match -FileCodeGroup_PermissionSet = Same directory FileIO - '{0}' -#endif // FEATURE_CAS_POLICY - ; MembershipConditions StrongName_ToString = StrongName - {0}{1}{2} StrongName_Name = name = {0} @@ -2295,12 +2038,6 @@ Zone_ToString = Zone - {0} All_ToString = All code Url_ToString = Url GAC_ToString = GAC -#if FEATURE_CAS_POLICY -Site_ToStringArg = Site - {0} -Publisher_ToStringArg = Publisher - {0} -Url_ToStringArg = Url - {0} -#endif // FEATURE_CAS_POLICY - ; Interop non exception strings. TypeLibConverter_ImportedTypeLibProductName = Assembly imported from type library '{0}'. @@ -2381,956 +2118,8 @@ InvalidOperation_CollectionBackingListTooLarge=The collection backing this List InvalidOperation_CollectionBackingDictionaryTooLarge=The collection backing this Dictionary contains too many elements. InvalidOperation_CannotRemoveLastFromEmptyCollection=Cannot remove the last element from an empty collection. -; Globalization resources -;------------------ - -#if !FEATURE_CORECLR -Globalization.LegacyModifier = Legacy - -; -;Total items: 809 -; -Globalization.ci_ = Invariant Language (Invariant Country) -Globalization.ci_aa = Afar -Globalization.ci_aa-DJ = Afar (Djibouti) -Globalization.ci_aa-ER = Afar (Eritrea) -Globalization.ci_aa-ET = Afar (Ethiopia) -Globalization.ci_af = Afrikaans -Globalization.ci_af-NA = Afrikaans (Namibia) -Globalization.ci_af-ZA = Afrikaans (South Africa) -Globalization.ci_agq = Aghem -Globalization.ci_agq-CM = Aghem (Cameroon) -Globalization.ci_ak = Akan -Globalization.ci_ak-GH = Akan (Ghana) -Globalization.ci_am = Amharic -Globalization.ci_am-ET = Amharic (Ethiopia) -Globalization.ci_ar = Arabic -Globalization.ci_ar-001 = Arabic (World) -Globalization.ci_ar-AE = Arabic (U.A.E.) -Globalization.ci_ar-BH = Arabic (Bahrain) -Globalization.ci_ar-DJ = Arabic (Djibouti) -Globalization.ci_ar-DZ = Arabic (Algeria) -Globalization.ci_ar-EG = Arabic (Egypt) -Globalization.ci_ar-ER = Arabic (Eritrea) -Globalization.ci_ar-IL = Arabic (Israel) -Globalization.ci_ar-IQ = Arabic (Iraq) -Globalization.ci_ar-JO = Arabic (Jordan) -Globalization.ci_ar-KM = Arabic (Comoros) -Globalization.ci_ar-KW = Arabic (Kuwait) -Globalization.ci_ar-LB = Arabic (Lebanon) -Globalization.ci_ar-LY = Arabic (Libya) -Globalization.ci_ar-MA = Arabic (Morocco) -Globalization.ci_ar-MR = Arabic (Mauritania) -Globalization.ci_ar-OM = Arabic (Oman) -Globalization.ci_ar-PS = Arabic (Palestinian Authority) -Globalization.ci_ar-QA = Arabic (Qatar) -Globalization.ci_ar-SA = Arabic (Saudi Arabia) -Globalization.ci_ar-SD = Arabic (Sudan) -Globalization.ci_ar-SO = Arabic (Somalia) -Globalization.ci_ar-SS = Arabic (South Sudan) -Globalization.ci_ar-SY = Arabic (Syria) -Globalization.ci_ar-TD = Arabic (Chad) -Globalization.ci_ar-TN = Arabic (Tunisia) -Globalization.ci_ar-YE = Arabic (Yemen) -Globalization.ci_arn = Mapudungun -Globalization.ci_arn-CL = Mapudungun (Chile) -Globalization.ci_as = Assamese -Globalization.ci_as-IN = Assamese (India) -Globalization.ci_asa = Asu -Globalization.ci_asa-TZ = Asu (Tanzania) -Globalization.ci_ast = Asturian -Globalization.ci_ast-ES = Asturian (Spain) -Globalization.ci_az = Azerbaijani -Globalization.ci_az-Cyrl = Azerbaijani (Cyrillic) -Globalization.ci_az-Cyrl-AZ = Azerbaijani (Cyrillic, Azerbaijan) -Globalization.ci_az-Latn = Azerbaijani (Latin) -Globalization.ci_az-Latn-AZ = Azerbaijani (Latin, Azerbaijan) -Globalization.ci_ba = Bashkir -Globalization.ci_ba-RU = Bashkir (Russia) -Globalization.ci_bas = Basaa -Globalization.ci_bas-CM = Basaa (Cameroon) -Globalization.ci_be = Belarusian -Globalization.ci_be-BY = Belarusian (Belarus) -Globalization.ci_bem = Bemba -Globalization.ci_bem-ZM = Bemba (Zambia) -Globalization.ci_bez = Bena -Globalization.ci_bez-TZ = Bena (Tanzania) -Globalization.ci_bg = Bulgarian -Globalization.ci_bg-BG = Bulgarian (Bulgaria) -Globalization.ci_bm = Bambara -Globalization.ci_bm-Latn = Bambara (Latin) -Globalization.ci_bm-Latn-ML = Bambara (Latin, Mali) -Globalization.ci_bm-ML = Bamanankan (Latin, Mali) -Globalization.ci_bn = Bangla -Globalization.ci_bn-BD = Bangla (Bangladesh) -Globalization.ci_bn-IN = Bangla (India) -Globalization.ci_bo = Tibetan -Globalization.ci_bo-CN = Tibetan (PRC) -Globalization.ci_bo-IN = Tibetan (India) -Globalization.ci_br = Breton -Globalization.ci_br-FR = Breton (France) -Globalization.ci_brx = Bodo -Globalization.ci_brx-IN = Bodo (India) -Globalization.ci_bs = Bosnian -Globalization.ci_bs-Cyrl = Bosnian (Cyrillic) -Globalization.ci_bs-Cyrl-BA = Bosnian (Cyrillic, Bosnia and Herzegovina) -Globalization.ci_bs-Latn = Bosnian (Latin) -Globalization.ci_bs-Latn-BA = Bosnian (Latin, Bosnia and Herzegovina) -Globalization.ci_byn = Blin -Globalization.ci_byn-ER = Blin (Eritrea) -Globalization.ci_ca = Catalan -Globalization.ci_ca-AD = Catalan (Andorra) -Globalization.ci_ca-ES = Catalan (Catalan) -Globalization.ci_ca-ES-valencia = Valencian (Spain) -Globalization.ci_ca-FR = Catalan (France) -Globalization.ci_ca-IT = Catalan (Italy) -Globalization.ci_cgg = Chiga -Globalization.ci_cgg-UG = Chiga (Uganda) -Globalization.ci_chr = Cherokee -Globalization.ci_chr-Cher = Cherokee (Cherokee) -Globalization.ci_chr-Cher-US = Cherokee (Cherokee) -Globalization.ci_co = Corsican -Globalization.ci_co-FR = Corsican (France) -Globalization.ci_cs = Czech -Globalization.ci_cs-CZ = Czech (Czech Republic) -Globalization.ci_cy = Welsh -Globalization.ci_cy-GB = Welsh (United Kingdom) -Globalization.ci_da = Danish -Globalization.ci_da-DK = Danish (Denmark) -Globalization.ci_da-GL = Danish (Greenland) -Globalization.ci_dav = Taita -Globalization.ci_dav-KE = Taita (Kenya) -Globalization.ci_de = German -Globalization.ci_de-AT = German (Austria) -Globalization.ci_de-BE = German (Belgium) -Globalization.ci_de-CH = German (Switzerland) -Globalization.ci_de-DE = German (Germany) -Globalization.ci_de-DE_phoneb = German (Germany) -Globalization.ci_de-LI = German (Liechtenstein) -Globalization.ci_de-LU = German (Luxembourg) -Globalization.ci_dje = Zarma -Globalization.ci_dje-NE = Zarma (Niger) -Globalization.ci_dsb = Lower Sorbian -Globalization.ci_dsb-DE = Lower Sorbian (Germany) -Globalization.ci_dua = Duala -Globalization.ci_dua-CM = Duala (Cameroon) -Globalization.ci_dv = Divehi -Globalization.ci_dv-MV = Divehi (Maldives) -Globalization.ci_dyo = Jola-Fonyi -Globalization.ci_dyo-SN = Jola-Fonyi (Senegal) -Globalization.ci_dz = Dzongkha -Globalization.ci_dz-BT = Dzongkha (Bhutan) -Globalization.ci_ebu = Embu -Globalization.ci_ebu-KE = Embu (Kenya) -Globalization.ci_ee = Ewe -Globalization.ci_ee-GH = Ewe (Ghana) -Globalization.ci_ee-TG = Ewe (Togo) -Globalization.ci_el = Greek -Globalization.ci_el-CY = Greek (Cyprus) -Globalization.ci_el-GR = Greek (Greece) -Globalization.ci_en = English -Globalization.ci_en-001 = English (World) -Globalization.ci_en-029 = English (Caribbean) -Globalization.ci_en-150 = English (Europe) -Globalization.ci_en-AG = English (Antigua and Barbuda) -Globalization.ci_en-AI = English (Anguilla) -Globalization.ci_en-AS = English (American Samoa) -Globalization.ci_en-AU = English (Australia) -Globalization.ci_en-BB = English (Barbados) -Globalization.ci_en-BE = English (Belgium) -Globalization.ci_en-BM = English (Bermuda) -Globalization.ci_en-BS = English (Bahamas) -Globalization.ci_en-BW = English (Botswana) -Globalization.ci_en-BZ = English (Belize) -Globalization.ci_en-CA = English (Canada) -Globalization.ci_en-CC = English (Cocos [Keeling] Islands) -Globalization.ci_en-CK = English (Cook Islands) -Globalization.ci_en-CM = English (Cameroon) -Globalization.ci_en-CX = English (Christmas Island) -Globalization.ci_en-DM = English (Dominica) -Globalization.ci_en-ER = English (Eritrea) -Globalization.ci_en-FJ = English (Fiji) -Globalization.ci_en-FK = English (Falkland Islands) -Globalization.ci_en-FM = English (Micronesia) -Globalization.ci_en-GB = English (United Kingdom) -Globalization.ci_en-GD = English (Grenada) -Globalization.ci_en-GG = English (Guernsey) -Globalization.ci_en-GH = English (Ghana) -Globalization.ci_en-GI = English (Gibraltar) -Globalization.ci_en-GM = English (Gambia) -Globalization.ci_en-GU = English (Guam) -Globalization.ci_en-GY = English (Guyana) -Globalization.ci_en-HK = English (Hong Kong SAR) -Globalization.ci_en-IE = English (Ireland) -Globalization.ci_en-IM = English (Isle of Man) -Globalization.ci_en-IN = English (India) -Globalization.ci_en-IO = English (British Indian Ocean Territory) -Globalization.ci_en-JE = English (Jersey) -Globalization.ci_en-JM = English (Jamaica) -Globalization.ci_en-KE = English (Kenya) -Globalization.ci_en-KI = English (Kiribati) -Globalization.ci_en-KN = English (Saint Kitts and Nevis) -Globalization.ci_en-KY = English (Cayman Islands) -Globalization.ci_en-LC = English (Saint Lucia) -Globalization.ci_en-LR = English (Liberia) -Globalization.ci_en-LS = English (Lesotho) -Globalization.ci_en-MG = English (Madagascar) -Globalization.ci_en-MH = English (Marshall Islands) -Globalization.ci_en-MO = English (Macao SAR) -Globalization.ci_en-MP = English (Northern Mariana Islands) -Globalization.ci_en-MS = English (Montserrat) -Globalization.ci_en-MT = English (Malta) -Globalization.ci_en-MU = English (Mauritius) -Globalization.ci_en-MW = English (Malawi) -Globalization.ci_en-MY = English (Malaysia) -Globalization.ci_en-NA = English (Namibia) -Globalization.ci_en-NF = English (Norfolk Island) -Globalization.ci_en-NG = English (Nigeria) -Globalization.ci_en-NR = English (Nauru) -Globalization.ci_en-NU = English (Niue) -Globalization.ci_en-NZ = English (New Zealand) -Globalization.ci_en-PG = English (Papua New Guinea) -Globalization.ci_en-PH = English (Republic of the Philippines) -Globalization.ci_en-PK = English (Pakistan) -Globalization.ci_en-PN = English (Pitcairn Islands) -Globalization.ci_en-PR = English (Puerto Rico) -Globalization.ci_en-PW = English (Palau) -Globalization.ci_en-RW = English (Rwanda) -Globalization.ci_en-SB = English (Solomon Islands) -Globalization.ci_en-SC = English (Seychelles) -Globalization.ci_en-SD = English (Sudan) -Globalization.ci_en-SG = English (Singapore) -Globalization.ci_en-SH = English (St Helena, Ascension, Tristan da Cunha) -Globalization.ci_en-SL = English (Sierra Leone) -Globalization.ci_en-SS = English (South Sudan) -Globalization.ci_en-SX = English (Sint Maarten) -Globalization.ci_en-SZ = English (Swaziland) -Globalization.ci_en-TC = English (Turks and Caicos Islands) -Globalization.ci_en-TK = English (Tokelau) -Globalization.ci_en-TO = English (Tonga) -Globalization.ci_en-TT = English (Trinidad and Tobago) -Globalization.ci_en-TV = English (Tuvalu) -Globalization.ci_en-TZ = English (Tanzania) -Globalization.ci_en-UG = English (Uganda) -Globalization.ci_en-UM = English (US Minor Outlying Islands) -Globalization.ci_en-US = English (United States) -Globalization.ci_en-VC = English (Saint Vincent and the Grenadines) -Globalization.ci_en-VG = English (British Virgin Islands) -Globalization.ci_en-VI = English (US Virgin Islands) -Globalization.ci_en-VU = English (Vanuatu) -Globalization.ci_en-WS = English (Samoa) -Globalization.ci_en-ZA = English (South Africa) -Globalization.ci_en-ZM = English (Zambia) -Globalization.ci_en-ZW = English (Zimbabwe) -Globalization.ci_eo = Esperanto -Globalization.ci_eo-001 = Esperanto (World) -Globalization.ci_es = Spanish -Globalization.ci_es-419 = Spanish (Latin America) -Globalization.ci_es-AR = Spanish (Argentina) -Globalization.ci_es-BO = Spanish (Bolivia) -Globalization.ci_es-CL = Spanish (Chile) -Globalization.ci_es-CO = Spanish (Colombia) -Globalization.ci_es-CR = Spanish (Costa Rica) -Globalization.ci_es-CU = Spanish (Cuba) -Globalization.ci_es-DO = Spanish (Dominican Republic) -Globalization.ci_es-EC = Spanish (Ecuador) -Globalization.ci_es-ES = Spanish (Spain) -Globalization.ci_es-ES_tradnl = Spanish (Spain) -Globalization.ci_es-GQ = Spanish (Equatorial Guinea) -Globalization.ci_es-GT = Spanish (Guatemala) -Globalization.ci_es-HN = Spanish (Honduras) -Globalization.ci_es-MX = Spanish (Mexico) -Globalization.ci_es-NI = Spanish (Nicaragua) -Globalization.ci_es-PA = Spanish (Panama) -Globalization.ci_es-PE = Spanish (Peru) -Globalization.ci_es-PH = Spanish (Philippines) -Globalization.ci_es-PR = Spanish (Puerto Rico) -Globalization.ci_es-PY = Spanish (Paraguay) -Globalization.ci_es-SV = Spanish (El Salvador) -Globalization.ci_es-US = Spanish (United States) -Globalization.ci_es-UY = Spanish (Uruguay) -Globalization.ci_es-VE = Spanish (Bolivarian Republic of Venezuela) -Globalization.ci_et = Estonian -Globalization.ci_et-EE = Estonian (Estonia) -Globalization.ci_eu = Basque -Globalization.ci_eu-ES = Basque (Basque) -Globalization.ci_ewo = Ewondo -Globalization.ci_ewo-CM = Ewondo (Cameroon) -Globalization.ci_fa = Persian -Globalization.ci_fa-AF = Persian (Afghanistan) -Globalization.ci_fa-IR = Persian (Iran) -Globalization.ci_ff = Fulah -Globalization.ci_ff-CM = Fulah (Cameroon) -Globalization.ci_ff-GN = Fulah (Guinea) -Globalization.ci_ff-Latn = Fulah (Latin) -Globalization.ci_ff-Latn-SN = Fulah (Latin, Senegal) -Globalization.ci_ff-MR = Fulah (Mauritania) -Globalization.ci_fi = Finnish -Globalization.ci_fi-FI = Finnish (Finland) -Globalization.ci_fil = Filipino -Globalization.ci_fil-PH = Filipino (Philippines) -Globalization.ci_fo = Faroese -Globalization.ci_fo-FO = Faroese (Faroe Islands) -Globalization.ci_fr = French -Globalization.ci_fr-BE = French (Belgium) -Globalization.ci_fr-BF = French (Burkina Faso) -Globalization.ci_fr-BI = French (Burundi) -Globalization.ci_fr-BJ = French (Benin) -Globalization.ci_fr-BL = French (Saint Barthélemy) -Globalization.ci_fr-CA = French (Canada) -Globalization.ci_fr-CD = French (Congo DRC) -Globalization.ci_fr-CF = French (Central African Republic) -Globalization.ci_fr-CG = French (Congo) -Globalization.ci_fr-CH = French (Switzerland) -Globalization.ci_fr-CI = French (Côte d’Ivoire) -Globalization.ci_fr-CM = French (Cameroon) -Globalization.ci_fr-DJ = French (Djibouti) -Globalization.ci_fr-DZ = French (Algeria) -Globalization.ci_fr-FR = French (France) -Globalization.ci_fr-GA = French (Gabon) -Globalization.ci_fr-GF = French (French Guiana) -Globalization.ci_fr-GN = French (Guinea) -Globalization.ci_fr-GP = French (Guadeloupe) -Globalization.ci_fr-GQ = French (Equatorial Guinea) -Globalization.ci_fr-HT = French (Haiti) -Globalization.ci_fr-KM = French (Comoros) -Globalization.ci_fr-LU = French (Luxembourg) -Globalization.ci_fr-MA = French (Morocco) -Globalization.ci_fr-MC = French (Monaco) -Globalization.ci_fr-MF = French (Saint Martin) -Globalization.ci_fr-MG = French (Madagascar) -Globalization.ci_fr-ML = French (Mali) -Globalization.ci_fr-MQ = French (Martinique) -Globalization.ci_fr-MR = French (Mauritania) -Globalization.ci_fr-MU = French (Mauritius) -Globalization.ci_fr-NC = French (New Caledonia) -Globalization.ci_fr-NE = French (Niger) -Globalization.ci_fr-PF = French (French Polynesia) -Globalization.ci_fr-PM = French (Saint Pierre and Miquelon) -Globalization.ci_fr-RE = French (Reunion) -Globalization.ci_fr-RW = French (Rwanda) -Globalization.ci_fr-SC = French (Seychelles) -Globalization.ci_fr-SN = French (Senegal) -Globalization.ci_fr-SY = French (Syria) -Globalization.ci_fr-TD = French (Chad) -Globalization.ci_fr-TG = French (Togo) -Globalization.ci_fr-TN = French (Tunisia) -Globalization.ci_fr-VU = French (Vanuatu) -Globalization.ci_fr-WF = French (Wallis and Futuna) -Globalization.ci_fr-YT = French (Mayotte) -Globalization.ci_fur = Friulian -Globalization.ci_fur-IT = Friulian (Italy) -Globalization.ci_fy = Frisian -Globalization.ci_fy-NL = Frisian (Netherlands) -Globalization.ci_ga = Irish -Globalization.ci_ga-IE = Irish (Ireland) -Globalization.ci_gd = Scottish Gaelic -Globalization.ci_gd-GB = Scottish Gaelic (United Kingdom) -Globalization.ci_gl = Galician -Globalization.ci_gl-ES = Galician (Galician) -Globalization.ci_gn = Guarani -Globalization.ci_gn-PY = Guarani (Paraguay) -Globalization.ci_gsw = Alsatian -Globalization.ci_gsw-CH = Alsatian (Switzerland) -Globalization.ci_gsw-FR = Alsatian (France) -Globalization.ci_gsw-LI = Alsatian (Liechtenstein) -Globalization.ci_gu = Gujarati -Globalization.ci_gu-IN = Gujarati (India) -Globalization.ci_guz = Gusii -Globalization.ci_guz-KE = Gusii (Kenya) -Globalization.ci_gv = Manx -Globalization.ci_gv-IM = Manx (Isle of Man) -Globalization.ci_ha = Hausa -Globalization.ci_ha-Latn = Hausa (Latin) -Globalization.ci_ha-Latn-GH = Hausa (Latin, Ghana) -Globalization.ci_ha-Latn-NE = Hausa (Latin, Niger) -Globalization.ci_ha-Latn-NG = Hausa (Latin, Nigeria) -Globalization.ci_haw = Hawaiian -Globalization.ci_haw-US = Hawaiian (United States) -Globalization.ci_he = Hebrew -Globalization.ci_he-IL = Hebrew (Israel) -Globalization.ci_hi = Hindi -Globalization.ci_hi-IN = Hindi (India) -Globalization.ci_hr = Croatian -Globalization.ci_hr-BA = Croatian (Latin, Bosnia and Herzegovina) -Globalization.ci_hr-HR = Croatian (Croatia) -Globalization.ci_hsb = Upper Sorbian -Globalization.ci_hsb-DE = Upper Sorbian (Germany) -Globalization.ci_hu = Hungarian -Globalization.ci_hu-HU = Hungarian (Hungary) -Globalization.ci_hu-HU_technl = Hungarian (Hungary) -Globalization.ci_hy = Armenian -Globalization.ci_hy-AM = Armenian (Armenia) -Globalization.ci_ia = Interlingua -Globalization.ci_ia-001 = Interlingua (World) -Globalization.ci_ia-FR = Interlingua (France) -Globalization.ci_id = Indonesian -Globalization.ci_id-ID = Indonesian (Indonesia) -Globalization.ci_ig = Igbo -Globalization.ci_ig-NG = Igbo (Nigeria) -Globalization.ci_ii = Yi -Globalization.ci_ii-CN = Yi (PRC) -Globalization.ci_is = Icelandic -Globalization.ci_is-IS = Icelandic (Iceland) -Globalization.ci_it = Italian -Globalization.ci_it-CH = Italian (Switzerland) -Globalization.ci_it-IT = Italian (Italy) -Globalization.ci_it-SM = Italian (San Marino) -Globalization.ci_iu = Inuktitut -Globalization.ci_iu-Cans = Inuktitut (Syllabics) -Globalization.ci_iu-Cans-CA = Inuktitut (Syllabics, Canada) -Globalization.ci_iu-Latn = Inuktitut (Latin) -Globalization.ci_iu-Latn-CA = Inuktitut (Latin, Canada) -Globalization.ci_ja = Japanese -Globalization.ci_ja-JP = Japanese (Japan) -Globalization.ci_ja-JP_radstr = Japanese (Japan) -Globalization.ci_jgo = Ngomba -Globalization.ci_jgo-CM = Ngomba (Cameroon) -Globalization.ci_jmc = Machame -Globalization.ci_jmc-TZ = Machame (Tanzania) -Globalization.ci_jv = Javanese -Globalization.ci_jv-Latn = Javanese -Globalization.ci_jv-Latn-ID = Javanese (Indonesia) -Globalization.ci_ka = Georgian -Globalization.ci_ka-GE = Georgian (Georgia) -Globalization.ci_ka-GE_modern = Georgian (Georgia) -Globalization.ci_kab = Kabyle -Globalization.ci_kab-DZ = Kabyle (Algeria) -Globalization.ci_kam = Kamba -Globalization.ci_kam-KE = Kamba (Kenya) -Globalization.ci_kde = Makonde -Globalization.ci_kde-TZ = Makonde (Tanzania) -Globalization.ci_kea = Kabuverdianu -Globalization.ci_kea-CV = Kabuverdianu (Cabo Verde) -Globalization.ci_khq = Koyra Chiini -Globalization.ci_khq-ML = Koyra Chiini (Mali) -Globalization.ci_ki = Kikuyu -Globalization.ci_ki-KE = Kikuyu (Kenya) -Globalization.ci_kk = Kazakh -Globalization.ci_kk-KZ = Kazakh (Kazakhstan) -Globalization.ci_kkj = Kako -Globalization.ci_kkj-CM = Kako (Cameroon) -Globalization.ci_kl = Greenlandic -Globalization.ci_kl-GL = Greenlandic (Greenland) -Globalization.ci_kln = Kalenjin -Globalization.ci_kln-KE = Kalenjin (Kenya) -Globalization.ci_km = Khmer -Globalization.ci_km-KH = Khmer (Cambodia) -Globalization.ci_kn = Kannada -Globalization.ci_kn-IN = Kannada (India) -Globalization.ci_ko = Korean -Globalization.ci_ko-KR = Korean (Korea) -Globalization.ci_kok = Konkani -Globalization.ci_kok-IN = Konkani (India) -Globalization.ci_ks = Kashmiri -Globalization.ci_ks-Arab = Kashmiri (Perso-Arabic) -Globalization.ci_ks-Arab-IN = Kashmiri (Perso-Arabic) -Globalization.ci_ksb = Shambala -Globalization.ci_ksb-TZ = Shambala (Tanzania) -Globalization.ci_ksf = Bafia -Globalization.ci_ksf-CM = Bafia (Cameroon) -Globalization.ci_ksh = Colognian -Globalization.ci_ksh-DE = Ripuarian (Germany) -Globalization.ci_ku = Central Kurdish -Globalization.ci_ku-Arab = Central Kurdish (Arabic) -Globalization.ci_ku-Arab-IQ = Central Kurdish (Iraq) -Globalization.ci_kw = Cornish -Globalization.ci_kw-GB = Cornish (United Kingdom) -Globalization.ci_ky = Kyrgyz -Globalization.ci_ky-KG = Kyrgyz (Kyrgyzstan) -Globalization.ci_lag = Langi -Globalization.ci_lag-TZ = Langi (Tanzania) -Globalization.ci_lb = Luxembourgish -Globalization.ci_lb-LU = Luxembourgish (Luxembourg) -Globalization.ci_lg = Ganda -Globalization.ci_lg-UG = Ganda (Uganda) -Globalization.ci_lkt = Lakota -Globalization.ci_lkt-US = Lakota (United States) -Globalization.ci_ln = Lingala -Globalization.ci_ln-AO = Lingala (Angola) -Globalization.ci_ln-CD = Lingala (Congo DRC) -Globalization.ci_ln-CF = Lingala (Central African Republic) -Globalization.ci_ln-CG = Lingala (Congo) -Globalization.ci_lo = Lao -Globalization.ci_lo-LA = Lao (Lao P.D.R.) -Globalization.ci_lt = Lithuanian -Globalization.ci_lt-LT = Lithuanian (Lithuania) -Globalization.ci_lu = Luba-Katanga -Globalization.ci_lu-CD = Luba-Katanga (Congo DRC) -Globalization.ci_luo = Luo -Globalization.ci_luo-KE = Luo (Kenya) -Globalization.ci_luy = Luyia -Globalization.ci_luy-KE = Luyia (Kenya) -Globalization.ci_lv = Latvian -Globalization.ci_lv-LV = Latvian (Latvia) -Globalization.ci_mas = Masai -Globalization.ci_mas-KE = Masai (Kenya) -Globalization.ci_mas-TZ = Masai (Tanzania) -Globalization.ci_mer = Meru -Globalization.ci_mer-KE = Meru (Kenya) -Globalization.ci_mfe = Morisyen -Globalization.ci_mfe-MU = Morisyen (Mauritius) -Globalization.ci_mg = Malagasy -Globalization.ci_mg-MG = Malagasy (Madagascar) -Globalization.ci_mgh = Makhuwa-Meetto -Globalization.ci_mgh-MZ = Makhuwa-Meetto (Mozambique) -Globalization.ci_mgo = Meta' -Globalization.ci_mgo-CM = Meta' (Cameroon) -Globalization.ci_mi = Maori -Globalization.ci_mi-NZ = Maori (New Zealand) -Globalization.ci_mk = Macedonian (FYROM) -Globalization.ci_mk-MK = Macedonian (Former Yugoslav Republic of Macedonia) -Globalization.ci_ml = Malayalam -Globalization.ci_ml-IN = Malayalam (India) -Globalization.ci_mn = Mongolian -Globalization.ci_mn-Cyrl = Mongolian (Cyrillic) -Globalization.ci_mn-MN = Mongolian (Cyrillic, Mongolia) -Globalization.ci_mn-Mong = Mongolian (Traditional Mongolian) -Globalization.ci_mn-Mong-CN = Mongolian (Traditional Mongolian, PRC) -Globalization.ci_mn-Mong-MN = Mongolian (Traditional Mongolian, Mongolia) -Globalization.ci_moh = Mohawk -Globalization.ci_moh-CA = Mohawk (Mohawk) -Globalization.ci_mr = Marathi -Globalization.ci_mr-IN = Marathi (India) -Globalization.ci_ms = Malay -Globalization.ci_ms-BN = Malay (Brunei Darussalam) -Globalization.ci_ms-MY = Malay (Malaysia) -Globalization.ci_ms-SG = Malay (Latin, Singapore) -Globalization.ci_mt = Maltese -Globalization.ci_mt-MT = Maltese (Malta) -Globalization.ci_mua = Mundang -Globalization.ci_mua-CM = Mundang (Cameroon) -Globalization.ci_my = Burmese -Globalization.ci_my-MM = Burmese (Myanmar) -Globalization.ci_naq = Nama -Globalization.ci_naq-NA = Nama (Namibia) -Globalization.ci_nb = Norwegian (BokmÃ¥l) -Globalization.ci_nb-NO = Norwegian, BokmÃ¥l (Norway) -Globalization.ci_nb-SJ = Norwegian, BokmÃ¥l (Svalbard and Jan Mayen) -Globalization.ci_nd = North Ndebele -Globalization.ci_nd-ZW = North Ndebele (Zimbabwe) -Globalization.ci_ne = Nepali -Globalization.ci_ne-IN = Nepali (India) -Globalization.ci_ne-NP = Nepali (Nepal) -Globalization.ci_nl = Dutch -Globalization.ci_nl-AW = Dutch (Aruba) -Globalization.ci_nl-BE = Dutch (Belgium) -Globalization.ci_nl-BQ = Dutch (Bonaire, Sint Eustatius and Saba) -Globalization.ci_nl-CW = Dutch (Curaçao) -Globalization.ci_nl-NL = Dutch (Netherlands) -Globalization.ci_nl-SR = Dutch (Suriname) -Globalization.ci_nl-SX = Dutch (Sint Maarten) -Globalization.ci_nmg = Kwasio -Globalization.ci_nmg-CM = Kwasio (Cameroon) -Globalization.ci_nn = Norwegian (Nynorsk) -Globalization.ci_nn-NO = Norwegian, Nynorsk (Norway) -Globalization.ci_nnh = Ngiemboon -Globalization.ci_nnh-CM = Ngiemboon (Cameroon) -Globalization.ci_no = Norwegian -Globalization.ci_nqo = N'ko -Globalization.ci_nqo-GN = N'ko (Guinea) -Globalization.ci_nr = South Ndebele -Globalization.ci_nr-ZA = South Ndebele (South Africa) -Globalization.ci_nso = Sesotho sa Leboa -Globalization.ci_nso-ZA = Sesotho sa Leboa (South Africa) -Globalization.ci_nus = Nuer -Globalization.ci_nus-SD = Nuer (Sudan) -Globalization.ci_nyn = Nyankole -Globalization.ci_nyn-UG = Nyankole (Uganda) -Globalization.ci_oc = Occitan -Globalization.ci_oc-FR = Occitan (France) -Globalization.ci_om = Oromo -Globalization.ci_om-ET = Oromo (Ethiopia) -Globalization.ci_om-KE = Oromo (Kenya) -Globalization.ci_or = Odia -Globalization.ci_or-IN = Odia (India) -Globalization.ci_os = Ossetic -Globalization.ci_os-GE = Ossetian (Cyrillic, Georgia) -Globalization.ci_os-RU = Ossetian (Cyrillic, Russia) -Globalization.ci_pa = Punjabi -Globalization.ci_pa-Arab = Punjabi (Arabic) -Globalization.ci_pa-Arab-PK = Punjabi (Islamic Republic of Pakistan) -Globalization.ci_pa-IN = Punjabi (India) -Globalization.ci_pl = Polish -Globalization.ci_pl-PL = Polish (Poland) -Globalization.ci_prs = Dari -Globalization.ci_prs-AF = Dari (Afghanistan) -Globalization.ci_ps = Pashto -Globalization.ci_ps-AF = Pashto (Afghanistan) -Globalization.ci_pt = Portuguese -Globalization.ci_pt-AO = Portuguese (Angola) -Globalization.ci_pt-BR = Portuguese (Brazil) -Globalization.ci_pt-CV = Portuguese (Cabo Verde) -Globalization.ci_pt-GW = Portuguese (Guinea-Bissau) -Globalization.ci_pt-MO = Portuguese (Macao SAR) -Globalization.ci_pt-MZ = Portuguese (Mozambique) -Globalization.ci_pt-PT = Portuguese (Portugal) -Globalization.ci_pt-ST = Portuguese (São Tomé and Príncipe) -Globalization.ci_pt-TL = Portuguese (Timor-Leste) -Globalization.ci_qps-ploc = Pseudo Language (Pseudo) -Globalization.ci_qps-ploca = Pseudo Language (Pseudo Asia) -Globalization.ci_qps-plocm = Pseudo Language (Pseudo Mirrored) -Globalization.ci_qu = Quechua -Globalization.ci_qu-BO = Quechua (Bolivia) -Globalization.ci_qu-EC = Quechua (Ecuador) -Globalization.ci_qu-PE = Quechua (Peru) -Globalization.ci_quc = K'iche' -Globalization.ci_quc-Latn = K'iche' -Globalization.ci_quc-Latn-GT = K'iche' (Guatemala) -Globalization.ci_qut = K'iche -Globalization.ci_qut-GT = K'iche (Guatemala) -Globalization.ci_quz = Quechua -Globalization.ci_quz-BO = Quechua (Bolivia) -Globalization.ci_quz-EC = Quechua (Ecuador) -Globalization.ci_quz-PE = Quechua (Peru) -Globalization.ci_rm = Romansh -Globalization.ci_rm-CH = Romansh (Switzerland) -Globalization.ci_rn = Rundi -Globalization.ci_rn-BI = Rundi (Burundi) -Globalization.ci_ro = Romanian -Globalization.ci_ro-MD = Romanian (Moldova) -Globalization.ci_ro-RO = Romanian (Romania) -Globalization.ci_rof = Rombo -Globalization.ci_rof-TZ = Rombo (Tanzania) -Globalization.ci_ru = Russian -Globalization.ci_ru-BY = Russian (Belarus) -Globalization.ci_ru-KG = Russian (Kyrgyzstan) -Globalization.ci_ru-KZ = Russian (Kazakhstan) -Globalization.ci_ru-MD = Russian (Moldova) -Globalization.ci_ru-RU = Russian (Russia) -Globalization.ci_ru-UA = Russian (Ukraine) -Globalization.ci_rw = Kinyarwanda -Globalization.ci_rw-RW = Kinyarwanda (Rwanda) -Globalization.ci_rwk = Rwa -Globalization.ci_rwk-TZ = Rwa (Tanzania) -Globalization.ci_sa = Sanskrit -Globalization.ci_sa-IN = Sanskrit (India) -Globalization.ci_sah = Sakha -Globalization.ci_sah-RU = Sakha (Russia) -Globalization.ci_saq = Samburu -Globalization.ci_saq-KE = Samburu (Kenya) -Globalization.ci_sbp = Sangu -Globalization.ci_sbp-TZ = Sangu (Tanzania) -Globalization.ci_sd = Sindhi -Globalization.ci_sd-Arab = Sindhi (Arabic) -Globalization.ci_sd-Arab-PK = Sindhi (Islamic Republic of Pakistan) -Globalization.ci_se = Sami (Northern) -Globalization.ci_se-FI = Sami, Northern (Finland) -Globalization.ci_se-NO = Sami, Northern (Norway) -Globalization.ci_se-SE = Sami, Northern (Sweden) -Globalization.ci_seh = Sena -Globalization.ci_seh-MZ = Sena (Mozambique) -Globalization.ci_ses = Koyraboro Senni -Globalization.ci_ses-ML = Koyraboro Senni (Mali) -Globalization.ci_sg = Sango -Globalization.ci_sg-CF = Sango (Central African Republic) -Globalization.ci_shi = Tachelhit -Globalization.ci_shi-Latn = Tachelhit (Latin) -Globalization.ci_shi-Latn-MA = Tachelhit (Latin, Morocco) -Globalization.ci_shi-Tfng = Tachelhit (Tifinagh) -Globalization.ci_shi-Tfng-MA = Tachelhit (Tifinagh, Morocco) -Globalization.ci_si = Sinhala -Globalization.ci_si-LK = Sinhala (Sri Lanka) -Globalization.ci_sk = Slovak -Globalization.ci_sk-SK = Slovak (Slovakia) -Globalization.ci_sl = Slovenian -Globalization.ci_sl-SI = Slovenian (Slovenia) -Globalization.ci_sma = Sami (Southern) -Globalization.ci_sma-NO = Sami, Southern (Norway) -Globalization.ci_sma-SE = Sami, Southern (Sweden) -Globalization.ci_smj = Sami (Lule) -Globalization.ci_smj-NO = Sami, Lule (Norway) -Globalization.ci_smj-SE = Sami, Lule (Sweden) -Globalization.ci_smn = Sami (Inari) -Globalization.ci_smn-FI = Sami, Inari (Finland) -Globalization.ci_sms = Sami (Skolt) -Globalization.ci_sms-FI = Sami, Skolt (Finland) -Globalization.ci_sn = Shona -Globalization.ci_sn-Latn = Shona (Latin) -Globalization.ci_sn-Latn-ZW = Shona (Latin, Zimbabwe) -Globalization.ci_so = Somali -Globalization.ci_so-DJ = Somali (Djibouti) -Globalization.ci_so-ET = Somali (Ethiopia) -Globalization.ci_so-KE = Somali (Kenya) -Globalization.ci_so-SO = Somali (Somalia) -Globalization.ci_sq = Albanian -Globalization.ci_sq-AL = Albanian (Albania) -Globalization.ci_sq-MK = Albanian (Macedonia, FYRO) -Globalization.ci_sr = Serbian -Globalization.ci_sr-Cyrl = Serbian (Cyrillic) -Globalization.ci_sr-Cyrl-BA = Serbian (Cyrillic, Bosnia and Herzegovina) -Globalization.ci_sr-Cyrl-CS = Serbian (Cyrillic, Serbia and Montenegro (Former)) -Globalization.ci_sr-Cyrl-ME = Serbian (Cyrillic, Montenegro) -Globalization.ci_sr-Cyrl-RS = Serbian (Cyrillic, Serbia) -Globalization.ci_sr-Latn = Serbian (Latin) -Globalization.ci_sr-Latn-BA = Serbian (Latin, Bosnia and Herzegovina) -Globalization.ci_sr-Latn-CS = Serbian (Latin, Serbia and Montenegro (Former)) -Globalization.ci_sr-Latn-ME = Serbian (Latin, Montenegro) -Globalization.ci_sr-Latn-RS = Serbian (Latin, Serbia) -Globalization.ci_ss = Swati -Globalization.ci_ss-SZ = Swati (Swaziland) -Globalization.ci_ss-ZA = Swati (South Africa) -Globalization.ci_ssy = Saho -Globalization.ci_ssy-ER = Saho (Eritrea) -Globalization.ci_st = Southern Sotho -Globalization.ci_st-LS = Sesotho (Lesotho) -Globalization.ci_st-ZA = Southern Sotho (South Africa) -Globalization.ci_sv = Swedish -Globalization.ci_sv-AX = Swedish (Åland Islands) -Globalization.ci_sv-FI = Swedish (Finland) -Globalization.ci_sv-SE = Swedish (Sweden) -Globalization.ci_sw = Kiswahili -Globalization.ci_sw-KE = Kiswahili (Kenya) -Globalization.ci_sw-TZ = Kiswahili (Tanzania) -Globalization.ci_sw-UG = Kiswahili (Uganda) -Globalization.ci_swc = Congo Swahili -Globalization.ci_swc-CD = Congo Swahili (Congo DRC) -Globalization.ci_syr = Syriac -Globalization.ci_syr-SY = Syriac (Syria) -Globalization.ci_ta = Tamil -Globalization.ci_ta-IN = Tamil (India) -Globalization.ci_ta-LK = Tamil (Sri Lanka) -Globalization.ci_ta-MY = Tamil (Malaysia) -Globalization.ci_ta-SG = Tamil (Singapore) -Globalization.ci_te = Telugu -Globalization.ci_te-IN = Telugu (India) -Globalization.ci_teo = Teso -Globalization.ci_teo-KE = Teso (Kenya) -Globalization.ci_teo-UG = Teso (Uganda) -Globalization.ci_tg = Tajik -Globalization.ci_tg-Cyrl = Tajik (Cyrillic) -Globalization.ci_tg-Cyrl-TJ = Tajik (Cyrillic, Tajikistan) -Globalization.ci_th = Thai -Globalization.ci_th-TH = Thai (Thailand) -Globalization.ci_ti = Tigrinya -Globalization.ci_ti-ER = Tigrinya (Eritrea) -Globalization.ci_ti-ET = Tigrinya (Ethiopia) -Globalization.ci_tig = Tigre -Globalization.ci_tig-ER = Tigre (Eritrea) -Globalization.ci_tk = Turkmen -Globalization.ci_tk-TM = Turkmen (Turkmenistan) -Globalization.ci_tn = Setswana -Globalization.ci_tn-BW = Setswana (Botswana) -Globalization.ci_tn-ZA = Setswana (South Africa) -Globalization.ci_to = Tongan -Globalization.ci_to-TO = Tongan (Tonga) -Globalization.ci_tr = Turkish -Globalization.ci_tr-CY = Turkish (Cyprus) -Globalization.ci_tr-TR = Turkish (Turkey) -Globalization.ci_ts = Tsonga -Globalization.ci_ts-ZA = Tsonga (South Africa) -Globalization.ci_tt = Tatar -Globalization.ci_tt-RU = Tatar (Russia) -Globalization.ci_twq = Tasawaq -Globalization.ci_twq-NE = Tasawaq (Niger) -Globalization.ci_tzm = Tamazight -Globalization.ci_tzm-Latn = Tamazight (Latin) -Globalization.ci_tzm-Latn-DZ = Tamazight (Latin, Algeria) -Globalization.ci_tzm-Latn-MA = Central Atlas Tamazight (Latin, Morocco) -Globalization.ci_tzm-Tfng = Tamazight (Tifinagh) -Globalization.ci_tzm-Tfng-MA = Central Atlas Tamazight (Tifinagh, Morocco) -Globalization.ci_ug = Uyghur -Globalization.ci_ug-CN = Uyghur (PRC) -Globalization.ci_uk = Ukrainian -Globalization.ci_uk-UA = Ukrainian (Ukraine) -Globalization.ci_ur = Urdu -Globalization.ci_ur-IN = Urdu (India) -Globalization.ci_ur-PK = Urdu (Islamic Republic of Pakistan) -Globalization.ci_uz = Uzbek -Globalization.ci_uz-Arab = Uzbek (Perso-Arabic) -Globalization.ci_uz-Arab-AF = Uzbek (Perso-Arabic, Afghanistan) -Globalization.ci_uz-Cyrl = Uzbek (Cyrillic) -Globalization.ci_uz-Cyrl-UZ = Uzbek (Cyrillic, Uzbekistan) -Globalization.ci_uz-Latn = Uzbek (Latin) -Globalization.ci_uz-Latn-UZ = Uzbek (Latin, Uzbekistan) -Globalization.ci_vai = Vai -Globalization.ci_vai-Latn = Vai (Latin) -Globalization.ci_vai-Latn-LR = Vai (Latin, Liberia) -Globalization.ci_vai-Vaii = Vai (Vai) -Globalization.ci_vai-Vaii-LR = Vai (Vai, Liberia) -Globalization.ci_ve = Venda -Globalization.ci_ve-ZA = Venda (South Africa) -Globalization.ci_vi = Vietnamese -Globalization.ci_vi-VN = Vietnamese (Vietnam) -Globalization.ci_vo = Volapük -Globalization.ci_vo-001 = Volapük (World) -Globalization.ci_vun = Vunjo -Globalization.ci_vun-TZ = Vunjo (Tanzania) -Globalization.ci_wae = Walser -Globalization.ci_wae-CH = Walser (Switzerland) -Globalization.ci_wal = Wolaytta -Globalization.ci_wal-ET = Wolaytta (Ethiopia) -Globalization.ci_wo = Wolof -Globalization.ci_wo-SN = Wolof (Senegal) -Globalization.ci_x-IV = Invariant Language (Invariant Country) -Globalization.ci_x-IV_mathan = Invariant Language (Invariant Country) -Globalization.ci_xh = isiXhosa -Globalization.ci_xh-ZA = isiXhosa (South Africa) -Globalization.ci_xog = Soga -Globalization.ci_xog-UG = Soga (Uganda) -Globalization.ci_yav = Yangben -Globalization.ci_yav-CM = Yangben (Cameroon) -Globalization.ci_yi = Yiddish -Globalization.ci_yi-001 = Yiddish (World) -Globalization.ci_yo = Yoruba -Globalization.ci_yo-BJ = Yoruba (Benin) -Globalization.ci_yo-NG = Yoruba (Nigeria) -Globalization.ci_zgh = Standard Moroccan Tamazight -Globalization.ci_zgh-Tfng = Standard Moroccan Tamazight (Tifinagh) -Globalization.ci_zgh-Tfng-MA = Standard Moroccan Tamazight (Tifinagh, Morocco) -Globalization.ci_zh = Chinese -Globalization.ci_zh-CHS = Chinese (Simplified) Legacy -Globalization.ci_zh-CHT = Chinese (Traditional) Legacy -Globalization.ci_zh-CN = Chinese (Simplified, PRC) -Globalization.ci_zh-CN_stroke = Chinese (Simplified, PRC) -Globalization.ci_zh-Hans = Chinese (Simplified) -Globalization.ci_zh-Hant = Chinese (Traditional) -Globalization.ci_zh-HK = Chinese (Traditional, Hong Kong S.A.R.) -Globalization.ci_zh-HK_radstr = Chinese (Traditional, Hong Kong S.A.R.) -Globalization.ci_zh-MO = Chinese (Traditional, Macao S.A.R.) -Globalization.ci_zh-MO_radstr = Chinese (Traditional, Macao S.A.R.) -Globalization.ci_zh-MO_stroke = Chinese (Traditional, Macao S.A.R.) -Globalization.ci_zh-SG = Chinese (Simplified, Singapore) -Globalization.ci_zh-SG_stroke = Chinese (Simplified, Singapore) -Globalization.ci_zh-TW = Chinese (Traditional, Taiwan) -Globalization.ci_zh-TW_pronun = Chinese (Traditional, Taiwan) -Globalization.ci_zh-TW_radstr = Chinese (Traditional, Taiwan) -Globalization.ci_zu = isiZulu -Globalization.ci_zu-ZA = isiZulu (South Africa) -;------------------ -; -;Total items: 129 -; -Globalization.ri_029 = Caribbean -Globalization.ri_AE = U.A.E. -Globalization.ri_AF = Afghanistan -Globalization.ri_AL = Albania -Globalization.ri_AM = Armenia -Globalization.ri_AR = Argentina -Globalization.ri_AT = Austria -Globalization.ri_AU = Australia -Globalization.ri_AZ = Azerbaijan -Globalization.ri_BA = Bosnia and Herzegovina -Globalization.ri_BD = Bangladesh -Globalization.ri_BE = Belgium -Globalization.ri_BG = Bulgaria -Globalization.ri_BH = Bahrain -Globalization.ri_BN = Brunei Darussalam -Globalization.ri_BO = Bolivia -Globalization.ri_BR = Brazil -Globalization.ri_BY = Belarus -Globalization.ri_BZ = Belize -Globalization.ri_CA = Canada -Globalization.ri_CH = Switzerland -Globalization.ri_CL = Chile -Globalization.ri_CN = People's Republic of China -Globalization.ri_CO = Colombia -Globalization.ri_CR = Costa Rica -Globalization.ri_CS = Serbia and Montenegro (Former) -Globalization.ri_CZ = Czech Republic -Globalization.ri_DE = Germany -Globalization.ri_DK = Denmark -Globalization.ri_DO = Dominican Republic -Globalization.ri_DZ = Algeria -Globalization.ri_EC = Ecuador -Globalization.ri_EE = Estonia -Globalization.ri_EG = Egypt -Globalization.ri_ER = Eritrea -Globalization.ri_ES = Spain -Globalization.ri_ET = Ethiopia -Globalization.ri_FI = Finland -Globalization.ri_FO = Faroe Islands -Globalization.ri_FR = France -Globalization.ri_GB = United Kingdom -Globalization.ri_GE = Georgia -Globalization.ri_GL = Greenland -Globalization.ri_GR = Greece -Globalization.ri_GT = Guatemala -Globalization.ri_HK = Hong Kong S.A.R. -Globalization.ri_HN = Honduras -Globalization.ri_HR = Croatia -Globalization.ri_HU = Hungary -Globalization.ri_ID = Indonesia -Globalization.ri_IE = Ireland -Globalization.ri_IL = Israel -Globalization.ri_IN = India -Globalization.ri_IQ = Iraq -Globalization.ri_IR = Iran -Globalization.ri_IS = Iceland -Globalization.ri_IT = Italy -Globalization.ri_IV = Invariant Country -Globalization.ri_JM = Jamaica -Globalization.ri_JO = Jordan -Globalization.ri_JP = Japan -Globalization.ri_KE = Kenya -Globalization.ri_KG = Kyrgyzstan -Globalization.ri_KH = Cambodia -Globalization.ri_KR = Korea -Globalization.ri_KW = Kuwait -Globalization.ri_KZ = Kazakhstan -Globalization.ri_LA = Lao P.D.R. -Globalization.ri_LB = Lebanon -Globalization.ri_LI = Liechtenstein -Globalization.ri_LK = Sri Lanka -Globalization.ri_LT = Lithuania -Globalization.ri_LU = Luxembourg -Globalization.ri_LV = Latvia -Globalization.ri_LY = Libya -Globalization.ri_MA = Morocco -Globalization.ri_MC = Principality of Monaco -Globalization.ri_ME = Montenegro -Globalization.ri_MK = Macedonia (FYROM) -Globalization.ri_MN = Mongolia -Globalization.ri_MO = Macao S.A.R. -Globalization.ri_MT = Malta -Globalization.ri_MV = Maldives -Globalization.ri_MX = Mexico -Globalization.ri_MY = Malaysia -Globalization.ri_NG = Nigeria -Globalization.ri_NI = Nicaragua -Globalization.ri_NL = Netherlands -Globalization.ri_NO = Norway -Globalization.ri_NP = Nepal -Globalization.ri_NZ = New Zealand -Globalization.ri_OM = Oman -Globalization.ri_PA = Panama -Globalization.ri_PE = Peru -Globalization.ri_PH = Philippines -Globalization.ri_PK = Islamic Republic of Pakistan -Globalization.ri_PL = Poland -Globalization.ri_PR = Puerto Rico -Globalization.ri_PT = Portugal -Globalization.ri_PY = Paraguay -Globalization.ri_QA = Qatar -Globalization.ri_RO = Romania -Globalization.ri_RS = Serbia -Globalization.ri_RU = Russia -Globalization.ri_RW = Rwanda -Globalization.ri_SA = Saudi Arabia -Globalization.ri_SE = Sweden -Globalization.ri_SG = Singapore -Globalization.ri_SI = Slovenia -Globalization.ri_SK = Slovakia -Globalization.ri_SN = Senegal -Globalization.ri_SV = El Salvador -Globalization.ri_SY = Syria -Globalization.ri_TH = Thailand -Globalization.ri_TJ = Tajikistan -Globalization.ri_TM = Turkmenistan -Globalization.ri_TN = Tunisia -Globalization.ri_TR = Turkey -Globalization.ri_TT = Trinidad and Tobago -Globalization.ri_TW = Taiwan -Globalization.ri_UA = Ukraine -Globalization.ri_US = United States -Globalization.ri_UY = Uruguay -Globalization.ri_UZ = Uzbekistan -Globalization.ri_VE = Bolivarian Republic of Venezuela -Globalization.ri_VN = Vietnam -Globalization.ri_YE = Yemen -Globalization.ri_ZA = South Africa -Globalization.ri_ZW = Zimbabwe -#endif //!FEATURE_CORECLR +; Buffers +ArgumentException_BufferNotFromPool=The buffer is not associated with this pool and may not be returned to it. ;------------------ ; Encoding names: diff --git a/src/mscorlib/src/System/Action.cs b/src/mscorlib/src/System/Action.cs index d6653c7..27f7faf 100644 --- a/src/mscorlib/src/System/Action.cs +++ b/src/mscorlib/src/System/Action.cs @@ -2,62 +2,23 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -namespace System { - using System.Runtime.CompilerServices; - +namespace System +{ public delegate void Action(T obj); // Action/Func delegates first shipped with .NET Framework 3.5 in System.Core.dll as part of LINQ // These were type forwarded to mscorlib.dll in .NET Framework 4.0 and in Silverlight 5.0 - -#if !FEATURE_CORECLR - [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] -#endif public delegate void Action(); - -#if !FEATURE_CORECLR - [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] -#endif public delegate void Action(T1 arg1, T2 arg2); - -#if !FEATURE_CORECLR - [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] -#endif public delegate void Action(T1 arg1, T2 arg2, T3 arg3); - -#if !FEATURE_CORECLR - [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] -#endif public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4); -#if !FEATURE_CORECLR - [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] -#endif public delegate TResult Func(); - -#if !FEATURE_CORECLR - [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] -#endif public delegate TResult Func(T arg); - -#if !FEATURE_CORECLR - [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] -#endif public delegate TResult Func(T1 arg1, T2 arg2); - -#if !FEATURE_CORECLR - [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] -#endif public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3); - -#if !FEATURE_CORECLR - [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] -#endif public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6); public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7); diff --git a/src/mscorlib/src/System/Activator.cs b/src/mscorlib/src/System/Activator.cs index 274b0e7..6fad8f3 100644 --- a/src/mscorlib/src/System/Activator.cs +++ b/src/mscorlib/src/System/Activator.cs @@ -16,10 +16,6 @@ namespace System { using System; using System.Reflection; using System.Runtime.Remoting; -#if FEATURE_REMOTING - using System.Runtime.Remoting.Activation; - using Message = System.Runtime.Remoting.Messaging.Message; -#endif using System.Security; using CultureInfo = System.Globalization.CultureInfo; using Evidence = System.Security.Policy.Evidence; @@ -34,7 +30,7 @@ namespace System { // Only statics, does not need to be marked with the serializable attribute [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_Activator))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public sealed class Activator : _Activator { internal const int LookupMask = 0x000000FF; @@ -60,7 +56,6 @@ namespace System { return CreateInstance(type, bindingAttr, binder, args, culture, null); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable static public Object CreateInstance(Type type, BindingFlags bindingAttr, @@ -70,7 +65,7 @@ namespace System { Object[] activationAttributes) { if ((object)type == null) - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); Contract.EndContractBlock(); if (type is System.Reflection.Emit.TypeBuilder) @@ -81,26 +76,13 @@ namespace System { bindingAttr |= Activator.ConstructorDefault; if (activationAttributes != null && activationAttributes.Length > 0){ - // If type does not derive from MBR - // throw notsupportedexception -#if FEATURE_REMOTING - if(type.IsMarshalByRef){ - // The fix below is preventative. - // - if(!(type.IsContextful)){ - if(activationAttributes.Length > 1 || !(activationAttributes[0] is UrlAttribute)) - throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonUrlAttrOnMBR")); - } - } - else -#endif - throw new NotSupportedException(Environment.GetResourceString("NotSupported_ActivAttrOnNonMBR" )); + throw new PlatformNotSupportedException(Environment.GetResourceString("NotSupported_ActivAttr" )); } RuntimeType rt = type.UnderlyingSystemType as RuntimeType; if (rt == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"type"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), nameof(type)); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return rt.CreateInstanceImpl(bindingAttr,binder,args,culture,activationAttributes, ref stackMark); @@ -138,7 +120,6 @@ namespace System { * types to be created remotely without having to load the type locally. */ - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable static public ObjectHandle CreateInstance(String assemblyName, String typeName) @@ -156,7 +137,6 @@ namespace System { ref stackMark); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable static public ObjectHandle CreateInstance(String assemblyName, String typeName, @@ -180,13 +160,13 @@ namespace System { static public Object CreateInstance(Type type, bool nonPublic) { if ((object)type == null) - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); Contract.EndContractBlock(); RuntimeType rt = type.UnderlyingSystemType as RuntimeType; if (rt == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "type"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), nameof(type)); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return rt.CreateInstanceDefaultCtor(!nonPublic, false, true, ref stackMark); @@ -230,7 +210,6 @@ namespace System { activationAttributes); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of CreateInstance which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] static public ObjectHandle CreateInstance(String assemblyName, @@ -256,7 +235,6 @@ namespace System { ref stackMark); } - [SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static ObjectHandle CreateInstance(string assemblyName, string typeName, @@ -280,7 +258,6 @@ namespace System { ref stackMark); } - [System.Security.SecurityCritical] // auto-generated static internal ObjectHandle CreateInstance(String assemblyString, String typeName, bool ignoreCase, @@ -292,13 +269,6 @@ namespace System { Evidence securityInfo, ref StackCrawlMark stackMark) { -#if FEATURE_CAS_POLICY - if (securityInfo != null && !AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit")); - } -#endif // FEATURE_CAS_POLICY - Type type = null; Assembly assembly = null; if (assemblyString == null) { @@ -356,13 +326,6 @@ namespace System { Evidence securityInfo) { -#if FEATURE_CAS_POLICY - if (securityInfo != null && !AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit")); - } -#endif // FEATURE_CAS_POLICY - return CreateInstanceFromInternal(assemblyFile, typeName, ignoreCase, @@ -404,10 +367,6 @@ namespace System { Object[] activationAttributes, Evidence securityInfo) { -#if FEATURE_CAS_POLICY - Contract.Assert(AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled || securityInfo == null); -#endif // FEATURE_CAS_POLICY - #pragma warning disable 618 Assembly assembly = Assembly.LoadFrom(assemblyFile, securityInfo); #pragma warning restore 618 @@ -436,15 +395,13 @@ namespace System { // to pass the security checks when activating the type. // - [System.Security.SecurityCritical] // auto-generated_required public static ObjectHandle CreateInstance (AppDomain domain, string assemblyName, string typeName) { if (domain == null) - throw new ArgumentNullException("domain"); + throw new ArgumentNullException(nameof(domain)); Contract.EndContractBlock(); return domain.InternalCreateInstanceWithNoSecurity(assemblyName, typeName); } - [System.Security.SecurityCritical] // auto-generated_required [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of CreateInstance which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] public static ObjectHandle CreateInstance (AppDomain domain, string assemblyName, @@ -457,20 +414,12 @@ namespace System { Object[] activationAttributes, Evidence securityAttributes) { if (domain == null) - throw new ArgumentNullException("domain"); + throw new ArgumentNullException(nameof(domain)); Contract.EndContractBlock(); -#if FEATURE_CAS_POLICY - if (securityAttributes != null && !AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit")); - } -#endif // FEATURE_CAS_POLICY - return domain.InternalCreateInstanceWithNoSecurity(assemblyName, typeName, ignoreCase, bindingAttr, binder, args, culture, activationAttributes, securityAttributes); } - [SecurityCritical] public static ObjectHandle CreateInstance(AppDomain domain, string assemblyName, string typeName, @@ -482,7 +431,7 @@ namespace System { object[] activationAttributes) { if (domain == null) - throw new ArgumentNullException("domain"); + throw new ArgumentNullException(nameof(domain)); Contract.EndContractBlock(); return domain.InternalCreateInstanceWithNoSecurity(assemblyName, @@ -503,15 +452,13 @@ namespace System { // to pass the security checks when activating the type. // - [System.Security.SecurityCritical] // auto-generated_required public static ObjectHandle CreateInstanceFrom (AppDomain domain, string assemblyFile, string typeName) { if (domain == null) - throw new ArgumentNullException("domain"); + throw new ArgumentNullException(nameof(domain)); Contract.EndContractBlock(); return domain.InternalCreateInstanceFromWithNoSecurity(assemblyFile, typeName); } - [System.Security.SecurityCritical] // auto-generated_required [Obsolete("Methods which use Evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of CreateInstanceFrom which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] public static ObjectHandle CreateInstanceFrom (AppDomain domain, string assemblyFile, @@ -524,20 +471,12 @@ namespace System { Object[] activationAttributes, Evidence securityAttributes) { if (domain == null) - throw new ArgumentNullException("domain"); + throw new ArgumentNullException(nameof(domain)); Contract.EndContractBlock(); -#if FEATURE_CAS_POLICY - if (securityAttributes != null && !AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit")); - } -#endif // FEATURE_CAS_POLICY - return domain.InternalCreateInstanceFromWithNoSecurity(assemblyFile, typeName, ignoreCase, bindingAttr, binder, args, culture, activationAttributes, securityAttributes); } - [SecurityCritical] public static ObjectHandle CreateInstanceFrom(AppDomain domain, string assemblyFile, string typeName, @@ -549,7 +488,7 @@ namespace System { object[] activationAttributes) { if (domain == null) - throw new ArgumentNullException("domain"); + throw new ArgumentNullException(nameof(domain)); Contract.EndContractBlock(); return domain.InternalCreateInstanceFromWithNoSecurity(assemblyFile, @@ -563,28 +502,8 @@ namespace System { null); } -#if FEATURE_CLICKONCE - [System.Security.SecuritySafeCritical] // auto-generated - public static ObjectHandle CreateInstance (ActivationContext activationContext) { - AppDomainManager domainManager = AppDomain.CurrentDomain.DomainManager; - if (domainManager == null) - domainManager = new AppDomainManager(); - - return domainManager.ApplicationActivator.CreateInstance(activationContext); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public static ObjectHandle CreateInstance (ActivationContext activationContext, string[] activationCustomData) { - AppDomainManager domainManager = AppDomain.CurrentDomain.DomainManager; - if (domainManager == null) - domainManager = new AppDomainManager(); - - return domainManager.ApplicationActivator.CreateInstance(activationContext, activationCustomData); - } -#endif // FEATURE_CLICKONCE - public static ObjectHandle CreateComInstanceFrom(String assemblyName, - String typeName) + String typeName) { return CreateComInstanceFrom(assemblyName, typeName, @@ -630,38 +549,11 @@ namespace System { } } -#if FEATURE_REMOTING - // This method is a helper method and delegates to the remoting - // services to do the actual work. - [System.Security.SecurityCritical] // auto-generated_required - static public Object GetObject(Type type, String url) - { - return GetObject(type, url, null); - } - - // This method is a helper method and delegates to the remoting - // services to do the actual work. - [System.Security.SecurityCritical] // auto-generated_required - static public Object GetObject(Type type, String url, Object state) - { - if (type == null) - throw new ArgumentNullException("type"); - Contract.EndContractBlock(); - return RemotingServices.Connect(type, url, state); - } -#endif - [System.Diagnostics.Conditional("_DEBUG")] private static void Log(bool test, string title, string success, string failure) { -#if FEATURE_REMOTING - if(test) - BCLDebug.Trace("REMOTE", "{0}{1}", title, success); - else - BCLDebug.Trace("REMOTE", "{0}{1}", title, failure); -#endif } - + void _Activator.GetTypeInfoCount(out uint pcTInfo) { throw new NotImplementedException(); diff --git a/src/mscorlib/src/System/AggregateException.cs b/src/mscorlib/src/System/AggregateException.cs index 064432a..c0f2122 100644 --- a/src/mscorlib/src/System/AggregateException.cs +++ b/src/mscorlib/src/System/AggregateException.cs @@ -69,7 +69,7 @@ namespace System { if (innerException == null) { - throw new ArgumentNullException("innerException"); + throw new ArgumentNullException(nameof(innerException)); } m_innerExceptions = new ReadOnlyCollection(new Exception[] { innerException }); @@ -149,7 +149,7 @@ namespace System { if (innerExceptions == null) { - throw new ArgumentNullException("innerExceptions"); + throw new ArgumentNullException(nameof(innerExceptions)); } // Copy exceptions to our internal array and validate them. We must copy them, @@ -227,7 +227,7 @@ namespace System { if (innerExceptionInfos == null) { - throw new ArgumentNullException("innerExceptionInfos"); + throw new ArgumentNullException(nameof(innerExceptionInfos)); } // Copy exceptions to our internal array and validate them. We must copy them, @@ -258,13 +258,12 @@ namespace System /// contains contextual information about the source or destination. /// The argument is null. /// The exception could not be deserialized correctly. - [SecurityCritical] protected AggregateException(SerializationInfo info, StreamingContext context) : base(info, context) { if (info == null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Exception[] innerExceptions = info.GetValue("InnerExceptions", typeof(Exception[])) as Exception[]; @@ -285,12 +284,11 @@ namespace System /// The that /// contains contextual information about the source or destination. /// The argument is null. - [SecurityCritical] public override void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } base.GetObjectData(info, context); @@ -351,7 +349,7 @@ namespace System { if (predicate == null) { - throw new ArgumentNullException("predicate"); + throw new ArgumentNullException(nameof(predicate)); } List unhandledExceptions = null; @@ -379,7 +377,8 @@ namespace System /// - /// Flattens an instances into a single, new instance. + /// Flattens the inner instances of by expanding its contained instances + /// into a new /// /// A new, flattened . /// diff --git a/src/mscorlib/src/System/AppContext/AppContext.cs b/src/mscorlib/src/System/AppContext/AppContext.cs index 0b0643d..41e4450 100644 --- a/src/mscorlib/src/System/AppContext/AppContext.cs +++ b/src/mscorlib/src/System/AppContext/AppContext.cs @@ -21,9 +21,6 @@ namespace System public static string BaseDirectory { -#if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] -#endif get { // The value of APP_CONTEXT_BASE_DIRECTORY key has to be a string and it is not allowed to be any other type. @@ -41,14 +38,53 @@ namespace System } } -#if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] -#endif public static object GetData(string name) { return AppDomain.CurrentDomain.GetData(name); } + public static void SetData(string name, object data) + { + AppDomain.CurrentDomain.SetData(name, data); + } + + public static event UnhandledExceptionEventHandler UnhandledException + { + add + { + AppDomain.CurrentDomain.UnhandledException += value; + } + + remove + { + AppDomain.CurrentDomain.UnhandledException -= value; + } + } + + public static event System.EventHandler FirstChanceException + { + add + { + AppDomain.CurrentDomain.FirstChanceException += value; + } + remove + { + AppDomain.CurrentDomain.FirstChanceException -= value; + } + } + + public static event System.EventHandler ProcessExit + { + add + { + AppDomain.CurrentDomain.ProcessExit += value; + } + remove + { + AppDomain.CurrentDomain.ProcessExit -= value; + } + } + #region Switch APIs static AppContext() { @@ -65,9 +101,9 @@ namespace System public static bool TryGetSwitch(string switchName, out bool isEnabled) { if (switchName == null) - throw new ArgumentNullException("switchName"); + throw new ArgumentNullException(nameof(switchName)); if (switchName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "switchName"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(switchName)); // By default, the switch is not enabled. isEnabled = false; @@ -161,9 +197,9 @@ namespace System public static void SetSwitch(string switchName, bool isEnabled) { if (switchName == null) - throw new ArgumentNullException("switchName"); + throw new ArgumentNullException(nameof(switchName)); if (switchName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "switchName"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(switchName)); SwitchValueState switchValue = (isEnabled ? SwitchValueState.HasTrueValue : SwitchValueState.HasFalseValue) | SwitchValueState.HasLookedForOverride; diff --git a/src/mscorlib/src/System/AppContext/AppContextDefaultValues.Defaults.cs b/src/mscorlib/src/System/AppContext/AppContextDefaultValues.Defaults.cs index c80913e..52bdf9d 100644 --- a/src/mscorlib/src/System/AppContext/AppContextDefaultValues.Defaults.cs +++ b/src/mscorlib/src/System/AppContext/AppContextDefaultValues.Defaults.cs @@ -12,10 +12,6 @@ namespace System internal static readonly string SwitchNoAsyncCurrentCulture = "Switch.System.Globalization.NoAsyncCurrentCulture"; internal static readonly string SwitchThrowExceptionIfDisposedCancellationTokenSource = "Switch.System.Threading.ThrowExceptionIfDisposedCancellationTokenSource"; internal static readonly string SwitchPreserveEventListnerObjectIdentity = "Switch.System.Diagnostics.EventSource.PreserveEventListnerObjectIdentity"; -#if FEATURE_PATHCOMPAT - internal static readonly string SwitchUseLegacyPathHandling = "Switch.System.IO.UseLegacyPathHandling"; - internal static readonly string SwitchBlockLongPaths = "Switch.System.IO.BlockLongPaths"; -#endif // This is a partial method. Platforms can provide an implementation of it that will set override values // from whatever mechanism is available on that platform. If no implementation is provided, the compiler is going to remove the calls @@ -43,13 +39,7 @@ namespace System AppContext.DefineSwitchDefault(SwitchNoAsyncCurrentCulture, true); AppContext.DefineSwitchDefault(SwitchThrowExceptionIfDisposedCancellationTokenSource, true); } -#if FEATURE_PATHCOMPAT - if (version <= 40601) - { - AppContext.DefineSwitchDefault(SwitchUseLegacyPathHandling, true); - AppContext.DefineSwitchDefault(SwitchBlockLongPaths, true); - } -#endif + break; } case "WindowsPhone": diff --git a/src/mscorlib/src/System/AppContext/AppContextDefaultValues.cs b/src/mscorlib/src/System/AppContext/AppContextDefaultValues.cs index 7ab7ffb..9f00e81 100644 --- a/src/mscorlib/src/System/AppContext/AppContextDefaultValues.cs +++ b/src/mscorlib/src/System/AppContext/AppContextDefaultValues.cs @@ -30,7 +30,6 @@ namespace System if (!TryParseFrameworkName(targetFrameworkMoniker, out identifier, out version, out profile)) { -#if FEATURE_CORECLR // If we can't parse the TFM or we don't have a TFM, default to latest behavior for all // switches (ie. all of them false). // If we want to use the latest behavior it is enough to set the value of the switch to string.Empty. @@ -39,11 +38,6 @@ namespace System // identifier we are simply saying -- don't turn on any switches, and we are going to get the latest // behavior for all the switches identifier = string.Empty; -#else - identifier = ".NETFramework"; - version = 40000; - profile = string.Empty; -#endif } } diff --git a/src/mscorlib/src/System/AppContext/AppContextSwitches.cs b/src/mscorlib/src/System/AppContext/AppContextSwitches.cs index 3a96ec2..5fdd2bc 100644 --- a/src/mscorlib/src/System/AppContext/AppContextSwitches.cs +++ b/src/mscorlib/src/System/AppContext/AppContextSwitches.cs @@ -39,36 +39,6 @@ namespace System } } -#if FEATURE_PATHCOMPAT - private static int _useLegacyPathHandling; - - /// - /// Use legacy path normalization logic and blocking of extended syntax. - /// - public static bool UseLegacyPathHandling - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return GetCachedSwitchValue(AppContextDefaultValues.SwitchUseLegacyPathHandling, ref _useLegacyPathHandling); - } - } - - private static int _blockLongPaths; - - /// - /// Throw PathTooLongException for paths greater than MAX_PATH or directories greater than 248 (as per CreateDirectory Win32 limitations) - /// - public static bool BlockLongPaths - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return GetCachedSwitchValue(AppContextDefaultValues.SwitchBlockLongPaths, ref _blockLongPaths); - } - } -#endif // FEATURE_PATHCOMPAT - // // Implementation details // diff --git a/src/mscorlib/src/System/AppDomain.cs b/src/mscorlib/src/System/AppDomain.cs index abaaf48..fe524c4 100644 --- a/src/mscorlib/src/System/AppDomain.cs +++ b/src/mscorlib/src/System/AppDomain.cs @@ -13,46 +13,29 @@ ** =============================================================================*/ -namespace System { +namespace System +{ using System; -#if FEATURE_CLICKONCE - using System.Deployment.Internal.Isolation; - using System.Deployment.Internal.Isolation.Manifest; - using System.Runtime.Hosting; -#endif using System.Reflection; using System.Runtime; using System.Runtime.CompilerServices; -#if FEATURE_REMOTING - using System.Runtime.Remoting.Channels; - using System.Runtime.Remoting.Contexts; -#endif using System.Security; using System.Security.Permissions; -#if FEATURE_IMPERSONATION - using System.Security.Principal; -#endif using System.Security.Policy; using System.Security.Util; using System.Collections; using System.Collections.Generic; using System.Threading; using System.Runtime.InteropServices; - using System.Runtime.Remoting; -#if FEATURE_REMOTING - using Context = System.Runtime.Remoting.Contexts.Context; -#endif + using System.Runtime.Remoting; using System.Reflection.Emit; using CultureInfo = System.Globalization.CultureInfo; -#if !FEATURE_CORECLR - using System.Globalization; -#endif using System.IO; using AssemblyHashAlgorithm = System.Configuration.Assemblies.AssemblyHashAlgorithm; using System.Text; - using Microsoft.Win32; using System.Runtime.ConstrainedExecution; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; #if FEATURE_EXCEPTION_NOTIFICATIONS using System.Runtime.ExceptionServices; @@ -107,10 +90,6 @@ namespace System { } } - - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif [Serializable] [ComVisible(true)] public delegate Assembly ResolveEventHandler(Object sender, ResolveEventArgs args); @@ -177,7 +156,6 @@ namespace System { Info = itemInfo.ToArray(); } - [System.Security.SecuritySafeCritical] // auto-generated internal AppDomainInitializer Unwrap() { if (Info==null) @@ -204,17 +182,13 @@ namespace System { [ComDefaultInterface(typeof(System._AppDomain))] [ComVisible(true)] public sealed class AppDomain : -#if FEATURE_REMOTING - MarshalByRefObject, -#endif _AppDomain, IEvidenceFactory { // Domain security information // These fields initialized from the other side only. (NOTE: order // of these fields cannot be changed without changing the layout in - // the EE) + // the EE- AppDomainBaseObject in this case) - [System.Security.SecurityCritical] // auto-generated private AppDomainManager _domainManager; private Dictionary _LocalStore; private AppDomainSetup _FusionStore; @@ -225,12 +199,10 @@ namespace System { [method: System.Security.SecurityCritical] public event AssemblyLoadEventHandler AssemblyLoad; - [System.Security.SecurityCritical] private ResolveEventHandler _TypeResolve; public event ResolveEventHandler TypeResolve { - [System.Security.SecurityCritical] add { lock (this) @@ -239,7 +211,6 @@ namespace System { } } - [System.Security.SecurityCritical] remove { lock (this) @@ -249,12 +220,10 @@ namespace System { } } - [System.Security.SecurityCritical] private ResolveEventHandler _ResourceResolve; public event ResolveEventHandler ResourceResolve { - [System.Security.SecurityCritical] add { lock (this) @@ -263,7 +232,6 @@ namespace System { } } - [System.Security.SecurityCritical] remove { lock (this) @@ -273,12 +241,10 @@ namespace System { } } - [System.Security.SecurityCritical] private ResolveEventHandler _AssemblyResolve; public event ResolveEventHandler AssemblyResolve { - [System.Security.SecurityCritical] add { lock (this) @@ -287,7 +253,6 @@ namespace System { } } - [System.Security.SecurityCritical] remove { lock (this) @@ -302,38 +267,13 @@ namespace System { public event ResolveEventHandler ReflectionOnlyAssemblyResolve; #endif // FEATURE_REFLECTION_ONLY -#if FEATURE_REMOTING - private Context _DefaultContext; -#endif - -#if FEATURE_CLICKONCE - private ActivationContext _activationContext; - private ApplicationIdentity _applicationIdentity; -#endif private ApplicationTrust _applicationTrust; - -#if FEATURE_IMPERSONATION - private IPrincipal _DefaultPrincipal; -#endif // FEATURE_IMPERSONATION -#if FEATURE_REMOTING - private DomainSpecificRemotingData _RemotingData; -#endif private EventHandler _processExit; - #if FEATURE_CORECLR - [System.Security.SecurityCritical] - #endif private EventHandler _domainUnload; - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif private UnhandledExceptionEventHandler _unhandledException; -#if FEATURE_APTCA - private String[] _aptcaVisibleAssemblies; -#endif - // The compat flags are set at domain creation time to indicate that the given breaking // changes (named in the strings) should not be used in this domain. We only use the // keys, the vhe values are ignored. @@ -346,9 +286,6 @@ namespace System { private IntPtr _pDomain; // this is an unmanaged pointer (AppDomain * m_pDomain)` used from the VM. -#if FEATURE_CAS_POLICY - private PrincipalPolicy _PrincipalPolicy; // this is an enum -#endif private bool _HasSetPolicy; private bool _IsFastFullTrustDomain; // quick check to see if the AppDomain is fully trusted and homogenous private bool _compatFlagsInitialized; @@ -378,20 +315,18 @@ namespace System { private static APPX_FLAGS Flags { - [SecuritySafeCritical] get { if (s_flags == 0) s_flags = nGetAppXFlags(); - Contract.Assert(s_flags != 0); + Debug.Assert(s_flags != 0); return s_flags; } } internal static bool ProfileAPICheck { - [SecuritySafeCritical] get { return (Flags & APPX_FLAGS.APPX_FLAGS_API_CHECK) != 0; @@ -400,7 +335,6 @@ namespace System { internal static bool IsAppXNGen { - [SecuritySafeCritical] get { return (Flags & APPX_FLAGS.APPX_FLAGS_APPX_NGEN) != 0; @@ -409,56 +343,37 @@ namespace System { #endif // FEATURE_APPX [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SecurityCritical] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool DisableFusionUpdatesFromADManager(AppDomainHandle domain); #if FEATURE_APPX [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SecurityCritical] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.I4)] private static extern APPX_FLAGS nGetAppXFlags(); #endif [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SecurityCritical] [SuppressUnmanagedCodeSecurity] private static extern void GetAppDomainManagerType(AppDomainHandle domain, StringHandleOnStack retAssembly, StringHandleOnStack retType); [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SecurityCritical] [SuppressUnmanagedCodeSecurity] private static extern void SetAppDomainManagerType(AppDomainHandle domain, string assembly, string type); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void nSetHostSecurityManagerFlags (HostSecurityManagerOptions flags); - [SecurityCritical] [SuppressUnmanagedCodeSecurity] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] private static extern void SetSecurityHomogeneousFlag(AppDomainHandle domain, [MarshalAs(UnmanagedType.Bool)] bool runtimeSuppliedHomogenousGrantSet); -#if FEATURE_CAS_POLICY - [SecurityCritical] - [SuppressUnmanagedCodeSecurity] - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - private static extern void SetLegacyCasPolicyEnabled(AppDomainHandle domain); - - [SecurityCritical] - private void SetLegacyCasPolicyEnabled() - { - SetLegacyCasPolicyEnabled(GetNativeHandle()); - } -#endif // FEATURE_CAS_POLICY - /// /// Get a handle used to make a call into the VM pointing to this domain /// @@ -471,9 +386,6 @@ namespace System { throw new InvalidOperationException(Environment.GetResourceString("Argument_InvalidHandle")); } -#if FEATURE_REMOTING - BCLDebug.Assert(!RemotingServices.IsTransparentProxy(this), "QCalls should be made with the real AppDomain object rather than a transparent proxy"); -#endif // FEATURE_REMOTING return new AppDomainHandle(_pDomain); } @@ -481,10 +393,9 @@ namespace System { /// If this AppDomain is configured to have an AppDomain manager then create the instance of it. /// This method is also called from the VM to create the domain manager in the default domain. /// - [SecuritySafeCritical] private void CreateAppDomainManager() { - Contract.Assert(_domainManager == null, "_domainManager == null"); + Debug.Assert(_domainManager == null, "_domainManager == null"); AppDomainSetup adSetup = FusionStore; #if FEATURE_VERSIONING @@ -566,17 +477,9 @@ namespace System { if (notifyFusion) SetupFusionStore(_FusionStore, FusionStoreOld); // Notify Fusion about the changes the user implementation of InitializeNewDomain may have made to the FusionStore object. - -#if FEATURE_APPDOMAINMANAGER_INITOPTIONS - AppDomainManagerInitializationOptions flags = _domainManager.InitializationFlags; - if ((flags & AppDomainManagerInitializationOptions.RegisterWithHost) == AppDomainManagerInitializationOptions.RegisterWithHost) - { - _domainManager.RegisterWithHost(); - } -#endif // FEATURE_APPDOMAINMANAGER_INITOPTIONS } - InitializeCompatibilityFlags(); + InitializeCompatibilityFlags(); } /// @@ -596,7 +499,7 @@ namespace System { // for perf, we don't intialize the _compatFlags dictionary when we don't need to. However, we do need to make a // note that we've run this method, because IsCompatibilityFlagsSet needs to return different values for the // case where the compat flags have been setup. - Contract.Assert(!_compatFlagsInitialized); + Debug.Assert(!_compatFlagsInitialized); _compatFlagsInitialized = true; CompatibilitySwitches.InitializeSwitches(); @@ -606,7 +509,6 @@ namespace System { // either by a host in native, a host in managed using an AppDomainSetup, or by the // TargetFrameworkAttribute on the executable (VS emits its target framework moniker using this // attribute starting in version 4). - [SecuritySafeCritical] internal String GetTargetFrameworkName() { String targetFrameworkName = _FusionStore.TargetFrameworkName; @@ -621,7 +523,7 @@ namespace System { TargetFrameworkAttribute[] attrs = (TargetFrameworkAttribute[])assembly.GetCustomAttributes(typeof(TargetFrameworkAttribute)); if (attrs != null && attrs.Length > 0) { - Contract.Assert(attrs.Length == 1); + Debug.Assert(attrs.Length == 1); targetFrameworkName = attrs[0].FrameworkName; _FusionStore.TargetFrameworkName = targetFrameworkName; } @@ -635,7 +537,6 @@ namespace System { /// /// Returns the setting of the corresponding compatibility config switch (see CreateAppDomainManager for the impact). /// - [SecuritySafeCritical] internal bool DisableFusionUpdatesFromADManager() { return DisableFusionUpdatesFromADManager(GetNativeHandle()); @@ -644,7 +545,6 @@ namespace System { /// /// Returns whether the current AppDomain follows the AppX rules. /// - [SecuritySafeCritical] [Pure] internal static bool IsAppXModel() { @@ -658,7 +558,6 @@ namespace System { /// /// Returns the setting of the AppXDevMode config switch. /// - [SecuritySafeCritical] [Pure] internal static bool IsAppXDesignMode() { @@ -672,7 +571,6 @@ namespace System { /// /// Checks (and throws on failure) if the domain supports Assembly.LoadFrom. /// - [SecuritySafeCritical] [Pure] internal static void CheckLoadFromSupported() { @@ -685,7 +583,6 @@ namespace System { /// /// Checks (and throws on failure) if the domain supports Assembly.LoadFile. /// - [SecuritySafeCritical] [Pure] internal static void CheckLoadFileSupported() { @@ -698,7 +595,6 @@ namespace System { /// /// Checks (and throws on failure) if the domain supports Assembly.ReflectionOnlyLoad. /// - [SecuritySafeCritical] [Pure] internal static void CheckReflectionOnlyLoadSupported() { @@ -711,7 +607,6 @@ namespace System { /// /// Checks (and throws on failure) if the domain supports Assembly.LoadWithPartialName. /// - [SecuritySafeCritical] [Pure] internal static void CheckLoadWithPartialNameSupported(StackCrawlMark stackMark) { @@ -731,7 +626,6 @@ namespace System { /// /// Checks (and throws on failure) if the domain supports DefinePInvokeMethod. /// - [SecuritySafeCritical] [Pure] internal static void CheckDefinePInvokeSupported() { @@ -745,7 +639,6 @@ namespace System { /// /// Checks (and throws on failure) if the domain supports Assembly.Load(byte[] ...). /// - [SecuritySafeCritical] [Pure] internal static void CheckLoadByteArraySupported() { @@ -758,7 +651,6 @@ namespace System { /// /// Checks (and throws on failure) if the domain supports AppDomain.CreateDomain. /// - [SecuritySafeCritical] [Pure] internal static void CheckCreateDomainSupported() { @@ -779,7 +671,6 @@ namespace System { /// /// Get the name of the assembly and type that act as the AppDomainManager for this domain /// - [SecuritySafeCritical] internal void GetAppDomainManagerType(out string assembly, out string type) { // We can't just use our parameters because we need to ensure that the strings used for hte QCall @@ -798,77 +689,16 @@ namespace System { /// /// Set the assembly and type which act as the AppDomainManager for this domain /// - [SecuritySafeCritical] private void SetAppDomainManagerType(string assembly, string type) { - Contract.Assert(assembly != null, "assembly != null"); - Contract.Assert(type != null, "type != null"); + Debug.Assert(assembly != null, "assembly != null"); + Debug.Assert(type != null, "type != null"); SetAppDomainManagerType(GetNativeHandle(), assembly, type); } -#if FEATURE_APTCA - internal String[] PartialTrustVisibleAssemblies - { - get { return _aptcaVisibleAssemblies; } - - [SecuritySafeCritical] - set - { - _aptcaVisibleAssemblies = value; - - // Build up the canonical representaiton of this list to allow the VM to do optimizations in - // common cases - string canonicalConditionalAptcaList = null; - if (value != null) - { - StringBuilder conditionalAptcaListBuilder = StringBuilderCache.Acquire(); - for (int i = 0; i < value.Length; ++i) - { - if (value[i] != null) - { - conditionalAptcaListBuilder.Append(value[i].ToUpperInvariant()); - if (i != value.Length - 1) - { - conditionalAptcaListBuilder.Append(';'); - } - } - } - - canonicalConditionalAptcaList = StringBuilderCache.GetStringAndRelease(conditionalAptcaListBuilder); - } - - SetCanonicalConditionalAptcaList(canonicalConditionalAptcaList); - } - } - - [SecurityCritical] - [SuppressUnmanagedCodeSecurity] - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - private static extern void SetCanonicalConditionalAptcaList(AppDomainHandle appDomain, string canonicalList); - - [SecurityCritical] - private void SetCanonicalConditionalAptcaList(string canonicalList) - { - SetCanonicalConditionalAptcaList(GetNativeHandle(), canonicalList); - } -#endif // FEATURE_APTCA - -#if FEATURE_CLICKONCE - /// - /// If the CLR is being started up to run a ClickOnce applicaiton, setup the default AppDomain - /// with information about that application. - /// - private void SetupDefaultClickOnceDomain(string fullName, string[] manifestPaths, string[] activationData) - { - Contract.Requires(fullName != null, "fullName != null"); - FusionStore.ActivationArguments = new ActivationArguments(fullName, manifestPaths, activationData); - } -#endif // FEATURE_CLICKONCE - /// /// Called for every AppDomain (including the default domain) to initialize the security of the AppDomain) /// - [SecurityCritical] private void InitializeDomainSecurity(Evidence providedSecurityInfo, Evidence creatorsSecurityInfo, bool generateDefaultEvidence, @@ -877,91 +707,23 @@ namespace System { { AppDomainSetup adSetup = FusionStore; -#if FEATURE_CAS_POLICY - // If the AppDomain is setup to use legacy CAS policy, then set that bit in the application - // security descriptor. - if (CompatibilitySwitches.IsNetFx40LegacySecurityPolicy) - { - SetLegacyCasPolicyEnabled(); - } -#endif // FEATURE_CAS_POLICY - -#if FEATURE_CLICKONCE - - // Check if the domain manager set an ActivationContext (Debug-In-Zone for example) - // or if this is an AppDomain with an ApplicationTrust. - if (adSetup.ActivationArguments != null) { - // Merge the new evidence with the manifest's evidence if applicable - ActivationContext activationContext = null; - ApplicationIdentity appIdentity = null; - string[] activationData = null; - CmsUtils.CreateActivationContext(adSetup.ActivationArguments.ApplicationFullName, - adSetup.ActivationArguments.ApplicationManifestPaths, - adSetup.ActivationArguments.UseFusionActivationContext, - out appIdentity, out activationContext); - activationData = adSetup.ActivationArguments.ActivationData; - providedSecurityInfo = CmsUtils.MergeApplicationEvidence(providedSecurityInfo, - appIdentity, - activationContext, - activationData, - adSetup.ApplicationTrust); - SetupApplicationHelper(providedSecurityInfo, creatorsSecurityInfo, appIdentity, activationContext, activationData); - } - else -#endif // FEATURE_CLICKONCE - { - bool runtimeSuppliedHomogenousGrant = false; - ApplicationTrust appTrust = adSetup.ApplicationTrust; - -#if FEATURE_CAS_POLICY - // In non-legacy CAS mode, domains should be homogenous. If the host has not specified a sandbox - // of their own, we'll set it up to be fully trusted. We must read the IsLegacyCasPolicy - // enabled property here rathern than just reading the switch from above because the entire - // process may also be opted into legacy CAS policy mode. - if (appTrust == null && !IsLegacyCasPolicyEnabled) { - _IsFastFullTrustDomain = true; - runtimeSuppliedHomogenousGrant = true; - } -#endif // FEATURE_CAS_POLICY + bool runtimeSuppliedHomogenousGrant = false; + ApplicationTrust appTrust = adSetup.ApplicationTrust; - if (appTrust != null) { - SetupDomainSecurityForHomogeneousDomain(appTrust, runtimeSuppliedHomogenousGrant); - } - else if (_IsFastFullTrustDomain) { - SetSecurityHomogeneousFlag(GetNativeHandle(), runtimeSuppliedHomogenousGrant); - } + if (appTrust != null) { + SetupDomainSecurityForHomogeneousDomain(appTrust, runtimeSuppliedHomogenousGrant); + } + else if (_IsFastFullTrustDomain) { + SetSecurityHomogeneousFlag(GetNativeHandle(), runtimeSuppliedHomogenousGrant); } // Get the evidence supplied for the domain. If no evidence was supplied, it means that we want // to use the default evidence creation strategy for this domain Evidence newAppDomainEvidence = (providedSecurityInfo != null ? providedSecurityInfo : creatorsSecurityInfo); if (newAppDomainEvidence == null && generateDefaultEvidence) { -#if FEATURE_CAS_POLICY - newAppDomainEvidence = new Evidence(new AppDomainEvidenceFactory(this)); -#else // !FEATURE_CAS_POLICY newAppDomainEvidence = new Evidence(); -#endif // FEATURE_CAS_POLICY } -#if FEATURE_CAS_POLICY - if (_domainManager != null) { - // Give the host a chance to alter the AppDomain evidence - HostSecurityManager securityManager = _domainManager.HostSecurityManager; - if (securityManager != null) { - nSetHostSecurityManagerFlags (securityManager.Flags); - if ((securityManager.Flags & HostSecurityManagerOptions.HostAppDomainEvidence) == HostSecurityManagerOptions.HostAppDomainEvidence) { - newAppDomainEvidence = securityManager.ProvideAppDomainEvidence(newAppDomainEvidence); - // If this is a disconnected evidence collection, then attach it to the AppDomain, - // allowing the host security manager to get callbacks for delay generated evidence - if (newAppDomainEvidence != null && newAppDomainEvidence.Target == null) { - newAppDomainEvidence.Target = new AppDomainEvidenceFactory(this); - } - } - } - } - -#endif // FEATURE_CAS_POLICY - // Set the evidence on the managed side _SecurityIdentity = newAppDomainEvidence; @@ -971,106 +733,8 @@ namespace System { SetupDomainSecurity(newAppDomainEvidence, parentSecurityDescriptor, publishAppDomain); - -#if FEATURE_CAS_POLICY - // The AppDomain is now resolved. Go ahead and set the PolicyLevel - // from the HostSecurityManager if specified. - if (_domainManager != null) - RunDomainManagerPostInitialization(_domainManager); -#endif // FEATURE_CAS_POLICY - } - -#if FEATURE_CAS_POLICY - [System.Security.SecurityCritical] // auto-generated - private void RunDomainManagerPostInitialization (AppDomainManager domainManager) - { - // force creation of the HostExecutionContextManager for the current AppDomain - HostExecutionContextManager contextManager = domainManager.HostExecutionContextManager; - - if (IsLegacyCasPolicyEnabled) - { -#pragma warning disable 618 - HostSecurityManager securityManager = domainManager.HostSecurityManager; - if (securityManager != null) - { - if ((securityManager.Flags & HostSecurityManagerOptions.HostPolicyLevel) == HostSecurityManagerOptions.HostPolicyLevel) - { - // set AppDomain policy if specified - PolicyLevel level = securityManager.DomainPolicy; - if (level != null) - SetAppDomainPolicy(level); - } - } -#pragma warning restore 618 - } - } -#endif - - -#if FEATURE_CLICKONCE - - [System.Security.SecurityCritical] // auto-generated - private void SetupApplicationHelper (Evidence providedSecurityInfo, Evidence creatorsSecurityInfo, ApplicationIdentity appIdentity, ActivationContext activationContext, string[] activationData) { - Contract.Requires(providedSecurityInfo != null); - HostSecurityManager securityManager = AppDomain.CurrentDomain.HostSecurityManager; - ApplicationTrust appTrust = securityManager.DetermineApplicationTrust(providedSecurityInfo, creatorsSecurityInfo, new TrustManagerContext()); - if (appTrust == null || !appTrust.IsApplicationTrustedToRun) - throw new PolicyException(Environment.GetResourceString("Policy_NoExecutionPermission"), - System.__HResults.CORSEC_E_NO_EXEC_PERM, - null); - - // The application is trusted to run. Set up the AppDomain according to the manifests. - if (activationContext != null) - SetupDomainForApplication(activationContext, activationData); - SetupDomainSecurityForApplication(appIdentity, appTrust); } - [System.Security.SecurityCritical] // auto-generated - private void SetupDomainForApplication(ActivationContext activationContext, string[] activationData) { - Contract.Requires(activationContext != null); - if (IsDefaultAppDomain()) { - // make the ActivationArguments available off the AppDomain object. - AppDomainSetup adSetup = this.FusionStore; - adSetup.ActivationArguments = new ActivationArguments(activationContext, activationData); - - // set the application base to point at where the application resides - string entryPointPath = CmsUtils.GetEntryPointFullPath(activationContext); - if (!String.IsNullOrEmpty(entryPointPath)) - adSetup.SetupDefaults(entryPointPath); - else - adSetup.ApplicationBase = activationContext.ApplicationDirectory; - - // update fusion context - SetupFusionStore(adSetup, null); - } - - // perform app data directory migration. - activationContext.PrepareForExecution(); - activationContext.SetApplicationState(ActivationContext.ApplicationState.Starting); - // set current app data directory. - activationContext.SetApplicationState(ActivationContext.ApplicationState.Running); - - // make data directory path available. - IPermission permission = null; - string dataDirectory = activationContext.DataDirectory; - if (dataDirectory != null && dataDirectory.Length > 0) - permission = new FileIOPermission(FileIOPermissionAccess.PathDiscovery, dataDirectory); - this.SetData("DataDirectory", dataDirectory, permission); - - _activationContext = activationContext; - } - - [System.Security.SecurityCritical] // auto-generated - private void SetupDomainSecurityForApplication(ApplicationIdentity appIdentity, - ApplicationTrust appTrust) - { - // Set the Application trust on the managed side. - _applicationIdentity = appIdentity; - SetupDomainSecurityForHomogeneousDomain(appTrust, false); - } -#endif // FEATURE_CLICKONCE - - [System.Security.SecurityCritical] // auto-generated private void SetupDomainSecurityForHomogeneousDomain(ApplicationTrust appTrust, bool runtimeSuppliedHomogenousGrantSet) { @@ -1084,9 +748,6 @@ namespace System { if (runtimeSuppliedHomogenousGrantSet) { BCLDebug.Assert(_FusionStore.ApplicationTrust != null, "Expected to find runtime supplied ApplicationTrust"); -#if FEATURE_CAS_POLICY - _FusionStore.ApplicationTrust = null; -#endif // FEATURE_CAS_POLICY } _applicationTrust = appTrust; @@ -1096,38 +757,13 @@ namespace System { runtimeSuppliedHomogenousGrantSet); } - // This method is called from CorHost2::ExecuteApplication to activate a ClickOnce application in the default AppDomain. -#if FEATURE_CLICKONCE - [System.Security.SecuritySafeCritical] // auto-generated - private int ActivateApplication () { - ObjectHandle oh = Activator.CreateInstance(AppDomain.CurrentDomain.ActivationContext); - return (int) oh.Unwrap(); - } -#endif //FEATURE_CLICKONCE - public AppDomainManager DomainManager { - [System.Security.SecurityCritical] // auto-generated_required get { return _domainManager; } } -#if FEATURE_CAS_POLICY - internal HostSecurityManager HostSecurityManager { - [System.Security.SecurityCritical] // auto-generated - get { - HostSecurityManager securityManager = null; - AppDomainManager domainManager = AppDomain.CurrentDomain.DomainManager; - if (domainManager != null) - securityManager = domainManager.HostSecurityManager; - - if (securityManager == null) - securityManager = new HostSecurityManager(); - return securityManager; - } - } -#endif // FEATURE_CAS_POLICY -#if FEATURE_REFLECTION_ONLY_LOAD +#if FEATURE_REFLECTION_ONLY_LOAD private Assembly ResolveAssemblyForIntrospection(Object sender, ResolveEventArgs args) { Contract.Requires(args != null); @@ -1143,7 +779,6 @@ namespace System { _packageGraphFilePaths = packageGraphFilePaths; } - [System.Security.SecurityCritical] public void ResolveNamespace( object sender, System.Runtime.InteropServices.WindowsRuntime.NamespaceResolveEventArgs args) @@ -1162,7 +797,6 @@ namespace System { } // Called only by native function code:ValidateWorker - [System.Security.SecuritySafeCritical] private void EnableResolveAssembliesForIntrospection(string verifiedFileDirectory) { CurrentDomain.ReflectionOnlyAssemblyResolve += new ResolveEventHandler(ResolveAssemblyForIntrospection); @@ -1183,7 +817,6 @@ namespace System { * to have a strong name and a hash will be computed when the assembly * is saved. **********************************************/ - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public AssemblyBuilder DefineDynamicAssembly( AssemblyName name, @@ -1196,7 +829,6 @@ namespace System { null, null, null, null, ref stackMark, null, SecurityContextSource.CurrentAssembly); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public AssemblyBuilder DefineDynamicAssembly( AssemblyName name, @@ -1214,7 +846,6 @@ namespace System { } [MethodImplAttribute(MethodImplOptions.NoInlining)] // Due to the stack crawl mark - [SecuritySafeCritical] public AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access, IEnumerable assemblyAttributes, @@ -1231,7 +862,6 @@ namespace System { securityContextSource); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public AssemblyBuilder DefineDynamicAssembly( AssemblyName name, @@ -1248,7 +878,6 @@ namespace System { SecurityContextSource.CurrentAssembly); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] public AssemblyBuilder DefineDynamicAssembly( @@ -1266,7 +895,6 @@ namespace System { SecurityContextSource.CurrentAssembly); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] public AssemblyBuilder DefineDynamicAssembly( @@ -1288,7 +916,6 @@ namespace System { SecurityContextSource.CurrentAssembly); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of DefineDynamicAssembly which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkId=155570 for more information.")] public AssemblyBuilder DefineDynamicAssembly( @@ -1304,7 +931,6 @@ namespace System { null, null, null, ref stackMark, null, SecurityContextSource.CurrentAssembly); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] public AssemblyBuilder DefineDynamicAssembly( @@ -1327,7 +953,6 @@ namespace System { SecurityContextSource.CurrentAssembly); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] public AssemblyBuilder DefineDynamicAssembly( @@ -1351,7 +976,6 @@ namespace System { SecurityContextSource.CurrentAssembly); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. Please see http://go.microsoft.com/fwlink/?LinkId=155570 for more information.")] public AssemblyBuilder DefineDynamicAssembly( @@ -1376,8 +1000,6 @@ namespace System { SecurityContextSource.CurrentAssembly); } - - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] public AssemblyBuilder DefineDynamicAssembly( @@ -1405,7 +1027,6 @@ namespace System { SecurityContextSource.CurrentAssembly); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] public AssemblyBuilder DefineDynamicAssembly( @@ -1434,7 +1055,6 @@ namespace System { SecurityContextSource.CurrentAssembly); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public AssemblyBuilder DefineDynamicAssembly( AssemblyName name, @@ -1458,7 +1078,6 @@ namespace System { SecurityContextSource.CurrentAssembly); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable private AssemblyBuilder InternalDefineDynamicAssembly( AssemblyName name, @@ -1484,7 +1103,6 @@ namespace System { securityContextSource); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern String nApplyPolicy(AssemblyName an); @@ -1506,7 +1124,6 @@ namespace System { return nApplyPolicy(asmName); } - public ObjectHandle CreateInstance(String assemblyName, String typeName) @@ -1516,14 +1133,13 @@ namespace System { throw new NullReferenceException(); if (assemblyName == null) - throw new ArgumentNullException("assemblyName"); + throw new ArgumentNullException(nameof(assemblyName)); Contract.EndContractBlock(); return Activator.CreateInstance(assemblyName, typeName); } - [System.Security.SecurityCritical] // auto-generated internal ObjectHandle InternalCreateInstanceWithNoSecurity (string assemblyName, string typeName) { PermissionSet.s_fullTrust.Assert(); return CreateInstance(assemblyName, typeName); @@ -1542,7 +1158,6 @@ namespace System { typeName); } - [System.Security.SecurityCritical] // auto-generated internal ObjectHandle InternalCreateInstanceFromWithNoSecurity (string assemblyName, string typeName) { PermissionSet.s_fullTrust.Assert(); return CreateInstanceFrom(assemblyName, typeName); @@ -1591,7 +1206,7 @@ namespace System { throw new NullReferenceException(); if (assemblyName == null) - throw new ArgumentNullException("assemblyName"); + throw new ArgumentNullException(nameof(assemblyName)); Contract.EndContractBlock(); return Activator.CreateInstance(assemblyName, @@ -1630,16 +1245,9 @@ namespace System { throw new NullReferenceException(); if (assemblyName == null) - throw new ArgumentNullException("assemblyName"); + throw new ArgumentNullException(nameof(assemblyName)); Contract.EndContractBlock(); -#if FEATURE_CAS_POLICY - if (securityAttributes != null && !IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit")); - } -#endif // FEATURE_CAS_POLICY - #pragma warning disable 618 return Activator.CreateInstance(assemblyName, typeName, @@ -1667,7 +1275,7 @@ namespace System { throw new NullReferenceException(); if (assemblyName == null) - throw new ArgumentNullException("assemblyName"); + throw new ArgumentNullException(nameof(assemblyName)); Contract.EndContractBlock(); return Activator.CreateInstance(assemblyName, @@ -1680,7 +1288,6 @@ namespace System { activationAttributes); } - [System.Security.SecurityCritical] // auto-generated internal ObjectHandle InternalCreateInstanceWithNoSecurity (string assemblyName, string typeName, bool ignoreCase, @@ -1691,10 +1298,6 @@ namespace System { Object[] activationAttributes, Evidence securityAttributes) { -#if FEATURE_CAS_POLICY - Contract.Assert(IsLegacyCasPolicyEnabled || securityAttributes == null); -#endif // FEATURE_CAS_POLICY - PermissionSet.s_fullTrust.Assert(); #pragma warning disable 618 return CreateInstance(assemblyName, typeName, ignoreCase, bindingAttr, binder, args, culture, activationAttributes, securityAttributes); @@ -1718,13 +1321,6 @@ namespace System { throw new NullReferenceException(); Contract.EndContractBlock(); -#if FEATURE_CAS_POLICY - if (securityAttributes != null && !IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit")); - } -#endif // FEATURE_CAS_POLICY - return Activator.CreateInstanceFrom(assemblyFile, typeName, ignoreCase, @@ -1760,7 +1356,6 @@ namespace System { activationAttributes); } - [System.Security.SecurityCritical] // auto-generated internal ObjectHandle InternalCreateInstanceFromWithNoSecurity (string assemblyName, string typeName, bool ignoreCase, @@ -1771,17 +1366,12 @@ namespace System { Object[] activationAttributes, Evidence securityAttributes) { -#if FEATURE_CAS_POLICY - Contract.Assert(IsLegacyCasPolicyEnabled || securityAttributes == null); -#endif // FEATURE_CAS_POLICY - PermissionSet.s_fullTrust.Assert(); #pragma warning disable 618 return CreateInstanceFrom(assemblyName, typeName, ignoreCase, bindingAttr, binder, args, culture, activationAttributes, securityAttributes); #pragma warning restore 618 } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public Assembly Load(AssemblyName assemblyRef) { @@ -1789,7 +1379,6 @@ namespace System { return RuntimeAssembly.InternalLoadAssemblyName(assemblyRef, null, null, ref stackMark, true /*thrownOnFileNotFound*/, false, false); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public Assembly Load(String assemblyString) { @@ -1797,7 +1386,6 @@ namespace System { return RuntimeAssembly.InternalLoad(assemblyString, null, ref stackMark, false); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public Assembly Load(byte[] rawAssembly) { @@ -1811,7 +1399,6 @@ namespace System { } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public Assembly Load(byte[] rawAssembly, byte[] rawSymbolStore) @@ -1825,23 +1412,12 @@ namespace System { SecurityContextSource.CurrentAssembly); } - [System.Security.SecuritySafeCritical] // auto-generated -#pragma warning disable 618 - [SecurityPermissionAttribute(SecurityAction.Demand, ControlEvidence = true)] -#pragma warning restore 618 [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of Load which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkId=155570 for more information.")] public Assembly Load(byte[] rawAssembly, byte[] rawSymbolStore, Evidence securityEvidence) { -#if FEATURE_CAS_POLICY - if (securityEvidence != null && !IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit")); - } -#endif // FEATURE_CAS_POLICY - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return RuntimeAssembly.nLoadImage(rawAssembly, rawSymbolStore, @@ -1851,7 +1427,6 @@ namespace System { SecurityContextSource.CurrentAssembly); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of Load which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] public Assembly Load(AssemblyName assemblyRef, @@ -1861,7 +1436,6 @@ namespace System { return RuntimeAssembly.InternalLoadAssemblyName(assemblyRef, assemblySecurity, null, ref stackMark, true /*thrownOnFileNotFound*/, false, false); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of Load which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] public Assembly Load(String assemblyString, @@ -1888,15 +1462,8 @@ namespace System { Evidence assemblySecurity, String[] args) { -#if FEATURE_CAS_POLICY - if (assemblySecurity != null && !IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit")); - } -#endif // FEATURE_CAS_POLICY - RuntimeAssembly assembly = (RuntimeAssembly)Assembly.LoadFrom(assemblyFile, assemblySecurity); - + if (args == null) args = new String[0]; @@ -1920,13 +1487,6 @@ namespace System { byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm) { -#if FEATURE_CAS_POLICY - if (assemblySecurity != null && !IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit")); - } -#endif // FEATURE_CAS_POLICY - RuntimeAssembly assembly = (RuntimeAssembly)Assembly.LoadFrom(assemblyFile, assemblySecurity, hashValue, @@ -1951,9 +1511,6 @@ namespace System { return nExecuteAssembly(assembly, args); } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif public int ExecuteAssemblyByName(String assemblyName) { return ExecuteAssemblyByName(assemblyName, (string[])null); @@ -1973,15 +1530,8 @@ namespace System { Evidence assemblySecurity, params String[] args) { -#if FEATURE_CAS_POLICY - if (assemblySecurity != null && !IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit")); - } -#endif // FEATURE_CAS_POLICY - RuntimeAssembly assembly = (RuntimeAssembly)Assembly.Load(assemblyName, assemblySecurity); - + if (args == null) args = new String[0]; @@ -2003,15 +1553,8 @@ namespace System { Evidence assemblySecurity, params String[] args) { -#if FEATURE_CAS_POLICY - if (assemblySecurity != null && !IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit")); - } -#endif // FEATURE_CAS_POLICY - RuntimeAssembly assembly = (RuntimeAssembly)Assembly.Load(assemblyName, assemblySecurity); - + if (args == null) args = new String[0]; @@ -2036,114 +1579,28 @@ namespace System { } } -#if FEATURE_CAS_POLICY - public Evidence Evidence - { - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute(SecurityAction.Demand, ControlEvidence = true)] - get { - return EvidenceNoDemand; - } - } - - internal Evidence EvidenceNoDemand { - [SecurityCritical] - get { - if (_SecurityIdentity == null) { - if (!IsDefaultAppDomain() && nIsDefaultAppDomainForEvidence()) { -#if !FEATURE_CORECLR - // - // V1.x compatibility: If this is an AppDomain created - // by the default appdomain without an explicit evidence - // then reuse the evidence of the default AppDomain. - // - return GetDefaultDomain().Evidence; -#else - Contract.Assert(false,"This code should not be called for core CLR"); - - // This operation is not allowed - throw new InvalidOperationException(); -#endif - } - else { - // We can't cache this value, since the VM needs to differentiate between AppDomains - // which have no user supplied evidence and those which do and it uses the presence - // of Evidence on the domain to make that switch. - return new Evidence(new AppDomainEvidenceFactory(this)); - } - } - else { - return _SecurityIdentity.Clone(); - } - } - } - - internal Evidence InternalEvidence - { - get { - return _SecurityIdentity; - } - } - - internal EvidenceBase GetHostEvidence(Type type) - { - if (_SecurityIdentity != null) - { - return _SecurityIdentity.GetHostEvidence(type); - } - else - { - return new Evidence(new AppDomainEvidenceFactory(this)).GetHostEvidence(type); - } - } -#endif // FEATURE_CAS_POLICY - public String FriendlyName { - [System.Security.SecuritySafeCritical] // auto-generated get { return nGetFriendlyName(); } } public String BaseDirectory { -#if FEATURE_CORECLR - [System.Security.SecurityCritical] -#endif get { return FusionStore.ApplicationBase; } } -#if FEATURE_FUSION - public String RelativeSearchPath - { - get { return FusionStore.PrivateBinPath; } - } - - public bool ShadowCopyFiles - { - get { - String s = FusionStore.ShadowCopyFiles; - if((s != null) && - (String.Compare(s, "true", StringComparison.OrdinalIgnoreCase) == 0)) - return true; - else - return false; - } - } -#endif - - [System.Security.SecuritySafeCritical] // auto-generated public override String ToString() { StringBuilder sb = StringBuilderCache.Acquire(); - + String fn = nGetFriendlyName(); if (fn != null) { sb.Append(Environment.GetResourceString("Loader_Name") + fn); sb.Append(Environment.NewLine); } - + if(_Policies == null || _Policies.Length == 0) sb.Append(Environment.GetResourceString("Loader_NoContextPolicies") + Environment.NewLine); @@ -2164,222 +1621,67 @@ namespace System { return nGetAssemblies(false /* forIntrospection */); } - public Assembly[] ReflectionOnlyGetAssemblies() { return nGetAssemblies(true /* forIntrospection */); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern Assembly[] nGetAssemblies(bool forIntrospection); // this is true when we've removed the handles etc so really can't do anything - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern bool IsUnloadingForcedFinalize(); - // this is true when we've just started going through the finalizers and are forcing objects to finalize - // so must be aware that certain infrastructure may have gone away - [System.Security.SecuritySafeCritical] // auto-generated + // this is true when we've just started going through the finalizers and are forcing objects to finalize + // so must be aware that certain infrastructure may have gone away [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern bool IsFinalizingForUnload(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void PublishAnonymouslyHostedDynamicMethodsAssembly(RuntimeAssembly assemblyHandle); -#if FEATURE_FUSION - // Appends the following string to the private path. Valid paths - // are of the form "bin;util/i386" etc. - [System.Security.SecurityCritical] // auto-generated_required - [Obsolete("AppDomain.AppendPrivatePath has been deprecated. Please investigate the use of AppDomainSetup.PrivateBinPath instead. http://go.microsoft.com/fwlink/?linkid=14202")] - public void AppendPrivatePath(String path) - { - if(path == null || path.Length == 0) - return; - - String current = FusionStore.Value[(int) AppDomainSetup.LoaderInformation.PrivateBinPathValue]; - StringBuilder appendPath = StringBuilderCache.Acquire(); - - if(current != null && current.Length > 0) { - // See if the last character is a separator - appendPath.Append(current); - if((current[current.Length-1] != Path.PathSeparator) && - (path[0] != Path.PathSeparator)) - appendPath.Append(Path.PathSeparator); - } - appendPath.Append(path); - - String result = StringBuilderCache.GetStringAndRelease(appendPath); - InternalSetPrivateBinPath(result); - } - - - [System.Security.SecurityCritical] // auto-generated_required - [Obsolete("AppDomain.ClearPrivatePath has been deprecated. Please investigate the use of AppDomainSetup.PrivateBinPath instead. http://go.microsoft.com/fwlink/?linkid=14202")] - public void ClearPrivatePath() - { - InternalSetPrivateBinPath(String.Empty); - } - - [System.Security.SecurityCritical] // auto-generated_required - [Obsolete("AppDomain.ClearShadowCopyPath has been deprecated. Please investigate the use of AppDomainSetup.ShadowCopyDirectories instead. http://go.microsoft.com/fwlink/?linkid=14202")] - public void ClearShadowCopyPath() - { - InternalSetShadowCopyPath(String.Empty); - } - - [System.Security.SecurityCritical] // auto-generated_required - [Obsolete("AppDomain.SetCachePath has been deprecated. Please investigate the use of AppDomainSetup.CachePath instead. http://go.microsoft.com/fwlink/?linkid=14202")] - public void SetCachePath(String path) - { - InternalSetCachePath(path); - } -#endif // FEATURE_FUSION - - [System.Security.SecurityCritical] // auto-generated_required public void SetData (string name, object data) { -#if FEATURE_CORECLR - if (!name.Equals("LOCATION_URI")) - { - // Only LOCATION_URI can be set using AppDomain.SetData - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SetData_OnlyLocationURI", name)); - } -#endif // FEATURE_CORECLR SetDataHelper(name, data, null); } - [System.Security.SecurityCritical] // auto-generated_required - public void SetData (string name, object data, IPermission permission) { -#if FEATURE_CORECLR + public void SetData (string name, object data, IPermission permission) + { if (!name.Equals("LOCATION_URI")) { // Only LOCATION_URI can be set using AppDomain.SetData throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SetData_OnlyLocationURI", name)); } -#endif // FEATURE_CORECLR + SetDataHelper(name, data, permission); } - [System.Security.SecurityCritical] // auto-generated - private void SetDataHelper (string name, object data, IPermission permission) { + private void SetDataHelper (string name, object data, IPermission permission) + { if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); Contract.EndContractBlock(); - // - // Synopsis: - // IgnoreSystemPolicy is provided as a legacy flag to allow callers to - // skip enterprise, machine and user policy levels. When this flag is set, - // any demands triggered in this AppDomain will be evaluated against the - // AppDomain CAS policy level that is set on the AppDomain. - // Security Requirements: - // The caller needs to be fully trusted in order to be able to set - // this legacy mode. - // Remarks: - // There needs to be an AppDomain policy level set before this compat - // switch can be set on the AppDomain. - // -#if FEATURE_FUSION - if (name.Equals(TargetFrameworkNameAppCompatSetting)) { - _FusionStore.TargetFrameworkName = (String) data; - return; - } -#if FEATURE_CAS_POLICY - if (name.Equals("IgnoreSystemPolicy")) { - lock (this) { - if (!_HasSetPolicy) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SetData")); - } - new PermissionSet(PermissionState.Unrestricted).Demand(); - } -#endif - int key = AppDomainSetup.Locate(name); - - if(key == -1) { - lock (((ICollection)LocalStore).SyncRoot) { - LocalStore[name] = new object[] {data, permission}; - } - } - else { - if (permission != null) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SetData")); - // Be sure to call these properties, not Value, since - // these do more than call Value. - switch(key) { - case (int) AppDomainSetup.LoaderInformation.DynamicBaseValue: - FusionStore.DynamicBase = (string) data; - break; - case (int) AppDomainSetup.LoaderInformation.DevPathValue: - FusionStore.DeveloperPath = (string) data; - break; - case (int) AppDomainSetup.LoaderInformation.ShadowCopyDirectoriesValue: - FusionStore.ShadowCopyDirectories = (string) data; - break; - case (int) AppDomainSetup.LoaderInformation.DisallowPublisherPolicyValue: - if(data != null) - FusionStore.DisallowPublisherPolicy = true; - else - FusionStore.DisallowPublisherPolicy = false; - break; - case (int) AppDomainSetup.LoaderInformation.DisallowCodeDownloadValue: - if (data != null) - FusionStore.DisallowCodeDownload = true; - else - FusionStore.DisallowCodeDownload = false; - break; - case (int) AppDomainSetup.LoaderInformation.DisallowBindingRedirectsValue: - if(data != null) - FusionStore.DisallowBindingRedirects = true; - else - FusionStore.DisallowBindingRedirects = false; - break; - case (int) AppDomainSetup.LoaderInformation.DisallowAppBaseProbingValue: - if(data != null) - FusionStore.DisallowApplicationBaseProbing = true; - else - FusionStore.DisallowApplicationBaseProbing = false; - break; - case (int) AppDomainSetup.LoaderInformation.ConfigurationBytesValue: - FusionStore.SetConfigurationBytes((byte[]) data); - break; - default: - FusionStore.Value[key] = (string) data; - break; - } - } -#else // FEATURE_FUSION -#if FEATURE_CORECLR // SetData should only be used to set values that don't already exist. + object[] currentVal; + lock (((ICollection)LocalStore).SyncRoot) { + LocalStore.TryGetValue(name, out currentVal); + } + if (currentVal != null && currentVal[0] != null) { - object[] currentVal; - lock (((ICollection)LocalStore).SyncRoot) { - LocalStore.TryGetValue(name, out currentVal); - } - if (currentVal != null && currentVal[0] != null) - { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SetData_OnlyOnce")); - } + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SetData_OnlyOnce")); } -#endif // FEATURE_CORECLR lock (((ICollection)LocalStore).SyncRoot) { LocalStore[name] = new object[] {data, permission}; } -#endif // FEATURE_FUSION } [Pure] - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif public Object GetData(string name) { if(name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); Contract.EndContractBlock(); int key = AppDomainSetup.Locate(name); @@ -2412,43 +1714,11 @@ namespace System { return FusionStore.ApplicationBase; case (int) AppDomainSetup.LoaderInformation.ApplicationNameValue: return FusionStore.ApplicationName; -#if FEATURE_FUSION - case (int) AppDomainSetup.LoaderInformation.ConfigurationFileValue: - return FusionStore.ConfigurationFile; - case (int) AppDomainSetup.LoaderInformation.DynamicBaseValue: - return FusionStore.DynamicBase; - case (int) AppDomainSetup.LoaderInformation.DevPathValue: - return FusionStore.DeveloperPath; - case (int) AppDomainSetup.LoaderInformation.PrivateBinPathValue: - return FusionStore.PrivateBinPath; - case (int) AppDomainSetup.LoaderInformation.PrivateBinPathProbeValue: - return FusionStore.PrivateBinPathProbe; - case (int) AppDomainSetup.LoaderInformation.ShadowCopyDirectoriesValue: - return FusionStore.ShadowCopyDirectories; - case (int) AppDomainSetup.LoaderInformation.ShadowCopyFilesValue: - return FusionStore.ShadowCopyFiles; - case (int) AppDomainSetup.LoaderInformation.CachePathValue: - return FusionStore.CachePath; - case (int) AppDomainSetup.LoaderInformation.LicenseFileValue: - return FusionStore.LicenseFile; - case (int) AppDomainSetup.LoaderInformation.DisallowPublisherPolicyValue: - return FusionStore.DisallowPublisherPolicy; - case (int) AppDomainSetup.LoaderInformation.DisallowCodeDownloadValue: - return FusionStore.DisallowCodeDownload; - case (int) AppDomainSetup.LoaderInformation.DisallowBindingRedirectsValue: - return FusionStore.DisallowBindingRedirects; - case (int) AppDomainSetup.LoaderInformation.DisallowAppBaseProbingValue: - return FusionStore.DisallowApplicationBaseProbing; - case (int) AppDomainSetup.LoaderInformation.ConfigurationBytesValue: - return FusionStore.GetConfigurationBytes(); -#endif //FEATURE_FUSION - default: - Contract.Assert(false, "Need to handle new LoaderInformation value in AppDomain.GetData()"); + Debug.Assert(false, "Need to handle new LoaderInformation value in AppDomain.GetData()"); return null; } } - } // The compat flags are set at domain creation time to indicate that the given breaking @@ -2477,84 +1747,8 @@ namespace System { [DllImport(Microsoft.Win32.Win32Native.KERNEL32)] public static extern int GetCurrentThreadId(); -#if FEATURE_REMOTING - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute( SecurityAction.Demand, ControlAppDomain = true ), - ReliabilityContract(Consistency.MayCorruptAppDomain, Cer.MayFail)] - public static void Unload(AppDomain domain) + internal ApplicationTrust ApplicationTrust { - if (domain == null) - throw new ArgumentNullException("domain"); - Contract.EndContractBlock(); - - try { - Int32 domainID = AppDomain.GetIdForUnload(domain); - if (domainID==0) - throw new CannotUnloadAppDomainException(); - AppDomain.nUnload(domainID); - } - catch(Exception e) { - throw e; // throw it again to reset stack trace - } - } -#endif - - // Explicitly set policy for a domain (providing policy hasn't been set - // previously). Making this call will guarantee that previously loaded - // assemblies will be granted permissions based on the default machine - // policy that was in place prior to this call. -#if FEATURE_CAS_POLICY - [System.Security.SecurityCritical] // auto-generated_required - [Obsolete("AppDomain policy levels are obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public void SetAppDomainPolicy(PolicyLevel domainPolicy) - { - if (domainPolicy == null) - throw new ArgumentNullException("domainPolicy"); - Contract.EndContractBlock(); - - if (!IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit")); - } - - // Check that policy has not been set previously. - lock (this) { - if (_HasSetPolicy) - throw new PolicyException(Environment.GetResourceString("Policy_PolicyAlreadySet")); - _HasSetPolicy = true; - - // Make sure that the loader allows us to change security policy - // at this time (this will throw if not.) - nChangeSecurityPolicy(); - } - - // Add the new policy level. - SecurityManager.PolicyManager.AddLevel(domainPolicy); - } -#endif //#if !FEATURE_CAS_POLICY -#if FEATURE_CLICKONCE - public ActivationContext ActivationContext { - [System.Security.SecurityCritical] // auto-generated_required - get { - return _activationContext; - } - } - - public ApplicationIdentity ApplicationIdentity { - [System.Security.SecurityCritical] // auto-generated_required - get { - return _applicationIdentity; - } - } -#endif // FEATURE_CLICKONCE - - -#if FEATURE_CLICKONCE - public ApplicationTrust ApplicationTrust { - [System.Security.SecurityCritical] // auto-generated_required -#else // FEATURE_CLICKONCE - internal ApplicationTrust ApplicationTrust { -#endif // FEATURE_CLICKONCE get { if (_applicationTrust == null && _IsFastFullTrustDomain) { _applicationTrust = new ApplicationTrust(new PermissionSet(PermissionState.Unrestricted)); @@ -2564,66 +1758,8 @@ namespace System { } } -#if FEATURE_IMPERSONATION - // Set the default principal object to be attached to threads if they - // attempt to bind to a principal while executing in this appdomain. The - // default can only be set once. - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPrincipal)] - public void SetThreadPrincipal(IPrincipal principal) + public String DynamicDirectory { - if (principal == null) - throw new ArgumentNullException("principal"); - Contract.EndContractBlock(); - - lock (this) { - // Check that principal has not been set previously. - if (_DefaultPrincipal != null) - throw new PolicyException(Environment.GetResourceString("Policy_PrincipalTwice")); - - _DefaultPrincipal = principal; - } - } -#endif // FEATURE_IMPERSONATION - -#if FEATURE_CAS_POLICY - // Similar to the above, but sets the class of principal to be created - // instead. - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPrincipal)] - public void SetPrincipalPolicy(PrincipalPolicy policy) - { - _PrincipalPolicy = policy; - } -#endif - - -#if FEATURE_REMOTING - // This method gives AppDomain an infinite life time by preventing a lease from being - // created - [System.Security.SecurityCritical] // auto-generated_required - public override Object InitializeLifetimeService() - { - return null; - } - // This is useful for requesting execution of some code - // in another appDomain ... the delegate may be defined - // on a marshal-by-value object or a marshal-by-ref or - // contextBound object. - public void DoCallBack(CrossAppDomainDelegate callBackDelegate) - { - if (callBackDelegate == null) - throw new ArgumentNullException("callBackDelegate"); - Contract.EndContractBlock(); - - callBackDelegate(); - } -#endif - - - public String DynamicDirectory - { - [System.Security.SecuritySafeCritical] // auto-generated get { String dyndir = GetDynamicDir(); if (dyndir != null) @@ -2633,211 +1769,13 @@ namespace System { } } -#if FEATURE_CAS_POLICY - public static AppDomain CreateDomain(String friendlyName, - Evidence securityInfo) // Optional - { - return CreateDomain(friendlyName, - securityInfo, - null); - } - - public static AppDomain CreateDomain(String friendlyName, - Evidence securityInfo, // Optional - String appBasePath, - String appRelativeSearchPath, - bool shadowCopyFiles) - { - AppDomainSetup info = new AppDomainSetup(); - info.ApplicationBase = appBasePath; - info.PrivateBinPath = appRelativeSearchPath; - if(shadowCopyFiles) - info.ShadowCopyFiles = "true"; - - return CreateDomain(friendlyName, - securityInfo, - info); - } -#endif // #if FEATURE_CAS_POLICY (not exposed in core) - - - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] extern private String GetDynamicDir(); - // Private helpers called from unmanaged code. - -#if FEATURE_REMOTING - - public static AppDomain CreateDomain(String friendlyName) - { - return CreateDomain(friendlyName, null, null); - } - - - // Marshal a single object into a serialized blob. - [System.Security.SecurityCritical] // auto-generated - private static byte[] MarshalObject(Object o) - { - CodeAccessPermission.Assert(true); - - return Serialize(o); - } - - // Marshal two objects into serialized blobs. - [System.Security.SecurityCritical] // auto-generated - private static byte[] MarshalObjects(Object o1, Object o2, out byte[] blob2) - { - CodeAccessPermission.Assert(true); - - byte[] blob1 = Serialize(o1); - blob2 = Serialize(o2); - return blob1; - } - - // Unmarshal a single object from a serialized blob. - [System.Security.SecurityCritical] // auto-generated - private static Object UnmarshalObject(byte[] blob) - { - CodeAccessPermission.Assert(true); - - return Deserialize(blob); - } - - // Unmarshal two objects from serialized blobs. - [System.Security.SecurityCritical] // auto-generated - private static Object UnmarshalObjects(byte[] blob1, byte[] blob2, out Object o2) - { - CodeAccessPermission.Assert(true); - - Object o1 = Deserialize(blob1); - o2 = Deserialize(blob2); - return o1; - } - - // Helper routines. - [System.Security.SecurityCritical] // auto-generated - private static byte[] Serialize(Object o) - { - if (o == null) - { - return null; - } - else if (o is ISecurityEncodable) - { - SecurityElement element = ((ISecurityEncodable)o).ToXml(); - MemoryStream ms = new MemoryStream( 4096 ); - ms.WriteByte( 0 ); - StreamWriter writer = new StreamWriter( ms, Encoding.UTF8 ); - element.ToWriter( writer ); - writer.Flush(); - return ms.ToArray(); - } - else - { - MemoryStream ms = new MemoryStream(); - ms.WriteByte( 1 ); - CrossAppDomainSerializer.SerializeObject(o, ms); - return ms.ToArray(); - } - } - - [System.Security.SecurityCritical] // auto-generated - private static Object Deserialize(byte[] blob) - { - if (blob == null) - return null; - - if (blob[0] == 0) - { - Parser parser = new Parser( blob, Tokenizer.ByteTokenEncoding.UTF8Tokens, 1 ); - SecurityElement root = parser.GetTopElement(); - if (root.Tag.Equals( "IPermission" ) || root.Tag.Equals( "Permission" )) - { - IPermission ip = System.Security.Util.XMLUtil.CreatePermission( root, PermissionState.None, false ); - - if (ip == null) - { - return null; - } - - ip.FromXml( root ); - - return ip; - } - else if (root.Tag.Equals( "PermissionSet" )) - { - PermissionSet permissionSet = new PermissionSet(); - - permissionSet.FromXml( root, false, false ); - - return permissionSet; - } - else if (root.Tag.Equals( "PermissionToken" )) - { - PermissionToken pToken = new PermissionToken(); - - pToken.FromXml( root ); - - return pToken; - } - else - { - return null; - } - - } - else - { - Object obj = null; - using(MemoryStream stream = new MemoryStream( blob, 1, blob.Length - 1 )) { - obj = CrossAppDomainSerializer.DeserializeObject(stream); - } - - Contract.Assert( !(obj is IPermission), "IPermission should be xml deserialized" ); - Contract.Assert( !(obj is PermissionSet), "PermissionSet should be xml deserialized" ); - - return obj; - } - } - -#endif // FEATURE_REMOTING - -#if !FEATURE_CORECLR - // - // Called by the VM if ICLRExecutionManager::Pause is called with the PAUSE_APP_DOMAINS flag. - // This mimics the behavior of the CoreCLR FAS (fast application switching) model, to ensure - // that code that depends on things happening in a particular order will work. - // - [System.Security.SecurityCritical] - internal static void Pause() - { - AppDomainPauseManager.Instance.Pausing(); - AppDomainPauseManager.Instance.Paused(); - } - - // - // Called by the VM if ICLRExecutionManager::Resume is called after ICLRExecutionManager::Pause - // was called with the PAUSE_APP_DOMAINS flag. - // This mimics the behavior of the CoreCLR FAS (fast application switching) model, to ensure - // that code that depends on things happening in a particular order will work. - // - [System.Security.SecurityCritical] - internal static void Resume() - { - if (AppDomainPauseManager.IsPaused) - { - AppDomainPauseManager.Instance.Resuming(); - AppDomainPauseManager.Instance.Resumed(); - } - } -#endif - private AppDomain() { throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_Constructor)); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern int _nExecuteAssembly(RuntimeAssembly assembly, String[] args); internal int nExecuteAssembly(RuntimeAssembly assembly, String[] args) @@ -2849,45 +1787,18 @@ namespace System { [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern void nCreateContext(); - [System.Security.SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void nSetupBindingPaths(String trustedPlatformAssemblies, String platformResourceRoots, String appPath, String appNiPaths, String appLocalWinMD); - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal void SetupBindingPaths(String trustedPlatformAssemblies, String platformResourceRoots, String appPath, String appNiPaths, String appLocalWinMD) { nSetupBindingPaths(trustedPlatformAssemblies, platformResourceRoots, appPath, appNiPaths, appLocalWinMD); } #endif // FEATURE_VERSIONING -#if FEATURE_REMOTING - internal void CreateRemotingData() - { - lock(this) { - if (_RemotingData == null) - _RemotingData = new DomainSpecificRemotingData(); - } - } - - internal DomainSpecificRemotingData RemotingData - { - get - { - if (_RemotingData == null) - CreateRemotingData(); - - return _RemotingData; - } - } -#endif // FEATURE_REMOTING - - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern String nGetFriendlyName(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern bool nIsDefaultAppDomainForEvidence(); @@ -2899,7 +1810,6 @@ namespace System { public event EventHandler ProcessExit { - [System.Security.SecuritySafeCritical] // auto-generated_required add { if (value != null) @@ -2919,7 +1829,6 @@ namespace System { public event EventHandler DomainUnload { - [System.Security.SecuritySafeCritical] // auto-generated_required add { if (value != null) @@ -2929,9 +1838,6 @@ namespace System { _domainUnload += value; } } -#if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] -#endif remove { lock(this) @@ -2942,7 +1848,6 @@ namespace System { public event UnhandledExceptionEventHandler UnhandledException { - [System.Security.SecurityCritical] // auto-generated_required add { if (value != null) @@ -2952,7 +1857,6 @@ namespace System { _unhandledException += value; } } - [System.Security.SecurityCritical] // auto-generated_required remove { lock(this) @@ -2967,7 +1871,6 @@ namespace System { // To register/unregister the callback, the code must be SecurityCritical. public event EventHandler FirstChanceException { - [System.Security.SecurityCritical] // auto-generated_required add { if (value != null) @@ -2977,7 +1880,6 @@ namespace System { _firstChanceException += value; } } - [System.Security.SecurityCritical] // auto-generated_required remove { lock(this) @@ -2996,7 +1898,6 @@ namespace System { } // This method is called by the VM. - [System.Security.SecurityCritical] private RuntimeAssembly OnResourceResolveEvent(RuntimeAssembly assembly, String resourceName) { ResolveEventHandler eventHandler = _ResourceResolve; @@ -3016,7 +1917,6 @@ namespace System { } // This method is called by the VM - [System.Security.SecurityCritical] private RuntimeAssembly OnTypeResolveEvent(RuntimeAssembly assembly, String typeName) { ResolveEventHandler eventHandler = _TypeResolve; @@ -3036,7 +1936,6 @@ namespace System { } // This method is called by the VM. - [System.Security.SecurityCritical] private RuntimeAssembly OnAssemblyResolveEvent(RuntimeAssembly assembly, String assemblyFullName) { ResolveEventHandler eventHandler = _AssemblyResolve; @@ -3058,36 +1957,6 @@ namespace System { return null; } -#if FEATURE_REFLECTION_ONLY_LOAD - - private RuntimeAssembly OnReflectionOnlyAssemblyResolveEvent(RuntimeAssembly assembly, String assemblyFullName) - { - ResolveEventHandler eventHandler = ReflectionOnlyAssemblyResolve; - if (eventHandler != null) { - - Delegate[] ds = eventHandler.GetInvocationList(); - int len = ds.Length; - for (int i = 0; i < len; i++) { - Assembly asm = ((ResolveEventHandler)ds[i])(this, new ResolveEventArgs(assemblyFullName, assembly)); - RuntimeAssembly ret = GetRuntimeAssembly(asm); - if (ret != null) - return ret; - } - } - - return null; - } - -#if FEATURE_COMINTEROP - // Called by VM - code:CLRPrivTypeCacheReflectionOnlyWinRT::RaiseNamespaceResolveEvent - private RuntimeAssembly[] OnReflectionOnlyNamespaceResolveEvent(RuntimeAssembly assembly, string namespaceName) - { - return System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeMetadata.OnReflectionOnlyNamespaceResolveEvent(this, assembly, namespaceName); - } -#endif // FEATURE_COMINTEROP - -#endif // FEATURE_REFLECTION_ONLY_LOAD - #if FEATURE_COMINTEROP // Called by VM - code:CLRPrivTypeCacheWinRT::RaiseDesignerNamespaceResolveEvent private string[] OnDesignerNamespaceResolveEvent(string namespaceName) @@ -3099,7 +1968,7 @@ namespace System { internal AppDomainSetup FusionStore { get { - Contract.Assert(_FusionStore != null, + Debug.Assert(_FusionStore != null, "Fusion store has not been correctly setup in this domain"); return _FusionStore; } @@ -3133,319 +2002,33 @@ namespace System { } } -#if FEATURE_FUSION - private void TurnOnBindingRedirects() - { - _FusionStore.DisallowBindingRedirects = false; - } -#endif - - // This will throw a CannotUnloadAppDomainException if the appdomain is - // in another process. -#if FEATURE_REMOTING - [System.Security.SecurityCritical] // auto-generated - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - internal static Int32 GetIdForUnload(AppDomain domain) - { - if (RemotingServices.IsTransparentProxy(domain)) - { - return RemotingServices.GetServerDomainIdForProxy(domain); - } - else - return domain.Id; - } -#endif - // Used to determine if server object context is valid in // x-domain remoting scenarios. - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal static extern bool IsDomainIdValid(Int32 id); - -#if FEATURE_REMOTING - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - static internal extern AppDomain GetDefaultDomain(); -#endif - -#if FEATURE_IMPERSONATION - // Internal routine to retrieve the default principal object. If this is - // called before the principal has been explicitly set, it will - // automatically allocate a default principal based on the policy set by - // SetPrincipalPolicy. - internal IPrincipal GetThreadPrincipal() - { - IPrincipal principal = null; - if (_DefaultPrincipal == null) { -#if FEATURE_CAS_POLICY - switch (_PrincipalPolicy) { - case PrincipalPolicy.NoPrincipal: - principal = null; - break; - case PrincipalPolicy.UnauthenticatedPrincipal: - principal = new GenericPrincipal(new GenericIdentity("", ""), - new String[] {""}); - break; - case PrincipalPolicy.WindowsPrincipal: - principal = new WindowsPrincipal(WindowsIdentity.GetCurrent()); - break; - default: - principal = null; - break; - } -#else - principal = new GenericPrincipal(new GenericIdentity("", ""), - new String[] {""}); - -#endif - } - else - principal = _DefaultPrincipal; - - return principal; - } -#endif // FEATURE_IMPERSONATION - -#if FEATURE_REMOTING - - [System.Security.SecurityCritical] // auto-generated - internal void CreateDefaultContext() - { - lock(this) { - // if it has not been created we ask the Context class to - // create a new default context for this appdomain. - if (_DefaultContext == null) - _DefaultContext = Context.CreateDefaultContext(); - } - } - - [System.Security.SecurityCritical] // auto-generated - internal Context GetDefaultContext() - { - if (_DefaultContext == null) - CreateDefaultContext(); - return _DefaultContext; - } - // Ensure that evidence provided when creating an AppDomain would not have been used to create a - // sandbox in legacy CAS mode. If it could have been used to create a sandbox, and we're not in CAS - // mode, then we throw an exception to prevent acciental creation of unsandboxed domains where a - // sandbox would have been expected. - [SecuritySafeCritical] - internal static void CheckDomainCreationEvidence(AppDomainSetup creationDomainSetup, - Evidence creationEvidence) - { - if (creationEvidence != null && !CurrentDomain.IsLegacyCasPolicyEnabled) - { - if (creationDomainSetup == null || creationDomainSetup.ApplicationTrust == null) - { - // We allow non-null evidence in CAS mode to support the common pattern of passing in - // AppDomain.CurrentDomain.Evidence. Since the zone evidence must have been changed - // if the user has any expectation of sandboxing the domain under legacy CAS policy, - // we use a zone comparison to check for this pattern. A strict comparison will not - // work, since MSDN samples for creating a domain show using a modified version of the - // current domain's evidence and we would capturce people who copied and pasted these - // samples without intending to sandbox. - Zone creatorsZone = CurrentDomain.EvidenceNoDemand.GetHostEvidence(); - SecurityZone creatorsSecurityZone = creatorsZone != null ? - creatorsZone.SecurityZone : - SecurityZone.MyComputer; - - Zone suppliedZone = creationEvidence.GetHostEvidence(); - if (suppliedZone != null) - { - if (suppliedZone.SecurityZone != creatorsSecurityZone && - suppliedZone.SecurityZone != SecurityZone.MyComputer) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit")); - } - } - } - } - } - -#if FEATURE_CAS_POLICY - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute( SecurityAction.Demand, ControlAppDomain = true )] - public static AppDomain CreateDomain(String friendlyName, - Evidence securityInfo, - AppDomainSetup info) - { - return InternalCreateDomain(friendlyName, securityInfo, info); - } -#else - internal static AppDomain CreateDomain(String friendlyName, - Evidence securityInfo, - AppDomainSetup info) - { - return InternalCreateDomain(friendlyName, securityInfo, info); - } -#endif - - [System.Security.SecurityCritical] // auto-generated - internal static AppDomain InternalCreateDomain(String friendlyName, - Evidence securityInfo, - AppDomainSetup info) - { - if (friendlyName == null) - throw new ArgumentNullException("friendlyName", Environment.GetResourceString("ArgumentNull_String")); - - Contract.EndContractBlock(); - - AppDomain.CheckCreateDomainSupported(); - - if (info == null) - info = new AppDomainSetup(); - if (info.TargetFrameworkName == null) - info.TargetFrameworkName = AppDomain.CurrentDomain.GetTargetFrameworkName(); - - AppDomainManager domainManager = AppDomain.CurrentDomain.DomainManager; - if (domainManager != null) - return domainManager.CreateDomain(friendlyName, securityInfo, info); - - // No AppDomainManager is set up for this domain - - // If evidence is provided, we check to make sure that is allowed. - if (securityInfo != null) - { - new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand(); - - // If we're potentially trying to sandbox without using a homogenous domain, we need to reject - // the domain creation. - CheckDomainCreationEvidence(info, securityInfo); - } - - return nCreateDomain(friendlyName, - info, - securityInfo, - securityInfo == null ? AppDomain.CurrentDomain.InternalEvidence : null, - AppDomain.CurrentDomain.GetSecurityDescriptor()); - } -#endif // FEATURE_REMOTING - -#if FEATURE_CAS_POLICY - - public static AppDomain CreateDomain (string friendlyName, - Evidence securityInfo, - AppDomainSetup info, - PermissionSet grantSet, - params StrongName[] fullTrustAssemblies) - { - if (info == null) - throw new ArgumentNullException("info"); - if (info.ApplicationBase == null) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AppDomainSandboxAPINeedsExplicitAppBase")); - Contract.EndContractBlock(); - - if (fullTrustAssemblies == null) - { - fullTrustAssemblies = new StrongName[0]; - } - - info.ApplicationTrust = new ApplicationTrust(grantSet, fullTrustAssemblies); - return CreateDomain(friendlyName, securityInfo, info); - } - - public static AppDomain CreateDomain(String friendlyName, - Evidence securityInfo, // Optional - String appBasePath, - String appRelativeSearchPath, - bool shadowCopyFiles, - AppDomainInitializer adInit, - string[] adInitArgs) - { - AppDomainSetup info = new AppDomainSetup(); - info.ApplicationBase = appBasePath; - info.PrivateBinPath = appRelativeSearchPath; - info.AppDomainInitializer=adInit; - info.AppDomainInitializerArguments=adInitArgs; - if(shadowCopyFiles) - info.ShadowCopyFiles = "true"; - - return CreateDomain(friendlyName, - securityInfo, - info); - } -#endif // FEATURE_CAS_POLICY - -#if FEATURE_CORECLR - [System.Security.SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void nSetNativeDllSearchDirectories(string paths); -#endif - [System.Security.SecurityCritical] // auto-generated private void SetupFusionStore(AppDomainSetup info, AppDomainSetup oldInfo) { Contract.Requires(info != null); -#if FEATURE_FUSION - if (oldInfo == null) { - - // Create the application base and configuration file from the imagelocation - // passed in or use the Win32 Image name. - if(info.Value[(int) AppDomainSetup.LoaderInformation.ApplicationBaseValue] == null || - info.Value[(int) AppDomainSetup.LoaderInformation.ConfigurationFileValue] == null ) -#else if (info.ApplicationBase == null) -#endif - { -#if FEATURE_FUSION - AppDomain defaultDomain = GetDefaultDomain(); - if (this == defaultDomain) { - // The default domain gets its defaults from the main process. - info.SetupDefaults(RuntimeEnvironment.GetModuleFileName(), imageLocationAlreadyNormalized : true); - } - else { - // Other domains get their defaults from the default domain. This way, a host process - // can use AppDomainManager to set up the defaults for every domain created in the process. - if (info.Value[(int) AppDomainSetup.LoaderInformation.ConfigurationFileValue] == null) - info.ConfigurationFile = defaultDomain.FusionStore.Value[(int) AppDomainSetup.LoaderInformation.ConfigurationFileValue]; - if (info.Value[(int) AppDomainSetup.LoaderInformation.ApplicationBaseValue] == null) - info.ApplicationBase = defaultDomain.FusionStore.Value[(int) AppDomainSetup.LoaderInformation.ApplicationBaseValue]; - if (info.Value[(int) AppDomainSetup.LoaderInformation.ApplicationNameValue] == null) - info.ApplicationName = defaultDomain.FusionStore.Value[(int) AppDomainSetup.LoaderInformation.ApplicationNameValue]; - } -#else info.SetupDefaults(RuntimeEnvironment.GetModuleFileName(), imageLocationAlreadyNormalized : true); -#endif - } -#if FEATURE_FUSION - // If there is no relative path then check the - // environment - if(info.Value[(int) AppDomainSetup.LoaderInformation.PrivateBinPathValue] == null) - info.PrivateBinPath = Environment.nativeGetEnvironmentVariable(AppDomainSetup.PrivateBinPathEnvironmentVariable); - - // Add the developer path if it exists on this - // machine. - if(info.DeveloperPath == null) - info.DeveloperPath = RuntimeEnvironment.GetDeveloperPath(); - - } - - // Set up the fusion context - IntPtr fusionContext = GetFusionContext(); - info.SetupFusionContext(fusionContext, oldInfo); - - // Set loader optimization policy -#else #if FEATURE_VERSIONING nCreateContext(); #endif // FEATURE_VERSIONING -#endif // FEATURE_FUSION #if FEATURE_LOADER_OPTIMIZATION if (info.LoaderOptimization != LoaderOptimization.NotSpecified || (oldInfo != null && info.LoaderOptimization != oldInfo.LoaderOptimization)) UpdateLoaderOptimization(info.LoaderOptimization); -#endif - - - +#endif // This must be the last action taken _FusionStore = info; } @@ -3475,7 +2058,6 @@ namespace System { // are any remoting sinks registered, they can add non-mscorlib // objects to the message (causing an assembly load exception when // we try to deserialize it on the other side) - [System.Security.SecurityCritical] // auto-generated private static object PrepareDataForSetup(String friendlyName, AppDomainSetup setup, Evidence providedSecurityInfo, @@ -3488,54 +2070,6 @@ namespace System { byte[] serializedEvidence = null; bool generateDefaultEvidence = false; -#if FEATURE_CAS_POLICY - // serialize evidence - EvidenceCollection evidenceCollection = null; - - if (providedSecurityInfo != null || creatorsSecurityInfo != null) - { - // If we're just passing through AppDomain.CurrentDomain.Evidence, and that evidence is just - // using the standard runtime AppDomainEvidenceFactory, don't waste time serializing it and - // deserializing it back -- instead, we can recreate a new AppDomainEvidenceFactory in the new - // domain. We only want to do this if there is no HostSecurityManager, otherwise the - // HostSecurityManager could have added additional evidence on top of our standard factory. - HostSecurityManager hsm = CurrentDomain.DomainManager != null ? CurrentDomain.DomainManager.HostSecurityManager : null; - bool hostMayContributeEvidence = hsm != null && - hsm.GetType() != typeof(HostSecurityManager) && - (hsm.Flags & HostSecurityManagerOptions.HostAppDomainEvidence) == HostSecurityManagerOptions.HostAppDomainEvidence; - if (!hostMayContributeEvidence) - { - if (providedSecurityInfo != null && - providedSecurityInfo.IsUnmodified && - providedSecurityInfo.Target != null && - providedSecurityInfo.Target is AppDomainEvidenceFactory) - { - providedSecurityInfo = null; - generateDefaultEvidence = true; - } - if (creatorsSecurityInfo != null && - creatorsSecurityInfo.IsUnmodified && - creatorsSecurityInfo.Target != null && - creatorsSecurityInfo.Target is AppDomainEvidenceFactory) - { - creatorsSecurityInfo = null; - generateDefaultEvidence = true; - } - } - } - if ((providedSecurityInfo != null) || - (creatorsSecurityInfo != null)) { - evidenceCollection = new EvidenceCollection(); - evidenceCollection.ProvidedSecurityInfo = providedSecurityInfo; - evidenceCollection.CreatorsSecurityInfo = creatorsSecurityInfo; - } - - if (evidenceCollection != null) { - serializedEvidence = - CrossAppDomainSerializer.SerializeObject(evidenceCollection).GetBuffer(); - } -#endif // FEATURE_CAS_POLICY - AppDomainInitializerInfo initializerInfo = null; if (setup!=null && setup.AppDomainInitializer!=null) initializerInfo=new AppDomainInitializerInfo(setup.AppDomainInitializer); @@ -3543,7 +2077,6 @@ namespace System { // will travel x-Ad, drop non-agile data AppDomainSetup newSetup = new AppDomainSetup(setup, false); -#if FEATURE_CORECLR // Remove the special AppDomainCompatSwitch entries from the set of name value pairs // And add them to the AppDomainSetup // @@ -3551,7 +2084,7 @@ namespace System { // Desktop code should use System.AppDomain.CreateDomain() or // System.AppDomainManager.CreateDomain() and add the flags to the AppDomainSetup List compatList = new List(); - + if(propertyNames!=null && propertyValues != null) { for (int i=0; i 0) { newSetup.SetCompatibilitySwitches(compatList); - } + } } -#endif // FEATURE_CORECLR - return new Object[] { @@ -3587,8 +2118,6 @@ namespace System { }; } // PrepareDataForSetup - - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] private static Object Setup(Object arg) { @@ -3604,44 +2133,47 @@ namespace System { AppDomainInitializerInfo initializerInfo = (AppDomainInitializerInfo)args[5]; string sandboxName = (string)args[6]; string[] propertyNames = (string[])args[7]; // can contain null elements - string[] propertyValues = (string[])args[8]; // can contain null elements + string[] propertyValues = (string[])args[8]; // can contain null elements // extract evidence Evidence providedSecurityInfo = null; Evidence creatorsSecurityInfo = null; - AppDomain ad = AppDomain.CurrentDomain; AppDomainSetup newSetup=new AppDomainSetup(setup,false); if(propertyNames!=null && propertyValues != null) { -#if FEATURE_CORECLR - StringBuilder normalisedAppPathList = null; -#endif // FEATURE_CORECLR + for (int i = 0; i < propertyNames.Length; i++) + { + // We want to set native dll probing directories before any P/Invokes have a + // chance to fire. The Path class, for one, has P/Invokes. + if (propertyNames[i] == "NATIVE_DLL_SEARCH_DIRECTORIES") + { + if (propertyValues[i] == null) + throw new ArgumentNullException("NATIVE_DLL_SEARCH_DIRECTORIES"); + + string paths = propertyValues[i]; + if (paths.Length == 0) + break; + + nSetNativeDllSearchDirectories(paths); + } + } + for (int i=0; i 0) - { - normalisedAppPathList.Remove(normalisedAppPathList.Length - 1, 1); - } - ad.SetDataHelper(propertyNames[i],normalisedAppPathList.ToString(),null); // not supported by fusion, so set explicitly + ad.SetDataHelper(propertyNames[i], NormalizeAppPaths(values), null); } - else - if(propertyNames[i]!= null) + else if(propertyNames[i]!= null) { ad.SetDataHelper(propertyNames[i],propertyValues[i],null); // just propagate } -#endif - - } - } - -#if !FEATURE_CORECLR - AppDomainSortingSetupInfo sortingSetup = newSetup._AppDomainSortingSetupInfo; - - if(sortingSetup != null) - { - if(sortingSetup._pfnIsNLSDefinedString == IntPtr.Zero || sortingSetup._pfnCompareStringEx == IntPtr.Zero || sortingSetup._pfnLCMapStringEx == IntPtr.Zero || sortingSetup._pfnFindNLSStringEx == IntPtr.Zero - || sortingSetup._pfnCompareStringOrdinal == IntPtr.Zero || sortingSetup._pfnGetNLSVersionEx == IntPtr.Zero) - { - - if(!(sortingSetup._pfnIsNLSDefinedString == IntPtr.Zero && sortingSetup._pfnCompareStringEx == IntPtr.Zero && sortingSetup._pfnLCMapStringEx == IntPtr.Zero && sortingSetup._pfnFindNLSStringEx == IntPtr.Zero - && sortingSetup._pfnCompareStringOrdinal == IntPtr.Zero && sortingSetup._pfnGetNLSVersionEx == IntPtr.Zero)) - { - // Some functions defined but not all of them. - throw new ArgumentException(Environment.GetResourceString("ArgumentException_NotAllCustomSortingFuncsDefined")); - } - } } -#endif ad.SetupFusionStore(newSetup, null); // makes FusionStore a ref to newSetup @@ -3757,18 +2212,8 @@ namespace System { // but it's confusing since it isn't immediately obvious whether we have a ref or a copy AppDomainSetup adSetup = ad.FusionStore; -#if FEATURE_CORECLR adSetup.InternalSetApplicationTrust(sandboxName); -#endif // FEATURE_CORECLR - -#if !FEATURE_CORECLR // not used by coreclr - if (serializedEvidence != null) { - EvidenceCollection evidenceCollection = (EvidenceCollection) - CrossAppDomainSerializer.DeserializeObject(new MemoryStream(serializedEvidence)); - providedSecurityInfo = evidenceCollection.ProvidedSecurityInfo; - creatorsSecurityInfo = evidenceCollection.CreatorsSecurityInfo; - } -#endif + // set up the friendly name ad.nSetupFriendlyName(friendlyName); @@ -3785,11 +2230,6 @@ namespace System { ad.SetAppDomainManagerType(adSetup.AppDomainManagerAssembly, adSetup.AppDomainManagerType); } -#if FEATURE_APTCA - // set any conditial-aptca visible assemblies - ad.PartialTrustVisibleAssemblies = adSetup.PartialTrustVisibleAssemblies; -#endif // FEATURE_APTCA - ad.CreateAppDomainManager(); // could modify FusionStore's object ad.InitializeDomainSecurity(providedSecurityInfo, creatorsSecurityInfo, @@ -3802,221 +2242,81 @@ namespace System { adSetup.AppDomainInitializer=initializerInfo.Unwrap(); RunInitializer(adSetup); - // Activate the application if needed. -#if FEATURE_CLICKONCE - ObjectHandle oh = null; - if (adSetup.ActivationArguments != null && adSetup.ActivationArguments.ActivateInstance) - oh = Activator.CreateInstance(ad.ActivationContext); - return RemotingServices.MarshalInternal(oh, null, null); -#else return null; -#endif // FEATURE_CLICKONCE } - [SecuritySafeCritical] - internal static string NormalizePath(string path, bool fullCheck) + private static string NormalizeAppPaths(string values) { -#if FEATURE_PATHCOMPAT - // Appcontext switches can't currently be safely hit during AppDomain bringup - return Path.LegacyNormalizePath( - path: path, - fullCheck: fullCheck, - maxPathLength: PathInternal.MaxShortPath, - expandShortPaths: true); -#else - return Path.NormalizePath( - path: path, - fullCheck: fullCheck, - expandShortPaths: true); -#endif - } - -#if FEATURE_APTCA - // Called from DomainAssembly in Conditional APTCA cases - [PermissionSet(SecurityAction.Assert, Unrestricted = true)] - [SecuritySafeCritical] - private bool IsAssemblyOnAptcaVisibleList(RuntimeAssembly assembly) - { - if (_aptcaVisibleAssemblies == null) - return false; - - AssemblyName assemblyName = assembly.GetName(); - String name = assemblyName.GetNameWithPublicKey(); - - name = name.ToUpperInvariant(); + int estimatedLength = values.Length + 1; // +1 for extra separator temporarily added at end + StringBuilder sb = StringBuilderCache.Acquire(estimatedLength); - int index = Array.BinarySearch(_aptcaVisibleAssemblies, name, - StringComparer.OrdinalIgnoreCase); - return (index >=0); - - } - - //Used to binary search the list of C-APTCA strings for an AssemblyName. It compares assembly name - //and public key token. - private class CAPTCASearcher : IComparer - { - int IComparer.Compare(object /*string*/lhs, object /*AssemblyName*/rhs) + for (int pos = 0; pos < values.Length; pos++) { - AssemblyName captcaEntry = new AssemblyName((string)lhs); - AssemblyName comparand = (AssemblyName)rhs; - int nameComp = string.Compare(captcaEntry.Name, - comparand.Name, - StringComparison.OrdinalIgnoreCase); - if (nameComp != 0) - { - return nameComp; - } - - //simple names match. Compare public key tokens. - byte[] lhsKey = captcaEntry.GetPublicKeyToken(); - byte[] rhsKey = comparand.GetPublicKeyToken(); + string path; - // We require both sides have a public key token - if (lhsKey == null) + int nextPos = values.IndexOf(Path.PathSeparator, pos); + if (nextPos == -1) { - return -1; + path = values.Substring(pos); + pos = values.Length - 1; } - if (rhsKey == null) - { - return 1; - } - if (lhsKey.Length < rhsKey.Length) - { - return -1; - } - if (lhsKey.Length > rhsKey.Length) + else { - return 1; + path = values.Substring(pos, nextPos - pos); + pos = nextPos; } - // Tokens seem valid - make sure the compare correctly - for (int i = 0; i < lhsKey.Length; ++i) - { - byte lhsByte = lhsKey[i]; - byte rhsByte = rhsKey[i]; + // Skip empty directories + if (path.Length == 0) + continue; - if (lhsByte < rhsByte) - { - return -1; - } - if (lhsByte > rhsByte) - { - return 1; - } - } + if (PathInternal.IsPartiallyQualified(path)) + throw new ArgumentException(Environment.GetResourceString("Argument_AbsolutePathRequired")); - //They match. - return 0; + string appPath = NormalizePath(path, fullCheck: true); + sb.Append(appPath); + sb.Append(Path.PathSeparator); } - } - [System.Security.SecurityCritical] - private unsafe bool IsAssemblyOnAptcaVisibleListRaw(char * namePtr, int nameLen, byte * keyTokenPtr, - int keyTokenLen) - { - //This version is used for checking ngen dependencies against the C-APTCA list. It lets us - //reject ngen images that depend on an assembly that has been disabled in the current domain. - //Since we only have the public key token in the ngen image, we'll check against that. The - //rationale is that if you have a public key token collision in your process you have many - //problems. Since the source of this public key token is an ngen image for a full trust - //assembly, there is essentially no risk to the reduced check. - if (_aptcaVisibleAssemblies == null) - return false; - - string name = new string(namePtr, 0, nameLen); - byte[] keyToken = new byte[keyTokenLen]; - for( int i = 0; i < keyToken.Length; ++i ) - keyToken[i] = keyTokenPtr[i]; - - AssemblyName asmName = new AssemblyName(); - asmName.Name = name; - asmName.SetPublicKeyToken(keyToken); - try + // Strip the last separator + if (sb.Length > 0) { - int index = Array.BinarySearch(_aptcaVisibleAssemblies, asmName, new CAPTCASearcher()); - return (index >= 0); + sb.Remove(sb.Length - 1, 1); } - catch (InvalidOperationException) { /* Can happen for poorly formed assembly names */ return false; } + + return StringBuilderCache.GetStringAndRelease(sb); } -#endif + internal static string NormalizePath(string path, bool fullCheck) + { + return Path.GetFullPath(path); + } // This routine is called from unmanaged code to // set the default fusion context. - [System.Security.SecurityCritical] // auto-generated private void SetupDomain(bool allowRedirects, String path, String configFile, String[] propertyNames, String[] propertyValues) { // It is possible that we could have multiple threads initializing // the default domain. We will just take the winner of these two. // (eg. one thread doing a com call and another doing attach for IJW) - lock (this) { - if(_FusionStore == null) { + lock (this) + { + if(_FusionStore == null) + { AppDomainSetup setup = new AppDomainSetup(); -#if FEATURE_CORECLR + // always use internet permission set setup.InternalSetApplicationTrust("Internet"); -#endif // FEATURE_CORECLR -#if FEATURE_FUSION - setup.SetupDefaults(RuntimeEnvironment.GetModuleFileName(), imageLocationAlreadyNormalized : true); - if(path != null) - setup.Value[(int) AppDomainSetup.LoaderInformation.ApplicationBaseValue] = path; - if(configFile != null) - setup.Value[(int) AppDomainSetup.LoaderInformation.ConfigurationFileValue] = configFile; - - // Default fusion context starts with binding redirects turned off. - if (!allowRedirects) - setup.DisallowBindingRedirects = true; -#endif - -#if !FEATURE_CORECLR - if (propertyNames != null) { - BCLDebug.Assert(propertyValues != null, "propertyValues != null"); - BCLDebug.Assert(propertyNames.Length == propertyValues.Length, "propertyNames.Length == propertyValues.Length"); - - for (int i = 0; i < propertyNames.Length; ++i) { - if (String.Equals(propertyNames[i], "PARTIAL_TRUST_VISIBLE_ASSEMBLIES", StringComparison.Ordinal)) { - // The value of the PARTIAL_TRUST_VISIBLE_ASSEMBLIES property is a semicolon - // delimited list of assembly names to add to the - // PartialTrustVisibleAssemblies setting of the domain setup - if (propertyValues[i] != null) { - if (propertyValues[i].Length > 0) { - setup.PartialTrustVisibleAssemblies = propertyValues[i].Split(';'); - } - else { - setup.PartialTrustVisibleAssemblies = new string[0]; - } - } - } - else { - // In v4 we disallow anything but PARTIAL_TRUST_VISIBLE_ASSEMBLIES to come - // in via the default domain properties. That restriction could be lifted - // in a future release, at which point this assert should be removed. - // - // This should be kept in sync with the real externally facing filter code - // in CorHost2::SetPropertiesForDefaultAppDomain - BCLDebug.Assert(false, "Unexpected default domain property"); - } - } - } -#endif // !FEATURE_CORECLR - -#if FEATURE_APTCA - // Propigate the set of conditional APTCA assemblies that will be used in the default - // domain onto the domain itself and also into the VM - PartialTrustVisibleAssemblies = setup.PartialTrustVisibleAssemblies; -#endif // FEATURE_APTCA - SetupFusionStore(setup, null); } } } #if FEATURE_LOADER_OPTIMIZATION - [System.Security.SecurityCritical] // auto-generated private void SetupLoaderOptimization(LoaderOptimization policy) { if(policy != LoaderOptimization.NotSpecified) { - Contract.Assert(FusionStore.LoaderOptimization == LoaderOptimization.NotSpecified, + Debug.Assert(FusionStore.LoaderOptimization == LoaderOptimization.NotSpecified, "It is illegal to change the Loader optimization on a domain"); FusionStore.LoaderOptimization = policy; @@ -4024,36 +2324,10 @@ namespace System { } } #endif - -#if FEATURE_FUSION - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal extern IntPtr GetFusionContext(); -#endif // FEATURE_FUSION - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern IntPtr GetSecurityDescriptor(); -#if FEATURE_REMOTING - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern AppDomain nCreateDomain(String friendlyName, - AppDomainSetup setup, - Evidence providedSecurityInfo, - Evidence creatorsSecurityInfo, - IntPtr parentSecurityDescriptor); - - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern ObjRef nCreateInstance(String friendlyName, - AppDomainSetup setup, - Evidence providedSecurityInfo, - Evidence creatorsSecurityInfo, - IntPtr parentSecurityDescriptor); -#endif - - [SecurityCritical] private void SetupDomainSecurity(Evidence appDomainEvidence, IntPtr creatorsSecurityDescriptor, bool publishAppDomain) @@ -4066,7 +2340,6 @@ namespace System { } - [SecurityCritical] [SuppressUnmanagedCodeSecurity] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] private static extern void SetupDomainSecurity(AppDomainHandle appDomain, @@ -4074,7 +2347,6 @@ namespace System { IntPtr creatorsSecurityDescriptor, [MarshalAs(UnmanagedType.Bool)] bool publishAppDomain); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern void nSetupFriendlyName(string friendlyName); @@ -4084,39 +2356,10 @@ namespace System { #endif // FEATURE_COMINTEROP #if FEATURE_LOADER_OPTIMIZATION - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern void UpdateLoaderOptimization(LoaderOptimization optimization); #endif -#if FEATURE_FUSION - // - // This is just designed to prevent compiler warnings. - // This field is used from native, but we need to prevent the compiler warnings. - // - - [System.Security.SecurityCritical] // auto-generated_required - [Obsolete("AppDomain.SetShadowCopyPath has been deprecated. Please investigate the use of AppDomainSetup.ShadowCopyDirectories instead. http://go.microsoft.com/fwlink/?linkid=14202")] - public void SetShadowCopyPath(String path) - { - InternalSetShadowCopyPath(path); - } - - [System.Security.SecurityCritical] // auto-generated_required - [Obsolete("AppDomain.SetShadowCopyFiles has been deprecated. Please investigate the use of AppDomainSetup.ShadowCopyFiles instead. http://go.microsoft.com/fwlink/?linkid=14202")] - public void SetShadowCopyFiles() - { - InternalSetShadowCopyFiles(); - } - - [System.Security.SecurityCritical] // auto-generated_required - [Obsolete("AppDomain.SetDynamicBase has been deprecated. Please investigate the use of AppDomainSetup.DynamicBase instead. http://go.microsoft.com/fwlink/?linkid=14202")] - public void SetDynamicBase(String path) - { - InternalSetDynamicBase(path); - } -#endif // FEATURE_FUSION - public AppDomainSetup SetupInformation { get { @@ -4124,84 +2367,19 @@ namespace System { } } -#if FEATURE_FUSION - [System.Security.SecurityCritical] // auto-generated - internal void InternalSetShadowCopyPath(String path) - { - if (path != null) - { - IntPtr fusionContext = GetFusionContext(); - AppDomainSetup.UpdateContextProperty(fusionContext, AppDomainSetup.ShadowCopyDirectoriesKey, path); - } - FusionStore.ShadowCopyDirectories = path; - } - - [System.Security.SecurityCritical] // auto-generated - internal void InternalSetShadowCopyFiles() - { - IntPtr fusionContext = GetFusionContext(); - AppDomainSetup.UpdateContextProperty(fusionContext, AppDomainSetup.ShadowCopyFilesKey, "true"); - FusionStore.ShadowCopyFiles = "true"; - } - - [System.Security.SecurityCritical] // auto-generated - internal void InternalSetCachePath(String path) - { - FusionStore.CachePath = path; - if (FusionStore.Value[(int) AppDomainSetup.LoaderInformation.CachePathValue] != null) - { - IntPtr fusionContext = GetFusionContext(); - AppDomainSetup.UpdateContextProperty(fusionContext, AppDomainSetup.CachePathKey, - FusionStore.Value[(int) AppDomainSetup.LoaderInformation.CachePathValue]); - } - } - - [System.Security.SecurityCritical] // auto-generated - internal void InternalSetPrivateBinPath(String path) - { - IntPtr fusionContext = GetFusionContext(); - AppDomainSetup.UpdateContextProperty(fusionContext, AppDomainSetup.PrivateBinPathKey, path); - FusionStore.PrivateBinPath = path; - } - - [System.Security.SecurityCritical] // auto-generated - internal void InternalSetDynamicBase(String path) - { - FusionStore.DynamicBase = path; - if (FusionStore.Value[(int) AppDomainSetup.LoaderInformation.DynamicBaseValue] != null) - { - IntPtr fusionContext = GetFusionContext(); - AppDomainSetup.UpdateContextProperty(fusionContext, AppDomainSetup.DynamicBaseKey, - FusionStore.Value[(int) AppDomainSetup.LoaderInformation.DynamicBaseValue]); - } - } -#endif // FEATURE_FUSION - - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern String IsStringInterned(String str); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern String GetOrInternString(String str); - [SecurityCritical] [SuppressUnmanagedCodeSecurity] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] private static extern void GetGrantSet(AppDomainHandle domain, ObjectHandleOnStack retGrantSet); -#if FEATURE_CAS_POLICY - [SecurityCritical] - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool GetIsLegacyCasPolicyEnabled(AppDomainHandle domain); -#endif // FEATURE_CAS_POLICY - public PermissionSet PermissionSet { // SecurityCritical because permissions can contain sensitive information such as paths - [SecurityCritical] get { PermissionSet grantSet = null; @@ -4220,7 +2398,6 @@ namespace System { public bool IsFullyTrusted { - [SecuritySafeCritical] get { PermissionSet grantSet = null; @@ -4239,62 +2416,9 @@ namespace System { } } -#if FEATURE_CAS_POLICY - internal bool IsLegacyCasPolicyEnabled - { - [SecuritySafeCritical] - get - { - return GetIsLegacyCasPolicyEnabled(GetNativeHandle()); - } - } - - // Determine what this homogenous domain thinks the grant set should be for a specific set of evidence - [SecuritySafeCritical] - internal PermissionSet GetHomogenousGrantSet(Evidence evidence) - { - Contract.Assert(evidence != null); - Contract.Assert(IsHomogenous); - Contract.Assert(evidence.GetHostEvidence() == null); - - if (_IsFastFullTrustDomain) - { - return new PermissionSet(PermissionState.Unrestricted); - } - - // If the ApplicationTrust's full trust list calls out the assembly, then it is fully trusted - if (evidence.GetDelayEvaluatedHostEvidence() != null) - { - foreach (StrongName fullTrustAssembly in ApplicationTrust.FullTrustAssemblies) - { - StrongNameMembershipCondition sn = new StrongNameMembershipCondition(fullTrustAssembly.PublicKey, - fullTrustAssembly.Name, - fullTrustAssembly.Version); - - object usedEvidence = null; - if ((sn as IReportMatchMembershipCondition).Check(evidence, out usedEvidence)) - { - IDelayEvaluatedEvidence delayEvidence = usedEvidence as IDelayEvaluatedEvidence; - if (usedEvidence != null) - { - delayEvidence.MarkUsed(); - } - - return new PermissionSet(PermissionState.Unrestricted); - } - } - } - - // Otherwise, the grant set is just the default grant set - return ApplicationTrust.DefaultGrantSet.PermissionSet.Copy(); - } -#endif // FEATURE_CAS_POLICY - - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern void nChangeSecurityPolicy(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.MayCorruptAppDomain, Cer.MayFail)] internal static extern void nUnload(Int32 domainInternal); @@ -4309,7 +2433,6 @@ namespace System { return oh.Unwrap(); } // CreateInstanceAndUnwrap - public Object CreateInstanceAndUnwrap(String assemblyName, String typeName, Object[] activationAttributes) @@ -4454,7 +2577,6 @@ namespace System { } } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal extern Int32 GetId(); @@ -4468,76 +2590,35 @@ namespace System { return false; } -#if FEATURE_FUSION - private static AppDomainSetup InternalCreateDomainSetup(String imageLocation) - { - int i = imageLocation.LastIndexOf('\\'); - - Contract.Assert(i != -1, "invalid image location"); - - AppDomainSetup info = new AppDomainSetup(); - info.ApplicationBase = imageLocation.Substring(0, i+1); - - StringBuilder config = new StringBuilder(imageLocation.Substring(i+1)); - config.Append(AppDomainSetup.ConfigurationExtension); - info.ConfigurationFile = config.ToString(); - - return info; - } - - // Used by the validator for testing but not executing an assembly - private static AppDomain InternalCreateDomain(String imageLocation) - { - AppDomainSetup info = InternalCreateDomainSetup(imageLocation); - return CreateDomain("Validator", - null, - info); - } - - [System.Security.SecurityCritical] // auto-generated - private void InternalSetDomainContext(String imageLocation) - { - SetupFusionStore(InternalCreateDomainSetup(imageLocation), null); - } -#endif - #if FEATURE_APPDOMAIN_RESOURCE_MONITORING - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void nEnableMonitoring(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool nMonitoringIsEnabled(); // return -1 if ARM is not supported. - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern Int64 nGetTotalProcessorTime(); // return -1 if ARM is not supported. - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern Int64 nGetTotalAllocatedMemorySize(); // return -1 if ARM is not supported. - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern Int64 nGetLastSurvivedMemorySize(); // return -1 if ARM is not supported. - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern Int64 nGetLastSurvivedProcessMemorySize(); public static bool MonitoringIsEnabled { - [System.Security.SecurityCritical] get { return nMonitoringIsEnabled(); } - [System.Security.SecurityCritical] set { if (value == false) { @@ -4554,7 +2635,6 @@ namespace System { // Throws NotSupportedException if ARM is not enabled. public TimeSpan MonitoringTotalProcessorTime { - [System.Security.SecurityCritical] get { Int64 i64ProcessorTime = nGetTotalProcessorTime(); if (i64ProcessorTime == -1) @@ -4570,7 +2650,6 @@ namespace System { // Throws NotSupportedException if ARM is not enabled. public Int64 MonitoringTotalAllocatedMemorySize { - [System.Security.SecurityCritical] get { Int64 i64AllocatedMemory = nGetTotalAllocatedMemorySize(); if (i64AllocatedMemory == -1) @@ -4588,7 +2667,6 @@ namespace System { // Throws NotSupportedException if ARM is not enabled. public Int64 MonitoringSurvivedMemorySize { - [System.Security.SecurityCritical] get { Int64 i64LastSurvivedMemory = nGetLastSurvivedMemorySize(); if (i64LastSurvivedMemory == -1) @@ -4608,7 +2686,6 @@ namespace System { // Throws NotSupportedException if ARM is not enabled. public static Int64 MonitoringSurvivedProcessMemorySize { - [System.Security.SecurityCritical] get { Int64 i64LastSurvivedProcessMemory = nGetLastSurvivedProcessMemorySize(); if (i64LastSurvivedProcessMemory == -1) @@ -4619,49 +2696,8 @@ namespace System { } } #endif - -#if !FEATURE_CORECLR - // this method is required so Object.GetType is not made virtual by the compiler - // _AppDomain.GetType() - public new Type GetType() - { - return base.GetType(); - } - - void _AppDomain.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _AppDomain.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _AppDomain.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - // If you implement this method, make sure to include _AppDomain.Invoke in VM\DangerousAPIs.h and - // include _AppDomain in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp. - void _AppDomain.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif } - // CallBacks provide a facility to request execution of some code - // in another context/appDomain. - // CrossAppDomainDelegate type is defined for appdomain call backs. - // The delegate used to request a callbak through the DoCallBack method - // must be of CrossContextDelegate type. -#if FEATURE_REMOTING -[System.Runtime.InteropServices.ComVisible(true)] - public delegate void CrossAppDomainDelegate(); -#endif - /// /// Handle used to marshal an AppDomain to the VM (eg QCall). When marshaled via a QCall, the target /// method in the VM will recieve a QCall::AppDomainHandle parameter. diff --git a/src/mscorlib/src/System/AppDomainManager.cs b/src/mscorlib/src/System/AppDomainManager.cs index 291099e..71bc088 100644 --- a/src/mscorlib/src/System/AppDomainManager.cs +++ b/src/mscorlib/src/System/AppDomainManager.cs @@ -8,151 +8,28 @@ // participate in the creation and control the settings of new AppDomains. // -namespace System { - using System.Collections; - using System.Globalization; - using System.IO; +namespace System +{ using System.Reflection; using System.Runtime.CompilerServices; using System.Security; - using System.Security.Permissions; - using System.Security.Policy; - using System.Threading; -#if FEATURE_CLICKONCE - using System.Runtime.Hosting; -#endif - using System.Runtime.Versioning; using System.Runtime.InteropServices; - using System.Diagnostics.Contracts; -#if FEATURE_APPDOMAINMANAGER_INITOPTIONS - [Flags] [System.Runtime.InteropServices.ComVisible(true)] - public enum AppDomainManagerInitializationOptions { - None = 0x0000, - RegisterWithHost = 0x0001 - } -#endif // FEATURE_APPDOMAINMANAGER_INITOPTIONS - - [System.Security.SecurityCritical] // auto-generated_required - [System.Runtime.InteropServices.ComVisible(true)] -#if !FEATURE_CORECLR - [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags = SecurityPermissionFlag.Infrastructure)] -#endif -#if FEATURE_REMOTING - public class AppDomainManager : MarshalByRefObject { -#else // FEATURE_REMOTING - public class AppDomainManager { -#endif // FEATURE_REMOTING + public class AppDomainManager : MarshalByRefObject + { public AppDomainManager () {} -#if FEATURE_REMOTING - [System.Security.SecurityCritical] // auto-generated - public virtual AppDomain CreateDomain (string friendlyName, - Evidence securityInfo, - AppDomainSetup appDomainInfo) { - return CreateDomainHelper(friendlyName, securityInfo, appDomainInfo); - } - - [System.Security.SecurityCritical] // auto-generated_required - [SecurityPermissionAttribute(SecurityAction.Demand, ControlAppDomain = true)] - protected static AppDomain CreateDomainHelper (string friendlyName, - Evidence securityInfo, - AppDomainSetup appDomainInfo) { - if (friendlyName == null) - throw new ArgumentNullException("friendlyName", Environment.GetResourceString("ArgumentNull_String")); - - Contract.EndContractBlock(); - // If evidence is provided, we check to make sure that is allowed. - if (securityInfo != null) { - new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand(); - - // Check the evidence to ensure that if it expects a sandboxed domain, it actually gets one. - AppDomain.CheckDomainCreationEvidence(appDomainInfo, securityInfo); - } - - if (appDomainInfo == null) { - appDomainInfo = new AppDomainSetup(); - } - - // If there was no specified AppDomainManager for the new domain, default it to being the same - // as the current domain's AppDomainManager. - if (appDomainInfo.AppDomainManagerAssembly == null || appDomainInfo.AppDomainManagerType == null) { - string inheritedDomainManagerAssembly; - string inheritedDomainManagerType; - - AppDomain.CurrentDomain.GetAppDomainManagerType(out inheritedDomainManagerAssembly, - out inheritedDomainManagerType); - if (appDomainInfo.AppDomainManagerAssembly == null) { - appDomainInfo.AppDomainManagerAssembly = inheritedDomainManagerAssembly; - } - if (appDomainInfo.AppDomainManagerType == null) { - appDomainInfo.AppDomainManagerType = inheritedDomainManagerType; - } - } - - // If there was no specified TargetFrameworkName for the new domain, default it to the current domain's. - if (appDomainInfo.TargetFrameworkName == null) - appDomainInfo.TargetFrameworkName = AppDomain.CurrentDomain.GetTargetFrameworkName(); - - return AppDomain.nCreateDomain(friendlyName, - appDomainInfo, - securityInfo, - securityInfo == null ? AppDomain.CurrentDomain.InternalEvidence : null, - AppDomain.CurrentDomain.GetSecurityDescriptor()); - } -#endif // FEATURE_REMOTING - - [System.Security.SecurityCritical] - public virtual void InitializeNewDomain (AppDomainSetup appDomainInfo) { + public virtual void InitializeNewDomain (AppDomainSetup appDomainInfo) + { // By default, InitializeNewDomain does nothing. AppDomain.CreateAppDomainManager relies on this fact. } -#if FEATURE_APPDOMAINMANAGER_INITOPTIONS - - private AppDomainManagerInitializationOptions m_flags = AppDomainManagerInitializationOptions.None; - public AppDomainManagerInitializationOptions InitializationFlags { - get { - return m_flags; - } - set { - m_flags = value; - } - } -#endif // FEATURE_APPDOMAINMANAGER_INITOPTIONS - -#if FEATURE_CLICKONCE - private ApplicationActivator m_appActivator = null; - public virtual ApplicationActivator ApplicationActivator { - get { - if (m_appActivator == null) - m_appActivator = new ApplicationActivator(); - return m_appActivator; - } - } -#endif //#if FEATURE_CLICKONCE - -#if FEATURE_CAS_POLICY - public virtual HostSecurityManager HostSecurityManager { - get { - return null; - } - } - - public virtual HostExecutionContextManager HostExecutionContextManager { - get { - // By default, the AppDomainManager returns the HostExecutionContextManager. - return HostExecutionContextManager.GetInternalHostExecutionContextManager(); - } - } -#endif // FEATURE_CAS_POLICY - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] private static extern void GetEntryAssembly(ObjectHandleOnStack retAssembly); private Assembly m_entryAssembly = null; public virtual Assembly EntryAssembly { - [System.Security.SecurityCritical] // auto-generated get { // The default AppDomainManager sets the EntryAssembly depending on whether the // AppDomain is a manifest application domain or not. In the first case, we parse @@ -160,14 +37,6 @@ namespace System { // In the second case, we maintain the old behavior by calling GetEntryAssembly(). if (m_entryAssembly == null) { - -#if FEATURE_CLICKONCE - AppDomain domain = AppDomain.CurrentDomain; - if (domain.IsDefaultAppDomain() && domain.ActivationContext != null) { - ManifestRunner runner = new ManifestRunner(domain, domain.ActivationContext); - m_entryAssembly = runner.EntryAssembly; - } else -#endif //#if FEATURE_CLICKONCE { RuntimeAssembly entryAssembly = null; GetEntryAssembly(JitHelpers.GetObjectHandleOnStack(ref entryAssembly)); @@ -179,7 +48,6 @@ namespace System { } internal static AppDomainManager CurrentAppDomainManager { - [System.Security.SecurityCritical] // auto-generated get { return AppDomain.CurrentDomain.DomainManager; } @@ -189,32 +57,5 @@ namespace System { { return false; } - -#if FEATURE_APPDOMAINMANAGER_INITOPTIONS - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern bool HasHost(); - - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SecurityCritical] - [SuppressUnmanagedCodeSecurity] - private static extern void RegisterWithHost(IntPtr appDomainManager); - - internal void RegisterWithHost() { - if (HasHost()) { - IntPtr punkAppDomainManager = IntPtr.Zero; - - RuntimeHelpers.PrepareConstrainedRegions(); - try { - punkAppDomainManager = Marshal.GetIUnknownForObject(this); - RegisterWithHost(punkAppDomainManager); - } - finally { - if (!punkAppDomainManager.IsNull()) { - Marshal.Release(punkAppDomainManager); - } - } - } - } -#endif // FEATURE_APPDOMAINMANAGER_INITOPTIONS } } diff --git a/src/mscorlib/src/System/AppDomainSetup.cs b/src/mscorlib/src/System/AppDomainSetup.cs index f1057da..fc8a64c 100644 --- a/src/mscorlib/src/System/AppDomainSetup.cs +++ b/src/mscorlib/src/System/AppDomainSetup.cs @@ -13,28 +13,16 @@ ** =============================================================================*/ -namespace System { - using System; -#if FEATURE_CLICKONCE - using System.Deployment.Internal.Isolation; - using System.Deployment.Internal.Isolation.Manifest; - using System.Runtime.Hosting; -#endif - using System.Runtime.CompilerServices; - using System.Runtime; +namespace System +{ using System.Text; - using System.Threading; using System.Runtime.InteropServices; using System.Runtime.Serialization; - using System.Reflection; using System.Security; - using System.Security.Permissions; using System.Security.Policy; - using System.Globalization; using Path = System.IO.Path; - using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; - using System.Collections; using System.Collections.Generic; [Serializable] @@ -75,10 +63,6 @@ namespace System { private const string MACHINE_CONFIGURATION_FILE = "config\\machine.config"; private const string ACTAG_HOST_CONFIG_FILE = "HOST_CONFIG"; -#if FEATURE_FUSION - private const string LICENSE_FILE = "LICENSE_FILE"; -#endif - // Constants from fusionpriv.h private const string ACTAG_APP_CONFIG_FILE = "APP_CONFIG_FILE"; private const string ACTAG_MACHINE_CONFIG = "MACHINE_CONFIG"; @@ -109,14 +93,9 @@ namespace System { private AppDomainInitializer _AppDomainInitializer; [OptionalField(VersionAdded = 2)] private string[] _AppDomainInitializerArguments; -#if FEATURE_CLICKONCE - [OptionalField(VersionAdded = 2)] - private ActivationArguments _ActivationArguments; -#endif -#if FEATURE_CORECLR + // On the CoreCLR, this contains just the name of the permission set that we install in the new appdomain. // Not the ToXml().ToString() of an ApplicationTrust object. -#endif [OptionalField(VersionAdded = 2)] private string _ApplicationTrust; [OptionalField(VersionAdded = 2)] @@ -130,11 +109,6 @@ namespace System { [OptionalField(VersionAdded = 4)] private string _AppDomainManagerType; -#if FEATURE_APTCA - [OptionalField(VersionAdded = 4)] - private string[] _AptcaVisibleAssemblies; -#endif - // A collection of strings used to indicate which breaking changes shouldn't be applied // to an AppDomain. We only use the keys, the values are ignored. [OptionalField(VersionAdded = 4)] @@ -143,11 +117,6 @@ namespace System { [OptionalField(VersionAdded = 5)] // This was added in .NET FX v4.5 private String _TargetFrameworkName; -#if !FEATURE_CORECLR - [NonSerialized] - internal AppDomainSortingSetupInfo _AppDomainSortingSetupInfo; -#endif - [OptionalField(VersionAdded = 5)] // This was added in .NET FX v4.5 private bool _CheckedForTargetFrameworkName; @@ -156,7 +125,6 @@ namespace System { private bool _UseRandomizedStringHashing; #endif - [SecuritySafeCritical] internal AppDomainSetup(AppDomainSetup copy, bool copyDomainBoundData) { string[] mine = Value; @@ -180,10 +148,8 @@ namespace System { _LoaderOptimization = copy._LoaderOptimization; _AppDomainInitializerArguments = copy.AppDomainInitializerArguments; -#if FEATURE_CLICKONCE - _ActivationArguments = copy.ActivationArguments; -#endif _ApplicationTrust = copy._ApplicationTrust; + if (copyDomainBoundData) _AppDomainInitializer = copy.AppDomainInitializer; else @@ -195,21 +161,12 @@ namespace System { #endif // FEATURE_COMINTEROP _AppDomainManagerAssembly = copy.AppDomainManagerAssembly; _AppDomainManagerType = copy.AppDomainManagerType; -#if FEATURE_APTCA - _AptcaVisibleAssemblies = copy.PartialTrustVisibleAssemblies; -#endif if (copy._CompatFlags != null) { SetCompatibilitySwitches(copy._CompatFlags.Keys); } -#if !FEATURE_CORECLR - if(copy._AppDomainSortingSetupInfo != null) - { - _AppDomainSortingSetupInfo = new AppDomainSortingSetupInfo(copy._AppDomainSortingSetupInfo); - } -#endif _TargetFrameworkName = copy._TargetFrameworkName; #if FEATURE_RANDOMIZED_STRING_HASHING @@ -226,32 +183,6 @@ namespace System { _LoaderOptimization = LoaderOptimization.NotSpecified; } -#if FEATURE_CLICKONCE - // Creates an AppDomainSetup object from an application identity. - public AppDomainSetup (ActivationContext activationContext) : this (new ActivationArguments(activationContext)) {} - - [System.Security.SecuritySafeCritical] // auto-generated - public AppDomainSetup (ActivationArguments activationArguments) { - if (activationArguments == null) - throw new ArgumentNullException("activationArguments"); - Contract.EndContractBlock(); - - _LoaderOptimization = LoaderOptimization.NotSpecified; - ActivationArguments = activationArguments; - - Contract.Assert(activationArguments.ActivationContext != null, "Cannot set base directory without activation context"); - string entryPointPath = CmsUtils.GetEntryPointFullPath(activationArguments); - if (!String.IsNullOrEmpty(entryPointPath)) - SetupDefaults(entryPointPath); - else - ApplicationBase = activationArguments.ActivationContext.ApplicationDirectory; - - } -#endif // !FEATURE_CLICKONCE - - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal void SetupDefaults(string imageLocation, bool imageLocationAlreadyNormalized = false) { char[] sep = {'\\', '/'}; int i = imageLocation.LastIndexOfAny(sep); @@ -297,37 +228,13 @@ namespace System { set { _AppDomainManagerType = value; } } -#if FEATURE_APTCA - public string[] PartialTrustVisibleAssemblies - { - get { return _AptcaVisibleAssemblies; } - set { - if (value != null) { - _AptcaVisibleAssemblies = (string[])value.Clone(); - Array.Sort(_AptcaVisibleAssemblies, StringComparer.OrdinalIgnoreCase); - } - else { - _AptcaVisibleAssemblies = null; - } - } - } -#endif - public String ApplicationBase { - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif [Pure] get { return VerifyDir(GetUnsecureApplicationBase(), false); } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif set { Value[(int) LoaderInformation.ApplicationBaseValue] = NormalizePath(value, false); } @@ -550,7 +457,6 @@ namespace System { public String ConfigurationFile { - [System.Security.SecuritySafeCritical] // auto-generated get { return VerifyDir(Value[(int) LoaderInformation.ConfigurationFileValue], true); } @@ -604,15 +510,6 @@ namespace System { public void SetCompatibilitySwitches(IEnumerable switches) { - -#if !FEATURE_CORECLR - if(_AppDomainSortingSetupInfo != null) - { - _AppDomainSortingSetupInfo._useV2LegacySorting = false; - _AppDomainSortingSetupInfo._useV4LegacySorting = false; - } -#endif - #if FEATURE_RANDOMIZED_STRING_HASHING _UseRandomizedStringHashing = false; #endif @@ -621,30 +518,11 @@ namespace System { _CompatFlags = new Dictionary(); foreach (String str in switches) { -#if !FEATURE_CORECLR - if(StringComparer.OrdinalIgnoreCase.Equals("NetFx40_Legacy20SortingBehavior", str)) { - if(_AppDomainSortingSetupInfo == null) - { - _AppDomainSortingSetupInfo = new AppDomainSortingSetupInfo(); - } - _AppDomainSortingSetupInfo._useV2LegacySorting = true; - } - - if(StringComparer.OrdinalIgnoreCase.Equals("NetFx45_Legacy40SortingBehavior", str)) { - if(_AppDomainSortingSetupInfo == null) - { - _AppDomainSortingSetupInfo = new AppDomainSortingSetupInfo(); - } - _AppDomainSortingSetupInfo._useV4LegacySorting = true; - } -#endif - #if FEATURE_RANDOMIZED_STRING_HASHING if(StringComparer.OrdinalIgnoreCase.Equals("UseRandomizedStringHashAlgorithm", str)) { _UseRandomizedStringHashing = true; } #endif - _CompatFlags.Add(str, null); } } @@ -671,82 +549,12 @@ namespace System { set { _CheckedForTargetFrameworkName = value; } } -#if !FEATURE_CORECLR - [SecurityCritical] - public void SetNativeFunction(string functionName, int functionVersion, IntPtr functionPointer) - { - if(functionName == null) - { - throw new ArgumentNullException("functionName"); - } - - if(functionPointer == IntPtr.Zero) - { - throw new ArgumentNullException("functionPointer"); - } - - if(String.IsNullOrWhiteSpace(functionName)) - { - throw new ArgumentException(Environment.GetResourceString("Argument_NPMSInvalidName"), "functionName"); - } - - Contract.EndContractBlock(); - - if(functionVersion < 1) - { - throw new ArgumentException(Environment.GetResourceString("ArgumentException_MinSortingVersion", 1, functionName)); - } - - if(_AppDomainSortingSetupInfo == null) - { - _AppDomainSortingSetupInfo = new AppDomainSortingSetupInfo(); - } - - if(String.Equals(functionName, "IsNLSDefinedString", StringComparison.OrdinalIgnoreCase)) - { - _AppDomainSortingSetupInfo._pfnIsNLSDefinedString = functionPointer; - } - - if (String.Equals(functionName, "CompareStringEx", StringComparison.OrdinalIgnoreCase)) - { - _AppDomainSortingSetupInfo._pfnCompareStringEx = functionPointer; - } - - if (String.Equals(functionName, "LCMapStringEx", StringComparison.OrdinalIgnoreCase)) - { - _AppDomainSortingSetupInfo._pfnLCMapStringEx = functionPointer; - } - - if (String.Equals(functionName, "FindNLSStringEx", StringComparison.OrdinalIgnoreCase)) - { - _AppDomainSortingSetupInfo._pfnFindNLSStringEx = functionPointer; - } - - if (String.Equals(functionName, "CompareStringOrdinal", StringComparison.OrdinalIgnoreCase)) - { - _AppDomainSortingSetupInfo._pfnCompareStringOrdinal = functionPointer; - } - - if (String.Equals(functionName, "GetNLSVersionEx", StringComparison.OrdinalIgnoreCase)) - { - _AppDomainSortingSetupInfo._pfnGetNLSVersionEx = functionPointer; - } - - if (String.Equals(functionName, "FindStringOrdinal", StringComparison.OrdinalIgnoreCase)) - { - _AppDomainSortingSetupInfo._pfnFindStringOrdinal = functionPointer; - } - } -#endif - public String DynamicBase { - [System.Security.SecuritySafeCritical] // auto-generated get { return VerifyDir(Value[(int) LoaderInformation.DynamicBaseValue], true); } - [System.Security.SecuritySafeCritical] // auto-generated set { if (value == null) Value[(int) LoaderInformation.DynamicBaseValue] = null; @@ -772,7 +580,6 @@ namespace System { } } - public bool DisallowPublisherPolicy { get @@ -835,7 +642,6 @@ namespace System { } } - [System.Security.SecurityCritical] // auto-generated private String VerifyDir(String dir, bool normalize) { if (dir != null) { @@ -844,22 +650,12 @@ namespace System { else { if (normalize) dir = NormalizePath(dir, true); - - // The only way AppDomainSetup is exposed in coreclr is through the AppDomainManager - // and the AppDomainManager is a SecurityCritical type. Also, all callers of callstacks - // leading from VerifyDir are SecurityCritical. So we can remove the Demand because - // we have validated that all callers are SecurityCritical -#if !FEATURE_CORECLR - if (IsFilePath(dir)) - new FileIOPermission( FileIOPermissionAccess.PathDiscovery, dir ).Demand(); -#endif // !FEATURE_CORECLR } } return dir; } - [System.Security.SecurityCritical] // auto-generated private void VerifyDirList(String dirs) { if (dirs != null) { @@ -873,7 +669,6 @@ namespace System { internal String DeveloperPath { - [System.Security.SecurityCritical] // auto-generated get { String dirs = Value[(int) LoaderInformation.DevPathValue]; VerifyDirList(dirs); @@ -896,7 +691,7 @@ namespace System { else fDelimiter = true; - newPath.Append(Path.GetFullPathInternal(directories[i])); + newPath.Append(Path.GetFullPath(directories[i])); } } @@ -988,83 +783,29 @@ namespace System { } } -#if FEATURE_CLICKONCE - [XmlIgnoreMember] - public ActivationArguments ActivationArguments { - [Pure] - get { - return _ActivationArguments; - } - set { - _ActivationArguments = value; - } - } -#endif // !FEATURE_CLICKONCE - internal ApplicationTrust InternalGetApplicationTrust() { - if (_ApplicationTrust == null) return null; - - -#if FEATURE_CORECLR ApplicationTrust grantSet = new ApplicationTrust(NamedPermissionSet.GetBuiltInSet(_ApplicationTrust)); -#else - SecurityElement securityElement = SecurityElement.FromString(_ApplicationTrust); - ApplicationTrust grantSet = new ApplicationTrust(); - grantSet.FromXml(securityElement); -#endif return grantSet; } -#if FEATURE_CORECLR internal void InternalSetApplicationTrust(String permissionSetName) { _ApplicationTrust = permissionSetName; } -#else - internal void InternalSetApplicationTrust(ApplicationTrust value) - { - if (value != null) - { - _ApplicationTrust = value.ToXml().ToString(); - } - else - { - _ApplicationTrust = null; - } - } -#endif -#if FEATURE_CLICKONCE - [XmlIgnoreMember] - public ApplicationTrust ApplicationTrust - { - get { - return InternalGetApplicationTrust(); - } - set { - InternalSetApplicationTrust(value); - } - } -#else // FEATURE_CLICKONCE [XmlIgnoreMember] internal ApplicationTrust ApplicationTrust { - get { + get + { return InternalGetApplicationTrust(); } -#if !FEATURE_CORECLR - set { - InternalSetApplicationTrust(value); - } -#endif } -#endif // FEATURE_CLICKONCE public String PrivateBinPath { - [System.Security.SecuritySafeCritical] // auto-generated get { String dirs = Value[(int) LoaderInformation.PrivateBinPathValue]; VerifyDirList(dirs); @@ -1083,7 +824,6 @@ namespace System { } } - public String PrivateBinPathProbe { get { @@ -1104,7 +844,6 @@ namespace System { public String ShadowCopyDirectories { - [System.Security.SecuritySafeCritical] // auto-generated get { String dirs = Value[(int) LoaderInformation.ShadowCopyDirectoriesValue]; VerifyDirList(dirs); @@ -1147,7 +886,6 @@ namespace System { public String CachePath { - [System.Security.SecuritySafeCritical] // auto-generated get { return VerifyDir(Value[(int) LoaderInformation.CachePathValue], false); } @@ -1166,7 +904,6 @@ namespace System { public String LicenseFile { - [System.Security.SecuritySafeCritical] // auto-generated get { return VerifyDir(Value[(int) LoaderInformation.LicenseFileValue], true); } @@ -1229,203 +966,17 @@ namespace System { } } -#if FEATURE_FUSION - [SecurityCritical] - internal bool UpdateContextPropertyIfNeeded(LoaderInformation FieldValue, String FieldKey, String UpdatedField, IntPtr fusionContext, AppDomainSetup oldADS) - { - String FieldString = Value[(int) FieldValue], - OldFieldString = (oldADS == null ? null : oldADS.Value[(int) FieldValue]); - if (FieldString != OldFieldString) { // Compare references since strings are immutable - UpdateContextProperty(fusionContext, FieldKey, UpdatedField == null ? FieldString : UpdatedField); - return true; - } - - return false; - } - - [SecurityCritical] - internal void UpdateBooleanContextPropertyIfNeeded(LoaderInformation FieldValue, String FieldKey, IntPtr fusionContext, AppDomainSetup oldADS) - { - if (Value[(int) FieldValue] != null) - UpdateContextProperty(fusionContext, FieldKey, "true"); - else if (oldADS != null && oldADS.Value[(int) FieldValue] != null) - UpdateContextProperty(fusionContext, FieldKey, "false"); - } - - [SecurityCritical] - internal static bool ByteArraysAreDifferent(Byte[] A, Byte[] B) - { - int length = A.Length; - if (length != B.Length) - return true; - - for(int i = 0; i < length; i++) { - if (A[i] != B[i]) - return true; - } - - return false; - } - - [System.Security.SecurityCritical] // auto-generated - internal static void UpdateByteArrayContextPropertyIfNeeded(Byte[] NewArray, Byte[] OldArray, String FieldKey, IntPtr fusionContext) - { - if ((NewArray != null && OldArray == null) || - (NewArray == null && OldArray != null) || - (NewArray != null && OldArray != null && ByteArraysAreDifferent(NewArray, OldArray))) - UpdateContextProperty(fusionContext, FieldKey, NewArray); - } - - [System.Security.SecurityCritical] // auto-generated - internal void SetupFusionContext(IntPtr fusionContext, AppDomainSetup oldADS) - { - UpdateContextPropertyIfNeeded(LoaderInformation.ApplicationBaseValue, ApplicationBaseKey, null, fusionContext, oldADS); - UpdateContextPropertyIfNeeded(LoaderInformation.PrivateBinPathValue, PrivateBinPathKey, null, fusionContext, oldADS); - UpdateContextPropertyIfNeeded(LoaderInformation.DevPathValue, DeveloperPathKey, null, fusionContext, oldADS); - - UpdateBooleanContextPropertyIfNeeded(LoaderInformation.DisallowPublisherPolicyValue, DisallowPublisherPolicyKey, fusionContext, oldADS); - UpdateBooleanContextPropertyIfNeeded(LoaderInformation.DisallowCodeDownloadValue, DisallowCodeDownloadKey, fusionContext, oldADS); - UpdateBooleanContextPropertyIfNeeded(LoaderInformation.DisallowBindingRedirectsValue, DisallowBindingRedirectsKey, fusionContext, oldADS); - UpdateBooleanContextPropertyIfNeeded(LoaderInformation.DisallowAppBaseProbingValue, DisallowAppBaseProbingKey, fusionContext, oldADS); - - if(UpdateContextPropertyIfNeeded(LoaderInformation.ShadowCopyFilesValue, ShadowCopyFilesKey, ShadowCopyFiles, fusionContext, oldADS)) { - - // If we are asking for shadow copy directories then default to - // only to the ones that are in the private bin path. - if(Value[(int) LoaderInformation.ShadowCopyDirectoriesValue] == null) - ShadowCopyDirectories = BuildShadowCopyDirectories(); - - UpdateContextPropertyIfNeeded(LoaderInformation.ShadowCopyDirectoriesValue, ShadowCopyDirectoriesKey, null, fusionContext, oldADS); - } - - UpdateContextPropertyIfNeeded(LoaderInformation.CachePathValue, CachePathKey, null, fusionContext, oldADS); - UpdateContextPropertyIfNeeded(LoaderInformation.PrivateBinPathProbeValue, PrivateBinPathProbeKey, PrivateBinPathProbe, fusionContext, oldADS); - UpdateContextPropertyIfNeeded(LoaderInformation.ConfigurationFileValue, ConfigurationFileKey, null, fusionContext, oldADS); - - UpdateByteArrayContextPropertyIfNeeded(_ConfigurationBytes, oldADS == null ? null : oldADS.GetConfigurationBytes(), ConfigurationBytesKey, fusionContext); - - UpdateContextPropertyIfNeeded(LoaderInformation.ApplicationNameValue, ApplicationNameKey, ApplicationName, fusionContext, oldADS); - UpdateContextPropertyIfNeeded(LoaderInformation.DynamicBaseValue, DynamicBaseKey, null, fusionContext, oldADS); - - // Always add the runtime configuration file to the appdomain - UpdateContextProperty(fusionContext, MachineConfigKey, RuntimeEnvironment.GetRuntimeDirectoryImpl() + RuntimeConfigurationFile); - - String hostBindingFile = RuntimeEnvironment.GetHostBindingFile(); - if(hostBindingFile != null || oldADS != null) // If oldADS != null, we don't know the old value of the hostBindingFile, so we force an update even when hostBindingFile == null. - UpdateContextProperty(fusionContext, HostBindingKey, hostBindingFile); - } - - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern void UpdateContextProperty(IntPtr fusionContext, string key, Object value); -#endif // FEATURE_FUSION - static internal int Locate(String s) { if(String.IsNullOrEmpty(s)) return -1; -#if FEATURE_FUSION - - // verify assumptions hardcoded into the switch below - Contract.Assert('A' == ACTAG_APP_CONFIG_FILE[0] , "Assumption violated"); - Contract.Assert('A' == ACTAG_APP_NAME[0] , "Assumption violated"); - Contract.Assert('A' == ACTAG_APP_BASE_URL[0] , "Assumption violated"); - Contract.Assert('B' == ACTAG_BINPATH_PROBE_ONLY[0] , "Assumption violated"); - Contract.Assert('C' == ACTAG_APP_CACHE_BASE[0] , "Assumption violated"); - Contract.Assert('D' == ACTAG_DEV_PATH[0] , "Assumption violated"); - Contract.Assert('D' == ACTAG_APP_DYNAMIC_BASE[0] , "Assumption violated"); - Contract.Assert('F' == ACTAG_FORCE_CACHE_INSTALL[0] , "Assumption violated"); - Contract.Assert('L' == LICENSE_FILE[0] , "Assumption violated"); - Contract.Assert('P' == ACTAG_APP_PRIVATE_BINPATH[0] , "Assumption violated"); - Contract.Assert('S' == ACTAG_APP_SHADOW_COPY_DIRS[0], "Assumption violated"); - Contract.Assert('D' == ACTAG_DISALLOW_APPLYPUBLISHERPOLICY[0], "Assumption violated"); - Contract.Assert('C' == ACTAG_CODE_DOWNLOAD_DISABLED[0], "Assumption violated"); - Contract.Assert('D' == ACTAG_DISALLOW_APP_BINDING_REDIRECTS[0], "Assumption violated"); - Contract.Assert('D' == ACTAG_DISALLOW_APP_BASE_PROBING[0], "Assumption violated"); - Contract.Assert('A' == ACTAG_APP_CONFIG_BLOB[0], "Assumption violated"); - - switch (s[0]) { - case 'A': - if (s == ACTAG_APP_CONFIG_FILE) return (int)LoaderInformation.ConfigurationFileValue; - if (s == ACTAG_APP_NAME) return (int)LoaderInformation.ApplicationNameValue; - if (s == ACTAG_APP_BASE_URL) return (int)LoaderInformation.ApplicationBaseValue; - if (s == ACTAG_APP_CONFIG_BLOB) return (int)LoaderInformation.ConfigurationBytesValue; - break; - case 'B': - if (s == ACTAG_BINPATH_PROBE_ONLY) return (int)LoaderInformation.PrivateBinPathProbeValue; - break; - case 'C': - if (s == ACTAG_APP_CACHE_BASE) return (int)LoaderInformation.CachePathValue; - if (s == ACTAG_CODE_DOWNLOAD_DISABLED) return (int)LoaderInformation.DisallowCodeDownloadValue; - break; - case 'D': - if (s == ACTAG_DEV_PATH) return (int)LoaderInformation.DevPathValue; - if (s == ACTAG_APP_DYNAMIC_BASE) return (int)LoaderInformation.DynamicBaseValue; - if (s == ACTAG_DISALLOW_APPLYPUBLISHERPOLICY) return (int)LoaderInformation.DisallowPublisherPolicyValue; - if (s == ACTAG_DISALLOW_APP_BINDING_REDIRECTS) return (int)LoaderInformation.DisallowBindingRedirectsValue; - if (s == ACTAG_DISALLOW_APP_BASE_PROBING) return (int)LoaderInformation.DisallowAppBaseProbingValue; - break; - case 'F': - if (s == ACTAG_FORCE_CACHE_INSTALL) return (int)LoaderInformation.ShadowCopyFilesValue; - break; - case 'L': - if (s == LICENSE_FILE) return (int)LoaderInformation.LicenseFileValue; - break; - case 'P': - if (s == ACTAG_APP_PRIVATE_BINPATH) return (int)LoaderInformation.PrivateBinPathValue; - break; - case 'S': - if (s == ACTAG_APP_SHADOW_COPY_DIRS) return (int)LoaderInformation.ShadowCopyDirectoriesValue; - break; - } -#else - Contract.Assert('A' == ACTAG_APP_BASE_URL[0] , "Assumption violated"); + + Debug.Assert('A' == ACTAG_APP_BASE_URL[0] , "Assumption violated"); if (s[0]=='A' && s == ACTAG_APP_BASE_URL) return (int)LoaderInformation.ApplicationBaseValue; -#endif //FEATURE_FUSION - return -1; } -#if FEATURE_FUSION - private string BuildShadowCopyDirectories() - { - // Default to only to the ones that are in the private bin path. - String binPath = Value[(int) LoaderInformation.PrivateBinPathValue]; - if(binPath == null) - return null; - - StringBuilder result = StringBuilderCache.Acquire(); - String appBase = Value[(int) LoaderInformation.ApplicationBaseValue]; - if(appBase != null) { - char[] sep = {';'}; - string[] directories = binPath.Split(sep); - int size = directories.Length; - bool appendSlash = !( (appBase[appBase.Length-1] == '/') || - (appBase[appBase.Length-1] == '\\') ); - - if (size == 0) { - result.Append(appBase); - if (appendSlash) - result.Append('\\'); - result.Append(binPath); - } - else { - for(int i = 0; i < size; i++) { - result.Append(appBase); - if (appendSlash) - result.Append('\\'); - result.Append(directories[i]); - - if (i < size-1) - result.Append(';'); - } - } - } - - return StringBuilderCache.GetStringAndRelease(result); - } -#endif // FEATURE_FUSION #if FEATURE_COMINTEROP public bool SandboxInterop diff --git a/src/mscorlib/src/System/ApplicationId.cs b/src/mscorlib/src/System/ApplicationId.cs index fa8be95..93fc37d 100644 --- a/src/mscorlib/src/System/ApplicationId.cs +++ b/src/mscorlib/src/System/ApplicationId.cs @@ -33,13 +33,13 @@ namespace System { public ApplicationId (byte[] publicKeyToken, string name, Version version, string processorArchitecture, string culture) { if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); if (name.Length == 0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyApplicationName")); if (version == null) - throw new ArgumentNullException("version"); + throw new ArgumentNullException(nameof(version)); if (publicKeyToken == null) - throw new ArgumentNullException("publicKeyToken"); + throw new ArgumentNullException(nameof(publicKeyToken)); Contract.EndContractBlock(); m_publicKeyToken = new byte[publicKeyToken.Length]; diff --git a/src/mscorlib/src/System/ArgIterator.cs b/src/mscorlib/src/System/ArgIterator.cs index 0ce27ed..c5bc379 100644 --- a/src/mscorlib/src/System/ArgIterator.cs +++ b/src/mscorlib/src/System/ArgIterator.cs @@ -16,19 +16,16 @@ namespace System { [StructLayout(LayoutKind.Sequential)] public struct ArgIterator { - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern ArgIterator(IntPtr arglist); // create an arg iterator that points at the first argument that // is not statically declared (that is the first ... arg) // 'arglist' is the value returned by the ARGLIST instruction - [System.Security.SecuritySafeCritical] // auto-generated public ArgIterator(RuntimeArgumentHandle arglist) : this(arglist.Value) { } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private unsafe extern ArgIterator(IntPtr arglist, void *ptr); @@ -36,7 +33,6 @@ namespace System { // 'arglist' is the value returned by the ARGLIST instruction // This is much like the C va_start macro - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] public unsafe ArgIterator(RuntimeArgumentHandle arglist, void* ptr) : this(arglist.Value, ptr) @@ -45,7 +41,6 @@ namespace System { // Fetch an argument as a typed referece, advance the iterator. // Throws an exception if past end of argument list - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] public TypedReference GetNextArg() { @@ -58,14 +53,12 @@ namespace System { return result; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] // reference to TypedReference is banned, so have to pass result as void pointer private unsafe extern void FCallGetNextArg(void * result); // Alternate version of GetNextArg() intended primarily for IJW code // generated by VC's "va_arg()" construct. - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] public TypedReference GetNextArg(RuntimeTypeHandle rth) { @@ -96,7 +89,6 @@ namespace System { } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] // reference to TypedReference is banned, so have to pass result as void pointer private unsafe extern void InternalGetNextArg(void * result, RuntimeType rt); @@ -107,16 +99,13 @@ namespace System { } // How many arguments are left in the list - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern int GetRemainingCount(); // Gets the type of the current arg, does NOT advance the iterator - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern unsafe void* _GetNextArgType(); - [System.Security.SecuritySafeCritical] // auto-generated public unsafe RuntimeTypeHandle GetNextArgType() { return new RuntimeTypeHandle(Type.GetTypeFromHandleUnsafe((IntPtr)_GetNextArgType())); diff --git a/src/mscorlib/src/System/ArgumentException.cs b/src/mscorlib/src/System/ArgumentException.cs index 8edb7e4..f37b769 100644 --- a/src/mscorlib/src/System/ArgumentException.cs +++ b/src/mscorlib/src/System/ArgumentException.cs @@ -82,10 +82,9 @@ namespace System { get { return m_paramName; } } - [System.Security.SecurityCritical] // auto-generated_required public override void GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); base.GetObjectData(info, context); diff --git a/src/mscorlib/src/System/ArgumentNullException.cs b/src/mscorlib/src/System/ArgumentNullException.cs index 4bcb537..661ebd2 100644 --- a/src/mscorlib/src/System/ArgumentNullException.cs +++ b/src/mscorlib/src/System/ArgumentNullException.cs @@ -48,7 +48,6 @@ namespace System { SetErrorCode(__HResults.E_POINTER); } - [System.Security.SecurityCritical] // auto-generated_required protected ArgumentNullException(SerializationInfo info, StreamingContext context) : base(info, context) { } } diff --git a/src/mscorlib/src/System/ArgumentOutOfRangeException.cs b/src/mscorlib/src/System/ArgumentOutOfRangeException.cs index a54380b..78a90db 100644 --- a/src/mscorlib/src/System/ArgumentOutOfRangeException.cs +++ b/src/mscorlib/src/System/ArgumentOutOfRangeException.cs @@ -89,10 +89,9 @@ namespace System { get { return m_actualValue; } } - [System.Security.SecurityCritical] // auto-generated_required public override void GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); base.GetObjectData(info, context); diff --git a/src/mscorlib/src/System/Array.cs b/src/mscorlib/src/System/Array.cs index 0879049..7bb6ebb 100644 --- a/src/mscorlib/src/System/Array.cs +++ b/src/mscorlib/src/System/Array.cs @@ -19,6 +19,7 @@ namespace System { using System.Runtime.ConstrainedExecution; using System.Runtime.Versioning; using System.Security; + using System.Diagnostics; using System.Security.Permissions; using System.Diagnostics.Contracts; @@ -64,13 +65,12 @@ namespace System { } // Create instance will create an array - [System.Security.SecuritySafeCritical] // auto-generated public unsafe static Array CreateInstance(Type elementType, int length) { if ((object)elementType == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType); if (length < 0) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); Contract.Ensures(Contract.Result() != null); Contract.Ensures(Contract.Result().Length == length); Contract.Ensures(Contract.Result().Rank == 1); @@ -82,7 +82,6 @@ namespace System { return InternalCreate((void*)t.TypeHandle.Value,1,&length,null); } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe static Array CreateInstance(Type elementType, int length1, int length2) { if ((object)elementType == null) @@ -105,7 +104,6 @@ namespace System { return InternalCreate((void*)t.TypeHandle.Value,2,pLengths,null); } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe static Array CreateInstance(Type elementType, int length1, int length2, int length3) { if ((object)elementType == null) @@ -132,7 +130,6 @@ namespace System { return InternalCreate((void*)t.TypeHandle.Value,3,pLengths,null); } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe static Array CreateInstance(Type elementType, params int[] lengths) { if ((object)elementType == null) @@ -186,7 +183,6 @@ namespace System { } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe static Array CreateInstance(Type elementType, int[] lengths,int[] lowerBounds) { if (elementType == null) @@ -219,41 +215,25 @@ namespace System { fixed(int* pLowerBounds = lowerBounds) return InternalCreate((void*)t.TypeHandle.Value,lengths.Length,pLengths,pLowerBounds); } - [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] private unsafe static extern Array InternalCreate(void* elementType,int rank,int *pLengths,int *pLowerBounds); - [SecurityCritical] -#if !FEATURE_CORECLR - [PermissionSet(SecurityAction.Assert, Unrestricted = true)] -#endif internal static Array UnsafeCreateInstance(Type elementType, int length) { return CreateInstance(elementType, length); } - [SecurityCritical] -#if !FEATURE_CORECLR - [PermissionSet(SecurityAction.Assert, Unrestricted = true)] -#endif internal static Array UnsafeCreateInstance(Type elementType, int length1, int length2) { return CreateInstance(elementType, length1, length2); } - [SecurityCritical] -#if !FEATURE_CORECLR - [PermissionSet(SecurityAction.Assert, Unrestricted = true)] -#endif internal static Array UnsafeCreateInstance(Type elementType, params int[] lengths) { return CreateInstance(elementType, lengths); } - [SecurityCritical] -#if !FEATURE_CORECLR - [PermissionSet(SecurityAction.Assert, Unrestricted = true)] -#endif internal static Array UnsafeCreateInstance(Type elementType, int[] lengths, int[] lowerBounds) { return CreateInstance(elementType, lengths, lowerBounds); @@ -262,7 +242,6 @@ namespace System { // Copies length elements from sourceArray, starting at index 0, to // destinationArray, starting at index 0. // - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Copy(Array sourceArray, Array destinationArray, int length) { @@ -284,7 +263,6 @@ namespace System { // Copies length elements from sourceArray, starting at sourceIndex, to // destinationArray, starting at destinationIndex. // - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Copy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length) { @@ -295,7 +273,6 @@ namespace System { // instance & might fail when called from within a CER, or if the // reliable flag is true, it will either always succeed or always // throw an exception with no side effects. - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void Copy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length, bool reliable); @@ -305,7 +282,6 @@ namespace System { // compatible array types based on the array element type - this // method does not support casting, boxing, or primitive widening. // It will up-cast, assuming the array types are correct. - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static void ConstrainedCopy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length) { @@ -338,13 +314,11 @@ namespace System { // Sets length elements in array to 0 (or null for Object arrays), starting // at index. // - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static extern void Clear(Array array, int index, int length); // The various Get values... - [System.Security.SecuritySafeCritical] // auto-generated public unsafe Object GetValue(params int[] indices) { if (indices == null) @@ -359,7 +333,6 @@ namespace System { return TypedReference.InternalToObject(&elemref); } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe Object GetValue(int index) { if (Rank != 1) @@ -371,7 +344,6 @@ namespace System { return TypedReference.InternalToObject(&elemref); } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe Object GetValue(int index1, int index2) { if (Rank != 2) @@ -387,7 +359,6 @@ namespace System { return TypedReference.InternalToObject(&elemref); } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe Object GetValue(int index1, int index2, int index3) { if (Rank != 3) @@ -463,7 +434,6 @@ namespace System { } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe void SetValue(Object value,int index) { if (Rank != 1) @@ -475,7 +445,6 @@ namespace System { InternalSetValue(&elemref,value); } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe void SetValue(Object value,int index1, int index2) { if (Rank != 2) @@ -491,7 +460,6 @@ namespace System { InternalSetValue(&elemref,value); } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe void SetValue(Object value,int index1, int index2, int index3) { if (Rank != 3) @@ -508,7 +476,6 @@ namespace System { InternalSetValue(&elemref,value); } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe void SetValue(Object value,params int[] indices) { if (indices == null) @@ -581,20 +548,17 @@ namespace System { this.SetValue(value, intIndices); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] // reference to TypedReference is banned, so have to pass result as pointer private unsafe extern void InternalGetReference(void * elemRef, int rank, int * pIndices); // Ideally, we would like to use TypedReference.SetValue instead. Unfortunately, TypedReference.SetValue // always throws not-supported exception - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private unsafe extern static void InternalSetValue(void * target, Object value); public extern int Length { [Pure] - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [MethodImpl(MethodImplOptions.InternalCall)] get; @@ -604,7 +568,7 @@ namespace System { private static int GetMedian(int low, int hi) { // Note both may be negative, if we are dealing with arrays w/ negative lower bounds. Contract.Requires(low <= hi); - Contract.Assert( hi - low >= 0, "Length overflow!"); + Debug.Assert( hi - low >= 0, "Length overflow!"); return low + ((hi - low) >> 1); } @@ -619,14 +583,12 @@ namespace System { [ComVisible(false)] public extern long LongLength { [Pure] - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [MethodImpl(MethodImplOptions.InternalCall)] get; } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern int GetLength(int dimension); @@ -639,25 +601,21 @@ namespace System { public extern int Rank { [Pure] - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [MethodImplAttribute(MethodImplOptions.InternalCall)] get; } - [System.Security.SecuritySafeCritical] // auto-generated [Pure] [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public extern int GetUpperBound(int dimension); - [System.Security.SecuritySafeCritical] // auto-generated [Pure] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern int GetLowerBound(int dimension); - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern int GetDataPtrOffsetInternal(); @@ -894,7 +852,6 @@ namespace System { // is larger than the given search value. // [Pure] - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static int BinarySearch(Array array, int index, int length, Object value, IComparer comparer) { if (array==null) @@ -904,7 +861,7 @@ namespace System { if (index < lb) ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); if (length < 0) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); if (array.Length - (index - lb) < length) ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); if (array.Rank != 1) @@ -965,7 +922,6 @@ namespace System { return ~lo; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] private static extern bool TrySZBinarySearch(Array sourceArray, int sourceIndex, int count, Object value, out int retVal); @@ -1002,7 +958,7 @@ namespace System { if (index < 0) ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); if (length < 0) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); if (array.Length - index < length) ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); @@ -1073,6 +1029,42 @@ namespace System { return Array.FindIndex(array, match) != -1; } + public static void Fill(T[] array, T value) + { + if (array == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + } + + for (int i = 0; i < array.Length; i++) + { + array[i] = value; + } + } + + public static void Fill(T[] array, T value, int startIndex, int count) + { + if (array == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + } + + if (startIndex < 0 || startIndex > array.Length) + { + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); + } + + if (count < 0 || startIndex > array.Length - count) + { + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); + } + + for (int i = startIndex; i < startIndex + count; i++) + { + array[i] = value; + } + } + public static T Find(T[] array, Predicate match) { if( array == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -1136,11 +1128,11 @@ namespace System { } if( startIndex < 0 || startIndex > array.Length ) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); } if (count < 0 || startIndex > array.Length - count) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count); + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); } if( match == null) { @@ -1205,19 +1197,19 @@ namespace System { if(array.Length == 0) { // Special case for 0 length List if( startIndex != -1) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); } } else { // Make sure we're not out of range if ( startIndex < 0 || startIndex >= array.Length) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); } } // 2nd have of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0. if (count < 0 || startIndex - count + 1 < 0) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count); + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); } int endIndex = startIndex - count; @@ -1293,7 +1285,6 @@ namespace System { // elements of the array are compared to the given value using the // Object.Equals method. // - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static int IndexOf(Array array, Object value, int startIndex, int count) { if (array==null) @@ -1305,9 +1296,9 @@ namespace System { int lb = array.GetLowerBound(0); if (startIndex < lb || startIndex > array.Length + lb) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); if (count < 0 || count > array.Length - startIndex + lb) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count); + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); // Try calling a quick native method to handle primitive types. int retVal; @@ -1376,11 +1367,11 @@ namespace System { } if (startIndex < 0 || startIndex > array.Length ) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); } if (count < 0 || count > array.Length - startIndex) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count); + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); } Contract.Ensures(Contract.Result() < array.Length); Contract.EndContractBlock(); @@ -1388,7 +1379,6 @@ namespace System { return EqualityComparer.Default.IndexOf(array, value, startIndex, count); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] private static extern bool TrySZIndexOf(Array sourceArray, int sourceIndex, int count, Object value, out int retVal); @@ -1429,7 +1419,6 @@ namespace System { // the array are compared to the given value using the Object.Equals // method. // - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static int LastIndexOf(Array array, Object value, int startIndex, int count) { if (array==null) @@ -1442,9 +1431,9 @@ namespace System { } if (startIndex < lb || startIndex >= array.Length + lb) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); if (count < 0) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count); + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); if (count > startIndex - lb + 1) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.endIndex, ExceptionResource.ArgumentOutOfRange_EndIndexStartIndex); if (array.Rank != 1) @@ -1518,30 +1507,29 @@ namespace System { // accept -1 and 0 as valid startIndex for compablility reason. // if( startIndex != -1 && startIndex != 0) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); } // only 0 is a valid value for count if array is empty if( count != 0) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count); + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); } return -1; } // Make sure we're not out of range if ( startIndex < 0 || startIndex >= array.Length) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); } // 2nd have of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0. if (count < 0 || startIndex - count + 1 < 0) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count); + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); } return EqualityComparer.Default.LastIndexOf(array, value, startIndex, count); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] private static extern bool TrySZLastIndexOf(Array sourceArray, int sourceIndex, int count, Object value, out int retVal); @@ -1566,7 +1554,6 @@ namespace System { // index index + (index + count - i - 1). // Reliability note: This may fail because it may have to box objects. // - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Reverse(Array array, int index, int length) { if (array==null) @@ -1575,7 +1562,7 @@ namespace System { if (index < lowerBound) ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); if (length < 0) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); if (array.Length - (index - lowerBound) < length) ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); @@ -1610,11 +1597,44 @@ namespace System { } } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] private static extern bool TrySZReverse(Array array, int index, int count); - + + [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] + public static void Reverse(T[] array) + { + if (array == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + Contract.EndContractBlock(); + Reverse(array, 0, array.Length); + } + + [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] + public static void Reverse(T[] array, int index, int length) + { + if (array == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + if (index < 0) + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + if (length < 0) + ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); + if (array.Length - index < length) + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); + Contract.EndContractBlock(); + + int i = index; + int j = index + length - 1; + while (i < j) + { + T temp = array[i]; + array[i] = array[j]; + array[j] = temp; + i++; + j--; + } + } + // Sorts the elements of an array. The sort compares the elements to each // other using the IComparable interface, which must be implemented // by all elements of the array. @@ -1710,7 +1730,6 @@ namespace System { // the IComparable interface, which in that case must be implemented // by all elements of the given section of the keys array. // - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Sort(Array keys, Array items, int index, int length, IComparer comparer) { if (keys==null) @@ -1723,7 +1742,7 @@ namespace System { if (index < keysLowerBound) ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); if (length < 0) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); if (keys.Length - (index - keysLowerBound) < length || (items != null && (index - keysLowerBound) > items.Length - length)) ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); @@ -1752,7 +1771,6 @@ namespace System { } } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] private static extern bool TrySZSort(Array keys, Array items, int left, int right); @@ -1799,7 +1817,6 @@ namespace System { Sort(keys, items, 0, keys.Length, comparer); } - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Sort(T[] array, int index, int length, System.Collections.Generic.IComparer comparer) { if (array==null) @@ -1807,7 +1824,7 @@ namespace System { if (index < 0) ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); if (length < 0) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); if (array.Length - index < length) ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); Contract.EndContractBlock(); @@ -1823,7 +1840,6 @@ namespace System { } } - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Sort(TKey[] keys, TValue[] items, int index, int length, System.Collections.Generic.IComparer comparer) { if (keys==null) @@ -1831,7 +1847,7 @@ namespace System { if (index < 0) ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); if (length < 0) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); if (keys.Length - index < length || (items != null && index > items.Length - length)) ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); Contract.EndContractBlock(); @@ -1863,8 +1879,7 @@ namespace System { } Contract.EndContractBlock(); - IComparer comparer = Comparer.Create(comparison); - Array.Sort(array, comparer); + ArraySortHelper.Sort(array, 0, array.Length, comparison); } public static bool TrueForAll(T[] array, Predicate match) { @@ -1935,120 +1950,7 @@ namespace System { internal void Sort(int left, int length) { -#if FEATURE_CORECLR - // Since QuickSort and IntrospectiveSort produce different sorting sequence for equal keys the upgrade - // to IntrospectiveSort was quirked. However since the phone builds always shipped with the new sort aka - // IntrospectiveSort and we would want to continue using this sort moving forward CoreCLR always uses the new sort. - IntrospectiveSort(left, length); -#else - if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) - { - IntrospectiveSort(left, length); - } - else - { - DepthLimitedQuickSort(left, length + left - 1, IntrospectiveSortUtilities.QuickSortDepthThreshold); - } -#endif - } - - private void DepthLimitedQuickSort(int left, int right, int depthLimit) - { - // Can use the much faster jit helpers for array access. - do - { - if (depthLimit == 0) - { - // Add a try block here to detect IComparers (or their - // underlying IComparables, etc) that are bogus. - try - { - Heapsort(left, right); - return; - } - catch (IndexOutOfRangeException) - { - ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_BogusIComparer, ExceptionArgument.comparer); - } - catch (Exception e) - { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e); - } - } - - int i = left; - int j = right; - - // pre-sort the low, middle (pivot), and high values in place. - // this improves performance in the face of already sorted data, or - // data that is made up of multiple sorted runs appended together. - int middle = GetMedian(i, j); - - // Add a try block here to detect IComparers (or their - // underlying IComparables, etc) that are bogus. - try - { - SwapIfGreaterWithItems(i, middle); // swap the low with the mid point - SwapIfGreaterWithItems(i, j); // swap the low with the high - SwapIfGreaterWithItems(middle, j); // swap the middle with the high - } - catch (Exception e) - { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e); - } - Object x = keys[middle]; - do - { - // Add a try block here to detect IComparers (or their - // underlying IComparables, etc) that are bogus. - try - { - while (comparer.Compare(keys[i], x) < 0) i++; - while (comparer.Compare(x, keys[j]) < 0) j--; - } - catch (IndexOutOfRangeException) - { - ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_BogusIComparer, ExceptionArgument.comparer); - } - catch (Exception e) - { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e); - } - Contract.Assert(i >= left && j <= right, "(i>=left && j<=right) Sort failed - Is your IComparer bogus?"); - if (i > j) break; - if (i < j) - { - Object key = keys[i]; - keys[i] = keys[j]; - keys[j] = key; - if (items != null) - { - Object item = items[i]; - items[i] = items[j]; - items[j] = item; - } - } - i++; - j--; - } while (i <= j); - - // The next iteration of the while loop is to "recursively" sort the larger half of the array and the - // following calls recursively sort the smaller half. So we subtract one from depthLimit here so - // both sorts see the new value. - depthLimit--; - - if (j - left <= right - i) - { - if (left < j) DepthLimitedQuickSort(left, j, depthLimit); - left = i; - } - else - { - if (i < right) DepthLimitedQuickSort(i, right, depthLimit); - right = j; - } - } while (left < right); } private void IntrospectiveSort(int left, int length) @@ -2254,118 +2156,7 @@ namespace System { internal void Sort(int left, int length) { -#if FEATURE_CORECLR - // Since QuickSort and IntrospectiveSort produce different sorting sequence for equal keys the upgrade - // to IntrospectiveSort was quirked. However since the phone builds always shipped with the new sort aka - // IntrospectiveSort and we would want to continue using this sort moving forward CoreCLR always uses the new sort. - IntrospectiveSort(left, length); -#else - if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) - { - IntrospectiveSort(left, length); - } - else - { - DepthLimitedQuickSort(left, length + left - 1, IntrospectiveSortUtilities.QuickSortDepthThreshold); - } -#endif - } - - private void DepthLimitedQuickSort(int left, int right, int depthLimit) - { - // Must use slow Array accessors (GetValue & SetValue) - do - { - if (depthLimit == 0) - { - // Add a try block here to detect IComparers (or their - // underlying IComparables, etc) that are bogus. - try - { - Heapsort(left, right); - return; - } - catch (IndexOutOfRangeException) - { - ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_BogusIComparer, ExceptionArgument.comparer); - } - catch (Exception e) - { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e); - } - } - - int i = left; - int j = right; - - // pre-sort the low, middle (pivot), and high values in place. - // this improves performance in the face of already sorted data, or - // data that is made up of multiple sorted runs appended together. - int middle = GetMedian(i, j); - try - { - SwapIfGreaterWithItems(i, middle); // swap the low with the mid point - SwapIfGreaterWithItems(i, j); // swap the low with the high - SwapIfGreaterWithItems(middle, j); // swap the middle with the high - } - catch (Exception e) - { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e); - } - - Object x = keys.GetValue(middle); - do - { - // Add a try block here to detect IComparers (or their - // underlying IComparables, etc) that are bogus. - try - { - while (comparer.Compare(keys.GetValue(i), x) < 0) i++; - while (comparer.Compare(x, keys.GetValue(j)) < 0) j--; - } - catch (IndexOutOfRangeException) - { - ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_BogusIComparer, ExceptionArgument.comparer); - } - catch (Exception e) - { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e); - } - Contract.Assert(i >= left && j <= right, "(i>=left && j<=right) Sort failed - Is your IComparer bogus?"); - if (i > j) break; - if (i < j) - { - Object key = keys.GetValue(i); - keys.SetValue(keys.GetValue(j), i); - keys.SetValue(key, j); - if (items != null) - { - Object item = items.GetValue(i); - items.SetValue(items.GetValue(j), i); - items.SetValue(item, j); - } - } - if (i != Int32.MaxValue) ++i; - if (j != Int32.MinValue) --j; - } while (i <= j); - - // The next iteration of the while loop is to "recursively" sort the larger half of the array and the - // following calls recursively sort the smaller half. So we subtract one from depthLimit here so - // both sorts see the new value. - depthLimit--; - - if (j - left <= right - i) - { - if (left < j) DepthLimitedQuickSort(left, j, depthLimit); - left = i; - } - else - { - if (i < right) DepthLimitedQuickSort(i, right, depthLimit); - right = j; - } - } while (left < right); } private void IntrospectiveSort(int left, int length) @@ -2530,7 +2321,7 @@ namespace System { private int _endIndex; // cache array length, since it's a little slow. internal SZArrayEnumerator(Array array) { - Contract.Assert(array.Rank == 1 && array.GetLowerBound(0) == 0, "SZArrayEnumerator only works on single dimension arrays w/ a lower bound of zero."); + Debug.Assert(array.Rank == 1 && array.GetLowerBound(0) == 0, "SZArrayEnumerator only works on single dimension arrays w/ a lower bound of zero."); _array = array; _index = -1; _endIndex = array.Length; @@ -2551,8 +2342,8 @@ namespace System { public Object Current { get { - if (_index < 0) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumNotStarted); - if (_index >= _endIndex) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumEnded); + if (_index < 0) ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumNotStarted(); + if (_index >= _endIndex) ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumEnded(); return _array.GetValue(_index); } } @@ -2629,8 +2420,8 @@ namespace System { public Object Current { get { - if (index < startIndex) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumNotStarted); - if (_complete) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumEnded); + if (index < startIndex) ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumNotStarted(); + if (_complete) ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumEnded(); return array.GetValue(_indices); } } @@ -2652,7 +2443,6 @@ namespace System { // if this is an array of value classes and that value class has a default constructor // then this calls this default constructor on every element in the value class array. // otherwise this is a no-op. Generally this method is called automatically by the compiler - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern void Initialize(); } @@ -2689,13 +2479,12 @@ namespace System { sealed class SZArrayHelper { // It is never legal to instantiate this class. private SZArrayHelper() { - Contract.Assert(false, "Hey! How'd I get here?"); + Debug.Assert(false, "Hey! How'd I get here?"); } // ----------------------------------------------------------- // ------- Implement IEnumerable interface methods -------- // ----------------------------------------------------------- - [SecuritySafeCritical] internal IEnumerator GetEnumerator() { //! Warning: "this" is an array, not an SZArrayHelper. See comments above //! or you may introduce a security hole! @@ -2707,7 +2496,6 @@ namespace System { // ----------------------------------------------------------- // ------- Implement ICollection interface methods -------- // ----------------------------------------------------------- - [SecuritySafeCritical] void CopyTo(T[] array, int index) { //! Warning: "this" is an array, not an SZArrayHelper. See comments above //! or you may introduce a security hole! @@ -2716,7 +2504,6 @@ namespace System { Array.Copy(_this, 0, array, index, _this.Length); } - [SecuritySafeCritical] internal int get_Count() { //! Warning: "this" is an array, not an SZArrayHelper. See comments above //! or you may introduce a security hole! @@ -2727,7 +2514,6 @@ namespace System { // ----------------------------------------------------------- // ---------- Implement IList interface methods ----------- // ----------------------------------------------------------- - [SecuritySafeCritical] internal T get_Item(int index) { //! Warning: "this" is an array, not an SZArrayHelper. See comments above //! or you may introduce a security hole! @@ -2739,7 +2525,6 @@ namespace System { return _this[index]; } - [SecuritySafeCritical] internal void set_Item(int index, T value) { //! Warning: "this" is an array, not an SZArrayHelper. See comments above //! or you may introduce a security hole! @@ -2756,12 +2541,11 @@ namespace System { ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection); } - [SecuritySafeCritical] bool Contains(T value) { //! Warning: "this" is an array, not an SZArrayHelper. See comments above //! or you may introduce a security hole! T[] _this = JitHelpers.UnsafeCast(this); - return Array.IndexOf(_this, value) != -1; + return Array.IndexOf(_this, value, 0, _this.Length) >= 0; } bool get_IsReadOnly() { @@ -2775,12 +2559,11 @@ namespace System { ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); } - [SecuritySafeCritical] int IndexOf(T value) { //! Warning: "this" is an array, not an SZArrayHelper. See comments above //! or you may introduce a security hole! T[] _this = JitHelpers.UnsafeCast(this); - return Array.IndexOf(_this, value); + return Array.IndexOf(_this, value, 0, _this.Length); } void Insert(int index, T value) { @@ -2812,7 +2595,7 @@ namespace System { internal SZGenericArrayEnumerator(T[] array, int endIndex) { // We allow passing null array in case of empty enumerator. - Contract.Assert(array != null || endIndex == -1, "endIndex should be -1 in the case of a null array (for the empty enumerator)."); + Debug.Assert(array != null || endIndex == -1, "endIndex should be -1 in the case of a null array (for the empty enumerator)."); _array = array; _index = -1; _endIndex = endIndex; @@ -2828,8 +2611,8 @@ namespace System { public T Current { get { - if (_index < 0) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumNotStarted); - if (_index >= _endIndex) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumEnded); + if (_index < 0) ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumNotStarted(); + if (_index >= _endIndex) ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumEnded(); return _array[_index]; } } diff --git a/src/mscorlib/src/System/ArraySegment.cs b/src/mscorlib/src/System/ArraySegment.cs index bc39c24..b767e7b 100644 --- a/src/mscorlib/src/System/ArraySegment.cs +++ b/src/mscorlib/src/System/ArraySegment.cs @@ -16,6 +16,7 @@ using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; +using System.Diagnostics; using System.Diagnostics.Contracts; namespace System @@ -28,10 +29,10 @@ namespace System [Serializable] public struct ArraySegment : IList, IReadOnlyList { - private T[] _array; - private int _offset; - private int _count; - + private readonly T[] _array; + private readonly int _offset; + private readonly int _count; + public ArraySegment(T[] array) { if (array == null) @@ -64,10 +65,10 @@ namespace System { get { - Contract.Assert( (null == _array && 0 == _offset && 0 == _count) + Debug.Assert( (null == _array && 0 == _offset && 0 == _count) || (null != _array && _offset >= 0 && _count >= 0 && _offset + _count <= _array.Length), "ArraySegment is invalid"); - + return _array; } } @@ -83,7 +84,7 @@ namespace System // after reading each field out of an ArraySegment into their stack. Contract.Ensures(Contract.Result() >= 0); - Contract.Assert( (null == _array && 0 == _offset && 0 == _count) + Debug.Assert( (null == _array && 0 == _offset && 0 == _count) || (null != _array && _offset >= 0 && _count >= 0 && _offset + _count <= _array.Length), "ArraySegment is invalid"); @@ -102,19 +103,38 @@ namespace System // after reading each field out of an ArraySegment into their stack. Contract.Ensures(Contract.Result() >= 0); - Contract.Assert( (null == _array && 0 == _offset && 0 == _count) + Debug.Assert( (null == _array && 0 == _offset && 0 == _count) || (null != _array && _offset >= 0 && _count >= 0 && _offset + _count <= _array.Length), "ArraySegment is invalid"); return _count; } } - + + public Enumerator GetEnumerator() + { + if (_array == null) + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray); + Contract.EndContractBlock(); + + return new Enumerator(this); + } + public override int GetHashCode() { - return null == _array - ? 0 - : _array.GetHashCode() ^ _offset ^ _count; + if (_array == null) + { + return 0; + } + + int hash = 5381; + hash = System.Numerics.Hashing.HashHelpers.Combine(hash, _offset); + hash = System.Numerics.Hashing.HashHelpers.Combine(hash, _count); + + // The array hash is expected to be an evenly-distributed mixture of bits, + // so rather than adding the cost of another rotation we just xor it. + hash ^= _array.GetHashCode(); + return hash; } public override bool Equals(Object obj) @@ -174,7 +194,7 @@ namespace System int index = System.Array.IndexOf(_array, item, _offset, _count); - Contract.Assert(index == -1 || + Debug.Assert(index == -1 || (index >= _offset && index < _offset + _count)); return index >= 0 ? index - _offset : -1; @@ -236,7 +256,7 @@ namespace System int index = System.Array.IndexOf(_array, item, _offset, _count); - Contract.Assert(index == -1 || + Debug.Assert(index == -1 || (index >= _offset && index < _offset + _count)); return index >= 0; @@ -259,46 +279,34 @@ namespace System #endregion #region IEnumerable - IEnumerator IEnumerable.GetEnumerator() - { - if (_array == null) - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray); - Contract.EndContractBlock(); - return new ArraySegmentEnumerator(this); - } + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); #endregion #region IEnumerable - IEnumerator IEnumerable.GetEnumerator() - { - if (_array == null) - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray); - Contract.EndContractBlock(); - return new ArraySegmentEnumerator(this); - } + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); #endregion [Serializable] - private sealed class ArraySegmentEnumerator : IEnumerator + public struct Enumerator : IEnumerator { - private T[] _array; - private int _start; - private int _end; + private readonly T[] _array; + private readonly int _start; + private readonly int _end; // cache Offset + Count, since it's a little slow private int _current; - internal ArraySegmentEnumerator(ArraySegment arraySegment) + internal Enumerator(ArraySegment arraySegment) { Contract.Requires(arraySegment.Array != null); Contract.Requires(arraySegment.Offset >= 0); Contract.Requires(arraySegment.Count >= 0); Contract.Requires(arraySegment.Offset + arraySegment.Count <= arraySegment.Array.Length); - _array = arraySegment._array; - _start = arraySegment._offset; - _end = _start + arraySegment._count; - _current = _start - 1; + _array = arraySegment.Array; + _start = arraySegment.Offset; + _end = arraySegment.Offset + arraySegment.Count; + _current = arraySegment.Offset - 1; } public bool MoveNext() @@ -315,19 +323,15 @@ namespace System { get { - if (_current < _start) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumNotStarted); - if (_current >= _end) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumEnded); + if (_current < _start) + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumNotStarted(); + if (_current >= _end) + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumEnded(); return _array[_current]; } } - object IEnumerator.Current - { - get - { - return Current; - } - } + object IEnumerator.Current => Current; void IEnumerator.Reset() { diff --git a/src/mscorlib/src/System/Attribute.cs b/src/mscorlib/src/System/Attribute.cs index 6475d8d..e77450e 100644 --- a/src/mscorlib/src/System/Attribute.cs +++ b/src/mscorlib/src/System/Attribute.cs @@ -10,6 +10,7 @@ namespace System { using System.Collections.Generic; using System.Runtime.InteropServices; using System.Globalization; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Security; using System.Security.Permissions; @@ -436,7 +437,6 @@ namespace System { Environment.GetResourceString("Format_AttributeUsage", type)); } - [System.Security.SecuritySafeCritical] private static Attribute[] CreateAttributeArrayHelper(Type elementType, int elementCount) { return (Attribute[])Array.UnsafeCreateInstance(elementType, elementCount); @@ -456,10 +456,10 @@ namespace System { public static Attribute[] GetCustomAttributes(MemberInfo element, Type type, bool inherit) { if (element == null) - throw new ArgumentNullException("element"); + throw new ArgumentNullException(nameof(element)); if (type == null) - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); if (!type.IsSubclassOf(typeof(Attribute)) && type != typeof(Attribute)) throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass")); @@ -486,7 +486,7 @@ namespace System { public static Attribute[] GetCustomAttributes(MemberInfo element, bool inherit) { if (element == null) - throw new ArgumentNullException("element"); + throw new ArgumentNullException(nameof(element)); Contract.EndContractBlock(); switch (element.MemberType) @@ -511,10 +511,10 @@ namespace System { { // Returns true if a custom attribute subclass of attributeType class/interface with inheritance walk if (element == null) - throw new ArgumentNullException("element"); + throw new ArgumentNullException(nameof(element)); if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute)) throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass")); @@ -568,16 +568,16 @@ namespace System { public static Attribute[] GetCustomAttributes(ParameterInfo element, Type attributeType, bool inherit) { if (element == null) - throw new ArgumentNullException("element"); + throw new ArgumentNullException(nameof(element)); if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute)) throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass")); if (element.Member == null) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidParameterInfo"), "element"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidParameterInfo"), nameof(element)); Contract.EndContractBlock(); @@ -591,10 +591,10 @@ namespace System { public static Attribute[] GetCustomAttributes(ParameterInfo element, bool inherit) { if (element == null) - throw new ArgumentNullException("element"); + throw new ArgumentNullException(nameof(element)); if (element.Member == null) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidParameterInfo"), "element"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidParameterInfo"), nameof(element)); Contract.EndContractBlock(); @@ -614,10 +614,10 @@ namespace System { { // Returns true is a custom attribute subclass of attributeType class/interface with inheritance walk if (element == null) - throw new ArgumentNullException("element"); + throw new ArgumentNullException(nameof(element)); if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute)) throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass")); @@ -637,7 +637,7 @@ namespace System { return element.IsDefined(attributeType, false); default: - Contract.Assert(false, "Invalid type for ParameterInfo member in Attribute class"); + Debug.Assert(false, "Invalid type for ParameterInfo member in Attribute class"); throw new ArgumentException(Environment.GetResourceString("Argument_InvalidParamInfo")); } } @@ -681,7 +681,7 @@ namespace System { public static Attribute[] GetCustomAttributes(Module element, bool inherit) { if (element == null) - throw new ArgumentNullException("element"); + throw new ArgumentNullException(nameof(element)); Contract.EndContractBlock(); return (Attribute[])element.GetCustomAttributes(typeof(Attribute), inherit); @@ -690,10 +690,10 @@ namespace System { public static Attribute[] GetCustomAttributes(Module element, Type attributeType, bool inherit) { if (element == null) - throw new ArgumentNullException("element"); + throw new ArgumentNullException(nameof(element)); if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute)) throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass")); @@ -711,10 +711,10 @@ namespace System { { // Returns true is a custom attribute subclass of attributeType class/interface with no inheritance walk if (element == null) - throw new ArgumentNullException("element"); + throw new ArgumentNullException(nameof(element)); if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute)) throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass")); @@ -754,10 +754,10 @@ namespace System { public static Attribute[] GetCustomAttributes(Assembly element, Type attributeType, bool inherit) { if (element == null) - throw new ArgumentNullException("element"); + throw new ArgumentNullException(nameof(element)); if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute)) throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass")); @@ -774,7 +774,7 @@ namespace System { public static Attribute[] GetCustomAttributes(Assembly element, bool inherit) { if (element == null) - throw new ArgumentNullException("element"); + throw new ArgumentNullException(nameof(element)); Contract.EndContractBlock(); return (Attribute[])element.GetCustomAttributes(typeof(Attribute), inherit); @@ -789,10 +789,10 @@ namespace System { { // Returns true is a custom attribute subclass of attributeType class/interface with no inheritance walk if (element == null) - throw new ArgumentNullException("element"); + throw new ArgumentNullException(nameof(element)); if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute)) throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass")); @@ -830,14 +830,13 @@ namespace System { #endregion #region Object Overrides - [SecuritySafeCritical] public override bool Equals(Object obj) { if (obj == null) return false; - RuntimeType thisType = (RuntimeType)this.GetType(); - RuntimeType thatType = (RuntimeType)obj.GetType(); + Type thisType = this.GetType(); + Type thatType = obj.GetType(); if (thatType != thisType) return false; @@ -845,18 +844,22 @@ namespace System { Object thisObj = this; Object thisResult, thatResult; - FieldInfo[] thisFields = thisType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - - for (int i = 0; i < thisFields.Length; i++) + while (thisType != typeof(Attribute)) { - // Visibility check and consistency check are not necessary. - thisResult = ((RtFieldInfo)thisFields[i]).UnsafeGetValue(thisObj); - thatResult = ((RtFieldInfo)thisFields[i]).UnsafeGetValue(obj); + FieldInfo[] thisFields = thisType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); - if (!AreFieldValuesEqual(thisResult, thatResult)) + for (int i = 0; i < thisFields.Length; i++) { - return false; + // Visibility check and consistency check are not necessary. + thisResult = ((RtFieldInfo)thisFields[i]).UnsafeGetValue(thisObj); + thatResult = ((RtFieldInfo)thisFields[i]).UnsafeGetValue(obj); + + if (!AreFieldValuesEqual(thisResult, thatResult)) + { + return false; + } } + thisType = thisType.BaseType; } return true; @@ -887,7 +890,7 @@ namespace System { // Attributes can only contain single-dimension arrays, so we don't need to worry about // multidimensional arrays. - Contract.Assert(thisValueArray.Rank == 1 && thatValueArray.Rank == 1); + Debug.Assert(thisValueArray.Rank == 1 && thatValueArray.Rank == 1); for (int j = 0; j < thisValueArray.Length; j++) { if (!AreFieldValuesEqual(thisValueArray.GetValue(j), thatValueArray.GetValue(j))) @@ -901,7 +904,7 @@ namespace System { // An object of type Attribute will cause a stack overflow. // However, this should never happen because custom attributes cannot contain values other than // constants, single-dimensional arrays and typeof expressions. - Contract.Assert(!(thisValue is Attribute)); + Debug.Assert(!(thisValue is Attribute)); if (!thisValue.Equals(thatValue)) return false; } @@ -909,32 +912,36 @@ namespace System { return true; } - [SecuritySafeCritical] public override int GetHashCode() { Type type = GetType(); - FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - Object vThis = null; - - for (int i = 0; i < fields.Length; i++) + while (type != typeof(Attribute)) { - // Visibility check and consistency check are not necessary. - Object fieldValue = ((RtFieldInfo)fields[i]).UnsafeGetValue(this); + FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); + Object vThis = null; - // The hashcode of an array ignores the contents of the array, so it can produce - // different hashcodes for arrays with the same contents. - // Since we do deep comparisons of arrays in Equals(), this means Equals and GetHashCode will - // be inconsistent for arrays. Therefore, we ignore hashes of arrays. - if (fieldValue != null && !fieldValue.GetType().IsArray) - vThis = fieldValue; + for (int i = 0; i < fields.Length; i++) + { + // Visibility check and consistency check are not necessary. + Object fieldValue = ((RtFieldInfo)fields[i]).UnsafeGetValue(this); + + // The hashcode of an array ignores the contents of the array, so it can produce + // different hashcodes for arrays with the same contents. + // Since we do deep comparisons of arrays in Equals(), this means Equals and GetHashCode will + // be inconsistent for arrays. Therefore, we ignore hashes of arrays. + if (fieldValue != null && !fieldValue.GetType().IsArray) + vThis = fieldValue; + + if (vThis != null) + break; + } if (vThis != null) - break; - } + return vThis.GetHashCode(); - if (vThis != null) - return vThis.GetHashCode(); + type = type.BaseType; + } return type.GetHashCode(); } @@ -949,27 +956,5 @@ namespace System { #region Public Members public virtual bool IsDefaultAttribute() { return false; } #endregion - -#if !FEATURE_CORECLR - void _Attribute.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _Attribute.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _Attribute.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - void _Attribute.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif } } diff --git a/src/mscorlib/src/System/BCLDebug.cs b/src/mscorlib/src/System/BCLDebug.cs index 9b2ade2..0ca6e61 100644 --- a/src/mscorlib/src/System/BCLDebug.cs +++ b/src/mscorlib/src/System/BCLDebug.cs @@ -119,7 +119,6 @@ namespace System { [Pure] [Conditional("_LOGGING")] - [SecuritySafeCritical] static public void Log(String message) { if (AppDomain.CurrentDomain.IsUnloadingForcedFinalize()) return; @@ -132,7 +131,6 @@ namespace System { [Pure] [Conditional("_LOGGING")] - [SecuritySafeCritical] static public void Log(String switchName, String message) { if (AppDomain.CurrentDomain.IsUnloadingForcedFinalize()) return; @@ -160,7 +158,6 @@ namespace System { [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static int GetRegistryLoggingValues(out bool loggingEnabled, out bool logToConsole, out int logLevel, out bool perfWarnings, out bool correctnessWarnings, out bool safeHandleStackTraces); - [SecuritySafeCritical] private static void CheckRegistry() { if (AppDomain.CurrentDomain.IsUnloadingForcedFinalize()) return; @@ -207,7 +204,6 @@ namespace System { } } - [SecuritySafeCritical] internal static bool CheckEnabled(String switchName) { if (AppDomain.CurrentDomain.IsUnloadingForcedFinalize()) return false; @@ -220,7 +216,6 @@ namespace System { return ((int)logSwitch.MinimumLevel<=(int)LogLevel.Trace); } - [SecuritySafeCritical] private static bool CheckEnabled(String switchName, LogLevel level, out LogSwitch logSwitch) { if (AppDomain.CurrentDomain.IsUnloadingForcedFinalize()) { @@ -236,7 +231,6 @@ namespace System { [Pure] [Conditional("_LOGGING")] - [SecuritySafeCritical] public static void Log(String switchName, LogLevel level, params Object[]messages) { if (AppDomain.CurrentDomain.IsUnloadingForcedFinalize()) return; @@ -338,33 +332,9 @@ namespace System { System.Diagnostics.Log.LogMessage(LoggingLevels.TraceLevel0, logSwitch, trace.ToString()); } - // For logging errors related to the console - we often can't expect to - // write to stdout if it doesn't exist. - [SecuritySafeCritical] - [Conditional("_DEBUG")] - internal static void ConsoleError(String msg) - { - if (AppDomain.CurrentDomain.IsUnloadingForcedFinalize()) - return; - - if (m_MakeConsoleErrorLoggingWork == null) { - PermissionSet perms = new PermissionSet(); - perms.AddPermission(new EnvironmentPermission(PermissionState.Unrestricted)); - perms.AddPermission(new FileIOPermission(FileIOPermissionAccess.AllAccess, Path.GetFullPath("."))); - m_MakeConsoleErrorLoggingWork = perms; - } - m_MakeConsoleErrorLoggingWork.Assert(); - - using (TextWriter err = File.AppendText("ConsoleErrors.log")) - { - err.WriteLine(msg); - } - } - // For perf-related asserts. On a debug build, set the registry key // BCLPerfWarnings to non-zero. [Conditional("_DEBUG")] - [SecuritySafeCritical] internal static void Perf(bool expr, String msg) { if (AppDomain.CurrentDomain.IsUnloadingForcedFinalize()) @@ -384,7 +354,6 @@ namespace System { // BCLCorrectnessWarnings to non-zero. [Conditional("_DEBUG")] #if _DEBUG - [SecuritySafeCritical] #endif internal static void Correctness(bool expr, String msg) { @@ -409,7 +378,6 @@ namespace System { } #if !BIT64 // 32 - [SecuritySafeCritical] #endif internal static bool CorrectnessEnabled() { diff --git a/src/mscorlib/src/System/BadImageFormatException.cs b/src/mscorlib/src/System/BadImageFormatException.cs index b71fcc3..3f3f4a5 100644 --- a/src/mscorlib/src/System/BadImageFormatException.cs +++ b/src/mscorlib/src/System/BadImageFormatException.cs @@ -132,14 +132,11 @@ namespace System { } public String FusionLog { - [System.Security.SecuritySafeCritical] // auto-generated #pragma warning disable CS0618 // Type or member is obsolete - [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] #pragma warning restore CS0618 // Type or member is obsolete get { return _fusionLog; } } - [System.Security.SecurityCritical] // auto-generated_required public override void GetObjectData(SerializationInfo info, StreamingContext context) { // Serialize data for our base classes. base will verify info != null. base.GetObjectData(info, context); diff --git a/src/mscorlib/src/System/BitConverter.cs b/src/mscorlib/src/System/BitConverter.cs index e4bb9dd..3a6d1c0 100644 --- a/src/mscorlib/src/System/BitConverter.cs +++ b/src/mscorlib/src/System/BitConverter.cs @@ -15,6 +15,7 @@ namespace System { using System; using System.Runtime.CompilerServices; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Security; @@ -56,7 +57,6 @@ namespace System { // Converts a short into an array of bytes with length // two. - [System.Security.SecuritySafeCritical] // auto-generated public unsafe static byte[] GetBytes(short value) { Contract.Ensures(Contract.Result() != null); @@ -70,7 +70,6 @@ namespace System { // Converts an int into an array of bytes with length // four. - [System.Security.SecuritySafeCritical] // auto-generated public unsafe static byte[] GetBytes(int value) { Contract.Ensures(Contract.Result() != null); @@ -84,7 +83,6 @@ namespace System { // Converts a long into an array of bytes with length // eight. - [System.Security.SecuritySafeCritical] // auto-generated public unsafe static byte[] GetBytes(long value) { Contract.Ensures(Contract.Result() != null); @@ -128,7 +126,6 @@ namespace System { // Converts a float into an array of bytes with length // four. - [System.Security.SecuritySafeCritical] // auto-generated public unsafe static byte[] GetBytes(float value) { Contract.Ensures(Contract.Result() != null); @@ -139,7 +136,6 @@ namespace System { // Converts a double into an array of bytes with length // eight. - [System.Security.SecuritySafeCritical] // auto-generated public unsafe static byte[] GetBytes(double value) { Contract.Ensures(Contract.Result() != null); @@ -156,7 +152,7 @@ namespace System { } if ((uint)startIndex >= value.Length) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); } if (startIndex > value.Length - 2) { @@ -168,14 +164,13 @@ namespace System { } // Converts an array of bytes into a short. - [System.Security.SecuritySafeCritical] // auto-generated public static unsafe short ToInt16(byte[] value, int startIndex) { if( value == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value); } if ((uint) startIndex >= value.Length) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); } if (startIndex > value.Length -2) { @@ -200,14 +195,13 @@ namespace System { } // Converts an array of bytes into an int. - [System.Security.SecuritySafeCritical] // auto-generated public static unsafe int ToInt32 (byte[] value, int startIndex) { if( value == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value); } if ((uint) startIndex >= value.Length) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); } if (startIndex > value.Length -4) { @@ -231,14 +225,13 @@ namespace System { } // Converts an array of bytes into a long. - [System.Security.SecuritySafeCritical] // auto-generated public static unsafe long ToInt64 (byte[] value, int startIndex) { if (value == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value); } if ((uint) startIndex >= value.Length) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); } if (startIndex > value.Length -8) { @@ -274,7 +267,7 @@ namespace System { if (value == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value); if ((uint)startIndex >= value.Length) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); if (startIndex > value.Length - 2) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); Contract.EndContractBlock(); @@ -290,7 +283,7 @@ namespace System { if (value == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value); if ((uint)startIndex >= value.Length) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); if (startIndex > value.Length - 4) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); Contract.EndContractBlock(); @@ -306,7 +299,7 @@ namespace System { if (value == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value); if ((uint)startIndex >= value.Length) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); if (startIndex > value.Length - 8) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); Contract.EndContractBlock(); @@ -315,13 +308,12 @@ namespace System { } // Converts an array of bytes into a float. - [System.Security.SecuritySafeCritical] // auto-generated unsafe public static float ToSingle (byte[] value, int startIndex) { if (value == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value); if ((uint)startIndex >= value.Length) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); if (startIndex > value.Length - 4) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); Contract.EndContractBlock(); @@ -331,13 +323,12 @@ namespace System { } // Converts an array of bytes into a double. - [System.Security.SecuritySafeCritical] // auto-generated unsafe public static double ToDouble (byte[] value, int startIndex) { if (value == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value); if ((uint)startIndex >= value.Length) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); if (startIndex > value.Length - 8) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); Contract.EndContractBlock(); @@ -347,7 +338,7 @@ namespace System { } private static char GetHexValue(int i) { - Contract.Assert( i >=0 && i <16, "i is out of range."); + Debug.Assert( i >=0 && i <16, "i is out of range."); if (i<10) { return (char)(i + '0'); } @@ -358,15 +349,15 @@ namespace System { // Converts an array of bytes into a String. public static String ToString (byte[] value, int startIndex, int length) { if (value == null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } if (startIndex < 0 || startIndex >= value.Length && startIndex > 0) { // Don't throw for a 0 length array. - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); } if (length < 0) { - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); } if (startIndex > value.Length - length) { @@ -380,7 +371,7 @@ namespace System { if (length > (Int32.MaxValue / 3)) { // (Int32.MaxValue / 3) == 715,827,882 Bytes == 699 MB - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_LengthTooLarge", (Int32.MaxValue / 3))); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_LengthTooLarge", (Int32.MaxValue / 3))); } int chArrayLength = length * 3; @@ -402,7 +393,7 @@ namespace System { // Converts an array of bytes into a String. public static String ToString(byte [] value) { if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); return ToString(value, 0, value.Length); @@ -411,7 +402,7 @@ namespace System { // Converts an array of bytes into a String. public static String ToString (byte [] value, int startIndex) { if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); return ToString(value, startIndex, value.Length - startIndex); @@ -428,24 +419,30 @@ namespace System { // Converts an array of bytes into a boolean. public static bool ToBoolean(byte[] value, int startIndex) { if (value==null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); if (startIndex < 0) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (startIndex > value.Length - 1) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.EndContractBlock(); return (value[startIndex]==0)?false:true; } - [SecuritySafeCritical] public static unsafe long DoubleToInt64Bits(double value) { return *((long *)&value); } - [SecuritySafeCritical] public static unsafe double Int64BitsToDouble(long value) { return *((double*)&value); - } + } + + public static unsafe int SingleToInt32Bits(float value) { + return *((int*)&value); + } + + public static unsafe float Int32BitsToSingle(int value) { + return *((float*)&value); + } } } diff --git a/src/mscorlib/src/System/Boolean.cs b/src/mscorlib/src/System/Boolean.cs index c5cd45a..9aaec9a 100644 --- a/src/mscorlib/src/System/Boolean.cs +++ b/src/mscorlib/src/System/Boolean.cs @@ -151,7 +151,7 @@ namespace System { // Determines whether a String represents true or false. // public static Boolean Parse (String value) { - if (value==null) throw new ArgumentNullException("value"); + if (value==null) throw new ArgumentNullException(nameof(value)); Contract.EndContractBlock(); Boolean result = false; if (!TryParse(value, out result)) { diff --git a/src/mscorlib/src/System/Buffer.cs b/src/mscorlib/src/System/Buffer.cs index ea647f1..eee2a81 100644 --- a/src/mscorlib/src/System/Buffer.cs +++ b/src/mscorlib/src/System/Buffer.cs @@ -11,6 +11,7 @@ namespace System { using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Security; using System.Runtime; @@ -28,7 +29,6 @@ namespace System { // respecting types. This calls memmove internally. The count and // offset parameters here are in bytes. If you want to use traditional // array element indices and counts, use Array.Copy. - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern void BlockCopy(Array src, int srcOffset, Array dst, int dstOffset, int count); @@ -37,7 +37,6 @@ namespace System { // parameter validation has already been done. The count and offset // parameters here are in bytes. If you want to use traditional // array element indices and counts, use Array.Copy. - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void InternalBlockCopy(Array src, int srcOffsetBytes, Array dst, int dstOffsetBytes, int byteCount); @@ -47,10 +46,9 @@ namespace System { // It is however cross platform as the CRT hasn't ported their fast version to 64-bit // platforms. // - [System.Security.SecurityCritical] // auto-generated internal unsafe static int IndexOfByte(byte* src, byte value, int index, int count) { - Contract.Assert(src != null, "src should not be null"); + Debug.Assert(src != null, "src should not be null"); byte* pByte = src + index; @@ -122,7 +120,6 @@ namespace System { // Returns a bool to indicate if the array is of primitive data types // or not. - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool IsPrimitiveTypeArray(Array array); @@ -132,24 +129,22 @@ namespace System { // This essentially does the following: // return ((byte*)array) + index. // - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern byte _GetByte(Array array, int index); - [System.Security.SecuritySafeCritical] // auto-generated public static byte GetByte(Array array, int index) { // Is the array present? if (array == null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); // Is it of primitive types? if (!IsPrimitiveTypeArray(array)) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBePrimArray"), "array"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBePrimArray"), nameof(array)); // Is the index in valid range of the array? if (index < 0 || index >= _ByteLength(array)) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); return _GetByte(array, index); } @@ -160,24 +155,22 @@ namespace System { // This essentially does the following: // *(((byte*)array) + index) = value. // - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void _SetByte(Array array, int index, byte value); - [System.Security.SecuritySafeCritical] // auto-generated public static void SetByte(Array array, int index, byte value) { // Is the array present? if (array == null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); // Is it of primitive types? if (!IsPrimitiveTypeArray(array)) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBePrimArray"), "array"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBePrimArray"), nameof(array)); // Is the index in valid range of the array? if (index < 0 || index >= _ByteLength(array)) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); // Make the FCall to do the work _SetByte(array, index, value); @@ -190,36 +183,32 @@ namespace System { // This essentially does the following: // return array.length * sizeof(array.UnderlyingElementType). // - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern int _ByteLength(Array array); - [System.Security.SecuritySafeCritical] // auto-generated public static int ByteLength(Array array) { // Is the array present? if (array == null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); // Is it of primitive types? if (!IsPrimitiveTypeArray(array)) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBePrimArray"), "array"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBePrimArray"), nameof(array)); return _ByteLength(array); } - [System.Security.SecurityCritical] // auto-generated internal unsafe static void ZeroMemory(byte* src, long len) { while(len-- > 0) *(src + len) = 0; } - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal unsafe static void Memcpy(byte[] dest, int destIndex, byte* src, int srcIndex, int len) { - Contract.Assert( (srcIndex >= 0) && (destIndex >= 0) && (len >= 0), "Index and length must be non-negative!"); - Contract.Assert(dest.Length - destIndex >= len, "not enough bytes in dest"); + Debug.Assert( (srcIndex >= 0) && (destIndex >= 0) && (len >= 0), "Index and length must be non-negative!"); + Debug.Assert(dest.Length - destIndex >= len, "not enough bytes in dest"); // If dest has 0 elements, the fixed statement will throw an // IndexOutOfRangeException. Special-case 0-byte copies. if (len==0) @@ -229,12 +218,11 @@ namespace System { } } - [SecurityCritical] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal unsafe static void Memcpy(byte* pDest, int destIndex, byte[] src, int srcIndex, int len) { - Contract.Assert( (srcIndex >= 0) && (destIndex >= 0) && (len >= 0), "Index and length must be non-negative!"); - Contract.Assert(src.Length - srcIndex >= len, "not enough bytes in src"); + Debug.Assert( (srcIndex >= 0) && (destIndex >= 0) && (len >= 0), "Index and length must be non-negative!"); + Debug.Assert(src.Length - srcIndex >= len, "not enough bytes in src"); // If dest has 0 elements, the fixed statement will throw an // IndexOutOfRangeException. Special-case 0-byte copies. if (len==0) @@ -254,7 +242,6 @@ namespace System { // 1. This method is given access to other internal dlls and this close to release we do not want to change it. // 2. It is difficult to get this right for arm and again due to release dates we would like to visit it later. [FriendAccessAllowed] - [System.Security.SecurityCritical] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] #if ARM [MethodImplAttribute(MethodImplOptions.InternalCall)] @@ -262,13 +249,12 @@ namespace System { #else // ARM [MethodImplAttribute(MethodImplOptions.AggressiveInlining)] internal unsafe static void Memcpy(byte* dest, byte* src, int len) { - Contract.Assert(len >= 0, "Negative length in memcopy!"); + Debug.Assert(len >= 0, "Negative length in memcopy!"); Memmove(dest, src, (uint)len); } #endif // ARM // This method has different signature for x64 and other platforms and is done for performance reasons. - [System.Security.SecurityCritical] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal unsafe static void Memmove(byte* dest, byte* src, nuint len) { @@ -524,7 +510,7 @@ namespace System { // We know due to the above switch-case that this loop will always run 1 iteration; max // bytes we copy before checking is 23 (7 to align the pointers, 16 for 1 iteration) so // the switch handles lengths 0-22. - Contract.Assert(end >= 7 && i <= end); + Debug.Assert(end >= 7 && i <= end); // This is separated out into a different variable, so the i + 16 addition can be // performed at the start of the pipeline and the loop condition does not have @@ -595,7 +581,6 @@ namespace System { // Non-inlinable wrapper around the QCall that avoids poluting the fast path // with P/Invoke prolog/epilog. - [SecurityCritical] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [MethodImplAttribute(MethodImplOptions.NoInlining)] private unsafe static void _Memmove(byte* dest, byte* src, nuint len) @@ -605,13 +590,11 @@ namespace System { [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] - [SecurityCritical] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] extern private unsafe static void __Memmove(byte* dest, byte* src, nuint len); // The attributes on this method are chosen for best JIT performance. // Please do not edit unless intentional. - [System.Security.SecurityCritical] [MethodImplAttribute(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static unsafe void MemoryCopy(void* source, void* destination, long destinationSizeInBytes, long sourceBytesToCopy) @@ -626,7 +609,6 @@ namespace System { // The attributes on this method are chosen for best JIT performance. // Please do not edit unless intentional. - [System.Security.SecurityCritical] [MethodImplAttribute(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static unsafe void MemoryCopy(void* source, void* destination, ulong destinationSizeInBytes, ulong sourceBytesToCopy) diff --git a/src/mscorlib/src/System/ByReference.cs b/src/mscorlib/src/System/ByReference.cs new file mode 100644 index 0000000..6f8bb22 --- /dev/null +++ b/src/mscorlib/src/System/ByReference.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. +// See the LICENSE file in the project root for more information. + +using System.Runtime.CompilerServices; + +namespace System +{ + // ByReference is meant to be used to represent "ref T" fields. It is working + // around lack of first class support for byref fields in C# and IL. The JIT and + // type loader has special handling for it that turns it into a thin wrapper around ref T. + internal struct ByReference + { + private IntPtr _value; + + public ByReference(ref T value) + { + // TODO-SPAN: This has GC hole. It needs to be JIT intrinsic instead + unsafe { _value = (IntPtr)Unsafe.AsPointer(ref value); } + } + + public ref T Value + { + get + { + // TODO-SPAN: This has GC hole. It needs to be JIT intrinsic instead + unsafe { return ref Unsafe.As(ref *(IntPtr*)_value); } + } + } + } +} diff --git a/src/mscorlib/src/System/Byte.cs b/src/mscorlib/src/System/Byte.cs index 2c24bf6..980412b 100644 --- a/src/mscorlib/src/System/Byte.cs +++ b/src/mscorlib/src/System/Byte.cs @@ -139,28 +139,24 @@ namespace System { } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated public override String ToString() { Contract.Ensures(Contract.Result() != null); return Number.FormatInt32(m_value, null, NumberFormatInfo.CurrentInfo); } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(String format) { Contract.Ensures(Contract.Result() != null); return Number.FormatInt32(m_value, format, NumberFormatInfo.CurrentInfo); } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(IFormatProvider provider) { Contract.Ensures(Contract.Result() != null); return Number.FormatInt32(m_value, null, NumberFormatInfo.GetInstance(provider)); } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(String format, IFormatProvider provider) { Contract.Ensures(Contract.Result() != null); return Number.FormatInt32(m_value, format, NumberFormatInfo.GetInstance(provider)); diff --git a/src/mscorlib/src/System/CLRConfig.cs b/src/mscorlib/src/System/CLRConfig.cs index 0831c4b..01ad7c3 100644 --- a/src/mscorlib/src/System/CLRConfig.cs +++ b/src/mscorlib/src/System/CLRConfig.cs @@ -19,12 +19,10 @@ namespace System { internal class CLRConfig { [FriendAccessAllowed] - [System.Security.SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] [SuppressUnmanagedCodeSecurity] internal static extern bool CheckLegacyManagedDeflateStream(); - [System.Security.SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] [SuppressUnmanagedCodeSecurity] internal static extern bool CheckThrowUnobservedTaskExceptions(); diff --git a/src/mscorlib/src/System/CfgParser.cs b/src/mscorlib/src/System/CfgParser.cs index ef368a9..b21da7f 100644 --- a/src/mscorlib/src/System/CfgParser.cs +++ b/src/mscorlib/src/System/CfgParser.cs @@ -213,7 +213,6 @@ namespace System int textLength, int prefixLength); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern void RunParser(String fileName); } @@ -245,11 +244,10 @@ namespace System return Parse(fileName, configPath, false); } - [System.Security.SecuritySafeCritical] // auto-generated internal ConfigNode Parse(String fileName, String configPath, bool skipSecurityStuff) { if (fileName == null) - throw new ArgumentNullException("fileName"); + throw new ArgumentNullException(nameof(fileName)); Contract.EndContractBlock(); this.fileName = fileName; if (configPath[0] == '/'){ @@ -264,7 +262,7 @@ namespace System } if (!skipSecurityStuff) { - (new FileIOPermission( FileIOPermissionAccess.Read, System.IO.Path.GetFullPathInternal( fileName ) )).Demand(); + (new FileIOPermission(FileIOPermissionAccess.Read, Path.GetFullPath(fileName))).Demand(); } #pragma warning disable 618 (new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)).Assert(); @@ -291,11 +289,7 @@ namespace System // Neither Exception nor ApplicationException are the "right" exceptions here. // Desktop throws ApplicationException for backwards compatibility. // On Silverlight we don't have ApplicationException, so fall back to Exception. -#if FEATURE_CORECLR throw new Exception(message, inner); -#else - throw new ApplicationException(message, inner); -#endif } return rootNode; } @@ -440,11 +434,7 @@ namespace System // Neither Exception nor ApplicationException are the "right" exceptions here. // Desktop throws ApplicationException for backwards compatibility. // On Silverlight we don't have ApplicationException, so fall back to Exception. -#if FEATURE_CORECLR throw new Exception(message); -#else - throw new ApplicationException(message); -#endif } } } diff --git a/src/mscorlib/src/System/Char.cs b/src/mscorlib/src/System/Char.cs index ff936c6..b9c9305 100644 --- a/src/mscorlib/src/System/Char.cs +++ b/src/mscorlib/src/System/Char.cs @@ -18,6 +18,7 @@ namespace System { using System.Runtime; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; + using System.Diagnostics; using System.Diagnostics.Contracts; [System.Runtime.InteropServices.ComVisible(true)] @@ -86,7 +87,7 @@ namespace System { // Return the Unicode category for Unicode character <= 0x00ff. private static UnicodeCategory GetLatin1UnicodeCategory(char ch) { - Contract.Assert(IsLatin1(ch), "Char.GetLatin1UnicodeCategory(): ch should be <= 007f"); + Debug.Assert(IsLatin1(ch), "Char.GetLatin1UnicodeCategory(): ch should be <= 007f"); return (UnicodeCategory)(categoryForLatin1[(int)ch]); } @@ -167,7 +168,7 @@ namespace System { public static char Parse(String s) { if (s==null) { - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); } Contract.EndContractBlock(); @@ -364,7 +365,7 @@ namespace System { // <;<;Not fully implemented>;>; public static char ToUpper(char c, CultureInfo culture) { if (culture==null) - throw new ArgumentNullException("culture"); + throw new ArgumentNullException(nameof(culture)); Contract.EndContractBlock(); return culture.TextInfo.ToUpper(c); } @@ -393,7 +394,7 @@ namespace System { // <;<;Not fully implemented>;>; public static char ToLower(char c, CultureInfo culture) { if (culture==null) - throw new ArgumentNullException("culture"); + throw new ArgumentNullException(nameof(culture)); Contract.EndContractBlock(); return culture.TextInfo.ToLower(c); } @@ -508,9 +509,9 @@ namespace System { public static bool IsControl(String s, int index) { if (s==null) - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); if (((uint)index)>=((uint)s.Length)) { - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); } Contract.EndContractBlock(); char c = s[index]; @@ -524,9 +525,9 @@ namespace System { public static bool IsDigit(String s, int index) { if (s==null) - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); if (((uint)index)>=((uint)s.Length)) { - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); } Contract.EndContractBlock(); char c = s[index]; @@ -539,9 +540,9 @@ namespace System { public static bool IsLetter(String s, int index) { if (s==null) - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); if (((uint)index)>=((uint)s.Length)) { - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); } Contract.EndContractBlock(); char c = s[index]; @@ -558,9 +559,9 @@ namespace System { public static bool IsLetterOrDigit(String s, int index) { if (s==null) - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); if (((uint)index)>=((uint)s.Length)) { - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); } Contract.EndContractBlock(); char c = s[index]; @@ -573,9 +574,9 @@ namespace System { public static bool IsLower(String s, int index) { if (s==null) - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); if (((uint)index)>=((uint)s.Length)) { - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); } Contract.EndContractBlock(); char c = s[index]; @@ -617,9 +618,9 @@ namespace System { public static bool IsNumber(String s, int index) { if (s==null) - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); if (((uint)index)>=((uint)s.Length)) { - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); } Contract.EndContractBlock(); char c = s[index]; @@ -643,9 +644,9 @@ namespace System { public static bool IsPunctuation (String s, int index) { if (s==null) - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); if (((uint)index)>=((uint)s.Length)) { - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); } Contract.EndContractBlock(); char c = s[index]; @@ -688,9 +689,9 @@ namespace System { public static bool IsSeparator(String s, int index) { if (s==null) - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); if (((uint)index)>=((uint)s.Length)) { - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); } Contract.EndContractBlock(); char c = s[index]; @@ -710,10 +711,10 @@ namespace System { public static bool IsSurrogate(String s, int index) { if (s==null) { - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); } if (((uint)index)>=((uint)s.Length)) { - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); } Contract.EndContractBlock(); return (IsSurrogate(s[index])); @@ -745,9 +746,9 @@ namespace System { public static bool IsSymbol(String s, int index) { if (s==null) - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); if (((uint)index)>=((uint)s.Length)) { - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); } Contract.EndContractBlock(); if (IsLatin1(s[index])) { @@ -760,9 +761,9 @@ namespace System { public static bool IsUpper(String s, int index) { if (s==null) - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); if (((uint)index)>=((uint)s.Length)) { - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); } Contract.EndContractBlock(); char c = s[index]; @@ -779,9 +780,9 @@ namespace System { public static bool IsWhiteSpace(String s, int index) { if (s==null) - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); if (((uint)index)>=((uint)s.Length)) { - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); } Contract.EndContractBlock(); @@ -803,9 +804,9 @@ namespace System { public static UnicodeCategory GetUnicodeCategory(String s, int index) { if (s==null) - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); if (((uint)index)>=((uint)s.Length)) { - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); } Contract.EndContractBlock(); if (IsLatin1(s[index])) { @@ -822,9 +823,9 @@ namespace System { public static double GetNumericValue(String s, int index) { if (s==null) - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); if (((uint)index)>=((uint)s.Length)) { - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); } Contract.EndContractBlock(); return CharUnicodeInfo.GetNumericValue(s, index); @@ -842,10 +843,10 @@ namespace System { [Pure] public static bool IsHighSurrogate(String s, int index) { if (s == null) { - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); } if (index < 0 || index >= s.Length) { - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); } Contract.EndContractBlock(); return (IsHighSurrogate(s[index])); @@ -862,10 +863,10 @@ namespace System { [Pure] public static bool IsLowSurrogate(String s, int index) { if (s == null) { - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); } if (index < 0 || index >= s.Length) { - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); } Contract.EndContractBlock(); return (IsLowSurrogate(s[index])); @@ -877,10 +878,10 @@ namespace System { [Pure] public static bool IsSurrogatePair(String s, int index) { if (s == null) { - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); } if (index < 0 || index >= s.Length) { - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); } Contract.EndContractBlock(); if (index + 1 < s.Length) { @@ -911,13 +912,12 @@ namespace System { ** Convert an UTF32 value into a surrogate pair. ==============================================================================*/ - [System.Security.SecuritySafeCritical] public static String ConvertFromUtf32(int utf32) { // For UTF32 values from U+00D800 ~ U+00DFFF, we should throw. They // are considered as irregular code unit sequence, but they are not illegal. if ((utf32 < 0 || utf32 > UNICODE_PLANE16_END) || (utf32 >= HIGH_SURROGATE_START && utf32 <= LOW_SURROGATE_END)) { - throw new ArgumentOutOfRangeException("utf32", Environment.GetResourceString("ArgumentOutOfRange_InvalidUTF32")); + throw new ArgumentOutOfRangeException(nameof(utf32), Environment.GetResourceString("ArgumentOutOfRange_InvalidUTF32")); } Contract.EndContractBlock(); @@ -945,10 +945,10 @@ namespace System { public static int ConvertToUtf32(char highSurrogate, char lowSurrogate) { if (!IsHighSurrogate(highSurrogate)) { - throw new ArgumentOutOfRangeException("highSurrogate", Environment.GetResourceString("ArgumentOutOfRange_InvalidHighSurrogate")); + throw new ArgumentOutOfRangeException(nameof(highSurrogate), Environment.GetResourceString("ArgumentOutOfRange_InvalidHighSurrogate")); } if (!IsLowSurrogate(lowSurrogate)) { - throw new ArgumentOutOfRangeException("lowSurrogate", Environment.GetResourceString("ArgumentOutOfRange_InvalidLowSurrogate")); + throw new ArgumentOutOfRangeException(nameof(lowSurrogate), Environment.GetResourceString("ArgumentOutOfRange_InvalidLowSurrogate")); } Contract.EndContractBlock(); return (((highSurrogate - CharUnicodeInfo.HIGH_SURROGATE_START) * 0x400) + (lowSurrogate - CharUnicodeInfo.LOW_SURROGATE_START) + UNICODE_PLANE01_START); @@ -964,11 +964,11 @@ namespace System { public static int ConvertToUtf32(String s, int index) { if (s == null) { - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); } if (index < 0 || index >= s.Length) { - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); } Contract.EndContractBlock(); // Check if the character at index is a high surrogate. @@ -983,15 +983,15 @@ namespace System { // Found a low surrogate. return ((temp1 * 0x400) + temp2 + UNICODE_PLANE01_START); } else { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHighSurrogate", index), "s"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHighSurrogate", index), nameof(s)); } } else { // Found a high surrogate at the end of the string. - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHighSurrogate", index), "s"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHighSurrogate", index), nameof(s)); } } else { // Find a low surrogate at the character pointed by index. - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidLowSurrogate", index), "s"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidLowSurrogate", index), nameof(s)); } } // Not a high-surrogate or low-surrogate. Genereate the UTF32 value for the BMP characters. diff --git a/src/mscorlib/src/System/Collections/ArrayList.cs b/src/mscorlib/src/System/Collections/ArrayList.cs index 94f4dc7..e7f1213 100644 --- a/src/mscorlib/src/System/Collections/ArrayList.cs +++ b/src/mscorlib/src/System/Collections/ArrayList.cs @@ -31,9 +31,7 @@ namespace System.Collections { // of the ArrayList is automatically increased as required by reallocating the // internal array. // -#if FEATURE_CORECLR [FriendAccessAllowed] -#endif [DebuggerTypeProxy(typeof(System.Collections.ArrayList.ArrayListDebugView))] [DebuggerDisplay("Count = {Count}")] [Serializable] @@ -68,7 +66,7 @@ namespace System.Collections { // before any reallocations are required. // public ArrayList(int capacity) { - if (capacity < 0) throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_MustBeNonNegNum", "capacity")); + if (capacity < 0) throw new ArgumentOutOfRangeException(nameof(capacity), Environment.GetResourceString("ArgumentOutOfRange_MustBeNonNegNum", nameof(capacity))); Contract.EndContractBlock(); if (capacity == 0) @@ -83,7 +81,7 @@ namespace System.Collections { // public ArrayList(ICollection c) { if (c==null) - throw new ArgumentNullException("c", Environment.GetResourceString("ArgumentNull_Collection")); + throw new ArgumentNullException(nameof(c), Environment.GetResourceString("ArgumentNull_Collection")); Contract.EndContractBlock(); int count = c.Count; @@ -108,7 +106,7 @@ namespace System.Collections { } set { if (value < _size) { - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity")); + throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity")); } Contract.Ensures(Capacity >= 0); Contract.EndContractBlock(); @@ -166,12 +164,12 @@ namespace System.Collections { // public virtual Object this[int index] { get { - if (index < 0 || index >= _size) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + if (index < 0 || index >= _size) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.EndContractBlock(); return _items[index]; } set { - if (index < 0 || index >= _size) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + if (index < 0 || index >= _size) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.EndContractBlock(); _items[index] = value; _version++; @@ -188,7 +186,7 @@ namespace System.Collections { // public static ArrayList Adapter(IList list) { if (list==null) - throw new ArgumentNullException("list"); + throw new ArgumentNullException(nameof(list)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); return new IListWrapper(list); @@ -236,9 +234,9 @@ namespace System.Collections { // public virtual int BinarySearch(int index, int count, Object value, IComparer comparer) { if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (_size - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.Ensures(Contract.Result() < Count); @@ -356,7 +354,7 @@ namespace System.Collections { // public static IList FixedSize(IList list) { if (list==null) - throw new ArgumentNullException("list"); + throw new ArgumentNullException(nameof(list)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); return new FixedSizeList(list); @@ -367,7 +365,7 @@ namespace System.Collections { // public static ArrayList FixedSize(ArrayList list) { if (list==null) - throw new ArgumentNullException("list"); + throw new ArgumentNullException(nameof(list)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); return new FixedSizeArrayList(list); @@ -390,9 +388,9 @@ namespace System.Collections { // public virtual IEnumerator GetEnumerator(int index, int count) { if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (_size - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.Ensures(Contract.Result() != null); @@ -425,7 +423,7 @@ namespace System.Collections { // public virtual int IndexOf(Object value, int startIndex) { if (startIndex > _size) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.Ensures(Contract.Result() < Count); Contract.EndContractBlock(); return Array.IndexOf((Array)_items, value, startIndex, _size - startIndex); @@ -442,8 +440,8 @@ namespace System.Collections { // public virtual int IndexOf(Object value, int startIndex, int count) { if (startIndex > _size) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); - if (count <0 || startIndex > _size - count) throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); + if (count <0 || startIndex > _size - count) throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); Contract.Ensures(Contract.Result() < Count); Contract.EndContractBlock(); return Array.IndexOf((Array)_items, value, startIndex, count); @@ -455,7 +453,7 @@ namespace System.Collections { // public virtual void Insert(int index, Object value) { // Note that insertions at the end are legal. - if (index < 0 || index > _size) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_ArrayListInsert")); + if (index < 0 || index > _size) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_ArrayListInsert")); //Contract.Ensures(Count == Contract.OldValue(Count) + 1); Contract.EndContractBlock(); @@ -475,8 +473,8 @@ namespace System.Collections { // public virtual void InsertRange(int index, ICollection c) { if (c==null) - throw new ArgumentNullException("c", Environment.GetResourceString("ArgumentNull_Collection")); - if (index < 0 || index > _size) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentNullException(nameof(c), Environment.GetResourceString("ArgumentNull_Collection")); + if (index < 0 || index > _size) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); //Contract.Ensures(Count == Contract.OldValue(Count) + c.Count); Contract.EndContractBlock(); @@ -522,7 +520,7 @@ namespace System.Collections { public virtual int LastIndexOf(Object value, int startIndex) { if (startIndex >= _size) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.Ensures(Contract.Result() < Count); Contract.EndContractBlock(); return LastIndexOf(value, startIndex, startIndex + 1); @@ -539,7 +537,7 @@ namespace System.Collections { // public virtual int LastIndexOf(Object value, int startIndex, int count) { if (Count != 0 && (startIndex < 0 || count < 0)) - throw new ArgumentOutOfRangeException((startIndex<0 ? "startIndex" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((startIndex<0 ? nameof(startIndex) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.Ensures(Contract.Result() < Count); Contract.EndContractBlock(); @@ -547,19 +545,17 @@ namespace System.Collections { return -1; if (startIndex >= _size || count > startIndex + 1) - throw new ArgumentOutOfRangeException((startIndex>=_size ? "startIndex" : "count"), Environment.GetResourceString("ArgumentOutOfRange_BiggerThanCollection")); + throw new ArgumentOutOfRangeException((startIndex>=_size ? nameof(startIndex) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_BiggerThanCollection")); return Array.LastIndexOf((Array)_items, value, startIndex, count); } // Returns a read-only IList wrapper for the given IList. // -#if FEATURE_CORECLR [FriendAccessAllowed] -#endif public static IList ReadOnly(IList list) { if (list==null) - throw new ArgumentNullException("list"); + throw new ArgumentNullException(nameof(list)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); return new ReadOnlyList(list); @@ -569,7 +565,7 @@ namespace System.Collections { // public static ArrayList ReadOnly(ArrayList list) { if (list==null) - throw new ArgumentNullException("list"); + throw new ArgumentNullException(nameof(list)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); return new ReadOnlyArrayList(list); @@ -591,7 +587,7 @@ namespace System.Collections { // decreased by one. // public virtual void RemoveAt(int index) { - if (index < 0 || index >= _size) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + if (index < 0 || index >= _size) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.Ensures(Count >= 0); //Contract.Ensures(Count == Contract.OldValue(Count) - 1); Contract.EndContractBlock(); @@ -608,9 +604,9 @@ namespace System.Collections { // public virtual void RemoveRange(int index, int count) { if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (_size - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.Ensures(Count >= 0); @@ -632,7 +628,7 @@ namespace System.Collections { // public static ArrayList Repeat(Object value, int count) { if (count < 0) - throw new ArgumentOutOfRangeException("count",Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count),Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -657,9 +653,9 @@ namespace System.Collections { // public virtual void Reverse(int index, int count) { if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (_size - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -671,10 +667,10 @@ namespace System.Collections { // given collection. // public virtual void SetRange(int index, ICollection c) { - if (c==null) throw new ArgumentNullException("c", Environment.GetResourceString("ArgumentNull_Collection")); + if (c==null) throw new ArgumentNullException(nameof(c), Environment.GetResourceString("ArgumentNull_Collection")); Contract.EndContractBlock(); int count = c.Count; - if (index < 0 || index > _size - count) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + if (index < 0 || index > _size - count) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); if (count > 0) { c.CopyTo(_items, index); @@ -684,7 +680,7 @@ namespace System.Collections { public virtual ArrayList GetRange(int index, int count) { if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (_size - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.Ensures(Contract.Result() != null); @@ -716,9 +712,9 @@ namespace System.Collections { // public virtual void Sort(int index, int count, IComparer comparer) { if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (_size - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -729,10 +725,9 @@ namespace System.Collections { // Returns a thread-safe wrapper around an IList. // - [HostProtection(Synchronization=true)] public static IList Synchronized(IList list) { if (list==null) - throw new ArgumentNullException("list"); + throw new ArgumentNullException(nameof(list)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); return new SyncIList(list); @@ -740,10 +735,9 @@ namespace System.Collections { // Returns a thread-safe wrapper around a ArrayList. // - [HostProtection(Synchronization=true)] public static ArrayList Synchronized(ArrayList list) { if (list==null) - throw new ArgumentNullException("list"); + throw new ArgumentNullException(nameof(list)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); return new SyncArrayList(list); @@ -764,10 +758,9 @@ namespace System.Collections { // downcasting all elements. This copy may fail and is an O(n) operation. // Internally, this implementation calls Array.Copy. // - [SecuritySafeCritical] public virtual Array ToArray(Type type) { if (type==null) - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); Array array = Array.UnsafeCreateInstance(type, _size); @@ -804,7 +797,7 @@ namespace System.Collections { public override int Capacity { get { return _list.Count; } set { - if (value < Count) throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity")); + if (value < Count) throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity")); Contract.EndContractBlock(); } } @@ -854,7 +847,7 @@ namespace System.Collections { public override int BinarySearch(int index, int count, Object value, IComparer comparer) { if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (this.Count - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -906,11 +899,11 @@ namespace System.Collections { public override void CopyTo(int index, Array array, int arrayIndex, int count) { if (array==null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); if (index < 0 || arrayIndex < 0) - throw new ArgumentOutOfRangeException((index < 0) ? "index" : "arrayIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index < 0) ? nameof(index) : nameof(arrayIndex), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if( count < 0) - throw new ArgumentOutOfRangeException( "count" , Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException( nameof(count) , Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (array.Length - arrayIndex < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); if (array.Rank != 1) @@ -930,7 +923,7 @@ namespace System.Collections { public override IEnumerator GetEnumerator(int index, int count) { if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); if (_list.Count - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); @@ -948,8 +941,8 @@ namespace System.Collections { } public override int IndexOf(Object value, int startIndex, int count) { - if (startIndex < 0 || startIndex > this.Count) throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); - if (count < 0 || startIndex > this.Count - count) throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); + if (startIndex < 0 || startIndex > this.Count) throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); + if (count < 0 || startIndex > this.Count - count) throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); Contract.EndContractBlock(); int endIndex = startIndex + count; @@ -973,8 +966,8 @@ namespace System.Collections { public override void InsertRange(int index, ICollection c) { if (c==null) - throw new ArgumentNullException("c", Environment.GetResourceString("ArgumentNull_Collection")); - if (index < 0 || index > this.Count) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentNullException(nameof(c), Environment.GetResourceString("ArgumentNull_Collection")); + if (index < 0 || index > this.Count) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.EndContractBlock(); if( c.Count > 0) { @@ -1009,8 +1002,8 @@ namespace System.Collections { if (_list.Count == 0) return -1; - if (startIndex < 0 || startIndex >= _list.Count) throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); - if (count < 0 || count > startIndex + 1) throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); + if (startIndex < 0 || startIndex >= _list.Count) throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); + if (count < 0 || count > startIndex + 1) throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); int endIndex = startIndex - count + 1; if (value == null) { @@ -1039,7 +1032,7 @@ namespace System.Collections { public override void RemoveRange(int index, int count) { if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); if (_list.Count - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); @@ -1055,7 +1048,7 @@ namespace System.Collections { public override void Reverse(int index, int count) { if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); if (_list.Count - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); @@ -1073,12 +1066,12 @@ namespace System.Collections { public override void SetRange(int index, ICollection c) { if (c==null) { - throw new ArgumentNullException("c", Environment.GetResourceString("ArgumentNull_Collection")); + throw new ArgumentNullException(nameof(c), Environment.GetResourceString("ArgumentNull_Collection")); } Contract.EndContractBlock(); if (index < 0 || index > _list.Count - c.Count) { - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); } if( c.Count > 0) { @@ -1092,7 +1085,7 @@ namespace System.Collections { public override ArrayList GetRange(int index, int count) { if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); if (_list.Count - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); @@ -1101,7 +1094,7 @@ namespace System.Collections { public override void Sort(int index, int count, IComparer comparer) { if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); if (_list.Count - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); @@ -1122,11 +1115,10 @@ namespace System.Collections { return array; } - [SecuritySafeCritical] public override Array ToArray(Type type) { if (type==null) - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); Contract.EndContractBlock(); Array array = Array.UnsafeCreateInstance(type, _list.Count); _list.CopyTo(array, 0); @@ -1806,7 +1798,7 @@ namespace System.Collections { public override ArrayList GetRange(int index, int count) { if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (Count - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -2062,7 +2054,7 @@ namespace System.Collections { public override ArrayList GetRange(int index, int count) { if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (Count - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -2191,7 +2183,7 @@ namespace System.Collections { public override void AddRange(ICollection c) { if( c == null ) { - throw new ArgumentNullException("c"); + throw new ArgumentNullException(nameof(c)); } Contract.EndContractBlock(); @@ -2207,7 +2199,7 @@ namespace System.Collections { // Other overloads with automatically work public override int BinarySearch(int index, int count, Object value, IComparer comparer) { if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (_baseSize - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -2224,7 +2216,7 @@ namespace System.Collections { } set { - if (value < Count) throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity")); + if (value < Count) throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity")); Contract.EndContractBlock(); } } @@ -2265,11 +2257,11 @@ namespace System.Collections { public override void CopyTo(Array array, int index) { if (array==null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); if (array.Rank != 1) throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported")); if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (array.Length - index < _baseSize) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -2280,11 +2272,11 @@ namespace System.Collections { public override void CopyTo(int index, Array array, int arrayIndex, int count) { if (array==null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); if (array.Rank != 1) throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported")); if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (array.Length - arrayIndex < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); if (_baseSize - index < count) @@ -2320,7 +2312,7 @@ namespace System.Collections { public override IEnumerator GetEnumerator(int index, int count) { if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (_baseSize - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -2331,7 +2323,7 @@ namespace System.Collections { public override ArrayList GetRange(int index, int count) { if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (_baseSize - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -2356,9 +2348,9 @@ namespace System.Collections { public override int IndexOf(Object value, int startIndex) { if (startIndex < 0) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (startIndex > _baseSize) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.EndContractBlock(); InternalUpdateRange(); @@ -2369,10 +2361,10 @@ namespace System.Collections { public override int IndexOf(Object value, int startIndex, int count) { if (startIndex < 0 || startIndex > _baseSize) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); if (count < 0 || (startIndex > _baseSize - count)) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); Contract.EndContractBlock(); InternalUpdateRange(); @@ -2382,7 +2374,7 @@ namespace System.Collections { } public override void Insert(int index, Object value) { - if (index < 0 || index > _baseSize) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + if (index < 0 || index > _baseSize) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.EndContractBlock(); InternalUpdateRange(); @@ -2392,9 +2384,9 @@ namespace System.Collections { } public override void InsertRange(int index, ICollection c) { - if (index < 0 || index > _baseSize) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + if (index < 0 || index > _baseSize) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); if( c == null) { - throw new ArgumentNullException("c"); + throw new ArgumentNullException(nameof(c)); } Contract.EndContractBlock(); @@ -2426,9 +2418,9 @@ namespace System.Collections { return -1; if (startIndex >= _baseSize) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); if (startIndex < 0) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); int i = _baseList.LastIndexOf(value, _baseIndex + startIndex, count); if (i >= 0) return i - _baseIndex; @@ -2438,7 +2430,7 @@ namespace System.Collections { // Don't need to override Remove public override void RemoveAt(int index) { - if (index < 0 || index >= _baseSize) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + if (index < 0 || index >= _baseSize) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.EndContractBlock(); InternalUpdateRange(); @@ -2449,7 +2441,7 @@ namespace System.Collections { public override void RemoveRange(int index, int count) { if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (_baseSize - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -2466,7 +2458,7 @@ namespace System.Collections { public override void Reverse(int index, int count) { if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (_baseSize - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -2479,7 +2471,7 @@ namespace System.Collections { [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. public override void SetRange(int index, ICollection c) { InternalUpdateRange(); - if (index < 0 || index >= _baseSize) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + if (index < 0 || index >= _baseSize) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); _baseList.SetRange(_baseIndex + index, c); if( c.Count > 0) { InternalUpdateVersion(); @@ -2488,7 +2480,7 @@ namespace System.Collections { public override void Sort(int index, int count, IComparer comparer) { if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (_baseSize - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -2501,12 +2493,12 @@ namespace System.Collections { public override Object this[int index] { get { InternalUpdateRange(); - if (index < 0 || index >= _baseSize) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + if (index < 0 || index >= _baseSize) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); return _baseList[_baseIndex + index]; } set { InternalUpdateRange(); - if (index < 0 || index >= _baseSize) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + if (index < 0 || index >= _baseSize) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); _baseList[_baseIndex + index] = value; InternalUpdateVersion(); } @@ -2519,10 +2511,9 @@ namespace System.Collections { return array; } - [SecuritySafeCritical] public override Array ToArray(Type type) { if (type==null) - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); Contract.EndContractBlock(); InternalUpdateRange(); @@ -2619,7 +2610,7 @@ namespace System.Collections { public ArrayListDebugView( ArrayList arrayList) { if( arrayList == null) - throw new ArgumentNullException("arrayList"); + throw new ArgumentNullException(nameof(arrayList)); this.arrayList = arrayList; } diff --git a/src/mscorlib/src/System/Collections/BitArray.cs b/src/mscorlib/src/System/Collections/BitArray.cs deleted file mode 100644 index 2f565f8..0000000 --- a/src/mscorlib/src/System/Collections/BitArray.cs +++ /dev/null @@ -1,524 +0,0 @@ -// 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. - -/*============================================================================= -** -** -** -** -** -** Purpose: The BitArray class manages a compact array of bit values. -** -** -=============================================================================*/ -namespace System.Collections { - - using System; - using System.Security.Permissions; - using System.Diagnostics.Contracts; - // A vector of bits. Use this to store bits efficiently, without having to do bit - // shifting yourself. -[System.Runtime.InteropServices.ComVisible(true)] - [Serializable()] public sealed class BitArray : ICollection, ICloneable { - private BitArray() { - } - - /*========================================================================= - ** Allocates space to hold length bit values. All of the values in the bit - ** array are set to false. - ** - ** Exceptions: ArgumentException if length < 0. - =========================================================================*/ - public BitArray(int length) - : this(length, false) { - } - - /*========================================================================= - ** Allocates space to hold length bit values. All of the values in the bit - ** array are set to defaultValue. - ** - ** Exceptions: ArgumentOutOfRangeException if length < 0. - =========================================================================*/ - public BitArray(int length, bool defaultValue) { - if (length < 0) { - throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - } - Contract.EndContractBlock(); - - m_array = new int[GetArrayLength(length, BitsPerInt32)]; - m_length = length; - - int fillValue = defaultValue ? unchecked(((int)0xffffffff)) : 0; - for (int i = 0; i < m_array.Length; i++) { - m_array[i] = fillValue; - } - - _version = 0; - } - - /*========================================================================= - ** Allocates space to hold the bit values in bytes. bytes[0] represents - ** bits 0 - 7, bytes[1] represents bits 8 - 15, etc. The LSB of each byte - ** represents the lowest index value; bytes[0] & 1 represents bit 0, - ** bytes[0] & 2 represents bit 1, bytes[0] & 4 represents bit 2, etc. - ** - ** Exceptions: ArgumentException if bytes == null. - =========================================================================*/ - public BitArray(byte[] bytes) { - if (bytes == null) { - throw new ArgumentNullException(nameof(bytes)); - } - Contract.EndContractBlock(); - // this value is chosen to prevent overflow when computing m_length. - // m_length is of type int32 and is exposed as a property, so - // type of m_length can't be changed to accommodate. - if (bytes.Length > Int32.MaxValue / BitsPerByte) { - throw new ArgumentException(Environment.GetResourceString("Argument_ArrayTooLarge", BitsPerByte), nameof(bytes)); - } - - m_array = new int[GetArrayLength(bytes.Length, BytesPerInt32)]; - m_length = bytes.Length * BitsPerByte; - - int i = 0; - int j = 0; - while (bytes.Length - j >= 4) { - m_array[i++] = (bytes[j] & 0xff) | - ((bytes[j + 1] & 0xff) << 8) | - ((bytes[j + 2] & 0xff) << 16) | - ((bytes[j + 3] & 0xff) << 24); - j += 4; - } - - Contract.Assert(bytes.Length - j >= 0, "BitArray byteLength problem"); - Contract.Assert(bytes.Length - j < 4, "BitArray byteLength problem #2"); - - switch (bytes.Length - j) { - case 3: - m_array[i] = ((bytes[j + 2] & 0xff) << 16); - goto case 2; - // fall through - case 2: - m_array[i] |= ((bytes[j + 1] & 0xff) << 8); - goto case 1; - // fall through - case 1: - m_array[i] |= (bytes[j] & 0xff); - break; - } - - _version = 0; - } - - public BitArray(bool[] values) { - if (values == null) { - throw new ArgumentNullException(nameof(values)); - } - Contract.EndContractBlock(); - - m_array = new int[GetArrayLength(values.Length, BitsPerInt32)]; - m_length = values.Length; - - for (int i = 0;i Int32.MaxValue / BitsPerInt32) { - throw new ArgumentException(Environment.GetResourceString("Argument_ArrayTooLarge", BitsPerInt32), nameof(values)); - } - - m_array = new int[values.Length]; - m_length = values.Length * BitsPerInt32; - - Array.Copy(values, m_array, values.Length); - - _version = 0; - } - - /*========================================================================= - ** Allocates a new BitArray with the same length and bit values as bits. - ** - ** Exceptions: ArgumentException if bits == null. - =========================================================================*/ - public BitArray(BitArray bits) { - if (bits == null) { - throw new ArgumentNullException(nameof(bits)); - } - Contract.EndContractBlock(); - - int arrayLength = GetArrayLength(bits.m_length, BitsPerInt32); - m_array = new int[arrayLength]; - m_length = bits.m_length; - - Array.Copy(bits.m_array, m_array, arrayLength); - - _version = bits._version; - } - - public bool this[int index] { - get { - return Get(index); - } - set { - Set(index,value); - } - } - - /*========================================================================= - ** Returns the bit value at position index. - ** - ** Exceptions: ArgumentOutOfRangeException if index < 0 or - ** index >= GetLength(). - =========================================================================*/ - public bool Get(int index) { - if (index < 0 || index >= Length) { - throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); - } - Contract.EndContractBlock(); - - return (m_array[index / 32] & (1 << (index % 32))) != 0; - } - - /*========================================================================= - ** Sets the bit value at position index to value. - ** - ** Exceptions: ArgumentOutOfRangeException if index < 0 or - ** index >= GetLength(). - =========================================================================*/ - public void Set(int index, bool value) { - if (index < 0 || index >= Length) { - throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); - } - Contract.EndContractBlock(); - - if (value) { - m_array[index / 32] |= (1 << (index % 32)); - } else { - m_array[index / 32] &= ~(1 << (index % 32)); - } - - _version++; - } - - /*========================================================================= - ** Sets all the bit values to value. - =========================================================================*/ - public void SetAll(bool value) { - int fillValue = value ? unchecked(((int)0xffffffff)) : 0; - int ints = GetArrayLength(m_length, BitsPerInt32); - for (int i = 0; i < ints; i++) { - m_array[i] = fillValue; - } - - _version++; - } - - /*========================================================================= - ** Returns a reference to the current instance ANDed with value. - ** - ** Exceptions: ArgumentException if value == null or - ** value.Length != this.Length. - =========================================================================*/ - public BitArray And(BitArray value) { - if (value==null) - throw new ArgumentNullException(nameof(value)); - if (Length != value.Length) - throw new ArgumentException(Environment.GetResourceString("Arg_ArrayLengthsDiffer")); - Contract.EndContractBlock(); - - int ints = GetArrayLength(m_length, BitsPerInt32); - for (int i = 0; i < ints; i++) { - m_array[i] &= value.m_array[i]; - } - - _version++; - return this; - } - - /*========================================================================= - ** Returns a reference to the current instance ORed with value. - ** - ** Exceptions: ArgumentException if value == null or - ** value.Length != this.Length. - =========================================================================*/ - public BitArray Or(BitArray value) { - if (value==null) - throw new ArgumentNullException(nameof(value)); - if (Length != value.Length) - throw new ArgumentException(Environment.GetResourceString("Arg_ArrayLengthsDiffer")); - Contract.EndContractBlock(); - - int ints = GetArrayLength(m_length, BitsPerInt32); - for (int i = 0; i < ints; i++) { - m_array[i] |= value.m_array[i]; - } - - _version++; - return this; - } - - /*========================================================================= - ** Returns a reference to the current instance XORed with value. - ** - ** Exceptions: ArgumentException if value == null or - ** value.Length != this.Length. - =========================================================================*/ - public BitArray Xor(BitArray value) { - if (value==null) - throw new ArgumentNullException(nameof(value)); - if (Length != value.Length) - throw new ArgumentException(Environment.GetResourceString("Arg_ArrayLengthsDiffer")); - Contract.EndContractBlock(); - - int ints = GetArrayLength(m_length, BitsPerInt32); - for (int i = 0; i < ints; i++) { - m_array[i] ^= value.m_array[i]; - } - - _version++; - return this; - } - - /*========================================================================= - ** Inverts all the bit values. On/true bit values are converted to - ** off/false. Off/false bit values are turned on/true. The current instance - ** is updated and returned. - =========================================================================*/ - public BitArray Not() { - int ints = GetArrayLength(m_length, BitsPerInt32); - for (int i = 0; i < ints; i++) { - m_array[i] = ~m_array[i]; - } - - _version++; - return this; - } - - public int Length { - get { - Contract.Ensures(Contract.Result() >= 0); - return m_length; - } - set { - if (value < 0) { - throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - } - Contract.EndContractBlock(); - - int newints = GetArrayLength(value, BitsPerInt32); - if (newints > m_array.Length || newints + _ShrinkThreshold < m_array.Length) { - // grow or shrink (if wasting more than _ShrinkThreshold ints) - int[] newarray = new int[newints]; - Array.Copy(m_array, newarray, newints > m_array.Length ? m_array.Length : newints); - m_array = newarray; - } - - if (value > m_length) { - // clear high bit values in the last int - int last = GetArrayLength(m_length, BitsPerInt32) - 1; - int bits = m_length % 32; - if (bits > 0) { - m_array[last] &= (1 << bits) - 1; - } - - // clear remaining int values - Array.Clear(m_array, last + 1, newints - last - 1); - } - - m_length = value; - _version++; - } - } - - // ICollection implementation - public void CopyTo(Array array, int index) - { - if (array == null) - throw new ArgumentNullException(nameof(array)); - - if (index < 0) - throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - - if (array.Rank != 1) - throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"), nameof(array)); - - Contract.EndContractBlock(); - - if (array is int[]) - { - Array.Copy(m_array, 0, array, index, GetArrayLength(m_length, BitsPerInt32)); - } - else if (array is byte[]) - { - int arrayLength = GetArrayLength(m_length, BitsPerByte); - if ((array.Length - index) < arrayLength) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - - byte [] b = (byte[])array; - for (int i = 0; i < arrayLength; i++) - b[index + i] = (byte)((m_array[i/4] >> ((i%4)*8)) & 0x000000FF); // Shift to bring the required byte to LSB, then mask - } - else if (array is bool[]) - { - if (array.Length - index < m_length) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - - bool [] b = (bool[])array; - for (int i = 0;i> (i%32)) & 0x00000001) != 0; - } - else - throw new ArgumentException(Environment.GetResourceString("Arg_BitArrayTypeUnsupported"), nameof(array)); - } - - public int Count - { - get - { - Contract.Ensures(Contract.Result() >= 0); - - return m_length; - } - } - - public Object Clone() - { - Contract.Ensures(Contract.Result() != null); - Contract.Ensures(((BitArray)Contract.Result()).Length == this.Length); - - return new BitArray(this); - } - - public Object SyncRoot - { - get - { - if( _syncRoot == null) { - System.Threading.Interlocked.CompareExchange(ref _syncRoot, new Object(), null); - } - return _syncRoot; - } - } - - public bool IsReadOnly - { - get - { - return false; - } - } - - public bool IsSynchronized - { - get - { - return false; - } - } - - public IEnumerator GetEnumerator() - { - return new BitArrayEnumeratorSimple(this); - } - - // XPerY=n means that n Xs can be stored in 1 Y. - private const int BitsPerInt32 = 32; - private const int BytesPerInt32 = 4; - private const int BitsPerByte = 8; - - /// - /// Used for conversion between different representations of bit array. - /// Returns (n+(div-1))/div, rearranged to avoid arithmetic overflow. - /// For example, in the bit to int case, the straightforward calc would - /// be (n+31)/32, but that would cause overflow. So instead it's - /// rearranged to ((n-1)/32) + 1, with special casing for 0. - /// - /// Usage: - /// GetArrayLength(77, BitsPerInt32): returns how many ints must be - /// allocated to store 77 bits. - /// - /// - /// use a conversion constant, e.g. BytesPerInt32 to get - /// how many ints are required to store n bytes - /// - private static int GetArrayLength(int n, int div) { - Contract.Assert(div > 0, "GetArrayLength: div arg must be greater than 0"); - return n > 0 ? (((n - 1) / div) + 1) : 0; - } - - [Serializable] - private class BitArrayEnumeratorSimple : IEnumerator, ICloneable - { - private BitArray bitarray; - private int index; - private int version; - private bool currentElement; - - internal BitArrayEnumeratorSimple(BitArray bitarray) { - this.bitarray = bitarray; - this.index = -1; - version = bitarray._version; - } - - public Object Clone() { - return MemberwiseClone(); - } - - public virtual bool MoveNext() { - if (version != bitarray._version) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion)); - if (index < (bitarray.Count-1)) { - index++; - currentElement = bitarray.Get(index); - return true; - } - else - index = bitarray.Count; - - return false; - } - - public virtual Object Current { - get { - if (index == -1) - throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumNotStarted)); - if (index >= bitarray.Count) - throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumEnded)); - return currentElement; - } - } - - public void Reset() { - if (version != bitarray._version) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion)); - index = -1; - } - } - - private int[] m_array; - private int m_length; - private int _version; - [NonSerialized] - private Object _syncRoot; - - private const int _ShrinkThreshold = 256; - } - -} diff --git a/src/mscorlib/src/System/Collections/CollectionBase.cs b/src/mscorlib/src/System/Collections/CollectionBase.cs index 1bb08af..ae0c0d3 100644 --- a/src/mscorlib/src/System/Collections/CollectionBase.cs +++ b/src/mscorlib/src/System/Collections/CollectionBase.cs @@ -62,7 +62,7 @@ namespace System.Collections { public void RemoveAt(int index) { if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.EndContractBlock(); Object temp = InnerList[index]; OnValidate(temp); @@ -101,13 +101,13 @@ namespace System.Collections { Object IList.this[int index] { get { if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.EndContractBlock(); return InnerList[index]; } set { if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.EndContractBlock(); OnValidate(value); Object temp = InnerList[index]; @@ -163,7 +163,7 @@ namespace System.Collections { void IList.Insert(int index, Object value) { if (index < 0 || index > Count) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.EndContractBlock(); OnValidate(value); OnInsert(index, value); @@ -194,7 +194,7 @@ namespace System.Collections { } protected virtual void OnValidate(Object value) { - if (value == null) throw new ArgumentNullException("value"); + if (value == null) throw new ArgumentNullException(nameof(value)); Contract.EndContractBlock(); } diff --git a/src/mscorlib/src/System/Collections/Comparer.cs b/src/mscorlib/src/System/Collections/Comparer.cs index 11e2625..0e3c78b 100644 --- a/src/mscorlib/src/System/Collections/Comparer.cs +++ b/src/mscorlib/src/System/Collections/Comparer.cs @@ -36,7 +36,7 @@ namespace System.Collections { public Comparer(CultureInfo culture) { if (culture==null) { - throw new ArgumentNullException("culture"); + throw new ArgumentNullException(nameof(culture)); } Contract.EndContractBlock(); m_compareInfo = culture.CompareInfo; @@ -83,10 +83,9 @@ namespace System.Collections { throw new ArgumentException(Environment.GetResourceString("Argument_ImplementIComparable")); } - [System.Security.SecurityCritical] // auto-generated_required public void GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/Collections/CompatibleComparer.cs b/src/mscorlib/src/System/Collections/CompatibleComparer.cs index 85e6c3f..e5d3961 100644 --- a/src/mscorlib/src/System/Collections/CompatibleComparer.cs +++ b/src/mscorlib/src/System/Collections/CompatibleComparer.cs @@ -39,7 +39,7 @@ namespace System.Collections { public int GetHashCode(Object obj) { if( obj == null) { - throw new ArgumentNullException("obj"); + throw new ArgumentNullException(nameof(obj)); } Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs index d805dc8..c1a6f75 100644 --- a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs +++ b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs @@ -28,7 +28,6 @@ using System.Security.Permissions; namespace System.Collections.Concurrent { - /// /// Represents a thread-safe collection of keys and values. /// @@ -38,13 +37,9 @@ namespace System.Collections.Concurrent /// All public and protected members of are thread-safe and may be used /// concurrently from multiple threads. /// -#if !FEATURE_CORECLR - [Serializable] -#endif [ComVisible(false)] [DebuggerTypeProxy(typeof(Mscorlib_DictionaryDebugView<,>))] [DebuggerDisplay("Count = {Count}")] - [HostProtection(Synchronization = true, ExternalThreading = true)] public class ConcurrentDictionary : IDictionary, IDictionary, IReadOnlyDictionary { /// @@ -68,41 +63,20 @@ namespace System.Collections.Concurrent m_comparer = comparer; } } -#if !FEATURE_CORECLR - [NonSerialized] -#endif + private volatile Tables m_tables; // Internal tables of the dictionary // NOTE: this is only used for compat reasons to serialize the comparer. // This should not be accessed from anywhere else outside of the serialization methods. internal IEqualityComparer m_comparer; -#if !FEATURE_CORECLR - [NonSerialized] -#endif private readonly bool m_growLockArray; // Whether to dynamically increase the size of the striped lock // How many times we resized becaused of collisions. // This is used to make sure we don't resize the dictionary because of multi-threaded Add() calls // that generate collisions. Whenever a GrowTable() should be the only place that changes this -#if !FEATURE_CORECLR - // The field should be have been marked as NonSerialized but because we shipped it without that attribute in 4.5.1. - // we can't add it back without breaking compat. To maximize compat we are going to keep the OptionalField attribute - // This will prevent cases where the field was not serialized. - [OptionalField] -#endif private int m_keyRehashCount; -#if !FEATURE_CORECLR - [NonSerialized] -#endif private int m_budget; // The maximum number of elements per lock before a resize operation is triggered -#if !FEATURE_CORECLR // These fields are not used in CoreCLR - private KeyValuePair[] m_serializationArray; // Used for custom serialization - - private int m_serializationConcurrencyLevel; // used to save the concurrency level in serialization - - private int m_serializationCapacity; // used to save the capacity in serialization -#endif // The default concurrency level is DEFAULT_CONCURRENCY_MULTIPLIER * #CPUs. The higher the // DEFAULT_CONCURRENCY_MULTIPLIER, the more concurrent writes can take place without interference // and blocking, but also the more expensive operations that require all locks become (e.g. table @@ -229,7 +203,7 @@ namespace System.Collections.Concurrent public ConcurrentDictionary(IEnumerable> collection, IEqualityComparer comparer) : this(comparer) { - if (collection == null) throw new ArgumentNullException("collection"); + if (collection == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); InitializeFromCollection(collection); } @@ -259,8 +233,8 @@ namespace System.Collections.Concurrent int concurrencyLevel, IEnumerable> collection, IEqualityComparer comparer) : this(concurrencyLevel, DEFAULT_CAPACITY, false, comparer) { - if (collection == null) throw new ArgumentNullException("collection"); - if (comparer == null) throw new ArgumentNullException("comparer"); + if (collection == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); + if (comparer == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparer); InitializeFromCollection(collection); } @@ -270,11 +244,11 @@ namespace System.Collections.Concurrent TValue dummy; foreach (KeyValuePair pair in collection) { - if (pair.Key == null) throw new ArgumentNullException("key"); + if (pair.Key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); if (!TryAddInternal(pair.Key, pair.Value, false, false, out dummy)) { - throw new ArgumentException(GetResource("ConcurrentDictionary_SourceContainsDuplicateKeys")); + ThrowHelper.ThrowArgumentException(ExceptionResource.ConcurrentDictionary_SourceContainsDuplicateKeys); } } @@ -312,13 +286,13 @@ namespace System.Collections.Concurrent { if (concurrencyLevel < 1) { - throw new ArgumentOutOfRangeException("concurrencyLevel", GetResource("ConcurrentDictionary_ConcurrencyLevelMustBePositive")); + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.concurrencyLevel, ExceptionResource.ConcurrentDictionary_ConcurrencyLevelMustBePositive); } if (capacity < 0) { - throw new ArgumentOutOfRangeException("capacity", GetResource("ConcurrentDictionary_CapacityMustNotBeNegative")); + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity, ExceptionResource.ConcurrentDictionary_CapacityMustNotBeNegative); } - if (comparer == null) throw new ArgumentNullException("comparer"); + if (comparer == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparer); // The capacity should be at least as large as the concurrency level. Otherwise, we would have locks that don't guard // any buckets. @@ -358,7 +332,7 @@ namespace System.Collections.Concurrent /// contains too many elements. public bool TryAdd(TKey key, TValue value) { - if (key == null) throw new ArgumentNullException("key"); + if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); TValue dummy; return TryAddInternal(key, value, false, true, out dummy); } @@ -375,7 +349,7 @@ namespace System.Collections.Concurrent /// (Nothing in Visual Basic). public bool ContainsKey(TKey key) { - if (key == null) throw new ArgumentNullException("key"); + if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); TValue throwAwayValue; return TryGetValue(key, out throwAwayValue); @@ -395,7 +369,7 @@ namespace System.Collections.Concurrent /// (Nothing in Visual Basic). public bool TryRemove(TKey key, out TValue value) { - if (key == null) throw new ArgumentNullException("key"); + if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); return TryRemoveInternal(key, out value, false, default(TValue)); } @@ -486,7 +460,7 @@ namespace System.Collections.Concurrent [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")] public bool TryGetValue(TKey key, out TValue value) { - if (key == null) throw new ArgumentNullException("key"); + if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); int bucketNo, lockNoUnused; @@ -531,7 +505,7 @@ namespace System.Collections.Concurrent [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")] public bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue) { - if (key == null) throw new ArgumentNullException("key"); + if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); IEqualityComparer valueComparer = EqualityComparer.Default; @@ -642,8 +616,8 @@ namespace System.Collections.Concurrent [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "ConcurrencyCop just doesn't know about these locks")] void ICollection>.CopyTo(KeyValuePair[] array, int index) { - if (array == null) throw new ArgumentNullException("array"); - if (index < 0) throw new ArgumentOutOfRangeException("index", GetResource("ConcurrentDictionary_IndexIsNegative")); + if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + if (index < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ConcurrentDictionary_IndexIsNegative); int locksAcquired = 0; try @@ -659,7 +633,7 @@ namespace System.Collections.Concurrent if (array.Length - count < index || count < 0) //"count" itself or "count + index" can overflow { - throw new ArgumentException(GetResource("ConcurrentDictionary_ArrayNotLargeEnough")); + ThrowHelper.ThrowArgumentException(ExceptionResource.ConcurrentDictionary_ArrayNotLargeEnough); } CopyToPairs(array, index); @@ -803,11 +777,6 @@ namespace System.Collections.Concurrent bool resizeDesired = false; bool lockTaken = false; -#if FEATURE_RANDOMIZED_STRING_HASHING -#if !FEATURE_CORECLR - bool resizeDueToCollisions = false; -#endif // !FEATURE_CORECLR -#endif try { @@ -821,12 +790,6 @@ namespace System.Collections.Concurrent continue; } -#if FEATURE_RANDOMIZED_STRING_HASHING -#if !FEATURE_CORECLR - int collisionCount = 0; -#endif // !FEATURE_CORECLR -#endif - // Try to find this key in the bucket Node prev = null; for (Node node = tables.m_buckets[bucketNo]; node != null; node = node.m_next) @@ -864,23 +827,7 @@ namespace System.Collections.Concurrent return false; } prev = node; - -#if FEATURE_RANDOMIZED_STRING_HASHING -#if !FEATURE_CORECLR - collisionCount++; -#endif // !FEATURE_CORECLR -#endif - } - -#if FEATURE_RANDOMIZED_STRING_HASHING -#if !FEATURE_CORECLR - if(collisionCount > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(comparer)) - { - resizeDesired = true; - resizeDueToCollisions = true; } -#endif // !FEATURE_CORECLR -#endif // The key was not found in the bucket. Insert the key-value pair. Volatile.Write(ref tables.m_buckets[bucketNo], new Node(key, value, hashcode, tables.m_buckets[bucketNo])); @@ -916,16 +863,7 @@ namespace System.Collections.Concurrent if (resizeDesired) { #if FEATURE_RANDOMIZED_STRING_HASHING -#if !FEATURE_CORECLR - if (resizeDueToCollisions) - { - GrowTable(tables, (IEqualityComparer)HashHelpers.GetRandomizedEqualityComparer(comparer), true, m_keyRehashCount); - } - else -#endif // !FEATURE_CORECLR - { - GrowTable(tables, tables.m_comparer, false, m_keyRehashCount); - } + GrowTable(tables, tables.m_comparer, false, m_keyRehashCount); #else GrowTable(tables, tables.m_comparer, false, m_keyRehashCount); #endif @@ -956,13 +894,13 @@ namespace System.Collections.Concurrent TValue value; if (!TryGetValue(key, out value)) { - throw new KeyNotFoundException(); + ThrowHelper.ThrowKeyNotFoundException(); } return value; } set { - if (key == null) throw new ArgumentNullException("key"); + if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); TValue dummy; TryAddInternal(key, value, true, true, out dummy); } @@ -1026,8 +964,8 @@ namespace System.Collections.Concurrent /// if the key was not in the dictionary. public TValue GetOrAdd(TKey key, Func valueFactory) { - if (key == null) throw new ArgumentNullException("key"); - if (valueFactory == null) throw new ArgumentNullException("valueFactory"); + if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + if (valueFactory == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.valueFactory); TValue resultingValue; if (TryGetValue(key, out resultingValue)) @@ -1052,7 +990,7 @@ namespace System.Collections.Concurrent /// key is already in the dictionary, or the new value if the key was not in the dictionary. public TValue GetOrAdd(TKey key, TValue value) { - if (key == null) throw new ArgumentNullException("key"); + if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); TValue resultingValue; TryAddInternal(key, value, false, true, out resultingValue); @@ -1080,9 +1018,9 @@ namespace System.Collections.Concurrent /// absent) or the result of updateValueFactory (if the key was present). public TValue AddOrUpdate(TKey key, Func addValueFactory, Func updateValueFactory) { - if (key == null) throw new ArgumentNullException("key"); - if (addValueFactory == null) throw new ArgumentNullException("addValueFactory"); - if (updateValueFactory == null) throw new ArgumentNullException("updateValueFactory"); + if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + if (addValueFactory == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.addValueFactory); + if (updateValueFactory == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.updateValueFactory); TValue newValue, resultingValue; while (true) @@ -1127,8 +1065,8 @@ namespace System.Collections.Concurrent /// absent) or the result of updateValueFactory (if the key was present). public TValue AddOrUpdate(TKey key, TValue addValue, Func updateValueFactory) { - if (key == null) throw new ArgumentNullException("key"); - if (updateValueFactory == null) throw new ArgumentNullException("updateValueFactory"); + if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + if (updateValueFactory == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.updateValueFactory); TValue newValue, resultingValue; while (true) { @@ -1207,7 +1145,7 @@ namespace System.Collections.Concurrent { if (!TryAdd(key, value)) { - throw new ArgumentException(GetResource("ConcurrentDictionary_KeyAlreadyExisted")); + ThrowHelper.ThrowArgumentException(ExceptionResource.ConcurrentDictionary_KeyAlreadyExisted); } } @@ -1340,8 +1278,7 @@ namespace System.Collections.Concurrent /// name="keyValuePair"/> is a null reference (Nothing in Visual Basic). bool ICollection>.Remove(KeyValuePair keyValuePair) { - if (keyValuePair.Key == null) throw new ArgumentNullException(GetResource("ConcurrentDictionary_ItemKeyIsNull")); - + if (keyValuePair.Key == null) ThrowHelper.ThrowArgumentNullException(ExceptionResource.ConcurrentDictionary_ItemKeyIsNull); TValue throwAwayValue; return TryRemoveInternal(keyValuePair.Key, out throwAwayValue, true, keyValuePair.Value); } @@ -1387,17 +1324,17 @@ namespace System.Collections.Concurrent /// void IDictionary.Add(object key, object value) { - if (key == null) throw new ArgumentNullException("key"); - if (!(key is TKey)) throw new ArgumentException(GetResource("ConcurrentDictionary_TypeOfKeyIncorrect")); + if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + if (!(key is TKey)) ThrowHelper.ThrowArgumentException(ExceptionResource.ConcurrentDictionary_TypeOfKeyIncorrect); - TValue typedValue; + TValue typedValue = default(TValue); try { typedValue = (TValue)value; } catch (InvalidCastException) { - throw new ArgumentException(GetResource("ConcurrentDictionary_TypeOfValueIncorrect")); + ThrowHelper.ThrowArgumentException(ExceptionResource.ConcurrentDictionary_TypeOfValueIncorrect); } ((IDictionary)this).Add((TKey)key, typedValue); @@ -1415,7 +1352,7 @@ namespace System.Collections.Concurrent /// (Nothing in Visual Basic). bool IDictionary.Contains(object key) { - if (key == null) throw new ArgumentNullException("key"); + if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); return (key is TKey) && ((ConcurrentDictionary)this).ContainsKey((TKey)key); } @@ -1475,7 +1412,7 @@ namespace System.Collections.Concurrent /// (Nothing in Visual Basic). void IDictionary.Remove(object key) { - if (key == null) throw new ArgumentNullException("key"); + if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); TValue throwAwayValue; if (key is TKey) @@ -1517,7 +1454,7 @@ namespace System.Collections.Concurrent { get { - if (key == null) throw new ArgumentNullException("key"); + if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); TValue value; if (key is TKey && this.TryGetValue((TKey)key, out value)) @@ -1529,10 +1466,10 @@ namespace System.Collections.Concurrent } set { - if (key == null) throw new ArgumentNullException("key"); + if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); - if (!(key is TKey)) throw new ArgumentException(GetResource("ConcurrentDictionary_TypeOfKeyIncorrect")); - if (!(value is TValue)) throw new ArgumentException(GetResource("ConcurrentDictionary_TypeOfValueIncorrect")); + if (!(key is TKey)) ThrowHelper.ThrowArgumentException(ExceptionResource.ConcurrentDictionary_TypeOfKeyIncorrect); + if (!(value is TValue)) ThrowHelper.ThrowArgumentException(ExceptionResource.ConcurrentDictionary_TypeOfValueIncorrect); ((ConcurrentDictionary)this)[(TKey)key] = (TValue)value; } @@ -1563,8 +1500,8 @@ namespace System.Collections.Concurrent [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "ConcurrencyCop just doesn't know about these locks")] void ICollection.CopyTo(Array array, int index) { - if (array == null) throw new ArgumentNullException("array"); - if (index < 0) throw new ArgumentOutOfRangeException("index", GetResource("ConcurrentDictionary_IndexIsNegative")); + if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + if (index < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ConcurrentDictionary_IndexIsNegative); int locksAcquired = 0; try @@ -1581,7 +1518,7 @@ namespace System.Collections.Concurrent if (array.Length - count < index || count < 0) //"count" itself or "count + index" can overflow { - throw new ArgumentException(GetResource("ConcurrentDictionary_ArrayNotLargeEnough")); + ThrowHelper.ThrowArgumentException(ExceptionResource.ConcurrentDictionary_ArrayNotLargeEnough); } // To be consistent with the behavior of ICollection.CopyTo() in Dictionary, @@ -1611,7 +1548,7 @@ namespace System.Collections.Concurrent return; } - throw new ArgumentException(GetResource("ConcurrentDictionary_ArrayIncorrectType"), "array"); + ThrowHelper.ThrowArgumentException(ExceptionResource.ConcurrentDictionary_ArrayIncorrectType, ExceptionArgument.array); } finally { @@ -1641,7 +1578,8 @@ namespace System.Collections.Concurrent { get { - throw new NotSupportedException(Environment.GetResourceString("ConcurrentCollection_SyncRoot_NotSupported")); + ThrowHelper.ThrowNotSupportedException(ExceptionResource.ConcurrentCollection_SyncRoot_NotSupported); + return default(object); } } @@ -1850,13 +1788,6 @@ namespace System.Collections.Concurrent /// private void AcquireAllLocks(ref int locksAcquired) { -#if !FEATURE_CORECLR - if (CDSCollectionETWBCLProvider.Log.IsEnabled()) - { - CDSCollectionETWBCLProvider.Log.ConcurrentDictionary_AcquiringAllLocks(m_tables.m_buckets.Length); - } -#endif //!FEATURE_CORECLR - // First, acquire lock 0 AcquireLocks(0, 1, ref locksAcquired); @@ -1973,19 +1904,7 @@ namespace System.Collections.Concurrent [Conditional("DEBUG")] private void Assert(bool condition) { - Contract.Assert(condition); - } - - /// - /// A helper function to obtain the string for a particular resource key. - /// - /// - /// - private string GetResource(string key) - { - Assert(key != null); - - return Environment.GetResourceString(key); + Debug.Assert(condition); } /// @@ -2050,46 +1969,5 @@ namespace System.Collections.Concurrent m_enumerator.Reset(); } } - -#if !FEATURE_CORECLR - /// - /// Get the data array to be serialized - /// - [OnSerializing] - private void OnSerializing(StreamingContext context) - { - Tables tables = m_tables; - - // save the data into the serialization array to be saved - m_serializationArray = ToArray(); - m_serializationConcurrencyLevel = tables.m_locks.Length; - m_serializationCapacity = tables.m_buckets.Length; - m_comparer = (IEqualityComparer)HashHelpers.GetEqualityComparerForSerialization(tables.m_comparer); - } - - /// - /// Construct the dictionary from a previously serialized one - /// - [OnDeserialized] - private void OnDeserialized(StreamingContext context) - { - KeyValuePair[] array = m_serializationArray; - - var buckets = new Node[m_serializationCapacity]; - var countPerLock = new int[m_serializationConcurrencyLevel]; - - var locks = new object[m_serializationConcurrencyLevel]; - for (int i = 0; i < locks.Length; i++) - { - locks[i] = new object(); - } - - m_tables = new Tables(buckets, locks, countPerLock, m_comparer); - - InitializeFromCollection(array); - m_serializationArray = null; - - } -#endif } } diff --git a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentQueue.cs b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentQueue.cs index 9164ead..7aa5971 100644 --- a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentQueue.cs +++ b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentQueue.cs @@ -38,7 +38,6 @@ namespace System.Collections.Concurrent [ComVisible(false)] [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(SystemCollectionsConcurrent_ProducerConsumerCollectionDebugView<>))] - [HostProtection(Synchronization = true, ExternalThreading = true)] [Serializable] public class ConcurrentQueue : IProducerConsumerCollection, IReadOnlyCollection { @@ -77,7 +76,7 @@ namespace System.Collections.Concurrent int index = 0; foreach (T element in collection) { - Contract.Assert(index >= 0 && index < SEGMENT_SIZE); + Debug.Assert(index >= 0 && index < SEGMENT_SIZE); localTail.UnsafeAdd(element); index++; @@ -103,7 +102,7 @@ namespace System.Collections.Concurrent { if (collection == null) { - throw new ArgumentNullException("collection"); + throw new ArgumentNullException(nameof(collection)); } InitializeFromCollection(collection); @@ -125,7 +124,7 @@ namespace System.Collections.Concurrent [OnDeserialized] private void OnDeserialized(StreamingContext context) { - Contract.Assert(m_serializationArray != null); + Debug.Assert(m_serializationArray != null); InitializeFromCollection(m_serializationArray); m_serializationArray = null; } @@ -160,7 +159,7 @@ namespace System.Collections.Concurrent // Validate arguments. if (array == null) { - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); } // We must be careful not to corrupt the array, so we will first accumulate an @@ -441,7 +440,7 @@ namespace System.Collections.Concurrent { if (array == null) { - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); } // We must be careful not to corrupt the array, so we will first accumulate an @@ -689,7 +688,7 @@ namespace System.Collections.Concurrent m_array = new T[SEGMENT_SIZE]; m_state = new VolatileBool[SEGMENT_SIZE]; //all initialized to false m_high = -1; - Contract.Assert(index >= 0); + Debug.Assert(index >= 0); m_index = index; m_source = source; } @@ -721,7 +720,7 @@ namespace System.Collections.Concurrent /// internal void UnsafeAdd(T value) { - Contract.Assert(m_high < SEGMENT_SIZE - 1); + Debug.Assert(m_high < SEGMENT_SIZE - 1); m_high++; m_array[m_high] = value; m_state[m_high].m_value = true; @@ -737,7 +736,7 @@ namespace System.Collections.Concurrent /// the reference to the new Segment internal Segment UnsafeGrow() { - Contract.Assert(m_high >= SEGMENT_SIZE - 1); + Debug.Assert(m_high >= SEGMENT_SIZE - 1); Segment newSegment = new Segment(m_index + 1, m_source); //m_index is Int64, we don't need to worry about overflow m_next = newSegment; return newSegment; @@ -753,7 +752,7 @@ namespace System.Collections.Concurrent //no CAS is needed, since there is no contention (other threads are blocked, busy waiting) Segment newSegment = new Segment(m_index + 1, m_source); //m_index is Int64, we don't need to worry about overflow m_next = newSegment; - Contract.Assert(m_source.m_tail == this); + Debug.Assert(m_source.m_tail == this); m_source.m_tail = m_next; } @@ -860,7 +859,7 @@ namespace System.Collections.Concurrent { spinLocal.SpinOnce(); } - Contract.Assert(m_source.m_head == this); + Debug.Assert(m_source.m_head == this); m_source.m_head = m_next; } return true; diff --git a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentStack.cs b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentStack.cs index 15d4176..c36d96c 100644 --- a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentStack.cs +++ b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentStack.cs @@ -45,10 +45,6 @@ namespace System.Collections.Concurrent /// [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(SystemCollectionsConcurrent_ProducerConsumerCollectionDebugView<>))] - [HostProtection(Synchronization = true, ExternalThreading = true)] -#if !FEATURE_CORECLR - [Serializable] -#endif //!FEATURE_CORECLR public class ConcurrentStack : IProducerConsumerCollection, IReadOnlyCollection { /// @@ -70,15 +66,8 @@ namespace System.Collections.Concurrent } } -#if !FEATURE_CORECLR - [NonSerialized] -#endif //!FEATURE_CORECLR private volatile Node m_head; // The stack is a singly linked list, and only remembers the head. -#if !FEATURE_CORECLR - private T[] m_serializationArray; // Used for custom serialization. -#endif //!FEATURE_CORECLR - private const int BACKOFF_MAX_YIELDS = 8; // Arbitrary number to cap backoff. /// @@ -101,7 +90,7 @@ namespace System.Collections.Concurrent { if (collection == null) { - throw new ArgumentNullException("collection"); + throw new ArgumentNullException(nameof(collection)); } InitializeFromCollection(collection); } @@ -124,50 +113,6 @@ namespace System.Collections.Concurrent m_head = lastNode; } -#if !FEATURE_CORECLR - /// - /// Get the data array to be serialized - /// - [OnSerializing] - private void OnSerializing(StreamingContext context) - { - // save the data into the serialization array to be saved - m_serializationArray = ToArray(); - } - - /// - /// Construct the stack from a previously seiralized one - /// - [OnDeserialized] - private void OnDeserialized(StreamingContext context) - { - Contract.Assert(m_serializationArray != null); - // Add the elements to our stack. We need to add them from head-to-tail, to - // preserve the original ordering of the stack before serialization. - Node prevNode = null; - Node head = null; - for (int i = 0; i < m_serializationArray.Length; i++) - { - Node currNode = new Node(m_serializationArray[i]); - - if (prevNode == null) - { - head = currNode; - } - else - { - prevNode.m_next = currNode; - } - - prevNode = currNode; - } - - m_head = head; - m_serializationArray = null; - } -#endif //!FEATURE_CORECLR - - /// /// Gets a value that indicates whether the is empty. /// @@ -221,7 +166,6 @@ namespace System.Collections.Concurrent } } - /// /// Gets a value indicating whether access to the is /// synchronized with the SyncRoot. @@ -293,7 +237,7 @@ namespace System.Collections.Concurrent // Validate arguments. if (array == null) { - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); } // We must be careful not to corrupt the array, so we will first accumulate an @@ -327,7 +271,7 @@ namespace System.Collections.Concurrent { if (array == null) { - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); } // We must be careful not to corrupt the array, so we will first accumulate an @@ -379,7 +323,7 @@ namespace System.Collections.Concurrent { if (items == null) { - throw new ArgumentNullException("items"); + throw new ArgumentNullException(nameof(items)); } PushRange(items, 0, items.Length); } @@ -455,13 +399,6 @@ namespace System.Collections.Concurrent } while (Interlocked.CompareExchange( ref m_head, head, tail.m_next) != tail.m_next); - -#if !FEATURE_CORECLR - if (CDSCollectionETWBCLProvider.Log.IsEnabled()) - { - CDSCollectionETWBCLProvider.Log.ConcurrentStack_FastPushFailed(spin.Count); - } -#endif // !FEATURE_CORECLR } /// @@ -471,16 +408,16 @@ namespace System.Collections.Concurrent { if (items == null) { - throw new ArgumentNullException("items"); + throw new ArgumentNullException(nameof(items)); } if (count < 0) { - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ConcurrentStack_PushPopRange_CountOutOfRange")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ConcurrentStack_PushPopRange_CountOutOfRange")); } int length = items.Length; if (startIndex >= length || startIndex < 0) { - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ConcurrentStack_PushPopRange_StartOutOfRange")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ConcurrentStack_PushPopRange_StartOutOfRange")); } if (length - count < startIndex) //instead of (startIndex + count > items.Length) to prevent overflow { @@ -584,7 +521,7 @@ namespace System.Collections.Concurrent { if (items == null) { - throw new ArgumentNullException("items"); + throw new ArgumentNullException(nameof(items)); } return TryPopRange(items, 0, items.Length); @@ -683,12 +620,6 @@ namespace System.Collections.Concurrent // Is the stack empty? if (head == null) { -#if !FEATURE_CORECLR - if (count == 1 && CDSCollectionETWBCLProvider.Log.IsEnabled()) - { - CDSCollectionETWBCLProvider.Log.ConcurrentStack_FastPopFailed(spin.Count); - } -#endif //!FEATURE_CORECLR poppedHead = null; return 0; } @@ -702,12 +633,6 @@ namespace System.Collections.Concurrent // Try to swap the new head. If we succeed, break out of the loop. if (Interlocked.CompareExchange(ref m_head, next.m_next, head) == head) { -#if !FEATURE_CORECLR - if (count == 1 && CDSCollectionETWBCLProvider.Log.IsEnabled()) - { - CDSCollectionETWBCLProvider.Log.ConcurrentStack_FastPopFailed(spin.Count); - } -#endif //!FEATURE_CORECLR // Return the popped Node. poppedHead = head; return nodesCount; diff --git a/src/mscorlib/src/System/Collections/Concurrent/IProducerConsumerCollection.cs b/src/mscorlib/src/System/Collections/Concurrent/IProducerConsumerCollection.cs index a74f690..56be775 100644 --- a/src/mscorlib/src/System/Collections/Concurrent/IProducerConsumerCollection.cs +++ b/src/mscorlib/src/System/Collections/Concurrent/IProducerConsumerCollection.cs @@ -97,7 +97,7 @@ namespace System.Collections.Concurrent { if (collection == null) { - throw new ArgumentNullException("collection"); + throw new ArgumentNullException(nameof(collection)); } m_collection = collection; diff --git a/src/mscorlib/src/System/Collections/Concurrent/OrderablePartitioner.cs b/src/mscorlib/src/System/Collections/Concurrent/OrderablePartitioner.cs index 02263b7..33e3c88 100644 --- a/src/mscorlib/src/System/Collections/Concurrent/OrderablePartitioner.cs +++ b/src/mscorlib/src/System/Collections/Concurrent/OrderablePartitioner.cs @@ -61,7 +61,6 @@ namespace System.Collections.Concurrent /// /// /// - [HostProtection(Synchronization = true, ExternalThreading = true)] public abstract class OrderablePartitioner : Partitioner { /// diff --git a/src/mscorlib/src/System/Collections/Concurrent/Partitioner.cs b/src/mscorlib/src/System/Collections/Concurrent/Partitioner.cs index 3d54c14..0192b19 100644 --- a/src/mscorlib/src/System/Collections/Concurrent/Partitioner.cs +++ b/src/mscorlib/src/System/Collections/Concurrent/Partitioner.cs @@ -44,7 +44,6 @@ namespace System.Collections.Concurrent /// /// /// - [HostProtection(Synchronization = true, ExternalThreading = true)] public abstract class Partitioner { /// diff --git a/src/mscorlib/src/System/Collections/Concurrent/PartitionerStatic.cs b/src/mscorlib/src/System/Collections/Concurrent/PartitionerStatic.cs index 2169c6d..9b36c05 100644 --- a/src/mscorlib/src/System/Collections/Concurrent/PartitionerStatic.cs +++ b/src/mscorlib/src/System/Collections/Concurrent/PartitionerStatic.cs @@ -14,6 +14,7 @@ using System.Collections.Generic; using System.Security.Permissions; using System.Threading; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; @@ -26,9 +27,6 @@ namespace System.Collections.Concurrent /// non-blocking. These behaviors can be overridden via this enumeration. /// [Flags] -#if !FEATURE_CORECLR - [Serializable] -#endif public enum EnumerablePartitionerOptions { /// @@ -71,7 +69,6 @@ namespace System.Collections.Concurrent /// thread. /// /// - [HostProtection(Synchronization = true, ExternalThreading = true)] public static class Partitioner { /// @@ -91,7 +88,7 @@ namespace System.Collections.Concurrent { if (list == null) { - throw new ArgumentNullException("list"); + throw new ArgumentNullException(nameof(list)); } if (loadBalance) { @@ -122,7 +119,7 @@ namespace System.Collections.Concurrent if (array == null) { - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); } if (loadBalance) { @@ -172,11 +169,11 @@ namespace System.Collections.Concurrent { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if ((partitionerOptions & (~EnumerablePartitionerOptions.NoBuffering)) != 0) - throw new ArgumentOutOfRangeException("partitionerOptions"); + throw new ArgumentOutOfRangeException(nameof(partitionerOptions)); return (new DynamicPartitionerForIEnumerable(source, partitionerOptions)); } @@ -194,7 +191,7 @@ namespace System.Collections.Concurrent // load balancing on a busy system if you make it higher than 1. int coreOversubscriptionRate = 3; - if (toExclusive <= fromInclusive) throw new ArgumentOutOfRangeException("toExclusive"); + if (toExclusive <= fromInclusive) throw new ArgumentOutOfRangeException(nameof(toExclusive)); long rangeSize = (toExclusive - fromInclusive) / (PlatformHelper.ProcessorCount * coreOversubscriptionRate); if (rangeSize == 0) rangeSize = 1; @@ -212,8 +209,8 @@ namespace System.Collections.Concurrent /// less than or equal to 0. public static OrderablePartitioner> Create(long fromInclusive, long toExclusive, long rangeSize) { - if (toExclusive <= fromInclusive) throw new ArgumentOutOfRangeException("toExclusive"); - if (rangeSize <= 0) throw new ArgumentOutOfRangeException("rangeSize"); + if (toExclusive <= fromInclusive) throw new ArgumentOutOfRangeException(nameof(toExclusive)); + if (rangeSize <= 0) throw new ArgumentOutOfRangeException(nameof(rangeSize)); return Partitioner.Create(CreateRanges(fromInclusive, toExclusive, rangeSize), EnumerablePartitionerOptions.NoBuffering); // chunk one range at a time } @@ -251,7 +248,7 @@ namespace System.Collections.Concurrent // load balancing on a busy system if you make it higher than 1. int coreOversubscriptionRate = 3; - if (toExclusive <= fromInclusive) throw new ArgumentOutOfRangeException("toExclusive"); + if (toExclusive <= fromInclusive) throw new ArgumentOutOfRangeException(nameof(toExclusive)); int rangeSize = (toExclusive - fromInclusive) / (PlatformHelper.ProcessorCount * coreOversubscriptionRate); if (rangeSize == 0) rangeSize = 1; @@ -269,8 +266,8 @@ namespace System.Collections.Concurrent /// less than or equal to 0. public static OrderablePartitioner> Create(int fromInclusive, int toExclusive, int rangeSize) { - if (toExclusive <= fromInclusive) throw new ArgumentOutOfRangeException("toExclusive"); - if (rangeSize <= 0) throw new ArgumentOutOfRangeException("rangeSize"); + if (toExclusive <= fromInclusive) throw new ArgumentOutOfRangeException(nameof(toExclusive)); + if (rangeSize <= 0) throw new ArgumentOutOfRangeException(nameof(rangeSize)); return Partitioner.Create(CreateRanges(fromInclusive, toExclusive, rangeSize), EnumerablePartitionerOptions.NoBuffering); // chunk one range at a time } @@ -431,7 +428,7 @@ namespace System.Collections.Concurrent //perform deferred allocating of the local variables. if (m_localOffset == null) { - Contract.Assert(m_currentChunkSize == null); + Debug.Assert(m_currentChunkSize == null); m_localOffset = new SharedInt(-1); m_currentChunkSize = new SharedInt(0); m_doublingCountdown = CHUNK_DOUBLING_RATE; @@ -449,7 +446,7 @@ namespace System.Collections.Concurrent { // The second part of the || condition is necessary to handle the case when MoveNext() is called // after a previous MoveNext call returned false. - Contract.Assert(m_localOffset.Value == m_currentChunkSize.Value - 1 || m_currentChunkSize.Value == 0); + Debug.Assert(m_localOffset.Value == m_currentChunkSize.Value - 1 || m_currentChunkSize.Value == 0); //set the requested chunk size to a proper value int requestedChunkSize; @@ -470,11 +467,11 @@ namespace System.Collections.Concurrent // Decrement your doubling countdown m_doublingCountdown--; - Contract.Assert(requestedChunkSize > 0 && requestedChunkSize <= m_maxChunkSize); + Debug.Assert(requestedChunkSize > 0 && requestedChunkSize <= m_maxChunkSize); //GrabNextChunk will update the value of m_currentChunkSize if (GrabNextChunk(requestedChunkSize)) { - Contract.Assert(m_currentChunkSize.Value <= requestedChunkSize && m_currentChunkSize.Value > 0); + Debug.Assert(m_currentChunkSize.Value <= requestedChunkSize && m_currentChunkSize.Value > 0); m_localOffset.Value = 0; return true; } @@ -517,7 +514,7 @@ namespace System.Collections.Concurrent { if (partitionCount <= 0) { - throw new ArgumentOutOfRangeException("partitionCount"); + throw new ArgumentOutOfRangeException(nameof(partitionCount)); } IEnumerator>[] partitions = new IEnumerator>[partitionCount]; @@ -715,10 +712,10 @@ namespace System.Collections.Concurrent /// internal bool GrabChunk_Single(KeyValuePair[] destArray, int requestedChunkSize, ref int actualNumElementsGrabbed) { - Contract.Assert(m_useSingleChunking, "Expected m_useSingleChecking to be true"); - Contract.Assert(requestedChunkSize == 1, "Got requested chunk size of " + requestedChunkSize + " when single-chunking was on"); - Contract.Assert(actualNumElementsGrabbed == 0, "Expected actualNumElementsGrabbed == 0, instead it is " + actualNumElementsGrabbed); - Contract.Assert(destArray.Length == 1, "Expected destArray to be of length 1, instead its length is " + destArray.Length); + Debug.Assert(m_useSingleChunking, "Expected m_useSingleChecking to be true"); + Debug.Assert(requestedChunkSize == 1, "Got requested chunk size of " + requestedChunkSize + " when single-chunking was on"); + Debug.Assert(actualNumElementsGrabbed == 0, "Expected actualNumElementsGrabbed == 0, instead it is " + actualNumElementsGrabbed); + Debug.Assert(destArray.Length == 1, "Expected destArray to be of length 1, instead its length is " + destArray.Length); lock (m_sharedLock) { @@ -764,8 +761,8 @@ namespace System.Collections.Concurrent /// internal bool GrabChunk_Buffered(KeyValuePair[] destArray, int requestedChunkSize, ref int actualNumElementsGrabbed) { - Contract.Assert(requestedChunkSize > 0); - Contract.Assert(!m_useSingleChunking, "Did not expect to be in single-chunking mode"); + Debug.Assert(requestedChunkSize > 0); + Debug.Assert(!m_useSingleChunking, "Did not expect to be in single-chunking mode"); TryCopyFromFillBuffer(destArray, requestedChunkSize, ref actualNumElementsGrabbed); @@ -803,7 +800,7 @@ namespace System.Collections.Concurrent while( m_activeCopiers > 0) sw.SpinOnce(); } - Contract.Assert(m_sharedIndex != null); //already been allocated in MoveNext() before calling GrabNextChunk + Debug.Assert(m_sharedIndex != null); //already been allocated in MoveNext() before calling GrabNextChunk // Now's the time to actually enumerate the source @@ -940,7 +937,7 @@ namespace System.Collections.Concurrent /// override protected bool GrabNextChunk(int requestedChunkSize) { - Contract.Assert(requestedChunkSize > 0); + Debug.Assert(requestedChunkSize > 0); if (HasNoElementsLeft) { @@ -973,8 +970,8 @@ namespace System.Collections.Concurrent { //we only set it from false to true once //we should never set it back in any circumstances - Contract.Assert(value); - Contract.Assert(!m_hasNoElementsLeft.Value); + Debug.Assert(value); + Debug.Assert(!m_hasNoElementsLeft.Value); m_hasNoElementsLeft.Value = true; } } @@ -988,8 +985,8 @@ namespace System.Collections.Concurrent { throw new InvalidOperationException(Environment.GetResourceString("PartitionerStatic_CurrentCalledBeforeMoveNext")); } - Contract.Assert(m_localList != null); - Contract.Assert(m_localOffset.Value >= 0 && m_localOffset.Value < m_currentChunkSize.Value); + Debug.Assert(m_localList != null); + Debug.Assert(m_localOffset.Value >= 0 && m_localOffset.Value < m_currentChunkSize.Value); return (m_localList[m_localOffset.Value]); } } @@ -1053,7 +1050,7 @@ namespace System.Collections.Concurrent { if (partitionCount <= 0) { - throw new ArgumentOutOfRangeException("partitionCount"); + throw new ArgumentOutOfRangeException(nameof(partitionCount)); } IEnumerator>[] partitions = new IEnumerator>[partitionCount]; @@ -1127,11 +1124,11 @@ namespace System.Collections.Concurrent /// override protected bool GrabNextChunk(int requestedChunkSize) { - Contract.Assert(requestedChunkSize > 0); + Debug.Assert(requestedChunkSize > 0); while (!HasNoElementsLeft) { - Contract.Assert(m_sharedIndex != null); + Debug.Assert(m_sharedIndex != null); // use the new Volatile.Read method because it is cheaper than Interlocked.Read on AMD64 architecture long oldSharedIndex = Volatile.Read(ref m_sharedIndex.Value); @@ -1173,13 +1170,13 @@ namespace System.Collections.Concurrent { get { - Contract.Assert(m_sharedIndex != null); + Debug.Assert(m_sharedIndex != null); // use the new Volatile.Read method because it is cheaper than Interlocked.Read on AMD64 architecture return Volatile.Read(ref m_sharedIndex.Value) >= SourceCount - 1; } set { - Contract.Assert(false); + Debug.Assert(false); } } @@ -1268,7 +1265,7 @@ namespace System.Collections.Concurrent throw new InvalidOperationException(Environment.GetResourceString("PartitionerStatic_CurrentCalledBeforeMoveNext")); } - Contract.Assert(m_localOffset.Value >= 0 && m_localOffset.Value < m_currentChunkSize.Value); + Debug.Assert(m_localOffset.Value >= 0 && m_localOffset.Value < m_currentChunkSize.Value); return new KeyValuePair(m_startIndex + m_localOffset.Value, m_sharedReader[m_startIndex + m_localOffset.Value]); } @@ -1352,7 +1349,7 @@ namespace System.Collections.Concurrent throw new InvalidOperationException(Environment.GetResourceString("PartitionerStatic_CurrentCalledBeforeMoveNext")); } - Contract.Assert(m_localOffset.Value >= 0 && m_localOffset.Value < m_currentChunkSize.Value); + Debug.Assert(m_localOffset.Value >= 0 && m_localOffset.Value < m_currentChunkSize.Value); return new KeyValuePair(m_startIndex + m_localOffset.Value, m_sharedReader[m_startIndex + m_localOffset.Value]); } @@ -1417,7 +1414,7 @@ namespace System.Collections.Concurrent { if (partitionCount <= 0) { - throw new ArgumentOutOfRangeException("partitionCount"); + throw new ArgumentOutOfRangeException(nameof(partitionCount)); } int quotient, remainder; @@ -1539,7 +1536,7 @@ namespace System.Collections.Concurrent internal StaticIndexRangePartitionerForIList(IList list) : base() { - Contract.Assert(list != null); + Debug.Assert(list != null); m_list = list; } override protected int SourceCount @@ -1565,7 +1562,7 @@ namespace System.Collections.Concurrent internal StaticIndexRangePartitionForIList(IList list, int startIndex, int endIndex) : base(startIndex, endIndex) { - Contract.Assert(startIndex >= 0 && endIndex <= list.Count - 1); + Debug.Assert(startIndex >= 0 && endIndex <= list.Count - 1); m_list = list; } @@ -1579,7 +1576,7 @@ namespace System.Collections.Concurrent throw new InvalidOperationException(Environment.GetResourceString("PartitionerStatic_CurrentCalledBeforeMoveNext")); } - Contract.Assert(m_offset >= m_startIndex && m_offset <= m_endIndex); + Debug.Assert(m_offset >= m_startIndex && m_offset <= m_endIndex); return (new KeyValuePair(m_offset, m_list[m_offset])); } } @@ -1597,7 +1594,7 @@ namespace System.Collections.Concurrent internal StaticIndexRangePartitionerForArray(TSource[] array) : base() { - Contract.Assert(array != null); + Debug.Assert(array != null); m_array = array; } override protected int SourceCount @@ -1622,7 +1619,7 @@ namespace System.Collections.Concurrent internal StaticIndexRangePartitionForArray(TSource[] array, int startIndex, int endIndex) : base(startIndex, endIndex) { - Contract.Assert(startIndex >= 0 && endIndex <= array.Length - 1); + Debug.Assert(startIndex >= 0 && endIndex <= array.Length - 1); m_array = array; } @@ -1636,7 +1633,7 @@ namespace System.Collections.Concurrent throw new InvalidOperationException(Environment.GetResourceString("PartitionerStatic_CurrentCalledBeforeMoveNext")); } - Contract.Assert(m_offset >= m_startIndex && m_offset <= m_endIndex); + Debug.Assert(m_offset >= m_startIndex && m_offset <= m_endIndex); return (new KeyValuePair(m_offset, m_array[m_offset])); } } @@ -1704,30 +1701,15 @@ namespace System.Collections.Concurrent if (typeof(TSource).IsValueType) { -#if !FEATURE_CORECLR // Marshal.SizeOf is not supported in CoreCLR - - if (typeof(TSource).StructLayoutAttribute.Value == LayoutKind.Explicit) - { - chunkSize = Math.Max(1, DEFAULT_BYTES_PER_CHUNK / Marshal.SizeOf(typeof(TSource))); - } - else - { - // We choose '128' because this ensures, no matter the actual size of the value type, - // the total bytes used will be a multiple of 128. This ensures it's cache aligned. - chunkSize = 128; - } -#else chunkSize = 128; -#endif } else { - Contract.Assert((DEFAULT_BYTES_PER_CHUNK % IntPtr.Size) == 0, "bytes per chunk should be a multiple of pointer size"); + Debug.Assert((DEFAULT_BYTES_PER_CHUNK % IntPtr.Size) == 0, "bytes per chunk should be a multiple of pointer size"); chunkSize = (DEFAULT_BYTES_PER_CHUNK / IntPtr.Size); } return chunkSize; } #endregion - } } diff --git a/src/mscorlib/src/System/Collections/DictionaryEntry.cs b/src/mscorlib/src/System/Collections/DictionaryEntry.cs index fc1d57f..3ee392b 100644 --- a/src/mscorlib/src/System/Collections/DictionaryEntry.cs +++ b/src/mscorlib/src/System/Collections/DictionaryEntry.cs @@ -51,5 +51,12 @@ namespace System.Collections { _value = value; } } + + // BLOCKED (do not add now): [EditorBrowsable(EditorBrowsableState.Never)] + public void Deconstruct(out object key, out object value) + { + key = Key; + value = Value; + } } } diff --git a/src/mscorlib/src/System/Collections/EmptyReadOnlyDictionaryInternal.cs b/src/mscorlib/src/System/Collections/EmptyReadOnlyDictionaryInternal.cs index 6e28493..a610fce 100644 --- a/src/mscorlib/src/System/Collections/EmptyReadOnlyDictionaryInternal.cs +++ b/src/mscorlib/src/System/Collections/EmptyReadOnlyDictionaryInternal.cs @@ -36,16 +36,16 @@ namespace System.Collections { public void CopyTo(Array array, int index) { if (array==null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); if (array.Rank != 1) throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported")); if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if ( array.Length - index < this.Count ) - throw new ArgumentException( Environment.GetResourceString("ArgumentOutOfRange_Index"), "index"); + throw new ArgumentException( Environment.GetResourceString("ArgumentOutOfRange_Index"), nameof(index)); Contract.EndContractBlock(); // the actual copy is a NOP @@ -74,21 +74,21 @@ namespace System.Collections { public Object this[Object key] { get { if (key == null) { - throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key")); + throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key")); } Contract.EndContractBlock(); return null; } set { if (key == null) { - throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key")); + throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key")); } if (!key.GetType().IsSerializable) - throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "key"); + throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), nameof(key)); if( (value != null) && (!value.GetType().IsSerializable ) ) - throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "value"); + throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), nameof(value)); Contract.EndContractBlock(); throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); @@ -113,14 +113,14 @@ namespace System.Collections { public void Add(Object key, Object value) { if (key == null) { - throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key")); + throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key")); } if (!key.GetType().IsSerializable) - throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "key" ); + throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), nameof(key) ); if( (value != null) && (!value.GetType().IsSerializable) ) - throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "value"); + throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), nameof(value)); Contract.EndContractBlock(); throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); diff --git a/src/mscorlib/src/System/Collections/Generic/ArraySortHelper.cs b/src/mscorlib/src/System/Collections/Generic/ArraySortHelper.cs index b2fed9d..298ac3e 100644 --- a/src/mscorlib/src/System/Collections/Generic/ArraySortHelper.cs +++ b/src/mscorlib/src/System/Collections/Generic/ArraySortHelper.cs @@ -17,6 +17,7 @@ namespace System.Collections.Generic using System; using System.Globalization; using System.Runtime.CompilerServices; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.Versioning; @@ -49,16 +50,7 @@ namespace System.Collections.Generic } internal static void ThrowOrIgnoreBadComparer(Object comparer) { - // This is hit when an invarant of QuickSort is violated due to a bad IComparer implementation (for - // example, imagine an IComparer that returns 0 when items are equal but -1 all other times). - // - // We could have thrown this exception on v4, but due to changes in v4.5 around how we partition arrays - // there are different sets of input where we would throw this exception. In order to reduce overall risk from - // an app compat persective, we're changing to never throw on v4. Instead, we'll return with a partially - // sorted array. - if(BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) { - throw new ArgumentException(Environment.GetResourceString("Arg_BogusIComparer", comparer)); - } + throw new ArgumentException(Environment.GetResourceString("Arg_BogusIComparer", comparer)); } } @@ -81,7 +73,6 @@ namespace System.Collections.Generic } } - [System.Security.SecuritySafeCritical] // auto-generated private static IArraySortHelper CreateArraySortHelper() { if (typeof(IComparable).IsAssignableFrom(typeof(T))) @@ -99,8 +90,8 @@ namespace System.Collections.Generic public void Sort(T[] keys, int index, int length, IComparer comparer) { - Contract.Assert(keys != null, "Check the arguments in the caller!"); - Contract.Assert( index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!"); + Debug.Assert(keys != null, "Check the arguments in the caller!"); + Debug.Assert( index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!"); // Add a try block here to detect IComparers (or their // underlying IComparables, etc) that are bogus. @@ -111,22 +102,7 @@ namespace System.Collections.Generic comparer = Comparer.Default; } -#if FEATURE_CORECLR - // Since QuickSort and IntrospectiveSort produce different sorting sequence for equal keys the upgrade - // to IntrospectiveSort was quirked. However since the phone builds always shipped with the new sort aka - // IntrospectiveSort and we would want to continue using this sort moving forward CoreCLR always uses the new sort. - - IntrospectiveSort(keys, index, length, comparer); -#else - if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) - { - IntrospectiveSort(keys, index, length, comparer); - } - else - { - DepthLimitedQuickSort(keys, index, length + index - 1, comparer, IntrospectiveSortUtilities.QuickSortDepthThreshold); - } -#endif + IntrospectiveSort(keys, index, length, comparer.Compare); } catch (IndexOutOfRangeException) { @@ -157,6 +133,27 @@ namespace System.Collections.Generic #endregion + internal static void Sort(T[] keys, int index, int length, Comparison comparer) + { + Debug.Assert(keys != null, "Check the arguments in the caller!"); + Debug.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!"); + Debug.Assert(comparer != null, "Check the arguments in the caller!"); + + // Add a try block here to detect bogus comparisons + try + { + IntrospectiveSort(keys, index, length, comparer); + } + catch (IndexOutOfRangeException) + { + IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer); + } + catch (Exception e) + { + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_IComparerFailed"), e); + } + } + internal static int InternalBinarySearch(T[] array, int index, int length, T value, IComparer comparer) { Contract.Requires(array != null, "Check the arguments in the caller!"); @@ -183,11 +180,11 @@ namespace System.Collections.Generic return ~lo; } - private static void SwapIfGreater(T[] keys, IComparer comparer, int a, int b) + private static void SwapIfGreater(T[] keys, Comparison comparer, int a, int b) { if (a != b) { - if (comparer.Compare(keys[a], keys[b]) > 0) + if (comparer(keys[a], keys[b]) > 0) { T key = keys[a]; keys[a] = keys[b]; @@ -198,7 +195,7 @@ namespace System.Collections.Generic private static void Swap(T[] a, int i, int j) { - if(i != j) + if (i != j) { T t = a[i]; a[i] = a[j]; @@ -206,63 +203,7 @@ namespace System.Collections.Generic } } - internal static void DepthLimitedQuickSort(T[] keys, int left, int right, IComparer comparer, int depthLimit) - { - do - { - if (depthLimit == 0) - { - Heapsort(keys, left, right, comparer); - return; - } - - int i = left; - int j = right; - - // pre-sort the low, middle (pivot), and high values in place. - // this improves performance in the face of already sorted data, or - // data that is made up of multiple sorted runs appended together. - int middle = i + ((j - i) >> 1); - SwapIfGreater(keys, comparer, i, middle); // swap the low with the mid point - SwapIfGreater(keys, comparer, i, j); // swap the low with the high - SwapIfGreater(keys, comparer, middle, j); // swap the middle with the high - - T x = keys[middle]; - do - { - while (comparer.Compare(keys[i], x) < 0) i++; - while (comparer.Compare(x, keys[j]) < 0) j--; - Contract.Assert(i >= left && j <= right, "(i>=left && j<=right) Sort failed - Is your IComparer bogus?"); - if (i > j) break; - if (i < j) - { - T key = keys[i]; - keys[i] = keys[j]; - keys[j] = key; - } - i++; - j--; - } while (i <= j); - - // The next iteration of the while loop is to "recursively" sort the larger half of the array and the - // following calls recursively sort the smaller half. So we subtract one from depthLimit here so - // both sorts see the new value. - depthLimit--; - - if (j - left <= right - i) - { - if (left < j) DepthLimitedQuickSort(keys, left, j, comparer, depthLimit); - left = i; - } - else - { - if (i < right) DepthLimitedQuickSort(keys, i, right, comparer, depthLimit); - right = j; - } - } while (left < right); - } - - internal static void IntrospectiveSort(T[] keys, int left, int length, IComparer comparer) + internal static void IntrospectiveSort(T[] keys, int left, int length, Comparison comparer) { Contract.Requires(keys != null); Contract.Requires(comparer != null); @@ -277,7 +218,7 @@ namespace System.Collections.Generic IntroSort(keys, left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2(keys.Length), comparer); } - private static void IntroSort(T[] keys, int lo, int hi, int depthLimit, IComparer comparer) + private static void IntroSort(T[] keys, int lo, int hi, int depthLimit, Comparison comparer) { Contract.Requires(keys != null); Contract.Requires(comparer != null); @@ -324,7 +265,7 @@ namespace System.Collections.Generic } } - private static int PickPivotAndPartition(T[] keys, int lo, int hi, IComparer comparer) + private static int PickPivotAndPartition(T[] keys, int lo, int hi, Comparison comparer) { Contract.Requires(keys != null); Contract.Requires(comparer != null); @@ -347,8 +288,8 @@ namespace System.Collections.Generic while (left < right) { - while (comparer.Compare(keys[++left], pivot) < 0) ; - while (comparer.Compare(pivot, keys[--right]) < 0) ; + while (comparer(keys[++left], pivot) < 0) ; + while (comparer(pivot, keys[--right]) < 0) ; if (left >= right) break; @@ -361,7 +302,7 @@ namespace System.Collections.Generic return left; } - private static void Heapsort(T[] keys, int lo, int hi, IComparer comparer) + private static void Heapsort(T[] keys, int lo, int hi, Comparison comparer) { Contract.Requires(keys != null); Contract.Requires(comparer != null); @@ -381,7 +322,7 @@ namespace System.Collections.Generic } } - private static void DownHeap(T[] keys, int i, int n, int lo, IComparer comparer) + private static void DownHeap(T[] keys, int i, int n, int lo, Comparison comparer) { Contract.Requires(keys != null); Contract.Requires(comparer != null); @@ -393,11 +334,11 @@ namespace System.Collections.Generic while (i <= n / 2) { child = 2 * i; - if (child < n && comparer.Compare(keys[lo + child - 1], keys[lo + child]) < 0) + if (child < n && comparer(keys[lo + child - 1], keys[lo + child]) < 0) { child++; } - if (!(comparer.Compare(d, keys[lo + child - 1]) < 0)) + if (!(comparer(d, keys[lo + child - 1]) < 0)) break; keys[lo + i - 1] = keys[lo + child - 1]; i = child; @@ -405,7 +346,7 @@ namespace System.Collections.Generic keys[lo + i - 1] = d; } - private static void InsertionSort(T[] keys, int lo, int hi, IComparer comparer) + private static void InsertionSort(T[] keys, int lo, int hi, Comparison comparer) { Contract.Requires(keys != null); Contract.Requires(lo >= 0); @@ -418,7 +359,7 @@ namespace System.Collections.Generic { j = i; t = keys[i + 1]; - while (j >= lo && comparer.Compare(t, keys[j]) < 0) + while (j >= lo && comparer(t, keys[j]) < 0) { keys[j + 1] = keys[j]; j--; @@ -439,49 +380,18 @@ namespace System.Collections.Generic public void Sort(T[] keys, int index, int length, IComparer comparer) { - Contract.Assert(keys != null, "Check the arguments in the caller!"); - Contract.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!"); + Debug.Assert(keys != null, "Check the arguments in the caller!"); + Debug.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!"); try { - if (comparer == null || comparer == Comparer.Default) { - -#if FEATURE_CORECLR - // Since QuickSort and IntrospectiveSort produce different sorting sequence for equal keys the upgrade - // to IntrospectiveSort was quirked. However since the phone builds always shipped with the new sort aka - // IntrospectiveSort and we would want to continue using this sort moving forward CoreCLR always uses the new sort. - + if (comparer == null || comparer == Comparer.Default) + { IntrospectiveSort(keys, index, length); -#else - // call the faster version of our sort algorithm if the user doesn't provide a comparer - if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) - { - IntrospectiveSort(keys, index, length); - } - else - { - DepthLimitedQuickSort(keys, index, length + index - 1, IntrospectiveSortUtilities.QuickSortDepthThreshold); - } -#endif } else { -#if FEATURE_CORECLR - // Since QuickSort and IntrospectiveSort produce different sorting sequence for equal keys the upgrade - // to IntrospectiveSort was quirked. However since the phone builds always shipped with the new sort aka - // IntrospectiveSort and we would want to continue using this sort moving forward CoreCLR always uses the new sort. - - ArraySortHelper.IntrospectiveSort(keys, index, length, comparer); -#else - if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) - { - ArraySortHelper.IntrospectiveSort(keys, index, length, comparer); - } - else - { - ArraySortHelper.DepthLimitedQuickSort(keys, index, length + index - 1, comparer, IntrospectiveSortUtilities.QuickSortDepthThreshold); - } -#endif + ArraySortHelper.IntrospectiveSort(keys, index, length, comparer.Compare); } } catch (IndexOutOfRangeException) @@ -496,8 +406,8 @@ namespace System.Collections.Generic public int BinarySearch(T[] array, int index, int length, T value, IComparer comparer) { - Contract.Assert(array != null, "Check the arguments in the caller!"); - Contract.Assert(index >= 0 && length >= 0 && (array.Length - index >= length), "Check the arguments in the caller!"); + Debug.Assert(array != null, "Check the arguments in the caller!"); + Debug.Assert(index >= 0 && length >= 0 && (array.Length - index >= length), "Check the arguments in the caller!"); try { @@ -583,78 +493,6 @@ namespace System.Collections.Generic } } - private static void DepthLimitedQuickSort(T[] keys, int left, int right, int depthLimit) - { - Contract.Requires(keys != null); - Contract.Requires(0 <= left && left < keys.Length); - Contract.Requires(0 <= right && right < keys.Length); - - // The code in this function looks very similar to QuickSort in ArraySortHelper class. - // The difference is that T is constrainted to IComparable here. - // So the IL code will be different. This function is faster than the one in ArraySortHelper. - - do - { - if (depthLimit == 0) - { - Heapsort(keys, left, right); - return; - } - - int i = left; - int j = right; - - // pre-sort the low, middle (pivot), and high values in place. - // this improves performance in the face of already sorted data, or - // data that is made up of multiple sorted runs appended together. - int middle = i + ((j - i) >> 1); - SwapIfGreaterWithItems(keys, i, middle); // swap the low with the mid point - SwapIfGreaterWithItems(keys, i, j); // swap the low with the high - SwapIfGreaterWithItems(keys, middle, j); // swap the middle with the high - - T x = keys[middle]; - do - { - if (x == null) - { - // if x null, the loop to find two elements to be switched can be reduced. - while (keys[j] != null) j--; - } - else - { - while (x.CompareTo(keys[i]) > 0) i++; - while (x.CompareTo(keys[j]) < 0) j--; - } - Contract.Assert(i >= left && j <= right, "(i>=left && j<=right) Sort failed - Is your IComparer bogus?"); - if (i > j) break; - if (i < j) - { - T key = keys[i]; - keys[i] = keys[j]; - keys[j] = key; - } - i++; - j--; - } while (i <= j); - - // The next iteration of the while loop is to "recursively" sort the larger half of the array and the - // following calls recursively sort the smaller half. So we subtract one from depthLimit here so - // both sorts see the new value. - depthLimit--; - - if (j - left <= right - i) - { - if (left < j) DepthLimitedQuickSort(keys, left, j, depthLimit); - left = i; - } - else - { - if (i < right) DepthLimitedQuickSort(keys, i, right, depthLimit); - right = j; - } - } while (left < right); - } - internal static void IntrospectiveSort(T[] keys, int left, int length) { Contract.Requires(keys != null); @@ -824,7 +662,7 @@ namespace System.Collections.Generic } } - #endregion +#endregion #region ArraySortHelper for paired key and value arrays @@ -851,7 +689,6 @@ namespace System.Collections.Generic } } - [System.Security.SecuritySafeCritical] // auto-generated private static IArraySortHelper CreateArraySortHelper() { if (typeof(IComparable).IsAssignableFrom(typeof(TKey))) @@ -867,8 +704,8 @@ namespace System.Collections.Generic public void Sort(TKey[] keys, TValue[] values, int index, int length, IComparer comparer) { - Contract.Assert(keys != null, "Check the arguments in the caller!"); // Precondition on interface method - Contract.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!"); + Debug.Assert(keys != null, "Check the arguments in the caller!"); // Precondition on interface method + Debug.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!"); // Add a try block here to detect IComparers (or their // underlying IComparables, etc) that are bogus. @@ -879,22 +716,7 @@ namespace System.Collections.Generic comparer = Comparer.Default; } -#if FEATURE_CORECLR - // Since QuickSort and IntrospectiveSort produce different sorting sequence for equal keys the upgrade - // to IntrospectiveSort was quirked. However since the phone builds always shipped with the new sort aka - // IntrospectiveSort and we would want to continue using this sort moving forward CoreCLR always uses the new sort. - IntrospectiveSort(keys, values, index, length, comparer); -#else - if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) - { - IntrospectiveSort(keys, values, index, length, comparer); - } - else - { - DepthLimitedQuickSort(keys, values, index, length + index - 1, comparer, IntrospectiveSortUtilities.QuickSortDepthThreshold); - } -#endif } catch (IndexOutOfRangeException) { @@ -947,68 +769,6 @@ namespace System.Collections.Generic } } - internal static void DepthLimitedQuickSort(TKey[] keys, TValue[] values, int left, int right, IComparer comparer, int depthLimit) - { - do - { - if (depthLimit == 0) - { - Heapsort(keys, values, left, right, comparer); - return; - } - - int i = left; - int j = right; - - // pre-sort the low, middle (pivot), and high values in place. - // this improves performance in the face of already sorted data, or - // data that is made up of multiple sorted runs appended together. - int middle = i + ((j - i) >> 1); - SwapIfGreaterWithItems(keys, values, comparer, i, middle); // swap the low with the mid point - SwapIfGreaterWithItems(keys, values, comparer, i, j); // swap the low with the high - SwapIfGreaterWithItems(keys, values, comparer, middle, j); // swap the middle with the high - - TKey x = keys[middle]; - do - { - while (comparer.Compare(keys[i], x) < 0) i++; - while (comparer.Compare(x, keys[j]) < 0) j--; - Contract.Assert(i >= left && j <= right, "(i>=left && j<=right) Sort failed - Is your IComparer bogus?"); - if (i > j) break; - if (i < j) - { - TKey key = keys[i]; - keys[i] = keys[j]; - keys[j] = key; - if (values != null) - { - TValue value = values[i]; - values[i] = values[j]; - values[j] = value; - } - } - i++; - j--; - } while (i <= j); - - // The next iteration of the while loop is to "recursively" sort the larger half of the array and the - // following calls recursively sort the smaller half. So we subtract one from depthLimit here so - // both sorts see the new value. - depthLimit--; - - if (j - left <= right - i) - { - if (left < j) DepthLimitedQuickSort(keys, values, left, j, comparer, depthLimit); - left = i; - } - else - { - if (i < right) DepthLimitedQuickSort(keys, values, i, right, comparer, depthLimit); - right = j; - } - } while (left < right); - } - internal static void IntrospectiveSort(TKey[] keys, TValue[] values, int left, int length, IComparer comparer) { Contract.Requires(keys != null); @@ -1199,8 +959,8 @@ namespace System.Collections.Generic { public void Sort(TKey[] keys, TValue[] values, int index, int length, IComparer comparer) { - Contract.Assert(keys != null, "Check the arguments in the caller!"); - Contract.Assert( index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!"); + Debug.Assert(keys != null, "Check the arguments in the caller!"); + Debug.Assert( index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!"); // Add a try block here to detect IComparers (or their // underlying IComparables, etc) that are bogus. @@ -1208,44 +968,12 @@ namespace System.Collections.Generic { if (comparer == null || comparer == Comparer.Default) { -#if FEATURE_CORECLR - // Since QuickSort and IntrospectiveSort produce different sorting sequence for equal keys the upgrade - // to IntrospectiveSort was quirked. However since the phone builds always shipped with the new sort aka - // IntrospectiveSort and we would want to continue using this sort moving forward CoreCLR always uses the new sort. - IntrospectiveSort(keys, values, index, length); -#else - // call the faster version of our sort algorithm if the user doesn't provide a comparer - if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) - { - IntrospectiveSort(keys, values, index, length); - } - else - { - DepthLimitedQuickSort(keys, values, index, length + index - 1, IntrospectiveSortUtilities.QuickSortDepthThreshold); - } -#endif } else { -#if FEATURE_CORECLR - // Since QuickSort and IntrospectiveSort produce different sorting sequence for equal keys the upgrade - // to IntrospectiveSort was quirked. However since the phone builds always shipped with the new sort aka - // IntrospectiveSort and we would want to continue using this sort moving forward CoreCLR always uses the new sort. - ArraySortHelper.IntrospectiveSort(keys, values, index, length, comparer); -#else - if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) - { - ArraySortHelper.IntrospectiveSort(keys, values, index, length, comparer); - } - else - { - ArraySortHelper.DepthLimitedQuickSort(keys, values, index, length + index - 1, comparer, IntrospectiveSortUtilities.QuickSortDepthThreshold); - } -#endif } - } catch (IndexOutOfRangeException) { @@ -1292,80 +1020,6 @@ namespace System.Collections.Generic } } - private static void DepthLimitedQuickSort(TKey[] keys, TValue[] values, int left, int right, int depthLimit) - { - // The code in this function looks very similar to QuickSort in ArraySortHelper class. - // The difference is that T is constrainted to IComparable here. - // So the IL code will be different. This function is faster than the one in ArraySortHelper. - - do - { - if (depthLimit == 0) - { - Heapsort(keys, values, left, right); - return; - } - - int i = left; - int j = right; - - // pre-sort the low, middle (pivot), and high values in place. - // this improves performance in the face of already sorted data, or - // data that is made up of multiple sorted runs appended together. - int middle = i + ((j - i) >> 1); - SwapIfGreaterWithItems(keys, values, i, middle); // swap the low with the mid point - SwapIfGreaterWithItems(keys, values, i, j); // swap the low with the high - SwapIfGreaterWithItems(keys, values, middle, j); // swap the middle with the high - - TKey x = keys[middle]; - do - { - if (x == null) - { - // if x null, the loop to find two elements to be switched can be reduced. - while (keys[j] != null) j--; - } - else - { - while (x.CompareTo(keys[i]) > 0) i++; - while (x.CompareTo(keys[j]) < 0) j--; - } - Contract.Assert(i >= left && j <= right, "(i>=left && j<=right) Sort failed - Is your IComparer bogus?"); - if (i > j) break; - if (i < j) - { - TKey key = keys[i]; - keys[i] = keys[j]; - keys[j] = key; - if (values != null) - { - TValue value = values[i]; - values[i] = values[j]; - values[j] = value; - } - } - i++; - j--; - } while (i <= j); - - // The next iteration of the while loop is to "recursively" sort the larger half of the array and the - // following calls recursively sort the smaller half. So we subtract one from depthLimit here so - // both sorts see the new value. - depthLimit--; - - if (j - left <= right - i) - { - if (left < j) DepthLimitedQuickSort(keys, values, left, j, depthLimit); - left = i; - } - else - { - if (i < right) DepthLimitedQuickSort(keys, values, i, right, depthLimit); - right = j; - } - } while (left < right); - } - internal static void IntrospectiveSort(TKey[] keys, TValue[] values, int left, int length) { Contract.Requires(keys != null); @@ -1554,5 +1208,3 @@ namespace System.Collections.Generic #endregion } - - diff --git a/src/mscorlib/src/System/Collections/Generic/Comparer.cs b/src/mscorlib/src/System/Collections/Generic/Comparer.cs index 9f1a8bf..4f06b0a 100644 --- a/src/mscorlib/src/System/Collections/Generic/Comparer.cs +++ b/src/mscorlib/src/System/Collections/Generic/Comparer.cs @@ -7,6 +7,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; //using System.Globalization; using System.Runtime.CompilerServices; @@ -33,7 +34,7 @@ namespace System.Collections.Generic Contract.Ensures(Contract.Result>() != null); if (comparison == null) - throw new ArgumentNullException("comparison"); + throw new ArgumentNullException(nameof(comparison)); return new ComparisonComparer(comparison); } @@ -42,7 +43,6 @@ namespace System.Collections.Generic // Note that logic in this method is replicated in vm\compile.cpp to ensure that NGen // saves the right instantiations // - [System.Security.SecuritySafeCritical] // auto-generated private static Comparer CreateComparer() { object result = null; @@ -139,7 +139,7 @@ namespace System.Collections.Generic [Serializable] internal sealed class NullableComparer : Comparer where T : struct, IComparable { - public override int Compare(Nullable x, Nullable y) { + public override int Compare(T? x, T? y) { if (x.HasValue) { if (y.HasValue) return x.value.CompareTo(y.value); return 1; @@ -196,7 +196,7 @@ namespace System.Collections.Generic { public Int32EnumComparer() { - Contract.Assert(typeof(T).IsEnum, "This type is only intended to be used to compare enums!"); + Debug.Assert(typeof(T).IsEnum, "This type is only intended to be used to compare enums!"); } // Used by the serialization engine. @@ -216,7 +216,6 @@ namespace System.Collections.Generic public override int GetHashCode() => GetType().GetHashCode(); - [SecurityCritical] public void GetObjectData(SerializationInfo info, StreamingContext context) { // Previously Comparer was not specialized for enums, @@ -232,7 +231,7 @@ namespace System.Collections.Generic { public UInt32EnumComparer() { - Contract.Assert(typeof(T).IsEnum, "This type is only intended to be used to compare enums!"); + Debug.Assert(typeof(T).IsEnum, "This type is only intended to be used to compare enums!"); } // Used by the serialization engine. @@ -252,7 +251,6 @@ namespace System.Collections.Generic public override int GetHashCode() => GetType().GetHashCode(); - [SecurityCritical] public void GetObjectData(SerializationInfo info, StreamingContext context) { info.SetType(typeof(ObjectComparer)); @@ -264,7 +262,7 @@ namespace System.Collections.Generic { public Int64EnumComparer() { - Contract.Assert(typeof(T).IsEnum, "This type is only intended to be used to compare enums!"); + Debug.Assert(typeof(T).IsEnum, "This type is only intended to be used to compare enums!"); } // Used by the serialization engine. @@ -284,7 +282,6 @@ namespace System.Collections.Generic public override int GetHashCode() => GetType().GetHashCode(); - [SecurityCritical] public void GetObjectData(SerializationInfo info, StreamingContext context) { info.SetType(typeof(ObjectComparer)); @@ -296,7 +293,7 @@ namespace System.Collections.Generic { public UInt64EnumComparer() { - Contract.Assert(typeof(T).IsEnum, "This type is only intended to be used to compare enums!"); + Debug.Assert(typeof(T).IsEnum, "This type is only intended to be used to compare enums!"); } // Used by the serialization engine. @@ -316,7 +313,6 @@ namespace System.Collections.Generic public override int GetHashCode() => GetType().GetHashCode(); - [SecurityCritical] public void GetObjectData(SerializationInfo info, StreamingContext context) { info.SetType(typeof(ObjectComparer)); diff --git a/src/mscorlib/src/System/Collections/Generic/DebugView.cs b/src/mscorlib/src/System/Collections/Generic/DebugView.cs index 57b91ef..d0711e5 100644 --- a/src/mscorlib/src/System/Collections/Generic/DebugView.cs +++ b/src/mscorlib/src/System/Collections/Generic/DebugView.cs @@ -110,7 +110,7 @@ namespace System.Collections.Generic { public Mscorlib_KeyedCollectionDebugView(KeyedCollection keyedCollection) { if (keyedCollection == null) { - throw new ArgumentNullException("keyedCollection"); + throw new ArgumentNullException(nameof(keyedCollection)); } Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/Collections/Generic/Dictionary.cs b/src/mscorlib/src/System/Collections/Generic/Dictionary.cs index 9cbfff5..c2b2da9 100644 --- a/src/mscorlib/src/System/Collections/Generic/Dictionary.cs +++ b/src/mscorlib/src/System/Collections/Generic/Dictionary.cs @@ -91,12 +91,12 @@ namespace System.Collections.Generic { if (capacity > 0) Initialize(capacity); this.comparer = comparer ?? EqualityComparer.Default; -#if FEATURE_RANDOMIZED_STRING_HASHING && FEATURE_CORECLR +#if FEATURE_RANDOMIZED_STRING_HASHING if (HashHelpers.s_UseRandomizedStringHashing && comparer == EqualityComparer.Default) { this.comparer = (IEqualityComparer) NonRandomizedStringEqualityComparer.Default; } -#endif // FEATURE_RANDOMIZED_STRING_HASHING && FEATURE_CORECLR +#endif // FEATURE_RANDOMIZED_STRING_HASHING } public Dictionary(IDictionary dictionary): this(dictionary, null) {} @@ -129,6 +129,21 @@ namespace System.Collections.Generic { } } + public Dictionary(IEnumerable> collection): + this(collection, null) { } + + public Dictionary(IEnumerable> collection, IEqualityComparer comparer): + this((collection as ICollection>)?.Count ?? 0, comparer) + { + if (collection == null) { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); + } + + foreach (KeyValuePair pair in collection) { + Add(pair.Key, pair.Value); + } + } + protected Dictionary(SerializationInfo info, StreamingContext context) { //We can't do anything with the keys and values until the entire graph has been deserialized //and we have a resonable estimate that GetHashCode is not going to fail. For the time being, @@ -263,7 +278,7 @@ namespace System.Collections.Generic { } if (index < 0 || index > array.Length ) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (array.Length - index < Count) { @@ -287,7 +302,6 @@ namespace System.Collections.Generic { return new Enumerator(this, Enumerator.KeyValuePair); } - [System.Security.SecurityCritical] // auto-generated_required public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.info); @@ -347,11 +361,7 @@ namespace System.Collections.Generic { for (int i = buckets[targetBucket]; i >= 0; i = entries[i].next) { if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) { if (add) { -#if FEATURE_CORECLR ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(key); -#else - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate); -#endif } entries[i].value = value; version++; @@ -386,8 +396,6 @@ namespace System.Collections.Generic { version++; #if FEATURE_RANDOMIZED_STRING_HASHING - -#if FEATURE_CORECLR // In case we hit the collision threshold we'll need to switch to the comparer which is using randomized string hashing // in this case will be EqualityComparer.Default. // Note, randomized string hashing is turned on by default on coreclr so EqualityComparer.Default will @@ -398,14 +406,6 @@ namespace System.Collections.Generic { comparer = (IEqualityComparer) EqualityComparer.Default; Resize(entries.Length, true); } -#else - if(collisionCount > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(comparer)) - { - comparer = (IEqualityComparer) HashHelpers.GetRandomizedEqualityComparer(comparer); - Resize(entries.Length, true); - } -#endif // FEATURE_CORECLR - #endif } @@ -459,7 +459,7 @@ namespace System.Collections.Generic { } private void Resize(int newSize, bool forceNewHashCodes) { - Contract.Assert(newSize >= entries.Length); + Debug.Assert(newSize >= entries.Length); int[] newBuckets = new int[newSize]; for (int i = 0; i < newBuckets.Length; i++) newBuckets[i] = -1; Entry[] newEntries = new Entry[newSize]; @@ -523,16 +523,19 @@ namespace System.Collections.Generic { return false; } - // This is a convenience method for the internal callers that were converted from using Hashtable. - // Many were combining key doesn't exist and key exists but null value (for non-value types) checks. - // This allows them to continue getting that behavior with minimal code delta. This is basically - // TryGetValue without the out param - internal TValue GetValueOrDefault(TKey key) { + // Method similar to TryGetValue that returns the value instead of putting it in an out param. + public TValue GetValueOrDefault(TKey key) => GetValueOrDefault(key, default(TValue)); + + // Method similar to TryGetValue that returns the value instead of putting it in an out param. If the entry + // doesn't exist, returns the defaultValue instead. + public TValue GetValueOrDefault(TKey key, TValue defaultValue) + { int i = FindEntry(key); - if (i >= 0) { + if (i >= 0) + { return entries[i].value; } - return default(TValue); + return defaultValue; } bool ICollection>.IsReadOnly { @@ -557,7 +560,7 @@ namespace System.Collections.Generic { } if (index < 0 || index > array.Length) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (array.Length - index < Count) { @@ -580,7 +583,7 @@ namespace System.Collections.Generic { else { object[] objects = array as object[]; if (objects == null) { - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } try { @@ -593,7 +596,7 @@ namespace System.Collections.Generic { } } catch(ArrayTypeMismatchException) { - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } } } @@ -733,7 +736,7 @@ namespace System.Collections.Generic { public bool MoveNext() { if (version != dictionary.version) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } // Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends. @@ -762,7 +765,7 @@ namespace System.Collections.Generic { object IEnumerator.Current { get { if( index == 0 || (index == dictionary.count + 1)) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } if (getEnumeratorRetType == DictEntry) { @@ -775,7 +778,7 @@ namespace System.Collections.Generic { void IEnumerator.Reset() { if (version != dictionary.version) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } index = 0; @@ -785,7 +788,7 @@ namespace System.Collections.Generic { DictionaryEntry IDictionaryEnumerator.Entry { get { if( index == 0 || (index == dictionary.count + 1)) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } return new DictionaryEntry(current.Key, current.Value); @@ -795,7 +798,7 @@ namespace System.Collections.Generic { object IDictionaryEnumerator.Key { get { if( index == 0 || (index == dictionary.count + 1)) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } return current.Key; @@ -805,7 +808,7 @@ namespace System.Collections.Generic { object IDictionaryEnumerator.Value { get { if( index == 0 || (index == dictionary.count + 1)) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } return current.Value; @@ -837,7 +840,7 @@ namespace System.Collections.Generic { } if (index < 0 || index > array.Length) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (array.Length - index < dictionary.Count) { @@ -898,7 +901,7 @@ namespace System.Collections.Generic { } if (index < 0 || index > array.Length) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (array.Length - index < dictionary.Count) { @@ -912,7 +915,7 @@ namespace System.Collections.Generic { else { object[] objects = array as object[]; if (objects == null) { - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } int count = dictionary.count; @@ -923,7 +926,7 @@ namespace System.Collections.Generic { } } catch(ArrayTypeMismatchException) { - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } } } @@ -956,7 +959,7 @@ namespace System.Collections.Generic { public bool MoveNext() { if (version != dictionary.version) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } while ((uint)index < (uint)dictionary.count) { @@ -982,7 +985,7 @@ namespace System.Collections.Generic { Object System.Collections.IEnumerator.Current { get { if( index == 0 || (index == dictionary.count + 1)) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } return currentKey; @@ -991,7 +994,7 @@ namespace System.Collections.Generic { void System.Collections.IEnumerator.Reset() { if (version != dictionary.version) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } index = 0; @@ -1024,7 +1027,7 @@ namespace System.Collections.Generic { } if (index < 0 || index > array.Length) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (array.Length - index < dictionary.Count) { @@ -1085,7 +1088,7 @@ namespace System.Collections.Generic { } if (index < 0 || index > array.Length) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (array.Length - index < dictionary.Count) @@ -1098,7 +1101,7 @@ namespace System.Collections.Generic { else { object[] objects = array as object[]; if (objects == null) { - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } int count = dictionary.count; @@ -1109,7 +1112,7 @@ namespace System.Collections.Generic { } } catch(ArrayTypeMismatchException) { - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } } } @@ -1142,7 +1145,7 @@ namespace System.Collections.Generic { public bool MoveNext() { if (version != dictionary.version) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } while ((uint)index < (uint)dictionary.count) { @@ -1167,7 +1170,7 @@ namespace System.Collections.Generic { Object System.Collections.IEnumerator.Current { get { if( index == 0 || (index == dictionary.count + 1)) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } return currentValue; @@ -1176,7 +1179,7 @@ namespace System.Collections.Generic { void System.Collections.IEnumerator.Reset() { if (version != dictionary.version) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } index = 0; currentValue = default(TValue); diff --git a/src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs b/src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs index b845d64..3731114 100644 --- a/src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs +++ b/src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs @@ -32,7 +32,6 @@ namespace System.Collections.Generic // Note that logic in this method is replicated in vm\compile.cpp to ensure that NGen // saves the right instantiations // - [System.Security.SecuritySafeCritical] // auto-generated private static EqualityComparer CreateComparer() { Contract.Ensures(Contract.Result>() != null); @@ -144,10 +143,7 @@ namespace System.Collections.Generic } [Pure] - public override int GetHashCode(T obj) { - if (obj == null) return 0; - return obj.GetHashCode(); - } + public override int GetHashCode(T obj) => obj?.GetHashCode() ?? 0; internal override int IndexOf(T[] array, T value, int startIndex, int count) { int endIndex = startIndex + count; @@ -179,22 +175,21 @@ namespace System.Collections.Generic return -1; } - // Equals method for the comparer itself. - public override bool Equals(Object obj){ - GenericEqualityComparer comparer = obj as GenericEqualityComparer; - return comparer != null; - } + // Equals method for the comparer itself. + // If in the future this type is made sealed, change the is check to obj != null && GetType() == obj.GetType(). + public override bool Equals(Object obj) => + obj is GenericEqualityComparer; - public override int GetHashCode() { - return this.GetType().Name.GetHashCode(); - } + // If in the future this type is made sealed, change typeof(...) to GetType(). + public override int GetHashCode() => + typeof(GenericEqualityComparer).GetHashCode(); } [Serializable] - internal class NullableEqualityComparer : EqualityComparer> where T : struct, IEquatable + internal sealed class NullableEqualityComparer : EqualityComparer where T : struct, IEquatable { [Pure] - public override bool Equals(Nullable x, Nullable y) { + public override bool Equals(T? x, T? y) { if (x.HasValue) { if (y.HasValue) return x.value.Equals(y.value); return false; @@ -204,11 +199,9 @@ namespace System.Collections.Generic } [Pure] - public override int GetHashCode(Nullable obj) { - return obj.GetHashCode(); - } + public override int GetHashCode(T? obj) => obj.GetHashCode(); - internal override int IndexOf(Nullable[] array, Nullable value, int startIndex, int count) { + internal override int IndexOf(T?[] array, T? value, int startIndex, int count) { int endIndex = startIndex + count; if (!value.HasValue) { for (int i = startIndex; i < endIndex; i++) { @@ -223,7 +216,7 @@ namespace System.Collections.Generic return -1; } - internal override int LastIndexOf(Nullable[] array, Nullable value, int startIndex, int count) { + internal override int LastIndexOf(T?[] array, T? value, int startIndex, int count) { int endIndex = startIndex - count + 1; if (!value.HasValue) { for (int i = startIndex; i >= endIndex; i--) { @@ -238,19 +231,16 @@ namespace System.Collections.Generic return -1; } - // Equals method for the comparer itself. - public override bool Equals(Object obj){ - NullableEqualityComparer comparer = obj as NullableEqualityComparer; - return comparer != null; - } + // Equals method for the comparer itself. + public override bool Equals(Object obj) => + obj != null && GetType() == obj.GetType(); - public override int GetHashCode() { - return this.GetType().Name.GetHashCode(); - } + public override int GetHashCode() => + GetType().GetHashCode(); } [Serializable] - internal class ObjectEqualityComparer: EqualityComparer + internal sealed class ObjectEqualityComparer: EqualityComparer { [Pure] public override bool Equals(T x, T y) { @@ -263,10 +253,7 @@ namespace System.Collections.Generic } [Pure] - public override int GetHashCode(T obj) { - if (obj == null) return 0; - return obj.GetHashCode(); - } + public override int GetHashCode(T obj) => obj?.GetHashCode() ?? 0; internal override int IndexOf(T[] array, T value, int startIndex, int count) { int endIndex = startIndex + count; @@ -298,25 +285,21 @@ namespace System.Collections.Generic return -1; } - // Equals method for the comparer itself. - public override bool Equals(Object obj){ - ObjectEqualityComparer comparer = obj as ObjectEqualityComparer; - return comparer != null; - } + // Equals method for the comparer itself. + public override bool Equals(Object obj) => + obj != null && GetType() == obj.GetType(); - public override int GetHashCode() { - return this.GetType().Name.GetHashCode(); - } + public override int GetHashCode() => + GetType().GetHashCode(); } -#if FEATURE_CORECLR // NonRandomizedStringEqualityComparer is the comparer used by default with the Dictionary // As the randomized string hashing is turned on by default on coreclr, we need to keep the performance not affected // as much as possible in the main stream scenarios like Dictionary // We use NonRandomizedStringEqualityComparer as default comparer as it doesnt use the randomized string hashing which // keep the perofrmance not affected till we hit collision threshold and then we switch to the comparer which is using // randomized string hashing GenericEqualityComparer - + [Serializable] internal class NonRandomizedStringEqualityComparer : GenericEqualityComparer { static IEqualityComparer s_nonRandomizedComparer; @@ -335,12 +318,11 @@ namespace System.Collections.Generic return obj.GetLegacyNonRandomizedHashCode(); } } -#endif // FEATURE_CORECLR // Performance of IndexOf on byte array is very important for some scenarios. // We will call the C runtime function memchr, which is optimized. [Serializable] - internal class ByteEqualityComparer: EqualityComparer + internal sealed class ByteEqualityComparer: EqualityComparer { [Pure] public override bool Equals(byte x, byte y) { @@ -352,14 +334,13 @@ namespace System.Collections.Generic return b.GetHashCode(); } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe override int IndexOf(byte[] array, byte value, int startIndex, int count) { if (array==null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); if (startIndex < 0) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); if (count > array.Length - startIndex) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -377,15 +358,12 @@ namespace System.Collections.Generic return -1; } - // Equals method for the comparer itself. - public override bool Equals(Object obj){ - ByteEqualityComparer comparer = obj as ByteEqualityComparer; - return comparer != null; - } + // Equals method for the comparer itself. + public override bool Equals(Object obj) => + obj != null && GetType() == obj.GetType(); - public override int GetHashCode() { - return this.GetType().Name.GetHashCode(); - } + public override int GetHashCode() => + GetType().GetHashCode(); } [Serializable] @@ -409,7 +387,6 @@ namespace System.Collections.Generic // This is used by the serialization engine. protected EnumEqualityComparer(SerializationInfo information, StreamingContext context) { } - [SecurityCritical] public void GetObjectData(SerializationInfo info, StreamingContext context) { // For back-compat we need to serialize the comparers for enums with underlying types other than int as ObjectEqualityComparer if (Type.GetTypeCode(Enum.GetUnderlyingType(typeof(T))) != TypeCode.Int32) { @@ -417,14 +394,35 @@ namespace System.Collections.Generic } } - // Equals method for the comparer itself. - public override bool Equals(Object obj){ - EnumEqualityComparer comparer = obj as EnumEqualityComparer; - return comparer != null; + // Equals method for the comparer itself. + public override bool Equals(Object obj) => + obj != null && GetType() == obj.GetType(); + + public override int GetHashCode() => + GetType().GetHashCode(); + + internal override int IndexOf(T[] array, T value, int startIndex, int count) + { + int toFind = JitHelpers.UnsafeEnumCast(value); + int endIndex = startIndex + count; + for (int i = startIndex; i < endIndex; i++) + { + int current = JitHelpers.UnsafeEnumCast(array[i]); + if (toFind == current) return i; + } + return -1; } - public override int GetHashCode() { - return this.GetType().Name.GetHashCode(); + internal override int LastIndexOf(T[] array, T value, int startIndex, int count) + { + int toFind = JitHelpers.UnsafeEnumCast(value); + int endIndex = startIndex - count + 1; + for (int i = startIndex; i >= endIndex; i--) + { + int current = JitHelpers.UnsafeEnumCast(array[i]); + if (toFind == current) return i; + } + return -1; } } @@ -474,28 +472,48 @@ namespace System.Collections.Generic return x_final.GetHashCode(); } - // Equals method for the comparer itself. - public override bool Equals(Object obj){ - LongEnumEqualityComparer comparer = obj as LongEnumEqualityComparer; - return comparer != null; - } + // Equals method for the comparer itself. + public override bool Equals(Object obj) => + obj != null && GetType() == obj.GetType(); - public override int GetHashCode() { - return this.GetType().Name.GetHashCode(); - } + public override int GetHashCode() => + GetType().GetHashCode(); public LongEnumEqualityComparer() { } // This is used by the serialization engine. public LongEnumEqualityComparer(SerializationInfo information, StreamingContext context) { } - [SecurityCritical] public void GetObjectData(SerializationInfo info, StreamingContext context) { // The LongEnumEqualityComparer does not exist on 4.0 so we need to serialize this comparer as ObjectEqualityComparer // to allow for roundtrip between 4.0 and 4.5. info.SetType(typeof(ObjectEqualityComparer)); } + + internal override int IndexOf(T[] array, T value, int startIndex, int count) + { + long toFind = JitHelpers.UnsafeEnumCastLong(value); + int endIndex = startIndex + count; + for (int i = startIndex; i < endIndex; i++) + { + long current = JitHelpers.UnsafeEnumCastLong(array[i]); + if (toFind == current) return i; + } + return -1; + } + + internal override int LastIndexOf(T[] array, T value, int startIndex, int count) + { + long toFind = JitHelpers.UnsafeEnumCastLong(value); + int endIndex = startIndex - count + 1; + for (int i = startIndex; i >= endIndex; i--) + { + long current = JitHelpers.UnsafeEnumCastLong(array[i]); + if (toFind == current) return i; + } + return -1; + } } #if FEATURE_RANDOMIZED_STRING_HASHING @@ -528,14 +546,12 @@ namespace System.Collections.Generic } [Pure] - [SecuritySafeCritical] public int GetHashCode(String obj) { if(obj == null) return 0; return String.InternalMarvin32HashString(obj, obj.Length, _entropy); } [Pure] - [SecuritySafeCritical] public int GetHashCode(Object obj) { if(obj == null) return 0; @@ -552,7 +568,7 @@ namespace System.Collections.Generic } public override int GetHashCode() { - return (this.GetType().Name.GetHashCode() ^ ((int) (_entropy & 0x7FFFFFFF))); + return (this.GetType().GetHashCode() ^ ((int) (_entropy & 0x7FFFFFFF))); } @@ -587,7 +603,6 @@ namespace System.Collections.Generic } [Pure] - [SecuritySafeCritical] public int GetHashCode(Object obj) { if(obj == null) return 0; @@ -604,7 +619,7 @@ namespace System.Collections.Generic } public override int GetHashCode() { - return (this.GetType().Name.GetHashCode() ^ ((int) (_entropy & 0x7FFFFFFF))); + return (this.GetType().GetHashCode() ^ ((int) (_entropy & 0x7FFFFFFF))); } IEqualityComparer IWellKnownStringEqualityComparer.GetRandomizedEqualityComparer() { diff --git a/src/mscorlib/src/System/Collections/Generic/KeyValuePair.cs b/src/mscorlib/src/System/Collections/Generic/KeyValuePair.cs index 17e1c53..ad9f747 100644 --- a/src/mscorlib/src/System/Collections/Generic/KeyValuePair.cs +++ b/src/mscorlib/src/System/Collections/Generic/KeyValuePair.cs @@ -18,6 +18,16 @@ namespace System.Collections.Generic { using System; using System.Text; + // Provides the Create factory method for KeyValuePair. + public static class KeyValuePair + { + // Creates a new KeyValuePair from the given values. + public static KeyValuePair Create(TKey key, TValue value) + { + return new KeyValuePair(key, value); + } + } + // A KeyValuePair holds a key and a value from a dictionary. // It is used by the IEnumerable implementation for both IDictionary // and IReadOnlyDictionary. @@ -52,5 +62,12 @@ namespace System.Collections.Generic { s.Append(']'); return StringBuilderCache.GetStringAndRelease(s); } + + // BLOCKED (do not add now): [EditorBrowsable(EditorBrowsableState.Never)] + public void Deconstruct(out TKey key, out TValue value) + { + key = Key; + value = Value; + } } } diff --git a/src/mscorlib/src/System/Collections/Generic/List.cs b/src/mscorlib/src/System/Collections/Generic/List.cs index ae3356d..3e2947f 100644 --- a/src/mscorlib/src/System/Collections/Generic/List.cs +++ b/src/mscorlib/src/System/Collections/Generic/List.cs @@ -91,14 +91,7 @@ namespace System.Collections.Generic { else { _size = 0; _items = _emptyArray; - // This enumerable could be empty. Let Add allocate a new array, if needed. - // Note it will also go to _defaultCapacity first, not 1, then 2, etc. - - using(IEnumerator en = collection.GetEnumerator()) { - while(en.MoveNext()) { - Add(en.Current); - } - } + AddEnumerable(collection); } } @@ -274,7 +267,7 @@ namespace System.Collections.Generic { // public int BinarySearch(int index, int count, T item, IComparer comparer) { if (index < 0) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); if (count < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); if (_size - index < count) @@ -369,7 +362,7 @@ namespace System.Collections.Generic { Array.Copy(_items, 0, array, arrayIndex, _size); } catch(ArrayTypeMismatchException){ - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } } @@ -393,7 +386,7 @@ namespace System.Collections.Generic { } // Ensures that the capacity of this list is at least the given minimum - // value. If the currect capacity of the list is less than min, the + // value. If the current capacity of the list is less than min, the // capacity is increased to twice the current capacity or to min, // whichever is larger. private void EnsureCapacity(int min) { @@ -454,11 +447,11 @@ namespace System.Collections.Generic { public int FindIndex(int startIndex, int count, Predicate match) { if( (uint)startIndex > (uint)_size ) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); } if (count < 0 || startIndex > _size - count) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count); + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); } if( match == null) { @@ -512,19 +505,19 @@ namespace System.Collections.Generic { if(_size == 0) { // Special case for 0 length List if( startIndex != -1) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); } } else { // Make sure we're not out of range if ( (uint)startIndex >= (uint)_size) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); } } // 2nd have of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0. if (count < 0 || startIndex - count + 1 < 0) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count); + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); } int endIndex = startIndex - count; @@ -545,14 +538,14 @@ namespace System.Collections.Generic { int version = _version; for(int i = 0 ; i < _size; i++) { - if (version != _version && BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) { + if (version != _version) { break; } action(_items[i]); } - if (version != _version && BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); + if (version != _version) + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } // Returns an enumerator for this list with the given @@ -575,7 +568,7 @@ namespace System.Collections.Generic { public List GetRange(int index, int count) { if (index < 0) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (count < 0) { @@ -628,7 +621,7 @@ namespace System.Collections.Generic { // public int IndexOf(T item, int index) { if (index > _size) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowArgumentOutOfRange_IndexException(); Contract.Ensures(Contract.Result() >= -1); Contract.Ensures(Contract.Result() < Count); Contract.EndContractBlock(); @@ -646,9 +639,9 @@ namespace System.Collections.Generic { // public int IndexOf(T item, int index, int count) { if (index > _size) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowArgumentOutOfRange_IndexException(); - if (count <0 || index > _size - count) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count); + if (count <0 || index > _size - count) ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); Contract.Ensures(Contract.Result() >= -1); Contract.Ensures(Contract.Result() < Count); Contract.EndContractBlock(); @@ -698,7 +691,7 @@ namespace System.Collections.Generic { } if ((uint)index > (uint)_size) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowArgumentOutOfRange_IndexException(); } Contract.EndContractBlock(); @@ -719,20 +712,24 @@ namespace System.Collections.Generic { Array.Copy(_items, index+count, _items, index*2, _size-index); } else { - T[] itemsToInsert = new T[count]; - c.CopyTo(itemsToInsert, 0); - itemsToInsert.CopyTo(_items, index); + c.CopyTo(_items, index); } _size += count; } } - else { + else if (index < _size) { + // We're inserting a lazy enumerable. Call Insert on each of the constituent items. using(IEnumerator en = collection.GetEnumerator()) { while(en.MoveNext()) { Insert(index++, en.Current); } } } + else + { + // We're adding a lazy enumerable because the index is at the end of this list. + AddEnumerable(collection); + } _version++; } @@ -768,7 +765,7 @@ namespace System.Collections.Generic { public int LastIndexOf(T item, int index) { if (index >= _size) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowArgumentOutOfRange_IndexException(); Contract.Ensures(Contract.Result() >= -1); Contract.Ensures(((Count == 0) && (Contract.Result() == -1)) || ((Count > 0) && (Contract.Result() <= index))); Contract.EndContractBlock(); @@ -786,7 +783,7 @@ namespace System.Collections.Generic { // public int LastIndexOf(T item, int index, int count) { if ((Count != 0) && (index < 0)) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if ((Count !=0) && (count < 0)) { @@ -885,7 +882,7 @@ namespace System.Collections.Generic { // public void RemoveRange(int index, int count) { if (index < 0) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (count < 0) { @@ -919,7 +916,7 @@ namespace System.Collections.Generic { // public void Reverse(int index, int count) { if (index < 0) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (count < 0) { @@ -930,22 +927,7 @@ namespace System.Collections.Generic { ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); Contract.EndContractBlock(); - // The non-generic Array.Reverse is not used because it does not perform - // well for non-primitive value types. - // If/when a generic Array.Reverse becomes available, the below code - // can be deleted and replaced with a call to Array.Reverse. - int i = index; - int j = index + count - 1; - T[] array = _items; - while (i < j) - { - T temp = array[i]; - array[i] = array[j]; - array[j] = temp; - i++; - j--; - } - + Array.Reverse(_items, index, count); _version++; } @@ -973,7 +955,7 @@ namespace System.Collections.Generic { // public void Sort(int index, int count, IComparer comparer) { if (index < 0) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (count < 0) { @@ -995,8 +977,7 @@ namespace System.Collections.Generic { Contract.EndContractBlock(); if( _size > 0) { - IComparer comparer = Comparer.Create(comparison); - Array.Sort(_items, 0, _size, comparer); + ArraySortHelper.Sort(_items, 0, _size, comparison); } } @@ -1006,12 +987,10 @@ namespace System.Collections.Generic { Contract.Ensures(Contract.Result() != null); Contract.Ensures(Contract.Result().Length == Count); -#if FEATURE_CORECLR if (_size == 0) { return _emptyArray; } -#endif T[] array = new T[_size]; Array.Copy(_items, 0, array, 0, _size); @@ -1048,6 +1027,31 @@ namespace System.Collections.Generic { return true; } + private void AddEnumerable(IEnumerable enumerable) + { + Debug.Assert(enumerable != null); + Debug.Assert(!(enumerable is ICollection), "We should have optimized for this beforehand."); + + using (IEnumerator en = enumerable.GetEnumerator()) + { + _version++; // Even if the enumerable has no items, we can update _version. + + while (en.MoveNext()) + { + // Capture Current before doing anything else. If this throws + // an exception, we want to make a clean break. + T current = en.Current; + + if (_size == _items.Length) + { + EnsureCapacity(_size + 1); + } + + _items[_size++] = current; + } + } + } + [Serializable] public struct Enumerator : IEnumerator, System.Collections.IEnumerator { @@ -1082,7 +1086,7 @@ namespace System.Collections.Generic { private bool MoveNextRare() { if (version != list._version) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } index = list._size + 1; @@ -1099,7 +1103,7 @@ namespace System.Collections.Generic { Object System.Collections.IEnumerator.Current { get { if( index == 0 || index == list._size + 1) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } return Current; } @@ -1107,7 +1111,7 @@ namespace System.Collections.Generic { void System.Collections.IEnumerator.Reset() { if (version != list._version) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } index = 0; diff --git a/src/mscorlib/src/System/Collections/Hashtable.cs b/src/mscorlib/src/System/Collections/Hashtable.cs index 262cced..d4c7d8d 100644 --- a/src/mscorlib/src/System/Collections/Hashtable.cs +++ b/src/mscorlib/src/System/Collections/Hashtable.cs @@ -23,10 +23,7 @@ namespace System.Collections { using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; using System.Diagnostics.Contracts; -#if !FEATURE_CORECLR - using System.Security.Cryptography; -#endif - + // The Hashtable class represents a dictionary of associated keys and values // with constant lookup time. // @@ -271,9 +268,9 @@ namespace System.Collections { // public Hashtable(int capacity, float loadFactor) { if (capacity < 0) - throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(capacity), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (!(loadFactor >= 0.1f && loadFactor <= 1.0f)) - throw new ArgumentOutOfRangeException("loadFactor", Environment.GetResourceString("ArgumentOutOfRange_HashtableLoadFactor", .1, 1.0)); + throw new ArgumentOutOfRangeException(nameof(loadFactor), Environment.GetResourceString("ArgumentOutOfRange_HashtableLoadFactor", .1, 1.0)); Contract.EndContractBlock(); // Based on perf work, .72 is the optimal load factor for this table. @@ -290,7 +287,7 @@ namespace System.Collections { loadsize = (int)(this.loadFactor * hashsize); isWriterInProgress = false; // Based on the current algorithm, loadsize must be less than hashsize. - Contract.Assert( loadsize < hashsize, "Invalid hashtable loadsize!"); + Debug.Assert( loadsize < hashsize, "Invalid hashtable loadsize!"); } // Constructs a new hashtable with the given initial capacity and load @@ -375,7 +372,7 @@ namespace System.Collections { public Hashtable(IDictionary d, float loadFactor, IHashCodeProvider hcp, IComparer comparer) : this((d != null ? d.Count : 0), loadFactor, hcp, comparer) { if (d==null) - throw new ArgumentNullException("d", Environment.GetResourceString("ArgumentNull_Dictionary")); + throw new ArgumentNullException(nameof(d), Environment.GetResourceString("ArgumentNull_Dictionary")); Contract.EndContractBlock(); IDictionaryEnumerator e = d.GetEnumerator(); @@ -385,7 +382,7 @@ namespace System.Collections { public Hashtable(IDictionary d, float loadFactor, IEqualityComparer equalityComparer) : this((d != null ? d.Count : 0), loadFactor, equalityComparer) { if (d==null) - throw new ArgumentNullException("d", Environment.GetResourceString("ArgumentNull_Dictionary")); + throw new ArgumentNullException(nameof(d), Environment.GetResourceString("ArgumentNull_Dictionary")); Contract.EndContractBlock(); IDictionaryEnumerator e = d.GetEnumerator(); @@ -444,14 +441,11 @@ namespace System.Collections { // Removes all entries from this hashtable. [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public virtual void Clear() { - Contract.Assert(!isWriterInProgress, "Race condition detected in usages of Hashtable - multiple threads appear to be writing to a Hashtable instance simultaneously! Don't do that - use Hashtable.Synchronized."); + Debug.Assert(!isWriterInProgress, "Race condition detected in usages of Hashtable - multiple threads appear to be writing to a Hashtable instance simultaneously! Don't do that - use Hashtable.Synchronized."); if (count == 0 && occupancy == 0) return; -#if !FEATURE_CORECLR - Thread.BeginCriticalRegion(); -#endif isWriterInProgress = true; for (int i = 0; i < buckets.Length; i++){ buckets[i].hash_coll = 0; @@ -463,9 +457,6 @@ namespace System.Collections { occupancy = 0; UpdateVersion(); isWriterInProgress = false; -#if !FEATURE_CORECLR - Thread.EndCriticalRegion(); -#endif } // Clone returns a virtually identical copy of this hash table. This does @@ -501,7 +492,7 @@ namespace System.Collections { // public virtual bool ContainsKey(Object key) { if (key == null) { - throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key")); + throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key")); } Contract.EndContractBlock(); @@ -526,9 +517,7 @@ namespace System.Collections { } while (b.hash_coll < 0 && ++ntry < lbuckets.Length); return false; } - - - + // Checks if this hashtable contains an entry with the given value. The // values of the entries of the hashtable are compared to the given value // using the Object.Equals method. This method performs a linear @@ -590,11 +579,11 @@ namespace System.Collections { public virtual void CopyTo(Array array, int arrayIndex) { if (array == null) - throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Array")); + throw new ArgumentNullException(nameof(array), Environment.GetResourceString("ArgumentNull_Array")); if (array.Rank != 1) throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported")); if (arrayIndex < 0) - throw new ArgumentOutOfRangeException("arrayIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(arrayIndex), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (array.Length - arrayIndex < Count) throw new ArgumentException(Environment.GetResourceString("Arg_ArrayPlusOffTooSmall")); Contract.EndContractBlock(); @@ -643,7 +632,7 @@ namespace System.Collections { public virtual Object this[Object key] { get { if (key == null) { - throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key")); + throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key")); } Contract.EndContractBlock(); @@ -750,28 +739,23 @@ namespace System.Collections { for (nb = 0; nb < buckets.Length; nb++){ bucket oldb = buckets[nb]; if ((oldb.key != null) && (oldb.key != buckets)) { - int hashcode = ((forceNewHashCode ? GetHash(oldb.key) : oldb.hash_coll) & 0x7FFFFFFF); + int hashcode = ((forceNewHashCode ? GetHash(oldb.key) : oldb.hash_coll) & 0x7FFFFFFF); putEntry(newBuckets, oldb.key, oldb.val, hashcode); } } - + // New bucket[] is good to go - replace buckets and other internal state. -#if !FEATURE_CORECLR - Thread.BeginCriticalRegion(); -#endif isWriterInProgress = true; buckets = newBuckets; loadsize = (int)(loadFactor * newsize); UpdateVersion(); isWriterInProgress = false; -#if !FEATURE_CORECLR - Thread.EndCriticalRegion(); -#endif + // minimun size of hashtable is 3 now and maximum loadFactor is 0.72 now. - Contract.Assert(loadsize < newsize, "Our current implementaion means this is not possible."); + Debug.Assert(loadsize < newsize, "Our current implementaion means this is not possible."); return; } - + // Returns an enumerator for this hashtable. // If modifications made to the hashtable while an enumeration is // in progress, the MoveNext and Current methods of the @@ -820,7 +804,7 @@ namespace System.Collections { // protected virtual bool KeyEquals(Object item, Object key) { - Contract.Assert(key != null, "key can't be null here!"); + Debug.Assert(key != null, "key can't be null here!"); if( Object.ReferenceEquals(buckets, item)) { return false; } @@ -872,7 +856,7 @@ namespace System.Collections { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] private void Insert (Object key, Object nvalue, bool add) { if (key == null) { - throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key")); + throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key")); } Contract.EndContractBlock(); if (count >= loadsize) { @@ -913,36 +897,14 @@ namespace System.Collections { // We pretty much have to insert in this order. Don't set hash // code until the value & key are set appropriately. -#if !FEATURE_CORECLR - Thread.BeginCriticalRegion(); -#endif - isWriterInProgress = true; + isWriterInProgress = true; buckets[bucketNumber].val = nvalue; buckets[bucketNumber].key = key; buckets[bucketNumber].hash_coll |= (int) hashcode; count++; UpdateVersion(); isWriterInProgress = false; -#if !FEATURE_CORECLR - Thread.EndCriticalRegion(); -#endif -#if FEATURE_RANDOMIZED_STRING_HASHING -#if !FEATURE_CORECLR - // coreclr has the randomized string hashing on by default so we don't need to resize at this point - - if(ntry > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(_keycomparer)) - { - // PERF: We don't want to rehash if _keycomparer is already a RandomizedObjectEqualityComparer since in some - // cases there may not be any strings in the hashtable and we wouldn't get any mixing. - if(_keycomparer == null || !(_keycomparer is System.Collections.Generic.RandomizedObjectEqualityComparer)) - { - _keycomparer = HashHelpers.GetRandomizedEqualityComparer(_keycomparer); - rehash(buckets.Length, true); - } - } -#endif // !FEATURE_CORECLR -#endif // FEATURE_RANDOMIZED_STRING_HASHING return; } @@ -954,31 +916,10 @@ namespace System.Collections { if (add) { throw new ArgumentException(Environment.GetResourceString("Argument_AddingDuplicate__", buckets[bucketNumber].key, key)); } -#if !FEATURE_CORECLR - Thread.BeginCriticalRegion(); -#endif - isWriterInProgress = true; + isWriterInProgress = true; buckets[bucketNumber].val = nvalue; - UpdateVersion(); + UpdateVersion(); isWriterInProgress = false; -#if !FEATURE_CORECLR - Thread.EndCriticalRegion(); -#endif - -#if FEATURE_RANDOMIZED_STRING_HASHING -#if !FEATURE_CORECLR - if(ntry > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(_keycomparer)) - { - // PERF: We don't want to rehash if _keycomparer is already a RandomizedObjectEqualityComparer since in some - // cases there may not be any strings in the hashtable and we wouldn't get any mixing. - if(_keycomparer == null || !(_keycomparer is System.Collections.Generic.RandomizedObjectEqualityComparer)) - { - _keycomparer = HashHelpers.GetRandomizedEqualityComparer(_keycomparer); - rehash(buckets.Length, true); - } - } -#endif // !FEATURE_CORECLR -#endif return; } @@ -992,7 +933,7 @@ namespace System.Collections { } } - bucketNumber = (int) (((long)bucketNumber + incr)% (uint)buckets.Length); + bucketNumber = (int) (((long)bucketNumber + incr)% (uint)buckets.Length); } while (++ntry < buckets.Length); // This code is here if and only if there were no buckets without a collision bit set in the entire table @@ -1000,47 +941,27 @@ namespace System.Collections { { // We pretty much have to insert in this order. Don't set hash // code until the value & key are set appropriately. -#if !FEATURE_CORECLR - Thread.BeginCriticalRegion(); -#endif - isWriterInProgress = true; + isWriterInProgress = true; buckets[emptySlotNumber].val = nvalue; buckets[emptySlotNumber].key = key; buckets[emptySlotNumber].hash_coll |= (int) hashcode; count++; UpdateVersion(); isWriterInProgress = false; -#if !FEATURE_CORECLR - Thread.EndCriticalRegion(); -#endif -#if FEATURE_RANDOMIZED_STRING_HASHING -#if !FEATURE_CORECLR - if(buckets.Length > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(_keycomparer)) - { - // PERF: We don't want to rehash if _keycomparer is already a RandomizedObjectEqualityComparer since in some - // cases there may not be any strings in the hashtable and we wouldn't get any mixing. - if(_keycomparer == null || !(_keycomparer is System.Collections.Generic.RandomizedObjectEqualityComparer)) - { - _keycomparer = HashHelpers.GetRandomizedEqualityComparer(_keycomparer); - rehash(buckets.Length, true); - } - } -#endif // !FEATURE_CORECLR -#endif return; } - + // If you see this assert, make sure load factor & count are reasonable. // Then verify that our double hash function (h2, described at top of file) // meets the requirements described above. You should never see this assert. - Contract.Assert(false, "hash table insert failed! Load factor too high, or our double hashing function is incorrect."); + Debug.Assert(false, "hash table insert failed! Load factor too high, or our double hashing function is incorrect."); throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HashInsertFailed")); } private void putEntry (bucket[] newBuckets, Object key, Object nvalue, int hashcode) { - Contract.Assert(hashcode >= 0, "hashcode >= 0"); // make sure collision bit (sign bit) wasn't set. + Debug.Assert(hashcode >= 0, "hashcode >= 0"); // make sure collision bit (sign bit) wasn't set. uint seed = (uint) hashcode; uint incr = (uint)(1 + ((seed * HashPrime) % ((uint)newBuckets.Length - 1))); @@ -1058,7 +979,7 @@ namespace System.Collections { newBuckets[bucketNumber].hash_coll |= unchecked((int)0x80000000); occupancy++; } - bucketNumber = (int) (((long)bucketNumber + incr)% (uint)newBuckets.Length); + bucketNumber = (int) (((long)bucketNumber + incr)% (uint)newBuckets.Length); } while (true); } @@ -1069,10 +990,10 @@ namespace System.Collections { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public virtual void Remove(Object key) { if (key == null) { - throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key")); + throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key")); } Contract.EndContractBlock(); - Contract.Assert(!isWriterInProgress, "Race condition detected in usages of Hashtable - multiple threads appear to be writing to a Hashtable instance simultaneously! Don't do that - use Hashtable.Synchronized."); + Debug.Assert(!isWriterInProgress, "Race condition detected in usages of Hashtable - multiple threads appear to be writing to a Hashtable instance simultaneously! Don't do that - use Hashtable.Synchronized."); uint seed; uint incr; @@ -1086,9 +1007,6 @@ namespace System.Collections { b = buckets[bn]; if (((b.hash_coll & 0x7FFFFFFF) == hashcode) && KeyEquals (b.key, key)) { -#if !FEATURE_CORECLR - Thread.BeginCriticalRegion(); -#endif isWriterInProgress = true; // Clear hash_coll field, then key, then value buckets[bn].hash_coll &= unchecked((int)0x80000000); @@ -1102,12 +1020,9 @@ namespace System.Collections { count--; UpdateVersion(); isWriterInProgress = false; -#if !FEATURE_CORECLR - Thread.EndCriticalRegion(); -#endif return; } - bn = (int) (((long)bn + incr)% (uint)buckets.Length); + bn = (int) (((long)bn + incr)% (uint)buckets.Length); } while (b.hash_coll < 0 && ++ntry < buckets.Length); //throw new ArgumentException(Environment.GetResourceString("Arg_RemoveArgNotFound")); @@ -1131,10 +1046,9 @@ namespace System.Collections { // Returns a thread-safe wrapper for a Hashtable. // - [HostProtection(Synchronization=true)] public static Hashtable Synchronized(Hashtable table) { if (table==null) - throw new ArgumentNullException("table"); + throw new ArgumentNullException(nameof(table)); Contract.EndContractBlock(); return new SyncHashtable(table); } @@ -1143,10 +1057,9 @@ namespace System.Collections { // The ISerializable Implementation // - [System.Security.SecurityCritical] public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); // This is imperfect - it only works well if all other writes are @@ -1302,11 +1215,11 @@ namespace System.Collections { public virtual void CopyTo(Array array, int arrayIndex) { if (array==null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); if (array.Rank != 1) throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported")); if (arrayIndex < 0) - throw new ArgumentOutOfRangeException("arrayIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(arrayIndex), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); if (array.Length - arrayIndex < _hashtable.count) throw new ArgumentException(Environment.GetResourceString("Arg_ArrayPlusOffTooSmall")); @@ -1343,11 +1256,11 @@ namespace System.Collections { public virtual void CopyTo(Array array, int arrayIndex) { if (array==null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); if (array.Rank != 1) throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported")); if (arrayIndex < 0) - throw new ArgumentOutOfRangeException("arrayIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(arrayIndex), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); if (array.Length - arrayIndex < _hashtable.count) throw new ArgumentException(Environment.GetResourceString("Arg_ArrayPlusOffTooSmall")); @@ -1399,10 +1312,9 @@ namespace System.Collections { ** context -- the StreamingContext for the current serialization (ignored) **Exceptions: ArgumentNullException if info is null. ==============================================================================*/ - [System.Security.SecurityCritical] // auto-generated public override void GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); // Our serialization code hasn't been fully tweaked to be safe @@ -1461,7 +1373,7 @@ namespace System.Collections { public override bool ContainsKey(Object key) { if (key == null) { - throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key")); + throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key")); } Contract.EndContractBlock(); return _table.ContainsKey(key); @@ -1630,7 +1542,7 @@ namespace System.Collections { public HashtableDebugView( Hashtable hashtable) { if( hashtable == null) { - throw new ArgumentNullException( "hashtable"); + throw new ArgumentNullException(nameof(hashtable)); } Contract.EndContractBlock(); @@ -1746,7 +1658,7 @@ namespace System.Collections { // Note that this check works even when _items.Length overflowed thanks to the (uint) cast if ((uint)newSize > MaxPrimeArrayLength && MaxPrimeArrayLength > oldSize) { - Contract.Assert( MaxPrimeArrayLength == GetPrime(MaxPrimeArrayLength), "Invalid MaxPrimeArrayLength"); + Debug.Assert( MaxPrimeArrayLength == GetPrime(MaxPrimeArrayLength), "Invalid MaxPrimeArrayLength"); return MaxPrimeArrayLength; } @@ -1765,7 +1677,7 @@ namespace System.Collections { public static IEqualityComparer GetRandomizedEqualityComparer(object comparer) { - Contract.Assert(comparer == null || comparer == System.Collections.Generic.EqualityComparer.Default || comparer is IWellKnownStringEqualityComparer); + Debug.Assert(comparer == null || comparer == System.Collections.Generic.EqualityComparer.Default || comparer is IWellKnownStringEqualityComparer); if(comparer == null) { return new System.Collections.Generic.RandomizedObjectEqualityComparer(); @@ -1781,7 +1693,7 @@ namespace System.Collections { return cmp.GetRandomizedEqualityComparer(); } - Contract.Assert(false, "Missing case in GetRandomizedEqualityComparer!"); + Debug.Assert(false, "Missing case in GetRandomizedEqualityComparer!"); return null; } @@ -1804,9 +1716,6 @@ namespace System.Collections { } private const int bufferSize = 1024; -#if !FEATURE_CORECLR - private static RandomNumberGenerator rng; -#endif private static byte[] data; private static int currentIndex = bufferSize; private static readonly object lockObj = new Object(); @@ -1821,18 +1730,10 @@ namespace System.Collections { if(data == null) { data = new byte[bufferSize]; - Contract.Assert(bufferSize % 8 == 0, "We increment our current index by 8, so our buffer size must be a multiple of 8"); -#if !FEATURE_CORECLR - rng = RandomNumberGenerator.Create(); -#endif - + Debug.Assert(bufferSize % 8 == 0, "We increment our current index by 8, so our buffer size must be a multiple of 8"); } -#if FEATURE_CORECLR Microsoft.Win32.Win32Native.Random(true, data, data.Length); -#else - rng.GetBytes(data); -#endif currentIndex = 0; } diff --git a/src/mscorlib/src/System/Collections/ListDictionaryInternal.cs b/src/mscorlib/src/System/Collections/ListDictionaryInternal.cs index 944523c..be5490b 100644 --- a/src/mscorlib/src/System/Collections/ListDictionaryInternal.cs +++ b/src/mscorlib/src/System/Collections/ListDictionaryInternal.cs @@ -30,7 +30,7 @@ namespace System.Collections { public Object this[Object key] { get { if (key == null) { - throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key")); + throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key")); } Contract.EndContractBlock(); DictionaryNode node = head; @@ -45,16 +45,16 @@ namespace System.Collections { } set { if (key == null) { - throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key")); + throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key")); } Contract.EndContractBlock(); #if FEATURE_SERIALIZATION if (!key.GetType().IsSerializable) - throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "key"); + throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), nameof(key)); if( (value != null) && (!value.GetType().IsSerializable ) ) - throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "value"); + throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), nameof(value)); #endif version++; @@ -132,16 +132,16 @@ namespace System.Collections { public void Add(Object key, Object value) { if (key == null) { - throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key")); + throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key")); } Contract.EndContractBlock(); #if FEATURE_SERIALIZATION if (!key.GetType().IsSerializable) - throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "key" ); + throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), nameof(key) ); if( (value != null) && (!value.GetType().IsSerializable) ) - throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "value"); + throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), nameof(value)); #endif version++; @@ -179,7 +179,7 @@ namespace System.Collections { public bool Contains(Object key) { if (key == null) { - throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key")); + throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key")); } Contract.EndContractBlock(); for (DictionaryNode node = head; node != null; node = node.next) { @@ -192,16 +192,16 @@ namespace System.Collections { public void CopyTo(Array array, int index) { if (array==null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); if (array.Rank != 1) throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported")); if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if ( array.Length - index < this.Count ) - throw new ArgumentException( Environment.GetResourceString("ArgumentOutOfRange_Index"), "index"); + throw new ArgumentException( Environment.GetResourceString("ArgumentOutOfRange_Index"), nameof(index)); Contract.EndContractBlock(); for (DictionaryNode node = head; node != null; node = node.next) { @@ -220,7 +220,7 @@ namespace System.Collections { public void Remove(Object key) { if (key == null) { - throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key")); + throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key")); } Contract.EndContractBlock(); version++; @@ -328,14 +328,14 @@ namespace System.Collections { void ICollection.CopyTo(Array array, int index) { if (array==null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); if (array.Rank != 1) throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported")); if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); if (array.Length - index < list.Count) - throw new ArgumentException(Environment.GetResourceString("ArgumentOutOfRange_Index"), "index"); + throw new ArgumentException(Environment.GetResourceString("ArgumentOutOfRange_Index"), nameof(index)); for (DictionaryNode node = list.head; node != null; node = node.next) { array.SetValue(isKeys ? node.key : node.value, index); index++; diff --git a/src/mscorlib/src/System/Collections/ObjectModel/Collection.cs b/src/mscorlib/src/System/Collections/ObjectModel/Collection.cs index 54aa7bb..a3804ad 100644 --- a/src/mscorlib/src/System/Collections/ObjectModel/Collection.cs +++ b/src/mscorlib/src/System/Collections/ObjectModel/Collection.cs @@ -183,7 +183,7 @@ namespace System.Collections.ObjectModel } if (index < 0 ) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (array.Length - index < Count) { @@ -204,7 +204,7 @@ namespace System.Collections.ObjectModel Type targetType = array.GetType().GetElementType(); Type sourceType = typeof(T); if(!(targetType.IsAssignableFrom(sourceType) || sourceType.IsAssignableFrom(targetType))) { - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } // @@ -213,7 +213,7 @@ namespace System.Collections.ObjectModel // object[] objects = array as object[]; if( objects == null) { - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } int count = items.Count; @@ -223,7 +223,7 @@ namespace System.Collections.ObjectModel } } catch(ArrayTypeMismatchException) { - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } } } diff --git a/src/mscorlib/src/System/Collections/ObjectModel/KeyedCollection.cs b/src/mscorlib/src/System/Collections/ObjectModel/KeyedCollection.cs index 7313d71..b6fe6de 100644 --- a/src/mscorlib/src/System/Collections/ObjectModel/KeyedCollection.cs +++ b/src/mscorlib/src/System/Collections/ObjectModel/KeyedCollection.cs @@ -53,7 +53,7 @@ namespace System.Collections.ObjectModel /// new private List Items { get { - Contract.Assert(base.Items is List); + Debug.Assert(base.Items is List); return (List)base.Items; } @@ -233,7 +233,7 @@ namespace System.Collections.ObjectModel } private void RemoveKey(TKey key) { - Contract.Assert(key != null, "key shouldn't be null!"); + Debug.Assert(key != null, "key shouldn't be null!"); if (dict != null) { dict.Remove(key); } diff --git a/src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyCollection.cs b/src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyCollection.cs index ec7149e..a0b8b3b 100644 --- a/src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyCollection.cs +++ b/src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyCollection.cs @@ -128,7 +128,7 @@ namespace System.Collections.ObjectModel } if (index < 0) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.arrayIndex, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (array.Length - index < Count) { @@ -149,7 +149,7 @@ namespace System.Collections.ObjectModel Type targetType = array.GetType().GetElementType(); Type sourceType = typeof(T); if(!(targetType.IsAssignableFrom(sourceType) || sourceType.IsAssignableFrom(targetType))) { - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } // @@ -158,7 +158,7 @@ namespace System.Collections.ObjectModel // object[] objects = array as object[]; if( objects == null) { - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } int count = list.Count; @@ -168,7 +168,7 @@ namespace System.Collections.ObjectModel } } catch(ArrayTypeMismatchException) { - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } } } diff --git a/src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyDictionary.cs b/src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyDictionary.cs index 11833c2..5c9e8c4 100644 --- a/src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyDictionary.cs +++ b/src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyDictionary.cs @@ -34,7 +34,7 @@ namespace System.Collections.ObjectModel public ReadOnlyDictionary(IDictionary dictionary) { if (dictionary == null) { - throw new ArgumentNullException("dictionary"); + throw new ArgumentNullException(nameof(dictionary)); } Contract.EndContractBlock(); m_dictionary = dictionary; @@ -240,7 +240,7 @@ namespace System.Collections.ObjectModel } if (index < 0 || index > array.Length) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (array.Length - index < Count) { @@ -261,7 +261,7 @@ namespace System.Collections.ObjectModel else { object[] objects = array as object[]; if (objects == null) { - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } try { @@ -270,7 +270,7 @@ namespace System.Collections.ObjectModel } } catch (ArrayTypeMismatchException) { - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } } } @@ -596,7 +596,7 @@ namespace System.Collections.ObjectModel Type targetType = array.GetType().GetElementType(); Type sourceType = typeof(T); if (!(targetType.IsAssignableFrom(sourceType) || sourceType.IsAssignableFrom(targetType))) { - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } // @@ -605,7 +605,7 @@ namespace System.Collections.ObjectModel // object[] objects = array as object[]; if (objects == null) { - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } try { @@ -614,7 +614,7 @@ namespace System.Collections.ObjectModel } } catch (ArrayTypeMismatchException) { - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } } } diff --git a/src/mscorlib/src/System/Collections/SortedList.cs b/src/mscorlib/src/System/Collections/SortedList.cs index 8e3926a..4a480a2 100644 --- a/src/mscorlib/src/System/Collections/SortedList.cs +++ b/src/mscorlib/src/System/Collections/SortedList.cs @@ -60,10 +60,8 @@ namespace System.Collections { // [DebuggerTypeProxy(typeof(System.Collections.SortedList.SortedListDebugView))] [DebuggerDisplay("Count = {Count}")] -[System.Runtime.InteropServices.ComVisible(true)] -#if FEATURE_CORECLR + [System.Runtime.InteropServices.ComVisible(true)] [Obsolete("Non-generic collections have been deprecated. Please use collections in System.Collections.Generic.")] -#endif [Serializable] public class SortedList : IDictionary, ICloneable { @@ -107,7 +105,7 @@ namespace System.Collections { // public SortedList(int initialCapacity) { if (initialCapacity < 0) - throw new ArgumentOutOfRangeException("initialCapacity", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(initialCapacity), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); keys = new Object[initialCapacity]; values = new Object[initialCapacity]; @@ -164,7 +162,7 @@ namespace System.Collections { public SortedList(IDictionary d, IComparer comparer) : this(comparer, (d != null ? d.Count : 0)) { if (d==null) - throw new ArgumentNullException("d", Environment.GetResourceString("ArgumentNull_Dictionary")); + throw new ArgumentNullException(nameof(d), Environment.GetResourceString("ArgumentNull_Dictionary")); Contract.EndContractBlock(); d.Keys.CopyTo(keys, 0); d.Values.CopyTo(values, 0); @@ -176,7 +174,7 @@ namespace System.Collections { // ArgumentException is thrown if the key is already present in the sorted list. // public virtual void Add(Object key, Object value) { - if (key == null) throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key")); + if (key == null) throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key")); Contract.EndContractBlock(); int i = Array.BinarySearch(keys, 0, _size, key, comparer); if (i >= 0) @@ -196,7 +194,7 @@ namespace System.Collections { } set { if (value < Count) { - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity")); + throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity")); } Contract.EndContractBlock(); @@ -213,7 +211,7 @@ namespace System.Collections { } else { // size can only be zero here. - Contract.Assert( _size == 0, "Size is not zero"); + Debug.Assert( _size == 0, "Size is not zero"); keys = emptyArray; values = emptyArray; } @@ -325,11 +323,11 @@ namespace System.Collections { // Copies the values in this SortedList to an array. public virtual void CopyTo(Array array, int arrayIndex) { if (array == null) - throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Array")); + throw new ArgumentNullException(nameof(array), Environment.GetResourceString("ArgumentNull_Array")); if (array.Rank != 1) throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported")); if (arrayIndex < 0) - throw new ArgumentOutOfRangeException("arrayIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(arrayIndex), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (array.Length - arrayIndex < Count) throw new ArgumentException(Environment.GetResourceString("Arg_ArrayPlusOffTooSmall")); Contract.EndContractBlock(); @@ -368,7 +366,7 @@ namespace System.Collections { // public virtual Object GetByIndex(int index) { if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.EndContractBlock(); return values[index]; } @@ -394,7 +392,7 @@ namespace System.Collections { // Returns the key of the entry at the given index. // public virtual Object GetKey(int index) { - if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.EndContractBlock(); return keys[index]; } @@ -442,7 +440,7 @@ namespace System.Collections { return null; } set { - if (key == null) throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key")); + if (key == null) throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key")); Contract.EndContractBlock(); int i = Array.BinarySearch(keys, 0, _size, key, comparer); if (i >= 0) { @@ -463,7 +461,7 @@ namespace System.Collections { // public virtual int IndexOfKey(Object key) { if (key == null) - throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key")); + throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key")); Contract.EndContractBlock(); int ret = Array.BinarySearch(keys, 0, _size, key, comparer); return ret >=0 ? ret : -1; @@ -496,7 +494,7 @@ namespace System.Collections { // decreased by one. // public virtual void RemoveAt(int index) { - if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.EndContractBlock(); _size--; if (index < _size) { @@ -522,7 +520,7 @@ namespace System.Collections { // the given entry is overwritten. // public virtual void SetByIndex(int index, Object value) { - if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.EndContractBlock(); values[index] = value; version++; @@ -530,10 +528,9 @@ namespace System.Collections { // Returns a thread-safe SortedList. // - [HostProtection(Synchronization=true)] public static SortedList Synchronized(SortedList list) { if (list==null) - throw new ArgumentNullException("list"); + throw new ArgumentNullException(nameof(list)); Contract.EndContractBlock(); return new SyncSortedList(list); } @@ -677,7 +674,7 @@ namespace System.Collections { public override int IndexOfKey(Object key) { if (key == null) - throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key")); + throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key")); Contract.EndContractBlock(); lock(_root) { @@ -888,7 +885,7 @@ namespace System.Collections { public virtual int IndexOf(Object key) { if (key==null) - throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key")); + throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key")); Contract.EndContractBlock(); int i = Array.BinarySearch(sortedList.keys, 0, @@ -993,7 +990,7 @@ namespace System.Collections { public SortedListDebugView( SortedList sortedList) { if( sortedList == null) { - throw new ArgumentNullException("sortedList"); + throw new ArgumentNullException(nameof(sortedList)); } Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/Collections/Stack.cs b/src/mscorlib/src/System/Collections/Stack.cs index 0384a4e..c3ad15a 100644 --- a/src/mscorlib/src/System/Collections/Stack.cs +++ b/src/mscorlib/src/System/Collections/Stack.cs @@ -44,7 +44,7 @@ namespace System.Collections { // must be a non-negative number. public Stack(int initialCapacity) { if (initialCapacity < 0) - throw new ArgumentOutOfRangeException("initialCapacity", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(initialCapacity), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); if (initialCapacity < _defaultCapacity) initialCapacity = _defaultCapacity; // Simplify doubling logic in Push. @@ -59,7 +59,7 @@ namespace System.Collections { public Stack(ICollection col) : this((col==null ? 32 : col.Count)) { if (col==null) - throw new ArgumentNullException("col"); + throw new ArgumentNullException(nameof(col)); Contract.EndContractBlock(); IEnumerator en = col.GetEnumerator(); while(en.MoveNext()) @@ -121,11 +121,11 @@ namespace System.Collections { // Copies the stack into an array. public virtual void CopyTo(Array array, int index) { if (array==null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); if (array.Rank != 1) throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported")); if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (array.Length - index < _size) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -189,10 +189,9 @@ namespace System.Collections { // Returns a synchronized Stack. // - [HostProtection(Synchronization=true)] public static Stack Synchronized(Stack stack) { if (stack==null) - throw new ArgumentNullException("stack"); + throw new ArgumentNullException(nameof(stack)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); return new SyncStack(stack); @@ -363,7 +362,7 @@ namespace System.Collections { public StackDebugView( Stack stack) { if( stack == null) - throw new ArgumentNullException("stack"); + throw new ArgumentNullException(nameof(stack)); Contract.EndContractBlock(); this.stack = stack; diff --git a/src/mscorlib/src/System/CompatibilitySwitches.cs b/src/mscorlib/src/System/CompatibilitySwitches.cs index 7facf85..bb2f02a 100644 --- a/src/mscorlib/src/System/CompatibilitySwitches.cs +++ b/src/mscorlib/src/System/CompatibilitySwitches.cs @@ -2,8 +2,6 @@ // 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.Runtime; using System.Runtime.CompilerServices; namespace System @@ -12,16 +10,7 @@ namespace System internal static class CompatibilitySwitches { private static bool s_AreSwitchesSet; - -#if FEATURE_CORECLR private static bool s_useLatestBehaviorWhenTFMNotSpecified; // Which behavior to use when the TFM is not specified. -#endif //FEATURE_CORECLR - -#if !FEATURE_CORECLR - private static bool s_isNetFx40TimeSpanLegacyFormatMode; - private static bool s_isNetFx40LegacySecurityPolicy; - private static bool s_isNetFx45LegacyManagedDeflateStream; -#endif //!FEATURE_CORECLR public static bool IsCompatibilityBehaviorDefined { @@ -39,67 +28,14 @@ namespace System internal static void InitializeSwitches() { -#if FEATURE_CORECLR - s_useLatestBehaviorWhenTFMNotSpecified = IsCompatibilitySwitchSet("UseLatestBehaviorWhenTFMNotSpecified"); -#endif //FEATURE_CORECLR - -#if !FEATURE_CORECLR - s_isNetFx40TimeSpanLegacyFormatMode = IsCompatibilitySwitchSet("NetFx40_TimeSpanLegacyFormatMode"); - s_isNetFx40LegacySecurityPolicy = IsCompatibilitySwitchSet("NetFx40_LegacySecurityPolicy"); - s_isNetFx45LegacyManagedDeflateStream = IsCompatibilitySwitchSet("NetFx45_LegacyManagedDeflateStream"); -#endif //FEATURE_CORECLR - s_AreSwitchesSet = true; } -#if FEATURE_CORECLR - /// - /// This property returns whether to give the latest behavior when the TFM is missing - /// - internal static bool UseLatestBehaviorWhenTFMNotSpecified - { - get - { - return s_useLatestBehaviorWhenTFMNotSpecified; - } - } -#else //FEATURE_CORECLR - - public static bool IsAppEarlierThanSilverlight4 - { - get - { - return false; - } - } - - public static bool IsAppEarlierThanWindowsPhone8 - { - get - { - return false; - } - } - - public static bool IsAppEarlierThanWindowsPhoneMango - { - get - { - return false; - } - } - -#endif //FEATURE_CORECLR - public static bool IsNetFx40TimeSpanLegacyFormatMode { get { -#if !FEATURE_CORECLR - return s_isNetFx40TimeSpanLegacyFormatMode; -#else return false; -#endif //!FEATURE_CORECLR } } @@ -107,11 +43,7 @@ namespace System { get { -#if !FEATURE_CORECLR - return s_isNetFx40LegacySecurityPolicy; -#else return false; -#endif //!FEATURE_CORECLR } } @@ -119,11 +51,7 @@ namespace System { get { -#if !FEATURE_CORECLR - return s_isNetFx45LegacyManagedDeflateStream; -#else return false; -#endif //!FEATURE_CORECLR } } } diff --git a/src/mscorlib/src/System/ContextBoundObject.cs b/src/mscorlib/src/System/ContextBoundObject.cs deleted file mode 100644 index 01929da..0000000 --- a/src/mscorlib/src/System/ContextBoundObject.cs +++ /dev/null @@ -1,24 +0,0 @@ -// 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. - -/*============================================================ -** -** -** Purpose: Defines the root type for all context bound types -** -** -===========================================================*/ -namespace System { - - using System; - using System.Security.Permissions; - [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] -#if FEATURE_REMOTING - public abstract class ContextBoundObject : MarshalByRefObject { -#else // FEATURE_REMOTING - public abstract class ContextBoundObject { -#endif // FEATURE_REMOTING - } -} diff --git a/src/mscorlib/src/System/ContextStaticAttribute.cs b/src/mscorlib/src/System/ContextStaticAttribute.cs deleted file mode 100644 index b875aa3..0000000 --- a/src/mscorlib/src/System/ContextStaticAttribute.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. -// See the LICENSE file in the project root for more information. - -/*============================================================ -** -** -** -** -** Purpose: Custom attribute to indicate that the field should be treated -** as a static relative to a context. -** -** -** -===========================================================*/ -namespace System { - - using System; - using System.Runtime.Remoting; -[Serializable] - [AttributeUsage(AttributeTargets.Field, Inherited = false)] - [System.Runtime.InteropServices.ComVisible(true)] -#if FEATURE_CORECLR - [Obsolete("ContextStaticAttribute is not supported in this release. It has been left in so that legacy tools can be used with this release, but it cannot be used in your code.", true)] -#endif // FEATURE_CORECLR - public class ContextStaticAttribute : Attribute - { - public ContextStaticAttribute() - { - } - } -} diff --git a/src/mscorlib/src/System/Convert.cs b/src/mscorlib/src/System/Convert.cs index d146831..0e14f93 100644 --- a/src/mscorlib/src/System/Convert.cs +++ b/src/mscorlib/src/System/Convert.cs @@ -19,6 +19,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; +using System.Diagnostics; using System.Diagnostics.Contracts; @@ -146,13 +147,13 @@ namespace System { #if _DEBUG private static bool TriggerAsserts = DoAsserts(); private static bool DoAsserts() { - Contract.Assert(ConvertTypes!=null, "[Convert.cctor]ConvertTypes!=null"); - Contract.Assert(ConvertTypes.Length == ((int)TypeCode.String + 1), "[Convert.cctor]ConvertTypes.Length == ((int)TypeCode.String + 1)"); - Contract.Assert(ConvertTypes[(int)TypeCode.Empty]==typeof(System.Empty), + Debug.Assert(ConvertTypes!=null, "[Convert.cctor]ConvertTypes!=null"); + Debug.Assert(ConvertTypes.Length == ((int)TypeCode.String + 1), "[Convert.cctor]ConvertTypes.Length == ((int)TypeCode.String + 1)"); + Debug.Assert(ConvertTypes[(int)TypeCode.Empty]==typeof(System.Empty), "[Convert.cctor]ConvertTypes[(int)TypeCode.Empty]==typeof(System.Empty)"); - Contract.Assert(ConvertTypes[(int)TypeCode.String]==typeof(String), + Debug.Assert(ConvertTypes[(int)TypeCode.String]==typeof(String), "[Convert.cctor]ConvertTypes[(int)TypeCode.String]==typeof(System.String)"); - Contract.Assert(ConvertTypes[(int)TypeCode.Int32]==typeof(int), + Debug.Assert(ConvertTypes[(int)TypeCode.Int32]==typeof(int), "[Convert.cctor]ConvertTypes[(int)TypeCode.Int32]==typeof(int)"); return true; } @@ -259,7 +260,7 @@ namespace System { internal static Object DefaultToType(IConvertible value, Type targetType, IFormatProvider provider) { Contract.Requires(value != null, "[Convert.DefaultToType]value!=null"); if (targetType==null) { - throw new ArgumentNullException("targetType"); + throw new ArgumentNullException(nameof(targetType)); } Contract.EndContractBlock(); @@ -322,7 +323,7 @@ namespace System { public static Object ChangeType(Object value, Type conversionType, IFormatProvider provider) { if( conversionType == null) { - throw new ArgumentNullException("conversionType"); + throw new ArgumentNullException(nameof(conversionType)); } Contract.EndContractBlock(); @@ -575,7 +576,7 @@ namespace System { public static char ToChar(String value, IFormatProvider provider) { if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); Contract.EndContractBlock(); if (value.Length != 1) @@ -1129,7 +1130,6 @@ namespace System { throw new OverflowException(Environment.GetResourceString("Overflow_Int32")); } - [System.Security.SecuritySafeCritical] // auto-generated public static int ToInt32(decimal value) { return Decimal.FCallToInt32(value); } @@ -2114,7 +2114,6 @@ namespace System { } // Convert the byte value to a string in base fromBase - [System.Security.SecuritySafeCritical] // auto-generated public static String ToString (byte value, int toBase) { if (toBase!=2 && toBase!=8 && toBase!=10 && toBase!=16) { throw new ArgumentException(Environment.GetResourceString("Arg_InvalidBase")); @@ -2124,7 +2123,6 @@ namespace System { } // Convert the Int16 value to a string in base fromBase - [System.Security.SecuritySafeCritical] // auto-generated public static String ToString (short value, int toBase) { if (toBase!=2 && toBase!=8 && toBase!=10 && toBase!=16) { throw new ArgumentException(Environment.GetResourceString("Arg_InvalidBase")); @@ -2134,7 +2132,6 @@ namespace System { } // Convert the Int32 value to a string in base toBase - [System.Security.SecuritySafeCritical] // auto-generated public static String ToString (int value, int toBase) { if (toBase!=2 && toBase!=8 && toBase!=10 && toBase!=16) { throw new ArgumentException(Environment.GetResourceString("Arg_InvalidBase")); @@ -2144,7 +2141,6 @@ namespace System { } // Convert the Int64 value to a string in base toBase - [System.Security.SecuritySafeCritical] // auto-generated public static String ToString (long value, int toBase) { if (toBase!=2 && toBase!=8 && toBase!=10 && toBase!=16) { throw new ArgumentException(Environment.GetResourceString("Arg_InvalidBase")); @@ -2155,7 +2151,7 @@ namespace System { public static String ToBase64String(byte[] inArray) { if (inArray==null) { - throw new ArgumentNullException("inArray"); + throw new ArgumentNullException(nameof(inArray)); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -2165,7 +2161,7 @@ namespace System { [System.Runtime.InteropServices.ComVisible(false)] public static String ToBase64String(byte[] inArray, Base64FormattingOptions options) { if (inArray==null) { - throw new ArgumentNullException("inArray"); + throw new ArgumentNullException(nameof(inArray)); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -2176,16 +2172,15 @@ namespace System { return ToBase64String(inArray, offset, length, Base64FormattingOptions.None); } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(false)] public static unsafe String ToBase64String(byte[] inArray, int offset, int length, Base64FormattingOptions options) { //Do data verfication if (inArray==null) - throw new ArgumentNullException("inArray"); + throw new ArgumentNullException(nameof(inArray)); if (length<0) - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_Index")); if (offset<0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); + throw new ArgumentOutOfRangeException(nameof(offset), Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); if (options < Base64FormattingOptions.None || options > Base64FormattingOptions.InsertLineBreaks) throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)options)); Contract.Ensures(Contract.Result() != null); @@ -2196,7 +2191,7 @@ namespace System { inArrayLength = inArray.Length; if (offset > (inArrayLength - length)) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_OffsetLength")); + throw new ArgumentOutOfRangeException(nameof(offset), Environment.GetResourceString("ArgumentOutOfRange_OffsetLength")); if (inArrayLength == 0) return String.Empty; @@ -2223,20 +2218,19 @@ namespace System { return ToBase64CharArray(inArray, offsetIn, length, outArray, offsetOut, Base64FormattingOptions.None); } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(false)] public static unsafe int ToBase64CharArray(byte[] inArray, int offsetIn, int length, char[] outArray, int offsetOut, Base64FormattingOptions options) { //Do data verfication if (inArray==null) - throw new ArgumentNullException("inArray"); + throw new ArgumentNullException(nameof(inArray)); if (outArray==null) - throw new ArgumentNullException("outArray"); + throw new ArgumentNullException(nameof(outArray)); if (length<0) - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_Index")); if (offsetIn<0) - throw new ArgumentOutOfRangeException("offsetIn", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); + throw new ArgumentOutOfRangeException(nameof(offsetIn), Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); if (offsetOut<0) - throw new ArgumentOutOfRangeException("offsetOut", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); + throw new ArgumentOutOfRangeException(nameof(offsetOut), Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); if( options < Base64FormattingOptions.None || options > Base64FormattingOptions.InsertLineBreaks) { throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)options)); @@ -2255,7 +2249,7 @@ namespace System { inArrayLength = inArray.Length; if (offsetIn > (int)(inArrayLength - length)) - throw new ArgumentOutOfRangeException("offsetIn", Environment.GetResourceString("ArgumentOutOfRange_OffsetLength")); + throw new ArgumentOutOfRangeException(nameof(offsetIn), Environment.GetResourceString("ArgumentOutOfRange_OffsetLength")); if (inArrayLength == 0) return 0; @@ -2268,7 +2262,7 @@ namespace System { numElementsToCopy = ToBase64_CalculateAndValidateOutputLength(length, insertLineBreaks); if (offsetOut > (int)(outArrayLength - numElementsToCopy)) - throw new ArgumentOutOfRangeException("offsetOut", Environment.GetResourceString("ArgumentOutOfRange_OffsetOut")); + throw new ArgumentOutOfRangeException(nameof(offsetOut), Environment.GetResourceString("ArgumentOutOfRange_OffsetOut")); fixed (char* outChars = &outArray[offsetOut]) { fixed (byte* inData = inArray) { @@ -2279,7 +2273,6 @@ namespace System { return retVal; } - [System.Security.SecurityCritical] // auto-generated private static unsafe int ConvertToBase64Array(char* outChars, byte* inData, int offset, int length, bool insertLineBreaks) { int lengthmod3 = length%3; int calcLength = offset + (length - lengthmod3); @@ -2366,13 +2359,12 @@ namespace System { /// /// The string to convert /// The array of bytes represented by the specifed Base64 string. - [SecuritySafeCritical] public static Byte[] FromBase64String(String s) { // "s" is an unfortunate parameter name, but we need to keep it for backward compat. if (s == null) - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); Contract.EndContractBlock(); @@ -2392,20 +2384,19 @@ namespace System { /// A position within the input array. /// Number of element to convert. /// The array of bytes represented by the specified Base64 encoding characters. - [SecuritySafeCritical] public static Byte[] FromBase64CharArray(Char[] inArray, Int32 offset, Int32 length) { if (inArray == null) - throw new ArgumentNullException("inArray"); + throw new ArgumentNullException(nameof(inArray)); if (length < 0) - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_Index")); if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); + throw new ArgumentOutOfRangeException(nameof(offset), Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); if (offset > inArray.Length - length) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_OffsetLength")); + throw new ArgumentOutOfRangeException(nameof(offset), Environment.GetResourceString("ArgumentOutOfRange_OffsetLength")); Contract.EndContractBlock(); @@ -2428,12 +2419,11 @@ namespace System { /// Pointer to the first input char /// Number of input chars /// - [SecurityCritical] private static unsafe Byte[] FromBase64CharPtr(Char* inputPtr, Int32 inputLength) { // The validity of parameters much be checked by callers, thus we are Critical here. - Contract.Assert(0 <= inputLength); + Debug.Assert(0 <= inputLength); // We need to get rid of any trailing white spaces. // Otherwise we would be rejecting input such as "abc= ": @@ -2448,7 +2438,7 @@ namespace System { // Compute the output length: Int32 resultLength = FromBase64_ComputeResultLength(inputPtr, inputLength); - Contract.Assert(0 <= resultLength); + Debug.Assert(0 <= resultLength); // resultLength can be zero. We will still enter FromBase64_Decode and process the input. // It may either simply write no bytes (e.g. input = " ") or throw (e.g. input = "ab"). @@ -2482,7 +2472,6 @@ namespace System { /// Max length of the preallocated result buffer /// If the result buffer was not large enough to write all result bytes, return -1; /// Otherwise return the number of result bytes actually produced. - [SecurityCritical] private static unsafe Int32 FromBase64_Decode(Char* startInputPtr, Int32 inputLength, Byte* startDestPtr, Int32 destLength) { // You may find this method weird to look at. It’s written for performance, not aesthetics. @@ -2583,12 +2572,12 @@ namespace System { }} // unchecked while // 'd be nice to have an assert that we never get here, but CS0162: Unreachable code detected. - // Contract.Assert(false, "We only leave the above loop by jumping; should never get here."); + // Debug.Assert(false, "We only leave the above loop by jumping; should never get here."); // We jump here out of the loop if we hit an '=': _EqualityCharEncountered: - Contract.Assert(currCode == intEq); + Debug.Assert(currCode == intEq); // Recall that inputPtr is now one position past where '=' was read. // '=' can only be at the last input pos: @@ -2662,13 +2651,12 @@ namespace System { /// Walk the entire input counting white spaces and padding chars, then compute result length /// based on 3 bytes per 4 chars. /// - [SecurityCritical] private static unsafe Int32 FromBase64_ComputeResultLength(Char* inputPtr, Int32 inputLength) { const UInt32 intEq = (UInt32) '='; const UInt32 intSpace = (UInt32) ' '; - Contract.Assert(0 <= inputLength); + Debug.Assert(0 <= inputLength); Char* inputEndPtr = inputPtr + inputLength; Int32 usefulInputLength = inputLength; @@ -2691,11 +2679,11 @@ namespace System { } } - Contract.Assert(0 <= usefulInputLength); + Debug.Assert(0 <= usefulInputLength); // For legal input, we can assume that 0 <= padding < 3. But it may be more for illegal input. // We will notice it at decode when we see a '=' at the wrong place. - Contract.Assert(0 <= padding); + Debug.Assert(0 <= padding); // Perf: reuse the variable that stored the number of '=' to store the number of bytes encoded by the // last group that contains the '=': diff --git a/src/mscorlib/src/System/Currency.cs b/src/mscorlib/src/System/Currency.cs index d29ad24..05a0980 100644 --- a/src/mscorlib/src/System/Currency.cs +++ b/src/mscorlib/src/System/Currency.cs @@ -46,7 +46,6 @@ namespace System { // Converts a Currency to a Decimal. // - [System.Security.SecuritySafeCritical] // auto-generated public static Decimal ToDecimal(Currency c) { Decimal result = new Decimal (); @@ -54,7 +53,6 @@ namespace System { return result; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void FCallToDecimal(ref Decimal result,Currency c); } diff --git a/src/mscorlib/src/System/CurrentTimeZone.cs b/src/mscorlib/src/System/CurrentTimeZone.cs index f015c05..804bbcc 100644 --- a/src/mscorlib/src/System/CurrentTimeZone.cs +++ b/src/mscorlib/src/System/CurrentTimeZone.cs @@ -21,36 +21,18 @@ namespace System { using System; using System.Diagnostics.Contracts; using System.Text; - using System.Threading; using System.Collections; using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.Versioning; - // - // Currently, this is the only supported timezone. - // The values of the timezone is from the current system timezone setting in the - // control panel. - // -#if FEATURE_CORECLR [Obsolete("System.CurrentSystemTimeZone has been deprecated. Please investigate the use of System.TimeZoneInfo.Local instead.")] -#endif [Serializable] - internal class CurrentSystemTimeZone : TimeZone { - // BUGBUG : - // One problem is when user changes the current timezone. We - // are not able to update currentStandardName/currentDaylightName/ - // currentDaylightChanges. - // We need WM_TIMECHANGE to do this or use - // RegNotifyChangeKeyValue() to monitor - // - private const long TicksPerMillisecond = 10000; - private const long TicksPerSecond = TicksPerMillisecond * 1000; - private const long TicksPerMinute = TicksPerSecond * 60; - + internal class CurrentSystemTimeZone : TimeZone + { // The per-year information is cached in in this instance value. As a result it can // be cleaned up by CultureInfo.ClearCachedData, which will clear the instance of this object - private Hashtable m_CachedDaylightChanges = new Hashtable(); + private readonly Hashtable m_CachedDaylightChanges = new Hashtable(); // Standard offset in ticks to the Universal time if // no daylight saving is in used. @@ -60,43 +42,40 @@ namespace System { private String m_standardName; private String m_daylightName; - [System.Security.SecuritySafeCritical] // auto-generated - internal CurrentSystemTimeZone() { - m_ticksOffset = nativeGetTimeZoneMinuteOffset() * TicksPerMinute; - m_standardName = null; - m_daylightName = null; + internal CurrentSystemTimeZone() + { + TimeZoneInfo local = TimeZoneInfo.Local; + + m_ticksOffset = local.BaseUtcOffset.Ticks; + m_standardName = local.StandardName; + m_daylightName = local.DaylightName; } - public override String StandardName { - [System.Security.SecuritySafeCritical] // auto-generated - get { - if (m_standardName == null) { - m_standardName = nativeGetStandardName(); - } - return (m_standardName); + public override String StandardName + { + get + { + return m_standardName; } } - public override String DaylightName { - [System.Security.SecuritySafeCritical] // auto-generated - get { - if (m_daylightName == null) { - m_daylightName = nativeGetDaylightName(); - if (m_daylightName == null) { - m_daylightName = this.StandardName; - } - } - return (m_daylightName); + public override String DaylightName + { + get + { + return m_daylightName; } } - internal long GetUtcOffsetFromUniversalTime(DateTime time, ref Boolean isAmbiguousLocalDst) { + internal long GetUtcOffsetFromUniversalTime(DateTime time, ref Boolean isAmbiguousLocalDst) + { // Get the daylight changes for the year of the specified time. TimeSpan offset = new TimeSpan(m_ticksOffset); DaylightTime daylightTime = GetDaylightChanges(time.Year); isAmbiguousLocalDst= false; - if (daylightTime == null || daylightTime.Delta.Ticks == 0) { + if (daylightTime == null || daylightTime.Delta.Ticks == 0) + { return offset.Ticks; } @@ -107,119 +86,109 @@ namespace System { DateTime endTime = daylightTime.End - offset - daylightTime.Delta; DateTime ambiguousStart; DateTime ambiguousEnd; - if (daylightTime.Delta.Ticks > 0) { + + if (daylightTime.Delta.Ticks > 0) + { ambiguousStart = endTime - daylightTime.Delta; ambiguousEnd = endTime; - } else { + } + else + { ambiguousStart = startTime; ambiguousEnd = startTime - daylightTime.Delta; } Boolean isDst = false; - if (startTime > endTime) { + if (startTime > endTime) + { // In southern hemisphere, the daylight saving time starts later in the year, and ends in the beginning of next year. // Note, the summer in the southern hemisphere begins late in the year. isDst = (time < endTime || time >= startTime); } - else { + else + { // In northern hemisphere, the daylight saving time starts in the middle of the year. - isDst = (time>=startTime && time= startTime && time < endTime); } - if (isDst) { + + if (isDst) + { offset += daylightTime.Delta; // See if the resulting local time becomes ambiguous. This must be captured here or the // DateTime will not be able to round-trip back to UTC accurately. - if (time >= ambiguousStart && time < ambiguousEnd ) { + if (time >= ambiguousStart && time < ambiguousEnd ) + { isAmbiguousLocalDst = true; } } return offset.Ticks; } - public override DateTime ToLocalTime(DateTime time) { - if (time.Kind == DateTimeKind.Local) { + public override DateTime ToLocalTime(DateTime time) + { + if (time.Kind == DateTimeKind.Local) + { return time; } Boolean isAmbiguousLocalDst = false; Int64 offset = GetUtcOffsetFromUniversalTime(time, ref isAmbiguousLocalDst); long tick = time.Ticks + offset; - if (tick>DateTime.MaxTicks) { + if (tick > DateTime.MaxTicks) + { return new DateTime(DateTime.MaxTicks, DateTimeKind.Local); } - if (tick(ref s_InternalSyncObject, o, null); - } - return s_InternalSyncObject; - } + return new DateTime(tick, DateTimeKind.Local, isAmbiguousLocalDst); } - - [System.Security.SecuritySafeCritical] // auto-generated - public override DaylightTime GetDaylightChanges(int year) { - if (year < 1 || year > 9999) { - throw new ArgumentOutOfRangeException("year", Environment.GetResourceString("ArgumentOutOfRange_Range", 1, 9999)); + public override DaylightTime GetDaylightChanges(int year) + { + if (year < 1 || year > 9999) + { + throw new ArgumentOutOfRangeException(nameof(year), Environment.GetResourceString("ArgumentOutOfRange_Range", 1, 9999)); } Contract.EndContractBlock(); - Object objYear = (Object)year; - - if (!m_CachedDaylightChanges.Contains(objYear)) { - lock (InternalSyncObject) { + Object objYear = (Object) year; - if (!m_CachedDaylightChanges.Contains(objYear)) { + if (!m_CachedDaylightChanges.Contains(objYear)) + { + DaylightTime currentDaylightChanges = null; - // - // rawData is an array of 17 short (16 bit) numbers. - // The first 8 numbers contains the - // year/month/day/dayOfWeek/hour/minute/second/millisecond for the starting time of daylight saving time. - // The next 8 numbers contains the - // year/month/day/dayOfWeek/hour/minute/second/millisecond for the ending time of daylight saving time. - // The last short number is the delta to the standard offset in minutes. - // - short[] rawData = nativeGetDaylightChanges(year); + if (TimeZoneInfo.Local.SupportsDaylightSavingTime) + { + DateTime start; + DateTime end; + TimeSpan delta; - if (rawData == null) { - // - // If rawData is null, it means that daylight saving time is not used - // in this timezone. So keep currentDaylightChanges as the empty array. - // - m_CachedDaylightChanges.Add(objYear, new DaylightTime(DateTime.MinValue, DateTime.MinValue, TimeSpan.Zero)); - } else { - DateTime start; - DateTime end; - TimeSpan delta; + foreach (var rule in TimeZoneInfo.Local.GetAdjustmentRules()) + { + if (rule.DateStart.Year <= year && rule.DateEnd.Year >= year && rule.DaylightDelta != TimeSpan.Zero) + { + start = TimeZoneInfo.TransitionTimeToDateTime(year, rule.DaylightTransitionStart); + end = TimeZoneInfo.TransitionTimeToDateTime(year, rule.DaylightTransitionEnd); + delta = rule.DaylightDelta; - // - // Store the start of daylight saving time. - // - - start = GetDayOfWeek(year, (rawData[0] != 0), rawData[1], rawData[2], - rawData[3], - rawData[4], rawData[5], rawData[6], rawData[7]); + currentDaylightChanges = new DaylightTime(start, end, delta); + break; + } + } + } - // - // Store the end of daylight saving time. - // - end = GetDayOfWeek(year, (rawData[8] != 0), rawData[9], rawData[10], - rawData[11], - rawData[12], rawData[13], rawData[14], rawData[15]); + if (currentDaylightChanges == null) + { + currentDaylightChanges = new DaylightTime(DateTime.MinValue, DateTime.MinValue, TimeSpan.Zero); + } - delta = new TimeSpan(rawData[16] * TicksPerMinute); - DaylightTime currentDaylightChanges = new DaylightTime(start, end, delta); - m_CachedDaylightChanges.Add(objYear, currentDaylightChanges); - } + lock (m_CachedDaylightChanges) + { + if (!m_CachedDaylightChanges.Contains(objYear)) + { + m_CachedDaylightChanges.Add(objYear, currentDaylightChanges); } } } @@ -229,82 +198,17 @@ namespace System { return result; } - public override TimeSpan GetUtcOffset(DateTime time) { - if (time.Kind == DateTimeKind.Utc) { + public override TimeSpan GetUtcOffset(DateTime time) + { + if (time.Kind == DateTimeKind.Utc) + { return TimeSpan.Zero; } - else { + else + { return new TimeSpan(TimeZone.CalculateUtcOffset(time, GetDaylightChanges(time.Year)).Ticks + m_ticksOffset); } } - // - // Return the (numberOfSunday)th day of week in a particular year/month. - // - private static DateTime GetDayOfWeek(int year, bool fixedDate, int month, int targetDayOfWeek, int numberOfSunday, int hour, int minute, int second, int millisecond) { - DateTime time; - - if (fixedDate) { - // - // Create a Fixed-Date transition time based on the supplied parameters - // For Fixed-Dated transition times, the 'numberOfSunday' parameter actually - // represents the day of the month. - // - - // if the day is out of range for the month then use the last day of the month - int day = DateTime.DaysInMonth(year, month); - - time = new DateTime(year, month, (day < numberOfSunday) ? day : numberOfSunday, - hour, minute, second, millisecond, DateTimeKind.Local); - } - else if (numberOfSunday <= 4) { - // - // Get the (numberOfSunday)th Sunday. - // - - time = new DateTime(year, month, 1, hour, minute, second, millisecond, DateTimeKind.Local); - - int dayOfWeek = (int)time.DayOfWeek; - int delta = targetDayOfWeek - dayOfWeek; - if (delta < 0) { - delta += 7; - } - delta += 7 * (numberOfSunday - 1); - - if (delta > 0) { - time = time.AddDays(delta); - } - } else { - // - // If numberOfSunday is greater than 4, we will get the last sunday. - // - Calendar cal = GregorianCalendar.GetDefaultInstance(); - time = new DateTime(year, month, cal.GetDaysInMonth(year, month), hour, minute, second, millisecond, DateTimeKind.Local); - // This is the day of week for the last day of the month. - int dayOfWeek = (int)time.DayOfWeek; - int delta = dayOfWeek - targetDayOfWeek; - if (delta < 0) { - delta += 7; - } - - if (delta > 0) { - time = time.AddDays(-delta); - } - } - return (time); - } - - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal extern static int nativeGetTimeZoneMinuteOffset(); - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal extern static String nativeGetDaylightName(); - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal extern static String nativeGetStandardName(); - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal extern static short[] nativeGetDaylightChanges(int year); } // class CurrentSystemTimeZone } diff --git a/src/mscorlib/src/System/DBNull.cs b/src/mscorlib/src/System/DBNull.cs index 130366d..6f80af7 100644 --- a/src/mscorlib/src/System/DBNull.cs +++ b/src/mscorlib/src/System/DBNull.cs @@ -26,7 +26,6 @@ namespace System { public static readonly DBNull Value = new DBNull(); - [System.Security.SecurityCritical] public void GetObjectData(SerializationInfo info, StreamingContext context) { UnitySerializationHolder.GetUnitySerializationInfo(info, UnitySerializationHolder.NullUnity, null, null); } diff --git a/src/mscorlib/src/System/DateTime.cs b/src/mscorlib/src/System/DateTime.cs index c464549..e93346c 100644 --- a/src/mscorlib/src/System/DateTime.cs +++ b/src/mscorlib/src/System/DateTime.cs @@ -143,7 +143,7 @@ namespace System { // public DateTime(long ticks) { if (ticks < MinTicks || ticks > MaxTicks) - throw new ArgumentOutOfRangeException("ticks", Environment.GetResourceString("ArgumentOutOfRange_DateTimeBadTicks")); + throw new ArgumentOutOfRangeException(nameof(ticks), Environment.GetResourceString("ArgumentOutOfRange_DateTimeBadTicks")); Contract.EndContractBlock(); dateData = (UInt64)ticks; } @@ -154,10 +154,10 @@ namespace System { public DateTime(long ticks, DateTimeKind kind) { if (ticks < MinTicks || ticks > MaxTicks) { - throw new ArgumentOutOfRangeException("ticks", Environment.GetResourceString("ArgumentOutOfRange_DateTimeBadTicks")); + throw new ArgumentOutOfRangeException(nameof(ticks), Environment.GetResourceString("ArgumentOutOfRange_DateTimeBadTicks")); } if (kind < DateTimeKind.Unspecified || kind > DateTimeKind.Local) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDateTimeKind"), "kind"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDateTimeKind"), nameof(kind)); } Contract.EndContractBlock(); this.dateData = ((UInt64)ticks | ((UInt64)kind << KindShift)); @@ -165,7 +165,7 @@ namespace System { internal DateTime(long ticks, DateTimeKind kind, Boolean isAmbiguousDst) { if (ticks < MinTicks || ticks > MaxTicks) { - throw new ArgumentOutOfRangeException("ticks", Environment.GetResourceString("ArgumentOutOfRange_DateTimeBadTicks")); + throw new ArgumentOutOfRangeException(nameof(ticks), Environment.GetResourceString("ArgumentOutOfRange_DateTimeBadTicks")); } Contract.Requires(kind == DateTimeKind.Local, "Internal Constructor is for local times only"); Contract.EndContractBlock(); @@ -196,7 +196,7 @@ namespace System { public DateTime(int year, int month, int day, int hour, int minute, int second, DateTimeKind kind) { if (kind < DateTimeKind.Unspecified || kind > DateTimeKind.Local) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDateTimeKind"), "kind"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDateTimeKind"), nameof(kind)); } Contract.EndContractBlock(); Int64 ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second); @@ -208,7 +208,7 @@ namespace System { // public DateTime(int year, int month, int day, int hour, int minute, int second, Calendar calendar) { if (calendar == null) - throw new ArgumentNullException("calendar"); + throw new ArgumentNullException(nameof(calendar)); Contract.EndContractBlock(); this.dateData = (UInt64)calendar.ToDateTime(year, month, day, hour, minute, second, 0).Ticks; } @@ -218,7 +218,7 @@ namespace System { // public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond) { if (millisecond < 0 || millisecond >= MillisPerSecond) { - throw new ArgumentOutOfRangeException("millisecond", Environment.GetResourceString("ArgumentOutOfRange_Range", 0, MillisPerSecond - 1)); + throw new ArgumentOutOfRangeException(nameof(millisecond), Environment.GetResourceString("ArgumentOutOfRange_Range", 0, MillisPerSecond - 1)); } Contract.EndContractBlock(); Int64 ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second); @@ -230,10 +230,10 @@ namespace System { public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, DateTimeKind kind) { if (millisecond < 0 || millisecond >= MillisPerSecond) { - throw new ArgumentOutOfRangeException("millisecond", Environment.GetResourceString("ArgumentOutOfRange_Range", 0, MillisPerSecond - 1)); + throw new ArgumentOutOfRangeException(nameof(millisecond), Environment.GetResourceString("ArgumentOutOfRange_Range", 0, MillisPerSecond - 1)); } if (kind < DateTimeKind.Unspecified || kind > DateTimeKind.Local) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDateTimeKind"), "kind"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDateTimeKind"), nameof(kind)); } Contract.EndContractBlock(); Int64 ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second); @@ -248,9 +248,9 @@ namespace System { // public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar) { if (calendar == null) - throw new ArgumentNullException("calendar"); + throw new ArgumentNullException(nameof(calendar)); if (millisecond < 0 || millisecond >= MillisPerSecond) { - throw new ArgumentOutOfRangeException("millisecond", Environment.GetResourceString("ArgumentOutOfRange_Range", 0, MillisPerSecond - 1)); + throw new ArgumentOutOfRangeException(nameof(millisecond), Environment.GetResourceString("ArgumentOutOfRange_Range", 0, MillisPerSecond - 1)); } Contract.EndContractBlock(); Int64 ticks = calendar.ToDateTime(year, month, day, hour, minute, second, 0).Ticks; @@ -262,12 +262,12 @@ namespace System { public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar, DateTimeKind kind) { if (calendar == null) - throw new ArgumentNullException("calendar"); + throw new ArgumentNullException(nameof(calendar)); if (millisecond < 0 || millisecond >= MillisPerSecond) { - throw new ArgumentOutOfRangeException("millisecond", Environment.GetResourceString("ArgumentOutOfRange_Range", 0, MillisPerSecond - 1)); + throw new ArgumentOutOfRangeException(nameof(millisecond), Environment.GetResourceString("ArgumentOutOfRange_Range", 0, MillisPerSecond - 1)); } if (kind < DateTimeKind.Unspecified || kind > DateTimeKind.Local) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDateTimeKind"), "kind"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDateTimeKind"), nameof(kind)); } Contract.EndContractBlock(); Int64 ticks = calendar.ToDateTime(year, month, day, hour, minute, second, 0).Ticks; @@ -279,7 +279,7 @@ namespace System { private DateTime(SerializationInfo info, StreamingContext context) { if (info==null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); Boolean foundTicks = false; @@ -346,7 +346,7 @@ namespace System { private DateTime Add(double value, int scale) { long millis = (long)(value * scale + (value >= 0? 0.5: -0.5)); if (millis <= -MaxMillis || millis >= MaxMillis) - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_AddValue")); + throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_AddValue")); return AddTicks(millis * TicksPerMillisecond); } @@ -408,7 +408,7 @@ namespace System { // y1. // public DateTime AddMonths(int months) { - if (months < -120000 || months > 120000) throw new ArgumentOutOfRangeException("months", Environment.GetResourceString("ArgumentOutOfRange_DateTimeBadMonths")); + if (months < -120000 || months > 120000) throw new ArgumentOutOfRangeException(nameof(months), Environment.GetResourceString("ArgumentOutOfRange_DateTimeBadMonths")); Contract.EndContractBlock(); int y = GetDatePart(DatePartYear); int m = GetDatePart(DatePartMonth); @@ -423,7 +423,7 @@ namespace System { y = y + (i - 11) / 12; } if (y < 1 || y > 9999) { - throw new ArgumentOutOfRangeException("months", Environment.GetResourceString("ArgumentOutOfRange_DateArithmetic")); + throw new ArgumentOutOfRangeException(nameof(months), Environment.GetResourceString("ArgumentOutOfRange_DateArithmetic")); } int days = DaysInMonth(y, m); if (d > days) d = days; @@ -447,7 +447,7 @@ namespace System { public DateTime AddTicks(long value) { long ticks = InternalTicks; if (value > MaxTicks - ticks || value < MinTicks - ticks) { - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_DateArithmetic")); + throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_DateArithmetic")); } return new DateTime((UInt64)(ticks + value) | InternalKind); } @@ -527,7 +527,7 @@ namespace System { // month arguments. // public static int DaysInMonth(int year, int month) { - if (month < 1 || month > 12) throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month")); + if (month < 1 || month > 12) throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Month")); Contract.EndContractBlock(); // IsLeapYear checks the year argument int[] days = IsLeapYear(year)? DaysToMonth366: DaysToMonth365; @@ -556,20 +556,6 @@ namespace System { return millis * TicksPerMillisecond; } -#if !FEATURE_CORECLR - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SecurityCritical] - [SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool LegacyParseMode(); - - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SecurityCritical] - [SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool EnableAmPmParseAdjustment(); -#endif - // Checks if this DateTime is equal to a given object. Returns // true if the given object is a boxed DateTime and its value // is equal to the value of this DateTime. Returns false @@ -629,7 +615,7 @@ namespace System { ticks += TicksPerDay; } if (ticks < MinTicks || ticks > MaxTicks) { - throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeBadBinaryData"), "dateData"); + throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeBadBinaryData"), nameof(dateData)); } return new DateTime(ticks, DateTimeKind.Local, isAmbiguousLocalDst); } @@ -643,7 +629,7 @@ namespace System { internal static DateTime FromBinaryRaw(Int64 dateData) { Int64 ticks = dateData & (Int64)TicksMask; if (ticks < MinTicks || ticks > MaxTicks) - throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeBadBinaryData"), "dateData"); + throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeBadBinaryData"), nameof(dateData)); return new DateTime((UInt64)dateData); } @@ -657,7 +643,7 @@ namespace System { public static DateTime FromFileTimeUtc(long fileTime) { if (fileTime < 0 || fileTime > MaxTicks - FileTimeOffset) { - throw new ArgumentOutOfRangeException("fileTime", Environment.GetResourceString("ArgumentOutOfRange_FileTimeInvalid")); + throw new ArgumentOutOfRangeException(nameof(fileTime), Environment.GetResourceString("ArgumentOutOfRange_FileTimeInvalid")); } Contract.EndContractBlock(); @@ -675,7 +661,7 @@ namespace System { [System.Security.SecurityCritical /*auto-generated_required*/] void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); @@ -775,7 +761,7 @@ namespace System { int[] days = leapYear? DaysToMonth366: DaysToMonth365; // All months have less than 32 days, so n >> 5 is a good conservative // estimate for the month - int m = n >> 5 + 1; + int m = (n >> 5) + 1; // m = 1-based month number while (n >= days[m]) m++; // If month was requested, return it @@ -912,7 +898,6 @@ namespace System { } public static DateTime UtcNow { - [System.Security.SecuritySafeCritical] // auto-generated get { Contract.Ensures(Contract.Result().Kind == DateTimeKind.Utc); // following code is tuned for speed. Don't change it without running benchmark. @@ -924,7 +909,6 @@ namespace System { } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern long GetSystemTimeAsFileTime(); @@ -985,7 +969,7 @@ namespace System { // public static bool IsLeapYear(int year) { if (year < 1 || year > 9999) { - throw new ArgumentOutOfRangeException("year", Environment.GetResourceString("ArgumentOutOfRange_Year")); + throw new ArgumentOutOfRangeException(nameof(year), Environment.GetResourceString("ArgumentOutOfRange_Year")); } Contract.EndContractBlock(); return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); @@ -1008,7 +992,7 @@ namespace System { } public static DateTime Parse(String s, IFormatProvider provider, DateTimeStyles styles) { - DateTimeFormatInfo.ValidateStyles(styles, "styles"); + DateTimeFormatInfo.ValidateStyles(styles, nameof(styles)); return (DateTimeParse.Parse(s, DateTimeFormatInfo.GetInstance(provider), styles)); } @@ -1025,12 +1009,12 @@ namespace System { // Leading and trailing whitespace characters are allowed. // public static DateTime ParseExact(String s, String format, IFormatProvider provider, DateTimeStyles style) { - DateTimeFormatInfo.ValidateStyles(style, "style"); + DateTimeFormatInfo.ValidateStyles(style, nameof(style)); return (DateTimeParse.ParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), style)); } public static DateTime ParseExact(String s, String[] formats, IFormatProvider provider, DateTimeStyles style) { - DateTimeFormatInfo.ValidateStyles(style, "style"); + DateTimeFormatInfo.ValidateStyles(style, nameof(style)); return DateTimeParse.ParseExactMultiple(s, formats, DateTimeFormatInfo.GetInstance(provider), style); } @@ -1042,7 +1026,7 @@ namespace System { long ticks = InternalTicks; long valueTicks = value._ticks; if (ticks - MinTicks < valueTicks || ticks - MaxTicks > valueTicks) { - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_DateArithmetic")); + throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_DateArithmetic")); } return new DateTime((UInt64)(ticks - valueTicks) | InternalKind); } @@ -1166,17 +1150,17 @@ namespace System { } public static Boolean TryParse(String s, IFormatProvider provider, DateTimeStyles styles, out DateTime result) { - DateTimeFormatInfo.ValidateStyles(styles, "styles"); + DateTimeFormatInfo.ValidateStyles(styles, nameof(styles)); return DateTimeParse.TryParse(s, DateTimeFormatInfo.GetInstance(provider), styles, out result); } public static Boolean TryParseExact(String s, String format, IFormatProvider provider, DateTimeStyles style, out DateTime result) { - DateTimeFormatInfo.ValidateStyles(style, "style"); + DateTimeFormatInfo.ValidateStyles(style, nameof(style)); return DateTimeParse.TryParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), style, out result); } public static Boolean TryParseExact(String s, String[] formats, IFormatProvider provider, DateTimeStyles style, out DateTime result) { - DateTimeFormatInfo.ValidateStyles(style, "style"); + DateTimeFormatInfo.ValidateStyles(style, nameof(style)); return DateTimeParse.TryParseExactMultiple(s, formats, DateTimeFormatInfo.GetInstance(provider), style, out result); } @@ -1184,7 +1168,7 @@ namespace System { long ticks = d.InternalTicks; long valueTicks = t._ticks; if (valueTicks > MaxTicks - ticks || valueTicks < MinTicks - ticks) { - throw new ArgumentOutOfRangeException("t", Environment.GetResourceString("ArgumentOutOfRange_DateArithmetic")); + throw new ArgumentOutOfRangeException(nameof(t), Environment.GetResourceString("ArgumentOutOfRange_DateArithmetic")); } return new DateTime((UInt64)(ticks + valueTicks) | d.InternalKind); } @@ -1193,7 +1177,7 @@ namespace System { long ticks = d.InternalTicks; long valueTicks = t._ticks; if (ticks - MinTicks < valueTicks || ticks - MaxTicks > valueTicks) { - throw new ArgumentOutOfRangeException("t", Environment.GetResourceString("ArgumentOutOfRange_DateArithmetic")); + throw new ArgumentOutOfRangeException(nameof(t), Environment.GetResourceString("ArgumentOutOfRange_DateArithmetic")); } return new DateTime((UInt64)(ticks - valueTicks) | d.InternalKind); } diff --git a/src/mscorlib/src/System/DateTimeOffset.cs b/src/mscorlib/src/System/DateTimeOffset.cs index 3e63c76..5bdaa18 100644 --- a/src/mscorlib/src/System/DateTimeOffset.cs +++ b/src/mscorlib/src/System/DateTimeOffset.cs @@ -11,6 +11,7 @@ namespace System { using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Security.Permissions; + using System.Diagnostics; using System.Diagnostics.Contracts; // DateTimeOffset is a value type that consists of a DateTime and a time zone offset, @@ -87,12 +88,12 @@ namespace System { public DateTimeOffset(DateTime dateTime, TimeSpan offset) { if (dateTime.Kind == DateTimeKind.Local) { if (offset != TimeZoneInfo.GetLocalUtcOffset(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime)) { - throw new ArgumentException(Environment.GetResourceString("Argument_OffsetLocalMismatch"), "offset"); + throw new ArgumentException(Environment.GetResourceString("Argument_OffsetLocalMismatch"), nameof(offset)); } } else if (dateTime.Kind == DateTimeKind.Utc) { if (offset != TimeSpan.Zero) { - throw new ArgumentException(Environment.GetResourceString("Argument_OffsetUtcMismatch"), "offset"); + throw new ArgumentException(Environment.GetResourceString("Argument_OffsetUtcMismatch"), nameof(offset)); } } m_offsetMinutes = ValidateOffset(offset); @@ -479,7 +480,7 @@ namespace System { public static DateTimeOffset FromUnixTimeSeconds(long seconds) { if (seconds < UnixMinSeconds || seconds > UnixMaxSeconds) { - throw new ArgumentOutOfRangeException("seconds", + throw new ArgumentOutOfRangeException(nameof(seconds), string.Format(Environment.GetResourceString("ArgumentOutOfRange_Range"), UnixMinSeconds, UnixMaxSeconds)); } @@ -492,7 +493,7 @@ namespace System { const long MaxMilliseconds = DateTime.MaxTicks / TimeSpan.TicksPerMillisecond - UnixEpochMilliseconds; if (milliseconds < MinMilliseconds || milliseconds > MaxMilliseconds) { - throw new ArgumentOutOfRangeException("milliseconds", + throw new ArgumentOutOfRangeException(nameof(milliseconds), string.Format(Environment.GetResourceString("ArgumentOutOfRange_Range"), MinMilliseconds, MaxMilliseconds)); } @@ -513,10 +514,9 @@ namespace System { } - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); @@ -528,7 +528,7 @@ namespace System { DateTimeOffset(SerializationInfo info, StreamingContext context) { if (info == null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } m_dateTime = (DateTime)info.GetValue("DateTime", typeof(DateTime)); @@ -563,7 +563,7 @@ namespace System { } public static DateTimeOffset Parse(String input, IFormatProvider formatProvider, DateTimeStyles styles) { - styles = ValidateStyles(styles, "styles"); + styles = ValidateStyles(styles, nameof(styles)); TimeSpan offset; DateTime dateResult = DateTimeParse.Parse(input, DateTimeFormatInfo.GetInstance(formatProvider), @@ -585,7 +585,7 @@ namespace System { // Leading and trailing whitespace characters are allowed. // public static DateTimeOffset ParseExact(String input, String format, IFormatProvider formatProvider, DateTimeStyles styles) { - styles = ValidateStyles(styles, "styles"); + styles = ValidateStyles(styles, nameof(styles)); TimeSpan offset; DateTime dateResult = DateTimeParse.ParseExact(input, format, @@ -596,7 +596,7 @@ namespace System { } public static DateTimeOffset ParseExact(String input, String[] formats, IFormatProvider formatProvider, DateTimeStyles styles) { - styles = ValidateStyles(styles, "styles"); + styles = ValidateStyles(styles, nameof(styles)); TimeSpan offset; DateTime dateResult = DateTimeParse.ParseExactMultiple(input, formats, @@ -693,7 +693,7 @@ namespace System { } public static Boolean TryParse(String input, IFormatProvider formatProvider, DateTimeStyles styles, out DateTimeOffset result) { - styles = ValidateStyles(styles, "styles"); + styles = ValidateStyles(styles, nameof(styles)); TimeSpan offset; DateTime dateResult; Boolean parsed = DateTimeParse.TryParse(input, @@ -707,7 +707,7 @@ namespace System { public static Boolean TryParseExact(String input, String format, IFormatProvider formatProvider, DateTimeStyles styles, out DateTimeOffset result) { - styles = ValidateStyles(styles, "styles"); + styles = ValidateStyles(styles, nameof(styles)); TimeSpan offset; DateTime dateResult; Boolean parsed = DateTimeParse.TryParseExact(input, @@ -722,7 +722,7 @@ namespace System { public static Boolean TryParseExact(String input, String[] formats, IFormatProvider formatProvider, DateTimeStyles styles, out DateTimeOffset result) { - styles = ValidateStyles(styles, "styles"); + styles = ValidateStyles(styles, nameof(styles)); TimeSpan offset; DateTime dateResult; Boolean parsed = DateTimeParse.TryParseExactMultiple(input, @@ -739,10 +739,10 @@ namespace System { private static Int16 ValidateOffset(TimeSpan offset) { Int64 ticks = offset.Ticks; if (ticks % TimeSpan.TicksPerMinute != 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_OffsetPrecision"), "offset"); + throw new ArgumentException(Environment.GetResourceString("Argument_OffsetPrecision"), nameof(offset)); } if (ticks < MinOffset || ticks > MaxOffset) { - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("Argument_OffsetOutOfRange")); + throw new ArgumentOutOfRangeException(nameof(offset), Environment.GetResourceString("Argument_OffsetOutOfRange")); } return (Int16)(offset.Ticks / TimeSpan.TicksPerMinute); } @@ -751,12 +751,12 @@ namespace System { private static DateTime ValidateDate(DateTime dateTime, TimeSpan offset) { // The key validation is that both the UTC and clock times fit. The clock time is validated // by the DateTime constructor. - Contract.Assert(offset.Ticks >= MinOffset && offset.Ticks <= MaxOffset, "Offset not validated."); + Debug.Assert(offset.Ticks >= MinOffset && offset.Ticks <= MaxOffset, "Offset not validated."); // This operation cannot overflow because offset should have already been validated to be within // 14 hours and the DateTime instance is more than that distance from the boundaries of Int64. Int64 utcTicks = dateTime.Ticks - offset.Ticks; if (utcTicks < DateTime.MinTicks || utcTicks > DateTime.MaxTicks) { - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("Argument_UTCOutOfRange")); + throw new ArgumentOutOfRangeException(nameof(offset), Environment.GetResourceString("Argument_UTCOutOfRange")); } // make sure the Kind is set to Unspecified // diff --git a/src/mscorlib/src/System/Decimal.cs b/src/mscorlib/src/System/Decimal.cs index 8a2c30f..fd16697 100644 --- a/src/mscorlib/src/System/Decimal.cs +++ b/src/mscorlib/src/System/Decimal.cs @@ -206,13 +206,11 @@ namespace System { // Constructs a Decimal from a float value. // - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern Decimal(float value); // Constructs a Decimal from a double value. // - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern Decimal(double value); @@ -264,7 +262,7 @@ namespace System { private void SetBits(int[] bits) { if (bits==null) - throw new ArgumentNullException("bits"); + throw new ArgumentNullException(nameof(bits)); Contract.EndContractBlock(); if (bits.Length == 4) { int f = bits[3]; @@ -283,7 +281,7 @@ namespace System { // public Decimal(int lo, int mid, int hi, bool isNegative, byte scale) { if (scale > 28) - throw new ArgumentOutOfRangeException("scale", Environment.GetResourceString("ArgumentOutOfRange_DecimalScale")); + throw new ArgumentOutOfRangeException(nameof(scale), Environment.GetResourceString("ArgumentOutOfRange_DecimalScale")); Contract.EndContractBlock(); this.lo = lo; this.mid = mid; @@ -335,7 +333,6 @@ namespace System { // Adds two Decimal values. // - [System.Security.SecuritySafeCritical] // auto-generated public static Decimal Add(Decimal d1, Decimal d2) { FCallAddSub (ref d1, ref d2, DECIMAL_ADD); @@ -346,11 +343,9 @@ namespace System { // of the operation. Passing in DECIMAL_ADD or DECIMAL_NEG for bSign indicates // addition or subtraction, respectively. // - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void FCallAddSub(ref Decimal d1, ref Decimal d2, byte bSign); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void FCallAddSubOverflowed(ref Decimal d1, ref Decimal d2, byte bSign, ref bool overflowed); @@ -363,13 +358,11 @@ namespace System { // Compares two Decimal values, returning an integer that indicates their // relationship. // - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static int Compare(Decimal d1, Decimal d2) { return FCallCompare(ref d1, ref d2); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] private static extern int FCallCompare(ref Decimal d1, ref Decimal d2); @@ -380,7 +373,6 @@ namespace System { // null is considered to be less than any instance. // If object is not of type Decimal, this method throws an ArgumentException. // - [System.Security.SecuritySafeCritical] // auto-generated public int CompareTo(Object value) { if (value == null) @@ -392,7 +384,6 @@ namespace System { return FCallCompare(ref this, ref other); } - [System.Security.SecuritySafeCritical] // auto-generated public int CompareTo(Decimal value) { return FCallCompare(ref this, ref value); @@ -400,7 +391,6 @@ namespace System { // Divides two Decimal values. // - [System.Security.SecuritySafeCritical] // auto-generated public static Decimal Divide(Decimal d1, Decimal d2) { FCallDivide (ref d1, ref d2); @@ -410,11 +400,9 @@ namespace System { // FCallDivide divides two decimal values. On return, d1 contains the result // of the operation. // - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void FCallDivide(ref Decimal d1, ref Decimal d2); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void FCallDivideOverflowed(ref Decimal d1, ref Decimal d2, ref bool overflowed); @@ -423,7 +411,6 @@ namespace System { // if the given object is a boxed Decimal and its value is equal to the // value of this Decimal. Returns false otherwise. // - [System.Security.SecuritySafeCritical] // auto-generated public override bool Equals(Object value) { if (value is Decimal) { Decimal other = (Decimal)value; @@ -432,7 +419,6 @@ namespace System { return false; } - [System.Security.SecuritySafeCritical] // auto-generated public bool Equals(Decimal value) { return FCallCompare(ref this, ref value) == 0; @@ -440,14 +426,12 @@ namespace System { // Returns the hash code for this Decimal. // - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern override int GetHashCode(); // Compares two Decimal values for equality. Returns true if the two // Decimal values are equal, or false if they are not equal. // - [System.Security.SecuritySafeCritical] // auto-generated public static bool Equals(Decimal d1, Decimal d2) { return FCallCompare(ref d1, ref d2) == 0; } @@ -455,14 +439,12 @@ namespace System { // Rounds a Decimal to an integer value. The Decimal argument is rounded // towards negative infinity. // - [System.Security.SecuritySafeCritical] // auto-generated public static Decimal Floor(Decimal d) { FCallFloor (ref d); return d; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void FCallFloor(ref Decimal d); @@ -471,25 +453,21 @@ namespace System { // optionally followed by a decimal point (".") and another sequence of // digits. // - [System.Security.SecuritySafeCritical] // auto-generated public override String ToString() { Contract.Ensures(Contract.Result() != null); return Number.FormatDecimal(this, null, NumberFormatInfo.CurrentInfo); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(String format) { Contract.Ensures(Contract.Result() != null); return Number.FormatDecimal(this, format, NumberFormatInfo.CurrentInfo); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(IFormatProvider provider) { Contract.Ensures(Contract.Result() != null); return Number.FormatDecimal(this, null, NumberFormatInfo.GetInstance(provider)); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(String format, IFormatProvider provider) { Contract.Ensures(Contract.Result() != null); return Number.FormatDecimal(this, format, NumberFormatInfo.GetInstance(provider)); @@ -650,7 +628,6 @@ namespace System { // Returns the larger of two Decimal values. // - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal static Decimal Max(Decimal d1, Decimal d2) { return FCallCompare(ref d1, ref d2) >= 0? d1: d2; @@ -658,7 +635,6 @@ namespace System { // Returns the smaller of two Decimal values. // - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal static Decimal Min(Decimal d1, Decimal d2) { return FCallCompare(ref d1, ref d2) < 0? d1: d2; @@ -709,7 +685,6 @@ namespace System { // Multiplies two Decimal values. // - [System.Security.SecuritySafeCritical] // auto-generated public static Decimal Multiply(Decimal d1, Decimal d2) { FCallMultiply (ref d1, ref d2); @@ -719,11 +694,9 @@ namespace System { // FCallMultiply multiples two decimal values. On return, d1 contains the result // of the operation. // - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void FCallMultiply(ref Decimal d1, ref Decimal d2); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void FCallMultiplyOverflowed(ref Decimal d1, ref Decimal d2, ref bool overflowed); @@ -746,7 +719,6 @@ namespace System { return Round(d, 0); } - [System.Security.SecuritySafeCritical] // auto-generated public static Decimal Round(Decimal d, int decimals) { FCallRound (ref d, decimals); @@ -757,12 +729,11 @@ namespace System { return Round(d, 0, mode); } - [System.Security.SecuritySafeCritical] // auto-generated public static Decimal Round(Decimal d, int decimals, MidpointRounding mode) { if ((decimals < 0) || (decimals > 28)) - throw new ArgumentOutOfRangeException("decimals", Environment.GetResourceString("ArgumentOutOfRange_DecimalRound")); + throw new ArgumentOutOfRangeException(nameof(decimals), Environment.GetResourceString("ArgumentOutOfRange_DecimalRound")); if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidEnumValue", mode, "MidpointRounding"), "mode"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidEnumValue", mode, nameof(MidpointRounding)), nameof(mode)); } Contract.EndContractBlock(); @@ -775,13 +746,11 @@ namespace System { return d; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void FCallRound(ref Decimal d, int decimals); // Subtracts two Decimal values. // - [System.Security.SecuritySafeCritical] // auto-generated public static Decimal Subtract(Decimal d1, Decimal d2) { FCallAddSub(ref d1, ref d2, DECIMAL_NEG); @@ -843,7 +812,6 @@ namespace System { // has fewer significant digits than a Decimal, this operation may // produce round-off errors. // - [System.Security.SecuritySafeCritical] // auto-generated internal static Currency ToCurrency(Decimal d) { Currency result = new Currency (); @@ -851,18 +819,15 @@ namespace System { return result; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void FCallToCurrency(ref Currency result, Decimal d); // Converts a Decimal to a double. Since a double has fewer significant // digits than a Decimal, this operation may produce round-off errors. // - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern double ToDouble(Decimal d); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern int FCallToInt32(Decimal d); @@ -870,7 +835,6 @@ namespace System { // zero to the nearest integer value, and the result of this operation is // returned as an integer. // - [System.Security.SecuritySafeCritical] // auto-generated public static int ToInt32(Decimal d) { if ((d.flags & ScaleMask) != 0) FCallTruncate (ref d); if (d.hi == 0 && d.mid == 0) { @@ -890,7 +854,6 @@ namespace System { // to the nearest integer value, and the result of this operation is // returned as a long. // - [System.Security.SecuritySafeCritical] // auto-generated public static long ToInt64(Decimal d) { if ((d.flags & ScaleMask) != 0) FCallTruncate (ref d); if (d.hi == 0) { @@ -927,7 +890,6 @@ namespace System { // value is rounded towards zero to the nearest integer value, and the // result of this operation is returned as an unsigned integer. // - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] public static uint ToUInt32(Decimal d) { if ((d.flags & ScaleMask) != 0) FCallTruncate (ref d); @@ -943,7 +905,6 @@ namespace System { // value is rounded towards zero to the nearest integer value, and the // result of this operation is returned as a long. // - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] public static ulong ToUInt64(Decimal d) { if ((d.flags & ScaleMask) != 0) FCallTruncate (ref d); @@ -958,7 +919,6 @@ namespace System { // Converts a Decimal to a float. Since a float has fewer significant // digits than a Decimal, this operation may produce round-off errors. // - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern float ToSingle(Decimal d); @@ -966,7 +926,6 @@ namespace System { // towards zero to the nearest integer value, corresponding to removing all // digits after the decimal point. // - [System.Security.SecuritySafeCritical] // auto-generated public static Decimal Truncate(Decimal d) { FCallTruncate (ref d); @@ -974,7 +933,6 @@ namespace System { } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void FCallTruncate(ref Decimal d); @@ -1099,25 +1057,21 @@ namespace System { return Subtract(d, One); } - [System.Security.SecuritySafeCritical] // auto-generated public static Decimal operator +(Decimal d1, Decimal d2) { FCallAddSub(ref d1, ref d2, DECIMAL_ADD); return d1; } - [System.Security.SecuritySafeCritical] // auto-generated public static Decimal operator -(Decimal d1, Decimal d2) { FCallAddSub(ref d1, ref d2, DECIMAL_NEG); return d1; } - [System.Security.SecuritySafeCritical] // auto-generated public static Decimal operator *(Decimal d1, Decimal d2) { FCallMultiply (ref d1, ref d2); return d1; } - [System.Security.SecuritySafeCritical] // auto-generated public static Decimal operator /(Decimal d1, Decimal d2) { FCallDivide (ref d1, ref d2); return d1; @@ -1127,32 +1081,26 @@ namespace System { return Remainder(d1, d2); } - [System.Security.SecuritySafeCritical] // auto-generated public static bool operator ==(Decimal d1, Decimal d2) { return FCallCompare(ref d1, ref d2) == 0; } - [System.Security.SecuritySafeCritical] // auto-generated public static bool operator !=(Decimal d1, Decimal d2) { return FCallCompare(ref d1, ref d2) != 0; } - [System.Security.SecuritySafeCritical] // auto-generated public static bool operator <(Decimal d1, Decimal d2) { return FCallCompare(ref d1, ref d2) < 0; } - [System.Security.SecuritySafeCritical] // auto-generated public static bool operator <=(Decimal d1, Decimal d2) { return FCallCompare(ref d1, ref d2) <= 0; } - [System.Security.SecuritySafeCritical] // auto-generated public static bool operator >(Decimal d1, Decimal d2) { return FCallCompare(ref d1, ref d2) > 0; } - [System.Security.SecuritySafeCritical] // auto-generated public static bool operator >=(Decimal d1, Decimal d2) { return FCallCompare(ref d1, ref d2) >= 0; } diff --git a/src/mscorlib/src/System/DefaultBinder.cs b/src/mscorlib/src/System/DefaultBinder.cs index 405055e..b4681c4 100644 --- a/src/mscorlib/src/System/DefaultBinder.cs +++ b/src/mscorlib/src/System/DefaultBinder.cs @@ -14,6 +14,7 @@ namespace System { using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; using CultureInfo = System.Globalization.CultureInfo; //Marked serializable even though it has no state. @@ -33,13 +34,12 @@ namespace System { // // The most specific match will be selected. // - [System.Security.SecuritySafeCritical] // auto-generated public override MethodBase BindToMethod( BindingFlags bindingAttr, MethodBase[] match, ref Object[] args, ParameterModifier[] modifiers, CultureInfo cultureInfo, String[] names, out Object state) { if (match == null || match.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Arg_EmptyArray"), "match"); + throw new ArgumentException(Environment.GetResourceString("Arg_EmptyArray"), nameof(match)); Contract.EndContractBlock(); MethodBase[] candidates = (MethodBase[]) match.Clone(); @@ -437,11 +437,10 @@ namespace System { // Given a set of fields that match the base criteria, select a field. // if value is null then we have no way to select a field - [System.Security.SecuritySafeCritical] // auto-generated public override FieldInfo BindToField(BindingFlags bindingAttr,FieldInfo[] match, Object value,CultureInfo cultureInfo) { if (match == null) { - throw new ArgumentNullException("match"); + throw new ArgumentNullException(nameof(match)); } int i; @@ -514,7 +513,6 @@ namespace System { // Given a set of methods that match the base criteria, select a method based // upon an array of types. This method should return null if no method matchs // the criteria. - [System.Security.SecuritySafeCritical] // auto-generated public override MethodBase SelectMethod(BindingFlags bindingAttr,MethodBase[] match,Type[] types,ParameterModifier[] modifiers) { int i; @@ -524,13 +522,13 @@ namespace System { for (i=0;i /// Expression to assume will always be true. /// - /// At runtime this is equivalent to an . + /// At runtime this is equivalent to an . /// [Pure] [Conditional("DEBUG")] @@ -308,7 +309,7 @@ namespace System.Diagnostics.Contracts { /// Expression to assume will always be true. /// If it is not a constant string literal, then the contract may not be understood by tools. /// - /// At runtime this is equivalent to an . + /// At runtime this is equivalent to an . /// [Pure] [Conditional("DEBUG")] @@ -654,7 +655,7 @@ namespace System.Diagnostics.Contracts { throw new ArgumentException("fromInclusive must be less than or equal to toExclusive."); #endif if (predicate == null) - throw new ArgumentNullException("predicate"); + throw new ArgumentNullException(nameof(predicate)); Contract.EndContractBlock(); for (int i = fromInclusive; i < toExclusive; i++) @@ -679,9 +680,9 @@ namespace System.Diagnostics.Contracts { public static bool ForAll(IEnumerable collection, Predicate predicate) { if (collection == null) - throw new ArgumentNullException("collection"); + throw new ArgumentNullException(nameof(collection)); if (predicate == null) - throw new ArgumentNullException("predicate"); + throw new ArgumentNullException(nameof(predicate)); Contract.EndContractBlock(); foreach (T t in collection) @@ -716,7 +717,7 @@ namespace System.Diagnostics.Contracts { throw new ArgumentException("fromInclusive must be less than or equal to toExclusive."); #endif if (predicate == null) - throw new ArgumentNullException("predicate"); + throw new ArgumentNullException(nameof(predicate)); Contract.EndContractBlock(); for (int i = fromInclusive; i < toExclusive; i++) @@ -740,9 +741,9 @@ namespace System.Diagnostics.Contracts { public static bool Exists(IEnumerable collection, Predicate predicate) { if (collection == null) - throw new ArgumentNullException("collection"); + throw new ArgumentNullException(nameof(collection)); if (predicate == null) - throw new ArgumentNullException("predicate"); + throw new ArgumentNullException(nameof(predicate)); Contract.EndContractBlock(); foreach (T t in collection) @@ -805,7 +806,6 @@ namespace System.Diagnostics.Contracts { [CLSCompliant(false)] [Pure] [ContractRuntimeIgnored] - [SecurityCritical] #if FEATURE_RELIABILITY_CONTRACTS [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] #endif @@ -852,7 +852,6 @@ namespace System.Diagnostics.Contracts { [CLSCompliant(false)] [Pure] [ContractRuntimeIgnored] - [SecurityCritical] #if FEATURE_RELIABILITY_CONTRACTS [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] #endif diff --git a/src/mscorlib/src/System/Diagnostics/Contracts/ContractsBCL.cs b/src/mscorlib/src/System/Diagnostics/Contracts/ContractsBCL.cs index 804318e..d5e3f29 100644 --- a/src/mscorlib/src/System/Diagnostics/Contracts/ContractsBCL.cs +++ b/src/mscorlib/src/System/Diagnostics/Contracts/ContractsBCL.cs @@ -51,7 +51,6 @@ namespace System.Diagnostics.Contracts { /// This method is used internally to trigger a failure indicating to the "programmer" that he is using the interface incorrectly. /// It is NEVER used to indicate failure of actual contracts at runtime. /// - [SecuritySafeCritical] static partial void AssertMustUseRewriter(ContractFailureKind kind, String contractKind) { if (_assertingMustUseRewriter) @@ -99,7 +98,7 @@ namespace System.Diagnostics.Contracts { static partial void ReportFailure(ContractFailureKind failureKind, String userMessage, String conditionText, Exception innerException) { if (failureKind < ContractFailureKind.Precondition || failureKind > ContractFailureKind.Assume) - throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", failureKind), "failureKind"); + throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", failureKind), nameof(failureKind)); Contract.EndContractBlock(); // displayMessage == null means: yes we handled it. Otherwise it is the localized failure message @@ -121,18 +120,14 @@ namespace System.Diagnostics.Contracts { /// public static event EventHandler ContractFailed { #if FEATURE_UNTRUSTED_CALLERS - [SecurityCritical] #if FEATURE_LINK_DEMAND - [SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)] #endif #endif add { System.Runtime.CompilerServices.ContractHelper.InternalContractFailed += value; } #if FEATURE_UNTRUSTED_CALLERS - [SecurityCritical] #if FEATURE_LINK_DEMAND - [SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)] #endif #endif remove { @@ -176,9 +171,7 @@ namespace System.Diagnostics.Contracts { } #if FEATURE_UNTRUSTED_CALLERS - [SecurityCritical] #if FEATURE_LINK_DEMAND - [SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)] #endif #endif public void SetHandled() @@ -191,9 +184,7 @@ namespace System.Diagnostics.Contracts { } #if FEATURE_UNTRUSTED_CALLERS - [SecurityCritical] #if FEATURE_LINK_DEMAND - [SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)] #endif #endif public void SetUnwind() @@ -243,9 +234,7 @@ namespace System.Diagnostics.Contracts { } #if FEATURE_UNTRUSTED_CALLERS && FEATURE_SERIALIZATION - [SecurityCritical] #if FEATURE_LINK_DEMAND && FEATURE_SERIALIZATION - [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)] #endif // FEATURE_LINK_DEMAND #endif // FEATURE_UNTRUSTED_CALLERS public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) @@ -284,7 +273,6 @@ namespace System.Runtime.CompilerServices internal static event EventHandler InternalContractFailed { #if FEATURE_UNTRUSTED_CALLERS - [SecurityCritical] #endif add { // Eagerly prepare each event handler _marked with a reliability contract_, to @@ -301,7 +289,6 @@ namespace System.Runtime.CompilerServices } } #if FEATURE_UNTRUSTED_CALLERS - [SecurityCritical] #endif remove { lock (lockObject) @@ -326,12 +313,11 @@ namespace System.Runtime.CompilerServices [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] [System.Diagnostics.DebuggerNonUserCode] #if FEATURE_RELIABILITY_CONTRACTS - [SecuritySafeCritical] #endif static partial void RaiseContractFailedEventImplementation(ContractFailureKind failureKind, String userMessage, String conditionText, Exception innerException, ref string resultFailureMessage) { if (failureKind < ContractFailureKind.Precondition || failureKind > ContractFailureKind.Assume) - throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", failureKind), "failureKind"); + throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", failureKind), nameof(failureKind)); Contract.EndContractBlock(); string returnValue; @@ -361,10 +347,6 @@ namespace System.Runtime.CompilerServices } if (eventArgs.Unwind) { -#if !FEATURE_CORECLR - if (Environment.IsCLRHosted) - TriggerCodeContractEscalationPolicy(failureKind, displayMessage, conditionText, innerException); -#endif // unwind if (innerException == null) { innerException = eventArgs.thrownDuringHandler; } throw new ContractException(failureKind, displayMessage, userMessage, conditionText, innerException); @@ -393,9 +375,6 @@ namespace System.Runtime.CompilerServices [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "kind")] [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "innerException")] [System.Diagnostics.DebuggerNonUserCode] -#if FEATURE_UNTRUSTED_CALLERS && !FEATURE_CORECLR - [SecuritySafeCritical] -#endif static partial void TriggerFailureImplementation(ContractFailureKind kind, String displayMessage, String userMessage, String conditionText, Exception innerException) { // If we're here, our intent is to pop up a dialog box (if we can). For developers @@ -403,21 +382,12 @@ namespace System.Runtime.CompilerServices // hosted in Internet Explorer, the assert window is great. If we cannot // pop up a dialog box, throw an exception (consider a library compiled with // "Assert On Failure" but used in a process that can't pop up asserts, like an - // NT Service). For the CLR hosted by server apps like SQL or Exchange, we should - // trigger escalation policy. -#if !FEATURE_CORECLR - if (Environment.IsCLRHosted) - { - TriggerCodeContractEscalationPolicy(kind, displayMessage, conditionText, innerException); - // Hosts like SQL may choose to abort the thread, so we will not get here in all cases. - // But if the host's chosen action was to throw an exception, we should throw an exception - // here (which is easier to do in managed code with the right parameters). - throw new ContractException(kind, displayMessage, userMessage, conditionText, innerException); - } -#endif // !FEATURE_CORECLR + // NT Service). + if (!Environment.UserInteractive) { throw new ContractException(kind, displayMessage, userMessage, conditionText, innerException); } + // May need to rethink Assert.Fail w/ TaskDialogIndirect as a model. Window title. Main instruction. Content. Expanded info. // Optional info like string for collapsed text vs. expanded text. String windowTitle = Environment.GetResourceString(GetResourceNameForFailure(kind)); @@ -494,28 +464,6 @@ namespace System.Runtime.CompilerServices return failureMessage; } } - -#if !FEATURE_CORECLR - // Will trigger escalation policy, if hosted and the host requested us to do something (such as - // abort the thread or exit the process). Starting in Dev11, for hosted apps the default behavior - // is to throw an exception. - // Implementation notes: - // We implement our default behavior of throwing an exception by simply returning from our native - // method inside the runtime and falling through to throw an exception. - // We must call through this method before calling the method on the Environment class - // because our security team does not yet support SecuritySafeCritical on P/Invoke methods. - // Note this can be called in the context of throwing another exception (EnsuresOnThrow). - [SecuritySafeCritical] - [DebuggerNonUserCode] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - private static void TriggerCodeContractEscalationPolicy(ContractFailureKind failureKind, String message, String conditionText, Exception innerException) - { - String exceptionAsString = null; - if (innerException != null) - exceptionAsString = innerException.ToString(); - Environment.TriggerCodeContractFailure(failureKind, message, conditionText, exceptionAsString); - } -#endif // !FEATURE_CORECLR } } // namespace System.Runtime.CompilerServices diff --git a/src/mscorlib/src/System/Diagnostics/Debugger.cs b/src/mscorlib/src/System/Diagnostics/Debugger.cs index 339c89e..8ebbc0a 100644 --- a/src/mscorlib/src/System/Diagnostics/Debugger.cs +++ b/src/mscorlib/src/System/Diagnostics/Debugger.cs @@ -32,7 +32,6 @@ namespace System.Diagnostics // Break causes a breakpoint to be signalled to an attached debugger. If no debugger // is attached, the user is asked if he wants to attach a debugger. If yes, then the // debugger is launched. - [System.Security.SecuritySafeCritical] // auto-generated public static void Break() { if (!Debugger.IsAttached) @@ -61,7 +60,6 @@ namespace System.Diagnostics BreakInternal(); } - [System.Security.SecuritySafeCritical] // auto-generated static void BreakCanThrow() { if (!Debugger.IsAttached) @@ -75,14 +73,12 @@ namespace System.Diagnostics BreakInternal(); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void BreakInternal(); // Launch launches & attaches a debugger to the process. If a debugger is already attached, // nothing happens. // - [System.Security.SecuritySafeCritical] // auto-generated public static bool Launch() { if (Debugger.IsAttached) @@ -147,7 +143,6 @@ namespace System.Diagnostics } } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool LaunchInternal(); @@ -155,7 +150,6 @@ namespace System.Diagnostics // public static extern bool IsAttached { - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] get; } @@ -173,20 +167,17 @@ namespace System.Diagnostics // Posts a message for the attached debugger. If there is no // debugger attached, has no effect. The debugger may or may not // report the message depending on its settings. - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern void Log(int level, String category, String message); // Checks to see if an attached debugger has logging enabled // - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern bool IsLogging(); // Posts a custom notification for the attached debugger. If there is no // debugger attached, has no effect. The debugger may or may not // report the notification depending on its settings. - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void CustomNotification(ICustomDebuggerNotification data); diff --git a/src/mscorlib/src/System/Diagnostics/DebuggerAttributes.cs b/src/mscorlib/src/System/Diagnostics/DebuggerAttributes.cs index 6adcf34..e75b653 100644 --- a/src/mscorlib/src/System/Diagnostics/DebuggerAttributes.cs +++ b/src/mscorlib/src/System/Diagnostics/DebuggerAttributes.cs @@ -142,7 +142,7 @@ namespace System.Diagnostics { public DebuggerBrowsableAttribute(DebuggerBrowsableState state) { if( state < DebuggerBrowsableState.Never || state > DebuggerBrowsableState.RootHidden) - throw new ArgumentOutOfRangeException("state"); + throw new ArgumentOutOfRangeException(nameof(state)); Contract.EndContractBlock(); this.state = state; @@ -166,7 +166,7 @@ namespace System.Diagnostics { public DebuggerTypeProxyAttribute(Type type) { if (type == null) { - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); } Contract.EndContractBlock(); @@ -186,7 +186,7 @@ namespace System.Diagnostics { { set { if( value == null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); @@ -257,7 +257,7 @@ namespace System.Diagnostics { { set { if( value == null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); @@ -302,7 +302,7 @@ namespace System.Diagnostics { public DebuggerVisualizerAttribute(string visualizerTypeName, Type visualizerObjectSource) { if (visualizerObjectSource == null) { - throw new ArgumentNullException("visualizerObjectSource"); + throw new ArgumentNullException(nameof(visualizerObjectSource)); } Contract.EndContractBlock(); this.visualizerName = visualizerTypeName; @@ -311,7 +311,7 @@ namespace System.Diagnostics { public DebuggerVisualizerAttribute(Type visualizer) { if (visualizer == null) { - throw new ArgumentNullException("visualizer"); + throw new ArgumentNullException(nameof(visualizer)); } Contract.EndContractBlock(); this.visualizerName = visualizer.AssemblyQualifiedName; @@ -319,10 +319,10 @@ namespace System.Diagnostics { public DebuggerVisualizerAttribute(Type visualizer, Type visualizerObjectSource) { if (visualizer == null) { - throw new ArgumentNullException("visualizer"); + throw new ArgumentNullException(nameof(visualizer)); } if (visualizerObjectSource == null) { - throw new ArgumentNullException("visualizerObjectSource"); + throw new ArgumentNullException(nameof(visualizerObjectSource)); } Contract.EndContractBlock(); this.visualizerName = visualizer.AssemblyQualifiedName; @@ -331,7 +331,7 @@ namespace System.Diagnostics { public DebuggerVisualizerAttribute(Type visualizer, string visualizerObjectSourceTypeName) { if (visualizer == null) { - throw new ArgumentNullException("visualizer"); + throw new ArgumentNullException(nameof(visualizer)); } Contract.EndContractBlock(); this.visualizerName = visualizer.AssemblyQualifiedName; @@ -356,7 +356,7 @@ namespace System.Diagnostics { { set { if( value == null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/ActivityTracker.cs b/src/mscorlib/src/System/Diagnostics/Eventing/ActivityTracker.cs index a7124a2..1a1f5fa 100644 --- a/src/mscorlib/src/System/Diagnostics/Eventing/ActivityTracker.cs +++ b/src/mscorlib/src/System/Diagnostics/Eventing/ActivityTracker.cs @@ -72,7 +72,7 @@ namespace System.Diagnostics.Tracing } - Contract.Assert((options & EventActivityOptions.Disable) == 0); + Debug.Assert((options & EventActivityOptions.Disable) == 0); var currentActivity = m_current.Value; var fullActivityName = NormalizeActivityName(providerName, activityName, task); @@ -191,7 +191,7 @@ namespace System.Diagnostics.Tracing else { orphan.m_stopped = 1; - Contract.Assert(orphan.m_stopped != 0); + Debug.Assert(orphan.m_stopped != 0); } orphan = orphan.m_creator; } @@ -221,7 +221,6 @@ namespace System.Diagnostics.Tracing /// /// Turns on activity tracking. It is sticky, once on it stays on (race issues otherwise) /// - [System.Security.SecuritySafeCritical] public void Enable() { if (m_current == null) @@ -366,7 +365,6 @@ namespace System.Diagnostics.Tracing /// byte (since the top nibble can't be zero you can determine if this is true by seeing if /// this byte is nonZero. This offset is needed to efficiently create the ID for child activities. /// - [System.Security.SecuritySafeCritical] private unsafe void CreateActivityPathGuid(out Guid idRet, out int activityPathGuidOffset) { fixed (Guid* outPtr = &idRet) @@ -403,7 +401,6 @@ namespace System.Diagnostics.Tracing /// sufficient space for this ID. By doing this, we preserve the fact that this activity /// is a child (of unknown depth) from that ancestor. /// - [System.Security.SecurityCritical] private unsafe void CreateOverflowGuid(Guid* outPtr) { // Search backwards for an ancestor that has sufficient space to put the ID. @@ -452,7 +449,6 @@ namespace System.Diagnostics.Tracing /// is the maximum number of bytes that fit in a GUID) if the path did not fit. /// If 'overflow' is true, then the number is encoded as an 'overflow number (which has a /// special (longer prefix) that indicates that this ID is allocated differently - [System.Security.SecurityCritical] private static unsafe int AddIdToGuid(Guid* outPtr, int whereToAddId, uint id, bool overflow = false) { byte* ptr = (byte*)outPtr; @@ -526,11 +522,10 @@ namespace System.Diagnostics.Tracing /// Thus if it is non-zero it adds to the current byte, otherwise it advances and writes /// the new byte (in the high bits) of the next byte. /// - [System.Security.SecurityCritical] private static unsafe void WriteNibble(ref byte* ptr, byte* endPtr, uint value) { - Contract.Assert(0 <= value && value < 16); - Contract.Assert(ptr < endPtr); + Debug.Assert(0 <= value && value < 16); + Debug.Assert(ptr < endPtr); if (*ptr != 0) *ptr++ |= (byte)value; diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/EventProvider.cs b/src/mscorlib/src/System/Diagnostics/Eventing/EventProvider.cs index 6ea8d98..ce0fcb6 100644 --- a/src/mscorlib/src/System/Diagnostics/Eventing/EventProvider.cs +++ b/src/mscorlib/src/System/Diagnostics/Eventing/EventProvider.cs @@ -74,7 +74,6 @@ namespace System.Diagnostics.Tracing private static bool m_setInformationMissing; - [SecurityCritical] UnsafeNativeMethods.ManifestEtw.EtwEnableCallback m_etwCallback; // Trace Callback function private long m_regHandle; // Trace Registration Handle private byte m_level; // Tracing Level @@ -128,7 +127,6 @@ namespace System.Diagnostics.Tracing // // // - [System.Security.SecurityCritical] internal unsafe void Register(Guid providerGuid) { m_providerId = providerGuid; @@ -157,7 +155,6 @@ namespace System.Diagnostics.Tracing // // // - [System.Security.SecuritySafeCritical] protected virtual void Dispose(bool disposing) { // @@ -175,16 +172,31 @@ namespace System.Diagnostics.Tracing // Disable the provider. m_enabled = false; - // Do most of the work under a lock to avoid shutdown race. + // Do most of the work under a lock to avoid shutdown race. + + long registrationHandle = 0; lock (EventListener.EventListenersLock) { // Double check if (m_disposed) return; - Deregister(); + registrationHandle = m_regHandle; + m_regHandle = 0; m_disposed = true; } + + // We do the Unregistration outside the EventListenerLock because there is a lock + // inside the ETW routines. This lock is taken before ETW issues commands + // Thus the ETW lock gets taken first and then our EventListenersLock gets taken + // in SendCommand(), and also here. If we called EventUnregister after taking + // the EventListenersLock then the take-lock order is reversed and we can have + // deadlocks in race conditions (dispose racing with an ETW command). + // + // We solve by Unregistering after releasing the EventListenerLock. + if (registrationHandle != 0) + EventUnregister(registrationHandle); + } /// @@ -201,33 +213,10 @@ namespace System.Diagnostics.Tracing Dispose(false); } - /// - /// This method un-registers from ETW. - /// - // - // - // - // TODO Check return code from UnsafeNativeMethods.ManifestEtw.EventUnregister - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Win32.UnsafeNativeMethods.ManifestEtw.EventUnregister(System.Int64)"), System.Security.SecurityCritical] - private unsafe void Deregister() - { - // - // Unregister from ETW using the RegHandle saved from - // the register call. - // - - if (m_regHandle != 0) - { - EventUnregister(); - m_regHandle = 0; - } - } - // // // // - [System.Security.SecurityCritical] unsafe void EtwEnableCallBack( [In] ref System.Guid sourceId, [In] int controlCode, @@ -348,7 +337,6 @@ namespace System.Diagnostics.Tracing /// ETW session that was added or remove, and the bool specifies whether the /// session was added or whether it was removed from the set. /// - [System.Security.SecuritySafeCritical] private List> GetSessions() { List liveSessionList = null; @@ -424,7 +412,6 @@ namespace System.Diagnostics.Tracing /// for the current process ID, calling 'action' for each session, and passing it the /// ETW session and the 'AllKeywords' the session enabled for the current provider. /// - [System.Security.SecurityCritical] private unsafe void GetSessionInfo(Action action) { // We wish the EventSource package to be legal for Windows Store applications. @@ -470,7 +457,7 @@ namespace System.Diagnostics.Tracing } if (providerInstance->NextOffset == 0) break; - Contract.Assert(0 <= providerInstance->NextOffset && providerInstance->NextOffset < buffSize); + Debug.Assert(0 <= providerInstance->NextOffset && providerInstance->NextOffset < buffSize); var structBase = (byte*)providerInstance; providerInstance = (UnsafeNativeMethods.ManifestEtw.TRACE_PROVIDER_INSTANCE_INFO*)&structBase[providerInstance->NextOffset]; } @@ -552,7 +539,6 @@ namespace System.Diagnostics.Tracing /// returns an array of bytes representing the data, the index into that byte array where the data /// starts, and the command being issued associated with that data. /// - [System.Security.SecurityCritical] private unsafe bool GetDataFromController(int etwSessionId, UnsafeNativeMethods.ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData, out ControllerCommand command, out byte[] data, out int dataStart) { @@ -685,7 +671,6 @@ namespace System.Diagnostics.Tracing // // // - [System.Security.SecurityCritical] private static unsafe object EncodeObject(ref object data, ref EventData* dataDescriptor, ref byte* dataBuffer, ref uint totalEventSize) /*++ @@ -934,7 +919,6 @@ namespace System.Diagnostics.Tracing // [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Performance-critical code")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")] - [System.Security.SecurityCritical] internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, Guid* activityID, Guid* childActivityID, params object[] eventPayload) { int status = 0; @@ -1131,13 +1115,12 @@ namespace System.Diagnostics.Tracing // // [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")] - [System.Security.SecurityCritical] internal unsafe protected bool WriteEvent(ref EventDescriptor eventDescriptor, Guid* activityID, Guid* childActivityID, int dataCount, IntPtr data) { if (childActivityID != null) { // activity transfers are supported only for events that specify the Send or Receive opcode - Contract.Assert((EventOpcode)eventDescriptor.Opcode == EventOpcode.Send || + Debug.Assert((EventOpcode)eventDescriptor.Opcode == EventOpcode.Send || (EventOpcode)eventDescriptor.Opcode == EventOpcode.Receive || (EventOpcode)eventDescriptor.Opcode == EventOpcode.Start || (EventOpcode)eventDescriptor.Opcode == EventOpcode.Stop); @@ -1154,7 +1137,6 @@ namespace System.Diagnostics.Tracing } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")] - [System.Security.SecurityCritical] internal unsafe bool WriteEventRaw( ref EventDescriptor eventDescriptor, Guid* activityID, @@ -1183,7 +1165,6 @@ namespace System.Diagnostics.Tracing // These are look-alikes to the Manifest based ETW OS APIs that have been shimmed to work // either with Manifest ETW or Classic ETW (if Manifest based ETW is not available). - [SecurityCritical] private unsafe uint EventRegister(ref Guid providerId, UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback) { m_providerId = providerId; @@ -1191,12 +1172,9 @@ namespace System.Diagnostics.Tracing return UnsafeNativeMethods.ManifestEtw.EventRegister(ref providerId, enableCallback, null, ref m_regHandle); } - [SecurityCritical] - private uint EventUnregister() + private uint EventUnregister(long registrationHandle) { - uint status = UnsafeNativeMethods.ManifestEtw.EventUnregister(m_regHandle); - m_regHandle = 0; - return status; + return UnsafeNativeMethods.ManifestEtw.EventUnregister(registrationHandle); } static int[] nibblebits = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; @@ -1209,7 +1187,7 @@ namespace System.Diagnostics.Tracing } private static int bitindex(uint n) { - Contract.Assert(bitcount(n) == 1); + Debug.Assert(bitcount(n) == 1); int idx = 0; while ((n & (1 << idx)) == 0) idx++; diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/EventSource.cs b/src/mscorlib/src/System/Diagnostics/Eventing/EventSource.cs index 8c2edfd..aa0d8d7 100644 --- a/src/mscorlib/src/System/Diagnostics/Eventing/EventSource.cs +++ b/src/mscorlib/src/System/Diagnostics/Eventing/EventSource.cs @@ -529,7 +529,6 @@ namespace System.Diagnostics.Tracing /// internal static Guid InternalCurrentThreadActivityId { - [System.Security.SecurityCritical] get { Guid retval = CurrentThreadActivityId; @@ -543,12 +542,11 @@ namespace System.Diagnostics.Tracing internal static Guid FallbackActivityId { - [System.Security.SecurityCritical] get { #pragma warning disable 612, 618 int threadID = AppDomain.GetCurrentThreadId(); - + // Managed thread IDs are more aggressively re-used than native thread IDs, // so we'll use the latter... return new Guid(unchecked((uint)threadID), @@ -608,7 +606,7 @@ namespace System.Diagnostics.Tracing add { m_eventCommandExecuted += value; - + // If we have an EventHandler attached to the EventSource before the first command arrives // It should get a chance to handle the deferred commands. EventCommandEventArgs deferredCommands = m_deferredCommands; @@ -706,7 +704,7 @@ namespace System.Diagnostics.Tracing return; } - + /// /// This method is called when the eventSource is updated by the controller. /// @@ -714,7 +712,6 @@ namespace System.Diagnostics.Tracing #pragma warning disable 1591 // optimized for common signatures (no args) - [SecuritySafeCritical] [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] protected unsafe void WriteEvent(int eventId) { @@ -722,7 +719,6 @@ namespace System.Diagnostics.Tracing } // optimized for common signatures (ints) - [SecuritySafeCritical] [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] protected unsafe void WriteEvent(int eventId, int arg1) { @@ -735,7 +731,6 @@ namespace System.Diagnostics.Tracing } } - [SecuritySafeCritical] [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] protected unsafe void WriteEvent(int eventId, int arg1, int arg2) { @@ -750,7 +745,6 @@ namespace System.Diagnostics.Tracing } } - [SecuritySafeCritical] [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] protected unsafe void WriteEvent(int eventId, int arg1, int arg2, int arg3) { @@ -768,7 +762,6 @@ namespace System.Diagnostics.Tracing } // optimized for common signatures (longs) - [SecuritySafeCritical] [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] protected unsafe void WriteEvent(int eventId, long arg1) { @@ -781,7 +774,6 @@ namespace System.Diagnostics.Tracing } } - [SecuritySafeCritical] [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] protected unsafe void WriteEvent(int eventId, long arg1, long arg2) { @@ -796,7 +788,6 @@ namespace System.Diagnostics.Tracing } } - [SecuritySafeCritical] [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] protected unsafe void WriteEvent(int eventId, long arg1, long arg2, long arg3) { @@ -814,7 +805,6 @@ namespace System.Diagnostics.Tracing } // optimized for common signatures (strings) - [SecuritySafeCritical] [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] protected unsafe void WriteEvent(int eventId, string arg1) { @@ -831,7 +821,6 @@ namespace System.Diagnostics.Tracing } } - [SecuritySafeCritical] [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] protected unsafe void WriteEvent(int eventId, string arg1, string arg2) { @@ -852,7 +841,6 @@ namespace System.Diagnostics.Tracing } } - [SecuritySafeCritical] [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] protected unsafe void WriteEvent(int eventId, string arg1, string arg2, string arg3) { @@ -878,7 +866,6 @@ namespace System.Diagnostics.Tracing } // optimized for common signatures (string and ints) - [SecuritySafeCritical] [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] protected unsafe void WriteEvent(int eventId, string arg1, int arg2) { @@ -897,7 +884,6 @@ namespace System.Diagnostics.Tracing } } - [SecuritySafeCritical] [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] protected unsafe void WriteEvent(int eventId, string arg1, int arg2, int arg3) { @@ -919,7 +905,6 @@ namespace System.Diagnostics.Tracing } // optimized for common signatures (string and longs) - [SecuritySafeCritical] [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] protected unsafe void WriteEvent(int eventId, string arg1, long arg2) { @@ -939,7 +924,6 @@ namespace System.Diagnostics.Tracing } // optimized for common signatures (long and string) - [SecuritySafeCritical] [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] protected unsafe void WriteEvent(int eventId, long arg1, string arg2) { @@ -959,7 +943,6 @@ namespace System.Diagnostics.Tracing } // optimized for common signatures (int and string) - [SecuritySafeCritical] [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] protected unsafe void WriteEvent(int eventId, int arg1, string arg2) { @@ -977,70 +960,68 @@ namespace System.Diagnostics.Tracing } } } - - [SecuritySafeCritical] - [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] - protected unsafe void WriteEvent(int eventId, byte[] arg1) - { - if (m_eventSourceEnabled) - { - EventSource.EventData* descrs = stackalloc EventSource.EventData[2]; - if (arg1 == null || arg1.Length == 0) - { - int blobSize = 0; - descrs[0].DataPointer = (IntPtr)(&blobSize); - descrs[0].Size = 4; - descrs[1].DataPointer = (IntPtr)(&blobSize); // valid address instead of empty content - descrs[1].Size = 0; - WriteEventCore(eventId, 2, descrs); - } - else - { - int blobSize = arg1.Length; - fixed (byte* blob = &arg1[0]) - { - descrs[0].DataPointer = (IntPtr)(&blobSize); - descrs[0].Size = 4; - descrs[1].DataPointer = (IntPtr)blob; - descrs[1].Size = blobSize; - WriteEventCore(eventId, 2, descrs); - } - } - } - } - - [SecuritySafeCritical] - [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] - protected unsafe void WriteEvent(int eventId, long arg1, byte[] arg2) - { - if (m_eventSourceEnabled) - { - EventSource.EventData* descrs = stackalloc EventSource.EventData[3]; - descrs[0].DataPointer = (IntPtr)(&arg1); - descrs[0].Size = 8; - if (arg2 == null || arg2.Length == 0) - { - int blobSize = 0; - descrs[1].DataPointer = (IntPtr)(&blobSize); - descrs[1].Size = 4; - descrs[2].DataPointer = (IntPtr)(&blobSize); // valid address instead of empty contents - descrs[2].Size = 0; - WriteEventCore(eventId, 3, descrs); - } - else - { - int blobSize = arg2.Length; - fixed (byte* blob = &arg2[0]) - { - descrs[1].DataPointer = (IntPtr)(&blobSize); - descrs[1].Size = 4; - descrs[2].DataPointer = (IntPtr)blob; - descrs[2].Size = blobSize; - WriteEventCore(eventId, 3, descrs); - } - } - } - } + + [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] + protected unsafe void WriteEvent(int eventId, byte[] arg1) + { + if (m_eventSourceEnabled) + { + EventSource.EventData* descrs = stackalloc EventSource.EventData[2]; + if (arg1 == null || arg1.Length == 0) + { + int blobSize = 0; + descrs[0].DataPointer = (IntPtr)(&blobSize); + descrs[0].Size = 4; + descrs[1].DataPointer = (IntPtr)(&blobSize); // valid address instead of empty content + descrs[1].Size = 0; + WriteEventCore(eventId, 2, descrs); + } + else + { + int blobSize = arg1.Length; + fixed (byte* blob = &arg1[0]) + { + descrs[0].DataPointer = (IntPtr)(&blobSize); + descrs[0].Size = 4; + descrs[1].DataPointer = (IntPtr)blob; + descrs[1].Size = blobSize; + WriteEventCore(eventId, 2, descrs); + } + } + } + } + + [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] + protected unsafe void WriteEvent(int eventId, long arg1, byte[] arg2) + { + if (m_eventSourceEnabled) + { + EventSource.EventData* descrs = stackalloc EventSource.EventData[3]; + descrs[0].DataPointer = (IntPtr)(&arg1); + descrs[0].Size = 8; + if (arg2 == null || arg2.Length == 0) + { + int blobSize = 0; + descrs[1].DataPointer = (IntPtr)(&blobSize); + descrs[1].Size = 4; + descrs[2].DataPointer = (IntPtr)(&blobSize); // valid address instead of empty contents + descrs[2].Size = 0; + WriteEventCore(eventId, 3, descrs); + } + else + { + int blobSize = arg2.Length; + fixed (byte* blob = &arg2[0]) + { + descrs[1].DataPointer = (IntPtr)(&blobSize); + descrs[1].Size = 4; + descrs[2].DataPointer = (IntPtr)blob; + descrs[2].Size = blobSize; + WriteEventCore(eventId, 3, descrs); + } + } + } + } #pragma warning restore 1591 @@ -1067,7 +1048,6 @@ namespace System.Diagnostics.Tracing /// Pinned tracelogging-compatible metadata blob. /// The size of the metadata blob. /// Value for reserved: 2 for per-provider metadata, 1 for per-event metadata - [SecurityCritical] internal unsafe void SetMetadata(byte* pointer, int size, int reserved) { this.m_Ptr = (long)(ulong)(UIntPtr)pointer; @@ -1109,7 +1089,6 @@ namespace System.Diagnostics.Tracing /// } /// /// - [SecurityCritical] [CLSCompliant(false)] protected unsafe void WriteEventCore(int eventId, int eventDataCount, EventSource.EventData* data) { @@ -1141,7 +1120,6 @@ namespace System.Diagnostics.Tracing /// } /// /// - [SecurityCritical] [CLSCompliant(false)] protected unsafe void WriteEventWithRelatedActivityIdCore(int eventId, Guid* relatedActivityId, int eventDataCount, EventSource.EventData* data) { @@ -1149,36 +1127,37 @@ namespace System.Diagnostics.Tracing { try { - Contract.Assert(m_eventData != null); // You must have initialized this if you enabled the source. + Debug.Assert(m_eventData != null); // You must have initialized this if you enabled the source. if (relatedActivityId != null) ValidateEventOpcodeForTransfer(ref m_eventData[eventId], m_eventData[eventId].Name); -#if FEATURE_MANAGED_ETW - if (m_eventData[eventId].EnabledForETW) + EventOpcode opcode = (EventOpcode)m_eventData[eventId].Descriptor.Opcode; + EventActivityOptions activityOptions = m_eventData[eventId].ActivityOptions; + Guid* pActivityId = null; + Guid activityId = Guid.Empty; + Guid relActivityId = Guid.Empty; + + if (opcode != EventOpcode.Info && relatedActivityId == null && + ((activityOptions & EventActivityOptions.Disable) == 0)) { - EventOpcode opcode = (EventOpcode)m_eventData[eventId].Descriptor.Opcode; - EventActivityOptions activityOptions = m_eventData[eventId].ActivityOptions; - Guid* pActivityId = null; - Guid activityId = Guid.Empty; - Guid relActivityId = Guid.Empty; - - if (opcode != EventOpcode.Info && relatedActivityId == null && - ((activityOptions & EventActivityOptions.Disable) == 0)) + if (opcode == EventOpcode.Start) { - if (opcode == EventOpcode.Start) - { - m_activityTracker.OnStart(m_name, m_eventData[eventId].Name, m_eventData[eventId].Descriptor.Task, ref activityId, ref relActivityId, m_eventData[eventId].ActivityOptions); - } - else if (opcode == EventOpcode.Stop) - { - m_activityTracker.OnStop(m_name, m_eventData[eventId].Name, m_eventData[eventId].Descriptor.Task, ref activityId); - } - - if (activityId != Guid.Empty) - pActivityId = &activityId; - if (relActivityId != Guid.Empty) - relatedActivityId = &relActivityId; + m_activityTracker.OnStart(m_name, m_eventData[eventId].Name, m_eventData[eventId].Descriptor.Task, ref activityId, ref relActivityId, m_eventData[eventId].ActivityOptions); } + else if (opcode == EventOpcode.Stop) + { + m_activityTracker.OnStop(m_name, m_eventData[eventId].Name, m_eventData[eventId].Descriptor.Task, ref activityId); + } + + if (activityId != Guid.Empty) + pActivityId = &activityId; + if (relActivityId != Guid.Empty) + relatedActivityId = &relActivityId; + } + +#if FEATURE_MANAGED_ETW + if (m_eventData[eventId].EnabledForETW) + { #if FEATURE_ACTIVITYSAMPLING // this code should be kept in sync with WriteEventVarargs(). @@ -1298,7 +1277,6 @@ namespace System.Diagnostics.Tracing /// method signature. Even if you use this for rare events, this call should be guarded by an /// check so that the varargs call is not made when the EventSource is not active. /// - [SecuritySafeCritical] [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] protected unsafe void WriteEvent(int eventId, params object[] args) { @@ -1313,7 +1291,6 @@ namespace System.Diagnostics.Tracing /// particular method signature. Even if you use this for rare events, this call should be guarded by an /// check so that the varargs call is not made when the EventSource is not active. /// - [SecuritySafeCritical] protected unsafe void WriteEventWithRelatedActivityId(int eventId, Guid relatedActivityId, params object[] args) { WriteEventVarargs(eventId, &relatedActivityId, args); @@ -1380,7 +1357,7 @@ namespace System.Diagnostics.Tracing #if FEATURE_ACTIVITYSAMPLING internal void WriteStringToListener(EventListener listener, string msg, SessionMask m) { - Contract.Assert(listener == null || (uint)m == (uint)SessionMask.FromId(0)); + Debug.Assert(listener == null || (uint)m == (uint)SessionMask.FromId(0)); if (m_eventSourceEnabled) { @@ -1390,18 +1367,18 @@ namespace System.Diagnostics.Tracing } else { - List arg = new List(); - arg.Add(msg); EventWrittenEventArgs eventCallbackArgs = new EventWrittenEventArgs(this); eventCallbackArgs.EventId = 0; - eventCallbackArgs.Payload = new ReadOnlyCollection(arg); + eventCallbackArgs.Message = msg; + eventCallbackArgs.Payload = new ReadOnlyCollection(new List() { msg }); + eventCallbackArgs.PayloadNames = new ReadOnlyCollection(new List { "message" }); + eventCallbackArgs.EventName = "EventSourceMessage"; listener.OnEventWritten(eventCallbackArgs); } } } #endif - [SecurityCritical] private unsafe void WriteEventRaw( string eventName, ref EventDescriptor eventDescriptor, @@ -1443,7 +1420,6 @@ namespace System.Diagnostics.Tracing /// member, and any future access to the "Log" would throw the cached exception). /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "guid")] - [SecuritySafeCritical] private unsafe void Initialize(Guid eventSourceGuid, string eventSourceName, string[] traits) { try @@ -1500,7 +1476,7 @@ namespace System.Diagnostics.Tracing #endif { int setInformationResult; - System.Runtime.InteropServices.GCHandle metadataHandle = + System.Runtime.InteropServices.GCHandle metadataHandle = System.Runtime.InteropServices.GCHandle.Alloc(this.providerMetadata, System.Runtime.InteropServices.GCHandleType.Pinned); IntPtr providerMetadata = metadataHandle.AddrOfPinnedObject(); @@ -1513,7 +1489,7 @@ namespace System.Diagnostics.Tracing } #endif // FEATURE_MANAGED_ETW - Contract.Assert(!m_eventSourceEnabled); // We can't be enabled until we are completely initted. + Debug.Assert(!m_eventSourceEnabled); // We can't be enabled until we are completely initted. // We are logically completely initialized at this point. m_completelyInited = true; } @@ -1742,7 +1718,6 @@ namespace System.Diagnostics.Tracing return new Guid(bytes); } - [SecurityCritical] private unsafe object DecodeObject(int eventId, int parameterId, ref EventSource.EventData* data) { // TODO FIX : We use reflection which in turn uses EventSource, right now we carefully avoid @@ -1754,7 +1729,7 @@ namespace System.Diagnostics.Tracing Type dataType = GetDataType(m_eventData[eventId], parameterId); - Again: + Again: if (dataType == typeof(IntPtr)) { return *((IntPtr*)dataPointer); @@ -1889,14 +1864,13 @@ namespace System.Diagnostics.Tracing return dispatcher; } - [SecurityCritical] private unsafe void WriteEventVarargs(int eventId, Guid* childActivityID, object[] args) { if (m_eventSourceEnabled) { try { - Contract.Assert(m_eventData != null); // You must have initialized this if you enabled the source. + Debug.Assert(m_eventData != null); // You must have initialized this if you enabled the source. if (childActivityID != null) { ValidateEventOpcodeForTransfer(ref m_eventData[eventId], m_eventData[eventId].Name); @@ -1916,33 +1890,34 @@ namespace System.Diagnostics.Tracing } LogEventArgsMismatches(m_eventData[eventId].Parameters, args); -#if FEATURE_MANAGED_ETW - if (m_eventData[eventId].EnabledForETW) + + Guid* pActivityId = null; + Guid activityId = Guid.Empty; + Guid relatedActivityId = Guid.Empty; + EventOpcode opcode = (EventOpcode)m_eventData[eventId].Descriptor.Opcode; + EventActivityOptions activityOptions = m_eventData[eventId].ActivityOptions; + + if (childActivityID == null && + ((activityOptions & EventActivityOptions.Disable) == 0)) { - Guid* pActivityId = null; - Guid activityId = Guid.Empty; - Guid relatedActivityId = Guid.Empty; - EventOpcode opcode = (EventOpcode)m_eventData[eventId].Descriptor.Opcode; - EventActivityOptions activityOptions = m_eventData[eventId].ActivityOptions; - - if (childActivityID == null && - ((activityOptions & EventActivityOptions.Disable) == 0)) + if (opcode == EventOpcode.Start) { - if (opcode == EventOpcode.Start) - { - m_activityTracker.OnStart(m_name, m_eventData[eventId].Name, m_eventData[eventId].Descriptor.Task, ref activityId, ref relatedActivityId, m_eventData[eventId].ActivityOptions); - } - else if (opcode == EventOpcode.Stop) - { - m_activityTracker.OnStop(m_name, m_eventData[eventId].Name, m_eventData[eventId].Descriptor.Task, ref activityId); - } - - if (activityId != Guid.Empty) - pActivityId = &activityId; - if (relatedActivityId != Guid.Empty) - childActivityID = &relatedActivityId; + m_activityTracker.OnStart(m_name, m_eventData[eventId].Name, m_eventData[eventId].Descriptor.Task, ref activityId, ref relatedActivityId, m_eventData[eventId].ActivityOptions); + } + else if (opcode == EventOpcode.Stop) + { + m_activityTracker.OnStop(m_name, m_eventData[eventId].Name, m_eventData[eventId].Descriptor.Task, ref activityId); } + if (activityId != Guid.Empty) + pActivityId = &activityId; + if (relatedActivityId != Guid.Empty) + childActivityID = &relatedActivityId; + } + +#if FEATURE_MANAGED_ETW + if (m_eventData[eventId].EnabledForETW) + { #if FEATURE_ACTIVITYSAMPLING // this code should be kept in sync with WriteEventWithRelatedActivityIdCore(). SessionMask etwSessions = SessionMask.All; @@ -2059,7 +2034,6 @@ namespace System.Diagnostics.Tracing } } - [SecurityCritical] unsafe private object[] SerializeEventArgs(int eventId, object[] args) { TraceLoggingEventTypes eventTypes = m_eventData[eventId].TraceLoggingEventTypes; @@ -2120,9 +2094,9 @@ namespace System.Diagnostics.Tracing private int GetParamLenghtIncludingByteArray(ParameterInfo[] parameters) { int sum = 0; - foreach(ParameterInfo info in parameters) + foreach (ParameterInfo info in parameters) { - if(info.ParameterType == typeof(byte[])) + if (info.ParameterType == typeof(byte[])) { sum += 2; } @@ -2135,7 +2109,6 @@ namespace System.Diagnostics.Tracing return sum; } - [SecurityCritical] unsafe private void WriteToAllListeners(int eventId, Guid* childActivityID, int eventDataCount, EventSource.EventData* data) { // We represent a byte[] as a integer denoting the length and then a blob of bytes in the data pointer. This causes a spurious @@ -2159,7 +2132,6 @@ namespace System.Diagnostics.Tracing } // helper for writing to all EventListeners attached the current eventSource. - [SecurityCritical] unsafe private void WriteToAllListeners(int eventId, Guid* childActivityID, params object[] args) { EventWrittenEventArgs eventCallbackArgs = new EventWrittenEventArgs(this); @@ -2173,13 +2145,12 @@ namespace System.Diagnostics.Tracing DispatchToAllListeners(eventId, childActivityID, eventCallbackArgs); } - [SecurityCritical] private unsafe void DispatchToAllListeners(int eventId, Guid* childActivityID, EventWrittenEventArgs eventCallbackArgs) { Exception lastThrownException = null; for (EventDispatcher dispatcher = m_Dispatchers; dispatcher != null; dispatcher = dispatcher.m_Next) { - Contract.Assert(dispatcher.m_EventEnabled != null); + Debug.Assert(dispatcher.m_EventEnabled != null); if (eventId == -1 || dispatcher.m_EventEnabled[eventId]) { #if FEATURE_ACTIVITYSAMPLING @@ -2214,8 +2185,7 @@ namespace System.Diagnostics.Tracing throw new EventSourceException(lastThrownException); } } - - [SecuritySafeCritical] + [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")] private unsafe void WriteEventString(EventLevel level, long keywords, string msgString) { @@ -2310,7 +2280,6 @@ namespace System.Diagnostics.Tracing } #if FEATURE_ACTIVITYSAMPLING - [SecurityCritical] unsafe private SessionMask GetEtwSessionMask(int eventId, Guid* childActivityID) { SessionMask etwSessions = new SessionMask(); @@ -2429,9 +2398,9 @@ namespace System.Diagnostics.Tracing try { m_EventSourceExceptionRecurenceCount++; - + string errorPrefix = "EventSourceException"; - if(eventName != null) + if (eventName != null) { errorPrefix += " while processing event \"" + eventName + "\""; } @@ -2473,7 +2442,7 @@ namespace System.Diagnostics.Tracing private void ValidateEventOpcodeForTransfer(ref EventMetadata eventData, string eventName) { if ((EventOpcode)eventData.Descriptor.Opcode != EventOpcode.Send && - (EventOpcode)eventData.Descriptor.Opcode != EventOpcode.Receive && + (EventOpcode)eventData.Descriptor.Opcode != EventOpcode.Receive && (EventOpcode)eventData.Descriptor.Opcode != EventOpcode.Start) { ThrowEventSourceException(eventName); @@ -2545,7 +2514,7 @@ namespace System.Diagnostics.Tracing public TraceLoggingEventTypes TraceLoggingEventTypes; public EventActivityOptions ActivityOptions; - + #if PROJECTN public EventParameterType[] ParameterTypes; #endif @@ -2611,7 +2580,7 @@ namespace System.Diagnostics.Tracing { // PRECONDITION: We should be holding the EventListener.EventListenersLock // We defer commands until we are completely inited. This allows error messages to be sent. - Contract.Assert(m_completelyInited); + Debug.Assert(m_completelyInited); #if FEATURE_MANAGED_ETW if (m_provider == null) // If we failed to construct @@ -2623,7 +2592,7 @@ namespace System.Diagnostics.Tracing try { EnsureDescriptorsInitialized(); - Contract.Assert(m_eventData != null); + Debug.Assert(m_eventData != null); // Find the per-EventSource dispatcher corresponding to registered dispatcher commandArgs.dispatcher = GetDispatcher(commandArgs.listener); @@ -2682,7 +2651,7 @@ namespace System.Diagnostics.Tracing // hasn't changed. // sesisonId = SessionMask.MAX when one of the legacy ETW sessions changed // 0 <= perEventSourceSessionId < SessionMask.MAX for activity-tracing aware sessions - Contract.Assert(commandArgs.perEventSourceSessionId >= -1 && commandArgs.perEventSourceSessionId <= SessionMask.MAX); + Debug.Assert(commandArgs.perEventSourceSessionId >= -1 && commandArgs.perEventSourceSessionId <= SessionMask.MAX); // Send the manifest if we are enabling an ETW session if (bSessionEnable && commandArgs.dispatcher == null) @@ -2737,7 +2706,7 @@ namespace System.Diagnostics.Tracing // things like log messages, or test if keywords are enabled in the callback. if (commandArgs.enable) { - Contract.Assert(m_eventData != null); + Debug.Assert(m_eventData != null); m_eventSourceEnabled = true; } @@ -2825,9 +2794,9 @@ namespace System.Diagnostics.Tracing } // These are not used for non-update commands and thus should always be 'default' values - // Contract.Assert(enable == true); - // Contract.Assert(level == EventLevel.LogAlways); - // Contract.Assert(matchAnyKeyword == EventKeywords.None); + // Debug.Assert(enable == true); + // Debug.Assert(level == EventLevel.LogAlways); + // Debug.Assert(matchAnyKeyword == EventKeywords.None); this.OnEventCommand(commandArgs); var eventCommandCallback = m_eventCommandExecuted; @@ -3017,16 +2986,15 @@ namespace System.Diagnostics.Tracing return false; } - private bool IsDisposed + private bool IsDisposed { get { return m_eventSourceDisposed; } } - [SecuritySafeCritical] private void EnsureDescriptorsInitialized() { #if !ES_BUILD_STANDALONE - Contract.Assert(Monitor.IsEntered(EventListener.EventListenersLock)); + Debug.Assert(Monitor.IsEntered(EventListener.EventListenersLock)); #endif if (m_eventData == null) { @@ -3042,9 +3010,9 @@ namespace System.Diagnostics.Tracing if (eventSourceGuid.Equals(Guid.Empty) || eventSourceName == null || eventData == null || manifest == null) { // GetMetadata failed, so we have to set it via reflection. - Contract.Assert(m_rawManifest == null); + Debug.Assert(m_rawManifest == null); m_rawManifest = CreateManifestAndDescriptors(this.GetType(), Name, this); - Contract.Assert(m_eventData != null); + Debug.Assert(m_eventData != null); } else @@ -3089,7 +3057,6 @@ namespace System.Diagnostics.Tracing // Send out the ETW manifest XML out to ETW // Today, we only send the manifest to ETW, custom listeners don't get it. - [SecuritySafeCritical] private unsafe bool SendManifest(byte[] rawManifest) { bool success = true; @@ -3097,7 +3064,7 @@ namespace System.Diagnostics.Tracing if (rawManifest == null) return false; - Contract.Assert(!SelfDescribingEvents); + Debug.Assert(!SelfDescribingEvents); #if FEATURE_MANAGED_ETW fixed (byte* dataPtr = rawManifest) @@ -3124,7 +3091,7 @@ namespace System.Diagnostics.Tracing dataDescrs[1].Reserved = 0; int chunkSize = ManifestEnvelope.MaxChunkSize; - TRY_AGAIN_WITH_SMALLER_CHUNK_SIZE: + TRY_AGAIN_WITH_SMALLER_CHUNK_SIZE: envelope.TotalChunks = (ushort)((dataLeft + (chunkSize - 1)) / chunkSize); while (dataLeft > 0) { @@ -3153,10 +3120,10 @@ namespace System.Diagnostics.Tracing dataLeft -= chunkSize; dataDescrs[1].Ptr += (uint)chunkSize; envelope.ChunkNumber++; - + // For large manifests we want to not overflow any receiver's buffer. Most manifests will fit within // 5 chunks, so only the largest manifests will hit the pause. - if((envelope.ChunkNumber % 5) == 0) + if ((envelope.ChunkNumber % 5) == 0) Thread.Sleep(15); } } @@ -3201,7 +3168,7 @@ namespace System.Diagnostics.Tracing { Attribute attr = null; - Contract.Assert(data.ConstructorArguments.Count <= 1); + Debug.Assert(data.ConstructorArguments.Count <= 1); if (data.ConstructorArguments.Count == 1) { @@ -3236,7 +3203,7 @@ namespace System.Diagnostics.Tracing return null; #else // ES_BUILD_PCL && PROJECTN - throw new ArgumentException(Resources.GetResourceString("EventSource", "EventSource_PCLPlatformNotSupportedReflection")); + throw new ArgumentException(Resources.GetResourceString("EventSource", nameof(EventSource_PCLPlatformNotSupportedReflection))); #endif } @@ -3256,8 +3223,8 @@ namespace System.Diagnostics.Tracing attributeType == reflectedAttributeType || // are the full typenames equal? string.Equals(attributeType.FullName, reflectedAttributeType.FullName, StringComparison.Ordinal) || - // are the typenames equal and the namespaces under "Diagnostics.Tracing" (typically - // either Microsoft.Diagnostics.Tracing or System.Diagnostics.Tracing)? + // are the typenames equal and the namespaces under "Diagnostics.Tracing" (typically + // either Microsoft.Diagnostics.Tracing or System.Diagnostics.Tracing)? string.Equals(attributeType.Name, reflectedAttributeType.Name, StringComparison.Ordinal) && attributeType.Namespace.EndsWith("Diagnostics.Tracing", StringComparison.Ordinal) && (reflectedAttributeType.Namespace.EndsWith("Diagnostics.Tracing", StringComparison.Ordinal) @@ -3488,7 +3455,7 @@ namespace System.Diagnostics.Tracing int startEventId = eventAttribute.EventId - 1; if (eventData != null && startEventId < eventData.Length) { - Contract.Assert(0 <= startEventId); // Since we reserve id 0, we know that id-1 is <= 0 + Debug.Assert(0 <= startEventId); // Since we reserve id 0, we know that id-1 is <= 0 EventMetadata startEventMetadata = eventData[startEventId]; // If you remove the Stop and add a Start does that name match the Start Event's Name? @@ -3535,7 +3502,7 @@ namespace System.Diagnostics.Tracing { unchecked { - eventAttribute.Keywords |= (EventKeywords)manifest.GetChannelKeyword(eventAttribute.Channel, (ulong) eventAttribute.Keywords); + eventAttribute.Keywords |= (EventKeywords)manifest.GetChannelKeyword(eventAttribute.Channel, (ulong)eventAttribute.Keywords); } } #endif @@ -3658,7 +3625,7 @@ namespace System.Diagnostics.Tracing } #endif return; - Error: + Error: manifest.ManifestError(Resources.GetResourceString("EventSource_EnumKindMismatch", staticField.Name, staticField.FieldType.Name, providerEnumKind)); } @@ -3751,7 +3718,7 @@ namespace System.Diagnostics.Tracing // We give a task to things if they don't have one. // TODO this is moderately expensive (N*N). We probably should not even bother.... - Contract.Assert(eventAttribute.Task != EventTask.None || eventAttribute.Opcode != EventOpcode.Info); + Debug.Assert(eventAttribute.Task != EventTask.None || eventAttribute.Opcode != EventOpcode.Info); for (int idx = 0; idx < eventData.Length; ++idx) { // skip unused Event IDs. @@ -3821,7 +3788,6 @@ namespace System.Diagnostics.Tracing /// /// The method to probe. /// The literal value or -1 if the value could not be determined. - [SecuritySafeCritical] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Switch statement is clearer than alternatives")] static private int GetHelperCallFirstArg(MethodInfo method) { @@ -3840,7 +3806,7 @@ namespace System.Diagnostics.Tracing (new ReflectionPermission(ReflectionPermissionFlag.MemberAccess)).Assert(); byte[] instrs = method.GetMethodBody().GetILAsByteArray(); int retVal = -1; - for (int idx = 0; idx < instrs.Length; ) + for (int idx = 0; idx < instrs.Length;) { switch (instrs[idx]) { @@ -3934,7 +3900,7 @@ namespace System.Diagnostics.Tracing goto default; break; default: - /* Contract.Assert(false, "Warning: User validation code sub-optimial: Unsuported opcode " + instrs[idx] + + /* Debug.Assert(false, "Warning: User validation code sub-optimial: Unsuported opcode " + instrs[idx] + " at " + idx + " in method " + method.Name); */ return -1; } @@ -3968,7 +3934,7 @@ namespace System.Diagnostics.Tracing { #if (!ES_BUILD_PCL && !PROJECTN) // send message to debugger without delay - System.Diagnostics.Debugger.Log(0, null, String.Format("EventSource Error: {0}{1}", msg , Environment.NewLine)); + System.Diagnostics.Debugger.Log(0, null, String.Format("EventSource Error: {0}{1}", msg, Environment.NewLine)); #endif // Send it to all listeners. @@ -4017,7 +3983,7 @@ namespace System.Diagnostics.Tracing { get { - Contract.Assert(((m_config & EventSourceSettings.EtwManifestEventFormat) != 0) != + Debug.Assert(((m_config & EventSourceSettings.EtwManifestEventFormat) != 0) != ((m_config & EventSourceSettings.EtwSelfDescribingEventFormat) != 0)); return (m_config & EventSourceSettings.EtwSelfDescribingEventFormat) != 0; } @@ -4039,7 +4005,7 @@ namespace System.Diagnostics.Tracing #if FEATURE_ACTIVITYSAMPLING private void ReportActivitySamplingInfo(EventListener listener, SessionMask sessions) { - Contract.Assert(listener == null || (uint)sessions == (uint)SessionMask.FromId(0)); + Debug.Assert(listener == null || (uint)sessions == (uint)SessionMask.FromId(0)); for (int perEventSourceSessionId = 0; perEventSourceSessionId < SessionMask.MAX; ++perEventSourceSessionId) { @@ -4050,7 +4016,7 @@ namespace System.Diagnostics.Tracing if (listener == null) { EtwSession etwSession = m_etwSessionIdMap[perEventSourceSessionId]; - Contract.Assert(etwSession != null); + Debug.Assert(etwSession != null); af = etwSession.m_activityFilter; } else @@ -4090,7 +4056,7 @@ namespace System.Diagnostics.Tracing private EventSourceSettings m_config; // configuration information private bool m_eventSourceDisposed; // has Dispose been called. - + // Enabling bits private bool m_eventSourceEnabled; // am I enabled (any of my events are enabled for any dispatcher) internal EventLevel m_level; // highest level enabled by any output dispatcher @@ -4229,7 +4195,7 @@ namespace System.Diagnostics.Tracing /// events for a particular eventSource to occur BEFORE the EventSourceCreatedCallback is issued. /// public event EventHandler EventSourceCreated - { + { add { CallBackForExistingEventSources(false, value); @@ -4255,7 +4221,7 @@ namespace System.Diagnostics.Tracing public EventListener() { // This will cause the OnEventSourceCreated callback to fire. - CallBackForExistingEventSources(true, (obj, args) => args.EventSource.AddListener(this) ); + CallBackForExistingEventSources(true, (obj, args) => args.EventSource.AddListener(this)); } /// @@ -4283,7 +4249,7 @@ namespace System.Diagnostics.Tracing { // Find 'this' from the s_Listeners linked list. EventListener prev = s_Listeners; - for (; ; ) + for (;;) { EventListener cur = prev.m_Next; if (cur == null) @@ -4397,7 +4363,7 @@ namespace System.Diagnostics.Tracing internal protected virtual void OnEventSourceCreated(EventSource eventSource) { EventHandler callBack = this._EventSourceCreated; - if(callBack != null) + if (callBack != null) { EventSourceCreatedEventArgs args = new EventSourceCreatedEventArgs(); args.EventSource = eventSource; @@ -4443,10 +4409,6 @@ namespace System.Diagnostics.Tracing if (!s_EventSourceShutdownRegistered) { s_EventSourceShutdownRegistered = true; -#if (!ES_BUILD_PCL && !FEATURE_CORECLR && !PROJECTN) - AppDomain.CurrentDomain.ProcessExit += DisposeOnShutdown; - AppDomain.CurrentDomain.DomainUnload += DisposeOnShutdown; -#endif } @@ -4492,7 +4454,7 @@ namespace System.Diagnostics.Tracing // See bug 724140 for more private static void DisposeOnShutdown(object sender, EventArgs e) { - lock(EventListenersLock) + lock (EventListenersLock) { foreach (var esRef in s_EventSources) { @@ -4512,7 +4474,7 @@ namespace System.Diagnostics.Tracing private static void RemoveReferencesToListenerInEventSources(EventListener listenerToRemove) { #if !ES_BUILD_STANDALONE - Contract.Assert(Monitor.IsEntered(EventListener.EventListenersLock)); + Debug.Assert(Monitor.IsEntered(EventListener.EventListenersLock)); #endif // Foreach existing EventSource in the appdomain foreach (WeakReference eventSourceRef in s_EventSources) @@ -4527,12 +4489,12 @@ namespace System.Diagnostics.Tracing { // Remove 'listenerToRemove' from the eventSource.m_Dispatchers linked list. EventDispatcher prev = eventSource.m_Dispatchers; - for (; ; ) + for (;;) { EventDispatcher cur = prev.m_Next; if (cur == null) { - Contract.Assert(false, "EventSource did not have a registered EventListener!"); + Debug.Assert(false, "EventSource did not have a registered EventListener!"); break; } if (cur.m_Listener == listenerToRemove) @@ -4572,13 +4534,13 @@ namespace System.Diagnostics.Tracing EventSource eventSource = eventSourceRef.Target as EventSource; if (eventSource == null) continue; - Contract.Assert(eventSource.m_id == id, "Unexpected event source ID."); + Debug.Assert(eventSource.m_id == id, "Unexpected event source ID."); // None listeners on eventSources exist in the dispatcher list. EventDispatcher dispatcher = eventSource.m_Dispatchers; while (dispatcher != null) { - Contract.Assert(allListeners.ContainsKey(dispatcher.m_Listener), "EventSource has a listener not on the global list."); + Debug.Assert(allListeners.ContainsKey(dispatcher.m_Listener), "EventSource has a listener not on the global list."); dispatcher = dispatcher.m_Next; } @@ -4586,9 +4548,9 @@ namespace System.Diagnostics.Tracing foreach (EventListener listener in allListeners.Keys) { dispatcher = eventSource.m_Dispatchers; - for (; ; ) + for (;;) { - Contract.Assert(dispatcher != null, "Listener is not on all eventSources."); + Debug.Assert(dispatcher != null, "Listener is not on all eventSources."); if (dispatcher.m_Listener == listener) break; dispatcher = dispatcher.m_Next; @@ -4818,7 +4780,6 @@ namespace System.Diagnostics.Tracing /// public Guid ActivityId { - [System.Security.SecurityCritical] get { return EventSource.CurrentThreadActivityId; } } @@ -4827,7 +4788,6 @@ namespace System.Diagnostics.Tracing /// public Guid RelatedActivityId { - [System.Security.SecurityCritical] get; internal set; } @@ -4848,7 +4808,7 @@ namespace System.Diagnostics.Tracing if (m_payloadNames == null) { // Self described events are identified by id -1. - Contract.Assert(EventId != -1); + Debug.Assert(EventId != -1); var names = new List(); foreach (var parameter in m_eventSource.m_eventData[EventId].Parameters) @@ -4893,7 +4853,7 @@ namespace System.Diagnostics.Tracing { get { - if (EventId < 0) // TraceLogging convention EventID == -1 + if (EventId <= 0) // TraceLogging convention EventID == -1 return m_opcode; return (EventOpcode)m_eventSource.m_eventData[EventId].Descriptor.Opcode; } @@ -4906,7 +4866,7 @@ namespace System.Diagnostics.Tracing { get { - if (EventId < 0) // TraceLogging convention EventID == -1 + if (EventId <= 0) // TraceLogging convention EventID == -1 return EventTask.None; return (EventTask)m_eventSource.m_eventData[EventId].Descriptor.Task; @@ -4920,20 +4880,20 @@ namespace System.Diagnostics.Tracing { get { - if (EventId < 0) // TraceLogging convention EventID == -1 + if (EventId <= 0) // TraceLogging convention EventID == -1 return m_tags; return m_eventSource.m_eventData[EventId].Tags; } } /// - /// Gets the message for the event. + /// Gets the message for the event. If the message has {N} parameters they are NOT substituted. /// public string Message { get { - if (EventId < 0) // TraceLogging convention EventID == -1 + if (EventId <= 0) // TraceLogging convention EventID == -1 return m_message; else return m_eventSource.m_eventData[EventId].Message; @@ -4953,7 +4913,7 @@ namespace System.Diagnostics.Tracing { get { - if (EventId < 0) // TraceLogging convention EventID == -1 + if (EventId <= 0) // TraceLogging convention EventID == -1 return EventChannel.None; return (EventChannel)m_eventSource.m_eventData[EventId].Descriptor.Channel; } @@ -4967,7 +4927,7 @@ namespace System.Diagnostics.Tracing { get { - if (EventId < 0) // TraceLogging convention EventID == -1 + if (EventId <= 0) // TraceLogging convention EventID == -1 return 0; return m_eventSource.m_eventData[EventId].Descriptor.Version; } @@ -4980,7 +4940,7 @@ namespace System.Diagnostics.Tracing { get { - if (EventId < 0) // TraceLogging convention EventID == -1 + if (EventId <= 0) // TraceLogging convention EventID == -1 return m_level; return (EventLevel)m_eventSource.m_eventData[EventId].Descriptor.Level; } @@ -5277,7 +5237,7 @@ namespace System.Diagnostics.Tracing public static void DisableFilter(ref ActivityFilter filterList, EventSource source) { #if !ES_BUILD_STANDALONE - Contract.Assert(Monitor.IsEntered(EventListener.EventListenersLock)); + Debug.Assert(Monitor.IsEntered(EventListener.EventListenersLock)); #endif if (filterList == null) @@ -5345,7 +5305,7 @@ namespace System.Diagnostics.Tracing string startEvents) { #if !ES_BUILD_STANDALONE - Contract.Assert(Monitor.IsEntered(EventListener.EventListenersLock)); + Debug.Assert(Monitor.IsEntered(EventListener.EventListenersLock)); #endif // first remove all filters associated with 'source' @@ -5432,7 +5392,6 @@ namespace System.Diagnostics.Tracing /// If 'childActivityID' is present, it will be added to the active set if the /// current activity is active. /// - [SecurityCritical] unsafe public static bool PassesActivityFilter( ActivityFilter filterList, Guid* childActivityID, @@ -5440,7 +5399,7 @@ namespace System.Diagnostics.Tracing EventSource source, int eventId) { - Contract.Assert(filterList != null && filterList.m_activeActivities != null); + Debug.Assert(filterList != null && filterList.m_activeActivities != null); bool shouldBeLogged = false; if (triggeringEvent) { @@ -5513,7 +5472,6 @@ namespace System.Diagnostics.Tracing return shouldBeLogged; } - [System.Security.SecuritySafeCritical] public static bool IsCurrentActivityActive(ActivityFilter filterList) { var activeActivities = GetActiveActivities(filterList); @@ -5530,13 +5488,12 @@ namespace System.Diagnostics.Tracing /// value for 'currentActivityid' is an indication tha caller has already verified /// that the current activity is active. /// - [SecurityCritical] unsafe public static void FlowActivityIfNeeded(ActivityFilter filterList, Guid* currentActivityId, Guid* childActivityID) { - Contract.Assert(childActivityID != null); + Debug.Assert(childActivityID != null); var activeActivities = GetActiveActivities(filterList); - Contract.Assert(activeActivities != null); + Debug.Assert(activeActivities != null); // take currentActivityId == null to mean we *know* the current activity is "active" if (currentActivityId != null && !activeActivities.ContainsKey(*currentActivityId)) @@ -5593,7 +5550,7 @@ namespace System.Diagnostics.Tracing public void Dispose() { #if !ES_BUILD_STANDALONE - Contract.Assert(Monitor.IsEntered(EventListener.EventListenersLock)); + Debug.Assert(Monitor.IsEntered(EventListener.EventListenersLock)); #endif // m_myActivityDelegate is still alive (held by the static EventSource.s_activityDying). // Therefore we are ok to take a dependency on m_myActivityDelegate being valid even @@ -5620,7 +5577,7 @@ namespace System.Diagnostics.Tracing m_samplingFreq = samplingFreq; m_next = existingFilter; - Contract.Assert(existingFilter == null || + Debug.Assert(existingFilter == null || (existingFilter.m_activeActivities == null) == (existingFilter.m_rootActiveActivities == null)); // if this is the first filter we add for this session, we need to create a new @@ -5694,10 +5651,10 @@ namespace System.Diagnostics.Tracing private static bool EnableFilter(ref ActivityFilter filterList, EventSource source, int perEventSourceSessionId, int eventId, int samplingFreq) { #if !ES_BUILD_STANDALONE - Contract.Assert(Monitor.IsEntered(EventListener.EventListenersLock)); + Debug.Assert(Monitor.IsEntered(EventListener.EventListenersLock)); #endif - Contract.Assert(samplingFreq > 0); - Contract.Assert(eventId >= 0); + Debug.Assert(samplingFreq > 0); + Debug.Assert(eventId >= 0); filterList = new ActivityFilter(source, perEventSourceSessionId, eventId, samplingFreq, filterList); @@ -5828,7 +5785,7 @@ namespace System.Diagnostics.Tracing public static void RemoveEtwSession(EtwSession etwSession) { - Contract.Assert(etwSession != null); + Debug.Assert(etwSession != null); if (s_etwSessions == null || etwSession == null) return; @@ -5909,7 +5866,7 @@ namespace System.Diagnostics.Tracing public static SessionMask FromId(int perEventSourceSessionId) { - Contract.Assert(perEventSourceSessionId < MAX); + Debug.Assert(perEventSourceSessionId < MAX); return new SessionMask((uint)1 << perEventSourceSessionId); } @@ -5927,12 +5884,12 @@ namespace System.Diagnostics.Tracing { get { - Contract.Assert(perEventSourceSessionId < MAX); + Debug.Assert(perEventSourceSessionId < MAX); return (m_mask & (1 << perEventSourceSessionId)) != 0; } set { - Contract.Assert(perEventSourceSessionId < MAX); + Debug.Assert(perEventSourceSessionId < MAX); if (value) m_mask |= ((uint)1 << perEventSourceSessionId); else m_mask &= ~((uint)1 << perEventSourceSessionId); } @@ -6163,7 +6120,7 @@ namespace System.Diagnostics.Tracing private EventChannelType EventChannelToChannelType(EventChannel channel) { #if !ES_BUILD_STANDALONE - Contract.Assert(channel >= EventChannel.Admin && channel <= EventChannel.Debug); + Debug.Assert(channel >= EventChannel.Admin && channel <= EventChannel.Debug); #endif return (EventChannelType)((int)channel - (int)EventChannel.Admin + (int)EventChannelType.Admin); } @@ -6206,8 +6163,8 @@ namespace System.Diagnostics.Tracing #endif public void StartEvent(string eventName, EventAttribute eventAttribute) { - Contract.Assert(numParams == 0); - Contract.Assert(this.eventName == null); + Debug.Assert(numParams == 0); + Debug.Assert(this.eventName == null); this.eventName = eventName; numParams = 0; byteArrArgIndices = null; @@ -6311,7 +6268,7 @@ namespace System.Diagnostics.Tracing // otherwise we allocate a channel bit for the channel. // explicit channel bits are only used by WCF to mimic an existing manifest, // so we don't dont do error checking. - public ulong GetChannelKeyword(EventChannel channel, ulong channelKeyword=0) + public ulong GetChannelKeyword(EventChannel channel, ulong channelKeyword = 0) { // strip off any non-channel keywords, since we are only interested in channels here. channelKeyword &= ValidPredefinedChannelKeywords; @@ -6560,7 +6517,7 @@ namespace System.Diagnostics.Tracing // very early in the app domain creation, when _FusionStore is not set up yet, resulting in a failure to run the static constructory // for BinaryCompatibility. This failure is then cached and a TypeInitializationException is thrown every time some code attampts to // access BinaryCompatibility. - ArraySortHelper.IntrospectiveSort(sortedStrings, 0, sortedStrings.Length, Comparer.Default); + ArraySortHelper.IntrospectiveSort(sortedStrings, 0, sortedStrings.Length, string.Compare); #endif foreach (var ci in cultures) { @@ -6642,13 +6599,7 @@ namespace System.Diagnostics.Tracing private static List GetSupportedCultures(ResourceManager resources) { var cultures = new List(); -#if !ES_BUILD_PCL && !FEATURE_CORECLR && !PROJECTN - foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.SpecificCultures /*| CultureTypes.NeutralCultures*/)) - { - if (resources.GetResourceSet(ci, true, false) != null) - cultures.Add(ci); - } -#endif // !ES_BUILD_PCL && !FEATURE_CORECLR + if (!cultures.Contains(CultureInfo.CurrentUICulture)) cultures.Insert(0, CultureInfo.CurrentUICulture); return cultures; @@ -6701,7 +6652,7 @@ namespace System.Diagnostics.Tracing ret = taskTab[(int)task] = eventName; return ret; } - + private string GetOpcodeName(EventOpcode opcode, string eventName) { switch (opcode) @@ -6738,12 +6689,12 @@ namespace System.Diagnostics.Tracing } return ret; } - + private string GetKeywords(ulong keywords, string eventName) { // ignore keywords associate with channels // See ValidPredefinedChannelKeywords def for more. - keywords &= ~ValidPredefinedChannelKeywords; + keywords &= ~ValidPredefinedChannelKeywords; string ret = ""; for (ulong bit = 1; bit != 0; bit <<= 1) @@ -6770,7 +6721,7 @@ namespace System.Diagnostics.Tracing } return ret; } - + private string GetTypeName(Type type) { if (type.IsEnum()) @@ -6779,7 +6730,7 @@ namespace System.Diagnostics.Tracing var typeName = GetTypeName(fields[0].FieldType); return typeName.Replace("win:Int", "win:UInt"); // ETW requires enums to be unsigned. } - + return GetTypeNameHelper(type); } @@ -6797,7 +6748,7 @@ namespace System.Diagnostics.Tracing StringBuilder stringBuilder = null; // We lazily create this int writtenSoFar = 0; int chIdx = -1; - for (int i = 0; ; ) + for (int i = 0; ;) { if (i >= eventMessage.Length) { diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/EventSource_CoreCLR.cs b/src/mscorlib/src/System/Diagnostics/Eventing/EventSource_CoreCLR.cs index 00bd0b7..0a689ef 100644 --- a/src/mscorlib/src/System/Diagnostics/Eventing/EventSource_CoreCLR.cs +++ b/src/mscorlib/src/System/Diagnostics/Eventing/EventSource_CoreCLR.cs @@ -29,7 +29,6 @@ namespace System.Diagnostics.Tracing /// /// A Guid that represents the new activity with which to mark /// the current thread - [System.Security.SecuritySafeCritical] public static void SetCurrentThreadActivityId(Guid activityId) { if (TplEtwProvider.Log != null) @@ -80,7 +79,6 @@ namespace System.Diagnostics.Tracing /// the current thread /// The Guid that represents the current activity /// which will continue at some point in the future, on the current thread - [System.Security.SecuritySafeCritical] public static void SetCurrentThreadActivityId(Guid activityId, out Guid oldActivityThatWillContinue) { oldActivityThatWillContinue = activityId; @@ -104,7 +102,6 @@ namespace System.Diagnostics.Tracing /// public static Guid CurrentThreadActivityId { - [System.Security.SecuritySafeCritical] get { // We ignore errors to keep with the convention that EventSources do not throw @@ -186,7 +183,6 @@ namespace System.Diagnostics.Tracing internal partial class EventProvider { - [System.Security.SecurityCritical] internal unsafe int SetInformation( UnsafeNativeMethods.ManifestEtw.EVENT_INFO_CLASS eventInfoClass, IntPtr data, diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/DataCollector.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/DataCollector.cs index d0d687e..079d7f4 100644 --- a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/DataCollector.cs +++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/DataCollector.cs @@ -22,7 +22,6 @@ namespace System.Diagnostics.Tracing /// EventWrite. The instance must be Disabled before the arrays referenced /// by the pointers are freed or unpinned. /// - [SecurityCritical] internal unsafe struct DataCollector { [ThreadStatic] diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventPayload.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventPayload.cs index be97447..5967ad6 100644 --- a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventPayload.cs +++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventPayload.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Collections; +using System.Diagnostics; #if !ES_BUILD_AGAINST_DOTNET_V35 using Contract = System.Diagnostics.Contracts.Contract; @@ -26,7 +27,7 @@ namespace System.Diagnostics.Tracing { internal EventPayload(List payloadNames, List payloadValues) { - Contract.Assert(payloadNames.Count == payloadValues.Count); + Debug.Assert(payloadNames.Count == payloadValues.Count); m_names = payloadNames; m_values = payloadValues; @@ -40,7 +41,7 @@ namespace System.Diagnostics.Tracing get { if (key == null) - throw new System.ArgumentNullException("key"); + throw new System.ArgumentNullException(nameof(key)); int position = 0; foreach(var name in m_names) @@ -83,7 +84,7 @@ namespace System.Diagnostics.Tracing public bool ContainsKey(string key) { if (key == null) - throw new System.ArgumentNullException("key"); + throw new System.ArgumentNullException(nameof(key)); foreach (var item in m_names) { @@ -129,7 +130,7 @@ namespace System.Diagnostics.Tracing public bool TryGetValue(string key, out object value) { if (key == null) - throw new System.ArgumentNullException("key"); + throw new System.ArgumentNullException(nameof(key)); int position = 0; foreach (var name in m_names) diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventSourceActivity.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventSourceActivity.cs index fccfd48..38c1767 100644 --- a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventSourceActivity.cs +++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventSourceActivity.cs @@ -35,7 +35,7 @@ namespace System.Diagnostics.Tracing public EventSourceActivity(EventSource eventSource) { if (eventSource == null) - throw new ArgumentNullException("eventSource"); + throw new ArgumentNullException(nameof(eventSource)); Contract.EndContractBlock(); this.eventSource = eventSource; diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/FieldMetadata.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/FieldMetadata.cs index 45673f7..309226b 100644 --- a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/FieldMetadata.cs +++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/FieldMetadata.cs @@ -108,7 +108,7 @@ namespace System.Diagnostics.Tracing if (name == null) { throw new ArgumentNullException( - "name", + nameof(name), "This usually means that the object passed to Write is of a type that" + " does not support being used as the top-level object in an event," + " e.g. a primitive or built-in type."); diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/PropertyValue.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/PropertyValue.cs index 0f34d95..3ea7812 100644 --- a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/PropertyValue.cs +++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/PropertyValue.cs @@ -1,5 +1,6 @@ using System.Reflection; using System.Runtime.InteropServices; +using System.Diagnostics; #if !ES_BUILD_AGAINST_DOTNET_V35 using Contract = System.Diagnostics.Contracts.Contract; @@ -132,7 +133,7 @@ namespace System.Diagnostics.Tracing { get { - Contract.Assert(_scalarLength == 0, "This ReflectedValue refers to an unboxed value type, not a reference type or boxed value type."); + Debug.Assert(_scalarLength == 0, "This ReflectedValue refers to an unboxed value type, not a reference type or boxed value type."); return _reference; } } @@ -141,7 +142,7 @@ namespace System.Diagnostics.Tracing { get { - Contract.Assert(_scalarLength > 0, "This ReflectedValue refers to a reference type or boxed value type, not an unboxed value type"); + Debug.Assert(_scalarLength > 0, "This ReflectedValue refers to a reference type or boxed value type, not an unboxed value type"); return _scalar; } } @@ -150,7 +151,7 @@ namespace System.Diagnostics.Tracing { get { - Contract.Assert(_scalarLength > 0, "This ReflectedValue refers to a reference type or boxed value type, not an unboxed value type"); + Debug.Assert(_scalarLength > 0, "This ReflectedValue refers to a reference type or boxed value type, not an unboxed value type"); return _scalarLength; } } diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/SimpleTypeInfos.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/SimpleTypeInfos.cs index e51aff0..901a0ed 100644 --- a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/SimpleTypeInfos.cs +++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/SimpleTypeInfos.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Reflection; +using System.Diagnostics; #if !ES_BUILD_AGAINST_DOTNET_V35 using Contract = System.Diagnostics.Contracts.Contract; @@ -269,7 +270,7 @@ namespace System.Diagnostics.Tracing : base(type) { var typeArgs = type.GenericTypeArguments; - Contract.Assert(typeArgs.Length == 1); + Debug.Assert(typeArgs.Length == 1); this.valueInfo = TraceLoggingTypeInfo.GetInstance(typeArgs[0], recursionCheck); this.hasValueGetter = PropertyValue.GetPropertyGetter(type.GetTypeInfo().GetDeclaredProperty("HasValue")); this.valueGetter = PropertyValue.GetPropertyGetter(type.GetTypeInfo().GetDeclaredProperty("Value")); diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/Statics.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/Statics.cs index fa0f79f..516c8ba 100644 --- a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/Statics.cs +++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/Statics.cs @@ -175,7 +175,7 @@ namespace System.Diagnostics.Tracing { if (name != null && 0 <= name.IndexOf('\0')) { - throw new ArgumentOutOfRangeException("name"); + throw new ArgumentOutOfRangeException(nameof(name)); } } diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingDataCollector.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingDataCollector.cs index 4b6e633..04a047f 100644 --- a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingDataCollector.cs +++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingDataCollector.cs @@ -21,7 +21,6 @@ namespace System.Diagnostics.Tracing /// full-trust code, this abstraction is unnecessary (though it probably /// doesn't hurt anything). /// - [SecuritySafeCritical] internal unsafe class TraceLoggingDataCollector { internal static readonly TraceLoggingDataCollector Instance = new TraceLoggingDataCollector(); diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventSource.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventSource.cs index 963c492..07a5675 100644 --- a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventSource.cs +++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventSource.cs @@ -100,7 +100,7 @@ namespace System.Diagnostics.Tracing { if (eventSourceName == null) { - throw new ArgumentNullException("eventSourceName"); + throw new ArgumentNullException(nameof(eventSourceName)); } Contract.EndContractBlock(); } @@ -110,12 +110,11 @@ namespace System.Diagnostics.Tracing /// (Native API: EventWriteTransfer) /// /// The name of the event. Must not be null. - [SecuritySafeCritical] public unsafe void Write(string eventName) { if (eventName == null) { - throw new ArgumentNullException("eventName"); + throw new ArgumentNullException(nameof(eventName)); } Contract.EndContractBlock(); @@ -138,12 +137,11 @@ namespace System.Diagnostics.Tracing /// Options for the event, such as the level, keywords, and opcode. Unset /// options will be set to default values. /// - [SecuritySafeCritical] public unsafe void Write(string eventName, EventSourceOptions options) { if (eventName == null) { - throw new ArgumentNullException("eventName"); + throw new ArgumentNullException(nameof(eventName)); } Contract.EndContractBlock(); @@ -175,7 +173,6 @@ namespace System.Diagnostics.Tracing /// public instance properties of data will be written recursively to /// create the fields of the event. /// - [SecuritySafeCritical] public unsafe void Write( string eventName, T data) @@ -212,7 +209,6 @@ namespace System.Diagnostics.Tracing /// public instance properties of data will be written recursively to /// create the fields of the event. /// - [SecuritySafeCritical] public unsafe void Write( string eventName, EventSourceOptions options, @@ -251,7 +247,6 @@ namespace System.Diagnostics.Tracing /// public instance properties of data will be written recursively to /// create the fields of the event. /// - [SecuritySafeCritical] public unsafe void Write( string eventName, ref EventSourceOptions options, @@ -297,7 +292,6 @@ namespace System.Diagnostics.Tracing /// public instance properties of data will be written recursively to /// create the fields of the event. /// - [SecuritySafeCritical] public unsafe void Write( string eventName, ref EventSourceOptions options, @@ -354,7 +348,6 @@ namespace System.Diagnostics.Tracing /// the values must match the number and types of the fields described by the /// eventTypes parameter. /// - [SecuritySafeCritical] private unsafe void WriteMultiMerge( string eventName, ref EventSourceOptions options, @@ -415,7 +408,6 @@ namespace System.Diagnostics.Tracing /// the values must match the number and types of the fields described by the /// eventTypes parameter. /// - [SecuritySafeCritical] private unsafe void WriteMultiMergeInner( string eventName, ref EventSourceOptions options, @@ -526,7 +518,6 @@ namespace System.Diagnostics.Tracing /// The number and types of the values must match the number and types of the /// fields described by the eventTypes parameter. /// - [SecuritySafeCritical] internal unsafe void WriteMultiMerge( string eventName, ref EventSourceOptions options, @@ -604,7 +595,6 @@ namespace System.Diagnostics.Tracing #endif // FEATURE_MANAGED_ETW } - [SecuritySafeCritical] private unsafe void WriteImpl( string eventName, ref EventSourceOptions options, @@ -721,7 +711,6 @@ namespace System.Diagnostics.Tracing } } - [SecurityCritical] private unsafe void WriteToAllListeners(string eventName, ref EventDescriptor eventDescriptor, EventTags tags, Guid* pActivityId, EventPayload payload) { EventWrittenEventArgs eventCallbackArgs = new EventWrittenEventArgs(this); @@ -750,7 +739,6 @@ namespace System.Diagnostics.Tracing System.Runtime.ConstrainedExecution.Consistency.WillNotCorruptState, System.Runtime.ConstrainedExecution.Cer.Success)] #endif - [SecurityCritical] [NonEvent] private unsafe void WriteCleanup(GCHandle* pPins, int cPins) { diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventTypes.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventTypes.cs index 4e33e58..c223967 100644 --- a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventTypes.cs +++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventTypes.cs @@ -94,7 +94,7 @@ namespace System.Diagnostics.Tracing { if (name == null) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } Contract.EndContractBlock(); @@ -132,7 +132,7 @@ namespace System.Diagnostics.Tracing { if (defaultName == null) { - throw new ArgumentNullException("defaultName"); + throw new ArgumentNullException(nameof(defaultName)); } Contract.EndContractBlock(); @@ -212,7 +212,7 @@ namespace System.Diagnostics.Tracing { if (paramInfos == null) { - throw new ArgumentNullException("paramInfos"); + throw new ArgumentNullException(nameof(paramInfos)); } Contract.EndContractBlock(); @@ -231,7 +231,7 @@ namespace System.Diagnostics.Tracing { if (types == null) { - throw new ArgumentNullException("types"); + throw new ArgumentNullException(nameof(types)); } Contract.EndContractBlock(); @@ -251,7 +251,7 @@ namespace System.Diagnostics.Tracing { if (typeInfos == null) { - throw new ArgumentNullException("typeInfos"); + throw new ArgumentNullException(nameof(typeInfos)); } Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingMetadataCollector.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingMetadataCollector.cs index 0467ec4..41225c8 100644 --- a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingMetadataCollector.cs +++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingMetadataCollector.cs @@ -156,7 +156,7 @@ namespace System.Diagnostics.Tracing size = 16; break; default: - throw new ArgumentOutOfRangeException("type"); + throw new ArgumentOutOfRangeException(nameof(type)); } this.impl.AddScalar(size); @@ -183,7 +183,7 @@ namespace System.Diagnostics.Tracing case TraceLoggingDataType.CountedUtf16String: break; default: - throw new ArgumentOutOfRangeException("type"); + throw new ArgumentOutOfRangeException(nameof(type)); } this.impl.AddScalar(2); @@ -227,7 +227,7 @@ namespace System.Diagnostics.Tracing case TraceLoggingDataType.Char8: break; default: - throw new ArgumentOutOfRangeException("type"); + throw new ArgumentOutOfRangeException(nameof(type)); } if (this.BeginningBufferedArray) diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingTypeInfo.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingTypeInfo.cs index 5815d12..0cc17e0 100644 --- a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingTypeInfo.cs +++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingTypeInfo.cs @@ -36,7 +36,7 @@ namespace System.Diagnostics.Tracing { if (dataType == null) { - throw new ArgumentNullException("dataType"); + throw new ArgumentNullException(nameof(dataType)); } Contract.EndContractBlock(); @@ -56,7 +56,7 @@ namespace System.Diagnostics.Tracing { if (dataType == null) { - throw new ArgumentNullException("dataType"); + throw new ArgumentNullException(nameof(dataType)); } if (name == null) diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/XplatEventLogger.cs b/src/mscorlib/src/System/Diagnostics/Eventing/XplatEventLogger.cs index d7112fc..c96d212 100644 --- a/src/mscorlib/src/System/Diagnostics/Eventing/XplatEventLogger.cs +++ b/src/mscorlib/src/System/Diagnostics/Eventing/XplatEventLogger.cs @@ -73,9 +73,8 @@ namespace System.Diagnostics.Tracing } } - private static string Serialize(ReadOnlyCollection payloadName, ReadOnlyCollection payload, string sep = ", ") + private static string Serialize(ReadOnlyCollection payloadName, ReadOnlyCollection payload, string eventMessage) { - if (payloadName == null || payload == null ) return String.Empty; @@ -92,8 +91,22 @@ namespace System.Diagnostics.Tracing var sb = StringBuilderCache.Acquire(); sb.Append('{'); + + // If the event has a message, send that as well as a pseudo-field + if (!string.IsNullOrEmpty(eventMessage)) + { + sb.Append("\\\"EventSource_Message\\\":\\\""); + minimalJsonserializer(eventMessage,sb); + sb.Append("\\\""); + if (eventDataCount != 0) + sb.Append(", "); + } + for (int i = 0; i < eventDataCount; i++) { + if (i != 0) + sb.Append(", "); + var fieldstr = payloadName[i].ToString(); sb.Append("\\\""); @@ -114,14 +127,9 @@ namespace System.Diagnostics.Tracing sb.Append(payload[i].ToString()); } - sb.Append(sep); - } - - sb.Length -= sep.Length; - sb.Append('}'); - - return StringBuilderCache.GetStringAndRelease(sb); + sb.Append('}'); + return StringBuilderCache.GetStringAndRelease(sb); } internal protected override void OnEventSourceCreated(EventSource eventSource) @@ -149,7 +157,7 @@ namespace System.Diagnostics.Tracing if (eventData.Payload != null) { try{ - payload = Serialize(eventData.PayloadNames, eventData.Payload); + payload = Serialize(eventData.PayloadNames, eventData.Payload, eventData.Message); } catch (Exception ex) { diff --git a/src/mscorlib/src/System/Diagnostics/LogSwitch.cs b/src/mscorlib/src/System/Diagnostics/LogSwitch.cs index e3e2b86..84f6b91 100644 --- a/src/mscorlib/src/System/Diagnostics/LogSwitch.cs +++ b/src/mscorlib/src/System/Diagnostics/LogSwitch.cs @@ -33,11 +33,10 @@ namespace System.Diagnostics { // // All switches (except for the global LogSwitch) have a parent LogSwitch. // - [System.Security.SecuritySafeCritical] // auto-generated public LogSwitch(String name, String description, LogSwitch parent) { if (name != null && name.Length == 0) - throw new ArgumentOutOfRangeException("Name", Environment.GetResourceString("Argument_StringZeroLength")); + throw new ArgumentOutOfRangeException(nameof(Name), Environment.GetResourceString("Argument_StringZeroLength")); Contract.EndContractBlock(); if ((name != null) && (parent != null)) @@ -55,10 +54,9 @@ namespace System.Diagnostics { Log.AddLogSwitch (this); } else - throw new ArgumentNullException ((name==null ? "name" : "parent")); + throw new ArgumentNullException ((name==null ? nameof(name) : nameof(parent))); } - [System.Security.SecuritySafeCritical] // auto-generated internal LogSwitch(String name, String description) { strName = name; @@ -100,7 +98,6 @@ namespace System.Diagnostics { public virtual LoggingLevels MinimumLevel { get { return iLevel; } - [System.Security.SecuritySafeCritical] // auto-generated set { iLevel = value; diff --git a/src/mscorlib/src/System/Diagnostics/Stackframe.cs b/src/mscorlib/src/System/Diagnostics/Stackframe.cs index 397c3e1..06d675e 100644 --- a/src/mscorlib/src/System/Diagnostics/Stackframe.cs +++ b/src/mscorlib/src/System/Diagnostics/Stackframe.cs @@ -11,13 +11,7 @@ namespace System.Diagnostics { using System.Security.Permissions; using System.Diagnostics.Contracts; - // There is no good reason for the methods of this class to be virtual. - // In order to ensure trusted code can trust the data it gets from a - // StackTrace, we use an InheritanceDemand to prevent partially-trusted - // subclasses. -#if !FEATURE_CORECLR - [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)] -#endif + // There is no good reason for the methods of this class to be virtual. [Serializable] [System.Runtime.InteropServices.ComVisible(true)] public class StackFrame @@ -49,9 +43,6 @@ namespace System.Diagnostics { } // Constructs a StackFrame corresponding to the active stack frame. -#if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] -#endif public StackFrame() { InitMembers(); @@ -59,9 +50,6 @@ namespace System.Diagnostics { } // Constructs a StackFrame corresponding to the active stack frame. - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif public StackFrame(bool fNeedFileInfo) { InitMembers(); @@ -78,9 +66,6 @@ namespace System.Diagnostics { // Constructs a StackFrame corresponding to a calling stack frame. // - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif public StackFrame(int skipFrames, bool fNeedFileInfo) { InitMembers(); @@ -200,11 +185,6 @@ namespace System.Diagnostics { // information is normally extracted from the debugging symbols // for the executable. // - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif public virtual String GetFileName() { if (strFileName != null) @@ -242,7 +222,6 @@ namespace System.Diagnostics { // Builds a readable representation of the stack frame // - [System.Security.SecuritySafeCritical] // auto-generated public override String ToString() { StringBuilder sb = new StringBuilder(255); diff --git a/src/mscorlib/src/System/Diagnostics/Stacktrace.cs b/src/mscorlib/src/System/Diagnostics/Stacktrace.cs index 047a60f..7dc5d9d 100644 --- a/src/mscorlib/src/System/Diagnostics/Stacktrace.cs +++ b/src/mscorlib/src/System/Diagnostics/Stacktrace.cs @@ -61,14 +61,12 @@ namespace System.Diagnostics { IntPtr inMemoryPdbAddress, int inMemoryPdbSize, int methodToken, int ilOffset, out string sourceFile, out int sourceLine, out int sourceColumn); -#if FEATURE_CORECLR private static Type s_symbolsType = null; private static MethodInfo s_symbolsMethodInfo = null; [ThreadStatic] private static int t_reentrancy = 0; -#endif - + public StackFrameHelper(Thread target) { targetThread = target; @@ -111,7 +109,6 @@ namespace System.Diagnostics { { StackTrace.GetStackFramesInternal(this, iSkip, fNeedFileInfo, exception); -#if FEATURE_CORECLR if (!fNeedFileInfo) return; @@ -164,12 +161,10 @@ namespace System.Diagnostics { { t_reentrancy--; } -#endif } void IDisposable.Dispose() { -#if FEATURE_CORECLR if (getSourceLineInfo != null) { IDisposable disposable = getSourceLineInfo.Target as IDisposable; @@ -178,10 +173,8 @@ namespace System.Diagnostics { disposable.Dispose(); } } -#endif } - [System.Security.SecuritySafeCritical] public virtual MethodBase GetMethodBase(int i) { // There may be a better way to do this. @@ -219,7 +212,6 @@ namespace System.Diagnostics { // serialization implementation // [OnSerializing] - [SecuritySafeCritical] void OnSerializing(StreamingContext context) { // this is called in the process of serializing this object. @@ -244,7 +236,6 @@ namespace System.Diagnostics { } [OnDeserialized] - [SecuritySafeCritical] void OnDeserialized(StreamingContext context) { // after we are done deserializing we need to transform the rgMethodBase in rgMethodHandle @@ -267,9 +258,6 @@ namespace System.Diagnostics { // In order to ensure trusted code can trust the data it gets from a // StackTrace, we use an InheritanceDemand to prevent partially-trusted // subclasses. -#if !FEATURE_CORECLR - [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)] -#endif [Serializable] [System.Runtime.InteropServices.ComVisible(true)] public class StackTrace @@ -280,9 +268,6 @@ namespace System.Diagnostics { private int m_iMethodsToSkip; // Constructs a stack trace from the current location. -#if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] -#endif public StackTrace() { m_iNumOfFrames = 0; @@ -292,9 +277,6 @@ namespace System.Diagnostics { // Constructs a stack trace from the current location. // -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif public StackTrace(bool fNeedFileInfo) { m_iNumOfFrames = 0; @@ -305,14 +287,11 @@ namespace System.Diagnostics { // Constructs a stack trace from the current location, in a caller's // frame // -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif public StackTrace(int skipFrames) { if (skipFrames < 0) - throw new ArgumentOutOfRangeException("skipFrames", + throw new ArgumentOutOfRangeException(nameof(skipFrames), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -325,14 +304,11 @@ namespace System.Diagnostics { // Constructs a stack trace from the current location, in a caller's // frame // -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif public StackTrace(int skipFrames, bool fNeedFileInfo) { if (skipFrames < 0) - throw new ArgumentOutOfRangeException("skipFrames", + throw new ArgumentOutOfRangeException(nameof(skipFrames), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -347,7 +323,7 @@ namespace System.Diagnostics { public StackTrace(Exception e) { if (e == null) - throw new ArgumentNullException("e"); + throw new ArgumentNullException(nameof(e)); Contract.EndContractBlock(); m_iNumOfFrames = 0; @@ -357,13 +333,10 @@ namespace System.Diagnostics { // Constructs a stack trace from the current location. // -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif public StackTrace(Exception e, bool fNeedFileInfo) { if (e == null) - throw new ArgumentNullException("e"); + throw new ArgumentNullException(nameof(e)); Contract.EndContractBlock(); m_iNumOfFrames = 0; @@ -374,16 +347,13 @@ namespace System.Diagnostics { // Constructs a stack trace from the current location, in a caller's // frame // -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif public StackTrace(Exception e, int skipFrames) { if (e == null) - throw new ArgumentNullException("e"); + throw new ArgumentNullException(nameof(e)); if (skipFrames < 0) - throw new ArgumentOutOfRangeException("skipFrames", + throw new ArgumentOutOfRangeException(nameof(skipFrames), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -396,16 +366,13 @@ namespace System.Diagnostics { // Constructs a stack trace from the current location, in a caller's // frame // -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif public StackTrace(Exception e, int skipFrames, bool fNeedFileInfo) { if (e == null) - throw new ArgumentNullException("e"); + throw new ArgumentNullException(nameof(e)); if (skipFrames < 0) - throw new ArgumentOutOfRangeException("skipFrames", + throw new ArgumentOutOfRangeException(nameof(skipFrames), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -430,9 +397,6 @@ namespace System.Diagnostics { // Constructs a stack trace for the given thread // -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif [Obsolete("This constructor has been deprecated. Please use a constructor that does not require a Thread parameter. http://go.microsoft.com/fwlink/?linkid=14202")] public StackTrace(Thread targetThread, bool needFileInfo) { @@ -443,7 +407,6 @@ namespace System.Diagnostics { } - [System.Security.SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void GetStackFramesInternal(StackFrameHelper sfh, int iSkip, bool fNeedFileInfo, Exception e); @@ -576,9 +539,6 @@ namespace System.Diagnostics { // Builds a readable representation of the stack trace // -#if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] -#endif public override String ToString() { // Include a trailing newline for backwards compatibility @@ -596,9 +556,6 @@ namespace System.Diagnostics { // Builds a readable representation of the stack trace, specifying // the format for backwards compatibility. -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif internal String ToString(TraceFormat traceFormat) { bool displayFilenames = true; // we'll try, but demand may fail @@ -656,26 +613,22 @@ namespace System.Diagnostics { else fFirstTyParam = false; - sb.Append(typars[k].Name); + sb.Append(typars[k].Name); k++; } sb.Append(']'); } ParameterInfo[] pi = null; -#if FEATURE_CORECLR try { -#endif pi = mb.GetParameters(); -#if FEATURE_CORECLR } catch { // The parameter info cannot be loaded, so we don't // append the parameter list. } -#endif if (pi != null) { // arguments printing @@ -712,15 +665,6 @@ namespace System.Diagnostics { { fileName = sf.GetFileName(); } -#if FEATURE_CAS_POLICY - catch (NotSupportedException) - { - // Having a deprecated stack modifier on the callstack (such as Deny) will cause - // a NotSupportedException to be thrown. Since we don't know if the app can - // access the file names, we'll conservatively hide them. - displayFilenames = false; - } -#endif // FEATURE_CAS_POLICY catch (SecurityException) { // If the demand for displaying filenames fails, then it won't @@ -754,9 +698,6 @@ namespace System.Diagnostics { // This helper is called from within the EE to construct a string representation // of the current stack trace. -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif private static String GetManagedStackTraceStringHelper(bool fNeedFileInfo) { // Note all the frames in System.Diagnostics will be skipped when capturing diff --git a/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymWriter.cs b/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymWriter.cs index b6177be..a0d3640 100644 --- a/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymWriter.cs +++ b/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymWriter.cs @@ -31,9 +31,6 @@ namespace System.Diagnostics.SymbolStore { // Define a source document. Guid's will be provided for the // languages, vendors, and document types that we currently know // about. - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif ISymbolDocumentWriter DefineDocument(String url, Guid language, Guid languageVendor, @@ -42,9 +39,6 @@ namespace System.Diagnostics.SymbolStore { // Define the method that the user has defined as their entrypoint // for this module. This would be, perhaps, the user's main method // rather than compiler generated stubs before main. - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif void SetUserEntryPoint(SymbolToken entryMethod); // Open a method to emit symbol information into. The given method @@ -55,25 +49,16 @@ namespace System.Diagnostics.SymbolStore { // defined symbols for that method. // // There can be only one open method at a time. - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif void OpenMethod(SymbolToken method); // Close the current method. Once a method is closed, no more // symbols can be defined within it. - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif void CloseMethod(); // Define a group of sequence points within the current method. // Each line/column defines the start of a statement within a // method. The arrays should be sorted by offset. The offset is // always the offset from the start of the method, in bytes. - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif void DefineSequencePoints(ISymbolDocumentWriter document, int[] offsets, int[] lines, @@ -96,17 +81,11 @@ namespace System.Diagnostics.SymbolStore { // Note: scope id's are only valid in the current method. // - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif int OpenScope(int startOffset); // Close the current lexical scope. Once a scope is closed no more // variables can be defined within it. endOffset points past the // last instruction in the scope. - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif void CloseScope(int endOffset); // Define the offset range for a given lexical scope. @@ -120,9 +99,6 @@ namespace System.Diagnostics.SymbolStore { // variable of the same name that has multiple homes throughout a // scope. (Note: start/end offsets must not overlap in such a // case.) - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif void DefineLocalVariable(String name, FieldAttributes attributes, byte[] signature, @@ -178,9 +154,6 @@ namespace System.Diagnostics.SymbolStore { // Defines a custom attribute based upon its name. Not to be // confused with Metadata custom attributes, these attributes are // held in the symbol store. - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif void SetSymAttribute(SymbolToken parent, String name, byte[] data); // Opens a new namespace. Call this before defining methods or @@ -195,9 +168,6 @@ namespace System.Diagnostics.SymbolStore { // current scope will also stop using the namespace, and the // namespace will be in use in all scopes that inherit from the // currently open scope. - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif void UsingNamespace(String fullName); // Specifies the true start and end of a method within a source diff --git a/src/mscorlib/src/System/Diagnostics/log.cs b/src/mscorlib/src/System/Diagnostics/log.cs index 1c68aad..6916ce3 100644 --- a/src/mscorlib/src/System/Diagnostics/log.cs +++ b/src/mscorlib/src/System/Diagnostics/log.cs @@ -22,7 +22,6 @@ namespace System.Diagnostics { // programatically, by registry (specifics....) or environment // variables. [Serializable] - [HostProtection(Synchronization=true, ExternalThreading=true)] internal delegate void LogMessageEventHandler(LoggingLevels level, LogSwitch category, String message, StackTrace location); @@ -140,7 +139,7 @@ namespace System.Diagnostics { throw new ArgumentNullException ("LogSwitch"); if (level < 0) - throw new ArgumentOutOfRangeException("level", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(level), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); // Is logging for this level for this switch enabled? @@ -240,10 +239,8 @@ namespace System.Diagnostics { // Native method to inform the EE about the creation of a new LogSwitch - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void AddLogSwitch(LogSwitch logSwitch); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void ModifyLogSwitch (int iNewLevel, String strSwitchName, String strParentName); } diff --git a/src/mscorlib/src/System/Double.cs b/src/mscorlib/src/System/Double.cs index b2d509a..ce146a1 100644 --- a/src/mscorlib/src/System/Double.cs +++ b/src/mscorlib/src/System/Double.cs @@ -44,7 +44,6 @@ namespace System { internal static double NegativeZero = BitConverter.Int64BitsToDouble(unchecked((long)0x8000000000000000)); [Pure] - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.Versioning.NonVersionable] public unsafe static bool IsInfinity(double d) { return (*(long*)(&d) & 0x7FFFFFFFFFFFFFFF) == 0x7FF0000000000000; @@ -79,14 +78,12 @@ namespace System { } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static bool IsNegative(double d) { return (*(UInt64*)(&d) & 0x8000000000000000) == 0x8000000000000000; } [Pure] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [System.Security.SecuritySafeCritical] [System.Runtime.Versioning.NonVersionable] public unsafe static bool IsNaN(double d) { @@ -187,7 +184,6 @@ namespace System { //The hashcode for a double is the absolute value of the integer representation //of that double. // - [System.Security.SecuritySafeCritical] public unsafe override int GetHashCode() { double d = m_value; if (d == 0) { @@ -198,25 +194,21 @@ namespace System { return unchecked((int)value) ^ ((int)(value >> 32)); } - [System.Security.SecuritySafeCritical] // auto-generated public override String ToString() { Contract.Ensures(Contract.Result() != null); return Number.FormatDouble(m_value, null, NumberFormatInfo.CurrentInfo); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(String format) { Contract.Ensures(Contract.Result() != null); return Number.FormatDouble(m_value, format, NumberFormatInfo.CurrentInfo); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(IFormatProvider provider) { Contract.Ensures(Contract.Result() != null); return Number.FormatDouble(m_value, null, NumberFormatInfo.GetInstance(provider)); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(String format, IFormatProvider provider) { Contract.Ensures(Contract.Result() != null); return Number.FormatDouble(m_value, format, NumberFormatInfo.GetInstance(provider)); diff --git a/src/mscorlib/src/System/Empty.cs b/src/mscorlib/src/System/Empty.cs index f7e7486..4790d9a 100644 --- a/src/mscorlib/src/System/Empty.cs +++ b/src/mscorlib/src/System/Empty.cs @@ -25,10 +25,9 @@ namespace System { return String.Empty; } - [System.Security.SecurityCritical] // auto-generated public void GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); UnitySerializationHolder.GetUnitySerializationInfo(info, UnitySerializationHolder.EmptyUnity, null, null); diff --git a/src/mscorlib/src/System/Enum.cs b/src/mscorlib/src/System/Enum.cs index a810455..d39e005 100644 --- a/src/mscorlib/src/System/Enum.cs +++ b/src/mscorlib/src/System/Enum.cs @@ -9,6 +9,7 @@ using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; +using System.Diagnostics; using System.Diagnostics.Contracts; namespace System @@ -23,7 +24,6 @@ namespace System #endregion #region Private Static Methods - [System.Security.SecuritySafeCritical] // auto-generated private static TypeValuesAndNames GetCachedValuesAndNames(RuntimeType enumType, bool getNames) { TypeValuesAndNames entry = enumType.GenericCache as TypeValuesAndNames; @@ -47,7 +47,6 @@ namespace System return entry; } - [System.Security.SecuritySafeCritical] private unsafe String InternalFormattedHexString() { fixed (void* pValue = &JitHelpers.GetPinningHelper(this).m_data) @@ -71,7 +70,7 @@ namespace System case CorElementType.U8: return (*(ulong*)pValue).ToString("X16", null); default: - Contract.Assert(false, "Invalid Object type in Format"); + Debug.Assert(false, "Invalid Object type in Format"); throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType")); } } @@ -106,7 +105,7 @@ namespace System return ((UInt64)(Int64)value).ToString("X16", null); // All unsigned types will be directly cast default: - Contract.Assert(false, "Invalid Object type in Format"); + Debug.Assert(false, "Invalid Object type in Format"); throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType")); } } @@ -157,7 +156,7 @@ namespace System String[] names = entry.Names; ulong[] values = entry.Values; - Contract.Assert(names.Length == values.Length); + Debug.Assert(names.Length == values.Length); int index = values.Length - 1; StringBuilder retval = new StringBuilder(); @@ -245,27 +244,23 @@ namespace System break; // All unsigned types will be directly cast default: - Contract.Assert(false, "Invalid Object type in ToUInt64"); + Debug.Assert(false, "Invalid Object type in ToUInt64"); throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType")); } return result; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern int InternalCompareTo(Object o1, Object o2); - [System.Security.SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern RuntimeType InternalGetUnderlyingType(RuntimeType enumType); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [System.Security.SuppressUnmanagedCodeSecurity] private static extern void GetEnumValuesAndNames(RuntimeTypeHandle enumType, ObjectHandleOnStack values, ObjectHandleOnStack names, bool getNames); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern Object InternalBoxEnum(RuntimeType enumType, long value); #endregion @@ -328,12 +323,28 @@ namespace System return m_innerException; default: - Contract.Assert(false, "Unknown EnumParseFailure: " + m_failure); + Debug.Assert(false, "Unknown EnumParseFailure: " + m_failure); return new ArgumentException(Environment.GetResourceString("Arg_EnumValueNotFound")); } } } + public static bool TryParse(Type enumType, String value, out Object result) + { + return TryParse(enumType, value, false, out result); + } + + public static bool TryParse(Type enumType, String value, bool ignoreCase, out Object result) + { + result = null; + EnumResult parseResult = new EnumResult(); + bool retValue; + + if (retValue = TryParseEnum(enumType, value, ignoreCase, ref parseResult)) + result = parseResult.parsedEnum; + return retValue; + } + public static bool TryParse(String value, out TEnum result) where TEnum : struct { return TryParse(value, false, out result); @@ -366,21 +377,35 @@ namespace System throw parseResult.GetEnumParseException(); } + public static TEnum Parse(String value) where TEnum : struct + { + return Parse(value, false); + } + + public static TEnum Parse(String value, bool ignoreCase) where TEnum : struct + { + EnumResult parseResult = new EnumResult() { canThrow = true }; + if (TryParseEnum(typeof(TEnum), value, ignoreCase, ref parseResult)) + return (TEnum)parseResult.parsedEnum; + else + throw parseResult.GetEnumParseException(); + } + private static bool TryParseEnum(Type enumType, String value, bool ignoreCase, ref EnumResult parseResult) { if (enumType == null) - throw new ArgumentNullException("enumType"); + throw new ArgumentNullException(nameof(enumType)); Contract.EndContractBlock(); RuntimeType rtType = enumType as RuntimeType; if (rtType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), nameof(enumType)); if (!enumType.IsEnum) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), nameof(enumType)); if (value == null) { - parseResult.SetFailure(ParseFailureKind.ArgumentNull, "value"); + parseResult.SetFailure(ParseFailureKind.ArgumentNull, nameof(value)); return false; } @@ -504,7 +529,7 @@ namespace System public static Type GetUnderlyingType(Type enumType) { if (enumType == null) - throw new ArgumentNullException("enumType"); + throw new ArgumentNullException(nameof(enumType)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -515,7 +540,7 @@ namespace System public static Array GetValues(Type enumType) { if (enumType == null) - throw new ArgumentNullException("enumType"); + throw new ArgumentNullException(nameof(enumType)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -532,7 +557,7 @@ namespace System public static String GetName(Type enumType, Object value) { if (enumType == null) - throw new ArgumentNullException("enumType"); + throw new ArgumentNullException(nameof(enumType)); Contract.EndContractBlock(); return enumType.GetEnumName(value); @@ -542,7 +567,7 @@ namespace System public static String[] GetNames(Type enumType) { if (enumType == null) - throw new ArgumentNullException("enumType"); + throw new ArgumentNullException(nameof(enumType)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -559,7 +584,7 @@ namespace System public static Object ToObject(Type enumType, Object value) { if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); Contract.EndContractBlock(); // Delegate rest of error checking to the other functions @@ -599,7 +624,7 @@ namespace System default: // All unsigned types will be directly cast - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnumBaseTypeOrEnum"), "value"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnumBaseTypeOrEnum"), nameof(value)); } } @@ -608,7 +633,7 @@ namespace System public static bool IsDefined(Type enumType, Object value) { if (enumType == null) - throw new ArgumentNullException("enumType"); + throw new ArgumentNullException(nameof(enumType)); Contract.EndContractBlock(); return enumType.IsEnumDefined(value); @@ -618,21 +643,21 @@ namespace System public static String Format(Type enumType, Object value, String format) { if (enumType == null) - throw new ArgumentNullException("enumType"); + throw new ArgumentNullException(nameof(enumType)); if (!enumType.IsEnum) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), nameof(enumType)); if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); if (format == null) - throw new ArgumentNullException("format"); + throw new ArgumentNullException(nameof(format)); Contract.EndContractBlock(); RuntimeType rtType = enumType as RuntimeType; if (rtType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), nameof(enumType)); // Check if both of them are of the same type Type valueType = value.GetType(); @@ -698,7 +723,6 @@ namespace System #endregion #region Private Methods - [System.Security.SecuritySafeCritical] internal unsafe Object GetValue() { fixed (void* pValue = &JitHelpers.GetPinningHelper(this).m_data) @@ -734,13 +758,12 @@ namespace System case CorElementType.U: return *(UIntPtr*)pValue; default: - Contract.Assert(false, "Invalid primitive type"); + Debug.Assert(false, "Invalid primitive type"); return null; } } } - [System.Security.SecuritySafeCritical] private unsafe ulong ToUInt64() { fixed (void* pValue = &JitHelpers.GetPinningHelper(this).m_data) @@ -787,32 +810,29 @@ namespace System return *(uint*)pValue; } default: - Contract.Assert(false, "Invalid primitive type"); + Debug.Assert(false, "Invalid primitive type"); return 0; } } } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern bool InternalHasFlag(Enum flags); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern CorElementType InternalGetCorElementType(); #endregion #region Object Overrides - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern override bool Equals(Object obj); - [System.Security.SecuritySafeCritical] public override unsafe int GetHashCode() { - // Avoid boxing by inlining GetValue() - // return GetValue().GetHashCode(); + // CONTRACT with the runtime: GetHashCode of enum types is implemented as GetHashCode of the underlying type. + // The runtime can bypass calls to Enum::GetHashCode and call the underlying type's GetHashCode directly + // to avoid boxing the enum. fixed (void* pValue = &JitHelpers.GetPinningHelper(this).m_data) { @@ -847,7 +867,7 @@ namespace System case CorElementType.U: return (*(UIntPtr*)pValue).GetHashCode(); default: - Contract.Assert(false, "Invalid primitive type"); + Debug.Assert(false, "Invalid primitive type"); return 0; } } @@ -876,7 +896,6 @@ namespace System #endregion #region IComparable - [System.Security.SecuritySafeCritical] // auto-generated public int CompareTo(Object target) { const int retIncompatibleMethodTables = 2; // indicates that the method tables did not match @@ -904,7 +923,7 @@ namespace System else { // assert valid return code (3) - Contract.Assert(ret == retInvalidEnumType, "Enum.InternalCompareTo return code was invalid"); + Debug.Assert(ret == retInvalidEnumType, "Enum.InternalCompareTo return code was invalid"); throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType")); } @@ -942,10 +961,9 @@ namespace System return ToString(); } - [System.Security.SecuritySafeCritical] public Boolean HasFlag(Enum flag) { if (flag == null) - throw new ArgumentNullException("flag"); + throw new ArgumentNullException(nameof(flag)); Contract.EndContractBlock(); if (!this.GetType().IsEquivalentTo(flag.GetType())) { @@ -1013,7 +1031,7 @@ namespace System return TypeCode.Char; } - Contract.Assert(false, "Unknown underlying type."); + Debug.Assert(false, "Unknown underlying type."); throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType")); } @@ -1109,155 +1127,145 @@ namespace System #endregion #region ToObject - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(true)] public static Object ToObject(Type enumType, sbyte value) { if (enumType == null) - throw new ArgumentNullException("enumType"); + throw new ArgumentNullException(nameof(enumType)); if (!enumType.IsEnum) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), nameof(enumType)); Contract.EndContractBlock(); RuntimeType rtType = enumType as RuntimeType; if (rtType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), nameof(enumType)); return InternalBoxEnum(rtType, value); } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public static Object ToObject(Type enumType, short value) { if (enumType == null) - throw new ArgumentNullException("enumType"); + throw new ArgumentNullException(nameof(enumType)); if (!enumType.IsEnum) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), nameof(enumType)); Contract.EndContractBlock(); RuntimeType rtType = enumType as RuntimeType; if (rtType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), nameof(enumType)); return InternalBoxEnum(rtType, value); } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public static Object ToObject(Type enumType, int value) { if (enumType == null) - throw new ArgumentNullException("enumType"); + throw new ArgumentNullException(nameof(enumType)); if (!enumType.IsEnum) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), nameof(enumType)); Contract.EndContractBlock(); RuntimeType rtType = enumType as RuntimeType; if (rtType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), nameof(enumType)); return InternalBoxEnum(rtType, value); } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public static Object ToObject(Type enumType, byte value) { if (enumType == null) - throw new ArgumentNullException("enumType"); + throw new ArgumentNullException(nameof(enumType)); if (!enumType.IsEnum) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), nameof(enumType)); Contract.EndContractBlock(); RuntimeType rtType = enumType as RuntimeType; if (rtType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), nameof(enumType)); return InternalBoxEnum(rtType, value); } - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(true)] public static Object ToObject(Type enumType, ushort value) { if (enumType == null) - throw new ArgumentNullException("enumType"); + throw new ArgumentNullException(nameof(enumType)); if (!enumType.IsEnum) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), nameof(enumType)); Contract.EndContractBlock(); RuntimeType rtType = enumType as RuntimeType; if (rtType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), nameof(enumType)); return InternalBoxEnum(rtType, value); } - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(true)] public static Object ToObject(Type enumType, uint value) { if (enumType == null) - throw new ArgumentNullException("enumType"); + throw new ArgumentNullException(nameof(enumType)); if (!enumType.IsEnum) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), nameof(enumType)); Contract.EndContractBlock(); RuntimeType rtType = enumType as RuntimeType; if (rtType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), nameof(enumType)); return InternalBoxEnum(rtType, value); } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public static Object ToObject(Type enumType, long value) { if (enumType == null) - throw new ArgumentNullException("enumType"); + throw new ArgumentNullException(nameof(enumType)); if (!enumType.IsEnum) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), nameof(enumType)); Contract.EndContractBlock(); RuntimeType rtType = enumType as RuntimeType; if (rtType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), nameof(enumType)); return InternalBoxEnum(rtType, value); } - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(true)] public static Object ToObject(Type enumType, ulong value) { if (enumType == null) - throw new ArgumentNullException("enumType"); + throw new ArgumentNullException(nameof(enumType)); if (!enumType.IsEnum) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), nameof(enumType)); Contract.EndContractBlock(); RuntimeType rtType = enumType as RuntimeType; if (rtType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), nameof(enumType)); return InternalBoxEnum(rtType, unchecked((long)value)); } - [System.Security.SecuritySafeCritical] // auto-generated private static Object ToObject(Type enumType, char value) { if (enumType == null) - throw new ArgumentNullException("enumType"); + throw new ArgumentNullException(nameof(enumType)); if (!enumType.IsEnum) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), nameof(enumType)); Contract.EndContractBlock(); RuntimeType rtType = enumType as RuntimeType; if (rtType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), nameof(enumType)); return InternalBoxEnum(rtType, value); } - [System.Security.SecuritySafeCritical] // auto-generated private static Object ToObject(Type enumType, bool value) { if (enumType == null) - throw new ArgumentNullException("enumType"); + throw new ArgumentNullException(nameof(enumType)); if (!enumType.IsEnum) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), nameof(enumType)); Contract.EndContractBlock(); RuntimeType rtType = enumType as RuntimeType; if (rtType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), nameof(enumType)); return InternalBoxEnum(rtType, value ? 1 : 0); } #endregion diff --git a/src/mscorlib/src/System/Environment.cs b/src/mscorlib/src/System/Environment.cs index 5ee30bb..835219a 100644 --- a/src/mscorlib/src/System/Environment.cs +++ b/src/mscorlib/src/System/Environment.cs @@ -32,17 +32,16 @@ namespace System { using System.Diagnostics.Contracts; [ComVisible(true)] - public enum EnvironmentVariableTarget { + public enum EnvironmentVariableTarget + { Process = 0, -#if FEATURE_WIN32_REGISTRY User = 1, Machine = 2, -#endif } [ComVisible(true)] - public static class Environment { - + public static partial class Environment + { // Assume the following constants include the terminating '\0' - use <, not <= const int MaxEnvVariableValueLength = 32767; // maximum length for environment variable name and value // System environment variables are stored in the registry, and have @@ -89,11 +88,10 @@ namespace System { } } - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal String GetResourceString(String key) { if (key == null || key.Length == 0) { - Contract.Assert(false, "Environment::GetResourceString with null or empty key. Bug in caller, or weird recursive loading problem?"); + Debug.Assert(false, "Environment::GetResourceString with null or empty key. Bug in caller, or weird recursive loading problem?"); return "[Resource lookup failed - null or empty resource name]"; } @@ -125,11 +123,6 @@ namespace System { return userData.m_retVal; } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif private void GetResourceStringCode(Object userDataIn) { GetResourceStringUserData userData = (GetResourceStringUserData) userDataIn; @@ -189,14 +182,11 @@ namespace System { String s = rh.SystemResMgr.GetString(key, null); rh.currentlyLoading.RemoveAt(rh.currentlyLoading.Count - 1); // Pop - Contract.Assert(s!=null, "Managed resource string lookup failed. Was your resource name misspelled? Did you rebuild mscorlib after adding a resource to resources.txt? Debug this w/ cordbg and bug whoever owns the code that called Environment.GetResourceString. Resource name was: \""+key+"\""); + Debug.Assert(s!=null, "Managed resource string lookup failed. Was your resource name misspelled? Did you rebuild mscorlib after adding a resource to resources.txt? Debug this w/ cordbg and bug whoever owns the code that called Environment.GetResourceString. Resource name was: \""+key+"\""); userData.m_retVal = s; } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif [PrePrepareMethod] private void GetResourceStringBackoutCode(Object userDataIn, bool exceptionThrown) { @@ -248,32 +238,24 @@ namespace System { **Exceptions: None ==============================================================================*/ public static extern int TickCount { - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] get; } // Terminates this process with the given exit code. - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern void _Exit(int exitCode); - [System.Security.SecuritySafeCritical] // auto-generated -#pragma warning disable 618 - [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] -#pragma warning restore 618 public static void Exit(int exitCode) { _Exit(exitCode); } public static extern int ExitCode { - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] get; - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] set; } @@ -281,11 +263,9 @@ namespace System { // Note: The CLR's Watson bucketization code looks at the caller of the FCALL method // to assign blame for crashes. Don't mess with this, such as by making it call // another managed helper method, unless you consult with some CLR Watson experts. - [System.Security.SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern void FailFast(String message); - [System.Security.SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void FailFast(String message, uint exitCode); @@ -302,44 +282,9 @@ namespace System { // if the exception object is preallocated, the runtime will use the callsite's // IP for bucketing. If the exception object is not preallocated, it will use the bucket // details contained in the object (if any). - [System.Security.SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern void FailFast(String message, Exception exception); -#if !FEATURE_CORECLR - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SecurityCritical] // Our security team doesn't yet allow safe-critical P/Invoke methods. - [SuppressUnmanagedCodeSecurity] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - internal static extern void TriggerCodeContractFailure(ContractFailureKind failureKind, String message, String condition, String exceptionAsString); - - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SecurityCritical] // Our security team doesn't yet allow safe-critical P/Invoke methods. - [SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool GetIsCLRHosted(); - - internal static bool IsCLRHosted { - [SecuritySafeCritical] - get { return GetIsCLRHosted(); } - } - - public static String CommandLine { - [System.Security.SecuritySafeCritical] // auto-generated - get { - new EnvironmentPermission(EnvironmentPermissionAccess.Read, "Path").Demand(); - - String commandLine = null; - GetCommandLine(JitHelpers.GetStringHandleOnStack(ref commandLine)); - return commandLine; - } - } - - [System.Security.SecurityCritical] // auto-generated - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] - private static extern void GetCommandLine(StringHandleOnStack retString); -#endif // !FEATURE_CORECLR - /*===============================CurrentDirectory=============================== **Action: Provides a getter and setter for the current directory. The original ** current directory is the one from which the process was started. @@ -353,9 +298,6 @@ namespace System { return Directory.GetCurrentDirectory(); } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif set { Directory.SetCurrentDirectory(value); } @@ -363,22 +305,12 @@ namespace System { // Returns the system directory (ie, C:\WinNT\System32). public static String SystemDirectory { -#if FEATURE_CORECLR - [System.Security.SecurityCritical] -#else - [System.Security.SecuritySafeCritical] // auto-generated -#endif get { StringBuilder sb = new StringBuilder(Path.MaxPath); int r = Win32Native.GetSystemDirectory(sb, Path.MaxPath); - Contract.Assert(r < Path.MaxPath, "r < Path.MaxPath"); + Debug.Assert(r < Path.MaxPath, "r < Path.MaxPath"); if (r==0) __Error.WinIOError(); String path = sb.ToString(); - -#if !FEATURE_CORECLR - // Do security check - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, path).Demand(); -#endif return path; } @@ -387,11 +319,10 @@ namespace System { // Returns the windows directory (ie, C:\WinNT). // Used by NLS+ custom culures only at the moment. internal static String InternalWindowsDirectory { - [System.Security.SecurityCritical] // auto-generated get { StringBuilder sb = new StringBuilder(Path.MaxPath); int r = Win32Native.GetWindowsDirectory(sb, Path.MaxPath); - Contract.Assert(r < Path.MaxPath, "r < Path.MaxPath"); + Debug.Assert(r < Path.MaxPath, "r < Path.MaxPath"); if (r==0) __Error.WinIOError(); String path = sb.ToString(); @@ -399,11 +330,10 @@ namespace System { } } - [System.Security.SecuritySafeCritical] // auto-generated public static String ExpandEnvironmentVariables(String name) { if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); Contract.EndContractBlock(); if (name.Length == 0) { @@ -442,63 +372,6 @@ namespace System { int size; -#if !FEATURE_CORECLR - bool isFullTrust = CodeAccessSecurityEngine.QuickCheckForAllDemands(); - - // Do a security check to guarantee we can read each of the - // individual environment variables requested here. - String[] varArray = name.Split(new char[] {'%'}); - StringBuilder vars = isFullTrust ? null : new StringBuilder(); - - bool fJustExpanded = false; // to accommodate expansion alg. - - for(int i=1; i currentSize) { - currentSize = size; - blob.Capacity = currentSize; - blob.Length = 0; - size = Win32Native.ExpandEnvironmentStrings(envVar, blob, currentSize); - if (size == 0) - Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); - } - - if (!isFullTrust) { - String temp = blob.ToString(); - fJustExpanded = (temp != envVar); - if (fJustExpanded) { // We expanded successfully, we need to do String comparison here - // since %FOO% can become %FOOD - vars.Append(varArray[i]); - vars.Append(';'); - } - } - } - - if (!isFullTrust) - new EnvironmentPermission(EnvironmentPermissionAccess.Read, vars.ToString()).Demand(); -#endif // !FEATURE_CORECLR - blob.Length = 0; size = Win32Native.ExpandEnvironmentStrings(name, blob, currentSize); if (size == 0) @@ -519,7 +392,6 @@ namespace System { } public static String MachineName { - [System.Security.SecuritySafeCritical] // auto-generated get { // UWP Debug scenarios @@ -531,9 +403,6 @@ namespace System { // In future release of operating systems, you might be able to rename a machine without // rebooting. Therefore, don't cache this machine name. -#if !FEATURE_CORECLR - new EnvironmentPermission(EnvironmentPermissionAccess.Read, "COMPUTERNAME").Demand(); -#endif StringBuilder buf = new StringBuilder(MaxMachineNameLength); int len = MaxMachineNameLength; if (Win32Native.GetComputerName(buf, ref len) == 0) @@ -542,20 +411,17 @@ namespace System { } } - [SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern Int32 GetProcessorCount(); public static int ProcessorCount { - [System.Security.SecuritySafeCritical] // auto-generated get { return GetProcessorCount(); } } public static int SystemPageSize { - [System.Security.SecuritySafeCritical] // auto-generated get { (new EnvironmentPermission(PermissionState.Unrestricted)).Demand(); Win32Native.SYSTEM_INFO info = new Win32Native.SYSTEM_INFO(); @@ -571,11 +437,9 @@ namespace System { **Arguments: None **Exceptions: None. ==============================================================================*/ - [System.Security.SecuritySafeCritical] // auto-generated public static String[] GetCommandLineArgs() { new EnvironmentPermission(EnvironmentPermissionAccess.Read, "Path").Demand(); -#if FEATURE_CORECLR /* * There are multiple entry points to a hosted app. * The host could use ::ExecuteAssembly() or ::CreateDelegate option @@ -591,145 +455,37 @@ namespace System { */ if(s_CommandLineArgs != null) return (string[])s_CommandLineArgs.Clone(); -#endif + return GetCommandLineArgsNative(); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern String[] GetCommandLineArgsNative(); -#if !FEATURE_CORECLR - // We need to keep this Fcall since it is used in AppDomain.cs. - // If we call GetEnvironmentVariable from AppDomain.cs, we will use StringBuilder class. - // That has side effect to change the ApartmentState of the calling Thread to MTA. - // So runtime can't change the ApartmentState of calling thread any more. - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern String nativeGetEnvironmentVariable(String variable); -#endif //!FEATURE_CORECLR - -#if FEATURE_CORECLR private static string[] s_CommandLineArgs = null; private static void SetCommandLineArgs(string[] cmdLineArgs) { s_CommandLineArgs = cmdLineArgs; } -#endif - - /*============================GetEnvironmentVariable============================ - **Action: - **Returns: - **Arguments: - **Exceptions: - ==============================================================================*/ - [System.Security.SecuritySafeCritical] // auto-generated - public static String GetEnvironmentVariable(String variable) - { - if (variable == null) - throw new ArgumentNullException("variable"); - Contract.EndContractBlock(); - - if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode()) { - // Environment variable accessors are not approved modern API. - // Behave as if the variable was not found in this case. - return null; - } - -#if !FEATURE_CORECLR - (new EnvironmentPermission(EnvironmentPermissionAccess.Read, variable)).Demand(); -#endif //!FEATURE_CORECLR - - StringBuilder blob = StringBuilderCache.Acquire(128); // A somewhat reasonable default size - int requiredSize = Win32Native.GetEnvironmentVariable(variable, blob, blob.Capacity); - - if (requiredSize == 0) { // GetEnvironmentVariable failed - if (Marshal.GetLastWin32Error() == Win32Native.ERROR_ENVVAR_NOT_FOUND) { - StringBuilderCache.Release(blob); - return null; - } - } - - while (requiredSize > blob.Capacity) { // need to retry since the environment variable might be changed - blob.Capacity = requiredSize; - blob.Length = 0; - requiredSize = Win32Native.GetEnvironmentVariable(variable, blob, blob.Capacity); - } - return StringBuilderCache.GetStringAndRelease(blob); - } - [System.Security.SecuritySafeCritical] // auto-generated - public static string GetEnvironmentVariable( string variable, EnvironmentVariableTarget target) - { - if (variable == null) - { - throw new ArgumentNullException("variable"); - } - Contract.EndContractBlock(); - - if (target == EnvironmentVariableTarget.Process) - { - return GetEnvironmentVariable(variable); - } - -#if FEATURE_WIN32_REGISTRY - (new EnvironmentPermission(PermissionState.Unrestricted)).Demand(); - - if( target == EnvironmentVariableTarget.Machine) { - using (RegistryKey environmentKey = - Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\Session Manager\Environment", false)) { - - Contract.Assert(environmentKey != null, @"HKLM\System\CurrentControlSet\Control\Session Manager\Environment is missing!"); - if (environmentKey == null) { - return null; - } - - string value = environmentKey.GetValue(variable) as string; - return value; - } - } - else if( target == EnvironmentVariableTarget.User) { - using (RegistryKey environmentKey = - Registry.CurrentUser.OpenSubKey("Environment", false)) { - - Contract.Assert(environmentKey != null, @"HKCU\Environment is missing!"); - if (environmentKey == null) { - return null; - } - - string value = environmentKey.GetValue(variable) as string; - return value; - } - } - else -#endif // FEATURE_WIN32_REGISTRY - { - throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)target)); - } - } - - /*===========================GetEnvironmentVariables============================ - **Action: Returns an IDictionary containing all enviroment variables and their values. - **Returns: An IDictionary containing all environment variables and their values. - **Arguments: None. - **Exceptions: None. - ==============================================================================*/ - [System.Security.SecurityCritical] // auto-generated private unsafe static char[] GetEnvironmentCharArray() { char[] block = null; // Make sure pStrings is not leaked with async exceptions RuntimeHelpers.PrepareConstrainedRegions(); - try { + try + { } - finally { - char * pStrings = null; + finally + { + char* pStrings = null; try { pStrings = Win32Native.GetEnvironmentStrings(); - if (pStrings == null) { + if (pStrings == null) + { throw new OutOfMemoryException(); } @@ -739,7 +495,7 @@ namespace System { // CreateProcess page (null-terminated array of null-terminated strings). // Search for terminating \0\0 (two unicode \0's). - char * p = pStrings; + char* p = pStrings; while (!(*p == '\0' && *(p + 1) == '\0')) p++; @@ -747,7 +503,7 @@ namespace System { block = new char[len]; fixed (char* pBlock = block) - String.wstrcpy(pBlock, pStrings, len); + string.wstrcpy(pBlock, pStrings, len); } finally { @@ -759,275 +515,12 @@ namespace System { return block; } - [System.Security.SecuritySafeCritical] // auto-generated - public static IDictionary GetEnvironmentVariables() - { - if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode()) { - // Environment variable accessors are not approved modern API. - // Behave as if no environment variables are defined in this case. - return new Hashtable(0); - } - -#if !FEATURE_CORECLR - bool isFullTrust = CodeAccessSecurityEngine.QuickCheckForAllDemands(); - StringBuilder vars = isFullTrust ? null : new StringBuilder(); - bool first = true; -#endif - - char[] block = GetEnvironmentCharArray(); - - Hashtable table = new Hashtable(20); - - // Copy strings out, parsing into pairs and inserting into the table. - // The first few environment variable entries start with an '='! - // The current working directory of every drive (except for those drives - // you haven't cd'ed into in your DOS window) are stored in the - // environment block (as =C:=pwd) and the program's exit code is - // as well (=ExitCode=00000000) Skip all that start with =. - // Read docs about Environment Blocks on MSDN's CreateProcess page. - - // Format for GetEnvironmentStrings is: - // (=HiddenVar=value\0 | Variable=value\0)* \0 - // See the description of Environment Blocks in MSDN's - // CreateProcess page (null-terminated array of null-terminated strings). - // Note the =HiddenVar's aren't always at the beginning. - - for(int i=0; i= MaxEnvVariableValueLength) { - throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarValue")); - } - } - - if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode()) { - // Environment variable accessors are not approved modern API. - // so we throw PlatformNotSupportedException. - throw new PlatformNotSupportedException(); - } - - if(!Win32Native.SetEnvironmentVariable(variable, value)) { - int errorCode = Marshal.GetLastWin32Error(); - - // Allow user to try to clear a environment variable - if( errorCode == Win32Native.ERROR_ENVVAR_NOT_FOUND) { - return; - } - - // The error message from Win32 is "The filename or extension is too long", - // which is not accurate. - if( errorCode == Win32Native.ERROR_FILENAME_EXCED_RANGE) { - throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarValue")); - } - - throw new ArgumentException(Win32Native.GetMessage(errorCode)); - } - } - - private static void CheckEnvironmentVariableName(string variable) { - if (variable == null) { - throw new ArgumentNullException("variable"); - } - - if( variable.Length == 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_StringZeroLength"), "variable"); - } - - if( variable[0] == '\0') { - throw new ArgumentException(Environment.GetResourceString("Argument_StringFirstCharIsZero"), "variable"); - } - - // Make sure the environment variable name isn't longer than the - // max limit on environment variable values. (MSDN is ambiguous - // on whether this check is necessary.) - if( variable.Length >= MaxEnvVariableValueLength ) { - throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarValue")); - } - - if( variable.IndexOf('=') != -1) { - throw new ArgumentException(Environment.GetResourceString("Argument_IllegalEnvVarName")); - } - Contract.EndContractBlock(); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public static void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target) { - if( target == EnvironmentVariableTarget.Process) { - SetEnvironmentVariable(variable, value); - return; - } - - CheckEnvironmentVariableName(variable); - - // System-wide environment variables stored in the registry are - // limited to 1024 chars for the environment variable name. - if (variable.Length >= MaxSystemEnvVariableLength) { - throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarName")); - } - - new EnvironmentPermission(PermissionState.Unrestricted).Demand(); - // explicitly null out value if is the empty string. - if (String.IsNullOrEmpty(value) || value[0] == '\0') { - value = null; - } -#if FEATURE_WIN32_REGISTRY - if( target == EnvironmentVariableTarget.Machine) { - using (RegistryKey environmentKey = - Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\Session Manager\Environment", true)) { - - Contract.Assert(environmentKey != null, @"HKLM\System\CurrentControlSet\Control\Session Manager\Environment is missing!"); - if (environmentKey != null) { - if (value == null) - environmentKey.DeleteValue(variable, false); - else - environmentKey.SetValue(variable, value); - } - } - } - else if( target == EnvironmentVariableTarget.User) { - // User-wide environment variables stored in the registry are - // limited to 255 chars for the environment variable name. - if (variable.Length >= MaxUserEnvVariableLength) { - throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarValue")); - } - using (RegistryKey environmentKey = - Registry.CurrentUser.OpenSubKey("Environment", true)) { - Contract.Assert(environmentKey != null, @"HKCU\Environment is missing!"); - if (environmentKey != null) { - if (value == null) - environmentKey.DeleteValue(variable, false); - else - environmentKey.SetValue(variable, value); - } - } - } - else - { - throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)target)); - } - // send a WM_SETTINGCHANGE message to all windows - IntPtr r = Win32Native.SendMessageTimeout(new IntPtr(Win32Native.HWND_BROADCAST), Win32Native.WM_SETTINGCHANGE, IntPtr.Zero, "Environment", 0, 1000, IntPtr.Zero); - - if (r == IntPtr.Zero) BCLDebug.Assert(false, "SetEnvironmentVariable failed: " + Marshal.GetLastWin32Error()); - -#else // FEATURE_WIN32_REGISTRY - throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)target)); -#endif - } - - /*===============================GetLogicalDrives=============================== **Action: Retrieves the names of the logical drives on this machine in the form "C:\". **Arguments: None. **Exceptions: IOException. **Permissions: SystemInfo Permission. ==============================================================================*/ - [System.Security.SecuritySafeCritical] // auto-generated public static String[] GetLogicalDrives() { new EnvironmentPermission(PermissionState.Unrestricted).Demand(); @@ -1097,12 +590,10 @@ namespace System { **Arguments: **Exceptions: ==============================================================================*/ - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] private static extern long GetWorkingSet(); public static long WorkingSet { - [System.Security.SecuritySafeCritical] // auto-generated get { new EnvironmentPermission(PermissionState.Unrestricted).Demand(); return GetWorkingSet(); @@ -1117,7 +608,6 @@ namespace System { **Exceptions: ==============================================================================*/ public static OperatingSystem OSVersion { - [System.Security.SecuritySafeCritical] // auto-generated get { Contract.Ensures(Contract.Result() != null); @@ -1141,7 +631,7 @@ namespace System { Version v = new Version(osvi.MajorVersion, osvi.MinorVersion, osvi.BuildNumber, (osviEx.ServicePackMajor << 16) |osviEx.ServicePackMinor); m_os = new OperatingSystem(id, v, osvi.CSDVersion); } - Contract.Assert(m_os != null, "m_os != null"); + Debug.Assert(m_os != null, "m_os != null"); return m_os; } } @@ -1186,7 +676,6 @@ namespace System { // Does the current version of Windows have Windows Runtime suppport? internal static bool IsWinRTSupported { - [SecuritySafeCritical] get { if (!s_CheckedWinRT) { s_WinRTSupported = WinRTSupported(); @@ -1197,7 +686,6 @@ namespace System { } } - [SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] @@ -1206,11 +694,9 @@ namespace System { #endif // FEATURE_CORESYSTEM - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool GetVersion(Microsoft.Win32.Win32Native.OSVERSIONINFO osVer); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool GetVersionEx(Microsoft.Win32.Win32Native.OSVERSIONINFOEX osVer); @@ -1222,7 +708,6 @@ namespace System { **Exceptions: ==============================================================================*/ public static String StackTrace { - [System.Security.SecuritySafeCritical] // auto-generated get { Contract.Ensures(Contract.Result() != null); @@ -1231,9 +716,6 @@ namespace System { } } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif internal static String GetStackTrace(Exception e, bool needFileInfo) { // Note: Setting needFileInfo to true will start up COM and set our @@ -1250,7 +732,6 @@ namespace System { return st.ToString( System.Diagnostics.StackTrace.TraceFormat.Normal ); } - [System.Security.SecuritySafeCritical] // auto-generated private static void InitResourceHelper() { // Only the default AppDomain should have a ResourceHelper. All calls to // GetResourceString from any AppDomain delegate to GetResourceStringLocal @@ -1275,20 +756,13 @@ namespace System { } } -#if !FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal extern static String GetResourceFromDefault(String key); -#endif - // Looks up the resource string value for key. // // if you change this method's signature then you must change the code that calls it // in excep.cpp and probably you will have to visit mscorlib.h to add the new signature // as well as metasig.h to create the new signature type -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif + // NoInlining causes the caller and callee to not be inlined in mscorlib as it is an assumption of StackCrawlMark use + [MethodImpl(MethodImplOptions.NoInlining)] internal static String GetResourceStringLocal(String key) { if (m_resHelper == null) InitResourceHelper(); @@ -1296,30 +770,74 @@ namespace System { return m_resHelper.GetResourceString(key); } - [System.Security.SecuritySafeCritical] // auto-generated internal static String GetResourceString(String key) { -#if FEATURE_CORECLR return GetResourceStringLocal(key); -#else - return GetResourceFromDefault(key); -#endif //FEATURE_CORECLR } - [System.Security.SecuritySafeCritical] // auto-generated - internal static String GetResourceString(String key, params Object[] values) { - String s = GetResourceString(key); - return String.Format(CultureInfo.CurrentCulture, s, values); + // The reason the following overloads exist are to reduce code bloat. + // Since GetResourceString is basically only called when exceptions are + // thrown, we want the code size to be as small as possible. + // Using the params object[] overload works against this since the + // initialization of the array is done inline in the caller at the IL + // level. So we have overloads that simply wrap the params one, and + // the methods they call through to are tagged as NoInlining. + // In mscorlib NoInlining causes the caller and callee to not be inlined + // as it is an assumption of StackCrawlMark use so it is not added + // directly to these methods, but to the ones they call. + // That way they do not bloat either the IL or the generated asm. + + internal static string GetResourceString(string key, object val0) + { + return GetResourceStringFormatted(key, new object[] { val0 }); } - //The following two internal methods are not used anywhere within the framework, + internal static string GetResourceString(string key, object val0, object val1) + { + return GetResourceStringFormatted(key, new object[] { val0, val1 }); + } + + internal static string GetResourceString(string key, object val0, object val1, object val2) + { + return GetResourceStringFormatted(key, new object[] { val0, val1, val2 }); + } + + internal static string GetResourceString(string key, object val0, object val1, object val2, object val3) + { + return GetResourceStringFormatted(key, new object[] { val0, val1, val2, val3 }); + } + + internal static string GetResourceString(string key, object val0, object val1, object val2, object val3, object val4) + { + return GetResourceStringFormatted(key, new object[] { val0, val1, val2, val3, val4 }); + } + + internal static string GetResourceString(string key, object val0, object val1, object val2, object val3, object val4, object val5) + { + return GetResourceStringFormatted(key, new object[] { val0, val1, val2, val3, val4, val5 }); + } + + internal static String GetResourceString(string key, params object[] values) + { + return GetResourceStringFormatted(key, values); + } + + // NoInlining causes the caller and callee to not be inlined in mscorlib as it is an assumption of StackCrawlMark use + [MethodImpl(MethodImplOptions.NoInlining)] + private static String GetResourceStringFormatted(string key, params object[] values) + { + string rs = GetResourceString(key); + return String.Format(CultureInfo.CurrentCulture, rs, values); + } + + // The following two internal methods are not used anywhere within the framework, // but are being kept around as external platforms built on top of us have taken // dependency by using private reflection on them for getting system resource strings - internal static String GetRuntimeResourceString(String key) { + private static String GetRuntimeResourceString(String key) { return GetResourceString(key); } - internal static String GetRuntimeResourceString(String key, params Object[] values) { - return GetResourceString(key,values); + private static String GetRuntimeResourceString(String key, params Object[] values) { + return GetResourceStringFormatted(key,values); } public static bool Is64BitProcess { @@ -1333,7 +851,6 @@ namespace System { } public static bool Is64BitOperatingSystem { - [System.Security.SecuritySafeCritical] get { #if BIT64 // 64-bit programs run only on 64-bit @@ -1348,20 +865,11 @@ namespace System { } public static extern bool HasShutdownStarted { - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] get; } -#if !FEATURE_CORECLR - // This is the temporary Whidbey stub for compatibility flags - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [System.Security.SecurityCritical] - internal static extern bool GetCompatibilityFlag(CompatibilityFlag flag); -#endif //!FEATURE_CORECLR - public static string UserName { - [System.Security.SecuritySafeCritical] // auto-generated get { new EnvironmentPermission(EnvironmentPermissionAccess.Read,"UserName").Demand(); @@ -1375,40 +883,13 @@ namespace System { } } - // Note that this is a handle to a process window station, but it does - // not need to be closed. CloseWindowStation would ignore this handle. - // We also do handle equality checking as well. This isn't a great fit - // for SafeHandle. We don't gain anything by using SafeHandle here. -#if !FEATURE_CORECLR - private static volatile IntPtr processWinStation; // Doesn't need to be initialized as they're zero-init. - private static volatile bool isUserNonInteractive; -#endif - - public static bool UserInteractive { - [System.Security.SecuritySafeCritical] // auto-generated + public static bool UserInteractive + { get { -#if !FEATURE_CORECLR - IntPtr hwinsta = Win32Native.GetProcessWindowStation(); - if (hwinsta != IntPtr.Zero && processWinStation != hwinsta) { - int lengthNeeded = 0; - Win32Native.USEROBJECTFLAGS flags = new Win32Native.USEROBJECTFLAGS(); - if (Win32Native.GetUserObjectInformation(hwinsta, Win32Native.UOI_FLAGS, flags, Marshal.SizeOf(flags),ref lengthNeeded)) { - if ((flags.dwFlags & Win32Native.WSF_VISIBLE) == 0) { - isUserNonInteractive = true; - } - } - processWinStation = hwinsta; - } - - // The logic is reversed to avoid static initialization to true - return !isUserNonInteractive; -#else return true; -#endif } } - [System.Security.SecuritySafeCritical] // auto-generated public static string GetFolderPath(SpecialFolder folder) { if (!Enum.IsDefined(typeof(SpecialFolder), folder)) throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)folder)); @@ -1417,7 +898,6 @@ namespace System { return InternalGetFolderPath(folder, SpecialFolderOption.None); } - [System.Security.SecuritySafeCritical] // auto-generated public static string GetFolderPath(SpecialFolder folder, SpecialFolderOption option) { if (!Enum.IsDefined(typeof(SpecialFolder),folder)) throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)folder)); @@ -1428,13 +908,11 @@ namespace System { return InternalGetFolderPath(folder, option); } - [System.Security.SecurityCritical] internal static string UnsafeGetFolderPath(SpecialFolder folder) { return InternalGetFolderPath(folder, SpecialFolderOption.None, suppressSecurityChecks: true); } - [System.Security.SecurityCritical] private static string InternalGetFolderPath(SpecialFolder folder, SpecialFolderOption option, bool suppressSecurityChecks = false) { #if FEATURE_CORESYSTEM @@ -1455,13 +933,6 @@ namespace System { throw new PlatformNotSupportedException(); } #else // FEATURE_CORESYSTEM -#if !FEATURE_CORECLR - if (option == SpecialFolderOption.Create && !suppressSecurityChecks) { - FileIOPermission createPermission = new FileIOPermission(PermissionState.None); - createPermission.AllFiles = FileIOPermissionAccess.Write; - createPermission.Demand(); - } -#endif StringBuilder sb = new StringBuilder(Path.MaxPath); int hresult = Win32Native.SHGetFolderPath(IntPtr.Zero, /* hwndOwner: [in] Reserved */ @@ -1499,14 +970,12 @@ namespace System { // On CoreCLR we can check with the host if we're not trying to use any special options. // Otherwise, we need to do a full demand since hosts aren't expecting to handle requests to // create special folders. -#if FEATURE_CORECLR if (option == SpecialFolderOption.None) { FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, s); state.EnsureState(); } else -#endif // FEATURE_CORECLR { new FileIOPermission(FileIOPermissionAccess.PathDiscovery, s).Demand(); } @@ -1517,7 +986,6 @@ namespace System { public static string UserDomainName { - [System.Security.SecuritySafeCritical] // auto-generated get { new EnvironmentPermission(EnvironmentPermissionAccess.Read,"UserDomain").Demand(); @@ -1650,7 +1118,7 @@ namespace System { // // "MyDocuments" is a better name than "Personal" // - MyDocuments = Win32Native.CSIDL_PERSONAL, + MyDocuments = Win32Native.CSIDL_PERSONAL, // // Represents the program files folder. // @@ -1658,101 +1126,7 @@ namespace System { // // Represents the folder for components that are shared across applications. // - CommonProgramFiles = Win32Native.CSIDL_PROGRAM_FILES_COMMON, -#if !FEATURE_CORECLR - // - // \Start Menu\Programs\Administrative Tools - // - AdminTools = Win32Native.CSIDL_ADMINTOOLS, - // - // USERPROFILE\Local Settings\Application Data\Microsoft\CD Burning - // - CDBurning = Win32Native.CSIDL_CDBURN_AREA, - // - // All Users\Start Menu\Programs\Administrative Tools - // - CommonAdminTools = Win32Native.CSIDL_COMMON_ADMINTOOLS, - // - // All Users\Documents - // - CommonDocuments = Win32Native.CSIDL_COMMON_DOCUMENTS, - // - // All Users\My Music - // - CommonMusic = Win32Native.CSIDL_COMMON_MUSIC, - // - // Links to All Users OEM specific apps - // - CommonOemLinks = Win32Native.CSIDL_COMMON_OEM_LINKS, - // - // All Users\My Pictures - // - CommonPictures = Win32Native.CSIDL_COMMON_PICTURES, - // - // All Users\Start Menu - // - CommonStartMenu = Win32Native.CSIDL_COMMON_STARTMENU, - // - // All Users\Start Menu\Programs - // - CommonPrograms = Win32Native.CSIDL_COMMON_PROGRAMS, - // - // All Users\Startup - // - CommonStartup = Win32Native.CSIDL_COMMON_STARTUP, - // - // All Users\Desktop - // - CommonDesktopDirectory = Win32Native.CSIDL_COMMON_DESKTOPDIRECTORY, - // - // All Users\Templates - // - CommonTemplates = Win32Native.CSIDL_COMMON_TEMPLATES, - // - // All Users\My Video - // - CommonVideos = Win32Native.CSIDL_COMMON_VIDEO, - // - // windows\fonts - // - Fonts = Win32Native.CSIDL_FONTS, - // - // %APPDATA%\Microsoft\Windows\Network Shortcuts - // - NetworkShortcuts = Win32Native.CSIDL_NETHOOD, - // - // %APPDATA%\Microsoft\Windows\Printer Shortcuts - // - PrinterShortcuts = Win32Native.CSIDL_PRINTHOOD, - // - // USERPROFILE - // - UserProfile = Win32Native.CSIDL_PROFILE, - // - // x86 Program Files\Common on RISC - // - CommonProgramFilesX86 = Win32Native.CSIDL_PROGRAM_FILES_COMMONX86, - // - // x86 C:\Program Files on RISC - // - ProgramFilesX86 = Win32Native.CSIDL_PROGRAM_FILESX86, - // - // Resource Directory - // - Resources = Win32Native.CSIDL_RESOURCES, - // - // Localized Resource Directory - // - LocalizedResources = Win32Native.CSIDL_RESOURCES_LOCALIZED, - // - // %windir%\System32 or %windir%\syswow64 - // - SystemX86 = Win32Native.CSIDL_SYSTEMX86, - // - // GetWindowsDirectory() - // - Windows = Win32Native.CSIDL_WINDOWS, -#endif // !FEATURE_CORECLR + CommonProgramFiles = Win32Native.CSIDL_PROGRAM_FILES_COMMON, } public static int CurrentManagedThreadId @@ -1764,5 +1138,367 @@ namespace System { } } + internal static extern int CurrentProcessorNumber + { + [MethodImplAttribute(MethodImplOptions.InternalCall)] + get; + } + + public static string GetEnvironmentVariable(string variable) + { + if (variable == null) + { + throw new ArgumentNullException(nameof(variable)); + } + + // separated from the EnvironmentVariableTarget overload to help with tree shaking in common case + return GetEnvironmentVariableCore(variable); + } + + public static string GetEnvironmentVariable(string variable, EnvironmentVariableTarget target) + { + if (variable == null) + { + throw new ArgumentNullException(nameof(variable)); + } + + ValidateTarget(target); + + return GetEnvironmentVariableCore(variable, target); + } + + public static IDictionary GetEnvironmentVariables() + { + // separated from the EnvironmentVariableTarget overload to help with tree shaking in common case + return GetEnvironmentVariablesCore(); + } + + public static IDictionary GetEnvironmentVariables(EnvironmentVariableTarget target) + { + ValidateTarget(target); + + return GetEnvironmentVariablesCore(target); + } + + public static void SetEnvironmentVariable(string variable, string value) + { + ValidateVariableAndValue(variable, ref value); + + // separated from the EnvironmentVariableTarget overload to help with tree shaking in common case + SetEnvironmentVariableCore(variable, value); + } + + public static void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target) + { + ValidateVariableAndValue(variable, ref value); + ValidateTarget(target); + + SetEnvironmentVariableCore(variable, value, target); + } + + private static void ValidateVariableAndValue(string variable, ref string value) + { + const int MaxEnvVariableValueLength = 32767; + + if (variable == null) + { + throw new ArgumentNullException(nameof(variable)); + } + if (variable.Length == 0) + { + throw new ArgumentException(GetResourceString("Argument_StringZeroLength"), nameof(variable)); + } + if (variable[0] == '\0') + { + throw new ArgumentException(GetResourceString("Argument_StringFirstCharIsZero"), nameof(variable)); + } + if (variable.Length >= MaxEnvVariableValueLength) + { + throw new ArgumentException(GetResourceString("Argument_LongEnvVarValue"), nameof(variable)); + } + if (variable.IndexOf('=') != -1) + { + throw new ArgumentException(GetResourceString("Argument_IllegalEnvVarName"), nameof(variable)); + } + + if (string.IsNullOrEmpty(value) || value[0] == '\0') + { + // Explicitly null out value if it's empty + value = null; + } + else if (value.Length >= MaxEnvVariableValueLength) + { + throw new ArgumentException(GetResourceString("Argument_LongEnvVarValue"), nameof(value)); + } + } + + private static void ValidateTarget(EnvironmentVariableTarget target) + { + if (target != EnvironmentVariableTarget.Process && + target != EnvironmentVariableTarget.Machine && + target != EnvironmentVariableTarget.User) + { + throw new ArgumentOutOfRangeException(nameof(target), target, SR.Format(GetResourceString("Arg_EnumIllegalVal"), target)); + } + } + + private static Dictionary GetRawEnvironmentVariables() + { + // Format for GetEnvironmentStrings is: + // (=HiddenVar=value\0 | Variable=value\0)* \0 + // See the description of Environment Blocks in MSDN's + // CreateProcess page (null-terminated array of null-terminated strings). + // Note the =HiddenVar's aren't always at the beginning. + + // Copy strings out, parsing into pairs and inserting into the table. + // The first few environment variable entries start with an '='. + // The current working directory of every drive (except for those drives + // you haven't cd'ed into in your DOS window) are stored in the + // environment block (as =C:=pwd) and the program's exit code is + // as well (=ExitCode=00000000). + + var results = new Dictionary(); + char[] block = GetEnvironmentCharArray(); + for (int i = 0; i < block.Length; i++) + { + int startKey = i; + + // Skip to key. On some old OS, the environment block can be corrupted. + // Some will not have '=', so we need to check for '\0'. + while (block[i] != '=' && block[i] != '\0') i++; + if (block[i] == '\0') continue; + + // Skip over environment variables starting with '=' + if (i - startKey == 0) + { + while (block[i] != 0) i++; + continue; + } + + string key = new string(block, startKey, i - startKey); + i++; // skip over '=' + + int startValue = i; + while (block[i] != 0) i++; // Read to end of this entry + string value = new string(block, startValue, i - startValue); // skip over 0 handled by for loop's i++ + + results[key] = value; + } + return results; + } + + private static string GetEnvironmentVariableCore(string variable) + { + if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode()) + { + // Environment variable accessors are not approved modern API. + // Behave as if the variable was not found in this case. + return null; + } + + StringBuilder sb = StringBuilderCache.Acquire(128); // A somewhat reasonable default size + int requiredSize = Win32Native.GetEnvironmentVariable(variable, sb, sb.Capacity); + + if (requiredSize == 0 && Marshal.GetLastWin32Error() == Win32Native.ERROR_ENVVAR_NOT_FOUND) + { + StringBuilderCache.Release(sb); + return null; + } + + while (requiredSize > sb.Capacity) + { + sb.Capacity = requiredSize; + sb.Length = 0; + requiredSize = Win32Native.GetEnvironmentVariable(variable, sb, sb.Capacity); + } + + return StringBuilderCache.GetStringAndRelease(sb); + } + + private static string GetEnvironmentVariableCore(string variable, EnvironmentVariableTarget target) + { + if (target == EnvironmentVariableTarget.Process) + return GetEnvironmentVariableCore(variable); + +#if !FEATURE_WIN32_REGISTRY + return null; +#else + RegistryKey baseKey; + string keyName; + + if (target == EnvironmentVariableTarget.Machine) + { + baseKey = Registry.LocalMachine; + keyName = @"System\CurrentControlSet\Control\Session Manager\Environment"; + } + else if (target == EnvironmentVariableTarget.User) + { + Debug.Assert(target == EnvironmentVariableTarget.User); + baseKey = Registry.CurrentUser; + keyName = "Environment"; + } + else + { + throw new ArgumentException(GetResourceString("Arg_EnumIllegalVal", (int)target)); + } + + using (RegistryKey environmentKey = baseKey.OpenSubKey(keyName, writable: false)) + { + return environmentKey?.GetValue(variable) as string; + } +#endif + } + + private static IDictionary GetEnvironmentVariablesCore() + { + if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode()) + { + // Environment variable accessors are not approved modern API. + // Behave as if no environment variables are defined in this case. + return new Dictionary(0); + } + + return GetRawEnvironmentVariables(); + } + + private static IDictionary GetEnvironmentVariablesCore(EnvironmentVariableTarget target) + { + if (target == EnvironmentVariableTarget.Process) + return GetEnvironmentVariablesCore(); + +#if !FEATURE_WIN32_REGISTRY + // Without registry support we have nothing to return + return new Dictionary(0); +#else + RegistryKey baseKey; + string keyName; + if (target == EnvironmentVariableTarget.Machine) + { + baseKey = Registry.LocalMachine; + keyName = @"System\CurrentControlSet\Control\Session Manager\Environment"; + } + else if (target == EnvironmentVariableTarget.User) + { + Debug.Assert(target == EnvironmentVariableTarget.User); + baseKey = Registry.CurrentUser; + keyName = @"Environment"; + } + else + { + throw new ArgumentException(GetResourceString("Arg_EnumIllegalVal", (int)target)); + } + + using (RegistryKey environmentKey = baseKey.OpenSubKey(keyName, writable: false)) + { + var table = new Dictionary(); + if (environmentKey != null) + { + foreach (string name in environmentKey.GetValueNames()) + { + table.Add(name, environmentKey.GetValue(name, "").ToString()); + } + } + return table; + } +#endif // FEATURE_WIN32_REGISTRY + } + + private static void SetEnvironmentVariableCore(string variable, string value) + { + // explicitly null out value if is the empty string. + if (string.IsNullOrEmpty(value) || value[0] == '\0') + value = null; + + if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode()) + { + // Environment variable accessors are not approved modern API. + // so we throw PlatformNotSupportedException. + throw new PlatformNotSupportedException(); + } + + if (!Win32Native.SetEnvironmentVariable(variable, value)) + { + int errorCode = Marshal.GetLastWin32Error(); + + switch (errorCode) + { + case Win32Native.ERROR_ENVVAR_NOT_FOUND: + // Allow user to try to clear a environment variable + return; + case Win32Native.ERROR_FILENAME_EXCED_RANGE: + // The error message from Win32 is "The filename or extension is too long", + // which is not accurate. + throw new ArgumentException(GetResourceString("Argument_LongEnvVarValue")); + default: + throw new ArgumentException(Win32Native.GetMessage(errorCode)); + } + } + } + + private static void SetEnvironmentVariableCore(string variable, string value, EnvironmentVariableTarget target) + { + if (target == EnvironmentVariableTarget.Process) + { + SetEnvironmentVariableCore(variable, value); + return; + } + +#if !FEATURE_WIN32_REGISTRY + // other targets ignored + return; +#else + // explicitly null out value if is the empty string. + if (string.IsNullOrEmpty(value) || value[0] == '\0') + value = null; + + RegistryKey baseKey; + string keyName; + + if (target == EnvironmentVariableTarget.Machine) + { + baseKey = Registry.LocalMachine; + keyName = @"System\CurrentControlSet\Control\Session Manager\Environment"; + } + else if (target == EnvironmentVariableTarget.User) + { + Debug.Assert(target == EnvironmentVariableTarget.User); + + // User-wide environment variables stored in the registry are limited to 255 chars for the environment variable name. + const int MaxUserEnvVariableLength = 255; + if (variable.Length >= MaxUserEnvVariableLength) + { + throw new ArgumentException(GetResourceString("Argument_LongEnvVarValue"), nameof(variable)); + } + + baseKey = Registry.CurrentUser; + keyName = "Environment"; + } + else + { + throw new ArgumentException(GetResourceString("Arg_EnumIllegalVal", (int)target)); + } + + using (RegistryKey environmentKey = baseKey.OpenSubKey(keyName, writable: true)) + { + if (environmentKey != null) + { + if (value == null) + { + environmentKey.DeleteValue(variable, throwOnMissingValue: false); + } + else + { + environmentKey.SetValue(variable, value); + } + } + } + + // send a WM_SETTINGCHANGE message to all windows + IntPtr r = Win32Native.SendMessageTimeout(new IntPtr(Win32Native.HWND_BROADCAST), + Win32Native.WM_SETTINGCHANGE, IntPtr.Zero, "Environment", 0, 1000, IntPtr.Zero); + + if (r == IntPtr.Zero) Debug.Assert(false, "SetEnvironmentVariable failed: " + Marshal.GetLastWin32Error()); +#endif // FEATURE_WIN32_REGISTRY + } } } diff --git a/src/mscorlib/src/System/Exception.cs b/src/mscorlib/src/System/Exception.cs index 12799e7..a8ee328 100644 --- a/src/mscorlib/src/System/Exception.cs +++ b/src/mscorlib/src/System/Exception.cs @@ -73,11 +73,10 @@ namespace System { _innerException = innerException; } - [System.Security.SecuritySafeCritical] // auto-generated protected Exception(SerializationInfo info, StreamingContext context) { if (info==null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); _className = info.GetString("ClassName"); @@ -143,7 +142,6 @@ namespace System { } public virtual IDictionary Data { - [System.Security.SecuritySafeCritical] // auto-generated get { if (_data == null) if (IsImmutableAgileException(this)) @@ -155,7 +153,6 @@ namespace System { } } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool IsImmutableAgileException(Exception e); @@ -260,11 +257,9 @@ namespace System { } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] static extern private IRuntimeMethodInfo GetMethodFromStackTrace(Object stackTrace); - [System.Security.SecuritySafeCritical] // auto-generated private MethodBase GetExceptionMethodFromStackTrace() { IRuntimeMethodInfo method = GetMethodFromStackTrace(_stackTrace); @@ -277,7 +272,6 @@ namespace System { } public MethodBase TargetSite { - [System.Security.SecuritySafeCritical] // auto-generated get { return GetTargetSiteInternal(); } @@ -285,7 +279,6 @@ namespace System { // this function is provided as a private helper to avoid the security demand - [System.Security.SecurityCritical] // auto-generated private MethodBase GetTargetSiteInternal() { if (_exceptionMethod!=null) { return _exceptionMethod; @@ -306,9 +299,6 @@ namespace System { // available, null is returned. public virtual String StackTrace { -#if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] -#endif get { // By default attempt to include file and line number info @@ -321,24 +311,11 @@ namespace System { // is true. Note that this requires FileIOPermission(PathDiscovery), and so // will usually fail in CoreCLR. To avoid the demand and resulting // SecurityException we can explicitly not even try to get fileinfo. -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif private string GetStackTrace(bool needFileInfo) { string stackTraceString = _stackTraceString; string remoteStackTraceString = _remoteStackTraceString; -#if !FEATURE_CORECLR - if (!needFileInfo) - { - // Filter out file names/paths and line numbers from _stackTraceString and _remoteStackTraceString. - // This is used only when generating stack trace for Watson where the strings must be PII-free. - stackTraceString = StripFileInfo(stackTraceString, false); - remoteStackTraceString = StripFileInfo(remoteStackTraceString, true); - } -#endif // !FEATURE_CORECLR - // if no stack trace, try to get one if (stackTraceString != null) { @@ -380,9 +357,6 @@ namespace System { } public virtual String Source { -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif get { if (_source == null) { @@ -411,23 +385,14 @@ namespace System { return _source; } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif set { _source = value; } } -#if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] -#endif public override String ToString() { return ToString(true, true); } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif private String ToString(bool needFileLineInfo, bool needMessage) { String message = (needMessage ? Message : null); String s; @@ -454,7 +419,6 @@ namespace System { return s; } - [System.Security.SecurityCritical] // auto-generated private String GetExceptionMethodString() { MethodBase methBase = GetTargetSiteInternal(); if (methBase==null) { @@ -487,7 +451,7 @@ namespace System { result.Append(separator); result.Append(rci.ToString()); } else { - Contract.Assert(methBase is MethodInfo, "[Exception.GetExceptionMethodString]methBase is MethodInfo"); + Debug.Assert(methBase is MethodInfo, "[Exception.GetExceptionMethodString]methBase is MethodInfo"); RuntimeMethodInfo rmi = (RuntimeMethodInfo)methBase; Type t = rmi.DeclaringType; result.Append((int)MemberTypes.Method); @@ -507,9 +471,8 @@ namespace System { return result.ToString(); } - [System.Security.SecurityCritical] // auto-generated private MethodBase GetExceptionMethodFromString() { - Contract.Assert(_exceptionMethodString != null, "Method string cannot be NULL!"); + Debug.Assert(_exceptionMethodString != null, "Method string cannot be NULL!"); String[] args = _exceptionMethodString.Split(new char[]{'\0', '\n'}); if (args.Length!=5) { throw new SerializationException(); @@ -536,14 +499,19 @@ namespace System { add { _safeSerializationManager.SerializeObjectState += value; } remove { _safeSerializationManager.SerializeObjectState -= value; } } +#else + protected event EventHandler SerializeObjectState + { + add { throw new PlatformNotSupportedException();} + remove { throw new PlatformNotSupportedException();} + } #endif // FEATURE_SERIALIZATION - [System.Security.SecurityCritical] // auto-generated_required public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); @@ -591,7 +559,7 @@ namespace System { // often created in the VM with AllocateObject instead if the managed construtor) // If you are adding code to use a SafeSerializationManager from an mscorlib exception, update // this assert to ensure that it fails when that exception's _safeSerializationManager is NULL - Contract.Assert(((_safeSerializationManager != null) || (this.GetType().Assembly == typeof(object).Assembly)), + Debug.Assert(((_safeSerializationManager != null) || (this.GetType().Assembly == typeof(object).Assembly)), "User defined exceptions must have a valid _safeSerializationManager"); // Handle serializing any transparent or partial trust subclass data @@ -656,9 +624,6 @@ namespace System { // This is used by the runtime when re-throwing a managed exception. It will // copy the stack trace to _remoteStackTraceString. -#if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] -#endif internal void InternalPreserveStackTrace() { string tmpStackTraceString; @@ -731,33 +696,21 @@ namespace System { } } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void PrepareForForeignExceptionRaise(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void GetStackTracesDeepCopy(Exception exception, out object currentStackTrace, out object dynamicMethodArray); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void SaveStackTracesFromDeepCopy(Exception exception, object currentStackTrace, object dynamicMethodArray); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern object CopyStackTrace(object currentStackTrace); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern object CopyDynamicMethods(object currentDynamicMethods); -#if !FEATURE_CORECLR - [System.Security.SecuritySafeCritical] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern string StripFileInfo(string stackTrace, bool isRemoteStackTrace); -#endif // !FEATURE_CORECLR - - [SecuritySafeCritical] internal object DeepCopyStackTrace(object currentStackTrace) { if (currentStackTrace != null) @@ -770,7 +723,6 @@ namespace System { } } - [SecuritySafeCritical] internal object DeepCopyDynamicMethods(object currentDynamicMethods) { if (currentDynamicMethods != null) @@ -783,7 +735,6 @@ namespace System { } } - [SecuritySafeCritical] internal void GetStackTracesDeepCopy(out object currentStackTrace, out object dynamicMethodArray) { GetStackTracesDeepCopy(this, out currentStackTrace, out dynamicMethodArray); @@ -791,7 +742,6 @@ namespace System { // This is invoked by ExceptionDispatchInfo.Throw to restore the exception stack trace, corresponding to the original throw of the // exception, just before the exception is "rethrown". - [SecuritySafeCritical] internal void RestoreExceptionDispatchInfo(System.Runtime.ExceptionServices.ExceptionDispatchInfo exceptionDispatchInfo) { bool fCanProcessException = !(IsImmutableAgileException(this)); @@ -894,7 +844,6 @@ namespace System { // InternalToString is called by the runtime to get the exception text // and create a corresponding CrossAppDomainMarshaledException - [System.Security.SecurityCritical] // auto-generated internal virtual String InternalToString() { try @@ -923,13 +872,11 @@ namespace System { internal bool IsTransient { - [System.Security.SecuritySafeCritical] // auto-generated get { return nIsTransient(_HResult); } } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static bool nIsTransient(int hr); @@ -951,7 +898,6 @@ namespace System { } // See comment on ExceptionMessageKind - [System.Security.SecuritySafeCritical] // auto-generated internal static String GetMessageFromNativeResources(ExceptionMessageKind kind) { string retMesg = null; @@ -959,16 +905,11 @@ namespace System { return retMesg; } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void GetMessageFromNativeResources(ExceptionMessageKind kind, StringHandleOnStack retMesg); } - - -#if FEATURE_CORECLR - //-------------------------------------------------------------------------- // Telesto: Telesto doesn't support appdomain marshaling of objects so // managed exceptions that leak across appdomain boundaries are flatted to @@ -990,17 +931,10 @@ namespace System { // Normally, only Telesto's UEF will see these exceptions. // This override prints out the original Exception's ToString() // output and hides the fact that it is wrapped inside another excepton. -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif internal override String InternalToString() { return Message; } - } -#endif - - } diff --git a/src/mscorlib/src/System/FormattableString.cs b/src/mscorlib/src/System/FormattableString.cs index ef56bcf..294b2c1 100644 --- a/src/mscorlib/src/System/FormattableString.cs +++ b/src/mscorlib/src/System/FormattableString.cs @@ -67,7 +67,7 @@ namespace System { if (formattable == null) { - throw new ArgumentNullException("formattable"); + throw new ArgumentNullException(nameof(formattable)); } return formattable.ToString(Globalization.CultureInfo.InvariantCulture); diff --git a/src/mscorlib/src/System/GC.cs b/src/mscorlib/src/System/GC.cs index 73c676d..e338e44 100644 --- a/src/mscorlib/src/System/GC.cs +++ b/src/mscorlib/src/System/GC.cs @@ -63,71 +63,56 @@ namespace System { public static class GC { - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern int GetGCLatencyMode(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern int SetGCLatencyMode(int newLatencyMode); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern int _StartNoGCRegion(long totalSize, bool lohSizeKnown, long lohSize, bool disallowFullBlockingGC); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern int _EndNoGCRegion(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern int GetLOHCompactionMode(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void SetLOHCompactionMode(int newLOHCompactionMode); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern int GetGenerationWR(IntPtr handle); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern long GetTotalMemory(); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void _Collect(int generation, int mode); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern int GetMaxGeneration(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] private static extern int _CollectionCount (int generation, int getSpecialGCCount); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool IsServerGC(); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] private static extern void _AddMemoryPressure(UInt64 bytesAllocated); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] private static extern void _RemoveMemoryPressure(UInt64 bytesAllocated); - [System.Security.SecurityCritical] // auto-generated_required public static void AddMemoryPressure (long bytesAllocated) { if( bytesAllocated <= 0) { - throw new ArgumentOutOfRangeException("bytesAllocated", + throw new ArgumentOutOfRangeException(nameof(bytesAllocated), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); } @@ -140,15 +125,14 @@ namespace System { _AddMemoryPressure((ulong)bytesAllocated); } - [System.Security.SecurityCritical] // auto-generated_required public static void RemoveMemoryPressure (long bytesAllocated) { if( bytesAllocated <= 0) { - throw new ArgumentOutOfRangeException("bytesAllocated", + throw new ArgumentOutOfRangeException(nameof(bytesAllocated), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); } if( (4 == IntPtr.Size) && (bytesAllocated > Int32.MaxValue) ) { - throw new ArgumentOutOfRangeException("bytesAllocated", + throw new ArgumentOutOfRangeException(nameof(bytesAllocated), Environment.GetResourceString("ArgumentOutOfRange_MustBeNonNegInt32")); } Contract.EndContractBlock(); @@ -159,7 +143,6 @@ namespace System { // Returns the generation that obj is currently in. // - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern int GetGeneration(Object obj); @@ -172,35 +155,31 @@ namespace System { // Garbage Collect all generations. // - [System.Security.SecuritySafeCritical] // auto-generated public static void Collect() { //-1 says to GC all generations. _Collect(-1, (int)InternalGCCollectionMode.Blocking); } - [System.Security.SecuritySafeCritical] // auto-generated public static void Collect(int generation, GCCollectionMode mode) { Collect(generation, mode, true); } - [System.Security.SecuritySafeCritical] // auto-generated public static void Collect(int generation, GCCollectionMode mode, bool blocking) { Collect(generation, mode, blocking, false); } - [System.Security.SecuritySafeCritical] // auto-generated public static void Collect(int generation, GCCollectionMode mode, bool blocking, bool compacting) { if (generation<0) { - throw new ArgumentOutOfRangeException("generation", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); + throw new ArgumentOutOfRangeException(nameof(generation), Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); } if ((mode < GCCollectionMode.Default) || (mode > GCCollectionMode.Optimized)) { - throw new ArgumentOutOfRangeException("mode", Environment.GetResourceString("ArgumentOutOfRange_Enum")); + throw new ArgumentOutOfRangeException(nameof(mode), Environment.GetResourceString("ArgumentOutOfRange_Enum")); } Contract.EndContractBlock(); @@ -227,26 +206,24 @@ namespace System { _Collect(generation, iInternalModes); } - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static int CollectionCount (int generation) { if (generation<0) { - throw new ArgumentOutOfRangeException("generation", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); + throw new ArgumentOutOfRangeException(nameof(generation), Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); } Contract.EndContractBlock(); return _CollectionCount(generation, 0); } // pass in true to get the BGC or FGC count. - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal static int CollectionCount (int generation, bool getSpecialGCCount) { if (generation<0) { - throw new ArgumentOutOfRangeException("generation", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); + throw new ArgumentOutOfRangeException(nameof(generation), Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); } Contract.EndContractBlock(); return _CollectionCount(generation, (getSpecialGCCount ? 1 : 0)); @@ -295,7 +272,6 @@ namespace System { // Returns the generation in which wo currently resides. // - [System.Security.SecuritySafeCritical] // auto-generated public static int GetGeneration(WeakReference wo) { int result = GetGenerationWR(wo.m_handle); KeepAlive(wo); @@ -305,16 +281,13 @@ namespace System { // Returns the maximum GC generation. Currently assumes only 1 heap. // public static int MaxGeneration { - [System.Security.SecuritySafeCritical] // auto-generated get { return GetMaxGeneration(); } } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void _WaitForPendingFinalizers(); - [System.Security.SecuritySafeCritical] // auto-generated public static void WaitForPendingFinalizers() { // QCalls can not be exposed from mscorlib directly, need to wrap it. _WaitForPendingFinalizers(); @@ -322,16 +295,14 @@ namespace System { // Indicates that the system should not call the Finalize() method on // an object that would normally require this call. - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] private static extern void _SuppressFinalize(Object o); - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static void SuppressFinalize(Object obj) { if (obj == null) - throw new ArgumentNullException("obj"); + throw new ArgumentNullException(nameof(obj)); Contract.EndContractBlock(); _SuppressFinalize(obj); } @@ -340,14 +311,12 @@ namespace System { // for which SuppressFinalize has already been called. The other situation // where calling ReRegisterForFinalize is useful is inside a finalizer that // needs to resurrect itself or an object that it references. - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void _ReRegisterForFinalize(Object o); - [System.Security.SecuritySafeCritical] // auto-generated public static void ReRegisterForFinalize(Object obj) { if (obj == null) - throw new ArgumentNullException("obj"); + throw new ArgumentNullException(nameof(obj)); Contract.EndContractBlock(); _ReRegisterForFinalize(obj); } @@ -356,7 +325,6 @@ namespace System { // the GC heap. This does not return the total size of the GC heap, but // only the live objects in the GC heap. // - [System.Security.SecuritySafeCritical] // auto-generated public static long GetTotalMemory(bool forceFullCollection) { long size = GetTotalMemory(); if (!forceFullCollection) @@ -379,16 +347,13 @@ namespace System { return newSize; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern long _GetAllocatedBytesForCurrentThread(); - [System.Security.SecuritySafeCritical] // auto-generated public static long GetAllocatedBytesForCurrentThread() { return _GetAllocatedBytesForCurrentThread(); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool _RegisterForFullGCNotification(int maxGenerationPercentage, int largeObjectHeapPercentage); @@ -401,12 +366,11 @@ namespace System { [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern int _WaitForFullGCComplete(int millisecondsTimeout); - [SecurityCritical] public static void RegisterForFullGCNotification(int maxGenerationThreshold, int largeObjectHeapThreshold) { if ((maxGenerationThreshold <= 0) || (maxGenerationThreshold >= 100)) { - throw new ArgumentOutOfRangeException("maxGenerationThreshold", + throw new ArgumentOutOfRangeException(nameof(maxGenerationThreshold), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper"), @@ -416,7 +380,7 @@ namespace System { if ((largeObjectHeapThreshold <= 0) || (largeObjectHeapThreshold >= 100)) { - throw new ArgumentOutOfRangeException("largeObjectHeapThreshold", + throw new ArgumentOutOfRangeException(nameof(largeObjectHeapThreshold), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper"), @@ -430,7 +394,6 @@ namespace System { } } - [SecurityCritical] public static void CancelFullGCNotification() { if (!_CancelFullGCNotification()) @@ -439,32 +402,28 @@ namespace System { } } - [SecurityCritical] public static GCNotificationStatus WaitForFullGCApproach() { return (GCNotificationStatus)_WaitForFullGCApproach(-1); } - [SecurityCritical] public static GCNotificationStatus WaitForFullGCApproach(int millisecondsTimeout) { if (millisecondsTimeout < -1) - throw new ArgumentOutOfRangeException("millisecondsTimeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); return (GCNotificationStatus)_WaitForFullGCApproach(millisecondsTimeout); } - [SecurityCritical] public static GCNotificationStatus WaitForFullGCComplete() { return (GCNotificationStatus)_WaitForFullGCComplete(-1); } - [SecurityCritical] public static GCNotificationStatus WaitForFullGCComplete(int millisecondsTimeout) { if (millisecondsTimeout < -1) - throw new ArgumentOutOfRangeException("millisecondsTimeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); return (GCNotificationStatus)_WaitForFullGCComplete(millisecondsTimeout); } @@ -484,12 +443,11 @@ namespace System { AllocationExceeded = 3 } - [SecurityCritical] static bool StartNoGCRegionWorker(long totalSize, bool hasLohSize, long lohSize, bool disallowFullBlockingGC) { StartNoGCRegionStatus status = (StartNoGCRegionStatus)_StartNoGCRegion(totalSize, hasLohSize, lohSize, disallowFullBlockingGC); if (status == StartNoGCRegionStatus.AmountTooLarge) - throw new ArgumentOutOfRangeException("totalSize", + throw new ArgumentOutOfRangeException(nameof(totalSize), "totalSize is too large. For more information about setting the maximum size, see \"Latency Modes\" in http://go.microsoft.com/fwlink/?LinkId=522706"); else if (status == StartNoGCRegionStatus.AlreadyInProgress) throw new InvalidOperationException("The NoGCRegion mode was already in progress"); @@ -498,31 +456,26 @@ namespace System { return true; } - [SecurityCritical] public static bool TryStartNoGCRegion(long totalSize) { return StartNoGCRegionWorker(totalSize, false, 0, false); } - [SecurityCritical] public static bool TryStartNoGCRegion(long totalSize, long lohSize) { return StartNoGCRegionWorker(totalSize, true, lohSize, false); } - [SecurityCritical] public static bool TryStartNoGCRegion(long totalSize, bool disallowFullBlockingGC) { return StartNoGCRegionWorker(totalSize, false, 0, disallowFullBlockingGC); } - [SecurityCritical] public static bool TryStartNoGCRegion(long totalSize, long lohSize, bool disallowFullBlockingGC) { return StartNoGCRegionWorker(totalSize, true, lohSize, disallowFullBlockingGC); } - [SecurityCritical] static EndNoGCRegionStatus EndNoGCRegionWorker() { EndNoGCRegionStatus status = (EndNoGCRegionStatus)_EndNoGCRegion(); @@ -536,106 +489,9 @@ namespace System { return EndNoGCRegionStatus.Succeeded; } - [SecurityCritical] public static void EndNoGCRegion() { EndNoGCRegionWorker(); } } - -#if !FEATURE_CORECLR - internal class SizedReference : IDisposable - { - [System.Security.SecurityCritical] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern IntPtr CreateSizedRef(Object o); - - [System.Security.SecurityCritical] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern void FreeSizedRef(IntPtr h); - - [System.Security.SecurityCritical] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern Object GetTargetOfSizedRef(IntPtr h); - - [System.Security.SecurityCritical] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern Int64 GetApproximateSizeOfSizedRef(IntPtr h); - - #pragma warning disable 420 - [System.Security.SecuritySafeCritical] - private void Free() - { - IntPtr temp = _handle; - if (temp != IntPtr.Zero && - (Interlocked.CompareExchange(ref _handle, IntPtr.Zero, temp) == temp)) - { - FreeSizedRef(temp); - } - } - - internal volatile IntPtr _handle; - - [System.Security.SecuritySafeCritical] - public SizedReference(Object target) - { - IntPtr temp = IntPtr.Zero; - temp = CreateSizedRef(target); - _handle = temp; - } - - ~SizedReference() - { - Free(); - } - - public Object Target - { - [System.Security.SecuritySafeCritical] - get - { - IntPtr temp = _handle; - if (temp == IntPtr.Zero) - { - return null; - } - - Object o = GetTargetOfSizedRef(temp); - - return (_handle == IntPtr.Zero) ? null : o; - } - } - - public Int64 ApproximateSize - { - [System.Security.SecuritySafeCritical] - get - { - IntPtr temp = _handle; - - if (temp == IntPtr.Zero) - { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized")); - } - - Int64 size = GetApproximateSizeOfSizedRef(temp); - - if (_handle == IntPtr.Zero) - { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized")); - } - else - { - return size; - } - } - } - - public void Dispose() - { - Free(); - GC.SuppressFinalize(this); - } - } -#endif } diff --git a/src/mscorlib/src/System/Globalization/Calendar.cs b/src/mscorlib/src/System/Globalization/Calendar.cs index d6dfdc9..d046038 100644 --- a/src/mscorlib/src/System/Globalization/Calendar.cs +++ b/src/mscorlib/src/System/Globalization/Calendar.cs @@ -7,6 +7,7 @@ namespace System.Globalization { using System.Runtime.CompilerServices; using System.Globalization; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; // This abstract class represents a calendar. A calendar reckons time in @@ -192,7 +193,7 @@ namespace System.Globalization { [System.Runtime.InteropServices.ComVisible(false)] public static Calendar ReadOnly(Calendar calendar) { - if (calendar == null) { throw new ArgumentNullException("calendar"); } + if (calendar == null) { throw new ArgumentNullException(nameof(calendar)); } Contract.EndContractBlock(); if (calendar.IsReadOnly) { return (calendar); } @@ -229,7 +230,7 @@ namespace System.Globalization { get { // The following code assumes that the current era value can not be -1. if (m_currentEraValue == -1) { - Contract.Assert(BaseCalendarID > 0, "[Calendar.CurrentEraValue] Expected ID > 0"); + Debug.Assert(BaseCalendarID > 0, "[Calendar.CurrentEraValue] Expected ID > 0"); m_currentEraValue = CalendarData.GetCalendarData(BaseCalendarID).iCurrentEra; } return (m_currentEraValue); @@ -262,7 +263,7 @@ namespace System.Globalization { double tempMillis = (value * scale + (value >= 0 ? 0.5 : -0.5)); if (!((tempMillis > -(double)MaxMillis) && (tempMillis < (double)MaxMillis))) { - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_AddValue")); + throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_AddValue")); } long millis = (long)tempMillis; @@ -529,7 +530,7 @@ namespace System.Globalization { // this value can be less than 0. It's fine since we are making it positive again in calculating offset. int dayForJan1 = (int)GetDayOfWeek(time) - (dayOfYear % 7); int offset = (dayForJan1 - firstDayOfWeek + 14) % 7; - Contract.Assert(offset >= 0, "Calendar.GetFirstDayWeekOfYear(): offset >= 0"); + Debug.Assert(offset >= 0, "Calendar.GetFirstDayWeekOfYear(): offset >= 0"); return ((dayOfYear + offset) / 7 + 1); } @@ -651,7 +652,7 @@ namespace System.Globalization { { if ((int)firstDayOfWeek < 0 || (int)firstDayOfWeek > 6) { throw new ArgumentOutOfRangeException( - "firstDayOfWeek", Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(firstDayOfWeek), Environment.GetResourceString("ArgumentOutOfRange_Range", DayOfWeek.Sunday, DayOfWeek.Saturday)); } Contract.EndContractBlock(); @@ -664,7 +665,7 @@ namespace System.Globalization { return (GetWeekOfYearFullDays(time, (int)firstDayOfWeek, 4)); } throw new ArgumentOutOfRangeException( - "rule", Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(rule), Environment.GetResourceString("ArgumentOutOfRange_Range", CalendarWeekRule.FirstDay, CalendarWeekRule.FirstFourDayWeek)); } @@ -815,7 +816,7 @@ namespace System.Globalization { public virtual int ToFourDigitYear(int year) { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.EndContractBlock(); @@ -835,7 +836,7 @@ namespace System.Globalization { { if (millisecond < 0 || millisecond >= MillisPerSecond) { throw new ArgumentOutOfRangeException( - "millisecond", + nameof(millisecond), String.Format( CultureInfo.InvariantCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), 0, MillisPerSecond - 1)); @@ -845,7 +846,6 @@ namespace System.Globalization { throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadHourMinuteSecond")); } - [System.Security.SecuritySafeCritical] // auto-generated internal static int GetSystemTwoDigitYearSetting(int CalID, int defaultYearValue) { // Call nativeGetTwoDigitYearMax diff --git a/src/mscorlib/src/System/Globalization/CalendarData.cs b/src/mscorlib/src/System/Globalization/CalendarData.cs index 8c187f0..6f583fb 100644 --- a/src/mscorlib/src/System/Globalization/CalendarData.cs +++ b/src/mscorlib/src/System/Globalization/CalendarData.cs @@ -9,6 +9,7 @@ namespace System.Globalization using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; // // List of calendar data @@ -121,7 +122,7 @@ namespace System.Globalization this.bUseUserOverrides = bUseUserOverrides; if (!nativeGetCalendarData(this, localeName, calendarId)) { - Contract.Assert(false, "[CalendarData] nativeGetCalendarData call isn't expected to fail for calendar " + calendarId + " locale " +localeName); + Debug.Assert(false, "[CalendarData] nativeGetCalendarData call isn't expected to fail for calendar " + calendarId + " locale " +localeName); // Something failed, try invariant for missing parts // This is really not good, but we don't want the callers to crash. @@ -436,17 +437,14 @@ namespace System.Globalization // Get native two digit year max - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern int nativeGetTwoDigitYearMax(int calID); // Call native side to load our calendar data - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool nativeGetCalendarData(CalendarData data, String localeName, int calendar); // Call native side to figure out which calendars are allowed - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern int nativeGetCalendars(String localeName, bool useUserOverride, [In, Out] int[] calendars); diff --git a/src/mscorlib/src/System/Globalization/CalendricalCalculationsHelper.cs b/src/mscorlib/src/System/Globalization/CalendricalCalculationsHelper.cs index 7084511..1113cd5 100644 --- a/src/mscorlib/src/System/Globalization/CalendricalCalculationsHelper.cs +++ b/src/mscorlib/src/System/Globalization/CalendricalCalculationsHelper.cs @@ -5,6 +5,7 @@ namespace System.Globalization { using System; + using System.Diagnostics; using System.Diagnostics.Contracts; internal class CalendricalCalculationsHelper @@ -153,7 +154,7 @@ namespace System.Globalization // the following formulas defines a polynomial function which gives us the amount that the earth is slowing down for specific year ranges static double DefaultEphemerisCorrection(int gregorianYear) { - Contract.Assert(gregorianYear < 1620 || 2020 <= gregorianYear); + Debug.Assert(gregorianYear < 1620 || 2020 <= gregorianYear); long january1stOfYear = GetNumberOfDays(new DateTime(gregorianYear, 1, 1)); double daysSinceStartOf1810 = january1stOfYear - StartOf1810; double x = TwelveHours + daysSinceStartOf1810; @@ -162,34 +163,34 @@ namespace System.Globalization static double EphemerisCorrection1988to2019(int gregorianYear) { - Contract.Assert(1988 <= gregorianYear && gregorianYear <= 2019); + Debug.Assert(1988 <= gregorianYear && gregorianYear <= 2019); return (double)(gregorianYear - 1933) / SecondsPerDay; } static double EphemerisCorrection1900to1987(int gregorianYear) { - Contract.Assert(1900 <= gregorianYear && gregorianYear <= 1987); + Debug.Assert(1900 <= gregorianYear && gregorianYear <= 1987); double centuriesFrom1900 = CenturiesFrom1900(gregorianYear); return PolynomialSum(Coefficients1900to1987, centuriesFrom1900); } static double EphemerisCorrection1800to1899(int gregorianYear) { - Contract.Assert(1800 <= gregorianYear && gregorianYear <= 1899); + Debug.Assert(1800 <= gregorianYear && gregorianYear <= 1899); double centuriesFrom1900 = CenturiesFrom1900(gregorianYear); return PolynomialSum(Coefficients1800to1899, centuriesFrom1900); } static double EphemerisCorrection1700to1799(int gregorianYear) { - Contract.Assert(1700 <= gregorianYear && gregorianYear <= 1799); + Debug.Assert(1700 <= gregorianYear && gregorianYear <= 1799); double yearsSince1700 = gregorianYear - 1700; return PolynomialSum(Coefficients1700to1799, yearsSince1700) / SecondsPerDay; } static double EphemerisCorrection1620to1699(int gregorianYear) { - Contract.Assert(1620 <= gregorianYear && gregorianYear <= 1699); + Debug.Assert(1620 <= gregorianYear && gregorianYear <= 1699); double yearsSince1600 = gregorianYear - 1600; return PolynomialSum(Coefficients1620to1699, yearsSince1600) / SecondsPerDay; } @@ -216,7 +217,7 @@ namespace System.Globalization } } - Contract.Assert(false, "Not expected to come here"); + Debug.Assert(false, "Not expected to come here"); return DefaultEphemerisCorrection(year); } @@ -405,7 +406,7 @@ namespace System.Globalization break; } } - Contract.Assert(day != upperBoundNewYearDay); + Debug.Assert(day != upperBoundNewYearDay); return day - 1; } diff --git a/src/mscorlib/src/System/Globalization/CharUnicodeInfo.cs b/src/mscorlib/src/System/Globalization/CharUnicodeInfo.cs index 6315195..2822b41 100644 --- a/src/mscorlib/src/System/Globalization/CharUnicodeInfo.cs +++ b/src/mscorlib/src/System/Globalization/CharUnicodeInfo.cs @@ -23,6 +23,7 @@ namespace System.Globalization { using System.Runtime.Versioning; using System.Reflection; using System.Security; + using System.Diagnostics; using System.Diagnostics.Contracts; @@ -46,14 +47,11 @@ namespace System.Globalization { static bool s_initialized = InitTable(); // The native pointer to the 12:4:4 index table of the Unicode cateogry data. - [SecurityCritical] unsafe static ushort* s_pCategoryLevel1Index; - [SecurityCritical] unsafe static byte* s_pCategoriesValue; // The native pointer to the 12:4:4 index table of the Unicode numeric data. // The value of this index table is an index into the real value table stored in s_pNumericValues. - [SecurityCritical] unsafe static ushort* s_pNumericLevel1Index; // The numeric value table, which is indexed by s_pNumericLevel1Index. @@ -61,12 +59,10 @@ namespace System.Globalization { // unsafe static double* s_pNumericValues; // To get around the IA64 alignment issue. Our double data is aligned in 8-byte boundary, but loader loads the embeded table starting // at 4-byte boundary. This cause a alignment issue since double is 8-byte. - [SecurityCritical] unsafe static byte* s_pNumericValues; // The digit value table, which is indexed by s_pNumericLevel1Index. It shares the same indice as s_pNumericValues. // Every item contains the value for decimal digit/digit value. - [SecurityCritical] unsafe static DigitValues* s_pDigitValues; internal const String UNICODE_INFO_FILE_NAME = "charinfo.nlp"; @@ -111,7 +107,6 @@ namespace System.Globalization { //use. We allocate this once in the class initializer and then we don't need to worry //about it again. // - [System.Security.SecuritySafeCritical] // auto-generated unsafe static bool InitTable() { // Go to native side and get pointer to the native table @@ -143,8 +138,8 @@ namespace System.Globalization { //////////////////////////////////////////////////////////////////////// internal static int InternalConvertToUtf32(String s, int index) { - Contract.Assert(s != null, "s != null"); - Contract.Assert(index >= 0 && index < s.Length, "index < s.Length"); + Debug.Assert(s != null, "s != null"); + Debug.Assert(index >= 0 && index < s.Length, "index < s.Length"); if (index < s.Length - 1) { int temp1 = (int)s[index] - HIGH_SURROGATE_START; if (temp1 >= 0 && temp1 <= 0x3ff) { @@ -181,9 +176,9 @@ namespace System.Globalization { //////////////////////////////////////////////////////////////////////// internal static int InternalConvertToUtf32(String s, int index, out int charLength) { - Contract.Assert(s != null, "s != null"); - Contract.Assert(s.Length > 0, "s.Length > 0"); - Contract.Assert(index >= 0 && index < s.Length, "index >= 0 && index < s.Length"); + Debug.Assert(s != null, "s != null"); + Debug.Assert(s.Length > 0, "s.Length > 0"); + Debug.Assert(index >= 0 && index < s.Length, "index >= 0 && index < s.Length"); charLength = 1; if (index < s.Length - 1) { int temp1 = (int)s[index] - HIGH_SURROGATE_START; @@ -209,8 +204,8 @@ namespace System.Globalization { internal static bool IsWhiteSpace(String s, int index) { - Contract.Assert(s != null, "s!=null"); - Contract.Assert(index >= 0 && index < s.Length, "index >= 0 && index < s.Length"); + Debug.Assert(s != null, "s!=null"); + Debug.Assert(index >= 0 && index < s.Length, "index >= 0 && index < s.Length"); UnicodeCategory uc = GetUnicodeCategory(s, index); // In Unicode 3.0, U+2028 is the only character which is under the category "LineSeparator". @@ -245,9 +240,8 @@ namespace System.Globalization { // // Note that for ch in the range D800-DFFF we just treat it as any other non-numeric character // - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static double InternalGetNumericValue(int ch) { - Contract.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range."); + Debug.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range."); // Get the level 2 item from the highest 12 bit (8 - 19) of ch. ushort index = s_pNumericLevel1Index[ch >> 8]; // Get the level 2 WORD offset from the 4 - 7 bit of ch. This provides the base offset of the level 3 table. @@ -278,9 +272,8 @@ namespace System.Globalization { // // Note that for ch in the range D800-DFFF we just treat it as any other non-numeric character // - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static DigitValues* InternalGetDigitValues(int ch) { - Contract.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range."); + Debug.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range."); // Get the level 2 item from the highest 12 bit (8 - 19) of ch. ushort index = s_pNumericLevel1Index[ch >> 8]; // Get the level 2 WORD offset from the 4 - 7 bit of ch. This provides the base offset of the level 3 table. @@ -292,12 +285,10 @@ namespace System.Globalization { return &(s_pDigitValues[pBytePtr[(ch & 0x000f)]]); } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static sbyte InternalGetDecimalDigitValue(int ch) { return (InternalGetDigitValues(ch)->decimalDigit); } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static sbyte InternalGetDigitValue(int ch) { return (InternalGetDigitValues(ch)->digit); } @@ -326,10 +317,10 @@ namespace System.Globalization { public static double GetNumericValue(String s, int index) { if (s == null) { - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); } if (index < 0 || index >= s.Length) { - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); } Contract.EndContractBlock(); return (InternalGetNumericValue(InternalConvertToUtf32(s, index))); @@ -361,10 +352,10 @@ namespace System.Globalization { public static int GetDecimalDigitValue(String s, int index) { if (s == null) { - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); } if (index < 0 || index >= s.Length) { - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); } Contract.EndContractBlock(); @@ -398,10 +389,10 @@ namespace System.Globalization { public static int GetDigitValue(String s, int index) { if (s == null) { - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); } if (index < 0 || index >= s.Length) { - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); } Contract.EndContractBlock(); return (InternalGetDigitValue(InternalConvertToUtf32(s, index))); @@ -415,9 +406,9 @@ namespace System.Globalization { public static UnicodeCategory GetUnicodeCategory(String s, int index) { if (s==null) - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); if (((uint)index)>=((uint)s.Length)) { - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); } Contract.EndContractBlock(); return InternalGetUnicodeCategory(s, index); @@ -441,9 +432,8 @@ namespace System.Globalization { // //////////////////////////////////////////////////////////////////////// - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static byte InternalGetCategoryValue(int ch, int offset) { - Contract.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range."); + Debug.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range."); // Get the level 2 item from the highest 12 bit (8 - 19) of ch. ushort index = s_pCategoryLevel1Index[ch >> 8]; // Get the level 2 WORD offset from the 4 - 7 bit of ch. This provides the base offset of the level 3 table. @@ -457,7 +447,7 @@ namespace System.Globalization { // Make sure that OtherNotAssigned is the last category in UnicodeCategory. // If that changes, change the following assertion as well. // - //Contract.Assert(uc >= 0 && uc <= UnicodeCategory.OtherNotAssigned, "Table returns incorrect Unicode category"); + //Debug.Assert(uc >= 0 && uc <= UnicodeCategory.OtherNotAssigned, "Table returns incorrect Unicode category"); return (uc); } @@ -467,9 +457,9 @@ namespace System.Globalization { internal static BidiCategory GetBidiCategory(String s, int index) { if (s==null) - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); if (((uint)index)>=((uint)s.Length)) { - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); } Contract.EndContractBlock(); return ((BidiCategory)InternalGetCategoryValue(InternalConvertToUtf32(s, index), BIDI_CATEGORY_OFFSET)); @@ -489,8 +479,8 @@ namespace System.Globalization { //////////////////////////////////////////////////////////////////////// internal static UnicodeCategory InternalGetUnicodeCategory(String value, int index) { - Contract.Assert(value != null, "value can not be null"); - Contract.Assert(index < value.Length, "index < value.Length"); + Debug.Assert(value != null, "value can not be null"); + Debug.Assert(index < value.Length, "index < value.Length"); return (InternalGetUnicodeCategory(InternalConvertToUtf32(value, index))); } @@ -503,15 +493,15 @@ namespace System.Globalization { //////////////////////////////////////////////////////////////////////// internal static UnicodeCategory InternalGetUnicodeCategory(String str, int index, out int charLength) { - Contract.Assert(str != null, "str can not be null"); - Contract.Assert(str.Length > 0, "str.Length > 0");; - Contract.Assert(index >= 0 && index < str.Length, "index >= 0 && index < str.Length"); + Debug.Assert(str != null, "str can not be null"); + Debug.Assert(str.Length > 0, "str.Length > 0");; + Debug.Assert(index >= 0 && index < str.Length, "index >= 0 && index < str.Length"); return (InternalGetUnicodeCategory(InternalConvertToUtf32(str, index, out charLength))); } internal static bool IsCombiningCategory(UnicodeCategory uc) { - Contract.Assert(uc >= 0, "uc >= 0"); + Debug.Assert(uc >= 0, "uc >= 0"); return ( uc == UnicodeCategory.NonSpacingMark || uc == UnicodeCategory.SpacingCombiningMark || diff --git a/src/mscorlib/src/System/Globalization/ChineseLunisolarCalendar.cs b/src/mscorlib/src/System/Globalization/ChineseLunisolarCalendar.cs index a5cf37f..6479152 100644 --- a/src/mscorlib/src/System/Globalization/ChineseLunisolarCalendar.cs +++ b/src/mscorlib/src/System/Globalization/ChineseLunisolarCalendar.cs @@ -331,12 +331,12 @@ namespace System.Globalization { internal override int GetGregorianYear(int year, int era) { if (era != CurrentEra && era != ChineseEra) { - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); } if (year < MIN_LUNISOLAR_YEAR || year > MAX_LUNISOLAR_YEAR) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR)); diff --git a/src/mscorlib/src/System/Globalization/CompareInfo.cs b/src/mscorlib/src/System/Globalization/CompareInfo.cs index 0b14f05..dcf1f32 100644 --- a/src/mscorlib/src/System/Globalization/CompareInfo.cs +++ b/src/mscorlib/src/System/Globalization/CompareInfo.cs @@ -32,6 +32,7 @@ namespace System.Globalization { using System.Security.Permissions; using Microsoft.Win32; using System.Security; + using System.Diagnostics; using System.Diagnostics.Contracts; // @@ -135,7 +136,7 @@ namespace System.Globalization { public static CompareInfo GetCompareInfo(int culture, Assembly assembly){ // Parameter checking. if (assembly == null) { - throw new ArgumentNullException("assembly"); + throw new ArgumentNullException(nameof(assembly)); } if (assembly!=typeof(Object).Module.Assembly) { throw new ArgumentException(Environment.GetResourceString("Argument_OnlyMscorlib")); @@ -161,7 +162,7 @@ namespace System.Globalization { // Assembly constructor should be deprecated, we don't act on the assembly information any more public static CompareInfo GetCompareInfo(String name, Assembly assembly){ if (name == null || assembly == null) { - throw new ArgumentNullException(name == null ? "name" : "assembly"); + throw new ArgumentNullException(name == null ? nameof(name) : nameof(assembly)); } Contract.EndContractBlock(); @@ -189,7 +190,7 @@ namespace System.Globalization { if (CultureData.IsCustomCultureId(culture)) { // Customized culture cannot be created by the LCID. - throw new ArgumentException(Environment.GetResourceString("Argument_CustomCultureCannotBePassedByNumber", "culture")); + throw new ArgumentException(Environment.GetResourceString("Argument_CustomCultureCannotBePassedByNumber", nameof(culture))); } return CultureInfo.GetCultureInfo(culture).CompareInfo; @@ -209,7 +210,7 @@ namespace System.Globalization { { if (name == null) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } Contract.EndContractBlock(); @@ -221,12 +222,11 @@ namespace System.Globalization { return(IsSortable(ch.ToString())); } - [System.Security.SecuritySafeCritical] [System.Runtime.InteropServices.ComVisible(false)] public static bool IsSortable(String text) { if (text == null) { // A null param is invalid here. - throw new ArgumentNullException("text"); + throw new ArgumentNullException(nameof(text)); } if (0 == text.Length) { @@ -291,7 +291,7 @@ namespace System.Globalization { #if FEATURE_USE_LCID // This is merely for serialization compatibility with Whidbey/Orcas, it can go away when we don't want that compat any more. culture = CultureInfo.GetCultureInfo(this.Name).LCID; // This is the lcid of the constructing culture (still have to dereference to get target sort) - Contract.Assert(m_name != null, "CompareInfo.OnSerializing - expected m_name to be set already"); + Debug.Assert(m_name != null, "CompareInfo.OnSerializing - expected m_name to be set already"); #endif } @@ -321,12 +321,7 @@ namespace System.Globalization { { get { - Contract.Assert(m_name != null, "CompareInfo.Name Expected m_name to be set"); - if (m_name == "zh-CHT" || m_name == "zh-CHS") - { - return m_name; - } - + Debug.Assert(m_name != null, "CompareInfo.Name Expected m_name to be set"); return (m_sortName); } } @@ -352,7 +347,7 @@ namespace System.Globalization { // some NLS VM functions can handle COMPARE_OPTIONS_ORDINAL // in which case options should be simply cast to int instead of using this function // Does not look like the best approach to me but for now I am going to leave it as it is - Contract.Assert(options != CompareOptions.OrdinalIgnoreCase, "[CompareInfo.GetNativeCompareFlags]CompareOptions.OrdinalIgnoreCase should be handled separately"); + Debug.Assert(options != CompareOptions.OrdinalIgnoreCase, "[CompareInfo.GetNativeCompareFlags]CompareOptions.OrdinalIgnoreCase should be handled separately"); // Use "linguistic casing" by default (load the culture's casing exception tables) int nativeCompareFlags = NORM_LINGUISTIC_CASING; @@ -367,7 +362,7 @@ namespace System.Globalization { // Suffix & Prefix shouldn't use this, make sure to turn off the NORM_LINGUISTIC_CASING flag if (options == CompareOptions.Ordinal) { nativeCompareFlags = COMPARE_OPTIONS_ORDINAL; } - Contract.Assert(((options & ~(CompareOptions.IgnoreCase | + Debug.Assert(((options & ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreKanaType | CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreSymbols | @@ -375,7 +370,7 @@ namespace System.Globalization { CompareOptions.StringSort)) == 0) || (options == CompareOptions.Ordinal), "[CompareInfo.GetNativeCompareFlags]Expected all flags to be handled"); - Contract.Assert((nativeCompareFlags & RESERVED_FIND_ASCII_STRING) == 0, "[CompareInfo.GetNativeCompareFlags] RESERVED_FIND_ASCII_STRING shouldn't be set here"); + Debug.Assert((nativeCompareFlags & RESERVED_FIND_ASCII_STRING) == 0, "[CompareInfo.GetNativeCompareFlags] RESERVED_FIND_ASCII_STRING shouldn't be set here"); return nativeCompareFlags; } @@ -398,7 +393,6 @@ namespace System.Globalization { return (Compare(string1, string2, CompareOptions.None)); } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe virtual int Compare(String string1, String string2, CompareOptions options){ if (options == CompareOptions.OrdinalIgnoreCase) @@ -411,14 +405,14 @@ namespace System.Globalization { { if (options != CompareOptions.Ordinal) { - throw new ArgumentException(Environment.GetResourceString("Argument_CompareOptionOrdinal"), "options"); + throw new ArgumentException(Environment.GetResourceString("Argument_CompareOptionOrdinal"), nameof(options)); } return String.CompareOrdinal(string1, string2); } if ((options & ValidCompareMaskOffFlags) != 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); } //Our paradigm is that null sorts less than any other string and @@ -469,7 +463,6 @@ namespace System.Globalization { } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe virtual int Compare(String string1, int offset1, int length1, String string2, int offset2, int length2, CompareOptions options) { if (options == CompareOptions.OrdinalIgnoreCase) @@ -483,31 +476,31 @@ namespace System.Globalization { // Verify inputs if (length1 < 0 || length2 < 0) { - throw new ArgumentOutOfRangeException((length1 < 0) ? "length1" : "length2", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); + throw new ArgumentOutOfRangeException((length1 < 0) ? nameof(length1) : nameof(length2), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); } if (offset1 < 0 || offset2 < 0) { - throw new ArgumentOutOfRangeException((offset1 < 0) ? "offset1" : "offset2", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); + throw new ArgumentOutOfRangeException((offset1 < 0) ? nameof(offset1) : nameof(offset2), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); } if (offset1 > (string1 == null ? 0 : string1.Length) - length1) { - throw new ArgumentOutOfRangeException("string1", Environment.GetResourceString("ArgumentOutOfRange_OffsetLength")); + throw new ArgumentOutOfRangeException(nameof(string1), Environment.GetResourceString("ArgumentOutOfRange_OffsetLength")); } if (offset2 > (string2 == null ? 0 : string2.Length) - length2) { - throw new ArgumentOutOfRangeException("string2", Environment.GetResourceString("ArgumentOutOfRange_OffsetLength")); + throw new ArgumentOutOfRangeException(nameof(string2), Environment.GetResourceString("ArgumentOutOfRange_OffsetLength")); } if ((options & CompareOptions.Ordinal) != 0) { if (options != CompareOptions.Ordinal) { throw new ArgumentException(Environment.GetResourceString("Argument_CompareOptionOrdinal"), - "options"); + nameof(options)); } } else if ((options & ValidCompareMaskOffFlags) != 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); } // @@ -546,11 +539,10 @@ namespace System.Globalization { //////////////////////////////////////////////////////////////////////// - [System.Security.SecuritySafeCritical] // auto-generated public unsafe virtual bool IsPrefix(String source, String prefix, CompareOptions options) { if (source == null || prefix == null) { - throw new ArgumentNullException((source == null ? "source" : "prefix"), + throw new ArgumentNullException((source == null ? nameof(source) : nameof(prefix)), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -572,7 +564,7 @@ namespace System.Globalization { } if ((options & ValidIndexMaskOffFlags) != 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); } @@ -601,11 +593,10 @@ namespace System.Globalization { //////////////////////////////////////////////////////////////////////// - [System.Security.SecuritySafeCritical] // auto-generated public unsafe virtual bool IsSuffix(String source, String suffix, CompareOptions options) { if (source == null || suffix == null) { - throw new ArgumentNullException((source == null ? "source" : "suffix"), + throw new ArgumentNullException((source == null ? nameof(source) : nameof(suffix)), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -625,7 +616,7 @@ namespace System.Globalization { } if ((options & ValidIndexMaskOffFlags) != 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); } // to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to @@ -659,7 +650,7 @@ namespace System.Globalization { public unsafe virtual int IndexOf(String source, char value) { if (source==null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); return IndexOf(source, value, 0, source.Length, CompareOptions.None); @@ -669,7 +660,7 @@ namespace System.Globalization { public unsafe virtual int IndexOf(String source, String value) { if (source==null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); return IndexOf(source, value, 0, source.Length, CompareOptions.None); @@ -679,7 +670,7 @@ namespace System.Globalization { public unsafe virtual int IndexOf(String source, char value, CompareOptions options) { if (source==null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); return IndexOf(source, value, 0, source.Length, options); @@ -689,7 +680,7 @@ namespace System.Globalization { public unsafe virtual int IndexOf(String source, String value, CompareOptions options) { if (source==null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); return IndexOf(source, value, 0, source.Length, options); @@ -699,7 +690,7 @@ namespace System.Globalization { public unsafe virtual int IndexOf(String source, char value, int startIndex) { if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); return IndexOf(source, value, startIndex, source.Length - startIndex, CompareOptions.None); @@ -709,7 +700,7 @@ namespace System.Globalization { public unsafe virtual int IndexOf(String source, String value, int startIndex) { if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); return IndexOf(source, value, startIndex, source.Length - startIndex, CompareOptions.None); @@ -719,7 +710,7 @@ namespace System.Globalization { public unsafe virtual int IndexOf(String source, char value, int startIndex, CompareOptions options) { if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); return IndexOf(source, value, startIndex, source.Length - startIndex, options); @@ -729,7 +720,7 @@ namespace System.Globalization { public unsafe virtual int IndexOf(String source, String value, int startIndex, CompareOptions options) { if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); return IndexOf(source, value, startIndex, source.Length - startIndex, options); @@ -747,18 +738,17 @@ namespace System.Globalization { return IndexOf(source, value, startIndex, count, CompareOptions.None); } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe virtual int IndexOf(String source, char value, int startIndex, int count, CompareOptions options) { // Validate inputs if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); if (startIndex < 0 || startIndex > source.Length) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); if (count < 0 || startIndex > source.Length - count) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); Contract.EndContractBlock(); if (options == CompareOptions.OrdinalIgnoreCase) @@ -769,7 +759,7 @@ namespace System.Globalization { // Validate CompareOptions // Ordinal can't be selected with other flags if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal)) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); // to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to // the sorting DLL API SortFindString so sorting DLL don't have to check if the string is Ascii with every call to SortFindString. @@ -780,18 +770,17 @@ namespace System.Globalization { } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe virtual int IndexOf(String source, String value, int startIndex, int count, CompareOptions options) { // Validate inputs if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); if (startIndex > source.Length) { - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); } Contract.EndContractBlock(); @@ -808,11 +797,11 @@ namespace System.Globalization { if (startIndex < 0) { - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); } if (count < 0 || startIndex > source.Length - count) - throw new ArgumentOutOfRangeException("count",Environment.GetResourceString("ArgumentOutOfRange_Count")); + throw new ArgumentOutOfRangeException(nameof(count),Environment.GetResourceString("ArgumentOutOfRange_Count")); if (options == CompareOptions.OrdinalIgnoreCase) { @@ -822,7 +811,7 @@ namespace System.Globalization { // Validate CompareOptions // Ordinal can't be selected with other flags if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal)) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); // to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to // the sorting DLL API SortFindString so sorting DLL don't have to check if the string is Ascii with every call to SortFindString. @@ -849,7 +838,7 @@ namespace System.Globalization { public unsafe virtual int LastIndexOf(String source, char value) { if (source==null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); // Can't start at negative index, so make sure we check for the length == 0 case. @@ -861,7 +850,7 @@ namespace System.Globalization { public virtual int LastIndexOf(String source, String value) { if (source==null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); // Can't start at negative index, so make sure we check for the length == 0 case. @@ -873,7 +862,7 @@ namespace System.Globalization { public virtual int LastIndexOf(String source, char value, CompareOptions options) { if (source==null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); // Can't start at negative index, so make sure we check for the length == 0 case. @@ -884,7 +873,7 @@ namespace System.Globalization { public unsafe virtual int LastIndexOf(String source, String value, CompareOptions options) { if (source==null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); // Can't start at negative index, so make sure we check for the length == 0 case. @@ -929,12 +918,11 @@ namespace System.Globalization { } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe virtual int LastIndexOf(String source, char value, int startIndex, int count, CompareOptions options) { // Verify Arguments if (source==null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); Contract.EndContractBlock(); // Validate CompareOptions @@ -942,7 +930,7 @@ namespace System.Globalization { if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal) && (options != CompareOptions.OrdinalIgnoreCase)) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); // Special case for 0 length input strings if (source.Length == 0 && (startIndex == -1 || startIndex == 0)) @@ -950,7 +938,7 @@ namespace System.Globalization { // Make sure we're not out of range if (startIndex < 0 || startIndex > source.Length) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); // Make sure that we allow startIndex == source.Length if (startIndex == source.Length) @@ -962,7 +950,7 @@ namespace System.Globalization { // 2nd have of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0. if (count < 0 || startIndex - count + 1 < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); if (options == CompareOptions.OrdinalIgnoreCase) { @@ -978,14 +966,13 @@ namespace System.Globalization { } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe virtual int LastIndexOf(String source, String value, int startIndex, int count, CompareOptions options) { // Verify Arguments if (source == null) - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); Contract.EndContractBlock(); // Validate CompareOptions @@ -993,7 +980,7 @@ namespace System.Globalization { if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal) && (options != CompareOptions.OrdinalIgnoreCase)) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); // Special case for 0 length input strings if (source.Length == 0 && (startIndex == -1 || startIndex == 0)) @@ -1001,7 +988,7 @@ namespace System.Globalization { // Make sure we're not out of range if (startIndex < 0 || startIndex > source.Length) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); // Make sure that we allow startIndex == source.Length if (startIndex == source.Length) @@ -1017,7 +1004,7 @@ namespace System.Globalization { // 2nd half of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0. if (count < 0 || startIndex - count + 1 < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); if (options == CompareOptions.OrdinalIgnoreCase) { @@ -1051,10 +1038,9 @@ namespace System.Globalization { return CreateSortKey(source, CompareOptions.None); } - [System.Security.SecuritySafeCritical] private SortKey CreateSortKey(String source, CompareOptions options) { - if (source==null) { throw new ArgumentNullException("source"); } + if (source==null) { throw new ArgumentNullException(nameof(source)); } Contract.EndContractBlock(); // Mask used to check if we have the right flags. @@ -1067,7 +1053,7 @@ namespace System.Globalization { if ((options & ValidSortkeyCtorMaskOffFlags) != 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); } byte[] keyData = null; // The OS doesn't have quite the same behavior so we have to test for empty inputs @@ -1088,7 +1074,7 @@ namespace System.Globalization { // If there was an error, return an error if (length == 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "source"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(source)); } // If input was empty, return the empty byte[] we made earlier and skip this @@ -1157,7 +1143,7 @@ namespace System.Globalization { { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (options == CompareOptions.Ordinal) @@ -1207,7 +1193,6 @@ namespace System.Globalization { return GetHashCodeOfString(source, options, false, 0); } - [System.Security.SecuritySafeCritical] // auto-generated internal int GetHashCodeOfString(string source, CompareOptions options, bool forceRandomizedHashing, long additionalEntropy) { // @@ -1215,12 +1200,12 @@ namespace System.Globalization { // if(null == source) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if ((options & ValidHashCodeOfStringMaskOffFlags) != 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), nameof(options)); } Contract.EndContractBlock(); @@ -1259,39 +1244,16 @@ namespace System.Globalization { } #endif - [System.Security.SecuritySafeCritical] internal static IntPtr InternalInitSortHandle(String localeName, out IntPtr handleOrigin) { return NativeInternalInitSortHandle(localeName, out handleOrigin); } -#if !FEATURE_CORECLR - private const int SORT_VERSION_WHIDBEY = 0x00001000; - private const int SORT_VERSION_V4 = 0x00060101; - - internal static bool IsLegacy20SortingBehaviorRequested - { - get - { - return InternalSortVersion == SORT_VERSION_WHIDBEY; - } - } - - private static uint InternalSortVersion - { - [System.Security.SecuritySafeCritical] - get - { - return InternalGetSortVersion(); - } - } - [OptionalField(VersionAdded = 3)] private SortVersion m_SortVersion; public SortVersion Version { - [SecuritySafeCritical] get { if(m_SortVersion == null) @@ -1306,38 +1268,27 @@ namespace System.Globalization { } } - [System.Security.SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool InternalGetNlsVersionEx(IntPtr handle, IntPtr handleOrigin, String localeName, ref Win32Native.NlsVersionInfoEx lpNlsVersionInformation); - [System.Security.SecurityCritical] - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - private static extern uint InternalGetSortVersion(); - -#endif - [System.Security.SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern IntPtr NativeInternalInitSortHandle(String localeName, out IntPtr handleOrigin); // Get a locale sensitive sort hash code from native code -- COMNlsInfo::InternalGetGlobalizedHashCode - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern int InternalGetGlobalizedHashCode(IntPtr handle, IntPtr handleOrigin, string localeName, string source, int length, int dwFlags, bool forceRandomizedHashing, long additionalEntropy); // Use native API calls to see if this string is entirely defined -- COMNlsInfo::InternalIsSortable - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool InternalIsSortable(IntPtr handle, IntPtr handleOrigin, String localeName, String source, int length); // Compare a string using the native API calls -- COMNlsInfo::InternalCompareString - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern int InternalCompareString(IntPtr handle, IntPtr handleOrigin, String localeName, String string1, int offset1, int length1, @@ -1345,13 +1296,11 @@ namespace System.Globalization { // InternalFindNLSStringEx parameters is not exactly matching kernel32::FindNLSStringEx parameters. // Call through to NewApis::FindNLSStringEx so we can get the right behavior - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern int InternalFindNLSStringEx(IntPtr handle, IntPtr handleOrigin, String localeName, int flags, String source, int sourceCount, int startIndex, string target, int targetCount); // Call through to NewAPis::LCMapStringEx so we can get appropriate behavior for all platforms - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern int InternalGetSortKey(IntPtr handle, IntPtr handleOrigin, String localeName, int flags, String source, int sourceCount, byte[] target, int targetCount); diff --git a/src/mscorlib/src/System/Globalization/CultureData.cs b/src/mscorlib/src/System/Globalization/CultureData.cs index ae1eeea..0bcb796 100644 --- a/src/mscorlib/src/System/Globalization/CultureData.cs +++ b/src/mscorlib/src/System/Globalization/CultureData.cs @@ -10,13 +10,10 @@ namespace System.Globalization using System.Collections.Generic; using System.Text; using System.Threading; -#if !FEATURE_CORECLR - using System.Reflection; - using System.Resources; -#endif using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Security; @@ -451,8 +448,8 @@ namespace System.Globalization invariant.iDefaultOemCodePage = 437; // default oem code page ID (OCP or OEM) invariant.iDefaultMacCodePage = 10000; // default macintosh code page invariant.iDefaultEbcdicCodePage = 037; // default EBCDIC code page - invariant.sAbbrevLang = "IVL"; // abbreviated language name (Windows Language Name) - invariant.sAbbrevCountry = "IVC"; // abbreviated country name (RegionInfo) (Windows Region Name) + invariant.sAbbrevLang = "IVL"; // abbreviated language name (Windows Language Name) + invariant.sAbbrevCountry = "IVC"; // abbreviated country name (RegionInfo) (Windows Region Name) invariant.sISO639Language2 = "ivl"; // 3 char ISO 639 lang name 2 invariant.sISO3166CountryName2 = "ivc"; // 3 char ISO 3166 country name 2 2(RegionInfo) invariant.iInputLanguageHandle = 0x007f; // input language handle @@ -466,23 +463,6 @@ namespace System.Globalization } private volatile static CultureData s_Invariant; - -#if !FEATURE_CORECLR - internal static volatile ResourceSet MscorlibResourceSet; -#endif - -#if !FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - private static bool IsResourcePresent(String resourceKey) - { - if (MscorlibResourceSet == null) - { - MscorlibResourceSet = new ResourceSet(typeof(Environment).Assembly.GetManifestResourceStream("mscorlib.resources")); - } - return MscorlibResourceSet.GetString(resourceKey) != null; - } -#endif - /////////////// // Constructors // /////////////// @@ -549,13 +529,7 @@ namespace System.Globalization // Ask native code if that one's real if (culture.InitCultureData() == false) { -#if !FEATURE_CORECLR - if (culture.InitCompatibilityCultureData() == false - && culture.InitLegacyAlternateSortData() == false) -#endif - { - return null; - } + return null; } return culture; @@ -567,142 +541,12 @@ namespace System.Globalization { return false; } - -#if !FEATURE_CORECLR - if (CultureInfo.IsTaiwanSku) - { - TreatTaiwanParentChainAsHavingTaiwanAsSpecific(); - } -#endif - return true; - } - -#if !FEATURE_CORECLR - [System.Security.SecuritySafeCritical] - private void TreatTaiwanParentChainAsHavingTaiwanAsSpecific() - { - if (IsNeutralInParentChainOfTaiwan() && IsOsPriorToWin7() && !IsReplacementCulture) - { - // force population of fields that should have information that is - // different than zh-TW: - string s = SNATIVELANGUAGE; - s = SENGLISHLANGUAGE; - s = SLOCALIZEDLANGUAGE; - s = STEXTINFO; - s = SCOMPAREINFO; - s = FONTSIGNATURE; - int i = IDEFAULTANSICODEPAGE; - i = IDEFAULTOEMCODEPAGE; - i = IDEFAULTMACCODEPAGE; - - this.sSpecificCulture = "zh-TW"; - this.sWindowsName = "zh-TW"; - } - } - - private bool IsNeutralInParentChainOfTaiwan() - { - return this.sRealName == "zh" || this.sRealName == "zh-Hant"; - } - - static readonly Version s_win7Version = new Version(6, 1); - static private bool IsOsPriorToWin7() - { - return Environment.OSVersion.Platform == PlatformID.Win32NT && - Environment.OSVersion.Version < s_win7Version; - } - static private bool IsOsWin7OrPrior() - { - return Environment.OSVersion.Platform == PlatformID.Win32NT && - Environment.OSVersion.Version < new Version(6, 2); // Win7 is 6.1.Build.Revision so we have to check for anything less than 6.2 - } - - private bool InitCompatibilityCultureData() - { - // for compatibility handle the deprecated ids: zh-chs, zh-cht - string cultureName = this.sRealName; - - string fallbackCultureName; - string realCultureName; - switch (AnsiToLower(cultureName)) - { - case "zh-chs": - fallbackCultureName = "zh-Hans"; - realCultureName = "zh-CHS"; - break; - case "zh-cht": - fallbackCultureName = "zh-Hant"; - realCultureName = "zh-CHT"; - break; - default: - return false; - } - - this.sRealName = fallbackCultureName; - if (InitCultureData() == false) - { - return false; - } - // fixup our data - this.sName = realCultureName; // the name that goes back to the user - this.sParent = fallbackCultureName; - this.bFramework = true; - - return true; - } - - private bool InitLegacyAlternateSortData() - { - if (!CompareInfo.IsLegacy20SortingBehaviorRequested) - { - return false; - } - - // For V2 compatibility, handle deprecated alternate sorts - string cultureName = this.sRealName; - - switch (AnsiToLower(cultureName)) - { - case "ko-kr_unicod": - cultureName = "ko-KR_unicod"; - this.sRealName = "ko-KR"; - this.iLanguage = 0x00010412; - break; - case "ja-jp_unicod": - cultureName = "ja-JP_unicod"; - this.sRealName = "ja-JP"; - this.iLanguage = 0x00010411; - break; - case "zh-hk_stroke": - cultureName = "zh-HK_stroke"; - this.sRealName = "zh-HK"; - this.iLanguage = 0x00020c04; - break; - default: - return false; - } - - if (nativeInitCultureData(this) == false) - { - return false; - } - - this.sRealName = cultureName; - this.sCompareInfo = cultureName; - this.bFramework = true; - return true; } -#if FEATURE_WIN32_REGISTRY - private static String s_RegionKey = @"System\CurrentControlSet\Control\Nls\RegionMapping"; -#endif // FEATURE_WIN32_REGISTRY - -#endif // !FEATURE_CORECLR // Cache of regions we've already looked up private static volatile Dictionary s_cachedRegions; - [System.Security.SecurityCritical] // auto-generated internal static CultureData GetCultureDataForRegion(String cultureName, bool useUserOverride) { // First do a shortcut for Invariant @@ -749,41 +593,6 @@ namespace System.Globalization // // Not found in the hash table, look it up the hard way // -#if !FEATURE_CORECLR -#if FEATURE_WIN32_REGISTRY - // First try the registry in case there are overrides of our table - try - { - // Open in read-only mode. - // Use InternalOpenSubKey so that we avoid the security check. - Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.InternalOpenSubKey(s_RegionKey, false); - - if (key != null) - { - try - { - Object value = key.InternalGetValue(cultureName, null, false, false); - - if (value != null) - { - // Get the name of the locale to try. - String specificForRegion = value.ToString(); - - // See if it's real - retVal = GetCultureData(specificForRegion, useUserOverride); - } - } - finally - { - key.Close(); - } - } - } - // If this fails for any reason, we'll just ignore it, likely it just isn't there. - catch (ObjectDisposedException) { } - catch (ArgumentException) { } -#endif // FEATURE_WIN32_REGISTRY -#endif // !FEATURE_CORECLR // If not a valid mapping from the registry we'll have to try the hard coded table if (retVal == null || (retVal.IsNeutralCulture == true)) @@ -841,7 +650,6 @@ namespace System.Globalization #if FEATURE_USE_LCID // Obtain locale name from LCID // NOTE: This will get neutral names, unlike the OS API - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern String LCIDToLocaleName(int lcid); @@ -851,25 +659,6 @@ namespace System.Globalization String localeName = null; CultureData retVal = null; -#if !FEATURE_CORECLR - // If V2 legacy sort is requested, then provide deprecated alternate sorts - if (CompareInfo.IsLegacy20SortingBehaviorRequested) - { - switch (culture) - { - case 0x00010412: - localeName = "ko-KR_unicod"; - break; - case 0x00010411: - localeName = "ja-JP_unicod"; - break; - case 0x00020c04: - localeName = "zh-HK_stroke"; - break; - } - } -#endif - if (localeName == null) { // Convert the lcid to a name, then use that @@ -886,19 +675,6 @@ namespace System.Globalization } else { -#if !FEATURE_CORECLR - switch (localeName) - { - // for compatibility with Whidbey, when requesting - // a locale from LCID, return the old localeName - case "zh-Hans": - localeName = "zh-CHS"; - break; - case "zh-Hant": - localeName = "zh-CHT"; - break; - } -#endif // Valid name, use it retVal = GetCultureData(localeName, bUseUserOverride); } @@ -906,7 +682,7 @@ namespace System.Globalization // If not successful, throw if (retVal == null) throw new CultureNotFoundException( - "culture", culture, Environment.GetResourceString("Argument_CultureNotSupported")); + nameof(culture), culture, Environment.GetResourceString("Argument_CultureNotSupported")); // Return the one we found return retVal; @@ -921,7 +697,6 @@ namespace System.Globalization s_replacementCultureNames = null; } - [System.Security.SecuritySafeCritical] // auto-generated internal static CultureInfo[] GetCultures(CultureTypes types) { // Disable warning 618: System.Globalization.CultureTypes.FrameworkCultures' is obsolete @@ -933,7 +708,7 @@ namespace System.Globalization CultureTypes.FrameworkCultures)) != 0) { throw new ArgumentOutOfRangeException( - "types", + nameof(types), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), CultureTypes.NeutralCultures, CultureTypes.FrameworkCultures)); @@ -972,25 +747,12 @@ namespace System.Globalization int arrayLength = cultureNames.Length; - if ((types & (CultureTypes.NeutralCultures | CultureTypes.FrameworkCultures)) != 0) // add zh-CHT and zh-CHS - { - arrayLength += 2; - } - CultureInfo[] cultures = new CultureInfo[arrayLength]; for (int i = 0; i < cultureNames.Length; i++) { cultures[i] = new CultureInfo(cultureNames[i]); } - - if ((types & (CultureTypes.NeutralCultures | CultureTypes.FrameworkCultures)) != 0) // add zh-CHT and zh-CHS - { - Contract.Assert(arrayLength == cultureNames.Length + 2, "CultureData.nativeEnumCultureNames() Incorrect array size"); - cultures[cultureNames.Length] = new CultureInfo("zh-CHS"); - cultures[cultureNames.Length + 1] = new CultureInfo("zh-CHT"); - } - #pragma warning restore 618 return cultures; @@ -1028,10 +790,9 @@ namespace System.Globalization //////////////////////////////////////////////////////////////////////// - [System.Security.SecuritySafeCritical] // auto-generated private static bool IsReplacementCultureName(String name) { - Contract.Assert(name != null, "IsReplacementCultureName(): name should not be null"); + Debug.Assert(name != null, "IsReplacementCultureName(): name should not be null"); String[] replacementCultureNames = s_replacementCultureNames; if (replacementCultureNames == null) { @@ -1041,7 +802,7 @@ namespace System.Globalization } // Even if we don't have any replacement cultures, the returned replacementCultureNames will still an empty string array, not null. - Contract.Assert(name != null, "IsReplacementCultureName(): replacementCultureNames should not be null"); + Debug.Assert(name != null, "IsReplacementCultureName(): replacementCultureNames should not be null"); Array.Sort(replacementCultureNames); s_replacementCultureNames = replacementCultureNames; } @@ -1065,7 +826,7 @@ namespace System.Globalization { get { - Contract.Assert(this.sRealName != null, "[CultureData.CultureName] Expected this.sRealName to be populated by COMNlsInfo::nativeInitCultureData already"); + Debug.Assert(this.sRealName != null, "[CultureData.CultureName] Expected this.sRealName to be populated by COMNlsInfo::nativeInitCultureData already"); // since windows doesn't know about zh-CHS and zh-CHT, // we leave sRealName == zh-Hanx but we still need to // pretend that it was zh-CHX. @@ -1093,7 +854,7 @@ namespace System.Globalization { get { - // Contract.Assert(this.sName != null, + // Debug.Assert(this.sName != null, // "[CultureData.SNAME] Expected this.sName to be populated by COMNlsInfo::nativeInitCultureData already"); if (this.sName == null) { @@ -1106,31 +867,12 @@ namespace System.Globalization // Parent name (which may be a custom locale/culture) internal String SPARENT { - [System.Security.SecurityCritical] // auto-generated get { if (this.sParent == null) { // Ask using the real name, so that we get parents of neutrals this.sParent = DoGetLocaleInfo(this.sRealName, LOCALE_SPARENT); - -#if !FEATURE_CORECLR - // for compatibility, the chain should be: - // zh-CN -> zh-CHS -> zh-Hans -> zh - // zh-TW -> zh-CHT -> zh-Hant -> zh - Contract.Assert(this.sName != "zh-CHS" && this.sName != "zh-CHT", - "sParent should have been initialized for zh-CHS and zh-CHT when they were constructed, otherwise we get recursion"); - switch (this.sParent) - { - case "zh-Hans": - this.sParent = "zh-CHS"; - break; - case "zh-Hant": - this.sParent = "zh-CHT"; - break; - } -#endif - } return this.sParent; } @@ -1139,18 +881,10 @@ namespace System.Globalization // Localized pretty name for this locale (ie: Inglis (estados Unitos)) internal String SLOCALIZEDDISPLAYNAME { - [System.Security.SecurityCritical] // auto-generated get { if (this.sLocalizedDisplayName == null) { -#if !FEATURE_CORECLR - String resourceKey = "Globalization.ci_" + this.sName; - if (IsResourcePresent(resourceKey)) - { - this.sLocalizedDisplayName = Environment.GetResourceString(resourceKey); - } -#endif // If it hasn't been found (Windows 8 and up), fallback to the system if (String.IsNullOrEmpty(this.sLocalizedDisplayName)) { @@ -1180,7 +914,6 @@ namespace System.Globalization // English pretty name for this locale (ie: English (United States)) internal String SENGDISPLAYNAME { - [System.Security.SecurityCritical] // auto-generated get { if (this.sEnglishDisplayName == null) @@ -1189,17 +922,6 @@ namespace System.Globalization if (this.IsNeutralCulture) { this.sEnglishDisplayName = this.SENGLISHLANGUAGE; -#if !FEATURE_CORECLR - // differentiate the legacy display names - switch (this.sName) - { - case "zh-CHS": - case "zh-CHT": - this.sEnglishDisplayName += " Legacy"; - break; - } -#endif - } else { @@ -1233,7 +955,6 @@ namespace System.Globalization // Native pretty name for this locale (ie: Deutsch (Deutschland)) internal String SNATIVEDISPLAYNAME { - [System.Security.SecurityCritical] // auto-generated get { if (this.sNativeDisplayName == null) @@ -1242,32 +963,10 @@ namespace System.Globalization if (this.IsNeutralCulture) { this.sNativeDisplayName = this.SNATIVELANGUAGE; -#if !FEATURE_CORECLR - // differentiate the legacy display names - switch (this.sName) - { - case "zh-CHS": - this.sNativeDisplayName += " \u65E7\u7248"; - break; - case "zh-CHT": - this.sNativeDisplayName += " \u820A\u7248"; - break; - } -#endif } else { -#if !FEATURE_CORECLR - if (IsIncorrectNativeLanguageForSinhala()) - { - // work around bug in Windows 7 for native name of Sinhala - this.sNativeDisplayName ="\x0dc3\x0dd2\x0d82\x0dc4\x0dbd (\x0DC1\x0DCA\x200D\x0DBB\x0DD3\x0020\x0DBD\x0D82\x0D9A\x0DCF)"; - } - else -#endif - { - this.sNativeDisplayName = DoGetLocaleInfo(LOCALE_SNATIVEDISPLAYNAME); - } + this.sNativeDisplayName = DoGetLocaleInfo(LOCALE_SNATIVEDISPLAYNAME); // if it isn't found build one: if (String.IsNullOrEmpty(this.sNativeDisplayName)) @@ -1287,7 +986,7 @@ namespace System.Globalization get { // This got populated when ComNlsInfo::nativeInitCultureData told us we had a culture - Contract.Assert(this.sSpecificCulture != null, "[CultureData.SSPECIFICCULTURE] Expected this.sSpecificCulture to be populated by COMNlsInfo::nativeInitCultureData already"); + Debug.Assert(this.sSpecificCulture != null, "[CultureData.SSPECIFICCULTURE] Expected this.sSpecificCulture to be populated by COMNlsInfo::nativeInitCultureData already"); return this.sSpecificCulture; } } @@ -1299,7 +998,6 @@ namespace System.Globalization // iso 639 language name, ie: en internal String SISO639LANGNAME { - [System.Security.SecurityCritical] // auto-generated get { if (this.sISO639Language == null) @@ -1313,7 +1011,6 @@ namespace System.Globalization // iso 639 language name, ie: eng internal String SISO639LANGNAME2 { - [System.Security.SecurityCritical] // auto-generated get { if (this.sISO639Language2 == null) @@ -1327,7 +1024,6 @@ namespace System.Globalization // abbreviated windows language name (ie: enu) (non-standard, avoid this) internal String SABBREVLANGNAME { - [System.Security.SecurityCritical] // auto-generated get { if (this.sAbbrevLang == null) @@ -1342,7 +1038,6 @@ namespace System.Globalization // This is only valid for Windows 8 and higher neutrals: internal String SLOCALIZEDLANGUAGE { - [System.Security.SecurityCritical] // auto-generated get { if (this.sLocalizedLanguage == null) @@ -1365,7 +1060,6 @@ namespace System.Globalization // English name for this language (Windows Only) ie: German internal String SENGLISHLANGUAGE { - [System.Security.SecurityCritical] // auto-generated get { if (this.sEnglishLanguage == null) @@ -1379,18 +1073,10 @@ namespace System.Globalization // Native name of this language (Windows Only) ie: Deutsch internal String SNATIVELANGUAGE { - [System.Security.SecurityCritical] // auto-generated get { if (this.sNativeLanguage == null) { -#if !FEATURE_CORECLR - if (IsIncorrectNativeLanguageForSinhala()) - { - this.sNativeLanguage = "\x0dc3\x0dd2\x0d82\x0dc4\x0dbd"; - } - else -#endif { this.sNativeLanguage = DoGetLocaleInfo(LOCALE_SNATIVELANGUAGENAME); } @@ -1399,15 +1085,6 @@ namespace System.Globalization } } -#if !FEATURE_CORECLR - private bool IsIncorrectNativeLanguageForSinhala() - { - return IsOsWin7OrPrior() - && (sName == "si-LK" || sName == "si") - && !IsReplacementCulture; - } -#endif - /////////// // Region // /////////// @@ -1415,7 +1092,6 @@ namespace System.Globalization // region name (eg US) internal String SREGIONNAME { - [System.Security.SecurityCritical] // auto-generated get { if (this.sRegionName == null) @@ -1451,18 +1127,10 @@ namespace System.Globalization // localized name for the country internal string SLOCALIZEDCOUNTRY { - [System.Security.SecurityCritical] // auto-generated get { if (this.sLocalizedCountry == null) { -#if !FEATURE_CORECLR - String resourceKey = "Globalization.ri_" + this.SREGIONNAME; - if (IsResourcePresent(resourceKey)) - { - this.sLocalizedCountry = Environment.GetResourceString(resourceKey); - } -#endif // If it hasn't been found (Windows 8 and up), fallback to the system if (String.IsNullOrEmpty(this.sLocalizedCountry)) { @@ -1484,7 +1152,6 @@ namespace System.Globalization // english country name (RegionInfo) ie: Germany internal String SENGCOUNTRY { - [System.Security.SecurityCritical] // auto-generated get { if (this.sEnglishCountry == null) @@ -1498,7 +1165,6 @@ namespace System.Globalization // native country name (RegionInfo) ie: Deutschland internal String SNATIVECOUNTRY { - [System.Security.SecurityCritical] // auto-generated get { if (this.sNativeCountry == null) @@ -1512,7 +1178,6 @@ namespace System.Globalization // ISO 3166 Country Name internal String SISO3166CTRYNAME { - [System.Security.SecurityCritical] // auto-generated get { if (this.sISO3166CountryName == null) @@ -1526,7 +1191,6 @@ namespace System.Globalization // ISO 3166 Country Name internal String SISO3166CTRYNAME2 { - [System.Security.SecurityCritical] // auto-generated get { if (this.sISO3166CountryName2 == null) @@ -1540,7 +1204,6 @@ namespace System.Globalization // abbreviated Country Name (windows version, non-standard, avoid) internal String SABBREVCTRYNAME { - [System.Security.SecurityCritical] // auto-generated get { if (this.sAbbrevCountry == null) @@ -1584,7 +1247,6 @@ namespace System.Globalization // Console fallback name (ie: locale to use for console apps for unicode-only locales) internal String SCONSOLEFALLBACKNAME { - [System.Security.SecurityCritical] // auto-generated get { if (this.sConsoleFallbackName == null) @@ -1624,7 +1286,6 @@ namespace System.Globalization // (user can override) grouping of digits internal int[] WAGROUPING { - [System.Security.SecurityCritical] // auto-generated get { if (this.waGrouping == null || UseUserOverride) @@ -1642,7 +1303,6 @@ namespace System.Globalization // Not a Number internal String SNAN { - [System.Security.SecurityCritical] // auto-generated get { if (this.sNaN == null) @@ -1656,7 +1316,6 @@ namespace System.Globalization // + Infinity internal String SPOSINFINITY { - [System.Security.SecurityCritical] // auto-generated get { if (this.sPositiveInfinity == null) @@ -1670,7 +1329,6 @@ namespace System.Globalization // - Infinity internal String SNEGINFINITY { - [System.Security.SecurityCritical] // auto-generated get { if (this.sNegativeInfinity == null) @@ -1717,7 +1375,6 @@ namespace System.Globalization // Percent (%) symbol internal String SPERCENT { - [System.Security.SecurityCritical] // auto-generated get { if (this.sPercent == null) @@ -1732,7 +1389,6 @@ namespace System.Globalization // PerMille (‰) symbol internal String SPERMILLE { - [System.Security.SecurityCritical] // auto-generated get { if (this.sPerMille == null) @@ -1751,7 +1407,6 @@ namespace System.Globalization // (user can override) local monetary symbol, eg: $ internal String SCURRENCY { - [System.Security.SecurityCritical] // auto-generated get { if (this.sCurrency == null || UseUserOverride) @@ -1765,7 +1420,6 @@ namespace System.Globalization // international monetary symbol (RegionInfo), eg: USD internal String SINTLSYMBOL { - [System.Security.SecurityCritical] // auto-generated get { if (this.sIntlMonetarySymbol == null) @@ -1779,7 +1433,6 @@ namespace System.Globalization // English name for this currency (RegionInfo), eg: US Dollar internal String SENGLISHCURRENCY { - [System.Security.SecurityCritical] // auto-generated get { if (this.sEnglishCurrency == null) @@ -1793,7 +1446,6 @@ namespace System.Globalization // Native name for this currency (RegionInfo), eg: Schweiz Frank internal String SNATIVECURRENCY { - [System.Security.SecurityCritical] // auto-generated get { if (this.sNativeCurrency == null) @@ -1811,7 +1463,6 @@ namespace System.Globalization // (user can override) monetary grouping of digits internal int[] WAMONGROUPING { - [System.Security.SecurityCritical] // auto-generated get { if (this.waMonetaryGrouping == null || UseUserOverride) @@ -1845,7 +1496,6 @@ namespace System.Globalization // (user can override) list Separator internal String SLIST { - [System.Security.SecurityCritical] // auto-generated get { if (this.sListSeparator == null || UseUserOverride) @@ -1872,7 +1522,6 @@ namespace System.Globalization // (user can override) AM designator internal String SAM1159 { - [System.Security.SecurityCritical] // auto-generated get { if (this.sAM1159 == null || UseUserOverride) @@ -1886,7 +1535,6 @@ namespace System.Globalization // (user can override) PM designator internal String SPM2359 { - [System.Security.SecurityCritical] // auto-generated get { if (this.sPM2359 == null || UseUserOverride) @@ -2067,7 +1715,6 @@ namespace System.Globalization // time duration format internal String[] SADURATION { - [System.Security.SecurityCritical] // auto-generated get { if (this.saDurationFormats == null) @@ -2198,7 +1845,7 @@ namespace System.Globalization // We then have to copy that list to a new array of the right size. // Default calendar should be first int[] calendarInts = new int[23]; - Contract.Assert(this.sWindowsName != null, "[CultureData.CalendarIds] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); + Debug.Assert(this.sWindowsName != null, "[CultureData.CalendarIds] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); int count = CalendarData.nativeGetCalendars(this.sWindowsName, this.bUseOverrides, calendarInts); // See if we had a calendar to add. @@ -2243,7 +1890,6 @@ namespace System.Globalization // Want 1st calendar to be default // Prior to Vista the enumeration didn't have default calendar first // Only a coreclr concern, culture.dll does the right thing. -#if FEATURE_CORECLR if (temp.Length > 1) { int i = DoGetLocaleInfoInt(LOCALE_ICALENDARTYPE); @@ -2253,7 +1899,6 @@ namespace System.Globalization temp[0] = i; } } -#endif this.waCalendars = temp; } @@ -2272,7 +1917,7 @@ namespace System.Globalization internal CalendarData GetCalendar(int calendarId) { - Contract.Assert(calendarId > 0 && calendarId <= CalendarData.MAX_CALENDARS, + Debug.Assert(calendarId > 0 && calendarId <= CalendarData.MAX_CALENDARS, "[CultureData.GetCalendar] Expect calendarId to be in a valid range"); // arrays are 0 based, calendarIds are 1 based @@ -2291,16 +1936,8 @@ namespace System.Globalization // Make sure that calendar has data if (calendarData == null || UseUserOverride) { - Contract.Assert(this.sWindowsName != null, "[CultureData.GetCalendar] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); + Debug.Assert(this.sWindowsName != null, "[CultureData.GetCalendar] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); calendarData = new CalendarData(this.sWindowsName, calendarId, this.UseUserOverride); -#if !FEATURE_CORECLR - //Work around issue where Win7 data for MonthDay contains invalid two sets of data separated by semicolon - //even though MonthDay is not enumerated - if (IsOsWin7OrPrior() && !IsSupplementalCustomCulture && !IsReplacementCulture) - { - calendarData.FixupWin7MonthDaySemicolonBug(); - } -#endif calendars[calendarIndex] = calendarData; } @@ -2344,7 +1981,7 @@ namespace System.Globalization { if (this.iReadingLayout == undef) { - Contract.Assert(this.sRealName != null, "[CultureData.IsRightToLeft] Expected this.sRealName to be populated by COMNlsInfo::nativeInitCultureData already"); + Debug.Assert(this.sRealName != null, "[CultureData.IsRightToLeft] Expected this.sRealName to be populated by COMNlsInfo::nativeInitCultureData already"); this.iReadingLayout = DoGetLocaleInfoInt(LOCALE_IREADINGLAYOUT); } @@ -2361,7 +1998,6 @@ namespace System.Globalization // es-ES_tradnl -> es-ES internal String STEXTINFO // Text info name to use for text information { - [System.Security.SecuritySafeCritical] get { if (this.sTextInfo == null) @@ -2387,7 +2023,6 @@ namespace System.Globalization // Compare info name (including sorting key) to use if custom internal String SCOMPAREINFO { - [System.Security.SecuritySafeCritical] get { if (this.sCompareInfo == null) @@ -2423,7 +2058,6 @@ namespace System.Globalization private String SSCRIPTS { - [System.Security.SecuritySafeCritical] // auto-generated get { if (this.sScripts == null) @@ -2436,7 +2070,6 @@ namespace System.Globalization private String SOPENTYPELANGUAGETAG { - [System.Security.SecuritySafeCritical] // auto-generated get { return DoGetLocaleInfo(LOCALE_SOPENTYPELANGUAGETAG); @@ -2445,7 +2078,6 @@ namespace System.Globalization private String FONTSIGNATURE { - [System.Security.SecuritySafeCritical] // auto-generated get { if (this.fontSignature == null) @@ -2458,7 +2090,6 @@ namespace System.Globalization private String SKEYBOARDSTOINSTALL { - [System.Security.SecuritySafeCritical] // auto-generated get { return DoGetLocaleInfo(LOCALE_SKEYBOARDSTOINSTALL); @@ -2516,7 +2147,6 @@ namespace System.Globalization // Obtain locale name from LCID // NOTE: This will get neutral names, unlike the OS API - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern int LocaleNameToLCID(String localeName); @@ -2528,7 +2158,7 @@ namespace System.Globalization { if (this.iLanguage == 0) { - Contract.Assert(this.sRealName != null, "[CultureData.ILANGUAGE] Expected this.sRealName to be populated by COMNlsInfo::nativeInitCultureData already"); + Debug.Assert(this.sRealName != null, "[CultureData.ILANGUAGE] Expected this.sRealName to be populated by COMNlsInfo::nativeInitCultureData already"); this.iLanguage = LocaleNameToLCID(this.sRealName); } return this.iLanguage; @@ -2584,21 +2214,21 @@ namespace System.Globalization // All of our era names internal String[] EraNames(int calendarId) { - Contract.Assert(calendarId > 0, "[CultureData.saEraNames] Expected Calendar.ID > 0"); + Debug.Assert(calendarId > 0, "[CultureData.saEraNames] Expected Calendar.ID > 0"); return this.GetCalendar(calendarId).saEraNames; } internal String[] AbbrevEraNames(int calendarId) { - Contract.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0"); + Debug.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0"); return this.GetCalendar(calendarId).saAbbrevEraNames; } internal String[] AbbreviatedEnglishEraNames(int calendarId) { - Contract.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0"); + Debug.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0"); return this.GetCalendar(calendarId).saAbbrevEnglishEraNames; } @@ -2610,7 +2240,6 @@ namespace System.Globalization // Time separator (derived from time format) internal String TimeSeparator { - [System.Security.SecuritySafeCritical] // auto-generated get { if (sTimeSeparator == null || UseUserOverride) @@ -2856,8 +2485,8 @@ namespace System.Globalization private static int IndexOfTimePart(string format, int startIndex, string timeParts) { - Contract.Assert(startIndex >= 0, "startIndex cannot be negative"); - Contract.Assert(timeParts.IndexOfAny(new char[] { '\'', '\\' }) == -1, "timeParts cannot include quote characters"); + Debug.Assert(startIndex >= 0, "startIndex cannot be negative"); + Debug.Assert(timeParts.IndexOfAny(new char[] { '\'', '\\' }) == -1, "timeParts cannot include quote characters"); bool inQuote = false; for (int i = startIndex; i < format.Length; ++i) { @@ -2892,16 +2521,14 @@ namespace System.Globalization return -1; } - [System.Security.SecurityCritical] string DoGetLocaleInfo(uint lctype) { - Contract.Assert(this.sWindowsName != null, "[CultureData.DoGetLocaleInfo] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); + Debug.Assert(this.sWindowsName != null, "[CultureData.DoGetLocaleInfo] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); return DoGetLocaleInfo(this.sWindowsName, lctype); } // For LOCALE_SPARENT we need the option of using the "real" name (forcing neutral names) instead of the // "windows" name, which can be specific for downlevel (< windows 7) os's. - [System.Security.SecurityCritical] // auto-generated string DoGetLocaleInfo(string localeName, uint lctype) { // Fix lctype if we don't want overrides @@ -2911,7 +2538,7 @@ namespace System.Globalization } // Ask OS for data - Contract.Assert(localeName != null, "[CultureData.DoGetLocaleInfo] Expected localeName to be not be null"); + Debug.Assert(localeName != null, "[CultureData.DoGetLocaleInfo] Expected localeName to be not be null"); string result = CultureInfo.nativeGetLocaleInfoEx(localeName, lctype); if (result == null) { @@ -2932,7 +2559,7 @@ namespace System.Globalization // Ask OS for data, note that we presume it returns success, so we have to know that // sWindowsName is valid before calling. - Contract.Assert(this.sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); + Debug.Assert(this.sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); int result = CultureInfo.nativeGetLocaleInfoExInt(this.sWindowsName, lctype); return result; @@ -2941,7 +2568,7 @@ namespace System.Globalization String[] DoEnumTimeFormats() { // Note that this gets overrides for us all the time - Contract.Assert(this.sWindowsName != null, "[CultureData.DoEnumTimeFormats] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); + Debug.Assert(this.sWindowsName != null, "[CultureData.DoEnumTimeFormats] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); String[] result = ReescapeWin32Strings(nativeEnumTimeFormats(this.sWindowsName, 0, UseUserOverride)); return result; @@ -2950,7 +2577,7 @@ namespace System.Globalization String[] DoEnumShortTimeFormats() { // Note that this gets overrides for us all the time - Contract.Assert(this.sWindowsName != null, "[CultureData.DoEnumShortTimeFormats] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); + Debug.Assert(this.sWindowsName != null, "[CultureData.DoEnumShortTimeFormats] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); String[] result = ReescapeWin32Strings(nativeEnumTimeFormats(this.sWindowsName, TIME_NOSECONDS, UseUserOverride)); return result; @@ -2975,7 +2602,6 @@ namespace System.Globalization // not affected by the Calendar property in DTFI. // //////////////////////////////////////////////////////////////////////////// - [System.Security.SecurityCritical] // auto-generated internal void GetNFIValues(NumberFormatInfo nfi) { if (this.IsInvariantCulture) @@ -3013,7 +2639,7 @@ namespace System.Globalization // // Ask native side for our data. // - Contract.Assert(this.sWindowsName != null, "[CultureData.GetNFIValues] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); + Debug.Assert(this.sWindowsName != null, "[CultureData.GetNFIValues] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); CultureData.nativeGetNumberFormatInfoValues(this.sWindowsName, nfi, UseUserOverride); } @@ -3056,17 +2682,6 @@ namespace System.Globalization { nfi.currencyDecimalSeparator = nfi.numberDecimalSeparator; } - -#if !FEATURE_CORECLR - if ((932 == this.IDEFAULTANSICODEPAGE) || - (949 == this.IDEFAULTANSICODEPAGE)) - { - // Legacy behavior for cultures that use Japanese/Korean default ANSI code pages - // Note that this is a code point, not a character. On Japanese/Korean machines this - // will be rendered as their currency symbol, not rendered as a "\" - nfi.ansiCurrencySymbol = "\x5c"; - } -#endif // !FEATURE_CORECLR } static private int ConvertFirstDayOfWeekMonToSun(int iTemp) @@ -3333,20 +2948,16 @@ namespace System.Globalization internal const uint TIME_NOSECONDS = 0x00000002; // Don't use seconds (get short time format for enumtimeformats on win7+) // Get our initial minimal culture data (name, parent, etc.) - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool nativeInitCultureData(CultureData cultureData); // Grab the NumberFormatInfo data - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool nativeGetNumberFormatInfoValues(String localeName, NumberFormatInfo nfi, bool useUserOverride); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern String[] nativeEnumTimeFormats(String localeName, uint dwFlags, bool useUserOverride); - [System.Security.SecurityCritical] // auto-generated [SuppressUnmanagedCodeSecurityAttribute()] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] internal static extern int nativeEnumCultureNames(int cultureTypes, ObjectHandleOnStack retStringArray); diff --git a/src/mscorlib/src/System/Globalization/CultureInfo.cs b/src/mscorlib/src/System/Globalization/CultureInfo.cs index d620d2d..9f306c3 100644 --- a/src/mscorlib/src/System/Globalization/CultureInfo.cs +++ b/src/mscorlib/src/System/Globalization/CultureInfo.cs @@ -39,6 +39,7 @@ namespace System.Globalization { using System.Security.Permissions; using System.Reflection; using Microsoft.Win32; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Resources; @@ -66,10 +67,6 @@ namespace System.Globalization { internal bool m_isReadOnly; internal CompareInfo compareInfo; internal TextInfo textInfo; - // Not serialized for now since we only build it privately for use in the CARIB (so rebuilding is OK) -#if !FEATURE_CORECLR - [NonSerialized]internal RegionInfo regionInfo; -#endif internal NumberFormatInfo numInfo; internal DateTimeFormatInfo dateTimeInfo; internal Calendar calendar; @@ -88,10 +85,8 @@ namespace System.Globalization { #if FEATURE_LEAK_CULTURE_INFO [NonSerialized]private bool m_isSafeCrossDomain; [NonSerialized]private int m_createdDomainID; -#endif // !FEATURE_CORECLR -#if !FEATURE_CORECLR +#endif // !FEATURE_LEAK_CULTURE_INFO [NonSerialized]private CultureInfo m_consoleFallbackCulture; -#endif // !FEATURE_CORECLR // Names are confusing. Here are 3 names we have: // @@ -152,7 +147,6 @@ namespace System.Globalization { #if FEATURE_APPX // When running under AppX, we use this to get some information about the language list - [SecurityCritical] private static volatile WindowsRuntimeResourceManagerBase s_WindowsRuntimeResourceManager; [ThreadStatic] @@ -197,7 +191,6 @@ namespace System.Globalization { return true; } - [System.Security.SecuritySafeCritical] // auto-generated static CultureInfo InitUserDefaultCulture() { String strDefault = GetDefaultLocaleName(LOCALE_USER_DEFAULT); @@ -241,7 +234,6 @@ namespace System.Globalization { } #if FEATURE_APPX - [SecuritySafeCritical] internal static CultureInfo GetCultureInfoForUserPreferredLanguageInAppX() { // If a call to GetCultureInfoForUserPreferredLanguageInAppX() generated a recursive @@ -287,7 +279,6 @@ namespace System.Globalization { return toReturn; } - [SecuritySafeCritical] internal static bool SetCultureInfoForUserPreferredLanguageInAppX(CultureInfo ci) { // If running within a compilation process (mscorsvw.exe, for example), it is illegal to @@ -323,7 +314,7 @@ namespace System.Globalization { public CultureInfo(String name, bool useUserOverride) { if (name==null) { - throw new ArgumentNullException("name", + throw new ArgumentNullException(nameof(name), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -332,7 +323,7 @@ namespace System.Globalization { this.m_cultureData = CultureData.GetCultureData(name, useUserOverride); if (this.m_cultureData == null) { - throw new CultureNotFoundException("name", name, Environment.GetResourceString("Argument_CultureNotSupported")); + throw new CultureNotFoundException(nameof(name), name, Environment.GetResourceString("Argument_CultureNotSupported")); } this.m_name = this.m_cultureData.CultureName; @@ -347,7 +338,7 @@ namespace System.Globalization { public CultureInfo(int culture, bool useUserOverride) { // We don't check for other invalid LCIDS here... if (culture < 0) { - throw new ArgumentOutOfRangeException("culture", + throw new ArgumentOutOfRangeException(nameof(culture), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); } Contract.EndContractBlock(); @@ -367,7 +358,7 @@ namespace System.Globalization { // Can't support unknown custom cultures and we do not support neutral or // non-custom user locales. throw new CultureNotFoundException( - "culture", culture, Environment.GetResourceString("Argument_CultureNotSupported")); + nameof(culture), culture, Environment.GetResourceString("Argument_CultureNotSupported")); default: // Now see if this LCID is supported in the system default CultureData table. @@ -413,18 +404,18 @@ namespace System.Globalization { // e.g. for es-ES_tradnl: v2 puts es-ES in m_name; v4 puts es-ES_tradnl if (m_name == null || IsAlternateSortLcid(cultureID)) { - Contract.Assert(cultureID >=0, "[CultureInfo.OnDeserialized] cultureID >= 0"); + Debug.Assert(cultureID >=0, "[CultureInfo.OnDeserialized] cultureID >= 0"); InitializeFromCultureId(cultureID, m_useUserOverride); } else { #endif - Contract.Assert(m_name != null, "[CultureInfo.OnDeserialized] m_name != null"); + Debug.Assert(m_name != null, "[CultureInfo.OnDeserialized] m_name != null"); this.m_cultureData = CultureData.GetCultureData(m_name, m_useUserOverride); if (this.m_cultureData == null) throw new CultureNotFoundException( - "m_name", m_name, Environment.GetResourceString("Argument_CultureNotSupported")); + nameof(m_name), m_name, Environment.GetResourceString("Argument_CultureNotSupported")); #if FEATURE_USE_LCID } @@ -486,14 +477,14 @@ namespace System.Globalization { // For Silverlight, the answer is always no. internal bool IsSafeCrossDomain { get { - Contract.Assert(m_createdDomainID != 0, "[CultureInfo.IsSafeCrossDomain] m_createdDomainID != 0"); + Debug.Assert(m_createdDomainID != 0, "[CultureInfo.IsSafeCrossDomain] m_createdDomainID != 0"); return m_isSafeCrossDomain; } } internal int CreatedDomainID { get { - Contract.Assert(m_createdDomainID != 0, "[CultureInfo.CreatedDomain] m_createdDomainID != 0"); + Debug.Assert(m_createdDomainID != 0, "[CultureInfo.CreatedDomain] m_createdDomainID != 0"); return m_createdDomainID; } } @@ -540,7 +531,7 @@ namespace System.Globalization { internal CultureInfo(String cultureName, String textAndCompareCultureName) { if (cultureName==null) { - throw new ArgumentNullException("cultureName", + throw new ArgumentNullException(nameof(cultureName), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -548,7 +539,7 @@ namespace System.Globalization { this.m_cultureData = CultureData.GetCultureData(cultureName, false); if (this.m_cultureData == null) throw new CultureNotFoundException( - "cultureName", cultureName, Environment.GetResourceString("Argument_CultureNotSupported")); + nameof(cultureName), cultureName, Environment.GetResourceString("Argument_CultureNotSupported")); this.m_name = this.m_cultureData.CultureName; @@ -644,7 +635,7 @@ namespace System.Globalization { } internal static bool VerifyCultureName(CultureInfo culture, bool throwException) { - Contract.Assert(culture!=null, "[CultureInfo.VerifyCultureName]culture!=null"); + Debug.Assert(culture!=null, "[CultureInfo.VerifyCultureName]culture!=null"); //If we have an instance of one of our CultureInfos, the user can't have changed the //name and we know that all names are valid in files. @@ -672,9 +663,6 @@ namespace System.Globalization { get { Contract.Ensures(Contract.Result() != null); -#if !FEATURE_CORECLR - return Thread.CurrentThread.CurrentCulture; -#else // In the case of CoreCLR, Thread.m_CurrentCulture and // Thread.m_CurrentUICulture are thread static so as not to let // CultureInfo objects leak across AppDomain boundaries. The @@ -695,13 +683,12 @@ namespace System.Globalization { s_DefaultThreadCurrentCulture ?? s_userDefaultCulture ?? UserDefaultCulture; -#endif } set { #if FEATURE_APPX if (value == null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } if (AppDomain.IsAppXModel()) { @@ -770,9 +757,6 @@ namespace System.Globalization { get { Contract.Ensures(Contract.Result() != null); -#if !FEATURE_CORECLR - return Thread.CurrentThread.CurrentUICulture; -#else // In the case of CoreCLR, Thread.m_CurrentCulture and // Thread.m_CurrentUICulture are thread static so as not to let // CultureInfo objects leak across AppDomain boundaries. The @@ -793,13 +777,12 @@ namespace System.Globalization { s_DefaultThreadCurrentUICulture ?? s_userDefaultUICulture ?? UserDefaultUICulture; -#endif } set { #if FEATURE_APPX if (value == null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } if (AppDomain.IsAppXModel()) { @@ -843,10 +826,6 @@ namespace System.Globalization { return s_DefaultThreadCurrentCulture; } - [System.Security.SecuritySafeCritical] // auto-generated -#pragma warning disable 618 - [SecurityPermission(SecurityAction.Demand, ControlThread = true)] -#pragma warning restore 618 set { // If you add pre-conditions to this method, check to see if you also need to @@ -861,10 +840,6 @@ namespace System.Globalization { return s_DefaultThreadCurrentUICulture; } - [System.Security.SecuritySafeCritical] // auto-generated -#pragma warning disable 618 - [SecurityPermission(SecurityAction.Demand, ControlThread = true)] -#pragma warning restore 618 set { //If they're trying to use a Culture with a name that we can't use in resource lookup, @@ -915,24 +890,23 @@ namespace System.Globalization { public virtual CultureInfo Parent { - [System.Security.SecuritySafeCritical] // auto-generated get { Contract.Ensures(Contract.Result() != null); + CultureInfo culture = null; if (null == m_parent) { try { string parentName = this.m_cultureData.SPARENT; - if (String.IsNullOrEmpty(parentName)) { - m_parent = InvariantCulture; + culture = InvariantCulture; } else { - m_parent = new CultureInfo(parentName, this.m_cultureData.UseUserOverride); + culture = new CultureInfo(parentName, this.m_cultureData.UseUserOverride); } } catch (ArgumentException) @@ -940,8 +914,10 @@ namespace System.Globalization { // For whatever reason our IPARENT or SPARENT wasn't correct, so use invariant // We can't allow ourselves to fail. In case of custom cultures the parent of the // current custom culture isn't installed. - m_parent = InvariantCulture; + culture = InvariantCulture; } + + Interlocked.CompareExchange(ref m_parent, culture, null); } return m_parent; } @@ -1034,7 +1010,6 @@ namespace System.Globalization { } } -#if !FEATURE_CORECLR [System.Runtime.InteropServices.ComVisible(false)] public String IetfLanguageTag { @@ -1054,7 +1029,6 @@ namespace System.Globalization { } } } -#endif //////////////////////////////////////////////////////////////////////// // @@ -1067,11 +1041,10 @@ namespace System.Globalization { //////////////////////////////////////////////////////////////////////// public virtual String DisplayName { - [System.Security.SecuritySafeCritical] // auto-generated get { Contract.Ensures(Contract.Result() != null); - Contract.Assert(m_name != null, "[CultureInfo.DisplayName]Always expect m_name to be set"); + Debug.Assert(m_name != null, "[CultureInfo.DisplayName]Always expect m_name to be set"); return m_cultureData.SLOCALIZEDDISPLAYNAME; } @@ -1087,7 +1060,6 @@ namespace System.Globalization { // //////////////////////////////////////////////////////////////////////// public virtual String NativeName { - [System.Security.SecuritySafeCritical] // auto-generated get { Contract.Ensures(Contract.Result() != null); return (this.m_cultureData.SNATIVEDISPLAYNAME); @@ -1104,7 +1076,6 @@ namespace System.Globalization { // //////////////////////////////////////////////////////////////////////// public virtual String EnglishName { - [System.Security.SecuritySafeCritical] // auto-generated get { Contract.Ensures(Contract.Result() != null); return (this.m_cultureData.SENGDISPLAYNAME); @@ -1113,7 +1084,6 @@ namespace System.Globalization { // ie: en public virtual String TwoLetterISOLanguageName { - [System.Security.SecuritySafeCritical] // auto-generated get { Contract.Ensures(Contract.Result() != null); return (this.m_cultureData.SISO639LANGNAME); @@ -1122,7 +1092,6 @@ namespace System.Globalization { // ie: eng public virtual String ThreeLetterISOLanguageName { - [System.Security.SecuritySafeCritical] // auto-generated get { Contract.Ensures(Contract.Result() != null); return (this.m_cultureData.SISO639LANGNAME2); @@ -1138,7 +1107,6 @@ namespace System.Globalization { // //////////////////////////////////////////////////////////////////////// public virtual String ThreeLetterWindowsLanguageName { - [System.Security.SecuritySafeCritical] // auto-generated get { Contract.Ensures(Contract.Result() != null); return (this.m_cultureData.SABBREVLANGNAME); @@ -1178,31 +1146,6 @@ namespace System.Globalization { } } -#if !FEATURE_CORECLR - //////////////////////////////////////////////////////////////////////// - // - // RegionInfo - // - // Gets the RegionInfo for this culture. - // - //////////////////////////////////////////////////////////////////////// - private RegionInfo Region - { - get - { - if (regionInfo==null) - { - // Make a new regionInfo - RegionInfo tempRegionInfo = new RegionInfo(this.m_cultureData); - regionInfo = tempRegionInfo; - } - return (regionInfo); - } - } -#endif // FEATURE_CORECLR - - - //////////////////////////////////////////////////////////////////////// // // TextInfo @@ -1294,7 +1237,7 @@ namespace System.Globalization { { Contract.Ensures(Contract.Result() != null); - Contract.Assert(m_name != null, "[CultureInfo.ToString]Always expect m_name to be set"); + Debug.Assert(m_name != null, "[CultureInfo.ToString]Always expect m_name to be set"); return m_name; } @@ -1315,7 +1258,6 @@ namespace System.Globalization { } } -#if !FEATURE_CORECLR [System.Runtime.InteropServices.ComVisible(false)] public CultureTypes CultureTypes { @@ -1333,15 +1275,14 @@ namespace System.Globalization { // Disable warning 618: System.Globalization.CultureTypes.FrameworkCultures' is obsolete #pragma warning disable 618 types |= m_cultureData.IsFramework ? CultureTypes.FrameworkCultures : 0; - #pragma warning restore 618 + types |= m_cultureData.IsSupplementalCustomCulture ? CultureTypes.UserCustomCulture : 0; types |= m_cultureData.IsReplacementCulture ? CultureTypes.ReplacementCultures | CultureTypes.UserCustomCulture : 0; return types; } } -#endif public virtual NumberFormatInfo NumberFormat { get @@ -1351,13 +1292,13 @@ namespace System.Globalization { if (numInfo == null) { NumberFormatInfo temp = new NumberFormatInfo(this.m_cultureData); temp.isReadOnly = m_isReadOnly; - numInfo = temp; + Interlocked.CompareExchange(ref numInfo, temp, null); } return (numInfo); } set { if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_Obj")); } Contract.EndContractBlock(); @@ -1385,15 +1326,14 @@ namespace System.Globalization { DateTimeFormatInfo temp = new DateTimeFormatInfo( this.m_cultureData, this.Calendar); temp.m_isReadOnly = m_isReadOnly; - System.Threading.Thread.MemoryBarrier(); - dateTimeInfo = temp; + Interlocked.CompareExchange(ref dateTimeInfo, temp, null); } return (dateTimeInfo); } set { if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_Obj")); } Contract.EndContractBlock(); @@ -1402,17 +1342,16 @@ namespace System.Globalization { } } - - public void ClearCachedData() { s_userDefaultUICulture = null; s_userDefaultCulture = null; RegionInfo.s_currentRegionInfo = null; -#if !FEATURE_CORECLR // System.TimeZone does not exist in CoreCLR +#pragma warning disable CS0618 TimeZone.ResetTimeZone(); -#endif // FEATURE_CORECLR +#pragma warning restore CS0618 TimeZoneInfo.ClearCachedData(); + // Delete the cached cultures. s_LcidCachedCultures = null; s_NameCachedCultures = null; @@ -1438,7 +1377,7 @@ namespace System.Globalization { //This function exists as a shortcut to prevent us from loading all of the non-gregorian //calendars unless they're required. internal static Calendar GetCalendarInstanceRare(int calType) { - Contract.Assert(calType!=Calendar.CAL_GREGORIAN, "calType!=Calendar.CAL_GREGORIAN"); + Debug.Assert(calType!=Calendar.CAL_GREGORIAN, "calType!=Calendar.CAL_GREGORIAN"); switch (calType) { case Calendar.CAL_GREGORIAN_US: // Gregorian (U.S.) calendar @@ -1490,7 +1429,7 @@ namespace System.Globalization { get { Contract.Ensures(Contract.Result() != null); if (calendar == null) { - Contract.Assert(this.m_cultureData.CalendarIds.Length > 0, "this.m_cultureData.CalendarIds.Length > 0"); + Debug.Assert(this.m_cultureData.CalendarIds.Length > 0, "this.m_cultureData.CalendarIds.Length > 0"); // Get the default calendar for this culture. Note that the value can be // from registry if this is a user default culture. Calendar newObj = this.m_cultureData.DefaultCalendar; @@ -1534,8 +1473,6 @@ namespace System.Globalization { } } -#if !FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(false)] public CultureInfo GetConsoleFallbackUICulture() { @@ -1550,7 +1487,6 @@ namespace System.Globalization { } return (temp); } -#endif public virtual Object Clone() { @@ -1595,7 +1531,7 @@ namespace System.Globalization { public static CultureInfo ReadOnly(CultureInfo ci) { if (ci == null) { - throw new ArgumentNullException("ci"); + throw new ArgumentNullException(nameof(ci)); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -1827,7 +1763,7 @@ namespace System.Globalization { // the altCulture code path for SQL Server. // Also check for zero as this would fail trying to add as a key to the hash. if (culture <= 0) { - throw new ArgumentOutOfRangeException("culture", + throw new ArgumentOutOfRangeException(nameof(culture), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); } Contract.Ensures(Contract.Result() != null); @@ -1836,7 +1772,7 @@ namespace System.Globalization { if (null == retval) { throw new CultureNotFoundException( - "culture", culture, Environment.GetResourceString("Argument_CultureNotSupported")); + nameof(culture), culture, Environment.GetResourceString("Argument_CultureNotSupported")); } return retval; } @@ -1849,7 +1785,7 @@ namespace System.Globalization { // Make sure we have a valid, non-zero length string as name if (name == null) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -1858,7 +1794,7 @@ namespace System.Globalization { if (retval == null) { throw new CultureNotFoundException( - "name", name, Environment.GetResourceString("Argument_CultureNotSupported")); + nameof(name), name, Environment.GetResourceString("Argument_CultureNotSupported")); } return retval; @@ -1871,12 +1807,12 @@ namespace System.Globalization { // Make sure we have a valid, non-zero length string as name if (null == name) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } if (null == altName) { - throw new ArgumentNullException("altName"); + throw new ArgumentNullException(nameof(altName)); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -1884,7 +1820,7 @@ namespace System.Globalization { CultureInfo retval = GetCultureInfoHelper(-1, name, altName); if (retval == null) { - throw new CultureNotFoundException("name or altName", + throw new CultureNotFoundException(nameof(name) + " or " + nameof(altName), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_OneOfCulturesNotSupported"), @@ -1904,7 +1840,7 @@ namespace System.Globalization { if (name == "zh-CHT" || name == "zh-CHS") { throw new CultureNotFoundException( - "name", + nameof(name), String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_CultureIetfNotSupported"), name) ); } @@ -1915,7 +1851,7 @@ namespace System.Globalization { if (ci.LCID > 0xffff || ci.LCID == 0x040a) { throw new CultureNotFoundException( - "name", + nameof(name), String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_CultureIetfNotSupported"), name) ); } @@ -1943,22 +1879,18 @@ namespace System.Globalization { // // Get Locale Info Ex calls. So we don't have to muck with the different int/string return types we declared two of these: - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern String nativeGetLocaleInfoEx(String localeName, uint field); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern int nativeGetLocaleInfoExInt(String localeName, uint field); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool nativeSetThreadLocale(String localeName); - [System.Security.SecurityCritical] private static String GetDefaultLocaleName(int localeType) { - Contract.Assert(localeType == LOCALE_USER_DEFAULT || localeType == LOCALE_SYSTEM_DEFAULT, "[CultureInfo.GetDefaultLocaleName] localeType must be LOCALE_USER_DEFAULT or LOCALE_SYSTEM_DEFAULT"); + Debug.Assert(localeType == LOCALE_USER_DEFAULT || localeType == LOCALE_SYSTEM_DEFAULT, "[CultureInfo.GetDefaultLocaleName] localeType must be LOCALE_USER_DEFAULT or LOCALE_SYSTEM_DEFAULT"); string localeName = null; if(InternalGetDefaultLocaleName(localeType, JitHelpers.GetStringHandleOnStack(ref localeName))) @@ -1969,13 +1901,11 @@ namespace System.Globalization { } // Get the default locale name - [System.Security.SecurityCritical] // auto-generated [SuppressUnmanagedCodeSecurity] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool InternalGetDefaultLocaleName(int localetype, StringHandleOnStack localeString); - [System.Security.SecuritySafeCritical] // auto-generated private static String GetUserDefaultUILanguage() { string userDefaultUiLanguage = null; @@ -1987,13 +1917,11 @@ namespace System.Globalization { } // Get the user's default UI language, return locale name - [System.Security.SecurityCritical] // auto-generated [SuppressUnmanagedCodeSecurity] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool InternalGetUserDefaultUILanguage(StringHandleOnStack userDefaultUiLanguage); - [System.Security.SecuritySafeCritical] // auto-generated private static String GetSystemDefaultUILanguage() { string systemDefaultUiLanguage = null; @@ -2005,19 +1933,14 @@ namespace System.Globalization { } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [SuppressUnmanagedCodeSecurity] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool InternalGetSystemDefaultUILanguage(StringHandleOnStack systemDefaultUiLanguage); -// Added but disabled from desktop in .NET 4.0, stayed disabled in .NET 4.5 -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern String[] nativeGetResourceFallbackArray(); -#endif } } diff --git a/src/mscorlib/src/System/Globalization/CultureNotFoundException.cs b/src/mscorlib/src/System/Globalization/CultureNotFoundException.cs index 0486cc9..17c0b43 100644 --- a/src/mscorlib/src/System/Globalization/CultureNotFoundException.cs +++ b/src/mscorlib/src/System/Globalization/CultureNotFoundException.cs @@ -66,10 +66,9 @@ namespace System.Globalization { m_invalidCultureName = (string) info.GetValue("InvalidCultureName", typeof(string)); } - [System.Security.SecurityCritical] // auto-generated_required public override void GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); base.GetObjectData(info, context); diff --git a/src/mscorlib/src/System/Globalization/DateTimeFormat.cs b/src/mscorlib/src/System/Globalization/DateTimeFormat.cs index 228e5f5..c6e0591 100644 --- a/src/mscorlib/src/System/Globalization/DateTimeFormat.cs +++ b/src/mscorlib/src/System/Globalization/DateTimeFormat.cs @@ -11,6 +11,7 @@ namespace System { using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; + using System.Diagnostics; using System.Diagnostics.Contracts; /* @@ -139,8 +140,13 @@ namespace System { internal const String RoundtripFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK"; internal const String RoundtripDateTimeUnfixed = "yyyy'-'MM'-'ddTHH':'mm':'ss zzz"; - private const int DEFAULT_ALL_DATETIMES_SIZE = 132; - + private const int DEFAULT_ALL_DATETIMES_SIZE = 132; + + internal static readonly DateTimeFormatInfo InvariantFormatInfo = CultureInfo.InvariantCulture.DateTimeFormat; + internal static readonly string[] InvariantAbbreviatedMonthNames = InvariantFormatInfo.AbbreviatedMonthNames; + internal static readonly string[] InvariantAbbreviatedDayNames = InvariantFormatInfo.AbbreviatedDayNames; + internal const string Gmt = "GMT"; + internal static String[] fixedNumberFormats = new String[] { "0", "00", @@ -166,13 +172,12 @@ namespace System { // //////////////////////////////////////////////////////////////////////////// internal static void FormatDigits(StringBuilder outputBuffer, int value, int len) { - Contract.Assert(value >= 0, "DateTimeFormat.FormatDigits(): value >= 0"); + Debug.Assert(value >= 0, "DateTimeFormat.FormatDigits(): value >= 0"); FormatDigits(outputBuffer, value, len, false); } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static void FormatDigits(StringBuilder outputBuffer, int value, int len, bool overrideLengthLimit) { - Contract.Assert(value >= 0, "DateTimeFormat.FormatDigits(): value >= 0"); + Debug.Assert(value >= 0, "DateTimeFormat.FormatDigits(): value >= 0"); // Limit the use of this function to be two-digits, so that we have the same behavior // as RTM bits. @@ -218,7 +223,7 @@ namespace System { private static String FormatDayOfWeek(int dayOfWeek, int repeat, DateTimeFormatInfo dtfi) { - Contract.Assert(dayOfWeek >= 0 && dayOfWeek <= 6, "dayOfWeek >= 0 && dayOfWeek <= 6"); + Debug.Assert(dayOfWeek >= 0 && dayOfWeek <= 6, "dayOfWeek >= 0 && dayOfWeek <= 6"); if (repeat == 3) { return (dtfi.GetAbbreviatedDayName((DayOfWeek)dayOfWeek)); @@ -230,7 +235,7 @@ namespace System { private static String FormatMonth(int month, int repeatCount, DateTimeFormatInfo dtfi) { - Contract.Assert(month >=1 && month <= 12, "month >=1 && month <= 12"); + Debug.Assert(month >=1 && month <= 12, "month >=1 && month <= 12"); if (repeatCount == 3) { return (dtfi.GetAbbreviatedMonthName(month)); @@ -271,7 +276,7 @@ namespace System { */ private static String FormatHebrewMonthName(DateTime time, int month, int repeatCount, DateTimeFormatInfo dtfi) { - Contract.Assert(repeatCount != 3 || repeatCount != 4, "repeateCount should be 3 or 4"); + Debug.Assert(repeatCount != 3 || repeatCount != 4, "repeateCount should be 3 or 4"); if (dtfi.Calendar.IsLeapYear(dtfi.Calendar.GetYear(time))) { // This month is in a leap year return (dtfi.internalGetMonthName(month, MonthNameStyles.LeapYear, (repeatCount == 3))); @@ -703,24 +708,13 @@ namespace System { // accurate than the system's current offset because of daylight saving time. offset = TimeZoneInfo.GetLocalUtcOffset(DateTime.Now, TimeZoneInfoOptions.NoThrowOnInvalidTime); } else if (dateTime.Kind == DateTimeKind.Utc) { -#if FEATURE_CORECLR offset = TimeSpan.Zero; -#else // FEATURE_CORECLR - // This code path points to a bug in user code. It would make sense to return a 0 offset in this case. - // However, because it was only possible to detect this in Whidbey, there is user code that takes a - // dependency on being serialize a UTC DateTime using the 'z' format, and it will work almost all the - // time if it is offset by an incorrect conversion to local time when parsed. Therefore, we need to - // explicitly emit the local time offset, which we can do by removing the UTC flag. - InvalidFormatForUtc(format, dateTime); - dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Local); - offset = TimeZoneInfo.GetLocalUtcOffset(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime); -#endif // FEATURE_CORECLR } else { offset = TimeZoneInfo.GetLocalUtcOffset(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime); } } if (offset >= TimeSpan.Zero) { - result.Append('+'); + result.Append('+'); } else { result.Append('-'); @@ -739,7 +733,7 @@ namespace System { // 'zzz*' or longer format e.g "-07:30" result.AppendFormat(CultureInfo.InvariantCulture, ":{0:00}", offset.Minutes); } - } + } } // output the 'K' format, which is for round-tripping the data @@ -775,7 +769,9 @@ namespace System { offset = offset.Negate(); } - result.AppendFormat(CultureInfo.InvariantCulture, "{0:00}:{1:00}", offset.Hours, offset.Minutes); + AppendNumber(result, offset.Hours, 2); + result.Append(':'); + AppendNumber(result, offset.Minutes, 2); } @@ -957,12 +953,101 @@ namespace System { } if (format.Length == 1) { + switch (format[0]) + { + case 'O': + case 'o': + return FastFormatRoundtrip(dateTime, offset); + case 'R': + case 'r': + return FastFormatRfc1123(dateTime, offset, dtfi); + } + format = ExpandPredefinedFormat(format, ref dateTime, ref dtfi, ref offset); - } + } return (FormatCustomized(dateTime, format, dtfi, offset)); } - + + internal static string FastFormatRfc1123(DateTime dateTime, TimeSpan offset, DateTimeFormatInfo dtfi) + { + // ddd, dd MMM yyyy HH:mm:ss GMT + const int Rfc1123FormatLength = 29; + StringBuilder result = StringBuilderCache.Acquire(Rfc1123FormatLength); + + if (offset != NullOffset) + { + // Convert to UTC invariants + dateTime = dateTime - offset; + } + + result.Append(InvariantAbbreviatedDayNames[(int)dateTime.DayOfWeek]); + result.Append(','); + result.Append(' '); + AppendNumber(result, dateTime.Day, 2); + result.Append(' '); + result.Append(InvariantAbbreviatedMonthNames[dateTime.Month - 1]); + result.Append(' '); + AppendNumber(result, dateTime.Year, 4); + result.Append(' '); + AppendHHmmssTimeOfDay(result, dateTime); + result.Append(' '); + result.Append(Gmt); + + return StringBuilderCache.GetStringAndRelease(result); + } + + internal static string FastFormatRoundtrip(DateTime dateTime, TimeSpan offset) + { + // yyyy-MM-ddTHH:mm:ss.fffffffK + const int roundTripFormatLength = 28; + StringBuilder result = StringBuilderCache.Acquire(roundTripFormatLength); + + AppendNumber(result, dateTime.Year, 4); + result.Append('-'); + AppendNumber(result, dateTime.Month, 2); + result.Append('-'); + AppendNumber(result, dateTime.Day, 2); + result.Append('T'); + AppendHHmmssTimeOfDay(result, dateTime); + result.Append('.'); + + long fraction = dateTime.Ticks % TimeSpan.TicksPerSecond; + AppendNumber(result, fraction, 7); + + FormatCustomizedRoundripTimeZone(dateTime, offset, result); + + return StringBuilderCache.GetStringAndRelease(result); + } + + private static void AppendHHmmssTimeOfDay(StringBuilder result, DateTime dateTime) + { + // HH:mm:ss + AppendNumber(result, dateTime.Hour, 2); + result.Append(':'); + AppendNumber(result, dateTime.Minute, 2); + result.Append(':'); + AppendNumber(result, dateTime.Second, 2); + } + + internal static void AppendNumber(StringBuilder builder, long val, int digits) + { + for (int i = 0; i < digits; i++) + { + builder.Append('0'); + } + + int index = 1; + while (val > 0 && index <= digits) + { + builder[builder.Length - index] = (char)('0' + (val % 10)); + val = val / 10; + index++; + } + + Debug.Assert(val == 0, "DateTimeFormat.AppendNumber(): digits less than size of val"); + } + internal static String[] GetAllDateTimes(DateTime dateTime, char format, DateTimeFormatInfo dtfi) { Contract.Requires(dtfi != null); @@ -1042,7 +1127,6 @@ namespace System { // This is an MDA for cases when the user is using a local format with // a Utc DateTime. - [System.Security.SecuritySafeCritical] // auto-generated internal static void InvalidFormatForUtc(String format, DateTime dateTime) { #if MDA_SUPPORTED Mda.DateTimeInvalidLocalFormat(); diff --git a/src/mscorlib/src/System/Globalization/DateTimeFormatInfo.cs b/src/mscorlib/src/System/Globalization/DateTimeFormatInfo.cs index 00c2d1f..14cdeb6 100644 --- a/src/mscorlib/src/System/Globalization/DateTimeFormatInfo.cs +++ b/src/mscorlib/src/System/Globalization/DateTimeFormatInfo.cs @@ -14,6 +14,7 @@ namespace System.Globalization { using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; + using System.Diagnostics; using System.Diagnostics.Contracts; // @@ -181,18 +182,6 @@ namespace System.Globalization { // genitive form or leap year month names. [OptionalField(VersionAdded = 2)] internal DateTimeFormatFlags formatFlags = DateTimeFormatFlags.NotInitialized; - internal static bool preferExistingTokens = InitPreferExistingTokens(); - - - [System.Security.SecuritySafeCritical] - static bool InitPreferExistingTokens() - { - bool ret = false; -#if !FEATURE_CORECLR - ret = DateTime.LegacyParseMode(); -#endif - return ret; - } private String CultureName { @@ -220,7 +209,6 @@ namespace System.Globalization { private String LanguageName { - [System.Security.SecurityCritical] // auto-generated get { if (m_langName == null) @@ -243,7 +231,7 @@ namespace System.Globalization { { // Get the abbreviated day names for our current calendar this.abbreviatedDayNames = this.m_cultureData.AbbreviatedDayNames(Calendar.ID); - Contract.Assert(this.abbreviatedDayNames.Length == 7, "[DateTimeFormatInfo.GetAbbreviatedDayOfWeekNames] Expected 7 day names in a week"); + Debug.Assert(this.abbreviatedDayNames.Length == 7, "[DateTimeFormatInfo.GetAbbreviatedDayOfWeekNames] Expected 7 day names in a week"); } return (this.abbreviatedDayNames); } @@ -266,7 +254,7 @@ namespace System.Globalization { { // Get the super short day names for our current calendar this.m_superShortDayNames = this.m_cultureData.SuperShortDayNames(Calendar.ID); - Contract.Assert(this.m_superShortDayNames.Length == 7, "[DateTimeFormatInfo.internalGetSuperShortDayNames] Expected 7 day names in a week"); + Debug.Assert(this.m_superShortDayNames.Length == 7, "[DateTimeFormatInfo.internalGetSuperShortDayNames] Expected 7 day names in a week"); } return (this.m_superShortDayNames); } @@ -283,7 +271,7 @@ namespace System.Globalization { { // Get the day names for our current calendar this.dayNames = this.m_cultureData.DayNames(Calendar.ID); - Contract.Assert(this.dayNames.Length == 7, "[DateTimeFormatInfo.GetDayOfWeekNames] Expected 7 day names in a week"); + Debug.Assert(this.dayNames.Length == 7, "[DateTimeFormatInfo.GetDayOfWeekNames] Expected 7 day names in a week"); } return (this.dayNames); } @@ -300,7 +288,7 @@ namespace System.Globalization { { // Get the month names for our current calendar this.abbreviatedMonthNames = this.m_cultureData.AbbreviatedMonthNames(Calendar.ID); - Contract.Assert(this.abbreviatedMonthNames.Length == 12 || this.abbreviatedMonthNames.Length == 13, + Debug.Assert(this.abbreviatedMonthNames.Length == 12 || this.abbreviatedMonthNames.Length == 13, "[DateTimeFormatInfo.GetAbbreviatedMonthNames] Expected 12 or 13 month names in a year"); } return (this.abbreviatedMonthNames); @@ -319,7 +307,7 @@ namespace System.Globalization { { // Get the month names for our current calendar this.monthNames = this.m_cultureData.MonthNames(Calendar.ID); - Contract.Assert(this.monthNames.Length == 12 || this.monthNames.Length == 13, + Debug.Assert(this.monthNames.Length == 12 || this.monthNames.Length == 13, "[DateTimeFormatInfo.GetMonthNames] Expected 12 or 13 month names in a year"); } @@ -347,16 +335,12 @@ namespace System.Globalization { // m_isDefaultCalendar is set in the setter of Calendar below. this.Calendar = cal; } - -#if !FEATURE_CORECLR - [System.Security.SecuritySafeCritical] -#endif private void InitializeOverridableProperties(CultureData cultureData, int calendarID) { // Silverlight 2.0 never took a snapshot of the user's overridable properties // This has a substantial performance impact so skip when CoreCLR Contract.Requires(cultureData != null); - Contract.Assert(calendarID > 0, "[DateTimeFormatInfo.Populate] Expected Calendar.ID > 0"); + Debug.Assert(calendarID > 0, "[DateTimeFormatInfo.Populate] Expected Calendar.ID > 0"); if (this.firstDayOfWeek == -1) { this.firstDayOfWeek = cultureData.IFIRSTDAYOFWEEK; } if (this.calendarWeekRule == -1) { this.calendarWeekRule = cultureData.IFIRSTWEEKOFYEAR; } @@ -367,19 +351,19 @@ namespace System.Globalization { if (this.dateSeparator == null) { this.dateSeparator = cultureData.DateSeparator(calendarID); } this.allLongTimePatterns = this.m_cultureData.LongTimes; - Contract.Assert(this.allLongTimePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some long time patterns"); + Debug.Assert(this.allLongTimePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some long time patterns"); this.allShortTimePatterns = this.m_cultureData.ShortTimes; - Contract.Assert(this.allShortTimePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some short time patterns"); + Debug.Assert(this.allShortTimePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some short time patterns"); this.allLongDatePatterns = cultureData.LongDates(calendarID); - Contract.Assert(this.allLongDatePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some long date patterns"); + Debug.Assert(this.allLongDatePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some long date patterns"); this.allShortDatePatterns = cultureData.ShortDates(calendarID); - Contract.Assert(this.allShortDatePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some short date patterns"); + Debug.Assert(this.allShortDatePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some short date patterns"); this.allYearMonthPatterns = cultureData.YearMonths(calendarID); - Contract.Assert(this.allYearMonthPatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some year month patterns"); + Debug.Assert(this.allYearMonthPatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some year month patterns"); } #region Serialization @@ -411,7 +395,7 @@ namespace System.Globalization { if (this.m_cultureData == null) throw new CultureNotFoundException( - "m_name", m_name, Environment.GetResourceString("Argument_CultureNotSupported")); + nameof(m_name), m_name, Environment.GetResourceString("Argument_CultureNotSupported")); } // Note: This is for Everett compatibility @@ -458,11 +442,6 @@ namespace System.Globalization { // make sure the m_name is initialized. m_name = this.CultureName; -#if !FEATURE_CORECLR - if (s_calendarNativeNames == null) - s_calendarNativeNames = new Hashtable(); -#endif // FEATURE_CORECLR - // Important to initialize these fields otherwise we may run into exception when deserializing on Whidbey // because Whidbey try to initialize some of these fields using calendar data which could be null values // and then we get exceptions. So we call the accessors to force the caches to get loaded. @@ -561,18 +540,14 @@ namespace System.Globalization { public String AMDesignator { -#if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // auto-generated -#endif get { -#if FEATURE_CORECLR if (this.amDesignator == null) { this.amDesignator = this.m_cultureData.SAM1159; } -#endif - Contract.Assert(this.amDesignator != null, "DateTimeFormatInfo.AMDesignator, amDesignator != null"); + + Debug.Assert(this.amDesignator != null, "DateTimeFormatInfo.AMDesignator, amDesignator != null"); return (this.amDesignator); } @@ -582,7 +557,7 @@ namespace System.Globalization { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -596,7 +571,7 @@ namespace System.Globalization { get { Contract.Ensures(Contract.Result() != null); - Contract.Assert(this.calendar != null, "DateTimeFormatInfo.Calendar: calendar != null"); + Debug.Assert(this.calendar != null, "DateTimeFormatInfo.Calendar: calendar != null"); return (this.calendar); } @@ -604,7 +579,7 @@ namespace System.Globalization { if (IsReadOnly) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_Obj")); } Contract.EndContractBlock(); @@ -694,7 +669,7 @@ namespace System.Globalization { } // The assigned calendar is not a valid calendar for this culture, throw - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("Argument_InvalidCalendar")); + throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("Argument_InvalidCalendar")); } } @@ -718,7 +693,7 @@ namespace System.Globalization { public int GetEra(String eraName) { if (eraName == null) { - throw new ArgumentNullException("eraName", + throw new ArgumentNullException(nameof(eraName), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -795,7 +770,7 @@ namespace System.Globalization { if ((--era) < EraNames.Length && (era >= 0)) { return (m_eraNames[era]); } - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); } internal String[] AbbreviatedEraNames @@ -823,7 +798,7 @@ namespace System.Globalization { if ((--era) < m_abbrevEraNames.Length && (era >= 0)) { return (m_abbrevEraNames[era]); } - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); } internal String[] AbbreviatedEnglishEraNames @@ -832,7 +807,7 @@ namespace System.Globalization { { if (this.m_abbrevEnglishEraNames == null) { - Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.AbbreviatedEnglishEraNames] Expected Calendar.ID > 0"); + Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.AbbreviatedEnglishEraNames] Expected Calendar.ID > 0"); this.m_abbrevEnglishEraNames = this.m_cultureData.AbbreviatedEnglishEraNames(Calendar.ID); } return (this.m_abbrevEnglishEraNames); @@ -846,13 +821,12 @@ namespace System.Globalization { { get { -#if FEATURE_CORECLR if (this.dateSeparator == null) { this.dateSeparator = this.m_cultureData.DateSeparator(Calendar.ID); } -#endif - Contract.Assert(this.dateSeparator != null, "DateTimeFormatInfo.DateSeparator, dateSeparator != null"); + + Debug.Assert(this.dateSeparator != null, "DateTimeFormatInfo.DateSeparator, dateSeparator != null"); return (this.dateSeparator); } @@ -862,7 +836,7 @@ namespace System.Globalization { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -876,14 +850,12 @@ namespace System.Globalization { { get { -#if FEATURE_CORECLR if (this.firstDayOfWeek == -1) { this.firstDayOfWeek = this.m_cultureData.IFIRSTDAYOFWEEK; } -#endif - Contract.Assert(this.firstDayOfWeek != -1, "DateTimeFormatInfo.FirstDayOfWeek, firstDayOfWeek != -1"); - + + Debug.Assert(this.firstDayOfWeek != -1, "DateTimeFormatInfo.FirstDayOfWeek, firstDayOfWeek != -1"); return ((DayOfWeek)this.firstDayOfWeek); } @@ -894,7 +866,7 @@ namespace System.Globalization { firstDayOfWeek = (int)value; } else { throw new ArgumentOutOfRangeException( - "value", Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(value), Environment.GetResourceString("ArgumentOutOfRange_Range", DayOfWeek.Sunday, DayOfWeek.Saturday)); } } @@ -905,13 +877,12 @@ namespace System.Globalization { { get { -#if FEATURE_CORECLR if (this.calendarWeekRule == -1) { this.calendarWeekRule = this.m_cultureData.IFIRSTWEEKOFYEAR; } -#endif - Contract.Assert(this.calendarWeekRule != -1, "DateTimeFormatInfo.CalendarWeekRule, calendarWeekRule != -1"); + + Debug.Assert(this.calendarWeekRule != -1, "DateTimeFormatInfo.CalendarWeekRule, calendarWeekRule != -1"); return ((CalendarWeekRule)this.calendarWeekRule); } @@ -922,7 +893,7 @@ namespace System.Globalization { calendarWeekRule = (int)value; } else { throw new ArgumentOutOfRangeException( - "value", Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(value), Environment.GetResourceString("ArgumentOutOfRange_Range", CalendarWeekRule.FirstDay, CalendarWeekRule.FirstFourDayWeek)); } } @@ -945,7 +916,7 @@ namespace System.Globalization { if (IsReadOnly) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -977,7 +948,7 @@ namespace System.Globalization { if (IsReadOnly) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -1016,7 +987,7 @@ namespace System.Globalization { if (IsReadOnly) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -1042,10 +1013,10 @@ namespace System.Globalization { { if (this.monthDayPattern == null) { - Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.MonthDayPattern] Expected calID > 0"); + Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.MonthDayPattern] Expected calID > 0"); this.monthDayPattern = this.m_cultureData.MonthDay(Calendar.ID); } - Contract.Assert(this.monthDayPattern != null, "DateTimeFormatInfo.MonthDayPattern, monthDayPattern != null"); + Debug.Assert(this.monthDayPattern != null, "DateTimeFormatInfo.MonthDayPattern, monthDayPattern != null"); return (this.monthDayPattern); } @@ -1053,7 +1024,7 @@ namespace System.Globalization { if (IsReadOnly) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -1065,18 +1036,14 @@ namespace System.Globalization { public String PMDesignator { -#if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // auto-generated -#endif get { -#if FEATURE_CORECLR if (this.pmDesignator == null) { this.pmDesignator = this.m_cultureData.SPM2359; } -#endif - Contract.Assert(this.pmDesignator != null, "DateTimeFormatInfo.PMDesignator, pmDesignator != null"); + + Debug.Assert(this.pmDesignator != null, "DateTimeFormatInfo.PMDesignator, pmDesignator != null"); return (this.pmDesignator); } @@ -1084,7 +1051,7 @@ namespace System.Globalization { if (IsReadOnly) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -1128,7 +1095,7 @@ namespace System.Globalization { if (IsReadOnly) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_String")); Contract.EndContractBlock(); @@ -1168,7 +1135,7 @@ namespace System.Globalization { if (IsReadOnly) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -1292,13 +1259,12 @@ namespace System.Globalization { { get { -#if FEATURE_CORECLR if (timeSeparator == null) { timeSeparator = this.m_cultureData.TimeSeparator; } -#endif - Contract.Assert(this.timeSeparator != null, "DateTimeFormatInfo.TimeSeparator, timeSeparator != null"); + + Debug.Assert(this.timeSeparator != null, "DateTimeFormatInfo.TimeSeparator, timeSeparator != null"); return (timeSeparator); } @@ -1308,7 +1274,7 @@ namespace System.Globalization { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -1349,7 +1315,7 @@ namespace System.Globalization { if (IsReadOnly) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -1388,11 +1354,11 @@ namespace System.Globalization { if (IsReadOnly) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_Array")); } if (value.Length != 7) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 7), "value"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 7), nameof(value)); } Contract.EndContractBlock(); CheckNullValue(value, value.Length); @@ -1416,12 +1382,12 @@ namespace System.Globalization { if (IsReadOnly) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_Array")); } if (value.Length != 7) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 7), "value"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 7), nameof(value)); } Contract.EndContractBlock(); CheckNullValue(value, value.Length); @@ -1441,12 +1407,12 @@ namespace System.Globalization { if (IsReadOnly) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_Array")); } if (value.Length != 7) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 7), "value"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 7), nameof(value)); } Contract.EndContractBlock(); CheckNullValue(value, value.Length); @@ -1466,12 +1432,12 @@ namespace System.Globalization { if (IsReadOnly) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_Array")); } if (value.Length != 13) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 13), "value"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 13), nameof(value)); } Contract.EndContractBlock(); CheckNullValue(value, value.Length - 1); @@ -1492,12 +1458,12 @@ namespace System.Globalization { if (IsReadOnly) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_Array")); } if (value.Length != 13) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 13), "value"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 13), nameof(value)); } Contract.EndContractBlock(); CheckNullValue(value, value.Length - 1); @@ -1556,7 +1522,7 @@ namespace System.Globalization { // (actually is 13 right now for all cases) if ((month < 1) || (month > monthNamesArray.Length)) { throw new ArgumentOutOfRangeException( - "month", Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Range", 1, monthNamesArray.Length)); } return (monthNamesArray[month-1]); @@ -1575,7 +1541,7 @@ namespace System.Globalization { if (this.m_genitiveAbbreviatedMonthNames == null) { this.m_genitiveAbbreviatedMonthNames = this.m_cultureData.AbbreviatedGenitiveMonthNames(this.Calendar.ID); - Contract.Assert(this.m_genitiveAbbreviatedMonthNames.Length == 13, + Debug.Assert(this.m_genitiveAbbreviatedMonthNames.Length == 13, "[DateTimeFormatInfo.GetGenitiveMonthNames] Expected 13 abbreviated genitive month names in a year"); } return (this.m_genitiveAbbreviatedMonthNames); @@ -1584,7 +1550,7 @@ namespace System.Globalization { if (this.genitiveMonthNames == null) { this.genitiveMonthNames = this.m_cultureData.GenitiveMonthNames(this.Calendar.ID); - Contract.Assert(this.genitiveMonthNames.Length == 13, + Debug.Assert(this.genitiveMonthNames.Length == 13, "[DateTimeFormatInfo.GetGenitiveMonthNames] Expected 13 genitive month names in a year"); } return (this.genitiveMonthNames); @@ -1600,9 +1566,9 @@ namespace System.Globalization { internal String[] internalGetLeapYearMonthNames(/*bool abbreviated*/) { if (this.leapYearMonthNames == null) { - Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.internalGetLeapYearMonthNames] Expected Calendar.ID > 0"); + Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.internalGetLeapYearMonthNames] Expected Calendar.ID > 0"); this.leapYearMonthNames = this.m_cultureData.LeapYearMonthNames(Calendar.ID); - Contract.Assert(this.leapYearMonthNames.Length == 13, + Debug.Assert(this.leapYearMonthNames.Length == 13, "[DateTimeFormatInfo.internalGetLeapYearMonthNames] Expepcted 13 leap year month names"); } return (leapYearMonthNames); @@ -1614,7 +1580,7 @@ namespace System.Globalization { if ((int)dayofweek < 0 || (int)dayofweek > 6) { throw new ArgumentOutOfRangeException( - "dayofweek", Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(dayofweek), Environment.GetResourceString("ArgumentOutOfRange_Range", DayOfWeek.Sunday, DayOfWeek.Saturday)); } Contract.EndContractBlock(); @@ -1633,7 +1599,7 @@ namespace System.Globalization { if ((int)dayOfWeek < 0 || (int)dayOfWeek > 6) { throw new ArgumentOutOfRangeException( - "dayOfWeek", Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(dayOfWeek), Environment.GetResourceString("ArgumentOutOfRange_Range", DayOfWeek.Sunday, DayOfWeek.Saturday)); } Contract.EndContractBlock(); @@ -1740,7 +1706,7 @@ namespace System.Globalization { result = this.AllYearMonthPatterns; break; default: - throw new ArgumentException(Environment.GetResourceString("Format_BadFormatSpecifier"), "format"); + throw new ArgumentException(Environment.GetResourceString("Format_BadFormatSpecifier"), nameof(format)); } return (result); } @@ -1750,7 +1716,7 @@ namespace System.Globalization { { if ((int)dayofweek < 0 || (int)dayofweek > 6) { throw new ArgumentOutOfRangeException( - "dayofweek", Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(dayofweek), Environment.GetResourceString("ArgumentOutOfRange_Range", DayOfWeek.Sunday, DayOfWeek.Saturday)); } Contract.EndContractBlock(); @@ -1765,7 +1731,7 @@ namespace System.Globalization { { if (month < 1 || month > 13) { throw new ArgumentOutOfRangeException( - "month", Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Range", 1, 13)); } Contract.EndContractBlock(); @@ -1778,7 +1744,7 @@ namespace System.Globalization { { if (month < 1 || month > 13) { throw new ArgumentOutOfRangeException( - "month", Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Range", 1, 13)); } Contract.EndContractBlock(); @@ -1795,9 +1761,9 @@ namespace System.Globalization { // The resulting [] can get returned to the calling app, so clone it. private static string[] GetMergedPatterns(string [] patterns, string defaultPattern) { - Contract.Assert(patterns != null && patterns.Length > 0, + Debug.Assert(patterns != null && patterns.Length > 0, "[DateTimeFormatInfo.GetMergedPatterns]Expected array of at least one pattern"); - Contract.Assert(defaultPattern != null, + Debug.Assert(defaultPattern != null, "[DateTimeFormatInfo.GetMergedPatterns]Expected non null default string"); // If the default happens to be the first in the list just return (a cloned) copy @@ -1894,9 +1860,9 @@ namespace System.Globalization { { if (this.allYearMonthPatterns == null) { - Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedYearMonthPatterns] Expected Calendar.ID > 0"); + Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedYearMonthPatterns] Expected Calendar.ID > 0"); this.allYearMonthPatterns = this.m_cultureData.YearMonths(this.Calendar.ID); - Contract.Assert(this.allYearMonthPatterns.Length > 0, + Debug.Assert(this.allYearMonthPatterns.Length > 0, "[DateTimeFormatInfo.UnclonedYearMonthPatterns] Expected some year month patterns"); } @@ -1913,9 +1879,9 @@ namespace System.Globalization { { if (allShortDatePatterns == null) { - Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedShortDatePatterns] Expected Calendar.ID > 0"); + Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedShortDatePatterns] Expected Calendar.ID > 0"); this.allShortDatePatterns = this.m_cultureData.ShortDates(this.Calendar.ID); - Contract.Assert(this.allShortDatePatterns.Length > 0, + Debug.Assert(this.allShortDatePatterns.Length > 0, "[DateTimeFormatInfo.UnclonedShortDatePatterns] Expected some short date patterns"); } @@ -1931,9 +1897,9 @@ namespace System.Globalization { { if (allLongDatePatterns == null) { - Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedLongDatePatterns] Expected Calendar.ID > 0"); + Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedLongDatePatterns] Expected Calendar.ID > 0"); this.allLongDatePatterns = this.m_cultureData.LongDates(this.Calendar.ID); - Contract.Assert(this.allLongDatePatterns.Length > 0, + Debug.Assert(this.allLongDatePatterns.Length > 0, "[DateTimeFormatInfo.UnclonedLongDatePatterns] Expected some long date patterns"); } @@ -1950,7 +1916,7 @@ namespace System.Globalization { if (this.allShortTimePatterns == null) { this.allShortTimePatterns = this.m_cultureData.ShortTimes; - Contract.Assert(this.allShortTimePatterns.Length > 0, + Debug.Assert(this.allShortTimePatterns.Length > 0, "[DateTimeFormatInfo.UnclonedShortTimePatterns] Expected some short time patterns"); } @@ -1967,7 +1933,7 @@ namespace System.Globalization { if (this.allLongTimePatterns == null) { this.allLongTimePatterns = this.m_cultureData.LongTimes; - Contract.Assert(this.allLongTimePatterns.Length > 0, + Debug.Assert(this.allLongTimePatterns.Length > 0, "[DateTimeFormatInfo.UnclonedLongTimePatterns] Expected some long time patterns"); } @@ -1977,7 +1943,7 @@ namespace System.Globalization { public static DateTimeFormatInfo ReadOnly(DateTimeFormatInfo dtfi) { if (dtfi == null) { - throw new ArgumentNullException("dtfi", + throw new ArgumentNullException(nameof(dtfi), Environment.GetResourceString("ArgumentNull_Obj")); } Contract.EndContractBlock(); @@ -2038,13 +2004,13 @@ namespace System.Globalization { if (IsReadOnly) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (patterns == null) { - throw new ArgumentNullException("patterns", + throw new ArgumentNullException(nameof(patterns), Environment.GetResourceString("ArgumentNull_Array")); } if (patterns.Length == 0) { - throw new ArgumentException(Environment.GetResourceString("Arg_ArrayZeroError"), "patterns"); + throw new ArgumentException(Environment.GetResourceString("Arg_ArrayZeroError"), nameof(patterns)); } Contract.EndContractBlock(); @@ -2086,7 +2052,7 @@ namespace System.Globalization { break; default: - throw new ArgumentException(Environment.GetResourceString("Format_BadFormatSpecifier"), "format"); + throw new ArgumentException(Environment.GetResourceString("Format_BadFormatSpecifier"), nameof(format)); } // Clear the token hash table, note that even short dates could require this @@ -2109,12 +2075,12 @@ namespace System.Globalization { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_Array")); } if (value.Length != 13) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 13), "value"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 13), nameof(value)); } Contract.EndContractBlock(); CheckNullValue(value, value.Length - 1); @@ -2137,12 +2103,12 @@ namespace System.Globalization { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) { - throw new ArgumentNullException("value", + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_Array")); } if (value.Length != 13) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 13), "value"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 13), nameof(value)); } Contract.EndContractBlock(); CheckNullValue(value, value.Length - 1); @@ -2396,7 +2362,6 @@ namespace System.Globalization { formatFlags = DateTimeFormatFlags.NotInitialized; } - [System.Security.SecurityCritical] // auto-generated internal TokenHashValue[] CreateTokenHashTable() { TokenHashValue[] temp = m_dtfiTokenHash; if (temp == null) { @@ -2689,7 +2654,7 @@ namespace System.Globalization { } while (i < str.Value.Length && (state != HebrewNumberParsingState.FoundEndOfHebrewNumber)); // When we are here, we are either at the end of the string, or we find a valid Hebrew number. - Contract.Assert(state == HebrewNumberParsingState.ContinueParsing || state == HebrewNumberParsingState.FoundEndOfHebrewNumber, + Debug.Assert(state == HebrewNumberParsingState.ContinueParsing || state == HebrewNumberParsingState.FoundEndOfHebrewNumber, "Invalid returned state from HebrewNumber.ParseByChar()"); if (state != HebrewNumberParsingState.FoundEndOfHebrewNumber) { @@ -2710,13 +2675,12 @@ namespace System.Globalization { return (ch >= '\x0590' && ch <= '\x05ff'); } - [System.Security.SecurityCritical] // auto-generated internal bool Tokenize(TokenType TokenMask, out TokenType tokenType, out int tokenValue, ref __DTString str) { tokenType = TokenType.UnknownToken; tokenValue = 0; TokenHashValue value; - Contract.Assert(str.Index < str.Value.Length, "DateTimeFormatInfo.Tokenize(): start < value.Length"); + Debug.Assert(str.Index < str.Value.Length, "DateTimeFormatInfo.Tokenize(): start < value.Length"); char ch = str.m_current; bool isLetter = Char.IsLetter(ch); @@ -2825,7 +2789,7 @@ namespace System.Globalization { } previousNode = temp; } ; - Contract.Assert(false, "The hashtable is full. This should not happen."); + Debug.Assert(false, "The hashtable is full. This should not happen."); } void InsertHash(TokenHashValue[] hashTable, String str, TokenType tokenType, int tokenValue) { @@ -2877,35 +2841,13 @@ namespace System.Globalization { int nTokenType = (int)tokenType; int nCurrentTokenTypeInHash = (int)value.tokenType; - // The idea behind this check is: - // - if the app is targetting 4.5.1 or above OR the compat flag is set, use the correct behavior by default. - // - if the app is targetting 4.5 or below AND the compat switch is set, use the correct behavior - // - if the app is targetting 4.5 or below AND the compat switch is NOT set, use the incorrect behavior - if (preferExistingTokens || BinaryCompatibility.TargetsAtLeast_Desktop_V4_5_1) + if (((nCurrentTokenTypeInHash & (int)TokenType.RegularTokenMask) == 0) && ((nTokenType & (int)TokenType.RegularTokenMask) != 0) || + ((nCurrentTokenTypeInHash & (int)TokenType.SeparatorTokenMask) == 0) && ((nTokenType & (int)TokenType.SeparatorTokenMask) != 0)) { - if (((nCurrentTokenTypeInHash & (int)TokenType.RegularTokenMask) == 0) && ((nTokenType & (int)TokenType.RegularTokenMask) != 0) || - ((nCurrentTokenTypeInHash & (int)TokenType.SeparatorTokenMask) == 0) && ((nTokenType & (int)TokenType.SeparatorTokenMask) != 0)) - { - value.tokenType |= tokenType; - if (tokenValue != 0) - { - value.tokenValue = tokenValue; - } - } - } - else - { - // The following logic is incorrect and causes updates to happen depending on the bitwise relationship between the existing token type and the - // the stored token type. It was this way in .NET 4 RTM. The behavior above is correct and will be adopted going forward. - - if ((((nTokenType | nCurrentTokenTypeInHash) & (int)TokenType.RegularTokenMask) == nTokenType) || - (((nTokenType | nCurrentTokenTypeInHash) & (int)TokenType.SeparatorTokenMask) == nTokenType)) + value.tokenType |= tokenType; + if (tokenValue != 0) { - value.tokenType |= tokenType; - if (tokenValue != 0) - { - value.tokenValue = tokenValue; - } + value.tokenValue = tokenValue; } } // The token to be inserted is already in the table. Skip it. @@ -2918,7 +2860,7 @@ namespace System.Globalization { hashcode += hashProbe; if (hashcode >= TOKEN_HASH_SIZE) hashcode -= TOKEN_HASH_SIZE; } while (i < TOKEN_HASH_SIZE); - Contract.Assert(false, "The hashtable is full. This should not happen."); + Debug.Assert(false, "The hashtable is full. This should not happen."); } } // class DateTimeFormatInfo diff --git a/src/mscorlib/src/System/Globalization/DateTimeFormatInfoScanner.cs b/src/mscorlib/src/System/Globalization/DateTimeFormatInfoScanner.cs index 40cbabc..4555bb2 100644 --- a/src/mscorlib/src/System/Globalization/DateTimeFormatInfoScanner.cs +++ b/src/mscorlib/src/System/Globalization/DateTimeFormatInfoScanner.cs @@ -498,9 +498,6 @@ namespace System.Globalization // //////////////////////////////////////////////////////////////////////////// - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal String[] GetDateWordsOfDTFI(DateTimeFormatInfo dtfi) { // Enumarate all LongDatePatterns, and get the DateWords and scan for month postfix. String[] datePatterns = dtfi.GetAllDateTimePatterns('D'); diff --git a/src/mscorlib/src/System/Globalization/DateTimeParse.cs b/src/mscorlib/src/System/Globalization/DateTimeParse.cs index 8de3242..363747c 100644 --- a/src/mscorlib/src/System/Globalization/DateTimeParse.cs +++ b/src/mscorlib/src/System/Globalization/DateTimeParse.cs @@ -35,16 +35,6 @@ namespace System { internal static MatchNumberDelegate m_hebrewNumberParser = new MatchNumberDelegate(DateTimeParse.MatchHebrewDigits); -#if !FEATURE_CORECLR - [SecuritySafeCritical] - internal static bool GetAmPmParseFlag() - { - return DateTime.EnableAmPmParseAdjustment(); - } - - internal static bool enableAmPmParseAdjustment = GetAmPmParseFlag(); -#endif - internal static DateTime ParseExact(String s, String format, DateTimeFormatInfo dtfi, DateTimeStyles style) { DateTimeResult result = new DateTimeResult(); // The buffer to store the parsing result. result.Init(); @@ -97,11 +87,11 @@ namespace System { internal static bool TryParseExact(String s, String format, DateTimeFormatInfo dtfi, DateTimeStyles style, ref DateTimeResult result) { if (s == null) { - result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "s"); + result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, nameof(s)); return false; } if (format == null) { - result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "format"); + result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, nameof(format)); return false; } if (s.Length == 0) { @@ -114,7 +104,7 @@ namespace System { return false; } - Contract.Assert(dtfi != null, "dtfi == null"); + Debug.Assert(dtfi != null, "dtfi == null"); return DoStrictParse(s, format, style, dtfi, ref result); } @@ -178,11 +168,11 @@ namespace System { internal static bool TryParseExactMultiple(String s, String[] formats, DateTimeFormatInfo dtfi, DateTimeStyles style, ref DateTimeResult result) { if (s == null) { - result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "s"); + result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, nameof(s)); return false; } if (formats == null) { - result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "formats"); + result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, nameof(formats)); return false; } @@ -196,7 +186,7 @@ namespace System { return false; } - Contract.Assert(dtfi != null, "dtfi == null"); + Debug.Assert(dtfi != null, "dtfi == null"); // // Do a loop through the provided formats and see if we can parse succesfully in @@ -546,8 +536,8 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, // Wrong number of digits return false; } - Contract.Assert(hourOffset >= 0 && hourOffset <= 99, "hourOffset >= 0 && hourOffset <= 99"); - Contract.Assert(minuteOffset >= 0 && minuteOffset <= 99, "minuteOffset >= 0 && minuteOffset <= 99"); + Debug.Assert(hourOffset >= 0 && hourOffset <= 99, "hourOffset >= 0 && hourOffset <= 99"); + Debug.Assert(minuteOffset >= 0 && minuteOffset <= 99, "minuteOffset >= 0 && minuteOffset <= 99"); if (minuteOffset < 0 || minuteOffset >= 60) { return false; } @@ -591,7 +581,6 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, // This is the lexer. Check the character at the current index, and put the found token in dtok and // some raw date/time information in raw. // - [System.Security.SecuritySafeCritical] // auto-generated private static Boolean Lex(DS dps, ref __DTString str, ref DateTimeToken dtok, ref DateTimeRawInfo raw, ref DateTimeResult result, ref DateTimeFormatInfo dtfi, DateTimeStyles styles) { @@ -761,11 +750,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, raw.timeMark = (sep == TokenType.SEP_Am ? TM.AM : TM.PM); dtok.dtt = DTT.NumAmpm; // Fix AM/PM parsing case, e.g. "1/10 5 AM" - if (dps == DS.D_NN -#if !FEATURE_CORECLR - && enableAmPmParseAdjustment -#endif - ) + if (dps == DS.D_NN) { if (!ProcessTerminaltState(DS.DX_NN, ref result, ref styles, ref raw, dtfi)) { @@ -1076,16 +1061,6 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, return (false); } -#if !FEATURE_CORECLR - // If DateTimeParseIgnorePunctuation is defined, we want to have the V1.1 behavior of just - // ignoring any unrecognized punctuation and moving on to the next character - if (Environment.GetCompatibilityFlag(CompatibilityFlag.DateTimeParseIgnorePunctuation) && ((result.flags & ParseFlags.CaptureOffset) == 0)) { - str.GetNext(); - LexTraceExit("0210 (success)", dps); - return true; - } -#endif // FEATURE_CORECLR - if ((str.m_current == '-' || str.m_current == '+') && ((result.flags & ParseFlags.TimeZoneUsed) == 0)) { Int32 originalIndex = str.Index; if (ParseTimeZone(ref str, ref result.timeZoneOffset)) { @@ -1096,7 +1071,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, else { // Time zone parse attempt failed. Fall through to punctuation handling. str.Index = originalIndex; - } + } } // Visual Basic implements string to date conversions on top of DateTime.Parse: @@ -1104,7 +1079,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, // if (VerifyValidPunctuation(ref str)) { LexTraceExit("0230 (success)", dps); - return true; + return true; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); @@ -1936,7 +1911,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, private static Boolean GetTimeOfNN(DateTimeFormatInfo dtfi, ref DateTimeResult result, ref DateTimeRawInfo raw) { - Contract.Assert(raw.numCount >= 2, "raw.numCount >= 2"); + Debug.Assert(raw.numCount >= 2, "raw.numCount >= 2"); if ((result.flags & ParseFlags.HaveTime) != 0) { // Multiple times in the input string result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); @@ -1956,7 +1931,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } - Contract.Assert(raw.numCount >= 3, "raw.numCount >= 3"); + Debug.Assert(raw.numCount >= 3, "raw.numCount >= 3"); result.Hour = raw.GetNumber(0); result.Minute = raw.GetNumber(1); result.Second = raw.GetNumber(2); @@ -2316,10 +2291,9 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, // // This is the real method to do the parsing work. // - [System.Security.SecuritySafeCritical] // auto-generated internal static bool TryParse(String s, DateTimeFormatInfo dtfi, DateTimeStyles styles, ref DateTimeResult result) { if (s == null) { - result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "s"); + result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, nameof(s)); return false; } if (s.Length == 0) { @@ -2327,7 +2301,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, return false; } - Contract.Assert(dtfi != null, "dtfi == null"); + Debug.Assert(dtfi != null, "dtfi == null"); #if _LOGGING DTFITrace(dtfi); @@ -2548,17 +2522,15 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, // no adjustment is required in most cases return DateTimeOffsetTimeZonePostProcessing(ref result, styles); } -#if FEATURE_CORECLR // on CoreCLR DateTime is also restricted to +- 14:00, just like DateTimeOffset else { Int64 offsetTicks = result.timeZoneOffset.Ticks; - + // the DateTime offset must be within +- 14:00 hours. if (offsetTicks < DateTimeOffset.MinOffset || offsetTicks > DateTimeOffset.MaxOffset) { result.SetFailure(ParseFailureKind.Format, "Format_OffsetOutOfRange", null); return false; } } -#endif // FEATURE_CORECLR // The flags AssumeUniveral and AssumeLocal only apply when the input does not have a time zone if ((result.flags & ParseFlags.TimeZoneUsed) == 0) { @@ -2592,7 +2564,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, } else { // No time zone and no Assume flags, so DateTimeKind.Unspecified is fine - Contract.Assert(result.parsedDate.Kind == DateTimeKind.Unspecified, "result.parsedDate.Kind == DateTimeKind.Unspecified"); + Debug.Assert(result.parsedDate.Kind == DateTimeKind.Unspecified, "result.parsedDate.Kind == DateTimeKind.Unspecified"); return true; } } @@ -2882,9 +2854,9 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, } internal static bool ParseDigits(ref __DTString str, int minDigitLen, int maxDigitLen, out int result) { - Contract.Assert(minDigitLen > 0, "minDigitLen > 0"); - Contract.Assert(maxDigitLen < 9, "maxDigitLen < 9"); - Contract.Assert(minDigitLen <= maxDigitLen, "minDigitLen <= maxDigitLen"); + Debug.Assert(minDigitLen > 0, "minDigitLen > 0"); + Debug.Assert(maxDigitLen < 9, "maxDigitLen < 9"); + Debug.Assert(minDigitLen <= maxDigitLen, "minDigitLen <= maxDigitLen"); result = 0; int startingIndex = str.Index; int tokenLength = 0; @@ -4151,7 +4123,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, case ParseFailureKind.FormatBadDateTimeCalendar: return new FormatException(Environment.GetResourceString(result.failureMessageID, result.calendar)); default: - Contract.Assert(false, "Unkown DateTimeParseFailure: " + result); + Debug.Assert(false, "Unkown DateTimeParseFailure: " + result); return null; } @@ -4373,7 +4345,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, } internal bool Advance(int count) { - Contract.Assert(Index + count <= len, "__DTString::Advance: Index + count <= len"); + Debug.Assert(Index + count <= len, "__DTString::Advance: Index + count <= len"); Index += count; if (Index < len) { m_current = Value[Index]; @@ -4384,7 +4356,6 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, // Used by DateTime.Parse() to get the next token. - [System.Security.SecurityCritical] // auto-generated internal void GetRegularToken(out TokenType tokenType, out int tokenValue, DateTimeFormatInfo dtfi) { tokenValue = 0; if (Index >= len) { @@ -4464,7 +4435,6 @@ Start: } } - [System.Security.SecurityCritical] // auto-generated internal TokenType GetSeparatorToken(DateTimeFormatInfo dtfi, out int indexBeforeSeparator, out char charBeforeSeparator) { indexBeforeSeparator = Index; charBeforeSeparator = m_current; @@ -4668,7 +4638,7 @@ Start: // Get the current character. // internal char GetChar() { - Contract.Assert(Index >= 0 && Index < len, "Index >= 0 && Index < len"); + Debug.Assert(Index >= 0 && Index < len, "Index >= 0 && Index < len"); return (Value[Index]); } @@ -4676,8 +4646,8 @@ Start: // Convert the current character to a digit, and return it. // internal int GetDigit() { - Contract.Assert(Index >= 0 && Index < len, "Index >= 0 && Index < len"); - Contract.Assert(DateTimeParse.IsDigit(Value[Index]), "IsDigit(Value[Index])"); + Debug.Assert(Index >= 0 && Index < len, "Index >= 0 && Index < len"); + Debug.Assert(DateTimeParse.IsDigit(Value[Index]), "IsDigit(Value[Index])"); return (Value[Index] - '0'); } @@ -4810,7 +4780,7 @@ Start: return sub; } int number = ch - '0'; - Contract.Assert(number >= 0 && number <= 9, "number >= 0 && number <= 9"); + Debug.Assert(number >= 0 && number <= 9, "number >= 0 && number <= 9"); sub.value = sub.value * 10 + number; } else { @@ -4829,8 +4799,8 @@ Start: } internal void ConsumeSubString(DTSubString sub) { - Contract.Assert(sub.index == Index, "sub.index == Index"); - Contract.Assert(sub.index + sub.length <= len, "sub.index + sub.length <= len"); + Debug.Assert(sub.index == Index, "sub.index == Index"); + Debug.Assert(sub.index + sub.length <= len, "sub.index + sub.length <= len"); Index = sub.index + sub.length; if (Index < len) { m_current = Value[Index]; @@ -4875,7 +4845,6 @@ Start: // internal unsafe struct DateTimeRawInfo { - [SecurityCritical] private int* num; internal int numCount; internal int month; @@ -4889,7 +4858,6 @@ Start: internal bool timeZone; - [System.Security.SecurityCritical] // auto-generated internal void Init(int * numberBuffer) { month = -1; year = -1; @@ -4899,11 +4867,9 @@ Start: fraction = -1; num = numberBuffer; } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe void AddNumber(int value) { num[numCount++] = value; } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe int GetNumber(int index) { return num[index]; } diff --git a/src/mscorlib/src/System/Globalization/DaylightTime.cs b/src/mscorlib/src/System/Globalization/DaylightTime.cs index 037d9ff..a164867 100644 --- a/src/mscorlib/src/System/Globalization/DaylightTime.cs +++ b/src/mscorlib/src/System/Globalization/DaylightTime.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Globalization { - - using System; +using System.Runtime.InteropServices; + +namespace System.Globalization +{ // This class represents a starting/ending time for a period of daylight saving time. [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] + [ComVisible(true)] public class DaylightTime { internal DateTime m_start; @@ -46,4 +47,18 @@ namespace System.Globalization { } + // Value type version of DaylightTime + internal struct DaylightTimeStruct + { + public DaylightTimeStruct(DateTime start, DateTime end, TimeSpan delta) + { + Start = start; + End = end; + Delta = delta; + } + + public DateTime Start { get; } + public DateTime End { get; } + public TimeSpan Delta { get; } + } } diff --git a/src/mscorlib/src/System/Globalization/EastAsianLunisolarCalendar.cs b/src/mscorlib/src/System/Globalization/EastAsianLunisolarCalendar.cs index 2460eee..3c9391f 100644 --- a/src/mscorlib/src/System/Globalization/EastAsianLunisolarCalendar.cs +++ b/src/mscorlib/src/System/Globalization/EastAsianLunisolarCalendar.cs @@ -65,7 +65,7 @@ namespace System.Globalization { public int GetCelestialStem(int sexagenaryYear) { if ((sexagenaryYear < 1) || (sexagenaryYear > 60)) { throw new ArgumentOutOfRangeException( - "sexagenaryYear", + nameof(sexagenaryYear), Environment.GetResourceString("ArgumentOutOfRange_Range", 1, 60)); } Contract.EndContractBlock(); @@ -80,7 +80,7 @@ namespace System.Globalization { public int GetTerrestrialBranch(int sexagenaryYear) { if ((sexagenaryYear < 1) || (sexagenaryYear > 60)) { throw new ArgumentOutOfRangeException( - "sexagenaryYear", + nameof(sexagenaryYear), Environment.GetResourceString("ArgumentOutOfRange_Range", 1, 60)); } Contract.EndContractBlock(); @@ -121,7 +121,7 @@ namespace System.Globalization { return (mEraInfo[i].minEraYear); } } - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); } internal int MaxEraCalendarYear (int era) { @@ -144,7 +144,7 @@ namespace System.Globalization { return (mEraInfo[i].maxEraYear); } } - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); } // Construct an instance of EastAsianLunisolar calendar. @@ -168,7 +168,7 @@ namespace System.Globalization { } if ((era GetEra(MaxDate))) { - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); } } @@ -178,7 +178,7 @@ namespace System.Globalization { if ((year < MinCalendarYear) || (year > MaxCalendarYear)) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), Environment.GetResourceString("ArgumentOutOfRange_Range", MinEraCalendarYear(era), MaxEraCalendarYear(era))); } return year; @@ -191,11 +191,11 @@ namespace System.Globalization { { //Reject if there is no leap month this year if (GetYearInfo(year , LeapMonth) == 0) - throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month")); + throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Month")); } if (month < 1 || month > 13) { - throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month")); + throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Month")); } return year; } @@ -236,7 +236,7 @@ namespace System.Globalization { if (day < 1 || day > daysInMonth) { BCLDebug.Log("year = " + year + ", month = " + month + ", day = " + day); throw new ArgumentOutOfRangeException( - "day", + nameof(day), Environment.GetResourceString("ArgumentOutOfRange_Day", daysInMonth, month)); } @@ -399,7 +399,7 @@ namespace System.Globalization { public override DateTime AddMonths(DateTime time, int months) { if (months < -120000 || months > 120000) { throw new ArgumentOutOfRangeException( - "months", + nameof(months), Environment.GetResourceString("ArgumentOutOfRange_Range", -120000, 120000)); } Contract.EndContractBlock(); @@ -561,7 +561,7 @@ namespace System.Globalization { if (day < 1 || day > daysInMonth) { throw new ArgumentOutOfRangeException( - "day", + nameof(day), Environment.GetResourceString("ArgumentOutOfRange_Day", daysInMonth, month)); } int m = GetYearInfo(year, LeapMonth); @@ -620,7 +620,7 @@ namespace System.Globalization { if (value < 99 || value > MaxCalendarYear) { throw new ArgumentOutOfRangeException( - "value", + nameof(value), Environment.GetResourceString("ArgumentOutOfRange_Range", 99, MaxCalendarYear)); } twoDigitYearMax = value; @@ -630,7 +630,7 @@ namespace System.Globalization { public override int ToFourDigitYear(int year) { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/Globalization/EncodingDataItem.cs b/src/mscorlib/src/System/Globalization/EncodingDataItem.cs index 1dc1bd2..89ac780 100644 --- a/src/mscorlib/src/System/Globalization/EncodingDataItem.cs +++ b/src/mscorlib/src/System/Globalization/EncodingDataItem.cs @@ -27,14 +27,12 @@ namespace System.Globalization { internal String m_bodyName; internal uint m_flags; - [SecurityCritical] unsafe internal CodePageDataItem(int dataIndex) { m_dataIndex = dataIndex; m_uiFamilyCodePage = EncodingTable.codePageDataPtr[dataIndex].uiFamilyCodePage; m_flags = EncodingTable.codePageDataPtr[dataIndex].flags; } - [System.Security.SecurityCritical] unsafe internal static String CreateString(sbyte* pStrings, uint index) { if (pStrings[0] == '|') // |str1|str2|str3 @@ -62,7 +60,7 @@ namespace System.Globalization { } } - throw new ArgumentException("pStrings"); + throw new ArgumentException(null, nameof(pStrings)); } else { @@ -71,7 +69,6 @@ namespace System.Globalization { } unsafe public String WebName { - [System.Security.SecuritySafeCritical] // auto-generated get { if (m_webName==null) { m_webName = CreateString(EncodingTable.codePageDataPtr[m_dataIndex].Names, 0); @@ -87,7 +84,6 @@ namespace System.Globalization { } unsafe public String HeaderName { - [System.Security.SecuritySafeCritical] // auto-generated get { if (m_headerName==null) { m_headerName = CreateString(EncodingTable.codePageDataPtr[m_dataIndex].Names, 1); @@ -97,7 +93,6 @@ namespace System.Globalization { } unsafe public String BodyName { - [System.Security.SecuritySafeCritical] // auto-generated get { if (m_bodyName==null) { m_bodyName = CreateString(EncodingTable.codePageDataPtr[m_dataIndex].Names, 2); diff --git a/src/mscorlib/src/System/Globalization/EncodingTable.Unix.cs b/src/mscorlib/src/System/Globalization/EncodingTable.Unix.cs index 5628a2d..0fce2e5 100644 --- a/src/mscorlib/src/System/Globalization/EncodingTable.Unix.cs +++ b/src/mscorlib/src/System/Globalization/EncodingTable.Unix.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Text; @@ -30,7 +31,7 @@ namespace System.Globalization { if (name == null) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } Contract.EndContractBlock(); @@ -44,7 +45,7 @@ namespace System.Globalization throw new ArgumentException( string.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("Argument_EncodingNotSupported"), name), "name"); + Environment.GetResourceString("Argument_EncodingNotSupported"), name), nameof(name)); } internal static CodePageDataItem GetCodePageDataItem(int codepage) @@ -82,7 +83,7 @@ namespace System.Globalization break; } - Contract.Assert(item == null || item.CodePage == codepage, "item.CodePage needs to equal the specified codepage"); + Debug.Assert(item == null || item.CodePage == codepage, "item.CodePage needs to equal the specified codepage"); return item; } @@ -91,7 +92,7 @@ namespace System.Globalization #if DEBUG static EncodingTable() { - Contract.Assert( + Debug.Assert( s_encodingDataTable.Count == EncodingTableCapacity, string.Format(CultureInfo.InvariantCulture, "EncodingTable s_encodingDataTable's initial capacity (EncodingTableCapacity) is incorrect.{0}Expected (s_encodingDataTable.Count): {1}, Actual (EncodingTableCapacity): {2}", diff --git a/src/mscorlib/src/System/Globalization/EncodingTable.cs b/src/mscorlib/src/System/Globalization/EncodingTable.cs index cdda9ea..d908a2a 100644 --- a/src/mscorlib/src/System/Globalization/EncodingTable.cs +++ b/src/mscorlib/src/System/Globalization/EncodingTable.cs @@ -34,13 +34,11 @@ namespace System.Globalization // // This points to a native data table which maps an encoding name to the correct code page. // - [SecurityCritical] unsafe internal static InternalEncodingDataItem *encodingDataPtr = GetEncodingData(); // // This points to a native data table which stores the properties for the code page, and // the table is indexed by code page. // - [SecurityCritical] unsafe internal static InternalCodePageDataItem *codePageDataPtr = GetCodePageData(); // // This caches the mapping of an encoding name to a code page. @@ -51,14 +49,12 @@ namespace System.Globalization // private static Hashtable hashByCodePage = Hashtable.Synchronized(new Hashtable()); - [System.Security.SecuritySafeCritical] // static constructors should be safe to call static EncodingTable() { } // Find the data item by binary searching the table that we have in native. // nativeCompareOrdinalWC is an internal-only function. - [System.Security.SecuritySafeCritical] // auto-generated unsafe private static int internalGetCodePageFromName(String name) { int left = 0; int right = lastEncodingItem; @@ -94,11 +90,10 @@ namespace System.Globalization throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("Argument_EncodingNotSupported"), name), "name"); + Environment.GetResourceString("Argument_EncodingNotSupported"), name), nameof(name)); } // Return a list of all EncodingInfo objects describing all of our encodings - [System.Security.SecuritySafeCritical] // auto-generated internal static unsafe EncodingInfo[] GetEncodings() { if (lastCodePageItem == 0) @@ -136,7 +131,7 @@ namespace System.Globalization internal static int GetCodePageFromName(String name) { if (name==null) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } Contract.EndContractBlock(); @@ -161,7 +156,6 @@ namespace System.Globalization return codePage; } - [System.Security.SecuritySafeCritical] // auto-generated unsafe internal static CodePageDataItem GetCodePageDataItem(int codepage) { CodePageDataItem dataItem; @@ -198,22 +192,18 @@ namespace System.Globalization return null; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private unsafe static extern InternalEncodingDataItem *GetEncodingData(); // // Return the number of encoding data items. // - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern int GetNumEncodingItems(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private unsafe static extern InternalCodePageDataItem* GetCodePageData(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal unsafe static extern byte* nativeCreateOpenFileMapping( String inSectionName, int inBytesToAllocate, out IntPtr mappedFileHandle); @@ -228,7 +218,6 @@ namespace System.Globalization [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)] internal unsafe struct InternalEncodingDataItem { - [SecurityCritical] internal sbyte * webName; internal UInt16 codePage; } @@ -243,7 +232,6 @@ namespace System.Globalization internal UInt16 codePage; internal UInt16 uiFamilyCodePage; internal uint flags; - [SecurityCritical] internal sbyte * Names; } diff --git a/src/mscorlib/src/System/Globalization/GlobalizationAssembly.cs b/src/mscorlib/src/System/Globalization/GlobalizationAssembly.cs index 4de3fd3..0810d67 100644 --- a/src/mscorlib/src/System/Globalization/GlobalizationAssembly.cs +++ b/src/mscorlib/src/System/Globalization/GlobalizationAssembly.cs @@ -15,6 +15,7 @@ namespace System.Globalization { using System.Runtime.ConstrainedExecution; using System.Runtime.Versioning; using System.IO; + using System.Diagnostics; using System.Diagnostics.Contracts; @@ -32,10 +33,9 @@ namespace System.Globalization { // Instance data members and instance methods. // // ---------------------------------------------------------------------------------------------------- - [System.Security.SecurityCritical] // auto-generated internal unsafe static byte* GetGlobalizationResourceBytePtr(Assembly assembly, String tableName) { - Contract.Assert(assembly != null, "assembly can not be null. This should be generally the "+System.CoreLib.Name+" assembly."); - Contract.Assert(tableName != null, "table name can not be null"); + Debug.Assert(assembly != null, "assembly can not be null. This should be generally the "+System.CoreLib.Name+" assembly."); + Debug.Assert(tableName != null, "table name can not be null"); Stream stream = assembly.GetManifestResourceStream(tableName); UnmanagedMemoryStream bytesStream = stream as UnmanagedMemoryStream; @@ -46,7 +46,7 @@ namespace System.Globalization { } } - Contract.Assert( + Debug.Assert( false, String.Format( CultureInfo.CurrentCulture, diff --git a/src/mscorlib/src/System/Globalization/GregorianCalendar.cs b/src/mscorlib/src/System/Globalization/GregorianCalendar.cs index e540add..6cf9b2e 100644 --- a/src/mscorlib/src/System/Globalization/GregorianCalendar.cs +++ b/src/mscorlib/src/System/Globalization/GregorianCalendar.cs @@ -132,7 +132,7 @@ namespace System.Globalization { public GregorianCalendar(GregorianCalendarTypes type) { if ((int)type < (int)GregorianCalendarTypes.Localized || (int)type > (int)GregorianCalendarTypes.TransliteratedFrench) { throw new ArgumentOutOfRangeException( - "type", + nameof(type), Environment.GetResourceString("ArgumentOutOfRange_Range", GregorianCalendarTypes.Localized, GregorianCalendarTypes.TransliteratedFrench)); } @@ -159,7 +159,7 @@ namespace System.Globalization { break; default: - throw new ArgumentOutOfRangeException("m_type", Environment.GetResourceString("ArgumentOutOfRange_Enum")); + throw new ArgumentOutOfRangeException(nameof(m_type), Environment.GetResourceString("ArgumentOutOfRange_Enum")); } } } @@ -217,7 +217,7 @@ namespace System.Globalization { int[] days = leapYear? DaysToMonth366: DaysToMonth365; // All months have less than 32 days, so n >> 5 is a good conservative // estimate for the month - int m = n >> 5 + 1; + int m = (n >> 5) + 1; // m = 1-based month number while (n >= days[m]) m++; // If month was requested, return it @@ -285,7 +285,7 @@ namespace System.Globalization { { if (months < -120000 || months > 120000) { throw new ArgumentOutOfRangeException( - "months", + nameof(months), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -371,16 +371,16 @@ namespace System.Globalization { public override int GetDaysInMonth(int year, int month, int era) { if (era == CurrentEra || era == ADEra) { if (year < 1 || year > MaxYear) { - throw new ArgumentOutOfRangeException("year", Environment.GetResourceString("ArgumentOutOfRange_Range", + throw new ArgumentOutOfRangeException(nameof(year), Environment.GetResourceString("ArgumentOutOfRange_Range", 1, MaxYear)); } if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month")); + throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Month")); } int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366: DaysToMonth365); return (days[month] - days[month - 1]); } - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); } // Returns the number of days in the year given by the year argument for the current era. @@ -393,14 +393,14 @@ namespace System.Globalization { return ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? 366:365); } throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), 1, MaxYear)); } - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); } // Returns the era for the specified DateTime value. @@ -437,14 +437,14 @@ namespace System.Globalization { return (12); } throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), 1, MaxYear)); } - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); } // Returns the year part of the specified DateTime. The returned value is an @@ -463,23 +463,23 @@ namespace System.Globalization { public override bool IsLeapDay(int year, int month, int day, int era) { if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Range", + throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Range", 1, 12)); } Contract.EndContractBlock(); if (era != CurrentEra && era != ADEra) { - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); } if (year < 1 || year > MaxYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), Environment.GetResourceString("ArgumentOutOfRange_Range", 1, MaxYear)); } if (day < 1 || day > GetDaysInMonth(year, month)) { - throw new ArgumentOutOfRangeException("day", Environment.GetResourceString("ArgumentOutOfRange_Range", + throw new ArgumentOutOfRangeException(nameof(day), Environment.GetResourceString("ArgumentOutOfRange_Range", 1, GetDaysInMonth(year, month))); } if (!IsLeapYear(year)) { @@ -500,11 +500,11 @@ namespace System.Globalization { { if (era != CurrentEra && era != ADEra) { - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); } if (year < 1 || year > MaxYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), 1, MaxYear)); @@ -520,19 +520,19 @@ namespace System.Globalization { public override bool IsLeapMonth(int year, int month, int era) { if (era != CurrentEra && era != ADEra) { - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); } if (year < 1 || year > MaxYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), 1, MaxYear)); } if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Range", + throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Range", 1, 12)); } Contract.EndContractBlock(); @@ -551,12 +551,12 @@ namespace System.Globalization { } throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), 1, MaxYear)); } - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); } // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid. @@ -567,7 +567,7 @@ namespace System.Globalization { if (era == CurrentEra || era == ADEra) { return new DateTime(year, month, day, hour, minute, second, millisecond); } - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); } internal override Boolean TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result) { @@ -609,14 +609,14 @@ namespace System.Globalization { public override int ToFourDigitYear(int year) { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.EndContractBlock(); if (year > MaxYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), 1, MaxYear)); diff --git a/src/mscorlib/src/System/Globalization/GregorianCalendarHelper.cs b/src/mscorlib/src/System/Globalization/GregorianCalendarHelper.cs index 75b280d..062ae48 100644 --- a/src/mscorlib/src/System/Globalization/GregorianCalendarHelper.cs +++ b/src/mscorlib/src/System/Globalization/GregorianCalendarHelper.cs @@ -153,7 +153,7 @@ namespace System.Globalization { internal int GetGregorianYear(int year, int era) { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.EndContractBlock(); @@ -166,7 +166,7 @@ namespace System.Globalization { if (era == m_EraInfo[i].era) { if (year < m_EraInfo[i].minEraYear || year > m_EraInfo[i].maxEraYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -176,7 +176,7 @@ namespace System.Globalization { return (m_EraInfo[i].yearOffset + year); } } - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); } internal bool IsValidYear(int year, int era) { @@ -243,7 +243,7 @@ namespace System.Globalization { int[] days = leapYear? DaysToMonth366: DaysToMonth365; // All months have less than 32 days, so n >> 5 is a good conservative // estimate for the month - int m = n >> 5 + 1; + int m = (n >> 5) + 1; // m = 1-based month number while (n >= days[m]) m++; // If month was requested, return it @@ -299,7 +299,7 @@ namespace System.Globalization { { if (millisecond < 0 || millisecond >= MillisPerSecond) { throw new ArgumentOutOfRangeException( - "millisecond", + nameof(millisecond), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -346,7 +346,7 @@ namespace System.Globalization { { if (months < -120000 || months > 120000) { throw new ArgumentOutOfRangeException( - "months", + nameof(months), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -432,7 +432,7 @@ namespace System.Globalization { // year = GetGregorianYear(year, era); if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month")); + throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Month")); } int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366: DaysToMonth365); return (days[month] - days[month - 1]); @@ -460,7 +460,7 @@ namespace System.Globalization { return (m_EraInfo[i].era); } } - throw new ArgumentOutOfRangeException("time", Environment.GetResourceString("ArgumentOutOfRange_Era")); + throw new ArgumentOutOfRangeException(nameof(time), Environment.GetResourceString("ArgumentOutOfRange_Era")); } @@ -533,7 +533,7 @@ namespace System.Globalization { // year/month/era checking is done in GetDaysInMonth() if (day < 1 || day > GetDaysInMonth(year, month, era)) { throw new ArgumentOutOfRangeException( - "day", + nameof(day), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -570,7 +570,7 @@ namespace System.Globalization { year = GetGregorianYear(year, era); if (month < 1 || month > 12) { throw new ArgumentOutOfRangeException( - "month", + nameof(month), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -607,7 +607,7 @@ namespace System.Globalization { public int ToFourDigitYear(int year, int twoDigitYearMax) { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); } Contract.EndContractBlock(); @@ -619,7 +619,7 @@ namespace System.Globalization { if (year < m_minYear || year > m_maxYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), m_minYear, m_maxYear)); diff --git a/src/mscorlib/src/System/Globalization/HebrewCalendar.cs b/src/mscorlib/src/System/Globalization/HebrewCalendar.cs index 3a17494..44cbdb8 100644 --- a/src/mscorlib/src/System/Globalization/HebrewCalendar.cs +++ b/src/mscorlib/src/System/Globalization/HebrewCalendar.cs @@ -5,6 +5,7 @@ namespace System.Globalization { using System; using System.Text; + using System.Diagnostics; using System.Diagnostics.Contracts; //////////////////////////////////////////////////////////////////////////// @@ -397,7 +398,7 @@ namespace System.Globalization { int monthsInYear = GetMonthsInYear(year, era); if (month < 1 || month > monthsInYear) { throw new ArgumentOutOfRangeException( - "month", + nameof(month), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -421,7 +422,7 @@ namespace System.Globalization { int daysInMonth = GetDaysInMonth(year, month, era); if (day < 1 || day > daysInMonth) { throw new ArgumentOutOfRangeException( - "day", + nameof(day), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -432,7 +433,7 @@ namespace System.Globalization { static internal void CheckEraRange(int era) { if (era != CurrentEra && era != HebrewEra) { - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); } } @@ -486,7 +487,7 @@ namespace System.Globalization { // int index = gregorianYear - FirstGregorianTableYear; if (index < 0 || index > TABLESIZE) { - throw new ArgumentOutOfRangeException("gregorianYear"); + throw new ArgumentOutOfRangeException(nameof(gregorianYear)); } index *= 2; @@ -607,7 +608,7 @@ namespace System.Globalization { // is true. // NumDays -= (long)(LunarMonthLen[hebrewYearType, lunarDate.month] - lunarDate.day); - Contract.Assert(NumDays >= 1, "NumDays >= 1"); + Debug.Assert(NumDays >= 1, "NumDays >= 1"); // If NumDays is 1, then we are done. Otherwise, find the correct Hebrew month // and day. @@ -705,7 +706,7 @@ namespace System.Globalization { catch (ArgumentException) { throw new ArgumentOutOfRangeException( - "months", + nameof(months), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_AddValue"))); @@ -727,7 +728,7 @@ namespace System.Globalization { int d = GetDatePart(time.Ticks, DatePartDay); y += years; - CheckHebrewYearValue(y, Calendar.CurrentEra, "years"); + CheckHebrewYearValue(y, Calendar.CurrentEra, nameof(years)); int months = GetMonthsInYear(y, CurrentEra); if (m > months) { @@ -765,7 +766,7 @@ namespace System.Globalization { } static internal int GetHebrewYearType(int year, int era) { - CheckHebrewYearValue(year, era, "year"); + CheckHebrewYearValue(year, era, nameof(year)); // The HebrewTable is indexed by Gregorian year and starts from FirstGregorianYear. // So we need to convert year (Hebrew year value) to Gregorian Year below. return (HebrewTable[(year - HebrewYearOf1AD - FirstGregorianTableYear) * 2 + 1]); @@ -811,11 +812,11 @@ namespace System.Globalization { int hebrewYearType = GetHebrewYearType(year, era); CheckHebrewMonthValue(year, month, era); - Contract.Assert(hebrewYearType>= 1 && hebrewYearType <= 6, + Debug.Assert(hebrewYearType>= 1 && hebrewYearType <= 6, "hebrewYearType should be from 1 to 6, but now hebrewYearType = " + hebrewYearType + " for hebrew year " + year); int monthDays = LunarMonthLen[hebrewYearType, month]; if (monthDays == 0) { - throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month")); + throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Month")); } return (monthDays); } @@ -931,7 +932,7 @@ namespace System.Globalization { // public override bool IsLeapYear(int year, int era) { - CheckHebrewYearValue(year, era, "year"); + CheckHebrewYearValue(year, era, nameof(year)); return (((7 * (long)year + 1) % 19) < 7); } @@ -1015,7 +1016,7 @@ namespace System.Globalization { // public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) { - CheckHebrewYearValue(year, era, "year"); + CheckHebrewYearValue(year, era, nameof(year)); CheckHebrewMonthValue(year, month, era); CheckHebrewDayValue(year, month, day, era); DateTime dt = HebrewToGregorian(year, month, day, hour, minute, second, millisecond); @@ -1042,7 +1043,7 @@ namespace System.Globalization { } else { - CheckHebrewYearValue(value, HebrewEra, "value"); + CheckHebrewYearValue(value, HebrewEra, nameof(value)); } twoDigitYearMax = value; } @@ -1051,7 +1052,7 @@ namespace System.Globalization { public override int ToFourDigitYear(int year) { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.EndContractBlock(); @@ -1062,7 +1063,7 @@ namespace System.Globalization { if (year > MaxHebrewYear || year < MinHebrewYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), diff --git a/src/mscorlib/src/System/Globalization/HebrewNumber.cs b/src/mscorlib/src/System/Globalization/HebrewNumber.cs index cf05955..5517cb1 100644 --- a/src/mscorlib/src/System/Globalization/HebrewNumber.cs +++ b/src/mscorlib/src/System/Globalization/HebrewNumber.cs @@ -6,6 +6,7 @@ namespace System.Globalization { using System; using System.Text; + using System.Diagnostics; using System.Diagnostics.Contracts; //////////////////////////////////////////////////////////////////////////// @@ -98,7 +99,7 @@ namespace System.Globalization { Number -= 5000; } - Contract.Assert(Number > 0 && Number <= 999, "Number is out of range.");; + Debug.Assert(Number > 0 && Number <= 999, "Number is out of range.");; // // Get the Hundreds. diff --git a/src/mscorlib/src/System/Globalization/HijriCalendar.cs b/src/mscorlib/src/System/Globalization/HijriCalendar.cs index 194d329..39a01e5 100644 --- a/src/mscorlib/src/System/Globalization/HijriCalendar.cs +++ b/src/mscorlib/src/System/Globalization/HijriCalendar.cs @@ -209,7 +209,6 @@ namespace System.Globalization { public int HijriAdjustment { - [System.Security.SecuritySafeCritical] // auto-generated get { if (m_HijriAdvance == Int32.MinValue) { // Never been set before. Use the system value from registry. @@ -222,7 +221,7 @@ namespace System.Globalization { // NOTE: Check the value of Min/MaxAdavncedHijri with Arabic speakers to see if the assumption is good. if (value < MinAdvancedHijri || value > MaxAdvancedHijri) { throw new ArgumentOutOfRangeException( - "HijriAdjustment", + nameof(HijriAdjustment), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper"), @@ -252,7 +251,6 @@ namespace System.Globalization { ** "AddHijriDate+1" => Add +1 days to the current calculated Hijri date. ** "AddHijriDate+2" => Add +2 days to the current calculated Hijri date. ============================================================================*/ - [System.Security.SecurityCritical] // auto-generated static int GetAdvanceHijriDate() { #if FEATURE_WIN32_REGISTRY @@ -320,7 +318,7 @@ namespace System.Globalization { static internal void CheckEraRange(int era) { if (era != CurrentEra && era != HijriEra) { - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); } } @@ -328,7 +326,7 @@ namespace System.Globalization { CheckEraRange(era); if (year < 1 || year > MaxCalendarYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -342,7 +340,7 @@ namespace System.Globalization { if (year == MaxCalendarYear) { if (month > MaxCalendarMonth) { throw new ArgumentOutOfRangeException( - "month", + nameof(month), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -352,7 +350,7 @@ namespace System.Globalization { } if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month")); + throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Month")); } } @@ -465,7 +463,7 @@ namespace System.Globalization { public override DateTime AddMonths(DateTime time, int months) { if (months < -120000 || months > 120000) { throw new ArgumentOutOfRangeException( - "months", + nameof(months), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -602,7 +600,7 @@ namespace System.Globalization { int daysInMonth = GetDaysInMonth(year, month, era); if (day < 1 || day > daysInMonth) { throw new ArgumentOutOfRangeException( - "day", + nameof(day), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Day"), @@ -650,7 +648,7 @@ namespace System.Globalization { if (day < 1 || day > daysInMonth) { BCLDebug.Log("year = " + year + ", month = " + month + ", day = " + day); throw new ArgumentOutOfRangeException( - "day", + nameof(day), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Day"), @@ -683,7 +681,7 @@ namespace System.Globalization { if (value < 99 || value > MaxCalendarYear) { throw new ArgumentOutOfRangeException( - "value", + nameof(value), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -698,7 +696,7 @@ namespace System.Globalization { public override int ToFourDigitYear(int year) { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.EndContractBlock(); @@ -709,7 +707,7 @@ namespace System.Globalization { if (year > MaxCalendarYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), diff --git a/src/mscorlib/src/System/Globalization/IdnMapping.cs b/src/mscorlib/src/System/Globalization/IdnMapping.cs index 599a32a..bf75f5b 100644 --- a/src/mscorlib/src/System/Globalization/IdnMapping.cs +++ b/src/mscorlib/src/System/Globalization/IdnMapping.cs @@ -65,6 +65,7 @@ namespace System.Globalization using System.Text; using System.Runtime.Versioning; using System.Runtime.InteropServices; + using System.Diagnostics; using System.Diagnostics.Contracts; // IdnMapping class used to map names to Punycode @@ -125,23 +126,22 @@ namespace System.Globalization public String GetAscii(String unicode, int index) { - if (unicode==null) throw new ArgumentNullException("unicode"); + if (unicode==null) throw new ArgumentNullException(nameof(unicode)); Contract.EndContractBlock(); return GetAscii(unicode, index, unicode.Length - index); } - public String GetAscii(String unicode, int index, int count) + public string GetAscii(String unicode, int index, int count) { - throw null; - /*if (unicode==null) throw new ArgumentNullException("unicode"); + if (unicode == null) throw new ArgumentNullException(nameof(unicode)); if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index < 0) ? "index" : "count", + throw new ArgumentOutOfRangeException((index < 0) ? nameof(index) : nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (index > unicode.Length) - throw new ArgumentOutOfRangeException("byteIndex", + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); if (index > unicode.Length - count) - throw new ArgumentOutOfRangeException("unicode", + throw new ArgumentOutOfRangeException(nameof(unicode), Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); Contract.EndContractBlock(); @@ -161,12 +161,12 @@ namespace System.Globalization // Cannot be null terminated (normalization won't help us with this one, and // may have returned false before checking the whole string above) - Contract.Assert(unicode.Length >= 1, "[IdnMapping.GetAscii]Expected 0 length strings to fail before now."); + Debug.Assert(unicode.Length >= 1, "[IdnMapping.GetAscii]Expected 0 length strings to fail before now."); if (unicode[unicode.Length - 1] <= 0x1f) { throw new ArgumentException( Environment.GetResourceString("Argument_InvalidCharSequence", unicode.Length-1 ), - "unicode"); + nameof(unicode)); } // Have to correctly IDNA normalize the string and Unassigned flags @@ -178,7 +178,7 @@ namespace System.Globalization if ((!bHasLastDot) && unicode.Length > 0 && IsDot(unicode[unicode.Length - 1])) { throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), "unicode"); + "Argument_IdnBadLabelSize"), nameof(unicode)); } // May need to check Std3 rules again for non-ascii @@ -188,24 +188,23 @@ namespace System.Globalization } // Go ahead and encode it - return punycode_encode(unicode);*/ + return punycode_encode(unicode); } - [System.Security.SecuritySafeCritical] private String GetAsciiUsingOS(String unicode) { if (unicode.Length == 0) { throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), "unicode"); + "Argument_IdnBadLabelSize"), nameof(unicode)); } if (unicode[unicode.Length - 1] == 0) { throw new ArgumentException( Environment.GetResourceString("Argument_InvalidCharSequence", unicode.Length - 1), - "unicode"); + nameof(unicode)); } uint flags = (uint) ((AllowUnassigned ? IDN_ALLOW_UNASSIGNED : 0) | (UseStd3AsciiRules ? IDN_USE_STD3_ASCII_RULES : 0)); @@ -218,10 +217,10 @@ namespace System.Globalization lastError = Marshal.GetLastWin32Error(); if (lastError == ERROR_INVALID_NAME) { - throw new ArgumentException(Environment.GetResourceString("Argument_IdnIllegalName"), "unicode"); + throw new ArgumentException(Environment.GetResourceString("Argument_IdnIllegalName"), nameof(unicode)); } - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex"), "unicode"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex"), nameof(unicode)); } char [] output = new char[length]; @@ -232,10 +231,10 @@ namespace System.Globalization lastError = Marshal.GetLastWin32Error(); if (lastError == ERROR_INVALID_NAME) { - throw new ArgumentException(Environment.GetResourceString("Argument_IdnIllegalName"), "unicode"); + throw new ArgumentException(Environment.GetResourceString("Argument_IdnIllegalName"), nameof(unicode)); } - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex"), "unicode"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex"), nameof(unicode)); } return new String(output, 0, length); @@ -249,30 +248,30 @@ namespace System.Globalization public String GetUnicode(String ascii, int index) { - if (ascii==null) throw new ArgumentNullException("ascii"); + if (ascii==null) throw new ArgumentNullException(nameof(ascii)); Contract.EndContractBlock(); return GetUnicode(ascii, index, ascii.Length - index); } public String GetUnicode(String ascii, int index, int count) { - if (ascii==null) throw new ArgumentNullException("ascii"); + if (ascii==null) throw new ArgumentNullException(nameof(ascii)); if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index < 0) ? "index" : "count", + throw new ArgumentOutOfRangeException((index < 0) ? nameof(index) : nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (index > ascii.Length) throw new ArgumentOutOfRangeException("byteIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); if (index > ascii.Length - count) - throw new ArgumentOutOfRangeException("ascii", + throw new ArgumentOutOfRangeException(nameof(ascii), Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); // This is a case (i.e. explicitly null-terminated input) where behavior in .NET and Win32 intentionally differ. // The .NET APIs should (and did in v4.0 and earlier) throw an ArgumentException on input that includes a terminating null. // The Win32 APIs fail on an embedded null, but not on a terminating null. if (count > 0 && ascii[index + count - 1] == (char)0) - throw new ArgumentException("ascii", - Environment.GetResourceString("Argument_IdnBadPunycode")); + throw new ArgumentException(Environment.GetResourceString("Argument_IdnBadPunycode"), + nameof(ascii)); Contract.EndContractBlock(); // We're only using part of the string @@ -289,13 +288,12 @@ namespace System.Globalization // Output name MUST obey IDNA rules & round trip (casing differences are allowed) if (!ascii.Equals(GetAscii(strUnicode), StringComparison.OrdinalIgnoreCase)) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnIllegalName"), "ascii"); + "Argument_IdnIllegalName"), nameof(ascii)); return strUnicode; } - [System.Security.SecuritySafeCritical] private string GetUnicodeUsingOS(string ascii) { uint flags = (uint)((AllowUnassigned ? IDN_ALLOW_UNASSIGNED : 0) | (UseStd3AsciiRules ? IDN_USE_STD3_ASCII_RULES : 0)); @@ -307,10 +305,10 @@ namespace System.Globalization lastError = Marshal.GetLastWin32Error(); if (lastError == ERROR_INVALID_NAME) { - throw new ArgumentException(Environment.GetResourceString("Argument_IdnIllegalName"), "ascii"); + throw new ArgumentException(Environment.GetResourceString("Argument_IdnIllegalName"), nameof(ascii)); } - throw new ArgumentException(Environment.GetResourceString("Argument_IdnBadPunycode"), "ascii"); + throw new ArgumentException(Environment.GetResourceString("Argument_IdnBadPunycode"), nameof(ascii)); } char [] output = new char[length]; @@ -321,10 +319,10 @@ namespace System.Globalization lastError = Marshal.GetLastWin32Error(); if (lastError == ERROR_INVALID_NAME) { - throw new ArgumentException(Environment.GetResourceString("Argument_IdnIllegalName"), "ascii"); + throw new ArgumentException(Environment.GetResourceString("Argument_IdnIllegalName"), nameof(ascii)); } - throw new ArgumentException(Environment.GetResourceString("Argument_IdnBadPunycode"), "ascii"); + throw new ArgumentException(Environment.GetResourceString("Argument_IdnBadPunycode"), nameof(ascii)); } return new String(output, 0, length); @@ -370,7 +368,7 @@ namespace System.Globalization // If its empty, then its too small if (unicode.Length == 0) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), "unicode"); + "Argument_IdnBadLabelSize"), nameof(unicode)); Contract.EndContractBlock(); int iLastDot = -1; @@ -383,7 +381,7 @@ namespace System.Globalization { throw new ArgumentException( Environment.GetResourceString("Argument_InvalidCharSequence", i ), - "unicode"); + nameof(unicode)); } // If its Unicode or a control character, return false (non-ascii) @@ -396,12 +394,12 @@ namespace System.Globalization // Can't have 2 dots in a row if (i == iLastDot + 1) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), "unicode"); + "Argument_IdnBadLabelSize"), nameof(unicode)); // If its too far between dots then fail if (i - iLastDot > M_labelLimit + 1) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), "Unicode"); + "Argument_IdnBadLabelSize"), nameof(unicode)); // If validating Std3, then char before dot can't be - char if (bUseStd3 && i > 0) @@ -422,14 +420,14 @@ namespace System.Globalization // If we never had a dot, then we need to be shorter than the label limit if (iLastDot == -1 && unicode.Length > M_labelLimit) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), "unicode"); + "Argument_IdnBadLabelSize"), nameof(unicode)); // Need to validate entire string length, 1 shorter if last char wasn't a dot if (unicode.Length > M_defaultNameLimit - (IsDot(unicode[unicode.Length-1])? 0 : 1)) throw new ArgumentException(Environment.GetResourceString( "Argument_IdnBadNameSize", M_defaultNameLimit - (IsDot(unicode[unicode.Length-1]) ? 0 : 1)), - "unicode"); + nameof(unicode)); // If last char wasn't a dot we need to check for trailing - if (bUseStd3 && !IsDot(unicode[unicode.Length-1])) @@ -510,7 +508,7 @@ namespace System.Globalization static char encode_digit(int d) { - Contract.Assert(d >= 0 && d < punycodeBase, "[IdnMapping.encode_digit]Expected 0 <= d < punycodeBase"); + Debug.Assert(d >= 0 && d < punycodeBase, "[IdnMapping.encode_digit]Expected 0 <= d < punycodeBase"); // 26-35 map to ASCII 0-9 if (d > 25) return (char)(d - 26 + '0'); @@ -547,7 +545,7 @@ namespace System.Globalization uint k; delta = firsttime ? delta / damp : delta / 2; - Contract.Assert(numpoints != 0, "[IdnMapping.adapt]Expected non-zero numpoints."); + Debug.Assert(numpoints != 0, "[IdnMapping.adapt]Expected non-zero numpoints."); delta += delta / numpoints; for (k = 0; delta > ((punycodeBase - tmin) * tmax) / 2; k += punycodeBase) @@ -555,7 +553,7 @@ namespace System.Globalization delta /= punycodeBase - tmin; } - Contract.Assert(delta + skew != 0, "[IdnMapping.adapt]Expected non-zero delta+skew."); + Debug.Assert(delta + skew != 0, "[IdnMapping.adapt]Expected non-zero delta+skew."); return (int)(k + (punycodeBase - tmin + 1) * delta / (delta + skew)); } @@ -592,7 +590,7 @@ namespace System.Globalization // 0 length strings aren't allowed if (unicode.Length == 0) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), "unicode"); + "Argument_IdnBadLabelSize"), nameof(unicode)); Contract.EndContractBlock(); StringBuilder output = new StringBuilder(unicode.Length); @@ -605,7 +603,7 @@ namespace System.Globalization { // Find end of this segment iNextDot = unicode.IndexOfAny(M_Dots, iAfterLastDot); - Contract.Assert(iNextDot <= unicode.Length, "[IdnMapping.punycode_encode]IndexOfAny is broken"); + Debug.Assert(iNextDot <= unicode.Length, "[IdnMapping.punycode_encode]IndexOfAny is broken"); if (iNextDot < 0) iNextDot = unicode.Length; @@ -615,7 +613,7 @@ namespace System.Globalization // Only allowed to have empty sections as trailing . if (iNextDot != unicode.Length) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), "unicode"); + "Argument_IdnBadLabelSize"), nameof(unicode)); // Last dot, stop break; } @@ -645,7 +643,7 @@ namespace System.Globalization { // Oops, last wasn't RTL, last should be RTL if first is RTL throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadBidi"), "unicode"); + "Argument_IdnBadBidi"), nameof(unicode)); } } @@ -655,7 +653,7 @@ namespace System.Globalization for (basicCount = iAfterLastDot; basicCount < iNextDot; basicCount++) { // Can't be lonely surrogate because it would've thrown in normalization - Contract.Assert(Char.IsLowSurrogate(unicode, basicCount) == false, + Debug.Assert(Char.IsLowSurrogate(unicode, basicCount) == false, "[IdnMapping.punycode_encode]Unexpected low surrogate"); // Double check our bidi rules @@ -666,7 +664,7 @@ namespace System.Globalization { // Oops, throw error throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadBidi"), "unicode"); + "Argument_IdnBadBidi"), nameof(unicode)); } // If we're not RTL we can't have RTL chars @@ -675,7 +673,7 @@ namespace System.Globalization { // Oops, throw error throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadBidi"), "unicode"); + "Argument_IdnBadBidi"), nameof(unicode)); } // If its basic then add it @@ -704,7 +702,7 @@ namespace System.Globalization unicode.Substring(iAfterLastDot, M_strAcePrefix.Length).Equals( M_strAcePrefix, StringComparison.OrdinalIgnoreCase)) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadPunycode"), "unicode"); + "Argument_IdnBadPunycode"), nameof(unicode)); // Need to do ACE encoding int numSurrogatePairs = 0; // number of surrogate pairs so far @@ -739,7 +737,7 @@ namespace System.Globalization /* Increase delta enough to advance the decoder's */ /* state to , but guard against overflow: */ delta += (int)((m - n) * ((numProcessed - numSurrogatePairs) + 1)); - Contract.Assert(delta > 0, "[IdnMapping.cs]1 punycode_encode - delta overflowed int"); + Debug.Assert(delta > 0, "[IdnMapping.cs]1 punycode_encode - delta overflowed int"); n = m; for (j = iAfterLastDot; j < iNextDot; j+= IsSupplementary(test) ? 2 : 1) @@ -753,7 +751,7 @@ namespace System.Globalization if (test < n) { delta++; - Contract.Assert(delta > 0, "[IdnMapping.cs]2 punycode_encode - delta overflowed int"); + Debug.Assert(delta > 0, "[IdnMapping.cs]2 punycode_encode - delta overflowed int"); } if (test == n) @@ -765,9 +763,11 @@ namespace System.Globalization int t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias; if (q < t) break; - Contract.Assert(punycodeBase != t, "[IdnMapping.punycode_encode]Expected punycodeBase (36) to be != t"); - output.Append(encode_digit(t + (q - t) % (punycodeBase - t))); - q = (q - t) / (punycodeBase - t); + Debug.Assert(punycodeBase != t, "[IdnMapping.punycode_encode]Expected punycodeBase (36) to be != t"); + + int mod; + q = Math.DivRem(q - t, punycodeBase - t, out mod); + output.Append(encode_digit(t + mod)); } output.Append(encode_digit(q)); @@ -784,14 +784,14 @@ namespace System.Globalization } ++delta; ++n; - Contract.Assert(delta > 0, "[IdnMapping.cs]3 punycode_encode - delta overflowed int"); + Debug.Assert(delta > 0, "[IdnMapping.cs]3 punycode_encode - delta overflowed int"); } } // Make sure its not too big if (output.Length - iOutputAfterLastDot > M_labelLimit) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), "unicode"); + "Argument_IdnBadLabelSize"), nameof(unicode)); // Done with this segment, add dot if necessary if (iNextDot != unicode.Length) @@ -806,7 +806,7 @@ namespace System.Globalization throw new ArgumentException(Environment.GetResourceString( "Argument_IdnBadNameSize", M_defaultNameLimit - (IsDot(unicode[unicode.Length-1]) ? 0 : 1)), - "unicode"); + nameof(unicode)); // Return our output string return output.ToString(); @@ -840,14 +840,14 @@ namespace System.Globalization // 0 length strings aren't allowed if (ascii.Length == 0) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), "ascii"); + "Argument_IdnBadLabelSize"), nameof(ascii)); Contract.EndContractBlock(); // Throw if we're too long if (ascii.Length > M_defaultNameLimit - (IsDot(ascii[ascii.Length-1]) ? 0 : 1)) throw new ArgumentException(Environment.GetResourceString( "Argument_IdnBadNameSize", - M_defaultNameLimit - (IsDot(ascii[ascii.Length-1]) ? 0 : 1)), "ascii"); + M_defaultNameLimit - (IsDot(ascii[ascii.Length-1]) ? 0 : 1)), nameof(ascii)); // output stringbuilder StringBuilder output = new StringBuilder(ascii.Length); @@ -870,7 +870,7 @@ namespace System.Globalization // Only allowed to have empty sections as trailing . if (iNextDot != ascii.Length) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), "ascii"); + "Argument_IdnBadLabelSize"), nameof(ascii)); // Last dot, stop break; @@ -879,7 +879,7 @@ namespace System.Globalization // In either case it can't be bigger than segment size if (iNextDot - iAfterLastDot > M_labelLimit) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), "ascii"); + "Argument_IdnBadLabelSize"), nameof(ascii)); // See if this section's ASCII or ACE if (ascii.Length < M_strAcePrefix.Length + iAfterLastDot || @@ -893,7 +893,7 @@ namespace System.Globalization // // Only ASCII is allowed // if (ascii[i] >= 0x80) // throw new ArgumentException(Environment.GetResourceString( - // "Argument_IdnBadPunycode"), "ascii"); + // "Argument_IdnBadPunycode"), nameof(ascii)); // } // Its ASCII, copy it @@ -913,7 +913,7 @@ namespace System.Globalization // Trailing - not allowed if (iTemp == iNextDot - 1) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadPunycode"), "ascii"); + "Argument_IdnBadPunycode"), nameof(ascii)); int numBasicCodePoints; if (iTemp <= iAfterLastDot) @@ -931,7 +931,7 @@ namespace System.Globalization // Make sure we don't allow unicode in the ascii part if (ascii[copyAscii] > 0x7f) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadPunycode"), "ascii"); + "Argument_IdnBadPunycode"), nameof(ascii)); // When appending make sure they get lower cased output.Append((char)(ascii[copyAscii] >= 'A' && ascii[copyAscii] <='Z' ? @@ -970,24 +970,24 @@ namespace System.Globalization // Check to make sure we aren't overrunning our ascii string if (asciiIndex >= iNextDot) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadPunycode"), "ascii"); + "Argument_IdnBadPunycode"), nameof(ascii)); // decode the digit from the next char int digit = decode_digit(ascii[asciiIndex++]); - Contract.Assert(w > 0, "[IdnMapping.punycode_decode]Expected w > 0"); + Debug.Assert(w > 0, "[IdnMapping.punycode_decode]Expected w > 0"); if (digit > (maxint - i) / w) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadPunycode"), "ascii"); + "Argument_IdnBadPunycode"), nameof(ascii)); i += (int)(digit * w); int t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias; if (digit < t) break; - Contract.Assert(punycodeBase != t, "[IdnMapping.punycode_decode]Expected t != punycodeBase (36)"); + Debug.Assert(punycodeBase != t, "[IdnMapping.punycode_decode]Expected t != punycodeBase (36)"); if (w > maxint / (punycodeBase - t)) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadPunycode"), "ascii"); + "Argument_IdnBadPunycode"), nameof(ascii)); w *= (punycodeBase - t); } @@ -996,11 +996,11 @@ namespace System.Globalization /* i was supposed to wrap around from output.Length to 0, */ /* incrementing n each time, so we'll fix that now: */ - Contract.Assert((output.Length - iOutputAfterLastDot - numSurrogatePairs) + 1 > 0, + Debug.Assert((output.Length - iOutputAfterLastDot - numSurrogatePairs) + 1 > 0, "[IdnMapping.punycode_decode]Expected to have added > 0 characters this segment"); if (i / ((output.Length - iOutputAfterLastDot - numSurrogatePairs) + 1) > maxint - n) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadPunycode"), "ascii"); + "Argument_IdnBadPunycode"), nameof(ascii)); n += (int)(i / (output.Length - iOutputAfterLastDot - numSurrogatePairs + 1)); i %= (output.Length - iOutputAfterLastDot - numSurrogatePairs + 1); @@ -1016,7 +1016,7 @@ namespace System.Globalization // Make sure n is legal if ((n < 0 || n > 0x10ffff) || (n >= 0xD800 && n <= 0xDFFF)) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadPunycode"), "ascii"); + "Argument_IdnBadPunycode"), nameof(ascii)); // insert n at position i of the output: Really tricky if we have surrogates int iUseInsertLocation; @@ -1034,7 +1034,7 @@ namespace System.Globalization // If its a surrogate, we have to go one more if (iUseInsertLocation >= output.Length) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadPunycode"), "ascii"); + "Argument_IdnBadPunycode"), nameof(ascii)); if (Char.IsSurrogate(output[iUseInsertLocation])) iUseInsertLocation++; } @@ -1079,7 +1079,7 @@ namespace System.Globalization (!bRightToLeft && (eBidi == BidiCategory.RightToLeft || eBidi == BidiCategory.RightToLeftArabic))) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadBidi"), "ascii"); + "Argument_IdnBadBidi"), nameof(ascii)); // Make it lower case if we must (so we can test IsNormalized later) // if (output[iTest] >= 'A' && output[iTest] <= 'Z') @@ -1091,14 +1091,14 @@ namespace System.Globalization { // Oops, last wasn't RTL, last should be RTL if first is RTL throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadBidi"), "ascii"); + "Argument_IdnBadBidi"), nameof(ascii)); } } // See if this label was too long if (iNextDot - iAfterLastDot > M_labelLimit) throw new ArgumentException(Environment.GetResourceString( - "Argument_IdnBadLabelSize"), "ascii"); + "Argument_IdnBadLabelSize"), nameof(ascii)); // Done with this segment, add dot if necessary if (iNextDot != ascii.Length) @@ -1112,7 +1112,7 @@ namespace System.Globalization if (output.Length > M_defaultNameLimit - (IsDot(output[output.Length-1]) ? 0 : 1)) throw new ArgumentException(Environment.GetResourceString( "Argument_IdnBadNameSize", - M_defaultNameLimit -(IsDot(output[output.Length-1]) ? 0 : 1)), "ascii"); + M_defaultNameLimit -(IsDot(output[output.Length-1]) ? 0 : 1)), nameof(ascii)); // Return our output string return output.ToString(); @@ -1157,9 +1157,8 @@ namespace System.Globalization private const int ERROR_INVALID_NAME = 123; - [System.Security.SecurityCritical] [SuppressUnmanagedCodeSecurityAttribute()] - [DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)] + [DllImport("normaliz.dll", CharSet=CharSet.Unicode, SetLastError=true)] private static extern int IdnToAscii( uint dwFlags, [InAttribute()] @@ -1171,9 +1170,8 @@ namespace System.Globalization char [] lpASCIICharStr, int cchASCIIChar); - [System.Security.SecurityCritical] [SuppressUnmanagedCodeSecurityAttribute()] - [DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)] + [DllImport("normaliz.dll", CharSet=CharSet.Unicode, SetLastError=true)] private static extern int IdnToUnicode( uint dwFlags, [InAttribute()] diff --git a/src/mscorlib/src/System/Globalization/JapaneseCalendar.cs b/src/mscorlib/src/System/Globalization/JapaneseCalendar.cs index 2984d08..6b168ce 100644 --- a/src/mscorlib/src/System/Globalization/JapaneseCalendar.cs +++ b/src/mscorlib/src/System/Globalization/JapaneseCalendar.cs @@ -159,7 +159,6 @@ namespace System.Globalization { // . is a delimiter, but the value of . doesn't matter. // '_' marks the space between the japanese era name, japanese abbreviated era name // english name, and abbreviated english names. - [System.Security.SecuritySafeCritical] // auto-generated private static EraInfo[] GetErasFromRegistry() { // Look in the registry key and see if we can find any ranges @@ -491,14 +490,14 @@ namespace System.Globalization { public override int ToFourDigitYear(int year) { if (year <= 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); } Contract.EndContractBlock(); if (year > helper.MaxYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), diff --git a/src/mscorlib/src/System/Globalization/JulianCalendar.cs b/src/mscorlib/src/System/Globalization/JulianCalendar.cs index 9c8db34..db286e0 100644 --- a/src/mscorlib/src/System/Globalization/JulianCalendar.cs +++ b/src/mscorlib/src/System/Globalization/JulianCalendar.cs @@ -112,7 +112,7 @@ namespace System.Globalization { static internal void CheckEraRange(int era) { if (era != CurrentEra && era != JulianEra) { - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); } } @@ -120,7 +120,7 @@ namespace System.Globalization { CheckEraRange(era); if (year <= 0 || year > MaxYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -131,7 +131,7 @@ namespace System.Globalization { static internal void CheckMonthRange(int month) { if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month")); + throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Month")); } } @@ -159,7 +159,7 @@ namespace System.Globalization { int monthDays = days[month] - days[month - 1]; if (day < 1 || day > monthDays) { throw new ArgumentOutOfRangeException( - "day", + nameof(day), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -204,7 +204,7 @@ namespace System.Globalization { int[] days = leapYear? DaysToMonth366: DaysToMonth365; // All months have less than 32 days, so n >> 5 is a good conservative // estimate for the month - int m = n >> 5 + 1; + int m = (n >> 5) + 1; // m = 1-based month number while (n >= days[m]) m++; // If month was requested, return it @@ -230,7 +230,7 @@ namespace System.Globalization { { if (months < -120000 || months > 120000) { throw new ArgumentOutOfRangeException( - "months", + nameof(months), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -377,7 +377,7 @@ namespace System.Globalization { CheckDayRange(year, month, day); if (millisecond < 0 || millisecond >= MillisPerSecond) { throw new ArgumentOutOfRangeException( - "millisecond", + nameof(millisecond), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -420,14 +420,14 @@ namespace System.Globalization { public override int ToFourDigitYear(int year) { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.EndContractBlock(); if (year > MaxYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper"), diff --git a/src/mscorlib/src/System/Globalization/KoreanCalendar.cs b/src/mscorlib/src/System/Globalization/KoreanCalendar.cs index 9343884..dde82b6 100644 --- a/src/mscorlib/src/System/Globalization/KoreanCalendar.cs +++ b/src/mscorlib/src/System/Globalization/KoreanCalendar.cs @@ -254,7 +254,7 @@ namespace System.Globalization { public override int ToFourDigitYear(int year) { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/Globalization/KoreanLunisolarCalendar.cs b/src/mscorlib/src/System/Globalization/KoreanLunisolarCalendar.cs index eb0a810..9e36b43 100644 --- a/src/mscorlib/src/System/Globalization/KoreanLunisolarCalendar.cs +++ b/src/mscorlib/src/System/Globalization/KoreanLunisolarCalendar.cs @@ -1267,12 +1267,12 @@ namespace System.Globalization { internal override int GetGregorianYear(int year, int era) { if (era != CurrentEra && era != GregorianEra) - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); if (year < MIN_LUNISOLAR_YEAR || year > MAX_LUNISOLAR_YEAR) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR)); diff --git a/src/mscorlib/src/System/Globalization/NumberFormatInfo.cs b/src/mscorlib/src/System/Globalization/NumberFormatInfo.cs index fae91c2..a5dce46 100644 --- a/src/mscorlib/src/System/Globalization/NumberFormatInfo.cs +++ b/src/mscorlib/src/System/Globalization/NumberFormatInfo.cs @@ -120,28 +120,8 @@ namespace System.Globalization { [OnSerializing] private void OnSerializing(StreamingContext ctx) { -#if !FEATURE_CORECLR - // Update these legacy flags, so that 1.1/2.0 versions of the framework - // can still throw while parsing; even when using a de-serialized - // NumberFormatInfo from a 4.0+ version of the framework - if (numberDecimalSeparator != numberGroupSeparator) { - validForParseAsNumber = true; - } else { - validForParseAsNumber = false; - } - - if ((numberDecimalSeparator != numberGroupSeparator) && - (numberDecimalSeparator != currencyGroupSeparator) && - (currencyDecimalSeparator != numberGroupSeparator) && - (currencyDecimalSeparator != currencyGroupSeparator)) { - validForParseAsCurrency = true; - } else { - validForParseAsCurrency = false; - } -#endif // !FEATURE_CORECLR } - [OnDeserializing] private void OnDeserializing(StreamingContext ctx) { @@ -153,7 +133,6 @@ namespace System.Globalization { } #endregion Serialization - static private void VerifyDecimalSeparator(String decSep, String propertyName) { if (decSep==null) { throw new ArgumentNullException(propertyName, @@ -231,7 +210,6 @@ namespace System.Globalization { // We aren't persisting dataItem any more (since its useless & we weren't using it), // Ditto with m_useUserOverride. Don't use them, we use a local copy of everything. - [System.Security.SecuritySafeCritical] // auto-generated internal NumberFormatInfo(CultureData cultureData) { if (cultureData != null) @@ -316,7 +294,7 @@ namespace System.Globalization { set { if (value < 0 || value > 99) { throw new ArgumentOutOfRangeException( - "CurrencyDecimalDigits", + nameof(CurrencyDecimalDigits), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -376,7 +354,7 @@ namespace System.Globalization { } set { if (value == null) { - throw new ArgumentNullException("CurrencyGroupSizes", + throw new ArgumentNullException(nameof(CurrencyGroupSizes), Environment.GetResourceString("ArgumentNull_Obj")); } Contract.EndContractBlock(); @@ -397,7 +375,7 @@ namespace System.Globalization { } set { if (value == null) { - throw new ArgumentNullException("NumberGroupSizes", + throw new ArgumentNullException(nameof(NumberGroupSizes), Environment.GetResourceString("ArgumentNull_Obj")); } Contract.EndContractBlock(); @@ -416,7 +394,7 @@ namespace System.Globalization { } set { if (value == null) { - throw new ArgumentNullException("PercentGroupSizes", + throw new ArgumentNullException(nameof(PercentGroupSizes), Environment.GetResourceString("ArgumentNull_Obj")); } Contract.EndContractBlock(); @@ -443,7 +421,7 @@ namespace System.Globalization { get { return currencySymbol; } set { if (value == null) { - throw new ArgumentNullException("CurrencySymbol", + throw new ArgumentNullException(nameof(CurrencySymbol), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -475,7 +453,7 @@ namespace System.Globalization { } set { if (value == null) { - throw new ArgumentNullException("NaNSymbol", + throw new ArgumentNullException(nameof(NaNSymbol), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -491,7 +469,7 @@ namespace System.Globalization { set { if (value < 0 || value > 15) { throw new ArgumentOutOfRangeException( - "CurrencyNegativePattern", + nameof(CurrencyNegativePattern), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -513,7 +491,7 @@ namespace System.Globalization { // if (value < 0 || value > 4) { throw new ArgumentOutOfRangeException( - "NumberNegativePattern", + nameof(NumberNegativePattern), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -535,7 +513,7 @@ namespace System.Globalization { // if (value < 0 || value > 3) { throw new ArgumentOutOfRangeException( - "PercentPositivePattern", + nameof(PercentPositivePattern), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -557,7 +535,7 @@ namespace System.Globalization { // if (value < 0 || value > 11) { throw new ArgumentOutOfRangeException( - "PercentNegativePattern", + nameof(PercentNegativePattern), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -577,7 +555,7 @@ namespace System.Globalization { } set { if (value == null) { - throw new ArgumentNullException("NegativeInfinitySymbol", + throw new ArgumentNullException(nameof(NegativeInfinitySymbol), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -591,7 +569,7 @@ namespace System.Globalization { get { return negativeSign; } set { if (value == null) { - throw new ArgumentNullException("NegativeSign", + throw new ArgumentNullException(nameof(NegativeSign), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -606,7 +584,7 @@ namespace System.Globalization { set { if (value < 0 || value > 99) { throw new ArgumentOutOfRangeException( - "NumberDecimalDigits", + nameof(NumberDecimalDigits), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -645,7 +623,7 @@ namespace System.Globalization { set { if (value < 0 || value > 3) { throw new ArgumentOutOfRangeException( - "CurrencyPositivePattern", + nameof(CurrencyPositivePattern), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -665,7 +643,7 @@ namespace System.Globalization { } set { if (value == null) { - throw new ArgumentNullException("PositiveInfinitySymbol", + throw new ArgumentNullException(nameof(PositiveInfinitySymbol), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -679,7 +657,7 @@ namespace System.Globalization { get { return positiveSign; } set { if (value == null) { - throw new ArgumentNullException("PositiveSign", + throw new ArgumentNullException(nameof(PositiveSign), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -694,7 +672,7 @@ namespace System.Globalization { set { if (value < 0 || value > 99) { throw new ArgumentOutOfRangeException( - "PercentDecimalDigits", + nameof(PercentDecimalDigits), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -734,7 +712,7 @@ namespace System.Globalization { } set { if (value == null) { - throw new ArgumentNullException("PercentSymbol", + throw new ArgumentNullException(nameof(PercentSymbol), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -748,7 +726,7 @@ namespace System.Globalization { get { return perMilleSymbol; } set { if (value == null) { - throw new ArgumentNullException("PerMilleSymbol", + throw new ArgumentNullException(nameof(PerMilleSymbol), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -788,7 +766,7 @@ namespace System.Globalization { public static NumberFormatInfo ReadOnly(NumberFormatInfo nfi) { if (nfi == null) { - throw new ArgumentNullException("nfi"); + throw new ArgumentNullException(nameof(nfi)); } Contract.EndContractBlock(); if (nfi.IsReadOnly) { @@ -809,7 +787,7 @@ namespace System.Globalization { internal static void ValidateParseStyleInteger(NumberStyles style) { // Check for undefined flags if ((style & InvalidNumberStyles) != 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNumberStyles"), "style"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNumberStyles"), nameof(style)); } Contract.EndContractBlock(); if ((style & NumberStyles.AllowHexSpecifier) != 0) { // Check for hex number @@ -822,7 +800,7 @@ namespace System.Globalization { internal static void ValidateParseStyleFloatingPoint(NumberStyles style) { // Check for undefined flags if ((style & InvalidNumberStyles) != 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNumberStyles"), "style"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNumberStyles"), nameof(style)); } Contract.EndContractBlock(); if ((style & NumberStyles.AllowHexSpecifier) != 0) { // Check for hex number diff --git a/src/mscorlib/src/System/Globalization/PersianCalendar.cs b/src/mscorlib/src/System/Globalization/PersianCalendar.cs index 2f1ffac..e61a007 100644 --- a/src/mscorlib/src/System/Globalization/PersianCalendar.cs +++ b/src/mscorlib/src/System/Globalization/PersianCalendar.cs @@ -4,6 +4,7 @@ namespace System.Globalization { using System; + using System.Diagnostics; using System.Diagnostics.Contracts; //////////////////////////////////////////////////////////////////////////// @@ -147,7 +148,7 @@ namespace System.Globalization { static internal void CheckEraRange(int era) { if (era != CurrentEra && era != PersianEra) { - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); } } @@ -155,7 +156,7 @@ namespace System.Globalization { CheckEraRange(era); if (year < 1 || year > MaxCalendarYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -169,7 +170,7 @@ namespace System.Globalization { if (year == MaxCalendarYear) { if (month > MaxCalendarMonth) { throw new ArgumentOutOfRangeException( - "month", + nameof(month), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -179,13 +180,13 @@ namespace System.Globalization { } if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month")); + throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Month")); } } static int MonthFromOrdinalDay(int ordinalDay) { - Contract.Assert(ordinalDay <= 366); + Debug.Assert(ordinalDay <= 366); int index = 0; while (ordinalDay > DaysToMonth[index]) index++; @@ -195,7 +196,7 @@ namespace System.Globalization { static int DaysInPreviousMonths(int month) { - Contract.Assert(1 <= month && month <= 12); + Debug.Assert(1 <= month && month <= 12); --month; // months are one based but for calculations use 0 based return DaysToMonth[month]; } @@ -225,7 +226,7 @@ namespace System.Globalization { long yearStart = CalendricalCalculationsHelper.PersianNewYearOnOrBefore(NumDays); int y = (int)(Math.Floor(((yearStart - PersianEpoch) / CalendricalCalculationsHelper.MeanTropicalYearInDays) + 0.5)) + 1; - Contract.Assert(y >= 1); + Debug.Assert(y >= 1); if (part == DatePartYear) { @@ -244,16 +245,16 @@ namespace System.Globalization { } int m = MonthFromOrdinalDay(ordinalDay); - Contract.Assert(ordinalDay >= 1); - Contract.Assert(m >= 1 && m <= 12); + Debug.Assert(ordinalDay >= 1); + Debug.Assert(m >= 1 && m <= 12); if (part == DatePartMonth) { return m; } int d = ordinalDay - DaysInPreviousMonths(m); - Contract.Assert(1 <= d); - Contract.Assert(d <= 31); + Debug.Assert(1 <= d); + Debug.Assert(d <= 31); // // Calculate the Persian Day. @@ -290,7 +291,7 @@ namespace System.Globalization { public override DateTime AddMonths(DateTime time, int months) { if (months < -120000 || months > 120000) { throw new ArgumentOutOfRangeException( - "months", + nameof(months), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -377,7 +378,7 @@ namespace System.Globalization { int daysInMonth = DaysToMonth[month] - DaysToMonth[month - 1]; if ((month == MonthsPerYear) && !IsLeapYear(year)) { - Contract.Assert(daysInMonth == 30); + Debug.Assert(daysInMonth == 30); --daysInMonth; } return daysInMonth; @@ -450,7 +451,7 @@ namespace System.Globalization { int daysInMonth = GetDaysInMonth(year, month, era); if (day < 1 || day > daysInMonth) { throw new ArgumentOutOfRangeException( - "day", + nameof(day), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Day"), @@ -506,7 +507,7 @@ namespace System.Globalization { if (day < 1 || day > daysInMonth) { BCLDebug.Log("year = " + year + ", month = " + month + ", day = " + day); throw new ArgumentOutOfRangeException( - "day", + nameof(day), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Day"), @@ -538,7 +539,7 @@ namespace System.Globalization { if (value < 99 || value > MaxCalendarYear) { throw new ArgumentOutOfRangeException( - "value", + nameof(value), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -553,7 +554,7 @@ namespace System.Globalization { public override int ToFourDigitYear(int year) { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.EndContractBlock(); @@ -564,7 +565,7 @@ namespace System.Globalization { if (year > MaxCalendarYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), diff --git a/src/mscorlib/src/System/Globalization/RegionInfo.cs b/src/mscorlib/src/System/Globalization/RegionInfo.cs index f06d63f..4bed875 100644 --- a/src/mscorlib/src/System/Globalization/RegionInfo.cs +++ b/src/mscorlib/src/System/Globalization/RegionInfo.cs @@ -19,6 +19,7 @@ namespace System.Globalization { using System; using System.Runtime.Serialization; + using System.Diagnostics; using System.Diagnostics.Contracts; [Serializable] @@ -59,14 +60,13 @@ namespace System.Globalization { // In Silverlight we enforce that RegionInfos must be created with a full culture name // //////////////////////////////////////////////////////////////////////// - [System.Security.SecuritySafeCritical] // auto-generated public RegionInfo(String name) { if (name==null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); if (name.Length == 0) //The InvariantCulture has no matching region { - throw new ArgumentException(Environment.GetResourceString("Argument_NoRegionInvariantCulture"), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_NoRegionInvariantCulture"), nameof(name)); } Contract.EndContractBlock(); @@ -83,19 +83,18 @@ namespace System.Globalization { throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("Argument_InvalidCultureName"), name), "name"); + Environment.GetResourceString("Argument_InvalidCultureName"), name), nameof(name)); // Not supposed to be neutral if (this.m_cultureData.IsNeutralCulture) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNeutralRegionName", name), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNeutralRegionName", name), nameof(name)); SetName(name); } #if FEATURE_USE_LCID // We'd rather people use the named version since this doesn't allow custom locales - [System.Security.SecuritySafeCritical] // auto-generated public RegionInfo(int culture) { if (culture == CultureInfo.LOCALE_INVARIANT) //The InvariantCulture has no matching region @@ -106,13 +105,13 @@ namespace System.Globalization { if (culture == CultureInfo.LOCALE_NEUTRAL) { // Not supposed to be neutral - throw new ArgumentException(Environment.GetResourceString("Argument_CultureIsNeutral", culture), "culture"); + throw new ArgumentException(Environment.GetResourceString("Argument_CultureIsNeutral", culture), nameof(culture)); } if (culture == CultureInfo.LOCALE_CUSTOM_DEFAULT) { // Not supposed to be neutral - throw new ArgumentException(Environment.GetResourceString("Argument_CustomCultureCannotBePassedByNumber", culture), "culture"); + throw new ArgumentException(Environment.GetResourceString("Argument_CustomCultureCannotBePassedByNumber", culture), nameof(culture)); } this.m_cultureData = CultureData.GetCultureData(culture,true); @@ -121,34 +120,23 @@ namespace System.Globalization { if (this.m_cultureData.IsNeutralCulture) { // Not supposed to be neutral - throw new ArgumentException(Environment.GetResourceString("Argument_CultureIsNeutral", culture), "culture"); + throw new ArgumentException(Environment.GetResourceString("Argument_CultureIsNeutral", culture), nameof(culture)); } m_cultureId = culture; } #endif - [System.Security.SecuritySafeCritical] // auto-generated internal RegionInfo(CultureData cultureData) { this.m_cultureData = cultureData; this.m_name = this.m_cultureData.SREGIONNAME; } - [System.Security.SecurityCritical] // auto-generated private void SetName(string name) { -#if FEATURE_CORECLR // Use the name of the region we found this.m_name = this.m_cultureData.SREGIONNAME; -#else - // when creating region by culture name, we keep the region name as the culture name so regions - // created by custom culture names can be differentiated from built in regions. - this.m_name = name.Equals(this.m_cultureData.SREGIONNAME, StringComparison.OrdinalIgnoreCase) ? - this.m_cultureData.SREGIONNAME : - this.m_cultureData.CultureName; -#endif // FEATURE_CORECLR } - #region Serialization // @@ -163,174 +151,17 @@ namespace System.Globalization { [OptionalField(VersionAdded = 2)] internal int m_dataItem = 0; -#if !FEATURE_CORECLR - static private readonly int[] IdFromEverettRegionInfoDataItem = - { - 0x3801, /* 0 */ // AE ar-AE Arabic (U.A.E.) - 0x041C, /* 1 */ // AL sq-AL Albanian (Albania) - 0x042B, /* 2 */ // AM hy-AM Armenian (Armenia) - 0x2C0A, /* 3 */ // AR es-AR Spanish (Argentina) - 0x0C07, /* 4 */ // AT de-AT German (Austria) - 0x0C09, /* 5 */ // AU en-AU English (Australia) - 0x042C, /* 6 */ // AZ az-AZ-Latn Azeri (Latin) (Azerbaijan) - // 0x082C, 6, // AZ az-AZ-Cyrl Azeri (Cyrillic) (Azerbaijan) - 0x080C, /* 7 */ // BE fr-BE French (Belgium) - // 0x0813, 7, // BE nl-BE Dutch (Belgium) - 0x0402, /* 8 */ // BG bg-BG Bulgarian (Bulgaria) - 0x3C01, /* 9 */ // BH ar-BH Arabic (Bahrain) - 0x083E, /* 10 */ // BN ms-BN Malay (Brunei Darussalam) - 0x400A, /* 11 */ // BO es-BO Spanish (Bolivia) - 0x0416, /* 12 */ // BR pt-BR Portuguese (Brazil) - 0x0423, /* 13 */ // BY be-BY Belarusian (Belarus) - 0x2809, /* 14 */ // BZ en-BZ English (Belize) - 0x0C0C, /* 15 */ // CA fr-CA French (Canada) - // 0x1009, 15, // CA en-CA English (Canada) - 0x2409, /* 16 */ // CB en-CB English (Caribbean) - 0x0807, /* 17 */ // CH de-CH German (Switzerland) - // 0x0810, 17, // CH it-CH Italian (Switzerland) - // 0x100C, 17, // CH fr-CH French (Switzerland) - 0x340A, /* 18 */ // CL es-CL Spanish (Chile) - 0x0804, /* 19 */ // CN zh-CN Chinese (People's Republic of China) - 0x240A, /* 20 */ // CO es-CO Spanish (Colombia) - 0x140A, /* 21 */ // CR es-CR Spanish (Costa Rica) - 0x0405, /* 22 */ // CZ cs-CZ Czech (Czech Republic) - 0x0407, /* 23 */ // DE de-DE German (Germany) - 0x0406, /* 24 */ // DK da-DK Danish (Denmark) - 0x1C0A, /* 25 */ // DO es-DO Spanish (Dominican Republic) - 0x1401, /* 26 */ // DZ ar-DZ Arabic (Algeria) - 0x300A, /* 27 */ // EC es-EC Spanish (Ecuador) - 0x0425, /* 28 */ // EE et-EE Estonian (Estonia) - 0x0C01, /* 29 */ // EG ar-EG Arabic (Egypt) - 0x0403, /* 30 */ // ES ca-ES Catalan (Catalan) - // 0x042D, 30, // ES eu-ES Basque (Basque) - // 0x0456, 30, // ES gl-ES Galician (Galician) - // 0x0C0A, 30, // ES es-ES Spanish (Spain) - 0x040B, /* 31 */ // FI fi-FI Finnish (Finland) - // 0x081D, 31, // FI sv-FI Swedish (Finland) - 0x0438, /* 32 */ // FO fo-FO Faroese (Faroe Islands) - 0x040C, /* 33 */ // FR fr-FR French (France) - 0x0809, /* 34 */ // GB en-GB English (United Kingdom) - 0x0437, /* 35 */ // GE ka-GE Georgian (Georgia) - 0x0408, /* 36 */ // GR el-GR Greek (Greece) - 0x100A, /* 37 */ // GT es-GT Spanish (Guatemala) - 0x0C04, /* 38 */ // HK zh-HK Chinese (Hong Kong S.A.R.) - 0x480A, /* 39 */ // HN es-HN Spanish (Honduras) - 0x041A, /* 40 */ // HR hr-HR Croatian (Croatia) - 0x040E, /* 41 */ // HU hu-HU Hungarian (Hungary) - 0x0421, /* 42 */ // ID id-ID Indonesian (Indonesia) - 0x1809, /* 43 */ // IE en-IE English (Ireland) - 0x040D, /* 44 */ // IL he-IL Hebrew (Israel) - 0x0439, /* 45 */ // IN hi-IN Hindi (India) - // 0x0446, 45, // IN pa-IN Punjabi (India) - // 0x0447, 45, // IN gu-IN Gujarati (India) - // 0x0449, 45, // IN ta-IN Tamil (India) - // 0x044A, 45, // IN te-IN Telugu (India) - // 0x044B, 45, // IN kn-IN Kannada (India) - // 0x044E, 45, // IN mr-IN Marathi (India) - // 0x044F, 45, // IN sa-IN Sanskrit (India) - // 0x0457, 45, // IN kok-IN Konkani (India) - 0x0801, /* 46 */ // IQ ar-IQ Arabic (Iraq) - 0x0429, /* 47 */ // IR fa-IR (Iran) - 0x040F, /* 48 */ // IS is-IS Icelandic (Iceland) - 0x0410, /* 49 */ // IT it-IT Italian (Italy) - 0x2009, /* 50 */ // JM en-JM English (Jamaica) - 0x2C01, /* 51 */ // JO ar-JO Arabic (Jordan) - 0x0411, /* 52 */ // JP ja-JP Japanese (Japan) - 0x0441, /* 53 */ // KE sw-KE Swahili (Kenya) - 0x0440, /* 54 */ // KG ky-KG Kyrgyz (Kyrgyzstan) - 0x0412, /* 55 */ // KR ko-KR Korean (Korea) - 0x3401, /* 56 */ // KW ar-KW Arabic (Kuwait) - 0x043F, /* 57 */ // KZ kk-KZ Kazakh (Kazakhstan) - 0x3001, /* 58 */ // LB ar-LB Arabic (Lebanon) - 0x1407, /* 59 */ // LI de-LI German (Liechtenstein) - 0x0427, /* 60 */ // LT lt-LT Lithuanian (Lithuania) - 0x1007, /* 61 */ // LU de-LU German (Luxembourg) - // 0x140C, 61, // LU fr-LU French (Luxembourg) - 0x0426, /* 62 */ // LV lv-LV Latvian (Latvia) - 0x1001, /* 63 */ // LY ar-LY Arabic (Libya) - 0x1801, /* 64 */ // MA ar-MA Arabic (Morocco) - 0x180C, /* 65 */ // MC fr-MC French (Principality of Monaco) - 0x042F, /* 66 */ // MK mk-MK Macedonian (Macedonia, FYRO) - 0x0450, /* 67 */ // MN mn-MN Mongolian (Mongolia) - 0x1404, /* 68 */ // MO zh-MO Chinese (Macau S.A.R.) - 0x0465, /* 69 */ // MV div-MV Divehi (Maldives) - 0x080A, /* 70 */ // MX es-MX Spanish (Mexico) - 0x043E, /* 71 */ // MY ms-MY Malay (Malaysia) - 0x4C0A, /* 72 */ // NI es-NI Spanish (Nicaragua) - 0x0413, /* 73 */ // NL nl-NL Dutch (Netherlands) - 0x0414, /* 74 */ // NO nb-NO Norwegian (Bokm?) (Norway) - // 0x0814, 74, // NO nn-NO Norwegian (Nynorsk) (Norway) - 0x1409, /* 75 */ // NZ en-NZ English (New Zealand) - 0x2001, /* 76 */ // OM ar-OM Arabic (Oman) - 0x180A, /* 77 */ // PA es-PA Spanish (Panama) - 0x280A, /* 78 */ // PE es-PE Spanish (Peru) - 0x3409, /* 79 */ // PH en-PH English (Republic of the Philippines) - 0x0420, /* 80 */ // PK ur-PK Urdu (Islamic Republic of Pakistan) - 0x0415, /* 81 */ // PL pl-PL Polish (Poland) - 0x500A, /* 82 */ // PR es-PR Spanish (Puerto Rico) - 0x0816, /* 83 */ // PT pt-PT Portuguese (Portugal) - 0x3C0A, /* 84 */ // PY es-PY Spanish (Paraguay) - 0x4001, /* 85 */ // QA ar-QA Arabic (Qatar) - 0x0418, /* 86 */ // RO ro-RO Romanian (Romania) - 0x0419, /* 87 */ // RU ru-RU Russian (Russia) - // 0x0444, 87, // RU tt-RU Tatar (Russia) - 0x0401, /* 88 */ // SA ar-SA Arabic (Saudi Arabia) - 0x041D, /* 89 */ // SE sv-SE Swedish (Sweden) - 0x1004, /* 90 */ // SG zh-SG Chinese (Singapore) - 0x0424, /* 91 */ // SI sl-SI Slovenian (Slovenia) - 0x041B, /* 92 */ // SK sk-SK Slovak (Slovakia) - 0x081A, /* 93 */ // SP sr-SP-Latn Serbian (Latin) (Serbia) - // 0x0C1A, 93, // SP sr-SP-Cyrl Serbian (Cyrillic) (Serbia) - 0x440A, /* 94 */ // SV es-SV Spanish (El Salvador) - 0x045A, /* 95 */ // SY syr-SY Syriac (Syria) - // 0x2801, 95, // SY ar-SY Arabic (Syria) - 0x041E, /* 96 */ // TH th-TH Thai (Thailand) - 0x1C01, /* 97 */ // TN ar-TN Arabic (Tunisia) - 0x041F, /* 98 */ // TR tr-TR Turkish (Turkey) - 0x2C09, /* 99 */ // TT en-TT English (Trinidad and Tobago) - 0x0404, /*100 */ // TW zh-TW Chinese (Taiwan) - 0x0422, /*101 */ // UA uk-UA Ukrainian (Ukraine) - 0x0409, /*102 */ // US en-US English (United States) - 0x380A, /*103 */ // UY es-UY Spanish (Uruguay) - 0x0443, /*104 */ // UZ uz-UZ-Latn Uzbek (Latin) (Uzbekistan) - // 0x0843, 104 // UZ uz-UZ-Cyrl Uzbek (Cyrillic) (Uzbekistan) - 0x200A, /*105*/ // VE es-VE Spanish (Venezuela) - 0x042A, /*106*/ // VN vi-VN Vietnamese (Viet Nam) - 0x2401, /*107*/ // YE ar-YE Arabic (Yemen) - 0x0436, /*108*/ // ZA af-ZA Afrikaans (South Africa) - // 0x1C09, 108, // ZA en-ZA English (South Africa) - 0x3009, /*109*/ // ZW en-ZW English (Zimbabwe) - }; -#endif - [System.Security.SecurityCritical] // auto-generated [OnDeserialized] private void OnDeserialized(StreamingContext ctx) { -#if FEATURE_CORECLR // This won't happen anyway since CoreCLR doesn't support serialization this.m_cultureData = CultureData.GetCultureData(m_name, true); -#else - if (m_name == null) - { - Contract.Assert(m_dataItem >= 0, "[RegionInfo.OnDeserialized] null name and invalid dataItem"); - m_cultureId = IdFromEverettRegionInfoDataItem[m_dataItem]; - } - if (m_cultureId == 0) - { - this.m_cultureData = CultureData.GetCultureDataForRegion(this.m_name, true); - } - else - { - this.m_cultureData = CultureData.GetCultureData(m_cultureId, true); - } - -#endif if (this.m_cultureData == null) throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, - Environment.GetResourceString("Argument_InvalidCultureName"), m_name), "m_name"); + Environment.GetResourceString("Argument_InvalidCultureName"), m_name), nameof(m_name)); if (m_cultureId == 0) { @@ -359,7 +190,6 @@ namespace System.Globalization { // //////////////////////////////////////////////////////////////////////// public static RegionInfo CurrentRegion { - [System.Security.SecuritySafeCritical] // auto-generated get { RegionInfo temp = s_currentRegionInfo; if (temp == null) @@ -383,7 +213,7 @@ namespace System.Globalization { //////////////////////////////////////////////////////////////////////// public virtual String Name { get { - Contract.Assert(m_name != null, "Expected RegionInfo.m_name to be populated already"); + Debug.Assert(m_name != null, "Expected RegionInfo.m_name to be populated already"); return (m_name); } } @@ -397,7 +227,6 @@ namespace System.Globalization { //////////////////////////////////////////////////////////////////////// public virtual String EnglishName { - [System.Security.SecuritySafeCritical] // auto-generated get { return (this.m_cultureData.SENGCOUNTRY); @@ -415,7 +244,6 @@ namespace System.Globalization { //////////////////////////////////////////////////////////////////////// public virtual String DisplayName { - [System.Security.SecuritySafeCritical] // auto-generated get { return (this.m_cultureData.SLOCALIZEDCOUNTRY); @@ -434,7 +262,6 @@ namespace System.Globalization { [System.Runtime.InteropServices.ComVisible(false)] public virtual String NativeName { - [System.Security.SecuritySafeCritical] // auto-generated get { return (this.m_cultureData.SNATIVECOUNTRY); @@ -450,7 +277,6 @@ namespace System.Globalization { //////////////////////////////////////////////////////////////////////// public virtual String TwoLetterISORegionName { - [System.Security.SecuritySafeCritical] // auto-generated get { return (this.m_cultureData.SISO3166CTRYNAME); @@ -467,7 +293,6 @@ namespace System.Globalization { //////////////////////////////////////////////////////////////////////// public virtual String ThreeLetterISORegionName { - [System.Security.SecuritySafeCritical] // auto-generated get { return (this.m_cultureData.SISO3166CTRYNAME2); @@ -483,7 +308,6 @@ namespace System.Globalization { //////////////////////////////////////////////////////////////////////// public virtual String ThreeLetterWindowsRegionName { - [System.Security.SecuritySafeCritical] // auto-generated get { return (this.m_cultureData.SABBREVCTRYNAME); @@ -524,7 +348,6 @@ namespace System.Globalization { [System.Runtime.InteropServices.ComVisible(false)] public virtual String CurrencyEnglishName { - [System.Security.SecuritySafeCritical] // auto-generated get { return (this.m_cultureData.SENGLISHCURRENCY); @@ -542,7 +365,6 @@ namespace System.Globalization { [System.Runtime.InteropServices.ComVisible(false)] public virtual String CurrencyNativeName { - [System.Security.SecuritySafeCritical] // auto-generated get { return (this.m_cultureData.SNATIVECURRENCY); @@ -557,7 +379,6 @@ namespace System.Globalization { // //////////////////////////////////////////////////////////////////////// public virtual String CurrencySymbol { - [System.Security.SecuritySafeCritical] // auto-generated get { return (this.m_cultureData.SCURRENCY); } @@ -571,7 +392,6 @@ namespace System.Globalization { // //////////////////////////////////////////////////////////////////////// public virtual String ISOCurrencySymbol { - [System.Security.SecuritySafeCritical] // auto-generated get { return (this.m_cultureData.SINTLSYMBOL); } diff --git a/src/mscorlib/src/System/Globalization/SortKey.cs b/src/mscorlib/src/System/Globalization/SortKey.cs index e3308dc..9c35f48 100644 --- a/src/mscorlib/src/System/Globalization/SortKey.cs +++ b/src/mscorlib/src/System/Globalization/SortKey.cs @@ -16,6 +16,7 @@ namespace System.Globalization { using System; using System.Runtime.CompilerServices; using System.Runtime.Serialization; + using System.Diagnostics; using System.Diagnostics.Contracts; [System.Runtime.InteropServices.ComVisible(true)] @@ -119,15 +120,15 @@ namespace System.Globalization { public static int Compare(SortKey sortkey1, SortKey sortkey2) { if (sortkey1==null || sortkey2==null) { - throw new ArgumentNullException((sortkey1==null ? "sortkey1": "sortkey2")); + throw new ArgumentNullException((sortkey1==null ? nameof(sortkey1): nameof(sortkey2))); } Contract.EndContractBlock(); byte[] key1Data = sortkey1.m_KeyData; byte[] key2Data = sortkey2.m_KeyData; - Contract.Assert(key1Data!=null, "key1Data!=null"); - Contract.Assert(key2Data!=null, "key2Data!=null"); + Debug.Assert(key1Data!=null, "key1Data!=null"); + Debug.Assert(key2Data!=null, "key2Data!=null"); if (key1Data.Length == 0) { if (key2Data.Length == 0) { diff --git a/src/mscorlib/src/System/Globalization/StringInfo.cs b/src/mscorlib/src/System/Globalization/StringInfo.cs index b1151bd..d86e115 100644 --- a/src/mscorlib/src/System/Globalization/StringInfo.cs +++ b/src/mscorlib/src/System/Globalization/StringInfo.cs @@ -17,6 +17,7 @@ namespace System.Globalization { using System; using System.Runtime.Serialization; using System.Security.Permissions; + using System.Diagnostics; using System.Diagnostics.Contracts; [Serializable] @@ -92,7 +93,7 @@ namespace System.Globalization { } set { if (null == value) { - throw new ArgumentNullException("String", + throw new ArgumentNullException(nameof(String), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); @@ -118,11 +119,11 @@ namespace System.Globalization { if(null == this.Indexes) { // Just decide which error to give depending on the param they gave us.... if(startingTextElement < 0) { - throw new ArgumentOutOfRangeException("startingTextElement", + throw new ArgumentOutOfRangeException(nameof(startingTextElement), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); } else { - throw new ArgumentOutOfRangeException("startingTextElement", + throw new ArgumentOutOfRangeException(nameof(startingTextElement), Environment.GetResourceString("Arg_ArgumentOutOfRangeException")); } } @@ -135,22 +136,22 @@ namespace System.Globalization { // Parameter checking // if(startingTextElement < 0) { - throw new ArgumentOutOfRangeException("startingTextElement", + throw new ArgumentOutOfRangeException(nameof(startingTextElement), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); } if(this.String.Length == 0 || startingTextElement >= this.Indexes.Length) { - throw new ArgumentOutOfRangeException("startingTextElement", + throw new ArgumentOutOfRangeException(nameof(startingTextElement), Environment.GetResourceString("Arg_ArgumentOutOfRangeException")); } if(lengthInTextElements < 0) { - throw new ArgumentOutOfRangeException("lengthInTextElements", + throw new ArgumentOutOfRangeException(nameof(lengthInTextElements), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); } if(startingTextElement > this.Indexes.Length - lengthInTextElements) { - throw new ArgumentOutOfRangeException("lengthInTextElements", + throw new ArgumentOutOfRangeException(nameof(lengthInTextElements), Environment.GetResourceString("Arg_ArgumentOutOfRangeException")); } @@ -206,8 +207,8 @@ namespace System.Globalization { internal static int GetCurrentTextElementLen(String str, int index, int len, ref UnicodeCategory ucCurrent, ref int currentCharCount) { - Contract.Assert(index >= 0 && len >= 0, "StringInfo.GetCurrentTextElementLen() : index = " + index + ", len = " + len); - Contract.Assert(index < len, "StringInfo.GetCurrentTextElementLen() : index = " + index + ", len = " + len); + Debug.Assert(index >= 0 && len >= 0, "StringInfo.GetCurrentTextElementLen() : index = " + index + ", len = " + len); + Debug.Assert(index < len, "StringInfo.GetCurrentTextElementLen() : index = " + index + ", len = " + len); if (index + currentCharCount == len) { // This is the last character/surrogate in the string. @@ -268,7 +269,7 @@ namespace System.Globalization { // Validate parameters. // if (str==null) { - throw new ArgumentNullException("str"); + throw new ArgumentNullException(nameof(str)); } Contract.EndContractBlock(); @@ -277,7 +278,7 @@ namespace System.Globalization { if (index == len) { return (String.Empty); } - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); } int charLen; @@ -297,14 +298,14 @@ namespace System.Globalization { // if (str==null) { - throw new ArgumentNullException("str"); + throw new ArgumentNullException(nameof(str)); } Contract.EndContractBlock(); int len = str.Length; if (index < 0 || (index > len)) { - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); } return (new TextElementEnumerator(str, index, len)); @@ -326,7 +327,7 @@ namespace System.Globalization { { if (str == null) { - throw new ArgumentNullException("str"); + throw new ArgumentNullException(nameof(str)); } Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/Globalization/TaiwanCalendar.cs b/src/mscorlib/src/System/Globalization/TaiwanCalendar.cs index 013e2cd..476ddee 100644 --- a/src/mscorlib/src/System/Globalization/TaiwanCalendar.cs +++ b/src/mscorlib/src/System/Globalization/TaiwanCalendar.cs @@ -241,14 +241,14 @@ namespace System.Globalization { public override int ToFourDigitYear(int year) { if (year <= 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); } Contract.EndContractBlock(); if (year > helper.MaxYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), diff --git a/src/mscorlib/src/System/Globalization/TextElementEnumerator.cs b/src/mscorlib/src/System/Globalization/TextElementEnumerator.cs index 5f47f5f..049ccf6 100644 --- a/src/mscorlib/src/System/Globalization/TextElementEnumerator.cs +++ b/src/mscorlib/src/System/Globalization/TextElementEnumerator.cs @@ -15,6 +15,7 @@ using System.Runtime.Serialization; namespace System.Globalization { using System.Collections; + using System.Diagnostics; using System.Diagnostics.Contracts; // @@ -43,9 +44,9 @@ namespace System.Globalization { internal TextElementEnumerator(String str, int startIndex, int strLen) { - Contract.Assert(str != null, "TextElementEnumerator(): str != null"); - Contract.Assert(startIndex >= 0 && strLen >= 0, "TextElementEnumerator(): startIndex >= 0 && strLen >= 0"); - Contract.Assert(strLen >= startIndex, "TextElementEnumerator(): strLen >= startIndex"); + Debug.Assert(str != null, "TextElementEnumerator(): str != null"); + Debug.Assert(startIndex >= 0 && strLen >= 0, "TextElementEnumerator(): startIndex >= 0 && strLen >= 0"); + Debug.Assert(strLen >= startIndex, "TextElementEnumerator(): strLen >= startIndex"); this.str = str; this.startIndex = startIndex; this.strLen = strLen; diff --git a/src/mscorlib/src/System/Globalization/TextInfo.cs b/src/mscorlib/src/System/Globalization/TextInfo.cs index 9b84486..c8108e4 100644 --- a/src/mscorlib/src/System/Globalization/TextInfo.cs +++ b/src/mscorlib/src/System/Globalization/TextInfo.cs @@ -24,6 +24,7 @@ namespace System.Globalization { using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security.Permissions; + using System.Diagnostics; using System.Diagnostics.Contracts; @@ -106,11 +107,6 @@ namespace System.Globalization { this.m_cultureData = cultureData; this.m_cultureName = this.m_cultureData.CultureName; this.m_textInfoName = this.m_cultureData.STEXTINFO; -#if !FEATURE_CORECLR - IntPtr handleOrigin; - this.m_dataHandle = CompareInfo.InternalInitSortHandle(m_textInfoName, out handleOrigin); - this.m_handleOrigin = handleOrigin; -#endif } //////////////////////////////////////////////////////////////////////// @@ -179,30 +175,18 @@ namespace System.Globalization { // Get the text info name belonging to that culture this.m_cultureData = CultureInfo.GetCultureInfo(m_cultureName).m_cultureData; this.m_textInfoName = this.m_cultureData.STEXTINFO; -#if !FEATURE_CORECLR - IntPtr handleOrigin; - this.m_dataHandle = CompareInfo.InternalInitSortHandle(m_textInfoName, out handleOrigin); - this.m_handleOrigin = handleOrigin; -#endif - } + } } - [OnDeserialized] private void OnDeserialized(StreamingContext ctx) { OnDeserialized(); - } - + } + [OnSerializing] private void OnSerializing(StreamingContext ctx) - { -#if !FEATURE_CORECLR - // Initialize the fields Whidbey expects: - // Whidbey expected this, so set it, but the value doesn't matter much - this.m_useUserOverride = false; -#endif // FEATURE_CORECLR - + { // Relabel our name since Whidbey expects it to be called customCultureName this.customCultureName = this.m_cultureName; @@ -229,7 +213,6 @@ namespace System.Globalization { return (Invariant.GetCaseInsensitiveHashCode(s, forceRandomizedHashing, additionalEntropy)); } - [System.Security.SecuritySafeCritical] internal static unsafe bool TryFastFindStringOrdinalIgnoreCase(int searchFlags, String source, int startIndex, String value, int count, ref int foundIndex) { return InternalTryFindStringOrdinalIgnoreCase(searchFlags, source, count, startIndex, value, value.Length, ref foundIndex); @@ -237,7 +220,6 @@ namespace System.Globalization { // This function doesn't check arguments. Please do check in the caller. // The underlying unmanaged code will assert the sanity of arguments. - [System.Security.SecuritySafeCritical] // auto-generated internal static unsafe int CompareOrdinalIgnoreCase(String str1, String str2) { // Compare the whole string and ignore case. @@ -246,19 +228,18 @@ namespace System.Globalization { // This function doesn't check arguments. Please do check in the caller. // The underlying unmanaged code will assert the sanity of arguments. - [System.Security.SecuritySafeCritical] // auto-generated internal static unsafe int CompareOrdinalIgnoreCaseEx(String strA, int indexA, String strB, int indexB, int lengthA, int lengthB ) { - Contract.Assert(strA.Length >= indexA + lengthA, "[TextInfo.CompareOrdinalIgnoreCaseEx] Caller should've validated strA.Length >= indexA + lengthA"); - Contract.Assert(strB.Length >= indexB + lengthB, "[TextInfo.CompareOrdinalIgnoreCaseEx] Caller should've validated strB.Length >= indexB + lengthB"); + Debug.Assert(strA.Length >= indexA + lengthA, "[TextInfo.CompareOrdinalIgnoreCaseEx] Caller should've validated strA.Length >= indexA + lengthA"); + Debug.Assert(strB.Length >= indexB + lengthB, "[TextInfo.CompareOrdinalIgnoreCaseEx] Caller should've validated strB.Length >= indexB + lengthB"); return InternalCompareStringOrdinalIgnoreCase(strA, indexA, strB, indexB, lengthA, lengthB); } internal static int IndexOfStringOrdinalIgnoreCase(String source, String value, int startIndex, int count) { - Contract.Assert(source != null, "[TextInfo.IndexOfStringOrdinalIgnoreCase] Caller should've validated source != null"); - Contract.Assert(value != null, "[TextInfo.IndexOfStringOrdinalIgnoreCase] Caller should've validated value != null"); - Contract.Assert(startIndex + count <= source.Length, "[TextInfo.IndexOfStringOrdinalIgnoreCase] Caller should've validated startIndex + count <= source.Length"); + Debug.Assert(source != null, "[TextInfo.IndexOfStringOrdinalIgnoreCase] Caller should've validated source != null"); + Debug.Assert(value != null, "[TextInfo.IndexOfStringOrdinalIgnoreCase] Caller should've validated value != null"); + Debug.Assert(startIndex + count <= source.Length, "[TextInfo.IndexOfStringOrdinalIgnoreCase] Caller should've validated startIndex + count <= source.Length"); // We return 0 if both inputs are empty strings if (source.Length == 0 && value.Length == 0) @@ -285,7 +266,7 @@ namespace System.Globalization { for (; startIndex <= maxStartIndex; startIndex++) { // We should always have the same or more characters left to search than our actual pattern - Contract.Assert(end - startIndex >= value.Length); + Debug.Assert(end - startIndex >= value.Length); // since this is an ordinal comparison, we can assume that the lengths must match if (CompareOrdinalIgnoreCaseEx(source, startIndex, value, 0, value.Length, value.Length) == 0) { @@ -299,10 +280,10 @@ namespace System.Globalization { internal static int LastIndexOfStringOrdinalIgnoreCase(String source, String value, int startIndex, int count) { - Contract.Assert(source != null, "[TextInfo.LastIndexOfStringOrdinalIgnoreCase] Caller should've validated source != null"); - Contract.Assert(value != null, "[TextInfo.LastIndexOfStringOrdinalIgnoreCase] Caller should've validated value != null"); - Contract.Assert(startIndex - count+1 >= 0, "[TextInfo.LastIndexOfStringOrdinalIgnoreCase] Caller should've validated startIndex - count+1 >= 0"); - Contract.Assert(startIndex <= source.Length, "[TextInfo.LastIndexOfStringOrdinalIgnoreCase] Caller should've validated startIndex <= source.Length"); + Debug.Assert(source != null, "[TextInfo.LastIndexOfStringOrdinalIgnoreCase] Caller should've validated source != null"); + Debug.Assert(value != null, "[TextInfo.LastIndexOfStringOrdinalIgnoreCase] Caller should've validated value != null"); + Debug.Assert(startIndex - count+1 >= 0, "[TextInfo.LastIndexOfStringOrdinalIgnoreCase] Caller should've validated startIndex - count+1 >= 0"); + Debug.Assert(startIndex <= source.Length, "[TextInfo.LastIndexOfStringOrdinalIgnoreCase] Caller should've validated startIndex <= source.Length"); // If value is Empty, the return value is startIndex if (value.Length == 0) @@ -462,7 +443,7 @@ namespace System.Globalization { [System.Runtime.InteropServices.ComVisible(false)] public static TextInfo ReadOnly(TextInfo textInfo) { - if (textInfo == null) { throw new ArgumentNullException("textInfo"); } + if (textInfo == null) { throw new ArgumentNullException(nameof(textInfo)); } Contract.EndContractBlock(); if (textInfo.IsReadOnly) { return (textInfo); } @@ -498,7 +479,6 @@ namespace System.Globalization { public virtual String ListSeparator { - [System.Security.SecuritySafeCritical] // auto-generated get { if (m_listSeparator == null) { @@ -512,7 +492,7 @@ namespace System.Globalization { { if (value == null) { - throw new ArgumentNullException("value", Environment.GetResourceString("ArgumentNull_String")); + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_String")); } Contract.EndContractBlock(); VerifyWritable(); @@ -529,7 +509,6 @@ namespace System.Globalization { // //////////////////////////////////////////////////////////////////////// - [System.Security.SecuritySafeCritical] // auto-generated public unsafe virtual char ToLower(char c) { if(IsAscii(c) && IsAsciiCasingSameAsInvariant) @@ -539,10 +518,9 @@ namespace System.Globalization { return (InternalChangeCaseChar(this.m_dataHandle, this.m_handleOrigin, this.m_textInfoName, c, false)); } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe virtual String ToLower(String str) { - if (str == null) { throw new ArgumentNullException("str"); } + if (str == null) { throw new ArgumentNullException(nameof(str)); } Contract.EndContractBlock(); return InternalChangeCaseString(this.m_dataHandle, this.m_handleOrigin, this.m_textInfoName, str, false); @@ -567,7 +545,6 @@ namespace System.Globalization { // //////////////////////////////////////////////////////////////////////// - [System.Security.SecuritySafeCritical] // auto-generated public unsafe virtual char ToUpper(char c) { if (IsAscii(c) && IsAsciiCasingSameAsInvariant) @@ -578,10 +555,9 @@ namespace System.Globalization { } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe virtual String ToUpper(String str) { - if (str == null) { throw new ArgumentNullException("str"); } + if (str == null) { throw new ArgumentNullException(nameof(str)); } Contract.EndContractBlock(); return InternalChangeCaseString(this.m_dataHandle, this.m_handleOrigin, this.m_textInfoName, str, true); } @@ -698,7 +674,7 @@ namespace System.Globalization { { if (str == null) { - throw new ArgumentNullException("str"); + throw new ArgumentNullException(nameof(str)); } Contract.EndContractBlock(); if (str.Length == 0) @@ -809,7 +785,7 @@ namespace System.Globalization { private static int AddNonLetter(ref StringBuilder result, ref String input, int inputIndex, int charLen) { - Contract.Assert(charLen == 1 || charLen == 2, "[TextInfo.AddNonLetter] CharUnicodeInfo.InternalGetUnicodeCategory returned an unexpected charLen!"); + Debug.Assert(charLen == 1 || charLen == 2, "[TextInfo.AddNonLetter] CharUnicodeInfo.InternalGetUnicodeCategory returned an unexpected charLen!"); if (charLen == 2) { // Surrogate pair @@ -826,7 +802,7 @@ namespace System.Globalization { private int AddTitlecaseLetter(ref StringBuilder result, ref String input, int inputIndex, int charLen) { - Contract.Assert(charLen == 1 || charLen == 2, "[TextInfo.AddTitlecaseLetter] CharUnicodeInfo.InternalGetUnicodeCategory returned an unexpected charLen!"); + Debug.Assert(charLen == 1 || charLen == 2, "[TextInfo.AddTitlecaseLetter] CharUnicodeInfo.InternalGetUnicodeCategory returned an unexpected charLen!"); // for surrogate pairs do a simple ToUpper operation on the substring if (charLen == 2) @@ -947,19 +923,17 @@ namespace System.Globalization { // is not null before calling this. Currenlty, CaseInsensitiveHashCodeProvider // does that. // - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe int GetCaseInsensitiveHashCode(String str) { return GetCaseInsensitiveHashCode(str, false, 0); } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe int GetCaseInsensitiveHashCode(String str, bool forceRandomizedHashing, long additionalEntropy) { // Validate inputs if (str==null) { - throw new ArgumentNullException("str"); + throw new ArgumentNullException(nameof(str)); } Contract.EndContractBlock(); @@ -968,23 +942,19 @@ namespace System.Globalization { } // Change case (ToUpper/ToLower) -- COMNlsInfo::InternalChangeCaseChar - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static unsafe extern char InternalChangeCaseChar(IntPtr handle, IntPtr handleOrigin, String localeName, char ch, bool isToUpper); // Change case (ToUpper/ToLower) -- COMNlsInfo::InternalChangeCaseString - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static unsafe extern String InternalChangeCaseString(IntPtr handle, IntPtr handleOrigin, String localeName, String str, bool isToUpper); // Get case insensitive hash -- ComNlsInfo::InternalGetCaseInsHash - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static unsafe extern int InternalGetCaseInsHash(IntPtr handle, IntPtr handleOrigin, String localeName, String str, bool forceRandomizedHashing, long additionalEntropy); // Call ::CompareStringOrdinal -- ComNlsInfo::InternalCompareStringOrdinalIgnoreCase // Start at indexes and compare for length characters (or remainder of string if length == -1) - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static unsafe extern int InternalCompareStringOrdinalIgnoreCase(String string1, int index1, String string2, int index2, int length1, int length2); @@ -992,7 +962,6 @@ namespace System.Globalization { // ComNlsInfo::InternalTryFindStringOrdinalIgnoreCase attempts a faster IndexOf/LastIndexOf OrdinalIgnoreCase using a kernel function. // Returns true if FindStringOrdinal was handled, with foundIndex set to the target's index into the source // Returns false when FindStringOrdinal wasn't handled - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] diff --git a/src/mscorlib/src/System/Globalization/ThaiBuddhistCalendar.cs b/src/mscorlib/src/System/Globalization/ThaiBuddhistCalendar.cs index f26c68a..e294b51 100644 --- a/src/mscorlib/src/System/Globalization/ThaiBuddhistCalendar.cs +++ b/src/mscorlib/src/System/Globalization/ThaiBuddhistCalendar.cs @@ -213,7 +213,7 @@ namespace System.Globalization { public override int ToFourDigitYear(int year) { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/Globalization/TimeSpanFormat.cs b/src/mscorlib/src/System/Globalization/TimeSpanFormat.cs index 8f58623..e5e615f 100644 --- a/src/mscorlib/src/System/Globalization/TimeSpanFormat.cs +++ b/src/mscorlib/src/System/Globalization/TimeSpanFormat.cs @@ -6,12 +6,12 @@ namespace System.Globalization { using System.Text; using System; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Globalization; internal static class TimeSpanFormat { - [System.Security.SecuritySafeCritical] // auto-generated private static String IntToString(int n, int digits) { return ParseNumbers.IntToString(n, 10, digits, '0', 0); } @@ -143,7 +143,7 @@ namespace System.Globalization { // internal static String FormatCustomized(TimeSpan value, String format, DateTimeFormatInfo dtfi) { - Contract.Assert(dtfi != null, "dtfi == null"); + Debug.Assert(dtfi != null, "dtfi == null"); int day = (int)(value._ticks / TimeSpan.TicksPerDay); long time = value._ticks % TimeSpan.TicksPerDay; @@ -369,7 +369,7 @@ namespace System.Globalization { case '\"': if (inQuote && (quote == format[i])) { /* we were in a quote and found a matching exit quote, so we are outside a quote now */ - Contract.Assert(field >= 0 && field <= 5, "field >= 0 && field <= 5"); + Debug.Assert(field >= 0 && field <= 5, "field >= 0 && field <= 5"); if (field >= 0 && field <= 5) { literals[field] = sb.ToString(); sb.Length = 0; @@ -389,7 +389,7 @@ namespace System.Globalization { } break; case '%': - Contract.Assert(false, "Unexpected special token '%', Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern"); + Debug.Assert(false, "Unexpected special token '%', Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern"); goto default; case '\\': if (!inQuote) { @@ -399,7 +399,7 @@ namespace System.Globalization { goto default; case 'd': if (!inQuote) { - Contract.Assert((field == 0 && sb.Length == 0) || field == 1, + Debug.Assert((field == 0 && sb.Length == 0) || field == 1, "field == 0 || field == 1, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern"); field = 1; // DayHourSep dd++; @@ -407,7 +407,7 @@ namespace System.Globalization { break; case 'h': if (!inQuote) { - Contract.Assert((field == 1 && sb.Length == 0) || field == 2, + Debug.Assert((field == 1 && sb.Length == 0) || field == 2, "field == 1 || field == 2, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern"); field = 2; // HourMinuteSep hh++; @@ -415,7 +415,7 @@ namespace System.Globalization { break; case 'm': if (!inQuote) { - Contract.Assert((field == 2 && sb.Length == 0) || field == 3, + Debug.Assert((field == 2 && sb.Length == 0) || field == 3, "field == 2 || field == 3, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern"); field = 3; // MinuteSecondSep mm++; @@ -423,7 +423,7 @@ namespace System.Globalization { break; case 's': if (!inQuote) { - Contract.Assert((field == 3 && sb.Length == 0) || field == 4, + Debug.Assert((field == 3 && sb.Length == 0) || field == 4, "field == 3 || field == 4, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern"); field = 4; // SecondFractionSep ss++; @@ -432,7 +432,7 @@ namespace System.Globalization { case 'f': case 'F': if (!inQuote) { - Contract.Assert((field == 4 && sb.Length == 0) || field == 5, + Debug.Assert((field == 4 && sb.Length == 0) || field == 5, "field == 4 || field == 5, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern"); field = 5; // End ff++; @@ -444,14 +444,14 @@ namespace System.Globalization { } } - Contract.Assert(field == 5); + Debug.Assert(field == 5); AppCompatLiteral = MinuteSecondSep + SecondFractionSep; - Contract.Assert(0 < dd && dd < 3, "0 < dd && dd < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern"); - Contract.Assert(0 < hh && hh < 3, "0 < hh && hh < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern"); - Contract.Assert(0 < mm && mm < 3, "0 < mm && mm < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern"); - Contract.Assert(0 < ss && ss < 3, "0 < ss && ss < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern"); - Contract.Assert(0 < ff && ff < 8, "0 < ff && ff < 8, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern"); + Debug.Assert(0 < dd && dd < 3, "0 < dd && dd < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern"); + Debug.Assert(0 < hh && hh < 3, "0 < hh && hh < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern"); + Debug.Assert(0 < mm && mm < 3, "0 < mm && mm < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern"); + Debug.Assert(0 < ss && ss < 3, "0 < ss && ss < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern"); + Debug.Assert(0 < ff && ff < 8, "0 < ff && ff < 8, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern"); if (useInvariantFieldLengths) { dd = 2; diff --git a/src/mscorlib/src/System/Globalization/TimeSpanParse.cs b/src/mscorlib/src/System/Globalization/TimeSpanParse.cs index e72e582..d83c5fa 100644 --- a/src/mscorlib/src/System/Globalization/TimeSpanParse.cs +++ b/src/mscorlib/src/System/Globalization/TimeSpanParse.cs @@ -53,6 +53,7 @@ namespace System.Globalization { using System.Text; using System; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Globalization; @@ -126,10 +127,10 @@ namespace System.Globalization { } public bool IsInvalidNumber(int maxValue, int maxPrecision) { - Contract.Assert(ttt == TTT.Num); - Contract.Assert(num > -1); - Contract.Assert(maxValue > 0); - Contract.Assert(maxPrecision == maxFractionDigits || maxPrecision == unlimitedDigits); + Debug.Assert(ttt == TTT.Num); + Debug.Assert(num > -1); + Debug.Assert(maxValue > 0); + Debug.Assert(maxPrecision == maxFractionDigits || maxPrecision == unlimitedDigits); if (num > maxValue) return true; @@ -163,7 +164,7 @@ namespace System.Globalization { } // used by the parsing routines that operate on standard-formats internal TimeSpanToken GetNextToken() { - Contract.Assert(m_pos > -1); + Debug.Assert(m_pos > -1); TimeSpanToken tok = new TimeSpanToken(); char ch = CurrentChar; @@ -374,7 +375,7 @@ namespace System.Globalization { private const int MaxNumericTokens = 5; internal void Init(DateTimeFormatInfo dtfi) { - Contract.Assert(dtfi != null); + Debug.Assert(dtfi != null); lastSeenTTT = TTT.None; tokenCount = 0; @@ -416,7 +417,7 @@ namespace System.Globalization { } lastSeenTTT = tok.ttt; - Contract.Assert(tokenCount == (SepCount + NumCount), "tokenCount == (SepCount + NumCount)"); + Debug.Assert(tokenCount == (SepCount + NumCount), "tokenCount == (SepCount + NumCount)"); return true; } @@ -486,7 +487,7 @@ namespace System.Globalization { return new OverflowException(Environment.GetResourceString(m_failureMessageID)); default: - Contract.Assert(false, "Unknown TimeSpanParseFailure: " + m_failure); + Debug.Assert(false, "Unknown TimeSpanParseFailure: " + m_failure); return new FormatException(Environment.GetResourceString("Format_InvalidString")); } } @@ -627,7 +628,7 @@ namespace System.Globalization { // private static Boolean TryParseTimeSpan(String input, TimeSpanStandardStyles style, IFormatProvider formatProvider, ref TimeSpanResult result) { if (input == null) { - result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "input"); + result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, nameof(input)); return false; } @@ -1117,11 +1118,11 @@ namespace System.Globalization { // private static Boolean TryParseExactTimeSpan(String input, String format, IFormatProvider formatProvider, TimeSpanStyles styles, ref TimeSpanResult result) { if (input == null) { - result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "input"); + result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, nameof(input)); return false; } if (format == null) { - result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "format"); + result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, nameof(format)); return false; } if (format.Length == 0) { @@ -1158,8 +1159,8 @@ namespace System.Globalization { // Actions: Parse the TimeSpan instance using the specified format. Used by TryParseExactTimeSpan. // private static Boolean TryParseByFormat(String input, String format, TimeSpanStyles styles, ref TimeSpanResult result) { - Contract.Assert(input != null, "input != null"); - Contract.Assert(format != null, "format != null"); + Debug.Assert(input != null, "input != null"); + Debug.Assert(format != null, "format != null"); bool seenDD = false; // already processed days? bool seenHH = false; // already processed hours? @@ -1376,7 +1377,7 @@ namespace System.Globalization { result.parsedTimeSpan._ticks = 0; if (input == null) { - result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "input"); + result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, nameof(input)); return false; } str = input; @@ -1511,11 +1512,11 @@ namespace System.Globalization { // private static Boolean TryParseExactMultipleTimeSpan(String input, String[] formats, IFormatProvider formatProvider, TimeSpanStyles styles, ref TimeSpanResult result) { if (input == null) { - result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "input"); + result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, nameof(input)); return false; } if (formats == null) { - result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "formats"); + result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, nameof(formats)); return false; } diff --git a/src/mscorlib/src/System/Globalization/UmAlQuraCalendar.cs b/src/mscorlib/src/System/Globalization/UmAlQuraCalendar.cs index 94b2350..06e7c7d 100644 --- a/src/mscorlib/src/System/Globalization/UmAlQuraCalendar.cs +++ b/src/mscorlib/src/System/Globalization/UmAlQuraCalendar.cs @@ -4,6 +4,7 @@ namespace System.Globalization { using System; + using System.Diagnostics; using System.Diagnostics.Contracts; @@ -338,9 +339,9 @@ namespace System.Globalization { =========================ConvertHijriToGregorian============================*/ static void ConvertHijriToGregorian(int HijriYear, int HijriMonth, int HijriDay, ref int yg, ref int mg, ref int dg) { - Contract.Assert( (HijriYear >= MinCalendarYear) && (HijriYear <= MaxCalendarYear), "Hijri year is out of range."); - Contract.Assert( HijriMonth >= 1, "Hijri month is out of range."); - Contract.Assert( HijriDay >= 1, "Hijri day is out of range."); + Debug.Assert( (HijriYear >= MinCalendarYear) && (HijriYear <= MaxCalendarYear), "Hijri year is out of range."); + Debug.Assert( HijriMonth >= 1, "Hijri month is out of range."); + Debug.Assert( HijriDay >= 1, "Hijri day is out of range."); int index, b, nDays = HijriDay-1; DateTime dt; @@ -392,7 +393,7 @@ namespace System.Globalization { static internal void CheckEraRange(int era) { if (era != CurrentEra && era != UmAlQuraEra) { - throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); + throw new ArgumentOutOfRangeException(nameof(era), Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue")); } } @@ -400,7 +401,7 @@ namespace System.Globalization { CheckEraRange(era); if (year < MinCalendarYear || year > MaxCalendarYear) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -412,7 +413,7 @@ namespace System.Globalization { static internal void CheckYearMonthRange(int year, int month, int era) { CheckYearRange(year, era); if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month")); + throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_Month")); } } @@ -430,7 +431,7 @@ namespace System.Globalization { TimeSpan ts; int yh1=0, mh1=0, dh1=0; - Contract.Assert((time.Ticks >= minDate.Ticks) && (time.Ticks <= maxDate.Ticks), "Gregorian date is out of range."); + Debug.Assert((time.Ticks >= minDate.Ticks) && (time.Ticks <= maxDate.Ticks), "Gregorian date is out of range."); // Find the index where we should start our search by quessing the Hijri year that we will be in HijriYearInfo. // A Hijri year is 354 or 355 days. Use 355 days so that we will search from a lower index. @@ -528,7 +529,7 @@ namespace System.Globalization { public override DateTime AddMonths(DateTime time, int months) { if (months < -120000 || months > 120000) { throw new ArgumentOutOfRangeException( - "months", + nameof(months), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -631,7 +632,7 @@ namespace System.Globalization { { int days = 0, b; - Contract.Assert( (year >= MinCalendarYear) && (year <= MaxCalendarYear), "Hijri year is out of range."); + Debug.Assert( (year >= MinCalendarYear) && (year <= MaxCalendarYear), "Hijri year is out of range."); b = HijriYearInfo[year-MinCalendarYear].HijriMonthsLengthFlags; @@ -640,7 +641,7 @@ namespace System.Globalization { days += 29 + (b & 0x1); b = b >> 1; } - Contract.Assert((days == 354)||(days == 355), "Hijri year has to be 354 or 355 days."); + Debug.Assert((days == 354)||(days == 355), "Hijri year has to be 354 or 355 days."); return days; } @@ -712,7 +713,7 @@ namespace System.Globalization { int daysInMonth = GetDaysInMonth(year, month, era); if (day < 1 || day > daysInMonth) { throw new ArgumentOutOfRangeException( - "day", + nameof(day), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Day"), @@ -774,7 +775,7 @@ namespace System.Globalization { if (day < 1 || day > daysInMonth) { BCLDebug.Log("year = " + year + ", month = " + month + ", day = " + day); throw new ArgumentOutOfRangeException( - "day", + nameof(day), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Day"), @@ -806,7 +807,7 @@ DayInRang: set { if (value != 99 && (value < MinCalendarYear || value > MaxCalendarYear)) { throw new ArgumentOutOfRangeException( - "value", + nameof(value), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), @@ -824,7 +825,7 @@ DayInRang: public override int ToFourDigitYear(int year) { if (year < 0) { - throw new ArgumentOutOfRangeException("year", + throw new ArgumentOutOfRangeException(nameof(year), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.EndContractBlock(); @@ -835,7 +836,7 @@ DayInRang: if ((year < MinCalendarYear) || (year > MaxCalendarYear)) { throw new ArgumentOutOfRangeException( - "year", + nameof(year), String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), diff --git a/src/mscorlib/src/System/Guid.cs b/src/mscorlib/src/System/Guid.cs index 1ccabeb..e2e36ba 100644 --- a/src/mscorlib/src/System/Guid.cs +++ b/src/mscorlib/src/System/Guid.cs @@ -10,6 +10,7 @@ namespace System { using Microsoft.Win32; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; + using System.Diagnostics; using System.Diagnostics.Contracts; // Represents a Globally Unique Identifier. @@ -47,9 +48,9 @@ namespace System { public Guid(byte[] b) { if (b==null) - throw new ArgumentNullException("b"); + throw new ArgumentNullException(nameof(b)); if (b.Length != 16) - throw new ArgumentException(Environment.GetResourceString("Arg_GuidArrayCtor", "16"), "b"); + throw new ArgumentException(Environment.GetResourceString("Arg_GuidArrayCtor", "16"), nameof(b)); Contract.EndContractBlock(); _a = ((int)b[3] << 24) | ((int)b[2] << 16) | ((int)b[1] << 8) | b[0]; @@ -87,10 +88,10 @@ namespace System { public Guid(int a, short b, short c, byte[] d) { if (d==null) - throw new ArgumentNullException("d"); + throw new ArgumentNullException(nameof(d)); // Check that array is not too big if(d.Length != 8) - throw new ArgumentException(Environment.GetResourceString("Arg_GuidArrayCtor", "8"), "d"); + throw new ArgumentException(Environment.GetResourceString("Arg_GuidArrayCtor", "8"), nameof(d)); Contract.EndContractBlock(); _a = a; @@ -185,7 +186,7 @@ namespace System { } internal void SetFailure(ParseFailureKind failure, string failureMessageID, object failureMessageFormatArgument, string failureArgumentName, Exception innerException) { - Contract.Assert(failure != ParseFailureKind.NativeException, "ParseFailureKind.NativeException should not be used with this overload"); + Debug.Assert(failure != ParseFailureKind.NativeException, "ParseFailureKind.NativeException should not be used with this overload"); m_failure = failure; m_failureMessageID = failureMessageID; m_failureMessageFormatArgument = failureMessageFormatArgument; @@ -214,7 +215,7 @@ namespace System { return m_innerException; default: - Contract.Assert(false, "Unknown GuidParseFailure: " + m_failure); + Debug.Assert(false, "Unknown GuidParseFailure: " + m_failure); return new FormatException(Environment.GetResourceString("Format_GuidUnrecognized")); } } @@ -231,7 +232,7 @@ namespace System { public Guid(String g) { if (g==null) { - throw new ArgumentNullException("g"); + throw new ArgumentNullException(nameof(g)); } Contract.EndContractBlock(); this = Guid.Empty; @@ -250,7 +251,7 @@ namespace System { public static Guid Parse(String input) { if (input == null) { - throw new ArgumentNullException("input"); + throw new ArgumentNullException(nameof(input)); } Contract.EndContractBlock(); @@ -281,10 +282,10 @@ namespace System { public static Guid ParseExact(String input, String format) { if (input == null) - throw new ArgumentNullException("input"); + throw new ArgumentNullException(nameof(input)); if (format == null) - throw new ArgumentNullException("format"); + throw new ArgumentNullException(nameof(format)); if( format.Length != 1) { // all acceptable format strings are of length 1 @@ -752,17 +753,14 @@ namespace System { // // StringToShort, StringToInt, and StringToLong are wrappers around COMUtilNative integer parsing routines; - [System.Security.SecuritySafeCritical] private static unsafe bool StringToShort(String str, int requiredLength, int flags, out short result, ref GuidResult parseResult) { return StringToShort(str, null, requiredLength, flags, out result, ref parseResult); } - [System.Security.SecuritySafeCritical] private static unsafe bool StringToShort(String str, ref int parsePos, int requiredLength, int flags, out short result, ref GuidResult parseResult) { fixed(int * ppos = &parsePos) { return StringToShort(str, ppos, requiredLength, flags, out result, ref parseResult); } } - [System.Security.SecurityCritical] private static unsafe bool StringToShort(String str, int* parsePos, int requiredLength, int flags, out short result, ref GuidResult parseResult) { result = 0; int x; @@ -771,17 +769,14 @@ namespace System { return retValue; } - [System.Security.SecuritySafeCritical] private static unsafe bool StringToInt(String str, int requiredLength, int flags, out int result, ref GuidResult parseResult) { return StringToInt(str, null, requiredLength, flags, out result, ref parseResult); } - [System.Security.SecuritySafeCritical] private static unsafe bool StringToInt(String str, ref int parsePos, int requiredLength, int flags, out int result, ref GuidResult parseResult) { fixed(int * ppos = &parsePos) { return StringToInt(str, ppos, requiredLength, flags, out result, ref parseResult); } } - [System.Security.SecurityCritical] private static unsafe bool StringToInt(String str, int* parsePos, int requiredLength, int flags, out int result, ref GuidResult parseResult) { result = 0; @@ -818,17 +813,14 @@ namespace System { } return true; } - [System.Security.SecuritySafeCritical] private static unsafe bool StringToLong(String str, int flags, out long result, ref GuidResult parseResult) { return StringToLong(str, null, flags, out result, ref parseResult); } - [System.Security.SecuritySafeCritical] private static unsafe bool StringToLong(String str, ref int parsePos, int flags, out long result, ref GuidResult parseResult) { fixed(int * ppos = &parsePos) { return StringToLong(str, ppos, flags, out result, ref parseResult); } } - [System.Security.SecuritySafeCritical] private static unsafe bool StringToLong(String str, int* parsePos, int flags, out long result, ref GuidResult parseResult) { result = 0; @@ -921,7 +913,6 @@ namespace System { return ToString("D",null); } - [System.Security.SecuritySafeCritical] public unsafe override int GetHashCode() { // Simply XOR all the bits of the GUID 32 bits at a time. @@ -1007,7 +998,7 @@ namespace System { return 1; } if (!(value is Guid)) { - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeGuid"), "value"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeGuid"), nameof(value)); } Guid g = (Guid)value; @@ -1143,7 +1134,6 @@ namespace System { // This will create a new guid. Since we've now decided that constructors should 0-init, // we need a method that allows users to create a guid. - [System.Security.SecuritySafeCritical] // auto-generated public static Guid NewGuid() { // CoCreateGuid should never return Guid.Empty, since it attempts to maintain some // uniqueness guarantees. It should also never return a known GUID, but it's unclear @@ -1165,13 +1155,11 @@ namespace System { return (char) ((a > 9) ? a - 10 + 0x61 : a + 0x30); } - [System.Security.SecurityCritical] unsafe private static int HexsToChars(char* guidChars, int offset, int a, int b) { return HexsToChars(guidChars, offset, a, b, false); } - [System.Security.SecurityCritical] unsafe private static int HexsToChars(char* guidChars, int offset, int a, int b, bool hex) { if (hex) { @@ -1192,7 +1180,6 @@ namespace System { // IFormattable interface // We currently ignore provider - [System.Security.SecuritySafeCritical] public String ToString(String format, IFormatProvider provider) { if (format == null || format.Length == 0) diff --git a/src/mscorlib/src/System/IAppDomain.cs b/src/mscorlib/src/System/IAppDomain.cs index bd8b876..cdb8316 100644 --- a/src/mscorlib/src/System/IAppDomain.cs +++ b/src/mscorlib/src/System/IAppDomain.cs @@ -13,256 +13,16 @@ ** ** ===========================================================*/ -namespace System { - using System.Reflection; - using System.Runtime.CompilerServices; - using SecurityManager = System.Security.SecurityManager; - using System.Security.Permissions; - using IEvidenceFactory = System.Security.IEvidenceFactory; -#if FEATURE_IMPERSONATION - using System.Security.Principal; -#endif - using System.Security.Policy; - using System.Security; - using System.Security.Util; - using System.Collections; - using System.Text; - using System.Configuration.Assemblies; - using System.Threading; +namespace System +{ using System.Runtime.InteropServices; - using System.Runtime.Remoting; - using System.Reflection.Emit; - using CultureInfo = System.Globalization.CultureInfo; - using System.IO; - using System.Runtime.Versioning; [GuidAttribute("05F696DC-2B29-3663-AD8B-C4389CF2A713")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _AppDomain { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); - - String ToString(); - - bool Equals (Object other); - - int GetHashCode (); - - Type GetType (); - -#if FEATURE_REMOTING - [System.Security.SecurityCritical] // auto-generated_required - Object InitializeLifetimeService (); - - [System.Security.SecurityCritical] // auto-generated_required - Object GetLifetimeService (); -#endif // FEATURE_REMOTING - -#if FEATURE_CAS_POLICY - Evidence Evidence { get; } -#endif // FEATURE_CAS_POLICY - event EventHandler DomainUnload; - - [method:System.Security.SecurityCritical] - event AssemblyLoadEventHandler AssemblyLoad; - - event EventHandler ProcessExit; - - [method:System.Security.SecurityCritical] - event ResolveEventHandler TypeResolve; - - [method:System.Security.SecurityCritical] - event ResolveEventHandler ResourceResolve; - - [method:System.Security.SecurityCritical] - event ResolveEventHandler AssemblyResolve; - - [method:System.Security.SecurityCritical] - event UnhandledExceptionEventHandler UnhandledException; - - AssemblyBuilder DefineDynamicAssembly(AssemblyName name, - AssemblyBuilderAccess access); - - AssemblyBuilder DefineDynamicAssembly(AssemblyName name, - AssemblyBuilderAccess access, - String dir); - - AssemblyBuilder DefineDynamicAssembly(AssemblyName name, - AssemblyBuilderAccess access, - Evidence evidence); - - AssemblyBuilder DefineDynamicAssembly(AssemblyName name, - AssemblyBuilderAccess access, - PermissionSet requiredPermissions, - PermissionSet optionalPermissions, - PermissionSet refusedPermissions); - - AssemblyBuilder DefineDynamicAssembly(AssemblyName name, - AssemblyBuilderAccess access, - String dir, - Evidence evidence); - - AssemblyBuilder DefineDynamicAssembly(AssemblyName name, - AssemblyBuilderAccess access, - String dir, - PermissionSet requiredPermissions, - PermissionSet optionalPermissions, - PermissionSet refusedPermissions); - - AssemblyBuilder DefineDynamicAssembly(AssemblyName name, - AssemblyBuilderAccess access, - Evidence evidence, - PermissionSet requiredPermissions, - PermissionSet optionalPermissions, - PermissionSet refusedPermissions); - - AssemblyBuilder DefineDynamicAssembly(AssemblyName name, - AssemblyBuilderAccess access, - String dir, - Evidence evidence, - PermissionSet requiredPermissions, - PermissionSet optionalPermissions, - PermissionSet refusedPermissions); - - AssemblyBuilder DefineDynamicAssembly(AssemblyName name, - AssemblyBuilderAccess access, - String dir, - Evidence evidence, - PermissionSet requiredPermissions, - PermissionSet optionalPermissions, - PermissionSet refusedPermissions, - bool isSynchronized); - - ObjectHandle CreateInstance(String assemblyName, - String typeName); - - - ObjectHandle CreateInstanceFrom(String assemblyFile, - String typeName); - - - ObjectHandle CreateInstance(String assemblyName, - String typeName, - Object[] activationAttributes); - - ObjectHandle CreateInstanceFrom(String assemblyFile, - String typeName, - Object[] activationAttributes); - - ObjectHandle CreateInstance(String assemblyName, - String typeName, - bool ignoreCase, - BindingFlags bindingAttr, - Binder binder, - Object[] args, - CultureInfo culture, - Object[] activationAttributes, - Evidence securityAttributes); - - ObjectHandle CreateInstanceFrom(String assemblyFile, - String typeName, - bool ignoreCase, - BindingFlags bindingAttr, - Binder binder, - Object[] args, - CultureInfo culture, - Object[] activationAttributes, - Evidence securityAttributes); - - Assembly Load(AssemblyName assemblyRef); - - Assembly Load(String assemblyString); - - Assembly Load(byte[] rawAssembly); - - Assembly Load(byte[] rawAssembly, - byte[] rawSymbolStore); - - Assembly Load(byte[] rawAssembly, - byte[] rawSymbolStore, - Evidence securityEvidence); - - Assembly Load(AssemblyName assemblyRef, - Evidence assemblySecurity); - - Assembly Load(String assemblyString, - Evidence assemblySecurity); - - int ExecuteAssembly(String assemblyFile, - Evidence assemblySecurity); - - int ExecuteAssembly(String assemblyFile); - - int ExecuteAssembly(String assemblyFile, - Evidence assemblySecurity, - String[] args); - - String FriendlyName - { get; } -#if FEATURE_FUSION - String BaseDirectory - { - get; - } - - String RelativeSearchPath - { get; } - - bool ShadowCopyFiles - { get; } -#endif - Assembly[] GetAssemblies(); -#if FEATURE_FUSION - [System.Security.SecurityCritical] // auto-generated_required - void AppendPrivatePath(String path); - - [System.Security.SecurityCritical] // auto-generated_required - void ClearPrivatePath(); - - [System.Security.SecurityCritical] // auto-generated_required - void SetShadowCopyPath (String s); - - [System.Security.SecurityCritical] // auto-generated_required - void ClearShadowCopyPath ( ); - - [System.Security.SecurityCritical] // auto-generated_required - void SetCachePath (String s); -#endif //FEATURE_FUSION - [System.Security.SecurityCritical] // auto-generated_required - void SetData(String name, Object data); - - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif - Object GetData(string name); - -#if FEATURE_CAS_POLICY - [System.Security.SecurityCritical] // auto-generated_required - void SetAppDomainPolicy(PolicyLevel domainPolicy); - -#if FEATURE_IMPERSONATION - void SetThreadPrincipal(IPrincipal principal); -#endif // FEATURE_IMPERSONATION - - void SetPrincipalPolicy(PrincipalPolicy policy); -#endif - -#if FEATURE_REMOTING - void DoCallBack(CrossAppDomainDelegate theDelegate); -#endif - - String DynamicDirectory - { get; } -#endif } } diff --git a/src/mscorlib/src/System/IAppDomainPauseManager.cs b/src/mscorlib/src/System/IAppDomainPauseManager.cs index 7e03145..902a79b 100644 --- a/src/mscorlib/src/System/IAppDomainPauseManager.cs +++ b/src/mscorlib/src/System/IAppDomainPauseManager.cs @@ -20,16 +20,13 @@ namespace System using System.Runtime.Versioning; using System.Runtime.CompilerServices; - [System.Security.SecurityCritical] internal class AppDomainPauseManager { - [System.Security.SecurityCritical] public AppDomainPauseManager() { isPaused = false; } - [System.Security.SecurityCritical] static AppDomainPauseManager() { } @@ -37,22 +34,19 @@ namespace System static readonly AppDomainPauseManager instance = new AppDomainPauseManager(); internal static AppDomainPauseManager Instance { - [System.Security.SecurityCritical] get { return instance; } } // FAS: IAppDomainPauseConsumer interface implementation // currently there is nothing we do here as the implementation // of updating pause times have been moved to native CorHost2 - [System.Security.SecurityCritical] public void Pausing() { } - [System.Security.SecurityCritical] public void Paused() { - Contract.Assert(!isPaused); + Debug.Assert(!isPaused); if(ResumeEvent == null) ResumeEvent = new ManualResetEvent(false); @@ -67,15 +61,13 @@ namespace System isPaused = true; } - [System.Security.SecurityCritical] public void Resuming() { - Contract.Assert(isPaused); + Debug.Assert(isPaused); isPaused = false; ResumeEvent.Set(); } - [System.Security.SecurityCritical] public void Resumed() { Timer.Resume(); @@ -85,15 +77,12 @@ namespace System internal static bool IsPaused { - [System.Security.SecurityCritical] get { return isPaused; } } internal static ManualResetEvent ResumeEvent { - [System.Security.SecurityCritical] get; - [System.Security.SecurityCritical] set; } } diff --git a/src/mscorlib/src/System/IO/BinaryReader.cs b/src/mscorlib/src/System/IO/BinaryReader.cs index 8accf0b..4145a7f 100644 --- a/src/mscorlib/src/System/IO/BinaryReader.cs +++ b/src/mscorlib/src/System/IO/BinaryReader.cs @@ -19,6 +19,7 @@ namespace System.IO { using System.Runtime; using System.Text; using System.Globalization; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Security; @@ -40,7 +41,7 @@ namespace System.IO { private bool m_isMemoryStream; // "do we sit on MemoryStream?" for Read/ReadInt32 perf private bool m_leaveOpen; - public BinaryReader(Stream input) : this(input, new UTF8Encoding(), false) { + public BinaryReader(Stream input) : this(input, Encoding.UTF8, false) { } public BinaryReader(Stream input, Encoding encoding) : this(input, encoding, false) { @@ -48,10 +49,10 @@ namespace System.IO { public BinaryReader(Stream input, Encoding encoding, bool leaveOpen) { if (input==null) { - throw new ArgumentNullException("input"); + throw new ArgumentNullException(nameof(input)); } if (encoding==null) { - throw new ArgumentNullException("encoding"); + throw new ArgumentNullException(nameof(encoding)); } if (!input.CanRead) throw new ArgumentException(Environment.GetResourceString("Argument_StreamNotReadable")); @@ -73,7 +74,7 @@ namespace System.IO { m_isMemoryStream = (m_stream.GetType() == typeof(MemoryStream)); m_leaveOpen = leaveOpen; - Contract.Assert(m_decoder!=null, "[BinaryReader.ctor]m_decoder!=null"); + Debug.Assert(m_decoder!=null, "[BinaryReader.ctor]m_decoder!=null"); } public virtual Stream BaseStream { @@ -173,7 +174,7 @@ namespace System.IO { if (m_stream==null) __Error.FileNotOpen(); // read directly from MemoryStream buffer MemoryStream mStream = m_stream as MemoryStream; - Contract.Assert(mStream != null, "m_stream as MemoryStream != null"); + Debug.Assert(mStream != null, "m_stream as MemoryStream != null"); return mStream.InternalReadInt32(); } @@ -209,14 +210,12 @@ namespace System.IO { return ((ulong)hi) << 32 | lo; } - [System.Security.SecuritySafeCritical] // auto-generated public virtual unsafe float ReadSingle() { FillBuffer(4); uint tmpBuffer = (uint)(m_buffer[0] | m_buffer[1] << 8 | m_buffer[2] << 16 | m_buffer[3] << 24); return *((float*)&tmpBuffer); } - [System.Security.SecuritySafeCritical] // auto-generated public virtual unsafe double ReadDouble() { FillBuffer(8); uint lo = (uint)(m_buffer[0] | m_buffer[1] << 8 | @@ -294,16 +293,15 @@ namespace System.IO { return StringBuilderCache.GetStringAndRelease(sb); } - [SecuritySafeCritical] public virtual int Read(char[] buffer, int index, int count) { if (buffer==null) { - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); } if (index < 0) { - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (count < 0) { - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (buffer.Length - index < count) { throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); @@ -319,11 +317,10 @@ namespace System.IO { return InternalReadChars(buffer, index, count); } - [SecurityCritical] private int InternalReadChars(char[] buffer, int index, int count) { Contract.Requires(buffer != null); Contract.Requires(index >= 0 && count >= 0); - Contract.Assert(m_stream != null); + Debug.Assert(m_stream != null); int numBytes = 0; int charsRemaining = count; @@ -355,7 +352,7 @@ namespace System.IO { if (m_isMemoryStream) { MemoryStream mStream = m_stream as MemoryStream; - Contract.Assert(mStream != null, "m_stream as MemoryStream != null"); + Debug.Assert(mStream != null, "m_stream as MemoryStream != null"); position = mStream.InternalGetPosition(); numBytes = mStream.InternalEmulateRead(numBytes); @@ -371,7 +368,7 @@ namespace System.IO { return (count - charsRemaining); } - Contract.Assert(byteBuffer != null, "expected byteBuffer to be non-null"); + Debug.Assert(byteBuffer != null, "expected byteBuffer to be non-null"); checked { @@ -398,7 +395,7 @@ namespace System.IO { } // this should never fail - Contract.Assert(charsRemaining >= 0, "We read too many characters."); + Debug.Assert(charsRemaining >= 0, "We read too many characters."); // we may have read fewer than the number of characters requested if end of stream reached // or if the encoding makes the char count too big for the buffer (e.g. fallback sequence) @@ -447,7 +444,7 @@ namespace System.IO { return -1; } - Contract.Assert(numBytes == 1 || numBytes == 2, "BinaryReader::InternalReadOneChar assumes it's reading one or 2 bytes only."); + Debug.Assert(numBytes == 1 || numBytes == 2, "BinaryReader::InternalReadOneChar assumes it's reading one or 2 bytes only."); try { @@ -464,7 +461,7 @@ namespace System.IO { throw; } - Contract.Assert(charsRead < 2, "InternalReadOneChar - assuming we only got 0 or 1 char, not 2!"); + Debug.Assert(charsRead < 2, "InternalReadOneChar - assuming we only got 0 or 1 char, not 2!"); // Console.WriteLine("That became: " + charsRead + " characters."); } if (charsRead == 0) @@ -472,10 +469,9 @@ namespace System.IO { return m_singleChar[0]; } - [SecuritySafeCritical] public virtual char[] ReadChars(int count) { if (count<0) { - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.Ensures(Contract.Result() != null); Contract.Ensures(Contract.Result().Length <= count); @@ -502,11 +498,11 @@ namespace System.IO { public virtual int Read(byte[] buffer, int index, int count) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.Ensures(Contract.Result() >= 0); @@ -518,7 +514,7 @@ namespace System.IO { } public virtual byte[] ReadBytes(int count) { - if (count < 0) throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + if (count < 0) throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.Ensures(Contract.Result() != null); Contract.Ensures(Contract.Result().Length <= Contract.OldValue(count)); Contract.EndContractBlock(); @@ -551,7 +547,7 @@ namespace System.IO { protected virtual void FillBuffer(int numBytes) { if (m_buffer != null && (numBytes < 0 || numBytes > m_buffer.Length)) { - throw new ArgumentOutOfRangeException("numBytes", Environment.GetResourceString("ArgumentOutOfRange_BinaryReaderFillBuffer")); + throw new ArgumentOutOfRangeException(nameof(numBytes), Environment.GetResourceString("ArgumentOutOfRange_BinaryReaderFillBuffer")); } int bytesRead=0; int n = 0; diff --git a/src/mscorlib/src/System/IO/BinaryWriter.cs b/src/mscorlib/src/System/IO/BinaryWriter.cs index c775cbc..f99b4d3 100644 --- a/src/mscorlib/src/System/IO/BinaryWriter.cs +++ b/src/mscorlib/src/System/IO/BinaryWriter.cs @@ -17,6 +17,7 @@ using System; using System.Runtime; using System.Runtime.Serialization; using System.Text; +using System.Diagnostics; using System.Diagnostics.Contracts; namespace System.IO { @@ -25,7 +26,7 @@ namespace System.IO { // give unique encodings. // [Serializable] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public class BinaryWriter : IDisposable { public static readonly BinaryWriter Null = new BinaryWriter(); @@ -38,14 +39,6 @@ namespace System.IO { [OptionalField] // New in .NET FX 4.5. False is the right default value. private bool _leaveOpen; - // This field should never have been serialized and has not been used since before v2.0. - // However, this type is serializable, and we need to keep the field name around when deserializing. - // Also, we'll make .NET FX 4.5 not break if it's missing. -#pragma warning disable 169 - [OptionalField] - private char[] _tmpOneCharBuffer; -#pragma warning restore 169 - // Perf optimization stuff private byte[] _largeByteBuffer; // temp space for writing chars. private int _maxChars; // max # of chars we can put in _largeByteBuffer @@ -58,11 +51,11 @@ namespace System.IO { { OutStream = Stream.Null; _buffer = new byte[16]; - _encoding = new UTF8Encoding(false, true); + _encoding = EncodingCache.UTF8NoBOM; _encoder = _encoding.GetEncoder(); } - public BinaryWriter(Stream output) : this(output, new UTF8Encoding(false, true), false) + public BinaryWriter(Stream output) : this(output, EncodingCache.UTF8NoBOM, false) { } @@ -73,9 +66,9 @@ namespace System.IO { public BinaryWriter(Stream output, Encoding encoding, bool leaveOpen) { if (output==null) - throw new ArgumentNullException("output"); + throw new ArgumentNullException(nameof(output)); if (encoding==null) - throw new ArgumentNullException("encoding"); + throw new ArgumentNullException(nameof(encoding)); if (!output.CanWrite) throw new ArgumentException(Environment.GetResourceString("Argument_StreamNotWritable")); Contract.EndContractBlock(); @@ -166,7 +159,7 @@ namespace System.IO { // public virtual void Write(byte[] buffer) { if (buffer == null) - throw new ArgumentNullException("buffer"); + throw new ArgumentNullException(nameof(buffer)); Contract.EndContractBlock(); OutStream.Write(buffer, 0, buffer.Length); } @@ -185,13 +178,12 @@ namespace System.IO { // advanced by two. // Note this method cannot handle surrogates properly in UTF-8. // - [System.Security.SecuritySafeCritical] // auto-generated public unsafe virtual void Write(char ch) { if (Char.IsSurrogate(ch)) throw new ArgumentException(Environment.GetResourceString("Arg_SurrogatesNotAllowedAsSingleChar")); Contract.EndContractBlock(); - Contract.Assert(_encoding.GetMaxByteCount(1) <= 16, "_encoding.GetMaxByteCount(1) <= 16)"); + Debug.Assert(_encoding.GetMaxByteCount(1) <= 16, "_encoding.GetMaxByteCount(1) <= 16)"); int numBytes = 0; fixed(byte * pBytes = _buffer) { numBytes = _encoder.GetBytes(&ch, 1, pBytes, _buffer.Length, flush: true); @@ -207,7 +199,7 @@ namespace System.IO { public virtual void Write(char[] chars) { if (chars == null) - throw new ArgumentNullException("chars"); + throw new ArgumentNullException(nameof(chars)); Contract.EndContractBlock(); byte[] bytes = _encoding.GetBytes(chars, 0, chars.Length); @@ -229,7 +221,6 @@ namespace System.IO { // Writes a double to this stream. The current position of the stream is // advanced by eight. // - [System.Security.SecuritySafeCritical] // auto-generated public unsafe virtual void Write(double value) { ulong TmpValue = *(ulong *)&value; @@ -332,7 +323,6 @@ namespace System.IO { // Writes a float to this stream. The current position of the stream is // advanced by four. // - [System.Security.SecuritySafeCritical] // auto-generated public unsafe virtual void Write(float value) { uint TmpValue = *(uint *)&value; @@ -349,11 +339,10 @@ namespace System.IO { // a four-byte unsigned integer, and then writes that many characters // to the stream. // - [System.Security.SecuritySafeCritical] // auto-generated public unsafe virtual void Write(String value) { if (value==null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); Contract.EndContractBlock(); int len = _encoding.GetByteCount(value); @@ -366,7 +355,7 @@ namespace System.IO { if (len <= _largeByteBuffer.Length) { - //Contract.Assert(len == _encoding.GetBytes(chars, 0, chars.Length, _largeByteBuffer, 0), "encoding's GetByteCount & GetBytes gave different answers! encoding type: "+_encoding.GetType().Name); + //Debug.Assert(len == _encoding.GetBytes(chars, 0, chars.Length, _largeByteBuffer, 0), "encoding's GetByteCount & GetBytes gave different answers! encoding type: "+_encoding.GetType().Name); _encoding.GetBytes(value, 0, value.Length, _largeByteBuffer, 0); OutStream.Write(_largeByteBuffer, 0, len); } @@ -401,14 +390,14 @@ namespace System.IO { } #if _DEBUG totalBytes += byteLen; - Contract.Assert (totalBytes <= len && byteLen <= _largeByteBuffer.Length, "BinaryWriter::Write(String) - More bytes encoded than expected!"); + Debug.Assert (totalBytes <= len && byteLen <= _largeByteBuffer.Length, "BinaryWriter::Write(String) - More bytes encoded than expected!"); #endif OutStream.Write(_largeByteBuffer, 0, byteLen); charStart += charCount; numLeft -= charCount; } #if _DEBUG - Contract.Assert(totalBytes == len, "BinaryWriter::Write(String) - Didn't write out all the bytes!"); + Debug.Assert(totalBytes == len, "BinaryWriter::Write(String) - Didn't write out all the bytes!"); #endif } } diff --git a/src/mscorlib/src/System/IO/BufferedStream.cs b/src/mscorlib/src/System/IO/BufferedStream.cs deleted file mode 100644 index 0c73b5c..0000000 --- a/src/mscorlib/src/System/IO/BufferedStream.cs +++ /dev/null @@ -1,1320 +0,0 @@ -// 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. - -/*============================================================ -** -** -** -** -** Purpose: A composable Stream that buffers reads & writes to the underlying stream. -** -** -===========================================================*/ -using System; -using System.Runtime.InteropServices; -using System.Globalization; -using System.Diagnostics.Contracts; -using System.Runtime.CompilerServices; -using System.Threading; -using System.Collections.ObjectModel; -using System.Security; -using System.Threading.Tasks; - -namespace System.IO { - -/// -/// One of the design goals here is to prevent the buffer from getting in the way and slowing -/// down underlying stream accesses when it is not needed. If you always read & write for sizes -/// greater than the internal buffer size, then this class may not even allocate the internal buffer. -/// See a large comment in Write for the details of the write buffer heuristic. -/// -/// This class buffers reads & writes in a shared buffer. -/// (If you maintained two buffers separately, one operation would always trash the other buffer -/// anyways, so we might as well use one buffer.) -/// The assumption here is you will almost always be doing a series of reads or writes, but rarely -/// alternate between the two of them on the same stream. -/// -/// Class Invariants: -/// The class has one buffer, shared for reading & writing. -/// It can only be used for one or the other at any point in time - not both. -/// The following should be true: -/// 0 implies the read buffer is valid, but we're at the end of the buffer. -/// * _readPos == _readLen == 0 means the read buffer contains garbage. -/// * Either _writePos can be greater than 0, or _readLen & _readPos can be greater than zero, -/// but neither can be greater than zero at the same time. -/// ]]> -/// This class will never cache more bytes than the max specified buffer size. -/// However, it may use a temporary buffer of up to twice the size in order to combine several IO operations on -/// the underlying stream into a single operation. This is because we assume that memory copies are significantly -/// faster than IO operations on the underlying stream (if this was not true, using buffering is never appropriate). -/// The max size of this "shadow" buffer is limited as to not allocate it on the LOH. -/// Shadowing is always transient. Even when using this technique, this class still guarantees that the number of -/// bytes cached (not yet written to the target stream or not yet consumed by the user) is never larger than the -/// actual specified buffer size. -/// -[ComVisible(true)] -public sealed class BufferedStream : Stream { - - - private const Int32 _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 Int32 _bufferSize; // Length of internal buffer (not counting the shadow buffer). - - private Int32 _readPos; // Read pointer within shared buffer. - private Int32 _readLen; // Number of bytes read in buffer from _stream. - private Int32 _writePos; // Write pointer within shared buffer. - - private BeginEndAwaitableAdapter _beginEndAwaitable; // Used to be able to await a BeginXxx call and thus to share code - // between the APM and Async pattern implementations - - 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 DataContractSerializer. - // Because this ctor was here previously we need to keep it around. - private BufferedStream() { } - - - public BufferedStream(Stream stream) - - : this(stream, _DefaultBufferSize) { - } - - - public BufferedStream(Stream stream, Int32 bufferSize) { - - if (stream == null) - throw new ArgumentNullException("stream"); - - if (bufferSize <= 0) - throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", "bufferSize")); - - Contract.EndContractBlock(); - - BCLDebug.Perf(!(stream is FileStream), "FileStream is buffered - don't wrap it in a BufferedStream"); - BCLDebug.Perf(!(stream is MemoryStream), "MemoryStream shouldn't be wrapped in a BufferedStream!"); - BCLDebug.Perf(!(stream is BufferedStream), "BufferedStream shouldn't be wrapped in another BufferedStream!"); - - _stream = stream; - _bufferSize = bufferSize; - - // Allocate _buffer on its first use - it will not be used if all reads - // & writes are greater than or equal to buffer size. - - if (!_stream.CanRead && !_stream.CanWrite) - __Error.StreamIsClosed(); - } - - - private void EnsureNotClosed() { - - if (_stream == null) - __Error.StreamIsClosed(); - } - - - private void EnsureCanSeek() { - - Contract.Requires(_stream != null); - - if (!_stream.CanSeek) - __Error.SeekNotSupported(); - } - - - private void EnsureCanRead() { - - Contract.Requires(_stream != null); - - if (!_stream.CanRead) - __Error.ReadNotSupported(); - } - - - private void EnsureCanWrite() { - - Contract.Requires(_stream != null); - - if (!_stream.CanWrite) - __Error.WriteNotSupported(); - } - - - private void EnsureBeginEndAwaitableAllocated() { - // We support only a single ongoing async operation and enforce this with a semaphore, - // so singleton is fine and no need to worry about a race condition here. - if (_beginEndAwaitable == null) - _beginEndAwaitable = new BeginEndAwaitableAdapter(); - } - - - /// MaxShadowBufferSize is chosed such that shadow buffers are not allocated on the Large Object Heap. - /// Currently, an object is allocated on the LOH if it is larger than 85000 bytes. See LARGE_OBJECT_SIZE in ndp\clr\src\vm\gc.h - /// We will go with exactly 80 KBytes, although this is somewhat arbitrary. - private const Int32 MaxShadowBufferSize = 81920; // Make sure not to get to the Large Object Heap. - private void EnsureShadowBufferAllocated() { - - Contract.Assert(_buffer != null); - Contract.Assert(_bufferSize > 0); - - // Already have shadow buffer? - if (_buffer.Length != _bufferSize || _bufferSize >= MaxShadowBufferSize) - return; - - Byte[] shadowBuffer = new Byte[Math.Min(_bufferSize + _bufferSize, MaxShadowBufferSize)]; - Buffer.InternalBlockCopy(_buffer, 0, shadowBuffer, 0, _writePos); - _buffer = shadowBuffer; - } - - - private void EnsureBufferAllocated() { - - Contract.Assert(_bufferSize > 0); - - // BufferedStream is not intended for multi-threaded use, so no worries about the get/set race conditions on _buffer. - if (_buffer == null) - _buffer = new Byte[_bufferSize]; - } - - - internal Stream UnderlyingStream { - [FriendAccessAllowed] - [Pure] - get { return _stream; } - } - - - internal Int32 BufferSize { - [FriendAccessAllowed] - [Pure] - get { return _bufferSize; } - } - - - public override bool CanRead { - [Pure] - get { return _stream != null && _stream.CanRead; } - } - - - public override bool CanWrite { - [Pure] - get { return _stream != null && _stream.CanWrite; } - } - - - public override bool CanSeek { - [Pure] - get { return _stream != null && _stream.CanSeek; } - } - - - public override Int64 Length { - get { - EnsureNotClosed(); - - if (_writePos > 0) - FlushWrite(); - - return _stream.Length; - } - } - - - public override Int64 Position { - get { - EnsureNotClosed(); - EnsureCanSeek(); - - Contract.Assert(! (_writePos > 0 && _readPos != _readLen), "Read and Write buffers cannot both have data in them at the same time."); - return _stream.Position + (_readPos - _readLen + _writePos); - } - set { - if (value < 0) - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - Contract.EndContractBlock(); - - EnsureNotClosed(); - EnsureCanSeek(); - - if (_writePos > 0) - FlushWrite(); - - _readPos = 0; - _readLen = 0; - _stream.Seek(value, SeekOrigin.Begin); - } - } - - - protected override void Dispose(bool disposing) { - - try { - if (disposing && _stream != null) { - try { - Flush(); - } finally { - _stream.Close(); - } - } - } finally { - _stream = null; - _buffer = null; - _lastSyncCompletedReadTask = null; - - // Call base.Dispose(bool) to cleanup async IO resources - base.Dispose(disposing); - } - } - - - public override void Flush() { - - EnsureNotClosed(); - - // Has WRITE data in the buffer: - if (_writePos > 0) { - - FlushWrite(); - Contract.Assert(_writePos == 0 && _readPos == 0 && _readLen == 0); - return; - } - - // Has READ data in the buffer: - if (_readPos < _readLen) { - - // If the underlying stream is not seekable AND we have something in the read buffer, then FlushRead would throw. - // We can either throw away the buffer resulting in data loss (!) or ignore the Flush. - // (We cannot throw becasue it would be a breaking change.) We opt into ignoring the Flush in that situation. - if (!_stream.CanSeek) - return; - - FlushRead(); - - // User streams may have opted to throw from Flush if CanWrite is false (although the abstract Stream does not do so). - // However, if we do not forward the Flush to the underlying stream, we may have problems when chaining several streams. - // Let us make a best effort attempt: - if (_stream.CanWrite || _stream is BufferedStream) - _stream.Flush(); - - Contract.Assert(_writePos == 0 && _readPos == 0 && _readLen == 0); - return; - } - - // We had no data in the buffer, but we still need to tell the underlying stream to flush. - if (_stream.CanWrite || _stream is BufferedStream) - _stream.Flush(); - - _writePos = _readPos = _readLen = 0; - } - - public override Task FlushAsync(CancellationToken cancellationToken) { - - if (cancellationToken.IsCancellationRequested) - return Task.FromCanceled(cancellationToken); - - EnsureNotClosed(); - - return FlushAsyncInternal(cancellationToken, this, _stream, _writePos, _readPos, _readLen); - } - - - private static async Task FlushAsyncInternal(CancellationToken cancellationToken, - BufferedStream _this, Stream stream, Int32 writePos, Int32 readPos, Int32 readLen) { - - // We bring instance fields down as local parameters to this async method becasue BufferedStream is derived from MarshalByRefObject. - // Field access would be from the async state machine i.e., not via the this pointer and would require runtime checking to see - // if we are talking to a remote object, which is currently very slow - - Contract.Assert(stream != null); - - SemaphoreSlim sem = _this.EnsureAsyncActiveSemaphoreInitialized(); - await sem.WaitAsync().ConfigureAwait(false); - try { - - if (writePos > 0) { - - await _this.FlushWriteAsync(cancellationToken).ConfigureAwait(false); - Contract.Assert(_this._writePos == 0 && _this._readPos == 0 && _this._readLen == 0); - return; - } - - if (readPos < readLen) { - - // If the underlying stream is not seekable AND we have something in the read buffer, then FlushRead would throw. - // We can either throw away the buffer resulting in date loss (!) or ignore the Flush. (We cannot throw becasue it - // would be a breaking change.) We opt into ignoring the Flush in that situation. - if (!stream.CanSeek) - return; - - _this.FlushRead(); // not async; it uses Seek, but there's no SeekAsync - - // User streams may have opted to throw from Flush if CanWrite is false (although the abstract Stream does not do so). - // However, if we do not forward the Flush to the underlying stream, we may have problems when chaining several streams. - // Let us make a best effort attempt: - if (stream.CanRead || stream is BufferedStream) - await stream.FlushAsync(cancellationToken).ConfigureAwait(false); - - Contract.Assert(_this._writePos == 0 && _this._readPos == 0 && _this._readLen == 0); - return; - } - - // We had no data in the buffer, but we still need to tell the underlying stream to flush. - if (stream.CanWrite || stream is BufferedStream) - await stream.FlushAsync(cancellationToken).ConfigureAwait(false); - - // There was nothing in the buffer: - Contract.Assert(_this._writePos == 0 && _this._readPos == _this._readLen); - - } finally { - sem.Release(); - } - } - - - // Reading is done in blocks, but someone could read 1 byte from the buffer then write. - // At that point, the underlying stream's pointer is out of sync with this stream's position. - // All write functions should call this function to ensure that the buffered data is not lost. - private void FlushRead() { - - Contract.Assert(_writePos == 0, "BufferedStream: Write buffer must be empty in FlushRead!"); - - if (_readPos - _readLen != 0) - _stream.Seek(_readPos - _readLen, SeekOrigin.Current); - - _readPos = 0; - _readLen = 0; - } - - - private void ClearReadBufferBeforeWrite() { - - // This is called by write methods to clear the read buffer. - - Contract.Assert(_readPos <= _readLen, "_readPos <= _readLen [" + _readPos +" <= " + _readLen + "]"); - - // No READ data in the buffer: - if (_readPos == _readLen) { - - _readPos = _readLen = 0; - return; - } - - // Must have READ data. - Contract.Assert(_readPos < _readLen); - - // If the underlying stream cannot seek, FlushRead would end up throwing NotSupported. - // However, since the user did not call a method that is intuitively expected to seek, a better message is in order. - // Ideally, we would throw an InvalidOperation here, but for backward compat we have to stick with NotSupported. - if (!_stream.CanSeek) - throw new NotSupportedException(Environment.GetResourceString("NotSupported_CannotWriteToBufferedStreamIfReadBufferCannotBeFlushed")); - - FlushRead(); - } - - - private void FlushWrite() { - - Contract.Assert(_readPos == 0 && _readLen == 0, - "BufferedStream: Read buffer must be empty in FlushWrite!"); - Contract.Assert(_buffer != null && _bufferSize >= _writePos, - "BufferedStream: Write buffer must be allocated and write position must be in the bounds of the buffer in FlushWrite!"); - - _stream.Write(_buffer, 0, _writePos); - _writePos = 0; - _stream.Flush(); - } - - - private async Task FlushWriteAsync(CancellationToken cancellationToken) { - - Contract.Assert(_readPos == 0 && _readLen == 0, - "BufferedStream: Read buffer must be empty in FlushWrite!"); - Contract.Assert(_buffer != null && _bufferSize >= _writePos, - "BufferedStream: Write buffer must be allocated and write position must be in the bounds of the buffer in FlushWrite!"); - - await _stream.WriteAsync(_buffer, 0, _writePos, cancellationToken).ConfigureAwait(false); - _writePos = 0; - await _stream.FlushAsync(cancellationToken).ConfigureAwait(false); - } - - - private Int32 ReadFromBuffer(Byte[] array, Int32 offset, Int32 count) { - - Int32 readBytes = _readLen - _readPos; - Contract.Assert(readBytes >= 0); - - if (readBytes == 0) - return 0; - - Contract.Assert(readBytes > 0); - - if (readBytes > count) - readBytes = count; - - Buffer.InternalBlockCopy(_buffer, _readPos, array, offset, readBytes); - _readPos += readBytes; - - return readBytes; - } - - - private Int32 ReadFromBuffer(Byte[] array, Int32 offset, Int32 count, out Exception error) { - - try { - - error = null; - return ReadFromBuffer(array, offset, count); - - } catch (Exception ex) { - error = ex; - return 0; - } - } - - - public override int Read([In, Out] Byte[] array, Int32 offset, Int32 count) { - - if (array == null) - throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Buffer")); - if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (array.Length - offset < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - EnsureNotClosed(); - EnsureCanRead(); - - Int32 bytesFromBuffer = ReadFromBuffer(array, offset, count); - - // We may have read less than the number of bytes the user asked for, but that is part of the Stream contract. - - // Reading again for more data may cause us to block if we're using a device with no clear end of file, - // such as a serial port or pipe. If we blocked here and this code was used with redirected pipes for a - // process's standard output, this can lead to deadlocks involving two processes. - // BUT - this is a breaking change. - // So: If we could not read all bytes the user asked for from the buffer, we will try once from the underlying - // stream thus ensuring the same blocking behaviour as if the underlying stream was not wrapped in this BufferedStream. - if (bytesFromBuffer == count) - return bytesFromBuffer; - - Int32 alreadySatisfied = bytesFromBuffer; - if (bytesFromBuffer > 0) { - count -= bytesFromBuffer; - offset += bytesFromBuffer; - } - - // So the READ buffer is empty. - Contract.Assert(_readLen == _readPos); - _readPos = _readLen = 0; - - // If there was anything in the WRITE buffer, clear it. - if (_writePos > 0) - FlushWrite(); - - // If the requested read is larger than buffer size, avoid the buffer and still use a single read: - if (count >= _bufferSize) { - - return _stream.Read(array, offset, count) + alreadySatisfied; - } - - // Ok. We can fill the buffer: - EnsureBufferAllocated(); - _readLen = _stream.Read(_buffer, 0, _bufferSize); - - bytesFromBuffer = ReadFromBuffer(array, offset, count); - - // We may have read less than the number of bytes the user asked for, but that is part of the Stream contract. - // Reading again for more data may cause us to block if we're using a device with no clear end of stream, - // such as a serial port or pipe. If we blocked here & this code was used with redirected pipes for a process's - // standard output, this can lead to deadlocks involving two processes. Additionally, translating one read on the - // BufferedStream to more than one read on the underlying Stream may defeat the whole purpose of buffering of the - // underlying reads are significantly more expensive. - - return bytesFromBuffer + alreadySatisfied; - } - - - public override IAsyncResult BeginRead(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state) { - - if (buffer == null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); - if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (buffer.Length - offset < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - // Previous version incorrectly threw NotSupported instead of ObjectDisposed. We keep that behaviour for back-compat. - // EnsureNotClosed(); - if (_stream == null) __Error.ReadNotSupported(); - EnsureCanRead(); - - Int32 bytesFromBuffer = 0; - // Try to satisfy the request from the buffer synchronously. But still need a sem-lock in case that another - // Async IO Task accesses the buffer concurrently. If we fail to acquire the lock without waiting, make this - // an Async operation. - SemaphoreSlim sem = base.EnsureAsyncActiveSemaphoreInitialized(); - Task semaphoreLockTask = sem.WaitAsync(); - if (semaphoreLockTask.Status == TaskStatus.RanToCompletion) { - - bool completeSynchronously = true; - try { - - Exception error; - bytesFromBuffer = ReadFromBuffer(buffer, offset, count, out error); - - // If we satistied enough data from the buffer, we can complete synchronously. - // Reading again for more data may cause us to block if we're using a device with no clear end of file, - // such as a serial port or pipe. If we blocked here and this code was used with redirected pipes for a - // process's standard output, this can lead to deadlocks involving two processes. - // BUT - this is a breaking change. - // So: If we could not read all bytes the user asked for from the buffer, we will try once from the underlying - // stream thus ensuring the same blocking behaviour as if the underlying stream was not wrapped in this BufferedStream. - completeSynchronously = (bytesFromBuffer == count || error != null); - - if (completeSynchronously) { - - SynchronousAsyncResult asyncResult = (error == null) - ? new SynchronousAsyncResult(bytesFromBuffer, state) - : new SynchronousAsyncResult(error, state, isWrite: false); - if (callback != null) - callback(asyncResult); - - return asyncResult; - } - } finally { - if (completeSynchronously) // if this is FALSE, we will be entering ReadFromUnderlyingStreamAsync and releasing there. - sem.Release(); - } - } - - // Delegate to the async implementation. - return BeginReadFromUnderlyingStream(buffer, offset + bytesFromBuffer, count - bytesFromBuffer, callback, state, - bytesFromBuffer, semaphoreLockTask); - } - - - private IAsyncResult BeginReadFromUnderlyingStream(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state, - Int32 bytesAlreadySatisfied, Task semaphoreLockTask) { - - Task readOp = ReadFromUnderlyingStreamAsync(buffer, offset, count, CancellationToken.None, - bytesAlreadySatisfied, semaphoreLockTask, useApmPattern: true); - return TaskToApm.Begin(readOp, callback, state); - } - - - public override Int32 EndRead(IAsyncResult asyncResult) { - - if (asyncResult == null) - throw new ArgumentNullException("asyncResult"); - Contract.Ensures(Contract.Result() >= 0); - Contract.EndContractBlock(); - - var sAR = asyncResult as SynchronousAsyncResult; - if (sAR != null) - return SynchronousAsyncResult.EndRead(asyncResult); - return TaskToApm.End(asyncResult); - } - - - private Task LastSyncCompletedReadTask(Int32 val) { - - Task t = _lastSyncCompletedReadTask; - Contract.Assert(t == null || t.Status == TaskStatus.RanToCompletion); - - if (t != null && t.Result == val) - return t; - - t = Task.FromResult(val); - _lastSyncCompletedReadTask = t; - return t; - } - - - public override Task ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) { - - if (buffer == null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); - if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (buffer.Length - offset < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - // Fast path check for cancellation already requested - if (cancellationToken.IsCancellationRequested) - return Task.FromCanceled(cancellationToken); - - EnsureNotClosed(); - EnsureCanRead(); - - Int32 bytesFromBuffer = 0; - // Try to satisfy the request from the buffer synchronously. But still need a sem-lock in case that another - // Async IO Task accesses the buffer concurrently. If we fail to acquire the lock without waiting, make this - // an Async operation. - SemaphoreSlim sem = base.EnsureAsyncActiveSemaphoreInitialized(); - Task semaphoreLockTask = sem.WaitAsync(); - if (semaphoreLockTask.Status == TaskStatus.RanToCompletion) { - - bool completeSynchronously = true; - try { - Exception error; - bytesFromBuffer = ReadFromBuffer(buffer, offset, count, out error); - - // If we satistied enough data from the buffer, we can complete synchronously. - // Reading again for more data may cause us to block if we're using a device with no clear end of file, - // such as a serial port or pipe. If we blocked here and this code was used with redirected pipes for a - // process's standard output, this can lead to deadlocks involving two processes. - // BUT - this is a breaking change. - // So: If we could not read all bytes the user asked for from the buffer, we will try once from the underlying - // stream thus ensuring the same blocking behaviour as if the underlying stream was not wrapped in this BufferedStream. - completeSynchronously = (bytesFromBuffer == count || error != null); - - if (completeSynchronously) { - - return (error == null) - ? LastSyncCompletedReadTask(bytesFromBuffer) - : Task.FromException(error); - } - } finally { - if (completeSynchronously) // if this is FALSE, we will be entering ReadFromUnderlyingStreamAsync and releasing there. - sem.Release(); - } - } - - // Delegate to the async implementation. - return ReadFromUnderlyingStreamAsync(buffer, offset + bytesFromBuffer, count - bytesFromBuffer, cancellationToken, - bytesFromBuffer, semaphoreLockTask, useApmPattern: false); - } - - - /// BufferedStream should be as thin a wrapper as possible. We want that ReadAsync delegates to - /// ReadAsync of the underlying _stream and that BeginRead delegates to BeginRead of the underlying stream, - /// rather than calling the base Stream which implements the one in terms of the other. This allows BufferedStream - /// to affect the semantics of the stream it wraps as little as possible. At the same time, we want to share as - /// much code between the APM and the Async pattern implementations as possible. This method is called by both with - /// a corresponding useApmPattern value. Recall that Task implements IAsyncResult. - /// -2 if _bufferSize was set to 0 while waiting on the semaphore; otherwise num of bytes read. - private async Task ReadFromUnderlyingStreamAsync(Byte[] array, Int32 offset, Int32 count, - CancellationToken cancellationToken, - Int32 bytesAlreadySatisfied, - Task semaphoreLockTask, bool useApmPattern) { - - // Same conditions validated with exceptions in ReadAsync: - // (These should be Contract.Requires(..) but that method had some issues in async methods; using Assert(..) for now.) - Contract.Assert(array != null); - Contract.Assert(offset >= 0); - Contract.Assert(count >= 0); - Contract.Assert(array.Length - offset >= count); - Contract.Assert(_stream != null); - Contract.Assert(_stream.CanRead); - Contract.Assert(_bufferSize > 0); - Contract.Assert(semaphoreLockTask != null); - - // Employ async waiting based on the same synchronization used in BeginRead of the abstract Stream. - await semaphoreLockTask.ConfigureAwait(false); - try { - - // The buffer might have been changed by another async task while we were waiting on the semaphore. - // Check it now again. - Int32 bytesFromBuffer = ReadFromBuffer(array, offset, count); - if (bytesFromBuffer == count) - return bytesAlreadySatisfied + bytesFromBuffer; - - if (bytesFromBuffer > 0) { - count -= bytesFromBuffer; - offset += bytesFromBuffer; - bytesAlreadySatisfied += bytesFromBuffer; - } - - Contract.Assert(_readLen == _readPos); - _readPos = _readLen = 0; - - // If there was anything in the WRITE buffer, clear it. - if (_writePos > 0) - await FlushWriteAsync(cancellationToken).ConfigureAwait(false); // no Begin-End read version for Flush. Use Async. - - // If the requested read is larger than buffer size, avoid the buffer and still use a single read: - if (count >= _bufferSize) { - - if (useApmPattern) { - EnsureBeginEndAwaitableAllocated(); - _stream.BeginRead(array, offset, count, BeginEndAwaitableAdapter.Callback, _beginEndAwaitable); - return bytesAlreadySatisfied + _stream.EndRead(await _beginEndAwaitable); - } else { - return bytesAlreadySatisfied + await _stream.ReadAsync(array, offset, count, cancellationToken).ConfigureAwait(false); - } - } - - // Ok. We can fill the buffer: - EnsureBufferAllocated(); - if (useApmPattern) { - EnsureBeginEndAwaitableAllocated(); - _stream.BeginRead(_buffer, 0, _bufferSize, BeginEndAwaitableAdapter.Callback, _beginEndAwaitable); - _readLen = _stream.EndRead(await _beginEndAwaitable); - } else { - _readLen = await _stream.ReadAsync(_buffer, 0, _bufferSize, cancellationToken).ConfigureAwait(false); - } - - bytesFromBuffer = ReadFromBuffer(array, offset, count); - return bytesAlreadySatisfied + bytesFromBuffer; - - } finally { - SemaphoreSlim sem = base.EnsureAsyncActiveSemaphoreInitialized(); - sem.Release(); - } - } - - - public override Int32 ReadByte() { - - EnsureNotClosed(); - EnsureCanRead(); - - if (_readPos == _readLen) { - - if (_writePos > 0) - FlushWrite(); - - EnsureBufferAllocated(); - _readLen = _stream.Read(_buffer, 0, _bufferSize); - _readPos = 0; - } - - if (_readPos == _readLen) - return -1; - - Int32 b = _buffer[_readPos++]; - return b; - } - - - private void WriteToBuffer(Byte[] array, ref Int32 offset, ref Int32 count) { - - Int32 bytesToWrite = Math.Min(_bufferSize - _writePos, count); - - if (bytesToWrite <= 0) - return; - - EnsureBufferAllocated(); - Buffer.InternalBlockCopy(array, offset, _buffer, _writePos, bytesToWrite); - - _writePos += bytesToWrite; - count -= bytesToWrite; - offset += bytesToWrite; - } - - - private void WriteToBuffer(Byte[] array, ref Int32 offset, ref Int32 count, out Exception error) { - - try { - - error = null; - WriteToBuffer(array, ref offset, ref count); - - } catch (Exception ex) { - error = ex; - } - } - - - public override void Write(Byte[] array, Int32 offset, Int32 count) { - - if (array == null) - throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Buffer")); - if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (array.Length - offset < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - EnsureNotClosed(); - EnsureCanWrite(); - - if (_writePos == 0) - ClearReadBufferBeforeWrite(); - - #region Write algorithm comment - // We need to use the buffer, while avoiding unnecessary buffer usage / memory copies. - // We ASSUME that memory copies are much cheaper than writes to the underlying stream, so if an extra copy is - // guaranteed to reduce the number of writes, we prefer it. - // We pick a simple strategy that makes degenerate cases rare if our assumptions are right. - // - // For every write, we use a simple heuristic (below) to decide whether to use the buffer. - // The heuristic has the desirable property (*) that if the specified user data can fit into the currently available - // buffer space without filling it up completely, the heuristic will always tell us to use the buffer. It will also - // tell us to use the buffer in cases where the current write would fill the buffer, but the remaining data is small - // enough such that subsequent operations can use the buffer again. - // - // Algorithm: - // Determine whether or not to buffer according to the heuristic (below). - // If we decided to use the buffer: - // Copy as much user data as we can into the buffer. - // If we consumed all data: We are finished. - // Otherwise, write the buffer out. - // Copy the rest of user data into the now cleared buffer (no need to write out the buffer again as the heuristic - // will prevent it from being filled twice). - // If we decided not to use the buffer: - // Can the data already in the buffer and current user data be combines to a single write - // by allocating a "shadow" buffer of up to twice the size of _bufferSize (up to a limit to avoid LOH)? - // Yes, it can: - // Allocate a larger "shadow" buffer and ensure the buffered data is moved there. - // Copy user data to the shadow buffer. - // Write shadow buffer to the underlying stream in a single operation. - // No, it cannot (amount of data is still too large): - // Write out any data possibly in the buffer. - // Write out user data directly. - // - // Heuristic: - // If the subsequent write operation that follows the current write operation will result in a write to the - // underlying stream in case that we use the buffer in the current write, while it would not have if we avoided - // using the buffer in the current write (by writing current user data to the underlying stream directly), then we - // prefer to avoid using the buffer since the corresponding memory copy is wasted (it will not reduce the number - // of writes to the underlying stream, which is what we are optimising for). - // ASSUME that the next write will be for the same amount of bytes as the current write (most common case) and - // determine if it will cause a write to the underlying stream. If the next write is actually larger, our heuristic - // still yields the right behaviour, if the next write is actually smaller, we may making an unnecessary write to - // the underlying stream. However, this can only occur if the current write is larger than half the buffer size and - // we will recover after one iteration. - // We have: - // useBuffer = (_writePos + count + count < _bufferSize + _bufferSize) - // - // Example with _bufferSize = 20, _writePos = 6, count = 10: - // - // +---------------------------------------+---------------------------------------+ - // | current buffer | next iteration's "future" buffer | - // +---------------------------------------+---------------------------------------+ - // |0| | | | | | | | | |1| | | | | | | | | |2| | | | | | | | | |3| | | | | | | | | | - // |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9| - // +-----------+-------------------+-------------------+---------------------------+ - // | _writePos | current count | assumed next count|avail buff after next write| - // +-----------+-------------------+-------------------+---------------------------+ - // - // A nice property (*) of this heuristic is that it will always succeed if the user data completely fits into the - // available buffer, i.e. if count < (_bufferSize - _writePos). - #endregion Write algorithm comment - - Contract.Assert(_writePos < _bufferSize); - - Int32 totalUserBytes; - bool useBuffer; - checked { // We do not expect buffer sizes big enough for an overflow, but if it happens, lets fail early: - totalUserBytes = _writePos + count; - useBuffer = (totalUserBytes + count < (_bufferSize + _bufferSize)); - } - - if (useBuffer) { - - WriteToBuffer(array, ref offset, ref count); - - if (_writePos < _bufferSize) { - - Contract.Assert(count == 0); - return; - } - - Contract.Assert(count >= 0); - Contract.Assert(_writePos == _bufferSize); - Contract.Assert(_buffer != null); - - _stream.Write(_buffer, 0, _writePos); - _writePos = 0; - - WriteToBuffer(array, ref offset, ref count); - - Contract.Assert(count == 0); - Contract.Assert(_writePos < _bufferSize); - - } else { // if (!useBuffer) - - // Write out the buffer if necessary. - if (_writePos > 0) { - - Contract.Assert(_buffer != null); - Contract.Assert(totalUserBytes >= _bufferSize); - - // Try avoiding extra write to underlying stream by combining previously buffered data with current user data: - if (totalUserBytes <= (_bufferSize + _bufferSize) && totalUserBytes <= MaxShadowBufferSize) { - - EnsureShadowBufferAllocated(); - Buffer.InternalBlockCopy(array, offset, _buffer, _writePos, count); - _stream.Write(_buffer, 0, totalUserBytes); - _writePos = 0; - return; - } - - _stream.Write(_buffer, 0, _writePos); - _writePos = 0; - } - - // Write out user data. - _stream.Write(array, offset, count); - } - } - - - - - public override IAsyncResult BeginWrite(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state) { - - if (buffer == null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); - if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (buffer.Length - offset < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - // Previous version incorrectly threw NotSupported instead of ObjectDisposed. We keep that behaviour for back-compat. - // EnsureNotClosed(); - if (_stream == null) __Error.ReadNotSupported(); - EnsureCanWrite(); - - // Try to satisfy the request from the buffer synchronously. But still need a sem-lock in case that another - // Async IO Task accesses the buffer concurrently. If we fail to acquire the lock without waiting, make this - // an Async operation. - SemaphoreSlim sem = base.EnsureAsyncActiveSemaphoreInitialized(); - Task semaphoreLockTask = sem.WaitAsync(); - if (semaphoreLockTask.Status == TaskStatus.RanToCompletion) { - - bool completeSynchronously = true; - try { - if (_writePos == 0) - ClearReadBufferBeforeWrite(); - - // If the write completely fits into the buffer, we can complete synchronously. - Contract.Assert(_writePos < _bufferSize); - completeSynchronously = (count < _bufferSize - _writePos); - - if (completeSynchronously) { - - Exception error; - WriteToBuffer(buffer, ref offset, ref count, out error); - Contract.Assert(count == 0); - - SynchronousAsyncResult asyncResult = (error == null) - ? new SynchronousAsyncResult(state) - : new SynchronousAsyncResult(error, state, isWrite: true); - if (callback != null) - callback(asyncResult); - - return asyncResult; - } - } finally { - if (completeSynchronously) // if this is FALSE, we will be entering WriteToUnderlyingStreamAsync and releasing there. - sem.Release(); - } - } - - // Delegate to the async implementation. - return BeginWriteToUnderlyingStream(buffer, offset, count, callback, state, semaphoreLockTask); - } - - - private IAsyncResult BeginWriteToUnderlyingStream(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state, - Task semaphoreLockTask) { - - Task writeOp = WriteToUnderlyingStreamAsync(buffer, offset, count, CancellationToken.None, semaphoreLockTask, useApmPattern: true); - return TaskToApm.Begin(writeOp, callback, state); - } - - - public override void EndWrite(IAsyncResult asyncResult) { - - if (asyncResult == null) - throw new ArgumentNullException("asyncResult"); - Contract.EndContractBlock(); - - var sAR = asyncResult as SynchronousAsyncResult; - if (sAR != null) { - SynchronousAsyncResult.EndWrite(asyncResult); - return; - } - - TaskToApm.End(asyncResult); - } - - - public override Task WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) { - - if (buffer == null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); - if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (buffer.Length - offset < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - // Fast path check for cancellation already requested - if (cancellationToken.IsCancellationRequested) - return Task.FromCanceled(cancellationToken); - - EnsureNotClosed(); - EnsureCanWrite(); - - // Try to satisfy the request from the buffer synchronously. But still need a sem-lock in case that another - // Async IO Task accesses the buffer concurrently. If we fail to acquire the lock without waiting, make this - // an Async operation. - SemaphoreSlim sem = base.EnsureAsyncActiveSemaphoreInitialized(); - Task semaphoreLockTask = sem.WaitAsync(); - if (semaphoreLockTask.Status == TaskStatus.RanToCompletion) { - - bool completeSynchronously = true; - try { - - if (_writePos == 0) - ClearReadBufferBeforeWrite(); - - Contract.Assert(_writePos < _bufferSize); - - // If the write completely fits into the buffer, we can complete synchronously: - completeSynchronously = (count < _bufferSize - _writePos); - - if (completeSynchronously) { - - Exception error; - WriteToBuffer(buffer, ref offset, ref count, out error); - Contract.Assert(count == 0); - - return (error == null) - ? Task.CompletedTask - : Task.FromException(error); - } - } finally { - if (completeSynchronously) // if this is FALSE, we will be entering WriteToUnderlyingStreamAsync and releasing there. - sem.Release(); - } - } - - // Delegate to the async implementation. - return WriteToUnderlyingStreamAsync(buffer, offset, count, cancellationToken, semaphoreLockTask, useApmPattern: false); - } - - - /// BufferedStream should be as thin a wrapper as possible. We want that WriteAsync delegates to - /// WriteAsync of the underlying _stream and that BeginWrite delegates to BeginWrite of the underlying stream, - /// rather than calling the base Stream which implements the one in terms of the other. This allows BufferedStream - /// to affect the semantics of the stream it wraps as little as possible. At the same time, we want to share as - /// much code between the APM and the Async pattern implementations as possible. This method is called by both with - /// a corresponding useApmPattern value. Recall that Task implements IAsyncResult. - private async Task WriteToUnderlyingStreamAsync(Byte[] array, Int32 offset, Int32 count, - CancellationToken cancellationToken, - Task semaphoreLockTask, bool useApmPattern) { - - // (These should be Contract.Requires(..) but that method had some issues in async methods; using Assert(..) for now.) - Contract.Assert(array != null); - Contract.Assert(offset >= 0); - Contract.Assert(count >= 0); - Contract.Assert(array.Length - offset >= count); - Contract.Assert(_stream != null); - Contract.Assert(_stream.CanWrite); - Contract.Assert(_bufferSize > 0); - Contract.Assert(semaphoreLockTask != null); - - // See the LARGE COMMENT in Write(..) for the explanation of the write buffer algorithm. - - await semaphoreLockTask.ConfigureAwait(false); - try { - - // The buffer might have been changed by another async task while we were waiting on the semaphore. - // However, note that if we recalculate the sync completion condition to TRUE, then useBuffer will also be TRUE. - - if (_writePos == 0) - ClearReadBufferBeforeWrite(); - - Int32 totalUserBytes; - bool useBuffer; - checked { // We do not expect buffer sizes big enough for an overflow, but if it happens, lets fail early: - totalUserBytes = _writePos + count; - useBuffer = (totalUserBytes + count < (_bufferSize + _bufferSize)); - } - - if (useBuffer) { - - WriteToBuffer(array, ref offset, ref count); - - if (_writePos < _bufferSize) { - - Contract.Assert(count == 0); - return; - } - - Contract.Assert(count >= 0); - Contract.Assert(_writePos == _bufferSize); - Contract.Assert(_buffer != null); - - if (useApmPattern) { - EnsureBeginEndAwaitableAllocated(); - _stream.BeginWrite(_buffer, 0, _writePos, BeginEndAwaitableAdapter.Callback, _beginEndAwaitable); - _stream.EndWrite(await _beginEndAwaitable); - } else { - await _stream.WriteAsync(_buffer, 0, _writePos, cancellationToken).ConfigureAwait(false); - } - _writePos = 0; - - WriteToBuffer(array, ref offset, ref count); - - Contract.Assert(count == 0); - Contract.Assert(_writePos < _bufferSize); - - } else { // if (!useBuffer) - - // Write out the buffer if necessary. - if (_writePos > 0) { - - Contract.Assert(_buffer != null); - Contract.Assert(totalUserBytes >= _bufferSize); - - // Try avoiding extra write to underlying stream by combining previously buffered data with current user data: - if (totalUserBytes <= (_bufferSize + _bufferSize) && totalUserBytes <= MaxShadowBufferSize) { - - EnsureShadowBufferAllocated(); - Buffer.InternalBlockCopy(array, offset, _buffer, _writePos, count); - if (useApmPattern) { - EnsureBeginEndAwaitableAllocated(); - _stream.BeginWrite(_buffer, 0, totalUserBytes, BeginEndAwaitableAdapter.Callback, _beginEndAwaitable); - _stream.EndWrite(await _beginEndAwaitable); - } else { - await _stream.WriteAsync(_buffer, 0, totalUserBytes, cancellationToken).ConfigureAwait(false); - } - _writePos = 0; - return; - } - - if (useApmPattern) { - EnsureBeginEndAwaitableAllocated(); - _stream.BeginWrite(_buffer, 0, _writePos, BeginEndAwaitableAdapter.Callback, _beginEndAwaitable); - _stream.EndWrite(await _beginEndAwaitable); - } else { - await _stream.WriteAsync(_buffer, 0, _writePos, cancellationToken).ConfigureAwait(false); - } - _writePos = 0; - } - - // Write out user data. - if (useApmPattern) { - EnsureBeginEndAwaitableAllocated(); - _stream.BeginWrite(array, offset, count, BeginEndAwaitableAdapter.Callback, _beginEndAwaitable); - _stream.EndWrite(await _beginEndAwaitable); - } else { - await _stream.WriteAsync(array, offset, count, cancellationToken).ConfigureAwait(false); - } - } - } finally { - SemaphoreSlim sem = base.EnsureAsyncActiveSemaphoreInitialized(); - sem.Release(); - } - } - - - public override void WriteByte(Byte value) { - - EnsureNotClosed(); - - if (_writePos == 0) { - - EnsureCanWrite(); - ClearReadBufferBeforeWrite(); - EnsureBufferAllocated(); - } - - // We should not be flushing here, but only writing to the underlying stream, but previous version flushed, so we keep this. - if (_writePos >= _bufferSize - 1) - FlushWrite(); - - _buffer[_writePos++] = value; - - Contract.Assert(_writePos < _bufferSize); - } - - - public override Int64 Seek(Int64 offset, SeekOrigin origin) { - - EnsureNotClosed(); - EnsureCanSeek(); - - // If we have bytes in the WRITE buffer, flush them out, seek and be done. - if (_writePos > 0) { - - // We should be only writing the buffer and not flushing, - // but the previous version did flush and we stick to it for back-compat reasons. - FlushWrite(); - return _stream.Seek(offset, origin); - } - - // The buffer is either empty or we have a buffered READ. - - if (_readLen - _readPos > 0 && origin == SeekOrigin.Current) { - - // If we have bytes in the READ buffer, adjust the seek offset to account for the resulting difference - // between this stream's position and the underlying stream's position. - offset -= (_readLen - _readPos); - } - - Int64 oldPos = Position; - Contract.Assert(oldPos == _stream.Position + (_readPos - _readLen)); - - Int64 newPos = _stream.Seek(offset, origin); - - // If the seek destination is still within the data currently in the buffer, we want to keep the buffer data and continue using it. - // Otherwise we will throw away the buffer. This can only happen on READ, as we flushed WRITE data above. - - // The offset of the new/updated seek pointer within _buffer: - _readPos = (Int32) (newPos - (oldPos - _readPos)); - - // If the offset of the updated seek pointer in the buffer is still legal, then we can keep using the buffer: - if (0 <= _readPos && _readPos < _readLen) { - - // Adjust the seek pointer of the underlying stream to reflect the amount of useful bytes in the read buffer: - _stream.Seek(_readLen - _readPos, SeekOrigin.Current); - - } else { // The offset of the updated seek pointer is not a legal offset. Loose the buffer. - - _readPos = _readLen = 0; - } - - Contract.Assert(newPos == Position, "newPos (=" + newPos + ") == Position (=" + Position + ")"); - return newPos; - } - - - public override void SetLength(Int64 value) { - - if (value < 0) - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NegFileSize")); - Contract.EndContractBlock(); - - EnsureNotClosed(); - EnsureCanSeek(); - EnsureCanWrite(); - - Flush(); - _stream.SetLength(value); - } - -} // class BufferedStream -} // namespace diff --git a/src/mscorlib/src/System/IO/Directory.cs b/src/mscorlib/src/System/IO/Directory.cs index be74538..d6b6822 100644 --- a/src/mscorlib/src/System/IO/Directory.cs +++ b/src/mscorlib/src/System/IO/Directory.cs @@ -15,168 +15,70 @@ ** ===========================================================*/ -using System; -using System.Collections; using System.Collections.Generic; using System.Security; using System.Security.Permissions; using Microsoft.Win32; using Microsoft.Win32.SafeHandles; -using System.Text; using System.Runtime.InteropServices; -using System.Globalization; -using System.Runtime.Versioning; +using System.Diagnostics; using System.Diagnostics.Contracts; -using System.Threading; -#if FEATURE_MACL -using System.Security.AccessControl; -#endif - -namespace System.IO { +namespace System.IO +{ [ComVisible(true)] public static class Directory { public static DirectoryInfo GetParent(String path) { if (path==null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (path.Length==0) - throw new ArgumentException(Environment.GetResourceString("Argument_PathEmpty"), "path"); + throw new ArgumentException(Environment.GetResourceString("Argument_PathEmpty"), nameof(path)); Contract.EndContractBlock(); - String fullPath = Path.GetFullPathInternal(path); - - String s = Path.GetDirectoryName(fullPath); + string fullPath = Path.GetFullPath(path); + + string s = Path.GetDirectoryName(fullPath); if (s==null) return null; return new DirectoryInfo(s); } - [System.Security.SecuritySafeCritical] public static DirectoryInfo CreateDirectory(String path) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (path.Length == 0) throw new ArgumentException(Environment.GetResourceString("Argument_PathEmpty")); Contract.EndContractBlock(); - return InternalCreateDirectoryHelper(path, true); + return InternalCreateDirectoryHelper(path); } - [System.Security.SecurityCritical] - internal static DirectoryInfo UnsafeCreateDirectory(String path) - { - if (path == null) - throw new ArgumentNullException("path"); - if (path.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_PathEmpty")); - Contract.EndContractBlock(); - - return InternalCreateDirectoryHelper(path, false); - } - - [System.Security.SecurityCritical] - internal static DirectoryInfo InternalCreateDirectoryHelper(String path, bool checkHost) + internal static DirectoryInfo InternalCreateDirectoryHelper(String path) { Contract.Requires(path != null); Contract.Requires(path.Length != 0); - String fullPath = Path.GetFullPathInternal(path); - - // You need read access to the directory to be returned back and write access to all the directories - // that you need to create. If we fail any security checks we will not create any directories at all. - // We attempt to create directories only after all the security checks have passed. This is avoid doing - // a demand at every level. - String demandDir = GetDemandDir(fullPath, true); - -#if FEATURE_CORECLR - if (checkHost) - { - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, path, demandDir); - state.EnsureState(); // do the check on the AppDomainManager to make sure this is allowed - } -#else - FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, demandDir, false, false); -#endif - - InternalCreateDirectory(fullPath, path, null, checkHost); - - return new DirectoryInfo(fullPath, false); - } - -#if FEATURE_MACL - [System.Security.SecuritySafeCritical] // auto-generated - public static DirectoryInfo CreateDirectory(String path, DirectorySecurity directorySecurity) { - if (path==null) - throw new ArgumentNullException("path"); - if (path.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_PathEmpty")); - Contract.EndContractBlock(); - - String fullPath = Path.GetFullPathInternal(path); + String fullPath = Path.GetFullPath(path); - // You need read access to the directory to be returned back and write access to all the directories - // that you need to create. If we fail any security checks we will not create any directories at all. - // We attempt to create directories only after all the security checks have passed. This is avoid doing - // a demand at every level. - String demandDir = GetDemandDir(fullPath, true); - FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, demandDir, false, false ); + InternalCreateDirectory(fullPath, path, null); - InternalCreateDirectory(fullPath, path, directorySecurity); - return new DirectoryInfo(fullPath, false); } -#endif // FEATURE_MACL - // Input to this method should already be fullpath. This method will ensure that we append - // the trailing slash only when appropriate and when thisDirOnly is specified append a "." - // at the end of the path to indicate that the demand is only for the fullpath and not - // everything underneath it. - internal static String GetDemandDir(string fullPath, bool thisDirOnly) + internal unsafe static void InternalCreateDirectory(String fullPath, String path, Object dirSecurityObj) { - String demandPath; - - if (thisDirOnly) { - if (fullPath.EndsWith( Path.DirectorySeparatorChar ) - || fullPath.EndsWith( Path.AltDirectorySeparatorChar ) ) - demandPath = fullPath + "."; - else - demandPath = fullPath + Path.DirectorySeparatorCharAsString + "."; - } - else { - if (!(fullPath.EndsWith( Path.DirectorySeparatorChar ) - || fullPath.EndsWith( Path.AltDirectorySeparatorChar )) ) - demandPath = fullPath + Path.DirectorySeparatorCharAsString; - else - demandPath = fullPath; - } - return demandPath; - } - - internal static void InternalCreateDirectory(String fullPath, String path, Object dirSecurityObj) - { - InternalCreateDirectory(fullPath, path, dirSecurityObj, false); - } - - - [System.Security.SecuritySafeCritical] - internal unsafe static void InternalCreateDirectory(String fullPath, String path, Object dirSecurityObj, bool checkHost) - { -#if FEATURE_MACL - DirectorySecurity dirSecurity = (DirectorySecurity)dirSecurityObj; -#endif // FEATURE_MACL - int length = fullPath.Length; // We need to trim the trailing slash or the code will try to create 2 directories of the same name. - if (length >= 2 && Path.IsDirectorySeparator(fullPath[length - 1])) + if (length >= 2 && PathInternal.IsDirectorySeparator(fullPath[length - 1])) length--; - int lengthRoot = Path.GetRootLength(fullPath); + int lengthRoot = PathInternal.GetRootLength(fullPath); // For UNC paths that are only // or /// - if (length == 2 && Path.IsDirectorySeparator(fullPath[1])) + if (length == 2 && PathInternal.IsDirectorySeparator(fullPath[1])) throw new IOException(Environment.GetResourceString("IO.IO_CannotCreateDirectory", path)); // We can save a bunch of work if the directory we want to create already exists. This also @@ -215,56 +117,9 @@ namespace System.IO { int count = stackDir.Count; - if (stackDir.Count != 0 -#if FEATURE_CAS_POLICY - // All demands in full trust domains are no-ops, so skip - // - // The full path went through validity checks by being passed through FileIOPermissions already. - // As a sub string of the full path can't fail the checks if the full path passes. - && !CodeAccessSecurityEngine.QuickCheckForAllDemands() -#endif - ) - { - String[] securityList = new String[stackDir.Count]; - stackDir.CopyTo(securityList, 0); - for (int j = 0 ; j < securityList.Length; j++) - securityList[j] += "\\."; // leaf will never have a slash at the end - - // Security check for all directories not present only. -#if FEATURE_MACL - AccessControlActions control = (dirSecurity == null) ? AccessControlActions.None : AccessControlActions.Change; - FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, control, securityList, false, false); -#else -#if FEATURE_CORECLR - if (checkHost) - { - foreach (String demandPath in securityList) - { - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Write, String.Empty, demandPath); - state.EnsureState(); - } - } -#else - FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, securityList, false, false); -#endif -#endif //FEATURE_MACL - } - // If we were passed a DirectorySecurity, convert it to a security // descriptor and set it in he call to CreateDirectory. Win32Native.SECURITY_ATTRIBUTES secAttrs = null; -#if FEATURE_MACL - if (dirSecurity != null) { - secAttrs = new Win32Native.SECURITY_ATTRIBUTES(); - secAttrs.nLength = (int)Marshal.SizeOf(secAttrs); - - // For ACL's, get the security descriptor from the FileSecurity. - byte[] sd = dirSecurity.GetSecurityDescriptorBinaryForm(); - byte * bytesOnStack = stackalloc byte[sd.Length]; - Buffer.Memcpy(bytesOnStack, 0, sd, 0, sd.Length); - secAttrs.pSecurityDescriptor = bytesOnStack; - } -#endif bool r = true; int firstError = 0; @@ -290,22 +145,10 @@ namespace System.IO { firstError = currentError; else { // If there's a file in this directory's place, or if we have ERROR_ACCESS_DENIED when checking if the directory already exists throw. - if (File.InternalExists(name) || (!InternalExists(name, out currentError) && currentError == Win32Native.ERROR_ACCESS_DENIED)) { + if (File.InternalExists(name) || (!InternalExists(name, out currentError) && currentError == Win32Native.ERROR_ACCESS_DENIED)) + { firstError = currentError; - // Give the user a nice error message, but don't leak path information. - try { -#if FEATURE_CORECLR - if (checkHost) - { - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, GetDemandDir(name, true)); - state.EnsureState(); - } -#else - FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, GetDemandDir(name, true)); -#endif // FEATURE_CORECLR - errorString = name; - } - catch(SecurityException) {} + errorString = name; } } } @@ -335,20 +178,12 @@ namespace System.IO { // Your application must have Read permission to the directory's // contents. // - [System.Security.SecuritySafeCritical] // auto-generated public static bool Exists(String path) { - return InternalExistsHelper(path, true); - } - - [System.Security.SecurityCritical] - internal static bool UnsafeExists(String path) - { - return InternalExistsHelper(path, false); + return InternalExistsHelper(path); } - [System.Security.SecurityCritical] - internal static bool InternalExistsHelper(String path, bool checkHost) { + internal static bool InternalExistsHelper(String path) { try { if (path == null) @@ -356,23 +191,7 @@ namespace System.IO { if (path.Length == 0) return false; - // Get fully qualified file name ending in \* for security check - - String fullPath = Path.GetFullPathInternal(path); - String demandPath = GetDemandDir(fullPath, true); - -#if FEATURE_CORECLR - if (checkHost) - { - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, path, demandPath); - state.EnsureState(); - } -#else - FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, demandPath, false, false); -#endif - - - return InternalExists(fullPath); + return InternalExists(Path.GetFullPath(path)); } catch (ArgumentException) { } catch (NotSupportedException) { } // Security can throw this on ":" @@ -380,14 +199,13 @@ namespace System.IO { catch (IOException) { } catch (UnauthorizedAccessException) { - Contract.Assert(false, "Ignore this assert and send a repro to Microsoft. This assert was tracking purposes only."); + Debug.Assert(false, "Ignore this assert and send a repro to Microsoft. This assert was tracking purposes only."); } return false; } // Determine whether path describes an existing directory // on disk, avoiding security checks. - [System.Security.SecurityCritical] // auto-generated internal static bool InternalExists(String path) { int lastError = Win32Native.ERROR_SUCCESS; return InternalExists(path, out lastError); @@ -395,7 +213,6 @@ namespace System.IO { // Determine whether path describes an existing directory // on disk, avoiding security checks. - [System.Security.SecurityCritical] // auto-generated internal static bool InternalExists(String path, out int lastError) { Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA(); lastError = File.FillAttributeInfo(path, ref data, false, true); @@ -404,25 +221,6 @@ namespace System.IO { && ((data.fileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY) != 0); } - public static void SetCreationTime(String path,DateTime creationTime) - { - SetCreationTimeUtc(path, creationTime.ToUniversalTime()); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public unsafe static void SetCreationTimeUtc(String path,DateTime creationTimeUtc) - { - using (SafeFileHandle handle = Directory.OpenHandle(path)) { - Win32Native.FILE_TIME fileTime = new Win32Native.FILE_TIME(creationTimeUtc.ToFileTimeUtc()); - bool r = Win32Native.SetFileTime(handle, &fileTime, null, null); - if (!r) - { - int errorCode = Marshal.GetLastWin32Error(); - __Error.WinIOError(errorCode, path); - } - } - } - public static DateTime GetCreationTime(String path) { return File.GetCreationTime(path); @@ -433,25 +231,6 @@ namespace System.IO { return File.GetCreationTimeUtc(path); } - public static void SetLastWriteTime(String path,DateTime lastWriteTime) - { - SetLastWriteTimeUtc(path, lastWriteTime.ToUniversalTime()); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public unsafe static void SetLastWriteTimeUtc(String path,DateTime lastWriteTimeUtc) - { - using (SafeFileHandle handle = Directory.OpenHandle(path)) { - Win32Native.FILE_TIME fileTime = new Win32Native.FILE_TIME(lastWriteTimeUtc.ToFileTimeUtc()); - bool r = Win32Native.SetFileTime(handle, null, null, &fileTime); - if (!r) - { - int errorCode = Marshal.GetLastWin32Error(); - __Error.WinIOError(errorCode, path); - } - } - } - public static DateTime GetLastWriteTime(String path) { return File.GetLastWriteTime(path); @@ -462,25 +241,6 @@ namespace System.IO { return File.GetLastWriteTimeUtc(path); } - public static void SetLastAccessTime(String path,DateTime lastAccessTime) - { - SetLastAccessTimeUtc(path, lastAccessTime.ToUniversalTime()); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public unsafe static void SetLastAccessTimeUtc(String path,DateTime lastAccessTimeUtc) - { - using (SafeFileHandle handle = Directory.OpenHandle(path)) { - Win32Native.FILE_TIME fileTime = new Win32Native.FILE_TIME(lastAccessTimeUtc.ToFileTimeUtc()); - bool r = Win32Native.SetFileTime(handle, null, &fileTime, null); - if (!r) - { - int errorCode = Marshal.GetLastWin32Error(); - __Error.WinIOError(errorCode, path); - } - } - } - public static DateTime GetLastAccessTime(String path) { return File.GetLastAccessTime(path); @@ -489,36 +249,13 @@ namespace System.IO { public static DateTime GetLastAccessTimeUtc(String path) { return File.GetLastAccessTimeUtc(path); - } - -#if FEATURE_MACL - public static DirectorySecurity GetAccessControl(String path) - { - return new DirectorySecurity(path, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group); } - public static DirectorySecurity GetAccessControl(String path, AccessControlSections includeSections) - { - return new DirectorySecurity(path, includeSections); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public static void SetAccessControl(String path, DirectorySecurity directorySecurity) - { - if (directorySecurity == null) - throw new ArgumentNullException("directorySecurity"); - Contract.EndContractBlock(); - - String fullPath = Path.GetFullPathInternal(path); - directorySecurity.Persist(fullPath); - } -#endif - // Returns an array of filenames in the DirectoryInfo specified by path public static String[] GetFiles(String path) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -530,9 +267,9 @@ namespace System.IO { public static String[] GetFiles(String path, String searchPattern) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -544,11 +281,11 @@ namespace System.IO { public static String[] GetFiles(String path, String searchPattern, SearchOption searchOption) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories)) - throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum")); + throw new ArgumentOutOfRangeException(nameof(searchOption), Environment.GetResourceString("ArgumentOutOfRange_Enum")); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -566,7 +303,6 @@ namespace System.IO { return InternalGetFileDirectoryNames(path, path, searchPattern, true, false, searchOption, true); } - [System.Security.SecurityCritical] internal static String[] UnsafeGetFiles(String path, String searchPattern, SearchOption searchOption) { Contract.Requires(path != null); @@ -580,7 +316,7 @@ namespace System.IO { public static String[] GetDirectories(String path) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -592,9 +328,9 @@ namespace System.IO { public static String[] GetDirectories(String path, String searchPattern) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -606,11 +342,11 @@ namespace System.IO { public static String[] GetDirectories(String path, String searchPattern, SearchOption searchOption) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories)) - throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum")); + throw new ArgumentOutOfRangeException(nameof(searchOption), Environment.GetResourceString("ArgumentOutOfRange_Enum")); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -629,7 +365,6 @@ namespace System.IO { return InternalGetFileDirectoryNames(path, path, searchPattern, false, true, searchOption, true); } - [System.Security.SecurityCritical] internal static String[] UnsafeGetDirectories(String path, String searchPattern, SearchOption searchOption) { Contract.Requires(path != null); @@ -644,7 +379,7 @@ namespace System.IO { public static String[] GetFileSystemEntries(String path) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -656,9 +391,9 @@ namespace System.IO { public static String[] GetFileSystemEntries(String path, String searchPattern) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -670,11 +405,11 @@ namespace System.IO { public static String[] GetFileSystemEntries(String path, String searchPattern, SearchOption searchOption) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories)) - throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum")); + throw new ArgumentOutOfRangeException(nameof(searchOption), Environment.GetResourceString("ArgumentOutOfRange_Enum")); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -690,7 +425,6 @@ namespace System.IO { return InternalGetFileDirectoryNames(path, path, searchPattern, true, true, searchOption, true); } - // Private class that holds search data that is passed around // in the heap based stack recursion internal sealed class SearchData @@ -734,7 +468,7 @@ namespace System.IO { public static IEnumerable EnumerateDirectories(String path) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); Contract.EndContractBlock(); return InternalEnumerateDirectories(path, "*", SearchOption.TopDirectoryOnly); @@ -743,9 +477,9 @@ namespace System.IO { public static IEnumerable EnumerateDirectories(String path, String searchPattern) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); Contract.EndContractBlock(); return InternalEnumerateDirectories(path, searchPattern, SearchOption.TopDirectoryOnly); @@ -754,11 +488,11 @@ namespace System.IO { public static IEnumerable EnumerateDirectories(String path, String searchPattern, SearchOption searchOption) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories)) - throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum")); + throw new ArgumentOutOfRangeException(nameof(searchOption), Environment.GetResourceString("ArgumentOutOfRange_Enum")); Contract.EndContractBlock(); return InternalEnumerateDirectories(path, searchPattern, searchOption); @@ -776,7 +510,7 @@ namespace System.IO { public static IEnumerable EnumerateFiles(String path) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); Contract.Ensures(Contract.Result>() != null); Contract.EndContractBlock(); @@ -786,9 +520,9 @@ namespace System.IO { public static IEnumerable EnumerateFiles(String path, String searchPattern) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); Contract.Ensures(Contract.Result>() != null); Contract.EndContractBlock(); @@ -798,11 +532,11 @@ namespace System.IO { public static IEnumerable EnumerateFiles(String path, String searchPattern, SearchOption searchOption) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories)) - throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum")); + throw new ArgumentOutOfRangeException(nameof(searchOption), Environment.GetResourceString("ArgumentOutOfRange_Enum")); Contract.Ensures(Contract.Result>() != null); Contract.EndContractBlock(); @@ -822,7 +556,7 @@ namespace System.IO { public static IEnumerable EnumerateFileSystemEntries(String path) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); Contract.Ensures(Contract.Result>() != null); Contract.EndContractBlock(); @@ -832,9 +566,9 @@ namespace System.IO { public static IEnumerable EnumerateFileSystemEntries(String path, String searchPattern) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); Contract.Ensures(Contract.Result>() != null); Contract.EndContractBlock(); @@ -844,11 +578,11 @@ namespace System.IO { public static IEnumerable EnumerateFileSystemEntries(String path, String searchPattern, SearchOption searchOption) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories)) - throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum")); + throw new ArgumentOutOfRangeException(nameof(searchOption), Environment.GetResourceString("ArgumentOutOfRange_Enum")); Contract.Ensures(Contract.Result>() != null); Contract.EndContractBlock(); @@ -882,7 +616,6 @@ namespace System.IO { // // Your application must have System Info permission. // - [System.Security.SecuritySafeCritical] // auto-generated public static String[] GetLogicalDrives() { Contract.Ensures(Contract.Result() != null); @@ -914,29 +647,20 @@ namespace System.IO { return result; } - [System.Security.SecuritySafeCritical] public static String GetDirectoryRoot(String path) { if (path==null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); Contract.EndContractBlock(); - - String fullPath = Path.GetFullPathInternal(path); - String root = fullPath.Substring(0, Path.GetRootLength(fullPath)); - String demandPath = GetDemandDir(root, true); - -#if FEATURE_CORECLR - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, path, demandPath); - state.EnsureState(); -#else - FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, demandPath, false, false); -#endif - + + string fullPath = Path.GetFullPath(path); + string root = fullPath.Substring(0, PathInternal.GetRootLength(fullPath)); + return root; } internal static String InternalGetDirectoryRoot(String path) { if (path == null) return null; - return path.Substring(0, Path.GetRootLength(path)); + return path.Substring(0, PathInternal.GetRootLength(path)); } /*===============================CurrentDirectory=============================== @@ -946,77 +670,10 @@ namespace System.IO { **Arguments: The current DirectoryInfo to which to switch to the setter. **Exceptions: ==============================================================================*/ - [System.Security.SecuritySafeCritical] public static String GetCurrentDirectory() { - return InternalGetCurrentDirectory(true); - } - - [System.Security.SecurityCritical] - internal static String UnsafeGetCurrentDirectory() - { - return InternalGetCurrentDirectory(false); - } - - [System.Security.SecuritySafeCritical] - private static string InternalGetCurrentDirectory(bool checkHost) - { - string currentDirectory = ( -#if FEATURE_PATHCOMPAT - AppContextSwitches.UseLegacyPathHandling ? LegacyGetCurrentDirectory() : -#endif - NewGetCurrentDirectory()); - - string demandPath = GetDemandDir(currentDirectory, true); - -#if FEATURE_CORECLR - if (checkHost) - { - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandPath); - state.EnsureState(); - } -#else - FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, demandPath, false, false); -#endif - return currentDirectory; - } - -#if FEATURE_PATHCOMPAT - [System.Security.SecurityCritical] - private static String LegacyGetCurrentDirectory() - { - StringBuilder sb = StringBuilderCache.Acquire(Path.MaxPath + 1); - if (Win32Native.GetCurrentDirectory(sb.Capacity, sb) == 0) - __Error.WinIOError(); - String currentDirectory = sb.ToString(); - // Note that if we have somehow put our command prompt into short - // file name mode (ie, by running edlin or a DOS grep, etc), then - // this will return a short file name. - if (currentDirectory.IndexOf('~') >= 0) { - int r = Win32Native.GetLongPathName(currentDirectory, sb, sb.Capacity); - if (r == 0 || r >= Path.MaxPath) { - int errorCode = Marshal.GetLastWin32Error(); - if (r >= Path.MaxPath) - errorCode = Win32Native.ERROR_FILENAME_EXCED_RANGE; - if (errorCode != Win32Native.ERROR_FILE_NOT_FOUND && - errorCode != Win32Native.ERROR_PATH_NOT_FOUND && - errorCode != Win32Native.ERROR_INVALID_FUNCTION && // by design - enough said. - errorCode != Win32Native.ERROR_ACCESS_DENIED) - __Error.WinIOError(errorCode, String.Empty); - } - currentDirectory = sb.ToString(); - } - StringBuilderCache.Release(sb); - String demandPath = GetDemandDir(currentDirectory, true); - - return currentDirectory; - } -#endif // FEATURE_PATHCOMPAT - - [System.Security.SecurityCritical] - private static string NewGetCurrentDirectory() - { - using (StringBuffer buffer = new StringBuffer(PathInternal.MaxShortPath)) + // Start with a buffer the size of MAX_PATH + using (StringBuffer buffer = new StringBuffer(260)) { uint result = 0; while ((result = Win32Native.GetCurrentDirectoryW(buffer.CharCapacity, buffer.GetHandle())) > buffer.CharCapacity) @@ -1033,35 +690,23 @@ namespace System.IO { #if !PLATFORM_UNIX if (buffer.Contains('~')) - return LongPathHelper.GetLongPathName(buffer); + return Path.GetFullPath(buffer.ToString()); #endif return buffer.ToString(); } } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif public static void SetCurrentDirectory(String path) { if (path==null) throw new ArgumentNullException("value"); if (path.Length==0) throw new ArgumentException(Environment.GetResourceString("Argument_PathEmpty")); - Contract.EndContractBlock(); if (path.Length >= Path.MaxPath) throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - - // This will have some large effects on the rest of the runtime - // and other appdomains in this process. Demand unmanaged code. -#pragma warning disable 618 - new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); -#pragma warning restore 618 - String fulldestDirName = Path.GetFullPathInternal(path); + String fulldestDirName = Path.GetFullPath(path); if (!Win32Native.SetCurrentDirectory(fulldestDirName)) { // If path doesn't exist, this sets last error to 2 (File @@ -1074,52 +719,19 @@ namespace System.IO { } } - [System.Security.SecuritySafeCritical] - public static void Move(String sourceDirName,String destDirName) { - InternalMove(sourceDirName, destDirName, true); - } - - [System.Security.SecurityCritical] - internal static void UnsafeMove(String sourceDirName,String destDirName) { - InternalMove(sourceDirName, destDirName, false); - } - - [System.Security.SecurityCritical] - private static void InternalMove(String sourceDirName,String destDirName,bool checkHost) { + public static void Move(String sourceDirName,String destDirName) + { if (sourceDirName==null) - throw new ArgumentNullException("sourceDirName"); + throw new ArgumentNullException(nameof(sourceDirName)); if (sourceDirName.Length==0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "sourceDirName"); - + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), nameof(sourceDirName)); if (destDirName==null) - throw new ArgumentNullException("destDirName"); + throw new ArgumentNullException(nameof(destDirName)); if (destDirName.Length==0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destDirName"); - Contract.EndContractBlock(); - - String fullsourceDirName = Path.GetFullPathInternal(sourceDirName); - String sourcePath = GetDemandDir(fullsourceDirName, false); - - if (PathInternal.IsDirectoryTooLong(sourcePath)) - throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - - String fulldestDirName = Path.GetFullPathInternal(destDirName); - String destPath = GetDemandDir(fulldestDirName, false); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), nameof(destDirName)); - if (PathInternal.IsDirectoryTooLong(destPath)) - throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - -#if FEATURE_CORECLR - if (checkHost) { - FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Write | FileSecurityStateAccess.Read, sourceDirName, sourcePath); - FileSecurityState destState = new FileSecurityState(FileSecurityStateAccess.Write, destDirName, destPath); - sourceState.EnsureState(); - destState.EnsureState(); - } -#else - FileIOPermission.QuickDemand(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, sourcePath, false, false); - FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, destPath, false, false); -#endif + String sourcePath = Path.GetFullPath(sourceDirName); + String destPath = Path.GetFullPath(destDirName); if (String.Compare(sourcePath, destPath, StringComparison.OrdinalIgnoreCase) == 0) throw new IOException(Environment.GetResourceString("IO.IO_SourceDestMustBeDifferent")); @@ -1135,7 +747,7 @@ namespace System.IO { if (hr == Win32Native.ERROR_FILE_NOT_FOUND) // Source dir not found { hr = Win32Native.ERROR_PATH_NOT_FOUND; - __Error.WinIOError(hr, fullsourceDirName); + __Error.WinIOError(hr, sourcePath); } // This check was originally put in for Win9x (unfortunately without special casing it to be for Win9x only). We can't change the NT codepath now for backcomp reasons. if (hr == Win32Native.ERROR_ACCESS_DENIED) // WinNT throws IOException. This check is for Win9x. We can't change it for backcomp. @@ -1144,49 +756,22 @@ namespace System.IO { } } - [System.Security.SecuritySafeCritical] public static void Delete(String path) { - String fullPath = Path.GetFullPathInternal(path); - Delete(fullPath, path, false, true); + String fullPath = Path.GetFullPath(path); + Delete(fullPath, path, false); } - [System.Security.SecuritySafeCritical] public static void Delete(String path, bool recursive) { - String fullPath = Path.GetFullPathInternal(path); - Delete(fullPath, path, recursive, true); + String fullPath = Path.GetFullPath(path); + Delete(fullPath, path, recursive); } - [System.Security.SecurityCritical] - internal static void UnsafeDelete(String path, bool recursive) - { - String fullPath = Path.GetFullPathInternal(path); - Delete(fullPath, path, recursive, false); - } - - // Called from DirectoryInfo as well. FullPath is fully qualified, + // Called from DirectoryInfo as well. FullPath is fully qualified, // while the user path is used for feedback in exceptions. - [System.Security.SecurityCritical] // auto-generated - internal static void Delete(String fullPath, String userPath, bool recursive, bool checkHost) + internal static void Delete(String fullPath, String userPath, bool recursive) { - String demandPath; - - // If not recursive, do permission check only on this directory - // else check for the whole directory structure rooted below - demandPath = GetDemandDir(fullPath, !recursive); - -#if FEATURE_CORECLR - if (checkHost) - { - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Write, userPath, demandPath); - state.EnsureState(); - } -#else - // Make sure we have write permission to this directory - new FileIOPermission(FileIOPermissionAccess.Write, new String[] { demandPath }, false, false ).Demand(); -#endif - // Do not recursively delete through reparse points. Perhaps in a // future version we will add a new flag to control this behavior, // but for now we're much safer if we err on the conservative side. @@ -1206,10 +791,7 @@ namespace System.IO { DeleteHelper(fullPath, userPath, recursive, true); } - // Note that fullPath is fully qualified, while userPath may be - // relative. Use userPath for all exception messages to avoid leaking - // fully qualified path information. - [System.Security.SecurityCritical] // auto-generated + // Note that fullPath is fully qualified, while userPath may be relative. private static void DeleteHelper(String fullPath, String userPath, bool recursive, bool throwOnTopLevelDirectoryNotFound) { bool r; @@ -1229,12 +811,12 @@ namespace System.IO { Win32Native.WIN32_FIND_DATA data = new Win32Native.WIN32_FIND_DATA(); // Open a Find handle - using (SafeFindHandle hnd = Win32Native.FindFirstFile(fullPath+Path.DirectorySeparatorCharAsString+"*", data)) { + using (SafeFindHandle hnd = Win32Native.FindFirstFile(fullPath + Path.DirectorySeparatorChar + "*", data)) { if (hnd.IsInvalid) { hr = Marshal.GetLastWin32Error(); __Error.WinIOError(hr, fullPath); } - + do { bool isDir = (0!=(data.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY)); if (isDir) { @@ -1248,8 +830,8 @@ namespace System.IO { // itself. bool shouldRecurse = (0 == (data.dwFileAttributes & (int) FileAttributes.ReparsePoint)); if (shouldRecurse) { - String newFullPath = Path.InternalCombine(fullPath, data.cFileName); - String newUserPath = Path.InternalCombine(userPath, data.cFileName); + String newFullPath = Path.Combine(fullPath, data.cFileName); + String newUserPath = Path.Combine(userPath, data.cFileName); try { DeleteHelper(newFullPath, newUserPath, recursive, false); } @@ -1264,7 +846,7 @@ namespace System.IO { // unmount it. if (data.dwReserved0 == Win32Native.IO_REPARSE_TAG_MOUNT_POINT) { // Use full path plus a trailing '\' - String mountPoint = Path.InternalCombine(fullPath, data.cFileName + Path.DirectorySeparatorChar); + String mountPoint = Path.Combine(fullPath, data.cFileName + Path.DirectorySeparatorChar); r = Win32Native.DeleteVolumeMountPoint(mountPoint); if (!r) { hr = Marshal.GetLastWin32Error(); @@ -1283,7 +865,7 @@ namespace System.IO { // RemoveDirectory on a symbolic link will // remove the link itself. - String reparsePoint = Path.InternalCombine(fullPath, data.cFileName); + String reparsePoint = Path.Combine(fullPath, data.cFileName); r = Win32Native.RemoveDirectory(reparsePoint); if (!r) { hr = Marshal.GetLastWin32Error(); @@ -1301,7 +883,7 @@ namespace System.IO { } } else { - String fileName = Path.InternalCombine(fullPath, data.cFileName); + String fileName = Path.Combine(fullPath, data.cFileName); r = Win32Native.DeleteFile(fileName); if (!r) { hr = Marshal.GetLastWin32Error(); @@ -1346,44 +928,6 @@ namespace System.IO { __Error.WinIOError(hr, fullPath); } } - - // WinNT only. Win9x this code will not work. - [System.Security.SecurityCritical] // auto-generated - private static SafeFileHandle OpenHandle(String path) - { - String fullPath = Path.GetFullPathInternal(path); - String root = Path.GetPathRoot(fullPath); - if (root == fullPath && root[1] == Path.VolumeSeparatorChar) - throw new ArgumentException(Environment.GetResourceString("Arg_PathIsVolume")); - -#if !FEATURE_CORECLR - FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, GetDemandDir(fullPath, true), false, false); -#endif - - SafeFileHandle handle = Win32Native.SafeCreateFile ( - fullPath, - GENERIC_WRITE, - (FileShare) (FILE_SHARE_WRITE|FILE_SHARE_DELETE), - null, - FileMode.Open, - FILE_FLAG_BACKUP_SEMANTICS, - IntPtr.Zero - ); - - if (handle.IsInvalid) { - int hr = Marshal.GetLastWin32Error(); - __Error.WinIOError(hr, fullPath); - } - return handle; - } - - private const int FILE_ATTRIBUTE_DIRECTORY = 0x00000010; - private const int GENERIC_WRITE = unchecked((int)0x40000000); - private const int FILE_SHARE_WRITE = 0x00000002; - private const int FILE_SHARE_DELETE = 0x00000004; - private const int OPEN_EXISTING = 0x00000003; - private const int FILE_FLAG_BACKUP_SEMANTICS = 0x02000000; } - } diff --git a/src/mscorlib/src/System/IO/DirectoryInfo.cs b/src/mscorlib/src/System/IO/DirectoryInfo.cs index f7b0709..c4c350d 100644 --- a/src/mscorlib/src/System/IO/DirectoryInfo.cs +++ b/src/mscorlib/src/System/IO/DirectoryInfo.cs @@ -15,63 +15,33 @@ ** ===========================================================*/ -using System; -using System.Collections; using System.Collections.Generic; -using System.Security; -#if FEATURE_MACL -using System.Security.AccessControl; -#endif -using System.Security.Permissions; using Microsoft.Win32; -using System.Text; using System.Runtime.InteropServices; -using System.Globalization; using System.Runtime.Serialization; using System.Runtime.Versioning; +using System.Diagnostics; using System.Diagnostics.Contracts; -namespace System.IO { +namespace System.IO +{ [Serializable] [ComVisible(true)] - public sealed class DirectoryInfo : FileSystemInfo { - private String[] demandDir; - -#if FEATURE_CORECLR - // Migrating InheritanceDemands requires this default ctor, so we can annotate it. -#if FEATURE_CORESYSTEM - [System.Security.SecurityCritical] -#else - [System.Security.SecuritySafeCritical] -#endif //FEATURE_CORESYSTEM + public sealed class DirectoryInfo : FileSystemInfo + { + // Migrating InheritanceDemands requires this default ctor, so we can annotate it. private DirectoryInfo(){} - - [System.Security.SecurityCritical] - public static DirectoryInfo UnsafeCreateDirectoryInfo(String path) - { - if (path == null) - throw new ArgumentNullException("path"); - Contract.EndContractBlock(); - - DirectoryInfo di = new DirectoryInfo(); - di.Init(path, false); - return di; - } -#endif - - [System.Security.SecuritySafeCritical] public DirectoryInfo(String path) { if (path==null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); Contract.EndContractBlock(); - Init(path, true); + Init(path); } - [System.Security.SecurityCritical] - private void Init(String path, bool checkHost) + private void Init(String path) { // Special case ":" to point to "" instead if ((path.Length == 2) && (path[1] == ':')) @@ -83,138 +53,79 @@ namespace System.IO { OriginalPath = path; } - // Must fully qualify the path for the security check - String fullPath = Path.GetFullPathInternal(path); - - demandDir = new String[] {Directory.GetDemandDir(fullPath, true)}; -#if FEATURE_CORECLR - if (checkHost) - { - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, OriginalPath, fullPath); - state.EnsureState(); - } -#else - new FileIOPermission(FileIOPermissionAccess.Read, demandDir, false, false ).Demand(); -#endif - - FullPath = fullPath; + FullPath = Path.GetFullPath(path); ; DisplayPath = GetDisplayName(OriginalPath, FullPath); } -#if FEATURE_CORESYSTEM - [System.Security.SecuritySafeCritical] -#endif //FEATURE_CORESYSTEM internal DirectoryInfo(String fullPath, bool junk) { - Contract.Assert(Path.GetRootLength(fullPath) > 0, "fullPath must be fully qualified!"); + Debug.Assert(PathInternal.GetRootLength(fullPath) > 0, "fullPath must be fully qualified!"); // Fast path when we know a DirectoryInfo exists. OriginalPath = Path.GetFileName(fullPath); FullPath = fullPath; DisplayPath = GetDisplayName(OriginalPath, FullPath); - demandDir = new String[] {Directory.GetDemandDir(fullPath, true)}; } - [System.Security.SecurityCritical] // auto-generated private DirectoryInfo(SerializationInfo info, StreamingContext context) : base(info, context) { -#if !FEATURE_CORECLR - demandDir = new String[] {Directory.GetDemandDir(FullPath, true)}; - new FileIOPermission(FileIOPermissionAccess.Read, demandDir, false, false ).Demand(); -#endif DisplayPath = GetDisplayName(OriginalPath, FullPath); } - public override String Name { + public override String Name + { get { -#if FEATURE_CORECLR // DisplayPath is dir name for coreclr return DisplayPath; -#else - // Return just dir name - return GetDirName(FullPath); -#endif } } public DirectoryInfo Parent { - [System.Security.SecuritySafeCritical] get { String parentName; // FullPath might be either "c:\bar" or "c:\bar\". Handle // those cases, as well as avoiding mangling "c:\". String s = FullPath; if (s.Length > 3 && s.EndsWith(Path.DirectorySeparatorChar)) - s = FullPath.Substring(0, FullPath.Length - 1); + s = FullPath.Substring(0, FullPath.Length - 1); parentName = Path.GetDirectoryName(s); if (parentName==null) return null; - DirectoryInfo dir = new DirectoryInfo(parentName,false); -#if FEATURE_CORECLR - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.PathDiscovery | FileSecurityStateAccess.Read, String.Empty, dir.demandDir[0]); - state.EnsureState(); -#else - new FileIOPermission(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, dir.demandDir, false, false).Demand(); -#endif - return dir; + + return new DirectoryInfo(parentName, false); } } - -#if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] -#endif public DirectoryInfo CreateSubdirectory(String path) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); Contract.EndContractBlock(); return CreateSubdirectory(path, null); } -#if FEATURE_MACL - [System.Security.SecuritySafeCritical] // auto-generated - public DirectoryInfo CreateSubdirectory(String path, DirectorySecurity directorySecurity) - { - return CreateSubdirectoryHelper(path, directorySecurity); - } -#else // FEATURE_MACL - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif public DirectoryInfo CreateSubdirectory(String path, Object directorySecurity) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); Contract.EndContractBlock(); return CreateSubdirectoryHelper(path, directorySecurity); } -#endif // FEATURE_MACL - [System.Security.SecurityCritical] // auto-generated private DirectoryInfo CreateSubdirectoryHelper(String path, Object directorySecurity) { Contract.Requires(path != null); - String newDirs = Path.InternalCombine(FullPath, path); - String fullPath = Path.GetFullPathInternal(newDirs); + String newDirs = Path.Combine(FullPath, path); + String fullPath = Path.GetFullPath(newDirs); if (0!=String.Compare(FullPath,0,fullPath,0, FullPath.Length,StringComparison.OrdinalIgnoreCase)) { String displayPath = __Error.GetDisplayablePath(DisplayPath, false); throw new ArgumentException(Environment.GetResourceString("Argument_InvalidSubPath", path, displayPath)); } - // Ensure we have permission to create this subdirectory. - String demandDirForCreation = Directory.GetDemandDir(fullPath, true); -#if FEATURE_CORECLR - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Write, OriginalPath, demandDirForCreation); - state.EnsureState(); -#else - new FileIOPermission(FileIOPermissionAccess.Write, new String[] { demandDirForCreation }, false, false).Demand(); -#endif - Directory.InternalCreateDirectory(fullPath, path, directorySecurity); // Check for read permission to directory we hand back by calling this constructor. @@ -223,23 +134,11 @@ namespace System.IO { public void Create() { - Directory.InternalCreateDirectory(FullPath, OriginalPath, null, true); + Directory.InternalCreateDirectory(FullPath, OriginalPath, null); } -#if FEATURE_MACL - public void Create(DirectorySecurity directorySecurity) - { - Directory.InternalCreateDirectory(FullPath, OriginalPath, directorySecurity, true); - } -#endif - // Tests if the given path refers to an existing DirectoryInfo on disk. - // - // Your application must have Read permission to the directory's - // contents. - // public override bool Exists { - [System.Security.SecuritySafeCritical] // auto-generated get { try @@ -248,7 +147,6 @@ namespace System.IO { Refresh(); if (_dataInitialised != 0) // Refresh was unable to initialise the data return false; - return _data.fileAttributes != -1 && (_data.fileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY) != 0; } catch @@ -257,30 +155,13 @@ namespace System.IO { } } } - -#if FEATURE_MACL - public DirectorySecurity GetAccessControl() - { - return Directory.GetAccessControl(FullPath, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group); - } - - public DirectorySecurity GetAccessControl(AccessControlSections includeSections) - { - return Directory.GetAccessControl(FullPath, includeSections); - } - - public void SetAccessControl(DirectorySecurity directorySecurity) - { - Directory.SetAccessControl(FullPath, directorySecurity); - } -#endif // Returns an array of Files in the current DirectoryInfo matching the // given search criteria (ie, "*.txt"). public FileInfo[] GetFiles(String searchPattern) { if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); Contract.EndContractBlock(); return InternalGetFiles(searchPattern, SearchOption.TopDirectoryOnly); @@ -291,9 +172,9 @@ namespace System.IO { public FileInfo[] GetFiles(String searchPattern, SearchOption searchOption) { if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories)) - throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum")); + throw new ArgumentOutOfRangeException(nameof(searchOption), Environment.GetResourceString("ArgumentOutOfRange_Enum")); Contract.EndContractBlock(); return InternalGetFiles(searchPattern, searchOption); @@ -328,7 +209,7 @@ namespace System.IO { public FileSystemInfo[] GetFileSystemInfos(String searchPattern) { if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); Contract.EndContractBlock(); return InternalGetFileSystemInfos(searchPattern, SearchOption.TopDirectoryOnly); @@ -339,9 +220,9 @@ namespace System.IO { public FileSystemInfo[] GetFileSystemInfos(String searchPattern, SearchOption searchOption) { if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories)) - throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum")); + throw new ArgumentOutOfRangeException(nameof(searchOption), Environment.GetResourceString("ArgumentOutOfRange_Enum")); Contract.EndContractBlock(); return InternalGetFileSystemInfos(searchPattern, searchOption); @@ -372,7 +253,7 @@ namespace System.IO { public DirectoryInfo[] GetDirectories(String searchPattern) { if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); Contract.EndContractBlock(); return InternalGetDirectories(searchPattern, SearchOption.TopDirectoryOnly); @@ -384,9 +265,9 @@ namespace System.IO { public DirectoryInfo[] GetDirectories(String searchPattern, SearchOption searchOption) { if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories)) - throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum")); + throw new ArgumentOutOfRangeException(nameof(searchOption), Environment.GetResourceString("ArgumentOutOfRange_Enum")); Contract.EndContractBlock(); return InternalGetDirectories(searchPattern, searchOption); @@ -413,7 +294,7 @@ namespace System.IO { public IEnumerable EnumerateDirectories(String searchPattern) { if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); Contract.EndContractBlock(); return InternalEnumerateDirectories(searchPattern, SearchOption.TopDirectoryOnly); @@ -422,9 +303,9 @@ namespace System.IO { public IEnumerable EnumerateDirectories(String searchPattern, SearchOption searchOption) { if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories)) - throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum")); + throw new ArgumentOutOfRangeException(nameof(searchOption), Environment.GetResourceString("ArgumentOutOfRange_Enum")); Contract.EndContractBlock(); return InternalEnumerateDirectories(searchPattern, searchOption); @@ -446,7 +327,7 @@ namespace System.IO { public IEnumerable EnumerateFiles(String searchPattern) { if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); Contract.EndContractBlock(); return InternalEnumerateFiles(searchPattern, SearchOption.TopDirectoryOnly); @@ -455,9 +336,9 @@ namespace System.IO { public IEnumerable EnumerateFiles(String searchPattern, SearchOption searchOption) { if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories)) - throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum")); + throw new ArgumentOutOfRangeException(nameof(searchOption), Environment.GetResourceString("ArgumentOutOfRange_Enum")); Contract.EndContractBlock(); return InternalEnumerateFiles(searchPattern, searchOption); @@ -479,7 +360,7 @@ namespace System.IO { public IEnumerable EnumerateFileSystemInfos(String searchPattern) { if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); Contract.EndContractBlock(); return InternalEnumerateFileSystemInfos(searchPattern, SearchOption.TopDirectoryOnly); @@ -488,9 +369,9 @@ namespace System.IO { public IEnumerable EnumerateFileSystemInfos(String searchPattern, SearchOption searchOption) { if (searchPattern == null) - throw new ArgumentNullException("searchPattern"); + throw new ArgumentNullException(nameof(searchPattern)); if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories)) - throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum")); + throw new ArgumentOutOfRangeException(nameof(searchOption), Environment.GetResourceString("ArgumentOutOfRange_Enum")); Contract.EndContractBlock(); return InternalEnumerateFileSystemInfos(searchPattern, searchOption); @@ -503,7 +384,7 @@ namespace System.IO { return FileSystemEnumerableFactory.CreateFileSystemInfoIterator(FullPath, OriginalPath, searchPattern, searchOption); } - + // Returns the root portion of the given path. The resulting string // consists of those rightmost characters of the path that constitute the // root of the path. Possible patterns for the resulting string are: An @@ -512,61 +393,27 @@ namespace System.IO { // where X is the drive letter), "X:\" (an absolute path on a given drive), // and "\\server\share" (a UNC path for a given server and share name). // The resulting string is null if path is null. - // - public DirectoryInfo Root { - [System.Security.SecuritySafeCritical] get { - String demandPath; - int rootLength = Path.GetRootLength(FullPath); + int rootLength = PathInternal.GetRootLength(FullPath); String rootPath = FullPath.Substring(0, rootLength); - demandPath = Directory.GetDemandDir(rootPath, true); - -#if FEATURE_CORECLR - FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandPath); - sourceState.EnsureState(); -#else - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { demandPath }, false, false).Demand(); -#endif + return new DirectoryInfo(rootPath); } } - [System.Security.SecuritySafeCritical] public void MoveTo(String destDirName) { if (destDirName==null) - throw new ArgumentNullException("destDirName"); + throw new ArgumentNullException(nameof(destDirName)); if (destDirName.Length==0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destDirName"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), nameof(destDirName)); Contract.EndContractBlock(); - -#if FEATURE_CORECLR - FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Write | FileSecurityStateAccess.Read, DisplayPath, Directory.GetDemandDir(FullPath, true)); - sourceState.EnsureState(); -#else - new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, demandDir, false, false).Demand(); -#endif - String fullDestDirName = Path.GetFullPathInternal(destDirName); - String demandPath; + + String fullDestDirName = Path.GetFullPath(destDirName); if (!fullDestDirName.EndsWith(Path.DirectorySeparatorChar)) fullDestDirName = fullDestDirName + Path.DirectorySeparatorChar; - demandPath = fullDestDirName + '.'; - - // Demand read & write permission to destination. The reason is - // we hand back a DirectoryInfo to the destination that would allow - // you to read a directory listing from that directory. Sure, you - // had the ability to read the file contents in the old location, - // but you technically also need read permissions to the new - // location as well, and write is not a true superset of read. -#if FEATURE_CORECLR - FileSecurityState destState = new FileSecurityState(FileSecurityStateAccess.Write, destDirName, demandPath); - destState.EnsureState(); -#else - new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, demandPath).Demand(); -#endif - String fullSourcePath; if (FullPath.EndsWith(Path.DirectorySeparatorChar)) fullSourcePath = FullPath; @@ -599,22 +446,19 @@ namespace System.IO { FullPath = fullDestDirName; OriginalPath = destDirName; DisplayPath = GetDisplayName(OriginalPath, FullPath); - demandDir = new String[] { Directory.GetDemandDir(FullPath, true) }; // Flush any cached information about the directory. _dataInitialised = -1; } - [System.Security.SecuritySafeCritical] public override void Delete() { - Directory.Delete(FullPath, OriginalPath, false, true); + Directory.Delete(FullPath, OriginalPath, false); } - [System.Security.SecuritySafeCritical] public void Delete(bool recursive) { - Directory.Delete(FullPath, OriginalPath, recursive, true); + Directory.Delete(FullPath, OriginalPath, recursive); } // Returns the fully qualified path @@ -625,8 +469,8 @@ namespace System.IO { private static String GetDisplayName(String originalPath, String fullPath) { - Contract.Assert(originalPath != null); - Contract.Assert(fullPath != null); + Debug.Assert(originalPath != null); + Debug.Assert(fullPath != null); String displayName = ""; @@ -637,18 +481,14 @@ namespace System.IO { } else { -#if FEATURE_CORECLR displayName = GetDirName(fullPath); -#else - displayName = originalPath; -#endif } return displayName; } private static String GetDirName(String fullPath) { - Contract.Assert(fullPath != null); + Debug.Assert(fullPath != null); String dirName = null; if (fullPath.Length > 3) @@ -666,7 +506,6 @@ namespace System.IO { } return dirName; } - - } + } } diff --git a/src/mscorlib/src/System/IO/DriveInfo.cs b/src/mscorlib/src/System/IO/DriveInfo.cs deleted file mode 100644 index be75e89..0000000 --- a/src/mscorlib/src/System/IO/DriveInfo.cs +++ /dev/null @@ -1,281 +0,0 @@ -// 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. - -/*============================================================ -** -** -** -** -** -** Purpose: Exposes routines for exploring a drive. -** -** -===========================================================*/ - -using System; -using System.Text; -using System.Runtime.InteropServices; -using Microsoft.Win32; -using System.Security.Permissions; -using System.Runtime.Serialization; -using System.Runtime.Versioning; -using System.Diagnostics.Contracts; - -namespace System.IO -{ - // Matches Win32's DRIVE_XXX #defines from winbase.h - [Serializable] -[System.Runtime.InteropServices.ComVisible(true)] - public enum DriveType - { - Unknown = 0, - NoRootDirectory = 1, - Removable = 2, - Fixed = 3, - Network = 4, - CDRom = 5, - Ram = 6 - } - - // Ideally we'll get a better security permission, but possibly - // not for Whidbey. -#if FEATURE_SERIALIZATION - [Serializable] -#endif - [ComVisible(true)] - public sealed class DriveInfo -#if FEATURE_SERIALIZATION - : ISerializable -#endif - { - private String _name; - - private const String NameField = "_name"; // For serialization - - [System.Security.SecuritySafeCritical] // auto-generated - public DriveInfo(String driveName) - { - if (driveName == null) - throw new ArgumentNullException("driveName"); - Contract.EndContractBlock(); - if (driveName.Length == 1) - _name = driveName + ":\\"; - else { - // GetPathRoot does not check all invalid characters - Path.CheckInvalidPathChars(driveName); - _name = Path.GetPathRoot(driveName); - // Disallow null or empty drive letters and UNC paths - if (_name == null || _name.Length == 0 || _name.StartsWith("\\\\", StringComparison.Ordinal)) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDriveLetterOrRootDir")); - } - // We want to normalize to have a trailing backslash so we don't have two equivalent forms and - // because some Win32 API don't work without it. - if (_name.Length == 2 && _name[1] == ':') { - _name = _name + "\\"; - } - - // Now verify that the drive letter could be a real drive name. - // On Windows this means it's between A and Z, ignoring case. - // On a Unix platform, perhaps this should be a device name with - // a partition like /dev/hdc0, or possibly a mount point. - char letter = driveName[0]; - if (!((letter >= 'A' && letter <= 'Z') || (letter >= 'a' && letter <= 'z'))) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDriveLetterOrRootDir")); - - // Now do a security check. - String demandPath = _name + '.'; - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPath).Demand(); - } - - [System.Security.SecurityCritical] // auto-generated - private DriveInfo(SerializationInfo info, StreamingContext context) - { - // Need to add in a security check here once it has been spec'ed. - _name = (String) info.GetValue(NameField, typeof(String)); - - // Now do a security check. - String demandPath = _name + '.'; - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPath).Demand(); - } - - public String Name { - get { return _name; } - } - - public DriveType DriveType { - [System.Security.SecuritySafeCritical] // auto-generated - get { - // GetDriveType can't fail - return (DriveType) Win32Native.GetDriveType(Name); - } - } - - public String DriveFormat { - [System.Security.SecuritySafeCritical] // auto-generated - get { - const int volNameLen = 50; - StringBuilder volumeName = new StringBuilder(volNameLen); - const int fileSystemNameLen = 50; - StringBuilder fileSystemName = new StringBuilder(fileSystemNameLen); - int serialNumber, maxFileNameLen, fileSystemFlags; - - int oldMode = Win32Native.SetErrorMode(Win32Native.SEM_FAILCRITICALERRORS); - try { - bool r = Win32Native.GetVolumeInformation(Name, volumeName, volNameLen, out serialNumber, out maxFileNameLen, out fileSystemFlags, fileSystemName, fileSystemNameLen); - if (!r) { - int errorCode = Marshal.GetLastWin32Error(); - __Error.WinIODriveError(Name, errorCode); - } - } - finally { - Win32Native.SetErrorMode(oldMode); - } - return fileSystemName.ToString(); - } - } - - public bool IsReady { - [System.Security.SecuritySafeCritical] // auto-generated - get { - return Directory.InternalExists(Name); - } - } - - public long AvailableFreeSpace { - [System.Security.SecuritySafeCritical] // auto-generated - get { - long userBytes, totalBytes, freeBytes; - int oldMode = Win32Native.SetErrorMode(Win32Native.SEM_FAILCRITICALERRORS); - try { - bool r = Win32Native.GetDiskFreeSpaceEx(Name, out userBytes, out totalBytes, out freeBytes); - if (!r) - __Error.WinIODriveError(Name); - } - finally { - Win32Native.SetErrorMode(oldMode); - } - return userBytes; - } - } - - public long TotalFreeSpace { - [System.Security.SecuritySafeCritical] // auto-generated - get { - long userBytes, totalBytes, freeBytes; - int oldMode = Win32Native.SetErrorMode(Win32Native.SEM_FAILCRITICALERRORS); - try { - bool r = Win32Native.GetDiskFreeSpaceEx(Name, out userBytes, out totalBytes, out freeBytes); - if (!r) - __Error.WinIODriveError(Name); - } - finally { - Win32Native.SetErrorMode(oldMode); - } - return freeBytes; - } - } - - public long TotalSize { - [System.Security.SecuritySafeCritical] // auto-generated - get { - // Don't cache this, to handle variable sized floppy drives - // or other various removable media drives. - long userBytes, totalBytes, freeBytes; - int oldMode = Win32Native.SetErrorMode(Win32Native.SEM_FAILCRITICALERRORS); - try { - bool r = Win32Native.GetDiskFreeSpaceEx(Name, out userBytes, out totalBytes, out freeBytes); - if (!r) - __Error.WinIODriveError(Name); - } - finally { - Win32Native.SetErrorMode(oldMode); - } - return totalBytes; - } - } - - public static DriveInfo[] GetDrives() - { - // Directory.GetLogicalDrives demands unmanaged code permission - String[] drives = Directory.GetLogicalDrives(); - DriveInfo[] di = new DriveInfo[drives.Length]; - for(int i=0; i - [System.Security.SecurityCritical] - void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) - { - // No need for an additional security check - everything is public. - info.AddValue(NameField, _name, typeof(String)); - } -#endif - - } -} diff --git a/src/mscorlib/src/System/IO/EncodingCache.cs b/src/mscorlib/src/System/IO/EncodingCache.cs new file mode 100644 index 0000000..53379bc --- /dev/null +++ b/src/mscorlib/src/System/IO/EncodingCache.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Text; + +namespace System.IO +{ + internal static class EncodingCache + { + internal static readonly Encoding UTF8NoBOM = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); + } +} diff --git a/src/mscorlib/src/System/IO/File.cs b/src/mscorlib/src/System/IO/File.cs index cfcb469..9f89f81 100644 --- a/src/mscorlib/src/System/IO/File.cs +++ b/src/mscorlib/src/System/IO/File.cs @@ -14,34 +14,32 @@ ** ===========================================================*/ -using System; using System.Security.Permissions; -using PermissionSet = System.Security.PermissionSet; using Win32Native = Microsoft.Win32.Win32Native; using System.Runtime.InteropServices; using System.Security; -#if FEATURE_MACL -using System.Security.AccessControl; -#endif using System.Text; using Microsoft.Win32.SafeHandles; using System.Collections.Generic; -using System.Globalization; -using System.Runtime.Versioning; +using System.Diagnostics; using System.Diagnostics.Contracts; - -namespace System.IO { + +namespace System.IO +{ // Class for creating FileStream objects, and some basic file management // routines such as Delete, etc. [ComVisible(true)] public static class File { + private const int ERROR_INVALID_PARAMETER = 87; + internal const int GENERIC_READ = unchecked((int)0x80000000); + private const int GetFileExInfoStandard = 0; public static StreamReader OpenText(String path) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); Contract.EndContractBlock(); return new StreamReader(path); } @@ -49,7 +47,7 @@ namespace System.IO { public static StreamWriter CreateText(String path) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); Contract.EndContractBlock(); return new StreamWriter(path,false); } @@ -57,7 +55,7 @@ namespace System.IO { public static StreamWriter AppendText(String path) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); Contract.EndContractBlock(); return new StreamWriter(path,true); } @@ -67,88 +65,51 @@ namespace System.IO { // destination file already exists. Use the // Copy(String, String, boolean) method to allow // overwriting an existing file. - // - // The caller must have certain FileIOPermissions. The caller must have - // Read permission to sourceFileName and Create - // and Write permissions to destFileName. - // public static void Copy(String sourceFileName, String destFileName) { if (sourceFileName == null) - throw new ArgumentNullException("sourceFileName", Environment.GetResourceString("ArgumentNull_FileName")); + throw new ArgumentNullException(nameof(sourceFileName), Environment.GetResourceString("ArgumentNull_FileName")); if (destFileName == null) - throw new ArgumentNullException("destFileName", Environment.GetResourceString("ArgumentNull_FileName")); + throw new ArgumentNullException(nameof(destFileName), Environment.GetResourceString("ArgumentNull_FileName")); if (sourceFileName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "sourceFileName"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), nameof(sourceFileName)); if (destFileName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destFileName"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), nameof(destFileName)); Contract.EndContractBlock(); - InternalCopy(sourceFileName, destFileName, false, true); + InternalCopy(sourceFileName, destFileName, false); } // Copies an existing file to a new file. If overwrite is // false, then an IOException is thrown if the destination file // already exists. If overwrite is true, the file is // overwritten. - // - // The caller must have certain FileIOPermissions. The caller must have - // Read permission to sourceFileName - // and Write permissions to destFileName. - // public static void Copy(String sourceFileName, String destFileName, bool overwrite) { if (sourceFileName == null) - throw new ArgumentNullException("sourceFileName", Environment.GetResourceString("ArgumentNull_FileName")); + throw new ArgumentNullException(nameof(sourceFileName), Environment.GetResourceString("ArgumentNull_FileName")); if (destFileName == null) - throw new ArgumentNullException("destFileName", Environment.GetResourceString("ArgumentNull_FileName")); + throw new ArgumentNullException(nameof(destFileName), Environment.GetResourceString("ArgumentNull_FileName")); if (sourceFileName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "sourceFileName"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), nameof(sourceFileName)); if (destFileName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destFileName"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), nameof(destFileName)); Contract.EndContractBlock(); - InternalCopy(sourceFileName, destFileName, overwrite, true); - } - - [System.Security.SecurityCritical] - internal static void UnsafeCopy(String sourceFileName, String destFileName, bool overwrite) { - if (sourceFileName == null) - throw new ArgumentNullException("sourceFileName", Environment.GetResourceString("ArgumentNull_FileName")); - if (destFileName == null) - throw new ArgumentNullException("destFileName", Environment.GetResourceString("ArgumentNull_FileName")); - if (sourceFileName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "sourceFileName"); - if (destFileName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destFileName"); - Contract.EndContractBlock(); - - InternalCopy(sourceFileName, destFileName, overwrite, false); + InternalCopy(sourceFileName, destFileName, overwrite); } /// /// Note: This returns the fully qualified name of the destination file. /// - [System.Security.SecuritySafeCritical] - internal static String InternalCopy(String sourceFileName, String destFileName, bool overwrite, bool checkHost) { + internal static String InternalCopy(String sourceFileName, String destFileName, bool overwrite) + { Contract.Requires(sourceFileName != null); Contract.Requires(destFileName != null); Contract.Requires(sourceFileName.Length > 0); Contract.Requires(destFileName.Length > 0); - String fullSourceFileName = Path.GetFullPathInternal(sourceFileName); - String fullDestFileName = Path.GetFullPathInternal(destFileName); - -#if FEATURE_CORECLR - if (checkHost) { - FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Read, sourceFileName, fullSourceFileName); - FileSecurityState destState = new FileSecurityState(FileSecurityStateAccess.Write, destFileName, fullDestFileName); - sourceState.EnsureState(); - destState.EnsureState(); - } -#else - FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullSourceFileName, false, false); - FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, fullDestFileName, false, false); -#endif - + String fullSourceFileName = Path.GetFullPath(sourceFileName); + String fullDestFileName = Path.GetFullPath(destFileName); + bool r = Win32Native.CopyFile(fullSourceFileName, fullDestFileName, !overwrite); if (!r) { // Save Win32 error because subsequent checks will overwrite this HRESULT. @@ -156,14 +117,6 @@ namespace System.IO { String fileName = destFileName; if (errorCode != Win32Native.ERROR_FILE_EXISTS) { - // For a number of error codes (sharing violation, path - // not found, etc) we don't know if the problem was with - // the source or dest file. Try reading the source file. - using(SafeFileHandle handle = Win32Native.UnsafeCreateFile(fullSourceFileName, FileStream.GENERIC_READ, FileShare.Read, null, FileMode.Open, 0, IntPtr.Zero)) { - if (handle.IsInvalid) - fileName = sourceFileName; - } - if (errorCode == Win32Native.ERROR_ACCESS_DENIED) { if (Directory.InternalExists(fullDestFileName)) throw new IOException(Environment.GetResourceString("Arg_FileIsDirectory_Name", destFileName), Win32Native.ERROR_ACCESS_DENIED, fullDestFileName); @@ -172,19 +125,14 @@ namespace System.IO { __Error.WinIOError(errorCode, fileName); } - + return fullDestFileName; } - // Creates a file in a particular path. If the file exists, it is replaced. // The file is opened with ReadWrite accessand cannot be opened by another // application until it has been closed. An IOException is thrown if the // directory specified doesn't exist. - // - // Your application must have Create, Read, and Write permissions to - // the file. - // public static FileStream Create(String path) { return Create(path, FileStream.DefaultBufferSize); } @@ -193,10 +141,6 @@ namespace System.IO { // The file is opened with ReadWrite access and cannot be opened by another // application until it has been closed. An IOException is thrown if the // directory specified doesn't exist. - // - // Your application must have Create, Read, and Write permissions to - // the file. - // public static FileStream Create(String path, int bufferSize) { return new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None, bufferSize); } @@ -206,57 +150,23 @@ namespace System.IO { FileShare.None, bufferSize, options); } -#if FEATURE_MACL - public static FileStream Create(String path, int bufferSize, FileOptions options, FileSecurity fileSecurity) { - return new FileStream(path, FileMode.Create, FileSystemRights.Read | FileSystemRights.Write, - FileShare.None, bufferSize, options, fileSecurity); - } -#endif - // Deletes a file. The file specified by the designated path is deleted. // If the file does not exist, Delete succeeds without throwing // an exception. // // On NT, Delete will fail for a file that is open for normal I/O // or a file that is memory mapped. - // - // Your application must have Delete permission to the target file. - // - [System.Security.SecuritySafeCritical] public static void Delete(String path) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); Contract.EndContractBlock(); - - InternalDelete(path, true); - } - [System.Security.SecurityCritical] - internal static void UnsafeDelete(String path) - { - if (path == null) - throw new ArgumentNullException("path"); - Contract.EndContractBlock(); - - InternalDelete(path, false); + InternalDelete(path); } - [System.Security.SecurityCritical] - internal static void InternalDelete(String path, bool checkHost) + internal static void InternalDelete(String path) { - String fullPath = Path.GetFullPathInternal(path); - -#if FEATURE_CORECLR - if (checkHost) - { - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Write, path, fullPath); - state.EnsureState(); - } -#else - // For security check, path should be resolved to an absolute path. - FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, fullPath, false, false); - -#endif + String fullPath = Path.GetFullPath(path); bool r = Win32Native.DeleteFile(fullPath); if (!r) { int hr = Marshal.GetLastWin32Error(); @@ -267,76 +177,16 @@ namespace System.IO { } } - - [System.Security.SecuritySafeCritical] // auto-generated - public static void Decrypt(String path) - { - if (path == null) - throw new ArgumentNullException("path"); - Contract.EndContractBlock(); - - String fullPath = Path.GetFullPathInternal(path); - FileIOPermission.QuickDemand(FileIOPermissionAccess.Read | FileIOPermissionAccess.Write, fullPath, false, false); - - bool r = Win32Native.DecryptFile(fullPath, 0); - if (!r) { - int errorCode = Marshal.GetLastWin32Error(); - if (errorCode == Win32Native.ERROR_ACCESS_DENIED) { - // Check to see if the file system is not NTFS. If so, - // throw a different exception. - DriveInfo di = new DriveInfo(Path.GetPathRoot(fullPath)); - if (!String.Equals("NTFS", di.DriveFormat)) - throw new NotSupportedException(Environment.GetResourceString("NotSupported_EncryptionNeedsNTFS")); - } - __Error.WinIOError(errorCode, fullPath); - } - } - - [System.Security.SecuritySafeCritical] // auto-generated - public static void Encrypt(String path) - { - if (path == null) - throw new ArgumentNullException("path"); - Contract.EndContractBlock(); - - String fullPath = Path.GetFullPathInternal(path); - FileIOPermission.QuickDemand(FileIOPermissionAccess.Read | FileIOPermissionAccess.Write, fullPath, false, false); - - bool r = Win32Native.EncryptFile(fullPath); - if (!r) { - int errorCode = Marshal.GetLastWin32Error(); - if (errorCode == Win32Native.ERROR_ACCESS_DENIED) { - // Check to see if the file system is not NTFS. If so, - // throw a different exception. - DriveInfo di = new DriveInfo(Path.GetPathRoot(fullPath)); - if (!String.Equals("NTFS", di.DriveFormat)) - throw new NotSupportedException(Environment.GetResourceString("NotSupported_EncryptionNeedsNTFS")); - } - __Error.WinIOError(errorCode, fullPath); - } - } - // Tests if a file exists. The result is true if the file // given by the specified path exists; otherwise, the result is // false. Note that if path describes a directory, // Exists will return true. - // - // Your application must have Read permission for the target directory. - // - [System.Security.SecuritySafeCritical] public static bool Exists(String path) { - return InternalExistsHelper(path, true); + return InternalExistsHelper(path); } - [System.Security.SecurityCritical] - internal static bool UnsafeExists(String path) - { - return InternalExistsHelper(path, false); - } - - [System.Security.SecurityCritical] - private static bool InternalExistsHelper(String path, bool checkHost) + private static bool InternalExistsHelper(String path) { try { @@ -345,26 +195,17 @@ namespace System.IO { if (path.Length == 0) return false; - path = Path.GetFullPathInternal(path); + path = Path.GetFullPath(path); + // After normalizing, check whether path ends in directory separator. // Otherwise, FillAttributeInfo removes it and we may return a false positive. - // GetFullPathInternal should never return null - Contract.Assert(path != null, "File.Exists: GetFullPathInternal returned null"); - if (path.Length > 0 && Path.IsDirectorySeparator(path[path.Length - 1])) + // GetFullPath should never return null + Debug.Assert(path != null, "File.Exists: GetFullPath returned null"); + if (path.Length > 0 && PathInternal.IsDirectorySeparator(path[path.Length - 1])) { return false; } -#if FEATURE_CORECLR - if (checkHost) - { - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, path); - state.EnsureState(); - } -#else - FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, path, false, false); -#endif - return InternalExists(path); } catch (ArgumentException) { } @@ -376,7 +217,6 @@ namespace System.IO { return false; } - [System.Security.SecurityCritical] // auto-generated internal static bool InternalExists(String path) { Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA(); int dataInitialised = FillAttributeInfo(path, ref data, false, true); @@ -397,51 +237,19 @@ namespace System.IO { return new FileStream(path, mode, access, share); } - public static void SetCreationTime(String path, DateTime creationTime) - { - SetCreationTimeUtc(path, creationTime.ToUniversalTime()); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public unsafe static void SetCreationTimeUtc(String path, DateTime creationTimeUtc) - { - SafeFileHandle handle; - using(OpenFile(path, FileAccess.Write, out handle)) { - Win32Native.FILE_TIME fileTime = new Win32Native.FILE_TIME(creationTimeUtc.ToFileTimeUtc()); - bool r = Win32Native.SetFileTime(handle, &fileTime, null, null); - if (!r) - { - int errorCode = Marshal.GetLastWin32Error(); - __Error.WinIOError(errorCode, path); - } - } - } - - [System.Security.SecuritySafeCritical] public static DateTime GetCreationTime(String path) { - return InternalGetCreationTimeUtc(path, true).ToLocalTime(); + return InternalGetCreationTimeUtc(path).ToLocalTime(); } - [System.Security.SecuritySafeCritical] // auto-generated public static DateTime GetCreationTimeUtc(String path) { - return InternalGetCreationTimeUtc(path, false); // this API isn't exposed in Silverlight + return InternalGetCreationTimeUtc(path); // this API isn't exposed in Silverlight } - [System.Security.SecurityCritical] - private static DateTime InternalGetCreationTimeUtc(String path, bool checkHost) + private static DateTime InternalGetCreationTimeUtc(String path) { - String fullPath = Path.GetFullPathInternal(path); -#if FEATURE_CORECLR - if (checkHost) - { - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, path, fullPath); - state.EnsureState(); - } -#else - FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullPath, false, false); -#endif + String fullPath = Path.GetFullPath(path); Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA(); int dataInitialised = FillAttributeInfo(fullPath, ref data, false, false); @@ -452,51 +260,19 @@ namespace System.IO { return DateTime.FromFileTimeUtc(dt); } - public static void SetLastAccessTime(String path, DateTime lastAccessTime) - { - SetLastAccessTimeUtc(path, lastAccessTime.ToUniversalTime()); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public unsafe static void SetLastAccessTimeUtc(String path, DateTime lastAccessTimeUtc) - { - SafeFileHandle handle; - using(OpenFile(path, FileAccess.Write, out handle)) { - Win32Native.FILE_TIME fileTime = new Win32Native.FILE_TIME(lastAccessTimeUtc.ToFileTimeUtc()); - bool r = Win32Native.SetFileTime(handle, null, &fileTime, null); - if (!r) - { - int errorCode = Marshal.GetLastWin32Error(); - __Error.WinIOError(errorCode, path); - } - } - } - - [System.Security.SecuritySafeCritical] public static DateTime GetLastAccessTime(String path) { - return InternalGetLastAccessTimeUtc(path, true).ToLocalTime(); + return InternalGetLastAccessTimeUtc(path).ToLocalTime(); } - [System.Security.SecuritySafeCritical] // auto-generated public static DateTime GetLastAccessTimeUtc(String path) { - return InternalGetLastAccessTimeUtc(path, false); // this API isn't exposed in Silverlight + return InternalGetLastAccessTimeUtc(path); } - [System.Security.SecurityCritical] - private static DateTime InternalGetLastAccessTimeUtc(String path, bool checkHost) - { - String fullPath = Path.GetFullPathInternal(path); -#if FEATURE_CORECLR - if (checkHost) - { - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, path, fullPath); - state.EnsureState(); - } -#else - FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullPath, false, false); -#endif + private static DateTime InternalGetLastAccessTimeUtc(String path) + { + String fullPath = Path.GetFullPath(path); Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA(); int dataInitialised = FillAttributeInfo(fullPath, ref data, false, false); @@ -507,51 +283,19 @@ namespace System.IO { return DateTime.FromFileTimeUtc(dt); } - public static void SetLastWriteTime(String path, DateTime lastWriteTime) - { - SetLastWriteTimeUtc(path, lastWriteTime.ToUniversalTime()); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public unsafe static void SetLastWriteTimeUtc(String path, DateTime lastWriteTimeUtc) - { - SafeFileHandle handle; - using(OpenFile(path, FileAccess.Write, out handle)) { - Win32Native.FILE_TIME fileTime = new Win32Native.FILE_TIME(lastWriteTimeUtc.ToFileTimeUtc()); - bool r = Win32Native.SetFileTime(handle, null, null, &fileTime); - if (!r) - { - int errorCode = Marshal.GetLastWin32Error(); - __Error.WinIOError(errorCode, path); - } - } - } - - [System.Security.SecuritySafeCritical] public static DateTime GetLastWriteTime(String path) { - return InternalGetLastWriteTimeUtc(path, true).ToLocalTime(); + return InternalGetLastWriteTimeUtc(path).ToLocalTime(); } - [System.Security.SecuritySafeCritical] // auto-generated public static DateTime GetLastWriteTimeUtc(String path) { - return InternalGetLastWriteTimeUtc(path, false); // this API isn't exposed in Silverlight + return InternalGetLastWriteTimeUtc(path); } - [System.Security.SecurityCritical] - private static DateTime InternalGetLastWriteTimeUtc(String path, bool checkHost) + private static DateTime InternalGetLastWriteTimeUtc(String path) { - String fullPath = Path.GetFullPathInternal(path); -#if FEATURE_CORECLR - if (checkHost) - { - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, path, fullPath); - state.EnsureState(); - } -#else - FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullPath, false, false); -#endif + String fullPath = Path.GetFullPath(path); Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA(); int dataInitialised = FillAttributeInfo(fullPath, ref data, false, false); @@ -562,16 +306,9 @@ namespace System.IO { return DateTime.FromFileTimeUtc(dt); } - [System.Security.SecuritySafeCritical] public static FileAttributes GetAttributes(String path) { - String fullPath = Path.GetFullPathInternal(path); -#if FEATURE_CORECLR - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, path, fullPath); - state.EnsureState(); -#else - FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullPath, false, false); -#endif + String fullPath = Path.GetFullPath(path); Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA(); int dataInitialised = FillAttributeInfo(fullPath, ref data, false, true); @@ -581,17 +318,9 @@ namespace System.IO { return (FileAttributes) data.fileAttributes; } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] - #else - [System.Security.SecuritySafeCritical] - #endif public static void SetAttributes(String path, FileAttributes fileAttributes) { - String fullPath = Path.GetFullPathInternal(path); -#if !FEATURE_CORECLR - FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, fullPath, false, false); -#endif + String fullPath = Path.GetFullPath(path); bool r = Win32Native.SetFileAttributes(fullPath, (int) fileAttributes); if (!r) { int hr = Marshal.GetLastWin32Error(); @@ -601,158 +330,88 @@ namespace System.IO { } } -#if FEATURE_MACL - public static FileSecurity GetAccessControl(String path) - { - return GetAccessControl(path, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group); - } - - public static FileSecurity GetAccessControl(String path, AccessControlSections includeSections) - { - // Appropriate security check should be done for us by FileSecurity. - return new FileSecurity(path, includeSections); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public static void SetAccessControl(String path, FileSecurity fileSecurity) - { - if (fileSecurity == null) - throw new ArgumentNullException("fileSecurity"); - Contract.EndContractBlock(); - - String fullPath = Path.GetFullPathInternal(path); - // Appropriate security check should be done for us by FileSecurity. - fileSecurity.Persist(fullPath); - } -#endif - public static FileStream OpenRead(String path) { return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); } - public static FileStream OpenWrite(String path) { return new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None); } - [System.Security.SecuritySafeCritical] // auto-generated public static String ReadAllText(String path) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (path.Length == 0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); Contract.EndContractBlock(); - return InternalReadAllText(path, Encoding.UTF8, true); + return InternalReadAllText(path, Encoding.UTF8); } - [System.Security.SecuritySafeCritical] // auto-generated public static String ReadAllText(String path, Encoding encoding) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (encoding == null) - throw new ArgumentNullException("encoding"); - if (path.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); - Contract.EndContractBlock(); - - return InternalReadAllText(path, encoding, true); - } - - [System.Security.SecurityCritical] - internal static String UnsafeReadAllText(String path) - { - if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(encoding)); if (path.Length == 0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); Contract.EndContractBlock(); - return InternalReadAllText(path, Encoding.UTF8, false); + return InternalReadAllText(path, encoding); } - [System.Security.SecurityCritical] - private static String InternalReadAllText(String path, Encoding encoding, bool checkHost) + private static String InternalReadAllText(String path, Encoding encoding) { Contract.Requires(path != null); Contract.Requires(encoding != null); Contract.Requires(path.Length > 0); - using (StreamReader sr = new StreamReader(path, encoding, true, StreamReader.DefaultBufferSize, checkHost)) + using (StreamReader sr = new StreamReader(path, encoding, true, StreamReader.DefaultBufferSize)) return sr.ReadToEnd(); } - [System.Security.SecuritySafeCritical] // auto-generated public static void WriteAllText(String path, String contents) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (path.Length == 0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); Contract.EndContractBlock(); - InternalWriteAllText(path, contents, StreamWriter.UTF8NoBOM, true); + InternalWriteAllText(path, contents, StreamWriter.UTF8NoBOM); } - [System.Security.SecuritySafeCritical] // auto-generated public static void WriteAllText(String path, String contents, Encoding encoding) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (encoding == null) - throw new ArgumentNullException("encoding"); + throw new ArgumentNullException(nameof(encoding)); if (path.Length == 0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); Contract.EndContractBlock(); - InternalWriteAllText(path, contents, encoding, true); + InternalWriteAllText(path, contents, encoding); } - - [System.Security.SecurityCritical] - internal static void UnsafeWriteAllText(String path, String contents) - { - if (path == null) - throw new ArgumentNullException("path"); - if (path.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); - Contract.EndContractBlock(); - InternalWriteAllText(path, contents, StreamWriter.UTF8NoBOM, false); - } - - [System.Security.SecurityCritical] - private static void InternalWriteAllText(String path, String contents, Encoding encoding, bool checkHost) + private static void InternalWriteAllText(String path, String contents, Encoding encoding) { Contract.Requires(path != null); Contract.Requires(encoding != null); Contract.Requires(path.Length > 0); - using (StreamWriter sw = new StreamWriter(path, false, encoding, StreamWriter.DefaultBufferSize, checkHost)) + using (StreamWriter sw = new StreamWriter(path, false, encoding, StreamWriter.DefaultBufferSize)) sw.Write(contents); } - [System.Security.SecuritySafeCritical] // auto-generated public static byte[] ReadAllBytes(String path) { - return InternalReadAllBytes(path, true); - } - - [System.Security.SecurityCritical] - internal static byte[] UnsafeReadAllBytes(String path) - { - return InternalReadAllBytes(path, false); - } - - - [System.Security.SecurityCritical] - private static byte[] InternalReadAllBytes(String path, bool checkHost) - { byte[] bytes; using(FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, - FileStream.DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false, false, checkHost)) { + FileStream.DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false, false)) { // Do a blocking read int index = 0; long fileLength = fs.Length; @@ -771,43 +430,27 @@ namespace System.IO { return bytes; } - [System.Security.SecuritySafeCritical] // auto-generated public static void WriteAllBytes(String path, byte[] bytes) { if (path == null) - throw new ArgumentNullException("path", Environment.GetResourceString("ArgumentNull_Path")); + throw new ArgumentNullException(nameof(path), Environment.GetResourceString("ArgumentNull_Path")); if (path.Length == 0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); if (bytes == null) - throw new ArgumentNullException("bytes"); + throw new ArgumentNullException(nameof(bytes)); Contract.EndContractBlock(); - InternalWriteAllBytes(path, bytes, true); + InternalWriteAllBytes(path, bytes); } - [System.Security.SecurityCritical] - internal static void UnsafeWriteAllBytes(String path, byte[] bytes) - { - if (path == null) - throw new ArgumentNullException("path", Environment.GetResourceString("ArgumentNull_Path")); - if (path.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); - if (bytes == null) - throw new ArgumentNullException("bytes"); - Contract.EndContractBlock(); - - InternalWriteAllBytes(path, bytes, false); - } - - [System.Security.SecurityCritical] - private static void InternalWriteAllBytes(String path, byte[] bytes, bool checkHost) + private static void InternalWriteAllBytes(String path, byte[] bytes) { Contract.Requires(path != null); Contract.Requires(path.Length != 0); Contract.Requires(bytes != null); using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, - FileStream.DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false, false, checkHost)) + FileStream.DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false, false)) { fs.Write(bytes, 0, bytes.Length); } @@ -816,7 +459,7 @@ namespace System.IO { public static String[] ReadAllLines(String path) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (path.Length == 0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); Contract.EndContractBlock(); @@ -827,9 +470,9 @@ namespace System.IO { public static String[] ReadAllLines(String path, Encoding encoding) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (encoding == null) - throw new ArgumentNullException("encoding"); + throw new ArgumentNullException(nameof(encoding)); if (path.Length == 0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); Contract.EndContractBlock(); @@ -856,9 +499,9 @@ namespace System.IO { public static IEnumerable ReadLines(String path) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (path.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"), "path"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"), nameof(path)); Contract.EndContractBlock(); return ReadLinesIterator.CreateIterator(path, Encoding.UTF8); @@ -867,11 +510,11 @@ namespace System.IO { public static IEnumerable ReadLines(String path, Encoding encoding) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (encoding == null) - throw new ArgumentNullException("encoding"); + throw new ArgumentNullException(nameof(encoding)); if (path.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"), "path"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"), nameof(path)); Contract.EndContractBlock(); return ReadLinesIterator.CreateIterator(path, encoding); @@ -880,9 +523,9 @@ namespace System.IO { public static void WriteAllLines(String path, String[] contents) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (contents == null) - throw new ArgumentNullException("contents"); + throw new ArgumentNullException(nameof(contents)); if (path.Length == 0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); Contract.EndContractBlock(); @@ -893,11 +536,11 @@ namespace System.IO { public static void WriteAllLines(String path, String[] contents, Encoding encoding) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (contents == null) - throw new ArgumentNullException("contents"); + throw new ArgumentNullException(nameof(contents)); if (encoding == null) - throw new ArgumentNullException("encoding"); + throw new ArgumentNullException(nameof(encoding)); if (path.Length == 0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); Contract.EndContractBlock(); @@ -908,9 +551,9 @@ namespace System.IO { public static void WriteAllLines(String path, IEnumerable contents) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (contents == null) - throw new ArgumentNullException("contents"); + throw new ArgumentNullException(nameof(contents)); if (path.Length == 0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); Contract.EndContractBlock(); @@ -921,11 +564,11 @@ namespace System.IO { public static void WriteAllLines(String path, IEnumerable contents, Encoding encoding) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (contents == null) - throw new ArgumentNullException("contents"); + throw new ArgumentNullException(nameof(contents)); if (encoding == null) - throw new ArgumentNullException("encoding"); + throw new ArgumentNullException(nameof(encoding)); if (path.Length == 0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); Contract.EndContractBlock(); @@ -950,7 +593,7 @@ namespace System.IO { public static void AppendAllText(String path, String contents) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (path.Length == 0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); Contract.EndContractBlock(); @@ -961,9 +604,9 @@ namespace System.IO { public static void AppendAllText(String path, String contents, Encoding encoding) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (encoding == null) - throw new ArgumentNullException("encoding"); + throw new ArgumentNullException(nameof(encoding)); if (path.Length == 0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); Contract.EndContractBlock(); @@ -984,9 +627,9 @@ namespace System.IO { public static void AppendAllLines(String path, IEnumerable contents) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (contents == null) - throw new ArgumentNullException("contents"); + throw new ArgumentNullException(nameof(contents)); if (path.Length == 0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); Contract.EndContractBlock(); @@ -997,11 +640,11 @@ namespace System.IO { public static void AppendAllLines(String path, IEnumerable contents, Encoding encoding) { if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (contents == null) - throw new ArgumentNullException("contents"); + throw new ArgumentNullException(nameof(contents)); if (encoding == null) - throw new ArgumentNullException("encoding"); + throw new ArgumentNullException(nameof(encoding)); if (path.Length == 0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); Contract.EndContractBlock(); @@ -1011,48 +654,23 @@ namespace System.IO { // Moves a specified file to a new location and potentially a new file name. // This method does work across volumes. - // - // The caller must have certain FileIOPermissions. The caller must - // have Read and Write permission to - // sourceFileName and Write - // permissions to destFileName. - // - [System.Security.SecuritySafeCritical] public static void Move(String sourceFileName, String destFileName) { - InternalMove(sourceFileName, destFileName, true); - } - - [System.Security.SecurityCritical] - internal static void UnsafeMove(String sourceFileName, String destFileName) { - InternalMove(sourceFileName, destFileName, false); + InternalMove(sourceFileName, destFileName); } - [System.Security.SecurityCritical] - private static void InternalMove(String sourceFileName, String destFileName, bool checkHost) { + private static void InternalMove(String sourceFileName, String destFileName) { if (sourceFileName == null) - throw new ArgumentNullException("sourceFileName", Environment.GetResourceString("ArgumentNull_FileName")); + throw new ArgumentNullException(nameof(sourceFileName), Environment.GetResourceString("ArgumentNull_FileName")); if (destFileName == null) - throw new ArgumentNullException("destFileName", Environment.GetResourceString("ArgumentNull_FileName")); + throw new ArgumentNullException(nameof(destFileName), Environment.GetResourceString("ArgumentNull_FileName")); if (sourceFileName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "sourceFileName"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), nameof(sourceFileName)); if (destFileName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destFileName"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), nameof(destFileName)); Contract.EndContractBlock(); - String fullSourceFileName = Path.GetFullPathInternal(sourceFileName); - String fullDestFileName = Path.GetFullPathInternal(destFileName); - -#if FEATURE_CORECLR - if (checkHost) { - FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Write | FileSecurityStateAccess.Read, sourceFileName, fullSourceFileName); - FileSecurityState destState = new FileSecurityState(FileSecurityStateAccess.Write, destFileName, fullDestFileName); - sourceState.EnsureState(); - destState.EnsureState(); - } -#else - FileIOPermission.QuickDemand(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, fullSourceFileName, false, false); - FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, fullDestFileName, false, false); -#endif + String fullSourceFileName = Path.GetFullPath(sourceFileName); + String fullDestFileName = Path.GetFullPath(destFileName); if (!InternalExists(fullSourceFileName)) __Error.WinIOError(Win32Native.ERROR_FILE_NOT_FOUND, fullSourceFileName); @@ -1067,9 +685,9 @@ namespace System.IO { public static void Replace(String sourceFileName, String destinationFileName, String destinationBackupFileName) { if (sourceFileName == null) - throw new ArgumentNullException("sourceFileName"); + throw new ArgumentNullException(nameof(sourceFileName)); if (destinationFileName == null) - throw new ArgumentNullException("destinationFileName"); + throw new ArgumentNullException(nameof(destinationFileName)); Contract.EndContractBlock(); InternalReplace(sourceFileName, destinationFileName, destinationBackupFileName, false); @@ -1078,41 +696,24 @@ namespace System.IO { public static void Replace(String sourceFileName, String destinationFileName, String destinationBackupFileName, bool ignoreMetadataErrors) { if (sourceFileName == null) - throw new ArgumentNullException("sourceFileName"); + throw new ArgumentNullException(nameof(sourceFileName)); if (destinationFileName == null) - throw new ArgumentNullException("destinationFileName"); + throw new ArgumentNullException(nameof(destinationFileName)); Contract.EndContractBlock(); InternalReplace(sourceFileName, destinationFileName, destinationBackupFileName, ignoreMetadataErrors); } - [System.Security.SecuritySafeCritical] private static void InternalReplace(String sourceFileName, String destinationFileName, String destinationBackupFileName, bool ignoreMetadataErrors) { Contract.Requires(sourceFileName != null); Contract.Requires(destinationFileName != null); - // Write permission to all three files, read permission to source - // and dest. - String fullSrcPath = Path.GetFullPathInternal(sourceFileName); - String fullDestPath = Path.GetFullPathInternal(destinationFileName); + String fullSrcPath = Path.GetFullPath(sourceFileName); + String fullDestPath = Path.GetFullPath(destinationFileName); String fullBackupPath = null; if (destinationBackupFileName != null) - fullBackupPath = Path.GetFullPathInternal(destinationBackupFileName); - -#if FEATURE_CORECLR - FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Read | FileSecurityStateAccess.Write, sourceFileName, fullSrcPath); - FileSecurityState destState = new FileSecurityState(FileSecurityStateAccess.Read | FileSecurityStateAccess.Write, destinationFileName, fullDestPath); - FileSecurityState backupState = new FileSecurityState(FileSecurityStateAccess.Read | FileSecurityStateAccess.Write, destinationBackupFileName, fullBackupPath); - sourceState.EnsureState(); - destState.EnsureState(); - backupState.EnsureState(); -#else - FileIOPermission perm = new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.Write, new String[] { fullSrcPath, fullDestPath}); - if (destinationBackupFileName != null) - perm.AddPathList(FileIOPermissionAccess.Write, fullBackupPath); - perm.Demand(); -#endif + fullBackupPath = Path.GetFullPath(destinationBackupFileName); int flags = Win32Native.REPLACEFILE_WRITE_THROUGH; if (ignoreMetadataErrors) @@ -1126,7 +727,6 @@ namespace System.IO { // Returns 0 on success, otherwise a Win32 error code. Note that // classes should use -1 as the uninitialized state for dataInitialized. - [System.Security.SecurityCritical] // auto-generated internal static int FillAttributeInfo(String path, ref Win32Native.WIN32_FILE_ATTRIBUTE_DATA data, bool tryagain, bool returnErrorOnNotFound) { int dataInitialised = 0; @@ -1172,7 +772,7 @@ namespace System.IO { catch { // if we're already returning an error, don't throw another one. if (!error) { - Contract.Assert(false, "File::FillAttributeInfo - FindClose failed!"); + Debug.Assert(false, "File::FillAttributeInfo - FindClose failed!"); __Error.WinIOError(); } } @@ -1187,7 +787,6 @@ namespace System.IO { } else { - // For floppy drives, normally the OS will pop up a dialog saying // there is no disk in drive A:, please insert one. We don't want that. // SetErrorMode will let us disable this, but we should set the error @@ -1222,34 +821,5 @@ namespace System.IO { return dataInitialised; } - - [System.Security.SecurityCritical] // auto-generated - private static FileStream OpenFile(String path, FileAccess access, out SafeFileHandle handle) - { - FileStream fs = new FileStream(path, FileMode.Open, access, FileShare.ReadWrite, 1); - handle = fs.SafeFileHandle; - - if (handle.IsInvalid) { - // Return a meaningful error, using the RELATIVE path to - // the file to avoid returning extra information to the caller. - - // NT5 oddity - when trying to open "C:\" as a FileStream, - // we usually get ERROR_PATH_NOT_FOUND from the OS. We should - // probably be consistent w/ every other directory. - int hr = Marshal.GetLastWin32Error(); - String FullPath = Path.GetFullPathInternal(path); - if (hr==__Error.ERROR_PATH_NOT_FOUND && FullPath.Equals(Directory.GetDirectoryRoot(FullPath))) - hr = __Error.ERROR_ACCESS_DENIED; - - - __Error.WinIOError(hr, path); - } - return fs; - } - - - // Defined in WinError.h - private const int ERROR_INVALID_PARAMETER = 87; - private const int ERROR_ACCESS_DENIED = 0x5; } } diff --git a/src/mscorlib/src/System/IO/FileAttributes.cs b/src/mscorlib/src/System/IO/FileAttributes.cs index 19d5f22..51ef597 100644 --- a/src/mscorlib/src/System/IO/FileAttributes.cs +++ b/src/mscorlib/src/System/IO/FileAttributes.cs @@ -11,13 +11,13 @@ ===========================================================*/ using System; -namespace System.IO { +namespace System.IO +{ // File attributes for use with the FileEnumerator class. // These constants correspond to the constants in WinNT.h. - // -[Serializable] + [Serializable] [Flags] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public enum FileAttributes { // From WinNT.h (FILE_ATTRIBUTE_XXX) @@ -35,17 +35,5 @@ namespace System.IO { Offline = 0x1000, NotContentIndexed = 0x2000, Encrypted = 0x4000, - -#if !FEATURE_CORECLR -#if FEATURE_COMINTEROP - [System.Runtime.InteropServices.ComVisible(false)] -#endif // FEATURE_COMINTEROP - IntegrityStream = 0x8000, - -#if FEATURE_COMINTEROP - [System.Runtime.InteropServices.ComVisible(false)] -#endif // FEATURE_COMINTEROP - NoScrubData = 0x20000, -#endif } } diff --git a/src/mscorlib/src/System/IO/FileInfo.cs b/src/mscorlib/src/System/IO/FileInfo.cs index 3ab1a51..32622c6 100644 --- a/src/mscorlib/src/System/IO/FileInfo.cs +++ b/src/mscorlib/src/System/IO/FileInfo.cs @@ -2,33 +2,17 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -/*============================================================ -** -** -** -** -** -** Purpose: A collection of methods for manipulating Files. -** -** April 09,2000 (some design refactorization) -** -===========================================================*/ - -using System; -#if FEATURE_MACL -using System.Security.AccessControl; -#endif -using System.Security.Permissions; -using PermissionSet = System.Security.PermissionSet; using Win32Native = Microsoft.Win32.Win32Native; using System.Runtime.InteropServices; using System.Text; using System.Runtime.Serialization; using System.Globalization; using System.Runtime.Versioning; +using System.Diagnostics; using System.Diagnostics.Contracts; -namespace System.IO { +namespace System.IO +{ // Class for creating FileStream objects, and some basic file management // routines such as Delete, etc. [Serializable] @@ -37,85 +21,40 @@ namespace System.IO { { private String _name; -#if FEATURE_CORECLR // Migrating InheritanceDemands requires this default ctor, so we can annotate it. -#if FEATURE_CORESYSTEM - [System.Security.SecurityCritical] -#else - [System.Security.SecuritySafeCritical] -#endif //FEATURE_CORESYSTEM private FileInfo(){} - [System.Security.SecurityCritical] - public static FileInfo UnsafeCreateFileInfo(String fileName) - { - if (fileName == null) - throw new ArgumentNullException("fileName"); - Contract.EndContractBlock(); - - FileInfo fi = new FileInfo(); - fi.Init(fileName, false); - return fi; - } -#endif - - [System.Security.SecuritySafeCritical] public FileInfo(String fileName) { if (fileName == null) - throw new ArgumentNullException("fileName"); + throw new ArgumentNullException(nameof(fileName)); Contract.EndContractBlock(); - Init(fileName, true); + Init(fileName); } - [System.Security.SecurityCritical] - private void Init(String fileName, bool checkHost) + private void Init(String fileName) { OriginalPath = fileName; - // Must fully qualify the path for the security check - String fullPath = Path.GetFullPathInternal(fileName); -#if FEATURE_CORECLR - if (checkHost) - { - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, fileName, fullPath); - state.EnsureState(); - } -#else - FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullPath, false, false); -#endif - _name = Path.GetFileName(fileName); - FullPath = fullPath; + FullPath = Path.GetFullPath(fileName); DisplayPath = GetDisplayPath(fileName); } private String GetDisplayPath(String originalPath) { -#if FEATURE_CORECLR return Path.GetFileName(originalPath); -#else - return originalPath; -#endif - } - [System.Security.SecurityCritical] // auto-generated private FileInfo(SerializationInfo info, StreamingContext context) : base(info, context) { -#if !FEATURE_CORECLR - new FileIOPermission(FileIOPermissionAccess.Read, new String[] { FullPath }, false, false).Demand(); -#endif _name = Path.GetFileName(OriginalPath); DisplayPath = GetDisplayPath(OriginalPath); } -#if FEATURE_CORESYSTEM - [System.Security.SecuritySafeCritical] -#endif //FEATURE_CORESYSTEM internal FileInfo(String fullPath, bool ignoreThis) { - Contract.Assert(Path.GetRootLength(fullPath) > 0, "fullPath must be fully qualified!"); + Debug.Assert(PathInternal.GetRootLength(fullPath) > 0, "fullPath must be fully qualified!"); _name = Path.GetFileName(fullPath); OriginalPath = _name; FullPath = fullPath; @@ -125,10 +64,8 @@ namespace System.IO { public override String Name { get { return _name; } } - - + public long Length { - [System.Security.SecuritySafeCritical] // auto-generated get { if (_dataInitialised == -1) Refresh(); @@ -146,20 +83,9 @@ namespace System.IO { /* Returns the name of the directory that the file is in */ public String DirectoryName { - [System.Security.SecuritySafeCritical] get { - String directoryName = Path.GetDirectoryName(FullPath); - if (directoryName != null) - { -#if FEATURE_CORECLR - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, DisplayPath, FullPath); - state.EnsureState(); -#else - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { directoryName }, false, false).Demand(); -#endif - } - return directoryName; + return Path.GetDirectoryName(FullPath); } } @@ -171,7 +97,7 @@ namespace System.IO { String dirName = DirectoryName; if (dirName == null) return null; - return new DirectoryInfo(dirName); + return new DirectoryInfo(dirName); } } @@ -187,27 +113,9 @@ namespace System.IO { } } -#if FEATURE_MACL - public FileSecurity GetAccessControl() - { - return File.GetAccessControl(FullPath, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group); - } - - public FileSecurity GetAccessControl(AccessControlSections includeSections) - { - return File.GetAccessControl(FullPath, includeSections); - } - - public void SetAccessControl(FileSecurity fileSecurity) - { - File.SetAccessControl(FullPath, fileSecurity); - } -#endif - - [System.Security.SecuritySafeCritical] // auto-generated public StreamReader OpenText() { - return new StreamReader(FullPath, Encoding.UTF8, true, StreamReader.DefaultBufferSize, false); + return new StreamReader(FullPath, Encoding.UTF8, true, StreamReader.DefaultBufferSize); } public StreamWriter CreateText() @@ -220,45 +128,33 @@ namespace System.IO { return new StreamWriter(FullPath,true); } - // Copies an existing file to a new file. An exception is raised if the // destination file already exists. Use the // Copy(String, String, boolean) method to allow // overwriting an existing file. - // - // The caller must have certain FileIOPermissions. The caller must have - // Read permission to sourceFileName - // and Write permissions to destFileName. - // public FileInfo CopyTo(String destFileName) { if (destFileName == null) - throw new ArgumentNullException("destFileName", Environment.GetResourceString("ArgumentNull_FileName")); + throw new ArgumentNullException(nameof(destFileName), Environment.GetResourceString("ArgumentNull_FileName")); if (destFileName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destFileName"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), nameof(destFileName)); Contract.EndContractBlock(); - destFileName = File.InternalCopy(FullPath, destFileName, false, true); + destFileName = File.InternalCopy(FullPath, destFileName, false); return new FileInfo(destFileName, false); } - // Copies an existing file to a new file. If overwrite is // false, then an IOException is thrown if the destination file // already exists. If overwrite is true, the file is // overwritten. - // - // The caller must have certain FileIOPermissions. The caller must have - // Read permission to sourceFileName and Create - // and Write permissions to destFileName. - // public FileInfo CopyTo(String destFileName, bool overwrite) { if (destFileName == null) - throw new ArgumentNullException("destFileName", Environment.GetResourceString("ArgumentNull_FileName")); + throw new ArgumentNullException(nameof(destFileName), Environment.GetResourceString("ArgumentNull_FileName")); if (destFileName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destFileName"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), nameof(destFileName)); Contract.EndContractBlock(); - destFileName = File.InternalCopy(FullPath, destFileName, overwrite, true); + destFileName = File.InternalCopy(FullPath, destFileName, overwrite); return new FileInfo(destFileName, false); } @@ -271,22 +167,9 @@ namespace System.IO { // an exception. // // On NT, Delete will fail for a file that is open for normal I/O - // or a file that is memory mapped. On Win95, the file will be - // deleted irregardless of whether the file is being used. - // - // Your application must have Delete permission to the target file. - // - [System.Security.SecuritySafeCritical] + // or a file that is memory mapped. public override void Delete() { -#if FEATURE_CORECLR - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Write, DisplayPath, FullPath); - state.EnsureState(); -#else - // For security check, path should be resolved to an absolute path. - new FileIOPermission(FileIOPermissionAccess.Write, new String[] { FullPath }, false, false).Demand(); -#endif - bool r = Win32Native.DeleteFile(FullPath); if (!r) { int hr = Marshal.GetLastWin32Error(); @@ -297,25 +180,10 @@ namespace System.IO { } } - [ComVisible(false)] - public void Decrypt() - { - File.Decrypt(FullPath); - } - - [ComVisible(false)] - public void Encrypt() - { - File.Encrypt(FullPath); - } - // Tests if the given file exists. The result is true if the file // given by the specified path exists; otherwise, the result is // false. - // - // Your application must have Read permission for the target directory. public override bool Exists { - [System.Security.SecuritySafeCritical] // auto-generated get { try { if (_dataInitialised == -1) @@ -335,9 +203,6 @@ namespace System.IO { } } - - - // User must explicitly specify opening a new file or appending to one. public FileStream Open(FileMode mode) { return Open(mode, FileAccess.ReadWrite, FileShare.None); @@ -351,54 +216,28 @@ namespace System.IO { return new FileStream(FullPath, mode, access, share); } - -#if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // auto-generated -#endif public FileStream OpenRead() { return new FileStream(FullPath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, false); } - public FileStream OpenWrite() { return new FileStream(FullPath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None); } - - - - - // Moves a given file to a new location and potentially a new file name. // This method does work across volumes. - // - // The caller must have certain FileIOPermissions. The caller must - // have Read and Write permission to - // sourceFileName and Write - // permissions to destFileName. - // - [System.Security.SecuritySafeCritical] public void MoveTo(String destFileName) { if (destFileName==null) - throw new ArgumentNullException("destFileName"); + throw new ArgumentNullException(nameof(destFileName)); if (destFileName.Length==0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destFileName"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), nameof(destFileName)); Contract.EndContractBlock(); - String fullDestFileName = Path.GetFullPathInternal(destFileName); -#if FEATURE_CORECLR - FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Write | FileSecurityStateAccess.Read, DisplayPath, FullPath); - FileSecurityState destState = new FileSecurityState(FileSecurityStateAccess.Write, destFileName, fullDestFileName); - sourceState.EnsureState(); - destState.EnsureState(); -#else - new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, new String[] { FullPath }, false, false).Demand(); - FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, fullDestFileName, false, false); -#endif - + string fullDestFileName = Path.GetFullPath(destFileName); + if (!Win32Native.MoveFile(FullPath, fullDestFileName)) __Error.WinIOError(); FullPath = fullDestFileName; diff --git a/src/mscorlib/src/System/IO/FileLoadException.cs b/src/mscorlib/src/System/IO/FileLoadException.cs index fabe261..2b56c00 100644 --- a/src/mscorlib/src/System/IO/FileLoadException.cs +++ b/src/mscorlib/src/System/IO/FileLoadException.cs @@ -91,7 +91,6 @@ namespace System.IO { if (StackTrace != null) s += Environment.NewLine + StackTrace; -#if FEATURE_FUSION try { if(FusionLog!=null) @@ -107,7 +106,6 @@ namespace System.IO { { } -#endif // FEATURE_FUSION return s; } @@ -117,7 +115,6 @@ namespace System.IO { _fileName = info.GetString("FileLoad_FileName"); -#if FEATURE_FUSION try { _fusionLog = info.GetString("FileLoad_FusionLog"); @@ -126,7 +123,6 @@ namespace System.IO { { _fusionLog = null; } -#endif } private FileLoadException(String fileName, String fusionLog,int hResult) @@ -138,15 +134,10 @@ namespace System.IO { SetMessageField(); } -#if FEATURE_FUSION public String FusionLog { - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] get { return _fusionLog; } } -#endif // FEATURE_FUSION - [System.Security.SecurityCritical] // auto-generated_required public override void GetObjectData(SerializationInfo info, StreamingContext context) { // Serialize data for our base classes. base will verify info != null. base.GetObjectData(info, context); @@ -154,7 +145,6 @@ namespace System.IO { // Serialize data for this class info.AddValue("FileLoad_FileName", _fileName, typeof(String)); -#if FEATURE_FUSION try { info.AddValue("FileLoad_FusionLog", FusionLog, typeof(String)); @@ -162,10 +152,8 @@ namespace System.IO { catch (SecurityException) { } -#endif } - [System.Security.SecuritySafeCritical] // auto-generated internal static String FormatFileLoadExceptionMessage(String fileName, int hResult) { @@ -178,12 +166,10 @@ namespace System.IO { return String.Format(CultureInfo.CurrentCulture, format, fileName, message); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void GetFileLoadExceptionMessage(int hResult, StringHandleOnStack retString); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void GetMessageForHR(int hresult, StringHandleOnStack retString); diff --git a/src/mscorlib/src/System/IO/FileNotFoundException.cs b/src/mscorlib/src/System/IO/FileNotFoundException.cs index 933e4fd..8cc75f8 100644 --- a/src/mscorlib/src/System/IO/FileNotFoundException.cs +++ b/src/mscorlib/src/System/IO/FileNotFoundException.cs @@ -93,7 +93,6 @@ namespace System.IO { if (StackTrace != null) s += Environment.NewLine + StackTrace; -#if FEATURE_FUSION try { if(FusionLog!=null) @@ -109,7 +108,6 @@ namespace System.IO { { } -#endif return s; } @@ -118,7 +116,6 @@ namespace System.IO { // Base class constructor will check info != null. _fileName = info.GetString("FileNotFound_FileName"); -#if FEATURE_FUSION try { _fusionLog = info.GetString("FileNotFound_FusionLog"); @@ -127,7 +124,6 @@ namespace System.IO { { _fusionLog = null; } -#endif } private FileNotFoundException(String fileName, String fusionLog,int hResult) @@ -139,15 +135,10 @@ namespace System.IO { SetMessageField(); } -#if FEATURE_FUSION public String FusionLog { - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] get { return _fusionLog; } } -#endif - [System.Security.SecurityCritical] // auto-generated_required public override void GetObjectData(SerializationInfo info, StreamingContext context) { // Serialize data for our base classes. base will verify info != null. base.GetObjectData(info, context); @@ -155,7 +146,6 @@ namespace System.IO { // Serialize data for this class info.AddValue("FileNotFound_FileName", _fileName, typeof(String)); -#if FEATURE_FUSION try { info.AddValue("FileNotFound_FusionLog", FusionLog, typeof(String)); @@ -163,7 +153,6 @@ namespace System.IO { catch (SecurityException) { } -#endif } } } diff --git a/src/mscorlib/src/System/IO/FileSecurityState.cs b/src/mscorlib/src/System/IO/FileSecurityState.cs deleted file mode 100644 index 249848a..0000000 --- a/src/mscorlib/src/System/IO/FileSecurityState.cs +++ /dev/null @@ -1,133 +0,0 @@ -// 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. - -/*============================================================ -** -** Enum: FileSecurityState -** -** -** -** -** Purpose: Determines whether file system access is safe -** -** -===========================================================*/ - -using System; -using System.Diagnostics.Contracts; -using System.IO; -using System.Security; -using System.Security.Permissions; - -namespace System.IO -{ - [SecurityCritical] - [System.Runtime.CompilerServices.FriendAccessAllowed] - internal class FileSecurityState : SecurityState - { -#if !PLATFORM_UNIX - private static readonly char[] m_illegalCharacters = { '?', '*' }; -#endif // !PLATFORM_UNIX - - private FileSecurityStateAccess m_access; - private String m_userPath; - private String m_canonicalizedPath; - - // default ctor needed for security rule consistency - [SecurityCritical] - private FileSecurityState() - { - } - - internal FileSecurityState(FileSecurityStateAccess access, String path) - { - if (path == null) - { - throw new ArgumentNullException("path"); - } - VerifyAccess(access); - m_access = access; - m_userPath = path; - if (path.Equals(String.Empty, StringComparison.OrdinalIgnoreCase)) - { - m_canonicalizedPath = String.Empty; - } - else - { - VerifyPath(path); - m_canonicalizedPath = System.IO.Path.GetFullPathInternal(path); - } - } - - // slight perf savings for trusted internal callers - internal FileSecurityState(FileSecurityStateAccess access, String path, String canonicalizedPath) - { - VerifyAccess(access); - VerifyPath(path); - VerifyPath(canonicalizedPath); - - m_access = access; - m_userPath = path; - m_canonicalizedPath = canonicalizedPath; - } - - internal FileSecurityStateAccess Access - { - get - { - return m_access; - } - } - - public String Path { - [System.Runtime.CompilerServices.FriendAccessAllowed] - get - { - return m_canonicalizedPath; - } - } - - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif - public override void EnsureState() - { - // this is the case for empty string machine name, etc - if (String.Empty.Equals(m_canonicalizedPath)) - return; - - if (!IsStateAvailable()) - { - throw new SecurityException(Environment.GetResourceString("FileSecurityState_OperationNotPermitted", (m_userPath == null) ? String.Empty : m_userPath)); - } - } - - internal static FileSecurityStateAccess ToFileSecurityState(FileIOPermissionAccess access) - { - Contract.Requires((access & ~FileIOPermissionAccess.AllAccess) == 0); - return (FileSecurityStateAccess)access; // flags are identical; just cast - } - - private static void VerifyAccess(FileSecurityStateAccess access) - { - if ((access & ~FileSecurityStateAccess.AllAccess) != 0) - throw new ArgumentOutOfRangeException("access", Environment.GetResourceString("Arg_EnumIllegalVal")); - } - - private static void VerifyPath(String path) - { - if (path != null) - { - path = path.Trim(); - -#if !PLATFORM_UNIX - if (!PathInternal.IsDevice(path) && PathInternal.HasInvalidVolumeSeparator(path)) - throw new ArgumentException(Environment.GetResourceString("Argument_PathFormatNotSupported")); -#endif - - System.IO.Path.CheckInvalidPathChars(path, checkAdditional: true); - } - } - } -} diff --git a/src/mscorlib/src/System/IO/FileSecurityStateAccess.cs b/src/mscorlib/src/System/IO/FileSecurityStateAccess.cs deleted file mode 100644 index b6378c6..0000000 --- a/src/mscorlib/src/System/IO/FileSecurityStateAccess.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. -// See the LICENSE file in the project root for more information. - -/*============================================================ -** -** Enum: FileSecurityStateAccess -** -** -** -** -** Purpose: FileSecurityState enum -** -** -===========================================================*/ - -using System; - -namespace System.IO -{ - [Flags] - internal enum FileSecurityStateAccess - { - NoAccess = 0, - Read = 1, - Write = 2, - Append = 4, - PathDiscovery = 8, - AllAccess = 15 - } -} - diff --git a/src/mscorlib/src/System/IO/FileStream.cs b/src/mscorlib/src/System/IO/FileStream.cs deleted file mode 100644 index deef30c..0000000 --- a/src/mscorlib/src/System/IO/FileStream.cs +++ /dev/null @@ -1,2695 +0,0 @@ -// 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. - -/*============================================================ -** -** -** -** -** -** Purpose: Exposes a Stream around a file, with full -** synchronous and asychronous support, and buffering. -** -** -===========================================================*/ -using System; -using Microsoft.Win32; -using Microsoft.Win32.SafeHandles; -using System.Security; -#if FEATURE_MACL -using System.Security.AccessControl; -#endif -using System.Security.Permissions; -using System.Threading; -using System.Threading.Tasks; -using System.Runtime.InteropServices; -#if FEATURE_REMOTING -using System.Runtime.Remoting.Messaging; -#endif -using System.Runtime.CompilerServices; -using System.Globalization; -using System.Runtime.Versioning; -using System.Diagnostics.Contracts; -using System.Diagnostics.Tracing; - -/* - * FileStream supports different modes of accessing the disk - async mode - * and sync mode. They are two completely different codepaths in the - * sync & async methods (ie, Read/Write vs. BeginRead/BeginWrite). File - * handles in NT can be opened in only sync or overlapped (async) mode, - * and we have to deal with this pain. Stream has implementations of - * the sync methods in terms of the async ones, so we'll - * call through to our base class to get those methods when necessary. - * - * Also buffering is added into FileStream as well. Folded in the - * code from BufferedStream, so all the comments about it being mostly - * aggressive (and the possible perf improvement) apply to FileStream as - * well. Also added some buffering to the async code paths. - * - * Class Invariants: - * The class has one buffer, shared for reading & writing. It can only be - * used for one or the other at any point in time - not both. The following - * should be true: - * 0 <= _readPos <= _readLen < _bufferSize - * 0 <= _writePos < _bufferSize - * _readPos == _readLen && _readPos > 0 implies the read buffer is valid, - * but we're at the end of the buffer. - * _readPos == _readLen == 0 means the read buffer contains garbage. - * Either _writePos can be greater than 0, or _readLen & _readPos can be - * greater than zero, but neither can be greater than zero at the same time. - * - */ - -namespace System.IO { - - // This is an internal object implementing IAsyncResult with fields - // for all of the relevant data necessary to complete the IO operation. - // This is used by AsyncFSCallback and all of the async methods. - // We should probably make this a nested type of FileStream. But - // I don't know how to define a nested class in mscorlib.h - - unsafe internal sealed class FileStreamAsyncResult : IAsyncResult - { - // README: - // If you modify the order of these fields, make sure to update - // the native VM definition of this class as well!!! - // User code callback - private AsyncCallback _userCallback; - private Object _userStateObject; - private ManualResetEvent _waitHandle; - [System.Security.SecurityCritical] - private SafeFileHandle _handle; // For cancellation support. - - [SecurityCritical] - private NativeOverlapped* _overlapped; - internal NativeOverlapped* OverLapped { [SecurityCritical]get { return _overlapped; } } - internal bool IsAsync { [SecuritySafeCritical]get { return _overlapped != null; } } - - - internal int _EndXxxCalled; // Whether we've called EndXxx already. - private int _numBytes; // number of bytes read OR written - internal int NumBytes { get { return _numBytes; } } - - private int _errorCode; - internal int ErrorCode { get { return _errorCode; } } - - private int _numBufferedBytes; - internal int NumBufferedBytes { get { return _numBufferedBytes; } } - - internal int NumBytesRead { get { return _numBytes + _numBufferedBytes; } } - - private bool _isWrite; // Whether this is a read or a write - internal bool IsWrite { get { return _isWrite; } } - - private bool _isComplete; // Value for IsCompleted property - private bool _completedSynchronously; // Which thread called callback - - // The NativeOverlapped struct keeps a GCHandle to this IAsyncResult object. - // So if the user doesn't call EndRead/EndWrite, a finalizer won't help because - // it'll never get called. - - // Overlapped class will take care of the async IO operations in progress - // when an appdomain unload occurs. - - [System.Security.SecurityCritical] // auto-generated - private unsafe static IOCompletionCallback s_IOCallback; - - [SecuritySafeCritical] - internal FileStreamAsyncResult( - int numBufferedBytes, - byte[] bytes, - SafeFileHandle handle, - AsyncCallback userCallback, - Object userStateObject, - bool isWrite) - { - _userCallback = userCallback; - _userStateObject = userStateObject; - _isWrite = isWrite; - _numBufferedBytes = numBufferedBytes; - _handle = handle; - - // For Synchronous IO, I could go with either a callback and using - // the managed Monitor class, or I could create a handle and wait on it. - ManualResetEvent waitHandle = new ManualResetEvent(false); - _waitHandle = waitHandle; - - // Create a managed overlapped class - // We will set the file offsets later - Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, this); - - // Pack the Overlapped class, and store it in the async result - if (userCallback != null) - { - var ioCallback = s_IOCallback; // cached static delegate; delay initialized due to it being SecurityCritical - if (ioCallback == null) s_IOCallback = ioCallback = new IOCompletionCallback(AsyncFSCallback); - _overlapped = overlapped.Pack(ioCallback, bytes); - } - else - { - _overlapped = overlapped.UnsafePack(null, bytes); - } - - Contract.Assert(_overlapped != null, "Did Overlapped.Pack or Overlapped.UnsafePack just return a null?"); - } - - internal static FileStreamAsyncResult CreateBufferedReadResult(int numBufferedBytes, AsyncCallback userCallback, Object userStateObject, bool isWrite) - { - FileStreamAsyncResult asyncResult = new FileStreamAsyncResult(numBufferedBytes, userCallback, userStateObject, isWrite); - asyncResult.CallUserCallback(); - return asyncResult; - } - - // This creates a synchronous Async Result. We should consider making this a separate class and maybe merge it with - // System.IO.Stream.SynchronousAsyncResult - private FileStreamAsyncResult(int numBufferedBytes, AsyncCallback userCallback, Object userStateObject, bool isWrite) - { - _userCallback = userCallback; - _userStateObject = userStateObject; - _isWrite = isWrite; - _numBufferedBytes = numBufferedBytes; - } - - public Object AsyncState - { - get { return _userStateObject; } - } - - public bool IsCompleted - { - get { return _isComplete; } - } - - public WaitHandle AsyncWaitHandle - { - [System.Security.SecuritySafeCritical] // auto-generated - get { - // Consider uncommenting this someday soon - the EventHandle - // in the Overlapped struct is really useless half of the - // time today since the OS doesn't signal it. If users call - // EndXxx after the OS call happened to complete, there's no - // reason to create a synchronization primitive here. Fixing - // this will save us some perf, assuming we can correctly - // initialize the ManualResetEvent. - if (_waitHandle == null) { - ManualResetEvent mre = new ManualResetEvent(false); - if (_overlapped != null && _overlapped->EventHandle != IntPtr.Zero) { - mre.SafeWaitHandle = new SafeWaitHandle(_overlapped->EventHandle, true); - } - - // make sure only one thread sets _waitHandle - if (Interlocked.CompareExchange(ref _waitHandle, mre, null) == null) { - if (_isComplete) - _waitHandle.Set(); - } - else { - // There's a slight but acceptable race condition if we weren't - // the thread that set _waitHandle and this code path - // returns before the code in the if statement - // executes (on the other thread). However, the - // caller is waiting for the wait handle to be set, - // which will still happen. - mre.Close(); - } - } - return _waitHandle; - } - } - - // Returns true iff the user callback was called by the thread that - // called BeginRead or BeginWrite. If we use an async delegate or - // threadpool thread internally, this will be false. This is used - // by code to determine whether a successive call to BeginRead needs - // to be done on their main thread or in their callback to avoid a - // stack overflow on many reads or writes. - public bool CompletedSynchronously - { - get { return _completedSynchronously; } - } - - private void CallUserCallbackWorker() - { - _isComplete = true; - - // ensure _isComplete is set before reading _waitHandle - Thread.MemoryBarrier(); - if (_waitHandle != null) - _waitHandle.Set(); - - _userCallback(this); - } - - internal void CallUserCallback() - { - // Convenience method for me, since I have to do this in a number - // of places in the buffering code for fake IAsyncResults. - // AsyncFSCallback intentionally does not use this method. - - if (_userCallback != null) { - // Call user's callback on a threadpool thread. - // Set completedSynchronously to false, since it's on another - // thread, not the main thread. - _completedSynchronously = false; - ThreadPool.QueueUserWorkItem(state => ((FileStreamAsyncResult)state).CallUserCallbackWorker(), this); - } - else { - _isComplete = true; - - // ensure _isComplete is set before reading _waitHandle - Thread.MemoryBarrier(); - if (_waitHandle != null) - _waitHandle.Set(); - } - } - - [SecurityCritical] - internal void ReleaseNativeResource() - { - // Free memory & GC handles. - if (this._overlapped != null) - Overlapped.Free(_overlapped); - } - - internal void Wait() - { - if (_waitHandle != null) - { - // We must block to ensure that AsyncFSCallback has completed, - // and we should close the WaitHandle in here. AsyncFSCallback - // and the hand-ported imitation version in COMThreadPool.cpp - // are the only places that set this event. - try - { - _waitHandle.WaitOne(); - Contract.Assert(_isComplete == true, "FileStreamAsyncResult::Wait - AsyncFSCallback didn't set _isComplete to true!"); - } - finally - { - _waitHandle.Close(); - } - } - } - - // When doing IO asynchronously (ie, _isAsync==true), this callback is - // called by a free thread in the threadpool when the IO operation - // completes. - [System.Security.SecurityCritical] // auto-generated - unsafe private static void AsyncFSCallback(uint errorCode, uint numBytes, NativeOverlapped* pOverlapped) - { - BCLDebug.Log(String.Format("AsyncFSCallback called. errorCode: " + errorCode + " numBytes: " + numBytes)); - - // Unpack overlapped - Overlapped overlapped = Overlapped.Unpack(pOverlapped); - // Free the overlapped struct in EndRead/EndWrite. - - // Extract async result from overlapped - FileStreamAsyncResult asyncResult = - (FileStreamAsyncResult)overlapped.AsyncResult; - asyncResult._numBytes = (int)numBytes; - - if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.ThreadTransfer)) - FrameworkEventSource.Log.ThreadTransferReceive((long)(asyncResult.OverLapped), 2, string.Empty); - - // Handle reading from & writing to closed pipes. While I'm not sure - // this is entirely necessary anymore, maybe it's possible for - // an async read on a pipe to be issued and then the pipe is closed, - // returning this error. This may very well be necessary. - if (errorCode == FileStream.ERROR_BROKEN_PIPE || errorCode == FileStream.ERROR_NO_DATA) - errorCode = 0; - - asyncResult._errorCode = (int)errorCode; - - // Call the user-provided callback. It can and often should - // call EndRead or EndWrite. There's no reason to use an async - // delegate here - we're already on a threadpool thread. - // IAsyncResult's completedSynchronously property must return - // false here, saying the user callback was called on another thread. - asyncResult._completedSynchronously = false; - asyncResult._isComplete = true; - - // ensure _isComplete is set before reading _waitHandle - Thread.MemoryBarrier(); - - // The OS does not signal this event. We must do it ourselves. - ManualResetEvent wh = asyncResult._waitHandle; - if (wh != null) - { - Contract.Assert(!wh.SafeWaitHandle.IsClosed, "ManualResetEvent already closed!"); - bool r = wh.Set(); - Contract.Assert(r, "ManualResetEvent::Set failed!"); - if (!r) __Error.WinIOError(); - } - - AsyncCallback userCallback = asyncResult._userCallback; - if (userCallback != null) - userCallback(asyncResult); - } - - [SecuritySafeCritical] - [HostProtection(ExternalThreading = true)] - internal void Cancel() - { - Contract.Assert(_handle != null, "_handle should not be null."); - Contract.Assert(_overlapped != null, "Cancel should only be called on true asynchronous FileStreamAsyncResult, i.e. _overlapped is not null"); - - if (IsCompleted) - return; - - if (_handle.IsInvalid) - return; - - bool r = Win32Native.CancelIoEx(_handle, _overlapped); - if (!r) - { - int errorCode = Marshal.GetLastWin32Error(); - - // ERROR_NOT_FOUND is returned if CancelIoEx cannot find the request to cancel. - // This probably means that the IO operation has completed. - if (errorCode != Win32Native.ERROR_NOT_FOUND) - __Error.WinIOError(errorCode, String.Empty); - } - } - } - - [ComVisible(true)] - public class FileStream : Stream - { - internal const int DefaultBufferSize = 4096; - - private byte[] _buffer; // Shared read/write buffer. Alloc on first use. - private String _fileName; // Fully qualified file name. - private bool _isAsync; // Whether we opened the handle for overlapped IO - private bool _canRead; - private bool _canWrite; - private bool _canSeek; - private bool _exposedHandle; // Could other code be using this handle? - private bool _isPipe; // Whether to disable async buffering code. - private int _readPos; // Read pointer within shared buffer. - private int _readLen; // Number of bytes read in buffer from file. - private int _writePos; // Write pointer within shared buffer. - private int _bufferSize; // Length of internal buffer, if it's allocated. - [System.Security.SecurityCritical] // auto-generated - private SafeFileHandle _handle; - private long _pos; // Cache current location in the file. - private long _appendStart;// When appending, prevent overwriting file. - private static AsyncCallback s_endReadTask; - private static AsyncCallback s_endWriteTask; - private static Action s_cancelReadHandler; - private static Action s_cancelWriteHandler; - - //This exists only to support IsolatedStorageFileStream. - //Any changes to FileStream must include the corresponding changes in IsolatedStorage. - internal FileStream() { - } -#if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] - public FileStream(String path, FileMode mode) - : this(path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.Read, DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false, false, true) { - } - - [System.Security.SecuritySafeCritical] - public FileStream(String path, FileMode mode, FileAccess access) - : this(path, mode, access, FileShare.Read, DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false, false, true) { - } - - [System.Security.SecuritySafeCritical] - public FileStream(String path, FileMode mode, FileAccess access, FileShare share) - : this(path, mode, access, share, DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false, false, true) { - } - - [System.Security.SecuritySafeCritical] - public FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize) - : this(path, mode, access, share, bufferSize, FileOptions.None, Path.GetFileName(path), false, false, true) - { - } - -#else // FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // auto-generated - public FileStream(String path, FileMode mode) - : this(path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.Read, DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false) { - } - - [System.Security.SecuritySafeCritical] // auto-generated - public FileStream(String path, FileMode mode, FileAccess access) - : this(path, mode, access, FileShare.Read, DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false) { - } - - [System.Security.SecuritySafeCritical] // auto-generated - public FileStream(String path, FileMode mode, FileAccess access, FileShare share) - : this(path, mode, access, share, DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false) { - } - - [System.Security.SecuritySafeCritical] // auto-generated - public FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize) - : this(path, mode, access, share, bufferSize, FileOptions.None, Path.GetFileName(path), false) - { - } -#endif // FEATURE_CORECLR - - [System.Security.SecuritySafeCritical] // auto-generated - public FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options) - : this(path, mode, access, share, bufferSize, options, Path.GetFileName(path), false) - { - } - - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif - public FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync) - : this(path, mode, access, share, bufferSize, (useAsync ? FileOptions.Asynchronous : FileOptions.None), Path.GetFileName(path), false) - { - } - -#if FEATURE_MACL - // This constructor is done differently to avoid loading a few more - // classes, and more importantly, to build correctly on Rotor. - [System.Security.SecuritySafeCritical] // auto-generated - public FileStream(String path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options, FileSecurity fileSecurity) - { - Object pinningHandle; - Win32Native.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share, fileSecurity, out pinningHandle); - try { - Init(path, mode, (FileAccess)0, (int)rights, true, share, bufferSize, options, secAttrs, Path.GetFileName(path), false, false, false); - } - finally { - if (pinningHandle != null) { - GCHandle pinHandle = (GCHandle) pinningHandle; - pinHandle.Free(); - } - } - } - - [System.Security.SecuritySafeCritical] // auto-generated - public FileStream(String path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options) - { - Win32Native.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share); - Init(path, mode, (FileAccess)0, (int)rights, true, share, bufferSize, options, secAttrs, Path.GetFileName(path), false, false, false); - } -#endif - - [System.Security.SecurityCritical] // auto-generated - internal FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, String msgPath, bool bFromProxy) - { - Win32Native.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share); - Init(path, mode, access, 0, false, share, bufferSize, options, secAttrs, msgPath, bFromProxy, false, false); - } - - [System.Security.SecurityCritical] - internal FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, String msgPath, bool bFromProxy, bool useLongPath) - { - Win32Native.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share); - Init(path, mode, access, 0, false, share, bufferSize, options, secAttrs, msgPath, bFromProxy, useLongPath, false); - } - - [System.Security.SecurityCritical] - internal FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, String msgPath, bool bFromProxy, bool useLongPath, bool checkHost) - { - Win32Native.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share); - Init(path, mode, access, 0, false, share, bufferSize, options, secAttrs, msgPath, bFromProxy, useLongPath, checkHost); - } - - // AccessControl namespace is not defined in Rotor - [System.Security.SecuritySafeCritical] - private void Init(String path, FileMode mode, FileAccess access, int rights, bool useRights, FileShare share, int bufferSize, FileOptions options, Win32Native.SECURITY_ATTRIBUTES secAttrs, String msgPath, bool bFromProxy, bool useLongPath, bool checkHost) - { - if (path == null) - throw new ArgumentNullException("path", Environment.GetResourceString("ArgumentNull_Path")); - if (path.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); - Contract.EndContractBlock(); - -#if FEATURE_MACL - FileSystemRights fileSystemRights = (FileSystemRights)rights; -#endif - // msgPath must be safe to hand back to untrusted code. - - _fileName = msgPath; // To handle odd cases of finalizing partially constructed objects. - _exposedHandle = false; - - // don't include inheritable in our bounds check for share - FileShare tempshare = share & ~FileShare.Inheritable; - String badArg = null; - - if (mode < FileMode.CreateNew || mode > FileMode.Append) - badArg = "mode"; - else if (!useRights && (access < FileAccess.Read || access > FileAccess.ReadWrite)) - badArg = "access"; -#if FEATURE_MACL - else if (useRights && (fileSystemRights < FileSystemRights.ReadData || fileSystemRights > FileSystemRights.FullControl)) - badArg = "rights"; -#endif - else if (tempshare < FileShare.None || tempshare > (FileShare.ReadWrite | FileShare.Delete)) - badArg = "share"; - - if (badArg != null) - throw new ArgumentOutOfRangeException(badArg, Environment.GetResourceString("ArgumentOutOfRange_Enum")); - - // NOTE: any change to FileOptions enum needs to be matched here in the error validation - if (options != FileOptions.None && (options & ~(FileOptions.WriteThrough | FileOptions.Asynchronous | FileOptions.RandomAccess | FileOptions.DeleteOnClose | FileOptions.SequentialScan | FileOptions.Encrypted | (FileOptions)0x20000000 /* NoBuffering */)) != 0) - throw new ArgumentOutOfRangeException("options", Environment.GetResourceString("ArgumentOutOfRange_Enum")); - - if (bufferSize <= 0) - throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); - - // Write access validation -#if FEATURE_MACL - if ((!useRights && (access & FileAccess.Write) == 0) - || (useRights && (fileSystemRights & FileSystemRights.Write) == 0)) -#else - if (!useRights && (access & FileAccess.Write) == 0) -#endif //FEATURE_MACL - { - if (mode==FileMode.Truncate || mode==FileMode.CreateNew || mode==FileMode.Create || mode==FileMode.Append) { - // No write access - if (!useRights) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFileMode&AccessCombo", mode, access)); -#if FEATURE_MACL - else - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFileMode&RightsCombo", mode, fileSystemRights)); -#endif //FEATURE_MACL - } - } - -#if FEATURE_MACL - // FileMode.Truncate only works with GENERIC_WRITE (FileAccess.Write), source:MSDN - // For backcomp use FileAccess.Write when FileSystemRights.Write is specified - if (useRights && (mode == FileMode.Truncate)) { - if (fileSystemRights == FileSystemRights.Write) { - useRights = false; - access = FileAccess.Write; - } - else { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFileModeTruncate&RightsCombo", mode, fileSystemRights)); - } - } -#endif - - int fAccess; - if (!useRights) { - fAccess = access == FileAccess.Read? GENERIC_READ: - access == FileAccess.Write? GENERIC_WRITE: - GENERIC_READ | GENERIC_WRITE; - } - else { - fAccess = rights; - } - - // Get absolute path - Security needs this to prevent something - // like trying to create a file in c:\tmp with the name - // "..\WinNT\System32\ntoskrnl.exe". Store it for user convenience. - int maxPath = useLongPath ? Path.MaxLongPath : Path.MaxPath; - String filePath = Path.NormalizePath(path, true, maxPath); - - _fileName = filePath; - - // Prevent access to your disk drives as raw block devices. - if (filePath.StartsWith("\\\\.\\", StringComparison.Ordinal)) - throw new ArgumentException(Environment.GetResourceString("Arg_DevicesNotSupported")); - - // In 4.0, we always construct a FileIOPermission object below. - // If filePath contained a ':', we would throw a NotSupportedException in - // System.Security.Util.StringExpressionSet.CanonicalizePath. - // If filePath contained other illegal characters, we would throw an ArgumentException in - // FileIOPermission.CheckIllegalCharacters. - // In 4.5 we on longer construct the FileIOPermission object in full trust. - // To preserve the 4.0 behavior we do an explicit check for ':' here and also call Path.CheckInvalidPathChars. - // Note that we need to call CheckInvalidPathChars before checking for ':' because that is what FileIOPermission does. - - Path.CheckInvalidPathChars(filePath, true); - -#if !PLATFORM_UNIX - if (filePath.IndexOf( ':', 2 ) != -1) - throw new NotSupportedException( Environment.GetResourceString( "Argument_PathFormatNotSupported" ) ); -#endif // !PLATFORM_UNIX - - bool read = false; - -#if FEATURE_MACL - if ((!useRights && (access & FileAccess.Read) != 0) || (useRights && (fileSystemRights & FileSystemRights.ReadAndExecute) != 0)) -#else - if (!useRights && (access & FileAccess.Read) != 0) -#endif //FEATURE_MACL - { - if (mode == FileMode.Append) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidAppendMode")); - else - read = true; - } - - // All demands in full trust domains are no-ops, so skip -#if FEATURE_CAS_POLICY - if (!CodeAccessSecurityEngine.QuickCheckForAllDemands()) -#endif // FEATURE_CAS_POLICY - { - // Build up security permissions required, as well as validate we - // have a sensible set of parameters. IE, creating a brand new file - // for reading doesn't make much sense. - FileIOPermissionAccess secAccess = FileIOPermissionAccess.NoAccess; - - if (read) - { - Contract.Assert(mode != FileMode.Append); - secAccess = secAccess | FileIOPermissionAccess.Read; - } - - // I can't think of any combos of FileMode we should disallow if we - // don't have read access. Writing would pretty much always be valid - // in those cases. - - // For any FileSystemRights other than ReadAndExecute, demand Write permission - // This is probably bit overkill for TakeOwnership etc but we don't have any - // matching FileIOPermissionAccess to demand. It is better that we ask for Write permission. - -#if FEATURE_MACL - // FileMode.OpenOrCreate & FileSystemRights.Synchronize can create 0-byte file; demand write - if ((!useRights && (access & FileAccess.Write) != 0) - || (useRights && (fileSystemRights & (FileSystemRights.Write | FileSystemRights.Delete - | FileSystemRights.DeleteSubdirectoriesAndFiles - | FileSystemRights.ChangePermissions - | FileSystemRights.TakeOwnership)) != 0) - || (useRights && ((fileSystemRights & FileSystemRights.Synchronize) != 0) - && mode==FileMode.OpenOrCreate) - ) -#else - if (!useRights && (access & FileAccess.Write) != 0) -#endif //FEATURE_MACL - { - if (mode==FileMode.Append) - secAccess = secAccess | FileIOPermissionAccess.Append; - else - secAccess = secAccess | FileIOPermissionAccess.Write; - } - -#if FEATURE_MACL - bool specifiedAcl; - unsafe { - specifiedAcl = secAttrs != null && secAttrs.pSecurityDescriptor != null; - } - - AccessControlActions control = specifiedAcl ? AccessControlActions.Change : AccessControlActions.None; - new FileIOPermission(secAccess, control, new String[] { filePath }, false, false).Demand(); -#else -#if FEATURE_CORECLR - if (checkHost) { - FileSecurityState state = new FileSecurityState(FileSecurityState.ToFileSecurityState(secAccess), path, filePath); - state.EnsureState(); - } -#else - new FileIOPermission(secAccess, new String[] { filePath }, false, false).Demand(); -#endif // FEATURE_CORECLR -#endif - } - - // Our Inheritable bit was stolen from Windows, but should be set in - // the security attributes class. Don't leave this bit set. - share &= ~FileShare.Inheritable; - - bool seekToEnd = (mode==FileMode.Append); - // Must use a valid Win32 constant here... - if (mode == FileMode.Append) - mode = FileMode.OpenOrCreate; - - // WRT async IO, do the right thing for whatever platform we're on. - // This way, someone can easily write code that opens a file - // asynchronously no matter what their platform is. - if ((options & FileOptions.Asynchronous) != 0) - _isAsync = true; - else - options &= ~FileOptions.Asynchronous; - - int flagsAndAttributes = (int) options; - -#if !PLATFORM_UNIX - // For mitigating local elevation of privilege attack through named pipes - // make sure we always call CreateFile with SECURITY_ANONYMOUS so that the - // named pipe server can't impersonate a high privileged client security context - flagsAndAttributes |= (Win32Native.SECURITY_SQOS_PRESENT | Win32Native.SECURITY_ANONYMOUS); -#endif - - // Don't pop up a dialog for reading from an emtpy floppy drive - int oldMode = Win32Native.SetErrorMode(Win32Native.SEM_FAILCRITICALERRORS); - try { - String tempPath = filePath; - if (useLongPath) - tempPath = Path.AddLongPathPrefix(tempPath); - _handle = Win32Native.SafeCreateFile(tempPath, fAccess, share, secAttrs, mode, flagsAndAttributes, IntPtr.Zero); - - if (_handle.IsInvalid) { - // Return a meaningful exception, using the RELATIVE path to - // the file to avoid returning extra information to the caller - // unless they have path discovery permission, in which case - // the full path is fine & useful. - - // NT5 oddity - when trying to open "C:\" as a FileStream, - // we usually get ERROR_PATH_NOT_FOUND from the OS. We should - // probably be consistent w/ every other directory. - int errorCode = Marshal.GetLastWin32Error(); - if (errorCode==__Error.ERROR_PATH_NOT_FOUND && filePath.Equals(Directory.InternalGetDirectoryRoot(filePath))) - errorCode = __Error.ERROR_ACCESS_DENIED; - - // We need to give an exception, and preferably it would include - // the fully qualified path name. Do security check here. If - // we fail, give back the msgPath, which should not reveal much. - // While this logic is largely duplicated in - // __Error.WinIOError, we need this for - // IsolatedStorageFileStream. - bool canGiveFullPath = false; - - if (!bFromProxy) - { - try { -#if !FEATURE_CORECLR - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { _fileName }, false, false ).Demand(); -#endif - canGiveFullPath = true; - } - catch(SecurityException) {} - } - - if (canGiveFullPath) - __Error.WinIOError(errorCode, _fileName); - else - __Error.WinIOError(errorCode, msgPath); - } - } - finally { - Win32Native.SetErrorMode(oldMode); - } - - // Disallow access to all non-file devices from the FileStream - // constructors that take a String. Everyone else can call - // CreateFile themselves then use the constructor that takes an - // IntPtr. Disallows "con:", "com1:", "lpt1:", etc. - int fileType = Win32Native.GetFileType(_handle); - if (fileType != Win32Native.FILE_TYPE_DISK) { - _handle.Close(); - throw new NotSupportedException(Environment.GetResourceString("NotSupported_FileStreamOnNonFiles")); - } - - // This is necessary for async IO using IO Completion ports via our - // managed Threadpool API's. This (theoretically) calls the OS's - // BindIoCompletionCallback method, and passes in a stub for the - // LPOVERLAPPED_COMPLETION_ROUTINE. This stub looks at the Overlapped - // struct for this request and gets a delegate to a managed callback - // from there, which it then calls on a threadpool thread. (We allocate - // our native OVERLAPPED structs 2 pointers too large and store EE state - // & GC handles there, one to an IAsyncResult, the other to a delegate.) - if (_isAsync) { - bool b = false; - // BindHandle requires UnmanagedCode permission -#pragma warning disable 618 - new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); -#pragma warning restore 618 - try { - b = ThreadPool.BindHandle(_handle); - } - finally { - CodeAccessPermission.RevertAssert(); - if (!b) { - // We should close the handle so that the handle is not open until SafeFileHandle GC - Contract.Assert(!_exposedHandle, "Are we closing handle that we exposed/not own, how?"); - _handle.Close(); - } - } - if (!b) - throw new IOException(Environment.GetResourceString("IO.IO_BindHandleFailed")); - } - - if (!useRights) { - _canRead = (access & FileAccess.Read) != 0; - _canWrite = (access & FileAccess.Write) != 0; - } -#if FEATURE_MACL - else { - _canRead = (fileSystemRights & FileSystemRights.ReadData) != 0; - _canWrite = ((fileSystemRights & FileSystemRights.WriteData) != 0) - || ((fileSystemRights & FileSystemRights.AppendData) != 0); - } -#endif //FEATURE_MACL - - _canSeek = true; - _isPipe = false; - _pos = 0; - _bufferSize = bufferSize; - _readPos = 0; - _readLen = 0; - _writePos = 0; - - // For Append mode... - if (seekToEnd) { - _appendStart = SeekCore(0, SeekOrigin.End); - } - else { - _appendStart = -1; - } - } - - [Obsolete("This constructor has been deprecated. Please use new FileStream(SafeFileHandle handle, FileAccess access) instead. http://go.microsoft.com/fwlink/?linkid=14202")] - public FileStream(IntPtr handle, FileAccess access) - : this(handle, access, true, DefaultBufferSize, false) { - } - - [Obsolete("This constructor has been deprecated. Please use new FileStream(SafeFileHandle handle, FileAccess access) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")] - public FileStream(IntPtr handle, FileAccess access, bool ownsHandle) - : this(handle, access, ownsHandle, DefaultBufferSize, false) { - } - - [Obsolete("This constructor has been deprecated. Please use new FileStream(SafeFileHandle handle, FileAccess access, int bufferSize) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")] - public FileStream(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize) - : this(handle, access, ownsHandle, bufferSize, false) { - } - - // We explicitly do a Demand, not a LinkDemand here. - [System.Security.SecuritySafeCritical] // auto-generated - [Obsolete("This constructor has been deprecated. Please use new FileStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")] -#pragma warning disable 618 - [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] -#pragma warning restore 618 - public FileStream(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize, bool isAsync) - : this(new SafeFileHandle(handle, ownsHandle), access, bufferSize, isAsync) { - } - - [System.Security.SecuritySafeCritical] // auto-generated - public FileStream(SafeFileHandle handle, FileAccess access) - : this(handle, access, DefaultBufferSize, false) { - } - - [System.Security.SecuritySafeCritical] // auto-generated - public FileStream(SafeFileHandle handle, FileAccess access, int bufferSize) - : this(handle, access, bufferSize, false) { - } - - [System.Security.SecuritySafeCritical] // auto-generated -#pragma warning disable 618 - [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] -#pragma warning restore 618 - public FileStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) { - // To ensure we don't leak a handle, put it in a SafeFileHandle first - if (handle.IsInvalid) - throw new ArgumentException(Environment.GetResourceString("Arg_InvalidHandle"), "handle"); - Contract.EndContractBlock(); - - _handle = handle; - _exposedHandle = true; - - // Now validate arguments. - if (access < FileAccess.Read || access > FileAccess.ReadWrite) - throw new ArgumentOutOfRangeException("access", Environment.GetResourceString("ArgumentOutOfRange_Enum")); - if (bufferSize <= 0) - throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); - - int handleType = Win32Native.GetFileType(_handle); - Contract.Assert(handleType == Win32Native.FILE_TYPE_DISK || handleType == Win32Native.FILE_TYPE_PIPE || handleType == Win32Native.FILE_TYPE_CHAR, "FileStream was passed an unknown file type!"); - _isAsync = isAsync; - _canRead = 0 != (access & FileAccess.Read); - _canWrite = 0 != (access & FileAccess.Write); - _canSeek = handleType == Win32Native.FILE_TYPE_DISK; - _bufferSize = bufferSize; - _readPos = 0; - _readLen = 0; - _writePos = 0; - _fileName = null; - _isPipe = handleType == Win32Native.FILE_TYPE_PIPE; - - // This is necessary for async IO using IO Completion ports via our - // managed Threadpool API's. This calls the OS's - // BindIoCompletionCallback method, and passes in a stub for the - // LPOVERLAPPED_COMPLETION_ROUTINE. This stub looks at the Overlapped - // struct for this request and gets a delegate to a managed callback - // from there, which it then calls on a threadpool thread. (We allocate - // our native OVERLAPPED structs 2 pointers too large and store EE - // state & a handle to a delegate there.) -#if !FEATURE_CORECLR - if (_isAsync) { - bool b = false; - try { - b = ThreadPool.BindHandle(_handle); - } - catch (ApplicationException) { - // If you passed in a synchronous handle and told us to use - // it asynchronously, throw here. - throw new ArgumentException(Environment.GetResourceString("Arg_HandleNotAsync")); - } - if (!b) { - throw new IOException(Environment.GetResourceString("IO.IO_BindHandleFailed")); - } - } - else { -#endif // FEATURE_CORECLR - if (handleType != Win32Native.FILE_TYPE_PIPE) - VerifyHandleIsSync(); -#if !FEATURE_CORECLR - } -#endif // FEATURE_CORECLR - - if (_canSeek) - SeekCore(0, SeekOrigin.Current); - else - _pos = 0; - } - - [System.Security.SecuritySafeCritical] // auto-generated - private static Win32Native.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share) - { - Win32Native.SECURITY_ATTRIBUTES secAttrs = null; - if ((share & FileShare.Inheritable) != 0) { - secAttrs = new Win32Native.SECURITY_ATTRIBUTES(); - secAttrs.nLength = (int)Marshal.SizeOf(secAttrs); - - secAttrs.bInheritHandle = 1; - } - return secAttrs; - } - -#if FEATURE_MACL - // If pinningHandle is not null, caller must free it AFTER the call to - // CreateFile has returned. - [System.Security.SecuritySafeCritical] // auto-generated - private unsafe static Win32Native.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share, FileSecurity fileSecurity, out Object pinningHandle) - { - pinningHandle = null; - Win32Native.SECURITY_ATTRIBUTES secAttrs = null; - if ((share & FileShare.Inheritable) != 0 || fileSecurity != null) { - secAttrs = new Win32Native.SECURITY_ATTRIBUTES(); - secAttrs.nLength = (int)Marshal.SizeOf(secAttrs); - - if ((share & FileShare.Inheritable) != 0) { - secAttrs.bInheritHandle = 1; - } - - // For ACL's, get the security descriptor from the FileSecurity. - if (fileSecurity != null) { - byte[] sd = fileSecurity.GetSecurityDescriptorBinaryForm(); - pinningHandle = GCHandle.Alloc(sd, GCHandleType.Pinned); - fixed(byte* pSecDescriptor = sd) - secAttrs.pSecurityDescriptor = pSecDescriptor; - } - } - return secAttrs; - } -#endif - - // Verifies that this handle supports synchronous IO operations (unless you - // didn't open it for either reading or writing). - [System.Security.SecuritySafeCritical] // auto-generated - private unsafe void VerifyHandleIsSync() - { - // Do NOT use this method on pipes. Reading or writing to a pipe may - // cause an app to block incorrectly, introducing a deadlock (depending - // on whether a write will wake up an already-blocked thread or this - // FileStream's thread). - - // Do NOT change this to use a byte[] of length 0, or test test won't - // work. Our ReadFile & WriteFile methods are special cased to return - // for arrays of length 0, since we'd get an IndexOutOfRangeException - // while using C#'s fixed syntax. - byte[] bytes = new byte[1]; - int hr = 0; - int r = 0; - - // If the handle is a pipe, ReadFile will block until there - // has been a write on the other end. We'll just have to deal with it, - // For the read end of a pipe, you can mess up and - // accidentally read synchronously from an async pipe. - if (CanRead) { - r = ReadFileNative(_handle, bytes, 0, 0, null, out hr); - } - else if (CanWrite) { - r = WriteFileNative(_handle, bytes, 0, 0, null, out hr); - } - - if (hr==ERROR_INVALID_PARAMETER) - throw new ArgumentException(Environment.GetResourceString("Arg_HandleNotSync")); - if (hr == Win32Native.ERROR_INVALID_HANDLE) - __Error.WinIOError(hr, ""); - } - - - public override bool CanRead { - [Pure] - get { return _canRead; } - } - - public override bool CanWrite { - [Pure] - get { return _canWrite; } - } - - public override bool CanSeek { - [Pure] - get { return _canSeek; } - } - - public virtual bool IsAsync { - get { return _isAsync; } - } - - public override long Length { - [System.Security.SecuritySafeCritical] // auto-generated - get { - if (_handle.IsClosed) __Error.FileNotOpen(); - if (!CanSeek) __Error.SeekNotSupported(); - int hi = 0, lo = 0; - - lo = Win32Native.GetFileSize(_handle, out hi); - - if (lo==-1) { // Check for either an error or a 4GB - 1 byte file. - int hr = Marshal.GetLastWin32Error(); - if (hr != 0) - __Error.WinIOError(hr, String.Empty); - } - long len = (((long)hi) << 32) | ((uint) lo); - // If we're writing near the end of the file, we must include our - // internal buffer in our Length calculation. Don't flush because - // we use the length of the file in our async write method. - if (_writePos > 0 && _pos + _writePos > len) - len = _writePos + _pos; - return len; - } - } - - public String Name { - [System.Security.SecuritySafeCritical] - get { - if (_fileName == null) - return Environment.GetResourceString("IO_UnknownFileName"); -#if FEATURE_CORECLR - FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, _fileName); - sourceState.EnsureState(); -#else - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { _fileName }, false, false).Demand(); -#endif - return _fileName; - } - } - - internal String NameInternal { - get { - if (_fileName == null) - return ""; - return _fileName; - } - } - - public override long Position { - [System.Security.SecuritySafeCritical] // auto-generated - get { - if (_handle.IsClosed) __Error.FileNotOpen(); - if (!CanSeek) __Error.SeekNotSupported(); - - Contract.Assert((_readPos == 0 && _readLen == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLen), "We're either reading or writing, but not both."); - - // Verify that internal position is in sync with the handle - if (_exposedHandle) - VerifyOSHandlePosition(); - - // Compensate for buffer that we read from the handle (_readLen) Vs what the user - // read so far from the internel buffer (_readPos). Of course add any unwrittern - // buffered data - return _pos + (_readPos - _readLen + _writePos); - } - set { - if (value < 0) throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - Contract.EndContractBlock(); - if (_writePos > 0) FlushWrite(false); - _readPos = 0; - _readLen = 0; - Seek(value, SeekOrigin.Begin); - } - } - -#if FEATURE_MACL - [System.Security.SecuritySafeCritical] // auto-generated - public FileSecurity GetAccessControl() - { - if (_handle.IsClosed) __Error.FileNotOpen(); - return new FileSecurity(_handle, _fileName, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public void SetAccessControl(FileSecurity fileSecurity) - { - if (fileSecurity == null) - throw new ArgumentNullException("fileSecurity"); - Contract.EndContractBlock(); - - if (_handle.IsClosed) __Error.FileNotOpen(); - - fileSecurity.Persist(_handle, _fileName); - } -#endif - - [System.Security.SecuritySafeCritical] // auto-generated - protected override void Dispose(bool disposing) - { - // Nothing will be done differently based on whether we are - // disposing vs. finalizing. This is taking advantage of the - // weak ordering between normal finalizable objects & critical - // finalizable objects, which I included in the SafeHandle - // design for FileStream, which would often "just work" when - // finalized. - try { - if (_handle != null && !_handle.IsClosed) { - // Flush data to disk iff we were writing. After - // thinking about this, we also don't need to flush - // our read position, regardless of whether the handle - // was exposed to the user. They probably would NOT - // want us to do this. - if (_writePos > 0) { - FlushWrite(!disposing); - } - } - } - finally { - if (_handle != null && !_handle.IsClosed) - _handle.Dispose(); - - _canRead = false; - _canWrite = false; - _canSeek = false; - // Don't set the buffer to null, to avoid a NullReferenceException - // when users have a race condition in their code (ie, they call - // Close when calling another method on Stream like Read). - //_buffer = null; - base.Dispose(disposing); - } - } - - [System.Security.SecuritySafeCritical] // auto-generated - ~FileStream() - { - if (_handle != null) { - BCLDebug.Correctness(_handle.IsClosed, "You didn't close a FileStream & it got finalized. Name: \""+_fileName+"\""); - Dispose(false); - } - } - - public override void Flush() - { - Flush(false); - } - - [System.Security.SecuritySafeCritical] - public virtual void Flush(Boolean flushToDisk) - { - // This code is duplicated in Dispose - if (_handle.IsClosed) __Error.FileNotOpen(); - - FlushInternalBuffer(); - - if (flushToDisk && CanWrite) - { - FlushOSBuffer(); - } - } - - private void FlushInternalBuffer() - { - if (_writePos > 0) - { - FlushWrite(false); - } - else if (_readPos < _readLen && CanSeek) - { - FlushRead(); - } - } - - [System.Security.SecuritySafeCritical] - private void FlushOSBuffer() - { - if (!Win32Native.FlushFileBuffers(_handle)) - { - __Error.WinIOError(); - } - } - - // Reading is done by blocks from the file, but someone could read - // 1 byte from the buffer then write. At that point, the OS's file - // pointer is out of sync with the stream's position. All write - // functions should call this function to preserve the position in the file. - private void FlushRead() { - Contract.Assert(_writePos == 0, "FileStream: Write buffer must be empty in FlushRead!"); - if (_readPos - _readLen != 0) { - Contract.Assert(CanSeek, "FileStream will lose buffered read data now."); - SeekCore(_readPos - _readLen, SeekOrigin.Current); - } - _readPos = 0; - _readLen = 0; - } - - // Writes are buffered. Anytime the buffer fills up - // (_writePos + delta > _bufferSize) or the buffer switches to reading - // and there is left over data (_writePos > 0), this function must be called. - private void FlushWrite(bool calledFromFinalizer) { - Contract.Assert(_readPos == 0 && _readLen == 0, "FileStream: Read buffer must be empty in FlushWrite!"); - - if (_isAsync) { - IAsyncResult asyncResult = BeginWriteCore(_buffer, 0, _writePos, null, null); - // With our Whidbey async IO & overlapped support for AD unloads, - // we don't strictly need to block here to release resources - // since that support takes care of the pinning & freeing the - // overlapped struct. We need to do this when called from - // Close so that the handle is closed when Close returns, but - // we do't need to call EndWrite from the finalizer. - // Additionally, if we do call EndWrite, we block forever - // because AD unloads prevent us from running the managed - // callback from the IO completion port. Blocking here when - // called from the finalizer during AD unload is clearly wrong, - // but we can't use any sort of test for whether the AD is - // unloading because if we weren't unloading, an AD unload - // could happen on a separate thread before we call EndWrite. - if (!calledFromFinalizer) - EndWrite(asyncResult); - } - else - WriteCore(_buffer, 0, _writePos); - - _writePos = 0; - } - - - [Obsolete("This property has been deprecated. Please use FileStream's SafeFileHandle property instead. http://go.microsoft.com/fwlink/?linkid=14202")] - public virtual IntPtr Handle { - [System.Security.SecurityCritical] // auto-generated_required -#if !FEATURE_CORECLR - [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] -#endif - get { - Flush(); - // Explicitly dump any buffered data, since the user could move our - // position or write to the file. - _readPos = 0; - _readLen = 0; - _writePos = 0; - _exposedHandle = true; - - return _handle.DangerousGetHandle(); - } - } - - public virtual SafeFileHandle SafeFileHandle { - [System.Security.SecurityCritical] // auto-generated_required -#if !FEATURE_CORECLR - [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] -#endif - get { - Flush(); - // Explicitly dump any buffered data, since the user could move our - // position or write to the file. - _readPos = 0; - _readLen = 0; - _writePos = 0; - _exposedHandle = true; - - return _handle; - } - } - - [System.Security.SecuritySafeCritical] // auto-generated - public override void SetLength(long value) - { - if (value < 0) - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - Contract.EndContractBlock(); - - if (_handle.IsClosed) __Error.FileNotOpen(); - if (!CanSeek) __Error.SeekNotSupported(); - if (!CanWrite) __Error.WriteNotSupported(); - - // Handle buffering updates. - if (_writePos > 0) { - FlushWrite(false); - } - else if (_readPos < _readLen) { - FlushRead(); - } - _readPos = 0; - _readLen = 0; - - if (_appendStart != -1 && value < _appendStart) - throw new IOException(Environment.GetResourceString("IO.IO_SetLengthAppendTruncate")); - SetLengthCore(value); - } - - // We absolutely need this method broken out so that BeginWriteCore can call - // a method without having to go through buffering code that might call - // FlushWrite. - [System.Security.SecuritySafeCritical] // auto-generated - private void SetLengthCore(long value) - { - Contract.Assert(value >= 0, "value >= 0"); - long origPos = _pos; - - if (_exposedHandle) - VerifyOSHandlePosition(); - if (_pos != value) - SeekCore(value, SeekOrigin.Begin); - if (!Win32Native.SetEndOfFile(_handle)) { - int hr = Marshal.GetLastWin32Error(); - if (hr==__Error.ERROR_INVALID_PARAMETER) - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_FileLengthTooBig")); - __Error.WinIOError(hr, String.Empty); - } - // Return file pointer to where it was before setting length - if (origPos != value) { - if (origPos < value) - SeekCore(origPos, SeekOrigin.Begin); - else - SeekCore(0, SeekOrigin.End); - } - } - - [System.Security.SecuritySafeCritical] // auto-generated - public override int Read([In, Out] byte[] array, int offset, int count) { - if (array==null) - throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Buffer")); - if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (array.Length - offset < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - if (_handle.IsClosed) __Error.FileNotOpen(); - - Contract.Assert((_readPos==0 && _readLen==0 && _writePos >= 0) || (_writePos==0 && _readPos <= _readLen), "We're either reading or writing, but not both."); - - bool isBlocked = false; - int n = _readLen - _readPos; - // if the read buffer is empty, read into either user's array or our - // buffer, depending on number of bytes user asked for and buffer size. - if (n == 0) { - if (!CanRead) __Error.ReadNotSupported(); - if (_writePos > 0) FlushWrite(false); - if (!CanSeek || (count >= _bufferSize)) { - n = ReadCore(array, offset, count); - // Throw away read buffer. - _readPos = 0; - _readLen = 0; - return n; - } - if (_buffer == null) _buffer = new byte[_bufferSize]; - n = ReadCore(_buffer, 0, _bufferSize); - if (n == 0) return 0; - isBlocked = n < _bufferSize; - _readPos = 0; - _readLen = n; - } - // Now copy min of count or numBytesAvailable (ie, near EOF) to array. - if (n > count) n = count; - Buffer.InternalBlockCopy(_buffer, _readPos, array, offset, n); - _readPos += n; - - // We may have read less than the number of bytes the user asked - // for, but that is part of the Stream contract. Reading again for - // more data may cause us to block if we're using a device with - // no clear end of file, such as a serial port or pipe. If we - // blocked here & this code was used with redirected pipes for a - // process's standard output, this can lead to deadlocks involving - // two processes. But leave this here for files to avoid what would - // probably be a breaking change. -- - - // If we are reading from a device with no clear EOF like a - // serial port or a pipe, this will cause us to block incorrectly. - if (!_isPipe) { - // If we hit the end of the buffer and didn't have enough bytes, we must - // read some more from the underlying stream. However, if we got - // fewer bytes from the underlying stream than we asked for (ie, we're - // probably blocked), don't ask for more bytes. - if (n < count && !isBlocked) { - Contract.Assert(_readPos == _readLen, "Read buffer should be empty!"); - int moreBytesRead = ReadCore(array, offset + n, count - n); - n += moreBytesRead; - // We've just made our buffer inconsistent with our position - // pointer. We must throw away the read buffer. - _readPos = 0; - _readLen = 0; - } - } - - return n; - } - - [System.Security.SecuritySafeCritical] // auto-generated - private unsafe int ReadCore(byte[] buffer, int offset, int count) { - Contract.Assert(!_handle.IsClosed, "!_handle.IsClosed"); - Contract.Assert(CanRead, "CanRead"); - - Contract.Assert(buffer != null, "buffer != null"); - Contract.Assert(_writePos == 0, "_writePos == 0"); - Contract.Assert(offset >= 0, "offset is negative"); - Contract.Assert(count >= 0, "count is negative"); - - if (_isAsync) { - IAsyncResult result = BeginReadCore(buffer, offset, count, null, null, 0); - return EndRead(result); - } - - // Make sure we are reading from the right spot - if (_exposedHandle) - VerifyOSHandlePosition(); - - int hr = 0; - int r = ReadFileNative(_handle, buffer, offset, count, null, out hr); - if (r == -1) { - // For pipes, ERROR_BROKEN_PIPE is the normal end of the pipe. - if (hr == ERROR_BROKEN_PIPE) { - r = 0; - } - else { - if (hr == ERROR_INVALID_PARAMETER) - throw new ArgumentException(Environment.GetResourceString("Arg_HandleNotSync")); - - __Error.WinIOError(hr, String.Empty); - } - } - Contract.Assert(r >= 0, "FileStream's ReadCore is likely broken."); - _pos += r; - - return r; - } - - [System.Security.SecuritySafeCritical] // auto-generated - public override long Seek(long offset, SeekOrigin origin) { - if (originSeekOrigin.End) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidSeekOrigin")); - Contract.EndContractBlock(); - if (_handle.IsClosed) __Error.FileNotOpen(); - if (!CanSeek) __Error.SeekNotSupported(); - - Contract.Assert((_readPos==0 && _readLen==0 && _writePos >= 0) || (_writePos==0 && _readPos <= _readLen), "We're either reading or writing, but not both."); - - // If we've got bytes in our buffer to write, write them out. - // If we've read in and consumed some bytes, we'll have to adjust - // our seek positions ONLY IF we're seeking relative to the current - // position in the stream. This simulates doing a seek to the new - // position, then a read for the number of bytes we have in our buffer. - if (_writePos > 0) { - FlushWrite(false); - } - else if (origin == SeekOrigin.Current) { - // Don't call FlushRead here, which would have caused an infinite - // loop. Simply adjust the seek origin. This isn't necessary - // if we're seeking relative to the beginning or end of the stream. - offset -= (_readLen - _readPos); - } - - // Verify that internal position is in sync with the handle - if (_exposedHandle) - VerifyOSHandlePosition(); - - long oldPos = _pos + (_readPos - _readLen); - long pos = SeekCore(offset, origin); - - // Prevent users from overwriting data in a file that was opened in - // append mode. - if (_appendStart != -1 && pos < _appendStart) { - SeekCore(oldPos, SeekOrigin.Begin); - throw new IOException(Environment.GetResourceString("IO.IO_SeekAppendOverwrite")); - } - - // We now must update the read buffer. We can in some cases simply - // update _readPos within the buffer, copy around the buffer so our - // Position property is still correct, and avoid having to do more - // reads from the disk. Otherwise, discard the buffer's contents. - if (_readLen > 0) { - // We can optimize the following condition: - // oldPos - _readPos <= pos < oldPos + _readLen - _readPos - if (oldPos == pos) { - if (_readPos > 0) { - //Console.WriteLine("Seek: seeked for 0, adjusting buffer back by: "+_readPos+" _readLen: "+_readLen); - Buffer.InternalBlockCopy(_buffer, _readPos, _buffer, 0, _readLen - _readPos); - _readLen -= _readPos; - _readPos = 0; - } - // If we still have buffered data, we must update the stream's - // position so our Position property is correct. - if (_readLen > 0) - SeekCore(_readLen, SeekOrigin.Current); - } - else if (oldPos - _readPos < pos && pos < oldPos + _readLen - _readPos) { - int diff = (int)(pos - oldPos); - //Console.WriteLine("Seek: diff was "+diff+", readpos was "+_readPos+" adjusting buffer - shrinking by "+ (_readPos + diff)); - Buffer.InternalBlockCopy(_buffer, _readPos+diff, _buffer, 0, _readLen - (_readPos + diff)); - _readLen -= (_readPos + diff); - _readPos = 0; - if (_readLen > 0) - SeekCore(_readLen, SeekOrigin.Current); - } - else { - // Lose the read buffer. - _readPos = 0; - _readLen = 0; - } - Contract.Assert(_readLen >= 0 && _readPos <= _readLen, "_readLen should be nonnegative, and _readPos should be less than or equal _readLen"); - Contract.Assert(pos == Position, "Seek optimization: pos != Position! Buffer math was mangled."); - } - return pos; - } - - // This doesn't do argument checking. Necessary for SetLength, which must - // set the file pointer beyond the end of the file. This will update the - // internal position - [System.Security.SecuritySafeCritical] // auto-generated - private long SeekCore(long offset, SeekOrigin origin) { - Contract.Assert(!_handle.IsClosed && CanSeek, "!_handle.IsClosed && CanSeek"); - Contract.Assert(origin>=SeekOrigin.Begin && origin<=SeekOrigin.End, "origin>=SeekOrigin.Begin && origin<=SeekOrigin.End"); - int hr = 0; - long ret = 0; - - ret = Win32Native.SetFilePointer(_handle, offset, origin, out hr); - if (ret == -1) { - // #errorInvalidHandle - // If ERROR_INVALID_HANDLE is returned, it doesn't suffice to set - // the handle as invalid; the handle must also be closed. - // - // Marking the handle as invalid but not closing the handle - // resulted in exceptions during finalization and locked column - // values (due to invalid but unclosed handle) in SQL FileStream - // scenarios. - // - // A more mainstream scenario involves accessing a file on a - // network share. ERROR_INVALID_HANDLE may occur because the network - // connection was dropped and the server closed the handle. However, - // the client side handle is still open and even valid for certain - // operations. - // - // Note that Dispose doesn't throw so we don't need to special case. - // SetHandleAsInvalid only sets _closed field to true (without - // actually closing handle) so we don't need to call that as well. - if (hr == Win32Native.ERROR_INVALID_HANDLE) - _handle.Dispose(); - __Error.WinIOError(hr, String.Empty); - } - - _pos = ret; - return ret; - } - - // Checks the position of the OS's handle equals what we expect it to. - // This will fail if someone else moved the FileStream's handle or if - // we've hit a bug in FileStream's position updating code. - private void VerifyOSHandlePosition() - { - if (!CanSeek) - return; - - // SeekCore will override the current _pos, so save it now - long oldPos = _pos; - long curPos = SeekCore(0, SeekOrigin.Current); - - if (curPos != oldPos) { - // For reads, this is non-fatal but we still could have returned corrupted - // data in some cases. So discard the internal buffer. Potential MDA - _readPos = 0; - _readLen = 0; - if(_writePos > 0) { - // Discard the buffer and let the user know! - _writePos = 0; - throw new IOException(Environment.GetResourceString("IO.IO_FileStreamHandlePosition")); - } - } - } - - [System.Security.SecuritySafeCritical] // auto-generated - public override void Write(byte[] array, int offset, int count) { - if (array==null) - throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Buffer")); - if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (array.Length - offset < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - if (_handle.IsClosed) __Error.FileNotOpen(); - - if (_writePos == 0) - { - // Ensure we can write to the stream, and ready buffer for writing. - if (!CanWrite) __Error.WriteNotSupported(); - if (_readPos < _readLen) FlushRead(); - _readPos = 0; - _readLen = 0; - } - - // If our buffer has data in it, copy data from the user's array into - // the buffer, and if we can fit it all there, return. Otherwise, write - // the buffer to disk and copy any remaining data into our buffer. - // The assumption here is memcpy is cheaper than disk (or net) IO. - // (10 milliseconds to disk vs. ~20-30 microseconds for a 4K memcpy) - // So the extra copying will reduce the total number of writes, in - // non-pathological cases (ie, write 1 byte, then write for the buffer - // size repeatedly) - if (_writePos > 0) { - int numBytes = _bufferSize - _writePos; // space left in buffer - if (numBytes > 0) { - if (numBytes > count) - numBytes = count; - Buffer.InternalBlockCopy(array, offset, _buffer, _writePos, numBytes); - _writePos += numBytes; - if (count==numBytes) return; - offset += numBytes; - count -= numBytes; - } - // Reset our buffer. We essentially want to call FlushWrite - // without calling Flush on the underlying Stream. - - if (_isAsync) { - IAsyncResult result = BeginWriteCore(_buffer, 0, _writePos, null, null); - EndWrite(result); - } - else - { - WriteCore(_buffer, 0, _writePos); - } - - _writePos = 0; - } - // If the buffer would slow writes down, avoid buffer completely. - if (count >= _bufferSize) { - Contract.Assert(_writePos == 0, "FileStream cannot have buffered data to write here! Your stream will be corrupted."); - WriteCore(array, offset, count); - return; - } - else if (count == 0) - return; // Don't allocate a buffer then call memcpy for 0 bytes. - if (_buffer==null) _buffer = new byte[_bufferSize]; - // Copy remaining bytes into buffer, to write at a later date. - Buffer.InternalBlockCopy(array, offset, _buffer, _writePos, count); - _writePos = count; - return; - } - - [System.Security.SecuritySafeCritical] // auto-generated - private unsafe void WriteCore(byte[] buffer, int offset, int count) { - Contract.Assert(!_handle.IsClosed, "!_handle.IsClosed"); - Contract.Assert(CanWrite, "CanWrite"); - - Contract.Assert(buffer != null, "buffer != null"); - Contract.Assert(_readPos == _readLen, "_readPos == _readLen"); - Contract.Assert(offset >= 0, "offset is negative"); - Contract.Assert(count >= 0, "count is negative"); - - if (_isAsync) { - IAsyncResult result = BeginWriteCore(buffer, offset, count, null, null); - EndWrite(result); - return; - } - - // Make sure we are writing to the position that we think we are - if (_exposedHandle) - VerifyOSHandlePosition(); - - int hr = 0; - int r = WriteFileNative(_handle, buffer, offset, count, null, out hr); - if (r == -1) { - // For pipes, ERROR_NO_DATA is not an error, but the pipe is closing. - if (hr == ERROR_NO_DATA) { - r = 0; - } - else { - // ERROR_INVALID_PARAMETER may be returned for writes - // where the position is too large (ie, writing at Int64.MaxValue - // on Win9x) OR for synchronous writes to a handle opened - // asynchronously. - if (hr == ERROR_INVALID_PARAMETER) - throw new IOException(Environment.GetResourceString("IO.IO_FileTooLongOrHandleNotSync")); - __Error.WinIOError(hr, String.Empty); - } - } - Contract.Assert(r >= 0, "FileStream's WriteCore is likely broken."); - _pos += r; - return; - } - - - [System.Security.SecuritySafeCritical] // auto-generated - [HostProtection(ExternalThreading = true)] - public override IAsyncResult BeginRead(byte[] array, int offset, int numBytes, AsyncCallback userCallback, Object stateObject) - { - if (array==null) - throw new ArgumentNullException("array"); - if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (numBytes < 0) - throw new ArgumentOutOfRangeException("numBytes", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (array.Length - offset < numBytes) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - if (_handle.IsClosed) __Error.FileNotOpen(); - - if (!_isAsync) - return base.BeginRead(array, offset, numBytes, userCallback, stateObject); - else - return BeginReadAsync(array, offset, numBytes, userCallback, stateObject); - } - - [System.Security.SecuritySafeCritical] // auto-generated - [HostProtection(ExternalThreading = true)] - private FileStreamAsyncResult BeginReadAsync(byte[] array, int offset, int numBytes, AsyncCallback userCallback, Object stateObject) - { - Contract.Assert(_isAsync); - - if (!CanRead) __Error.ReadNotSupported(); - - Contract.Assert((_readPos == 0 && _readLen == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLen), "We're either reading or writing, but not both."); - - if (_isPipe) - { - // When redirecting stdout & stderr with the Process class, it's easy to deadlock your - // parent & child processes when doing writes 4K at a time. The - // OS appears to use a 4K buffer internally. If you write to a - // pipe that is full, you will block until someone read from - // that pipe. If you try reading from an empty pipe and - // FileStream's BeginRead blocks waiting for data to fill it's - // internal buffer, you will be blocked. In a case where a child - // process writes to stdout & stderr while a parent process tries - // reading from both, you can easily get into a deadlock here. - // To avoid this deadlock, don't buffer when doing async IO on - // pipes. But don't completely ignore buffered data either. - if (_readPos < _readLen) - { - int n = _readLen - _readPos; - if (n > numBytes) n = numBytes; - Buffer.InternalBlockCopy(_buffer, _readPos, array, offset, n); - _readPos += n; - - // Return a synchronous FileStreamAsyncResult - return FileStreamAsyncResult.CreateBufferedReadResult(n, userCallback, stateObject, false); - } - else - { - Contract.Assert(_writePos == 0, "FileStream must not have buffered write data here! Pipes should be unidirectional."); - return BeginReadCore(array, offset, numBytes, userCallback, stateObject, 0); - } - } - - Contract.Assert(!_isPipe, "Should not be a pipe."); - - // Handle buffering. - if (_writePos > 0) FlushWrite(false); - if (_readPos == _readLen) - { - // I can't see how to handle buffering of async requests when - // filling the buffer asynchronously, without a lot of complexity. - // The problems I see are issuing an async read, we do an async - // read to fill the buffer, then someone issues another read - // (either synchronously or asynchronously) before the first one - // returns. This would involve some sort of complex buffer locking - // that we probably don't want to get into, at least not in V1. - // If we did a sync read to fill the buffer, we could avoid the - // problem, and any async read less than 64K gets turned into a - // synchronous read by NT anyways... -- - - if (numBytes < _bufferSize) - { - if (_buffer == null) _buffer = new byte[_bufferSize]; - IAsyncResult bufferRead = BeginReadCore(_buffer, 0, _bufferSize, null, null, 0); - _readLen = EndRead(bufferRead); - int n = _readLen; - if (n > numBytes) n = numBytes; - Buffer.InternalBlockCopy(_buffer, 0, array, offset, n); - _readPos = n; - - // Return a synchronous FileStreamAsyncResult - return FileStreamAsyncResult.CreateBufferedReadResult(n, userCallback, stateObject, false); - } - else - { - // Here we're making our position pointer inconsistent - // with our read buffer. Throw away the read buffer's contents. - _readPos = 0; - _readLen = 0; - return BeginReadCore(array, offset, numBytes, userCallback, stateObject, 0); - } - } - else - { - int n = _readLen - _readPos; - if (n > numBytes) n = numBytes; - Buffer.InternalBlockCopy(_buffer, _readPos, array, offset, n); - _readPos += n; - - if (n >= numBytes) - { - // Return a synchronous FileStreamAsyncResult - return FileStreamAsyncResult.CreateBufferedReadResult(n, userCallback, stateObject, false); - } - else - { - // For streams with no clear EOF like serial ports or pipes - // we cannot read more data without causing an app to block - // incorrectly. Pipes don't go down this path - // though. This code needs to be fixed. - // Throw away read buffer. - _readPos = 0; - _readLen = 0; - return BeginReadCore(array, offset + n, numBytes - n, userCallback, stateObject, n); - } - // WARNING: all state on asyncResult objects must be set before - // we call ReadFile in BeginReadCore, since the OS can run our - // callback & the user's callback before ReadFile returns. - } - } - - [System.Security.SecuritySafeCritical] // auto-generated - unsafe private FileStreamAsyncResult BeginReadCore(byte[] bytes, int offset, int numBytes, AsyncCallback userCallback, Object stateObject, int numBufferedBytesRead) - { - Contract.Assert(!_handle.IsClosed, "!_handle.IsClosed"); - Contract.Assert(CanRead, "CanRead"); - Contract.Assert(bytes != null, "bytes != null"); - Contract.Assert(_writePos == 0, "_writePos == 0"); - Contract.Assert(_isAsync, "BeginReadCore doesn't work on synchronous file streams!"); - Contract.Assert(offset >= 0, "offset is negative"); - Contract.Assert(numBytes >= 0, "numBytes is negative"); - - // Create and store async stream class library specific data in the async result - - // Must pass in _numBufferedBytes here to ensure all the state on the IAsyncResult - // object is set before we call ReadFile, which gives the OS an - // opportunity to run our callback (including the user callback & - // the call to EndRead) before ReadFile has returned. - FileStreamAsyncResult asyncResult = new FileStreamAsyncResult(numBufferedBytesRead, bytes, _handle, userCallback, stateObject, false); - NativeOverlapped* intOverlapped = asyncResult.OverLapped; - - // Calculate position in the file we should be at after the read is done - if (CanSeek) { - long len = Length; - - // Make sure we are reading from the position that we think we are - if (_exposedHandle) - VerifyOSHandlePosition(); - - if (_pos + numBytes > len) { - if (_pos <= len) - numBytes = (int) (len - _pos); - else - numBytes = 0; - } - - // Now set the position to read from in the NativeOverlapped struct - // For pipes, we should leave the offset fields set to 0. - intOverlapped->OffsetLow = unchecked((int)_pos); - intOverlapped->OffsetHigh = (int)(_pos>>32); - - // When using overlapped IO, the OS is not supposed to - // touch the file pointer location at all. We will adjust it - // ourselves. This isn't threadsafe. - - // WriteFile should not update the file pointer when writing - // in overlapped mode, according to MSDN. But it does update - // the file pointer when writing to a UNC path! - // So changed the code below to seek to an absolute - // location, not a relative one. ReadFile seems consistent though. - SeekCore(numBytes, SeekOrigin.Current); - } - - if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.ThreadTransfer)) - FrameworkEventSource.Log.ThreadTransferSend((long)(asyncResult.OverLapped), 2, string.Empty, false); - - // queue an async ReadFile operation and pass in a packed overlapped - int hr = 0; - int r = ReadFileNative(_handle, bytes, offset, numBytes, intOverlapped, out hr); - // ReadFile, the OS version, will return 0 on failure. But - // my ReadFileNative wrapper returns -1. My wrapper will return - // the following: - // On error, r==-1. - // On async requests that are still pending, r==-1 w/ hr==ERROR_IO_PENDING - // on async requests that completed sequentially, r==0 - // You will NEVER RELIABLY be able to get the number of bytes - // read back from this call when using overlapped structures! You must - // not pass in a non-null lpNumBytesRead to ReadFile when using - // overlapped structures! This is by design NT behavior. - if (r==-1 && numBytes!=-1) { - - // For pipes, when they hit EOF, they will come here. - if (hr == ERROR_BROKEN_PIPE) { - // Not an error, but EOF. AsyncFSCallback will NOT be - // called. Call the user callback here. - - // We clear the overlapped status bit for this special case. - // Failure to do so looks like we are freeing a pending overlapped later. - intOverlapped->InternalLow = IntPtr.Zero; - asyncResult.CallUserCallback(); - // EndRead will free the Overlapped struct correctly. - } - else if (hr != ERROR_IO_PENDING) { - if (!_handle.IsClosed && CanSeek) // Update Position - It could be anywhere. - SeekCore(0, SeekOrigin.Current); - - if (hr == ERROR_HANDLE_EOF) - __Error.EndOfFile(); - else - __Error.WinIOError(hr, String.Empty); - } - } - else { - // Due to a workaround for a race condition in NT's ReadFile & - // WriteFile routines, we will always be returning 0 from ReadFileNative - // when we do async IO instead of the number of bytes read, - // irregardless of whether the operation completed - // synchronously or asynchronously. We absolutely must not - // set asyncResult._numBytes here, since will never have correct - // results. - //Console.WriteLine("ReadFile returned: "+r+" (0x"+Int32.Format(r, "x")+") The IO completed synchronously, but the user callback was called on a separate thread"); - } - - return asyncResult; - } - - [System.Security.SecuritySafeCritical] // Although the unsafe code is only required in PAL, the block is wide scoped. Leave it here for desktop to ensure it's reviewed. - public unsafe override int EndRead(IAsyncResult asyncResult) - { - // There are 3 significantly different IAsyncResults we'll accept - // here. One is from Stream::BeginRead. The other two are variations - // on our FileStreamAsyncResult. One is from BeginReadCore, - // while the other is from the BeginRead buffering wrapper. - if (asyncResult==null) - throw new ArgumentNullException("asyncResult"); - Contract.EndContractBlock(); - - if (!_isAsync) - return base.EndRead(asyncResult); - - FileStreamAsyncResult afsar = asyncResult as FileStreamAsyncResult; - if (afsar==null || afsar.IsWrite) - __Error.WrongAsyncResult(); - - // Ensure we don't have any race conditions by doing an interlocked - // CompareExchange here. Avoids corrupting memory via freeing the - // NativeOverlapped class or GCHandle twice. -- - if (1 == Interlocked.CompareExchange(ref afsar._EndXxxCalled, 1, 0)) - __Error.EndReadCalledTwice(); - - // Obtain the WaitHandle, but don't use public property in case we - // delay initialize the manual reset event in the future. - afsar.Wait(); - - // Free memory & GC handles. - afsar.ReleaseNativeResource(); - - // Now check for any error during the read. - if (afsar.ErrorCode != 0) - __Error.WinIOError(afsar.ErrorCode, String.Empty); - - return afsar.NumBytesRead; - } - - // Reads a byte from the file stream. Returns the byte cast to an int - // or -1 if reading from the end of the stream. - [System.Security.SecuritySafeCritical] // auto-generated - public override int ReadByte() { - if (_handle.IsClosed) __Error.FileNotOpen(); - if (_readLen==0 && !CanRead) __Error.ReadNotSupported(); - Contract.Assert((_readPos==0 && _readLen==0 && _writePos >= 0) || (_writePos==0 && _readPos <= _readLen), "We're either reading or writing, but not both."); - if (_readPos == _readLen) { - if (_writePos > 0) FlushWrite(false); - Contract.Assert(_bufferSize > 0, "_bufferSize > 0"); - if (_buffer == null) _buffer = new byte[_bufferSize]; - _readLen = ReadCore(_buffer, 0, _bufferSize); - _readPos = 0; - } - if (_readPos == _readLen) - return -1; - - int result = _buffer[_readPos]; - _readPos++; - return result; - } - - - [System.Security.SecuritySafeCritical] // auto-generated - [HostProtection(ExternalThreading=true)] - public override IAsyncResult BeginWrite(byte[] array, int offset, int numBytes, AsyncCallback userCallback, Object stateObject) - { - if (array==null) - throw new ArgumentNullException("array"); - if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (numBytes < 0) - throw new ArgumentOutOfRangeException("numBytes", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (array.Length - offset < numBytes) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - if (_handle.IsClosed) __Error.FileNotOpen(); - - if (!_isAsync) - return base.BeginWrite(array, offset, numBytes, userCallback, stateObject); - else - return BeginWriteAsync(array, offset, numBytes, userCallback, stateObject); - } - - [System.Security.SecuritySafeCritical] // auto-generated - [HostProtection(ExternalThreading = true)] - private FileStreamAsyncResult BeginWriteAsync(byte[] array, int offset, int numBytes, AsyncCallback userCallback, Object stateObject) - { - Contract.Assert(_isAsync); - - if (!CanWrite) __Error.WriteNotSupported(); - - Contract.Assert((_readPos == 0 && _readLen == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLen), "We're either reading or writing, but not both."); - - if (_isPipe) - { - // When redirecting stdout & stderr with the Process class, it's easy to deadlock your - // parent & child processes when doing writes 4K at a time. The - // OS appears to use a 4K buffer internally. If you write to a - // pipe that is full, you will block until someone read from - // that pipe. If you try reading from an empty pipe and - // FileStream's BeginRead blocks waiting for data to fill it's - // internal buffer, you will be blocked. In a case where a child - // process writes to stdout & stderr while a parent process tries - // reading from both, you can easily get into a deadlock here. - // To avoid this deadlock, don't buffer when doing async IO on - // pipes. - Contract.Assert(_readPos == 0 && _readLen == 0, "FileStream must not have buffered data here! Pipes should be unidirectional."); - - if (_writePos > 0) - FlushWrite(false); - - return BeginWriteCore(array, offset, numBytes, userCallback, stateObject); - } - - // Handle buffering. - if (_writePos == 0) - { - if (_readPos < _readLen) FlushRead(); - _readPos = 0; - _readLen = 0; - } - - int n = _bufferSize - _writePos; - if (numBytes <= n) - { - if (_writePos == 0) _buffer = new byte[_bufferSize]; - Buffer.InternalBlockCopy(array, offset, _buffer, _writePos, numBytes); - _writePos += numBytes; - - // Return a synchronous FileStreamAsyncResult - return FileStreamAsyncResult.CreateBufferedReadResult(numBytes, userCallback, stateObject, true); - } - - if (_writePos > 0) - FlushWrite(false); - - return BeginWriteCore(array, offset, numBytes, userCallback, stateObject); - } - - [System.Security.SecuritySafeCritical] // auto-generated - unsafe private FileStreamAsyncResult BeginWriteCore(byte[] bytes, int offset, int numBytes, AsyncCallback userCallback, Object stateObject) - { - Contract.Assert(!_handle.IsClosed, "!_handle.IsClosed"); - Contract.Assert(CanWrite, "CanWrite"); - Contract.Assert(bytes != null, "bytes != null"); - Contract.Assert(_readPos == _readLen, "_readPos == _readLen"); - Contract.Assert(_isAsync, "BeginWriteCore doesn't work on synchronous file streams!"); - Contract.Assert(offset >= 0, "offset is negative"); - Contract.Assert(numBytes >= 0, "numBytes is negative"); - - // Create and store async stream class library specific data in the async result - FileStreamAsyncResult asyncResult = new FileStreamAsyncResult(0, bytes, _handle, userCallback, stateObject, true); - NativeOverlapped* intOverlapped = asyncResult.OverLapped; - - if (CanSeek) { - // Make sure we set the length of the file appropriately. - long len = Length; - //Console.WriteLine("BeginWrite - Calculating end pos. pos: "+pos+" len: "+len+" numBytes: "+numBytes); - - // Make sure we are writing to the position that we think we are - if (_exposedHandle) - VerifyOSHandlePosition(); - - if (_pos + numBytes > len) { - //Console.WriteLine("BeginWrite - Setting length to: "+(pos + numBytes)); - SetLengthCore(_pos + numBytes); - } - - // Now set the position to read from in the NativeOverlapped struct - // For pipes, we should leave the offset fields set to 0. - intOverlapped->OffsetLow = (int)_pos; - intOverlapped->OffsetHigh = (int)(_pos>>32); - - // When using overlapped IO, the OS is not supposed to - // touch the file pointer location at all. We will adjust it - // ourselves. This isn't threadsafe. - - SeekCore(numBytes, SeekOrigin.Current); - } - - //Console.WriteLine("BeginWrite finishing. pos: "+pos+" numBytes: "+numBytes+" _pos: "+_pos+" Position: "+Position); - - if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.ThreadTransfer)) - FrameworkEventSource.Log.ThreadTransferSend((long)(asyncResult.OverLapped), 2, string.Empty, false); - - int hr = 0; - // queue an async WriteFile operation and pass in a packed overlapped - int r = WriteFileNative(_handle, bytes, offset, numBytes, intOverlapped, out hr); - - // WriteFile, the OS version, will return 0 on failure. But - // my WriteFileNative wrapper returns -1. My wrapper will return - // the following: - // On error, r==-1. - // On async requests that are still pending, r==-1 w/ hr==ERROR_IO_PENDING - // On async requests that completed sequentially, r==0 - // You will NEVER RELIABLY be able to get the number of bytes - // written back from this call when using overlapped IO! You must - // not pass in a non-null lpNumBytesWritten to WriteFile when using - // overlapped structures! This is ByDesign NT behavior. - if (r==-1 && numBytes!=-1) { - //Console.WriteLine("WriteFile returned 0; Write will complete asynchronously (if hr==3e5) hr: 0x{0:x}", hr); - - // For pipes, when they are closed on the other side, they will come here. - if (hr == ERROR_NO_DATA) { - // Not an error, but EOF. AsyncFSCallback will NOT be - // called. Call the user callback here. - asyncResult.CallUserCallback(); - // EndWrite will free the Overlapped struct correctly. - } - else if (hr != ERROR_IO_PENDING) { - if (!_handle.IsClosed && CanSeek) // Update Position - It could be anywhere. - SeekCore(0, SeekOrigin.Current); - - if (hr == ERROR_HANDLE_EOF) - __Error.EndOfFile(); - else - __Error.WinIOError(hr, String.Empty); - } - } - else { - // Due to a workaround for a race condition in NT's ReadFile & - // WriteFile routines, we will always be returning 0 from WriteFileNative - // when we do async IO instead of the number of bytes written, - // irregardless of whether the operation completed - // synchronously or asynchronously. We absolutely must not - // set asyncResult._numBytes here, since will never have correct - // results. - //Console.WriteLine("WriteFile returned: "+r+" (0x"+Int32.Format(r, "x")+") The IO completed synchronously, but the user callback was called on another thread."); - } - - return asyncResult; - } - - [System.Security.SecuritySafeCritical] // Although the unsafe code is only required in PAL, the block is wide scoped. Leave it here for desktop to ensure it's reviewed. - public unsafe override void EndWrite(IAsyncResult asyncResult) - { - if (asyncResult==null) - throw new ArgumentNullException("asyncResult"); - Contract.EndContractBlock(); - - if (!_isAsync) { - base.EndWrite(asyncResult); - return; - } - - FileStreamAsyncResult afsar = asyncResult as FileStreamAsyncResult; - if (afsar==null || !afsar.IsWrite) - __Error.WrongAsyncResult(); - - // Ensure we can't have any race conditions by doing an interlocked - // CompareExchange here. Avoids corrupting memory via freeing the - // NativeOverlapped class or GCHandle twice. -- - if (1 == Interlocked.CompareExchange(ref afsar._EndXxxCalled, 1, 0)) - __Error.EndWriteCalledTwice(); - - // Obtain the WaitHandle, but don't use public property in case we - // delay initialize the manual reset event in the future. - afsar.Wait(); - - // Free memory & GC handles. - afsar.ReleaseNativeResource(); - - // Now check for any error during the write. - if (afsar.ErrorCode != 0) - __Error.WinIOError(afsar.ErrorCode, String.Empty); - - // Number of bytes written is afsar._numBytes + afsar._numBufferedBytes. - return; - } - - [System.Security.SecuritySafeCritical] // auto-generated - public override void WriteByte(byte value) - { - if (_handle.IsClosed) __Error.FileNotOpen(); - if (_writePos==0) { - if (!CanWrite) __Error.WriteNotSupported(); - if (_readPos < _readLen) FlushRead(); - _readPos = 0; - _readLen = 0; - Contract.Assert(_bufferSize > 0, "_bufferSize > 0"); - if (_buffer==null) _buffer = new byte[_bufferSize]; - } - if (_writePos == _bufferSize) - FlushWrite(false); - - _buffer[_writePos] = value; - _writePos++; - } - - [System.Security.SecuritySafeCritical] // auto-generated - public virtual void Lock(long position, long length) { - if (position < 0 || length < 0) - throw new ArgumentOutOfRangeException((position < 0 ? "position" : "length"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - Contract.EndContractBlock(); - if (_handle.IsClosed) __Error.FileNotOpen(); - - int positionLow = unchecked((int)(position )); - int positionHigh = unchecked((int)(position >> 32)); - int lengthLow = unchecked((int)(length )); - int lengthHigh = unchecked((int)(length >> 32)); - - if (!Win32Native.LockFile(_handle, positionLow, positionHigh, lengthLow, lengthHigh)) - __Error.WinIOError(); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public virtual void Unlock(long position, long length) { - if (position < 0 || length < 0) - throw new ArgumentOutOfRangeException((position < 0 ? "position" : "length"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - Contract.EndContractBlock(); - if (_handle.IsClosed) __Error.FileNotOpen(); - - int positionLow = unchecked((int)(position )); - int positionHigh = unchecked((int)(position >> 32)); - int lengthLow = unchecked((int)(length )); - int lengthHigh = unchecked((int)(length >> 32)); - - if (!Win32Native.UnlockFile(_handle, positionLow, positionHigh, lengthLow, lengthHigh)) - __Error.WinIOError(); - } - - // Windows API definitions, from winbase.h and others - - private const int FILE_ATTRIBUTE_NORMAL = 0x00000080; - private const int FILE_ATTRIBUTE_ENCRYPTED = 0x00004000; - private const int FILE_FLAG_OVERLAPPED = 0x40000000; - internal const int GENERIC_READ = unchecked((int)0x80000000); - private const int GENERIC_WRITE = 0x40000000; - - private const int FILE_BEGIN = 0; - private const int FILE_CURRENT = 1; - private const int FILE_END = 2; - - // Error codes (not HRESULTS), from winerror.h - internal const int ERROR_BROKEN_PIPE = 109; - internal const int ERROR_NO_DATA = 232; - private const int ERROR_HANDLE_EOF = 38; - private const int ERROR_INVALID_PARAMETER = 87; - private const int ERROR_IO_PENDING = 997; - - - // __ConsoleStream also uses this code. - [System.Security.SecurityCritical] // auto-generated - private unsafe int ReadFileNative(SafeFileHandle handle, byte[] bytes, int offset, int count, NativeOverlapped* overlapped, out int hr) - { - Contract.Requires(handle != null, "handle != null"); - Contract.Requires(offset >= 0, "offset >= 0"); - Contract.Requires(count >= 0, "count >= 0"); - Contract.Requires(bytes != null, "bytes != null"); - // Don't corrupt memory when multiple threads are erroneously writing - // to this stream simultaneously. - if (bytes.Length - offset < count) - throw new IndexOutOfRangeException(Environment.GetResourceString("IndexOutOfRange_IORaceCondition")); - Contract.EndContractBlock(); - - Contract.Assert((_isAsync && overlapped != null) || (!_isAsync && overlapped == null), "Async IO parameter mismatch in call to ReadFileNative."); - - // You can't use the fixed statement on an array of length 0. - if (bytes.Length==0) { - hr = 0; - return 0; - } - - int r = 0; - int numBytesRead = 0; - - fixed(byte* p = bytes) { - if (_isAsync) - r = Win32Native.ReadFile(handle, p + offset, count, IntPtr.Zero, overlapped); - else - r = Win32Native.ReadFile(handle, p + offset, count, out numBytesRead, IntPtr.Zero); - } - - if (r==0) { - hr = Marshal.GetLastWin32Error(); - // We should never silently drop an error here without some - // extra work. We must make sure that BeginReadCore won't return an - // IAsyncResult that will cause EndRead to block, since the OS won't - // call AsyncFSCallback for us. - if (hr == ERROR_BROKEN_PIPE || hr == Win32Native.ERROR_PIPE_NOT_CONNECTED) { - // This handle was a pipe, and it's done. Not an error, but EOF. - // However, the OS will not call AsyncFSCallback! - // Let the caller handle this, since BeginReadCore & ReadCore - // need to do different things. - return -1; - } - - // See code:#errorInvalidHandle in "private long SeekCore(long offset, SeekOrigin origin)". - if (hr == Win32Native.ERROR_INVALID_HANDLE) - _handle.Dispose(); - - return -1; - } - else - hr = 0; - return numBytesRead; - } - - [System.Security.SecurityCritical] // auto-generated - private unsafe int WriteFileNative(SafeFileHandle handle, byte[] bytes, int offset, int count, NativeOverlapped* overlapped, out int hr) { - Contract.Requires(handle != null, "handle != null"); - Contract.Requires(offset >= 0, "offset >= 0"); - Contract.Requires(count >= 0, "count >= 0"); - Contract.Requires(bytes != null, "bytes != null"); - // Don't corrupt memory when multiple threads are erroneously writing - // to this stream simultaneously. (the OS is reading from - // the array we pass to WriteFile, but if we read beyond the end and - // that memory isn't allocated, we could get an AV.) - if (bytes.Length - offset < count) - throw new IndexOutOfRangeException(Environment.GetResourceString("IndexOutOfRange_IORaceCondition")); - Contract.EndContractBlock(); - - Contract.Assert((_isAsync && overlapped != null) || (!_isAsync && overlapped == null), "Async IO parameter missmatch in call to WriteFileNative."); - - // You can't use the fixed statement on an array of length 0. - if (bytes.Length==0) { - hr = 0; - return 0; - } - - int numBytesWritten = 0; - int r = 0; - - fixed(byte* p = bytes) { - if (_isAsync) - r = Win32Native.WriteFile(handle, p + offset, count, IntPtr.Zero, overlapped); - else - r = Win32Native.WriteFile(handle, p + offset, count, out numBytesWritten, IntPtr.Zero); - } - - if (r==0) { - hr = Marshal.GetLastWin32Error(); - // We should never silently drop an error here without some - // extra work. We must make sure that BeginWriteCore won't return an - // IAsyncResult that will cause EndWrite to block, since the OS won't - // call AsyncFSCallback for us. - - if (hr==ERROR_NO_DATA) { - // This handle was a pipe, and the pipe is being closed on the - // other side. Let the caller handle this, since BeginWriteCore - // & WriteCore need to do different things. - return -1; - } - - // See code:#errorInvalidHandle in "private long SeekCore(long offset, SeekOrigin origin)". - if (hr == Win32Native.ERROR_INVALID_HANDLE) - _handle.Dispose(); - - return -1; - } - else - hr = 0; - return numBytesWritten; - } - - - [HostProtection(ExternalThreading = true)] - [ComVisible(false)] - [SecuritySafeCritical] - public override Task ReadAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - if (buffer == null) - throw new ArgumentNullException("buffer"); - if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (buffer.Length - offset < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - // If we have been inherited into a subclass, the following implementation could be incorrect - // since it does not call through to Read() or BeginRead() which a subclass might have overriden. - // To be safe we will only use this implementation in cases where we know it is safe to do so, - // and delegate to our base class (which will call into Read/BeginRead) when we are not sure. - if (this.GetType() != typeof(FileStream)) - return base.ReadAsync(buffer, offset, count, cancellationToken); - - if (cancellationToken.IsCancellationRequested) - return Task.FromCanceled(cancellationToken); - - if (_handle.IsClosed) - __Error.FileNotOpen(); - - // If async IO is not supported on this platform or - // if this FileStream was not opened with FileOptions.Asynchronous. - if (!_isAsync) - return base.ReadAsync(buffer, offset, count, cancellationToken); - - var readTask = new FileStreamReadWriteTask(cancellationToken); - var endReadTask = s_endReadTask; - if (endReadTask == null) s_endReadTask = endReadTask = EndReadTask; // benign initialization race condition - readTask._asyncResult = BeginReadAsync(buffer, offset, count, endReadTask, readTask); - - if (readTask._asyncResult.IsAsync && cancellationToken.CanBeCanceled) - { - var cancelReadHandler = s_cancelReadHandler; - if (cancelReadHandler == null) s_cancelReadHandler = cancelReadHandler = CancelTask; // benign initialization race condition - readTask._registration = cancellationToken.Register(cancelReadHandler, readTask); - - // In case the task is completed right before we register the cancellation callback. - if (readTask._asyncResult.IsCompleted) - readTask._registration.Dispose(); - } - - return readTask; - } - - [HostProtection(ExternalThreading = true)] - [ComVisible(false)] - [SecuritySafeCritical] - public override Task WriteAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - if (buffer == null) - throw new ArgumentNullException("buffer"); - if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (buffer.Length - offset < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - // If we have been inherited into a subclass, the following implementation could be incorrect - // since it does not call through to Write() or BeginWrite() which a subclass might have overriden. - // To be safe we will only use this implementation in cases where we know it is safe to do so, - // and delegate to our base class (which will call into Write/BeginWrite) when we are not sure. - if (this.GetType() != typeof(FileStream)) - return base.WriteAsync(buffer, offset, count, cancellationToken); - - if (cancellationToken.IsCancellationRequested) - return Task.FromCanceled(cancellationToken); - - if (_handle.IsClosed) - __Error.FileNotOpen(); - - // If async IO is not supported on this platform or - // if this FileStream was not opened with FileOptions.Asynchronous. - if (!_isAsync) - return base.WriteAsync(buffer, offset, count, cancellationToken); - - var writeTask = new FileStreamReadWriteTask(cancellationToken); - var endWriteTask = s_endWriteTask; - if (endWriteTask == null) s_endWriteTask = endWriteTask = EndWriteTask; // benign initialization race condition - writeTask._asyncResult = BeginWriteAsync(buffer, offset, count, endWriteTask, writeTask); - - if (writeTask._asyncResult.IsAsync && cancellationToken.CanBeCanceled) - { - var cancelWriteHandler = s_cancelWriteHandler; - if (cancelWriteHandler == null) s_cancelWriteHandler = cancelWriteHandler = CancelTask; // benign initialization race condition - writeTask._registration = cancellationToken.Register(cancelWriteHandler, writeTask); - - // In case the task is completed right before we register the cancellation callback. - if (writeTask._asyncResult.IsCompleted) - writeTask._registration.Dispose(); - } - - return writeTask; - } - - // The task instance returned from ReadAsync and WriteAsync. - // Also stores all of the state necessary for those calls to avoid closures and extraneous delegate allocations. - private sealed class FileStreamReadWriteTask : Task - { - internal CancellationToken _cancellationToken; - internal CancellationTokenRegistration _registration; - internal FileStreamAsyncResult _asyncResult; // initialized after Begin call completes - - internal FileStreamReadWriteTask(CancellationToken cancellationToken) : base() - { - _cancellationToken = cancellationToken; - } - } - - // Cancellation callback for both ReadAsync and WriteAsync. - [SecuritySafeCritical] - private static void CancelTask(object state) - { - var task = state as FileStreamReadWriteTask; - Contract.Assert(task != null); - FileStreamAsyncResult asyncResult = task._asyncResult; - - // This method is used as both the completion callback and the cancellation callback. - // We should try to cancel the operation if this is running as the completion callback - // or if cancellation is not applicable: - // 1. asyncResult is not a FileStreamAsyncResult - // 2. asyncResult.IsAsync is false: asyncResult is a "synchronous" FileStreamAsyncResult. - // 3. The asyncResult is completed: this should never happen. - Contract.Assert((!asyncResult.IsWrite && typeof(T) == typeof(int)) || - (asyncResult.IsWrite && typeof(T) == typeof(VoidTaskResult))); - Contract.Assert(asyncResult != null); - Contract.Assert(asyncResult.IsAsync); - - try - { - // Cancel the overlapped read and set the task to cancelled state. - if (!asyncResult.IsCompleted) - asyncResult.Cancel(); - } - catch (Exception ex) - { - task.TrySetException(ex); - } - } - - // Completion callback for ReadAsync - [SecuritySafeCritical] - private static void EndReadTask(IAsyncResult iar) - { - FileStreamAsyncResult asyncResult = iar as FileStreamAsyncResult; - Contract.Assert(asyncResult != null); - Contract.Assert(asyncResult.IsCompleted, "How can we end up in the completion callback if the IAsyncResult is not completed?"); - - var readTask = asyncResult.AsyncState as FileStreamReadWriteTask; - Contract.Assert(readTask != null); - - try - { - if (asyncResult.IsAsync) - { - asyncResult.ReleaseNativeResource(); - - // release the resource held by CancellationTokenRegistration - readTask._registration.Dispose(); - } - - if (asyncResult.ErrorCode == Win32Native.ERROR_OPERATION_ABORTED) - { - var cancellationToken = readTask._cancellationToken; - Contract.Assert(cancellationToken.IsCancellationRequested, "How can the IO operation be aborted if cancellation was not requested?"); - readTask.TrySetCanceled(cancellationToken); - } - else - readTask.TrySetResult(asyncResult.NumBytesRead); - } - catch (Exception ex) - { - readTask.TrySetException(ex); - } - } - - // Completion callback for WriteAsync - [SecuritySafeCritical] - private static void EndWriteTask(IAsyncResult iar) - { - var asyncResult = iar as FileStreamAsyncResult; - Contract.Assert(asyncResult != null); - Contract.Assert(asyncResult.IsCompleted, "How can we end up in the completion callback if the IAsyncResult is not completed?"); - - var writeTask = iar.AsyncState as FileStreamReadWriteTask; - Contract.Assert(writeTask != null); - - try - { - if (asyncResult.IsAsync) - { - asyncResult.ReleaseNativeResource(); - - // release the resource held by CancellationTokenRegistration - writeTask._registration.Dispose(); - } - - if (asyncResult.ErrorCode == Win32Native.ERROR_OPERATION_ABORTED) - { - var cancellationToken = writeTask._cancellationToken; - Contract.Assert(cancellationToken.IsCancellationRequested, "How can the IO operation be aborted if cancellation was not requested?"); - writeTask.TrySetCanceled(cancellationToken); - } - else - writeTask.TrySetResult(default(VoidTaskResult)); - } - catch (Exception ex) - { - writeTask.TrySetException(ex); - } - } - - // Unlike Flush(), FlushAsync() always flushes to disk. This is intentional. - // Legend is that we chose not to flush the OS file buffers in Flush() in fear of - // perf problems with frequent, long running FlushFileBuffers() calls. But we don't - // have that problem with FlushAsync() because we will call FlushFileBuffers() in the background. - [HostProtection(ExternalThreading = true)] - [ComVisible(false)] - [System.Security.SecuritySafeCritical] - public override Task FlushAsync(CancellationToken cancellationToken) - { - // If we have been inherited into a subclass, the following implementation could be incorrect - // since it does not call through to Flush() which a subclass might have overriden. To be safe - // we will only use this implementation in cases where we know it is safe to do so, - // and delegate to our base class (which will call into Flush) when we are not sure. - if (this.GetType() != typeof(FileStream)) - return base.FlushAsync(cancellationToken); - - if (cancellationToken.IsCancellationRequested) - return Task.FromCanceled(cancellationToken); - - if (_handle.IsClosed) - __Error.FileNotOpen(); - - // The always synchronous data transfer between the OS and the internal buffer is intentional - // because this is needed to allow concurrent async IO requests. Concurrent data transfer - // between the OS and the internal buffer will result in race conditions. Since FlushWrite and - // FlushRead modify internal state of the stream and transfer data between the OS and the - // internal buffer, they cannot be truly async. We will, however, flush the OS file buffers - // asynchronously because it doesn't modify any internal state of the stream and is potentially - // a long running process. - try - { - FlushInternalBuffer(); - } - catch (Exception e) - { - return Task.FromException(e); - } - - if (CanWrite) - return Task.Factory.StartNew( - state => ((FileStream)state).FlushOSBuffer(), - this, - cancellationToken, - TaskCreationOptions.DenyChildAttach, - TaskScheduler.Default); - else - return Task.CompletedTask; - } - - } -} diff --git a/src/mscorlib/src/System/IO/FileSystemEnumerable.cs b/src/mscorlib/src/System/IO/FileSystemEnumerable.cs index c2e603c..f861805 100644 --- a/src/mscorlib/src/System/IO/FileSystemEnumerable.cs +++ b/src/mscorlib/src/System/IO/FileSystemEnumerable.cs @@ -12,17 +12,14 @@ ** ===========================================================*/ -using System; using System.Collections; using System.Collections.Generic; -using System.Security; -using System.Security.Permissions; using Microsoft.Win32; using Microsoft.Win32.SafeHandles; -using System.Text; using System.Runtime.InteropServices; using System.Globalization; using System.Runtime.Versioning; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Threading; @@ -158,7 +155,6 @@ namespace System.IO // For all the dirs/files returned, demands path discovery permission for their parent folders internal class FileSystemEnumerableIterator : Iterator { - private const int STATE_INIT = 1; private const int STATE_SEARCH_NEXT_DIR = 2; private const int STATE_FIND_NEXT_FILE = 3; @@ -168,9 +164,7 @@ namespace System.IO private List searchStack; private Directory.SearchData searchData; private String searchCriteria; - [System.Security.SecurityCritical] SafeFindHandle _hnd = null; - bool needsParentPathDiscoveryDemand; // empty means we know in advance that we wonÂ’t find any search results, which can happen if: // 1. we donÂ’t have a search pattern @@ -185,9 +179,7 @@ namespace System.IO private String fullPath; private String normalizedSearchPath; private int oldMode; - private bool _checkHost; - [System.Security.SecuritySafeCritical] internal FileSystemEnumerableIterator(String path, String originalUserPath, String searchPattern, SearchOption searchOption, SearchResultHandler resultHandler, bool checkHost) { Contract.Requires(path != null); @@ -211,30 +203,10 @@ namespace System.IO _resultHandler = resultHandler; this.searchOption = searchOption; - fullPath = Path.GetFullPathInternal(path); + fullPath = Path.GetFullPath(path); String fullSearchString = GetFullSearchString(fullPath, normalizedSearchPattern); normalizedSearchPath = Path.GetDirectoryName(fullSearchString); - // permission demands - String[] demandPaths = new String[2]; - // Any illegal chars such as *, ? will be caught by FileIOPermission.HasIllegalCharacters - demandPaths[0] = Directory.GetDemandDir(fullPath, true); - // For filters like foo\*.cs we need to verify if the directory foo is not denied access. - // Do a demand on the combined path so that we can fail early in case of deny - demandPaths[1] = Directory.GetDemandDir(normalizedSearchPath, true); - _checkHost = checkHost; -#if FEATURE_CORECLR - if (checkHost) - { - FileSecurityState state1 = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandPaths[0]); - state1.EnsureState(); - FileSecurityState state2 = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandPaths[1]); - state2.EnsureState(); - } -#else - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPaths, false, false).Demand(); -#endif - // normalize search criteria searchCriteria = GetNormalizedSearchCriteria(fullSearchString, normalizedSearchPath); @@ -254,13 +226,12 @@ namespace System.IO } - [System.Security.SecurityCritical] private void CommonInit() { - Contract.Assert(searchCriteria != null && searchData != null, "searchCriteria and searchData should be initialized"); + Debug.Assert(searchCriteria != null && searchData != null, "searchCriteria and searchData should be initialized"); // Execute searchCriteria against the current directory - String searchPath = Path.InternalCombine(searchData.fullPath, searchCriteria); + String searchPath = Path.Combine(searchData.fullPath, searchCriteria); Win32Native.WIN32_FIND_DATA data = new Win32Native.WIN32_FIND_DATA(); @@ -307,8 +278,7 @@ namespace System.IO } } - [System.Security.SecuritySafeCritical] - private FileSystemEnumerableIterator(String fullPath, String normalizedSearchPath, String searchCriteria, String userPath, SearchOption searchOption, SearchResultHandler resultHandler, bool checkHost) + private FileSystemEnumerableIterator(String fullPath, String normalizedSearchPath, String searchCriteria, String userPath, SearchOption searchOption, SearchResultHandler resultHandler) { this.fullPath = fullPath; this.normalizedSearchPath = normalizedSearchPath; @@ -316,30 +286,11 @@ namespace System.IO this._resultHandler = resultHandler; this.userPath = userPath; this.searchOption = searchOption; - this._checkHost = checkHost; searchStack = new List(); if (searchCriteria != null) { - // permission demands - String[] demandPaths = new String[2]; - // Any illegal chars such as *, ? will be caught by FileIOPermission.HasIllegalCharacters - demandPaths[0] = Directory.GetDemandDir(fullPath, true); - // For filters like foo\*.cs we need to verify if the directory foo is not denied access. - // Do a demand on the combined path so that we can fail early in case of deny - demandPaths[1] = Directory.GetDemandDir(normalizedSearchPath, true); -#if FEATURE_CORECLR - if (checkHost) - { - FileSecurityState state1 = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandPaths[0]); - state1.EnsureState(); - FileSecurityState state2 = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandPaths[1]); - state2.EnsureState(); - } -#else - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPaths, false, false).Demand(); -#endif searchData = new Directory.SearchData(normalizedSearchPath, userPath, searchOption); CommonInit(); } @@ -351,10 +302,9 @@ namespace System.IO protected override Iterator Clone() { - return new FileSystemEnumerableIterator(fullPath, normalizedSearchPath, searchCriteria, userPath, searchOption, _resultHandler, _checkHost); + return new FileSystemEnumerableIterator(fullPath, normalizedSearchPath, searchCriteria, userPath, searchOption, _resultHandler); } - [System.Security.SecuritySafeCritical] protected override void Dispose(bool disposing) { try @@ -371,7 +321,6 @@ namespace System.IO } } - [System.Security.SecuritySafeCritical] public override bool MoveNext() { Win32Native.WIN32_FIND_DATA data = new Win32Native.WIN32_FIND_DATA(); @@ -404,19 +353,19 @@ namespace System.IO } case STATE_SEARCH_NEXT_DIR: { - Contract.Assert(searchData.searchOption != SearchOption.TopDirectoryOnly, "should not reach this code path if searchOption == TopDirectoryOnly"); + Debug.Assert(searchData.searchOption != SearchOption.TopDirectoryOnly, "should not reach this code path if searchOption == TopDirectoryOnly"); // Traverse directory structure. We need to get '*' while (searchStack.Count > 0) { searchData = searchStack[0]; - Contract.Assert((searchData.fullPath != null), "fullpath can't be null!"); + Debug.Assert((searchData.fullPath != null), "fullpath can't be null!"); searchStack.RemoveAt(0); // Traverse the subdirs AddSearchableDirsToStack(searchData); // Execute searchCriteria against the current directory - String searchPath = Path.InternalCombine(searchData.fullPath, searchCriteria); + String searchPath = Path.Combine(searchData.fullPath, searchCriteria); // Open a Find handle _hnd = Win32Native.FindFirstFile(searchPath, data); @@ -431,15 +380,9 @@ namespace System.IO } state = STATE_FIND_NEXT_FILE; - needsParentPathDiscoveryDemand = true; SearchResult searchResult = CreateSearchResult(searchData, data); if (_resultHandler.IsResultIncluded(searchResult)) { - if (needsParentPathDiscoveryDemand) - { - DoDemand(searchData.fullPath); - needsParentPathDiscoveryDemand = false; - } current = _resultHandler.CreateObject(searchResult); return true; } @@ -461,11 +404,6 @@ namespace System.IO SearchResult searchResult = CreateSearchResult(searchData, data); if (_resultHandler.IsResultIncluded(searchResult)) { - if (needsParentPathDiscoveryDemand) - { - DoDemand(searchData.fullPath); - needsParentPathDiscoveryDemand = false; - } current = _resultHandler.CreateObject(searchResult); return true; } @@ -506,27 +444,24 @@ namespace System.IO return false; } - [System.Security.SecurityCritical] private SearchResult CreateSearchResult(Directory.SearchData localSearchData, Win32Native.WIN32_FIND_DATA findData) { - String userPathFinal = Path.InternalCombine(localSearchData.userPath, findData.cFileName); - String fullPathFinal = Path.InternalCombine(localSearchData.fullPath, findData.cFileName); + String userPathFinal = Path.Combine(localSearchData.userPath, findData.cFileName); + String fullPathFinal = Path.Combine(localSearchData.fullPath, findData.cFileName); return new SearchResult(fullPathFinal, userPathFinal, findData); } - [System.Security.SecurityCritical] private void HandleError(int hr, String path) { Dispose(); __Error.WinIOError(hr, path); } - [System.Security.SecurityCritical] // auto-generated private void AddSearchableDirsToStack(Directory.SearchData localSearchData) { Contract.Requires(localSearchData != null); - String searchPath = Path.InternalCombine(localSearchData.fullPath, "*"); + String searchPath = Path.Combine(localSearchData.fullPath, "*"); SafeFindHandle hnd = null; Win32Native.WIN32_FIND_DATA data = new Win32Native.WIN32_FIND_DATA(); try @@ -553,8 +488,8 @@ namespace System.IO { if (FileSystemEnumerableHelpers.IsDir(data)) { - String tempFullPath = Path.InternalCombine(localSearchData.fullPath, data.cFileName); - String tempUserPath = Path.InternalCombine(localSearchData.userPath, data.cFileName); + String tempFullPath = Path.Combine(localSearchData.fullPath, data.cFileName); + String tempUserPath = Path.Combine(localSearchData.userPath, data.cFileName); SearchOption option = localSearchData.searchOption; @@ -578,28 +513,12 @@ namespace System.IO } } - [System.Security.SecurityCritical] - internal void DoDemand(String fullPathToDemand) - { -#if FEATURE_CORECLR - if(_checkHost) { - String demandDir = Directory.GetDemandDir(fullPathToDemand, true); - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandDir); - state.EnsureState(); - } -#else - String demandDir = Directory.GetDemandDir(fullPathToDemand, true); - String[] demandPaths = new String[] { demandDir }; - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPaths, false, false).Demand(); -#endif - } - private static String NormalizeSearchPattern(String searchPattern) { Contract.Requires(searchPattern != null); - // Win32 normalization trims only U+0020. - String tempSearchPattern = searchPattern.TrimEnd(Path.TrimEndChars); + // Win32 normalization trims only U+0020. + String tempSearchPattern = searchPattern.TrimEnd(PathInternal.s_trimEndChars); // Make this corner case more useful, like dir if (tempSearchPattern.Equals(".")) @@ -607,7 +526,7 @@ namespace System.IO tempSearchPattern = "*"; } - Path.CheckSearchPattern(tempSearchPattern); + PathInternal.CheckSearchPattern(tempSearchPattern); return tempSearchPattern; } @@ -619,14 +538,14 @@ namespace System.IO String searchCriteria = null; char lastChar = fullPathMod[fullPathMod.Length - 1]; - if (Path.IsDirectorySeparator(lastChar)) + if (PathInternal.IsDirectorySeparator(lastChar)) { // Can happen if the path is C:\temp, in which case GetDirectoryName would return C:\ searchCriteria = fullSearchString.Substring(fullPathMod.Length); } else { - Contract.Assert(fullSearchString.Length > fullPathMod.Length); + Debug.Assert(fullSearchString.Length > fullPathMod.Length); searchCriteria = fullSearchString.Substring(fullPathMod.Length + 1); } return searchCriteria; @@ -637,11 +556,11 @@ namespace System.IO Contract.Requires(fullPath != null); Contract.Requires(searchPattern != null); - String tempStr = Path.InternalCombine(fullPath, searchPattern); + String tempStr = Path.Combine(fullPath, searchPattern); // If path ends in a trailing slash (\), append a * or we'll get a "Cannot find the file specified" exception char lastChar = tempStr[tempStr.Length - 1]; - if (Path.IsDirectorySeparator(lastChar) || lastChar == Path.VolumeSeparatorChar) + if (PathInternal.IsDirectorySeparator(lastChar) || lastChar == Path.VolumeSeparatorChar) { tempStr = tempStr + '*'; } @@ -653,10 +572,8 @@ namespace System.IO internal abstract class SearchResultHandler { - [System.Security.SecurityCritical] internal abstract bool IsResultIncluded(SearchResult result); - [System.Security.SecurityCritical] internal abstract TSource CreateObject(SearchResult result); } @@ -672,16 +589,14 @@ namespace System.IO _includeDirs = includeDirs; } - [System.Security.SecurityCritical] internal override bool IsResultIncluded(SearchResult result) { bool includeFile = _includeFiles && FileSystemEnumerableHelpers.IsFile(result.FindData); bool includeDir = _includeDirs && FileSystemEnumerableHelpers.IsDir(result.FindData); - Contract.Assert(!(includeFile && includeDir), result.FindData.cFileName + ": current item can't be both file and dir!"); + Debug.Assert(!(includeFile && includeDir), result.FindData.cFileName + ": current item can't be both file and dir!"); return (includeFile || includeDir); } - [System.Security.SecurityCritical] internal override String CreateObject(SearchResult result) { return result.UserPath; @@ -690,23 +605,14 @@ namespace System.IO internal class FileInfoResultHandler : SearchResultHandler { - [System.Security.SecurityCritical] internal override bool IsResultIncluded(SearchResult result) { return FileSystemEnumerableHelpers.IsFile(result.FindData); } - [System.Security.SecurityCritical] internal override FileInfo CreateObject(SearchResult result) { String name = result.FullPath; -#if FEATURE_CORECLR - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, name); - state.EnsureState(); -#else - String[] names = new String[] { name }; - new FileIOPermission(FileIOPermissionAccess.Read, names, false, false).Demand(); -#endif FileInfo fi = new FileInfo(name, false); fi.InitializeFrom(result.FindData); return fi; @@ -715,26 +621,14 @@ namespace System.IO internal class DirectoryInfoResultHandler : SearchResultHandler { - [System.Security.SecurityCritical] internal override bool IsResultIncluded(SearchResult result) { return FileSystemEnumerableHelpers.IsDir(result.FindData); } - [System.Security.SecurityCritical] internal override DirectoryInfo CreateObject(SearchResult result) { - String name = result.FullPath; - String permissionName = name + "\\."; - -#if FEATURE_CORECLR - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, permissionName); - state.EnsureState(); -#else - String[] permissionNames = new String[] { permissionName }; - new FileIOPermission(FileIOPermissionAccess.Read, permissionNames, false, false).Demand(); -#endif - DirectoryInfo di = new DirectoryInfo(name, false); + DirectoryInfo di = new DirectoryInfo(result.FullPath, false); di.InitializeFrom(result.FindData); return di; } @@ -743,17 +637,15 @@ namespace System.IO internal class FileSystemInfoResultHandler : SearchResultHandler { - [System.Security.SecurityCritical] internal override bool IsResultIncluded(SearchResult result) { bool includeFile = FileSystemEnumerableHelpers.IsFile(result.FindData); bool includeDir = FileSystemEnumerableHelpers.IsDir(result.FindData); - Contract.Assert(!(includeFile && includeDir), result.FindData.cFileName + ": current item can't be both file and dir!"); + Debug.Assert(!(includeFile && includeDir), result.FindData.cFileName + ": current item can't be both file and dir!"); return (includeDir || includeFile); } - [System.Security.SecurityCritical] internal override FileSystemInfo CreateObject(SearchResult result) { bool isFile = FileSystemEnumerableHelpers.IsFile(result.FindData); @@ -761,33 +653,14 @@ namespace System.IO if (isDir) { - String name = result.FullPath; - String permissionName = name + "\\."; - -#if FEATURE_CORECLR - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, permissionName); - state.EnsureState(); -#else - String[] permissionNames = new String[] { permissionName }; - new FileIOPermission(FileIOPermissionAccess.Read, permissionNames, false, false).Demand(); -#endif - DirectoryInfo di = new DirectoryInfo(name, false); + DirectoryInfo di = new DirectoryInfo(result.FullPath, false); di.InitializeFrom(result.FindData); return di; } else { Contract.Assert(isFile); - String name = result.FullPath; - -#if FEATURE_CORECLR - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, name); - state.EnsureState(); -#else - String[] names = new String[] { name }; - new FileIOPermission(FileIOPermissionAccess.Read, names, false, false).Demand(); -#endif - FileInfo fi = new FileInfo(name, false); + FileInfo fi = new FileInfo(result.FullPath, false); fi.InitializeFrom(result.FindData); return fi; } @@ -799,10 +672,8 @@ namespace System.IO { private String fullPath; // fully-qualifed path private String userPath; // user-specified path - [System.Security.SecurityCritical] private Win32Native.WIN32_FIND_DATA findData; - [System.Security.SecurityCritical] internal SearchResult(String fullPath, String userPath, Win32Native.WIN32_FIND_DATA findData) { Contract.Requires(fullPath != null); @@ -825,15 +696,12 @@ namespace System.IO internal Win32Native.WIN32_FIND_DATA FindData { - [System.Security.SecurityCritical] get { return findData; } } - } internal static class FileSystemEnumerableHelpers { - [System.Security.SecurityCritical] // auto-generated internal static bool IsDir(Win32Native.WIN32_FIND_DATA data) { // Don't add "." nor ".." @@ -841,7 +709,6 @@ namespace System.IO && !data.cFileName.Equals(".") && !data.cFileName.Equals(".."); } - [System.Security.SecurityCritical] // auto-generated internal static bool IsFile(Win32Native.WIN32_FIND_DATA data) { return 0 == (data.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY); diff --git a/src/mscorlib/src/System/IO/FileSystemInfo.cs b/src/mscorlib/src/System/IO/FileSystemInfo.cs index 7a17a41..94cd531 100644 --- a/src/mscorlib/src/System/IO/FileSystemInfo.cs +++ b/src/mscorlib/src/System/IO/FileSystemInfo.cs @@ -2,43 +2,19 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -/*============================================================ -** -** -** -** -** -** Purpose: -** -** -===========================================================*/ - -using System; -using System.Collections; -using System.Security; -using System.Security.Permissions; using Microsoft.Win32; -using System.Text; using System.Runtime.InteropServices; using System.Runtime.Serialization; -using System.Runtime.Versioning; using System.Diagnostics.Contracts; -namespace System.IO { +namespace System.IO +{ #if FEATURE_SERIALIZATION [Serializable] #endif -#if !FEATURE_CORECLR - [FileIOPermissionAttribute(SecurityAction.InheritanceDemand,Unrestricted=true)] -#endif [ComVisible(true)] -#if FEATURE_REMOTING public abstract class FileSystemInfo : MarshalByRefObject, ISerializable { -#else // FEATURE_REMOTING - public abstract class FileSystemInfo : ISerializable { -#endif //FEATURE_REMOTING - [System.Security.SecurityCritical] // auto-generated internal Win32Native.WIN32_FILE_ATTRIBUTE_DATA _data; // Cache the file information internal int _dataInitialised = -1; // We use this field in conjunction with the Refresh methods, if we succeed // we store a zero, on failure we store the HResult in it so that we can @@ -51,13 +27,6 @@ namespace System.IO { protected String OriginalPath; // path passed in by the user private String _displayPath = ""; // path that can be displayed to the user -#if FEATURE_CORECLR -#if FEATURE_CORESYSTEM - [System.Security.SecurityCritical] -#else - [System.Security.SecuritySafeCritical] -#endif //FEATURE_CORESYSTEM -#endif protected FileSystemInfo() { } @@ -65,19 +34,18 @@ namespace System.IO { protected FileSystemInfo(SerializationInfo info, StreamingContext context) { if (info == null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); - + // Must use V1 field names here, since V1 didn't implement // ISerializable. - FullPath = Path.GetFullPathInternal(info.GetString("FullPath")); + FullPath = Path.GetFullPath(info.GetString("FullPath")); OriginalPath = info.GetString("OriginalPath"); // Lazily initialize the file attributes. _dataInitialised = -1; } - [System.Security.SecurityCritical] internal void InitializeFrom(Win32Native.WIN32_FIND_DATA findData) { _data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA(); @@ -87,37 +55,8 @@ namespace System.IO { // Full path of the direcory/file public virtual String FullName { - [System.Security.SecuritySafeCritical] get { - String demandDir; - if (this is DirectoryInfo) - demandDir = Directory.GetDemandDir(FullPath, true); - else - demandDir = FullPath; -#if FEATURE_CORECLR - FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandDir); - sourceState.EnsureState(); -#else - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandDir).Demand(); -#endif - return FullPath; - } - } - - internal virtual String UnsafeGetFullName - { - [System.Security.SecurityCritical] - get - { - String demandDir; - if (this is DirectoryInfo) - demandDir = Directory.GetDemandDir(FullPath, true); - else - demandDir = FullPath; -#if !FEATURE_CORECLR - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandDir).Demand(); -#endif return FullPath; } } @@ -160,21 +99,11 @@ namespace System.IO { // depends on the security check in get_CreationTimeUtc return CreationTimeUtc.ToLocalTime(); } - - set { - CreationTimeUtc = value.ToUniversalTime(); - } } [ComVisible(false)] public DateTime CreationTimeUtc { - [System.Security.SecuritySafeCritical] get { -#if FEATURE_CORECLR - // get_CreationTime also depends on this security check - FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, FullPath); - sourceState.EnsureState(); -#endif if (_dataInitialised == -1) { _data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA(); Refresh(); @@ -187,19 +116,10 @@ namespace System.IO { return DateTime.FromFileTimeUtc(fileTime); } - - set { - if (this is DirectoryInfo) - Directory.SetCreationTimeUtc(FullPath,value); - else - File.SetCreationTimeUtc(FullPath,value); - _dataInitialised = -1; - } } - public DateTime LastAccessTime - { + { get { // depends on the security check in get_LastAccessTimeUtc return LastAccessTimeUtc.ToLocalTime(); @@ -211,13 +131,7 @@ namespace System.IO { [ComVisible(false)] public DateTime LastAccessTimeUtc { - [System.Security.SecuritySafeCritical] get { -#if FEATURE_CORECLR - // get_LastAccessTime also depends on this security check - FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, FullPath); - sourceState.EnsureState(); -#endif if (_dataInitialised == -1) { _data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA(); Refresh(); @@ -228,15 +142,9 @@ namespace System.IO { long fileTime = ((long)_data.ftLastAccessTimeHigh << 32) | _data.ftLastAccessTimeLow; return DateTime.FromFileTimeUtc(fileTime); - } set { - if (this is DirectoryInfo) - Directory.SetLastAccessTimeUtc(FullPath,value); - else - File.SetLastAccessTimeUtc(FullPath,value); - _dataInitialised = -1; } } @@ -254,13 +162,7 @@ namespace System.IO { [ComVisible(false)] public DateTime LastWriteTimeUtc { - [System.Security.SecuritySafeCritical] get { -#if FEATURE_CORECLR - // get_LastWriteTime also depends on this security check - FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, FullPath); - sourceState.EnsureState(); -#endif if (_dataInitialised == -1) { _data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA(); Refresh(); @@ -275,28 +177,17 @@ namespace System.IO { } set { - if (this is DirectoryInfo) - Directory.SetLastWriteTimeUtc(FullPath,value); - else - File.SetLastWriteTimeUtc(FullPath,value); - _dataInitialised = -1; } } - [System.Security.SecuritySafeCritical] // auto-generated public void Refresh() { _dataInitialised = File.FillAttributeInfo(FullPath, ref _data, false, false); } public FileAttributes Attributes { - [System.Security.SecuritySafeCritical] get { -#if FEATURE_CORECLR - FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, FullPath); - sourceState.EnsureState(); -#endif if (_dataInitialised == -1) { _data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA(); Refresh(); // Call refresh to intialise the data @@ -307,15 +198,8 @@ namespace System.IO { return (FileAttributes) _data.fileAttributes; } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif + set { -#if !FEATURE_CORECLR - new FileIOPermission(FileIOPermissionAccess.Write, FullPath).Demand(); -#endif bool r = Win32Native.SetFileAttributes(FullPath, (int) value); if (!r) { int hr = Marshal.GetLastWin32Error(); @@ -334,14 +218,9 @@ namespace System.IO { } } - [System.Security.SecurityCritical] // auto-generated_required [ComVisible(false)] public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { -#if !FEATURE_CORECLR - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, FullPath).Demand(); -#endif - info.AddValue("OriginalPath", OriginalPath, typeof(String)); info.AddValue("FullPath", FullPath, typeof(String)); } @@ -357,5 +236,5 @@ namespace System.IO { _displayPath = value; } } - } + } } diff --git a/src/mscorlib/src/System/IO/LongPathHelper.cs b/src/mscorlib/src/System/IO/LongPathHelper.cs deleted file mode 100644 index 9746fdc..0000000 --- a/src/mscorlib/src/System/IO/LongPathHelper.cs +++ /dev/null @@ -1,521 +0,0 @@ -// 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.Diagnostics.Contracts; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using Microsoft.Win32; - -namespace System.IO -{ - /// - /// Wrapper to help with path normalization. - /// - internal class LongPathHelper - { - // Can't be over 8.3 and be a short name - private const int MaxShortName = 12; - - private const char LastAnsi = (char)255; - private const char Delete = (char)127; - - [ThreadStatic] - private static StringBuffer t_fullPathBuffer; - - /// - /// Normalize the given path. - /// - /// - /// Normalizes via Win32 GetFullPathName(). It will also trim all "typical" whitespace at the end of the path (see s_trimEndChars). Will also trim initial - /// spaces if the path is determined to be rooted. - /// - /// Note that invalid characters will be checked after the path is normalized, which could remove bad characters. (C:\|\..\a.txt -- C:\a.txt) - /// - /// Path to normalize - /// True to check for invalid characters - /// Attempt to expand short paths if true - /// Thrown if the path is an illegal UNC (does not contain a full server/share) or contains illegal characters. - /// Thrown if the path or a path segment exceeds the filesystem limits. - /// Thrown if Windows returns ERROR_FILE_NOT_FOUND. (See Win32Marshal.GetExceptionForWin32Error) - /// Thrown if Windows returns ERROR_PATH_NOT_FOUND. (See Win32Marshal.GetExceptionForWin32Error) - /// Thrown if Windows returns ERROR_ACCESS_DENIED. (See Win32Marshal.GetExceptionForWin32Error) - /// Thrown if Windows returns an error that doesn't map to the above. (See Win32Marshal.GetExceptionForWin32Error) - /// Normalized path - [System.Security.SecurityCritical] - unsafe internal static string Normalize(string path, uint maxPathLength, bool checkInvalidCharacters, bool expandShortPaths) - { - // Get the full path - StringBuffer fullPath = t_fullPathBuffer ?? (t_fullPathBuffer = new StringBuffer(PathInternal.MaxShortPath)); - try - { - GetFullPathName(path, fullPath); - - // Trim whitespace off the end of the string. Win32 normalization trims only U+0020. - fullPath.TrimEnd(Path.TrimEndChars); - - if (fullPath.Length >= maxPathLength) - { - // Fullpath is genuinely too long - throw new PathTooLongException(); - } - - // Checking path validity used to happen before getting the full path name. To avoid additional input allocation - // (to trim trailing whitespace) we now do it after the Win32 call. This will allow legitimate paths through that - // used to get kicked back (notably segments with invalid characters might get removed via ".."). - // - // There is no way that GetLongPath can invalidate the path so we'll do this (cheaper) check before we attempt to - // expand short file names. - - // Scan the path for: - // - // - Illegal path characters. - // - Invalid UNC paths like \\, \\server, \\server\. - // - Segments that are too long (over MaxComponentLength) - - // As the path could be > 60K, we'll combine the validity scan. None of these checks are performed by the Win32 - // GetFullPathName() API. - - bool possibleShortPath = false; - bool foundTilde = false; - - // We can get UNCs as device paths through this code (e.g. \\.\UNC\), we won't validate them as there isn't - // an easy way to normalize without extensive cost (we'd have to hunt down the canonical name for any device - // path that contains UNC or to see if the path was doing something like \\.\GLOBALROOT\Device\Mup\, - // \\.\GLOBAL\UNC\, \\.\GLOBALROOT\GLOBAL??\UNC\, etc. - bool specialPath = fullPath.Length > 1 && fullPath[0] == '\\' && fullPath[1] == '\\'; - bool isDevice = PathInternal.IsDevice(fullPath); - bool possibleBadUnc = specialPath && !isDevice; - uint index = specialPath ? 2u : 0; - uint lastSeparator = specialPath ? 1u : 0; - uint segmentLength; - char* start = fullPath.CharPointer; - char current; - - while (index < fullPath.Length) - { - current = start[index]; - - // Try to skip deeper analysis. '?' and higher are valid/ignorable except for '\', '|', and '~' - if (current < '?' || current == '\\' || current == '|' || current == '~') - { - switch (current) - { - case '|': - case '>': - case '<': - case '\"': - if (checkInvalidCharacters) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars")); - // No point in expanding a bad path - foundTilde = false; - break; - case '~': - foundTilde = true; - break; - case '\\': - segmentLength = index - lastSeparator - 1; - if (segmentLength > (uint)PathInternal.MaxComponentLength) - throw new PathTooLongException(); - lastSeparator = index; - - if (foundTilde) - { - if (segmentLength <= MaxShortName) - { - // Possibly a short path. - possibleShortPath = true; - } - - foundTilde = false; - } - - if (possibleBadUnc) - { - // If we're at the end of the path and this is the first separator, we're missing the share. - // Otherwise we're good, so ignore UNC tracking from here. - if (index == fullPath.Length - 1) - throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegalUNC")); - else - possibleBadUnc = false; - } - - break; - - default: - if (checkInvalidCharacters && current < ' ') throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars")); - break; - } - } - - index++; - } - - if (possibleBadUnc) - throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegalUNC")); - - segmentLength = fullPath.Length - lastSeparator - 1; - if (segmentLength > (uint)PathInternal.MaxComponentLength) - throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - - if (foundTilde && segmentLength <= MaxShortName) - possibleShortPath = true; - - // Check for a short filename path and try and expand it. Technically you don't need to have a tilde for a short name, but - // this is how we've always done this. This expansion is costly so we'll continue to let other short paths slide. - if (expandShortPaths && possibleShortPath) - { - return TryExpandShortFileName(fullPath, originalPath: path); - } - else - { - if (fullPath.Length == (uint)path.Length && fullPath.StartsWith(path)) - { - // If we have the exact same string we were passed in, don't bother to allocate another string from the StringBuilder. - return path; - } - else - { - return fullPath.ToString(); - } - } - } - finally - { - // Clear the buffer - fullPath.Free(); - } - } - - [System.Security.SecurityCritical] - unsafe private static void GetFullPathName(string path, StringBuffer fullPath) - { - // If the string starts with an extended prefix we would need to remove it from the path before we call GetFullPathName as - // it doesn't root extended paths correctly. We don't currently resolve extended paths, so we'll just assert here. - Contract.Assert(PathInternal.IsPartiallyQualified(path) || !PathInternal.IsExtended(path)); - - // Historically we would skip leading spaces *only* if the path started with a drive " C:" or a UNC " \\" - int startIndex = PathInternal.PathStartSkip(path); - - fixed (char* pathStart = path) - { - uint result = 0; - while ((result = Win32Native.GetFullPathNameW(pathStart + startIndex, fullPath.CharCapacity, fullPath.GetHandle(), IntPtr.Zero)) > fullPath.CharCapacity) - { - // Reported size (which does not include the null) is greater than the buffer size. Increase the capacity. - fullPath.EnsureCharCapacity(result); - } - - if (result == 0) - { - // Failure, get the error and throw - int errorCode = Marshal.GetLastWin32Error(); - if (errorCode == 0) - errorCode = Win32Native.ERROR_BAD_PATHNAME; - __Error.WinIOError(errorCode, path); - } - - fullPath.Length = result; - } - } - - [System.Security.SecurityCritical] - unsafe internal static string GetLongPathName(StringBuffer path) - { - using (StringBuffer outputBuffer = new StringBuffer(path.Length)) - { - uint result = 0; - while ((result = Win32Native.GetLongPathNameW(path.GetHandle(), outputBuffer.GetHandle(), outputBuffer.CharCapacity)) > outputBuffer.CharCapacity) - { - // Reported size (which does not include the null) is greater than the buffer size. Increase the capacity. - outputBuffer.EnsureCharCapacity(result); - } - - if (result == 0) - { - // Failure, get the error and throw - GetErrorAndThrow(path.ToString()); - } - - outputBuffer.Length = result; - return outputBuffer.ToString(); - } - } - - [System.Security.SecurityCritical] - unsafe internal static string GetLongPathName(string path) - { - using (StringBuffer outputBuffer = new StringBuffer((uint)path.Length)) - { - uint result = 0; - while ((result = Win32Native.GetLongPathNameW(path, outputBuffer.GetHandle(), outputBuffer.CharCapacity)) > outputBuffer.CharCapacity) - { - // Reported size (which does not include the null) is greater than the buffer size. Increase the capacity. - outputBuffer.EnsureCharCapacity(result); - } - - if (result == 0) - { - // Failure, get the error and throw - GetErrorAndThrow(path); - } - - outputBuffer.Length = result; - return outputBuffer.ToString(); - } - } - - [System.Security.SecurityCritical] - private static void GetErrorAndThrow(string path) - { - int errorCode = Marshal.GetLastWin32Error(); - if (errorCode == 0) - errorCode = Win32Native.ERROR_BAD_PATHNAME; - __Error.WinIOError(errorCode, path); - } - - // It is significantly more complicated to get the long path with minimal allocations if we're injecting the extended dos path prefix. The implicit version - // should match up with what is in CoreFx System.Runtime.Extensions. -#if !FEATURE_IMPLICIT_LONGPATH - [System.Security.SecuritySafeCritical] - private unsafe static string TryExpandShortFileName(StringBuffer outputBuffer, string originalPath) - { - // We guarantee we'll expand short names for paths that only partially exist. As such, we need to find the part of the path that actually does exist. To - // avoid allocating like crazy we'll create only one input array and modify the contents with embedded nulls. - - Contract.Assert(!PathInternal.IsPartiallyQualified(outputBuffer), "should have resolved by now"); - - using (StringBuffer inputBuffer = new StringBuffer(outputBuffer)) - { - bool success = false; - uint lastIndex = outputBuffer.Length - 1; - uint foundIndex = lastIndex; - uint rootLength = PathInternal.GetRootLength(outputBuffer); - - while (!success) - { - uint result = Win32Native.GetLongPathNameW(inputBuffer.GetHandle(), outputBuffer.GetHandle(), outputBuffer.CharCapacity); - - // Replace any temporary null we added - if (inputBuffer[foundIndex] == '\0') inputBuffer[foundIndex] = '\\'; - - if (result == 0) - { - // Look to see if we couldn't find the file - int error = Marshal.GetLastWin32Error(); - if (error != Win32Native.ERROR_FILE_NOT_FOUND && error != Win32Native.ERROR_PATH_NOT_FOUND) - { - // Some other failure, give up - break; - } - - // We couldn't find the path at the given index, start looking further back in the string. - foundIndex--; - - for (; foundIndex > rootLength && inputBuffer[foundIndex] != '\\'; foundIndex--) ; - if (foundIndex == rootLength) - { - // Can't trim the path back any further - break; - } - else - { - // Temporarily set a null in the string to get Windows to look further up the path - inputBuffer[foundIndex] = '\0'; - } - } - else if (result > outputBuffer.CharCapacity) - { - // Not enough space. The result count for this API does not include the null terminator. - outputBuffer.EnsureCharCapacity(result); - } - else - { - // Found the path - success = true; - outputBuffer.Length = result; - if (foundIndex < lastIndex) - { - // It was a partial find, put the non-existant part of the path back - outputBuffer.Append(inputBuffer, foundIndex, inputBuffer.Length - foundIndex); - } - } - } - - StringBuffer bufferToUse = success ? outputBuffer : inputBuffer; - - if (bufferToUse.SubstringEquals(originalPath)) - { - // Use the original path to avoid allocating - return originalPath; - } - - return bufferToUse.ToString(); - } - } -#else // !FEATURE_IMPLICIT_LONGPATH - - private static uint GetInputBuffer(StringBuffer content, bool isDosUnc, out StringBuffer buffer) - { - uint length = content.Length; - - length += isDosUnc - ? (uint)PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength - : PathInternal.DevicePrefixLength; - - buffer = new StringBuffer(length); - - if (isDosUnc) - { - // Put the extended UNC prefix (\\?\UNC\) in front of the path - buffer.CopyFrom(bufferIndex: 0, source: PathInternal.UncExtendedPathPrefix); - - // Copy the source buffer over after the existing UNC prefix - content.CopyTo( - bufferIndex: PathInternal.UncPrefixLength, - destination: buffer, - destinationIndex: PathInternal.UncExtendedPrefixLength, - count: content.Length - PathInternal.UncPrefixLength); - - // Return the prefix difference - return (uint)PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength; - } - else - { - uint prefixSize = (uint)PathInternal.ExtendedPathPrefix.Length; - buffer.CopyFrom(bufferIndex: 0, source: PathInternal.ExtendedPathPrefix); - content.CopyTo(bufferIndex: 0, destination: buffer, destinationIndex: prefixSize, count: content.Length); - return prefixSize; - } - } - - [System.Security.SecuritySafeCritical] - private static string TryExpandShortFileName(StringBuffer outputBuffer, string originalPath) - { - // We'll have one of a few cases by now (the normalized path will have already: - // - // 1. Dos path (C:\) - // 2. Dos UNC (\\Server\Share) - // 3. Dos device path (\\.\C:\, \\?\C:\) - // - // We want to put the extended syntax on the front if it doesn't already have it, which may mean switching from \\.\. - - uint rootLength = PathInternal.GetRootLength(outputBuffer); - bool isDevice = PathInternal.IsDevice(outputBuffer); - - StringBuffer inputBuffer = null; - bool isDosUnc = false; - uint rootDifference = 0; - bool wasDotDevice = false; - - // Add the extended prefix before expanding to allow growth over MAX_PATH - if (isDevice) - { - // We have one of the following (\\?\ or \\.\) - // We will never get \??\ here as GetFullPathName() does not recognize \??\ and will return it as C:\??\ (or whatever the current drive is). - inputBuffer = new StringBuffer(); - inputBuffer.Append(outputBuffer); - - if (outputBuffer[2] == '.') - { - wasDotDevice = true; - inputBuffer[2] = '?'; - } - } - else - { - // \\Server\Share, but not \\.\ or \\?\. - // We need to know this to be able to push \\?\UNC\ on if required - isDosUnc = outputBuffer.Length > 1 && outputBuffer[0] == '\\' && outputBuffer[1] == '\\' && !PathInternal.IsDevice(outputBuffer); - rootDifference = GetInputBuffer(outputBuffer, isDosUnc, out inputBuffer); - } - - rootLength += rootDifference; - uint inputLength = inputBuffer.Length; - - bool success = false; - uint foundIndex = inputBuffer.Length - 1; - - while (!success) - { - uint result = Win32Native.GetLongPathNameW(inputBuffer.GetHandle(), outputBuffer.GetHandle(), outputBuffer.CharCapacity); - - // Replace any temporary null we added - if (inputBuffer[foundIndex] == '\0') inputBuffer[foundIndex] = '\\'; - - if (result == 0) - { - // Look to see if we couldn't find the file - int error = Marshal.GetLastWin32Error(); - if (error != Win32Native.ERROR_FILE_NOT_FOUND && error != Win32Native.ERROR_PATH_NOT_FOUND) - { - // Some other failure, give up - break; - } - - // We couldn't find the path at the given index, start looking further back in the string. - foundIndex--; - - for (; foundIndex > rootLength && inputBuffer[foundIndex] != '\\'; foundIndex--) ; - if (foundIndex == rootLength) - { - // Can't trim the path back any further - break; - } - else - { - // Temporarily set a null in the string to get Windows to look further up the path - inputBuffer[foundIndex] = '\0'; - } - } - else if (result > outputBuffer.CharCapacity) - { - // Not enough space. The result count for this API does not include the null terminator. - outputBuffer.EnsureCharCapacity(result); - result = Win32Native.GetLongPathNameW(inputBuffer.GetHandle(), outputBuffer.GetHandle(), outputBuffer.CharCapacity); - } - else - { - // Found the path - success = true; - outputBuffer.Length = result; - if (foundIndex < inputLength - 1) - { - // It was a partial find, put the non-existent part of the path back - outputBuffer.Append(inputBuffer, foundIndex, inputBuffer.Length - foundIndex); - } - } - } - - // Strip out the prefix and return the string - StringBuffer bufferToUse = success ? outputBuffer : inputBuffer; - - // Switch back from \\?\ to \\.\ if necessary - if (wasDotDevice) - bufferToUse[2] = '.'; - - string returnValue = null; - - int newLength = (int)(bufferToUse.Length - rootDifference); - if (isDosUnc) - { - // Need to go from \\?\UNC\ to \\?\UN\\ - bufferToUse[PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength] = '\\'; - } - - // We now need to strip out any added characters at the front of the string - if (bufferToUse.SubstringEquals(originalPath, rootDifference, newLength)) - { - // Use the original path to avoid allocating - returnValue = originalPath; - } - else - { - returnValue = bufferToUse.Substring(rootDifference, newLength); - } - - inputBuffer.Dispose(); - return returnValue; - } -#endif // FEATURE_IMPLICIT_LONGPATH - } -} \ No newline at end of file diff --git a/src/mscorlib/src/System/IO/MemoryStream.cs b/src/mscorlib/src/System/IO/MemoryStream.cs index edb583b..bdddc83 100644 --- a/src/mscorlib/src/System/IO/MemoryStream.cs +++ b/src/mscorlib/src/System/IO/MemoryStream.cs @@ -19,6 +19,7 @@ using System; using System.Runtime; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Threading; using System.Threading.Tasks; @@ -61,7 +62,7 @@ namespace System.IO { public MemoryStream(int capacity) { if (capacity < 0) { - throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_NegativeCapacity")); + throw new ArgumentOutOfRangeException(nameof(capacity), Environment.GetResourceString("ArgumentOutOfRange_NegativeCapacity")); } Contract.EndContractBlock(); @@ -79,7 +80,7 @@ namespace System.IO { } public MemoryStream(byte[] buffer, bool writable) { - if (buffer == null) throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + if (buffer == null) throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); Contract.EndContractBlock(); _buffer = buffer; _length = _capacity = buffer.Length; @@ -99,11 +100,11 @@ namespace System.IO { public MemoryStream(byte[] buffer, int index, int count, bool writable, bool publiclyVisible) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -180,7 +181,6 @@ namespace System.IO { public override void Flush() { } - [HostProtection(ExternalThreading=true)] [ComVisible(false)] public override Task FlushAsync(CancellationToken cancellationToken) { @@ -259,7 +259,7 @@ namespace System.IO { if (n > count) n = count; if (n < 0) n = 0; - Contract.Assert(_position + n >= 0, "_position + n >= 0"); // len is less than 2^31 -1. + Debug.Assert(_position + n >= 0, "_position + n >= 0"); // len is less than 2^31 -1. _position += n; return n; } @@ -276,7 +276,7 @@ namespace System.IO { set { // Only update the capacity if the MS is expandable and the value is different than the current capacity. // Special behavior if the MS isn't expandable: we don't throw if value is the same as the current capacity - if (value < Length) throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity")); + if (value < Length) throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity")); Contract.Ensures(_capacity - _origin == value); Contract.EndContractBlock(); @@ -312,25 +312,25 @@ namespace System.IO { } set { if (value < 0) - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.Ensures(Position == value); Contract.EndContractBlock(); if (!_isOpen) __Error.StreamIsClosed(); if (value > MemStreamMaxLength) - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_StreamLength")); + throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_StreamLength")); _position = _origin + (int)value; } } public override int Read([In, Out] byte[] buffer, int offset, int count) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(offset), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - offset < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -342,7 +342,7 @@ namespace System.IO { if (n <= 0) return 0; - Contract.Assert(_position + n >= 0, "_position + n >= 0"); // len is less than 2^31 -1. + Debug.Assert(_position + n >= 0, "_position + n >= 0"); // len is less than 2^31 -1. if (n <= 8) { @@ -357,16 +357,15 @@ namespace System.IO { return n; } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public override Task ReadAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(offset), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - offset < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); // contract validation copied from Read(...) @@ -379,7 +378,7 @@ namespace System.IO { { int n = Read(buffer, offset, count); var t = _lastReadTask; - Contract.Assert(t == null || t.Status == TaskStatus.RanToCompletion, + 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)); } @@ -402,36 +401,46 @@ namespace System.IO { return _buffer[_position++]; } + public override void CopyTo(Stream destination, int bufferSize) + { + // Since we did not originally override this method, validate the arguments + // the same way Stream does for back-compat. + StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize); - public override Task CopyToAsync(Stream destination, Int32 bufferSize, CancellationToken cancellationToken) { - - // This implementation offers beter performance compared to the base class version. - - // The parameter checks must be in sync with the base version: - if (destination == null) - throw new ArgumentNullException("destination"); + // 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. + // To be safe we will only use this implementation in cases where we know it is safe to do so, + // and delegate to our base class (which will call into Read) when we are not sure. + if (GetType() != typeof(MemoryStream)) + { + base.CopyTo(destination, bufferSize); + return; + } - if (bufferSize <= 0) - throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); + int originalPosition = _position; - if (!CanRead && !CanWrite) - throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_StreamClosed")); + // Seek to the end of the MemoryStream. + int remaining = InternalEmulateRead(_length - originalPosition); - if (!destination.CanRead && !destination.CanWrite) - throw new ObjectDisposedException("destination", Environment.GetResourceString("ObjectDisposed_StreamClosed")); + // If we were already at or past the end, there's no copying to do so just quit. + if (remaining > 0) + { + // Call Write() on the other Stream, using our internal buffer and avoiding any + // intermediary allocations. + destination.Write(_buffer, originalPosition, remaining); + } + } - if (!CanRead) - throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnreadableStream")); + public override Task CopyToAsync(Stream destination, Int32 bufferSize, CancellationToken cancellationToken) { - if (!destination.CanWrite) - throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnwritableStream")); + // This implementation offers beter performance compared to the base class version. - Contract.EndContractBlock(); + StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize); // If we have been inherited into a subclass, the following implementation could be incorrect - // since it does not call through to Read() or Write() which a subclass might have overriden. + // since it does not call through to ReadAsync() which a subclass might have overridden. // To be safe we will only use this implementation in cases where we know it is safe to do so, - // and delegate to our base class (which will call into Read/Write) when we are not sure. + // and delegate to our base class (which will call into ReadAsync) when we are not sure. if (this.GetType() != typeof(MemoryStream)) return base.CopyToAsync(destination, bufferSize, cancellationToken); @@ -467,7 +476,7 @@ namespace System.IO { if (!_isOpen) __Error.StreamIsClosed(); if (offset > MemStreamMaxLength) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_StreamLength")); + throw new ArgumentOutOfRangeException(nameof(offset), Environment.GetResourceString("ArgumentOutOfRange_StreamLength")); switch(loc) { case SeekOrigin.Begin: { int tempPosition = unchecked(_origin + (int)offset); @@ -494,7 +503,7 @@ namespace System.IO { throw new ArgumentException(Environment.GetResourceString("Argument_InvalidSeekOrigin")); } - Contract.Assert(_position >= 0, "_position >= 0"); + Debug.Assert(_position >= 0, "_position >= 0"); return _position; } @@ -510,16 +519,16 @@ namespace System.IO { // public override void SetLength(long value) { if (value < 0 || value > Int32.MaxValue) { - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_StreamLength")); + throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_StreamLength")); } Contract.Ensures(_length - _origin == value); Contract.EndContractBlock(); EnsureWriteable(); // Origin wasn't publicly exposed above. - Contract.Assert(MemStreamMaxLength == Int32.MaxValue); // Check parameter validation logic in this method if this fails. + Debug.Assert(MemStreamMaxLength == Int32.MaxValue); // Check parameter validation logic in this method if this fails. if (value > (Int32.MaxValue - _origin)) { - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_StreamLength")); + throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_StreamLength")); } int newLength = _origin + (int)value; @@ -540,11 +549,11 @@ namespace System.IO { public override void Write(byte[] buffer, int offset, int count) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(offset), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - offset < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -580,16 +589,15 @@ namespace System.IO { } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public override Task WriteAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken) { if (buffer == null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(offset), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - offset < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); // contract validation copied from Write(...) @@ -636,7 +644,7 @@ namespace System.IO { // Writes this MemoryStream to another stream. public virtual void WriteTo(Stream stream) { if (stream==null) - throw new ArgumentNullException("stream", Environment.GetResourceString("ArgumentNull_Stream")); + throw new ArgumentNullException(nameof(stream), Environment.GetResourceString("ArgumentNull_Stream")); Contract.EndContractBlock(); if (!_isOpen) __Error.StreamIsClosed(); diff --git a/src/mscorlib/src/System/IO/Path.cs b/src/mscorlib/src/System/IO/Path.cs deleted file mode 100644 index 4f79936..0000000 --- a/src/mscorlib/src/System/IO/Path.cs +++ /dev/null @@ -1,1435 +0,0 @@ -// 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. - -/*============================================================ -** -** -** -** -** -** Purpose: A collection of path manipulation methods. -** -** -===========================================================*/ - -using System; -using System.Security.Permissions; -using Win32Native = Microsoft.Win32.Win32Native; -using System.Text; -using System.Runtime.InteropServices; -using System.Security; -#if FEATURE_LEGACYSURFACE -using System.Security.Cryptography; -#endif -using System.Runtime.CompilerServices; -using System.Globalization; -using System.Runtime.Versioning; -using System.Diagnostics.Contracts; - -namespace System.IO { - // Provides methods for processing directory strings in an ideally - // cross-platform manner. Most of the methods don't do a complete - // full parsing (such as examining a UNC hostname), but they will - // handle most string operations. - [ComVisible(true)] - public static class Path - { - // Platform specific directory separator character. This is backslash - // ('\') on Windows and slash ('/') on Unix. - // -#if !PLATFORM_UNIX - public static readonly char DirectorySeparatorChar = '\\'; - internal const string DirectorySeparatorCharAsString = "\\"; -#else - public static readonly char DirectorySeparatorChar = '/'; - internal const string DirectorySeparatorCharAsString = "/"; -#endif // !PLATFORM_UNIX - - // Platform specific alternate directory separator character. - // There is only one directory separator char on Unix, - // so the same definition is used for both Unix and Windows. - public static readonly char AltDirectorySeparatorChar = '/'; - - // Platform specific volume separator character. This is colon (':') - // on Windows and MacOS, and slash ('/') on Unix. This is mostly - // useful for parsing paths like "c:\windows" or "MacVolume:System Folder". - // -#if !PLATFORM_UNIX - public static readonly char VolumeSeparatorChar = ':'; -#else - public static readonly char VolumeSeparatorChar = '/'; -#endif // !PLATFORM_UNIX - - // Platform specific invalid list of characters in a path. - // See the "Naming a File" MSDN conceptual docs for more details on - // what is valid in a file name (which is slightly different from what - // is legal in a path name). - // Note: This list is duplicated in CheckInvalidPathChars - [Obsolete("Please use GetInvalidPathChars or GetInvalidFileNameChars instead.")] -#if !PLATFORM_UNIX - public static readonly char[] InvalidPathChars = { '\"', '<', '>', '|', '\0', (Char)1, (Char)2, (Char)3, (Char)4, (Char)5, (Char)6, (Char)7, (Char)8, (Char)9, (Char)10, (Char)11, (Char)12, (Char)13, (Char)14, (Char)15, (Char)16, (Char)17, (Char)18, (Char)19, (Char)20, (Char)21, (Char)22, (Char)23, (Char)24, (Char)25, (Char)26, (Char)27, (Char)28, (Char)29, (Char)30, (Char)31 }; -#else - public static readonly char[] InvalidPathChars = { '\0' }; -#endif // !PLATFORM_UNIX - - // Trim trailing white spaces, tabs etc but don't be aggressive in removing everything that has UnicodeCategory of trailing space. - // String.WhitespaceChars will trim aggressively than what the underlying FS does (for ex, NTFS, FAT). - internal static readonly char[] TrimEndChars = - { - (char)0x09, // Horizontal tab - (char)0x0A, // Line feed - (char)0x0B, // Vertical tab - (char)0x0C, // Form feed - (char)0x0D, // Carriage return - (char)0x20, // Space - (char)0x85, // Next line - (char)0xA0 // Non breaking space - }; - -#if !PLATFORM_UNIX - private static readonly char[] RealInvalidPathChars = PathInternal.InvalidPathChars; - - private static readonly char[] InvalidFileNameChars = { '\"', '<', '>', '|', '\0', (Char)1, (Char)2, (Char)3, (Char)4, (Char)5, (Char)6, (Char)7, (Char)8, (Char)9, (Char)10, (Char)11, (Char)12, (Char)13, (Char)14, (Char)15, (Char)16, (Char)17, (Char)18, (Char)19, (Char)20, (Char)21, (Char)22, (Char)23, (Char)24, (Char)25, (Char)26, (Char)27, (Char)28, (Char)29, (Char)30, (Char)31, ':', '*', '?', '\\', '/' }; -#else - private static readonly char[] RealInvalidPathChars = { '\0' }; - - private static readonly char[] InvalidFileNameChars = { '\0', '/' }; -#endif // !PLATFORM_UNIX - -#if !PLATFORM_UNIX - public static readonly char PathSeparator = ';'; -#else - public static readonly char PathSeparator = ':'; -#endif // !PLATFORM_UNIX - - - // The max total path is 260, and the max individual component length is 255. - // For example, D:\<256 char file name> isn't legal, even though it's under 260 chars. - internal static readonly int MaxPath = PathInternal.MaxShortPath; - - internal static readonly int MaxPathComponentLength = PathInternal.MaxComponentLength; - - // Windows API definitions - internal const int MAX_PATH = 260; // From WinDef.h - internal const int MAX_DIRECTORY_PATH = 248; // cannot create directories greater than 248 characters - - // Changes the extension of a file path. The path parameter - // specifies a file path, and the extension parameter - // specifies a file extension (with a leading period, such as - // ".exe" or ".cs"). - // - // The function returns a file path with the same root, directory, and base - // name parts as path, but with the file extension changed to - // the specified extension. If path is null, the function - // returns null. If path does not contain a file extension, - // the new file extension is appended to the path. If extension - // is null, any exsiting extension is removed from path. - // - public static String ChangeExtension(String path, String extension) { - if (path != null) { - CheckInvalidPathChars(path); - - String s = path; - for (int i = path.Length; --i >= 0;) { - char ch = path[i]; - if (ch == '.') { - s = path.Substring(0, i); - break; - } - if (ch == DirectorySeparatorChar || ch == AltDirectorySeparatorChar || ch == VolumeSeparatorChar) break; - } - if (extension != null && path.Length != 0) { - if (extension.Length == 0 || extension[0] != '.') { - s = s + "."; - } - s = s + extension; - } - return s; - } - return null; - } - - // Returns the directory path of a file path. This method effectively - // removes the last element of the given file path, i.e. it returns a - // string consisting of all characters up to but not including the last - // backslash ("\") in the file path. The returned value is null if the file - // path is null or if the file path denotes a root (such as "\", "C:", or - // "\\server\share"). - public static String GetDirectoryName(String path) - { - return GetDirectoryNameInternal(path); - } - - [System.Security.SecuritySafeCritical] - private static string GetDirectoryNameInternal(string path) - { - if (path != null) - { - CheckInvalidPathChars(path); - - // Expanding short paths is dangerous in this case as the results will change with the current directory. - // - // Suppose you have a path called "PICTUR~1\Foo". Now suppose you have two folders on disk "C:\Mine\Pictures Of Me" - // and "C:\Yours\Pictures of You". If the current directory is neither you'll get back "PICTUR~1". If it is "C:\Mine" - // get back "Pictures Of Me". "C:\Yours" would give back "Pictures of You". - // - // Because of this and as it isn't documented that short paths are expanded we will not expand short names unless - // we're in legacy mode. - string normalizedPath = NormalizePath(path, fullCheck: false, expandShortPaths: -#if FEATURE_PATHCOMPAT - AppContextSwitches.UseLegacyPathHandling -#else - false -#endif - ); - - // If there are no permissions for PathDiscovery to this path, we should NOT expand the short paths - // as this would leak information about paths to which the user would not have access to. - if (path.Length > 0 -#if FEATURE_CAS_POLICY - // Only do the extra logic if we're not in full trust - && !CodeAccessSecurityEngine.QuickCheckForAllDemands() -#endif - ) - { - try - { - // If we were passed in a path with \\?\ we need to remove it as FileIOPermission does not like it. - string tempPath = RemoveLongPathPrefix(path); - - // FileIOPermission cannot handle paths that contain ? or * - // So we only pass to FileIOPermission the text up to them. - int pos = 0; - while (pos < tempPath.Length && (tempPath[pos] != '?' && tempPath[pos] != '*')) - pos++; - - // GetFullPath will Demand that we have the PathDiscovery FileIOPermission and thus throw - // SecurityException if we don't. - // While we don't use the result of this call we are using it as a consistent way of - // doing the security checks. - if (pos > 0) - GetFullPath(tempPath.Substring(0, pos)); - } - catch (SecurityException) - { - // If the user did not have permissions to the path, make sure that we don't leak expanded short paths - // Only re-normalize if the original path had a ~ in it. - if (path.IndexOf("~", StringComparison.Ordinal) != -1) - { - normalizedPath = NormalizePath(path, fullCheck: false, expandShortPaths: false); - } - } - catch (PathTooLongException) { } - catch (NotSupportedException) { } // Security can throw this on "c:\foo:" - catch (IOException) { } - catch (ArgumentException) { } // The normalizePath with fullCheck will throw this for file: and http: - } - - path = normalizedPath; - - int root = GetRootLength(path); - int i = path.Length; - if (i > root) - { - i = path.Length; - if (i == root) return null; - while (i > root && path[--i] != DirectorySeparatorChar && path[i] != AltDirectorySeparatorChar); - return path.Substring(0, i); - } - } - return null; - } - - // Gets the length of the root DirectoryInfo or whatever DirectoryInfo markers - // are specified for the first part of the DirectoryInfo name. - // - internal static int GetRootLength(string path) - { - CheckInvalidPathChars(path); - -#if !PLATFORM_UNIX && FEATURE_PATHCOMPAT - if (AppContextSwitches.UseLegacyPathHandling) - { - int i = 0; - int length = path.Length; - - if (length >= 1 && (IsDirectorySeparator(path[0]))) - { - // handles UNC names and directories off current drive's root. - i = 1; - if (length >= 2 && (IsDirectorySeparator(path[1]))) - { - i = 2; - int n = 2; - while (i < length && ((path[i] != DirectorySeparatorChar && path[i] != AltDirectorySeparatorChar) || --n > 0)) i++; - } - } - else if (length >= 2 && path[1] == VolumeSeparatorChar) - { - // handles A:\foo. - i = 2; - if (length >= 3 && (IsDirectorySeparator(path[2]))) i++; - } - return i; - } - else -#endif // !PLATFORM_UNIX && FEATURE_PATHCOMPAT - { - return PathInternal.GetRootLength(path); - } - } - - internal static bool IsDirectorySeparator(char c) { - return (c==DirectorySeparatorChar || c == AltDirectorySeparatorChar); - } - - public static char[] GetInvalidPathChars() - { - return (char[]) RealInvalidPathChars.Clone(); - } - - public static char[] GetInvalidFileNameChars() - { - return (char[]) InvalidFileNameChars.Clone(); - } - - // Returns the extension of the given path. The returned value includes the - // period (".") character of the extension except when you have a terminal period when you get String.Empty, such as ".exe" or - // ".cpp". The returned value is null if the given path is - // null or if the given path does not include an extension. - // - [Pure] - public static String GetExtension(String path) { - if (path==null) - return null; - - CheckInvalidPathChars(path); - int length = path.Length; - for (int i = length; --i >= 0;) { - char ch = path[i]; - if (ch == '.') - { - if (i != length - 1) - return path.Substring(i, length - i); - else - return String.Empty; - } - if (ch == DirectorySeparatorChar || ch == AltDirectorySeparatorChar || ch == VolumeSeparatorChar) - break; - } - return String.Empty; - } - - // Expands the given path to a fully qualified path. The resulting string - // consists of a drive letter, a colon, and a root relative path. This - // function does not verify that the resulting path - // refers to an existing file or directory on the associated volume. - [Pure] - [System.Security.SecuritySafeCritical] - public static String GetFullPath(String path) { - String fullPath = GetFullPathInternal(path); -#if FEATURE_CORECLR - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, path, fullPath); - state.EnsureState(); -#else - FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, fullPath, false, false); -#endif - return fullPath; - } - - [System.Security.SecurityCritical] - internal static String UnsafeGetFullPath(String path) - { - String fullPath = GetFullPathInternal(path); -#if !FEATURE_CORECLR - FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, fullPath, false, false); -#endif - return fullPath; - } - - // This method is package access to let us quickly get a string name - // while avoiding a security check. This also serves a slightly - // different purpose - when we open a file, we need to resolve the - // path into a fully qualified, non-relative path name. This - // method does that, finding the current drive &; directory. But - // as long as we don't return this info to the user, we're good. However, - // the public GetFullPath does need to do a security check. - internal static string GetFullPathInternal(string path) - { - if (path == null) - throw new ArgumentNullException("path"); - Contract.EndContractBlock(); - - string newPath = NormalizePath(path, fullCheck: true); - return newPath; - } - - [System.Security.SecuritySafeCritical] // auto-generated - internal unsafe static string NormalizePath(string path, bool fullCheck) - { - return NormalizePath(path, fullCheck, -#if FEATURE_PATHCOMPAT - AppContextSwitches.BlockLongPaths ? PathInternal.MaxShortPath : -#endif - PathInternal.MaxLongPath); - } - - [System.Security.SecuritySafeCritical] // auto-generated - internal unsafe static string NormalizePath(string path, bool fullCheck, bool expandShortPaths) - { - return NormalizePath(path, fullCheck, -#if FEATURE_PATHCOMPAT - AppContextSwitches.BlockLongPaths ? PathInternal.MaxShortPath : -#endif - PathInternal.MaxLongPath, - expandShortPaths); - } - - [System.Security.SecuritySafeCritical] // auto-generated - internal static string NormalizePath(string path, bool fullCheck, int maxPathLength) - { - return NormalizePath(path, fullCheck, maxPathLength, expandShortPaths: true); - } - - [System.Security.SecuritySafeCritical] - internal static string NormalizePath(string path, bool fullCheck, int maxPathLength, bool expandShortPaths) - { -#if FEATURE_PATHCOMPAT - if (AppContextSwitches.UseLegacyPathHandling) - { - return LegacyNormalizePath(path, fullCheck, maxPathLength, expandShortPaths); - } - else -#endif // FEATURE_APPCOMPAT - { - if (PathInternal.IsExtended(path)) - { - // We can't really know what is valid for all cases of extended paths. - // - // - object names can include other characters as well (':', '/', etc.) - // - even file objects have different rules (pipe names can contain most characters) - // - // As such we will do no further analysis of extended paths to avoid blocking known and unknown - // scenarios as well as minimizing compat breaks should we block now and need to unblock later. - return path; - } - - string normalizedPath = null; - - if (fullCheck == false) - { - // Disabled fullCheck is only called by GetDirectoryName and GetPathRoot. - // Avoid adding addtional callers and try going direct to lighter weight NormalizeDirectorySeparators. - normalizedPath = NewNormalizePathLimitedChecks(path, maxPathLength, expandShortPaths); - } - else - { - normalizedPath = NewNormalizePath(path, maxPathLength, expandShortPaths: true); - } - - if (string.IsNullOrWhiteSpace(normalizedPath)) - throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal")); - return normalizedPath; - } - } - - [System.Security.SecuritySafeCritical] - private static string NewNormalizePathLimitedChecks(string path, int maxPathLength, bool expandShortPaths) - { - string normalized = PathInternal.NormalizeDirectorySeparators(path); - - if (PathInternal.IsPathTooLong(normalized) || PathInternal.AreSegmentsTooLong(normalized)) - throw new PathTooLongException(); - -#if !PLATFORM_UNIX - if (!PathInternal.IsDevice(normalized) && PathInternal.HasInvalidVolumeSeparator(path)) - throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal")); - - if (expandShortPaths && normalized.IndexOf('~') != -1) - { - try - { - return LongPathHelper.GetLongPathName(normalized); - } - catch - { - // Don't care if we can't get the long path- might not exist, etc. - } - } -#endif - - return normalized; - } - - /// - /// Normalize the path and check for bad characters or other invalid syntax. - /// - [System.Security.SecuritySafeCritical] - [ResourceExposure(ResourceScope.Machine)] - [ResourceConsumption(ResourceScope.Machine)] - private static string NewNormalizePath(string path, int maxPathLength, bool expandShortPaths) - { - Contract.Requires(path != null, "path can't be null"); - - // Embedded null characters are the only invalid character case we want to check up front. - // This is because the nulls will signal the end of the string to Win32 and therefore have - // unpredictable results. Other invalid characters we give a chance to be normalized out. - if (path.IndexOf('\0') != -1) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars")); - -#if !PLATFORM_UNIX - // Note that colon and wildcard checks happen in FileIOPermissions - - // Technically this doesn't matter but we used to throw for this case - if (string.IsNullOrWhiteSpace(path)) - throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal")); - - // We don't want to check invalid characters for device format- see comments for extended above - return LongPathHelper.Normalize(path, (uint)maxPathLength, checkInvalidCharacters: !PathInternal.IsDevice(path), expandShortPaths: expandShortPaths); -#else - if (path.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal")); - - // Expand with current directory if necessary - if (!IsPathRooted(path)) - path = Combine(Directory.GetCurrentDirectory(), path); - - // We would ideally use realpath to do this, but it resolves symlinks, requires that the file actually exist, - // and turns it into a full path, which we only want if fullCheck is true. - string collapsedString = PathInternal.RemoveRelativeSegments(path); - - if (collapsedString.Length > maxPathLength) - throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - - return collapsedString.Length == 0 ? "/" : collapsedString; -#endif // PLATFORM_UNIX - } - -#if FEATURE_PATHCOMPAT - [System.Security.SecurityCritical] // auto-generated - internal unsafe static String LegacyNormalizePath(String path, bool fullCheck, int maxPathLength, bool expandShortPaths) { - - Contract.Requires(path != null, "path can't be null"); - // If we're doing a full path check, trim whitespace and look for - // illegal path characters. - if (fullCheck) { - // Trim whitespace off the end of the string. - // Win32 normalization trims only U+0020. - path = path.TrimEnd(TrimEndChars); - - // Look for illegal path characters. - if (PathInternal.AnyPathHasIllegalCharacters(path)) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars")); - } - - int index = 0; - // We prefer to allocate on the stack for workingset/perf gain. If the - // starting path is less than MaxPath then we can stackalloc; otherwise we'll - // use a StringBuilder (PathHelper does this under the hood). The latter may - // happen in 2 cases: - // 1. Starting path is greater than MaxPath but it normalizes down to MaxPath. - // This is relevant for paths containing escape sequences. In this case, we - // attempt to normalize down to MaxPath, but the caller pays a perf penalty - // since StringBuilder is used. - // 2. IsolatedStorage, which supports paths longer than MaxPath (value given - // by maxPathLength. - PathHelper newBuffer; - if (path.Length + 1 <= MaxPath) { - char* m_arrayPtr = stackalloc char[MaxPath]; - newBuffer = new PathHelper(m_arrayPtr, MaxPath); - } else { - newBuffer = new PathHelper(path.Length + Path.MaxPath, maxPathLength); - } - - uint numSpaces = 0; - uint numDots = 0; - bool fixupDirectorySeparator = false; - // Number of significant chars other than potentially suppressible - // dots and spaces since the last directory or volume separator char - uint numSigChars = 0; - int lastSigChar = -1; // Index of last significant character. - // Whether this segment of the path (not the complete path) started - // with a volume separator char. Reject "c:...". - bool startedWithVolumeSeparator = false; - bool firstSegment = true; - int lastDirectorySeparatorPos = 0; - -#if !PLATFORM_UNIX - bool mightBeShortFileName = false; - - // LEGACY: This code is here for backwards compatibility reasons. It - // ensures that \\foo.cs\bar.cs stays \\foo.cs\bar.cs instead of being - // turned into \foo.cs\bar.cs. - if (path.Length > 0 && (path[0] == DirectorySeparatorChar || path[0] == AltDirectorySeparatorChar)) { - newBuffer.Append('\\'); - index++; - lastSigChar = 0; - } -#endif - - // Normalize the string, stripping out redundant dots, spaces, and - // slashes. - while (index < path.Length) { - char currentChar = path[index]; - - // We handle both directory separators and dots specially. For - // directory separators, we consume consecutive appearances. - // For dots, we consume all dots beyond the second in - // succession. All other characters are added as is. In - // addition we consume all spaces after the last other char - // in a directory name up until the directory separator. - - if (currentChar == DirectorySeparatorChar || currentChar == AltDirectorySeparatorChar) { - // If we have a path like "123.../foo", remove the trailing dots. - // However, if we found "c:\temp\..\bar" or "c:\temp\...\bar", don't. - // Also remove trailing spaces from both files & directory names. - // This was agreed on with the OS team to fix undeletable directory - // names ending in spaces. - - // If we saw a '\' as the previous last significant character and - // are simply going to write out dots, suppress them. - // If we only contain dots and slashes though, only allow - // a string like [dot]+ [space]*. Ignore everything else. - // Legal: "\.. \", "\...\", "\. \" - // Illegal: "\.. .\", "\. .\", "\ .\" - if (numSigChars == 0) { - // Dot and space handling - if (numDots > 0) { - // Look for ".[space]*" or "..[space]*" - int start = lastSigChar + 1; - if (path[start] != '.') - throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal")); - - // Only allow "[dot]+[space]*", and normalize the - // legal ones to "." or ".." - if (numDots >= 2) { - // Reject "C:..." - if (startedWithVolumeSeparator && numDots > 2) - - throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal")); - - if (path[start + 1] == '.') { - // Search for a space in the middle of the - // dots and throw - for(int i=start + 2; i < start + numDots; i++) { - if (path[i] != '.') - throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal")); - } - - numDots = 2; - } - else { - if (numDots > 1) - throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal")); - numDots = 1; - } - } - - if (numDots == 2) { - newBuffer.Append('.'); - } - - newBuffer.Append('.'); - fixupDirectorySeparator = false; - - // Continue in this case, potentially writing out '\'. - } - - if (numSpaces > 0 && firstSegment) { - // Handle strings like " \\server\share". - if (index + 1 < path.Length && - (path[index + 1] == DirectorySeparatorChar || path[index + 1] == AltDirectorySeparatorChar)) - { - newBuffer.Append(DirectorySeparatorChar); - } - } - } - numDots = 0; - numSpaces = 0; // Suppress trailing spaces - - if (!fixupDirectorySeparator) { - fixupDirectorySeparator = true; - newBuffer.Append(DirectorySeparatorChar); - } - numSigChars = 0; - lastSigChar = index; - startedWithVolumeSeparator = false; - firstSegment = false; - -#if !PLATFORM_UNIX - // For short file names, we must try to expand each of them as - // soon as possible. We need to allow people to specify a file - // name that doesn't exist using a path with short file names - // in it, such as this for a temp file we're trying to create: - // C:\DOCUME~1\USERNA~1.RED\LOCALS~1\Temp\bg3ylpzp - // We could try doing this afterwards piece by piece, but it's - // probably a lot simpler to do it here. - if (mightBeShortFileName) { - newBuffer.TryExpandShortFileName(); - mightBeShortFileName = false; - } -#endif - int thisPos = newBuffer.Length - 1; - if (thisPos - lastDirectorySeparatorPos > MaxPathComponentLength) - { - throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - } - lastDirectorySeparatorPos = thisPos; - } // if (Found directory separator) - else if (currentChar == '.') { - // Reduce only multiple .'s only after slash to 2 dots. For - // instance a...b is a valid file name. - numDots++; - // Don't flush out non-terminal spaces here, because they may in - // the end not be significant. Turn "c:\ . .\foo" -> "c:\foo" - // which is the conclusion of removing trailing dots & spaces, - // as well as folding multiple '\' characters. - } - else if (currentChar == ' ') { - numSpaces++; - } - else { // Normal character logic -#if !PLATFORM_UNIX - if (currentChar == '~' && expandShortPaths) - mightBeShortFileName = true; -#endif - - fixupDirectorySeparator = false; - -#if !PLATFORM_UNIX - // To reject strings like "C:...\foo" and "C :\foo" - if (firstSegment && currentChar == VolumeSeparatorChar) { - // Only accept "C:", not "c :" or ":" - // Get a drive letter or ' ' if index is 0. - char driveLetter = (index > 0) ? path[index-1] : ' '; - bool validPath = ((numDots == 0) && (numSigChars >= 1) && (driveLetter != ' ')); - if (!validPath) - throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal")); - - startedWithVolumeSeparator = true; - // We need special logic to make " c:" work, we should not fix paths like " foo::$DATA" - if (numSigChars > 1) { // Common case, simply do nothing - int spaceCount = 0; // How many spaces did we write out, numSpaces has already been reset. - while((spaceCount < newBuffer.Length) && newBuffer[spaceCount] == ' ') - spaceCount++; - if (numSigChars - spaceCount == 1) { - //Safe to update stack ptr directly - newBuffer.Length = 0; - newBuffer.Append(driveLetter); // Overwrite spaces, we need a special case to not break " foo" as a relative path. - } - } - numSigChars = 0; - } - else -#endif // !PLATFORM_UNIX - { - numSigChars += 1 + numDots + numSpaces; - } - - // Copy any spaces & dots since the last significant character - // to here. Note we only counted the number of dots & spaces, - // and don't know what order they're in. Hence the copy. - if (numDots > 0 || numSpaces > 0) { - int numCharsToCopy = (lastSigChar >= 0) ? index - lastSigChar - 1 : index; - if (numCharsToCopy > 0) { - for (int i=0; i MaxPathComponentLength) - { - throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - } - - // Drop any trailing dots and spaces from file & directory names, EXCEPT - // we MUST make sure that "C:\foo\.." is correctly handled. - // Also handle "C:\foo\." -> "C:\foo", while "C:\." -> "C:\" - if (numSigChars == 0) { - if (numDots > 0) { - // Look for ".[space]*" or "..[space]*" - int start = lastSigChar + 1; - if (path[start] != '.') - throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal")); - - // Only allow "[dot]+[space]*", and normalize the - // legal ones to "." or ".." - if (numDots >= 2) { - // Reject "C:..." - if (startedWithVolumeSeparator && numDots > 2) - throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal")); - - if (path[start + 1] == '.') { - // Search for a space in the middle of the - // dots and throw - for(int i=start + 2; i < start + numDots; i++) { - if (path[i] != '.') - throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal")); - } - - numDots = 2; - } - else { - if (numDots > 1) - throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal")); - numDots = 1; - } - } - - if (numDots == 2) { - newBuffer.Append('.'); - } - - newBuffer.Append('.'); - } - } // if (numSigChars == 0) - - // If we ended up eating all the characters, bail out. - if (newBuffer.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal")); - - // Disallow URL's here. Some of our other Win32 API calls will reject - // them later, so we might be better off rejecting them here. - // Note we've probably turned them into "file:\D:\foo.tmp" by now. - // But for compatibility, ensure that callers that aren't doing a - // full check aren't rejected here. - if (fullCheck) { - if ( newBuffer.OrdinalStartsWith("http:", false) || - newBuffer.OrdinalStartsWith("file:", false)) - { - throw new ArgumentException(Environment.GetResourceString("Argument_PathUriFormatNotSupported")); - } - } - -#if !PLATFORM_UNIX - // If the last part of the path (file or directory name) had a tilde, - // expand that too. - if (mightBeShortFileName) { - newBuffer.TryExpandShortFileName(); - } -#endif - - // Call the Win32 API to do the final canonicalization step. - int result = 1; - - if (fullCheck) { - // NOTE: Win32 GetFullPathName requires the input buffer to be big enough to fit the initial - // path which is a concat of CWD and the relative path, this can be of an arbitrary - // size and could be > MAX_PATH (which becomes an artificial limit at this point), - // even though the final normalized path after fixing up the relative path syntax - // might be well within the MAX_PATH restriction. For ex, - // "c:\SomeReallyLongDirName(thinkGreaterThan_MAXPATH)\..\foo.txt" which actually requires a - // buffer well with in the MAX_PATH as the normalized path is just "c:\foo.txt" - // This buffer requirement seems wrong, it could be a bug or a perf optimization - // like returning required buffer length quickly or avoid stratch buffer etc. - // Ideally we would get the required buffer length first by calling GetFullPathName - // once without the buffer and use that in the later call but this doesn't always work - // due to Win32 GetFullPathName bug. For instance, in Win2k, when the path we are trying to - // fully qualify is a single letter name (such as "a", "1", ",") GetFullPathName - // fails to return the right buffer size (i.e, resulting in insufficient buffer). - // To workaround this bug we will start with MAX_PATH buffer and grow it once if the - // return value is > MAX_PATH. - - result = newBuffer.GetFullPathName(); - -#if !PLATFORM_UNIX - // If we called GetFullPathName with something like "foo" and our - // command window was in short file name mode (ie, by running edlin or - // DOS versions of grep, etc), we might have gotten back a short file - // name. So, check to see if we need to expand it. - mightBeShortFileName = false; - for(int i=0; i < newBuffer.Length && !mightBeShortFileName; i++) { - if (newBuffer[i] == '~' && expandShortPaths) - mightBeShortFileName = true; - } - - if (mightBeShortFileName) { - bool r = newBuffer.TryExpandShortFileName(); - // Consider how the path "Doesn'tExist" would expand. If - // we add in the current directory, it too will need to be - // fully expanded, which doesn't happen if we use a file - // name that doesn't exist. - if (!r) { - int lastSlash = -1; - - for (int i = newBuffer.Length - 1; i >= 0; i--) { - if (newBuffer[i] == DirectorySeparatorChar) { - lastSlash = i; - break; - } - } - - if (lastSlash >= 0) { - - // This bounds check is for safe memcpy but we should never get this far - if (newBuffer.Length >= maxPathLength) - throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - - int lenSavedName = newBuffer.Length - lastSlash - 1; - Contract.Assert(lastSlash < newBuffer.Length, "path unexpectedly ended in a '\'"); - - newBuffer.Fixup(lenSavedName, lastSlash); - } - } - } -#endif // PLATFORM_UNIX - } - - if (result != 0) { - /* Throw an ArgumentException for paths like \\, \\server, \\server\ - This check can only be properly done after normalizing, so - \\foo\.. will be properly rejected. Also, reject \\?\GLOBALROOT\ - (an internal kernel path) because it provides aliases for drives. */ - if (newBuffer.Length > 1 && newBuffer[0] == '\\' && newBuffer[1] == '\\') { - int startIndex = 2; - while (startIndex < result) { - if (newBuffer[startIndex] == '\\') { - startIndex++; - break; - } - else { - startIndex++; - } - } - if (startIndex == result) - throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegalUNC")); - - // Check for \\?\Globalroot, an internal mechanism to the kernel - // that provides aliases for drives and other undocumented stuff. - // The kernel team won't even describe the full set of what - // is available here - we don't want managed apps mucking - // with this for security reasons. - if ( newBuffer.OrdinalStartsWith("\\\\?\\globalroot", true)) - throw new ArgumentException(Environment.GetResourceString("Arg_PathGlobalRoot")); - } - } - - // Check our result and form the managed string as necessary. - if (newBuffer.Length >= maxPathLength) - throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - - if (result == 0) { - int errorCode = Marshal.GetLastWin32Error(); - if (errorCode == 0) - errorCode = Win32Native.ERROR_BAD_PATHNAME; - __Error.WinIOError(errorCode, path); - return null; // Unreachable - silence a compiler error. - } - - return newBuffer.ToStringOrExisting(path); - } -#endif // FEATURE_PATHCOMPAT - - internal const int MaxLongPath = PathInternal.MaxLongPath; - - private const string LongPathPrefix = PathInternal.ExtendedPathPrefix; - private const string UNCPathPrefix = PathInternal.UncPathPrefix; - private const string UNCLongPathPrefixToInsert = PathInternal.UncExtendedPrefixToInsert; - private const string UNCLongPathPrefix = PathInternal.UncExtendedPathPrefix; - - internal static bool HasLongPathPrefix(string path) - { -#if FEATURE_PATHCOMPAT - if (AppContextSwitches.UseLegacyPathHandling) - return path.StartsWith(LongPathPrefix, StringComparison.Ordinal); - else -#endif - return PathInternal.IsExtended(path); - } - - internal static string AddLongPathPrefix(string path) - { -#if FEATURE_PATHCOMPAT - if (AppContextSwitches.UseLegacyPathHandling) - { - if (path.StartsWith(LongPathPrefix, StringComparison.Ordinal)) - return path; - - if (path.StartsWith(UNCPathPrefix, StringComparison.Ordinal)) - return path.Insert(2, UNCLongPathPrefixToInsert); // Given \\server\share in longpath becomes \\?\UNC\server\share => UNCLongPathPrefix + path.SubString(2); => The actual command simply reduces the operation cost. - - return LongPathPrefix + path; - } - else -#endif - { - return PathInternal.EnsureExtendedPrefix(path); - } - } - - internal static string RemoveLongPathPrefix(string path) - { -#if FEATURE_PATHCOMPAT - if (AppContextSwitches.UseLegacyPathHandling) - { - if (!path.StartsWith(LongPathPrefix, StringComparison.Ordinal)) - return path; - - if (path.StartsWith(UNCLongPathPrefix, StringComparison.OrdinalIgnoreCase)) - return path.Remove(2, 6); // Given \\?\UNC\server\share we return \\server\share => @'\\' + path.SubString(UNCLongPathPrefix.Length) => The actual command simply reduces the operation cost. - - return path.Substring(4); - } - else -#endif - { - return PathInternal.RemoveExtendedPrefix(path); - } - } - - internal static StringBuilder RemoveLongPathPrefix(StringBuilder pathSB) - { -#if FEATURE_PATHCOMPAT - if (AppContextSwitches.UseLegacyPathHandling) - { - if (!PathInternal.StartsWithOrdinal(pathSB, LongPathPrefix)) - return pathSB; - - // Given \\?\UNC\server\share we return \\server\share => @'\\' + path.SubString(UNCLongPathPrefix.Length) => The actual command simply reduces the operation cost. - if (PathInternal.StartsWithOrdinal(pathSB, UNCLongPathPrefix, ignoreCase: true)) - return pathSB.Remove(2, 6); - - return pathSB.Remove(0, 4); - } - else -#endif - { - return PathInternal.RemoveExtendedPrefix(pathSB); - } - } - - - // Returns the name and extension parts of the given path. The resulting - // string contains the characters of path that follow the last - // backslash ("\"), slash ("/"), or colon (":") character in - // path. The resulting string is the entire path if path - // contains no backslash after removing trailing slashes, slash, or colon characters. The resulting - // string is null if path is null. - // - [Pure] - public static String GetFileName(String path) { - if (path != null) { - CheckInvalidPathChars(path); - - int length = path.Length; - for (int i = length; --i >= 0;) { - char ch = path[i]; - if (ch == DirectorySeparatorChar || ch == AltDirectorySeparatorChar || ch == VolumeSeparatorChar) - return path.Substring(i + 1, length - i - 1); - - } - } - return path; - } - - [Pure] - public static String GetFileNameWithoutExtension(String path) { - path = GetFileName(path); - if (path != null) - { - int i; - if ((i=path.LastIndexOf('.')) == -1) - return path; // No path extension found - else - return path.Substring(0,i); - } - return null; - } - - - - // Returns the root portion of the given path. The resulting string - // consists of those rightmost characters of the path that constitute the - // root of the path. Possible patterns for the resulting string are: An - // empty string (a relative path on the current drive), "\" (an absolute - // path on the current drive), "X:" (a relative path on a given drive, - // where X is the drive letter), "X:\" (an absolute path on a given drive), - // and "\\server\share" (a UNC path for a given server and share name). - // The resulting string is null if path is null. - // - [Pure] - public static String GetPathRoot(String path) { - if (path == null) return null; - - // Expanding short paths has no impact on the path root- there is no such thing as an - // 8.3 volume or server/share name. - path = NormalizePath(path, fullCheck: false, expandShortPaths: false); - return path.Substring(0, GetRootLength(path)); - } - - [System.Security.SecuritySafeCritical] - public static String GetTempPath() - { -#if !FEATURE_CORECLR - new EnvironmentPermission(PermissionState.Unrestricted).Demand(); -#endif - StringBuilder sb = new StringBuilder(PathInternal.MaxShortPath); - uint r = Win32Native.GetTempPath(PathInternal.MaxShortPath, sb); - String path = sb.ToString(); - if (r==0) __Error.WinIOError(); - path = GetFullPathInternal(path); -#if FEATURE_CORECLR - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Write, String.Empty, path); - state.EnsureState(); -#endif - return path; - } - - internal static bool IsRelative(string path) - { - Contract.Assert(path != null, "path can't be null"); - return PathInternal.IsPartiallyQualified(path); - } - - // Returns a cryptographically strong random 8.3 string that can be - // used as either a folder name or a file name. -#if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] -#endif - public static String GetRandomFileName() - { - // 5 bytes == 40 bits == 40/5 == 8 chars in our encoding - // This gives us exactly 8 chars. We want to avoid the 8.3 short name issue - byte[] key = new byte[10]; - -#if FEATURE_CORECLR - Win32Native.Random(true, key, key.Length); -#else - // RNGCryptoServiceProvider is disposable in post-Orcas desktop mscorlibs, but not in CoreCLR's - // mscorlib, so we need to do a manual using block for it. - RNGCryptoServiceProvider rng = null; - try - { - rng = new RNGCryptoServiceProvider(); - - rng.GetBytes(key); - } - finally - { - if (rng != null) - { - rng.Dispose(); - } - } -#endif - - // rndCharArray is expected to be 16 chars - char[] rndCharArray = Path.ToBase32StringSuitableForDirName(key).ToCharArray(); - rndCharArray[8] = '.'; - return new String(rndCharArray, 0, 12); - } - - // Returns a unique temporary file name, and creates a 0-byte file by that - // name on disk. - [System.Security.SecuritySafeCritical] - public static String GetTempFileName() - { - return InternalGetTempFileName(true); - } - - [System.Security.SecurityCritical] - internal static String UnsafeGetTempFileName() - { - return InternalGetTempFileName(false); - } - - [System.Security.SecurityCritical] - private static String InternalGetTempFileName(bool checkHost) - { - String path = GetTempPath(); - - // Since this can write to the temp directory and theoretically - // cause a denial of service attack, demand FileIOPermission to - // that directory. - -#if FEATURE_CORECLR - if (checkHost) - { - FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Write, String.Empty, path); - state.EnsureState(); - } -#else - FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, path); -#endif - StringBuilder sb = new StringBuilder(MaxPath); - uint r = Win32Native.GetTempFileName(path, "tmp", 0, sb); - if (r==0) __Error.WinIOError(); - return sb.ToString(); - } - - // Tests if a path includes a file extension. The result is - // true if the characters that follow the last directory - // separator ('\\' or '/') or volume separator (':') in the path include - // a period (".") other than a terminal period. The result is false otherwise. - // - [Pure] - public static bool HasExtension(String path) { - if (path != null) { - CheckInvalidPathChars(path); - - for (int i = path.Length; --i >= 0;) { - char ch = path[i]; - if (ch == '.') { - if ( i != path.Length - 1) - return true; - else - return false; - } - if (ch == DirectorySeparatorChar || ch == AltDirectorySeparatorChar || ch == VolumeSeparatorChar) break; - } - } - return false; - } - - // Tests if the given path contains a root. A path is considered rooted - // if it starts with a backslash ("\") or a drive letter and a colon (":"). - // - [Pure] - public static bool IsPathRooted(String path) { - if (path != null) { - CheckInvalidPathChars(path); - - int length = path.Length; -#if !PLATFORM_UNIX - if ((length >= 1 && (path[0] == DirectorySeparatorChar || path[0] == AltDirectorySeparatorChar)) || (length >= 2 && path[1] == VolumeSeparatorChar)) - return true; -#else - if (length >= 1 && (path[0] == DirectorySeparatorChar || path[0] == AltDirectorySeparatorChar)) - return true; -#endif - } - return false; - } - - public static String Combine(String path1, String path2) { - if (path1==null || path2==null) - throw new ArgumentNullException((path1==null) ? "path1" : "path2"); - Contract.EndContractBlock(); - CheckInvalidPathChars(path1); - CheckInvalidPathChars(path2); - - return CombineNoChecks(path1, path2); - } - - public static String Combine(String path1, String path2, String path3) { - if (path1 == null || path2 == null || path3 == null) - throw new ArgumentNullException((path1 == null) ? "path1" : (path2 == null) ? "path2" : "path3"); - Contract.EndContractBlock(); - CheckInvalidPathChars(path1); - CheckInvalidPathChars(path2); - CheckInvalidPathChars(path3); - - return CombineNoChecks(CombineNoChecks(path1, path2), path3); - } - - public static String Combine(String path1, String path2, String path3, String path4) { - if (path1 == null || path2 == null || path3 == null || path4 == null) - throw new ArgumentNullException((path1 == null) ? "path1" : (path2 == null) ? "path2" : (path3 == null) ? "path3" : "path4"); - Contract.EndContractBlock(); - CheckInvalidPathChars(path1); - CheckInvalidPathChars(path2); - CheckInvalidPathChars(path3); - CheckInvalidPathChars(path4); - - return CombineNoChecks(CombineNoChecks(CombineNoChecks(path1, path2), path3), path4); - } - - public static String Combine(params String[] paths) { - if (paths == null) { - throw new ArgumentNullException("paths"); - } - Contract.EndContractBlock(); - - int finalSize = 0; - int firstComponent = 0; - - // We have two passes, the first calcuates how large a buffer to allocate and does some precondition - // checks on the paths passed in. The second actually does the combination. - - for (int i = 0; i < paths.Length; i++) { - if (paths[i] == null) { - throw new ArgumentNullException("paths"); - } - - if (paths[i].Length == 0) { - continue; - } - - CheckInvalidPathChars(paths[i]); - - if (Path.IsPathRooted(paths[i])) { - firstComponent = i; - finalSize = paths[i].Length; - } else { - finalSize += paths[i].Length; - } - - char ch = paths[i][paths[i].Length - 1]; - if (ch != DirectorySeparatorChar && ch != AltDirectorySeparatorChar && ch != VolumeSeparatorChar) - finalSize++; - } - - StringBuilder finalPath = StringBuilderCache.Acquire(finalSize); - - for (int i = firstComponent; i < paths.Length; i++) { - if (paths[i].Length == 0) { - continue; - } - - if (finalPath.Length == 0) { - finalPath.Append(paths[i]); - } else { - char ch = finalPath[finalPath.Length - 1]; - if (ch != DirectorySeparatorChar && ch != AltDirectorySeparatorChar && ch != VolumeSeparatorChar) { - finalPath.Append(DirectorySeparatorChar); - } - - finalPath.Append(paths[i]); - } - } - - return StringBuilderCache.GetStringAndRelease(finalPath); - } - - private static String CombineNoChecks(String path1, String path2) { - if (path2.Length == 0) - return path1; - - if (path1.Length == 0) - return path2; - - if (IsPathRooted(path2)) - return path2; - - char ch = path1[path1.Length - 1]; - if (ch != DirectorySeparatorChar && ch != AltDirectorySeparatorChar && ch != VolumeSeparatorChar) - return path1 + DirectorySeparatorCharAsString + path2; - return path1 + path2; - } - - private static readonly Char[] s_Base32Char = { - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', - 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', '0', '1', '2', '3', '4', '5'}; - - internal static String ToBase32StringSuitableForDirName(byte[] buff) - { - // This routine is optimised to be used with buffs of length 20 - Contract.Assert(((buff.Length % 5) == 0), "Unexpected hash length"); - - StringBuilder sb = StringBuilderCache.Acquire(); - byte b0, b1, b2, b3, b4; - int l, i; - - l = buff.Length; - i = 0; - - // Create l chars using the last 5 bits of each byte. - // Consume 3 MSB bits 5 bytes at a time. - - do - { - b0 = (i < l) ? buff[i++] : (byte)0; - b1 = (i < l) ? buff[i++] : (byte)0; - b2 = (i < l) ? buff[i++] : (byte)0; - b3 = (i < l) ? buff[i++] : (byte)0; - b4 = (i < l) ? buff[i++] : (byte)0; - - // Consume the 5 Least significant bits of each byte - sb.Append(s_Base32Char[b0 & 0x1F]); - sb.Append(s_Base32Char[b1 & 0x1F]); - sb.Append(s_Base32Char[b2 & 0x1F]); - sb.Append(s_Base32Char[b3 & 0x1F]); - sb.Append(s_Base32Char[b4 & 0x1F]); - - // Consume 3 MSB of b0, b1, MSB bits 6, 7 of b3, b4 - sb.Append(s_Base32Char[( - ((b0 & 0xE0) >> 5) | - ((b3 & 0x60) >> 2))]); - - sb.Append(s_Base32Char[( - ((b1 & 0xE0) >> 5) | - ((b4 & 0x60) >> 2))]); - - // Consume 3 MSB bits of b2, 1 MSB bit of b3, b4 - - b2 >>= 5; - - Contract.Assert(((b2 & 0xF8) == 0), "Unexpected set bits"); - - if ((b3 & 0x80) != 0) - b2 |= 0x08; - if ((b4 & 0x80) != 0) - b2 |= 0x10; - - sb.Append(s_Base32Char[b2]); - - } while (i < l); - - return StringBuilderCache.GetStringAndRelease(sb); - } - - // ".." can only be used if it is specified as a part of a valid File/Directory name. We disallow - // the user being able to use it to move up directories. Here are some examples eg - // Valid: a..b abc..d - // Invalid: ..ab ab.. .. abc..d\abc.. - // - internal static void CheckSearchPattern(String searchPattern) - { - int index; - while ((index = searchPattern.IndexOf("..", StringComparison.Ordinal)) != -1) { - - if (index + 2 == searchPattern.Length) // Terminal ".." . Files names cannot end in ".." - throw new ArgumentException(Environment.GetResourceString("Arg_InvalidSearchPattern")); - - if ((searchPattern[index+2] == DirectorySeparatorChar) - || (searchPattern[index+2] == AltDirectorySeparatorChar)) - throw new ArgumentException(Environment.GetResourceString("Arg_InvalidSearchPattern")); - - searchPattern = searchPattern.Substring(index + 2); - } - - } - - internal static void CheckInvalidPathChars(String path, bool checkAdditional = false) - { - if (path == null) - throw new ArgumentNullException("path"); - - if (PathInternal.HasIllegalCharacters(path, checkAdditional)) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars")); - } - - internal static String InternalCombine(String path1, String path2) { - if (path1==null || path2==null) - throw new ArgumentNullException((path1==null) ? "path1" : "path2"); - Contract.EndContractBlock(); - CheckInvalidPathChars(path1); - CheckInvalidPathChars(path2); - - if (path2.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_PathEmpty"), "path2"); - if (IsPathRooted(path2)) - throw new ArgumentException(Environment.GetResourceString("Arg_Path2IsRooted"), "path2"); - int i = path1.Length; - if (i == 0) return path2; - char ch = path1[i - 1]; - if (ch != DirectorySeparatorChar && ch != AltDirectorySeparatorChar && ch != VolumeSeparatorChar) - return path1 + DirectorySeparatorCharAsString + path2; - return path1 + path2; - } - - } -} diff --git a/src/mscorlib/src/System/IO/PathHelper.cs b/src/mscorlib/src/System/IO/PathHelper.cs deleted file mode 100644 index 8e39b3c..0000000 --- a/src/mscorlib/src/System/IO/PathHelper.cs +++ /dev/null @@ -1,448 +0,0 @@ -// 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. - -#if FEATURE_PATHCOMPAT -using System; -using System.Collections; -using System.Text; -using Microsoft.Win32; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using System.Globalization; -using System.Runtime.Versioning; -using System.Security; -using System.Security.Permissions; -using System.Diagnostics.Contracts; - -namespace System.IO { - - // ABOUT: - // Helps with path normalization; support allocating on the stack or heap - // - // PathHelper can't stackalloc the array for obvious reasons; you must pass - // in an array of chars allocated on the stack. - // - // USAGE: - // Suppose you need to represent a char array of length len. Then this is the - // suggested way to instantiate PathHelper: - // *************************************************************************** - // PathHelper pathHelper; - // if (charArrayLength less than stack alloc threshold == Path.MaxPath) - // char* arrayPtr = stackalloc char[Path.MaxPath]; - // pathHelper = new PathHelper(arrayPtr); - // else - // pathHelper = new PathHelper(capacity, maxPath); - // *************************************************************************** - // - // note in the StringBuilder ctor: - // - maxPath may be greater than Path.MaxPath (for isolated storage) - // - capacity may be greater than maxPath. This is even used for non-isolated - // storage scenarios where we want to temporarily allow strings greater - // than Path.MaxPath if they can be normalized down to Path.MaxPath. This - // can happen if the path contains escape characters "..". - // - unsafe internal struct PathHelper { // should not be serialized - - // maximum size, max be greater than max path if contains escape sequence - private int m_capacity; - // current length (next character position) - private int m_length; - // max path, may be less than capacity - private int m_maxPath; - - // ptr to stack alloc'd array of chars - [SecurityCritical] - private char* m_arrayPtr; - - // StringBuilder - private StringBuilder m_sb; - - // whether to operate on stack alloc'd or heap alloc'd array - private bool useStackAlloc; - - // Whether to skip calls to Win32Native.GetLongPathName becasue we tried before and failed: - private bool doNotTryExpandShortFileName; - - // Instantiates a PathHelper with a stack alloc'd array of chars - [System.Security.SecurityCritical] - internal PathHelper(char* charArrayPtr, int length) { - Contract.Requires(charArrayPtr != null); - // force callers to be aware of this - Contract.Requires(length == Path.MaxPath); - this.m_length = 0; - this.m_sb = null; - - this.m_arrayPtr = charArrayPtr; - this.m_capacity = length; - this.m_maxPath = Path.MaxPath; - useStackAlloc = true; - doNotTryExpandShortFileName = false; - } - - // Instantiates a PathHelper with a heap alloc'd array of ints. Will create a StringBuilder - [System.Security.SecurityCritical] - internal PathHelper(int capacity, int maxPath) - { - this.m_length = 0; - this.m_arrayPtr = null; - this.useStackAlloc = false; - - this.m_sb = new StringBuilder(capacity); - this.m_capacity = capacity; - this.m_maxPath = maxPath; - doNotTryExpandShortFileName = false; - } - - internal int Length { - get { - if (useStackAlloc) { - return m_length; - } - else { - return m_sb.Length; - } - } - set { - if (useStackAlloc) { - m_length = value; - } - else { - m_sb.Length = value; - } - } - } - - internal int Capacity { - get { - return m_capacity; - } - } - - internal char this[int index] { - [System.Security.SecurityCritical] - get { - Contract.Requires(index >= 0 && index < Length); - if (useStackAlloc) { - return m_arrayPtr[index]; - } - else { - return m_sb[index]; - } - } - [System.Security.SecurityCritical] - set { - Contract.Requires(index >= 0 && index < Length); - if (useStackAlloc) { - m_arrayPtr[index] = value; - } - else { - m_sb[index] = value; - } - } - } - - [System.Security.SecurityCritical] - internal unsafe void Append(char value) { - if (Length + 1 >= m_capacity) - throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - - if (useStackAlloc) { - m_arrayPtr[Length] = value; - m_length++; - } - else { - m_sb.Append(value); - } - } - - [System.Security.SecurityCritical] - internal unsafe int GetFullPathName() { - if (useStackAlloc) { - char* finalBuffer = stackalloc char[Path.MaxPath + 1]; - int result = Win32Native.GetFullPathName(m_arrayPtr, Path.MaxPath + 1, finalBuffer, IntPtr.Zero); - - // If success, the return buffer length does not account for the terminating null character. - // If in-sufficient buffer, the return buffer length does account for the path + the terminating null character. - // If failure, the return buffer length is zero - if (result > Path.MaxPath) { - char* tempBuffer = stackalloc char[result]; - finalBuffer = tempBuffer; - result = Win32Native.GetFullPathName(m_arrayPtr, result, finalBuffer, IntPtr.Zero); - } - - // Full path is genuinely long - if (result >= Path.MaxPath) - throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - - Contract.Assert(result < Path.MaxPath, "did we accidently remove a PathTooLongException check?"); - if (result == 0 && m_arrayPtr[0] != '\0') { - __Error.WinIOError(); - } - - else if (result < Path.MaxPath) { - // Null terminate explicitly (may be only needed for some cases such as empty strings) - // GetFullPathName return length doesn't account for null terminating char... - finalBuffer[result] = '\0'; // Safe to write directly as result is < Path.MaxPath - } - - // We have expanded the paths and GetLongPathName may or may not behave differently from before. - // We need to call it again to see: - doNotTryExpandShortFileName = false; - - String.wstrcpy(m_arrayPtr, finalBuffer, result); - // Doesn't account for null terminating char. Think of this as the last - // valid index into the buffer but not the length of the buffer - Length = result; - return result; - } - else { - StringBuilder finalBuffer = new StringBuilder(m_capacity + 1); - int result = Win32Native.GetFullPathName(m_sb.ToString(), m_capacity + 1, finalBuffer, IntPtr.Zero); - - // If success, the return buffer length does not account for the terminating null character. - // If in-sufficient buffer, the return buffer length does account for the path + the terminating null character. - // If failure, the return buffer length is zero - if (result > m_maxPath) { - finalBuffer.Length = result; - result = Win32Native.GetFullPathName(m_sb.ToString(), result, finalBuffer, IntPtr.Zero); - } - - // Fullpath is genuinely long - if (result >= m_maxPath) - throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - - Contract.Assert(result < m_maxPath, "did we accidentally remove a PathTooLongException check?"); - if (result == 0 && m_sb[0] != '\0') { - if (Length >= m_maxPath) { - throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - } - __Error.WinIOError(); - } - - // We have expanded the paths and GetLongPathName may or may not behave differently from before. - // We need to call it again to see: - doNotTryExpandShortFileName = false; - - m_sb = finalBuffer; - return result; - } - } - - [System.Security.SecurityCritical] - internal unsafe bool TryExpandShortFileName() { - - if (doNotTryExpandShortFileName) - return false; - - if (useStackAlloc) { - NullTerminate(); - char* buffer = UnsafeGetArrayPtr(); - char* shortFileNameBuffer = stackalloc char[Path.MaxPath + 1]; - - int r = Win32Native.GetLongPathName(buffer, shortFileNameBuffer, Path.MaxPath); - - // If success, the return buffer length does not account for the terminating null character. - // If in-sufficient buffer, the return buffer length does account for the path + the terminating null character. - // If failure, the return buffer length is zero - if (r >= Path.MaxPath) - throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - - if (r == 0) { - // Note: GetLongPathName will return ERROR_INVALID_FUNCTION on a - // path like \\.\PHYSICALDEVICE0 - some device driver doesn't - // support GetLongPathName on that string. This behavior is - // by design, according to the Core File Services team. - // We also get ERROR_NOT_ENOUGH_QUOTA in SQL_CLR_STRESS runs - // intermittently on paths like D:\DOCUME~1\user\LOCALS~1\Temp\ - - // We do not need to call GetLongPathName if we know it will fail becasue the path does not exist: - int lastErr = Marshal.GetLastWin32Error(); - if (lastErr == Win32Native.ERROR_FILE_NOT_FOUND || lastErr == Win32Native.ERROR_PATH_NOT_FOUND) - doNotTryExpandShortFileName = true; - - return false; - } - - // Safe to copy as we have already done Path.MaxPath bound checking - String.wstrcpy(buffer, shortFileNameBuffer, r); - Length = r; - // We should explicitly null terminate as in some cases the long version of the path - // might actually be shorter than what we started with because of Win32's normalization - // Safe to write directly as bufferLength is guaranteed to be < Path.MaxPath - NullTerminate(); - return true; - } - else { - StringBuilder sb = GetStringBuilder(); - - String origName = sb.ToString(); - String tempName = origName; - bool addedPrefix = false; - if (tempName.Length > Path.MaxPath) { - tempName = Path.AddLongPathPrefix(tempName); - addedPrefix = true; - } - sb.Capacity = m_capacity; - sb.Length = 0; - int r = Win32Native.GetLongPathName(tempName, sb, m_capacity); - - if (r == 0) { - // Note: GetLongPathName will return ERROR_INVALID_FUNCTION on a - // path like \\.\PHYSICALDEVICE0 - some device driver doesn't - // support GetLongPathName on that string. This behavior is - // by design, according to the Core File Services team. - // We also get ERROR_NOT_ENOUGH_QUOTA in SQL_CLR_STRESS runs - // intermittently on paths like D:\DOCUME~1\user\LOCALS~1\Temp\ - - // We do not need to call GetLongPathName if we know it will fail becasue the path does not exist: - int lastErr = Marshal.GetLastWin32Error(); - if (Win32Native.ERROR_FILE_NOT_FOUND == lastErr || Win32Native.ERROR_PATH_NOT_FOUND == lastErr) - doNotTryExpandShortFileName = true; - - sb.Length = 0; - sb.Append(origName); - return false; - } - - if (addedPrefix) - r -= 4; - - // If success, the return buffer length does not account for the terminating null character. - // If in-sufficient buffer, the return buffer length does account for the path + the terminating null character. - // If failure, the return buffer length is zero - if (r >= m_maxPath) - throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - - - sb = Path.RemoveLongPathPrefix(sb); - Length = sb.Length; - return true; - - } - } - - [System.Security.SecurityCritical] - internal unsafe void Fixup(int lenSavedName, int lastSlash) { - if (useStackAlloc) { - char* savedName = stackalloc char[lenSavedName]; - String.wstrcpy(savedName, m_arrayPtr + lastSlash + 1, lenSavedName); - Length = lastSlash; - NullTerminate(); - doNotTryExpandShortFileName = false; - bool r = TryExpandShortFileName(); - // Clean up changes made to the newBuffer. - Append(Path.DirectorySeparatorChar); - if (Length + lenSavedName >= Path.MaxPath) - throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - String.wstrcpy(m_arrayPtr + Length, savedName, lenSavedName); - Length = Length + lenSavedName; - - } - else { - String savedName = m_sb.ToString(lastSlash + 1, lenSavedName); - Length = lastSlash; - doNotTryExpandShortFileName = false; - bool r = TryExpandShortFileName(); - // Clean up changes made to the newBuffer. - Append(Path.DirectorySeparatorChar); - if (Length + lenSavedName >= m_maxPath) - throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); - m_sb.Append(savedName); - } - } - - [System.Security.SecurityCritical] - internal unsafe bool OrdinalStartsWith(String compareTo, bool ignoreCase) { - if (Length < compareTo.Length) - return false; - - if (useStackAlloc) { - NullTerminate(); - if (ignoreCase) { - String s = new String(m_arrayPtr, 0, compareTo.Length); - return compareTo.Equals(s, StringComparison.OrdinalIgnoreCase); - } - else { - for (int i = 0; i < compareTo.Length; i++) { - if (m_arrayPtr[i] != compareTo[i]) { - return false; - } - } - return true; - } - } - else { - if (ignoreCase) { - return m_sb.ToString().StartsWith(compareTo, StringComparison.OrdinalIgnoreCase); - } - else { - return m_sb.ToString().StartsWith(compareTo, StringComparison.Ordinal); - } - } - } - - [System.Security.SecurityCritical] - private unsafe bool OrdinalEqualsStackAlloc(String compareTo) - { - Contract.Requires(useStackAlloc, "Currently no efficient implementation for StringBuilder.OrdinalEquals(String)"); - - if (Length != compareTo.Length) { - return false; - } - - for (int i = 0; i < compareTo.Length; i++) { - if (m_arrayPtr[i] != compareTo[i]) { - return false; - } - } - - return true; - } - - [System.Security.SecuritySafeCritical] - public override String ToString() { - if (useStackAlloc) { - return new String(m_arrayPtr, 0, Length); - } - else { - return m_sb.ToString(); - } - } - - [System.Security.SecuritySafeCritical] - internal String ToStringOrExisting(String existingString) - { - if (useStackAlloc) { - return OrdinalEqualsStackAlloc(existingString) ? - existingString : - new String(m_arrayPtr, 0, Length); - } - else { - string newString = m_sb.ToString(); // currently no good StringBuilder.OrdinalEquals(string) - return String.Equals(newString, existingString, StringComparison.Ordinal) ? - existingString : - newString; - } - } - - [System.Security.SecurityCritical] - private unsafe char* UnsafeGetArrayPtr() { - Contract.Requires(useStackAlloc, "This should never be called for PathHelpers wrapping a StringBuilder"); - return m_arrayPtr; - } - - private StringBuilder GetStringBuilder() { - Contract.Requires(!useStackAlloc, "This should never be called for PathHelpers that wrap a stackalloc'd buffer"); - return m_sb; - } - - [System.Security.SecurityCritical] - private unsafe void NullTerminate() { - Contract.Requires(useStackAlloc, "This should never be called for PathHelpers wrapping a StringBuilder"); - m_arrayPtr[m_length] = '\0'; - } - - } -} -#endif // FEATURE_PATHCOMPAT \ No newline at end of file diff --git a/src/mscorlib/src/System/IO/PathInternal.cs b/src/mscorlib/src/System/IO/PathInternal.cs deleted file mode 100644 index 3970e22..0000000 --- a/src/mscorlib/src/System/IO/PathInternal.cs +++ /dev/null @@ -1,806 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using Microsoft.Win32; -using System; -using System.Diagnostics.Contracts; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Security; -using System.Text; - -namespace System.IO -{ - /// Contains internal path helpers that are shared between many projects. - internal static class PathInternal - { - internal const string ExtendedPathPrefix = @"\\?\"; - internal const string UncPathPrefix = @"\\"; - internal const string UncExtendedPrefixToInsert = @"?\UNC\"; - internal const string UncExtendedPathPrefix = @"\\?\UNC\"; - internal const string DevicePathPrefix = @"\\.\"; - // \\?\, \\.\, \??\ - internal const int DevicePrefixLength = 4; - // \\ - internal const int UncPrefixLength = 2; - // \\?\UNC\, \\.\UNC\ - internal const int UncExtendedPrefixLength = 8; -#if !PLATFORM_UNIX - internal const int MaxShortPath = 260; - internal const int MaxShortDirectoryPath = 248; -#else - internal const int MaxShortPath = 1024; - internal const int MaxShortDirectoryPath = MaxShortPath; -#endif - - // Windows is limited in long paths by the max size of its internal representation of a unicode string. - // UNICODE_STRING has a max length of USHORT in _bytes_ without a trailing null. - // https://msdn.microsoft.com/en-us/library/windows/hardware/ff564879.aspx - internal const int MaxLongPath = short.MaxValue; - internal static readonly int MaxComponentLength = 255; - -#if !PLATFORM_UNIX - internal static readonly char[] InvalidPathChars = - { - '\"', '<', '>', '|', '\0', - (char)1, (char)2, (char)3, (char)4, (char)5, (char)6, (char)7, (char)8, (char)9, (char)10, - (char)11, (char)12, (char)13, (char)14, (char)15, (char)16, (char)17, (char)18, (char)19, (char)20, - (char)21, (char)22, (char)23, (char)24, (char)25, (char)26, (char)27, (char)28, (char)29, (char)30, - (char)31 - }; -#else - internal static readonly char[] InvalidPathChars = { '\0' }; -#endif - - - /// - /// Validates volume separator only occurs as C: or \\?\C:. This logic is meant to filter out Alternate Data Streams. - /// - /// True if the path has an invalid volume separator. - internal static bool HasInvalidVolumeSeparator(string path) - { - // Toss out paths with colons that aren't a valid drive specifier. - // Cannot start with a colon and can only be of the form "C:" or "\\?\C:". - // (Note that we used to explicitly check "http:" and "file:"- these are caught by this check now.) - - // We don't care about skipping starting space for extended paths. Assume no knowledge of extended paths if we're forcing old path behavior. - bool isExtended = -#if FEATURE_PATHCOMPAT - !AppContextSwitches.UseLegacyPathHandling && -#endif - IsExtended(path); - int startIndex = isExtended ? ExtendedPathPrefix.Length : PathStartSkip(path); - - // If we start with a colon - if ((path.Length > startIndex && path[startIndex] == Path.VolumeSeparatorChar) - // Or have an invalid drive letter and colon - || (path.Length >= startIndex + 2 && path[startIndex + 1] == Path.VolumeSeparatorChar && !IsValidDriveChar(path[startIndex])) - // Or have any colons beyond the drive colon - || (path.Length > startIndex + 2 && path.IndexOf(Path.VolumeSeparatorChar, startIndex + 2) != -1)) - { - return true; - } - - return false; - } - - /// - /// Returns true if the given StringBuilder starts with the given value. - /// - /// The string to compare against the start of the StringBuilder. - internal static bool StartsWithOrdinal(StringBuilder builder, string value, bool ignoreCase = false) - { - if (value == null || builder.Length < value.Length) - return false; - - if (ignoreCase) - { - for (int i = 0; i < value.Length; i++) - if (char.ToUpperInvariant(builder[i]) != char.ToUpperInvariant(value[i])) return false; - } - else - { - for (int i = 0; i < value.Length; i++) - if (builder[i] != value[i]) return false; - } - - return true; - } - - /// - /// Returns true if the given character is a valid drive letter - /// - internal static bool IsValidDriveChar(char value) - { - return ((value >= 'A' && value <= 'Z') || (value >= 'a' && value <= 'z')); - } - - /// - /// Returns true if the path is too long - /// - internal static bool IsPathTooLong(string fullPath) - { - // We'll never know precisely what will fail as paths get changed internally in Windows and - // may grow beyond / shrink below exceed MaxLongPath. -#if FEATURE_PATHCOMPAT - if (AppContextSwitches.BlockLongPaths) - { - // We allow paths of any length if extended (and not in compat mode) - if (AppContextSwitches.UseLegacyPathHandling || !IsExtended(fullPath)) - return fullPath.Length >= MaxShortPath; - } -#endif - - return fullPath.Length >= MaxLongPath; - } - - /// - /// Return true if any path segments are too long - /// - internal static bool AreSegmentsTooLong(string fullPath) - { - int length = fullPath.Length; - int lastSeparator = 0; - - for (int i = 0; i < length; i++) - { - if (IsDirectorySeparator(fullPath[i])) - { - if (i - lastSeparator > MaxComponentLength) - return true; - lastSeparator = i; - } - } - - if (length - 1 - lastSeparator > MaxComponentLength) - return true; - - return false; - } - - /// - /// Returns true if the directory is too long - /// - internal static bool IsDirectoryTooLong(string fullPath) - { -#if FEATURE_PATHCOMPAT - if (AppContextSwitches.BlockLongPaths) - { - // We allow paths of any length if extended (and not in compat mode) - if (AppContextSwitches.UseLegacyPathHandling || !IsExtended(fullPath)) - return (fullPath.Length >= MaxShortDirectoryPath); - } -#endif - - return IsPathTooLong(fullPath); - } - - /// - /// Adds the extended path prefix (\\?\) if not relative or already a device path. - /// - internal static string EnsureExtendedPrefix(string path) - { - // Putting the extended prefix on the path changes the processing of the path. It won't get normalized, which - // means adding to relative paths will prevent them from getting the appropriate current directory inserted. - - // If it already has some variant of a device path (\??\, \\?\, \\.\, //./, etc.) we don't need to change it - // as it is either correct or we will be changing the behavior. When/if Windows supports long paths implicitly - // in the future we wouldn't want normalization to come back and break existing code. - - // In any case, all internal usages should be hitting normalize path (Path.GetFullPath) before they hit this - // shimming method. (Or making a change that doesn't impact normalization, such as adding a filename to a - // normalized base path.) - if (IsPartiallyQualified(path) || IsDevice(path)) - return path; - - // Given \\server\share in longpath becomes \\?\UNC\server\share - if (path.StartsWith(UncPathPrefix, StringComparison.OrdinalIgnoreCase)) - return path.Insert(2, UncExtendedPrefixToInsert); - - return ExtendedPathPrefix + path; - } - - /// - /// Removes the extended path prefix (\\?\) if present. - /// - internal static string RemoveExtendedPrefix(string path) - { - if (!IsExtended(path)) - return path; - - // Given \\?\UNC\server\share we return \\server\share - if (IsExtendedUnc(path)) - return path.Remove(2, 6); - - return path.Substring(DevicePrefixLength); - } - - /// - /// Removes the extended path prefix (\\?\) if present. - /// - internal static StringBuilder RemoveExtendedPrefix(StringBuilder path) - { - if (!IsExtended(path)) - return path; - - // Given \\?\UNC\server\share we return \\server\share - if (IsExtendedUnc(path)) - return path.Remove(2, 6); - - return path.Remove(0, DevicePrefixLength); - } - - /// - /// Returns true if the path uses any of the DOS device path syntaxes. ("\\.\", "\\?\", or "\??\") - /// - internal static bool IsDevice(string path) - { - // If the path begins with any two separators it will be recognized and normalized and prepped with - // "\??\" for internal usage correctly. "\??\" is recognized and handled, "/??/" is not. - return IsExtended(path) - || - ( - path.Length >= DevicePrefixLength - && IsDirectorySeparator(path[0]) - && IsDirectorySeparator(path[1]) - && (path[2] == '.' || path[2] == '?') - && IsDirectorySeparator(path[3]) - ); - } - - /// - /// Returns true if the path uses any of the DOS device path syntaxes. ("\\.\", "\\?\", or "\??\") - /// - internal static bool IsDevice(StringBuffer path) - { - // If the path begins with any two separators it will be recognized and normalized and prepped with - // "\??\" for internal usage correctly. "\??\" is recognized and handled, "/??/" is not. - return IsExtended(path) - || - ( - path.Length >= DevicePrefixLength - && IsDirectorySeparator(path[0]) - && IsDirectorySeparator(path[1]) - && (path[2] == '.' || path[2] == '?') - && IsDirectorySeparator(path[3]) - ); - } - - /// - /// Returns true if the path uses the canonical form of extended syntax ("\\?\" or "\??\"). If the - /// path matches exactly (cannot use alternate directory separators) Windows will skip normalization - /// and path length checks. - /// - internal static bool IsExtended(string path) - { - // While paths like "//?/C:/" will work, they're treated the same as "\\.\" paths. - // Skipping of normalization will *only* occur if back slashes ('\') are used. - return path.Length >= DevicePrefixLength - && path[0] == '\\' - && (path[1] == '\\' || path[1] == '?') - && path[2] == '?' - && path[3] == '\\'; - } - - /// - /// Returns true if the path uses the canonical form of extended syntax ("\\?\" or "\??\"). If the - /// path matches exactly (cannot use alternate directory separators) Windows will skip normalization - /// and path length checks. - /// - internal static bool IsExtended(StringBuilder path) - { - // While paths like "//?/C:/" will work, they're treated the same as "\\.\" paths. - // Skipping of normalization will *only* occur if back slashes ('\') are used. - return path.Length >= DevicePrefixLength - && path[0] == '\\' - && (path[1] == '\\' || path[1] == '?') - && path[2] == '?' - && path[3] == '\\'; - } - - /// - /// Returns true if the path uses the canonical form of extended syntax ("\\?\" or "\??\"). If the - /// path matches exactly (cannot use alternate directory separators) Windows will skip normalization - /// and path length checks. - /// - internal static bool IsExtended(StringBuffer path) - { - // While paths like "//?/C:/" will work, they're treated the same as "\\.\" paths. - // Skipping of normalization will *only* occur if back slashes ('\') are used. - return path.Length >= DevicePrefixLength - && path[0] == '\\' - && (path[1] == '\\' || path[1] == '?') - && path[2] == '?' - && path[3] == '\\'; - } - - /// - /// Returns true if the path uses the extended UNC syntax (\\?\UNC\ or \??\UNC\) - /// - internal static bool IsExtendedUnc(string path) - { - return path.Length >= UncExtendedPathPrefix.Length - && IsExtended(path) - && char.ToUpper(path[4]) == 'U' - && char.ToUpper(path[5]) == 'N' - && char.ToUpper(path[6]) == 'C' - && path[7] == '\\'; - } - - /// - /// Returns true if the path uses the extended UNC syntax (\\?\UNC\ or \??\UNC\) - /// - internal static bool IsExtendedUnc(StringBuilder path) - { - return path.Length >= UncExtendedPathPrefix.Length - && IsExtended(path) - && char.ToUpper(path[4]) == 'U' - && char.ToUpper(path[5]) == 'N' - && char.ToUpper(path[6]) == 'C' - && path[7] == '\\'; - } - - /// - /// Returns a value indicating if the given path contains invalid characters (", <, >, | - /// NUL, or any ASCII char whose integer representation is in the range of 1 through 31). - /// Does not check for wild card characters ? and *. - /// - /// Will not check if the path is a device path and not in Legacy mode as many of these - /// characters are valid for devices (pipes for example). - /// - internal static bool HasIllegalCharacters(string path, bool checkAdditional = false) - { - if ( -#if FEATURE_PATHCOMPAT - !AppContextSwitches.UseLegacyPathHandling && -#endif - IsDevice(path)) - { - return false; - } - - return AnyPathHasIllegalCharacters(path, checkAdditional: checkAdditional); - } - - /// - /// Version of HasIllegalCharacters that checks no AppContextSwitches. Only use if you know you need to skip switches and don't care - /// about proper device path handling. - /// - internal static bool AnyPathHasIllegalCharacters(string path, bool checkAdditional = false) - { - return path.IndexOfAny(InvalidPathChars) >= 0 -#if !PLATFORM_UNIX - || (checkAdditional && AnyPathHasWildCardCharacters(path)) -#endif - ; - } - - /// - /// Check for ? and *. - /// - internal static bool HasWildCardCharacters(string path) - { - // Question mark is part of some device paths - int startIndex = -#if FEATURE_PATHCOMPAT - AppContextSwitches.UseLegacyPathHandling ? 0 : -#endif - IsDevice(path) ? ExtendedPathPrefix.Length : 0; - return AnyPathHasWildCardCharacters(path, startIndex: startIndex); - } - - /// - /// Version of HasWildCardCharacters that checks no AppContextSwitches. Only use if you know you need to skip switches and don't care - /// about proper device path handling. - /// - internal static bool AnyPathHasWildCardCharacters(string path, int startIndex = 0) - { - char currentChar; - for (int i = startIndex; i < path.Length; i++) - { - currentChar = path[i]; - if (currentChar == '*' || currentChar == '?') return true; - } - return false; - } - - /// - /// Gets the length of the root of the path (drive, share, etc.). - /// - [System.Security.SecuritySafeCritical] - internal unsafe static int GetRootLength(string path) - { - fixed (char* value = path) - { - return (int)GetRootLength(value, (ulong)path.Length); - } - } - - /// - /// Gets the length of the root of the path (drive, share, etc.). - /// - [System.Security.SecuritySafeCritical] - internal unsafe static uint GetRootLength(StringBuffer path) - { - if (path.Length == 0) return 0; - return GetRootLength(path.CharPointer, path.Length); - } - - [System.Security.SecurityCritical] - private unsafe static uint GetRootLength(char* path, ulong pathLength) - { - uint i = 0; - -#if PLATFORM_UNIX - if (pathLength >= 1 && (IsDirectorySeparator(path[0]))) - i = 1; -#else - uint volumeSeparatorLength = 2; // Length to the colon "C:" - uint uncRootLength = 2; // Length to the start of the server name "\\" - - bool extendedSyntax = StartsWithOrdinal(path, pathLength, ExtendedPathPrefix); - bool extendedUncSyntax = StartsWithOrdinal(path, pathLength, UncExtendedPathPrefix); - if (extendedSyntax) - { - // Shift the position we look for the root from to account for the extended prefix - if (extendedUncSyntax) - { - // "\\" -> "\\?\UNC\" - uncRootLength = (uint)UncExtendedPathPrefix.Length; - } - else - { - // "C:" -> "\\?\C:" - volumeSeparatorLength += (uint)ExtendedPathPrefix.Length; - } - } - - if ((!extendedSyntax || extendedUncSyntax) && pathLength > 0 && IsDirectorySeparator(path[0])) - { - // UNC or simple rooted path (e.g. "\foo", NOT "\\?\C:\foo") - - i = 1; // Drive rooted (\foo) is one character - if (extendedUncSyntax || (pathLength > 1 && IsDirectorySeparator(path[1]))) - { - // UNC (\\?\UNC\ or \\), scan past the next two directory separators at most - // (e.g. to \\?\UNC\Server\Share or \\Server\Share\) - i = uncRootLength; - int n = 2; // Maximum separators to skip - while (i < pathLength && (!IsDirectorySeparator(path[i]) || --n > 0)) i++; - } - } - else if (pathLength >= volumeSeparatorLength && path[volumeSeparatorLength - 1] == Path.VolumeSeparatorChar) - { - // Path is at least longer than where we expect a colon, and has a colon (\\?\A:, A:) - // If the colon is followed by a directory separator, move past it - i = volumeSeparatorLength; - if (pathLength >= volumeSeparatorLength + 1 && IsDirectorySeparator(path[volumeSeparatorLength])) i++; - } -#endif // !PLATFORM_UNIX - return i; - } - - [System.Security.SecurityCritical] - private unsafe static bool StartsWithOrdinal(char* source, ulong sourceLength, string value) - { - if (sourceLength < (ulong)value.Length) return false; - for (int i = 0; i < value.Length; i++) - { - if (value[i] != source[i]) return false; - } - return true; - } - - /// - /// Returns true if the path specified is relative to the current drive or working directory. - /// Returns false if the path is fixed to a specific drive or UNC path. This method does no - /// validation of the path (URIs will be returned as relative as a result). - /// - /// - /// Handles paths that use the alternate directory separator. It is a frequent mistake to - /// assume that rooted paths (Path.IsPathRooted) are not relative. This isn't the case. - /// "C:a" is drive relative- meaning that it will be resolved against the current directory - /// for C: (rooted, but relative). "C:\a" is rooted and not relative (the current directory - /// will not be used to modify the path). - /// - internal static bool IsPartiallyQualified(string path) - { -#if PLATFORM_UNIX - return !(path.Length >= 1 && path[0] == Path.DirectorySeparatorChar); -#else - if (path.Length < 2) - { - // It isn't fixed, it must be relative. There is no way to specify a fixed - // path with one character (or less). - return true; - } - - if (IsDirectorySeparator(path[0])) - { - // There is no valid way to specify a relative path with two initial slashes or - // \? as ? isn't valid for drive relative paths and \??\ is equivalent to \\?\ - return !(path[1] == '?' || IsDirectorySeparator(path[1])); - } - - // The only way to specify a fixed path that doesn't begin with two slashes - // is the drive, colon, slash format- i.e. C:\ - return !((path.Length >= 3) - && (path[1] == Path.VolumeSeparatorChar) - && IsDirectorySeparator(path[2]) - // To match old behavior we'll check the drive character for validity as the path is technically - // not qualified if you don't have a valid drive. "=:\" is the "=" file's default data stream. - && IsValidDriveChar(path[0])); -#endif // !PLATFORM_UNIX - } - - /// - /// Returns true if the path specified is relative to the current drive or working directory. - /// Returns false if the path is fixed to a specific drive or UNC path. This method does no - /// validation of the path (URIs will be returned as relative as a result). - /// - /// - /// Handles paths that use the alternate directory separator. It is a frequent mistake to - /// assume that rooted paths (Path.IsPathRooted) are not relative. This isn't the case. - /// "C:a" is drive relative- meaning that it will be resolved against the current directory - /// for C: (rooted, but relative). "C:\a" is rooted and not relative (the current directory - /// will not be used to modify the path). - /// - internal static bool IsPartiallyQualified(StringBuffer path) - { -#if PLATFORM_UNIX - return !(path.Length >= 1 && path[0] == Path.DirectorySeparatorChar); -#else - if (path.Length < 2) - { - // It isn't fixed, it must be relative. There is no way to specify a fixed - // path with one character (or less). - return true; - } - - if (IsDirectorySeparator(path[0])) - { - // There is no valid way to specify a relative path with two initial slashes or - // \? as ? isn't valid for drive relative paths and \??\ is equivalent to \\?\ - return !(path[1] == '?' || IsDirectorySeparator(path[1])); - } - - // The only way to specify a fixed path that doesn't begin with two slashes - // is the drive, colon, slash format- i.e. C:\ - return !((path.Length >= 3) - && (path[1] == Path.VolumeSeparatorChar) - && IsDirectorySeparator(path[2]) - // To match old behavior we'll check the drive character for validity as the path is technically - // not qualified if you don't have a valid drive. "=:\" is the "=" file's default data stream. - && IsValidDriveChar(path[0])); -#endif // !PLATFORM_UNIX - } - - /// - /// On Windows, returns the characters to skip at the start of the path if it starts with space(s) and a drive or directory separator. - /// (examples are " C:", " \") - /// This is a legacy behavior of Path.GetFullPath(). - /// - /// - /// Note that this conflicts with IsPathRooted() which doesn't (and never did) such a skip. - /// - internal static int PathStartSkip(string path) - { -#if !PLATFORM_UNIX - int startIndex = 0; - while (startIndex < path.Length && path[startIndex] == ' ') startIndex++; - - if (startIndex > 0 && (startIndex < path.Length && IsDirectorySeparator(path[startIndex])) - || (startIndex + 1 < path.Length && path[startIndex + 1] == Path.VolumeSeparatorChar && IsValidDriveChar(path[startIndex]))) - { - // Go ahead and skip spaces as we're either " C:" or " \" - return startIndex; - } -#endif - - return 0; - } - - /// - /// True if the given character is a directory separator. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static bool IsDirectorySeparator(char c) - { - return c == Path.DirectorySeparatorChar -#if !PLATFORM_UNIX - || c == Path.AltDirectorySeparatorChar -#endif - ; - } - - /// - /// Normalize separators in the given path. Converts forward slashes into back slashes and compresses slash runs, keeping initial 2 if present. - /// Also trims initial whitespace in front of "rooted" paths (see PathStartSkip). - /// - /// This effectively replicates the behavior of the legacy NormalizePath when it was called with fullCheck=false and expandShortpaths=false. - /// The current NormalizePath gets directory separator normalization from Win32's GetFullPathName(), which will resolve relative paths and as - /// such can't be used here (and is overkill for our uses). - /// - /// Like the current NormalizePath this will not try and analyze periods/spaces within directory segments. - /// - /// - /// The only callers that used to use Path.Normalize(fullCheck=false) were Path.GetDirectoryName() and Path.GetPathRoot(). Both usages do - /// not need trimming of trailing whitespace here. - /// - /// GetPathRoot() could technically skip normalizing separators after the second segment- consider as a future optimization. - /// - /// For legacy desktop behavior with ExpandShortPaths: - /// - It has no impact on GetPathRoot() so doesn't need consideration. - /// - It could impact GetDirectoryName(), but only if the path isn't relative (C:\ or \\Server\Share). - /// - /// In the case of GetDirectoryName() the ExpandShortPaths behavior was undocumented and provided inconsistent results if the path was - /// fixed/relative. For example: "C:\PROGRA~1\A.TXT" would return "C:\Program Files" while ".\PROGRA~1\A.TXT" would return ".\PROGRA~1". If you - /// ultimately call GetFullPath() this doesn't matter, but if you don't or have any intermediate string handling could easily be tripped up by - /// this undocumented behavior. - /// - internal static string NormalizeDirectorySeparators(string path) - { - if (string.IsNullOrEmpty(path)) return path; - - char current; - int start = PathStartSkip(path); - - if (start == 0) - { - // Make a pass to see if we need to normalize so we can potentially skip allocating - bool normalized = true; - - for (int i = 0; i < path.Length; i++) - { - current = path[i]; - if (IsDirectorySeparator(current) - && (current != Path.DirectorySeparatorChar -#if !PLATFORM_UNIX - // Check for sequential separators past the first position (we need to keep initial two for UNC/extended) - || (i > 0 && i + 1 < path.Length && IsDirectorySeparator(path[i + 1])) -#endif - )) - { - normalized = false; - break; - } - } - - if (normalized) return path; - } - - StringBuilder builder = StringBuilderCache.Acquire(path.Length); - -#if !PLATFORM_UNIX - // On Windows we always keep the first separator, even if the next is a separator (we need to keep initial two for UNC/extended) - if (IsDirectorySeparator(path[start])) - { - start++; - builder.Append(Path.DirectorySeparatorChar); - } -#endif - - for (int i = start; i < path.Length; i++) - { - current = path[i]; - - // If we have a separator - if (IsDirectorySeparator(current)) - { - // If the next is a separator, skip adding this - if (i + 1 < path.Length && IsDirectorySeparator(path[i + 1])) - { - continue; - } - - // Ensure it is the primary separator - current = Path.DirectorySeparatorChar; - } - - builder.Append(current); - } - - return StringBuilderCache.GetStringAndRelease(builder); - } - -#if PLATFORM_UNIX - // We rely on Windows to remove relative segments on Windows. This would need to be updated to - // handle the proper rooting on Windows if we for some reason need it. - - /// - /// Try to remove relative segments from the given path (without combining with a root). - /// - /// Skip the specified number of characters before evaluating. - internal static string RemoveRelativeSegments(string path, int skip = 0) - { - bool flippedSeparator = false; - - // Remove "//", "/./", and "/../" from the path by copying each character to the output, - // except the ones we're removing, such that the builder contains the normalized path - // at the end. - var sb = StringBuilderCache.Acquire(path.Length); - if (skip > 0) - { - sb.Append(path, 0, skip); - } - - int componentCharCount = 0; - for (int i = skip; i < path.Length; i++) - { - char c = path[i]; - - if (PathInternal.IsDirectorySeparator(c) && i + 1 < path.Length) - { - componentCharCount = 0; - - // Skip this character if it's a directory separator and if the next character is, too, - // e.g. "parent//child" => "parent/child" - if (PathInternal.IsDirectorySeparator(path[i + 1])) - { - continue; - } - - // Skip this character and the next if it's referring to the current directory, - // e.g. "parent/./child" =? "parent/child" - if ((i + 2 == path.Length || PathInternal.IsDirectorySeparator(path[i + 2])) && - path[i + 1] == '.') - { - i++; - continue; - } - - // Skip this character and the next two if it's referring to the parent directory, - // e.g. "parent/child/../grandchild" => "parent/grandchild" - if (i + 2 < path.Length && - (i + 3 == path.Length || PathInternal.IsDirectorySeparator(path[i + 3])) && - path[i + 1] == '.' && path[i + 2] == '.') - { - // Unwind back to the last slash (and if there isn't one, clear out everything). - int s; - for (s = sb.Length - 1; s >= 0; s--) - { - if (PathInternal.IsDirectorySeparator(sb[s])) - { - sb.Length = s; - break; - } - } - if (s < 0) - { - sb.Length = 0; - } - - i += 2; - continue; - } - } - - if (++componentCharCount > PathInternal.MaxComponentLength) - { - throw new PathTooLongException(); - } - - // Normalize the directory separator if needed - if (c != Path.DirectorySeparatorChar && c == Path.AltDirectorySeparatorChar) - { - c = Path.DirectorySeparatorChar; - flippedSeparator = true; - } - - sb.Append(c); - } - - if (flippedSeparator || sb.Length != path.Length) - { - return StringBuilderCache.GetStringAndRelease(sb); - } - else - { - // We haven't changed the source path, return the original - StringBuilderCache.Release(sb); - return path; - } - } -#endif // PLATFORM_UNIX - } -} \ No newline at end of file diff --git a/src/mscorlib/src/System/IO/PinnedBufferMemoryStream.cs b/src/mscorlib/src/System/IO/PinnedBufferMemoryStream.cs index 4fd54f5..890669f 100644 --- a/src/mscorlib/src/System/IO/PinnedBufferMemoryStream.cs +++ b/src/mscorlib/src/System/IO/PinnedBufferMemoryStream.cs @@ -15,6 +15,7 @@ ===========================================================*/ using System; using System.Runtime.InteropServices; +using System.Diagnostics; using System.Diagnostics.Contracts; namespace System.IO { @@ -24,13 +25,11 @@ namespace System.IO { private GCHandle _pinningHandle; // The new inheritance model requires a Critical default ctor since base (UnmanagedMemoryStream) has one - [System.Security.SecurityCritical] private PinnedBufferMemoryStream():base(){} - [System.Security.SecurityCritical] // auto-generated internal PinnedBufferMemoryStream(byte[] array) { - Contract.Assert(array != null, "Array can't be null"); + Debug.Assert(array != null, "Array can't be null"); int len = array.Length; // Handle 0 length byte arrays specially. @@ -52,7 +51,6 @@ namespace System.IO { Dispose(false); } - [System.Security.SecuritySafeCritical] // auto-generated protected override void Dispose(bool disposing) { if (_isOpen) { diff --git a/src/mscorlib/src/System/IO/Stream.cs b/src/mscorlib/src/System/IO/Stream.cs index a1f2936..3cdfad6 100644 --- a/src/mscorlib/src/System/IO/Stream.cs +++ b/src/mscorlib/src/System/IO/Stream.cs @@ -15,26 +15,23 @@ ** ===========================================================*/ using System; +using System.Buffers; using System.Threading; using System.Threading.Tasks; - using System.Runtime; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Security; using System.Security.Permissions; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Reflection; namespace System.IO { [Serializable] [ComVisible(true)] -#if FEATURE_REMOTING public abstract class Stream : MarshalByRefObject, IDisposable { -#else // FEATURE_REMOTING - public abstract class Stream : IDisposable { -#endif // FEATURE_REMOTING public static readonly Stream Null = new NullStream(); @@ -112,13 +109,11 @@ namespace System.IO { } } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public Task CopyToAsync(Stream destination) { int bufferSize = _DefaultCopyBufferSize; -#if FEATURE_CORECLR if (CanSeek) { long length = Length; @@ -147,23 +142,20 @@ namespace System.IO { bufferSize = (int)Math.Min(bufferSize, remaining); } } -#endif // FEATURE_CORECLR - + return CopyToAsync(destination, bufferSize); } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public Task CopyToAsync(Stream destination, Int32 bufferSize) { return CopyToAsync(destination, bufferSize, CancellationToken.None); } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public virtual Task CopyToAsync(Stream destination, Int32 bufferSize, CancellationToken cancellationToken) { - ValidateCopyToArguments(destination, bufferSize); + StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize); return CopyToAsyncInternal(destination, bufferSize, cancellationToken); } @@ -175,11 +167,22 @@ namespace System.IO { Contract.Requires(CanRead); Contract.Requires(destination.CanWrite); - byte[] buffer = new byte[bufferSize]; - int bytesRead; - while ((bytesRead = await ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0) + byte[] buffer = ArrayPool.Shared.Rent(bufferSize); + bufferSize = 0; // reuse same field for high water mark to avoid needing another field in the state machine + try + { + while (true) + { + int bytesRead = await ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); + if (bytesRead == 0) break; + if (bytesRead > bufferSize) bufferSize = bytesRead; + await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false); + } + } + finally { - await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false); + Array.Clear(buffer, 0, bufferSize); // clear only the most we used + ArrayPool.Shared.Return(buffer, clearArray: false); } } @@ -190,7 +193,6 @@ namespace System.IO { { int bufferSize = _DefaultCopyBufferSize; -#if FEATURE_CORECLR if (CanSeek) { long length = Length; @@ -209,19 +211,30 @@ namespace System.IO { bufferSize = (int)Math.Min(bufferSize, remaining); } } -#endif // FEATURE_CORECLR - + CopyTo(destination, bufferSize); } public virtual void CopyTo(Stream destination, int bufferSize) { - ValidateCopyToArguments(destination, bufferSize); - - byte[] buffer = new byte[bufferSize]; - int read; - while ((read = Read(buffer, 0, buffer.Length)) != 0) - destination.Write(buffer, 0, read); + StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize); + + byte[] buffer = ArrayPool.Shared.Rent(bufferSize); + int highwaterMark = 0; + try + { + int read; + while ((read = Read(buffer, 0, buffer.Length)) != 0) + { + if (read > highwaterMark) highwaterMark = read; + destination.Write(buffer, 0, read); + } + } + finally + { + Array.Clear(buffer, 0, highwaterMark); // clear only the most we used + ArrayPool.Shared.Return(buffer, clearArray: false); + } } // Stream used to require that all cleanup logic went into Close(), @@ -265,14 +278,12 @@ namespace System.IO { public abstract void Flush(); - [HostProtection(ExternalThreading=true)] [ComVisible(false)] public Task FlushAsync() { return FlushAsync(CancellationToken.None); } - [HostProtection(ExternalThreading=true)] [ComVisible(false)] public virtual Task FlushAsync(CancellationToken cancellationToken) { @@ -287,14 +298,12 @@ namespace System.IO { return new ManualResetEvent(false); } - [HostProtection(ExternalThreading=true)] public virtual IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) { Contract.Ensures(Contract.Result() != null); return BeginReadInternal(buffer, offset, count, callback, state, serializeAsynchronously: false, apm: true); } - [HostProtection(ExternalThreading = true)] internal IAsyncResult BeginReadInternal( byte[] buffer, int offset, int count, AsyncCallback callback, Object state, bool serializeAsynchronously, bool apm) @@ -326,7 +335,7 @@ namespace System.IO { // As we're currently inside of it, we can get the current task // and grab the parameters from it. var thisTask = Task.InternalCurrent as ReadWriteTask; - Contract.Assert(thisTask != null, "Inside ReadWriteTask, InternalCurrent should be the ReadWriteTask"); + Debug.Assert(thisTask != null, "Inside ReadWriteTask, InternalCurrent should be the ReadWriteTask"); try { @@ -360,7 +369,7 @@ namespace System.IO { public virtual int EndRead(IAsyncResult asyncResult) { if (asyncResult == null) - throw new ArgumentNullException("asyncResult"); + throw new ArgumentNullException(nameof(asyncResult)); Contract.Ensures(Contract.Result() >= 0); Contract.EndContractBlock(); @@ -389,14 +398,12 @@ namespace System.IO { } } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public Task ReadAsync(Byte[] buffer, int offset, int count) { return ReadAsync(buffer, offset, count, CancellationToken.None); } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public virtual Task ReadAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken) { @@ -407,7 +414,6 @@ namespace System.IO { : BeginEndReadAsync(buffer, offset, count); } - [System.Security.SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern bool HasOverriddenBeginEndRead(); @@ -436,14 +442,12 @@ namespace System.IO { - [HostProtection(ExternalThreading=true)] public virtual IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) { Contract.Ensures(Contract.Result() != null); return BeginWriteInternal(buffer, offset, count, callback, state, serializeAsynchronously: false, apm: true); } - [HostProtection(ExternalThreading = true)] internal IAsyncResult BeginWriteInternal( byte[] buffer, int offset, int count, AsyncCallback callback, Object state, bool serializeAsynchronously, bool apm) @@ -475,7 +479,7 @@ namespace System.IO { // As we're currently inside of it, we can get the current task // and grab the parameters from it. var thisTask = Task.InternalCurrent as ReadWriteTask; - Contract.Assert(thisTask != null, "Inside ReadWriteTask, InternalCurrent should be the ReadWriteTask"); + Debug.Assert(thisTask != null, "Inside ReadWriteTask, InternalCurrent should be the ReadWriteTask"); try { @@ -508,20 +512,20 @@ namespace System.IO { private void RunReadWriteTaskWhenReady(Task asyncWaiter, ReadWriteTask readWriteTask) { - Contract.Assert(readWriteTask != null); // Should be Contract.Requires, but CCRewrite is doing a poor job with + Debug.Assert(readWriteTask != null); // Should be Contract.Requires, but CCRewrite is doing a poor job with // preconditions in async methods that await. - Contract.Assert(asyncWaiter != null); // Ditto + Debug.Assert(asyncWaiter != null); // Ditto // If the wait has already completed, run the task. if (asyncWaiter.IsCompleted) { - Contract.Assert(asyncWaiter.IsRanToCompletion, "The semaphore wait should always complete successfully."); + Debug.Assert(asyncWaiter.IsRanToCompletion, "The semaphore wait should always complete successfully."); RunReadWriteTask(readWriteTask); } else // Otherwise, wait for our turn, and then run the task. { asyncWaiter.ContinueWith((t, state) => { - Contract.Assert(t.IsRanToCompletion, "The semaphore wait should always complete successfully."); + Debug.Assert(t.IsRanToCompletion, "The semaphore wait should always complete successfully."); var rwt = (ReadWriteTask)state; rwt._stream.RunReadWriteTask(rwt); // RunReadWriteTask(readWriteTask); }, readWriteTask, default(CancellationToken), TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); @@ -531,7 +535,7 @@ namespace System.IO { private void RunReadWriteTask(ReadWriteTask readWriteTask) { Contract.Requires(readWriteTask != null); - Contract.Assert(_activeReadWriteTask == null, "Expected no other readers or writers"); + Debug.Assert(_activeReadWriteTask == null, "Expected no other readers or writers"); // Schedule the task. ScheduleAndStart must happen after the write to _activeReadWriteTask to avoid a race. // Internally, we're able to directly call ScheduleAndStart rather than Start, avoiding @@ -545,14 +549,14 @@ namespace System.IO { private void FinishTrackingAsyncOperation() { _activeReadWriteTask = null; - Contract.Assert(_asyncActiveSemaphore != null, "Must have been initialized in order to get here."); + Debug.Assert(_asyncActiveSemaphore != null, "Must have been initialized in order to get here."); _asyncActiveSemaphore.Release(); } public virtual void EndWrite(IAsyncResult asyncResult) { if (asyncResult==null) - throw new ArgumentNullException("asyncResult"); + throw new ArgumentNullException(nameof(asyncResult)); Contract.EndContractBlock(); var writeTask = _activeReadWriteTask; @@ -572,7 +576,7 @@ namespace System.IO { try { writeTask.GetAwaiter().GetResult(); // block until completion, then propagate any exceptions - Contract.Assert(writeTask.Status == TaskStatus.RanToCompletion); + Debug.Assert(writeTask.Status == TaskStatus.RanToCompletion); } finally { @@ -613,7 +617,6 @@ namespace System.IO { _buffer = null; } - [SecuritySafeCritical] // necessary for EC.Capture [MethodImpl(MethodImplOptions.NoInlining)] public ReadWriteTask( bool isRead, @@ -651,7 +654,6 @@ namespace System.IO { } } - [SecurityCritical] // necessary for CoreCLR private static void InvokeAsyncCallback(object completedTask) { var rwc = (ReadWriteTask)completedTask; @@ -660,10 +662,8 @@ namespace System.IO { callback(rwc); } - [SecurityCritical] // necessary for CoreCLR private static ContextCallback s_invokeAsyncCallback; - [SecuritySafeCritical] // necessary for ExecutionContext.Run void ITaskCompletionAction.Invoke(Task completingTask) { // Get the ExecutionContext. If there is none, just run the callback @@ -690,7 +690,6 @@ namespace System.IO { bool ITaskCompletionAction.InvokeMayRunArbitraryCode { get { return true; } } } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public Task WriteAsync(Byte[] buffer, int offset, int count) { @@ -699,7 +698,6 @@ namespace System.IO { - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public virtual Task WriteAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken) { @@ -710,7 +708,6 @@ namespace System.IO { : BeginEndWriteAsync(buffer, offset, count); } - [System.Security.SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern bool HasOverriddenBeginEndWrite(); @@ -772,11 +769,10 @@ namespace System.IO { Write(oneByteArray, 0, 1); } - [HostProtection(Synchronization=true)] public static Stream Synchronized(Stream stream) { if (stream==null) - throw new ArgumentNullException("stream"); + throw new ArgumentNullException(nameof(stream)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); if (stream is SyncStream) @@ -853,23 +849,6 @@ namespace System.IO { { SynchronousAsyncResult.EndWrite(asyncResult); } - - internal void ValidateCopyToArguments(Stream destination, int bufferSize) - { - if (destination == null) - throw new ArgumentNullException("destination"); - if (bufferSize <= 0) - throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); - if (!CanRead && !CanWrite) - throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_StreamClosed")); - if (!destination.CanRead && !destination.CanWrite) - throw new ObjectDisposedException("destination", Environment.GetResourceString("ObjectDisposed_StreamClosed")); - if (!CanRead) - throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnreadableStream")); - if (!destination.CanWrite) - throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnwritableStream")); - Contract.EndContractBlock(); - } [Serializable] private sealed class NullStream : Stream @@ -900,11 +879,18 @@ namespace System.IO { set {} } + public override void CopyTo(Stream destination, int bufferSize) + { + StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize); + + // After we validate arguments this is a nop. + } + public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) { // Validate arguments here for compat, since previously this method // was inherited from Stream (which did check its arguments). - ValidateCopyToArguments(destination, bufferSize); + StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize); return cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) : @@ -928,7 +914,6 @@ namespace System.IO { Task.CompletedTask; } - [HostProtection(ExternalThreading = true)] public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) { if (!CanRead) __Error.ReadNotSupported(); @@ -939,13 +924,12 @@ namespace System.IO { public override int EndRead(IAsyncResult asyncResult) { if (asyncResult == null) - throw new ArgumentNullException("asyncResult"); + throw new ArgumentNullException(nameof(asyncResult)); Contract.EndContractBlock(); return BlockingEndRead(asyncResult); } - [HostProtection(ExternalThreading = true)] public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) { if (!CanWrite) __Error.WriteNotSupported(); @@ -956,7 +940,7 @@ namespace System.IO { public override void EndWrite(IAsyncResult asyncResult) { if (asyncResult == null) - throw new ArgumentNullException("asyncResult"); + throw new ArgumentNullException(nameof(asyncResult)); Contract.EndContractBlock(); BlockingEndWrite(asyncResult); @@ -1102,7 +1086,7 @@ namespace System.IO { internal SyncStream(Stream stream) { if (stream == null) - throw new ArgumentNullException("stream"); + throw new ArgumentNullException(nameof(stream)); Contract.EndContractBlock(); _stream = stream; } @@ -1217,7 +1201,6 @@ namespace System.IO { return _stream.ReadByte(); } - [HostProtection(ExternalThreading=true)] public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) { bool overridesBeginRead = _stream.HasOverriddenBeginEndRead(); @@ -1239,7 +1222,7 @@ namespace System.IO { public override int EndRead(IAsyncResult asyncResult) { if (asyncResult == null) - throw new ArgumentNullException("asyncResult"); + throw new ArgumentNullException(nameof(asyncResult)); Contract.Ensures(Contract.Result() >= 0); Contract.EndContractBlock(); @@ -1271,7 +1254,6 @@ namespace System.IO { _stream.WriteByte(b); } - [HostProtection(ExternalThreading=true)] public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) { bool overridesBeginWrite = _stream.HasOverriddenBeginEndWrite(); @@ -1293,7 +1275,7 @@ namespace System.IO { public override void EndWrite(IAsyncResult asyncResult) { if (asyncResult == null) - throw new ArgumentNullException("asyncResult"); + throw new ArgumentNullException(nameof(asyncResult)); Contract.EndContractBlock(); lock(_stream) diff --git a/src/mscorlib/src/System/IO/StreamHelpers.CopyValidation.cs b/src/mscorlib/src/System/IO/StreamHelpers.CopyValidation.cs new file mode 100644 index 0000000..8ff0e04 --- /dev/null +++ b/src/mscorlib/src/System/IO/StreamHelpers.CopyValidation.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.IO +{ + /// Provides methods to help in the implementation of Stream-derived types. + internal static partial class StreamHelpers + { + /// Validate the arguments to CopyTo, as would Stream.CopyTo. + public static void ValidateCopyToArgs(Stream source, Stream destination, int bufferSize) + { + if (destination == null) + { + throw new ArgumentNullException(nameof(destination)); + } + + if (bufferSize <= 0) + { + throw new ArgumentOutOfRangeException(nameof(bufferSize), bufferSize, Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); + } + + bool sourceCanRead = source.CanRead; + if (!sourceCanRead && !source.CanWrite) + { + throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_StreamClosed")); + } + + bool destinationCanWrite = destination.CanWrite; + if (!destinationCanWrite && !destination.CanRead) + { + throw new ObjectDisposedException(nameof(destination), Environment.GetResourceString("ObjectDisposed_StreamClosed")); + } + + if (!sourceCanRead) + { + throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnreadableStream")); + } + + if (!destinationCanWrite) + { + throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnwritableStream")); + } + } + } +} diff --git a/src/mscorlib/src/System/IO/StreamReader.cs b/src/mscorlib/src/System/IO/StreamReader.cs index 549733b..708db08 100644 --- a/src/mscorlib/src/System/IO/StreamReader.cs +++ b/src/mscorlib/src/System/IO/StreamReader.cs @@ -2,22 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -/*============================================================ -** -** -** -** -** -** Purpose: For reading text from streams in a particular -** encoding. -** -** -===========================================================*/ - -using System; using System.Text; using System.Runtime.InteropServices; using System.Runtime.Versioning; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; using System.Security.Permissions; @@ -161,11 +149,11 @@ namespace System.IO public StreamReader(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool leaveOpen) { if (stream == null || encoding == null) - throw new ArgumentNullException((stream == null ? "stream" : "encoding")); + throw new ArgumentNullException((stream == null ? nameof(stream) : nameof(encoding))); if (!stream.CanRead) throw new ArgumentException(Environment.GetResourceString("Argument_StreamNotReadable")); if (bufferSize <= 0) - throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); + throw new ArgumentOutOfRangeException(nameof(bufferSize), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); Contract.EndContractBlock(); Init(stream, encoding, detectEncodingFromByteOrderMarks, bufferSize, leaveOpen); @@ -187,26 +175,20 @@ namespace System.IO : this(path, encoding, detectEncodingFromByteOrderMarks, DefaultBufferSize) { } - [System.Security.SecuritySafeCritical] public StreamReader(String path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize) - : this(path, encoding, detectEncodingFromByteOrderMarks, bufferSize, true) { - } - - [System.Security.SecurityCritical] - internal StreamReader(String path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool checkHost) { // Don't open a Stream before checking for invalid arguments, // or we'll create a FileStream on disk and we won't close it until // the finalizer runs, causing problems for applications. if (path==null || encoding==null) - throw new ArgumentNullException((path==null ? "path" : "encoding")); + throw new ArgumentNullException((path==null ? nameof(path) : nameof(encoding))); if (path.Length==0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); if (bufferSize <= 0) - throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); + throw new ArgumentOutOfRangeException(nameof(bufferSize), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); Contract.EndContractBlock(); - Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize, FileOptions.SequentialScan, Path.GetFileName(path), false, false, checkHost); + Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize, FileOptions.SequentialScan, Path.GetFileName(path), false, false); Init(stream, encoding, detectEncodingFromByteOrderMarks, bufferSize, false); } @@ -358,9 +340,9 @@ namespace System.IO public override int Read([In, Out] char[] buffer, int index, int count) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -416,9 +398,9 @@ namespace System.IO public override int ReadBlock([In, Out] char[] buffer, int index, int count) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -434,7 +416,7 @@ namespace System.IO // Trims n bytes from the front of the buffer. private void CompressBuffer(int n) { - Contract.Assert(byteLen >= n, "CompressBuffer was called with a number of bytes greater than the current buffer length. Are two threads using this StreamReader at the same time?"); + Debug.Assert(byteLen >= n, "CompressBuffer was called with a number of bytes greater than the current buffer length. Are two threads using this StreamReader at the same time?"); Buffer.InternalBlockCopy(byteBuffer, n, byteBuffer, 0, byteLen - n); byteLen -= n; } @@ -502,7 +484,7 @@ namespace System.IO if (!_checkPreamble) return _checkPreamble; - Contract.Assert(bytePos <= _preamble.Length, "_compressPreamble was called with the current bytePos greater than the preamble buffer length. Are two threads using this StreamReader at the same time?"); + Debug.Assert(bytePos <= _preamble.Length, "_compressPreamble was called with the current bytePos greater than the preamble buffer length. Are two threads using this StreamReader at the same time?"); int len = (byteLen >= (_preamble.Length))? (_preamble.Length - bytePos) : (byteLen - bytePos); for(int i=0; i= 0, "Stream.Read returned a negative number! This is a bug in your stream class."); + Debug.Assert(len >= 0, "Stream.Read returned a negative number! This is a bug in your stream class."); if (len == 0) { // EOF but we might have buffered bytes from previous @@ -588,9 +570,9 @@ namespace System.IO byteLen += len; } else { - Contract.Assert(bytePos == 0, "bytePos can be non zero only when we are trying to _checkPreamble. Are two threads using this StreamReader at the same time?"); + Debug.Assert(bytePos == 0, "bytePos can be non zero only when we are trying to _checkPreamble. Are two threads using this StreamReader at the same time?"); byteLen = stream.Read(byteBuffer, 0, byteBuffer.Length); - Contract.Assert(byteLen >= 0, "Stream.Read returned a negative number! This is a bug in your stream class."); + Debug.Assert(byteLen >= 0, "Stream.Read returned a negative number! This is a bug in your stream class."); if (byteLen == 0) // We're at EOF return charLen; @@ -650,12 +632,12 @@ namespace System.IO readToUserBuffer = desiredChars >= _maxCharsPerBuffer; do { - Contract.Assert(charsRead == 0); + Debug.Assert(charsRead == 0); if (_checkPreamble) { - Contract.Assert(bytePos <= _preamble.Length, "possible bug in _compressPreamble. Are two threads using this StreamReader at the same time?"); + Debug.Assert(bytePos <= _preamble.Length, "possible bug in _compressPreamble. Are two threads using this StreamReader at the same time?"); int len = stream.Read(byteBuffer, bytePos, byteBuffer.Length - bytePos); - Contract.Assert(len >= 0, "Stream.Read returned a negative number! This is a bug in your stream class."); + Debug.Assert(len >= 0, "Stream.Read returned a negative number! This is a bug in your stream class."); if (len == 0) { // EOF but we might have buffered bytes from previous @@ -677,11 +659,11 @@ namespace System.IO byteLen += len; } else { - Contract.Assert(bytePos == 0, "bytePos can be non zero only when we are trying to _checkPreamble. Are two threads using this StreamReader at the same time?"); + Debug.Assert(bytePos == 0, "bytePos can be non zero only when we are trying to _checkPreamble. Are two threads using this StreamReader at the same time?"); byteLen = stream.Read(byteBuffer, 0, byteBuffer.Length); - Contract.Assert(byteLen >= 0, "Stream.Read returned a negative number! This is a bug in your stream class."); + Debug.Assert(byteLen >= 0, "Stream.Read returned a negative number! This is a bug in your stream class."); if (byteLen == 0) // EOF break; @@ -775,7 +757,6 @@ namespace System.IO } #region Task based Async APIs - [HostProtection(ExternalThreading=true)] [ComVisible(false)] public override Task ReadLineAsync() { @@ -856,7 +837,6 @@ namespace System.IO return GetStringAndReleaseSharedStringBuilder(sb); } - [HostProtection(ExternalThreading=true)] [ComVisible(false)] public override Task ReadToEndAsync() { @@ -893,14 +873,13 @@ namespace System.IO return GetStringAndReleaseSharedStringBuilder(sb); } - [HostProtection(ExternalThreading=true)] [ComVisible(false)] public override Task ReadAsync(char[] buffer, int index, int count) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -957,14 +936,14 @@ namespace System.IO // We break out of the loop if the stream is blocked (EOF is reached). do { - Contract.Assert(n == 0); + Debug.Assert(n == 0); if (CheckPreamble_Prop) { - Contract.Assert(BytePos_Prop <= Preamble_Prop.Length, "possible bug in _compressPreamble. Are two threads using this StreamReader at the same time?"); + Debug.Assert(BytePos_Prop <= Preamble_Prop.Length, "possible bug in _compressPreamble. Are two threads using this StreamReader at the same time?"); int tmpBytePos = BytePos_Prop; int len = await tmpStream.ReadAsync(tmpByteBuffer, tmpBytePos, tmpByteBuffer.Length - tmpBytePos).ConfigureAwait(false); - Contract.Assert(len >= 0, "Stream.Read returned a negative number! This is a bug in your stream class."); + Debug.Assert(len >= 0, "Stream.Read returned a negative number! This is a bug in your stream class."); if (len == 0) { @@ -985,7 +964,7 @@ namespace System.IO } // How can part of the preamble yield any chars? - Contract.Assert(n == 0); + Debug.Assert(n == 0); IsBlocked_Prop = true; break; @@ -997,11 +976,11 @@ namespace System.IO } else { - Contract.Assert(BytePos_Prop == 0, "_bytePos can be non zero only when we are trying to _checkPreamble. Are two threads using this StreamReader at the same time?"); + Debug.Assert(BytePos_Prop == 0, "_bytePos can be non zero only when we are trying to _checkPreamble. Are two threads using this StreamReader at the same time?"); ByteLen_Prop = await tmpStream.ReadAsync(tmpByteBuffer, 0, tmpByteBuffer.Length).ConfigureAwait(false); - Contract.Assert(ByteLen_Prop >= 0, "Stream.Read returned a negative number! This is a bug in your stream class."); + Debug.Assert(ByteLen_Prop >= 0, "Stream.Read returned a negative number! This is a bug in your stream class."); if (ByteLen_Prop == 0) // EOF { @@ -1031,7 +1010,7 @@ namespace System.IO readToUserBuffer = count >= MaxCharsPerBuffer_Prop; } - Contract.Assert(n == 0); + Debug.Assert(n == 0); CharPos_Prop = 0; if (readToUserBuffer) @@ -1039,7 +1018,7 @@ namespace System.IO n += Decoder_Prop.GetChars(tmpByteBuffer, 0, ByteLen_Prop, buffer, index + charsRead); // Why did the bytes yield no chars? - Contract.Assert(n > 0); + Debug.Assert(n > 0); CharLen_Prop = 0; // StreamReader's buffer is empty. } @@ -1048,7 +1027,7 @@ namespace System.IO n = Decoder_Prop.GetChars(tmpByteBuffer, 0, ByteLen_Prop, CharBuffer_Prop, 0); // Why did the bytes yield no chars? - Contract.Assert(n > 0); + Debug.Assert(n > 0); CharLen_Prop += n; // Number of chars in StreamReader's buffer. } @@ -1081,14 +1060,13 @@ namespace System.IO return charsRead; } - [HostProtection(ExternalThreading=true)] [ComVisible(false)] public override Task ReadBlockAsync(char[] buffer, int index, int count) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -1185,10 +1163,10 @@ namespace System.IO ByteLen_Prop = 0; do { if (CheckPreamble_Prop) { - Contract.Assert(BytePos_Prop <= Preamble_Prop.Length, "possible bug in _compressPreamble. Are two threads using this StreamReader at the same time?"); + Debug.Assert(BytePos_Prop <= Preamble_Prop.Length, "possible bug in _compressPreamble. Are two threads using this StreamReader at the same time?"); int tmpBytePos = BytePos_Prop; int len = await tmpStream.ReadAsync(tmpByteBuffer, tmpBytePos, tmpByteBuffer.Length - tmpBytePos).ConfigureAwait(false); - Contract.Assert(len >= 0, "Stream.Read returned a negative number! This is a bug in your stream class."); + Debug.Assert(len >= 0, "Stream.Read returned a negative number! This is a bug in your stream class."); if (len == 0) { // EOF but we might have buffered bytes from previous @@ -1206,9 +1184,9 @@ namespace System.IO ByteLen_Prop += len; } else { - Contract.Assert(BytePos_Prop == 0, "_bytePos can be non zero only when we are trying to _checkPreamble. Are two threads using this StreamReader at the same time?"); + Debug.Assert(BytePos_Prop == 0, "_bytePos can be non zero only when we are trying to _checkPreamble. Are two threads using this StreamReader at the same time?"); ByteLen_Prop = await tmpStream.ReadAsync(tmpByteBuffer, 0, tmpByteBuffer.Length).ConfigureAwait(false); - Contract.Assert(ByteLen_Prop >= 0, "Stream.Read returned a negative number! Bug in stream class."); + Debug.Assert(ByteLen_Prop >= 0, "Stream.Read returned a negative number! Bug in stream class."); if (ByteLen_Prop == 0) // We're at EOF return CharLen_Prop; diff --git a/src/mscorlib/src/System/IO/StreamWriter.cs b/src/mscorlib/src/System/IO/StreamWriter.cs index 65613bb..22eba82 100644 --- a/src/mscorlib/src/System/IO/StreamWriter.cs +++ b/src/mscorlib/src/System/IO/StreamWriter.cs @@ -2,25 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -/*============================================================ -** -** -** -** -** -** Purpose: For writing text to streams in a particular -** encoding. -** -** -===========================================================*/ -using System; using System.Text; -using System.Threading; -using System.Globalization; using System.Runtime.CompilerServices; -using System.Runtime.Versioning; using System.Security.Permissions; using System.Runtime.Serialization; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Threading.Tasks; @@ -45,10 +31,8 @@ namespace System.IO private const int DefaultFileStreamBufferSize = 4096; private const int MinBufferSize = 128; - private const Int32 DontCopyOnWriteLineThreshold = 512; - // Bit bucket - Null has no backing store. Non closable. - public new static readonly StreamWriter Null = new StreamWriter(Stream.Null, new UTF8Encoding(false, true), MinBufferSize, true); + public new static readonly StreamWriter Null = new StreamWriter(Stream.Null, UTF8NoBOM, MinBufferSize, true); private Stream stream; private Encoding encoding; @@ -61,12 +45,6 @@ namespace System.IO private bool haveWrittenPreamble; private bool closable; -#if MDA_SUPPORTED - [NonSerialized] - // For StreamWriterBufferedDataLost MDA - private MdaHelper mdaHelper; -#endif - // We don't guarantee thread safety on StreamWriter, but we should at // least prevent users from trying to write anything while an Async // write from the same thread is in progress. @@ -93,20 +71,9 @@ namespace System.IO // Even Close() will hit the exception as it would try to flush the unwritten data. // Maybe we can add a DiscardBufferedData() method to get out of such situation (like // StreamReader though for different reason). Either way, the buffered data will be lost! - private static volatile Encoding _UTF8NoBOM; - internal static Encoding UTF8NoBOM { [FriendAccessAllowed] - get { - if (_UTF8NoBOM == null) { - // No need for double lock - we just want to avoid extra - // allocations in the common case. - UTF8Encoding noBOM = new UTF8Encoding(false, true); - Thread.MemoryBarrier(); - _UTF8NoBOM = noBOM; - } - return _UTF8NoBOM; - } + get { return EncodingCache.UTF8NoBOM; } } @@ -133,10 +100,10 @@ namespace System.IO : base(null) // Ask for CurrentCulture all the time { if (stream == null || encoding == null) - throw new ArgumentNullException((stream == null ? "stream" : "encoding")); + throw new ArgumentNullException((stream == null ? nameof(stream) : nameof(encoding))); if (!stream.CanWrite) throw new ArgumentException(Environment.GetResourceString("Argument_StreamNotWritable")); - if (bufferSize <= 0) throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); + if (bufferSize <= 0) throw new ArgumentOutOfRangeException(nameof(bufferSize), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); Contract.EndContractBlock(); Init(stream, encoding, bufferSize, leaveOpen); @@ -154,28 +121,23 @@ namespace System.IO : this(path, append, encoding, DefaultBufferSize) { } - [System.Security.SecuritySafeCritical] - public StreamWriter(String path, bool append, Encoding encoding, int bufferSize): this(path, append, encoding, bufferSize, true) { - } - - [System.Security.SecurityCritical] - internal StreamWriter(String path, bool append, Encoding encoding, int bufferSize, bool checkHost) + public StreamWriter(String path, bool append, Encoding encoding, int bufferSize) : base(null) - { // Ask for CurrentCulture all the time + { + // Ask for CurrentCulture all the time if (path == null) - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); if (encoding == null) - throw new ArgumentNullException("encoding"); + throw new ArgumentNullException(nameof(encoding)); if (path.Length == 0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); - if (bufferSize <= 0) throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); + if (bufferSize <= 0) throw new ArgumentOutOfRangeException(nameof(bufferSize), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); Contract.EndContractBlock(); - Stream stream = CreateFile(path, append, checkHost); + Stream stream = CreateFile(path, append); Init(stream, encoding, bufferSize, false); } - [System.Security.SecuritySafeCritical] private void Init(Stream streamArg, Encoding encodingArg, int bufferSize, bool shouldLeaveOpen) { this.stream = streamArg; @@ -190,21 +152,12 @@ namespace System.IO if (stream.CanSeek && stream.Position > 0) haveWrittenPreamble = true; closable = !shouldLeaveOpen; -#if MDA_SUPPORTED - if (Mda.StreamWriterBufferedDataLost.Enabled) { - String callstack = null; - if (Mda.StreamWriterBufferedDataLost.CaptureAllocatedCallStack) - callstack = Environment.GetStackTrace(null, false); - mdaHelper = new MdaHelper(this, callstack); - } -#endif } - [System.Security.SecurityCritical] - private static Stream CreateFile(String path, bool append, bool checkHost) { + private static Stream CreateFile(String path, bool append) { FileMode mode = append? FileMode.Append: FileMode.Create; FileStream f = new FileStream(path, mode, FileAccess.Write, FileShare.Read, - DefaultFileStreamBufferSize, FileOptions.SequentialScan, Path.GetFileName(path), false, false, checkHost); + DefaultFileStreamBufferSize, FileOptions.SequentialScan, Path.GetFileName(path), false, false); return f; } @@ -221,20 +174,11 @@ namespace System.IO // is generally the right thing to do. if (stream != null) { // Note: flush on the underlying stream can throw (ex., low disk space) -#if FEATURE_CORECLR if (disposing) -#else - if (disposing || (LeaveOpen && stream is __ConsoleStream)) -#endif { CheckAsyncTaskInProgress(); Flush(true, true); -#if MDA_SUPPORTED - // Disable buffered data loss mda - if (mdaHelper != null) - GC.SuppressFinalize(mdaHelper); -#endif } } } @@ -354,7 +298,7 @@ namespace System.IO if (charPos == charLen) Flush(false, false); int n = charLen - charPos; if (n > count) n = count; - Contract.Assert(n > 0, "StreamWriter::Write(char[]) isn't making progress! This is most likely a race condition in user code."); + Debug.Assert(n > 0, "StreamWriter::Write(char[]) isn't making progress! This is most likely a race condition in user code."); Buffer.InternalBlockCopy(buffer, index * sizeof(char), charBuffer, charPos * sizeof(char), n * sizeof(char)); charPos += n; index += n; @@ -365,11 +309,11 @@ namespace System.IO public override void Write(char[] buffer, int index, int count) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -380,7 +324,7 @@ namespace System.IO if (charPos == charLen) Flush(false, false); int n = charLen - charPos; if (n > count) n = count; - Contract.Assert(n > 0, "StreamWriter::Write(char[], int, int) isn't making progress! This is most likely a race condition in user code."); + Debug.Assert(n > 0, "StreamWriter::Write(char[], int, int) isn't making progress! This is most likely a race condition in user code."); Buffer.InternalBlockCopy(buffer, index * sizeof(char), charBuffer, charPos * sizeof(char), n * sizeof(char)); charPos += n; index += n; @@ -402,7 +346,7 @@ namespace System.IO if (charPos == charLen) Flush(false, false); int n = charLen - charPos; if (n > count) n = count; - Contract.Assert(n > 0, "StreamWriter::Write(String) isn't making progress! This is most likely a race condition in user code."); + Debug.Assert(n > 0, "StreamWriter::Write(String) isn't making progress! This is most likely a race condition in user code."); value.CopyTo(index, charBuffer, charPos, n); charPos += n; index += n; @@ -413,7 +357,6 @@ namespace System.IO } #region Task based Async APIs - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public override Task WriteAsync(char value) { @@ -444,7 +387,7 @@ namespace System.IO { if (charPos == charLen) { await _this.FlushAsyncInternal(false, false, charBuffer, charPos).ConfigureAwait(false); - Contract.Assert(_this.charPos == 0); + Debug.Assert(_this.charPos == 0); charPos = 0; } @@ -457,7 +400,7 @@ namespace System.IO { if (charPos == charLen) { await _this.FlushAsyncInternal(false, false, charBuffer, charPos).ConfigureAwait(false); - Contract.Assert(_this.charPos == 0); + Debug.Assert(_this.charPos == 0); charPos = 0; } @@ -468,14 +411,13 @@ namespace System.IO if (autoFlush) { await _this.FlushAsyncInternal(true, false, charBuffer, charPos).ConfigureAwait(false); - Contract.Assert(_this.charPos == 0); + Debug.Assert(_this.charPos == 0); charPos = 0; } _this.CharPos_Prop = charPos; } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public override Task WriteAsync(String value) { @@ -520,7 +462,7 @@ namespace System.IO { if (charPos == charLen) { await _this.FlushAsyncInternal(false, false, charBuffer, charPos).ConfigureAwait(false); - Contract.Assert(_this.charPos == 0); + Debug.Assert(_this.charPos == 0); charPos = 0; } @@ -528,7 +470,7 @@ namespace System.IO if (n > count) n = count; - Contract.Assert(n > 0, "StreamWriter::Write(String) isn't making progress! This is most likely a race condition in user code."); + Debug.Assert(n > 0, "StreamWriter::Write(String) isn't making progress! This is most likely a race condition in user code."); value.CopyTo(index, charBuffer, charPos, n); @@ -543,7 +485,7 @@ namespace System.IO { if (charPos == charLen) { await _this.FlushAsyncInternal(false, false, charBuffer, charPos).ConfigureAwait(false); - Contract.Assert(_this.charPos == 0); + Debug.Assert(_this.charPos == 0); charPos = 0; } @@ -554,23 +496,22 @@ namespace System.IO if (autoFlush) { await _this.FlushAsyncInternal(true, false, charBuffer, charPos).ConfigureAwait(false); - Contract.Assert(_this.charPos == 0); + Debug.Assert(_this.charPos == 0); charPos = 0; } _this.CharPos_Prop = charPos; } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public override Task WriteAsync(char[] buffer, int index, int count) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -609,14 +550,14 @@ namespace System.IO { if (charPos == charLen) { await _this.FlushAsyncInternal(false, false, charBuffer, charPos).ConfigureAwait(false); - Contract.Assert(_this.charPos == 0); + Debug.Assert(_this.charPos == 0); charPos = 0; } int n = charLen - charPos; if (n > count) n = count; - Contract.Assert(n > 0, "StreamWriter::Write(char[], int, int) isn't making progress! This is most likely a race condition in user code."); + Debug.Assert(n > 0, "StreamWriter::Write(char[], int, int) isn't making progress! This is most likely a race condition in user code."); Buffer.InternalBlockCopy(buffer, index * sizeof(char), charBuffer, charPos * sizeof(char), n * sizeof(char)); @@ -631,7 +572,7 @@ namespace System.IO { if (charPos == charLen) { await _this.FlushAsyncInternal(false, false, charBuffer, charPos).ConfigureAwait(false); - Contract.Assert(_this.charPos == 0); + Debug.Assert(_this.charPos == 0); charPos = 0; } @@ -642,14 +583,13 @@ namespace System.IO if (autoFlush) { await _this.FlushAsyncInternal(true, false, charBuffer, charPos).ConfigureAwait(false); - Contract.Assert(_this.charPos == 0); + Debug.Assert(_this.charPos == 0); charPos = 0; } _this.CharPos_Prop = charPos; } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public override Task WriteLineAsync() { @@ -672,7 +612,6 @@ namespace System.IO } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public override Task WriteLineAsync(char value) { @@ -695,7 +634,6 @@ namespace System.IO } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public override Task WriteLineAsync(String value) { @@ -718,16 +656,15 @@ namespace System.IO } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public override Task WriteLineAsync(char[] buffer, int index, int count) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -751,7 +688,6 @@ namespace System.IO } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public override Task FlushAsync() { @@ -825,42 +761,5 @@ namespace System.IO await stream.FlushAsync().ConfigureAwait(false); } #endregion - -#if MDA_SUPPORTED - // StreamWriterBufferedDataLost MDA - // Instead of adding a finalizer to StreamWriter for detecting buffered data loss - // (ie, when the user forgets to call Close/Flush on the StreamWriter), we will - // have a separate object with normal finalization semantics that maintains a - // back pointer to this StreamWriter and alerts about any data loss - private sealed class MdaHelper - { - private StreamWriter streamWriter; - private String allocatedCallstack; // captures the callstack when this streamwriter was allocated - - internal MdaHelper(StreamWriter sw, String cs) - { - streamWriter = sw; - allocatedCallstack = cs; - } - - // Finalizer - ~MdaHelper() - { - // Make sure people closed this StreamWriter, exclude StreamWriter::Null. - if (streamWriter.charPos != 0 && streamWriter.stream != null && streamWriter.stream != Stream.Null) { - String fileName = (streamWriter.stream is FileStream) ? ((FileStream)streamWriter.stream).NameInternal : ""; - String callStack = allocatedCallstack; - - if (callStack == null) - callStack = Environment.GetResourceString("IO_StreamWriterBufferedDataLostCaptureAllocatedFromCallstackNotEnabled"); - - String message = Environment.GetResourceString("IO_StreamWriterBufferedDataLost", streamWriter.stream.GetType().FullName, fileName, callStack); - - Mda.StreamWriterBufferedDataLost.ReportError(message); - } - } - } // class MdaHelper -#endif // MDA_SUPPORTED - } // class StreamWriter } // namespace diff --git a/src/mscorlib/src/System/IO/StringReader.cs b/src/mscorlib/src/System/IO/StringReader.cs deleted file mode 100644 index e5fa811..0000000 --- a/src/mscorlib/src/System/IO/StringReader.cs +++ /dev/null @@ -1,187 +0,0 @@ -// 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. - -/*============================================================ -** -** -** -** -** Purpose: For reading text from strings -** -** -===========================================================*/ - -using System; -using System.Runtime.InteropServices; -using System.Diagnostics.Contracts; -using System.Security.Permissions; -using System.Threading.Tasks; - -namespace System.IO { - // This class implements a text reader that reads from a string. - // - [Serializable] - [ComVisible(true)] - public class StringReader : TextReader - { - private String _s; - private int _pos; - private int _length; - - public StringReader(String s) { - if (s == null) - throw new ArgumentNullException("s"); - Contract.EndContractBlock(); - _s = s; - _length = s == null? 0: s.Length; - } - - // Closes this StringReader. Following a call to this method, the String - // Reader will throw an ObjectDisposedException. - public override void Close() { - Dispose(true); - } - - protected override void Dispose(bool disposing) { - _s = null; - _pos = 0; - _length = 0; - base.Dispose(disposing); - } - - // Returns the next available character without actually reading it from - // the underlying string. The current position of the StringReader is not - // changed by this operation. The returned value is -1 if no further - // characters are available. - // - [Pure] - public override int Peek() { - if (_s == null) - __Error.ReaderClosed(); - if (_pos == _length) return -1; - return _s[_pos]; - } - - // Reads the next character from the underlying string. The returned value - // is -1 if no further characters are available. - // - public override int Read() { - if (_s == null) - __Error.ReaderClosed(); - if (_pos == _length) return -1; - return _s[_pos++]; - } - - // Reads a block of characters. This method will read up to count - // characters from this StringReader into the buffer character - // array starting at position index. Returns the actual number of - // characters read, or zero if the end of the string is reached. - // - public override int Read([In, Out] char[] buffer, int index, int count) { - if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); - if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (buffer.Length - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - if (_s == null) - __Error.ReaderClosed(); - - int n = _length - _pos; - if (n > 0) { - if (n > count) n = count; - _s.CopyTo(_pos, buffer, index, n); - _pos += n; - } - return n; - } - - public override String ReadToEnd() - { - if (_s == null) - __Error.ReaderClosed(); - String s; - if (_pos==0) - s = _s; - else - s = _s.Substring(_pos, _length - _pos); - _pos = _length; - return s; - } - - // Reads a line. A line is defined as a sequence of characters followed by - // a carriage return ('\r'), a line feed ('\n'), or a carriage return - // immediately followed by a line feed. The resulting string does not - // contain the terminating carriage return and/or line feed. The returned - // value is null if the end of the underlying string has been reached. - // - public override String ReadLine() { - if (_s == null) - __Error.ReaderClosed(); - int i = _pos; - while (i < _length) { - char ch = _s[i]; - if (ch == '\r' || ch == '\n') { - String result = _s.Substring(_pos, i - _pos); - _pos = i + 1; - if (ch == '\r' && _pos < _length && _s[_pos] == '\n') _pos++; - return result; - } - i++; - } - if (i > _pos) { - String result = _s.Substring(_pos, i - _pos); - _pos = i; - return result; - } - return null; - } - - #region Task based Async APIs - [ComVisible(false)] - public override Task ReadLineAsync() - { - return Task.FromResult(ReadLine()); - } - - [ComVisible(false)] - public override Task ReadToEndAsync() - { - return Task.FromResult(ReadToEnd()); - } - - [ComVisible(false)] - public override Task ReadBlockAsync(char[] buffer, int index, int count) - { - if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (buffer.Length - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - - Contract.EndContractBlock(); - - return Task.FromResult(ReadBlock(buffer, index, count)); - } - - [ComVisible(false)] - public override Task ReadAsync(char[] buffer, int index, int count) - { - if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (buffer.Length - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - return Task.FromResult(Read(buffer, index, count)); - } - #endregion - } -} diff --git a/src/mscorlib/src/System/IO/StringWriter.cs b/src/mscorlib/src/System/IO/StringWriter.cs deleted file mode 100644 index 282a791..0000000 --- a/src/mscorlib/src/System/IO/StringWriter.cs +++ /dev/null @@ -1,196 +0,0 @@ -// 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. - -/*============================================================ -** -** -** -** -** Purpose: For writing text to a string -** -** -===========================================================*/ - -using System; -using System.Runtime; -using System.Text; -using System.Globalization; -using System.Diagnostics.Contracts; -using System.Runtime.InteropServices; -using System.Security.Permissions; -using System.Threading.Tasks; - -namespace System.IO { - // This class implements a text writer that writes to a string buffer and allows - // the resulting sequence of characters to be presented as a string. - // - [Serializable] - [ComVisible(true)] - public class StringWriter : TextWriter - { - private static volatile UnicodeEncoding m_encoding=null; - - private StringBuilder _sb; - private bool _isOpen; - - // Constructs a new StringWriter. A new StringBuilder is automatically - // created and associated with the new StringWriter. - public StringWriter() - : this(new StringBuilder(), CultureInfo.CurrentCulture) - { - } - - public StringWriter(IFormatProvider formatProvider) - : this(new StringBuilder(), formatProvider) { - } - - // Constructs a new StringWriter that writes to the given StringBuilder. - // - public StringWriter(StringBuilder sb) : this(sb, CultureInfo.CurrentCulture) { - } - - public StringWriter(StringBuilder sb, IFormatProvider formatProvider) : base(formatProvider) { - if (sb==null) - throw new ArgumentNullException("sb", Environment.GetResourceString("ArgumentNull_Buffer")); - Contract.EndContractBlock(); - _sb = sb; - _isOpen = true; - } - - public override void Close() - { - Dispose(true); - } - - protected override void Dispose(bool disposing) - { - // Do not destroy _sb, so that we can extract this after we are - // done writing (similar to MemoryStream's GetBuffer & ToArray methods) - _isOpen = false; - base.Dispose(disposing); - } - - - public override Encoding Encoding { - get { - if (m_encoding==null) { - m_encoding = new UnicodeEncoding(false, false); - } - return m_encoding; - } - } - - // Returns the underlying StringBuilder. This is either the StringBuilder - // that was passed to the constructor, or the StringBuilder that was - // automatically created. - // - public virtual StringBuilder GetStringBuilder() { - return _sb; - } - - // Writes a character to the underlying string buffer. - // - public override void Write(char value) { - if (!_isOpen) - __Error.WriterClosed(); - _sb.Append(value); - } - - // Writes a range of a character array to the underlying string buffer. - // This method will write count characters of data into this - // StringWriter from the buffer character array starting at position - // index. - // - public override void Write(char[] buffer, int index, int count) { - if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); - if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (buffer.Length - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - if (!_isOpen) - __Error.WriterClosed(); - - _sb.Append(buffer, index, count); - } - - // Writes a string to the underlying string buffer. If the given string is - // null, nothing is written. - // - public override void Write(String value) { - if (!_isOpen) - __Error.WriterClosed(); - if (value != null) _sb.Append(value); - } - - - #region Task based Async APIs - [HostProtection(ExternalThreading = true)] - [ComVisible(false)] - public override Task WriteAsync(char value) - { - Write(value); - return Task.CompletedTask; - } - - [HostProtection(ExternalThreading = true)] - [ComVisible(false)] - public override Task WriteAsync(String value) - { - Write(value); - return Task.CompletedTask; - } - - [HostProtection(ExternalThreading = true)] - [ComVisible(false)] - public override Task WriteAsync(char[] buffer, int index, int count) - { - Write(buffer, index, count); - return Task.CompletedTask; - } - - [HostProtection(ExternalThreading = true)] - [ComVisible(false)] - public override Task WriteLineAsync(char value) - { - WriteLine(value); - return Task.CompletedTask; - } - - [HostProtection(ExternalThreading = true)] - [ComVisible(false)] - public override Task WriteLineAsync(String value) - { - WriteLine(value); - return Task.CompletedTask; - } - - [HostProtection(ExternalThreading = true)] - [ComVisible(false)] - public override Task WriteLineAsync(char[] buffer, int index, int count) - { - WriteLine(buffer, index, count); - return Task.CompletedTask; - } - - [HostProtection(ExternalThreading = true)] - [ComVisible(false)] - public override Task FlushAsync() - { - return Task.CompletedTask; - } - #endregion - - // Returns a string containing the characters written to this TextWriter - // so far. - // - public override String ToString() { - return _sb.ToString(); - } - } -} diff --git a/src/mscorlib/src/System/IO/TextReader.cs b/src/mscorlib/src/System/IO/TextReader.cs index ede4827..6cbadfb 100644 --- a/src/mscorlib/src/System/IO/TextReader.cs +++ b/src/mscorlib/src/System/IO/TextReader.cs @@ -14,11 +14,9 @@ ** ===========================================================*/ -using System; using System.Text; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; -using System.Reflection; using System.Security.Permissions; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; @@ -35,11 +33,7 @@ namespace System.IO { // There are methods on the Stream class for reading bytes. [Serializable] [ComVisible(true)] -#if FEATURE_REMOTING public abstract class TextReader : MarshalByRefObject, IDisposable { -#else // FEATURE_REMOTING - public abstract class TextReader : IDisposable { -#endif // FEATURE_REMOTING public static readonly TextReader Null = new NullTextReader(); @@ -101,11 +95,11 @@ namespace System.IO { public virtual int Read([In, Out] char[] buffer, int index, int count) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.Ensures(Contract.Result() >= 0); @@ -176,7 +170,6 @@ namespace System.IO { } #region Task based Async APIs - [HostProtection(ExternalThreading=true)] [ComVisible(false)] public virtual Task ReadLineAsync() { @@ -187,7 +180,6 @@ namespace System.IO { this, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } - [HostProtection(ExternalThreading=true)] [ComVisible(false)] public async virtual Task ReadToEndAsync() { @@ -201,14 +193,13 @@ namespace System.IO { return sb.ToString(); } - [HostProtection(ExternalThreading=true)] [ComVisible(false)] public virtual Task ReadAsync(char[] buffer, int index, int count) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -232,14 +223,13 @@ namespace System.IO { tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } - [HostProtection(ExternalThreading=true)] [ComVisible(false)] public virtual Task ReadBlockAsync(char[] buffer, int index, int count) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); @@ -248,7 +238,6 @@ namespace System.IO { return ReadBlockAsyncInternal(buffer, index, count); } - [HostProtection(ExternalThreading=true)] private async Task ReadBlockAsyncInternal(char[] buffer, int index, int count) { Contract.Requires(buffer != null); @@ -267,11 +256,10 @@ namespace System.IO { } #endregion - [HostProtection(Synchronization=true)] public static TextReader Synchronized(TextReader reader) { if (reader==null) - throw new ArgumentNullException("reader"); + throw new ArgumentNullException(nameof(reader)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -383,9 +371,9 @@ namespace System.IO { public override Task ReadBlockAsync(char[] buffer, int index, int count) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); @@ -399,9 +387,9 @@ namespace System.IO { public override Task ReadAsync(char[] buffer, int index, int count) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/IO/TextWriter.cs b/src/mscorlib/src/System/IO/TextWriter.cs index 165001e..131f69d 100644 --- a/src/mscorlib/src/System/IO/TextWriter.cs +++ b/src/mscorlib/src/System/IO/TextWriter.cs @@ -2,24 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -/*============================================================ -** -** -** -** -** -** Purpose: Abstract base class for Text-only Writers. -** Subclasses will include StreamWriter & StringWriter. -** -** -===========================================================*/ - -using System; using System.Text; using System.Threading; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Reflection; using System.Security.Permissions; using System.Globalization; using System.Diagnostics.CodeAnalysis; @@ -35,11 +21,7 @@ namespace System.IO { // There are methods on the Stream class for writing bytes. [Serializable] [ComVisible(true)] -#if FEATURE_REMOTING public abstract class TextWriter : MarshalByRefObject, IDisposable { -#else // FEATURE_REMOTING - public abstract class TextWriter : IDisposable { -#endif // FEATURE_REMOTING public static readonly TextWriter Null = new NullTextWriter(); // This should be initialized to Environment.NewLine, but @@ -128,10 +110,9 @@ namespace System.IO { } - [HostProtection(Synchronization=true)] public static TextWriter Synchronized(TextWriter writer) { if (writer==null) - throw new ArgumentNullException("writer"); + throw new ArgumentNullException(nameof(writer)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -162,11 +143,11 @@ namespace System.IO { // public virtual void Write(char[] buffer, int index, int count) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -490,7 +471,6 @@ namespace System.IO { } #region Task based Async APIs - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public virtual Task WriteAsync(char value) { @@ -503,7 +483,6 @@ namespace System.IO { tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public virtual Task WriteAsync(String value) { @@ -516,7 +495,6 @@ namespace System.IO { tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public Task WriteAsync(char[] buffer) { @@ -524,7 +502,6 @@ namespace System.IO { return WriteAsync(buffer, 0, buffer.Length); } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public virtual Task WriteAsync(char[] buffer, int index, int count) { @@ -537,7 +514,6 @@ namespace System.IO { tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public virtual Task WriteLineAsync(char value) { @@ -550,7 +526,6 @@ namespace System.IO { tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public virtual Task WriteLineAsync(String value) { @@ -563,7 +538,6 @@ namespace System.IO { tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public Task WriteLineAsync(char[] buffer) { @@ -571,7 +545,6 @@ namespace System.IO { return WriteLineAsync(buffer, 0, buffer.Length); } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public virtual Task WriteLineAsync(char[] buffer, int index, int count) { @@ -584,14 +557,12 @@ namespace System.IO { tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public virtual Task WriteLineAsync() { return WriteAsync(CoreNewLine); } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public virtual Task FlushAsync() { diff --git a/src/mscorlib/src/System/IO/UnmanagedMemoryAccessor.cs b/src/mscorlib/src/System/IO/UnmanagedMemoryAccessor.cs index ea70057..4208ebf 100644 --- a/src/mscorlib/src/System/IO/UnmanagedMemoryAccessor.cs +++ b/src/mscorlib/src/System/IO/UnmanagedMemoryAccessor.cs @@ -19,6 +19,7 @@ using System.Runtime.ConstrainedExecution; using System.Runtime.Versioning; using System.Security.Permissions; using Microsoft.Win32.SafeHandles; +using System.Diagnostics; using System.Diagnostics.Contracts; namespace System.IO { @@ -28,7 +29,6 @@ namespace System.IO { /// this gives better throughput; benchmarks showed about 12-15% better. public class UnmanagedMemoryAccessor : IDisposable { - [System.Security.SecurityCritical] // auto-generated private SafeBuffer _buffer; private Int64 _offset; [ContractPublicPropertyName("Capacity")] @@ -46,35 +46,29 @@ namespace System.IO { // // // - [System.Security.SecuritySafeCritical] public UnmanagedMemoryAccessor(SafeBuffer buffer, Int64 offset, Int64 capacity) { Initialize(buffer, offset, capacity, FileAccess.Read); } - [System.Security.SecuritySafeCritical] // auto-generated public UnmanagedMemoryAccessor(SafeBuffer buffer, Int64 offset, Int64 capacity, FileAccess access) { Initialize(buffer, offset, capacity, access); } - [System.Security.SecuritySafeCritical] // auto-generated -#pragma warning disable 618 - [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] -#pragma warning restore 618 protected void Initialize(SafeBuffer buffer, Int64 offset, Int64 capacity, FileAccess access) { if (buffer == null) { - throw new ArgumentNullException("buffer"); + throw new ArgumentNullException(nameof(buffer)); } if (offset < 0) { - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(offset), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (capacity < 0) { - throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(capacity), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (buffer.ByteLength < (UInt64)(offset + capacity)) { throw new ArgumentException(Environment.GetResourceString("Argument_OffsetAndCapacityOutOfBounds")); } if (access < FileAccess.Read || access > FileAccess.ReadWrite) { - throw new ArgumentOutOfRangeException("access"); + throw new ArgumentOutOfRangeException(nameof(access)); } Contract.EndContractBlock(); @@ -155,7 +149,6 @@ namespace System.IO { return InternalReadByte(position); } - [System.Security.SecuritySafeCritical] // auto-generated public char ReadChar(Int64 position) { int sizeOfType = sizeof(char); EnsureSafeToRead(position, sizeOfType); @@ -192,7 +185,6 @@ namespace System.IO { } // See comment above. - [System.Security.SecuritySafeCritical] public Int16 ReadInt16(Int64 position) { int sizeOfType = sizeof(Int16); EnsureSafeToRead(position, sizeOfType); @@ -229,7 +221,6 @@ namespace System.IO { } - [System.Security.SecuritySafeCritical] // auto-generated public Int32 ReadInt32(Int64 position) { int sizeOfType = sizeof(Int32); EnsureSafeToRead(position, sizeOfType); @@ -264,7 +255,6 @@ namespace System.IO { return result; } - [System.Security.SecuritySafeCritical] // auto-generated public Int64 ReadInt64(Int64 position) { int sizeOfType = sizeof(Int64); EnsureSafeToRead(position, sizeOfType); @@ -301,18 +291,63 @@ namespace System.IO { return result; } - [System.Security.SecuritySafeCritical] // auto-generated + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private unsafe Int32 UnsafeReadInt32(byte* pointer) + { + Int32 result; + // check if pointer is aligned + if (((int)pointer & (sizeof(Int32) - 1)) == 0) + { + result = *((Int32*)pointer); + } + else + { + result = (Int32)(*(pointer) | *(pointer + 1) << 8 | *(pointer + 2) << 16 | *(pointer + 3) << 24); + } + + return result; + } public Decimal ReadDecimal(Int64 position) { + const int ScaleMask = 0x00FF0000; + const int SignMask = unchecked((int)0x80000000); + int sizeOfType = sizeof(Decimal); EnsureSafeToRead(position, sizeOfType); - int[] decimalArray = new int[4]; - ReadArray(position, decimalArray, 0, decimalArray.Length); + unsafe + { + byte* pointer = null; + try + { + _buffer.AcquirePointer(ref pointer); + pointer += (_offset + position); - return new Decimal(decimalArray); + int lo = UnsafeReadInt32(pointer); + int mid = UnsafeReadInt32(pointer + 4); + int hi = UnsafeReadInt32(pointer + 8); + int flags = UnsafeReadInt32(pointer + 12); + + // Check for invalid Decimal values + if (!((flags & ~(SignMask | ScaleMask)) == 0 && (flags & ScaleMask) <= (28 << 16))) + { + throw new ArgumentException(Environment.GetResourceString("Arg_BadDecimal")); // Throw same Exception type as Decimal(int[]) ctor for compat + } + + bool isNegative = (flags & SignMask) != 0; + byte scale = (byte)(flags >> 16); + + return new decimal(lo, mid, hi, isNegative, scale); + } + finally + { + if (pointer != null) + { + _buffer.ReleasePointer(); + } + } + } } - [System.Security.SecuritySafeCritical] // auto-generated public Single ReadSingle(Int64 position) { int sizeOfType = sizeof(Single); EnsureSafeToRead(position, sizeOfType); @@ -329,7 +364,7 @@ namespace System.IO { // check if pointer is aligned if (((int)pointer & (sizeOfType - 1)) == 0) { #endif - result = *((Single*)(pointer)); + result = BitConverter.Int32BitsToSingle(*((int*)(pointer))); #if ALIGN_ACCESS } else { @@ -348,7 +383,6 @@ namespace System.IO { return result; } - [System.Security.SecuritySafeCritical] // auto-generated public Double ReadDouble(Int64 position) { int sizeOfType = sizeof(Double); EnsureSafeToRead(position, sizeOfType); @@ -365,7 +399,7 @@ namespace System.IO { // check if pointer is aligned if (((int)pointer & (sizeOfType - 1)) == 0) { #endif - result = *((Double*)(pointer)); + result = BitConverter.Int64BitsToDouble(*((long*)(pointer))); #if ALIGN_ACCESS } else { @@ -388,7 +422,6 @@ namespace System.IO { return result; } - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] public SByte ReadSByte(Int64 position) { int sizeOfType = sizeof(SByte); @@ -413,7 +446,6 @@ namespace System.IO { return result; } - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] public UInt16 ReadUInt16(Int64 position) { int sizeOfType = sizeof(UInt16); @@ -450,7 +482,6 @@ namespace System.IO { return result; } - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] public UInt32 ReadUInt32(Int64 position) { int sizeOfType = sizeof(UInt32); @@ -487,7 +518,6 @@ namespace System.IO { return result; } - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] public UInt64 ReadUInt64(Int64 position) { int sizeOfType = sizeof(UInt64); @@ -540,10 +570,9 @@ namespace System.IO { // such, it is best to use the ReadXXX methods for small standard types such as ints, longs, // bools, etc. - [System.Security.SecurityCritical] // auto-generated_required public void Read(Int64 position, out T structure) where T : struct { if (position < 0) { - throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(position), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.EndContractBlock(); @@ -557,10 +586,10 @@ namespace System.IO { UInt32 sizeOfT = Marshal.SizeOfType(typeof(T)); if (position > _capacity - sizeOfT) { if (position >= _capacity) { - throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired")); + throw new ArgumentOutOfRangeException(nameof(position), Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired")); } else { - throw new ArgumentException(Environment.GetResourceString("Argument_NotEnoughBytesToRead", typeof(T).FullName), "position"); + throw new ArgumentException(Environment.GetResourceString("Argument_NotEnoughBytesToRead", typeof(T).FullName), nameof(position)); } } @@ -573,16 +602,15 @@ namespace System.IO { // struct that contains reference members will most likely cause the runtime to AV. This // is consistent with Marshal.PtrToStructure. - [System.Security.SecurityCritical] // auto-generated_required public int ReadArray(Int64 position, T[] array, Int32 offset, Int32 count) where T : struct { if (array == null) { - throw new ArgumentNullException("array", "Buffer cannot be null."); + throw new ArgumentNullException(nameof(array), "Buffer cannot be null."); } if (offset < 0) { - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(offset), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (count < 0) { - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (array.Length - offset < count) { throw new ArgumentException(Environment.GetResourceString("Argument_OffsetAndLengthOutOfBounds")); @@ -597,14 +625,14 @@ namespace System.IO { } } if (position < 0) { - throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(position), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } UInt32 sizeOfT = Marshal.AlignedSizeOf(); // only check position and ask for fewer Ts if count is too big if (position >= _capacity) { - throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired")); + throw new ArgumentOutOfRangeException(nameof(position), Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired")); } int n = count; @@ -647,7 +675,6 @@ namespace System.IO { InternalWrite(position, value); } - [System.Security.SecuritySafeCritical] // auto-generated public void Write(Int64 position, char value) { int sizeOfType = sizeof(char); EnsureSafeToWrite(position, sizeOfType); @@ -682,7 +709,6 @@ namespace System.IO { } - [System.Security.SecuritySafeCritical] // auto-generated public void Write(Int64 position, Int16 value) { int sizeOfType = sizeof(Int16); EnsureSafeToWrite(position, sizeOfType); @@ -716,7 +742,6 @@ namespace System.IO { } - [System.Security.SecuritySafeCritical] // auto-generated public void Write(Int64 position, Int32 value) { int sizeOfType = sizeof(Int32); EnsureSafeToWrite(position, sizeOfType); @@ -751,7 +776,6 @@ namespace System.IO { } } - [System.Security.SecuritySafeCritical] // auto-generated public void Write(Int64 position, Int64 value) { int sizeOfType = sizeof(Int64); EnsureSafeToWrite(position, sizeOfType); @@ -789,28 +813,56 @@ namespace System.IO { } } - [System.Security.SecuritySafeCritical] // auto-generated + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private unsafe void UnsafeWriteInt32(byte* pointer, Int32 value) + { + // check if pointer is aligned + if (((int)pointer & (sizeof(Int32) - 1)) == 0) + { + *((Int32*)pointer) = value; + } + else + { + *(pointer) = (byte)value; + *(pointer + 1) = (byte)(value >> 8); + *(pointer + 2) = (byte)(value >> 16); + *(pointer + 3) = (byte)(value >> 24); + } + } + public void Write(Int64 position, Decimal value) { int sizeOfType = sizeof(Decimal); EnsureSafeToWrite(position, sizeOfType); - byte[] decimalArray = new byte[16]; - Decimal.GetBytes(value, decimalArray); + unsafe + { + byte* pointer = null; + try + { + _buffer.AcquirePointer(ref pointer); + pointer += (_offset + position); - int[] bits = new int[4]; - int flags = ((int)decimalArray[12]) | ((int)decimalArray[13] << 8) | ((int)decimalArray[14] << 16) | ((int)decimalArray[15] << 24); - int lo = ((int)decimalArray[0]) | ((int)decimalArray[1] << 8) | ((int)decimalArray[2] << 16) | ((int)decimalArray[3] << 24); - int mid = ((int)decimalArray[4]) | ((int)decimalArray[5] << 8) | ((int)decimalArray[6] << 16) | ((int)decimalArray[7] << 24); - int hi = ((int)decimalArray[8]) | ((int)decimalArray[9] << 8) | ((int)decimalArray[10] << 16) | ((int)decimalArray[11] << 24); - bits[0] = lo; - bits[1] = mid; - bits[2] = hi; - bits[3] = flags; + int* valuePtr = (int*)(&value); + int flags = *valuePtr; + int hi = *(valuePtr + 1); + int lo = *(valuePtr + 2); + int mid = *(valuePtr + 3); - WriteArray(position, bits, 0, bits.Length); + UnsafeWriteInt32(pointer, lo); + UnsafeWriteInt32(pointer + 4, mid); + UnsafeWriteInt32(pointer + 8, hi); + UnsafeWriteInt32(pointer + 12, flags); + } + finally + { + if (pointer != null) + { + _buffer.ReleasePointer(); + } + } + } } - [System.Security.SecuritySafeCritical] // auto-generated public void Write(Int64 position, Single value) { int sizeOfType = sizeof(Single); EnsureSafeToWrite(position, sizeOfType); @@ -825,7 +877,7 @@ namespace System.IO { // check if pointer is aligned if (((int)pointer & (sizeOfType - 1)) == 0) { #endif - *((Single*)pointer) = value; + *((int*)pointer) = BitConverter.SingleToInt32Bits(value); #if ALIGN_ACCESS } else { @@ -846,7 +898,6 @@ namespace System.IO { } } - [System.Security.SecuritySafeCritical] // auto-generated public void Write(Int64 position, Double value) { int sizeOfType = sizeof(Double); EnsureSafeToWrite(position, sizeOfType); @@ -861,7 +912,7 @@ namespace System.IO { // check if pointer is aligned if (((int)pointer & (sizeOfType - 1)) == 0) { #endif - *((Double*)pointer) = value; + *((long*)pointer) = BitConverter.DoubleToInt64Bits(value); #if ALIGN_ACCESS } else { @@ -886,7 +937,6 @@ namespace System.IO { } } - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] public void Write(Int64 position, SByte value) { int sizeOfType = sizeof(SByte); @@ -908,7 +958,6 @@ namespace System.IO { } } - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] public void Write(Int64 position, UInt16 value) { int sizeOfType = sizeof(UInt16); @@ -942,7 +991,6 @@ namespace System.IO { } } - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] public void Write(Int64 position, UInt32 value) { int sizeOfType = sizeof(UInt32); @@ -979,7 +1027,6 @@ namespace System.IO { } } - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] public void Write(Int64 position, UInt64 value) { int sizeOfType = sizeof(UInt64); @@ -1024,10 +1071,9 @@ namespace System.IO { // though this is number is JIT and architecture dependent). As such, it is best to use // the WriteX methods for small standard types such as ints, longs, bools, etc. - [System.Security.SecurityCritical] // auto-generated_required public void Write(Int64 position, ref T structure) where T : struct { if (position < 0) { - throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(position), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.EndContractBlock(); @@ -1041,10 +1087,10 @@ namespace System.IO { UInt32 sizeOfT = Marshal.SizeOfType(typeof(T)); if (position > _capacity - sizeOfT) { if (position >= _capacity) { - throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired")); + throw new ArgumentOutOfRangeException(nameof(position), Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired")); } else { - throw new ArgumentException(Environment.GetResourceString("Argument_NotEnoughBytesToWrite", typeof(T).FullName), "position"); + throw new ArgumentException(Environment.GetResourceString("Argument_NotEnoughBytesToWrite", typeof(T).FullName), nameof(position)); } } @@ -1054,25 +1100,24 @@ namespace System.IO { // Writes 'count' structs of type T from 'array' (starting at 'offset') into unmanaged memory. - [System.Security.SecurityCritical] // auto-generated_required public void WriteArray(Int64 position, T[] array, Int32 offset, Int32 count) where T : struct { if (array == null) { - throw new ArgumentNullException("array", "Buffer cannot be null."); + throw new ArgumentNullException(nameof(array), "Buffer cannot be null."); } if (offset < 0) { - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(offset), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (count < 0) { - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (array.Length - offset < count) { throw new ArgumentException(Environment.GetResourceString("Argument_OffsetAndLengthOutOfBounds")); } if (position < 0) { - throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(position), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (position >= Capacity) { - throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired")); + throw new ArgumentOutOfRangeException(nameof(position), Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired")); } Contract.EndContractBlock(); @@ -1086,11 +1131,10 @@ namespace System.IO { _buffer.WriteArray((UInt64)(_offset + position), array, offset, count); } - [System.Security.SecuritySafeCritical] // auto-generated private byte InternalReadByte(Int64 position) { - Contract.Assert(CanRead, "UMA not readable"); - Contract.Assert(position >= 0, "position less than 0"); - Contract.Assert(position <= _capacity - sizeof(byte), "position is greater than capacity - sizeof(byte)"); + Debug.Assert(CanRead, "UMA not readable"); + Debug.Assert(position >= 0, "position less than 0"); + Debug.Assert(position <= _capacity - sizeof(byte), "position is greater than capacity - sizeof(byte)"); byte result; unsafe { @@ -1109,11 +1153,10 @@ namespace System.IO { return result; } - [System.Security.SecuritySafeCritical] // auto-generated private void InternalWrite(Int64 position, byte value) { - Contract.Assert(CanWrite, "UMA not writeable"); - Contract.Assert(position >= 0, "position less than 0"); - Contract.Assert(position <= _capacity - sizeof(byte), "position is greater than capacity - sizeof(byte)"); + Debug.Assert(CanWrite, "UMA not writable"); + Debug.Assert(position >= 0, "position less than 0"); + Debug.Assert(position <= _capacity - sizeof(byte), "position is greater than capacity - sizeof(byte)"); unsafe { byte* pointer = null; @@ -1138,15 +1181,15 @@ namespace System.IO { throw new NotSupportedException(Environment.GetResourceString("NotSupported_Reading")); } if (position < 0) { - throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(position), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.EndContractBlock(); if (position > _capacity - sizeOfType) { if (position >= _capacity) { - throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired")); + throw new ArgumentOutOfRangeException(nameof(position), Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired")); } else { - throw new ArgumentException(Environment.GetResourceString("Argument_NotEnoughBytesToRead"), "position"); + throw new ArgumentException(Environment.GetResourceString("Argument_NotEnoughBytesToRead"), nameof(position)); } } } @@ -1159,15 +1202,15 @@ namespace System.IO { throw new NotSupportedException(Environment.GetResourceString("NotSupported_Writing")); } if (position < 0) { - throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(position), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.EndContractBlock(); if (position > _capacity - sizeOfType) { if (position >= _capacity) { - throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired")); + throw new ArgumentOutOfRangeException(nameof(position), Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired")); } else { - throw new ArgumentException(Environment.GetResourceString("Argument_NotEnoughBytesToWrite", "Byte"), "position"); + throw new ArgumentException(Environment.GetResourceString("Argument_NotEnoughBytesToWrite", nameof(Byte)), nameof(position)); } } } diff --git a/src/mscorlib/src/System/IO/UnmanagedMemoryStream.cs b/src/mscorlib/src/System/IO/UnmanagedMemoryStream.cs index 6b506ea..d786326 100644 --- a/src/mscorlib/src/System/IO/UnmanagedMemoryStream.cs +++ b/src/mscorlib/src/System/IO/UnmanagedMemoryStream.cs @@ -19,6 +19,7 @@ using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Threading; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Threading.Tasks; @@ -43,7 +44,7 @@ namespace System.IO { * * It may become necessary to add in some sort of * DeallocationMode enum, specifying whether we unmap a section of memory, - * call free, run a user-provided delegate to free the memory, etc etc. + * call free, run a user-provided delegate to free the memory, etc. * We'll suggest user write a subclass of UnmanagedMemoryStream that uses * a SafeHandle subclass to hold onto the memory. * Check for problems when using this in the negative parts of a @@ -76,7 +77,7 @@ namespace System.IO { * a. a race condition in WriteX that could have allowed a thread to * read from unzeroed memory was fixed * b. memory region cannot be expanded beyond _capacity; in other - * words, a UMS creator is saying a writeable UMS is safe to + * words, a UMS creator is saying a writable UMS is safe to * write to anywhere in the memory range up to _capacity, specified * in the ctor. Even if the caller doesn't specify a capacity, then * length is used as the capacity. @@ -85,22 +86,19 @@ namespace System.IO { { private const long UnmanagedMemStreamMaxLength = Int64.MaxValue; - [System.Security.SecurityCritical] // auto-generated private SafeBuffer _buffer; - [SecurityCritical] private unsafe byte* _mem; private long _length; private long _capacity; private long _position; private long _offset; private FileAccess _access; - internal bool _isOpen; + internal bool _isOpen; [NonSerialized] private Task _lastReadTask; // The last successful task returned from ReadAsync // Needed for subclasses that need to map a file, etc. - [System.Security.SecuritySafeCritical] // auto-generated protected UnmanagedMemoryStream() { unsafe { @@ -109,12 +107,10 @@ namespace System.IO { _isOpen = false; } - [System.Security.SecuritySafeCritical] // auto-generated public UnmanagedMemoryStream(SafeBuffer buffer, long offset, long length) { Initialize(buffer, offset, length, FileAccess.Read, false); } - [System.Security.SecuritySafeCritical] // auto-generated public UnmanagedMemoryStream(SafeBuffer buffer, long offset, long length, FileAccess access) { Initialize(buffer, offset, length, access, false); } @@ -122,32 +118,29 @@ namespace System.IO { // We must create one of these without doing a security check. This // class is created while security is trying to start up. Plus, doing // a Demand from Assembly.GetManifestResourceStream isn't useful. - [System.Security.SecurityCritical] // auto-generated internal UnmanagedMemoryStream(SafeBuffer buffer, long offset, long length, FileAccess access, bool skipSecurityCheck) { Initialize(buffer, offset, length, access, skipSecurityCheck); } - [System.Security.SecuritySafeCritical] // auto-generated protected void Initialize(SafeBuffer buffer, long offset, long length, FileAccess access) { Initialize(buffer, offset, length, access, false); } - [System.Security.SecurityCritical] // auto-generated internal void Initialize(SafeBuffer buffer, long offset, long length, FileAccess access, bool skipSecurityCheck) { if (buffer == null) { - throw new ArgumentNullException("buffer"); + throw new ArgumentNullException(nameof(buffer)); } if (offset < 0) { - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(offset), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (length < 0) { - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (buffer.ByteLength < (ulong)(offset + length)) { throw new ArgumentException(Environment.GetResourceString("Argument_InvalidSafeBufferOffLen")); } if (access < FileAccess.Read || access > FileAccess.ReadWrite) { - throw new ArgumentOutOfRangeException("access"); + throw new ArgumentOutOfRangeException(nameof(access)); } Contract.EndContractBlock(); @@ -185,14 +178,12 @@ namespace System.IO { _isOpen = true; } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] public unsafe UnmanagedMemoryStream(byte* pointer, long length) { Initialize(pointer, length, length, FileAccess.Read, false); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] public unsafe UnmanagedMemoryStream(byte* pointer, long length, long capacity, FileAccess access) { @@ -202,41 +193,39 @@ namespace System.IO { // We must create one of these without doing a security check. This // class is created while security is trying to start up. Plus, doing // a Demand from Assembly.GetManifestResourceStream isn't useful. - [System.Security.SecurityCritical] // auto-generated internal unsafe UnmanagedMemoryStream(byte* pointer, long length, long capacity, FileAccess access, bool skipSecurityCheck) { Initialize(pointer, length, capacity, access, skipSecurityCheck); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] protected unsafe void Initialize(byte* pointer, long length, long capacity, FileAccess access) { Initialize(pointer, length, capacity, access, false); } - [System.Security.SecurityCritical] // auto-generated internal unsafe void Initialize(byte* pointer, long length, long capacity, FileAccess access, bool skipSecurityCheck) { if (pointer == null) - throw new ArgumentNullException("pointer"); + throw new ArgumentNullException(nameof(pointer)); if (length < 0 || capacity < 0) - throw new ArgumentOutOfRangeException((length < 0) ? "length" : "capacity", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException((length < 0) ? nameof(length) : nameof(capacity), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (length > capacity) - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_LengthGreaterThanCapacity")); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_LengthGreaterThanCapacity")); Contract.EndContractBlock(); // Check for wraparound. if (((byte*) ((long)pointer + capacity)) < pointer) - throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_UnmanagedMemStreamWrapAround")); + throw new ArgumentOutOfRangeException(nameof(capacity), Environment.GetResourceString("ArgumentOutOfRange_UnmanagedMemStreamWrapAround")); if (access < FileAccess.Read || access > FileAccess.ReadWrite) - throw new ArgumentOutOfRangeException("access", Environment.GetResourceString("ArgumentOutOfRange_Enum")); + throw new ArgumentOutOfRangeException(nameof(access), Environment.GetResourceString("ArgumentOutOfRange_Enum")); if (_isOpen) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CalledTwice")); - if (!skipSecurityCheck) + if (!skipSecurityCheck) { #pragma warning disable 618 new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); #pragma warning restore 618 + } _mem = pointer; _offset = 0; @@ -261,7 +250,6 @@ namespace System.IO { get { return _isOpen && (_access & FileAccess.Write) != 0; } } - [System.Security.SecuritySafeCritical] // auto-generated protected override void Dispose(bool disposing) { _isOpen = false; @@ -277,7 +265,6 @@ namespace System.IO { if (!_isOpen) __Error.StreamIsClosed(); } - [HostProtection(ExternalThreading=true)] [ComVisible(false)] public override Task FlushAsync(CancellationToken cancellationToken) { @@ -316,10 +303,9 @@ namespace System.IO { Contract.EndContractBlock(); return Interlocked.Read(ref _position); } - [System.Security.SecuritySafeCritical] // auto-generated set { if (value < 0) - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); if (!CanSeek) __Error.StreamIsClosed(); @@ -327,7 +313,7 @@ namespace System.IO { unsafe { // On 32 bit machines, ensure we don't wrap around. if (value > (long) Int32.MaxValue || _mem + value < _mem) - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_StreamLength")); + throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_StreamLength")); } #endif Interlocked.Exchange(ref _position, value); @@ -336,7 +322,6 @@ namespace System.IO { [CLSCompliant(false)] public unsafe byte* PositionPointer { - [System.Security.SecurityCritical] // auto-generated_required get { if (_buffer != null) { throw new NotSupportedException(Environment.GetResourceString("NotSupported_UmsSafeBuffer")); @@ -350,7 +335,6 @@ namespace System.IO { if (!_isOpen) __Error.StreamIsClosed(); return ptr; } - [System.Security.SecurityCritical] // auto-generated_required set { if (_buffer != null) throw new NotSupportedException(Environment.GetResourceString("NotSupported_UmsSafeBuffer")); @@ -368,7 +352,6 @@ namespace System.IO { } internal unsafe byte* Pointer { - [System.Security.SecurityCritical] // auto-generated get { if (_buffer != null) throw new NotSupportedException(Environment.GetResourceString("NotSupported_UmsSafeBuffer")); @@ -377,14 +360,13 @@ namespace System.IO { } } - [System.Security.SecuritySafeCritical] // auto-generated public override int Read([In, Out] byte[] buffer, int offset, int count) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(offset), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - offset < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); // Keep this in sync with contract validation in ReadAsync @@ -404,42 +386,49 @@ namespace System.IO { int nInt = (int) n; // Safe because n <= count, which is an Int32 if (nInt < 0) - nInt = 0; // _position could be beyond EOF - Contract.Assert(pos + nInt >= 0, "_position + n >= 0"); // len is less than 2^63 -1. - - if (_buffer != null) { - unsafe { - byte* pointer = null; - RuntimeHelpers.PrepareConstrainedRegions(); - try { - _buffer.AcquirePointer(ref pointer); - Buffer.Memcpy(buffer, offset, pointer + pos + _offset, 0, nInt); - } - finally { - if (pointer != null) { - _buffer.ReleasePointer(); + return 0; // _position could be beyond EOF + Debug.Assert(pos + nInt >= 0, "_position + n >= 0"); // len is less than 2^63 -1. + + unsafe + { + fixed (byte* pBuffer = buffer) + { + if (_buffer != null) + { + byte* pointer = null; + + RuntimeHelpers.PrepareConstrainedRegions(); + try + { + _buffer.AcquirePointer(ref pointer); + Buffer.Memcpy(pBuffer + offset, pointer + pos + _offset, nInt); + } + finally + { + if (pointer != null) + { + _buffer.ReleasePointer(); + } } } - } - } - else { - unsafe { - Buffer.Memcpy(buffer, offset, _mem + pos, 0, nInt); + else + { + Buffer.Memcpy(pBuffer + offset, _mem + pos, nInt); + } } } Interlocked.Exchange(ref _position, pos + n); return nInt; } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public override Task ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(offset), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - offset < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); // contract validation copied from Read(...) @@ -455,12 +444,11 @@ namespace System.IO { } catch (Exception ex) { - Contract.Assert(! (ex is OperationCanceledException)); + Debug.Assert(! (ex is OperationCanceledException)); return Task.FromException(ex); } } - [System.Security.SecuritySafeCritical] // auto-generated public override int ReadByte() { if (!_isOpen) __Error.StreamIsClosed(); if (!CanRead) __Error.ReadNotSupported(); @@ -497,7 +485,7 @@ namespace System.IO { public override long Seek(long offset, SeekOrigin loc) { if (!_isOpen) __Error.StreamIsClosed(); if (offset > UnmanagedMemStreamMaxLength) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_UnmanagedMemStreamLength")); + throw new ArgumentOutOfRangeException(nameof(offset), Environment.GetResourceString("ArgumentOutOfRange_UnmanagedMemStreamLength")); switch(loc) { case SeekOrigin.Begin: if (offset < 0) @@ -524,11 +512,10 @@ namespace System.IO { } long finalPos = Interlocked.Read(ref _position); - Contract.Assert(finalPos >= 0, "_position >= 0"); + Debug.Assert(finalPos >= 0, "_position >= 0"); return finalPos; } - [System.Security.SecuritySafeCritical] // auto-generated public override void SetLength(long value) { if (value < 0) throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); @@ -554,14 +541,13 @@ namespace System.IO { } } - [System.Security.SecuritySafeCritical] // auto-generated public override void Write(byte[] buffer, int offset, int count) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(offset), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - offset < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); // Keep contract validation in sync with WriteAsync(..) @@ -595,46 +581,52 @@ namespace System.IO { } } - if (_buffer != null) { - - long bytesLeft = _capacity - pos; - if (bytesLeft < count) { - throw new ArgumentException(Environment.GetResourceString("Arg_BufferTooSmall")); - } + unsafe + { + fixed (byte* pBuffer = buffer) + { + if (_buffer != null) + { + long bytesLeft = _capacity - pos; + if (bytesLeft < count) + { + throw new ArgumentException(Environment.GetResourceString("Arg_BufferTooSmall")); + } - unsafe { - byte* pointer = null; - RuntimeHelpers.PrepareConstrainedRegions(); - try { - _buffer.AcquirePointer(ref pointer); - Buffer.Memcpy(pointer + pos + _offset, 0, buffer, offset, count); - } - finally { - if (pointer != null) { - _buffer.ReleasePointer(); + byte* pointer = null; + RuntimeHelpers.PrepareConstrainedRegions(); + try + { + _buffer.AcquirePointer(ref pointer); + Buffer.Memcpy(pointer + pos + _offset, pBuffer + offset, count); + } + finally + { + if (pointer != null) + { + _buffer.ReleasePointer(); + } } } - } - } - else { - unsafe { - Buffer.Memcpy(_mem + pos, 0, buffer, offset, count); + else + { + Buffer.Memcpy(_mem + pos, pBuffer + offset, count); + } } } Interlocked.Exchange(ref _position, n); return; } - [HostProtection(ExternalThreading = true)] [ComVisible(false)] public override Task WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) { if (buffer==null) - throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); if (offset < 0) - throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(offset), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (buffer.Length - offset < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); // contract validation copied from Write(..) @@ -649,13 +641,12 @@ namespace System.IO { } catch (Exception ex) { - Contract.Assert(! (ex is OperationCanceledException)); + Debug.Assert(! (ex is OperationCanceledException)); return Task.FromException(ex); } } - [System.Security.SecuritySafeCritical] // auto-generated public override void WriteByte(byte value) { if (!_isOpen) __Error.StreamIsClosed(); if (!CanWrite) __Error.WriteNotSupported(); @@ -674,7 +665,7 @@ namespace System.IO { // Check to see whether we are now expanding the stream and must // zero any memory in the middle. // don't do if created from SafeBuffer - if (_buffer == null) { + if (_buffer == null) { if (pos > len) { unsafe { Buffer.ZeroMemory(_mem+len, pos-len); diff --git a/src/mscorlib/src/System/IO/UnmanagedMemoryStreamWrapper.cs b/src/mscorlib/src/System/IO/UnmanagedMemoryStreamWrapper.cs index 5727eed..040ddbb 100644 --- a/src/mscorlib/src/System/IO/UnmanagedMemoryStreamWrapper.cs +++ b/src/mscorlib/src/System/IO/UnmanagedMemoryStreamWrapper.cs @@ -106,7 +106,6 @@ namespace System.IO { return _unmanagedStream.Seek(offset, loc); } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe override byte[] ToArray() { if (!_unmanagedStream._isOpen) __Error.StreamIsClosed(); if (!_unmanagedStream.CanRead) __Error.ReadNotSupported(); @@ -127,7 +126,7 @@ namespace System.IO { // Writes this MemoryStream to another stream. public unsafe override void WriteTo(Stream stream) { if (stream==null) - throw new ArgumentNullException("stream", Environment.GetResourceString("ArgumentNull_Stream")); + throw new ArgumentNullException(nameof(stream), Environment.GetResourceString("ArgumentNull_Stream")); Contract.EndContractBlock(); if (!_unmanagedStream._isOpen) __Error.StreamIsClosed(); @@ -151,16 +150,16 @@ namespace System.IO { // The parameter checks must be in sync with the base version: if (destination == null) - throw new ArgumentNullException("destination"); + throw new ArgumentNullException(nameof(destination)); if (bufferSize <= 0) - throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); + throw new ArgumentOutOfRangeException(nameof(bufferSize), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); if (!CanRead && !CanWrite) throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_StreamClosed")); if (!destination.CanRead && !destination.CanWrite) - throw new ObjectDisposedException("destination", Environment.GetResourceString("ObjectDisposed_StreamClosed")); + throw new ObjectDisposedException(nameof(destination), Environment.GetResourceString("ObjectDisposed_StreamClosed")); if (!CanRead) throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnreadableStream")); diff --git a/src/mscorlib/src/System/IO/__DebugOutputTextWriter.cs b/src/mscorlib/src/System/IO/__DebugOutputTextWriter.cs deleted file mode 100644 index 621bc41..0000000 --- a/src/mscorlib/src/System/IO/__DebugOutputTextWriter.cs +++ /dev/null @@ -1,76 +0,0 @@ -// 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. - -#if _DEBUG -// This class writes to wherever OutputDebugString writes to. If you don't have -// a Windows app (ie, something hosted in IE), you can use this to redirect Console -// output for some good old-fashioned console spew in MSDEV's debug output window. - -using System; -using System.IO; -using System.Text; -using System.Security; -using System.Runtime.InteropServices; -using System.Runtime.Versioning; -using Microsoft.Win32; -using System.Globalization; - -namespace System.IO { - internal class __DebugOutputTextWriter : TextWriter { - private readonly String _consoleType; - - internal __DebugOutputTextWriter(String consoleType): base(CultureInfo.InvariantCulture) - { - _consoleType = consoleType; - } - - public override Encoding Encoding { -#if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] -#endif - get { - if (Marshal.SystemDefaultCharSize == 1) - return Encoding.Default; - else - return new UnicodeEncoding(false, false); - } - } - - [System.Security.SecuritySafeCritical] // auto-generated - public override void Write(char c) - { - OutputDebugString(c.ToString()); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public override void Write(String str) - { - OutputDebugString(str); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public override void Write(char[] array) - { - if (array != null) - OutputDebugString(new String(array)); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public override void WriteLine(String str) - { - if (str != null) - OutputDebugString(_consoleType + str); - else - OutputDebugString(""); - OutputDebugString(new String(CoreNewLine)); - } - - [System.Security.SecurityCritical] // auto-generated - [DllImport(Win32Native.KERNEL32, CharSet=CharSet.Auto)] - [SuppressUnmanagedCodeSecurityAttribute()] - private static extern void OutputDebugString(String output); - } -} - -#endif // _DEBUG diff --git a/src/mscorlib/src/System/IO/__Error.cs b/src/mscorlib/src/System/IO/__Error.cs index a31d965..ad4972d 100644 --- a/src/mscorlib/src/System/IO/__Error.cs +++ b/src/mscorlib/src/System/IO/__Error.cs @@ -74,7 +74,6 @@ namespace System.IO { // discovery permission to that path. If we do not, return just the // file name. If we know it is a directory, then don't return the // directory name. - [System.Security.SecurityCritical] // auto-generated internal static String GetDisplayablePath(String path, bool isInvalidPath) { @@ -85,7 +84,7 @@ namespace System.IO { bool isFullyQualified = false; if (path.Length < 2) return path; - if (Path.IsDirectorySeparator(path[0]) && Path.IsDirectorySeparator(path[1])) + if (PathInternal.IsDirectorySeparator(path[0]) && PathInternal.IsDirectorySeparator(path[1])) isFullyQualified = true; else if (path[1] == Path.VolumeSeparatorChar) { isFullyQualified = true; @@ -97,9 +96,6 @@ namespace System.IO { bool safeToReturn = false; try { if (!isInvalidPath) { -#if !FEATURE_CORECLR - new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { path }, false, false).Demand(); -#endif safeToReturn = true; } } @@ -116,7 +112,7 @@ namespace System.IO { } if (!safeToReturn) { - if (Path.IsDirectorySeparator(path[path.Length - 1])) + if (PathInternal.IsDirectorySeparator(path[path.Length - 1])) path = Environment.GetResourceString("IO.IO_NoPermissionToDirectoryName"); else path = Path.GetFileName(path); @@ -125,7 +121,6 @@ namespace System.IO { return path; } - [System.Security.SecuritySafeCritical] // auto-generated internal static void WinIOError() { int errorCode = Marshal.GetLastWin32Error(); WinIOError(errorCode, String.Empty); @@ -136,7 +131,6 @@ namespace System.IO { // will determine the appropriate exception to throw dependent on your // error, and depending on the error, insert a string into the message // gotten from the ResourceManager. - [System.Security.SecurityCritical] // auto-generated internal static void WinIOError(int errorCode, String maybeFullPath) { // This doesn't have to be perfect, but is a perf optimization. bool isInvalidPath = errorCode == Win32Native.ERROR_INVALID_NAME || errorCode == Win32Native.ERROR_BAD_PATHNAME; @@ -195,13 +189,11 @@ namespace System.IO { } // An alternative to WinIOError with friendlier messages for drives - [System.Security.SecuritySafeCritical] // auto-generated internal static void WinIODriveError(String driveName) { int errorCode = Marshal.GetLastWin32Error(); WinIODriveError(driveName, errorCode); } - [System.Security.SecurityCritical] // auto-generated internal static void WinIODriveError(String driveName, int errorCode) { switch (errorCode) { diff --git a/src/mscorlib/src/System/Int16.cs b/src/mscorlib/src/System/Int16.cs index 0adc64c..f02a5f2 100644 --- a/src/mscorlib/src/System/Int16.cs +++ b/src/mscorlib/src/System/Int16.cs @@ -71,13 +71,11 @@ namespace System { } - [System.Security.SecuritySafeCritical] // auto-generated public override String ToString() { Contract.Ensures(Contract.Result() != null); return Number.FormatInt32(m_value, null, NumberFormatInfo.CurrentInfo); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(IFormatProvider provider) { Contract.Ensures(Contract.Result() != null); return Number.FormatInt32(m_value, null, NumberFormatInfo.GetInstance(provider)); @@ -93,7 +91,6 @@ namespace System { return ToString(format, NumberFormatInfo.GetInstance(provider)); } - [System.Security.SecuritySafeCritical] // auto-generated private String ToString(String format, NumberFormatInfo info) { Contract.Ensures(Contract.Result() != null); diff --git a/src/mscorlib/src/System/Int32.cs b/src/mscorlib/src/System/Int32.cs index 778a893..2da55bf 100644 --- a/src/mscorlib/src/System/Int32.cs +++ b/src/mscorlib/src/System/Int32.cs @@ -77,21 +77,18 @@ namespace System { return m_value; } - [System.Security.SecuritySafeCritical] // auto-generated [Pure] public override String ToString() { Contract.Ensures(Contract.Result() != null); return Number.FormatInt32(m_value, null, NumberFormatInfo.CurrentInfo); } - [System.Security.SecuritySafeCritical] // auto-generated [Pure] public String ToString(String format) { Contract.Ensures(Contract.Result() != null); return Number.FormatInt32(m_value, format, NumberFormatInfo.CurrentInfo); } - [System.Security.SecuritySafeCritical] // auto-generated [Pure] public String ToString(IFormatProvider provider) { Contract.Ensures(Contract.Result() != null); @@ -99,7 +96,6 @@ namespace System { } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(String format, IFormatProvider provider) { Contract.Ensures(Contract.Result() != null); return Number.FormatInt32(m_value, format, NumberFormatInfo.GetInstance(provider)); diff --git a/src/mscorlib/src/System/Int64.cs b/src/mscorlib/src/System/Int64.cs index 0cd2558..e5fcf86 100644 --- a/src/mscorlib/src/System/Int64.cs +++ b/src/mscorlib/src/System/Int64.cs @@ -76,25 +76,21 @@ namespace System { return (unchecked((int)((long)m_value)) ^ (int)(m_value >> 32)); } - [System.Security.SecuritySafeCritical] // auto-generated public override String ToString() { Contract.Ensures(Contract.Result() != null); return Number.FormatInt64(m_value, null, NumberFormatInfo.CurrentInfo); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(IFormatProvider provider) { Contract.Ensures(Contract.Result() != null); return Number.FormatInt64(m_value, null, NumberFormatInfo.GetInstance(provider)); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(String format) { Contract.Ensures(Contract.Result() != null); return Number.FormatInt64(m_value, format, NumberFormatInfo.CurrentInfo); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(String format, IFormatProvider provider) { Contract.Ensures(Contract.Result() != null); return Number.FormatInt64(m_value, format, NumberFormatInfo.GetInstance(provider)); diff --git a/src/mscorlib/src/System/IntPtr.cs b/src/mscorlib/src/System/IntPtr.cs index c7eea36..2d66652 100644 --- a/src/mscorlib/src/System/IntPtr.cs +++ b/src/mscorlib/src/System/IntPtr.cs @@ -26,13 +26,11 @@ namespace System { [System.Runtime.InteropServices.ComVisible(true)] public struct IntPtr : IEquatable, ISerializable { - [SecurityCritical] unsafe private void* m_value; // The compiler treats void* closest to uint hence explicit casts are required to preserve int behavior public static readonly IntPtr Zero; // fast way to compare IntPtr to (IntPtr)0 while IntPtr.Zero doesn't work due to slow statics access - [System.Security.SecuritySafeCritical] // auto-generated [Pure] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal unsafe bool IsNull() @@ -40,7 +38,6 @@ namespace System { return (this.m_value == null); } - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] [System.Runtime.Versioning.NonVersionable] public unsafe IntPtr(int value) @@ -52,7 +49,6 @@ namespace System { #endif } - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] [System.Runtime.Versioning.NonVersionable] public unsafe IntPtr(long value) @@ -64,7 +60,6 @@ namespace System { #endif } - [System.Security.SecurityCritical] [CLSCompliant(false)] [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] [System.Runtime.Versioning.NonVersionable] @@ -73,7 +68,6 @@ namespace System { m_value = value; } - [System.Security.SecurityCritical] // auto-generated private unsafe IntPtr(SerializationInfo info, StreamingContext context) { long l = info.GetInt64("value"); @@ -84,10 +78,9 @@ namespace System { m_value = (void *)l; } - [System.Security.SecurityCritical] unsafe void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); #if BIT64 @@ -97,7 +90,6 @@ namespace System { #endif } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe override bool Equals(Object obj) { if (obj is IntPtr) { return (m_value == ((IntPtr)obj).m_value); @@ -105,27 +97,20 @@ namespace System { return false; } - [SecuritySafeCritical] unsafe bool IEquatable.Equals(IntPtr other) { return m_value == other.m_value; } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe override int GetHashCode() { -#if FEATURE_CORECLR #if BIT64 long l = (long)m_value; return (unchecked((int)l) ^ (int)(l >> 32)); #else // !BIT64 (32) return unchecked((int)m_value); #endif -#else - return unchecked((int)((long)m_value)); -#endif } - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [System.Runtime.Versioning.NonVersionable] public unsafe int ToInt32() { @@ -137,7 +122,6 @@ namespace System { #endif } - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [System.Runtime.Versioning.NonVersionable] public unsafe long ToInt64() { @@ -148,7 +132,6 @@ namespace System { #endif } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe override String ToString() { #if BIT64 return ((long)m_value).ToString(CultureInfo.InvariantCulture); @@ -157,7 +140,6 @@ namespace System { #endif } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe String ToString(String format) { Contract.Ensures(Contract.Result() != null); @@ -184,7 +166,6 @@ namespace System { return new IntPtr(value); } - [System.Security.SecurityCritical] [CLSCompliant(false), ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] [System.Runtime.Versioning.NonVersionable] public static unsafe explicit operator IntPtr (void* value) @@ -192,7 +173,6 @@ namespace System { return new IntPtr(value); } - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.Versioning.NonVersionable] public static unsafe explicit operator void* (IntPtr value) @@ -200,7 +180,6 @@ namespace System { return value.m_value; } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.Versioning.NonVersionable] public unsafe static explicit operator int (IntPtr value) { @@ -212,7 +191,6 @@ namespace System { #endif } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.Versioning.NonVersionable] public unsafe static explicit operator long (IntPtr value) { @@ -223,7 +201,6 @@ namespace System { #endif } - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [System.Runtime.Versioning.NonVersionable] public unsafe static bool operator == (IntPtr value1, IntPtr value2) @@ -231,7 +208,6 @@ namespace System { return value1.m_value == value2.m_value; } - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [System.Runtime.Versioning.NonVersionable] public unsafe static bool operator != (IntPtr value1, IntPtr value2) @@ -289,7 +265,6 @@ namespace System { } - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [System.Runtime.Versioning.NonVersionable] diff --git a/src/mscorlib/src/System/Internal.cs b/src/mscorlib/src/System/Internal.cs index c6be49f..0eb2bce 100644 --- a/src/mscorlib/src/System/Internal.cs +++ b/src/mscorlib/src/System/Internal.cs @@ -85,16 +85,15 @@ namespace System new Dictionary(); new Dictionary(); new Dictionary(); -#if FEATURE_CORECLR + // to genereate mdil for Dictionary instantiation when key is user defined value type new Dictionary(); -#endif - // Microsoft.Windows.Design + // Microsoft.Windows.Design new Dictionary(); new EnumEqualityComparer(); - // Microsoft.Expression.DesignModel + // Microsoft.Expression.DesignModel new Dictionary>(); new Dictionary, Object>(); @@ -157,14 +156,12 @@ namespace System SZArrayHelper(null); SZArrayHelper(null); -#if FEATURE_CORECLR #pragma warning disable 4014 // This is necessary to generate MDIL for AsyncVoidMethodBuilder AsyncHelper(); AsyncHelper2(); AsyncHelper3(); #pragma warning restore 4014 -#endif } static T NullableHelper() where T : struct @@ -183,7 +180,6 @@ namespace System oSZArrayHelper.GetEnumerator(); } -#if FEATURE_CORECLR // System.Runtime.CompilerServices.AsyncVoidMethodBuilder // System.Runtime.CompilerServices.TaskAwaiter static async void AsyncHelper() @@ -203,7 +199,6 @@ namespace System { await Task.FromResult(""); } -#endif #if FEATURE_COMINTEROP @@ -214,7 +209,6 @@ namespace System // typed as matching instantiations of mscorlib copies of WinRT interfaces (IIterable, IVector, // IMap, ...) which is necessary to generate all required IL stubs. - [SecurityCritical] static void CommonlyUsedWinRTRedirectedInterfaceStubs() { WinRT_IEnumerable(null, null, null); @@ -261,7 +255,6 @@ namespace System WinRT_Nullable(); } - [SecurityCritical] static void WinRT_IEnumerable(IterableToEnumerableAdapter iterableToEnumerableAdapter, EnumerableToIterableAdapter enumerableToIterableAdapter, IIterable iterable) { // instantiate stubs for the one method on IEnumerable and the one method on IIterable @@ -269,7 +262,6 @@ namespace System enumerableToIterableAdapter.First_Stub(); } - [SecurityCritical] static void WinRT_IList(VectorToListAdapter vectorToListAdapter, VectorToCollectionAdapter vectorToCollectionAdapter, ListToVectorAdapter listToVectorAdapter, IVector vector) { WinRT_IEnumerable(null, null, null); @@ -294,7 +286,6 @@ namespace System listToVectorAdapter.Clear(); } - [SecurityCritical] static void WinRT_IReadOnlyCollection(VectorViewToReadOnlyCollectionAdapter vectorViewToReadOnlyCollectionAdapter) { WinRT_IEnumerable(null, null, null); @@ -303,7 +294,6 @@ namespace System vectorViewToReadOnlyCollectionAdapter.Count(); } - [SecurityCritical] static void WinRT_IReadOnlyList(IVectorViewToIReadOnlyListAdapter vectorToListAdapter, IReadOnlyListToIVectorViewAdapter listToVectorAdapter, IVectorView vectorView) { WinRT_IEnumerable(null, null, null); @@ -317,7 +307,6 @@ namespace System listToVectorAdapter.Size(); } - [SecurityCritical] static void WinRT_IDictionary(MapToDictionaryAdapter mapToDictionaryAdapter, MapToCollectionAdapter mapToCollectionAdapter, DictionaryToMapAdapter dictionaryToMapAdapter, IMap map) { WinRT_IEnumerable>(null, null, null); @@ -343,7 +332,6 @@ namespace System dictionaryToMapAdapter.Clear(); } - [SecurityCritical] static void WinRT_IReadOnlyDictionary(IMapViewToIReadOnlyDictionaryAdapter mapToDictionaryAdapter, IReadOnlyDictionaryToIMapViewAdapter dictionaryToMapAdapter, IMapView mapView, MapViewToReadOnlyCollectionAdapter mapViewToReadOnlyCollectionAdapter) { WinRT_IEnumerable>(null, null, null); @@ -364,7 +352,6 @@ namespace System dictionaryToMapAdapter.HasKey(default(K)); } - [SecurityCritical] static void WinRT_Nullable() where T : struct { Nullable nullable = new Nullable(); diff --git a/src/mscorlib/src/System/InvalidTimeZoneException.cs b/src/mscorlib/src/System/InvalidTimeZoneException.cs index 2c57bc8..f334754 100644 --- a/src/mscorlib/src/System/InvalidTimeZoneException.cs +++ b/src/mscorlib/src/System/InvalidTimeZoneException.cs @@ -2,16 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System { - using System.Runtime.Serialization; - using System.Runtime.CompilerServices; +using System.Runtime.Serialization; +namespace System +{ [Serializable] [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] -#if !FEATURE_CORECLR - [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] -#endif - public class InvalidTimeZoneException : Exception { + public class InvalidTimeZoneException : Exception + { public InvalidTimeZoneException(String message) : base(message) { } diff --git a/src/mscorlib/src/System/Lazy.cs b/src/mscorlib/src/System/Lazy.cs index 883979e..85cbb98 100644 --- a/src/mscorlib/src/System/Lazy.cs +++ b/src/mscorlib/src/System/Lazy.cs @@ -48,9 +48,6 @@ namespace System /// [Serializable] [ComVisible(false)] -#if !FEATURE_CORECLR - [HostProtection(Synchronization = true, ExternalThreading = true)] -#endif [DebuggerTypeProxy(typeof(System_LazyDebugView<>))] [DebuggerDisplay("ThreadSafetyMode={Mode}, IsValueCreated={IsValueCreated}, IsValueFaulted={IsValueFaulted}, Value={ValueForDebugDisplay}")] public class Lazy @@ -90,7 +87,7 @@ namespace System // 2- Flag to m_threadSafeObj if ExecutionAndPublication mode and the value is known to be initialized static readonly Func ALREADY_INVOKED_SENTINEL = delegate { - Contract.Assert(false, "ALREADY_INVOKED_SENTINEL should never be invoked."); + Debug.Assert(false, "ALREADY_INVOKED_SENTINEL should never be invoked."); return default(T); }; @@ -207,7 +204,7 @@ namespace System public Lazy(Func valueFactory, LazyThreadSafetyMode mode) { if (valueFactory == null) - throw new ArgumentNullException("valueFactory"); + throw new ArgumentNullException(nameof(valueFactory)); m_threadSafeObj = GetObjectFromMode(mode); m_valueFactory = valueFactory; @@ -223,7 +220,7 @@ namespace System else if (mode == LazyThreadSafetyMode.PublicationOnly) return LazyHelpers.PUBLICATION_ONLY_SENTINEL; else if (mode != LazyThreadSafetyMode.None) - throw new ArgumentOutOfRangeException("mode", Environment.GetResourceString("Lazy_ctor_ModeInvalid")); + throw new ArgumentOutOfRangeException(nameof(mode), Environment.GetResourceString("Lazy_ctor_ModeInvalid")); return null; // None mode } @@ -336,18 +333,12 @@ namespace System } LazyInternalExceptionHolder exc = m_boxed as LazyInternalExceptionHolder; - Contract.Assert(exc != null); + Debug.Assert(exc != null); exc.m_edi.Throw(); } // Fall through to the slow path. -#if !FEATURE_CORECLR - // We call NOCTD to abort attempts by the debugger to funceval this property (e.g. on mouseover) - // (the debugger proxy is the correct way to look at state/value of this object) - Debugger.NotifyOfCrossThreadDependency(); -#endif return LazyInitValue(); - } } @@ -391,7 +382,7 @@ namespace System if (threadSafeObj != (object)ALREADY_INVOKED_SENTINEL) Monitor.Enter(threadSafeObj, ref lockTaken); else - Contract.Assert(m_boxed != null); + Debug.Assert(m_boxed != null); if (m_boxed == null) { @@ -405,7 +396,7 @@ namespace System if (boxed == null) // it is not Boxed, so it is a LazyInternalExceptionHolder { LazyInternalExceptionHolder exHolder = m_boxed as LazyInternalExceptionHolder; - Contract.Assert(exHolder != null); + Debug.Assert(exHolder != null); exHolder.m_edi.Throw(); } } @@ -416,7 +407,7 @@ namespace System Monitor.Exit(threadSafeObj); } } - Contract.Assert(boxed != null); + Debug.Assert(boxed != null); return boxed.m_value; } diff --git a/src/mscorlib/src/System/LowLevelConsole.cs b/src/mscorlib/src/System/LowLevelConsole.cs index 3aba3db..316583e 100644 --- a/src/mscorlib/src/System/LowLevelConsole.cs +++ b/src/mscorlib/src/System/LowLevelConsole.cs @@ -16,16 +16,13 @@ namespace System public static class Console { - [SecurityCritical] static SafeFileHandle _outputHandle; - [SecuritySafeCritical] static Console() { _outputHandle = new SafeFileHandle(Win32Native.GetStdHandle(Win32Native.STD_OUTPUT_HANDLE), false); } - [SecuritySafeCritical] public static unsafe void Write(string s) { byte[] bytes = Encoding.UTF8.GetBytes(s); diff --git a/src/mscorlib/src/System/MarshalByRefObject.cs b/src/mscorlib/src/System/MarshalByRefObject.cs index 4948a43..53ebda7 100644 --- a/src/mscorlib/src/System/MarshalByRefObject.cs +++ b/src/mscorlib/src/System/MarshalByRefObject.cs @@ -13,250 +13,25 @@ ** ** ===========================================================*/ -namespace System { - - using System; - using System.Security; - using System.Security.Permissions; - using System.Threading; - using System.Runtime.Remoting; -#if FEATURE_REMOTING - using System.Runtime.Remoting.Lifetime; - using System.Runtime.Remoting.Services; -#endif - using System.Runtime.InteropServices; - using System.Reflection; - using System.Runtime.CompilerServices; - using System.Runtime.Versioning; - using System.Diagnostics.Contracts; - using CultureInfo = System.Globalization.CultureInfo; - +namespace System +{ [Serializable] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public abstract class MarshalByRefObject { -#if FEATURE_REMOTING - private Object __identity; - - private Object Identity { get { return __identity; } set { __identity = value; } } -#if FEATURE_COMINTEROP - [System.Security.SecuritySafeCritical] // auto-generated - internal IntPtr GetComIUnknown(bool fIsBeingMarshalled) - { - IntPtr pUnk; - if(RemotingServices.IsTransparentProxy(this)) - { - pUnk = RemotingServices.GetRealProxy(this).GetCOMIUnknown(fIsBeingMarshalled); - } - else - { - pUnk = Marshal.GetIUnknownForObject(this); - } - return pUnk; - } - - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern IntPtr GetComIUnknown(MarshalByRefObject o); -#endif // FEATURE_COMINTEROP - - // (1) for remote COM objects IsInstance of can't be executed on - // the proxies, so we need this method to be executed on the - // actual object. - // (2) for remote objects that do not have the complete type information - // we intercept calls to check the type and execute it on the actual - // object - internal bool IsInstanceOfType(Type T) + protected MarshalByRefObject() { } + public object GetLifetimeService() { - return T.IsInstanceOfType(this); + throw new PlatformNotSupportedException(); } - - // for remote COM Objects the late binding methods can't be - // executed on proxies, so we need this method to execute on - // the real object - internal Object InvokeMember(String name,BindingFlags invokeAttr,Binder binder, - Object[] args,ParameterModifier[] modifiers,CultureInfo culture,String[] namedParameters) + public virtual object InitializeLifetimeService() { - Type t = GetType(); - - // Sanity check - if(!t.IsCOMObject) - throw new InvalidOperationException(Environment.GetResourceString("Arg_InvokeMember")); - - // Call into the runtime to invoke on the COM object. - return t.InvokeMember(name, invokeAttr, binder, this, args, modifiers, culture, namedParameters); + throw new PlatformNotSupportedException(); } - - // Returns a new cloned MBR instance that is a memberwise copy of this - // with the identity nulled out, so there are no identity conflicts - // when the cloned object is marshalled protected MarshalByRefObject MemberwiseClone(bool cloneIdentity) { MarshalByRefObject mbr = (MarshalByRefObject)base.MemberwiseClone(); - // set the identity on the cloned object to null - if (!cloneIdentity) - mbr.Identity = null; return mbr; } - - - - // A helper routine to extract the identity either from the marshalbyrefobject base - // class if it is not a proxy, otherwise from the real proxy. - // A flag is set to indicate whether the object passed in is a server or a proxy - [System.Security.SecuritySafeCritical] // auto-generated - internal static Identity GetIdentity(MarshalByRefObject obj, out bool fServer) - { - fServer = true; - Identity id = null; - - if(null != obj) - { - if(!RemotingServices.IsTransparentProxy(obj)) - { - id = (Identity)obj.Identity; - } - else - { - // Toggle flag to indicate that we have a proxy - fServer = false; - id = RemotingServices.GetRealProxy(obj).IdentityObject; - } - } - - return id; - } - - // Another helper that delegates to the helper above - internal static Identity GetIdentity(MarshalByRefObject obj) - { - Contract.Assert(!RemotingServices.IsTransparentProxy(obj), "Use this method for server objects only"); - - bool fServer; - return GetIdentity(obj, out fServer); - } - - - internal ServerIdentity __RaceSetServerIdentity(ServerIdentity id) - { - if (__identity == null) - { - // For strictly MBR types, the TP field in the identity - // holds the real server - if (!id.IsContextBound) - { - id.RaceSetTransparentProxy(this); - } - Interlocked.CompareExchange(ref __identity, id, null); - } - return (ServerIdentity)__identity; - } - - - internal void __ResetServerIdentity() - { - __identity = null; - } - - // This method is used return a lifetime service object which - // is used to control the lifetime policy to the object. - // For the default Lifetime service this will be an object of typoe ILease. - // - [System.Security.SecurityCritical] // auto-generated_required - public Object GetLifetimeService() - { - return LifetimeServices.GetLease(this); - } - - // This method is used return lifetime service object. This method - // can be overridden to return a LifetimeService object with properties unique to - // this object. - // For the default Lifetime service this will be an object of type ILease. - // - [System.Security.SecurityCritical] // auto-generated_required - public virtual Object InitializeLifetimeService() - { - return LifetimeServices.GetLeaseInitial(this); - } - - [System.Security.SecurityCritical] // auto-generated_required - public virtual ObjRef CreateObjRef(Type requestedType) - { - if(__identity == null) - { - throw new RemotingException(Environment.GetResourceString( - "Remoting_NoIdentityEntry")); - } - return new ObjRef(this, requestedType); - } - - // This is for casting interop ObjRefLite's. - // ObjRefLite's have been deprecated. These methods are not exposed - // through any user APIs and would be removed in the future - [System.Security.SecuritySafeCritical] // auto-generated - internal bool CanCastToXmlType(String xmlTypeName, String xmlTypeNamespace) - { - Type castType = SoapServices.GetInteropTypeFromXmlType(xmlTypeName, xmlTypeNamespace); - if (castType == null) - { - String typeNamespace; - String assemblyName; - if (!SoapServices.DecodeXmlNamespaceForClrTypeNamespace(xmlTypeNamespace, - out typeNamespace, out assemblyName)) - return false; - - String typeName; - if ((typeNamespace != null) && (typeNamespace.Length > 0)) - typeName = typeNamespace + "." + xmlTypeName; - else - typeName = xmlTypeName; - - try - { - Assembly asm = Assembly.Load(assemblyName); - castType = asm.GetType(typeName, false, false); - } - catch - { - return false; - } - } - - if (castType != null) - return castType.IsAssignableFrom(this.GetType()); - - return false; - } // CanCastToXmlType - - // helper method for calling CanCastToXmlType - // ObjRefLite's have been deprecated. These methods are not exposed - // through any user APIs and would be removed in the future - [System.Security.SecuritySafeCritical] // auto-generated - internal static bool CanCastToXmlTypeHelper(RuntimeType castType, MarshalByRefObject o) - { - if (castType == null) - throw new ArgumentNullException("castType"); - - Contract.EndContractBlock(); - // MarshalByRefObject's can only be casted to MarshalByRefObject's or interfaces. - if (!castType.IsInterface && !castType.IsMarshalByRef) - return false; - - // figure out xml type name - String xmlTypeName = null; - String xmlTypeNamespace = null; - if (!SoapServices.GetXmlTypeForInteropType(castType, out xmlTypeName, out xmlTypeNamespace)) - { - // There's no registered interop type name, so just use the default. - xmlTypeName = castType.Name; - xmlTypeNamespace = - SoapServices.CodeXmlNamespaceForClrTypeNamespace( - castType.Namespace, castType.GetRuntimeAssembly().GetSimpleName()); - } - - return o.CanCastToXmlType(xmlTypeName, xmlTypeNamespace); - } // CanCastToXmlType - -#endif // FEATURE_REMOTING - } -} // namespace + } +} diff --git a/src/mscorlib/src/System/Math.cs b/src/mscorlib/src/System/Math.cs index 4e280d5..3ac1f06 100644 --- a/src/mscorlib/src/System/Math.cs +++ b/src/mscorlib/src/System/Math.cs @@ -35,16 +35,12 @@ namespace System { public const double PI = 3.14159265358979323846; public const double E = 2.7182818284590452354; - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern double Acos(double d); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern double Asin(double d); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern double Atan(double d); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern double Atan2(double y,double x); @@ -52,15 +48,12 @@ namespace System { return Decimal.Ceiling(d); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern double Ceiling(double a); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern double Cos (double d); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern double Cosh(double value); @@ -68,11 +61,9 @@ namespace System { return Decimal.Floor(d); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern double Floor(double d); - [System.Security.SecuritySafeCritical] // auto-generated private static unsafe double InternalRound(double value, int digits, MidpointRounding mode) { if (Abs(value) < doubleRoundLimit) { Double power10 = roundPower10Double[digits]; @@ -92,33 +83,27 @@ namespace System { return value; } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe static double InternalTruncate(double d) { SplitFractionDouble(&d); return d; } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern double Sin(double a); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern double Tan(double a); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern double Sinh(double value); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern double Tanh(double value); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern double Round(double a); public static double Round(double value, int digits) { if ((digits < 0) || (digits > maxRoundingDigits)) - throw new ArgumentOutOfRangeException("digits", Environment.GetResourceString("ArgumentOutOfRange_RoundingDigits")); + throw new ArgumentOutOfRangeException(nameof(digits), Environment.GetResourceString("ArgumentOutOfRange_RoundingDigits")); Contract.EndContractBlock(); return InternalRound(value, digits, MidpointRounding.ToEven); } @@ -129,9 +114,9 @@ namespace System { public static double Round(double value, int digits, MidpointRounding mode) { if ((digits < 0) || (digits > maxRoundingDigits)) - throw new ArgumentOutOfRangeException("digits", Environment.GetResourceString("ArgumentOutOfRange_RoundingDigits")); + throw new ArgumentOutOfRangeException(nameof(digits), Environment.GetResourceString("ArgumentOutOfRange_RoundingDigits")); if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidEnumValue", mode, "MidpointRounding"), "mode"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidEnumValue", mode, nameof(MidpointRounding)), nameof(mode)); } Contract.EndContractBlock(); return InternalRound(value, digits, mode); @@ -153,7 +138,6 @@ namespace System { return Decimal.Round(d, decimals, mode); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static unsafe extern double SplitFractionDouble(double* value); @@ -165,20 +149,15 @@ namespace System { return InternalTruncate(d); } - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern double Sqrt(double d); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern double Log (double d); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern double Log10(double d); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern double Exp(double d); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern double Pow(double x, double y); @@ -284,7 +263,6 @@ namespace System { return -value; } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] extern public static float Abs(float value); // This is special code to handle NaN (We need to make sure NaN's aren't @@ -296,7 +274,6 @@ namespace System { // it runs the else case, which returns +value instead of negating it. // return (value < 0) ? -value : value; - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] extern public static double Abs(double value); // This is special code to handle NaN (We need to make sure NaN's aren't @@ -476,7 +453,151 @@ namespace System { public static Decimal Min(Decimal val1, Decimal val2) { return Decimal.Min(val1,val2); } - + + /*=====================================Clamp==================================== + ** + ==============================================================================*/ + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Byte Clamp(Byte value, Byte min, Byte max) + { + if (min > max) + ThrowMinMaxException(min, max); + if (value < min) + return min; + else if (value > max) + return max; + return value; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Decimal Clamp(Decimal value, Decimal min, Decimal max) + { + if (min > max) + ThrowMinMaxException(min, max); + if (value < min) + return min; + else if (value > max) + return max; + return value; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Double Clamp(Double value, Double min, Double max) + { + if (min > max) + ThrowMinMaxException(min, max); + if (value < min) + return min; + else if (value > max) + return max; + return value; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Int16 Clamp(Int16 value, Int16 min, Int16 max) + { + if (min > max) + ThrowMinMaxException(min, max); + if (value < min) + return min; + else if (value > max) + return max; + return value; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Int32 Clamp(Int32 value, Int32 min, Int32 max) + { + if (min > max) + ThrowMinMaxException(min, max); + if (value < min) + return min; + else if (value > max) + return max; + return value; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Int64 Clamp(Int64 value, Int64 min, Int64 max) + { + if (min > max) + ThrowMinMaxException(min, max); + if (value < min) + return min; + else if (value > max) + return max; + return value; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [CLSCompliant(false)] + public static SByte Clamp(SByte value, SByte min, SByte max) + { + if (min > max) + ThrowMinMaxException(min, max); + if (value < min) + return min; + else if (value > max) + return max; + return value; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Single Clamp(Single value, Single min, Single max) + { + if (min > max) + ThrowMinMaxException(min, max); + if (value < min) + return min; + else if (value > max) + return max; + return value; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [CLSCompliant(false)] + public static UInt16 Clamp(UInt16 value, UInt16 min, UInt16 max) + { + if (min > max) + ThrowMinMaxException(min, max); + if (value < min) + return min; + else if (value > max) + return max; + return value; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [CLSCompliant(false)] + public static UInt32 Clamp(UInt32 value, UInt32 min, UInt32 max) + { + if (min > max) + ThrowMinMaxException(min, max); + if (value < min) + return min; + else if (value > max) + return max; + return value; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [CLSCompliant(false)] + public static UInt64 Clamp(UInt64 value, UInt64 min, UInt64 max) + { + if (min > max) + ThrowMinMaxException(min, max); + if (value < min) + return min; + else if (value > max) + return max; + return value; + } + + private static void ThrowMinMaxException(T min, T max) + { + throw new ArgumentException(Environment.GetResourceString("Argument_MinMaxValue", min, max)); + } + /*=====================================Log====================================== ** ==============================================================================*/ @@ -582,13 +703,21 @@ namespace System { } public static int DivRem(int a, int b, out int result) { - result = a%b; - return a/b; + // TODO https://github.com/dotnet/coreclr/issues/3439: + // Restore to using % and / when the JIT is able to eliminate one of the idivs. + // In the meantime, a * and - is measurably faster than an extra /. + int div = a / b; + result = a - (div * b); + return div; } public static long DivRem(long a, long b, out long result) { - result = a%b; - return a/b; + // TODO https://github.com/dotnet/coreclr/issues/3439: + // Restore to using % and / when the JIT is able to eliminate one of the idivs. + // In the meantime, a * and - is measurably faster than an extra /. + long div = a / b; + result = a - (div * b); + return div; } } } diff --git a/src/mscorlib/src/System/MathF.cs b/src/mscorlib/src/System/MathF.cs new file mode 100644 index 0000000..fb80092 --- /dev/null +++ b/src/mscorlib/src/System/MathF.cs @@ -0,0 +1,253 @@ +// 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. + +/*============================================================ +** +** Purpose: Some single-precision floating-point math operations +** +===========================================================*/ +namespace System { + + //This class contains only static members and doesn't require serialization. + using System; + using System.Runtime; + using System.Runtime.CompilerServices; + using System.Runtime.ConstrainedExecution; + using System.Runtime.Versioning; + using System.Diagnostics.Contracts; + + public static class MathF + { + private static float singleRoundLimit = 1e8f; + + private const int maxRoundingDigits = 6; + + // This table is required for the Round function which can specify the number of digits to round to + private static float[] roundPower10Single = new float[] { + 1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f, 1e6f + }; + + public const float PI = 3.14159265f; + + public const float E = 2.71828183f; + + public static float Abs(float x) => Math.Abs(x); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern float Acos(float x); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern float Asin(float x); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern float Atan(float x); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern float Atan2(float y, float x); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern float Ceiling(float x); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern float Cos(float x); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern float Cosh(float x); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern float Exp(float x); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern float Floor(float x); + + public static float IEEERemainder(float x, float y) + { + if (float.IsNaN(x)) + { + return x; // IEEE 754-2008: NaN payload must be preserved + } + + if (float.IsNaN(y)) + { + return y; // IEEE 754-2008: NaN payload must be preserved + } + + var regularMod = x % y; + + if (float.IsNaN(regularMod)) + { + return float.NaN; + } + + if ((regularMod == 0) && float.IsNegative(x)) + { + return float.NegativeZero; + } + + var alternativeResult = (regularMod - (Abs(y) * Sign(x))); + + if (Abs(alternativeResult) == Abs(regularMod)) + { + var divisionResult = x / y; + var roundedResult = Round(divisionResult); + + if (Abs(roundedResult) > Abs(divisionResult)) + { + return alternativeResult; + } + else + { + return regularMod; + } + } + + if (Abs(alternativeResult) < Abs(regularMod)) + { + return alternativeResult; + } + else + { + return regularMod; + } + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern float Log(float x); + + public static float Log(float x, float y) + { + if (float.IsNaN(x)) + { + return x; // IEEE 754-2008: NaN payload must be preserved + } + + if (float.IsNaN(y)) + { + return y; // IEEE 754-2008: NaN payload must be preserved + } + + if (y == 1) + { + return float.NaN; + } + + if ((x != 1) && ((y == 0) || float.IsPositiveInfinity(y))) + { + return float.NaN; + } + + return Log(x) / Log(y); + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern float Log10(float x); + + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public static float Max(float x, float y) => Math.Max(x, y); + + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public static float Min(float x, float y) => Math.Min(x, y); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern float Pow(float x, float y); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern float Round(float x); + + public static float Round(float x, int digits) + { + if ((digits < 0) || (digits > maxRoundingDigits)) + { + throw new ArgumentOutOfRangeException(nameof(digits), Environment.GetResourceString("ArgumentOutOfRange_RoundingDigits")); + } + Contract.EndContractBlock(); + + return InternalRound(x, digits, MidpointRounding.ToEven); + } + + public static float Round(float x, int digits, MidpointRounding mode) + { + if ((digits < 0) || (digits > maxRoundingDigits)) + { + throw new ArgumentOutOfRangeException(nameof(digits), Environment.GetResourceString("ArgumentOutOfRange_RoundingDigits")); + } + + if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero) + { + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidEnumx", mode, nameof(MidpointRounding)), nameof(mode)); + } + Contract.EndContractBlock(); + + return InternalRound(x, digits, mode); + } + + public static float Round(float x, MidpointRounding mode) + { + if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero) + { + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidEnumx", mode, nameof(MidpointRounding)), nameof(mode)); + } + Contract.EndContractBlock(); + + return InternalRound(x, 0, mode); + } + + public static int Sign(float x) => Math.Sign(x); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern float Sin(float x); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern float Sinh(float x); + + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern float Sqrt(float x); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern float Tan(float x); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern float Tanh(float x); + + public static float Truncate(float x) => InternalTruncate(x); + + private static unsafe float InternalRound(float x, int digits, MidpointRounding mode) + { + if (Abs(x) < singleRoundLimit) + { + var power10 = roundPower10Single[digits]; + + x *= power10; + + if (mode == MidpointRounding.AwayFromZero) + { + var fraction = SplitFractionSingle(&x); + + if (Abs(fraction) >= 0.5f) + { + x += Sign(fraction); + } + } + else + { + x = Round(x); + } + + x /= power10; + } + + return x; + } + + private unsafe static float InternalTruncate(float x) + { + SplitFractionSingle(&x); + return x; + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static unsafe extern float SplitFractionSingle(float* x); + } +} diff --git a/src/mscorlib/src/System/MissingFieldException.cs b/src/mscorlib/src/System/MissingFieldException.cs index 4196ea8..d96d037 100644 --- a/src/mscorlib/src/System/MissingFieldException.cs +++ b/src/mscorlib/src/System/MissingFieldException.cs @@ -39,7 +39,6 @@ namespace System { public override String Message { - [System.Security.SecuritySafeCritical] // auto-generated get { if (ClassName == null) { return base.Message; diff --git a/src/mscorlib/src/System/MissingMemberException.cs b/src/mscorlib/src/System/MissingMemberException.cs index 30ce5b8..ab773dc 100644 --- a/src/mscorlib/src/System/MissingMemberException.cs +++ b/src/mscorlib/src/System/MissingMemberException.cs @@ -48,7 +48,6 @@ namespace System { public override String Message { - [System.Security.SecuritySafeCritical] // auto-generated get { if (ClassName == null) { return base.Message; @@ -62,7 +61,6 @@ namespace System { } // Called to format signature - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern String FormatSignature(byte [] signature); @@ -82,10 +80,9 @@ namespace System { MemberName = memberName; } - [System.Security.SecurityCritical] // auto-generated_required public override void GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); base.GetObjectData(info, context); diff --git a/src/mscorlib/src/System/MissingMethodException.cs b/src/mscorlib/src/System/MissingMethodException.cs index cba33ef..7943490 100644 --- a/src/mscorlib/src/System/MissingMethodException.cs +++ b/src/mscorlib/src/System/MissingMethodException.cs @@ -41,7 +41,6 @@ namespace System { public override String Message { - [System.Security.SecuritySafeCritical] // auto-generated get { if (ClassName == null) { return base.Message; diff --git a/src/mscorlib/src/System/MulticastDelegate.cs b/src/mscorlib/src/System/MulticastDelegate.cs index f59db16..a7b244c 100644 --- a/src/mscorlib/src/System/MulticastDelegate.cs +++ b/src/mscorlib/src/System/MulticastDelegate.cs @@ -9,6 +9,7 @@ namespace System using System.Runtime; using System.Runtime.CompilerServices; using System.Runtime.Serialization; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Reflection.Emit; @@ -20,9 +21,7 @@ namespace System // 1. Multicast delegate // 2. Secure/Wrapper delegate // 3. Inner delegate of secure delegate where the secure delegate security context is a collectible method - [System.Security.SecurityCritical] private Object _invocationList; - [System.Security.SecurityCritical] private IntPtr _invocationCount; // This constructor is called from the class generated by the @@ -39,19 +38,16 @@ namespace System { } - [System.Security.SecuritySafeCritical] internal bool IsUnmanagedFunctionPtr() { return (_invocationCount == (IntPtr)(-1)); } - [System.Security.SecuritySafeCritical] internal bool InvocationListLogicallyNull() { return (_invocationList == null) || (_invocationList is LoaderAllocator) || (_invocationList is DynamicResolver); } - [System.Security.SecurityCritical] public override void GetObjectData(SerializationInfo info, StreamingContext context) { int targetIndex = 0; @@ -101,7 +97,6 @@ namespace System // equals returns true IIF the delegate is not null and has the // same target, method and invocation list as this object - [System.Security.SecuritySafeCritical] // auto-generated public override sealed bool Equals(Object obj) { if (obj == null) @@ -114,7 +109,7 @@ namespace System // Since this is a MulticastDelegate and we know // the types are the same, obj should also be a // MulticastDelegate - Contract.Assert(obj is MulticastDelegate, "Shouldn't have failed here since we already checked the types are the same!"); + Debug.Assert(obj is MulticastDelegate, "Shouldn't have failed here since we already checked the types are the same!"); var d = JitHelpers.UnsafeCast(obj); if (_invocationCount != (IntPtr)0) @@ -151,7 +146,7 @@ namespace System } else { - Contract.Assert((_invocationList as Object[]) != null, "empty invocation list on multicast delegate"); + Debug.Assert((_invocationList as Object[]) != null, "empty invocation list on multicast delegate"); return InvocationListEquals(d); } } @@ -180,10 +175,9 @@ namespace System } // Recursive function which will check for equality of the invocation list. - [System.Security.SecuritySafeCritical] private bool InvocationListEquals(MulticastDelegate d) { - Contract.Assert(d != null && (_invocationList as Object[]) != null, "bogus delegate in multicast list comparison"); + Debug.Assert(d != null && (_invocationList as Object[]) != null, "bogus delegate in multicast list comparison"); Object[] invocationList = _invocationList as Object[]; if (d._invocationCount != _invocationCount) return false; @@ -199,7 +193,6 @@ namespace System return true; } - [System.Security.SecurityCritical] private bool TrySetSlot(Object[] a, int index, Object o) { if (a[index] == null && System.Threading.Interlocked.CompareExchange(ref a[index], o, null) == null) @@ -222,7 +215,6 @@ namespace System return false; } - [System.Security.SecurityCritical] private MulticastDelegate NewMulticastDelegate(Object[] invocationList, int invocationCount, bool thisIsMultiCastAlready) { // First, allocate a new multicast delegate just like this one, i.e. same type as the this object @@ -247,18 +239,16 @@ namespace System return result; } - [System.Security.SecurityCritical] internal MulticastDelegate NewMulticastDelegate(Object[] invocationList, int invocationCount) { return NewMulticastDelegate(invocationList, invocationCount, false); } - [System.Security.SecurityCritical] internal void StoreDynamicMethod(MethodInfo dynamicMethod) { if (_invocationCount != (IntPtr)0) { - Contract.Assert(!IsUnmanagedFunctionPtr(), "dynamic method and unmanaged fntptr delegate combined"); + Debug.Assert(!IsUnmanagedFunctionPtr(), "dynamic method and unmanaged fntptr delegate combined"); // must be a secure/wrapper one, unwrap and save MulticastDelegate d = (MulticastDelegate)_invocationList; d._methodBase = dynamicMethod; @@ -270,7 +260,6 @@ namespace System // This method will combine this delegate with the passed delegate // to form a new delegate. - [System.Security.SecuritySafeCritical] // auto-generated protected override sealed Delegate CombineImpl(Delegate follow) { if ((Object)follow == null) // cast to object for a more efficient test @@ -356,7 +345,6 @@ namespace System } } - [System.Security.SecurityCritical] private Object[] DeleteFromInvocationList(Object[] invocationList, int invocationCount, int deleteIndex, int deleteCount) { Object[] thisInvocationList = _invocationList as Object[]; @@ -390,7 +378,6 @@ namespace System // look at the invocation list.) If this is found we remove it from // this list and return a new delegate. If its not found a copy of the // current list is returned. - [System.Security.SecuritySafeCritical] // auto-generated protected override sealed Delegate RemoveImpl(Delegate value) { // There is a special case were we are removing using a delegate as @@ -464,7 +451,6 @@ namespace System } // This method returns the Invocation list of this multicast delegate. - [System.Security.SecuritySafeCritical] public override sealed Delegate[] GetInvocationList() { Contract.Ensures(Contract.Result() != null); @@ -505,7 +491,6 @@ namespace System return !d1.Equals(d2); } - [System.Security.SecuritySafeCritical] public override sealed int GetHashCode() { if (IsUnmanagedFunctionPtr()) @@ -528,7 +513,6 @@ namespace System } } - [System.Security.SecuritySafeCritical] internal override Object GetTarget() { if (_invocationCount != (IntPtr)0) @@ -562,7 +546,6 @@ namespace System return base.GetTarget(); } - [System.Security.SecuritySafeCritical] protected override MethodInfo GetMethodImpl() { if (_invocationCount != (IntPtr)0 && _invocationList != null) @@ -613,7 +596,6 @@ namespace System throw new ArgumentException(Environment.GetResourceString("Arg_DlgtNullInst")); } - [System.Security.SecurityCritical] [System.Diagnostics.DebuggerNonUserCode] private void CtorClosed(Object target, IntPtr methodPtr) { @@ -623,7 +605,6 @@ namespace System this._methodPtr = methodPtr; } - [System.Security.SecurityCritical] [System.Diagnostics.DebuggerNonUserCode] private void CtorClosedStatic(Object target, IntPtr methodPtr) { @@ -631,7 +612,6 @@ namespace System this._methodPtr = methodPtr; } - [System.Security.SecurityCritical] // auto-generated [System.Diagnostics.DebuggerNonUserCode] private void CtorRTClosed(Object target, IntPtr methodPtr) { @@ -639,7 +619,6 @@ namespace System this._methodPtr = AdjustTarget(target, methodPtr); } - [System.Security.SecurityCritical] [System.Diagnostics.DebuggerNonUserCode] private void CtorOpened(Object target, IntPtr methodPtr, IntPtr shuffleThunk) { @@ -648,7 +627,6 @@ namespace System this._methodPtrAux = methodPtr; } - [System.Security.SecurityCritical] // auto-generated [System.Diagnostics.DebuggerNonUserCode] private void CtorSecureClosed(Object target, IntPtr methodPtr, IntPtr callThunk, IntPtr creatorMethod) { @@ -661,7 +639,6 @@ namespace System this._invocationCount = GetInvokeMethod(); } - [System.Security.SecurityCritical] // auto-generated [System.Diagnostics.DebuggerNonUserCode] private void CtorSecureClosedStatic(Object target, IntPtr methodPtr, IntPtr callThunk, IntPtr creatorMethod) { @@ -674,7 +651,6 @@ namespace System this._invocationCount = GetInvokeMethod(); } - [System.Security.SecurityCritical] // auto-generated [System.Diagnostics.DebuggerNonUserCode] private void CtorSecureRTClosed(Object target, IntPtr methodPtr, IntPtr callThunk, IntPtr creatorMethod) { @@ -687,7 +663,6 @@ namespace System this._invocationCount = GetInvokeMethod(); } - [System.Security.SecurityCritical] // auto-generated [System.Diagnostics.DebuggerNonUserCode] private void CtorSecureOpened(Object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr callThunk, IntPtr creatorMethod) { @@ -700,7 +675,6 @@ namespace System this._invocationCount = GetInvokeMethod(); } - [System.Security.SecurityCritical] // auto-generated [System.Diagnostics.DebuggerNonUserCode] private void CtorVirtualDispatch(Object target, IntPtr methodPtr, IntPtr shuffleThunk) { @@ -709,7 +683,6 @@ namespace System this._methodPtrAux = GetCallStub(methodPtr); } - [System.Security.SecurityCritical] // auto-generated [System.Diagnostics.DebuggerNonUserCode] private void CtorSecureVirtualDispatch(Object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr callThunk, IntPtr creatorMethod) { @@ -722,7 +695,6 @@ namespace System this._invocationCount = GetInvokeMethod(); } - [System.Security.SecurityCritical] // auto-generated [System.Diagnostics.DebuggerNonUserCode] private void CtorCollectibleClosedStatic(Object target, IntPtr methodPtr, IntPtr gchandle) { @@ -731,7 +703,6 @@ namespace System this._methodBase = System.Runtime.InteropServices.GCHandle.InternalGet(gchandle); } - [System.Security.SecurityCritical] // auto-generated [System.Diagnostics.DebuggerNonUserCode] private void CtorCollectibleOpened(Object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr gchandle) { @@ -741,7 +712,6 @@ namespace System this._methodBase = System.Runtime.InteropServices.GCHandle.InternalGet(gchandle); } - [System.Security.SecurityCritical] // auto-generated [System.Diagnostics.DebuggerNonUserCode] private void CtorCollectibleVirtualDispatch(Object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr gchandle) { diff --git a/src/mscorlib/src/System/NotFiniteNumberException.cs b/src/mscorlib/src/System/NotFiniteNumberException.cs index a3d455a..3a896ce 100644 --- a/src/mscorlib/src/System/NotFiniteNumberException.cs +++ b/src/mscorlib/src/System/NotFiniteNumberException.cs @@ -57,10 +57,9 @@ namespace System { get { return _offendingNumber; } } - [System.Security.SecurityCritical] // auto-generated_required public override void GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); base.GetObjectData(info, context); diff --git a/src/mscorlib/src/System/Nullable.cs b/src/mscorlib/src/System/Nullable.cs index 2091e20..8a22c8e 100644 --- a/src/mscorlib/src/System/Nullable.cs +++ b/src/mscorlib/src/System/Nullable.cs @@ -130,7 +130,7 @@ namespace System // Otherwise, returns the underlying type of the Nullable type public static Type GetUnderlyingType(Type nullableType) { if((object)nullableType == null) { - throw new ArgumentNullException("nullableType"); + throw new ArgumentNullException(nameof(nullableType)); } Contract.EndContractBlock(); Type result = null; diff --git a/src/mscorlib/src/System/Number.cs b/src/mscorlib/src/System/Number.cs index 3c1215d..3412c02 100644 --- a/src/mscorlib/src/System/Number.cs +++ b/src/mscorlib/src/System/Number.cs @@ -11,6 +11,7 @@ namespace System { using System.Runtime.Versioning; using System.Security; using System.Text; + using System.Diagnostics; using System.Diagnostics.Contracts; // The Number class implements methods for formatting and parsing @@ -289,38 +290,28 @@ namespace System { private Number() { } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern String FormatDecimal(Decimal value, String format, NumberFormatInfo info); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern String FormatDouble(double value, String format, NumberFormatInfo info); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern String FormatInt32(int value, String format, NumberFormatInfo info); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern String FormatUInt32(uint value, String format, NumberFormatInfo info); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern String FormatInt64(long value, String format, NumberFormatInfo info); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern String FormatUInt64(ulong value, String format, NumberFormatInfo info); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern String FormatSingle(float value, String format, NumberFormatInfo info); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public unsafe static extern Boolean NumberBufferToDecimal(byte* number, ref Decimal value); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal unsafe static extern Boolean NumberBufferToDouble(byte* number, ref Double value); [MethodImplAttribute(MethodImplOptions.InternalCall)] [System.Runtime.CompilerServices.FriendAccessAllowed] - [System.Security.SecurityCritical] // auto-generated internal static extern unsafe string FormatNumberBuffer(byte* number, string format, NumberFormatInfo info, char* allDigits); // Constants used by number parsing @@ -350,15 +341,12 @@ namespace System { // Enough space for NumberMaxDigit characters plus null and 3 32 bit integers and a pointer public static readonly Int32 NumberBufferBytes = 12 + ((NumberMaxDigits + 1) * 2) + IntPtr.Size; - [SecurityCritical] private Byte * baseAddress; - [SecurityCritical] public Char * digits; public Int32 precision; public Int32 scale; public Boolean sign; - [System.Security.SecurityCritical] // auto-generated public NumberBuffer(Byte* stackBuffer) { this.baseAddress = stackBuffer; this.digits = (((Char*) stackBuffer) + 6); @@ -367,7 +355,6 @@ namespace System { this.sign = false; } - [System.Security.SecurityCritical] // auto-generated public Byte* PackForNative() { Int32* baseInteger = (Int32*) baseAddress; baseInteger[0] = precision; @@ -391,7 +378,6 @@ namespace System { return returnValue; } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe static Boolean HexNumberToUInt32(ref NumberBuffer number, ref UInt32 value) { Int32 i = number.scale; @@ -399,7 +385,7 @@ namespace System { return false; } Char* p = number.digits; - Contract.Assert(p != null, ""); + Debug.Assert(p != null, ""); UInt32 n = 0; while (--i >= 0) { @@ -418,7 +404,7 @@ namespace System { newN += (UInt32)((*p - 'A') + 10); } else { - Contract.Assert(*p >= 'a' && *p <= 'f', ""); + Debug.Assert(*p >= 'a' && *p <= 'f', ""); newN += (UInt32)((*p - 'a') + 10); } } @@ -436,7 +422,6 @@ namespace System { return true; } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe static Boolean HexNumberToUInt64(ref NumberBuffer number, ref UInt64 value) { Int32 i = number.scale; @@ -444,7 +429,7 @@ namespace System { return false; } Char* p = number.digits; - Contract.Assert(p != null, ""); + Debug.Assert(p != null, ""); UInt64 n = 0; while (--i >= 0) { @@ -463,7 +448,7 @@ namespace System { newN += (UInt64)((*p - 'A') + 10); } else { - Contract.Assert(*p >= 'a' && *p <= 'f', ""); + Debug.Assert(*p >= 'a' && *p <= 'f', ""); newN += (UInt64)((*p - 'a') + 10); } } @@ -485,7 +470,6 @@ namespace System { return (((ch) == 0x20) || ((ch) >= 0x09 && (ch) <= 0x0D)); } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe static Boolean NumberToInt32(ref NumberBuffer number, ref Int32 value) { Int32 i = number.scale; @@ -493,7 +477,7 @@ namespace System { return false; } char * p = number.digits; - Contract.Assert(p != null, ""); + Debug.Assert(p != null, ""); Int32 n = 0; while (--i >= 0) { if ((UInt32)n > (0x7FFFFFFF / 10)) { @@ -519,7 +503,6 @@ namespace System { return true; } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe static Boolean NumberToInt64(ref NumberBuffer number, ref Int64 value) { Int32 i = number.scale; @@ -527,7 +510,7 @@ namespace System { return false; } char* p = number.digits; - Contract.Assert(p != null, ""); + Debug.Assert(p != null, ""); Int64 n = 0; while (--i >= 0) { if ((UInt64)n > (0x7FFFFFFFFFFFFFFF / 10)) { @@ -553,7 +536,6 @@ namespace System { return true; } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe static Boolean NumberToUInt32(ref NumberBuffer number, ref UInt32 value) { Int32 i = number.scale; @@ -561,7 +543,7 @@ namespace System { return false; } char* p = number.digits; - Contract.Assert(p != null, ""); + Debug.Assert(p != null, ""); UInt32 n = 0; while (--i >= 0) { if (n > (0xFFFFFFFF / 10)) { @@ -581,7 +563,6 @@ namespace System { return true; } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe static Boolean NumberToUInt64(ref NumberBuffer number, ref UInt64 value) { Int32 i = number.scale; @@ -589,7 +570,7 @@ namespace System { return false; } char * p = number.digits; - Contract.Assert(p != null, ""); + Debug.Assert(p != null, ""); UInt64 n = 0; while (--i >= 0) { if (n > (0xFFFFFFFFFFFFFFFF / 10)) { @@ -609,32 +590,29 @@ namespace System { return true; } - [System.Security.SecurityCritical] // auto-generated private unsafe static char * MatchChars(char* p, string str) { fixed (char* stringPointer = str) { return MatchChars(p, stringPointer); } } - [System.Security.SecurityCritical] // auto-generated private unsafe static char * MatchChars(char* p, char* str) { - Contract.Assert(p != null && str != null, ""); + Debug.Assert(p != null && str != null, ""); if (*str == '\0') { return null; } - for (; (*str != '\0'); p++, str++) { - if (*p != *str) { //We only hurt the failure case - if ((*str == '\u00A0') && (*p == '\u0020')) {// This fix is for French or Kazakh cultures. Since a user cannot type 0xA0 as a - // space character we use 0x20 space character instead to mean the same. - continue; - } - return null; - } + // We only hurt the failure case + // This fix is for French or Kazakh cultures. Since a user cannot type 0xA0 as a + // space character we use 0x20 space character instead to mean the same. + while (*p == *str || (*str == '\u00a0' && *p == '\u0020')) + { + p++; + str++; + if (*str == '\0') return p; } - return p; + return null; } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static Decimal ParseDecimal(String value, NumberStyles options, NumberFormatInfo numfmt) { Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes]; @@ -649,10 +627,9 @@ namespace System { return result; } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static Double ParseDouble(String value, NumberStyles options, NumberFormatInfo numfmt) { if (value == null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes]; @@ -683,7 +660,6 @@ namespace System { return d; } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static Int32 ParseInt32(String s, NumberStyles style, NumberFormatInfo info) { Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes]; @@ -705,7 +681,6 @@ namespace System { return i; } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static Int64 ParseInt64(String value, NumberStyles options, NumberFormatInfo numfmt) { Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes]; NumberBuffer number = new NumberBuffer(numberBufferBytes); @@ -726,7 +701,6 @@ namespace System { return i; } - [System.Security.SecurityCritical] // auto-generated private unsafe static Boolean ParseNumber(ref char * str, NumberStyles options, ref NumberBuffer number, StringBuilder sb, NumberFormatInfo numfmt, Boolean parseDecimal) { const Int32 StateSign = 0x0001; @@ -742,26 +716,12 @@ namespace System { string groupSep; // group separator from NumberFormatInfo. string currSymbol = null; // currency symbol from NumberFormatInfo. - // The alternative currency symbol used in ANSI codepage, that can not roundtrip between ANSI and Unicode. - // Currently, only ja-JP and ko-KR has non-null values (which is U+005c, backslash) - string ansicurrSymbol = null; // currency symbol from NumberFormatInfo. - string altdecSep = null; // decimal separator from NumberFormatInfo as a decimal - string altgroupSep = null; // group separator from NumberFormatInfo as a decimal - Boolean parsingCurrency = false; if ((options & NumberStyles.AllowCurrencySymbol) != 0) { currSymbol = numfmt.CurrencySymbol; -#if !FEATURE_COREFX_GLOBALIZATION - if (numfmt.ansiCurrencySymbol != null) { - ansicurrSymbol = numfmt.ansiCurrencySymbol; - } -#endif - // The idea here is to match the currency separators and on failure match the number separators to keep the perf of VB's IsNumeric fast. // The values of decSep are setup to use the correct relevant separator (currency in the if part and decimal in the else part). - altdecSep = numfmt.NumberDecimalSeparator; - altgroupSep = numfmt.NumberGroupSeparator; decSep = numfmt.CurrencyDecimalSeparator; groupSep = numfmt.CurrencyGroupSeparator; parsingCurrency = true; @@ -772,9 +732,7 @@ namespace System { } Int32 state = 0; - Boolean signflag = false; // Cache the results of "options & PARSE_LEADINGSIGN && !(state & STATE_SIGN)" to avoid doing this twice Boolean bigNumber = (sb != null); // When a StringBuilder is provided then we use it in place of the number.digits char[50] - Boolean bigNumberHex = (bigNumber && ((options & NumberStyles.AllowHexSpecifier) != 0)); Int32 maxParseDigits = bigNumber ? Int32.MaxValue : NumberMaxDigits; char* p = str; @@ -784,32 +742,26 @@ namespace System { while (true) { // Eat whitespace unless we've found a sign which isn't followed by a currency symbol. // "-Kr 1231.47" is legal but "- 1231.47" is not. - if (IsWhite(ch) && ((options & NumberStyles.AllowLeadingWhite) != 0) && (((state & StateSign) == 0) || (((state & StateSign) != 0) && (((state & StateCurrency) != 0) || numfmt.numberNegativePattern == 2)))) { - // Do nothing here. We will increase p at the end of the loop. - } - else if ((signflag = (((options & NumberStyles.AllowLeadingSign) != 0) && ((state & StateSign) == 0))) && ((next = MatchChars(p, numfmt.positiveSign)) != null)) { - state |= StateSign; - p = next - 1; - } else if (signflag && (next = MatchChars(p, numfmt.negativeSign)) != null) { - state |= StateSign; - number.sign = true; - p = next - 1; - } - else if (ch == '(' && ((options & NumberStyles.AllowParentheses) != 0) && ((state & StateSign) == 0)) { - state |= StateSign | StateParens; - number.sign = true; - } - else if ((currSymbol != null && (next = MatchChars(p, currSymbol)) != null) || (ansicurrSymbol != null && (next = MatchChars(p, ansicurrSymbol)) != null)) { - state |= StateCurrency; - currSymbol = null; - ansicurrSymbol = null; - // We already found the currency symbol. There should not be more currency symbols. Set - // currSymbol to NULL so that we won't search it again in the later code path. - p = next - 1; - } - else { - break; - } + if (!IsWhite(ch) || (options & NumberStyles.AllowLeadingWhite) == 0 || ((state & StateSign) != 0 && ((state & StateCurrency) == 0 && numfmt.NumberNegativePattern != 2))){ + if ((((options & NumberStyles.AllowLeadingSign) != 0) && (state & StateSign) == 0) && ((next = MatchChars(p, numfmt.PositiveSign)) != null || ((next = MatchChars(p, numfmt.NegativeSign)) != null && (number.sign = true)))){ + state |= StateSign; + p = next - 1; + } + else if (ch == '(' && ((options & NumberStyles.AllowParentheses) != 0) && ((state & StateSign) == 0)) { + state |= StateSign | StateParens; + number.sign = true; + } + else if (currSymbol != null && (next = MatchChars(p, currSymbol)) != null) { + state |= StateCurrency; + currSymbol = null; + // We already found the currency symbol. There should not be more currency symbols. Set + // currSymbol to NULL so that we won't search it again in the later code path. + p = next - 1; + } + else { + break; + } + } ch = *++p; } Int32 digCount = 0; @@ -818,7 +770,7 @@ namespace System { if ((ch >= '0' && ch <= '9') || (((options & NumberStyles.AllowHexSpecifier) != 0) && ((ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')))) { state |= StateDigits; - if (ch != '0' || (state & StateNonZero) != 0 || bigNumberHex) { + if (ch != '0' || (state & StateNonZero) != 0 || (bigNumber && ((options & NumberStyles.AllowHexSpecifier) != 0))) { if (digCount < maxParseDigits) { if (bigNumber) sb.Append(ch); @@ -837,11 +789,11 @@ namespace System { number.scale--; } } - else if (((options & NumberStyles.AllowDecimalPoint) != 0) && ((state & StateDecimal) == 0) && ((next = MatchChars(p, decSep)) != null || ((parsingCurrency) && (state & StateCurrency) == 0) && (next = MatchChars(p, altdecSep)) != null)) { + else if (((options & NumberStyles.AllowDecimalPoint) != 0) && ((state & StateDecimal) == 0) && ((next = MatchChars(p, decSep)) != null || ((parsingCurrency) && (state & StateCurrency) == 0) && (next = MatchChars(p, numfmt.NumberDecimalSeparator)) != null)) { state |= StateDecimal; p = next - 1; } - else if (((options & NumberStyles.AllowThousands) != 0) && ((state & StateDigits) != 0) && ((state & StateDecimal) == 0) && ((next = MatchChars(p, groupSep)) != null || ((parsingCurrency) && (state & StateCurrency) == 0) && (next = MatchChars(p, altgroupSep)) != null)) { + else if (((options & NumberStyles.AllowThousands) != 0) && ((state & StateDigits) != 0) && ((state & StateDecimal) == 0) && ((next = MatchChars(p, groupSep)) != null || ((parsingCurrency) && (state & StateCurrency) == 0) && (next = MatchChars(p, numfmt.NumberGroupSeparator)) != null)) { p = next - 1; } else { @@ -890,27 +842,22 @@ namespace System { } } while (true) { - if (IsWhite(ch) && ((options & NumberStyles.AllowTrailingWhite) != 0)) { - } - else if ((signflag = (((options & NumberStyles.AllowTrailingSign) != 0) && ((state & StateSign) == 0))) && (next = MatchChars(p, numfmt.positiveSign)) != null) { - state |= StateSign; - p = next - 1; - } else if (signflag && (next = MatchChars(p, numfmt.negativeSign)) != null) { - state |= StateSign; - number.sign = true; - p = next - 1; - } - else if (ch == ')' && ((state & StateParens) != 0)) { - state &= ~StateParens; - } - else if ((currSymbol != null && (next = MatchChars(p, currSymbol)) != null) || (ansicurrSymbol != null && (next = MatchChars(p, ansicurrSymbol)) != null)) { - currSymbol = null; - ansicurrSymbol = null; - p = next - 1; - } - else { - break; - } + if (!IsWhite(ch) || (options & NumberStyles.AllowTrailingWhite) == 0){ + if (((options & NumberStyles.AllowTrailingSign) != 0 && ((state & StateSign) == 0)) && ((next = MatchChars(p, numfmt.PositiveSign)) != null || (((next = MatchChars(p, numfmt.NegativeSign)) != null) && (number.sign = true)))) { + state |= StateSign; + p = next - 1; + } + else if (ch == ')' && ((state & StateParens) != 0)) { + state &= ~StateParens; + } + else if (currSymbol != null && (next = MatchChars(p, currSymbol)) != null) { + currSymbol = null; + p = next - 1; + } + else { + break; + } + } ch = *++p; } if ((state & StateParens) == 0) { @@ -930,10 +877,9 @@ namespace System { return false; } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static Single ParseSingle(String value, NumberStyles options, NumberFormatInfo numfmt) { if (value == null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes]; @@ -967,7 +913,6 @@ namespace System { return castSingle; } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static UInt32 ParseUInt32(String value, NumberStyles options, NumberFormatInfo numfmt) { Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes]; @@ -990,7 +935,6 @@ namespace System { return i; } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static UInt64 ParseUInt64(String value, NumberStyles options, NumberFormatInfo numfmt) { Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes]; NumberBuffer number = new NumberBuffer(numberBufferBytes); @@ -1010,14 +954,13 @@ namespace System { return i; } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe static void StringToNumber(String str, NumberStyles options, ref NumberBuffer number, NumberFormatInfo info, Boolean parseDecimal) { if (str == null) { - throw new ArgumentNullException("String"); + throw new ArgumentNullException(nameof(String)); } Contract.EndContractBlock(); - Contract.Assert(info != null, ""); + Debug.Assert(info != null, ""); fixed (char* stringPointer = str) { char * p = stringPointer; if (!ParseNumber(ref p, options, ref number, null, info , parseDecimal) @@ -1037,7 +980,6 @@ namespace System { return true; } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static Boolean TryParseDecimal(String value, NumberStyles options, NumberFormatInfo numfmt, out Decimal result) { Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes]; @@ -1054,7 +996,6 @@ namespace System { return true; } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static Boolean TryParseDouble(String value, NumberStyles options, NumberFormatInfo numfmt, out Double result) { Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes]; NumberBuffer number = new NumberBuffer(numberBufferBytes); @@ -1070,7 +1011,6 @@ namespace System { return true; } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static Boolean TryParseInt32(String s, NumberStyles style, NumberFormatInfo info, out Int32 result) { Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes]; @@ -1094,7 +1034,6 @@ namespace System { return true; } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static Boolean TryParseInt64(String s, NumberStyles style, NumberFormatInfo info, out Int64 result) { Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes]; @@ -1118,7 +1057,6 @@ namespace System { return true; } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static Boolean TryParseSingle(String value, NumberStyles options, NumberFormatInfo numfmt, out Single result) { Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes]; NumberBuffer number = new NumberBuffer(numberBufferBytes); @@ -1140,7 +1078,6 @@ namespace System { return true; } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static Boolean TryParseUInt32(String s, NumberStyles style, NumberFormatInfo info, out UInt32 result) { Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes]; @@ -1164,7 +1101,6 @@ namespace System { return true; } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static Boolean TryParseUInt64(String s, NumberStyles style, NumberFormatInfo info, out UInt64 result) { Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes]; @@ -1192,14 +1128,13 @@ namespace System { return TryStringToNumber(str, options, ref number, null, numfmt, parseDecimal); } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.CompilerServices.FriendAccessAllowed] internal unsafe static Boolean TryStringToNumber(String str, NumberStyles options, ref NumberBuffer number, StringBuilder sb, NumberFormatInfo numfmt, Boolean parseDecimal) { if (str == null) { return false; } - Contract.Assert(numfmt != null, ""); + Debug.Assert(numfmt != null, ""); fixed (char* stringPointer = str) { char * p = stringPointer; diff --git a/src/mscorlib/src/System/Numerics/Hashing/HashHelpers.cs b/src/mscorlib/src/System/Numerics/Hashing/HashHelpers.cs new file mode 100644 index 0000000..0314d1a --- /dev/null +++ b/src/mscorlib/src/System/Numerics/Hashing/HashHelpers.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. +// See the LICENSE file in the project root for more information. + +namespace System.Numerics.Hashing +{ + // Please change the corresponding file in corefx if this is changed. + + internal static class HashHelpers + { + public static int Combine(int h1, int h2) + { + // The jit optimizes this to use the ROL instruction on x86 + // Related GitHub pull request: dotnet/coreclr#1830 + uint shift5 = ((uint)h1 << 5) | ((uint)h1 >> 27); + return ((int)shift5 + h1) ^ h2; + } + } +} diff --git a/src/mscorlib/src/System/Object.cs b/src/mscorlib/src/System/Object.cs index 769c5a6..d8d9a0e 100644 --- a/src/mscorlib/src/System/Object.cs +++ b/src/mscorlib/src/System/Object.cs @@ -12,7 +12,8 @@ ** ===========================================================*/ -namespace System { +namespace System +{ using System; using System.Runtime; using System.Runtime.InteropServices; @@ -23,9 +24,7 @@ namespace System { using CultureInfo = System.Globalization.CultureInfo; using FieldInfo = System.Reflection.FieldInfo; using BindingFlags = System.Reflection.BindingFlags; -#if FEATURE_REMOTING - using RemotingException = System.Runtime.Remoting.RemotingException; -#endif + // The Object is the root class for all object in the CLR System. Object // is the super class for all other CLR objects and provide a set of methods and low level // services to subclasses. These services include object synchronization and support for clone @@ -96,7 +95,6 @@ public class Object // Returns a Type object which represent this object instance. // - [System.Security.SecuritySafeCritical] // auto-generated [Pure] [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern Type GetType(); @@ -114,14 +112,12 @@ public class Object // so that other object may only call this method on themselves. It is entended to // support the ICloneable interface. // - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] protected extern Object MemberwiseClone(); // Sets the value specified in the variant on the field // - [System.Security.SecurityCritical] // auto-generated private void FieldSetter(String typeName, String fieldName, Object val) { Contract.Requires(typeName != null); @@ -135,26 +131,21 @@ public class Object // Make sure that the value is compatible with the type // of field -#if FEATURE_REMOTING - System.Runtime.Remoting.Messaging.Message.CoerceArg(val, fldInfo.FieldType); -#else Type pt=fldInfo.FieldType; if (pt.IsByRef) { pt = pt.GetElementType(); } - + if (!pt.IsInstanceOfType(val)) { val = Convert.ChangeType(val, pt, CultureInfo.InvariantCulture); } -#endif - - // Set the value + // Set the value fldInfo.SetValue(this, val); } - + // Gets the value specified in the variant on the field // private void FieldGetter(String typeName, String fieldName, ref Object val) @@ -166,7 +157,7 @@ public class Object FieldInfo fldInfo = GetFieldInfo(typeName, fieldName); // Get the value - val = fldInfo.GetValue(this); + val = fldInfo.GetValue(this); } // Gets the field info object given the type name and field name. @@ -190,13 +181,7 @@ public class Object if (null == t) { -#if FEATURE_REMOTING - throw new RemotingException(String.Format( - CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_BadType"), - typeName)); -#else throw new ArgumentException(); -#endif } FieldInfo fldInfo = t.GetField(fieldName, BindingFlags.Public | @@ -204,16 +189,9 @@ public class Object BindingFlags.IgnoreCase); if(null == fldInfo) { -#if FEATURE_REMOTING - throw new RemotingException(String.Format( - CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_BadField"), - fieldName, typeName)); -#else throw new ArgumentException(); -#endif - } - + return fldInfo; } } @@ -233,22 +211,16 @@ internal class __Canon // This class is used to define the name of the base class library internal class CoreLib { - -#if FEATURE_CORECLR public const string Name = "System.Private.CoreLib"; -#else - public const string Name = "mscorlib"; -#endif public static string FixupCoreLibName(string strToFixup) { -#if FEATURE_CORECLR if (!String.IsNullOrEmpty(strToFixup)) { strToFixup = strToFixup.Replace("mscorlib", System.CoreLib.Name); } -#endif - return strToFixup; + + return strToFixup; } } diff --git a/src/mscorlib/src/System/ObjectDisposedException.cs b/src/mscorlib/src/System/ObjectDisposedException.cs index cf92cef..d2eca37 100644 --- a/src/mscorlib/src/System/ObjectDisposedException.cs +++ b/src/mscorlib/src/System/ObjectDisposedException.cs @@ -64,7 +64,6 @@ namespace System { objectName = info.GetString("ObjectName"); } - [System.Security.SecurityCritical] // auto-generated_required public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); info.AddValue("ObjectName",ObjectName,typeof(String)); diff --git a/src/mscorlib/src/System/OleAutBinder.cs b/src/mscorlib/src/System/OleAutBinder.cs index 1ed1e32..acae95a 100644 --- a/src/mscorlib/src/System/OleAutBinder.cs +++ b/src/mscorlib/src/System/OleAutBinder.cs @@ -20,7 +20,6 @@ namespace System { { // ChangeType // This binder uses OLEAUT to change the type of the variant. - [System.Security.SecuritySafeCritical] // overrides transparent member public override Object ChangeType(Object value, Type type, CultureInfo cultureInfo) { Variant myValue = new Variant(value); @@ -60,24 +59,6 @@ namespace System { return Enum.Parse(type, value.ToString()); } -#if !FEATURE_CORECLR - // Special case the convertion from DBNull. - if (srcType == typeof(DBNull)) - { - // The requested type is a DBNull so no convertion is required. - if (type == typeof(DBNull)) - return value; - - // Visual J++ supported converting from DBNull to null so customers - // have requested (via a CDCR) that DBNull be convertible to null. - // We don't however allow this when converting to a value class, since null - // doesn't make sense for these, or to object since this would change existing - // semantics. - if ((type.IsClass && type != typeof(Object)) || type.IsInterface) - return null; - } -#endif //!FEATURE_CORECLR - // Use the OA variant lib to convert primitive types. try { @@ -107,7 +88,5 @@ namespace System { throw new COMException(Environment.GetResourceString("Interop.COM_TypeMismatch"), unchecked((int)0x80020005)); } } - - } } diff --git a/src/mscorlib/src/System/OperatingSystem.cs b/src/mscorlib/src/System/OperatingSystem.cs index 6955310..a11d4bc 100644 --- a/src/mscorlib/src/System/OperatingSystem.cs +++ b/src/mscorlib/src/System/OperatingSystem.cs @@ -38,11 +38,11 @@ namespace System { if( platform < PlatformID.Win32S || platform > PlatformID.MacOSX) { throw new ArgumentException( Environment.GetResourceString("Arg_EnumIllegalVal", (int)platform), - "platform"); + nameof(platform)); } if ((Object) version == null) - throw new ArgumentNullException("version"); + throw new ArgumentNullException(nameof(version)); Contract.EndContractBlock(); _platform = platform; @@ -71,10 +71,9 @@ namespace System { } } - [System.Security.SecurityCritical] // auto-generated_required public void GetObjectData(SerializationInfo info, StreamingContext context) { if( info == null ) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/ParseNumbers.cs b/src/mscorlib/src/System/ParseNumbers.cs index 01c2ae3..2a375f7 100644 --- a/src/mscorlib/src/System/ParseNumbers.cs +++ b/src/mscorlib/src/System/ParseNumbers.cs @@ -33,41 +33,33 @@ namespace System { // NATIVE METHODS // For comments on these methods please see $\src\vm\COMUtilNative.cpp // - [System.Security.SecuritySafeCritical] // auto-generated public unsafe static long StringToLong(System.String s, int radix, int flags) { return StringToLong(s,radix,flags, null); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public unsafe extern static long StringToLong(System.String s, int radix, int flags, int* currPos); - [System.Security.SecuritySafeCritical] // auto-generated public unsafe static long StringToLong(System.String s, int radix, int flags, ref int currPos) { fixed(int * ppos = &currPos) { return StringToLong( s, radix, flags, ppos); } } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe static int StringToInt(System.String s, int radix, int flags) { return StringToInt(s,radix,flags, null); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public unsafe extern static int StringToInt(System.String s, int radix, int flags, int* currPos); - [System.Security.SecuritySafeCritical] // auto-generated public unsafe static int StringToInt(System.String s, int radix, int flags, ref int currPos) { fixed(int * ppos = &currPos) { return StringToInt( s, radix, flags, ppos); } } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern static String IntToString(int l, int radix, int width, char paddingChar, int flags); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern static String LongToString(long l, int radix, int width, char paddingChar, int flags); } diff --git a/src/mscorlib/src/System/Progress.cs b/src/mscorlib/src/System/Progress.cs index 8800c03..72c43c3 100644 --- a/src/mscorlib/src/System/Progress.cs +++ b/src/mscorlib/src/System/Progress.cs @@ -48,7 +48,7 @@ namespace System // sync ctx reference identity issues where the sync ctx for one thread could be Current on another. // If there is no current context, we use a default instance targeting the ThreadPool. m_synchronizationContext = SynchronizationContext.CurrentNoFlow ?? ProgressStatics.DefaultContext; - Contract.Assert(m_synchronizationContext != null); + Debug.Assert(m_synchronizationContext != null); m_invokeHandlers = new SendOrPostCallback(InvokeHandlers); } @@ -63,7 +63,7 @@ namespace System /// The is null (Nothing in Visual Basic). public Progress(Action handler) : this() { - if (handler == null) throw new ArgumentNullException("handler"); + if (handler == null) throw new ArgumentNullException(nameof(handler)); m_handler = handler; } diff --git a/src/mscorlib/src/System/Random.cs b/src/mscorlib/src/System/Random.cs index adede6a..f5941d6 100644 --- a/src/mscorlib/src/System/Random.cs +++ b/src/mscorlib/src/System/Random.cs @@ -11,13 +11,14 @@ ** ===========================================================*/ namespace System { - + using System; using System.Runtime; using System.Runtime.CompilerServices; using System.Globalization; using System.Diagnostics.Contracts; -[System.Runtime.InteropServices.ComVisible(true)] + + [System.Runtime.InteropServices.ComVisible(true)] [Serializable] public class Random { // @@ -46,13 +47,19 @@ namespace System { // // Constructors // - + + /*========================================================================================= + **Action: Initializes a new instance of the Random class, using a default seed value + ===========================================================================================*/ public Random() - : this(Environment.TickCount) { + : this(GenerateSeed()) { } - + + /*========================================================================================= + **Action: Initializes a new instance of the Random class, using a specified seed value + ===========================================================================================*/ public Random(int Seed) { - int ii; + int ii = 0; int mj, mk; //Initialize our Seed array. @@ -61,7 +68,7 @@ namespace System { SeedArray[55]=mj; mk=1; for (int i=1; i<55; i++) { //Apparently the range [1..55] is special (Knuth) and so we're wasting the 0'th position. - ii = (21*i)%55; + if ((ii += 21) >= 55) ii -= 55; SeedArray[ii]=mk; mk = mj - mk; if (mk<0) mk+=MBIG; @@ -69,19 +76,21 @@ namespace System { } for (int k=1; k<5; k++) { for (int i=1; i<56; i++) { - SeedArray[i] -= SeedArray[1+(i+30)%55]; - if (SeedArray[i]<0) SeedArray[i]+=MBIG; + int n = i + 30; + if (n >= 55) n -= 55; + SeedArray[i] -= SeedArray[1 + n]; + if (SeedArray[i]<0) SeedArray[i]+=MBIG; } } inext=0; inextp = 21; Seed = 1; } - + // // Package Private Methods // - + /*====================================Sample==================================== **Action: Return a new random number [0..1) and reSeed the Seed array. **Returns: A double [0..1) @@ -115,11 +124,41 @@ namespace System { return retVal; } + + [ThreadStatic] + private static Random t_threadRandom; + private static readonly Random s_globalRandom = new Random(GenerateGlobalSeed()); + + /*=====================================GenerateSeed===================================== + **Returns: An integer that can be used as seed values for consecutively + creating lots of instances on the same thread within a short period of time. + ========================================================================================*/ + private static int GenerateSeed() { + Random rnd = t_threadRandom; + if (rnd == null) { + int seed; + lock (s_globalRandom) { + seed = s_globalRandom.Next(); + } + rnd = new Random(seed); + t_threadRandom = rnd; + } + return rnd.Next(); + } + + /*==================================GenerateGlobalSeed==================================== + **Action: Creates a number to use as global seed. + **Returns: An integer that is safe to use as seed values for thread-local seed generators. + ==========================================================================================*/ + private static int GenerateGlobalSeed() { + return Guid.NewGuid().GetHashCode(); + } + // // Public Instance Methods // - - + + /*=====================================Next===================================== **Returns: An int [0..Int32.MaxValue) **Arguments: None @@ -156,7 +195,7 @@ namespace System { ==============================================================================*/ public virtual int Next(int minValue, int maxValue) { if (minValue>maxValue) { - throw new ArgumentOutOfRangeException("minValue",Environment.GetResourceString("Argument_MinMaxValue", "minValue", "maxValue")); + throw new ArgumentOutOfRangeException(nameof(minValue),Environment.GetResourceString("Argument_MinMaxValue", nameof(minValue), nameof(maxValue))); } Contract.EndContractBlock(); @@ -177,7 +216,7 @@ namespace System { ==============================================================================*/ public virtual int Next(int maxValue) { if (maxValue<0) { - throw new ArgumentOutOfRangeException("maxValue", Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", "maxValue")); + throw new ArgumentOutOfRangeException(nameof(maxValue), Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", nameof(maxValue))); } Contract.EndContractBlock(); return (int)(Sample()*maxValue); @@ -201,14 +240,11 @@ namespace System { **Exceptions: None ==============================================================================*/ public virtual void NextBytes(byte [] buffer){ - if (buffer==null) throw new ArgumentNullException("buffer"); + if (buffer==null) throw new ArgumentNullException(nameof(buffer)); Contract.EndContractBlock(); for (int i=0; i.Equals(object)' overrides non-obsolete member 'object.Equals(object)' + +namespace System +{ + /// + /// ReadOnlySpan represents contiguous read-only region of arbitrary memory, with performance + /// characteristics on par with T[]. Unlike arrays, it can point to either managed + /// or native memory, or to memory allocated on the stack. It is type- and memory-safe. + /// + public struct ReadOnlySpan + { + /// A byref or a native ptr. + private readonly ByReference _pointer; + /// The number of elements this ReadOnlySpan contains. + private readonly int _length; + + /// + /// Creates a new span over the entirety of the target array. + /// + /// The target array. + /// Thrown when is a null + /// reference (Nothing in Visual Basic). + public ReadOnlySpan(T[] array) + { + if (array == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + + _pointer = new ByReference(ref JitHelpers.GetArrayData(array)); + _length = array.Length; + } + + /// + /// Creates a new span over the portion of the target array beginning + /// at 'start' index and covering the remainder of the array. + /// + /// The target array. + /// The index at which to begin the span. + /// Thrown when is a null + /// reference (Nothing in Visual Basic). + /// + /// Thrown when the specified is not in the range (<0 or >&eq;Length). + /// + public ReadOnlySpan(T[] array, int start) + { + if (array == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + if ((uint)start > (uint)array.Length) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + _pointer = new ByReference(ref Unsafe.Add(ref JitHelpers.GetArrayData(array), start)); + _length = array.Length - start; + } + + /// + /// Creates a new span over the portion of the target array beginning + /// at 'start' index and ending at 'end' index (exclusive). + /// + /// The target array. + /// The index at which to begin the span. + /// The number of items in the span. + /// Thrown when is a null + /// reference (Nothing in Visual Basic). + /// + /// Thrown when the specified or end index is not in the range (<0 or >&eq;Length). + /// + public ReadOnlySpan(T[] array, int start, int length) + { + if (array == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start)) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + _pointer = new ByReference(ref Unsafe.Add(ref JitHelpers.GetArrayData(array), start)); + _length = length; + } + + /// + /// Creates a new span over the target unmanaged buffer. Clearly this + /// is quite dangerous, because we are creating arbitrarily typed T's + /// out of a void*-typed block of memory. And the length is not checked. + /// But if this creation is correct, then all subsequent uses are correct. + /// + /// An unmanaged pointer to memory. + /// The number of elements the memory contains. + /// + /// Thrown when is reference type or contains pointers and hence cannot be stored in unmanaged memory. + /// + /// + /// Thrown when the specified is negative. + /// + [CLSCompliant(false)] + public unsafe ReadOnlySpan(void* pointer, int length) + { + if (JitHelpers.ContainsReferences()) + ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T)); + if (length < 0) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + _pointer = new ByReference(ref Unsafe.As(ref *(byte*)pointer)); + _length = length; + } + + /// + /// An internal helper for creating spans. + /// + internal ReadOnlySpan(ref T ptr, int length) + { + _pointer = new ByReference(ref ptr); + _length = length; + } + + /// + /// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to the location where the 0th element + /// would have been stored. Such a reference can be used for pinning but must never be dereferenced. + /// + public ref T DangerousGetPinnableReference() + { + return ref _pointer.Value; + } + + /// + /// This method is not supported as spans cannot be boxed. To compare two spans, use operator==. + /// + /// Always thrown by this method. + /// + /// + [Obsolete("Equals() on Span will always throw an exception. Use == instead.")] + public override bool Equals(object obj) + { + ThrowHelper.ThrowNotSupportedException_CannotCallEqualsOnSpan(); + // Prevent compiler error CS0161: 'Span.Equals(object)': not all code paths return a value + return default(bool); + } + + /// + /// This method is not supported as spans cannot be boxed. + /// + /// Always thrown by this method. + /// + /// + [Obsolete("GetHashCode() on Span will always throw an exception.")] + public override int GetHashCode() + { + ThrowHelper.ThrowNotSupportedException_CannotCallGetHashCodeOnSpan(); + // Prevent compiler error CS0161: 'Span.GetHashCode()': not all code paths return a value + return default(int); + } + + /// + /// Create a new read-only span over a portion of a regular managed object. This can be useful + /// if part of a managed object represents a "fixed array." This is dangerous because + /// "length" is not checked, nor is the fact that "rawPointer" actually lies within the object. + /// + /// The managed object that contains the data to span over. + /// A reference to data within that object. + /// The number of elements the memory contains. + /// + /// Thrown when the specified object is null. + /// + /// + /// Thrown when the specified is negative. + /// + public static ReadOnlySpan DangerousCreate(object obj, ref T objectData, int length) + { + if (obj == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.obj); + if (length < 0) + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length); + + return new ReadOnlySpan(ref objectData, length); + } + + /// + /// Defines an implicit conversion of a to a + /// + public static implicit operator ReadOnlySpan(Span slice) + { + return new ReadOnlySpan(ref slice.DangerousGetPinnableReference(), slice.Length); + } + + /// + /// Defines an implicit conversion of an array to a + /// + public static implicit operator ReadOnlySpan(T[] array) + { + return new ReadOnlySpan(array); + } + + /// + /// Defines an implicit conversion of a to a + /// + public static implicit operator ReadOnlySpan(ArraySegment arraySegment) + { + return new ReadOnlySpan(arraySegment.Array, arraySegment.Offset, arraySegment.Count); + } + + /// + /// Gets the number of elements contained in the + /// + public int Length + { + get { return _length; } + } + + /// + /// Returns an empty + /// + public static ReadOnlySpan Empty + { + get { return default(ReadOnlySpan); } + } + + /// + /// Returns whether the is empty. + /// + public bool IsEmpty + { + get { return _length == 0; } + } + + /// + /// Fetches the element at the specified index. + /// + /// + /// Thrown when the specified is not in range (<0 or >&eq;Length). + /// + public T this[int index] + { + get + { + if ((uint)index >= (uint)_length) + ThrowHelper.ThrowIndexOutOfRangeException(); + + return Unsafe.Add(ref DangerousGetPinnableReference(), index); + } + } + + /// + /// Copies the contents of this span into a new array. This heap + /// allocates, so should generally be avoided, however is sometimes + /// necessary to bridge the gap with APIs written in terms of arrays. + /// + public T[] ToArray() + { + if (_length == 0) + return Array.Empty(); + + var destination = new T[_length]; + SpanHelper.CopyTo(ref JitHelpers.GetArrayData(destination), ref DangerousGetPinnableReference(), _length); + return destination; + } + + /// + /// Forms a slice out of the given span, beginning at 'start'. + /// + /// The index at which to begin this slice. + /// + /// Thrown when the specified index is not in range (<0 or >length). + /// + [MethodImpl(MethodImplOptions.NoOptimization)] // TODO-SPAN: Workaround for https://github.com/dotnet/coreclr/issues/7894 + public ReadOnlySpan Slice(int start) + { + if ((uint)start > (uint)_length) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + return new ReadOnlySpan(ref Unsafe.Add(ref DangerousGetPinnableReference(), start), _length - start); + } + + /// + /// Forms a slice out of the given span, beginning at 'start', of given length + /// + /// The index at which to begin this slice. + /// The index at which to end this slice (exclusive). + /// + /// Thrown when the specified or end index is not in range (<0 or >&eq;Length). + /// + [MethodImpl(MethodImplOptions.NoOptimization)] // TODO-SPAN: Workaround for https://github.com/dotnet/coreclr/issues/7894 + public ReadOnlySpan Slice(int start, int length) + { + if ((uint)start > (uint)_length || (uint)length > (uint)(_length - start)) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + return new ReadOnlySpan(ref Unsafe.Add(ref DangerousGetPinnableReference(), start), length); + } + + /// + /// Copies the contents of this read-only span into destination span. If the source + /// and destinations overlap, this method behaves as if the original values in + /// a temporary location before the destination is overwritten. + /// + /// The span to copy items into. + /// + /// Thrown when the destination Span is shorter than the source Span. + /// + /// + public void CopyTo(Span destination) + { + if (!TryCopyTo(destination)) + ThrowHelper.ThrowArgumentException_DestinationTooShort(); + } + + /// + /// Copies the contents of this span into destination span. The destination + /// must be at least as big as the source, and may be bigger. + /// + /// The span to copy items into. + public bool TryCopyTo(Span destination) + { + if ((uint)_length > (uint)destination.Length) + return false; + + SpanHelper.CopyTo(ref destination.DangerousGetPinnableReference(), ref DangerousGetPinnableReference(), _length); + return true; + } + + /// + /// Returns true if left and right point at the same memory and have the same length. Note that + /// this does *not* check to see if the *contents* are equal. + /// + public static bool operator ==(ReadOnlySpan left, ReadOnlySpan right) + { + return left._length == right._length && Unsafe.AreSame(ref left.DangerousGetPinnableReference(), ref right.DangerousGetPinnableReference()); + } + + /// + /// Returns false if left and right point at the same memory and have the same length. Note that + /// this does *not* check to see if the *contents* are equal. + /// + public static bool operator !=(ReadOnlySpan left, ReadOnlySpan right) => !(left == right); + } + + public static class ReadOnlySpanExtensions + { + /// + /// Creates a new readonly span over the portion of the target string. + /// + /// The target string. + /// Thrown when is a null + /// reference (Nothing in Visual Basic). + public static ReadOnlySpan Slice(this string text) + { + if (text == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.text); + + return new ReadOnlySpan(ref text.GetFirstCharRef(), text.Length); + } + + /// + /// Creates a new readonly span over the portion of the target string, beginning at 'start'. + /// + /// The target string. + /// The index at which to begin this slice. + /// Thrown when is a null + /// reference (Nothing in Visual Basic). + /// + /// Thrown when the specified index is not in range (<0 or >Length). + /// + public static ReadOnlySpan Slice(this string text, int start) + { + if (text == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.text); + if ((uint)start > (uint)text.Length) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + return new ReadOnlySpan(ref Unsafe.Add(ref text.GetFirstCharRef(), start), text.Length - start); + } + + /// + /// Creates a new readonly span over the portion of the target string, beginning at , of given . + /// + /// The target string. + /// The index at which to begin this slice. + /// The number of items in the span. + /// Thrown when is a null + /// reference (Nothing in Visual Basic). + /// + /// Thrown when the specified or end index is not in range (<0 or >&eq;Length). + /// + public static ReadOnlySpan Slice(this string text, int start, int length) + { + if (text == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.text); + if ((uint)start > (uint)text.Length || (uint)length > (uint)(text.Length - start)) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + return new ReadOnlySpan(ref Unsafe.Add(ref text.GetFirstCharRef(), start), length); + } + } +} diff --git a/src/mscorlib/src/System/Reflection/Assembly.cs b/src/mscorlib/src/System/Reflection/Assembly.cs index 479d6ca..677e4aa 100644 --- a/src/mscorlib/src/System/Reflection/Assembly.cs +++ b/src/mscorlib/src/System/Reflection/Assembly.cs @@ -37,7 +37,7 @@ namespace System.Reflection using __HResults = System.__HResults; using System.Runtime.Versioning; using System.Diagnostics.Contracts; - + using System.Runtime.Loader; [Serializable] [System.Runtime.InteropServices.ComVisible(true)] @@ -48,14 +48,9 @@ namespace System.Reflection [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_Assembly))] [System.Runtime.InteropServices.ComVisible(true)] -#pragma warning disable 618 - [PermissionSetAttribute(SecurityAction.InheritanceDemand, Unrestricted = true)] -#pragma warning restore 618 public abstract class Assembly : _Assembly, IEvidenceFactory, ICustomAttributeProvider, ISerializable { -#region constructors protected Assembly() {} -#endregion #region public static methods @@ -67,7 +62,7 @@ namespace System.Reflection public static Assembly GetAssembly(Type type) { if (type == null) - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); Contract.EndContractBlock(); Module m = type.Module; @@ -105,36 +100,15 @@ namespace System.Reflection return base.GetHashCode(); } - // Locate an assembly by the name of the file containing the manifest. -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static Assembly LoadFrom(String assemblyFile) { - Contract.Ensures(Contract.Result() != null); - Contract.Ensures(!Contract.Result().ReflectionOnly); - -#if FEATURE_WINDOWSPHONE - throw new NotSupportedException(Environment.GetResourceString("NotSupported_WindowsPhone", "Assembly.LoadFrom")); -#else - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - - return RuntimeAssembly.InternalLoadFrom( - assemblyFile, - null, // securityEvidence - null, // hashValue - AssemblyHashAlgorithm.None, - false,// forIntrospection - false,// suppressSecurityChecks - ref stackMark); -#endif // FEATURE_WINDOWSPHONE + if(assemblyFile == null) + throw new ArgumentNullException(nameof(assemblyFile)); + string fullPath = Path.GetFullPath(assemblyFile); + return AssemblyLoadContext.Default.LoadFromAssemblyPath(fullPath); } // Locate an assembly for reflection by the name of the file containing the manifest. - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static Assembly ReflectionOnlyLoadFrom(String assemblyFile) { @@ -153,7 +127,6 @@ namespace System.Reflection } // Evidence is protected in Assembly.Load() - [System.Security.SecuritySafeCritical] // auto-generated [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. Please use an overload of LoadFrom which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static Assembly LoadFrom(String assemblyFile, @@ -174,7 +147,6 @@ namespace System.Reflection } // Evidence is protected in Assembly.Load() - [System.Security.SecuritySafeCritical] // auto-generated [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. Please use an overload of LoadFrom which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static Assembly LoadFrom(String assemblyFile, @@ -196,49 +168,21 @@ namespace System.Reflection ref stackMark); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static Assembly LoadFrom(String assemblyFile, byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm) { - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - - return RuntimeAssembly.InternalLoadFrom( - assemblyFile, - null, - hashValue, - hashAlgorithm, - false, - false, - ref stackMark); + throw new NotSupportedException(Environment.GetResourceString("NotSupported_AssemblyLoadFromHash")); } -#if FEATURE_CAS_POLICY - // Load an assembly into the LoadFrom context bypassing some security checks - [SecurityCritical] - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static Assembly UnsafeLoadFrom(string assemblyFile) { - - Contract.Ensures(Contract.Result() != null); - Contract.Ensures(!Contract.Result().ReflectionOnly); - - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - - return RuntimeAssembly.InternalLoadFrom(assemblyFile, - null, // securityEvidence - null, // hashValue - AssemblyHashAlgorithm.None, - false, // forIntrospection - true, // suppressSecurityChecks - ref stackMark); + return LoadFrom(assemblyFile); } -#endif // FEATURE_CAS_POLICY // Locate an assembly by the long form of the assembly name. // eg. "Toolbox.dll, version=1.1.10.1220, locale=en, publickey=1234567890123456789012345678901234567890" - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static Assembly Load(String assemblyString) { @@ -253,7 +197,6 @@ namespace System.Reflection // Calls Type.GetType for WinRT types. // Note: Type.GetType fails for assembly names that start with weird characters like '['. By calling it for managed types we would // break AppCompat. - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable internal static Type GetType_Compat(String assemblyString, String typeName) { @@ -283,7 +226,6 @@ namespace System.Reflection // Locate an assembly for reflection by the long form of the assembly name. // eg. "Toolbox.dll, version=1.1.10.1220, locale=en, publickey=1234567890123456789012345678901234567890" // - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static Assembly ReflectionOnlyLoad(String assemblyString) { @@ -293,7 +235,6 @@ namespace System.Reflection return RuntimeAssembly.InternalLoad(assemblyString, null, ref stackMark, true /*forIntrospection*/); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. Please use an overload of Load which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] public static Assembly Load(String assemblyString, Evidence assemblySecurity) @@ -307,11 +248,6 @@ namespace System.Reflection // Locate an assembly by its name. The name can be strong or // weak. The assembly is loaded into the domain of the caller. -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static Assembly Load(AssemblyName assemblyRef) { @@ -331,11 +267,6 @@ namespace System.Reflection // Locate an assembly by its name. The name can be strong or // weak. The assembly is loaded into the domain of the caller. -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable internal static Assembly Load(AssemblyName assemblyRef, IntPtr ptrLoadContextBinder) { @@ -353,7 +284,6 @@ namespace System.Reflection return RuntimeAssembly.InternalLoadAssemblyName(assemblyRef, null, null, ref stackMark, true /*thrownOnFileNotFound*/, false /*forIntrospection*/, false /*suppressSecurityChecks*/, ptrLoadContextBinder); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. Please use an overload of Load which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] public static Assembly Load(AssemblyName assemblyRef, Evidence assemblySecurity) @@ -365,34 +295,17 @@ namespace System.Reflection return RuntimeAssembly.InternalLoadAssemblyName(assemblyRef, assemblySecurity, null, ref stackMark, true /*thrownOnFileNotFound*/, false /*forIntrospection*/, false /*suppressSecurityChecks*/); } -#if FEATURE_FUSION - [System.Security.SecuritySafeCritical] // auto-generated [Obsolete("This method has been deprecated. Please use Assembly.Load() instead. http://go.microsoft.com/fwlink/?linkid=14202")] - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static Assembly LoadWithPartialName(String partialName) { - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return RuntimeAssembly.LoadWithPartialNameInternal(partialName, null, ref stackMark); - } - - [System.Security.SecuritySafeCritical] // auto-generated - [Obsolete("This method has been deprecated. Please use Assembly.Load() instead. http://go.microsoft.com/fwlink/?linkid=14202")] - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - public static Assembly LoadWithPartialName(String partialName, Evidence securityEvidence) - { - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return RuntimeAssembly.LoadWithPartialNameInternal(partialName, securityEvidence, ref stackMark); + if(partialName == null) + throw new ArgumentNullException(nameof(partialName)); + return Load(partialName); } -#endif // FEATURE_FUSION // Loads the assembly with a COFF based IMAGE containing // an emitted assembly. The assembly is loaded into the domain // of the caller. -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static Assembly Load(byte[] rawAssembly) { @@ -401,20 +314,12 @@ namespace System.Reflection AppDomain.CheckLoadByteArraySupported(); - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return RuntimeAssembly.nLoadImage( - rawAssembly, - null, // symbol store - null, // evidence - ref stackMark, - false, // fIntrospection - SecurityContextSource.CurrentAssembly); + return Load(rawAssembly, null); } // Loads the assembly for reflection with a COFF based IMAGE containing // an emitted assembly. The assembly is loaded into the domain // of the caller. - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static Assembly ReflectionOnlyLoad(byte[] rawAssembly) { @@ -436,40 +341,30 @@ namespace System.Reflection // an emitted assembly. The assembly is loaded into the domain // of the caller. The second parameter is the raw bytes // representing the symbol store that matches the assembly. -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static Assembly Load(byte[] rawAssembly, byte[] rawSymbolStore) { - Contract.Ensures(Contract.Result() != null); Contract.Ensures(!Contract.Result().ReflectionOnly); AppDomain.CheckLoadByteArraySupported(); - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return RuntimeAssembly.nLoadImage( - rawAssembly, - rawSymbolStore, - null, // evidence - ref stackMark, - false, // fIntrospection - SecurityContextSource.CurrentAssembly); + if(rawAssembly == null) + throw new ArgumentNullException(nameof(rawAssembly)); + AssemblyLoadContext alc = new IndividualAssemblyLoadContext(); + MemoryStream assemblyStream = new MemoryStream(rawAssembly); + MemoryStream symbolStream = (rawSymbolStore!=null)?new MemoryStream(rawSymbolStore):null; + return alc.LoadFromStream(assemblyStream, symbolStream); } // Load an assembly from a byte array, controlling where the grant set of this assembly is // propigated from. - [SecuritySafeCritical] [MethodImpl(MethodImplOptions.NoInlining)] // Due to the stack crawl mark public static Assembly Load(byte[] rawAssembly, byte[] rawSymbolStore, SecurityContextSource securityContextSource) { - Contract.Ensures(Contract.Result() != null); Contract.Ensures(!Contract.Result().ReflectionOnly); @@ -478,7 +373,7 @@ namespace System.Reflection if (securityContextSource < SecurityContextSource.CurrentAppDomain || securityContextSource > SecurityContextSource.CurrentAssembly) { - throw new ArgumentOutOfRangeException("securityContextSource"); + throw new ArgumentOutOfRangeException(nameof(securityContextSource)); } StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -490,79 +385,37 @@ namespace System.Reflection securityContextSource); } -#if FEATURE_CAS_POLICY - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlEvidence)] - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. Please use an overload of Load which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public static Assembly Load(byte[] rawAssembly, - byte[] rawSymbolStore, - Evidence securityEvidence) - { - - Contract.Ensures(Contract.Result() != null); - Contract.Ensures(!Contract.Result().ReflectionOnly); - - AppDomain.CheckLoadByteArraySupported(); + private static Dictionary s_loadfile = new Dictionary(); - if (securityEvidence != null && !AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - // A zone of MyComputer could not have been used to sandbox, so for compatibility we do not - // throw an exception when we see it. - Zone zone = securityEvidence.GetHostEvidence(); - if (zone == null || zone.SecurityZone != SecurityZone.MyComputer) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit")); - } - } - - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return RuntimeAssembly.nLoadImage( - rawAssembly, - rawSymbolStore, - securityEvidence, - ref stackMark, - false, // fIntrospection - SecurityContextSource.CurrentAssembly); - } -#endif // FEATURE_CAS_POLICY - - [System.Security.SecuritySafeCritical] // auto-generated public static Assembly LoadFile(String path) { - Contract.Ensures(Contract.Result() != null); Contract.Ensures(!Contract.Result().ReflectionOnly); AppDomain.CheckLoadFileSupported(); - new FileIOPermission(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, path).Demand(); - return RuntimeAssembly.nLoadFile(path, null); - } - -#if FEATURE_CAS_POLICY - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlEvidence)] - [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. Please use an overload of LoadFile which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public static Assembly LoadFile(String path, - Evidence securityEvidence) - { - - Contract.Ensures(Contract.Result() != null); - Contract.Ensures(!Contract.Result().ReflectionOnly); + Assembly result = null; + if(path == null) + throw new ArgumentNullException(nameof(path)); - AppDomain.CheckLoadFileSupported(); + if (PathInternal.IsPartiallyQualified(path)) + { + throw new ArgumentException(Environment.GetResourceString("Argument_AbsolutePathRequired"), nameof(path)); + } - if (securityEvidence != null && !AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit")); + string normalizedPath = Path.GetFullPath(path); - new FileIOPermission(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, path).Demand(); - return RuntimeAssembly.nLoadFile(path, securityEvidence); + lock(s_loadfile) + { + if(s_loadfile.TryGetValue(normalizedPath, out result)) + return result; + AssemblyLoadContext alc = new IndividualAssemblyLoadContext(); + result = alc.LoadFromAssemblyPath(normalizedPath); + s_loadfile.Add(normalizedPath, result); + } + return result; } -#endif // FEATURE_CAS_POLICY -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static Assembly Load(Stream assemblyStream, Stream pdbStream) { @@ -572,8 +425,6 @@ namespace System.Reflection StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return RuntimeAssembly.InternalLoadFromStream(assemblyStream, pdbStream, ref stackMark); } - - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static Assembly Load(Stream assemblyStream) { @@ -583,12 +434,10 @@ namespace System.Reflection StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return RuntimeAssembly.InternalLoadFromStream(assemblyStream, null, ref stackMark); } -#endif //FEATURE_CORECLR /* * Get the assembly that the current code is running from. */ - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static Assembly GetExecutingAssembly() { @@ -596,7 +445,6 @@ namespace System.Reflection return RuntimeAssembly.GetExecutingAssembly(ref stackMark); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static Assembly GetCallingAssembly() { @@ -607,25 +455,22 @@ namespace System.Reflection return RuntimeAssembly.GetExecutingAssembly(ref stackMark); } - [System.Security.SecuritySafeCritical] // auto-generated public static Assembly GetEntryAssembly() { AppDomainManager domainManager = AppDomain.CurrentDomain.DomainManager; if (domainManager == null) domainManager = new AppDomainManager(); return domainManager.EntryAssembly; } - + #endregion // public static methods #region public methods public virtual event ModuleResolveEventHandler ModuleResolve { - [System.Security.SecurityCritical] // auto-generated_required add { throw new NotImplementedException(); } - [System.Security.SecurityCritical] // auto-generated_required remove { throw new NotImplementedException(); @@ -634,9 +479,6 @@ namespace System.Reflection public virtual String CodeBase { -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif get { throw new NotImplementedException(); @@ -645,24 +487,17 @@ namespace System.Reflection public virtual String EscapedCodeBase { - [System.Security.SecuritySafeCritical] // auto-generated get { return AssemblyName.EscapeCodeBase(CodeBase); } } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif public virtual AssemblyName GetName() { return GetName(false); } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif public virtual AssemblyName GetName(bool copiedName) { throw new NotImplementedException(); @@ -684,13 +519,6 @@ namespace System.Reflection } } -#if !FEATURE_CORECLR - Type _Assembly.GetType() - { - return base.GetType(); - } -#endif - public virtual Type GetType(String name) { return GetType(name, false, false); @@ -789,31 +617,11 @@ namespace System.Reflection throw new NotImplementedException(); } -#if FEATURE_CAS_POLICY - public virtual Evidence Evidence - { - get - { - throw new NotImplementedException(); - } - } - - public virtual PermissionSet PermissionSet - { - // SecurityCritical because permissions can contain sensitive information such as paths - [SecurityCritical] - get - { - throw new NotImplementedException(); - } - } - public bool IsFullyTrusted { - [SecuritySafeCritical] get { - return PermissionSet.IsUnrestricted(); + return true; } } @@ -821,14 +629,11 @@ namespace System.Reflection { get { - throw new NotImplementedException(); + return SecurityRuleSet.None; } } -#endif // FEATURE_CAS_POLICY - // ISerializable implementation - [System.Security.SecurityCritical] // auto-generated_required public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { throw new NotImplementedException(); @@ -890,8 +695,6 @@ namespace System.Reflection } } -#if FEATURE_MULTIMODULE_ASSEMBLIES - public Module LoadModule(String moduleName, byte[] rawModule) { @@ -904,7 +707,6 @@ namespace System.Reflection { throw new NotImplementedException(); } -#endif //FEATURE_MULTIMODULE_ASSEMBLIES // // Locates a type from this assembly and creates an instance of it using @@ -986,9 +788,6 @@ namespace System.Reflection // Returns the file in the File table of the manifest that matches the // given name. (Name should not include path.) -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif public virtual FileStream GetFile(String name) { throw new NotImplementedException(); @@ -999,9 +798,6 @@ namespace System.Reflection return GetFiles(false); } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif public virtual FileStream[] GetFiles(bool getResourceModules) { throw new NotImplementedException(); @@ -1034,9 +830,6 @@ namespace System.Reflection public virtual String Location { -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif get { throw new NotImplementedException(); @@ -1103,27 +896,7 @@ namespace System.Reflection [Serializable] internal class RuntimeAssembly : Assembly -#if !FEATURE_CORECLR - , ICustomQueryInterface -#endif { -#if !FEATURE_CORECLR -#region ICustomQueryInterface - [System.Security.SecurityCritical] - CustomQueryInterfaceResult ICustomQueryInterface.GetInterface([In]ref Guid iid, out IntPtr ppv) - { - if (iid == typeof(NativeMethods.IDispatch).GUID) - { - ppv = Marshal.GetComInterfaceForObject(this, typeof(_Assembly)); - return CustomQueryInterfaceResult.Handled; - } - - ppv = IntPtr.Zero; - return CustomQueryInterfaceResult.NotHandled; - } -#endregion -#endif // !FEATURE_CORECLR - #if FEATURE_APPX // The highest byte is the flags and the lowest 3 bytes are // the cached ctor token of [DynamicallyInvocableAttribute]. @@ -1166,54 +939,12 @@ namespace System.Reflection private ASSEMBLY_FLAGS Flags { - [SecuritySafeCritical] get { if ((m_flags & ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_INITIALIZED) == 0) { - ASSEMBLY_FLAGS flags = ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_UNKNOWN; - -#if FEATURE_CORECLR - flags |= ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_FRAMEWORK | ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_SAFE_REFLECTION; -#else - if (RuntimeAssembly.IsFrameworkAssembly(GetName())) - { - flags |= ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_FRAMEWORK | ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_SAFE_REFLECTION; - - foreach (string name in s_unsafeFrameworkAssemblyNames) - { - if (String.Compare(GetSimpleName(), name, StringComparison.OrdinalIgnoreCase) == 0) - { - flags &= ~ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_SAFE_REFLECTION; - break; - } - } - - // Each blessed API will be annotated with a "__DynamicallyInvokableAttribute". - // This "__DynamicallyInvokableAttribute" is a type defined in its own assembly. - // So the ctor is always a MethodDef and the type a TypeDef. - // We cache this ctor MethodDef token for faster custom attribute lookup. - // If this attribute type doesn't exist in the assembly, it means the assembly - // doesn't contain any blessed APIs. - Type invocableAttribute = GetType("__DynamicallyInvokableAttribute", false); - if (invocableAttribute != null) - { - Contract.Assert(((MetadataToken)invocableAttribute.MetadataToken).IsTypeDef); - - ConstructorInfo ctor = invocableAttribute.GetConstructor(Type.EmptyTypes); - Contract.Assert(ctor != null); - - int token = ctor.MetadataToken; - Contract.Assert(((MetadataToken)token).IsMethodDef); - - flags |= (ASSEMBLY_FLAGS)token & ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_TOKEN_MASK; - } - } - else if (IsDesignerBindingContext()) - { - flags = ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_SAFE_REFLECTION; - } -#endif + ASSEMBLY_FLAGS flags = ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_UNKNOWN + | ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_FRAMEWORK | ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_SAFE_REFLECTION; m_flags = flags | ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_INITIALIZED; } @@ -1221,7 +952,7 @@ namespace System.Reflection return m_flags; } } -#endif // FEATURE_CORECLR +#endif // FEATURE_APPX internal object SyncRoot { @@ -1237,12 +968,10 @@ namespace System.Reflection public override event ModuleResolveEventHandler ModuleResolve { - [System.Security.SecurityCritical] // auto-generated_required add { _ModuleResolve += value; } - [System.Security.SecurityCritical] // auto-generated_required remove { _ModuleResolve -= value; @@ -1251,14 +980,12 @@ namespace System.Reflection private const String s_localFilePrefix = "file:"; - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void GetCodeBase(RuntimeAssembly assembly, bool copiedName, StringHandleOnStack retString); - [System.Security.SecurityCritical] // auto-generated internal String GetCodeBase(bool copiedName) { String codeBase = null; @@ -1268,11 +995,6 @@ namespace System.Reflection public override String CodeBase { -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif get { String codeBase = GetCodeBase(false); VerifyCodeBaseDiscovery(codeBase); @@ -1288,11 +1010,6 @@ namespace System.Reflection // If the assembly is copied before it is loaded, the codebase will be set to the // actual file loaded if copiedName is true. If it is false, then the original code base // is returned. -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif public override AssemblyName GetName(bool copiedName) { AssemblyName an = new AssemblyName(); @@ -1326,27 +1043,12 @@ namespace System.Reflection return an; } -#if FEATURE_APTCA - // This method is called from the VM when creating conditional APTCA exceptions, in order to include - // the text which must be added to the partial trust visible assembly list - [SecurityCritical] - [PermissionSet(SecurityAction.Assert, Unrestricted = true)] - private string GetNameForConditionalAptca() - { - AssemblyName assemblyName = GetName(); - return assemblyName.GetNameWithPublicKey(); - - } -#endif // FEATURE_APTCA - - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void GetFullName(RuntimeAssembly assembly, StringHandleOnStack retString); public override String FullName { - [System.Security.SecuritySafeCritical] // auto-generated get { // If called by Object.ToString(), return val may be NULL. if (m_fullname == null) @@ -1360,14 +1062,12 @@ namespace System.Reflection } } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void GetEntryPoint(RuntimeAssembly assembly, ObjectHandleOnStack retMethod); public override MethodInfo EntryPoint { - [System.Security.SecuritySafeCritical] // auto-generated get { IRuntimeMethodInfo methodHandle = null; GetEntryPoint(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref methodHandle)); @@ -1379,7 +1079,6 @@ namespace System.Reflection } } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void GetType(RuntimeAssembly assembly, @@ -1389,12 +1088,11 @@ namespace System.Reflection ObjectHandleOnStack type, ObjectHandleOnStack keepAlive); - [System.Security.SecuritySafeCritical] public override Type GetType(String name, bool throwOnError, bool ignoreCase) { // throw on null strings regardless of the value of "throwOnError" if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); RuntimeType type = null; Object keepAlive = null; @@ -1404,17 +1102,14 @@ namespace System.Reflection return type; } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal extern static void GetForwardedTypes(RuntimeAssembly assembly, ObjectHandleOnStack retTypes); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void GetExportedTypes(RuntimeAssembly assembly, ObjectHandleOnStack retTypes); - [System.Security.SecuritySafeCritical] // auto-generated public override Type[] GetExportedTypes() { Type[] types = null; @@ -1424,7 +1119,6 @@ namespace System.Reflection public override IEnumerable DefinedTypes { - [System.Security.SecuritySafeCritical] get { List rtTypes = new List(); @@ -1441,7 +1135,6 @@ namespace System.Reflection } // Load a resource based on the NameSpace of the type. - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public override Stream GetManifestResourceStream(Type type, String name) { @@ -1449,7 +1142,6 @@ namespace System.Reflection return GetManifestResourceStream(type, name, false, ref stackMark); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public override Stream GetManifestResourceStream(String name) { @@ -1457,76 +1149,11 @@ namespace System.Reflection return GetManifestResourceStream(name, ref stackMark, false); } -#if FEATURE_CAS_POLICY - [System.Security.SecurityCritical] // auto-generated - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - private extern static void GetEvidence(RuntimeAssembly assembly, ObjectHandleOnStack retEvidence); - - [SecurityCritical] - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - private extern static SecurityRuleSet GetSecurityRuleSet(RuntimeAssembly assembly); - - public override Evidence Evidence - { - [SecuritySafeCritical] - [SecurityPermissionAttribute( SecurityAction.Demand, ControlEvidence = true )] - get - { - Evidence evidence = EvidenceNoDemand; - return evidence.Clone(); - } - } - - internal Evidence EvidenceNoDemand - { - [SecurityCritical] - get - { - Evidence evidence = null; - GetEvidence(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref evidence)); - return evidence; - } - } - - public override PermissionSet PermissionSet - { - [SecurityCritical] - get - { - PermissionSet grantSet = null; - PermissionSet deniedSet = null; - - GetGrantSet(out grantSet, out deniedSet); - - if (grantSet != null) - { - return grantSet.Copy(); - } - else - { - return new PermissionSet(PermissionState.Unrestricted); - } - } - } - - public override SecurityRuleSet SecurityRuleSet - { - [SecuritySafeCritical] - get - { - return GetSecurityRuleSet(GetNativeHandle()); - } - } -#endif // FEATURE_CAS_POLICY - // ISerializable implementation - [System.Security.SecurityCritical] // auto-generated_required public override void GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); @@ -1550,17 +1177,17 @@ namespace System.Reflection { return CustomAttribute.GetCustomAttributes(this, typeof(object) as RuntimeType); } - + public override Object[] GetCustomAttributes(Type attributeType, bool inherit) { if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),nameof(attributeType)); return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType); } @@ -1568,13 +1195,13 @@ namespace System.Reflection public override bool IsDefined(Type attributeType, bool inherit) { if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"caType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),nameof(attributeType)); return CustomAttribute.IsDefined(this, attributeRuntimeType); } @@ -1583,8 +1210,7 @@ namespace System.Reflection { return CustomAttributeData.GetCustomAttributesInternal(this); } - - [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable internal static RuntimeAssembly InternalLoadFrom(String assemblyFile, Evidence securityEvidence, @@ -1595,16 +1221,10 @@ namespace System.Reflection ref StackCrawlMark stackMark) { if (assemblyFile == null) - throw new ArgumentNullException("assemblyFile"); + throw new ArgumentNullException(nameof(assemblyFile)); Contract.EndContractBlock(); -#if FEATURE_CAS_POLICY - if (securityEvidence != null && !AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit")); - } -#endif // FEATURE_CAS_POLICY AssemblyName an = new AssemblyName(); an.CodeBase = assemblyFile; an.SetHashControl(hashValue, hashAlgorithm); @@ -1613,7 +1233,6 @@ namespace System.Reflection } // Wrapper function to wrap the typical use of InternalLoad. - [System.Security.SecurityCritical] // auto-generated internal static RuntimeAssembly InternalLoad(String assemblyString, Evidence assemblySecurity, ref StackCrawlMark stackMark, @@ -1622,7 +1241,6 @@ namespace System.Reflection return InternalLoad(assemblyString, assemblySecurity, ref stackMark, IntPtr.Zero, forIntrospection); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable internal static RuntimeAssembly InternalLoad(String assemblyString, Evidence assemblySecurity, @@ -1644,14 +1262,13 @@ namespace System.Reflection } // Creates AssemblyName. Fills assembly if AssemblyResolve event has been raised. - [System.Security.SecurityCritical] // auto-generated internal static AssemblyName CreateAssemblyName( String assemblyString, bool forIntrospection, out RuntimeAssembly assemblyFromResolveEvent) { if (assemblyString == null) - throw new ArgumentNullException("assemblyString"); + throw new ArgumentNullException(nameof(assemblyString)); Contract.EndContractBlock(); if ((assemblyString.Length == 0) || @@ -1670,7 +1287,6 @@ namespace System.Reflection } // Wrapper function to wrap the typical use of InternalLoadAssemblyName. - [System.Security.SecurityCritical] // auto-generated internal static RuntimeAssembly InternalLoadAssemblyName( AssemblyName assemblyRef, Evidence assemblySecurity, @@ -1684,7 +1300,6 @@ namespace System.Reflection return InternalLoadAssemblyName(assemblyRef, assemblySecurity, reqAssembly, ref stackMark, IntPtr.Zero, true /*throwOnError*/, forIntrospection, suppressSecurityChecks, ptrLoadContextBinder); } - [System.Security.SecurityCritical] // auto-generated internal static RuntimeAssembly InternalLoadAssemblyName( AssemblyName assemblyRef, Evidence assemblySecurity, @@ -1698,7 +1313,7 @@ namespace System.Reflection { if (assemblyRef == null) - throw new ArgumentNullException("assemblyRef"); + throw new ArgumentNullException(nameof(assemblyRef)); Contract.EndContractBlock(); if (assemblyRef.CodeBase != null) @@ -1717,13 +1332,6 @@ namespace System.Reflection if (assemblySecurity != null) { -#if FEATURE_CAS_POLICY - if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit")); - } -#endif // FEATURE_CAS_POLICY - if (!suppressSecurityChecks) { #pragma warning disable 618 @@ -1732,22 +1340,19 @@ namespace System.Reflection } } - String codeBase = VerifyCodeBase(assemblyRef.CodeBase); - if (codeBase != null && !suppressSecurityChecks) { - - if (String.Compare( codeBase, 0, s_localFilePrefix, 0, 5, StringComparison.OrdinalIgnoreCase) != 0) { -#if FEATURE_FUSION // Of all the binders, Fusion is the only one that understands Web locations - IPermission perm = CreateWebPermission( assemblyRef.EscapedCodeBase ); - perm.Demand(); -#else + if (codeBase != null && !suppressSecurityChecks) + { + if (String.Compare( codeBase, 0, s_localFilePrefix, 0, 5, StringComparison.OrdinalIgnoreCase) != 0) + { + // Of all the binders, Fusion is the only one that understands Web locations throw new ArgumentException(Environment.GetResourceString("Arg_InvalidFileName"), "assemblyRef.CodeBase"); -#endif } - else { + else + { System.Security.Util.URLString urlString = new System.Security.Util.URLString( codeBase, true ); new FileIOPermission( FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read , urlString.GetFileName() ).Demand(); - } + } } return nLoad(assemblyRef, codeBase, assemblySecurity, reqAssembly, ref stackMark, @@ -1765,7 +1370,6 @@ namespace System.Reflection }; #if FEATURE_APPX - [System.Security.SecuritySafeCritical] internal bool IsFrameworkAssembly() { ASSEMBLY_FLAGS flags = Flags; @@ -1780,43 +1384,28 @@ namespace System.Reflection return (flags & ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_SAFE_REFLECTION) != 0; } - [System.Security.SecuritySafeCritical] private bool IsDesignerBindingContext() { return RuntimeAssembly.nIsDesignerBindingContext(this); } - [System.Security.SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static bool nIsDesignerBindingContext(RuntimeAssembly assembly); #endif - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern RuntimeAssembly _nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, - ref StackCrawlMark stackMark, + ref StackCrawlMark stackMark, IntPtr pPrivHostBinder, - bool throwOnFileNotFound, + bool throwOnFileNotFound, bool forIntrospection, bool suppressSecurityChecks, IntPtr ptrLoadContextBinder); -#if !FEATURE_CORECLR - // The NGEN task uses this method, so please do not modify its signature - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern bool IsFrameworkAssembly(AssemblyName assemblyName); - - [System.Security.SecurityCritical] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern bool IsNewPortableAssembly(AssemblyName assemblyName); -#endif - - [System.Security.SecurityCritical] // auto-generated private static RuntimeAssembly nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, @@ -1832,177 +1421,6 @@ namespace System.Reflection throwOnFileNotFound, forIntrospection, suppressSecurityChecks, ptrLoadContextBinder); } -#if FEATURE_FUSION - // used by vm - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - private static unsafe RuntimeAssembly LoadWithPartialNameHack(String partialName, bool cropPublicKey) - { - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - - AssemblyName an = new AssemblyName(partialName); - - if (!IsSimplyNamed(an)) - { - if (cropPublicKey) - { - an.SetPublicKey(null); - an.SetPublicKeyToken(null); - } - - if(IsFrameworkAssembly(an) || !AppDomain.IsAppXModel()) - { - AssemblyName GACAssembly = EnumerateCache(an); - if(GACAssembly != null) - return InternalLoadAssemblyName(GACAssembly, null, null,ref stackMark, true /*thrownOnFileNotFound*/, false, false); - else - return null; - } - } - - if (AppDomain.IsAppXModel()) - { - // also try versionless bind from the package - an.Version = null; - return nLoad(an, null, null, null, ref stackMark, - IntPtr.Zero, - false, false, false); - } - return null; - - } - -#if !FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - internal static RuntimeAssembly LoadWithPartialNameInternal(String partialName, Evidence securityEvidence, ref StackCrawlMark stackMark) - { - AssemblyName an = new AssemblyName(partialName); - return LoadWithPartialNameInternal(an, securityEvidence, ref stackMark); - } - - [System.Security.SecurityCritical] // auto-generated - internal static RuntimeAssembly LoadWithPartialNameInternal(AssemblyName an, Evidence securityEvidence, ref StackCrawlMark stackMark) - { - if (securityEvidence != null) - { -#if FEATURE_CAS_POLICY - if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit")); - } -#endif // FEATURE_CAS_POLICY - new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand(); - } - - AppDomain.CheckLoadWithPartialNameSupported(stackMark); - - RuntimeAssembly result = null; - try { - result = nLoad(an, null, securityEvidence, null, ref stackMark, - IntPtr.Zero, - true, false, false); - } - catch(Exception e) { - if (e.IsTransient) - throw e; - - if (IsUserError(e)) - throw; - - - if(IsFrameworkAssembly(an) || !AppDomain.IsAppXModel()) - { - if (IsSimplyNamed(an)) - return null; - - AssemblyName GACAssembly = EnumerateCache(an); - if(GACAssembly != null) - result = InternalLoadAssemblyName(GACAssembly, securityEvidence, null, ref stackMark, true /*thrownOnFileNotFound*/, false, false); - } - else - { - an.Version = null; - result = nLoad(an, null, securityEvidence, null, ref stackMark, - IntPtr.Zero, - false, false, false); - } - } - - - return result; - } -#endif // !FEATURE_CORECLR - - [SecuritySafeCritical] - private static bool IsUserError(Exception e) - { - return (uint)e.HResult == COR_E_LOADING_REFERENCE_ASSEMBLY; - } - - private static bool IsSimplyNamed(AssemblyName partialName) - { - byte[] pk = partialName.GetPublicKeyToken(); - if ((pk != null) && - (pk.Length == 0)) - return true; - - pk = partialName.GetPublicKey(); - if ((pk != null) && - (pk.Length == 0)) - return true; - - return false; - } - - [System.Security.SecurityCritical] // auto-generated - private static AssemblyName EnumerateCache(AssemblyName partialName) - { - new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); - - partialName.Version = null; - - ArrayList a = new ArrayList(); - Fusion.ReadCache(a, partialName.FullName, ASM_CACHE.GAC); - - IEnumerator myEnum = a.GetEnumerator(); - AssemblyName ainfoBest = null; - CultureInfo refCI = partialName.CultureInfo; - - while (myEnum.MoveNext()) { - AssemblyName ainfo = new AssemblyName((String)myEnum.Current); - - if (CulturesEqual(refCI, ainfo.CultureInfo)) { - if (ainfoBest == null) - ainfoBest = ainfo; - else { - // Choose highest version - if (ainfo.Version > ainfoBest.Version) - ainfoBest = ainfo; - } - } - } - - return ainfoBest; - } - - private static bool CulturesEqual(CultureInfo refCI, CultureInfo defCI) - { - bool defNoCulture = defCI.Equals(CultureInfo.InvariantCulture); - - // cultured asms aren't allowed to be bound to if - // the ref doesn't ask for them specifically - if ((refCI == null) || refCI.Equals(CultureInfo.InvariantCulture)) - return defNoCulture; - - if (defNoCulture || - ( !defCI.Equals(refCI) )) - return false; - - return true; - } -#endif // FEATURE_FUSION - - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool IsReflectionOnly(RuntimeAssembly assembly); @@ -2011,23 +1429,20 @@ namespace System.Reflection [ComVisible(false)] public override bool ReflectionOnly { - [System.Security.SecuritySafeCritical] // auto-generated get { return IsReflectionOnly(GetNativeHandle()); } } -#if FEATURE_CORECLR // Loads the assembly with a COFF based IMAGE containing // an emitted assembly. The assembly is loaded into the domain // of the caller. Currently is implemented only for UnmanagedMemoryStream // (no derived classes since we are not calling Read()) - [System.Security.SecurityCritical] // auto-generated internal static RuntimeAssembly InternalLoadFromStream(Stream assemblyStream, Stream pdbStream, ref StackCrawlMark stackMark) { if (assemblyStream == null) - throw new ArgumentNullException("assemblyStream"); + throw new ArgumentNullException(nameof(assemblyStream)); if (assemblyStream.GetType()!=typeof(UnmanagedMemoryStream)) throw new NotSupportedException(); @@ -2070,44 +1485,13 @@ namespace System.Reflection return assembly; } } -#endif //FEATURE_CORECLR - -#if FEATURE_MULTIMODULE_ASSEMBLIES - [System.Security.SecurityCritical] // auto-generated - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - private extern static void LoadModule(RuntimeAssembly assembly, - String moduleName, - byte[] rawModule, int cbModule, - byte[] rawSymbolStore, int cbSymbolStore, - ObjectHandleOnStack retModule); - - [SecurityPermissionAttribute(SecurityAction.Demand, ControlEvidence = true)] - [System.Security.SecuritySafeCritical] // auto-generated - public override Module LoadModule(String moduleName, byte[] rawModule, byte[] rawSymbolStore) - { - RuntimeModule retModule = null; - LoadModule( - GetNativeHandle(), - moduleName, - rawModule, - (rawModule != null) ? rawModule.Length : 0, - rawSymbolStore, - (rawSymbolStore != null) ? rawSymbolStore.Length : 0, - JitHelpers.GetObjectHandleOnStack(ref retModule)); - - return retModule; - } -#endif //FEATURE_MULTIMODULE_ASSEMBLIES // Returns the module in this assembly with name 'name' - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void GetModule(RuntimeAssembly assembly, String name, ObjectHandleOnStack retModule); - [System.Security.SecuritySafeCritical] // auto-generated public override Module GetModule(String name) { Module retModule = null; @@ -2117,11 +1501,6 @@ namespace System.Reflection // Returns the file in the File table of the manifest that matches the // given name. (Name should not include path.) -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif public override FileStream GetFile(String name) { RuntimeModule m = (RuntimeModule)GetModule(name); @@ -2133,11 +1512,6 @@ namespace System.Reflection FileAccess.Read, FileShare.Read, FileStream.DefaultBufferSize, false); } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif public override FileStream[] GetFiles(bool getResourceModules) { Module[] m = GetModules(getResourceModules); @@ -2152,26 +1526,20 @@ namespace System.Reflection return fs; } - // Returns the names of all the resources - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern String[] GetManifestResourceNames(RuntimeAssembly assembly); // Returns the names of all the resources - [System.Security.SecuritySafeCritical] // auto-generated public override String[] GetManifestResourceNames() { return GetManifestResourceNames(GetNativeHandle()); } - - - [System.Security.SecurityCritical] // auto-generated + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void GetExecutingAssembly(StackCrawlMarkHandle stackMark, ObjectHandleOnStack retAssembly); - [System.Security.SecurityCritical] // auto-generated internal static RuntimeAssembly GetExecutingAssembly(ref StackCrawlMark stackMark) { RuntimeAssembly retAssembly = null; @@ -2180,17 +1548,14 @@ namespace System.Reflection } // Returns the names of all the resources - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern AssemblyName[] GetReferencedAssemblies(RuntimeAssembly assembly); - [System.Security.SecuritySafeCritical] // auto-generated public override AssemblyName[] GetReferencedAssemblies() { return GetReferencedAssemblies(GetNativeHandle()); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern int GetManifestResourceInfo(RuntimeAssembly assembly, @@ -2199,7 +1564,6 @@ namespace System.Reflection StringHandleOnStack retFileName, StackCrawlMarkHandle stackMark); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public override ManifestResourceInfo GetManifestResourceInfo(String resourceName) { @@ -2218,18 +1582,12 @@ namespace System.Reflection (ResourceLocation) location); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void GetLocation(RuntimeAssembly assembly, StringHandleOnStack retString); public override String Location { -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif get { String location = null; @@ -2242,7 +1600,6 @@ namespace System.Reflection } } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void GetImageRuntimeVersion(RuntimeAssembly assembly, StringHandleOnStack retString); @@ -2252,7 +1609,6 @@ namespace System.Reflection [ComVisible(false)] public override String ImageRuntimeVersion { - [System.Security.SecuritySafeCritical] // auto-generated get{ String s = null; GetImageRuntimeVersion(GetNativeHandle(), JitHelpers.GetStringHandleOnStack(ref s)); @@ -2261,30 +1617,26 @@ namespace System.Reflection } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static bool IsGlobalAssemblyCache(RuntimeAssembly assembly); public override bool GlobalAssemblyCache { - [System.Security.SecuritySafeCritical] // auto-generated get { - return IsGlobalAssemblyCache(GetNativeHandle()); + return false; } } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static Int64 GetHostContext(RuntimeAssembly assembly); public override Int64 HostContext { - [System.Security.SecuritySafeCritical] // auto-generated get { - return GetHostContext(GetNativeHandle()); + return 0; } } @@ -2309,14 +1661,13 @@ namespace System.Reflection else if ((len > 2) && (codebase[0] == '\\') && (codebase[1] == '\\')) return "file://" + codebase; else - return "file:///" + Path.GetFullPathInternal( codebase ); + return "file:///" + Path.GetFullPath(codebase); #else else - return "file://" + Path.GetFullPathInternal( codebase ); + return "file://" + Path.GetFullPath(codebase); #endif // !PLATFORM_UNIX } - [System.Security.SecurityCritical] // auto-generated internal Stream GetManifestResourceStream( Type type, String name, @@ -2326,7 +1677,7 @@ namespace System.Reflection StringBuilder sb = new StringBuilder(); if(type == null) { if (name == null) - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); } else { String nameSpace = type.Namespace; @@ -2339,25 +1690,11 @@ namespace System.Reflection if(name != null) sb.Append(name); - - return GetManifestResourceStream(sb.ToString(), ref stackMark, skipSecurityCheck); - } -#if FEATURE_CAS_POLICY - internal bool IsStrongNameVerified - { - [System.Security.SecurityCritical] // auto-generated - get { return GetIsStrongNameVerified(GetNativeHandle()); } + return GetManifestResourceStream(sb.ToString(), ref stackMark, skipSecurityCheck); } - [System.Security.SecurityCritical] // auto-generated - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - private static extern bool GetIsStrongNameVerified(RuntimeAssembly assembly); -#endif // FEATURE_CAS_POLICY - // GetResource will return a pointer to the resources in memory. - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static unsafe extern byte* GetResource(RuntimeAssembly assembly, @@ -2366,7 +1703,6 @@ namespace System.Reflection StackCrawlMarkHandle stackMark, bool skipSecurityCheck); - [System.Security.SecurityCritical] // auto-generated internal unsafe Stream GetManifestResourceStream(String name, ref StackCrawlMark stackMark, bool skipSecurityCheck) { ulong length = 0; @@ -2384,7 +1720,6 @@ namespace System.Reflection return null; } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void GetVersion(RuntimeAssembly assembly, @@ -2393,7 +1728,6 @@ namespace System.Reflection out int buildNum, out int revNum); - [System.Security.SecurityCritical] // auto-generated internal Version GetVersion() { int majorVer, minorVer, build, revision; @@ -2401,12 +1735,10 @@ namespace System.Reflection return new Version (majorVer, minorVer, build, revision); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void GetLocale(RuntimeAssembly assembly, StringHandleOnStack retString); - [System.Security.SecurityCritical] // auto-generated internal CultureInfo GetLocale() { String locale = null; @@ -2419,27 +1751,18 @@ namespace System.Reflection return new CultureInfo(locale); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool FCallIsDynamic(RuntimeAssembly assembly); public override bool IsDynamic { - [SecuritySafeCritical] get { return FCallIsDynamic(GetNativeHandle()); } } - [System.Security.SecurityCritical] // auto-generated private void VerifyCodeBaseDiscovery(String codeBase) { -#if FEATURE_CAS_POLICY - if (CodeAccessSecurityEngine.QuickCheckForAllDemands()) { - return; - } -#endif // FEATURE_CAS_POLICY - if ((codeBase != null) && (String.Compare( codeBase, 0, s_localFilePrefix, 0, 5, StringComparison.OrdinalIgnoreCase) == 0)) { System.Security.Util.URLString urlString = new System.Security.Util.URLString( codeBase, true ); @@ -2447,12 +1770,10 @@ namespace System.Reflection } } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void GetSimpleName(RuntimeAssembly assembly, StringHandleOnStack retSimpleName); - [SecuritySafeCritical] internal String GetSimpleName() { string name = null; @@ -2460,35 +1781,29 @@ namespace System.Reflection return name; } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static AssemblyHashAlgorithm GetHashAlgorithm(RuntimeAssembly assembly); - [System.Security.SecurityCritical] // auto-generated private AssemblyHashAlgorithm GetHashAlgorithm() { return GetHashAlgorithm(GetNativeHandle()); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static AssemblyNameFlags GetFlags(RuntimeAssembly assembly); - [System.Security.SecurityCritical] // auto-generated private AssemblyNameFlags GetFlags() { return GetFlags(GetNativeHandle()); } [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SecurityCritical] [SuppressUnmanagedCodeSecurity] private static extern void GetRawBytes(RuntimeAssembly assembly, ObjectHandleOnStack retRawBytes); // Get the raw bytes of the assembly - [SecuritySafeCritical] internal byte[] GetRawBytes() { byte[] rawBytes = null; @@ -2497,12 +1812,10 @@ namespace System.Reflection return rawBytes; } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void GetPublicKey(RuntimeAssembly assembly, ObjectHandleOnStack retPublicKey); - [System.Security.SecurityCritical] // auto-generated internal byte[] GetPublicKey() { byte[] publicKey = null; @@ -2510,12 +1823,10 @@ namespace System.Reflection return publicKey; } - [SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void GetGrantSet(RuntimeAssembly assembly, ObjectHandleOnStack granted, ObjectHandleOnStack denied); - [SecurityCritical] internal void GetGrantSet(out PermissionSet newGrant, out PermissionSet newDenied) { PermissionSet granted = null, denied = null; @@ -2523,134 +1834,51 @@ namespace System.Reflection newGrant = granted; newDenied = denied; } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private extern static bool IsAllSecurityCritical(RuntimeAssembly assembly); // Is everything introduced by this assembly critical - [System.Security.SecuritySafeCritical] // auto-generated internal bool IsAllSecurityCritical() { return IsAllSecurityCritical(GetNativeHandle()); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private extern static bool IsAllSecuritySafeCritical(RuntimeAssembly assembly); // Is everything introduced by this assembly safe critical - [System.Security.SecuritySafeCritical] // auto-generated internal bool IsAllSecuritySafeCritical() { return IsAllSecuritySafeCritical(GetNativeHandle()); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private extern static bool IsAllPublicAreaSecuritySafeCritical(RuntimeAssembly assembly); // Is everything introduced by this assembly safe critical - [System.Security.SecuritySafeCritical] // auto-generated internal bool IsAllPublicAreaSecuritySafeCritical() { return IsAllPublicAreaSecuritySafeCritical(GetNativeHandle()); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private extern static bool IsAllSecurityTransparent(RuntimeAssembly assembly); // Is everything introduced by this assembly transparent - [System.Security.SecuritySafeCritical] // auto-generated internal bool IsAllSecurityTransparent() { return IsAllSecurityTransparent(GetNativeHandle()); } -#if FEATURE_FUSION - // demandFlag: - // 0 demand PathDiscovery permission only - // 1 demand Read permission only - // 2 demand both Read and PathDiscovery - // 3 demand Web permission only - [System.Security.SecurityCritical] // auto-generated - private static void DemandPermission(String codeBase, bool havePath, - int demandFlag) - { - FileIOPermissionAccess access = FileIOPermissionAccess.PathDiscovery; - switch(demandFlag) { - - case 0: // default - break; - case 1: - access = FileIOPermissionAccess.Read; - break; - case 2: - access = FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read; - break; - - case 3: - IPermission perm = CreateWebPermission(AssemblyName.EscapeCodeBase(codeBase)); - perm.Demand(); - return; - } - - if (!havePath) { - System.Security.Util.URLString urlString = new System.Security.Util.URLString( codeBase, true ); - codeBase = urlString.GetFileName(); - } - - codeBase = Path.GetFullPathInternal(codeBase); // canonicalize - - new FileIOPermission(access, codeBase).Demand(); - } -#endif - -#if FEATURE_FUSION - private static IPermission CreateWebPermission( String codeBase ) - { - Contract.Assert( codeBase != null, "Must pass in a valid CodeBase" ); - Assembly sys = Assembly.Load("System, Version=" + ThisAssembly.Version + ", Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken); - - Type type = sys.GetType("System.Net.NetworkAccess", true); - - IPermission retval = null; - if (!type.IsEnum || !type.IsVisible) - goto Exit; - - Object[] webArgs = new Object[2]; - webArgs[0] = (Enum) Enum.Parse(type, "Connect", true); - if (webArgs[0] == null) - goto Exit; - - webArgs[1] = codeBase; - - type = sys.GetType("System.Net.WebPermission", true); - - if (!type.IsVisible) - goto Exit; - - retval = (IPermission) Activator.CreateInstance(type, webArgs); - - Exit: - if (retval == null) { - Contract.Assert( false, "Unable to create WebPermission" ); - throw new InvalidOperationException(); - } - - return retval; - } -#endif // This method is called by the VM. - [System.Security.SecurityCritical] private RuntimeModule OnModuleResolveEvent(String moduleName) { ModuleResolveEventHandler moduleResolve = _ModuleResolve; @@ -2683,14 +1911,13 @@ namespace System.Reflection return InternalGetSatelliteAssembly(culture, version, ref stackMark); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable internal Assembly InternalGetSatelliteAssembly(CultureInfo culture, Version version, ref StackCrawlMark stackMark) { if (culture == null) - throw new ArgumentNullException("culture"); + throw new ArgumentNullException(nameof(culture)); Contract.EndContractBlock(); @@ -2698,15 +1925,6 @@ namespace System.Reflection return InternalGetSatelliteAssembly(name, culture, version, true, ref stackMark); } -#if !FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool UseRelativeBindForSatellites(); -#endif - - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable internal RuntimeAssembly InternalGetSatelliteAssembly(String name, CultureInfo culture, @@ -2728,104 +1946,9 @@ namespace System.Reflection an.CultureInfo = culture; an.Name = name; - RuntimeAssembly retAssembly = null; - -#if !FEATURE_CORECLR - bool bIsAppXDevMode = AppDomain.IsAppXDesignMode(); - - bool useRelativeBind = false; - if (CodeAccessSecurityEngine.QuickCheckForAllDemands()) - { - if (IsFrameworkAssembly()) - useRelativeBind = true; - else - useRelativeBind = UseRelativeBindForSatellites(); - } - - - if (bIsAppXDevMode || useRelativeBind) - { - if (GlobalAssemblyCache) - { - // lookup in GAC - ArrayList a = new ArrayList(); - bool bTryLoadAnyway = false; - try - { - Fusion.ReadCache(a, an.FullName, ASM_CACHE.GAC); - } - catch(Exception e) - { - if (e.IsTransient) - throw; - - // We also catch any other exception types we haven't come across yet, - // not just UnauthorizedAccessException. - - // We do not want this by itself to cause us to fail to load resources. - - // On Classic, try the old unoptimized way, for full compatibility with 4.0. - // i.e. fall back to using nLoad. - if (!AppDomain.IsAppXModel()) - bTryLoadAnyway = true; - - // On AppX: - // Do not try nLoad since that would effectively allow Framework - // resource satellite assemblies to be placed in AppX packages. - // Instead, leave retAssembly == null. If we were called by the - // ResourceManager, this will usually result in falling back to - // the next culture in the resource fallback chain, possibly the - // neutral culture. - - // Note: if throwOnFileNotFound is true, arbitrary - // exceptions will be absorbed here and - // FileNotFoundException will be thrown in their place. - // (See below: "throw new FileNotFoundException"). - } - if (a.Count > 0 || bTryLoadAnyway) - { - // present in the GAC, load it from there - retAssembly = nLoad(an, null, null, this, ref stackMark, - IntPtr.Zero, - throwOnFileNotFound, false, false); - } - } - else - { - String codeBase = CodeBase; - - if ((codeBase != null) && - (String.Compare(codeBase, 0, s_localFilePrefix, 0, 5, StringComparison.OrdinalIgnoreCase) == 0)) - { - retAssembly = InternalProbeForSatelliteAssemblyNextToParentAssembly(an, - name, - codeBase, - culture, - throwOnFileNotFound, - bIsAppXDevMode /* useLoadFile */, // if bIsAppXDevMode is false, then useRelativeBind is true. - ref stackMark); - if (retAssembly != null && !IsSimplyNamed(an)) - { - AssemblyName defName = retAssembly.GetName(); - if (!AssemblyName.ReferenceMatchesDefinitionInternal(an,defName,false)) - retAssembly = null; - } - } - else if (!bIsAppXDevMode) - { - retAssembly = nLoad(an, null, null, this, ref stackMark, - IntPtr.Zero, - throwOnFileNotFound, false, false); - } - } - } - else -#endif // !FEATURE_CORECLR - { - retAssembly = nLoad(an, null, null, this, ref stackMark, - IntPtr.Zero, - throwOnFileNotFound, false, false); - } + RuntimeAssembly retAssembly = nLoad(an, null, null, this, ref stackMark, + IntPtr.Zero, + throwOnFileNotFound, false, false); if (retAssembly == this || (retAssembly == null && throwOnFileNotFound)) { @@ -2836,7 +1959,6 @@ namespace System.Reflection } // Helper method used by InternalGetSatelliteAssembly only. Not abstracted for use elsewhere. - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable private RuntimeAssembly InternalProbeForSatelliteAssemblyNextToParentAssembly(AssemblyName an, String name, @@ -2930,7 +2052,7 @@ namespace System.Reflection // the .DLL and .EXE load attempts if the user is interested in digging deeper. if (retAssembly == null && throwOnFileNotFound) - throw dllNotFoundException; + throw dllNotFoundException; } } catch (DirectoryNotFoundException) @@ -2944,11 +2066,9 @@ namespace System.Reflection return retAssembly; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] static internal extern RuntimeAssembly nLoadFile(String path, Evidence evidence); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] static internal extern RuntimeAssembly nLoadImage(byte[] rawAssembly, byte[] rawSymbolStore, @@ -2956,8 +2076,7 @@ namespace System.Reflection ref StackCrawlMark stackMark, bool fIntrospection, SecurityContextSource securityContextSource); -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] static internal extern unsafe void nLoadFromUnmanagedArray(bool fIntrospection, @@ -2967,9 +2086,7 @@ namespace System.Reflection ulong pdbSize, StackCrawlMarkHandle stackMark, ObjectHandleOnStack retAssembly); -#endif - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void GetModules(RuntimeAssembly assembly, @@ -2977,7 +2094,6 @@ namespace System.Reflection bool getResourceModules, ObjectHandleOnStack retModuleHandles); - [System.Security.SecuritySafeCritical] // auto-generated private RuntimeModule[] GetModulesInternal(bool loadIfNotFound, bool getResourceModules) { @@ -2996,17 +2112,9 @@ namespace System.Reflection return GetModulesInternal(false, getResourceModules); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern RuntimeModule GetManifestModule(RuntimeAssembly assembly); -#if FEATURE_APTCA - [System.Security.SecuritySafeCritical] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern bool AptcaCheck(RuntimeAssembly targetAssembly, RuntimeAssembly sourceAssembly); -#endif // FEATURE_APTCA - - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern int GetToken(RuntimeAssembly assembly); } diff --git a/src/mscorlib/src/System/Reflection/AssemblyAttributes.cs b/src/mscorlib/src/System/Reflection/AssemblyAttributes.cs index 9552555..b2e44b0 100644 --- a/src/mscorlib/src/System/Reflection/AssemblyAttributes.cs +++ b/src/mscorlib/src/System/Reflection/AssemblyAttributes.cs @@ -190,7 +190,7 @@ namespace System.Reflection { public AssemblyFileVersionAttribute(String version) { if (version == null) - throw new ArgumentNullException("version"); + throw new ArgumentNullException(nameof(version)); Contract.EndContractBlock(); _version = version; } diff --git a/src/mscorlib/src/System/Reflection/AssemblyName.cs b/src/mscorlib/src/System/Reflection/AssemblyName.cs index 051f3b5..48eab33 100644 --- a/src/mscorlib/src/System/Reflection/AssemblyName.cs +++ b/src/mscorlib/src/System/Reflection/AssemblyName.cs @@ -24,6 +24,7 @@ namespace System.Reflection { using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Diagnostics.Contracts; + using System.Text; [Serializable] [ClassInterface(ClassInterfaceType.None)] @@ -103,19 +104,12 @@ namespace System.Reflection { public String CodeBase { -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif get { return _CodeBase; } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif set { _CodeBase = value; } } public String EscapedCodeBase { - [System.Security.SecuritySafeCritical] // auto-generated get { if (_CodeBase == null) @@ -189,16 +183,15 @@ namespace System.Reflection { * if the file contains an assembly manifest. This method causes * the file to be opened and closed. */ - [System.Security.SecuritySafeCritical] // auto-generated static public AssemblyName GetAssemblyName(String assemblyFile) { if(assemblyFile == null) - throw new ArgumentNullException("assemblyFile"); + throw new ArgumentNullException(nameof(assemblyFile)); Contract.EndContractBlock(); // Assembly.GetNameInternal() will not demand path discovery // permission, so do that first. - String fullPath = Path.GetFullPathInternal(assemblyFile); + string fullPath = Path.GetFullPath(assemblyFile); new FileIOPermission( FileIOPermissionAccess.PathDiscovery, fullPath ).Demand(); return nGetFileInformation(fullPath); } @@ -230,7 +223,6 @@ namespace System.Reflection { // The compressed version of the public key formed from a truncated hash. // Will throw a SecurityException if _PublicKey is invalid - [System.Security.SecuritySafeCritical] // auto-generated public byte[] GetPublicKeyToken() { if (_PublicKeyToken == null) @@ -279,7 +271,6 @@ namespace System.Reflection { public String FullName { - [System.Security.SecuritySafeCritical] // auto-generated get { return nToString(); } @@ -295,11 +286,10 @@ namespace System.Reflection { return s; } - [System.Security.SecurityCritical] // auto-generated_required public void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); //Allocate the serialization info and serialize our static data. @@ -360,11 +350,10 @@ namespace System.Reflection { m_siInfo = info; } - [System.Security.SecuritySafeCritical] // auto-generated public AssemblyName(String assemblyName) { if (assemblyName == null) - throw new ArgumentNullException("assemblyName"); + throw new ArgumentNullException(nameof(assemblyName)); Contract.EndContractBlock(); if ((assemblyName.Length == 0) || (assemblyName[0] == '\0')) @@ -374,7 +363,6 @@ namespace System.Reflection { nInit(); } - [System.Security.SecuritySafeCritical] // auto-generated static public bool ReferenceMatchesDefinition(AssemblyName reference, AssemblyName definition) { @@ -389,7 +377,6 @@ namespace System.Reflection { /// "parse" tells us to parse the simple name of the assembly as if it was the full name /// almost never the right thing to do, but needed for compat - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] static internal extern bool ReferenceMatchesDefinitionInternal(AssemblyName reference, AssemblyName definition, @@ -397,11 +384,9 @@ namespace System.Reflection { - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern void nInit(out RuntimeAssembly assembly, bool forIntrospection, bool raiseResolveEvent); - [System.Security.SecurityCritical] // auto-generated internal void nInit() { RuntimeAssembly dummy = null; @@ -486,54 +471,239 @@ namespace System.Reflection { _StrongNameKeyPair = keyPair; } -#if !FEATURE_CORECLR - void _AssemblyName.GetTypeInfoCount(out uint pcTInfo) + // This call opens and closes the file, but does not add the + // assembly to the domain. + [MethodImplAttribute(MethodImplOptions.InternalCall)] + static internal extern AssemblyName nGetFileInformation(String s); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private extern String nToString(); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private extern byte[] nGetPublicKeyToken(); + + static internal String EscapeCodeBase(String codebase) { - throw new NotImplementedException(); + if (codebase == null) + return string.Empty; + + int position = 0; + char[] dest = EscapeString(codebase, 0, codebase.Length, null, ref position, true, c_DummyChar, c_DummyChar, c_DummyChar); + if (dest == null) + return codebase; + + return new string(dest, 0, position); } - void _AssemblyName.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) + // This implementation of EscapeString has been copied from System.Private.Uri from corefx repo + // - forceX characters are always escaped if found + // - rsvd character will remain unescaped + // + // start - starting offset from input + // end - the exclusive ending offset in input + // destPos - starting offset in dest for output, on return this will be an exclusive "end" in the output. + // + // In case "dest" has lack of space it will be reallocated by preserving the _whole_ content up to current destPos + // + // Returns null if nothing has to be escaped AND passed dest was null, otherwise the resulting array with the updated destPos + // + internal unsafe static char[] EscapeString(string input, int start, int end, char[] dest, ref int destPos, + bool isUriString, char force1, char force2, char rsvd) { - throw new NotImplementedException(); + int i = start; + int prevInputPos = start; + byte* bytes = stackalloc byte[c_MaxUnicodeCharsReallocate * c_MaxUTF_8BytesPerUnicodeChar]; // 40*4=160 + + fixed (char* pStr = input) + { + for (; i < end; ++i) + { + char ch = pStr[i]; + + // a Unicode ? + if (ch > '\x7F') + { + short maxSize = (short)Math.Min(end - i, (int)c_MaxUnicodeCharsReallocate - 1); + + short count = 1; + for (; count < maxSize && pStr[i + count] > '\x7f'; ++count) + ; + + // Is the last a high surrogate? + if (pStr[i + count - 1] >= 0xD800 && pStr[i + count - 1] <= 0xDBFF) + { + // Should be a rare case where the app tries to feed an invalid Unicode surrogates pair + if (count == 1 || count == end - i) + throw new FormatException(Environment.GetResourceString("Arg_FormatException")); + // need to grab one more char as a Surrogate except when it's a bogus input + ++count; + } + + dest = EnsureDestinationSize(pStr, dest, i, + (short)(count * c_MaxUTF_8BytesPerUnicodeChar * c_EncodedCharsPerByte), + c_MaxUnicodeCharsReallocate * c_MaxUTF_8BytesPerUnicodeChar * c_EncodedCharsPerByte, + ref destPos, prevInputPos); + + short numberOfBytes = (short)Encoding.UTF8.GetBytes(pStr + i, count, bytes, + c_MaxUnicodeCharsReallocate * c_MaxUTF_8BytesPerUnicodeChar); + + // This is the only exception that built in UriParser can throw after a Uri ctor. + // Should not happen unless the app tries to feed an invalid Unicode String + if (numberOfBytes == 0) + throw new FormatException(Environment.GetResourceString("Arg_FormatException")); + + i += (count - 1); + + for (count = 0; count < numberOfBytes; ++count) + EscapeAsciiChar((char)bytes[count], dest, ref destPos); + + prevInputPos = i + 1; + } + else if (ch == '%' && rsvd == '%') + { + // Means we don't reEncode '%' but check for the possible escaped sequence + dest = EnsureDestinationSize(pStr, dest, i, c_EncodedCharsPerByte, + c_MaxAsciiCharsReallocate * c_EncodedCharsPerByte, ref destPos, prevInputPos); + if (i + 2 < end && EscapedAscii(pStr[i + 1], pStr[i + 2]) != c_DummyChar) + { + // leave it escaped + dest[destPos++] = '%'; + dest[destPos++] = pStr[i + 1]; + dest[destPos++] = pStr[i + 2]; + i += 2; + } + else + { + EscapeAsciiChar('%', dest, ref destPos); + } + prevInputPos = i + 1; + } + else if (ch == force1 || ch == force2) + { + dest = EnsureDestinationSize(pStr, dest, i, c_EncodedCharsPerByte, + c_MaxAsciiCharsReallocate * c_EncodedCharsPerByte, ref destPos, prevInputPos); + EscapeAsciiChar(ch, dest, ref destPos); + prevInputPos = i + 1; + } + else if (ch != rsvd && (isUriString ? !IsReservedUnreservedOrHash(ch) : !IsUnreserved(ch))) + { + dest = EnsureDestinationSize(pStr, dest, i, c_EncodedCharsPerByte, + c_MaxAsciiCharsReallocate * c_EncodedCharsPerByte, ref destPos, prevInputPos); + EscapeAsciiChar(ch, dest, ref destPos); + prevInputPos = i + 1; + } + } + + if (prevInputPos != i) + { + // need to fill up the dest array ? + if (prevInputPos != start || dest != null) + dest = EnsureDestinationSize(pStr, dest, i, 0, 0, ref destPos, prevInputPos); + } + } + + return dest; } - void _AssemblyName.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) + // + // ensure destination array has enough space and contains all the needed input stuff + // + private unsafe static char[] EnsureDestinationSize(char* pStr, char[] dest, int currentInputPos, + short charsToAdd, short minReallocateChars, ref int destPos, int prevInputPos) { - throw new NotImplementedException(); - } + if ((object)dest == null || dest.Length < destPos + (currentInputPos - prevInputPos) + charsToAdd) + { + // allocating or reallocating array by ensuring enough space based on maxCharsToAdd. + char[] newresult = new char[destPos + (currentInputPos - prevInputPos) + minReallocateChars]; + + if ((object)dest != null && destPos != 0) + Buffer.BlockCopy(dest, 0, newresult, 0, destPos << 1); + dest = newresult; + } - void _AssemblyName.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) + // ensuring we copied everything form the input string left before last escaping + while (prevInputPos != currentInputPos) + dest[destPos++] = pStr[prevInputPos++]; + return dest; + } + + internal static void EscapeAsciiChar(char ch, char[] to, ref int pos) { - throw new NotImplementedException(); + to[pos++] = '%'; + to[pos++] = s_hexUpperChars[(ch & 0xf0) >> 4]; + to[pos++] = s_hexUpperChars[ch & 0xf]; } -#endif -#if FEATURE_APTCA - internal string GetNameWithPublicKey() + internal static char EscapedAscii(char digit, char next) { - byte[] key = GetPublicKey(); + if (!(((digit >= '0') && (digit <= '9')) + || ((digit >= 'A') && (digit <= 'F')) + || ((digit >= 'a') && (digit <= 'f')))) + { + return c_DummyChar; + } + + int res = (digit <= '9') + ? ((int)digit - (int)'0') + : (((digit <= 'F') + ? ((int)digit - (int)'A') + : ((int)digit - (int)'a')) + + 10); + + if (!(((next >= '0') && (next <= '9')) + || ((next >= 'A') && (next <= 'F')) + || ((next >= 'a') && (next <= 'f')))) + { + return c_DummyChar; + } + + return (char)((res << 4) + ((next <= '9') + ? ((int)next - (int)'0') + : (((next <= 'F') + ? ((int)next - (int)'A') + : ((int)next - (int)'a')) + + 10))); + } - // The following string should not be localized because it is used in security decisions. - return Name + ", PublicKey=" + System.Security.Util.Hex.EncodeHexString(key); + private static unsafe bool IsReservedUnreservedOrHash(char c) + { + if (IsUnreserved(c)) + { + return true; + } + return (RFC3986ReservedMarks.IndexOf(c) >= 0); } -#endif - // This call opens and closes the file, but does not add the - // assembly to the domain. - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - static internal extern AssemblyName nGetFileInformation(String s); + internal static unsafe bool IsUnreserved(char c) + { + if (IsAsciiLetterOrDigit(c)) + { + return true; + } + return (RFC3986UnreservedMarks.IndexOf(c) >= 0); + } - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern String nToString(); + //Only consider ASCII characters + internal static bool IsAsciiLetter(char character) + { + return (character >= 'a' && character <= 'z') || + (character >= 'A' && character <= 'Z'); + } - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern byte[] nGetPublicKeyToken(); - - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - static internal extern String EscapeCodeBase(String codeBase); + internal static bool IsAsciiLetterOrDigit(char character) + { + return IsAsciiLetter(character) || (character >= '0' && character <= '9'); + } + + private static readonly char[] s_hexUpperChars = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + internal const char c_DummyChar = (char)0xFFFF; //An Invalid Unicode character used as a dummy char passed into the parameter + private const short c_MaxAsciiCharsReallocate = 40; + private const short c_MaxUnicodeCharsReallocate = 40; + private const short c_MaxUTF_8BytesPerUnicodeChar = 4; + private const short c_EncodedCharsPerByte = 3; + private const string RFC3986ReservedMarks = @":/?#[]@!$&'()*+,;="; + private const string RFC3986UnreservedMarks = @"-._~"; } } diff --git a/src/mscorlib/src/System/Reflection/Associates.cs b/src/mscorlib/src/System/Reflection/Associates.cs index 8b34e77..9eaf74a 100644 --- a/src/mscorlib/src/System/Reflection/Associates.cs +++ b/src/mscorlib/src/System/Reflection/Associates.cs @@ -8,6 +8,7 @@ namespace System.Reflection { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Diagnostics.Contracts; internal static class Associates @@ -35,7 +36,6 @@ namespace System.Reflection return false; } - [System.Security.SecurityCritical] // auto-generated private static unsafe RuntimeMethodInfo AssignAssociates( int tkMethod, RuntimeType declaredType, @@ -44,8 +44,8 @@ namespace System.Reflection if (MetadataToken.IsNullToken(tkMethod)) return null; - Contract.Assert(declaredType != null); - Contract.Assert(reflectedType != null); + Debug.Assert(declaredType != null); + Debug.Assert(reflectedType != null); bool isInherited = declaredType != reflectedType; @@ -63,7 +63,7 @@ namespace System.Reflection } RuntimeMethodHandleInternal associateMethodHandle = ModuleHandle.ResolveMethodHandleInternalCore(RuntimeTypeHandle.GetModule(declaredType), tkMethod, genericArgumentHandles, genericArgumentCount, null, 0); - Contract.Assert(!associateMethodHandle.IsNullHandle(), "Failed to resolve associateRecord methodDef token"); + Debug.Assert(!associateMethodHandle.IsNullHandle(), "Failed to resolve associateRecord methodDef token"); if (isInherited) { @@ -109,7 +109,6 @@ namespace System.Reflection return associateMethod; } - [System.Security.SecurityCritical] // auto-generated internal static unsafe void AssignAssociates( MetadataImport scope, int mdPropEvent, diff --git a/src/mscorlib/src/System/Reflection/ComInterfaces.cs b/src/mscorlib/src/System/Reflection/ComInterfaces.cs index 6343811..6e4b0cc 100644 --- a/src/mscorlib/src/System/Reflection/ComInterfaces.cs +++ b/src/mscorlib/src/System/Reflection/ComInterfaces.cs @@ -2,248 +2,26 @@ // 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.Globalization; -using System.IO; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Runtime.Serialization; -using System.Security.Permissions; -using System.Security.Policy; - namespace System.Runtime.InteropServices { [GuidAttribute("BCA8B44D-AAD6-3A86-8AB7-03349F4F2DA2")] [CLSCompliant(false)] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [TypeLibImportClassAttribute(typeof(System.Type))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _Type { -#if !FEATURE_CORECLR - #region IDispatch Members - void GetTypeInfoCount(out uint pcTInfo); - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); - #endregion - - #region Object Members - String ToString(); - bool Equals(Object other); - int GetHashCode(); - Type GetType(); - #endregion - - #region MemberInfo Members - MemberTypes MemberType { get; } - String Name { get; } - Type DeclaringType { get; } - Type ReflectedType { get; } - Object[] GetCustomAttributes(Type attributeType, bool inherit); - Object[] GetCustomAttributes(bool inherit); - bool IsDefined(Type attributeType, bool inherit); - #endregion - - #region Type Members - Guid GUID { get; } - Module Module { get; } - Assembly Assembly { get; } - RuntimeTypeHandle TypeHandle { get; } - String FullName { get; } - String Namespace { get; } - String AssemblyQualifiedName { get; } - int GetArrayRank(); - Type BaseType { get; } - - ConstructorInfo[] GetConstructors(BindingFlags bindingAttr); - Type GetInterface(String name, bool ignoreCase); - Type[] GetInterfaces(); - Type[] FindInterfaces(TypeFilter filter,Object filterCriteria); - EventInfo GetEvent(String name,BindingFlags bindingAttr); - EventInfo[] GetEvents(); - EventInfo[] GetEvents(BindingFlags bindingAttr); - Type[] GetNestedTypes(BindingFlags bindingAttr); - Type GetNestedType(String name, BindingFlags bindingAttr); - MemberInfo[] GetMember(String name, MemberTypes type, BindingFlags bindingAttr); - MemberInfo[] GetDefaultMembers(); - MemberInfo[] FindMembers(MemberTypes memberType,BindingFlags bindingAttr,MemberFilter filter,Object filterCriteria); - Type GetElementType(); - bool IsSubclassOf(Type c); - bool IsInstanceOfType(Object o); - bool IsAssignableFrom(Type c); - InterfaceMapping GetInterfaceMap(Type interfaceType); - MethodInfo GetMethod(String name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers); - MethodInfo GetMethod(String name, BindingFlags bindingAttr); - MethodInfo[] GetMethods(BindingFlags bindingAttr); - FieldInfo GetField(String name, BindingFlags bindingAttr); - FieldInfo[] GetFields(BindingFlags bindingAttr); - PropertyInfo GetProperty(String name, BindingFlags bindingAttr); - PropertyInfo GetProperty(String name,BindingFlags bindingAttr,Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers); - PropertyInfo[] GetProperties(BindingFlags bindingAttr); - MemberInfo[] GetMember(String name, BindingFlags bindingAttr); - MemberInfo[] GetMembers(BindingFlags bindingAttr); - Object InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParameters); - Type UnderlyingSystemType - { - get; - } - - Object InvokeMember(String name,BindingFlags invokeAttr,Binder binder, Object target, Object[] args, CultureInfo culture); - Object InvokeMember(String name,BindingFlags invokeAttr,Binder binder, Object target, Object[] args); - ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers); - ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers); - ConstructorInfo GetConstructor(Type[] types); - ConstructorInfo[] GetConstructors(); - ConstructorInfo TypeInitializer - { - get; - } - - MethodInfo GetMethod(String name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers); - MethodInfo GetMethod(String name, Type[] types, ParameterModifier[] modifiers); - MethodInfo GetMethod(String name, Type[] types); - MethodInfo GetMethod(String name); - MethodInfo[] GetMethods(); - FieldInfo GetField(String name); - FieldInfo[] GetFields(); - Type GetInterface(String name); - EventInfo GetEvent(String name); - PropertyInfo GetProperty(String name, Type returnType, Type[] types,ParameterModifier[] modifiers); - PropertyInfo GetProperty(String name, Type returnType, Type[] types); - PropertyInfo GetProperty(String name, Type[] types); - PropertyInfo GetProperty(String name, Type returnType); - PropertyInfo GetProperty(String name); - PropertyInfo[] GetProperties(); - Type[] GetNestedTypes(); - Type GetNestedType(String name); - MemberInfo[] GetMember(String name); - MemberInfo[] GetMembers(); - TypeAttributes Attributes { get; } - bool IsNotPublic { get; } - bool IsPublic { get; } - bool IsNestedPublic { get; } - bool IsNestedPrivate { get; } - bool IsNestedFamily { get; } - bool IsNestedAssembly { get; } - bool IsNestedFamANDAssem { get; } - bool IsNestedFamORAssem { get; } - bool IsAutoLayout { get; } - bool IsLayoutSequential { get; } - bool IsExplicitLayout { get; } - bool IsClass { get; } - bool IsInterface { get; } - bool IsValueType { get; } - bool IsAbstract { get; } - bool IsSealed { get; } - bool IsEnum { get; } - bool IsSpecialName { get; } - bool IsImport { get; } - bool IsSerializable { get; } - bool IsAnsiClass { get; } - bool IsUnicodeClass { get; } - bool IsAutoClass { get; } - bool IsArray { get; } - bool IsByRef { get; } - bool IsPointer { get; } - bool IsPrimitive { get; } - bool IsCOMObject { get; } - bool HasElementType { get; } - bool IsContextful { get; } - bool IsMarshalByRef { get; } - bool Equals(Type o); - #endregion -#endif } [GuidAttribute("17156360-2f1a-384a-bc52-fde93c215c5b")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)] [TypeLibImportClassAttribute(typeof(System.Reflection.Assembly))] [CLSCompliant(false)] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _Assembly { -#if !FEATURE_CORECLR - #region Object Members - String ToString(); - bool Equals(Object other); - int GetHashCode(); - Type GetType(); - #endregion - - #region Assembly Members - String CodeBase { -#if FEATURE_CORECLR -[System.Security.SecurityCritical] // auto-generated -#endif -get; } - String EscapedCodeBase { get; } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif - AssemblyName GetName(); - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif - AssemblyName GetName(bool copiedName); - String FullName { get; } - MethodInfo EntryPoint { get; } - Type GetType(String name); - Type GetType(String name, bool throwOnError); - Type[] GetExportedTypes(); - Type[] GetTypes(); - Stream GetManifestResourceStream(Type type, String name); - Stream GetManifestResourceStream(String name); - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif - FileStream GetFile(String name); - FileStream[] GetFiles(); - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif - FileStream[] GetFiles(bool getResourceModules); - String[] GetManifestResourceNames(); - ManifestResourceInfo GetManifestResourceInfo(String resourceName); - String Location { -#if FEATURE_CORECLR -[System.Security.SecurityCritical] // auto-generated -#endif -get; } -#if FEATURE_CAS_POLICY - Evidence Evidence { get; } -#endif // FEATURE_CAS_POLICY - Object[] GetCustomAttributes(Type attributeType, bool inherit); - Object[] GetCustomAttributes(bool inherit); - bool IsDefined(Type attributeType, bool inherit); -#if FEATURE_SERIALIZATION - [System.Security.SecurityCritical] // auto-generated_required - void GetObjectData(SerializationInfo info, StreamingContext context); -#endif - [method: System.Security.SecurityCritical] - event ModuleResolveEventHandler ModuleResolve; - Type GetType(String name, bool throwOnError, bool ignoreCase); - Assembly GetSatelliteAssembly(CultureInfo culture); - Assembly GetSatelliteAssembly(CultureInfo culture, Version version); -#if FEATURE_MULTIMODULE_ASSEMBLIES - Module LoadModule(String moduleName, byte[] rawModule); - Module LoadModule(String moduleName, byte[] rawModule, byte[] rawSymbolStore); -#endif - Object CreateInstance(String typeName); - Object CreateInstance(String typeName, bool ignoreCase); - Object CreateInstance(String typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes); - Module[] GetLoadedModules(); - Module[] GetLoadedModules(bool getResourceModules); - Module[] GetModules(); - Module[] GetModules(bool getResourceModules); - Module GetModule(String name); - AssemblyName[] GetReferencedAssemblies(); - bool GlobalAssemblyCache { get; } - #endregion -#endif } - [GuidAttribute("f7102fa9-cabb-3a74-a6da-b4567ef1b079")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [TypeLibImportClassAttribute(typeof(System.Reflection.MemberInfo))] @@ -251,34 +29,8 @@ get; } [System.Runtime.InteropServices.ComVisible(true)] public interface _MemberInfo { -#if !FEATURE_CORECLR - #region IDispatch Members - void GetTypeInfoCount(out uint pcTInfo); - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); - #endregion - - #region Object Members - String ToString(); - bool Equals(Object other); - int GetHashCode(); - Type GetType(); - #endregion - - #region MemberInfo Members - MemberTypes MemberType { get; } - String Name { get; } - Type DeclaringType { get; } - Type ReflectedType { get; } - Object[] GetCustomAttributes(Type attributeType, bool inherit); - Object[] GetCustomAttributes(bool inherit); - bool IsDefined(Type attributeType, bool inherit); - #endregion -#endif } - [GuidAttribute("6240837A-707F-3181-8E98-A36AE086766B")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] @@ -286,57 +38,8 @@ get; } [System.Runtime.InteropServices.ComVisible(true)] public interface _MethodBase { -#if !FEATURE_CORECLR - #region IDispatch Members - void GetTypeInfoCount(out uint pcTInfo); - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); - #endregion - - #region Object Members - String ToString(); - bool Equals(Object other); - int GetHashCode(); - Type GetType(); - #endregion - - #region MemberInfo Members - MemberTypes MemberType { get; } - String Name { get; } - Type DeclaringType { get; } - Type ReflectedType { get; } - Object[] GetCustomAttributes(Type attributeType, bool inherit); - Object[] GetCustomAttributes(bool inherit); - bool IsDefined(Type attributeType, bool inherit); - #endregion - - #region MethodBase Members - ParameterInfo[] GetParameters(); - MethodImplAttributes GetMethodImplementationFlags(); - RuntimeMethodHandle MethodHandle { get; } - MethodAttributes Attributes { get; } - CallingConventions CallingConvention { get; } - Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture); - bool IsPublic { get; } - bool IsPrivate { get; } - bool IsFamily { get; } - bool IsAssembly { get; } - bool IsFamilyAndAssembly { get; } - bool IsFamilyOrAssembly { get; } - bool IsStatic { get; } - bool IsFinal { get; } - bool IsVirtual { get; } - bool IsHideBySig { get; } - bool IsAbstract { get; } - bool IsSpecialName { get; } - bool IsConstructor { get; } - Object Invoke(Object obj, Object[] parameters); - #endregion -#endif } - [GuidAttribute("FFCC1B5D-ECB8-38DD-9B01-3DC8ABC2AA5F")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] @@ -344,62 +47,7 @@ get; } [System.Runtime.InteropServices.ComVisible(true)] public interface _MethodInfo { -#if !FEATURE_CORECLR - #region IDispatch Members - void GetTypeInfoCount(out uint pcTInfo); - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); - #endregion - - #region Object Members - String ToString(); - bool Equals(Object other); - int GetHashCode(); - Type GetType(); - #endregion - - #region MemberInfo Members - MemberTypes MemberType { get; } - String Name { get; } - Type DeclaringType { get; } - Type ReflectedType { get; } - Object[] GetCustomAttributes(Type attributeType, bool inherit); - Object[] GetCustomAttributes(bool inherit); - bool IsDefined(Type attributeType, bool inherit); - #endregion - - #region MethodBase Members - ParameterInfo[] GetParameters(); - MethodImplAttributes GetMethodImplementationFlags(); - RuntimeMethodHandle MethodHandle { get; } - MethodAttributes Attributes { get; } - CallingConventions CallingConvention { get; } - Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture); - bool IsPublic { get; } - bool IsPrivate { get; } - bool IsFamily { get; } - bool IsAssembly { get; } - bool IsFamilyAndAssembly { get; } - bool IsFamilyOrAssembly { get; } - bool IsStatic { get; } - bool IsFinal { get; } - bool IsVirtual { get; } - bool IsHideBySig { get; } - bool IsAbstract { get; } - bool IsSpecialName { get; } - bool IsConstructor { get; } - Object Invoke(Object obj, Object[] parameters); - #endregion - - #region MethodInfo Members - Type ReturnType { get; } - ICustomAttributeProvider ReturnTypeCustomAttributes { get; } - MethodInfo GetBaseDefinition(); - #endregion -#endif } - [GuidAttribute("E9A19478-9646-3679-9B10-8411AE1FD57D")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] @@ -408,174 +56,26 @@ get; } [System.Runtime.InteropServices.ComVisible(true)] public interface _ConstructorInfo { -#if !FEATURE_CORECLR - #region IDispatch Members - void GetTypeInfoCount(out uint pcTInfo); - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); - #endregion - - #region Object Members - String ToString(); - bool Equals(Object other); - int GetHashCode(); - Type GetType(); - #endregion - - #region MemberInfo Members - MemberTypes MemberType { get; } - String Name { get; } - Type DeclaringType { get; } - Type ReflectedType { get; } - Object[] GetCustomAttributes(Type attributeType, bool inherit); - Object[] GetCustomAttributes(bool inherit); - bool IsDefined(Type attributeType, bool inherit); - #endregion - - #region MethodBase Members - ParameterInfo[] GetParameters(); - MethodImplAttributes GetMethodImplementationFlags(); - RuntimeMethodHandle MethodHandle { get; } - MethodAttributes Attributes { get; } - CallingConventions CallingConvention { get; } - Object Invoke_2(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture); - bool IsPublic { get; } - bool IsPrivate { get; } - bool IsFamily { get; } - bool IsAssembly { get; } - bool IsFamilyAndAssembly { get; } - bool IsFamilyOrAssembly { get; } - bool IsStatic { get; } - bool IsFinal { get; } - bool IsVirtual { get; } - bool IsHideBySig { get; } - bool IsAbstract { get; } - bool IsSpecialName { get; } - bool IsConstructor { get; } - Object Invoke_3(Object obj, Object[] parameters); - #endregion - - #region ConstructorInfo - Object Invoke_4(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture); - Object Invoke_5(Object[] parameters); - #endregion -#endif } - [GuidAttribute("8A7C1442-A9FB-366B-80D8-4939FFA6DBE0")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Reflection.FieldInfo))] [System.Runtime.InteropServices.ComVisible(true)] public interface _FieldInfo - { -#if !FEATURE_CORECLR - #region IDispatch Members - void GetTypeInfoCount(out uint pcTInfo); - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); - #endregion - - #region Object Members - String ToString(); - bool Equals(Object other); - int GetHashCode(); - Type GetType(); - #endregion - - #region MemberInfo Members - MemberTypes MemberType { get; } - String Name { get; } - Type DeclaringType { get; } - Type ReflectedType { get; } - Object[] GetCustomAttributes(Type attributeType, bool inherit); - Object[] GetCustomAttributes(bool inherit); - bool IsDefined(Type attributeType, bool inherit); - #endregion - - #region FieldInfo Members - Type FieldType { get; } - Object GetValue(Object obj); - Object GetValueDirect(TypedReference obj); - void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture); - void SetValueDirect(TypedReference obj,Object value); - RuntimeFieldHandle FieldHandle { get; } - FieldAttributes Attributes { get; } - void SetValue(Object obj, Object value); - bool IsPublic { get; } - bool IsPrivate { get; } - bool IsFamily { get; } - bool IsAssembly { get; } - bool IsFamilyAndAssembly { get; } - bool IsFamilyOrAssembly { get; } - bool IsStatic { get; } - bool IsInitOnly { get; } - bool IsLiteral { get; } - bool IsNotSerialized { get; } - bool IsSpecialName { get; } - bool IsPinvokeImpl { get; } - #endregion -#endif + { } - [GuidAttribute("F59ED4E4-E68F-3218-BD77-061AA82824BF")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Reflection.PropertyInfo))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _PropertyInfo { -#if !FEATURE_CORECLR - #region IDispatch Members - void GetTypeInfoCount(out uint pcTInfo); - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); - #endregion - - #region Object Members - String ToString(); - bool Equals(Object other); - int GetHashCode(); - Type GetType(); - #endregion - - #region MemberInfo Members - MemberTypes MemberType { get; } - String Name { get; } - Type DeclaringType { get; } - Type ReflectedType { get; } - Object[] GetCustomAttributes(Type attributeType, bool inherit); - Object[] GetCustomAttributes(bool inherit); - bool IsDefined(Type attributeType, bool inherit); - #endregion - - #region Property Members - Type PropertyType { get; } - Object GetValue(Object obj,Object[] index); - Object GetValue(Object obj,BindingFlags invokeAttr,Binder binder, Object[] index, CultureInfo culture); - void SetValue(Object obj, Object value, Object[] index); - void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture); - MethodInfo[] GetAccessors(bool nonPublic); - MethodInfo GetGetMethod(bool nonPublic); - MethodInfo GetSetMethod(bool nonPublic); - ParameterInfo[] GetIndexParameters(); - PropertyAttributes Attributes { get; } - bool CanRead { get; } - bool CanWrite { get; } - MethodInfo[] GetAccessors(); - MethodInfo GetGetMethod(); - MethodInfo GetSetMethod(); - bool IsSpecialName { get; } - #endregion -#endif } - [GuidAttribute("9DE59C64-D889-35A1-B897-587D74469E5B")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] @@ -583,91 +83,33 @@ get; } [System.Runtime.InteropServices.ComVisible(true)] public interface _EventInfo { -#if !FEATURE_CORECLR - #region IDispatch Members - void GetTypeInfoCount(out uint pcTInfo); - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); - #endregion - - #region Object Members - String ToString(); - bool Equals(Object other); - int GetHashCode(); - Type GetType(); - #endregion - - #region MemberInfo Members - MemberTypes MemberType { get; } - String Name { get; } - Type DeclaringType { get; } - Type ReflectedType { get; } - Object[] GetCustomAttributes(Type attributeType, bool inherit); - Object[] GetCustomAttributes(bool inherit); - bool IsDefined(Type attributeType, bool inherit); - #endregion - - #region EventInfo Members - MethodInfo GetAddMethod(bool nonPublic); - MethodInfo GetRemoveMethod(bool nonPublic); - MethodInfo GetRaiseMethod(bool nonPublic); - EventAttributes Attributes { get; } - MethodInfo GetAddMethod(); - MethodInfo GetRemoveMethod(); - MethodInfo GetRaiseMethod(); - void AddEventHandler(Object target, Delegate handler); - void RemoveEventHandler(Object target, Delegate handler); - Type EventHandlerType { get; } - bool IsSpecialName { get; } - bool IsMulticast { get; } - #endregion -#endif } [GuidAttribute("993634C4-E47A-32CC-BE08-85F567DC27D6")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Reflection.ParameterInfo))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _ParameterInfo { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); -#endif } [GuidAttribute("D002E9BA-D9E3-3749-B1D3-D565A08B13E7")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Reflection.Module))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _Module { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); -#endif } [GuidAttribute("B42B6AAC-317E-34D5-9FA9-093BB4160C50")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Reflection.AssemblyName))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _AssemblyName { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); -#endif } } diff --git a/src/mscorlib/src/System/Reflection/ConstructorInfo.cs b/src/mscorlib/src/System/Reflection/ConstructorInfo.cs index d5b5cc3..3d927fc 100644 --- a/src/mscorlib/src/System/Reflection/ConstructorInfo.cs +++ b/src/mscorlib/src/System/Reflection/ConstructorInfo.cs @@ -14,9 +14,6 @@ namespace System.Reflection using System.Runtime; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; -#if FEATURE_REMOTING - using System.Runtime.Remoting.Metadata; -#endif //FEATURE_REMOTING using System.Runtime.Serialization; using System.Security; using System.Security.Permissions; @@ -28,9 +25,6 @@ namespace System.Reflection [Serializable] [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_ConstructorInfo))] -#pragma warning disable 618 - [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")] -#pragma warning restore 618 [System.Runtime.InteropServices.ComVisible(true)] public abstract class ConstructorInfo : MethodBase, _ConstructorInfo { @@ -101,57 +95,6 @@ namespace System.Reflection return Invoke(BindingFlags.Default, null, parameters, null); } #endregion - -#if !FEATURE_CORECLR - #region COM Interop Support - Type _ConstructorInfo.GetType() - { - return base.GetType(); - } - - Object _ConstructorInfo.Invoke_2(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) - { - return Invoke(obj, invokeAttr, binder, parameters, culture); - } - - Object _ConstructorInfo.Invoke_3(Object obj, Object[] parameters) - { - return Invoke(obj, parameters); - } - - Object _ConstructorInfo.Invoke_4(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) - { - return Invoke(invokeAttr, binder, parameters, culture); - } - - Object _ConstructorInfo.Invoke_5(Object[] parameters) - { - return Invoke(parameters); - } - - void _ConstructorInfo.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _ConstructorInfo.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _ConstructorInfo.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - // If you implement this method, make sure to include _ConstructorInfo.Invoke in VM\DangerousAPIs.h and - // include _ConstructorInfo in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp. - void _ConstructorInfo.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } - #endregion -#endif } [Serializable] @@ -205,7 +148,6 @@ namespace System.Reflection internal INVOCATION_FLAGS InvocationFlags { - [System.Security.SecuritySafeCritical] get { if ((m_invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0) @@ -261,7 +203,6 @@ namespace System.Reflection #endregion #region Constructor - [System.Security.SecurityCritical] // auto-generated internal RuntimeConstructorInfo( RuntimeMethodHandleInternal handle, RuntimeType declaringType, RuntimeTypeCache reflectedTypeCache, MethodAttributes methodAttributes, BindingFlags bindingFlags) @@ -276,40 +217,9 @@ namespace System.Reflection } #endregion -#if FEATURE_REMOTING - #region Legacy Remoting Cache - // The size of CachedData is accounted for by BaseObjectWithCachedData in object.h. - // This member is currently being used by Remoting for caching remoting data. If you - // need to cache data here, talk to the Remoting team to work out a mechanism, so that - // both caching systems can happily work together. - private RemotingMethodCachedData m_cachedData; - - internal RemotingMethodCachedData RemotingCache - { - get - { - // This grabs an internal copy of m_cachedData and uses - // that instead of looking at m_cachedData directly because - // the cache may get cleared asynchronously. This prevents - // us from having to take a lock. - RemotingMethodCachedData cache = m_cachedData; - if (cache == null) - { - cache = new RemotingMethodCachedData(this); - RemotingMethodCachedData ret = Interlocked.CompareExchange(ref m_cachedData, cache, null); - if (ret != null) - cache = ret; - } - return cache; - } - } - #endregion -#endif //FEATURE_REMOTING - #region NonPublic Methods RuntimeMethodHandleInternal IRuntimeMethodInfo.Value { - [System.Security.SecuritySafeCritical] get { return new RuntimeMethodHandleInternal(m_handle); @@ -397,28 +307,27 @@ namespace System.Reflection public override Object[] GetCustomAttributes(Type attributeType, bool inherit) { if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),nameof(attributeType)); return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType); } - [System.Security.SecuritySafeCritical] // auto-generated public override bool IsDefined(Type attributeType, bool inherit) { if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),nameof(attributeType)); return CustomAttribute.IsDefined(this, attributeRuntimeType); } @@ -433,7 +342,6 @@ namespace System.Reflection #region MemberInfo Overrides public override String Name { - [System.Security.SecuritySafeCritical] // auto-generated get { return RuntimeMethodHandle.GetName(this); } } [System.Runtime.InteropServices.ComVisible(true)] @@ -457,7 +365,6 @@ namespace System.Reflection public override int MetadataToken { - [System.Security.SecuritySafeCritical] // auto-generated get { return RuntimeMethodHandle.GetMethodDef(this); } } public override Module Module @@ -475,7 +382,6 @@ namespace System.Reflection // This seems to always returns System.Void. internal override Type GetReturnType() { return Signature.ReturnType; } - [System.Security.SecuritySafeCritical] // auto-generated internal override ParameterInfo[] GetParametersNoCopy() { if (m_parameters == null) @@ -532,7 +438,7 @@ namespace System.Reflection internal static void CheckCanCreateInstance(Type declaringType, bool isVarArg) { if (declaringType == null) - throw new ArgumentNullException("declaringType"); + throw new ArgumentNullException(nameof(declaringType)); Contract.EndContractBlock(); // ctor is ReflectOnly @@ -580,7 +486,6 @@ namespace System.Reflection throw new TargetException(); } - [System.Security.SecuritySafeCritical] // auto-generated [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable @@ -607,26 +512,10 @@ namespace System.Reflection if (obj != null) { - -#if FEATURE_CORECLR // For unverifiable code, we require the caller to be critical. // Adding the INVOCATION_FLAGS_NEED_SECURITY flag makes that check happen invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY; -#else // FEATURE_CORECLR - new SecurityPermission(SecurityPermissionFlag.SkipVerification).Demand(); -#endif // FEATURE_CORECLR - - } - -#if !FEATURE_CORECLR - if ((invocationFlags &(INVOCATION_FLAGS.INVOCATION_FLAGS_RISKY_METHOD | INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY)) != 0) - { - if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_RISKY_METHOD) != 0) - CodeAccessPermission.Demand(PermissionType.ReflectionMemberAccess); - if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY) != 0) - RuntimeMethodHandle.PerformSecurityCheck(obj, this, m_declaringType, (uint)m_invocationFlags); } -#endif // !FEATURE_CORECLR Signature sig = Signature; @@ -650,7 +539,6 @@ namespace System.Reflection } - [System.Security.SecuritySafeCritical] // overrides SC member #pragma warning disable 618 [ReflectionPermissionAttribute(SecurityAction.Demand, Flags = ReflectionPermissionFlag.MemberAccess)] #pragma warning restore 618 @@ -664,17 +552,17 @@ namespace System.Reflection public override bool IsSecurityCritical { - get { return RuntimeMethodHandle.IsSecurityCritical(this); } + get { return true; } } public override bool IsSecuritySafeCritical { - get { return RuntimeMethodHandle.IsSecuritySafeCritical(this); } + get { return false; } } public override bool IsSecurityTransparent { - get { return RuntimeMethodHandle.IsSecurityTransparent(this); } + get { return false; } } public override bool ContainsGenericParameters @@ -687,7 +575,6 @@ namespace System.Reflection #endregion #region ConstructorInfo Overrides - [System.Security.SecuritySafeCritical] // auto-generated [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable @@ -711,18 +598,6 @@ namespace System.Reflection } #endif -#if !FEATURE_CORECLR - if ((invocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_RISKY_METHOD | INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY | INVOCATION_FLAGS.INVOCATION_FLAGS_IS_DELEGATE_CTOR)) != 0) - { - if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_RISKY_METHOD) != 0) - CodeAccessPermission.Demand(PermissionType.ReflectionMemberAccess); - if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY) != 0) - RuntimeMethodHandle.PerformSecurityCheck(null, this, m_declaringType, (uint)(m_invocationFlags | INVOCATION_FLAGS.INVOCATION_FLAGS_CONSTRUCTOR_INVOKE)); - if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_IS_DELEGATE_CTOR) != 0) - new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); - } -#endif // !FEATURE_CORECLR - // get the signature Signature sig = Signature; @@ -749,11 +624,10 @@ namespace System.Reflection #endregion #region ISerializable Implementation - [System.Security.SecurityCritical] // auto-generated public void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); MemberInfoSerializationHolder.GetSerializationInfo( info, @@ -777,5 +651,4 @@ namespace System.Reflection } #endregion } - } diff --git a/src/mscorlib/src/System/Reflection/CustomAttribute.cs b/src/mscorlib/src/System/Reflection/CustomAttribute.cs index 463c976..e568a17 100644 --- a/src/mscorlib/src/System/Reflection/CustomAttribute.cs +++ b/src/mscorlib/src/System/Reflection/CustomAttribute.cs @@ -29,7 +29,7 @@ namespace System.Reflection public static IList GetCustomAttributes(MemberInfo target) { if (target == null) - throw new ArgumentNullException("target"); + throw new ArgumentNullException(nameof(target)); return target.GetCustomAttributesData(); } @@ -37,7 +37,7 @@ namespace System.Reflection public static IList GetCustomAttributes(Module target) { if (target == null) - throw new ArgumentNullException("target"); + throw new ArgumentNullException(nameof(target)); Contract.EndContractBlock(); return target.GetCustomAttributesData(); @@ -46,7 +46,7 @@ namespace System.Reflection public static IList GetCustomAttributes(Assembly target) { if (target == null) - throw new ArgumentNullException("target"); + throw new ArgumentNullException(nameof(target)); Contract.EndContractBlock(); return target.GetCustomAttributesData(); @@ -55,7 +55,7 @@ namespace System.Reflection public static IList GetCustomAttributes(ParameterInfo target) { if (target == null) - throw new ArgumentNullException("target"); + throw new ArgumentNullException(nameof(target)); Contract.EndContractBlock(); return target.GetCustomAttributesData(); @@ -63,10 +63,9 @@ namespace System.Reflection #endregion #region Internal Static Members - [System.Security.SecuritySafeCritical] // auto-generated internal static IList GetCustomAttributesInternal(RuntimeType target) { - Contract.Assert(target != null); + Debug.Assert(target != null); IList cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken); @@ -86,10 +85,9 @@ namespace System.Reflection return Array.AsReadOnly(pca); } - [System.Security.SecuritySafeCritical] // auto-generated internal static IList GetCustomAttributesInternal(RuntimeFieldInfo target) { - Contract.Assert(target != null); + Debug.Assert(target != null); IList cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken); @@ -109,10 +107,9 @@ namespace System.Reflection return Array.AsReadOnly(pca); } - [System.Security.SecuritySafeCritical] // auto-generated internal static IList GetCustomAttributesInternal(RuntimeMethodInfo target) { - Contract.Assert(target != null); + Debug.Assert(target != null); IList cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken); @@ -132,34 +129,30 @@ namespace System.Reflection return Array.AsReadOnly(pca); } - [System.Security.SecuritySafeCritical] // auto-generated internal static IList GetCustomAttributesInternal(RuntimeConstructorInfo target) { - Contract.Assert(target != null); + Debug.Assert(target != null); return GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken); } - [System.Security.SecuritySafeCritical] // auto-generated internal static IList GetCustomAttributesInternal(RuntimeEventInfo target) { - Contract.Assert(target != null); + Debug.Assert(target != null); return GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken); } - [System.Security.SecuritySafeCritical] // auto-generated internal static IList GetCustomAttributesInternal(RuntimePropertyInfo target) { - Contract.Assert(target != null); + Debug.Assert(target != null); return GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken); } - [System.Security.SecuritySafeCritical] // auto-generated internal static IList GetCustomAttributesInternal(RuntimeModule target) { - Contract.Assert(target != null); + Debug.Assert(target != null); if (target.IsResource()) return new List(); @@ -167,10 +160,9 @@ namespace System.Reflection return GetCustomAttributes(target, target.MetadataToken); } - [System.Security.SecuritySafeCritical] // auto-generated internal static IList GetCustomAttributesInternal(RuntimeAssembly target) { - Contract.Assert(target != null); + Debug.Assert(target != null); IList cad = GetCustomAttributes((RuntimeModule)target.ManifestModule, RuntimeAssembly.GetToken(target.GetNativeHandle())); @@ -190,10 +182,9 @@ namespace System.Reflection return Array.AsReadOnly(pca); } - [System.Security.SecuritySafeCritical] // auto-generated internal static IList GetCustomAttributesInternal(RuntimeParameterInfo target) { - Contract.Assert(target != null); + Debug.Assert(target != null); IList cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken); @@ -279,7 +270,7 @@ namespace System.Reflection if (type.IsValueType) return CustomAttributeEncoding.Undefined; - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidKindOfTypeForCA"), "type"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidKindOfTypeForCA"), nameof(type)); } private static CustomAttributeType InitCustomAttributeType(RuntimeType parameterType) { @@ -302,7 +293,6 @@ namespace System.Reflection return new CustomAttributeType(encodedType, encodedArrayType, encodedEnumType, enumName); } - [System.Security.SecurityCritical] // auto-generated private static IList GetCustomAttributes(RuntimeModule module, int tkTarget) { CustomAttributeRecord[] records = GetCustomAttributeRecords(module, tkTarget); @@ -316,7 +306,6 @@ namespace System.Reflection #endregion #region Internal Static Members - [System.Security.SecurityCritical] // auto-generated internal unsafe static CustomAttributeRecord[] GetCustomAttributeRecords(RuntimeModule module, int targetToken) { MetadataImport scope = module.MetadataImport; @@ -369,7 +358,6 @@ namespace System.Reflection { } - [System.Security.SecuritySafeCritical] // auto-generated private CustomAttributeData(RuntimeModule scope, CustomAttributeRecord caRecord) { m_scope = scope; @@ -611,7 +599,7 @@ namespace System.Reflection public CustomAttributeNamedArgument(MemberInfo memberInfo, object value) { if (memberInfo == null) - throw new ArgumentNullException("memberInfo"); + throw new ArgumentNullException(nameof(memberInfo)); Type type = null; FieldInfo field = memberInfo as FieldInfo; @@ -631,7 +619,7 @@ namespace System.Reflection public CustomAttributeNamedArgument(MemberInfo memberInfo, CustomAttributeTypedArgument typedArgument) { if (memberInfo == null) - throw new ArgumentNullException("memberInfo"); + throw new ArgumentNullException(nameof(memberInfo)); m_memberInfo = memberInfo; m_value = typedArgument; @@ -749,11 +737,10 @@ namespace System.Reflection return typeof(object); default : - throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)encodedType), "encodedType"); + throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)encodedType), nameof(encodedType)); } } - [SecuritySafeCritical] private static object EncodedValueToRawValue(long val, CustomAttributeEncoding encodedType) { switch (encodedType) @@ -795,7 +782,7 @@ namespace System.Reflection unsafe { return *(double*)&val; } default: - throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)val), "val"); + throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)val), nameof(val)); } } private static RuntimeType ResolveType(RuntimeModule scope, string typeName) @@ -820,7 +807,7 @@ namespace System.Reflection { // value can be null. if (argumentType == null) - throw new ArgumentNullException("argumentType"); + throw new ArgumentNullException(nameof(argumentType)); m_value = (value == null) ? null : CanonicalizeValue(value); m_argumentType = argumentType; @@ -830,7 +817,7 @@ namespace System.Reflection { // value cannot be null. if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); m_value = CanonicalizeValue(value); m_argumentType = value.GetType(); @@ -838,7 +825,7 @@ namespace System.Reflection private static object CanonicalizeValue(object value) { - Contract.Assert(value != null); + Debug.Assert(value != null); if (value.GetType().IsEnum) { @@ -852,7 +839,7 @@ namespace System.Reflection CustomAttributeEncoding encodedType = encodedArg.CustomAttributeType.EncodedType; if (encodedType == CustomAttributeEncoding.Undefined) - throw new ArgumentException("encodedArg"); + throw new ArgumentException(null, nameof(encodedArg)); else if (encodedType == CustomAttributeEncoding.Enum) { @@ -1015,7 +1002,6 @@ namespace System.Reflection internal struct CustomAttributeEncodedArgument { #region Parser - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void ParseAttributeArguments( IntPtr pCa, @@ -1024,18 +1010,17 @@ namespace System.Reflection ref CustomAttributeNamedParameter[] CustomAttributeTypedArgument, RuntimeAssembly assembly); - [System.Security.SecurityCritical] // auto-generated internal static void ParseAttributeArguments(ConstArray attributeBlob, ref CustomAttributeCtorParameter[] customAttributeCtorParameters, ref CustomAttributeNamedParameter[] customAttributeNamedParameters, RuntimeModule customAttributeModule) { if (customAttributeModule == null) - throw new ArgumentNullException("customAttributeModule"); + throw new ArgumentNullException(nameof(customAttributeModule)); Contract.EndContractBlock(); - Contract.Assert(customAttributeCtorParameters != null); - Contract.Assert(customAttributeNamedParameters != null); + Debug.Assert(customAttributeCtorParameters != null); + Debug.Assert(customAttributeNamedParameters != null); if (customAttributeCtorParameters.Length != 0 || customAttributeNamedParameters.Length != 0) { @@ -1083,7 +1068,7 @@ namespace System.Reflection public CustomAttributeNamedParameter(string argumentName, CustomAttributeEncoding fieldOrProperty, CustomAttributeType type) { if (argumentName == null) - throw new ArgumentNullException("argumentName"); + throw new ArgumentNullException(nameof(argumentName)); Contract.EndContractBlock(); m_argumentName = argumentName; @@ -1131,11 +1116,9 @@ namespace System.Reflection IntPtr m_Next; IntPtr m_Assembly; - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern void Push(RuntimeAssembly assembly); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public extern void Pop(); @@ -1183,7 +1166,6 @@ namespace System.Reflection #endregion #region Internal Static Members - [System.Security.SecurityCritical] // auto-generated internal static bool IsDefined(RuntimeType type, RuntimeType caType, bool inherit) { Contract.Requires(type != null); @@ -1213,7 +1195,6 @@ namespace System.Reflection return false; } - [System.Security.SecuritySafeCritical] // auto-generated internal static bool IsDefined(RuntimeMethodInfo method, RuntimeType caType, bool inherit) { Contract.Requires(method != null); @@ -1241,7 +1222,6 @@ namespace System.Reflection return false; } - [System.Security.SecurityCritical] // auto-generated internal static bool IsDefined(RuntimeConstructorInfo ctor, RuntimeType caType) { Contract.Requires(ctor != null); @@ -1253,7 +1233,6 @@ namespace System.Reflection return IsCustomAttributeDefined(ctor.GetRuntimeModule(), ctor.MetadataToken, caType); } - [System.Security.SecurityCritical] // auto-generated internal static bool IsDefined(RuntimePropertyInfo property, RuntimeType caType) { Contract.Requires(property != null); @@ -1265,7 +1244,6 @@ namespace System.Reflection return IsCustomAttributeDefined(property.GetRuntimeModule(), property.MetadataToken, caType); } - [System.Security.SecurityCritical] // auto-generated internal static bool IsDefined(RuntimeEventInfo e, RuntimeType caType) { Contract.Requires(e != null); @@ -1277,7 +1255,6 @@ namespace System.Reflection return IsCustomAttributeDefined(e.GetRuntimeModule(), e.MetadataToken, caType); } - [System.Security.SecurityCritical] // auto-generated internal static bool IsDefined(RuntimeFieldInfo field, RuntimeType caType) { Contract.Requires(field != null); @@ -1289,7 +1266,6 @@ namespace System.Reflection return IsCustomAttributeDefined(field.GetRuntimeModule(), field.MetadataToken, caType); } - [System.Security.SecurityCritical] // auto-generated internal static bool IsDefined(RuntimeParameterInfo parameter, RuntimeType caType) { Contract.Requires(parameter != null); @@ -1301,7 +1277,6 @@ namespace System.Reflection return IsCustomAttributeDefined(parameter.GetRuntimeModule(), parameter.MetadataToken, caType); } - [System.Security.SecuritySafeCritical] // auto-generated internal static bool IsDefined(RuntimeAssembly assembly, RuntimeType caType) { Contract.Requires(assembly != null); @@ -1313,7 +1288,6 @@ namespace System.Reflection return IsCustomAttributeDefined(assembly.ManifestModule as RuntimeModule, RuntimeAssembly.GetToken(assembly.GetNativeHandle()), caType); } - [System.Security.SecurityCritical] // auto-generated internal static bool IsDefined(RuntimeModule module, RuntimeType caType) { Contract.Requires(module != null); @@ -1325,7 +1299,6 @@ namespace System.Reflection return IsCustomAttributeDefined(module, module.MetadataToken, caType); } - [System.Security.SecurityCritical] // auto-generated internal static Object[] GetCustomAttributes(RuntimeType type, RuntimeType caType, bool inherit) { Contract.Requires(type != null); @@ -1388,7 +1361,7 @@ namespace System.Reflection else { type = type.DeclaringType as RuntimeType; - Contract.Assert(type != null); + Debug.Assert(type != null); } } @@ -1397,16 +1370,7 @@ namespace System.Reflection private static bool SpecialAllowCriticalAttributes(RuntimeType type) { - // Types participating in Type Equivalence are always transparent. - // See TokenSecurityDescriptor::VerifySemanticDataComputed in securitymeta.cpp. - // Because of that we allow critical attributes applied to full trust equivalent types. - // DeclaringType is null for global methods and fields and the global type never participates in type equivalency. - -#if FEATURE_CORECLR return false; -#else - return type != null && type.Assembly.IsFullyTrusted && RuntimeTypeHandle.IsEquivalentType(type); -#endif //!FEATURE_CORECLR } private static bool AllowCriticalCustomAttributes(MethodBase method) @@ -1429,7 +1393,6 @@ namespace System.Reflection return AllowCriticalCustomAttributes(parameter.DefiningMethod); } - [System.Security.SecurityCritical] // auto-generated internal static Object[] GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, bool inherit) { Contract.Requires(method != null); @@ -1474,7 +1437,6 @@ namespace System.Reflection return typedResult; } - [System.Security.SecuritySafeCritical] // auto-generated internal static Object[] GetCustomAttributes(RuntimeConstructorInfo ctor, RuntimeType caType) { Contract.Requires(ctor != null); @@ -1487,7 +1449,6 @@ namespace System.Reflection return attributes; } - [System.Security.SecuritySafeCritical] // auto-generated internal static Object[] GetCustomAttributes(RuntimePropertyInfo property, RuntimeType caType) { Contract.Requires(property != null); @@ -1506,7 +1467,6 @@ namespace System.Reflection return attributes; } - [System.Security.SecuritySafeCritical] // auto-generated internal static Object[] GetCustomAttributes(RuntimeEventInfo e, RuntimeType caType) { Contract.Requires(e != null); @@ -1524,7 +1484,6 @@ namespace System.Reflection return attributes; } - [System.Security.SecuritySafeCritical] // auto-generated internal static Object[] GetCustomAttributes(RuntimeFieldInfo field, RuntimeType caType) { Contract.Requires(field != null); @@ -1537,7 +1496,6 @@ namespace System.Reflection return attributes; } - [System.Security.SecuritySafeCritical] // auto-generated internal static Object[] GetCustomAttributes(RuntimeParameterInfo parameter, RuntimeType caType) { Contract.Requires(parameter != null); @@ -1550,7 +1508,6 @@ namespace System.Reflection return attributes; } - [System.Security.SecuritySafeCritical] // auto-generated internal static Object[] GetCustomAttributes(RuntimeAssembly assembly, RuntimeType caType) { Contract.Requires(assembly != null); @@ -1565,7 +1522,6 @@ namespace System.Reflection return attributes; } - [System.Security.SecuritySafeCritical] // auto-generated internal static Object[] GetCustomAttributes(RuntimeModule module, RuntimeType caType) { Contract.Requires(module != null); @@ -1579,20 +1535,17 @@ namespace System.Reflection return attributes; } - [System.Security.SecuritySafeCritical] internal static bool IsAttributeDefined(RuntimeModule decoratedModule, int decoratedMetadataToken, int attributeCtorToken) { return IsCustomAttributeDefined(decoratedModule, decoratedMetadataToken, null, attributeCtorToken, false); } - [System.Security.SecurityCritical] // auto-generated private static bool IsCustomAttributeDefined( RuntimeModule decoratedModule, int decoratedMetadataToken, RuntimeType attributeFilterType) { return IsCustomAttributeDefined(decoratedModule, decoratedMetadataToken, attributeFilterType, 0, false); } - [System.Security.SecurityCritical] // auto-generated private static bool IsCustomAttributeDefined( RuntimeModule decoratedModule, int decoratedMetadataToken, RuntimeType attributeFilterType, int attributeCtorToken, bool mustBeInheritable) { @@ -1604,7 +1557,7 @@ namespace System.Reflection if (attributeFilterType != null) { - Contract.Assert(attributeCtorToken == 0); + Debug.Assert(attributeCtorToken == 0); MetadataImport scope = decoratedModule.MetadataImport; RuntimeType attributeType; @@ -1627,8 +1580,8 @@ namespace System.Reflection } else { - Contract.Assert(attributeFilterType == null); - Contract.Assert(!MetadataToken.IsNullToken(attributeCtorToken)); + Debug.Assert(attributeFilterType == null); + Debug.Assert(!MetadataToken.IsNullToken(attributeCtorToken)); for (int i = 0; i < car.Length; i++) { @@ -1642,14 +1595,12 @@ namespace System.Reflection return false; } - [System.Security.SecurityCritical] // auto-generated private unsafe static object[] GetCustomAttributes( RuntimeModule decoratedModule, int decoratedMetadataToken, int pcaCount, RuntimeType attributeFilterType, bool isDecoratedTargetSecurityTransparent) { return GetCustomAttributes(decoratedModule, decoratedMetadataToken, pcaCount, attributeFilterType, false, null, isDecoratedTargetSecurityTransparent); } - [System.Security.SecurityCritical] private unsafe static object[] GetCustomAttributes( RuntimeModule decoratedModule, int decoratedMetadataToken, int pcaCount, RuntimeType attributeFilterType, bool mustBeInheritable, IList derivedAttributes, bool isDecoratedTargetSecurityTransparent) @@ -1841,7 +1792,6 @@ namespace System.Reflection return result; } - [System.Security.SecurityCritical] // auto-generated private unsafe static bool FilterCustomAttributeRecord( CustomAttributeRecord caRecord, MetadataImport scope, @@ -1885,19 +1835,6 @@ namespace System.Reflection return false; } -#if FEATURE_APTCA - // APTCA checks - RuntimeAssembly attributeAssembly = (RuntimeAssembly)attributeType.Assembly; - RuntimeAssembly decoratedModuleAssembly = (RuntimeAssembly)decoratedModule.Assembly; - - if (attributeAssembly != lastAptcaOkAssembly && - !RuntimeAssembly.AptcaCheck(attributeAssembly, decoratedModuleAssembly)) - return false; - - // Cache last successful APTCA check (optimization) - lastAptcaOkAssembly = decoratedModuleAssembly; -#endif // FEATURE_APTCA - // Resolve the attribute ctor ConstArray ctorSig = scope.GetMethodSignature(caRecord.tkCtor); isVarArg = (ctorSig[0] & 0x05) != 0; @@ -1944,7 +1881,7 @@ namespace System.Reflection else { // We need to relax this when we add support for other types of decorated tokens. - Contract.Assert(decoratedToken.IsModule || decoratedToken.IsAssembly, + Debug.Assert(decoratedToken.IsModule || decoratedToken.IsAssembly, "The decoratedToken must be either an assembly, a module, a type, or a member."); } @@ -1959,7 +1896,6 @@ namespace System.Reflection #endregion #region Private Static Methods - [System.Security.SecurityCritical] // auto-generated private static bool AttributeUsageCheck( RuntimeType attributeType, bool mustBeInheritable, object[] attributes, IList derivedAttributes) { @@ -1992,7 +1928,6 @@ namespace System.Reflection return true; } - [System.Security.SecurityCritical] // auto-generated internal static AttributeUsageAttribute GetAttributeUsage(RuntimeType decoratedAttribute) { RuntimeModule decoratedModule = decoratedAttribute.GetRuntimeModule(); @@ -2027,11 +1962,9 @@ namespace System.Reflection #endregion #region Private Static FCalls - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void _ParseAttributeUsageAttribute( IntPtr pCa, int cCa, out int targets, out bool inherited, out bool allowMultiple); - [System.Security.SecurityCritical] // auto-generated private static void ParseAttributeUsageAttribute( ConstArray ca, out AttributeTargets targets, out bool inherited, out bool allowMultiple) { @@ -2040,10 +1973,8 @@ namespace System.Reflection targets = (AttributeTargets)_targets; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static unsafe extern Object _CreateCaObject(RuntimeModule pModule, IRuntimeMethodInfo pCtor, byte** ppBlob, byte* pEndBlob, int* pcNamedArgs); - [System.Security.SecurityCritical] // auto-generated private static unsafe Object CreateCaObject(RuntimeModule module, IRuntimeMethodInfo ctor, ref IntPtr blob, IntPtr blobEnd, out int namedArgs) { byte* pBlob = (byte*)blob; @@ -2055,11 +1986,9 @@ namespace System.Reflection return ca; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private unsafe extern static void _GetPropertyOrFieldData( RuntimeModule pModule, byte** ppBlobStart, byte* pBlobEnd, out string name, out bool bIsProperty, out RuntimeType type, out object value); - [System.Security.SecurityCritical] // auto-generated private unsafe static void GetPropertyOrFieldData( RuntimeModule module, ref IntPtr blobStart, IntPtr blobEnd, out string name, out bool isProperty, out RuntimeType type, out object value) { @@ -2069,7 +1998,6 @@ namespace System.Reflection blobStart = (IntPtr)pBlobStart; } - [System.Security.SecuritySafeCritical] private static object[] CreateAttributeArrayHelper(Type elementType, int elementCount) { return (object[])Array.UnsafeCreateInstance(elementType, elementCount); @@ -2089,18 +2017,13 @@ namespace System.Reflection #endregion #region FCalls - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - unsafe private static extern void _GetSecurityAttributes(RuntimeModule module, int token, bool assembly, out object[] securityAttributes); - [System.Security.SecurityCritical] // auto-generated - unsafe internal static void GetSecurityAttributes(RuntimeModule module, int token, bool assembly, out object[] securityAttributes) + internal static void GetSecurityAttributes(RuntimeModule module, int token, bool assembly, out object[] securityAttributes) { - _GetSecurityAttributes(module.GetNativeHandle(), token, assembly, out securityAttributes); + securityAttributes = null; } #endregion #region Static Constructor - [System.Security.SecurityCritical] // auto-generated static PseudoCustomAttribute() { RuntimeType[] pcas = new RuntimeType[] @@ -2130,21 +2053,20 @@ namespace System.Reflection s_pca = temp_pca; } - [System.Security.SecurityCritical] // auto-generated [Conditional("_DEBUG")] private static void VerifyPseudoCustomAttribute(RuntimeType pca) { // If any of these are invariants are no longer true will have to // re-architect the PCA product logic and test cases -- you've been warned! - Contract.Assert(pca.BaseType == (RuntimeType)typeof(Attribute), "Pseudo CA Error"); + Debug.Assert(pca.BaseType == (RuntimeType)typeof(Attribute), "Pseudo CA Error"); AttributeUsageAttribute usage = CustomAttribute.GetAttributeUsage(pca); - Contract.Assert(usage.Inherited == false, "Pseudo CA Error"); + Debug.Assert(usage.Inherited == false, "Pseudo CA Error"); //AllowMultiple is true for TypeForwardedToAttribute - //Contract.Assert(usage.AllowMultiple == false, "Pseudo CA Error"); + //Debug.Assert(usage.AllowMultiple == false, "Pseudo CA Error"); } - #endregion +#endregion - #region Internal Static +#region Internal Static internal static bool IsSecurityAttribute(RuntimeType type) { #pragma warning disable 618 @@ -2152,7 +2074,6 @@ namespace System.Reflection #pragma warning restore 618 } - [System.Security.SecurityCritical] // auto-generated internal static Attribute[] GetCustomAttributes(RuntimeType type, RuntimeType caType, bool includeSecCa, out int count) { Contract.Requires(type != null); @@ -2196,7 +2117,6 @@ namespace System.Reflection count = pcas.Count; return pcas.ToArray(); } - [System.Security.SecurityCritical] // auto-generated internal static bool IsDefined(RuntimeType type, RuntimeType caType) { bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute); @@ -2221,7 +2141,6 @@ namespace System.Reflection return false; } - [System.Security.SecurityCritical] // auto-generated internal static Attribute[] GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, bool includeSecCa, out int count) { Contract.Requires(method != null); @@ -2260,7 +2179,6 @@ namespace System.Reflection count = pcas.Count; return pcas.ToArray(); } - [System.Security.SecurityCritical] // auto-generated internal static bool IsDefined(RuntimeMethodInfo method, RuntimeType caType) { bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute); @@ -2286,7 +2204,6 @@ namespace System.Reflection return false; } - [System.Security.SecurityCritical] // auto-generated internal static Attribute[] GetCustomAttributes(RuntimeParameterInfo parameter, RuntimeType caType, out int count) { Contract.Requires(parameter != null); @@ -2323,7 +2240,6 @@ namespace System.Reflection } return pcas; } - [System.Security.SecurityCritical] // auto-generated internal static bool IsDefined(RuntimeParameterInfo parameter, RuntimeType caType) { bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute); @@ -2351,7 +2267,6 @@ namespace System.Reflection return false; } - [System.Security.SecurityCritical] // auto-generated internal static Attribute[] GetCustomAttributes(RuntimeAssembly assembly, RuntimeType caType, bool includeSecCa, out int count) { count = 0; @@ -2386,7 +2301,6 @@ namespace System.Reflection count = pcas.Count; return pcas.ToArray(); } - [System.Security.SecurityCritical] // auto-generated internal static bool IsDefined(RuntimeAssembly assembly, RuntimeType caType) { int count; @@ -2403,7 +2317,6 @@ namespace System.Reflection return false; } - [System.Security.SecurityCritical] // auto-generated internal static Attribute[] GetCustomAttributes(RuntimeFieldInfo field, RuntimeType caType, out int count) { Contract.Requires(field != null); @@ -2435,7 +2348,6 @@ namespace System.Reflection } return pcas; } - [System.Security.SecurityCritical] // auto-generated internal static bool IsDefined(RuntimeFieldInfo field, RuntimeType caType) { bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute); @@ -2458,7 +2370,6 @@ namespace System.Reflection return false; } - [System.Security.SecurityCritical] // auto-generated internal static Attribute[] GetCustomAttributes(RuntimeConstructorInfo ctor, RuntimeType caType, bool includeSecCa, out int count) { count = 0; @@ -2484,7 +2395,6 @@ namespace System.Reflection count = pcas.Count; return pcas.ToArray(); } - [System.Security.SecurityCritical] // auto-generated internal static bool IsDefined(RuntimeConstructorInfo ctor, RuntimeType caType) { bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute); @@ -2522,6 +2432,6 @@ namespace System.Reflection { return false; } - #endregion +#endregion } } diff --git a/src/mscorlib/src/System/Reflection/Emit/AQNBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/AQNBuilder.cs index 6484677..fb93249 100644 --- a/src/mscorlib/src/System/Reflection/Emit/AQNBuilder.cs +++ b/src/mscorlib/src/System/Reflection/Emit/AQNBuilder.cs @@ -22,59 +22,45 @@ namespace System.Reflection.Emit } #region QCalls - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern IntPtr CreateTypeNameBuilder(); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void ReleaseTypeNameBuilder(IntPtr pAQN); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void OpenGenericArguments(IntPtr tnb); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void CloseGenericArguments(IntPtr tnb); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void OpenGenericArgument(IntPtr tnb); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void CloseGenericArgument(IntPtr tnb); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void AddName(IntPtr tnb, string name); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void AddPointer(IntPtr tnb); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void AddByRef(IntPtr tnb); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void AddSzArray(IntPtr tnb); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void AddArray(IntPtr tnb, int rank); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void AddAssemblySpec(IntPtr tnb, string assemblySpec); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void ToString(IntPtr tnb, StringHandleOnStack retString); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void Clear(IntPtr tnb); @@ -83,7 +69,6 @@ namespace System.Reflection.Emit #region Static Members // TypeNameBuilder is NOT thread safe NOR reliable - [System.Security.SecuritySafeCritical] // auto-generated internal static string ToString(Type type, Format format) { if (format == Format.FullName || format == Format.AssemblyQualifiedName) @@ -107,12 +92,10 @@ namespace System.Reflection.Emit #region Constructor private TypeNameBuilder(IntPtr typeNameBuilder) { m_typeNameBuilder = typeNameBuilder; } - [System.Security.SecurityCritical] // auto-generated internal void Dispose() { ReleaseTypeNameBuilder(m_typeNameBuilder); } #endregion #region private Members - [System.Security.SecurityCritical] // auto-generated private void AddElementType(Type elementType) { if (elementType.HasElementType) @@ -131,7 +114,6 @@ namespace System.Reflection.Emit AddArray(elementType.GetArrayRank()); } - [System.Security.SecurityCritical] // auto-generated private void ConstructAssemblyQualifiedNameWorker(Type type, Format format) { Type rootType = type; @@ -179,29 +161,17 @@ namespace System.Reflection.Emit AddAssemblySpec(type.Module.Assembly.FullName); } - [System.Security.SecurityCritical] // auto-generated private void OpenGenericArguments() { OpenGenericArguments(m_typeNameBuilder); } - [System.Security.SecurityCritical] // auto-generated private void CloseGenericArguments() { CloseGenericArguments(m_typeNameBuilder); } - [System.Security.SecurityCritical] // auto-generated private void OpenGenericArgument() { OpenGenericArgument(m_typeNameBuilder); } - [System.Security.SecurityCritical] // auto-generated private void CloseGenericArgument() { CloseGenericArgument(m_typeNameBuilder); } - [System.Security.SecurityCritical] // auto-generated private void AddName(string name) { AddName(m_typeNameBuilder, name); } - [System.Security.SecurityCritical] // auto-generated private void AddPointer() { AddPointer(m_typeNameBuilder); } - [System.Security.SecurityCritical] // auto-generated private void AddByRef() { AddByRef(m_typeNameBuilder); } - [System.Security.SecurityCritical] // auto-generated private void AddSzArray() { AddSzArray(m_typeNameBuilder); } - [System.Security.SecurityCritical] // auto-generated private void AddArray(int rank) { AddArray(m_typeNameBuilder, rank); } - [System.Security.SecurityCritical] // auto-generated private void AddAssemblySpec(string assemblySpec) { AddAssemblySpec(m_typeNameBuilder, assemblySpec); } - [System.Security.SecuritySafeCritical] // auto-generated public override string ToString() { string ret = null; ToString(m_typeNameBuilder, JitHelpers.GetStringHandleOnStack(ref ret)); return ret; } - [System.Security.SecurityCritical] // auto-generated private void Clear() { Clear(m_typeNameBuilder); } #endregion } diff --git a/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilder.cs index 5e7f83f..9331ae1 100644 --- a/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilder.cs +++ b/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilder.cs @@ -98,17 +98,11 @@ namespace System.Reflection.Emit throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicAssembly")); } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif public override FileStream GetFile(String name) { throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicAssembly")); } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif public override FileStream[] GetFiles(bool getResourceModules) { throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicAssembly")); @@ -131,9 +125,6 @@ namespace System.Reflection.Emit public override String Location { -#if FEATURE_CORECLR - [SecurityCritical] -#endif // FEATURE_CORECLR get { throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicAssembly")); @@ -142,9 +133,6 @@ namespace System.Reflection.Emit public override String CodeBase { -#if FEATURE_CORECLR - [SecurityCritical] -#endif // FEATURE_CORECLR get { throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicAssembly")); @@ -168,43 +156,20 @@ namespace System.Reflection.Emit // AssemblyBuilder class. // deliberately not [serializable] - [HostProtection(MayLeakOnAbort = true)] [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_AssemblyBuilder))] [ComVisible(true)] public sealed class AssemblyBuilder : Assembly, _AssemblyBuilder { #region FCALL - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern RuntimeModule GetInMemoryAssemblyModule(RuntimeAssembly assembly); - [System.Security.SecurityCritical] // auto-generated private Module nGetInMemoryAssemblyModule() { return AssemblyBuilder.GetInMemoryAssemblyModule(GetNativeHandle()); } -#if !FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern RuntimeModule GetOnDiskAssemblyModule(RuntimeAssembly assembly); - - [System.Security.SecurityCritical] // auto-generated - private ModuleBuilder GetOnDiskAssemblyModuleBuilder() - { - if (m_onDiskAssemblyModuleBuilder == null) - { - Module module = AssemblyBuilder.GetOnDiskAssemblyModule(InternalAssembly.GetNativeHandle()); - ModuleBuilder modBuilder = new ModuleBuilder(this, (InternalModuleBuilder)module); - modBuilder.Init("RefEmit_OnDiskManifestModule", null, 0); - m_onDiskAssemblyModuleBuilder = modBuilder; - } - - return m_onDiskAssemblyModuleBuilder; - } -#endif // FEATURE_CORECLR - #endregion #region Internal Data Members @@ -215,9 +180,6 @@ namespace System.Reflection.Emit // Set to true if the manifest module was returned by code:DefineDynamicModule to the user private bool m_fManifestModuleUsedAsDefinedModule; internal const string MANIFEST_MODULE_NAME = "RefEmit_InMemoryManifestModule"; -#if !FEATURE_CORECLR - private ModuleBuilder m_onDiskAssemblyModuleBuilder; -#endif // !FEATURE_CORECLR #if FEATURE_APPX private bool m_profileAPICheck; @@ -226,27 +188,15 @@ namespace System.Reflection.Emit internal ModuleBuilder GetModuleBuilder(InternalModuleBuilder module) { Contract.Requires(module != null); - Contract.Assert(this.InternalAssembly == module.Assembly); + Debug.Assert(this.InternalAssembly == module.Assembly); lock(SyncRoot) { -#if !FEATURE_CORECLR - foreach (ModuleBuilder modBuilder in m_assemblyData.m_moduleBuilderList) - { - if (modBuilder.InternalModule == module) - return modBuilder; - } - - // m_onDiskAssemblyModuleBuilder is null before Save - if (m_onDiskAssemblyModuleBuilder != null && m_onDiskAssemblyModuleBuilder.InternalModule == module) - return m_onDiskAssemblyModuleBuilder; -#endif // !FEATURE_CORECLR - // in CoreCLR there is only one module in each dynamic assembly, the manifest module if (m_manifestModuleBuilder.InternalModule == module) return m_manifestModuleBuilder; - throw new ArgumentException("module"); + throw new ArgumentException(null, nameof(module)); } } @@ -271,7 +221,6 @@ namespace System.Reflection.Emit return InternalAssembly.GetNativeHandle(); } - [SecurityCritical] internal Version GetVersion() { return InternalAssembly.GetVersion(); @@ -289,7 +238,6 @@ namespace System.Reflection.Emit #endregion #region Constructor - [System.Security.SecurityCritical] // auto-generated internal AssemblyBuilder(AppDomain domain, AssemblyName name, AssemblyBuilderAccess access, @@ -303,13 +251,9 @@ namespace System.Reflection.Emit SecurityContextSource securityContextSource) { if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); if (access != AssemblyBuilderAccess.Run -#if !FEATURE_CORECLR - && access != AssemblyBuilderAccess.Save - && access != AssemblyBuilderAccess.RunAndSave -#endif // !FEATURE_CORECLR #if FEATURE_REFLECTION_ONLY_LOAD && access != AssemblyBuilderAccess.ReflectionOnly #endif // FEATURE_REFLECTION_ONLY_LOAD @@ -318,25 +262,17 @@ namespace System.Reflection.Emit #endif // FEATURE_COLLECTIBLE_TYPES ) { - throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)access), "access"); + throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)access), nameof(access)); } if (securityContextSource < SecurityContextSource.CurrentAppDomain || securityContextSource > SecurityContextSource.CurrentAssembly) { - throw new ArgumentOutOfRangeException("securityContextSource"); + throw new ArgumentOutOfRangeException(nameof(securityContextSource)); } // Clone the name in case the caller modifies it underneath us. name = (AssemblyName)name.Clone(); - -#if !FEATURE_CORECLR - // Set the public key from the key pair if one has been provided. - // (Overwite any public key in the Assembly name, since it's no - // longer valid to have a disparity). - if (name.KeyPair != null) - name.SetPublicKey(name.KeyPair.PublicKey); -#endif // If the caller is trusted they can supply identity // evidence for the new assembly. Otherwise we copy the @@ -350,13 +286,6 @@ namespace System.Reflection.Emit new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand(); #pragma warning restore 618 -#if FEATURE_COLLECTIBLE_TYPES && !FEATURE_CORECLR - // Collectible assemblies require FullTrust. This demand may be removed if we deem the - // feature robust enough to be used directly by untrusted API consumers. - if (access == AssemblyBuilderAccess.RunAndCollect) - new PermissionSet(PermissionState.Unrestricted).Demand(); -#endif // FEATURE_COLLECTIBLE_TYPES && !FEATURE_CORECLR - // Scan the assembly level attributes for any attributes which modify how we create the // assembly. Currently, we look for any attribute which modifies the security transparency // of the assembly. @@ -379,41 +308,10 @@ namespace System.Reflection.Emit } else if (attribute.m_con.DeclaringType == typeof(SecurityCriticalAttribute)) { -#if !FEATURE_CORECLR - SecurityCriticalScope scope = SecurityCriticalScope.Everything; - if (attribute.m_constructorArgs != null && - attribute.m_constructorArgs.Length == 1 && - attribute.m_constructorArgs[0] is SecurityCriticalScope) - { - scope = (SecurityCriticalScope)attribute.m_constructorArgs[0]; - } - - assemblyFlags |= DynamicAssemblyFlags.Critical; - if (scope == SecurityCriticalScope.Everything) -#endif // !FEATURE_CORECLR { assemblyFlags |= DynamicAssemblyFlags.AllCritical; } } -#if !FEATURE_CORECLR - else if (attribute.m_con.DeclaringType == typeof(SecurityRulesAttribute)) - { - securityRulesBlob = new byte[attribute.m_blob.Length]; - Buffer.BlockCopy(attribute.m_blob, 0, securityRulesBlob, 0, securityRulesBlob.Length); - } - else if (attribute.m_con.DeclaringType == typeof(SecurityTreatAsSafeAttribute)) - { - assemblyFlags |= DynamicAssemblyFlags.TreatAsSafe; - } -#endif // !FEATURE_CORECLR -#if FEATURE_APTCA - else if (attribute.m_con.DeclaringType == typeof(AllowPartiallyTrustedCallersAttribute)) - { - assemblyFlags |= DynamicAssemblyFlags.Aptca; - aptcaBlob = new byte[attribute.m_blob.Length]; - Buffer.BlockCopy(attribute.m_blob, 0, aptcaBlob, 0, aptcaBlob.Length); - } -#endif // FEATURE_APTCA } #pragma warning restore 618 } @@ -458,7 +356,6 @@ namespace System.Reflection.Emit } } - [System.Security.SecurityCritical] // auto-generated private void InitManifestModule() { InternalModuleBuilder modBuilder = (InternalModuleBuilder)nGetInMemoryAssemblyModule(); @@ -487,7 +384,6 @@ namespace System.Reflection.Emit * to have a strong name and a hash will be computed when the assembly * is saved. **********************************************/ - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static AssemblyBuilder DefineDynamicAssembly( AssemblyName name, @@ -500,7 +396,6 @@ namespace System.Reflection.Emit null, null, null, null, ref stackMark, null, SecurityContextSource.CurrentAssembly); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static AssemblyBuilder DefineDynamicAssembly( AssemblyName name, @@ -518,7 +413,6 @@ namespace System.Reflection.Emit } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern Assembly nCreateDynamicAssembly(AppDomain domain, AssemblyName name, @@ -535,7 +429,6 @@ namespace System.Reflection.Emit private class AssemblyBuilderLock { } - [System.Security.SecurityCritical] // auto-generated internal static AssemblyBuilder InternalDefineDynamicAssembly( AssemblyName name, AssemblyBuilderAccess access, @@ -548,13 +441,6 @@ namespace System.Reflection.Emit IEnumerable unsafeAssemblyAttributes, SecurityContextSource securityContextSource) { -#if FEATURE_CAS_POLICY - if (evidence != null && !AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit")); - } -#endif // FEATURE_CAS_POLICY - lock (typeof(AssemblyBuilderLock)) { // we can only create dynamic assemblies in the current domain @@ -581,7 +467,6 @@ namespace System.Reflection.Emit * a transient module. * **********************************************/ - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public ModuleBuilder DefineDynamicModule( String name) @@ -592,7 +477,6 @@ namespace System.Reflection.Emit return DefineDynamicModuleInternal(name, false, ref stackMark); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public ModuleBuilder DefineDynamicModule( String name, @@ -604,7 +488,6 @@ namespace System.Reflection.Emit return DefineDynamicModuleInternal( name, emitSymbolInfo, ref stackMark ); } - [System.Security.SecurityCritical] // auto-generated private ModuleBuilder DefineDynamicModuleInternal( String name, bool emitSymbolInfo, // specify if emit symbol info or not @@ -616,115 +499,38 @@ namespace System.Reflection.Emit } } - [System.Security.SecurityCritical] // auto-generated private ModuleBuilder DefineDynamicModuleInternalNoLock( String name, bool emitSymbolInfo, // specify if emit symbol info or not ref StackCrawlMark stackMark) { if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); if (name.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(name)); if (name[0] == '\0') - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidName"), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidName"), nameof(name)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); BCLDebug.Log("DYNIL", "## DYNIL LOGGING: AssemblyBuilder.DefineDynamicModule( " + name + " )"); - Contract.Assert(m_assemblyData != null, "m_assemblyData is null in DefineDynamicModuleInternal"); + Debug.Assert(m_assemblyData != null, "m_assemblyData is null in DefineDynamicModuleInternal"); ModuleBuilder dynModule; ISymbolWriter writer = null; IntPtr pInternalSymWriter = new IntPtr(); - // create the dynamic module - -#if FEATURE_MULTIMODULE_ASSEMBLIES - -#if FEATURE_CORECLR -#error FEATURE_MULTIMODULE_ASSEMBLIES should always go with !FEATURE_CORECLR -#endif //FEATURE_CORECLR - - m_assemblyData.CheckNameConflict(name); - - if (m_fManifestModuleUsedAsDefinedModule == true) - { // We need to define a new module - int tkFile; - InternalModuleBuilder internalDynModule = (InternalModuleBuilder)DefineDynamicModule( - InternalAssembly, - emitSymbolInfo, - name, - name, - ref stackMark, - ref pInternalSymWriter, - true /*fIsTransient*/, - out tkFile); - dynModule = new ModuleBuilder(this, internalDynModule); - - // initialize the dynamic module's managed side information - dynModule.Init(name, null, tkFile); - } - else - { // We will reuse the manifest module - m_manifestModuleBuilder.ModifyModuleName(name); - dynModule = m_manifestModuleBuilder; - - if (emitSymbolInfo) - { - pInternalSymWriter = ModuleBuilder.nCreateISymWriterForDynamicModule(dynModule.InternalModule, name); - } - } - -#else // FEATURE_MULTIMODULE_ASSEMBLIES - // Without FEATURE_MULTIMODULE_ASSEMBLIES only one ModuleBuilder per AssemblyBuilder can be created + // create the dynamic module- only one ModuleBuilder per AssemblyBuilder can be created if (m_fManifestModuleUsedAsDefinedModule == true) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NoMultiModuleAssembly")); // Init(...) has already been called on m_manifestModuleBuilder in InitManifestModule() dynModule = m_manifestModuleBuilder; -#endif // FEATURE_MULTIMODULE_ASSEMBLIES // Create the symbol writer if (emitSymbolInfo) { -#if FEATURE_MULTIMODULE_ASSEMBLIES && !FEATURE_CORECLR - // this is the code path for the desktop runtime - - // create the default SymWriter - Assembly assem = LoadISymWrapper(); - Type symWriter = assem.GetType("System.Diagnostics.SymbolStore.SymWriter", true, false); - if (symWriter != null && !symWriter.IsVisible) - symWriter = null; - - if (symWriter == null) - { - // cannot find SymWriter - throw TypeLoadException since we couldnt find the type. - throw new TypeLoadException(Environment.GetResourceString(ResId.MissingType, "SymWriter")); - } - - new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); - - try - { - (new PermissionSet(PermissionState.Unrestricted)).Assert(); - writer = (ISymbolWriter)Activator.CreateInstance(symWriter); - - // Set the underlying writer for the managed writer - // that we're using. Note that this function requires - // unmanaged code access. - writer.SetUnderlyingWriter(pInternalSymWriter); - } - finally - { - CodeAccessPermission.RevertAssert(); - } -#endif // FEATURE_MULTIMODULE_ASSEMBLIES && !FEATURE_CORECLR - -#if !FEATURE_MULTIMODULE_ASSEMBLIES && FEATURE_CORECLR - // this is the code path for CoreCLR - writer = SymWrapperCore.SymWriter.CreateSymWriter(); // Set the underlying writer for the managed writer // that we're using. Note that this function requires @@ -741,7 +547,6 @@ namespace System.Reflection.Emit // In Telesto, we took the SetUnderlyingWriter method private as it's a very rickety method. // This might someday be a good move for the desktop CLR too. ((SymWrapperCore.SymWriter)writer).InternalSetUnderlyingWriter(pInternalSymWriter); -#endif // !FEATURE_MULTIMODULE_ASSEMBLIES && FEATURE_CORECLR } // Creating the symbol writer dynModule.SetSymWriter(writer); @@ -754,174 +559,6 @@ namespace System.Reflection.Emit return dynModule; } // DefineDynamicModuleInternalNoLock - -#if !FEATURE_CORECLR - // All dynamic modules in SilverLight are transient so we removed this overload of DefineDynamicModule - // Note that it is assumed that !FEATURE_CORECLR always goes with FEATURE_MULTIMODULE_ASSEMBLIES - // If we ever will build a non coreclr version of the runtime without FEATURE_MULTIMODULE_ASSEMBLIES - // we will need to make the same changes here as the ones we made in the transient overload - - /********************************************** - * - * Defines a named dynamic module. It is an error to define multiple - * modules within an Assembly with the same name. No symbol information - * will be emitted. - * - **********************************************/ - [System.Security.SecuritySafeCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - public ModuleBuilder DefineDynamicModule( - String name, - String fileName) - { - Contract.Ensures(Contract.Result() != null); - - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - - // delegate to the next DefineDynamicModule - return DefineDynamicModuleInternal(name, fileName, false, ref stackMark); - } - - /********************************************** - * - * Emit symbol information if emitSymbolInfo is true using the - * default symbol writer interface. - * An exception will be thrown if the assembly is transient. - * - **********************************************/ - [System.Security.SecuritySafeCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - public ModuleBuilder DefineDynamicModule( - String name, // module name - String fileName, // module file name - bool emitSymbolInfo) // specify if emit symbol info or not - { - Contract.Ensures(Contract.Result() != null); - - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return DefineDynamicModuleInternal(name, fileName, emitSymbolInfo, ref stackMark); - } - - [System.Security.SecurityCritical] // auto-generated - private ModuleBuilder DefineDynamicModuleInternal( - String name, // module name - String fileName, // module file name - bool emitSymbolInfo, // specify if emit symbol info or not - ref StackCrawlMark stackMark) // stack crawl mark used to find caller - { - lock(SyncRoot) - { - return DefineDynamicModuleInternalNoLock(name, fileName, emitSymbolInfo, ref stackMark); - } - } - - // "name" will be used for: - // 1. The Name field in the Module table. - // 2. ModuleBuilder.GetModule(string). - // "fileName" will be used for: - // 1. The name field in the ModuleRef table when this module is being referenced by - // another module in the same assembly. - // 2. .file record in the in memory assembly manifest when the module is created in memory - // 3. .file record in the on disk assembly manifest when the assembly is saved to disk - // 4. The file name of the saved module. - [System.Security.SecurityCritical] // auto-generated - private ModuleBuilder DefineDynamicModuleInternalNoLock( - String name, // module name - String fileName, // module file name - bool emitSymbolInfo, // specify if emit symbol info or not - ref StackCrawlMark stackMark) // stack crawl mark used to find caller - { - if (name == null) - throw new ArgumentNullException("name"); - if (name.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); - if (name[0] == '\0') - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidName"), "name"); - - if (fileName == null) - throw new ArgumentNullException("fileName"); - if (fileName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "fileName"); - if (!String.Equals(fileName, Path.GetFileName(fileName))) - throw new ArgumentException(Environment.GetResourceString("Argument_NotSimpleFileName"), "fileName"); - Contract.Ensures(Contract.Result() != null); - Contract.EndContractBlock(); - - BCLDebug.Log("DYNIL", "## DYNIL LOGGING: AssemblyBuilder.DefineDynamicModule( " + name + ", " + fileName + ", " + emitSymbolInfo + " )"); - if (m_assemblyData.m_access == AssemblyBuilderAccess.Run) - { - // Error! You cannot define a persistable module within a transient data. - throw new NotSupportedException(Environment.GetResourceString("Argument_BadPersistableModuleInTransientAssembly")); - } - - if (m_assemblyData.m_isSaved == true) - { - // assembly has been saved before! - throw new InvalidOperationException(Environment.GetResourceString( - "InvalidOperation_CannotAlterAssembly")); - } - - ModuleBuilder dynModule; - ISymbolWriter writer = null; - IntPtr pInternalSymWriter = new IntPtr(); - - // create the dynamic module - - m_assemblyData.CheckNameConflict(name); - m_assemblyData.CheckFileNameConflict(fileName); - - int tkFile; - InternalModuleBuilder internalDynModule = (InternalModuleBuilder)DefineDynamicModule( - InternalAssembly, - emitSymbolInfo, - name, - fileName, - ref stackMark, - ref pInternalSymWriter, - false /*fIsTransient*/, - out tkFile); - dynModule = new ModuleBuilder(this, internalDynModule); - - // initialize the dynamic module's managed side information - dynModule.Init(name, fileName, tkFile); - - // Create the symbol writer - if (emitSymbolInfo) - { - // create the default SymWriter - Assembly assem = LoadISymWrapper(); - Type symWriter = assem.GetType("System.Diagnostics.SymbolStore.SymWriter", true, false); - if (symWriter != null && !symWriter.IsVisible) - symWriter = null; - - if (symWriter == null) - { - // cannot find SymWriter - throw TypeLoadException since we couldnt find the type. - throw new TypeLoadException(Environment.GetResourceString("MissingType", "SymWriter")); - } - try - { - (new PermissionSet(PermissionState.Unrestricted)).Assert(); - writer = (ISymbolWriter)Activator.CreateInstance(symWriter); - - // Set the underlying writer for the managed writer - // that we're using. Note that this function requires - // unmanaged code access. - writer.SetUnderlyingWriter(pInternalSymWriter); - } - finally - { - CodeAccessPermission.RevertAssert(); - } - } - - dynModule.SetSymWriter(writer); - - m_assemblyData.AddModule(dynModule); - - return dynModule; - } // DefineDynamicModuleInternalNoLock -#endif // !FEATURE_CORECLR #endregion private Assembly LoadISymWrapper() @@ -970,170 +607,6 @@ namespace System.Reflection.Emit } } -#if !FEATURE_CORECLR - /********************************************** - * - * Define stand alone managed resource for Assembly - * - **********************************************/ - public IResourceWriter DefineResource( - String name, - String description, - String fileName) - { - return DefineResource(name, description, fileName, ResourceAttributes.Public); - } - - /********************************************** - * - * Define stand alone managed resource for Assembly - * - **********************************************/ - public IResourceWriter DefineResource( - String name, - String description, - String fileName, - ResourceAttributes attribute) - { - lock(SyncRoot) - { - return DefineResourceNoLock(name, description, fileName, attribute); - } - } - - private IResourceWriter DefineResourceNoLock( - String name, - String description, - String fileName, - ResourceAttributes attribute) - { - if (name == null) - throw new ArgumentNullException("name"); - if (name.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), name); - if (fileName == null) - throw new ArgumentNullException("fileName"); - if (fileName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "fileName"); - if (!String.Equals(fileName, Path.GetFileName(fileName))) - throw new ArgumentException(Environment.GetResourceString("Argument_NotSimpleFileName"), "fileName"); - Contract.EndContractBlock(); - - BCLDebug.Log("DYNIL", "## DYNIL LOGGING: AssemblyBuilder.DefineResource( " + name + ", " + fileName + ")"); - - m_assemblyData.CheckResNameConflict(name); - m_assemblyData.CheckFileNameConflict(fileName); - - ResourceWriter resWriter; - String fullFileName; - - if (m_assemblyData.m_strDir == null) - { - // If assembly directory is null, use current directory - fullFileName = Path.Combine(Directory.GetCurrentDirectory(), fileName); - resWriter = new ResourceWriter(fullFileName); - } - else - { - // Form the full path given the directory provided by user - fullFileName = Path.Combine(m_assemblyData.m_strDir, fileName); - resWriter = new ResourceWriter(fullFileName); - } - // get the full path - fullFileName = Path.GetFullPath(fullFileName); - - // retrieve just the file name - fileName = Path.GetFileName(fullFileName); - - m_assemblyData.AddResWriter( new ResWriterData( resWriter, null, name, fileName, fullFileName, attribute) ); - return resWriter; - } - -#endif // !FEATURE_CORECLR - - /********************************************** - * - * Add an existing resource file to the Assembly - * - **********************************************/ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif - public void AddResourceFile( - String name, - String fileName) - { - AddResourceFile(name, fileName, ResourceAttributes.Public); - } - - /********************************************** - * - * Add an existing resource file to the Assembly - * - **********************************************/ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif - public void AddResourceFile( - String name, - String fileName, - ResourceAttributes attribute) - { - lock(SyncRoot) - { - AddResourceFileNoLock(name, fileName, attribute); - } - } - - [System.Security.SecuritySafeCritical] - private void AddResourceFileNoLock( - String name, - String fileName, - ResourceAttributes attribute) - { - if (name == null) - throw new ArgumentNullException("name"); - if (name.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), name); - if (fileName == null) - throw new ArgumentNullException("fileName"); - if (fileName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), fileName); - if (!String.Equals(fileName, Path.GetFileName(fileName))) - throw new ArgumentException(Environment.GetResourceString("Argument_NotSimpleFileName"), "fileName"); - Contract.EndContractBlock(); - - BCLDebug.Log("DYNIL", "## DYNIL LOGGING: AssemblyBuilder.AddResourceFile( " + name + ", " + fileName + ")"); - - m_assemblyData.CheckResNameConflict(name); - m_assemblyData.CheckFileNameConflict(fileName); - - String fullFileName; - - if (m_assemblyData.m_strDir == null) - { - // If assembly directory is null, use current directory - fullFileName = Path.Combine(Directory.GetCurrentDirectory(), fileName); - } - else - { - // Form the full path given the directory provided by user - fullFileName = Path.Combine(m_assemblyData.m_strDir, fileName); - } - - // get the full path - fullFileName = Path.UnsafeGetFullPath(fullFileName); - - // retrieve just the file name - fileName = Path.GetFileName(fullFileName); - - if (File.UnsafeExists(fullFileName) == false) - throw new FileNotFoundException(Environment.GetResourceString( - "IO.FileNotFound_FileName", - fileName), fileName); - m_assemblyData.AddResWriter( new ResWriterData( null, null, name, fileName, fullFileName, attribute) ); - } - #region object overrides public override bool Equals(object obj) { @@ -1172,17 +645,11 @@ namespace System.Reflection.Emit return InternalAssembly.GetManifestResourceNames(); } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif public override FileStream GetFile(String name) { return InternalAssembly.GetFile(name); } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif public override FileStream[] GetFiles(bool getResourceModules) { return InternalAssembly.GetFiles(getResourceModules); @@ -1205,9 +672,6 @@ namespace System.Reflection.Emit public override String Location { - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif get { return InternalAssembly.Location; @@ -1224,9 +688,6 @@ namespace System.Reflection.Emit public override String CodeBase { - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif get { return InternalAssembly.CodeBase; @@ -1249,9 +710,6 @@ namespace System.Reflection.Emit return InternalAssembly.GetExportedTypes(); } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif public override AssemblyName GetName(bool copiedName) { return InternalAssembly.GetName(copiedName); @@ -1270,33 +728,6 @@ namespace System.Reflection.Emit return InternalAssembly.GetType(name, throwOnError, ignoreCase); } -#if FEATURE_CAS_POLICY - public override Evidence Evidence - { - get - { - return InternalAssembly.Evidence; - } - } - - public override PermissionSet PermissionSet - { - [SecurityCritical] - get - { - return InternalAssembly.PermissionSet; - } - } - - public override SecurityRuleSet SecurityRuleSet - { - get - { - return InternalAssembly.SecurityRuleSet; - } - } -#endif // FEATURE_CAS_POLICY - public override Module ManifestModule { get @@ -1371,143 +802,8 @@ namespace System.Reflection.Emit } } #endregion - - - /********************************************** - * - * Add an unmanaged Version resource to the - * assembly - * - **********************************************/ - public void DefineVersionInfoResource( - String product, - String productVersion, - String company, - String copyright, - String trademark) - { - lock(SyncRoot) - { - DefineVersionInfoResourceNoLock( - product, - productVersion, - company, - copyright, - trademark); - } - } - - private void DefineVersionInfoResourceNoLock( - String product, - String productVersion, - String company, - String copyright, - String trademark) - { - if (m_assemblyData.m_strResourceFileName != null || - m_assemblyData.m_resourceBytes != null || - m_assemblyData.m_nativeVersion != null) - throw new ArgumentException(Environment.GetResourceString("Argument_NativeResourceAlreadyDefined")); - - m_assemblyData.m_nativeVersion = new NativeVersionInfo(); - - m_assemblyData.m_nativeVersion.m_strCopyright = copyright; - m_assemblyData.m_nativeVersion.m_strTrademark = trademark; - m_assemblyData.m_nativeVersion.m_strCompany = company; - m_assemblyData.m_nativeVersion.m_strProduct = product; - m_assemblyData.m_nativeVersion.m_strProductVersion = productVersion; - m_assemblyData.m_hasUnmanagedVersionInfo = true; - m_assemblyData.m_OverrideUnmanagedVersionInfo = true; - - } - - public void DefineVersionInfoResource() - { - lock(SyncRoot) - { - DefineVersionInfoResourceNoLock(); - } - } - - private void DefineVersionInfoResourceNoLock() - { - if (m_assemblyData.m_strResourceFileName != null || - m_assemblyData.m_resourceBytes != null || - m_assemblyData.m_nativeVersion != null) - throw new ArgumentException(Environment.GetResourceString("Argument_NativeResourceAlreadyDefined")); - - m_assemblyData.m_hasUnmanagedVersionInfo = true; - m_assemblyData.m_nativeVersion = new NativeVersionInfo(); - } - - public void DefineUnmanagedResource(Byte[] resource) - { - if (resource == null) - throw new ArgumentNullException("resource"); - Contract.EndContractBlock(); - - lock(SyncRoot) - { - DefineUnmanagedResourceNoLock(resource); - } - } - private void DefineUnmanagedResourceNoLock(Byte[] resource) - { - if (m_assemblyData.m_strResourceFileName != null || - m_assemblyData.m_resourceBytes != null || - m_assemblyData.m_nativeVersion != null) - throw new ArgumentException(Environment.GetResourceString("Argument_NativeResourceAlreadyDefined")); - - m_assemblyData.m_resourceBytes = new byte[resource.Length]; - Buffer.BlockCopy(resource, 0, m_assemblyData.m_resourceBytes, 0, resource.Length); - } - [System.Security.SecuritySafeCritical] // auto-generated - public void DefineUnmanagedResource(String resourceFileName) - { - if (resourceFileName == null) - throw new ArgumentNullException("resourceFileName"); - Contract.EndContractBlock(); - - lock(SyncRoot) - { - DefineUnmanagedResourceNoLock(resourceFileName); - } - } - - [System.Security.SecurityCritical] // auto-generated - private void DefineUnmanagedResourceNoLock(String resourceFileName) - { - if (m_assemblyData.m_strResourceFileName != null || - m_assemblyData.m_resourceBytes != null || - m_assemblyData.m_nativeVersion != null) - throw new ArgumentException(Environment.GetResourceString("Argument_NativeResourceAlreadyDefined")); - - // Check caller has the right to read the file. - string strFullFileName; - if (m_assemblyData.m_strDir == null) - { - // If assembly directory is null, use current directory - strFullFileName = Path.Combine(Directory.GetCurrentDirectory(), resourceFileName); - } - else - { - // Form the full path given the directory provided by user - strFullFileName = Path.Combine(m_assemblyData.m_strDir, resourceFileName); - } - strFullFileName = Path.GetFullPath(resourceFileName); - new FileIOPermission(FileIOPermissionAccess.Read, strFullFileName).Demand(); - - if (File.Exists(strFullFileName) == false) - throw new FileNotFoundException(Environment.GetResourceString( - "IO.FileNotFound_FileName", - resourceFileName), resourceFileName); - m_assemblyData.m_strResourceFileName = strFullFileName; - } - - - /********************************************** * * return a dynamic module with the specified name. @@ -1526,9 +822,9 @@ namespace System.Reflection.Emit String name) // the name of module for the look up { if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); if (name.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(name)); Contract.EndContractBlock(); BCLDebug.Log("DYNIL", "## DYNIL LOGGING: AssemblyBuilder.GetDynamicModule( " + name + " )"); @@ -1550,17 +846,11 @@ namespace System.Reflection.Emit * an exe. * **********************************************/ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif public void SetEntryPoint( MethodInfo entryMethod) { SetEntryPoint(entryMethod, PEFileKinds.ConsoleApplication); } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif public void SetEntryPoint( MethodInfo entryMethod, // entry method for the assembly. We use this to determine the entry module PEFileKinds fileKind) // file kind for the assembly. @@ -1577,7 +867,7 @@ namespace System.Reflection.Emit { if (entryMethod == null) - throw new ArgumentNullException("entryMethod"); + throw new ArgumentNullException(nameof(entryMethod)); Contract.EndContractBlock(); BCLDebug.Log("DYNIL", "## DYNIL LOGGING: AssemblyBuilder.SetEntryPoint"); @@ -1588,36 +878,19 @@ namespace System.Reflection.Emit m_assemblyData.m_entryPointMethod = entryMethod; m_assemblyData.m_peFileKind = fileKind; - -#if !FEATURE_CORECLR - // Setting the entry point - ModuleBuilder tmpMB = tmpModule as ModuleBuilder; - if (tmpMB != null) - m_assemblyData.m_entryPointModule = tmpMB; - else - m_assemblyData.m_entryPointModule = GetModuleBuilder((InternalModuleBuilder)tmpModule); - - MethodToken entryMethodToken = m_assemblyData.m_entryPointModule.GetMethodToken(entryMethod); - m_assemblyData.m_entryPointModule.SetEntryPoint(entryMethodToken); -#endif //!FEATURE_CORECLR } /********************************************** * Use this function if client decides to form the custom attribute blob themselves **********************************************/ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif [System.Runtime.InteropServices.ComVisible(true)] public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) { if (con == null) - throw new ArgumentNullException("con"); + throw new ArgumentNullException(nameof(con)); if (binaryAttribute == null) - throw new ArgumentNullException("binaryAttribute"); + throw new ArgumentNullException(nameof(binaryAttribute)); Contract.EndContractBlock(); lock(SyncRoot) @@ -1626,7 +899,6 @@ namespace System.Reflection.Emit } } - [System.Security.SecurityCritical] // auto-generated private void SetCustomAttributeNoLock(ConstructorInfo con, byte[] binaryAttribute) { TypeBuilder.DefineCustomAttribute( @@ -1648,12 +920,11 @@ namespace System.Reflection.Emit /********************************************** * Use this function if client wishes to build CustomAttribute using CustomAttributeBuilder **********************************************/ - [System.Security.SecuritySafeCritical] // auto-generated public void SetCustomAttribute(CustomAttributeBuilder customBuilder) { if (customBuilder == null) { - throw new ArgumentNullException("customBuilder"); + throw new ArgumentNullException(nameof(customBuilder)); } Contract.EndContractBlock(); @@ -1663,7 +934,6 @@ namespace System.Reflection.Emit } } - [System.Security.SecurityCritical] // auto-generated private void SetCustomAttributeNoLock(CustomAttributeBuilder customBuilder) { customBuilder.CreateCustomAttribute( @@ -1693,7 +963,6 @@ namespace System.Reflection.Emit Save(assemblyFileName, System.Reflection.PortableExecutableKinds.ILOnly, System.Reflection.ImageFileMachine.I386); } - [System.Security.SecuritySafeCritical] // auto-generated public void Save(String assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine) { @@ -1703,358 +972,15 @@ namespace System.Reflection.Emit } } -#if FEATURE_CORECLR private void SaveNoLock(String assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine) { - // AssemblyBuilderAccess.Save can never be set with FEATURE_CORECLR + // AssemblyBuilderAccess.Save can never be set in CoreCLR throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CantSaveTransientAssembly")); } -#else // FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - private void SaveNoLock(String assemblyFileName, - PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine) - { - if (assemblyFileName == null) - throw new ArgumentNullException("assemblyFileName"); - if (assemblyFileName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "assemblyFileName"); - if (!String.Equals(assemblyFileName, Path.GetFileName(assemblyFileName))) - throw new ArgumentException(Environment.GetResourceString("Argument_NotSimpleFileName"), "assemblyFileName"); - Contract.EndContractBlock(); - - int i; - int size; - Type type; - TypeBuilder typeBuilder; - ModuleBuilder modBuilder; - String strModFileName; - ModuleBuilder assemblyModule; - ResWriterData tempRes; - int[] tkAttrs = null; - int[] tkAttrs2 = null; - ModuleBuilder onDiskAssemblyModule; - BCLDebug.Log("DYNIL","## DYNIL LOGGING: AssemblyBuilder.Save( " + assemblyFileName + " )"); - - String tmpVersionFile = null; - - try - { - if (m_assemblyData.m_iCABuilder != 0) - tkAttrs = new int[m_assemblyData.m_iCABuilder]; - if ( m_assemblyData.m_iCAs != 0) - tkAttrs2 = new int[m_assemblyData.m_iCAs]; - - if (m_assemblyData.m_isSaved == true) - { - // assembly has been saved before! - throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_AssemblyHasBeenSaved, - InternalAssembly.GetSimpleName())); - } - - if ((m_assemblyData.m_access & AssemblyBuilderAccess.Save) != AssemblyBuilderAccess.Save) - { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CantSaveTransientAssembly")); - } - - // Check if assembly info is supposed to be stored with one of the module files. - assemblyModule = m_assemblyData.FindModuleWithFileName(assemblyFileName); - - if (assemblyModule != null) - { - m_onDiskAssemblyModuleBuilder = assemblyModule; - - // In memory this module is not the manifest module and has a valid file token - // On disk it will be the manifest module so lets clean the file token - // We should not retrieve FileToken after the assembly has been saved - // If that is absolutely necessary, we need two separate fields on ModuleBuilderData: - // the in memory file token and the on disk file token. - assemblyModule.m_moduleData.FileToken = 0; - } - else - { // If assembly is to be stored alone, then no file name should conflict with it. - // This check will ensure resource file names are different assembly file name. - m_assemblyData.CheckFileNameConflict(assemblyFileName); - } - - if (m_assemblyData.m_strDir == null) - { - // set it to current directory - m_assemblyData.m_strDir = Directory.GetCurrentDirectory(); - } - else if (Directory.Exists(m_assemblyData.m_strDir) == false) - { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDirectory", - m_assemblyData.m_strDir)); - } - - // after this point, assemblyFileName is the full path name. - assemblyFileName = Path.Combine(m_assemblyData.m_strDir, assemblyFileName); - assemblyFileName = Path.GetFullPath(assemblyFileName); - - // Check caller has the right to create the assembly file itself. - new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Append, assemblyFileName).Demand(); - - // 1. setup/create the IMetaDataAssemblyEmit for the on disk version - if (assemblyModule != null) - { - // prepare saving CAs on assembly def. We need to introduce the MemberRef for - // the CA's type first of all. This is for the case the we have embedded manifest. - // We need to introduce these MRs before we call PreSave where we will snap - // into a ondisk metadata. If we do it after this, the ondisk metadata will - // not contain the proper MRs. - // - for (i=0; i < m_assemblyData.m_iCABuilder; i++) - { - tkAttrs[i] = m_assemblyData.m_CABuilders[i].PrepareCreateCustomAttributeToDisk( - assemblyModule); - } - for (i=0; i < m_assemblyData.m_iCAs; i++) - { - tkAttrs2[i] = assemblyModule.InternalGetConstructorToken(m_assemblyData.m_CACons[i], true).Token; - } - assemblyModule.PreSave(assemblyFileName, portableExecutableKind, imageFileMachine); - } - - RuntimeModule runtimeAssemblyModule = (assemblyModule != null) ? assemblyModule.ModuleHandle.GetRuntimeModule() : null; - PrepareForSavingManifestToDisk(GetNativeHandle(), runtimeAssemblyModule); - - // This function will return the embedded manifest module, an already exposed ModuleBuilder - // created by user, or make the stand alone manifest module exposed through managed code. - // - onDiskAssemblyModule = GetOnDiskAssemblyModuleBuilder(); - - // Set any native resources on the OnDiskAssemblyModule. - if (m_assemblyData.m_strResourceFileName != null) - onDiskAssemblyModule.DefineUnmanagedResourceFileInternalNoLock(m_assemblyData.m_strResourceFileName); - else if (m_assemblyData.m_resourceBytes != null) - onDiskAssemblyModule.DefineUnmanagedResourceInternalNoLock(m_assemblyData.m_resourceBytes); - else if (m_assemblyData.m_hasUnmanagedVersionInfo == true) - { - // calculate unmanaged version info from assembly's custom attributes - m_assemblyData.FillUnmanagedVersionInfo(); - - String strFileVersion = m_assemblyData.m_nativeVersion.m_strFileVersion; - if (strFileVersion == null) - strFileVersion = GetVersion().ToString(); - - // Create the file. - CreateVersionInfoResource( - assemblyFileName, - m_assemblyData.m_nativeVersion.m_strTitle, // title - null, // Icon filename - m_assemblyData.m_nativeVersion.m_strDescription, // description - m_assemblyData.m_nativeVersion.m_strCopyright, - m_assemblyData.m_nativeVersion.m_strTrademark, - m_assemblyData.m_nativeVersion.m_strCompany, - m_assemblyData.m_nativeVersion.m_strProduct, - m_assemblyData.m_nativeVersion.m_strProductVersion, - strFileVersion, - m_assemblyData.m_nativeVersion.m_lcid, - m_assemblyData.m_peFileKind == PEFileKinds.Dll, - JitHelpers.GetStringHandleOnStack(ref tmpVersionFile)); - - onDiskAssemblyModule.DefineUnmanagedResourceFileInternalNoLock(tmpVersionFile); - } - - if (assemblyModule == null) - { - - // This is for introducing the MRs for CA's type. This case is for stand alone - // manifest. We need to wait till PrepareForSavingManifestToDisk is called. - // That will trigger the creation of the on-disk stand alone manifest module. - // - for (i=0; i < m_assemblyData.m_iCABuilder; i++) - { - tkAttrs[i] = m_assemblyData.m_CABuilders[i].PrepareCreateCustomAttributeToDisk( - onDiskAssemblyModule); - } - for (i=0; i < m_assemblyData.m_iCAs; i++) - { - tkAttrs2[i] = onDiskAssemblyModule.InternalGetConstructorToken(m_assemblyData.m_CACons[i], true).Token; - } - } - - // 2. save all of the persistable modules contained by this AssemblyBuilder except the module that is going to contain - // Assembly information - // - // 3. create the file list in the manifest and track the file token. If it is embedded assembly, - // the assembly file should not be on the file list. - // - size = m_assemblyData.m_moduleBuilderList.Count; - for (i = 0; i < size; i++) - { - ModuleBuilder mBuilder = (ModuleBuilder) m_assemblyData.m_moduleBuilderList[i]; - if (mBuilder.IsTransient() == false && mBuilder != assemblyModule) - { - strModFileName = mBuilder.m_moduleData.m_strFileName; - if (m_assemblyData.m_strDir != null) - { - strModFileName = Path.Combine(m_assemblyData.m_strDir, strModFileName); - strModFileName = Path.GetFullPath(strModFileName); - } - - // Check caller has the right to create the Module file itself. - new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Append, strModFileName).Demand(); - - mBuilder.m_moduleData.FileToken = AddFile(GetNativeHandle(), mBuilder.m_moduleData.m_strFileName); - mBuilder.PreSave(strModFileName, portableExecutableKind, imageFileMachine); - mBuilder.Save(strModFileName, false, portableExecutableKind, imageFileMachine); - - // Cannot set the hash value when creating the file since the file token - // is needed to created the entries for the embedded resources in the - // module and the resources need to be there before you figure the hash. - SetFileHashValue(GetNativeHandle(), mBuilder.m_moduleData.FileToken, strModFileName); - } - } - - // 4. Add the public ComType - for (i=0; i < m_assemblyData.m_iPublicComTypeCount; i++) - { - type = m_assemblyData.m_publicComTypeList[i]; - // If the type that was added as a Public Com Type was obtained via Reflection, - // it will be a System.RuntimeType, even if it was really, at the same time, - // a TypeBuilder. Unfortunately, you can't get back to the TypeBuilder, so - // this code has to deal with either-or. - if (type is RuntimeType) - { - // If type is a runtime type, it must be a baked TypeBuilder, - // ttype.Module should be an InternalModuleBuilder - - InternalModuleBuilder internalMB = (InternalModuleBuilder)type.Module; - modBuilder = this.GetModuleBuilder(internalMB); - if (modBuilder != assemblyModule) - DefineNestedComType(type, modBuilder.m_moduleData.FileToken, type.MetadataToken); - } - else - { - // Could assert that "type" is a TypeBuilder, but next statement throws if it isn't. - typeBuilder = (TypeBuilder) type; - // If type is a TypeBuilder, type.Module must be a ModuleBuilder. - modBuilder = typeBuilder.GetModuleBuilder(); - if (modBuilder != assemblyModule) - DefineNestedComType(type, modBuilder.m_moduleData.FileToken, typeBuilder.MetadataTokenInternal); - } - } - - // 5. write AssemblyDef's CAs (only if we are not saving directly the manifest module itself) - if (onDiskAssemblyModule != m_manifestModuleBuilder) - { - for (i = 0; i < m_assemblyData.m_iCABuilder; i++) - { - m_assemblyData.m_CABuilders[i].CreateCustomAttribute( - onDiskAssemblyModule, - AssemblyBuilderData.m_tkAssembly, // This is the AssemblyDef token - tkAttrs[i], true); - } - - for (i = 0; i < m_assemblyData.m_iCAs; i++) - { - TypeBuilder.DefineCustomAttribute( - onDiskAssemblyModule, // pass in the in-memory assembly module - AssemblyBuilderData.m_tkAssembly, // This is the AssemblyDef token - tkAttrs2[i], - m_assemblyData.m_CABytes[i], - true, false); - } - } - - // 6. write security permission requests to the manifest. -#pragma warning disable 618 - if (m_assemblyData.m_RequiredPset != null) - AddDeclarativeSecurity(m_assemblyData.m_RequiredPset, SecurityAction.RequestMinimum); - - if (m_assemblyData.m_RefusedPset != null) - AddDeclarativeSecurity(m_assemblyData.m_RefusedPset, SecurityAction.RequestRefuse); - - if (m_assemblyData.m_OptionalPset != null) - AddDeclarativeSecurity(m_assemblyData.m_OptionalPset, SecurityAction.RequestOptional); -#pragma warning restore 618 - - // 7. Save the stand alone managed resources - size = m_assemblyData.m_resWriterList.Count; - for (i = 0; i < size; i++) - { - tempRes = null; - - try - { - tempRes = (ResWriterData)m_assemblyData.m_resWriterList[i]; - - // If the user added an existing resource to the manifest, the - // corresponding ResourceWriter will be null. - if (tempRes.m_resWriter != null) - // Check caller has the right to create the Resource file itself. - new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Append, tempRes.m_strFullFileName).Demand(); - } - finally - { - if (tempRes != null && tempRes.m_resWriter != null) - tempRes.m_resWriter.Close(); - } - - // Add entry to manifest for this stand alone resource - AddStandAloneResource(GetNativeHandle(), tempRes.m_strName, tempRes.m_strFileName, tempRes.m_strFullFileName, (int)tempRes.m_attribute); - } - - // Save now!! - if (assemblyModule == null) - { - onDiskAssemblyModule.DefineNativeResource(portableExecutableKind, imageFileMachine); - - // Stand alone manifest - int entryPoint = (m_assemblyData.m_entryPointModule != null) ? m_assemblyData.m_entryPointModule.m_moduleData.FileToken : 0; - - SaveManifestToDisk(GetNativeHandle(), assemblyFileName, entryPoint, (int)m_assemblyData.m_peFileKind, - (int)portableExecutableKind, (int)imageFileMachine); - } - else - { - // embedded manifest - - // If the module containing the entry point is not the manifest file, we need to - // let the manifest file point to the module which contains the entry point. - // - // - // - // - if (m_assemblyData.m_entryPointModule != null && m_assemblyData.m_entryPointModule != assemblyModule) - assemblyModule.SetEntryPoint(new MethodToken(m_assemblyData.m_entryPointModule.m_moduleData.FileToken)); - assemblyModule.Save(assemblyFileName, true, portableExecutableKind, imageFileMachine); - } - m_assemblyData.m_isSaved = true; - } - finally - { - if (tmpVersionFile != null) - { - // Delete file. - System.IO.File.Delete(tmpVersionFile); - } - } - } -#endif // FEATURE_CORECLR - -#if FEATURE_CAS_POLICY - [System.Security.SecurityCritical] // auto-generated - private void AddDeclarativeSecurity(PermissionSet pset, SecurityAction action) - { - // Translate sets into internal encoding (uses standard binary serialization). - byte[] blob = pset.EncodeXml(); - AddDeclarativeSecurity(GetNativeHandle(), action, blob, blob.Length); - } -#endif // FEATURE_CAS_POLICY - internal bool IsPersistable() { -#if !FEATURE_CORECLR // AssemblyBuilderAccess.Save is never set in CoreCLR - if ((m_assemblyData.m_access & AssemblyBuilderAccess.Save) == AssemblyBuilderAccess.Save) - { - return true; - } - else -#endif // FEATURE_CORECLR { return false; } @@ -2065,7 +991,6 @@ namespace System.Reflection.Emit * Internal helper to walk the nested type hierachy * **********************************************/ - [System.Security.SecurityCritical] // auto-generated private int DefineNestedComType(Type type, int tkResolutionScope, int tkTypeDef) { Type enclosingType = type.DeclaringType; @@ -2080,7 +1005,6 @@ namespace System.Reflection.Emit return AddExportedTypeOnDisk(GetNativeHandle(), type.Name, tkResolutionScope, tkTypeDef, type.Attributes); } - [System.Security.SecurityCritical] // auto-generated internal int DefineExportedTypeInMemory(Type type, int tkResolutionScope, int tkTypeDef) { Type enclosingType = type.DeclaringType; @@ -2107,32 +1031,7 @@ namespace System.Reflection.Emit **********************************************/ private AssemblyBuilder() {} -#if !FEATURE_CORECLR - void _AssemblyBuilder.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _AssemblyBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _AssemblyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - // If you implement this method, make sure to include _AssemblyBuilder.Invoke in VM\DangerousAPIs.h and - // include _AssemblyBuilder in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp. - void _AssemblyBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif - // Create a new module in which to emit code. This module will not contain the manifest. - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] static private extern void DefineDynamicModule(RuntimeAssembly containingAssembly, @@ -2145,7 +1044,6 @@ namespace System.Reflection.Emit bool fIsTransient, out int tkFile); - [System.Security.SecurityCritical] // auto-generated private static Module DefineDynamicModule(RuntimeAssembly containingAssembly, bool emitSymbolInfo, String name, @@ -2171,12 +1069,10 @@ namespace System.Reflection.Emit } // The following functions are native helpers for creating on-disk manifest - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] static private extern void PrepareForSavingManifestToDisk(RuntimeAssembly assembly, RuntimeModule assemblyModule); // module to contain assembly information if assembly is embedded - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] static private extern void SaveManifestToDisk(RuntimeAssembly assembly, @@ -2186,19 +1082,16 @@ namespace System.Reflection.Emit int portableExecutableKind, int ImageFileMachine); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] static private extern int AddFile(RuntimeAssembly assembly, String strFileName); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] static private extern void SetFileHashValue(RuntimeAssembly assembly, int tkFile, String strFullFileName); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] static private extern int AddExportedTypeInMemory(RuntimeAssembly assembly, @@ -2207,7 +1100,6 @@ namespace System.Reflection.Emit int tkTypeDef, TypeAttributes flags); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] static private extern int AddExportedTypeOnDisk(RuntimeAssembly assembly, @@ -2217,7 +1109,6 @@ namespace System.Reflection.Emit TypeAttributes flags); // Add an entry to assembly's manifestResource table for a stand alone resource. - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] static private extern void AddStandAloneResource(RuntimeAssembly assembly, @@ -2226,7 +1117,6 @@ namespace System.Reflection.Emit String strFullFileName, int attribute); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] #pragma warning disable 618 @@ -2234,7 +1124,6 @@ namespace System.Reflection.Emit #pragma warning restore 618 // Functions for defining unmanaged resources. - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] static private extern void CreateVersionInfoResource(String filename, String title, String iconFilename, String description, diff --git a/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilderAccess.cs b/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilderAccess.cs index 00a961d..5c86d8e 100644 --- a/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilderAccess.cs +++ b/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilderAccess.cs @@ -8,17 +8,13 @@ using System; // EE uses these enum values..look for m_dwDynamicAssemblyAccess in Assembly.hpp namespace System.Reflection.Emit -{ +{ [Serializable] [System.Runtime.InteropServices.ComVisible(true)] [Flags] public enum AssemblyBuilderAccess { Run = 1, -#if !FEATURE_CORECLR // these are unsupported - Save = 2, - RunAndSave = Run | Save, -#endif // !FEATURE_CORECLR #if FEATURE_REFLECTION_ONLY_LOAD ReflectionOnly = 6, // 4 | Save, #endif // FEATURE_REFLECTION_ONLY_LOAD diff --git a/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilderData.cs b/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilderData.cs index f1a38c6..f0f83e7 100644 --- a/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilderData.cs +++ b/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilderData.cs @@ -14,11 +14,7 @@ namespace System.Reflection.Emit { using System.Security; using System.Diagnostics; using CultureInfo = System.Globalization.CultureInfo; -#if !FEATURE_CORECLR - using ResourceWriter = System.Resources.ResourceWriter; -#else // FEATURE_CORECLR using IResourceWriter = System.Resources.IResourceWriter; -#endif // !FEATURE_CORECLR using System.IO; using System.Runtime.Versioning; using System.Diagnostics.SymbolStore; @@ -29,7 +25,6 @@ namespace System.Reflection.Emit { // this class cannot be accessed from the EE. internal class AssemblyBuilderData { - [SecurityCritical] internal AssemblyBuilderData( InternalAssemblyBuilder assembly, String strAssemblyName, @@ -120,7 +115,6 @@ namespace System.Reflection.Emit { // If DefineUnmanagedVersionInfo is called, the parameter provided will override // the CA's value. // - [System.Security.SecurityCritical] // auto-generated internal void FillUnmanagedVersionInfo() { // Get the lcid set on the assembly name as default if available @@ -242,7 +236,7 @@ namespace System.Reflection.Emit { } // CultureInfo attribute overrides the lcid from AssemblyName. CultureInfo culture = new CultureInfo(m_CABuilders[i].m_constructorArgs[0].ToString()); -#if FEATURE_USE_LCID +#if FEATURE_USE_LCID m_nativeVersion.m_lcid = culture.LCID; #endif } @@ -469,7 +463,7 @@ namespace System.Reflection.Emit { // hard coding the assembly def token internal const int m_tkAssembly = 0x20000001; - + // Security permission requests internal PermissionSet m_RequiredPset; internal PermissionSet m_OptionalPset; @@ -485,10 +479,6 @@ namespace System.Reflection.Emit { internal MethodInfo m_entryPointMethod; internal Assembly m_ISymWrapperAssembly; -#if !FEATURE_CORECLR - internal ModuleBuilder m_entryPointModule; -#endif //!FEATURE_CORECLR - // For unmanaged resources internal String m_strResourceFileName; internal byte[] m_resourceBytes; @@ -507,7 +497,6 @@ namespace System.Reflection.Emit { **********************************************/ internal class ResWriterData { -#if FEATURE_CORECLR internal ResWriterData( IResourceWriter resWriter, Stream memoryStream, @@ -524,29 +513,8 @@ namespace System.Reflection.Emit { m_nextResWriter = null; m_attribute = attribute; } -#else - internal ResWriterData( - ResourceWriter resWriter, - Stream memoryStream, - String strName, - String strFileName, - String strFullFileName, - ResourceAttributes attribute) - { - m_resWriter = resWriter; - m_memoryStream = memoryStream; - m_strName = strName; - m_strFileName = strFileName; - m_strFullFileName = strFullFileName; - m_nextResWriter = null; - m_attribute = attribute; - } -#endif -#if !FEATURE_CORECLR - internal ResourceWriter m_resWriter; -#else // FEATURE_CORECLR - internal IResourceWriter m_resWriter; -#endif // !FEATURE_CORECLR + + internal IResourceWriter m_resWriter; internal String m_strName; internal String m_strFileName; internal String m_strFullFileName; diff --git a/src/mscorlib/src/System/Reflection/Emit/ComInterfaces.cs b/src/mscorlib/src/System/Reflection/Emit/ComInterfaces.cs index 0d8ce5a..8dba934 100644 --- a/src/mscorlib/src/System/Reflection/Emit/ComInterfaces.cs +++ b/src/mscorlib/src/System/Reflection/Emit/ComInterfaces.cs @@ -2,33 +2,15 @@ // 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.Globalization; -using System.IO; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Runtime.Serialization; -using System.Security.Permissions; -using System.Security.Policy; - namespace System.Runtime.InteropServices { [GuidAttribute("BEBB2505-8B54-3443-AEAD-142A16DD9CC7")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.AssemblyBuilder))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _AssemblyBuilder { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); -#endif } [GuidAttribute("ED3E4384-D7E2-3FA7-8FFD-8940D330519A")] @@ -38,141 +20,69 @@ namespace System.Runtime.InteropServices [System.Runtime.InteropServices.ComVisible(true)] public interface _ConstructorBuilder { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); -#endif } [GuidAttribute("BE9ACCE8-AAFF-3B91-81AE-8211663F5CAD")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.CustomAttributeBuilder))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _CustomAttributeBuilder { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); -#endif } [GuidAttribute("C7BD73DE-9F85-3290-88EE-090B8BDFE2DF")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.EnumBuilder))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _EnumBuilder { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); -#endif } [GuidAttribute("AADABA99-895D-3D65-9760-B1F12621FAE8")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.EventBuilder))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _EventBuilder { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); -#endif } [GuidAttribute("CE1A3BF5-975E-30CC-97C9-1EF70F8F3993")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.FieldBuilder))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _FieldBuilder { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); -#endif } [GuidAttribute("A4924B27-6E3B-37F7-9B83-A4501955E6A7")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.ILGenerator))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _ILGenerator { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); -#endif } [GuidAttribute("4E6350D1-A08B-3DEC-9A3E-C465F9AEEC0C")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.LocalBuilder))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _LocalBuilder { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); -#endif } [GuidAttribute("007D8A14-FDF3-363E-9A0B-FEC0618260A2")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.MethodBuilder))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _MethodBuilder { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); -#endif } #if FEATURE_METHOD_RENTAL @@ -180,18 +90,9 @@ namespace System.Runtime.InteropServices [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.MethodRental))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _MethodRental { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); -#endif } #endif @@ -199,90 +100,44 @@ namespace System.Runtime.InteropServices [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.ModuleBuilder))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _ModuleBuilder { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); -#endif } [GuidAttribute("36329EBA-F97A-3565-BC07-0ED5C6EF19FC")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.ParameterBuilder))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _ParameterBuilder { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); -#endif } [GuidAttribute("15F9A479-9397-3A63-ACBD-F51977FB0F02")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.PropertyBuilder))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _PropertyBuilder { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); -#endif } [GuidAttribute("7D13DD37-5A04-393C-BBCA-A5FEA802893D")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.SignatureHelper))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _SignatureHelper { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); -#endif } [GuidAttribute("7E5678EE-48B3-3F83-B076-C58543498A58")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.TypeBuilder))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _TypeBuilder { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); -#endif } - } diff --git a/src/mscorlib/src/System/Reflection/Emit/ConstructorBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/ConstructorBuilder.cs index e5062d3..ef76adc 100644 --- a/src/mscorlib/src/System/Reflection/Emit/ConstructorBuilder.cs +++ b/src/mscorlib/src/System/Reflection/Emit/ConstructorBuilder.cs @@ -16,7 +16,6 @@ namespace System.Reflection.Emit using System.Runtime.InteropServices; using System.Diagnostics.Contracts; - [HostProtection(MayLeakOnAbort = true)] [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_ConstructorBuilder))] [System.Runtime.InteropServices.ComVisible(true)] @@ -31,7 +30,6 @@ namespace System.Reflection.Emit { } - [System.Security.SecurityCritical] // auto-generated internal ConstructorBuilder(String name, MethodAttributes attributes, CallingConventions callingConvention, Type[] parameterTypes, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers, ModuleBuilder mod, TypeBuilder type) { @@ -49,7 +47,6 @@ namespace System.Reflection.Emit token = m_methodBuilder.GetToken(); } - [System.Security.SecurityCritical] // auto-generated internal ConstructorBuilder(String name, MethodAttributes attributes, CallingConventions callingConvention, Type[] parameterTypes, ModuleBuilder mod, TypeBuilder type) : this(name, attributes, callingConvention, parameterTypes, null, null, mod, type) @@ -205,9 +202,6 @@ namespace System.Reflection.Emit return m_methodBuilder.GetILGenerator(streamSize); } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif public void SetMethodBody(byte[] il, int maxStack, byte[] localSignature, IEnumerable exceptionHandlers, IEnumerable tokenFixups) { if (m_isDefaultConstructor) @@ -218,36 +212,6 @@ namespace System.Reflection.Emit m_methodBuilder.SetMethodBody(il, maxStack, localSignature, exceptionHandlers, tokenFixups); } -#if FEATURE_CAS_POLICY - [System.Security.SecuritySafeCritical] // auto-generated - public void AddDeclarativeSecurity(SecurityAction action, PermissionSet pset) - { - if (pset == null) - throw new ArgumentNullException("pset"); - -#pragma warning disable 618 - if (!Enum.IsDefined(typeof(SecurityAction), action) || - action == SecurityAction.RequestMinimum || - action == SecurityAction.RequestOptional || - action == SecurityAction.RequestRefuse) - { - throw new ArgumentOutOfRangeException("action"); - } -#pragma warning restore 618 - Contract.EndContractBlock(); - - // Cannot add declarative security after type is created. - if (m_methodBuilder.IsTypeCreated()) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_TypeHasBeenCreated")); - - // Translate permission set into serialized format (use standard binary serialization). - byte[] blob = pset.EncodeXml(); - - // Write the blob into the metadata. - TypeBuilder.AddDeclarativeSecurity(GetModuleBuilder().GetNativeHandle(), GetToken().Token, action, blob, blob.Length); - } -#endif // FEATURE_CAS_POLICY - public override CallingConventions CallingConvention { get @@ -282,9 +246,6 @@ namespace System.Reflection.Emit get { return m_methodBuilder.Signature; } } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif [System.Runtime.InteropServices.ComVisible(true)] public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) { @@ -308,28 +269,6 @@ namespace System.Reflection.Emit } #endregion - -#if !FEATURE_CORECLR - void _ConstructorBuilder.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _ConstructorBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _ConstructorBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - void _ConstructorBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif } } diff --git a/src/mscorlib/src/System/Reflection/Emit/CustomAttributeBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/CustomAttributeBuilder.cs index 2a29a5c..545657a 100644 --- a/src/mscorlib/src/System/Reflection/Emit/CustomAttributeBuilder.cs +++ b/src/mscorlib/src/System/Reflection/Emit/CustomAttributeBuilder.cs @@ -22,9 +22,9 @@ namespace System.Reflection.Emit { using System.Security.Permissions; using System.Runtime.InteropServices; using System.Globalization; + using System.Diagnostics; using System.Diagnostics.Contracts; - [HostProtection(MayLeakOnAbort = true)] [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_CustomAttributeBuilder))] [System.Runtime.InteropServices.ComVisible(true)] @@ -70,8 +70,14 @@ namespace System.Reflection.Emit { // Check that a type is suitable for use in a custom attribute. private bool ValidateType(Type t) { - if (t.IsPrimitive || t == typeof(String) || t == typeof(Type)) + if (t.IsPrimitive) + { + return t != typeof(IntPtr) && t != typeof(UIntPtr); + } + if (t == typeof(String) || t == typeof(Type)) + { return true; + } if (t.IsEnum) { switch (Type.GetTypeCode(Enum.GetUnderlyingType(t))) @@ -103,17 +109,17 @@ namespace System.Reflection.Emit { FieldInfo[] namedFields, Object[] fieldValues) { if (con == null) - throw new ArgumentNullException("con"); + throw new ArgumentNullException(nameof(con)); if (constructorArgs == null) - throw new ArgumentNullException("constructorArgs"); + throw new ArgumentNullException(nameof(constructorArgs)); if (namedProperties == null) - throw new ArgumentNullException("namedProperties"); + throw new ArgumentNullException(nameof(namedProperties)); if (propertyValues == null) - throw new ArgumentNullException("propertyValues"); + throw new ArgumentNullException(nameof(propertyValues)); if (namedFields == null) - throw new ArgumentNullException("namedFields"); + throw new ArgumentNullException(nameof(namedFields)); if (fieldValues == null) - throw new ArgumentNullException("fieldValues"); + throw new ArgumentNullException(nameof(fieldValues)); if (namedProperties.Length != propertyValues.Length) throw new ArgumentException(Environment.GetResourceString("Arg_ArrayLengthsDiffer"), "namedProperties, propertyValues"); if (namedFields.Length != fieldValues.Length) @@ -123,7 +129,7 @@ namespace System.Reflection.Emit { if ((con.Attributes & MethodAttributes.Static) == MethodAttributes.Static || (con.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private) throw new ArgumentException(Environment.GetResourceString("Argument_BadConstructor")); - + if ((con.CallingConvention & CallingConventions.Standard) != CallingConventions.Standard) throw new ArgumentException(Environment.GetResourceString("Argument_BadConstructorCallConv")); @@ -150,12 +156,16 @@ namespace System.Reflection.Emit { // Now verify that the types of the actual parameters are compatible with the types of the formal parameters. for (i = 0; i < paramTypes.Length; i++) { - if (constructorArgs[i] == null) + object constructorArg = constructorArgs[i]; + if (constructorArg == null) + { + if (paramTypes[i].IsValueType) + { + throw new ArgumentNullException($"{nameof(constructorArgs)}[{i}]"); + } continue; - TypeCode paramTC = Type.GetTypeCode(paramTypes[i]); - if (paramTC != Type.GetTypeCode(constructorArgs[i].GetType())) - if (paramTC != TypeCode.Object || !ValidateType(constructorArgs[i].GetType())) - throw new ArgumentException(Environment.GetResourceString("Argument_BadParameterTypeForConstructor", i)); + } + VerifyTypeAndPassedObjectType(paramTypes[i], constructorArg.GetType(), $"{nameof(constructorArgs)}[{i}]"); } // Allocate a memory stream to represent the CA blob in the metadata and a binary writer to help format it. @@ -176,12 +186,14 @@ namespace System.Reflection.Emit { for (i = 0; i < namedProperties.Length; i++) { // Validate the property. - if (namedProperties[i] == null) + PropertyInfo property = namedProperties[i]; + if (property == null) throw new ArgumentNullException("namedProperties[" + i + "]"); // Allow null for non-primitive types only. - Type propType = namedProperties[i].PropertyType; - if (propertyValues[i] == null && propType.IsPrimitive) + Type propType = property.PropertyType; + object propertyValue = propertyValues[i]; + if (propertyValue == null && propType.IsValueType) throw new ArgumentNullException("propertyValues[" + i + "]"); // Validate property type. @@ -189,55 +201,57 @@ namespace System.Reflection.Emit { throw new ArgumentException(Environment.GetResourceString("Argument_BadTypeInCustomAttribute")); // Property has to be writable. - if (!namedProperties[i].CanWrite) + if (!property.CanWrite) throw new ArgumentException(Environment.GetResourceString("Argument_NotAWritableProperty")); - + // Property has to be from the same class or base class as ConstructorInfo. - if (namedProperties[i].DeclaringType != con.DeclaringType + if (property.DeclaringType != con.DeclaringType && (!(con.DeclaringType is TypeBuilderInstantiation)) - && !con.DeclaringType.IsSubclassOf(namedProperties[i].DeclaringType)) + && !con.DeclaringType.IsSubclassOf(property.DeclaringType)) { // Might have failed check because one type is a XXXBuilder // and the other is not. Deal with these special cases // separately. - if (!TypeBuilder.IsTypeEqual(namedProperties[i].DeclaringType, con.DeclaringType)) + if (!TypeBuilder.IsTypeEqual(property.DeclaringType, con.DeclaringType)) { // IsSubclassOf is overloaded to do the right thing if // the constructor is a TypeBuilder, but we still need // to deal with the case where the property's declaring // type is one. - if (!(namedProperties[i].DeclaringType is TypeBuilder) || - !con.DeclaringType.IsSubclassOf(((TypeBuilder)namedProperties[i].DeclaringType).BakedRuntimeType)) + if (!(property.DeclaringType is TypeBuilder) || + !con.DeclaringType.IsSubclassOf(((TypeBuilder)property.DeclaringType).BakedRuntimeType)) throw new ArgumentException(Environment.GetResourceString("Argument_BadPropertyForConstructorBuilder")); } } // Make sure the property's type can take the given value. // Note that there will be no coersion. - if (propertyValues[i] != null && - propType != typeof(Object) && - Type.GetTypeCode(propertyValues[i].GetType()) != Type.GetTypeCode(propType)) - throw new ArgumentException(Environment.GetResourceString("Argument_ConstantDoesntMatch")); - + if (propertyValue != null) + { + VerifyTypeAndPassedObjectType(propType, propertyValue.GetType(), $"{nameof(propertyValues)}[{i}]"); + } + // First a byte indicating that this is a property. writer.Write((byte)CustomAttributeEncoding.Property); // Emit the property type, name and value. EmitType(writer, propType); EmitString(writer, namedProperties[i].Name); - EmitValue(writer, propType, propertyValues[i]); + EmitValue(writer, propType, propertyValue); } // Emit all the field sets. for (i = 0; i < namedFields.Length; i++) { // Validate the field. - if (namedFields[i] == null) + FieldInfo namedField = namedFields[i]; + if (namedField == null) throw new ArgumentNullException("namedFields[" + i + "]"); // Allow null for non-primitive types only. - Type fldType = namedFields[i].FieldType; - if (fieldValues[i] == null && fldType.IsPrimitive) + Type fldType = namedField.FieldType; + object fieldValue = fieldValues[i]; + if (fieldValue == null && fldType.IsValueType) throw new ArgumentNullException("fieldValues[" + i + "]"); // Validate field type. @@ -245,20 +259,20 @@ namespace System.Reflection.Emit { throw new ArgumentException(Environment.GetResourceString("Argument_BadTypeInCustomAttribute")); // Field has to be from the same class or base class as ConstructorInfo. - if (namedFields[i].DeclaringType != con.DeclaringType + if (namedField.DeclaringType != con.DeclaringType && (!(con.DeclaringType is TypeBuilderInstantiation)) - && !con.DeclaringType.IsSubclassOf(namedFields[i].DeclaringType)) + && !con.DeclaringType.IsSubclassOf(namedField.DeclaringType)) { // Might have failed check because one type is a XXXBuilder // and the other is not. Deal with these special cases // separately. - if (!TypeBuilder.IsTypeEqual(namedFields[i].DeclaringType, con.DeclaringType)) + if (!TypeBuilder.IsTypeEqual(namedField.DeclaringType, con.DeclaringType)) { // IsSubclassOf is overloaded to do the right thing if // the constructor is a TypeBuilder, but we still need // to deal with the case where the field's declaring // type is one. - if (!(namedFields[i].DeclaringType is TypeBuilder) || + if (!(namedField.DeclaringType is TypeBuilder) || !con.DeclaringType.IsSubclassOf(((TypeBuilder)namedFields[i].DeclaringType).BakedRuntimeType)) throw new ArgumentException(Environment.GetResourceString("Argument_BadFieldForConstructorBuilder")); } @@ -266,24 +280,36 @@ namespace System.Reflection.Emit { // Make sure the field's type can take the given value. // Note that there will be no coersion. - if (fieldValues[i] != null && - fldType != typeof(Object) && - Type.GetTypeCode(fieldValues[i].GetType()) != Type.GetTypeCode(fldType)) - throw new ArgumentException(Environment.GetResourceString("Argument_ConstantDoesntMatch")); + if (fieldValue != null) + { + VerifyTypeAndPassedObjectType(fldType, fieldValue.GetType(), $"{nameof(fieldValues)}[{i}]"); + } // First a byte indicating that this is a field. writer.Write((byte)CustomAttributeEncoding.Field); // Emit the field type, name and value. EmitType(writer, fldType); - EmitString(writer, namedFields[i].Name); - EmitValue(writer, fldType, fieldValues[i]); + EmitString(writer, namedField.Name); + EmitValue(writer, fldType, fieldValue); } // Create the blob array. m_blob = ((MemoryStream)writer.BaseStream).ToArray(); } + private static void VerifyTypeAndPassedObjectType(Type type, Type passedType, string paramName) + { + if (type != typeof(object) && Type.GetTypeCode(passedType) != Type.GetTypeCode(type)) + { + throw new ArgumentException(Environment.GetResourceString("Argument_ConstantDoesntMatch")); + } + if (passedType == typeof(IntPtr) || passedType == typeof(UIntPtr)) + { + throw new ArgumentException(Environment.GetResourceString("Argument_BadParameterTypeForCAB"), paramName); + } + } + private void EmitType(BinaryWriter writer, Type type) { if (type.IsPrimitive) @@ -327,7 +353,7 @@ namespace System.Reflection.Emit { writer.Write((byte)CustomAttributeEncoding.Double); break; default: - Contract.Assert(false, "Invalid primitive type"); + Debug.Assert(false, "Invalid primitive type"); break; } } @@ -411,7 +437,7 @@ namespace System.Reflection.Emit { writer.Write((ulong)value); break; default: - Contract.Assert(false, "Invalid enum base type"); + Debug.Assert(false, "Invalid enum base type"); break; } } @@ -489,7 +515,7 @@ namespace System.Reflection.Emit { writer.Write((double)value); break; default: - Contract.Assert(false, "Invalid primitive type"); + Debug.Assert(false, "Invalid primitive type"); break; } } @@ -524,7 +550,6 @@ namespace System.Reflection.Emit { // return the byte interpretation of the custom attribute - [System.Security.SecurityCritical] // auto-generated internal void CreateCustomAttribute(ModuleBuilder mod, int tkOwner) { CreateCustomAttribute(mod, tkOwner, mod.GetConstructorToken(m_con).Token, false); @@ -537,7 +562,6 @@ namespace System.Reflection.Emit { // This function has to be called before we snap the in-memory module for on disk (i.e. Presave on // ModuleBuilder. //************************************************* - [System.Security.SecurityCritical] // auto-generated internal int PrepareCreateCustomAttributeToDisk(ModuleBuilder mod) { return mod.InternalGetConstructorToken(m_con, true).Token; @@ -546,35 +570,12 @@ namespace System.Reflection.Emit { //************************************************* // Call this function with toDisk=1, after on disk module has been snapped. //************************************************* - [System.Security.SecurityCritical] // auto-generated internal void CreateCustomAttribute(ModuleBuilder mod, int tkOwner, int tkAttrib, bool toDisk) { TypeBuilder.DefineCustomAttribute(mod, tkOwner, tkAttrib, m_blob, toDisk, typeof(System.Diagnostics.DebuggableAttribute) == m_con.DeclaringType); } -#if !FEATURE_CORECLR - void _CustomAttributeBuilder.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _CustomAttributeBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _CustomAttributeBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - void _CustomAttributeBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif - internal ConstructorInfo m_con; internal Object[] m_constructorArgs; internal byte[] m_blob; diff --git a/src/mscorlib/src/System/Reflection/Emit/DynamicILGenerator.cs b/src/mscorlib/src/System/Reflection/Emit/DynamicILGenerator.cs index b66fdad..9e1d829 100644 --- a/src/mscorlib/src/System/Reflection/Emit/DynamicILGenerator.cs +++ b/src/mscorlib/src/System/Reflection/Emit/DynamicILGenerator.cs @@ -9,7 +9,6 @@ namespace System.Reflection.Emit using System; using System.Globalization; - using TextWriter = System.IO.TextWriter; using System.Diagnostics.SymbolStore; using System.Runtime.InteropServices; using System.Reflection; @@ -17,6 +16,7 @@ namespace System.Reflection.Emit using System.Collections.Generic; using System.Security.Permissions; using System.Threading; + using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; using System.Security; @@ -36,7 +36,6 @@ namespace System.Reflection.Emit } - [System.Security.SecurityCritical] // auto-generated internal void GetCallableMethod(RuntimeModule module, DynamicMethod dm) { dm.m_methodHandle = ModuleHandle.GetDynamicMethod(dm, @@ -62,7 +61,7 @@ namespace System.Reflection.Emit { LocalBuilder localBuilder; if (localType == null) - throw new ArgumentNullException("localType"); + throw new ArgumentNullException(nameof(localType)); Contract.EndContractBlock(); RuntimeType rtType = localType as RuntimeType; @@ -87,11 +86,10 @@ namespace System.Reflection.Emit // Token resolution calls // // - [System.Security.SecuritySafeCritical] // auto-generated public override void Emit(OpCode opcode, MethodInfo meth) { if (meth == null) - throw new ArgumentNullException("meth"); + throw new ArgumentNullException(nameof(meth)); Contract.EndContractBlock(); int stackchange = 0; @@ -101,7 +99,7 @@ namespace System.Reflection.Emit { RuntimeMethodInfo rtMeth = meth as RuntimeMethodInfo; if (rtMeth == null) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "meth"); + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), nameof(meth)); RuntimeType declaringType = rtMeth.GetRuntimeType(); if (declaringType != null && (declaringType.IsGenericType || declaringType.IsArray)) @@ -148,12 +146,12 @@ namespace System.Reflection.Emit public override void Emit(OpCode opcode, ConstructorInfo con) { if (con == null) - throw new ArgumentNullException("con"); + throw new ArgumentNullException(nameof(con)); Contract.EndContractBlock(); RuntimeConstructorInfo rtConstructor = con as RuntimeConstructorInfo; if (rtConstructor == null) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "con"); + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), nameof(con)); RuntimeType declaringType = rtConstructor.GetRuntimeType(); int token; @@ -176,7 +174,7 @@ namespace System.Reflection.Emit public override void Emit(OpCode opcode, Type type) { if (type == null) - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); Contract.EndContractBlock(); RuntimeType rtType = type as RuntimeType; @@ -193,12 +191,12 @@ namespace System.Reflection.Emit public override void Emit(OpCode opcode, FieldInfo field) { if (field == null) - throw new ArgumentNullException("field"); + throw new ArgumentNullException(nameof(field)); Contract.EndContractBlock(); RuntimeFieldInfo runtimeField = field as RuntimeFieldInfo; if (runtimeField == null) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeFieldInfo"), "field"); + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeFieldInfo"), nameof(field)); int token; if (field.DeclaringType == null) @@ -214,7 +212,7 @@ namespace System.Reflection.Emit public override void Emit(OpCode opcode, String str) { if (str == null) - throw new ArgumentNullException("str"); + throw new ArgumentNullException(nameof(str)); Contract.EndContractBlock(); int tempVal = GetTokenForString(str); @@ -228,7 +226,6 @@ namespace System.Reflection.Emit // Signature related calls (vararg, calli) // // - [System.Security.SecuritySafeCritical] // overrides SC public override void EmitCalli(OpCode opcode, CallingConventions callingConvention, Type returnType, @@ -307,20 +304,19 @@ namespace System.Reflection.Emit PutInteger4(token); } - [System.Security.SecuritySafeCritical] // auto-generated public override void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[] optionalParameterTypes) { if (methodInfo == null) - throw new ArgumentNullException("methodInfo"); + throw new ArgumentNullException(nameof(methodInfo)); if (!(opcode.Equals(OpCodes.Call) || opcode.Equals(OpCodes.Callvirt) || opcode.Equals(OpCodes.Newobj))) - throw new ArgumentException(Environment.GetResourceString("Argument_NotMethodCallOpcode"), "opcode"); + throw new ArgumentException(Environment.GetResourceString("Argument_NotMethodCallOpcode"), nameof(opcode)); if (methodInfo.ContainsGenericParameters) - throw new ArgumentException(Environment.GetResourceString("Argument_GenericsInvalid"), "methodInfo"); + throw new ArgumentException(Environment.GetResourceString("Argument_GenericsInvalid"), nameof(methodInfo)); if (methodInfo.DeclaringType != null && methodInfo.DeclaringType.ContainsGenericParameters) - throw new ArgumentException(Environment.GetResourceString("Argument_GenericsInvalid"), "methodInfo"); + throw new ArgumentException(Environment.GetResourceString("Argument_GenericsInvalid"), nameof(methodInfo)); Contract.EndContractBlock(); int tk; @@ -351,7 +347,7 @@ namespace System.Reflection.Emit public override void Emit(OpCode opcode, SignatureHelper signature) { if (signature == null) - throw new ArgumentNullException("signature"); + throw new ArgumentNullException(nameof(signature)); Contract.EndContractBlock(); int stackchange = 0; @@ -365,7 +361,7 @@ namespace System.Reflection.Emit // SignatureHelper. if (opcode.StackBehaviourPop == StackBehaviour.Varpop) { - Contract.Assert(opcode.Equals(OpCodes.Calli), + Debug.Assert(opcode.Equals(OpCodes.Calli), "Unexpected opcode encountered for StackBehaviour VarPop."); // Pop the arguments.. stackchange -= signature.ArgumentCount; @@ -421,7 +417,7 @@ namespace System.Reflection.Emit { // execute this branch if previous clause is Catch or Fault if (exceptionType == null) - throw new ArgumentNullException("exceptionType"); + throw new ArgumentNullException(nameof(exceptionType)); if (rtType == null) throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType")); @@ -482,7 +478,6 @@ namespace System.Reflection.Emit throw new NotSupportedException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod")); } - [System.Security.SecurityCritical] // auto-generated private int GetMemberRefToken(MethodBase methodInfo, Type[] optionalParameterTypes) { Type[] parameterTypes; @@ -494,7 +489,7 @@ namespace System.Reflection.Emit DynamicMethod dm = methodInfo as DynamicMethod; if (rtMeth == null && dm == null) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "methodInfo"); + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), nameof(methodInfo)); ParameterInfo[] paramInfo = methodInfo.GetParametersNoCopy(); if (paramInfo != null && paramInfo.Length != 0) @@ -519,7 +514,6 @@ namespace System.Reflection.Emit return GetTokenForVarArgMethod(dm, sig); } - [System.Security.SecurityCritical] // auto-generated internal override SignatureHelper GetMemberRefSignature( CallingConventions call, Type returnType, @@ -704,9 +698,6 @@ namespace System.Reflection.Emit m_method.m_resolver = this; } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif internal DynamicResolver(DynamicILInfo dynamicILInfo) { m_stackSize = dynamicILInfo.MaxStackSize; @@ -774,7 +765,6 @@ namespace System.Reflection.Emit { internal RuntimeMethodHandleInternal m_methodHandle; - [System.Security.SecuritySafeCritical] // auto-generated ~DestroyScout() { if (m_methodHandle.IsNullHandle()) @@ -887,7 +877,6 @@ namespace System.Reflection.Emit return m_exceptionHeader; } - [System.Security.SecurityCritical] // auto-generated internal override unsafe void GetEHInfo(int excNumber, void* exc) { CORINFO_EH_CLAUSE* exception = (CORINFO_EH_CLAUSE*)exc; @@ -922,7 +911,6 @@ namespace System.Reflection.Emit } #endif // FEATURE_COMPRESSEDSTACK - [System.Security.SecurityCritical] internal override void ResolveToken(int token, out IntPtr typeHandle, out IntPtr methodHandle, out IntPtr fieldHandle) { typeHandle = new IntPtr(); @@ -1003,9 +991,6 @@ namespace System.Reflection.Emit } -#if FEATURE_CORECLR -[System.Security.SecurityCritical] // auto-generated -#endif [System.Runtime.InteropServices.ComVisible(true)] public class DynamicILInfo { @@ -1032,7 +1017,6 @@ namespace System.Reflection.Emit #endregion #region Internal Methods - [System.Security.SecurityCritical] // auto-generated internal void GetCallableMethod(RuntimeModule module, DynamicMethod dm) { dm.m_methodHandle = ModuleHandle.GetDynamicMethod(dm, @@ -1064,15 +1048,14 @@ namespace System.Reflection.Emit m_maxStackSize = maxStackSize; } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] public unsafe void SetCode(byte* code, int codeSize, int maxStackSize) { if (codeSize < 0) - throw new ArgumentOutOfRangeException("codeSize", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); + throw new ArgumentOutOfRangeException(nameof(codeSize), Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); if (codeSize > 0 && code == null) - throw new ArgumentNullException("code"); + throw new ArgumentNullException(nameof(code)); Contract.EndContractBlock(); m_code = new byte[codeSize]; @@ -1090,15 +1073,14 @@ namespace System.Reflection.Emit m_exceptions = (exceptions != null) ? (byte[])exceptions.Clone() : EmptyArray.Value; } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] public unsafe void SetExceptions(byte* exceptions, int exceptionsSize) { if (exceptionsSize < 0) - throw new ArgumentOutOfRangeException("exceptionsSize", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); + throw new ArgumentOutOfRangeException(nameof(exceptionsSize), Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); if (exceptionsSize > 0 && exceptions == null) - throw new ArgumentNullException("exceptions"); + throw new ArgumentNullException(nameof(exceptions)); Contract.EndContractBlock(); m_exceptions = new byte[exceptionsSize]; @@ -1115,15 +1097,14 @@ namespace System.Reflection.Emit m_localSignature = (localSignature != null) ? (byte[])localSignature.Clone() : EmptyArray.Value; } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] public unsafe void SetLocalSignature(byte* localSignature, int signatureSize) { if (signatureSize < 0) - throw new ArgumentOutOfRangeException("signatureSize", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); + throw new ArgumentOutOfRangeException(nameof(signatureSize), Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); if (signatureSize > 0 && localSignature == null) - throw new ArgumentNullException("localSignature"); + throw new ArgumentNullException(nameof(localSignature)); Contract.EndContractBlock(); m_localSignature = new byte[signatureSize]; @@ -1136,7 +1117,6 @@ namespace System.Reflection.Emit #endregion #region Public Scope Methods - [System.Security.SecuritySafeCritical] // auto-generated public int GetTokenFor(RuntimeMethodHandle method) { return DynamicScope.GetTokenFor(method); @@ -1222,7 +1202,6 @@ namespace System.Reflection.Emit #endregion #region Public Methods - [System.Security.SecuritySafeCritical] // auto-generated public int GetTokenFor(RuntimeMethodHandle method) { IRuntimeMethodInfo methodReal = method.GetMethodInfo(); diff --git a/src/mscorlib/src/System/Reflection/Emit/DynamicMethod.cs b/src/mscorlib/src/System/Reflection/Emit/DynamicMethod.cs index 6f6b436..1b8c97d 100644 --- a/src/mscorlib/src/System/Reflection/Emit/DynamicMethod.cs +++ b/src/mscorlib/src/System/Reflection/Emit/DynamicMethod.cs @@ -15,6 +15,7 @@ namespace System.Reflection.Emit using System.Threading; using System.Runtime.CompilerServices; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; @@ -25,9 +26,6 @@ namespace System.Reflection.Emit internal IRuntimeMethodInfo m_methodHandle; private RuntimeType m_returnType; private DynamicILGenerator m_ilGenerator; - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif private DynamicILInfo m_DynamicILInfo; private bool m_fInitLocals; private RuntimeModule m_module; @@ -72,7 +70,6 @@ namespace System.Reflection.Emit private DynamicMethod() { } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public DynamicMethod(string name, Type returnType, @@ -92,7 +89,6 @@ namespace System.Reflection.Emit ref stackMark); // transparentMethod } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public DynamicMethod(string name, Type returnType, @@ -113,11 +109,6 @@ namespace System.Reflection.Emit ref stackMark); // transparentMethod } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public DynamicMethod(string name, Type returnType, @@ -137,11 +128,6 @@ namespace System.Reflection.Emit ref stackMark); // transparentMethod } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public DynamicMethod(string name, Type returnType, @@ -162,11 +148,6 @@ namespace System.Reflection.Emit ref stackMark); // transparentMethod } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public DynamicMethod(string name, MethodAttributes attributes, @@ -189,11 +170,6 @@ namespace System.Reflection.Emit ref stackMark); // transparentMethod } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public DynamicMethod(string name, Type returnType, @@ -213,11 +189,6 @@ namespace System.Reflection.Emit ref stackMark); // transparentMethod } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public DynamicMethod(string name, Type returnType, @@ -238,11 +209,6 @@ namespace System.Reflection.Emit ref stackMark); // transparentMethod } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public DynamicMethod(string name, MethodAttributes attributes, @@ -286,7 +252,6 @@ namespace System.Reflection.Emit // We create a transparent assembly to host DynamicMethods. Since the assembly does not have any // non-public fields (or any fields at all), it is a safe anonymous assembly to host DynamicMethods - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable private static RuntimeModule GetDynamicMethodsModule() { @@ -302,21 +267,6 @@ namespace System.Reflection.Emit CustomAttributeBuilder transparencyAttribute = new CustomAttributeBuilder(transparencyCtor, EmptyArray.Value); List assemblyAttributes = new List(); assemblyAttributes.Add(transparencyAttribute); -#if !FEATURE_CORECLR - // On the desktop, we need to use the security rule set level 1 for anonymously hosted - // dynamic methods. In level 2, transparency rules are strictly enforced, which leads to - // errors when a fully trusted application causes a dynamic method to be generated that tries - // to call a method with a LinkDemand or a SecurityCritical method. To retain compatibility - // with the v2.0 and v3.x frameworks, these calls should be allowed. - // - // If this rule set was not explicitly called out, then the anonymously hosted dynamic methods - // assembly would inherit the rule set from the creating assembly - which would cause it to - // be level 2 because mscorlib.dll is using the level 2 rules. - ConstructorInfo securityRulesCtor = typeof(SecurityRulesAttribute).GetConstructor(new Type[] { typeof(SecurityRuleSet) }); - CustomAttributeBuilder securityRulesAttribute = - new CustomAttributeBuilder(securityRulesCtor, new object[] { SecurityRuleSet.Level1 }); - assemblyAttributes.Add(securityRulesAttribute); -#endif // !FEATURE_CORECLR AssemblyName assemblyName = new AssemblyName("Anonymously Hosted DynamicMethods Assembly"); StackCrawlMark stackMark = StackCrawlMark.LookForMe; @@ -338,7 +288,6 @@ namespace System.Reflection.Emit return s_anonymouslyHostedDynamicMethodsModule; } - [System.Security.SecurityCritical] // auto-generated private unsafe void Init(String name, MethodAttributes attributes, CallingConventions callingConvention, @@ -374,7 +323,7 @@ namespace System.Reflection.Emit if (transparentMethod) { - Contract.Assert(owner == null && m == null, "owner and m cannot be set for transparent methods"); + Debug.Assert(owner == null && m == null, "owner and m cannot be set for transparent methods"); m_module = GetDynamicMethodsModule(); if (skipVisibility) { @@ -387,9 +336,9 @@ namespace System.Reflection.Emit } else { - Contract.Assert(m != null || owner != null, "PerformSecurityCheck should ensure that either m or owner is set"); - Contract.Assert(m == null || !m.Equals(s_anonymouslyHostedDynamicMethodsModule), "The user cannot explicitly use this assembly"); - Contract.Assert(m == null || owner == null, "m and owner cannot both be set"); + Debug.Assert(m != null || owner != null, "PerformSecurityCheck should ensure that either m or owner is set"); + Debug.Assert(m == null || !m.Equals(s_anonymouslyHostedDynamicMethodsModule), "The user cannot explicitly use this assembly"); + Debug.Assert(m == null || owner == null, "m and owner cannot both be set"); if (m != null) m_module = m.ModuleHandle.GetRuntimeModule(); // this returns the underlying module for all RuntimeModule and ModuleBuilder objects. @@ -419,7 +368,7 @@ namespace System.Reflection.Emit m_methodHandle = null; if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); #if FEATURE_APPX if (AppDomain.ProfileAPICheck) @@ -435,101 +384,23 @@ namespace System.Reflection.Emit m_dynMethod = new RTDynamicMethod(this, name, attributes, callingConvention); } - [System.Security.SecurityCritical] // auto-generated private void PerformSecurityCheck(Module m, ref StackCrawlMark stackMark, bool skipVisibility) { if (m == null) - throw new ArgumentNullException("m"); + throw new ArgumentNullException(nameof(m)); Contract.EndContractBlock(); -#if !FEATURE_CORECLR - - RuntimeModule rtModule; - ModuleBuilder mb = m as ModuleBuilder; - if (mb != null) - rtModule = mb.InternalModule; - else - rtModule = m as RuntimeModule; - - if (rtModule == null) - { - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeModule"), "m"); - } - - // The user cannot explicitly use this assembly - if (rtModule == s_anonymouslyHostedDynamicMethodsModule) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidValue"), "m"); - - // ask for member access if skip visibility - if (skipVisibility) - new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand(); - -#if !FEATURE_CORECLR - // ask for control evidence if outside of the caller assembly - RuntimeType callingType = RuntimeMethodHandle.GetCallerType(ref stackMark); - m_creatorAssembly = callingType.GetRuntimeAssembly(); - if (m.Assembly != m_creatorAssembly) - { - // Demand the permissions of the assembly where the DynamicMethod will live - CodeAccessSecurityEngine.ReflectionTargetDemandHelper(PermissionType.SecurityControlEvidence, - m.Assembly.PermissionSet); - } -#else //FEATURE_CORECLR -#pragma warning disable 618 - new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand(); -#pragma warning restore 618 -#endif //FEATURE_CORECLR -#endif //!FEATURE_CORECLR } - [System.Security.SecurityCritical] // auto-generated private void PerformSecurityCheck(Type owner, ref StackCrawlMark stackMark, bool skipVisibility) { if (owner == null) - throw new ArgumentNullException("owner"); -#if !FEATURE_CORECLR - - RuntimeType rtOwner = owner as RuntimeType; - if (rtOwner == null) - rtOwner = owner.UnderlyingSystemType as RuntimeType; - - if (rtOwner == null) - throw new ArgumentNullException("owner", Environment.GetResourceString("Argument_MustBeRuntimeType")); - - // get the type the call is coming from - RuntimeType callingType = RuntimeMethodHandle.GetCallerType(ref stackMark); - - // ask for member access if skip visibility - if (skipVisibility) - new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand(); - else - { - // if the call is not coming from the same class ask for member access - if (callingType != rtOwner) - new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand(); - } -#if !FEATURE_CORECLR - m_creatorAssembly = callingType.GetRuntimeAssembly(); - - // ask for control evidence if outside of the caller module - if (rtOwner.Assembly != m_creatorAssembly) - { - // Demand the permissions of the assembly where the DynamicMethod will live - CodeAccessSecurityEngine.ReflectionTargetDemandHelper(PermissionType.SecurityControlEvidence, - owner.Assembly.PermissionSet); - } -#else //FEATURE_CORECLR -#pragma warning disable 618 - new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand(); -#pragma warning restore 618 -#endif //FEATURE_CORECLR -#endif //!FEATURE_CORECLR + throw new ArgumentNullException(nameof(owner)); } // // Delegate and method creation // - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public sealed override Delegate CreateDelegate(Type delegateType) { if (m_restrictedSkipVisibility) @@ -545,7 +416,6 @@ namespace System.Reflection.Emit return d; } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public sealed override Delegate CreateDelegate(Type delegateType, Object target) { if (m_restrictedSkipVisibility) @@ -578,7 +448,6 @@ namespace System.Reflection.Emit #endif // This is guaranteed to return a valid handle - [System.Security.SecurityCritical] // auto-generated internal unsafe RuntimeMethodHandle GetMethodDescriptor() { if (m_methodHandle == null) { lock (this) { @@ -636,83 +505,19 @@ namespace System.Reflection.Emit public override bool IsSecurityCritical { - [SecuritySafeCritical] - get - { - if (m_methodHandle != null) - { - return RuntimeMethodHandle.IsSecurityCritical(m_methodHandle); - } - else if (m_typeOwner != null) - { - RuntimeAssembly assembly = m_typeOwner.Assembly as RuntimeAssembly; - Contract.Assert(assembly != null); - - return assembly.IsAllSecurityCritical(); - } - else - { - RuntimeAssembly assembly = m_module.Assembly as RuntimeAssembly; - Contract.Assert(assembly != null); - - return assembly.IsAllSecurityCritical(); - } - } + get { return true; } } public override bool IsSecuritySafeCritical { - [SecuritySafeCritical] - get - { - if (m_methodHandle != null) - { - return RuntimeMethodHandle.IsSecuritySafeCritical(m_methodHandle); - } - else if (m_typeOwner != null) - { - RuntimeAssembly assembly = m_typeOwner.Assembly as RuntimeAssembly; - Contract.Assert(assembly != null); - - return assembly.IsAllPublicAreaSecuritySafeCritical(); - } - else - { - RuntimeAssembly assembly = m_module.Assembly as RuntimeAssembly; - Contract.Assert(assembly != null); - - return assembly.IsAllSecuritySafeCritical(); - } - } + get { return false; } } public override bool IsSecurityTransparent { - [SecuritySafeCritical] - get - { - if (m_methodHandle != null) - { - return RuntimeMethodHandle.IsSecurityTransparent(m_methodHandle); - } - else if (m_typeOwner != null) - { - RuntimeAssembly assembly = m_typeOwner.Assembly as RuntimeAssembly; - Contract.Assert(assembly != null); - - return !assembly.IsAllSecurityCritical(); - } - else - { - RuntimeAssembly assembly = m_module.Assembly as RuntimeAssembly; - Contract.Assert(assembly != null); - - return !assembly.IsAllSecurityCritical(); - } - } + get { return false; } } - [System.Security.SecuritySafeCritical] // auto-generated public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) { if ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs) throw new NotSupportedException(Environment.GetResourceString("NotSupported_CallToVarArg")); @@ -789,7 +594,6 @@ namespace System.Reflection.Emit return null; } - [System.Security.SecuritySafeCritical] // auto-generated public DynamicILInfo GetDynamicILInfo() { #pragma warning disable 618 @@ -802,7 +606,6 @@ namespace System.Reflection.Emit return GetDynamicILInfo(new DynamicScope()); } - [System.Security.SecurityCritical] // auto-generated internal DynamicILInfo GetDynamicILInfo(DynamicScope scope) { if (m_DynamicILInfo == null) @@ -819,7 +622,6 @@ namespace System.Reflection.Emit return GetILGenerator(64); } - [System.Security.SecuritySafeCritical] // auto-generated public ILGenerator GetILGenerator(int streamSize) { if (m_ilGenerator == null) @@ -935,7 +737,7 @@ namespace System.Reflection.Emit public override Object[] GetCustomAttributes(Type attributeType, bool inherit) { if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); if (attributeType.IsAssignableFrom(typeof(MethodImplAttribute))) @@ -951,7 +753,7 @@ namespace System.Reflection.Emit public override bool IsDefined(Type attributeType, bool inherit) { if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); if (attributeType.IsAssignableFrom(typeof(MethodImplAttribute))) diff --git a/src/mscorlib/src/System/Reflection/Emit/EnumBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/EnumBuilder.cs index f8e3ab2..82dc282 100644 --- a/src/mscorlib/src/System/Reflection/Emit/EnumBuilder.cs +++ b/src/mscorlib/src/System/Reflection/Emit/EnumBuilder.cs @@ -23,7 +23,6 @@ namespace System.Reflection.Emit { using System.Security.Permissions; - [HostProtection(MayLeakOnAbort = true)] [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_EnumBuilder))] [System.Runtime.InteropServices.ComVisible(true)] @@ -313,9 +312,6 @@ namespace System.Reflection.Emit { // Use this function if client decides to form the custom attribute blob themselves -#if FEATURE_CORECLR -[System.Security.SecurityCritical] // auto-generated -#endif [System.Runtime.InteropServices.ComVisible(true)] public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) { @@ -398,7 +394,6 @@ namespace System.Reflection.Emit { // Constructs a EnumBuilder. // EnumBuilder can only be a top-level (not nested) enum type. - [System.Security.SecurityCritical] // auto-generated internal EnumBuilder( String name, // name of type Type underlyingType, // underlying type for an Enum @@ -407,36 +402,13 @@ namespace System.Reflection.Emit { { // Client should not set any bits other than the visibility bits. if ((visibility & ~TypeAttributes.VisibilityMask) != 0) - throw new ArgumentException(Environment.GetResourceString("Argument_ShouldOnlySetVisibilityFlags"), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_ShouldOnlySetVisibilityFlags"), nameof(name)); m_typeBuilder = new TypeBuilder(name, visibility | TypeAttributes.Sealed, typeof(System.Enum), null, module, PackingSize.Unspecified, TypeBuilder.UnspecifiedTypeSize, null); // Define the underlying field for the enum. It will be a non-static, private field with special name bit set. m_underlyingField = m_typeBuilder.DefineField("value__", underlyingType, FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName); } -#if !FEATURE_CORECLR - void _EnumBuilder.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _EnumBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _EnumBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - void _EnumBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif - - /***************************************************** * * private data members diff --git a/src/mscorlib/src/System/Reflection/Emit/EventBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/EventBuilder.cs index 42a5252..449b208 100644 --- a/src/mscorlib/src/System/Reflection/Emit/EventBuilder.cs +++ b/src/mscorlib/src/System/Reflection/Emit/EventBuilder.cs @@ -24,7 +24,6 @@ namespace System.Reflection.Emit { // A EventBuilder is always associated with a TypeBuilder. The TypeBuilder.DefineEvent // method will return a new EventBuilder to a client. // - [HostProtection(MayLeakOnAbort = true)] [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_EventBuilder))] [System.Runtime.InteropServices.ComVisible(true)] @@ -58,12 +57,11 @@ namespace System.Reflection.Emit { return m_evToken; } - [System.Security.SecurityCritical] // auto-generated private void SetMethodSemantics(MethodBuilder mdBuilder, MethodSemanticsAttributes semantics) { if (mdBuilder == null) { - throw new ArgumentNullException("mdBuilder"); + throw new ArgumentNullException(nameof(mdBuilder)); } Contract.EndContractBlock(); @@ -75,25 +73,21 @@ namespace System.Reflection.Emit { mdBuilder.GetToken().Token); } - [System.Security.SecuritySafeCritical] // auto-generated public void SetAddOnMethod(MethodBuilder mdBuilder) { SetMethodSemantics(mdBuilder, MethodSemanticsAttributes.AddOn); } - [System.Security.SecuritySafeCritical] // auto-generated public void SetRemoveOnMethod(MethodBuilder mdBuilder) { SetMethodSemantics(mdBuilder, MethodSemanticsAttributes.RemoveOn); } - [System.Security.SecuritySafeCritical] // auto-generated public void SetRaiseMethod(MethodBuilder mdBuilder) { SetMethodSemantics(mdBuilder, MethodSemanticsAttributes.Fire); } - [System.Security.SecuritySafeCritical] // auto-generated public void AddOtherMethod(MethodBuilder mdBuilder) { SetMethodSemantics(mdBuilder, MethodSemanticsAttributes.Other); @@ -101,18 +95,13 @@ namespace System.Reflection.Emit { // Use this function if client decides to form the custom attribute blob themselves -#if FEATURE_CORECLR -[System.Security.SecurityCritical] // auto-generated -#else -[System.Security.SecuritySafeCritical] -#endif [System.Runtime.InteropServices.ComVisible(true)] public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) { if (con == null) - throw new ArgumentNullException("con"); + throw new ArgumentNullException(nameof(con)); if (binaryAttribute == null) - throw new ArgumentNullException("binaryAttribute"); + throw new ArgumentNullException(nameof(binaryAttribute)); Contract.EndContractBlock(); m_type.ThrowIfCreated(); @@ -125,41 +114,17 @@ namespace System.Reflection.Emit { } // Use this function if client wishes to build CustomAttribute using CustomAttributeBuilder - [System.Security.SecuritySafeCritical] // auto-generated public void SetCustomAttribute(CustomAttributeBuilder customBuilder) { if (customBuilder == null) { - throw new ArgumentNullException("customBuilder"); + throw new ArgumentNullException(nameof(customBuilder)); } Contract.EndContractBlock(); m_type.ThrowIfCreated(); customBuilder.CreateCustomAttribute(m_module, m_evToken.Token); } -#if !FEATURE_CORECLR - void _EventBuilder.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _EventBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _EventBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - void _EventBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif - - // These are package private so that TypeBuilder can access them. private String m_name; // The name of the event private EventToken m_evToken; // The token of this event @@ -167,8 +132,4 @@ namespace System.Reflection.Emit { private EventAttributes m_attributes; private TypeBuilder m_type; } - - - - } diff --git a/src/mscorlib/src/System/Reflection/Emit/FieldBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/FieldBuilder.cs index 0f2de5b..595d60a 100644 --- a/src/mscorlib/src/System/Reflection/Emit/FieldBuilder.cs +++ b/src/mscorlib/src/System/Reflection/Emit/FieldBuilder.cs @@ -13,7 +13,6 @@ namespace System.Reflection.Emit using System.Security.Permissions; using System.Diagnostics.Contracts; - [HostProtection(MayLeakOnAbort = true)] [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_FieldBuilder))] [System.Runtime.InteropServices.ComVisible(true)] @@ -29,21 +28,20 @@ namespace System.Reflection.Emit #endregion #region Constructor - [System.Security.SecurityCritical] // auto-generated internal FieldBuilder(TypeBuilder typeBuilder, String fieldName, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes) { if (fieldName == null) - throw new ArgumentNullException("fieldName"); + throw new ArgumentNullException(nameof(fieldName)); if (fieldName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "fieldName"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(fieldName)); if (fieldName[0] == '\0') - throw new ArgumentException(Environment.GetResourceString("Argument_IllegalName"), "fieldName"); + throw new ArgumentException(Environment.GetResourceString("Argument_IllegalName"), nameof(fieldName)); if (type == null) - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); if (type == typeof(void)) throw new ArgumentException(Environment.GetResourceString("Argument_BadFieldType")); @@ -69,7 +67,6 @@ namespace System.Reflection.Emit #endregion #region Internal Members - [System.Security.SecurityCritical] // auto-generated internal void SetData(byte[] data, int size) { ModuleBuilder.SetFieldRVAContent(m_typeBuilder.GetModuleBuilder().GetNativeHandle(), m_tkField.Token, data, size); @@ -181,11 +178,6 @@ namespace System.Reflection.Emit return m_tkField; } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif public void SetOffset(int iOffset) { m_typeBuilder.ThrowIfCreated(); @@ -193,12 +185,11 @@ namespace System.Reflection.Emit TypeBuilder.SetFieldLayoutOffset(m_typeBuilder.GetModuleBuilder().GetNativeHandle(), GetToken().Token, iOffset); } - [System.Security.SecuritySafeCritical] // auto-generated [Obsolete("An alternate API is available: Emit the MarshalAs custom attribute instead. http://go.microsoft.com/fwlink/?linkid=14202")] public void SetMarshal(UnmanagedMarshal unmanagedMarshal) { if (unmanagedMarshal == null) - throw new ArgumentNullException("unmanagedMarshal"); + throw new ArgumentNullException(nameof(unmanagedMarshal)); Contract.EndContractBlock(); m_typeBuilder.ThrowIfCreated(); @@ -208,7 +199,6 @@ namespace System.Reflection.Emit TypeBuilder.SetFieldMarshal(m_typeBuilder.GetModuleBuilder().GetNativeHandle(), GetToken().Token, ubMarshal, ubMarshal.Length); } - [System.Security.SecuritySafeCritical] // auto-generated public void SetConstant(Object defaultValue) { m_typeBuilder.ThrowIfCreated(); @@ -217,19 +207,14 @@ namespace System.Reflection.Emit } -#if FEATURE_CORECLR -[System.Security.SecurityCritical] // auto-generated -#else -[System.Security.SecuritySafeCritical] -#endif [System.Runtime.InteropServices.ComVisible(true)] public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) { if (con == null) - throw new ArgumentNullException("con"); + throw new ArgumentNullException(nameof(con)); if (binaryAttribute == null) - throw new ArgumentNullException("binaryAttribute"); + throw new ArgumentNullException(nameof(binaryAttribute)); Contract.EndContractBlock(); ModuleBuilder module = m_typeBuilder.Module as ModuleBuilder; @@ -240,11 +225,10 @@ namespace System.Reflection.Emit m_tkField.Token, module.GetConstructorToken(con).Token, binaryAttribute, false, false); } - [System.Security.SecuritySafeCritical] // auto-generated public void SetCustomAttribute(CustomAttributeBuilder customBuilder) { if (customBuilder == null) - throw new ArgumentNullException("customBuilder"); + throw new ArgumentNullException(nameof(customBuilder)); Contract.EndContractBlock(); m_typeBuilder.ThrowIfCreated(); @@ -255,27 +239,5 @@ namespace System.Reflection.Emit } #endregion - -#if !FEATURE_CORECLR - void _FieldBuilder.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _FieldBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _FieldBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - void _FieldBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif } } diff --git a/src/mscorlib/src/System/Reflection/Emit/FlowControl.cs b/src/mscorlib/src/System/Reflection/Emit/FlowControl.cs index 5bfe5bb..31bb564 100644 --- a/src/mscorlib/src/System/Reflection/Emit/FlowControl.cs +++ b/src/mscorlib/src/System/Reflection/Emit/FlowControl.cs @@ -26,11 +26,8 @@ public enum FlowControl Cond_Branch = 3, Meta = 4, Next = 5, -#if !FEATURE_CORECLR - /// [Obsolete("This API has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")] Phi = 6, -#endif Return = 7, Throw = 8, } diff --git a/src/mscorlib/src/System/Reflection/Emit/GenericTypeParameterBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/GenericTypeParameterBuilder.cs index bcf70db..6987ea1 100644 --- a/src/mscorlib/src/System/Reflection/Emit/GenericTypeParameterBuilder.cs +++ b/src/mscorlib/src/System/Reflection/Emit/GenericTypeParameterBuilder.cs @@ -212,9 +212,6 @@ namespace System.Reflection.Emit #endregion #region Public Members - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) { m_type.SetGenParamCustomAttribute(con, binaryAttribute); diff --git a/src/mscorlib/src/System/Reflection/Emit/ILGenerator.cs b/src/mscorlib/src/System/Reflection/Emit/ILGenerator.cs index 15dece9..ed0763b 100644 --- a/src/mscorlib/src/System/Reflection/Emit/ILGenerator.cs +++ b/src/mscorlib/src/System/Reflection/Emit/ILGenerator.cs @@ -7,12 +7,12 @@ namespace System.Reflection.Emit { using System; - using TextWriter = System.IO.TextWriter; using System.Diagnostics.SymbolStore; using System.Runtime.InteropServices; using System.Reflection; using System.Security.Permissions; using System.Globalization; + using System.Diagnostics; using System.Diagnostics.Contracts; [ClassInterface(ClassInterfaceType.None)] @@ -210,20 +210,17 @@ namespace System.Reflection.Emit } } - [System.Security.SecurityCritical] // auto-generated private int GetMethodToken(MethodBase method, Type[] optionalParameterTypes, bool useMethodDef) { return ((ModuleBuilder)m_methodBuilder.Module).GetMethodTokenInternal(method, optionalParameterTypes, useMethodDef); } - [System.Security.SecurityCritical] // auto-generated internal virtual SignatureHelper GetMemberRefSignature(CallingConventions call, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes) { return GetMemberRefSignature(call, returnType, parameterTypes, optionalParameterTypes, 0); } - [System.Security.SecurityCritical] // auto-generated private SignatureHelper GetMemberRefSignature(CallingConventions call, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes, int cGenericParameters) { @@ -414,7 +411,7 @@ namespace System.Reflection.Emit { if (m_RelocFixupCount == 0) { - Contract.Assert(m_RelocFixupList == null); + Debug.Assert(m_RelocFixupList == null); return null; } @@ -472,11 +469,10 @@ namespace System.Reflection.Emit PutInteger4(arg); } - [System.Security.SecuritySafeCritical] // auto-generated public virtual void Emit(OpCode opcode, MethodInfo meth) { if (meth == null) - throw new ArgumentNullException("meth"); + throw new ArgumentNullException(nameof(meth)); Contract.EndContractBlock(); if (opcode.Equals(OpCodes.Call) || opcode.Equals(OpCodes.Callvirt) || opcode.Equals(OpCodes.Newobj)) @@ -504,7 +500,6 @@ namespace System.Reflection.Emit } - [System.Security.SecuritySafeCritical] // auto-generated public virtual void EmitCalli(OpCode opcode, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes) { @@ -593,14 +588,13 @@ namespace System.Reflection.Emit PutInteger4(modBuilder.GetSignatureToken(sig).Token); } - [System.Security.SecuritySafeCritical] // auto-generated public virtual void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[] optionalParameterTypes) { if (methodInfo == null) - throw new ArgumentNullException("methodInfo"); + throw new ArgumentNullException(nameof(methodInfo)); if (!(opcode.Equals(OpCodes.Call) || opcode.Equals(OpCodes.Callvirt) || opcode.Equals(OpCodes.Newobj))) - throw new ArgumentException(Environment.GetResourceString("Argument_NotMethodCallOpcode"), "opcode"); + throw new ArgumentException(Environment.GetResourceString("Argument_NotMethodCallOpcode"), nameof(opcode)); Contract.EndContractBlock(); @@ -634,7 +628,7 @@ namespace System.Reflection.Emit public virtual void Emit(OpCode opcode, SignatureHelper signature) { if (signature == null) - throw new ArgumentNullException("signature"); + throw new ArgumentNullException(nameof(signature)); Contract.EndContractBlock(); int stackchange = 0; @@ -653,7 +647,7 @@ namespace System.Reflection.Emit // SignatureHelper. if (opcode.StackBehaviourPop == StackBehaviour.Varpop) { - Contract.Assert(opcode.Equals(OpCodes.Calli), + Debug.Assert(opcode.Equals(OpCodes.Calli), "Unexpected opcode encountered for StackBehaviour VarPop."); // Pop the arguments.. stackchange -= signature.ArgumentCount; @@ -666,12 +660,11 @@ namespace System.Reflection.Emit PutInteger4(tempVal); } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public virtual void Emit(OpCode opcode, ConstructorInfo con) { if (con == null) - throw new ArgumentNullException("con"); + throw new ArgumentNullException(nameof(con)); Contract.EndContractBlock(); int stackchange = 0; @@ -687,7 +680,7 @@ namespace System.Reflection.Emit if (opcode.StackBehaviourPush == StackBehaviour.Varpush) { // Instruction must be one of call or callvirt. - Contract.Assert(opcode.Equals(OpCodes.Call) || + Debug.Assert(opcode.Equals(OpCodes.Call) || opcode.Equals(OpCodes.Callvirt), "Unexpected opcode encountered for StackBehaviour of VarPush."); stackchange++; @@ -695,7 +688,7 @@ namespace System.Reflection.Emit if (opcode.StackBehaviourPop == StackBehaviour.Varpop) { // Instruction must be one of call, callvirt or newobj. - Contract.Assert(opcode.Equals(OpCodes.Call) || + Debug.Assert(opcode.Equals(OpCodes.Call) || opcode.Equals(OpCodes.Callvirt) || opcode.Equals(OpCodes.Newobj), "Unexpected opcode encountered for StackBehaviour of VarPop."); @@ -710,7 +703,6 @@ namespace System.Reflection.Emit PutInteger4(tk); } - [System.Security.SecuritySafeCritical] // auto-generated public virtual void Emit(OpCode opcode, Type cls) { // Puts opcode onto the stream and then the metadata token represented @@ -750,7 +742,6 @@ namespace System.Reflection.Emit m_ILStream[m_length++] = (byte) (arg>>56); } - [System.Security.SecuritySafeCritical] // auto-generated unsafe public virtual void Emit(OpCode opcode, float arg) { EnsureCapacity(7); InternalEmit(opcode); @@ -761,7 +752,6 @@ namespace System.Reflection.Emit m_ILStream[m_length++] = (byte) (tempVal>>24); } - [System.Security.SecuritySafeCritical] // auto-generated unsafe public virtual void Emit(OpCode opcode, double arg) { EnsureCapacity(11); InternalEmit(opcode); @@ -805,7 +795,7 @@ namespace System.Reflection.Emit public virtual void Emit(OpCode opcode, Label[] labels) { if (labels == null) - throw new ArgumentNullException("labels"); + throw new ArgumentNullException(nameof(labels)); Contract.EndContractBlock(); // Emitting a switch table @@ -854,13 +844,13 @@ namespace System.Reflection.Emit if (local == null) { - throw new ArgumentNullException("local"); + throw new ArgumentNullException(nameof(local)); } Contract.EndContractBlock(); int tempVal = local.GetLocalIndex(); if (local.GetMethodBuilder() != m_methodBuilder) { - throw new ArgumentException(Environment.GetResourceString("Argument_UnmatchedMethodForLocal"), "local"); + throw new ArgumentException(Environment.GetResourceString("Argument_UnmatchedMethodForLocal"), nameof(local)); } // If the instruction is a ldloc, ldloca a stloc, morph it to the optimal form. if (opcode.Equals(OpCodes.Ldloc)) @@ -1020,7 +1010,7 @@ namespace System.Reflection.Emit public virtual void BeginExceptFilterBlock() { - // Begins a eception filter block. Emits a branch instruction to the end of the current exception block. + // Begins an exception filter block. Emits a branch instruction to the end of the current exception block. if (m_currExcStackCount == 0) throw new NotSupportedException(Environment.GetResourceString("Argument_NotInExceptionBlock")); @@ -1051,7 +1041,7 @@ namespace System.Reflection.Emit } else { // execute this branch if previous clause is Catch or Fault if (exceptionType==null) { - throw new ArgumentNullException("exceptionType"); + throw new ArgumentNullException(nameof(exceptionType)); } Label endLabel = current.GetEndLabel(); @@ -1153,7 +1143,7 @@ namespace System.Reflection.Emit // Emits the il to throw an exception if (excType==null) { - throw new ArgumentNullException("excType"); + throw new ArgumentNullException(nameof(excType)); } if (!excType.IsSubclassOf(typeof(Exception)) && excType!=typeof(Exception)) { @@ -1212,9 +1202,9 @@ namespace System.Reflection.Emit throw new ArgumentException(Environment.GetResourceString("NotSupported_OutputStreamUsingTypeBuilder")); } parameterTypes[0] = (Type)cls; - MethodInfo mi = typeof(TextWriter).GetMethod("WriteLine", parameterTypes); + MethodInfo mi = prop.ReturnType.GetMethod("WriteLine", parameterTypes); if (mi==null) { - throw new ArgumentException(Environment.GetResourceString("Argument_EmitWriteLineType"), "localBuilder"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmitWriteLineType"), nameof(localBuilder)); } Emit(OpCodes.Callvirt, mi); @@ -1231,7 +1221,7 @@ namespace System.Reflection.Emit if (fld == null) { - throw new ArgumentNullException("fld"); + throw new ArgumentNullException(nameof(fld)); } Contract.EndContractBlock(); @@ -1250,9 +1240,9 @@ namespace System.Reflection.Emit throw new NotSupportedException(Environment.GetResourceString("NotSupported_OutputStreamUsingTypeBuilder")); } parameterTypes[0] = (Type)cls; - MethodInfo mi = typeof(TextWriter).GetMethod("WriteLine", parameterTypes); + MethodInfo mi = prop.ReturnType.GetMethod("WriteLine", parameterTypes); if (mi==null) { - throw new ArgumentException(Environment.GetResourceString("Argument_EmitWriteLineType"), "fld"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmitWriteLineType"), nameof(fld)); } Emit(OpCodes.Callvirt, mi); } @@ -1283,7 +1273,7 @@ namespace System.Reflection.Emit } if (localType==null) { - throw new ArgumentNullException("localType"); + throw new ArgumentNullException(nameof(localType)); } if (methodBuilder.m_bIsBaked) { @@ -1304,10 +1294,10 @@ namespace System.Reflection.Emit // for the current active lexical scope. if (usingNamespace == null) - throw new ArgumentNullException("usingNamespace"); + throw new ArgumentNullException(nameof(usingNamespace)); if (usingNamespace.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "usingNamespace"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(usingNamespace)); Contract.EndContractBlock(); int index; @@ -1335,7 +1325,7 @@ namespace System.Reflection.Emit { if (startLine == 0 || startLine < 0 || endLine == 0 || endLine < 0) { - throw new ArgumentOutOfRangeException("startLine"); + throw new ArgumentOutOfRangeException(nameof(startLine)); } Contract.EndContractBlock(); m_LineNumberInfo.AddLineNumberInfo(document, m_length, startLine, startColumn, endLine, endColumn); @@ -1362,28 +1352,6 @@ namespace System.Reflection.Emit #endregion #endregion - -#if !FEATURE_CORECLR - void _ILGenerator.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _ILGenerator.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _ILGenerator.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - void _ILGenerator.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif } internal struct __FixupData @@ -1472,7 +1440,7 @@ namespace System.Reflection.Emit m_catchAddr[m_currentCatch] = -1; if (m_currentCatch > 0) { - Contract.Assert(m_catchEndAddr[m_currentCatch-1] == -1,"m_catchEndAddr[m_currentCatch-1] == -1"); + Debug.Assert(m_catchEndAddr[m_currentCatch-1] == -1,"m_catchEndAddr[m_currentCatch-1] == -1"); m_catchEndAddr[m_currentCatch-1] = catchorfilterAddr; } } @@ -1489,7 +1457,7 @@ namespace System.Reflection.Emit { if (m_type[m_currentCatch] != Filter) { - Contract.Assert(m_catchEndAddr[m_currentCatch-1] == -1,"m_catchEndAddr[m_currentCatch-1] == -1"); + Debug.Assert(m_catchEndAddr[m_currentCatch-1] == -1,"m_catchEndAddr[m_currentCatch-1] == -1"); m_catchEndAddr[m_currentCatch-1] = catchEndAddr; } } @@ -1531,9 +1499,9 @@ namespace System.Reflection.Emit } internal void Done(int endAddr) { - Contract.Assert(m_currentCatch > 0,"m_currentCatch > 0"); - Contract.Assert(m_catchAddr[m_currentCatch-1] > 0,"m_catchAddr[m_currentCatch-1] > 0"); - Contract.Assert(m_catchEndAddr[m_currentCatch-1] == -1,"m_catchEndAddr[m_currentCatch-1] == -1"); + Debug.Assert(m_currentCatch > 0,"m_currentCatch > 0"); + Debug.Assert(m_catchAddr[m_currentCatch-1] > 0,"m_catchAddr[m_currentCatch-1] > 0"); + Debug.Assert(m_catchEndAddr[m_currentCatch-1] == -1,"m_catchEndAddr[m_currentCatch-1] == -1"); m_catchEndAddr[m_currentCatch-1] = endAddr; m_currentState = State_Done; } @@ -1596,8 +1564,8 @@ namespace System.Reflection.Emit // not having a nesting relation. internal bool IsInner(__ExceptionInfo exc) { Contract.Requires(exc != null); - Contract.Assert(m_currentCatch > 0,"m_currentCatch > 0"); - Contract.Assert(exc.m_currentCatch > 0,"exc.m_currentCatch > 0"); + Debug.Assert(m_currentCatch > 0,"m_currentCatch > 0"); + Debug.Assert(exc.m_currentCatch > 0,"exc.m_currentCatch > 0"); int exclast = exc.m_currentCatch - 1; int last = m_currentCatch - 1; @@ -1606,7 +1574,7 @@ namespace System.Reflection.Emit return true; else if (exc.m_catchEndAddr[exclast] == m_catchEndAddr[last]) { - Contract.Assert(exc.GetEndAddress() != GetEndAddress(), + Debug.Assert(exc.GetEndAddress() != GetEndAddress(), "exc.GetEndAddress() != GetEndAddress()"); if (exc.GetEndAddress() > GetEndAddress()) return true; @@ -1762,9 +1730,6 @@ namespace System.Reflection.Emit } } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal void EmitScopeTree(ISymbolWriter symWriter) { int i; @@ -1821,7 +1786,7 @@ namespace System.Reflection.Emit // make sure that arrays are large enough to hold addition info i = FindDocument(document); - Contract.Assert(i < m_DocumentCount, "Bad document look up!"); + Debug.Assert(i < m_DocumentCount, "Bad document look up!"); m_Documents[i].AddLineNumberInfo(document, iOffset, iStartLine, iStartColumn, iEndLine, iEndColumn); } @@ -1874,9 +1839,6 @@ namespace System.Reflection.Emit } } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal void EmitLineNumberInfo(ISymbolWriter symWriter) { for (int i = 0; i < m_DocumentCount; i++) @@ -1912,7 +1874,7 @@ namespace System.Reflection.Emit int iEndLine, int iEndColumn) { - Contract.Assert(document == m_document, "Bad document look up!"); + Debug.Assert(document == m_document, "Bad document look up!"); // make sure that arrays are large enough to hold addition info EnsureCapacity(); @@ -1968,9 +1930,6 @@ namespace System.Reflection.Emit } } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal void EmitLineNumberInfo(ISymbolWriter symWriter) { int[] iOffsetsTemp; diff --git a/src/mscorlib/src/System/Reflection/Emit/ISymWrapperCore.cs b/src/mscorlib/src/System/Reflection/Emit/ISymWrapperCore.cs index 00fdd00..a737895 100644 --- a/src/mscorlib/src/System/Reflection/Emit/ISymWrapperCore.cs +++ b/src/mscorlib/src/System/Reflection/Emit/ISymWrapperCore.cs @@ -2,10 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -#if FEATURE_CORECLR - namespace System.Reflection.Emit { using System; @@ -14,7 +10,6 @@ namespace System.Reflection.Emit using System.Runtime.CompilerServices; using System.Diagnostics.SymbolStore; - //----------------------------------------------------------------------------------- // On Telesto, we don't ship the ISymWrapper.dll assembly. However, ReflectionEmit // relies on that assembly to write out managed PDBs. @@ -58,9 +53,6 @@ namespace System.Reflection.Emit //------------------------------------------------------------------------------ // Ctor //------------------------------------------------------------------------------ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal SymDocumentWriter(PunkSafeHandle pDocumentWriterSafeHandle) { m_pDocumentWriterSafeHandle = pDocumentWriterSafeHandle; @@ -72,9 +64,6 @@ namespace System.Reflection.Emit //------------------------------------------------------------------------------ // Returns the underlying ISymUnmanagedDocumentWriter* (as a safehandle.) //------------------------------------------------------------------------------ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal PunkSafeHandle GetUnmanaged() { return m_pDocumentWriterSafeHandle; @@ -97,9 +86,6 @@ namespace System.Reflection.Emit //------------------------------------------------------------------------------ // SetCheckSum() wrapper //------------------------------------------------------------------------------ - #if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] - #endif void ISymbolDocumentWriter.SetCheckSum(Guid algorithmId, byte [] checkSum) { int hr = m_vtable.SetCheckSum(m_pDocWriter, algorithmId, (uint)checkSum.Length, checkSum); @@ -109,7 +95,6 @@ namespace System.Reflection.Emit } } - [System.Security.SecurityCritical] private delegate int DSetCheckSum(ISymUnmanagedDocumentWriter * pThis, Guid algorithmId, uint checkSumSize, [In] byte[] checkSum); //------------------------------------------------------------------------------ @@ -117,7 +102,6 @@ namespace System.Reflection.Emit // exactly. If a member is declared as an IntPtr rather than a delegate, it means // we don't call that particular member. //------------------------------------------------------------------------------ - [System.Security.SecurityCritical] [StructLayout(LayoutKind.Sequential)] private struct ISymUnmanagedDocumentWriterVTable { @@ -126,9 +110,6 @@ namespace System.Reflection.Emit internal IntPtr Release; internal IntPtr SetSource; - #if FEATURE_CORECLR - [System.Security.SecurityCritical] - #endif internal DSetCheckSum SetCheckSum; } @@ -136,7 +117,6 @@ namespace System.Reflection.Emit // This layout must match the (start) of the unmanaged ISymUnmanagedDocumentWriter // COM object. //------------------------------------------------------------------------------ - [System.Security.SecurityCritical] [StructLayout(LayoutKind.Sequential)] private struct ISymUnmanagedDocumentWriter { @@ -146,19 +126,14 @@ namespace System.Reflection.Emit //------------------------------------------------------------------------------ // Stores underlying ISymUnmanagedDocumentWriter* pointer (wrapped in a safehandle.) //------------------------------------------------------------------------------ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif private PunkSafeHandle m_pDocumentWriterSafeHandle; - [SecurityCritical] private ISymUnmanagedDocumentWriter * m_pDocWriter; //------------------------------------------------------------------------------ // Stores the "managed vtable" (actually a structure full of delegates that // P/Invoke to the corresponding unmanaged COM methods.) //------------------------------------------------------------------------------ - [SecurityCritical] private ISymUnmanagedDocumentWriterVTable m_vtable; @@ -212,9 +187,6 @@ namespace System.Reflection.Emit //------------------------------------------------------------------------------ // DefineDocument() wrapper //------------------------------------------------------------------------------ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif ISymbolDocumentWriter ISymbolWriter.DefineDocument(String url, Guid language, Guid languageVendor, @@ -237,9 +209,6 @@ namespace System.Reflection.Emit //------------------------------------------------------------------------------ // SetUserEntryPoint() wrapper //------------------------------------------------------------------------------ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif void ISymbolWriter.SetUserEntryPoint(SymbolToken entryMethod) { int hr = m_vtable.SetUserEntryPoint(m_pWriter, entryMethod.GetToken()); @@ -252,9 +221,6 @@ namespace System.Reflection.Emit //------------------------------------------------------------------------------ // OpenMethod() wrapper //------------------------------------------------------------------------------ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif void ISymbolWriter.OpenMethod(SymbolToken method) { int hr = m_vtable.OpenMethod(m_pWriter, method.GetToken()); @@ -267,9 +233,6 @@ namespace System.Reflection.Emit //------------------------------------------------------------------------------ // CloseMethod() wrapper //------------------------------------------------------------------------------ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif void ISymbolWriter.CloseMethod() { int hr = m_vtable.CloseMethod(m_pWriter); @@ -282,9 +245,6 @@ namespace System.Reflection.Emit //------------------------------------------------------------------------------ // DefineSequencePoints() wrapper //------------------------------------------------------------------------------ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif void ISymbolWriter.DefineSequencePoints(ISymbolDocumentWriter document, int[] offsets, int[] lines, @@ -344,9 +304,6 @@ namespace System.Reflection.Emit //------------------------------------------------------------------------------ // OpenScope() wrapper //------------------------------------------------------------------------------ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif int ISymbolWriter.OpenScope(int startOffset) { int ret; @@ -361,9 +318,6 @@ namespace System.Reflection.Emit //------------------------------------------------------------------------------ // CloseScope() wrapper //------------------------------------------------------------------------------ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif void ISymbolWriter.CloseScope(int endOffset) { int hr = m_vtable.CloseScope(m_pWriter, endOffset); @@ -388,9 +342,6 @@ namespace System.Reflection.Emit //------------------------------------------------------------------------------ // DefineLocalVariable() wrapper //------------------------------------------------------------------------------ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif void ISymbolWriter.DefineLocalVariable(String name, FieldAttributes attributes, byte[] signature, @@ -476,9 +427,6 @@ namespace System.Reflection.Emit //------------------------------------------------------------------------------ // SetSymAttribute() wrapper //------------------------------------------------------------------------------ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif void ISymbolWriter.SetSymAttribute(SymbolToken parent, String name, byte[] data) { int hr = m_vtable.SetSymAttribute(m_pWriter, parent.GetToken(), name, data.Length, data); @@ -515,9 +463,6 @@ namespace System.Reflection.Emit //------------------------------------------------------------------------------ // UsingNamespace() wrapper //------------------------------------------------------------------------------ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif void ISymbolWriter.UsingNamespace(String name) { int hr = m_vtable.UsingNamespace(m_pWriter, name); @@ -557,9 +502,6 @@ namespace System.Reflection.Emit // with the real ISymWrapper.dll, ISymWrapper performs *no* Release (or AddRef) on pointers // furnished through SetUnderlyingWriter. Lifetime management is entirely up to the caller. //------------------------------------------------------------------------------ - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal void InternalSetUnderlyingWriter(IntPtr ppUnderlyingWriter) { m_pWriter = *((ISymUnmanagedWriter**)ppUnderlyingWriter); @@ -569,7 +511,6 @@ namespace System.Reflection.Emit //------------------------------------------------------------------------------ // Define delegates for the unmanaged COM methods we invoke. //------------------------------------------------------------------------------ - [System.Security.SecurityCritical] private delegate int DInitialize(ISymUnmanagedWriter* pthis, IntPtr emitter, //IUnknown* [MarshalAs(UnmanagedType.LPWStr)] String filename, //WCHAR* @@ -577,7 +518,6 @@ namespace System.Reflection.Emit [MarshalAs(UnmanagedType.Bool)] bool fFullBuild ); - [System.Security.SecurityCritical] private delegate int DDefineDocument(ISymUnmanagedWriter* pthis, [MarshalAs(UnmanagedType.LPWStr)] String url, [In] ref Guid language, @@ -586,14 +526,10 @@ namespace System.Reflection.Emit [Out] out PunkSafeHandle ppsymUnmanagedDocumentWriter ); - [System.Security.SecurityCritical] private delegate int DSetUserEntryPoint(ISymUnmanagedWriter* pthis, int entryMethod); - [System.Security.SecurityCritical] private delegate int DOpenMethod(ISymUnmanagedWriter* pthis, int entryMethod); - [System.Security.SecurityCritical] private delegate int DCloseMethod(ISymUnmanagedWriter* pthis); - [System.Security.SecurityCritical] private delegate int DDefineSequencePoints(ISymUnmanagedWriter* pthis, PunkSafeHandle document, int spCount, @@ -603,15 +539,11 @@ namespace System.Reflection.Emit [In] int[] endLines, [In] int[] endColumns); - [System.Security.SecurityCritical] private delegate int DOpenScope(ISymUnmanagedWriter* pthis, int startOffset, [Out] out int pretval); - [System.Security.SecurityCritical] private delegate int DCloseScope(ISymUnmanagedWriter* pthis, int endOffset); - [System.Security.SecurityCritical] private delegate int DSetScopeRange(ISymUnmanagedWriter* pthis, int scopeID, int startOffset, int endOffset); - [System.Security.SecurityCritical] private delegate int DDefineLocalVariable(ISymUnmanagedWriter* pthis, [MarshalAs(UnmanagedType.LPWStr)] String name, int attributes, @@ -625,10 +557,8 @@ namespace System.Reflection.Emit int endOffset ); - [System.Security.SecurityCritical] private delegate int DClose(ISymUnmanagedWriter* pthis); - [System.Security.SecurityCritical] private delegate int DSetSymAttribute(ISymUnmanagedWriter* pthis, int parent, [MarshalAs(UnmanagedType.LPWStr)] String name, @@ -637,11 +567,8 @@ namespace System.Reflection.Emit ); - [System.Security.SecurityCritical] private delegate int DOpenNamespace(ISymUnmanagedWriter* pthis, [MarshalAs(UnmanagedType.LPWStr)] String name); - [System.Security.SecurityCritical] private delegate int DCloseNamespace(ISymUnmanagedWriter* pthis); - [System.Security.SecurityCritical] private delegate int DUsingNamespace(ISymUnmanagedWriter* pthis, [MarshalAs(UnmanagedType.LPWStr)] String name); @@ -658,77 +585,32 @@ namespace System.Reflection.Emit internal IntPtr AddRef; internal IntPtr Release; - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal DDefineDocument DefineDocument; - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal DSetUserEntryPoint SetUserEntryPoint; - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal DOpenMethod OpenMethod; - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal DCloseMethod CloseMethod; - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal DOpenScope OpenScope; - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal DCloseScope CloseScope; - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal DSetScopeRange SetScopeRange; - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal DDefineLocalVariable DefineLocalVariable; internal IntPtr DefineParameter; internal IntPtr DefineField; internal IntPtr DefineGlobalVariable; - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal DClose Close; - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal DSetSymAttribute SetSymAttribute; - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal DOpenNamespace OpenNamespace; - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal DCloseNamespace CloseNamespace; - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal DUsingNamespace UsingNamespace; internal IntPtr SetMethodSourceRange; - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal DInitialize Initialize; internal IntPtr GetDebugInfo; - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal DDefineSequencePoints DefineSequencePoints; } @@ -749,7 +631,6 @@ namespace System.Reflection.Emit // As with the real ISymWrapper.dll, ISymWrapper performs *no* Release (or AddRef) on this pointer. // Managing lifetime is up to the caller (coreclr.dll). //------------------------------------------------------------------------------ - [SecurityCritical] private ISymUnmanagedWriter *m_pWriter; //------------------------------------------------------------------------------ @@ -778,20 +659,13 @@ namespace System.Reflection.Emit // // Had to make this a non-nested class since FCall's don't like to bind to nested classes. //-------------------------------------------------------------------------------------- - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif sealed class PunkSafeHandle : SafeHandle { - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal PunkSafeHandle() : base((IntPtr)0, true) { } - [SecurityCritical] override protected bool ReleaseHandle() { m_Release(handle); @@ -800,7 +674,6 @@ namespace System.Reflection.Emit public override bool IsInvalid { - [SecurityCritical] get { return handle == ((IntPtr)0); } } @@ -810,19 +683,10 @@ namespace System.Reflection.Emit [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern IntPtr nGetDReleaseTarget(); // FCall gets us the native DRelease target (so we don't need named dllexport from coreclr.dll) - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif static PunkSafeHandle() { m_Release = (DRelease)(Marshal.GetDelegateForFunctionPointer(nGetDReleaseTarget(), typeof(DRelease))); m_Release((IntPtr)0); // make one call to make sure the delegate is fully prepped before we're in the critical finalizer situation. } - } // PunkSafeHandle - } //namespace System.Reflection.Emit - - -#endif //FEATURE_CORECLR - diff --git a/src/mscorlib/src/System/Reflection/Emit/LocalBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/LocalBuilder.cs index 4008703..a34d5ebe 100644 --- a/src/mscorlib/src/System/Reflection/Emit/LocalBuilder.cs +++ b/src/mscorlib/src/System/Reflection/Emit/LocalBuilder.cs @@ -124,28 +124,6 @@ namespace System.Reflection.Emit } } #endregion - -#if !FEATURE_CORECLR - void _LocalBuilder.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _LocalBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _LocalBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - void _LocalBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif } } diff --git a/src/mscorlib/src/System/Reflection/Emit/MethodBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/MethodBuilder.cs index 015a73b..654e166 100644 --- a/src/mscorlib/src/System/Reflection/Emit/MethodBuilder.cs +++ b/src/mscorlib/src/System/Reflection/Emit/MethodBuilder.cs @@ -16,12 +16,12 @@ namespace System.Reflection.Emit using System.Collections.Generic; using System.Security.Permissions; using System.Runtime.InteropServices; + using System.Diagnostics; using System.Diagnostics.Contracts; - [HostProtection(MayLeakOnAbort = true)] [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_MethodBuilder))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public sealed class MethodBuilder : MethodInfo, _MethodBuilder { #region Private Data Members @@ -90,16 +90,16 @@ namespace System.Reflection.Emit ModuleBuilder mod, TypeBuilder type, bool bIsGlobalMethod) { if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); if (name.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(name)); if (name[0] == '\0') - throw new ArgumentException(Environment.GetResourceString("Argument_IllegalName"), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_IllegalName"), nameof(name)); if (mod == null) - throw new ArgumentNullException("mod"); + throw new ArgumentNullException(nameof(mod)); Contract.EndContractBlock(); if (parameterTypes != null) @@ -107,7 +107,7 @@ namespace System.Reflection.Emit foreach(Type t in parameterTypes) { if (t == null) - throw new ArgumentNullException("parameterTypes"); + throw new ArgumentNullException(nameof(parameterTypes)); } } @@ -196,14 +196,13 @@ namespace System.Reflection.Emit m_module.CheckContext(types); } - [System.Security.SecurityCritical] // auto-generated internal void CreateMethodBodyHelper(ILGenerator il) { // Sets the IL of the method. An ILGenerator is passed as an argument and the method // queries this instance to get all of the information which it needs. if (il == null) { - throw new ArgumentNullException("il"); + throw new ArgumentNullException(nameof(il)); } Contract.EndContractBlock(); @@ -367,7 +366,7 @@ namespace System.Reflection.Emit } else { - Contract.Assert(false, "We should never get here!"); + Debug.Assert(false, "We should never get here!"); return null; } } @@ -389,7 +388,6 @@ namespace System.Reflection.Emit return m_mdMethodFixups; } - [System.Security.SecurityCritical] // auto-generated internal SignatureHelper GetMethodSignature() { if (m_parameterTypes == null) @@ -480,7 +478,6 @@ namespace System.Reflection.Emit #endregion #region Object Overrides - [System.Security.SecuritySafeCritical] // auto-generated public override bool Equals(Object obj) { if (!(obj is MethodBuilder)) { return false; @@ -505,7 +502,6 @@ namespace System.Reflection.Emit return this.m_strName.GetHashCode(); } - [System.Security.SecuritySafeCritical] // auto-generated public override String ToString() { StringBuilder sb = new StringBuilder(1000); @@ -599,17 +595,17 @@ namespace System.Reflection.Emit public override bool IsSecurityCritical { - get { throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule")); } + get { return true; } } public override bool IsSecuritySafeCritical { - get { throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule")); } + get { return false; } } public override bool IsSecurityTransparent { - get { throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule")); } + get { return false; } } #endregion @@ -693,10 +689,10 @@ namespace System.Reflection.Emit public GenericTypeParameterBuilder[] DefineGenericParameters (params string[] names) { if (names == null) - throw new ArgumentNullException("names"); + throw new ArgumentNullException(nameof(names)); if (names.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Arg_EmptyArray"), "names"); + throw new ArgumentException(Environment.GetResourceString("Arg_EmptyArray"), nameof(names)); Contract.EndContractBlock(); if (m_inst != null) @@ -704,7 +700,7 @@ namespace System.Reflection.Emit for (int i = 0; i < names.Length; i ++) if (names[i] == null) - throw new ArgumentNullException("names"); + throw new ArgumentNullException(nameof(names)); if (m_tkMethod.Token != 0) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_MethodBuilderBaked")); @@ -721,7 +717,6 @@ namespace System.Reflection.Emit #endregion #region Public Members - [System.Security.SecuritySafeCritical] // auto-generated public MethodToken GetToken() { // We used to always "tokenize" a MethodBuilder when it is constructed. After change list 709498 @@ -767,16 +762,15 @@ namespace System.Reflection.Emit m_containingType.m_lastTokenizedMethod = i; } - Contract.Assert(currentMethod == this, "We should have found this method in m_containingType.m_listMethods"); - Contract.Assert(currentToken.Token != 0, "The token should not be 0"); + Debug.Assert(currentMethod == this, "We should have found this method in m_containingType.m_listMethods"); + Debug.Assert(currentToken.Token != 0, "The token should not be 0"); return currentToken; } - [System.Security.SecurityCritical] // auto-generated private MethodToken GetTokenNoLock() { - Contract.Assert(m_tkMethod.Token == 0, "m_tkMethod should not have been initialized"); + Debug.Assert(m_tkMethod.Token == 0, "m_tkMethod should not have been initialized"); int sigLength; byte[] sigBytes = GetMethodSignature().InternalGetSignature(out sigLength); @@ -841,7 +835,6 @@ namespace System.Reflection.Emit } - [System.Security.SecuritySafeCritical] // auto-generated public ParameterBuilder DefineParameter(int position, ParameterAttributes attributes, String strParamName) { if (position < 0) @@ -858,7 +851,6 @@ namespace System.Reflection.Emit return new ParameterBuilder(this, position, attributes, strParamName); } - [System.Security.SecuritySafeCritical] // auto-generated [Obsolete("An alternate API is available: Emit the MarshalAs custom attribute instead. http://go.microsoft.com/fwlink/?linkid=14202")] public void SetMarshal(UnmanagedMarshal unmanagedMarshal) { @@ -915,55 +907,15 @@ namespace System.Reflection.Emit m_symCustomAttrs.Add(new SymCustomAttr(name, data)); } -#if FEATURE_CAS_POLICY - [System.Security.SecuritySafeCritical] // auto-generated - public void AddDeclarativeSecurity(SecurityAction action, PermissionSet pset) - { - if (pset == null) - throw new ArgumentNullException("pset"); - Contract.EndContractBlock(); - - ThrowIfGeneric (); - -#pragma warning disable 618 - if (!Enum.IsDefined(typeof(SecurityAction), action) || - action == SecurityAction.RequestMinimum || - action == SecurityAction.RequestOptional || - action == SecurityAction.RequestRefuse) - { - throw new ArgumentOutOfRangeException("action"); - } -#pragma warning restore 618 - - // cannot declarative security after type is created - m_containingType.ThrowIfCreated(); - - // Translate permission set into serialized format (uses standard binary serialization format). - byte[] blob = null; - int length = 0; - if (!pset.IsEmpty()) - { - blob = pset.EncodeXml(); - length = blob.Length; - } - - // Write the blob into the metadata. - TypeBuilder.AddDeclarativeSecurity(m_module.GetNativeHandle(), MetadataTokenInternal, action, blob, length); - } -#endif // FEATURE_CAS_POLICY - - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif public void SetMethodBody(byte[] il, int maxStack, byte[] localSignature, IEnumerable exceptionHandlers, IEnumerable tokenFixups) { if (il == null) { - throw new ArgumentNullException("il", Environment.GetResourceString("ArgumentNull_Array")); + throw new ArgumentNullException(nameof(il), Environment.GetResourceString("ArgumentNull_Array")); } if (maxStack < 0) { - throw new ArgumentOutOfRangeException("maxStack", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(maxStack), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.EndContractBlock(); @@ -1056,9 +1008,6 @@ namespace System.Reflection.Emit /// /// Obsolete. /// - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif public void CreateMethodBody(byte[] il, int count) { ThrowIfGeneric(); @@ -1075,7 +1024,7 @@ namespace System.Reflection.Emit if (il != null && (count < 0 || count > il.Length)) { - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Index")); } if (il == null) @@ -1095,7 +1044,6 @@ namespace System.Reflection.Emit m_bIsBaked = true; } - [System.Security.SecuritySafeCritical] // auto-generated public void SetImplementationFlags(MethodImplAttributes attributes) { ThrowIfGeneric (); @@ -1158,7 +1106,6 @@ namespace System.Reflection.Emit public String Signature { - [System.Security.SecuritySafeCritical] // auto-generated get { return GetMethodSignature().ToString(); @@ -1166,18 +1113,13 @@ namespace System.Reflection.Emit } -#if FEATURE_CORECLR -[System.Security.SecurityCritical] // auto-generated -#else -[System.Security.SecuritySafeCritical] -#endif [System.Runtime.InteropServices.ComVisible(true)] public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) { if (con == null) - throw new ArgumentNullException("con"); + throw new ArgumentNullException(nameof(con)); if (binaryAttribute == null) - throw new ArgumentNullException("binaryAttribute"); + throw new ArgumentNullException(nameof(binaryAttribute)); Contract.EndContractBlock(); ThrowIfGeneric(); @@ -1191,11 +1133,10 @@ namespace System.Reflection.Emit ParseCA(con, binaryAttribute); } - [System.Security.SecuritySafeCritical] // auto-generated public void SetCustomAttribute(CustomAttributeBuilder customBuilder) { if (customBuilder == null) - throw new ArgumentNullException("customBuilder"); + throw new ArgumentNullException(nameof(customBuilder)); Contract.EndContractBlock(); ThrowIfGeneric(); @@ -1239,29 +1180,6 @@ namespace System.Reflection.Emit internal bool m_isDllImport = false; #endregion - -#if !FEATURE_CORECLR - void _MethodBuilder.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _MethodBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _MethodBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - void _MethodBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif - } internal class LocalSymInfo @@ -1366,9 +1284,6 @@ namespace System.Reflection.Emit checked { m_iNameSpaceCount++; } } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif internal virtual void EmitLocalSymInfo(ISymbolWriter symWriter) { int i; @@ -1468,51 +1383,51 @@ namespace System.Reflection.Emit { if (tryOffset < 0) { - throw new ArgumentOutOfRangeException("tryOffset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(tryOffset), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (tryLength < 0) { - throw new ArgumentOutOfRangeException("tryLength", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(tryLength), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (filterOffset < 0) { - throw new ArgumentOutOfRangeException("filterOffset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(filterOffset), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (handlerOffset < 0) { - throw new ArgumentOutOfRangeException("handlerOffset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(handlerOffset), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (handlerLength < 0) { - throw new ArgumentOutOfRangeException("handlerLength", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(handlerLength), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if ((long)tryOffset + tryLength > Int32.MaxValue) { - throw new ArgumentOutOfRangeException("tryLength", Environment.GetResourceString("ArgumentOutOfRange_Range", 0, Int32.MaxValue - tryOffset)); + throw new ArgumentOutOfRangeException(nameof(tryLength), Environment.GetResourceString("ArgumentOutOfRange_Range", 0, Int32.MaxValue - tryOffset)); } if ((long)handlerOffset + handlerLength > Int32.MaxValue) { - throw new ArgumentOutOfRangeException("handlerLength", Environment.GetResourceString("ArgumentOutOfRange_Range", 0, Int32.MaxValue - handlerOffset)); + throw new ArgumentOutOfRangeException(nameof(handlerLength), Environment.GetResourceString("ArgumentOutOfRange_Range", 0, Int32.MaxValue - handlerOffset)); } // Other tokens migth also be invalid. We only check nil tokens as the implementation (SectEH_Emit in corhlpr.cpp) requires it, // and we can't check for valid tokens until the module is baked. if (kind == ExceptionHandlingClauseOptions.Clause && (exceptionTypeToken & 0x00FFFFFF) == 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidTypeToken", exceptionTypeToken), "exceptionTypeToken"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidTypeToken", exceptionTypeToken), nameof(exceptionTypeToken)); } Contract.EndContractBlock(); if (!IsValidKind(kind)) { - throw new ArgumentOutOfRangeException("kind", Environment.GetResourceString("ArgumentOutOfRange_Enum")); + throw new ArgumentOutOfRangeException(nameof(kind), Environment.GetResourceString("ArgumentOutOfRange_Enum")); } m_tryStartOffset = tryOffset; @@ -1527,13 +1442,13 @@ namespace System.Reflection.Emit internal ExceptionHandler(int tryStartOffset, int tryEndOffset, int filterOffset, int handlerStartOffset, int handlerEndOffset, int kind, int exceptionTypeToken) { - Contract.Assert(tryStartOffset >= 0); - Contract.Assert(tryEndOffset >= 0); - Contract.Assert(filterOffset >= 0); - Contract.Assert(handlerStartOffset >= 0); - Contract.Assert(handlerEndOffset >= 0); - Contract.Assert(IsValidKind((ExceptionHandlingClauseOptions)kind)); - Contract.Assert(kind != (int)ExceptionHandlingClauseOptions.Clause || (exceptionTypeToken & 0x00FFFFFF) != 0); + Debug.Assert(tryStartOffset >= 0); + Debug.Assert(tryEndOffset >= 0); + Debug.Assert(filterOffset >= 0); + Debug.Assert(handlerStartOffset >= 0); + Debug.Assert(handlerEndOffset >= 0); + Debug.Assert(IsValidKind((ExceptionHandlingClauseOptions)kind)); + Debug.Assert(kind != (int)ExceptionHandlingClauseOptions.Clause || (exceptionTypeToken & 0x00FFFFFF) != 0); m_tryStartOffset = tryStartOffset; m_tryEndOffset = tryEndOffset; diff --git a/src/mscorlib/src/System/Reflection/Emit/ModuleBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/ModuleBuilder.cs index ce2a592..6884f50 100644 --- a/src/mscorlib/src/System/Reflection/Emit/ModuleBuilder.cs +++ b/src/mscorlib/src/System/Reflection/Emit/ModuleBuilder.cs @@ -12,7 +12,6 @@ namespace System.Reflection.Emit using System.Diagnostics.SymbolStore; using System.Globalization; using System.Reflection; - using System.Diagnostics; using System.IO; using System.Resources; using System.Security; @@ -22,6 +21,7 @@ namespace System.Reflection.Emit using System.Threading; using System.Runtime.Versioning; using System.Runtime.CompilerServices; + using System.Diagnostics; using System.Diagnostics.Contracts; internal sealed class InternalModuleBuilder : RuntimeModule @@ -50,7 +50,6 @@ namespace System.Reflection.Emit } // deliberately not [serializable] - [HostProtection(MayLeakOnAbort = true)] [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_ModuleBuilder))] [System.Runtime.InteropServices.ComVisible(true)] @@ -97,9 +96,6 @@ namespace System.Reflection.Emit private Dictionary m_TypeBuilderDict; private ISymbolWriter m_iSymWriter; internal ModuleBuilderData m_moduleData; -#if !FEATURE_CORECLR - private MethodToken m_EntryPoint; -#endif //!FEATURE_CORECLR internal InternalModuleBuilder m_internalModuleBuilder; // This is the "external" AssemblyBuilder // only the "external" ModuleBuilder has this set @@ -157,42 +153,35 @@ namespace System.Reflection.Emit } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static int GetTypeRef(RuntimeModule module, String strFullName, RuntimeModule refedModule, String strRefedModuleFileName, int tkResolution); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static int GetMemberRef(RuntimeModule module, RuntimeModule refedModule, int tr, int defToken); - [System.Security.SecurityCritical] // auto-generated private int GetMemberRef(Module refedModule, int tr, int defToken) { return GetMemberRef(GetNativeHandle(), GetRuntimeModuleFromModule(refedModule).GetNativeHandle(), tr, defToken); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static int GetMemberRefFromSignature(RuntimeModule module, int tr, String methodName, byte[] signature, int length); - [System.Security.SecurityCritical] // auto-generated private int GetMemberRefFromSignature(int tr, String methodName, byte[] signature, int length) { return GetMemberRefFromSignature(GetNativeHandle(), tr, methodName, signature, length); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static int GetMemberRefOfMethodInfo(RuntimeModule module, int tr, IRuntimeMethodInfo method); - [System.Security.SecurityCritical] // auto-generated private int GetMemberRefOfMethodInfo(int tr, RuntimeMethodInfo method) { - Contract.Assert(method != null); + Debug.Assert(method != null); #if FEATURE_APPX if (ContainingAssemblyBuilder.ProfileAPICheck) @@ -205,10 +194,9 @@ namespace System.Reflection.Emit return GetMemberRefOfMethodInfo(GetNativeHandle(), tr, method); } - [System.Security.SecurityCritical] // auto-generated private int GetMemberRefOfMethodInfo(int tr, RuntimeConstructorInfo method) { - Contract.Assert(method != null); + Debug.Assert(method != null); #if FEATURE_APPX if (ContainingAssemblyBuilder.ProfileAPICheck) @@ -221,15 +209,13 @@ namespace System.Reflection.Emit return GetMemberRefOfMethodInfo(GetNativeHandle(), tr, method); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static int GetMemberRefOfFieldInfo(RuntimeModule module, int tkType, RuntimeTypeHandle declaringType, int tkField); - [System.Security.SecurityCritical] // auto-generated private int GetMemberRefOfFieldInfo(int tkType, RuntimeTypeHandle declaringType, RuntimeFieldInfo runtimeField) { - Contract.Assert(runtimeField != null); + Debug.Assert(runtimeField != null); #if FEATURE_APPX if (ContainingAssemblyBuilder.ProfileAPICheck) @@ -243,38 +229,31 @@ namespace System.Reflection.Emit return GetMemberRefOfFieldInfo(GetNativeHandle(), tkType, declaringType, runtimeField.MetadataToken); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static int GetTokenFromTypeSpec(RuntimeModule pModule, byte[] signature, int length); - [System.Security.SecurityCritical] // auto-generated private int GetTokenFromTypeSpec(byte[] signature, int length) { return GetTokenFromTypeSpec(GetNativeHandle(), signature, length); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static int GetArrayMethodToken(RuntimeModule module, int tkTypeSpec, String methodName, byte[] signature, int sigLength); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static int GetStringConstant(RuntimeModule module, String str, int length); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void PreSavePEFile(RuntimeModule module, int portableExecutableKind, int imageFileMachine); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void SavePEFile(RuntimeModule module, String fileName, int entryPoint, int isExe, bool isManifestFile); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void AddResource( @@ -282,17 +261,14 @@ namespace System.Reflection.Emit byte[] resBytes, int resByteCount, int tkFile, int attribute, int portableExecutableKind, int imageFileMachine); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void SetModuleName(RuntimeModule module, String strModuleName); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal extern static void SetFieldRVAContent(RuntimeModule module, int fdToken, byte[] data, int length); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void DefineNativeResourceFile(RuntimeModule module, @@ -300,7 +276,6 @@ namespace System.Reflection.Emit int portableExecutableKind, int ImageFileMachine); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void DefineNativeResourceBytes(RuntimeModule module, @@ -308,7 +283,6 @@ namespace System.Reflection.Emit int portableExecutableKind, int imageFileMachine); - [System.Security.SecurityCritical] // auto-generated internal void DefineNativeResource(PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine) { string strResourceFileName = m_moduleData.m_strResourceFileName; @@ -351,105 +325,7 @@ namespace System.Reflection.Emit return null; } - -#if !FEATURE_CORECLR - internal void SetEntryPoint(MethodToken entryPoint) - { - // Sets the entry point of the module to be a given method. If no entry point - // is specified, calling EmitPEFile will generate a dll. - // AssemblyBuilder.SetEntryPoint has already demanded required permission - m_EntryPoint = entryPoint; - } -#endif //!FEATURE_CORECLR - - -#if !FEATURE_CORECLR - // This is a helper called by AssemblyBuilder save to presave information for the persistable modules. - // no need to lock here because we have already taken the lock in AssemblyBuilder.Save - [System.Security.SecurityCritical] // auto-generated - internal void PreSave(String fileName, - PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine) - { - if (m_moduleData.m_isSaved == true) - { - // can only save once - throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, - Environment.GetResourceString("InvalidOperation_ModuleHasBeenSaved"), - m_moduleData.m_strModuleName)); - } - - if (m_moduleData.m_fGlobalBeenCreated == false && m_moduleData.m_fHasGlobal == true) - throw new NotSupportedException(Environment.GetResourceString("NotSupported_GlobalFunctionNotBaked")); - TypeBuilder typeBuilder; - foreach (Type item in m_TypeBuilderDict.Values) - { - if (item is TypeBuilder) - { - typeBuilder = (TypeBuilder)item; - } - else - { - EnumBuilder enumBuilder = (EnumBuilder)item; - typeBuilder = enumBuilder.m_typeBuilder; - } - - if (!typeBuilder.IsCreated()) - { - // cannot save to PE file without creating all of the types first - throw new NotSupportedException(String.Format(CultureInfo.InvariantCulture, - Environment.GetResourceString("NotSupported_NotAllTypesAreBaked"), - typeBuilder.FullName)); - } - } - - PreSavePEFile(GetNativeHandle(), (int)portableExecutableKind, (int)imageFileMachine); - } - - // no need to lock here because we have already taken the lock in AssemblyBuilder.Save - [System.Security.SecurityCritical] // auto-generated - internal void Save(String fileName, bool isAssemblyFile, PortableExecutableKinds portableExecutableKind, - ImageFileMachine imageFileMachine) - { - // This is a helper called by AssemblyBuilder save to save information for the persistable modules. - if (m_moduleData.m_embeddedRes != null) - { - // There are embedded resources for this module - ResWriterData resWriter; - - // Add each resource content into the to be saved PE file - for (resWriter = m_moduleData.m_embeddedRes; resWriter != null; resWriter = resWriter.m_nextResWriter) - { - if (resWriter.m_resWriter != null) - resWriter.m_resWriter.Generate(); - - byte[] resBytes = new byte[resWriter.m_memoryStream.Length]; - resWriter.m_memoryStream.Flush(); - resWriter.m_memoryStream.Position = 0; - resWriter.m_memoryStream.Read(resBytes, 0, resBytes.Length); - - AddResource(GetNativeHandle(), - resWriter.m_strName, - resBytes, - resBytes.Length, - m_moduleData.FileToken, - (int)resWriter.m_attribute, - (int)portableExecutableKind, - (int)imageFileMachine); - } - } - - DefineNativeResource(portableExecutableKind, imageFileMachine); - - PEFileKinds pekind = isAssemblyFile ? ContainingAssemblyBuilder.m_assemblyData.m_peFileKind : PEFileKinds.Dll; - - SavePEFile(GetNativeHandle(), fileName, m_EntryPoint.Token, (int)pekind, isAssemblyFile); - - m_moduleData.m_isSaved = true; - } -#endif // !FEATURE_CORECLR - - [System.Security.SecurityCritical] // auto-generated private int GetTypeRefNested(Type type, Module refedModule, String strRefedModuleFileName) { // This function will generate correct TypeRef token for top level type and nested type. @@ -464,8 +340,8 @@ namespace System.Reflection.Emit typeName = UnmangleTypeName(typeName); } - Contract.Assert(!type.IsByRef, "Must not be ByRef."); - Contract.Assert(!type.IsGenericType || type.IsGenericTypeDefinition, "Must not have generic arguments."); + Debug.Assert(!type.IsByRef, "Must not be ByRef."); + Debug.Assert(!type.IsGenericType || type.IsGenericTypeDefinition, "Must not have generic arguments."); #if FEATURE_APPX if (ContainingAssemblyBuilder.ProfileAPICheck) @@ -481,13 +357,12 @@ namespace System.Reflection.Emit return GetTypeRef(GetNativeHandle(), typeName, GetRuntimeModuleFromModule(refedModule).GetNativeHandle(), strRefedModuleFileName, tkResolution); } - [System.Security.SecurityCritical] // auto-generated internal MethodToken InternalGetConstructorToken(ConstructorInfo con, bool usingRef) { // Helper to get constructor token. If usingRef is true, we will never use the def token if (con == null) - throw new ArgumentNullException("con"); + throw new ArgumentNullException(nameof(con)); Contract.EndContractBlock(); int tr; @@ -556,7 +431,6 @@ namespace System.Reflection.Emit return new MethodToken( mr ); } - [System.Security.SecurityCritical] // auto-generated internal void Init(String strModuleName, String strFileName, int tkFile) { m_moduleData = new ModuleBuilderData(this, strModuleName, strFileName, tkFile); @@ -565,7 +439,6 @@ namespace System.Reflection.Emit // This is a method for changing module and file name of the manifest module (created by default for // each assembly). - [System.Security.SecurityCritical] // auto-generated internal void ModifyModuleName(string name) { // Reset the names in the managed ModuleBuilderData @@ -589,7 +462,7 @@ namespace System.Reflection.Emit } #endregion - + #region Module Overrides // m_internalModuleBuilder is null iff this is a "internal" ModuleBuilder @@ -622,7 +495,6 @@ namespace System.Reflection.Emit return m as RuntimeModule; } - [System.Security.SecurityCritical] // auto-generated private int GetMemberRefToken(MethodBase method, IEnumerable optionalParameterTypes) { Type[] parameterTypes; @@ -671,11 +543,11 @@ namespace System.Reflection.Emit } else { - Contract.Assert(method is RuntimeMethodInfo || method is RuntimeConstructorInfo); + Debug.Assert(method is RuntimeMethodInfo || method is RuntimeConstructorInfo); if (method.IsGenericMethod) { - Contract.Assert(masmi != null); + Debug.Assert(masmi != null); methDef = masmi.GetGenericMethodDefinition(); methDef = methDef.Module.ResolveMethod( @@ -728,7 +600,6 @@ namespace System.Reflection.Emit return GetMemberRefFromSignature(tkParent, method.Name, sigBytes, sigLength); } - [System.Security.SecurityCritical] // auto-generated internal SignatureHelper GetMemberRefSignature(CallingConventions call, Type returnType, Type[] parameterTypes, IEnumerable optionalParameterTypes, int cGenericParameters) { @@ -949,11 +820,6 @@ namespace System.Reflection.Emit public override String FullyQualifiedName { -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif get { String fullyQualifiedName = m_moduleData.m_strFileName; @@ -962,7 +828,7 @@ namespace System.Reflection.Emit if (ContainingAssemblyBuilder.m_assemblyData.m_strDir != null) { fullyQualifiedName = Path.Combine(ContainingAssemblyBuilder.m_assemblyData.m_strDir, fullyQualifiedName); - fullyQualifiedName = Path.UnsafeGetFullPath(fullyQualifiedName); + fullyQualifiedName = Path.GetFullPath(fullyQualifiedName); } if (ContainingAssemblyBuilder.m_assemblyData.m_strDir != null && fullyQualifiedName != null) @@ -1085,18 +951,11 @@ namespace System.Reflection.Emit } } -#if FEATURE_X509 && FEATURE_CAS_POLICY - public override System.Security.Cryptography.X509Certificates.X509Certificate GetSignerCertificate() - { - return InternalModule.GetSignerCertificate(); - } -#endif // FEATURE_X509 && FEATURE_CAS_POLICY #endregion #region Public Members #region Define Type - [System.Security.SecuritySafeCritical] // auto-generated public TypeBuilder DefineType(String name) { Contract.Ensures(Contract.Result() != null); @@ -1107,7 +966,6 @@ namespace System.Reflection.Emit } } - [System.Security.SecuritySafeCritical] // auto-generated public TypeBuilder DefineType(String name, TypeAttributes attr) { Contract.Ensures(Contract.Result() != null); @@ -1118,7 +976,6 @@ namespace System.Reflection.Emit } } - [System.Security.SecuritySafeCritical] // auto-generated public TypeBuilder DefineType(String name, TypeAttributes attr, Type parent) { Contract.Ensures(Contract.Result() != null); @@ -1132,11 +989,6 @@ namespace System.Reflection.Emit } } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif public TypeBuilder DefineType(String name, TypeAttributes attr, Type parent, int typesize) { Contract.Ensures(Contract.Result() != null); @@ -1147,11 +999,6 @@ namespace System.Reflection.Emit } } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif public TypeBuilder DefineType(String name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize) { Contract.Ensures(Contract.Result() != null); @@ -1162,7 +1009,6 @@ namespace System.Reflection.Emit } } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public TypeBuilder DefineType(String name, TypeAttributes attr, Type parent, Type[] interfaces) { @@ -1174,7 +1020,6 @@ namespace System.Reflection.Emit } } - [System.Security.SecurityCritical] // auto-generated private TypeBuilder DefineTypeNoLock(String name, TypeAttributes attr, Type parent, Type[] interfaces, PackingSize packingSize, int typesize) { Contract.Ensures(Contract.Result() != null); @@ -1182,11 +1027,6 @@ namespace System.Reflection.Emit return new TypeBuilder(name, attr, parent, interfaces, this, packingSize, typesize, null); ; } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif public TypeBuilder DefineType(String name, TypeAttributes attr, Type parent, PackingSize packsize) { Contract.Ensures(Contract.Result() != null); @@ -1197,7 +1037,6 @@ namespace System.Reflection.Emit } } - [System.Security.SecurityCritical] // auto-generated private TypeBuilder DefineTypeNoLock(String name, TypeAttributes attr, Type parent, PackingSize packsize) { Contract.Ensures(Contract.Result() != null); @@ -1211,7 +1050,6 @@ namespace System.Reflection.Emit // This API can only be used to construct a top-level (not nested) enum type. // Nested enum types can be defined manually using ModuleBuilder.DefineType. - [System.Security.SecuritySafeCritical] // auto-generated public EnumBuilder DefineEnum(String name, TypeAttributes visibility, Type underlyingType) { Contract.Ensures(Contract.Result() != null); @@ -1222,17 +1060,16 @@ namespace System.Reflection.Emit EnumBuilder enumBuilder = DefineEnumNoLock(name, visibility, underlyingType); // This enum is not generic, nested, and cannot have any element type. - Contract.Assert(name == enumBuilder.FullName); + Debug.Assert(name == enumBuilder.FullName); // Replace the TypeBuilder object in m_TypeBuilderDict with this EnumBuilder object. - Contract.Assert(enumBuilder.m_typeBuilder == m_TypeBuilderDict[name]); + Debug.Assert(enumBuilder.m_typeBuilder == m_TypeBuilderDict[name]); m_TypeBuilderDict[name] = enumBuilder; return enumBuilder; } } - [System.Security.SecurityCritical] // auto-generated private EnumBuilder DefineEnumNoLock(String name, TypeAttributes visibility, Type underlyingType) { Contract.Ensures(Contract.Result() != null); @@ -1243,178 +1080,7 @@ namespace System.Reflection.Emit #endregion #region Define Resource -#if !FEATURE_CORECLR - public IResourceWriter DefineResource(String name, String description) - { - // Define embedded managed resource to be stored in this module - Contract.Ensures(Contract.Result() != null); - - return DefineResource(name, description, ResourceAttributes.Public); - } - - public IResourceWriter DefineResource(String name, String description, ResourceAttributes attribute) - { - // Define embedded managed resource to be stored in this module - Contract.Ensures(Contract.Result() != null); - - lock(SyncRoot) - { - return DefineResourceNoLock(name, description, attribute); - } - } - - private IResourceWriter DefineResourceNoLock(String name, String description, ResourceAttributes attribute) - { - // Define embedded managed resource to be stored in this module - - if (IsTransient()) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadResourceContainer")); - - if (name == null) - throw new ArgumentNullException("name"); - if (name.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); - Contract.Ensures(Contract.Result() != null); - Contract.EndContractBlock(); - - if (m_assemblyBuilder.IsPersistable()) - { - m_assemblyBuilder.m_assemblyData.CheckResNameConflict(name); - - MemoryStream stream = new MemoryStream(); - ResourceWriter resWriter = new ResourceWriter(stream); - ResWriterData resWriterData = new ResWriterData( resWriter, stream, name, String.Empty, String.Empty, attribute); - - // chain it to the embedded resource list - resWriterData.m_nextResWriter = m_moduleData.m_embeddedRes; - m_moduleData.m_embeddedRes = resWriterData; - return resWriter; - } - else - { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadResourceContainer")); - } - } -#endif // !FEATURE_CORECLR - -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif - public void DefineManifestResource(String name, Stream stream, ResourceAttributes attribute) - { - if (name == null) - throw new ArgumentNullException("name"); - - if (stream == null) - throw new ArgumentNullException("stream"); - Contract.EndContractBlock(); - - // Define embedded managed resource to be stored in this module - lock(SyncRoot) - { - DefineManifestResourceNoLock(name, stream, attribute); - } - } - - private void DefineManifestResourceNoLock(String name, Stream stream, ResourceAttributes attribute) - { - // Define embedded managed resource to be stored in this module - if (IsTransient()) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadResourceContainer")); - Contract.EndContractBlock(); - -#if !FEATURE_CORECLR - if (name == null) - throw new ArgumentNullException("name"); - if (name.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); - - if (m_assemblyBuilder.IsPersistable()) - { - m_assemblyBuilder.m_assemblyData.CheckResNameConflict(name); - - ResWriterData resWriterData = new ResWriterData( null, stream, name, String.Empty, String.Empty, attribute); - - // chain it to the embedded resource list - resWriterData.m_nextResWriter = m_moduleData.m_embeddedRes; - m_moduleData.m_embeddedRes = resWriterData; - } - else - { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadResourceContainer")); - } -#endif // !FEATURE_CORECLR - } - - -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif - public void DefineUnmanagedResource(Byte[] resource) - { - lock(SyncRoot) - { - DefineUnmanagedResourceInternalNoLock(resource); - } - } - - internal void DefineUnmanagedResourceInternalNoLock(Byte[] resource) - { - if (resource == null) - throw new ArgumentNullException("resource"); - Contract.EndContractBlock(); - - if (m_moduleData.m_strResourceFileName != null || m_moduleData.m_resourceBytes != null) - throw new ArgumentException(Environment.GetResourceString("Argument_NativeResourceAlreadyDefined")); - - m_moduleData.m_resourceBytes = new byte[resource.Length]; - Buffer.BlockCopy(resource, 0, m_moduleData.m_resourceBytes, 0, resource.Length); - } - -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif - public void DefineUnmanagedResource(String resourceFileName) - { - lock(SyncRoot) - { - DefineUnmanagedResourceFileInternalNoLock(resourceFileName); - } - } - - [System.Security.SecurityCritical] // auto-generated - internal void DefineUnmanagedResourceFileInternalNoLock(String resourceFileName) - { - if (resourceFileName == null) - throw new ArgumentNullException("resourceFileName"); - Contract.EndContractBlock(); - - if (m_moduleData.m_resourceBytes != null || m_moduleData.m_strResourceFileName != null) - throw new ArgumentException(Environment.GetResourceString("Argument_NativeResourceAlreadyDefined")); - - // Check caller has the right to read the file. - string strFullFileName; - strFullFileName = Path.UnsafeGetFullPath(resourceFileName); - new FileIOPermission(FileIOPermissionAccess.Read, strFullFileName).Demand(); - - new EnvironmentPermission(PermissionState.Unrestricted).Assert(); - try - { - if (File.UnsafeExists(resourceFileName) == false) - throw new FileNotFoundException(Environment.GetResourceString( - "IO.FileNotFound_FileName", - resourceFileName), resourceFileName); - } - finally - { - CodeAccessPermission.RevertAssert(); - } - - m_moduleData.m_strResourceFileName = strFullFileName; - } #endregion #region Define Global Method @@ -1453,10 +1119,10 @@ namespace System.Reflection.Emit throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_GlobalsHaveBeenCreated")); if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); if (name.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(name)); if ((attributes & MethodAttributes.Static) == 0) throw new ArgumentException(Environment.GetResourceString("Argument_GlobalFunctionHasToBeStatic")); @@ -1475,9 +1141,6 @@ namespace System.Reflection.Emit parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers); } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif public MethodBuilder DefinePInvokeMethod(String name, String dllName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet) @@ -1487,9 +1150,6 @@ namespace System.Reflection.Emit return DefinePInvokeMethod(name, dllName, name, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet); } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif public MethodBuilder DefinePInvokeMethod(String name, String dllName, String entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet) @@ -1503,9 +1163,6 @@ namespace System.Reflection.Emit } } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif private MethodBuilder DefinePInvokeMethodNoLock(String name, String dllName, String entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet) @@ -1548,9 +1205,6 @@ namespace System.Reflection.Emit #region Define Data -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif public FieldBuilder DefineInitializedData(String name, byte[] data, FieldAttributes attributes) { // This method will define an initialized Data in .sdata. @@ -1564,9 +1218,6 @@ namespace System.Reflection.Emit } } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif private FieldBuilder DefineInitializedDataNoLock(String name, byte[] data, FieldAttributes attributes) { // This method will define an initialized Data in .sdata. @@ -1583,9 +1234,6 @@ namespace System.Reflection.Emit return m_moduleData.m_globalTypeBuilder.DefineInitializedData(name, data, attributes); } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif public FieldBuilder DefineUninitializedData(String name, int size, FieldAttributes attributes) { Contract.Ensures(Contract.Result() != null); @@ -1596,9 +1244,6 @@ namespace System.Reflection.Emit } } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif private FieldBuilder DefineUninitializedDataNoLock(String name, int size, FieldAttributes attributes) { // This method will define an uninitialized Data in .sdata. @@ -1623,13 +1268,11 @@ namespace System.Reflection.Emit // 1. GetTypeToken // 2. ldtoken (see ILGenerator) // For all other occasions we should return the generic type instantiated on its formal parameters. - [System.Security.SecurityCritical] // auto-generated internal TypeToken GetTypeTokenInternal(Type type) { return GetTypeTokenInternal(type, false); } - [System.Security.SecurityCritical] // auto-generated private TypeToken GetTypeTokenInternal(Type type, bool getGenericDefinition) { lock(SyncRoot) @@ -1638,17 +1281,15 @@ namespace System.Reflection.Emit } } - [System.Security.SecuritySafeCritical] // auto-generated public TypeToken GetTypeToken(Type type) { return GetTypeTokenInternal(type, true); } - [System.Security.SecurityCritical] // auto-generated private TypeToken GetTypeTokenWorkerNoLock(Type type, bool getGenericDefinition) { if (type == null) - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); Contract.EndContractBlock(); CheckContext(type); @@ -1710,19 +1351,6 @@ namespace System.Reflection.Emit // ModuleBuilder refedModuleBuilder = refedModule as ModuleBuilder; -#if !FEATURE_CORECLR - Contract.Assert(refedModuleBuilder != null || refedModule is RuntimeModule); - bool isRefedModuleTransient = refedModuleBuilder != null ? - refedModuleBuilder.IsTransient() : - ((RuntimeModule)refedModule).IsTransientInternal(); - - // We cannot have a non-transient module referencing to a transient module. - if (IsTransient() == false && isRefedModuleTransient) - { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadTransientModuleReference")); - } -#endif // !FEATURE_CORECLR - String strRefedModuleFileName = String.Empty; if (refedModule.Assembly.Equals(this.Assembly)) { @@ -1753,7 +1381,6 @@ namespace System.Reflection.Emit return GetTypeToken(InternalModule.GetType(name, false, true)); } - [System.Security.SecuritySafeCritical] // auto-generated public MethodToken GetMethodToken(MethodInfo method) { lock(SyncRoot) @@ -1762,7 +1389,6 @@ namespace System.Reflection.Emit } } - [System.Security.SecurityCritical] // auto-generated internal MethodToken GetMethodTokenInternal(MethodInfo method) { lock(SyncRoot) @@ -1775,13 +1401,12 @@ namespace System.Reflection.Emit // 1. GetMethodToken // 2. ldtoken (see ILGenerator) // For all other occasions we should return the method on the generic type instantiated on the formal parameters. - [System.Security.SecurityCritical] // auto-generated private MethodToken GetMethodTokenNoLock(MethodInfo method, bool getGenericTypeDefinition) { // Return a MemberRef token if MethodInfo is not defined in this module. Or // return the MethodDef token. if (method == null) - throw new ArgumentNullException("method"); + throw new ArgumentNullException(nameof(method)); Contract.EndContractBlock(); int tr; @@ -1885,12 +1510,11 @@ namespace System.Reflection.Emit return new MethodToken(mr); } - [System.Security.SecuritySafeCritical] // auto-generated public MethodToken GetConstructorToken(ConstructorInfo constructor, IEnumerable optionalParameterTypes) { if (constructor == null) { - throw new ArgumentNullException("constructor"); + throw new ArgumentNullException(nameof(constructor)); } lock (SyncRoot) @@ -1900,12 +1524,11 @@ namespace System.Reflection.Emit } } - [System.Security.SecuritySafeCritical] // auto-generated public MethodToken GetMethodToken(MethodInfo method, IEnumerable optionalParameterTypes) { if (method == null) { - throw new ArgumentNullException("method"); + throw new ArgumentNullException(nameof(method)); } // useMethodDef flag only affects the result if we pass in a generic method definition. @@ -1922,7 +1545,6 @@ namespace System.Reflection.Emit } } - [System.Security.SecurityCritical] // auto-generated internal int GetMethodTokenInternal(MethodBase method, IEnumerable optionalParameterTypes, bool useMethodDef) { int tk = 0; @@ -1931,7 +1553,7 @@ namespace System.Reflection.Emit if (method.IsGenericMethod) { // Constructors cannot be generic. - Contract.Assert(methodInfo != null); + Debug.Assert(methodInfo != null); // Given M unbind to M MethodInfo methodInfoUnbound = methodInfo; @@ -1989,7 +1611,6 @@ namespace System.Reflection.Emit return tk; } - [System.Security.SecuritySafeCritical] // auto-generated public MethodToken GetArrayMethodToken(Type arrayClass, String methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes) { @@ -1999,18 +1620,17 @@ namespace System.Reflection.Emit } } - [System.Security.SecurityCritical] // auto-generated private MethodToken GetArrayMethodTokenNoLock(Type arrayClass, String methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes) { if (arrayClass == null) - throw new ArgumentNullException("arrayClass"); + throw new ArgumentNullException(nameof(arrayClass)); if (methodName == null) - throw new ArgumentNullException("methodName"); + throw new ArgumentNullException(nameof(methodName)); if (methodName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "methodName"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(methodName)); if (arrayClass.IsArray == false) throw new ArgumentException(Environment.GetResourceString("Argument_HasToBeArrayClass")); @@ -2035,7 +1655,6 @@ namespace System.Reflection.Emit typeSpec.Token, methodName, sigBytes, length)); } - [System.Security.SecuritySafeCritical] // auto-generated public MethodInfo GetArrayMethod(Type arrayClass, String methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes) { @@ -2052,7 +1671,6 @@ namespace System.Reflection.Emit return new SymbolMethod(this, token, arrayClass, methodName, callingConvention, returnType, parameterTypes); } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public MethodToken GetConstructorToken(ConstructorInfo con) { @@ -2060,7 +1678,6 @@ namespace System.Reflection.Emit return InternalGetConstructorToken(con, false); } - [System.Security.SecuritySafeCritical] // auto-generated public FieldToken GetFieldToken(FieldInfo field) { lock(SyncRoot) @@ -2069,7 +1686,6 @@ namespace System.Reflection.Emit } } - [System.Security.SecurityCritical] // auto-generated private FieldToken GetFieldTokenNoLock(FieldInfo field) { if (field == null) { @@ -2158,12 +1774,11 @@ namespace System.Reflection.Emit return new FieldToken(mr, field.GetType()); } - [System.Security.SecuritySafeCritical] // auto-generated public StringToken GetStringConstant(String str) { if (str == null) { - throw new ArgumentNullException("str"); + throw new ArgumentNullException(nameof(str)); } Contract.EndContractBlock(); @@ -2172,7 +1787,6 @@ namespace System.Reflection.Emit return new StringToken(GetStringConstant(GetNativeHandle(), str, str.Length)); } - [System.Security.SecuritySafeCritical] // auto-generated public SignatureToken GetSignatureToken(SignatureHelper sigHelper) { // Define signature token given a signature helper. This will define a metadata @@ -2180,7 +1794,7 @@ namespace System.Reflection.Emit if (sigHelper == null) { - throw new ArgumentNullException("sigHelper"); + throw new ArgumentNullException(nameof(sigHelper)); } Contract.EndContractBlock(); @@ -2191,11 +1805,10 @@ namespace System.Reflection.Emit sigBytes = sigHelper.InternalGetSignature(out sigLength); return new SignatureToken(TypeBuilder.GetTokenFromSig(GetNativeHandle(), sigBytes, sigLength), this); } - [System.Security.SecuritySafeCritical] // auto-generated public SignatureToken GetSignatureToken(byte[] sigBytes, int sigLength) { if (sigBytes == null) - throw new ArgumentNullException("sigBytes"); + throw new ArgumentNullException(nameof(sigBytes)); Contract.EndContractBlock(); byte[] localSigBytes = new byte[sigBytes.Length]; @@ -2208,18 +1821,13 @@ namespace System.Reflection.Emit #region Other -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif [System.Runtime.InteropServices.ComVisible(true)] public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) { if (con == null) - throw new ArgumentNullException("con"); + throw new ArgumentNullException(nameof(con)); if (binaryAttribute == null) - throw new ArgumentNullException("binaryAttribute"); + throw new ArgumentNullException(nameof(binaryAttribute)); Contract.EndContractBlock(); TypeBuilder.DefineCustomAttribute( @@ -2230,12 +1838,11 @@ namespace System.Reflection.Emit false, false); } - [System.Security.SecuritySafeCritical] // auto-generated public void SetCustomAttribute(CustomAttributeBuilder customBuilder) { if (customBuilder == null) { - throw new ArgumentNullException("customBuilder"); + throw new ArgumentNullException(nameof(customBuilder)); } Contract.EndContractBlock(); @@ -2276,14 +1883,11 @@ namespace System.Reflection.Emit return m_iSymWriter; } -#if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] -#endif public ISymbolDocumentWriter DefineDocument(String url, Guid language, Guid languageVendor, Guid documentType) { // url cannot be null but can be an empty string if (url == null) - throw new ArgumentNullException("url"); + throw new ArgumentNullException(nameof(url)); Contract.EndContractBlock(); lock(SyncRoot) @@ -2292,9 +1896,6 @@ namespace System.Reflection.Emit } } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif private ISymbolDocumentWriter DefineDocumentNoLock(String url, Guid language, Guid languageVendor, Guid documentType) { if (m_iSymWriter == null) @@ -2306,11 +1907,6 @@ namespace System.Reflection.Emit return m_iSymWriter.DefineDocument(url, language, languageVendor, documentType); } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif public void SetUserEntryPoint(MethodInfo entryPoint) { lock(SyncRoot) @@ -2319,7 +1915,6 @@ namespace System.Reflection.Emit } } - [System.Security.SecurityCritical] // auto-generated private void SetUserEntryPointNoLock(MethodInfo entryPoint) { // Set the user entry point. Compiler may generate startup stub before calling user main. @@ -2328,7 +1923,7 @@ namespace System.Reflection.Emit if (entryPoint == null) { - throw new ArgumentNullException("entryPoint"); + throw new ArgumentNullException(nameof(entryPoint)); } Contract.EndContractBlock(); @@ -2396,27 +1991,5 @@ namespace System.Reflection.Emit #endregion #endregion - -#if !FEATURE_CORECLR - void _ModuleBuilder.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _ModuleBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _ModuleBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - void _ModuleBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif } } diff --git a/src/mscorlib/src/System/Reflection/Emit/ModuleBuilderData.cs b/src/mscorlib/src/System/Reflection/Emit/ModuleBuilderData.cs index 2bec04a..96e60d9 100644 --- a/src/mscorlib/src/System/Reflection/Emit/ModuleBuilderData.cs +++ b/src/mscorlib/src/System/Reflection/Emit/ModuleBuilderData.cs @@ -9,6 +9,7 @@ namespace System.Reflection.Emit { using System; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Globalization; using System.IO; @@ -21,7 +22,6 @@ namespace System.Reflection.Emit [Serializable] internal class ModuleBuilderData { - [System.Security.SecurityCritical] // auto-generated internal ModuleBuilderData(ModuleBuilder module, String strModuleName, String strFileName, int tkFile) { m_globalTypeBuilder = new TypeBuilder(module); @@ -32,7 +32,6 @@ namespace System.Reflection.Emit } // Initialize module and file names. - [System.Security.SecurityCritical] // auto-generated private void InitNames(String strModuleName, String strFileName) { m_strModuleName = strModuleName; @@ -55,10 +54,9 @@ namespace System.Reflection.Emit // This is a method for changing module and file name of the manifest module (created by default for // each assembly). - [System.Security.SecurityCritical] // auto-generated internal virtual void ModifyModuleName(String strModuleName) { - Contract.Assert(m_strModuleName == AssemblyBuilder.MANIFEST_MODULE_NAME, "Changing names for non-manifest module"); + Debug.Assert(m_strModuleName == AssemblyBuilder.MANIFEST_MODULE_NAME, "Changing names for non-manifest module"); InitNames(strModuleName, null /*strFileName*/); } diff --git a/src/mscorlib/src/System/Reflection/Emit/Opcode.cs b/src/mscorlib/src/System/Reflection/Emit/Opcode.cs index cae4f05..d7bfacd 100644 --- a/src/mscorlib/src/System/Reflection/Emit/Opcode.cs +++ b/src/mscorlib/src/System/Reflection/Emit/Opcode.cs @@ -36,7 +36,6 @@ public struct OpCode internal const int StackChangeShift = 28; // XXXX0000000000000000000000000000 -#if FEATURE_CORECLR private OpCodeValues m_value; private int m_flags; @@ -80,7 +79,6 @@ public struct OpCode } } - public StackBehaviour StackBehaviourPop { get @@ -112,121 +110,6 @@ public struct OpCode return (short)m_value; } } -#else // FEATURE_CORECLR - // - // The exact layout is part of the legacy COM mscorlib surface, so it is - // pretty much set in stone for desktop CLR. Ideally, we would use the packed - // bit field like for CoreCLR, but that would be a breaking change. - // - -// disable csharp compiler warning #0414: field assigned unused value -#pragma warning disable 0414 - private String m_stringname; // not used - computed lazily -#pragma warning restore 0414 - private StackBehaviour m_pop; - private StackBehaviour m_push; - private OperandType m_operand; - private OpCodeType m_type; - private int m_size; - private byte m_s1; - private byte m_s2; - private FlowControl m_ctrl; - - // Specifies whether the current instructions causes the control flow to - // change unconditionally. - private bool m_endsUncondJmpBlk; - - - // Specifies the stack change that the current instruction causes not - // taking into account the operand dependant stack changes. - private int m_stackChange; - - - internal OpCode(OpCodeValues value, int flags) - { - m_stringname = null; // computed lazily - m_pop = (StackBehaviour)((flags >> StackBehaviourPopShift) & StackBehaviourMask); - m_push = (StackBehaviour)((flags >> StackBehaviourPushShift) & StackBehaviourMask); - m_operand = (OperandType)(flags & OperandTypeMask); - m_type = (OpCodeType)((flags >> OpCodeTypeShift) & OpCodeTypeMask); - m_size = (flags >> SizeShift) & SizeMask; - m_s1 = (byte)((int)value >> 8); - m_s2 = (byte)(int)value; - m_ctrl = (FlowControl)((flags >> FlowControlShift) & FlowControlMask); - m_endsUncondJmpBlk = (flags & EndsUncondJmpBlkFlag) != 0; - m_stackChange = (flags >> StackChangeShift); - } - - internal bool EndsUncondJmpBlk() - { - return m_endsUncondJmpBlk; - } - - internal int StackChange() - { - return m_stackChange; - } - - public OperandType OperandType - { - get - { - return (m_operand); - } - } - - public FlowControl FlowControl - { - get - { - return (m_ctrl); - } - } - - public OpCodeType OpCodeType - { - get - { - return (m_type); - } - } - - - public StackBehaviour StackBehaviourPop - { - get - { - return (m_pop); - } - } - - public StackBehaviour StackBehaviourPush - { - get - { - return (m_push); - } - } - - public int Size - { - get - { - return (m_size); - } - } - - public short Value - { - get - { - if (m_size == 2) - return (short)(m_s1 << 8 | m_s2); - return (short)m_s2; - } - } -#endif // FEATURE_CORECLR - private static volatile string[] g_nameCache; @@ -308,5 +191,4 @@ public struct OpCode return Name; } } - } diff --git a/src/mscorlib/src/System/Reflection/Emit/OpcodeType.cs b/src/mscorlib/src/System/Reflection/Emit/OpcodeType.cs index 5ef5f80..3636cb7 100644 --- a/src/mscorlib/src/System/Reflection/Emit/OpcodeType.cs +++ b/src/mscorlib/src/System/Reflection/Emit/OpcodeType.cs @@ -21,11 +21,8 @@ using System; public enum OpCodeType { -#if !FEATURE_CORECLR - /// [Obsolete("This API has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")] Annotation = 0, -#endif Macro = 1, Nternal = 2, Objmodel = 3, diff --git a/src/mscorlib/src/System/Reflection/Emit/OperandType.cs b/src/mscorlib/src/System/Reflection/Emit/OperandType.cs index fdde19a..808844a 100644 --- a/src/mscorlib/src/System/Reflection/Emit/OperandType.cs +++ b/src/mscorlib/src/System/Reflection/Emit/OperandType.cs @@ -27,11 +27,8 @@ public enum OperandType InlineI8 = 3, InlineMethod = 4, InlineNone = 5, -#if !FEATURE_CORECLR - /// [Obsolete("This API has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")] InlinePhi = 6, -#endif InlineR = 7, InlineSig = 9, InlineString = 10, diff --git a/src/mscorlib/src/System/Reflection/Emit/ParameterBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/ParameterBuilder.cs index 693e2d3..7909562 100644 --- a/src/mscorlib/src/System/Reflection/Emit/ParameterBuilder.cs +++ b/src/mscorlib/src/System/Reflection/Emit/ParameterBuilder.cs @@ -25,13 +25,12 @@ namespace System.Reflection.Emit { public class ParameterBuilder : _ParameterBuilder { // set ParamMarshal - [System.Security.SecuritySafeCritical] // auto-generated [Obsolete("An alternate API is available: Emit the MarshalAs custom attribute instead. http://go.microsoft.com/fwlink/?linkid=14202")] public virtual void SetMarshal(UnmanagedMarshal unmanagedMarshal) { if (unmanagedMarshal == null) { - throw new ArgumentNullException("unmanagedMarshal"); + throw new ArgumentNullException(nameof(unmanagedMarshal)); } Contract.EndContractBlock(); @@ -44,7 +43,6 @@ namespace System.Reflection.Emit { } // Set the default value of the parameter - [System.Security.SecuritySafeCritical] // auto-generated public virtual void SetConstant(Object defaultValue) { TypeBuilder.SetConstantValue( @@ -56,14 +54,13 @@ namespace System.Reflection.Emit { // Use this function if client decides to form the custom attribute blob themselves - [System.Security.SecuritySafeCritical] [System.Runtime.InteropServices.ComVisible(true)] public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) { if (con == null) - throw new ArgumentNullException("con"); + throw new ArgumentNullException(nameof(con)); if (binaryAttribute == null) - throw new ArgumentNullException("binaryAttribute"); + throw new ArgumentNullException(nameof(binaryAttribute)); Contract.EndContractBlock(); TypeBuilder.DefineCustomAttribute( @@ -75,12 +72,11 @@ namespace System.Reflection.Emit { } // Use this function if client wishes to build CustomAttribute using CustomAttributeBuilder - [System.Security.SecuritySafeCritical] // auto-generated public void SetCustomAttribute(CustomAttributeBuilder customBuilder) { if (customBuilder == null) { - throw new ArgumentNullException("customBuilder"); + throw new ArgumentNullException(nameof(customBuilder)); } Contract.EndContractBlock(); customBuilder.CreateCustomAttribute((ModuleBuilder) (m_methodBuilder .GetModule()), m_pdToken.Token); @@ -92,7 +88,6 @@ namespace System.Reflection.Emit { private ParameterBuilder() {} - [System.Security.SecurityCritical] // auto-generated internal ParameterBuilder( MethodBuilder methodBuilder, int sequence, @@ -117,28 +112,6 @@ namespace System.Reflection.Emit { return m_pdToken; } -#if !FEATURE_CORECLR - void _ParameterBuilder.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _ParameterBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _ParameterBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - void _ParameterBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif - internal int MetadataTokenInternal { get { return m_pdToken.Token; } } public virtual String Name { diff --git a/src/mscorlib/src/System/Reflection/Emit/PropertyBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/PropertyBuilder.cs index 5ac69f2..e7442b4 100644 --- a/src/mscorlib/src/System/Reflection/Emit/PropertyBuilder.cs +++ b/src/mscorlib/src/System/Reflection/Emit/PropertyBuilder.cs @@ -25,7 +25,6 @@ namespace System.Reflection.Emit { // A PropertyBuilder is always associated with a TypeBuilder. The TypeBuilder.DefineProperty // method will return a new PropertyBuilder to a client. // - [HostProtection(MayLeakOnAbort = true)] [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_PropertyBuilder))] [System.Runtime.InteropServices.ComVisible(true)] @@ -47,11 +46,11 @@ namespace System.Reflection.Emit { TypeBuilder containingType) // the containing type { if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); if (name.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(name)); if (name[0] == '\0') - throw new ArgumentException(Environment.GetResourceString("Argument_IllegalName"), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_IllegalName"), nameof(name)); Contract.EndContractBlock(); m_name = name; @@ -67,7 +66,6 @@ namespace System.Reflection.Emit { //************************************************ // Set the default value of the Property //************************************************ - [System.Security.SecuritySafeCritical] // auto-generated public void SetConstant(Object defaultValue) { m_containingType.ThrowIfCreated(); @@ -103,12 +101,11 @@ namespace System.Reflection.Emit { } } - [System.Security.SecurityCritical] // auto-generated private void SetMethodSemantics(MethodBuilder mdBuilder, MethodSemanticsAttributes semantics) { if (mdBuilder == null) { - throw new ArgumentNullException("mdBuilder"); + throw new ArgumentNullException(nameof(mdBuilder)); } m_containingType.ThrowIfCreated(); @@ -119,21 +116,18 @@ namespace System.Reflection.Emit { mdBuilder.GetToken().Token); } - [System.Security.SecuritySafeCritical] // auto-generated public void SetGetMethod(MethodBuilder mdBuilder) { SetMethodSemantics(mdBuilder, MethodSemanticsAttributes.Getter); m_getMethod = mdBuilder; } - [System.Security.SecuritySafeCritical] // auto-generated public void SetSetMethod(MethodBuilder mdBuilder) { SetMethodSemantics(mdBuilder, MethodSemanticsAttributes.Setter); m_setMethod = mdBuilder; } - [System.Security.SecuritySafeCritical] // auto-generated public void AddOtherMethod(MethodBuilder mdBuilder) { SetMethodSemantics(mdBuilder, MethodSemanticsAttributes.Other); @@ -141,18 +135,13 @@ namespace System.Reflection.Emit { // Use this function if client decides to form the custom attribute blob themselves -#if FEATURE_CORECLR -[System.Security.SecurityCritical] // auto-generated -#else -[System.Security.SecuritySafeCritical] -#endif [System.Runtime.InteropServices.ComVisible(true)] public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) { if (con == null) - throw new ArgumentNullException("con"); + throw new ArgumentNullException(nameof(con)); if (binaryAttribute == null) - throw new ArgumentNullException("binaryAttribute"); + throw new ArgumentNullException(nameof(binaryAttribute)); m_containingType.ThrowIfCreated(); TypeBuilder.DefineCustomAttribute( @@ -164,12 +153,11 @@ namespace System.Reflection.Emit { } // Use this function if client wishes to build CustomAttribute using CustomAttributeBuilder - [System.Security.SecuritySafeCritical] // auto-generated public void SetCustomAttribute(CustomAttributeBuilder customBuilder) { if (customBuilder == null) { - throw new ArgumentNullException("customBuilder"); + throw new ArgumentNullException(nameof(customBuilder)); } m_containingType.ThrowIfCreated(); customBuilder.CreateCustomAttribute(m_moduleBuilder, m_prToken.Token); @@ -256,28 +244,6 @@ namespace System.Reflection.Emit { throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule")); } -#if !FEATURE_CORECLR - void _PropertyBuilder.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _PropertyBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _PropertyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - void _PropertyBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif - public override String Name { get { return m_name; } } @@ -302,5 +268,4 @@ namespace System.Reflection.Emit { private MethodInfo m_setMethod; private TypeBuilder m_containingType; } - } diff --git a/src/mscorlib/src/System/Reflection/Emit/SignatureHelper.cs b/src/mscorlib/src/System/Reflection/Emit/SignatureHelper.cs index 35e8cc7..c40035b 100644 --- a/src/mscorlib/src/System/Reflection/Emit/SignatureHelper.cs +++ b/src/mscorlib/src/System/Reflection/Emit/SignatureHelper.cs @@ -8,6 +8,7 @@ namespace System.Reflection.Emit { using System.Text; using System; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Reflection; using System.Runtime.CompilerServices; @@ -25,19 +26,16 @@ namespace System.Reflection.Emit #endregion #region Static Members - [System.Security.SecuritySafeCritical] // auto-generated public static SignatureHelper GetMethodSigHelper(Module mod, Type returnType, Type[] parameterTypes) { return GetMethodSigHelper(mod, CallingConventions.Standard, returnType, null, null, parameterTypes, null, null); } - [System.Security.SecurityCritical] // auto-generated internal static SignatureHelper GetMethodSigHelper(Module mod, CallingConventions callingConvention, Type returnType, int cGenericParam) { return GetMethodSigHelper(mod, callingConvention, cGenericParam, returnType, null, null, null, null, null); } - [System.Security.SecuritySafeCritical] // auto-generated public static SignatureHelper GetMethodSigHelper(Module mod, CallingConventions callingConvention, Type returnType) { return GetMethodSigHelper(mod, callingConvention, returnType, null, null, null, null, null); @@ -52,7 +50,6 @@ namespace System.Reflection.Emit return sigHelp; } - [System.Security.SecurityCritical] // auto-generated internal static SignatureHelper GetMethodSigHelper( Module scope, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, @@ -62,7 +59,6 @@ namespace System.Reflection.Emit optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers); } - [System.Security.SecurityCritical] // auto-generated internal static SignatureHelper GetMethodSigHelper( Module scope, CallingConventions callingConvention, int cGenericParam, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, @@ -96,7 +92,6 @@ namespace System.Reflection.Emit return sigHelp; } - [System.Security.SecuritySafeCritical] // auto-generated public static SignatureHelper GetMethodSigHelper(Module mod, CallingConvention unmanagedCallConv, Type returnType) { SignatureHelper sigHelp; @@ -123,7 +118,7 @@ namespace System.Reflection.Emit } else { - throw new ArgumentException(Environment.GetResourceString("Argument_UnknownUnmanagedCallConv"), "unmanagedCallConv"); + throw new ArgumentException(Environment.GetResourceString("Argument_UnknownUnmanagedCallConv"), nameof(unmanagedCallConv)); } sigHelp = new SignatureHelper(mod, intCall, returnType, null, null); @@ -168,7 +163,6 @@ namespace System.Reflection.Emit return GetPropertySigHelper(mod, (CallingConventions)0, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers); } - [System.Security.SecuritySafeCritical] // auto-generated public static SignatureHelper GetPropertySigHelper(Module mod, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers) @@ -192,14 +186,13 @@ namespace System.Reflection.Emit return sigHelp; } - [System.Security.SecurityCritical] // auto-generated internal static SignatureHelper GetTypeSigToken(Module mod, Type type) { if (mod == null) throw new ArgumentNullException("module"); if (type == null) - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); return new SignatureHelper(mod, type); } @@ -221,7 +214,6 @@ namespace System.Reflection.Emit Init(mod, callingConvention); } - [System.Security.SecurityCritical] // auto-generated private SignatureHelper(Module mod, MdSigCallingConvention callingConvention, int cGenericParameters, Type returnType, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers) { @@ -234,14 +226,12 @@ namespace System.Reflection.Emit AddOneArgTypeHelper(returnType, requiredCustomModifiers, optionalCustomModifiers); } - [System.Security.SecurityCritical] // auto-generated private SignatureHelper(Module mod, MdSigCallingConvention callingConvention, Type returnType, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers) : this(mod, callingConvention, 0, returnType, requiredCustomModifiers, optionalCustomModifiers) { } - [System.Security.SecurityCritical] // auto-generated private SignatureHelper(Module mod, Type type) { Init(mod); @@ -290,7 +280,6 @@ namespace System.Reflection.Emit #endregion #region Private Members - [System.Security.SecurityCritical] // auto-generated private void AddOneArgTypeHelper(Type argument, bool pinned) { if (pinned) @@ -299,7 +288,6 @@ namespace System.Reflection.Emit AddOneArgTypeHelper(argument); } - [System.Security.SecurityCritical] // auto-generated private void AddOneArgTypeHelper(Type clsArgument, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers) { // This function will not increase the argument count. It only fills in bytes @@ -315,18 +303,18 @@ namespace System.Reflection.Emit Type t = optionalCustomModifiers[i]; if (t == null) - throw new ArgumentNullException("optionalCustomModifiers"); + throw new ArgumentNullException(nameof(optionalCustomModifiers)); if (t.HasElementType) - throw new ArgumentException(Environment.GetResourceString("Argument_ArraysInvalid"), "optionalCustomModifiers"); + throw new ArgumentException(Environment.GetResourceString("Argument_ArraysInvalid"), nameof(optionalCustomModifiers)); if (t.ContainsGenericParameters) - throw new ArgumentException(Environment.GetResourceString("Argument_GenericsInvalid"), "optionalCustomModifiers"); + throw new ArgumentException(Environment.GetResourceString("Argument_GenericsInvalid"), nameof(optionalCustomModifiers)); AddElementType(CorElementType.CModOpt); int token = m_module.GetTypeToken(t).Token; - Contract.Assert(!MetadataToken.IsNullToken(token)); + Debug.Assert(!MetadataToken.IsNullToken(token)); AddToken(token); } } @@ -338,18 +326,18 @@ namespace System.Reflection.Emit Type t = requiredCustomModifiers[i]; if (t == null) - throw new ArgumentNullException("requiredCustomModifiers"); + throw new ArgumentNullException(nameof(requiredCustomModifiers)); if (t.HasElementType) - throw new ArgumentException(Environment.GetResourceString("Argument_ArraysInvalid"), "requiredCustomModifiers"); + throw new ArgumentException(Environment.GetResourceString("Argument_ArraysInvalid"), nameof(requiredCustomModifiers)); if (t.ContainsGenericParameters) - throw new ArgumentException(Environment.GetResourceString("Argument_GenericsInvalid"), "requiredCustomModifiers"); + throw new ArgumentException(Environment.GetResourceString("Argument_GenericsInvalid"), nameof(requiredCustomModifiers)); AddElementType(CorElementType.CModReqd); int token = m_module.GetTypeToken(t).Token; - Contract.Assert(!MetadataToken.IsNullToken(token)); + Debug.Assert(!MetadataToken.IsNullToken(token)); AddToken(token); } } @@ -357,9 +345,7 @@ namespace System.Reflection.Emit AddOneArgTypeHelper(clsArgument); } - [System.Security.SecurityCritical] // auto-generated private void AddOneArgTypeHelper(Type clsArgument) { AddOneArgTypeHelperWorker(clsArgument, false); } - [System.Security.SecurityCritical] // auto-generated private void AddOneArgTypeHelperWorker(Type clsArgument, bool lastWasGenericInst) { if (clsArgument.IsGenericParameter) @@ -613,7 +599,6 @@ namespace System.Reflection.Emit AddToken(clsToken.Token); } - [System.Security.SecurityCritical] // auto-generated private unsafe void InternalAddRuntimeType(Type type) { // Add a runtime type into the signature. @@ -822,11 +807,10 @@ namespace System.Reflection.Emit AddArgument(clsArgument, null, null); } - [System.Security.SecuritySafeCritical] // auto-generated public void AddArgument(Type argument, bool pinned) { if (argument == null) - throw new ArgumentNullException("argument"); + throw new ArgumentNullException(nameof(argument)); IncrementArgCounts(); AddOneArgTypeHelper(argument, pinned); @@ -835,10 +819,10 @@ namespace System.Reflection.Emit public void AddArguments(Type[] arguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers) { if (requiredCustomModifiers != null && (arguments == null || requiredCustomModifiers.Length != arguments.Length)) - throw new ArgumentException(Environment.GetResourceString("Argument_MismatchedArrays", "requiredCustomModifiers", "arguments")); + throw new ArgumentException(Environment.GetResourceString("Argument_MismatchedArrays", nameof(requiredCustomModifiers), nameof(arguments))); if (optionalCustomModifiers != null && (arguments == null || optionalCustomModifiers.Length != arguments.Length)) - throw new ArgumentException(Environment.GetResourceString("Argument_MismatchedArrays", "optionalCustomModifiers", "arguments")); + throw new ArgumentException(Environment.GetResourceString("Argument_MismatchedArrays", nameof(optionalCustomModifiers), nameof(arguments))); if (arguments != null) { @@ -851,14 +835,13 @@ namespace System.Reflection.Emit } } - [System.Security.SecuritySafeCritical] // auto-generated public void AddArgument(Type argument, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers) { if (m_sigDone) throw new ArgumentException(Environment.GetResourceString("Argument_SigIsFinalized")); if (argument == null) - throw new ArgumentNullException("argument"); + throw new ArgumentNullException(nameof(argument)); IncrementArgCounts(); @@ -968,28 +951,6 @@ namespace System.Reflection.Emit #endregion -#if !FEATURE_CORECLR - void _SignatureHelper.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _SignatureHelper.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _SignatureHelper.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - void _SignatureHelper.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif - } } diff --git a/src/mscorlib/src/System/Reflection/Emit/SymbolMethod.cs b/src/mscorlib/src/System/Reflection/Emit/SymbolMethod.cs index 62780f4..6b47770 100644 --- a/src/mscorlib/src/System/Reflection/Emit/SymbolMethod.cs +++ b/src/mscorlib/src/System/Reflection/Emit/SymbolMethod.cs @@ -26,7 +26,6 @@ namespace System.Reflection.Emit #endregion #region Constructor - [System.Security.SecurityCritical] // auto-generated internal SymbolMethod(ModuleBuilder mod, MethodToken token, Type arrayClass, String methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes) { diff --git a/src/mscorlib/src/System/Reflection/Emit/SymbolType.cs b/src/mscorlib/src/System/Reflection/Emit/SymbolType.cs index 633a2bf..84ece90 100644 --- a/src/mscorlib/src/System/Reflection/Emit/SymbolType.cs +++ b/src/mscorlib/src/System/Reflection/Emit/SymbolType.cs @@ -234,7 +234,7 @@ namespace System.Reflection.Emit internal void SetElementType(Type baseType) { if (baseType == null) - throw new ArgumentNullException("baseType"); + throw new ArgumentNullException(nameof(baseType)); Contract.EndContractBlock(); m_baseType = baseType; diff --git a/src/mscorlib/src/System/Reflection/Emit/TypeBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/TypeBuilder.cs index 6db0471..73778d5 100644 --- a/src/mscorlib/src/System/Reflection/Emit/TypeBuilder.cs +++ b/src/mscorlib/src/System/Reflection/Emit/TypeBuilder.cs @@ -10,13 +10,13 @@ namespace System.Reflection.Emit { using System.Reflection; using System.Security; using System.Security.Permissions; - using System.Diagnostics; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using System.Collections.Generic; using CultureInfo = System.Globalization.CultureInfo; using System.Threading; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; @@ -35,7 +35,6 @@ namespace System.Reflection.Emit { Size128 = 128, } - [HostProtection(MayLeakOnAbort = true)] [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_TypeBuilder))] [System.Runtime.InteropServices.ComVisible(true)] @@ -56,10 +55,10 @@ namespace System.Reflection.Emit { public CustAttr(ConstructorInfo con, byte[] binaryAttribute) { if (con == null) - throw new ArgumentNullException("con"); + throw new ArgumentNullException(nameof(con)); if (binaryAttribute == null) - throw new ArgumentNullException("binaryAttribute"); + throw new ArgumentNullException(nameof(binaryAttribute)); Contract.EndContractBlock(); m_con = con; @@ -69,13 +68,12 @@ namespace System.Reflection.Emit { public CustAttr(CustomAttributeBuilder customBuilder) { if (customBuilder == null) - throw new ArgumentNullException("customBuilder"); + throw new ArgumentNullException(nameof(customBuilder)); Contract.EndContractBlock(); m_customBuilder = customBuilder; } - [System.Security.SecurityCritical] // auto-generated public void Bake(ModuleBuilder module, int token) { if (m_customBuilder == null) @@ -105,13 +103,13 @@ namespace System.Reflection.Emit { // if we wanted to but that just complicates things so these checks are designed to prevent that scenario. if (method.IsGenericMethod && !method.IsGenericMethodDefinition) - throw new ArgumentException(Environment.GetResourceString("Argument_NeedGenericMethodDefinition"), "method"); + throw new ArgumentException(Environment.GetResourceString("Argument_NeedGenericMethodDefinition"), nameof(method)); if (method.DeclaringType == null || !method.DeclaringType.IsGenericTypeDefinition) - throw new ArgumentException(Environment.GetResourceString("Argument_MethodNeedGenericDeclaringType"), "method"); + throw new ArgumentException(Environment.GetResourceString("Argument_MethodNeedGenericDeclaringType"), nameof(method)); if (type.GetGenericTypeDefinition() != method.DeclaringType) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidMethodDeclaringType"), "type"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidMethodDeclaringType"), nameof(type)); Contract.EndContractBlock(); // The following converts from Type or TypeBuilder of G to TypeBuilderInstantiation G. These types @@ -121,7 +119,7 @@ namespace System.Reflection.Emit { type = type.MakeGenericType(type.GetGenericArguments()); if (!(type is TypeBuilderInstantiation)) - throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "type"); + throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), nameof(type)); return MethodOnTypeBuilderInstantiation.GetMethod(method, type as TypeBuilderInstantiation); } @@ -131,18 +129,18 @@ namespace System.Reflection.Emit { throw new ArgumentException(Environment.GetResourceString("Argument_MustBeTypeBuilder")); if (!constructor.DeclaringType.IsGenericTypeDefinition) - throw new ArgumentException(Environment.GetResourceString("Argument_ConstructorNeedGenericDeclaringType"), "constructor"); + throw new ArgumentException(Environment.GetResourceString("Argument_ConstructorNeedGenericDeclaringType"), nameof(constructor)); Contract.EndContractBlock(); if (!(type is TypeBuilderInstantiation)) - throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "type"); + throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), nameof(type)); // TypeBuilder G ==> TypeBuilderInstantiation G if (type is TypeBuilder && type.IsGenericTypeDefinition) type = type.MakeGenericType(type.GetGenericArguments()); if (type.GetGenericTypeDefinition() != constructor.DeclaringType) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidConstructorDeclaringType"), "type"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidConstructorDeclaringType"), nameof(type)); return ConstructorOnTypeBuilderInstantiation.GetConstructor(constructor, type as TypeBuilderInstantiation); } @@ -152,18 +150,18 @@ namespace System.Reflection.Emit { throw new ArgumentException(Environment.GetResourceString("Argument_MustBeTypeBuilder")); if (!field.DeclaringType.IsGenericTypeDefinition) - throw new ArgumentException(Environment.GetResourceString("Argument_FieldNeedGenericDeclaringType"), "field"); + throw new ArgumentException(Environment.GetResourceString("Argument_FieldNeedGenericDeclaringType"), nameof(field)); Contract.EndContractBlock(); if (!(type is TypeBuilderInstantiation)) - throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "type"); + throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), nameof(type)); // TypeBuilder G ==> TypeBuilderInstantiation G if (type is TypeBuilder && type.IsGenericTypeDefinition) type = type.MakeGenericType(type.GetGenericArguments()); if (type.GetGenericTypeDefinition() != field.DeclaringType) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFieldDeclaringType"), "type"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFieldDeclaringType"), nameof(type)); return FieldOnTypeBuilderInstantiation.GetField(field, type as TypeBuilderInstantiation); } @@ -174,36 +172,30 @@ namespace System.Reflection.Emit { #endregion #region Private Static FCalls - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void SetParentType(RuntimeModule module, int tdTypeDef, int tkParent); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void AddInterfaceImpl(RuntimeModule module, int tdTypeDef, int tkInterface); #endregion #region Internal Static FCalls - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern int DefineMethod(RuntimeModule module, int tkParent, String name, byte[] signature, int sigLength, MethodAttributes attributes); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern int DefineMethodSpec(RuntimeModule module, int tkParent, byte[] signature, int sigLength); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern int DefineField(RuntimeModule module, int tkParent, String name, byte[] signature, int sigLength, FieldAttributes attributes); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void SetMethodIL(RuntimeModule module, int tk, bool isInitLocals, @@ -213,13 +205,11 @@ namespace System.Reflection.Emit { ExceptionHandler[] exceptions, int numExceptions, int [] tokenFixups, int numTokenFixups); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void DefineCustomAttribute(RuntimeModule module, int tkAssociate, int tkConstructor, byte[] attr, int attrLength, bool toDisk, bool updateCompilerFlags); - [System.Security.SecurityCritical] // auto-generated internal static void DefineCustomAttribute(ModuleBuilder module, int tkAssociate, int tkConstructor, byte[] attr, bool toDisk, bool updateCompilerFlags) { @@ -235,75 +225,56 @@ namespace System.Reflection.Emit { localAttr, (localAttr != null) ? localAttr.Length : 0, toDisk, updateCompilerFlags); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern void SetPInvokeData(RuntimeModule module, String DllName, String name, int token, int linkFlags); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern int DefineProperty(RuntimeModule module, int tkParent, String name, PropertyAttributes attributes, byte[] signature, int sigLength); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern int DefineEvent(RuntimeModule module, int tkParent, String name, EventAttributes attributes, int tkEventType); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern void DefineMethodSemantics(RuntimeModule module, int tkAssociation, MethodSemanticsAttributes semantics, int tkMethod); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern void DefineMethodImpl(RuntimeModule module, int tkType, int tkBody, int tkDecl); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern void SetMethodImpl(RuntimeModule module, int tkMethod, MethodImplAttributes MethodImplAttributes); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern int SetParamInfo(RuntimeModule module, int tkMethod, int iSequence, ParameterAttributes iParamAttributes, String strParamName); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern int GetTokenFromSig(RuntimeModule module, byte[] signature, int sigLength); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern void SetFieldLayoutOffset(RuntimeModule module, int fdToken, int iOffset); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern void SetClassLayout(RuntimeModule module, int tk, PackingSize iPackingSize, int iTypeSize); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern void SetFieldMarshal(RuntimeModule module, int tk, byte[] ubMarshal, int ubSize); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern unsafe void SetConstantValue(RuntimeModule module, int tk, int corType, void* pValue); - -#if FEATURE_CAS_POLICY - [System.Security.SecurityCritical] // auto-generated - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - internal static extern void AddDeclarativeSecurity(RuntimeModule module, int parent, SecurityAction action, byte[] blob, int cb); -#endif #endregion #region Internal\Private Static Members @@ -381,7 +352,6 @@ namespace System.Reflection.Emit { return false; } - [System.Security.SecurityCritical] // auto-generated internal static unsafe void SetConstantValue(ModuleBuilder module, int tk, Type destType, Object value) { // This is a helper function that is used by ParameterBuilder, PropertyBuilder, @@ -433,7 +403,7 @@ namespace System.Reflection.Emit { } else // must be a runtime Enum Type { - Contract.Assert(destType is RuntimeType, "destType is not a runtime type, an EnumBuilder, or a TypeBuilder."); + Debug.Assert(destType is RuntimeType, "destType is not a runtime type, an EnumBuilder, or a TypeBuilder."); underlyingType = Enum.GetUnderlyingType(destType); @@ -576,7 +546,6 @@ namespace System.Reflection.Emit { m_typeInterfaces = new List(); } - [System.Security.SecurityCritical] // auto-generated internal TypeBuilder( String name, TypeAttributes attr, @@ -590,22 +559,21 @@ namespace System.Reflection.Emit { Init(name, attr, parent, interfaces, module, iPackingSize, iTypeSize, enclosingType); } - [System.Security.SecurityCritical] // auto-generated private void Init(String fullname, TypeAttributes attr, Type parent, Type[] interfaces, ModuleBuilder module, PackingSize iPackingSize, int iTypeSize, TypeBuilder enclosingType) { if (fullname == null) - throw new ArgumentNullException("fullname"); + throw new ArgumentNullException(nameof(fullname)); if (fullname.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "fullname"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(fullname)); if (fullname[0] == '\0') - throw new ArgumentException(Environment.GetResourceString("Argument_IllegalName"), "fullname"); + throw new ArgumentException(Environment.GetResourceString("Argument_IllegalName"), nameof(fullname)); if (fullname.Length > 1023) - throw new ArgumentException(Environment.GetResourceString("Argument_TypeNameTooLong"), "fullname"); + throw new ArgumentException(Environment.GetResourceString("Argument_TypeNameTooLong"), nameof(fullname)); Contract.EndContractBlock(); int i; @@ -621,7 +589,7 @@ namespace System.Reflection.Emit { // Nested Type should have nested attribute set. // If we are renumbering TypeAttributes' bit, we need to change the logic here. if (((attr & TypeAttributes.VisibilityMask) == TypeAttributes.Public) ||((attr & TypeAttributes.VisibilityMask) == TypeAttributes.NotPublic)) - throw new ArgumentException(Environment.GetResourceString("Argument_BadNestedTypeFlags"), "attr"); + throw new ArgumentException(Environment.GetResourceString("Argument_BadNestedTypeFlags"), nameof(attr)); } int[] interfaceTokens = null; @@ -632,7 +600,7 @@ namespace System.Reflection.Emit { if (interfaces[i] == null) { // cannot contain null in the interface list - throw new ArgumentNullException("interfaces"); + throw new ArgumentNullException(nameof(interfaces)); } } interfaceTokens = new int[interfaces.Length + 1]; @@ -685,32 +653,12 @@ namespace System.Reflection.Emit { if ((m_iPackingSize != 0) ||(m_iTypeSize != 0)) SetClassLayout(GetModuleBuilder().GetNativeHandle(), m_tdType.Token, m_iPackingSize, m_iTypeSize); -#if !FEATURE_CORECLR - // If the type is public and it is contained in a assemblyBuilder, - // update the public COMType list. - if (IsPublicComType(this)) - { - if (containingAssem.IsPersistable() && m_module.IsTransient() == false) - { - // This will throw InvalidOperationException if the assembly has been saved - // Ideally we should reject all emit operations if the assembly has been saved, - // but that would be a breaking change for some. Currently you cannot define - // modules and public types, but you can still define private types and global methods. - containingAssem.m_assemblyData.AddPublicComType(this); - } - - // Now add the type to the ExportedType table - if (!m_module.Equals(containingAssem.ManifestModule)) - containingAssem.DefineExportedTypeInMemory(this, m_module.m_moduleData.FileToken, m_tdType.Token); - } -#endif m_module.AddType(FullName, this); } #endregion #region Private Members - [System.Security.SecurityCritical] // auto-generated private MethodBuilder DefinePInvokeMethodHelper( String name, String dllName, String importName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, @@ -733,7 +681,6 @@ namespace System.Reflection.Emit { } } - [System.Security.SecurityCritical] // auto-generated private MethodBuilder DefinePInvokeMethodHelperNoLock( String name, String dllName, String importName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, @@ -741,22 +688,22 @@ namespace System.Reflection.Emit { CallingConvention nativeCallConv, CharSet nativeCharSet) { if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); if (name.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(name)); if (dllName == null) - throw new ArgumentNullException("dllName"); + throw new ArgumentNullException(nameof(dllName)); if (dllName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "dllName"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(dllName)); if (importName == null) - throw new ArgumentNullException("importName"); + throw new ArgumentNullException(nameof(importName)); if (importName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "importName"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(importName)); if ((attributes & MethodAttributes.Abstract) != 0) throw new ArgumentException(Environment.GetResourceString("Argument_BadPInvokeMethod")); @@ -831,7 +778,6 @@ namespace System.Reflection.Emit { return method; } - [System.Security.SecurityCritical] // auto-generated private FieldBuilder DefineDataHelper(String name, byte[] data, int size, FieldAttributes attributes) { String strValueClassName; @@ -840,10 +786,10 @@ namespace System.Reflection.Emit { TypeAttributes typeAttributes; if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); if (name.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(name)); if (size <= 0 || size >= 0x003f0000) throw new ArgumentException(Environment.GetResourceString("Argument_BadSizeForData")); @@ -916,19 +862,16 @@ namespace System.Reflection.Emit { #endregion #region FCalls - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static int DefineType(RuntimeModule module, String fullname, int tkParent, TypeAttributes attributes, int tkEnclosingType, int[] interfaceTokens); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static int DefineGenericParam(RuntimeModule module, String name, int tkParent, GenericParameterAttributes attributes, int position, int[] constraints); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void TermCreateClass(RuntimeModule module, int tk, ObjectHandleOnStack type); @@ -1363,38 +1306,17 @@ namespace System.Reflection.Emit { public override bool IsSecurityCritical { - get - { - if (!IsCreated()) - throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated")); - Contract.EndContractBlock(); - - return m_bakedRuntimeType.IsSecurityCritical; - } + get { return true; } } public override bool IsSecuritySafeCritical { - get - { - if (!IsCreated()) - throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated")); - Contract.EndContractBlock(); - - return m_bakedRuntimeType.IsSecuritySafeCritical; - } + get { return false; } } public override bool IsSecurityTransparent { - get - { - if (!IsCreated()) - throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated")); - Contract.EndContractBlock(); - - return m_bakedRuntimeType.IsSecurityTransparent; - } + get { return false; } } [System.Runtime.InteropServices.ComVisible(true)] @@ -1479,7 +1401,6 @@ namespace System.Reflection.Emit { #endregion #region ICustomAttributeProvider Implementation - [System.Security.SecuritySafeCritical] // auto-generated public override Object[] GetCustomAttributes(bool inherit) { if (!IsCreated()) @@ -1489,38 +1410,36 @@ namespace System.Reflection.Emit { return CustomAttribute.GetCustomAttributes(m_bakedRuntimeType, typeof(object) as RuntimeType, inherit); } - [System.Security.SecuritySafeCritical] // auto-generated public override Object[] GetCustomAttributes(Type attributeType, bool inherit) { if (!IsCreated()) throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated")); if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),nameof(attributeType)); return CustomAttribute.GetCustomAttributes(m_bakedRuntimeType, attributeRuntimeType, inherit); } - [System.Security.SecuritySafeCritical] // auto-generated public override bool IsDefined(Type attributeType, bool inherit) { if (!IsCreated()) throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated")); if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"caType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),nameof(attributeType)); return CustomAttribute.IsDefined(m_bakedRuntimeType, attributeRuntimeType, inherit); } @@ -1547,7 +1466,7 @@ namespace System.Reflection.Emit { public GenericTypeParameterBuilder[] DefineGenericParameters(params string[] names) { if (names == null) - throw new ArgumentNullException("names"); + throw new ArgumentNullException(nameof(names)); if (names.Length == 0) throw new ArgumentException(); @@ -1555,7 +1474,7 @@ namespace System.Reflection.Emit { for (int i = 0; i < names.Length; i ++) if (names[i] == null) - throw new ArgumentNullException("names"); + throw new ArgumentNullException(nameof(names)); if (m_inst != null) throw new InvalidOperationException(); @@ -1589,7 +1508,6 @@ namespace System.Reflection.Emit { #endregion #region Define Method - [System.Security.SecuritySafeCritical] // auto-generated public void DefineMethodOverride(MethodInfo methodInfoBody, MethodInfo methodInfoDeclaration) { lock(SyncRoot) @@ -1598,14 +1516,13 @@ namespace System.Reflection.Emit { } } - [System.Security.SecurityCritical] // auto-generated private void DefineMethodOverrideNoLock(MethodInfo methodInfoBody, MethodInfo methodInfoDeclaration) { if (methodInfoBody == null) - throw new ArgumentNullException("methodInfoBody"); + throw new ArgumentNullException(nameof(methodInfoBody)); if (methodInfoDeclaration == null) - throw new ArgumentNullException("methodInfoDeclaration"); + throw new ArgumentNullException(nameof(methodInfoDeclaration)); Contract.EndContractBlock(); ThrowIfCreated(); @@ -1671,10 +1588,10 @@ namespace System.Reflection.Emit { Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers) { if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); if (name.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(name)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -1686,10 +1603,10 @@ namespace System.Reflection.Emit { if (parameterTypes != null) { if (parameterTypeOptionalCustomModifiers != null && parameterTypeOptionalCustomModifiers.Length != parameterTypes.Length) - throw new ArgumentException(Environment.GetResourceString("Argument_MismatchedArrays", "parameterTypeOptionalCustomModifiers", "parameterTypes")); + throw new ArgumentException(Environment.GetResourceString("Argument_MismatchedArrays", nameof(parameterTypeOptionalCustomModifiers), nameof(parameterTypes))); if (parameterTypeRequiredCustomModifiers != null && parameterTypeRequiredCustomModifiers.Length != parameterTypes.Length) - throw new ArgumentException(Environment.GetResourceString("Argument_MismatchedArrays", "parameterTypeRequiredCustomModifiers", "parameterTypes")); + throw new ArgumentException(Environment.GetResourceString("Argument_MismatchedArrays", nameof(parameterTypeRequiredCustomModifiers), nameof(parameterTypes))); } ThrowIfCreated(); @@ -1725,7 +1642,6 @@ namespace System.Reflection.Emit { #endregion #region Define Constructor - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public ConstructorBuilder DefineTypeInitializer() { @@ -1735,7 +1651,6 @@ namespace System.Reflection.Emit { } } - [System.Security.SecurityCritical] // auto-generated private ConstructorBuilder DefineTypeInitializerNoLock() { ThrowIfCreated(); @@ -1823,7 +1738,6 @@ namespace System.Reflection.Emit { return DefineConstructor(attributes, callingConvention, parameterTypes, null, null); } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public ConstructorBuilder DefineConstructor(MethodAttributes attributes, CallingConventions callingConvention, Type[] parameterTypes, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers) @@ -1839,7 +1753,6 @@ namespace System.Reflection.Emit { } } - [System.Security.SecurityCritical] // auto-generated private ConstructorBuilder DefineConstructorNoLock(MethodAttributes attributes, CallingConventions callingConvention, Type[] parameterTypes, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers) { @@ -1874,11 +1787,6 @@ namespace System.Reflection.Emit { #endregion #region Define PInvoke -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif public MethodBuilder DefinePInvokeMethod(String name, String dllName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet) @@ -1889,11 +1797,6 @@ namespace System.Reflection.Emit { return method; } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif public MethodBuilder DefinePInvokeMethod(String name, String dllName, String entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet) @@ -1904,11 +1807,6 @@ namespace System.Reflection.Emit { return method; } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif public MethodBuilder DefinePInvokeMethod(String name, String dllName, String entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, @@ -1924,7 +1822,6 @@ namespace System.Reflection.Emit { #endregion #region Define Nested Type - [System.Security.SecuritySafeCritical] // auto-generated public TypeBuilder DefineNestedType(String name) { lock(SyncRoot) @@ -1933,7 +1830,6 @@ namespace System.Reflection.Emit { } } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public TypeBuilder DefineNestedType(String name, TypeAttributes attr, Type parent, Type[] interfaces) { @@ -1947,7 +1843,6 @@ namespace System.Reflection.Emit { } } - [System.Security.SecuritySafeCritical] // auto-generated public TypeBuilder DefineNestedType(String name, TypeAttributes attr, Type parent) { lock(SyncRoot) @@ -1956,7 +1851,6 @@ namespace System.Reflection.Emit { } } - [System.Security.SecuritySafeCritical] // auto-generated public TypeBuilder DefineNestedType(String name, TypeAttributes attr) { lock(SyncRoot) @@ -1965,11 +1859,6 @@ namespace System.Reflection.Emit { } } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif public TypeBuilder DefineNestedType(String name, TypeAttributes attr, Type parent, int typeSize) { lock(SyncRoot) @@ -1978,11 +1867,6 @@ namespace System.Reflection.Emit { } } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif public TypeBuilder DefineNestedType(String name, TypeAttributes attr, Type parent, PackingSize packSize) { lock(SyncRoot) @@ -1991,11 +1875,6 @@ namespace System.Reflection.Emit { } } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif public TypeBuilder DefineNestedType(String name, TypeAttributes attr, Type parent, PackingSize packSize, int typeSize) { lock (SyncRoot) @@ -2004,7 +1883,6 @@ namespace System.Reflection.Emit { } } - [System.Security.SecurityCritical] // auto-generated private TypeBuilder DefineNestedTypeNoLock(String name, TypeAttributes attr, Type parent, Type[] interfaces, PackingSize packSize, int typeSize) { return new TypeBuilder(name, attr, parent, interfaces, m_module, packSize, typeSize, this); @@ -2018,7 +1896,6 @@ namespace System.Reflection.Emit { return DefineField(fieldName, type, null, null, attributes); } - [System.Security.SecuritySafeCritical] // auto-generated public FieldBuilder DefineField(String fieldName, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes) { @@ -2028,7 +1905,6 @@ namespace System.Reflection.Emit { } } - [System.Security.SecurityCritical] // auto-generated private FieldBuilder DefineFieldNoLock(String fieldName, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes) { @@ -2048,11 +1924,6 @@ namespace System.Reflection.Emit { return new FieldBuilder(this, fieldName, type, requiredCustomModifiers, optionalCustomModifiers, attributes); } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif public FieldBuilder DefineInitializedData(String name, byte[] data, FieldAttributes attributes) { lock(SyncRoot) @@ -2061,11 +1932,10 @@ namespace System.Reflection.Emit { } } - [System.Security.SecurityCritical] // auto-generated private FieldBuilder DefineInitializedDataNoLock(String name, byte[] data, FieldAttributes attributes) { if (data == null) - throw new ArgumentNullException("data"); + throw new ArgumentNullException(nameof(data)); Contract.EndContractBlock(); // This method will define an initialized Data in .sdata. @@ -2075,11 +1945,6 @@ namespace System.Reflection.Emit { return DefineDataHelper(name, data, data.Length, attributes); } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif public FieldBuilder DefineUninitializedData(String name, int size, FieldAttributes attributes) { lock(SyncRoot) @@ -2088,7 +1953,6 @@ namespace System.Reflection.Emit { } } - [System.Security.SecurityCritical] // auto-generated private FieldBuilder DefineUninitializedDataNoLock(String name, int size, FieldAttributes attributes) { // This method will define an uninitialized Data in .sdata. @@ -2121,7 +1985,6 @@ namespace System.Reflection.Emit { parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers); } - [System.Security.SecuritySafeCritical] // auto-generated public PropertyBuilder DefineProperty(String name, PropertyAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers) @@ -2133,15 +1996,14 @@ namespace System.Reflection.Emit { } } - [System.Security.SecurityCritical] // auto-generated private PropertyBuilder DefinePropertyNoLock(String name, PropertyAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers) { if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); if (name.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(name)); Contract.EndContractBlock(); CheckContext(returnType); @@ -2183,7 +2045,6 @@ namespace System.Reflection.Emit { this); } - [System.Security.SecuritySafeCritical] // auto-generated public EventBuilder DefineEvent(String name, EventAttributes attributes, Type eventtype) { lock(SyncRoot) @@ -2192,15 +2053,14 @@ namespace System.Reflection.Emit { } } - [System.Security.SecurityCritical] // auto-generated private EventBuilder DefineEventNoLock(String name, EventAttributes attributes, Type eventtype) { if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); if (name.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(name)); if (name[0] == '\0') - throw new ArgumentException(Environment.GetResourceString("Argument_IllegalName"), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_IllegalName"), nameof(name)); Contract.EndContractBlock(); int tkType; @@ -2234,7 +2094,6 @@ namespace System.Reflection.Emit { #region Create Type - [System.Security.SecuritySafeCritical] // auto-generated public TypeInfo CreateTypeInfo() { lock (SyncRoot) @@ -2243,7 +2102,6 @@ namespace System.Reflection.Emit { } } - [System.Security.SecuritySafeCritical] // auto-generated public Type CreateType() { lock (SyncRoot) @@ -2261,7 +2119,6 @@ namespace System.Reflection.Emit { m_module.CheckContext(types); } - [System.Security.SecurityCritical] // auto-generated private TypeInfo CreateTypeNoLock() { if (IsCreated()) @@ -2486,13 +2343,12 @@ namespace System.Reflection.Emit { } } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public void AddInterfaceImplementation(Type interfaceType) { if (interfaceType == null) { - throw new ArgumentNullException("interfaceType"); + throw new ArgumentNullException(nameof(interfaceType)); } Contract.EndContractBlock(); @@ -2506,50 +2362,6 @@ namespace System.Reflection.Emit { m_typeInterfaces.Add(interfaceType); } -#if FEATURE_CAS_POLICY - [System.Security.SecuritySafeCritical] // auto-generated - public void AddDeclarativeSecurity(SecurityAction action, PermissionSet pset) - { - lock(SyncRoot) - { - AddDeclarativeSecurityNoLock(action, pset); - } - } - - [System.Security.SecurityCritical] // auto-generated - private void AddDeclarativeSecurityNoLock(SecurityAction action, PermissionSet pset) - { - if (pset == null) - throw new ArgumentNullException("pset"); - -#pragma warning disable 618 - if (!Enum.IsDefined(typeof(SecurityAction), action) || - action == SecurityAction.RequestMinimum || - action == SecurityAction.RequestOptional || - action == SecurityAction.RequestRefuse) - { - throw new ArgumentOutOfRangeException("action"); - } -#pragma warning restore 618 - - Contract.EndContractBlock(); - - ThrowIfCreated(); - - // Translate permission set into serialized format(uses standard binary serialization format). - byte[] blob = null; - int length = 0; - if (!pset.IsEmpty()) - { - blob = pset.EncodeXml(); - length = blob.Length; - } - - // Write the blob into the metadata. - AddDeclarativeSecurity(m_module.GetNativeHandle(), m_tdType.Token, action, blob, length); - } -#endif // FEATURE_CAS_POLICY - public TypeToken TypeToken { get @@ -2562,30 +2374,24 @@ public TypeToken TypeToken } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif [System.Runtime.InteropServices.ComVisible(true)] public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) { if (con == null) - throw new ArgumentNullException("con"); + throw new ArgumentNullException(nameof(con)); if (binaryAttribute == null) - throw new ArgumentNullException("binaryAttribute"); + throw new ArgumentNullException(nameof(binaryAttribute)); Contract.EndContractBlock(); TypeBuilder.DefineCustomAttribute(m_module, m_tdType.Token, ((ModuleBuilder)m_module).GetConstructorToken(con).Token, binaryAttribute, false, false); } - [System.Security.SecuritySafeCritical] // auto-generated public void SetCustomAttribute(CustomAttributeBuilder customBuilder) { if (customBuilder == null) - throw new ArgumentNullException("customBuilder"); + throw new ArgumentNullException(nameof(customBuilder)); Contract.EndContractBlock(); customBuilder.CreateCustomAttribute((ModuleBuilder)m_module, m_tdType.Token); @@ -2594,27 +2400,5 @@ public TypeToken TypeToken #endregion #endregion - -#if !FEATURE_CORECLR - void _TypeBuilder.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _TypeBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _TypeBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - void _TypeBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif } } diff --git a/src/mscorlib/src/System/Reflection/Emit/TypeBuilderInstantiation.cs b/src/mscorlib/src/System/Reflection/Emit/TypeBuilderInstantiation.cs index 13b98b6..3bae585 100644 --- a/src/mscorlib/src/System/Reflection/Emit/TypeBuilderInstantiation.cs +++ b/src/mscorlib/src/System/Reflection/Emit/TypeBuilderInstantiation.cs @@ -28,13 +28,13 @@ namespace System.Reflection.Emit throw new InvalidOperationException(); if (typeArguments == null) - throw new ArgumentNullException("typeArguments"); + throw new ArgumentNullException(nameof(typeArguments)); Contract.EndContractBlock(); foreach (Type t in typeArguments) { if (t == null) - throw new ArgumentNullException("typeArguments"); + throw new ArgumentNullException(nameof(typeArguments)); } return new TypeBuilderInstantiation(type, typeArguments); diff --git a/src/mscorlib/src/System/Reflection/Emit/UnmanagedMarshal.cs b/src/mscorlib/src/System/Reflection/Emit/UnmanagedMarshal.cs index 09eac3a..28e95e2 100644 --- a/src/mscorlib/src/System/Reflection/Emit/UnmanagedMarshal.cs +++ b/src/mscorlib/src/System/Reflection/Emit/UnmanagedMarshal.cs @@ -10,7 +10,6 @@ namespace System.Reflection.Emit // This class is describing the fieldmarshal. [Serializable] - [HostProtection(MayLeakOnAbort = true)] [System.Runtime.InteropServices.ComVisible(true)] [Obsolete("An alternate API is available: Emit the MarshalAs custom attribute instead. http://go.microsoft.com/fwlink/?linkid=14202")] public sealed class UnmanagedMarshal diff --git a/src/mscorlib/src/System/Reflection/Emit/XXXOnTypeBuilderInstantiation.cs b/src/mscorlib/src/System/Reflection/Emit/XXXOnTypeBuilderInstantiation.cs index 5b36e0e..aaaffc0 100644 --- a/src/mscorlib/src/System/Reflection/Emit/XXXOnTypeBuilderInstantiation.cs +++ b/src/mscorlib/src/System/Reflection/Emit/XXXOnTypeBuilderInstantiation.cs @@ -11,6 +11,7 @@ namespace System.Reflection.Emit using System.Collections; using System.Collections.Generic; using System.Globalization; + using System.Diagnostics; using System.Diagnostics.Contracts; internal sealed class MethodOnTypeBuilderInstantiation : MethodInfo @@ -30,7 +31,7 @@ namespace System.Reflection.Emit #region Constructor internal MethodOnTypeBuilderInstantiation(MethodInfo method, TypeBuilderInstantiation type) { - Contract.Assert(method is MethodBuilder || method is RuntimeMethodInfo); + Debug.Assert(method is MethodBuilder || method is RuntimeMethodInfo); m_method = method; m_type = type; @@ -60,7 +61,7 @@ namespace System.Reflection.Emit return mb.MetadataTokenInternal; else { - Contract.Assert(m_method is RuntimeMethodInfo); + Debug.Assert(m_method is RuntimeMethodInfo); return m_method.MetadataToken; } } @@ -122,7 +123,7 @@ namespace System.Reflection.Emit #region Constructor internal ConstructorOnTypeBuilderInstantiation(ConstructorInfo constructor, TypeBuilderInstantiation type) { - Contract.Assert(constructor is ConstructorBuilder || constructor is RuntimeConstructorInfo); + Debug.Assert(constructor is ConstructorBuilder || constructor is RuntimeConstructorInfo); m_ctor = constructor; m_type = type; @@ -157,7 +158,7 @@ namespace System.Reflection.Emit return cb.MetadataTokenInternal; else { - Contract.Assert(m_ctor is RuntimeConstructorInfo); + Debug.Assert(m_ctor is RuntimeConstructorInfo); return m_ctor.MetadataToken; } } @@ -231,7 +232,7 @@ namespace System.Reflection.Emit #region Constructor internal FieldOnTypeBuilderInstantiation(FieldInfo field, TypeBuilderInstantiation type) { - Contract.Assert(field is FieldBuilder || field is RuntimeFieldInfo); + Debug.Assert(field is FieldBuilder || field is RuntimeFieldInfo); m_field = field; m_type = type; @@ -258,7 +259,7 @@ namespace System.Reflection.Emit return fb.MetadataTokenInternal; else { - Contract.Assert(m_field is RuntimeFieldInfo); + Debug.Assert(m_field is RuntimeFieldInfo); return m_field.MetadataToken; } } diff --git a/src/mscorlib/src/System/Reflection/EventInfo.cs b/src/mscorlib/src/System/Reflection/EventInfo.cs index 3fd1951..0eabb9d 100644 --- a/src/mscorlib/src/System/Reflection/EventInfo.cs +++ b/src/mscorlib/src/System/Reflection/EventInfo.cs @@ -19,9 +19,6 @@ namespace System.Reflection [Serializable] [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_EventInfo))] -#pragma warning disable 618 - [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")] -#pragma warning restore 618 [System.Runtime.InteropServices.ComVisible(true)] public abstract class EventInfo : MemberInfo, _EventInfo { @@ -123,7 +120,7 @@ namespace System.Reflection throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotSupportedOnWinRTEvent")); // Must be a normal non-WinRT event - Contract.Assert(addMethod.ReturnType == typeof(void)); + Debug.Assert(addMethod.ReturnType == typeof(void)); #endif // FEATURE_COMINTEROP addMethod.Invoke(target, new object[] { handler }); @@ -140,13 +137,13 @@ namespace System.Reflection #if FEATURE_COMINTEROP ParameterInfo[] parameters = removeMethod.GetParametersNoCopy(); - Contract.Assert(parameters != null && parameters.Length == 1); + Debug.Assert(parameters != null && parameters.Length == 1); if (parameters[0].ParameterType == typeof(System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken)) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotSupportedOnWinRTEvent")); // Must be a normal non-WinRT event - Contract.Assert(parameters[0].ParameterType.BaseType == typeof(MulticastDelegate)); + Debug.Assert(parameters[0].ParameterType.BaseType == typeof(MulticastDelegate)); #endif // FEATURE_COMINTEROP removeMethod.Invoke(target, new object[] { handler }); @@ -190,35 +187,6 @@ namespace System.Reflection } } #endregion - -#if !FEATURE_CORECLR - Type _EventInfo.GetType() - { - return base.GetType(); - } - - void _EventInfo.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _EventInfo.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _EventInfo.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - // If you implement this method, make sure to include _EventInfo.Invoke in VM\DangerousAPIs.h and - // include _EventInfo in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp. - void _EventInfo.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif } [Serializable] @@ -228,7 +196,6 @@ namespace System.Reflection private int m_token; private EventAttributes m_flags; private string m_name; - [System.Security.SecurityCritical] private void* m_utf8name; private RuntimeTypeCache m_reflectedTypeCache; private RuntimeMethodInfo m_addMethod; @@ -244,12 +211,11 @@ namespace System.Reflection { // Used for dummy head node during population } - [System.Security.SecurityCritical] // auto-generated internal RuntimeEventInfo(int tkEvent, RuntimeType declaredType, RuntimeTypeCache reflectedTypeCache, out bool isPrivate) { Contract.Requires(declaredType != null); Contract.Requires(reflectedTypeCache != null); - Contract.Assert(!reflectedTypeCache.IsGlobal); + Debug.Assert(!reflectedTypeCache.IsGlobal); MetadataImport scope = declaredType.GetRuntimeModule().MetadataImport; @@ -305,28 +271,27 @@ namespace System.Reflection public override Object[] GetCustomAttributes(Type attributeType, bool inherit) { if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),nameof(attributeType)); return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType); } - [System.Security.SecuritySafeCritical] // auto-generated public override bool IsDefined(Type attributeType, bool inherit) { if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),nameof(attributeType)); return CustomAttribute.IsDefined(this, attributeRuntimeType); } @@ -341,7 +306,6 @@ namespace System.Reflection public override MemberTypes MemberType { get { return MemberTypes.Event; } } public override String Name { - [System.Security.SecuritySafeCritical] // auto-generated get { if (m_name == null) @@ -373,11 +337,10 @@ namespace System.Reflection #endregion #region ISerializable - [System.Security.SecurityCritical] // auto-generated_required public void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); MemberInfoSerializationHolder.GetSerializationInfo( diff --git a/src/mscorlib/src/System/Reflection/FieldInfo.cs b/src/mscorlib/src/System/Reflection/FieldInfo.cs index c6a44d4..e61207a 100644 --- a/src/mscorlib/src/System/Reflection/FieldInfo.cs +++ b/src/mscorlib/src/System/Reflection/FieldInfo.cs @@ -15,9 +15,6 @@ namespace System.Reflection using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; -#if FEATURE_REMOTING - using System.Runtime.Remoting.Metadata; -#endif //FEATURE_REMOTING using System.Runtime.Serialization; using System.Security.Permissions; using System.Threading; @@ -26,9 +23,6 @@ namespace System.Reflection [Serializable] [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_FieldInfo))] -#pragma warning disable 618 - [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")] -#pragma warning restore 618 [System.Runtime.InteropServices.ComVisible(true)] public abstract class FieldInfo : MemberInfo, _FieldInfo { @@ -36,7 +30,7 @@ namespace System.Reflection public static FieldInfo GetFieldFromHandle(RuntimeFieldHandle handle) { if (handle.IsNullHandle()) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHandle"), "handle"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHandle"), nameof(handle)); FieldInfo f = RuntimeType.GetFieldInfo(handle.GetRuntimeFieldInfo()); @@ -186,35 +180,6 @@ namespace System.Reflection } #endregion - -#if !FEATURE_CORECLR - Type _FieldInfo.GetType() - { - return base.GetType(); - } - - void _FieldInfo.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _FieldInfo.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _FieldInfo.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - // If you implement this method, make sure to include _FieldInfo.Invoke in VM\DangerousAPIs.h and - // include _FieldInfo in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp. - void _FieldInfo.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif } [Serializable] @@ -239,36 +204,6 @@ namespace System.Reflection } #endregion -#if FEATURE_REMOTING - #region Legacy Remoting Cache - // The size of CachedData is accounted for by BaseObjectWithCachedData in object.h. - // This member is currently being used by Remoting for caching remoting data. If you - // need to cache data here, talk to the Remoting team to work out a mechanism, so that - // both caching systems can happily work together. - private RemotingFieldCachedData m_cachedData; - - internal RemotingFieldCachedData RemotingCache - { - get - { - // This grabs an internal copy of m_cachedData and uses - // that instead of looking at m_cachedData directly because - // the cache may get cleared asynchronously. This prevents - // us from having to take a lock. - RemotingFieldCachedData cache = m_cachedData; - if (cache == null) - { - cache = new RemotingFieldCachedData(this); - RemotingFieldCachedData ret = Interlocked.CompareExchange(ref m_cachedData, cache, null); - if (ret != null) - cache = ret; - } - return cache; - } - } - #endregion -#endif //FEATURE_REMOTING - #region NonPublic Members internal BindingFlags BindingFlags { get { return m_bindingFlags; } } private RuntimeType ReflectedTypeInternal @@ -325,28 +260,27 @@ namespace System.Reflection public override Object[] GetCustomAttributes(Type attributeType, bool inherit) { if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),nameof(attributeType)); return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType); } - [System.Security.SecuritySafeCritical] // auto-generated public override bool IsDefined(Type attributeType, bool inherit) { if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),nameof(attributeType)); return CustomAttribute.IsDefined(this, attributeRuntimeType); } @@ -362,11 +296,10 @@ namespace System.Reflection #endregion #region ISerializable Implementation - [System.Security.SecurityCritical] // auto-generated public void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); MemberInfoSerializationHolder.GetSerializationInfo( info, @@ -382,7 +315,6 @@ namespace System.Reflection internal unsafe sealed class RtFieldInfo : RuntimeFieldInfo, IRuntimeFieldInfo { #region FCalls - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] static private extern void PerformVisibilityCheckOnField(IntPtr field, Object target, RuntimeType declaringType, FieldAttributes attr, uint invocationFlags); #endregion @@ -480,7 +412,6 @@ namespace System.Reflection private RuntimeAssembly GetRuntimeAssembly() { return m_declaringType.GetRuntimeAssembly(); } #region Constructor - [System.Security.SecurityCritical] // auto-generated internal RtFieldInfo( RuntimeFieldHandleInternal handle, RuntimeType declaringType, RuntimeTypeCache reflectedTypeCache, BindingFlags bindingFlags) : base(reflectedTypeCache, declaringType, bindingFlags) @@ -493,7 +424,6 @@ namespace System.Reflection #region Private Members RuntimeFieldHandleInternal IRuntimeFieldInfo.Value { - [System.Security.SecuritySafeCritical] get { return new RuntimeFieldHandleInternal(m_fieldHandle); @@ -535,7 +465,6 @@ namespace System.Reflection return m.m_fieldHandle == m_fieldHandle; } - [System.Security.SecurityCritical] [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] internal void InternalSetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture, ref StackCrawlMark stackMark) @@ -592,7 +521,6 @@ namespace System.Reflection // InternalSetValue() instead. When the caller needs to perform // consistency checks they should call CheckConsistency() before // calling this method. - [System.Security.SecurityCritical] // auto-generated [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] internal void UnsafeSetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture) @@ -614,7 +542,6 @@ namespace System.Reflection } } - [System.Security.SecuritySafeCritical] [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] internal Object InternalGetValue(Object obj, ref StackCrawlMark stackMark) @@ -657,7 +584,6 @@ namespace System.Reflection // InternalGetValue() instead. When the caller needs to perform // consistency checks they should call CheckConsistency() before // calling this method. - [System.Security.SecurityCritical] [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] internal Object UnsafeGetValue(Object obj) @@ -685,7 +611,6 @@ namespace System.Reflection #region MemberInfo Overrides public override String Name { - [System.Security.SecuritySafeCritical] // auto-generated get { if (m_name == null) @@ -705,11 +630,9 @@ namespace System.Reflection public override int MetadataToken { - [System.Security.SecuritySafeCritical] // auto-generated get { return RuntimeFieldHandle.GetToken(this); } } - [System.Security.SecuritySafeCritical] // auto-generated internal override RuntimeModule GetRuntimeModule() { return RuntimeTypeHandle.GetModule(RuntimeFieldHandle.GetApproxDeclaringType(this)); @@ -726,7 +649,6 @@ namespace System.Reflection public override object GetRawConstantValue() { throw new InvalidOperationException(); } - [System.Security.SecuritySafeCritical] // auto-generated [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] public override Object GetValueDirect(TypedReference obj) @@ -742,7 +664,6 @@ namespace System.Reflection } } - [System.Security.SecuritySafeCritical] // auto-generated [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] public override void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture) @@ -751,7 +672,6 @@ namespace System.Reflection InternalSetValue(obj, value, invokeAttr, binder, culture, ref stackMark); } - [System.Security.SecuritySafeCritical] // auto-generated [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] public override void SetValueDirect(TypedReference obj, Object value) @@ -793,7 +713,6 @@ namespace System.Reflection public override Type FieldType { - [System.Security.SecuritySafeCritical] // auto-generated get { if (m_fieldType == null) @@ -803,13 +722,11 @@ namespace System.Reflection } } - [System.Security.SecuritySafeCritical] // auto-generated public override Type[] GetRequiredCustomModifiers() { return new Signature(this, m_declaringType).GetCustomModifiers(1, true); } - [System.Security.SecuritySafeCritical] // auto-generated public override Type[] GetOptionalCustomModifiers() { return new Signature(this, m_declaringType).GetCustomModifiers(1, false); @@ -857,7 +774,6 @@ namespace System.Reflection #region MemberInfo Overrides public override String Name { - [System.Security.SecuritySafeCritical] // auto-generated get { if (m_name == null) @@ -902,7 +818,6 @@ namespace System.Reflection public unsafe override Object GetRawConstantValue() { return GetValue(true); } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe Object GetValue(bool raw) { // Cannot cache these because they could be user defined non-agile enumerations @@ -924,7 +839,6 @@ namespace System.Reflection public override Type FieldType { - [System.Security.SecuritySafeCritical] // auto-generated get { if (m_fieldType == null) diff --git a/src/mscorlib/src/System/Reflection/IntrospectionExtensions.cs b/src/mscorlib/src/System/Reflection/IntrospectionExtensions.cs index ce2630a..49819a9 100644 --- a/src/mscorlib/src/System/Reflection/IntrospectionExtensions.cs +++ b/src/mscorlib/src/System/Reflection/IntrospectionExtensions.cs @@ -8,28 +8,21 @@ ** ** ** -** Purpose: go from type to type info +** Purpose: Get the underlying TypeInfo from a Type ** ** =============================================================================*/ - namespace System.Reflection { - using System.Reflection; - public static class IntrospectionExtensions { - public static TypeInfo GetTypeInfo(this Type type){ - if(type == null){ - throw new ArgumentNullException("type"); - } + public static TypeInfo GetTypeInfo(this Type type) + { + if (type == null) + throw new ArgumentNullException(nameof(type)); + var rcType=(IReflectableType)type; - if(rcType==null){ - return null; - }else{ - return rcType.GetTypeInfo(); - } - } + return rcType.GetTypeInfo(); + } } } - diff --git a/src/mscorlib/src/System/Reflection/InvalidFilterCriteriaException.cs b/src/mscorlib/src/System/Reflection/InvalidFilterCriteriaException.cs index 7c980da..fa95e37 100644 --- a/src/mscorlib/src/System/Reflection/InvalidFilterCriteriaException.cs +++ b/src/mscorlib/src/System/Reflection/InvalidFilterCriteriaException.cs @@ -19,11 +19,7 @@ namespace System.Reflection { using ApplicationException = System.ApplicationException; [Serializable] [System.Runtime.InteropServices.ComVisible(true)] -#if FEATURE_CORECLR - public class InvalidFilterCriteriaException : Exception { -#else public class InvalidFilterCriteriaException : ApplicationException { -#endif // FEATURE_CORECLR public InvalidFilterCriteriaException() : base(Environment.GetResourceString("Arg_InvalidFilterCriteriaException")) { SetErrorCode(__HResults.COR_E_INVALIDFILTERCRITERIA); diff --git a/src/mscorlib/src/System/Reflection/LoaderAllocator.cs b/src/mscorlib/src/System/Reflection/LoaderAllocator.cs index a8b4b0c..7c6c6bd 100644 --- a/src/mscorlib/src/System/Reflection/LoaderAllocator.cs +++ b/src/mscorlib/src/System/Reflection/LoaderAllocator.cs @@ -34,11 +34,9 @@ namespace System.Reflection internal IntPtr m_nativeLoaderAllocator; [SuppressUnmanagedCodeSecurity] - [SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] private static extern bool Destroy(IntPtr nativeLoaderAllocator); - [SecuritySafeCritical] ~LoaderAllocatorScout() { if (m_nativeLoaderAllocator.IsNull()) diff --git a/src/mscorlib/src/System/Reflection/MdConstant.cs b/src/mscorlib/src/System/Reflection/MdConstant.cs index 1941736..e59244f 100644 --- a/src/mscorlib/src/System/Reflection/MdConstant.cs +++ b/src/mscorlib/src/System/Reflection/MdConstant.cs @@ -10,7 +10,6 @@ namespace System.Reflection internal static class MdConstant { - [System.Security.SecurityCritical] // auto-generated public static unsafe Object GetValue(MetadataImport scope, int token, RuntimeTypeHandle fieldTypeHandle, bool raw) { CorElementType corElementType = 0; diff --git a/src/mscorlib/src/System/Reflection/MdImport.cs b/src/mscorlib/src/System/Reflection/MdImport.cs index 3bf8edd..bbdf948 100644 --- a/src/mscorlib/src/System/Reflection/MdImport.cs +++ b/src/mscorlib/src/System/Reflection/MdImport.cs @@ -174,7 +174,6 @@ namespace System.Reflection public int Length { get { return m_length; } } public byte this[int index] { - [System.Security.SecuritySafeCritical] // auto-generated get { if (index < 0 || index >= m_length) @@ -269,7 +268,6 @@ namespace System.Reflection public int this[int index] { - [System.Security.SecurityCritical] get { Contract.Requires(0 <= index && index < Length); @@ -312,12 +310,10 @@ namespace System.Reflection #endregion #region Static Members - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void _GetMarshalAs(IntPtr pNativeType, int cNativeType, out int unmanagedType, out int safeArraySubType, out string safeArrayUserDefinedSubType, out int arraySubType, out int sizeParamIndex, out int sizeConst, out string marshalType, out string marshalCookie, out int iidParamIndex); - [System.Security.SecurityCritical] // auto-generated internal static void GetMarshalAs(ConstArray nativeType, out UnmanagedType unmanagedType, out VarEnum safeArraySubType, out string safeArrayUserDefinedSubType, out UnmanagedType arraySubType, out int sizeParamIndex, out int sizeConst, out string marshalType, out string marshalCookie, @@ -351,56 +347,46 @@ namespace System.Reflection #endregion #region FCalls - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute (MethodImplOptions.InternalCall)] private unsafe static extern void _Enum(IntPtr scope, int type, int parent, out MetadataEnumResult result); - [System.Security.SecurityCritical] // auto-generated public unsafe void Enum(MetadataTokenType type, int parent, out MetadataEnumResult result) { _Enum(m_metadataImport2, (int)type, parent, out result); } - [System.Security.SecurityCritical] // auto-generated public unsafe void EnumNestedTypes(int mdTypeDef, out MetadataEnumResult result) { Enum(MetadataTokenType.TypeDef, mdTypeDef, out result); } - [System.Security.SecurityCritical] // auto-generated public unsafe void EnumCustomAttributes(int mdToken, out MetadataEnumResult result) { Enum(MetadataTokenType.CustomAttribute, mdToken, out result); } - [System.Security.SecurityCritical] // auto-generated public unsafe void EnumParams(int mdMethodDef, out MetadataEnumResult result) { Enum(MetadataTokenType.ParamDef, mdMethodDef, out result); } - [System.Security.SecurityCritical] // auto-generated public unsafe void EnumFields(int mdTypeDef, out MetadataEnumResult result) { Enum(MetadataTokenType.FieldDef, mdTypeDef, out result); } - [System.Security.SecurityCritical] // auto-generated public unsafe void EnumProperties(int mdTypeDef, out MetadataEnumResult result) { Enum(MetadataTokenType.Property, mdTypeDef, out result); } - [System.Security.SecurityCritical] // auto-generated public unsafe void EnumEvents(int mdTypeDef, out MetadataEnumResult result) { Enum(MetadataTokenType.Event, mdTypeDef, out result); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute (MethodImplOptions.InternalCall)] private static extern String _GetDefaultValue(IntPtr scope, int mdToken, out long value, out int length, out int corElementType); - [System.Security.SecurityCritical] // auto-generated public String GetDefaultValue(int mdToken, out long value, out int length, out CorElementType corElementType) { int _corElementType; @@ -410,10 +396,8 @@ namespace System.Reflection return stringVal; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute (MethodImplOptions.InternalCall)] private static unsafe extern void _GetUserString(IntPtr scope, int mdToken, void** name, out int length); - [System.Security.SecurityCritical] // auto-generated public unsafe String GetUserString(int mdToken) { void* name; @@ -436,10 +420,8 @@ namespace System.Reflection return new String(c); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute (MethodImplOptions.InternalCall)] private static unsafe extern void _GetName(IntPtr scope, int mdToken, void** name); - [System.Security.SecurityCritical] // auto-generated public unsafe Utf8String GetName(int mdToken) { void* name; @@ -448,10 +430,8 @@ namespace System.Reflection return new Utf8String(name); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute (MethodImplOptions.InternalCall)] private static unsafe extern void _GetNamespace(IntPtr scope, int mdToken, void** namesp); - [System.Security.SecurityCritical] // auto-generated public unsafe Utf8String GetNamespace(int mdToken) { void* namesp; @@ -460,10 +440,8 @@ namespace System.Reflection return new Utf8String(namesp); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute (MethodImplOptions.InternalCall)] private unsafe static extern void _GetEventProps(IntPtr scope, int mdToken, void** name, out int eventAttributes); - [System.Security.SecurityCritical] // auto-generated public unsafe void GetEventProps(int mdToken, out void* name, out EventAttributes eventAttributes) { int _eventAttributes; @@ -473,10 +451,8 @@ namespace System.Reflection eventAttributes = (EventAttributes)_eventAttributes; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute (MethodImplOptions.InternalCall)] private static extern void _GetFieldDefProps(IntPtr scope, int mdToken, out int fieldAttributes); - [System.Security.SecurityCritical] // auto-generated public void GetFieldDefProps(int mdToken, out FieldAttributes fieldAttributes) { int _fieldAttributes; @@ -484,11 +460,9 @@ namespace System.Reflection fieldAttributes = (FieldAttributes)_fieldAttributes; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute (MethodImplOptions.InternalCall)] private unsafe static extern void _GetPropertyProps(IntPtr scope, int mdToken, void** name, out int propertyAttributes, out ConstArray signature); - [System.Security.SecurityCritical] // auto-generated public unsafe void GetPropertyProps(int mdToken, out void* name, out PropertyAttributes propertyAttributes, out ConstArray signature) { int _propertyAttributes; @@ -498,11 +472,9 @@ namespace System.Reflection propertyAttributes = (PropertyAttributes)_propertyAttributes; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute (MethodImplOptions.InternalCall)] private static extern void _GetParentToken(IntPtr scope, int mdToken, out int tkParent); - [System.Security.SecurityCritical] // auto-generated public int GetParentToken(int tkToken) { int tkParent; @@ -510,11 +482,9 @@ namespace System.Reflection return tkParent; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void _GetParamDefProps(IntPtr scope, int parameterToken, out int sequence, out int attributes); - [System.Security.SecurityCritical] // auto-generated public void GetParamDefProps(int parameterToken, out int sequence, out ParameterAttributes attributes) { int _attributes; @@ -524,13 +494,11 @@ namespace System.Reflection attributes = (ParameterAttributes)_attributes; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void _GetGenericParamProps(IntPtr scope, int genericParameter, out int flags); - [System.Security.SecurityCritical] // auto-generated public void GetGenericParamProps( int genericParameter, out GenericParameterAttributes attributes) @@ -540,12 +508,10 @@ namespace System.Reflection attributes = (GenericParameterAttributes)_attributes; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void _GetScopeProps(IntPtr scope, out Guid mvid); - [System.Security.SecurityCritical] // auto-generated public void GetScopeProps( out Guid mvid) { @@ -553,7 +519,6 @@ namespace System.Reflection } - [System.Security.SecurityCritical] // auto-generated public ConstArray GetMethodSignature(MetadataToken token) { if (token.IsMemberRef) @@ -562,13 +527,11 @@ namespace System.Reflection return GetSigOfMethodDef(token); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void _GetSigOfMethodDef(IntPtr scope, int methodToken, ref ConstArray signature); - [System.Security.SecurityCritical] // auto-generated public ConstArray GetSigOfMethodDef(int methodToken) { ConstArray signature = new ConstArray(); @@ -578,13 +541,11 @@ namespace System.Reflection return signature; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void _GetSignatureFromToken(IntPtr scope, int methodToken, ref ConstArray signature); - [System.Security.SecurityCritical] // auto-generated public ConstArray GetSignatureFromToken(int token) { ConstArray signature = new ConstArray(); @@ -594,13 +555,11 @@ namespace System.Reflection return signature; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void _GetMemberRefProps(IntPtr scope, int memberTokenRef, out ConstArray signature); - [System.Security.SecurityCritical] // auto-generated public ConstArray GetMemberRefProps(int memberTokenRef) { ConstArray signature = new ConstArray(); @@ -610,14 +569,12 @@ namespace System.Reflection return signature; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void _GetCustomAttributeProps(IntPtr scope, int customAttributeToken, out int constructorToken, out ConstArray signature); - [System.Security.SecurityCritical] // auto-generated public void GetCustomAttributeProps( int customAttributeToken, out int constructorToken, @@ -627,11 +584,9 @@ namespace System.Reflection out constructorToken, out signature); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void _GetClassLayout(IntPtr scope, int typeTokenDef, out int packSize, out int classSize); - [System.Security.SecurityCritical] // auto-generated public void GetClassLayout( int typeTokenDef, out int packSize, @@ -640,11 +595,9 @@ namespace System.Reflection _GetClassLayout(m_metadataImport2, typeTokenDef, out packSize, out classSize); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool _GetFieldOffset(IntPtr scope, int typeTokenDef, int fieldTokenDef, out int offset); - [System.Security.SecurityCritical] // auto-generated public bool GetFieldOffset( int typeTokenDef, int fieldTokenDef, @@ -653,13 +606,11 @@ namespace System.Reflection return _GetFieldOffset(m_metadataImport2, typeTokenDef, fieldTokenDef, out offset); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void _GetSigOfFieldDef(IntPtr scope, int fieldToken, ref ConstArray fieldMarshal); - [System.Security.SecurityCritical] // auto-generated public ConstArray GetSigOfFieldDef(int fieldToken) { ConstArray fieldMarshal = new ConstArray(); @@ -669,13 +620,11 @@ namespace System.Reflection return fieldMarshal; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void _GetFieldMarshal(IntPtr scope, int fieldToken, ref ConstArray fieldMarshal); - [System.Security.SecurityCritical] // auto-generated public ConstArray GetFieldMarshal(int fieldToken) { ConstArray fieldMarshal = new ConstArray(); @@ -685,7 +634,6 @@ namespace System.Reflection return fieldMarshal; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private unsafe static extern void _GetPInvokeMap(IntPtr scope, int token, @@ -693,7 +641,6 @@ namespace System.Reflection void** importName, void** importDll); - [System.Security.SecurityCritical] // auto-generated public unsafe void GetPInvokeMap( int token, out PInvokeAttributes attributes, @@ -709,10 +656,8 @@ namespace System.Reflection attributes = (PInvokeAttributes)_attributes; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool _IsValidToken(IntPtr scope, int token); - [System.Security.SecurityCritical] // auto-generated public bool IsValidToken(int token) { return _IsValidToken(m_metadataImport2, token); diff --git a/src/mscorlib/src/System/Reflection/MemberInfo.cs b/src/mscorlib/src/System/Reflection/MemberInfo.cs index 248c78b..96a89ad 100644 --- a/src/mscorlib/src/System/Reflection/MemberInfo.cs +++ b/src/mscorlib/src/System/Reflection/MemberInfo.cs @@ -16,9 +16,6 @@ namespace System.Reflection [Serializable] [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_MemberInfo))] -#pragma warning disable 618 - [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")] -#pragma warning restore 618 [System.Runtime.InteropServices.ComVisible(true)] public abstract class MemberInfo : ICustomAttributeProvider, _MemberInfo { @@ -116,33 +113,5 @@ namespace System.Reflection { return base.GetHashCode(); } - -#if !FEATURE_CORECLR - // this method is required so Object.GetType is not made final virtual by the compiler - Type _MemberInfo.GetType() - { - return base.GetType(); - } - - void _MemberInfo.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _MemberInfo.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _MemberInfo.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - void _MemberInfo.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif } } diff --git a/src/mscorlib/src/System/Reflection/MemberInfoSerializationHolder.cs b/src/mscorlib/src/System/Reflection/MemberInfoSerializationHolder.cs index c1b4ee5..20ff376 100644 --- a/src/mscorlib/src/System/Reflection/MemberInfoSerializationHolder.cs +++ b/src/mscorlib/src/System/Reflection/MemberInfoSerializationHolder.cs @@ -31,7 +31,7 @@ namespace System.Reflection Type[] genericArguments) { if (info == null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); String assemblyName = reflectedClass.Module.Assembly.FullName; @@ -65,7 +65,7 @@ namespace System.Reflection internal MemberInfoSerializationHolder(SerializationInfo info, StreamingContext context) { if (info == null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); String assemblyName = info.GetString("AssemblyName"); @@ -86,7 +86,6 @@ namespace System.Reflection #endregion #region ISerializable - [System.Security.SecurityCritical] // auto-generated public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_Method)); @@ -94,7 +93,6 @@ namespace System.Reflection #endregion #region IObjectReference - [System.Security.SecurityCritical] // auto-generated public virtual Object GetRealObject(StreamingContext context) { if (m_memberName == null || m_reflectedType == null || m_memberType == 0) diff --git a/src/mscorlib/src/System/Reflection/Metadata/AssemblyExtensions.cs b/src/mscorlib/src/System/Reflection/Metadata/AssemblyExtensions.cs index dd5d69b..388e4f4 100644 --- a/src/mscorlib/src/System/Reflection/Metadata/AssemblyExtensions.cs +++ b/src/mscorlib/src/System/Reflection/Metadata/AssemblyExtensions.cs @@ -11,7 +11,6 @@ namespace System.Reflection.Metadata public static class AssemblyExtensions { [DllImport(JitHelpers.QCall)] - [SecurityCritical] // unsafe method [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private unsafe static extern bool InternalTryGetRawMetadata(RuntimeAssembly assembly, ref byte* blob, ref int length); @@ -24,12 +23,11 @@ namespace System.Reflection.Metadata // associated, is alive. The caller is responsible for keeping the assembly object alive while accessing the // metadata blob. [CLSCompliant(false)] // out byte* blob - [SecurityCritical] // unsafe method public unsafe static bool TryGetRawMetadata(this Assembly assembly, out byte* blob, out int length) { if (assembly == null) { - throw new ArgumentNullException("assembly"); + throw new ArgumentNullException(nameof(assembly)); } blob = null; diff --git a/src/mscorlib/src/System/Reflection/MethodBase.cs b/src/mscorlib/src/System/Reflection/MethodBase.cs index 68363bf..644a1ac 100644 --- a/src/mscorlib/src/System/Reflection/MethodBase.cs +++ b/src/mscorlib/src/System/Reflection/MethodBase.cs @@ -50,9 +50,6 @@ namespace System.Reflection [Serializable] [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_MethodBase))] -#pragma warning disable 618 - [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")] -#pragma warning restore 618 [System.Runtime.InteropServices.ComVisible(true)] public abstract class MethodBase : MemberInfo, _MethodBase { @@ -131,7 +128,6 @@ namespace System.Reflection #region Internal Members // used by EE - [System.Security.SecurityCritical] private IntPtr GetMethodDesc() { return MethodHandle.Value; } #if FEATURE_APPX @@ -243,7 +239,6 @@ namespace System.Reflection } } - [System.Security.SecuritySafeCritical] #pragma warning disable 618 [ReflectionPermissionAttribute(SecurityAction.Demand, Flags=ReflectionPermissionFlag.MemberAccess)] #pragma warning restore 618 @@ -329,7 +324,6 @@ namespace System.Reflection return parameterTypes; } - [System.Security.SecuritySafeCritical] internal Object[] CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig) { @@ -347,7 +341,7 @@ namespace System.Reflection if (p == null) p = GetParametersNoCopy(); if (p[i].DefaultValue == System.DBNull.Value) - throw new ArgumentException(Environment.GetResourceString("Arg_VarMissNull"),"parameters"); + throw new ArgumentException(Environment.GetResourceString("Arg_VarMissNull"),nameof(parameters)); arg = p[i].DefaultValue; } copyOfParameters[i] = argRT.CheckValue(arg, binder, culture, invokeAttr); @@ -356,47 +350,5 @@ namespace System.Reflection return copyOfParameters; } #endregion - - #region _MethodBase Implementation -#if !FEATURE_CORECLR - Type _MethodBase.GetType() { return base.GetType(); } - bool _MethodBase.IsPublic { get { return IsPublic; } } - bool _MethodBase.IsPrivate { get { return IsPrivate; } } - bool _MethodBase.IsFamily { get { return IsFamily; } } - bool _MethodBase.IsAssembly { get { return IsAssembly; } } - bool _MethodBase.IsFamilyAndAssembly { get { return IsFamilyAndAssembly; } } - bool _MethodBase.IsFamilyOrAssembly { get { return IsFamilyOrAssembly; } } - bool _MethodBase.IsStatic { get { return IsStatic; } } - bool _MethodBase.IsFinal { get { return IsFinal; } } - bool _MethodBase.IsVirtual { get { return IsVirtual; } } - bool _MethodBase.IsHideBySig { get { return IsHideBySig; } } - bool _MethodBase.IsAbstract { get { return IsAbstract; } } - bool _MethodBase.IsSpecialName { get { return IsSpecialName; } } - bool _MethodBase.IsConstructor { get { return IsConstructor; } } - - void _MethodBase.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _MethodBase.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _MethodBase.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - // If you implement this method, make sure to include _MethodBase.Invoke in VM\DangerousAPIs.h and - // include _MethodBase in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp. - void _MethodBase.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif - #endregion } - } diff --git a/src/mscorlib/src/System/Reflection/MethodBody.cs b/src/mscorlib/src/System/Reflection/MethodBody.cs index 81d7a9e..4634623 100644 --- a/src/mscorlib/src/System/Reflection/MethodBody.cs +++ b/src/mscorlib/src/System/Reflection/MethodBody.cs @@ -7,6 +7,7 @@ using System; using System.Globalization; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; namespace System.Reflection @@ -160,7 +161,7 @@ namespace System.Reflection #endregion #region Public Members - public virtual Type LocalType { get { Contract.Assert(m_type != null, "type must be set!"); return m_type; } } + public virtual Type LocalType { get { Debug.Assert(m_type != null, "type must be set!"); return m_type; } } public virtual bool IsPinned { get { return m_isPinned != 0; } } public virtual int LocalIndex { get { return m_localIndex; } } #endregion diff --git a/src/mscorlib/src/System/Reflection/MethodInfo.cs b/src/mscorlib/src/System/Reflection/MethodInfo.cs index eeb5a81..39387b1 100644 --- a/src/mscorlib/src/System/Reflection/MethodInfo.cs +++ b/src/mscorlib/src/System/Reflection/MethodInfo.cs @@ -14,9 +14,6 @@ namespace System.Reflection using System.Runtime; using System.Runtime.InteropServices; using System.Runtime.ConstrainedExecution; -#if FEATURE_REMOTING - using System.Runtime.Remoting.Metadata; -#endif //FEATURE_REMOTING using System.Runtime.Serialization; using System.Security; using System.Security.Permissions; @@ -29,9 +26,6 @@ namespace System.Reflection [Serializable] [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_MethodInfo))] -#pragma warning disable 618 - [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")] -#pragma warning restore 618 [System.Runtime.InteropServices.ComVisible(true)] public abstract class MethodInfo : MethodBase, _MethodInfo { @@ -91,35 +85,6 @@ namespace System.Reflection public virtual Delegate CreateDelegate(Type delegateType) { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride")); } public virtual Delegate CreateDelegate(Type delegateType, Object target) { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride")); } #endregion - -#if !FEATURE_CORECLR - Type _MethodInfo.GetType() - { - return base.GetType(); - } - - void _MethodInfo.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _MethodInfo.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _MethodInfo.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - // If you implement this method, make sure to include _MethodInfo.Invoke in VM\DangerousAPIs.h and - // include _MethodInfo in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp. - void _MethodInfo.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif } [Serializable] @@ -180,7 +145,6 @@ namespace System.Reflection internal INVOCATION_FLAGS InvocationFlags { - [System.Security.SecuritySafeCritical] get { if ((m_invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0) @@ -243,15 +207,14 @@ namespace System.Reflection #endregion #region Constructor - [System.Security.SecurityCritical] // auto-generated internal RuntimeMethodInfo( RuntimeMethodHandleInternal handle, RuntimeType declaringType, RuntimeTypeCache reflectedTypeCache, MethodAttributes methodAttributes, BindingFlags bindingFlags, object keepalive) { Contract.Ensures(!m_handle.IsNull()); - Contract.Assert(!handle.IsNullHandle()); - Contract.Assert(methodAttributes == RuntimeMethodHandle.GetAttributes(handle)); + Debug.Assert(!handle.IsNullHandle()); + Debug.Assert(methodAttributes == RuntimeMethodHandle.GetAttributes(handle)); m_bindingFlags = bindingFlags; m_declaringType = declaringType; @@ -262,40 +225,9 @@ namespace System.Reflection } #endregion -#if FEATURE_REMOTING - #region Legacy Remoting Cache - // The size of CachedData is accounted for by BaseObjectWithCachedData in object.h. - // This member is currently being used by Remoting for caching remoting data. If you - // need to cache data here, talk to the Remoting team to work out a mechanism, so that - // both caching systems can happily work together. - private RemotingMethodCachedData m_cachedData; - - internal RemotingMethodCachedData RemotingCache - { - get - { - // This grabs an internal copy of m_cachedData and uses - // that instead of looking at m_cachedData directly because - // the cache may get cleared asynchronously. This prevents - // us from having to take a lock. - RemotingMethodCachedData cache = m_cachedData; - if (cache == null) - { - cache = new RemotingMethodCachedData(this); - RemotingMethodCachedData ret = Interlocked.CompareExchange(ref m_cachedData, cache, null); - if (ret != null) - cache = ret; - } - return cache; - } - } - #endregion -#endif //FEATURE_REMOTING - #region Private Methods RuntimeMethodHandleInternal IRuntimeMethodInfo.Value { - [System.Security.SecuritySafeCritical] get { return new RuntimeMethodHandleInternal(m_handle); @@ -310,7 +242,6 @@ namespace System.Reflection } } - [System.Security.SecurityCritical] // auto-generated private ParameterInfo[] FetchNonReturnParameters() { if (m_parameters == null) @@ -319,7 +250,6 @@ namespace System.Reflection return m_parameters; } - [System.Security.SecurityCritical] // auto-generated private ParameterInfo FetchReturnParameter() { if (m_returnParameter == null) @@ -379,7 +309,6 @@ namespace System.Reflection return new RuntimeMethodHandle(this); } - [System.Security.SecuritySafeCritical] // auto-generated internal RuntimeMethodInfo GetParentDefinition() { if (!IsVirtual || m_declaringType.IsInterface) @@ -424,7 +353,6 @@ namespace System.Reflection return base.GetHashCode(); } - [System.Security.SecuritySafeCritical] // auto-generated public override bool Equals(object obj) { if (!IsGenericMethod) @@ -469,23 +397,21 @@ namespace System.Reflection #endregion #region ICustomAttributeProvider - [System.Security.SecuritySafeCritical] // auto-generated public override Object[] GetCustomAttributes(bool inherit) { return CustomAttribute.GetCustomAttributes(this, typeof(object) as RuntimeType as RuntimeType, inherit); } - [System.Security.SecuritySafeCritical] // auto-generated public override Object[] GetCustomAttributes(Type attributeType, bool inherit) { if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),nameof(attributeType)); return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType, inherit); } @@ -493,13 +419,13 @@ namespace System.Reflection public override bool IsDefined(Type attributeType, bool inherit) { if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),nameof(attributeType)); return CustomAttribute.IsDefined(this, attributeRuntimeType, inherit); } @@ -513,7 +439,6 @@ namespace System.Reflection #region MemberInfo Overrides public override String Name { - [System.Security.SecuritySafeCritical] // auto-generated get { if (m_name == null) @@ -548,7 +473,6 @@ namespace System.Reflection public override MemberTypes MemberType { get { return MemberTypes.Method; } } public override int MetadataToken { - [System.Security.SecuritySafeCritical] // auto-generated get { return RuntimeMethodHandle.GetMethodDef(this); } } public override Module Module { get { return GetRuntimeModule(); } } @@ -558,20 +482,19 @@ namespace System.Reflection public override bool IsSecurityCritical { - get { return RuntimeMethodHandle.IsSecurityCritical(this); } + get { return true; } } public override bool IsSecuritySafeCritical { - get { return RuntimeMethodHandle.IsSecuritySafeCritical(this); } + get { return false; } } public override bool IsSecurityTransparent { - get { return RuntimeMethodHandle.IsSecurityTransparent(this); } + get { return false; } } - #endregion +#endregion - #region MethodBase Overrides - [System.Security.SecuritySafeCritical] // auto-generated +#region MethodBase Overrides internal override ParameterInfo[] GetParametersNoCopy() { FetchNonReturnParameters(); @@ -579,7 +502,6 @@ namespace System.Reflection return m_parameters; } - [System.Security.SecuritySafeCritical] // auto-generated [System.Diagnostics.Contracts.Pure] public override ParameterInfo[] GetParameters() { @@ -629,12 +551,6 @@ namespace System.Reflection } } - [System.Security.SecuritySafeCritical] // overrides SafeCritical member -#if !FEATURE_CORECLR -#pragma warning disable 618 - [ReflectionPermissionAttribute(SecurityAction.Demand, Flags = ReflectionPermissionFlag.MemberAccess)] -#pragma warning restore 618 -#endif public override MethodBody GetMethodBody() { MethodBody mb = RuntimeMethodHandle.GetMethodBody(this, ReflectedTypeInternal); @@ -642,9 +558,9 @@ namespace System.Reflection mb.m_methodBase = this; return mb; } - #endregion +#endregion - #region Invocation Logic(On MemberBase) +#region Invocation Logic(On MemberBase) private void CheckConsistency(Object target) { // only test instance methods @@ -660,7 +576,6 @@ namespace System.Reflection } } - [System.Security.SecuritySafeCritical] private void ThrowNoInvokeException() { // method is ReflectionOnly @@ -698,7 +613,6 @@ namespace System.Reflection throw new TargetException(); } - [System.Security.SecuritySafeCritical] [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable @@ -706,7 +620,7 @@ namespace System.Reflection { object[] arguments = InvokeArgumentsCheck(obj, invokeAttr, binder, parameters, culture); - #region Security Check +#region Security Check INVOCATION_FLAGS invocationFlags = InvocationFlags; #if FEATURE_APPX @@ -718,23 +632,11 @@ namespace System.Reflection throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", FullName)); } #endif - -#if !FEATURE_CORECLR - if ((invocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_RISKY_METHOD | INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY)) != 0) - { - if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_RISKY_METHOD) != 0) - CodeAccessPermission.Demand(PermissionType.ReflectionMemberAccess); - - if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY) != 0) - RuntimeMethodHandle.PerformSecurityCheck(obj, this, m_declaringType, (uint)m_invocationFlags); - } -#endif // !FEATURE_CORECLR - #endregion +#endregion return UnsafeInvokeInternal(obj, parameters, arguments); } - [System.Security.SecurityCritical] [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] internal object UnsafeInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) @@ -744,7 +646,6 @@ namespace System.Reflection return UnsafeInvokeInternal(obj, parameters, arguments); } - [System.Security.SecurityCritical] [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] private object UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) @@ -793,9 +694,9 @@ namespace System.Reflection return null; } - #endregion +#endregion - #region MethodInfo Overrides +#region MethodInfo Overrides public override Type ReturnType { get { return Signature.ReturnType; } @@ -808,7 +709,6 @@ namespace System.Reflection public override ParameterInfo ReturnParameter { - [System.Security.SecuritySafeCritical] // auto-generated get { Contract.Ensures(m_returnParameter != null); @@ -818,7 +718,6 @@ namespace System.Reflection } } - [System.Security.SecuritySafeCritical] // auto-generated public override MethodInfo GetBaseDefinition() { if (!IsVirtual || IsStatic || m_declaringType == null || m_declaringType.IsInterface) @@ -844,7 +743,6 @@ namespace System.Reflection return(MethodInfo)RuntimeType.GetMethodBase(baseDeclaringType, baseMethodHandle); } - [System.Security.SecuritySafeCritical] public override Delegate CreateDelegate(Type delegateType) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -864,7 +762,6 @@ namespace System.Reflection ref stackMark); } - [System.Security.SecuritySafeCritical] public override Delegate CreateDelegate(Type delegateType, Object target) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -881,20 +778,19 @@ namespace System.Reflection ref stackMark); } - [System.Security.SecurityCritical] private Delegate CreateDelegateInternal(Type delegateType, Object firstArgument, DelegateBindingFlags bindingFlags, ref StackCrawlMark stackMark) { // Validate the parameters. if (delegateType == null) - throw new ArgumentNullException("delegateType"); + throw new ArgumentNullException(nameof(delegateType)); Contract.EndContractBlock(); RuntimeType rtType = delegateType as RuntimeType; if (rtType == null) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "delegateType"); + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), nameof(delegateType)); if (!rtType.IsDelegate()) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "delegateType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), nameof(delegateType)); Delegate d = Delegate.CreateDelegateInternal(rtType, this, firstArgument, bindingFlags, ref stackMark); if (d == null) @@ -905,14 +801,13 @@ namespace System.Reflection return d; } - #endregion +#endregion - #region Generics - [System.Security.SecuritySafeCritical] // auto-generated +#region Generics public override MethodInfo MakeGenericMethod(params Type[] methodInstantiation) { if (methodInstantiation == null) - throw new ArgumentNullException("methodInstantiation"); + throw new ArgumentNullException(nameof(methodInstantiation)); Contract.EndContractBlock(); RuntimeType[] methodInstantionRuntimeType = new RuntimeType[methodInstantiation.Length]; @@ -1017,14 +912,13 @@ namespace System.Reflection return false; } } - #endregion +#endregion - #region ISerializable Implementation - [System.Security.SecurityCritical] // auto-generated +#region ISerializable Implementation public void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); if (m_reflectedTypeCache.IsGlobal) @@ -1044,9 +938,9 @@ namespace System.Reflection { return ReturnType.FormatTypeName(true) + " " + FormatNameAndSig(true); } - #endregion +#endregion - #region Legacy Internal +#region Legacy Internal internal static MethodBase InternalGetCurrentMethod(ref StackCrawlMark stackMark) { IRuntimeMethodInfo method = RuntimeMethodHandle.GetCurrentMethod(ref stackMark); @@ -1056,6 +950,6 @@ namespace System.Reflection return RuntimeType.GetMethodBase(method); } - #endregion +#endregion } } diff --git a/src/mscorlib/src/System/Reflection/Missing.cs b/src/mscorlib/src/System/Reflection/Missing.cs index 8289193..24bf77b 100644 --- a/src/mscorlib/src/System/Reflection/Missing.cs +++ b/src/mscorlib/src/System/Reflection/Missing.cs @@ -24,11 +24,10 @@ namespace System.Reflection #endregion #region ISerializable - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); UnitySerializationHolder.GetUnitySerializationInfo(info, this); diff --git a/src/mscorlib/src/System/Reflection/Module.cs b/src/mscorlib/src/System/Reflection/Module.cs index 34705a4..b6be38e 100644 --- a/src/mscorlib/src/System/Reflection/Module.cs +++ b/src/mscorlib/src/System/Reflection/Module.cs @@ -59,9 +59,6 @@ namespace System.Reflection [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_Module))] [System.Runtime.InteropServices.ComVisible(true)] -#pragma warning disable 618 - [PermissionSetAttribute(SecurityAction.InheritanceDemand, Unrestricted = true)] -#pragma warning restore 618 public abstract class Module : _Module, ISerializable, ICustomAttributeProvider { #region Static Constructor @@ -274,7 +271,6 @@ namespace System.Reflection } } - [System.Security.SecurityCritical] // auto-generated_required public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { throw new NotImplementedException(); @@ -299,9 +295,6 @@ namespace System.Reflection public virtual String FullyQualifiedName { -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif get { throw new NotImplementedException(); @@ -432,16 +425,16 @@ namespace System.Reflection String name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) { if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); if (types == null) - throw new ArgumentNullException("types"); + throw new ArgumentNullException(nameof(types)); Contract.EndContractBlock(); for (int i = 0; i < types.Length; i++) { if (types[i] == null) - throw new ArgumentNullException("types"); + throw new ArgumentNullException(nameof(types)); } return GetMethodImpl(name, bindingAttr, binder, callConvention, types, modifiers); @@ -450,16 +443,16 @@ namespace System.Reflection public MethodInfo GetMethod(String name, Type[] types) { if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); if (types == null) - throw new ArgumentNullException("types"); + throw new ArgumentNullException(nameof(types)); Contract.EndContractBlock(); for (int i = 0; i < types.Length; i++) { if (types[i] == null) - throw new ArgumentNullException("types"); + throw new ArgumentNullException(nameof(types)); } return GetMethodImpl(name, Module.DefaultLookup, null, CallingConventions.Any, types, null); @@ -468,7 +461,7 @@ namespace System.Reflection public MethodInfo GetMethod(String name) { if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); Contract.EndContractBlock(); return GetMethodImpl(name, Module.DefaultLookup, null, CallingConventions.Any, @@ -543,36 +536,7 @@ namespace System.Reflection { return ModuleHandle.EmptyHandle; } - -#if FEATURE_X509 && FEATURE_CAS_POLICY - public virtual System.Security.Cryptography.X509Certificates.X509Certificate GetSignerCertificate() - { - throw new NotImplementedException(); - } -#endif // FEATURE_X509 && FEATURE_CAS_POLICY #endregion - -#if !FEATURE_CORECLR - void _Module.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _Module.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _Module.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - void _Module.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif } [Serializable] @@ -581,46 +545,32 @@ namespace System.Reflection internal RuntimeModule() { throw new NotSupportedException(); } #region FCalls - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void GetType(RuntimeModule module, String className, bool ignoreCase, bool throwOnError, ObjectHandleOnStack type, ObjectHandleOnStack keepAlive); - [System.Security.SecurityCritical] [DllImport(JitHelpers.QCall)] [SuppressUnmanagedCodeSecurity] private static extern bool nIsTransientInternal(RuntimeModule module); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void GetScopeName(RuntimeModule module, StringHandleOnStack retString); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void GetFullyQualifiedName(RuntimeModule module, StringHandleOnStack retString); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static RuntimeType[] GetTypes(RuntimeModule module); - [System.Security.SecuritySafeCritical] // auto-generated internal RuntimeType[] GetDefinedTypes() { return GetTypes(GetNativeHandle()); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static bool IsResource(RuntimeModule module); - -#if FEATURE_X509 && FEATURE_CAS_POLICY - [System.Security.SecurityCritical] // auto-generated - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - static private extern void GetSignerCertificate(RuntimeModule module, ObjectHandleOnStack retData); -#endif // FEATURE_X509 && FEATURE_CAS_POLICY #endregion #region Module overrides @@ -646,18 +596,17 @@ namespace System.Reflection return typeHandleArgs; } - [System.Security.SecuritySafeCritical] // auto-generated public override byte[] ResolveSignature(int metadataToken) { MetadataToken tk = new MetadataToken(metadataToken); if (!MetadataImport.IsValidToken(tk)) - throw new ArgumentOutOfRangeException("metadataToken", + throw new ArgumentOutOfRangeException(nameof(metadataToken), Environment.GetResourceString("Argument_InvalidToken", tk, this)); if (!tk.IsMemberRef && !tk.IsMethodDef && !tk.IsTypeSpec && !tk.IsSignature && !tk.IsFieldDef) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidToken", tk, this), - "metadataToken"); + nameof(metadataToken)); ConstArray signature; if (tk.IsMemberRef) @@ -673,13 +622,12 @@ namespace System.Reflection return sig; } - [System.Security.SecuritySafeCritical] // auto-generated public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) { MetadataToken tk = new MetadataToken(metadataToken); if (!MetadataImport.IsValidToken(tk)) - throw new ArgumentOutOfRangeException("metadataToken", + throw new ArgumentOutOfRangeException(nameof(metadataToken), Environment.GetResourceString("Argument_InvalidToken", tk, this)); RuntimeTypeHandle[] typeArgs = ConvertToTypeHandleArray(genericTypeArguments); @@ -690,16 +638,16 @@ namespace System.Reflection if (!tk.IsMethodDef && !tk.IsMethodSpec) { if (!tk.IsMemberRef) - throw new ArgumentException("metadataToken", - Environment.GetResourceString("Argument_ResolveMethod", tk, this)); + throw new ArgumentException(Environment.GetResourceString("Argument_ResolveMethod", tk, this), + nameof(metadataToken)); unsafe { ConstArray sig = MetadataImport.GetMemberRefProps(tk); if (*(MdSigCallingConvention*)sig.Signature.ToPointer() == MdSigCallingConvention.Field) - throw new ArgumentException("metadataToken", - Environment.GetResourceString("Argument_ResolveMethod", tk, this)); + throw new ArgumentException(Environment.GetResourceString("Argument_ResolveMethod", tk, this), + nameof(metadataToken)); } } @@ -724,13 +672,12 @@ namespace System.Reflection } } - [System.Security.SecurityCritical] // auto-generated private FieldInfo ResolveLiteralField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) { MetadataToken tk = new MetadataToken(metadataToken); if (!MetadataImport.IsValidToken(tk) || !tk.IsFieldDef) - throw new ArgumentOutOfRangeException("metadataToken", + throw new ArgumentOutOfRangeException(nameof(metadataToken), String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Argument_InvalidToken", tk, this))); int tkDeclaringType; @@ -752,17 +699,16 @@ namespace System.Reflection } catch { - throw new ArgumentException(Environment.GetResourceString("Argument_ResolveField", tk, this), "metadataToken"); + throw new ArgumentException(Environment.GetResourceString("Argument_ResolveField", tk, this), nameof(metadataToken)); } } - [System.Security.SecuritySafeCritical] // auto-generated public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) { MetadataToken tk = new MetadataToken(metadataToken); if (!MetadataImport.IsValidToken(tk)) - throw new ArgumentOutOfRangeException("metadataToken", + throw new ArgumentOutOfRangeException(nameof(metadataToken), Environment.GetResourceString("Argument_InvalidToken", tk, this)); RuntimeTypeHandle[] typeArgs = ConvertToTypeHandleArray(genericTypeArguments); @@ -775,16 +721,16 @@ namespace System.Reflection if (!tk.IsFieldDef) { if (!tk.IsMemberRef) - throw new ArgumentException("metadataToken", - Environment.GetResourceString("Argument_ResolveField", tk, this)); + throw new ArgumentException(Environment.GetResourceString("Argument_ResolveField", tk, this), + nameof(metadataToken)); unsafe { ConstArray sig = MetadataImport.GetMemberRefProps(tk); if (*(MdSigCallingConvention*)sig.Signature.ToPointer() != MdSigCallingConvention.Field) - throw new ArgumentException("metadataToken", - Environment.GetResourceString("Argument_ResolveField", tk, this)); + throw new ArgumentException(Environment.GetResourceString("Argument_ResolveField", tk, this), + nameof(metadataToken)); } fieldHandle = ModuleHandle.ResolveFieldHandleInternal(GetNativeHandle(), tk, typeArgs, methodArgs); @@ -811,20 +757,19 @@ namespace System.Reflection } } - [System.Security.SecuritySafeCritical] // auto-generated public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) { MetadataToken tk = new MetadataToken(metadataToken); if (tk.IsGlobalTypeDefToken) - throw new ArgumentException(Environment.GetResourceString("Argument_ResolveModuleType", tk), "metadataToken"); + throw new ArgumentException(Environment.GetResourceString("Argument_ResolveModuleType", tk), nameof(metadataToken)); if (!MetadataImport.IsValidToken(tk)) - throw new ArgumentOutOfRangeException("metadataToken", + throw new ArgumentOutOfRangeException(nameof(metadataToken), Environment.GetResourceString("Argument_InvalidToken", tk, this)); if (!tk.IsTypeDef && !tk.IsTypeSpec && !tk.IsTypeRef) - throw new ArgumentException(Environment.GetResourceString("Argument_ResolveType", tk, this), "metadataToken"); + throw new ArgumentException(Environment.GetResourceString("Argument_ResolveType", tk, this), nameof(metadataToken)); RuntimeTypeHandle[] typeArgs = ConvertToTypeHandleArray(genericTypeArguments); RuntimeTypeHandle[] methodArgs = ConvertToTypeHandleArray(genericMethodArguments); @@ -834,7 +779,7 @@ namespace System.Reflection Type t = GetModuleHandle().ResolveTypeHandle(metadataToken, typeArgs, methodArgs).GetRuntimeType(); if (t == null) - throw new ArgumentException(Environment.GetResourceString("Argument_ResolveType", tk, this), "metadataToken"); + throw new ArgumentException(Environment.GetResourceString("Argument_ResolveType", tk, this), nameof(metadataToken)); return t; } @@ -844,7 +789,6 @@ namespace System.Reflection } } - [System.Security.SecuritySafeCritical] // auto-generated public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) { MetadataToken tk = new MetadataToken(metadataToken); @@ -867,7 +811,7 @@ namespace System.Reflection if (tk.IsMemberRef) { if (!MetadataImport.IsValidToken(tk)) - throw new ArgumentOutOfRangeException("metadataToken", + throw new ArgumentOutOfRangeException(nameof(metadataToken), Environment.GetResourceString("Argument_InvalidToken", tk, this)); ConstArray sig = MetadataImport.GetMemberRefProps(tk); @@ -885,11 +829,10 @@ namespace System.Reflection } } - throw new ArgumentException("metadataToken", - Environment.GetResourceString("Argument_ResolveMember", tk, this)); + throw new ArgumentException(Environment.GetResourceString("Argument_ResolveMember", tk, this), + nameof(metadataToken)); } - [System.Security.SecuritySafeCritical] // auto-generated public override string ResolveString(int metadataToken) { MetadataToken tk = new MetadataToken(metadataToken); @@ -898,7 +841,7 @@ namespace System.Reflection String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Argument_ResolveString"), metadataToken, ToString())); if (!MetadataImport.IsValidToken(tk)) - throw new ArgumentOutOfRangeException("metadataToken", + throw new ArgumentOutOfRangeException(nameof(metadataToken), String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Argument_InvalidToken", tk, this))); string str = MetadataImport.GetUserString(metadataToken); @@ -917,7 +860,6 @@ namespace System.Reflection public override int MDStreamVersion { - [System.Security.SecuritySafeCritical] // auto-generated get { return ModuleHandle.GetMDStreamVersion(GetNativeHandle()); @@ -973,7 +915,6 @@ namespace System.Reflection } } - [System.Security.SecuritySafeCritical] internal bool IsTransientInternal() { return RuntimeModule.nIsTransientInternal(this.GetNativeHandle()); @@ -981,7 +922,6 @@ namespace System.Reflection internal MetadataImport MetadataImport { - [System.Security.SecurityCritical] // auto-generated get { unsafe @@ -1001,28 +941,27 @@ namespace System.Reflection public override Object[] GetCustomAttributes(Type attributeType, bool inherit) { if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),nameof(attributeType)); return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType); } - [System.Security.SecuritySafeCritical] // auto-generated public override bool IsDefined(Type attributeType, bool inherit) { if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),nameof(attributeType)); return CustomAttribute.IsDefined(this, attributeRuntimeType); } @@ -1034,24 +973,22 @@ namespace System.Reflection #endregion #region Public Virtuals - [System.Security.SecurityCritical] // auto-generated_required public override void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); UnitySerializationHolder.GetUnitySerializationInfo(info, UnitySerializationHolder.ModuleUnity, this.ScopeName, this.GetRuntimeAssembly()); } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] public override Type GetType(String className, bool throwOnError, bool ignoreCase) { // throw on null strings regardless of the value of "throwOnError" if (className == null) - throw new ArgumentNullException("className"); + throw new ArgumentNullException(nameof(className)); RuntimeType retType = null; Object keepAlive = null; @@ -1060,7 +997,6 @@ namespace System.Reflection return retType; } - [System.Security.SecurityCritical] // auto-generated internal string GetFullyQualifiedName() { String fullyQualifiedName = null; @@ -1070,11 +1006,6 @@ namespace System.Reflection public override String FullyQualifiedName { -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#else - [System.Security.SecuritySafeCritical] -#endif get { String fullyQualifiedName = GetFullyQualifiedName(); @@ -1082,7 +1013,7 @@ namespace System.Reflection if (fullyQualifiedName != null) { bool checkPermission = true; try { - Path.GetFullPathInternal(fullyQualifiedName); + Path.GetFullPath(fullyQualifiedName); } catch(ArgumentException) { checkPermission = false; @@ -1096,7 +1027,6 @@ namespace System.Reflection } } - [System.Security.SecuritySafeCritical] // auto-generated public override Type[] GetTypes() { return GetTypes(GetNativeHandle()); @@ -1108,7 +1038,6 @@ namespace System.Reflection public override Guid ModuleVersionId { - [System.Security.SecuritySafeCritical] // auto-generated get { unsafe @@ -1122,7 +1051,6 @@ namespace System.Reflection public override int MetadataToken { - [System.Security.SecuritySafeCritical] // auto-generated get { return ModuleHandle.GetToken(GetNativeHandle()); @@ -1145,7 +1073,7 @@ namespace System.Reflection public override FieldInfo GetField(String name, BindingFlags bindingAttr) { if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); if (RuntimeType == null) return null; @@ -1163,7 +1091,6 @@ namespace System.Reflection public override String ScopeName { - [System.Security.SecuritySafeCritical] // auto-generated get { string scopeName = null; @@ -1174,7 +1101,6 @@ namespace System.Reflection public override String Name { - [System.Security.SecuritySafeCritical] // auto-generated get { String s = GetFullyQualifiedName(); @@ -1215,16 +1141,6 @@ namespace System.Reflection { return this; } - -#if FEATURE_X509 && FEATURE_CAS_POLICY - [System.Security.SecuritySafeCritical] // auto-generated - public override System.Security.Cryptography.X509Certificates.X509Certificate GetSignerCertificate() - { - byte[] data = null; - GetSignerCertificate(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref data)); - return (data != null) ? new System.Security.Cryptography.X509Certificates.X509Certificate(data) : null; - } -#endif // FEATURE_X509 && FEATURE_CAS_POLICY #endregion } } diff --git a/src/mscorlib/src/System/Reflection/ParameterInfo.cs b/src/mscorlib/src/System/Reflection/ParameterInfo.cs index 63c6330..6592e5a 100644 --- a/src/mscorlib/src/System/Reflection/ParameterInfo.cs +++ b/src/mscorlib/src/System/Reflection/ParameterInfo.cs @@ -8,13 +8,11 @@ namespace System.Reflection { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.CompilerServices; -#if FEATURE_REMOTING - using System.Runtime.Remoting.Metadata; -#endif //FEATURE_REMOTING using System.Security.Permissions; using System.Threading; using MdToken = System.Reflection.MetadataToken; @@ -157,7 +155,7 @@ namespace System.Reflection public virtual Object[] GetCustomAttributes(Type attributeType, bool inherit) { if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); return EmptyArray.Value; @@ -166,7 +164,7 @@ namespace System.Reflection public virtual bool IsDefined(Type attributeType, bool inherit) { if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); return false; @@ -180,35 +178,12 @@ namespace System.Reflection #region _ParameterInfo implementation -#if !FEATURE_CORECLR - void _ParameterInfo.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _ParameterInfo.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _ParameterInfo.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - void _ParameterInfo.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif - #endregion #region IObjectReference // In V4 RuntimeParameterInfo is introduced. // To support deserializing ParameterInfo instances serialized in earlier versions // we need to implement IObjectReference. - [System.Security.SecurityCritical] public object GetRealObject(StreamingContext context) { Contract.Ensures(Contract.Result() != null); @@ -261,26 +236,23 @@ namespace System.Reflection internal unsafe sealed class RuntimeParameterInfo : ParameterInfo, ISerializable { #region Static Members - [System.Security.SecurityCritical] // auto-generated internal unsafe static ParameterInfo[] GetParameters(IRuntimeMethodInfo method, MemberInfo member, Signature sig) { - Contract.Assert(method is RuntimeMethodInfo || method is RuntimeConstructorInfo); + Debug.Assert(method is RuntimeMethodInfo || method is RuntimeConstructorInfo); ParameterInfo dummy; return GetParameters(method, member, sig, out dummy, false); } - [System.Security.SecurityCritical] // auto-generated internal unsafe static ParameterInfo GetReturnParameter(IRuntimeMethodInfo method, MemberInfo member, Signature sig) { - Contract.Assert(method is RuntimeMethodInfo || method is RuntimeConstructorInfo); + Debug.Assert(method is RuntimeMethodInfo || method is RuntimeConstructorInfo); ParameterInfo returnParameter; GetParameters(method, member, sig, out returnParameter, true); return returnParameter; } - [System.Security.SecurityCritical] // auto-generated internal unsafe static ParameterInfo[] GetParameters( IRuntimeMethodInfo methodHandle, MemberInfo member, Signature sig, out ParameterInfo returnParameter, bool fetchReturnParameter) { @@ -392,18 +364,17 @@ namespace System.Reflection get { MethodBase result = m_originalMember != null ? m_originalMember : MemberImpl as MethodBase; - Contract.Assert(result != null); + Debug.Assert(result != null); return result; } } #endregion #region VTS magic to serialize/deserialized to/from pre-Whidbey endpoints. - [System.Security.SecurityCritical] public void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // We could be serializing for consumption by a pre-Whidbey @@ -450,7 +421,7 @@ namespace System.Reflection // The original owner should always be a method, because this method is only used to // change the owner from a method to a property. m_originalMember = accessor.MemberImpl as MethodBase; - Contract.Assert(m_originalMember != null); + Debug.Assert(m_originalMember != null); // Populate all the caches -- we inherit this behavior from RTM NameImpl = accessor.Name; @@ -470,8 +441,8 @@ namespace System.Reflection int position, ParameterAttributes attributes, MemberInfo member) { Contract.Requires(member != null); - Contract.Assert(MdToken.IsNullToken(tkParamDef) == scope.Equals(MetadataImport.EmptyImport)); - Contract.Assert(MdToken.IsNullToken(tkParamDef) || MdToken.IsTokenOfType(tkParamDef, MetadataTokenType.ParamDef)); + Debug.Assert(MdToken.IsNullToken(tkParamDef) == scope.Equals(MetadataImport.EmptyImport)); + Debug.Assert(MdToken.IsNullToken(tkParamDef) || MdToken.IsTokenOfType(tkParamDef, MetadataTokenType.ParamDef)); PositionImpl = position; MemberImpl = member; @@ -513,7 +484,7 @@ namespace System.Reflection else parameterType = m_signature.Arguments[PositionImpl]; - Contract.Assert(parameterType != null); + Debug.Assert(parameterType != null); // different thread could only write ClassImpl to the same value, so a race condition is not a problem here ClassImpl = parameterType; } @@ -524,7 +495,6 @@ namespace System.Reflection public override String Name { - [System.Security.SecuritySafeCritical] // auto-generated get { if (!m_nameIsCached) @@ -588,10 +558,9 @@ namespace System.Reflection } // returns DBNull.Value if the parameter doesn't have a default value - [System.Security.SecuritySafeCritical] private Object GetDefaultValueInternal(bool raw) { - Contract.Assert(!m_noMetadata); + Debug.Assert(!m_noMetadata); if (m_noDefaultValue) return DBNull.Value; @@ -728,7 +697,7 @@ namespace System.Reflection public override Object[] GetCustomAttributes(Type attributeType, bool inherit) { if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); if (MdToken.IsNullToken(m_tkParamDef)) @@ -737,16 +706,15 @@ namespace System.Reflection RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "attributeType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), nameof(attributeType)); return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType); } - [System.Security.SecuritySafeCritical] // auto-generated public override bool IsDefined(Type attributeType, bool inherit) { if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); if (MdToken.IsNullToken(m_tkParamDef)) @@ -755,7 +723,7 @@ namespace System.Reflection RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "attributeType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), nameof(attributeType)); return CustomAttribute.IsDefined(this, attributeRuntimeType); } @@ -765,31 +733,5 @@ namespace System.Reflection return CustomAttributeData.GetCustomAttributesInternal(this); } #endregion - -#if FEATURE_REMOTING - #region Remoting Cache - private RemotingParameterCachedData m_cachedData; - - internal RemotingParameterCachedData RemotingCache - { - get - { - // This grabs an internal copy of m_cachedData and uses - // that instead of looking at m_cachedData directly because - // the cache may get cleared asynchronously. This prevents - // us from having to take a lock. - RemotingParameterCachedData cache = m_cachedData; - if (cache == null) - { - cache = new RemotingParameterCachedData(this); - RemotingParameterCachedData ret = Interlocked.CompareExchange(ref m_cachedData, cache, null); - if (ret != null) - cache = ret; - } - return cache; - } - } - #endregion -#endif //FEATURE_REMOTING } } diff --git a/src/mscorlib/src/System/Reflection/Pointer.cs b/src/mscorlib/src/System/Reflection/Pointer.cs index 8105208..95025b2 100644 --- a/src/mscorlib/src/System/Reflection/Pointer.cs +++ b/src/mscorlib/src/System/Reflection/Pointer.cs @@ -22,13 +22,11 @@ namespace System.Reflection { [System.Runtime.InteropServices.ComVisible(true)] public sealed class Pointer : ISerializable { - [SecurityCritical] unsafe private void* _ptr; private RuntimeType _ptrType; private Pointer() {} - [System.Security.SecurityCritical] // auto-generated private unsafe Pointer(SerializationInfo info, StreamingContext context) { _ptr = ((IntPtr)(info.GetValue("_ptr", typeof(IntPtr)))).ToPointer(); @@ -38,17 +36,16 @@ namespace System.Reflection { // This method will box an pointer. We save both the // value and the type so we can access it from the native code // during an Invoke. - [System.Security.SecurityCritical] // auto-generated public static unsafe Object Box(void *ptr,Type type) { if (type == null) - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); if (!type.IsPointer) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBePointer"),"ptr"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBePointer"),nameof(ptr)); Contract.EndContractBlock(); RuntimeType rt = type as RuntimeType; if (rt == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBePointer"), "ptr"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBePointer"), nameof(ptr)); Pointer x = new Pointer(); x._ptr = ptr; @@ -57,10 +54,9 @@ namespace System.Reflection { } // Returned the stored pointer. - [System.Security.SecurityCritical] // auto-generated public static unsafe void* Unbox(Object ptr) { if (!(ptr is Pointer)) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBePointer"),"ptr"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBePointer"),nameof(ptr)); return ((Pointer)ptr)._ptr; } @@ -68,12 +64,10 @@ namespace System.Reflection { return _ptrType; } - [System.Security.SecurityCritical] // auto-generated internal unsafe Object GetPointerValue() { return (IntPtr)_ptr; } - [System.Security.SecurityCritical] unsafe void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue("_ptr", new IntPtr(_ptr)); info.AddValue("_ptrType", _ptrType); diff --git a/src/mscorlib/src/System/Reflection/PropertyInfo.cs b/src/mscorlib/src/System/Reflection/PropertyInfo.cs index 3e451b1..e31b378 100644 --- a/src/mscorlib/src/System/Reflection/PropertyInfo.cs +++ b/src/mscorlib/src/System/Reflection/PropertyInfo.cs @@ -22,9 +22,6 @@ namespace System.Reflection [Serializable] [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_PropertyInfo))] -#pragma warning disable 618 - [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")] -#pragma warning restore 618 [System.Runtime.InteropServices.ComVisible(true)] public abstract class PropertyInfo : MemberInfo, _PropertyInfo { @@ -153,35 +150,6 @@ namespace System.Reflection public bool IsSpecialName { get { return(Attributes & PropertyAttributes.SpecialName) != 0; } } #endregion - -#if !FEATURE_CORECLR - Type _PropertyInfo.GetType() - { - return base.GetType(); - } - - void _PropertyInfo.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _PropertyInfo.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _PropertyInfo.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - // If you implement this method, make sure to include _PropertyInfo.Invoke in VM\DangerousAPIs.h and - // include _PropertyInfo in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp. - void _PropertyInfo.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif } [Serializable] @@ -190,7 +158,6 @@ namespace System.Reflection #region Private Data Members private int m_token; private string m_name; - [System.Security.SecurityCritical] private void* m_utf8name; private PropertyAttributes m_flags; private RuntimeTypeCache m_reflectedTypeCache; @@ -204,13 +171,12 @@ namespace System.Reflection #endregion #region Constructor - [System.Security.SecurityCritical] // auto-generated internal RuntimePropertyInfo( int tkProperty, RuntimeType declaredType, RuntimeTypeCache reflectedTypeCache, out bool isPrivate) { Contract.Requires(declaredType != null); Contract.Requires(reflectedTypeCache != null); - Contract.Assert(!reflectedTypeCache.IsGlobal); + Debug.Assert(!reflectedTypeCache.IsGlobal); MetadataImport scope = declaredType.GetRuntimeModule().MetadataImport; @@ -245,7 +211,6 @@ namespace System.Reflection internal Signature Signature { - [System.Security.SecuritySafeCritical] // auto-generated get { if (m_signature == null) @@ -332,28 +297,27 @@ namespace System.Reflection public override Object[] GetCustomAttributes(Type attributeType, bool inherit) { if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),nameof(attributeType)); return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType); } - [System.Security.SecuritySafeCritical] // auto-generated public override bool IsDefined(Type attributeType, bool inherit) { if (attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),nameof(attributeType)); return CustomAttribute.IsDefined(this, attributeRuntimeType); } @@ -368,7 +332,6 @@ namespace System.Reflection public override MemberTypes MemberType { get { return MemberTypes.Property; } } public override String Name { - [System.Security.SecuritySafeCritical] // auto-generated get { if (m_name == null) @@ -421,7 +384,6 @@ namespace System.Reflection return Signature.GetCustomModifiers(0, false); } - [System.Security.SecuritySafeCritical] // auto-generated internal object GetConstantValue(bool raw) { Object defaultValue = MdConstant.GetValue(GetRuntimeModule().MetadataImport, m_token, PropertyType.GetTypeHandleInternal(), raw); @@ -630,11 +592,10 @@ namespace System.Reflection #endregion #region ISerializable Implementation - [System.Security.SecurityCritical] // auto-generated public void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); MemberInfoSerializationHolder.GetSerializationInfo( diff --git a/src/mscorlib/src/System/Reflection/ReflectionContext.cs b/src/mscorlib/src/System/Reflection/ReflectionContext.cs index f9bfa87..34f6921 100644 --- a/src/mscorlib/src/System/Reflection/ReflectionContext.cs +++ b/src/mscorlib/src/System/Reflection/ReflectionContext.cs @@ -28,7 +28,7 @@ namespace System.Reflection public virtual TypeInfo GetTypeForObject(object value) { if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); return MapType(value.GetType().GetTypeInfo()); } diff --git a/src/mscorlib/src/System/Reflection/ReflectionTypeLoadException.cs b/src/mscorlib/src/System/Reflection/ReflectionTypeLoadException.cs index 9b55c26..7068113 100644 --- a/src/mscorlib/src/System/Reflection/ReflectionTypeLoadException.cs +++ b/src/mscorlib/src/System/Reflection/ReflectionTypeLoadException.cs @@ -65,10 +65,9 @@ namespace System.Reflection { get {return _exceptions;} } - [System.Security.SecurityCritical] // auto-generated_required public override void GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); base.GetObjectData(info, context); diff --git a/src/mscorlib/src/System/Reflection/RuntimeReflectionExtensions.cs b/src/mscorlib/src/System/Reflection/RuntimeReflectionExtensions.cs index b4ef9b9..00ab975 100644 --- a/src/mscorlib/src/System/Reflection/RuntimeReflectionExtensions.cs +++ b/src/mscorlib/src/System/Reflection/RuntimeReflectionExtensions.cs @@ -72,7 +72,7 @@ namespace System.Reflection public static InterfaceMapping GetRuntimeInterfaceMap(this TypeInfo typeInfo, Type interfaceType) { - if (typeInfo == null) throw new ArgumentNullException("typeInfo"); + if (typeInfo == null) throw new ArgumentNullException(nameof(typeInfo)); if (!(typeInfo is RuntimeType)) throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType")); return typeInfo.GetInterfaceMap(interfaceType); @@ -80,7 +80,7 @@ namespace System.Reflection public static MethodInfo GetMethodInfo(this Delegate del) { - if (del == null) throw new ArgumentNullException("del"); + if (del == null) throw new ArgumentNullException(nameof(del)); return del.Method; } diff --git a/src/mscorlib/src/System/Reflection/StrongNameKeyPair.cs b/src/mscorlib/src/System/Reflection/StrongNameKeyPair.cs index e8a441c..8107cf4 100644 --- a/src/mscorlib/src/System/Reflection/StrongNameKeyPair.cs +++ b/src/mscorlib/src/System/Reflection/StrongNameKeyPair.cs @@ -26,20 +26,7 @@ namespace System.Reflection using System.Runtime.Versioning; using Microsoft.Win32; using System.Diagnostics.Contracts; -#if !FEATURE_CORECLR - using Microsoft.Runtime.Hosting; -#endif -#if FEATURE_CORECLR - // Dummy type to avoid ifdefs in signature definitions - public class StrongNameKeyPair - { - private StrongNameKeyPair() - { - throw new NotSupportedException(); - } - } -#else [Serializable] [System.Runtime.InteropServices.ComVisible(true)] public class StrongNameKeyPair : IDeserializationCallback, ISerializable @@ -50,14 +37,10 @@ namespace System.Reflection private byte[] _publicKey; // Build key pair from file. - [System.Security.SecuritySafeCritical] // auto-generated -#pragma warning disable 618 - [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] -#pragma warning restore 618 public StrongNameKeyPair(FileStream keyPairFile) { if (keyPairFile == null) - throw new ArgumentNullException("keyPairFile"); + throw new ArgumentNullException(nameof(keyPairFile)); Contract.EndContractBlock(); int length = (int)keyPairFile.Length; @@ -68,14 +51,10 @@ namespace System.Reflection } // Build key pair from byte array in memory. - [System.Security.SecuritySafeCritical] // auto-generated -#pragma warning disable 618 - [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] -#pragma warning restore 618 public StrongNameKeyPair(byte[] keyPairArray) { if (keyPairArray == null) - throw new ArgumentNullException("keyPairArray"); + throw new ArgumentNullException(nameof(keyPairArray)); Contract.EndContractBlock(); _keyPairArray = new byte[keyPairArray.Length]; @@ -83,27 +62,7 @@ namespace System.Reflection _keyPairExported = true; } - - // Reference key pair in named key container. - [System.Security.SecuritySafeCritical] // auto-generated -#pragma warning disable 618 - [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] -#pragma warning restore 618 - public StrongNameKeyPair(String keyPairContainer) - { - if (keyPairContainer == null) - throw new ArgumentNullException("keyPairContainer"); - Contract.EndContractBlock(); - - _keyPairContainer = keyPairContainer; - - _keyPairExported = false; - } - - [System.Security.SecuritySafeCritical] // auto-generated -#pragma warning disable 618 - [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] -#pragma warning restore 618 + protected StrongNameKeyPair (SerializationInfo info, StreamingContext context) { _keyPairExported = (bool) info.GetValue("_keyPairExported", typeof(bool)); _keyPairArray = (byte[]) info.GetValue("_keyPairArray", typeof(byte[])); @@ -111,68 +70,20 @@ namespace System.Reflection _publicKey = (byte[]) info.GetValue("_publicKey", typeof(byte[])); } - // Get the public portion of the key pair. - public byte[] PublicKey + public StrongNameKeyPair(String keyPairContainer) { - [System.Security.SecuritySafeCritical] // auto-generated - get - { - if (_publicKey == null) - { - _publicKey = ComputePublicKey(); - } - - byte[] publicKey = new byte[_publicKey.Length]; - Array.Copy(_publicKey, publicKey, _publicKey.Length); - - return publicKey; - } + throw new PlatformNotSupportedException(); } - - [System.Security.SecurityCritical] // auto-generated - private unsafe byte[] ComputePublicKey() + + public byte[] PublicKey { - byte[] publicKey = null; - - // Make sure pbPublicKey is not leaked with async exceptions - RuntimeHelpers.PrepareConstrainedRegions(); - try { - } - finally + get { - IntPtr pbPublicKey = IntPtr.Zero; - int cbPublicKey = 0; - - try - { - bool result; - if (_keyPairExported) - { - result = StrongNameHelpers.StrongNameGetPublicKey(null, _keyPairArray, _keyPairArray.Length, - out pbPublicKey, out cbPublicKey); - } - else - { - result = StrongNameHelpers.StrongNameGetPublicKey(_keyPairContainer, null, 0, - out pbPublicKey, out cbPublicKey); - } - if (!result) - throw new ArgumentException(Environment.GetResourceString("Argument_StrongNameGetPublicKey")); - - publicKey = new byte[cbPublicKey]; - Buffer.Memcpy(publicKey, 0, (byte*)(pbPublicKey.ToPointer()), 0, cbPublicKey); - } - finally - { - if (pbPublicKey != IntPtr.Zero) - StrongNameHelpers.StrongNameFreeBuffer(pbPublicKey); - } + throw new PlatformNotSupportedException(); } - return publicKey; } /// - [System.Security.SecurityCritical] void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context) { info.AddValue("_keyPairExported", _keyPairExported); info.AddValue("_keyPairArray", _keyPairArray); @@ -182,13 +93,5 @@ namespace System.Reflection /// void IDeserializationCallback.OnDeserialization (Object sender) {} - - // Internal routine used to retrieve key pair info from unmanaged code. - private bool GetKeyPair(out Object arrayOrContainer) - { - arrayOrContainer = _keyPairExported ? (Object)_keyPairArray : (Object)_keyPairContainer; - return _keyPairExported; - } } -#endif // FEATURE_CORECLR } diff --git a/src/mscorlib/src/System/Reflection/TargetException.cs b/src/mscorlib/src/System/Reflection/TargetException.cs index 02772f7..9c56c12 100644 --- a/src/mscorlib/src/System/Reflection/TargetException.cs +++ b/src/mscorlib/src/System/Reflection/TargetException.cs @@ -19,11 +19,7 @@ namespace System.Reflection { using System.Runtime.Serialization; [Serializable] [System.Runtime.InteropServices.ComVisible(true)] -#if FEATURE_CORECLR - public class TargetException : Exception { -#else public class TargetException : ApplicationException { -#endif //FEATURE_CORECLR public TargetException() : base() { SetErrorCode(__HResults.COR_E_TARGET); } diff --git a/src/mscorlib/src/System/Reflection/TargetInvocationException.cs b/src/mscorlib/src/System/Reflection/TargetInvocationException.cs index 70de422..4a32ed2 100644 --- a/src/mscorlib/src/System/Reflection/TargetInvocationException.cs +++ b/src/mscorlib/src/System/Reflection/TargetInvocationException.cs @@ -19,11 +19,7 @@ namespace System.Reflection { using System.Runtime.Serialization; [Serializable] [System.Runtime.InteropServices.ComVisible(true)] -#if FEATURE_CORECLR - public sealed class TargetInvocationException : Exception { -#else public sealed class TargetInvocationException : ApplicationException { -#endif //FEATURE_CORECLR // This exception is not creatable without specifying the // inner exception. private TargetInvocationException() diff --git a/src/mscorlib/src/System/Reflection/TargetParameterCountException.cs b/src/mscorlib/src/System/Reflection/TargetParameterCountException.cs index 4f95b09..846732b 100644 --- a/src/mscorlib/src/System/Reflection/TargetParameterCountException.cs +++ b/src/mscorlib/src/System/Reflection/TargetParameterCountException.cs @@ -19,11 +19,7 @@ namespace System.Reflection { using System.Runtime.Serialization; [Serializable] [System.Runtime.InteropServices.ComVisible(true)] -#if FEATURE_CORECLR - public sealed class TargetParameterCountException : Exception { -#else public sealed class TargetParameterCountException : ApplicationException { -#endif //FEATURE_CORECLR public TargetParameterCountException() : base(Environment.GetResourceString("Arg_TargetParameterCountException")) { SetErrorCode(__HResults.COR_E_TARGETPARAMCOUNT); diff --git a/src/mscorlib/src/System/Reflection/TypeDelegator.cs b/src/mscorlib/src/System/Reflection/TypeDelegator.cs index cad4a42..d715df8 100644 --- a/src/mscorlib/src/System/Reflection/TypeDelegator.cs +++ b/src/mscorlib/src/System/Reflection/TypeDelegator.cs @@ -24,14 +24,11 @@ namespace System.Reflection { protected Type typeImpl; - #if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // auto-generated - #endif protected TypeDelegator() {} public TypeDelegator(Type delegatingType) { if (delegatingType == null) - throw new ArgumentNullException("delegatingType"); + throw new ArgumentNullException(nameof(delegatingType)); Contract.EndContractBlock(); typeImpl = delegatingType; diff --git a/src/mscorlib/src/System/Resources/FileBasedResourceGroveler.cs b/src/mscorlib/src/System/Resources/FileBasedResourceGroveler.cs index efd949f..76bf000 100644 --- a/src/mscorlib/src/System/Resources/FileBasedResourceGroveler.cs +++ b/src/mscorlib/src/System/Resources/FileBasedResourceGroveler.cs @@ -23,6 +23,7 @@ namespace System.Resources { using System.Runtime.Versioning; using System.Text; using System.Threading; + using System.Diagnostics; using System.Diagnostics.Contracts; internal class FileBasedResourceGroveler : IResourceGroveler @@ -31,17 +32,16 @@ namespace System.Resources { public FileBasedResourceGroveler(ResourceManager.ResourceManagerMediator mediator) { - Contract.Assert(mediator != null, "mediator shouldn't be null; check caller"); + Debug.Assert(mediator != null, "mediator shouldn't be null; check caller"); _mediator = mediator; } // Consider modifying IResourceGroveler interface (hence this method signature) when we figure out // serialization compat story for moving ResourceManager members to either file-based or // manifest-based classes. Want to continue tightening the design to get rid of unused params. - [System.Security.SecuritySafeCritical] // auto-generated public ResourceSet GrovelForResourceSet(CultureInfo culture, Dictionary localResourceSets, bool tryParents, bool createIfNotExists, ref StackCrawlMark stackMark) { - Contract.Assert(culture != null, "culture shouldn't be null; check caller"); + Debug.Assert(culture != null, "culture shouldn't be null; check caller"); String fileName = null; ResourceSet rs = null; @@ -79,24 +79,6 @@ namespace System.Resources { } } -#if !FEATURE_CORECLR // PAL doesn't support eventing, and we don't compile event providers for coreclr - public bool HasNeutralResources(CultureInfo culture, String defaultResName) - { - // Detect missing neutral locale resources. - String defaultResPath = FindResourceFile(culture, defaultResName); - if (defaultResPath == null || !File.Exists(defaultResPath)) - { - String dir = _mediator.ModuleDir; - if (defaultResPath != null) - { - dir = Path.GetDirectoryName(defaultResPath); - } - return false; - } - return true; - } -#endif - // Given a CultureInfo, it generates the path &; file name for // the .resources file for that CultureInfo. This method will grovel // the disk looking for the correct file name & path. Uses CultureInfo's @@ -107,8 +89,8 @@ namespace System.Resources { private String FindResourceFile(CultureInfo culture, String fileName) { - Contract.Assert(culture != null, "culture shouldn't be null; check caller"); - Contract.Assert(fileName != null, "fileName shouldn't be null; check caller"); + Debug.Assert(culture != null, "culture shouldn't be null; check caller"); + Debug.Assert(fileName != null, "fileName shouldn't be null; check caller"); // If we have a moduleDir, check there first. Get module fully // qualified name, append path to that. @@ -145,10 +127,9 @@ namespace System.Resources { // Constructs a new ResourceSet for a given file name. The logic in // here avoids a ReflectionPermission check for our RuntimeResourceSet // for perf and working set reasons. - [System.Security.SecurityCritical] private ResourceSet CreateResourceSet(String file) { - Contract.Assert(file != null, "file shouldn't be null; check caller"); + Debug.Assert(file != null, "file shouldn't be null; check caller"); if (_mediator.UserResourceSet == null) { diff --git a/src/mscorlib/src/System/Resources/IResourceGroveler.cs b/src/mscorlib/src/System/Resources/IResourceGroveler.cs index 983fd12..77c5c95 100644 --- a/src/mscorlib/src/System/Resources/IResourceGroveler.cs +++ b/src/mscorlib/src/System/Resources/IResourceGroveler.cs @@ -23,10 +23,5 @@ namespace System.Resources { { ResourceSet GrovelForResourceSet(CultureInfo culture, Dictionary localResourceSets, bool tryParents, bool createIfNotExists, ref StackCrawlMark stackMark); - -#if !FEATURE_CORECLR // PAL doesn't support eventing, and we don't compile event providers for coreclr - - bool HasNeutralResources(CultureInfo culture, String defaultResName); -#endif } } diff --git a/src/mscorlib/src/System/Resources/LooselyLinkedResourceReference.cs b/src/mscorlib/src/System/Resources/LooselyLinkedResourceReference.cs index 8235d60..15a076b 100644 --- a/src/mscorlib/src/System/Resources/LooselyLinkedResourceReference.cs +++ b/src/mscorlib/src/System/Resources/LooselyLinkedResourceReference.cs @@ -36,13 +36,13 @@ namespace System.Resources { public LooselyLinkedResourceReference(String looselyLinkedResourceName, String typeName) { if (looselyLinkedResourceName == null) - throw new ArgumentNullException("looselyLinkedResourceName"); + throw new ArgumentNullException(nameof(looselyLinkedResourceName)); if (typeName == null) - throw new ArgumentNullException("typeName"); + throw new ArgumentNullException(nameof(typeName)); if (looselyLinkedResourceName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "looselyLinkedResourceName"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(looselyLinkedResourceName)); if (typeName.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "typeName"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(typeName)); Contract.EndContractBlock(); _manifestResourceName = looselyLinkedResourceName; @@ -60,7 +60,7 @@ namespace System.Resources { public Object Resolve(Assembly assembly) { if (assembly == null) - throw new ArgumentNullException("assembly"); + throw new ArgumentNullException(nameof(assembly)); Contract.EndContractBlock(); Stream data = assembly.GetManifestResourceStream(_manifestResourceName); diff --git a/src/mscorlib/src/System/Resources/ManifestBasedResourceGroveler.cs b/src/mscorlib/src/System/Resources/ManifestBasedResourceGroveler.cs index 5fd0daa..78e961a 100644 --- a/src/mscorlib/src/System/Resources/ManifestBasedResourceGroveler.cs +++ b/src/mscorlib/src/System/Resources/ManifestBasedResourceGroveler.cs @@ -26,13 +26,10 @@ namespace System.Resources { using System.Runtime.Versioning; using System.Text; using System.Threading; + using System.Diagnostics; using System.Diagnostics.Contracts; using Microsoft.Win32; -#if !FEATURE_CORECLR - using System.Diagnostics.Tracing; -#endif - // // Note: this type is integral to the construction of exception objects, // and sometimes this has to be done in low memory situtations (OOM) or @@ -55,12 +52,11 @@ namespace System.Resources { _mediator = mediator; } - [System.Security.SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable public ResourceSet GrovelForResourceSet(CultureInfo culture, Dictionary localResourceSets, bool tryParents, bool createIfNotExists, ref StackCrawlMark stackMark) { - Contract.Assert(culture != null, "culture shouldn't be null; check caller"); - Contract.Assert(localResourceSets != null, "localResourceSets shouldn't be null; check caller"); + Debug.Assert(culture != null, "culture shouldn't be null; check caller"); + Debug.Assert(localResourceSets != null, "localResourceSets shouldn't be null; check caller"); ResourceSet rs = null; Stream stream = null; @@ -110,43 +106,15 @@ namespace System.Resources { // want to add it twice. lock (localResourceSets) { - if (localResourceSets.TryGetValue(culture.Name, out rs)) - { -#if !FEATURE_CORECLR - if (FrameworkEventSource.IsInitialized) - { - FrameworkEventSource.Log.ResourceManagerFoundResourceSetInCacheUnexpected(_mediator.BaseName, _mediator.MainAssembly, culture.Name); - } -#endif - } + localResourceSets.TryGetValue(culture.Name, out rs); } stream = GetManifestResourceStream(satellite, fileName, ref stackMark); } -#if !FEATURE_CORECLR - if (FrameworkEventSource.IsInitialized) - { - if (stream != null) - { - FrameworkEventSource.Log.ResourceManagerStreamFound(_mediator.BaseName, _mediator.MainAssembly, culture.Name, satellite, fileName); - } - else - { - FrameworkEventSource.Log.ResourceManagerStreamNotFound(_mediator.BaseName, _mediator.MainAssembly, culture.Name, satellite, fileName); - } - } -#endif - // 4a. Found a stream; create a ResourceSet if possible if (createIfNotExists && stream != null && rs == null) { -#if !FEATURE_CORECLR - if (FrameworkEventSource.IsInitialized) - { - FrameworkEventSource.Log.ResourceManagerCreatingResourceSet(_mediator.BaseName, _mediator.MainAssembly, culture.Name, fileName); - } -#endif rs = CreateResourceSet(stream, satellite); } else if (stream == null && tryParents) @@ -159,36 +127,9 @@ namespace System.Resources { } } -#if !FEATURE_CORECLR - if (!createIfNotExists && stream != null && rs == null) - { - if (FrameworkEventSource.IsInitialized) - { - FrameworkEventSource.Log.ResourceManagerNotCreatingResourceSet(_mediator.BaseName, _mediator.MainAssembly, culture.Name); - } - } -#endif - return rs; } -#if !FEATURE_CORECLR - // Returns whether or not the main assembly contains a particular resource - // file in it's assembly manifest. Used to verify that the neutral - // Culture's .resources file is present in the main assembly - public bool HasNeutralResources(CultureInfo culture, String defaultResName) - { - String resName = defaultResName; - if (_mediator.LocationInfo != null && _mediator.LocationInfo.Namespace != null) - resName = _mediator.LocationInfo.Namespace + Type.Delimiter + defaultResName; - String[] resourceFiles = _mediator.MainAssembly.GetManifestResourceNames(); - foreach(String s in resourceFiles) - if (s.Equals(resName)) - return true; - return false; - } -#endif - private CultureInfo UltimateFallbackFixup(CultureInfo lookForCulture) { @@ -199,13 +140,6 @@ namespace System.Resources { if (lookForCulture.Name == _mediator.NeutralResourcesCulture.Name && _mediator.FallbackLoc == UltimateResourceFallbackLocation.MainAssembly) { -#if !FEATURE_CORECLR - if (FrameworkEventSource.IsInitialized) - { - FrameworkEventSource.Log.ResourceManagerNeutralResourcesSufficient(_mediator.BaseName, _mediator.MainAssembly, lookForCulture.Name); - } -#endif - returnCulture = CultureInfo.InvariantCulture; } else if (lookForCulture.HasInvariantCultureName && _mediator.FallbackLoc == UltimateResourceFallbackLocation.Satellite) @@ -214,13 +148,11 @@ namespace System.Resources { } return returnCulture; - } - [System.Security.SecurityCritical] internal static CultureInfo GetNeutralResourcesLanguage(Assembly a, ref UltimateResourceFallbackLocation fallbackLocation) { - Contract.Assert(a != null, "assembly != null"); + Debug.Assert(a != null, "assembly != null"); string cultureName = null; short fallback = 0; if (GetNeutralResourcesLanguageAttribute(((RuntimeAssembly)a).GetNativeHandle(), @@ -232,11 +164,6 @@ namespace System.Resources { fallbackLocation = (UltimateResourceFallbackLocation)fallback; } else { -#if !FEATURE_CORECLR - if (FrameworkEventSource.IsInitialized) { - FrameworkEventSource.Log.ResourceManagerNeutralResourceAttributeMissing(a); - } -#endif fallbackLocation = UltimateResourceFallbackLocation.MainAssembly; return CultureInfo.InvariantCulture; } @@ -253,7 +180,7 @@ namespace System.Resources { // fires, please fix the build process for the BCL directory. if (a == typeof(Object).Assembly) { - Contract.Assert(false, System.CoreLib.Name+"'s NeutralResourcesLanguageAttribute is a malformed culture name! name: \"" + cultureName + "\" Exception: " + e); + Debug.Assert(false, System.CoreLib.Name+"'s NeutralResourcesLanguageAttribute is a malformed culture name! name: \"" + cultureName + "\" Exception: " + e); return CultureInfo.InvariantCulture; } @@ -267,10 +194,9 @@ namespace System.Resources { // Use the assembly to resolve assembly manifest resource references. // Note that is can be null, but probably shouldn't be. // This method could use some refactoring. One thing at a time. - [System.Security.SecurityCritical] internal ResourceSet CreateResourceSet(Stream store, Assembly assembly) { - Contract.Assert(store != null, "I need a Stream!"); + Debug.Assert(store != null, "I need a Stream!"); // Check to see if this is a Stream the ResourceManager understands, // and check for the correct resource reader type. if (store.CanSeek && store.Length > 4) @@ -350,7 +276,7 @@ namespace System.Resources { Type resSetType; if (_mediator.UserResourceSet == null) { - Contract.Assert(resSetTypeName != null, "We should have a ResourceSet type name from the custom resource file here."); + Debug.Assert(resSetTypeName != null, "We should have a ResourceSet type name from the custom resource file here."); resSetType = Type.GetType(resSetTypeName, true, false); } else @@ -413,7 +339,6 @@ namespace System.Resources { } } - [System.Security.SecurityCritical] private Stream GetManifestResourceStream(RuntimeAssembly satellite, String fileName, ref StackCrawlMark stackMark) { Contract.Requires(satellite != null, "satellite shouldn't be null; check caller"); @@ -437,7 +362,6 @@ namespace System.Resources { // case-insensitive lookup rules. Yes, this is slow. The metadata // dev lead refuses to make all assembly manifest resource lookups case-insensitive, // even optionally case-insensitive. - [System.Security.SecurityCritical] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable private Stream CaseInsensitiveManifestResourceStreamLookup(RuntimeAssembly satellite, String name) { @@ -475,48 +399,19 @@ namespace System.Resources { } } -#if !FEATURE_CORECLR - if (FrameworkEventSource.IsInitialized) - { - if (canonicalName != null) - { - FrameworkEventSource.Log.ResourceManagerCaseInsensitiveResourceStreamLookupSucceeded(_mediator.BaseName, _mediator.MainAssembly, satellite.GetSimpleName(), givenName); - } - else - { - FrameworkEventSource.Log.ResourceManagerCaseInsensitiveResourceStreamLookupFailed(_mediator.BaseName, _mediator.MainAssembly, satellite.GetSimpleName(), givenName); - } - } -#endif - if (canonicalName == null) { return null; } + // If we're looking in the main assembly AND if the main // assembly was the person who created the ResourceManager, // skip a security check for private manifest resources. bool canSkipSecurityCheck = _mediator.MainAssembly == satellite && _mediator.CallingAssembly == _mediator.MainAssembly; StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - Stream s = satellite.GetManifestResourceStream(canonicalName, ref stackMark, canSkipSecurityCheck); - // GetManifestResourceStream will return null if we don't have - // permission to read this stream from the assembly. For example, - // if the stream is private and we're trying to access it from another - // assembly (ie, ResMgr in mscorlib accessing anything else), we - // require Reflection TypeInformation permission to be able to read - // this. -#if !FEATURE_CORECLR - if (s!=null) { - if (FrameworkEventSource.IsInitialized) - { - FrameworkEventSource.Log.ResourceManagerManifestResourceAccessDenied(_mediator.BaseName, _mediator.MainAssembly, satellite.GetSimpleName(), canonicalName); - } - } -#endif - return s; + return satellite.GetManifestResourceStream(canonicalName, ref stackMark, canSkipSecurityCheck); } - [System.Security.SecurityCritical] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable private RuntimeAssembly GetSatelliteAssembly(CultureInfo lookForCulture, ref StackCrawlMark stackMark) { @@ -548,30 +443,16 @@ namespace System.Resources { int hr = fle._HResult; if (hr != Win32Native.MakeHRFromErrorCode(Win32Native.ERROR_ACCESS_DENIED)) { - Contract.Assert(false, "[This assert catches satellite assembly build/deployment problems - report this message to your build lab & loc engineer]" + Environment.NewLine + "GetSatelliteAssembly failed for culture " + lookForCulture.Name + " and version " + (_mediator.SatelliteContractVersion == null ? _mediator.MainAssembly.GetVersion().ToString() : _mediator.SatelliteContractVersion.ToString()) + " of assembly " + _mediator.MainAssembly.GetSimpleName() + " with error code 0x" + hr.ToString("X", CultureInfo.InvariantCulture) + Environment.NewLine + "Exception: " + fle); + Debug.Assert(false, "[This assert catches satellite assembly build/deployment problems - report this message to your build lab & loc engineer]" + Environment.NewLine + "GetSatelliteAssembly failed for culture " + lookForCulture.Name + " and version " + (_mediator.SatelliteContractVersion == null ? _mediator.MainAssembly.GetVersion().ToString() : _mediator.SatelliteContractVersion.ToString()) + " of assembly " + _mediator.MainAssembly.GetSimpleName() + " with error code 0x" + hr.ToString("X", CultureInfo.InvariantCulture) + Environment.NewLine + "Exception: " + fle); } } // Don't throw for zero-length satellite assemblies, for compat with v1 catch (BadImageFormatException bife) { - Contract.Assert(false, "[This assert catches satellite assembly build/deployment problems - report this message to your build lab & loc engineer]" + Environment.NewLine + "GetSatelliteAssembly failed for culture " + lookForCulture.Name + " and version " + (_mediator.SatelliteContractVersion == null ? _mediator.MainAssembly.GetVersion().ToString() : _mediator.SatelliteContractVersion.ToString()) + " of assembly " + _mediator.MainAssembly.GetSimpleName() + Environment.NewLine + "Exception: " + bife); + Debug.Assert(false, "[This assert catches satellite assembly build/deployment problems - report this message to your build lab & loc engineer]" + Environment.NewLine + "GetSatelliteAssembly failed for culture " + lookForCulture.Name + " and version " + (_mediator.SatelliteContractVersion == null ? _mediator.MainAssembly.GetVersion().ToString() : _mediator.SatelliteContractVersion.ToString()) + " of assembly " + _mediator.MainAssembly.GetSimpleName() + Environment.NewLine + "Exception: " + bife); } -#if !FEATURE_CORECLR - if (FrameworkEventSource.IsInitialized) - { - if (satellite != null) - { - FrameworkEventSource.Log.ResourceManagerGetSatelliteAssemblySucceeded(_mediator.BaseName, _mediator.MainAssembly, lookForCulture.Name, satAssemblyName); - } - else - { - FrameworkEventSource.Log.ResourceManagerGetSatelliteAssemblyFailed(_mediator.BaseName, _mediator.MainAssembly, lookForCulture.Name, satAssemblyName); - } - } -#endif - return satellite; } @@ -583,8 +464,8 @@ namespace System.Resources { // and causes partially trusted localized apps to fail. private bool CanUseDefaultResourceClasses(String readerTypeName, String resSetTypeName) { - Contract.Assert(readerTypeName != null, "readerTypeName shouldn't be null; check caller"); - Contract.Assert(resSetTypeName != null, "resSetTypeName shouldn't be null; check caller"); + Debug.Assert(readerTypeName != null, "readerTypeName shouldn't be null; check caller"); + Debug.Assert(resSetTypeName != null, "resSetTypeName shouldn't be null; check caller"); if (_mediator.UserResourceSet != null) return false; @@ -609,7 +490,6 @@ namespace System.Resources { return true; } - [System.Security.SecurityCritical] private String GetSatelliteAssemblyName() { String satAssemblyName = _mediator.MainAssembly.GetSimpleName(); @@ -617,7 +497,6 @@ namespace System.Resources { return satAssemblyName; } - [System.Security.SecurityCritical] private void HandleSatelliteMissing() { String satAssemName = _mediator.MainAssembly.GetSimpleName() + ".resources.dll"; @@ -646,14 +525,13 @@ namespace System.Resources { throw new MissingSatelliteAssemblyException(Environment.GetResourceString("MissingSatelliteAssembly_Culture_Name", _mediator.NeutralResourcesCulture, satAssemName), missingCultureName); } - [System.Security.SecurityCritical] // auto-generated private void HandleResourceStreamMissing(String fileName) { // Keep people from bothering me about resources problems if (_mediator.MainAssembly == typeof(Object).Assembly && _mediator.BaseName.Equals(System.CoreLib.Name)) { // This would break CultureInfo & all our exceptions. - Contract.Assert(false, "Couldn't get " + System.CoreLib.Name+ResourceManager.ResFileExtension + " from "+System.CoreLib.Name+"'s assembly" + Environment.NewLine + Environment.NewLine + "Are you building the runtime on your machine? Chances are the BCL directory didn't build correctly. Type 'build -c' in the BCL directory. If you get build errors, look at buildd.log. If you then can't figure out what's wrong (and you aren't changing the assembly-related metadata code), ask a BCL dev.\n\nIf you did NOT build the runtime, you shouldn't be seeing this and you've found a bug."); + Debug.Assert(false, "Couldn't get " + System.CoreLib.Name+ResourceManager.ResFileExtension + " from "+System.CoreLib.Name+"'s assembly" + Environment.NewLine + Environment.NewLine + "Are you building the runtime on your machine? Chances are the BCL directory didn't build correctly. Type 'build -c' in the BCL directory. If you get build errors, look at buildd.log. If you then can't figure out what's wrong (and you aren't changing the assembly-related metadata code), ask a BCL dev.\n\nIf you did NOT build the runtime, you shouldn't be seeing this and you've found a bug."); // We cannot continue further - simply FailFast. string mesgFailFast = System.CoreLib.Name + ResourceManager.ResFileExtension + " couldn't be found! Large parts of the BCL won't work!"; @@ -669,7 +547,6 @@ namespace System.Resources { } [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [System.Security.SecurityCritical] // Our security team doesn't yet allow safe-critical P/Invoke methods. [System.Security.SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool GetNeutralResourcesLanguageAttribute(RuntimeAssembly assemblyHandle, StringHandleOnStack cultureName, out short fallbackLocation); diff --git a/src/mscorlib/src/System/Resources/NeutralResourcesLanguageAttribute.cs b/src/mscorlib/src/System/Resources/NeutralResourcesLanguageAttribute.cs index 560cd5f..6517a56 100644 --- a/src/mscorlib/src/System/Resources/NeutralResourcesLanguageAttribute.cs +++ b/src/mscorlib/src/System/Resources/NeutralResourcesLanguageAttribute.cs @@ -35,7 +35,7 @@ namespace System.Resources { public NeutralResourcesLanguageAttribute(String cultureName) { if (cultureName == null) - throw new ArgumentNullException("cultureName"); + throw new ArgumentNullException(nameof(cultureName)); Contract.EndContractBlock(); _culture = cultureName; @@ -45,7 +45,7 @@ namespace System.Resources { public NeutralResourcesLanguageAttribute(String cultureName, UltimateResourceFallbackLocation location) { if (cultureName == null) - throw new ArgumentNullException("cultureName"); + throw new ArgumentNullException(nameof(cultureName)); if (!Enum.IsDefined(typeof(UltimateResourceFallbackLocation), location)) throw new ArgumentException(Environment.GetResourceString("Arg_InvalidNeutralResourcesLanguage_FallbackLoc", location)); Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/Resources/ResourceFallbackManager.cs b/src/mscorlib/src/System/Resources/ResourceFallbackManager.cs index def7836..de50ccc 100644 --- a/src/mscorlib/src/System/Resources/ResourceFallbackManager.cs +++ b/src/mscorlib/src/System/Resources/ResourceFallbackManager.cs @@ -17,9 +17,6 @@ using System; using System.Collections; using System.Collections.Generic; -#if FEATURE_CORECLR -using System.Diagnostics.Contracts; -#endif using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -33,8 +30,6 @@ namespace System.Resources private CultureInfo m_neutralResourcesCulture; private bool m_useParents; -// Added but disabled from desktop in .NET 4.0, stayed disabled in .NET 4.5 -#if FEATURE_CORECLR // This is a cache of the thread, process, user, and OS-preferred fallback cultures. // However, each thread may have a different value, and these may change during the // lifetime of the process. So this cache must be verified each time we use it. @@ -43,7 +38,6 @@ namespace System.Resources // as well to avoid differences across threads. [ThreadStatic] private static CultureInfo[] cachedOsFallbackArray; -#endif // FEATURE_CORECLR internal ResourceFallbackManager(CultureInfo startingCulture, CultureInfo neutralResourcesCulture, bool useParents) { @@ -91,8 +85,6 @@ namespace System.Resources yield break; } -// Added but disabled from desktop in .NET 4.0, stayed disabled in .NET 4.5 -#if FEATURE_CORECLR // 2. user preferred cultures, omitting starting culture if tried already // Compat note: For console apps, this API will return cultures like Arabic // or Hebrew that are displayed right-to-left. These don't work with today's @@ -118,7 +110,6 @@ namespace System.Resources } } } -#endif // FEATURE_CORECLR // 3. invariant // Don't return invariant twice though. @@ -128,8 +119,6 @@ namespace System.Resources yield return CultureInfo.InvariantCulture; } -// Added but disabled from desktop in .NET 4.0, stayed disabled in .NET 4.5 -#if FEATURE_CORECLR private static CultureInfo[] LoadPreferredCultures() { // The list of preferred cultures includes thread, process, user, and OS @@ -190,7 +179,6 @@ namespace System.Resources // Note: May return null. - [System.Security.SecuritySafeCritical] // auto-generated private static String[] GetResourceFallbackArray() { // AppCompat note: We've added this feature for desktop V4 but we ripped it out @@ -272,7 +260,5 @@ namespace System.Resources return CultureInfo.nativeGetResourceFallbackArray(); #endif } - -#endif // FEATURE_CORECLR } } diff --git a/src/mscorlib/src/System/Resources/ResourceManager.cs b/src/mscorlib/src/System/Resources/ResourceManager.cs index b088e7f..15f6af7 100644 --- a/src/mscorlib/src/System/Resources/ResourceManager.cs +++ b/src/mscorlib/src/System/Resources/ResourceManager.cs @@ -30,10 +30,8 @@ namespace System.Resources { using Microsoft.Win32; using System.Collections.Generic; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; -#if !FEATURE_CORECLR - using System.Diagnostics.Tracing; -#endif #if FEATURE_APPX // @@ -45,21 +43,16 @@ namespace System.Resources { // Also using interface or abstract class will not play nice with FriendAccessAllowed. // [FriendAccessAllowed] - [SecurityCritical] internal class WindowsRuntimeResourceManagerBase { - [SecurityCritical] public virtual bool Initialize(string libpath, string reswFilename, out PRIExceptionInfo exceptionInfo){exceptionInfo = null; return false;} - [SecurityCritical] public virtual String GetString(String stringName, String startingCulture, String neutralResourcesCulture){return null;} public virtual CultureInfo GlobalResourceContextBestFitCultureInfo { - [SecurityCritical] get { return null; } } - [SecurityCritical] public virtual bool SetGlobalResourceContextDefaultCulture(CultureInfo ci) { return false; } } @@ -266,13 +259,6 @@ namespace System.Resources { protected ResourceManager() { -#if !FEATURE_CORECLR - // This constructor is not designed to be used under AppX and is not in the Win8 profile. - // However designers may use them even if they are running under AppX since they are - // not subject to the restrictions of the Win8 profile. - Contract.Assert(!AppDomain.IsAppXModel() || AppDomain.IsAppXDesignMode()); -#endif - Init(); _lastUsedResourceCache = new CultureNameResourceSetPair(); @@ -292,18 +278,11 @@ namespace System.Resources { // private ResourceManager(String baseName, String resourceDir, Type usingResourceSet) { if (null==baseName) - throw new ArgumentNullException("baseName"); + throw new ArgumentNullException(nameof(baseName)); if (null==resourceDir) - throw new ArgumentNullException("resourceDir"); + throw new ArgumentNullException(nameof(resourceDir)); Contract.EndContractBlock(); -#if !FEATURE_CORECLR - // This constructor is not designed to be used under AppX and is not in the Win8 profile. - // However designers may use them even if they are running under AppX since they are - // not subject to the restrictions of the Win8 profile. - Contract.Assert(!AppDomain.IsAppXModel() || AppDomain.IsAppXDesignMode()); -#endif - BaseNameField = baseName; moduleDir = resourceDir; @@ -317,30 +296,16 @@ namespace System.Resources { ResourceManagerMediator mediator = new ResourceManagerMediator(this); resourceGroveler = new FileBasedResourceGroveler(mediator); - -#if !FEATURE_CORECLR // PAL doesn't support eventing, and we don't compile event providers for coreclr - if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled()) { - CultureInfo culture = CultureInfo.InvariantCulture; - String defaultResName = GetResourceFileName(culture); - - if (resourceGroveler.HasNeutralResources(culture, defaultResName)) { - FrameworkEventSource.Log.ResourceManagerNeutralResourcesFound(BaseNameField, MainAssembly, defaultResName); - } - else { - FrameworkEventSource.Log.ResourceManagerNeutralResourcesNotFound(BaseNameField, MainAssembly, defaultResName); - } - } -#endif } - + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable public ResourceManager(String baseName, Assembly assembly) { if (null==baseName) - throw new ArgumentNullException("baseName"); + throw new ArgumentNullException(nameof(baseName)); if (null==assembly) - throw new ArgumentNullException("assembly"); + throw new ArgumentNullException(nameof(assembly)); Contract.EndContractBlock(); if (!(assembly is RuntimeAssembly)) @@ -368,18 +333,11 @@ namespace System.Resources { public ResourceManager(String baseName, Assembly assembly, Type usingResourceSet) { if (null==baseName) - throw new ArgumentNullException("baseName"); + throw new ArgumentNullException(nameof(baseName)); if (null==assembly) - throw new ArgumentNullException("assembly"); + throw new ArgumentNullException(nameof(assembly)); Contract.EndContractBlock(); -#if !FEATURE_CORECLR - // This constructor is not designed to be used under AppX and is not in the Win8 profile. - // However designers may use them even if they are running under AppX since they are - // not subject to the restrictions of the Win8 profile. - Contract.Assert(!AppDomain.IsAppXModel() || AppDomain.IsAppXDesignMode()); -#endif - if (!(assembly is RuntimeAssembly)) throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly")); @@ -387,7 +345,7 @@ namespace System.Resources { BaseNameField = baseName; if (usingResourceSet != null && (usingResourceSet != _minResourceSet) && !(usingResourceSet.IsSubclassOf(_minResourceSet))) - throw new ArgumentException(Environment.GetResourceString("Arg_ResMgrNotResSet"), "usingResourceSet"); + throw new ArgumentException(Environment.GetResourceString("Arg_ResMgrNotResSet"), nameof(usingResourceSet)); _userResourceSet = usingResourceSet; CommonAssemblyInit(); @@ -404,7 +362,7 @@ namespace System.Resources { public ResourceManager(Type resourceSource) { if (null==resourceSource) - throw new ArgumentNullException("resourceSource"); + throw new ArgumentNullException(nameof(resourceSource)); Contract.EndContractBlock(); if (!(resourceSource is RuntimeType)) @@ -434,7 +392,6 @@ namespace System.Resources { this._lastUsedResourceCache = null; } - [System.Security.SecuritySafeCritical] [OnDeserialized] private void OnDeserialized(StreamingContext ctx) { @@ -479,7 +436,6 @@ namespace System.Resources { // Trying to unify code as much as possible, even though having to do a // security check in each constructor prevents it. - [System.Security.SecuritySafeCritical] private void CommonAssemblyInit() { if (_bUsingModernResourceManagement == false) @@ -496,30 +452,6 @@ namespace System.Resources { } _neutralResourcesCulture = ManifestBasedResourceGroveler.GetNeutralResourcesLanguage(MainAssembly, ref _fallbackLoc); - -#if !FEATURE_CORECLR // PAL doesn't support eventing, and we don't compile event providers for coreclr - if (_bUsingModernResourceManagement == false) - { - if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled()) { - CultureInfo culture = CultureInfo.InvariantCulture; - String defaultResName = GetResourceFileName(culture); - - if (resourceGroveler.HasNeutralResources(culture, defaultResName)) { - FrameworkEventSource.Log.ResourceManagerNeutralResourcesFound(BaseNameField, MainAssembly, defaultResName); - } - else { - String outputResName = defaultResName; - if (_locationInfo != null && _locationInfo.Namespace != null) - outputResName = _locationInfo.Namespace + Type.Delimiter + defaultResName; - FrameworkEventSource.Log.ResourceManagerNeutralResourcesNotFound(BaseNameField, MainAssembly, outputResName); - } - } - -#pragma warning disable 618 - ResourceSets = new Hashtable(); // for backward compatibility -#pragma warning restore 618 - } -#endif } // Gets the base name for the ResourceManager. @@ -557,12 +489,6 @@ namespace System.Resources { // creating a new ResourceManager isn't quite the correct behavior. public virtual void ReleaseAllResources() { -#if !FEATURE_CORECLR - if (FrameworkEventSource.IsInitialized) - { - FrameworkEventSource.Log.ResourceManagerReleasingResources(BaseNameField, MainAssembly); - } -#endif Dictionary localResourceSets = _resourceSets; // If any calls to Close throw, at least leave ourselves in a @@ -573,27 +499,9 @@ namespace System.Resources { lock(localResourceSets) { IDictionaryEnumerator setEnum = localResourceSets.GetEnumerator(); -#if !FEATURE_CORECLR - IDictionaryEnumerator setEnum2 = null; -#pragma warning disable 618 - if (ResourceSets != null) { - setEnum2 = ResourceSets.GetEnumerator(); - } - ResourceSets = new Hashtable(); // for backwards compat -#pragma warning restore 618 -#endif - while (setEnum.MoveNext()) { ((ResourceSet)setEnum.Value).Close(); } - -#if !FEATURE_CORECLR - if (setEnum2 != null) { - while (setEnum2.MoveNext()) { - ((ResourceSet)setEnum2.Value).Close(); - } - } -#endif } } @@ -677,11 +585,10 @@ namespace System.Resources { // if it hasn't yet been loaded and if parent CultureInfos should be // loaded as well for resource inheritance. // - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable public virtual ResourceSet GetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents) { if (null==culture) - throw new ArgumentNullException("culture"); + throw new ArgumentNullException(nameof(culture)); Contract.EndContractBlock(); Dictionary localResourceSets = _resourceSets; @@ -721,11 +628,10 @@ namespace System.Resources { // for getting a resource set lives. Access to it is controlled by // threadsafe methods such as GetResourceSet, GetString, & GetObject. // This will take a minimal number of locks. - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable protected virtual ResourceSet InternalGetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents) { - Contract.Assert(culture != null, "culture != null"); + Debug.Assert(culture != null, "culture != null"); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return InternalGetResourceSet(culture,createIfNotExists,tryParents, ref stackMark); @@ -735,7 +641,6 @@ namespace System.Resources { // for getting a resource set lives. Access to it is controlled by // threadsafe methods such as GetResourceSet, GetString, & GetObject. // This will take a minimal number of locks. - [System.Security.SecurityCritical] private ResourceSet InternalGetResourceSet(CultureInfo requestedCulture, bool createIfNotExists, bool tryParents, ref StackCrawlMark stackMark) { Dictionary localResourceSets = _resourceSets; @@ -743,11 +648,6 @@ namespace System.Resources { CultureInfo foundCulture = null; lock (localResourceSets) { if (localResourceSets.TryGetValue(requestedCulture.Name, out rs)) { -#if !FEATURE_CORECLR - if (FrameworkEventSource.IsInitialized) { - FrameworkEventSource.Log.ResourceManagerFoundResourceSetInCache(BaseNameField, MainAssembly, requestedCulture.Name); - } -#endif return rs; } } @@ -756,20 +656,8 @@ namespace System.Resources { foreach (CultureInfo currentCultureInfo in mgr) { -#if !FEATURE_CORECLR - if (FrameworkEventSource.IsInitialized) - { - FrameworkEventSource.Log.ResourceManagerLookingForResourceSet(BaseNameField, MainAssembly, currentCultureInfo.Name); - } -#endif lock(localResourceSets) { if (localResourceSets.TryGetValue(currentCultureInfo.Name, out rs)) { -#if !FEATURE_CORECLR - if (FrameworkEventSource.IsInitialized) - { - FrameworkEventSource.Log.ResourceManagerFoundResourceSetInCache(BaseNameField, MainAssembly, currentCultureInfo.Name); - } -#endif // we need to update the cache if we fellback if(requestedCulture != currentCultureInfo) foundCulture = currentCultureInfo; break; @@ -846,7 +734,7 @@ namespace System.Resources { { // Ensure that the assembly reference is not null if (a == null) { - throw new ArgumentNullException("a", Environment.GetResourceString("ArgumentNull_Assembly")); + throw new ArgumentNullException(nameof(a), Environment.GetResourceString("ArgumentNull_Assembly")); } Contract.EndContractBlock(); @@ -867,7 +755,7 @@ namespace System.Resources { Object[] attrs = a.GetCustomAttributes(typeof(SatelliteContractVersionAttribute), false); if (attrs.Length == 0) return null; - Contract.Assert(attrs.Length == 1, "Cannot have multiple instances of SatelliteContractVersionAttribute on an assembly!"); + Debug.Assert(attrs.Length == 1, "Cannot have multiple instances of SatelliteContractVersionAttribute on an assembly!"); v = ((SatelliteContractVersionAttribute)attrs[0]).Version; } Version ver; @@ -880,7 +768,7 @@ namespace System.Resources { // If this assert fires, please fix the build process for the // BCL directory. if (a == typeof(Object).Assembly) { - Contract.Assert(false, System.CoreLib.Name+"'s SatelliteContractVersionAttribute is a malformed version string!"); + Debug.Assert(false, System.CoreLib.Name+"'s SatelliteContractVersionAttribute is a malformed version string!"); return null; } @@ -894,7 +782,6 @@ namespace System.Resources { #endif } - [System.Security.SecuritySafeCritical] // auto-generated protected static CultureInfo GetNeutralResourcesLanguage(Assembly a) { // This method should be obsolete - replace it with the one below. @@ -909,7 +796,7 @@ namespace System.Resources { String typeName2, AssemblyName asmName2) { - Contract.Assert(asmTypeName1 != null, "asmTypeName1 was unexpectedly null"); + Debug.Assert(asmTypeName1 != null, "asmTypeName1 was unexpectedly null"); // First, compare type names int comma = asmTypeName1.IndexOf(','); @@ -961,13 +848,11 @@ namespace System.Resources { } #if FEATURE_APPX - [SecuritySafeCritical] - // Throws WinRT hresults private string GetStringFromPRI(String stringName, String startingCulture, String neutralResourcesCulture) { - Contract.Assert(_bUsingModernResourceManagement); - Contract.Assert(_WinRTResourceManager != null); - Contract.Assert(_PRIonAppXInitialized); - Contract.Assert(AppDomain.IsAppXModel()); + Debug.Assert(_bUsingModernResourceManagement); + Debug.Assert(_WinRTResourceManager != null); + Debug.Assert(_PRIonAppXInitialized); + Debug.Assert(AppDomain.IsAppXModel()); if (stringName.Length == 0) return null; @@ -987,7 +872,6 @@ namespace System.Resources { // Since we can't directly reference System.Runtime.WindowsRuntime from mscorlib, we have to get the type via reflection. // It would be better if we could just implement WindowsRuntimeResourceManager in mscorlib, but we can't, because // we can do very little with WinRT in mscorlib. - [SecurityCritical] internal static WindowsRuntimeResourceManagerBase GetWinRTResourceManager() { Type WinRTResourceManagerType = Type.GetType("System.Resources.WindowsRuntimeResourceManager, " + AssemblyRef.SystemRuntimeWindowsRuntime, true); @@ -1000,7 +884,6 @@ namespace System.Resources { #if FEATURE_APPX [NonSerialized] - [SecurityCritical] private WindowsRuntimeResourceManagerBase _WinRTResourceManager; // Written only by SetAppXConfiguration [NonSerialized] @@ -1029,12 +912,10 @@ namespace System.Resources { // // b) For any other non-FX assembly, we will use the modern resource manager with the premise that app package // contains the PRI resources. - [SecuritySafeCritical] private bool ShouldUseSatelliteAssemblyResourceLookupUnderAppX(RuntimeAssembly resourcesAssembly) { bool fUseSatelliteAssemblyResourceLookupUnderAppX = resourcesAssembly.IsFrameworkAssembly(); - -#if FEATURE_CORECLR + if (!fUseSatelliteAssemblyResourceLookupUnderAppX) { // Check to see if the assembly is under PLATFORM_RESOURCE_ROOTS. If it is, then we should use satellite assembly lookup for it. @@ -1055,23 +936,21 @@ namespace System.Resources { } } } -#endif // FEATURE_CORECLR + return fUseSatelliteAssemblyResourceLookupUnderAppX; - } - - [SecuritySafeCritical] + #endif // FEATURE_APPX // Only call SetAppXConfiguration from ResourceManager constructors, and nowhere else. // Throws MissingManifestResourceException and WinRT HResults private void SetAppXConfiguration() { - Contract.Assert(_bUsingModernResourceManagement == false); // Only this function writes to this member + Debug.Assert(_bUsingModernResourceManagement == false); // Only this function writes to this member #if FEATURE_APPX - Contract.Assert(_WinRTResourceManager == null); // Only this function writes to this member - Contract.Assert(_PRIonAppXInitialized == false); // Only this function writes to this member - Contract.Assert(_PRIExceptionInfo == null); // Only this function writes to this member + Debug.Assert(_WinRTResourceManager == null); // Only this function writes to this member + Debug.Assert(_PRIonAppXInitialized == false); // Only this function writes to this member + Debug.Assert(_PRIExceptionInfo == null); // Only this function writes to this member bool bUsingSatelliteAssembliesUnderAppX = false; @@ -1225,7 +1104,7 @@ namespace System.Resources { // public virtual String GetString(String name, CultureInfo culture) { if (null==name) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); Contract.EndContractBlock(); #if FEATURE_APPX @@ -1267,13 +1146,7 @@ namespace System.Resources { // This line behaves the same way as CultureInfo.CurrentUICulture would have in .NET 4 culture = Thread.CurrentThread.GetCurrentUICultureNoAppX(); } - -#if !FEATURE_CORECLR - if (FrameworkEventSource.IsInitialized) - { - FrameworkEventSource.Log.ResourceManagerLookupStarted(BaseNameField, MainAssembly, culture.Name); - } -#endif + ResourceSet last = GetFirstResourceSet(culture); if (last != null) @@ -1311,13 +1184,6 @@ namespace System.Resources { last = rs; } } - -#if !FEATURE_CORECLR - if (FrameworkEventSource.IsInitialized) - { - FrameworkEventSource.Log.ResourceManagerLookupFailed(BaseNameField, MainAssembly, culture.Name); - } -#endif } return null; @@ -1342,7 +1208,7 @@ namespace System.Resources { private Object GetObject(String name, CultureInfo culture, bool wrapUnmanagedMemStream) { if (null==name) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); Contract.EndContractBlock(); #if FEATURE_APPX @@ -1364,12 +1230,6 @@ namespace System.Resources { culture = Thread.CurrentThread.GetCurrentUICultureNoAppX(); } -#if !FEATURE_CORECLR - if (FrameworkEventSource.IsInitialized) - { - FrameworkEventSource.Log.ResourceManagerLookupStarted(BaseNameField, MainAssembly, culture.Name); - } -#endif ResourceSet last = GetFirstResourceSet(culture); if (last != null) { @@ -1422,12 +1282,6 @@ namespace System.Resources { } } -#if !FEATURE_CORECLR - if (FrameworkEventSource.IsInitialized) - { - FrameworkEventSource.Log.ResourceManagerLookupFailed(BaseNameField, MainAssembly, culture.Name); - } -#endif return null; } @@ -1448,7 +1302,6 @@ namespace System.Resources { #if RESOURCE_SATELLITE_CONFIG // Internal helper method - gives an end user the ability to prevent // satellite assembly probes for certain cultures via a config file. - [System.Security.SecurityCritical] // auto-generated private bool TryLookingForSatellite(CultureInfo lookForCulture) { if (!_checkedConfigFile) { @@ -1471,110 +1324,14 @@ namespace System.Resources { // The config file told us what satellites might be installed. int pos = Array.IndexOf(installedSatellites, lookForCulture.Name); -#if !FEATURE_CORECLR - if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled()) { - if (pos < 0) { - FrameworkEventSource.Log.ResourceManagerCultureNotFoundInConfigFile(BaseNameField, MainAssembly, lookForCulture.Name); - } - else { - FrameworkEventSource.Log.ResourceManagerCultureFoundInConfigFile(BaseNameField, MainAssembly, lookForCulture.Name); - } - } -#endif return pos >= 0; } // Note: There is one config file per appdomain. This is not // per-process nor per-assembly. - [System.Security.SecurityCritical] // auto-generated private Hashtable GetSatelliteAssembliesFromConfig() { -#if FEATURE_FUSION - - String fileName = AppDomain.CurrentDomain.FusionStore.ConfigurationFileInternal; - if (fileName == null) { - return null; - } - - // Don't do a security assert. We need to support semi-trusted - // scenarios, but asserting here causes infinite resource lookups - // while initializing security & looking up mscorlib's config file. - // Use internal methods to bypass security checks. - - // If we're dealing with a local file name or a UNC path instead - // of a URL, check to see if the file exists here for perf (avoids - // throwing a FileNotFoundException). - if (fileName.Length >= 2 && - ((fileName[1] == Path.VolumeSeparatorChar) || (fileName[0] == Path.DirectorySeparatorChar && fileName[1] == Path.DirectorySeparatorChar)) && - !File.InternalExists(fileName)) - return null; - - ConfigTreeParser parser = new ConfigTreeParser(); - String queryPath = "/configuration/satelliteassemblies"; - ConfigNode node = null; - // Catch exceptions in case a web app doesn't have a config file. - try { - node = parser.Parse(fileName, queryPath, true); - } - catch(Exception) {} - - if (node == null) { - return null; - } - - // The application config file will contain sections like this: - // - // - // - // - // fr - // - // - // fr-FR - // de-CH - // - // - // - // - // - Hashtable satelliteInfo = new Hashtable(StringComparer.OrdinalIgnoreCase); - foreach(ConfigNode assemblyNode in node.Children) { - if (!String.Equals(assemblyNode.Name, "assembly")) - throw new ApplicationException(Environment.GetResourceString("XMLSyntax_InvalidSyntaxSatAssemTag", Path.GetFileName(fileName), assemblyNode.Name)); - - if (assemblyNode.Attributes.Count == 0) - throw new ApplicationException(Environment.GetResourceString("XMLSyntax_InvalidSyntaxSatAssemTagNoAttr", Path.GetFileName(fileName))); - - DictionaryEntry de = (DictionaryEntry) assemblyNode.Attributes[0]; - String assemblyName = (String) de.Value; - if (!String.Equals(de.Key, "name") || String.IsNullOrEmpty(assemblyName) || assemblyNode.Attributes.Count > 1) - throw new ApplicationException(Environment.GetResourceString("XMLSyntax_InvalidSyntaxSatAssemTagBadAttr", Path.GetFileName(fileName), de.Key, de.Value)); - - ArrayList list = new ArrayList(5); - foreach(ConfigNode child in assemblyNode.Children) - if (child.Value != null) - list.Add(child.Value); - - String[] satellites = new String[list.Count]; - for(int i=0; i= 0, "negative ResourceTypeCode. What?"); + Debug.Assert(value >= 0, "negative ResourceTypeCode. What?"); return value <= ResourceTypeCode.LastPrimitive; } } @@ -94,10 +95,8 @@ namespace System.Resources { // of the assembly. The pointers here are pointers into that block of // memory controlled by the OS's loader. private int[] _nameHashes; // hash values for all names. - [SecurityCritical] private unsafe int* _nameHashesPtr; // In case we're using UnmanagedMemoryStream private int[] _namePositions; // relative locations of names - [SecurityCritical] private unsafe int* _namePositionsPtr; // If we're using UnmanagedMemoryStream private RuntimeType[] _typeTable; // Lazy array of Types for resource values. private int[] _typeNamePositions; // To delay initialize type table @@ -152,11 +151,6 @@ namespace System.Resources { }; #endif // FEATURE_SERIALIZATION - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif public ResourceReader(String fileName) { _resCache = new Dictionary(FastResourceComparer.Default); @@ -172,11 +166,10 @@ namespace System.Resources { } } - [System.Security.SecurityCritical] // auto-generated_required public ResourceReader(Stream stream) { if (stream==null) - throw new ArgumentNullException("stream"); + throw new ArgumentNullException(nameof(stream)); if (!stream.CanRead) throw new ArgumentException(Environment.GetResourceString("Argument_StreamNotReadable")); Contract.EndContractBlock(); @@ -194,7 +187,6 @@ namespace System.Resources { // passing in the stream to read from and the RuntimeResourceSet's // internal hash table (hash table of names with file offsets // and values, coupled to this ResourceReader). - [System.Security.SecurityCritical] // auto-generated internal ResourceReader(Stream stream, Dictionary resCache) { Contract.Requires(stream != null, "Need a stream!"); @@ -221,7 +213,6 @@ namespace System.Resources { Close(); } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe void Dispose(bool disposing) { if (_store != null) { @@ -243,7 +234,6 @@ namespace System.Resources { } } - [System.Security.SecurityCritical] // auto-generated internal static unsafe int ReadUnalignedI4(int* p) { byte* buffer = (byte*)p; @@ -264,11 +254,10 @@ namespace System.Resources { _store.BaseStream.Seek(stringLength, SeekOrigin.Current); } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe int GetNameHash(int index) { - Contract.Assert(index >=0 && index < _numResources, "Bad index into hash array. index: "+index); - Contract.Assert((_ums == null && _nameHashes != null && _nameHashesPtr == null) || + Debug.Assert(index >=0 && index < _numResources, "Bad index into hash array. index: "+index); + Debug.Assert((_ums == null && _nameHashes != null && _nameHashesPtr == null) || (_ums != null && _nameHashes == null && _nameHashesPtr != null), "Internal state mangled."); if (_ums == null) return _nameHashes[index]; @@ -276,11 +265,10 @@ namespace System.Resources { return ReadUnalignedI4(&_nameHashesPtr[index]); } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe int GetNamePosition(int index) { - Contract.Assert(index >=0 && index < _numResources, "Bad index into name position array. index: "+index); - Contract.Assert((_ums == null && _namePositions != null && _namePositionsPtr == null) || + Debug.Assert(index >=0 && index < _numResources, "Bad index into name position array. index: "+index); + Debug.Assert((_ums == null && _namePositions != null && _namePositionsPtr == null) || (_ums != null && _namePositions == null && _namePositionsPtr != null), "Internal state mangled."); int r; if (_ums == null) @@ -316,7 +304,7 @@ namespace System.Resources { // This does a binary search through the names. internal int FindPosForResource(String name) { - Contract.Assert(_store != null, "ResourceReader is closed!"); + Debug.Assert(_store != null, "ResourceReader is closed!"); int hash = FastResourceComparer.HashFunction(name); BCLDebug.Log("RESMGRFILEFORMAT", "FindPosForResource for "+name+" hash: "+hash.ToString("x", CultureInfo.InvariantCulture)); // Binary search over the hashes. Use the _namePositions array to @@ -395,10 +383,9 @@ namespace System.Resources { // with the string you pass in. // Whoever calls this method should make sure that they take a lock // so no one else can cause us to seek in the stream. - [System.Security.SecuritySafeCritical] // auto-generated private unsafe bool CompareStringEqualsName(String name) { - Contract.Assert(_store != null, "ResourceReader is closed!"); + Debug.Assert(_store != null, "ResourceReader is closed!"); int byteLen = _store.Read7BitEncodedInt(); if (byteLen < 0) { throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_NegativeStringLength")); @@ -433,10 +420,9 @@ namespace System.Resources { // This is used in the enumerator. The enumerator iterates from 0 to n // of our resources and this returns the resource name for a particular // index. The parameter is NOT a virtual offset. - [System.Security.SecurityCritical] // auto-generated private unsafe String AllocateStringForNameIndex(int index, out int dataOffset) { - Contract.Assert(_store != null, "ResourceReader is closed!"); + Debug.Assert(_store != null, "ResourceReader is closed!"); byte[] bytes; int byteLen; long nameVA = GetNamePosition(index); @@ -500,7 +486,7 @@ namespace System.Resources { // index. The parameter is NOT a virtual offset. private Object GetValueForNameIndex(int index) { - Contract.Assert(_store != null, "ResourceReader is closed!"); + Debug.Assert(_store != null, "ResourceReader is closed!"); long nameVA = GetNamePosition(index); lock(this) { _store.BaseStream.Seek(nameVA + _nameSectionOffset, SeekOrigin.Begin); @@ -525,7 +511,7 @@ namespace System.Resources { // no one can cause us to do a seek in here. internal String LoadString(int pos) { - Contract.Assert(_store != null, "ResourceReader is closed!"); + Debug.Assert(_store != null, "ResourceReader is closed!"); _store.BaseStream.Seek(_dataSectionOffset+pos, SeekOrigin.Begin); String s = null; int typeIndex = _store.Read7BitEncodedInt(); @@ -578,8 +564,8 @@ namespace System.Resources { // no one can cause us to do a seek in here. internal Object LoadObjectV1(int pos) { - Contract.Assert(_store != null, "ResourceReader is closed!"); - Contract.Assert(_version == 1, ".resources file was not a V1 .resources file!"); + Debug.Assert(_store != null, "ResourceReader is closed!"); + Debug.Assert(_version == 1, ".resources file was not a V1 .resources file!"); try { // mega try-catch performs exceptionally bad on x64; factored out body into @@ -595,7 +581,6 @@ namespace System.Resources { } #if FEATURE_SERIALIZATION - [SecuritySafeCritical] #endif private Object _LoadObjectV1(int pos) { _store.BaseStream.Seek(_dataSectionOffset+pos, SeekOrigin.Begin); @@ -654,8 +639,8 @@ namespace System.Resources { internal Object LoadObjectV2(int pos, out ResourceTypeCode typeCode) { - Contract.Assert(_store != null, "ResourceReader is closed!"); - Contract.Assert(_version >= 2, ".resources file was not a V2 (or higher) .resources file!"); + Debug.Assert(_store != null, "ResourceReader is closed!"); + Debug.Assert(_version >= 2, ".resources file was not a V2 (or higher) .resources file!"); try { // mega try-catch performs exceptionally bad on x64; factored out body into @@ -670,7 +655,6 @@ namespace System.Resources { } } - [System.Security.SecuritySafeCritical] // auto-generated private Object _LoadObjectV2(int pos, out ResourceTypeCode typeCode) { _store.BaseStream.Seek(_dataSectionOffset+pos, SeekOrigin.Begin); typeCode = (ResourceTypeCode) _store.Read7BitEncodedInt(); @@ -752,7 +736,7 @@ namespace System.Resources { byte[] bytes = new byte[len]; int r = _ums.Read(bytes, 0, len); - Contract.Assert(r == len, "ResourceReader needs to use a blocking read here. (Call _store.ReadBytes(len)?)"); + Debug.Assert(r == len, "ResourceReader needs to use a blocking read here. (Call _store.ReadBytes(len)?)"); return bytes; } @@ -801,7 +785,6 @@ namespace System.Resources { // deserialization binder to simulate a type-limiting deserializer. // This method handles types that are safe to deserialize, as well as // ensuring we only get back what we expect. - [System.Security.SecurityCritical] // auto-generated private Object DeserializeObject(int typeIndex) { RuntimeType type = FindType(typeIndex); @@ -843,10 +826,9 @@ namespace System.Resources { // Reads in the header information for a .resources file. Verifies some // of the assumptions about this resource set, and builds the class table // for the default resource file format. - [System.Security.SecurityCritical] // auto-generated private void ReadResources() { - Contract.Assert(_store != null, "ResourceReader is closed!"); + Debug.Assert(_store != null, "ResourceReader is closed!"); #if FEATURE_SERIALIZATION BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.File | StreamingContextStates.Persistence)); _typeLimitingBinder = new TypeLimitingDeserializationBinder(); @@ -867,7 +849,6 @@ namespace System.Resources { } } - [System.Security.SecurityCritical] // auto-generated private void _ReadResources() { // Read ResourceManager header @@ -1088,12 +1069,11 @@ namespace System.Resources { _store.BaseStream.Position = oldPos; } } - Contract.Assert(_typeTable[typeIndex] != null, "Should have found a type!"); + Debug.Assert(_typeTable[typeIndex] != null, "Should have found a type!"); return _typeTable[typeIndex]; } #if FEATURE_SERIALIZATION - [System.Security.SecurityCritical] // auto-generated private void InitSafeToDeserializeArray() { _safeToDeserialize = new bool[_typeTable.Length]; @@ -1165,7 +1145,7 @@ namespace System.Resources { public void GetResourceData(String resourceName, out String resourceType, out byte[] resourceData) { if (resourceName == null) - throw new ArgumentNullException("resourceName"); + throw new ArgumentNullException(nameof(resourceName)); Contract.EndContractBlock(); if (_resCache == null) throw new InvalidOperationException(Environment.GetResourceString("ResourceReaderIsClosed")); @@ -1200,10 +1180,10 @@ namespace System.Resources { Array.Sort(sortedDataPositions); int index = Array.BinarySearch(sortedDataPositions, dataPos); - Contract.Assert(index >= 0 && index < _numResources, "Couldn't find data position within sorted data positions array!"); + Debug.Assert(index >= 0 && index < _numResources, "Couldn't find data position within sorted data positions array!"); long nextData = (index < _numResources - 1) ? sortedDataPositions[index + 1] + _dataSectionOffset : _store.BaseStream.Length; int len = (int) (nextData - (dataPos + _dataSectionOffset)); - Contract.Assert(len >= 0 && len <= (int) _store.BaseStream.Length - dataPos + _dataSectionOffset, "Length was negative or outside the bounds of the file!"); + Debug.Assert(len >= 0 && len <= (int) _store.BaseStream.Length - dataPos + _dataSectionOffset, "Length was negative or outside the bounds of the file!"); // Read type code then byte[] _store.BaseStream.Position = _dataSectionOffset + dataPos; @@ -1227,12 +1207,12 @@ namespace System.Resources { { Contract.Requires(typeCode >= 0, "can't be negative"); if (typeCode < ResourceTypeCode.StartOfUserTypes) { - Contract.Assert(!String.Equals(typeCode.ToString(), "LastPrimitive"), "Change ResourceTypeCode metadata order so LastPrimitive isn't what Enum.ToString prefers."); + Debug.Assert(!String.Equals(typeCode.ToString(), "LastPrimitive"), "Change ResourceTypeCode metadata order so LastPrimitive isn't what Enum.ToString prefers."); return "ResourceTypeCode." + typeCode.ToString(); } else { int typeIndex = typeCode - ResourceTypeCode.StartOfUserTypes; - Contract.Assert(typeIndex >= 0 && typeIndex < _typeTable.Length, "TypeCode is broken or corrupted!"); + Debug.Assert(typeIndex >= 0 && typeIndex < _typeTable.Length, "TypeCode is broken or corrupted!"); long oldPos = _store.BaseStream.Position; try { _store.BaseStream.Position = _typeNamePositions[typeIndex]; @@ -1277,7 +1257,6 @@ namespace System.Resources { _typeToDeserialize = type; } - [System.Security.SecuritySafeCritical] // overrides transparent public member public override Type BindToType(string assemblyName, string typeName) { // BinaryObjectReader::Bind tries us first, then its own code. @@ -1343,7 +1322,6 @@ namespace System.Resources { } public Object Key { - [System.Security.SecuritySafeCritical] // auto-generated get { if (_currentName == ENUM_DONE) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumEnded)); if (!_currentIsValid) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumNotStarted)); @@ -1367,7 +1345,6 @@ namespace System.Resources { } public DictionaryEntry Entry { - [System.Security.SecuritySafeCritical] // auto-generated get { if (_currentName == ENUM_DONE) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumEnded)); if (!_currentIsValid) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumNotStarted)); diff --git a/src/mscorlib/src/System/Resources/ResourceSet.cs b/src/mscorlib/src/System/Resources/ResourceSet.cs index ed40a12..1b272fc 100644 --- a/src/mscorlib/src/System/Resources/ResourceSet.cs +++ b/src/mscorlib/src/System/Resources/ResourceSet.cs @@ -31,15 +31,11 @@ namespace System.Resources { // stores them in a hash table. Custom IResourceReaders can be used. // [Serializable] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public class ResourceSet : IDisposable, IEnumerable { [NonSerialized] protected IResourceReader Reader; -#if FEATURE_CORECLR internal Hashtable Table; -#else - protected Hashtable Table; -#endif private Hashtable _caseInsensitiveTable; // For case-insensitive lookups. @@ -65,9 +61,6 @@ namespace System.Resources { // implementation. Use this constructor to open & read from a file // on disk. // - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif public ResourceSet(String fileName) { Reader = new ResourceReader(fileName); @@ -89,7 +82,6 @@ namespace System.Resources { // implementation. Use this constructor to read from an open stream // of data. // - [System.Security.SecurityCritical] // auto-generated_required public ResourceSet(Stream stream) { Reader = new ResourceReader(stream); @@ -98,7 +90,6 @@ namespace System.Resources { } #if LOOSELY_LINKED_RESOURCE_REFERENCE - [System.Security.SecurityCritical] // auto_generated_required public ResourceSet(Stream stream, Assembly assembly) { Reader = new ResourceReader(stream); @@ -111,7 +102,7 @@ namespace System.Resources { public ResourceSet(IResourceReader reader) { if (reader == null) - throw new ArgumentNullException("reader"); + throw new ArgumentNullException(nameof(reader)); Contract.EndContractBlock(); Reader = reader; CommonInit(); @@ -122,7 +113,7 @@ namespace System.Resources { public ResourceSet(IResourceReader reader, Assembly assembly) { if (reader == null) - throw new ArgumentNullException("reader"); + throw new ArgumentNullException(nameof(reader)); Contract.EndContractBlock(); Reader = reader; CommonInit(); @@ -182,15 +173,13 @@ namespace System.Resources { return typeof(ResourceReader); } -#if !FEATURE_CORECLR // Returns the preferred IResourceWriter class for this kind of ResourceSet. // Subclasses of ResourceSet using their own Readers &; should override // GetDefaultReader and GetDefaultWriter. public virtual Type GetDefaultWriter() { - return typeof(ResourceWriter); + return Type.GetType("System.Resources.ResourceWriter, System.Resources.Writer, Version=4.0.1.0, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken, throwOnError: true); } -#endif // !FEATURE_CORECLR [ComVisible(false)] public virtual IDictionaryEnumerator GetEnumerator() @@ -291,7 +280,7 @@ namespace System.Resources { private Object GetObjectInternal(String name) { if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); Contract.EndContractBlock(); Hashtable copyOfTable = Table; // Avoid a race with Dispose diff --git a/src/mscorlib/src/System/Resources/RuntimeResourceSet.cs b/src/mscorlib/src/System/Resources/RuntimeResourceSet.cs index 6b512bc..a94ac82 100644 --- a/src/mscorlib/src/System/Resources/RuntimeResourceSet.cs +++ b/src/mscorlib/src/System/Resources/RuntimeResourceSet.cs @@ -20,6 +20,7 @@ namespace System.Resources { using System.Globalization; using System.Reflection; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; // A RuntimeResourceSet stores all the resources defined in one @@ -184,7 +185,6 @@ namespace System.Resources { // the resources once, adding them into the table. private bool _haveReadFromReader; - [System.Security.SecurityCritical] // auto-generated internal RuntimeResourceSet(String fileName) : base(false) { BCLDebug.Log("RESMGRFILEFORMAT", "RuntimeResourceSet .ctor(String)"); @@ -204,7 +204,6 @@ namespace System.Resources { Assembly = assembly; } #else - [System.Security.SecurityCritical] // auto-generated internal RuntimeResourceSet(Stream stream) : base(false) { BCLDebug.Log("RESMGRFILEFORMAT", "RuntimeResourceSet .ctor(Stream)"); @@ -285,7 +284,7 @@ namespace System.Resources { private Object GetObject(String key, bool ignoreCase, bool isString) { if (key==null) - throw new ArgumentNullException("key"); + throw new ArgumentNullException(nameof(key)); if (Reader == null || _resCache == null) throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_ResourceSet")); Contract.EndContractBlock(); @@ -312,7 +311,7 @@ namespace System.Resources { } if (dataPos != -1 && value == null) { - Contract.Assert(dataPos >= 0, "data section offset cannot be negative!"); + Debug.Assert(dataPos >= 0, "data section offset cannot be negative!"); // Normally calling LoadString or LoadObject requires // taking a lock. Note that in this case, we took a // lock on the entire RuntimeResourceSet, which is @@ -373,7 +372,7 @@ namespace System.Resources { Reader.Close(); } else { - Contract.Assert(ignoreCase, "This should only happen for case-insensitive lookups"); + Debug.Assert(ignoreCase, "This should only happen for case-insensitive lookups"); ResourceReader.ResourceEnumerator en = _defaultReader.GetEnumeratorInternal(); while (en.MoveNext()) { // Note: Always ask for the resource key before the data position. diff --git a/src/mscorlib/src/System/Resources/SatelliteContractVersionAttribute.cs b/src/mscorlib/src/System/Resources/SatelliteContractVersionAttribute.cs index f72e810..3272790 100644 --- a/src/mscorlib/src/System/Resources/SatelliteContractVersionAttribute.cs +++ b/src/mscorlib/src/System/Resources/SatelliteContractVersionAttribute.cs @@ -27,7 +27,7 @@ namespace System.Resources { public SatelliteContractVersionAttribute(String version) { if (version == null) - throw new ArgumentNullException("version"); + throw new ArgumentNullException(nameof(version)); Contract.EndContractBlock(); _version = version; } diff --git a/src/mscorlib/src/System/Resources/__FastResourceComparer.cs b/src/mscorlib/src/System/Resources/__FastResourceComparer.cs index 5bc7333..e0911fa 100644 --- a/src/mscorlib/src/System/Resources/__FastResourceComparer.cs +++ b/src/mscorlib/src/System/Resources/__FastResourceComparer.cs @@ -17,6 +17,7 @@ namespace System.Resources { using System; using System.Collections; using System.Collections.Generic; + using System.Diagnostics; using System.Diagnostics.Contracts; internal sealed class FastResourceComparer : IComparer, IEqualityComparer, IComparer, IEqualityComparer @@ -78,11 +79,10 @@ namespace System.Resources { // Input is one string to compare with, and a byte[] containing chars in // little endian unicode. Pass in the number of valid chars. - [System.Security.SecurityCritical] // auto-generated public unsafe static int CompareOrdinal(String a, byte[] bytes, int bCharLength) { - Contract.Assert(a != null && bytes != null, "FastResourceComparer::CompareOrdinal must have non-null params"); - Contract.Assert(bCharLength * 2 <= bytes.Length, "FastResourceComparer::CompareOrdinal - numChars is too big!"); + Debug.Assert(a != null && bytes != null, "FastResourceComparer::CompareOrdinal must have non-null params"); + Debug.Assert(bCharLength * 2 <= bytes.Length, "FastResourceComparer::CompareOrdinal - numChars is too big!"); // This is a managed version of strcmp, but I can't take advantage // of a terminating 0, unlike strcmp in C. int i = 0; @@ -107,7 +107,6 @@ namespace System.Resources { return a.Length - bCharLength; } - [System.Security.SecurityCritical] // auto-generated public static int CompareOrdinal(byte[] bytes, int aCharLength, String b) { return -CompareOrdinal(b, bytes, aCharLength); @@ -115,12 +114,11 @@ namespace System.Resources { // This method is to handle potentially misaligned data accesses. // The byte* must point to little endian Unicode characters. - [System.Security.SecurityCritical] // auto-generated internal unsafe static int CompareOrdinal(byte* a, int byteLen, String b) { - Contract.Assert((byteLen & 1) == 0, "CompareOrdinal is expecting a UTF-16 string length, which must be even!"); - Contract.Assert(a != null && b != null, "Null args not allowed."); - Contract.Assert(byteLen >= 0, "byteLen must be non-negative."); + Debug.Assert((byteLen & 1) == 0, "CompareOrdinal is expecting a UTF-16 string length, which must be even!"); + Debug.Assert(a != null && b != null, "Null args not allowed."); + Debug.Assert(byteLen >= 0, "byteLen must be non-negative."); int r = 0; int i = 0; diff --git a/src/mscorlib/src/System/RtType.cs b/src/mscorlib/src/System/RtType.cs index 037576f..168beef 100644 --- a/src/mscorlib/src/System/RtType.cs +++ b/src/mscorlib/src/System/RtType.cs @@ -25,12 +25,6 @@ using System.Runtime.CompilerServices; using System.Security; using System.Text; using System.Runtime.Remoting; -#if FEATURE_REMOTING -using System.Runtime.Remoting.Proxies; -using System.Runtime.Remoting.Messaging; -using System.Runtime.Remoting.Activation; -using System.Runtime.Remoting.Metadata; -#endif using MdSigCallingConvention = System.Signature.MdSigCallingConvention; using RuntimeTypeCache = System.RuntimeType.RuntimeTypeCache; using System.Runtime.InteropServices; @@ -203,7 +197,6 @@ namespace System private MemberListType m_listType; private uint m_nameHash; - [System.Security.SecurityCritical] // auto-generated public unsafe Filter(byte* pUtf8Name, int cUtf8Name, MemberListType listType) { this.m_name = new Utf8String((void*) pUtf8Name, cUtf8Name); @@ -227,7 +220,7 @@ namespace System // Currently the callers of UsesStringComparison assume that if it returns false // then the match always succeeds and can be skipped. Assert that this is maintained. - Contract.Assert(retVal || RequiresStringComparison()); + Debug.Assert(retVal || RequiresStringComparison()); return retVal; } @@ -248,7 +241,7 @@ namespace System public uint GetHashToMatch() { - Contract.Assert(RequiresStringComparison()); + Debug.Assert(RequiresStringComparison()); return m_nameHash; } @@ -272,7 +265,6 @@ namespace System #region Constructor #if MDA_SUPPORTED - [System.Security.SecuritySafeCritical] // auto-generated #endif internal MemberInfoCache(RuntimeTypeCache runtimeTypeCache) { @@ -282,7 +274,6 @@ namespace System m_runtimeTypeCache = runtimeTypeCache; } - [System.Security.SecuritySafeCritical] // auto-generated internal MethodBase AddMethod(RuntimeType declaringType, RuntimeMethodHandleInternal method, CacheType cacheType) { T[] list = null; @@ -310,7 +301,6 @@ namespace System return (MethodBase)(object)list[0]; } - [System.Security.SecuritySafeCritical] // auto-generated internal FieldInfo AddField(RuntimeFieldHandleInternal field) { // create the runtime field info @@ -333,7 +323,6 @@ namespace System return (FieldInfo)(object)list[0]; } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe T[] Populate(string name, MemberListType listType, CacheType cacheType) { T[] list = null; @@ -372,7 +361,6 @@ namespace System return list; } - [System.Security.SecurityCritical] // auto-generated private unsafe T[] GetListByName(char* pName, int cNameLen, byte* pUtf8Name, int cUtf8Name, MemberListType listType, CacheType cacheType) { if (cNameLen != 0) @@ -415,7 +403,6 @@ namespace System // May replace the list with a new one if certain cache // lookups succeed. Also, may modify the contents of the list // after merging these new data structures with cached ones. - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal void Insert(ref T[] list, string name, MemberListType listType) { @@ -545,7 +532,7 @@ namespace System // Grow the list by exactly one element in this case to avoid null entries at the end. // - Contract.Assert(false); + Debug.Assert(false); newSize = cachedMembers.Length + 1; } @@ -560,7 +547,7 @@ namespace System cachedMembers = cachedMembers2; } - Contract.Assert(cachedMembers[freeSlotIndex] == null); + Debug.Assert(cachedMembers[freeSlotIndex] == null); cachedMembers[freeSlotIndex] = newMemberInfo; freeSlotIndex++; } @@ -572,13 +559,12 @@ namespace System #region Population Logic - [System.Security.SecuritySafeCritical] // auto-generated private unsafe RuntimeMethodInfo[] PopulateMethods(Filter filter) { ListBuilder list = new ListBuilder(); RuntimeType declaringType = ReflectedType; - Contract.Assert(declaringType != null); + Debug.Assert(declaringType != null); if (RuntimeTypeHandle.IsInterface(declaringType)) { @@ -590,7 +576,7 @@ namespace System { if (!RuntimeMethodHandle.MatchesNameHash(methodHandle, filter.GetHashToMatch())) { - Contract.Assert(!filter.Match(RuntimeMethodHandle.GetUtf8Name(methodHandle))); + Debug.Assert(!filter.Match(RuntimeMethodHandle.GetUtf8Name(methodHandle))); continue; } @@ -599,10 +585,10 @@ namespace System } #region Loop through all methods on the interface - Contract.Assert(!methodHandle.IsNullHandle()); + Debug.Assert(!methodHandle.IsNullHandle()); // Except for .ctor, .cctor, IL_STUB*, and static methods, all interface methods should be abstract, virtual, and non-RTSpecialName. // Note that this assumption will become invalid when we add support for non-abstract or static methods on interfaces. - Contract.Assert( + Debug.Assert( (RuntimeMethodHandle.GetAttributes(methodHandle) & (MethodAttributes.RTSpecialName | MethodAttributes.Abstract | MethodAttributes.Virtual)) == (MethodAttributes.Abstract | MethodAttributes.Virtual) || (RuntimeMethodHandle.GetAttributes(methodHandle) & MethodAttributes.Static) == MethodAttributes.Static || RuntimeMethodHandle.GetName(methodHandle).Equals(".ctor") || @@ -650,7 +636,7 @@ namespace System { if (!RuntimeMethodHandle.MatchesNameHash(methodHandle, filter.GetHashToMatch())) { - Contract.Assert(!filter.Match(RuntimeMethodHandle.GetUtf8Name(methodHandle))); + Debug.Assert(!filter.Match(RuntimeMethodHandle.GetUtf8Name(methodHandle))); continue; } @@ -659,13 +645,13 @@ namespace System } #region Loop through all methods on the current type - Contract.Assert(!methodHandle.IsNullHandle()); + Debug.Assert(!methodHandle.IsNullHandle()); MethodAttributes methodAttributes = RuntimeMethodHandle.GetAttributes(methodHandle); MethodAttributes methodAccess = methodAttributes & MethodAttributes.MemberAccessMask; #region Continue if this is a constructor - Contract.Assert( + Debug.Assert( (RuntimeMethodHandle.GetAttributes(methodHandle) & MethodAttributes.RTSpecialName) == 0 || RuntimeMethodHandle.GetName(methodHandle).Equals(".ctor") || RuntimeMethodHandle.GetName(methodHandle).Equals(".cctor")); @@ -697,7 +683,7 @@ namespace System #region Continue if this is a virtual and is already overridden if (isVirtual) { - Contract.Assert( + Debug.Assert( (methodAttributes & MethodAttributes.Abstract) != 0 || (methodAttributes & MethodAttributes.Virtual) != 0 || RuntimeMethodHandle.GetDeclaringType(methodHandle) != declaringType); @@ -714,7 +700,7 @@ namespace System } else { - Contract.Assert((methodAttributes & (MethodAttributes.Virtual | MethodAttributes.Abstract)) == 0); + Debug.Assert((methodAttributes & (MethodAttributes.Virtual | MethodAttributes.Abstract)) == 0); } #endregion @@ -742,7 +728,6 @@ namespace System return list.ToArray(); } - [System.Security.SecuritySafeCritical] // auto-generated private RuntimeConstructorInfo[] PopulateConstructors(Filter filter) { if (ReflectedType.IsGenericParameter) @@ -760,7 +745,7 @@ namespace System { if (!RuntimeMethodHandle.MatchesNameHash(methodHandle, filter.GetHashToMatch())) { - Contract.Assert(!filter.Match(RuntimeMethodHandle.GetUtf8Name(methodHandle))); + Debug.Assert(!filter.Match(RuntimeMethodHandle.GetUtf8Name(methodHandle))); continue; } @@ -770,13 +755,13 @@ namespace System MethodAttributes methodAttributes = RuntimeMethodHandle.GetAttributes(methodHandle); - Contract.Assert(!methodHandle.IsNullHandle()); + Debug.Assert(!methodHandle.IsNullHandle()); if ((methodAttributes & MethodAttributes.RTSpecialName) == 0) continue; // Constructors should not be virtual or abstract - Contract.Assert( + Debug.Assert( (methodAttributes & MethodAttributes.Abstract) == 0 && (methodAttributes & MethodAttributes.Virtual) == 0); @@ -799,7 +784,6 @@ namespace System return list.ToArray(); } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe RuntimeFieldInfo[] PopulateFields(Filter filter) { ListBuilder list = new ListBuilder(); @@ -851,7 +835,6 @@ namespace System return list.ToArray(); } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe void PopulateRtFields(Filter filter, RuntimeType declaringType, ref ListBuilder list) { IntPtr* pResult = stackalloc IntPtr[64]; @@ -871,7 +854,6 @@ namespace System } } - [System.Security.SecurityCritical] // auto-generated private unsafe void PopulateRtFields(Filter filter, IntPtr* ppFieldHandles, int count, RuntimeType declaringType, ref ListBuilder list) { @@ -889,7 +871,7 @@ namespace System { if (!RuntimeFieldHandle.MatchesNameHash(runtimeFieldHandle, filter.GetHashToMatch())) { - Contract.Assert(!filter.Match(RuntimeFieldHandle.GetUtf8Name(runtimeFieldHandle))); + Debug.Assert(!filter.Match(RuntimeFieldHandle.GetUtf8Name(runtimeFieldHandle))); continue; } @@ -897,7 +879,7 @@ namespace System continue; } - Contract.Assert(!runtimeFieldHandle.IsNullHandle()); + Debug.Assert(!runtimeFieldHandle.IsNullHandle()); FieldAttributes fieldAttributes = RuntimeFieldHandle.GetAttributes(runtimeFieldHandle); FieldAttributes fieldAccess = fieldAttributes & FieldAttributes.FieldAccessMask; @@ -925,7 +907,6 @@ namespace System } } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe void PopulateLiteralFields(Filter filter, RuntimeType declaringType, ref ListBuilder list) { Contract.Requires(declaringType != null); @@ -945,8 +926,8 @@ namespace System for (int i = 0; i < tkFields.Length; i++) { int tkField = tkFields[i]; - Contract.Assert(MdToken.IsTokenOfType(tkField, MetadataTokenType.FieldDef)); - Contract.Assert(!MdToken.IsNullToken(tkField)); + Debug.Assert(MdToken.IsTokenOfType(tkField, MetadataTokenType.FieldDef)); + Debug.Assert(!MdToken.IsNullToken(tkField)); FieldAttributes fieldAttributes; scope.GetFieldDefProps(tkField, out fieldAttributes); @@ -1030,7 +1011,6 @@ namespace System } - [System.Security.SecuritySafeCritical] // auto-generated private RuntimeType[] PopulateInterfaces(Filter filter) { ListBuilder list = new ListBuilder(); @@ -1053,7 +1033,7 @@ namespace System continue; } - Contract.Assert(interfaceType.IsInterface); + Debug.Assert(interfaceType.IsInterface); list.Add(interfaceType); } } @@ -1120,7 +1100,6 @@ namespace System return list.ToArray(); } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe RuntimeType[] PopulateNestedClasses(Filter filter) { RuntimeType declaringType = ReflectedType; @@ -1171,7 +1150,6 @@ namespace System return list.ToArray(); } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe RuntimeEventInfo[] PopulateEvents(Filter filter) { Contract.Requires(ReflectedType != null); @@ -1204,7 +1182,6 @@ namespace System return list.ToArray(); } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe void PopulateEvents( Filter filter, RuntimeType declaringType, Dictionary csEventInfos, ref ListBuilder list) { @@ -1224,8 +1201,8 @@ namespace System int tkEvent = tkEvents[i]; bool isPrivate; - Contract.Assert(!MdToken.IsNullToken(tkEvent)); - Contract.Assert(MdToken.IsTokenOfType(tkEvent, MetadataTokenType.Event)); + Debug.Assert(!MdToken.IsNullToken(tkEvent)); + Debug.Assert(MdToken.IsTokenOfType(tkEvent, MetadataTokenType.Event)); if (filter.RequiresStringComparison()) { @@ -1265,7 +1242,6 @@ namespace System } } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe RuntimePropertyInfo[] PopulateProperties(Filter filter) { Contract.Requires(ReflectedType != null); @@ -1274,7 +1250,7 @@ namespace System // is called in Populate after this returns. RuntimeType declaringType = ReflectedType; - Contract.Assert(declaringType != null); + Debug.Assert(declaringType != null); ListBuilder list = new ListBuilder(); @@ -1306,7 +1282,6 @@ namespace System return list.ToArray(); } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe void PopulateProperties( Filter filter, RuntimeType declaringType, @@ -1329,7 +1304,7 @@ namespace System int numVirtuals = RuntimeTypeHandle.GetNumVirtuals(declaringType); - Contract.Assert((declaringType.IsInterface && usedSlots == null && csPropertyInfos == null) || + Debug.Assert((declaringType.IsInterface && usedSlots == null && csPropertyInfos == null) || (!declaringType.IsInterface && usedSlots != null && usedSlots.Length >= numVirtuals)); for (int i = 0; i < tkProperties.Length; i++) @@ -1337,14 +1312,14 @@ namespace System int tkProperty = tkProperties[i]; bool isPrivate; - Contract.Assert(!MdToken.IsNullToken(tkProperty)); - Contract.Assert(MdToken.IsTokenOfType(tkProperty, MetadataTokenType.Property)); + Debug.Assert(!MdToken.IsNullToken(tkProperty)); + Debug.Assert(MdToken.IsTokenOfType(tkProperty, MetadataTokenType.Property)); if (filter.RequiresStringComparison()) { if (!ModuleHandle.ContainsPropertyMatchingHash(declaringModuleHandle, tkProperty, filter.GetHashToMatch())) { - Contract.Assert(!filter.Match(declaringType.GetRuntimeModule().MetadataImport.GetName(tkProperty))); + Debug.Assert(!filter.Match(declaringType.GetRuntimeModule().MetadataImport.GetName(tkProperty))); continue; } @@ -1389,7 +1364,7 @@ namespace System if (slot < numVirtuals) { - Contract.Assert(associateMethod.IsVirtual); + Debug.Assert(associateMethod.IsVirtual); if (usedSlots[slot] == true) continue; else @@ -1475,7 +1450,7 @@ namespace System return Populate(name, listType, cacheType); default: - Contract.Assert(listType == MemberListType.All); + Debug.Assert(listType == MemberListType.All); if (Volatile.Read(ref m_cacheComplete)) return m_allMembers; @@ -1514,9 +1489,6 @@ namespace System private MemberInfoCache m_eventInfoCache; private static CerHashtable s_methodInstantiations; private static Object s_methodInstantiationsLock; -#if !FEATURE_CORECLR - private RuntimeConstructorInfo m_serializationCtor; -#endif private string m_defaultMemberName; private Object m_genericCache; // Generic cache for rare scenario specific data. It is used to cache Enum names and values. #endregion @@ -1614,7 +1586,6 @@ namespace System } } - [System.Security.SecuritySafeCritical] internal unsafe string GetNameSpace() { // @Optimization - Use ConstructName to populate m_namespace @@ -1638,14 +1609,13 @@ namespace System set { m_typeCode = value; } } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe RuntimeType GetEnclosingType() { if (m_enclosingType == null) { // Use void as a marker of null enclosing type RuntimeType enclosingType = RuntimeTypeHandle.GetDeclaringType(GetRuntimeType()); - Contract.Assert(enclosingType != typeof(void)); + Debug.Assert(enclosingType != typeof(void)); m_enclosingType = enclosingType ?? (RuntimeType)typeof(void); } @@ -1668,26 +1638,6 @@ namespace System m_nestedClassesCache = null; } -#if !FEATURE_CORECLR - internal RuntimeConstructorInfo GetSerializationCtor() - { - if (m_serializationCtor == null) - { - if (s_SICtorParamTypes == null) - s_SICtorParamTypes = new Type[] { typeof(SerializationInfo), typeof(StreamingContext) }; - - m_serializationCtor = m_runtimeType.GetConstructor( - BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, - null, - CallingConventions.Any, - s_SICtorParamTypes, - null) as RuntimeConstructorInfo; - } - - return m_serializationCtor; - } -#endif //!FEATURE_CORECLR - internal string GetDefaultMemberName() { if (m_defaultMemberName == null) @@ -1719,7 +1669,6 @@ namespace System #endregion #region Caches Accessors - [System.Security.SecurityCritical] // auto-generated internal MethodInfo GetGenericMethodInfo(RuntimeMethodHandleInternal genericMethod) { LoaderAllocator la = RuntimeMethodHandle.GetLoaderAllocator(genericMethod); @@ -1832,36 +1781,6 @@ namespace System } #endregion -#if FEATURE_REMOTING - #region Legacy Remoting Cache - // The size of CachedData is accounted for by BaseObjectWithCachedData in object.h. - // This member is currently being used by Remoting for caching remoting data. If you - // need to cache data here, talk to the Remoting team to work out a mechanism, so that - // both caching systems can happily work together. - private RemotingTypeCachedData m_cachedData; - - internal RemotingTypeCachedData RemotingCache - { - get - { - // This grabs an internal copy of m_cachedData and uses - // that instead of looking at m_cachedData directly because - // the cache may get cleared asynchronously. This prevents - // us from having to take a lock. - RemotingTypeCachedData cache = m_cachedData; - if (cache == null) - { - cache = new RemotingTypeCachedData(this); - RemotingTypeCachedData ret = Interlocked.CompareExchange(ref m_cachedData, cache, null); - if (ret != null) - cache = ret; - } - return cache; - } - } - #endregion -#endif //FEATURE_REMOTING - #region Static Members #region Internal @@ -1869,7 +1788,7 @@ namespace System ref StackCrawlMark stackMark) { if (typeName == null) - throw new ArgumentNullException("typeName"); + throw new ArgumentNullException(nameof(typeName)); Contract.EndContractBlock(); return RuntimeTypeHandle.GetTypeByName( @@ -1886,7 +1805,6 @@ namespace System return GetMethodBase(null, methodHandle); } - [System.Security.SecuritySafeCritical] internal static MethodBase GetMethodBase(RuntimeType reflectedType, IRuntimeMethodInfo methodHandle) { MethodBase retval = RuntimeType.GetMethodBase(reflectedType, methodHandle.Value); @@ -1894,10 +1812,9 @@ namespace System return retval; } - [System.Security.SecurityCritical] // auto-generated internal unsafe static MethodBase GetMethodBase(RuntimeType reflectedType, RuntimeMethodHandleInternal methodHandle) { - Contract.Assert(!methodHandle.IsNullHandle()); + Debug.Assert(!methodHandle.IsNullHandle()); if (RuntimeMethodHandle.IsDynamicMethod(methodHandle)) { @@ -2037,13 +1954,11 @@ namespace System set { Cache.DomainInitialized = value; } } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static FieldInfo GetFieldInfo(IRuntimeFieldInfo fieldHandle) { return GetFieldInfo(RuntimeFieldHandle.GetApproxDeclaringType(fieldHandle), fieldHandle); } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static FieldInfo GetFieldInfo(RuntimeType reflectedType, IRuntimeFieldInfo field) { RuntimeFieldHandleInternal fieldHandle = field.Value; @@ -2119,7 +2034,6 @@ namespace System Environment.GetResourceString("Argument_NotEnoughGenArguments", genericArguments.Length, genericParamters.Length)); } - [System.Security.SecuritySafeCritical] // auto-generated internal static void ValidateGenericArguments(MemberInfo definition, RuntimeType[] genericArguments, Exception e) { RuntimeType[] typeContext = null; @@ -2178,7 +2092,7 @@ namespace System name = fullname.Substring(nsDelimiter + 1, nameLength); else name = ""; - Contract.Assert(fullname.Equals(ns + "." + name)); + Debug.Assert(fullname.Equals(ns + "." + name)); } else { @@ -2270,7 +2184,7 @@ namespace System // Most of the plural GetXXX methods allow prefix lookups while the singular GetXXX methods mostly do not. private static bool FilterApplyPrefixLookup(MemberInfo memberInfo, string name, bool ignoreCase) { - Contract.Assert(name != null); + Debug.Assert(name != null); if (ignoreCase) { @@ -2376,7 +2290,7 @@ namespace System Type type, BindingFlags bindingFlags, string name, bool prefixLookup, string ns) { Contract.Requires((object)type != null); - Contract.Assert(type is RuntimeType); + Debug.Assert(type is RuntimeType); bool isPublic = type.IsNestedPublic || type.IsPublic; bool isStatic = false; @@ -2461,7 +2375,7 @@ namespace System { // If Binding flags did not include varargs we would have filtered this vararg method. // This Invariant established during callConv check. - Contract.Assert((callConv & CallingConventions.VarArgs) != 0); + Debug.Assert((callConv & CallingConventions.VarArgs) != 0); } #endregion } @@ -2632,7 +2546,6 @@ namespace System private RuntimeTypeCache Cache { - [System.Security.SecuritySafeCritical] // auto-generated get { if (m_cache.IsNull()) @@ -2654,7 +2567,7 @@ namespace System cache = existingCache; } - Contract.Assert(cache != null); + Debug.Assert(cache != null); return cache; } } @@ -2681,13 +2594,6 @@ namespace System { return Cache.GetDefaultMemberName(); } - -#if !FEATURE_CORECLR - internal RuntimeConstructorInfo GetSerializationCtor() - { - return Cache.GetSerializationCtor(); - } -#endif #endregion #region Type Overrides @@ -2868,7 +2774,6 @@ namespace System return GetFieldCandidates(null, bindingAttr, false).ToArray(); } - [System.Security.SecuritySafeCritical] // auto-generated public override Type[] GetInterfaces() { RuntimeType[] candidates = this.Cache.GetInterfaceList(MemberListType.All, null); @@ -2909,31 +2814,30 @@ namespace System events.CopyTo(members, i); i += events.Count; fields.CopyTo(members, i); i += fields.Count; nestedTypes.CopyTo(members, i); i += nestedTypes.Count; - Contract.Assert(i == members.Length); + Debug.Assert(i == members.Length); return members; } - [System.Security.SecuritySafeCritical] // auto-generated public override InterfaceMapping GetInterfaceMap(Type ifaceType) { if (IsGenericParameter) throw new InvalidOperationException(Environment.GetResourceString("Arg_GenericParameter")); if ((object)ifaceType == null) - throw new ArgumentNullException("ifaceType"); + throw new ArgumentNullException(nameof(ifaceType)); Contract.EndContractBlock(); RuntimeType ifaceRtType = ifaceType as RuntimeType; if (ifaceRtType == null) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "ifaceType"); + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), nameof(ifaceType)); RuntimeTypeHandle ifaceRtTypeHandle = ifaceRtType.GetTypeHandleInternal(); GetTypeHandleInternal().VerifyInterfaceIsImplemented(ifaceRtTypeHandle); - Contract.Assert(ifaceType.IsInterface); // VerifyInterfaceIsImplemented enforces this invariant - Contract.Assert(!IsInterface); // VerifyInterfaceIsImplemented enforces this invariant + Debug.Assert(ifaceType.IsInterface); // VerifyInterfaceIsImplemented enforces this invariant + Debug.Assert(!IsInterface); // VerifyInterfaceIsImplemented enforces this invariant // SZArrays implement the methods on IList`1, IEnumerable`1, and ICollection`1 with // SZArrayHelper and some runtime magic. We don't have accurate interface maps for them. @@ -2954,7 +2858,7 @@ namespace System // GetMethodBase will convert this to the instantiating/unboxing stub if necessary MethodBase ifaceMethodBase = RuntimeType.GetMethodBase(ifaceRtType, ifaceRtMethodHandle); - Contract.Assert(ifaceMethodBase is RuntimeMethodInfo); + Debug.Assert(ifaceMethodBase is RuntimeMethodInfo); im.InterfaceMethods[i] = (MethodInfo)ifaceMethodBase; // If the slot is -1, then virtual stub dispatch is active. @@ -2967,7 +2871,7 @@ namespace System // GetMethodBase will convert this to the instantiating/unboxing stub if necessary MethodBase rtTypeMethodBase = RuntimeType.GetMethodBase(this, classRtMethodHandle); // a class may not implement all the methods of an interface (abstract class) so null is a valid value - Contract.Assert(rtTypeMethodBase == null || rtTypeMethodBase is RuntimeMethodInfo); + Debug.Assert(rtTypeMethodBase == null || rtTypeMethodBase is RuntimeMethodInfo); im.TargetMethods[i] = (MethodInfo)rtTypeMethodBase; } @@ -3301,7 +3205,7 @@ namespace System events.CopyTo(compressMembers, i); i += events.Count; fields.CopyTo(compressMembers, i); i += fields.Count; nestedTypes.CopyTo(compressMembers, i); i += nestedTypes.Count; - Contract.Assert(i == compressMembers.Length); + Debug.Assert(i == compressMembers.Length); return compressMembers; } @@ -3348,13 +3252,11 @@ namespace System return new RuntimeTypeHandle(this); } - [System.Security.SecuritySafeCritical] internal bool IsCollectible() { return RuntimeTypeHandle.IsCollectible(GetTypeHandleInternal()); } - [System.Security.SecuritySafeCritical] // auto-generated protected override TypeCode GetTypeCodeImpl() { TypeCode typeCode = Cache.TypeCode; @@ -3435,7 +3337,6 @@ namespace System #endregion #region Hierarchy - [System.Security.SecuritySafeCritical] // auto-generated public override bool IsInstanceOfType(Object o) { return RuntimeTypeHandle.IsInstanceOfType(this, o); @@ -3446,7 +3347,7 @@ namespace System public override bool IsSubclassOf(Type type) { if ((object)type == null) - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); Contract.EndContractBlock(); RuntimeType rtType = type as RuntimeType; if (rtType == null) @@ -3519,23 +3420,6 @@ namespace System return false; } -#if !FEATURE_CORECLR - // Reflexive, symmetric, transitive. - public override bool IsEquivalentTo(Type other) - { - RuntimeType otherRtType = other as RuntimeType; - if ((object)otherRtType == null) - return false; - - if (otherRtType == this) - return true; - - // It's not worth trying to perform further checks in managed - // as they would lead to FCalls anyway. - return RuntimeTypeHandle.IsEquivalentTo(this, otherRtType); - } -#endif // FEATURE_CORECLR - public override Type BaseType { get @@ -3636,7 +3520,6 @@ namespace System #endregion #region Attributes - [System.Security.SecuritySafeCritical] // auto-generated protected override TypeAttributes GetAttributeFlagsImpl() { return RuntimeTypeHandle.GetAttributes(this); @@ -3644,7 +3527,6 @@ namespace System public override Guid GUID { - [System.Security.SecuritySafeCritical] // auto-generated get { Guid result = new Guid (); @@ -3653,22 +3535,13 @@ namespace System } } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern void GetGUID(ref Guid result); - [System.Security.SecuritySafeCritical] // auto-generated protected override bool IsContextfulImpl() { - return RuntimeTypeHandle.IsContextful(this); - } - - /* - protected override bool IsMarshalByRefImpl() - { - return GetTypeHandleInternal().IsMarshalByRef(); + return false; } - */ protected override bool IsByRefImpl() { @@ -3685,36 +3558,30 @@ namespace System return RuntimeTypeHandle.IsPointer(this); } - [System.Security.SecuritySafeCritical] // auto-generated protected override bool IsCOMObjectImpl() { return RuntimeTypeHandle.IsComObject(this, false); } #if FEATURE_COMINTEROP - [SecuritySafeCritical] internal override bool IsWindowsRuntimeObjectImpl() { return IsWindowsRuntimeObjectType(this); } - [SecuritySafeCritical] internal override bool IsExportedToWindowsRuntimeImpl() { return IsTypeExportedToWindowsRuntime(this); } [MethodImplAttribute(MethodImplOptions.InternalCall)] - [SecurityCritical] private static extern bool IsWindowsRuntimeObjectType(RuntimeType type); [MethodImplAttribute(MethodImplOptions.InternalCall)] - [SecurityCritical] private static extern bool IsTypeExportedToWindowsRuntime(RuntimeType type); #endif // FEATURE_COMINTEROP - [System.Security.SecuritySafeCritical] // auto-generated internal override bool HasProxyAttributeImpl() { return RuntimeTypeHandle.HasProxyAttribute(this); @@ -3736,16 +3603,6 @@ namespace System return IsSubclassOf(typeof(ValueType)); } -#if !FEATURE_CORECLR - public override bool IsEnum - { - get - { - return GetBaseType() == RuntimeType.EnumType; - } - } -#endif - protected override bool HasElementTypeImpl() { return RuntimeTypeHandle.HasElementType(this); @@ -3753,7 +3610,6 @@ namespace System public override GenericParameterAttributes GenericParameterAttributes { - [System.Security.SecuritySafeCritical] // auto-generated get { if (!IsGenericParameter) @@ -3796,7 +3652,6 @@ namespace System return RuntimeTypeHandle.IsArray(this); } - [System.Security.SecuritySafeCritical] // auto-generated public override int GetArrayRank() { if (!IsArrayImpl()) @@ -3828,7 +3683,6 @@ namespace System return retVal; } - [SecuritySafeCritical] public override Array GetEnumValues() { if (!IsEnum) @@ -3862,7 +3716,7 @@ namespace System public override bool IsEnumDefined(object value) { if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); Contract.EndContractBlock(); // Check if both of them are of the same type @@ -3909,13 +3763,13 @@ namespace System public override string GetEnumName(object value) { if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); Contract.EndContractBlock(); Type valueType = value.GetType(); if (!(valueType.IsEnum || IsIntegerType(valueType))) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnumBaseTypeOrEnum"), "value"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnumBaseTypeOrEnum"), nameof(value)); ulong ulValue = Enum.ToUInt64(value); @@ -3939,11 +3793,10 @@ namespace System return types; } - [System.Security.SecuritySafeCritical] // auto-generated public override Type MakeGenericType(Type[] instantiation) { if (instantiation == null) - throw new ArgumentNullException("instantiation"); + throw new ArgumentNullException(nameof(instantiation)); Contract.EndContractBlock(); RuntimeType[] instantiationRuntimeType = new RuntimeType[instantiation.Length]; @@ -3953,7 +3806,7 @@ namespace System Environment.GetResourceString("Arg_NotGenericTypeDefinition", this)); if (GetGenericArguments().Length != instantiation.Length) - throw new ArgumentException(Environment.GetResourceString("Argument_GenericArgsCount"), "instantiation"); + throw new ArgumentException(Environment.GetResourceString("Argument_GenericArgsCount"), nameof(instantiation)); for (int i = 0; i < instantiation.Length; i ++) { @@ -4055,7 +3908,6 @@ namespace System #endregion #region Misc - [System.Security.SecuritySafeCritical] // auto-generated public override Type MakePointerType() { return new RuntimeTypeHandle(this).MakePointer(); } public override Type MakeByRefType() { return new RuntimeTypeHandle(this).MakeByRef(); } public override Type MakeArrayType() { return new RuntimeTypeHandle(this).MakeSZArray(); } @@ -4069,7 +3921,6 @@ namespace System } public override StructLayoutAttribute StructLayoutAttribute { - [System.Security.SecuritySafeCritical] // overrides transparent public member get { return (StructLayoutAttribute)StructLayoutAttribute.GetCustomAttribute(this); @@ -4091,15 +3942,12 @@ namespace System BindingFlags.PutDispProperty | BindingFlags.PutRefDispProperty; private static RuntimeType s_typedRef = (RuntimeType)typeof(TypedReference); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] static private extern bool CanValueSpecialCast(RuntimeType valueType, RuntimeType targetType); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] static private extern Object AllocateValueType(RuntimeType type, object value, bool fForceTypeChange); - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe Object CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr) { // this method is used by invocation in reflection to check whether a value can be assigned to type. @@ -4107,26 +3955,9 @@ namespace System { // Since this cannot be a generic parameter, we use RuntimeTypeHandle.IsValueType here // because it is faster than RuntimeType.IsValueType - Contract.Assert(!IsGenericParameter); - - Type type = null; - -#if FEATURE_REMOTING - // For the remoting objects Object.GetType goes through proxy. Avoid the proxy call and just get - // the type directly. It is necessary to support proxies that do not handle GetType. - RealProxy realProxy = System.Runtime.Remoting.RemotingServices.GetRealProxy(value); + Debug.Assert(!IsGenericParameter); - if (realProxy != null) - { - type = realProxy.GetProxiedType(); - } - else - { - type = value.GetType(); - } -#else - type = value.GetType(); -#endif + Type type = value.GetType(); if (!Object.ReferenceEquals(type, this) && RuntimeTypeHandle.IsValueType(this)) { @@ -4186,7 +4017,6 @@ namespace System } // Factored out of CheckValue to reduce code complexity. - [System.Security.SecurityCritical] private Object TryChangeType(Object value, Binder binder, CultureInfo culture, bool needsSpecialCast) { if (binder != null && binder != Type.DefaultBinder) @@ -4245,7 +4075,6 @@ namespace System } #if FEATURE_COMINTEROP - [System.Security.SecuritySafeCritical] // auto-generated #endif [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] @@ -4260,7 +4089,7 @@ namespace System #region Preconditions if ((bindingFlags & InvocationMask) == 0) // "Must specify binding flags describing the invoke operation required." - throw new ArgumentException(Environment.GetResourceString("Arg_NoAccessSpec"),"bindingFlags"); + throw new ArgumentException(Environment.GetResourceString("Arg_NoAccessSpec"),nameof(bindingFlags)); // Provide a default binding mask if none is provided if ((bindingFlags & MemberBindingMask) == 0) @@ -4278,13 +4107,13 @@ namespace System { if (namedParams.Length > providedArgs.Length) // "Named parameter array can not be bigger than argument array." - throw new ArgumentException(Environment.GetResourceString("Arg_NamedParamTooBig"), "namedParams"); + throw new ArgumentException(Environment.GetResourceString("Arg_NamedParamTooBig"), nameof(namedParams)); } else { if (namedParams.Length != 0) // "Named parameter array can not be bigger than argument array." - throw new ArgumentException(Environment.GetResourceString("Arg_NamedParamTooBig"), "namedParams"); + throw new ArgumentException(Environment.GetResourceString("Arg_NamedParamTooBig"), nameof(namedParams)); } } #endregion @@ -4295,31 +4124,28 @@ namespace System { #region Preconditions if ((bindingFlags & ClassicBindingMask) == 0) - throw new ArgumentException(Environment.GetResourceString("Arg_COMAccess"), "bindingFlags"); + throw new ArgumentException(Environment.GetResourceString("Arg_COMAccess"), nameof(bindingFlags)); if ((bindingFlags & BindingFlags.GetProperty) != 0 && (bindingFlags & ClassicBindingMask & ~(BindingFlags.GetProperty | BindingFlags.InvokeMethod)) != 0) - throw new ArgumentException(Environment.GetResourceString("Arg_PropSetGet"), "bindingFlags"); + throw new ArgumentException(Environment.GetResourceString("Arg_PropSetGet"), nameof(bindingFlags)); if ((bindingFlags & BindingFlags.InvokeMethod) != 0 && (bindingFlags & ClassicBindingMask & ~(BindingFlags.GetProperty | BindingFlags.InvokeMethod)) != 0) - throw new ArgumentException(Environment.GetResourceString("Arg_PropSetInvoke"), "bindingFlags"); + throw new ArgumentException(Environment.GetResourceString("Arg_PropSetInvoke"), nameof(bindingFlags)); if ((bindingFlags & BindingFlags.SetProperty) != 0 && (bindingFlags & ClassicBindingMask & ~BindingFlags.SetProperty) != 0) - throw new ArgumentException(Environment.GetResourceString("Arg_COMPropSetPut"), "bindingFlags"); + throw new ArgumentException(Environment.GetResourceString("Arg_COMPropSetPut"), nameof(bindingFlags)); if ((bindingFlags & BindingFlags.PutDispProperty) != 0 && (bindingFlags & ClassicBindingMask & ~BindingFlags.PutDispProperty) != 0) - throw new ArgumentException(Environment.GetResourceString("Arg_COMPropSetPut"), "bindingFlags"); + throw new ArgumentException(Environment.GetResourceString("Arg_COMPropSetPut"), nameof(bindingFlags)); if ((bindingFlags & BindingFlags.PutRefDispProperty) != 0 && (bindingFlags & ClassicBindingMask & ~BindingFlags.PutRefDispProperty) != 0) - throw new ArgumentException(Environment.GetResourceString("Arg_COMPropSetPut"), "bindingFlags"); + throw new ArgumentException(Environment.GetResourceString("Arg_COMPropSetPut"), nameof(bindingFlags)); #endregion -#if FEATURE_REMOTING - if(!RemotingServices.IsTransparentProxy(target)) -#endif { #region Non-TransparentProxy case if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); bool[] isByRef = modifiers == null ? null : modifiers[0].IsByRefArray; @@ -4329,14 +4155,6 @@ namespace System return InvokeDispMethod(name, bindingFlags, target, providedArgs, isByRef, lcid, namedParams); #endregion } -#if FEATURE_REMOTING - else - { - #region TransparentProxy case - return ((MarshalByRefObject)target).InvokeMember(name, bindingFlags, binder, providedArgs, modifiers, culture, namedParams); - #endregion - } -#endif // FEATURE_REMOTING } #endif // FEATURE_COMINTEROP && FEATURE_USE_LCID #endregion @@ -4344,7 +4162,7 @@ namespace System #region Check that any named paramters are not null if (namedParams != null && Array.IndexOf(namedParams, null) != -1) // "Named parameter value must not be null." - throw new ArgumentException(Environment.GetResourceString("Arg_NamedParamNull"),"namedParams"); + throw new ArgumentException(Environment.GetResourceString("Arg_NamedParamNull"),nameof(namedParams)); #endregion int argCnt = (providedArgs != null) ? providedArgs.Length : 0; @@ -4361,7 +4179,7 @@ namespace System { if ((bindingFlags & BindingFlags.CreateInstance) != 0 && (bindingFlags & BinderNonCreateInstance) != 0) // "Can not specify both CreateInstance and another access type." - throw new ArgumentException(Environment.GetResourceString("Arg_CreatInstAccess"),"bindingFlags"); + throw new ArgumentException(Environment.GetResourceString("Arg_CreatInstAccess"),nameof(bindingFlags)); return Activator.CreateInstance(this, bindingFlags, binder, providedArgs, culture); } @@ -4373,7 +4191,7 @@ namespace System #region Name if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); if (name.Length == 0 || name.Equals(@"[DISPID=0]")) { @@ -4398,26 +4216,26 @@ namespace System { if (IsSetField) // "Can not specify both Get and Set on a field." - throw new ArgumentException(Environment.GetResourceString("Arg_FldSetGet"),"bindingFlags"); + throw new ArgumentException(Environment.GetResourceString("Arg_FldSetGet"),nameof(bindingFlags)); if ((bindingFlags & BindingFlags.SetProperty) != 0) // "Can not specify both GetField and SetProperty." - throw new ArgumentException(Environment.GetResourceString("Arg_FldGetPropSet"),"bindingFlags"); + throw new ArgumentException(Environment.GetResourceString("Arg_FldGetPropSet"),nameof(bindingFlags)); } else { - Contract.Assert(IsSetField); + Debug.Assert(IsSetField); if (providedArgs == null) - throw new ArgumentNullException("providedArgs"); + throw new ArgumentNullException(nameof(providedArgs)); if ((bindingFlags & BindingFlags.GetProperty) != 0) // "Can not specify both SetField and GetProperty." - throw new ArgumentException(Environment.GetResourceString("Arg_FldSetPropGet"),"bindingFlags"); + throw new ArgumentException(Environment.GetResourceString("Arg_FldSetPropGet"),nameof(bindingFlags)); if ((bindingFlags & BindingFlags.InvokeMethod) != 0) // "Can not specify Set on a Field and Invoke on a method." - throw new ArgumentException(Environment.GetResourceString("Arg_FldSetInvoke"),"bindingFlags"); + throw new ArgumentException(Environment.GetResourceString("Arg_FldSetInvoke"),nameof(bindingFlags)); } #endregion @@ -4425,7 +4243,7 @@ namespace System FieldInfo selFld = null; FieldInfo[] flds = GetMember(name, MemberTypes.Field, bindingFlags) as FieldInfo[]; - Contract.Assert(flds != null); + Debug.Assert(flds != null); if (flds.Length == 1) { @@ -4491,7 +4309,7 @@ namespace System { #region Get the field value if (argCnt != 0) - throw new ArgumentException(Environment.GetResourceString("Arg_FldGetArgErr"),"bindingFlags"); + throw new ArgumentException(Environment.GetResourceString("Arg_FldGetArgErr"),nameof(bindingFlags)); return selFld.GetValue(target); #endregion @@ -4500,7 +4318,7 @@ namespace System { #region Set the field Value if (argCnt != 1) - throw new ArgumentException(Environment.GetResourceString("Arg_FldSetArgErr"),"bindingFlags"); + throw new ArgumentException(Environment.GetResourceString("Arg_FldSetArgErr"),nameof(bindingFlags)); selFld.SetValue(target,providedArgs[0],bindingFlags,binder,culture); @@ -4548,19 +4366,19 @@ namespace System #region Preconditions if (isGetProperty) { - Contract.Assert(!IsSetField); + Debug.Assert(!IsSetField); if (isSetProperty) - throw new ArgumentException(Environment.GetResourceString("Arg_PropSetGet"), "bindingFlags"); + throw new ArgumentException(Environment.GetResourceString("Arg_PropSetGet"), nameof(bindingFlags)); } else { - Contract.Assert(isSetProperty); + Debug.Assert(isSetProperty); - Contract.Assert(!IsGetField); + Debug.Assert(!IsGetField); if ((bindingFlags & BindingFlags.InvokeMethod) != 0) - throw new ArgumentException(Environment.GetResourceString("Arg_PropSetInvoke"), "bindingFlags"); + throw new ArgumentException(Environment.GetResourceString("Arg_PropSetInvoke"), nameof(bindingFlags)); } #endregion } @@ -4579,7 +4397,7 @@ namespace System for(int i = 0; i < semiFinalists.Length; i ++) { MethodInfo semiFinalist = semiFinalists[i]; - Contract.Assert(semiFinalist != null); + Debug.Assert(semiFinalist != null); if (!FilterApplyMethodInfo((RuntimeMethodInfo)semiFinalist, bindingFlags, CallingConventions.Any, new Type[argCnt])) continue; @@ -4602,7 +4420,7 @@ namespace System if (results != null) { - Contract.Assert(results.Count > 1); + Debug.Assert(results.Count > 1); finalists = new MethodInfo[results.Count]; results.CopyTo(finalists); } @@ -4610,7 +4428,7 @@ namespace System } #endregion - Contract.Assert(finalists == null || finalist != null); + Debug.Assert(finalists == null || finalist != null); #region BindingFlags.GetProperty or BindingFlags.SetProperty if (finalist == null && isGetProperty || isSetProperty) @@ -4656,7 +4474,7 @@ namespace System if (results != null) { - Contract.Assert(results.Count > 1); + Debug.Assert(results.Count > 1); finalists = new MethodInfo[results.Count]; results.CopyTo(finalists); } @@ -4726,18 +4544,6 @@ namespace System return RuntimeHelpers.GetHashCode(this); } -#if !FEATURE_CORECLR - public static bool operator ==(RuntimeType left, RuntimeType right) - { - return object.ReferenceEquals(left, right); - } - - public static bool operator !=(RuntimeType left, RuntimeType right) - { - return !object.ReferenceEquals(left, right); - } -#endif // !FEATURE_CORECLR - public override String ToString() { return GetCachedName(TypeNameKind.ToString); @@ -4752,11 +4558,10 @@ namespace System #endregion #region ISerializable - [System.Security.SecurityCritical] // auto-generated public void GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); UnitySerializationHolder.GetUnitySerializationInfo(info, this); @@ -4764,38 +4569,35 @@ namespace System #endregion #region ICustomAttributeProvider - [System.Security.SecuritySafeCritical] // auto-generated public override Object[] GetCustomAttributes(bool inherit) { return CustomAttribute.GetCustomAttributes(this, RuntimeType.ObjectType, inherit); } - [System.Security.SecuritySafeCritical] // auto-generated public override Object[] GetCustomAttributes(Type attributeType, bool inherit) { if ((object)attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),nameof(attributeType)); return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType, inherit); } - [System.Security.SecuritySafeCritical] // auto-generated public override bool IsDefined(Type attributeType, bool inherit) { if ((object)attributeType == null) - throw new ArgumentNullException("attributeType"); + throw new ArgumentNullException(nameof(attributeType)); Contract.EndContractBlock(); RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),nameof(attributeType)); return CustomAttribute.IsDefined(this, attributeRuntimeType, inherit); } @@ -4887,7 +4689,6 @@ namespace System public override int MetadataToken { - [System.Security.SecuritySafeCritical] // auto-generated get { return RuntimeTypeHandle.GetToken(this); @@ -4915,7 +4716,6 @@ namespace System throw new NotSupportedException(Environment.GetResourceString("Acc_CreateVoid")); } - [System.Security.SecurityCritical] // auto-generated internal Object CreateInstanceImpl( BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, ref StackCrawlMark stackMark) { @@ -4923,170 +4723,117 @@ namespace System Object server = null; - try - { - try - { - // Store the activation attributes in thread local storage. - // These attributes are later picked up by specialized - // activation services like remote activation services to - // influence the activation. -#if FEATURE_REMOTING - if(null != activationAttributes) - { - ActivationServices.PushActivationAttributes(this, activationAttributes); - } -#endif - - if (args == null) - args = EmptyArray.Value; + if (args == null) + args = EmptyArray.Value; - int argCnt = args.Length; + int argCnt = args.Length; - // Without a binder we need to do use the default binder... - if (binder == null) - binder = DefaultBinder; + // Without a binder we need to do use the default binder... + if (binder == null) + binder = DefaultBinder; + + // deal with the __COMObject case first. It is very special because from a reflection point of view it has no ctors + // so a call to GetMemberCons would fail + if (argCnt == 0 && (bindingAttr & BindingFlags.Public) != 0 && (bindingAttr & BindingFlags.Instance) != 0 + && (IsGenericCOMObjectImpl() || IsValueType)) + { + server = CreateInstanceDefaultCtor((bindingAttr & BindingFlags.NonPublic) == 0 , false, true, ref stackMark); + } + else + { + ConstructorInfo[] candidates = GetConstructors(bindingAttr); + List matches = new List(candidates.Length); - // deal with the __COMObject case first. It is very special because from a reflection point of view it has no ctors - // so a call to GetMemberCons would fail - if (argCnt == 0 && (bindingAttr & BindingFlags.Public) != 0 && (bindingAttr & BindingFlags.Instance) != 0 - && (IsGenericCOMObjectImpl() || IsValueType)) + // We cannot use Type.GetTypeArray here because some of the args might be null + Type[] argsType = new Type[argCnt]; + for (int i = 0; i < argCnt; i++) + { + if (args[i] != null) { - server = CreateInstanceDefaultCtor((bindingAttr & BindingFlags.NonPublic) == 0 , false, true, ref stackMark); + argsType[i] = args[i].GetType(); } - else - { - ConstructorInfo[] candidates = GetConstructors(bindingAttr); - List matches = new List(candidates.Length); - - // We cannot use Type.GetTypeArray here because some of the args might be null - Type[] argsType = new Type[argCnt]; - for (int i = 0; i < argCnt; i++) - { - if (args[i] != null) - { - argsType[i] = args[i].GetType(); - } - } - - for(int i = 0; i < candidates.Length; i ++) - { - if (FilterApplyConstructorInfo((RuntimeConstructorInfo)candidates[i], bindingAttr, CallingConventions.Any, argsType)) - matches.Add(candidates[i]); - } + } - MethodBase[] cons = new MethodBase[matches.Count]; - matches.CopyTo(cons); - if (cons != null && cons.Length == 0) - cons = null; + for(int i = 0; i < candidates.Length; i ++) + { + if (FilterApplyConstructorInfo((RuntimeConstructorInfo)candidates[i], bindingAttr, CallingConventions.Any, argsType)) + matches.Add(candidates[i]); + } - if (cons == null) - { - // Null out activation attributes before throwing exception -#if FEATURE_REMOTING - if(null != activationAttributes) - { - ActivationServices.PopActivationAttributes(this); - activationAttributes = null; - } -#endif - throw new MissingMethodException(Environment.GetResourceString("MissingConstructor_Name", FullName)); - } + MethodBase[] cons = new MethodBase[matches.Count]; + matches.CopyTo(cons); + if (cons != null && cons.Length == 0) + cons = null; - MethodBase invokeMethod; - Object state = null; + if (cons == null) + { + throw new MissingMethodException(Environment.GetResourceString("MissingConstructor_Name", FullName)); + } - try - { - invokeMethod = binder.BindToMethod(bindingAttr, cons, ref args, null, culture, null, out state); - } - catch (MissingMethodException) { invokeMethod = null; } + MethodBase invokeMethod; + Object state = null; - if (invokeMethod == null) - { -#if FEATURE_REMOTING - // Null out activation attributes before throwing exception - if(null != activationAttributes) - { - ActivationServices.PopActivationAttributes(this); - activationAttributes = null; - } -#endif - throw new MissingMethodException(Environment.GetResourceString("MissingConstructor_Name", FullName)); - } + try + { + invokeMethod = binder.BindToMethod(bindingAttr, cons, ref args, null, culture, null, out state); + } + catch (MissingMethodException) { invokeMethod = null; } - // If we're creating a delegate, we're about to call a - // constructor taking an integer to represent a target - // method. Since this is very difficult (and expensive) - // to verify, we're just going to demand UnmanagedCode - // permission before allowing this. Partially trusted - // clients can instead use Delegate.CreateDelegate, - // which allows specification of the target method via - // name or MethodInfo. - //if (isDelegate) - if (RuntimeType.DelegateType.IsAssignableFrom(invokeMethod.DeclaringType)) - { -#if FEATURE_CORECLR - // In CoreCLR, CAS is not exposed externally. So what we really are looking - // for is to see if the external caller of this API is transparent or not. - // We get that information from the fact that a Demand will succeed only if - // the external caller is not transparent. - try - { + if (invokeMethod == null) + { + throw new MissingMethodException(Environment.GetResourceString("MissingConstructor_Name", FullName)); + } + + // If we're creating a delegate, we're about to call a + // constructor taking an integer to represent a target + // method. Since this is very difficult (and expensive) + // to verify, we're just going to demand UnmanagedCode + // permission before allowing this. Partially trusted + // clients can instead use Delegate.CreateDelegate, + // which allows specification of the target method via + // name or MethodInfo. + //if (isDelegate) + if (RuntimeType.DelegateType.IsAssignableFrom(invokeMethod.DeclaringType)) + { + // In CoreCLR, CAS is not exposed externally. So what we really are looking + // for is to see if the external caller of this API is transparent or not. + // We get that information from the fact that a Demand will succeed only if + // the external caller is not transparent. + try + { #pragma warning disable 618 - new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); + new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); #pragma warning restore 618 - } - catch - { - throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("NotSupported_DelegateCreationFromPT"))); - } -#else // FEATURE_CORECLR - new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); -#endif // FEATURE_CORECLR - } - - if (invokeMethod.GetParametersNoCopy().Length == 0) - { - if (args.Length != 0) - { - - Contract.Assert((invokeMethod.CallingConvention & CallingConventions.VarArgs) == - CallingConventions.VarArgs); - throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture, - Environment.GetResourceString("NotSupported_CallToVarArg"))); - } - - // fast path?? - server = Activator.CreateInstance(this, true); - } - else - { - server = ((ConstructorInfo)invokeMethod).Invoke(bindingAttr, binder, args, culture); - if (state != null) - binder.ReorderArgumentArray(ref args, state); - } } - } - finally + catch + { + throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("NotSupported_DelegateCreationFromPT"))); + } + } + + if (invokeMethod.GetParametersNoCopy().Length == 0) { -#if FEATURE_REMOTING - // Reset the TLS to null - if(null != activationAttributes) + if (args.Length != 0) { - ActivationServices.PopActivationAttributes(this); - activationAttributes = null; + + Debug.Assert((invokeMethod.CallingConvention & CallingConventions.VarArgs) == + CallingConventions.VarArgs); + throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture, + Environment.GetResourceString("NotSupported_CallToVarArg"))); } -#endif + + // fast path?? + server = Activator.CreateInstance(this, true); + } + else + { + server = ((ConstructorInfo)invokeMethod).Invoke(bindingAttr, binder, args, culture); + if (state != null) + binder.ReorderArgumentArray(ref args, state); } } - catch (Exception) - { - throw; - } - - //Console.WriteLine(server); - return server; + + return server; } // the cache entry @@ -5103,7 +4850,6 @@ namespace System // Lazy initialization was performed internal volatile bool m_bFullyInitialized; - [System.Security.SecurityCritical] internal ActivatorCacheEntry(RuntimeType t, RuntimeMethodHandleInternal rmh, bool bNeedSecurityCheck) { m_type = t; @@ -5137,12 +4883,11 @@ namespace System delegateCtorInfo = ctorInfo; // this assignment should be last } - [System.Security.SecuritySafeCritical] // auto-generated private void InitializeCacheEntry(ActivatorCacheEntry ace) { if (!ace.m_type.IsValueType) { - Contract.Assert(!ace.m_hCtorMethodHandle.IsNullHandle(), "Expected the default ctor method handle for a reference type."); + Debug.Assert(!ace.m_hCtorMethodHandle.IsNullHandle(), "Expected the default ctor method handle for a reference type."); if (delegateCtorInfo == null) InitializeDelegateCreator(); @@ -5184,7 +4929,6 @@ namespace System private static volatile ActivatorCache s_ActivatorCache; // the slow path of CreateInstanceDefaultCtor - [System.Security.SecuritySafeCritical] // auto-generated internal Object CreateInstanceSlow(bool publicOnly, bool skipCheckThis, bool fillCache, ref StackCrawlMark stackMark) { RuntimeMethodHandleInternal runtime_ctor = default(RuntimeMethodHandleInternal); @@ -5212,9 +4956,7 @@ namespace System bCanBeCached = false; } #endif -#if FEATURE_CORECLR bSecurityCheckOff = true; // CoreCLR does not use security at all. -#endif Object instance = RuntimeTypeHandle.CreateInstance(this, publicOnly, bSecurityCheckOff, ref bCanBeCached, ref runtime_ctor, ref bNeedSecurityCheck); @@ -5238,7 +4980,6 @@ namespace System // Helper to invoke the default (parameterless) ctor. // fillCache is set in the SL2/3 compat mode or when called from Marshal.PtrToStructure. - [System.Security.SecuritySafeCritical] // auto-generated [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] internal Object CreateInstanceDefaultCtor(bool publicOnly, bool skipCheckThis, bool fillCache, ref StackCrawlMark stackMark) @@ -5265,16 +5006,10 @@ namespace System Object instance = RuntimeTypeHandle.Allocate(this); // if m_ctor is null, this type doesn't have a default ctor - Contract.Assert(ace.m_ctor != null || this.IsValueType); + Debug.Assert(ace.m_ctor != null || this.IsValueType); if (ace.m_ctor != null) { -#if !FEATURE_CORECLR - // Perform security checks if needed - if (ace.m_bNeedSecurityCheck) - RuntimeMethodHandle.PerformSecurityCheck(instance, ace.m_hCtorMethodHandle, this, (uint)INVOCATION_FLAGS.INVOCATION_FLAGS_CONSTRUCTOR_INVOKE); -#endif - // Call ctor (value types wont have any) try { @@ -5296,7 +5031,6 @@ namespace System Cache.InvalidateCachedNestedType(); } - [System.Security.SecuritySafeCritical] // auto-generated internal bool IsGenericCOMObjectImpl() { return RuntimeTypeHandle.IsComObject(this, true); @@ -5304,27 +5038,22 @@ namespace System #endregion #region Legacy Static Internal - [System.Security.SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern Object _CreateEnum(RuntimeType enumType, long value); - [System.Security.SecuritySafeCritical] // auto-generated internal static Object CreateEnum(RuntimeType enumType, long value) { return _CreateEnum(enumType, value); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern Object InvokeDispMethod( String name, BindingFlags invokeAttr, Object target, Object[] args, bool[] byrefModifiers, int culture, String[] namedParameters); #if FEATURE_COMINTEROP_UNMANAGED_ACTIVATION - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern Type GetTypeFromProgIDImpl(String progID, String server, bool throwOnError); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern Type GetTypeFromCLSIDImpl(Guid clsid, String server, bool throwOnError); #else // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION @@ -5342,213 +5071,6 @@ namespace System #endregion #region COM -#if FEATURE_COMINTEROP && FEATURE_REMOTING - [System.Security.SecuritySafeCritical] // auto-generated - private Object ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, int[] aWrapperTypes, ref MessageData msgData) - { - ParameterModifier[] aParamMod = null; - Object ret = null; - - // Allocate a new message - Message reqMsg = new Message(); - reqMsg.InitFields(msgData); - - // Retrieve the required information from the message object. - MethodInfo meth = (MethodInfo)reqMsg.GetMethodBase(); - Object[] aArgs = reqMsg.Args; - int cArgs = aArgs.Length; - - // Retrieve information from the method we are invoking on. - ParameterInfo[] aParams = meth.GetParametersNoCopy(); - - // If we have arguments, then set the byref flags to true for byref arguments. - // We also wrap the arguments that require wrapping. - if (cArgs > 0) - { - ParameterModifier paramMod = new ParameterModifier(cArgs); - for (int i = 0; i < cArgs; i++) - { - if (aParams[i].ParameterType.IsByRef) - paramMod[i] = true; - } - - aParamMod = new ParameterModifier[1]; - aParamMod[0] = paramMod; - - if (aWrapperTypes != null) - WrapArgsForInvokeCall(aArgs, aWrapperTypes); - } - - // If the method has a void return type, then set the IgnoreReturn binding flag. - if (Object.ReferenceEquals(meth.ReturnType, typeof(void))) - flags |= BindingFlags.IgnoreReturn; - - try - { - // Invoke the method using InvokeMember(). - ret = InvokeMember(memberName, flags, null, target, aArgs, aParamMod, null, null); - } - catch (TargetInvocationException e) - { - // For target invocation exceptions, we need to unwrap the inner exception and - // re-throw it. - throw e.InnerException; - } - - // Convert each byref argument that is not of the proper type to - // the parameter type using the OleAutBinder. - for (int i = 0; i < cArgs; i++) - { - if (aParamMod[0][i] && aArgs[i] != null) - { - // The parameter is byref. - Type paramType = aParams[i].ParameterType.GetElementType(); - if (!Object.ReferenceEquals(paramType, aArgs[i].GetType())) - aArgs[i] = ForwardCallBinder.ChangeType(aArgs[i], paramType, null); - } - } - - // If the return type is not of the proper type, then convert it - // to the proper type using the OleAutBinder. - if (ret != null) - { - Type retType = meth.ReturnType; - if (!Object.ReferenceEquals(retType, ret.GetType())) - ret = ForwardCallBinder.ChangeType(ret, retType, null); - } - - // Propagate the out parameters - RealProxy.PropagateOutParameters(reqMsg, aArgs, ret); - - // Return the value returned by the InvokeMember call. - return ret; - } - - [SecuritySafeCritical] - private void WrapArgsForInvokeCall(Object[] aArgs, int[] aWrapperTypes) - { - int cArgs = aArgs.Length; - for (int i = 0; i < cArgs; i++) - { - if (aWrapperTypes[i] == 0) - continue; - - if (((DispatchWrapperType)aWrapperTypes[i] & DispatchWrapperType.SafeArray) != 0) - { - Type wrapperType = null; - bool isString = false; - - // Determine the type of wrapper to use. - switch ((DispatchWrapperType)aWrapperTypes[i] & ~DispatchWrapperType.SafeArray) - { - case DispatchWrapperType.Unknown: - wrapperType = typeof(UnknownWrapper); - break; - case DispatchWrapperType.Dispatch: - wrapperType = typeof(DispatchWrapper); - break; - case DispatchWrapperType.Error: - wrapperType = typeof(ErrorWrapper); - break; - case DispatchWrapperType.Currency: - wrapperType = typeof(CurrencyWrapper); - break; - case DispatchWrapperType.BStr: - wrapperType = typeof(BStrWrapper); - isString = true; - break; - default: - Contract.Assert(false, "[RuntimeType.WrapArgsForInvokeCall]Invalid safe array wrapper type specified."); - break; - } - - // Allocate the new array of wrappers. - Array oldArray = (Array)aArgs[i]; - int numElems = oldArray.Length; - Object[] newArray = (Object[])Array.UnsafeCreateInstance(wrapperType, numElems); - - // Retrieve the ConstructorInfo for the wrapper type. - ConstructorInfo wrapperCons; - if(isString) - { - wrapperCons = wrapperType.GetConstructor(new Type[] {typeof(String)}); - } - else - { - wrapperCons = wrapperType.GetConstructor(new Type[] {typeof(Object)}); - } - - // Wrap each of the elements of the array. - for (int currElem = 0; currElem < numElems; currElem++) - { - if(isString) - { - newArray[currElem] = wrapperCons.Invoke(new Object[] {(String)oldArray.GetValue(currElem)}); - } - else - { - newArray[currElem] = wrapperCons.Invoke(new Object[] {oldArray.GetValue(currElem)}); - } - } - - // Update the argument. - aArgs[i] = newArray; - } - else - { - // Determine the wrapper to use and then wrap the argument. - switch ((DispatchWrapperType)aWrapperTypes[i]) - { - case DispatchWrapperType.Unknown: - aArgs[i] = new UnknownWrapper(aArgs[i]); - break; - case DispatchWrapperType.Dispatch: - aArgs[i] = new DispatchWrapper(aArgs[i]); - break; - case DispatchWrapperType.Error: - aArgs[i] = new ErrorWrapper(aArgs[i]); - break; - case DispatchWrapperType.Currency: - aArgs[i] = new CurrencyWrapper(aArgs[i]); - break; - case DispatchWrapperType.BStr: - aArgs[i] = new BStrWrapper((String)aArgs[i]); - break; - default: - Contract.Assert(false, "[RuntimeType.WrapArgsForInvokeCall]Invalid wrapper type specified."); - break; - } - } - } - } - - private OleAutBinder ForwardCallBinder - { - get - { - // Synchronization is not required. - if (s_ForwardCallBinder == null) - s_ForwardCallBinder = new OleAutBinder(); - - return s_ForwardCallBinder; - } - } - - [Flags] - private enum DispatchWrapperType : int - { - // This enum must stay in sync with the DispatchWrapperType enum defined in MLInfo.h - Unknown = 0x00000001, - Dispatch = 0x00000002, - Record = 0x00000004, - Error = 0x00000008, - Currency = 0x00000010, - BStr = 0x00000020, - SafeArray = 0x00010000 - } - - private static volatile OleAutBinder s_ForwardCallBinder; -#endif // FEATURE_COMINTEROP && FEATURE_REMOTING #endregion } @@ -5580,21 +5102,17 @@ namespace System #region Library internal unsafe struct Utf8String { - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern unsafe bool EqualsCaseSensitive(void* szLhs, void* szRhs, int cSz); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern unsafe bool EqualsCaseInsensitive(void* szLhs, void* szRhs, int cSz); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern unsafe uint HashCaseInsensitive(void* sz, int cSz); - [System.Security.SecurityCritical] // auto-generated private static int GetUtf8StringByteLength(void* pUtf8String) { int len = 0; @@ -5613,11 +5131,9 @@ namespace System return len; } - [SecurityCritical] private void* m_pStringHeap; // This is the raw UTF8 string. private int m_StringHeapByteLength; - [System.Security.SecurityCritical] // auto-generated internal Utf8String(void* pStringHeap) { m_pStringHeap = pStringHeap; @@ -5631,14 +5147,12 @@ namespace System } } - [System.Security.SecurityCritical] // auto-generated internal unsafe Utf8String(void* pUtf8String, int cUtf8String) { m_pStringHeap = pUtf8String; m_StringHeapByteLength = cUtf8String; } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe bool Equals(Utf8String s) { if (m_pStringHeap == null) @@ -5652,7 +5166,6 @@ namespace System return false; } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe bool EqualsCaseInsensitive(Utf8String s) { if (m_pStringHeap == null) @@ -5666,13 +5179,11 @@ namespace System return false; } - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe uint HashCaseInsensitive() { return Utf8String.HashCaseInsensitive(m_pStringHeap, m_StringHeapByteLength); } - [System.Security.SecuritySafeCritical] // auto-generated public override string ToString() { unsafe @@ -5750,7 +5261,7 @@ namespace System.Reflection } else { - Contract.Assert(!hit.Equals(key), "Key was already in CerHashtable! Potential race condition (or bug) in the Reflection cache?"); + Debug.Assert(!hit.Equals(key), "Key was already in CerHashtable! Potential race condition (or bug) in the Reflection cache?"); index++; if (index >= keys.Length) diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs b/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs index 0585060..6a16462 100644 --- a/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs +++ b/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs @@ -32,7 +32,6 @@ namespace System.Runtime.CompilerServices /// Provides a builder for asynchronous methods that return void. /// This type is intended for compiler use only. /// - [HostProtection(Synchronization = true, ExternalThreading = true)] public struct AsyncVoidMethodBuilder { /// The synchronization context associated with this operation. @@ -59,14 +58,13 @@ namespace System.Runtime.CompilerServices /// Specifies the type of the state machine. /// The state machine instance, passed by reference. /// The argument was null (Nothing in Visual Basic). - [SecuritySafeCritical] [DebuggerStepThrough] public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { // See comment on AsyncMethodBuilderCore.Start // AsyncMethodBuilderCore.Start(ref stateMachine); - if (stateMachine == null) throw new ArgumentNullException("stateMachine"); + if (stateMachine == null) throw new ArgumentNullException(nameof(stateMachine)); Contract.EndContractBlock(); // Run the MoveNext method within a copy-on-write ExecutionContext scope. @@ -112,7 +110,7 @@ namespace System.Runtime.CompilerServices { AsyncMethodBuilderCore.MoveNextRunner runnerToInitialize = null; var continuation = m_coreState.GetCompletionAction(AsyncCausalityTracer.LoggingOn ? this.Task : null, ref runnerToInitialize); - Contract.Assert(continuation != null, "GetCompletionAction should always return a valid action."); + Debug.Assert(continuation != null, "GetCompletionAction should always return a valid action."); // If this is our first await, such that we've not yet boxed the state machine, do so now. if (m_coreState.m_stateMachine == null) @@ -149,7 +147,6 @@ namespace System.Runtime.CompilerServices /// Specifies the type of the state machine. /// The awaiter. /// The state machine. - [SecuritySafeCritical] public void AwaitUnsafeOnCompleted( ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion @@ -159,7 +156,7 @@ namespace System.Runtime.CompilerServices { AsyncMethodBuilderCore.MoveNextRunner runnerToInitialize = null; var continuation = m_coreState.GetCompletionAction(AsyncCausalityTracer.LoggingOn ? this.Task : null, ref runnerToInitialize); - Contract.Assert(continuation != null, "GetCompletionAction should always return a valid action."); + Debug.Assert(continuation != null, "GetCompletionAction should always return a valid action."); // If this is our first await, such that we've not yet boxed the state machine, do so now. if (m_coreState.m_stateMachine == null) @@ -200,7 +197,7 @@ namespace System.Runtime.CompilerServices /// The builder is not initialized. public void SetException(Exception exception) { - if (exception == null) throw new ArgumentNullException("exception"); + if (exception == null) throw new ArgumentNullException(nameof(exception)); Contract.EndContractBlock(); if (AsyncCausalityTracer.LoggingOn) @@ -231,7 +228,7 @@ namespace System.Runtime.CompilerServices /// Notifies the current synchronization context that the operation completed. private void NotifySynchronizationContextOfCompletion() { - Contract.Assert(m_synchronizationContext != null, "Must only be used with a non-null context."); + Debug.Assert(m_synchronizationContext != null, "Must only be used with a non-null context."); try { m_synchronizationContext.OperationCompleted(); @@ -273,7 +270,6 @@ namespace System.Runtime.CompilerServices /// Prior to being copied, one of its Task, SetResult, or SetException members must be accessed, /// or else the copies may end up building distinct Task instances. /// - [HostProtection(Synchronization = true, ExternalThreading = true)] public struct AsyncTaskMethodBuilder { /// A cached VoidTaskResult task used for builders that complete synchronously. @@ -294,14 +290,13 @@ namespace System.Runtime.CompilerServices /// Initiates the builder's execution with the associated state machine. /// Specifies the type of the state machine. /// The state machine instance, passed by reference. - [SecuritySafeCritical] [DebuggerStepThrough] public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { // See comment on AsyncMethodBuilderCore.Start // AsyncMethodBuilderCore.Start(ref stateMachine); - if (stateMachine == null) throw new ArgumentNullException("stateMachine"); + if (stateMachine == null) throw new ArgumentNullException(nameof(stateMachine)); Contract.EndContractBlock(); // Run the MoveNext method within a copy-on-write ExecutionContext scope. @@ -421,7 +416,6 @@ namespace System.Runtime.CompilerServices /// Prior to being copied, one of its Task, SetResult, or SetException members must be accessed, /// or else the copies may end up building distinct Task instances. /// - [HostProtection(Synchronization = true, ExternalThreading = true)] public struct AsyncTaskMethodBuilder { /// A cached task for default(TResult). @@ -450,14 +444,13 @@ namespace System.Runtime.CompilerServices /// Initiates the builder's execution with the associated state machine. /// Specifies the type of the state machine. /// The state machine instance, passed by reference. - [SecuritySafeCritical] [DebuggerStepThrough] public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { // See comment on AsyncMethodBuilderCore.Start // AsyncMethodBuilderCore.Start(ref stateMachine); - if (stateMachine == null) throw new ArgumentNullException("stateMachine"); + if (stateMachine == null) throw new ArgumentNullException(nameof(stateMachine)); Contract.EndContractBlock(); // Run the MoveNext method within a copy-on-write ExecutionContext scope. @@ -503,7 +496,7 @@ namespace System.Runtime.CompilerServices { AsyncMethodBuilderCore.MoveNextRunner runnerToInitialize = null; var continuation = m_coreState.GetCompletionAction(AsyncCausalityTracer.LoggingOn ? this.Task : null, ref runnerToInitialize); - Contract.Assert(continuation != null, "GetCompletionAction should always return a valid action."); + Debug.Assert(continuation != null, "GetCompletionAction should always return a valid action."); // If this is our first await, such that we've not yet boxed the state machine, do so now. if (m_coreState.m_stateMachine == null) @@ -534,7 +527,6 @@ namespace System.Runtime.CompilerServices /// Specifies the type of the state machine. /// The awaiter. /// The state machine. - [SecuritySafeCritical] public void AwaitUnsafeOnCompleted( ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion @@ -544,7 +536,7 @@ namespace System.Runtime.CompilerServices { AsyncMethodBuilderCore.MoveNextRunner runnerToInitialize = null; var continuation = m_coreState.GetCompletionAction(AsyncCausalityTracer.LoggingOn ? this.Task : null, ref runnerToInitialize); - Contract.Assert(continuation != null, "GetCompletionAction should always return a valid action."); + Debug.Assert(continuation != null, "GetCompletionAction should always return a valid action."); // If this is our first await, such that we've not yet boxed the state machine, do so now. if (m_coreState.m_stateMachine == null) @@ -595,7 +587,7 @@ namespace System.Runtime.CompilerServices if (task == null) { m_task = GetTaskForResult(result); - Contract.Assert(m_task != null, "GetTaskForResult should never return null"); + Debug.Assert(m_task != null, "GetTaskForResult should never return null"); } // Slow path: complete the existing task. else @@ -650,7 +642,7 @@ namespace System.Runtime.CompilerServices /// The task has already completed. public void SetException(Exception exception) { - if (exception == null) throw new ArgumentNullException("exception"); + if (exception == null) throw new ArgumentNullException(nameof(exception)); Contract.EndContractBlock(); @@ -713,7 +705,6 @@ namespace System.Runtime.CompilerServices /// /// The result for which we need a task. /// The completed task containing the result. - [SecuritySafeCritical] // for JitHelpers.UnsafeCast private Task GetTaskForResult(TResult result) { Contract.Ensures( @@ -819,7 +810,7 @@ namespace System.Runtime.CompilerServices /// Creates an array of cached tasks for the values in the range [INCLUSIVE_MIN,EXCLUSIVE_MAX). private static Task[] CreateInt32Tasks() { - Contract.Assert(EXCLUSIVE_INT32_MAX >= INCLUSIVE_INT32_MIN, "Expected max to be at least min"); + Debug.Assert(EXCLUSIVE_INT32_MAX >= INCLUSIVE_INT32_MIN, "Expected max to be at least min"); var tasks = new Task[EXCLUSIVE_INT32_MAX - INCLUSIVE_INT32_MIN]; for (int i = 0; i < tasks.Length; i++) { @@ -854,12 +845,11 @@ namespace System.Runtime.CompilerServices /// Specifies the type of the state machine. /// The state machine instance, passed by reference. /// The argument is null (Nothing in Visual Basic). - [SecuritySafeCritical] [DebuggerStepThrough] internal static void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { - if (stateMachine == null) throw new ArgumentNullException("stateMachine"); + if (stateMachine == null) throw new ArgumentNullException(nameof(stateMachine)); Contract.EndContractBlock(); // Run the MoveNext method within a copy-on-write ExecutionContext scope. @@ -887,7 +877,7 @@ namespace System.Runtime.CompilerServices /// The builder is incorrectly initialized. public void SetStateMachine(IAsyncStateMachine stateMachine) { - if (stateMachine == null) throw new ArgumentNullException("stateMachine"); + if (stateMachine == null) throw new ArgumentNullException(nameof(stateMachine)); Contract.EndContractBlock(); if (m_stateMachine != null) throw new InvalidOperationException(Environment.GetResourceString("AsyncMethodBuilder_InstanceNotInitialized")); m_stateMachine = stateMachine; @@ -902,10 +892,9 @@ namespace System.Runtime.CompilerServices /// The builder. /// The state machine. /// An Action to provide to the awaiter. - [SecuritySafeCritical] internal Action GetCompletionAction(Task taskForTracing, ref MoveNextRunner runnerToInitialize) { - Contract.Assert(m_defaultContextAction == null || m_stateMachine != null, + Debug.Assert(m_defaultContextAction == null || m_stateMachine != null, "Expected non-null m_stateMachine on non-null m_defaultContextAction"); // Alert a listening debugger that we can't make forward progress unless it slips threads. @@ -928,7 +917,7 @@ namespace System.Runtime.CompilerServices action = m_defaultContextAction; if (action != null) { - Contract.Assert(m_stateMachine != null, "If the delegate was set, the state machine should have been as well."); + Debug.Assert(m_stateMachine != null, "If the delegate was set, the state machine should have been as well."); return action; } @@ -994,8 +983,8 @@ namespace System.Runtime.CompilerServices m_stateMachine = stateMachine; m_stateMachine.SetStateMachine(m_stateMachine); - Contract.Assert(runner.m_stateMachine == null, "The runner's state machine should not yet have been populated."); - Contract.Assert(m_stateMachine != null, "The builder's state machine field should have been initialized."); + Debug.Assert(runner.m_stateMachine == null, "The runner's state machine should not yet have been populated."); + Debug.Assert(m_stateMachine != null, "The builder's state machine field should have been initialized."); // Now that we have the state machine, store it into the runner that the action delegate points to. // And return the action. @@ -1045,17 +1034,15 @@ namespace System.Runtime.CompilerServices /// Initializes the runner. /// The context with which to run MoveNext. - [SecurityCritical] // Run needs to be SSC to map to Action delegate, so to prevent misuse, we only allow construction through SC internal MoveNextRunnerWithContext(ExecutionContext context, IAsyncStateMachine stateMachine) : base(stateMachine) { m_context = context; } /// Invokes MoveNext under the provided context. - [SecuritySafeCritical] internal void RunWithCapturedContext() { - Contract.Assert(m_stateMachine != null, "The state machine must have been set before calling Run."); + Debug.Assert(m_stateMachine != null, "The state machine must have been set before calling Run."); if (m_context != null) { @@ -1080,34 +1067,29 @@ namespace System.Runtime.CompilerServices internal IAsyncStateMachine m_stateMachine; /// Initializes the runner. - [SecurityCritical] // Run needs to be SSC to map to Action delegate, so to prevent misuse, we only allow construction through SC internal MoveNextRunner(IAsyncStateMachine stateMachine) { m_stateMachine = stateMachine; } /// Invokes MoveNext under the default context. - [SecuritySafeCritical] internal void RunWithDefaultContext() { - Contract.Assert(m_stateMachine != null, "The state machine must have been set before calling Run."); + Debug.Assert(m_stateMachine != null, "The state machine must have been set before calling Run."); ExecutionContext.Run(ExecutionContext.PreAllocatedDefault, InvokeMoveNextCallback, m_stateMachine, preserveSyncCtx: true); } /// Gets a delegate to the InvokeMoveNext method. protected static ContextCallback InvokeMoveNextCallback { - [SecuritySafeCritical] get { return s_invokeMoveNext ?? (s_invokeMoveNext = InvokeMoveNext); } } /// Cached delegate used with ExecutionContext.Run. - [SecurityCritical] private static ContextCallback s_invokeMoveNext; // lazily-initialized due to SecurityCritical attribution /// Invokes the MoveNext method on the supplied IAsyncStateMachine. /// The IAsyncStateMachine machine instance. - [SecurityCritical] // necessary for ContextCallback in CoreCLR private static void InvokeMoveNext(object stateMachine) { ((IAsyncStateMachine)stateMachine).MoveNext(); diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CallingConvention.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CallingConvention.cs deleted file mode 100644 index f44251d..0000000 --- a/src/mscorlib/src/System/Runtime/CompilerServices/CallingConvention.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. -// See the LICENSE file in the project root for more information. - -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -namespace System.Runtime.CompilerServices -{ - // Types used in Custom Modifier to specify calling conventions. - [System.Runtime.InteropServices.ComVisible(true)] - public class CallConvCdecl - { - } - - [System.Runtime.InteropServices.ComVisible(true)] - public class CallConvStdcall - { - } - - [System.Runtime.InteropServices.ComVisible(true)] - public class CallConvThiscall - { - } - - [System.Runtime.InteropServices.ComVisible(true)] - public class CallConvFastcall - { - } - -} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs b/src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs index 21d6772..7455967 100644 --- a/src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs +++ b/src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs @@ -60,31 +60,29 @@ ** may be delayed until appdomain shutdown. ===========================================================*/ +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading; + namespace System.Runtime.CompilerServices { - using System; - using System.Collections.Generic; - using System.Runtime.Versioning; - using System.Runtime.InteropServices; - - #region ConditionalWeakTable - [System.Runtime.InteropServices.ComVisible(false)] + [ComVisible(false)] public sealed class ConditionalWeakTable where TKey : class where TValue : class { + #region Fields + private const int InitialCapacity = 8; // Initial length of the table. Must be a power of two. + private readonly object _lock; // This lock protects all mutation of data in the table. Readers do not take this lock. + private volatile Container _container; // The actual storage for the table; swapped out as the table grows. + #endregion #region Constructors - [System.Security.SecuritySafeCritical] public ConditionalWeakTable() { - _buckets = Array.Empty(); - _entries = Array.Empty(); - _freeList = -1; - _lock = new Object(); - - Resize(); // Resize at once (so won't need "if initialized" checks all over) + _lock = new object(); + _container = new Container(this); } #endregion @@ -99,18 +97,14 @@ namespace System.Runtime.CompilerServices // Note: The key may get garbaged collected during the TryGetValue operation. If so, TryGetValue // may at its discretion, return "false" and set "value" to the default (as if the key was not present.) //-------------------------------------------------------------------------------------------- - [System.Security.SecuritySafeCritical] public bool TryGetValue(TKey key, out TValue value) { if (key == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); } - lock(_lock) - { - VerifyIntegrity(); - return TryGetValueWorker(key, out value); - } + + return _container.TryGetValueWorker(key, out value); } //-------------------------------------------------------------------------------------------- @@ -123,7 +117,6 @@ namespace System.Runtime.CompilerServices // has the right to consider any prior entries successfully removed and add a new entry without // throwing an exception. //-------------------------------------------------------------------------------------------- - [System.Security.SecuritySafeCritical] public void Add(TKey key, TValue value) { if (key == null) @@ -131,22 +124,48 @@ namespace System.Runtime.CompilerServices ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); } - lock(_lock) + lock (_lock) { - VerifyIntegrity(); - _invalid = true; - - int entryIndex = FindEntry(key); + object otherValue; + int entryIndex = _container.FindEntry(key, out otherValue); if (entryIndex != -1) { - _invalid = false; ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate); } CreateEntry(key, value); - _invalid = false; } + } + + //-------------------------------------------------------------------------------------------- + // key: key to add or update. May not be null. + // value: value to associate with key. + // + // If the key is already entered into the dictionary, this method will update the value associated with key. + //-------------------------------------------------------------------------------------------- + public void AddOrUpdate(TKey key, TValue value) + { + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + } + + lock (_lock) + { + object otherValue; + int entryIndex = _container.FindEntry(key, out otherValue); + + // if we found a key we should just update, if no we should create a new entry. + if (entryIndex != -1) + { + _container.UpdateValue(entryIndex, value); + } + else + { + CreateEntry(key, value); + } + } } //-------------------------------------------------------------------------------------------- @@ -156,9 +175,8 @@ namespace System.Runtime.CompilerServices // // Note: The key may get garbage collected during the Remove() operation. If so, // Remove() will not fail or throw, however, the return value can be either true or false - // depending on the race condition. + // depending on who wins the race. //-------------------------------------------------------------------------------------------- - [System.Security.SecuritySafeCritical] public bool Remove(TKey key) { if (key == null) @@ -166,40 +184,9 @@ namespace System.Runtime.CompilerServices ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); } - lock(_lock) + lock (_lock) { - VerifyIntegrity(); - _invalid = true; - - int hashCode = RuntimeHelpers.GetHashCode(key) & Int32.MaxValue; - int bucket = hashCode % _buckets.Length; - int last = -1; - for (int entriesIndex = _buckets[bucket]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].next) - { - if (_entries[entriesIndex].hashCode == hashCode && _entries[entriesIndex].depHnd.GetPrimary() == key) - { - if (last == -1) - { - _buckets[bucket] = _entries[entriesIndex].next; - } - else - { - _entries[last].next = _entries[entriesIndex].next; - } - - _entries[entriesIndex].depHnd.Free(); - _entries[entriesIndex].next = _freeList; - - _freeList = entriesIndex; - - _invalid = false; - return true; - - } - last = entriesIndex; - } - _invalid = false; - return false; + return _container.Remove(key); } } @@ -219,46 +206,39 @@ namespace System.Runtime.CompilerServices // This rule permits the table to invoke createValueCallback outside the internal table lock // to prevent deadlocks. //-------------------------------------------------------------------------------------------- - [System.Security.SecuritySafeCritical] public TValue GetValue(TKey key, CreateValueCallback createValueCallback) { - // Our call to TryGetValue() validates key so no need for us to. - // - // if (key == null) - // { - // ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); - // } + // key is validated by TryGetValue if (createValueCallback == null) { - throw new ArgumentNullException("createValueCallback"); + throw new ArgumentNullException(nameof(createValueCallback)); } TValue existingValue; - if (TryGetValue(key, out existingValue)) - { - return existingValue; - } + return TryGetValue(key, out existingValue) ? + existingValue : + GetValueLocked(key, createValueCallback); + } - // If we got here, the key is not currently in table. Invoke the callback (outside the lock) + private TValue GetValueLocked(TKey key, CreateValueCallback createValueCallback) + { + // If we got here, the key was not in the table. Invoke the callback (outside the lock) // to generate the new value for the key. TValue newValue = createValueCallback(key); - lock(_lock) + lock (_lock) { - VerifyIntegrity(); - _invalid = true; - - // Now that we've retaken the lock, must recheck in case there was a race condition to add the key. - if (TryGetValueWorker(key, out existingValue)) + // Now that we've taken the lock, must recheck in case we lost a race to add the key. + TValue existingValue; + if (_container.TryGetValueWorker(key, out existingValue)) { - _invalid = false; return existingValue; } else { + // Verified in-lock that we won the race to add the key. Add it now. CreateEntry(key, newValue); - _invalid = false; return newValue; } } @@ -271,17 +251,15 @@ namespace System.Runtime.CompilerServices // to create new instances as needed. If TValue does not have a default constructor, this will // throw. //-------------------------------------------------------------------------------------------- - public TValue GetOrCreateValue(TKey key) - { - return GetValue(key, k => Activator.CreateInstance()); - } + + public TValue GetOrCreateValue(TKey key) => GetValue(key, _ => Activator.CreateInstance()); public delegate TValue CreateValueCallback(TKey key); - + #endregion - #region internal members - + #region Internal members + //-------------------------------------------------------------------------------------------- // Find a key that equals (value equality) with the given key - don't use in perf critical path // Note that it calls out to Object.Equals which may calls the override version of Equals @@ -290,56 +268,26 @@ namespace System.Runtime.CompilerServices // if you know for sure that either you won't run into dead locks or you need to live with the // possiblity //-------------------------------------------------------------------------------------------- - [System.Security.SecuritySafeCritical] [FriendAccessAllowed] internal TKey FindEquivalentKeyUnsafe(TKey key, out TValue value) { lock (_lock) { - for (int bucket = 0; bucket < _buckets.Length; ++bucket) - { - for (int entriesIndex = _buckets[bucket]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].next) - { - object thisKey, thisValue; - _entries[entriesIndex].depHnd.GetPrimaryAndSecondary(out thisKey, out thisValue); - if (Object.Equals(thisKey, key)) - { - value = (TValue) thisValue; - return (TKey) thisKey; - } - } - } + return _container.FindEquivalentKeyUnsafe(key, out value); } - - value = default(TValue); - return null; } - + //-------------------------------------------------------------------------------------------- // Returns a collection of keys - don't use in perf critical path //-------------------------------------------------------------------------------------------- internal ICollection Keys { - [System.Security.SecuritySafeCritical] get { - List list = new List(); lock (_lock) { - for (int bucket = 0; bucket < _buckets.Length; ++bucket) - { - for (int entriesIndex = _buckets[bucket]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].next) - { - TKey thisKey = (TKey) _entries[entriesIndex].depHnd.GetPrimary(); - if (thisKey != null) - { - list.Add(thisKey); - } - } - } + return _container.Keys; } - - return list; } } @@ -348,332 +296,500 @@ namespace System.Runtime.CompilerServices //-------------------------------------------------------------------------------------------- internal ICollection Values { - [System.Security.SecuritySafeCritical] get { - List list = new List(); lock (_lock) { - for (int bucket = 0; bucket < _buckets.Length; ++bucket) - { - for (int entriesIndex = _buckets[bucket]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].next) - { - Object primary = null; - Object secondary = null; - - _entries[entriesIndex].depHnd.GetPrimaryAndSecondary(out primary, out secondary); - - // Now that we've secured a strong reference to the secondary, must check the primary again - // to ensure it didn't expire (otherwise, we open a race condition where TryGetValue misreports an - // expired key as a live key with a null value.) - if (primary != null) - { - list.Add((TValue)secondary); - } - } - } + return _container.Values; } - - return list; } } - + //-------------------------------------------------------------------------------------------- // Clear all the key/value pairs //-------------------------------------------------------------------------------------------- - [System.Security.SecuritySafeCritical] internal void Clear() { lock (_lock) { - // Clear the buckets - for (int bucketIndex = 0; bucketIndex < _buckets.Length; bucketIndex++) - { - _buckets[bucketIndex] = -1; - } - - // Clear the entries and link them backwards together as part of free list - int entriesIndex; - for (entriesIndex = 0; entriesIndex < _entries.Length; entriesIndex++) - { - if (_entries[entriesIndex].depHnd.IsAllocated) - { - _entries[entriesIndex].depHnd.Free(); - } - - // Link back wards as free list - _entries[entriesIndex].next = entriesIndex - 1; - } - - _freeList = entriesIndex - 1; - } + _container = new Container(this); + } } #endregion - + #region Private Members - [System.Security.SecurityCritical] + //---------------------------------------------------------------------------------------- - // Worker for finding a key/value pair + // Worker for adding a new key/value pair. + // Will resize the container if it is full // // Preconditions: // Must hold _lock. - // Key already validated as non-null + // Key already validated as non-null and not already in table. //---------------------------------------------------------------------------------------- - private bool TryGetValueWorker(TKey key, out TValue value) + private void CreateEntry(TKey key, TValue value) { - int entryIndex = FindEntry(key); - if (entryIndex != -1) + Debug.Assert(Monitor.IsEntered(_lock)); + + Container c = _container; + if (!c.HasCapacity) { - Object primary = null; - Object secondary = null; - _entries[entryIndex].depHnd.GetPrimaryAndSecondary(out primary, out secondary); - // Now that we've secured a strong reference to the secondary, must check the primary again - // to ensure it didn't expire (otherwise, we open a race condition where TryGetValue misreports an - // expired key as a live key with a null value.) - if (primary != null) - { - value = (TValue)secondary; - return true; - } + _container = c = c.Resize(); } + c.CreateEntryNoResize(key, value); + } + + private static bool IsPowerOfTwo(int value) => (value > 0) && ((value & (value - 1)) == 0); - value = default(TValue); - return false; + #endregion + + #region Private Data Members + //-------------------------------------------------------------------------------------------- + // Entry can be in one of four states: + // + // - Unused (stored with an index _firstFreeEntry and above) + // depHnd.IsAllocated == false + // hashCode == + // next == ) + // + // - Used with live key (linked into a bucket list where _buckets[hashCode & (_buckets.Length - 1)] points to first entry) + // depHnd.IsAllocated == true, depHnd.GetPrimary() != null + // hashCode == RuntimeHelpers.GetHashCode(depHnd.GetPrimary()) & Int32.MaxValue + // next links to next Entry in bucket. + // + // - Used with dead key (linked into a bucket list where _buckets[hashCode & (_buckets.Length - 1)] points to first entry) + // depHnd.IsAllocated == true, depHnd.GetPrimary() == null + // hashCode == + // next links to next Entry in bucket. + // + // - Has been removed from the table (by a call to Remove) + // depHnd.IsAllocated == true, depHnd.GetPrimary() == + // hashCode == -1 + // next links to next Entry in bucket. + // + // The only difference between "used with live key" and "used with dead key" is that + // depHnd.GetPrimary() returns null. The transition from "used with live key" to "used with dead key" + // happens asynchronously as a result of normal garbage collection. The dictionary itself + // receives no notification when this happens. + // + // When the dictionary grows the _entries table, it scours it for expired keys and does not + // add those to the new container. + //-------------------------------------------------------------------------------------------- + private struct Entry + { + public DependentHandle depHnd; // Holds key and value using a weak reference for the key and a strong reference + // for the value that is traversed only if the key is reachable without going through the value. + public int HashCode; // Cached copy of key's hashcode + public int Next; // Index of next entry, -1 if last } - //---------------------------------------------------------------------------------------- - // Worker for adding a new key/value pair. // - // Preconditions: - // Must hold _lock. - // Key already validated as non-null and not already in table. - //---------------------------------------------------------------------------------------- - [System.Security.SecurityCritical] - private void CreateEntry(TKey key, TValue value) + // Container holds the actual data for the table. A given instance of Container always has the same capacity. When we need + // more capacity, we create a new Container, copy the old one into the new one, and discard the old one. This helps enable lock-free + // reads from the table, as readers never need to deal with motion of entries due to rehashing. + // + private sealed class Container { - if (_freeList == -1) + private readonly ConditionalWeakTable _parent; // the ConditionalWeakTable with which this container is associated + private int[] _buckets; // _buckets[hashcode & (_buckets.Length - 1)] contains index of the first entry in bucket (-1 if empty) + private Entry[] _entries; // the table entries containing the stored dependency handles + private int _firstFreeEntry; // _firstFreeEntry < _entries.Length => table has capacity, entries grow from the bottom of the table. + private bool _invalid; // flag detects if OOM or other background exception threw us out of the lock. + private bool _finalized; // set to true when initially finalized + private volatile object _oldKeepAlive; // used to ensure the next allocated container isn't finalized until this one is GC'd + + internal Container(ConditionalWeakTable parent) { - Resize(); + Debug.Assert(parent != null); + Debug.Assert(IsPowerOfTwo(InitialCapacity)); + + int size = InitialCapacity; + _buckets = new int[size]; + for (int i = 0; i < _buckets.Length; i++) + { + _buckets[i] = -1; + } + _entries = new Entry[size]; + + // Only store the parent after all of the allocations have happened successfully. + // Otherwise, as part of growing or clearing the container, we could end up allocating + // a new Container that fails (OOMs) part way through construction but that gets finalized + // and ends up clearing out some other container present in the associated CWT. + _parent = parent; } - int hashCode = RuntimeHelpers.GetHashCode(key) & Int32.MaxValue; - int bucket = hashCode % _buckets.Length; + private Container(ConditionalWeakTable parent, int[] buckets, Entry[] entries, int firstFreeEntry) + { + Debug.Assert(parent != null); + Debug.Assert(buckets != null); + Debug.Assert(entries != null); + Debug.Assert(buckets.Length == entries.Length); + Debug.Assert(IsPowerOfTwo(buckets.Length)); + + _parent = parent; + _buckets = buckets; + _entries = entries; + _firstFreeEntry = firstFreeEntry; + } - int newEntry = _freeList; - _freeList = _entries[newEntry].next; + internal bool HasCapacity => _firstFreeEntry < _entries.Length; - _entries[newEntry].hashCode = hashCode; - _entries[newEntry].depHnd = new DependentHandle(key, value); - _entries[newEntry].next = _buckets[bucket]; + //---------------------------------------------------------------------------------------- + // Worker for adding a new key/value pair. + // Preconditions: + // Container must NOT be full + //---------------------------------------------------------------------------------------- + internal void CreateEntryNoResize(TKey key, TValue value) + { + Debug.Assert(HasCapacity); - _buckets[bucket] = newEntry; + VerifyIntegrity(); + _invalid = true; - } + int hashCode = RuntimeHelpers.GetHashCode(key) & int.MaxValue; + int newEntry = _firstFreeEntry++; - //---------------------------------------------------------------------------------------- - // This does two things: resize and scrub expired keys off bucket lists. - // - // Precondition: - // Must hold _lock. - // - // Postcondition: - // _freeList is non-empty on exit. - //---------------------------------------------------------------------------------------- - [System.Security.SecurityCritical] - private void Resize() - { - // Start by assuming we won't resize. - int newSize = _buckets.Length; + _entries[newEntry].HashCode = hashCode; + _entries[newEntry].depHnd = new DependentHandle(key, value); + int bucket = hashCode & (_buckets.Length - 1); + _entries[newEntry].Next = _buckets[bucket]; + + // This write must be volatile, as we may be racing with concurrent readers. If they see + // the new entry, they must also see all of the writes earlier in this method. + Volatile.Write(ref _buckets[bucket], newEntry); + + _invalid = false; + } - // If any expired keys exist, we won't resize. - bool hasExpiredEntries = false; - int entriesIndex; - for (entriesIndex = 0; entriesIndex < _entries.Length; entriesIndex++) + //---------------------------------------------------------------------------------------- + // Worker for finding a key/value pair + // + // Preconditions: + // Must hold _lock. + // Key already validated as non-null + //---------------------------------------------------------------------------------------- + internal bool TryGetValueWorker(TKey key, out TValue value) { - if ( _entries[entriesIndex].depHnd.IsAllocated && _entries[entriesIndex].depHnd.GetPrimary() == null) + object secondary; + int entryIndex = FindEntry(key, out secondary); + value = JitHelpers.UnsafeCast(secondary); + return entryIndex != -1; + } + + //---------------------------------------------------------------------------------------- + // Returns -1 if not found (if key expires during FindEntry, this can be treated as "not found.") + // + // Preconditions: + // Must hold _lock, or be prepared to retry the search while holding _lock. + // Key already validated as non-null. + //---------------------------------------------------------------------------------------- + internal int FindEntry(TKey key, out object value) + { + int hashCode = RuntimeHelpers.GetHashCode(key) & int.MaxValue; + int bucket = hashCode & (_buckets.Length - 1); + for (int entriesIndex = Volatile.Read(ref _buckets[bucket]); entriesIndex != -1; entriesIndex = _entries[entriesIndex].Next) { - hasExpiredEntries = true; - break; + if (_entries[entriesIndex].HashCode == hashCode) + { + object primary, secondary; + _entries[entriesIndex].depHnd.GetPrimaryAndSecondary(out primary, out secondary); + if (primary == key) + { + GC.KeepAlive(this); // ensure we don't get finalized while accessing DependentHandles. + value = secondary; + return entriesIndex; + } + } } + + GC.KeepAlive(this); // ensure we don't get finalized while accessing DependentHandles. + value = null; + return -1; } - if (!hasExpiredEntries) + internal bool Remove(TKey key) { - newSize = System.Collections.HashHelpers.GetPrime(_buckets.Length == 0 ? _initialCapacity + 1 : _buckets.Length * 2); + VerifyIntegrity(); + + object value; + int entryIndex = FindEntry(key, out value); + if (entryIndex != -1) + { + ref Entry entry = ref _entries[entryIndex]; + + // We do not free the handle here, as we may be racing with readers who already saw the hash code. + // Instead, we simply overwrite the entry's hash code, so subsequent reads will ignore it. + // The handle will be free'd in Container's finalizer, after the table is resized or discarded. + Volatile.Write(ref entry.HashCode, -1); + + // Also, clear the key to allow GC to collect objects pointed to by the entry + entry.depHnd.SetPrimary(null); + + return true; + } + + return false; } - // Reallocate both buckets and entries and rebuild the bucket and freelists from scratch. - // This serves both to scrub entries with expired keys and to put the new entries in the proper bucket. - int newFreeList = -1; - int[] newBuckets = new int[newSize]; - for (int bucketIndex = 0; bucketIndex < newSize; bucketIndex++) + internal void UpdateValue(int entryIndex, TValue newValue) { - newBuckets[bucketIndex] = -1; + Debug.Assert(entryIndex != -1); + + VerifyIntegrity(); + _invalid = true; + + _entries[entryIndex].depHnd.SetSecondary(newValue); + + _invalid = false; } - Entry[] newEntries = new Entry[newSize]; - // Migrate existing entries to the new table. - for (entriesIndex = 0; entriesIndex < _entries.Length; entriesIndex++) + //---------------------------------------------------------------------------------------- + // This does two things: resize and scrub expired keys off bucket lists. + // + // Precondition: + // Must hold _lock. + // + // Postcondition: + // _firstEntry is less than _entries.Length on exit, that is, the table has at least one free entry. + //---------------------------------------------------------------------------------------- + internal Container Resize() { - DependentHandle depHnd = _entries[entriesIndex].depHnd; - if (depHnd.IsAllocated && depHnd.GetPrimary() != null) + // Start by assuming we won't resize. + int newSize = _buckets.Length; + + // If any expired or removed keys exist, we won't resize. + bool hasExpiredEntries = false; + for (int entriesIndex = 0; entriesIndex < _entries.Length; entriesIndex++) { - // Entry is used and has not expired. Link it into the appropriate bucket list. - int bucket = _entries[entriesIndex].hashCode % newSize; - newEntries[entriesIndex].depHnd = depHnd; - newEntries[entriesIndex].hashCode = _entries[entriesIndex].hashCode; - newEntries[entriesIndex].next = newBuckets[bucket]; - newBuckets[bucket] = entriesIndex; + if (_entries[entriesIndex].HashCode == -1) + { + // the entry was removed + hasExpiredEntries = true; + break; + } + + if (_entries[entriesIndex].depHnd.IsAllocated && _entries[entriesIndex].depHnd.GetPrimary() == null) + { + // the entry has expired + hasExpiredEntries = true; + break; + } } - else + + if (!hasExpiredEntries) { - // Entry has either expired or was on the freelist to begin with. Either way - // insert it on the new freelist. - _entries[entriesIndex].depHnd.Free(); - newEntries[entriesIndex].depHnd = new DependentHandle(); - newEntries[entriesIndex].next = newFreeList; - newFreeList = entriesIndex; + // Not necessary to check for overflow here, the attempt to allocate new arrays will throw + newSize = _buckets.Length * 2; } + + return Resize(newSize); } - // Add remaining entries to freelist. - while (entriesIndex != newEntries.Length) + internal Container Resize(int newSize) { - newEntries[entriesIndex].depHnd = new DependentHandle(); - newEntries[entriesIndex].next = newFreeList; - newFreeList = entriesIndex; - entriesIndex++; - } + Debug.Assert(IsPowerOfTwo(newSize)); - _buckets = newBuckets; - _entries = newEntries; - _freeList = newFreeList; - } + // Reallocate both buckets and entries and rebuild the bucket and entries from scratch. + // This serves both to scrub entries with expired keys and to put the new entries in the proper bucket. + int[] newBuckets = new int[newSize]; + for (int bucketIndex = 0; bucketIndex < newSize; bucketIndex++) + { + newBuckets[bucketIndex] = -1; + } + Entry[] newEntries = new Entry[newSize]; + int newEntriesIndex = 0; - //---------------------------------------------------------------------------------------- - // Returns -1 if not found (if key expires during FindEntry, this can be treated as "not found.") - // - // Preconditions: - // Must hold _lock. - // Key already validated as non-null. - //---------------------------------------------------------------------------------------- - [System.Security.SecurityCritical] - private int FindEntry(TKey key) - { - int hashCode = RuntimeHelpers.GetHashCode(key) & Int32.MaxValue; - for (int entriesIndex = _buckets[hashCode % _buckets.Length]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].next) + // Migrate existing entries to the new table. + for (int entriesIndex = 0; entriesIndex < _entries.Length; entriesIndex++) + { + int hashCode = _entries[entriesIndex].HashCode; + DependentHandle depHnd = _entries[entriesIndex].depHnd; + if (hashCode != -1 && depHnd.IsAllocated) + { + if (depHnd.GetPrimary() != null) + { + // Entry is used and has not expired. Link it into the appropriate bucket list. + newEntries[newEntriesIndex].HashCode = hashCode; + newEntries[newEntriesIndex].depHnd = depHnd; + int bucket = hashCode & (newBuckets.Length - 1); + newEntries[newEntriesIndex].Next = newBuckets[bucket]; + newBuckets[bucket] = newEntriesIndex; + newEntriesIndex++; + } + else + { + // Pretend the item was removed, so that this container's finalizer + // will clean up this dependent handle. + Volatile.Write(ref _entries[entriesIndex].HashCode, -1); + } + } + } + + // Create the new container. We want to transfer the responsibility of freeing the handles from + // the old container to the new container, and also ensure that the new container isn't finalized + // while the old container may still be in use. As such, we store a reference from the old container + // to the new one, which will keep the new container alive as long as the old one is. + var newContainer = new Container(_parent, newBuckets, newEntries, newEntriesIndex); + _oldKeepAlive = newContainer; // once this is set, the old container's finalizer will not free transferred dependent handles + + GC.KeepAlive(this); // ensure we don't get finalized while accessing DependentHandles. + + return newContainer; + } + + internal ICollection Keys { - if (_entries[entriesIndex].hashCode == hashCode && _entries[entriesIndex].depHnd.GetPrimary() == key) + get { - return entriesIndex; + var list = new List(); + + for (int bucket = 0; bucket < _buckets.Length; ++bucket) + { + for (int entriesIndex = _buckets[bucket]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].Next) + { + TKey thisKey = JitHelpers.UnsafeCast(_entries[entriesIndex].depHnd.GetPrimary()); + if (thisKey != null) + { + list.Add(thisKey); + } + } + } + + GC.KeepAlive(this); // ensure we don't get finalized while accessing DependentHandles. + return list; } } - return -1; - } - //---------------------------------------------------------------------------------------- - // Precondition: - // Must hold _lock. - //---------------------------------------------------------------------------------------- - private void VerifyIntegrity() - { - if (_invalid) + internal ICollection Values { - throw new InvalidOperationException(Environment.GetResourceString("CollectionCorrupted")); + get + { + var list = new List(); + + for (int bucket = 0; bucket < _buckets.Length; ++bucket) + { + for (int entriesIndex = _buckets[bucket]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].Next) + { + object primary = null, secondary = null; + _entries[entriesIndex].depHnd.GetPrimaryAndSecondary(out primary, out secondary); + + // Now that we've secured a strong reference to the secondary, must check the primary again + // to ensure it didn't expire (otherwise, we open a race where TryGetValue misreports an + // expired key as a live key with a null value.) + if (primary != null) + { + list.Add(JitHelpers.UnsafeCast(secondary)); + } + } + } + + GC.KeepAlive(this); // ensure we don't get finalized while accessing DependentHandles. + return list; + } } - } - //---------------------------------------------------------------------------------------- - // Finalizer. - //---------------------------------------------------------------------------------------- - [System.Security.SecuritySafeCritical] - ~ConditionalWeakTable() - { + internal TKey FindEquivalentKeyUnsafe(TKey key, out TValue value) + { + for (int bucket = 0; bucket < _buckets.Length; ++bucket) + { + for (int entriesIndex = _buckets[bucket]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].Next) + { + if (_entries[entriesIndex].HashCode == -1) + { + continue; // removed entry whose handle is awaiting condemnation by the finalizer. + } - // We're just freeing per-appdomain unmanaged handles here. If we're already shutting down the AD, - // don't bother. - // - // (Despite its name, Environment.HasShutdownStart also returns true if the current AD is finalizing.) - if (Environment.HasShutdownStarted) + object thisKey, thisValue; + _entries[entriesIndex].depHnd.GetPrimaryAndSecondary(out thisKey, out thisValue); + if (Equals(thisKey, key)) + { + GC.KeepAlive(this); // ensure we don't get finalized while accessing DependentHandles. + value = JitHelpers.UnsafeCast(thisValue); + return JitHelpers.UnsafeCast(thisKey); + } + } + } + + GC.KeepAlive(this); // ensure we don't get finalized while accessing DependentHandles. + value = default(TValue); + return null; + } + + //---------------------------------------------------------------------------------------- + // Precondition: + // Must hold _lock. + //---------------------------------------------------------------------------------------- + private void VerifyIntegrity() { - return; + if (_invalid) + { + throw new InvalidOperationException(Environment.GetResourceString("CollectionCorrupted")); + } } - if (_lock != null) + //---------------------------------------------------------------------------------------- + // Finalizer. + //---------------------------------------------------------------------------------------- + ~Container() { - lock(_lock) + // We're just freeing per-appdomain unmanaged handles here. If we're already shutting down the AD, + // don't bother. (Despite its name, Environment.HasShutdownStart also returns true if the current + // AD is finalizing.) We also skip doing anything if the container is invalid, including if someone + // the container object was allocated but its associated table never set. + if (Environment.HasShutdownStarted || _invalid || _parent == null) { - if (_invalid) + return; + } + + // It's possible that the ConditionalWeakTable could have been resurrected, in which case code could + // be accessing this Container as it's being finalized. We don't support usage after finalization, + // but we also don't want to potentially corrupt state by allowing dependency handles to be used as + // or after they've been freed. To avoid that, if it's at all possible that another thread has a + // reference to this container via the CWT, we remove such a reference and then re-register for + // finalization: the next time around, we can be sure that no references remain to this and we can + // clean up the dependency handles without fear of corruption. + if (!_finalized) + { + _finalized = true; + lock (_parent._lock) { - return; + if (_parent._container == this) + { + _parent._container = null; + } } - Entry[] entries = _entries; + GC.ReRegisterForFinalize(this); // next time it's finalized, we'll be sure there are no remaining refs + return; + } - // Make sure anyone sneaking into the table post-resurrection - // gets booted before they can damage the native handle table. - _invalid = true; - _entries = null; - _buckets = null; + Entry[] entries = _entries; + _invalid = true; + _entries = null; + _buckets = null; + if (entries != null) + { for (int entriesIndex = 0; entriesIndex < entries.Length; entriesIndex++) { - entries[entriesIndex].depHnd.Free(); + // We need to free handles in two cases: + // - If this container still owns the dependency handle (meaning ownership hasn't been transferred + // to another container that replaced this one), then it should be freed. + // - If this container had the entry removed, then even if in general ownership was transferred to + // another container, removed entries are not, therefore this container must free them. + if (_oldKeepAlive == null || entries[entriesIndex].HashCode == -1) + { + entries[entriesIndex].depHnd.Free(); + } } } } } #endregion - - #region Private Data Members - //-------------------------------------------------------------------------------------------- - // Entry can be in one of three states: - // - // - Linked into the freeList (_freeList points to first entry) - // depHnd.IsAllocated == false - // hashCode == - // next links to next Entry on freelist) - // - // - Used with live key (linked into a bucket list where _buckets[hashCode % _buckets.Length] points to first entry) - // depHnd.IsAllocated == true, depHnd.GetPrimary() != null - // hashCode == RuntimeHelpers.GetHashCode(depHnd.GetPrimary()) & Int32.MaxValue - // next links to next Entry in bucket. - // - // - Used with dead key (linked into a bucket list where _buckets[hashCode % _buckets.Length] points to first entry) - // depHnd.IsAllocated == true, depHnd.GetPrimary() == null - // hashCode == - // next links to next Entry in bucket. - // - // The only difference between "used with live key" and "used with dead key" is that - // depHnd.GetPrimary() returns null. The transition from "used with live key" to "used with dead key" - // happens asynchronously as a result of normal garbage collection. The dictionary itself - // receives no notification when this happens. - // - // When the dictionary grows the _entries table, it scours it for expired keys and puts those - // entries back on the freelist. - //-------------------------------------------------------------------------------------------- - private struct Entry - { - public DependentHandle depHnd; // Holds key and value using a weak reference for the key and a strong reference - // for the value that is traversed only if the key is reachable without going through the value. - public int hashCode; // Cached copy of key's hashcode - public int next; // Index of next entry, -1 if last - } - - private int[] _buckets; // _buckets[hashcode & _buckets.Length] contains index of first entry in bucket (-1 if empty) - private Entry[] _entries; - private int _freeList; // -1 = empty, else index of first unused Entry - private const int _initialCapacity = 5; - private readonly Object _lock; // this could be a ReaderWriterLock but CoreCLR does not support RWLocks. - private bool _invalid; // flag detects if OOM or other background exception threw us out of the lock. - #endregion } #endregion - - - #region DependentHandle //========================================================================================= // This struct collects all operations on native DependentHandles. The DependentHandle @@ -700,15 +816,10 @@ namespace System.Runtime.CompilerServices // to use DependentHandles in a thread-safe way. //========================================================================================= [ComVisible(false)] - struct DependentHandle + internal struct DependentHandle { #region Constructors - #if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // auto-generated - #else - [System.Security.SecurityCritical] - #endif - public DependentHandle(Object primary, Object secondary) + public DependentHandle(object primary, object secondary) { IntPtr handle = (IntPtr)0; nInitialize(primary, secondary, out handle); @@ -718,44 +829,37 @@ namespace System.Runtime.CompilerServices #endregion #region Public Members - public bool IsAllocated - { - get - { - return _handle != (IntPtr)0; - } - } + public bool IsAllocated => _handle != IntPtr.Zero; // Getting the secondary object is more expensive than getting the first so // we provide a separate primary-only accessor for those times we only want the // primary. - #if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // auto-generated - #else - [System.Security.SecurityCritical] - #endif - public Object GetPrimary() + public object GetPrimary() { - Object primary; + object primary; nGetPrimary(_handle, out primary); return primary; } - #if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // auto-generated - #else - [System.Security.SecurityCritical] - #endif - public void GetPrimaryAndSecondary(out Object primary, out Object secondary) + public void GetPrimaryAndSecondary(out object primary, out object secondary) { nGetPrimaryAndSecondary(_handle, out primary, out secondary); } + public void SetPrimary(object primary) + { + nSetPrimary(_handle, primary); + } + + public void SetSecondary(object secondary) + { + nSetSecondary(_handle, secondary); + } + //---------------------------------------------------------------------- // Forces dependentHandle back to non-allocated state (if not already there) // and frees the handle if needed. //---------------------------------------------------------------------- - [System.Security.SecurityCritical] public void Free() { if (_handle != (IntPtr)0) @@ -768,20 +872,22 @@ namespace System.Runtime.CompilerServices #endregion #region Private Members - [System.Security.SecurityCritical] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern void nInitialize(Object primary, Object secondary, out IntPtr dependentHandle); + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void nInitialize(object primary, object secondary, out IntPtr dependentHandle); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void nGetPrimary(IntPtr dependentHandle, out object primary); - [System.Security.SecurityCritical] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern void nGetPrimary(IntPtr dependentHandle, out Object primary); + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void nGetPrimaryAndSecondary(IntPtr dependentHandle, out object primary, out object secondary); - [System.Security.SecurityCritical] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern void nGetPrimaryAndSecondary(IntPtr dependentHandle, out Object primary, out Object secondary); + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void nSetPrimary(IntPtr dependentHandle, object primary); - [System.Security.SecurityCritical] - [MethodImplAttribute(MethodImplOptions.InternalCall)] + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void nSetSecondary(IntPtr dependentHandle, object secondary); + + [MethodImpl(MethodImplOptions.InternalCall)] private static extern void nFree(IntPtr dependentHandle); #endregion @@ -792,4 +898,3 @@ namespace System.Runtime.CompilerServices } // struct DependentHandle #endregion } - diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/DecimalConstantAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/DecimalConstantAttribute.cs index 39a4c86..7bfaa7a 100644 --- a/src/mscorlib/src/System/Runtime/CompilerServices/DecimalConstantAttribute.cs +++ b/src/mscorlib/src/System/Runtime/CompilerServices/DecimalConstantAttribute.cs @@ -6,6 +6,7 @@ // Note: If you add a new ctor overloads you need to update ParameterInfo.RawDefaultValue using System.Reflection; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Collections.Generic; @@ -57,16 +58,16 @@ namespace System.Runtime.CompilerServices if (namedArgument.MemberInfo.Name.Equals("Value")) { // This is not possible because Decimal cannot be represented directly in the metadata. - Contract.Assert(false, "Decimal cannot be represented directly in the metadata."); + Debug.Assert(false, "Decimal cannot be represented directly in the metadata."); return (Decimal)namedArgument.TypedValue.Value; } } ParameterInfo[] parameters = attr.Constructor.GetParameters(); - Contract.Assert(parameters.Length == 5); + Debug.Assert(parameters.Length == 5); System.Collections.Generic.IList args = attr.ConstructorArguments; - Contract.Assert(args.Count == 5); + Debug.Assert(args.Count == 5); if (parameters[2].ParameterType == typeof(uint)) { diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/FormattableStringFactory.cs b/src/mscorlib/src/System/Runtime/CompilerServices/FormattableStringFactory.cs index aee3bc2..4b99a8a 100644 --- a/src/mscorlib/src/System/Runtime/CompilerServices/FormattableStringFactory.cs +++ b/src/mscorlib/src/System/Runtime/CompilerServices/FormattableStringFactory.cs @@ -26,12 +26,12 @@ namespace System.Runtime.CompilerServices { if (format == null) { - throw new ArgumentNullException("format"); + throw new ArgumentNullException(nameof(format)); } if (arguments == null) { - throw new ArgumentNullException("arguments"); + throw new ArgumentNullException(nameof(arguments)); } return new ConcreteFormattableString(format, arguments); diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/HasCopySemanticsAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/HasCopySemanticsAttribute.cs deleted file mode 100644 index 944a286..0000000 --- a/src/mscorlib/src/System/Runtime/CompilerServices/HasCopySemanticsAttribute.cs +++ /dev/null @@ -1,14 +0,0 @@ -// 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. - -namespace System.Runtime.CompilerServices -{ -[Serializable] -[AttributeUsage(AttributeTargets.Struct)] - public sealed class HasCopySemanticsAttribute : Attribute - { - public HasCopySemanticsAttribute() - {} - } -} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IDispatchConstantAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IDispatchConstantAttribute.cs deleted file mode 100644 index d6dfcbb..0000000 --- a/src/mscorlib/src/System/Runtime/CompilerServices/IDispatchConstantAttribute.cs +++ /dev/null @@ -1,26 +0,0 @@ -// 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.Runtime.InteropServices; - -namespace System.Runtime.CompilerServices -{ -[Serializable] -[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited=false)] -[System.Runtime.InteropServices.ComVisible(true)] - public sealed class IDispatchConstantAttribute : CustomConstantAttribute - { - public IDispatchConstantAttribute() - { - } - - public override Object Value - { - get - { - return new DispatchWrapper(null); - } - } - } -} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/INotifyCompletion.cs b/src/mscorlib/src/System/Runtime/CompilerServices/INotifyCompletion.cs index 872a79b..aba0a06 100644 --- a/src/mscorlib/src/System/Runtime/CompilerServices/INotifyCompletion.cs +++ b/src/mscorlib/src/System/Runtime/CompilerServices/INotifyCompletion.cs @@ -34,7 +34,6 @@ namespace System.Runtime.CompilerServices /// The action to invoke when the operation completes. /// The argument is null (Nothing in Visual Basic). /// Unlike OnCompleted, UnsafeOnCompleted need not propagate ExecutionContext information. - [SecurityCritical] void UnsafeOnCompleted(Action continuation); } } diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IUnknownConstantAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IUnknownConstantAttribute.cs deleted file mode 100644 index f8717cf..0000000 --- a/src/mscorlib/src/System/Runtime/CompilerServices/IUnknownConstantAttribute.cs +++ /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. -// See the LICENSE file in the project root for more information. - -using System.Runtime.InteropServices; - -namespace System.Runtime.CompilerServices -{ -[Serializable] -[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited=false)] -[System.Runtime.InteropServices.ComVisible(true)] - public sealed class IUnknownConstantAttribute : CustomConstantAttribute - { - public IUnknownConstantAttribute() - { - } - - public override Object Value - { - get - { - return new UnknownWrapper(null); - } - } - - } -} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsBoxed.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsBoxed.cs deleted file mode 100644 index 8b6691c..0000000 --- a/src/mscorlib/src/System/Runtime/CompilerServices/IsBoxed.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace System.Runtime.CompilerServices -{ - // Indicates that the modified reference type is a boxed valuetype - public static class IsBoxed - { - } -} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsByValue.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsByValue.cs deleted file mode 100644 index d16a853..0000000 --- a/src/mscorlib/src/System/Runtime/CompilerServices/IsByValue.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace System.Runtime.CompilerServices -{ - // Indicates that the modified method argument is passed by value - public static class IsByValue - { - } -} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsConst.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsConst.cs deleted file mode 100644 index 210e599..0000000 --- a/src/mscorlib/src/System/Runtime/CompilerServices/IsConst.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace System.Runtime.CompilerServices -{ - // Indicates that the modified type is const (i.e. has a const modifier) - public static class IsConst - { - } -} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsCopyConstructed.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsCopyConstructed.cs deleted file mode 100644 index ee40ee7..0000000 --- a/src/mscorlib/src/System/Runtime/CompilerServices/IsCopyConstructed.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace System.Runtime.CompilerServices -{ - [System.Runtime.InteropServices.ComVisible(true)] - public static class IsCopyConstructed - {} -} - diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsExplicitlyDereferenced.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsExplicitlyDereferenced.cs deleted file mode 100644 index 480a621..0000000 --- a/src/mscorlib/src/System/Runtime/CompilerServices/IsExplicitlyDereferenced.cs +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -namespace System.Runtime.CompilerServices -{ - // Consider the following C++ method prototypes: - // 1) int foo(int ^arg); - // 2) int foo(int &arg); - // - // Both of these methods will have a .NET type signature that looks the - // same, but when importing a method from a metadata scope, the compiler - // needs to know what the calling syntax should be. This modopt and its - // partner "IsImplicitlyDereferenced" disambiguate reference versus - // pointer arguments. - // - // Indicates that the modified GC reference represents a pointer in a - // method signature. - public static class IsExplicitlyDereferenced - { - } -} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsImplicitlyDereferenced.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsImplicitlyDereferenced.cs deleted file mode 100644 index ea81cb8..0000000 --- a/src/mscorlib/src/System/Runtime/CompilerServices/IsImplicitlyDereferenced.cs +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -namespace System.Runtime.CompilerServices -{ - // Consider the following C++ method prototypes: - // 1) int foo(int ^arg); - // 2) int foo(int &arg); - // - // Both of these methods will have a .NET type signature that looks the - // same, but when importing a method from a metadata scope, the compiler - // needs to know what the calling syntax should be. This modopt and its - // partner "IsExplicitlyDereferenced" disambiguate reference versus - // pointer arguments. - // - // Indicates that the modified GC reference represents a reference in a - // method signature. - public static class IsImplicitlyDereferenced - { - } -} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsJitIntrinsic.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsJitIntrinsic.cs deleted file mode 100644 index 013e50f..0000000 --- a/src/mscorlib/src/System/Runtime/CompilerServices/IsJitIntrinsic.cs +++ /dev/null @@ -1,12 +0,0 @@ -// 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. - -namespace System.Runtime.CompilerServices -{ - // Indicates that the modified method is an intrinsic for which the JIT - // can perform special code generation. - public static class IsJitIntrinsic - { - } -} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsLong.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsLong.cs deleted file mode 100644 index e8bebfb..0000000 --- a/src/mscorlib/src/System/Runtime/CompilerServices/IsLong.cs +++ /dev/null @@ -1,18 +0,0 @@ -// 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. - -namespace System.Runtime.CompilerServices -{ - // The C++ standard indicates that a long is always 4-bytes, whereas the - // size of an integer is system dependent (not exceedign sizeof(long)). - // The CLR does not offer a mechanism for encoding this distinction, - // but it is critically important for maintaining language level type - // safety. - // - // Indicates that the modified integer is a standard C++ long. - // Could also be called IsAlternateIntegerType or something else. - public static class IsLong - { - } -} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsPinned.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsPinned.cs deleted file mode 100644 index e796d1a..0000000 --- a/src/mscorlib/src/System/Runtime/CompilerServices/IsPinned.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace System.Runtime.CompilerServices -{ - // Indicates that the modified instance is pinned in memory. - public static class IsPinned - { - } -} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsSignUnspecifiedByte.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsSignUnspecifiedByte.cs deleted file mode 100644 index e68f4d7..0000000 --- a/src/mscorlib/src/System/Runtime/CompilerServices/IsSignUnspecifiedByte.cs +++ /dev/null @@ -1,16 +0,0 @@ -// 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. - -namespace System.Runtime.CompilerServices -{ - // C++ recognizes three char types: signed char, unsigned char, and char. - // When a char is neither signed nor unsigned, it is a char. - // This modopt indicates that the modified instance is a char. - // - // Any compiler could use this to indicate that the user has not specified - // Sign behavior for the given byte. - public static class IsSignUnspecifiedByte - { - } -} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsUdtReturn.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsUdtReturn.cs deleted file mode 100644 index dd85914..0000000 --- a/src/mscorlib/src/System/Runtime/CompilerServices/IsUdtReturn.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace System.Runtime.CompilerServices -{ - // Indicates that the return type is a user defined type - public static class IsUdtReturn - { - } -} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/NativeCppClassAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/NativeCppClassAttribute.cs deleted file mode 100644 index 0d6c759..0000000 --- a/src/mscorlib/src/System/Runtime/CompilerServices/NativeCppClassAttribute.cs +++ /dev/null @@ -1,16 +0,0 @@ -// 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.Runtime.InteropServices; - -namespace System.Runtime.CompilerServices { -[Serializable] -[AttributeUsage(AttributeTargets.Struct, Inherited = true), - System.Runtime.InteropServices.ComVisible(true)] - public sealed class NativeCppClassAttribute : Attribute - { - public NativeCppClassAttribute () {} - } -} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/RequiredAttributeAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/RequiredAttributeAttribute.cs deleted file mode 100644 index f363696..0000000 --- a/src/mscorlib/src/System/Runtime/CompilerServices/RequiredAttributeAttribute.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; - -namespace System.Runtime.CompilerServices -{ -[Serializable] -[AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface, - AllowMultiple=true, Inherited=false)] -[System.Runtime.InteropServices.ComVisible(true)] - public sealed class RequiredAttributeAttribute : Attribute - { - private Type requiredContract; - - public RequiredAttributeAttribute (Type requiredContract) - { - this.requiredContract= requiredContract; - } - public Type RequiredContract - { - get { return this.requiredContract; } - } - } -} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs index d20fe0b..926eb6c 100644 --- a/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs +++ b/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs @@ -25,16 +25,13 @@ namespace System.Runtime.CompilerServices { public static class RuntimeHelpers { -#if FEATURE_CORECLR // Exposed here as a more appropriate place than on FormatterServices itself, // which is a high level reflection heavy type. public static Object GetUninitializedObject(Type type) { return FormatterServices.GetUninitializedObject(type); } -#endif // FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern void InitializeArray(Array array,RuntimeFieldHandle fldHandle); @@ -51,7 +48,6 @@ namespace System.Runtime.CompilerServices { // cloned when you pass them around, and are always passed by value. // Of course, reference types are not cloned. // - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern Object GetObjectValue(Object obj); @@ -63,7 +59,6 @@ namespace System.Runtime.CompilerServices { // This call will generate an exception if the specified class constructor threw an // exception when it ran. - [System.Security.SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void _RunClassConstructor(RuntimeType type); @@ -80,7 +75,6 @@ namespace System.Runtime.CompilerServices { // This call will generate an exception if the specified module constructor threw an // exception when it ran. - [System.Security.SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void _RunModuleConstructor(System.Reflection.RuntimeModule module); @@ -89,72 +83,25 @@ namespace System.Runtime.CompilerServices { _RunModuleConstructor(module.GetRuntimeModule()); } - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static unsafe extern void _PrepareMethod(IRuntimeMethodInfo method, IntPtr* pInstantiation, int cInstantiation); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] internal static extern void _CompileMethod(IRuntimeMethodInfo method); - // Simple (instantiation not required) method. - [System.Security.SecurityCritical] // auto-generated_required - public static void PrepareMethod(RuntimeMethodHandle method) + public static void PrepareMethod(RuntimeMethodHandle method){} + public static void PrepareMethod(RuntimeMethodHandle method, RuntimeTypeHandle[] instantiation){} + public static void PrepareContractedDelegate(Delegate d){} + + public static void PrepareDelegate(Delegate d) { - unsafe + if (d == null) { - _PrepareMethod(method.GetMethodInfo(), null, 0); + throw new ArgumentNullException ("d"); } } - // Generic method or method with generic class with specific instantiation. - [System.Security.SecurityCritical] // auto-generated_required - public static void PrepareMethod(RuntimeMethodHandle method, RuntimeTypeHandle[] instantiation) - { - unsafe - { - int length; - IntPtr[] instantiationHandles = RuntimeTypeHandle.CopyRuntimeTypeHandles(instantiation, out length); - fixed (IntPtr* pInstantiation = instantiationHandles) - { - _PrepareMethod(method.GetMethodInfo(), pInstantiation, length); - GC.KeepAlive(instantiation); - } - } - } - - // This method triggers a given delegate to be prepared. This involves preparing the - // delegate's Invoke method and preparing the target of that Invoke. In the case of - // a multi-cast delegate, we rely on the fact that each individual component was prepared - // prior to the Combine. In other words, this service does not navigate through the - // entire multicasting list. - // If our own reliable event sinks perform the Combine (for example AppDomain.DomainUnload), - // then the result is fully prepared. But if a client calls Combine himself and then - // then adds that combination to e.g. AppDomain.DomainUnload, then the client is responsible - // for his own preparation. - [System.Security.SecurityCritical] // auto-generated_required - [MethodImplAttribute(MethodImplOptions.InternalCall)] - public static extern void PrepareDelegate(Delegate d); - - // See comment above for PrepareDelegate - // - // PrepareContractedDelegate weakens this a bit by only assuring that we prepare - // delegates which also have a ReliabilityContract. This is useful for services that - // want to provide opt-in reliability, generally some random event sink providing - // always reliable semantics to random event handlers that are likely to have not - // been written with relability in mind is a lost cause anyway. - // - // NOTE: that for the NGen case you can sidestep the required ReliabilityContract - // by using the [PrePrepareMethod] attribute. - [System.Security.SecurityCritical] // auto-generated_required - [MethodImplAttribute(MethodImplOptions.InternalCall)] - public static extern void PrepareContractedDelegate(Delegate d); - - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern int GetHashCode(Object o); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public new static extern bool Equals(Object o1, Object o2); @@ -183,30 +130,24 @@ namespace System.Runtime.CompilerServices { // If there is not enough stack, then it throws System.InsufficientExecutionStackException. // Note: this method is not part of the CER support, and is not to be confused with ProbeForSufficientStack // below. - [System.Security.SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static extern void EnsureSufficientExecutionStack(); -#if FEATURE_CORECLR // This method ensures that there is sufficient stack to execute the average Framework function. // If there is not enough stack, then it return false. // Note: this method is not part of the CER support, and is not to be confused with ProbeForSufficientStack // below. - [System.Security.SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - internal static extern bool TryEnsureSufficientExecutionStack(); -#endif + public static extern bool TryEnsureSufficientExecutionStack(); - [System.Security.SecurityCritical] // auto-generated_required - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - public static extern void ProbeForSufficientStack(); + public static void ProbeForSufficientStack() + { + } // This method is a marker placed immediately before a try clause to mark the corresponding catch and finally blocks as // constrained. There's no code here other than the probe because most of the work is done at JIT time when we spot a call to this routine. - [System.Security.SecurityCritical] // auto-generated_required [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static void PrepareConstrainedRegions() { @@ -215,29 +156,18 @@ namespace System.Runtime.CompilerServices { // When we detect a CER with no calls, we can point the JIT to this non-probing version instead // as we don't need to probe. - [System.Security.SecurityCritical] // auto-generated_required [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static void PrepareConstrainedRegionsNoOP() { } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif public delegate void TryCode(Object userData); - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif public delegate void CleanupCode(Object userData, bool exceptionThrown); - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern void ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData); -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif [PrePrepareMethod] internal static void ExecuteBackoutCodeHelper(Object backoutCode, Object userData, bool exceptionThrown) { diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeWrappedException.cs b/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeWrappedException.cs index 2751d61..d2691df 100644 --- a/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeWrappedException.cs +++ b/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeWrappedException.cs @@ -33,10 +33,9 @@ namespace System.Runtime.CompilerServices { private Object m_wrappedException; - [System.Security.SecurityCritical] // auto-generated_required public override void GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); base.GetObjectData(info, context); diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/ScopelessEnumAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/ScopelessEnumAttribute.cs deleted file mode 100644 index 9176918..0000000 --- a/src/mscorlib/src/System/Runtime/CompilerServices/ScopelessEnumAttribute.cs +++ /dev/null @@ -1,14 +0,0 @@ -// 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. - -namespace System.Runtime.CompilerServices -{ -[Serializable] -[AttributeUsage(AttributeTargets.Enum)] - public sealed class ScopelessEnumAttribute : Attribute - { - public ScopelessEnumAttribute() - {} - } -} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/TaskAwaiter.cs b/src/mscorlib/src/System/Runtime/CompilerServices/TaskAwaiter.cs index ea6bb96..98a81ea 100644 --- a/src/mscorlib/src/System/Runtime/CompilerServices/TaskAwaiter.cs +++ b/src/mscorlib/src/System/Runtime/CompilerServices/TaskAwaiter.cs @@ -57,7 +57,6 @@ namespace System.Runtime.CompilerServices { /// Provides an awaiter for awaiting a . /// This type is intended for compiler use only. - [HostProtection(Synchronization = true, ExternalThreading = true)] public struct TaskAwaiter : ICriticalNotifyCompletion { /// The task being awaited. @@ -84,7 +83,6 @@ namespace System.Runtime.CompilerServices /// The argument is null (Nothing in Visual Basic). /// The awaiter was not properly initialized. /// This method is intended for compiler user rather than use directly in code. - [SecuritySafeCritical] public void OnCompleted(Action continuation) { OnCompletedInternal(m_task, continuation, continueOnCapturedContext:true, flowExecutionContext:true); @@ -95,7 +93,6 @@ namespace System.Runtime.CompilerServices /// The argument is null (Nothing in Visual Basic). /// The awaiter was not properly initialized. /// This method is intended for compiler user rather than use directly in code. - [SecurityCritical] public void UnsafeOnCompleted(Action continuation) { OnCompletedInternal(m_task, continuation, continueOnCapturedContext:true, flowExecutionContext:false); @@ -143,7 +140,7 @@ namespace System.Runtime.CompilerServices if (!task.IsCompleted) { bool taskCompleted = task.InternalWait(Timeout.Infinite, default(CancellationToken)); - Contract.Assert(taskCompleted, "With an infinite timeout, the task should have always completed."); + Debug.Assert(taskCompleted, "With an infinite timeout, the task should have always completed."); } // Now that we're done, alert the debugger if so requested @@ -171,7 +168,7 @@ namespace System.Runtime.CompilerServices if (oceEdi != null) { oceEdi.Throw(); - Contract.Assert(false, "Throw() should have thrown"); + Debug.Assert(false, "Throw() should have thrown"); } throw new TaskCanceledException(task); @@ -182,12 +179,12 @@ namespace System.Runtime.CompilerServices if (edis.Count > 0) { edis[0].Throw(); - Contract.Assert(false, "Throw() should have thrown"); + Debug.Assert(false, "Throw() should have thrown"); break; // Necessary to compile: non-reachable, but compiler can't determine that } else { - Contract.Assert(false, "There should be exceptions if we're Faulted."); + Debug.Assert(false, "There should be exceptions if we're Faulted."); throw task.Exception; } } @@ -202,10 +199,9 @@ namespace System.Runtime.CompilerServices /// The awaiter was not properly initialized. /// This method is intended for compiler user rather than use directly in code. [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable - [SecurityCritical] internal static void OnCompletedInternal(Task task, Action continuation, bool continueOnCapturedContext, bool flowExecutionContext) { - if (continuation == null) throw new ArgumentNullException("continuation"); + if (continuation == null) throw new ArgumentNullException(nameof(continuation)); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; // If TaskWait* ETW events are enabled, trace a beginning event for this await @@ -294,7 +290,6 @@ namespace System.Runtime.CompilerServices /// Provides an awaiter for awaiting a . /// This type is intended for compiler use only. - [HostProtection(Synchronization = true, ExternalThreading = true)] public struct TaskAwaiter : ICriticalNotifyCompletion { /// The task being awaited. @@ -321,7 +316,6 @@ namespace System.Runtime.CompilerServices /// The argument is null (Nothing in Visual Basic). /// The awaiter was not properly initialized. /// This method is intended for compiler user rather than use directly in code. - [SecuritySafeCritical] public void OnCompleted(Action continuation) { TaskAwaiter.OnCompletedInternal(m_task, continuation, continueOnCapturedContext:true, flowExecutionContext:true); @@ -332,7 +326,6 @@ namespace System.Runtime.CompilerServices /// The argument is null (Nothing in Visual Basic). /// The awaiter was not properly initialized. /// This method is intended for compiler user rather than use directly in code. - [SecurityCritical] public void UnsafeOnCompleted(Action continuation) { TaskAwaiter.OnCompletedInternal(m_task, continuation, continueOnCapturedContext:true, flowExecutionContext:false); @@ -377,7 +370,6 @@ namespace System.Runtime.CompilerServices /// Provides an awaiter for a . /// This type is intended for compiler use only. - [HostProtection(Synchronization = true, ExternalThreading = true)] public struct ConfiguredTaskAwaiter : ICriticalNotifyCompletion { /// The task being awaited. @@ -411,7 +403,6 @@ namespace System.Runtime.CompilerServices /// The argument is null (Nothing in Visual Basic). /// The awaiter was not properly initialized. /// This method is intended for compiler user rather than use directly in code. - [SecuritySafeCritical] public void OnCompleted(Action continuation) { TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext:true); @@ -422,7 +413,6 @@ namespace System.Runtime.CompilerServices /// The argument is null (Nothing in Visual Basic). /// The awaiter was not properly initialized. /// This method is intended for compiler user rather than use directly in code. - [SecurityCritical] public void UnsafeOnCompleted(Action continuation) { TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext:false); @@ -466,7 +456,6 @@ namespace System.Runtime.CompilerServices /// Provides an awaiter for a . /// This type is intended for compiler use only. - [HostProtection(Synchronization = true, ExternalThreading = true)] public struct ConfiguredTaskAwaiter : ICriticalNotifyCompletion { /// The task being awaited. @@ -499,7 +488,6 @@ namespace System.Runtime.CompilerServices /// The argument is null (Nothing in Visual Basic). /// The awaiter was not properly initialized. /// This method is intended for compiler user rather than use directly in code. - [SecuritySafeCritical] public void OnCompleted(Action continuation) { TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext:true); @@ -510,7 +498,6 @@ namespace System.Runtime.CompilerServices /// The argument is null (Nothing in Visual Basic). /// The awaiter was not properly initialized. /// This method is intended for compiler user rather than use directly in code. - [SecurityCritical] public void UnsafeOnCompleted(Action continuation) { TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext:false); diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/TypeDependencyAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/TypeDependencyAttribute.cs index db04eb9..2de9c1f 100644 --- a/src/mscorlib/src/System/Runtime/CompilerServices/TypeDependencyAttribute.cs +++ b/src/mscorlib/src/System/Runtime/CompilerServices/TypeDependencyAttribute.cs @@ -17,7 +17,7 @@ namespace System.Runtime.CompilerServices public TypeDependencyAttribute (string typeName) { - if(typeName == null) throw new ArgumentNullException("typeName"); + if(typeName == null) throw new ArgumentNullException(nameof(typeName)); Contract.EndContractBlock(); this.typeName = typeName; } diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedFromAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedFromAttribute.cs index c1656dc..671d1f0 100644 --- a/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedFromAttribute.cs +++ b/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedFromAttribute.cs @@ -20,7 +20,7 @@ namespace System.Runtime.CompilerServices { if (String.IsNullOrEmpty(assemblyFullName)) { - throw new ArgumentNullException("assemblyFullName"); + throw new ArgumentNullException(nameof(assemblyFullName)); } this.assemblyFullName = assemblyFullName; } diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedToAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedToAttribute.cs index 034dad1..d9e067b 100644 --- a/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedToAttribute.cs +++ b/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedToAttribute.cs @@ -26,7 +26,6 @@ namespace System.Runtime.CompilerServices } } - [System.Security.SecurityCritical] internal static TypeForwardedToAttribute[] GetCustomAttribute(RuntimeAssembly assembly) { Type[] types = null; diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/Unsafe.cs b/src/mscorlib/src/System/Runtime/CompilerServices/Unsafe.cs new file mode 100644 index 0000000..b212f45 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/Unsafe.cs @@ -0,0 +1,80 @@ +// 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.Runtime.Versioning; + +namespace System.Runtime.CompilerServices +{ + // + // Subsetted clone of System.Runtime.CompilerServices.Unsafe for internal runtime use. + // Keep in sync with https://github.com/dotnet/corefx/tree/master/src/System.Runtime.CompilerServices.Unsafe. + // + + /// + /// Contains generic, low-level functionality for manipulating pointers. + /// + internal static unsafe class Unsafe + { + /// + /// Returns a pointer to the given by-ref parameter. + /// + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void* AsPointer(ref T value) + { + // The body of this function will be replaced by the EE with unsafe code!!! + // See getILIntrinsicImplementationForUnsafe for how this happens. + throw new InvalidOperationException(); + } + + /// + /// Returns the size of an object of the given type parameter. + /// + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int SizeOf() + { + // The body of this function will be replaced by the EE with unsafe code that just returns sizeof !!T + // See getILIntrinsicImplementationForUnsafe for how this happens. + throw new InvalidOperationException(); + } + + /// + /// Reinterprets the given reference as a reference to a value of type . + /// + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ref TTo As(ref TFrom source) + { + // The body of this function will be replaced by the EE with unsafe code!!! + // See getILIntrinsicImplementationForUnsafe for how this happens. + throw new InvalidOperationException(); + } + + /// + /// Adds an element offset to the given reference. + /// + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ref T Add(ref T source, int elementOffset) + { + // The body of this function will be replaced by the EE with unsafe code!!! + // See getILIntrinsicImplementationForUnsafe for how this happens. + typeof(T).ToString(); // Type used by the actual method body + throw new InvalidOperationException(); + } + + /// + /// Determines whether the specified references point to the same location. + /// + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AreSame(ref T left, ref T right) + { + // The body of this function will be replaced by the EE with unsafe code!!! + // See getILIntrinsicImplementationForUnsafe for how this happens. + throw new InvalidOperationException(); + } + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/YieldAwaitable.cs b/src/mscorlib/src/System/Runtime/CompilerServices/YieldAwaitable.cs index b29b39c..86789bf 100644 --- a/src/mscorlib/src/System/Runtime/CompilerServices/YieldAwaitable.cs +++ b/src/mscorlib/src/System/Runtime/CompilerServices/YieldAwaitable.cs @@ -48,7 +48,6 @@ namespace System.Runtime.CompilerServices /// Provides an awaiter that switches into a target environment. /// This type is intended for compiler use only. - [HostProtection(Synchronization = true, ExternalThreading = true)] public struct YieldAwaiter : ICriticalNotifyCompletion { /// Gets whether a yield is not required. @@ -58,7 +57,6 @@ namespace System.Runtime.CompilerServices /// Posts the back to the current context. /// The action to invoke asynchronously. /// The argument is null (Nothing in Visual Basic). - [SecuritySafeCritical] public void OnCompleted(Action continuation) { QueueContinuation(continuation, flowContext: true); @@ -67,7 +65,6 @@ namespace System.Runtime.CompilerServices /// Posts the back to the current context. /// The action to invoke asynchronously. /// The argument is null (Nothing in Visual Basic). - [SecurityCritical] public void UnsafeOnCompleted(Action continuation) { QueueContinuation(continuation, flowContext: false); @@ -77,11 +74,10 @@ namespace System.Runtime.CompilerServices /// The action to invoke asynchronously. /// true to flow ExecutionContext; false if flowing is not required. /// The argument is null (Nothing in Visual Basic). - [SecurityCritical] private static void QueueContinuation(Action continuation, bool flowContext) { // Validate arguments - if (continuation == null) throw new ArgumentNullException("continuation"); + if (continuation == null) throw new ArgumentNullException(nameof(continuation)); Contract.EndContractBlock(); if (TplEtwProvider.Log.IsEnabled()) diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs b/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs index 8ee50da..c1346f7 100644 --- a/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs +++ b/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs @@ -11,6 +11,7 @@ using System; using System.Threading; using System.Runtime; using System.Runtime.Versioning; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Security; @@ -60,6 +61,12 @@ namespace System.Runtime.CompilerServices { public byte m_data; } + internal class ArrayPinningHelper + { + public IntPtr m_lengthAndPadding; + public byte m_arrayData; + } + [FriendAccessAllowed] internal static class JitHelpers { @@ -68,7 +75,6 @@ namespace System.Runtime.CompilerServices { // Wraps object variable into a handle. Used to return managed strings from QCalls. // s has to be a local variable on the stack. - [SecurityCritical] static internal StringHandleOnStack GetStringHandleOnStack(ref string s) { return new StringHandleOnStack(UnsafeCastToStackPointer(ref s)); @@ -76,7 +82,6 @@ namespace System.Runtime.CompilerServices { // Wraps object variable into a handle. Used to pass managed object references in and out of QCalls. // o has to be a local variable on the stack. - [SecurityCritical] static internal ObjectHandleOnStack GetObjectHandleOnStack(ref T o) where T : class { return new ObjectHandleOnStack(UnsafeCastToStackPointer(ref o)); @@ -84,25 +89,22 @@ namespace System.Runtime.CompilerServices { // Wraps StackCrawlMark into a handle. Used to pass StackCrawlMark to QCalls. // stackMark has to be a local variable on the stack. - [SecurityCritical] static internal StackCrawlMarkHandle GetStackCrawlMarkHandle(ref StackCrawlMark stackMark) { return new StackCrawlMarkHandle(UnsafeCastToStackPointer(ref stackMark)); } #if _DEBUG - [SecurityCritical] [FriendAccessAllowed] static internal T UnsafeCast(Object o) where T : class { T ret = UnsafeCastInternal(o); - Contract.Assert(ret == (o as T), "Invalid use of JitHelpers.UnsafeCast!"); + Debug.Assert(ret == (o as T), "Invalid use of JitHelpers.UnsafeCast!"); return ret; } // The IL body of this method is not critical, but its body will be replaced with unsafe code, so // this method is effectively critical - [SecurityCritical] static private T UnsafeCastInternal(Object o) where T : class { // The body of this function will be replaced by the EE with unsafe code that just returns o!!! @@ -112,7 +114,7 @@ namespace System.Runtime.CompilerServices { static internal int UnsafeEnumCast(T val) where T : struct // Actually T must be 4 byte (or less) enum { - Contract.Assert(typeof(T).IsEnum + Debug.Assert(typeof(T).IsEnum && (Enum.GetUnderlyingType(typeof(T)) == typeof(int) || Enum.GetUnderlyingType(typeof(T)) == typeof(uint) || Enum.GetUnderlyingType(typeof(T)) == typeof(short) @@ -132,7 +134,7 @@ namespace System.Runtime.CompilerServices { static internal long UnsafeEnumCastLong(T val) where T : struct // Actually T must be 8 byte enum { - Contract.Assert(typeof(T).IsEnum + Debug.Assert(typeof(T).IsEnum && (Enum.GetUnderlyingType(typeof(T)) == typeof(long) || Enum.GetUnderlyingType(typeof(T)) == typeof(ulong)), "Error, T must be an 8 byte enum JitHelpers.UnsafeEnumCastLong!"); @@ -148,15 +150,13 @@ namespace System.Runtime.CompilerServices { // Internal method for getting a raw pointer for handles in JitHelpers. // The reference has to point into a local stack variable in order so it can not be moved by the GC. - [SecurityCritical] static internal IntPtr UnsafeCastToStackPointer(ref T val) { IntPtr p = UnsafeCastToStackPointerInternal(ref val); - Contract.Assert(IsAddressInStack(p), "Pointer not in the stack!"); + Debug.Assert(IsAddressInStack(p), "Pointer not in the stack!"); return p; } - [SecurityCritical] static private IntPtr UnsafeCastToStackPointerInternal(ref T val) { // The body of this function will be replaced by the EE with unsafe code that just returns val!!! @@ -166,7 +166,6 @@ namespace System.Runtime.CompilerServices { #else // _DEBUG // The IL body of this method is not critical, but its body will be replaced with unsafe code, so // this method is effectively critical - [SecurityCritical] [FriendAccessAllowed] static internal T UnsafeCast(Object o) where T : class { @@ -189,7 +188,6 @@ namespace System.Runtime.CompilerServices { throw new InvalidOperationException(); } - [SecurityCritical] static internal IntPtr UnsafeCastToStackPointer(ref T val) { // The body of this function will be replaced by the EE with unsafe code that just returns o!!! @@ -199,12 +197,10 @@ namespace System.Runtime.CompilerServices { #endif // _DEBUG // Set the given element in the array without any type or range checks - [SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] extern static internal void UnsafeSetArrayElement(Object[] target, int index, Object element); // Used for unsafe pinning of arbitrary objects. - [System.Security.SecurityCritical] // auto-generated static internal PinningHelper GetPinningHelper(Object o) { // This cast is really unsafe - call the private version that does not assert in debug @@ -216,9 +212,33 @@ namespace System.Runtime.CompilerServices { } #if _DEBUG - [SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] extern static bool IsAddressInStack(IntPtr ptr); #endif + +#if FEATURE_SPAN_OF_T + static internal bool ByRefLessThan(ref T refA, ref T refB) + { + // The body of this function will be replaced by the EE with unsafe code!!! + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } + + /// true if given type is reference type or value type that contains references + static internal bool ContainsReferences() + { + // The body of this function will be replaced by the EE with unsafe code!!! + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } + + static internal ref T GetArrayData(T[] array) + { + // The body of this function will be replaced by the EE with unsafe code!!! + // See getILIntrinsicImplementation for how this happens. + typeof(ArrayPinningHelper).ToString(); // Type used by the actual method body + throw new InvalidOperationException(); + } +#endif // FEATURE_SPAN_OF_T } } diff --git a/src/mscorlib/src/System/Runtime/ExceptionServices/ExceptionNotification.cs b/src/mscorlib/src/System/Runtime/ExceptionServices/ExceptionNotification.cs new file mode 100644 index 0000000..b084891 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/ExceptionServices/ExceptionNotification.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. +// See the LICENSE file in the project root for more information. +/*============================================================================= +** +** File: ExceptionNotification.cs +** +** +** Purpose: Contains definitions for supporting Exception Notifications. +** +** Created: 10/07/2008 +** +** gkhanna +** +=============================================================================*/ +#if FEATURE_EXCEPTION_NOTIFICATIONS +namespace System.Runtime.ExceptionServices { + using System; + using System.Runtime.ConstrainedExecution; + + // Definition of the argument-type passed to the FirstChanceException event handler + public class FirstChanceExceptionEventArgs : EventArgs + { + // Constructor + public FirstChanceExceptionEventArgs(Exception exception) + { + m_Exception = exception; + } + + // Returns the exception object pertaining to the first chance exception + public Exception Exception + { + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + get { return m_Exception; } + } + + // Represents the FirstChance exception instance + private Exception m_Exception; + } +} +#endif // FEATURE_EXCEPTION_NOTIFICATIONS \ No newline at end of file diff --git a/src/mscorlib/src/System/Runtime/ExceptionServices/ExceptionServicesCommon.cs b/src/mscorlib/src/System/Runtime/ExceptionServices/ExceptionServicesCommon.cs index 7251d90..905f12d 100644 --- a/src/mscorlib/src/System/Runtime/ExceptionServices/ExceptionServicesCommon.cs +++ b/src/mscorlib/src/System/Runtime/ExceptionServices/ExceptionServicesCommon.cs @@ -101,7 +101,7 @@ namespace System.Runtime.ExceptionServices { { if (source == null) { - throw new ArgumentNullException("source", Environment.GetResourceString("ArgumentNull_Obj")); + throw new ArgumentNullException(nameof(source), Environment.GetResourceString("ArgumentNull_Obj")); } return new ExceptionDispatchInfo(source); diff --git a/src/mscorlib/src/System/Runtime/GcSettings.cs b/src/mscorlib/src/System/Runtime/GcSettings.cs index 5b4be27..91997f5 100644 --- a/src/mscorlib/src/System/Runtime/GcSettings.cs +++ b/src/mscorlib/src/System/Runtime/GcSettings.cs @@ -40,7 +40,6 @@ namespace System.Runtime { public static GCLatencyMode LatencyMode { - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] get { @@ -48,8 +47,6 @@ namespace System.Runtime { } // We don't want to allow this API when hosted. - [System.Security.SecurityCritical] // auto-generated_required - [HostProtection(MayLeakOnAbort = true)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] set { @@ -66,7 +63,6 @@ namespace System.Runtime { public static GCLargeObjectHeapCompactionMode LargeObjectHeapCompactionMode { - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] get { @@ -74,8 +70,6 @@ namespace System.Runtime { } // We don't want to allow this API when hosted. - [System.Security.SecurityCritical] // auto-generated_required - [HostProtection(MayLeakOnAbort = true)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] set { @@ -92,7 +86,6 @@ namespace System.Runtime { public static bool IsServerGC { - [System.Security.SecuritySafeCritical] // auto-generated get { return GC.IsServerGC(); } diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ArrayWithOffset.cs b/src/mscorlib/src/System/Runtime/InteropServices/ArrayWithOffset.cs index 83eae1c..77db3a7 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/ArrayWithOffset.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/ArrayWithOffset.cs @@ -17,7 +17,6 @@ namespace System.Runtime.InteropServices { // throw new Exception(); //} - [System.Security.SecuritySafeCritical] // auto-generated public ArrayWithOffset(Object array, int offset) { m_array = array; @@ -64,7 +63,6 @@ namespace System.Runtime.InteropServices { return !(a == b); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern int CalculateCount(); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/Attributes.cs b/src/mscorlib/src/System/Runtime/InteropServices/Attributes.cs index 06c963a..2de7304 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/Attributes.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/Attributes.cs @@ -8,6 +8,7 @@ namespace System.Runtime.InteropServices{ using System; using System.Reflection; + using System.Diagnostics; using System.Diagnostics.Contracts; [AttributeUsage(AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] @@ -525,31 +526,26 @@ namespace System.Runtime.InteropServices{ [System.Runtime.InteropServices.ComVisible(true)] public unsafe sealed class MarshalAsAttribute : Attribute { - [System.Security.SecurityCritical] // auto-generated internal static Attribute GetCustomAttribute(RuntimeParameterInfo parameter) { return GetCustomAttribute(parameter.MetadataToken, parameter.GetRuntimeModule()); } - [System.Security.SecurityCritical] // auto-generated internal static bool IsDefined(RuntimeParameterInfo parameter) { return GetCustomAttribute(parameter) != null; } - [System.Security.SecurityCritical] // auto-generated internal static Attribute GetCustomAttribute(RuntimeFieldInfo field) { return GetCustomAttribute(field.MetadataToken, field.GetRuntimeModule()); ; } - [System.Security.SecurityCritical] // auto-generated internal static bool IsDefined(RuntimeFieldInfo field) { return GetCustomAttribute(field) != null; } - [System.Security.SecurityCritical] // auto-generated internal static Attribute GetCustomAttribute(int token, RuntimeModule scope) { UnmanagedType unmanagedType, arraySubType; @@ -578,7 +574,7 @@ namespace System.Runtime.InteropServices{ { // The user may have supplied a bad type name string causing this TypeLoadException // Regardless, we return the bad type name - Contract.Assert(marshalTypeName != null); + Debug.Assert(marshalTypeName != null); } return new MarshalAsAttribute( @@ -772,7 +768,6 @@ namespace System.Runtime.InteropServices{ [System.Runtime.InteropServices.ComVisible(true)] public unsafe sealed class DllImportAttribute : Attribute { - [System.Security.SecurityCritical] // auto-generated internal static Attribute GetCustomAttribute(RuntimeMethodInfo method) { if ((method.Attributes & MethodAttributes.PinvokeImpl) == 0) @@ -869,7 +864,6 @@ namespace System.Runtime.InteropServices{ { private const int DEFAULT_PACKING_SIZE = 8; - [System.Security.SecurityCritical] // auto-generated internal static Attribute GetCustomAttribute(RuntimeType type) { if (!IsDefined(type)) @@ -940,7 +934,6 @@ namespace System.Runtime.InteropServices{ [System.Runtime.InteropServices.ComVisible(true)] public unsafe sealed class FieldOffsetAttribute : Attribute { - [System.Security.SecurityCritical] // auto-generated internal static Attribute GetCustomAttribute(RuntimeFieldInfo field) { int fieldOffset; @@ -952,7 +945,6 @@ namespace System.Runtime.InteropServices{ return null; } - [System.Security.SecurityCritical] // auto-generated internal static bool IsDefined(RuntimeFieldInfo field) { return GetCustomAttribute(field) != null; diff --git a/src/mscorlib/src/System/Runtime/InteropServices/BStrWrapper.cs b/src/mscorlib/src/System/Runtime/InteropServices/BStrWrapper.cs index 58e93a8..1673c91 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/BStrWrapper.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/BStrWrapper.cs @@ -21,19 +21,11 @@ namespace System.Runtime.InteropServices { [System.Runtime.InteropServices.ComVisible(true)] public sealed class BStrWrapper { - [System.Security.SecuritySafeCritical] // auto-generated -#pragma warning disable 618 - [SecurityPermissionAttribute(SecurityAction.Demand,Flags=SecurityPermissionFlag.UnmanagedCode)] -#pragma warning restore 618 public BStrWrapper(String value) { m_WrappedObject = value; } - [System.Security.SecuritySafeCritical] // auto-generated -#pragma warning disable 618 - [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] -#pragma warning restore 618 public BStrWrapper(Object value) { m_WrappedObject = (String)value; diff --git a/src/mscorlib/src/System/Runtime/InteropServices/COMException.cs b/src/mscorlib/src/System/Runtime/InteropServices/COMException.cs index 95b925c..fd500fd 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/COMException.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/COMException.cs @@ -46,7 +46,6 @@ namespace System.Runtime.InteropServices { SetErrorCode(errorCode); } - [SecuritySafeCritical] internal COMException(int hresult) : base(Win32Native.GetMessage(hresult)) { diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComEventsHelper.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsHelper.cs index 0bf616d..82692c1 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/ComEventsHelper.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsHelper.cs @@ -115,7 +115,6 @@ namespace System.Runtime.InteropServices { /// identifier of the source interface used by COM object to fire events /// dispatch identifier of the method on the source interface /// delegate to invoke when specifed COM event is fired - [System.Security.SecurityCritical] public static void Combine(object rcw, Guid iid, int dispid, System.Delegate d) { rcw = UnwrapIfTransparentProxy(rcw); @@ -146,7 +145,6 @@ namespace System.Runtime.InteropServices { /// dispatch identifier of the method on the source interface /// delegate to remove from the invocation list /// - [System.Security.SecurityCritical] public static Delegate Remove(object rcw, Guid iid, int dispid, System.Delegate d) { rcw = UnwrapIfTransparentProxy(rcw); @@ -183,18 +181,8 @@ namespace System.Runtime.InteropServices { } } - [System.Security.SecurityCritical] - internal static object UnwrapIfTransparentProxy(object rcw) { -#if FEATURE_REMOTING - if (RemotingServices.IsTransparentProxy(rcw)) { - IntPtr punk = Marshal.GetIUnknownForObject(rcw); - try { - rcw = Marshal.GetObjectForIUnknown(punk); - } finally { - Marshal.Release(punk); - } - } -#endif + internal static object UnwrapIfTransparentProxy(object rcw) + { return rcw; } } diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComEventsInfo.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsInfo.cs index 6feb524..2456ba3 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/ComEventsInfo.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsInfo.cs @@ -17,7 +17,6 @@ namespace System.Runtime.InteropServices { using ComTypes = System.Runtime.InteropServices.ComTypes; // see code:ComEventsHelper#ComEventsArchitecture - [System.Security.SecurityCritical] internal class ComEventsInfo { @@ -35,7 +34,6 @@ namespace System.Runtime.InteropServices { _rcw = rcw; } - [System.Security.SecuritySafeCritical] ~ComEventsInfo() { // see code:ComEventsHelper#ComEventsFinalization _sinks = ComEventsSink.RemoveAll(_sinks); @@ -46,13 +44,11 @@ namespace System.Runtime.InteropServices { #region static methods - [System.Security.SecurityCritical] internal static ComEventsInfo Find(object rcw) { return (ComEventsInfo)Marshal.GetComObjectData(rcw, typeof(ComEventsInfo)); } // it is caller's responsibility to call this method under lock(rcw) - [System.Security.SecurityCritical] internal static ComEventsInfo FromObject(object rcw) { ComEventsInfo eventsInfo = Find(rcw); if (eventsInfo == null) { @@ -80,7 +76,6 @@ namespace System.Runtime.InteropServices { } // it is caller's responsibility to call this method under lock(rcw) - [System.Security.SecurityCritical] internal ComEventsSink RemoveSink(ComEventsSink sink) { _sinks = ComEventsSink.Remove(_sinks, sink); return _sinks; diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComEventsSink.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsSink.cs index a414eff..05978a6 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/ComEventsSink.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsSink.cs @@ -16,7 +16,6 @@ namespace System.Runtime.InteropServices { using System.Diagnostics; // see code:ComEventsHelper#ComEventsArchitecture - [System.Security.SecurityCritical] internal class ComEventsSink : NativeMethods.IDispatch, ICustomQueryInterface { #region private fields @@ -57,7 +56,6 @@ namespace System.Runtime.InteropServices { return sink; } - [System.Security.SecurityCritical] internal static ComEventsSink RemoveAll(ComEventsSink sinks) { while (sinks != null) { sinks.Unadvise(); @@ -67,7 +65,6 @@ namespace System.Runtime.InteropServices { return null; } - [System.Security.SecurityCritical] internal static ComEventsSink Remove(ComEventsSink sinks, ComEventsSink sink) { BCLDebug.Assert(sinks != null, "removing event sink from empty sinks collection"); BCLDebug.Assert(sink != null, "specify event sink is null"); @@ -114,17 +111,14 @@ namespace System.Runtime.InteropServices { #region IDispatch Members - [System.Security.SecurityCritical] void NativeMethods.IDispatch.GetTypeInfoCount(out uint pctinfo) { pctinfo = 0; } - [System.Security.SecurityCritical] void NativeMethods.IDispatch.GetTypeInfo(uint iTInfo, int lcid, out IntPtr info) { throw new NotImplementedException(); } - [System.Security.SecurityCritical] void NativeMethods.IDispatch.GetIDsOfNames(ref Guid iid, string[] names, uint cNames, int lcid, int[] rgDispId) { throw new NotImplementedException(); } @@ -149,7 +143,6 @@ namespace System.Runtime.InteropServices { return pSrc; } - [System.Security.SecurityCritical] unsafe void NativeMethods.IDispatch.Invoke( int dispid, ref Guid riid, @@ -233,7 +226,6 @@ namespace System.Runtime.InteropServices { static Guid IID_IManagedObject = new Guid("{C3FCC19E-A970-11D2-8B5A-00A0C9B7C9C4}"); - [System.Security.SecurityCritical] CustomQueryInterfaceResult ICustomQueryInterface.GetInterface(ref Guid iid, out IntPtr ppv) { ppv = IntPtr.Zero; if (iid == this._iidSourceItf || iid == typeof(NativeMethods.IDispatch).GUID) { @@ -265,7 +257,6 @@ namespace System.Runtime.InteropServices { _connectionPoint = cp; } - [System.Security.SecurityCritical] private void Unadvise() { BCLDebug.Assert(_connectionPoint != null, "can not unadvise from empty connection point"); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/CriticalHandle.cs b/src/mscorlib/src/System/Runtime/InteropServices/CriticalHandle.cs index 54fd6b0..700e059 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/CriticalHandle.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/CriticalHandle.cs @@ -139,10 +139,6 @@ namespace System.Runtime.InteropServices // we'll do this to ensure we've cut off all attack vectors. Similarly, all // methods have a link demand to ensure untrusted code cannot directly edit // or alter a handle. -[System.Security.SecurityCritical] // auto-generated_required -#if !FEATURE_CORECLR -[SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)] -#endif public abstract class CriticalHandle : CriticalFinalizerObject, IDisposable { // ! Do not add or rearrange fields as the EE depends on this layout. @@ -168,19 +164,15 @@ public abstract class CriticalHandle : CriticalFinalizerObject, IDisposable #endif } -#if FEATURE_CORECLR // Adding an empty default constructor for annotation purposes private CriticalHandle(){} -#endif - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] ~CriticalHandle() { Dispose(false); } - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] private void Cleanup() { @@ -229,20 +221,17 @@ public abstract class CriticalHandle : CriticalFinalizerObject, IDisposable get; } - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public void Close() { Dispose(true); } - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public void Dispose() { Dispose(true); } - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] protected virtual void Dispose(bool disposing) { diff --git a/src/mscorlib/src/System/Runtime/InteropServices/CurrencyWrapper.cs b/src/mscorlib/src/System/Runtime/InteropServices/CurrencyWrapper.cs index 1f7a9f1..470e7b2 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/CurrencyWrapper.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/CurrencyWrapper.cs @@ -27,7 +27,7 @@ namespace System.Runtime.InteropServices { public CurrencyWrapper(Object obj) { if (!(obj is Decimal)) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDecimal"), "obj"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDecimal"), nameof(obj)); m_WrappedObject = (Decimal)obj; } diff --git a/src/mscorlib/src/System/Runtime/InteropServices/DispatchWrapper.cs b/src/mscorlib/src/System/Runtime/InteropServices/DispatchWrapper.cs index 1fc72f7..47b7542 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/DispatchWrapper.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/DispatchWrapper.cs @@ -21,10 +21,6 @@ namespace System.Runtime.InteropServices { [System.Runtime.InteropServices.ComVisible(true)] public sealed class DispatchWrapper { - [System.Security.SecuritySafeCritical] // auto-generated -#pragma warning disable 618 - [SecurityPermissionAttribute(SecurityAction.Demand,Flags=SecurityPermissionFlag.UnmanagedCode)] -#pragma warning restore 618 public DispatchWrapper(Object obj) { if (obj != null) diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ErrorWrapper.cs b/src/mscorlib/src/System/Runtime/InteropServices/ErrorWrapper.cs index d63d69c..a9fa58f 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/ErrorWrapper.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/ErrorWrapper.cs @@ -28,14 +28,10 @@ namespace System.Runtime.InteropServices { public ErrorWrapper(Object errorCode) { if (!(errorCode is int)) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeInt32"), "errorCode"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeInt32"), nameof(errorCode)); m_ErrorCode = (int)errorCode; } - [System.Security.SecuritySafeCritical] // auto-generated -#pragma warning disable 618 - [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] -#pragma warning restore 618 public ErrorWrapper(Exception e) { m_ErrorCode = Marshal.GetHRForException(e); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ExtensibleClassFactory.cs b/src/mscorlib/src/System/Runtime/InteropServices/ExtensibleClassFactory.cs index 62718de..a12a38e 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/ExtensibleClassFactory.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/ExtensibleClassFactory.cs @@ -34,7 +34,6 @@ namespace System.Runtime.InteropServices { // class for which the callbacks will be made. // It is not legal to register this callback from a class that has any // parents that have already registered a callback. - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern void RegisterObjectCreationCallback(ObjectCreationDelegate callback); } diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ExternalException.cs b/src/mscorlib/src/System/Runtime/InteropServices/ExternalException.cs index 417cf94..70a6dfe 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/ExternalException.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/ExternalException.cs @@ -52,7 +52,6 @@ namespace System.Runtime.InteropServices { } } -#if !FEATURE_CORECLR // Breaks the subset-of-Orcas property public override String ToString() { String message = Message; String s; @@ -75,6 +74,5 @@ namespace System.Runtime.InteropServices { return s; } -#endif // !FEATURE_CORECLR } } diff --git a/src/mscorlib/src/System/Runtime/InteropServices/GcHandle.cs b/src/mscorlib/src/System/Runtime/InteropServices/GcHandle.cs index 58fea97..5530819 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/GcHandle.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/GcHandle.cs @@ -47,7 +47,6 @@ namespace System.Runtime.InteropServices private const GCHandleType MaxHandleType = GCHandleType.Pinned; #if MDA_SUPPORTED - [System.Security.SecuritySafeCritical] // auto-generated static GCHandle() { s_probeIsActive = Mda.IsInvalidGCHandleCookieProbeEnabled(); @@ -57,12 +56,11 @@ namespace System.Runtime.InteropServices #endif // Allocate a handle storing the object and the type. - [System.Security.SecurityCritical] // auto-generated internal GCHandle(Object value, GCHandleType type) { // Make sure the type parameter is within the valid range for the enum. if ((uint)type > (uint)MaxHandleType) - throw new ArgumentOutOfRangeException("type", Environment.GetResourceString("ArgumentOutOfRange_Enum")); + throw new ArgumentOutOfRangeException(nameof(type), Environment.GetResourceString("ArgumentOutOfRange_Enum")); Contract.EndContractBlock(); m_handle = InternalAlloc(value, type); @@ -73,7 +71,6 @@ namespace System.Runtime.InteropServices } // Used in the conversion functions below. - [System.Security.SecurityCritical] // auto-generated internal GCHandle(IntPtr handle) { InternalCheckDomain(handle); @@ -86,13 +83,11 @@ namespace System.Runtime.InteropServices // type - The type of GC handle to create. // // returns a new GC handle that protects the object. - [System.Security.SecurityCritical] // auto-generated_required public static GCHandle Alloc(Object value) { return new GCHandle(value, GCHandleType.Normal); } - [System.Security.SecurityCritical] // auto-generated_required public static GCHandle Alloc(Object value, GCHandleType type) { return new GCHandle(value, type); @@ -100,7 +95,6 @@ namespace System.Runtime.InteropServices // Frees a GC handle. - [System.Security.SecurityCritical] // auto-generated_required public void Free() { // Copy the handle instance member to a local variable. This is required to prevent @@ -134,7 +128,6 @@ namespace System.Runtime.InteropServices // Target property - allows getting / updating of the handle's referent. public Object Target { - [System.Security.SecurityCritical] // auto-generated_required get { // Check if the handle was never initialized or was freed. @@ -144,7 +137,6 @@ namespace System.Runtime.InteropServices return InternalGet(GetHandleValue()); } - [System.Security.SecurityCritical] // auto-generated_required set { // Check if the handle was never initialized or was freed. @@ -157,7 +149,6 @@ namespace System.Runtime.InteropServices // Retrieve the address of an object in a Pinned handle. This throws // an exception if the handle is any type other than Pinned. - [System.Security.SecurityCritical] // auto-generated_required public IntPtr AddrOfPinnedObject() { // Check if the handle was not a pinned handle. @@ -186,13 +177,11 @@ namespace System.Runtime.InteropServices // Used to create a GCHandle from an int. This is intended to // be used with the reverse conversion. - [System.Security.SecurityCritical] // auto-generated_required public static explicit operator GCHandle(IntPtr value) { return FromIntPtr(value); } - [System.Security.SecurityCritical] // auto-generated_required public static GCHandle FromIntPtr(IntPtr value) { if (value == IntPtr.Zero) @@ -293,28 +282,20 @@ namespace System.Runtime.InteropServices } // Internal native calls that this implementation uses. - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern IntPtr InternalAlloc(Object value, GCHandleType type); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void InternalFree(IntPtr handle); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern Object InternalGet(IntPtr handle); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void InternalSet(IntPtr handle, Object value, bool isPinned); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern Object InternalCompareExchange(IntPtr handle, Object value, Object oldValue, bool isPinned); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern IntPtr InternalAddrOfPinnedObject(IntPtr handle); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void InternalCheckDomain(IntPtr handle); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern GCHandleType InternalGetHandleType(IntPtr handle); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ICustomQueryInterface.cs b/src/mscorlib/src/System/Runtime/InteropServices/ICustomQueryInterface.cs index 61688b9..c7d7937 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/ICustomQueryInterface.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/ICustomQueryInterface.cs @@ -33,7 +33,6 @@ namespace System.Runtime.InteropServices { [System.Runtime.InteropServices.ComVisible(false)] public interface ICustomQueryInterface { - [System.Security.SecurityCritical] CustomQueryInterfaceResult GetInterface([In]ref Guid iid, out IntPtr ppv); } } diff --git a/src/mscorlib/src/System/Runtime/InteropServices/IException.cs b/src/mscorlib/src/System/Runtime/InteropServices/IException.cs index 2da0a56..2330365 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/IException.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/IException.cs @@ -22,48 +22,9 @@ namespace System.Runtime.InteropServices { [GuidAttribute("b36b5c63-42ef-38bc-a07e-0b34c98f164a")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)] [CLSCompliant(false)] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _Exception { -#if !FEATURE_CORECLR - // This contains all of our V1 Exception class's members. - - // From Object - String ToString(); - bool Equals (Object obj); - int GetHashCode (); - Type GetType (); - - // From V1's Exception class - String Message { - get; - } - - Exception GetBaseException(); - - String StackTrace { - get; - } - - String HelpLink { - get; - set; - } - - String Source { - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif - get; - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif - set; - } - [System.Security.SecurityCritical] // auto-generated_required - void GetObjectData(SerializationInfo info, StreamingContext context); -#endif - // // This method is intentionally included in CoreCLR to make Exception.get_InnerException "newslot virtual final". // Some phone apps include MEF from desktop Silverlight. MEF's ComposablePartException depends on implicit interface @@ -73,12 +34,5 @@ namespace System.Runtime.InteropServices { Exception InnerException { get; } - -#if !FEATURE_CORECLR - MethodBase TargetSite { - get; - } -#endif } - } diff --git a/src/mscorlib/src/System/Runtime/InteropServices/IRegistrationServices.cs b/src/mscorlib/src/System/Runtime/InteropServices/IRegistrationServices.cs index ae330e8..f2f7c61 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/IRegistrationServices.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/IRegistrationServices.cs @@ -31,24 +31,18 @@ namespace System.Runtime.InteropServices { [System.Runtime.InteropServices.ComVisible(true)] public interface IRegistrationServices { - [System.Security.SecurityCritical] // auto-generated_required bool RegisterAssembly(Assembly assembly, AssemblyRegistrationFlags flags); - [System.Security.SecurityCritical] // auto-generated_required bool UnregisterAssembly(Assembly assembly); - [System.Security.SecurityCritical] // auto-generated_required Type[] GetRegistrableTypesInAssembly(Assembly assembly); - [System.Security.SecurityCritical] // auto-generated_required String GetProgIdForType(Type type); - [System.Security.SecurityCritical] // auto-generated_required void RegisterTypeForComClients(Type type, ref Guid g); Guid GetManagedCategoryGuid(); - [System.Security.SecurityCritical] // auto-generated_required bool TypeRequiresRegistration(Type type); bool TypeRepresentsComType(Type type); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/Marshal.cs b/src/mscorlib/src/System/Runtime/InteropServices/Marshal.cs index 86e8830..3a79650 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/Marshal.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/Marshal.cs @@ -29,6 +29,7 @@ namespace System.Runtime.InteropServices using System.Runtime.Versioning; using Win32Native = Microsoft.Win32.Win32Native; using Microsoft.Win32.SafeHandles; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices.ComTypes; @@ -45,9 +46,6 @@ namespace System.Runtime.InteropServices // declaration on the class. //======================================================================== - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif public static partial class Marshal { //==================================================================== @@ -117,7 +115,6 @@ namespace System.Runtime.InteropServices [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern int GetSystemMaxDBCSCharSize(); - [System.Security.SecurityCritical] // auto-generated_required unsafe public static String PtrToStringAnsi(IntPtr ptr) { if (IntPtr.Zero == ptr) { @@ -137,36 +134,32 @@ namespace System.Runtime.InteropServices } } - [System.Security.SecurityCritical] // auto-generated_required unsafe public static String PtrToStringAnsi(IntPtr ptr, int len) { if (ptr == IntPtr.Zero) - throw new ArgumentNullException("ptr"); + throw new ArgumentNullException(nameof(ptr)); if (len < 0) - throw new ArgumentException("len"); + throw new ArgumentException(null, nameof(len)); return new String((sbyte *)ptr, 0, len); } - [System.Security.SecurityCritical] // auto-generated_required unsafe public static String PtrToStringUni(IntPtr ptr, int len) { if (ptr == IntPtr.Zero) - throw new ArgumentNullException("ptr"); + throw new ArgumentNullException(nameof(ptr)); if (len < 0) - throw new ArgumentException("len"); + throw new ArgumentException(null, nameof(len)); return new String((char *)ptr, 0, len); } - [System.Security.SecurityCritical] // auto-generated_required public static String PtrToStringAuto(IntPtr ptr, int len) { // Ansi platforms are no longer supported return PtrToStringUni(ptr, len); } - [System.Security.SecurityCritical] // auto-generated_required unsafe public static String PtrToStringUni(IntPtr ptr) { if (IntPtr.Zero == ptr) { @@ -180,26 +173,23 @@ namespace System.Runtime.InteropServices } } - [System.Security.SecurityCritical] // auto-generated_required public static String PtrToStringAuto(IntPtr ptr) { // Ansi platforms are no longer supported return PtrToStringUni(ptr); } - [System.Security.SecurityCritical] // auto-generated_required unsafe public static String PtrToStringUTF8(IntPtr ptr) { int nbBytes = System.StubHelpers.StubHelpers.strlen((sbyte*)ptr.ToPointer()); return PtrToStringUTF8(ptr, nbBytes); } - [System.Security.SecurityCritical] // auto-generated_required unsafe public static String PtrToStringUTF8(IntPtr ptr,int byteLen) { if (byteLen < 0) { - throw new ArgumentException("byteLen"); + throw new ArgumentException(null, nameof(byteLen)); } else if (IntPtr.Zero == ptr) { @@ -227,7 +217,7 @@ namespace System.Runtime.InteropServices public static int SizeOf(Object structure) { if (structure == null) - throw new ArgumentNullException("structure"); + throw new ArgumentNullException(nameof(structure)); // we never had a check for generics here Contract.EndContractBlock(); @@ -243,11 +233,11 @@ namespace System.Runtime.InteropServices public static int SizeOf(Type t) { if (t == null) - throw new ArgumentNullException("t"); + throw new ArgumentNullException(nameof(t)); if (!(t is RuntimeType)) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "t"); + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), nameof(t)); if (t.IsGenericType) - throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "t"); + throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), nameof(t)); Contract.EndContractBlock(); return SizeOfHelper(t, true); @@ -290,9 +280,6 @@ namespace System.Runtime.InteropServices [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] private static extern uint AlignedSizeOfType(Type type); -#if !FEATURE_CORECLR // Marshal is critical in CoreCLR, so SafeCritical members trigger Annotator violations - [System.Security.SecuritySafeCritical] -#endif // !FEATURE_CORECLR [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern int SizeOfHelper(Type t, bool throwIfNotMarshalable); @@ -302,15 +289,15 @@ namespace System.Runtime.InteropServices public static IntPtr OffsetOf(Type t, String fieldName) { if (t == null) - throw new ArgumentNullException("t"); + throw new ArgumentNullException(nameof(t)); Contract.EndContractBlock(); FieldInfo f = t.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (f == null) - throw new ArgumentException(Environment.GetResourceString("Argument_OffsetOfFieldNotFound", t.FullName), "fieldName"); + throw new ArgumentException(Environment.GetResourceString("Argument_OffsetOfFieldNotFound", t.FullName), nameof(fieldName)); RtFieldInfo rtField = f as RtFieldInfo; if (rtField == null) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeFieldInfo"), "fieldName"); + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeFieldInfo"), nameof(fieldName)); return OffsetOfHelper(rtField); } @@ -330,11 +317,9 @@ namespace System.Runtime.InteropServices // an array that is not pinned or in the fixed heap can cause // unexpected results ! //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern IntPtr UnsafeAddrOfPinnedArrayElement(Array arr, int index); - [System.Security.SecurityCritical] public static IntPtr UnsafeAddrOfPinnedArrayElement(T[] arr, int index) { return UnsafeAddrOfPinnedArrayElement((Array)arr, index); @@ -343,42 +328,34 @@ namespace System.Runtime.InteropServices //==================================================================== // Copy blocks from CLR arrays to native memory. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static void Copy(int[] source, int startIndex, IntPtr destination, int length) { CopyToNative(source, startIndex, destination, length); } - [System.Security.SecurityCritical] // auto-generated_required public static void Copy(char[] source, int startIndex, IntPtr destination, int length) { CopyToNative(source, startIndex, destination, length); } - [System.Security.SecurityCritical] // auto-generated_required public static void Copy(short[] source, int startIndex, IntPtr destination, int length) { CopyToNative(source, startIndex, destination, length); } - [System.Security.SecurityCritical] // auto-generated_required public static void Copy(long[] source, int startIndex, IntPtr destination, int length) { CopyToNative(source, startIndex, destination, length); } - [System.Security.SecurityCritical] // auto-generated_required public static void Copy(float[] source, int startIndex, IntPtr destination, int length) { CopyToNative(source, startIndex, destination, length); } - [System.Security.SecurityCritical] // auto-generated_required public static void Copy(double[] source, int startIndex, IntPtr destination, int length) { CopyToNative(source, startIndex, destination, length); } - [System.Security.SecurityCritical] // auto-generated_required public static void Copy(byte[] source, int startIndex, IntPtr destination, int length) { CopyToNative(source, startIndex, destination, length); } - [System.Security.SecurityCritical] // auto-generated_required public static void Copy(IntPtr[] source, int startIndex, IntPtr destination, int length) { CopyToNative(source, startIndex, destination, length); @@ -389,42 +366,34 @@ namespace System.Runtime.InteropServices //==================================================================== // Copy blocks from native memory to CLR arrays //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static void Copy(IntPtr source, int[] destination, int startIndex, int length) { CopyToManaged(source, destination, startIndex, length); } - [System.Security.SecurityCritical] // auto-generated_required public static void Copy(IntPtr source, char[] destination, int startIndex, int length) { CopyToManaged(source, destination, startIndex, length); } - [System.Security.SecurityCritical] // auto-generated_required public static void Copy(IntPtr source, short[] destination, int startIndex, int length) { CopyToManaged(source, destination, startIndex, length); } - [System.Security.SecurityCritical] // auto-generated_required public static void Copy(IntPtr source, long[] destination, int startIndex, int length) { CopyToManaged(source, destination, startIndex, length); } - [System.Security.SecurityCritical] // auto-generated_required public static void Copy(IntPtr source, float[] destination, int startIndex, int length) { CopyToManaged(source, destination, startIndex, length); } - [System.Security.SecurityCritical] // auto-generated_required public static void Copy(IntPtr source, double[] destination, int startIndex, int length) { CopyToManaged(source, destination, startIndex, length); } - [System.Security.SecurityCritical] // auto-generated_required public static void Copy(IntPtr source, byte[] destination, int startIndex, int length) { CopyToManaged(source, destination, startIndex, length); } - [System.Security.SecurityCritical] // auto-generated_required public static void Copy(IntPtr source, IntPtr[] destination, int startIndex, int length) { CopyToManaged(source, destination, startIndex, length); @@ -435,19 +404,11 @@ namespace System.Runtime.InteropServices //==================================================================== // Read from memory //==================================================================== - [System.Security.SecurityCritical] // auto-generated -#if !FEATURE_CORECLR - [DllImport(Win32Native.SHIM, EntryPoint="ND_RU1")] - [SuppressUnmanagedCodeSecurity] - public static extern byte ReadByte([MarshalAs(UnmanagedType.AsAny), In] Object ptr, int ofs); -#else public static byte ReadByte([MarshalAs(UnmanagedType.AsAny), In] Object ptr, int ofs) { throw new PlatformNotSupportedException(); - } -#endif // !FEATURE_CORECLR + } - [System.Security.SecurityCritical] // auto-generated_required public static unsafe byte ReadByte(IntPtr ptr, int ofs) { try @@ -462,25 +423,16 @@ namespace System.Runtime.InteropServices } } - [System.Security.SecurityCritical] // auto-generated_required public static byte ReadByte(IntPtr ptr) { return ReadByte(ptr,0); } - - [System.Security.SecurityCritical] // auto-generated -#if !FEATURE_CORECLR - [DllImport(Win32Native.SHIM, EntryPoint="ND_RI2")] - [SuppressUnmanagedCodeSecurity] - public static extern short ReadInt16([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs); -#else + public static short ReadInt16([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs) { throw new PlatformNotSupportedException(); - } -#endif // !FEATURE_CORECLR + } - [System.Security.SecurityCritical] // auto-generated_required public static unsafe short ReadInt16(IntPtr ptr, int ofs) { try @@ -508,25 +460,16 @@ namespace System.Runtime.InteropServices } } - [System.Security.SecurityCritical] // auto-generated_required public static short ReadInt16(IntPtr ptr) { return ReadInt16(ptr, 0); } - - [System.Security.SecurityCritical] // auto-generated -#if !FEATURE_CORECLR - [DllImport(Win32Native.SHIM, EntryPoint="ND_RI4"), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [SuppressUnmanagedCodeSecurity] - public static extern int ReadInt32([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs); -#else + public static int ReadInt32([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs) { throw new PlatformNotSupportedException(); } -#endif // !FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated_required [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static unsafe int ReadInt32(IntPtr ptr, int ofs) { @@ -557,14 +500,12 @@ namespace System.Runtime.InteropServices } } - [System.Security.SecurityCritical] // auto-generated_required [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static int ReadInt32(IntPtr ptr) { return ReadInt32(ptr,0); } - [System.Security.SecurityCritical] // auto-generated_required [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static IntPtr ReadIntPtr([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs) { @@ -575,7 +516,6 @@ namespace System.Runtime.InteropServices #endif } - [System.Security.SecurityCritical] // auto-generated_required [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static IntPtr ReadIntPtr(IntPtr ptr, int ofs) { @@ -586,7 +526,6 @@ namespace System.Runtime.InteropServices #endif } - [System.Security.SecurityCritical] // auto-generated_required [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static IntPtr ReadIntPtr(IntPtr ptr) { @@ -597,19 +536,11 @@ namespace System.Runtime.InteropServices #endif } - [System.Security.SecurityCritical] // auto-generated -#if !FEATURE_CORECLR - [DllImport(Win32Native.SHIM, EntryPoint="ND_RI8"), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [SuppressUnmanagedCodeSecurity] - public static extern long ReadInt64([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs); -#else public static long ReadInt64([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs) { throw new PlatformNotSupportedException(); } -#endif // !FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated_required public static unsafe long ReadInt64(IntPtr ptr, int ofs) { try @@ -643,7 +574,6 @@ namespace System.Runtime.InteropServices } } - [System.Security.SecurityCritical] // auto-generated_required [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static long ReadInt64(IntPtr ptr) { @@ -654,7 +584,6 @@ namespace System.Runtime.InteropServices //==================================================================== // Write to memory //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static unsafe void WriteByte(IntPtr ptr, int ofs, byte val) { try @@ -669,25 +598,16 @@ namespace System.Runtime.InteropServices } } - [System.Security.SecurityCritical] // auto-generated -#if !FEATURE_CORECLR - [DllImport(Win32Native.SHIM, EntryPoint="ND_WU1")] - [SuppressUnmanagedCodeSecurity] - public static extern void WriteByte([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, byte val); -#else public static void WriteByte([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, byte val) { throw new PlatformNotSupportedException(); } -#endif // !FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated_required public static void WriteByte(IntPtr ptr, byte val) { WriteByte(ptr, 0, val); } - [System.Security.SecurityCritical] // auto-generated_required public static unsafe void WriteInt16(IntPtr ptr, int ofs, short val) { try @@ -712,44 +632,32 @@ namespace System.Runtime.InteropServices throw new AccessViolationException(); } } - - [System.Security.SecurityCritical] // auto-generated -#if !FEATURE_CORECLR - [DllImport(Win32Native.SHIM, EntryPoint="ND_WI2")] - [SuppressUnmanagedCodeSecurity] - public static extern void WriteInt16([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, short val); -#else + public static void WriteInt16([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, short val) { throw new PlatformNotSupportedException(); } -#endif // !FEATURE_CORECLR - - [System.Security.SecurityCritical] // auto-generated_required + public static void WriteInt16(IntPtr ptr, short val) { WriteInt16(ptr, 0, val); } - [System.Security.SecurityCritical] // auto-generated_required public static void WriteInt16(IntPtr ptr, int ofs, char val) { WriteInt16(ptr, ofs, (short)val); } - [System.Security.SecurityCritical] // auto-generated_required public static void WriteInt16([In,Out]Object ptr, int ofs, char val) { WriteInt16(ptr, ofs, (short)val); } - [System.Security.SecurityCritical] // auto-generated_required public static void WriteInt16(IntPtr ptr, char val) { WriteInt16(ptr, 0, (short)val); } - [System.Security.SecurityCritical] // auto-generated_required public static unsafe void WriteInt32(IntPtr ptr, int ofs, int val) { try @@ -776,26 +684,17 @@ namespace System.Runtime.InteropServices throw new AccessViolationException(); } } - - [System.Security.SecurityCritical] // auto-generated -#if !FEATURE_CORECLR - [DllImport(Win32Native.SHIM, EntryPoint="ND_WI4")] - [SuppressUnmanagedCodeSecurity] - public static extern void WriteInt32([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, int val); -#else + public static void WriteInt32([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, int val) { throw new PlatformNotSupportedException(); } -#endif // !FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated_required public static void WriteInt32(IntPtr ptr, int val) { WriteInt32(ptr,0,val); } - [System.Security.SecurityCritical] // auto-generated_required public static void WriteIntPtr(IntPtr ptr, int ofs, IntPtr val) { #if BIT64 @@ -805,7 +704,6 @@ namespace System.Runtime.InteropServices #endif } - [System.Security.SecurityCritical] // auto-generated_required public static void WriteIntPtr([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, IntPtr val) { #if BIT64 @@ -815,7 +713,6 @@ namespace System.Runtime.InteropServices #endif } - [System.Security.SecurityCritical] // auto-generated_required public static void WriteIntPtr(IntPtr ptr, IntPtr val) { #if BIT64 @@ -825,7 +722,6 @@ namespace System.Runtime.InteropServices #endif } - [System.Security.SecurityCritical] // auto-generated_required public static unsafe void WriteInt64(IntPtr ptr, int ofs, long val) { try @@ -856,20 +752,12 @@ namespace System.Runtime.InteropServices throw new AccessViolationException(); } } - - [System.Security.SecurityCritical] // auto-generated -#if !FEATURE_CORECLR - [DllImport(Win32Native.SHIM, EntryPoint="ND_WI8")] - [SuppressUnmanagedCodeSecurity] - public static extern void WriteInt64([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, long val); -#else + public static void WriteInt64([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, long val) { throw new PlatformNotSupportedException(); } -#endif // !FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated_required public static void WriteInt64(IntPtr ptr, long val) { WriteInt64(ptr, 0, val); @@ -879,7 +767,6 @@ namespace System.Runtime.InteropServices //==================================================================== // GetLastWin32Error //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static extern int GetLastWin32Error(); @@ -896,7 +783,6 @@ namespace System.Runtime.InteropServices //==================================================================== // GetHRForLastWin32Error //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static int GetHRForLastWin32Error() { @@ -911,11 +797,10 @@ namespace System.Runtime.InteropServices //==================================================================== // Prelink //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static void Prelink(MethodInfo m) { if (m == null) - throw new ArgumentNullException("m"); + throw new ArgumentNullException(nameof(m)); Contract.EndContractBlock(); RuntimeMethodInfo rmi = m as RuntimeMethodInfo; @@ -927,14 +812,12 @@ namespace System.Runtime.InteropServices } [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] - [SecurityCritical] private static extern void InternalPrelink(IRuntimeMethodInfo m); - [System.Security.SecurityCritical] // auto-generated_required public static void PrelinkAll(Type c) { if (c == null) - throw new ArgumentNullException("c"); + throw new ArgumentNullException(nameof(c)); Contract.EndContractBlock(); MethodInfo[] mi = c.GetMethods(); @@ -950,11 +833,10 @@ namespace System.Runtime.InteropServices //==================================================================== // NumParamBytes //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static int NumParamBytes(MethodInfo m) { if (m == null) - throw new ArgumentNullException("m"); + throw new ArgumentNullException(nameof(m)); Contract.EndContractBlock(); RuntimeMethodInfo rmi = m as RuntimeMethodInfo; @@ -965,7 +847,6 @@ namespace System.Runtime.InteropServices } [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] - [SecurityCritical] private static extern int InternalNumParamBytes(IRuntimeMethodInfo m); //==================================================================== @@ -973,12 +854,10 @@ namespace System.Runtime.InteropServices // These are mostly interesting for Structured exception handling, // but need to be exposed for all exceptions (not just SEHException). //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] [System.Runtime.InteropServices.ComVisible(true)] public static extern /* struct _EXCEPTION_POINTERS* */ IntPtr GetExceptionPointers(); - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern int GetExceptionCode(); @@ -988,12 +867,10 @@ namespace System.Runtime.InteropServices // If the structure contains pointers to allocated blocks and // "fDeleteOld" is true, this routine will call DestroyStructure() first. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [System.Runtime.InteropServices.ComVisible(true)] public static extern void StructureToPtr(Object structure, IntPtr ptr, bool fDeleteOld); - [System.Security.SecurityCritical] public static void StructureToPtr(T structure, IntPtr ptr, bool fDeleteOld) { StructureToPtr((object)structure, ptr, fDeleteOld); @@ -1002,14 +879,12 @@ namespace System.Runtime.InteropServices //==================================================================== // Marshals data from a native memory block to a preallocated structure class. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [System.Runtime.InteropServices.ComVisible(true)] public static void PtrToStructure(IntPtr ptr, Object structure) { PtrToStructureHelper(ptr, structure, false); } - [System.Security.SecurityCritical] public static void PtrToStructure(IntPtr ptr, T structure) { PtrToStructure(ptr, (object)structure); @@ -1019,7 +894,6 @@ namespace System.Runtime.InteropServices // Creates a new instance of "structuretype" and marshals data from a // native memory block to it. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [System.Runtime.InteropServices.ComVisible(true)] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static Object PtrToStructure(IntPtr ptr, Type structureType) @@ -1027,15 +901,15 @@ namespace System.Runtime.InteropServices if (ptr == IntPtr.Zero) return null; if (structureType == null) - throw new ArgumentNullException("structureType"); + throw new ArgumentNullException(nameof(structureType)); if (structureType.IsGenericType) - throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "structureType"); + throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), nameof(structureType)); RuntimeType rt = structureType.UnderlyingSystemType as RuntimeType; if (rt == null) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "type"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), nameof(structureType)); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -1044,7 +918,6 @@ namespace System.Runtime.InteropServices return structure; } - [System.Security.SecurityCritical] public static T PtrToStructure(IntPtr ptr) { return (T)PtrToStructure(ptr, typeof(T)); @@ -1061,27 +934,25 @@ namespace System.Runtime.InteropServices // Freeds all substructures pointed to by the native memory block. // "structureclass" is used to provide layout information. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] [System.Runtime.InteropServices.ComVisible(true)] public static extern void DestroyStructure(IntPtr ptr, Type structuretype); - [System.Security.SecurityCritical] public static void DestroyStructure(IntPtr ptr) { DestroyStructure(ptr, typeof(T)); } +#if FEATURE_COMINTEROP //==================================================================== // Returns the HInstance for this module. Returns -1 if the module // doesn't have an HInstance. In Memory (Dynamic) Modules won't have // an HInstance. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static IntPtr GetHINSTANCE(Module m) { if (m == null) - throw new ArgumentNullException("m"); + throw new ArgumentNullException(nameof(m)); Contract.EndContractBlock(); RuntimeModule rtModule = m as RuntimeModule; @@ -1093,26 +964,24 @@ namespace System.Runtime.InteropServices } if (rtModule == null) - throw new ArgumentNullException("m",Environment.GetResourceString("Argument_MustBeRuntimeModule")); + throw new ArgumentNullException(nameof(m),Environment.GetResourceString("Argument_MustBeRuntimeModule")); return GetHINSTANCE(rtModule.GetNativeHandle()); } - [System.Security.SecurityCritical] // auto-generated_required [SuppressUnmanagedCodeSecurity] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] private extern static IntPtr GetHINSTANCE(RuntimeModule m); +#endif // FEATURE_COMINTEROP //==================================================================== // Throws a CLR exception based on the HRESULT. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static void ThrowExceptionForHR(int errorCode) { if (errorCode < 0) ThrowExceptionForHRInternal(errorCode, IntPtr.Zero); } - [System.Security.SecurityCritical] // auto-generated_required public static void ThrowExceptionForHR(int errorCode, IntPtr errorInfo) { if (errorCode < 0) @@ -1126,7 +995,6 @@ namespace System.Runtime.InteropServices //==================================================================== // Converts the HRESULT to a CLR exception. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static Exception GetExceptionForHR(int errorCode) { if (errorCode < 0) @@ -1134,7 +1002,6 @@ namespace System.Runtime.InteropServices else return null; } - [System.Security.SecurityCritical] // auto-generated_required public static Exception GetExceptionForHR(int errorCode, IntPtr errorInfo) { if (errorCode < 0) @@ -1151,7 +1018,6 @@ namespace System.Runtime.InteropServices // This method is intended for compiler code generators rather // than applications. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [ObsoleteAttribute("The GetUnmanagedThunkForManagedMethodPtr method has been deprecated and will be removed in a future release.", false)] [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern IntPtr GetUnmanagedThunkForManagedMethodPtr(IntPtr pfnMethodToWrap, IntPtr pbSignature, int cbSignature); @@ -1160,7 +1026,6 @@ namespace System.Runtime.InteropServices // This method is intended for compiler code generators rather // than applications. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [ObsoleteAttribute("The GetManagedThunkForUnmanagedMethodPtr method has been deprecated and will be removed in a future release.", false)] [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern IntPtr GetManagedThunkForUnmanagedMethodPtr(IntPtr pfnMethodToWrap, IntPtr pbSignature, int cbSignature); @@ -1171,12 +1036,11 @@ namespace System.Runtime.InteropServices // activity. A fiber cookie can be redeemed for its managed Thread // object by calling the following service. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [ObsoleteAttribute("The GetThreadFromFiberCookie method has been deprecated. Use the hosting API to perform this operation.", false)] public static Thread GetThreadFromFiberCookie(int cookie) { if (cookie == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_ArgumentZero"), "cookie"); + throw new ArgumentException(Environment.GetResourceString("Argument_ArgumentZero"), nameof(cookie)); Contract.EndContractBlock(); return InternalGetThreadFromFiberCookie(cookie); @@ -1189,7 +1053,6 @@ namespace System.Runtime.InteropServices //==================================================================== // Memory allocation and deallocation. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static IntPtr AllocHGlobal(IntPtr cb) { @@ -1214,14 +1077,12 @@ namespace System.Runtime.InteropServices return pNewMem; } - [System.Security.SecurityCritical] // auto-generated_required [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static IntPtr AllocHGlobal(int cb) { return AllocHGlobal((IntPtr)cb); } - [System.Security.SecurityCritical] // auto-generated_required [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static void FreeHGlobal(IntPtr hglobal) { @@ -1232,7 +1093,6 @@ namespace System.Runtime.InteropServices } } - [System.Security.SecurityCritical] // auto-generated_required public static IntPtr ReAllocHGlobal(IntPtr pv, IntPtr cb) { IntPtr pNewMem = Win32Native.LocalReAlloc(pv, cb, LMEM_MOVEABLE); @@ -1246,7 +1106,6 @@ namespace System.Runtime.InteropServices //==================================================================== // String convertions. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required unsafe public static IntPtr StringToHGlobalAnsi(String s) { if (s == null) @@ -1259,7 +1118,7 @@ namespace System.Runtime.InteropServices // Overflow checking if (nb < s.Length) - throw new ArgumentOutOfRangeException("s"); + throw new ArgumentOutOfRangeException(nameof(s)); UIntPtr len = new UIntPtr((uint)nb); IntPtr hglobal = Win32Native.LocalAlloc_NoSafeHandle(LMEM_FIXED, len); @@ -1276,7 +1135,6 @@ namespace System.Runtime.InteropServices } } - [System.Security.SecurityCritical] // auto-generated_required unsafe public static IntPtr StringToHGlobalUni(String s) { if (s == null) @@ -1289,7 +1147,7 @@ namespace System.Runtime.InteropServices // Overflow checking if (nb < s.Length) - throw new ArgumentOutOfRangeException("s"); + throw new ArgumentOutOfRangeException(nameof(s)); UIntPtr len = new UIntPtr((uint)nb); IntPtr hglobal = Win32Native.LocalAlloc_NoSafeHandle(LMEM_FIXED, len); @@ -1309,7 +1167,6 @@ namespace System.Runtime.InteropServices } } - [System.Security.SecurityCritical] // auto-generated_required public static IntPtr StringToHGlobalAuto(String s) { // Ansi platforms are no longer supported @@ -1322,7 +1179,6 @@ namespace System.Runtime.InteropServices // Converts the CLR exception to an HRESULT. This function also sets // up an IErrorInfo for the exception. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern int GetHRForException(Exception e); @@ -1332,7 +1188,6 @@ namespace System.Runtime.InteropServices // This function is only used in WinRT and converts ObjectDisposedException // to RO_E_CLOSED //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern int GetHRForException_WinRT(Exception e); @@ -1341,7 +1196,6 @@ namespace System.Runtime.InteropServices //==================================================================== // Given a managed object that wraps a UCOMITypeLib, return its name //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [Obsolete("Use System.Runtime.InteropServices.Marshal.GetTypeLibName(ITypeLib pTLB) instead. http://go.microsoft.com/fwlink/?linkid=14202&ID=0000011.", false)] public static String GetTypeLibName(UCOMITypeLib pTLB) { @@ -1352,11 +1206,10 @@ namespace System.Runtime.InteropServices //==================================================================== // Given a managed object that wraps an ITypeLib, return its name //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static String GetTypeLibName(ITypeLib typelib) { if (typelib == null) - throw new ArgumentNullException("typelib"); + throw new ArgumentNullException(nameof(typelib)); Contract.EndContractBlock(); String strTypeLibName = null; @@ -1373,11 +1226,10 @@ namespace System.Runtime.InteropServices // Internal version of GetTypeLibName // Support GUID_ManagedName which aligns with TlbImp //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required internal static String GetTypeLibNameInternal(ITypeLib typelib) { if (typelib == null) - throw new ArgumentNullException("typelib"); + throw new ArgumentNullException(nameof(typelib)); Contract.EndContractBlock(); // Try GUID_ManagedName first @@ -1415,7 +1267,6 @@ namespace System.Runtime.InteropServices //==================================================================== // Given an managed object that wraps an UCOMITypeLib, return its guid //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [Obsolete("Use System.Runtime.InteropServices.Marshal.GetTypeLibGuid(ITypeLib pTLB) instead. http://go.microsoft.com/fwlink/?linkid=14202&ID=0000011.", false)] public static Guid GetTypeLibGuid(UCOMITypeLib pTLB) { @@ -1425,7 +1276,6 @@ namespace System.Runtime.InteropServices //==================================================================== // Given an managed object that wraps an ITypeLib, return its guid //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static Guid GetTypeLibGuid(ITypeLib typelib) { Guid result = new Guid (); @@ -1439,7 +1289,6 @@ namespace System.Runtime.InteropServices //==================================================================== // Given a managed object that wraps a UCOMITypeLib, return its lcid //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [Obsolete("Use System.Runtime.InteropServices.Marshal.GetTypeLibLcid(ITypeLib pTLB) instead. http://go.microsoft.com/fwlink/?linkid=14202&ID=0000011.", false)] public static int GetTypeLibLcid(UCOMITypeLib pTLB) { @@ -1449,7 +1298,6 @@ namespace System.Runtime.InteropServices //==================================================================== // Given a managed object that wraps an ITypeLib, return its lcid //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern int GetTypeLibLcid(ITypeLib typelib); @@ -1463,7 +1311,6 @@ namespace System.Runtime.InteropServices //==================================================================== // Given a managed object that wraps an ITypeInfo, return its guid. //==================================================================== - [System.Security.SecurityCritical] // auto-generated internal static Guid GetTypeInfoGuid(ITypeInfo typeInfo) { Guid result = new Guid (); @@ -1478,16 +1325,15 @@ namespace System.Runtime.InteropServices // Given a assembly, return the TLBID that will be generated for the // typelib exported from the assembly. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static Guid GetTypeLibGuidForAssembly(Assembly asm) { if (asm == null) - throw new ArgumentNullException("asm"); + throw new ArgumentNullException(nameof(asm)); Contract.EndContractBlock(); RuntimeAssembly rtAssembly = asm as RuntimeAssembly; if (rtAssembly == null) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"), "asm"); + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"), nameof(asm)); Guid result = new Guid(); FCallGetTypeLibGuidForAssembly(ref result, rtAssembly); @@ -1504,16 +1350,15 @@ namespace System.Runtime.InteropServices [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void _GetTypeLibVersionForAssembly(RuntimeAssembly inputAssembly, out int majorVersion, out int minorVersion); - [System.Security.SecurityCritical] // auto-generated_required public static void GetTypeLibVersionForAssembly(Assembly inputAssembly, out int majorVersion, out int minorVersion) { if (inputAssembly == null) - throw new ArgumentNullException("inputAssembly"); + throw new ArgumentNullException(nameof(inputAssembly)); Contract.EndContractBlock(); RuntimeAssembly rtAssembly = inputAssembly as RuntimeAssembly; if (rtAssembly == null) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"), "inputAssembly"); + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"), nameof(inputAssembly)); _GetTypeLibVersionForAssembly(rtAssembly, out majorVersion, out minorVersion); } @@ -1521,7 +1366,6 @@ namespace System.Runtime.InteropServices //==================================================================== // Given a managed object that wraps an UCOMITypeInfo, return its name //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [Obsolete("Use System.Runtime.InteropServices.Marshal.GetTypeInfoName(ITypeInfo pTLB) instead. http://go.microsoft.com/fwlink/?linkid=14202&ID=0000011.", false)] public static String GetTypeInfoName(UCOMITypeInfo pTI) { @@ -1531,11 +1375,10 @@ namespace System.Runtime.InteropServices //==================================================================== // Given a managed object that wraps an ITypeInfo, return its name //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static String GetTypeInfoName(ITypeInfo typeInfo) { if (typeInfo == null) - throw new ArgumentNullException("typeInfo"); + throw new ArgumentNullException(nameof(typeInfo)); Contract.EndContractBlock(); String strTypeLibName = null; @@ -1552,11 +1395,10 @@ namespace System.Runtime.InteropServices // Internal version of GetTypeInfoName // Support GUID_ManagedName which aligns with TlbImp //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required internal static String GetTypeInfoNameInternal(ITypeInfo typeInfo, out bool hasManagedName) { if (typeInfo == null) - throw new ArgumentNullException("typeInfo"); + throw new ArgumentNullException(nameof(typeInfo)); Contract.EndContractBlock(); // Try ManagedNameGuid first @@ -1590,7 +1432,6 @@ namespace System.Runtime.InteropServices // Get the corresponding managed name as converted by TlbImp // Used to get the type using GetType() from imported assemblies //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required internal static String GetManagedTypeInfoNameInternal(ITypeLib typeLib, ITypeInfo typeInfo) { bool hasManagedName; @@ -1609,95 +1450,8 @@ namespace System.Runtime.InteropServices [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern Type GetLoadedTypeForGUID(ref Guid guid); -#if !FEATURE_CORECLR // current implementation requires reflection only load - //==================================================================== - // map ITypeInfo* to Type - //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required - public static Type GetTypeForITypeInfo(IntPtr /* ITypeInfo* */ piTypeInfo) - { - ITypeInfo pTI = null; - ITypeLib pTLB = null; - Type TypeObj = null; - Assembly AsmBldr = null; - TypeLibConverter TlbConverter = null; - int Index = 0; - Guid clsid; - - // If the input ITypeInfo is NULL then return NULL. - if (piTypeInfo == IntPtr.Zero) - return null; - - // Wrap the ITypeInfo in a CLR object. - pTI = (ITypeInfo)GetObjectForIUnknown(piTypeInfo); - - // Check to see if a class exists with the specified GUID. - - clsid = GetTypeInfoGuid(pTI); - TypeObj = GetLoadedTypeForGUID(ref clsid); - - // If we managed to find the type based on the GUID then return it. - if (TypeObj != null) - return TypeObj; - - // There is no type with the specified GUID in the app domain so lets - // try and convert the containing typelib. - try - { - pTI.GetContainingTypeLib(out pTLB, out Index); - } - catch(COMException) - { - pTLB = null; - } - - // Check to see if we managed to get a containing typelib. - if (pTLB != null) - { - // Get the assembly name from the typelib. - AssemblyName AsmName = TypeLibConverter.GetAssemblyNameFromTypelib(pTLB, null, null, null, null, AssemblyNameFlags.None); - String AsmNameString = AsmName.FullName; - - // Check to see if the assembly that will contain the type already exists. - Assembly[] aAssemblies = Thread.GetDomain().GetAssemblies(); - int NumAssemblies = aAssemblies.Length; - for (int i = 0; i < NumAssemblies; i++) - { - if (String.Compare(aAssemblies[i].FullName, - AsmNameString,StringComparison.Ordinal) == 0) - AsmBldr = aAssemblies[i]; - } - - // If we haven't imported the assembly yet then import it. - if (AsmBldr == null) - { - TlbConverter = new TypeLibConverter(); - AsmBldr = TlbConverter.ConvertTypeLibToAssembly(pTLB, - GetTypeLibName(pTLB) + ".dll", 0, new ImporterCallback(), null, null, null, null); - } - - // Load the type object from the imported typelib. - // Call GetManagedTypeInfoNameInternal to align with TlbImp behavior - TypeObj = AsmBldr.GetType(GetManagedTypeInfoNameInternal(pTLB, pTI), true, false); - if (TypeObj != null && !TypeObj.IsVisible) - TypeObj = null; - } - else - { - // If the ITypeInfo does not have a containing typelib then simply - // return Object as the type. - TypeObj = typeof(Object); - } - - return TypeObj; - } -#endif // #if !FEATURE_CORECLR - // This method is identical to Type.GetTypeFromCLSID. Since it's interop specific, we expose it // on Marshal for more consistent API surface. -#if !FEATURE_CORECLR - [System.Security.SecuritySafeCritical] -#endif //!FEATURE_CORECLR public static Type GetTypeFromCLSID(Guid clsid) { return RuntimeType.GetTypeFromCLSIDImpl(clsid, null, false); @@ -1706,7 +1460,6 @@ namespace System.Runtime.InteropServices //==================================================================== // map Type to ITypeInfo* //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern IntPtr /* ITypeInfo* */ GetITypeInfoForType(Type t); @@ -1715,13 +1468,11 @@ namespace System.Runtime.InteropServices // is the one where the RCW was first seen. Will return null // otherwise. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static IntPtr /* IUnknown* */ GetIUnknownForObject(Object o) { return GetIUnknownForObjectNative(o, false); } - [System.Security.SecurityCritical] // auto-generated_required public static IntPtr /* IUnknown* */ GetIUnknownForObjectInContext(Object o) { return GetIUnknownForObjectNative(o, true); @@ -1737,22 +1488,22 @@ namespace System.Runtime.InteropServices //==================================================================== [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern IntPtr /* IUnknown* */ GetRawIUnknownForComObjectNoAddRef(Object o); +#endif // FEATURE_COMINTEROP //==================================================================== // return the IDispatch* for an Object //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static IntPtr /* IDispatch */ GetIDispatchForObject(Object o) { - return GetIDispatchForObjectNative(o, false); + throw new PlatformNotSupportedException(); } - + +#if FEATURE_COMINTEROP //==================================================================== // return the IDispatch* for an Object if the current context // is the one where the RCW was first seen. Will return null // otherwise. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static IntPtr /* IUnknown* */ GetIDispatchForObjectInContext(Object o) { return GetIDispatchForObjectNative(o, true); @@ -1765,13 +1516,11 @@ namespace System.Runtime.InteropServices // return the IUnknown* representing the interface for the Object // Object o should support Type T //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static IntPtr /* IUnknown* */ GetComInterfaceForObject(Object o, Type T) { return GetComInterfaceForObjectNative(o, T, false, true); } - [System.Security.SecurityCritical] public static IntPtr GetComInterfaceForObject(T o) { return GetComInterfaceForObject(o, typeof(TInterface)); @@ -1782,7 +1531,6 @@ namespace System.Runtime.InteropServices // Object o should support Type T, it refer the value of mode to // invoke customized QueryInterface or not //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static IntPtr /* IUnknown* */ GetComInterfaceForObject(Object o, Type T, CustomQueryInterfaceMode mode) { bool bEnableCustomizedQueryInterface = ((mode == CustomQueryInterfaceMode.Allow) ? true : false); @@ -1795,7 +1543,6 @@ namespace System.Runtime.InteropServices // is the one where the RCW was first seen. Will return null // otherwise. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static IntPtr /* IUnknown* */ GetComInterfaceForObjectInContext(Object o, Type t) { return GetComInterfaceForObjectNative(o, t, true, true); @@ -1807,7 +1554,6 @@ namespace System.Runtime.InteropServices //==================================================================== // return an Object for IUnknown //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern Object GetObjectForIUnknown(IntPtr /* IUnknown* */ pUnk); @@ -1818,7 +1564,6 @@ namespace System.Runtime.InteropServices // where you want to be able to call ReleaseComObject on a RCW // and not worry about other active uses of said RCW. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern Object GetUniqueObjectForIUnknown(IntPtr unknown); @@ -1828,40 +1573,31 @@ namespace System.Runtime.InteropServices // Type T should be either a COM imported Type or a sub-type of COM // imported Type //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern Object GetTypedObjectForIUnknown(IntPtr /* IUnknown* */ pUnk, Type t); - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern IntPtr CreateAggregatedObject(IntPtr pOuter, Object o); - [System.Security.SecurityCritical] public static IntPtr CreateAggregatedObject(IntPtr pOuter, T o) { return CreateAggregatedObject(pOuter, (object)o); } - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern void CleanupUnusedObjectsInCurrentContext(); - [System.Security.SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern bool AreComObjectsAvailableForCleanup(); //==================================================================== // check if the object is classic COM component //==================================================================== -#if !FEATURE_CORECLR // with FEATURE_CORECLR, the whole type is SecurityCritical - [System.Security.SecuritySafeCritical] -#endif [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern bool IsComObject(Object o); #endif // FEATURE_COMINTEROP - [System.Security.SecurityCritical] // auto-generated_required public static IntPtr AllocCoTaskMem(int cb) { IntPtr pNewMem = Win32Native.CoTaskMemAlloc(new UIntPtr((uint)cb)); @@ -1872,7 +1608,6 @@ namespace System.Runtime.InteropServices return pNewMem; } - [System.Security.SecurityCritical] // auto-generated_required unsafe public static IntPtr StringToCoTaskMemUni(String s) { if (s == null) @@ -1885,7 +1620,7 @@ namespace System.Runtime.InteropServices // Overflow checking if (nb < s.Length) - throw new ArgumentOutOfRangeException("s"); + throw new ArgumentOutOfRangeException(nameof(s)); IntPtr hglobal = Win32Native.CoTaskMemAlloc(new UIntPtr((uint)nb)); @@ -1904,7 +1639,6 @@ namespace System.Runtime.InteropServices } } - [System.Security.SecurityCritical] // auto-generated_required unsafe public static IntPtr StringToCoTaskMemUTF8(String s) { const int MAX_UTF8_CHAR_SIZE = 3; @@ -1918,7 +1652,7 @@ namespace System.Runtime.InteropServices // Overflow checking if (nb < s.Length) - throw new ArgumentOutOfRangeException("s"); + throw new ArgumentOutOfRangeException(nameof(s)); IntPtr pMem = Win32Native.CoTaskMemAlloc(new UIntPtr((uint)nb +1)); @@ -1936,14 +1670,12 @@ namespace System.Runtime.InteropServices } } - [System.Security.SecurityCritical] // auto-generated_required public static IntPtr StringToCoTaskMemAuto(String s) { // Ansi platforms are no longer supported return StringToCoTaskMemUni(s); } - [System.Security.SecurityCritical] // auto-generated_required unsafe public static IntPtr StringToCoTaskMemAnsi(String s) { if (s == null) @@ -1956,7 +1688,7 @@ namespace System.Runtime.InteropServices // Overflow checking if (nb < s.Length) - throw new ArgumentOutOfRangeException("s"); + throw new ArgumentOutOfRangeException(nameof(s)); IntPtr hglobal = Win32Native.CoTaskMemAlloc(new UIntPtr((uint)nb)); @@ -1972,7 +1704,6 @@ namespace System.Runtime.InteropServices } } - [System.Security.SecurityCritical] // auto-generated_required public static void FreeCoTaskMem(IntPtr ptr) { if (IsNotWin32Atom(ptr)) { @@ -1980,7 +1711,6 @@ namespace System.Runtime.InteropServices } } - [System.Security.SecurityCritical] // auto-generated_required public static IntPtr ReAllocCoTaskMem(IntPtr pv, int cb) { IntPtr pNewMem = Win32Native.CoTaskMemRealloc(pv, new UIntPtr((uint)cb)); @@ -1994,7 +1724,6 @@ namespace System.Runtime.InteropServices //==================================================================== // BSTR allocation and dealocation. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static void FreeBSTR(IntPtr ptr) { if (IsNotWin32Atom(ptr)) @@ -2003,7 +1732,6 @@ namespace System.Runtime.InteropServices } } - [System.Security.SecurityCritical] // auto-generated_required public static IntPtr StringToBSTR(String s) { if (s == null) @@ -2011,7 +1739,7 @@ namespace System.Runtime.InteropServices // Overflow checking if (s.Length + 1 < s.Length) - throw new ArgumentOutOfRangeException("s"); + throw new ArgumentOutOfRangeException(nameof(s)); IntPtr bstr = Win32Native.SysAllocStringLen(s, s.Length); if (bstr == IntPtr.Zero) @@ -2020,7 +1748,6 @@ namespace System.Runtime.InteropServices return bstr; } - [System.Security.SecurityCritical] // auto-generated_required public static String PtrToStringBSTR(IntPtr ptr) { return PtrToStringUni(ptr, (int)Win32Native.SysStringLen(ptr)); @@ -2031,7 +1758,6 @@ namespace System.Runtime.InteropServices // release the COM component and if the reference hits 0 zombie this object // further usage of this Object might throw an exception //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static int ReleaseComObject(Object o) { __ComObject co = null; @@ -2043,7 +1769,7 @@ namespace System.Runtime.InteropServices } catch (InvalidCastException) { - throw new ArgumentException(Environment.GetResourceString("Argument_ObjNotComObject"), "o"); + throw new ArgumentException(Environment.GetResourceString("Argument_ObjNotComObject"), nameof(o)); } return co.ReleaseSelf(); @@ -2057,11 +1783,10 @@ namespace System.Runtime.InteropServices // release the COM component and zombie this object // further usage of this Object might throw an exception //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static Int32 FinalReleaseComObject(Object o) { if (o == null) - throw new ArgumentNullException("o"); + throw new ArgumentNullException(nameof(o)); Contract.EndContractBlock(); __ComObject co = null; @@ -2073,7 +1798,7 @@ namespace System.Runtime.InteropServices } catch (InvalidCastException) { - throw new ArgumentException(Environment.GetResourceString("Argument_ObjNotComObject"), "o"); + throw new ArgumentException(Environment.GetResourceString("Argument_ObjNotComObject"), nameof(o)); } co.FinalReleaseSelf(); @@ -2083,39 +1808,14 @@ namespace System.Runtime.InteropServices [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void InternalFinalReleaseComObject(Object o); +#endif // FEATURE_COMINTEROP //==================================================================== // This method retrieves data from the COM object. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static Object GetComObjectData(Object obj, Object key) { - // Validate that the arguments aren't null. - if (obj == null) - throw new ArgumentNullException("obj"); - if (key == null) - throw new ArgumentNullException("key"); - Contract.EndContractBlock(); - - __ComObject comObj = null; - - // Make sure the obj is an __ComObject. - try - { - comObj = (__ComObject)obj; - } - catch (InvalidCastException) - { - throw new ArgumentException(Environment.GetResourceString("Argument_ObjNotComObject"), "obj"); - } - - if (obj.GetType().IsWindowsRuntimeObject) - { - throw new ArgumentException(Environment.GetResourceString("Argument_ObjIsWinRTObject"), "obj"); - } - - // Retrieve the data from the __ComObject. - return comObj.GetData(key); + throw new PlatformNotSupportedException(); } //==================================================================== @@ -2124,55 +1824,29 @@ namespace System.Runtime.InteropServices // true if the data has been added, false if the data could not be // added because there already was data for the specified key. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static bool SetComObjectData(Object obj, Object key, Object data) { - // Validate that the arguments aren't null. The data can validly be null. - if (obj == null) - throw new ArgumentNullException("obj"); - if (key == null) - throw new ArgumentNullException("key"); - Contract.EndContractBlock(); - - __ComObject comObj = null; - - // Make sure the obj is an __ComObject. - try - { - comObj = (__ComObject)obj; - } - catch (InvalidCastException) - { - throw new ArgumentException(Environment.GetResourceString("Argument_ObjNotComObject"), "obj"); - } - - if (obj.GetType().IsWindowsRuntimeObject) - { - throw new ArgumentException(Environment.GetResourceString("Argument_ObjIsWinRTObject"), "obj"); - } - - // Retrieve the data from the __ComObject. - return comObj.SetData(key, data); + throw new PlatformNotSupportedException(); } +#if FEATURE_COMINTEROP //==================================================================== // This method takes the given COM object and wraps it in an object // of the specified type. The type must be derived from __ComObject. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static Object CreateWrapperOfType(Object o, Type t) { // Validate the arguments. if (t == null) - throw new ArgumentNullException("t"); + throw new ArgumentNullException(nameof(t)); if (!t.IsCOMObject) - throw new ArgumentException(Environment.GetResourceString("Argument_TypeNotComObject"), "t"); + throw new ArgumentException(Environment.GetResourceString("Argument_TypeNotComObject"), nameof(t)); if (t.IsGenericType) - throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "t"); + throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), nameof(t)); Contract.EndContractBlock(); if (t.IsWindowsRuntimeObject) - throw new ArgumentException(Environment.GetResourceString("Argument_TypeIsWinRTType"), "t"); + throw new ArgumentException(Environment.GetResourceString("Argument_TypeIsWinRTType"), nameof(t)); // Check for the null case. if (o == null) @@ -2180,9 +1854,9 @@ namespace System.Runtime.InteropServices // Make sure the object is a COM object. if (!o.GetType().IsCOMObject) - throw new ArgumentException(Environment.GetResourceString("Argument_ObjNotComObject"), "o"); + throw new ArgumentException(Environment.GetResourceString("Argument_ObjNotComObject"), nameof(o)); if (o.GetType().IsWindowsRuntimeObject) - throw new ArgumentException(Environment.GetResourceString("Argument_ObjIsWinRTObject"), "o"); + throw new ArgumentException(Environment.GetResourceString("Argument_ObjIsWinRTObject"), nameof(o)); // Check to see if the type of the object is the requested type. if (o.GetType() == t) @@ -2206,7 +1880,6 @@ namespace System.Runtime.InteropServices return Wrapper; } - [System.Security.SecurityCritical] public static TWrapper CreateWrapperOfType(T o) { return (TWrapper)CreateWrapperOfType(o, typeof(TWrapper)); @@ -2215,7 +1888,6 @@ namespace System.Runtime.InteropServices //==================================================================== // Helper method called from CreateWrapperOfType. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern Object InternalCreateWrapperOfType(Object o, Type t); @@ -2223,7 +1895,6 @@ namespace System.Runtime.InteropServices // There may be a thread-based cache of COM components. This service can // force the aggressive release of the current thread's cache. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [Obsolete("This API did not perform any operation and will be removed in future versions of the CLR.", false)] public static void ReleaseThreadCache() { @@ -2232,50 +1903,40 @@ namespace System.Runtime.InteropServices //==================================================================== // check if the type is visible from COM. //==================================================================== - [System.Security.SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern bool IsTypeVisibleFromCom(Type t); //==================================================================== // IUnknown Helpers //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern int /* HRESULT */ QueryInterface(IntPtr /* IUnknown */ pUnk, ref Guid iid, out IntPtr ppv); - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern int /* ULONG */ AddRef(IntPtr /* IUnknown */ pUnk ); - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static extern int /* ULONG */ Release(IntPtr /* IUnknown */ pUnk ); - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern void GetNativeVariantForObject(Object obj, /* VARIANT * */ IntPtr pDstNativeVariant); - [System.Security.SecurityCritical] public static void GetNativeVariantForObject(T obj, IntPtr pDstNativeVariant) { GetNativeVariantForObject((object)obj, pDstNativeVariant); } - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern Object GetObjectForNativeVariant(/* VARIANT * */ IntPtr pSrcNativeVariant ); - [System.Security.SecurityCritical] public static T GetObjectForNativeVariant(IntPtr pSrcNativeVariant) { return (T)GetObjectForNativeVariant(pSrcNativeVariant); } - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern Object[] GetObjectsForNativeVariants(/* VARIANT * */ IntPtr aSrcNativeVariant, int cVars ); - [System.Security.SecurityCritical] public static T[] GetObjectsForNativeVariants(IntPtr aSrcNativeVariant, int cVars) { object[] objects = GetObjectsForNativeVariants(aSrcNativeVariant, cVars); @@ -2294,14 +1955,12 @@ namespace System.Runtime.InteropServices /// Returns the first valid COM slot that GetMethodInfoForSlot will work on /// This will be 3 for IUnknown based interfaces and 7 for IDispatch based interfaces. /// - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern int GetStartComSlot(Type t); /// /// Returns the last valid COM slot that GetMethodInfoForSlot will work on. /// - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern int GetEndComSlot(Type t); @@ -2312,7 +1971,6 @@ namespace System.Runtime.InteropServices /// For classes, the lookup is done on the default interface that will be /// exposed for the class. /// - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern MemberInfo GetMethodInfoForComSlot(Type t, int slot, ref ComMemberType memberType); @@ -2320,19 +1978,18 @@ namespace System.Runtime.InteropServices /// Returns the COM slot for a memeber info, taking into account whether /// the exposed interface is IUnknown based or IDispatch based /// - [System.Security.SecurityCritical] // auto-generated_required public static int GetComSlotForMethodInfo(MemberInfo m) { if (m== null) - throw new ArgumentNullException("m"); + throw new ArgumentNullException(nameof(m)); if (!(m is RuntimeMethodInfo)) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "m"); + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), nameof(m)); if (!m.DeclaringType.IsInterface) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeInterfaceMethod"), "m"); + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeInterfaceMethod"), nameof(m)); if (m.DeclaringType.IsGenericType) - throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "m"); + throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), nameof(m)); Contract.EndContractBlock(); return InternalGetComSlotForMethodInfo((IRuntimeMethodInfo)m); @@ -2340,6 +1997,7 @@ namespace System.Runtime.InteropServices [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern int InternalGetComSlotForMethodInfo(IRuntimeMethodInfo m); +#endif // FEATURE_COMINTEROP //==================================================================== // This method generates a GUID for the specified type. If the type @@ -2347,38 +2005,27 @@ namespace System.Runtime.InteropServices // guid GUID is generated based on the fully qualified name of the // type. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static Guid GenerateGuidForType(Type type) { - Guid result = new Guid (); - FCallGenerateGuidForType (ref result, type); - return result; + return type.GUID; } - // The full assembly name is used to compute the GUID, so this should be SxS-safe - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern void FCallGenerateGuidForType(ref Guid result, Type type); - //==================================================================== // This method generates a PROGID for the specified type. If the type // has a PROGID in the metadata then it is returned otherwise a stable // PROGID is generated based on the fully qualified name of the // type. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static String GenerateProgIdForType(Type type) { if (type == null) - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); if (type.IsImport) - throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustNotBeComImport"), "type"); + throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustNotBeComImport"), nameof(type)); if (type.IsGenericType) - throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "type"); + throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), nameof(type)); Contract.EndContractBlock(); - if (!RegistrationServices.TypeRequiresRegistrationHelper(type)) - throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustBeComCreatable"), "type"); - IList cas = CustomAttributeData.GetCustomAttributes(type); for (int i = 0; i < cas.Count; i ++) { @@ -2386,10 +2033,10 @@ namespace System.Runtime.InteropServices { // Retrieve the PROGID string from the ProgIdAttribute. IList caConstructorArgs = cas[i].ConstructorArguments; - Contract.Assert(caConstructorArgs.Count == 1, "caConstructorArgs.Count == 1"); + Debug.Assert(caConstructorArgs.Count == 1, "caConstructorArgs.Count == 1"); CustomAttributeTypedArgument progIdConstructorArg = caConstructorArgs[0]; - Contract.Assert(progIdConstructorArg.ArgumentType == typeof(String), "progIdConstructorArg.ArgumentType == typeof(String)"); + Debug.Assert(progIdConstructorArg.ArgumentType == typeof(String), "progIdConstructorArg.ArgumentType == typeof(String)"); String strProgId = (String)progIdConstructorArg.Value; @@ -2404,10 +2051,10 @@ namespace System.Runtime.InteropServices return type.FullName; } +#if FEATURE_COMINTEROP //==================================================================== // This method binds to the specified moniker. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static Object BindToMoniker(String monikerName) { Object obj = null; @@ -2425,7 +2072,6 @@ namespace System.Runtime.InteropServices //==================================================================== // This method gets the currently running object. //==================================================================== - [System.Security.SecurityCritical] // auto-generated_required public static Object GetActiveObject(String progID) { Object obj = null; @@ -2449,32 +2095,26 @@ namespace System.Runtime.InteropServices [DllImport(Microsoft.Win32.Win32Native.OLE32, PreserveSig = false)] [SuppressUnmanagedCodeSecurity] - [System.Security.SecurityCritical] // auto-generated private static extern void CLSIDFromProgIDEx([MarshalAs(UnmanagedType.LPWStr)] String progId, out Guid clsid); [DllImport(Microsoft.Win32.Win32Native.OLE32, PreserveSig = false)] [SuppressUnmanagedCodeSecurity] - [System.Security.SecurityCritical] // auto-generated private static extern void CLSIDFromProgID([MarshalAs(UnmanagedType.LPWStr)] String progId, out Guid clsid); [DllImport(Microsoft.Win32.Win32Native.OLE32, PreserveSig = false)] [SuppressUnmanagedCodeSecurity] - [System.Security.SecurityCritical] // auto-generated private static extern void CreateBindCtx(UInt32 reserved, out IBindCtx ppbc); [DllImport(Microsoft.Win32.Win32Native.OLE32, PreserveSig = false)] [SuppressUnmanagedCodeSecurity] - [System.Security.SecurityCritical] // auto-generated private static extern void MkParseDisplayName(IBindCtx pbc, [MarshalAs(UnmanagedType.LPWStr)] String szUserName, out UInt32 pchEaten, out IMoniker ppmk); [DllImport(Microsoft.Win32.Win32Native.OLE32, PreserveSig = false)] [SuppressUnmanagedCodeSecurity] - [System.Security.SecurityCritical] // auto-generated private static extern void BindMoniker(IMoniker pmk, UInt32 grfOpt, ref Guid iidResult, [MarshalAs(UnmanagedType.Interface)] out Object ppvResult); [DllImport(Microsoft.Win32.Win32Native.OLEAUT32, PreserveSig = false)] [SuppressUnmanagedCodeSecurity] - [System.Security.SecurityCritical] // auto-generated private static extern void GetActiveObject(ref Guid rclsid, IntPtr reserved, [MarshalAs(UnmanagedType.Interface)] out Object ppunk); //======================================================================== @@ -2489,7 +2129,6 @@ namespace System.Runtime.InteropServices //======================================================================== // Private method called from EE upon use of license/ICF2 marshaling. //======================================================================== - [SecurityCritical] private static IntPtr LoadLicenseManager() { Assembly sys = Assembly.Load("System, Version="+ ThisAssembly.Version + @@ -2500,16 +2139,13 @@ namespace System.Runtime.InteropServices return t.TypeHandle.Value; } - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern void ChangeWrapperHandleStrength(Object otp, bool fIsWeak); - [System.Security.SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void InitializeWrapperForWinRT(object o, ref IntPtr pUnk); #if FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION - [System.Security.SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void InitializeManagedWinRTFactoryObject(object o, RuntimeType runtimeClassType); #endif @@ -2517,7 +2153,6 @@ namespace System.Runtime.InteropServices //======================================================================== // Create activation factory and wraps it with a unique RCW //======================================================================== - [System.Security.SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern object GetNativeActivationFactory(Type type); @@ -2525,11 +2160,9 @@ namespace System.Runtime.InteropServices // Methods allowing retrieval of the IIDs exposed by an underlying WinRT // object, as specified by the object's IInspectable::GetIids() //======================================================================== - [System.Security.SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] private static extern void _GetInspectableIids(ObjectHandleOnStack obj, ObjectHandleOnStack guids); - [System.Security.SecurityCritical] internal static System.Guid[] GetInspectableIids(object obj) { System.Guid[] result = null; @@ -2547,14 +2180,12 @@ namespace System.Runtime.InteropServices // Methods allowing retrieval of the cached WinRT type corresponding to // the specified GUID //======================================================================== - [System.Security.SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] private static extern void _GetCachedWinRTTypeByIid( ObjectHandleOnStack appDomainObj, System.Guid iid, out IntPtr rthHandle); - [System.Security.SecurityCritical] internal static System.Type GetCachedWinRTTypeByIid( System.AppDomain ad, System.Guid iid) @@ -2572,14 +2203,12 @@ namespace System.Runtime.InteropServices // Methods allowing retrieval of the WinRT types cached in the specified // app domain //======================================================================== - [System.Security.SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] private static extern void _GetCachedWinRTTypes( ObjectHandleOnStack appDomainObj, ref int epoch, ObjectHandleOnStack winrtTypes); - [System.Security.SecurityCritical] internal static System.Type[] GetCachedWinRTTypes( System.AppDomain ad, ref int epoch) @@ -2599,7 +2228,6 @@ namespace System.Runtime.InteropServices return result; } - [System.Security.SecurityCritical] internal static System.Type[] GetCachedWinRTTypes( System.AppDomain ad) { @@ -2610,31 +2238,29 @@ namespace System.Runtime.InteropServices #endif // FEATURE_COMINTEROP - [System.Security.SecurityCritical] // auto-generated_required public static Delegate GetDelegateForFunctionPointer(IntPtr ptr, Type t) { // Validate the parameters if (ptr == IntPtr.Zero) - throw new ArgumentNullException("ptr"); + throw new ArgumentNullException(nameof(ptr)); if (t == null) - throw new ArgumentNullException("t"); + throw new ArgumentNullException(nameof(t)); Contract.EndContractBlock(); if ((t as RuntimeType) == null) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "t"); + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), nameof(t)); if (t.IsGenericType) - throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "t"); + throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), nameof(t)); Type c = t.BaseType; if (c == null || (c != typeof(Delegate) && c != typeof(MulticastDelegate))) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "t"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), nameof(t)); return GetDelegateForFunctionPointerInternal(ptr, t); } - [System.Security.SecurityCritical] public static TDelegate GetDelegateForFunctionPointer(IntPtr ptr) { return (TDelegate)(object)GetDelegateForFunctionPointer(ptr, typeof(TDelegate)); @@ -2643,17 +2269,15 @@ namespace System.Runtime.InteropServices [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern Delegate GetDelegateForFunctionPointerInternal(IntPtr ptr, Type t); - [System.Security.SecurityCritical] // auto-generated_required public static IntPtr GetFunctionPointerForDelegate(Delegate d) { if (d == null) - throw new ArgumentNullException("d"); + throw new ArgumentNullException(nameof(d)); Contract.EndContractBlock(); return GetFunctionPointerForDelegateInternal(d); } - [System.Security.SecurityCritical] public static IntPtr GetFunctionPointerForDelegate(TDelegate d) { return GetFunctionPointerForDelegate((Delegate)(object)d); @@ -2662,47 +2286,39 @@ namespace System.Runtime.InteropServices [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern IntPtr GetFunctionPointerForDelegateInternal(Delegate d); -#if FEATURE_LEGACYSURFACE - -#if FEATURE_COMINTEROP - [System.Security.SecurityCritical] // auto-generated_required public static IntPtr SecureStringToBSTR(SecureString s) { if( s == null) { - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); } Contract.EndContractBlock(); - return s.ToBSTR(); - } +#if FEATURE_COMINTEROP + return s.MarshalToBSTR(); +#else + throw new PlatformNotSupportedException(); #endif + } - [System.Security.SecurityCritical] // auto-generated_required public static IntPtr SecureStringToCoTaskMemAnsi(SecureString s) { if( s == null) { - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); } Contract.EndContractBlock(); - return s.ToAnsiStr(false); + return s.MarshalToString(globalAlloc: false, unicode: false); } - [System.Security.SecurityCritical] // auto-generated_required public static IntPtr SecureStringToCoTaskMemUnicode(SecureString s) { - if (s == null) - { - throw new ArgumentNullException("s"); + if( s == null) { + throw new ArgumentNullException(nameof(s)); } Contract.EndContractBlock(); - return s.ToUniStr(false); + return s.MarshalToString(globalAlloc: false, unicode: true); } -#endif // FEATURE_LEGACYSURFACE - - #if FEATURE_COMINTEROP - [System.Security.SecurityCritical] // auto-generated_required public static void ZeroFreeBSTR(IntPtr s) { Win32Native.ZeroMemory(s, (UIntPtr)(Win32Native.SysStringLen(s) * 2)); @@ -2710,97 +2326,51 @@ namespace System.Runtime.InteropServices } #endif - [System.Security.SecurityCritical] // auto-generated_required public static void ZeroFreeCoTaskMemAnsi(IntPtr s) { Win32Native.ZeroMemory(s, (UIntPtr)(Win32Native.lstrlenA(s))); FreeCoTaskMem(s); } - [System.Security.SecurityCritical] // auto-generated_required public static void ZeroFreeCoTaskMemUnicode(IntPtr s) { Win32Native.ZeroMemory(s, (UIntPtr)(Win32Native.lstrlenW(s) * 2)); FreeCoTaskMem(s); } - [System.Security.SecurityCritical] // auto-generated_required unsafe public static void ZeroFreeCoTaskMemUTF8(IntPtr s) { Win32Native.ZeroMemory(s, (UIntPtr)System.StubHelpers.StubHelpers.strlen((sbyte*)s)); FreeCoTaskMem(s); } -#if FEATURE_LEGACYSURFACE - [System.Security.SecurityCritical] // auto-generated_required public static IntPtr SecureStringToGlobalAllocAnsi(SecureString s) { if( s == null) { - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); } Contract.EndContractBlock(); - return s.ToAnsiStr(true); + return s.MarshalToString(globalAlloc: true, unicode: false); } - [System.Security.SecurityCritical] // auto-generated_required public static IntPtr SecureStringToGlobalAllocUnicode(SecureString s) { if( s == null) { - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); } Contract.EndContractBlock(); - return s.ToUniStr(true); + return s.MarshalToString(globalAlloc: true, unicode: true);; } -#endif // FEATURE_LEGACYSURFACE - [System.Security.SecurityCritical] // auto-generated_required public static void ZeroFreeGlobalAllocAnsi(IntPtr s) { Win32Native.ZeroMemory(s, (UIntPtr)(Win32Native.lstrlenA(s))); FreeHGlobal(s); } - [System.Security.SecurityCritical] // auto-generated_required public static void ZeroFreeGlobalAllocUnicode(IntPtr s) { Win32Native.ZeroMemory(s, (UIntPtr)(Win32Native.lstrlenW(s) * 2)); FreeHGlobal(s); } } - -#if FEATURE_COMINTEROP && !FEATURE_CORECLR // current implementation requires reflection only load - //======================================================================== - // Typelib importer callback implementation. - //======================================================================== - internal class ImporterCallback : ITypeLibImporterNotifySink - { - public void ReportEvent(ImporterEventKind EventKind, int EventCode, String EventMsg) - { - } - - [System.Security.SecuritySafeCritical] // overrides transparent public member - public Assembly ResolveRef(Object TypeLib) - { - try - { - // Create the TypeLibConverter. - ITypeLibConverter TLBConv = new TypeLibConverter(); - - // Convert the typelib. - return TLBConv.ConvertTypeLibToAssembly(TypeLib, - Marshal.GetTypeLibName((ITypeLib)TypeLib) + ".dll", - 0, - new ImporterCallback(), - null, - null, - null, - null); - } - catch(Exception) -// catch - { - return null; - } - } - } -#endif // FEATURE_COMINTEROP && !FEATURE_CORECLR } diff --git a/src/mscorlib/src/System/Runtime/InteropServices/NativeBuffer.cs b/src/mscorlib/src/System/Runtime/InteropServices/NativeBuffer.cs deleted file mode 100644 index 9426162..0000000 --- a/src/mscorlib/src/System/Runtime/InteropServices/NativeBuffer.cs +++ /dev/null @@ -1,175 +0,0 @@ -// 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.Runtime.CompilerServices; - -namespace System.Runtime.InteropServices -{ - /// - /// Wrapper for access to the native heap. Dispose to free the memory. Try to use with using statements. - /// Does not allocate zero size buffers, and will free the existing native buffer if capacity is dropped to zero. - /// - /// - /// Suggested use through P/Invoke: define DllImport arguments that take a byte buffer as SafeHandle. - /// - /// Using SafeHandle will ensure that the buffer will not get collected during a P/Invoke. - /// (Notably AddRef and ReleaseRef will be called by the interop layer.) - /// - /// This class is not threadsafe, changing the capacity or disposing on multiple threads risks duplicate heap - /// handles or worse. - /// - internal class NativeBuffer : IDisposable - { - [System.Security.SecurityCritical] - private readonly static SafeHandle s_emptyHandle; - [System.Security.SecurityCritical] - private SafeHeapHandle _handle; - private ulong _capacity; - - [System.Security.SecuritySafeCritical] - static NativeBuffer() - { - s_emptyHandle = new EmptySafeHandle(); - } - - /// - /// Create a buffer with at least the specified initial capacity in bytes. - /// - public NativeBuffer(ulong initialMinCapacity = 0) - { - EnsureByteCapacity(initialMinCapacity); - } - - protected unsafe void* VoidPointer - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [System.Security.SecurityCritical] - get - { - return _handle == null ? null : _handle.DangerousGetHandle().ToPointer(); - } - } - - protected unsafe byte* BytePointer - { - [System.Security.SecurityCritical] - get - { - return (byte*)VoidPointer; - } - } - - /// - /// Get the handle for the buffer. - /// - [System.Security.SecuritySafeCritical] - public SafeHandle GetHandle() - { - // Marshalling code will throw on null for SafeHandle - return _handle ?? s_emptyHandle; - } - - /// - /// The capacity of the buffer in bytes. - /// - public ulong ByteCapacity - { - get { return _capacity; } - } - - /// - /// Ensure capacity in bytes is at least the given minimum. - /// - /// Thrown if unable to allocate memory when setting. - /// Thrown if attempting to set to a value that is larger than the maximum addressable memory. - [System.Security.SecuritySafeCritical] - public void EnsureByteCapacity(ulong minCapacity) - { - if (_capacity < minCapacity) - { - Resize(minCapacity); - _capacity = minCapacity; - } - } - - public unsafe byte this[ulong index] - { - [System.Security.SecuritySafeCritical] - get - { - if (index >= _capacity) throw new ArgumentOutOfRangeException(); - return BytePointer[index]; - } - [System.Security.SecuritySafeCritical] - set - { - if (index >= _capacity) throw new ArgumentOutOfRangeException(); - BytePointer[index] = value; - } - } - - [System.Security.SecuritySafeCritical] - private unsafe void Resize(ulong byteLength) - { - if (byteLength == 0) - { - ReleaseHandle(); - return; - } - - if (_handle == null) - { - _handle = new SafeHeapHandle(byteLength); - } - else - { - _handle.Resize(byteLength); - } - } - - [System.Security.SecuritySafeCritical] - private void ReleaseHandle() - { - if (_handle != null) - { - _capacity = 0; - _handle = null; - } - } - - /// - /// Release the backing buffer - /// - [System.Security.SecuritySafeCritical] - public virtual void Free() - { - ReleaseHandle(); - } - - [System.Security.SecuritySafeCritical] - public void Dispose() - { - Free(); - } - - [System.Security.SecurityCritical] - private sealed class EmptySafeHandle : SafeHandle - { - public EmptySafeHandle() : base(IntPtr.Zero, true) { } - - public override bool IsInvalid - { - [System.Security.SecurityCritical] - get - { return true; } - } - - [System.Security.SecurityCritical] - protected override bool ReleaseHandle() - { - return true; - } - } - } -} \ No newline at end of file diff --git a/src/mscorlib/src/System/Runtime/InteropServices/NativeMethods.cs b/src/mscorlib/src/System/Runtime/InteropServices/NativeMethods.cs index 82cd4fa..650ea65 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/NativeMethods.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/NativeMethods.cs @@ -31,13 +31,10 @@ namespace System.Runtime.InteropServices { ] internal interface IDispatch { - [System.Security.SecurityCritical] void GetTypeInfoCount(out uint pctinfo); - [System.Security.SecurityCritical] void GetTypeInfo(uint iTInfo, int lcid, out IntPtr info); - [System.Security.SecurityCritical] void GetIDsOfNames( ref Guid iid, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 2)] @@ -48,7 +45,6 @@ namespace System.Runtime.InteropServices { [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I4, SizeParamIndex = 2)] int[] rgDispId); - [System.Security.SecurityCritical] void Invoke( int dispIdMember, ref Guid riid, diff --git a/src/mscorlib/src/System/Runtime/InteropServices/NonPortable.cs b/src/mscorlib/src/System/Runtime/InteropServices/NonPortable.cs index 408f56c..0c8ae76 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/NonPortable.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/NonPortable.cs @@ -33,6 +33,18 @@ namespace System.Runtime.InteropServices } [System.Security.SecurityCriticalAttribute] + public static Object BindToMoniker(String monikerName) + { + throw new PlatformNotSupportedException(); + } + + [System.Security.SecurityCriticalAttribute] + public static void CleanupUnusedObjectsInCurrentContext() + { + return; + } + + [System.Security.SecurityCriticalAttribute] public static System.IntPtr CreateAggregatedObject(System.IntPtr pOuter, T o) { throw new PlatformNotSupportedException(); @@ -51,6 +63,12 @@ namespace System.Runtime.InteropServices } [System.Security.SecurityCriticalAttribute] + public static void ChangeWrapperHandleStrength(Object otp, bool fIsWeak) + { + throw new PlatformNotSupportedException(); + } + + [System.Security.SecurityCriticalAttribute] public static int FinalReleaseComObject(object o) { throw new PlatformNotSupportedException(); @@ -75,6 +93,16 @@ namespace System.Runtime.InteropServices } [System.Security.SecurityCriticalAttribute] + public static System.IntPtr GetHINSTANCE(System.Reflection.Module m) + { + if (m == null) + { + throw new ArgumentNullException(nameof(m)); + } + return (System.IntPtr) (-1); + } + + [System.Security.SecurityCriticalAttribute] public static System.IntPtr GetIUnknownForObject(object o) { throw new PlatformNotSupportedException(); @@ -93,6 +121,12 @@ namespace System.Runtime.InteropServices } [System.Security.SecurityCriticalAttribute] + public static Object GetTypedObjectForIUnknown(System.IntPtr pUnk, System.Type t) + { + throw new PlatformNotSupportedException(); + } + + [System.Security.SecurityCriticalAttribute] public static object GetObjectForIUnknown(System.IntPtr pUnk) { throw new PlatformNotSupportedException(); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/RegistrationServices.cs b/src/mscorlib/src/System/Runtime/InteropServices/RegistrationServices.cs index 7d3670d..0105866 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/RegistrationServices.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/RegistrationServices.cs @@ -29,6 +29,7 @@ namespace System.Runtime.InteropServices { using System.Runtime.CompilerServices; using System.Globalization; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; [Flags] @@ -91,12 +92,11 @@ namespace System.Runtime.InteropServices { #region IRegistrationServices - [System.Security.SecurityCritical] // auto-generated_required public virtual bool RegisterAssembly(Assembly assembly, AssemblyRegistrationFlags flags) { // Validate the arguments. if (assembly == null) - throw new ArgumentNullException("assembly"); + throw new ArgumentNullException(nameof(assembly)); if (assembly.ReflectionOnly) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsmLoadedForReflectionOnly")); @@ -154,12 +154,11 @@ namespace System.Runtime.InteropServices { return false; } - [System.Security.SecurityCritical] // auto-generated_required public virtual bool UnregisterAssembly(Assembly assembly) { // Validate the arguments. if (assembly == null) - throw new ArgumentNullException("assembly"); + throw new ArgumentNullException(nameof(assembly)); if (assembly.ReflectionOnly) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsmLoadedForReflectionOnly")); @@ -214,16 +213,15 @@ namespace System.Runtime.InteropServices { return false; } - [System.Security.SecurityCritical] // auto-generated_required public virtual Type[] GetRegistrableTypesInAssembly(Assembly assembly) { // Validate the arguments. if (assembly == null) - throw new ArgumentNullException("assembly"); + throw new ArgumentNullException(nameof(assembly)); Contract.EndContractBlock(); if (!(assembly is RuntimeAssembly)) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"), "assembly"); + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"), nameof(assembly)); // Retrieve the list of types in the assembly. Type[] aTypes = assembly.GetExportedTypes(); @@ -246,23 +244,21 @@ namespace System.Runtime.InteropServices { return RetArray; } - [System.Security.SecurityCritical] // auto-generated_required public virtual String GetProgIdForType(Type type) { return Marshal.GenerateProgIdForType(type); } - [System.Security.SecurityCritical] // auto-generated_required public virtual void RegisterTypeForComClients(Type type, ref Guid g) { #if FEATURE_COMINTEROP_MANAGED_ACTIVATION if(type == null) - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); Contract.EndContractBlock(); if((type as RuntimeType) == null) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"),"type"); + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"),nameof(type)); if(!TypeRequiresRegistration(type)) - throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustBeComCreatable"),"type"); + throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustBeComCreatable"),nameof(type)); // Call the native method to do CoRegisterClassObject RegisterTypeForComClientsNative(type, ref g); @@ -276,13 +272,11 @@ namespace System.Runtime.InteropServices { return s_ManagedCategoryGuid; } - [System.Security.SecurityCritical] // auto-generated_required public virtual bool TypeRequiresRegistration(Type type) { return TypeRequiresRegistrationHelper(type); } - [System.Security.SecuritySafeCritical] // auto-generated public virtual bool TypeRepresentsComType(Type type) { // If the type is not a COM import, then it does not represent a COM type. @@ -296,7 +290,7 @@ namespace System.Runtime.InteropServices { // If the type is derived from a tdImport class and has the same GUID as the // imported class, then it represents a COM type. Type baseComImportType = GetBaseComImportType(type); - Contract.Assert(baseComImportType != null, "baseComImportType != null"); + Debug.Assert(baseComImportType != null, "baseComImportType != null"); if (Marshal.GenerateGuidForType(type) == Marshal.GenerateGuidForType(baseComImportType)) return true; @@ -307,18 +301,17 @@ namespace System.Runtime.InteropServices { #region Public methods not on IRegistrationServices - [System.Security.SecurityCritical] // auto-generated_required [ComVisible(false)] public virtual int RegisterTypeForComClients(Type type, RegistrationClassContext classContext, RegistrationConnectionType flags) { #if FEATURE_COMINTEROP_MANAGED_ACTIVATION if (type == null) - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); Contract.EndContractBlock(); if ((type as RuntimeType) == null) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"),"type"); + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"),nameof(type)); if (!TypeRequiresRegistration(type)) - throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustBeComCreatable"),"type"); + throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustBeComCreatable"),nameof(type)); // Call the native method to do CoRegisterClassObject return RegisterTypeForComClientsExNative(type, classContext, flags); @@ -327,7 +320,6 @@ namespace System.Runtime.InteropServices { #endif // FEATURE_COMINTEROP_MANAGED_ACTIVATION } - [System.Security.SecurityCritical] // auto-generated_required [ComVisible(false)] public virtual void UnregisterTypeForComClients(int cookie) { @@ -340,7 +332,6 @@ namespace System.Runtime.InteropServices { #region Internal helpers - [System.Security.SecurityCritical] // auto-generated_required internal static bool TypeRequiresRegistrationHelper(Type type) { // If the type is not a class or a value class, then it does not get registered. @@ -365,7 +356,6 @@ namespace System.Runtime.InteropServices { #region Private helpers - [System.Security.SecurityCritical] // auto-generated private void RegisterValueType(Type type, String strAsmName, String strAsmVersion, String strAsmCodeBase, String strRuntimeVersion) { // Retrieve some information that will be used during the registration process. @@ -397,7 +387,6 @@ namespace System.Runtime.InteropServices { } } - [System.Security.SecurityCritical] // auto-generated private void RegisterManagedType(Type type, String strAsmName, String strAsmVersion, String strAsmCodeBase, String strRuntimeVersion) { // @@ -483,7 +472,6 @@ namespace System.Runtime.InteropServices { EnsureManagedCategoryExists(); } - [System.Security.SecurityCritical] // auto-generated private void RegisterComImportedType(Type type, String strAsmName, String strAsmVersion, String strAsmCodeBase, String strRuntimeVersion) { // Retrieve some information that will be used during the registration process. @@ -525,7 +513,6 @@ namespace System.Runtime.InteropServices { } } - [System.Security.SecurityCritical] // auto-generated private bool UnregisterValueType(Type type, String strAsmVersion) { bool bAllVersionsGone = true; @@ -582,7 +569,6 @@ namespace System.Runtime.InteropServices { // Return : // true: All versions are gone. // false: Some versions are still left in registry - [System.Security.SecurityCritical] // auto-generated private bool UnregisterManagedType(Type type,String strAsmVersion) { bool bAllVersionsGone = true; @@ -776,7 +762,6 @@ namespace System.Runtime.InteropServices { // Return: // true: All version information are gone. // false: There are still some version left in registry - [System.Security.SecurityCritical] // auto-generated private bool UnregisterComImportedType(Type type, String strAsmVersion) { bool bAllVersionsGone = true; @@ -846,7 +831,6 @@ namespace System.Runtime.InteropServices { return bAllVersionsGone; } - [System.Security.SecurityCritical] // auto-generated private void RegisterPrimaryInteropAssembly(RuntimeAssembly assembly, String strAsmCodeBase, PrimaryInteropAssemblyAttribute attr) { // Validate that the PIA has a strong name. @@ -874,7 +858,6 @@ namespace System.Runtime.InteropServices { } } - [System.Security.SecurityCritical] // auto-generated private void UnregisterPrimaryInteropAssembly(Assembly assembly, PrimaryInteropAssemblyAttribute attr) { String strTlbId = "{" + Marshal.GetTypeLibGuidForAssembly(assembly).ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; @@ -937,20 +920,12 @@ namespace System.Runtime.InteropServices { private static bool ManagedCategoryExists() { using (RegistryKey componentCategoryKey = Registry.ClassesRoot.OpenSubKey(strComponentCategorySubKey, -#if FEATURE_MACL - RegistryKeyPermissionCheck.ReadSubTree)) -#else false)) -#endif { if (componentCategoryKey == null) return false; using (RegistryKey managedCategoryKey = componentCategoryKey.OpenSubKey(strManagedCategoryGuid, -#if FEATURE_MACL - RegistryKeyPermissionCheck.ReadSubTree)) -#else false)) -#endif { if (managedCategoryKey == null) return false; @@ -966,7 +941,6 @@ namespace System.Runtime.InteropServices { return true; } - [System.Security.SecurityCritical] // auto-generated private void CallUserDefinedRegistrationMethod(Type type, bool bRegister) { bool bFunctionCalled = false; @@ -1069,13 +1043,11 @@ namespace System.Runtime.InteropServices { #if FEATURE_COMINTEROP_MANAGED_ACTIVATION // GUID versioning can be controlled by using the GuidAttribute or // letting the runtime generate it based on type and assembly strong name. - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void RegisterTypeForComClientsNative(Type type,ref Guid g); // GUID versioning can be controlled by using the GuidAttribute or // letting the runtime generate it based on type and assembly strong name. - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern int RegisterTypeForComClientsExNative(Type t, RegistrationClassContext clsContext, RegistrationConnectionType flags); #endif // FEATURE_COMINTEROP_MANAGED_ACTIVATION diff --git a/src/mscorlib/src/System/Runtime/InteropServices/RuntimeEnvironment.cs b/src/mscorlib/src/System/Runtime/InteropServices/RuntimeEnvironment.cs index d722843..a5c058d 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/RuntimeEnvironment.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/RuntimeEnvironment.cs @@ -23,70 +23,31 @@ using Microsoft.Win32; using System.Runtime.Versioning; using StackCrawlMark = System.Threading.StackCrawlMark; -namespace System.Runtime.InteropServices { -[System.Runtime.InteropServices.ComVisible(true)] -#if FEATURE_CORECLR - static -#endif - public class RuntimeEnvironment { +namespace System.Runtime.InteropServices +{ + [System.Runtime.InteropServices.ComVisible(true)] + static public class RuntimeEnvironment { -#if !FEATURE_CORECLR - // This should have been a static class, but wasn't as of v3.5. Clearly, this is - // broken. We'll keep this in V4 for binary compat, but marked obsolete as error - // so migrated source code gets fixed. On Silverlight, this type exists but is - // not public. - [Obsolete("Do not create instances of the RuntimeEnvironment class. Call the static methods directly on this type instead", true)] - public RuntimeEnvironment() - { - // Should not have been instantiable - here for binary compatibility in V4. - } -#endif - - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern String GetModuleFileName(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern String GetDeveloperPath(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern String GetHostBindingFile(); -#if !FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - internal static extern void _GetSystemVersion(StringHandleOnStack retVer); -#endif //!FEATURE_CORECLR - public static bool FromGlobalAccessCache(Assembly a) { return a.GlobalAssemblyCache; } - -#if !FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // public member -#endif + [MethodImpl (MethodImplOptions.NoInlining)] public static String GetSystemVersion() { -#if FEATURE_CORECLR - return Assembly.GetExecutingAssembly().ImageRuntimeVersion; - -#else // FEATURE_CORECLR - - String ver = null; - _GetSystemVersion(JitHelpers.GetStringHandleOnStack(ref ver)); - return ver; - -#endif // FEATURE_CORECLR - } - - [System.Security.SecuritySafeCritical] // auto-generated + public static String GetRuntimeDirectory() { String dir = GetRuntimeDirectoryImpl(); @@ -94,13 +55,11 @@ namespace System.Runtime.InteropServices { return dir; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern String GetRuntimeDirectoryImpl(); // Returns the system ConfigurationFile public static String SystemConfigurationFile { - [System.Security.SecuritySafeCritical] // auto-generated get { StringBuilder sb = new StringBuilder(Path.MaxPath); sb.Append(GetRuntimeDirectory()); @@ -115,7 +74,6 @@ namespace System.Runtime.InteropServices { } #if FEATURE_COMINTEROP - [System.Security.SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern IntPtr GetRuntimeInterfaceImpl( @@ -130,7 +88,6 @@ namespace System.Runtime.InteropServices { // Returns unmanaged pointer to requested interface on success. Throws // COMException with failed HR if there is a QI failure. // - [System.Security.SecurityCritical] // do not allow partial trust callers [ComVisible(false)] public static IntPtr GetRuntimeInterfaceAsIntPtr(Guid clsid, Guid riid) { @@ -145,7 +102,6 @@ namespace System.Runtime.InteropServices { // Returns an RCW to requested interface on success. Throws // COMException with failed HR if there is a QI failure. // - [System.Security.SecurityCritical] // do not allow partial trust callers [ComVisible(false)] public static object GetRuntimeInterfaceAsObject(Guid clsid, Guid riid) { @@ -159,7 +115,6 @@ namespace System.Runtime.InteropServices { } } } - #endif // FEATURE_COMINTEROP } } diff --git a/src/mscorlib/src/System/Runtime/InteropServices/SafeBuffer.cs b/src/mscorlib/src/System/Runtime/InteropServices/SafeBuffer.cs index a659daf..eba67ae 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/SafeBuffer.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/SafeBuffer.cs @@ -75,10 +75,10 @@ using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; using System.Runtime.Versioning; using Microsoft.Win32.SafeHandles; +using System.Diagnostics; using System.Diagnostics.Contracts; - [System.Security.SecurityCritical] public abstract unsafe class SafeBuffer : SafeHandleZeroOrMinusOneIsInvalid { // Steal UIntPtr.MaxValue as our uninitialized value. @@ -101,13 +101,13 @@ using System.Diagnostics.Contracts; public void Initialize(ulong numBytes) { if (numBytes < 0) - throw new ArgumentOutOfRangeException("numBytes", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(numBytes), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (IntPtr.Size == 4 && numBytes > UInt32.MaxValue) - throw new ArgumentOutOfRangeException("numBytes", Environment.GetResourceString("ArgumentOutOfRange_AddressSpace")); + throw new ArgumentOutOfRangeException(nameof(numBytes), Environment.GetResourceString("ArgumentOutOfRange_AddressSpace")); Contract.EndContractBlock(); if (numBytes >= (ulong)Uninitialized) - throw new ArgumentOutOfRangeException("numBytes", Environment.GetResourceString("ArgumentOutOfRange_UIntPtrMax-1")); + throw new ArgumentOutOfRangeException(nameof(numBytes), Environment.GetResourceString("ArgumentOutOfRange_UIntPtrMax-1")); _numBytes = (UIntPtr) numBytes; } @@ -120,16 +120,16 @@ using System.Diagnostics.Contracts; public void Initialize(uint numElements, uint sizeOfEachElement) { if (numElements < 0) - throw new ArgumentOutOfRangeException("numElements", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(numElements), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (sizeOfEachElement < 0) - throw new ArgumentOutOfRangeException("sizeOfEachElement", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(sizeOfEachElement), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (IntPtr.Size == 4 && numElements * sizeOfEachElement > UInt32.MaxValue) throw new ArgumentOutOfRangeException("numBytes", Environment.GetResourceString("ArgumentOutOfRange_AddressSpace")); Contract.EndContractBlock(); if (numElements * sizeOfEachElement >= (ulong)Uninitialized) - throw new ArgumentOutOfRangeException("numElements", Environment.GetResourceString("ArgumentOutOfRange_UIntPtrMax-1")); + throw new ArgumentOutOfRangeException(nameof(numElements), Environment.GetResourceString("ArgumentOutOfRange_UIntPtrMax-1")); _numBytes = checked((UIntPtr) (numElements * sizeOfEachElement)); } @@ -245,11 +245,11 @@ using System.Diagnostics.Contracts; where T : struct { if (array == null) - throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(array), Environment.GetResourceString("ArgumentNull_Buffer")); if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (array.Length - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -317,11 +317,11 @@ using System.Diagnostics.Contracts; where T : struct { if (array == null) - throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Buffer")); + throw new ArgumentNullException(nameof(array), Environment.GetResourceString("ArgumentNull_Buffer")); if (index < 0) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (array.Length - index < count) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -385,7 +385,7 @@ using System.Diagnostics.Contracts; [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] private static InvalidOperationException NotInitialized() { - Contract.Assert(false, "Uninitialized SafeBuffer! Someone needs to call Initialize before using this instance!"); + Debug.Assert(false, "Uninitialized SafeBuffer! Someone needs to call Initialize before using this instance!"); return new InvalidOperationException(Environment.GetResourceString("InvalidOperation_MustCallInitialize")); } diff --git a/src/mscorlib/src/System/Runtime/InteropServices/SafeHandle.cs b/src/mscorlib/src/System/Runtime/InteropServices/SafeHandle.cs index c268528..ed9910e 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/SafeHandle.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/SafeHandle.cs @@ -134,10 +134,6 @@ using System.Runtime.Versioning; // we'll do this to ensure we've cut off all attack vectors. Similarly, all // methods have a link demand to ensure untrusted code cannot directly edit // or alter a handle. -[System.Security.SecurityCritical] // auto-generated_required -#if !FEATURE_CORECLR -[SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)] -#endif public abstract class SafeHandle : CriticalFinalizerObject, IDisposable { // ! Do not add or rearrange fields as the EE depends on this layout. @@ -182,16 +178,13 @@ public abstract class SafeHandle : CriticalFinalizerObject, IDisposable _fullyInitialized = true; } -#if FEATURE_CORECLR // Migrating InheritanceDemands requires this default ctor, so we can mark it critical protected SafeHandle() { BCLDebug.Assert(false, "SafeHandle's protected default ctor should never be used!"); throw new NotImplementedException(); } -#endif - [System.Security.SecuritySafeCritical] // auto-generated ~SafeHandle() { Dispose(false); @@ -236,19 +229,16 @@ public abstract class SafeHandle : CriticalFinalizerObject, IDisposable get; } - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public void Close() { Dispose(true); } - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public void Dispose() { Dispose(true); } - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] protected virtual void Dispose(bool disposing) { @@ -266,7 +256,6 @@ public abstract class SafeHandle : CriticalFinalizerObject, IDisposable // your handle is invalid and you want to record that information. // An example is calling a syscall and getting back ERROR_INVALID_HANDLE. // This method will normally leak handles! - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern void SetHandleAsInvalid(); @@ -295,7 +284,6 @@ public abstract class SafeHandle : CriticalFinalizerObject, IDisposable // when the method is interrupted prior to processing by a thread abort or // when the handle has already been (or is in the process of being) // released. - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern void DangerousAddRef(ref bool success); @@ -309,7 +297,6 @@ public abstract class SafeHandle : CriticalFinalizerObject, IDisposable // constitutes a potential security hole (via handle recycling) as well as a // correctness problem -- so don't ever expose Dangerous* calls out to // untrusted code. - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern void DangerousRelease(); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/SafeHeapHandle.cs b/src/mscorlib/src/System/Runtime/InteropServices/SafeHeapHandle.cs deleted file mode 100644 index b0c422d..0000000 --- a/src/mscorlib/src/System/Runtime/InteropServices/SafeHeapHandle.cs +++ /dev/null @@ -1,115 +0,0 @@ -// 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. - -namespace System.Runtime.InteropServices -{ - /// - /// Handle for heap memory that allows tracking of capacity and reallocating. - /// - [System.Security.SecurityCritical] - internal sealed class SafeHeapHandle : SafeBuffer - { - /// - /// Allocate a buffer of the given size if requested. - /// - /// Required size in bytes. Must be less than UInt32.MaxValue for 32 bit or UInt64.MaxValue for 64 bit. - /// Thrown if the requested memory size cannot be allocated. - /// Thrown if size is greater than the maximum memory size. - public SafeHeapHandle(ulong byteLength) : base(ownsHandle: true) - { - Resize(byteLength); - } - - public override bool IsInvalid - { - [System.Security.SecurityCritical] - get - { return handle == IntPtr.Zero; } - } - - /// - /// Resize the buffer to the given size if requested. - /// - /// Required size in bytes. Must be less than UInt32.MaxValue for 32 bit or UInt64.MaxValue for 64 bit. - /// Thrown if the requested memory size cannot be allocated. - /// Thrown if size is greater than the maximum memory size. - public void Resize(ulong byteLength) - { - if (IsClosed) throw new ObjectDisposedException("SafeHeapHandle"); - - ulong originalLength = 0; - if (handle == IntPtr.Zero) - { - handle = Marshal.AllocHGlobal((IntPtr)byteLength); - } - else - { - originalLength = ByteLength; - - // This may or may not be the same handle, may realloc in place. If the - // handle changes Windows will deal with the old handle, trying to free it will - // cause an error. - handle = Marshal.ReAllocHGlobal(pv: handle, cb: (IntPtr)byteLength); - } - - if (handle == IntPtr.Zero) - { - // Only real plausible answer - throw new OutOfMemoryException(); - } - - if (byteLength > originalLength) - { - // Add pressure - ulong addedBytes = byteLength - originalLength; - if (addedBytes > long.MaxValue) - { - GC.AddMemoryPressure(long.MaxValue); - GC.AddMemoryPressure((long)(addedBytes - long.MaxValue)); - } - else - { - GC.AddMemoryPressure((long)addedBytes); - } - } - else - { - // Shrank or did nothing, release pressure if needed - RemoveMemoryPressure(originalLength - byteLength); - } - - Initialize(byteLength); - } - - private void RemoveMemoryPressure(ulong removedBytes) - { - if (removedBytes == 0) return; - - if (removedBytes > long.MaxValue) - { - GC.RemoveMemoryPressure(long.MaxValue); - GC.RemoveMemoryPressure((long)(removedBytes - long.MaxValue)); - } - else - { - GC.RemoveMemoryPressure((long)removedBytes); - } - } - - [System.Security.SecurityCritical] - protected override bool ReleaseHandle() - { - IntPtr handle = this.handle; - this.handle = IntPtr.Zero; - - if (handle != IntPtr.Zero) - { - RemoveMemoryPressure(ByteLength); - Marshal.FreeHGlobal(handle); - } - - return true; - } - } -} \ No newline at end of file diff --git a/src/mscorlib/src/System/Runtime/InteropServices/StringBuffer.cs b/src/mscorlib/src/System/Runtime/InteropServices/StringBuffer.cs deleted file mode 100644 index 15b1b6a..0000000 --- a/src/mscorlib/src/System/Runtime/InteropServices/StringBuffer.cs +++ /dev/null @@ -1,402 +0,0 @@ -// 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. - -namespace System.Runtime.InteropServices -{ - /// - /// Native buffer that deals in char size increments. Dispose to free memory. Allows buffers larger - /// than a maximum size string to enable working with very large string arrays. Always makes ordinal - /// comparisons. - /// - /// A more performant replacement for StringBuilder when performing native interop. - /// - /// - /// Suggested use through P/Invoke: define DllImport arguments that take a character buffer as IntPtr. - /// NativeStringBuffer has an implicit conversion to IntPtr. - /// - internal class StringBuffer : NativeBuffer - { - private uint _length; - - /// - /// Instantiate the buffer with capacity for at least the specified number of characters. Capacity - /// includes the trailing null character. - /// - public StringBuffer(uint initialCapacity = 0) - : base(initialCapacity * (ulong)sizeof(char)) - { - } - - /// - /// Instantiate the buffer with a copy of the specified string. - /// - public StringBuffer(string initialContents) - : base(0) - { - // We don't pass the count of bytes to the base constructor, appending will - // initialize to the correct size for the specified initial contents. - if (initialContents != null) - { - Append(initialContents); - } - } - - /// - /// Instantiate the buffer with a copy of the specified StringBuffer. - /// - public StringBuffer(StringBuffer initialContents) - : base(0) - { - // We don't pass the count of bytes to the base constructor, appending will - // initialize to the correct size for the specified initial contents. - if (initialContents != null) - { - Append(initialContents); - } - } - - /// - /// Get/set the character at the given index. - /// - /// Thrown if attempting to index outside of the buffer length. - public unsafe char this[uint index] - { - [System.Security.SecuritySafeCritical] - get - { - if (index >= _length) throw new ArgumentOutOfRangeException("index"); - return CharPointer[index]; - } - [System.Security.SecuritySafeCritical] - set - { - if (index >= _length) throw new ArgumentOutOfRangeException("index"); - CharPointer[index] = value; - } - } - - /// - /// Character capacity of the buffer. Includes the count for the trailing null character. - /// - public uint CharCapacity - { - [System.Security.SecuritySafeCritical] - get - { - ulong byteCapacity = ByteCapacity; - ulong charCapacity = byteCapacity == 0 ? 0 : byteCapacity / sizeof(char); - return charCapacity > uint.MaxValue ? uint.MaxValue : (uint)charCapacity; - } - } - - /// - /// Ensure capacity in characters is at least the given minimum. Capacity includes space for the trailing - /// null, which is not part of the Length. - /// - /// Thrown if unable to allocate memory when setting. - [System.Security.SecuritySafeCritical] - public void EnsureCharCapacity(uint minCapacity) - { - EnsureByteCapacity(minCapacity * (ulong)sizeof(char)); - } - - /// - /// The logical length of the buffer in characters. (Does not include the final null, which is auto appended.) Will automatically attempt to increase capacity. - /// This is where the usable data ends. - /// - /// Thrown if unable to allocate memory when setting. - /// Thrown if the set size in bytes is uint.MaxValue (as space is implicitly reservced for the trailing null). - public unsafe uint Length - { - get { return _length; } - [System.Security.SecuritySafeCritical] - set - { - if (value == uint.MaxValue) throw new ArgumentOutOfRangeException("Length"); - - // Null terminate - EnsureCharCapacity(value + 1); - CharPointer[value] = '\0'; - - _length = value; - } - } - - /// - /// For use when the native api null terminates but doesn't return a length. - /// If no null is found, the length will not be changed. - /// - [System.Security.SecuritySafeCritical] - public unsafe void SetLengthToFirstNull() - { - char* buffer = CharPointer; - uint capacity = CharCapacity; - for (uint i = 0; i < capacity; i++) - { - if (buffer[i] == '\0') - { - _length = i; - break; - } - } - } - - internal unsafe char* CharPointer - { - [System.Security.SecurityCritical] - get - { - return (char*)VoidPointer; - } - } - - /// - /// True if the buffer contains the given character. - /// - [System.Security.SecurityCritical] - public unsafe bool Contains(char value) - { - char* start = CharPointer; - uint length = _length; - - for (uint i = 0; i < length; i++) - { - if (*start++ == value) return true; - } - - return false; - } - - /// - /// Returns true if the buffer starts with the given string. - /// - [System.Security.SecuritySafeCritical] - public bool StartsWith(string value) - { - if (value == null) throw new ArgumentNullException("value"); - if (_length < (uint)value.Length) return false; - return SubstringEquals(value, startIndex: 0, count: value.Length); - } - - /// - /// Returns true if the specified StringBuffer substring equals the given value. - /// - /// The value to compare against the specified substring. - /// Start index of the sub string. - /// Length of the substring, or -1 to check all remaining. - /// - /// Thrown if or are outside the range - /// of the buffer's length. - /// - [System.Security.SecuritySafeCritical] - public unsafe bool SubstringEquals(string value, uint startIndex = 0, int count = -1) - { - if (value == null) return false; - if (count < -1) throw new ArgumentOutOfRangeException("count"); - if (startIndex > _length) throw new ArgumentOutOfRangeException("startIndex"); - - uint realCount = count == -1 ? _length - startIndex : (uint)count; - if (checked(startIndex + realCount) > _length) throw new ArgumentOutOfRangeException("count"); - - int length = value.Length; - - // Check the substring length against the input length - if (realCount != (uint)length) return false; - - fixed (char* valueStart = value) - { - char* bufferStart = CharPointer + startIndex; - for (int i = 0; i < length; i++) - { - // Note that indexing in this case generates faster code than trying to copy the pointer and increment it - if (*bufferStart++ != valueStart[i]) return false; - } - } - - return true; - } - - /// - /// Append the given string. - /// - /// The string to append. - /// The index in the input string to start appending from. - /// The count of characters to copy from the input string, or -1 for all remaining. - /// Thrown if is null. - /// - /// Thrown if or are outside the range - /// of characters. - /// - [System.Security.SecuritySafeCritical] - public void Append(string value, int startIndex = 0, int count = -1) - { - CopyFrom( - bufferIndex: _length, - source: value, - sourceIndex: startIndex, - count: count); - } - - /// - /// Append the given buffer. - /// - /// The buffer to append. - /// The index in the input buffer to start appending from. - /// Thrown if is null. - /// - /// Thrown if is outside the range of characters. - /// - public void Append(StringBuffer value, uint startIndex = 0) - { - if (value == null) throw new ArgumentNullException("value"); - if (value.Length == 0) return; - value.CopyTo( - bufferIndex: startIndex, - destination: this, - destinationIndex: _length, - count: value.Length); - } - - /// - /// Append the given buffer. - /// - /// The buffer to append. - /// The index in the input buffer to start appending from. - /// The count of characters to copy from the buffer string. - /// Thrown if is null. - /// - /// Thrown if or are outside the range - /// of characters. - /// - public void Append(StringBuffer value, uint startIndex, uint count) - { - if (value == null) throw new ArgumentNullException("value"); - if (count == 0) return; - value.CopyTo( - bufferIndex: startIndex, - destination: this, - destinationIndex: _length, - count: count); - } - - /// - /// Copy contents to the specified buffer. Destination index must be within current destination length. - /// Will grow the destination buffer if needed. - /// - /// - /// Thrown if or or are outside the range - /// of characters. - /// - /// Thrown if is null. - [System.Security.SecuritySafeCritical] - public unsafe void CopyTo(uint bufferIndex, StringBuffer destination, uint destinationIndex, uint count) - { - if (destination == null) throw new ArgumentNullException("destination"); - if (destinationIndex > destination._length) throw new ArgumentOutOfRangeException("destinationIndex"); - if (bufferIndex >= _length) throw new ArgumentOutOfRangeException("bufferIndex"); - if (_length < checked(bufferIndex + count)) throw new ArgumentOutOfRangeException("count"); - - if (count == 0) return; - uint lastIndex = checked(destinationIndex + count); - if (destination._length < lastIndex) destination.Length = lastIndex; - - Buffer.MemoryCopy( - source: CharPointer + bufferIndex, - destination: destination.CharPointer + destinationIndex, - destinationSizeInBytes: checked((long)(destination.ByteCapacity - (destinationIndex * sizeof(char)))), - sourceBytesToCopy: checked((long)count * sizeof(char))); - } - - /// - /// Copy contents from the specified string into the buffer at the given index. Start index must be within the current length of - /// the buffer, will grow as necessary. - /// - /// - /// Thrown if or or are outside the range - /// of characters. - /// - /// Thrown if is null. - [System.Security.SecuritySafeCritical] - public unsafe void CopyFrom(uint bufferIndex, string source, int sourceIndex = 0, int count = -1) - { - if (source == null) throw new ArgumentNullException("source"); - if (bufferIndex > _length) throw new ArgumentOutOfRangeException("bufferIndex"); - if (sourceIndex < 0 || sourceIndex >= source.Length) throw new ArgumentOutOfRangeException("sourceIndex"); - if (count == -1) count = source.Length - sourceIndex; - if (count < 0 || source.Length - count < sourceIndex) throw new ArgumentOutOfRangeException("count"); - - if (count == 0) return; - uint lastIndex = bufferIndex + (uint)count; - if (_length < lastIndex) Length = lastIndex; - - fixed (char* content = source) - { - Buffer.MemoryCopy( - source: content + sourceIndex, - destination: CharPointer + bufferIndex, - destinationSizeInBytes: checked((long)(ByteCapacity - (bufferIndex * sizeof(char)))), - sourceBytesToCopy: (long)count * sizeof(char)); - } - } - - /// - /// Trim the specified values from the end of the buffer. If nothing is specified, nothing is trimmed. - /// - [System.Security.SecuritySafeCritical] - public unsafe void TrimEnd(char[] values) - { - if (values == null || values.Length == 0 || _length == 0) return; - - char* end = CharPointer + _length - 1; - - while (_length > 0 && Array.IndexOf(values, *end) >= 0) - { - Length = _length - 1; - end--; - } - } - - /// - /// String representation of the entire buffer. If the buffer is larger than the maximum size string (int.MaxValue) this will throw. - /// - /// Thrown if the buffer is too big to fit into a string. - [System.Security.SecuritySafeCritical] - public unsafe override string ToString() - { - if (_length == 0) return string.Empty; - if (_length > int.MaxValue) throw new InvalidOperationException(); - return new string(CharPointer, startIndex: 0, length: (int)_length); - } - - /// - /// Get the given substring in the buffer. - /// - /// Count of characters to take, or remaining characters from if -1. - /// - /// Thrown if or are outside the range of the buffer's length - /// or count is greater than the maximum string size (int.MaxValue). - /// - [System.Security.SecuritySafeCritical] - public unsafe string Substring(uint startIndex, int count = -1) - { - if (startIndex > (_length == 0 ? 0 : _length - 1)) throw new ArgumentOutOfRangeException("startIndex"); - if (count < -1) throw new ArgumentOutOfRangeException("count"); - - uint realCount = count == -1 ? _length - startIndex : (uint)count; - if (realCount > int.MaxValue || checked(startIndex + realCount) > _length) throw new ArgumentOutOfRangeException("count"); - if (realCount == 0) return string.Empty; - - // The buffer could be bigger than will fit into a string, but the substring might fit. As the starting - // index might be bigger than int we need to index ourselves. - return new string(value: CharPointer + startIndex, startIndex: 0, length: (int)realCount); - } - - [System.Security.SecuritySafeCritical] - public override void Free() - { - base.Free(); - _length = 0; - } - } -} \ No newline at end of file diff --git a/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventProviderWriter.cs b/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventProviderWriter.cs index 58f70e5..160a0ab 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventProviderWriter.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventProviderWriter.cs @@ -10,6 +10,7 @@ namespace System.Runtime.InteropServices.TCEAdapterGen { using System.Reflection.Emit; using System.Collections; using System.Threading; + using System.Diagnostics; using System.Diagnostics.Contracts; internal class EventProviderWriter @@ -96,34 +97,34 @@ namespace System.Runtime.InteropServices.TCEAdapterGen { // Find the delegate on the event sink helper. FieldInfo DelegateField = SinkHelperClass.GetField( "m_" + SrcItfMethod.Name + "Delegate" ); - Contract.Assert(DelegateField != null, "Unable to find the field m_" + SrcItfMethod.Name + "Delegate on the sink helper"); + Debug.Assert(DelegateField != null, "Unable to find the field m_" + SrcItfMethod.Name + "Delegate on the sink helper"); // Find the cookie on the event sink helper. FieldInfo CookieField = SinkHelperClass.GetField( "m_dwCookie" ); - Contract.Assert(CookieField != null, "Unable to find the field m_dwCookie on the sink helper"); + Debug.Assert(CookieField != null, "Unable to find the field m_dwCookie on the sink helper"); // Retrieve the sink helper's constructor. ConstructorInfo SinkHelperCons = SinkHelperClass.GetConstructor(EventProviderWriter.DefaultLookup | BindingFlags.NonPublic, null, Array.Empty(), null ); - Contract.Assert(SinkHelperCons != null, "Unable to find the constructor for the sink helper"); + Debug.Assert(SinkHelperCons != null, "Unable to find the constructor for the sink helper"); // Retrieve the IConnectionPoint.Advise method. MethodInfo CPAdviseMethod = typeof(IConnectionPoint).GetMethod( "Advise" ); - Contract.Assert(CPAdviseMethod != null, "Unable to find the method ConnectionPoint.Advise"); + Debug.Assert(CPAdviseMethod != null, "Unable to find the method ConnectionPoint.Advise"); // Retrieve the ArrayList.Add method. aParamTypes = new Type[1]; aParamTypes[0] = typeof(Object); MethodInfo ArrayListAddMethod = typeof(ArrayList).GetMethod( "Add", aParamTypes, null ); - Contract.Assert(ArrayListAddMethod != null, "Unable to find the method ArrayList.Add"); + Debug.Assert(ArrayListAddMethod != null, "Unable to find the method ArrayList.Add"); // Retrieve the Monitor.Enter() method. MethodInfo MonitorEnterMethod = typeof(Monitor).GetMethod( "Enter", MonitorEnterParamTypes, null ); - Contract.Assert(MonitorEnterMethod != null, "Unable to find the method Monitor.Enter()"); + Debug.Assert(MonitorEnterMethod != null, "Unable to find the method Monitor.Enter()"); // Retrieve the Monitor.Exit() method. aParamTypes[0] = typeof(Object); MethodInfo MonitorExitMethod = typeof(Monitor).GetMethod( "Exit", aParamTypes, null ); - Contract.Assert(MonitorExitMethod != null, "Unable to find the method Monitor.Exit()"); + Debug.Assert(MonitorExitMethod != null, "Unable to find the method Monitor.Exit()"); // Define the add_XXX method. Type[] parameterTypes; @@ -239,51 +240,51 @@ namespace System.Runtime.InteropServices.TCEAdapterGen { // Find the delegate on the event sink helper. FieldInfo DelegateField = SinkHelperClass.GetField( "m_" + SrcItfMethod.Name + "Delegate" ); - Contract.Assert(DelegateField != null, "Unable to find the field m_" + SrcItfMethod.Name + "Delegate on the sink helper"); + Debug.Assert(DelegateField != null, "Unable to find the field m_" + SrcItfMethod.Name + "Delegate on the sink helper"); // Find the cookie on the event sink helper. FieldInfo CookieField = SinkHelperClass.GetField( "m_dwCookie" ); - Contract.Assert(CookieField != null, "Unable to find the field m_dwCookie on the sink helper"); + Debug.Assert(CookieField != null, "Unable to find the field m_dwCookie on the sink helper"); // Retrieve the ArrayList.RemoveAt method. aParamTypes = new Type[1]; aParamTypes[0] = typeof(Int32); MethodInfo ArrayListRemoveMethod = typeof(ArrayList).GetMethod( "RemoveAt", aParamTypes, null ); - Contract.Assert(ArrayListRemoveMethod != null, "Unable to find the method ArrayList.RemoveAt()"); + Debug.Assert(ArrayListRemoveMethod != null, "Unable to find the method ArrayList.RemoveAt()"); // Retrieve the ArrayList.Item property get method. PropertyInfo ArrayListItemProperty = typeof(ArrayList).GetProperty( "Item" ); - Contract.Assert(ArrayListItemProperty != null, "Unable to find the property ArrayList.Item"); + Debug.Assert(ArrayListItemProperty != null, "Unable to find the property ArrayList.Item"); MethodInfo ArrayListItemGetMethod = ArrayListItemProperty.GetGetMethod(); - Contract.Assert(ArrayListItemGetMethod != null, "Unable to find the get method for property ArrayList.Item"); + Debug.Assert(ArrayListItemGetMethod != null, "Unable to find the get method for property ArrayList.Item"); // Retrieve the ArrayList.Count property get method. PropertyInfo ArrayListSizeProperty = typeof(ArrayList).GetProperty( "Count" ); - Contract.Assert(ArrayListSizeProperty != null, "Unable to find the property ArrayList.Count"); + Debug.Assert(ArrayListSizeProperty != null, "Unable to find the property ArrayList.Count"); MethodInfo ArrayListSizeGetMethod = ArrayListSizeProperty.GetGetMethod(); - Contract.Assert(ArrayListSizeGetMethod != null, "Unable to find the get method for property ArrayList.Count"); + Debug.Assert(ArrayListSizeGetMethod != null, "Unable to find the get method for property ArrayList.Count"); // Retrieve the Delegate.Equals() method. aParamTypes[0] = typeof(Delegate); MethodInfo DelegateEqualsMethod = typeof(Delegate).GetMethod( "Equals", aParamTypes, null ); - Contract.Assert(DelegateEqualsMethod != null, "Unable to find the method Delegate.Equlals()"); + Debug.Assert(DelegateEqualsMethod != null, "Unable to find the method Delegate.Equlals()"); // Retrieve the Monitor.Enter() method. MethodInfo MonitorEnterMethod = typeof(Monitor).GetMethod("Enter", MonitorEnterParamTypes, null); - Contract.Assert(MonitorEnterMethod != null, "Unable to find the method Monitor.Enter()"); + Debug.Assert(MonitorEnterMethod != null, "Unable to find the method Monitor.Enter()"); // Retrieve the Monitor.Exit() method. aParamTypes[0] = typeof(Object); MethodInfo MonitorExitMethod = typeof(Monitor).GetMethod( "Exit", aParamTypes, null ); - Contract.Assert(MonitorExitMethod != null, "Unable to find the method Monitor.Exit()"); + Debug.Assert(MonitorExitMethod != null, "Unable to find the method Monitor.Exit()"); // Retrieve the ConnectionPoint.Unadvise() method. MethodInfo CPUnadviseMethod = typeof(IConnectionPoint).GetMethod( "Unadvise" ); - Contract.Assert(CPUnadviseMethod != null, "Unable to find the method ConnectionPoint.Unadvise()"); + Debug.Assert(CPUnadviseMethod != null, "Unable to find the method ConnectionPoint.Unadvise()"); // Retrieve the Marshal.ReleaseComObject() method. MethodInfo ReleaseComObjectMethod = typeof(Marshal).GetMethod( "ReleaseComObject" ); - Contract.Assert(ReleaseComObjectMethod != null, "Unable to find the method Marshal.ReleaseComObject()"); + Debug.Assert(ReleaseComObjectMethod != null, "Unable to find the method Marshal.ReleaseComObject()"); // Define the remove_XXX method. Type[] parameterTypes; @@ -463,7 +464,7 @@ namespace System.Runtime.InteropServices.TCEAdapterGen { { // Retrieve the constructor info for the array list's default constructor. ConstructorInfo DefaultArrayListCons = typeof(ArrayList).GetConstructor(EventProviderWriter.DefaultLookup, null, Array.Empty(), null ); - Contract.Assert(DefaultArrayListCons != null, "Unable to find the constructor for class ArrayList"); + Debug.Assert(DefaultArrayListCons != null, "Unable to find the constructor for class ArrayList"); // Temp byte array for Guid ubyte[] rgByteGuid = new ubyte[16]; @@ -472,11 +473,11 @@ namespace System.Runtime.InteropServices.TCEAdapterGen { Type[] aParamTypes = new Type[1]; aParamTypes[0] = typeof(Byte[]); ConstructorInfo ByteArrayGUIDCons = typeof(Guid).GetConstructor(EventProviderWriter.DefaultLookup, null, aParamTypes, null ); - Contract.Assert(ByteArrayGUIDCons != null, "Unable to find the constructor for GUID that accepts a string as argument"); + Debug.Assert(ByteArrayGUIDCons != null, "Unable to find the constructor for GUID that accepts a string as argument"); // Retrieve the IConnectionPointContainer.FindConnectionPoint() method. MethodInfo CPCFindCPMethod = typeof(IConnectionPointContainer).GetMethod( "FindConnectionPoint" ); - Contract.Assert(CPCFindCPMethod != null, "Unable to find the method ConnectionPointContainer.FindConnectionPoint()"); + Debug.Assert(CPCFindCPMethod != null, "Unable to find the method ConnectionPointContainer.FindConnectionPoint()"); // Define the Init method itself. MethodBuilder Meth = OutputTypeBuilder.DefineMethod( @@ -553,7 +554,7 @@ namespace System.Runtime.InteropServices.TCEAdapterGen { { // Retrieve the constructor info for the base class's constructor. ConstructorInfo DefaultBaseClsCons = typeof(Object).GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, Array.Empty(), null ); - Contract.Assert(DefaultBaseClsCons != null, "Unable to find the object's public default constructor"); + Debug.Assert(DefaultBaseClsCons != null, "Unable to find the object's public default constructor"); // Define the default constructor. MethodAttributes ctorAttributes = MethodAttributes.SpecialName | (DefaultBaseClsCons.Attributes & MethodAttributes.MemberAccessMask); @@ -584,37 +585,37 @@ namespace System.Runtime.InteropServices.TCEAdapterGen { { // Find the cookie on the event sink helper. FieldInfo CookieField = SinkHelperClass.GetField( "m_dwCookie" ); - Contract.Assert(CookieField != null, "Unable to find the field m_dwCookie on the sink helper"); + Debug.Assert(CookieField != null, "Unable to find the field m_dwCookie on the sink helper"); // Retrieve the ArrayList.Item property get method. PropertyInfo ArrayListItemProperty = typeof(ArrayList).GetProperty( "Item" ); - Contract.Assert(ArrayListItemProperty != null, "Unable to find the property ArrayList.Item"); + Debug.Assert(ArrayListItemProperty != null, "Unable to find the property ArrayList.Item"); MethodInfo ArrayListItemGetMethod = ArrayListItemProperty.GetGetMethod(); - Contract.Assert(ArrayListItemGetMethod != null, "Unable to find the get method for property ArrayList.Item"); + Debug.Assert(ArrayListItemGetMethod != null, "Unable to find the get method for property ArrayList.Item"); // Retrieve the ArrayList.Count property get method. PropertyInfo ArrayListSizeProperty = typeof(ArrayList).GetProperty( "Count" ); - Contract.Assert(ArrayListSizeProperty != null, "Unable to find the property ArrayList.Count"); + Debug.Assert(ArrayListSizeProperty != null, "Unable to find the property ArrayList.Count"); MethodInfo ArrayListSizeGetMethod = ArrayListSizeProperty.GetGetMethod(); - Contract.Assert(ArrayListSizeGetMethod != null, "Unable to find the get method for property ArrayList.Count"); + Debug.Assert(ArrayListSizeGetMethod != null, "Unable to find the get method for property ArrayList.Count"); // Retrieve the ConnectionPoint.Unadvise() method. MethodInfo CPUnadviseMethod = typeof(IConnectionPoint).GetMethod( "Unadvise" ); - Contract.Assert(CPUnadviseMethod != null, "Unable to find the method ConnectionPoint.Unadvise()"); + Debug.Assert(CPUnadviseMethod != null, "Unable to find the method ConnectionPoint.Unadvise()"); // Retrieve the Marshal.ReleaseComObject() method. MethodInfo ReleaseComObjectMethod = typeof(Marshal).GetMethod( "ReleaseComObject" ); - Contract.Assert(ReleaseComObjectMethod != null, "Unable to find the method Marshal.ReleaseComObject()"); + Debug.Assert(ReleaseComObjectMethod != null, "Unable to find the method Marshal.ReleaseComObject()"); // Retrieve the Monitor.Enter() method. MethodInfo MonitorEnterMethod = typeof(Monitor).GetMethod("Enter", MonitorEnterParamTypes, null); - Contract.Assert(MonitorEnterMethod != null, "Unable to find the method Monitor.Enter()"); + Debug.Assert(MonitorEnterMethod != null, "Unable to find the method Monitor.Enter()"); // Retrieve the Monitor.Exit() method. Type[] aParamTypes = new Type[1]; aParamTypes[0] = typeof(Object); MethodInfo MonitorExitMethod = typeof(Monitor).GetMethod( "Exit", aParamTypes, null ); - Contract.Assert(MonitorExitMethod != null, "Unable to find the method Monitor.Exit()"); + Debug.Assert(MonitorExitMethod != null, "Unable to find the method Monitor.Exit()"); // Define the Finalize method itself. MethodBuilder Meth = OutputTypeBuilder.DefineMethod( "Finalize", MethodAttributes.Public | MethodAttributes.Virtual, null, null ); @@ -743,7 +744,7 @@ namespace System.Runtime.InteropServices.TCEAdapterGen { { // Retrieve the method info for GC.SuppressFinalize(). MethodInfo SuppressFinalizeMethod = typeof(GC).GetMethod("SuppressFinalize"); - Contract.Assert(SuppressFinalizeMethod != null, "Unable to find the GC.SuppressFinalize"); + Debug.Assert(SuppressFinalizeMethod != null, "Unable to find the GC.SuppressFinalize"); // Define the Finalize method itself. MethodBuilder Meth = OutputTypeBuilder.DefineMethod( "Dispose", MethodAttributes.Public | MethodAttributes.Virtual, null, null ); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventSinkHelperWriter.cs b/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventSinkHelperWriter.cs index 0367e79..862419c 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventSinkHelperWriter.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventSinkHelperWriter.cs @@ -8,6 +8,7 @@ namespace System.Runtime.InteropServices.TCEAdapterGen { using System.Reflection; using System.Reflection.Emit; using System.Collections; + using System.Diagnostics; using System.Diagnostics.Contracts; internal class EventSinkHelperWriter { @@ -65,7 +66,7 @@ namespace System.Runtime.InteropServices.TCEAdapterGen { // Retrieve the delegate type from the add_XXX method. MethodInfo AddMeth = m_EventItfType.GetMethod( "add_" + aMethods[cMethods].Name ); ParameterInfo[] aParams = AddMeth.GetParameters(); - Contract.Assert(aParams.Length == 1, "All event interface methods must take a single delegate derived type and have a void return type"); + Debug.Assert(aParams.Length == 1, "All event interface methods must take a single delegate derived type and have a void return type"); Type DelegateCls = aParams[0].ParameterType; // Define the delegate instance field. @@ -119,7 +120,7 @@ namespace System.Runtime.InteropServices.TCEAdapterGen { { // Retrieve the method info for the invoke method on the delegate. MethodInfo DelegateInvokeMethod = DelegateCls.GetMethod( "Invoke" ); - Contract.Assert(DelegateInvokeMethod != null, "Unable to find method Delegate.Invoke()"); + Debug.Assert(DelegateInvokeMethod != null, "Unable to find method Delegate.Invoke()"); // Retrieve the return type. Type ReturnType = Method.ReturnType; @@ -229,7 +230,7 @@ namespace System.Runtime.InteropServices.TCEAdapterGen { if ( ReturnType == typeof(IntPtr) ) il.Emit( OpCodes.Ldc_I4_0 ); else - Contract.Assert(false, "Unexpected type for Primitive type."); + Debug.Assert(false, "Unexpected type for Primitive type."); break; } } @@ -254,7 +255,7 @@ namespace System.Runtime.InteropServices.TCEAdapterGen { { // Retrieve the constructor info for the base classe's constructor. ConstructorInfo DefaultBaseClsCons = typeof(Object).GetConstructor(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, Array.Empty(), null ); - Contract.Assert(DefaultBaseClsCons != null, "Unable to find the constructor for class " + m_InputType.Name); + Debug.Assert(DefaultBaseClsCons != null, "Unable to find the constructor for class " + m_InputType.Name); // Define the default constructor. MethodBuilder Cons = OutputTypeBuilder.DefineMethod( ".ctor", diff --git a/src/mscorlib/src/System/Runtime/InteropServices/TypeLibConverter.cs b/src/mscorlib/src/System/Runtime/InteropServices/TypeLibConverter.cs deleted file mode 100644 index e6b148a..0000000 --- a/src/mscorlib/src/System/Runtime/InteropServices/TypeLibConverter.cs +++ /dev/null @@ -1,595 +0,0 @@ -// 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. - -/*============================================================================= -** -** -** -** Purpose: Component that implements the ITypeLibConverter interface and -** does the actual work of converting a typelib to metadata and -** vice versa. -** -** -=============================================================================*/ -#if !FEATURE_CORECLR // current implementation requires reflection only load -namespace System.Runtime.InteropServices { - - using System; - using System.Diagnostics.Contracts; - using System.Collections; - using System.Collections.Generic; - using System.Threading; - using System.Runtime.InteropServices.TCEAdapterGen; - using System.IO; - using System.Reflection; - using System.Reflection.Emit; - using System.Configuration.Assemblies; - using Microsoft.Win32; - using System.Runtime.CompilerServices; - using System.Globalization; - using System.Security; - using System.Security.Permissions; - using System.Runtime.InteropServices.ComTypes; - using System.Runtime.Versioning; - using WORD = System.UInt16; - using DWORD = System.UInt32; - using _TYPELIBATTR = System.Runtime.InteropServices.ComTypes.TYPELIBATTR; - - [Guid("F1C3BF79-C3E4-11d3-88E7-00902754C43A")] - [ClassInterface(ClassInterfaceType.None)] -[System.Runtime.InteropServices.ComVisible(true)] - public sealed class TypeLibConverter : ITypeLibConverter - { - private const String s_strTypeLibAssemblyTitlePrefix = "TypeLib "; - private const String s_strTypeLibAssemblyDescPrefix = "Assembly generated from typelib "; - private const int MAX_NAMESPACE_LENGTH = 1024; - - - // - // ITypeLibConverter interface. - // - - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] - public AssemblyBuilder ConvertTypeLibToAssembly([MarshalAs(UnmanagedType.Interface)] Object typeLib, - String asmFileName, - int flags, - ITypeLibImporterNotifySink notifySink, - byte[] publicKey, - StrongNameKeyPair keyPair, - bool unsafeInterfaces) - { - return ConvertTypeLibToAssembly(typeLib, - asmFileName, - (unsafeInterfaces - ? TypeLibImporterFlags.UnsafeInterfaces - : 0), - notifySink, - publicKey, - keyPair, - null, - null); - } - - - - - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] - public AssemblyBuilder ConvertTypeLibToAssembly([MarshalAs(UnmanagedType.Interface)] Object typeLib, - String asmFileName, - TypeLibImporterFlags flags, - ITypeLibImporterNotifySink notifySink, - byte[] publicKey, - StrongNameKeyPair keyPair, - String asmNamespace, - Version asmVersion) - { - // Validate the arguments. - if (typeLib == null) - throw new ArgumentNullException("typeLib"); - if (asmFileName == null) - throw new ArgumentNullException("asmFileName"); - if (notifySink == null) - throw new ArgumentNullException("notifySink"); - if (String.Empty.Equals(asmFileName)) - throw new ArgumentException(Environment.GetResourceString("Arg_InvalidFileName"), "asmFileName"); - if (asmFileName.Length > Path.MaxPath) - throw new ArgumentException(Environment.GetResourceString("IO.PathTooLong"), asmFileName); - if ((flags & TypeLibImporterFlags.PrimaryInteropAssembly) != 0 && publicKey == null && keyPair == null) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_PIAMustBeStrongNamed")); - Contract.EndContractBlock(); - - ArrayList eventItfInfoList = null; - - // Determine the AssemblyNameFlags - AssemblyNameFlags asmNameFlags = AssemblyNameFlags.None; - - // Retrieve the assembly name from the typelib. - AssemblyName asmName = GetAssemblyNameFromTypelib(typeLib, asmFileName, publicKey, keyPair, asmVersion, asmNameFlags); - - // Create the dynamic assembly that will contain the converted typelib types. - AssemblyBuilder asmBldr = CreateAssemblyForTypeLib(typeLib, asmFileName, asmName, - (flags & TypeLibImporterFlags.PrimaryInteropAssembly) != 0, - (flags & TypeLibImporterFlags.ReflectionOnlyLoading) != 0, - (flags & TypeLibImporterFlags.NoDefineVersionResource) != 0); - - // Define a dynamic module that will contain the contain the imported types. - String strNonQualifiedAsmFileName = Path.GetFileName(asmFileName); - ModuleBuilder modBldr = asmBldr.DefineDynamicModule(strNonQualifiedAsmFileName, strNonQualifiedAsmFileName); - - // If the namespace hasn't been specified, then use the assembly name. - if (asmNamespace == null) - asmNamespace = asmName.Name; - - // Create a type resolve handler that will also intercept resolve ref messages - // on the sink interface to build up a list of referenced assemblies. - TypeResolveHandler typeResolveHandler = new TypeResolveHandler(modBldr, notifySink); - - // Add a listener for the type resolve events. - AppDomain currentDomain = Thread.GetDomain(); - ResolveEventHandler resolveHandler = new ResolveEventHandler(typeResolveHandler.ResolveEvent); - ResolveEventHandler asmResolveHandler = new ResolveEventHandler(typeResolveHandler.ResolveAsmEvent); - ResolveEventHandler ROAsmResolveHandler = new ResolveEventHandler(typeResolveHandler.ResolveROAsmEvent); - currentDomain.TypeResolve += resolveHandler; - currentDomain.AssemblyResolve += asmResolveHandler; - currentDomain.ReflectionOnlyAssemblyResolve += ROAsmResolveHandler; - - // Convert the types contained in the typelib into metadata and add them to the assembly. - nConvertTypeLibToMetadata(typeLib, asmBldr.InternalAssembly, modBldr.InternalModule, asmNamespace, flags, typeResolveHandler, out eventItfInfoList); - - // Update the COM types in the assembly. - UpdateComTypesInAssembly(asmBldr, modBldr); - - // If there are any event sources then generate the TCE adapters. - if (eventItfInfoList.Count > 0) - new TCEAdapterGenerator().Process(modBldr, eventItfInfoList); - - // Remove the listener for the type resolve events. - currentDomain.TypeResolve -= resolveHandler; - currentDomain.AssemblyResolve -= asmResolveHandler; - currentDomain.ReflectionOnlyAssemblyResolve -= ROAsmResolveHandler; - - // We have finished converting the typelib and now have a fully formed assembly. - return asmBldr; - } - - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] - [return : MarshalAs(UnmanagedType.Interface)] - public Object ConvertAssemblyToTypeLib(Assembly assembly, String strTypeLibName, TypeLibExporterFlags flags, ITypeLibExporterNotifySink notifySink) - { - RuntimeAssembly rtAssembly; - AssemblyBuilder ab = assembly as AssemblyBuilder; - if (ab != null) - rtAssembly = ab.InternalAssembly; - else - rtAssembly = assembly as RuntimeAssembly; - - return nConvertAssemblyToTypeLib(rtAssembly, strTypeLibName, flags, notifySink); - } - - public bool GetPrimaryInteropAssembly(Guid g, Int32 major, Int32 minor, Int32 lcid, out String asmName, out String asmCodeBase) - { - String strTlbId = "{" + g.ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; - String strVersion = major.ToString("x", CultureInfo.InvariantCulture) + "." + minor.ToString("x", CultureInfo.InvariantCulture); - - // Set the two out values to null before we start. - asmName = null; - asmCodeBase = null; - - // Try to open the HKEY_CLASS_ROOT\TypeLib key. - using (RegistryKey TypeLibKey = Registry.ClassesRoot.OpenSubKey("TypeLib", false)) - { - if (TypeLibKey != null) - { - // Try to open the HKEY_CLASS_ROOT\TypeLib\ key. - using (RegistryKey TypeLibSubKey = TypeLibKey.OpenSubKey(strTlbId)) - { - if (TypeLibSubKey != null) - { - // Try to open the HKEY_CLASS_ROOT\TypeLib\\ key. - using (RegistryKey VersionKey = TypeLibSubKey.OpenSubKey(strVersion, false)) - { - if (VersionKey != null) - { - // Attempt to retrieve the assembly name and codebase under the version key. - asmName = (String)VersionKey.GetValue("PrimaryInteropAssemblyName"); - asmCodeBase = (String)VersionKey.GetValue("PrimaryInteropAssemblyCodeBase"); - } - } - } - } - } - } - - // If the assembly name isn't null, then we found an PIA. - return asmName != null; - } - - - // - // Non native helper methods. - // - - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - private static AssemblyBuilder CreateAssemblyForTypeLib(Object typeLib, String asmFileName, AssemblyName asmName, bool bPrimaryInteropAssembly, bool bReflectionOnly, bool bNoDefineVersionResource) - { - // Retrieve the current app domain. - AppDomain currentDomain = Thread.GetDomain(); - - // Retrieve the directory from the assembly file name. - String dir = null; - if (asmFileName != null) - { - dir = Path.GetDirectoryName(asmFileName); - if (String.IsNullOrEmpty(dir)) - dir = null; - } - - AssemblyBuilderAccess aba; - if (bReflectionOnly) - { - aba = AssemblyBuilderAccess.ReflectionOnly; - } - else - { - aba = AssemblyBuilderAccess.RunAndSave; - } - - // Create the dynamic assembly itself. - AssemblyBuilder asmBldr; - - List assemblyAttributes = new List(); -#if !FEATURE_CORECLR - // mscorlib.dll must specify the security rules that assemblies it emits are to use, since by - // default all assemblies will follow security rule set level 2, and we want to make that an - // explicit decision. - ConstructorInfo securityRulesCtor = typeof(SecurityRulesAttribute).GetConstructor(new Type[] { typeof(SecurityRuleSet) }); - CustomAttributeBuilder securityRulesAttribute = - new CustomAttributeBuilder(securityRulesCtor, new object[] { SecurityRuleSet.Level2 }); - assemblyAttributes.Add(securityRulesAttribute); -#endif // !FEATURE_CORECLR - - asmBldr = currentDomain.DefineDynamicAssembly(asmName, aba, dir, false, assemblyAttributes); - - // Set the Guid custom attribute on the assembly. - SetGuidAttributeOnAssembly(asmBldr, typeLib); - - // Set the imported from COM attribute on the assembly and return it. - SetImportedFromTypeLibAttrOnAssembly(asmBldr, typeLib); - - // Set the version information on the typelib. - if (bNoDefineVersionResource) - { - SetTypeLibVersionAttribute(asmBldr, typeLib); - } - else - { - SetVersionInformation(asmBldr, typeLib, asmName); - } - - // If we are generating a PIA, then set the PIA custom attribute. - if (bPrimaryInteropAssembly) - SetPIAAttributeOnAssembly(asmBldr, typeLib); - - return asmBldr; - } - - [System.Security.SecurityCritical] // auto-generated - internal static AssemblyName GetAssemblyNameFromTypelib(Object typeLib, String asmFileName, byte[] publicKey, StrongNameKeyPair keyPair, Version asmVersion, AssemblyNameFlags asmNameFlags) - { - // Extract the name of the typelib. - String strTypeLibName = null; - String strDocString = null; - int dwHelpContext = 0; - String strHelpFile = null; - ITypeLib pTLB = (ITypeLib)typeLib; - pTLB.GetDocumentation(-1, out strTypeLibName, out strDocString, out dwHelpContext, out strHelpFile); - - // Retrieve the name to use for the assembly. - if (asmFileName == null) - { - asmFileName = strTypeLibName; - } - else - { - Contract.Assert((asmFileName != null) && (asmFileName.Length > 0), "The assembly file name cannot be an empty string!"); - - String strFileNameNoPath = Path.GetFileName(asmFileName); - String strExtension = Path.GetExtension(asmFileName); - - // Validate that the extension is valid. - bool bExtensionValid = ".dll".Equals(strExtension, StringComparison.OrdinalIgnoreCase); - - // If the extension is not valid then tell the user and quit. - if (!bExtensionValid) - throw new ArgumentException(Environment.GetResourceString("Arg_InvalidFileExtension")); - - // The assembly cannot contain the path nor the extension. - asmFileName = strFileNameNoPath.Substring(0, strFileNameNoPath.Length - ".dll".Length); - } - - // If the version information was not specified, then retrieve it from the typelib. - if (asmVersion == null) - { - int major; - int minor; - Marshal.GetTypeLibVersion(pTLB, out major, out minor); - asmVersion = new Version(major, minor, 0, 0); - } - - // Create the assembly name for the imported typelib's assembly. - AssemblyName AsmName = new AssemblyName(); - AsmName.Init( - asmFileName, - publicKey, - null, - asmVersion, - null, - AssemblyHashAlgorithm.None, - AssemblyVersionCompatibility.SameMachine, - null, - asmNameFlags, - keyPair); - - return AsmName; - } - - private static void UpdateComTypesInAssembly(AssemblyBuilder asmBldr, ModuleBuilder modBldr) - { - // Retrieve the AssemblyBuilderData associated with the assembly builder. - AssemblyBuilderData AsmBldrData = asmBldr.m_assemblyData; - - // Go through the types in the module and add them as public COM types. - Type[] aTypes = modBldr.GetTypes(); - int NumTypes = aTypes.Length; - for (int cTypes = 0; cTypes < NumTypes; cTypes++) - AsmBldrData.AddPublicComType(aTypes[cTypes]); - } - - - [System.Security.SecurityCritical] // auto-generated - private static void SetGuidAttributeOnAssembly(AssemblyBuilder asmBldr, Object typeLib) - { - // Retrieve the GuidAttribute constructor. - Type []aConsParams = new Type[1] {typeof(String)}; - ConstructorInfo GuidAttrCons = typeof(GuidAttribute).GetConstructor(aConsParams); - - // Create an instance of the custom attribute builder. - Object[] aArgs = new Object[1] {Marshal.GetTypeLibGuid((ITypeLib)typeLib).ToString()}; - CustomAttributeBuilder GuidCABuilder = new CustomAttributeBuilder(GuidAttrCons, aArgs); - - // Set the GuidAttribute on the assembly builder. - asmBldr.SetCustomAttribute(GuidCABuilder); - } - - [System.Security.SecurityCritical] // auto-generated - private static void SetImportedFromTypeLibAttrOnAssembly(AssemblyBuilder asmBldr, Object typeLib) - { - // Retrieve the ImportedFromTypeLibAttribute constructor. - Type []aConsParams = new Type[1] {typeof(String)}; - ConstructorInfo ImpFromComAttrCons = typeof(ImportedFromTypeLibAttribute).GetConstructor(aConsParams); - - // Retrieve the name of the typelib. - String strTypeLibName = Marshal.GetTypeLibName((ITypeLib)typeLib); - - // Create an instance of the custom attribute builder. - Object[] aArgs = new Object[1] {strTypeLibName}; - CustomAttributeBuilder ImpFromComCABuilder = new CustomAttributeBuilder(ImpFromComAttrCons, aArgs); - - // Set the ImportedFromTypeLibAttribute on the assembly builder. - asmBldr.SetCustomAttribute(ImpFromComCABuilder); - } - - [System.Security.SecurityCritical] // auto-generated - private static void SetTypeLibVersionAttribute(AssemblyBuilder asmBldr, Object typeLib) - { - Type []aConsParams = new Type[2] {typeof(int), typeof(int)}; - ConstructorInfo TypeLibVerCons = typeof(TypeLibVersionAttribute).GetConstructor(aConsParams); - - // Get the typelib version - int major; - int minor; - Marshal.GetTypeLibVersion((ITypeLib)typeLib, out major, out minor); - - // Create an instance of the custom attribute builder. - Object[] aArgs = new Object[2] {major, minor}; - CustomAttributeBuilder TypeLibVerBuilder = new CustomAttributeBuilder(TypeLibVerCons, aArgs); - - // Set the attribute on the assembly builder. - asmBldr.SetCustomAttribute(TypeLibVerBuilder); - } - - [System.Security.SecurityCritical] // auto-generated - private static void SetVersionInformation(AssemblyBuilder asmBldr, Object typeLib, AssemblyName asmName) - { - // Extract the name of the typelib. - String strTypeLibName = null; - String strDocString = null; - int dwHelpContext = 0; - String strHelpFile = null; - ITypeLib pTLB = (ITypeLib)typeLib; - pTLB.GetDocumentation(-1, out strTypeLibName, out strDocString, out dwHelpContext, out strHelpFile); - - // Generate the product name string from the named of the typelib. - String strProductName = String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("TypeLibConverter_ImportedTypeLibProductName"), strTypeLibName); - - // Set the OS version information. - asmBldr.DefineVersionInfoResource(strProductName, asmName.Version.ToString(), null, null, null); - - // Set the TypeLibVersion attribute - SetTypeLibVersionAttribute(asmBldr, typeLib); - } - - [System.Security.SecurityCritical] // auto-generated - private static void SetPIAAttributeOnAssembly(AssemblyBuilder asmBldr, Object typeLib) - { - IntPtr pAttr = IntPtr.Zero; - _TYPELIBATTR Attr; - ITypeLib pTLB = (ITypeLib)typeLib; - int Major = 0; - int Minor = 0; - - // Retrieve the PrimaryInteropAssemblyAttribute constructor. - Type []aConsParams = new Type[2] {typeof(int), typeof(int)}; - ConstructorInfo PIAAttrCons = typeof(PrimaryInteropAssemblyAttribute).GetConstructor(aConsParams); - - // Retrieve the major and minor version from the typelib. - try - { - pTLB.GetLibAttr(out pAttr); - Attr = (_TYPELIBATTR)Marshal.PtrToStructure(pAttr, typeof(_TYPELIBATTR)); - Major = Attr.wMajorVerNum; - Minor = Attr.wMinorVerNum; - } - finally - { - // Release the typelib attributes. - if (pAttr != IntPtr.Zero) - pTLB.ReleaseTLibAttr(pAttr); - } - - // Create an instance of the custom attribute builder. - Object[] aArgs = new Object[2] {Major, Minor}; - CustomAttributeBuilder PIACABuilder = new CustomAttributeBuilder(PIAAttrCons, aArgs); - - // Set the PrimaryInteropAssemblyAttribute on the assembly builder. - asmBldr.SetCustomAttribute(PIACABuilder); - } - - - // - // Native helper methods. - // - - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern void nConvertTypeLibToMetadata(Object typeLib, RuntimeAssembly asmBldr, RuntimeModule modBldr, String nameSpace, TypeLibImporterFlags flags, ITypeLibImporterNotifySink notifySink, out ArrayList eventItfInfoList); - - // Must use assembly versioning or GuidAttribute to avoid collisions in typelib export or registration. - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern Object nConvertAssemblyToTypeLib(RuntimeAssembly assembly, String strTypeLibName, TypeLibExporterFlags flags, ITypeLibExporterNotifySink notifySink); - - [System.Security.SecurityCritical] // auto-generated - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] - internal extern static void LoadInMemoryTypeByName(RuntimeModule module, String className); - - // - // Helper class called when a resolve type event is fired. - // - - private class TypeResolveHandler : ITypeLibImporterNotifySink - { - public TypeResolveHandler(ModuleBuilder mod, ITypeLibImporterNotifySink userSink) - { - m_Module = mod; - m_UserSink = userSink; - } - - public void ReportEvent(ImporterEventKind eventKind, int eventCode, String eventMsg) - { - m_UserSink.ReportEvent(eventKind, eventCode, eventMsg); - } - - public Assembly ResolveRef(Object typeLib) - { - Contract.Ensures(Contract.Result() != null && Contract.Result() is RuntimeAssembly); - Contract.EndContractBlock(); - - // Call the user sink to resolve the reference. - Assembly asm = m_UserSink.ResolveRef(typeLib); - - if (asm == null) - throw new ArgumentNullException(); - - // Return the resolved assembly. We extract the internal assembly because we are called - // by the VM which accesses fields of the object directly and does not go via those - // delegating properties (the fields are empty if asm is an (external) AssemblyBuilder). - - RuntimeAssembly rtAssembly = asm as RuntimeAssembly; - if (rtAssembly == null) - { - AssemblyBuilder ab = asm as AssemblyBuilder; - if (ab != null) - rtAssembly = ab.InternalAssembly; - } - - if (rtAssembly == null) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly")); - - // Add the assembly to the list of assemblies. - m_AsmList.Add(rtAssembly); - - return rtAssembly; - } - - [System.Security.SecurityCritical] // auto-generated - public Assembly ResolveEvent(Object sender, ResolveEventArgs args) - { - // We need to load the type in the resolve event so that we will deal with - // cases where we are trying to load the CoClass before the interface has - // been loaded. - try - { - LoadInMemoryTypeByName(m_Module.GetNativeHandle(), args.Name); - return m_Module.Assembly; - } - catch (TypeLoadException e) - { - if (e.ResourceId != System.__HResults.COR_E_TYPELOAD) // type not found - throw; - } - - foreach (RuntimeAssembly asm in m_AsmList) - { - try - { - asm.GetType(args.Name, true, false); - return asm; - } - catch (TypeLoadException e) - { - if (e._HResult != System.__HResults.COR_E_TYPELOAD) // type not found - throw; - } - } - - return null; - } - - public Assembly ResolveAsmEvent(Object sender, ResolveEventArgs args) - { - foreach (RuntimeAssembly asm in m_AsmList) - { - if (String.Compare(asm.FullName, args.Name, StringComparison.OrdinalIgnoreCase) == 0) - return asm; - } - - return null; - } - - public Assembly ResolveROAsmEvent(Object sender, ResolveEventArgs args) - { - foreach (RuntimeAssembly asm in m_AsmList) - { - if (String.Compare(asm.FullName, args.Name, StringComparison.OrdinalIgnoreCase) == 0) - return asm; - } - - // We failed to find the referenced assembly in our pre-loaded assemblies, so try to load it based on policy. - string asmName = AppDomain.CurrentDomain.ApplyPolicy(args.Name); - return Assembly.ReflectionOnlyLoad(asmName); - } - - private ModuleBuilder m_Module; - private ITypeLibImporterNotifySink m_UserSink; - private List m_AsmList = new List(); - } - } -} -#endif // !FEATURE_CORECLR // current implementation requires reflection only load - diff --git a/src/mscorlib/src/System/Runtime/InteropServices/Variant.cs b/src/mscorlib/src/System/Runtime/InteropServices/Variant.cs index 9be1588..c7bbb78 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/Variant.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/Variant.cs @@ -11,7 +11,6 @@ namespace System.Runtime.InteropServices { /// to and from COM calls. /// [StructLayout(LayoutKind.Explicit)] - [System.Security.SecurityCritical] internal struct Variant { #if DEBUG diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToCollectionAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToCollectionAdapter.cs index 5574f3c..e3c6a92 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToCollectionAdapter.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToCollectionAdapter.cs @@ -9,6 +9,7 @@ using System.Runtime; using System.Security; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; @@ -27,12 +28,11 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private BindableVectorToCollectionAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } // int Count { get } [Pure] - [SecurityCritical] internal int Count() { IBindableVector _this = JitHelpers.UnsafeCast(this); @@ -47,7 +47,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime // bool IsSynchronized { get } [Pure] - [SecurityCritical] internal bool IsSynchronized() { return false; @@ -55,7 +54,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime // object SyncRoot { get } [Pure] - [SecurityCritical] internal object SyncRoot() { return this; @@ -63,11 +61,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime // void CopyTo(Array array, int index) [Pure] - [SecurityCritical] internal void CopyTo(Array array, int arrayIndex) { if (array == null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); // ICollection expects the destination array to be single-dimensional. if (array.Rank != 1) @@ -79,7 +76,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime int destLen = array.GetLength(0); if (arrayIndex < destLB) - throw new ArgumentOutOfRangeException("arrayIndex"); + throw new ArgumentOutOfRangeException(nameof(arrayIndex)); // Does the dimension in question have sufficient space to copy the expected number of entries? // We perform this check before valid index check to ensure the exception message is in sync with diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToListAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToListAdapter.cs index 73ebf72..d6e50f5 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToListAdapter.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToListAdapter.cs @@ -9,6 +9,7 @@ using System.Runtime; using System.Security; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; @@ -27,33 +28,30 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private BindableVectorToListAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } // object this[int index] { get } - [SecurityCritical] internal object Indexer_Get(int index) { if (index < 0) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); IBindableVector _this = JitHelpers.UnsafeCast(this); return GetAt(_this, (uint)index); } // object this[int index] { set } - [SecurityCritical] internal void Indexer_Set(int index, object value) { if (index < 0) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); IBindableVector _this = JitHelpers.UnsafeCast(this); SetAt(_this, (uint)index, value); } // int Add(object value) - [SecurityCritical] internal int Add(object value) { IBindableVector _this = JitHelpers.UnsafeCast(this); @@ -69,7 +67,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // bool Contains(object item) - [SecurityCritical] internal bool Contains(object item) { IBindableVector _this = JitHelpers.UnsafeCast(this); @@ -79,7 +76,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void Clear() - [SecurityCritical] internal void Clear() { IBindableVector _this = JitHelpers.UnsafeCast(this); @@ -88,7 +84,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime // bool IsFixedSize { get } [Pure] - [SecurityCritical] internal bool IsFixedSize() { return false; @@ -96,14 +91,12 @@ namespace System.Runtime.InteropServices.WindowsRuntime // bool IsReadOnly { get } [Pure] - [SecurityCritical] internal bool IsReadOnly() { return false; } // int IndexOf(object item) - [SecurityCritical] internal int IndexOf(object item) { IBindableVector _this = JitHelpers.UnsafeCast(this); @@ -123,18 +116,16 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void Insert(int index, object item) - [SecurityCritical] internal void Insert(int index, object item) { if (index < 0) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); IBindableVector _this = JitHelpers.UnsafeCast(this); InsertAtHelper(_this, (uint)index, item); } // bool Remove(object item) - [SecurityCritical] internal void Remove(object item) { IBindableVector _this = JitHelpers.UnsafeCast(this); @@ -154,11 +145,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void RemoveAt(int index) - [SecurityCritical] internal void RemoveAt(int index) { if (index < 0) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); IBindableVector _this = JitHelpers.UnsafeCast(this); RemoveAtHelper(_this, (uint)index); @@ -178,7 +168,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime catch (Exception ex) { if (__HResults.E_BOUNDS == ex._HResult) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); throw; } @@ -196,7 +186,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime catch (Exception ex) { if (__HResults.E_BOUNDS == ex._HResult) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); throw; } @@ -214,7 +204,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime catch (Exception ex) { if (__HResults.E_BOUNDS == ex._HResult) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); throw; } @@ -232,7 +222,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime catch (Exception ex) { if (__HResults.E_BOUNDS == ex._HResult) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); throw; } diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIPropertyValueImpl.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIPropertyValueImpl.cs index c88f13d..702e0c9 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIPropertyValueImpl.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIPropertyValueImpl.cs @@ -184,7 +184,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } [Pure] - [SecuritySafeCritical] public Point GetPoint() { if (this.Type != PropertyType.Point) @@ -195,7 +194,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } [Pure] - [SecuritySafeCritical] public Size GetSize() { if (this.Type != PropertyType.Size) @@ -206,7 +204,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } [Pure] - [SecuritySafeCritical] public Rect GetRect() { if (this.Type != PropertyType.Rect) @@ -328,7 +325,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } [Pure] - [SecuritySafeCritical] public Point[] GetPointArray() { if (this.Type != PropertyType.PointArray) @@ -339,7 +335,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } [Pure] - [SecuritySafeCritical] public Size[] GetSizeArray() { if (this.Type != PropertyType.SizeArray) @@ -351,7 +346,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } [Pure] - [SecuritySafeCritical] public Rect[] GetRectArray() { if (this.Type != PropertyType.RectArray) @@ -505,7 +499,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime // Unbox the data stored in the property value to a structurally equivilent type [Pure] - [SecurityCritical] private unsafe T Unbox(Type expectedBoxedType) where T : struct { Contract.Requires(expectedBoxedType != null); Contract.Requires(Marshal.SizeOf(expectedBoxedType) == Marshal.SizeOf(typeof(T))); @@ -526,7 +519,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime // Convert the array stored in the property value to a structurally equivilent array type [Pure] - [SecurityCritical] private unsafe T[] UnboxArray(Type expectedArrayElementType) where T : struct { Contract.Requires(expectedArrayElementType != null); Contract.Requires(Marshal.SizeOf(expectedArrayElementType) == Marshal.SizeOf(typeof(T))); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIReferenceImpl.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIReferenceImpl.cs index e379d38..9705b61 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIReferenceImpl.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIReferenceImpl.cs @@ -6,6 +6,7 @@ using System; using System.Collections; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Reflection; using System.Security; @@ -55,7 +56,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime { Contract.Requires(wrapper != null); IReference reference = (IReference) wrapper; - Contract.Assert(reference != null, "CLRIReferenceImpl::UnboxHelper - QI'ed for IReference<"+typeof(T)+">, but that failed."); + Debug.Assert(reference != null, "CLRIReferenceImpl::UnboxHelper - QI'ed for IReference<"+typeof(T)+">, but that failed."); return reference.Value; } } @@ -216,7 +217,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime { Contract.Requires(wrapper != null); IReferenceArray reference = (IReferenceArray)wrapper; - Contract.Assert(reference != null, "CLRIReferenceArrayImpl::UnboxHelper - QI'ed for IReferenceArray<" + typeof(T) + ">, but that failed."); + Debug.Assert(reference != null, "CLRIReferenceArrayImpl::UnboxHelper - QI'ed for IReferenceArray<" + typeof(T) + ">, but that failed."); T[] marshaled = reference.Value; return marshaled; } @@ -229,7 +230,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime internal static readonly Type s_rectType = Type.GetType("Windows.Foundation.Rect, " + AssemblyRef.SystemRuntimeWindowsRuntime); internal static readonly Type s_sizeType = Type.GetType("Windows.Foundation.Size, " + AssemblyRef.SystemRuntimeWindowsRuntime); - [SecuritySafeCritical] internal static Object CreateIReference(Object obj) { Contract.Requires(obj != null, "Null should not be boxed."); @@ -302,11 +302,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime return Activator.CreateInstance(specificType, new Object[] { propType.Value, obj }); } - Contract.Assert(false, "We should not see non-WinRT type here"); + Debug.Assert(false, "We should not see non-WinRT type here"); return null; } - [SecuritySafeCritical] internal static Object CreateIReferenceArray(Array obj) { Contract.Requires(obj != null); @@ -315,7 +314,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime Type type = obj.GetType().GetElementType(); - Contract.Assert(obj.Rank == 1 && obj.GetLowerBound(0) == 0 && !type.IsArray); + Debug.Assert(obj.Rank == 1 && obj.GetLowerBound(0) == 0 && !type.IsArray); if (type == typeof(int)) return new CLRIReferenceArrayImpl(PropertyType.Int32Array, (int[])obj); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ConstantSplittableMap.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ConstantSplittableMap.cs index af1381c..a5abb4f 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ConstantSplittableMap.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ConstantSplittableMap.cs @@ -45,7 +45,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime internal ConstantSplittableMap(IReadOnlyDictionary data) { if (data == null) - throw new ArgumentNullException("data"); + throw new ArgumentNullException(nameof(data)); Contract.EndContractBlock(); this.firstItemIndex = 0; @@ -56,7 +56,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime internal ConstantSplittableMap(IMapView data) { if (data == null) - throw new ArgumentNullException("data"); + throw new ArgumentNullException(nameof(data)); if (((UInt32)Int32.MaxValue) < data.Size) { diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CustomPropertyImpl.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CustomPropertyImpl.cs index 04fe1bf..d575201 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CustomPropertyImpl.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CustomPropertyImpl.cs @@ -7,6 +7,7 @@ using System; using System.Security; using System.Reflection; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; @@ -29,7 +30,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime public CustomPropertyImpl(PropertyInfo propertyInfo) { if (propertyInfo == null) - throw new ArgumentNullException("propertyInfo"); + throw new ArgumentNullException(nameof(propertyInfo)); m_property = propertyInfo; } @@ -88,7 +89,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime InvokeInternal(target, new object[] { indexValue, value }, false); } - [SecuritySafeCritical] private object InvokeInternal(object target, object[] args, bool getValue) { // Forward to the right object if we are dealing with a proxy @@ -123,7 +123,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime // We can safely skip access check because this is only used in full trust scenarios. // And we have already verified that the property accessor is public. - Contract.Assert(AppDomain.CurrentDomain.PermissionSet.IsUnrestricted()); + Debug.Assert(AppDomain.CurrentDomain.PermissionSet.IsUnrestricted()); return rtMethod.UnsafeInvoke(target, BindingFlags.Default, null, args, null); } diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryKeyCollection.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryKeyCollection.cs index c1586ee..c33e002 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryKeyCollection.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryKeyCollection.cs @@ -18,7 +18,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime public DictionaryKeyCollection(IDictionary dictionary) { if (dictionary == null) - throw new ArgumentNullException("dictionary"); + throw new ArgumentNullException(nameof(dictionary)); this.dictionary = dictionary; } @@ -26,9 +26,9 @@ namespace System.Runtime.InteropServices.WindowsRuntime public void CopyTo(TKey[] array, int index) { if (array == null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); if (index < 0) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); if (array.Length <= index && this.Count > 0) throw new ArgumentException(Environment.GetResourceString("Arg_IndexOutOfRangeException")); if (array.Length - index < dictionary.Count) @@ -90,7 +90,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime public DictionaryKeyEnumerator(IDictionary dictionary) { if (dictionary == null) - throw new ArgumentNullException("dictionary"); + throw new ArgumentNullException(nameof(dictionary)); this.dictionary = dictionary; this.enumeration = dictionary.GetEnumerator(); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryToMapAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryToMapAdapter.cs index fa021b7..24e5777 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryToMapAdapter.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryToMapAdapter.cs @@ -10,6 +10,7 @@ using System.Reflection; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; @@ -28,11 +29,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private DictionaryToMapAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } // V Lookup(K key) - [SecurityCritical] internal V Lookup(K key) { IDictionary _this = JitHelpers.UnsafeCast>(this); @@ -50,7 +50,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // uint Size { get } - [SecurityCritical] internal uint Size() { IDictionary _this = JitHelpers.UnsafeCast>(this); @@ -58,7 +57,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // bool HasKey(K key) - [SecurityCritical] internal bool HasKey(K key) { IDictionary _this = JitHelpers.UnsafeCast>(this); @@ -66,11 +64,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // IMapView GetView() - [SecurityCritical] internal IReadOnlyDictionary GetView() { IDictionary _this = JitHelpers.UnsafeCast>(this); - Contract.Assert(_this != null); + Debug.Assert(_this != null); // Note: This dictionary is not really read-only - you could QI for a modifiable // dictionary. We gain some perf by doing this. We believe this is acceptable. @@ -83,7 +80,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // bool Insert(K key, V value) - [SecurityCritical] internal bool Insert(K key, V value) { IDictionary _this = JitHelpers.UnsafeCast>(this); @@ -93,7 +89,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void Remove(K key) - [SecurityCritical] internal void Remove(K key) { IDictionary _this = JitHelpers.UnsafeCast>(this); @@ -108,7 +103,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void Clear() - [SecurityCritical] internal void Clear() { IDictionary _this = JitHelpers.UnsafeCast>(this); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryValueCollection.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryValueCollection.cs index 03e897a..fcc7755 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryValueCollection.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryValueCollection.cs @@ -21,7 +21,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime { public DictionaryValueCollection(IDictionary dictionary) { if (dictionary == null) - throw new ArgumentNullException("dictionary"); + throw new ArgumentNullException(nameof(dictionary)); this.dictionary = dictionary; } @@ -29,9 +29,9 @@ namespace System.Runtime.InteropServices.WindowsRuntime { public void CopyTo(TValue[] array, int index) { if (array == null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); if (index < 0) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); if (array.Length <= index && this.Count > 0) throw new ArgumentException(Environment.GetResourceString("Arg_IndexOutOfRangeException")); if (array.Length - index < dictionary.Count) @@ -97,7 +97,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime { public DictionaryValueEnumerator(IDictionary dictionary) { if (dictionary == null) - throw new ArgumentNullException("dictionary"); + throw new ArgumentNullException(nameof(dictionary)); this.dictionary = dictionary; this.enumeration = dictionary.GetEnumerator(); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EnumeratorToIteratorAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EnumeratorToIteratorAdapter.cs index 7329d31..3f9d516 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EnumeratorToIteratorAdapter.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EnumeratorToIteratorAdapter.cs @@ -7,6 +7,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; @@ -25,11 +26,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private EnumerableToIterableAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } // This method is invoked when First is called on a managed implementation of IIterable. - [System.Security.SecurityCritical] internal IIterator First_Stub() { IEnumerable _this = JitHelpers.UnsafeCast>(this); @@ -41,7 +41,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private EnumerableToBindableIterableAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } internal sealed class NonGenericToGenericEnumerator : IEnumerator @@ -58,7 +58,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // This method is invoked when First is called on a managed implementation of IBindableIterable. - [System.Security.SecurityCritical] internal IBindableIterator First_Stub() { IEnumerable _this = JitHelpers.UnsafeCast(this); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IClosable.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IClosable.cs index 847147a..4c6169a 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IClosable.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IClosable.cs @@ -7,6 +7,7 @@ using System; using System.Security; using System.Collections; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.CompilerServices; @@ -27,10 +28,9 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private IDisposableToIClosableAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } - [SecurityCritical] public void Close() { IDisposable _this = JitHelpers.UnsafeCast(this); @@ -39,15 +39,13 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // Adapter class which converts IDisposable.Dispose calls into IClosable.Close - [SecurityCritical] internal sealed class IClosableToIDisposableAdapter { private IClosableToIDisposableAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } - [SecurityCritical] private void Dispose() { IClosable _this = JitHelpers.UnsafeCast(this); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomPropertyProvider.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomPropertyProvider.cs index 143a33e..3bbde35 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomPropertyProvider.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomPropertyProvider.cs @@ -50,7 +50,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime // Creates a ICustomProperty implementation for Jupiter // Called from ICustomPropertyProvider_GetIndexedProperty from within runtime // - [System.Security.SecurityCritical] static internal unsafe ICustomProperty CreateIndexedProperty(object target, string propertyName, TypeNameNative *pIndexedParamType) { Contract.Requires(target != null); @@ -87,7 +86,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime return new CustomPropertyImpl(propertyInfo); } - [System.Security.SecurityCritical] static internal unsafe void GetType(object target, TypeNameNative *pIndexedParamType) { IGetProxyTarget proxy = target as IGetProxyTarget; @@ -207,7 +205,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime // // ICustomQueryInterface methods // - [System.Security.SecurityCritical] public CustomQueryInterfaceResult GetInterface([In]ref Guid iid, out IntPtr ppv) { ppv = IntPtr.Zero; @@ -441,7 +438,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } } - [SecuritySafeCritical] private IBindableVector GetIBindableVectorNoThrow() { if ((_flags & InterfaceForwardingSupport.IBindableVector) != 0) @@ -450,7 +446,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime return null; } - [SecuritySafeCritical] private IVector_Raw GetVectorOfT() { if ((_flags & InterfaceForwardingSupport.IVector) != 0) @@ -517,7 +512,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime public bool MoveNext() { return _iterator.MoveNext(); } } - [SecuritySafeCritical] private IBindableVectorView GetIBindableVectorViewNoThrow() { if ((_flags & InterfaceForwardingSupport.IBindableVectorView) != 0) @@ -526,7 +520,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime return null; } - [SecuritySafeCritical] private IVectorView GetVectorViewOfT() { if ((_flags & InterfaceForwardingSupport.IVectorView) != 0) diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs index 3600a3a..a7424da 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs @@ -28,15 +28,14 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private IMapViewToIReadOnlyDictionaryAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } // V this[K key] { get } - [SecurityCritical] internal V Indexer_Get(K key) { if (key == null) - throw new ArgumentNullException("key"); + throw new ArgumentNullException(nameof(key)); Contract.EndContractBlock(); IMapView _this = JitHelpers.UnsafeCast>(this); @@ -44,7 +43,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // IEnumerable Keys { get } - [SecurityCritical] internal IEnumerable Keys() { IMapView _this = JitHelpers.UnsafeCast>(this); @@ -53,7 +51,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // IEnumerable Values { get } - [SecurityCritical] internal IEnumerable Values() { IMapView _this = JitHelpers.UnsafeCast>(this); @@ -63,22 +60,20 @@ namespace System.Runtime.InteropServices.WindowsRuntime // bool ContainsKey(K key) [Pure] - [SecurityCritical] internal bool ContainsKey(K key) { if (key == null) - throw new ArgumentNullException("key"); + throw new ArgumentNullException(nameof(key)); IMapView _this = JitHelpers.UnsafeCast>(this); return _this.HasKey(key); } // bool TryGetValue(TKey key, out TValue value) - [SecurityCritical] internal bool TryGetValue(K key, out V value) { if (key == null) - throw new ArgumentNullException("key"); + throw new ArgumentNullException(nameof(key)); IMapView _this = JitHelpers.UnsafeCast>(this); @@ -137,7 +132,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime public ReadOnlyDictionaryKeyCollection(IReadOnlyDictionary dictionary) { if (dictionary == null) - throw new ArgumentNullException("dictionary"); + throw new ArgumentNullException(nameof(dictionary)); this.dictionary = dictionary; } @@ -146,9 +141,9 @@ namespace System.Runtime.InteropServices.WindowsRuntime public void CopyTo(TKey[] array, int index) { if (array == null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); if (index < 0) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); if (array.Length <= index && this.Count > 0) throw new ArgumentException(Environment.GetResourceString("Arg_IndexOutOfRangeException")); if (array.Length - index < dictionary.Count) @@ -192,7 +187,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime public ReadOnlyDictionaryKeyEnumerator(IReadOnlyDictionary dictionary) { if (dictionary == null) - throw new ArgumentNullException("dictionary"); + throw new ArgumentNullException(nameof(dictionary)); this.dictionary = dictionary; this.enumeration = dictionary.GetEnumerator(); @@ -232,7 +227,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime public ReadOnlyDictionaryValueCollection(IReadOnlyDictionary dictionary) { if (dictionary == null) - throw new ArgumentNullException("dictionary"); + throw new ArgumentNullException(nameof(dictionary)); this.dictionary = dictionary; } @@ -241,9 +236,9 @@ namespace System.Runtime.InteropServices.WindowsRuntime public void CopyTo(TValue[] array, int index) { if (array == null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); if (index < 0) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); if (array.Length <= index && this.Count > 0) throw new ArgumentException(Environment.GetResourceString("Arg_IndexOutOfRangeException")); if (array.Length - index < dictionary.Count) @@ -291,7 +286,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime public ReadOnlyDictionaryValueEnumerator(IReadOnlyDictionary dictionary) { if (dictionary == null) - throw new ArgumentNullException("dictionary"); + throw new ArgumentNullException(nameof(dictionary)); this.dictionary = dictionary; this.enumeration = dictionary.GetEnumerator(); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyDictionaryToIMapViewAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyDictionaryToIMapViewAdapter.cs index d57f8f1..b185b41 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyDictionaryToIMapViewAdapter.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyDictionaryToIMapViewAdapter.cs @@ -28,11 +28,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private IReadOnlyDictionaryToIMapViewAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } // V Lookup(K key) - [SecurityCritical] internal V Lookup(K key) { IReadOnlyDictionary _this = JitHelpers.UnsafeCast>(this); @@ -50,7 +49,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // uint Size { get } - [SecurityCritical] internal uint Size() { IReadOnlyDictionary _this = JitHelpers.UnsafeCast>(this); @@ -58,7 +56,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // bool HasKey(K key) - [SecurityCritical] internal bool HasKey(K key) { IReadOnlyDictionary _this = JitHelpers.UnsafeCast>(this); @@ -66,7 +63,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void Split(out IMapView first, out IMapView second) - [SecurityCritical] internal void Split(out IMapView first, out IMapView second) { IReadOnlyDictionary _this = JitHelpers.UnsafeCast>(this); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyListToIVectorViewAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyListToIVectorViewAdapter.cs index 95780bc..431d162 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyListToIVectorViewAdapter.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyListToIVectorViewAdapter.cs @@ -28,11 +28,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private IReadOnlyListToIVectorViewAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } // T GetAt(uint index) - [SecurityCritical] internal T GetAt(uint index) { IReadOnlyList _this = JitHelpers.UnsafeCast>(this); @@ -50,7 +49,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // uint Size { get } - [SecurityCritical] internal uint Size() { IReadOnlyList _this = JitHelpers.UnsafeCast>(this); @@ -58,7 +56,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // bool IndexOf(T value, out uint index) - [SecurityCritical] internal bool IndexOf(T value, out uint index) { IReadOnlyList _this = JitHelpers.UnsafeCast>(this); @@ -85,7 +82,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // uint GetMany(uint startIndex, T[] items) - [SecurityCritical] internal uint GetMany(uint startIndex, T[] items) { IReadOnlyList _this = JitHelpers.UnsafeCast>(this); @@ -130,7 +126,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime // that Size > Int32.MaxValue: if (((uint)Int32.MaxValue) <= index || index >= (uint)listCapacity) { - Exception e = new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_IndexLargerThanMaxValue")); + Exception e = new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_IndexLargerThanMaxValue")); e.SetErrorCode(__HResults.E_BOUNDS); throw e; } diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IRestrictedErrorInfo.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IRestrictedErrorInfo.cs index 48bcc4f..9de5e3f 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IRestrictedErrorInfo.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IRestrictedErrorInfo.cs @@ -8,9 +8,7 @@ using System; namespace System.Runtime.InteropServices.WindowsRuntime { -#if FEATURE_CORECLR [System.Runtime.CompilerServices.FriendAccessAllowed] -#endif [ComImport] [Guid("82BA7092-4C88-427D-A7BC-16DD93FEB67E")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IVectorViewToIReadOnlyListAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IVectorViewToIReadOnlyListAdapter.cs index 72d6fa8..37f2130 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IVectorViewToIReadOnlyListAdapter.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IVectorViewToIReadOnlyListAdapter.cs @@ -30,15 +30,14 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private IVectorViewToIReadOnlyListAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } // T this[int index] { get } - [SecurityCritical] internal T Indexer_Get(int index) { if (index < 0) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); IVectorView _this = JitHelpers.UnsafeCast>(this); @@ -52,14 +51,13 @@ namespace System.Runtime.InteropServices.WindowsRuntime catch (Exception ex) { if (__HResults.E_BOUNDS == ex._HResult) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); throw; } } // T this[int index] { get } - [SecurityCritical] internal T Indexer_Get_Variance(int index) where T : class { bool fUseString; diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IteratorToEnumeratorAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IteratorToEnumeratorAdapter.cs index f1b799a..e219a86 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IteratorToEnumeratorAdapter.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IteratorToEnumeratorAdapter.cs @@ -7,6 +7,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; @@ -28,11 +29,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private IterableToEnumerableAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } // This method is invoked when GetEnumerator is called on a WinRT-backed implementation of IEnumerable. - [SecurityCritical] internal IEnumerator GetEnumerator_Stub() { IIterable _this = JitHelpers.UnsafeCast>(this); @@ -43,7 +43,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime // and it is possible that the implementation supports IEnumerable/IEnumerable/IEnumerable/ // IEnumerable/IEnumerable rather than IEnumerable because T is assignable from Type/string/ // Exception/array/delegate via co-variance. - [SecurityCritical] internal IEnumerator GetEnumerator_Variance_Stub() where T : class { bool fUseString; @@ -70,7 +69,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private BindableIterableToEnumerableAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } private sealed class NonGenericToGenericIterator : IIterator @@ -87,7 +86,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // This method is invoked when GetEnumerator is called on a WinRT-backed implementation of IEnumerable. - [SecurityCritical] internal IEnumerator GetEnumerator_Stub() { IBindableIterable _this = JitHelpers.UnsafeCast(this); @@ -123,10 +121,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime { // The enumerator has not been advanced to the first element yet. if (!m_isInitialized) - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumNotStarted); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumNotStarted(); // The enumerator has reached the end of the collection if (!m_hadCurrent) - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumEnded); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumEnded(); return m_current; } } @@ -137,15 +135,14 @@ namespace System.Runtime.InteropServices.WindowsRuntime { // The enumerator has not been advanced to the first element yet. if (!m_isInitialized) - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumNotStarted); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumNotStarted(); // The enumerator has reached the end of the collection if (!m_hadCurrent) - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumEnded); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumEnded(); return m_current; } } - [SecuritySafeCritical] public bool MoveNext() { // If we've passed the end of the iteration, IEnumerable should return false, while @@ -187,7 +184,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime // Translate E_CHANGED_STATE into an InvalidOperationException for an updated enumeration if (Marshal.GetHRForException(e) == __HResults.E_CHANGED_STATE) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } else { diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorAdapter.cs index 35dc495..b9fe115 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorAdapter.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorAdapter.cs @@ -10,6 +10,7 @@ using System.Reflection; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; @@ -28,11 +29,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private ListToBindableVectorAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } // object GetAt(uint index) - [SecurityCritical] internal object GetAt(uint index) { IList _this = JitHelpers.UnsafeCast(this); @@ -49,7 +49,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // uint Size { get } - [SecurityCritical] internal uint Size() { IList _this = JitHelpers.UnsafeCast(this); @@ -57,7 +56,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // IBindableVectorView GetView() - [SecurityCritical] internal IBindableVectorView GetView() { IList _this = JitHelpers.UnsafeCast(this); @@ -65,7 +63,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // bool IndexOf(object value, out uint index) - [SecurityCritical] internal bool IndexOf(object value, out uint index) { IList _this = JitHelpers.UnsafeCast(this); @@ -82,7 +79,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void SetAt(uint index, object value) - [SecurityCritical] internal void SetAt(uint index, object value) { IList _this = JitHelpers.UnsafeCast(this); @@ -99,7 +95,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void InsertAt(uint index, object value) - [SecurityCritical] internal void InsertAt(uint index, object value) { IList _this = JitHelpers.UnsafeCast(this); @@ -121,7 +116,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void RemoveAt(uint index) - [SecurityCritical] internal void RemoveAt(uint index) { IList _this = JitHelpers.UnsafeCast(this); @@ -140,7 +134,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void Append(object value) - [SecurityCritical] internal void Append(object value) { IList _this = JitHelpers.UnsafeCast(this); @@ -148,7 +141,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void RemoveAtEnd() - [SecurityCritical] internal void RemoveAtEnd() { IList _this = JitHelpers.UnsafeCast(this); @@ -164,7 +156,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void Clear() - [SecurityCritical] internal void Clear() { IList _this = JitHelpers.UnsafeCast(this); @@ -179,7 +170,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime // that Size > Int32.MaxValue: if (((uint)Int32.MaxValue) <= index || index >= (uint)listCapacity) { - Exception e = new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_IndexLargerThanMaxValue")); + Exception e = new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_IndexLargerThanMaxValue")); e.SetErrorCode(__HResults.E_BOUNDS); throw e; } diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorViewAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorViewAdapter.cs index f760576..2e2ea9b 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorViewAdapter.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorViewAdapter.cs @@ -25,7 +25,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime internal ListToBindableVectorViewAdapter(IList list) { if (list == null) - throw new ArgumentNullException("list"); + throw new ArgumentNullException(nameof(list)); Contract.EndContractBlock(); @@ -38,7 +38,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime // that Size > Int32.MaxValue: if (((uint)Int32.MaxValue) <= index || index >= (uint)listCapacity) { - Exception e = new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_IndexLargerThanMaxValue")); + Exception e = new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_IndexLargerThanMaxValue")); e.SetErrorCode(__HResults.E_BOUNDS); throw e; } diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToVectorAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToVectorAdapter.cs index 77f3a94..b73f4d7 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToVectorAdapter.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToVectorAdapter.cs @@ -10,6 +10,7 @@ using System.Reflection; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; @@ -28,11 +29,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private ListToVectorAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } // T GetAt(uint index) - [SecurityCritical] internal T GetAt(uint index) { IList _this = JitHelpers.UnsafeCast>(this); @@ -49,7 +49,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // uint Size { get } - [SecurityCritical] internal uint Size() { IList _this = JitHelpers.UnsafeCast>(this); @@ -57,11 +56,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // IVectorView GetView() - [SecurityCritical] internal IReadOnlyList GetView() { IList _this = JitHelpers.UnsafeCast>(this); - Contract.Assert(_this != null); + Debug.Assert(_this != null); // Note: This list is not really read-only - you could QI for a modifiable // list. We gain some perf by doing this. We believe this is acceptable. @@ -74,7 +72,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // bool IndexOf(T value, out uint index) - [SecurityCritical] internal bool IndexOf(T value, out uint index) { IList _this = JitHelpers.UnsafeCast>(this); @@ -91,7 +88,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void SetAt(uint index, T value) - [SecurityCritical] internal void SetAt(uint index, T value) { IList _this = JitHelpers.UnsafeCast>(this); @@ -108,7 +104,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void InsertAt(uint index, T value) - [SecurityCritical] internal void InsertAt(uint index, T value) { IList _this = JitHelpers.UnsafeCast>(this); @@ -130,7 +125,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void RemoveAt(uint index) - [SecurityCritical] internal void RemoveAt(uint index) { IList _this = JitHelpers.UnsafeCast>(this); @@ -149,7 +143,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void Append(T value) - [SecurityCritical] internal void Append(T value) { IList _this = JitHelpers.UnsafeCast>(this); @@ -157,7 +150,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void RemoveAtEnd() - [SecurityCritical] internal void RemoveAtEnd() { IList _this = JitHelpers.UnsafeCast>(this); @@ -173,7 +165,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void Clear() - [SecurityCritical] internal void Clear() { IList _this = JitHelpers.UnsafeCast>(this); @@ -181,7 +172,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // uint GetMany(uint startIndex, T[] items) - [SecurityCritical] internal uint GetMany(uint startIndex, T[] items) { IList _this = JitHelpers.UnsafeCast>(this); @@ -189,7 +179,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void ReplaceAll(T[] items) - [SecurityCritical] internal void ReplaceAll(T[] items) { IList _this = JitHelpers.UnsafeCast>(this); @@ -212,7 +201,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime // that Size > Int32.MaxValue: if (((uint)Int32.MaxValue) <= index || index >= (uint)listCapacity) { - Exception e = new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_IndexLargerThanMaxValue")); + Exception e = new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_IndexLargerThanMaxValue")); e.SetErrorCode(__HResults.E_BOUNDS); throw e; } diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ManagedActivationFactory.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ManagedActivationFactory.cs index 3e93428..2d08cab 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ManagedActivationFactory.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ManagedActivationFactory.cs @@ -33,16 +33,15 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private Type m_type; - [SecurityCritical] internal ManagedActivationFactory(Type type) { if (type == null) - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); // Check whether the type is "exported to WinRT", i.e. it is declared in a managed .winmd and is decorated // with at least one ActivatableAttribute or StaticAttribute. if (!(type is RuntimeType) || !type.IsExportedToWindowsRuntime) - throw new ArgumentException(Environment.GetResourceString("Argument_TypeNotActivatableViaWindowsRuntime", type), "type"); + throw new ArgumentException(Environment.GetResourceString("Argument_TypeNotActivatableViaWindowsRuntime", type), nameof(type)); m_type = type; } diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapToCollectionAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapToCollectionAdapter.cs index 395bef9..f11260e 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapToCollectionAdapter.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapToCollectionAdapter.cs @@ -8,6 +8,7 @@ using System; using System.Security; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; @@ -29,12 +30,11 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private MapToCollectionAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } // int Count { get } [Pure] - [SecurityCritical] internal int Count() { object _this = JitHelpers.UnsafeCast(this); @@ -66,14 +66,12 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // bool IsReadOnly { get } - [SecurityCritical] internal bool IsReadOnly() { return false; } // void Add(T item) - [SecurityCritical] internal void Add(KeyValuePair item) { object _this = JitHelpers.UnsafeCast(this); @@ -91,7 +89,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void Clear() - [SecurityCritical] internal void Clear() { object _this = JitHelpers.UnsafeCast(this); @@ -109,7 +106,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // bool Contains(T item) - [SecurityCritical] internal bool Contains(KeyValuePair item) { object _this = JitHelpers.UnsafeCast(this); @@ -135,14 +131,13 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void CopyTo(T[] array, int arrayIndex) - [SecurityCritical] internal void CopyTo(KeyValuePair[] array, int arrayIndex) { if (array == null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); if (arrayIndex < 0) - throw new ArgumentOutOfRangeException("arrayIndex"); + throw new ArgumentOutOfRangeException(nameof(arrayIndex)); if (array.Length <= arrayIndex && Count() > 0) throw new ArgumentException(Environment.GetResourceString("Argument_IndexOutOfArrayBounds")); @@ -160,7 +155,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // bool Remove(T item) - [SecurityCritical] internal bool Remove(KeyValuePair item) { object _this = JitHelpers.UnsafeCast(this); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapToDictionaryAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapToDictionaryAdapter.cs index d7897ce..981972c 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapToDictionaryAdapter.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapToDictionaryAdapter.cs @@ -8,6 +8,7 @@ using System; using System.Security; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; @@ -26,15 +27,14 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private MapToDictionaryAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } // V this[K key] { get } - [SecurityCritical] internal V Indexer_Get(K key) { if (key == null) - throw new ArgumentNullException("key"); + throw new ArgumentNullException(nameof(key)); Contract.EndContractBlock(); @@ -43,11 +43,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // V this[K key] { set } - [SecurityCritical] internal void Indexer_Set(K key, V value) { if (key == null) - throw new ArgumentNullException("key"); + throw new ArgumentNullException(nameof(key)); Contract.EndContractBlock(); @@ -56,7 +55,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // ICollection Keys { get } - [SecurityCritical] internal ICollection Keys() { IMap _this = JitHelpers.UnsafeCast>(this); @@ -65,7 +63,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // ICollection Values { get } - [SecurityCritical] internal ICollection Values() { IMap _this = JitHelpers.UnsafeCast>(this); @@ -75,22 +72,20 @@ namespace System.Runtime.InteropServices.WindowsRuntime // bool ContainsKey(K key) [Pure] - [SecurityCritical] internal bool ContainsKey(K key) { if (key == null) - throw new ArgumentNullException("key"); + throw new ArgumentNullException(nameof(key)); IMap _this = JitHelpers.UnsafeCast>(this); return _this.HasKey(key); } // void Add(K key, V value) - [SecurityCritical] internal void Add(K key, V value) { if (key == null) - throw new ArgumentNullException("key"); + throw new ArgumentNullException(nameof(key)); if (ContainsKey(key)) throw new ArgumentException(Environment.GetResourceString("Argument_AddingDuplicate")); @@ -102,11 +97,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // bool Remove(TKey key) - [SecurityCritical] internal bool Remove(K key) { if (key == null) - throw new ArgumentNullException("key"); + throw new ArgumentNullException(nameof(key)); IMap _this = JitHelpers.UnsafeCast>(this); if (!_this.HasKey(key)) @@ -128,11 +122,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // bool TryGetValue(TKey key, out TValue value) - [SecurityCritical] internal bool TryGetValue(K key, out V value) { if (key == null) - throw new ArgumentNullException("key"); + throw new ArgumentNullException(nameof(key)); IMap _this = JitHelpers.UnsafeCast>(this); if (!_this.HasKey(key)) diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapViewToReadOnlyCollectionAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapViewToReadOnlyCollectionAdapter.cs index 58427fb..a3715da 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapViewToReadOnlyCollectionAdapter.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapViewToReadOnlyCollectionAdapter.cs @@ -8,6 +8,7 @@ using System; using System.Security; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; @@ -29,12 +30,11 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private MapViewToReadOnlyCollectionAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } // int Count { get } [Pure] - [SecurityCritical] internal int Count() { object _this = JitHelpers.UnsafeCast(this); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/NativeMethods.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/NativeMethods.cs index b8cd65e..4380369 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/NativeMethods.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/NativeMethods.cs @@ -22,30 +22,25 @@ namespace System.Runtime.InteropServices.WindowsRuntime internal static class UnsafeNativeMethods { [DllImport("api-ms-win-core-winrt-error-l1-1-1.dll", PreserveSig = false)] - [SecurityCritical] [SuppressUnmanagedCodeSecurity] internal static extern IRestrictedErrorInfo GetRestrictedErrorInfo(); [DllImport("api-ms-win-core-winrt-error-l1-1-1.dll")] - [SecurityCritical] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool RoOriginateLanguageException(int error, [MarshalAs(UnmanagedType.HString)]string message, IntPtr languageException); [DllImport("api-ms-win-core-winrt-error-l1-1-1.dll", PreserveSig = false)] - [SecurityCritical] [SuppressUnmanagedCodeSecurity] internal static extern void RoReportUnhandledError(IRestrictedErrorInfo error); [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] - [SecurityCritical] [SuppressUnmanagedCodeSecurity] internal static unsafe extern int WindowsCreateString([MarshalAs(UnmanagedType.LPWStr)] string sourceString, int length, [Out] IntPtr *hstring); [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] - [SecurityCritical] [SuppressUnmanagedCodeSecurity] internal static unsafe extern int WindowsCreateStringReference(char *sourceString, int length, @@ -53,12 +48,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime [Out] IntPtr *hstring); [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] - [SecurityCritical] [SuppressUnmanagedCodeSecurity] internal static extern int WindowsDeleteString(IntPtr hstring); [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] - [SecurityCritical] [SuppressUnmanagedCodeSecurity] internal static unsafe extern char* WindowsGetStringRawBuffer(IntPtr hstring, [Out] uint *length); } diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/RuntimeClass.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/RuntimeClass.cs index 5dd7d00..cd3c53a 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/RuntimeClass.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/RuntimeClass.cs @@ -57,15 +57,12 @@ namespace System.Runtime.InteropServices.WindowsRuntime { // // Support for ToString/GetHashCode/Equals override // - [System.Security.SecurityCritical] [MethodImpl(MethodImplOptions.InternalCall)] internal extern IntPtr GetRedirectedGetHashCodeMD(); - [System.Security.SecurityCritical] [MethodImpl(MethodImplOptions.InternalCall)] internal extern int RedirectGetHashCode(IntPtr pMD); - [System.Security.SecuritySafeCritical] public override int GetHashCode() { IntPtr pMD = GetRedirectedGetHashCodeMD(); @@ -74,15 +71,12 @@ namespace System.Runtime.InteropServices.WindowsRuntime { return RedirectGetHashCode(pMD); } - [System.Security.SecurityCritical] [MethodImpl(MethodImplOptions.InternalCall)] internal extern IntPtr GetRedirectedToStringMD(); - [System.Security.SecurityCritical] [MethodImpl(MethodImplOptions.InternalCall)] internal extern string RedirectToString(IntPtr pMD); - [System.Security.SecuritySafeCritical] public override string ToString() { // Check whether the type implements IStringable. @@ -102,15 +96,12 @@ namespace System.Runtime.InteropServices.WindowsRuntime { } } - [System.Security.SecurityCritical] [MethodImpl(MethodImplOptions.InternalCall)] internal extern IntPtr GetRedirectedEqualsMD(); - [System.Security.SecurityCritical] [MethodImpl(MethodImplOptions.InternalCall)] internal extern bool RedirectEquals(object obj, IntPtr pMD); - [System.Security.SecuritySafeCritical] public override bool Equals(object obj) { IntPtr pMD = GetRedirectedEqualsMD(); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToCollectionAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToCollectionAdapter.cs index 5eeb0af..898f1a6 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToCollectionAdapter.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToCollectionAdapter.cs @@ -8,6 +8,7 @@ using System; using System.Security; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; @@ -26,12 +27,11 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private VectorToCollectionAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } // int Count { get } [Pure] - [SecurityCritical] internal int Count() { IVector _this = JitHelpers.UnsafeCast>(this); @@ -45,14 +45,12 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // bool IsReadOnly { get } - [SecurityCritical] internal bool IsReadOnly() { return false; } // void Add(T item) - [SecurityCritical] internal void Add(T item) { IVector _this = JitHelpers.UnsafeCast>(this); @@ -60,7 +58,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void Clear() - [SecurityCritical] internal void Clear() { IVector _this = JitHelpers.UnsafeCast>(this); @@ -68,7 +65,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // bool Contains(T item) - [SecurityCritical] internal bool Contains(T item) { IVector _this = JitHelpers.UnsafeCast>(this); @@ -78,14 +74,13 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void CopyTo(T[] array, int arrayIndex) - [SecurityCritical] internal void CopyTo(T[] array, int arrayIndex) { if (array == null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); if (arrayIndex < 0) - throw new ArgumentOutOfRangeException("arrayIndex"); + throw new ArgumentOutOfRangeException(nameof(arrayIndex)); if (array.Length <= arrayIndex && Count() > 0) throw new ArgumentException(Environment.GetResourceString("Argument_IndexOutOfArrayBounds")); @@ -104,7 +99,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // bool Remove(T item) - [SecurityCritical] internal bool Remove(T item) { IVector _this = JitHelpers.UnsafeCast>(this); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToListAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToListAdapter.cs index f27cc95..3e33248 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToListAdapter.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToListAdapter.cs @@ -8,6 +8,7 @@ using System; using System.Security; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; @@ -26,33 +27,30 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private VectorToListAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } // T this[int index] { get } - [SecurityCritical] internal T Indexer_Get(int index) { if (index < 0) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); IVector _this = JitHelpers.UnsafeCast>(this); return GetAt(_this, (uint)index); } // T this[int index] { set } - [SecurityCritical] internal void Indexer_Set(int index, T value) { if (index < 0) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); IVector _this = JitHelpers.UnsafeCast>(this); SetAt(_this, (uint)index, value); } // int IndexOf(T item) - [SecurityCritical] internal int IndexOf(T item) { IVector _this = JitHelpers.UnsafeCast>(this); @@ -72,22 +70,20 @@ namespace System.Runtime.InteropServices.WindowsRuntime } // void Insert(int index, T item) - [SecurityCritical] internal void Insert(int index, T item) { if (index < 0) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); IVector _this = JitHelpers.UnsafeCast>(this); InsertAtHelper(_this, (uint)index, item); } // void RemoveAt(int index) - [SecurityCritical] internal void RemoveAt(int index) { if (index < 0) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); IVector _this = JitHelpers.UnsafeCast>(this); RemoveAtHelper(_this, (uint)index); @@ -107,7 +103,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime catch (Exception ex) { if (__HResults.E_BOUNDS == ex._HResult) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); throw; } @@ -125,7 +121,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime catch (Exception ex) { if (__HResults.E_BOUNDS == ex._HResult) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); throw; } @@ -143,7 +139,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime catch (Exception ex) { if (__HResults.E_BOUNDS == ex._HResult) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); throw; } @@ -161,7 +157,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime catch (Exception ex) { if (__HResults.E_BOUNDS == ex._HResult) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); throw; } diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorViewToReadOnlyCollectionAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorViewToReadOnlyCollectionAdapter.cs index 4b4ae5d..6b7785d 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorViewToReadOnlyCollectionAdapter.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorViewToReadOnlyCollectionAdapter.cs @@ -8,6 +8,7 @@ using System; using System.Security; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; @@ -26,12 +27,11 @@ namespace System.Runtime.InteropServices.WindowsRuntime { private VectorViewToReadOnlyCollectionAdapter() { - Contract.Assert(false, "This class is never instantiated"); + Debug.Assert(false, "This class is never instantiated"); } // int Count { get } [Pure] - [SecurityCritical] internal int Count() { IVectorView _this = JitHelpers.UnsafeCast>(this); diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeBufferHelper.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeBufferHelper.cs index 0d59895..a786880 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeBufferHelper.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeBufferHelper.cs @@ -19,7 +19,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime { internal static class WindowsRuntimeBufferHelper { - [SecurityCritical] [DllImport(JitHelpers.QCall)] [SuppressUnmanagedCodeSecurity] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] @@ -27,7 +26,6 @@ internal static class WindowsRuntimeBufferHelper { [FriendAccessAllowed] - [SecurityCritical] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal unsafe static void StoreOverlappedInCCW(Object windowsRuntimeBuffer, NativeOverlapped* overlapped) { diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMarshal.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMarshal.cs index 038efd5..a7ad491 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMarshal.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMarshal.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Reflection; using System.Runtime.CompilerServices; @@ -23,15 +24,14 @@ namespace System.Runtime.InteropServices.WindowsRuntime // delegate. It then stores the corresponding token in a dictionary for easy access by RemoveEventHandler // later. Note that the dictionary is indexed by the remove method that will be used for RemoveEventHandler // so the removeMethod given here must match the remove method supplied there exactly. - [SecurityCritical] public static void AddEventHandler(Func addMethod, Action removeMethod, T handler) { if (addMethod == null) - throw new ArgumentNullException("addMethod"); + throw new ArgumentNullException(nameof(addMethod)); if (removeMethod == null) - throw new ArgumentNullException("removeMethod"); + throw new ArgumentNullException(nameof(removeMethod)); Contract.EndContractBlock(); // Managed code allows adding a null event handler, the effect is a no-op. To match this behavior @@ -54,11 +54,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime // Remove the delegate handler from the Windows Runtime style event registration by looking for // its token, previously stored via AddEventHandler - [SecurityCritical] public static void RemoveEventHandler(Action removeMethod, T handler) { if (removeMethod == null) - throw new ArgumentNullException("removeMethod"); + throw new ArgumentNullException(nameof(removeMethod)); Contract.EndContractBlock(); // Managed code allows removing a null event handler, the effect is a no-op. To match this behavior @@ -79,11 +78,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime ManagedEventRegistrationImpl.RemoveEventHandler(removeMethod, handler); } - [SecurityCritical] public static void RemoveAllEventHandlers(Action removeMethod) { if (removeMethod == null) - throw new ArgumentNullException("removeMethod"); + throw new ArgumentNullException(nameof(removeMethod)); Contract.EndContractBlock(); // Delegate to managed event registration implementation or native event registration implementation @@ -220,7 +218,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime ConditionalWeakTable>> s_eventRegistrations = new ConditionalWeakTable>>(); - [SecurityCritical] internal static void AddEventHandler(Func addMethod, Action removeMethod, T handler) @@ -280,7 +277,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } } - [SecurityCritical] internal static void RemoveEventHandler(Action removeMethod, T handler) { Contract.Requires(removeMethod != null); @@ -322,7 +318,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime BCLDebug.Log("INTEROP", "[WinRT_Eventing] Event unsubscribed for managed instance = " + instance + ", handler = " + handler + ", token = " + token.m_value + "\n"); } - [SecurityCritical] internal static void RemoveAllEventHandlers(Action removeMethod) { Contract.Requires(removeMethod != null); @@ -538,11 +533,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime private volatile static MyReaderWriterLock s_eventCacheRWLock = new MyReaderWriterLock(); // Get InstanceKey to use in the cache - [SecuritySafeCritical] private static object GetInstanceKey(Action removeMethod) { object target = removeMethod.Target; - Contract.Assert(target == null || Marshal.IsComObject(target), "Must be null or a RCW"); + Debug.Assert(target == null || Marshal.IsComObject(target), "Must be null or a RCW"); if (target == null) return removeMethod.Method.DeclaringType; @@ -550,7 +544,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime return (object) Marshal.GetRawIUnknownForComObjectNoAddRef(target); } - [SecurityCritical] internal static void AddEventHandler(Func addMethod, Action removeMethod, T handler) @@ -685,7 +678,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } } - [SecurityCritical] internal static void RemoveEventHandler(Action removeMethod, T handler) { object instanceKey = GetInstanceKey(removeMethod); @@ -721,7 +713,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime // Note that inside TryGetValueWithValueEquality we assumes that any delegate // with the same value equality would have the same hash code object key = registrationTokens.FindEquivalentKeyUnsafe(handler, out tokens); - Contract.Assert((key != null && tokens != null) || (key == null && tokens == null), + Debug.Assert((key != null && tokens != null) || (key == null && tokens == null), "key and tokens must be both null or non-null"); if (tokens == null) { @@ -762,7 +754,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime removeMethod(token); } - [SecurityCritical] internal static void RemoveAllEventHandlers(Action removeMethod) { object instanceKey = GetInstanceKey(removeMethod); @@ -908,7 +899,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime internal void ReleaseReaderLock() { EnterMyLock(); - Contract.Assert(owners > 0, "ReleasingReaderLock: releasing lock and no read lock taken"); + Debug.Assert(owners > 0, "ReleasingReaderLock: releasing lock and no read lock taken"); --owners; ExitAndWakeUpAppropriateWaiters(); } @@ -916,7 +907,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime internal void ReleaseWriterLock() { EnterMyLock(); - Contract.Assert(owners == -1, "Calling ReleaseWriterLock when no write lock is held"); + Debug.Assert(owners == -1, "Calling ReleaseWriterLock when no write lock is held"); owners++; ExitAndWakeUpAppropriateWaiters(); } @@ -928,8 +919,8 @@ namespace System.Runtime.InteropServices.WindowsRuntime /// set 'waitEvent' /// private void LazyCreateEvent(ref EventWaitHandle waitEvent, bool makeAutoResetEvent) { - Contract.Assert(myLock != 0, "Lock must be held"); - Contract.Assert(waitEvent == null, "Wait event must be null"); + Debug.Assert(myLock != 0, "Lock must be held"); + Debug.Assert(waitEvent == null, "Wait event must be null"); ExitMyLock(); EventWaitHandle newEvent; @@ -948,7 +939,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime /// private void WaitOnEvent(EventWaitHandle waitEvent, ref uint numWaiters, int millisecondsTimeout) { - Contract.Assert(myLock != 0, "Lock must be held"); + Debug.Assert(myLock != 0, "Lock must be held"); waitEvent.Reset(); numWaiters++; @@ -976,7 +967,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime /// private void ExitAndWakeUpAppropriateWaiters() { - Contract.Assert(myLock != 0, "Lock must be held"); + Debug.Assert(myLock != 0, "Lock must be held"); if (owners == 0 && numWriteWaiters > 0) { @@ -1012,7 +1003,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime } private void ExitMyLock() { - Contract.Assert(myLock != 0, "Exiting spin lock that is not held"); + Debug.Assert(myLock != 0, "Exiting spin lock that is not held"); myLock = 0; } }; @@ -1044,7 +1035,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime throw new AggregateException(exceptions.ToArray()); } - [SecurityCritical] internal static unsafe string HStringToString(IntPtr hstring) { Contract.Requires(Environment.IsWinRTSupported); @@ -1092,7 +1082,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime private static bool s_haveBlueErrorApis = true; - [SecurityCritical] private static bool RoOriginateLanguageException(int error, string message, IntPtr languageException) { if (s_haveBlueErrorApis) @@ -1110,7 +1099,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime return false; } - [SecurityCritical] private static void RoReportUnhandledError(IRestrictedErrorInfo error) { if (s_haveBlueErrorApis) @@ -1134,7 +1122,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime /// /// true if the error was reported, false if not (ie running on Win8) [FriendAccessAllowed] - [SecuritySafeCritical] internal static bool ReportUnhandledError(Exception e) { // Only report to the WinRT global exception handler in modern apps @@ -1200,14 +1187,12 @@ namespace System.Runtime.InteropServices.WindowsRuntime #if FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION // Get an IActivationFactory * for a managed type - [SecurityCritical] internal static IntPtr GetActivationFactoryForType(Type type) { ManagedActivationFactory activationFactory = GetManagedActivationFactory(type); return Marshal.GetComInterfaceForObject(activationFactory, typeof(IActivationFactory)); } - [SecurityCritical] internal static ManagedActivationFactory GetManagedActivationFactory(Type type) { ManagedActivationFactory activationFactory = new ManagedActivationFactory(type); @@ -1224,7 +1209,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime // holds the IWinRTClassActivator* that is used for the process private static IntPtr s_pClassActivator = IntPtr.Zero; - [SecurityCritical] internal static IntPtr GetClassActivatorForApplication(string appBase) { if (s_pClassActivator == IntPtr.Zero) @@ -1268,11 +1252,10 @@ namespace System.Runtime.InteropServices.WindowsRuntime // factories from other apartments and make transiton to those apartments and cause // deadlocks and create objects in incorrect apartments // - [SecurityCritical] public static IActivationFactory GetActivationFactory(Type type) { if (type == null) - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); if (type.IsWindowsRuntimeObject && type.IsImport) { @@ -1291,14 +1274,13 @@ namespace System.Runtime.InteropServices.WindowsRuntime // HSTRING marshaling methods: - [SecurityCritical] public static IntPtr StringToHString(String s) { if (!Environment.IsWinRTSupported) throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_WinRT")); if (s == null) - throw new ArgumentNullException("s"); + throw new ArgumentNullException(nameof(s)); unsafe { @@ -1309,7 +1291,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime } } - [SecurityCritical] public static String PtrToStringHString(IntPtr ptr) { if (!Environment.IsWinRTSupported) @@ -1320,7 +1301,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime return HStringToString(ptr); } - [SecurityCritical] public static void FreeHString(IntPtr ptr) { if (!Environment.IsWinRTSupported) diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMetadata.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMetadata.cs index e2ad203..9ca959c 100644 --- a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMetadata.cs +++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMetadata.cs @@ -19,18 +19,16 @@ namespace System.Runtime.InteropServices.WindowsRuntime public static class WindowsRuntimeMetadata { // Wrapper for Win8 API RoResolveNamespace with default Windows SDK path as installed .winmd files in %WINDIR%\system32\WinMetadata. - [System.Security.SecurityCritical] public static IEnumerable ResolveNamespace(string namespaceName, IEnumerable packageGraphFilePaths) { return ResolveNamespace(namespaceName, null, packageGraphFilePaths); } // Wrapper for Win8 API RoResolveNamespace. - [System.Security.SecurityCritical] public static IEnumerable ResolveNamespace(string namespaceName, string windowsSdkFilePath, IEnumerable packageGraphFilePaths) { if (namespaceName == null) - throw new ArgumentNullException("namespaceName"); + throw new ArgumentNullException(nameof(namespaceName)); Contract.EndContractBlock(); string[] packageGraphFilePathsArray = null; @@ -58,7 +56,6 @@ namespace System.Runtime.InteropServices.WindowsRuntime return retFileNames; } - [System.Security.SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void nResolveNamespace( diff --git a/src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs index 7552986..e158a5a 100644 --- a/src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs +++ b/src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs @@ -17,7 +17,6 @@ using System.Threading; namespace System.Runtime.Loader { - [System.Security.SecuritySafeCritical] public abstract class AssemblyLoadContext { [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] @@ -62,7 +61,6 @@ namespace System.Runtime.Loader InitializeLoadContext(fRepresentsTPALoadContext); } - [System.Security.SecuritySafeCritical] void InitializeLoadContext(bool fRepresentsTPALoadContext) { // Initialize the VM side of AssemblyLoadContext if not already done. @@ -83,6 +81,17 @@ namespace System.Runtime.Loader [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void LoadFromPath(IntPtr ptrNativeAssemblyLoadContext, string ilPath, string niPath, ObjectHandleOnStack retAssembly); + + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + private static extern void GetLoadedAssembliesInternal(ObjectHandleOnStack assemblies); + + public static Assembly[] GetLoadedAssemblies() + { + Assembly[] assemblies = null; + GetLoadedAssembliesInternal(JitHelpers.GetObjectHandleOnStack(ref assemblies)); + return assemblies; + } // These are helpers that can be used by AssemblyLoadContext derivations. // They are used to load assemblies in DefaultContext. @@ -90,12 +99,12 @@ namespace System.Runtime.Loader { if (assemblyPath == null) { - throw new ArgumentNullException("assemblyPath"); + throw new ArgumentNullException(nameof(assemblyPath)); } - if (Path.IsRelative(assemblyPath)) + if (PathInternal.IsPartiallyQualified(assemblyPath)) { - throw new ArgumentException( Environment.GetResourceString("Argument_AbsolutePathRequired"), "assemblyPath"); + throw new ArgumentException( Environment.GetResourceString("Argument_AbsolutePathRequired"), nameof(assemblyPath)); } RuntimeAssembly loadedAssembly = null; @@ -107,17 +116,17 @@ namespace System.Runtime.Loader { if (nativeImagePath == null) { - throw new ArgumentNullException("nativeImagePath"); + throw new ArgumentNullException(nameof(nativeImagePath)); } - if (Path.IsRelative(nativeImagePath)) + if (PathInternal.IsPartiallyQualified(nativeImagePath)) { - throw new ArgumentException( Environment.GetResourceString("Argument_AbsolutePathRequired"), "nativeImagePath"); + throw new ArgumentException( Environment.GetResourceString("Argument_AbsolutePathRequired"), nameof(nativeImagePath)); } - if (assemblyPath != null && Path.IsRelative(assemblyPath)) + if (assemblyPath != null && PathInternal.IsPartiallyQualified(assemblyPath)) { - throw new ArgumentException(Environment.GetResourceString("Argument_AbsolutePathRequired"), "assemblyPath"); + throw new ArgumentException(Environment.GetResourceString("Argument_AbsolutePathRequired"), nameof(assemblyPath)); } // Basic validation has succeeded - lets try to load the NI image. @@ -136,7 +145,7 @@ namespace System.Runtime.Loader { if (assembly == null) { - throw new ArgumentNullException("assembly"); + throw new ArgumentNullException(nameof(assembly)); } int iAssemblyStreamLength = (int)assembly.Length; @@ -291,15 +300,15 @@ namespace System.Runtime.Loader { if (unmanagedDllPath == null) { - throw new ArgumentNullException("unmanagedDllPath"); + throw new ArgumentNullException(nameof(unmanagedDllPath)); } if (unmanagedDllPath.Length == 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"), "unmanagedDllPath"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"), nameof(unmanagedDllPath)); } - if (Path.IsRelative(unmanagedDllPath)) + if (PathInternal.IsPartiallyQualified(unmanagedDllPath)) { - throw new ArgumentException(Environment.GetResourceString("Argument_AbsolutePathRequired"), "unmanagedDllPath"); + throw new ArgumentException(Environment.GetResourceString("Argument_AbsolutePathRequired"), nameof(unmanagedDllPath)); } return InternalLoadUnmanagedDllFromPath(unmanagedDllPath); @@ -355,7 +364,7 @@ namespace System.Runtime.Loader { if (context == null) { - throw new ArgumentNullException("context"); + throw new ArgumentNullException(nameof(context)); } // Try to override the default assembly load context @@ -378,10 +387,10 @@ namespace System.Runtime.Loader { if (assemblyPath == null) { - throw new ArgumentNullException("assemblyPath"); + throw new ArgumentNullException(nameof(assemblyPath)); } - - String fullPath = Path.GetFullPathInternal(assemblyPath); + + string fullPath = Path.GetFullPath(assemblyPath); return nGetFileInformation(fullPath); } @@ -394,7 +403,7 @@ namespace System.Runtime.Loader { if (assembly == null) { - throw new ArgumentNullException("assembly"); + throw new ArgumentNullException(nameof(assembly)); } AssemblyLoadContext loadContextForAssembly = null; @@ -459,16 +468,43 @@ namespace System.Runtime.Loader // Synchronization primitive for controlling initialization of Default load context private static readonly object s_initLock = new Object(); + + // Occurs when an Assembly is loaded + public static event AssemblyLoadEventHandler AssemblyLoad + { + add { AppDomain.CurrentDomain.AssemblyLoad += value; } + remove { AppDomain.CurrentDomain.AssemblyLoad -= value; } + } + + // Occurs when resolution of type fails + public static event ResolveEventHandler TypeResolve + { + add { AppDomain.CurrentDomain.TypeResolve += value; } + remove { AppDomain.CurrentDomain.TypeResolve -= value; } + } + + // Occurs when resolution of resource fails + public static event ResolveEventHandler ResourceResolve + { + add { AppDomain.CurrentDomain.ResourceResolve += value; } + remove { AppDomain.CurrentDomain.ResourceResolve -= value; } + } + + // Occurs when resolution of assembly fails + // This event is fired after resolve events of AssemblyLoadContext fails + public static event ResolveEventHandler AssemblyResolve + { + add { AppDomain.CurrentDomain.AssemblyResolve += value; } + remove { AppDomain.CurrentDomain.AssemblyResolve -= value; } + } } - [System.Security.SecuritySafeCritical] class AppPathAssemblyLoadContext : AssemblyLoadContext { internal AppPathAssemblyLoadContext() : base(true) { } - [System.Security.SecuritySafeCritical] protected override Assembly Load(AssemblyName assemblyName) { // We were loading an assembly into TPA ALC that was not found on TPA list. As a result we are here. @@ -476,6 +512,18 @@ namespace System.Runtime.Loader return null; } } + + internal class IndividualAssemblyLoadContext : AssemblyLoadContext + { + internal IndividualAssemblyLoadContext() : base(false) + { + } + + protected override Assembly Load(AssemblyName assemblyName) + { + return null; + } + } } #endif // FEATURE_HOST_ASSEMBLY_RESOLVER diff --git a/src/mscorlib/src/System/Runtime/MemoryFailPoint.cs b/src/mscorlib/src/System/Runtime/MemoryFailPoint.cs index 6e35568..bd87d90 100644 --- a/src/mscorlib/src/System/Runtime/MemoryFailPoint.cs +++ b/src/mscorlib/src/System/Runtime/MemoryFailPoint.cs @@ -22,6 +22,7 @@ using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; using System.Security.Permissions; using System.Runtime.Versioning; +using System.Diagnostics; using System.Diagnostics.Contracts; /* @@ -143,7 +144,6 @@ namespace System.Runtime private ulong _reservedMemory; // The size of this request (from user) private bool _mustSubtractReservation; // Did we add data to SharedStatics? - [System.Security.SecuritySafeCritical] // auto-generated static MemoryFailPoint() { GetMemorySettings(out GCSegmentSize, out TopOfMemory); @@ -153,13 +153,13 @@ namespace System.Runtime // have scenarios for this in partial trust in the future, but // we're doing this just to restrict this in case the code below // is somehow incorrect. - [System.Security.SecurityCritical] // auto-generated_required public MemoryFailPoint(int sizeInMegabytes) { if (sizeInMegabytes <= 0) - throw new ArgumentOutOfRangeException("sizeInMegabytes", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(sizeInMegabytes), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); +#if !FEATURE_PAL // Remove this when CheckForAvailableMemory is able to provide legitimate estimates ulong size = ((ulong)sizeInMegabytes) << 20; _reservedMemory = size; @@ -283,7 +283,7 @@ namespace System.Runtime break; default: - Contract.Assert(false, "Fell through switch statement!"); + Debug.Assert(false, "Fell through switch statement!"); break; } } @@ -302,9 +302,9 @@ namespace System.Runtime SharedStatics.AddMemoryFailPointReservation((long) size); _mustSubtractReservation = true; } +#endif } - [System.Security.SecurityCritical] // auto-generated private static void CheckForAvailableMemory(out ulong availPageFile, out ulong totalAddressSpaceFree) { bool r; @@ -321,7 +321,6 @@ namespace System.Runtime // returns whether there is enough space. In all cases, we update // our last known free address space, hopefully avoiding needing to // probe again. - [System.Security.SecurityCritical] // auto-generated private static unsafe bool CheckForFreeAddressSpace(ulong size, bool shouldThrow) { // Start walking the address space at 0. VirtualAlloc may wrap @@ -348,7 +347,6 @@ namespace System.Runtime // of pages. If we didn't have enough address space, we still return // a positive value < size, to help potentially avoid the overhead of // this check if we use a MemoryFailPoint with a smaller size next. - [System.Security.SecurityCritical] // auto-generated private static unsafe ulong MemFreeAfterAddress(void * address, ulong size) { if (size >= TopOfMemory) @@ -375,11 +373,9 @@ namespace System.Runtime return largestFreeRegion; } - [System.Security.SecurityCritical] // auto-generated [MethodImpl(MethodImplOptions.InternalCall)] private static extern void GetMemorySettings(out ulong maxGCSegmentSize, out ulong topOfMemory); - [System.Security.SecuritySafeCritical] // destructors should be safe to call ~MemoryFailPoint() { Dispose(false); @@ -392,14 +388,12 @@ namespace System.Runtime // future create an allocation context and release it in the Dispose // method. While the finalizer will eventually free this block of // memory, apps will help their performance greatly by calling Dispose. - [System.Security.SecuritySafeCritical] // auto-generated public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] private void Dispose(bool disposing) { diff --git a/src/mscorlib/src/System/Runtime/ProfileOptimization.cs b/src/mscorlib/src/System/Runtime/ProfileOptimization.cs index c877d21..1e42308 100644 --- a/src/mscorlib/src/System/Runtime/ProfileOptimization.cs +++ b/src/mscorlib/src/System/Runtime/ProfileOptimization.cs @@ -27,22 +27,18 @@ namespace System.Runtime { public static class ProfileOptimization { [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SecurityCritical] [SuppressUnmanagedCodeSecurity] internal static extern void InternalSetProfileRoot(string directoryPath); [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SecurityCritical] [SuppressUnmanagedCodeSecurity] internal static extern void InternalStartProfile(string profile, IntPtr ptrNativeAssemblyLoadContext); - [SecurityCritical] public static void SetProfileRoot(string directoryPath) { InternalSetProfileRoot(directoryPath); } - [SecurityCritical] public static void StartProfile(string profile) { InternalStartProfile(profile, IntPtr.Zero); diff --git a/src/mscorlib/src/System/Runtime/Reliability/CriticalFinalizerObject.cs b/src/mscorlib/src/System/Runtime/Reliability/CriticalFinalizerObject.cs index 2524aaa..eb5a186 100644 --- a/src/mscorlib/src/System/Runtime/Reliability/CriticalFinalizerObject.cs +++ b/src/mscorlib/src/System/Runtime/Reliability/CriticalFinalizerObject.cs @@ -22,15 +22,9 @@ using System.Runtime.InteropServices; namespace System.Runtime.ConstrainedExecution { -#if !FEATURE_CORECLR - [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)] -#endif [System.Runtime.InteropServices.ComVisible(true)] public abstract class CriticalFinalizerObject { - #if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // auto-generated - #endif [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] protected CriticalFinalizerObject() { diff --git a/src/mscorlib/src/System/Runtime/Remoting/ObjectHandle.cs b/src/mscorlib/src/System/Runtime/Remoting/ObjectHandle.cs index d10df9d..5555670 100644 --- a/src/mscorlib/src/System/Runtime/Remoting/ObjectHandle.cs +++ b/src/mscorlib/src/System/Runtime/Remoting/ObjectHandle.cs @@ -14,23 +14,14 @@ ** ===========================================================*/ -namespace System.Runtime.Remoting{ - +namespace System.Runtime.Remoting +{ using System; - using System.Security.Permissions; using System.Runtime.InteropServices; - using System.Runtime.Remoting; -#if FEATURE_REMOTING - using System.Runtime.Remoting.Activation; - using System.Runtime.Remoting.Lifetime; -#endif [ClassInterface(ClassInterfaceType.AutoDual)] [System.Runtime.InteropServices.ComVisible(true)] public class ObjectHandle: -#if FEATURE_REMOTING - MarshalByRefObject, -#endif IObjectHandle { private Object WrappedObject; @@ -48,34 +39,5 @@ namespace System.Runtime.Remoting{ { return WrappedObject; } - - // ObjectHandle has a finite lifetime. For now the default - // lifetime is being used, this can be changed in this method to - // specify a custom lifetime. -#if FEATURE_REMOTING - [System.Security.SecurityCritical] // auto-generated_required - public override Object InitializeLifetimeService() - { - BCLDebug.Trace("REMOTE", "ObjectHandle.InitializeLifetimeService"); - - // - // If the wrapped object has implemented InitializeLifetimeService to return null, - // we don't want to go to the base class (which will result in a lease being - // requested from the MarshalByRefObject, which starts up the LeaseManager, - // which starts up the ThreadPool, adding three threads to the process. - // We check if the wrapped object is a MarshalByRef object, and call InitializeLifetimeServices on it - // and if it returns null, we return null. Otherwise we fall back to the old behavior. - // - - MarshalByRefObject mbr = WrappedObject as MarshalByRefObject; - if (mbr != null) { - Object o = mbr.InitializeLifetimeService(); - if (o == null) - return null; - } - ILease lease = (ILease)base.InitializeLifetimeService(); - return lease; - } -#endif // FEATURE_REMOTING } } diff --git a/src/mscorlib/src/System/Runtime/Serialization/FormatterConverter.cs b/src/mscorlib/src/System/Runtime/Serialization/FormatterConverter.cs index 7df221c..b710ed0 100644 --- a/src/mscorlib/src/System/Runtime/Serialization/FormatterConverter.cs +++ b/src/mscorlib/src/System/Runtime/Serialization/FormatterConverter.cs @@ -25,7 +25,7 @@ namespace System.Runtime.Serialization { public Object Convert(Object value, Type type) { if (value==null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); return System.Convert.ChangeType(value, type, CultureInfo.InvariantCulture); @@ -33,7 +33,7 @@ namespace System.Runtime.Serialization { public Object Convert(Object value, TypeCode typeCode) { if (value==null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); return System.Convert.ChangeType(value, typeCode, CultureInfo.InvariantCulture); @@ -41,7 +41,7 @@ namespace System.Runtime.Serialization { public bool ToBoolean(Object value) { if (value==null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); return System.Convert.ToBoolean(value, CultureInfo.InvariantCulture); @@ -49,7 +49,7 @@ namespace System.Runtime.Serialization { public char ToChar(Object value) { if (value==null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); return System.Convert.ToChar(value, CultureInfo.InvariantCulture); @@ -58,7 +58,7 @@ namespace System.Runtime.Serialization { [CLSCompliant(false)] public sbyte ToSByte(Object value) { if (value==null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); return System.Convert.ToSByte(value, CultureInfo.InvariantCulture); @@ -66,7 +66,7 @@ namespace System.Runtime.Serialization { public byte ToByte(Object value) { if (value==null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); return System.Convert.ToByte(value, CultureInfo.InvariantCulture); @@ -74,7 +74,7 @@ namespace System.Runtime.Serialization { public short ToInt16(Object value) { if (value==null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); return System.Convert.ToInt16(value, CultureInfo.InvariantCulture); @@ -83,7 +83,7 @@ namespace System.Runtime.Serialization { [CLSCompliant(false)] public ushort ToUInt16(Object value) { if (value==null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); return System.Convert.ToUInt16(value, CultureInfo.InvariantCulture); @@ -91,7 +91,7 @@ namespace System.Runtime.Serialization { public int ToInt32(Object value) { if (value==null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); return System.Convert.ToInt32(value, CultureInfo.InvariantCulture); @@ -100,7 +100,7 @@ namespace System.Runtime.Serialization { [CLSCompliant(false)] public uint ToUInt32(Object value) { if (value==null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); return System.Convert.ToUInt32(value, CultureInfo.InvariantCulture); @@ -108,7 +108,7 @@ namespace System.Runtime.Serialization { public long ToInt64(Object value) { if (value==null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); return System.Convert.ToInt64(value, CultureInfo.InvariantCulture); @@ -117,7 +117,7 @@ namespace System.Runtime.Serialization { [CLSCompliant(false)] public ulong ToUInt64(Object value) { if (value==null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); return System.Convert.ToUInt64(value, CultureInfo.InvariantCulture); @@ -125,7 +125,7 @@ namespace System.Runtime.Serialization { public float ToSingle(Object value) { if (value==null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); return System.Convert.ToSingle(value, CultureInfo.InvariantCulture); @@ -133,7 +133,7 @@ namespace System.Runtime.Serialization { public double ToDouble(Object value) { if (value==null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); return System.Convert.ToDouble(value, CultureInfo.InvariantCulture); @@ -141,7 +141,7 @@ namespace System.Runtime.Serialization { public Decimal ToDecimal(Object value) { if (value==null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); return System.Convert.ToDecimal(value, CultureInfo.InvariantCulture); @@ -149,7 +149,7 @@ namespace System.Runtime.Serialization { public DateTime ToDateTime(Object value) { if (value==null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); return System.Convert.ToDateTime(value, CultureInfo.InvariantCulture); @@ -157,7 +157,7 @@ namespace System.Runtime.Serialization { public String ToString(Object value) { if (value==null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); return System.Convert.ToString(value, CultureInfo.InvariantCulture); diff --git a/src/mscorlib/src/System/Runtime/Serialization/FormatterServices.cs b/src/mscorlib/src/System/Runtime/Serialization/FormatterServices.cs index c6f27b5..27c3f15 100644 --- a/src/mscorlib/src/System/Runtime/Serialization/FormatterServices.cs +++ b/src/mscorlib/src/System/Runtime/Serialization/FormatterServices.cs @@ -29,16 +29,15 @@ namespace System.Runtime.Serialization { using System.IO; using System.Text; using System.Globalization; + using System.Diagnostics; using System.Diagnostics.Contracts; [System.Runtime.InteropServices.ComVisible(true)] public static class FormatterServices { #if FEATURE_SERIALIZATION internal static Dictionary m_MemberInfoTable = new Dictionary(32); - [System.Security.SecurityCritical] private static bool unsafeTypeForwardersIsEnabled = false; - [System.Security.SecurityCritical] private static volatile bool unsafeTypeForwardersIsEnabledInitialized = false; private static Object s_FormatterServicesSyncObject = null; @@ -56,7 +55,6 @@ namespace System.Runtime.Serialization { } } - [SecuritySafeCritical] static FormatterServices() { // Static initialization touches security critical types, so we need an @@ -100,7 +98,7 @@ namespace System.Runtime.Serialization { FieldInfo [] typeFields; RuntimeType parentType; - Contract.Assert((object)type != null, "[GetAllSerializableMembers]type!=null"); + Debug.Assert((object)type != null, "[GetAllSerializableMembers]type!=null"); if (type.IsInterface) { return new MemberInfo[0]; @@ -186,7 +184,6 @@ namespace System.Runtime.Serialization { // be included, properties must have both a getter and a setter. N.B.: A class // which implements ISerializable or has a serialization surrogate may not use all of these members // (or may have additional members). - [System.Security.SecurityCritical] // auto-generated_required public static MemberInfo[] GetSerializableMembers(Type type) { return GetSerializableMembers(type, new StreamingContext(StreamingContextStates.All)); } @@ -194,12 +191,11 @@ namespace System.Runtime.Serialization { // Get all of the Serializable Members for a particular class. If we're not cloning, this is all // non-transient, non-static fields. If we are cloning, include the transient fields as well since // we know that we're going to live inside of the same context. - [System.Security.SecurityCritical] // auto-generated_required public static MemberInfo[] GetSerializableMembers(Type type, StreamingContext context) { MemberInfo[] members; if ((object)type==null) { - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); } Contract.EndContractBlock(); @@ -230,14 +226,9 @@ namespace System.Runtime.Serialization { static readonly Type[] advancedTypes = new Type[]{ typeof(System.DelegateSerializationHolder), -#if FEATURE_REMOTING - typeof(System.Runtime.Remoting.ObjRef), - typeof(System.Runtime.Remoting.IEnvoyInfo), - typeof(System.Runtime.Remoting.Lifetime.ISponsor), -#endif }; - - public static void CheckTypeSecurity(Type t, TypeFilterLevel securityLevel) { + + public static void CheckTypeSecurity(Type t, TypeFilterLevel securityLevel) { if (securityLevel == TypeFilterLevel.Low){ for(int i=0;i this is the serialization data member of the parent type + // m_serializedState -> list of saved serialized states from subclasses responding to the safe + // serialization event + // RealTypeSerializationName -> type which is using safe serialization + // Type: + // SafeSerializationManager + // + // That is, the serialized data claims to be of type SafeSerializationManager, however contains only the + // data from the real object being serialized along with one bit of safe serialization metadata. + // + // At deserialization time, since the serialized data claims to be of type SafeSerializationManager, the + // root object being created is an instance of the SafeSerializationManager class. However, it detects + // that this isn't a real SafeSerializationManager (by looking for the real type field in the metadata), + // and simply saves away the SerializationInfo and the real type being deserialized. + // + // Since SafeSerializationManager implements IObjectReference, the next step of deserialization is the + // GetRealObject callback. This callback is the one responsible for getting the + // SafeSerializationManager out of the way and instead creating an instance of the actual type which was + // serialized. + // + // It does this by first creating an instance of the real type being deserialzed (saved away in the + // deserialzation constructor), but not running any of its constructors. Instead, it walks the + // inheritance hierarchy (moving toward the most derived type) looking for the last full trust type to + // implement the standard ISerializable constructor before any type does not implement the constructor. + // It is this last type's deserialization constructor which is then invoked, passing in the saved + // SerializationInfo. Once the constructors are run, we return this object as the real deserialized + // object. + // + // The reason that we do this walk is so that ISerializable types can protect themselves from malicious + // input during deserialization by making their deserialization constructors unavailable to partial + // trust code. By not requiring every type have a copy of this constructor, partial trust code can + // participate in safe serialization and not be required to have access to the parent's constructor. + // + // It should be noted however, that this heuristic means that if a full trust type does derive from + // a transparent or partial trust type using this safe serialization mechanism, that full trust type + // will not have its constructor called. Further, the protection of not invoking partial trust + // deserialization constructors only comes into play if SafeSerializationManager is in control of + // deserialization, which means there must be at least one (even empty) safe serialization event + // handler registered. + // + // Another interesting note is that at this point there are now two SafeSerializationManagers alive for + // this deserialization. The first object is the one which is controlling the deserialization and was + // created as the root object of the deserialization. The second one is the object which contains the + // serialized data chunks and is a data member of the real object being deserialized. For this reason, + // the data objects cannot be notified that the deserialization is complete during GetRealObject since + // the ISafeSerializationData objects are not members of the active SafeSerializationManager instance. + // + // The next step is the OnDeserialized callback, which comes to SafeSerializableObject since it was + // pretending to be the root object of the deserialization. It responds to this callback by calling + // any existing OnDeserialized callback on the real type that was deserialized. + // + // The real type needs to call its data member SafeSerializationData object's CompleteDeserialization + // method in response to the OnDeserialized call. This CompleteDeserialization call will then iterate + // through the ISafeSerializationData objects calling each of their CompleteDeserialization methods so + // that they can plug the nearly-complete object with their saved data. + // + // The reason for having a new ISafeSerializationData interface which is basically identical to + // IDeserializationCallback is that IDeserializationCallback will be called on the stored data chunks + // by the serialization code when they are deserialized, and that's not a desirable behavior. + // Essentially, we need to change the meaning of the object parameter to mean "parent object which + // participated in safe serialization", rather than "this object". + // + // Implementing safe serialization on an ISerialiable type is relatively straight forward. (For an + // example, see System.Exception): + // + // 1. Include a data member of type SafeSerializationManager: + // + // private SafeSerializationManager m_safeSerializationManager; + // + // 2. Add a protected SerializeObjectState event, which passes through to the SafeSerializationManager: + // + // protected event EventHandler SerializeObjectState + // { + // add { m_safeSerializationManager.SerializeObjectState += value; } + // remove { m_safeSerializationManager.SerializeObjectState -= value; } + // } + // + // 3. Serialize the safe serialization object in GetObjectData, and call its CompleteSerialization method: + // + // { + // info.AddValue("m_safeSerializationManager", m_safeSerializationManager, typeof(SafeSerializationManager)); + // m_safeSerializationManager.CompleteSerialization(this, info, context); + // } + // + // 4. Add an OnDeserialized handler if one doesn't already exist, and call CompleteDeserialization in it: + // + // [OnDeserialized] + // private void OnDeserialized(StreamingContext context) + // { + // m_safeSerializationManager.CompleteDeserialization(this); + // } + // + // On the client side, using safe serialization is also pretty easy. For example: + // + // [Serializable] + // public class TransparentException : Exception + // { + // [Serializable] + // private struct TransparentExceptionState : ISafeSerializationData + // { + // public string m_extraData; + // + // void ISafeSerializationData.CompleteDeserialization(object obj) + // { + // TransparentException exception = obj as TransparentException; + // exception.m_state = this; + // } + // } + // + // [NonSerialized] + // private TransparentExceptionState m_state = new TransparentExceptionState(); + // + // public TransparentException() + // { + // SerializeObjectState += delegate(object exception, SafeSerializationEventArgs eventArgs) + // { + // eventArgs.AddSerializedState(m_state); + // }; + // } + // + // public string ExtraData + // { + // get { return m_state.m_extraData; } + // set { m_state.m_extraData = value; } + // } + // } + // + + // SafeSerializationEventArgs are provided to the delegates which do safe serialization. Each delegate + // serializes its own state into an IDeserializationCallback instance which must, itself, be serializable. + // These indivdiual states are then added to the SafeSerializationEventArgs in order to be saved away when + // the original ISerializable type is serialized. + public sealed class SafeSerializationEventArgs : EventArgs + { + private StreamingContext m_streamingContext; + private List m_serializedStates = new List(); + + internal SafeSerializationEventArgs(StreamingContext streamingContext) + { + m_streamingContext = streamingContext; + } + + public void AddSerializedState(ISafeSerializationData serializedState) + { + if (serializedState == null) + throw new ArgumentNullException(nameof(serializedState)); + if (!serializedState.GetType().IsSerializable) + throw new ArgumentException(Environment.GetResourceString("Serialization_NonSerType", serializedState.GetType(), serializedState.GetType().Assembly.FullName)); + + m_serializedStates.Add(serializedState); + } + + internal IList SerializedStates + { + get { return m_serializedStates; } + } + + public StreamingContext StreamingContext + { + get { return m_streamingContext; } + } + } + + // Interface to be supported by objects which are stored in safe serialization stores + public interface ISafeSerializationData + { + // CompleteDeserialization is called when the object to which the extra serialized data was attached + // has completed its deserialization, and now needs to be populated with the extra data stored in + // this object. + void CompleteDeserialization(object deserialized); + } +#if FEATURE_SERIALIZATION + // Helper class to implement safe serialization. Concrete ISerializable types which want to allow + // transparent subclasses code to participate in serialization should contain an instance of + // SafeSerializationManager and wire up to it as described in code:#SafeSerialization. + [Serializable] + internal sealed class SafeSerializationManager : IObjectReference, ISerializable + { + // Saved states to store in the serialization stream. This is typed as object rather than + // ISafeSerializationData because ISafeSerializationData can't be marked serializable. + private IList m_serializedStates; + + // This is the SerializationInfo that is used when the SafeSerializationManager type has replaced + // itself as the target of serialziation. It is not used directly by the safe serialization code, + // but just held onto so that the real object being deserialzed can use it later. + private SerializationInfo m_savedSerializationInfo; + + // Real object that we've deserialized - this is stored when we complete construction and calling + // the deserialization .ctors on it and is used when we need to notify the stored safe + // deserialization data that they should populate the object with their fields. + private object m_realObject; + + // Real type that should be deserialized + private RuntimeType m_realType; + + // Event fired when we need to collect state to serialize into the parent object + internal event EventHandler SerializeObjectState; + + // Name that is used to store the real type being deserialized in the main SerializationInfo + private const string RealTypeSerializationName = "CLR_SafeSerializationManager_RealType"; + + internal SafeSerializationManager() + { + } + + private SafeSerializationManager(SerializationInfo info, StreamingContext context) + { + // We need to determine if we're being called to really deserialize a SafeSerializationManager, + // or if we're being called because we've intercepted the deserialization callback for the real + // object being deserialized. We use the presence of the RealTypeSerializationName field in the + // serialization info to indicate that this is the interception callback and we just need to + // safe the info. If that field is not present, then we should be in a real deserialization + // construction. + RuntimeType realType = info.GetValueNoThrow(RealTypeSerializationName, typeof(RuntimeType)) as RuntimeType; + + if (realType == null) + { + m_serializedStates = info.GetValue("m_serializedStates", typeof(List)) as List; + } + else + { + m_realType = realType; + m_savedSerializationInfo = info; + } + } + + // Determine if the serialization manager is in an active state - that is if any code is hooked up + // to use it for serialization + internal bool IsActive + { + get { return SerializeObjectState != null; } + } + + // CompleteSerialization is called by the base ISerializable in its GetObjectData method. It is + // responsible for gathering up the serialized object state of any delegates that wish to add their + // own state to the serialized object. + internal void CompleteSerialization(object serializedObject, + SerializationInfo info, + StreamingContext context) + { + Contract.Requires(serializedObject != null); + Contract.Requires(info != null); + Contract.Requires(typeof(ISerializable).IsAssignableFrom(serializedObject.GetType())); + Contract.Requires(serializedObject.GetType().IsAssignableFrom(info.ObjectType)); + + // Clear out any stale state + m_serializedStates = null; + + // We only want to kick in our special serialization sauce if someone wants to participate in + // it, otherwise if we have no delegates registered there's no reason for us to get in the way + // of the regular serialization machinery. + EventHandler serializeObjectStateEvent = SerializeObjectState; + if (serializeObjectStateEvent != null) + { + // Get any extra data to add to our serialization state now + SafeSerializationEventArgs eventArgs = new SafeSerializationEventArgs(context); + serializeObjectStateEvent(serializedObject, eventArgs); + m_serializedStates = eventArgs.SerializedStates; + + // Replace the type to be deserialized by the standard serialization code paths with + // ourselves, which allows us to control the deserialization process. + info.AddValue(RealTypeSerializationName, serializedObject.GetType(), typeof(RuntimeType)); + info.SetType(typeof(SafeSerializationManager)); + } + } + + // CompleteDeserialization is called by the base ISerializable object's OnDeserialized handler to + // finish the deserialization of the object by notifying the saved states that they should + // re-populate their portions of the deserialized object. + internal void CompleteDeserialization(object deserializedObject) + { + Contract.Requires(deserializedObject != null); + + if (m_serializedStates != null) + { + foreach (ISafeSerializationData serializedState in m_serializedStates) + { + serializedState.CompleteDeserialization(deserializedObject); + } + } + } + + void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("m_serializedStates", m_serializedStates, typeof(List)); + } + + // GetRealObject intercepts the deserialization process in order to allow deserializing part of the + // object's inheritance heirarchy using standard ISerializable constructors, and the remaining + // portion using the saved serialization states. + object IObjectReference.GetRealObject(StreamingContext context) + { + // If we've already deserialized the real object, use that rather than deserializing it again + if (m_realObject != null) + { + return m_realObject; + } + + // If we don't have a real type to deserialize, then this is really a SafeSerializationManager + // and we don't need to rebuild the object that we're standing in for. + if (m_realType == null) + { + return this; + } + + // Look for the last type in GetRealType's inheritance hierarchy which implements a critical + // deserialization constructor. This will be the object that we use as the deserialization + // construction type to initialize via standard ISerializable semantics + + // First build up the chain starting at the type below Object and working to the real type we + // serialized. + Stack inheritanceChain = new Stack(); + RuntimeType currentType = m_realType; + do + { + inheritanceChain.Push(currentType); + currentType = currentType.BaseType as RuntimeType; + } + while (currentType != typeof(object)); + + // Now look for the first type that does not implement the ISerializable .ctor. When we find + // that, previousType will point at the last type that did implement the .ctor. We require that + // the .ctor we invoke also be non-transparent + RuntimeConstructorInfo serializationCtor = null; + RuntimeType previousType = null; + do + { + previousType = currentType; + currentType = inheritanceChain.Pop() as RuntimeType; + serializationCtor = currentType.GetSerializationCtor(); + } + while (serializationCtor != null && serializationCtor.IsSecurityCritical); + + // previousType is the last type that did implement the deserialization .ctor before the first + // type that did not, so we'll grab it's .ctor to use for deserialization. + BCLDebug.Assert(previousType != null, "We should have at least one inheritance from the base type"); + serializationCtor = ObjectManager.GetConstructor(previousType); + + // Allocate an instance of the final type and run the selected .ctor on that instance to get the + // standard ISerializable initialization done. + object deserialized = FormatterServices.GetUninitializedObject(m_realType); + serializationCtor.SerializationInvoke(deserialized, m_savedSerializationInfo, context); + m_savedSerializationInfo = null; + m_realType = null; + + // Save away the real object that was deserialized so that we can fill it in later, and return + // it back as the object that should result from the final deserialization. + m_realObject = deserialized; + return deserialized; + } + + [OnDeserialized] + private void OnDeserialized(StreamingContext context) + { + // We only need to complete deserialization if we were hooking the deserialization process. If + // we have not deserialized an object in the GetRealObject call, then there's nothing more for + // us to do here. + if (m_realObject != null) + { + // Fire the real object's OnDeserialized method if they registered one. Since we replaced + // ourselves as the target of the deserialization, OnDeserialized on the target won't + // automatically get triggered unless we do it manually. + SerializationEvents cache = SerializationEventsCache.GetSerializationEventsForType(m_realObject.GetType()); + cache.InvokeOnDeserialized(m_realObject, context); + m_realObject = null; + } + } + } +#endif +} diff --git a/src/mscorlib/src/System/Runtime/Serialization/SerializationFieldInfo.cs b/src/mscorlib/src/System/Runtime/Serialization/SerializationFieldInfo.cs index 5e7851b..82536ce 100644 --- a/src/mscorlib/src/System/Runtime/Serialization/SerializationFieldInfo.cs +++ b/src/mscorlib/src/System/Runtime/Serialization/SerializationFieldInfo.cs @@ -21,11 +21,9 @@ namespace System.Runtime.Serialization { using System; using System.Reflection; using System.Globalization; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Threading; -#if FEATURE_REMOTING - using System.Runtime.Remoting.Metadata; -#endif //FEATURE_REMOTING internal sealed class SerializationFieldInfo : FieldInfo { @@ -38,8 +36,8 @@ namespace System.Runtime.Serialization { public override int MetadataToken { get { return m_field.MetadataToken; } } internal SerializationFieldInfo(RuntimeFieldInfo field, String namePrefix) { - Contract.Assert(field!=null, "[SerializationFieldInfo.ctor]field!=null"); - Contract.Assert(namePrefix!=null, "[SerializationFieldInfo.ctor]namePrefix!=null"); + Debug.Assert(field!=null, "[SerializationFieldInfo.ctor]field!=null"); + Debug.Assert(namePrefix!=null, "[SerializationFieldInfo.ctor]namePrefix!=null"); m_field = field; m_serializationName = String.Concat(namePrefix, FakeNameSeparatorString, m_field.Name); @@ -91,7 +89,6 @@ namespace System.Runtime.Serialization { return m_field.GetValue(obj); } - [System.Security.SecurityCritical] internal Object InternalGetValue(Object obj) { RtFieldInfo field = m_field as RtFieldInfo; if (field != null) @@ -107,7 +104,6 @@ namespace System.Runtime.Serialization { m_field.SetValue(obj, value, invokeAttr, binder, culture); } - [System.Security.SecurityCritical] internal void InternalSetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture) { RtFieldInfo field = m_field as RtFieldInfo; if (field != null) @@ -136,31 +132,5 @@ namespace System.Runtime.Serialization { return m_field.Attributes; } } - -#if FEATURE_REMOTING - #region Legacy Remoting Cache - private RemotingFieldCachedData m_cachedData; - - internal RemotingFieldCachedData RemotingCache - { - get - { - // This grabs an internal copy of m_cachedData and uses - // that instead of looking at m_cachedData directly because - // the cache may get cleared asynchronously. This prevents - // us from having to take a lock. - RemotingFieldCachedData cache = m_cachedData; - if (cache == null) - { - cache = new RemotingFieldCachedData(this); - RemotingFieldCachedData ret = Interlocked.CompareExchange(ref m_cachedData, cache, null); - if (ret != null) - cache = ret; - } - return cache; - } - } - #endregion -#endif //FEATURE_REMOTING } } diff --git a/src/mscorlib/src/System/Runtime/Serialization/SerializationInfo.cs b/src/mscorlib/src/System/Runtime/Serialization/SerializationInfo.cs index 94e6825..55909c8 100644 --- a/src/mscorlib/src/System/Runtime/Serialization/SerializationInfo.cs +++ b/src/mscorlib/src/System/Runtime/Serialization/SerializationInfo.cs @@ -18,15 +18,11 @@ namespace System.Runtime.Serialization using System.Collections.Generic; using System.Reflection; using System.Runtime.Remoting; -#if FEATURE_REMOTING - using System.Runtime.Remoting.Proxies; -#endif using System.Globalization; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Security; -#if FEATURE_CORECLR using System.Runtime.CompilerServices; -#endif [System.Runtime.InteropServices.ComVisible(true)] public sealed class SerializationInfo @@ -61,12 +57,12 @@ namespace System.Runtime.Serialization { if ((object)type == null) { - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); } if (converter == null) { - throw new ArgumentNullException("converter"); + throw new ArgumentNullException(nameof(converter)); } Contract.EndContractBlock(); @@ -96,7 +92,7 @@ namespace System.Runtime.Serialization { if (null == value) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); @@ -111,12 +107,11 @@ namespace System.Runtime.Serialization { return m_assemName; } - [SecuritySafeCritical] set { if (null == value) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); if (this.requireSameTokenInPartialTrust) @@ -128,12 +123,11 @@ namespace System.Runtime.Serialization } } - [SecuritySafeCritical] public void SetType(Type type) { if ((object)type == null) { - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); } Contract.EndContractBlock(); @@ -170,15 +164,8 @@ namespace System.Runtime.Serialization } } - [SecuritySafeCritical] internal static void DemandForUnsafeAssemblyNameAssignments(string originalAssemblyName, string newAssemblyName) { -#if !FEATURE_CORECLR - if (!IsAssemblyNameAssignmentSafe(originalAssemblyName, newAssemblyName)) - { - CodeAccessPermission.Demand(PermissionType.SecuritySerialization); - } -#endif } internal static bool IsAssemblyNameAssignmentSafe(string originalAssemblyName, string newAssemblyName) @@ -242,7 +229,7 @@ namespace System.Runtime.Serialization private void ExpandArrays() { int newSize; - Contract.Assert(m_members.Length == m_currMember, "[SerializationInfo.ExpandArrays]m_members.Length == m_currMember"); + Debug.Assert(m_members.Length == m_currMember, "[SerializationInfo.ExpandArrays]m_members.Length == m_currMember"); newSize = (m_currMember * 2); @@ -280,12 +267,12 @@ namespace System.Runtime.Serialization { if (null == name) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } if ((object)type == null) { - throw new ArgumentNullException("type"); + throw new ArgumentNullException(nameof(type)); } Contract.EndContractBlock(); @@ -416,19 +403,14 @@ namespace System.Runtime.Serialization **Exceptions: None. All error checking is done with asserts. Although public in coreclr, ** it's not exposed in a contract and is only meant to be used by corefx. ==============================================================================*/ -#if FEATURE_CORECLR // This should not be used by clients: exposing out this functionality would allow children // to overwrite their parent's values. It is public in order to give corefx access to it for // its ObjectManager implementation, but it should not be exposed out of a contract. - public -#else - internal -#endif - void UpdateValue(String name, Object value, Type type) + public void UpdateValue(String name, Object value, Type type) { - Contract.Assert(null != name, "[SerializationInfo.UpdateValue]name!=null"); - Contract.Assert(null != value, "[SerializationInfo.UpdateValue]value!=null"); - Contract.Assert(null != (object)type, "[SerializationInfo.UpdateValue]type!=null"); + Debug.Assert(null != name, "[SerializationInfo.UpdateValue]name!=null"); + Debug.Assert(null != value, "[SerializationInfo.UpdateValue]value!=null"); + Debug.Assert(null != (object)type, "[SerializationInfo.UpdateValue]type!=null"); int index = FindElement(name); if (index < 0) @@ -447,7 +429,7 @@ namespace System.Runtime.Serialization { if (null == name) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } Contract.EndContractBlock(); BCLDebug.Trace("SER", "[SerializationInfo.FindElement]Looking for ", name, " CurrMember is: ", m_currMember); @@ -477,11 +459,11 @@ namespace System.Runtime.Serialization throw new SerializationException(Environment.GetResourceString("Serialization_NotFound", name)); } - Contract.Assert(index < m_data.Length, "[SerializationInfo.GetElement]index=0, "[SerializationInfoEnumerator.ctor]numItems>=0"); - Contract.Assert(members.Length>=numItems, "[SerializationInfoEnumerator.ctor]members.Length>=numItems"); - Contract.Assert(info.Length>=numItems, "[SerializationInfoEnumerator.ctor]info.Length>=numItems"); - Contract.Assert(types.Length>=numItems, "[SerializationInfoEnumerator.ctor]types.Length>=numItems"); + Debug.Assert(members!=null, "[SerializationInfoEnumerator.ctor]members!=null"); + Debug.Assert(info!=null, "[SerializationInfoEnumerator.ctor]info!=null"); + Debug.Assert(types!=null, "[SerializationInfoEnumerator.ctor]types!=null"); + Debug.Assert(numItems>=0, "[SerializationInfoEnumerator.ctor]numItems>=0"); + Debug.Assert(members.Length>=numItems, "[SerializationInfoEnumerator.ctor]members.Length>=numItems"); + Debug.Assert(info.Length>=numItems, "[SerializationInfoEnumerator.ctor]info.Length>=numItems"); + Debug.Assert(types.Length>=numItems, "[SerializationInfoEnumerator.ctor]types.Length>=numItems"); m_members = members; m_data = info; diff --git a/src/mscorlib/src/System/Runtime/Versioning/BinaryCompatibility.cs b/src/mscorlib/src/System/Runtime/Versioning/BinaryCompatibility.cs deleted file mode 100644 index 99e30b5..0000000 --- a/src/mscorlib/src/System/Runtime/Versioning/BinaryCompatibility.cs +++ /dev/null @@ -1,485 +0,0 @@ -// 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. - -/*============================================================ -** -** -** -** -** Purpose: This class is used to determine which binary compatibility -** behaviors are enabled at runtime. A type for -** tracking which target Framework an app was built against, or an -** appdomain-wide setting from the host telling us which .NET -** Framework version we should emulate. -** -** -===========================================================*/ -using System; -using System.Diagnostics.Contracts; -using System.Globalization; -using System.Runtime.CompilerServices; - -namespace System.Runtime.Versioning -{ - // Provides a simple way to test whether an application was built against specific .NET Framework - // flavors and versions, with the intent of allowing Framework developers to mimic behavior of older - // Framework releases. This allows us to make behavioral breaking changes in a binary compatible way, - // for an application. This works at the per-AppDomain level, not process nor per-Assembly. - // - // To opt into newer behavior, applications must specify a TargetFrameworkAttribute on their assembly - // saying what version they targeted, or a host must set this when creating an AppDomain. Note - // that command line apps don't have this attribute! - // - // To use this class: - // Developers need to figure out whether they're working on the phone, desktop, or Silverlight, and - // what version they are introducing a breaking change in. Pick one predicate below, and use that - // to decide whether to run the new or old behavior. Example: - // - // if (BinaryCompatibility.TargetsAtLeast_Phone_V7_1) { - // // new behavior for phone 7.1 and other releases where we will integrate this change, like .NET Framework 4.5 - // } - // else { - // // Legacy behavior - // } - // - // If you are making a breaking change in one specific branch that won't be integrated normally to - // all other branches (ie, say you're making breaking changes to Windows Phone 8 after .NET Framework v4.5 - // has locked down for release), then add in specific predicates for each relevant platform. - // - // Maintainers of this class: - // Revisit the table once per release, perhaps at the end of the last coding milestone, to verify a - // default policy saying whether all quirks from a particular flavor & release should be enabled in - // other releases (ie, should all Windows Phone 8.0 quirks be enabled in .NET Framework v5)? - // - // History: - // Here is the order in which releases were made along with some basic integration information. The idea - // is to track what set of compatibility features are present in each other. - // While we cannot guarantee this list is perfectly linear (ie, a feature could be implemented in the last - // few weeks before shipping and make it into only one of three concommittent releases due to triaging), - // this is a good high level summary of code flow. - // - // Desktop Silverlight Windows Phone - // .NET Framework 3.0 -> Silverlight 2 - // .NET Framework 3.5 - // Silverlight 3 - // Silverlight 4 - // .NET Framework 4 Phone 8.0 - // .NET Framework 4.5 Phone 8.1 - // .NET Framework 4.5.1 Phone 8.1 - // - // (Note: Windows Phone 7.0 was built using the .NET Compact Framework, which forked around v1 or v1.1) - // - // Compatibility Policy decisions: - // If we cannot determine that an app was built for a newer .NET Framework (ie, the app has no - // TargetFrameworkAttribute), then quirks will be enabled to emulate older behavior. - // As such, your test code should define the TargetFrameworkAttribute (which VS does for you) - // if you want to see the new behavior! - [FriendAccessAllowed] - internal static class BinaryCompatibility - { - // Use this for new behavior introduced in the phone branch. It will do the right thing for desktop & SL. - [FriendAccessAllowed] - internal static bool TargetsAtLeast_Phone_V7_1 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Phone_V7_1; } } - - [FriendAccessAllowed] - internal static bool TargetsAtLeast_Phone_V8_0 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Phone_V8_0; } } - - // Use this for new behavior introduced in the Desktop branch. It will do the right thing for Phone & SL. - [FriendAccessAllowed] - internal static bool TargetsAtLeast_Desktop_V4_5 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Desktop_V4_5; } } - [FriendAccessAllowed] - internal static bool TargetsAtLeast_Desktop_V4_5_1 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Desktop_V4_5_1; } } - [FriendAccessAllowed] - internal static bool TargetsAtLeast_Desktop_V4_5_2 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Desktop_V4_5_2; } } - [FriendAccessAllowed] - internal static bool TargetsAtLeast_Desktop_V4_5_3 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Desktop_V4_5_3; } } - [FriendAccessAllowed] - internal static bool TargetsAtLeast_Desktop_V4_5_4 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Desktop_V4_5_4; } } - - [FriendAccessAllowed] - internal static bool TargetsAtLeast_Desktop_V5_0 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Desktop_V5_0; } } - - // Use this for new behavior introduced in the Silverlight branch. It will do the right thing for desktop & Phone. - [FriendAccessAllowed] - internal static bool TargetsAtLeast_Silverlight_V4 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Silverlight_V4; } } - [FriendAccessAllowed] - internal static bool TargetsAtLeast_Silverlight_V5 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Silverlight_V5; } } - [FriendAccessAllowed] - internal static bool TargetsAtLeast_Silverlight_V6 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Silverlight_V6; } } - - [FriendAccessAllowed] - internal static TargetFrameworkId AppWasBuiltForFramework { - [FriendAccessAllowed] - get { - Contract.Ensures(Contract.Result() > TargetFrameworkId.NotYetChecked); - - if (s_AppWasBuiltForFramework == TargetFrameworkId.NotYetChecked) - ReadTargetFrameworkId(); - - return s_AppWasBuiltForFramework; - } - } - - // Version number is major * 10000 + minor * 100 + build (ie, 4.5.1.0 would be version 40501). - [FriendAccessAllowed] - internal static int AppWasBuiltForVersion { - [FriendAccessAllowed] - get { - Contract.Ensures(Contract.Result() > 0 || s_AppWasBuiltForFramework == TargetFrameworkId.Unspecified); - - if (s_AppWasBuiltForFramework == TargetFrameworkId.NotYetChecked) - ReadTargetFrameworkId(); - - Contract.Assert(s_AppWasBuiltForFramework != TargetFrameworkId.Unrecognized); - - return s_AppWasBuiltForVersion; - } - } - - #region private - private static TargetFrameworkId s_AppWasBuiltForFramework; - // Version number is major * 10000 + minor * 100 + build (ie, 4.5.1.0 would be version 40501). - private static int s_AppWasBuiltForVersion; - - readonly static BinaryCompatibilityMap s_map = new BinaryCompatibilityMap(); - - // For parsing a target Framework moniker, from the FrameworkName class - private const char c_componentSeparator = ','; - private const char c_keyValueSeparator = '='; - private const char c_versionValuePrefix = 'v'; - private const String c_versionKey = "Version"; - private const String c_profileKey = "Profile"; - - /// - /// BinaryCompatibilityMap is basically a bitvector. There is a boolean field for each of the - /// properties in BinaryCompatibility - /// - private sealed class BinaryCompatibilityMap - { - // A bit for each property - internal bool TargetsAtLeast_Phone_V7_1; - internal bool TargetsAtLeast_Phone_V8_0; - internal bool TargetsAtLeast_Phone_V8_1; - internal bool TargetsAtLeast_Desktop_V4_5; - internal bool TargetsAtLeast_Desktop_V4_5_1; - internal bool TargetsAtLeast_Desktop_V4_5_2; - internal bool TargetsAtLeast_Desktop_V4_5_3; - internal bool TargetsAtLeast_Desktop_V4_5_4; - internal bool TargetsAtLeast_Desktop_V5_0; - internal bool TargetsAtLeast_Silverlight_V4; - internal bool TargetsAtLeast_Silverlight_V5; - internal bool TargetsAtLeast_Silverlight_V6; - - internal BinaryCompatibilityMap() - { - AddQuirksForFramework(AppWasBuiltForFramework, AppWasBuiltForVersion); - } - - // The purpose of this method is to capture information about integrations & behavioral compatibility - // between our multiple different release vehicles. IE, if a behavior shows up in Silverlight version 5, - // does it show up in the .NET Framework version 4.5 and Windows Phone 8? - // Version number is major * 10000 + minor * 100 + build (ie, 4.5.1.0 would be version 40501). - private void AddQuirksForFramework(TargetFrameworkId builtAgainstFramework, int buildAgainstVersion) - { - Contract.Requires(buildAgainstVersion > 0 || builtAgainstFramework == TargetFrameworkId.Unspecified); - - switch (builtAgainstFramework) - { - case TargetFrameworkId.NetFramework: - case TargetFrameworkId.NetCore: // Treat Windows 8 tailored apps as normal desktop apps - same product - if (buildAgainstVersion >= 50000) - TargetsAtLeast_Desktop_V5_0 = true; - - // Potential 4.5 servicing releases - if (buildAgainstVersion >= 40504) - TargetsAtLeast_Desktop_V4_5_4 = true; - if (buildAgainstVersion >= 40503) - TargetsAtLeast_Desktop_V4_5_3 = true; - if (buildAgainstVersion >= 40502) - TargetsAtLeast_Desktop_V4_5_2 = true; - if (buildAgainstVersion >= 40501) - TargetsAtLeast_Desktop_V4_5_1 = true; - - if (buildAgainstVersion >= 40500) - { - TargetsAtLeast_Desktop_V4_5 = true; - // On XX/XX/XX we integrated all changes from the phone V7_1 into the branch from which contains Desktop V4_5, thus - // Any application built for V4_5 (or above) should have all the quirks for Phone V7_1 turned on. - AddQuirksForFramework(TargetFrameworkId.Phone, 70100); - // All Silverlight 5 behavior should be in the .NET Framework version 4.5 - AddQuirksForFramework(TargetFrameworkId.Silverlight, 50000); - } - break; - - case TargetFrameworkId.Phone: - if (buildAgainstVersion >= 80000) - { - // This is for Apollo apps. For Apollo apps we don't want to enable any of the 4.5 or 4.5.1 quirks - TargetsAtLeast_Phone_V8_0 = true; - //TargetsAtLeast_Desktop_V4_5 = true; - } - if (buildAgainstVersion >= 80100) - { - // For WindowsPhone 8.1 and SL 8.1 scenarios we want to enable both 4.5 and 4.5.1 quirks. - TargetsAtLeast_Desktop_V4_5 = true; - TargetsAtLeast_Desktop_V4_5_1 = true; - } - - if (buildAgainstVersion >= 710) - TargetsAtLeast_Phone_V7_1 = true; - break; - - case TargetFrameworkId.Silverlight: - if (buildAgainstVersion >= 40000) - TargetsAtLeast_Silverlight_V4 = true; - - if (buildAgainstVersion >= 50000) - TargetsAtLeast_Silverlight_V5 = true; - - if (buildAgainstVersion >= 60000) - { - TargetsAtLeast_Silverlight_V6 = true; - } - break; - - case TargetFrameworkId.Unspecified: - break; - - case TargetFrameworkId.NotYetChecked: - case TargetFrameworkId.Unrecognized: - Contract.Assert(false, "Bad framework kind"); - break; - default: - Contract.Assert(false, "Error: we introduced a new Target Framework but did not update our binary compatibility map"); - break; - } - } - } - - #region String Parsing - - // If this doesn't work, perhaps we could fall back to parsing the metadata version number. - private static bool ParseTargetFrameworkMonikerIntoEnum(String targetFrameworkMoniker, out TargetFrameworkId targetFramework, out int targetFrameworkVersion) - { - Contract.Requires(!String.IsNullOrEmpty(targetFrameworkMoniker)); - - targetFramework = TargetFrameworkId.NotYetChecked; - targetFrameworkVersion = 0; - - String identifier = null; - String profile = null; - ParseFrameworkName(targetFrameworkMoniker, out identifier, out targetFrameworkVersion, out profile); - - switch (identifier) - { - case ".NETFramework": - targetFramework = TargetFrameworkId.NetFramework; - break; - - case ".NETPortable": - targetFramework = TargetFrameworkId.Portable; - break; - - case ".NETCore": - targetFramework = TargetFrameworkId.NetCore; - break; - - case "WindowsPhone": - if (targetFrameworkVersion >= 80100) - { - // A TFM of the form WindowsPhone,Version=v8.1 corresponds to SL 8.1 scenario - // and gets the same quirks as WindowsPhoneApp\v8.1 store apps. - targetFramework = TargetFrameworkId.Phone; - } - else - { - // There is no TFM for Apollo or below and hence we assign the targetFramework to Unspecified. - targetFramework = TargetFrameworkId.Unspecified; - } - break; - - case "WindowsPhoneApp": - targetFramework = TargetFrameworkId.Phone; - break; - - case "Silverlight": - targetFramework = TargetFrameworkId.Silverlight; - // Windows Phone 7 is Silverlight,Version=v4.0,Profile=WindowsPhone - // Windows Phone 7.1 is Silverlight,Version=v4.0,Profile=WindowsPhone71 - if (!String.IsNullOrEmpty(profile)) - { - if (profile == "WindowsPhone") - { - targetFramework = TargetFrameworkId.Phone; - targetFrameworkVersion = 70000; - } - else if (profile == "WindowsPhone71") - { - targetFramework = TargetFrameworkId.Phone; - targetFrameworkVersion = 70100; - } - else if (profile == "WindowsPhone8") - { - targetFramework = TargetFrameworkId.Phone; - targetFrameworkVersion = 80000; - } - else if (profile.StartsWith("WindowsPhone", StringComparison.Ordinal)) - { - Contract.Assert(false, "This is a phone app, but we can't tell what version this is!"); - targetFramework = TargetFrameworkId.Unrecognized; - targetFrameworkVersion = 70100; - } - else - { - Contract.Assert(false, String.Format(CultureInfo.InvariantCulture, "Unrecognized Silverlight profile \"{0}\". What is this, an XBox app?", profile)); - targetFramework = TargetFrameworkId.Unrecognized; - } - } - break; - - default: - Contract.Assert(false, String.Format(CultureInfo.InvariantCulture, "Unrecognized Target Framework Moniker in our Binary Compatibility class. Framework name: \"{0}\"", targetFrameworkMoniker)); - targetFramework = TargetFrameworkId.Unrecognized; - break; - } - - return true; - } - - // This code was a constructor copied from the FrameworkName class, which is located in System.dll. - // Parses strings in the following format: ", Version=[v|V], Profile=" - // - The identifier and version is required, profile is optional - // - Only three components are allowed. - // - The version string must be in the System.Version format; an optional "v" or "V" prefix is allowed - private static void ParseFrameworkName(String frameworkName, out String identifier, out int version, out String profile) - { - if (frameworkName == null) - { - throw new ArgumentNullException("frameworkName"); - } - if (frameworkName.Length == 0) - { - throw new ArgumentException(Environment.GetResourceString("Argument_StringZeroLength"), "frameworkName"); - } - Contract.EndContractBlock(); - - String[] components = frameworkName.Split(c_componentSeparator); - version = 0; - - // Identifer and Version are required, Profile is optional. - if (components.Length < 2 || components.Length > 3) - { - throw new ArgumentException(Environment.GetResourceString("Argument_FrameworkNameTooShort"), "frameworkName"); - } - - // - // 1) Parse the "Identifier", which must come first. Trim any whitespace - // - identifier = components[0].Trim(); - - if (identifier.Length == 0) - { - throw new ArgumentException(Environment.GetResourceString("Argument_FrameworkNameInvalid"), "frameworkName"); - } - - bool versionFound = false; - profile = null; - - // - // The required "Version" and optional "Profile" component can be in any order - // - for (int i = 1; i < components.Length; i++) - { - // Get the key/value pair separated by '=' - string[] keyValuePair = components[i].Split(c_keyValueSeparator); - - if (keyValuePair.Length != 2) - { - throw new ArgumentException(Environment.GetResourceString("SR.Argument_FrameworkNameInvalid"), "frameworkName"); - } - - // Get the key and value, trimming any whitespace - string key = keyValuePair[0].Trim(); - string value = keyValuePair[1].Trim(); - - // - // 2) Parse the required "Version" key value - // - if (key.Equals(c_versionKey, StringComparison.OrdinalIgnoreCase)) - { - versionFound = true; - - // Allow the version to include a 'v' or 'V' prefix... - if (value.Length > 0 && (value[0] == c_versionValuePrefix || value[0] == 'V')) - { - value = value.Substring(1); - } - Version realVersion = new Version(value); - // The version class will represent some unset values as -1 internally (instead of 0). - version = realVersion.Major * 10000; - if (realVersion.Minor > 0) - version += realVersion.Minor * 100; - if (realVersion.Build > 0) - version += realVersion.Build; - } - // - // 3) Parse the optional "Profile" key value - // - else if (key.Equals(c_profileKey, StringComparison.OrdinalIgnoreCase)) - { - if (!String.IsNullOrEmpty(value)) - { - profile = value; - } - } - else - { - throw new ArgumentException(Environment.GetResourceString("Argument_FrameworkNameInvalid"), "frameworkName"); - } - } - - if (!versionFound) - { - throw new ArgumentException(Environment.GetResourceString("Argument_FrameworkNameMissingVersion"), "frameworkName"); - } - } - - [System.Security.SecuritySafeCritical] - private static void ReadTargetFrameworkId() - { - String targetFrameworkName = AppDomain.CurrentDomain.GetTargetFrameworkName(); - - var overrideValue = System.Runtime.Versioning.CompatibilitySwitch.GetValueInternal("TargetFrameworkMoniker"); - if (!string.IsNullOrEmpty(overrideValue)) - { - targetFrameworkName = overrideValue; - } - - // Write to a local then to _targetFramework, after writing the version number. - TargetFrameworkId fxId; - int fxVersion = 0; - if (targetFrameworkName == null) - { -#if FEATURE_CORECLR - // if we don't have a value for targetFrameworkName we need to figure out if we should give the newest behavior or not. - if (CompatibilitySwitches.UseLatestBehaviorWhenTFMNotSpecified) - { - fxId = TargetFrameworkId.NetFramework; - fxVersion = 50000; // We are going to default to the latest value for version that we have in our code. - } - else -#endif - fxId = TargetFrameworkId.Unspecified; - } - else if (!ParseTargetFrameworkMonikerIntoEnum(targetFrameworkName, out fxId, out fxVersion)) - fxId = TargetFrameworkId.Unrecognized; - - s_AppWasBuiltForFramework = fxId; - s_AppWasBuiltForVersion = fxVersion; - } - #endregion String Parsing - - #endregion private - } -} diff --git a/src/mscorlib/src/System/Runtime/Versioning/CompatibilitySwitch.cs b/src/mscorlib/src/System/Runtime/Versioning/CompatibilitySwitch.cs index b06c424..6bf8f8c 100644 --- a/src/mscorlib/src/System/Runtime/Versioning/CompatibilitySwitch.cs +++ b/src/mscorlib/src/System/Runtime/Versioning/CompatibilitySwitch.cs @@ -21,13 +21,11 @@ namespace System.Runtime.Versioning * * These apis are for internal use only for FX assmeblies. It has not been decided if they can be used by OOB components due to EULA restrictions */ - [System.Security.SecurityCritical] public static bool IsEnabled(string compatibilitySwitchName) { return IsEnabledInternalCall(compatibilitySwitchName, true); } - [System.Security.SecurityCritical] public static string GetValue(string compatibilitySwitchName) { // This is used by AppContext.TryGetSwitch to check switch overrides in the Windows Quirk DB @@ -36,19 +34,16 @@ namespace System.Runtime.Versioning return GetValueInternalCall(compatibilitySwitchName, true); } - [System.Security.SecurityCritical] internal static bool IsEnabledInternal(string compatibilitySwitchName) { return IsEnabledInternalCall(compatibilitySwitchName, false); } - [System.Security.SecurityCritical] internal static string GetValueInternal(string compatibilitySwitchName) { return GetValueInternalCall(compatibilitySwitchName, false); } - [System.Security.SecurityCritical] [MethodImpl(MethodImplOptions.InternalCall)] internal static extern string GetAppContextOverridesInternalCall(); diff --git a/src/mscorlib/src/System/Runtime/Versioning/ComponentGuaranteesAttribute.cs b/src/mscorlib/src/System/Runtime/Versioning/ComponentGuaranteesAttribute.cs deleted file mode 100644 index 0f906d5..0000000 --- a/src/mscorlib/src/System/Runtime/Versioning/ComponentGuaranteesAttribute.cs +++ /dev/null @@ -1,44 +0,0 @@ -// 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. - -/*============================================================ -** -** -** -** Purpose: Tracking whether a component signs up for a -** a strong contract spanning multiple versions. -** -===========================================================*/ -using System; - -namespace System.Runtime.Versioning { - - [Flags] - [Serializable] - public enum ComponentGuaranteesOptions - { - None = 0, - Exchange = 0x1, - Stable = 0x2, - SideBySide = 0x4, - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | - AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Delegate | - AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | - AttributeTargets.Constructor | AttributeTargets.Event, - AllowMultiple = false, Inherited = false)] - public sealed class ComponentGuaranteesAttribute : Attribute { - private ComponentGuaranteesOptions _guarantees; - - public ComponentGuaranteesAttribute(ComponentGuaranteesOptions guarantees) - { - _guarantees = guarantees; - } - - public ComponentGuaranteesOptions Guarantees { - get { return _guarantees; } - } - } -} diff --git a/src/mscorlib/src/System/Runtime/Versioning/ResourceAttributes.cs b/src/mscorlib/src/System/Runtime/Versioning/ResourceAttributes.cs deleted file mode 100644 index 78a9ddb..0000000 --- a/src/mscorlib/src/System/Runtime/Versioning/ResourceAttributes.cs +++ /dev/null @@ -1,237 +0,0 @@ -// 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. - -/*============================================================ -** -** Purpose: Resource annotation rules. -** -===========================================================*/ -using System; -using System.Diagnostics; -using System.Globalization; -using System.Runtime.CompilerServices; -using System.Text; -using Microsoft.Win32; -using System.Diagnostics.Contracts; - -namespace System.Runtime.Versioning -{ - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Constructor, Inherited = false)] - [Conditional("RESOURCE_ANNOTATION_WORK")] - public sealed class ResourceConsumptionAttribute : Attribute - { - private ResourceScope _consumptionScope; - private ResourceScope _resourceScope; - - public ResourceConsumptionAttribute(ResourceScope resourceScope) - { - _resourceScope = resourceScope; - _consumptionScope = _resourceScope; - } - - public ResourceConsumptionAttribute(ResourceScope resourceScope, ResourceScope consumptionScope) - { - _resourceScope = resourceScope; - _consumptionScope = consumptionScope; - } - - public ResourceScope ResourceScope { - get { return _resourceScope; } - } - - public ResourceScope ConsumptionScope { - get { return _consumptionScope; } - } - } - - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Constructor, Inherited = false)] - [Conditional("RESOURCE_ANNOTATION_WORK")] - public sealed class ResourceExposureAttribute : Attribute - { - private ResourceScope _resourceExposureLevel; - - public ResourceExposureAttribute(ResourceScope exposureLevel) - { - _resourceExposureLevel = exposureLevel; - } - - public ResourceScope ResourceExposureLevel { - get { return _resourceExposureLevel; } - } - } - - - // Default visibility is Public, which isn't specified in this enum. - // Public == the lack of Private or Assembly - // Does this actually work? Need to investigate that. - [Flags] - public enum ResourceScope - { - None = 0, - // Resource type - Machine = 0x1, - Process = 0x2, - AppDomain = 0x4, - Library = 0x8, - // Visibility - Private = 0x10, // Private to this one class. - Assembly = 0x20, // Assembly-level, like C#'s "internal" - } - - - [Flags] - internal enum SxSRequirements - { - None = 0, - AppDomainID = 0x1, - ProcessID = 0x2, - CLRInstanceID = 0x4, // for multiple CLR's within the process - AssemblyName = 0x8, - TypeName = 0x10 - } - - public static class VersioningHelper - { - // These depend on the exact values given to members of the ResourceScope enum. - private const ResourceScope ResTypeMask = ResourceScope.Machine | ResourceScope.Process | ResourceScope.AppDomain | ResourceScope.Library; - private const ResourceScope VisibilityMask = ResourceScope.Private | ResourceScope.Assembly; - - [System.Security.SecuritySafeCritical] - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern int GetRuntimeId(); - - public static String MakeVersionSafeName(String name, ResourceScope from, ResourceScope to) - { - return MakeVersionSafeName(name, from, to, null); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public static String MakeVersionSafeName(String name, ResourceScope from, ResourceScope to, Type type) - { - ResourceScope fromResType = from & ResTypeMask; - ResourceScope toResType = to & ResTypeMask; - if (fromResType > toResType) - throw new ArgumentException(Environment.GetResourceString("Argument_ResourceScopeWrongDirection", fromResType, toResType), "from"); - - SxSRequirements requires = GetRequirements(to, from); - - if ((requires & (SxSRequirements.AssemblyName | SxSRequirements.TypeName)) != 0 && type == null) - throw new ArgumentNullException("type", Environment.GetResourceString("ArgumentNull_TypeRequiredByResourceScope")); - - // Add in process ID, CLR base address, and appdomain ID's. Also, use a character identifier - // to ensure that these can never accidentally overlap (ie, you create enough appdomains and your - // appdomain ID might equal your process ID). - StringBuilder safeName = new StringBuilder(name); - char separator = '_'; - if ((requires & SxSRequirements.ProcessID) != 0) { - safeName.Append(separator); - safeName.Append('p'); - safeName.Append(Win32Native.GetCurrentProcessId()); - } - if ((requires & SxSRequirements.CLRInstanceID) != 0) { - String clrID = GetCLRInstanceString(); - safeName.Append(separator); - safeName.Append('r'); - safeName.Append(clrID); - } - if ((requires & SxSRequirements.AppDomainID) != 0) { - safeName.Append(separator); - safeName.Append("ad"); - safeName.Append(AppDomain.CurrentDomain.Id); - } - if ((requires & SxSRequirements.TypeName) != 0) { - safeName.Append(separator); - safeName.Append(type.Name); - } - if ((requires & SxSRequirements.AssemblyName) != 0) { - safeName.Append(separator); - safeName.Append(type.Assembly.FullName); - } - return safeName.ToString(); - } - - private static String GetCLRInstanceString() - { - int id = GetRuntimeId(); - return id.ToString(CultureInfo.InvariantCulture); - } - - private static SxSRequirements GetRequirements(ResourceScope consumeAsScope, ResourceScope calleeScope) - { - SxSRequirements requires = SxSRequirements.None; - - switch(calleeScope & ResTypeMask) { - case ResourceScope.Machine: - switch(consumeAsScope & ResTypeMask) { - case ResourceScope.Machine: - // No work - break; - - case ResourceScope.Process: - requires |= SxSRequirements.ProcessID; - break; - - case ResourceScope.AppDomain: - requires |= SxSRequirements.AppDomainID | SxSRequirements.CLRInstanceID | SxSRequirements.ProcessID; - break; - - default: - throw new ArgumentException(Environment.GetResourceString("Argument_BadResourceScopeTypeBits", consumeAsScope), "consumeAsScope"); - } - break; - - case ResourceScope.Process: - if ((consumeAsScope & ResourceScope.AppDomain) != 0) - requires |= SxSRequirements.AppDomainID | SxSRequirements.CLRInstanceID; - break; - - case ResourceScope.AppDomain: - // No work - break; - - default: - throw new ArgumentException(Environment.GetResourceString("Argument_BadResourceScopeTypeBits", calleeScope), "calleeScope"); - } - - switch(calleeScope & VisibilityMask) { - case ResourceScope.None: // Public - implied - switch(consumeAsScope & VisibilityMask) { - case ResourceScope.None: // Public - implied - // No work - break; - - case ResourceScope.Assembly: - requires |= SxSRequirements.AssemblyName; - break; - - case ResourceScope.Private: - requires |= SxSRequirements.TypeName | SxSRequirements.AssemblyName; - break; - - default: - throw new ArgumentException(Environment.GetResourceString("Argument_BadResourceScopeVisibilityBits", consumeAsScope), "consumeAsScope"); - } - break; - - case ResourceScope.Assembly: - if ((consumeAsScope & ResourceScope.Private) != 0) - requires |= SxSRequirements.TypeName; - break; - - case ResourceScope.Private: - // No work - break; - - default: - throw new ArgumentException(Environment.GetResourceString("Argument_BadResourceScopeVisibilityBits", calleeScope), "calleeScope"); - } - - if (consumeAsScope == calleeScope) { - Contract.Assert(requires == SxSRequirements.None, "Computed a strange set of required resource scoping. It's probably wrong."); - } - - return requires; - } - } -} diff --git a/src/mscorlib/src/System/Runtime/Versioning/TargetFrameworkAttribute.cs b/src/mscorlib/src/System/Runtime/Versioning/TargetFrameworkAttribute.cs index dbf98c0..600ba3f 100644 --- a/src/mscorlib/src/System/Runtime/Versioning/TargetFrameworkAttribute.cs +++ b/src/mscorlib/src/System/Runtime/Versioning/TargetFrameworkAttribute.cs @@ -26,7 +26,7 @@ namespace System.Runtime.Versioning { public TargetFrameworkAttribute(String frameworkName) { if (frameworkName == null) - throw new ArgumentNullException("frameworkName"); + throw new ArgumentNullException(nameof(frameworkName)); Contract.EndContractBlock(); _frameworkName = frameworkName; } diff --git a/src/mscorlib/src/System/RuntimeHandles.cs b/src/mscorlib/src/System/RuntimeHandles.cs index 24ca45e..127da1e 100644 --- a/src/mscorlib/src/System/RuntimeHandles.cs +++ b/src/mscorlib/src/System/RuntimeHandles.cs @@ -48,11 +48,9 @@ namespace System return type; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static bool IsInstanceOfType(RuntimeType type, Object o); - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static Type GetTypeHelper(Type typeStart, Type[] genericArgs, IntPtr pModifiers, int cModifiers) { Type type = typeStart; @@ -127,14 +125,12 @@ namespace System public IntPtr Value { - [SecurityCritical] get { return m_type != null ? m_type.m_handle : IntPtr.Zero; } } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImpl(MethodImplOptions.InternalCall)] internal static extern IntPtr GetValueInternal(RuntimeTypeHandle handle); @@ -148,7 +144,6 @@ namespace System return m_type == null; } - [System.Security.SecuritySafeCritical] // auto-generated internal static bool IsPrimitive(RuntimeType type) { CorElementType corElemType = GetCorElementType(type); @@ -157,35 +152,30 @@ namespace System corElemType == CorElementType.U; } - [System.Security.SecuritySafeCritical] // auto-generated internal static bool IsByRef(RuntimeType type) { CorElementType corElemType = GetCorElementType(type); return (corElemType == CorElementType.ByRef); } - [System.Security.SecuritySafeCritical] // auto-generated internal static bool IsPointer(RuntimeType type) { CorElementType corElemType = GetCorElementType(type); return (corElemType == CorElementType.Ptr); } - [System.Security.SecuritySafeCritical] // auto-generated internal static bool IsArray(RuntimeType type) { CorElementType corElemType = GetCorElementType(type); return (corElemType == CorElementType.Array || corElemType == CorElementType.SzArray); } - [System.Security.SecuritySafeCritical] // auto-generated internal static bool IsSzArray(RuntimeType type) { CorElementType corElemType = GetCorElementType(type); return (corElemType == CorElementType.SzArray); } - [System.Security.SecuritySafeCritical] // auto-generated internal static bool HasElementType(RuntimeType type) { CorElementType corElemType = GetCorElementType(type); @@ -195,7 +185,6 @@ namespace System || (corElemType == CorElementType.ByRef)); // IsByRef } - [SecurityCritical] internal static IntPtr[] CopyRuntimeTypeHandles(RuntimeTypeHandle[] inHandles, out int length) { if (inHandles == null || inHandles.Length == 0) @@ -213,7 +202,6 @@ namespace System return outHandles; } - [SecurityCritical] internal static IntPtr[] CopyRuntimeTypeHandles(Type[] inHandles, out int length) { if (inHandles == null || inHandles.Length == 0) @@ -231,19 +219,15 @@ namespace System return outHandles; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern Object CreateInstance(RuntimeType type, bool publicOnly, bool noCheck, ref bool canBeCached, ref RuntimeMethodHandleInternal ctor, ref bool bNeedSecurityCheck); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern Object CreateCaInstance(RuntimeType type, IRuntimeMethodInfo ctor); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern Object Allocate(RuntimeType type); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern Object CreateInstanceForAnotherGenericParameter(RuntimeType type, RuntimeType genericParameter); @@ -252,15 +236,12 @@ namespace System return m_type; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static CorElementType GetCorElementType(RuntimeType type); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static RuntimeAssembly GetAssembly(RuntimeType type); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal extern static RuntimeModule GetModule(RuntimeType type); @@ -272,31 +253,24 @@ namespace System return new ModuleHandle(RuntimeTypeHandle.GetModule(m_type)); } - [System.Security.SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static RuntimeType GetBaseType(RuntimeType type); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static TypeAttributes GetAttributes(RuntimeType type); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static RuntimeType GetElementType(RuntimeType type); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static bool CompareCanonicalHandles(RuntimeType left, RuntimeType right); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static int GetArrayRank(RuntimeType type); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static int GetToken(RuntimeType type); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static RuntimeMethodHandleInternal GetMethodAt(RuntimeType type, int slot); @@ -306,14 +280,12 @@ namespace System bool _firstCall; RuntimeMethodHandleInternal _handle; - [System.Security.SecuritySafeCritical] // auto-generated internal IntroducedMethodEnumerator(RuntimeType type) { _handle = RuntimeTypeHandle.GetFirstIntroducedMethod(type); _firstCall = true; } - [System.Security.SecuritySafeCritical] // auto-generated public bool MoveNext() { if (_firstCall) @@ -346,28 +318,22 @@ namespace System return new IntroducedMethodEnumerator(type); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern RuntimeMethodHandleInternal GetFirstIntroducedMethod(RuntimeType type); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void GetNextIntroducedMethod(ref RuntimeMethodHandleInternal method); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static bool GetFields(RuntimeType type, IntPtr* result, int* count); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static Type[] GetInterfaces(RuntimeType type); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void GetConstraints(RuntimeTypeHandle handle, ObjectHandleOnStack types); - [System.Security.SecuritySafeCritical] // auto-generated internal Type[] GetConstraints() { Type[] types = null; @@ -376,118 +342,96 @@ namespace System return types; } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static IntPtr GetGCHandle(RuntimeTypeHandle handle, GCHandleType type); - [System.Security.SecurityCritical] // auto-generated internal IntPtr GetGCHandle(GCHandleType type) { return GetGCHandle(GetNativeHandle(), type); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static int GetNumVirtuals(RuntimeType type); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void VerifyInterfaceIsImplemented(RuntimeTypeHandle handle, RuntimeTypeHandle interfaceHandle); - [System.Security.SecuritySafeCritical] // auto-generated internal void VerifyInterfaceIsImplemented(RuntimeTypeHandle interfaceHandle) { VerifyInterfaceIsImplemented(GetNativeHandle(), interfaceHandle.GetNativeHandle()); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static int GetInterfaceMethodImplementationSlot(RuntimeTypeHandle handle, RuntimeTypeHandle interfaceHandle, RuntimeMethodHandleInternal interfaceMethodHandle); - [System.Security.SecuritySafeCritical] // auto-generated internal int GetInterfaceMethodImplementationSlot(RuntimeTypeHandle interfaceHandle, RuntimeMethodHandleInternal interfaceMethodHandle) { return GetInterfaceMethodImplementationSlot(GetNativeHandle(), interfaceHandle.GetNativeHandle(), interfaceMethodHandle); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static bool IsComObject(RuntimeType type, bool isGenericCOM); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static bool IsContextful(RuntimeType type); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static bool IsInterface(RuntimeType type); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private extern static bool _IsVisible(RuntimeTypeHandle typeHandle); - [System.Security.SecuritySafeCritical] // auto-generated internal static bool IsVisible(RuntimeType type) { return _IsVisible(new RuntimeTypeHandle(type)); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool IsSecurityCritical(RuntimeTypeHandle typeHandle); - [System.Security.SecuritySafeCritical] // auto-generated internal bool IsSecurityCritical() { return IsSecurityCritical(GetNativeHandle()); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool IsSecuritySafeCritical(RuntimeTypeHandle typeHandle); - [System.Security.SecuritySafeCritical] // auto-generated internal bool IsSecuritySafeCritical() { return IsSecuritySafeCritical(GetNativeHandle()); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool IsSecurityTransparent(RuntimeTypeHandle typeHandle); - [System.Security.SecuritySafeCritical] // auto-generated internal bool IsSecurityTransparent() { return IsSecurityTransparent(GetNativeHandle()); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static bool HasProxyAttribute(RuntimeType type); - [System.Security.SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static bool IsValueType(RuntimeType type); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void ConstructName(RuntimeTypeHandle handle, TypeNameFormatFlags formatFlags, StringHandleOnStack retString); - [System.Security.SecuritySafeCritical] // auto-generated internal string ConstructName(TypeNameFormatFlags formatFlags) { string name = null; @@ -495,34 +439,27 @@ namespace System return name; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static void* _GetUtf8Name(RuntimeType type); - [System.Security.SecuritySafeCritical] // auto-generated internal static Utf8String GetUtf8Name(RuntimeType type) { return new Utf8String(_GetUtf8Name(type)); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static bool CanCastTo(RuntimeType type, RuntimeType target); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static RuntimeType GetDeclaringType(RuntimeType type); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static IRuntimeMethodInfo GetDeclaringMethod(RuntimeType type); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void GetDefaultConstructor(RuntimeTypeHandle handle, ObjectHandleOnStack method); - [System.Security.SecuritySafeCritical] // auto-generated internal IRuntimeMethodInfo GetDefaultConstructor() { IRuntimeMethodInfo ctor = null; @@ -530,7 +467,6 @@ namespace System return ctor; } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void GetTypeByName(string name, bool throwOnError, bool ignoreCase, bool reflectionOnly, StackCrawlMarkHandle stackMark, @@ -543,7 +479,6 @@ namespace System return GetTypeByName(name, throwOnError, ignoreCase, reflectionOnly, ref stackMark, IntPtr.Zero, loadTypeFromPartialName); } - [System.Security.SecuritySafeCritical] // auto-generated internal static RuntimeType GetTypeByName(string name, bool throwOnError, bool ignoreCase, bool reflectionOnly, ref StackCrawlMark stackMark, IntPtr pPrivHostBinder, bool loadTypeFromPartialName) @@ -573,16 +508,14 @@ namespace System return GetTypeByName(name, false, false, false, ref stackMark, false); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void GetTypeByNameUsingCARules(string name, RuntimeModule scope, ObjectHandleOnStack type); - [System.Security.SecuritySafeCritical] // auto-generated internal static RuntimeType GetTypeByNameUsingCARules(string name, RuntimeModule scope) { if (name == null || name.Length == 0) - throw new ArgumentException("name"); + throw new ArgumentException(null, nameof(name)); Contract.EndContractBlock(); RuntimeType type = null; @@ -591,12 +524,10 @@ namespace System return type; } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal extern static void GetInstantiation(RuntimeTypeHandle type, ObjectHandleOnStack types, bool fAsRuntimeTypeArray); - [System.Security.SecuritySafeCritical] // auto-generated internal RuntimeType[] GetInstantiationInternal() { RuntimeType[] types = null; @@ -604,7 +535,6 @@ namespace System return types; } - [System.Security.SecuritySafeCritical] // auto-generated internal Type[] GetInstantiationPublic() { Type[] types = null; @@ -612,12 +542,10 @@ namespace System return types; } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void Instantiate(RuntimeTypeHandle handle, IntPtr* pInst, int numGenericArgs, ObjectHandleOnStack type); - [System.Security.SecurityCritical] // auto-generated internal RuntimeType Instantiate(Type[] inst) { // defensive copy to be sure array is not mutated from the outside during processing @@ -633,12 +561,10 @@ namespace System } } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void MakeArray(RuntimeTypeHandle handle, int rank, ObjectHandleOnStack type); - [System.Security.SecuritySafeCritical] // auto-generated internal RuntimeType MakeArray(int rank) { RuntimeType type = null; @@ -646,12 +572,10 @@ namespace System return type; } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void MakeSZArray(RuntimeTypeHandle handle, ObjectHandleOnStack type); - [System.Security.SecuritySafeCritical] // auto-generated internal RuntimeType MakeSZArray() { RuntimeType type = null; @@ -659,12 +583,10 @@ namespace System return type; } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void MakeByRef(RuntimeTypeHandle handle, ObjectHandleOnStack type); - [System.Security.SecuritySafeCritical] // auto-generated internal RuntimeType MakeByRef() { RuntimeType type = null; @@ -672,12 +594,10 @@ namespace System return type; } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void MakePointer(RuntimeTypeHandle handle, ObjectHandleOnStack type); - [System.Security.SecurityCritical] // auto-generated internal RuntimeType MakePointer() { RuntimeType type = null; @@ -685,14 +605,10 @@ namespace System return type; } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal extern static bool IsCollectible(RuntimeTypeHandle handle); -#if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // auto-generated -#endif [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static bool HasInstantiation(RuntimeType type); @@ -701,12 +617,10 @@ namespace System return HasInstantiation(GetTypeChecked()); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void GetGenericTypeDefinition(RuntimeTypeHandle type, ObjectHandleOnStack retType); - [System.Security.SecuritySafeCritical] // auto-generated internal static RuntimeType GetGenericTypeDefinition(RuntimeType type) { RuntimeType retType = type; @@ -717,11 +631,9 @@ namespace System return retType; } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static bool IsGenericTypeDefinition(RuntimeType type); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static bool IsGenericVariable(RuntimeType type); @@ -730,11 +642,9 @@ namespace System return IsGenericVariable(GetTypeChecked()); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static int GetGenericVariableIndex(RuntimeType type); - [System.Security.SecuritySafeCritical] // auto-generated internal int GetGenericVariableIndex() { RuntimeType type = GetTypeChecked(); @@ -745,21 +655,17 @@ namespace System return GetGenericVariableIndex(type); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static bool ContainsGenericVariables(RuntimeType handle); - [System.Security.SecuritySafeCritical] // auto-generated internal bool ContainsGenericVariables() { return ContainsGenericVariables(GetTypeChecked()); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static bool SatisfiesConstraints(RuntimeType paramType, IntPtr *pTypeContext, int typeContextLength, IntPtr *pMethodContext, int methodContextLength, RuntimeType toType); - [System.Security.SecurityCritical] internal static bool SatisfiesConstraints(RuntimeType paramType, RuntimeType[] typeContext, RuntimeType[] methodContext, RuntimeType toType) { int typeContextLength; @@ -778,21 +684,18 @@ namespace System } } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static IntPtr _GetMetadataImport(RuntimeType type); - [System.Security.SecurityCritical] // auto-generated internal static MetadataImport GetMetadataImport(RuntimeType type) { return new MetadataImport(_GetMetadataImport(type), type); } - [System.Security.SecurityCritical] // auto-generated private RuntimeTypeHandle(SerializationInfo info, StreamingContext context) { if(info == null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); RuntimeType m = (RuntimeType)info.GetValue("TypeObj", typeof(RuntimeType)); @@ -803,11 +706,10 @@ namespace System throw new SerializationException(Environment.GetResourceString("Serialization_InsufficientState")); } - [System.Security.SecurityCritical] public void GetObjectData(SerializationInfo info, StreamingContext context) { if(info == null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); if (m_type == null) @@ -815,16 +717,6 @@ namespace System info.AddValue("TypeObj", m_type, typeof(RuntimeType)); } - -#if !FEATURE_CORECLR - [System.Security.SecuritySafeCritical] - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern bool IsEquivalentTo(RuntimeType rtType1, RuntimeType rtType2); - - [System.Security.SecuritySafeCritical] - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern bool IsEquivalentType(RuntimeType type); -#endif // FEATURE_CORECLR } // This type is used to remove the expense of having a managed reference object that is dynamically @@ -853,14 +745,12 @@ namespace System internal IntPtr Value { - [SecurityCritical] get { return m_handle; } } - [SecurityCritical] internal RuntimeMethodHandleInternal(IntPtr value) { m_handle = value; @@ -877,7 +767,6 @@ namespace System m_value = methodHandleValue; } - [SecurityCritical] public RuntimeMethodInfoStub(IntPtr methodHandleValue, object keepalive) { m_keepalive = keepalive; @@ -895,10 +784,8 @@ namespace System object m_e; object m_f; object m_g; -#if FEATURE_REMOTING - object m_h; -#endif #pragma warning restore 169 + public RuntimeMethodHandleInternal m_value; RuntimeMethodHandleInternal IRuntimeMethodInfo.Value @@ -948,18 +835,16 @@ namespace System } // Used by EE - [SecurityCritical] private static IntPtr GetValueInternal(RuntimeMethodHandle rmh) { return rmh.Value; } // ISerializable interface - [System.Security.SecurityCritical] // auto-generated private RuntimeMethodHandle(SerializationInfo info, StreamingContext context) { if(info == null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); MethodBase m =(MethodBase)info.GetValue("MethodObj", typeof(MethodBase)); @@ -970,11 +855,10 @@ namespace System throw new SerializationException(Environment.GetResourceString("Serialization_InsufficientState")); } - [System.Security.SecurityCritical] public void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); if (m_value == null) @@ -988,21 +872,18 @@ namespace System public IntPtr Value { - [SecurityCritical] get { return m_value != null ? m_value.Value.Value : IntPtr.Zero; } } - [SecuritySafeCritical] public override int GetHashCode() { return ValueType.GetHashCodeOfPtr(Value); } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [SecuritySafeCritical] public override bool Equals(object obj) { if (!(obj is RuntimeMethodHandle)) @@ -1024,7 +905,6 @@ namespace System } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [SecuritySafeCritical] public bool Equals(RuntimeMethodHandle handle) { return handle.Value == Value; @@ -1036,12 +916,10 @@ namespace System return m_value == null; } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal extern static IntPtr GetFunctionPointer(RuntimeMethodHandleInternal handle); - [System.Security.SecurityCritical] // auto-generated public IntPtr GetFunctionPointer() { IntPtr ptr = GetFunctionPointer(EnsureNonNullMethodInfo(m_value).Value); @@ -1049,11 +927,9 @@ namespace System return ptr; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal unsafe extern static void CheckLinktimeDemands(IRuntimeMethodInfo method, RuntimeModule module, bool isDecoratedTargetSecurityTransparent); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal extern static bool IsCAVisibleFromDecoratedType( @@ -1062,21 +938,17 @@ namespace System RuntimeTypeHandle sourceTypeHandle, RuntimeModule sourceModule); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern IRuntimeMethodInfo _GetCurrentMethod(ref StackCrawlMark stackMark); - [System.Security.SecuritySafeCritical] // auto-generated internal static IRuntimeMethodInfo GetCurrentMethod(ref StackCrawlMark stackMark) { return _GetCurrentMethod(ref stackMark); } [Pure] - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern MethodAttributes GetAttributes(RuntimeMethodHandleInternal method); - [System.Security.SecurityCritical] // auto-generated internal static MethodAttributes GetAttributes(IRuntimeMethodInfo method) { MethodAttributes retVal = RuntimeMethodHandle.GetAttributes(method.Value); @@ -1084,16 +956,13 @@ namespace System return retVal; } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern MethodImplAttributes GetImplAttributes(IRuntimeMethodInfo method); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void ConstructInstantiation(IRuntimeMethodInfo method, TypeNameFormatFlags format, StringHandleOnStack retString); - [System.Security.SecuritySafeCritical] // auto-generated internal static string ConstructInstantiation(IRuntimeMethodInfo method, TypeNameFormatFlags format) { string name = null; @@ -1101,11 +970,9 @@ namespace System return name; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static RuntimeType GetDeclaringType(RuntimeMethodHandleInternal method); - [System.Security.SecuritySafeCritical] // auto-generated internal static RuntimeType GetDeclaringType(IRuntimeMethodInfo method) { RuntimeType type = RuntimeMethodHandle.GetDeclaringType(method.Value); @@ -1113,11 +980,9 @@ namespace System return type; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static int GetSlot(RuntimeMethodHandleInternal method); - [System.Security.SecurityCritical] // auto-generated internal static int GetSlot(IRuntimeMethodInfo method) { Contract.Requires(method != null); @@ -1127,15 +992,12 @@ namespace System return slot; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static int GetMethodDef(IRuntimeMethodInfo method); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static string GetName(RuntimeMethodHandleInternal method); - [System.Security.SecurityCritical] // auto-generated internal static string GetName(IRuntimeMethodInfo method) { string name = RuntimeMethodHandle.GetName(method.Value); @@ -1143,53 +1005,33 @@ namespace System return name; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static void* _GetUtf8Name(RuntimeMethodHandleInternal method); - [System.Security.SecurityCritical] // auto-generated internal static Utf8String GetUtf8Name(RuntimeMethodHandleInternal method) { return new Utf8String(_GetUtf8Name(method)); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool MatchesNameHash(RuntimeMethodHandleInternal method, uint hash); - [System.Security.SecuritySafeCritical] // auto-generated [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static object InvokeMethod(object target, object[] arguments, Signature sig, bool constructor); #region Private Invocation Helpers - [System.Security.SecurityCritical] // auto-generated internal static INVOCATION_FLAGS GetSecurityFlags(IRuntimeMethodInfo handle) { return (INVOCATION_FLAGS)RuntimeMethodHandle.GetSpecialSecurityFlags(handle); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] static extern internal uint GetSpecialSecurityFlags(IRuntimeMethodInfo method); -#if !FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - static extern internal void PerformSecurityCheck(Object obj, RuntimeMethodHandleInternal method, RuntimeType parent, uint invocationFlags); - - [System.Security.SecurityCritical] - static internal void PerformSecurityCheck(Object obj, IRuntimeMethodInfo method, RuntimeType parent, uint invocationFlags) - { - RuntimeMethodHandle.PerformSecurityCheck(obj, method.Value, parent, invocationFlags); - GC.KeepAlive(method); - return; - } -#endif //!FEATURE_CORECLR #endregion - [System.Security.SecuritySafeCritical] // auto-generated [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] [MethodImplAttribute(MethodImplOptions.InternalCall)] @@ -1198,62 +1040,48 @@ namespace System // This returns true if the token is SecurityTransparent: // just the token - does not consider including module/type etc. - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool _IsTokenSecurityTransparent(RuntimeModule module, int metaDataToken); -#if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // auto-generated -#else - [System.Security.SecurityCritical] -#endif internal static bool IsTokenSecurityTransparent(Module module, int metaDataToken) { return _IsTokenSecurityTransparent(module.ModuleHandle.GetRuntimeModule(), metaDataToken); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool _IsSecurityCritical(IRuntimeMethodInfo method); - [System.Security.SecuritySafeCritical] // auto-generated internal static bool IsSecurityCritical(IRuntimeMethodInfo method) { return _IsSecurityCritical(method); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool _IsSecuritySafeCritical(IRuntimeMethodInfo method); - [System.Security.SecuritySafeCritical] // auto-generated internal static bool IsSecuritySafeCritical(IRuntimeMethodInfo method) { return _IsSecuritySafeCritical(method); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool _IsSecurityTransparent(IRuntimeMethodInfo method); - [System.Security.SecuritySafeCritical] // auto-generated internal static bool IsSecurityTransparent(IRuntimeMethodInfo method) { return _IsSecurityTransparent(method); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void GetMethodInstantiation(RuntimeMethodHandleInternal method, ObjectHandleOnStack types, bool fAsRuntimeTypeArray); - [System.Security.SecuritySafeCritical] // auto-generated internal static RuntimeType[] GetMethodInstantiationInternal(IRuntimeMethodInfo method) { RuntimeType[] types = null; @@ -1262,7 +1090,6 @@ namespace System return types; } - [System.Security.SecuritySafeCritical] // auto-generated internal static RuntimeType[] GetMethodInstantiationInternal(RuntimeMethodHandleInternal method) { RuntimeType[] types = null; @@ -1270,7 +1097,6 @@ namespace System return types; } - [System.Security.SecuritySafeCritical] // auto-generated internal static Type[] GetMethodInstantiationPublic(IRuntimeMethodInfo method) { RuntimeType[] types = null; @@ -1279,11 +1105,9 @@ namespace System return types; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static bool HasMethodInstantiation(RuntimeMethodHandleInternal method); - [System.Security.SecuritySafeCritical] // auto-generated internal static bool HasMethodInstantiation(IRuntimeMethodInfo method) { bool fRet = RuntimeMethodHandle.HasMethodInstantiation(method.Value); @@ -1291,19 +1115,15 @@ namespace System return fRet; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static RuntimeMethodHandleInternal GetStubIfNeeded(RuntimeMethodHandleInternal method, RuntimeType declaringType, RuntimeType[] methodInstantiation); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static RuntimeMethodHandleInternal GetMethodFromCanonical(RuntimeMethodHandleInternal method, RuntimeType declaringType); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static bool IsGenericMethodDefinition(RuntimeMethodHandleInternal method); - [System.Security.SecuritySafeCritical] // auto-generated internal static bool IsGenericMethodDefinition(IRuntimeMethodInfo method) { bool fRet = RuntimeMethodHandle.IsGenericMethodDefinition(method.Value); @@ -1312,16 +1132,13 @@ namespace System } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static bool IsTypicalMethodDefinition(IRuntimeMethodInfo method); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void GetTypicalMethodDefinition(IRuntimeMethodInfo method, ObjectHandleOnStack outMethod); - [System.Security.SecuritySafeCritical] // auto-generated internal static IRuntimeMethodInfo GetTypicalMethodDefinition(IRuntimeMethodInfo method) { if (!IsTypicalMethodDefinition(method)) @@ -1330,12 +1147,10 @@ namespace System return method; } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void StripMethodInstantiation(IRuntimeMethodInfo method, ObjectHandleOnStack outMethod); - [System.Security.SecuritySafeCritical] // auto-generated internal static IRuntimeMethodInfo StripMethodInstantiation(IRuntimeMethodInfo method) { IRuntimeMethodInfo strippedMethod = method; @@ -1345,25 +1160,20 @@ namespace System return strippedMethod; } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static bool IsDynamicMethod(RuntimeMethodHandleInternal method); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal extern static void Destroy(RuntimeMethodHandleInternal method); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static Resolver GetResolver(RuntimeMethodHandleInternal method); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void GetCallerType(StackCrawlMarkHandle stackMark, ObjectHandleOnStack retType); - [System.Security.SecuritySafeCritical] // auto-generated internal static RuntimeType GetCallerType(ref StackCrawlMark stackMark) { RuntimeType type = null; @@ -1372,14 +1182,11 @@ namespace System } [MethodImpl(MethodImplOptions.InternalCall)] - [System.Security.SecuritySafeCritical] // auto-generated internal extern static MethodBody GetMethodBody(IRuntimeMethodInfo method, RuntimeType declaringType); - [System.Security.SecurityCritical] // auto-generated [MethodImpl(MethodImplOptions.InternalCall)] internal extern static bool IsConstructor(RuntimeMethodHandleInternal method); - [System.Security.SecurityCritical] // auto-generated [MethodImpl(MethodImplOptions.InternalCall)] internal extern static LoaderAllocator GetLoaderAllocator(RuntimeMethodHandleInternal method); } @@ -1410,14 +1217,12 @@ namespace System internal IntPtr Value { - [SecurityCritical] get { return m_handle; } } - [SecurityCritical] internal RuntimeFieldHandleInternal(IntPtr value) { m_handle = value; @@ -1437,7 +1242,6 @@ namespace System [StructLayout(LayoutKind.Sequential)] internal class RuntimeFieldInfoStub : IRuntimeFieldInfo { - [SecuritySafeCritical] public RuntimeFieldInfoStub(IntPtr methodHandleValue, object keepalive) { m_keepalive = keepalive; @@ -1451,9 +1255,6 @@ namespace System object m_d; int m_b; object m_e; -#if FEATURE_REMOTING - object m_f; -#endif RuntimeFieldHandleInternal m_fieldHandle; #pragma warning restore 169 @@ -1494,7 +1295,6 @@ namespace System public IntPtr Value { - [SecurityCritical] get { return m_ptr != null ? m_ptr.Value.Value : IntPtr.Zero; @@ -1506,14 +1306,12 @@ namespace System return m_ptr == null; } - [SecuritySafeCritical] public override int GetHashCode() { return ValueType.GetHashCodeOfPtr(Value); } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [SecuritySafeCritical] public override bool Equals(object obj) { if (!(obj is RuntimeFieldHandle)) @@ -1525,7 +1323,6 @@ namespace System } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [SecuritySafeCritical] public unsafe bool Equals(RuntimeFieldHandle handle) { return handle.Value == Value; @@ -1541,30 +1338,23 @@ namespace System return !left.Equals(right); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern String GetName(RtFieldInfo field); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern unsafe void* _GetUtf8Name(RuntimeFieldHandleInternal field); - [System.Security.SecuritySafeCritical] // auto-generated internal static unsafe Utf8String GetUtf8Name(RuntimeFieldHandleInternal field) { return new Utf8String(_GetUtf8Name(field)); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool MatchesNameHash(RuntimeFieldHandleInternal handle, uint hash); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern FieldAttributes GetAttributes(RuntimeFieldHandleInternal field); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern RuntimeType GetApproxDeclaringType(RuntimeFieldHandleInternal field); - [System.Security.SecurityCritical] // auto-generated internal static RuntimeType GetApproxDeclaringType(IRuntimeFieldInfo field) { RuntimeType type = GetApproxDeclaringType(field.Value); @@ -1572,81 +1362,66 @@ namespace System return type; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern int GetToken(RtFieldInfo field); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern Object GetValue(RtFieldInfo field, Object instance, RuntimeType fieldType, RuntimeType declaringType, ref bool domainInitialized); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern Object GetValueDirect(RtFieldInfo field, RuntimeType fieldType, void *pTypedRef, RuntimeType contextType); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void SetValue(RtFieldInfo field, Object obj, Object value, RuntimeType fieldType, FieldAttributes fieldAttr, RuntimeType declaringType, ref bool domainInitialized); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void SetValueDirect(RtFieldInfo field, RuntimeType fieldType, void* pTypedRef, Object value, RuntimeType contextType); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern RuntimeFieldHandleInternal GetStaticFieldForGenericType(RuntimeFieldHandleInternal field, RuntimeType declaringType); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool AcquiresContextFromThis(RuntimeFieldHandleInternal field); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool IsSecurityCritical(RuntimeFieldHandle fieldHandle); - [System.Security.SecuritySafeCritical] // auto-generated internal bool IsSecurityCritical() { return IsSecurityCritical(GetNativeHandle()); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool IsSecuritySafeCritical(RuntimeFieldHandle fieldHandle); - [System.Security.SecuritySafeCritical] // auto-generated internal bool IsSecuritySafeCritical() { return IsSecuritySafeCritical(GetNativeHandle()); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool IsSecurityTransparent(RuntimeFieldHandle fieldHandle); - [System.Security.SecuritySafeCritical] // auto-generated internal bool IsSecurityTransparent() { return IsSecurityTransparent(GetNativeHandle()); } - [SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern void CheckAttributeAccess(RuntimeFieldHandle fieldHandle, RuntimeModule decoratedTarget); // ISerializable interface - [System.Security.SecurityCritical] // auto-generated private RuntimeFieldHandle(SerializationInfo info, StreamingContext context) { if(info==null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); FieldInfo f =(RuntimeFieldInfo) info.GetValue("FieldObj", typeof(RuntimeFieldInfo)); @@ -1660,11 +1435,10 @@ namespace System throw new SerializationException(Environment.GetResourceString("Serialization_InsufficientState")); } - [System.Security.SecurityCritical] public void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); if (m_ptr == null) @@ -1744,11 +1518,9 @@ namespace System return !left.Equals(right); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern IRuntimeMethodInfo GetDynamicMethod(DynamicMethod method, RuntimeModule module, string name, byte[] sig, Resolver resolver); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern int GetToken(RuntimeModule module); @@ -1770,7 +1542,6 @@ namespace System return new RuntimeTypeHandle(ModuleHandle.ResolveTypeHandleInternal(GetRuntimeModule(), typeToken, typeInstantiationContext, methodInstantiationContext)); } - [System.Security.SecuritySafeCritical] // auto-generated internal static RuntimeType ResolveTypeHandleInternal(RuntimeModule module, int typeToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext) { ValidateModulePointer(module); @@ -1792,7 +1563,6 @@ namespace System } } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void ResolveType(RuntimeModule module, @@ -1812,7 +1582,6 @@ namespace System return new RuntimeMethodHandle(ResolveMethodHandleInternal(GetRuntimeModule(), methodToken, typeInstantiationContext, methodInstantiationContext)); } - [System.Security.SecuritySafeCritical] // auto-generated internal static IRuntimeMethodInfo ResolveMethodHandleInternal(RuntimeModule module, int methodToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext) { int typeInstCount, methodInstCount; @@ -1827,7 +1596,6 @@ namespace System return retVal; } - [System.Security.SecurityCritical] // auto-generated internal static RuntimeMethodHandleInternal ResolveMethodHandleInternalCore(RuntimeModule module, int methodToken, IntPtr[] typeInstantiationContext, int typeInstCount, IntPtr[] methodInstantiationContext, int methodInstCount) { ValidateModulePointer(module); @@ -1841,7 +1609,6 @@ namespace System } } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static RuntimeMethodHandleInternal ResolveMethod(RuntimeModule module, @@ -1857,7 +1624,6 @@ namespace System public RuntimeFieldHandle ResolveFieldHandle(int fieldToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext) { return new RuntimeFieldHandle(ResolveFieldHandleInternal(GetRuntimeModule(), fieldToken, typeInstantiationContext, methodInstantiationContext)); } - [System.Security.SecuritySafeCritical] // auto-generated internal static IRuntimeFieldInfo ResolveFieldHandleInternal(RuntimeModule module, int fieldToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext) { ValidateModulePointer(module); @@ -1880,7 +1646,6 @@ namespace System } } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void ResolveField(RuntimeModule module, @@ -1891,23 +1656,19 @@ namespace System int methodInstCount, ObjectHandleOnStack retField); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static bool _ContainsPropertyMatchingHash(RuntimeModule module, int propertyToken, uint hash); - [System.Security.SecurityCritical] // auto-generated internal static bool ContainsPropertyMatchingHash(RuntimeModule module, int propertyToken, uint hash) { return _ContainsPropertyMatchingHash(module.GetNativeHandle(), propertyToken, hash); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void GetAssembly(RuntimeModule handle, ObjectHandleOnStack retAssembly); - [System.Security.SecuritySafeCritical] // auto-generated internal static RuntimeAssembly GetAssembly(RuntimeModule module) { RuntimeAssembly retAssembly = null; @@ -1915,12 +1676,10 @@ namespace System return retAssembly; } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal extern static void GetModuleType(RuntimeModule handle, ObjectHandleOnStack type); - [System.Security.SecuritySafeCritical] // auto-generated internal static RuntimeType GetModuleType(RuntimeModule module) { RuntimeType type = null; @@ -1928,13 +1687,11 @@ namespace System return type; } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private extern static void GetPEKind(RuntimeModule handle, out int peKind, out int machine); // making this internal, used by Module.GetPEKind - [System.Security.SecuritySafeCritical] // auto-generated internal static void GetPEKind(RuntimeModule module, out PortableExecutableKinds peKind, out ImageFileMachine machine) { int lKind, lMachine; @@ -1943,21 +1700,17 @@ namespace System machine = (ImageFileMachine)lMachine; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static int GetMDStreamVersion(RuntimeModule module); public int MDStreamVersion { - [System.Security.SecuritySafeCritical] // auto-generated get { return GetMDStreamVersion(GetRuntimeModule().GetNativeHandle()); } } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static IntPtr _GetMetadataImport(RuntimeModule module); - [System.Security.SecurityCritical] // auto-generated internal static MetadataImport GetMetadataImport(RuntimeModule module) { return new MetadataImport(_GetMetadataImport(module.GetNativeHandle()), module); @@ -1990,7 +1743,6 @@ namespace System #endregion #region FCalls - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern void GetSignature( void* pCorSig, int cCorSig, @@ -2006,7 +1758,6 @@ namespace System internal RuntimeType m_declaringType; internal RuntimeType m_returnTypeORfieldType; internal object m_keepalive; - [SecurityCritical] internal void* m_sig; internal int m_managedCallingConventionAndArgIteratorFlags; // lowest byte is CallingConvention, upper 3 bytes are ArgIterator flags internal int m_nSizeOfArgStack; @@ -2015,7 +1766,6 @@ namespace System #endregion #region Constructors - [System.Security.SecuritySafeCritical] // auto-generated public Signature ( IRuntimeMethodInfo method, RuntimeType[] arguments, @@ -2030,20 +1780,17 @@ namespace System GetSignature(null, 0, new RuntimeFieldHandleInternal(), method, null); } - [System.Security.SecuritySafeCritical] // auto-generated public Signature(IRuntimeMethodInfo methodHandle, RuntimeType declaringType) { GetSignature(null, 0, new RuntimeFieldHandleInternal(), methodHandle, declaringType); } - [System.Security.SecurityCritical] // auto-generated public Signature(IRuntimeFieldInfo fieldHandle, RuntimeType declaringType) { GetSignature(null, 0, fieldHandle.Value, null, declaringType); GC.KeepAlive(fieldHandle); } - [System.Security.SecurityCritical] // auto-generated public Signature(void* pCorSig, int cCorSig, RuntimeType declaringType) { GetSignature(pCorSig, cCorSig, new RuntimeFieldHandleInternal(), null, declaringType); @@ -2056,11 +1803,9 @@ namespace System internal RuntimeType ReturnType { get { return m_returnTypeORfieldType; } } internal RuntimeType FieldType { get { return m_returnTypeORfieldType; } } - [System.Security.SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool CompareSig(Signature sig1, Signature sig2); - [System.Security.SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern Type[] GetCustomModifiers(int position, bool required); #endregion @@ -2083,12 +1828,10 @@ namespace System internal abstract RuntimeType GetJitContext(ref int securityControlFlags); internal abstract byte[] GetCodeInfo(ref int stackSize, ref int initLocals, ref int EHCount); internal abstract byte[] GetLocalsSignature(); - [System.Security.SecurityCritical] // takes a pointer parameter internal abstract unsafe void GetEHInfo(int EHNumber, void* exception); internal abstract unsafe byte[] GetRawEHInfo(); // token resolution internal abstract String GetStringLiteral(int token); - [System.Security.SecurityCritical] // passes a pointer out internal abstract void ResolveToken(int token, out IntPtr typeHandle, out IntPtr methodHandle, out IntPtr fieldHandle); internal abstract byte[] ResolveSignature(int token, int fromMethod); // diff --git a/src/mscorlib/src/System/SByte.cs b/src/mscorlib/src/System/SByte.cs index a9ec9cf..da6ac5c 100644 --- a/src/mscorlib/src/System/SByte.cs +++ b/src/mscorlib/src/System/SByte.cs @@ -73,13 +73,11 @@ namespace System { // Provides a string representation of a byte. - [System.Security.SecuritySafeCritical] // auto-generated public override String ToString() { Contract.Ensures(Contract.Result() != null); return Number.FormatInt32(m_value, null, NumberFormatInfo.CurrentInfo); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(IFormatProvider provider) { Contract.Ensures(Contract.Result() != null); return Number.FormatInt32(m_value, null, NumberFormatInfo.GetInstance(provider)); @@ -95,7 +93,6 @@ namespace System { return ToString(format, NumberFormatInfo.GetInstance(provider)); } - [System.Security.SecuritySafeCritical] // auto-generated private String ToString(String format, NumberFormatInfo info) { Contract.Ensures(Contract.Result() != null); diff --git a/src/mscorlib/src/System/Security/AccessControl/Enums.cs b/src/mscorlib/src/System/Security/AccessControl/Enums.cs index c52176a..20f5c5f 100644 --- a/src/mscorlib/src/System/Security/AccessControl/Enums.cs +++ b/src/mscorlib/src/System/Security/AccessControl/Enums.cs @@ -70,12 +70,6 @@ namespace System.Security.AccessControl [Flags] public enum AccessControlActions { -#if FEATURE_MACL - None = 0, - View = 1, - Change = 2 -#else None = 0 -#endif } } diff --git a/src/mscorlib/src/System/Security/Attributes.cs b/src/mscorlib/src/System/Security/Attributes.cs index d222922..e4ebc53 100644 --- a/src/mscorlib/src/System/Security/Attributes.cs +++ b/src/mscorlib/src/System/Security/Attributes.cs @@ -57,14 +57,12 @@ namespace System.Security NotVisibleByDefault = 1 } -#if !FEATURE_CORECLR [Obsolete("SecurityCriticalScope is only used for .NET 2.0 transparency compatibility.")] public enum SecurityCriticalScope { Explicit = 0, Everything = 0x1 } -#endif // FEATURE_CORECLR // SecurityCriticalAttribute // Indicates that the decorated code or assembly performs security critical operations (e.g. Assert, "unsafe", LinkDemand, etc.) @@ -84,12 +82,10 @@ namespace System.Security { #pragma warning disable 618 // We still use SecurityCriticalScope for v2 compat -#if !FEATURE_CORECLR - private SecurityCriticalScope _val; -#endif // FEATURE_CORECLR + private SecurityCriticalScope _val; + public SecurityCriticalAttribute () {} -#if !FEATURE_CORECLR public SecurityCriticalAttribute(SecurityCriticalScope scope) { _val = scope; @@ -101,7 +97,6 @@ namespace System.Security return _val; } } -#endif // FEATURE_CORECLR #pragma warning restore 618 } @@ -167,7 +162,6 @@ namespace System.Security public SecurityTransparentAttribute () {} } -#if !FEATURE_CORECLR public enum SecurityRuleSet : byte { None = 0, @@ -205,5 +199,4 @@ namespace System.Security get { return m_ruleSet; } } } -#endif // !FEATURE_CORECLR } diff --git a/src/mscorlib/src/System/Security/BuiltInPermissionSets.cs b/src/mscorlib/src/System/Security/BuiltInPermissionSets.cs index e29dec3..4853957 100644 --- a/src/mscorlib/src/System/Security/BuiltInPermissionSets.cs +++ b/src/mscorlib/src/System/Security/BuiltInPermissionSets.cs @@ -6,6 +6,7 @@ // using System; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Security.Permissions; using Microsoft.Win32; @@ -180,30 +181,6 @@ namespace System.Security Flags = ""SkipVerification"" /> "; -#if FEATURE_CAS_POLICY - private const string s_wpfExtensionXml = - @" - - - "; - - private const string s_wpfExtensionUnrestrictedXml = - @" - - - "; -#endif //FEATURE_CAS_POLICY - // // Built in permission set objects // @@ -222,11 +199,7 @@ namespace System.Security internal static NamedPermissionSet Everything { - get { return GetOrDeserializeExtendablePermissionSet(ref s_everything, s_everythingXml -#if FEATURE_CAS_POLICY - , s_wpfExtensionUnrestrictedXml -#endif // FEATURE_CAS_POLICY - ); } + get { return GetOrDeserializeExtendablePermissionSet(ref s_everything, s_everythingXml); } } internal static NamedPermissionSet Execution @@ -241,20 +214,12 @@ namespace System.Security internal static NamedPermissionSet Internet { - get { return GetOrDeserializeExtendablePermissionSet(ref s_internet, s_internetXml -#if FEATURE_CAS_POLICY - , s_wpfExtensionXml -#endif // FEATURE_CAS_POLICY - ); } + get { return GetOrDeserializeExtendablePermissionSet(ref s_internet, s_internetXml); } } internal static NamedPermissionSet LocalIntranet { - get { return GetOrDeserializeExtendablePermissionSet(ref s_localIntranet, s_localIntranetXml -#if FEATURE_CAS_POLICY - , s_wpfExtensionXml -#endif // FEATURE_CAS_POLICY - ); } + get { return GetOrDeserializeExtendablePermissionSet(ref s_localIntranet, s_localIntranetXml); } } internal static NamedPermissionSet Nothing @@ -272,71 +237,19 @@ namespace System.Security // set extensions if necessary // - private static NamedPermissionSet GetOrDeserializeExtendablePermissionSet(ref NamedPermissionSet permissionSet, - string permissionSetXml -#if FEATURE_CAS_POLICY - ,string extensionXml -#endif // FEATURE_CAS_POLICY - ) + private static NamedPermissionSet GetOrDeserializeExtendablePermissionSet( + ref NamedPermissionSet permissionSet, + string permissionSetXml) { Contract.Requires(!String.IsNullOrEmpty(permissionSetXml)); -#if FEATURE_CAS_POLICY - Contract.Requires(!String.IsNullOrEmpty(extensionXml)); -#endif // FEATURE_CAS_POLICY - - if (permissionSet == null) - { -#if FEATURE_CAS_POLICY - SecurityElement securityElement = SecurityElement.FromString(permissionSetXml); - NamedPermissionSet deserializedPermissionSet = new NamedPermissionSet(securityElement); - - PermissionSet extensions = GetPermissionSetExtensions(extensionXml); - deserializedPermissionSet.InplaceUnion(extensions); - - permissionSet = deserializedPermissionSet; -#endif // FEATURE_CAS_POLICY - } - return permissionSet.Copy() as NamedPermissionSet; } private static NamedPermissionSet GetOrDeserializePermissionSet(ref NamedPermissionSet permissionSet, string permissionSetXml) { - Contract.Assert(!String.IsNullOrEmpty(permissionSetXml)); - -#if FEATURE_CAS_POLICY - if (permissionSet == null) - { - SecurityElement securityElement = SecurityElement.FromString(permissionSetXml); - NamedPermissionSet deserializedPermissionSet = new NamedPermissionSet(securityElement); - - permissionSet = deserializedPermissionSet; - } -#endif // FEATURE_CAS_POLICY - + Debug.Assert(!String.IsNullOrEmpty(permissionSetXml)); return permissionSet.Copy() as NamedPermissionSet; } - -#if FEATURE_CAS_POLICY - private static PermissionSet GetPermissionSetExtensions(string extensionXml) - { - Contract.Requires(!String.IsNullOrEmpty(extensionXml)); - - SecurityElement se = SecurityElement.FromString(extensionXml); - - // Return the permission set extension only if WPF is in the present framework profile. - // XMLUtil.GetClassFromElement() helps do the quickest check, with no exception thrown and - // minimal parsing. - SecurityElement firstPermission = (SecurityElement)se.Children[0]; - if (System.Security.Util.XMLUtil.GetClassFromElement(firstPermission, /*ignoreTypeLoadFailures*/true) != null) - { - PermissionSet extensions = new NamedPermissionSet(se); - return extensions; - } - - return null; - } -#endif // FEATURE_CAS_POLICY } } diff --git a/src/mscorlib/src/System/Security/CodeAccessPermission.cs b/src/mscorlib/src/System/Security/CodeAccessPermission.cs index 61334c2..70504d9 100644 --- a/src/mscorlib/src/System/Security/CodeAccessPermission.cs +++ b/src/mscorlib/src/System/Security/CodeAccessPermission.cs @@ -13,20 +13,16 @@ namespace System.Security using System.Collections; using System.Text; using System; - using System.Diagnostics; + using System.Diagnostics; using System.Diagnostics.Contracts; using IUnrestrictedPermission = System.Security.Permissions.IUnrestrictedPermission; [Serializable] -#if !FEATURE_CORECLR - [SecurityPermissionAttribute( SecurityAction.InheritanceDemand, ControlEvidence = true, ControlPolicy = true )] -#endif [System.Runtime.InteropServices.ComVisible(true)] abstract public class CodeAccessPermission : IPermission, ISecurityEncodable, IStackWalk { // Static methods for manipulation of stack - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static void RevertAssert() { @@ -34,7 +30,6 @@ namespace System.Security SecurityRuntime.RevertAssert(ref stackMark); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable [Obsolete("Deny is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] public static void RevertDeny() @@ -43,7 +38,6 @@ namespace System.Security SecurityRuntime.RevertDeny(ref stackMark); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static void RevertPermitOnly() { @@ -51,7 +45,6 @@ namespace System.Security SecurityRuntime.RevertPermitOnly(ref stackMark); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static void RevertAll() { @@ -66,7 +59,6 @@ namespace System.Security // Mark this method as requiring a security object on the caller's frame // so the caller won't be inlined (which would mess up stack crawling). - [System.Security.SecuritySafeCritical] // auto-generated [DynamicSecurityMethodAttribute()] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public void Demand() @@ -78,7 +70,6 @@ namespace System.Security } } - [System.Security.SecuritySafeCritical] // auto-generated [DynamicSecurityMethodAttribute()] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable internal static void Demand(PermissionType permissionType) @@ -87,7 +78,7 @@ namespace System.Security // without having to create objects. // The security annotation fxcop rule that flags all methods with a Demand() has logic // which checks for methods named Demand in types that implement IPermission or IStackWalk. - Contract.Assert(new StackFrame().GetMethod().Name.Equals("Demand"), "This method needs to be named Demand"); + Debug.Assert(new StackFrame().GetMethod().Name.Equals("Demand"), "This method needs to be named Demand"); StackCrawlMark stackMark = StackCrawlMark.LookForMyCallersCaller; CodeAccessSecurityEngine.SpecialDemand(permissionType, ref stackMark); @@ -96,7 +87,6 @@ namespace System.Security // Metadata for this method should be flaged with REQ_SQ so that // EE can allocate space on the stack frame for FrameSecurityDescriptor - [System.Security.SecuritySafeCritical] // auto-generated [DynamicSecurityMethodAttribute()] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public void Assert() @@ -106,7 +96,6 @@ namespace System.Security } - [System.Security.SecuritySafeCritical] // auto-generated [DynamicSecurityMethodAttribute()] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable static internal void Assert(bool allPossible) @@ -115,7 +104,7 @@ namespace System.Security // without having to new a PermissionSet. // The security annotation fxcop rule that flags all methods with an Assert() has logic // which checks for methods named Assert in types that implement IPermission or IStackWalk. - Contract.Assert(new StackFrame().GetMethod().Name.Equals("Assert"), "This method needs to be named Assert"); + Debug.Assert(new StackFrame().GetMethod().Name.Equals("Assert"), "This method needs to be named Assert"); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; SecurityRuntime.AssertAllPossible(ref stackMark); @@ -124,7 +113,6 @@ namespace System.Security // Metadata for this method should be flaged with REQ_SQ so that // EE can allocate space on the stack frame for FrameSecurityDescriptor - [System.Security.SecuritySafeCritical] // auto-generated [DynamicSecurityMethodAttribute()] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable [Obsolete("Deny is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] @@ -137,7 +125,6 @@ namespace System.Security // Metadata for this method should be flaged with REQ_SQ so that // EE can allocate space on the stack frame for FrameSecurityDescriptor - [System.Security.SecuritySafeCritical] // auto-generated [DynamicSecurityMethodAttribute()] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public void PermitOnly() @@ -160,48 +147,6 @@ namespace System.Security // otherwise we don't support it. throw new NotSupportedException(Environment.GetResourceString( "NotSupported_SecurityPermissionUnion" )); } - -#if FEATURE_CAS_POLICY - static internal SecurityElement CreatePermissionElement( IPermission perm, String permname ) - { - SecurityElement root = new SecurityElement( "IPermission" ); - XMLUtil.AddClassAttribute( root, perm.GetType(), permname ); - // If you hit this assert then most likely you are trying to change the name of this class. - // This is ok as long as you change the hard coded string above and change the assert below. - Contract.Assert( perm.GetType().FullName.Equals( permname ), "Incorrect class name passed in! Was: " + permname + " Should be " + perm.GetType().FullName); - - root.AddAttribute( "version", "1" ); - return root; - } - - static internal void ValidateElement( SecurityElement elem, IPermission perm ) - { - if (elem == null) - throw new ArgumentNullException( "elem" ); - Contract.EndContractBlock(); - - if (!XMLUtil.IsPermissionElement( perm, elem )) - throw new ArgumentException( Environment.GetResourceString( "Argument_NotAPermissionElement")); - - String version = elem.Attribute( "version" ); - - if (version != null && !version.Equals( "1" )) - throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidXMLBadVersion") ); - } - - abstract public SecurityElement ToXml(); - abstract public void FromXml( SecurityElement elem ); - - // - // Unimplemented interface methods - // (as a reminder only) - // - - public override String ToString() - { - return ToXml().ToString(); - } -#endif // FEATURE_CAS_POLICY // // HELPERS FOR IMPLEMENTING ABSTRACT METHODS @@ -258,26 +203,26 @@ namespace System.Security internal bool CheckDemand(CodeAccessPermission grant) { - Contract.Assert( grant == null || grant.GetType().Equals( this.GetType() ), "CheckDemand not defined for permissions of different type" ); + Debug.Assert( grant == null || grant.GetType().Equals( this.GetType() ), "CheckDemand not defined for permissions of different type" ); return IsSubsetOf( grant ); } internal bool CheckPermitOnly(CodeAccessPermission permitted) { - Contract.Assert( permitted == null || permitted.GetType().Equals( this.GetType() ), "CheckPermitOnly not defined for permissions of different type" ); + Debug.Assert( permitted == null || permitted.GetType().Equals( this.GetType() ), "CheckPermitOnly not defined for permissions of different type" ); return IsSubsetOf( permitted ); } internal bool CheckDeny(CodeAccessPermission denied) { - Contract.Assert( denied == null || denied.GetType().Equals( this.GetType() ), "CheckDeny not defined for permissions of different type" ); + Debug.Assert( denied == null || denied.GetType().Equals( this.GetType() ), "CheckDeny not defined for permissions of different type" ); IPermission intersectPerm = Intersect(denied); return (intersectPerm == null || intersectPerm.IsSubsetOf(null)); } internal bool CheckAssert(CodeAccessPermission asserted) { - Contract.Assert( asserted == null || asserted.GetType().Equals( this.GetType() ), "CheckPermitOnly not defined for permissions of different type" ); + Debug.Assert( asserted == null || asserted.GetType().Equals( this.GetType() ), "CheckPermitOnly not defined for permissions of different type" ); return IsSubsetOf( asserted ); } } diff --git a/src/mscorlib/src/System/Security/CodeAccessSecurityEngine.cs b/src/mscorlib/src/System/Security/CodeAccessSecurityEngine.cs index 2a1cf9a..d86897c 100644 --- a/src/mscorlib/src/System/Security/CodeAccessSecurityEngine.cs +++ b/src/mscorlib/src/System/Security/CodeAccessSecurityEngine.cs @@ -15,6 +15,7 @@ namespace System.Security { using System.Globalization; using System.Security.Policy; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; // Used in DemandInternal, to remember the result of previous demands @@ -52,40 +53,22 @@ namespace System.Security { internal static SecurityPermission AssertPermission; internal static PermissionToken AssertPermissionToken; - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void SpecialDemand(PermissionType whatPermission, ref StackCrawlMark stackMark); - [System.Security.SecurityCritical] // auto-generated [System.Diagnostics.Conditional( "_DEBUG" )] private static void DEBUG_OUT( String str ) { -#if _DEBUG +#if _DEBUG if (debug) - { -#if !FEATURE_CORECLR - if (to_file) - { - System.Text.StringBuilder sb = new System.Text.StringBuilder(); - sb.Append( str ); - sb.Append ((char)13) ; - sb.Append ((char)10) ; - PolicyManager.DebugOut( file, sb.ToString() ); - } - else -#endif - Console.WriteLine( str ); - } -#endif + Console.WriteLine( str ); +#endif } - -#if _DEBUG + +#if _DEBUG private static bool debug = false; -#if !FEATURE_CORECLR - private static readonly bool to_file = false; -#endif private const String file = "d:\\foo\\debug.txt"; -#endif +#endif // static default constructor. This will be called before any of the static members are accessed. static CodeAccessSecurityEngine() @@ -96,7 +79,6 @@ namespace System.Security { AssertPermissionToken = PermissionToken.GetToken(AssertPermission); } - [System.Security.SecurityCritical] // auto-generated #pragma warning disable 618 private static void ThrowSecurityException(RuntimeAssembly asm, PermissionSet granted, PermissionSet refused, RuntimeMethodHandleInternal rmh, SecurityAction action, Object demand, IPermission permThatFailed) #pragma warning restore 618 @@ -109,20 +91,15 @@ namespace System.Security { // there will be an infinite recursion that overflows the stack. PermissionSet.s_fullTrust.Assert(); asmName = asm.GetName(); -#if FEATURE_CAS_POLICY - if(asm != Assembly.GetExecutingAssembly()) // this condition is to avoid having to marshal mscorlib's evidence (which is always in teh default domain) to the current domain - asmEvidence = asm.Evidence; -#endif // FEATURE_CAS_POLICY } throw SecurityException.MakeSecurityException(asmName, asmEvidence, granted, refused, rmh, action, demand, permThatFailed); } - [System.Security.SecurityCritical] // auto-generated #pragma warning disable 618 private static void ThrowSecurityException(Object assemblyOrString, PermissionSet granted, PermissionSet refused, RuntimeMethodHandleInternal rmh, SecurityAction action, Object demand, IPermission permThatFailed) #pragma warning restore 618 { - Contract.Assert((assemblyOrString == null || assemblyOrString is RuntimeAssembly || assemblyOrString is String), "Must pass in an Assembly object or String object here"); + Debug.Assert((assemblyOrString == null || assemblyOrString is RuntimeAssembly || assemblyOrString is String), "Must pass in an Assembly object or String object here"); if (assemblyOrString == null || assemblyOrString is RuntimeAssembly) ThrowSecurityException((RuntimeAssembly)assemblyOrString, granted, refused, rmh, action, demand, permThatFailed); @@ -134,7 +111,6 @@ namespace System.Security { } #if FEATURE_COMPRESSEDSTACK - [System.Security.SecurityCritical] // auto-generated internal static void CheckSetHelper(CompressedStack cs, PermissionSet grants, PermissionSet refused, @@ -149,9 +125,6 @@ namespace System.Security { CheckSetHelper(grants, refused, demands, rmh, (Object)asm, action, true); } #else // FEATURE_COMPRESSEDSTACK - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif #pragma warning disable 618 internal static void CheckSetHelper(Object notUsed, PermissionSet grants, @@ -165,14 +138,13 @@ namespace System.Security { // To reduce the amount of ifdef-code-churn, a dummy arg is used for the first parameter - instead of a CompressedStack object, // we use a System.Object that should always be null. If we tried to change the signature of the function, there will need to be // corresponding changes in VM (metasig.h, mscorlib.h, securitystackwalk.cpp, number of elements in the arg array, etc.) - Contract.Assert(notUsed == null, "Should not reach here with a non-null first arg which is the CompressedStack"); + Debug.Assert(notUsed == null, "Should not reach here with a non-null first arg which is the CompressedStack"); CheckSetHelper(grants, refused, demands, rmh, (Object)asm, action, true); } #endif // FEATURE_COMPRESSEDSTACK - [System.Security.SecurityCritical] // auto-generated #pragma warning disable 618 internal static bool CheckSetHelper(PermissionSet grants, PermissionSet refused, @@ -183,19 +155,7 @@ namespace System.Security { bool throwException) #pragma warning restore 618 { - - Contract.Assert(demands != null, "Should not reach here with a null demand set"); -#if _DEBUG && FEATURE_CAS_POLICY - if (debug) - { - DEBUG_OUT("Granted: "); - DEBUG_OUT(grants.ToXml().ToString()); - DEBUG_OUT("Refused: "); - DEBUG_OUT(refused != null ? refused.ToXml().ToString() : ""); - DEBUG_OUT("Demanded: "); - DEBUG_OUT(demands!=null ? demands.ToXml().ToString() : ""); - } -#endif // _DEBUG && FEATURE_CAS_POLICY + Debug.Assert(demands != null, "Should not reach here with a null demand set"); IPermission permThatFailed = null; if (grants != null) @@ -248,7 +208,6 @@ namespace System.Security { return true; } #if FEATURE_COMPRESSEDSTACK - [System.Security.SecurityCritical] // auto-generated internal static void CheckHelper(CompressedStack cs, PermissionSet grantedSet, PermissionSet refusedSet, @@ -264,9 +223,6 @@ namespace System.Security { CheckHelper(grantedSet, refusedSet, demand, permToken, rmh, (Object)asm, action, true); } #else // FEATURE_COMPRESSEDSTACK - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif #pragma warning disable 618 internal static void CheckHelper(Object notUsed, PermissionSet grantedSet, @@ -281,11 +237,10 @@ namespace System.Security { // To reduce the amount of ifdef-code-churn, a dummy arg is used for the first parameter - instead of a CompressedStack object, // we use a System.Object that should always be null. If we tried to change the signature of the function, there will need to be // corresponding changes in VM (metasig.h, mscorlib.h, securitystackwalk.cpp, number of elements in the arg array, etc.) - Contract.Assert(notUsed == null, "Should not reach here with a non-null first arg which is the CompressedStack"); + Debug.Assert(notUsed == null, "Should not reach here with a non-null first arg which is the CompressedStack"); CheckHelper(grantedSet, refusedSet, demand, permToken, rmh, (Object)asm, action, true); } #endif // FEATURE_COMPRESSEDSTACK - [System.Security.SecurityCritical] // auto-generated #pragma warning disable 618 internal static bool CheckHelper(PermissionSet grantedSet, PermissionSet refusedSet, @@ -298,19 +253,7 @@ namespace System.Security { #pragma warning restore 618 { // We should never get here with a null demand - Contract.Assert(demand != null, "Should not reach here with a null demand"); - -#if _DEBUG && FEATURE_CAS_POLICY - if (debug) - { - DEBUG_OUT("Granted: "); - DEBUG_OUT(grantedSet.ToXml().ToString()); - DEBUG_OUT("Refused: "); - DEBUG_OUT(refusedSet != null ? refusedSet.ToXml().ToString() : ""); - DEBUG_OUT("Demanded: "); - DEBUG_OUT(demand.ToString()); - } -#endif // _DEBUG && FEATURE_CAS_POLICY + Debug.Assert(demand != null, "Should not reach here with a null demand"); if (permToken == null) permToken = PermissionToken.GetToken(demand); @@ -339,7 +282,7 @@ namespace System.Security { // If we aren't unrestricted, there is a refused set, or our permission is not of the unrestricted // variety, we need to do the proper callback. - Contract.Assert(demand != null,"demand != null"); + Debug.Assert(demand != null,"demand != null"); // Find the permission of matching type in the permission set. @@ -411,420 +354,35 @@ namespace System.Security { return true; } -#if FEATURE_CAS_POLICY - /// - /// Demand for the grant set of an assembly - /// - /// - /// Managed half of SecurityStackWalk::DemandGrantSet. - /// - [System.Security.SecurityCritical] // auto-generated - private static void CheckGrantSetHelper(PermissionSet grantSet) - { - Contract.Assert(grantSet != null, "Missing grant set"); - grantSet.CopyWithNoIdentityPermissions().Demand(); - } - - /// - /// Perform a security demand which succeeds if either a compatibilty permission is granted to the - /// call stack, or restricted member access and the grant set of the target of the reflection - /// operation is granted. - /// - /// compatibility permission to check - /// grant set of the reflection target - [System.Security.SecurityCritical] // auto-generated - internal static void ReflectionTargetDemandHelper(PermissionType permission, PermissionSet targetGrant) - { - ReflectionTargetDemandHelper((int)permission, targetGrant); - } - - /// - /// Perform a security demand which succeeds if either a compatibilty permission is granted to the - /// call stack, or restricted member access and the grant set of the target of the reflection - /// operation is granted. - /// - /// - /// Managed half of SecurityStackWalk::ReflectionTargetDemand. - /// - /// compatibility permission to check (See PermissionType) - /// grant set of the reflection target - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - private static void ReflectionTargetDemandHelper(int permission, PermissionSet targetGrant) - { - // Capture a compressed stack so that we can make both permission checks without walking the stack - // multiple times. - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - CompressedStack cs = CompressedStack.GetCompressedStack(ref stackMark); - - ReflectionTargetDemandHelper(permission, targetGrant, cs); - } - - /// - /// Perform a reflection target demand against a given access context - /// - /// - /// Managed half of SecurityStackWalk::ReflectionTargetDemand - /// - /// compatibility permission to check (See PermissionType) - /// grant set of the reflection target - /// access context to do the demand against - [System.Security.SecurityCritical] // auto-generated - private static void ReflectionTargetDemandHelper(int permission, - PermissionSet targetGrant, - Resolver accessContext) - { - ReflectionTargetDemandHelper(permission, targetGrant, accessContext.GetSecurityContext()); - } - - /// - /// Perform a reflection target demand against a given compressed stack - /// - /// - /// Managed half of SecurityStackWalk::ReflectionTargetDemand - /// - /// compatibility permission to check (See PermissionType) - /// grant set of the reflection target - /// compressed stack to do the demand against - [System.Security.SecurityCritical] // auto-generated - private static void ReflectionTargetDemandHelper(int permission, - PermissionSet targetGrant, - CompressedStack securityContext) - { - Contract.Assert(securityContext != null, "securityContext != null"); - - // We need to remove all identity permissions from the grant set of the target, otherwise the - // disjunctive demand will fail unless we're reflecting on the same assembly. - PermissionSet demandSet = null; - if (targetGrant == null) - { - demandSet = new PermissionSet(PermissionState.Unrestricted); - } - else - { - demandSet = targetGrant.CopyWithNoIdentityPermissions(); - demandSet.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess)); - } - - securityContext.DemandFlagsOrGrantSet((1 << (int)permission), demandSet); - } - - [System.Security.SecurityCritical] // auto-generated - internal static void GetZoneAndOriginHelper( CompressedStack cs, PermissionSet grantSet, PermissionSet refusedSet, ArrayList zoneList, ArrayList originList ) - { - if (cs != null) - cs.GetZoneAndOrigin(zoneList, originList, PermissionToken.GetToken(typeof(ZoneIdentityPermission)), PermissionToken.GetToken(typeof(UrlIdentityPermission))); - else - { - ZoneIdentityPermission zone = (ZoneIdentityPermission)grantSet.GetPermission( typeof( ZoneIdentityPermission ) ); - UrlIdentityPermission url = (UrlIdentityPermission)grantSet.GetPermission( typeof( UrlIdentityPermission ) ); - - if (zone != null) - zoneList.Add( zone.SecurityZone ); - - if (url != null) - originList.Add( url.Url ); - } - } - - [System.Security.SecurityCritical] // auto-generated - internal static void GetZoneAndOrigin( ref StackCrawlMark mark, out ArrayList zone, out ArrayList origin ) - { - zone = new ArrayList(); - origin = new ArrayList(); - - GetZoneAndOriginInternal( zone, origin, ref mark); - } - - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern void GetZoneAndOriginInternal(ArrayList zoneList, - ArrayList originList, - ref StackCrawlMark stackMark); - - [System.Security.SecurityCritical] // auto-generated - internal static void CheckAssembly(RuntimeAssembly asm, CodeAccessPermission demand ) - { - Contract.Assert( asm != null, "Must pass in a good assembly" ); - Contract.Assert( demand != null, "Must pass in a good demand" ); - - PermissionSet granted, refused; - asm.GetGrantSet( out granted, out refused ); -#pragma warning disable 618 - CheckHelper( granted, refused, demand, PermissionToken.GetToken(demand), RuntimeMethodHandleInternal.EmptyHandle, asm, SecurityAction.Demand, true ); -#pragma warning restore 618 - } - - // Check - Used to initiate a code-access security check. - // This method invokes a stack walk after skipping to the frame - // referenced by stackMark. - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern void Check (Object demand, - ref StackCrawlMark stackMark, - bool isPermSet); - - - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern bool QuickCheckForAllDemands(); - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern bool AllDomainsHomogeneousWithNoStackModifiers(); -#endif // FEATURE_CAS_POLICY - - [System.Security.SecurityCritical] // auto-generated internal static void Check(CodeAccessPermission cap, ref StackCrawlMark stackMark) { -#if FEATURE_CAS_POLICY - Check(cap, - ref stackMark, - false); -#endif // FEATURE_CAS_POLICY } - [System.Security.SecurityCritical] // auto-generated internal static void Check(PermissionSet permSet, ref StackCrawlMark stackMark) { -#if FEATURE_CAS_POLICY - Check(permSet, - ref stackMark, - true); -#endif // FEATURE_CAS_POLICY } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern FrameSecurityDescriptor CheckNReturnSO(PermissionToken permToken, CodeAccessPermission demand, ref StackCrawlMark stackMark, int create ); - [System.Security.SecurityCritical] // auto-generated internal static void Assert(CodeAccessPermission cap, ref StackCrawlMark stackMark) { -#if FEATURE_CAS_POLICY - // Make sure the caller of assert has the permission to assert - //WARNING: The placement of the call here is just right to check - // the appropriate frame. - - // Note: if the "AssertPermission" is not a permission that implements IUnrestrictedPermission - // you need to change the last parameter to a zero. - Contract.Assert(AssertPermissionToken != null && AssertPermission != null, "Assert Permission not setup correctly"); - FrameSecurityDescriptor secObj = CheckNReturnSO(AssertPermissionToken, - AssertPermission, - ref stackMark, - 1 ); - if (secObj == null) - { - // Security: REQ_SQ flag is missing. Bad compiler ? - // This can happen when you create delegates over functions that need the REQ_SQ - System.Environment.FailFast(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor")); - } - else - { - if (secObj.HasImperativeAsserts()) - throw new SecurityException( Environment.GetResourceString( "Security_MustRevertOverride" ) ); - - secObj.SetAssert(cap); - } -#endif // FEATURE_CAS_POLICY } - [System.Security.SecurityCritical] // auto-generated internal static void Deny(CodeAccessPermission cap, ref StackCrawlMark stackMark) { -#if FEATURE_CAS_POLICY - // Deny is only valid in legacy mode - if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_CasDeny")); - } - - FrameSecurityDescriptor secObj = - SecurityRuntime.GetSecurityObjectForFrame(ref stackMark, true); - if (secObj == null) - { - // Security: REQ_SQ flag is missing. Bad compiler ? - // This can happen when you create delegates over functions that need the REQ_SQ - System.Environment.FailFast(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor")); - } - else - { - if (secObj.HasImperativeDenials()) - throw new SecurityException( Environment.GetResourceString( "Security_MustRevertOverride" ) ); - - secObj.SetDeny(cap); - } -#endif // FEATURE_CAS_POLICY } - [System.Security.SecurityCritical] // auto-generated internal static void PermitOnly(CodeAccessPermission cap, ref StackCrawlMark stackMark) { -#if FEATURE_CAS_POLICY - FrameSecurityDescriptor secObj = - SecurityRuntime.GetSecurityObjectForFrame(ref stackMark, true); - if (secObj == null) - { - // Security: REQ_SQ flag is missing. Bad compiler ? - // This can happen when you create delegates over functions that need the REQ_SQ - System.Environment.FailFast(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor")); - } - else - { - if (secObj.HasImperativeRestrictions()) - throw new SecurityException( Environment.GetResourceString( "Security_MustRevertOverride" ) ); - - secObj.SetPermitOnly(cap); - } -#endif // FEATURE_CAS_POLICY - } - -#if FEATURE_CAS_POLICY - // Called from the VM to do a pre-domain initialization check of the security state of the - // AppDomain. This method looks at the state of the security of an AppDomain before it is - // completely initialized - so the output of this method does not always match what will be true - // when the domain is completely initialized. Instead, it is used to read what the input parameters - // to the domain setup say about the domain. - private static void PreResolve(out bool isFullyTrusted, out bool isHomogeneous) - { - // - // There are three main cases: - // 1. The AppDomain has an explict ApplicationTrust - we can use this to read the input state - // of the AppDomain. - // 2. The AppDomain is using legacy CAS policy - this means we can't tell much about the - // domain itself without a full policy resolution. - // 3. The domain is a standard v4+ AppDomain - these are always full trust and homogenous by - // default. - // - - // If the AppDomain is setup with an ApplicationTrust then it is always homogenous and we can - // tell its grant set right from the ApplicaitonTrust - ApplicationTrust domainTrust = AppDomain.CurrentDomain.SetupInformation.ApplicationTrust; - if (domainTrust != null) - { - isFullyTrusted = domainTrust.DefaultGrantSet.PermissionSet.IsUnrestricted(); - isHomogeneous = true; - return; - } - - // Otherwise, see if the domain is being configured on input to use legacy CAS policy - if (CompatibilitySwitches.IsNetFx40LegacySecurityPolicy || AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - isFullyTrusted = false; - isHomogeneous = false; - return; - } - - // If none of the above is true, then we must be a standard AppDomain - isFullyTrusted = true; - isHomogeneous = true; - } - - // Called from the VM when either a HostSecurityManager or simple sandbox domain can determine the - // grant set of an assembly - private static PermissionSet ResolveGrantSet(Evidence evidence, out int specialFlags, bool checkExecutionPermission) - { - Contract.Assert(evidence != null); - Contract.Assert(!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled); // This API does not do CAS policy resolution - - PermissionSet grantSet = null; - if (!TryResolveGrantSet(evidence, out grantSet)) - { - // If we couldn't figure out a grant set from the domain or the host, then we treat the - // assembly as fully trusted. - grantSet = new PermissionSet(PermissionState.Unrestricted); - } - - // Make sure the grant set includes the ability to execute code if that has been requested. - if (checkExecutionPermission) - { - SecurityPermission executionPermission = new SecurityPermission(SecurityPermissionFlag.Execution); - if (!grantSet.Contains(executionPermission)) - { - throw new PolicyException(Environment.GetResourceString("Policy_NoExecutionPermission"), - System.__HResults.CORSEC_E_NO_EXEC_PERM); - } - } - - specialFlags = SecurityManager.GetSpecialFlags(grantSet, null); - return grantSet; - } - - // Consult the host and the current AppDomain if it is homogenous to determine what the grant set - // of an assembly is. This API returns true if it was able to determine a grant set for the evidence, - // false if it cannot and other policy needs to be applied. - [SecuritySafeCritical] - internal static bool TryResolveGrantSet(Evidence evidence, out PermissionSet grantSet) - { - Contract.Assert(evidence != null); - - HostSecurityManager securityManager = AppDomain.CurrentDomain.HostSecurityManager; - - // GAC assemblies always are fully trusted - if (evidence.GetHostEvidence() != null) - { - grantSet = new PermissionSet(PermissionState.Unrestricted); - return true; - } - // If the host wants to participate in policy resolution, then our next option is to ask it for - // a grant set - else if ((securityManager.Flags & HostSecurityManagerOptions.HostResolvePolicy) == HostSecurityManagerOptions.HostResolvePolicy) - { - PermissionSet hostGrantSet = securityManager.ResolvePolicy(evidence); - - if (hostGrantSet == null) - { - throw new PolicyException(Environment.GetResourceString("Policy_NullHostGrantSet", securityManager.GetType().FullName)); - } - - // If we're in a homogenous domain, we don't want to allow the host to create multiple - // levels of permissions within the domain. So, if we see the host return something other - // than full trust or the homogenous grant set, we reject the grant set. - if (AppDomain.CurrentDomain.IsHomogenous) - { - // Some hosts, such as ASP.NET, return Nothing as a way of saying that the assembly should - // not be allowed to run in the AppDomain. Reject that with a specific - // no-execution-allowed-here exception message, rather than the return value validation - // exception message we'd hit below. - if (hostGrantSet.IsEmpty()) - { - throw new PolicyException(Environment.GetResourceString("Policy_NoExecutionPermission")); - } - - PermissionSet homogenousGrantSet = AppDomain.CurrentDomain.ApplicationTrust.DefaultGrantSet.PermissionSet; - bool isValidGrantSet = hostGrantSet.IsUnrestricted() || - (hostGrantSet.IsSubsetOf(homogenousGrantSet) && homogenousGrantSet.IsSubsetOf(hostGrantSet)); - - if (!isValidGrantSet) - { - throw new PolicyException(Environment.GetResourceString("Policy_GrantSetDoesNotMatchDomain", securityManager.GetType().FullName)); - } - } - - grantSet = hostGrantSet; - return true; - } - // If we're in a homogenous domain, we can get the grant set directly from the application trust - else if (AppDomain.CurrentDomain.IsHomogenous) - { - grantSet = AppDomain.CurrentDomain.GetHomogenousGrantSet(evidence); - return true; - } - // Otherwise we have no way to figure out what the grant set is - else - { - grantSet = null; - return false; - } } -#endif // FEATURE_CAS_POLICY #if FEATURE_PLS // Update the PLS used for optimization in the AppDomain: called from the VM - [System.Security.SecurityCritical] // auto-generated private static PermissionListSet UpdateAppDomainPLS(PermissionListSet adPLS, PermissionSet grantedPerms, PermissionSet refusedPerms) { if (adPLS == null) { adPLS = new PermissionListSet(); diff --git a/src/mscorlib/src/System/Security/FrameSecurityDescriptor.cs b/src/mscorlib/src/System/Security/FrameSecurityDescriptor.cs index 8f25bda..0ef5afd 100644 --- a/src/mscorlib/src/System/Security/FrameSecurityDescriptor.cs +++ b/src/mscorlib/src/System/Security/FrameSecurityDescriptor.cs @@ -12,6 +12,7 @@ namespace System.Security { using System.Globalization; using System.Runtime.ConstrainedExecution; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; #if !FEATURE_PAL using Microsoft.Win32.SafeHandles; @@ -40,10 +41,8 @@ namespace System.Security { // if this frame contains a call to any WindowsIdentity.Impersonate(), // we save the previous SafeTokenHandles here (in the next two fields) // Used during exceptionstackwalks to revert impersonation before calling filters - [System.Security.SecurityCritical] // auto-generated [NonSerialized] private SafeAccessTokenHandle m_callerToken; - [System.Security.SecurityCritical] // auto-generated [NonSerialized] private SafeAccessTokenHandle m_impToken; #endif @@ -56,16 +55,12 @@ namespace System.Security { - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void IncrementOverridesCount(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void DecrementOverridesCount(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void IncrementAssertCount(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void DecrementAssertCount(); @@ -105,14 +100,12 @@ namespace System.Security { // we store declarative actions in both fields, so check if they are different return (m_restriction != null); } - [System.Security.SecurityCritical] // auto-generated internal void SetAssert(IPermission perm) { m_assertions = CreateSingletonSet(perm); IncrementAssertCount(); } - [System.Security.SecurityCritical] // auto-generated internal void SetAssert(PermissionSet permSet) { m_assertions = permSet.Copy(); @@ -125,7 +118,6 @@ namespace System.Security { return (fDeclarative) ? m_DeclarativeAssertions : m_assertions; } - [System.Security.SecurityCritical] // auto-generated internal void SetAssertAllPossible() { m_assertAllPossible = true; @@ -141,19 +133,12 @@ namespace System.Security { // D E N Y //-----------------------------------------------------------+ - [System.Security.SecurityCritical] // auto-generated internal void SetDeny(IPermission perm) { -#if FEATURE_CAS_POLICY - BCLDebug.Assert(AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled, "Deny is only valid in legacy CAS mode"); -#endif // FEATURE_CAS_POLICY - m_denials = CreateSingletonSet(perm); IncrementOverridesCount(); - } - [System.Security.SecurityCritical] // auto-generated internal void SetDeny(PermissionSet permSet) { m_denials = permSet.Copy(); @@ -169,14 +154,12 @@ namespace System.Security { // R E S T R I C T //-----------------------------------------------------------+ - [System.Security.SecurityCritical] // auto-generated internal void SetPermitOnly(IPermission perm) { m_restriction = CreateSingletonSet(perm); IncrementOverridesCount(); } - [System.Security.SecurityCritical] // auto-generated internal void SetPermitOnly(PermissionSet permSet) { // permSet must not be null @@ -193,7 +176,6 @@ namespace System.Security { //-----------------------------------------------------------+ // SafeAccessTokenHandle (Impersonation + EH purposes) //-----------------------------------------------------------+ - [System.Security.SecurityCritical] // auto-generated internal void SetTokenHandles (SafeAccessTokenHandle callerToken, SafeAccessTokenHandle impToken) { m_callerToken = callerToken; @@ -204,7 +186,6 @@ namespace System.Security { // R E V E R T //-----------------------------------------------------------+ - [System.Security.SecurityCritical] // auto-generated internal void RevertAssert() { if (m_assertions != null) @@ -224,7 +205,6 @@ namespace System.Security { } } - [System.Security.SecurityCritical] // auto-generated internal void RevertAssertAllPossible() { if (m_assertAllPossible) @@ -234,7 +214,6 @@ namespace System.Security { } } - [System.Security.SecurityCritical] // auto-generated internal void RevertDeny() { if (HasImperativeDenials()) @@ -244,7 +223,6 @@ namespace System.Security { } } - [System.Security.SecurityCritical] // auto-generated internal void RevertPermitOnly() { if (HasImperativeRestrictions()) @@ -254,7 +232,6 @@ namespace System.Security { } } - [System.Security.SecurityCritical] // auto-generated internal void RevertAll() { RevertAssert(); @@ -270,7 +247,6 @@ namespace System.Security { // This will get called when we hit a FSD while evaluating a demand on the call stack or compressedstack - [System.Security.SecurityCritical] // auto-generated internal bool CheckDemand(CodeAccessPermission demand, PermissionToken permToken, RuntimeMethodHandleInternal rmh) { // imperative security @@ -283,13 +259,12 @@ namespace System.Security { return fContinue; } - [System.Security.SecurityCritical] // auto-generated internal bool CheckDemand2(CodeAccessPermission demand, PermissionToken permToken, RuntimeMethodHandleInternal rmh, bool fDeclarative) { PermissionSet permSet; // If the demand is null, there is no need to continue - Contract.Assert(demand != null && !demand.CheckDemand(null), "Empty demands should have been filtered out by this point"); + Debug.Assert(demand != null && !demand.CheckDemand(null), "Empty demands should have been filtered out by this point"); // decode imperative if (GetPermitOnly(fDeclarative) != null) @@ -397,7 +372,6 @@ namespace System.Security { return SecurityRuntime.StackContinue; } - [System.Security.SecurityCritical] // auto-generated internal bool CheckSetDemand(PermissionSet demandSet, out PermissionSet alteredDemandSet, RuntimeMethodHandleInternal rmh) @@ -429,7 +403,6 @@ namespace System.Security { return fContinue; } - [System.Security.SecurityCritical] // auto-generated internal bool CheckSetDemand2(PermissionSet demandSet, out PermissionSet alteredDemandSet, RuntimeMethodHandleInternal rmh, bool fDeclarative) diff --git a/src/mscorlib/src/System/Security/HostProtectionException.cs b/src/mscorlib/src/System/Security/HostProtectionException.cs index 83f005f..b08fccd 100644 --- a/src/mscorlib/src/System/Security/HostProtectionException.cs +++ b/src/mscorlib/src/System/Security/HostProtectionException.cs @@ -53,7 +53,7 @@ namespace System.Security protected HostProtectionException(SerializationInfo info, StreamingContext context) : base(info, context) { if (info==null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); m_protected = (HostProtectionResource)info.GetValue(ProtectedResourcesName, typeof(HostProtectionResource)); @@ -120,11 +120,10 @@ namespace System.Security } - [System.Security.SecurityCritical] // auto-generated_required public override void GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); base.GetObjectData( info, context ); diff --git a/src/mscorlib/src/System/Security/HostSecurityManager.cs b/src/mscorlib/src/System/Security/HostSecurityManager.cs index 46d5552..5313798 100644 --- a/src/mscorlib/src/System/Security/HostSecurityManager.cs +++ b/src/mscorlib/src/System/Security/HostSecurityManager.cs @@ -9,13 +9,9 @@ // participate in the security decisions in the AppDomain. // -namespace System.Security { +namespace System.Security +{ using System.Collections; -#if FEATURE_CLICKONCE - using System.Deployment.Internal.Isolation; - using System.Deployment.Internal.Isolation.Manifest; - using System.Runtime.Hosting; -#endif using System.Reflection; using System.Security; using System.Security.Permissions; @@ -24,7 +20,7 @@ namespace System.Security { using System.Diagnostics.Contracts; -[Serializable] + [Serializable] [Flags] [System.Runtime.InteropServices.ComVisible(true)] public enum HostSecurityManagerOptions { @@ -38,11 +34,7 @@ namespace System.Security { AllFlags = 0x001F } - [System.Security.SecurityCritical] // auto-generated_required [Serializable] -#if !FEATURE_CORECLR - [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.Infrastructure)] -#endif [System.Runtime.InteropServices.ComVisible(true)] public class HostSecurityManager { public HostSecurityManager () {} @@ -56,20 +48,6 @@ namespace System.Security { } } -#if FEATURE_CAS_POLICY - // provide policy for the AppDomain. - [Obsolete("AppDomain policy levels are obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public virtual PolicyLevel DomainPolicy { - get { - if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit")); - } - - return null; - } - } -#endif public virtual Evidence ProvideAppDomainEvidence (Evidence inputEvidence) { // The default implementation does not modify the input evidence. return inputEvidence; @@ -80,109 +58,6 @@ namespace System.Security { return inputEvidence; } -#if FEATURE_CLICKONCE - [System.Security.SecurityCritical] // auto-generated - [SecurityPermissionAttribute(SecurityAction.Assert, Unrestricted=true)] - public virtual ApplicationTrust DetermineApplicationTrust(Evidence applicationEvidence, Evidence activatorEvidence, TrustManagerContext context) - { - if (applicationEvidence == null) - throw new ArgumentNullException("applicationEvidence"); - Contract.EndContractBlock(); - - // This method looks for a trust decision for the ActivationContext in three locations, in order - // of preference: - // - // 1. Supplied by the host in the AppDomainSetup. If the host supplied a decision this way, it - // will be in the applicationEvidence. - // 2. Reuse the ApplicationTrust from the current AppDomain - // 3. Ask the TrustManager for a trust decision - - // get the activation context from the application evidence. - // The default HostSecurityManager does not examine the activatorEvidence - // but other security managers could use it to figure out the - // evidence of the domain attempting to activate the application. - - ActivationArguments activationArgs = applicationEvidence.GetHostEvidence(); - if (activationArgs == null) - throw new ArgumentException(Environment.GetResourceString("Policy_MissingActivationContextInAppEvidence")); - - ActivationContext actCtx = activationArgs.ActivationContext; - if (actCtx == null) - throw new ArgumentException(Environment.GetResourceString("Policy_MissingActivationContextInAppEvidence")); - - // Make sure that any ApplicationTrust we find applies to the ActivationContext we're - // creating the new AppDomain for. - ApplicationTrust appTrust = applicationEvidence.GetHostEvidence(); - if (appTrust != null && - !CmsUtils.CompareIdentities(appTrust.ApplicationIdentity, activationArgs.ApplicationIdentity, ApplicationVersionMatch.MatchExactVersion)) - { - appTrust = null; - } - - // If there was not a trust decision supplied in the Evidence, we can reuse the existing trust - // decision from this domain if its identity matches the ActivationContext of the new domain. - // Otherwise consult the TrustManager for a trust decision - if (appTrust == null) - { - if (AppDomain.CurrentDomain.ApplicationTrust != null && - CmsUtils.CompareIdentities(AppDomain.CurrentDomain.ApplicationTrust.ApplicationIdentity, activationArgs.ApplicationIdentity, ApplicationVersionMatch.MatchExactVersion)) - { - appTrust = AppDomain.CurrentDomain.ApplicationTrust; - } - else - { - appTrust = ApplicationSecurityManager.DetermineApplicationTrustInternal(actCtx, context); - } - } - - // If the trust decision allows the application to run, then it should also have a permission set - // which is at least the permission set the application requested. - ApplicationSecurityInfo appRequest = new ApplicationSecurityInfo(actCtx); - if (appTrust != null && - appTrust.IsApplicationTrustedToRun && - !appRequest.DefaultRequestSet.IsSubsetOf(appTrust.DefaultGrantSet.PermissionSet)) - { - throw new InvalidOperationException(Environment.GetResourceString("Policy_AppTrustMustGrantAppRequest")); - } - - return appTrust; - } -#endif // FEATURE_CLICKONCE - -#if FEATURE_CAS_POLICY - // Query the CLR to see what it would have granted a specific set of evidence - public virtual PermissionSet ResolvePolicy(Evidence evidence) - { - if (evidence == null) - throw new ArgumentNullException("evidence"); - Contract.EndContractBlock(); - - // - // If the evidence is from the GAC then the result is full trust. - // In a homogenous domain, then the application trust object provides the grant set. - // When CAS policy is disabled, the result is full trust. - // Otherwise, the result comes from evaluating CAS policy. - // - - if (evidence.GetHostEvidence() != null) - { - return new PermissionSet(PermissionState.Unrestricted); - } - else if (AppDomain.CurrentDomain.IsHomogenous) - { - return AppDomain.CurrentDomain.GetHomogenousGrantSet(evidence); - } - else if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - return new PermissionSet(PermissionState.Unrestricted); - } - else - { - return SecurityManager.PolicyManager.CodeGroupResolve(evidence, false); - } - } -#endif - /// /// Determine what types of evidence the host might be able to supply for the AppDomain if requested /// diff --git a/src/mscorlib/src/System/Security/IEvidenceFactory.cs b/src/mscorlib/src/System/Security/IEvidenceFactory.cs index 93f82a6..592ab53 100644 --- a/src/mscorlib/src/System/Security/IEvidenceFactory.cs +++ b/src/mscorlib/src/System/Security/IEvidenceFactory.cs @@ -2,19 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Security { - using System.Runtime.Remoting; - using System; - using System.Security.Policy; -[System.Runtime.InteropServices.ComVisible(true)] +namespace System.Security +{ + [System.Runtime.InteropServices.ComVisible(true)] public interface IEvidenceFactory { -#if FEATURE_CAS_POLICY - Evidence Evidence - { - get; - } -#endif // FEATURE_CAS_POLICY } - } diff --git a/src/mscorlib/src/System/Security/ISecurityEncodable.cs b/src/mscorlib/src/System/Security/ISecurityEncodable.cs index 9915da3..689b3e4 100644 --- a/src/mscorlib/src/System/Security/ISecurityEncodable.cs +++ b/src/mscorlib/src/System/Security/ISecurityEncodable.cs @@ -8,22 +8,10 @@ // implement this interface // -namespace System.Security { - - using System; - using System.Security.Util; - - -[System.Runtime.InteropServices.ComVisible(true)] +namespace System.Security +{ + [System.Runtime.InteropServices.ComVisible(true)] public interface ISecurityEncodable { -#if FEATURE_CAS_POLICY - SecurityElement ToXml(); - - void FromXml( SecurityElement e ); -#endif // FEATURE_CAS_POLICY } - } - - diff --git a/src/mscorlib/src/System/Security/ISecurityPolicyEncodable.cs b/src/mscorlib/src/System/Security/ISecurityPolicyEncodable.cs index b1c8d16..567e41e 100644 --- a/src/mscorlib/src/System/Security/ISecurityPolicyEncodable.cs +++ b/src/mscorlib/src/System/Security/ISecurityPolicyEncodable.cs @@ -8,21 +8,10 @@ // implement this interface // -namespace System.Security { - - using System; - using System.Security.Util; - using System.Security.Policy; - - -[System.Runtime.InteropServices.ComVisible(true)] +namespace System.Security +{ + [System.Runtime.InteropServices.ComVisible(true)] public interface ISecurityPolicyEncodable { -#if FEATURE_CAS_POLICY - SecurityElement ToXml( PolicyLevel level ); - - void FromXml( SecurityElement e, PolicyLevel level ); -#endif // FEATURE_CAS_POLICY } - } diff --git a/src/mscorlib/src/System/Security/NamedPermissionSet.cs b/src/mscorlib/src/System/Security/NamedPermissionSet.cs index fba7674..1bc166f 100644 --- a/src/mscorlib/src/System/Security/NamedPermissionSet.cs +++ b/src/mscorlib/src/System/Security/NamedPermissionSet.cs @@ -7,212 +7,19 @@ // Extends PermissionSet to allow an associated name and description // -namespace System.Security { - +namespace System.Security +{ using System; - using System.Security.Util; using System.Security.Permissions; - using System.Runtime.Serialization; - using System.Diagnostics.Contracts; -#if !FEATURE_CAS_POLICY - using Microsoft.Win32; - using System.Collections; - using System.Globalization; - using System.IO; - using System.Reflection; - using System.Runtime.InteropServices; - using System.Runtime.Remoting; - using System.Runtime.Versioning; - using System.Text; - -#else // FEATURE_CAS_POLICY - - using System.Threading; - -#endif // FEATURE_CAS_POLICY - [Serializable] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public sealed class NamedPermissionSet : PermissionSet { -#if FEATURE_CAS_POLICY - // The name of this PermissionSet - private String m_name; - - // The description of this PermissionSet - private String m_description; - [OptionalField(VersionAdded = 2)] - internal String m_descrResource; - - internal NamedPermissionSet() - : base() - { - } - - public NamedPermissionSet( String name ) - : base() - { - CheckName( name ); - m_name = name; - } - - public NamedPermissionSet( String name, PermissionState state) - : base( state ) - { - CheckName( name ); - m_name = name; - } - - - public NamedPermissionSet( String name, PermissionSet permSet ) - : base( permSet ) - { - CheckName( name ); - m_name = name; - } - - public NamedPermissionSet( NamedPermissionSet permSet ) - : base( permSet ) - { - m_name = permSet.m_name; - m_description = permSet.Description; - } - - internal NamedPermissionSet(SecurityElement permissionSetXml) - : base(PermissionState.None) - { - Contract.Assert(permissionSetXml != null); - FromXml(permissionSetXml); - } - - public String Name { - get { return m_name; } - set { CheckName( value ); m_name = value; } - } - - private static void CheckName( String name ) - { - if (name == null || name.Equals( "" )) - throw new ArgumentException( Environment.GetResourceString( "Argument_NPMSInvalidName" )); - Contract.EndContractBlock(); - } - - public String Description { - get - { - if(m_descrResource != null) - { - m_description = Environment.GetResourceString(m_descrResource); - m_descrResource = null; - } - return m_description; - } - - set - { - m_description = value; - m_descrResource = null; - } - } - - public override PermissionSet Copy() - { - return new NamedPermissionSet( this ); - } - - public NamedPermissionSet Copy( String name ) - { - NamedPermissionSet set = new NamedPermissionSet( this ); - set.Name = name; - return set; - } - - public override SecurityElement ToXml() - { - SecurityElement elem = base.ToXml("System.Security.NamedPermissionSet"); - // If you hit this assert then most likely you are trying to change the name of this class. - // This is ok as long as you change the hard coded string above and change the assert below. - Contract.Assert( this.GetType().FullName.Equals( "System.Security.NamedPermissionSet" ), "Class name changed!" ); - - if (m_name != null && !m_name.Equals( "" )) - { - elem.AddAttribute( "Name", SecurityElement.Escape( m_name ) ); - } - - if (Description != null && !Description.Equals( "" )) - { - elem.AddAttribute( "Description", SecurityElement.Escape( Description ) ); - } - - return elem; - } - - public override void FromXml( SecurityElement et ) - { - FromXml( et, false, false ); - } - - internal override void FromXml( SecurityElement et, bool allowInternalOnly, bool ignoreTypeLoadFailures ) - { - if (et == null) - throw new ArgumentNullException( "et" ); - Contract.EndContractBlock(); - - String elem; - - elem = et.Attribute( "Name" ); - m_name = elem == null ? null : elem; - - elem = et.Attribute( "Description" ); - m_description = (elem == null ? "" : elem); - m_descrResource = null; - - base.FromXml( et, allowInternalOnly, ignoreTypeLoadFailures ); - } - - internal void FromXmlNameOnly( SecurityElement et ) + internal static PermissionSet GetBuiltInSet(string name) { - // This function gets only the name for the permission set, ignoring all other info. - - String elem; - - elem = et.Attribute( "Name" ); - m_name = (elem == null ? null : elem); - } - - // NamedPermissionSet Equals should have the exact semantic as PermissionSet. - // We explicitly override them here to make sure that no one accidently - // changes this. - - [System.Runtime.InteropServices.ComVisible(false)] - public override bool Equals( Object obj ) - { - return base.Equals( obj ); - } - - [System.Runtime.InteropServices.ComVisible(false)] - public override int GetHashCode() - { - return base.GetHashCode(); - } - - private static Object s_InternalSyncObject; - private static Object InternalSyncObject { - get { - if (s_InternalSyncObject == null) { - Object o = new Object(); - Interlocked.CompareExchange(ref s_InternalSyncObject, o, null); - } - return s_InternalSyncObject; - } - } -#else // FEATURE_CAS_POLICY - - internal static PermissionSet GetBuiltInSet(string name) { // Used by PermissionSetAttribute to create one of the built-in, // immutable permission sets. - if (name == null) return null; else if (name.Equals("FullTrust")) @@ -264,6 +71,5 @@ namespace System.Security { } -#endif // !FEATURE_CAS_POLICY } } diff --git a/src/mscorlib/src/System/Security/PermissionListSet.cs b/src/mscorlib/src/System/Security/PermissionListSet.cs index 7eb13a7..093542a 100644 --- a/src/mscorlib/src/System/Security/PermissionListSet.cs +++ b/src/mscorlib/src/System/Security/PermissionListSet.cs @@ -23,6 +23,7 @@ namespace System.Security using System.Threading; using System.Collections; using System.Collections.Generic; + using System.Diagnostics; using System.Diagnostics.Contracts; [Serializable] @@ -53,15 +54,13 @@ namespace System.Security } #if FEATURE_PLS - [System.Security.SecurityCritical] // auto-generated internal void UpdateDomainPLS (PermissionListSet adPLS) { if (adPLS != null && adPLS.m_firstPermSetTriple != null) UpdateDomainPLS(adPLS.m_firstPermSetTriple.GrantSet, adPLS.m_firstPermSetTriple.RefusedSet); } - [System.Security.SecurityCritical] // auto-generated internal void UpdateDomainPLS (PermissionSet grantSet, PermissionSet deniedSet) { - Contract.Assert(m_permSetTriples == null, "m_permSetTriples != null"); + Debug.Assert(m_permSetTriples == null, "m_permSetTriples != null"); if (m_firstPermSetTriple == null) m_firstPermSetTriple = new PermissionSetTriple(); @@ -76,7 +75,6 @@ namespace System.Security UpdateTripleListAndCreateNewTriple(currentTriple, null); } - [System.Security.SecurityCritical] // auto-generated private void Terminate(PermissionSetTriple currentTriple, PermissionListSet pls) { #if FEATURE_COMPRESSEDSTACK @@ -86,7 +84,6 @@ namespace System.Security this.UpdateTripleListAndCreateNewTriple(currentTriple, null); } - [System.Security.SecurityCritical] // auto-generated private bool Update(PermissionSetTriple currentTriple, PermissionListSet pls) { #if FEATURE_COMPRESSEDSTACK @@ -95,7 +92,6 @@ namespace System.Security return this.UpdatePermissions(currentTriple, pls); } - [System.Security.SecurityCritical] // auto-generated private bool Update(PermissionSetTriple currentTriple, FrameSecurityDescriptor fsd) { #if FEATURE_COMPRESSEDSTACK @@ -117,7 +113,6 @@ namespace System.Security } #if FEATURE_COMPRESSEDSTACK - [System.Security.SecurityCritical] private bool Update2(PermissionSetTriple currentTriple, FrameSecurityDescriptorWithResolver fsdWithResolver) { System.Reflection.Emit.DynamicResolver resolver = fsdWithResolver.Resolver; @@ -127,7 +122,6 @@ namespace System.Security } #endif // FEATURE_COMPRESSEDSTACK - [System.Security.SecurityCritical] // auto-generated private bool Update2(PermissionSetTriple currentTriple, FrameSecurityDescriptor fsd, bool fDeclarative) { // Deny @@ -187,7 +181,6 @@ namespace System.Security return false; } - [System.Security.SecurityCritical] // auto-generated private void Update(PermissionSetTriple currentTriple, PermissionSet in_g, PermissionSet in_r) { #if FEATURE_COMPRESSEDSTACK @@ -203,7 +196,6 @@ namespace System.Security } // Called from the VM for HG CS construction - [System.Security.SecurityCritical] // auto-generated private void Update(PermissionSet in_g) { if (m_firstPermSetTriple == null) @@ -226,7 +218,6 @@ namespace System.Security } #endif // FEATURE_COMPRESSEDSTACK - [System.Security.SecurityCritical] // auto-generated private bool UpdatePermissions(PermissionSetTriple currentTriple, PermissionListSet pls) { if (pls != null) @@ -322,7 +313,6 @@ namespace System.Security } } -[System.Security.SecurityCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] // public(internal) interface begins... // Creation functions @@ -370,7 +360,6 @@ namespace System.Security return pls; } - [System.Security.SecurityCritical] // auto-generated static internal PermissionListSet CreateCompressedState(IntPtr unmanagedDCS, out bool bHaltConstruction) { PermissionListSet pls = new PermissionListSet(); @@ -411,7 +400,6 @@ namespace System.Security return pls; } - [System.Security.SecurityCritical] // auto-generated static internal PermissionListSet CreateCompressedState_HG() { PermissionListSet pls = new PermissionListSet(); @@ -420,11 +408,10 @@ namespace System.Security } #endif // #if FEATURE_COMPRESSEDSTACK // Private Demand evaluation functions - only called from the VM - [System.Security.SecurityCritical] // auto-generated internal bool CheckDemandNoThrow(CodeAccessPermission demand) { // AppDomain permissions - no asserts. So there should only be one triple to work with - Contract.Assert(m_permSetTriples == null && m_firstPermSetTriple != null, "More than one PermissionSetTriple encountered in AD PermissionListSet"); + Debug.Assert(m_permSetTriples == null && m_firstPermSetTriple != null, "More than one PermissionSetTriple encountered in AD PermissionListSet"); @@ -436,18 +423,16 @@ namespace System.Security } - [System.Security.SecurityCritical] // auto-generated internal bool CheckSetDemandNoThrow(PermissionSet pSet) { // AppDomain permissions - no asserts. So there should only be one triple to work with - Contract.Assert(m_permSetTriples == null && m_firstPermSetTriple != null, "More than one PermissionSetTriple encountered in AD PermissionListSet"); + Debug.Assert(m_permSetTriples == null && m_firstPermSetTriple != null, "More than one PermissionSetTriple encountered in AD PermissionListSet"); return m_firstPermSetTriple.CheckSetDemandNoThrow(pSet); } // Demand evauation functions - [System.Security.SecurityCritical] // auto-generated internal bool CheckDemand(CodeAccessPermission demand, PermissionToken permToken, RuntimeMethodHandleInternal rmh) { bool bRet = SecurityRuntime.StackContinue; @@ -467,7 +452,6 @@ namespace System.Security return bRet; } - [System.Security.SecurityCritical] // auto-generated internal bool CheckSetDemand(PermissionSet pset , RuntimeMethodHandleInternal rmh) { PermissionSet unused; @@ -475,7 +459,6 @@ namespace System.Security return SecurityRuntime.StackHalt; // CS demand check always terminates the stackwalk } - [System.Security.SecurityCritical] internal bool CheckSetDemandWithModification(PermissionSet pset, out PermissionSet alteredDemandSet, RuntimeMethodHandleInternal rmh) { bool bRet = SecurityRuntime.StackContinue; @@ -503,10 +486,9 @@ namespace System.Security /// Check to see if the PLS satisfies a demand for the special permissions encoded in flags /// /// set of flags to check (See PermissionType) - [System.Security.SecurityCritical] // auto-generated private bool CheckFlags(int flags) { - Contract.Assert(flags != 0, "Invalid permission flag demand"); + Debug.Assert(flags != 0, "Invalid permission flag demand"); bool check = true; @@ -531,7 +513,6 @@ namespace System.Security /// /// set of flags to check (See PermissionType) /// alternate permission set to check - [System.Security.SecurityCritical] // auto-generated internal void DemandFlagsOrGrantSet(int flags, PermissionSet grantSet) { if (CheckFlags(flags)) diff --git a/src/mscorlib/src/System/Security/PermissionSet.cs b/src/mscorlib/src/System/Security/PermissionSet.cs index e36f075..11ca02a 100644 --- a/src/mscorlib/src/System/Security/PermissionSet.cs +++ b/src/mscorlib/src/System/Security/PermissionSet.cs @@ -21,6 +21,7 @@ namespace System.Security { using System.Text; using System.Globalization; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; [Serializable] @@ -36,9 +37,6 @@ namespace System.Security { #if FEATURE_SERIALIZATION [Serializable] #endif -#if !FEATURE_CORECLR - [StrongNameIdentityPermissionAttribute(SecurityAction.InheritanceDemand, Name = "mscorlib", PublicKey = "0x" + AssemblyRef.EcmaPublicKeyFull)] -#endif [System.Runtime.InteropServices.ComVisible(true)] public class PermissionSet : ISecurityEncodable, ICollection, IStackWalk #if FEATURE_SERIALIZATION @@ -114,71 +112,13 @@ namespace System.Security { internal static readonly PermissionSet s_fullTrust = new PermissionSet( true ); -#if FEATURE_REMOTING - [OnDeserializing] - private void OnDeserializing(StreamingContext ctx) - { - Reset(); - } - - [OnDeserialized] - private void OnDeserialized(StreamingContext ctx) - { - if (m_serializedPermissionSet != null) - { - // Whidbey non X-AD case - FromXml(SecurityElement.FromString(m_serializedPermissionSet)); - } - else if (m_normalPermSet != null) - { - // Everett non X-AD case - m_permSet = m_normalPermSet.SpecialUnion(m_unrestrictedPermSet); - } - else if (m_unrestrictedPermSet != null) - { - // Everett non X-AD case - m_permSet = m_unrestrictedPermSet.SpecialUnion(m_normalPermSet); - } - - m_serializedPermissionSet = null; - m_normalPermSet = null; - m_unrestrictedPermSet = null; - - } - - [OnSerializing] - private void OnSerializing(StreamingContext ctx) - { - - if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0) - { - m_serializedPermissionSet = ToString(); // For v2.x and beyond - if (m_permSet != null) - m_permSet.SpecialSplit(ref m_unrestrictedPermSet, ref m_normalPermSet, m_ignoreTypeLoadFailures); - m_permSetSaved = m_permSet; - m_permSet = null; - } - } -#endif // !FEATURE_REMOTING - -#if FEATURE_REMOTING || _DEBUG +#if _DEBUG [OnSerialized] private void OnSerialized(StreamingContext context) { -#if FEATURE_REMOTING - if ((context.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0) - { - m_serializedPermissionSet = null; - m_permSet = m_permSetSaved; - m_permSetSaved = null; - m_unrestrictedPermSet = null; - m_normalPermSet = null; - } -#else // !FEATURE_REMOTING - Contract.Assert(false, "PermissionSet does not support serialization on CoreCLR"); -#endif // !FEATURE_REMOTING + Debug.Assert(false, "PermissionSet does not support serialization on CoreCLR"); } -#endif // FEATURE_REMOTING || _DEBUG +#endif // _DEBUG internal PermissionSet() { @@ -233,19 +173,11 @@ namespace System.Security { { Object obj = m_permSet.GetItem(i); IPermission perm = obj as IPermission; -#if FEATURE_CAS_POLICY - ISecurityElementFactory elem = obj as ISecurityElementFactory; -#endif // FEATURE_CAS_POLICY + if (perm != null) { m_permSet.SetItem(i, perm.Copy()); } -#if FEATURE_CAS_POLICY - else if (elem != null) - { - m_permSet.SetItem(i, elem.Copy()); - } -#endif // FEATURE_CAS_POLICY } } } @@ -253,7 +185,7 @@ namespace System.Security { public virtual void CopyTo(Array array, int index) { if (array == null) - throw new ArgumentNullException( "array" ); + throw new ArgumentNullException( nameof(array) ); Contract.EndContractBlock(); PermissionSetEnumeratorInternal enumerator = new PermissionSetEnumeratorInternal(this); @@ -365,19 +297,7 @@ namespace System.Security { Object obj = m_permSet.GetItem( index ); if (obj == null) return null; - IPermission perm = obj as IPermission; - if (perm != null) - return perm; -#if FEATURE_CAS_POLICY - perm = CreatePermission(obj, index); -#endif // FEATURE_CAS_POLICY - if (perm == null) - return null; - Contract.Assert( PermissionToken.IsTokenProperlyAssigned( perm, PermissionToken.GetToken( perm ) ), - "PermissionToken was improperly assigned" ); - Contract.Assert( PermissionToken.GetToken( perm ).m_index == index, - "Assigning permission to incorrect index in tokenbasedset" ); - return perm; + return obj as IPermission; } internal IPermission GetPermission(PermissionToken permToken) @@ -396,21 +316,6 @@ namespace System.Security { return GetPermission(PermissionToken.GetToken( perm )); } -#if FEATURE_CAS_POLICY - public IPermission GetPermission(Type permClass) - { - return GetPermissionImpl(permClass); - } - - protected virtual IPermission GetPermissionImpl(Type permClass) - { - if (permClass == null) - return null; - - return GetPermission(PermissionToken.FindToken(permClass)); - } -#endif // FEATURE_CAS_POLICY - public IPermission SetPermission(IPermission perm) { return SetPermissionImpl(perm); @@ -494,29 +399,6 @@ namespace System.Security { return (IPermission)m_permSet.RemoveItem( index ); // this cast is safe because the call to GetPermission will guarantee it is an IPermission } -#if FEATURE_CAS_POLICY - public IPermission RemovePermission(Type permClass) - { - return RemovePermissionImpl(permClass); - } - - protected virtual IPermission RemovePermissionImpl(Type permClass) - { - if (permClass == null) - { - return null; - } - - PermissionToken permToken = PermissionToken.FindToken(permClass); - if (permToken == null) - { - return null; - } - - return RemovePermission(permToken.m_index); - } -#endif // FEATURE_CAS_POLICY - // Make this internal soon. internal void SetUnrestricted(bool unrestricted) { @@ -527,12 +409,12 @@ namespace System.Security { m_permSet = null; } } - + public bool IsUnrestricted() { return m_Unrestricted; } - + internal enum IsSubsetOfType { Normal, @@ -580,7 +462,7 @@ namespace System.Security { IPermission targetPerm = target.GetPermission(i); #if _DEBUG PermissionToken token = (PermissionToken)PermissionToken.s_tokenSet.GetItem( i ); - Contract.Assert(targetPerm == null || (token.m_type & PermissionTokenType.DontKnow) == 0, "Token not properly initialized"); + Debug.Assert(targetPerm == null || (token.m_type & PermissionTokenType.DontKnow) == 0, "Token not properly initialized"); #endif if (target.m_Unrestricted) @@ -692,7 +574,7 @@ namespace System.Security { internal void CheckDecoded( CodeAccessPermission demandedPerm, PermissionToken tokenDemandedPerm ) { - Contract.Assert( demandedPerm != null, "Expected non-null value" ); + Debug.Assert( demandedPerm != null, "Expected non-null value" ); if (this.m_allPermissionsDecoded || this.m_permSet == null) return; @@ -700,7 +582,7 @@ namespace System.Security { if (tokenDemandedPerm == null) tokenDemandedPerm = PermissionToken.GetToken( demandedPerm ); - Contract.Assert( tokenDemandedPerm != null, "Unable to find token for demanded permission" ); + Debug.Assert( tokenDemandedPerm != null, "Unable to find token for demanded permission" ); CheckDecoded( tokenDemandedPerm.m_index ); } @@ -715,7 +597,7 @@ namespace System.Security { internal void CheckDecoded(PermissionSet demandedSet) { - Contract.Assert(demandedSet != null, "Expected non-null value"); + Debug.Assert(demandedSet != null, "Expected non-null value"); if (this.m_allPermissionsDecoded || this.m_permSet == null) return; @@ -728,37 +610,6 @@ namespace System.Security { } } -#if FEATURE_CAS_POLICY - static internal void SafeChildAdd( SecurityElement parent, ISecurityElementFactory child, bool copy ) - { - if (child == parent) - return; - if (child.GetTag().Equals( "IPermission" ) || child.GetTag().Equals( "Permission" )) - { - parent.AddChild( child ); - } - else if (parent.Tag.Equals( child.GetTag() )) - { - Contract.Assert( child is SecurityElement, "SecurityElement expected" ); - SecurityElement elChild = (SecurityElement)child; - Contract.Assert( elChild.InternalChildren != null, - "Non-permission elements should have children" ); - - for (int i = 0; i < elChild.InternalChildren.Count; ++i) - { - ISecurityElementFactory current = (ISecurityElementFactory)elChild.InternalChildren[i]; - Contract.Assert( !current.GetTag().Equals( parent.Tag ), - "Illegal to insert a like-typed element" ); - parent.AddChildNoDuplicates( current ); - } - } - else - { - parent.AddChild( (ISecurityElementFactory)(copy ? child.Copy() : child) ); - } - } -#endif // FEATURE_CAS_POLICY - internal void InplaceIntersect( PermissionSet other ) { Exception savedException = null; @@ -796,81 +647,24 @@ namespace System.Security { { Object thisObj = this.m_permSet.GetItem( i ); IPermission thisPerm = thisObj as IPermission; -#if FEATURE_CAS_POLICY - ISecurityElementFactory thisElem = thisObj as ISecurityElementFactory; -#endif // FEATURE_CAS_POLICY Object otherObj = other.m_permSet.GetItem( i ); IPermission otherPerm = otherObj as IPermission; -#if FEATURE_CAS_POLICY - ISecurityElementFactory otherElem = otherObj as ISecurityElementFactory; -#endif // FEATURE_CAS_POLICY if (thisObj == null && otherObj == null) continue; -#if FEATURE_CAS_POLICY - if (thisElem != null && otherElem != null) - { - // If we already have an intersection node, just add another child - if (thisElem.GetTag().Equals( s_str_PermissionIntersection ) || - thisElem.GetTag().Equals( s_str_PermissionUnrestrictedIntersection )) - { - Contract.Assert( thisElem is SecurityElement, "SecurityElement expected" ); - SafeChildAdd( (SecurityElement)thisElem, otherElem, true ); - } - // If either set is unrestricted, intersect the nodes unrestricted - else - { - bool copyOther = true; - if (this.IsUnrestricted()) - { - SecurityElement newElemUU = new SecurityElement( s_str_PermissionUnrestrictedUnion ); - newElemUU.AddAttribute( "class", thisElem.Attribute( "class" ) ); - SafeChildAdd( newElemUU, thisElem, false ); - thisElem = newElemUU; - } - if (other.IsUnrestricted()) - { - SecurityElement newElemUU = new SecurityElement( s_str_PermissionUnrestrictedUnion ); - newElemUU.AddAttribute( "class", otherElem.Attribute( "class" ) ); - SafeChildAdd( newElemUU, otherElem, true ); - otherElem = newElemUU; - copyOther = false; - } - - SecurityElement newElem = new SecurityElement( s_str_PermissionIntersection ); - newElem.AddAttribute( "class", thisElem.Attribute( "class" ) ); - - SafeChildAdd( newElem, thisElem, false ); - SafeChildAdd( newElem, otherElem, copyOther ); - this.m_permSet.SetItem( i, newElem ); - } - } - else -#endif // FEATURE_CAS_POLICY if (thisObj == null) { // There is no object in , so intersection is empty except for IUnrestrictedPermissions if (this.IsUnrestricted()) { -#if FEATURE_CAS_POLICY - if (otherElem != null) - { - SecurityElement newElem = new SecurityElement( s_str_PermissionUnrestrictedIntersection ); - newElem.AddAttribute( "class", otherElem.Attribute( "class" ) ); - SafeChildAdd( newElem, otherElem, true ); - this.m_permSet.SetItem( i, newElem ); - Contract.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" ); - } - else -#endif // FEATURE_CAS_POLICY { PermissionToken token = (PermissionToken)PermissionToken.s_tokenSet.GetItem( i ); if ((token.m_type & PermissionTokenType.IUnrestricted) != 0) { this.m_permSet.SetItem( i, otherPerm.Copy() ); - Contract.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" ); + Debug.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" ); } } } @@ -879,16 +673,6 @@ namespace System.Security { { if (other.IsUnrestricted()) { -#if FEATURE_CAS_POLICY - if (thisElem != null) - { - SecurityElement newElem = new SecurityElement( s_str_PermissionUnrestrictedIntersection ); - newElem.AddAttribute( "class", thisElem.Attribute( "class" ) ); - SafeChildAdd( newElem, thisElem, false ); - this.m_permSet.SetItem( i, newElem ); - } - else -#endif // FEATURE_CAS_POLICY { PermissionToken token = (PermissionToken)PermissionToken.s_tokenSet.GetItem( i ); if ((token.m_type & PermissionTokenType.IUnrestricted) == 0) @@ -902,13 +686,6 @@ namespace System.Security { } else { -#if FEATURE_CAS_POLICY - if (thisElem != null) - thisPerm = this.CreatePermission(thisElem, i); - if (otherElem != null) - otherPerm = other.CreatePermission(otherElem, i); -#endif // FEATURE_CAS_POLICY - try { IPermission intersectPerm; @@ -968,71 +745,23 @@ namespace System.Security { { Object thisObj = this.m_permSet.GetItem( i ); IPermission thisPerm = thisObj as IPermission; -#if FEATURE_CAS_POLICY - ISecurityElementFactory thisElem = thisObj as ISecurityElementFactory; -#endif // FEATURE_CAS_POLICY - Object otherObj = other.m_permSet.GetItem( i ); IPermission otherPerm = otherObj as IPermission; -#if FEATURE_CAS_POLICY - ISecurityElementFactory otherElem = otherObj as ISecurityElementFactory; -#endif // FEATURE_CAS_POLICY if (thisObj == null && otherObj == null) continue; -#if FEATURE_CAS_POLICY - if (thisElem != null && otherElem != null) - { - bool copyOther = true; - bool copyThis = true; - SecurityElement newElem = new SecurityElement( s_str_PermissionIntersection ); - newElem.AddAttribute( "class", otherElem.Attribute( "class" ) ); - if (this.IsUnrestricted()) - { - SecurityElement newElemUU = new SecurityElement( s_str_PermissionUnrestrictedUnion ); - newElemUU.AddAttribute( "class", thisElem.Attribute( "class" ) ); - SafeChildAdd( newElemUU, thisElem, true ); - copyThis = false; - thisElem = newElemUU; - } - if (other.IsUnrestricted()) - { - SecurityElement newElemUU = new SecurityElement( s_str_PermissionUnrestrictedUnion ); - newElemUU.AddAttribute( "class", otherElem.Attribute( "class" ) ); - SafeChildAdd( newElemUU, otherElem, true ); - copyOther = false; - otherElem = newElemUU; - } - - SafeChildAdd( newElem, otherElem, copyOther ); - SafeChildAdd( newElem, thisElem, copyThis ); - pset.m_permSet.SetItem( i, newElem ); - } - else -#endif // FEATURE_CAS_POLICY if (thisObj == null) { if (this.m_Unrestricted) { -#if FEATURE_CAS_POLICY - if (otherElem != null) - { - SecurityElement newElem = new SecurityElement( s_str_PermissionUnrestrictedIntersection ); - newElem.AddAttribute( "class", otherElem.Attribute( "class" ) ); - SafeChildAdd( newElem, otherElem, true ); - pset.m_permSet.SetItem( i, newElem ); - Contract.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" ); - } - else -#endif // FEATURE_CAS_POLICY if (otherPerm != null) { PermissionToken token = (PermissionToken)PermissionToken.s_tokenSet.GetItem( i ); if ((token.m_type & PermissionTokenType.IUnrestricted) != 0) { pset.m_permSet.SetItem( i, otherPerm.Copy() ); - Contract.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" ); + Debug.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" ); } } } @@ -1041,37 +770,19 @@ namespace System.Security { { if (other.m_Unrestricted) { -#if FEATURE_CAS_POLICY - if (thisElem != null) - { - SecurityElement newElem = new SecurityElement( s_str_PermissionUnrestrictedIntersection ); - newElem.AddAttribute( "class", thisElem.Attribute( "class" ) ); - SafeChildAdd( newElem, thisElem, true ); - pset.m_permSet.SetItem( i, newElem ); - Contract.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" ); - } - else -#endif // FEATURE_CAS_POLICY if (thisPerm != null) { PermissionToken token = (PermissionToken)PermissionToken.s_tokenSet.GetItem( i ); if ((token.m_type & PermissionTokenType.IUnrestricted) != 0) { pset.m_permSet.SetItem( i, thisPerm.Copy() ); - Contract.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" ); + Debug.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" ); } } } } else { -#if FEATURE_CAS_POLICY - if (thisElem != null) - thisPerm = this.CreatePermission(thisElem, i); - if (otherElem != null) - otherPerm = other.CreatePermission(otherElem, i); -#endif // FEATURE_CAS_POLICY - IPermission intersectPerm; if (thisPerm == null) intersectPerm = otherPerm; @@ -1080,7 +791,7 @@ namespace System.Security { else intersectPerm = thisPerm.Intersect( otherPerm ); pset.m_permSet.SetItem( i, intersectPerm ); - Contract.Assert( intersectPerm == null || PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" ); + Debug.Assert( intersectPerm == null || PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" ); } } @@ -1102,13 +813,9 @@ namespace System.Security { // Quick out conditions, union doesn't change this PermissionSet if (other == null || other.FastIsEmpty()) return; - - - m_CheckedForNonCas = false; - + m_CheckedForNonCas = false; - this.m_Unrestricted = this.m_Unrestricted || other.m_Unrestricted; if (this.m_Unrestricted) @@ -1124,7 +831,7 @@ namespace System.Security { int maxMax = -1; if (other.m_permSet != null) { - maxMax = other.m_permSet.GetMaxUsedIndex(); + maxMax = other.m_permSet.GetMaxUsedIndex(); this.CheckSet(); } // Save exceptions until the end @@ -1134,52 +841,15 @@ namespace System.Security { { Object thisObj = this.m_permSet.GetItem( i ); IPermission thisPerm = thisObj as IPermission; -#if FEATURE_CAS_POLICY - ISecurityElementFactory thisElem = thisObj as ISecurityElementFactory; -#endif // FEATURE_CAS_POLICY Object otherObj = other.m_permSet.GetItem( i ); IPermission otherPerm = otherObj as IPermission; -#if FEATURE_CAS_POLICY - ISecurityElementFactory otherElem = otherObj as ISecurityElementFactory; -#endif // FEATURE_CAS_POLICY if (thisObj == null && otherObj == null) continue; -#if FEATURE_CAS_POLICY - if (thisElem != null && otherElem != null) - { - if (thisElem.GetTag().Equals( s_str_PermissionUnion ) || - thisElem.GetTag().Equals( s_str_PermissionUnrestrictedUnion )) - { - Contract.Assert( thisElem is SecurityElement, "SecurityElement expected" ); - SafeChildAdd( (SecurityElement)thisElem, otherElem, true ); - } - else - { - SecurityElement newElem; - if (this.IsUnrestricted() || other.IsUnrestricted()) - newElem = new SecurityElement( s_str_PermissionUnrestrictedUnion ); - else - newElem = new SecurityElement( s_str_PermissionUnion ); - newElem.AddAttribute( "class", thisElem.Attribute( "class" ) ); - SafeChildAdd( newElem, thisElem, false ); - SafeChildAdd( newElem, otherElem, true ); - this.m_permSet.SetItem( i, newElem ); - } - } - else -#endif // FEATURE_CAS_POLICY if (thisObj == null) { -#if FEATURE_CAS_POLICY - if (otherElem != null) - { - this.m_permSet.SetItem( i, otherElem.Copy() ); - } - else -#endif // FEATURE_CAS_POLICY if (otherPerm != null) { PermissionToken token = (PermissionToken)PermissionToken.s_tokenSet.GetItem( i ); @@ -1195,13 +865,6 @@ namespace System.Security { } else { -#if FEATURE_CAS_POLICY - if (thisElem != null) - thisPerm = this.CreatePermission(thisElem, i); - if (otherElem != null) - otherPerm = other.CreatePermission(otherElem, i); -#endif // FEATURE_CAS_POLICY - try { IPermission unionPerm; @@ -1260,82 +923,39 @@ namespace System.Security { { Object thisObj = this.m_permSet.GetItem( i ); IPermission thisPerm = thisObj as IPermission; -#if FEATURE_CAS_POLICY - ISecurityElementFactory thisElem = thisObj as ISecurityElementFactory; -#endif // FEATURE_CAS_POLICY Object otherObj = other.m_permSet.GetItem( i ); IPermission otherPerm = otherObj as IPermission; -#if FEATURE_CAS_POLICY - ISecurityElementFactory otherElem = otherObj as ISecurityElementFactory; -#endif // FEATURE_CAS_POLICY if (thisObj == null && otherObj == null) continue; -#if FEATURE_CAS_POLICY - if (thisElem != null && otherElem != null) - { - SecurityElement newElem; - if (this.IsUnrestricted() || other.IsUnrestricted()) - newElem = new SecurityElement( s_str_PermissionUnrestrictedUnion ); - else - newElem = new SecurityElement( s_str_PermissionUnion ); - newElem.AddAttribute( "class", thisElem.Attribute( "class" ) ); - SafeChildAdd( newElem, thisElem, true ); - SafeChildAdd( newElem, otherElem, true ); - pset.m_permSet.SetItem( i, newElem ); - } - else -#endif // FEATURE_CAS_POLICY if (thisObj == null) { -#if FEATURE_CAS_POLICY - if (otherElem != null) - { - pset.m_permSet.SetItem( i, otherElem.Copy() ); - Contract.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" ); - } - else -#endif // FEATURE_CAS_POLICY if (otherPerm != null) { PermissionToken token = (PermissionToken)PermissionToken.s_tokenSet.GetItem( i ); if (((token.m_type & PermissionTokenType.IUnrestricted) == 0) || !pset.m_Unrestricted) { pset.m_permSet.SetItem( i, otherPerm.Copy() ); - Contract.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" ); + Debug.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" ); } } } else if (otherObj == null) { -#if FEATURE_CAS_POLICY - if (thisElem != null) - { - pset.m_permSet.SetItem( i, thisElem.Copy() ); - } - else -#endif // FEATURE_CAS_POLICY if (thisPerm != null) { PermissionToken token = (PermissionToken)PermissionToken.s_tokenSet.GetItem( i ); if (((token.m_type & PermissionTokenType.IUnrestricted) == 0) || !pset.m_Unrestricted) { pset.m_permSet.SetItem( i, thisPerm.Copy() ); - Contract.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" ); + Debug.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" ); } } } else { -#if FEATURE_CAS_POLICY - if (thisElem != null) - thisPerm = this.CreatePermission(thisElem, i); - if (otherElem != null) - otherPerm = other.CreatePermission(otherElem, i); -#endif // FEATURE_CAS_POLICY - IPermission unionPerm; if(thisPerm == null) unionPerm = otherPerm; @@ -1344,10 +964,10 @@ namespace System.Security { else unionPerm = thisPerm.Union( otherPerm ); pset.m_permSet.SetItem( i, unionPerm ); - Contract.Assert( unionPerm == null || PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" ); + Debug.Assert( unionPerm == null || PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" ); } } - + return pset; } @@ -1492,7 +1112,6 @@ namespace System.Security { // Mark this method as requiring a security object on the caller's frame // so the caller won't be inlined (which would mess up stack crawling). - [System.Security.SecuritySafeCritical] // auto-generated [DynamicSecurityMethodAttribute()] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public void Demand() @@ -1513,7 +1132,6 @@ namespace System.Security { } } - [System.Security.SecurityCritical] // auto-generated internal void DemandNonCAS() { ContainsNonCodeAccessPermissions(); @@ -1536,7 +1154,6 @@ namespace System.Security { // Metadata for this method should be flaged with REQ_SQ so that // EE can allocate space on the stack frame for FrameSecurityDescriptor - [System.Security.SecuritySafeCritical] // auto-generated [DynamicSecurityMethodAttribute()] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public void Assert() @@ -1548,7 +1165,6 @@ namespace System.Security { // Metadata for this method should be flaged with REQ_SQ so that // EE can allocate space on the stack frame for FrameSecurityDescriptor - [System.Security.SecuritySafeCritical] // auto-generated [DynamicSecurityMethodAttribute()] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable [Obsolete("Deny is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] @@ -1561,7 +1177,6 @@ namespace System.Security { // Metadata for this method should be flaged with REQ_SQ so that // EE can allocate space on the stack frame for FrameSecurityDescriptor - [System.Security.SecuritySafeCritical] // auto-generated [DynamicSecurityMethodAttribute()] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public void PermitOnly() @@ -1588,21 +1203,7 @@ namespace System.Security { { // Explicitly make a new PermissionSet, rather than copying, since we may have a // ReadOnlyPermissionSet which cannot have identity permissions removed from it in a true copy. - PermissionSet copy = new PermissionSet(this); - - // There's no easy way to distinguish an identity permission from any other CodeAccessPermission, - // so remove them directly. -#if FEATURE_CAS_POLICY - copy.RemovePermission(typeof(GacIdentityPermission)); -#if FEATURE_X509 - copy.RemovePermission(typeof(PublisherIdentityPermission)); -#endif - copy.RemovePermission(typeof(StrongNameIdentityPermission)); - copy.RemovePermission(typeof(UrlIdentityPermission)); - copy.RemovePermission(typeof(ZoneIdentityPermission)); -#endif // FEATURE_CAS_POLICY - - return copy; + return new PermissionSet(this); } public IEnumerator GetEnumerator() @@ -1620,13 +1221,6 @@ namespace System.Security { return new PermissionSetEnumeratorInternal(this); } -#if FEATURE_CAS_POLICY - public override String ToString() - { - return ToXml().ToString(); - } -#endif // FEATURE_CAS_POLICY - private void NormalizePermissionSet() { // This function guarantees that all the permissions are placed at @@ -1645,12 +1239,6 @@ namespace System.Security { { Object obj = this.m_permSet.GetItem(i); IPermission perm = obj as IPermission; -#if FEATURE_CAS_POLICY - ISecurityElementFactory elem = obj as ISecurityElementFactory; - - if (elem != null) - perm = CreatePerm( elem ); -#endif // FEATURE_CAS_POLICY if (perm != null) permSetTemp.SetPermission( perm ); } @@ -1659,29 +1247,6 @@ namespace System.Security { this.m_permSet = permSetTemp.m_permSet; } -#if FEATURE_CAS_POLICY - private bool DecodeXml(byte[] data, HostProtectionResource fullTrustOnlyResources, HostProtectionResource inaccessibleResources ) - { - if (data != null && data.Length > 0) - { - FromXml( new Parser( data, Tokenizer.ByteTokenEncoding.UnicodeTokens ).GetTopElement() ); - } - - FilterHostProtectionPermissions(fullTrustOnlyResources, inaccessibleResources); - - // We call this method from unmanaged to code a set we are going to use declaratively. In - // this case, all the lazy evaluation for partial policy resolution is wasted since we'll - // need to decode all of these shortly to make the demand for whatever. Therefore, we - // pay that price now so that we can calculate whether all the permissions in the set - // implement the IUnrestrictedPermission interface (the common case) for use in some - // unmanaged optimizations. - - DecodeAllPermissions(); - - return true; - } -#endif // FEATURE_CAS_POLICY - private void DecodeAllPermissions() { if (m_permSet == null) @@ -1710,11 +1275,7 @@ namespace System.Security { HostProtectionPermission newHpp = (HostProtectionPermission)hpp.Intersect(new HostProtectionPermission(fullTrustOnly)); if (newHpp == null) { -#if FEATURE_CAS_POLICY - RemovePermission(typeof(HostProtectionPermission)); -#else // !FEATURE_CAS_POLICY RemovePermission(HostProtectionPermission.GetTokenIndex()); -#endif // FEATURE_CAS_POLICY } else if (newHpp.Resources != hpp.Resources) { @@ -1722,539 +1283,8 @@ namespace System.Security { } } -#if FEATURE_CAS_POLICY - public virtual void FromXml( SecurityElement et ) - { - FromXml( et, false, false ); - } - - internal static bool IsPermissionTag( String tag, bool allowInternalOnly ) - { - if (tag.Equals( s_str_Permission ) || - tag.Equals( s_str_IPermission )) - { - return true; - } - - if (allowInternalOnly && - (tag.Equals( s_str_PermissionUnion ) || - tag.Equals( s_str_PermissionIntersection ) || - tag.Equals( s_str_PermissionUnrestrictedIntersection ) || - tag.Equals( s_str_PermissionUnrestrictedUnion))) - { - return true; - } - - return false; - } - - internal virtual void FromXml( SecurityElement et, bool allowInternalOnly, bool ignoreTypeLoadFailures ) - { - if (et == null) - throw new ArgumentNullException("et"); - - if (!et.Tag.Equals(s_str_PermissionSet)) - throw new ArgumentException(String.Format( null, Environment.GetResourceString( "Argument_InvalidXMLElement" ), "PermissionSet", this.GetType().FullName) ); - Contract.EndContractBlock(); - - Reset(); - m_ignoreTypeLoadFailures = ignoreTypeLoadFailures; - m_allPermissionsDecoded = false; - m_Unrestricted = XMLUtil.IsUnrestricted( et ); - - if (et.InternalChildren != null) - { - int childCount = et.InternalChildren.Count; - for (int i = 0; i < childCount; ++i) - { - SecurityElement elem = (SecurityElement)et.Children[i]; - - if (IsPermissionTag( elem.Tag, allowInternalOnly )) - { - String className = elem.Attribute( "class" ); - - PermissionToken token; - Object objectToInsert; - - if (className != null) - { - token = PermissionToken.GetToken( className ); - if (token == null) - { - objectToInsert = CreatePerm( elem ); -#if _DEBUG - PermissionToken tokenDebug = PermissionToken.GetToken( (IPermission)objectToInsert ); - Contract.Assert( tokenDebug != null && (tokenDebug.m_type & PermissionTokenType.BuiltIn) != 0, "This should only be called for built-ins" ); -#endif - if (objectToInsert != null) - { - Contract.Assert( objectToInsert.GetType().Module.Assembly == System.Reflection.Assembly.GetExecutingAssembly(), - "PermissionToken.GetToken returned null for non-mscorlib permission" ); - token = PermissionToken.GetToken( (IPermission)objectToInsert ); - Contract.Assert( (token.m_type & PermissionTokenType.DontKnow) == 0, "We should always know the permission type when getting a token from an instance" ); - } - } - else - { - objectToInsert = elem; - } - } - else - { - IPermission ip = CreatePerm( elem ); - if (ip == null) - { - token = null; - objectToInsert = null; - } - else - { - token = PermissionToken.GetToken( ip ); - Contract.Assert( PermissionToken.IsTokenProperlyAssigned( ip, token ), - "PermissionToken was improperly assigned" ); - objectToInsert = ip; - } - } - - if (token != null && objectToInsert != null) - { - if (m_permSet == null) - m_permSet = new TokenBasedSet(); - - if (this.m_permSet.GetItem( token.m_index ) != null) - { - // If there is already something in that slot, let's union them - // together. - - IPermission permInSlot; - - if (this.m_permSet.GetItem( token.m_index ) is IPermission) - permInSlot = (IPermission)this.m_permSet.GetItem( token.m_index ); - else - permInSlot = CreatePerm( (SecurityElement)this.m_permSet.GetItem( token.m_index ) ); - - if (objectToInsert is IPermission) - objectToInsert = ((IPermission)objectToInsert).Union( permInSlot ); - else - objectToInsert = CreatePerm( (SecurityElement)objectToInsert ).Union( permInSlot ); - } - - if(m_Unrestricted && objectToInsert is IPermission) - objectToInsert = null; - - this.m_permSet.SetItem( token.m_index, objectToInsert ); - } - } - } - } - } - - internal virtual void FromXml( SecurityDocument doc, int position, bool allowInternalOnly ) - { - if (doc == null) - throw new ArgumentNullException("doc"); - Contract.EndContractBlock(); - - if (!doc.GetTagForElement( position ).Equals(s_str_PermissionSet)) - throw new ArgumentException(String.Format( null, Environment.GetResourceString( "Argument_InvalidXMLElement" ), "PermissionSet", this.GetType().FullName) ); - - Reset(); - m_allPermissionsDecoded = false; - Exception savedException = null; - String strUnrestricted = doc.GetAttributeForElement( position, "Unrestricted" ); - if (strUnrestricted != null) - m_Unrestricted = strUnrestricted.Equals( "True" ) || strUnrestricted.Equals( "true" ) || strUnrestricted.Equals( "TRUE" ); - else - m_Unrestricted = false; - - ArrayList childrenIndices = doc.GetChildrenPositionForElement( position ); - int childCount = childrenIndices.Count; - for (int i = 0; i < childCount; ++i) - { - int childIndex = (int)childrenIndices[i]; - if (IsPermissionTag( doc.GetTagForElement( childIndex ), allowInternalOnly )) - { - try - { - String className = doc.GetAttributeForElement( childIndex, "class" ); - - PermissionToken token; - Object objectToInsert; - - if (className != null) - { - token = PermissionToken.GetToken( className ); - if (token == null) - { - objectToInsert = CreatePerm( doc.GetElement( childIndex, true ) ); - - if (objectToInsert != null) - { -#if _DEBUG - PermissionToken tokenDebug = PermissionToken.GetToken( (IPermission)objectToInsert ); - Contract.Assert((tokenDebug != null), "PermissionToken.GetToken returned null "); - Contract.Assert( (tokenDebug.m_type & PermissionTokenType.BuiltIn) != 0, "This should only be called for built-ins" ); -#endif - Contract.Assert( objectToInsert.GetType().Module.Assembly == System.Reflection.Assembly.GetExecutingAssembly(), - "PermissionToken.GetToken returned null for non-mscorlib permission" ); - token = PermissionToken.GetToken( (IPermission)objectToInsert ); - Contract.Assert((token != null), "PermissionToken.GetToken returned null "); - Contract.Assert( (token.m_type & PermissionTokenType.DontKnow) == 0, "We should always know the permission type when getting a token from an instance" ); - } - } - else - { - objectToInsert = ((ISecurityElementFactory)new SecurityDocumentElement(doc, childIndex)).CreateSecurityElement(); - } - } - else - { - IPermission ip = CreatePerm( doc.GetElement( childIndex, true ) ); - if (ip == null) - { - token = null; - objectToInsert = null; - } - else - { - token = PermissionToken.GetToken( ip ); - Contract.Assert( PermissionToken.IsTokenProperlyAssigned( ip, token ), - "PermissionToken was improperly assigned" ); - objectToInsert = ip; - } - } - - if (token != null && objectToInsert != null) - { - if (m_permSet == null) - m_permSet = new TokenBasedSet(); - - IPermission permInSlot = null; - if (this.m_permSet.GetItem( token.m_index ) != null) - { - // If there is already something in that slot, let's union them - // together. - - if (this.m_permSet.GetItem( token.m_index ) is IPermission) - permInSlot = (IPermission)this.m_permSet.GetItem( token.m_index ); - else - permInSlot = CreatePerm( this.m_permSet.GetItem( token.m_index ) ); - } - - if (permInSlot != null) - { - if (objectToInsert is IPermission) - objectToInsert = permInSlot.Union((IPermission)objectToInsert); - else - objectToInsert = permInSlot.Union(CreatePerm( objectToInsert )); - } - - if(m_Unrestricted && objectToInsert is IPermission) - objectToInsert = null; - - this.m_permSet.SetItem( token.m_index, objectToInsert ); - } - } - catch (Exception e) - { -#if _DEBUG - if (debug) - DEBUG_WRITE( "error while decoding permission set =\n" + e.ToString() ); -#endif - if (savedException == null) - savedException = e; - - } - } - } - - if (savedException != null) - throw savedException; - - } - - private IPermission CreatePerm(Object obj) - { - return CreatePerm(obj, m_ignoreTypeLoadFailures); - } - - internal static IPermission CreatePerm(Object obj, bool ignoreTypeLoadFailures) - { - SecurityElement el = obj as SecurityElement; - ISecurityElementFactory isf = obj as ISecurityElementFactory; - if (el == null && isf != null) - { - el = isf.CreateSecurityElement(); - } - - IEnumerator enumerator; - IPermission finalPerm = null; - - switch (el.Tag) - { - case s_str_PermissionUnion: - enumerator = el.Children.GetEnumerator(); - while (enumerator.MoveNext()) - { - IPermission tempPerm = CreatePerm( (SecurityElement)enumerator.Current, ignoreTypeLoadFailures); - - if (finalPerm != null) - finalPerm = finalPerm.Union( tempPerm ); - else - finalPerm = tempPerm; - } - break; - - case s_str_PermissionIntersection: - enumerator = el.Children.GetEnumerator(); - while (enumerator.MoveNext()) - { - IPermission tempPerm = CreatePerm( (SecurityElement)enumerator.Current, ignoreTypeLoadFailures); - - if (finalPerm != null) - finalPerm = finalPerm.Intersect( tempPerm ); - else - finalPerm = tempPerm; - - if (finalPerm == null) - return null; - } - break; - - case s_str_PermissionUnrestrictedUnion: - enumerator = el.Children.GetEnumerator(); - bool first = true; - while (enumerator.MoveNext()) - { - IPermission tempPerm = CreatePerm( (SecurityElement)enumerator.Current, ignoreTypeLoadFailures ); - - if (tempPerm == null) - continue; - - PermissionToken token = PermissionToken.GetToken( tempPerm ); - - Contract.Assert( (token.m_type & PermissionTokenType.DontKnow) == 0, "We should know the permission type already" ); - - if ((token.m_type & PermissionTokenType.IUnrestricted) != 0) - { - finalPerm = XMLUtil.CreatePermission( GetPermissionElement((SecurityElement)enumerator.Current), PermissionState.Unrestricted, ignoreTypeLoadFailures ); - first = false; - break; - } - else - { - Contract.Assert( tempPerm != null, "We should only come here if we have a real permission" ); - if (first) - finalPerm = tempPerm; - else - finalPerm = tempPerm.Union( finalPerm ); - first = false; - } - } - break; - - case s_str_PermissionUnrestrictedIntersection: - enumerator = el.Children.GetEnumerator(); - while (enumerator.MoveNext()) - { - IPermission tempPerm = CreatePerm( (SecurityElement)enumerator.Current, ignoreTypeLoadFailures ); - - if (tempPerm == null) - return null; - - PermissionToken token = PermissionToken.GetToken( tempPerm ); - - Contract.Assert( (token.m_type & PermissionTokenType.DontKnow) == 0, "We should know the permission type already" ); - - if ((token.m_type & PermissionTokenType.IUnrestricted) != 0) - { - if (finalPerm != null) - finalPerm = tempPerm.Intersect( finalPerm ); - else - finalPerm = tempPerm; - } - else - { - finalPerm = null; - } - - if (finalPerm == null) - return null; - } - break; - - case "IPermission": - case "Permission": - finalPerm = el.ToPermission(ignoreTypeLoadFailures); - break; - - default: - Contract.Assert( false, "Unrecognized case found during permission creation" ); - break; - } - - return finalPerm; - } - - internal IPermission CreatePermission(Object obj, int index) - { - IPermission perm = CreatePerm(obj); - if(perm == null) - return null; - - // See if the PermissionSet.m_Unrestricted flag covers this permission - if(m_Unrestricted) - perm = null; - - // Store the decoded result - CheckSet(); - m_permSet.SetItem(index, perm); - - // Do some consistency checks - Contract.Assert(perm == null || PermissionToken.IsTokenProperlyAssigned( perm, PermissionToken.GetToken( perm ) ), "PermissionToken was improperly assigned"); - if (perm != null) - { - PermissionToken permToken = PermissionToken.GetToken(perm); - if (permToken != null && permToken.m_index != index) - throw new ArgumentException( Environment.GetResourceString( "Argument_UnableToGeneratePermissionSet")); - } - - - return perm; - } - - private static SecurityElement GetPermissionElement( SecurityElement el ) - { - switch (el.Tag) - { - case "IPermission": - case "Permission": - return el; - } - IEnumerator enumerator = el.Children.GetEnumerator(); - if (enumerator.MoveNext()) - return GetPermissionElement((SecurityElement)enumerator.Current); - Contract.Assert( false, "No Permission or IPermission tag found" ); - return null; - } - - internal static SecurityElement CreateEmptyPermissionSetXml() - { - - SecurityElement elTrunk = new SecurityElement("PermissionSet"); - elTrunk.AddAttribute( "class", "System.Security.PermissionSet" ); - - elTrunk.AddAttribute( "version", "1" ); - return elTrunk; - - } - // internal helper which takes in the hardcoded permission name to avoid lookup at runtime - // can be called from classes that derive from PermissionSet - internal SecurityElement ToXml(String permName) - { - SecurityElement elTrunk = new SecurityElement("PermissionSet"); - elTrunk.AddAttribute( "class", permName ); - - elTrunk.AddAttribute( "version", "1" ); - - PermissionSetEnumeratorInternal enumerator = new PermissionSetEnumeratorInternal(this); - - if (m_Unrestricted) - { - elTrunk.AddAttribute(s_str_Unrestricted, "true" ); - } - - while (enumerator.MoveNext()) - { - IPermission perm = (IPermission)enumerator.Current; - - if (!m_Unrestricted) - elTrunk.AddChild( perm.ToXml() ); - } - return elTrunk; - } - - internal SecurityElement InternalToXml() - { - SecurityElement elTrunk = new SecurityElement("PermissionSet"); - elTrunk.AddAttribute( "class", this.GetType().FullName); - elTrunk.AddAttribute( "version", "1" ); - - if (m_Unrestricted) - { - elTrunk.AddAttribute(s_str_Unrestricted, "true" ); - } - - if (this.m_permSet != null) - { - int maxIndex = this.m_permSet.GetMaxUsedIndex(); - - for (int i = m_permSet.GetStartingIndex(); i <= maxIndex; ++i) - { - Object obj = this.m_permSet.GetItem( i ); - if (obj != null) - { - if (obj is IPermission) - { - if (!m_Unrestricted) - elTrunk.AddChild( ((IPermission)obj).ToXml() ); - } - else - { - elTrunk.AddChild( (SecurityElement)obj ); - } - } - - } - } - return elTrunk ; - } - - public virtual SecurityElement ToXml() - { - // If you hit this assert then most likely you are trying to change the name of this class. - // This is ok as long as you change the hard coded string above and change the assert below. - Contract.Assert( this.GetType().FullName.Equals( "System.Security.PermissionSet" ), "Class name changed! Was: System.Security.PermissionSet Should be:" + this.GetType().FullName); - - return ToXml("System.Security.PermissionSet"); - } -#endif // FEATURE_CAS_POLICY - -#if FEATURE_CAS_POLICY && FEATURE_SERIALIZATION - internal - byte[] EncodeXml() - { - MemoryStream ms = new MemoryStream(); - BinaryWriter writer = new BinaryWriter( ms, Encoding.Unicode ); - writer.Write( this.ToXml().ToString() ); - writer.Flush(); - - // The BinaryWriter is going to place - // two bytes indicating a Unicode stream. - // We want to chop those off before returning - // the bytes out. - - ms.Position = 2; - int countBytes = (int)ms.Length - 2; - byte[] retval = new byte[countBytes]; - ms.Read( retval, 0, retval.Length ); - return retval; - } - - /// - [Obsolete("This method is obsolete and shoud no longer be used.")] - public static byte[] ConvertPermissionSet(String inFormat, byte[] inData, String outFormat) - { - // Since this method has shipped and is public, we cannot remove it without being a breaking change - throw new NotImplementedException(); - } -#endif - // Determines whether the permission set contains any non-code access // security permissions. - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif public bool ContainsNonCodeAccessPermissions() { if (m_CheckedForNonCas) @@ -2324,59 +1354,11 @@ namespace System.Security { return pset; } -#if FEATURE_CAS_POLICY - private const String s_str_PermissionSet = "PermissionSet"; - private const String s_str_Permission = "Permission"; - private const String s_str_IPermission = "IPermission"; - private const String s_str_Unrestricted = "Unrestricted"; - private const String s_str_PermissionUnion = "PermissionUnion"; - private const String s_str_PermissionIntersection = "PermissionIntersection"; - private const String s_str_PermissionUnrestrictedUnion = "PermissionUnrestrictedUnion"; - private const String s_str_PermissionUnrestrictedIntersection = "PermissionUnrestrictedIntersection"; - - // This method supports v1.x security attrbutes only - we'll require legacy CAS policy mode - // to be enabled for that to work. -#pragma warning disable 618 - // Internal routine used to setup a special security context - // for creating and manipulated security custom attributes - // that we use when the Runtime is hosted. - [System.Security.SecurityCritical] // auto-generated - private static void SetupSecurity() - { - PolicyLevel level = PolicyLevel.CreateAppDomainLevel(); - - CodeGroup rootGroup = new UnionCodeGroup( new AllMembershipCondition(), level.GetNamedPermissionSet( "Execution" ) ); - - StrongNamePublicKeyBlob microsoftBlob = new StrongNamePublicKeyBlob( AssemblyRef.MicrosoftPublicKeyFull ); - CodeGroup microsoftGroup = new UnionCodeGroup( new StrongNameMembershipCondition( microsoftBlob, null, null ), level.GetNamedPermissionSet( "FullTrust" ) ); - - StrongNamePublicKeyBlob ecmaBlob = new StrongNamePublicKeyBlob( AssemblyRef.EcmaPublicKeyFull ); - CodeGroup ecmaGroup = new UnionCodeGroup( new StrongNameMembershipCondition( ecmaBlob, null, null ), level.GetNamedPermissionSet( "FullTrust" ) ); - - CodeGroup gacGroup = new UnionCodeGroup( new GacMembershipCondition(), level.GetNamedPermissionSet( "FullTrust" ) ); - - rootGroup.AddChild( microsoftGroup ); - rootGroup.AddChild( ecmaGroup ); - rootGroup.AddChild( gacGroup ); - - level.RootCodeGroup = rootGroup; - - try - { - AppDomain.CurrentDomain.SetAppDomainPolicy( level ); - } - catch (PolicyException) - { - } - } -#endif -#pragma warning restore 618 - // Internal routine used by CreateSerialized to add a permission to the set private static void MergePermission(IPermission perm, bool separateCasFromNonCas, ref PermissionSet casPset, ref PermissionSet nonCasPset) { - Contract.Assert(casPset == null || !casPset.IsReadOnly); - Contract.Assert(nonCasPset == null || !nonCasPset.IsReadOnly); + Debug.Assert(casPset == null || !casPset.IsReadOnly); + Debug.Assert(nonCasPset == null || !nonCasPset.IsReadOnly); if (perm == null) return; @@ -2402,9 +1384,6 @@ namespace System.Security { } // Converts an array of SecurityAttributes to a PermissionSet - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif private static byte[] CreateSerialized(Object[] attrs, bool serialize, ref byte[] nonCasBlob, @@ -2422,7 +1401,7 @@ namespace System.Security { for (int i = 0; i < attrs.Length; i++) { #pragma warning disable 618 - Contract.Assert(i == 0 || ((SecurityAttribute)attrs[i]).m_action == ((SecurityAttribute)attrs[i - 1]).m_action, "Mixed SecurityActions"); + Debug.Assert(i == 0 || ((SecurityAttribute)attrs[i]).m_action == ((SecurityAttribute)attrs[i - 1]).m_action, "Mixed SecurityActions"); #pragma warning restore 618 if (attrs[i] is PermissionSetAttribute) { @@ -2451,7 +1430,7 @@ namespace System.Security { MergePermission(perm, serialize, ref casPset, ref nonCasPset); } } - Contract.Assert(serialize || nonCasPset == null, "We shouldn't separate nonCAS permissions unless fSerialize is true"); + Debug.Assert(serialize || nonCasPset == null, "We shouldn't separate nonCAS permissions unless fSerialize is true"); // // Filter HostProtection permission. In the VM, some optimizations are done based upon these @@ -2475,22 +1454,8 @@ namespace System.Security { nonCasPset = null; } - // Serialize the set(s). - byte[] casBlob = null; - nonCasBlob = null; -#if FEATURE_CAS_POLICY - if(serialize) - { - if(casPset != null) - casBlob = casPset.EncodeXml(); - if(nonCasPset != null) - nonCasBlob = nonCasPset.EncodeXml(); - } -#else // FEATURE_CAS_POLICY - Contract.Assert(!serialize, "Cannot serialize permission sets on CoreCLR"); -#endif // FEATURE_CAS_POLICY - - return casBlob; + Debug.Assert(!serialize, "Cannot serialize permission sets on CoreCLR"); + return null; } #if FEATURE_SERIALIZATION @@ -2502,7 +1467,6 @@ namespace System.Security { } #endif - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static void RevertAssert() { @@ -2512,7 +1476,7 @@ namespace System.Security { internal static PermissionSet RemoveRefusedPermissionSet(PermissionSet assertSet, PermissionSet refusedSet, out bool bFailedToCompress) { - Contract.Assert((assertSet == null || !assertSet.IsUnrestricted()), "Cannot be unrestricted here"); + Debug.Assert((assertSet == null || !assertSet.IsUnrestricted()), "Cannot be unrestricted here"); PermissionSet retPs = null; bFailedToCompress = false; if (assertSet == null) @@ -2568,7 +1532,7 @@ namespace System.Security { internal static void RemoveAssertedPermissionSet(PermissionSet demandSet, PermissionSet assertSet, out PermissionSet alteredDemandSet) { - Contract.Assert(!assertSet.IsUnrestricted(), "Cannot call this function if assertSet is unrestricted"); + Debug.Assert(!assertSet.IsUnrestricted(), "Cannot call this function if assertSet is unrestricted"); alteredDemandSet = null; PermissionSetEnumeratorInternal enumerator = new PermissionSetEnumeratorInternal(demandSet); diff --git a/src/mscorlib/src/System/Security/PermissionSetEnumerator.cs b/src/mscorlib/src/System/Security/PermissionSetEnumerator.cs index 55b56cb5..7b234e9 100644 --- a/src/mscorlib/src/System/Security/PermissionSetEnumerator.cs +++ b/src/mscorlib/src/System/Security/PermissionSetEnumerator.cs @@ -81,20 +81,6 @@ namespace System.Security enm.Current = perm; return true; } - -#if FEATURE_CAS_POLICY - SecurityElement elem = obj as SecurityElement; - - if (elem != null) - { - perm = m_permSet.CreatePermission(elem, enm.Index); - if (perm != null) - { - enm.Current = perm; - return true; - } - } -#endif // FEATURE_CAS_POLICY } return false; } diff --git a/src/mscorlib/src/System/Security/PermissionSetTriple.cs b/src/mscorlib/src/System/Security/PermissionSetTriple.cs index f1527ac..56eb229 100644 --- a/src/mscorlib/src/System/Security/PermissionSetTriple.cs +++ b/src/mscorlib/src/System/Security/PermissionSetTriple.cs @@ -19,6 +19,7 @@ namespace System.Security using System.Security; using System.Security.Permissions; using System.Runtime.InteropServices; + using System.Diagnostics; using System.Diagnostics.Contracts; @@ -53,7 +54,6 @@ namespace System.Security private PermissionToken ZoneToken { - [System.Security.SecurityCritical] // auto-generated get { if (s_zoneToken == null) @@ -63,7 +63,6 @@ namespace System.Security } private PermissionToken UrlToken { - [System.Security.SecurityCritical] // auto-generated get { if (s_urlToken == null) @@ -71,7 +70,6 @@ namespace System.Security return s_urlToken; } } - [System.Security.SecurityCritical] // auto-generated internal bool Update(PermissionSetTriple psTriple, out PermissionSetTriple retTriple) { retTriple = null; @@ -86,13 +84,12 @@ namespace System.Security return false; } - [System.Security.SecurityCritical] // auto-generated internal PermissionSetTriple UpdateAssert(PermissionSet in_a) { PermissionSetTriple retTriple = null; if (in_a != null) { - Contract.Assert((!in_a.IsUnrestricted() || RefusedSet == null), "Cannot be unrestricted or refused must be null"); + Debug.Assert((!in_a.IsUnrestricted() || RefusedSet == null), "Cannot be unrestricted or refused must be null"); // if we're already asserting in_a, nothing to do if (in_a.IsSubsetOf(AssertSet)) return null; @@ -128,7 +125,6 @@ namespace System.Security } return retTriple; } - [System.Security.SecurityCritical] // auto-generated internal void UpdateGrant(PermissionSet in_g, out ZoneIdentityPermission z,out UrlIdentityPermission u) { z = null; @@ -145,7 +141,6 @@ namespace System.Security } } - [System.Security.SecurityCritical] // auto-generated internal void UpdateGrant(PermissionSet in_g) { if (in_g != null) @@ -168,7 +163,6 @@ namespace System.Security } - [System.Security.SecurityCritical] // auto-generated static bool CheckAssert(PermissionSet pSet, CodeAccessPermission demand, PermissionToken permToken) { if (pSet != null) @@ -193,7 +187,6 @@ namespace System.Security return SecurityRuntime.StackContinue; } - [System.Security.SecurityCritical] // auto-generated static bool CheckAssert(PermissionSet assertPset, PermissionSet demandSet, out PermissionSet newDemandSet) { newDemandSet = null; @@ -210,7 +203,6 @@ namespace System.Security } - [System.Security.SecurityCritical] // auto-generated internal bool CheckDemand(CodeAccessPermission demand, PermissionToken permToken, RuntimeMethodHandleInternal rmh) { if (CheckAssert(AssertSet, demand, permToken) == SecurityRuntime.StackHalt) @@ -222,7 +214,6 @@ namespace System.Security return SecurityRuntime.StackContinue; } - [System.Security.SecurityCritical] // auto-generated internal bool CheckSetDemand(PermissionSet demandSet , out PermissionSet alteredDemandset, RuntimeMethodHandleInternal rmh) { alteredDemandset = null; @@ -239,18 +230,16 @@ namespace System.Security } - [System.Security.SecurityCritical] // auto-generated internal bool CheckDemandNoThrow(CodeAccessPermission demand, PermissionToken permToken) { - Contract.Assert(AssertSet == null, "AssertSet not null"); + Debug.Assert(AssertSet == null, "AssertSet not null"); #pragma warning disable 618 return CodeAccessSecurityEngine.CheckHelper(GrantSet, RefusedSet, demand, permToken, RuntimeMethodHandleInternal.EmptyHandle, null, SecurityAction.Demand, false); #pragma warning restore 618 } - [System.Security.SecurityCritical] // auto-generated internal bool CheckSetDemandNoThrow(PermissionSet demandSet) { - Contract.Assert(AssertSet == null, "AssertSet not null"); + Debug.Assert(AssertSet == null, "AssertSet not null"); #pragma warning disable 618 return CodeAccessSecurityEngine.CheckSetHelper(GrantSet, RefusedSet, demandSet, RuntimeMethodHandleInternal.EmptyHandle, null, SecurityAction.Demand, false); @@ -263,7 +252,6 @@ namespace System.Security /// If the triple asserts for one of the bits in the flags, it is zeroed out. /// /// set of flags to check (See PermissionType) - [System.Security.SecurityCritical] // auto-generated internal bool CheckFlags(ref int flags) { if (AssertSet != null) diff --git a/src/mscorlib/src/System/Security/PermissionToken.cs b/src/mscorlib/src/System/Security/PermissionToken.cs index e78c0f1..5c6a322 100644 --- a/src/mscorlib/src/System/Security/PermissionToken.cs +++ b/src/mscorlib/src/System/Security/PermissionToken.cs @@ -2,7 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Security { +namespace System.Security +{ using System; using System.Security.Util; using System.Security.Permissions; @@ -11,6 +12,7 @@ namespace System.Security { using System.Threading; using System.Globalization; using System.Runtime.CompilerServices; + using System.Diagnostics; using System.Diagnostics.Contracts; [Flags] @@ -34,7 +36,6 @@ namespace System.Security { _info = CultureInfo.InvariantCulture.TextInfo; } - [System.Security.SecuritySafeCritical] // auto-generated public int Compare(Object a, Object b) { String strA = a as String; @@ -64,7 +65,7 @@ namespace System.Security { // The data structure consuming this will be responsible for dealing with null objects as keys. public int GetHashCode(Object obj) { - if (obj == null) throw new ArgumentNullException("obj"); + if (obj == null) throw new ArgumentNullException(nameof(obj)); Contract.EndContractBlock(); String str = obj as String; @@ -90,20 +91,13 @@ namespace System.Security { internal sealed class PermissionToken : ISecurityEncodable { private static readonly PermissionTokenFactory s_theTokenFactory; -#if FEATURE_CAS_POLICY - private static volatile ReflectionPermission s_reflectPerm = null; -#endif // FEATURE_CAS_POLICY - private const string c_mscorlibName = System.CoreLib.Name; internal int m_index; internal volatile PermissionTokenType m_type; -#if FEATURE_CAS_POLICY - internal String m_strTypeName; -#endif // FEATURE_CAS_POLICY static internal TokenBasedSet s_tokenSet = new TokenBasedSet(); internal static bool IsMscorlibClassName (string className) { - Contract.Assert( c_mscorlibName == ((RuntimeAssembly)Assembly.GetExecutingAssembly()).GetSimpleName(), + Debug.Assert( c_mscorlibName == ((RuntimeAssembly)Assembly.GetExecutingAssembly()).GetSimpleName(), System.CoreLib.Name+" name mismatch" ); // If the class name does not look like a fully qualified name, we cannot simply determine if it's @@ -119,11 +113,7 @@ namespace System.Security { // Search for the string 'mscorlib' in the classname. If we find it, we will conservatively assume it's an mscorlib.dll type and load it. for (int i = index; i < className.Length; i++) { -#if FEATURE_CORECLR - if (className[i] == 's' || className[i] == 'S') -#else - if (className[i] == 'm' || className[i] == 'M') -#endif + if (className[i] == 's' || className[i] == 'S') { if (String.Compare(className, i, c_mscorlibName, 0, c_mscorlibName.Length, StringComparison.OrdinalIgnoreCase) == 0) return true; @@ -145,39 +135,14 @@ namespace System.Security { { m_index = index; m_type = type; -#if FEATURE_CAS_POLICY - m_strTypeName = strTypeName; -#endif // FEATURE_CAS_POLICY } - [System.Security.SecurityCritical] // auto-generated public static PermissionToken GetToken(Type cls) { if (cls == null) return null; - -#if FEATURE_CAS_POLICY - if (cls.GetInterface( "System.Security.Permissions.IBuiltInPermission" ) != null) - { - if (s_reflectPerm == null) - s_reflectPerm = new ReflectionPermission(PermissionState.Unrestricted); - s_reflectPerm.Assert(); - MethodInfo method = cls.GetMethod( "GetTokenIndex", BindingFlags.Static | BindingFlags.NonPublic ); - Contract.Assert( method != null, "IBuiltInPermission types should have a static method called 'GetTokenIndex'" ); - - // GetTokenIndex needs to be invoked without any security checks, since doing a security check - // will involve a ReflectionTargetDemand which creates a CompressedStack and attempts to get the - // token. - RuntimeMethodInfo getTokenIndex = method as RuntimeMethodInfo; - Contract.Assert(getTokenIndex != null, "method is not a RuntimeMethodInfo"); - int token = (int)getTokenIndex.UnsafeInvoke(null, BindingFlags.Default, null, null, null); - return s_theTokenFactory.BuiltInGetToken(token, null, cls); - } - else -#endif // FEATURE_CAS_POLICY - { - return s_theTokenFactory.GetToken(cls, null); - } + + return s_theTokenFactory.GetToken(cls, null); } public static PermissionToken GetToken(IPermission perm) @@ -193,82 +158,6 @@ namespace System.Security { return s_theTokenFactory.GetToken(perm.GetType(), perm); } -#if FEATURE_CAS_POLICY - public static PermissionToken GetToken(String typeStr) - { - return GetToken( typeStr, false ); - } - -#if _DEBUG - [System.Security.SecuritySafeCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - private static void GetTokenHelper(String typeStr) - { - new PermissionSet(PermissionState.Unrestricted).Assert(); - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - Type type = RuntimeTypeHandle.GetTypeByName( typeStr.Trim().Replace( '\'', '\"' ), ref stackMark); - Contract.Assert( (type == null) || (type.Module.Assembly != System.Reflection.Assembly.GetExecutingAssembly()) || (typeStr.IndexOf("mscorlib", StringComparison.Ordinal) < 0), - "We should not go through this path for mscorlib based permissions" ); - } -#endif - - public static PermissionToken GetToken(String typeStr, bool bCreateMscorlib) - { - if (typeStr == null) - return null; - - if (IsMscorlibClassName( typeStr )) - { - if (!bCreateMscorlib) - { - return null; - } - else - { - return FindToken( Type.GetType( typeStr ) ); - } - } - else - { - PermissionToken token = s_theTokenFactory.GetToken(typeStr); -#if _DEBUG - GetTokenHelper(typeStr); -#endif - return token; - } - } - - [SecuritySafeCritical] - public static PermissionToken FindToken( Type cls ) - { - if (cls == null) - return null; - -#if FEATURE_CAS_POLICY - if (cls.GetInterface( "System.Security.Permissions.IBuiltInPermission" ) != null) - { - if (s_reflectPerm == null) - s_reflectPerm = new ReflectionPermission(PermissionState.Unrestricted); - s_reflectPerm.Assert(); - MethodInfo method = cls.GetMethod( "GetTokenIndex", BindingFlags.Static | BindingFlags.NonPublic ); - Contract.Assert( method != null, "IBuiltInPermission types should have a static method called 'GetTokenIndex'" ); - - // GetTokenIndex needs to be invoked without any security checks, since doing a security check - // will involve a ReflectionTargetDemand which creates a CompressedStack and attempts to get the - // token. - RuntimeMethodInfo getTokenIndex = method as RuntimeMethodInfo; - Contract.Assert(getTokenIndex != null, "method is not a RuntimeMethodInfo"); - int token = (int)getTokenIndex.UnsafeInvoke(null, BindingFlags.Default, null, null, null); - return s_theTokenFactory.BuiltInGetToken(token, null, cls); - } - else -#endif // FEATURE_CAS_POLICY - { - return s_theTokenFactory.FindToken( cls ); - } - } -#endif // FEATURE_CAS_POLICY - public static PermissionToken FindTokenByIndex( int i ) { return s_theTokenFactory.FindTokenByIndex( i ); @@ -289,41 +178,6 @@ namespace System.Security { return true; } - -#if FEATURE_CAS_POLICY - public SecurityElement ToXml() - { - Contract.Assert( (m_type & PermissionTokenType.DontKnow) == 0, "Should have valid token type when ToXml is called" ); - SecurityElement elRoot = new SecurityElement( "PermissionToken" ); - if ((m_type & PermissionTokenType.BuiltIn) != 0) - elRoot.AddAttribute( "Index", "" + this.m_index ); - else - elRoot.AddAttribute( "Name", SecurityElement.Escape( m_strTypeName ) ); - elRoot.AddAttribute("Type", m_type.ToString("F")); - return elRoot; - } - - public void FromXml(SecurityElement elRoot) - { - // For the most part there is no parameter checking here since this is an - // internal class and the serialization/deserialization path is controlled. - - if (!elRoot.Tag.Equals( "PermissionToken" )) - Contract.Assert( false, "Tried to deserialize non-PermissionToken element here" ); - - String strName = elRoot.Attribute( "Name" ); - PermissionToken realToken; - if (strName != null) - realToken = GetToken( strName, true ); - else - realToken = FindTokenByIndex( Int32.Parse( elRoot.Attribute( "Index" ), CultureInfo.InvariantCulture ) ); - - this.m_index = realToken.m_index; - this.m_type = (PermissionTokenType) Enum.Parse(typeof(PermissionTokenType), elRoot.Attribute("Type")); - Contract.Assert((this.m_type & PermissionTokenType.DontKnow) == 0, "Should have valid token type when FromXml is called."); - this.m_strTypeName = realToken.m_strTypeName; - } -#endif // FEATURE_CAS_POLICY } // Package access only @@ -357,33 +211,6 @@ namespace System.Security { m_indexTable = new Hashtable(size); } -#if FEATURE_CAS_POLICY - [SecuritySafeCritical] - internal PermissionToken FindToken( Type cls ) - { - IntPtr typePtr = cls.TypeHandle.Value; - PermissionToken tok = (PermissionToken)m_handleTable[typePtr]; - - if (tok != null) - return tok; - - if (m_tokenTable == null) - return null; - - tok = (PermissionToken)m_tokenTable[cls.AssemblyQualifiedName]; - - if (tok != null) - { - lock (this) - { - m_handleTable.Add(typePtr, tok); - } - } - - return tok; - } -#endif // FEATURE_CAS_POLICY - internal PermissionToken FindTokenByIndex( int i ) { PermissionToken token; @@ -400,10 +227,9 @@ namespace System.Security { return token; } - [SecuritySafeCritical] internal PermissionToken GetToken(Type cls, IPermission perm) { - Contract.Assert( cls != null, "Must pass in valid type" ); + Debug.Assert( cls != null, "Must pass in valid type" ); IntPtr typePtr = cls.TypeHandle.Value; object tok = m_handleTable[typePtr]; @@ -459,22 +285,16 @@ namespace System.Security { { if (perm != null) { - Contract.Assert( !(perm is IBuiltInPermission), "This should not be called for built-ins" ); + Debug.Assert( !(perm is IBuiltInPermission), "This should not be called for built-ins" ); ((PermissionToken)tok).m_type = PermissionTokenType.IUnrestricted; -#if FEATURE_CAS_POLICY - ((PermissionToken)tok).m_strTypeName = perm.GetType().AssemblyQualifiedName; -#endif // FEATURE_CAS_POLICY } else { - Contract.Assert( cls.GetInterface( "System.Security.Permissions.IBuiltInPermission" ) == null, "This shoudl not be called for built-ins" ); + Debug.Assert( cls.GetInterface( "System.Security.Permissions.IBuiltInPermission" ) == null, "This shoudl not be called for built-ins" ); if (cls.GetInterface(s_unrestrictedPermissionInferfaceName) != null) ((PermissionToken)tok).m_type = PermissionTokenType.IUnrestricted; else ((PermissionToken)tok).m_type = PermissionTokenType.Normal; -#if FEATURE_CAS_POLICY - ((PermissionToken)tok).m_strTypeName = cls.AssemblyQualifiedName; -#endif // FEATURE_CAS_POLICY } } diff --git a/src/mscorlib/src/System/Security/Permissions/EnvironmentPermission.cs b/src/mscorlib/src/System/Security/Permissions/EnvironmentPermission.cs index 8208ed3..567fe51 100644 --- a/src/mscorlib/src/System/Security/Permissions/EnvironmentPermission.cs +++ b/src/mscorlib/src/System/Security/Permissions/EnvironmentPermission.cs @@ -56,7 +56,6 @@ namespace System.Security.Permissions { return str; } - [SecuritySafeCritical] public override string ToString() { // SafeCritical: we're not storing path information in the strings, so exposing them out is fine ... @@ -103,7 +102,6 @@ namespace System.Security.Permissions { AddPathList( flag, pathList ); } - [System.Security.SecuritySafeCritical] // auto-generated public void AddPathList( EnvironmentPermissionAccess flag, String pathList ) { VerifyFlag( flag ); @@ -204,7 +202,6 @@ namespace System.Security.Permissions { // //------------------------------------------------------ - [System.Security.SecuritySafeCritical] // auto-generated public override bool IsSubsetOf(IPermission target) { if (target == null) @@ -232,7 +229,6 @@ namespace System.Security.Permissions { } } - [System.Security.SecuritySafeCritical] // auto-generated public override IPermission Intersect(IPermission target) { if (target == null) @@ -275,7 +271,6 @@ namespace System.Security.Permissions { return intersectPermission; } - [System.Security.SecuritySafeCritical] // auto-generated public override IPermission Union(IPermission other) { if (other == null) @@ -334,61 +329,8 @@ namespace System.Security.Permissions { } } - return copy; + return copy; } - -#if FEATURE_CAS_POLICY - public override SecurityElement ToXml() - { - SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.EnvironmentPermission" ); - if (!IsUnrestricted()) - { - if (this.m_read != null && !this.m_read.IsEmpty()) - { - esd.AddAttribute( "Read", SecurityElement.Escape( m_read.ToString() ) ); - } - if (this.m_write != null && !this.m_write.IsEmpty()) - { - esd.AddAttribute( "Write", SecurityElement.Escape( m_write.ToString() ) ); - } - } - else - { - esd.AddAttribute( "Unrestricted", "true" ); - } - return esd; - } - - public override void FromXml(SecurityElement esd) - { - CodeAccessPermission.ValidateElement( esd, this ); - - String et; - - if (XMLUtil.IsUnrestricted(esd)) - { - m_unrestricted = true; - return; - } - - m_unrestricted = false; - m_read = null; - m_write = null; - - et = esd.Attribute( "Read" ); - if (et != null) - { - m_read = new EnvironmentStringExpressionSet( et ); - } - - et = esd.Attribute( "Write" ); - if (et != null) - { - m_write = new EnvironmentStringExpressionSet( et ); - } - - } -#endif // FEATURE_CAS_POLICY /// int IBuiltInPermission.GetTokenIndex() diff --git a/src/mscorlib/src/System/Security/Permissions/FileDialogPermission.cs b/src/mscorlib/src/System/Security/Permissions/FileDialogPermission.cs index 6d6c221..98a7d54 100644 --- a/src/mscorlib/src/System/Security/Permissions/FileDialogPermission.cs +++ b/src/mscorlib/src/System/Security/Permissions/FileDialogPermission.cs @@ -66,22 +66,6 @@ namespace System.Security.Permissions { return new FileDialogPermission(this.access); } -#if FEATURE_CAS_POLICY - public override void FromXml(SecurityElement esd) { - CodeAccessPermission.ValidateElement(esd, this); - if (XMLUtil.IsUnrestricted(esd)) { - SetUnrestricted(true); - return; - } - - access = FileDialogPermissionAccess.None; - - string accessXml = esd.Attribute("Access"); - if (accessXml != null) - access = (FileDialogPermissionAccess)Enum.Parse(typeof(FileDialogPermissionAccess), accessXml); - } -#endif // FEATURE_CAS_POLICY - /// int IBuiltInPermission.GetTokenIndex() { return FileDialogPermission.GetTokenIndex(); @@ -152,21 +136,6 @@ namespace System.Security.Permissions { } } -#if FEATURE_CAS_POLICY - public override SecurityElement ToXml() { - SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.FileDialogPermission" ); - if (!IsUnrestricted()) { - if (access != FileDialogPermissionAccess.None) { - esd.AddAttribute("Access", Enum.GetName(typeof(FileDialogPermissionAccess), access)); - } - } - else { - esd.AddAttribute("Unrestricted", "true"); - } - return esd; - } -#endif // FEATURE_CAS_POLICY - public override IPermission Union(IPermission target) { if (target == null) { return this.Copy(); @@ -177,7 +146,7 @@ namespace System.Security.Permissions { FileDialogPermission operand = (FileDialogPermission)target; return new FileDialogPermission(access | operand.Access); - } + } static void VerifyAccess(FileDialogPermissionAccess access) { if ((access & ~FileDialogPermissionAccess.OpenSave) != 0 ) { diff --git a/src/mscorlib/src/System/Security/Permissions/FileIOPermission.cs b/src/mscorlib/src/System/Security/Permissions/FileIOPermission.cs index b4d4141..34b9f1e 100644 --- a/src/mscorlib/src/System/Security/Permissions/FileIOPermission.cs +++ b/src/mscorlib/src/System/Security/Permissions/FileIOPermission.cs @@ -2,13 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Security.Permissions { +namespace System.Security.Permissions +{ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if FEATURE_CAS_POLICY - using SecurityElement = System.Security.SecurityElement; -#endif // FEATURE_CAS_POLICY using System.Security.AccessControl; using System.Security.Util; using System.IO; @@ -16,11 +14,12 @@ namespace System.Security.Permissions { using System.Globalization; using System.Runtime.Serialization; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; -[Serializable] + [Serializable] [Flags] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public enum FileIOPermissionAccess { NoAccess = 0x00, @@ -30,9 +29,8 @@ namespace System.Security.Permissions { PathDiscovery = 0x08, AllAccess = 0x0F, } - - -[System.Runtime.InteropServices.ComVisible(true)] + + [System.Runtime.InteropServices.ComVisible(true)] [Serializable] sealed public class FileIOPermission : CodeAccessPermission, IUnrestrictedPermission, IBuiltInPermission { @@ -62,7 +60,6 @@ namespace System.Security.Permissions { } } - [System.Security.SecuritySafeCritical] // auto-generated public FileIOPermission( FileIOPermissionAccess access, String path ) { VerifyAccess( access ); @@ -71,7 +68,6 @@ namespace System.Security.Permissions { AddPathList( access, pathList, false, true, false ); } - [System.Security.SecuritySafeCritical] // auto-generated public FileIOPermission( FileIOPermissionAccess access, String[] pathList ) { VerifyAccess( access ); @@ -79,24 +75,6 @@ namespace System.Security.Permissions { AddPathList( access, pathList, false, true, false ); } -#if FEATURE_MACL - [System.Security.SecuritySafeCritical] // auto-generated - public FileIOPermission( FileIOPermissionAccess access, AccessControlActions control, String path ) - { - VerifyAccess( access ); - - String[] pathList = new String[] { path }; - AddPathList( access, control, pathList, false, true, false ); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public FileIOPermission( FileIOPermissionAccess access, AccessControlActions control, String[] pathList ) - : this( access, control, pathList, true, true ) - { - } -#endif - - [System.Security.SecurityCritical] // auto-generated internal FileIOPermission( FileIOPermissionAccess access, String[] pathList, bool checkForDuplicates, bool needFullPath ) { VerifyAccess( access ); @@ -104,16 +82,6 @@ namespace System.Security.Permissions { AddPathList( access, pathList, checkForDuplicates, needFullPath, true ); } -#if FEATURE_MACL - [System.Security.SecurityCritical] // auto-generated - internal FileIOPermission( FileIOPermissionAccess access, AccessControlActions control, String[] pathList, bool checkForDuplicates, bool needFullPath ) - { - VerifyAccess( access ); - - AddPathList( access, control, pathList, checkForDuplicates, needFullPath, true ); - } -#endif - public void SetPathList( FileIOPermissionAccess access, String path ) { String[] pathList; @@ -135,7 +103,6 @@ namespace System.Security.Permissions { SetPathList( access, AccessControlActions.None, pathList, checkForDuplicates ); } - [System.Security.SecuritySafeCritical] // auto-generated internal void SetPathList( FileIOPermissionAccess access, AccessControlActions control, String[] pathList, bool checkForDuplicates ) { VerifyAccess( access ); @@ -152,26 +119,13 @@ namespace System.Security.Permissions { if ((access & FileIOPermissionAccess.PathDiscovery) != 0) m_pathDiscovery = null; -#if FEATURE_MACL - if ((control & AccessControlActions.View) != 0) - m_viewAcl = null; - - if ((control & AccessControlActions.Change) != 0) - m_changeAcl = null; -#else m_viewAcl = null; m_changeAcl = null; -#endif - m_unrestricted = false; -#if FEATURE_MACL - AddPathList( access, control, pathList, checkForDuplicates, true, true ); -#else + AddPathList( access, pathList, checkForDuplicates, true, true ); -#endif } - [System.Security.SecuritySafeCritical] // auto-generated public void AddPathList( FileIOPermissionAccess access, String path ) { String[] pathList; @@ -182,19 +136,16 @@ namespace System.Security.Permissions { AddPathList( access, pathList, false, true, false ); } - [System.Security.SecuritySafeCritical] // auto-generated public void AddPathList( FileIOPermissionAccess access, String[] pathList ) { AddPathList( access, pathList, true, true, true ); } - [System.Security.SecurityCritical] // auto-generated internal void AddPathList( FileIOPermissionAccess access, String[] pathListOrig, bool checkForDuplicates, bool needFullPath, bool copyPathList ) { AddPathList( access, AccessControlActions.None, pathListOrig, checkForDuplicates, needFullPath, copyPathList ); } - [System.Security.SecurityCritical] // auto-generated internal void AddPathList(FileIOPermissionAccess access, AccessControlActions control, String[] pathListOrig, bool checkForDuplicates, bool needFullPath, bool copyPathList) { if (pathListOrig == null) @@ -267,29 +218,8 @@ namespace System.Security.Permissions { } m_pathDiscovery.AddExpressions( pathArrayList, checkForDuplicates); } - -#if FEATURE_MACL - if ((control & AccessControlActions.View) != 0) - { - if (m_viewAcl == null) - { - m_viewAcl = new FileIOAccess(); - } - m_viewAcl.AddExpressions( pathArrayList, checkForDuplicates); - } - - if ((control & AccessControlActions.Change) != 0) - { - if (m_changeAcl == null) - { - m_changeAcl = new FileIOAccess(); - } - m_changeAcl.AddExpressions( pathArrayList, checkForDuplicates); - } -#endif } - - [SecuritySafeCritical] + public String[] GetPathList( FileIOPermissionAccess access ) { VerifyAccess( access ); @@ -335,7 +265,6 @@ namespace System.Security.Permissions { return null; } - public FileIOPermissionAccess AllLocalFiles { @@ -558,7 +487,7 @@ namespace System.Security.Permissions { throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars")); if (!onlyCheckExtras) - Path.CheckInvalidPathChars(str[i]); + PathInternal.CheckInvalidPathChars(str[i]); } #else // There are no "extras" on Unix @@ -567,7 +496,7 @@ namespace System.Security.Permissions { for (int i = 0; i < str.Length; ++i) { - Path.CheckInvalidPathChars(str[i]); + PathInternal.CheckInvalidPathChars(str[i]); } #endif } @@ -785,123 +714,6 @@ namespace System.Security.Permissions { } return copy; } - -#if FEATURE_CAS_POLICY - public override SecurityElement ToXml() - { - SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.FileIOPermission" ); - if (!IsUnrestricted()) - { - if (this.m_read != null && !this.m_read.IsEmpty()) - { - esd.AddAttribute( "Read", SecurityElement.Escape( m_read.ToString() ) ); - } - if (this.m_write != null && !this.m_write.IsEmpty()) - { - esd.AddAttribute( "Write", SecurityElement.Escape( m_write.ToString() ) ); - } - if (this.m_append != null && !this.m_append.IsEmpty()) - { - esd.AddAttribute( "Append", SecurityElement.Escape( m_append.ToString() ) ); - } - if (this.m_pathDiscovery != null && !this.m_pathDiscovery.IsEmpty()) - { - esd.AddAttribute( "PathDiscovery", SecurityElement.Escape( m_pathDiscovery.ToString() ) ); - } - if (this.m_viewAcl != null && !this.m_viewAcl.IsEmpty()) - { - esd.AddAttribute( "ViewAcl", SecurityElement.Escape( m_viewAcl.ToString() ) ); - } - if (this.m_changeAcl != null && !this.m_changeAcl.IsEmpty()) - { - esd.AddAttribute( "ChangeAcl", SecurityElement.Escape( m_changeAcl.ToString() ) ); - } - - } - else - { - esd.AddAttribute( "Unrestricted", "true" ); - } - return esd; - } - - [System.Security.SecuritySafeCritical] // auto-generated - public override void FromXml(SecurityElement esd) - { - CodeAccessPermission.ValidateElement( esd, this ); - String et; - - if (XMLUtil.IsUnrestricted(esd)) - { - m_unrestricted = true; - return; - } - - - m_unrestricted = false; - - et = esd.Attribute( "Read" ); - if (et != null) - { - m_read = new FileIOAccess( et ); - } - else - { - m_read = null; - } - - et = esd.Attribute( "Write" ); - if (et != null) - { - m_write = new FileIOAccess( et ); - } - else - { - m_write = null; - } - - et = esd.Attribute( "Append" ); - if (et != null) - { - m_append = new FileIOAccess( et ); - } - else - { - m_append = null; - } - - et = esd.Attribute( "PathDiscovery" ); - if (et != null) - { - m_pathDiscovery = new FileIOAccess( et ); - m_pathDiscovery.PathDiscovery = true; - } - else - { - m_pathDiscovery = null; - } - - et = esd.Attribute( "ViewAcl" ); - if (et != null) - { - m_viewAcl = new FileIOAccess( et ); - } - else - { - m_viewAcl = null; - } - - et = esd.Attribute( "ChangeAcl" ); - if (et != null) - { - m_changeAcl = new FileIOAccess( et ); - } - else - { - m_changeAcl = null; - } - } -#endif // FEATURE_CAS_POLICY /// int IBuiltInPermission.GetTokenIndex() @@ -993,19 +805,9 @@ namespace System.Security.Permissions { /// /// IMPORTANT: This method should only be used after calling GetFullPath on the path to verify /// - [System.Security.SecuritySafeCritical] internal static void QuickDemand(FileIOPermissionAccess access, string fullPath, bool checkForDuplicates = false, bool needFullPath = false) { -#if FEATURE_CAS_POLICY - if (!CodeAccessSecurityEngine.QuickCheckForAllDemands()) - { - new FileIOPermission(access, new string[] { fullPath }, checkForDuplicates, needFullPath).Demand(); - } - else -#endif - { - EmulateFileIOPermissionChecks(fullPath); - } + EmulateFileIOPermissionChecks(fullPath); } /// @@ -1018,67 +820,19 @@ namespace System.Security.Permissions { /// IMPORTANT: This method should only be used after calling GetFullPath on the path to verify /// /// - [System.Security.SecuritySafeCritical] internal static void QuickDemand(FileIOPermissionAccess access, string[] fullPathList, bool checkForDuplicates = false, bool needFullPath = true) { -#if FEATURE_CAS_POLICY - if (!CodeAccessSecurityEngine.QuickCheckForAllDemands()) - { - new FileIOPermission(access, fullPathList, checkForDuplicates, needFullPath).Demand(); - } - else -#endif + foreach (string fullPath in fullPathList) { - foreach (string fullPath in fullPathList) - { - EmulateFileIOPermissionChecks(fullPath); - } + EmulateFileIOPermissionChecks(fullPath); } } - [System.Security.SecuritySafeCritical] internal static void QuickDemand(PermissionState state) { // Should be a no-op without CAS -#if FEATURE_CAS_POLICY - if (!CodeAccessSecurityEngine.QuickCheckForAllDemands()) - { - new FileIOPermission(state).Demand(); - } -#endif - } - -#if FEATURE_MACL - [System.Security.SecuritySafeCritical] - internal static void QuickDemand(FileIOPermissionAccess access, AccessControlActions control, string fullPath, bool checkForDuplicates = false, bool needFullPath = true) - { - if (!CodeAccessSecurityEngine.QuickCheckForAllDemands()) - { - new FileIOPermission(access, control, new string[] { fullPath }, checkForDuplicates, needFullPath).Demand(); - } - else - { - EmulateFileIOPermissionChecks(fullPath); - } } - [System.Security.SecuritySafeCritical] - internal static void QuickDemand(FileIOPermissionAccess access, AccessControlActions control, string[] fullPathList, bool checkForDuplicates = true, bool needFullPath = true) - { - if (!CodeAccessSecurityEngine.QuickCheckForAllDemands()) - { - new FileIOPermission(access, control, fullPathList, checkForDuplicates, needFullPath).Demand(); - } - else - { - foreach (string fullPath in fullPathList) - { - EmulateFileIOPermissionChecks(fullPath); - } - } - } -#endif - /// /// Perform the additional path checks that would normally happen when creating a FileIOPermission object. /// @@ -1088,18 +842,10 @@ namespace System.Security.Permissions { // Callers should have already made checks for invalid path format via normalization. This method will only make the // additional checks needed to throw the same exceptions that would normally throw when using FileIOPermission. // These checks are done via CheckIllegalCharacters() and StringExpressionSet in AddPathList() above. - // - // We have to check the beginning as some paths may be passed in as path + @"\.", which will be normalized away. - BCLDebug.Assert( - fullPath.StartsWith(Path.NormalizePath(fullPath, fullCheck: false), StringComparison.OrdinalIgnoreCase), - string.Format("path isn't normalized: {0}", fullPath)); +#if !PLATFORM_UNIX // Checking for colon / invalid characters on device paths blocks legitimate access to objects such as named pipes. - if ( -#if FEATURE_PATHCOMPAT - AppContextSwitches.UseLegacyPathHandling || -#endif - !PathInternal.IsDevice(fullPath)) + if (!PathInternal.IsDevice(fullPath)) { // GetFullPath already checks normal invalid path characters. We need to just check additional (wildcard) characters here. // (By calling the standard helper we can allow extended paths \\?\ through when the support is enabled.) @@ -1113,6 +859,7 @@ namespace System.Security.Permissions { throw new NotSupportedException(Environment.GetResourceString("Argument_PathFormatNotSupported")); } } +#endif // !PLATFORM_UNIX } } @@ -1149,7 +896,6 @@ namespace System.Security.Permissions { m_pathDiscovery = pathDiscovery; } - [System.Security.SecurityCritical] // auto-generated public FileIOAccess( String value ) { if (value == null) @@ -1204,7 +950,6 @@ namespace System.Security.Permissions { m_pathDiscovery = operand.m_pathDiscovery; } - [System.Security.SecurityCritical] // auto-generated public void AddExpressions(ArrayList values, bool checkForDuplicates) { m_allFiles = false; @@ -1255,7 +1000,6 @@ namespace System.Security.Permissions { return new FileIOAccess( this ); } - [System.Security.SecuritySafeCritical] // auto-generated public FileIOAccess Union( FileIOAccess operand ) { if (operand == null) @@ -1263,7 +1007,7 @@ namespace System.Security.Permissions { return this.IsEmpty() ? null : this.Copy(); } - Contract.Assert( this.m_pathDiscovery == operand.m_pathDiscovery, "Path discovery settings must match" ); + Debug.Assert( this.m_pathDiscovery == operand.m_pathDiscovery, "Path discovery settings must match" ); if (this.m_allFiles || operand.m_allFiles) { @@ -1273,7 +1017,6 @@ namespace System.Security.Permissions { return new FileIOAccess( this.m_set.Union( operand.m_set ), false, this.m_allLocalFiles || operand.m_allLocalFiles, this.m_pathDiscovery ); } - [System.Security.SecuritySafeCritical] // auto-generated public FileIOAccess Intersect( FileIOAccess operand ) { if (operand == null) @@ -1281,7 +1024,7 @@ namespace System.Security.Permissions { return null; } - Contract.Assert( this.m_pathDiscovery == operand.m_pathDiscovery, "Path discovery settings must match" ); + Debug.Assert( this.m_pathDiscovery == operand.m_pathDiscovery, "Path discovery settings must match" ); if (this.m_allFiles) { @@ -1343,7 +1086,6 @@ namespace System.Security.Permissions { return new FileIOAccess( intersectionSet, false, this.m_allLocalFiles && operand.m_allLocalFiles, this.m_pathDiscovery ); } - [System.Security.SecuritySafeCritical] // auto-generated public bool IsSubsetOf( FileIOAccess operand ) { if (operand == null) @@ -1356,7 +1098,7 @@ namespace System.Security.Permissions { return true; } - Contract.Assert( this.m_pathDiscovery == operand.m_pathDiscovery, "Path discovery settings must match" ); + Debug.Assert( this.m_pathDiscovery == operand.m_pathDiscovery, "Path discovery settings must match" ); if (!((m_pathDiscovery && this.m_set.IsSubsetOfPathDiscovery( operand.m_set )) || this.m_set.IsSubsetOf( operand.m_set ))) { @@ -1400,7 +1142,6 @@ namespace System.Security.Permissions { } } - [SecuritySafeCritical] public override String ToString() { // SafeCritical: all string expression sets are constructed with the throwOnRelative bit set, so @@ -1429,7 +1170,6 @@ namespace System.Security.Permissions { } } - [SecuritySafeCritical] public String[] ToStringArray() { // SafeCritical: all string expression sets are constructed with the throwOnRelative bit set, so @@ -1437,18 +1177,16 @@ namespace System.Security.Permissions { return m_set.UnsafeToStringArray(); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern bool IsLocalDrive(String path); - [System.Security.SecuritySafeCritical] // auto-generated public override bool Equals(Object obj) { FileIOAccess operand = obj as FileIOAccess; if(operand == null) return (IsEmpty() && obj == null); - Contract.Assert( this.m_pathDiscovery == operand.m_pathDiscovery, "Path discovery settings must match" ); + Debug.Assert( this.m_pathDiscovery == operand.m_pathDiscovery, "Path discovery settings must match" ); if(m_pathDiscovery) { if(this.m_allFiles && operand.m_allFiles) diff --git a/src/mscorlib/src/System/Security/Permissions/GACIdentityPermission.cs b/src/mscorlib/src/System/Security/Permissions/GACIdentityPermission.cs index 5c209af..f93f26d 100644 --- a/src/mscorlib/src/System/Security/Permissions/GACIdentityPermission.cs +++ b/src/mscorlib/src/System/Security/Permissions/GACIdentityPermission.cs @@ -5,9 +5,6 @@ namespace System.Security.Permissions { using System; -#if FEATURE_CAS_POLICY - using SecurityElement = System.Security.SecurityElement; -#endif // FEATURE_CAS_POLICY using System.Globalization; [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )] @@ -92,19 +89,6 @@ namespace System.Security.Permissions return this.Copy(); } -#if FEATURE_CAS_POLICY - public override SecurityElement ToXml() - { - SecurityElement securityElement = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.GacIdentityPermission" ); - return securityElement; - } - - public override void FromXml(SecurityElement securityElement) - { - CodeAccessPermission.ValidateElement(securityElement, this); - } -#endif // FEATURE_CAS_POLICY - /// int IBuiltInPermission.GetTokenIndex() { diff --git a/src/mscorlib/src/System/Security/Permissions/HostProtectionPermission.cs b/src/mscorlib/src/System/Security/Permissions/HostProtectionPermission.cs index 85be61a..c4facbb 100644 --- a/src/mscorlib/src/System/Security/Permissions/HostProtectionPermission.cs +++ b/src/mscorlib/src/System/Security/Permissions/HostProtectionPermission.cs @@ -41,11 +41,9 @@ namespace System.Security.Permissions [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly | AttributeTargets.Delegate, AllowMultiple = true, Inherited = false )] [System.Runtime.InteropServices.ComVisible(true)] [Serializable] -#if FEATURE_CORECLR // This needs to be in the asmmeta to enable SecAnnotate to successfully resolve and run the security rules. It gets marked // as internal by BCLRewriter so we are simply marking it as FriendAccessAllowed so it stays in the asmmeta. [System.Runtime.CompilerServices.FriendAccessAllowedAttribute] -#endif // FEATURE_CORECLR #pragma warning disable 618 sealed public class HostProtectionAttribute : CodeAccessSecurityAttribute #pragma warning restore 618 @@ -247,38 +245,6 @@ namespace System.Security.Permissions return new HostProtectionPermission(m_resources); } -#if FEATURE_CAS_POLICY - //------------------------------------------------------ - // - // XML - // - //------------------------------------------------------ - public override SecurityElement ToXml() - { - SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, this.GetType().FullName ); - if(IsUnrestricted()) - esd.AddAttribute( "Unrestricted", "true" ); - else - esd.AddAttribute( "Resources", XMLUtil.BitFieldEnumToString( typeof( HostProtectionResource ), Resources ) ); - return esd; - } - - public override void FromXml(SecurityElement esd) - { - CodeAccessPermission.ValidateElement( esd, this ); - if (XMLUtil.IsUnrestricted( esd )) - Resources = HostProtectionResource.All; - else - { - String resources = esd.Attribute( "Resources" ); - if (resources == null) - Resources = HostProtectionResource.None; - else - Resources = (HostProtectionResource)Enum.Parse( typeof( HostProtectionResource ), resources ); - } - } -#endif // FEATURE_CAS_POLICY - //------------------------------------------------------ // // OBJECT OVERRIDES diff --git a/src/mscorlib/src/System/Security/Permissions/IsolatedStorageFilePermission.cs b/src/mscorlib/src/System/Security/Permissions/IsolatedStorageFilePermission.cs index 1e11b4a..42bc648 100644 --- a/src/mscorlib/src/System/Security/Permissions/IsolatedStorageFilePermission.cs +++ b/src/mscorlib/src/System/Security/Permissions/IsolatedStorageFilePermission.cs @@ -158,19 +158,6 @@ namespace System.Security.Permissions { { return BuiltInPermissionIndex.IsolatedStorageFilePermissionIndex; } - - //------------------------------------------------------ - // - // IsolatedStoragePermission OVERRIDES - // - //------------------------------------------------------ -#if FEATURE_CAS_POLICY - [System.Runtime.InteropServices.ComVisible(false)] - public override SecurityElement ToXml() - { - return base.ToXml( "System.Security.Permissions.IsolatedStorageFilePermission" ); - } -#endif // FEATURE_CAS_POLICY } } diff --git a/src/mscorlib/src/System/Security/Permissions/IsolatedStoragePermission.cs b/src/mscorlib/src/System/Security/Permissions/IsolatedStoragePermission.cs index 308adbd..9f09a37 100644 --- a/src/mscorlib/src/System/Security/Permissions/IsolatedStoragePermission.cs +++ b/src/mscorlib/src/System/Security/Permissions/IsolatedStoragePermission.cs @@ -32,9 +32,6 @@ namespace System.Security.Permissions { [Serializable] -#if !FEATURE_CORECLR - [SecurityPermissionAttribute( SecurityAction.InheritanceDemand, ControlEvidence = true, ControlPolicy = true )] -#endif [System.Runtime.InteropServices.ComVisible(true)] abstract public class IsolatedStoragePermission : CodeAccessPermission, IUnrestrictedPermission @@ -182,93 +179,5 @@ namespace System.Security.Permissions { //------------------------------------------------------ internal static long min(long x,long y) {return x>y?y:x;} internal static long max(long x,long y) {return x0) - { - esd.AddAttribute(_strUserQuota, (m_userQuota).ToString(CultureInfo.InvariantCulture)) ; - } - if (m_machineQuota>0) - { - esd.AddAttribute(_strMachineQuota, (m_machineQuota).ToString(CultureInfo.InvariantCulture)) ; - } - if (m_expirationDays>0) - { - esd.AddAttribute( _strExpiry, (m_expirationDays).ToString(CultureInfo.InvariantCulture)) ; - } - if (m_permanentData) - { - esd.AddAttribute(_strPermDat, (m_permanentData).ToString()) ; - } - } - else - { - esd.AddAttribute( "Unrestricted", "true" ); - } - return esd; - } - - - public override void FromXml(SecurityElement esd) - { - CodeAccessPermission.ValidateElement( esd, this ); - - m_allowed = IsolatedStorageContainment.None; // default if no match - - if (XMLUtil.IsUnrestricted(esd)) - { - m_allowed = IsolatedStorageContainment.UnrestrictedIsolatedStorage; - } - else - { - String allowed = esd.Attribute( "Allowed" ); - - if (allowed != null) - m_allowed = (IsolatedStorageContainment)Enum.Parse( typeof( IsolatedStorageContainment ), allowed ); - } - - if (m_allowed == IsolatedStorageContainment.UnrestrictedIsolatedStorage) - { - m_userQuota = Int64.MaxValue; - m_machineQuota = Int64.MaxValue; - m_expirationDays = Int64.MaxValue ; - m_permanentData = true; - } - else - { - String param; - param = esd.Attribute (_strUserQuota) ; - m_userQuota = param != null ? Int64.Parse(param, CultureInfo.InvariantCulture) : 0 ; - param = esd.Attribute (_strMachineQuota) ; - m_machineQuota = param != null ? Int64.Parse(param, CultureInfo.InvariantCulture) : 0 ; - param = esd.Attribute (_strExpiry) ; - m_expirationDays = param != null ? Int64.Parse(param, CultureInfo.InvariantCulture) : 0 ; - param = esd.Attribute (_strPermDat) ; - m_permanentData = param != null ? (Boolean.Parse(param)) : false ; - } - } -#endif // FEATURE_CAS_POLICY } } diff --git a/src/mscorlib/src/System/Security/Permissions/PermissionAttributes.cs b/src/mscorlib/src/System/Security/Permissions/PermissionAttributes.cs index f14fb0d..b6ac8ec 100644 --- a/src/mscorlib/src/System/Security/Permissions/PermissionAttributes.cs +++ b/src/mscorlib/src/System/Security/Permissions/PermissionAttributes.cs @@ -8,9 +8,6 @@ namespace System.Security.Permissions using System.Security.Util; using System.IO; using System.Security.Policy; -#if FEATURE_MACL - using System.Security.AccessControl; -#endif using System.Text; using System.Threading; using System.Runtime.InteropServices; @@ -23,11 +20,9 @@ namespace System.Security.Permissions using System.Diagnostics.Contracts; [Serializable] -[System.Runtime.InteropServices.ComVisible(true)] -#if !FEATURE_CAS_POLICY + [System.Runtime.InteropServices.ComVisible(true)] // The csharp compiler requires these types to be public, but they are not used elsewhere. [Obsolete("SecurityAction is no longer accessible to application code.")] -#endif public enum SecurityAction { // Demand permission of all caller @@ -62,14 +57,11 @@ namespace System.Security.Permissions RequestRefuse = 10, } - -[Serializable] -[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )] -[System.Runtime.InteropServices.ComVisible(true)] -#if !FEATURE_CAS_POLICY + [Serializable] + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )] + [System.Runtime.InteropServices.ComVisible(true)] // The csharp compiler requires these types to be public, but they are not used elsewhere. [Obsolete("SecurityAttribute is no longer accessible to application code.")] -#endif public abstract class SecurityAttribute : System.Attribute { /// @@ -96,7 +88,6 @@ namespace System.Security.Permissions abstract public IPermission CreatePermission(); - [System.Security.SecurityCritical] // auto-generated internal static unsafe IntPtr FindSecurityAttributeTypeHandle(String typeName) { PermissionSet.s_fullTrust.Assert(); @@ -108,13 +99,11 @@ namespace System.Security.Permissions } } -[Serializable] -[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )] -[System.Runtime.InteropServices.ComVisible(true)] -#if !FEATURE_CAS_POLICY + [Serializable] + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )] + [System.Runtime.InteropServices.ComVisible(true)] // The csharp compiler requires these types to be public, but they are not used elsewhere. [Obsolete("CodeAccessSecurityAttribute is no longer accessible to application code.")] -#endif public abstract class CodeAccessSecurityAttribute : SecurityAttribute { protected CodeAccessSecurityAttribute( SecurityAction action ) @@ -307,12 +296,6 @@ namespace System.Security.Permissions perm.SetPathList( FileIOPermissionAccess.Append, m_append ); if (m_pathDiscovery != null) perm.SetPathList( FileIOPermissionAccess.PathDiscovery, m_pathDiscovery ); -#if FEATURE_MACL - if (m_viewAccess != null) - perm.SetPathList( FileIOPermissionAccess.NoAccess, AccessControlActions.View, new String[] { m_viewAccess }, false ); - if (m_changeAccess != null) - perm.SetPathList( FileIOPermissionAccess.NoAccess, AccessControlActions.Change, new String[] { m_changeAccess }, false ); -#endif perm.AllFiles = m_allFiles; perm.AllLocalFiles = m_allLocalFiles; @@ -384,59 +367,6 @@ namespace System.Security.Permissions } } -#if !FEATURE_CORECLR - // PrincipalPermissionAttribute currently derives from - // CodeAccessSecurityAttribute, even though it's not related to code access - // security. This is because compilers are currently looking for - // CodeAccessSecurityAttribute as a direct parent class rather than - // SecurityAttribute as the root class. - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true, Inherited = false )] -[System.Runtime.InteropServices.ComVisible(true)] - [Serializable] - sealed public class PrincipalPermissionAttribute : CodeAccessSecurityAttribute - { - private String m_name = null; - private String m_role = null; - private bool m_authenticated = true; - - public PrincipalPermissionAttribute( SecurityAction action ) - : base( action ) - { - } - - public String Name - { - get { return m_name; } - set { m_name = value; } - } - - public String Role - { - get { return m_role; } - set { m_role = value; } - } - - public bool Authenticated - { - get { return m_authenticated; } - set { m_authenticated = value; } - } - - - public override IPermission CreatePermission() - { - if (m_unrestricted) - { - return new PrincipalPermission( PermissionState.Unrestricted ); - } - else - { - return new PrincipalPermission( m_name, m_role, m_authenticated ); - } - } - } -#endif // !FEATURE_CORECLR - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )] [System.Runtime.InteropServices.ComVisible(true)] [Serializable] @@ -570,24 +500,16 @@ namespace System.Security.Permissions perm.SetPathList( RegistryPermissionAccess.Write, m_write ); if (m_create != null) perm.SetPathList( RegistryPermissionAccess.Create, m_create ); -#if FEATURE_MACL - if (m_viewAcl != null) - perm.SetPathList( AccessControlActions.View, m_viewAcl ); - if (m_changeAcl != null) - perm.SetPathList( AccessControlActions.Change, m_changeAcl ); -#endif return perm; } } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] [Serializable] -#if !FEATURE_CAS_POLICY // The csharp compiler requires these types to be public, but they are not used elsewhere. [Obsolete("SecurityPermissionAttribute is no longer accessible to application code.")] -#endif sealed public class SecurityPermissionAttribute : CodeAccessSecurityAttribute { private SecurityPermissionFlag m_flag = SecurityPermissionFlag.NoFlags; @@ -662,7 +584,7 @@ namespace System.Security.Permissions set { m_flag = value ? m_flag | SecurityPermissionFlag.RemotingConfiguration : m_flag & ~SecurityPermissionFlag.RemotingConfiguration; } } -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public bool Infrastructure { get { return (m_flag & SecurityPermissionFlag.Infrastructure) != 0; } set { m_flag = value ? m_flag | SecurityPermissionFlag.Infrastructure : m_flag & ~SecurityPermissionFlag.Infrastructure; } @@ -893,170 +815,6 @@ namespace System.Security.Permissions } } } - -#if FEATURE_X509 && FEATURE_CAS_POLICY - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )] -[System.Runtime.InteropServices.ComVisible(true)] - [Serializable] - sealed public class PublisherIdentityPermissionAttribute : CodeAccessSecurityAttribute - { - private String m_x509cert = null; - private String m_certFile = null; - private String m_signedFile = null; - - public PublisherIdentityPermissionAttribute( SecurityAction action ) - : base( action ) - { - m_x509cert = null; - m_certFile = null; - m_signedFile = null; - } - - public String X509Certificate { - get { return m_x509cert; } - set { m_x509cert = value; } - } - - public String CertFile { - get { return m_certFile; } - set { m_certFile = value; } - } - - public String SignedFile { - get { return m_signedFile; } - set { m_signedFile = value; } - } - - public override IPermission CreatePermission() - { - if (m_unrestricted) - { - return new PublisherIdentityPermission( PermissionState.Unrestricted ); - } - else - { - if (m_x509cert != null) - { - return new PublisherIdentityPermission( new X509Certificate( System.Security.Util.Hex.DecodeHexString( m_x509cert ) ) ); - } - else if (m_certFile != null) - { - return new PublisherIdentityPermission( System.Security.Cryptography.X509Certificates.X509Certificate.CreateFromCertFile( m_certFile ) ); - } - else if (m_signedFile != null) - { - return new PublisherIdentityPermission( System.Security.Cryptography.X509Certificates.X509Certificate.CreateFromSignedFile( m_signedFile ) ); - } - else - { - return new PublisherIdentityPermission( PermissionState.None ); - } - } - } - } -#endif // #if FEATURE_X509 && FEATURE_CAS_POLICY - -#if !FEATURE_CORECLR -[Serializable] -[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor - | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, - AllowMultiple=true, Inherited=false)] -[System.Runtime.InteropServices.ComVisible(true)] - public abstract class IsolatedStoragePermissionAttribute : CodeAccessSecurityAttribute - { - /// - internal long m_userQuota; -#if false - /// - internal long m_machineQuota; - /// - internal long m_expirationDays; - /// - internal bool m_permanentData; -#endif - /// - internal IsolatedStorageContainment m_allowed; - protected IsolatedStoragePermissionAttribute(SecurityAction action) : base(action) - { - } - - // properties - public long UserQuota { - set{ - m_userQuota = value; - } - get{ - return m_userQuota; - } - } -#if false - internal long MachineQuota { - set{ - m_machineQuota = value; - } - get{ - return m_machineQuota; - } - } - internal long ExpirationDays { - set{ - m_expirationDays = value; - } - get{ - return m_expirationDays; - } - } - internal bool PermanentData { - set{ - m_permanentData = value; - } - get{ - return m_permanentData; - } - } -#endif - public IsolatedStorageContainment UsageAllowed { - set{ - m_allowed = value; - } - get{ - return m_allowed; - } - } - - } - - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor - | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, - AllowMultiple=true, Inherited=false)] -[System.Runtime.InteropServices.ComVisible(true)] - [Serializable] - sealed public class IsolatedStorageFilePermissionAttribute : IsolatedStoragePermissionAttribute - { - public IsolatedStorageFilePermissionAttribute(SecurityAction action) : base(action) - { - - } - public override IPermission CreatePermission() - { - IsolatedStorageFilePermission p; - if (m_unrestricted) { - p = new IsolatedStorageFilePermission - (PermissionState.Unrestricted); - } else { - p = new IsolatedStorageFilePermission(PermissionState.None); - p.UserQuota = m_userQuota; - p.UsageAllowed = m_allowed; -#if false - p.PermanentData = m_permanentData; - p.MachineQuota = m_machineQuota; - p.ExpirationDays = m_expirationDays; -#endif - } - return p; - } - } -#endif // FEATURE_CORECLR [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )] [System.Runtime.InteropServices.ComVisible(true)] @@ -1109,66 +867,12 @@ namespace System.Security.Permissions return null; } -#if FEATURE_CAS_POLICY - private PermissionSet BruteForceParseStream(Stream stream) - { - Encoding[] encodings = new Encoding[] { Encoding.UTF8, - Encoding.ASCII, - Encoding.Unicode }; - - StreamReader reader = null; - Exception exception = null; - - for (int i = 0; reader == null && i < encodings.Length; ++i) - { - try - { - stream.Position = 0; - reader = new StreamReader( stream, encodings[i] ); - - return ParsePermissionSet( new Parser(reader) ); - } - catch (Exception e1) - { - if (exception == null) - exception = e1; - } - } - - throw exception; - } - - private PermissionSet ParsePermissionSet(Parser parser) - { - SecurityElement e = parser.GetTopElement(); - PermissionSet permSet = new PermissionSet( PermissionState.None ); - permSet.FromXml( e ); - - return permSet; - } -#endif // FEATURE_CAS_POLICY - -#if FEATURE_CAS_POLICY - [System.Security.SecuritySafeCritical] // auto-generated -#endif public PermissionSet CreatePermissionSet() { if (m_unrestricted) return new PermissionSet( PermissionState.Unrestricted ); else if (m_name != null) -#if FEATURE_CAS_POLICY - return PolicyLevel.GetBuiltInSet( m_name ); -#else return NamedPermissionSet.GetBuiltInSet( m_name ); -#endif // FEATURE_CAS_POLICY -#if FEATURE_CAS_POLICY - else if (m_xml != null) - return ParsePermissionSet( new Parser(m_xml.ToCharArray()) ); - else if (m_hex != null) - return BruteForceParseStream( new MemoryStream(Util.Hex.DecodeHexString(m_hex)) ); - else if (m_file != null) - return BruteForceParseStream( new FileStream( m_file, FileMode.Open, FileAccess.Read) ); -#endif // FEATURE_CAS_POLICY else return new PermissionSet( PermissionState.None ); } diff --git a/src/mscorlib/src/System/Security/Permissions/ReflectionPermission.cs b/src/mscorlib/src/System/Security/Permissions/ReflectionPermission.cs index 2bc3c08..1c9dd76 100644 --- a/src/mscorlib/src/System/Security/Permissions/ReflectionPermission.cs +++ b/src/mscorlib/src/System/Security/Permissions/ReflectionPermission.cs @@ -259,45 +259,6 @@ namespace System.Security.Permissions throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)type)); Contract.EndContractBlock(); } - -#if FEATURE_CAS_POLICY - //------------------------------------------------------ - // - // PUBLIC ENCODING METHODS - // - //------------------------------------------------------ - - public override SecurityElement ToXml() - { - SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.ReflectionPermission" ); - if (!IsUnrestricted()) - { - esd.AddAttribute( "Flags", XMLUtil.BitFieldEnumToString( typeof( ReflectionPermissionFlag ), m_flags ) ); - } - else - { - esd.AddAttribute( "Unrestricted", "true" ); - } - return esd; - } - - public override void FromXml(SecurityElement esd) - { - CodeAccessPermission.ValidateElement( esd, this ); - if (XMLUtil.IsUnrestricted( esd )) - { - m_flags = ReflectionPermission.AllFlagsAndMore; - return; - } - - Reset () ; - SetUnrestricted (false) ; - - String flags = esd.Attribute( "Flags" ); - if (flags != null) - m_flags = (ReflectionPermissionFlag)Enum.Parse( typeof( ReflectionPermissionFlag ), flags ); - } -#endif // FEATURE_CAS_POLICY /// int IBuiltInPermission.GetTokenIndex() diff --git a/src/mscorlib/src/System/Security/Permissions/RegistryPermission.cs b/src/mscorlib/src/System/Security/Permissions/RegistryPermission.cs index bf801d6..c0c51e9 100644 --- a/src/mscorlib/src/System/Security/Permissions/RegistryPermission.cs +++ b/src/mscorlib/src/System/Security/Permissions/RegistryPermission.cs @@ -59,14 +59,6 @@ namespace System.Security.Permissions SetPathList( access, pathList ); } -#if FEATURE_MACL - public RegistryPermission( RegistryPermissionAccess access, AccessControlActions control, String pathList ) - { - m_unrestricted = false; - AddPathList( access, control, pathList ); - } -#endif - public void SetPathList( RegistryPermissionAccess access, String pathList ) { VerifyAccess( access ); @@ -85,27 +77,11 @@ namespace System.Security.Permissions AddPathList( access, pathList ); } -#if FEATURE_MACL - internal void SetPathList( AccessControlActions control, String pathList ) - { - m_unrestricted = false; - - if ((control & AccessControlActions.View) != 0) - m_viewAcl = null; - - if ((control & AccessControlActions.Change) != 0) - m_changeAcl = null; - - AddPathList( RegistryPermissionAccess.NoAccess, control, pathList ); - } -#endif - public void AddPathList( RegistryPermissionAccess access, String pathList ) { AddPathList( access, AccessControlActions.None, pathList ); } - [System.Security.SecuritySafeCritical] // auto-generated public void AddPathList( RegistryPermissionAccess access, AccessControlActions control, String pathList ) { VerifyAccess( access ); @@ -130,25 +106,8 @@ namespace System.Security.Permissions m_create = new StringExpressionSet(); m_create.AddExpressions( pathList ); } - -#if FEATURE_MACL - if ((control & AccessControlActions.View) != 0) - { - if (m_viewAcl == null) - m_viewAcl = new StringExpressionSet(); - m_viewAcl.AddExpressions( pathList ); - } - - if ((control & AccessControlActions.Change) != 0) - { - if (m_changeAcl == null) - m_changeAcl = new StringExpressionSet(); - m_changeAcl.AddExpressions( pathList ); - } -#endif } - [SecuritySafeCritical] public String GetPathList( RegistryPermissionAccess access ) { // SafeCritical: these are registry paths, which means we're not leaking file system information here @@ -233,7 +192,6 @@ namespace System.Security.Permissions // //------------------------------------------------------ - [System.Security.SecuritySafeCritical] // auto-generated public override bool IsSubsetOf(IPermission target) { if (target == null) @@ -257,7 +215,6 @@ namespace System.Security.Permissions (this.m_changeAcl == null || this.m_changeAcl.IsSubsetOf( operand.m_changeAcl ))); } - [System.Security.SecuritySafeCritical] // auto-generated public override IPermission Intersect(IPermission target) { if (target == null) @@ -309,7 +266,6 @@ namespace System.Security.Permissions return intersectPermission; } - [System.Security.SecuritySafeCritical] // auto-generated public override IPermission Union(IPermission other) { if (other == null) @@ -391,93 +347,6 @@ namespace System.Security.Permissions } return copy; } - -#if FEATURE_CAS_POLICY - [SecuritySafeCritical] - public override SecurityElement ToXml() - { - // SafeCritical: our string expression sets don't contain paths, so there's no information that - // needs to be guarded in them. - SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.RegistryPermission" ); - if (!IsUnrestricted()) - { - if (this.m_read != null && !this.m_read.IsEmpty()) - { - esd.AddAttribute( "Read", SecurityElement.Escape( m_read.UnsafeToString() ) ); - } - if (this.m_write != null && !this.m_write.IsEmpty()) - { - esd.AddAttribute( "Write", SecurityElement.Escape( m_write.UnsafeToString() ) ); - } - if (this.m_create != null && !this.m_create.IsEmpty()) - { - esd.AddAttribute( "Create", SecurityElement.Escape( m_create.UnsafeToString() ) ); - } - if (this.m_viewAcl != null && !this.m_viewAcl.IsEmpty()) - { - esd.AddAttribute( "ViewAccessControl", SecurityElement.Escape( m_viewAcl.UnsafeToString() ) ); - } - if (this.m_changeAcl != null && !this.m_changeAcl.IsEmpty()) - { - esd.AddAttribute( "ChangeAccessControl", SecurityElement.Escape( m_changeAcl.UnsafeToString() ) ); - } - } - else - { - esd.AddAttribute( "Unrestricted", "true" ); - } - return esd; - } - - public override void FromXml(SecurityElement esd) - { - CodeAccessPermission.ValidateElement( esd, this ); - String et; - - if (XMLUtil.IsUnrestricted( esd )) - { - m_unrestricted = true; - return; - } - - m_unrestricted = false; - m_read = null; - m_write = null; - m_create = null; - m_viewAcl = null; - m_changeAcl = null; - - et = esd.Attribute( "Read" ); - if (et != null) - { - m_read = new StringExpressionSet( et ); - } - - et = esd.Attribute( "Write" ); - if (et != null) - { - m_write = new StringExpressionSet( et ); - } - - et = esd.Attribute( "Create" ); - if (et != null) - { - m_create = new StringExpressionSet( et ); - } - - et = esd.Attribute( "ViewAccessControl" ); - if (et != null) - { - m_viewAcl = new StringExpressionSet( et ); - } - - et = esd.Attribute( "ChangeAccessControl" ); - if (et != null) - { - m_changeAcl = new StringExpressionSet( et ); - } - } -#endif // FEATURE_CAS_POLICY /// int IBuiltInPermission.GetTokenIndex() diff --git a/src/mscorlib/src/System/Security/Permissions/SecurityPermission.cs b/src/mscorlib/src/System/Security/Permissions/SecurityPermission.cs index b359cc5..cf30029 100644 --- a/src/mscorlib/src/System/Security/Permissions/SecurityPermission.cs +++ b/src/mscorlib/src/System/Security/Permissions/SecurityPermission.cs @@ -16,13 +16,11 @@ namespace System.Security.Permissions using System.Globalization; using System.Diagnostics.Contracts; -[Serializable] + [Serializable] [Flags] -[System.Runtime.InteropServices.ComVisible(true)] -#if !FEATURE_CAS_POLICY + [System.Runtime.InteropServices.ComVisible(true)] // The csharp compiler requires these types to be public, but they are not used elsewhere. [Obsolete("SecurityPermissionFlag is no longer accessible to application code.")] -#endif public enum SecurityPermissionFlag { NoFlags = 0x00, @@ -254,99 +252,9 @@ namespace System.Security.Permissions Contract.EndContractBlock(); } -#if FEATURE_CAS_POLICY - //------------------------------------------------------ - // - // PUBLIC ENCODING METHODS - // - //------------------------------------------------------ - - private const String _strHeaderAssertion = "Assertion"; - private const String _strHeaderUnmanagedCode = "UnmanagedCode"; - private const String _strHeaderExecution = "Execution"; - private const String _strHeaderSkipVerification = "SkipVerification"; - private const String _strHeaderControlThread = "ControlThread"; - private const String _strHeaderControlEvidence = "ControlEvidence"; - private const String _strHeaderControlPolicy = "ControlPolicy"; - private const String _strHeaderSerializationFormatter = "SerializationFormatter"; - private const String _strHeaderControlDomainPolicy = "ControlDomainPolicy"; - private const String _strHeaderControlPrincipal = "ControlPrincipal"; - private const String _strHeaderControlAppDomain = "ControlAppDomain"; - - public override SecurityElement ToXml() - { - SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.SecurityPermission" ); - if (!IsUnrestricted()) - { - esd.AddAttribute( "Flags", XMLUtil.BitFieldEnumToString( typeof( SecurityPermissionFlag ), m_flags ) ); - } - else - { - esd.AddAttribute( "Unrestricted", "true" ); - } - return esd; - } - - public override void FromXml(SecurityElement esd) - { - CodeAccessPermission.ValidateElement( esd, this ); - if (XMLUtil.IsUnrestricted( esd )) - { - m_flags = SecurityPermissionFlag.AllFlags; - return; - } - - Reset () ; - SetUnrestricted (false) ; - - String flags = esd.Attribute( "Flags" ); - - if (flags != null) - m_flags = (SecurityPermissionFlag)Enum.Parse( typeof( SecurityPermissionFlag ), flags ); - } -#endif // FEATURE_CAS_POLICY - // // Object Overrides // - - #if ZERO // Do not remove this code, usefull for debugging - public override String ToString() - { - StringBuilder sb = new StringBuilder(); - sb.Append("SecurityPermission("); - if (IsUnrestricted()) - { - sb.Append("Unrestricted"); - } - else - { - if (GetFlag(SecurityPermissionFlag.Assertion)) - sb.Append("Assertion; "); - if (GetFlag(SecurityPermissionFlag.UnmanagedCode)) - sb.Append("UnmangedCode; "); - if (GetFlag(SecurityPermissionFlag.SkipVerification)) - sb.Append("SkipVerification; "); - if (GetFlag(SecurityPermissionFlag.Execution)) - sb.Append("Execution; "); - if (GetFlag(SecurityPermissionFlag.ControlThread)) - sb.Append("ControlThread; "); - if (GetFlag(SecurityPermissionFlag.ControlEvidence)) - sb.Append("ControlEvidence; "); - if (GetFlag(SecurityPermissionFlag.ControlPolicy)) - sb.Append("ControlPolicy; "); - if (GetFlag(SecurityPermissionFlag.SerializationFormatter)) - sb.Append("SerializationFormatter; "); - if (GetFlag(SecurityPermissionFlag.ControlDomainPolicy)) - sb.Append("ControlDomainPolicy; "); - if (GetFlag(SecurityPermissionFlag.ControlPrincipal)) - sb.Append("ControlPrincipal; "); - } - - sb.Append(")"); - return sb.ToString(); - } - #endif /// int IBuiltInPermission.GetTokenIndex() diff --git a/src/mscorlib/src/System/Security/Permissions/SiteIdentityPermission.cs b/src/mscorlib/src/System/Security/Permissions/SiteIdentityPermission.cs index 6050b58..ff38d51 100644 --- a/src/mscorlib/src/System/Security/Permissions/SiteIdentityPermission.cs +++ b/src/mscorlib/src/System/Security/Permissions/SiteIdentityPermission.cs @@ -5,9 +5,6 @@ namespace System.Security.Permissions { using System; -#if FEATURE_CAS_POLICY - using SecurityElement = System.Security.SecurityElement; -#endif // FEATURE_CAS_POLICY using SiteString = System.Security.Util.SiteString; using System.Text; using System.Collections; @@ -31,55 +28,6 @@ namespace System.Security.Permissions [OptionalField(VersionAdded = 2)] private SiteString[] m_sites; -#if FEATURE_REMOTING - // This field will be populated only for non X-AD scenarios where we create a XML-ised string of the Permission - [OptionalField(VersionAdded = 2)] - private String m_serializedPermission; - - // This field is legacy info from v1.x and is never used in v2.0 and beyond: purely for serialization purposes - private SiteString m_site; - - [OnDeserialized] - private void OnDeserialized(StreamingContext ctx) - { - // v2.0 and beyond XML case - if (m_serializedPermission != null) - { - FromXml(SecurityElement.FromString(m_serializedPermission)); - m_serializedPermission = null; - } - else if (m_site != null) //v1.x case where we read the m_site value - { - m_unrestricted = false; - m_sites = new SiteString[1]; - m_sites[0] = m_site; - m_site = null; - } - } - - [OnSerializing] - private void OnSerializing(StreamingContext ctx) - { - - if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0) - { - m_serializedPermission = ToXml().ToString(); //for the v2 and beyond case - if (m_sites != null && m_sites.Length == 1) // for the v1.x case - m_site = m_sites[0]; - - } - } - [OnSerialized] - private void OnSerialized(StreamingContext ctx) - { - if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0) - { - m_serializedPermission = null; - m_site = null; - } - } -#endif // FEATURE_REMOTING - //------------------------------------------------------ // // PUBLIC CONSTRUCTORS @@ -150,8 +98,6 @@ namespace System.Security.Permissions // IPERMISSION IMPLEMENTATION // //------------------------------------------------------ - - public override IPermission Copy() { SiteIdentityPermission perm = new SiteIdentityPermission( PermissionState.None ); @@ -291,60 +237,6 @@ namespace System.Security.Permissions return result; } -#if FEATURE_CAS_POLICY - public override void FromXml(SecurityElement esd) - { - m_unrestricted = false; - m_sites = null; - CodeAccessPermission.ValidateElement( esd, this ); - String unr = esd.Attribute( "Unrestricted" ); - if(unr != null && String.Compare(unr, "true", StringComparison.OrdinalIgnoreCase) == 0) - { - m_unrestricted = true; - return; - } - String elem = esd.Attribute( "Site" ); - List al = new List(); - if(elem != null) - al.Add(new SiteString( elem )); - ArrayList alChildren = esd.Children; - if(alChildren != null) - { - foreach(SecurityElement child in alChildren) - { - elem = child.Attribute( "Site" ); - if(elem != null) - al.Add(new SiteString( elem )); - } - } - if(al.Count != 0) - m_sites = al.ToArray(); - } - - public override SecurityElement ToXml() - { - SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.SiteIdentityPermission" ); - if (m_unrestricted) - esd.AddAttribute( "Unrestricted", "true" ); - else if (m_sites != null) - { - if (m_sites.Length == 1) - esd.AddAttribute( "Site", m_sites[0].ToString() ); - else - { - int n; - for(n = 0; n < m_sites.Length; n++) - { - SecurityElement child = new SecurityElement("Site"); - child.AddAttribute( "Site", m_sites[n].ToString() ); - esd.AddChild(child); - } - } - } - return esd; - } -#endif // FEATURE_CAS_POLICY - /// int IBuiltInPermission.GetTokenIndex() { diff --git a/src/mscorlib/src/System/Security/Permissions/StrongNameIdentityPermission.cs b/src/mscorlib/src/System/Security/Permissions/StrongNameIdentityPermission.cs index 5f5de0e..f09d84d 100644 --- a/src/mscorlib/src/System/Security/Permissions/StrongNameIdentityPermission.cs +++ b/src/mscorlib/src/System/Security/Permissions/StrongNameIdentityPermission.cs @@ -5,9 +5,6 @@ namespace System.Security.Permissions { using System; -#if FEATURE_CAS_POLICY - using SecurityElement = System.Security.SecurityElement; -#endif // FEATURE_CAS_POLICY using System.Security.Util; using System.IO; using String = System.String; @@ -135,7 +132,7 @@ namespace System.Security.Permissions public StrongNameIdentityPermission( StrongNamePublicKeyBlob blob, String name, Version version ) { if (blob == null) - throw new ArgumentNullException( "blob" ); + throw new ArgumentNullException( nameof(blob) ); if (name != null && name.Equals( "" )) throw new ArgumentException( Environment.GetResourceString( "Argument_EmptyStrongName" ) ); Contract.EndContractBlock(); @@ -156,7 +153,7 @@ namespace System.Security.Permissions set { if (value == null) - throw new ArgumentNullException( "PublicKey" ); + throw new ArgumentNullException( nameof(PublicKey) ); Contract.EndContractBlock(); m_unrestricted = false; if(m_strongNames != null && m_strongNames.Length == 1) @@ -389,89 +386,6 @@ namespace System.Security.Permissions return result; } -#if FEATURE_CAS_POLICY - public override void FromXml(SecurityElement e) - { - m_unrestricted = false; - m_strongNames = null; - CodeAccessPermission.ValidateElement( e, this ); - String unr = e.Attribute( "Unrestricted" ); - if(unr != null && String.Compare(unr, "true", StringComparison.OrdinalIgnoreCase) == 0) - { - m_unrestricted = true; - return; - } - String elBlob = e.Attribute("PublicKeyBlob"); - String elName = e.Attribute("Name"); - String elVersion = e.Attribute("AssemblyVersion"); - StrongName2 sn; - List al = new List(); - if(elBlob != null || elName != null || elVersion != null) - { - sn = new StrongName2( - (elBlob == null ? null : new StrongNamePublicKeyBlob(elBlob)), - elName, - (elVersion == null ? null : new Version(elVersion))); - al.Add(sn); - } - ArrayList alChildren = e.Children; - if(alChildren != null) - { - foreach(SecurityElement child in alChildren) - { - elBlob = child.Attribute("PublicKeyBlob"); - elName = child.Attribute("Name"); - elVersion = child.Attribute("AssemblyVersion"); - if(elBlob != null || elName != null || elVersion != null) - { - sn = new StrongName2( - (elBlob == null ? null : new StrongNamePublicKeyBlob(elBlob)), - elName, - (elVersion == null ? null : new Version(elVersion))); - al.Add(sn); - } - } - } - if(al.Count != 0) - m_strongNames = al.ToArray(); - } - - public override SecurityElement ToXml() - { - SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.StrongNameIdentityPermission" ); - if (m_unrestricted) - esd.AddAttribute( "Unrestricted", "true" ); - else if (m_strongNames != null) - { - if (m_strongNames.Length == 1) - { - if (m_strongNames[0].m_publicKeyBlob != null) - esd.AddAttribute("PublicKeyBlob", Hex.EncodeHexString(m_strongNames[0].m_publicKeyBlob.PublicKey)); - if (m_strongNames[0].m_name != null) - esd.AddAttribute("Name", m_strongNames[0].m_name); - if ((Object)m_strongNames[0].m_version != null) - esd.AddAttribute("AssemblyVersion", m_strongNames[0].m_version.ToString()); - } - else - { - int n; - for(n = 0; n < m_strongNames.Length; n++) - { - SecurityElement child = new SecurityElement("StrongName"); - if (m_strongNames[n].m_publicKeyBlob != null) - child.AddAttribute("PublicKeyBlob", Hex.EncodeHexString(m_strongNames[n].m_publicKeyBlob.PublicKey)); - if (m_strongNames[n].m_name != null) - child.AddAttribute("Name", m_strongNames[n].m_name); - if ((Object)m_strongNames[n].m_version != null) - child.AddAttribute("AssemblyVersion", m_strongNames[n].m_version.ToString()); - esd.AddChild(child); - } - } - } - return esd; - } -#endif // FEATURE_CAS_POLICY - /// int IBuiltInPermission.GetTokenIndex() { diff --git a/src/mscorlib/src/System/Security/Permissions/StrongNamePublicKeyBlob.cs b/src/mscorlib/src/System/Security/Permissions/StrongNamePublicKeyBlob.cs index e0aacaf..823eaba 100644 --- a/src/mscorlib/src/System/Security/Permissions/StrongNamePublicKeyBlob.cs +++ b/src/mscorlib/src/System/Security/Permissions/StrongNamePublicKeyBlob.cs @@ -20,7 +20,7 @@ namespace System.Security.Permissions public StrongNamePublicKeyBlob( byte[] publicKey ) { if (publicKey == null) - throw new ArgumentNullException( "PublicKey" ); + throw new ArgumentNullException( nameof(PublicKey) ); Contract.EndContractBlock(); this.PublicKey = new byte[publicKey.Length]; diff --git a/src/mscorlib/src/System/Security/Permissions/UIPermission.cs b/src/mscorlib/src/System/Security/Permissions/UIPermission.cs index bb122b7..4abe801 100644 --- a/src/mscorlib/src/System/Security/Permissions/UIPermission.cs +++ b/src/mscorlib/src/System/Security/Permissions/UIPermission.cs @@ -309,50 +309,6 @@ namespace System.Security.Permissions { return new UIPermission(this.m_windowFlag, this.m_clipboardFlag); } - -#if FEATURE_CAS_POLICY - public override SecurityElement ToXml() - { - SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.UIPermission" ); - if (!IsUnrestricted()) - { - if (m_windowFlag != UIPermissionWindow.NoWindows) - { - esd.AddAttribute( "Window", Enum.GetName( typeof( UIPermissionWindow ), m_windowFlag ) ); - } - if (m_clipboardFlag != UIPermissionClipboard.NoClipboard) - { - esd.AddAttribute( "Clipboard", Enum.GetName( typeof( UIPermissionClipboard ), m_clipboardFlag ) ); - } - } - else - { - esd.AddAttribute( "Unrestricted", "true" ); - } - return esd; - } - - public override void FromXml(SecurityElement esd) - { - CodeAccessPermission.ValidateElement( esd, this ); - if (XMLUtil.IsUnrestricted( esd )) - { - SetUnrestricted( true ); - return; - } - - m_windowFlag = UIPermissionWindow.NoWindows; - m_clipboardFlag = UIPermissionClipboard.NoClipboard; - - String window = esd.Attribute( "Window" ); - if (window != null) - m_windowFlag = (UIPermissionWindow)Enum.Parse( typeof( UIPermissionWindow ), window ); - - String clipboard = esd.Attribute( "Clipboard" ); - if (clipboard != null) - m_clipboardFlag = (UIPermissionClipboard)Enum.Parse( typeof( UIPermissionClipboard ), clipboard ); - } -#endif // FEATURE_CAS_POLICY /// int IBuiltInPermission.GetTokenIndex() diff --git a/src/mscorlib/src/System/Security/Permissions/URLIdentityPermission.cs b/src/mscorlib/src/System/Security/Permissions/URLIdentityPermission.cs index e62449c..0883bf8 100644 --- a/src/mscorlib/src/System/Security/Permissions/URLIdentityPermission.cs +++ b/src/mscorlib/src/System/Security/Permissions/URLIdentityPermission.cs @@ -5,9 +5,6 @@ namespace System.Security.Permissions { using System; -#if FEATURE_CAS_POLICY - using SecurityElement = System.Security.SecurityElement; -#endif // FEATURE_CAS_POLICY using System.Security.Util; using System.IO; using System.Text; @@ -31,58 +28,8 @@ namespace System.Security.Permissions [OptionalField(VersionAdded = 2)] private bool m_unrestricted; - [OptionalField(VersionAdded = 2)] - private URLString[] m_urls; - -#if FEATURE_REMOTING - // This field will be populated only for non X-AD scenarios where we create a XML-ised string of the Permission [OptionalField(VersionAdded = 2)] - private String m_serializedPermission; - - // This field is legacy info from v1.x and is never used in v2.0 and beyond: purely for serialization purposes - private URLString m_url; - - [OnDeserialized] - private void OnDeserialized(StreamingContext ctx) - { - // v2.0 and beyond XML case - if (m_serializedPermission != null) - { - FromXml(SecurityElement.FromString(m_serializedPermission)); - m_serializedPermission = null; - } - else if (m_url != null) //v1.x case where we read the m_site value - { - m_unrestricted = false; - m_urls = new URLString[1]; - m_urls[0] = m_url; - m_url = null; - } - - } - - [OnSerializing] - private void OnSerializing(StreamingContext ctx) - { - - if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0) - { - m_serializedPermission = ToXml().ToString(); //for the v2 and beyond case - if (m_urls != null && m_urls.Length == 1) // for the v1.x case - m_url = m_urls[0]; - - } - } - [OnSerialized] - private void OnSerialized(StreamingContext ctx) - { - if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0) - { - m_serializedPermission = null; - m_url = null; - } - } -#endif // FEATURE_REMOTING + private URLString[] m_urls; //------------------------------------------------------ // @@ -110,7 +57,7 @@ namespace System.Security.Permissions public UrlIdentityPermission( String site ) { if (site == null) - throw new ArgumentNullException( "site" ); + throw new ArgumentNullException( nameof(site) ); Contract.EndContractBlock(); Url = site; } @@ -323,60 +270,6 @@ namespace System.Security.Permissions return result; } -#if FEATURE_CAS_POLICY - public override void FromXml(SecurityElement esd) - { - m_unrestricted = false; - m_urls = null; - CodeAccessPermission.ValidateElement( esd, this ); - String unr = esd.Attribute( "Unrestricted" ); - if(unr != null && String.Compare(unr, "true", StringComparison.OrdinalIgnoreCase) == 0) - { - m_unrestricted = true; - return; - } - String elem = esd.Attribute( "Url" ); - List al = new List(); - if(elem != null) - al.Add(new URLString( elem, true )); - ArrayList alChildren = esd.Children; - if(alChildren != null) - { - foreach(SecurityElement child in alChildren) - { - elem = child.Attribute( "Url" ); - if(elem != null) - al.Add(new URLString( elem, true )); - } - } - if(al.Count != 0) - m_urls = al.ToArray(); - } - - public override SecurityElement ToXml() - { - SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.UrlIdentityPermission" ); - if (m_unrestricted) - esd.AddAttribute( "Unrestricted", "true" ); - else if (m_urls != null) - { - if (m_urls.Length == 1) - esd.AddAttribute( "Url", m_urls[0].ToString() ); - else - { - int n; - for(n = 0; n < m_urls.Length; n++) - { - SecurityElement child = new SecurityElement("Url"); - child.AddAttribute( "Url", m_urls[n].ToString() ); - esd.AddChild(child); - } - } - } - return esd; - } -#endif // FEATURE_CAS_POLICY - /// int IBuiltInPermission.GetTokenIndex() { diff --git a/src/mscorlib/src/System/Security/Permissions/ZoneIdentityPermission.cs b/src/mscorlib/src/System/Security/Permissions/ZoneIdentityPermission.cs index 803bd34..9023c7e 100644 --- a/src/mscorlib/src/System/Security/Permissions/ZoneIdentityPermission.cs +++ b/src/mscorlib/src/System/Security/Permissions/ZoneIdentityPermission.cs @@ -8,9 +8,6 @@ namespace System.Security.Permissions { using System; -#if FEATURE_CAS_POLICY - using SecurityElement = System.Security.SecurityElement; -#endif // FEATURE_CAS_POLICY using System.Globalization; using System.Runtime.Serialization; using System.Collections; @@ -42,57 +39,6 @@ namespace System.Security.Permissions [OptionalField(VersionAdded = 2)] private uint m_zones; -#if FEATURE_REMOTING - // This field will be populated only for non X-AD scenarios where we create a XML-ised string of the Permission - [OptionalField(VersionAdded = 2)] - private String m_serializedPermission; - - // This field is legacy info from v1.x and is never used in v2.0 and beyond: purely for serialization purposes - private SecurityZone m_zone = SecurityZone.NoZone; - - [OnDeserialized] - private void OnDeserialized(StreamingContext ctx) - { - if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0) - { - // v2.0 and beyond XML case - if (m_serializedPermission != null) - { - FromXml(SecurityElement.FromString(m_serializedPermission)); - m_serializedPermission = null; - } - else //v1.x case where we read the m_zone value - { - SecurityZone = m_zone; - m_zone = SecurityZone.NoZone; - } - } - - - } - - [OnSerializing] - private void OnSerializing(StreamingContext ctx) - { - - if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0) - { - m_serializedPermission = ToXml().ToString(); //for the v2 and beyond case - m_zone = SecurityZone; - - } - } - [OnSerialized] - private void OnSerialized(StreamingContext ctx) - { - if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0) - { - m_serializedPermission = null; - m_zone = SecurityZone.NoZone; - } - } -#endif // FEATURE_REMOTING - //------------------------------------------------------ // // PUBLIC CONSTRUCTORS @@ -247,53 +193,6 @@ namespace System.Security.Permissions return new ZoneIdentityPermission(this.m_zones | that.m_zones); } -#if FEATURE_CAS_POLICY - public override SecurityElement ToXml() - { - SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.ZoneIdentityPermission" ); - if (SecurityZone != SecurityZone.NoZone) - { - esd.AddAttribute( "Zone", Enum.GetName( typeof( SecurityZone ), this.SecurityZone ) ); - } - else - { - int nEnum = 0; - uint nFlag; - for(nFlag = 1; nFlag < AllZones; nFlag <<= 1) - { - if((m_zones & nFlag) != 0) - { - SecurityElement child = new SecurityElement("Zone"); - child.AddAttribute( "Zone", Enum.GetName( typeof( SecurityZone ), (SecurityZone)nEnum ) ); - esd.AddChild(child); - } - nEnum++; - } - } - return esd; - } - - public override void FromXml(SecurityElement esd) - { - m_zones = 0; - CodeAccessPermission.ValidateElement( esd, this ); - String eZone = esd.Attribute( "Zone" ); - if (eZone != null) - SecurityZone = (SecurityZone)Enum.Parse( typeof( SecurityZone ), eZone ); - if(esd.Children != null) - { - foreach(SecurityElement child in esd.Children) - { - eZone = child.Attribute( "Zone" ); - int enm = (int)Enum.Parse( typeof( SecurityZone ), eZone ); - if(enm == (int)SecurityZone.NoZone) - continue; - m_zones |= ((uint)1 << enm); - } - } - } -#endif // FEATURE_CAS_POLICY - /// int IBuiltInPermission.GetTokenIndex() { diff --git a/src/mscorlib/src/System/Security/Permissions/keycontainerpermission.cs b/src/mscorlib/src/System/Security/Permissions/keycontainerpermission.cs index 9691c03..d4f1c27 100644 --- a/src/mscorlib/src/System/Security/Permissions/keycontainerpermission.cs +++ b/src/mscorlib/src/System/Security/Permissions/keycontainerpermission.cs @@ -11,6 +11,7 @@ namespace System.Security.Permissions { #endif using System.Security.Util; using System.Globalization; + using System.Diagnostics; using System.Diagnostics.Contracts; [Serializable] @@ -88,7 +89,7 @@ namespace System.Security.Permissions { m_keyStore = "*"; } else { if (value != "User" && value != "Machine" && value != "*") - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidKeyStore", value), "value"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidKeyStore", value), nameof(value)); m_keyStore = value; } } @@ -232,7 +233,7 @@ namespace System.Security.Permissions { if (index < 0) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumNotStarted")); if (index >= Count) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.EndContractBlock(); return (KeyContainerPermissionAccessEntry)m_list[index]; @@ -247,7 +248,7 @@ namespace System.Security.Permissions { public int Add (KeyContainerPermissionAccessEntry accessEntry) { if (accessEntry == null) - throw new ArgumentNullException("accessEntry"); + throw new ArgumentNullException(nameof(accessEntry)); Contract.EndContractBlock(); int index = m_list.IndexOf(accessEntry); @@ -275,7 +276,7 @@ namespace System.Security.Permissions { public void Remove (KeyContainerPermissionAccessEntry accessEntry) { if (accessEntry == null) - throw new ArgumentNullException("accessEntry"); + throw new ArgumentNullException(nameof(accessEntry)); Contract.EndContractBlock(); m_list.Remove(accessEntry); } @@ -292,11 +293,11 @@ namespace System.Security.Permissions { /// void ICollection.CopyTo (Array array, int index) { if (array == null) - throw new ArgumentNullException("array"); + throw new ArgumentNullException(nameof(array)); if (array.Rank != 1) throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported")); if (index < 0 || index >= array.Length) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); if (index + this.Count > array.Length) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); Contract.EndContractBlock(); @@ -385,7 +386,7 @@ namespace System.Security.Permissions { public KeyContainerPermission (KeyContainerPermissionFlags flags, KeyContainerPermissionAccessEntry[] accessList) { if (accessList == null) - throw new ArgumentNullException("accessList"); + throw new ArgumentNullException(nameof(accessList)); Contract.EndContractBlock(); VerifyFlags(flags); @@ -525,61 +526,6 @@ namespace System.Security.Permissions { return cp; } -#if FEATURE_CAS_POLICY - public override SecurityElement ToXml () { - SecurityElement securityElement = CodeAccessPermission.CreatePermissionElement(this, "System.Security.Permissions.KeyContainerPermission"); - if (!IsUnrestricted()) { - securityElement.AddAttribute("Flags", m_flags.ToString()); - if (AccessEntries.Count > 0) { - SecurityElement al = new SecurityElement("AccessList"); - foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) { - SecurityElement entryElem = new SecurityElement("AccessEntry"); - entryElem.AddAttribute("KeyStore", accessEntry.KeyStore); - entryElem.AddAttribute("ProviderName", accessEntry.ProviderName); - entryElem.AddAttribute("ProviderType", accessEntry.ProviderType.ToString(null, null)); - entryElem.AddAttribute("KeyContainerName", accessEntry.KeyContainerName); - entryElem.AddAttribute("KeySpec", accessEntry.KeySpec.ToString(null, null)); - entryElem.AddAttribute("Flags", accessEntry.Flags.ToString()); - al.AddChild(entryElem); - } - securityElement.AddChild(al); - } - } else - securityElement.AddAttribute("Unrestricted", "true"); - - return securityElement; - } - - public override void FromXml (SecurityElement securityElement) { - CodeAccessPermission.ValidateElement(securityElement, this); - if (XMLUtil.IsUnrestricted(securityElement)) { - m_flags = KeyContainerPermissionFlags.AllFlags; - m_accessEntries = new KeyContainerPermissionAccessEntryCollection(m_flags); - return; - } - - m_flags = KeyContainerPermissionFlags.NoFlags; - string strFlags = securityElement.Attribute("Flags"); - if (strFlags != null) { - KeyContainerPermissionFlags flags = (KeyContainerPermissionFlags) Enum.Parse(typeof(KeyContainerPermissionFlags), strFlags); - VerifyFlags(flags); - m_flags = flags; - } - m_accessEntries = new KeyContainerPermissionAccessEntryCollection(m_flags); - - if (securityElement.InternalChildren != null && securityElement.InternalChildren.Count != 0) { - IEnumerator enumerator = securityElement.Children.GetEnumerator(); - while (enumerator.MoveNext()) { - SecurityElement current = (SecurityElement) enumerator.Current; - if (current != null) { - if (String.Equals(current.Tag, "AccessList")) - AddAccessEntries(current); - } - } - } - } -#endif // FEATURE_CAS_POLICY - /// int IBuiltInPermission.GetTokenIndex () { return KeyContainerPermission.GetTokenIndex(); @@ -597,7 +543,7 @@ namespace System.Security.Permissions { if (current != null) { if (String.Equals(current.Tag, "AccessEntry")) { int iMax = current.m_lAttributes.Count; - Contract.Assert(iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly"); + Debug.Assert(iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly"); string keyStore = null; string providerName = null; int providerType = -1; diff --git a/src/mscorlib/src/System/Security/Policy/ApplicationTrust.cs b/src/mscorlib/src/System/Security/Policy/ApplicationTrust.cs index 57b216e..3d4e35a 100644 --- a/src/mscorlib/src/System/Security/Policy/ApplicationTrust.cs +++ b/src/mscorlib/src/System/Security/Policy/ApplicationTrust.cs @@ -2,20 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -// // // This class encapsulates security decisions about an application. // -namespace System.Security.Policy { +namespace System.Security.Policy +{ using System.Collections; using System.Collections.Generic; -#if FEATURE_CLICKONCE - using System.Deployment.Internal.Isolation; - using System.Deployment.Internal.Isolation.Manifest; -#endif using System.Globalization; using System.IO; using System.Runtime.InteropServices; @@ -40,14 +34,6 @@ namespace System.Security.Policy { [Serializable] public sealed class ApplicationTrust : EvidenceBase, ISecurityEncodable { -#if FEATURE_CLICKONCE - private ApplicationIdentity m_appId; - private bool m_appTrustedToRun; - private bool m_persist; - - private object m_extraInfo; - private SecurityElement m_elExtraInfo; -#endif private PolicyStatement m_psDefaultGrant; private IList m_fullTrustAssemblies; @@ -65,11 +51,6 @@ namespace System.Security.Policy { [NonSerialized] private int m_grantSetSpecialFlags; -#if FEATURE_CLICKONCE - public ApplicationTrust (ApplicationIdentity applicationIdentity) : this () { - ApplicationIdentity = applicationIdentity; - } -#endif public ApplicationTrust () : this (new PermissionSet(PermissionState.None)) { } @@ -83,7 +64,7 @@ namespace System.Security.Policy { public ApplicationTrust(PermissionSet defaultGrantSet, IEnumerable fullTrustAssemblies) { if (fullTrustAssemblies == null) { - throw new ArgumentNullException("fullTrustAssemblies"); + throw new ArgumentNullException(nameof(fullTrustAssemblies)); } InitDefaultGrantSet(defaultGrantSet); @@ -91,7 +72,7 @@ namespace System.Security.Policy { List fullTrustList = new List(); foreach (StrongName strongName in fullTrustAssemblies) { if (strongName == null) { - throw new ArgumentException(Environment.GetResourceString("Argument_NullFullTrustAssembly"), "fullTrustAssemblies"); + throw new ArgumentException(Environment.GetResourceString("Argument_NullFullTrustAssembly"), nameof(fullTrustAssemblies)); } fullTrustList.Add(new StrongName(strongName.PublicKey, strongName.Name, strongName.Version)); @@ -104,7 +85,7 @@ namespace System.Security.Policy { // IEnumerable virtual dispatches on startup when there are no fullTrustAssemblies (CoreCLR) private void InitDefaultGrantSet(PermissionSet defaultGrantSet) { if (defaultGrantSet == null) { - throw new ArgumentNullException("defaultGrantSet"); + throw new ArgumentNullException(nameof(defaultGrantSet)); } // Creating a PolicyStatement copies the incoming permission set, so we don't have to worry @@ -113,19 +94,6 @@ namespace System.Security.Policy { DefaultGrantSet = new PolicyStatement(defaultGrantSet); } -#if FEATURE_CLICKONCE - public ApplicationIdentity ApplicationIdentity { - get { - return m_appId; - } - set { - if (value == null) - throw new ArgumentNullException("value", Environment.GetResourceString("Argument_InvalidAppId")); - Contract.EndContractBlock(); - m_appId = value; - } - } -#endif public PolicyStatement DefaultGrantSet { get { if (m_psDefaultGrant == null) @@ -149,541 +117,10 @@ namespace System.Security.Policy { return m_fullTrustAssemblies; } } -#if FEATURE_CLICKONCE - public bool IsApplicationTrustedToRun { - get { - return m_appTrustedToRun; - } - set { - m_appTrustedToRun = value; - } - } - - public bool Persist { - get { - return m_persist; - } - set { - m_persist = value; - } - } - - public object ExtraInfo { - get { - if (m_elExtraInfo != null) { - m_extraInfo = ObjectFromXml(m_elExtraInfo); - m_elExtraInfo = null; - } - return m_extraInfo; - } - set { - m_elExtraInfo = null; - m_extraInfo = value; - } - } -#endif //FEATURE_CLICKONCE - -#if FEATURE_CAS_POLICY - public SecurityElement ToXml () { - SecurityElement elRoot = new SecurityElement("ApplicationTrust"); - elRoot.AddAttribute("version", "1"); - -#if FEATURE_CLICKONCE - if (m_appId != null) { - elRoot.AddAttribute("FullName", SecurityElement.Escape(m_appId.FullName)); - } - if (m_appTrustedToRun) { - elRoot.AddAttribute("TrustedToRun", "true"); - } - if (m_persist) { - elRoot.AddAttribute("Persist", "true"); - } -#endif // FEATURE_CLICKONCE - - if (m_psDefaultGrant != null) { - SecurityElement elDefaultGrant = new SecurityElement("DefaultGrant"); - elDefaultGrant.AddChild(m_psDefaultGrant.ToXml()); - elRoot.AddChild(elDefaultGrant); - } - if (m_fullTrustAssemblies.Count > 0) { - SecurityElement elFullTrustAssemblies = new SecurityElement("FullTrustAssemblies"); - foreach (StrongName fullTrustAssembly in m_fullTrustAssemblies) { - elFullTrustAssemblies.AddChild(fullTrustAssembly.ToXml()); - } - elRoot.AddChild(elFullTrustAssemblies); - } - -#if FEATURE_CLICKONCE - if (ExtraInfo != null) { - elRoot.AddChild(ObjectToXml("ExtraInfo", ExtraInfo)); - } -#endif // FEATURE_CLICKONCE - return elRoot; - } - - public void FromXml (SecurityElement element) { - if (element == null) - throw new ArgumentNullException("element"); - if (String.Compare(element.Tag, "ApplicationTrust", StringComparison.Ordinal) != 0) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidXML")); - -#if FEATURE_CLICKONCE - m_appTrustedToRun = false; - string isAppTrustedToRun = element.Attribute("TrustedToRun"); - if (isAppTrustedToRun != null && String.Compare(isAppTrustedToRun, "true", StringComparison.Ordinal) == 0) { - m_appTrustedToRun = true; - } - - m_persist = false; - string persist = element.Attribute("Persist"); - if (persist != null && String.Compare(persist, "true", StringComparison.Ordinal) == 0) { - m_persist = true; - } - - m_appId = null; - string fullName = element.Attribute("FullName"); - if (fullName != null && fullName.Length > 0) { - m_appId = new ApplicationIdentity(fullName); - } -#endif // FEATURE_CLICKONCE - - m_psDefaultGrant = null; - m_grantSetSpecialFlags = 0; - SecurityElement elDefaultGrant = element.SearchForChildByTag("DefaultGrant"); - if (elDefaultGrant != null) { - SecurityElement elDefaultGrantPS = elDefaultGrant.SearchForChildByTag("PolicyStatement"); - if (elDefaultGrantPS != null) { - PolicyStatement ps = new PolicyStatement(null); - ps.FromXml(elDefaultGrantPS); - m_psDefaultGrant = ps; - m_grantSetSpecialFlags = SecurityManager.GetSpecialFlags(ps.PermissionSet, null); - } - } - - List fullTrustAssemblies = new List(); - SecurityElement elFullTrustAssemblies = element.SearchForChildByTag("FullTrustAssemblies"); - if (elFullTrustAssemblies != null && elFullTrustAssemblies.InternalChildren != null) { - IEnumerator enumerator = elFullTrustAssemblies.Children.GetEnumerator(); - while (enumerator.MoveNext()) { - StrongName fullTrustAssembly = new StrongName(); - fullTrustAssembly.FromXml(enumerator.Current as SecurityElement); - fullTrustAssemblies.Add(fullTrustAssembly); - } - } - - m_fullTrustAssemblies = fullTrustAssemblies.AsReadOnly(); - -#if FEATURE_CLICKONCE - m_elExtraInfo = element.SearchForChildByTag("ExtraInfo"); -#endif // FEATURE_CLICKONCE - } - -#if FEATURE_CLICKONCE - private static SecurityElement ObjectToXml (string tag, Object obj) { - BCLDebug.Assert(obj != null, "You need to pass in an object"); - - ISecurityEncodable encodableObj = obj as ISecurityEncodable; - - SecurityElement elObject; - if (encodableObj != null) { - elObject = encodableObj.ToXml(); - if (!elObject.Tag.Equals(tag)) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidXML")); - } - MemoryStream stream = new MemoryStream(); - BinaryFormatter formatter = new BinaryFormatter(); - formatter.Serialize(stream, obj); - byte[] array = stream.ToArray(); - - elObject = new SecurityElement(tag); - elObject.AddAttribute("Data", Hex.EncodeHexString(array)); - return elObject; - } - - private static Object ObjectFromXml (SecurityElement elObject) { - BCLDebug.Assert(elObject != null, "You need to pass in a security element"); - - if (elObject.Attribute("class") != null) { - ISecurityEncodable encodableObj = XMLUtil.CreateCodeGroup(elObject) as ISecurityEncodable; - if (encodableObj != null) { - encodableObj.FromXml(elObject); - return encodableObj; - } - } - - string objectData = elObject.Attribute("Data"); - MemoryStream stream = new MemoryStream(Hex.DecodeHexString(objectData)); - BinaryFormatter formatter = new BinaryFormatter(); - return formatter.Deserialize(stream); - } -#endif // FEATURE_CLICKONCE -#endif // FEATURE_CAS_POLICY - -#pragma warning disable 618 - [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)] -#pragma warning restore 618 - [SecuritySafeCritical] public override EvidenceBase Clone() { return base.Clone(); } } - -#if FEATURE_CLICKONCE - [System.Security.SecurityCritical] // auto-generated_required - [System.Runtime.InteropServices.ComVisible(true)] - public sealed class ApplicationTrustCollection : ICollection { - private const string ApplicationTrustProperty = "ApplicationTrust"; - private const string InstallerIdentifier = "{60051b8f-4f12-400a-8e50-dd05ebd438d1}"; - private static Guid ClrPropertySet = new Guid("c989bb7a-8385-4715-98cf-a741a8edb823"); - - // The CLR specific constant install reference. - private static object s_installReference = null; - private static StoreApplicationReference InstallReference { - get { - if (s_installReference == null) { - Interlocked.CompareExchange(ref s_installReference, - new StoreApplicationReference( - IsolationInterop.GUID_SXS_INSTALL_REFERENCE_SCHEME_OPAQUESTRING, - InstallerIdentifier, - null), - null); - } - return (StoreApplicationReference) s_installReference; - } - } - - private object m_appTrusts = null; - private ArrayList AppTrusts { - [System.Security.SecurityCritical] // auto-generated - get { - if (m_appTrusts == null) { - ArrayList appTrusts = new ArrayList(); - if (m_storeBounded) { - RefreshStorePointer(); - // enumerate the user store and populate the collection - StoreDeploymentMetadataEnumeration deplEnum = m_pStore.EnumInstallerDeployments(IsolationInterop.GUID_SXS_INSTALL_REFERENCE_SCHEME_OPAQUESTRING, InstallerIdentifier, ApplicationTrustProperty, null); - foreach (IDefinitionAppId defAppId in deplEnum) { - StoreDeploymentMetadataPropertyEnumeration metadataEnum = m_pStore.EnumInstallerDeploymentProperties(IsolationInterop.GUID_SXS_INSTALL_REFERENCE_SCHEME_OPAQUESTRING, InstallerIdentifier, ApplicationTrustProperty, defAppId); - foreach (StoreOperationMetadataProperty appTrustProperty in metadataEnum) { - string appTrustXml = appTrustProperty.Value; - if (appTrustXml != null && appTrustXml.Length > 0) { - SecurityElement seTrust = SecurityElement.FromString(appTrustXml); - ApplicationTrust appTrust = new ApplicationTrust(); - appTrust.FromXml(seTrust); - appTrusts.Add(appTrust); - } - } - } - } - Interlocked.CompareExchange(ref m_appTrusts, appTrusts, null); - } - return m_appTrusts as ArrayList; - } - } - - private bool m_storeBounded = false; - private Store m_pStore = null; // Component store interface pointer. - - // Only internal constructors are exposed. - [System.Security.SecurityCritical] // auto-generated - internal ApplicationTrustCollection () : this(false) {} - internal ApplicationTrustCollection (bool storeBounded) { - m_storeBounded = storeBounded; - } - - [System.Security.SecurityCritical] // auto-generated - private void RefreshStorePointer () { - // Refresh store pointer. - if (m_pStore != null) - Marshal.ReleaseComObject(m_pStore.InternalStore); - m_pStore = IsolationInterop.GetUserStore(); - } - - public int Count - { - [System.Security.SecuritySafeCritical] // overrides public transparent member - get { - return AppTrusts.Count; - } - } - - public ApplicationTrust this[int index] { - [System.Security.SecurityCritical] // auto-generated - get { - return AppTrusts[index] as ApplicationTrust; - } - } - - public ApplicationTrust this[string appFullName] { - [System.Security.SecurityCritical] // auto-generated - get { - ApplicationIdentity identity = new ApplicationIdentity(appFullName); - ApplicationTrustCollection appTrusts = Find(identity, ApplicationVersionMatch.MatchExactVersion); - if (appTrusts.Count > 0) - return appTrusts[0]; - return null; - } - } - - [System.Security.SecurityCritical] // auto-generated - private void CommitApplicationTrust(ApplicationIdentity applicationIdentity, string trustXml) { - StoreOperationMetadataProperty[] properties = new StoreOperationMetadataProperty[] { - new StoreOperationMetadataProperty(ClrPropertySet, ApplicationTrustProperty, trustXml) - }; - - IEnumDefinitionIdentity idenum = applicationIdentity.Identity.EnumAppPath(); - IDefinitionIdentity[] asbId = new IDefinitionIdentity[1]; - IDefinitionIdentity deplId = null; - if (idenum.Next(1, asbId) == 1) - deplId = asbId[0]; - - IDefinitionAppId defAppId = IsolationInterop.AppIdAuthority.CreateDefinition(); - defAppId.SetAppPath(1, new IDefinitionIdentity[] {deplId}); - defAppId.put_Codebase(applicationIdentity.CodeBase); - - using (StoreTransaction storeTxn = new StoreTransaction()) { - storeTxn.Add(new StoreOperationSetDeploymentMetadata(defAppId, InstallReference, properties)); - RefreshStorePointer(); - m_pStore.Transact(storeTxn.Operations); - } - - m_appTrusts = null; // reset the app trusts in the collection. - } - - [System.Security.SecurityCritical] // auto-generated - public int Add (ApplicationTrust trust) { - if (trust == null) - throw new ArgumentNullException("trust"); - if (trust.ApplicationIdentity == null) - throw new ArgumentException(Environment.GetResourceString("Argument_ApplicationTrustShouldHaveIdentity")); - Contract.EndContractBlock(); - - // Add the trust decision of the application to the fusion store. - if (m_storeBounded) { - CommitApplicationTrust(trust.ApplicationIdentity, trust.ToXml().ToString()); - return -1; - } else { - return AppTrusts.Add(trust); - } - } - - [System.Security.SecurityCritical] // auto-generated - public void AddRange (ApplicationTrust[] trusts) { - if (trusts == null) - throw new ArgumentNullException("trusts"); - Contract.EndContractBlock(); - - int i=0; - try { - for (; i - [System.Security.SecuritySafeCritical] // overrides public transparent member - IEnumerator IEnumerable.GetEnumerator() - { - return new ApplicationTrustEnumerator(this); - } - - /// - [System.Security.SecuritySafeCritical] // overrides public transparent member - void ICollection.CopyTo(Array array, int index) { - if (array == null) - throw new ArgumentNullException("array"); - if (array.Rank != 1) - throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported")); - if (index < 0 || index >= array.Length) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); - if (array.Length - index < this.Count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - for (int i=0; i < this.Count; i++) { - array.SetValue(this[i], index++); - } - } - - public void CopyTo (ApplicationTrust[] array, int index) { - ((ICollection)this).CopyTo(array, index); - } - - public bool IsSynchronized { - [System.Security.SecuritySafeCritical] // overrides public transparent member - get - { - return false; - } - } - - public object SyncRoot { - [System.Security.SecuritySafeCritical] // overrides public transparent member - get - { - return this; - } - } - } - - [System.Runtime.InteropServices.ComVisible(true)] - public sealed class ApplicationTrustEnumerator : IEnumerator { - [System.Security.SecurityCritical] // auto-generated - private ApplicationTrustCollection m_trusts; - private int m_current; - - private ApplicationTrustEnumerator() {} - [System.Security.SecurityCritical] // auto-generated - internal ApplicationTrustEnumerator(ApplicationTrustCollection trusts) { - m_trusts = trusts; - m_current = -1; - } - - public ApplicationTrust Current { - [System.Security.SecuritySafeCritical] // auto-generated - get { - return m_trusts[m_current]; - } - } - - /// - object IEnumerator.Current { - [System.Security.SecuritySafeCritical] // auto-generated - get { - return (object) m_trusts[m_current]; - } - } - - [System.Security.SecuritySafeCritical] // auto-generated - public bool MoveNext() { - if (m_current == ((int) m_trusts.Count - 1)) - return false; - m_current++; - return true; - } - - public void Reset() { - m_current = -1; - } - } -#endif // FEATURE_CLICKONCE } diff --git a/src/mscorlib/src/System/Security/Policy/Evidence.cs b/src/mscorlib/src/System/Security/Policy/Evidence.cs index 8bf8aa7..22479df 100644 --- a/src/mscorlib/src/System/Security/Policy/Evidence.cs +++ b/src/mscorlib/src/System/Security/Policy/Evidence.cs @@ -2,28 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - namespace System.Security.Policy { - using System; - using System.Collections; - using System.Collections.Generic; - using System.Configuration.Assemblies; - using System.Diagnostics.Contracts; - using System.IO; - using System.Reflection; - using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - using System.Runtime.Remoting; #if FEATURE_SERIALIZATION using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; #endif // FEATURE_SERIALIZATION - using System.Security.Permissions; - using System.Security.Util; - using System.Threading; - using Microsoft.Win32.SafeHandles; /// /// The Evidence class keeps track of information that can be used to make security decisions about @@ -48,1856 +33,6 @@ namespace System.Security.Policy #endif [ComVisible(true)] public sealed class Evidence -#if FEATURE_CAS_POLICY - : ICollection -#endif // FEATURE_CAS_POLICY { -#if !FEATURE_CORECLR && FEATURE_RWLOCK -#if FEATURE_SERIALIZATION - [OptionalField(VersionAdded = 4)] - private Dictionary m_evidence; - - [OptionalField(VersionAdded = 4)] - private bool m_deserializedTargetEvidence; - - // These fields are only used to deserialize v2.0 serialized versions of Evidence. It will be null - // after the seriailzation process is complete, and should not be used. -#pragma warning disable 414 - private volatile ArrayList m_hostList; - private volatile ArrayList m_assemblyList; -#pragma warning restore 414 -#else // !FEATURE_SERIALIZATION - private Dictionary m_evidence; -#endif // FEATURE_SERIALIZATION - - [NonSerialized] - private ReaderWriterLock m_evidenceLock; - - [NonSerialized] - private uint m_version; - - [NonSerialized] - private IRuntimeEvidenceFactory m_target; - - private bool m_locked; - - // If this evidence collection is a clone where we may need to backpatch to the original, this will - // reference the collection it was cloned from. See - // code:System.Security.Policy.Evidence#BackpatchGeneratedEvidence - [NonSerialized] - private WeakReference m_cloneOrigin; - - private static volatile Type[] s_runtimeEvidenceTypes; - - /// - /// Set of actions that we could perform if we detect that we are attempting to add evidence - /// when we already have evidence of that type stored. - /// - private enum DuplicateEvidenceAction - { - Throw, // Throw an exception - Merge, // Create a list of all the evidence objects - SelectNewObject // The newly added object wins - } - -#if FEATURE_CAS_POLICY - public Evidence() - { - m_evidence = new Dictionary(); - m_evidenceLock = new ReaderWriterLock(); - } -#endif // FEATURE_CAS_POLICY - - /// - /// Create a deep copy of an evidence object - /// - public Evidence(Evidence evidence) - { - m_evidence = new Dictionary(); - - if (evidence != null) - { - using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(evidence, EvidenceLockHolder.LockType.Reader)) - { - foreach (KeyValuePair evidenceType in evidence.m_evidence) - { - EvidenceTypeDescriptor cloneDescriptor = evidenceType.Value; - if (cloneDescriptor != null) - { - cloneDescriptor = cloneDescriptor.Clone(); - } - - m_evidence[evidenceType.Key] = cloneDescriptor; - } - - m_target = evidence.m_target; - m_locked = evidence.m_locked; -#if FEATURE_SERIALIZATION - m_deserializedTargetEvidence = evidence.m_deserializedTargetEvidence; -#endif // FEATURE_SERIALIZATION - - // see code:System.Security.Policy.Evidence#BackpatchGeneratedEvidence - if (evidence.Target != null) - { - m_cloneOrigin = new WeakReference(evidence); - } - } - } - - // see code:System.Security.Policy.Evidence#EvidenceLock - m_evidenceLock = new ReaderWriterLock(); - } - - [Obsolete("This constructor is obsolete. Please use the constructor which takes arrays of EvidenceBase instead.")] - public Evidence(object[] hostEvidence, object[] assemblyEvidence) - { - m_evidence = new Dictionary(); - - // This is a legacy evidence entry point, so we add through the legacy add APIs in order to get - // proper legacy wrapping and merge behavior. -#pragma warning disable 618 - if (hostEvidence != null) - { - foreach (object hostEvidenceObject in hostEvidence) - { - AddHost(hostEvidenceObject); - } - } - - if (assemblyEvidence != null) - { - foreach (object assemblyEvidenceObject in assemblyEvidence) - { - AddAssembly(assemblyEvidenceObject); - } - } -#pragma warning restore 618 - - // see code:System.Security.Policy.Evidence#EvidenceLock - m_evidenceLock = new ReaderWriterLock(); - } - - public Evidence(EvidenceBase[] hostEvidence, EvidenceBase[] assemblyEvidence) - { - m_evidence = new Dictionary(); - - if (hostEvidence != null) - { - foreach (EvidenceBase hostEvidenceObject in hostEvidence) - { - AddHostEvidence(hostEvidenceObject, GetEvidenceIndexType(hostEvidenceObject), DuplicateEvidenceAction.Throw); - } - } - - if (assemblyEvidence != null) - { - foreach (EvidenceBase assemblyEvidenceObject in assemblyEvidence) - { - AddAssemblyEvidence(assemblyEvidenceObject, GetEvidenceIndexType(assemblyEvidenceObject), DuplicateEvidenceAction.Throw); - } - } - - // see code:System.Security.Policy.Evidence#EvidenceLock - m_evidenceLock = new ReaderWriterLock(); - } - - /// - /// Create an empty evidence collection which will contain evidence for a specific assembly or - /// AppDomain - /// - [SecuritySafeCritical] - internal Evidence(IRuntimeEvidenceFactory target) - { - Contract.Assert(target != null); - - m_evidence = new Dictionary(); - m_target = target; - - // Setup the types of evidence that the CLR can generate for a target as keys in the dictionary - foreach (Type runtimeEvidenceType in RuntimeEvidenceTypes) - { - BCLDebug.Assert(typeof(EvidenceBase).IsAssignableFrom(runtimeEvidenceType), "All runtime evidence types should be EvidenceBases"); - m_evidence[runtimeEvidenceType] = null; - } - - QueryHostForPossibleEvidenceTypes(); - - // see code:System.Security.Policy.Evidence#EvidenceLock - m_evidenceLock = new ReaderWriterLock(); - } - - internal static Type[] RuntimeEvidenceTypes - { - get - { - if (s_runtimeEvidenceTypes == null) - { - Type[] runtimeEvidenceTypes = new Type[] - { -#if FEATURE_CLICKONCE - typeof(System.Runtime.Hosting.ActivationArguments), -#endif // FEATURE_CLICKONCE -#if FEATURE_CAS_POLICY - typeof(ApplicationDirectory), -#endif // FEATURE_CAS_POLICY - typeof(ApplicationTrust), -#if FEATURE_CAS_POLICY - typeof(GacInstalled), - typeof(Hash), - typeof(Publisher), -#endif // FEATURE_CAS_POLICY - typeof(Site), - typeof(StrongName), - typeof(Url), - typeof(Zone) - }; - -#if FEATURE_CAS_POLICY - // We only supply permission request evidence in legacy CAS mode - if (AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { -#pragma warning disable 618 // We need to generate PermissionRequestEvidence in compatibility mode - int l = runtimeEvidenceTypes.Length; - Array.Resize(ref runtimeEvidenceTypes, l+1); - runtimeEvidenceTypes[l] = typeof(PermissionRequestEvidence); -#pragma warning restore 618 - } -#endif // FEATURE_CAS_POLICY - - s_runtimeEvidenceTypes = runtimeEvidenceTypes; - } - - return s_runtimeEvidenceTypes; - } - } - - // - // #EvidenceLock - // - // Evidence synchronization locking wrappers. In the case where the lock has not yet been created, - // we know that we're in the process of constructing the evidence collection and therefore we can - // act as though the evidence is locked. If there is a lock in place, then just delegate back to it. - // - // The nested EvidenceLockHolder and EvidenceUpgradeLockHolder utility classes can be used to wrap - // these methods when acquiring and releasing the evidence lock. - // - - // Millisecond timeout when waiting to acquire the evidence lock - private const int LockTimeout = 5000; - - private bool IsReaderLockHeld - { - get { return m_evidenceLock == null || m_evidenceLock.IsReaderLockHeld; } - } - - private bool IsWriterLockHeld - { - get { return m_evidenceLock == null || m_evidenceLock.IsWriterLockHeld; } - } - - private void AcquireReaderLock() - { - Contract.Assert(m_evidenceLock == null || !IsReaderLockHeld); - - if (m_evidenceLock != null) - { - m_evidenceLock.AcquireReaderLock(LockTimeout); - } - } - - private void AcquireWriterlock() - { - Contract.Assert(m_evidenceLock == null || !IsWriterLockHeld); - - if (m_evidenceLock != null) - { - m_evidenceLock.AcquireWriterLock(LockTimeout); - } - } - - private void DowngradeFromWriterLock(ref LockCookie lockCookie) - { - Contract.Assert(IsWriterLockHeld); - if (m_evidenceLock != null) - { - m_evidenceLock.DowngradeFromWriterLock(ref lockCookie); - } - } - - private LockCookie UpgradeToWriterLock() - { - Contract.Assert(IsReaderLockHeld); - return m_evidenceLock != null ? m_evidenceLock.UpgradeToWriterLock(LockTimeout) : new LockCookie(); - } - - private void ReleaseReaderLock() - { - Contract.Assert(IsReaderLockHeld); - - if (m_evidenceLock != null) - { - m_evidenceLock.ReleaseReaderLock(); - } - } - - private void ReleaseWriterLock() - { - Contract.Assert(IsWriterLockHeld); - - if (m_evidenceLock != null) - { - m_evidenceLock.ReleaseWriterLock(); - } - } - - [Obsolete("This method is obsolete. Please use AddHostEvidence instead.")] - [SecuritySafeCritical] - public void AddHost(object id) - { - if (id == null) - throw new ArgumentNullException("id"); - if (!id.GetType().IsSerializable) - throw new ArgumentException(Environment.GetResourceString("Policy_EvidenceMustBeSerializable"), "id"); - Contract.EndContractBlock(); - - if (m_locked) - { - new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand(); - } - - EvidenceBase evidence = WrapLegacyEvidence(id); - Type evidenceIndex = GetEvidenceIndexType(evidence); - - // Whidbey allowed for multiple types of the same evidence, so if we're being called via the Whidbey - // APIs, then allow the evidences to merge together. - AddHostEvidence(evidence, evidenceIndex, DuplicateEvidenceAction.Merge); - } - - [Obsolete("This method is obsolete. Please use AddAssemblyEvidence instead.")] - public void AddAssembly(object id) - { - if (id == null) - throw new ArgumentNullException("id"); - if (!id.GetType().IsSerializable) - throw new ArgumentException(Environment.GetResourceString("Policy_EvidenceMustBeSerializable"), "id"); - Contract.EndContractBlock(); - - EvidenceBase evidence = WrapLegacyEvidence(id); - Type evidenceIndex = GetEvidenceIndexType(evidence); - - // Whidbey allowed for multiple types of the same evidence, so if we're being called via the Whidbey - // APIs, then allow the evidences to merge together. - AddAssemblyEvidence(evidence, evidenceIndex, DuplicateEvidenceAction.Merge); - } - - /// - /// Add a piece of evidence to the assembly supplied evidence list. This method will disallow adding - /// evidence if there is already evidence of that type in the assembly list. - /// - [ComVisible(false)] - public void AddAssemblyEvidence(T evidence) where T : EvidenceBase - { - if (evidence == null) - throw new ArgumentNullException("evidence"); - Contract.EndContractBlock(); - - // Index the evidence under the type that the Add function was called with, unless we were given - // a plain EvidenceBase or a wrapped legacy evidence. In that case, we need to index under a - // more specific type. - Type evidenceType = typeof(T); - if (typeof(T) == typeof(EvidenceBase) || evidence is ILegacyEvidenceAdapter) - { - evidenceType = GetEvidenceIndexType(evidence); - } - - AddAssemblyEvidence(evidence, evidenceType, DuplicateEvidenceAction.Throw); - } - - private void AddAssemblyEvidence(EvidenceBase evidence, Type evidenceType, DuplicateEvidenceAction duplicateAction) - { - using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Writer)) - { - AddAssemblyEvidenceNoLock(evidence, evidenceType, duplicateAction); - } - } - - private void AddAssemblyEvidenceNoLock(EvidenceBase evidence, Type evidenceType, DuplicateEvidenceAction duplicateAction) - { - Contract.Assert(IsWriterLockHeld); - Contract.Assert(evidence != null); - Contract.Assert(evidenceType != null); - - // We need to make sure that any target supplied evidence is deserialized before adding to the - // Assembly collection in order to preserve the semantics that the evidence objects supplied by - // the target are the original versions and evidence objects added via the APIs are the duplicates. - DeserializeTargetEvidence(); - - EvidenceTypeDescriptor descriptor = GetEvidenceTypeDescriptor(evidenceType, true); - - ++m_version; - if (descriptor.AssemblyEvidence == null) - { - descriptor.AssemblyEvidence = evidence; - } - else - { - descriptor.AssemblyEvidence = HandleDuplicateEvidence(descriptor.AssemblyEvidence, - evidence, - duplicateAction); - } - } - - /// - /// Add a piece of evidence to the host supplied evidence list. This method will disallow adding - /// evidence if there is already evidence of that type in the host list. - /// - [ComVisible(false)] - public void AddHostEvidence(T evidence) where T : EvidenceBase - { - if (evidence == null) - throw new ArgumentNullException("evidence"); - Contract.EndContractBlock(); - - // Index the evidence under the type that the Add function was called with, unless we were given - // a plain EvidenceBase or a wrapped legacy evidence. In that case, we need to index under a - // more specific type. - Type evidenceType = typeof(T); - if (typeof(T) == typeof(EvidenceBase) || evidence is ILegacyEvidenceAdapter) - { - evidenceType = GetEvidenceIndexType(evidence); - } - - AddHostEvidence(evidence, evidenceType, DuplicateEvidenceAction.Throw); - } - - [SecuritySafeCritical] - private void AddHostEvidence(EvidenceBase evidence, Type evidenceType, DuplicateEvidenceAction duplicateAction) - { - Contract.Assert(evidence != null); - Contract.Assert(evidenceType != null); - - if (Locked) - { - new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand(); - } - - using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Writer)) - { - AddHostEvidenceNoLock(evidence, evidenceType, duplicateAction); - } - } - - /// - /// Add evidence to the host supplied evidence collection without acquiring the evidence lock or - /// checking to make sure that the caller has permission to bypass locked evidence. - /// - private void AddHostEvidenceNoLock(EvidenceBase evidence, Type evidenceType, DuplicateEvidenceAction duplicateAction) - { - Contract.Assert(IsWriterLockHeld); - Contract.Assert(evidence != null); - Contract.Assert(evidenceType != null); - - EvidenceTypeDescriptor descriptor = GetEvidenceTypeDescriptor(evidenceType, true); - - ++m_version; - if (descriptor.HostEvidence == null) - { - descriptor.HostEvidence = evidence; - } - else - { - descriptor.HostEvidence = HandleDuplicateEvidence(descriptor.HostEvidence, - evidence, - duplicateAction); - } - } - - /// - /// Ask the host for the types of evidence that it might provide if it is asked. - /// - /// This should only be called when setting up the Evidence collection to interact with the - /// host, and should not be used once that connection is established and the evidence has been - /// made available to user code. - /// - [SecurityCritical] - private void QueryHostForPossibleEvidenceTypes() - { -#if FEATURE_CAS_POLICY - Contract.Assert(IsWriterLockHeld); - - // First check to see if we have a HostSecurityManager - if (AppDomain.CurrentDomain.DomainManager != null) - { - HostSecurityManager hsm = AppDomain.CurrentDomain.DomainManager.HostSecurityManager; - if (hsm != null) - { - Type[] hostSuppliedTypes = null; - - AppDomain targetDomain = m_target.Target as AppDomain; - Assembly targetAssembly = m_target.Target as Assembly; - - // - // If the HostSecurityManager wants to supply evidence for the type of target that we have, - // then ask it what types of evidence it might supply. - // - - if (targetAssembly != null && - (hsm.Flags & HostSecurityManagerOptions.HostAssemblyEvidence) == HostSecurityManagerOptions.HostAssemblyEvidence) - { - hostSuppliedTypes = hsm.GetHostSuppliedAssemblyEvidenceTypes(targetAssembly); - } - else if (targetDomain != null && - (hsm.Flags & HostSecurityManagerOptions.HostAppDomainEvidence) == HostSecurityManagerOptions.HostAppDomainEvidence) - { - hostSuppliedTypes = hsm.GetHostSuppliedAppDomainEvidenceTypes(); - } - - // - // Finally, mark the descriptor for each of the types that the host can supply to indicate - // we should ask the host to generate them if we're asked. - // - - if (hostSuppliedTypes != null) - { - foreach (Type hostEvidenceType in hostSuppliedTypes) - { - EvidenceTypeDescriptor evidenceDescriptor = GetEvidenceTypeDescriptor(hostEvidenceType, true); - evidenceDescriptor.HostCanGenerate = true; - } - } - } - } -#endif // FEATURE_CAS_POLICY - } - - internal bool IsUnmodified - { - get { return m_version == 0; } - } - - /// - /// Set or check to see if the evidence is locked. Locked evidence cannot have its host supplied - /// evidence list be modified without a successful demand for ControlEvidence. Any code can lock - /// evidence, but only code with ControlEvidence may unlock it. - /// - /// This lock is not the same as the synchronization lock that gates access to the evidence collection. - /// - public bool Locked - { - get - { - return m_locked; - } - - [SecuritySafeCritical] - set - { - if (!value) - { - new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand(); - - m_locked = false; - } - else - { - m_locked = true; - } - } - } - - /// - /// Target of any delay generated evidence objects - /// - internal IRuntimeEvidenceFactory Target - { - get { return m_target; } - - // - // There are two retargeting scenarios supported: - // - // 1. A PEFileEvidenceFactory is being upgraded to an AssemblyEvidenceFactory and we don't want - // to throw away any already generated evidence. - // 2. A detached evidence collection is being applied to an AppDomain and that domain has a - // HostSecurityManager. In that case, we want to attach the target to the AppDomain to - // allow the HostSecurityManager to get callbacks for delay generated evidence. - // - - [SecurityCritical] - set - { -#if FEATURE_CAS_POLICY - Contract.Assert((m_target != null && m_target is PEFileEvidenceFactory && value != null && value is AssemblyEvidenceFactory) || - (m_target == null && value != null && value is AppDomainEvidenceFactory), - "Evidence retargeting should only be from PEFile -> Assembly or detached -> AppDomain."); -#endif // FEATURE_CAS_POLICY - - using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Writer)) - { - m_target = value; - - // Since we've updated what we're pointing at, we need to query the host to determine what - // types of evidence that it can generate for this new target. - QueryHostForPossibleEvidenceTypes(); - } - } - } - - /// - /// Get the type that would be used to index into the evidence dictionary for this object - /// - private static Type GetEvidenceIndexType(EvidenceBase evidence) - { - Contract.Assert(evidence != null); - - // - // Legacy wrapper evidence types should be indexed via the type of evidence that they're wrapping - // so check to see if we have one of those; otherwise just return the type itself. - // - - ILegacyEvidenceAdapter adapter = evidence as ILegacyEvidenceAdapter; - return adapter == null ? evidence.GetType() : adapter.EvidenceType; - } - - /// - /// Get the type descriptor for a specific type of evidence. This method should be used instead - /// of accessing the dictionary directly as it will handle the case where a new descriptor needs - /// to be created. - /// - internal EvidenceTypeDescriptor GetEvidenceTypeDescriptor(Type evidenceType) - { - return GetEvidenceTypeDescriptor(evidenceType, false); - } - - /// - /// Get the type descriptor for a specific type of evidence, optionally creating a descriptor if - /// we did not yet know about this type of evidence. This method should be used instead of - /// accessing the dictionary directly as it will handle the case where a new descriptor needs - /// to be created. - /// - private EvidenceTypeDescriptor GetEvidenceTypeDescriptor(Type evidenceType, bool addIfNotExist) - { - Contract.Assert(IsReaderLockHeld || IsWriterLockHeld); - Contract.Assert(evidenceType != null); - - // If we don't know about the type being indexed and we don't want to add it then exit out - EvidenceTypeDescriptor descriptor = null; - if (!m_evidence.TryGetValue(evidenceType, out descriptor) && !addIfNotExist) - { - return null; - } - - // If we haven't yet created a descriptor for this type then create one now - if (descriptor == null) - { - descriptor = new EvidenceTypeDescriptor(); -#if _DEBUG - descriptor.SetEvidenceType(evidenceType); -#endif // _DEBUG - - bool upgradedLock = false; - LockCookie upgradeCookie = new LockCookie(); - try - { - if (!IsWriterLockHeld) - { - upgradeCookie = UpgradeToWriterLock(); - upgradedLock = true; - } - - m_evidence[evidenceType] = descriptor; - } - finally - { - if (upgradedLock) - DowngradeFromWriterLock(ref upgradeCookie); - } - } - - return descriptor; - } - - /// - /// This method is called if a piece of evidence is added but another piece of evidence of the same - /// type already existed. We have different strategies depending on compatibility concerns of the - /// calling code. - /// - private static EvidenceBase HandleDuplicateEvidence(EvidenceBase original, - EvidenceBase duplicate, - DuplicateEvidenceAction action) - { - Contract.Assert(original != null); - Contract.Assert(duplicate != null); - Contract.Assert(original.GetType() == duplicate.GetType() || original.GetType() == typeof(LegacyEvidenceList)); - - switch (action) - { - // Throw - duplicate evidence is not allowed (Arrowhead behavior), so throw an exception - case DuplicateEvidenceAction.Throw: - throw new InvalidOperationException(Environment.GetResourceString("Policy_DuplicateEvidence", duplicate.GetType().FullName)); - - // SelectNewObject - MergeWithNoDuplicates behavior - the duplicate object wins - case DuplicateEvidenceAction.SelectNewObject: - return duplicate; - - // Merge - compat behavior. Merge the old and new evidence into a list so that both may exist - case DuplicateEvidenceAction.Merge: - - LegacyEvidenceList list = original as LegacyEvidenceList; - if (list == null) - { - list = new LegacyEvidenceList(); - list.Add(original); - } - - list.Add(duplicate); - return list; - - default: - BCLDebug.Assert(false, "Uknown DuplicateEvidenceAction"); - return null; - } - } - - /// - /// Wrap evidence we recieved through a legacy API to ensure that it is stored in an EvidenceBase - /// - private static EvidenceBase WrapLegacyEvidence(object evidence) - { - Contract.Assert(evidence != null); - - EvidenceBase wrappedEvidence = evidence as EvidenceBase; - if (wrappedEvidence == null) - { - wrappedEvidence = new LegacyEvidenceWrapper(evidence); - } - - return wrappedEvidence; - } - - /// - /// Upwrap evidence stored in a legacy adapter. - /// - /// This is only necessary for the case where multiple objects derived from EvidenceBase is - /// are added via the legacy APIs and are then retrieved via GetHostEvidence. This may occur if - /// a legacy application adds CLR supplied evidence types via the old APIs and a new application - /// consumes the resulting evidence. - /// - private static object UnwrapEvidence(EvidenceBase evidence) - { - ILegacyEvidenceAdapter adapter = evidence as ILegacyEvidenceAdapter; - return adapter == null ? evidence : adapter.EvidenceObject; - } - - /// - /// Merge two evidence collections together. Note that this will cause all of the lazily - /// generated evidence for the input collection to be generated, as well as causing any lazily - /// generated evidence that both collections share to be generated in the target. - /// - [SecuritySafeCritical] - public void Merge(Evidence evidence) - { - if (evidence == null) - { - return; - } - - using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Writer)) - { - bool checkedLock = false; - IEnumerator hostEnumerator = evidence.GetHostEnumerator(); - while (hostEnumerator.MoveNext()) - { - if (Locked && !checkedLock) - { - new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand(); - checkedLock = true; - } - - // If we could potentially have evidence of the type about to be merged into our host list, - // then make sure that we generate that evidence before merging. This will prevent the - // newly merged evidence from masking the value that we would have generated on our own. - Type hostEvidenceType = hostEnumerator.Current.GetType(); - if (m_evidence.ContainsKey(hostEvidenceType)) - { - GetHostEvidenceNoLock(hostEvidenceType); - } - - EvidenceBase hostEvidence = WrapLegacyEvidence(hostEnumerator.Current); - AddHostEvidenceNoLock(hostEvidence, - GetEvidenceIndexType(hostEvidence), - DuplicateEvidenceAction.Merge); - } - - // Add each piece of assembly evidence. We don't need to deserialize our copy of the - // evidence because AddAssemblyEvidenceNoLock will do this for us. - IEnumerator assemblyEnumerator = evidence.GetAssemblyEnumerator(); - while (assemblyEnumerator.MoveNext()) - { - EvidenceBase assemblyEvidence = WrapLegacyEvidence(assemblyEnumerator.Current); - AddAssemblyEvidenceNoLock(assemblyEvidence, - GetEvidenceIndexType(assemblyEvidence), - DuplicateEvidenceAction.Merge); - } - } - } - - /// - /// Same as merge, except only one instance of any one evidence type is allowed. When duplicates - /// are found, the evidence in the input argument will have priority. Note this will force the - /// entire input evidence to be generated, and does not check for locked evidence - /// - internal void MergeWithNoDuplicates(Evidence evidence) - { - if (evidence == null) - { - return; - } - - using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Writer)) - { - IEnumerator hostEnumerator = evidence.GetHostEnumerator(); - while (hostEnumerator.MoveNext()) - { - EvidenceBase hostEvidence = WrapLegacyEvidence(hostEnumerator.Current); - AddHostEvidenceNoLock(hostEvidence, - GetEvidenceIndexType(hostEvidence), - DuplicateEvidenceAction.SelectNewObject); - } - - IEnumerator assemblyEnumerator = evidence.GetAssemblyEnumerator(); - while (assemblyEnumerator.MoveNext()) - { - EvidenceBase assemblyEvidence = WrapLegacyEvidence(assemblyEnumerator.Current); - AddAssemblyEvidenceNoLock(assemblyEvidence, - GetEvidenceIndexType(assemblyEvidence), - DuplicateEvidenceAction.SelectNewObject); - } - } - } - -#if FEATURE_SERIALIZATION - /// - /// Do a full serialization of the evidence, which requires that we generate all of the evidence - /// we can and disconnect ourselves from the host and source assembly. - /// - [ComVisible(false)] - [OnSerializing] - [SecurityCritical] - [PermissionSet(SecurityAction.Assert, Unrestricted = true)] - private void OnSerializing(StreamingContext context) - { - using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Reader)) - { - // First, force all of the host evidence that might be lazily generated to be created - foreach (Type evidenceType in new List(m_evidence.Keys)) - { - GetHostEvidenceNoLock(evidenceType); - } - - // Also ensure that all serialized assembly evidence has been created - DeserializeTargetEvidence(); - } - - // Fill in legacy evidence lists. We can't guarantee thread-safety here using locks - // because we can't put a lock in the serialization code that will read the lists. - // The best we can do is prevent another thread from seeing a half-populated list. - // Therefore, we assign the lists after we've populated them fully (and declare them volatile.) - ArrayList hostList = new ArrayList(); - IEnumerator hostEnumerator = GetHostEnumerator(); - while (hostEnumerator.MoveNext()) - { - hostList.Add(hostEnumerator.Current); - } - m_hostList = hostList; - - ArrayList assemblyList = new ArrayList(); - IEnumerator assemblyEnumerator = GetAssemblyEnumerator(); - while (assemblyEnumerator.MoveNext()) - { - assemblyList.Add(assemblyEnumerator.Current); - } - m_assemblyList = assemblyList; - } - - /// - /// Finish deserializing legacy evidence - /// - [ComVisible(false)] - [OnDeserialized] - [SecurityCritical] - private void OnDeserialized(StreamingContext context) - { - // Look at host and assembly evidence lists only if we serialized using Whidbey. - if (m_evidence == null) - { - m_evidence = new Dictionary(); - - // Whidbey evidence may need to be wrapped or added to a LegacyEvidenceList, so we go - // through the legacy APIs to add them. -#pragma warning disable 618 - if (m_hostList != null) - { - foreach (object evidenceObject in m_hostList) - { - if (evidenceObject != null) - { - AddHost(evidenceObject); - } - } - - m_hostList = null; - } - - if (m_assemblyList != null) - { - foreach (object evidenceObject in m_assemblyList) - { - if (evidenceObject != null) - { - AddAssembly(evidenceObject); - } - } - - m_assemblyList = null; - } -#pragma warning restore 618 - } - - // see code:System.Security.Policy.Evidence#EvidenceLock - m_evidenceLock = new ReaderWriterLock(); - } -#endif // FEATURE_SERIALIZATION - - /// - /// Load any serialized evidence out of the target assembly into our evidence collection. - /// - /// We allow entry to this method with only a reader lock held, since most of the time we will - /// not need to write to the evidence dictionary. If we haven't yet deserialized the target - /// evidence, then we will upgrade to a writer lock at that point. - /// - private void DeserializeTargetEvidence() - { -#if FEATURE_SERIALIZATION - Contract.Assert(IsReaderLockHeld || IsWriterLockHeld); - - if (m_target != null && !m_deserializedTargetEvidence) - { - bool upgradedLock = false; - LockCookie lockCookie = new LockCookie(); - try - { - if (!IsWriterLockHeld) - { - lockCookie = UpgradeToWriterLock(); - upgradedLock = true; - } - - // Set this to true here because AddAssemblyEvidenceNoLock will attempt to reenter this - // method creating possible infinite recursion. - m_deserializedTargetEvidence = true; - - foreach (EvidenceBase targetEvidence in m_target.GetFactorySuppliedEvidence()) - { - AddAssemblyEvidenceNoLock(targetEvidence, GetEvidenceIndexType(targetEvidence), DuplicateEvidenceAction.Throw); - } - } - finally - { - if (upgradedLock) - DowngradeFromWriterLock(ref lockCookie); - } - } -#endif // FEATURE_SERIALIZATION - } - -#if FEATURE_SERIALIZATION - /// - /// Serialize out raw evidence objects which have already been generated, ignoring any evidence - /// which might be present but has not yet been created for this assembly. - /// - /// This is used for indexing into the security policy cache, since we know that once policy is - /// resolved, the relevent membership conditions will have checked for any applicable evidence - /// and therefore after poliyc resolution this evidence collection will contain any evidence - /// objects necessary to arrive at its grant set. - /// - [SecurityCritical] - internal byte[] RawSerialize() - { - try - { - using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Reader)) - { - // Filter out any evidence which is not yet generated - Dictionary generatedEvidence = new Dictionary(); - foreach (KeyValuePair evidenceType in m_evidence) - { - if (evidenceType.Value != null && evidenceType.Value.HostEvidence != null) - { - generatedEvidence[evidenceType.Key] = evidenceType.Value.HostEvidence; - } - } - - using (MemoryStream serializationStream = new MemoryStream()) - { - BinaryFormatter formatter = new BinaryFormatter(); - formatter.Serialize(serializationStream, generatedEvidence); - return serializationStream.ToArray(); - } - } - } - catch (SecurityException) - { - // We're running in a context where it's not safe to serialize the evidence out. In this case - // Simply decline to cache the result of the policy evaluation - return null; - } - } -#endif // FEATURE_SERIALIZATION - - // - // ICollection implementation. All ICollection interface members are potentially much more - // expensive in Arrowhead then they were downlevel. They should not be used if the standard Get and - // Add methods will work instead. - // - - [Obsolete("Evidence should not be treated as an ICollection. Please use the GetHostEnumerator and GetAssemblyEnumerator methods rather than using CopyTo.")] - public void CopyTo(Array array, int index) - { - if (array == null) - throw new ArgumentNullException("array"); - if (index < 0 || index > array.Length - Count) - throw new ArgumentOutOfRangeException("index"); - Contract.EndContractBlock(); - - int currentIndex = index; - - IEnumerator hostEnumerator = GetHostEnumerator(); - while (hostEnumerator.MoveNext()) - { - array.SetValue(hostEnumerator.Current, currentIndex); - ++currentIndex; - } - - IEnumerator assemblyEnumerator = GetAssemblyEnumerator(); - while (assemblyEnumerator.MoveNext()) - { - array.SetValue(assemblyEnumerator.Current, currentIndex); - ++currentIndex; - } - } - - public IEnumerator GetHostEnumerator() - { - using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Reader)) - { - return new EvidenceEnumerator(this, EvidenceEnumerator.Category.Host); - } - } - - public IEnumerator GetAssemblyEnumerator() - { - using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Reader)) - { - DeserializeTargetEvidence(); - return new EvidenceEnumerator(this, EvidenceEnumerator.Category.Assembly); - } - } - - /// - /// Get an enumerator that can iterate over the raw evidence objects stored for the assembly - /// - internal RawEvidenceEnumerator GetRawAssemblyEvidenceEnumerator() - { - Contract.Assert(IsReaderLockHeld); - DeserializeTargetEvidence(); - return new RawEvidenceEnumerator(this, new List(m_evidence.Keys), false); - } - - /// - /// Get an enumerator that can iterate over the raw evidence objects stored for the host - /// - /// - internal RawEvidenceEnumerator GetRawHostEvidenceEnumerator() - { - Contract.Assert(IsReaderLockHeld); - return new RawEvidenceEnumerator(this, new List(m_evidence.Keys), true); - } - - [Obsolete("GetEnumerator is obsolete. Please use GetAssemblyEnumerator and GetHostEnumerator instead.")] - public IEnumerator GetEnumerator() - { - using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Reader)) - { - return new EvidenceEnumerator(this, EvidenceEnumerator.Category.Host | EvidenceEnumerator.Category.Assembly); - } - } - - /// - /// Get a specific type of assembly supplied evidence - /// - [ComVisible(false)] - public T GetAssemblyEvidence() where T : EvidenceBase - { - return UnwrapEvidence(GetAssemblyEvidence(typeof(T))) as T; - } - - internal EvidenceBase GetAssemblyEvidence(Type type) - { - Contract.Assert(type != null); - - using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Reader)) - { - return GetAssemblyEvidenceNoLock(type); - } - } - - private EvidenceBase GetAssemblyEvidenceNoLock(Type type) - { - Contract.Assert(IsReaderLockHeld || IsWriterLockHeld); - Contract.Assert(type != null); - - DeserializeTargetEvidence(); - EvidenceTypeDescriptor descriptor = GetEvidenceTypeDescriptor(type); - if (descriptor != null) - { - return descriptor.AssemblyEvidence; - } - - return null; - } - - /// - /// Get a specific type of host supplied evidence - /// - [ComVisible(false)] - public T GetHostEvidence() where T : EvidenceBase - { - return UnwrapEvidence(GetHostEvidence(typeof(T))) as T; - } - - /// - /// Get a specific type of evidence from the host which may not have been verified yet. If the - /// evidence was not verified, then don't mark it as being used yet. - /// - internal T GetDelayEvaluatedHostEvidence() where T : EvidenceBase, IDelayEvaluatedEvidence - { - return UnwrapEvidence(GetHostEvidence(typeof(T), false)) as T; - } - - internal EvidenceBase GetHostEvidence(Type type) - { - Contract.Assert(type != null); - - return GetHostEvidence(type, true); - } - - [SecuritySafeCritical] - private EvidenceBase GetHostEvidence(Type type, bool markDelayEvaluatedEvidenceUsed) - { - Contract.Assert(type != null); - - using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Reader)) - { - EvidenceBase evidence = GetHostEvidenceNoLock(type); - - if (markDelayEvaluatedEvidenceUsed) - { - IDelayEvaluatedEvidence delayEvidence = evidence as IDelayEvaluatedEvidence; - if (delayEvidence != null) - { - delayEvidence.MarkUsed(); - } - } - - return evidence; - } - } - - /// - /// Get host supplied evidence from the collection - /// - /// We attempt to find host evdience in the following order: - /// - /// 1. Already generated or explicitly supplied evidence - /// 2. Evidence supplied by the CLR host - /// 3. Evidence supplied by the CLR itself - /// - [SecurityCritical] - private EvidenceBase GetHostEvidenceNoLock(Type type) - { - Contract.Assert(IsReaderLockHeld || IsWriterLockHeld); - Contract.Assert(type != null); - - EvidenceTypeDescriptor descriptor = GetEvidenceTypeDescriptor(type); - - // If the evidence descriptor doesn't exist for the host evidence type than the evidence doesn't - // exist and neither the host nor the runtime can produce it. - if (descriptor == null) - { - return null; - } - - // If the evidence has already been generated or if it was explicitly provided then return that - if (descriptor.HostEvidence != null) - { - return descriptor.HostEvidence; - } - - // If we have a target, then the host or the runtime might be able to generate this type of - // evidence on demand. - if (m_target != null && !descriptor.Generated) - { - using (EvidenceUpgradeLockHolder lockHolder = new EvidenceUpgradeLockHolder(this)) - { - // Make sure that we don't attempt to generate this type of evidencea again if we fail to - // generate it now. - descriptor.Generated = true; - - EvidenceBase generatedEvidence = GenerateHostEvidence(type, descriptor.HostCanGenerate); - if (generatedEvidence != null) - { - descriptor.HostEvidence = generatedEvidence; - - // - // #BackpatchGeneratedEvidence - // - // If we were cloned from another evidence collection propigate any generated evidence - // back to the original collection. Since Assembly and AppDomain both clone their - // evidence before giving it to users, this prevents us from having to regenerate - // evidence types on each clone that gets created. Note that we do not want to do this - // backpatching if the origin already has evidence of this type or if it has had - // this type of evidence removed from its collection. - // - - Evidence cloneOrigin = m_cloneOrigin != null ? m_cloneOrigin.Target as Evidence : null; - if (cloneOrigin != null) - { - BCLDebug.Assert(cloneOrigin.Target != null && cloneOrigin.Target == Target, - "Attempt to backpatch evidence to a collection with a different target."); - - using (EvidenceLockHolder cloneLockHolder = new EvidenceLockHolder(cloneOrigin, EvidenceLockHolder.LockType.Writer)) - { - EvidenceTypeDescriptor cloneDescriptor = cloneOrigin.GetEvidenceTypeDescriptor(type); - if (cloneDescriptor != null && cloneDescriptor.HostEvidence == null) - { - cloneDescriptor.HostEvidence = generatedEvidence.Clone() as EvidenceBase; - } - } - } - - } - - return generatedEvidence; - } - } - - // The evidence could not be generated and was not found - return null; - } - - /// - /// Attempt to generate host evidence on demand via calls to the runtime host or the evidence facotry - /// - [SecurityCritical] - private EvidenceBase GenerateHostEvidence(Type type, bool hostCanGenerate) - { - Contract.Assert(type != null); - Contract.Assert(IsWriterLockHeld); - -#if FEATURE_CAS_POLICY - // First let the host generate the evidence if it can. - if (hostCanGenerate) - { - AppDomain targetDomain = m_target.Target as AppDomain; - Assembly targetAssembly = m_target.Target as Assembly; - - EvidenceBase hostEvidence = null; - if (targetDomain != null) - { - hostEvidence = AppDomain.CurrentDomain.HostSecurityManager.GenerateAppDomainEvidence(type); - } - else if (targetAssembly != null) - { - hostEvidence = AppDomain.CurrentDomain.HostSecurityManager.GenerateAssemblyEvidence(type, targetAssembly); - } - - // If the host generated the evidence, verify that it generated the evidence we expected - // and use that. - if (hostEvidence != null) - { - if (!type.IsAssignableFrom(hostEvidence.GetType())) - { - string hostType = AppDomain.CurrentDomain.HostSecurityManager.GetType().FullName; - string recievedType = hostEvidence.GetType().FullName; - string requestedType = type.FullName; - - throw new InvalidOperationException(Environment.GetResourceString("Policy_IncorrectHostEvidence", hostType, recievedType, requestedType)); - } - - return hostEvidence; - } - } -#endif // FEATURE_CAS_POLICY - - // Finally, check to see if the CLR can generate the evidence - return m_target.GenerateEvidence(type); - } - - [Obsolete("Evidence should not be treated as an ICollection. Please use GetHostEnumerator and GetAssemblyEnumerator to iterate over the evidence to collect a count.")] - public int Count - { - get - { - int count = 0; - - IEnumerator hostEvidence = GetHostEnumerator(); - while (hostEvidence.MoveNext()) - { - ++count; - } - - IEnumerator assemblyEvidence = GetAssemblyEnumerator(); - while (assemblyEvidence.MoveNext()) - { - ++count; - } - - return count; - } - } - - /// - /// Get the number of pieces of evidence which are currently generated, without causing any - /// lazily generated evidence to be created. - /// - [ComVisible(false)] - internal int RawCount - { - get - { - int count = 0; - - using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Reader)) - { - foreach (Type evidenceType in new List(m_evidence.Keys)) - { - EvidenceTypeDescriptor descriptor = GetEvidenceTypeDescriptor(evidenceType); - - if (descriptor != null) - { - if (descriptor.AssemblyEvidence != null) - { - ++count; - } - if (descriptor.HostEvidence != null) - { - ++count; - } - } - } - } - - return count; - } - } - - public Object SyncRoot - { - get { return this; } - } - - public bool IsSynchronized - { - get { return true; } - } - - public bool IsReadOnly - { - get { return false; } - } - -#if FEATURE_CAS_POLICY - [ComVisible(false)] - public Evidence Clone() - { - return new Evidence(this); - } -#endif // FEATURE_CAS_POLICY - - [ComVisible(false)] - [SecuritySafeCritical] - public void Clear() - { - if (Locked) - { - new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand(); - } - - using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Writer)) - { - ++m_version; - m_evidence.Clear(); - } - } - - [ComVisible(false)] - [SecuritySafeCritical] - public void RemoveType(Type t) - { - if (t == null) - throw new ArgumentNullException("t"); - Contract.EndContractBlock(); - - using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Writer)) - { - EvidenceTypeDescriptor descriptor = GetEvidenceTypeDescriptor(t); - if (descriptor != null) - { - ++m_version; - - // If we've locked this evidence collection, we need to do the lock check in the case that - // either we have host evidence, or that the host might generate it, since removing the - // evidence will cause us to bypass the host's ability to ever generate the evidence. - if (Locked && (descriptor.HostEvidence != null || descriptor.HostCanGenerate)) - { - new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand(); - } - - m_evidence.Remove(t); - } - } - } - - /// - /// Mark all of the already generated evidence in the collection as having been used during a - /// policy evaluation. - /// - internal void MarkAllEvidenceAsUsed() - { - using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Reader)) - { - foreach (KeyValuePair evidenceType in m_evidence) - { - if (evidenceType.Value != null) - { - IDelayEvaluatedEvidence hostEvidence = evidenceType.Value.HostEvidence as IDelayEvaluatedEvidence; - if (hostEvidence != null) - { - hostEvidence.MarkUsed(); - } - - IDelayEvaluatedEvidence assemblyEvidence = evidenceType.Value.AssemblyEvidence as IDelayEvaluatedEvidence; - if (assemblyEvidence != null) - { - assemblyEvidence.MarkUsed(); - } - } - } - } - } - -#if FEATURE_CAS_POLICY - /// - /// Determine if delay evaluated strong name evidence is contained in this collection, and if so - /// if it was used during policy evaluation. - /// - /// This method is called from the VM in SecurityPolicy::WasStrongNameEvidenceUsed - /// This class should be used as an adapter layer to allow the public facing EvidenceEnumerator to - /// be able to get the evidence values out of an Evidence class. It is tightly coupled with the - /// internal data structures holding the evidence objects in the Evidence class. - /// - private bool WasStrongNameEvidenceUsed() - { - using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Reader)) - { - EvidenceTypeDescriptor snTypeDescriptor = GetEvidenceTypeDescriptor(typeof(StrongName)); - if (snTypeDescriptor != null) - { - IDelayEvaluatedEvidence snEvidence = snTypeDescriptor.HostEvidence as IDelayEvaluatedEvidence; - return snEvidence != null && snEvidence.WasUsed; - } - - return false; - } - } -#endif // FEATURE_CAS_POLICY - - /// - /// Utility class to wrap acquiring a lock onto the evidence collection - /// - private class EvidenceLockHolder : IDisposable - { - private Evidence m_target; - private LockType m_lockType; - - public enum LockType - { - Reader, - Writer - } - - public EvidenceLockHolder(Evidence target, LockType lockType) - { - Contract.Assert(target != null); - Contract.Assert(lockType == LockType.Reader || lockType == LockType.Writer); - - m_target = target; - m_lockType = lockType; - - if (m_lockType == LockType.Reader) - { - m_target.AcquireReaderLock(); - } - else - { - m_target.AcquireWriterlock(); - } - } - - public void Dispose() - { - if (m_lockType == LockType.Reader && m_target.IsReaderLockHeld) - { - m_target.ReleaseReaderLock(); - } - else if (m_lockType == LockType.Writer && m_target.IsWriterLockHeld) - { - m_target.ReleaseWriterLock(); - } - } - } - - /// - /// Utility class to wrap upgrading an acquired reader lock to a writer lock and then - /// downgrading it back to a reader lock. - /// - private class EvidenceUpgradeLockHolder : IDisposable - { - private Evidence m_target; - private LockCookie m_cookie; - - public EvidenceUpgradeLockHolder(Evidence target) - { - Contract.Assert(target != null); - - m_target = target; - m_cookie = m_target.UpgradeToWriterLock(); - } - - public void Dispose() - { - if (m_target.IsWriterLockHeld) - { - m_target.DowngradeFromWriterLock(ref m_cookie); - } - } - } - - /// - /// Enumerator that iterates directly over the evidence type map, returning back the evidence objects - /// that are contained in it. This enumerator will generate any lazy evaluated evidence it finds, - /// but it does not attempt to deal with legacy evidence adapters. - /// - /// This class should be used as an adapter layer to allow the public facing EvidenceEnumerator to - /// be able to get the evidence values out of an Evidence class. It is tightly coupled with the - /// internal data structures holding the evidence objects in the Evidence class. - /// - internal sealed class RawEvidenceEnumerator : IEnumerator - { - private Evidence m_evidence; - private bool m_hostEnumerator; // true to enumerate host evidence, false to enumerate assembly evidence - private uint m_evidenceVersion; - - private Type[] m_evidenceTypes; - private int m_typeIndex; - private EvidenceBase m_currentEvidence; - - private static volatile List s_expensiveEvidence; - - public RawEvidenceEnumerator(Evidence evidence, IEnumerable evidenceTypes, bool hostEnumerator) - { - Contract.Assert(evidence != null); - Contract.Assert(evidenceTypes != null); - - m_evidence = evidence; - m_hostEnumerator = hostEnumerator; - m_evidenceTypes = GenerateEvidenceTypes(evidence, evidenceTypes, hostEnumerator); - m_evidenceVersion = evidence.m_version; - - Reset(); - } - - public EvidenceBase Current - { - get - { - if (m_evidence.m_version != m_evidenceVersion) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion")); - - return m_currentEvidence; - } - } - - object IEnumerator.Current - { - get - { - if (m_evidence.m_version != m_evidenceVersion) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion")); - - return m_currentEvidence; - } - } - - /// - /// List of types of evidence that we would like to avoid generating if possible - /// - private static List ExpensiveEvidence - { - get - { - if (s_expensiveEvidence == null) - { - List expensiveEvidence = new List(); -#if FEATURE_CAS_POLICY - expensiveEvidence.Add(typeof(Hash)); - expensiveEvidence.Add(typeof(Publisher)); -#endif // FEATURE_CAS_POLICY - s_expensiveEvidence = expensiveEvidence; - -#if _DEBUG - List runtimeTypes = new List(Evidence.RuntimeEvidenceTypes); - foreach (Type expensiveType in s_expensiveEvidence) - { - BCLDebug.Assert(runtimeTypes.Contains(expensiveType), - "Evidence type not generated by the runtime found in expensive evidence type list"); - } -#endif // _DEBUG - } - - return s_expensiveEvidence; - } - } - - public void Dispose() - { - return; - } - - /// - /// Generate the array of types of evidence that could have values for - /// - private static Type[] GenerateEvidenceTypes(Evidence evidence, - IEnumerable evidenceTypes, - bool hostEvidence) - { - Contract.Assert(evidence != null); - Contract.Assert(evidenceTypes != null); - - // - // Sort the evidence being generated into three categories, which we enumerate in order: - // 1. Evidence which has already been generated - // 2. Evidence which is relatively inexpensive to generate - // 3. Evidence which is expensive to generate. - // - // This allows us to be as efficient as possible in case the user of the enumerator stops the - // enumeration before we step up to the next more expensive category. - // - - List alreadyGeneratedList = new List(); - List inexpensiveList = new List(); - List expensiveList = new List(ExpensiveEvidence.Count); - - // Iterate over the evidence types classifying into the three groups. We need to copy the list - // here since GetEvidenceTypeDescriptor will potentially update the evidence dictionary, which - // evidenceTypes iterates over. - foreach (Type evidenceType in evidenceTypes) - { - EvidenceTypeDescriptor descriptor = evidence.GetEvidenceTypeDescriptor(evidenceType); - BCLDebug.Assert(descriptor != null, "descriptor != null"); - - bool alreadyGenerated = (hostEvidence && descriptor.HostEvidence != null) || - (!hostEvidence && descriptor.AssemblyEvidence != null); - - if (alreadyGenerated) - { - alreadyGeneratedList.Add(evidenceType); - } - else if (ExpensiveEvidence.Contains(evidenceType)) - { - expensiveList.Add(evidenceType); - } - else - { - inexpensiveList.Add(evidenceType); - } - } - - Type[] enumerationTypes = new Type[alreadyGeneratedList.Count + inexpensiveList.Count + expensiveList.Count]; - alreadyGeneratedList.CopyTo(enumerationTypes, 0); - inexpensiveList.CopyTo(enumerationTypes, alreadyGeneratedList.Count); - expensiveList.CopyTo(enumerationTypes, alreadyGeneratedList.Count + inexpensiveList.Count); - - return enumerationTypes; - } - - [SecuritySafeCritical] - public bool MoveNext() - { - using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(m_evidence, EvidenceLockHolder.LockType.Reader)) - { - if (m_evidence.m_version != m_evidenceVersion) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion")); - - m_currentEvidence = null; - - // Iterate over the possible types of evidence that we could have until we find one that - // really exists, or we run out of posibilities. - do - { - ++m_typeIndex; - - if (m_typeIndex < m_evidenceTypes.Length) - { - if (m_hostEnumerator) - { - m_currentEvidence = m_evidence.GetHostEvidenceNoLock(m_evidenceTypes[m_typeIndex]); - } - else - { - m_currentEvidence = m_evidence.GetAssemblyEvidenceNoLock(m_evidenceTypes[m_typeIndex]); - } - } - } - while (m_typeIndex < m_evidenceTypes.Length && m_currentEvidence == null); - } - - return m_currentEvidence != null; - } - - public void Reset() - { - if (m_evidence.m_version != m_evidenceVersion) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion")); - - m_typeIndex = -1; - m_currentEvidence = null; - } - } - - private sealed class EvidenceEnumerator : IEnumerator - { - private Evidence m_evidence; - private Category m_category; - private Stack m_enumerators; - - private object m_currentEvidence; - - [Flags] - internal enum Category - { - Host = 0x1, // Enumerate only host supplied evidence - Assembly = 0x2 // Enumerate only assembly supplied evidence - } - - internal EvidenceEnumerator(Evidence evidence, Category category) - { - Contract.Assert(evidence != null); - Contract.Assert(evidence.IsReaderLockHeld); - - m_evidence = evidence; - m_category = category; - ResetNoLock(); - } - - public bool MoveNext() - { - IEnumerator currentEnumerator = CurrentEnumerator; - - // No more enumerators means we can't go any further - if (currentEnumerator == null) - { - m_currentEvidence = null; - return false; - } - - // See if the current enumerator can continue - if (currentEnumerator.MoveNext()) - { - // - // If we've found an adapter for legacy evidence, we need to unwrap it for it to be the - // current enumerator's value. For wrapped evidence, this is a simple unwrap, for a list of - // evidence, we need to make that the current enumerator and get its first value. - // - - LegacyEvidenceWrapper legacyWrapper = currentEnumerator.Current as LegacyEvidenceWrapper; - LegacyEvidenceList legacyList = currentEnumerator.Current as LegacyEvidenceList; - - if (legacyWrapper != null) - { - m_currentEvidence = legacyWrapper.EvidenceObject; - } - else if (legacyList != null) - { - IEnumerator legacyListEnumerator = legacyList.GetEnumerator(); - m_enumerators.Push(legacyListEnumerator); - MoveNext(); - } - else - { - m_currentEvidence = currentEnumerator.Current; - } - - BCLDebug.Assert(m_currentEvidence != null, "m_currentEvidence != null"); - return true; - } - else - { - // If we've reached the end of the current enumerator, move to the next one and try again - m_enumerators.Pop(); - return MoveNext(); - } - } - - public object Current - { - get { return m_currentEvidence; } - } - - private IEnumerator CurrentEnumerator - { - get - { - return m_enumerators.Count > 0 ? m_enumerators.Peek() as IEnumerator : null; - } - } - - public void Reset() - { - using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(m_evidence, EvidenceLockHolder.LockType.Reader)) - { - ResetNoLock(); - } - } - - private void ResetNoLock() - { - Contract.Assert(m_evidence != null); - Contract.Assert(m_evidence.IsReaderLockHeld); - - m_currentEvidence = null; - m_enumerators = new Stack(); - - if ((m_category & Category.Host) == Category.Host) - { - m_enumerators.Push(m_evidence.GetRawHostEvidenceEnumerator()); - } - if ((m_category & Category.Assembly) == Category.Assembly) - { - m_enumerators.Push(m_evidence.GetRawAssemblyEvidenceEnumerator()); - } - } - } -#endif //!FEATURE_CORECLR && FEATURE_RWLOCK } } diff --git a/src/mscorlib/src/System/Security/Policy/EvidenceBase.cs b/src/mscorlib/src/System/Security/Policy/EvidenceBase.cs index f142ebe..7fef1de 100644 --- a/src/mscorlib/src/System/Security/Policy/EvidenceBase.cs +++ b/src/mscorlib/src/System/Security/Policy/EvidenceBase.cs @@ -7,6 +7,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.IO; using System.Runtime.InteropServices; @@ -22,9 +23,6 @@ namespace System.Security.Policy /// [ComVisible(true)] [Serializable] -#pragma warning disable 618 - [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)] -#pragma warning restore 618 public abstract class EvidenceBase { protected EvidenceBase() @@ -44,11 +42,6 @@ namespace System.Security.Policy /// Since legacy evidence objects would be cloned by being serialized, the default implementation /// of EvidenceBase will do the same. /// -#pragma warning disable 618 - [SecurityPermission(SecurityAction.Assert, SerializationFormatter = true)] - [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)] -#pragma warning restore 618 - [SecuritySafeCritical] public virtual EvidenceBase Clone() { #if FEATURE_SERIALIZATION @@ -86,9 +79,9 @@ namespace System.Security.Policy internal LegacyEvidenceWrapper(object legacyEvidence) { - Contract.Assert(legacyEvidence != null); - Contract.Assert(legacyEvidence.GetType() != typeof(EvidenceBase), "Attempt to wrap an EvidenceBase in a LegacyEvidenceWrapper"); - Contract.Assert(legacyEvidence.GetType().IsSerializable, "legacyEvidence.GetType().IsSerializable"); + Debug.Assert(legacyEvidence != null); + Debug.Assert(legacyEvidence.GetType() != typeof(EvidenceBase), "Attempt to wrap an EvidenceBase in a LegacyEvidenceWrapper"); + Debug.Assert(legacyEvidence.GetType().IsSerializable, "legacyEvidence.GetType().IsSerializable"); m_legacyEvidence = legacyEvidence; } @@ -113,10 +106,6 @@ namespace System.Security.Policy return m_legacyEvidence.GetHashCode(); } -#pragma warning disable 618 - [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)] -#pragma warning restore 618 - [SecuritySafeCritical] public override EvidenceBase Clone() { return base.Clone(); @@ -153,7 +142,7 @@ namespace System.Security.Policy { get { - Contract.Assert(m_legacyEvidenceList.Count > 0, "No items in LegacyEvidenceList, cannot tell what type they are"); + Debug.Assert(m_legacyEvidenceList.Count > 0, "No items in LegacyEvidenceList, cannot tell what type they are"); ILegacyEvidenceAdapter adapter = m_legacyEvidenceList[0] as ILegacyEvidenceAdapter; return adapter == null ? m_legacyEvidenceList[0].GetType() : adapter.EvidenceType; @@ -162,10 +151,10 @@ namespace System.Security.Policy public void Add(EvidenceBase evidence) { - Contract.Assert(evidence != null); - Contract.Assert(m_legacyEvidenceList.Count == 0 || EvidenceType == evidence.GetType() || (evidence is LegacyEvidenceWrapper && (evidence as LegacyEvidenceWrapper).EvidenceType == EvidenceType), + Debug.Assert(evidence != null); + Debug.Assert(m_legacyEvidenceList.Count == 0 || EvidenceType == evidence.GetType() || (evidence is LegacyEvidenceWrapper && (evidence as LegacyEvidenceWrapper).EvidenceType == EvidenceType), "LegacyEvidenceList must be homogeonous"); - Contract.Assert(evidence.GetType() != typeof(LegacyEvidenceList), + Debug.Assert(evidence.GetType() != typeof(LegacyEvidenceList), "Attempt to add a legacy evidence list to another legacy evidence list"); m_legacyEvidenceList.Add(evidence); @@ -181,10 +170,6 @@ namespace System.Security.Policy return m_legacyEvidenceList.GetEnumerator(); } -#pragma warning disable 618 - [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)] -#pragma warning restore 618 - [SecuritySafeCritical] public override EvidenceBase Clone() { return base.Clone(); diff --git a/src/mscorlib/src/System/Security/Policy/EvidenceTypeDescriptor.cs b/src/mscorlib/src/System/Security/Policy/EvidenceTypeDescriptor.cs index bccf392..8deb145 100644 --- a/src/mscorlib/src/System/Security/Policy/EvidenceTypeDescriptor.cs +++ b/src/mscorlib/src/System/Security/Policy/EvidenceTypeDescriptor.cs @@ -41,7 +41,7 @@ namespace System.Security.Policy /// private EvidenceTypeDescriptor(EvidenceTypeDescriptor descriptor) { - Contract.Assert(descriptor != null); + Debug.Assert(descriptor != null); m_hostCanGenerate = descriptor.m_hostCanGenerate; @@ -68,9 +68,9 @@ namespace System.Security.Policy set { - Contract.Assert(value != null); + Debug.Assert(value != null); #if _DEBUG - Contract.Assert(CheckEvidenceType(value), "Incorrect type of AssemblyEvidence set"); + Debug.Assert(CheckEvidenceType(value), "Incorrect type of AssemblyEvidence set"); #endif m_assemblyEvidence = value; } @@ -85,7 +85,7 @@ namespace System.Security.Policy set { - Contract.Assert(value, "Attempt to clear the Generated flag"); + Debug.Assert(value, "Attempt to clear the Generated flag"); m_generated = value; } } @@ -99,7 +99,7 @@ namespace System.Security.Policy set { - Contract.Assert(value, "Attempt to clear HostCanGenerate flag"); + Debug.Assert(value, "Attempt to clear HostCanGenerate flag"); m_hostCanGenerate = value; } } @@ -113,9 +113,9 @@ namespace System.Security.Policy set { - Contract.Assert(value != null); + Debug.Assert(value != null); #if _DEBUG - Contract.Assert(CheckEvidenceType(value), "Incorrect type of HostEvidence set"); + Debug.Assert(CheckEvidenceType(value), "Incorrect type of HostEvidence set"); #endif m_hostEvidence = value; } @@ -127,7 +127,7 @@ namespace System.Security.Policy /// private bool CheckEvidenceType(EvidenceBase evidence) { - Contract.Assert(evidence != null); + Debug.Assert(evidence != null); ILegacyEvidenceAdapter legacyAdapter = evidence as ILegacyEvidenceAdapter; Type storedType = legacyAdapter == null ? evidence.GetType() : legacyAdapter.EvidenceType; @@ -150,8 +150,8 @@ namespace System.Security.Policy /// internal void SetEvidenceType(Type evidenceType) { - Contract.Assert(evidenceType != null); - Contract.Assert(m_evidenceType == null, "Attempt to reset evidence type"); + Debug.Assert(evidenceType != null); + Debug.Assert(m_evidenceType == null, "Attempt to reset evidence type"); m_evidenceType = evidenceType; } diff --git a/src/mscorlib/src/System/Security/Policy/IDelayEvaluatedEvidence.cs b/src/mscorlib/src/System/Security/Policy/IDelayEvaluatedEvidence.cs index 5bd3648..8f8c07c 100644 --- a/src/mscorlib/src/System/Security/Policy/IDelayEvaluatedEvidence.cs +++ b/src/mscorlib/src/System/Security/Policy/IDelayEvaluatedEvidence.cs @@ -18,7 +18,6 @@ namespace System.Security.Policy { /// bool IsVerified { - [System.Security.SecurityCritical] get; } diff --git a/src/mscorlib/src/System/Security/Policy/PolicyStatement.cs b/src/mscorlib/src/System/Security/Policy/PolicyStatement.cs index 72c07d1..9b58ece 100644 --- a/src/mscorlib/src/System/Security/Policy/PolicyStatement.cs +++ b/src/mscorlib/src/System/Security/Policy/PolicyStatement.cs @@ -35,14 +35,6 @@ namespace System.Security.Policy { // The PermissionSet associated with this policy internal PermissionSet m_permSet; -#if FEATURE_CAS_POLICY - // Evidence which was not verified but which was required to generate this policy statement. - // This is not serialized, since once we serialize we lose the ability to verify the evidence, - // meaning that restoring this state is meaningless. - [NonSerialized] - private List m_dependentEvidence; -#endif - // The bitfield of inheritance properties associated with this policy internal PolicyStatementAttribute m_attributes; @@ -144,20 +136,13 @@ namespace System.Security.Policy { } } } - + public PolicyStatement Copy() { - PolicyStatement copy = new PolicyStatement(m_permSet, Attributes, true); // The PolicyStatement .ctor will copy the permission set -#if FEATURE_CAS_POLICY - if (HasDependentEvidence) - { - copy.m_dependentEvidence = new List(m_dependentEvidence); - } -#endif - - return copy; + // The PolicyStatement .ctor will copy the permission set + return new PolicyStatement(m_permSet, Attributes, true); } - + public String AttributeString { get @@ -199,44 +184,6 @@ namespace System.Security.Policy { return (flag & (int)m_attributes) != 0; } -#if FEATURE_CAS_POLICY - /// - /// Gets all of the delay evaluated evidence which needs to be verified before this policy can - /// be used. - /// - internal IEnumerable DependentEvidence - { - get - { - BCLDebug.Assert(HasDependentEvidence, "HasDependentEvidence"); - return m_dependentEvidence.AsReadOnly(); - } - } - - /// - /// Determine if this policy dependent upon the evaluation of any delay evaluated evidence - /// - internal bool HasDependentEvidence - { - get { return m_dependentEvidence != null && m_dependentEvidence.Count > 0; } - } - - /// - /// Add evidence which this policy statement is depending upon being verified to be valid. - /// - internal void AddDependentEvidence(IDelayEvaluatedEvidence dependentEvidence) - { - BCLDebug.Assert(dependentEvidence != null, "dependentEvidence != null"); - - if (m_dependentEvidence == null) - { - m_dependentEvidence = new List(); - } - - m_dependentEvidence.Add(dependentEvidence); - } -#endif - /// /// Union a child policy statement into this policy statement /// @@ -249,27 +196,6 @@ namespace System.Security.Policy { throw new PolicyException(Environment.GetResourceString( "Policy_MultipleExclusive" )); } -#if FEATURE_CAS_POLICY - // If our code group generated a grant set based upon unverified evidence, or it generated a grant - // set strictly less than that of a child group based upon unverified evidence, we need to keep - // track of any unverified evidence our child group has. - if (childPolicy.HasDependentEvidence) - { - bool childEvidenceNeedsVerification = m_permSet.IsSubsetOf(childPolicy.GetPermissionSetNoCopy()) && - !childPolicy.GetPermissionSetNoCopy().IsSubsetOf(m_permSet); - - if (HasDependentEvidence || childEvidenceNeedsVerification) - { - if (m_dependentEvidence == null) - { - m_dependentEvidence = new List(); - } - - m_dependentEvidence.AddRange(childPolicy.DependentEvidence); - } - } -#endif - // We need to merge together our grant set and attributes. The result of this merge is // dependent upon if we're merging a child marked exclusive or not. If the child is not // exclusive, we need to union in its grant set and or in its attributes. However, if the child @@ -287,226 +213,6 @@ namespace System.Security.Policy { } } -#if FEATURE_CAS_POLICY - - public SecurityElement ToXml() - { - return ToXml( null ); - } - - public void FromXml( SecurityElement et ) - { - FromXml( et, null ); - } - - public SecurityElement ToXml( PolicyLevel level ) - { - return ToXml( level, false ); - } - - internal SecurityElement ToXml( PolicyLevel level, bool useInternal ) - { - SecurityElement e = new SecurityElement( "PolicyStatement" ); - e.AddAttribute( "version", "1" ); - if (m_attributes != PolicyStatementAttribute.Nothing) - e.AddAttribute( "Attributes", XMLUtil.BitFieldEnumToString( typeof( PolicyStatementAttribute ), m_attributes ) ); - - lock (this) - { - if (m_permSet != null) - { - if (m_permSet is NamedPermissionSet) - { - // If the named permission set exists in the parent level of this - // policy struct, then just save the name of the permission set. - // Otherwise, serialize it like normal. - - NamedPermissionSet namedPermSet = (NamedPermissionSet)m_permSet; - if (level != null && level.GetNamedPermissionSet( namedPermSet.Name ) != null) - { - e.AddAttribute( "PermissionSetName", namedPermSet.Name ); - } - else - { - if (useInternal) - e.AddChild( namedPermSet.InternalToXml() ); - else - e.AddChild( namedPermSet.ToXml() ); - } - } - else - { - if (useInternal) - e.AddChild( m_permSet.InternalToXml() ); - else - e.AddChild( m_permSet.ToXml() ); - } - } - } - - return e; - } - - [System.Security.SecuritySafeCritical] // auto-generated - public void FromXml( SecurityElement et, PolicyLevel level ) - { - FromXml( et, level, false ); - } - - [System.Security.SecurityCritical] // auto-generated - internal void FromXml( SecurityElement et, PolicyLevel level, bool allowInternalOnly ) - { - if (et == null) - throw new ArgumentNullException( "et" ); - - if (!et.Tag.Equals( "PolicyStatement" )) - throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidXMLElement" ), "PolicyStatement", this.GetType().FullName ) ); - Contract.EndContractBlock(); - - m_attributes = (PolicyStatementAttribute) 0; - - String strAttributes = et.Attribute( "Attributes" ); - - if (strAttributes != null) - m_attributes = (PolicyStatementAttribute)Enum.Parse( typeof( PolicyStatementAttribute ), strAttributes ); - - lock (this) - { - m_permSet = null; - - if (level != null) - { - String permSetName = et.Attribute( "PermissionSetName" ); - - if (permSetName != null) - { - m_permSet = level.GetNamedPermissionSetInternal( permSetName ); - - if (m_permSet == null) - m_permSet = new PermissionSet( PermissionState.None ); - } - } - - - if (m_permSet == null) - { - // There is no provided level, it is not a named permission set, or - // the named permission set doesn't exist in the provided level, - // so just create the class through reflection and decode normally. - - SecurityElement e = et.SearchForChildByTag( "PermissionSet" ); - - if (e != null) - { - String className = e.Attribute( "class" ); - - if (className != null && (className.Equals( "NamedPermissionSet" ) || - className.Equals( "System.Security.NamedPermissionSet" ))) - m_permSet = new NamedPermissionSet( "DefaultName", PermissionState.None ); - else - m_permSet = new PermissionSet( PermissionState.None ); - - try - { - m_permSet.FromXml( e, allowInternalOnly, true ); - } - catch - { - // ignore any exceptions from the decode process. - // Note: we go ahead and use the permission set anyway. This should be safe since - // the decode process should never give permission beyond what a proper decode would have - // given. - } - } - else - { - throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidXML" ) ); - } - } - - if (m_permSet == null) - m_permSet = new PermissionSet( PermissionState.None ); - } - } - - - [System.Security.SecurityCritical] // auto-generated - internal void FromXml( SecurityDocument doc, int position, PolicyLevel level, bool allowInternalOnly ) - { - if (doc == null) - throw new ArgumentNullException( "doc" ); - Contract.EndContractBlock(); - - if (!doc.GetTagForElement( position ).Equals( "PolicyStatement" )) - throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidXMLElement" ), "PolicyStatement", this.GetType().FullName ) ); - - m_attributes = (PolicyStatementAttribute) 0; - - String strAttributes = doc.GetAttributeForElement( position, "Attributes" ); - - if (strAttributes != null) - m_attributes = (PolicyStatementAttribute)Enum.Parse( typeof( PolicyStatementAttribute ), strAttributes ); - - lock (this) - { - m_permSet = null; - - if (level != null) - { - String permSetName = doc.GetAttributeForElement( position, "PermissionSetName" ); - - if (permSetName != null) - { - m_permSet = level.GetNamedPermissionSetInternal( permSetName ); - - if (m_permSet == null) - m_permSet = new PermissionSet( PermissionState.None ); - } - } - - - if (m_permSet == null) - { - // There is no provided level, it is not a named permission set, or - // the named permission set doesn't exist in the provided level, - // so just create the class through reflection and decode normally. - - ArrayList childPositions = doc.GetChildrenPositionForElement( position ); - int positionPermissionSet = -1; - - for (int i = 0; i < childPositions.Count; ++i) - { - if (doc.GetTagForElement( (int)childPositions[i] ).Equals( "PermissionSet" )) - { - positionPermissionSet = (int)childPositions[i]; - } - } - - if (positionPermissionSet != -1) - { - String className = doc.GetAttributeForElement( positionPermissionSet, "class" ); - - if (className != null && (className.Equals( "NamedPermissionSet" ) || - className.Equals( "System.Security.NamedPermissionSet" ))) - m_permSet = new NamedPermissionSet( "DefaultName", PermissionState.None ); - else - m_permSet = new PermissionSet( PermissionState.None ); - - m_permSet.FromXml( doc, positionPermissionSet, allowInternalOnly ); - } - else - { - throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidXML" ) ); - } - } - - if (m_permSet == null) - m_permSet = new PermissionSet( PermissionState.None ); - } - } -#endif // FEATURE_CAS_POLICY - - [System.Runtime.InteropServices.ComVisible(false)] public override bool Equals( Object obj ) { diff --git a/src/mscorlib/src/System/Security/Policy/Site.cs b/src/mscorlib/src/System/Security/Policy/Site.cs index e7c6cd3..14a95e1 100644 --- a/src/mscorlib/src/System/Security/Policy/Site.cs +++ b/src/mscorlib/src/System/Security/Policy/Site.cs @@ -10,6 +10,7 @@ // using System; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Globalization; using System.Security.Permissions; @@ -26,7 +27,7 @@ namespace System.Security.Policy public Site(String name) { if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); Contract.EndContractBlock(); m_name = new SiteString( name ); @@ -34,7 +35,7 @@ namespace System.Security.Policy private Site(SiteString name) { - Contract.Assert(name != null); + Debug.Assert(name != null); m_name = name; } @@ -94,30 +95,6 @@ namespace System.Security.Policy return Clone(); } -#if FEATURE_CAS_POLICY - internal SecurityElement ToXml() - { - SecurityElement elem = new SecurityElement( "System.Security.Policy.Site" ); - // If you hit this assert then most likely you are trying to change the name of this class. - // This is ok as long as you change the hard coded string above and change the assert below. - Contract.Assert( this.GetType().FullName.Equals( "System.Security.Policy.Site" ), "Class name changed!" ); - - elem.AddAttribute( "version", "1" ); - - if(m_name != null) - elem.AddChild( new SecurityElement( "Name", m_name.ToString() ) ); - - return elem; - } -#endif // FEATURE_CAS_POLICY - -#if FEATURE_CAS_POLICY - public override String ToString() - { - return ToXml().ToString(); - } -#endif // FEATURE_CAS_POLICY - // INormalizeForIsolatedStorage is not implemented for startup perf // equivalent to INormalizeForIsolatedStorage.Normalize() internal Object Normalize() diff --git a/src/mscorlib/src/System/Security/Policy/StrongName.cs b/src/mscorlib/src/System/Security/Policy/StrongName.cs index c49f2b0..999b478 100644 --- a/src/mscorlib/src/System/Security/Policy/StrongName.cs +++ b/src/mscorlib/src/System/Security/Policy/StrongName.cs @@ -42,20 +42,20 @@ namespace System.Security.Policy { internal StrongName(StrongNamePublicKeyBlob blob, String name, Version version, Assembly assembly) { if (name == null) - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); if (String.IsNullOrEmpty(name)) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyStrongName")); if (blob == null) - throw new ArgumentNullException("blob"); + throw new ArgumentNullException(nameof(blob)); if (version == null) - throw new ArgumentNullException("version"); + throw new ArgumentNullException(nameof(version)); Contract.EndContractBlock(); RuntimeAssembly rtAssembly = assembly as RuntimeAssembly; if (assembly != null && rtAssembly == null) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"), "assembly"); + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"), nameof(assembly)); m_publicKeyBlob = blob; m_name = name; @@ -89,14 +89,9 @@ namespace System.Security.Policy { bool IDelayEvaluatedEvidence.IsVerified { - [System.Security.SecurityCritical] // auto-generated get { -#if FEATURE_CAS_POLICY - return m_assembly != null ? m_assembly.IsStrongNameVerified : true; -#else // !FEATURE_CAS_POLICY return true; -#endif // FEATURE_CAS_POLICY } } @@ -133,52 +128,6 @@ namespace System.Security.Policy { return Clone(); } -#if FEATURE_CAS_POLICY - internal SecurityElement ToXml() - { - SecurityElement root = new SecurityElement( "StrongName" ); - root.AddAttribute( "version", "1" ); - - if (m_publicKeyBlob != null) - root.AddAttribute( "Key", System.Security.Util.Hex.EncodeHexString( m_publicKeyBlob.PublicKey ) ); - - if (m_name != null) - root.AddAttribute( "Name", m_name ); - - if (m_version != null) - root.AddAttribute( "Version", m_version.ToString() ); - - return root; - } - - internal void FromXml (SecurityElement element) - { - if (element == null) - throw new ArgumentNullException("element"); - if (String.Compare(element.Tag, "StrongName", StringComparison.Ordinal) != 0) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidXML")); - Contract.EndContractBlock(); - - m_publicKeyBlob = null; - m_version = null; - - string key = element.Attribute("Key"); - if (key != null) - m_publicKeyBlob = new StrongNamePublicKeyBlob(System.Security.Util.Hex.DecodeHexString(key)); - - m_name = element.Attribute("Name"); - - string version = element.Attribute("Version"); - if (version != null) - m_version = new Version(version); - } - - public override String ToString() - { - return ToXml().ToString(); - } -#endif // FEATURE_CAS_POLICY - public override bool Equals( Object o ) { StrongName that = (o as StrongName); diff --git a/src/mscorlib/src/System/Security/Policy/URL.cs b/src/mscorlib/src/System/Security/Policy/URL.cs index d3ad4f8..3541124 100644 --- a/src/mscorlib/src/System/Security/Policy/URL.cs +++ b/src/mscorlib/src/System/Security/Policy/URL.cs @@ -14,6 +14,7 @@ namespace System.Security.Policy { using System.Security.Util; using UrlIdentityPermission = System.Security.Permissions.UrlIdentityPermission; using System.Runtime.Serialization; + using System.Diagnostics; using System.Diagnostics.Contracts; [Serializable] @@ -25,7 +26,7 @@ namespace System.Security.Policy { internal Url( String name, bool parsed ) { if (name == null) - throw new ArgumentNullException( "name" ); + throw new ArgumentNullException( nameof(name) ); Contract.EndContractBlock(); m_url = new URLString( name, parsed ); @@ -34,7 +35,7 @@ namespace System.Security.Policy { public Url( String name ) { if (name == null) - throw new ArgumentNullException( "name" ); + throw new ArgumentNullException( nameof(name) ); Contract.EndContractBlock(); m_url = new URLString( name ); @@ -42,7 +43,7 @@ namespace System.Security.Policy { private Url(Url url) { - Contract.Assert(url != null); + Debug.Assert(url != null); m_url = url.m_url; } @@ -87,28 +88,6 @@ namespace System.Security.Policy { return Clone(); } -#if FEATURE_CAS_POLICY - internal SecurityElement ToXml() - { - SecurityElement root = new SecurityElement( "System.Security.Policy.Url" ); - // If you hit this assert then most likely you are trying to change the name of this class. - // This is ok as long as you change the hard coded string above and change the assert below. - Contract.Assert( this.GetType().FullName.Equals( "System.Security.Policy.Url" ), "Class name changed!" ); - - root.AddAttribute( "version", "1" ); - - if (m_url != null) - root.AddChild( new SecurityElement( "Url", m_url.ToString() ) ); - - return root; - } - - public override String ToString() - { - return ToXml().ToString(); - } -#endif // FEATURE_CAS_POLICY - // INormalizeForIsolatedStorage is not implemented for startup perf // equivalent to INormalizeForIsolatedStorage.Normalize() internal Object Normalize() diff --git a/src/mscorlib/src/System/Security/Policy/Zone.cs b/src/mscorlib/src/System/Security/Policy/Zone.cs index c999abe..a9f5d84 100644 --- a/src/mscorlib/src/System/Security/Policy/Zone.cs +++ b/src/mscorlib/src/System/Security/Policy/Zone.cs @@ -9,23 +9,21 @@ // Zone is an IIdentity representing Internet/Intranet/MyComputer etc. // -namespace System.Security.Policy { +namespace System.Security.Policy +{ using System.Security.Util; using ZoneIdentityPermission = System.Security.Permissions.ZoneIdentityPermission; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Runtime.Serialization; + using System.Diagnostics; using System.Diagnostics.Contracts; [Serializable] [System.Runtime.InteropServices.ComVisible(true)] public sealed class Zone : EvidenceBase, IIdentityPermissionFactory { -#if FEATURE_CAS_POLICY - [OptionalField(VersionAdded = 2)] - private String m_url; -#endif // FEATURE_CAS_POLICY private SecurityZone m_zone; private static readonly String[] s_names = @@ -42,36 +40,10 @@ namespace System.Security.Policy { private Zone(Zone zone) { - Contract.Assert(zone != null); - -#if FEATURE_CAS_POLICY - m_url = zone.m_url; -#endif // FEATURE_CAS_POLICY + Debug.Assert(zone != null); m_zone = zone.m_zone; } -#if FEATURE_CAS_POLICY - private Zone(String url) - { - m_url = url; - m_zone = SecurityZone.NoZone; - } - - public static Zone CreateFromUrl( String url ) - { - if (url == null) - throw new ArgumentNullException( "url" ); - Contract.EndContractBlock(); - - return new Zone( url ); - } - - [System.Security.SecurityCritical] // auto-generated - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - private extern static SecurityZone _CreateFromUrl( String url ); -#endif // FEATURE_CAS_POLICY - public IPermission CreateIdentityPermission( Evidence evidence ) { return new ZoneIdentityPermission( SecurityZone ); @@ -79,14 +51,8 @@ namespace System.Security.Policy { public SecurityZone SecurityZone { - [System.Security.SecuritySafeCritical] // auto-generated get { -#if FEATURE_CAS_POLICY - if (m_url != null) - m_zone = _CreateFromUrl( m_url ); -#endif // FEATURE_CAS_POLICY - return m_zone; } } @@ -117,30 +83,6 @@ namespace System.Security.Policy { return Clone(); } -#if FEATURE_CAS_POLICY - internal SecurityElement ToXml() - { - SecurityElement elem = new SecurityElement( "System.Security.Policy.Zone" ); - // If you hit this assert then most likely you are trying to change the name of this class. - // This is ok as long as you change the hard coded string above and change the assert below. - Contract.Assert( this.GetType().FullName.Equals( "System.Security.Policy.Zone" ), "Class name changed!" ); - - elem.AddAttribute( "version", "1" ); - if (SecurityZone != SecurityZone.NoZone) - elem.AddChild( new SecurityElement( "Zone", s_names[(int)SecurityZone] ) ); - else - elem.AddChild( new SecurityElement( "Zone", s_names[s_names.Length-1] ) ); - return elem; - } -#endif // FEATURE_CAS_POLICY - -#if FEATURE_CAS_POLICY - public override String ToString() - { - return ToXml().ToString(); - } -#endif // FEATURE_CAS_POLICY - // INormalizeForIsolatedStorage is not implemented for startup perf // equivalent to INormalizeForIsolatedStorage.Normalize() internal Object Normalize() diff --git a/src/mscorlib/src/System/Security/Principal/TokenImpersonationLevel.cs b/src/mscorlib/src/System/Security/Principal/TokenImpersonationLevel.cs index fa77ac5..9eec46f 100644 --- a/src/mscorlib/src/System/Security/Principal/TokenImpersonationLevel.cs +++ b/src/mscorlib/src/System/Security/Principal/TokenImpersonationLevel.cs @@ -2,15 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - namespace System.Security.Principal { -#if !FEATURE_CORECLR - [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] -#endif - public enum TokenImpersonationLevel { + public enum TokenImpersonationLevel + { None = 0, Anonymous = 1, Identification = 2, diff --git a/src/mscorlib/src/System/Security/SafeSecurityHandles.cs b/src/mscorlib/src/System/Security/SafeSecurityHandles.cs index ea9cd4b..9a84164 100644 --- a/src/mscorlib/src/System/Security/SafeSecurityHandles.cs +++ b/src/mscorlib/src/System/Security/SafeSecurityHandles.cs @@ -11,7 +11,6 @@ namespace Microsoft.Win32.SafeHandles { // Introduce this handle to replace internal SafeTokenHandle, // which is mainly used to hold Windows thread or process access token - [SecurityCritical] public sealed class SafeAccessTokenHandle : SafeHandle { private SafeAccessTokenHandle() @@ -27,24 +26,20 @@ namespace Microsoft.Win32.SafeHandles { public static SafeAccessTokenHandle InvalidHandle { - [SecurityCritical] get { return new SafeAccessTokenHandle(IntPtr.Zero); } } public override bool IsInvalid { - [SecurityCritical] get { return handle == IntPtr.Zero || handle == new IntPtr(-1); } } - [SecurityCritical] protected override bool ReleaseHandle() { return Win32Native.CloseHandle(handle); } } - [System.Security.SecurityCritical] // auto-generated internal sealed class SafeLsaLogonProcessHandle : SafeHandleZeroOrMinusOneIsInvalid { private SafeLsaLogonProcessHandle() : base (true) {} @@ -57,7 +52,6 @@ namespace Microsoft.Win32.SafeHandles { get { return new SafeLsaLogonProcessHandle(IntPtr.Zero); } } - [System.Security.SecurityCritical] override protected bool ReleaseHandle() { // LsaDeregisterLogonProcess returns an NTSTATUS @@ -65,7 +59,6 @@ namespace Microsoft.Win32.SafeHandles { } } - [System.Security.SecurityCritical] // auto-generated internal sealed class SafeLsaMemoryHandle : SafeBuffer { private SafeLsaMemoryHandle() : base(true) {} @@ -78,14 +71,12 @@ namespace Microsoft.Win32.SafeHandles { get { return new SafeLsaMemoryHandle( IntPtr.Zero ); } } - [System.Security.SecurityCritical] override protected bool ReleaseHandle() { return Win32Native.LsaFreeMemory(handle) == 0; } } - [System.Security.SecurityCritical] // auto-generated internal sealed class SafeLsaPolicyHandle : SafeHandleZeroOrMinusOneIsInvalid { private SafeLsaPolicyHandle() : base(true) {} @@ -98,14 +89,12 @@ namespace Microsoft.Win32.SafeHandles { get { return new SafeLsaPolicyHandle( IntPtr.Zero ); } } - [System.Security.SecurityCritical] override protected bool ReleaseHandle() { return Win32Native.LsaClose(handle) == 0; } } - [System.Security.SecurityCritical] // auto-generated internal sealed class SafeLsaReturnBufferHandle : SafeBuffer { private SafeLsaReturnBufferHandle() : base (true) {} @@ -118,7 +107,6 @@ namespace Microsoft.Win32.SafeHandles { get { return new SafeLsaReturnBufferHandle(IntPtr.Zero); } } - [System.Security.SecurityCritical] override protected bool ReleaseHandle() { // LsaFreeReturnBuffer returns an NTSTATUS @@ -126,7 +114,6 @@ namespace Microsoft.Win32.SafeHandles { } } - [System.Security.SecurityCritical] // auto-generated internal sealed class SafeProcessHandle : SafeHandleZeroOrMinusOneIsInvalid { private SafeProcessHandle() : base (true) {} @@ -139,14 +126,12 @@ namespace Microsoft.Win32.SafeHandles { get { return new SafeProcessHandle(IntPtr.Zero); } } - [System.Security.SecurityCritical] override protected bool ReleaseHandle() { return Win32Native.CloseHandle(handle); } } - [System.Security.SecurityCritical] // auto-generated internal sealed class SafeThreadHandle : SafeHandleZeroOrMinusOneIsInvalid { private SafeThreadHandle() : base (true) {} @@ -155,7 +140,6 @@ namespace Microsoft.Win32.SafeHandles { SetHandle(handle); } - [System.Security.SecurityCritical] override protected bool ReleaseHandle() { return Win32Native.CloseHandle(handle); diff --git a/src/mscorlib/src/System/Security/SecurityContext.cs b/src/mscorlib/src/System/Security/SecurityContext.cs index e422a31..674c041 100644 --- a/src/mscorlib/src/System/Security/SecurityContext.cs +++ b/src/mscorlib/src/System/Security/SecurityContext.cs @@ -12,14 +12,11 @@ ** ===========================================================*/ namespace System.Security -{ +{ using Microsoft.Win32; using Microsoft.Win32.SafeHandles; using System.Threading; using System.Runtime.Remoting; -#if FEATURE_IMPERSONATION - using System.Security.Principal; -#endif using System.Collections; using System.Runtime.Serialization; using System.Security.Permissions; @@ -30,6 +27,7 @@ namespace System.Security #endif // FEATURE_CORRUPTING_EXCEPTIONS using System.Runtime.ConstrainedExecution; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; // This enum must be kept in sync with the SecurityContextSource enum in the VM @@ -46,15 +44,6 @@ namespace System.Security All = 0x3FFF } -#if FEATURE_IMPERSONATION - internal enum WindowsImpersonationFlowMode { - IMP_FASTFLOW = 0, - IMP_NOFLOW = 1, - IMP_ALWAYSFLOW = 2, - IMP_DEFAULT = IMP_FASTFLOW - } -#endif - #if FEATURE_COMPRESSEDSTACK internal struct SecurityContextSwitcher: IDisposable { @@ -62,17 +51,12 @@ namespace System.Security internal SecurityContext currSC; //current SC - SetSecurityContext that created the switcher set this on the Thread internal ExecutionContext currEC; // current ExecutionContext on Thread internal CompressedStackSwitcher cssw; -#if FEATURE_IMPERSONATION - internal WindowsImpersonationContext wic; -#endif - [System.Security.SecuritySafeCritical] // overrides public transparent member public void Dispose() { Undo(); } - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] #if FEATURE_CORRUPTING_EXCEPTIONS [HandleProcessCorruptedStateExceptions] @@ -90,7 +74,6 @@ namespace System.Security return true; } - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] #if FEATURE_CORRUPTING_EXCEPTIONS [HandleProcessCorruptedStateExceptions] @@ -104,8 +87,8 @@ namespace System.Security if (currEC != null) { - Contract.Assert(currEC == Thread.CurrentThread.GetMutableExecutionContext(), "SecurityContextSwitcher used from another thread"); - Contract.Assert(currSC == currEC.SecurityContext, "SecurityContextSwitcher context mismatch"); + Debug.Assert(currEC == Thread.CurrentThread.GetMutableExecutionContext(), "SecurityContextSwitcher used from another thread"); + Debug.Assert(currSC == currEC.SecurityContext, "SecurityContextSwitcher context mismatch"); // restore the saved security context currEC.SecurityContext = prevSC.DangerousGetRawSecurityContext(); @@ -113,26 +96,13 @@ namespace System.Security else { // caller must have already restored the ExecutionContext - Contract.Assert(Thread.CurrentThread.GetExecutionContextReader().SecurityContext.IsSame(prevSC)); + Debug.Assert(Thread.CurrentThread.GetExecutionContextReader().SecurityContext.IsSame(prevSC)); } currSC = null; // this will prevent the switcher object being used again bool bNoException = true; -#if FEATURE_IMPERSONATION - try - { - if (wic != null) - bNoException &= wic.UndoNoThrow(); - } - catch - { - // Failfast since we can't continue safely... - bNoException &= cssw.UndoNoThrow(); - System.Environment.FailFast(Environment.GetResourceString("ExecutionContext_UndoFailed")); - - } -#endif + bNoException &= cssw.UndoNoThrow(); @@ -144,15 +114,9 @@ namespace System.Security } } - public sealed class SecurityContext : IDisposable { -#if FEATURE_IMPERSONATION - // Note that only one of the following variables will be true. The way we set up the flow mode in the g_pConfig guarantees this. - static bool _LegacyImpersonationPolicy = (GetImpersonationFlowMode() == WindowsImpersonationFlowMode.IMP_NOFLOW); - static bool _alwaysFlowImpersonationPolicy = (GetImpersonationFlowMode() == WindowsImpersonationFlowMode.IMP_ALWAYSFLOW); -#endif /*========================================================================= ** Data accessed from managed code that needs to be defined in ** SecurityContextObject to maintain alignment between the two classes. @@ -160,9 +124,6 @@ namespace System.Security =========================================================================*/ private ExecutionContext _executionContext; -#if FEATURE_IMPERSONATION - private volatile WindowsIdentity _windowsIdentity; -#endif private volatile CompressedStack _compressedStack; static private volatile SecurityContext _fullTrustSC; @@ -204,7 +165,6 @@ namespace System.Security static internal SecurityContext FullTrustSecurityContext { - [System.Security.SecurityCritical] // auto-generated get { if (_fullTrustSC == null) @@ -222,27 +182,7 @@ namespace System.Security _executionContext = value; } } - -#if FEATURE_IMPERSONATION - - - internal WindowsIdentity WindowsIdentity - { - get - { - return _windowsIdentity; - } - set - { - // Note, we do not dispose of the existing windows identity, since some code such as remoting - // relies on reusing that identity. If you are not going to reuse the existing identity, then - // you should dispose of the existing identity before resetting it. - _windowsIdentity = value; - } - } -#endif // FEATURE_IMPERSONATION - internal CompressedStack CompressedStack { get @@ -258,25 +198,18 @@ namespace System.Security public void Dispose() { -#if FEATURE_IMPERSONATION - if (_windowsIdentity != null) - _windowsIdentity.Dispose(); -#endif // FEATURE_IMPERSONATION } - [System.Security.SecurityCritical] // auto-generated_required public static AsyncFlowControl SuppressFlow() { return SuppressFlow(SecurityContextDisableFlow.All); } - [System.Security.SecurityCritical] // auto-generated_required public static AsyncFlowControl SuppressFlowWindowsIdentity() { return SuppressFlow(SecurityContextDisableFlow.WI); } - [SecurityCritical] internal static AsyncFlowControl SuppressFlow(SecurityContextDisableFlow flags) { if (IsFlowSuppressed(flags)) @@ -292,7 +225,6 @@ namespace System.Security return afc; } - [SecuritySafeCritical] public static void RestoreFlow() { SecurityContext sc = Thread.CurrentThread.GetMutableExecutionContext().SecurityContext; @@ -307,13 +239,7 @@ namespace System.Security { return SecurityContext.IsFlowSuppressed(SecurityContextDisableFlow.All); } -#if FEATURE_IMPERSONATION - public static bool IsWindowsIdentityFlowSuppressed() - { - return (_LegacyImpersonationPolicy|| SecurityContext.IsFlowSuppressed(SecurityContextDisableFlow.WI)); - } -#endif - [SecuritySafeCritical] + internal static bool IsFlowSuppressed(SecurityContextDisableFlow flags) { return Thread.CurrentThread.GetExecutionContextReader().SecurityContext.IsFlowSuppressed(flags); @@ -323,7 +249,6 @@ namespace System.Security // continue past the call to SecurityContext.Run. If you change the signature to this method, or // provide an alternate way to do a SecurityContext.Run make sure to update // SecurityStackWalk::IsSpecialRunFrame in the VM to search for the new method. - [System.Security.SecurityCritical] // auto-generated_required [DynamicSecurityMethodAttribute()] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static void Run(SecurityContext securityContext, ContextCallback callback, Object state) @@ -360,7 +285,7 @@ namespace System.Security // and automatically goes away when the callback returns. WindowsIdentity.SafeRevertToSelf(ref stackMark); // Ensure we have reverted to the state we entered in. - Contract.Assert(GetCurrentWI(Thread.CurrentThread.GetExecutionContextReader()) == null); + Debug.Assert(GetCurrentWI(Thread.CurrentThread.GetExecutionContextReader()) == null); } } else @@ -369,7 +294,6 @@ namespace System.Security } } - [System.Security.SecurityCritical] // auto-generated internal static void RunInternal(SecurityContext securityContext, ContextCallback callBack, Object state) { if (cleanupCode == null) @@ -397,7 +321,6 @@ namespace System.Security } } - [System.Security.SecurityCritical] // auto-generated static internal void runTryCode(Object userData) { SecurityContextRunData rData = (SecurityContextRunData) userData; @@ -406,7 +329,6 @@ namespace System.Security } - [System.Security.SecurityCritical] // auto-generated [PrePrepareMethod] static internal void runFinallyCode(Object userData, bool exceptionThrown) { @@ -421,7 +343,6 @@ namespace System.Security // Internal API that gets called from public SetSecurityContext and from SetExecutionContext [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - [System.Security.SecurityCritical] // auto-generated [DynamicSecurityMethodAttribute()] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable internal static SecurityContextSwitcher SetSecurityContext(SecurityContext sc, SecurityContext.Reader prevSecurityContext, bool modifyCurrentExecutionContext) @@ -430,7 +351,6 @@ namespace System.Security return SetSecurityContext(sc, prevSecurityContext, modifyCurrentExecutionContext, ref stackMark); } - [System.Security.SecurityCritical] // auto-generated #if FEATURE_CORRUPTING_EXCEPTIONS [HandleProcessCorruptedStateExceptions] #endif // FEATURE_CORRUPTING_EXCEPTIONS @@ -458,22 +378,6 @@ namespace System.Security RuntimeHelpers.PrepareConstrainedRegions(); try { -#if FEATURE_IMPERSONATION - scsw.wic = null; - if (!_LegacyImpersonationPolicy) - { - if (sc.WindowsIdentity != null) - { - scsw.wic = sc.WindowsIdentity.Impersonate(ref stackMark); - } - else if ( ((_capturedFlowState & SecurityContextDisableFlow.WI) == 0) - && prevSecurityContext.WindowsIdentity != null) - { - // revert impersonation if there was no WI flow supression at capture and we're currently impersonating - scsw.wic = WindowsIdentity.SafeRevertToSelf(ref stackMark); - } - } -#endif scsw.cssw = CompressedStack.SetCompressedStack(sc.CompressedStack, prevSecurityContext.CompressedStack); } catch @@ -486,7 +390,6 @@ namespace System.Security } /// - [System.Security.SecuritySafeCritical] // auto-generated public SecurityContext CreateCopy() { if (!isNewCapture) @@ -498,11 +401,6 @@ namespace System.Security sc.isNewCapture = true; sc._disableFlow = _disableFlow; -#if FEATURE_IMPERSONATION - if (WindowsIdentity != null) - sc._windowsIdentity = new WindowsIdentity(WindowsIdentity.AccessToken); -#endif //FEATURE_IMPERSONATION - if (_compressedStack != null) sc._compressedStack = _compressedStack.CreateCopy(); @@ -510,26 +408,19 @@ namespace System.Security } /// - [System.Security.SecuritySafeCritical] // auto-generated internal SecurityContext CreateMutableCopy() { - Contract.Assert(!this.isNewCapture); + Debug.Assert(!this.isNewCapture); SecurityContext sc = new SecurityContext(); sc._disableFlow = this._disableFlow; -#if FEATURE_IMPERSONATION - if (this.WindowsIdentity != null) - sc._windowsIdentity = new WindowsIdentity(this.WindowsIdentity.AccessToken); -#endif //FEATURE_IMPERSONATION - if (this._compressedStack != null) sc._compressedStack = this._compressedStack.CreateCopy(); return sc; } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static SecurityContext Capture( ) { @@ -545,7 +436,6 @@ namespace System.Security } // create a clone from a non-existing SecurityContext - [System.Security.SecurityCritical] // auto-generated [MethodImpl(MethodImplOptions.AggressiveInlining)] static internal SecurityContext Capture(ExecutionContext.Reader currThreadEC, ref StackCrawlMark stackMark) { @@ -560,125 +450,26 @@ namespace System.Security return CaptureCore(currThreadEC, ref stackMark); } - [System.Security.SecurityCritical] // auto-generated static private SecurityContext CaptureCore(ExecutionContext.Reader currThreadEC, ref StackCrawlMark stackMark) { SecurityContext sc = new SecurityContext(); sc.isNewCapture = true; -#if FEATURE_IMPERSONATION - // Force create WindowsIdentity - if (!IsWindowsIdentityFlowSuppressed()) - { - WindowsIdentity currentIdentity = GetCurrentWI(currThreadEC); - if (currentIdentity != null) - sc._windowsIdentity = new WindowsIdentity(currentIdentity.AccessToken); - } - else - { - sc._disableFlow = SecurityContextDisableFlow.WI; - } -#endif // FEATURE_IMPERSONATION - // Force create CompressedStack sc.CompressedStack = CompressedStack.GetCompressedStack(ref stackMark); return sc; } - [System.Security.SecurityCritical] // auto-generated + static internal SecurityContext CreateFullTrustSecurityContext() { SecurityContext sc = new SecurityContext(); sc.isNewCapture = true; - -#if FEATURE_IMPERSONATION - if (IsWindowsIdentityFlowSuppressed()) - { - sc._disableFlow = SecurityContextDisableFlow.WI; - } -#endif // FEATURE_IMPERSONATION - // Force create CompressedStack sc.CompressedStack = new CompressedStack(null); return sc; } -#if FEATURE_IMPERSONATION - - static internal bool AlwaysFlowImpersonationPolicy { get { return _alwaysFlowImpersonationPolicy; } } - - // Check to see if we have a WI on the thread and return if we do - [System.Security.SecurityCritical] // auto-generated - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static internal WindowsIdentity GetCurrentWI(ExecutionContext.Reader threadEC) - { - return GetCurrentWI(threadEC, _alwaysFlowImpersonationPolicy); - } - - [System.Security.SecurityCritical] // auto-generated - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static internal WindowsIdentity GetCurrentWI(ExecutionContext.Reader threadEC, bool cachedAlwaysFlowImpersonationPolicy) - { - Contract.Assert(cachedAlwaysFlowImpersonationPolicy == _alwaysFlowImpersonationPolicy); - if (cachedAlwaysFlowImpersonationPolicy) - { - // Examine the threadtoken at the cost of a kernel call if the user has set the IMP_ALWAYSFLOW mode - return WindowsIdentity.GetCurrentInternal(TokenAccessLevels.MaximumAllowed, true); - } - - return threadEC.SecurityContext.WindowsIdentity; - } - - [System.Security.SecurityCritical] - static internal void RestoreCurrentWI(ExecutionContext.Reader currentEC, ExecutionContext.Reader prevEC, WindowsIdentity targetWI, bool cachedAlwaysFlowImpersonationPolicy) - { - Contract.Assert(currentEC.IsSame(Thread.CurrentThread.GetExecutionContextReader())); - Contract.Assert(cachedAlwaysFlowImpersonationPolicy == _alwaysFlowImpersonationPolicy); - - // NOTE: cachedAlwaysFlowImpersonationPolicy is a perf optimization to avoid always having to access a static variable here. - if (cachedAlwaysFlowImpersonationPolicy || prevEC.SecurityContext.WindowsIdentity != targetWI) - { - // - // Either we're always flowing, or the target WI was obtained from the current EC in the first place. - // - Contract.Assert(_alwaysFlowImpersonationPolicy || currentEC.SecurityContext.WindowsIdentity == targetWI); - - RestoreCurrentWIInternal(targetWI); - } - } - - [System.Security.SecurityCritical] - static private void RestoreCurrentWIInternal(WindowsIdentity targetWI) - { - int hr = Win32.RevertToSelf(); - if (hr < 0) - Environment.FailFast(Win32Native.GetMessage(hr)); - - if (targetWI != null) - { - SafeAccessTokenHandle tokenHandle = targetWI.AccessToken; - if (tokenHandle != null && !tokenHandle.IsInvalid) - { - hr = Win32.ImpersonateLoggedOnUser(tokenHandle); - if (hr < 0) - Environment.FailFast(Win32Native.GetMessage(hr)); - } - } - } - - [System.Security.SecurityCritical] // auto-generated - internal bool IsDefaultFTSecurityContext() - { - return (WindowsIdentity == null && (CompressedStack == null || CompressedStack.CompressedStackHandle == null)); - } - [System.Security.SecurityCritical] // auto-generated - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static internal bool CurrentlyInDefaultFTSecurityContext(ExecutionContext.Reader threadEC) - { - return (IsDefaultThreadSecurityInfo() && GetCurrentWI(threadEC) == null); - } -#else - internal bool IsDefaultFTSecurityContext() { return (CompressedStack == null || CompressedStack.CompressedStackHandle == null); @@ -687,16 +478,9 @@ namespace System.Security { return (IsDefaultThreadSecurityInfo()); } -#endif -#if FEATURE_IMPERSONATION - [System.Security.SecuritySafeCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - internal extern static WindowsImpersonationFlowMode GetImpersonationFlowMode(); -#endif - [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal extern static bool IsDefaultThreadSecurityInfo(); - } #endif // FEATURE_COMPRESSEDSTACK } diff --git a/src/mscorlib/src/System/Security/SecurityElement.cs b/src/mscorlib/src/System/Security/SecurityElement.cs index aa63029..f57665b 100644 --- a/src/mscorlib/src/System/Security/SecurityElement.cs +++ b/src/mscorlib/src/System/Security/SecurityElement.cs @@ -14,6 +14,7 @@ namespace System.Security using System.Globalization; using System.IO; using System.Security.Permissions; + using System.Diagnostics; using System.Diagnostics.Contracts; internal enum SecurityElementType @@ -93,23 +94,10 @@ namespace System.Security return ((SecurityElement)this).Attribute( attributeName ); } -////////////// - -#if FEATURE_CAS_POLICY - public static SecurityElement FromString( String xml ) - { - if (xml == null) - throw new ArgumentNullException( "xml" ); - Contract.EndContractBlock(); - - return new Parser( xml ).GetTopElement(); - } -#endif // FEATURE_CAS_POLICY - public SecurityElement( String tag ) { if (tag == null) - throw new ArgumentNullException( "tag" ); + throw new ArgumentNullException( nameof(tag) ); if (!IsValidTag( tag )) throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementTag" ), tag ) ); @@ -122,7 +110,7 @@ namespace System.Security public SecurityElement( String tag, String text ) { if (tag == null) - throw new ArgumentNullException( "tag" ); + throw new ArgumentNullException( nameof(tag) ); if (!IsValidTag( tag )) throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementTag" ), tag ) ); @@ -148,7 +136,7 @@ namespace System.Security set { if (value == null) - throw new ArgumentNullException( "Tag" ); + throw new ArgumentNullException( nameof(Tag) ); if (!IsValidTag( value )) throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementTag" ), value ) ); @@ -171,7 +159,7 @@ namespace System.Security Hashtable hashtable = new Hashtable( m_lAttributes.Count/2 ); int iMax = m_lAttributes.Count; - Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" ); + Debug.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" ); for (int i = 0; i < iMax; i += 2) { @@ -296,7 +284,7 @@ namespace System.Security else { int iMax = m_lAttributes.Count; - Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" ); + Debug.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" ); for (int i = 0; i < iMax; i += 2) { @@ -314,10 +302,10 @@ namespace System.Security public void AddAttribute( String name, String value ) { if (name == null) - throw new ArgumentNullException( "name" ); + throw new ArgumentNullException( nameof(name) ); if (value == null) - throw new ArgumentNullException( "value" ); + throw new ArgumentNullException( nameof(value) ); if (!IsValidAttributeName( name )) throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementName" ), name ) ); @@ -332,7 +320,7 @@ namespace System.Security public void AddChild( SecurityElement child ) { if (child == null) - throw new ArgumentNullException( "child" ); + throw new ArgumentNullException( nameof(child) ); Contract.EndContractBlock(); if (m_lChildren == null) @@ -344,7 +332,7 @@ namespace System.Security internal void AddChild( ISecurityElementFactory child ) { if (child == null) - throw new ArgumentNullException( "child" ); + throw new ArgumentNullException( nameof(child) ); Contract.EndContractBlock(); if (m_lChildren == null) @@ -356,7 +344,7 @@ namespace System.Security internal void AddChildNoDuplicates( ISecurityElementFactory child ) { if (child == null) - throw new ArgumentNullException( "child" ); + throw new ArgumentNullException( nameof(child) ); Contract.EndContractBlock(); if (m_lChildren == null) @@ -400,7 +388,7 @@ namespace System.Security else { int iMax = m_lAttributes.Count; - Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" ); + Debug.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" ); if (iMax != other.m_lAttributes.Count) return false; @@ -495,7 +483,7 @@ namespace System.Security private static String GetEscapeSequence( char c ) { int iMax = s_escapeStringPairs.Length; - Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" ); + Debug.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" ); for (int i = 0; i < iMax; i += 2) { @@ -506,7 +494,7 @@ namespace System.Security return strEscValue; } - Contract.Assert( false, "Unable to find escape sequence for this character" ); + Debug.Assert( false, "Unable to find escape sequence for this character" ); return c.ToString(); } @@ -557,7 +545,7 @@ namespace System.Security int maxCompareLength = str.Length - index; int iMax = s_escapeStringPairs.Length; - Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" ); + Debug.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" ); for (int i = 0; i < iMax; i += 2) { @@ -616,7 +604,7 @@ namespace System.Security while (true); // C# reports a warning if I leave this in, but I still kinda want to just in case. - // Contract.Assert( false, "If you got here, the execution engine or compiler is really confused" ); + // Debug.Assert( false, "If you got here, the execution engine or compiler is really confused" ); // return str; } @@ -626,11 +614,6 @@ namespace System.Security { ((StringBuilder)obj).Append( str ); } - - private static void ToStringHelperStreamWriter( Object obj, String str ) - { - ((StreamWriter)obj).Write( str ); - } public override String ToString () { @@ -641,16 +624,11 @@ namespace System.Security return sb.ToString(); } - internal void ToWriter( StreamWriter writer ) - { - ToString( "", writer, new ToStringHelperFunc( ToStringHelperStreamWriter ) ); - } - private void ToString( String indent, Object obj, ToStringHelperFunc func ) { // First add the indent - // func( obj, indent ); + // func( obj, indent ); // Add in the opening bracket and the tag. @@ -679,7 +657,7 @@ namespace System.Security func( obj, " " ); int iMax = m_lAttributes.Count; - Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" ); + Debug.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" ); for (int i = 0; i < iMax; i += 2) { @@ -770,7 +748,7 @@ namespace System.Security public String Attribute( String name ) { if (name == null) - throw new ArgumentNullException( "name" ); + throw new ArgumentNullException( nameof(name) ); Contract.EndContractBlock(); // Note: we don't check for validity here because an @@ -783,7 +761,7 @@ namespace System.Security // the one we are asked for int iMax = m_lAttributes.Count; - Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" ); + Debug.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" ); for (int i = 0; i < iMax; i += 2) { @@ -808,7 +786,7 @@ namespace System.Security // find the one are are asked for (matching tags) if (tag == null) - throw new ArgumentNullException( "tag" ); + throw new ArgumentNullException( nameof(tag) ); Contract.EndContractBlock(); // Note: we don't check for a valid tag here because @@ -829,45 +807,13 @@ namespace System.Security return null; } -#if FEATURE_CAS_POLICY - internal IPermission ToPermission(bool ignoreTypeLoadFailures) - { - IPermission ip = XMLUtil.CreatePermission( this, PermissionState.None, ignoreTypeLoadFailures ); - if (ip == null) - return null; - ip.FromXml(this); - - // Get the permission token here to ensure that the token - // type is updated appropriately now that we've loaded the type. - PermissionToken token = PermissionToken.GetToken( ip ); - Contract.Assert((token.m_type & PermissionTokenType.DontKnow) == 0, "Token type not properly assigned"); - - return ip; - } - - [System.Security.SecurityCritical] // auto-generated - internal Object ToSecurityObject() - { - switch (m_strTag) - { - case "PermissionSet": - PermissionSet pset = new PermissionSet(PermissionState.None); - pset.FromXml(this); - return pset; - - default: - return ToPermission(false); - } - } -#endif // FEATURE_CAS_POLICY - internal String SearchForTextOfLocalName(String strLocalName) { // Search on each child in order and each // child's child, depth-first if (strLocalName == null) - throw new ArgumentNullException( "strLocalName" ); + throw new ArgumentNullException( nameof(strLocalName) ); Contract.EndContractBlock(); // Note: we don't check for a valid tag here because @@ -899,7 +845,7 @@ namespace System.Security // child's child, depth-first if (tag == null) - throw new ArgumentNullException( "tag" ); + throw new ArgumentNullException( nameof(tag) ); Contract.EndContractBlock(); // Note: we don't check for a valid tag here because diff --git a/src/mscorlib/src/System/Security/SecurityException.cs b/src/mscorlib/src/System/Security/SecurityException.cs index 9fbd802..c76674c 100644 --- a/src/mscorlib/src/System/Security/SecurityException.cs +++ b/src/mscorlib/src/System/Security/SecurityException.cs @@ -34,589 +34,60 @@ namespace System.Security [Serializable] public class SecurityException : SystemException { -#if FEATURE_CAS_POLICY - private String m_debugString; // NOTE: If you change the name of this field, you'll have to update SOS as well! - private SecurityAction m_action; - [NonSerialized] private Type m_typeOfPermissionThatFailed; - private String m_permissionThatFailed; - private String m_demanded; - private String m_granted; - private String m_refused; - private String m_denied; - private String m_permitOnly; - private AssemblyName m_assemblyName; - private byte[] m_serializedMethodInfo; - private String m_strMethodInfo; - private SecurityZone m_zone; - private String m_url; - - private const String ActionName = "Action"; - private const String FirstPermissionThatFailedName = "FirstPermissionThatFailed"; - private const String DemandedName = "Demanded"; - private const String GrantedSetName = "GrantedSet"; - private const String RefusedSetName = "RefusedSet"; - private const String DeniedName = "Denied"; - private const String PermitOnlyName = "PermitOnly"; - private const String Assembly_Name = "Assembly"; - private const String MethodName_Serialized = "Method"; - private const String MethodName_String = "Method_String"; - private const String ZoneName = "Zone"; - private const String UrlName = "Url"; -#endif // #if FEATURE_CAS_POLICY - - [System.Security.SecuritySafeCritical] // auto-generated internal static string GetResString(string sResourceName) { PermissionSet.s_fullTrust.Assert(); return Environment.GetResourceString(sResourceName); } - [System.Security.SecurityCritical] // auto-generated #pragma warning disable 618 internal static Exception MakeSecurityException(AssemblyName asmName, Evidence asmEvidence, PermissionSet granted, PermissionSet refused, RuntimeMethodHandleInternal rmh, SecurityAction action, Object demand, IPermission permThatFailed) #pragma warning restore 618 { -#if FEATURE_CAS_POLICY - // See if we need to throw a HostProtectionException instead - HostProtectionPermission hostProtectionPerm = permThatFailed as HostProtectionPermission; - if(hostProtectionPerm != null) - return new HostProtectionException(GetResString("HostProtection_HostProtection"), HostProtectionPermission.protectedResources, hostProtectionPerm.Resources); - - // Produce relevant strings - String message = ""; - MethodInfo method = null; - try - { - if(granted == null && refused == null && demand == null) - { - message = GetResString("Security_NoAPTCA"); - } - else - { - if(demand != null && demand is IPermission) - message = String.Format(CultureInfo.InvariantCulture, GetResString("Security_Generic"), demand.GetType().AssemblyQualifiedName ); - else if (permThatFailed != null) - message = String.Format(CultureInfo.InvariantCulture, GetResString("Security_Generic"), permThatFailed.GetType().AssemblyQualifiedName); - else - message = GetResString("Security_GenericNoType"); - } - - method = SecurityRuntime.GetMethodInfo(rmh); - } - catch(Exception e) - { - // Environment.GetResourceString will throw if we are ReadyForAbort (thread abort). (We shouldn't do a Contract.Assert in this case or it will lock up the thread.) - if(e is System.Threading.ThreadAbortException) - throw; - } - -/* catch(System.Threading.ThreadAbortException) - { - // Environment.GetResourceString will throw if we are ReadyForAbort (thread abort). (We shouldn't do a BCLDebug.Assert in this case or it will lock up the thread.) - throw; - } - catch - { - } -*/ - // make the exception object - return new SecurityException(message, asmName, granted, refused, method, action, demand, permThatFailed, asmEvidence); -#else return new SecurityException(GetResString("Arg_SecurityException")); -#endif - } -#if FEATURE_CAS_POLICY - private static byte[] ObjectToByteArray(Object obj) - { - if(obj == null) - return null; - MemoryStream stream = new MemoryStream(); - BinaryFormatter formatter = new BinaryFormatter(); - try { - formatter.Serialize(stream, obj); - byte[] array = stream.ToArray(); - return array; - } catch (NotSupportedException) { - // Serialization of certain methods is not supported (namely - // global methods, since they have no representation outside of - // a module scope). - return null; - } - } - - private static Object ByteArrayToObject(byte[] array) - { - if(array == null || array.Length == 0) - return null; - MemoryStream stream = new MemoryStream(array); - BinaryFormatter formatter = new BinaryFormatter(); - Object obj = formatter.Deserialize(stream); - return obj; - } -#endif // FEATURE_CAS_POLICY - - public SecurityException() + public SecurityException() : base(GetResString("Arg_SecurityException")) { SetErrorCode(System.__HResults.COR_E_SECURITY); } - - public SecurityException(String message) - : base(message) - { - // This is the constructor that gets called if you Assert but don't have permission to Assert. (So don't assert in here.) - SetErrorCode(System.__HResults.COR_E_SECURITY); - } -#if FEATURE_CAS_POLICY - [System.Security.SecuritySafeCritical] // auto-generated - public SecurityException(String message, Type type ) + public SecurityException(String message) : base(message) { - PermissionSet.s_fullTrust.Assert(); - SetErrorCode(System.__HResults.COR_E_SECURITY); - m_typeOfPermissionThatFailed = type; - } - - // *** Don't use this constructor internally *** - [System.Security.SecuritySafeCritical] // auto-generated - public SecurityException(String message, Type type, String state ) - : base(message) - { - PermissionSet.s_fullTrust.Assert(); + // This is the constructor that gets called if you Assert but don't have permission to Assert. (So don't assert in here.) SetErrorCode(System.__HResults.COR_E_SECURITY); - m_typeOfPermissionThatFailed = type; - m_demanded = state; } -#endif //FEATURE_CAS_POLICY - public SecurityException(String message, Exception inner) + public SecurityException(String message, Exception inner) : base(message, inner) { SetErrorCode(System.__HResults.COR_E_SECURITY); } -#if FEATURE_CAS_POLICY - // *** Don't use this constructor internally *** - [System.Security.SecurityCritical] // auto-generated - internal SecurityException( PermissionSet grantedSetObj, PermissionSet refusedSetObj ) - : base(GetResString("Arg_SecurityException")) - { - PermissionSet.s_fullTrust.Assert(); - SetErrorCode(System.__HResults.COR_E_SECURITY); - if (grantedSetObj != null) - m_granted = grantedSetObj.ToXml().ToString(); - if (refusedSetObj != null) - m_refused = refusedSetObj.ToXml().ToString(); - } - - // *** Don't use this constructor internally *** - [System.Security.SecurityCritical] // auto-generated - internal SecurityException( String message, PermissionSet grantedSetObj, PermissionSet refusedSetObj ) - : base(message) - { - PermissionSet.s_fullTrust.Assert(); - SetErrorCode(System.__HResults.COR_E_SECURITY); - if (grantedSetObj != null) - m_granted = grantedSetObj.ToXml().ToString(); - if (refusedSetObj != null) - m_refused = refusedSetObj.ToXml().ToString(); - } - - [System.Security.SecuritySafeCritical] // auto-generated - protected SecurityException(SerializationInfo info, StreamingContext context) : base (info, context) - { - if (info==null) - throw new ArgumentNullException("info"); - Contract.EndContractBlock(); - - try - { - m_action = (SecurityAction)info.GetValue(ActionName, typeof(SecurityAction)); - m_permissionThatFailed = (String)info.GetValueNoThrow(FirstPermissionThatFailedName, typeof(String)); - m_demanded = (String)info.GetValueNoThrow(DemandedName, typeof(String)); - m_granted = (String)info.GetValueNoThrow(GrantedSetName, typeof(String)); - m_refused = (String)info.GetValueNoThrow(RefusedSetName, typeof(String)); - m_denied = (String)info.GetValueNoThrow(DeniedName, typeof(String)); - m_permitOnly = (String)info.GetValueNoThrow(PermitOnlyName, typeof(String)); - m_assemblyName = (AssemblyName)info.GetValueNoThrow(Assembly_Name, typeof(AssemblyName)); - m_serializedMethodInfo = (byte[])info.GetValueNoThrow(MethodName_Serialized, typeof(byte[])); - m_strMethodInfo = (String)info.GetValueNoThrow(MethodName_String, typeof(String)); - m_zone = (SecurityZone)info.GetValue(ZoneName, typeof(SecurityZone)); - m_url = (String)info.GetValueNoThrow(UrlName, typeof(String)); - } - catch - { - m_action = 0; - m_permissionThatFailed = ""; - m_demanded = ""; - m_granted = ""; - m_refused = ""; - m_denied = ""; - m_permitOnly = ""; - m_assemblyName = null; - m_serializedMethodInfo = null; - m_strMethodInfo = null; - m_zone = SecurityZone.NoZone; - m_url = ""; - } - } - - // ------------------------------------------ - // | For failures due to insufficient grant | - // ------------------------------------------ - [System.Security.SecuritySafeCritical] // auto-generated - public SecurityException(string message, AssemblyName assemblyName, PermissionSet grant, PermissionSet refused, MethodInfo method, SecurityAction action, Object demanded, IPermission permThatFailed, Evidence evidence) - : base(message) - { - PermissionSet.s_fullTrust.Assert(); - SetErrorCode(System.__HResults.COR_E_SECURITY); - Action = action; - if(permThatFailed != null) - m_typeOfPermissionThatFailed = permThatFailed.GetType(); - FirstPermissionThatFailed = permThatFailed; - Demanded = demanded; - m_granted = (grant == null ? "" : grant.ToXml().ToString()); - m_refused = (refused == null ? "" : refused.ToXml().ToString()); - m_denied = ""; - m_permitOnly = ""; - m_assemblyName = assemblyName; - Method = method; - m_url = ""; - m_zone = SecurityZone.NoZone; - if(evidence != null) - { - Url url = evidence.GetHostEvidence(); - if(url != null) - m_url = url.GetURLString().ToString(); - Zone zone = evidence.GetHostEvidence(); - if(zone != null) - m_zone = zone.SecurityZone; - } - m_debugString = this.ToString(true, false); - } - - // ------------------------------------------ - // | For failures due to deny or PermitOnly | - // ------------------------------------------ - [System.Security.SecuritySafeCritical] // auto-generated - public SecurityException(string message, Object deny, Object permitOnly, MethodInfo method, Object demanded, IPermission permThatFailed) - : base(message) - { - PermissionSet.s_fullTrust.Assert(); - SetErrorCode(System.__HResults.COR_E_SECURITY); - Action = SecurityAction.Demand; - if(permThatFailed != null) - m_typeOfPermissionThatFailed = permThatFailed.GetType(); - FirstPermissionThatFailed = permThatFailed; - Demanded = demanded; - m_granted = ""; - m_refused = ""; - DenySetInstance = deny; - PermitOnlySetInstance = permitOnly; - m_assemblyName = null; - Method = method; - m_zone = SecurityZone.NoZone; - m_url = ""; - m_debugString = this.ToString(true, false); - } - - - - - - - - - - - - [System.Runtime.InteropServices.ComVisible(false)] - public SecurityAction Action - { - get - { - return m_action; - } - - set - { - m_action = value; - } - } - - public Type PermissionType - { - [System.Security.SecuritySafeCritical] // auto-generated - get - { - if(m_typeOfPermissionThatFailed == null) - { - Object ob = XMLUtil.XmlStringToSecurityObject(m_permissionThatFailed); - if(ob == null) - ob = XMLUtil.XmlStringToSecurityObject(m_demanded); - if(ob != null) - m_typeOfPermissionThatFailed = ob.GetType(); - } - return m_typeOfPermissionThatFailed; - } - - set - { - m_typeOfPermissionThatFailed = value; - } - } - - public IPermission FirstPermissionThatFailed - { - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] - get - { - return (IPermission)XMLUtil.XmlStringToSecurityObject(m_permissionThatFailed); - } - - set - { - m_permissionThatFailed = XMLUtil.SecurityObjectToXmlString(value); - } - } - - public String PermissionState - { - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] - get - { - return m_demanded; - } - - set - { - m_demanded = value; - } - } - - [System.Runtime.InteropServices.ComVisible(false)] - public Object Demanded - { - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] - get - { - return XMLUtil.XmlStringToSecurityObject(m_demanded); - } - - set - { - m_demanded = XMLUtil.SecurityObjectToXmlString(value); - } - } - - public String GrantedSet - { - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] - get - { - return m_granted; - } - - set - { - m_granted = value; - } - } - - public String RefusedSet - { - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] - get - { - return m_refused; - } - - set - { - m_refused = value; - } - } - - [System.Runtime.InteropServices.ComVisible(false)] - public Object DenySetInstance - { - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] - get - { - return XMLUtil.XmlStringToSecurityObject(m_denied); - } - - set - { - m_denied = XMLUtil.SecurityObjectToXmlString(value); - } - } - - [System.Runtime.InteropServices.ComVisible(false)] - public Object PermitOnlySetInstance - { - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] - get - { - return XMLUtil.XmlStringToSecurityObject(m_permitOnly); - } - - set - { - m_permitOnly = XMLUtil.SecurityObjectToXmlString(value); - } - } - - [System.Runtime.InteropServices.ComVisible(false)] - public AssemblyName FailedAssemblyInfo - { - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] - get - { - return m_assemblyName; - } - - set - { - m_assemblyName = value; - } - } - - private MethodInfo getMethod() - { - return (MethodInfo)ByteArrayToObject(m_serializedMethodInfo); - } - - [System.Runtime.InteropServices.ComVisible(false)] - public MethodInfo Method - { - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] - get - { - return getMethod(); - } - - set - { - RuntimeMethodInfo m = value as RuntimeMethodInfo; - m_serializedMethodInfo = ObjectToByteArray(m); - if (m != null) - { - m_strMethodInfo = m.ToString(); - } - } - } - - public SecurityZone Zone - { - get - { - return m_zone; - } - - set - { - m_zone = value; - } - } - - public String Url - { - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] - get - { - return m_url; - } - - set - { - m_url = value; - } - } - - private void ToStringHelper(StringBuilder sb, String resourceString, Object attr) - { - if (attr == null) - return; - String attrString = attr as String; - if (attrString == null) - attrString = attr.ToString(); - if (attrString.Length == 0) - return; - sb.Append(Environment.NewLine); - sb.Append(GetResString(resourceString)); - sb.Append(Environment.NewLine); - sb.Append(attrString); - } - - [System.Security.SecurityCritical] // auto-generated - private String ToString(bool includeSensitiveInfo, bool includeBaseInfo) - { - PermissionSet.s_fullTrust.Assert(); - StringBuilder sb = new StringBuilder(); - - if(includeBaseInfo) - sb.Append(base.ToString()); - if(Action > 0) - ToStringHelper(sb, "Security_Action", Action); - ToStringHelper(sb, "Security_TypeFirstPermThatFailed", PermissionType); - if(includeSensitiveInfo) - { - ToStringHelper(sb, "Security_FirstPermThatFailed", m_permissionThatFailed); - ToStringHelper(sb, "Security_Demanded", m_demanded); - ToStringHelper(sb, "Security_GrantedSet", m_granted); - ToStringHelper(sb, "Security_RefusedSet", m_refused); - ToStringHelper(sb, "Security_Denied", m_denied); - ToStringHelper(sb, "Security_PermitOnly", m_permitOnly); - ToStringHelper(sb, "Security_Assembly", m_assemblyName); - ToStringHelper(sb, "Security_Method", m_strMethodInfo); - } - if(m_zone != SecurityZone.NoZone) - ToStringHelper(sb, "Security_Zone", m_zone); - if(includeSensitiveInfo) - ToStringHelper(sb, "Security_Url", m_url); - return sb.ToString(); - } -#else // FEATURE_CAS_POLICY - internal SecurityException( PermissionSet grantedSetObj, PermissionSet refusedSetObj ) + internal SecurityException(PermissionSet grantedSetObj, PermissionSet refusedSetObj) : this(){} #pragma warning disable 618 internal SecurityException(string message, AssemblyName assemblyName, PermissionSet grant, PermissionSet refused, MethodInfo method, SecurityAction action, Object demanded, IPermission permThatFailed, Evidence evidence) #pragma warning restore 618 : this(){} - + internal SecurityException(string message, Object deny, Object permitOnly, MethodInfo method, Object demanded, IPermission permThatFailed) : this(){} - [System.Security.SecuritySafeCritical] // auto-generated protected SecurityException(SerializationInfo info, StreamingContext context) : base(info, context) { if (info == null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); } - public override String ToString() - { - return base.ToString(); - } - -#endif // FEATURE_CAS_POLICY + public override String ToString() + { + return base.ToString(); + } - [System.Security.SecurityCritical] // auto-generated private bool CanAccessSensitiveInfo() { bool retVal = false; @@ -627,41 +98,46 @@ namespace System.Security #pragma warning restore 618 retVal = true; } - catch(SecurityException) + catch (SecurityException) { } return retVal; - } -#if FEATURE_CAS_POLICY - [System.Security.SecuritySafeCritical] // auto-generated - public override String ToString() - { - return ToString(CanAccessSensitiveInfo(), true); } -#endif //FEATURE_CAS_POLICY - [System.Security.SecurityCritical] // auto-generated_required + public override void GetObjectData(SerializationInfo info, StreamingContext context) { - if (info==null) - throw new ArgumentNullException("info"); + if (info == null) + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); - base.GetObjectData( info, context ); -#if FEATURE_CAS_POLICY + base.GetObjectData(info, context); + } - info.AddValue(ActionName, m_action, typeof(SecurityAction)); - info.AddValue(FirstPermissionThatFailedName, m_permissionThatFailed, typeof(String)); - info.AddValue(DemandedName, m_demanded, typeof(String)); - info.AddValue(GrantedSetName, m_granted, typeof(String)); - info.AddValue(RefusedSetName, m_refused, typeof(String)); - info.AddValue(DeniedName, m_denied, typeof(String)); - info.AddValue(PermitOnlyName, m_permitOnly, typeof(String)); - info.AddValue(Assembly_Name, m_assemblyName, typeof(AssemblyName)); - info.AddValue(MethodName_Serialized, m_serializedMethodInfo, typeof(byte[])); - info.AddValue(MethodName_String, m_strMethodInfo, typeof(String)); - info.AddValue(ZoneName, m_zone, typeof(SecurityZone)); - info.AddValue(UrlName, m_url, typeof(String)); -#endif // FEATURE_CAS_POLICY + // Stubs for surface area compatibility only + public SecurityException(String message, Type type) + : base(message) + { + SetErrorCode(System.__HResults.COR_E_SECURITY); + PermissionType = type; } + + public SecurityException(string message, System.Type type, string state) + : base(message) + { + SetErrorCode(System.__HResults.COR_E_SECURITY); + PermissionType = type; + PermissionState = state; + } + + public object Demanded { get; set; } + public object DenySetInstance { get; set; } + public System.Reflection.AssemblyName FailedAssemblyInfo { get; set; } + public string GrantedSet { get; set; } + public System.Reflection.MethodInfo Method { get; set; } + public string PermissionState { get; set; } + public System.Type PermissionType { get; set; } + public object PermitOnlySetInstance { get; set; } + public string RefusedSet { get; set; } + public string Url { get; set; } } } diff --git a/src/mscorlib/src/System/Security/SecurityManager.cs b/src/mscorlib/src/System/Security/SecurityManager.cs index 5c46dfc..933fe0b 100644 --- a/src/mscorlib/src/System/Security/SecurityManager.cs +++ b/src/mscorlib/src/System/Security/SecurityManager.cs @@ -2,32 +2,17 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -// // // The SecurityManager class provides a general purpose API for interacting // with the security system. // -namespace System.Security { +namespace System.Security +{ using System; - using System.Security.Util; - using System.Security.Policy; using System.Security.Permissions; - using System.Collections; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; -#if FEATURE_CLICKONCE - using System.Runtime.Hosting; -#endif // FEATURE_CLICKONCE - using System.Text; - using System.Threading; - using System.Reflection; - using System.IO; - using System.Globalization; - using System.Runtime.Versioning; - using System.Diagnostics.Contracts; [Serializable] [System.Runtime.InteropServices.ComVisible(true)] @@ -40,504 +25,8 @@ namespace System.Security { } [System.Runtime.InteropServices.ComVisible(true)] - static public class SecurityManager { -#if FEATURE_CAS_POLICY - private static volatile SecurityPermission executionSecurityPermission = null; - - private static PolicyManager polmgr = new PolicyManager(); - internal static PolicyManager PolicyManager { - get { - return polmgr; - } - } - - // - // Public APIs - // - [System.Security.SecuritySafeCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - [Obsolete("IsGranted is obsolete and will be removed in a future release of the .NET Framework. Please use the PermissionSet property of either AppDomain or Assembly instead.")] - public static bool IsGranted( IPermission perm ) - { - if (perm == null) - return true; - - PermissionSet granted = null, denied = null; - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - GetGrantedPermissions( JitHelpers.GetObjectHandleOnStack(ref granted), - JitHelpers.GetObjectHandleOnStack(ref denied), - JitHelpers.GetStackCrawlMarkHandle(ref stackMark) ); - return granted.Contains( perm ) && (denied == null || !denied.Contains( perm )); - } - - // Get a sandbox permission set that the CLR considers safe to grant an application with the given - // evidence. Note that this API is not a policy API, but rather a host helper API so that a host can - // determine if an application's requested permission set is reasonable. This is esentially just a - // hard coded mapping of Zone -> Sandbox and is not configurable in any way. - public static PermissionSet GetStandardSandbox(Evidence evidence) - { - if (evidence == null) - throw new ArgumentNullException("evidence"); - Contract.EndContractBlock(); - - // - // The top-level switch for grant set is based upon Zone - // MyComputer -> FullTrust - // Intranet -> LocalIntranet - // Trusted -> Internet - // Internet -> Internet - // All else -> Nothing - // - // Both the Internet and LocalIntranet zones can have permission set extensions applied to them - // if there is Activation. - // - - Zone zone = evidence.GetHostEvidence(); - if (zone == null) - { - return new PermissionSet(PermissionState.None); - } -#if FEATURE_CAS_POLICY - else if (zone.SecurityZone == SecurityZone.MyComputer) - { - return new PermissionSet(PermissionState.Unrestricted); - } - else if (zone.SecurityZone == SecurityZone.Intranet) - { - PermissionSet intranetGrantSet = BuiltInPermissionSets.LocalIntranet; - - // We also need to add in same site web and file IO permission - PolicyStatement webPolicy = - new NetCodeGroup(new AllMembershipCondition()).Resolve(evidence); - PolicyStatement filePolicy = - new FileCodeGroup(new AllMembershipCondition(), FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery).Resolve(evidence); - - if (webPolicy != null) - { - intranetGrantSet.InplaceUnion(webPolicy.PermissionSet); - } - if (filePolicy != null) - { - intranetGrantSet.InplaceUnion(filePolicy.PermissionSet); - } - - return intranetGrantSet; - } - else if (zone.SecurityZone == SecurityZone.Internet || - zone.SecurityZone == SecurityZone.Trusted) - { - PermissionSet internetGrantSet = BuiltInPermissionSets.Internet; - - // We also need to add in same site web permission - PolicyStatement webPolicy = - new NetCodeGroup(new AllMembershipCondition()).Resolve(evidence); - - if (webPolicy != null) - { - internetGrantSet.InplaceUnion(webPolicy.PermissionSet); - } - - return internetGrantSet; - } -#endif // FEATURE_CAS_POLICY - else - { - return new PermissionSet(PermissionState.None); - } - } - - /// - [System.Security.SecurityCritical] // auto-generated_required - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - static public void GetZoneAndOrigin( out ArrayList zone, out ArrayList origin ) - { - StackCrawlMark mark = StackCrawlMark.LookForMyCaller; - CodeAccessSecurityEngine.GetZoneAndOrigin( ref mark, out zone, out origin ); - } - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlPolicy )] - [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - static public PolicyLevel LoadPolicyLevelFromFile(string path, PolicyLevelType type) - { - if (path == null) - throw new ArgumentNullException( "path" ); - Contract.EndContractBlock(); - - if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit")); - } - - // We need to retain V1.x compatibility by throwing the same exception type. - if (!File.InternalExists(path)) - throw new ArgumentException( Environment.GetResourceString("Argument_PolicyFileDoesNotExist")); - - String fullPath = Path.GetFullPath( path ); - - FileIOPermission perm = new FileIOPermission( PermissionState.None ); - perm.AddPathList( FileIOPermissionAccess.Read, fullPath ); - perm.AddPathList( FileIOPermissionAccess.Write, fullPath ); - perm.Demand(); - - using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) { - using (StreamReader reader = new StreamReader(stream)) { - return LoadPolicyLevelFromStringHelper(reader.ReadToEnd(), path, type); - } - } - } - - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlPolicy )] - [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - static public PolicyLevel LoadPolicyLevelFromString(string str, PolicyLevelType type) - { - return LoadPolicyLevelFromStringHelper(str, null, type); - } - - private static PolicyLevel LoadPolicyLevelFromStringHelper (string str, string path, PolicyLevelType type) - { - if (str == null) - throw new ArgumentNullException( "str" ); - Contract.EndContractBlock(); - - PolicyLevel level = new PolicyLevel(type, path); - - Parser parser = new Parser( str ); - SecurityElement elRoot = parser.GetTopElement(); - if (elRoot == null) - throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Policy_BadXml" ), "configuration" ) ); - - SecurityElement elMscorlib = elRoot.SearchForChildByTag( "mscorlib" ); - if (elMscorlib == null) - throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Policy_BadXml" ), "mscorlib" ) ); - - SecurityElement elSecurity = elMscorlib.SearchForChildByTag( "security" ); - if (elSecurity == null) - throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Policy_BadXml" ), "security" ) ); - - SecurityElement elPolicy = elSecurity.SearchForChildByTag( "policy" ); - if (elPolicy == null) - throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Policy_BadXml" ), "policy" ) ); - - SecurityElement elPolicyLevel = elPolicy.SearchForChildByTag( "PolicyLevel" ); - if (elPolicyLevel != null) - level.FromXml( elPolicyLevel ); - else - throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Policy_BadXml" ), "PolicyLevel" ) ); - - return level; - } - - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlPolicy )] - [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - static public void SavePolicyLevel( PolicyLevel level ) - { - if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit")); - } - - PolicyManager.EncodeLevel( level ); - } - - [System.Security.SecuritySafeCritical] // auto-generated - [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - static public PermissionSet ResolvePolicy(Evidence evidence, - PermissionSet reqdPset, - PermissionSet optPset, - PermissionSet denyPset, - out PermissionSet denied) - { - if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit")); - } - - return ResolvePolicy(evidence, reqdPset, optPset, denyPset, out denied, true); - } - - [System.Security.SecuritySafeCritical] // auto-generated - [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - static public PermissionSet ResolvePolicy(Evidence evidence) - { - if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit")); - } - - // If we aren't passed any evidence, just make an empty object - if (evidence == null) - { - evidence = new Evidence(); - } - - return polmgr.Resolve(evidence); - } - - [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - static public PermissionSet ResolvePolicy( Evidence[] evidences ) - { - if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit")); - } - - if (evidences == null || evidences.Length == 0) - evidences = new Evidence[] { null }; - - PermissionSet retval = ResolvePolicy( evidences[0] ); - if (retval == null) - return null; - - for (int i = 1; i < evidences.Length; ++i) - { - retval = retval.Intersect( ResolvePolicy( evidences[i] ) ); - if (retval == null || retval.IsEmpty()) - return retval; - } - - return retval; - } - -#if FEATURE_CAS_POLICY - // Determine if the current thread would require a security context capture if the security state of - // the thread needs to be re-created at a later point in time. This can be used, for instance, if - // sensitive data is being obtained after security demands succeed, and that data is to be cached. - // If there is an Assert up the stack, then we wouldn't want to cache the data without capturing the - // corresponding security context to go along with it - otherwise we risk leaking data obtained - // under an assert to code which may no longer be running with that assert in place. - // - // A return value of false indicates that the CLR guarantees all of the following conditions are true: - // 1. No partial trust AppDomains are on the stack - // 2. No partial trust assemblies are on the stack - // 3. There are no currently active PermitOnly or Deny modifiers on the stack - // - // A return value of true means only that the CLR cannot guarantee that all of the conditions are - // true, and not that one of the conditions really is false. - // - // IMPORTANT: The above means is only reliable in the false return case. If we say that the thread - // does not require a context capture, then that answer is guaranteed to be correct. However, we may - // say that the thread does require a capture when it does not actually strictly need to capture the - // state. This is fine, as being overly conservative when capturing context will not lead to - // security holes; being overly agresssive in avoding the capture could lead to holes however. - // - // This API is SecurityCritical because its main use is to optimize away unnecessary security - // context captures, which means that the code using it is security sensitive and needs to be audited. - [SecurityCritical] - public static bool CurrentThreadRequiresSecurityContextCapture() - { - // If we know that the thread is not made up of entirely full trust code, and that there are no - // security stack modifiers on the thread, then there is no need to capture a security context. - return !CodeAccessSecurityEngine.QuickCheckForAllDemands(); - } -#endif // FEATURE_CAS_POLICY - - // - // This method resolves the policy for the specified evidence, but it - // ignores the AppDomain level even when one is available in the current policy. - // - - [System.Security.SecuritySafeCritical] // auto-generated - [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public static PermissionSet ResolveSystemPolicy (Evidence evidence) - { - if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit")); - } - - if (PolicyManager.IsGacAssembly(evidence)) - { - return new PermissionSet(PermissionState.Unrestricted); - } - - return polmgr.CodeGroupResolve(evidence, true); - } - - [System.Security.SecuritySafeCritical] // auto-generated - [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - static public IEnumerator ResolvePolicyGroups(Evidence evidence) - { - if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit")); - } - - return polmgr.ResolveCodeGroups(evidence); - } - - [System.Security.SecuritySafeCritical] // auto-generated - [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public static IEnumerator PolicyHierarchy() - { - if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit")); - } - - return polmgr.PolicyHierarchy(); - } - - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlPolicy )] - [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public static void SavePolicy() - { - if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit")); - } - - polmgr.Save(); - } - - - [System.Security.SecurityCritical] // auto-generated - private static PermissionSet ResolveCasPolicy(Evidence evidence, - PermissionSet reqdPset, - PermissionSet optPset, - PermissionSet denyPset, - out PermissionSet denied, - out int securitySpecialFlags, - bool checkExecutionPermission) - { - Contract.Assert(AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled); - - CodeAccessPermission.Assert(true); - - PermissionSet granted = ResolvePolicy(evidence, - reqdPset, - optPset, - denyPset, - out denied, - checkExecutionPermission); - - securitySpecialFlags = SecurityManager.GetSpecialFlags(granted, denied); - return granted; - } - - [System.Security.SecurityCritical] // auto-generated - static private PermissionSet ResolvePolicy(Evidence evidence, - PermissionSet reqdPset, - PermissionSet optPset, - PermissionSet denyPset, - out PermissionSet denied, - bool checkExecutionPermission) - { - Contract.Assert(AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled); - - if (executionSecurityPermission == null) - executionSecurityPermission = new SecurityPermission(SecurityPermissionFlag.Execution); - - PermissionSet requested = null; - PermissionSet optional; - PermissionSet allowed; - - Exception savedException = null; - - // We don't want to recurse back into here as a result of a - // stackwalk during resolution. So simply assert full trust (this - // implies that custom permissions cannot use any permissions that - // don't implement IUnrestrictedPermission. - // PermissionSet.s_fullTrust.Assert(); - - // The requested set is the union of the minimal request and the - // optional request. Minimal request defaults to empty, optional - // is "AllPossible" (includes any permission that can be defined) - // which is symbolized by null. - optional = optPset; - - if (reqdPset == null) - requested = optional; - else - // If optional is null, the requested set becomes null/"AllPossible". - requested = optional == null ? null : reqdPset.Union(optional); - - // Make sure that the right to execute is requested (if this feature is - // enabled). - - if (requested != null && !requested.IsUnrestricted()) - requested.AddPermission( executionSecurityPermission ); - - // If we aren't passed any evidence, just make an empty object - if (evidence == null) - { - evidence = new Evidence(); - } - - allowed = polmgr.Resolve(evidence); - // Intersect the grant with the RequestOptional - if (requested != null) - allowed.InplaceIntersect(requested); - - // Check that we were granted the right to execute. - if (checkExecutionPermission) - { - if (!allowed.Contains(executionSecurityPermission) || - (denyPset != null && denyPset.Contains(executionSecurityPermission))) - { - throw new PolicyException(Environment.GetResourceString("Policy_NoExecutionPermission"), - System.__HResults.CORSEC_E_NO_EXEC_PERM, - savedException); - } - } - - // Check that we were granted at least the minimal set we asked for. Do - // this before pruning away any overlap with the refused set so that - // users have the flexability of defining minimal permissions that are - // only expressable as set differences (e.g. allow access to "C:\" but - // disallow "C:\Windows"). - if (reqdPset != null && !reqdPset.IsSubsetOf(allowed)) - { - BCLDebug.Assert(AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled, "Evaluating assembly level declarative security without legacy CAS policy enabled"); - throw new PolicyException(Environment.GetResourceString( "Policy_NoRequiredPermission" ), - System.__HResults.CORSEC_E_MIN_GRANT_FAIL, - savedException ); - } - - // Remove any granted permissions that are safe subsets of some denied - // permission. The remaining denied permissions (if any) are returned - // along with the modified grant set for use in checks. - if (denyPset != null) - { - BCLDebug.Assert(AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled, "Evaluating assembly level declarative security without legacy CAS policy enabled"); - denied = denyPset.Copy(); - allowed.MergeDeniedSet(denied); - if (denied.IsEmpty()) - denied = null; - } - else - denied = null; - - allowed.IgnoreTypeLoadFailures = true; - - return allowed; - } - - [Obsolete("Because execution permission checks can no longer be turned off, the CheckExecutionRights property no longer has any effect.")] - static public bool CheckExecutionRights - { - get { return true; } - - set - { - // The setter for this property is a no-op since execution checking can no longer be turned off - } - } - - [Obsolete("Because security can no longer be turned off, the SecurityEnabled property no longer has any effect.")] - public static bool SecurityEnabled - { - get { return true; } - - set - { - // The setter for this property is a no-op since security cannot be turned off - } - } -#endif // #if FEATURE_CAS_POLICY - + static public class SecurityManager + { private static int[][] s_BuiltInPermissionIndexMap = { new int[] { BuiltInPermissionIndex.EnvironmentPermissionIndex, (int) PermissionType.EnvironmentPermission }, new int[] { BuiltInPermissionIndex.FileDialogPermissionIndex, (int) PermissionType.FileDialogPermission }, @@ -653,17 +142,14 @@ namespace System.Security { return flags; } #pragma warning restore 618 - - [System.Security.SecurityCritical] // auto-generated + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern bool IsSameType(String strLeft, String strRight); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool _SetThreadSecurity(bool bThreadSecurity); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern void GetGrantedPermissions(ObjectHandleOnStack retGranted, ObjectHandleOnStack retDenied, StackCrawlMarkHandle stackMark); diff --git a/src/mscorlib/src/System/Security/SecurityRuntime.cs b/src/mscorlib/src/System/Security/SecurityRuntime.cs index 9d776af..d037fe9 100644 --- a/src/mscorlib/src/System/Security/SecurityRuntime.cs +++ b/src/mscorlib/src/System/Security/SecurityRuntime.cs @@ -4,7 +4,8 @@ // -namespace System.Security { +namespace System.Security +{ using System; using System.Globalization; using System.Threading; @@ -26,7 +27,6 @@ namespace System.Security { // // Internal only, do not doc. // - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern FrameSecurityDescriptor GetSecurityObjectForFrame(ref StackCrawlMark stackMark, @@ -37,7 +37,6 @@ namespace System.Security { internal const bool StackHalt = false; // this method is a big perf hit, so don't call unnecessarily - [System.Security.SecurityCritical] // auto-generated internal static MethodInfo GetMethodInfo(RuntimeMethodHandleInternal rmh) { if (rmh.IsNullHandle()) @@ -60,7 +59,6 @@ namespace System.Security { #endif } - [System.Security.SecurityCritical] // auto-generated private static bool FrameDescSetHelper(FrameSecurityDescriptor secDesc, PermissionSet demandSet, out PermissionSet alteredDemandSet, @@ -69,7 +67,6 @@ namespace System.Security { return secDesc.CheckSetDemand(demandSet, out alteredDemandSet, rmh); } - [System.Security.SecurityCritical] // auto-generated private static bool FrameDescHelper(FrameSecurityDescriptor secDesc, IPermission demandIn, PermissionToken permToken, @@ -79,7 +76,6 @@ namespace System.Security { } #if FEATURE_COMPRESSEDSTACK - [System.Security.SecurityCritical] private static bool CheckDynamicMethodSetHelper(System.Reflection.Emit.DynamicResolver dynamicResolver, PermissionSet demandSet, out PermissionSet alteredDemandSet, @@ -99,7 +95,6 @@ namespace System.Security { return result; } - [System.Security.SecurityCritical] private static bool CheckDynamicMethodHelper(System.Reflection.Emit.DynamicResolver dynamicResolver, IPermission demandIn, PermissionToken permToken, @@ -122,176 +117,41 @@ namespace System.Security { // // API for PermissionSets // - - [System.Security.SecurityCritical] // auto-generated + internal static void Assert(PermissionSet permSet, ref StackCrawlMark stackMark) { -#if FEATURE_CAS_POLICY - // Note: if the "AssertPermission" is not a permission that implements IUnrestrictedPermission - // you need to change the fourth parameter to a zero. - FrameSecurityDescriptor secObj = CodeAccessSecurityEngine.CheckNReturnSO( - CodeAccessSecurityEngine.AssertPermissionToken, - CodeAccessSecurityEngine.AssertPermission, - ref stackMark, - 1 ); - - Contract.Assert(secObj != null,"Failure in SecurityRuntime.Assert() - secObj != null"); - if (secObj == null) - { - // Security: REQ_SQ flag is missing. Bad compiler ? - System.Environment.FailFast(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor")); - } - else - { - if (secObj.HasImperativeAsserts()) - throw new SecurityException( Environment.GetResourceString( "Security_MustRevertOverride" ) ); - - secObj.SetAssert(permSet); - } -#endif // FEATURE_CAS_POLICY } - - [System.Security.SecurityCritical] // auto-generated + internal static void AssertAllPossible(ref StackCrawlMark stackMark) { -#if FEATURE_CAS_POLICY - FrameSecurityDescriptor secObj = - SecurityRuntime.GetSecurityObjectForFrame(ref stackMark, true); - - Contract.Assert(secObj != null, "Failure in SecurityRuntime.AssertAllPossible() - secObj != null"); - if (secObj == null) - { - // Security: REQ_SQ flag is missing. Bad compiler ? - System.Environment.FailFast(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor")); - } - else - { - if (secObj.GetAssertAllPossible()) - throw new SecurityException( Environment.GetResourceString( "Security_MustRevertOverride" ) ); - - secObj.SetAssertAllPossible(); - } -#endif // FEATURE_CAS_POLICY } - - [System.Security.SecurityCritical] // auto-generated + internal static void Deny(PermissionSet permSet, ref StackCrawlMark stackMark) { -#if FEATURE_CAS_POLICY - // Deny is only valid in legacy mode - if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_CasDeny")); - } - - FrameSecurityDescriptor secObj = - SecurityRuntime.GetSecurityObjectForFrame(ref stackMark, true); - - Contract.Assert(secObj != null, "Failure in SecurityRuntime.Deny() - secObj != null"); - if (secObj == null) - { - // Security: REQ_SQ flag is missing. Bad compiler ? - System.Environment.FailFast(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor")); - } - else - { - if (secObj.HasImperativeDenials()) - throw new SecurityException( Environment.GetResourceString( "Security_MustRevertOverride" ) ); - - secObj.SetDeny(permSet); - } -#endif // FEATURE_CAS_POLICY } - - [System.Security.SecurityCritical] // auto-generated + internal static void PermitOnly(PermissionSet permSet, ref StackCrawlMark stackMark) { -#if FEATURE_CAS_POLICY - FrameSecurityDescriptor secObj = - SecurityRuntime.GetSecurityObjectForFrame(ref stackMark, true); - - Contract.Assert(secObj != null, "Failure in SecurityRuntime.PermitOnly() - secObj != null"); - if (secObj == null) - { - // Security: REQ_SQ flag is missing. Bad compiler ? - System.Environment.FailFast(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor")); - } - else - { - if (secObj.HasImperativeRestrictions()) - throw new SecurityException( Environment.GetResourceString( "Security_MustRevertOverride" ) ); - - secObj.SetPermitOnly(permSet); - } -#endif // FEATURE_CAS_POLICY } - + // // Revert API // - - [System.Security.SecurityCritical] // auto-generated + internal static void RevertAssert(ref StackCrawlMark stackMark) { -#if FEATURE_CAS_POLICY - FrameSecurityDescriptor secObj = GetSecurityObjectForFrame(ref stackMark, false); - if (secObj != null) - { - secObj.RevertAssert(); - } - else - { - throw new InvalidOperationException(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor")); - } -#endif // FEATURE_CAS_POLICY } - [System.Security.SecurityCritical] // auto-generated internal static void RevertDeny(ref StackCrawlMark stackMark) { -#if FEATURE_CAS_POLICY - FrameSecurityDescriptor secObj = GetSecurityObjectForFrame(ref stackMark, false); - if (secObj != null) - { - secObj.RevertDeny(); - } - else - { - throw new InvalidOperationException(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor")); - } -#endif // FEATURE_CAS_POLICY } - [System.Security.SecurityCritical] // auto-generated internal static void RevertPermitOnly(ref StackCrawlMark stackMark) { -#if FEATURE_CAS_POLICY - FrameSecurityDescriptor secObj = GetSecurityObjectForFrame(ref stackMark, false); - if (secObj != null) - { - secObj.RevertPermitOnly(); - } - else - { - throw new InvalidOperationException(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor")); - } -#endif // FEATURE_CAS_POLICY } - [System.Security.SecurityCritical] // auto-generated internal static void RevertAll(ref StackCrawlMark stackMark) { -#if FEATURE_CAS_POLICY - FrameSecurityDescriptor secObj = GetSecurityObjectForFrame(ref stackMark, false); - if (secObj != null) - { - secObj.RevertAll(); - } - else - { - throw new InvalidOperationException(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor")); - } -#endif // FEATURE_CAS_POLICY } } } diff --git a/src/mscorlib/src/System/Security/SecurityState.cs b/src/mscorlib/src/System/Security/SecurityState.cs index bd23acd..3c7f8bf 100644 --- a/src/mscorlib/src/System/Security/SecurityState.cs +++ b/src/mscorlib/src/System/Security/SecurityState.cs @@ -7,25 +7,17 @@ using System.Security.Permissions; namespace System.Security { - [System.Security.SecurityCritical] // auto-generated_required -#pragma warning disable 618 - [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)] -#pragma warning restore 618 public abstract class SecurityState { protected SecurityState(){} - [System.Security.SecurityCritical] // auto-generated public bool IsStateAvailable() { AppDomainManager domainManager = AppDomainManager.CurrentAppDomainManager; -#if FEATURE_CORECLR + // CheckSecuritySettings only when appdomainManager is present. So if there is no // appDomain Manager return true as by default coreclr runs in fulltrust. return domainManager != null ? domainManager.CheckSecuritySettings(this) : true; -#else - return domainManager != null ? domainManager.CheckSecuritySettings(this) : false; -#endif } // override this function and throw the appropriate public abstract void EnsureState(); diff --git a/src/mscorlib/src/System/Security/Util/Config.cs b/src/mscorlib/src/System/Security/Util/Config.cs index 988a39a..afc9b8c 100644 --- a/src/mscorlib/src/System/Security/Util/Config.cs +++ b/src/mscorlib/src/System/Security/Util/Config.cs @@ -37,7 +37,6 @@ namespace System.Security.Util { private static volatile string m_machineConfig; private static volatile string m_userConfig; - [System.Security.SecurityCritical] // auto-generated private static void GetFileLocales() { if (m_machineConfig == null) @@ -56,7 +55,6 @@ namespace System.Security.Util { internal static string MachineDirectory { - [System.Security.SecurityCritical] // auto-generated get { GetFileLocales(); @@ -66,7 +64,6 @@ namespace System.Security.Util { internal static string UserDirectory { - [System.Security.SecurityCritical] // auto-generated get { GetFileLocales(); @@ -74,57 +71,12 @@ namespace System.Security.Util { } } -#if FEATURE_CAS_POLICY - [System.Security.SecurityCritical] // auto-generated - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] - internal static extern int SaveDataByte(string path, [In] byte[] data, int length); - - [System.Security.SecurityCritical] // auto-generated - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] - internal static extern bool RecoverData(ConfigId id); - - [System.Security.SecurityCritical] // auto-generated - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] - internal static extern void SetQuickCache(ConfigId id, QuickCacheEntryType quickCacheFlags); - - [System.Security.SecurityCritical] // auto-generated - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] - private static extern bool GetCacheEntry(ConfigId id, int numKey, [In] byte[] key, int keyLength, ObjectHandleOnStack retData); - - [System.Security.SecurityCritical] // auto-generated - internal static bool GetCacheEntry(ConfigId id, int numKey, byte[] key, out byte[] data) - { - byte[] retData = null; - bool ret = GetCacheEntry(id, numKey, key, key.Length, JitHelpers.GetObjectHandleOnStack(ref retData)); - - data = retData; - return ret; - } - - [System.Security.SecurityCritical] // auto-generated - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] - private static extern void AddCacheEntry(ConfigId id, int numKey, [In] byte[] key, int keyLength, byte[] data, int dataLength); - - [System.Security.SecurityCritical] // auto-generated - internal static void AddCacheEntry(ConfigId id, int numKey, byte[] key, byte[] data) - { - AddCacheEntry(id, numKey, key, key.Length, data, data.Length); - } - - [System.Security.SecurityCritical] // auto-generated - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] - internal static extern void ResetCacheData(ConfigId id); -#endif - - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] private static extern void GetMachineDirectory(StringHandleOnStack retDirectory); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] private static extern void GetUserDirectory(StringHandleOnStack retDirectory); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] internal static extern bool WriteToEventLog(string message); } diff --git a/src/mscorlib/src/System/Security/Util/Hex.cs b/src/mscorlib/src/System/Security/Util/Hex.cs index 709744f..4ca1cf6 100644 --- a/src/mscorlib/src/System/Security/Util/Hex.cs +++ b/src/mscorlib/src/System/Security/Util/Hex.cs @@ -73,7 +73,7 @@ namespace System.Security.Util public static byte[] DecodeHexString(String hexString) { if (hexString == null) - throw new ArgumentNullException( "hexString" ); + throw new ArgumentNullException( nameof(hexString) ); Contract.EndContractBlock(); bool spaceSkippingMode = false; diff --git a/src/mscorlib/src/System/Security/Util/StringExpressionSet.cs b/src/mscorlib/src/System/Security/Util/StringExpressionSet.cs index 19937f5..8a12235 100644 --- a/src/mscorlib/src/System/Security/Util/StringExpressionSet.cs +++ b/src/mscorlib/src/System/Security/Util/StringExpressionSet.cs @@ -12,6 +12,7 @@ namespace System.Security.Util { using System.Globalization; using System.Runtime.Versioning; using System.IO; + using System.Diagnostics; using System.Diagnostics.Contracts; [Serializable] @@ -26,12 +27,9 @@ namespace System.Security.Util { // 2. Ensuring that the partial trust code has permission to see full path data // 3. Not using this set for paths (eg EnvironmentStringExpressionSet) // - [SecurityCritical] protected ArrayList m_list; protected bool m_ignoreCase; - [SecurityCritical] protected String m_expressions; - [SecurityCritical] protected String[] m_expressionsArray; protected bool m_throwOnRelative; @@ -61,7 +59,6 @@ namespace System.Security.Util { { } - [System.Security.SecuritySafeCritical] // auto-generated public StringExpressionSet( bool ignoreCase, String str, bool throwOnRelative ) { m_list = null; @@ -78,7 +75,6 @@ namespace System.Security.Util { return new StringExpressionSet(); } - [SecuritySafeCritical] public virtual StringExpressionSet Copy() { // SafeCritical: just copying this value around, not leaking it @@ -118,11 +114,10 @@ namespace System.Security.Util { return StaticProcessSingleString(str); } - [System.Security.SecurityCritical] // auto-generated public void AddExpressions( String str ) { if (str == null) - throw new ArgumentNullException( "str" ); + throw new ArgumentNullException( nameof(str) ); Contract.EndContractBlock(); if (str.Length == 0) return; @@ -165,7 +160,7 @@ namespace System.Security.Util { { if (m_throwOnRelative) { - if (Path.IsRelative(temp)) + if (PathInternal.IsPartiallyQualified(temp)) { throw new ArgumentException( Environment.GetResourceString( "Argument_AbsolutePathRequired" ) ); } @@ -181,16 +176,14 @@ namespace System.Security.Util { Reduce(); } - [System.Security.SecurityCritical] // auto-generated public void AddExpressions( String[] str, bool checkForDuplicates, bool needFullPath ) { AddExpressions(CreateListFromExpressions(str, needFullPath), checkForDuplicates); } - [System.Security.SecurityCritical] // auto-generated public void AddExpressions( ArrayList exprArrayList, bool checkForDuplicates) { - Contract.Assert( m_throwOnRelative, "This should only be called when throw on relative is set" ); + Debug.Assert( m_throwOnRelative, "This should only be called when throw on relative is set" ); m_expressionsArray = null; m_expressions = null; @@ -205,19 +198,18 @@ namespace System.Security.Util { } - [System.Security.SecurityCritical] // auto-generated internal static ArrayList CreateListFromExpressions(String[] str, bool needFullPath) { if (str == null) { - throw new ArgumentNullException( "str" ); + throw new ArgumentNullException( nameof(str) ); } Contract.EndContractBlock(); ArrayList retArrayList = new ArrayList(); for (int index = 0; index < str.Length; ++index) { if (str[index] == null) - throw new ArgumentNullException( "str" ); + throw new ArgumentNullException( nameof(str) ); // Replace alternate directory separators String oneString = StaticProcessWholeString( str[index] ); @@ -249,7 +241,6 @@ namespace System.Security.Util { return retArrayList; } - [System.Security.SecurityCritical] // auto-generated protected void CheckList() { if (m_list == null && m_expressions != null) @@ -303,7 +294,6 @@ namespace System.Security.Util { } - [System.Security.SecurityCritical] // auto-generated protected void CreateList() { String[] expressionsArray = Split( m_expressions ); @@ -325,7 +315,7 @@ namespace System.Security.Util { { if (m_throwOnRelative) { - if (Path.IsRelative(temp)) + if (PathInternal.IsPartiallyQualified(temp)) { throw new ArgumentException( Environment.GetResourceString( "Argument_AbsolutePathRequired" ) ); } @@ -339,7 +329,6 @@ namespace System.Security.Util { } } - [SecuritySafeCritical] public bool IsEmpty() { // SafeCritical: we're just showing that the expressions are empty, the sensitive portion is their @@ -354,7 +343,6 @@ namespace System.Security.Util { } } - [System.Security.SecurityCritical] // auto-generated public bool IsSubsetOf( StringExpressionSet ses ) { if (this.IsEmpty()) @@ -376,7 +364,6 @@ namespace System.Security.Util { return true; } - [System.Security.SecurityCritical] // auto-generated public bool IsSubsetOfPathDiscovery( StringExpressionSet ses ) { if (this.IsEmpty()) @@ -399,7 +386,6 @@ namespace System.Security.Util { } - [System.Security.SecurityCritical] // auto-generated public StringExpressionSet Union( StringExpressionSet ses ) { // If either set is empty, the union represents a copy of the other. @@ -434,7 +420,6 @@ namespace System.Security.Util { } - [System.Security.SecurityCritical] // auto-generated public StringExpressionSet Intersect( StringExpressionSet ses ) { // If either set is empty, the intersection is empty @@ -477,7 +462,6 @@ namespace System.Security.Util { return intersectSet; } - [SecuritySafeCritical] protected void GenerateString() { // SafeCritical - moves critical data around, but doesn't expose it out @@ -522,7 +506,6 @@ namespace System.Security.Util { // expressions contain paths that were canonicalized and expanded from the input that would cause // information disclosure, so we instead only expose this out to trusted code that can ensure they // either don't leak the information or required full path information. - [SecurityCritical] public string UnsafeToString() { CheckList(); @@ -534,7 +517,6 @@ namespace System.Security.Util { return m_expressions; } - [SecurityCritical] public String[] UnsafeToStringArray() { if (m_expressionsArray == null && m_list != null) @@ -550,7 +532,6 @@ namespace System.Security.Util { // protected static helper functions //------------------------------- - [SecurityCritical] private bool StringSubsetStringExpression( String left, StringExpressionSet right, bool ignoreCase ) { for (int index = 0; index < right.m_list.Count; ++index) @@ -563,7 +544,6 @@ namespace System.Security.Util { return false; } - [SecurityCritical] private static bool StringSubsetStringExpressionPathDiscovery( String left, StringExpressionSet right, bool ignoreCase ) { for (int index = 0; index < right.m_list.Count; ++index) @@ -661,7 +641,6 @@ namespace System.Security.Util { // protected helper functions //------------------------------- - [SecuritySafeCritical] protected void AddSingleExpressionNoDuplicates( String expression ) { // SafeCritical: We're not exposing out the string sets, just allowing modification of them @@ -691,7 +670,6 @@ namespace System.Security.Util { this.m_list.Add( expression ); } - [System.Security.SecurityCritical] // auto-generated protected void Reduce() { CheckList(); @@ -726,23 +704,20 @@ namespace System.Security.Util { } } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern void GetLongPathName( String path, StringHandleOnStack retLongPath ); - [System.Security.SecurityCritical] // auto-generated internal static String CanonicalizePath( String path ) { return CanonicalizePath( path, true ); } - [System.Security.SecurityCritical] // auto-generated internal static string CanonicalizePath(string path, bool needFullPath) { if (needFullPath) { - string newPath = Path.GetFullPathInternal(path); + string newPath = Path.GetFullPath(path); if (path.EndsWith(m_directorySeparator + ".", StringComparison.Ordinal)) { if (newPath.EndsWith(m_directorySeparator)) diff --git a/src/mscorlib/src/System/Security/Util/TokenBasedSet.cs b/src/mscorlib/src/System/Security/Util/TokenBasedSet.cs index 590a909..8589fa7 100644 --- a/src/mscorlib/src/System/Security/Util/TokenBasedSet.cs +++ b/src/mscorlib/src/System/Security/Util/TokenBasedSet.cs @@ -9,6 +9,7 @@ namespace System.Security.Util using System.Security.Permissions; using System.Runtime.Serialization; using System.Threading; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Diagnostics.CodeAnalysis; @@ -368,31 +369,17 @@ namespace System.Security.Util { Object thisObj = this.GetItem( i ); IPermission thisPerm = thisObj as IPermission; -#if FEATURE_CAS_POLICY - ISecurityElementFactory thisElem = thisObj as ISecurityElementFactory; -#endif // FEATURE_CAS_POLICY Object otherObj = (other != null)?other.GetItem( i ):null; IPermission otherPerm = otherObj as IPermission; -#if FEATURE_CAS_POLICY - ISecurityElementFactory otherElem = otherObj as ISecurityElementFactory; -#endif // FEATURE_CAS_POLICY if (thisObj == null && otherObj == null) continue; - - + if (thisObj == null) { -#if FEATURE_CAS_POLICY - if (otherElem != null) - { - otherPerm = PermissionSet.CreatePerm(otherElem, false); - } -#endif // FEATURE_CAS_POLICY - PermissionToken token = PermissionToken.GetToken(otherPerm); - + if (token == null) { throw new SerializationException(Environment.GetResourceString("Serialization_InsufficientState")); @@ -402,13 +389,6 @@ namespace System.Security.Util } else if (otherObj == null) { -#if FEATURE_CAS_POLICY - if (thisElem != null) - { - thisPerm = PermissionSet.CreatePerm(thisElem, false); - } -#endif // FEATURE_CAS_POLICY - PermissionToken token = PermissionToken.GetToken(thisPerm); if (token == null) { @@ -418,7 +398,7 @@ namespace System.Security.Util } else { - Contract.Assert( (thisObj == null || otherObj == null), "Permission cannot be in both TokenBasedSets" ); + Debug.Assert( (thisObj == null || otherObj == null), "Permission cannot be in both TokenBasedSets" ); } } return unionSet; @@ -434,10 +414,6 @@ namespace System.Security.Util if (obj != null) { IPermission perm = obj as IPermission; -#if FEATURE_CAS_POLICY - if (perm == null) - perm = PermissionSet.CreatePerm(obj, ignoreTypeLoadFailures); -#endif // FEATURE_CAS_POLICY PermissionToken token = PermissionToken.GetToken(perm); if (perm == null || token == null) diff --git a/src/mscorlib/src/System/Security/Util/URLString.cs b/src/mscorlib/src/System/Security/Util/URLString.cs index 51ae24c..83f9ce4 100644 --- a/src/mscorlib/src/System/Security/Util/URLString.cs +++ b/src/mscorlib/src/System/Security/Util/URLString.cs @@ -484,10 +484,11 @@ namespace System.Security.Util { private static void CheckPathTooLong(StringBuilder path) { if (path.Length >= ( -#if FEATURE_PATHCOMPAT - AppContextSwitches.BlockLongPaths ? PathInternal.MaxShortPath : -#endif +#if PLATFORM_UNIX + Interop.Sys.MaxPath)) +#else PathInternal.MaxLongPath)) +#endif { throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); } @@ -513,7 +514,7 @@ namespace System.Security.Util { // file:/home/johndoe/here // file:../johndoe/here // file:~/johndoe/here - String temp = url; + String temp = url; int nbSlashes = 0; while(nbSlashes" ) ) ; - Contract.EndContractBlock(); - - String className; - int classNameLength; - int classNameStart; - - if (!ParseElementForObjectCreation( el, - BuiltInCodeGroup, - out className, - out classNameStart, - out classNameLength )) - { - goto USEREFLECTION; - } - - switch (classNameLength) - { - case 12: - // NetCodeGroup - if (String.Compare(className, classNameStart, "NetCodeGroup", 0, classNameLength, StringComparison.Ordinal) == 0) - return new NetCodeGroup(); - else - goto USEREFLECTION; - - case 13: - // FileCodeGroup - if (String.Compare(className, classNameStart, "FileCodeGroup", 0, classNameLength, StringComparison.Ordinal) == 0) - return new FileCodeGroup(); - else - goto USEREFLECTION; - case 14: - // UnionCodeGroup - if (String.Compare(className, classNameStart, "UnionCodeGroup", 0, classNameLength, StringComparison.Ordinal) == 0) - return new UnionCodeGroup(); - else - goto USEREFLECTION; - - case 19: - // FirstMatchCodeGroup - if (String.Compare(className, classNameStart, "FirstMatchCodeGroup", 0, classNameLength, StringComparison.Ordinal) == 0) - return new FirstMatchCodeGroup(); - else - goto USEREFLECTION; - - default: - goto USEREFLECTION; - } - -USEREFLECTION: - Type groupClass = null; - CodeGroup group = null; - - new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert(); - groupClass = GetClassFromElement(el, true); - if (groupClass == null) - return null; - if (!(typeof(CodeGroup).IsAssignableFrom(groupClass))) - throw new ArgumentException( Environment.GetResourceString("Argument_NotACodeGroupType") ); - - group = (CodeGroup) Activator.CreateInstance(groupClass, true); - - Contract.Assert( groupClass.Module.Assembly != Assembly.GetExecutingAssembly(), - "This path should not get called for mscorlib based classes" ); - - return group; - } -#pragma warning restore 618 - - [System.Security.SecurityCritical] // auto-generated - internal static IMembershipCondition - CreateMembershipCondition( SecurityElement el ) - { - if (el == null || !el.Tag.Equals("IMembershipCondition")) - throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_WrongElementType" ), "" ) ) ; - Contract.EndContractBlock(); - - String className; - int classNameStart; - int classNameLength; - - if (!ParseElementForObjectCreation( el, - BuiltInMembershipCondition, - out className, - out classNameStart, - out classNameLength )) - { - goto USEREFLECTION; - } - - // We have a built in membership condition, figure out which it is. - - // Here's the list of built in membership conditions as of 9/17/2002 - // System.Security.Policy.AllMembershipCondition - // System.Security.Policy.URLMembershipCondition - // System.Security.Policy.SHA1MembershipCondition - // System.Security.Policy.SiteMembershipCondition - // System.Security.Policy.ZoneMembershipCondition - // System.Security.Policy.PublisherMembershipCondition - // System.Security.Policy.StrongNameMembershipCondition - // System.Security.Policy.ApplicationMembershipCondition - // System.Security.Policy.DomainApplicationMembershipCondition - // System.Security.Policy.ApplicationDirectoryMembershipCondition - - switch (classNameLength) - { - case 22: - // AllMembershipCondition - // URLMembershipCondition - if (className[classNameStart] == 'A') - { - if (String.Compare(className, classNameStart, "AllMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0) - return new AllMembershipCondition(); - else - goto USEREFLECTION; - } - else - { - if (String.Compare(className, classNameStart, "UrlMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0) - return new UrlMembershipCondition(); - else - goto USEREFLECTION; - } - - case 23: - // HashMembershipCondition - // SiteMembershipCondition - // ZoneMembershipCondition - if (className[classNameStart] == 'H') - { - if (String.Compare(className, classNameStart, "HashMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0) - return new HashMembershipCondition(); - else - goto USEREFLECTION; - } - else if (className[classNameStart] == 'S') - { - if (String.Compare(className, classNameStart, "SiteMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0) - return new SiteMembershipCondition(); - else - goto USEREFLECTION; - } - else - { - if (String.Compare(className, classNameStart, "ZoneMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0) - return new ZoneMembershipCondition(); - else - goto USEREFLECTION; - } - - case 28: - // PublisherMembershipCondition - if (String.Compare(className, classNameStart, "PublisherMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0) - return new PublisherMembershipCondition(); - else - goto USEREFLECTION; - - case 29: - // StrongNameMembershipCondition - if (String.Compare(className, classNameStart, "StrongNameMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0) - return new StrongNameMembershipCondition(); - else - goto USEREFLECTION; - - case 39: - // ApplicationDirectoryMembershipCondition - if (String.Compare(className, classNameStart, "ApplicationDirectoryMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0) - return new ApplicationDirectoryMembershipCondition(); - else - goto USEREFLECTION; - - default: - goto USEREFLECTION; - } - -USEREFLECTION: - Type condClass = null; - IMembershipCondition cond = null; - - new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert(); - condClass = GetClassFromElement(el, true); - if (condClass == null) - return null; - if (!(typeof(IMembershipCondition).IsAssignableFrom(condClass))) - throw new ArgumentException( Environment.GetResourceString("Argument_NotAMembershipCondition") ); - - cond = (IMembershipCondition) Activator.CreateInstance(condClass, true); - - return cond; - } -#endif //#if FEATURE_CAS_POLICY internal static Type GetClassFromElement (SecurityElement el, bool ignoreTypeLoadFailures) { @@ -624,7 +364,7 @@ USEREFLECTION: { try { - return Type.GetType(className, false, false); + return Type.GetType(className, false, false); } catch (SecurityException) { @@ -632,7 +372,7 @@ USEREFLECTION: } } else - return Type.GetType(className, true, false); + return Type.GetType(className, true, false); } public static bool diff --git a/src/mscorlib/src/System/Security/securestring.cs b/src/mscorlib/src/System/Security/securestring.cs index b53d0db..548126f 100644 --- a/src/mscorlib/src/System/Security/securestring.cs +++ b/src/mscorlib/src/System/Security/securestring.cs @@ -14,6 +14,7 @@ namespace System.Security { using System.Runtime.ConstrainedExecution; using System.Runtime.Versioning; using Microsoft.Win32.SafeHandles; + using System.Diagnostics; using System.Diagnostics.Contracts; public sealed class SecureString: IDisposable { @@ -105,15 +106,15 @@ namespace System.Security { [CLSCompliant(false)] public unsafe SecureString(char* value, int length) { if( value == null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } if( length < 0) { - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if( length > MaxLength) { - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_Length")); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_Length")); } Contract.EndContractBlock(); @@ -192,7 +193,7 @@ namespace System.Security { #endif // FEATURE_CORRUPTING_EXCEPTIONS public void InsertAt( int index, char c ) { if( index < 0 || index > m_length) { - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_IndexString")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_IndexString")); } Contract.EndContractBlock(); @@ -251,7 +252,7 @@ namespace System.Security { EnsureNotReadOnly(); if( index < 0 || index >= m_length) { - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_IndexString")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_IndexString")); } unsafe @@ -290,10 +291,10 @@ namespace System.Security { #endif // FEATURE_CORRUPTING_EXCEPTIONS public void SetAt( int index, char c ) { if( index < 0 || index >= m_length) { - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_IndexString")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_IndexString")); } Contract.EndContractBlock(); - Contract.Assert(index <= Int32.MaxValue / sizeof(char)); + Debug.Assert(index <= Int32.MaxValue / sizeof(char)); EnsureNotDisposed(); EnsureNotReadOnly(); @@ -315,7 +316,7 @@ namespace System.Security { private int BufferLength { [System.Security.SecurityCritical] // auto-generated get { - Contract.Assert(m_buffer != null, "Buffer is not initialized!"); + Debug.Assert(m_buffer != null, "Buffer is not initialized!"); return m_buffer.Length; } } @@ -341,7 +342,7 @@ namespace System.Security { [System.Security.SecurityCritical] // auto-generated private void EnsureCapacity(int capacity) { if( capacity > MaxLength) { - throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_Capacity")); + throw new ArgumentOutOfRangeException(nameof(capacity), Environment.GetResourceString("ArgumentOutOfRange_Capacity")); } Contract.EndContractBlock(); @@ -377,7 +378,7 @@ namespace System.Security { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] private static uint GetAlignedSize( int size) { - Contract.Assert(size >= 0, "size must be non-negative"); + Debug.Assert(size >= 0, "size must be non-negative"); uint alignedSize = ((uint)size / BlockSize) * BlockSize; if( (size % BlockSize != 0) || size == 0) { // if size is 0, set allocated size to blocksize @@ -449,8 +450,8 @@ namespace System.Security { [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] private void ProtectMemory() { - Contract.Assert(!m_buffer.IsInvalid && m_buffer.Length != 0, "Invalid buffer!"); - Contract.Assert(m_buffer.Length % BlockSize == 0, "buffer length must be multiple of blocksize!"); + Debug.Assert(!m_buffer.IsInvalid && m_buffer.Length != 0, "Invalid buffer!"); + Debug.Assert(m_buffer.Length % BlockSize == 0, "buffer length must be multiple of blocksize!"); if( m_length == 0 || m_encrypted) { return; @@ -650,8 +651,8 @@ namespace System.Security { [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] private void UnProtectMemory() { - Contract.Assert(!m_buffer.IsInvalid && m_buffer.Length != 0, "Invalid buffer!"); - Contract.Assert(m_buffer.Length % BlockSize == 0, "buffer length must be multiple of blocksize!"); + Debug.Assert(!m_buffer.IsInvalid && m_buffer.Length != 0, "Invalid buffer!"); + Debug.Assert(m_buffer.Length % BlockSize == 0, "buffer length must be multiple of blocksize!"); if( m_length == 0) { return; @@ -733,7 +734,7 @@ namespace System.Security { source.AcquirePointer(ref sourcePtr); target.AcquirePointer(ref targetPtr); - Contract.Assert(Win32Native.SysStringLen((IntPtr)targetPtr) >= Win32Native.SysStringLen((IntPtr)sourcePtr), "Target buffer is not large enough!"); + Debug.Assert(Win32Native.SysStringLen((IntPtr)targetPtr) >= Win32Native.SysStringLen((IntPtr)sourcePtr), "Target buffer is not large enough!"); Buffer.Memcpy(targetPtr, sourcePtr, (int) Win32Native.SysStringLen((IntPtr)sourcePtr) * 2); } diff --git a/src/mscorlib/src/System/SharedStatics.cs b/src/mscorlib/src/System/SharedStatics.cs index ec63a0e..cbc5c35 100644 --- a/src/mscorlib/src/System/SharedStatics.cs +++ b/src/mscorlib/src/System/SharedStatics.cs @@ -11,18 +11,16 @@ ** =============================================================================*/ -namespace System { - +namespace System +{ using System.Threading; using System.Runtime.Remoting; using System.Security; using System.Security.Util; using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; + using System.Diagnostics; using System.Diagnostics.Contracts; -#if FEATURE_CAS_POLICY - using StringMaker = System.Security.Util.Tokenizer.StringMaker; -#endif // FEATURE_CAS_POLICY internal sealed class SharedStatics { @@ -40,7 +38,6 @@ namespace System { private volatile String _Remoting_Identity_IDGuid; public static String Remoting_Identity_IDGuid { - [System.Security.SecuritySafeCritical] // auto-generated get { if (_sharedStatics._Remoting_Identity_IDGuid == null) @@ -61,63 +58,12 @@ namespace System { } } - Contract.Assert(_sharedStatics._Remoting_Identity_IDGuid != null, + Debug.Assert(_sharedStatics._Remoting_Identity_IDGuid != null, "_sharedStatics._Remoting_Identity_IDGuid != null"); return _sharedStatics._Remoting_Identity_IDGuid; } } -#if FEATURE_CAS_POLICY - private StringMaker _maker; - [System.Security.SecuritySafeCritical] // auto-generated - static public StringMaker GetSharedStringMaker() - { - StringMaker maker = null; - - bool tookLock = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try { - Monitor.Enter(_sharedStatics, ref tookLock); - - if (_sharedStatics._maker != null) - { - maker = _sharedStatics._maker; - _sharedStatics._maker = null; - } - } - finally { - if (tookLock) - Monitor.Exit(_sharedStatics); - } - - if (maker == null) - { - maker = new StringMaker(); - } - - return maker; - } - - [System.Security.SecuritySafeCritical] // auto-generated - static public void ReleaseSharedStringMaker(ref StringMaker maker) - { - // save this stringmaker so someone else can use it - bool tookLock = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - Monitor.Enter(_sharedStatics, ref tookLock); - - _sharedStatics._maker = maker; - maker = null; - } - finally { - if (tookLock) - Monitor.Exit(_sharedStatics); - } - } -#endif // FEATURE_CAS_POLICY - // Note this may not need to be process-wide. private int _Remoting_Identity_IDSeqNum; internal static int Remoting_Identity_GetNextSeqNum() @@ -140,7 +86,7 @@ namespace System { internal static ulong MemoryFailPointReservedMemory { get { - Contract.Assert(Volatile.Read(ref _sharedStatics._memFailPointReservedMemory) >= 0, "Process-wide MemoryFailPoint reserved memory was negative!"); + Debug.Assert(Volatile.Read(ref _sharedStatics._memFailPointReservedMemory) >= 0, "Process-wide MemoryFailPoint reserved memory was negative!"); return (ulong) Volatile.Read(ref _sharedStatics._memFailPointReservedMemory); } } diff --git a/src/mscorlib/src/System/Single.cs b/src/mscorlib/src/System/Single.cs index 6a77f08..481c088 100644 --- a/src/mscorlib/src/System/Single.cs +++ b/src/mscorlib/src/System/Single.cs @@ -37,22 +37,21 @@ namespace System { public const float NegativeInfinity = (float)-1.0 / (float)0.0; public const float NaN = (float)0.0 / (float)0.0; + internal static float NegativeZero = BitConverter.Int32BitsToSingle(unchecked((int)0x80000000)); + [Pure] - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.Versioning.NonVersionable] public unsafe static bool IsInfinity(float f) { return (*(int*)(&f) & 0x7FFFFFFF) == 0x7F800000; } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.Versioning.NonVersionable] public unsafe static bool IsPositiveInfinity(float f) { return *(int*)(&f) == 0x7F800000; } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.Versioning.NonVersionable] public unsafe static bool IsNegativeInfinity(float f) { return *(int*)(&f) == unchecked((int)0xFF800000); @@ -60,11 +59,15 @@ namespace System { [Pure] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [System.Security.SecuritySafeCritical] [System.Runtime.Versioning.NonVersionable] public unsafe static bool IsNaN(float f) { return (*(int*)(&f) & 0x7FFFFFFF) > 0x7F800000; } + + [Pure] + internal unsafe static bool IsNegative(float f) { + return (*(uint*)(&f) & 0x80000000) == 0x80000000; + } // Compares this object to another object, returning an integer that // indicates the relationship. @@ -155,7 +158,6 @@ namespace System { return IsNaN(obj) && IsNaN(m_value); } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe override int GetHashCode() { float f = m_value; if (f == 0) { @@ -166,25 +168,21 @@ namespace System { return v; } - [System.Security.SecuritySafeCritical] // auto-generated public override String ToString() { Contract.Ensures(Contract.Result() != null); return Number.FormatSingle(m_value, null, NumberFormatInfo.CurrentInfo); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(IFormatProvider provider) { Contract.Ensures(Contract.Result() != null); return Number.FormatSingle(m_value, null, NumberFormatInfo.GetInstance(provider)); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(String format) { Contract.Ensures(Contract.Result() != null); return Number.FormatSingle(m_value, format, NumberFormatInfo.CurrentInfo); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(String format, IFormatProvider provider) { Contract.Ensures(Contract.Result() != null); return Number.FormatSingle(m_value, format, NumberFormatInfo.GetInstance(provider)); diff --git a/src/mscorlib/src/System/Span.cs b/src/mscorlib/src/System/Span.cs new file mode 100644 index 0000000..9fa55c6 --- /dev/null +++ b/src/mscorlib/src/System/Span.cs @@ -0,0 +1,477 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.CompilerServices; + +#pragma warning disable 0809 //warning CS0809: Obsolete member 'Span.Equals(object)' overrides non-obsolete member 'object.Equals(object)' + +namespace System +{ + /// + /// Span represents contiguous region of arbitrary memory, with performance + /// characteristics on par with T[]. Unlike arrays, it can point to either managed + /// or native memory, or to memory allocated on the stack. It is type- and memory-safe. + /// + public struct Span + { + /// A byref or a native ptr. + private readonly ByReference _pointer; + /// The number of elements this Span contains. + private readonly int _length; + + /// + /// Creates a new span over the entirety of the target array. + /// + /// The target array. + /// Thrown when is a null + /// reference (Nothing in Visual Basic). + /// Thrown when is covariant and array's type is not exactly T[]. + public Span(T[] array) + { + if (array == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + if (default(T) == null) { // Arrays of valuetypes are never covariant + if (array.GetType() != typeof(T[])) + ThrowHelper.ThrowArrayTypeMismatchException(); + } + + _pointer = new ByReference(ref JitHelpers.GetArrayData(array)); + _length = array.Length; + } + + /// + /// Creates a new span over the portion of the target array beginning + /// at 'start' index and covering the remainder of the array. + /// + /// The target array. + /// The index at which to begin the span. + /// Thrown when is a null + /// reference (Nothing in Visual Basic). + /// Thrown when is covariant and array's type is not exactly T[]. + /// + /// Thrown when the specified is not in the range (<0 or >=Length). + /// + public Span(T[] array, int start) + { + if (array == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + if (default(T) == null) { // Arrays of valuetypes are never covariant + if (array.GetType() != typeof(T[])) + ThrowHelper.ThrowArrayTypeMismatchException(); + } + if ((uint)start > (uint)array.Length) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + _pointer = new ByReference(ref Unsafe.Add(ref JitHelpers.GetArrayData(array), start)); + _length = array.Length - start; + } + + /// + /// Creates a new span over the portion of the target array beginning + /// at 'start' index and ending at 'end' index (exclusive). + /// + /// The target array. + /// The index at which to begin the span. + /// The number of items in the span. + /// Thrown when is a null + /// reference (Nothing in Visual Basic). + /// Thrown when is covariant and array's type is not exactly T[]. + /// + /// Thrown when the specified or end index is not in the range (<0 or >=Length). + /// + public Span(T[] array, int start, int length) + { + if (array == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + if (default(T) == null) { // Arrays of valuetypes are never covariant + if (array.GetType() != typeof(T[])) + ThrowHelper.ThrowArrayTypeMismatchException(); + } + if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start)) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + _pointer = new ByReference(ref Unsafe.Add(ref JitHelpers.GetArrayData(array), start)); + _length = length; + } + + /// + /// Creates a new span over the target unmanaged buffer. Clearly this + /// is quite dangerous, because we are creating arbitrarily typed T's + /// out of a void*-typed block of memory. And the length is not checked. + /// But if this creation is correct, then all subsequent uses are correct. + /// + /// An unmanaged pointer to memory. + /// The number of elements the memory contains. + /// + /// Thrown when is reference type or contains pointers and hence cannot be stored in unmanaged memory. + /// + /// + /// Thrown when the specified is negative. + /// + [CLSCompliant(false)] + public unsafe Span(void* pointer, int length) + { + if (JitHelpers.ContainsReferences()) + ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T)); + if (length < 0) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + _pointer = new ByReference(ref Unsafe.As(ref *(byte*)pointer)); + _length = length; + } + + /// + /// Create a new span over a portion of a regular managed object. This can be useful + /// if part of a managed object represents a "fixed array." This is dangerous because + /// "length" is not checked, nor is the fact that "rawPointer" actually lies within the object. + /// + /// The managed object that contains the data to span over. + /// A reference to data within that object. + /// The number of elements the memory contains. + /// + /// Thrown when the specified object is null. + /// + /// + /// Thrown when the specified is negative. + /// + public static Span DangerousCreate(object obj, ref T objectData, int length) + { + if (obj == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.obj); + if (length < 0) + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length); + + return new Span(ref objectData, length); + } + + + /// + /// An internal helper for creating spans. + /// + internal Span(ref T ptr, int length) + { + _pointer = new ByReference(ref ptr); + _length = length; + } + + /// + /// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to the location where the 0th element + /// would have been stored. Such a reference can be used for pinning but must never be dereferenced. + /// + public ref T DangerousGetPinnableReference() + { + return ref _pointer.Value; + } + + /// + /// Gets the number of elements contained in the + /// + public int Length => _length; + + /// + /// Returns whether the is empty. + /// + public bool IsEmpty => _length == 0; + + /// + /// Fetches the element at the specified index. + /// + /// + /// Thrown when the specified is not in range (<0 or >&eq;Length). + /// + public T this[int index] + { + get + { + if ((uint)index >= (uint)_length) + ThrowHelper.ThrowIndexOutOfRangeException(); + + return Unsafe.Add(ref DangerousGetPinnableReference(), index); + } + set + { + if ((uint)index >= (uint)_length) + ThrowHelper.ThrowIndexOutOfRangeException(); + + Unsafe.Add(ref DangerousGetPinnableReference(), index) = value; + } + } + + /// + /// Copies the contents of this span into destination span. If the source + /// and destinations overlap, this method behaves as if the original values in + /// a temporary location before the destination is overwritten. + /// + /// The span to copy items into. + /// + /// Thrown when the destination Span is shorter than the source Span. + /// + public void CopyTo(Span destination) + { + if (!TryCopyTo(destination)) + ThrowHelper.ThrowArgumentException_DestinationTooShort(); + } + + /// + /// Copies the contents of this span into destination span. If the source + /// and destinations overlap, this method behaves as if the original values in + /// a temporary location before the destination is overwritten. + /// + /// The span to copy items into. + /// If the destination span is shorter than the source span, this method + /// return false and no data is written to the destination. + public bool TryCopyTo(Span destination) + { + if ((uint)_length > (uint)destination.Length) + return false; + + SpanHelper.CopyTo(ref destination.DangerousGetPinnableReference(), ref DangerousGetPinnableReference(), _length); + return true; + } + + /// + /// Returns true if left and right point at the same memory and have the same length. Note that + /// this does *not* check to see if the *contents* are equal. + /// + public static bool operator ==(Span left, Span right) + { + return left._length == right._length && Unsafe.AreSame(ref left.DangerousGetPinnableReference(), ref right.DangerousGetPinnableReference()); + } + + /// + /// Returns false if left and right point at the same memory and have the same length. Note that + /// this does *not* check to see if the *contents* are equal. + /// + public static bool operator !=(Span left, Span right) => !(left == right); + + /// + /// This method is not supported as spans cannot be boxed. To compare two spans, use operator==. + /// + /// Always thrown by this method. + /// + /// + [Obsolete("Equals() on Span will always throw an exception. Use == instead.")] + public override bool Equals(object obj) + { + ThrowHelper.ThrowNotSupportedException_CannotCallEqualsOnSpan(); + // Prevent compiler error CS0161: 'Span.Equals(object)': not all code paths return a value + return default(bool); + } + + /// + /// This method is not supported as spans cannot be boxed. + /// + /// Always thrown by this method. + /// + /// + [Obsolete("GetHashCode() on Span will always throw an exception.")] + public override int GetHashCode() + { + ThrowHelper.ThrowNotSupportedException_CannotCallGetHashCodeOnSpan(); + // Prevent compiler error CS0161: 'Span.GetHashCode()': not all code paths return a value + return default(int); + } + + /// + /// Defines an implicit conversion of an array to a + /// + public static implicit operator Span(T[] array) => new Span(array); + + /// + /// Defines an implicit conversion of a to a + /// + public static implicit operator Span(ArraySegment arraySegment) => new Span(arraySegment.Array, arraySegment.Offset, arraySegment.Count); + + /// + /// Defines an implicit conversion of a to a + /// + public static implicit operator ReadOnlySpan(Span span) => new ReadOnlySpan(ref span.DangerousGetPinnableReference(), span._length); + + /// + /// Forms a slice out of the given span, beginning at 'start'. + /// + /// The index at which to begin this slice. + /// + /// Thrown when the specified index is not in range (<0 or >Length). + /// + [MethodImpl(MethodImplOptions.NoOptimization)] // TODO-SPAN: Workaround for https://github.com/dotnet/coreclr/issues/7894 + public Span Slice(int start) + { + if ((uint)start > (uint)_length) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + return new Span(ref Unsafe.Add(ref DangerousGetPinnableReference(), start), _length - start); + } + + /// + /// Forms a slice out of the given span, beginning at 'start', of given length + /// + /// The index at which to begin this slice. + /// The desired length for the slice (exclusive). + /// + /// Thrown when the specified or end index is not in range (<0 or >&eq;Length). + /// + [MethodImpl(MethodImplOptions.NoOptimization)] // TODO-SPAN: Workaround for https://github.com/dotnet/coreclr/issues/7894 + public Span Slice(int start, int length) + { + if ((uint)start > (uint)_length || (uint)length > (uint)(_length - start)) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + return new Span(ref Unsafe.Add(ref DangerousGetPinnableReference(), start), length); + } + + /// + /// Copies the contents of this span into a new array. This heap + /// allocates, so should generally be avoided, however it is sometimes + /// necessary to bridge the gap with APIs written in terms of arrays. + /// + public T[] ToArray() + { + if (_length == 0) + return Array.Empty(); + + var destination = new T[_length]; + SpanHelper.CopyTo(ref JitHelpers.GetArrayData(destination), ref DangerousGetPinnableReference(), _length); + return destination; + } + + // + /// Returns an empty + /// + public static Span Empty => default(Span); + } + + public static class SpanExtensions + { + /// + /// Casts a Span of one primitive type to Span of bytes. + /// That type may not contain pointers or references. This is checked at runtime in order to preserve type safety. + /// + /// The source slice, of type . + /// + /// Thrown when contains pointers. + /// + public static Span AsBytes(this Span source) + where T : struct + { + if (JitHelpers.ContainsReferences()) + ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T)); + + return new Span( + ref Unsafe.As(ref source.DangerousGetPinnableReference()), + checked(source.Length * Unsafe.SizeOf())); + } + + /// + /// Casts a ReadOnlySpan of one primitive type to ReadOnlySpan of bytes. + /// That type may not contain pointers or references. This is checked at runtime in order to preserve type safety. + /// + /// The source slice, of type . + /// + /// Thrown when contains pointers. + /// + public static ReadOnlySpan AsBytes(this ReadOnlySpan source) + where T : struct + { + if (JitHelpers.ContainsReferences()) + ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T)); + + return new ReadOnlySpan( + ref Unsafe.As(ref source.DangerousGetPinnableReference()), + checked(source.Length * Unsafe.SizeOf())); + } + + /// + /// Casts a Span of one primitive type to another primitive type . + /// These types may not contain pointers or references. This is checked at runtime in order to preserve type safety. + /// + /// + /// Supported only for platforms that support misaligned memory access. + /// + /// The source slice, of type . + /// + /// Thrown when or contains pointers. + /// + public static Span NonPortableCast(this Span source) + where TFrom : struct + where TTo : struct + { + if (JitHelpers.ContainsReferences()) + ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(TFrom)); + if (JitHelpers.ContainsReferences()) + ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(TTo)); + + return new Span( + ref Unsafe.As(ref source.DangerousGetPinnableReference()), + checked((int)((long)source.Length * Unsafe.SizeOf() / Unsafe.SizeOf()))); + } + + /// + /// Casts a ReadOnlySpan of one primitive type to another primitive type . + /// These types may not contain pointers or references. This is checked at runtime in order to preserve type safety. + /// + /// + /// Supported only for platforms that support misaligned memory access. + /// + /// The source slice, of type . + /// + /// Thrown when or contains pointers. + /// + public static ReadOnlySpan NonPortableCast(this ReadOnlySpan source) + where TFrom : struct + where TTo : struct + { + if (JitHelpers.ContainsReferences()) + ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(TFrom)); + if (JitHelpers.ContainsReferences()) + ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(TTo)); + + return new ReadOnlySpan( + ref Unsafe.As(ref source.DangerousGetPinnableReference()), + checked((int)((long)source.Length * Unsafe.SizeOf() / Unsafe.SizeOf()))); + } + } + + internal static class SpanHelper + { + internal static unsafe void CopyTo(ref T destination, ref T source, int elementsCount) + { + if (elementsCount == 0) + return; + + if (Unsafe.AreSame(ref destination, ref source)) + return; + + if (!JitHelpers.ContainsReferences()) + { + fixed (byte* pDestination = &Unsafe.As(ref destination)) + { + fixed (byte* pSource = &Unsafe.As(ref source)) + { +#if BIT64 + Buffer.Memmove(pDestination, pSource, (ulong)elementsCount * (ulong)Unsafe.SizeOf()); +#else + Buffer.Memmove(pDestination, pSource, (uint)elementsCount * (uint)Unsafe.SizeOf()); +#endif + } + } + } + else + { + if (JitHelpers.ByRefLessThan(ref destination, ref source)) // copy forward + { + for (int i = 0; i < elementsCount; i++) + Unsafe.Add(ref destination, i) = Unsafe.Add(ref source, i); + } + else // copy backward to avoid overlapping issues + { + for (int i = elementsCount - 1; i >= 0; i--) + Unsafe.Add(ref destination, i) = Unsafe.Add(ref source, i); + } + } + } + } +} diff --git a/src/mscorlib/src/System/String.Comparison.cs b/src/mscorlib/src/System/String.Comparison.cs index a05f9f2..07f2f9d 100644 --- a/src/mscorlib/src/System/String.Comparison.cs +++ b/src/mscorlib/src/System/String.Comparison.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Globalization; using System.Runtime.CompilerServices; @@ -17,7 +18,6 @@ namespace System //Native Static Methods // - [System.Security.SecuritySafeCritical] // auto-generated private unsafe static int CompareOrdinalIgnoreCaseHelper(String strA, String strB) { Contract.Requires(strA != null); @@ -35,7 +35,7 @@ namespace System int charA = *a; int charB = *b; - Contract.Assert((charA | charB) <= 0x7F, "strings have to be ASCII"); + Debug.Assert((charA | charB) <= 0x7F, "strings have to be ASCII"); // uppercase both chars - notice that we need just one compare per char if ((uint)(charA - 'a') <= (uint)('z' - 'a')) charA -= 0x20; @@ -55,13 +55,11 @@ namespace System } // native call to COMString::CompareOrdinalEx - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern int CompareOrdinalHelper(String strA, int indexA, int countA, String strB, int indexB, int countB); //This will not work in case-insensitive mode for any character greater than 0x80. //We'll throw an ArgumentException. - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] unsafe internal static extern int nativeCompareOrdinalIgnoreCaseWC(String strA, sbyte *strBBytes); @@ -75,7 +73,6 @@ namespace System // Search/Query methods // - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] private unsafe static bool EqualsHelper(String strA, String strB) { @@ -137,7 +134,6 @@ namespace System } } - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] private unsafe static bool StartsWithOrdinalHelper(String str, String startsWith) { @@ -155,7 +151,7 @@ namespace System #if BIT64 // Single int read aligns pointers for the following long reads // No length check needed as this method is called when length >= 2 - Contract.Assert(length >= 2); + Debug.Assert(length >= 2); if (*(int*)a != *(int*)b) goto ReturnFalse; length -= 2; a += 2; b += 2; @@ -194,7 +190,6 @@ namespace System } } - [System.Security.SecuritySafeCritical] // auto-generated private unsafe static int CompareOrdinalHelper(String strA, String strB) { Contract.Requires(strA != null); @@ -202,7 +197,7 @@ namespace System // NOTE: This may be subject to change if eliminating the check // in the callers makes them small enough to be inlined by the JIT - Contract.Assert(strA.m_firstChar == strB.m_firstChar, + Debug.Assert(strA.m_firstChar == strB.m_firstChar, "For performance reasons, callers of this method should " + "check/short-circuit beforehand if the first char is the same."); @@ -310,7 +305,7 @@ namespace System if (*a != *b) return *a - *b; DiffOffset1: - Contract.Assert(*(a + 1) != *(b + 1), "This char must be different if we reach here!"); + Debug.Assert(*(a + 1) != *(b + 1), "This char must be different if we reach here!"); return *(a + 1) - *(b + 1); } } @@ -342,13 +337,12 @@ namespace System // Provides a more flexible function for string comparision. See StringComparison // for meaning of different comparisonType. [Pure] - [System.Security.SecuritySafeCritical] // auto-generated public static int Compare(String strA, String strB, StringComparison comparisonType) { // Single comparison to check if comparisonType is within [CurrentCulture .. OrdinalIgnoreCase] if ((uint)(comparisonType - StringComparison.CurrentCulture) > (uint)(StringComparison.OrdinalIgnoreCase - StringComparison.CurrentCulture)) { - throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType"); + throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType)); } Contract.EndContractBlock(); @@ -417,7 +411,7 @@ namespace System public static int Compare(String strA, String strB, CultureInfo culture, CompareOptions options) { if (culture == null) { - throw new ArgumentNullException("culture"); + throw new ArgumentNullException(nameof(culture)); } Contract.EndContractBlock(); @@ -511,7 +505,7 @@ namespace System { if (culture == null) { - throw new ArgumentNullException("culture"); + throw new ArgumentNullException(nameof(culture)); } Contract.EndContractBlock(); @@ -532,10 +526,9 @@ namespace System } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated public static int Compare(String strA, int indexA, String strB, int indexB, int length, StringComparison comparisonType) { if (comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase) { - throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType"); + throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType)); } Contract.EndContractBlock(); @@ -552,18 +545,18 @@ namespace System if (length < 0) { - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NegativeLength")); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_NegativeLength")); } if (indexA < 0 || indexB < 0) { - string paramName = indexA < 0 ? "indexA" : "indexB"; + string paramName = indexA < 0 ? nameof(indexA) : nameof(indexB); throw new ArgumentOutOfRangeException(paramName, Environment.GetResourceString("ArgumentOutOfRange_Index")); } if (strA.Length - indexA < 0 || strB.Length - indexB < 0) { - string paramName = strA.Length - indexA < 0 ? "indexA" : "indexB"; + string paramName = strA.Length - indexA < 0 ? nameof(indexA) : nameof(indexB); throw new ArgumentOutOfRangeException(paramName, Environment.GetResourceString("ArgumentOutOfRange_Index")); } @@ -638,7 +631,6 @@ namespace System // Compares strA and strB using an ordinal (code-point) comparison. // [Pure] - [System.Security.SecuritySafeCritical] // auto-generated public static int CompareOrdinal(String strA, int indexA, String strB, int indexB, int length) { if (strA == null || strB == null) @@ -657,12 +649,12 @@ namespace System if (length < 0) { - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NegativeCount")); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_NegativeCount")); } if (indexA < 0 || indexB < 0) { - string paramName = indexA < 0 ? "indexA" : "indexB"; + string paramName = indexA < 0 ? nameof(indexA) : nameof(indexB); throw new ArgumentOutOfRangeException(paramName, Environment.GetResourceString("ArgumentOutOfRange_Index")); } @@ -671,7 +663,7 @@ namespace System if (lengthA < 0 || lengthB < 0) { - string paramName = lengthA < 0 ? "indexA" : "indexB"; + string paramName = lengthA < 0 ? nameof(indexA) : nameof(indexB); throw new ArgumentOutOfRangeException(paramName, Environment.GetResourceString("ArgumentOutOfRange_Index")); } @@ -724,15 +716,14 @@ namespace System } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated [ComVisible(false)] public Boolean EndsWith(String value, StringComparison comparisonType) { if( (Object)value == null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } if( comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase) { - throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType"); + throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType)); } Contract.EndContractBlock(); @@ -767,14 +758,14 @@ namespace System return this.Length < value.Length ? false : (TextInfo.CompareOrdinalIgnoreCaseEx(this, this.Length - value.Length, value, 0, value.Length, value.Length) == 0); #endif default: - throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType"); + throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType)); } } [Pure] public Boolean EndsWith(String value, Boolean ignoreCase, CultureInfo culture) { if (null==value) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); @@ -846,10 +837,9 @@ namespace System } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated public bool Equals(String value, StringComparison comparisonType) { if (comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase) - throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType"); + throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType)); Contract.EndContractBlock(); if ((Object)this == (Object)value) { @@ -895,7 +885,7 @@ namespace System #endif default: - throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType"); + throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType)); } } @@ -915,10 +905,9 @@ namespace System } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated public static bool Equals(String a, String b, StringComparison comparisonType) { if (comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase) - throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType"); + throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType)); Contract.EndContractBlock(); if ((Object)a==(Object)b) { @@ -966,7 +955,7 @@ namespace System } default: - throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType"); + throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType)); } } @@ -981,16 +970,13 @@ namespace System #if FEATURE_RANDOMIZED_STRING_HASHING // Do not remove! // This method is called by reflection in System.Xml - [System.Security.SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern int InternalMarvin32HashString(string s, int strLen, long additionalEntropy); - [System.Security.SecuritySafeCritical] internal static bool UseRandomizedHashing() { return InternalUseRandomizedHashing(); } - [System.Security.SecurityCritical] [System.Security.SuppressUnmanagedCodeSecurity] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] private static extern bool InternalUseRandomizedHashing(); @@ -998,7 +984,6 @@ namespace System // Gets a hash code for this string. If strings A and B are such that A.Equals(B), then // they will return the same hash code. - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public override int GetHashCode() { @@ -1012,15 +997,19 @@ namespace System return GetLegacyNonRandomizedHashCode(); } + // Gets a hash code for this string and this comparison. If strings A and B and comparition C are such + // that String.Equals(A, B, C), then they will return the same hash code with this comparison C. + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + public int GetHashCode(StringComparison comparisonType) => StringComparer.FromComparison(comparisonType).GetHashCode(this); + // Use this if and only if you need the hashcode to not change across app domains (e.g. you have an app domain agile // hash table). - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal int GetLegacyNonRandomizedHashCode() { unsafe { fixed (char* src = &m_firstChar) { - Contract.Assert(src[this.Length] == '\0', "src[this.Length] == '\\0'"); - Contract.Assert( ((int)src)%4 == 0, "Managed string should start at 4 bytes boundary"); + Debug.Assert(src[this.Length] == '\0', "src[this.Length] == '\\0'"); + Debug.Assert( ((int)src)%4 == 0, "Managed string should start at 4 bytes boundary"); #if BIT64 int hash1 = 5381; #else // !BIT64 (32) @@ -1073,22 +1062,21 @@ namespace System [Pure] public Boolean StartsWith(String value) { if ((Object)value == null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); return StartsWith(value, StringComparison.CurrentCulture); } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated [ComVisible(false)] public Boolean StartsWith(String value, StringComparison comparisonType) { if( (Object)value == null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } if( comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase) { - throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType"); + throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType)); } Contract.EndContractBlock(); @@ -1133,14 +1121,14 @@ namespace System #endif default: - throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType"); + throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType)); } } [Pure] public Boolean StartsWith(String value, Boolean ignoreCase, CultureInfo culture) { if (null==value) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/String.Manipulation.cs b/src/mscorlib/src/System/String.Manipulation.cs index e9568a6..194b4f8 100644 --- a/src/mscorlib/src/System/String.Manipulation.cs +++ b/src/mscorlib/src/System/String.Manipulation.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Globalization; using System.Runtime.CompilerServices; @@ -17,7 +18,6 @@ namespace System private const int TrimTail = 1; private const int TrimBoth = 2; - [System.Security.SecuritySafeCritical] // auto-generated unsafe private static void FillStringChecked(String dest, int destPos, String src) { Contract.Requires(dest != null); @@ -109,12 +109,11 @@ namespace System return Concat(objArgs); } - [System.Security.SecuritySafeCritical] public static string Concat(params object[] args) { if (args == null) { - throw new ArgumentNullException("args"); + throw new ArgumentNullException(nameof(args)); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -167,8 +166,8 @@ namespace System { string s = strings[i]; - Contract.Assert(s != null); - Contract.Assert(position <= totalLength - s.Length, "We didn't allocate enough space for the result string!"); + Debug.Assert(s != null); + Debug.Assert(position <= totalLength - s.Length, "We didn't allocate enough space for the result string!"); FillStringChecked(result, position, s); position += s.Length; @@ -181,7 +180,7 @@ namespace System public static string Concat(IEnumerable values) { if (values == null) - throw new ArgumentNullException("values"); + throw new ArgumentNullException(nameof(values)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -232,7 +231,7 @@ namespace System public static string Concat(IEnumerable values) { if (values == null) - throw new ArgumentNullException("values"); + throw new ArgumentNullException(nameof(values)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -262,7 +261,6 @@ namespace System } - [System.Security.SecuritySafeCritical] // auto-generated public static String Concat(String str0, String str1) { Contract.Ensures(Contract.Result() != null); Contract.Ensures(Contract.Result().Length == @@ -291,7 +289,6 @@ namespace System return result; } - [System.Security.SecuritySafeCritical] // auto-generated public static String Concat(String str0, String str1, String str2) { Contract.Ensures(Contract.Result() != null); Contract.Ensures(Contract.Result().Length == @@ -325,7 +322,6 @@ namespace System return result; } - [System.Security.SecuritySafeCritical] // auto-generated public static String Concat(String str0, String str1, String str2, String str3) { Contract.Ensures(Contract.Result() != null); Contract.Ensures(Contract.Result().Length == @@ -366,10 +362,9 @@ namespace System return result; } - [System.Security.SecuritySafeCritical] public static String Concat(params String[] values) { if (values == null) - throw new ArgumentNullException("values"); + throw new ArgumentNullException(nameof(values)); Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -456,7 +451,7 @@ namespace System { // To preserve the original exception behavior, throw an exception about format if both // args and format are null. The actual null check for format is in FormatHelper. - throw new ArgumentNullException((format == null) ? "format" : "args"); + throw new ArgumentNullException((format == null) ? nameof(format) : nameof(args)); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -484,7 +479,7 @@ namespace System { // To preserve the original exception behavior, throw an exception about format if both // args and format are null. The actual null check for format is in FormatHelper. - throw new ArgumentNullException((format == null) ? "format" : "args"); + throw new ArgumentNullException((format == null) ? nameof(format) : nameof(args)); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -494,7 +489,7 @@ namespace System private static String FormatHelper(IFormatProvider provider, String format, ParamsArray args) { if (format == null) - throw new ArgumentNullException("format"); + throw new ArgumentNullException(nameof(format)); return StringBuilderCache.GetStringAndRelease( StringBuilderCache @@ -502,13 +497,12 @@ namespace System .AppendFormatHelper(provider, format, args)); } - [System.Security.SecuritySafeCritical] // auto-generated public String Insert(int startIndex, String value) { if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); if (startIndex < 0 || startIndex > this.Length) - throw new ArgumentOutOfRangeException("startIndex"); + throw new ArgumentOutOfRangeException(nameof(startIndex)); Contract.Ensures(Contract.Result() != null); Contract.Ensures(Contract.Result().Length == this.Length + value.Length); Contract.EndContractBlock(); @@ -541,27 +535,131 @@ namespace System } return result; } + + public static string Join(char separator, params string[] value) + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + return Join(separator, value, 0, value.Length); + } + + public unsafe static string Join(char separator, params object[] values) + { + // Defer argument validation to the internal function + return JoinCore(&separator, 1, values); + } + + public unsafe static string Join(char separator, IEnumerable values) + { + // Defer argument validation to the internal function + return JoinCore(&separator, 1, values); + } + + public unsafe static string Join(char separator, string[] value, int startIndex, int count) + { + // Defer argument validation to the internal function + return JoinCore(&separator, 1, value, startIndex, count); + } // Joins an array of strings together as one string with a separator between each original string. // - public static String Join(String separator, params String[] value) { - if (value==null) - throw new ArgumentNullException("value"); - Contract.EndContractBlock(); + public static string Join(string separator, params string[] value) + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } return Join(separator, value, 0, value.Length); } [ComVisible(false)] - public static string Join(string separator, params object[] values) + public unsafe static string Join(string separator, params object[] values) + { + separator = separator ?? string.Empty; + fixed (char* pSeparator = &separator.m_firstChar) + { + // Defer argument validation to the internal function + return JoinCore(pSeparator, separator.Length, values); + } + } + + [ComVisible(false)] + public unsafe static string Join(string separator, IEnumerable values) + { + separator = separator ?? string.Empty; + fixed (char* pSeparator = &separator.m_firstChar) + { + // Defer argument validation to the internal function + return JoinCore(pSeparator, separator.Length, values); + } + } + + [ComVisible(false)] + public static string Join(string separator, IEnumerable values) { if (values == null) - throw new ArgumentNullException("values"); - Contract.EndContractBlock(); + { + throw new ArgumentNullException(nameof(values)); + } + + using (IEnumerator en = values.GetEnumerator()) + { + if (!en.MoveNext()) + { + return string.Empty; + } + + string firstValue = en.Current; - if (values.Length == 0 || values[0] == null) + if (!en.MoveNext()) + { + // Only one value available + return firstValue ?? string.Empty; + } + + // Null separator and values are handled by the StringBuilder + StringBuilder result = StringBuilderCache.Acquire(); + result.Append(firstValue); + + do + { + result.Append(separator); + result.Append(en.Current); + } + while (en.MoveNext()); + + return StringBuilderCache.GetStringAndRelease(result); + } + } + + // Joins an array of strings together as one string with a separator between each original string. + // + public unsafe static string Join(string separator, string[] value, int startIndex, int count) + { + separator = separator ?? string.Empty; + fixed (char* pSeparator = &separator.m_firstChar) + { + // Defer argument validation to the internal function + return JoinCore(pSeparator, separator.Length, value, startIndex, count); + } + } + + private unsafe static string JoinCore(char* separator, int separatorLength, object[] values) + { + if (values == null) + { + throw new ArgumentNullException(nameof(values)); + } + + if (values.Length == 0) + { return string.Empty; + } - string firstString = values[0].ToString(); + string firstString = values[0]?.ToString(); if (values.Length == 1) { @@ -573,7 +671,7 @@ namespace System for (int i = 1; i < values.Length; i++) { - result.Append(separator); + result.Append(separator, separatorLength); object value = values[i]; if (value != null) { @@ -584,18 +682,19 @@ namespace System return StringBuilderCache.GetStringAndRelease(result); } - [ComVisible(false)] - public static String Join(String separator, IEnumerable values) + private unsafe static string JoinCore(char* separator, int separatorLength, IEnumerable values) { if (values == null) - throw new ArgumentNullException("values"); - Contract.Ensures(Contract.Result() != null); - Contract.EndContractBlock(); + { + throw new ArgumentNullException(nameof(values)); + } using (IEnumerator en = values.GetEnumerator()) { if (!en.MoveNext()) + { return string.Empty; + } // We called MoveNext once, so this will be the first item T currentValue = en.Current; @@ -616,14 +715,14 @@ namespace System } StringBuilder result = StringBuilderCache.Acquire(); - + result.Append(firstString); do { currentValue = en.Current; - result.Append(separator); + result.Append(separator, separatorLength); if (currentValue != null) { result.Append(currentValue.ToString()); @@ -635,107 +734,113 @@ namespace System } } - [ComVisible(false)] - public static String Join(String separator, IEnumerable values) { - if (values == null) - throw new ArgumentNullException("values"); - Contract.Ensures(Contract.Result() != null); - Contract.EndContractBlock(); - - using(IEnumerator en = values.GetEnumerator()) { - if (!en.MoveNext()) - return String.Empty; - - String firstValue = en.Current; - - if (!en.MoveNext()) { - // Only one value available - return firstValue ?? String.Empty; - } - - // Null separator and values are handled by the StringBuilder - StringBuilder result = StringBuilderCache.Acquire(); - result.Append(firstValue); - - do { - result.Append(separator); - result.Append(en.Current); - } while (en.MoveNext()); - return StringBuilderCache.GetStringAndRelease(result); - } - } + private unsafe static string JoinCore(char* separator, int separatorLength, string[] value, int startIndex, int count) + { + // If the separator is null, it is converted to an empty string before entering this function. + // Even for empty strings, fixed should never return null (it should return a pointer to a null char). + Debug.Assert(separator != null); + Debug.Assert(separatorLength >= 0); - // Joins an array of strings together as one string with a separator between each original string. - // - [System.Security.SecuritySafeCritical] // auto-generated - public unsafe static String Join(String separator, String[] value, int startIndex, int count) { - //Range check the array if (value == null) - throw new ArgumentNullException("value"); - + { + throw new ArgumentNullException(nameof(value)); + } if (startIndex < 0) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); + { + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); + } if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NegativeCount")); - + { + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NegativeCount")); + } if (startIndex > value.Length - count) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); - Contract.EndContractBlock(); - - //Treat null as empty string. - if (separator == null) { - separator = String.Empty; + { + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); } - - //If count is 0, that skews a whole bunch of the calculations below, so just special case that. - if (count == 0) { - return String.Empty; + + if (count <= 1) + { + return count == 0 ? + string.Empty : + value[startIndex] ?? string.Empty; } - if (count == 1) { - return value[startIndex] ?? String.Empty; + long totalSeparatorsLength = (long)(count - 1) * separatorLength; + if (totalSeparatorsLength > int.MaxValue) + { + throw new OutOfMemoryException(); } + int totalLength = (int)totalSeparatorsLength; - int jointLength = 0; - //Figure out the total length of the strings in value - int endIndex = startIndex + count - 1; - for (int stringToJoinIndex = startIndex; stringToJoinIndex <= endIndex; stringToJoinIndex++) { - string currentValue = value[stringToJoinIndex]; - - if (currentValue != null) { - jointLength += currentValue.Length; + // Calculate the length of the resultant string so we know how much space to allocate. + for (int i = startIndex, end = startIndex + count; i < end; i++) + { + string currentValue = value[i]; + if (currentValue != null) + { + totalLength += currentValue.Length; + if (totalLength < 0) // Check for overflow + { + throw new OutOfMemoryException(); + } } } - - //Add enough room for the separator. - jointLength += (count - 1) * separator.Length; - // Note that we may not catch all overflows with this check (since we could have wrapped around the 4gb range any number of times - // and landed back in the positive range.) The input array might be modifed from other threads, - // so we have to do an overflow check before each append below anyway. Those overflows will get caught down there. - if ((jointLength < 0) || ((jointLength + 1) < 0) ) { - throw new OutOfMemoryException(); - } + // Copy each of the strings into the resultant buffer, interleaving with the separator. + string result = FastAllocateString(totalLength); + int copiedLength = 0; - //If this is an empty string, just return. - if (jointLength == 0) { - return String.Empty; - } + for (int i = startIndex, end = startIndex + count; i < end; i++) + { + // It's possible that another thread may have mutated the input array + // such that our second read of an index will not be the same string + // we got during the first read. - string jointString = FastAllocateString( jointLength ); - fixed (char * pointerToJointString = &jointString.m_firstChar) { - UnSafeCharBuffer charBuffer = new UnSafeCharBuffer( pointerToJointString, jointLength); - - // Append the first string first and then append each following string prefixed by the separator. - charBuffer.AppendString( value[startIndex] ); - for (int stringToJoinIndex = startIndex + 1; stringToJoinIndex <= endIndex; stringToJoinIndex++) { - charBuffer.AppendString( separator ); - charBuffer.AppendString( value[stringToJoinIndex] ); + // We range check again to avoid buffer overflows if this happens. + + string currentValue = value[i]; + if (currentValue != null) + { + int valueLen = currentValue.Length; + if (valueLen > totalLength - copiedLength) + { + copiedLength = -1; + break; + } + + // Fill in the value. + FillStringChecked(result, copiedLength, currentValue); + copiedLength += valueLen; + } + + if (i < end - 1) + { + // Fill in the separator. + fixed (char* pResult = &result.m_firstChar) + { + // If we are called from the char-based overload, we will not + // want to call MemoryCopy each time we fill in the separator. So + // specialize for 1-length separators. + if (separatorLength == 1) + { + pResult[copiedLength] = *separator; + } + else + { + wstrcpy(pResult + copiedLength, separator, separatorLength); + } + } + copiedLength += separatorLength; } - Contract.Assert(*(pointerToJointString + charBuffer.Length) == '\0', "String must be null-terminated!"); } - return jointString; + // If we copied exactly the right amount, return the new string. Otherwise, + // something changed concurrently to mutate the input array: fall back to + // doing the concatenation again, but this time with a defensive copy. This + // fall back should be extremely rare. + return copiedLength == totalLength ? + result : + JoinCore(separator, separatorLength, (string[])value.Clone(), startIndex, count); } // @@ -746,10 +851,9 @@ namespace System } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated public String PadLeft(int totalWidth, char paddingChar) { if (totalWidth < 0) - throw new ArgumentOutOfRangeException("totalWidth", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(totalWidth), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); int oldLength = Length; int count = totalWidth - oldLength; if (count <= 0) @@ -776,10 +880,9 @@ namespace System } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated public String PadRight(int totalWidth, char paddingChar) { if (totalWidth < 0) - throw new ArgumentOutOfRangeException("totalWidth", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(totalWidth), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); int oldLength = Length; int count = totalWidth - oldLength; if (count <= 0) @@ -800,17 +903,16 @@ namespace System return result; } - [System.Security.SecuritySafeCritical] // auto-generated public String Remove(int startIndex, int count) { if (startIndex < 0) - throw new ArgumentOutOfRangeException("startIndex", + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); if (count < 0) - throw new ArgumentOutOfRangeException("count", + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NegativeCount")); if (count > Length - startIndex) - throw new ArgumentOutOfRangeException("count", + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_IndexCount")); Contract.Ensures(Contract.Result() != null); Contract.Ensures(Contract.Result().Length == this.Length - count); @@ -840,12 +942,12 @@ namespace System // a remove that just takes a startindex. public string Remove( int startIndex ) { if (startIndex < 0) { - throw new ArgumentOutOfRangeException("startIndex", + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); } if (startIndex >= Length) { - throw new ArgumentOutOfRangeException("startIndex", + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_StartIndexLessThanLength")); } @@ -857,7 +959,6 @@ namespace System // Replaces all instances of oldChar with newChar. // - [System.Security.SecuritySafeCritical] // auto-generated public String Replace(char oldChar, char newChar) { Contract.Ensures(Contract.Result() != null); @@ -928,14 +1029,13 @@ namespace System // This method contains the same functionality as StringBuilder Replace. The only difference is that // a new String has to be allocated since Strings are immutable - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern String ReplaceInternal(String oldValue, String newValue); public String Replace(String oldValue, String newValue) { if (oldValue == null) - throw new ArgumentNullException("oldValue"); + throw new ArgumentNullException(nameof(oldValue)); // Note that if newValue is null, we treat it like String.Empty. Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -944,19 +1044,13 @@ namespace System } [ComVisible(false)] - public String[] Split(char separator) { - Contract.Ensures(Contract.Result() != null); - return SplitInternal(separator, Int32.MaxValue, StringSplitOptions.None); - } - - [ComVisible(false)] - public String[] Split(char separator, StringSplitOptions options) { + public String[] Split(char separator, StringSplitOptions options = StringSplitOptions.None) { Contract.Ensures(Contract.Result() != null); return SplitInternal(separator, Int32.MaxValue, options); } [ComVisible(false)] - public String[] Split(char separator, int count, StringSplitOptions options) { + public String[] Split(char separator, int count, StringSplitOptions options = StringSplitOptions.None) { Contract.Ensures(Contract.Result() != null); return SplitInternal(separator, count, options); } @@ -1004,33 +1098,24 @@ namespace System return SplitInternal(separator, count, options); } - [System.Security.SecuritySafeCritical] private unsafe String[] SplitInternal(char separator, int count, StringSplitOptions options) { - char* pSeparators = stackalloc char[1]; - pSeparators[0] = separator; - return SplitInternal(pSeparators, /*separatorsLength*/ 1, count, options); + return SplitInternal(&separator, 1, count, options); } - [ComVisible(false)] - [System.Security.SecuritySafeCritical] - internal String[] SplitInternal(char[] separator, int count, StringSplitOptions options) + private unsafe String[] SplitInternal(char[] separator, int count, StringSplitOptions options) { - unsafe + fixed (char* pSeparators = separator) { - fixed (char* pSeparators = separator) - { - int separatorsLength = separator == null ? 0 : separator.Length; - return SplitInternal(pSeparators, separatorsLength, count, options); - } + int separatorsLength = separator == null ? 0 : separator.Length; + return SplitInternal(pSeparators, separatorsLength, count, options); } } - [System.Security.SecurityCritical] private unsafe String[] SplitInternal(char* separators, int separatorsLength, int count, StringSplitOptions options) { if (count < 0) - throw new ArgumentOutOfRangeException("count", + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NegativeCount")); if (options < StringSplitOptions.None || options > StringSplitOptions.RemoveEmptyEntries) @@ -1041,14 +1126,8 @@ namespace System bool omitEmptyEntries = (options == StringSplitOptions.RemoveEmptyEntries); if ((count == 0) || (omitEmptyEntries && this.Length == 0)) - { -#if FEATURE_CORECLR + { return EmptyArray.Value; -#else - // Keep the old behavior of returning a new empty array - // to mitigate any potential compat risk. - return new String[0]; -#endif } if (count == 1) @@ -1056,38 +1135,32 @@ namespace System return new String[] { this }; } - int[] sepList = new int[Length]; + int[] sepList = new int[Length]; int numReplaces = MakeSeparatorList(separators, separatorsLength, sepList); // Handle the special case of no replaces. if (0 == numReplaces) { return new String[] { this }; - } + } if(omitEmptyEntries) { - return InternalSplitOmitEmptyEntries(sepList, null, 1, numReplaces, count); + return SplitOmitEmptyEntries(sepList, null, 1, numReplaces, count); } else { - return InternalSplitKeepEmptyEntries(sepList, null, 1, numReplaces, count); - } - } - - [ComVisible(false)] - public String[] Split(String separator) { - Contract.Ensures(Contract.Result() != null); - return SplitInternal(separator ?? String.Empty, null, Int32.MaxValue, StringSplitOptions.None); + return SplitKeepEmptyEntries(sepList, null, 1, numReplaces, count); + } } [ComVisible(false)] - public String[] Split(String separator, StringSplitOptions options) { + public String[] Split(String separator, StringSplitOptions options = StringSplitOptions.None) { Contract.Ensures(Contract.Result() != null); return SplitInternal(separator ?? String.Empty, null, Int32.MaxValue, options); } [ComVisible(false)] - public String[] Split(String separator, Int32 count, StringSplitOptions options) { + public String[] Split(String separator, Int32 count, StringSplitOptions options = StringSplitOptions.None) { Contract.Ensures(Contract.Result() != null); return SplitInternal(separator ?? String.Empty, null, count, options); } @@ -1107,7 +1180,7 @@ namespace System private String[] SplitInternal(String separator, String[] separators, Int32 count, StringSplitOptions options) { if (count < 0) { - throw new ArgumentOutOfRangeException("count", + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NegativeCount")); } @@ -1125,23 +1198,13 @@ namespace System } if ((count == 0) || (omitEmptyEntries && this.Length ==0)) { -#if FEATURE_CORECLR return EmptyArray.Value; -#else - // Keep the old behavior of returning a new empty array - // to mitigate any potential compat risk. - return new String[0]; -#endif } - if (count == 1) { + if (count == 1 || (singleSeparator && separator.Length == 0)) { return new String[] { this }; } - if (singleSeparator && separator.Length == 0) { - return new[] { this }; - } - int[] sepList = new int[Length]; int[] lengthList; int defaultLength; @@ -1164,10 +1227,10 @@ namespace System } if (omitEmptyEntries) { - return InternalSplitOmitEmptyEntries(sepList, lengthList, defaultLength, numReplaces, count); + return SplitOmitEmptyEntries(sepList, lengthList, defaultLength, numReplaces, count); } else { - return InternalSplitKeepEmptyEntries(sepList, lengthList, defaultLength, numReplaces, count); + return SplitKeepEmptyEntries(sepList, lengthList, defaultLength, numReplaces, count); } } @@ -1176,7 +1239,7 @@ namespace System // the original string will be returned regardless of the count. // - private String[] InternalSplitKeepEmptyEntries(Int32[] sepList, Int32[] lengthList, Int32 defaultLength, Int32 numReplaces, int count) { + private String[] SplitKeepEmptyEntries(Int32[] sepList, Int32[] lengthList, Int32 defaultLength, Int32 numReplaces, int count) { Contract.Requires(numReplaces >= 0); Contract.Requires(count >= 2); Contract.Ensures(Contract.Result() != null); @@ -1212,7 +1275,7 @@ namespace System // This function will not keep the Empty String - private String[] InternalSplitOmitEmptyEntries(Int32[] sepList, Int32[] lengthList, Int32 defaultLength, Int32 numReplaces, int count) { + private String[] SplitOmitEmptyEntries(Int32[] sepList, Int32[] lengthList, Int32 defaultLength, Int32 numReplaces, int count) { Contract.Requires(numReplaces >= 0); Contract.Requires(count >= 2); Contract.Ensures(Contract.Result() != null); @@ -1242,7 +1305,7 @@ namespace System } // we must have at least one slot left to fill in the last string. - Contract.Assert(arrIndex < maxItems); + Debug.Assert(arrIndex < maxItems); //Handle the last string at the end of the array if there is one. if (currIndex< Length) { @@ -1265,9 +1328,8 @@ namespace System // Args: separator -- A string containing all of the split characters. // sepList -- an array of ints for split char indicies. //-------------------------------------------------------------------- - [System.Security.SecurityCritical] private unsafe int MakeSeparatorList(char* separators, int separatorsLength, int[] sepList) { - Contract.Assert(separatorsLength >= 0, "separatorsLength >= 0"); + Debug.Assert(separatorsLength >= 0, "separatorsLength >= 0"); int foundCount=0; if (separators == null || separatorsLength == 0) { @@ -1304,9 +1366,8 @@ namespace System // Args: separator -- the separator // sepList -- an array of ints for split string indicies. //-------------------------------------------------------------------- - [System.Security.SecuritySafeCritical] // auto-generated private unsafe int MakeSeparatorList(string separator, int[] sepList) { - Contract.Assert(!string.IsNullOrEmpty(separator), "!string.IsNullOrEmpty(separator)"); + Debug.Assert(!string.IsNullOrEmpty(separator), "!string.IsNullOrEmpty(separator)"); int foundCount = 0; int sepListCount = sepList.Length; @@ -1334,9 +1395,8 @@ namespace System // sepList -- an array of ints for split string indicies. // lengthList -- an array of ints for split string lengths. //-------------------------------------------------------------------- - [System.Security.SecuritySafeCritical] // auto-generated private unsafe int MakeSeparatorList(String[] separators, int[] sepList, int[] lengthList) { - Contract.Assert(separators != null && separators.Length > 0, "separators != null && separators.Length > 0"); + Debug.Assert(separators != null && separators.Length > 0, "separators != null && separators.Length > 0"); int foundCount = 0; int sepListCount = sepList.Length; @@ -1374,24 +1434,23 @@ namespace System // Returns a substring of this string. // - [System.Security.SecuritySafeCritical] // auto-generated public String Substring(int startIndex, int length) { //Bounds Checking. if (startIndex < 0) { - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); } if (startIndex > Length) { - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndexLargerThanLength")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_StartIndexLargerThanLength")); } if (length < 0) { - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NegativeLength")); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_NegativeLength")); } if (startIndex > Length - length) { - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_IndexLength")); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_IndexLength")); } Contract.EndContractBlock(); @@ -1406,10 +1465,9 @@ namespace System return InternalSubString(startIndex, length); } - [System.Security.SecurityCritical] // auto-generated unsafe string InternalSubString(int startIndex, int length) { - Contract.Assert( startIndex >= 0 && startIndex <= this.Length, "StartIndex is out of range!"); - Contract.Assert( length >= 0 && startIndex <= this.Length - length, "length is out of range!"); + Debug.Assert( startIndex >= 0 && startIndex <= this.Length, "StartIndex is out of range!"); + Debug.Assert( length >= 0 && startIndex <= this.Length - length, "length is out of range!"); String result = FastAllocateString(length); @@ -1434,7 +1492,7 @@ namespace System public String ToLower(CultureInfo culture) { if (culture == null) { - throw new ArgumentNullException("culture"); + throw new ArgumentNullException(nameof(culture)); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -1463,7 +1521,7 @@ namespace System public String ToUpper(CultureInfo culture) { if (culture == null) { - throw new ArgumentNullException("culture"); + throw new ArgumentNullException(nameof(culture)); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -1517,7 +1575,6 @@ namespace System } - [System.Security.SecuritySafeCritical] // auto-generated private String TrimHelper(int trimType) { //end will point to the first non-trimmed character on the right //start will point to the first non-trimmed character on the Left @@ -1541,7 +1598,6 @@ namespace System } - [System.Security.SecuritySafeCritical] // auto-generated private String TrimHelper(char[] trimChars, int trimType) { //end will point to the first non-trimmed character on the right //start will point to the first non-trimmed character on the Left @@ -1579,7 +1635,6 @@ namespace System } - [System.Security.SecurityCritical] // auto-generated private String CreateTrimmedString(int start, int end) { int len = end -start + 1; if (len == this.Length) { diff --git a/src/mscorlib/src/System/String.Searching.cs b/src/mscorlib/src/System/String.Searching.cs index b972529..2620cfd 100644 --- a/src/mscorlib/src/System/String.Searching.cs +++ b/src/mscorlib/src/System/String.Searching.cs @@ -29,13 +29,12 @@ namespace System } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated public unsafe int IndexOf(char value, int startIndex, int count) { if (startIndex < 0 || startIndex > Length) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); if (count < 0 || count > Length - startIndex) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); fixed (char* pChars = &m_firstChar) { @@ -85,7 +84,6 @@ namespace System } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern int IndexOfAny(char [] anyOf, int startIndex, int count); @@ -116,11 +114,11 @@ namespace System [Pure] public int IndexOf(String value, int startIndex, int count) { if (startIndex < 0 || startIndex > this.Length) { - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); } if (count < 0 || count > this.Length - startIndex) { - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); } Contract.EndContractBlock(); @@ -138,17 +136,16 @@ namespace System } [Pure] - [System.Security.SecuritySafeCritical] public int IndexOf(String value, int startIndex, int count, StringComparison comparisonType) { // Validate inputs if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); if (startIndex < 0 || startIndex > this.Length) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); if (count < 0 || startIndex > this.Length - count) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); Contract.EndContractBlock(); switch (comparisonType) { @@ -174,7 +171,7 @@ namespace System return TextInfo.IndexOfStringOrdinalIgnoreCase(this, value, startIndex, count); default: - throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType"); + throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType)); } } @@ -194,16 +191,15 @@ namespace System } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated public unsafe int LastIndexOf(char value, int startIndex, int count) { if (Length == 0) return -1; if (startIndex < 0 || startIndex >= Length) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); if (count < 0 || count - 1 > startIndex) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); fixed (char* pChars = &m_firstChar) { @@ -258,7 +254,6 @@ namespace System } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern int LastIndexOfAny(char [] anyOf, int startIndex, int count); @@ -281,7 +276,7 @@ namespace System [Pure] public int LastIndexOf(String value, int startIndex, int count) { if (count<0) { - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); } Contract.EndContractBlock(); @@ -299,10 +294,9 @@ namespace System } [Pure] - [System.Security.SecuritySafeCritical] public int LastIndexOf(String value, int startIndex, int count, StringComparison comparisonType) { if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); Contract.EndContractBlock(); // Special case for 0 length input strings @@ -311,7 +305,7 @@ namespace System // Now after handling empty strings, make sure we're not out of range if (startIndex < 0 || startIndex > this.Length) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); // Make sure that we allow startIndex == this.Length if (startIndex == this.Length) @@ -327,7 +321,7 @@ namespace System // 2nd half of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0. if (count < 0 || startIndex - count + 1 < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); switch (comparisonType) { @@ -351,7 +345,7 @@ namespace System else return TextInfo.LastIndexOfStringOrdinalIgnoreCase(this, value, startIndex, count); default: - throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType"); + throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType)); } } } diff --git a/src/mscorlib/src/System/String.cs b/src/mscorlib/src/System/String.cs index d406fd0..f9162ff 100644 --- a/src/mscorlib/src/System/String.cs +++ b/src/mscorlib/src/System/String.cs @@ -24,6 +24,7 @@ namespace System { using System.Runtime.InteropServices; using System.Runtime.Versioning; using Microsoft.Win32; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Security; @@ -67,7 +68,6 @@ namespace System { // than 0x80) before security is fully initialized. Without security initialized, we can't grab resources (the nlp's) // from the assembly. This provides a workaround for that problem and should NOT be used anywhere else. // - [System.Security.SecuritySafeCritical] // auto-generated internal unsafe static string SmallCharToUpper(string strIn) { Contract.Requires(strIn != null); Contract.EndContractBlock(); @@ -83,7 +83,7 @@ namespace System { for(int i = 0; i < length; i++) { int c = inBuff[i]; - Contract.Assert(c <= 0x7F, "string has to be ASCII"); + Debug.Assert(c <= 0x7F, "string has to be ASCII"); // uppercase - notice that we need just one compare if ((uint)(c - 'a') <= (uint)('z' - 'a')) c -= 0x20; @@ -91,7 +91,7 @@ namespace System { outBuff[i] = (char)c; } - Contract.Assert(outBuff[length]=='\0', "outBuff[length]=='\0'"); + Debug.Assert(outBuff[length]=='\0', "outBuff[length]=='\0'"); } return strOut; } @@ -102,7 +102,6 @@ namespace System { [System.Runtime.CompilerServices.IndexerName("Chars")] public extern char this[int index] { [MethodImpl(MethodImplOptions.InternalCall)] - [System.Security.SecuritySafeCritical] // public member get; } @@ -111,19 +110,18 @@ namespace System { // sourceIndex + count - 1 to the character array buffer, beginning // at destinationIndex. // - [System.Security.SecuritySafeCritical] // auto-generated unsafe public void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count) { if (destination == null) - throw new ArgumentNullException("destination"); + throw new ArgumentNullException(nameof(destination)); if (count < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NegativeCount")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NegativeCount")); if (sourceIndex < 0) - throw new ArgumentOutOfRangeException("sourceIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(sourceIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); if (count > Length - sourceIndex) - throw new ArgumentOutOfRangeException("sourceIndex", Environment.GetResourceString("ArgumentOutOfRange_IndexCount")); + throw new ArgumentOutOfRangeException(nameof(sourceIndex), Environment.GetResourceString("ArgumentOutOfRange_IndexCount")); if (destinationIndex > destination.Length - count || destinationIndex < 0) - throw new ArgumentOutOfRangeException("destinationIndex", Environment.GetResourceString("ArgumentOutOfRange_IndexCount")); + throw new ArgumentOutOfRangeException(nameof(destinationIndex), Environment.GetResourceString("ArgumentOutOfRange_IndexCount")); Contract.EndContractBlock(); // Note: fixed does not like empty arrays @@ -136,7 +134,6 @@ namespace System { } // Returns the entire string as an array of characters. - [System.Security.SecuritySafeCritical] // auto-generated unsafe public char[] ToCharArray() { int length = Length; if (length > 0) @@ -148,24 +145,19 @@ namespace System { } return chars; } - -#if FEATURE_CORECLR + return Array.Empty(); -#else - return new char[0]; -#endif } // Returns a substring of this string as an array of characters. // - [System.Security.SecuritySafeCritical] // auto-generated unsafe public char[] ToCharArray(int startIndex, int length) { // Range check everything. if (startIndex < 0 || startIndex > Length || startIndex > Length - length) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); if (length < 0) - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.EndContractBlock(); if (length > 0) @@ -177,12 +169,8 @@ namespace System { } return chars; } - -#if FEATURE_CORECLR + return Array.Empty(); -#else - return new char[0]; -#endif } [Pure] @@ -210,7 +198,6 @@ namespace System { // // Spec#: Add postcondition in a contract assembly. Potential perf problem. public extern int Length { - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] get; } @@ -218,36 +205,30 @@ namespace System { // Creates a new string with the characters copied in from ptr. If // ptr is null, a 0-length string (like String.Empty) is returned. // - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false), MethodImplAttribute(MethodImplOptions.InternalCall)] unsafe public extern String(char *value); - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false), MethodImplAttribute(MethodImplOptions.InternalCall)] unsafe public extern String(char *value, int startIndex, int length); - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false), MethodImplAttribute(MethodImplOptions.InternalCall)] unsafe public extern String(sbyte *value); - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false), MethodImplAttribute(MethodImplOptions.InternalCall)] unsafe public extern String(sbyte *value, int startIndex, int length); - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false), MethodImplAttribute(MethodImplOptions.InternalCall)] unsafe public extern String(sbyte *value, int startIndex, int length, Encoding enc); - [System.Security.SecurityCritical] // auto-generated unsafe static private String CreateString(sbyte *value, int startIndex, int length, Encoding enc) { if (enc == null) return new String(value, startIndex, length); // default to ANSI if (length < 0) - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (startIndex < 0) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); if ((value + startIndex) < value) { // overflow check - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_PartialWCHAR")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_PartialWCHAR")); } byte [] b = new byte[length]; @@ -258,7 +239,7 @@ namespace System { catch(NullReferenceException) { // If we got a NullReferencException. It means the pointer or // the index is out of range - throw new ArgumentOutOfRangeException("value", + throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_PartialWCHAR")); } @@ -267,7 +248,6 @@ namespace System { // Helper for encodings so they can talk to our buffer directly // stringLength must be the exact size we'll expect - [System.Security.SecurityCritical] // auto-generated unsafe static internal String CreateStringFromEncoding( byte* bytes, int byteLength, Encoding encoding) { @@ -276,7 +256,7 @@ namespace System { // Get our string length int stringLength = encoding.GetCharCount(bytes, byteLength, null); - Contract.Assert(stringLength >= 0, "stringLength >= 0"); + Debug.Assert(stringLength >= 0, "stringLength >= 0"); // They gave us an empty string if they needed one // 0 bytelength might be possible if there's something in an encoder @@ -287,7 +267,7 @@ namespace System { fixed(char* pTempChars = &s.m_firstChar) { int doubleCheck = encoding.GetChars(bytes, byteLength, pTempChars, stringLength, null); - Contract.Assert(stringLength == doubleCheck, + Debug.Assert(stringLength == doubleCheck, "Expected encoding.GetChars to return same length as encoding.GetCharCount"); } @@ -297,7 +277,6 @@ namespace System { // This is only intended to be used by char.ToString. // It is necessary to put the code in this class instead of Char, since m_firstChar is a private member. // Making m_firstChar internal would be dangerous since it would make it much easier to break String's immutability. - [SecuritySafeCritical] internal static string CreateFromChar(char c) { string result = FastAllocateString(1); @@ -305,7 +284,6 @@ namespace System { return result; } - [System.Security.SecuritySafeCritical] // auto-generated unsafe internal int GetBytesFromEncoding(byte* pbNativeBuffer, int cbNativeBuffer,Encoding encoding) { // encoding == Encoding.UTF8 @@ -315,10 +293,9 @@ namespace System { } } - [System.Security.SecuritySafeCritical] // auto-generated unsafe internal int ConvertToAnsi(byte *pbNativeBuffer, int cbNativeBuffer, bool fBestFit, bool fThrowOnUnmappableChar) { - Contract.Assert(cbNativeBuffer >= (Length + 1) * Marshal.SystemMaxDBCSCharSize, "Insufficient buffer length passed to ConvertToAnsi"); + Debug.Assert(cbNativeBuffer >= (Length + 1) * Marshal.SystemMaxDBCSCharSize, "Insufficient buffer length passed to ConvertToAnsi"); const uint CP_ACP = 0; int nb; @@ -363,7 +340,6 @@ namespace System { #endif } - [System.Security.SecuritySafeCritical] // auto-generated public bool IsNormalized(NormalizationForm normalizationForm) { #if !FEATURE_NORM_IDNA_ONLY @@ -391,7 +367,6 @@ namespace System { #endif } - [System.Security.SecuritySafeCritical] // auto-generated public String Normalize(NormalizationForm normalizationForm) { #if !FEATURE_NORM_IDNA_ONLY @@ -408,7 +383,6 @@ namespace System { return Normalization.Normalize(this, normalizationForm); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static String FastAllocateString(int length); @@ -416,7 +390,6 @@ namespace System { // be created from the characters in value between startIndex and // startIndex + length - 1. // - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern String(char [] value, int startIndex, int length); @@ -424,17 +397,14 @@ namespace System { // created from the characters in value. // - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern String(char [] value); - [System.Security.SecurityCritical] // auto-generated internal static unsafe void wstrcpy(char *dmem, char *smem, int charCount) { Buffer.Memcpy((byte*)dmem, (byte*)smem, charCount * 2); // 2 used everywhere instead of sizeof(char) } - [System.Security.SecuritySafeCritical] // auto-generated private String CtorCharArray(char [] value) { if (value != null && value.Length != 0) { @@ -451,20 +421,19 @@ namespace System { return String.Empty; } - [System.Security.SecuritySafeCritical] // auto-generated private String CtorCharArrayStartLength(char [] value, int startIndex, int length) { if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); if (startIndex < 0) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); if (length < 0) - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NegativeLength")); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_NegativeLength")); if (startIndex > value.Length - length) - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.EndContractBlock(); if (length > 0) { @@ -481,7 +450,6 @@ namespace System { return String.Empty; } - [System.Security.SecuritySafeCritical] // auto-generated private String CtorCharCount(char c, int count) { if (count > 0) { @@ -519,10 +487,9 @@ namespace System { else if (count == 0) return String.Empty; else - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_MustBeNonNegNum", "count")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_MustBeNonNegNum", nameof(count))); } - [System.Security.SecurityCritical] // auto-generated private static unsafe int wcslen(char *ptr) { char *end = ptr; @@ -553,7 +520,7 @@ namespace System { end += 2; } - Contract.Assert(end[0] == 0 || end[1] == 0); + Debug.Assert(end[0] == 0 || end[1] == 0); if (end[0] != 0) end++; #else // !BIT64 // Based on https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord @@ -610,14 +577,13 @@ namespace System { #endif // !BIT64 FoundZero: - Contract.Assert(*end == 0); + Debug.Assert(*end == 0); int count = (int)(end - ptr); return count; } - [System.Security.SecurityCritical] // auto-generated private unsafe String CtorCharPtr(char *ptr) { if (ptr == null) @@ -628,7 +594,7 @@ namespace System { throw new ArgumentException(Environment.GetResourceString("Arg_MustBeStringPtrNotAtom")); #endif // FEATURE_PAL - Contract.Assert(this == null, "this == null"); // this is the string constructor, we allocate it + Debug.Assert(this == null, "this == null"); // this is the string constructor, we allocate it try { int count = wcslen(ptr); @@ -641,27 +607,26 @@ namespace System { return result; } catch (NullReferenceException) { - throw new ArgumentOutOfRangeException("ptr", Environment.GetResourceString("ArgumentOutOfRange_PartialWCHAR")); + throw new ArgumentOutOfRangeException(nameof(ptr), Environment.GetResourceString("ArgumentOutOfRange_PartialWCHAR")); } } - [System.Security.SecurityCritical] // auto-generated private unsafe String CtorCharPtrStartLength(char *ptr, int startIndex, int length) { if (length < 0) { - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NegativeLength")); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_NegativeLength")); } if (startIndex < 0) { - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); } Contract.EndContractBlock(); - Contract.Assert(this == null, "this == null"); // this is the string constructor, we allocate it + Debug.Assert(this == null, "this == null"); // this is the string constructor, we allocate it char *pFrom = ptr + startIndex; if (pFrom < ptr) { // This means that the pointer operation has had an overflow - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_PartialWCHAR")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_PartialWCHAR")); } if (length == 0) @@ -675,11 +640,10 @@ namespace System { return result; } catch (NullReferenceException) { - throw new ArgumentOutOfRangeException("ptr", Environment.GetResourceString("ArgumentOutOfRange_PartialWCHAR")); + throw new ArgumentOutOfRangeException(nameof(ptr), Environment.GetResourceString("ArgumentOutOfRange_PartialWCHAR")); } } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern String(char c, int count); @@ -705,10 +669,9 @@ namespace System { return this; } - [System.Security.SecuritySafeCritical] // auto-generated unsafe public static String Copy (String str) { if (str==null) { - throw new ArgumentNullException("str"); + throw new ArgumentNullException(nameof(str)); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -724,10 +687,9 @@ namespace System { return result; } - [System.Security.SecuritySafeCritical] // auto-generated public static String Intern(String str) { if (str==null) { - throw new ArgumentNullException("str"); + throw new ArgumentNullException(nameof(str)); } Contract.Ensures(Contract.Result().Length == str.Length); Contract.Ensures(str.Equals(Contract.Result())); @@ -737,10 +699,9 @@ namespace System { } [Pure] - [System.Security.SecuritySafeCritical] // auto-generated public static String IsInterned(String str) { if (str==null) { - throw new ArgumentNullException("str"); + throw new ArgumentNullException(nameof(str)); } Contract.Ensures(Contract.Result() == null || Contract.Result().Length == str.Length); Contract.EndContractBlock(); @@ -834,31 +795,25 @@ namespace System { // Is this a string that can be compared quickly (that is it has only characters > 0x80 // and not a - or ' - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern bool IsFastSort(); // Is this a string that only contains characters < 0x80. - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern bool IsAscii(); // Set extra byte for odd-sized strings that came from interop as BSTR. - [System.Security.SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern void SetTrailByte(byte data); // Try to retrieve the extra byte - returns false if not present. - [System.Security.SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern bool TryGetTrailByte(out byte data); -#if !FEATURE_CORECLR public CharEnumerator GetEnumerator() { Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); BCLDebug.Perf(false, "Avoid using String's CharEnumerator until C# special cases foreach on String - use the indexed property on String instead."); return new CharEnumerator(this); } -#endif // !FEATURE_CORECLR IEnumerator IEnumerable.GetEnumerator() { Contract.Ensures(Contract.Result>() != null); @@ -876,7 +831,6 @@ namespace System { } // Copies the source String (byte buffer) to the destination IntPtr memory allocated with len bytes. - [System.Security.SecurityCritical] // auto-generated internal unsafe static void InternalCopy(String src, IntPtr dest,int len) { if (len == 0) @@ -886,6 +840,12 @@ namespace System { byte* dstPtr = (byte*) dest; Buffer.Memcpy(dstPtr, srcPtr, len); } - } + } + +#if FEATURE_SPAN_OF_T + internal ref char GetFirstCharRef() { + return ref m_firstChar; + } +#endif } } diff --git a/src/mscorlib/src/System/StringComparer.cs b/src/mscorlib/src/System/StringComparer.cs index 57bdf4c..02e8d71 100644 --- a/src/mscorlib/src/System/StringComparer.cs +++ b/src/mscorlib/src/System/StringComparer.cs @@ -62,9 +62,31 @@ namespace System { } } + // Convert a StringComparison to a StringComparer + public static StringComparer FromComparison(StringComparison comparisonType) + { + switch (comparisonType) + { + case StringComparison.CurrentCulture: + return CurrentCulture; + case StringComparison.CurrentCultureIgnoreCase: + return CurrentCultureIgnoreCase; + case StringComparison.InvariantCulture: + return InvariantCulture; + case StringComparison.InvariantCultureIgnoreCase: + return InvariantCultureIgnoreCase; + case StringComparison.Ordinal: + return Ordinal; + case StringComparison.OrdinalIgnoreCase: + return OrdinalIgnoreCase; + default: + throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType)); + } + } + public static StringComparer Create(CultureInfo culture, bool ignoreCase) { if( culture == null) { - throw new ArgumentNullException("culture"); + throw new ArgumentNullException(nameof(culture)); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -110,7 +132,7 @@ namespace System { public int GetHashCode(object obj) { if( obj == null) { - throw new ArgumentNullException("obj"); + throw new ArgumentNullException(nameof(obj)); } Contract.EndContractBlock(); @@ -161,7 +183,7 @@ namespace System { public override int GetHashCode(string obj) { if( obj == null) { - throw new ArgumentNullException("obj"); + throw new ArgumentNullException(nameof(obj)); } Contract.EndContractBlock(); @@ -229,7 +251,7 @@ namespace System { public override int GetHashCode(string obj) { if( obj == null) { - throw new ArgumentNullException("obj"); + throw new ArgumentNullException(nameof(obj)); } Contract.EndContractBlock(); @@ -311,7 +333,7 @@ namespace System { public override int GetHashCode(string obj) { if( obj == null) { - throw new ArgumentNullException("obj"); + throw new ArgumentNullException(nameof(obj)); } Contract.EndContractBlock(); @@ -385,10 +407,9 @@ namespace System { return x.Equals(y); } - [System.Security.SecuritySafeCritical] public override int GetHashCode(string obj) { if( obj == null) { - throw new ArgumentNullException("obj"); + throw new ArgumentNullException(nameof(obj)); } Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/StubHelpers.cs b/src/mscorlib/src/System/StubHelpers.cs index a9c584e..26a2276 100644 --- a/src/mscorlib/src/System/StubHelpers.cs +++ b/src/mscorlib/src/System/StubHelpers.cs @@ -16,6 +16,7 @@ namespace System.StubHelpers { #endif // FEATURE_COMINTEROP using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; + using System.Diagnostics; using System.Diagnostics.Contracts; [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] @@ -23,7 +24,6 @@ namespace System.StubHelpers { { // The length of the returned array is an approximation based on the length of the input string and the system // character set. It is only guaranteed to be larger or equal to cbLength, don't depend on the exact value. - [System.Security.SecurityCritical] unsafe static internal byte[] DoAnsiConversion(string str, bool fBestFit, bool fThrowOnUnmappableChar, out int cbLength) { byte[] buffer = new byte[(str.Length + 1) * Marshal.SystemMaxDBCSCharSize]; @@ -34,7 +34,6 @@ namespace System.StubHelpers { return buffer; } - [System.Security.SecurityCritical] unsafe static internal byte ConvertToNative(char managedChar, bool fBestFit, bool fThrowOnUnmappableChar) { int cbAllocLength = (1 + 1) * Marshal.SystemMaxDBCSCharSize; @@ -57,7 +56,6 @@ namespace System.StubHelpers { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal static class CSTRMarshaler { - [System.Security.SecurityCritical] // auto-generated static internal unsafe IntPtr ConvertToNative(int flags, string strManaged, IntPtr pNativeBuffer) { if (null == strManaged) @@ -109,7 +107,6 @@ namespace System.StubHelpers { return (IntPtr)pbNativeBuffer; } - [System.Security.SecurityCritical] // auto-generated static internal unsafe string ConvertToManaged(IntPtr cstr) { if (IntPtr.Zero == cstr) @@ -118,7 +115,6 @@ namespace System.StubHelpers { return new String((sbyte*)cstr); } - [System.Security.SecurityCritical] // auto-generated static internal void ClearNative(IntPtr pNative) { Win32Native.CoTaskMemFree(pNative); @@ -129,7 +125,6 @@ namespace System.StubHelpers { internal static class UTF8Marshaler { const int MAX_UTF8_CHAR_SIZE = 3; - [System.Security.SecurityCritical] static internal unsafe IntPtr ConvertToNative(int flags, string strManaged, IntPtr pNativeBuffer) { if (null == strManaged) @@ -166,7 +161,6 @@ namespace System.StubHelpers { return (IntPtr)pbNativeBuffer; } - [System.Security.SecurityCritical] static internal unsafe string ConvertToManaged(IntPtr cstr) { if (IntPtr.Zero == cstr) @@ -175,7 +169,6 @@ namespace System.StubHelpers { return String.CreateStringFromEncoding((byte*)cstr, nbBytes, Encoding.UTF8); } - [System.Security.SecurityCritical] static internal void ClearNative(IntPtr pNative) { if (pNative != IntPtr.Zero) @@ -188,7 +181,6 @@ namespace System.StubHelpers { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal static class UTF8BufferMarshaler { - [System.Security.SecurityCritical] static internal unsafe IntPtr ConvertToNative(StringBuilder sb, IntPtr pNativeBuffer, int flags) { if (null == sb) @@ -210,7 +202,6 @@ namespace System.StubHelpers { return (IntPtr)pbNativeBuffer; } - [System.Security.SecurityCritical] static internal unsafe void ConvertToManaged(StringBuilder sb, IntPtr pNative) { if (pNative == null) @@ -241,7 +232,6 @@ namespace System.StubHelpers { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal static class BSTRMarshaler { - [System.Security.SecurityCritical] // auto-generated static internal unsafe IntPtr ConvertToNative(string strManaged, IntPtr pNativeBuffer) { if (null == strManaged) @@ -311,7 +301,6 @@ namespace System.StubHelpers { } } - [System.Security.SecurityCritical] // auto-generated static internal unsafe string ConvertToManaged(IntPtr bstr) { if (IntPtr.Zero == bstr) @@ -356,7 +345,6 @@ namespace System.StubHelpers { } } - [System.Security.SecurityCritical] // auto-generated static internal void ClearNative(IntPtr pNative) { if (IntPtr.Zero != pNative) @@ -372,7 +360,6 @@ namespace System.StubHelpers { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal static class VBByValStrMarshaler { - [System.Security.SecurityCritical] // auto-generated static internal unsafe IntPtr ConvertToNative(string strManaged, bool fBestFit, bool fThrowOnUnmappableChar, ref int cch) { if (null == strManaged) @@ -414,7 +401,6 @@ namespace System.StubHelpers { return new IntPtr(pNative); } - [System.Security.SecurityCritical] // auto-generated static internal unsafe string ConvertToManaged(IntPtr pNative, int cch) { if (IntPtr.Zero == pNative) @@ -425,7 +411,6 @@ namespace System.StubHelpers { return new String((sbyte*)pNative, 0, cch); } - [System.Security.SecurityCritical] // auto-generated static internal unsafe void ClearNative(IntPtr pNative) { if (IntPtr.Zero != pNative) @@ -441,7 +426,6 @@ namespace System.StubHelpers { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal static class AnsiBSTRMarshaler { - [System.Security.SecurityCritical] // auto-generated static internal unsafe IntPtr ConvertToNative(int flags, string strManaged) { if (null == strManaged) @@ -464,7 +448,6 @@ namespace System.StubHelpers { return Win32Native.SysAllocStringByteLen(bytes, (uint)nb); } - [System.Security.SecurityCritical] // auto-generated static internal unsafe string ConvertToManaged(IntPtr bstr) { if (IntPtr.Zero == bstr) @@ -480,7 +463,6 @@ namespace System.StubHelpers { } } - [System.Security.SecurityCritical] // auto-generated static internal unsafe void ClearNative(IntPtr pNative) { if (IntPtr.Zero != pNative) @@ -498,19 +480,19 @@ namespace System.StubHelpers { { static internal IntPtr ConvertToNative(string strManaged) { - Contract.Assert(false, "NYI"); + Debug.Assert(false, "NYI"); return IntPtr.Zero; } static internal unsafe string ConvertToManaged(IntPtr bstr) { - Contract.Assert(false, "NYI"); + Debug.Assert(false, "NYI"); return null; } static internal void ClearNative(IntPtr pNative) { - Contract.Assert(false, "NYI"); + Debug.Assert(false, "NYI"); } } // class WSTRBufferMarshaler @@ -531,14 +513,12 @@ namespace System.StubHelpers { // You can get this through: (new DateTimeOffset(1601, 1, 1, 0, 0, 1, TimeSpan.Zero)).Ticks; private const Int64 ManagedUtcTicksAtNativeZero = 504911232000000000; - [SecurityCritical] internal static void ConvertToNative(ref DateTimeOffset managedDTO, out DateTimeNative dateTime) { Int64 managedUtcTicks = managedDTO.UtcTicks; dateTime.UniversalTime = managedUtcTicks - ManagedUtcTicksAtNativeZero; } - [SecurityCritical] internal static void ConvertToManaged(out DateTimeOffset managedLocalDTO, ref DateTimeNative nativeTicks) { Int64 managedUtcTicks = ManagedUtcTicksAtNativeZero + nativeTicks.UniversalTime; @@ -558,7 +538,6 @@ namespace System.StubHelpers { internal static class HStringMarshaler { // Slow-path, which requires making a copy of the managed string into the resulting HSTRING - [SecurityCritical] internal static unsafe IntPtr ConvertToNative(string managed) { if (!Environment.IsWinRTSupported) @@ -578,7 +557,6 @@ namespace System.StubHelpers { // Note that the managed string input to this method MUST be pinned, and stay pinned for the lifetime of // the returned HSTRING object. If the string is not pinned, or becomes unpinned before the HSTRING's // lifetime ends, the HSTRING instance will be corrupted. - [SecurityCritical] internal static unsafe IntPtr ConvertToNativeReference(string managed, [Out] HSTRING_HEADER *hstringHeader) { @@ -598,7 +576,6 @@ namespace System.StubHelpers { } } - [SecurityCritical] internal static string ConvertToManaged(IntPtr hstring) { if (!Environment.IsWinRTSupported) @@ -609,10 +586,9 @@ namespace System.StubHelpers { return WindowsRuntimeMarshal.HStringToString(hstring); } - [SecurityCritical] internal static void ClearNative(IntPtr hstring) { - Contract.Assert(Environment.IsWinRTSupported); + Debug.Assert(Environment.IsWinRTSupported); if (hstring != IntPtr.Zero) { @@ -639,7 +615,6 @@ namespace System.StubHelpers { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal static class ValueClassMarshaler { - [SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] static internal extern void ConvertToNative(IntPtr dst, IntPtr src, IntPtr pMT, ref CleanupWorkList pCleanupWorkList); @@ -672,7 +647,6 @@ namespace System.StubHelpers { [MethodImplAttribute(MethodImplOptions.InternalCall)] static internal extern object ConvertToManaged(IntPtr pUnk, IntPtr itfMT, IntPtr classMT, int flags); - [SecurityCritical] [DllImport(JitHelpers.QCall), SuppressUnmanagedCodeSecurity] static internal extern void ClearNative(IntPtr pUnk); @@ -690,10 +664,8 @@ namespace System.StubHelpers { static internal extern string GetRawUriFromNative(IntPtr pUri); [MethodImplAttribute(MethodImplOptions.InternalCall)] - [System.Security.SecurityCritical] static unsafe internal extern IntPtr CreateNativeUriInstanceHelper(char* rawUri, int strLen); - [System.Security.SecurityCritical] static unsafe internal IntPtr CreateNativeUriInstance(string rawUri) { fixed(char* pManaged = rawUri) @@ -707,7 +679,6 @@ namespace System.StubHelpers { [FriendAccessAllowed] internal static class EventArgsMarshaler { - [SecurityCritical] [FriendAccessAllowed] static internal IntPtr CreateNativeNCCEventArgsInstance(int action, object newItems, object oldItems, int newIndex, int oldIndex) { @@ -733,12 +704,10 @@ namespace System.StubHelpers { } } - [SecurityCritical] [FriendAccessAllowed] [DllImport(JitHelpers.QCall), SuppressUnmanagedCodeSecurity] static extern internal IntPtr CreateNativePCEventArgsInstance([MarshalAs(UnmanagedType.HString)]string name); - [SecurityCritical] [DllImport(JitHelpers.QCall), SuppressUnmanagedCodeSecurity] static extern internal IntPtr CreateNativeNCCEventArgsInstanceHelper(int action, IntPtr newItem, IntPtr oldItem, int newIndex, int oldIndex); } @@ -796,19 +765,15 @@ namespace System.StubHelpers { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal static class MngdHiddenLengthArrayMarshaler { - [SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] static internal extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, IntPtr cbElementSize, ushort vt); - [SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void ConvertSpaceToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome); - [SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void ConvertContentsToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome); - [SecurityCritical] internal static unsafe void ConvertContentsToNative_DateTime(ref DateTimeOffset[] managedArray, IntPtr pNativeHome) { if (managedArray != null) @@ -821,7 +786,6 @@ namespace System.StubHelpers { } } - [SecurityCritical] internal static unsafe void ConvertContentsToNative_Type(ref System.Type[] managedArray, IntPtr pNativeHome) { if (managedArray != null) @@ -834,7 +798,6 @@ namespace System.StubHelpers { } } - [SecurityCritical] internal static unsafe void ConvertContentsToNative_Exception(ref Exception[] managedArray, IntPtr pNativeHome) { if (managedArray != null) @@ -847,7 +810,6 @@ namespace System.StubHelpers { } } - [SecurityCritical] internal static unsafe void ConvertContentsToNative_Nullable(ref Nullable[] managedArray, IntPtr pNativeHome) where T : struct { @@ -861,7 +823,6 @@ namespace System.StubHelpers { } } - [SecurityCritical] internal static unsafe void ConvertContentsToNative_KeyValuePair(ref KeyValuePair[] managedArray, IntPtr pNativeHome) { if (managedArray != null) @@ -874,15 +835,12 @@ namespace System.StubHelpers { } } - [SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void ConvertSpaceToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome, int elementCount); - [SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void ConvertContentsToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome); - [SecurityCritical] internal static unsafe void ConvertContentsToManaged_DateTime(ref DateTimeOffset[] managedArray, IntPtr pNativeHome) { if (managedArray != null) @@ -895,7 +853,6 @@ namespace System.StubHelpers { } } - [SecurityCritical] internal static unsafe void ConvertContentsToManaged_Type(ref System.Type[] managedArray, IntPtr pNativeHome) { if (managedArray != null) @@ -908,7 +865,6 @@ namespace System.StubHelpers { } } - [SecurityCritical] internal static unsafe void ConvertContentsToManaged_Exception(ref Exception[] managedArray, IntPtr pNativeHome) { if (managedArray != null) @@ -921,7 +877,6 @@ namespace System.StubHelpers { } } - [SecurityCritical] internal static unsafe void ConvertContentsToManaged_Nullable(ref Nullable[] managedArray, IntPtr pNativeHome) where T : struct { @@ -935,7 +890,6 @@ namespace System.StubHelpers { } } - [SecurityCritical] internal static unsafe void ConvertContentsToManaged_KeyValuePair(ref KeyValuePair[] managedArray, IntPtr pNativeHome) { if (managedArray != null) @@ -948,14 +902,12 @@ namespace System.StubHelpers { } } - [SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void ClearNativeContents(IntPtr pMarshalState, IntPtr pNativeHome, int cElements); - [SecurityCritical] internal static unsafe void ClearNativeContents_Type(IntPtr pNativeHome, int cElements) { - Contract.Assert(Environment.IsWinRTSupported); + Debug.Assert(Environment.IsWinRTSupported); TypeNameNative *pNativeTypeArray = *(TypeNameNative **)pNativeHome; if (pNativeTypeArray != null) @@ -991,7 +943,6 @@ namespace System.StubHelpers { } // class MngdRefCustomMarshaler [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - [System.Security.SecurityCritical] internal struct AsAnyMarshaler { private const ushort VTHACK_ANSICHAR = 253; @@ -1037,7 +988,6 @@ namespace System.StubHelpers { #region ConvertToNative helpers - [System.Security.SecurityCritical] private unsafe IntPtr ConvertArrayToNative(object pManagedHome, int dwFlags) { Type elementType = pManagedHome.GetType().GetElementType(); @@ -1109,7 +1059,6 @@ namespace System.StubHelpers { return pNativeHome; } - [System.Security.SecurityCritical] private static IntPtr ConvertStringToNative(string pManagedHome, int dwFlags) { IntPtr pNativeHome; @@ -1137,7 +1086,6 @@ namespace System.StubHelpers { return pNativeHome; } - [System.Security.SecurityCritical] private unsafe IntPtr ConvertStringBuilderToNative(StringBuilder pManagedHome, int dwFlags) { IntPtr pNativeHome; @@ -1176,7 +1124,7 @@ namespace System.StubHelpers { ptr, allocSize, IsBestFit(dwFlags), IsThrowOn(dwFlags)); - Contract.Assert(length < allocSize, "Expected a length less than the allocated size"); + Debug.Assert(length < allocSize, "Expected a length less than the allocated size"); } if (IsOut(dwFlags)) { @@ -1211,7 +1159,6 @@ namespace System.StubHelpers { return pNativeHome; } - [System.Security.SecurityCritical] private unsafe IntPtr ConvertLayoutToNative(object pManagedHome, int dwFlags) { // Note that the following call will not throw exception if the type @@ -1237,7 +1184,6 @@ namespace System.StubHelpers { #endregion - [System.Security.SecurityCritical] internal IntPtr ConvertToNative(object pManagedHome, int dwFlags) { if (pManagedHome == null) @@ -1283,7 +1229,6 @@ namespace System.StubHelpers { return pNativeHome; } - [System.Security.SecurityCritical] internal unsafe void ConvertToManaged(object pManagedHome, IntPtr pNativeHome) { switch (backPropAction) @@ -1321,7 +1266,6 @@ namespace System.StubHelpers { } } - [System.Security.SecurityCritical] internal void ClearNative(IntPtr pNativeHome) { if (pNativeHome != IntPtr.Zero) @@ -1341,7 +1285,6 @@ namespace System.StubHelpers { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal static class NullableMarshaler { - [SecurityCritical] static internal IntPtr ConvertToNative(ref Nullable pManaged) where T : struct { if (pManaged.HasValue) @@ -1355,14 +1298,12 @@ namespace System.StubHelpers { } } - [SecurityCritical] static internal void ConvertToManagedRetVoid(IntPtr pNative, ref Nullable retObj) where T : struct { retObj = ConvertToManaged(pNative); } - [SecurityCritical] static internal Nullable ConvertToManaged(IntPtr pNative) where T : struct { if (pNative != IntPtr.Zero) @@ -1406,7 +1347,6 @@ namespace System.StubHelpers { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal static class SystemTypeMarshaler { - [SecurityCritical] internal static unsafe void ConvertToNative(System.Type managedType, TypeNameNative *pNativeType) { if (!Environment.IsWinRTSupported) @@ -1450,7 +1390,6 @@ namespace System.StubHelpers { Marshal.ThrowExceptionForHR(hrCreate, new IntPtr(-1)); } - [SecurityCritical] internal static unsafe void ConvertToManaged(TypeNameNative *pNativeType, ref System.Type managedType) { if (!Environment.IsWinRTSupported) @@ -1480,10 +1419,9 @@ namespace System.StubHelpers { } } - [SecurityCritical] internal static unsafe void ClearNative(TypeNameNative *pNativeType) { - Contract.Assert(Environment.IsWinRTSupported); + Debug.Assert(Environment.IsWinRTSupported); if (pNativeType->typeName != IntPtr.Zero) { @@ -1509,7 +1447,6 @@ namespace System.StubHelpers { return ex._HResult; } - [SecuritySafeCritical] static internal unsafe Exception ConvertToManaged(int hr) { Contract.Ensures(Contract.Result() != null || hr >= 0); @@ -1527,7 +1464,7 @@ namespace System.StubHelpers { // S_OK should be marshaled as null. WinRT API's should not return S_FALSE by convention. // We've chosen to treat S_FALSE as success and return null. - Contract.Assert(e != null || hr == 0 || hr == 1, "Unexpected HRESULT - it is a success HRESULT (without the high bit set) other than S_OK & S_FALSE."); + Debug.Assert(e != null || hr == 0 || hr == 1, "Unexpected HRESULT - it is a success HRESULT (without the high bit set) other than S_OK & S_FALSE."); return e; } } // class HResultExceptionMarshaler @@ -1535,14 +1472,12 @@ namespace System.StubHelpers { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal static class KeyValuePairMarshaler { - [SecurityCritical] internal static IntPtr ConvertToNative([In] ref KeyValuePair pair) { IKeyValuePair impl = new CLRIKeyValuePairImpl(ref pair); return Marshal.GetComInterfaceForObject(impl, typeof(IKeyValuePair)); } - [SecurityCritical] internal static KeyValuePair ConvertToManaged(IntPtr pInsp) { object obj = InterfaceMarshaler.ConvertToManagedWithoutUnboxing(pInsp); @@ -1552,7 +1487,6 @@ namespace System.StubHelpers { } // Called from COMInterfaceMarshaler - [SecurityCritical] internal static object ConvertToManagedBox(IntPtr pInsp) { return (object)ConvertToManaged(pInsp); @@ -1583,48 +1517,9 @@ namespace System.StubHelpers { #endif } // struct NativeVariant -#if !BIT64 && !FEATURE_CORECLR - // Structure filled by IL stubs if copy constructor(s) and destructor(s) need to be called - // on value types pushed on the stack. The structure is stored in s_copyCtorStubDesc by - // SetCopyCtorCookieChain and fetched by CopyCtorCallStubWorker. Must be stack-allocated. - [StructLayout(LayoutKind.Sequential)] - unsafe internal struct CopyCtorStubCookie - { - public void SetData(IntPtr srcInstancePtr, uint dstStackOffset, IntPtr ctorPtr, IntPtr dtorPtr) - { - m_srcInstancePtr = srcInstancePtr; - m_dstStackOffset = dstStackOffset; - m_ctorPtr = ctorPtr; - m_dtorPtr = dtorPtr; - } - - public void SetNext(IntPtr pNext) - { - m_pNext = pNext; - } - - public IntPtr m_srcInstancePtr; // pointer to the source instance - public uint m_dstStackOffset; // offset from the start of stack arguments of the pushed 'this' instance - - public IntPtr m_ctorPtr; // fnptr to the managed copy constructor, result of ldftn - public IntPtr m_dtorPtr; // fnptr to the managed destructor, result of ldftn - - public IntPtr m_pNext; // pointer to next cookie in the chain or IntPtr.Zero - } // struct CopyCtorStubCookie - - // Aggregates pointer to CopyCtorStubCookie and the target of the interop call. - [StructLayout(LayoutKind.Sequential)] - unsafe internal struct CopyCtorStubDesc - { - public IntPtr m_pCookie; - public IntPtr m_pTarget; - } // struct CopyCtorStubDes -#endif // !BIT64 && !FEATURE_CORECLR - // Aggregates SafeHandle and the "owned" bit which indicates whether the SafeHandle // has been successfully AddRef'ed. This allows us to do realiable cleanup (Release) // if and only if it is needed. - [System.Security.SecurityCritical] internal sealed class CleanupWorkListElement { public CleanupWorkListElement(SafeHandle handle) @@ -1640,7 +1535,6 @@ namespace System.StubHelpers { } // class CleanupWorkListElement [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - [System.Security.SecurityCritical] internal sealed class CleanupWorkList { private List m_list = new List(); @@ -1662,7 +1556,6 @@ namespace System.StubHelpers { } } // class CleanupWorkList - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [SuppressUnmanagedCodeSecurityAttribute()] internal static class StubHelpers @@ -1679,33 +1572,8 @@ namespace System.StubHelpers { [MethodImplAttribute(MethodImplOptions.InternalCall)] static internal extern IntPtr GetDelegateTarget(Delegate pThis, ref IntPtr pStubArg); -#if !BIT64 && !FEATURE_CORECLR - // Written to by a managed stub helper, read by CopyCtorCallStubWorker in VM. - [ThreadStatic] - static CopyCtorStubDesc s_copyCtorStubDesc; - - static internal void SetCopyCtorCookieChain(IntPtr pStubArg, IntPtr pUnmngThis, int dwStubFlags, IntPtr pCookie) - { - // we store both the cookie chain head and the target of the copy ctor stub to a thread - // static field to be accessed by the copy ctor (see code:CopyCtorCallStubWorker) - s_copyCtorStubDesc.m_pCookie = pCookie; - s_copyCtorStubDesc.m_pTarget = GetFinalStubTarget(pStubArg, pUnmngThis, dwStubFlags); - } - - // Returns the final unmanaged stub target, ignores interceptors. - [MethodImplAttribute(MethodImplOptions.InternalCall)] - static internal extern IntPtr GetFinalStubTarget(IntPtr pStubArg, IntPtr pUnmngThis, int dwStubFlags); -#endif // !FEATURE_CORECLR && !BIT64 - -#if !FEATURE_CORECLR - [MethodImplAttribute(MethodImplOptions.InternalCall)] - static internal extern void DemandPermission(IntPtr pNMD); -#endif // !FEATURE_CORECLR - -#if FEATURE_CORECLR [MethodImplAttribute(MethodImplOptions.InternalCall)] static internal extern void ClearLastError(); -#endif [MethodImplAttribute(MethodImplOptions.InternalCall)] static internal extern void SetLastError(); @@ -1713,7 +1581,6 @@ namespace System.StubHelpers { [MethodImplAttribute(MethodImplOptions.InternalCall)] static internal extern void ThrowInteropParamException(int resID, int paramIdx); - [System.Security.SecurityCritical] static internal IntPtr AddToCleanupList(ref CleanupWorkList pCleanupWorkList, SafeHandle handle) { if (pCleanupWorkList == null) @@ -1726,7 +1593,6 @@ namespace System.StubHelpers { return SafeHandleAddRef(handle, ref element.m_owned); } - [System.Security.SecurityCritical] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] static internal void DestroyCleanupList(ref CleanupWorkList pCleanupWorkList) { @@ -1775,12 +1641,11 @@ namespace System.StubHelpers { //------------------------------------------------------- // AddRefs the SH and returns the underlying unmanaged handle. - [System.Security.SecurityCritical] // auto-generated static internal IntPtr SafeHandleAddRef(SafeHandle pHandle, ref bool success) { if (pHandle == null) { - throw new ArgumentNullException("pHandle", Environment.GetResourceString("ArgumentNull_SafeHandle")); + throw new ArgumentNullException(nameof(pHandle), Environment.GetResourceString("ArgumentNull_SafeHandle")); } Contract.EndContractBlock(); @@ -1790,13 +1655,12 @@ namespace System.StubHelpers { } // Releases the SH (to be called from finally block). - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] static internal void SafeHandleRelease(SafeHandle pHandle) { if (pHandle == null) { - throw new ArgumentNullException("pHandle", Environment.GetResourceString("ArgumentNull_SafeHandle")); + throw new ArgumentNullException(nameof(pHandle), Environment.GetResourceString("ArgumentNull_SafeHandle")); } Contract.EndContractBlock(); @@ -1848,15 +1712,12 @@ namespace System.StubHelpers { static internal extern IntPtr GetDelegateInvokeMethod(Delegate pThis); [MethodImplAttribute(MethodImplOptions.InternalCall)] - [System.Security.SecurityCritical] static internal extern object GetWinRTFactoryObject(IntPtr pCPCMD); [MethodImplAttribute(MethodImplOptions.InternalCall)] - [System.Security.SecurityCritical] static internal extern IntPtr GetWinRTFactoryReturnValue(object pThis, IntPtr pCtorEntry); [MethodImplAttribute(MethodImplOptions.InternalCall)] - [System.Security.SecurityCritical] static internal extern IntPtr GetOuterInspectable(object pThis, IntPtr pCtorMD); #if MDA_SUPPORTED diff --git a/src/mscorlib/src/System/Text/ASCIIEncoding.cs b/src/mscorlib/src/System/Text/ASCIIEncoding.cs index bf1a62d..fc7589f 100644 --- a/src/mscorlib/src/System/Text/ASCIIEncoding.cs +++ b/src/mscorlib/src/System/Text/ASCIIEncoding.cs @@ -7,6 +7,7 @@ namespace System.Text using System; using System.Runtime.Serialization; using System.Security.Permissions; + using System.Diagnostics; using System.Diagnostics.Contracts; // ASCIIEncoding @@ -70,7 +71,6 @@ namespace System.Text return EncodingForwarder.GetByteCount(this, chars); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public override unsafe int GetByteCount(char* chars, int count) @@ -99,7 +99,6 @@ namespace System.Text return EncodingForwarder.GetBytes(this, chars, charIndex, charCount, bytes, byteIndex); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount) @@ -115,7 +114,6 @@ namespace System.Text return EncodingForwarder.GetCharCount(this, bytes, index, count); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public override unsafe int GetCharCount(byte* bytes, int count) @@ -129,7 +127,6 @@ namespace System.Text return EncodingForwarder.GetChars(this, bytes, byteIndex, byteCount, chars, charIndex); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount) @@ -150,15 +147,14 @@ namespace System.Text // GetByteCount // Note: We start by assuming that the output will be the same as count. Having // an encoder or fallback may change that assumption - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetByteCount(char* chars, int charCount, EncoderNLS encoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already - Contract.Assert(charCount >= 0, "[ASCIIEncoding.GetByteCount]count is negative"); - Contract.Assert(chars != null, "[ASCIIEncoding.GetByteCount]chars is null"); + Debug.Assert(charCount >= 0, "[ASCIIEncoding.GetByteCount]count is negative"); + Debug.Assert(chars != null, "[ASCIIEncoding.GetByteCount]chars is null"); // Assert because we shouldn't be able to have a null encoder. - Contract.Assert(encoderFallback != null, "[ASCIIEncoding.GetByteCount]Attempting to use null fallback encoder"); + Debug.Assert(encoderFallback != null, "[ASCIIEncoding.GetByteCount]Attempting to use null fallback encoder"); char charLeftOver = (char)0; EncoderReplacementFallback fallback = null; @@ -172,7 +168,7 @@ namespace System.Text if (encoder != null) { charLeftOver = encoder.charLeftOver; - Contract.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver), + Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver), "[ASCIIEncoding.GetByteCount]leftover character should be high surrogate"); fallback = encoder.Fallback as EncoderReplacementFallback; @@ -191,7 +187,7 @@ namespace System.Text } // Verify that we have no fallbackbuffer, for ASCII its always empty, so just assert - Contract.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer || + Debug.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer || encoder.FallbackBuffer.Remaining == 0, "[ASCIICodePageEncoding.GetByteCount]Expected empty fallback buffer"); // if (encoder.InternalHasFallbackBuffer && encoder.FallbackBuffer.Remaining > 0) @@ -228,8 +224,8 @@ namespace System.Text // We may have a left over character from last time, try and process it. if (charLeftOver > 0) { - Contract.Assert(Char.IsHighSurrogate(charLeftOver), "[ASCIIEncoding.GetByteCount]leftover character should be high surrogate"); - Contract.Assert(encoder != null, "[ASCIIEncoding.GetByteCount]Expected encoder"); + Debug.Assert(Char.IsHighSurrogate(charLeftOver), "[ASCIIEncoding.GetByteCount]leftover character should be high surrogate"); + Debug.Assert(encoder != null, "[ASCIIEncoding.GetByteCount]Expected encoder"); // Since left over char was a surrogate, it'll have to be fallen back. // Get Fallback @@ -279,24 +275,23 @@ namespace System.Text byteCount++; } - Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, + Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[ASCIIEncoding.GetByteCount]Expected Empty fallback buffer"); return byteCount; } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS encoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already - Contract.Assert(bytes != null, "[ASCIIEncoding.GetBytes]bytes is null"); - Contract.Assert(byteCount >= 0, "[ASCIIEncoding.GetBytes]byteCount is negative"); - Contract.Assert(chars != null, "[ASCIIEncoding.GetBytes]chars is null"); - Contract.Assert(charCount >= 0, "[ASCIIEncoding.GetBytes]charCount is negative"); + Debug.Assert(bytes != null, "[ASCIIEncoding.GetBytes]bytes is null"); + Debug.Assert(byteCount >= 0, "[ASCIIEncoding.GetBytes]byteCount is negative"); + Debug.Assert(chars != null, "[ASCIIEncoding.GetBytes]chars is null"); + Debug.Assert(charCount >= 0, "[ASCIIEncoding.GetBytes]charCount is negative"); // Assert because we shouldn't be able to have a null encoder. - Contract.Assert(encoderFallback != null, "[ASCIIEncoding.GetBytes]Attempting to use null encoder fallback"); + Debug.Assert(encoderFallback != null, "[ASCIIEncoding.GetBytes]Attempting to use null encoder fallback"); // Get any left over characters char charLeftOver = (char)0; @@ -328,11 +323,11 @@ namespace System.Text fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, true); } - Contract.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver), + Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver), "[ASCIIEncoding.GetBytes]leftover character should be high surrogate"); // Verify that we have no fallbackbuffer, for ASCII its always empty, so just assert - Contract.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer || + Debug.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer || encoder.FallbackBuffer.Remaining == 0, "[ASCIICodePageEncoding.GetBytes]Expected empty fallback buffer"); // if (encoder.m_throwOnOverflow && encoder.InternalHasFallbackBuffer && @@ -411,7 +406,7 @@ namespace System.Text if (charLeftOver > 0) { // Initialize the buffer - Contract.Assert(encoder != null, + Debug.Assert(encoder != null, "[ASCIIEncoding.GetBytes]Expected non null encoder if we have surrogate left over"); fallbackBuffer = encoder.FallbackBuffer; fallbackBuffer.InternalInitialize(chars, charEnd, encoder, true); @@ -465,7 +460,7 @@ namespace System.Text // didn't use this char, we'll throw or use buffer if (fallbackBuffer == null || fallbackBuffer.bFallingBack == false) { - Contract.Assert(chars > charStart || bytes == byteStart, + Debug.Assert(chars > charStart || bytes == byteStart, "[ASCIIEncoding.GetBytes]Expected chars to have advanced already."); chars--; // don't use last char } @@ -494,7 +489,7 @@ namespace System.Text encoder.m_charsUsed = (int)(chars - charStart); } - Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0 || + Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0 || (encoder != null && !encoder.m_throwOnOverflow ), "[ASCIIEncoding.GetBytes]Expected Empty fallback buffer at end"); @@ -502,12 +497,11 @@ namespace System.Text } // This is internal and called by something else, - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS decoder) { // Just assert, we're called internally so these should be safe, checked already - Contract.Assert(bytes != null, "[ASCIIEncoding.GetCharCount]bytes is null"); - Contract.Assert(count >= 0, "[ASCIIEncoding.GetCharCount]byteCount is negative"); + Debug.Assert(bytes != null, "[ASCIIEncoding.GetCharCount]bytes is null"); + Debug.Assert(count >= 0, "[ASCIIEncoding.GetCharCount]byteCount is negative"); // ASCII doesn't do best fit, so don't have to check for it, find out which decoder fallback we're using DecoderReplacementFallback fallback = null; @@ -517,7 +511,7 @@ namespace System.Text else { fallback = decoder.Fallback as DecoderReplacementFallback; - Contract.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer || + Debug.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[ASCIICodePageEncoding.GetCharCount]Expected empty fallback buffer"); } @@ -568,22 +562,21 @@ namespace System.Text } // Fallback buffer must be empty - Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, + Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[ASCIIEncoding.GetCharCount]Expected Empty fallback buffer"); // Converted sequence is same length as input return charCount; } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetChars(byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS decoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already - Contract.Assert(bytes != null, "[ASCIIEncoding.GetChars]bytes is null"); - Contract.Assert(byteCount >= 0, "[ASCIIEncoding.GetChars]byteCount is negative"); - Contract.Assert(chars != null, "[ASCIIEncoding.GetChars]chars is null"); - Contract.Assert(charCount >= 0, "[ASCIIEncoding.GetChars]charCount is negative"); + Debug.Assert(bytes != null, "[ASCIIEncoding.GetChars]bytes is null"); + Debug.Assert(byteCount >= 0, "[ASCIIEncoding.GetChars]byteCount is negative"); + Debug.Assert(chars != null, "[ASCIIEncoding.GetChars]chars is null"); + Debug.Assert(charCount >= 0, "[ASCIIEncoding.GetChars]charCount is negative"); // Do it fast way if using ? replacement fallback byte* byteEnd = bytes + byteCount; @@ -600,7 +593,7 @@ namespace System.Text else { fallback = decoder.Fallback as DecoderReplacementFallback; - Contract.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer || + Debug.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[ASCIICodePageEncoding.GetChars]Expected empty fallback buffer"); } @@ -668,7 +661,7 @@ namespace System.Text if (!fallbackBuffer.InternalFallback(byteBuffer, bytes, ref chars)) { // May or may not throw, but we didn't get this byte - Contract.Assert(bytes > byteStart || chars == charStart, + Debug.Assert(bytes > byteStart || chars == charStart, "[ASCIIEncoding.GetChars]Expected bytes to have advanced already (fallback case)"); bytes--; // unused byte fallbackBuffer.InternalReset(); // Didn't fall this back @@ -681,7 +674,7 @@ namespace System.Text // Make sure we have buffer space if (chars >= charEnd) { - Contract.Assert(bytes > byteStart || chars == charStart, + Debug.Assert(bytes > byteStart || chars == charStart, "[ASCIIEncoding.GetChars]Expected bytes to have advanced already (normal case)"); bytes--; // unused byte ThrowCharsOverflow(decoder, chars == charStart); // throw? @@ -698,7 +691,7 @@ namespace System.Text decoder.m_bytesUsed = (int)(bytes - byteStart); // Expect Empty fallback buffer for GetChars - Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, + Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[ASCIIEncoding.GetChars]Expected Empty fallback buffer"); return (int)(chars - charStart); @@ -708,7 +701,7 @@ namespace System.Text public override int GetMaxByteCount(int charCount) { if (charCount < 0) - throw new ArgumentOutOfRangeException("charCount", + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -721,7 +714,7 @@ namespace System.Text // 1 to 1 for most characters. Only surrogates with fallbacks have less. if (byteCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); return (int)byteCount; } @@ -729,7 +722,7 @@ namespace System.Text public override int GetMaxCharCount(int byteCount) { if (byteCount < 0) - throw new ArgumentOutOfRangeException("byteCount", + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -741,7 +734,7 @@ namespace System.Text charCount *= DecoderFallback.MaxCharCount; if (charCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow")); return (int)charCount; } diff --git a/src/mscorlib/src/System/Text/BaseCodePageEncoding.cs b/src/mscorlib/src/System/Text/BaseCodePageEncoding.cs index 4c9ca6e..0a42237 100644 --- a/src/mscorlib/src/System/Text/BaseCodePageEncoding.cs +++ b/src/mscorlib/src/System/Text/BaseCodePageEncoding.cs @@ -6,6 +6,7 @@ namespace System.Text { using System; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Globalization; using System.Runtime.InteropServices; @@ -72,7 +73,6 @@ namespace System.Text [NonSerialized] protected bool m_bUseMlangTypeForSerialization = false; - [System.Security.SecuritySafeCritical] // static constructors should be safe to call static BaseCodePageEncoding() { } @@ -136,32 +136,26 @@ namespace System.Text } // Initialize our global stuff - [SecurityCritical] unsafe static CodePageDataFileHeader* m_pCodePageFileHeader = (CodePageDataFileHeader*)GlobalizationAssembly.GetGlobalizationResourceBytePtr( typeof(CharUnicodeInfo).Assembly, CODE_PAGE_DATA_FILE_NAME); // Real variables [NonSerialized] - [SecurityCritical] unsafe protected CodePageHeader* pCodePage = null; // Safe handle wrapper around section map view - [System.Security.SecurityCritical] // auto-generated [NonSerialized] protected SafeViewOfFileHandle safeMemorySectionHandle = null; // Safe handle wrapper around mapped file handle - [System.Security.SecurityCritical] // auto-generated [NonSerialized] protected SafeFileMappingHandle safeFileMappingHandle = null; - [System.Security.SecurityCritical] // auto-generated internal BaseCodePageEncoding(int codepage) : this(codepage, codepage) { } - [System.Security.SecurityCritical] // auto-generated internal BaseCodePageEncoding(int codepage, int dataCodePage) : base(codepage == 0? Microsoft.Win32.Win32Native.GetACP(): codepage) { @@ -171,7 +165,6 @@ namespace System.Text } // Constructor called by serialization. - [System.Security.SecurityCritical] // auto-generated internal BaseCodePageEncoding(SerializationInfo info, StreamingContext context) : base(0) { // We cannot ever call this, we've proxied ourselved to CodePageEncoding @@ -179,12 +172,11 @@ namespace System.Text } // ISerializable implementation - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { // Make sure to get the base stuff too This throws if info is null SerializeEncoding(info, context); - Contract.Assert(info!=null, "[BaseCodePageEncoding.GetObjectData] Expected null info to throw"); + Debug.Assert(info!=null, "[BaseCodePageEncoding.GetObjectData] Expected null info to throw"); // Just need Everett maxCharSize (BaseCodePageEncoding) or m_maxByteSize (MLangBaseCodePageEncoding) info.AddValue(m_bUseMlangTypeForSerialization ? "m_maxByteSize" : "maxCharSize", @@ -196,7 +188,6 @@ namespace System.Text } // We need to load tables for our code page - [System.Security.SecurityCritical] // auto-generated private unsafe void LoadCodePageTables() { CodePageHeader* pCodePage = FindCodePage(dataTableCodePage); @@ -217,7 +208,6 @@ namespace System.Text } // Look up the code page pointer - [System.Security.SecurityCritical] // auto-generated private static unsafe CodePageHeader* FindCodePage(int codePage) { // We'll have to loop through all of the m_pCodePageIndex[] items to find our code page, this isn't @@ -240,7 +230,6 @@ namespace System.Text } // Get our code page byte count - [System.Security.SecurityCritical] // auto-generated internal static unsafe int GetCodePageByteSize(int codePage) { // Get our code page info @@ -250,18 +239,16 @@ namespace System.Text if (pCodePage == null) return 0; - Contract.Assert(pCodePage->ByteCount == 1 || pCodePage->ByteCount == 2, + Debug.Assert(pCodePage->ByteCount == 1 || pCodePage->ByteCount == 2, "[BaseCodePageEncoding] Code page (" + codePage + ") has invalid byte size (" + pCodePage->ByteCount + ") in table"); // Return what it says for byte count return pCodePage->ByteCount; } // We have a managed code page entry, so load our tables - [System.Security.SecurityCritical] protected abstract unsafe void LoadManagedCodePage(); // Allocate memory to load our code page - [System.Security.SecurityCritical] // auto-generated protected unsafe byte* GetSharedMemory(int iSize) { // Build our name @@ -271,7 +258,7 @@ namespace System.Text // This gets shared memory for our map. If its can't, it gives us clean memory. Byte *pMemorySection = EncodingTable.nativeCreateOpenFileMapping(strName, iSize, out mappedFileHandle); - Contract.Assert(pMemorySection != null, + Debug.Assert(pMemorySection != null, "[BaseCodePageEncoding.GetSharedMemory] Expected non-null memory section to be opened"); // If that failed, we have to die. @@ -291,7 +278,6 @@ namespace System.Text return pMemorySection; } - [System.Security.SecurityCritical] // auto-generated protected unsafe virtual String GetMemorySectionName() { int iUseCodePage = this.bFlagDataTable ? dataTableCodePage : CodePage; @@ -303,29 +289,26 @@ namespace System.Text return strName; } - [System.Security.SecurityCritical] protected abstract unsafe void ReadBestFitTable(); - [System.Security.SecuritySafeCritical] internal override char[] GetBestFitUnicodeToBytesData() { // Read in our best fit table if necessary if (arrayUnicodeBestFit == null) ReadBestFitTable(); - Contract.Assert(arrayUnicodeBestFit != null, + Debug.Assert(arrayUnicodeBestFit != null, "[BaseCodePageEncoding.GetBestFitUnicodeToBytesData]Expected non-null arrayUnicodeBestFit"); // Normally we don't have any best fit data. return arrayUnicodeBestFit; } - [System.Security.SecuritySafeCritical] internal override char[] GetBestFitBytesToUnicodeData() { // Read in our best fit table if necessary if (arrayBytesBestFit == null) ReadBestFitTable(); - Contract.Assert(arrayBytesBestFit != null, + Debug.Assert(arrayBytesBestFit != null, "[BaseCodePageEncoding.GetBestFitBytesToUnicodeData]Expected non-null arrayBytesBestFit"); // Normally we don't have any best fit data. @@ -336,7 +319,6 @@ namespace System.Text // is invalid. so we detect that by validating the memory section handle then re-initialize the memory // section by calling LoadManagedCodePage() method and eventually the mapped file handle and // the memory section pointer will get finalized one more time. - [System.Security.SecurityCritical] // auto-generated internal unsafe void CheckMemorySection() { if (safeMemorySectionHandle != null && safeMemorySectionHandle.DangerousGetHandle() == IntPtr.Zero) diff --git a/src/mscorlib/src/System/Text/CodePageEncoding.cs b/src/mscorlib/src/System/Text/CodePageEncoding.cs index 9f1b2d2..7805c65 100644 --- a/src/mscorlib/src/System/Text/CodePageEncoding.cs +++ b/src/mscorlib/src/System/Text/CodePageEncoding.cs @@ -11,6 +11,7 @@ namespace System.Text using System; using System.Runtime.Serialization; using System.Security.Permissions; + using System.Diagnostics; using System.Diagnostics.Contracts; /*=================================CodePageEncoding================================== @@ -44,7 +45,7 @@ namespace System.Text internal CodePageEncoding(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // All versions have a code page @@ -74,7 +75,6 @@ namespace System.Text } // Just get it from GetEncoding - [System.Security.SecurityCritical] // auto-generated public Object GetRealObject(StreamingContext context) { // Get our encoding (Note: This has default fallbacks for readonly and everett cases) @@ -93,11 +93,10 @@ namespace System.Text } // ISerializable implementation - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { // We cannot ever call this. - Contract.Assert(false, "Didn't expect to make it to CodePageEncoding ISerializable.GetObjectData"); + Debug.Assert(false, "Didn't expect to make it to CodePageEncoding ISerializable.GetObjectData"); throw new ArgumentException(Environment.GetResourceString("Arg_ExecutionEngineException")); } @@ -113,25 +112,23 @@ namespace System.Text internal Decoder(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); this.realEncoding = (Encoding)info.GetValue("encoding", typeof(Encoding)); } // Just get it from GetDecider - [System.Security.SecurityCritical] // auto-generated public Object GetRealObject(StreamingContext context) { return this.realEncoding.GetDecoder(); } // ISerializable implementation, get data for this object - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { // We cannot ever call this. - Contract.Assert(false, "Didn't expect to make it to CodePageEncoding.Decoder.GetObjectData"); + Debug.Assert(false, "Didn't expect to make it to CodePageEncoding.Decoder.GetObjectData"); throw new ArgumentException(Environment.GetResourceString("Arg_ExecutionEngineException")); } } diff --git a/src/mscorlib/src/System/Text/DBCSCodePageEncoding.cs b/src/mscorlib/src/System/Text/DBCSCodePageEncoding.cs index c103d78..28b85d5 100644 --- a/src/mscorlib/src/System/Text/DBCSCodePageEncoding.cs +++ b/src/mscorlib/src/System/Text/DBCSCodePageEncoding.cs @@ -6,6 +6,7 @@ namespace System.Text { using System; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Text; using System.Threading; @@ -20,13 +21,10 @@ namespace System.Text { // Pointers to our memory section parts [NonSerialized] - [SecurityCritical] protected unsafe char* mapBytesToUnicode = null; // char 65536 [NonSerialized] - [SecurityCritical] protected unsafe ushort* mapUnicodeToBytes = null; // byte 65536 [NonSerialized] - [SecurityCritical] protected unsafe int* mapCodePageCached = null; // to remember which CP is cached [NonSerialized] @@ -45,23 +43,20 @@ namespace System.Text [NonSerialized] protected char charUnknown = (char)0; - [System.Security.SecurityCritical] // auto-generated public DBCSCodePageEncoding(int codePage) : this(codePage, codePage) { } - [System.Security.SecurityCritical] // auto-generated internal DBCSCodePageEncoding(int codePage, int dataCodePage) : base(codePage, dataCodePage) { } // Constructor called by serialization. // Note: We use the base GetObjectData however - [System.Security.SecurityCritical] // auto-generated internal DBCSCodePageEncoding(SerializationInfo info, StreamingContext context) : base(0) { // Actually this can't ever get called, CodePageEncoding is our proxy - Contract.Assert(false, "Didn't expect to make it to DBCSCodePageEncoding serialization constructor"); + Debug.Assert(false, "Didn't expect to make it to DBCSCodePageEncoding serialization constructor"); throw new ArgumentNullException("this"); } @@ -93,11 +88,10 @@ namespace System.Text // corrospond to those unicode code points. // We have a managed code page entry, so load our tables // - [System.Security.SecurityCritical] // auto-generated protected override unsafe void LoadManagedCodePage() { // Should be loading OUR code page - Contract.Assert(pCodePage->CodePage == this.dataTableCodePage, + Debug.Assert(pCodePage->CodePage == this.dataTableCodePage, "[DBCSCodePageEncoding.LoadManagedCodePage]Expected to load data table code page"); // Make sure we're really a 1 byte code page @@ -120,7 +114,7 @@ namespace System.Text byteCountUnknown++; // We use fallback encoder, which uses ?, which so far all of our tables do as well - Contract.Assert(bytesUnknown == 0x3f, + Debug.Assert(bytesUnknown == 0x3f, "[DBCSCodePageEncoding.LoadManagedCodePage]Expected 0x3f (?) as unknown byte character"); // Get our mapped section (bytes to allocate = 2 bytes per 65536 Unicode chars + 2 bytes per 65536 DBCS chars) @@ -134,7 +128,7 @@ namespace System.Text // If its cached (& filled in) we don't have to do anything else if (*mapCodePageCached != 0) { - Contract.Assert(((*mapCodePageCached == this.dataTableCodePage && this.bFlagDataTable) || + Debug.Assert(((*mapCodePageCached == this.dataTableCodePage && this.bFlagDataTable) || (*mapCodePageCached == this.CodePage && !this.bFlagDataTable)), "[DBCSCodePageEncoding.LoadManagedCodePage]Expected mapped section cached page flag to be set to data table or regular code page."); @@ -188,7 +182,7 @@ namespace System.Text else if (input == LEAD_BYTE_CHAR) // 0xfffe { // Lead byte mark - Contract.Assert(bytePosition < 0x100, "[DBCSCodePageEncoding.LoadManagedCodePage]expected lead byte to be < 0x100"); + Debug.Assert(bytePosition < 0x100, "[DBCSCodePageEncoding.LoadManagedCodePage]expected lead byte to be < 0x100"); useBytes = bytePosition; // input stays 0xFFFE } @@ -235,7 +229,6 @@ namespace System.Text } // Any special processing for this code page - [System.Security.SecurityCritical] // auto-generated protected virtual unsafe void CleanUpEndBytes(char* chars) { } @@ -256,7 +249,6 @@ namespace System.Text } // Read in our best fit table - [System.Security.SecurityCritical] // auto-generated protected unsafe override void ReadBestFitTable() { // Lock so we don't confuse ourselves. @@ -407,7 +399,7 @@ namespace System.Text // If they're out of order we need to sort them. if (bOutOfOrder) { - Contract.Assert((arrayTemp.Length / 2) < 20, + Debug.Assert((arrayTemp.Length / 2) < 20, "[DBCSCodePageEncoding.ReadBestFitTable]Expected small best fit table < 20 for code page " + CodePage + ", not " + arrayTemp.Length / 2); for (int i = 0; i < arrayTemp.Length - 2; i+=2) @@ -515,7 +507,7 @@ namespace System.Text // We can't do this assert for CP 51932 & 50220 because they aren't // calling CleanUpBytes() for best fit. All the string stuff here // also makes this assert slow. - // Contract.Assert(arrayTemp[iBestFitCount-1] != (char)0xFFFD, String.Format( + // Debug.Assert(arrayTemp[iBestFitCount-1] != (char)0xFFFD, String.Format( // "[DBCSCodePageEncoding.ReadBestFitTable] No valid Unicode value {0:X4} for round trip bytes {1:X4}, encoding {2}", // (int)mapBytesToUnicode[input], (int)input, CodePage)); } @@ -534,15 +526,14 @@ namespace System.Text // GetByteCount // Note: We start by assuming that the output will be the same as count. Having // an encoder or fallback may change that assumption - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS encoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already - Contract.Assert(count >= 0, "[DBCSCodePageEncoding.GetByteCount]count is negative"); - Contract.Assert(chars != null, "[DBCSCodePageEncoding.GetByteCount]chars is null"); + Debug.Assert(count >= 0, "[DBCSCodePageEncoding.GetByteCount]count is negative"); + Debug.Assert(chars != null, "[DBCSCodePageEncoding.GetByteCount]chars is null"); // Assert because we shouldn't be able to have a null encoder. - Contract.Assert(encoderFallback != null, "[DBCSCodePageEncoding.GetByteCount]Attempting to use null fallback"); + Debug.Assert(encoderFallback != null, "[DBCSCodePageEncoding.GetByteCount]Attempting to use null fallback"); CheckMemorySection(); @@ -568,8 +559,8 @@ namespace System.Text // We may have a left over character from last time, try and process it. if (charLeftOver > 0) { - Contract.Assert(Char.IsHighSurrogate(charLeftOver), "[DBCSCodePageEncoding.GetByteCount]leftover character should be high surrogate"); - Contract.Assert(encoder != null, + Debug.Assert(Char.IsHighSurrogate(charLeftOver), "[DBCSCodePageEncoding.GetByteCount]leftover character should be high surrogate"); + Debug.Assert(encoder != null, "[DBCSCodePageEncoding.GetByteCount]Expect to have encoder if we have a charLeftOver"); // Since left over char was a surrogate, it'll have to be fallen back. @@ -625,18 +616,17 @@ namespace System.Text return (int)byteCount; } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS encoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already - Contract.Assert(bytes != null, "[DBCSCodePageEncoding.GetBytes]bytes is null"); - Contract.Assert(byteCount >= 0, "[DBCSCodePageEncoding.GetBytes]byteCount is negative"); - Contract.Assert(chars != null, "[DBCSCodePageEncoding.GetBytes]chars is null"); - Contract.Assert(charCount >= 0, "[DBCSCodePageEncoding.GetBytes]charCount is negative"); + Debug.Assert(bytes != null, "[DBCSCodePageEncoding.GetBytes]bytes is null"); + Debug.Assert(byteCount >= 0, "[DBCSCodePageEncoding.GetBytes]byteCount is negative"); + Debug.Assert(chars != null, "[DBCSCodePageEncoding.GetBytes]chars is null"); + Debug.Assert(charCount >= 0, "[DBCSCodePageEncoding.GetBytes]charCount is negative"); // Assert because we shouldn't be able to have a null encoder. - Contract.Assert(encoderFallback != null, "[DBCSCodePageEncoding.GetBytes]Attempting to use null encoder fallback"); + Debug.Assert(encoderFallback != null, "[DBCSCodePageEncoding.GetBytes]Attempting to use null encoder fallback"); CheckMemorySection(); @@ -654,7 +644,7 @@ namespace System.Text if (encoder != null) { charLeftOver = encoder.charLeftOver; - Contract.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver), + Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver), "[DBCSCodePageEncoding.GetBytes]leftover character should be high surrogate"); // Go ahead and get the fallback buffer (need leftover fallback if converting) @@ -669,7 +659,7 @@ namespace System.Text // We may have a left over character from last time, try and process it. if (charLeftOver > 0) { - Contract.Assert(encoder != null, + Debug.Assert(encoder != null, "[DBCSCodePageEncoding.GetBytes]Expect to have encoder if we have a charLeftOver"); // Since left over char was a surrogate, it'll have to be fallen back. @@ -702,7 +692,7 @@ namespace System.Text if (fallbackBuffer == null) { // Initialize the buffer - Contract.Assert(encoder == null, + Debug.Assert(encoder == null, "[DBCSCodePageEncoding.GetBytes]Expected delayed create fallback only if no encoder."); fallbackBuffer = this.encoderFallback.CreateFallbackBuffer(); fallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, true); @@ -724,7 +714,7 @@ namespace System.Text // didn't use this char, we'll throw or use buffer if (fallbackBuffer == null || fallbackBuffer.bFallingBack == false) { - Contract.Assert(chars > charStart, + Debug.Assert(chars > charStart, "[DBCSCodePageEncoding.GetBytes]Expected chars to have advanced (double byte case)"); chars--; // don't use last char } @@ -743,7 +733,7 @@ namespace System.Text // didn't use this char, we'll throw or use buffer if (fallbackBuffer == null || fallbackBuffer.bFallingBack == false) { - Contract.Assert(chars > charStart, + Debug.Assert(chars > charStart, "[DBCSCodePageEncoding.GetBytes]Expected chars to have advanced (single byte case)"); chars--; // don't use last char } @@ -771,7 +761,7 @@ namespace System.Text // If we're not converting we must not have a fallback buffer // (We don't really have a way to clear none-encoder using fallbacks however) -// Contract.Assert((encoder == null || encoder.m_throwOnOverflow) && +// Debug.Assert((encoder == null || encoder.m_throwOnOverflow) && // (fallbackBuffer == null || fallbackBuffer.Remaining == 0), // "[DBCSEncoding.GetBytes]Expected empty fallback buffer at end if not converting"); @@ -779,12 +769,11 @@ namespace System.Text } // This is internal and called by something else, - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder) { // Just assert, we're called internally so these should be safe, checked already - Contract.Assert(bytes != null, "[DBCSCodePageEncoding.GetCharCount]bytes is null"); - Contract.Assert(count >= 0, "[DBCSCodePageEncoding.GetCharCount]byteCount is negative"); + Debug.Assert(bytes != null, "[DBCSCodePageEncoding.GetCharCount]bytes is null"); + Debug.Assert(count >= 0, "[DBCSCodePageEncoding.GetCharCount]byteCount is negative"); CheckMemorySection(); @@ -800,7 +789,7 @@ namespace System.Text // Shouldn't have anything in fallback buffer for GetCharCount // (don't have to check m_throwOnOverflow for count) - Contract.Assert(decoder == null || + Debug.Assert(decoder == null || !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[DBCSCodePageEncoding.GetCharCount]Expected empty fallback buffer at start"); @@ -818,7 +807,7 @@ namespace System.Text } - Contract.Assert(fallbackBuffer == null, + Debug.Assert(fallbackBuffer == null, "[DBCSCodePageEncoding.GetCharCount]Expected empty fallback buffer"); fallbackBuffer = decoder.FallbackBuffer; fallbackBuffer.InternalInitialize(bytes, null); @@ -842,7 +831,7 @@ namespace System.Text charCount--; // We'll need a fallback - Contract.Assert(fallbackBuffer == null, + Debug.Assert(fallbackBuffer == null, "[DBCSCodePageEncoding.GetCharCount]Expected empty fallback buffer for unknown pair"); fallbackBuffer = decoder.FallbackBuffer; fallbackBuffer.InternalInitialize(byteEnd - count, null); @@ -917,7 +906,7 @@ namespace System.Text } // Shouldn't have anything in fallback buffer for GetChars - Contract.Assert(decoder == null || !decoder.m_throwOnOverflow || + Debug.Assert(decoder == null || !decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[DBCSCodePageEncoding.GetCharCount]Expected empty fallback buffer at end"); @@ -925,15 +914,14 @@ namespace System.Text return charCount; } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetChars(byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already - Contract.Assert(bytes != null, "[DBCSCodePageEncoding.GetChars]bytes is null"); - Contract.Assert(byteCount >= 0, "[DBCSCodePageEncoding.GetChars]byteCount is negative"); - Contract.Assert(chars != null, "[DBCSCodePageEncoding.GetChars]chars is null"); - Contract.Assert(charCount >= 0, "[DBCSCodePageEncoding.GetChars]charCount is negative"); + Debug.Assert(bytes != null, "[DBCSCodePageEncoding.GetChars]bytes is null"); + Debug.Assert(byteCount >= 0, "[DBCSCodePageEncoding.GetChars]byteCount is negative"); + Debug.Assert(chars != null, "[DBCSCodePageEncoding.GetChars]chars is null"); + Debug.Assert(charCount >= 0, "[DBCSCodePageEncoding.GetChars]charCount is negative"); CheckMemorySection(); @@ -951,7 +939,7 @@ namespace System.Text DecoderFallbackBuffer fallbackBuffer = null; // Shouldn't have anything in fallback buffer for GetChars - Contract.Assert(decoder == null || !decoder.m_throwOnOverflow || + Debug.Assert(decoder == null || !decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[DBCSCodePageEncoding.GetChars]Expected empty fallback buffer at start"); @@ -970,7 +958,7 @@ namespace System.Text // Well, we're flushing, so use '?' or fallback // fallback leftover byte - Contract.Assert(fallbackBuffer == null, + Debug.Assert(fallbackBuffer == null, "[DBCSCodePageEncoding.GetChars]Expected empty fallback"); fallbackBuffer = decoder.FallbackBuffer; fallbackBuffer.InternalInitialize(bytes, charEnd); @@ -995,7 +983,7 @@ namespace System.Text char cDecoder = mapBytesToUnicode[iBytes]; if (cDecoder == UNKNOWN_CHAR_FLAG && iBytes != 0) { - Contract.Assert(fallbackBuffer == null, + Debug.Assert(fallbackBuffer == null, "[DBCSCodePageEncoding.GetChars]Expected empty fallback for two bytes"); fallbackBuffer = decoder.FallbackBuffer; fallbackBuffer.InternalInitialize(byteEnd - byteCount, charEnd); @@ -1073,7 +1061,7 @@ namespace System.Text if (!fallbackBuffer.InternalFallback(byteBuffer, bytes, ref chars)) { // May or may not throw, but we didn't get these byte(s) - Contract.Assert(bytes >= byteStart + byteBuffer.Length, + Debug.Assert(bytes >= byteStart + byteBuffer.Length, "[DBCSCodePageEncoding.GetChars]Expected bytes to have advanced for fallback"); bytes-=byteBuffer.Length; // didn't use these byte(s) fallbackBuffer.InternalReset(); // Didn't fall this back @@ -1087,12 +1075,12 @@ namespace System.Text if (chars >= charEnd) { // May or may not throw, but we didn't get these byte(s) - Contract.Assert(bytes > byteStart, + Debug.Assert(bytes > byteStart, "[DBCSCodePageEncoding.GetChars]Expected bytes to have advanced for lead byte"); bytes--; // unused byte if (iBytes >= 0x100) { - Contract.Assert(bytes > byteStart, + Debug.Assert(bytes > byteStart, "[DBCSCodePageEncoding.GetChars]Expected bytes to have advanced for trail byte"); bytes--; // 2nd unused byte } @@ -1118,7 +1106,7 @@ namespace System.Text } // Shouldn't have anything in fallback buffer for GetChars - Contract.Assert(decoder == null || !decoder.m_throwOnOverflow || + Debug.Assert(decoder == null || !decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[DBCSCodePageEncoding.GetChars]Expected empty fallback buffer at end"); @@ -1129,7 +1117,7 @@ namespace System.Text public override int GetMaxByteCount(int charCount) { if (charCount < 0) - throw new ArgumentOutOfRangeException("charCount", + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -1143,7 +1131,7 @@ namespace System.Text byteCount *= 2; if (byteCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); return (int)byteCount; } @@ -1151,7 +1139,7 @@ namespace System.Text public override int GetMaxCharCount(int byteCount) { if (byteCount < 0) - throw new ArgumentOutOfRangeException("byteCount", + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -1163,7 +1151,7 @@ namespace System.Text charCount *= DecoderFallback.MaxCharCount; if (charCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow")); return (int)charCount; } diff --git a/src/mscorlib/src/System/Text/Decoder.cs b/src/mscorlib/src/System/Text/Decoder.cs index f794dc4..0ebbacd 100644 --- a/src/mscorlib/src/System/Text/Decoder.cs +++ b/src/mscorlib/src/System/Text/Decoder.cs @@ -7,6 +7,7 @@ namespace System.Text using System.Runtime.Serialization; using System.Text; using System; + using System.Diagnostics; using System.Diagnostics.Contracts; // A Decoder is used to decode a sequence of blocks of bytes into a // sequence of blocks of characters. Following instantiation of a decoder, @@ -49,13 +50,13 @@ namespace System.Text set { if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); Contract.EndContractBlock(); // Can't change fallback if buffer is wrong if (m_fallbackBuffer != null && m_fallbackBuffer.Remaining > 0) throw new ArgumentException( - Environment.GetResourceString("Argument_FallbackBufferNotEmpty"), "value"); + Environment.GetResourceString("Argument_FallbackBufferNotEmpty"), nameof(value)); m_fallback = value; m_fallbackBuffer = null; @@ -124,18 +125,17 @@ namespace System.Text // We expect this to be the workhorse for NLS Encodings, but for existing // ones we need a working (if slow) default implimentation) - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public virtual unsafe int GetCharCount(byte* bytes, int count, bool flush) { // Validate input parameters if (bytes == null) - throw new ArgumentNullException("bytes", + throw new ArgumentNullException(nameof(bytes), Environment.GetResourceString("ArgumentNull_Array")); if (count < 0) - throw new ArgumentOutOfRangeException("count", + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -189,7 +189,6 @@ namespace System.Text // the char[] to our char* output buffer. If the result count was wrong, we // could easily overflow our output buffer. Therefore we do an extra test // when we copy the buffer so that we don't overflow charCount either. - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public virtual unsafe int GetChars(byte* bytes, int byteCount, @@ -197,11 +196,11 @@ namespace System.Text { // Validate input parameters if (chars == null || bytes == null) - throw new ArgumentNullException(chars == null ? "chars" : "bytes", + throw new ArgumentNullException(chars == null ? nameof(chars) : nameof(bytes), Environment.GetResourceString("ArgumentNull_Array")); if (byteCount < 0 || charCount < 0) - throw new ArgumentOutOfRangeException((byteCount<0 ? "byteCount" : "charCount"), + throw new ArgumentOutOfRangeException((byteCount<0 ? nameof(byteCount) : nameof(charCount)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -218,7 +217,7 @@ namespace System.Text // Do the work int result = GetChars(arrByte, 0, byteCount, arrChar, 0, flush); - Contract.Assert(result <= charCount, "Returned more chars than we have space for"); + Debug.Assert(result <= charCount, "Returned more chars than we have space for"); // Copy the char array // WARNING: We MUST make sure that we don't copy too many chars. We can't @@ -256,23 +255,23 @@ namespace System.Text { // Validate parameters if (bytes == null || chars == null) - throw new ArgumentNullException((bytes == null ? "bytes" : "chars"), + throw new ArgumentNullException((bytes == null ? nameof(bytes) : nameof(chars)), Environment.GetResourceString("ArgumentNull_Array")); if (byteIndex < 0 || byteCount < 0) - throw new ArgumentOutOfRangeException((byteIndex<0 ? "byteIndex" : "byteCount"), + throw new ArgumentOutOfRangeException((byteIndex<0 ? nameof(byteIndex) : nameof(byteCount)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (charIndex < 0 || charCount < 0) - throw new ArgumentOutOfRangeException((charIndex<0 ? "charIndex" : "charCount"), + throw new ArgumentOutOfRangeException((charIndex<0 ? nameof(charIndex) : nameof(charCount)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (bytes.Length - byteIndex < byteCount) - throw new ArgumentOutOfRangeException("bytes", + throw new ArgumentOutOfRangeException(nameof(bytes), Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); if (chars.Length - charIndex < charCount) - throw new ArgumentOutOfRangeException("chars", + throw new ArgumentOutOfRangeException(nameof(chars), Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); Contract.EndContractBlock(); @@ -306,7 +305,6 @@ namespace System.Text // Note that if all of the input bytes are not consumed, then we'll do a /2, which means // that its likely that we didn't consume as many bytes as we could have. For some // applications this could be slow. (Like trying to exactly fill an output buffer from a bigger stream) - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public virtual unsafe void Convert(byte* bytes, int byteCount, @@ -315,11 +313,11 @@ namespace System.Text { // Validate input parameters if (chars == null || bytes == null) - throw new ArgumentNullException(chars == null ? "chars" : "bytes", + throw new ArgumentNullException(chars == null ? nameof(chars) : nameof(bytes), Environment.GetResourceString("ArgumentNull_Array")); if (byteCount < 0 || charCount < 0) - throw new ArgumentOutOfRangeException((byteCount<0 ? "byteCount" : "charCount"), + throw new ArgumentOutOfRangeException((byteCount<0 ? nameof(byteCount) : nameof(charCount)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/Text/DecoderBestFitFallback.cs b/src/mscorlib/src/System/Text/DecoderBestFitFallback.cs index 5c1dcd9..6389b4b 100644 --- a/src/mscorlib/src/System/Text/DecoderBestFitFallback.cs +++ b/src/mscorlib/src/System/Text/DecoderBestFitFallback.cs @@ -10,6 +10,7 @@ namespace System.Text using System; using System.Text; using System.Threading; + using System.Diagnostics; using System.Diagnostics.Contracts; [Serializable] @@ -101,7 +102,7 @@ namespace System.Text public override bool Fallback(byte[] bytesUnknown, int index) { // We expect no previous fallback in our buffer - Contract.Assert(iCount < 1, "[DecoderReplacementFallbackBuffer.Fallback] Calling fallback without a previously empty buffer"); + Debug.Assert(iCount < 1, "[DecoderReplacementFallbackBuffer.Fallback] Calling fallback without a previously empty buffer"); cBestFit = TryBestFit(bytesUnknown); if (cBestFit == '\0') @@ -155,7 +156,6 @@ namespace System.Text } // Clear the buffer - [System.Security.SecuritySafeCritical] // overrides public transparent member public override unsafe void Reset() { iCount = -1; @@ -163,7 +163,6 @@ namespace System.Text } // This version just counts the fallback and doesn't actually copy anything. - [System.Security.SecurityCritical] // auto-generated internal unsafe override int InternalFallback(byte[] bytes, byte* pBytes) // Right now this has both bytes and bytes[], since we might have extra bytes, hence the // array, and we might need the index, hence the byte* @@ -212,7 +211,7 @@ namespace System.Text if (cTest == cCheck) { // We found it - Contract.Assert(index + 1 < oFallback.arrayBestFit.Length, + Debug.Assert(index + 1 < oFallback.arrayBestFit.Length, "[InternalDecoderBestFitFallbackBuffer.TryBestFit]Expected replacement character at end of array"); return oFallback.arrayBestFit[index + 1]; } @@ -233,7 +232,7 @@ namespace System.Text if (oFallback.arrayBestFit[index] == cCheck) { // We found it - Contract.Assert(index + 1 < oFallback.arrayBestFit.Length, + Debug.Assert(index + 1 < oFallback.arrayBestFit.Length, "[InternalDecoderBestFitFallbackBuffer.TryBestFit]Expected replacement character at end of array"); return oFallback.arrayBestFit[index + 1]; } diff --git a/src/mscorlib/src/System/Text/DecoderFallback.cs b/src/mscorlib/src/System/Text/DecoderFallback.cs index 1698fd3..42483a7 100644 --- a/src/mscorlib/src/System/Text/DecoderFallback.cs +++ b/src/mscorlib/src/System/Text/DecoderFallback.cs @@ -7,6 +7,7 @@ using System; using System.Security; using System.Threading; using System.Globalization; +using System.Diagnostics; using System.Diagnostics.Contracts; namespace System.Text @@ -115,13 +116,10 @@ namespace System.Text // Internal items to help us figure out what we're doing as far as error messages, etc. // These help us with our performance and messages internally - [SecurityCritical] internal unsafe byte* byteStart; - [SecurityCritical] internal unsafe char* charEnd; // Internal Reset - [System.Security.SecurityCritical] // auto-generated internal unsafe void InternalReset() { byteStart = null; @@ -130,7 +128,6 @@ namespace System.Text // Set the above values // This can't be part of the constructor because DecoderFallbacks would have to know how to impliment these. - [System.Security.SecurityCritical] // auto-generated internal unsafe void InternalInitialize(byte* byteStart, char* charEnd) { this.byteStart = byteStart; @@ -145,7 +142,6 @@ namespace System.Text // Right now this has both bytes and bytes[], since we might have extra bytes, hence the // array, and we might need the index, hence the byte* // Don't touch ref chars unless we succeed - [System.Security.SecurityCritical] // auto-generated internal unsafe virtual bool InternalFallback(byte[] bytes, byte* pBytes, ref char* chars) { // Copy bytes to array (slow, but right now that's what we get to do. @@ -153,7 +149,7 @@ namespace System.Text // for (int i = 0; i < count; i++) // bytesUnknown[i] = *(bytes++); - Contract.Assert(byteStart != null, "[DecoderFallback.InternalFallback]Used InternalFallback without calling InternalInitialize"); + Debug.Assert(byteStart != null, "[DecoderFallback.InternalFallback]Used InternalFallback without calling InternalInitialize"); // See if there's a fallback character and we have an output buffer then copy our string. if (this.Fallback(bytes, (int)(pBytes - byteStart - bytes.Length))) @@ -204,7 +200,6 @@ namespace System.Text } // This version just counts the fallback and doesn't actually copy anything. - [System.Security.SecurityCritical] // auto-generated internal unsafe virtual int InternalFallback(byte[] bytes, byte* pBytes) // Right now this has both bytes and bytes[], since we might have extra bytes, hence the // array, and we might need the index, hence the byte* @@ -214,7 +209,7 @@ namespace System.Text // for (int i = 0; i < count; i++) // bytesUnknown[i] = *(bytes++); - Contract.Assert(byteStart != null, "[DecoderFallback.InternalFallback]Used InternalFallback without calling InternalInitialize"); + Debug.Assert(byteStart != null, "[DecoderFallback.InternalFallback]Used InternalFallback without calling InternalInitialize"); // See if there's a fallback character and we have an output buffer then copy our string. if (this.Fallback(bytes, (int)(pBytes - byteStart - bytes.Length))) @@ -277,7 +272,7 @@ namespace System.Text // Throw it, using our complete bytes throw new ArgumentException( Environment.GetResourceString("Argument_RecursiveFallbackBytes", - strBytes.ToString()), "bytesUnknown"); + strBytes.ToString()), nameof(bytesUnknown)); } } diff --git a/src/mscorlib/src/System/Text/DecoderNLS.cs b/src/mscorlib/src/System/Text/DecoderNLS.cs index c2e82dd..e44c43a 100644 --- a/src/mscorlib/src/System/Text/DecoderNLS.cs +++ b/src/mscorlib/src/System/Text/DecoderNLS.cs @@ -42,7 +42,6 @@ namespace System.Text } // ISerializable implementation. called during serialization. - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { SerializeDecoder(info); @@ -77,20 +76,19 @@ namespace System.Text return GetCharCount(bytes, index, count, false); } - [System.Security.SecuritySafeCritical] // auto-generated public override unsafe int GetCharCount(byte[] bytes, int index, int count, bool flush) { // Validate Parameters if (bytes == null) - throw new ArgumentNullException("bytes", + throw new ArgumentNullException(nameof(bytes), Environment.GetResourceString("ArgumentNull_Array")); if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), + throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (bytes.Length - index < count) - throw new ArgumentOutOfRangeException("bytes", + throw new ArgumentOutOfRangeException(nameof(bytes), Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); Contract.EndContractBlock(); @@ -104,16 +102,15 @@ namespace System.Text return GetCharCount(pBytes + index, count, flush); } - [System.Security.SecurityCritical] // auto-generated public unsafe override int GetCharCount(byte* bytes, int count, bool flush) { // Validate parameters if (bytes == null) - throw new ArgumentNullException("bytes", + throw new ArgumentNullException(nameof(bytes), Environment.GetResourceString("ArgumentNull_Array")); if (count < 0) - throw new ArgumentOutOfRangeException("count", + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -131,25 +128,24 @@ namespace System.Text return GetChars(bytes, byteIndex, byteCount, chars, charIndex, false); } - [System.Security.SecuritySafeCritical] // auto-generated public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex, bool flush) { // Validate Parameters if (bytes == null || chars == null) - throw new ArgumentNullException(bytes == null ? "bytes" : "chars", + throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), Environment.GetResourceString("ArgumentNull_Array")); if (byteIndex < 0 || byteCount < 0) - throw new ArgumentOutOfRangeException((byteIndex<0 ? "byteIndex" : "byteCount"), + throw new ArgumentOutOfRangeException((byteIndex<0 ? nameof(byteIndex) : nameof(byteCount)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if ( bytes.Length - byteIndex < byteCount) - throw new ArgumentOutOfRangeException("bytes", + throw new ArgumentOutOfRangeException(nameof(bytes), Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); if (charIndex < 0 || charIndex > chars.Length) - throw new ArgumentOutOfRangeException("charIndex", + throw new ArgumentOutOfRangeException(nameof(charIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.EndContractBlock(); @@ -170,17 +166,16 @@ namespace System.Text pChars + charIndex, charCount, flush); } - [System.Security.SecurityCritical] // auto-generated public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount, bool flush) { // Validate parameters if (chars == null || bytes == null) - throw new ArgumentNullException((chars == null ? "chars" : "bytes"), + throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), Environment.GetResourceString("ArgumentNull_Array")); if (byteCount < 0 || charCount < 0) - throw new ArgumentOutOfRangeException((byteCount<0 ? "byteCount" : "charCount"), + throw new ArgumentOutOfRangeException((byteCount<0 ? nameof(byteCount) : nameof(charCount)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -194,30 +189,29 @@ namespace System.Text // This method is used when the output buffer might not be big enough. // Just call the pointer version. (This gets chars) - [System.Security.SecuritySafeCritical] // auto-generated public override unsafe void Convert(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex, int charCount, bool flush, out int bytesUsed, out int charsUsed, out bool completed) { // Validate parameters if (bytes == null || chars == null) - throw new ArgumentNullException((bytes == null ? "bytes" : "chars"), + throw new ArgumentNullException((bytes == null ? nameof(bytes) : nameof(chars)), Environment.GetResourceString("ArgumentNull_Array")); if (byteIndex < 0 || byteCount < 0) - throw new ArgumentOutOfRangeException((byteIndex<0 ? "byteIndex" : "byteCount"), + throw new ArgumentOutOfRangeException((byteIndex<0 ? nameof(byteIndex) : nameof(byteCount)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (charIndex < 0 || charCount < 0) - throw new ArgumentOutOfRangeException((charIndex<0 ? "charIndex" : "charCount"), + throw new ArgumentOutOfRangeException((charIndex<0 ? nameof(charIndex) : nameof(charCount)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (bytes.Length - byteIndex < byteCount) - throw new ArgumentOutOfRangeException("bytes", + throw new ArgumentOutOfRangeException(nameof(bytes), Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); if (chars.Length - charIndex < charCount) - throw new ArgumentOutOfRangeException("chars", + throw new ArgumentOutOfRangeException(nameof(chars), Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); Contract.EndContractBlock(); @@ -241,18 +235,17 @@ namespace System.Text // This is the version that used pointers. We call the base encoding worker function // after setting our appropriate internal variables. This is getting chars - [System.Security.SecurityCritical] // auto-generated public unsafe override void Convert(byte* bytes, int byteCount, char* chars, int charCount, bool flush, out int bytesUsed, out int charsUsed, out bool completed) { // Validate input parameters if (chars == null || bytes == null) - throw new ArgumentNullException(chars == null ? "chars" : "bytes", + throw new ArgumentNullException(chars == null ? nameof(chars) : nameof(bytes), Environment.GetResourceString("ArgumentNull_Array")); if (byteCount < 0 || charCount < 0) - throw new ArgumentOutOfRangeException((byteCount<0 ? "byteCount" : "charCount"), + throw new ArgumentOutOfRangeException((byteCount<0 ? nameof(byteCount) : nameof(charCount)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/Text/DecoderReplacementFallback.cs b/src/mscorlib/src/System/Text/DecoderReplacementFallback.cs index c732d15..77c8560 100644 --- a/src/mscorlib/src/System/Text/DecoderReplacementFallback.cs +++ b/src/mscorlib/src/System/Text/DecoderReplacementFallback.cs @@ -5,6 +5,7 @@ namespace System.Text { using System; + using System.Diagnostics; using System.Diagnostics.Contracts; [Serializable] @@ -21,7 +22,7 @@ namespace System.Text public DecoderReplacementFallback(String replacement) { if (replacement == null) - throw new ArgumentNullException("replacement"); + throw new ArgumentNullException(nameof(replacement)); Contract.EndContractBlock(); // Make sure it doesn't have bad surrogate pairs @@ -58,7 +59,7 @@ namespace System.Text break; } if (bFoundHigh) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex", "replacement")); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex", nameof(replacement))); strDefault = replacement; } @@ -156,7 +157,7 @@ namespace System.Text } // Now make sure its in the expected range - Contract.Assert(fallbackIndex < strDefault.Length && fallbackIndex >= 0, + Debug.Assert(fallbackIndex < strDefault.Length && fallbackIndex >= 0, "Index exceeds buffer range"); return strDefault[fallbackIndex]; @@ -187,7 +188,6 @@ namespace System.Text } // Clear the buffer - [System.Security.SecuritySafeCritical] // auto-generated public override unsafe void Reset() { fallbackCount = -1; @@ -196,7 +196,6 @@ namespace System.Text } // This version just counts the fallback and doesn't actually copy anything. - [System.Security.SecurityCritical] // auto-generated internal unsafe override int InternalFallback(byte[] bytes, byte* pBytes) // Right now this has both bytes and bytes[], since we might have extra bytes, hence the // array, and we might need the index, hence the byte* diff --git a/src/mscorlib/src/System/Text/EUCJPEncoding.cs b/src/mscorlib/src/System/Text/EUCJPEncoding.cs index 7c90cae..44345b2 100644 --- a/src/mscorlib/src/System/Text/EUCJPEncoding.cs +++ b/src/mscorlib/src/System/Text/EUCJPEncoding.cs @@ -50,13 +50,11 @@ namespace System.Text internal class EUCJPEncoding : DBCSCodePageEncoding { // This pretends to be CP 932 as far as memory tables are concerned. - [System.Security.SecurityCritical] // auto-generated public EUCJPEncoding() : base(51932, 932) { this.m_bUseMlangTypeForSerialization = true; } - [System.Security.SecurityCritical] // auto-generated protected unsafe override String GetMemorySectionName() { int iUseCodePage = this.bFlagDataTable ? dataTableCodePage : CodePage; @@ -165,7 +163,6 @@ namespace System.Text return true; } - [System.Security.SecurityCritical] // auto-generated protected override unsafe void CleanUpEndBytes(char* chars) { // Need to special case CP 51932 diff --git a/src/mscorlib/src/System/Text/Encoder.cs b/src/mscorlib/src/System/Text/Encoder.cs index d223dd9..b9d4581 100644 --- a/src/mscorlib/src/System/Text/Encoder.cs +++ b/src/mscorlib/src/System/Text/Encoder.cs @@ -7,6 +7,7 @@ namespace System.Text using System.Runtime.Serialization; using System.Text; using System; + using System.Diagnostics; using System.Diagnostics.Contracts; // An Encoder is used to encode a sequence of blocks of characters into // a sequence of blocks of bytes. Following instantiation of an encoder, @@ -49,13 +50,13 @@ namespace System.Text set { if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); Contract.EndContractBlock(); // Can't change fallback if buffer is wrong if (m_fallbackBuffer != null && m_fallbackBuffer.Remaining > 0) throw new ArgumentException( - Environment.GetResourceString("Argument_FallbackBufferNotEmpty"), "value"); + Environment.GetResourceString("Argument_FallbackBufferNotEmpty"), nameof(value)); m_fallback = value; m_fallbackBuffer = null; @@ -120,18 +121,17 @@ namespace System.Text // We expect this to be the workhorse for NLS encodings // unfortunately for existing overrides, it has to call the [] version, // which is really slow, so avoid this method if you might be calling external encodings. - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public virtual unsafe int GetByteCount(char* chars, int count, bool flush) { // Validate input parameters if (chars == null) - throw new ArgumentNullException("chars", + throw new ArgumentNullException(nameof(chars), Environment.GetResourceString("ArgumentNull_Array")); if (count < 0) - throw new ArgumentOutOfRangeException("count", + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -182,7 +182,6 @@ namespace System.Text // the byte[] to our byte* output buffer. If the result count was wrong, we // could easily overflow our output buffer. Therefore we do an extra test // when we copy the buffer so that we don't overflow byteCount either. - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public virtual unsafe int GetBytes(char* chars, int charCount, @@ -190,11 +189,11 @@ namespace System.Text { // Validate input parameters if (bytes == null || chars == null) - throw new ArgumentNullException(bytes == null ? "bytes" : "chars", + throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), Environment.GetResourceString("ArgumentNull_Array")); if (charCount < 0 || byteCount < 0) - throw new ArgumentOutOfRangeException((charCount<0 ? "charCount" : "byteCount"), + throw new ArgumentOutOfRangeException((charCount<0 ? nameof(charCount) : nameof(byteCount)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -211,7 +210,7 @@ namespace System.Text // Do the work int result = GetBytes(arrChar, 0, charCount, arrByte, 0, flush); - Contract.Assert(result <= byteCount, "Returned more bytes than we have space for"); + Debug.Assert(result <= byteCount, "Returned more bytes than we have space for"); // Copy the byte array // WARNING: We MUST make sure that we don't copy too many bytes. We can't @@ -248,23 +247,23 @@ namespace System.Text { // Validate parameters if (chars == null || bytes == null) - throw new ArgumentNullException((chars == null ? "chars" : "bytes"), + throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), Environment.GetResourceString("ArgumentNull_Array")); if (charIndex < 0 || charCount < 0) - throw new ArgumentOutOfRangeException((charIndex<0 ? "charIndex" : "charCount"), + throw new ArgumentOutOfRangeException((charIndex<0 ? nameof(charIndex) : nameof(charCount)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (byteIndex < 0 || byteCount < 0) - throw new ArgumentOutOfRangeException((byteIndex<0 ? "byteIndex" : "byteCount"), + throw new ArgumentOutOfRangeException((byteIndex<0 ? nameof(byteIndex) : nameof(byteCount)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (chars.Length - charIndex < charCount) - throw new ArgumentOutOfRangeException("chars", + throw new ArgumentOutOfRangeException(nameof(chars), Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); if (bytes.Length - byteIndex < byteCount) - throw new ArgumentOutOfRangeException("bytes", + throw new ArgumentOutOfRangeException(nameof(bytes), Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); Contract.EndContractBlock(); @@ -299,7 +298,6 @@ namespace System.Text // Note that if all of the input chars are not consumed, then we'll do a /2, which means // that its likely that we didn't consume as many chars as we could have. For some // applications this could be slow. (Like trying to exactly fill an output buffer from a bigger stream) - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public virtual unsafe void Convert(char* chars, int charCount, @@ -308,10 +306,10 @@ namespace System.Text { // Validate input parameters if (bytes == null || chars == null) - throw new ArgumentNullException(bytes == null ? "bytes" : "chars", + throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), Environment.GetResourceString("ArgumentNull_Array")); if (charCount < 0 || byteCount < 0) - throw new ArgumentOutOfRangeException((charCount<0 ? "charCount" : "byteCount"), + throw new ArgumentOutOfRangeException((charCount<0 ? nameof(charCount) : nameof(byteCount)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/Text/EncoderBestFitFallback.cs b/src/mscorlib/src/System/Text/EncoderBestFitFallback.cs index 352e969..c5f82a2 100644 --- a/src/mscorlib/src/System/Text/EncoderBestFitFallback.cs +++ b/src/mscorlib/src/System/Text/EncoderBestFitFallback.cs @@ -11,6 +11,7 @@ namespace System.Text using System.Globalization; using System.Text; using System.Threading; + using System.Diagnostics; using System.Diagnostics.Contracts; [Serializable] @@ -103,7 +104,7 @@ namespace System.Text // If we had a buffer already we're being recursive, throw, it's probably at the suspect // character in our array. // Shouldn't be able to get here for all of our code pages, table would have to be messed up. - Contract.Assert(iCount < 1, "[InternalEncoderBestFitFallbackBuffer.Fallback(non surrogate)] Fallback char " + ((int)cBestFit).ToString("X4", CultureInfo.InvariantCulture) + " caused recursive fallback"); + Debug.Assert(iCount < 1, "[InternalEncoderBestFitFallbackBuffer.Fallback(non surrogate)] Fallback char " + ((int)cBestFit).ToString("X4", CultureInfo.InvariantCulture) + " caused recursive fallback"); iCount = iSize = 1; cBestFit = TryBestFit(charUnknown); @@ -117,7 +118,7 @@ namespace System.Text { // Double check input surrogate pair if (!Char.IsHighSurrogate(charUnknownHigh)) - throw new ArgumentOutOfRangeException("charUnknownHigh", + throw new ArgumentOutOfRangeException(nameof(charUnknownHigh), Environment.GetResourceString("ArgumentOutOfRange_Range", 0xD800, 0xDBFF)); @@ -130,7 +131,7 @@ namespace System.Text // If we had a buffer already we're being recursive, throw, it's probably at the suspect // character in our array. 0 is processing last character, < 0 is not falling back // Shouldn't be able to get here, table would have to be messed up. - Contract.Assert(iCount < 1, "[InternalEncoderBestFitFallbackBuffer.Fallback(surrogate)] Fallback char " + ((int)cBestFit).ToString("X4", CultureInfo.InvariantCulture) + " caused recursive fallback"); + Debug.Assert(iCount < 1, "[InternalEncoderBestFitFallbackBuffer.Fallback(surrogate)] Fallback char " + ((int)cBestFit).ToString("X4", CultureInfo.InvariantCulture) + " caused recursive fallback"); // Go ahead and get our fallback, surrogates don't have best fit cBestFit = '?'; @@ -183,7 +184,6 @@ namespace System.Text } // Clear the buffer - [System.Security.SecuritySafeCritical] // overrides public transparent member public override unsafe void Reset() { iCount = -1; @@ -212,7 +212,7 @@ namespace System.Text if (cTest == cUnknown) { // We found it - Contract.Assert(index + 1 < oFallback.arrayBestFit.Length, + Debug.Assert(index + 1 < oFallback.arrayBestFit.Length, "[InternalEncoderBestFitFallbackBuffer.TryBestFit]Expected replacement character at end of array"); return oFallback.arrayBestFit[index + 1]; } @@ -233,7 +233,7 @@ namespace System.Text if (oFallback.arrayBestFit[index] == cUnknown) { // We found it - Contract.Assert(index + 1 < oFallback.arrayBestFit.Length, + Debug.Assert(index + 1 < oFallback.arrayBestFit.Length, "[InternalEncoderBestFitFallbackBuffer.TryBestFit]Expected replacement character at end of array"); return oFallback.arrayBestFit[index + 1]; } diff --git a/src/mscorlib/src/System/Text/EncoderExceptionFallback.cs b/src/mscorlib/src/System/Text/EncoderExceptionFallback.cs index 5ab51cb..051f50a 100644 --- a/src/mscorlib/src/System/Text/EncoderExceptionFallback.cs +++ b/src/mscorlib/src/System/Text/EncoderExceptionFallback.cs @@ -62,7 +62,7 @@ namespace System.Text { if (!Char.IsHighSurrogate(charUnknownHigh)) { - throw new ArgumentOutOfRangeException("charUnknownHigh", + throw new ArgumentOutOfRangeException(nameof(charUnknownHigh), Environment.GetResourceString("ArgumentOutOfRange_Range", 0xD800, 0xDBFF)); } @@ -145,13 +145,13 @@ namespace System.Text { if (!Char.IsHighSurrogate(charUnknownHigh)) { - throw new ArgumentOutOfRangeException("charUnknownHigh", + throw new ArgumentOutOfRangeException(nameof(charUnknownHigh), Environment.GetResourceString("ArgumentOutOfRange_Range", 0xD800, 0xDBFF)); } if (!Char.IsLowSurrogate(charUnknownLow)) { - throw new ArgumentOutOfRangeException("CharUnknownLow", + throw new ArgumentOutOfRangeException(nameof(CharUnknownLow), Environment.GetResourceString("ArgumentOutOfRange_Range", 0xDC00, 0xDFFF)); } diff --git a/src/mscorlib/src/System/Text/EncoderFallback.cs b/src/mscorlib/src/System/Text/EncoderFallback.cs index 4b17041..db2bf93 100644 --- a/src/mscorlib/src/System/Text/EncoderFallback.cs +++ b/src/mscorlib/src/System/Text/EncoderFallback.cs @@ -5,6 +5,7 @@ using System; using System.Security; using System.Threading; +using System.Diagnostics; using System.Diagnostics.Contracts; namespace System.Text @@ -111,9 +112,7 @@ namespace System.Text // Internal items to help us figure out what we're doing as far as error messages, etc. // These help us with our performance and messages internally - [SecurityCritical] internal unsafe char* charStart; - [SecurityCritical] internal unsafe char* charEnd; internal EncoderNLS encoder; internal bool setEncoder; @@ -124,7 +123,6 @@ namespace System.Text // Internal Reset // For example, what if someone fails a conversion and wants to reset one of our fallback buffers? - [System.Security.SecurityCritical] // auto-generated internal unsafe void InternalReset() { charStart = null; @@ -135,7 +133,6 @@ namespace System.Text // Set the above values // This can't be part of the constructor because EncoderFallbacks would have to know how to impliment these. - [System.Security.SecurityCritical] // auto-generated internal unsafe void InternalInitialize(char* charStart, char* charEnd, EncoderNLS encoder, bool setEncoder) { this.charStart = charStart; @@ -163,11 +160,10 @@ namespace System.Text // Note that this could also change the contents of this.encoder, which is the same // object that the caller is using, so the caller could mess up the encoder for us // if they aren't careful. - [System.Security.SecurityCritical] // auto-generated internal unsafe virtual bool InternalFallback(char ch, ref char* chars) { // Shouldn't have null charStart - Contract.Assert(charStart != null, + Debug.Assert(charStart != null, "[EncoderFallback.InternalFallbackBuffer]Fallback buffer is not initialized"); // Get our index, remember chars was preincremented to point at next char, so have to -1 diff --git a/src/mscorlib/src/System/Text/EncoderNLS.cs b/src/mscorlib/src/System/Text/EncoderNLS.cs index d5c52f4..2add017 100644 --- a/src/mscorlib/src/System/Text/EncoderNLS.cs +++ b/src/mscorlib/src/System/Text/EncoderNLS.cs @@ -45,7 +45,6 @@ namespace System.Text } // ISerializable implementation. called during serialization. - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { SerializeEncoder(info); @@ -77,20 +76,19 @@ namespace System.Text m_fallbackBuffer.Reset(); } - [System.Security.SecuritySafeCritical] // auto-generated public override unsafe int GetByteCount(char[] chars, int index, int count, bool flush) { // Validate input parameters if (chars == null) - throw new ArgumentNullException( "chars", + throw new ArgumentNullException(nameof(chars), Environment.GetResourceString("ArgumentNull_Array")); if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), + throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (chars.Length - index < count) - throw new ArgumentOutOfRangeException("chars", + throw new ArgumentOutOfRangeException(nameof(chars), Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); Contract.EndContractBlock(); @@ -107,16 +105,15 @@ namespace System.Text return result; } - [System.Security.SecurityCritical] // auto-generated public unsafe override int GetByteCount(char* chars, int count, bool flush) { // Validate input parameters if (chars == null) - throw new ArgumentNullException( "chars", + throw new ArgumentNullException(nameof(chars), Environment.GetResourceString("ArgumentNull_Array")); if (count < 0) - throw new ArgumentOutOfRangeException("count", + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -125,25 +122,24 @@ namespace System.Text return m_encoding.GetByteCount(chars, count, this); } - [System.Security.SecuritySafeCritical] // auto-generated public override unsafe int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex, bool flush) { // Validate parameters if (chars == null || bytes == null) - throw new ArgumentNullException((chars == null ? "chars" : "bytes"), + throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), Environment.GetResourceString("ArgumentNull_Array")); if (charIndex < 0 || charCount < 0) - throw new ArgumentOutOfRangeException((charIndex<0 ? "charIndex" : "charCount"), + throw new ArgumentOutOfRangeException((charIndex<0 ? nameof(charIndex) : nameof(charCount)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (chars.Length - charIndex < charCount) - throw new ArgumentOutOfRangeException("chars", + throw new ArgumentOutOfRangeException(nameof(chars), Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); if (byteIndex < 0 || byteIndex > bytes.Length) - throw new ArgumentOutOfRangeException("byteIndex", + throw new ArgumentOutOfRangeException(nameof(byteIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); Contract.EndContractBlock(); @@ -163,16 +159,15 @@ namespace System.Text pBytes + byteIndex, byteCount, flush); } - [System.Security.SecurityCritical] // auto-generated public unsafe override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, bool flush) { // Validate parameters if (chars == null || bytes == null) - throw new ArgumentNullException((chars == null ? "chars" : "bytes"), + throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), Environment.GetResourceString("ArgumentNull_Array")); if (byteCount < 0 || charCount < 0) - throw new ArgumentOutOfRangeException((byteCount<0 ? "byteCount" : "charCount"), + throw new ArgumentOutOfRangeException((byteCount<0 ? nameof(byteCount) : nameof(charCount)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -183,30 +178,29 @@ namespace System.Text // This method is used when your output buffer might not be large enough for the entire result. // Just call the pointer version. (This gets bytes) - [System.Security.SecuritySafeCritical] // auto-generated public override unsafe void Convert(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex, int byteCount, bool flush, out int charsUsed, out int bytesUsed, out bool completed) { // Validate parameters if (chars == null || bytes == null) - throw new ArgumentNullException((chars == null ? "chars" : "bytes"), + throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), Environment.GetResourceString("ArgumentNull_Array")); if (charIndex < 0 || charCount < 0) - throw new ArgumentOutOfRangeException((charIndex<0 ? "charIndex" : "charCount"), + throw new ArgumentOutOfRangeException((charIndex<0 ? nameof(charIndex) : nameof(charCount)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (byteIndex < 0 || byteCount < 0) - throw new ArgumentOutOfRangeException((byteIndex<0 ? "byteIndex" : "byteCount"), + throw new ArgumentOutOfRangeException((byteIndex<0 ? nameof(byteIndex) : nameof(byteCount)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); if (chars.Length - charIndex < charCount) - throw new ArgumentOutOfRangeException("chars", + throw new ArgumentOutOfRangeException(nameof(chars), Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); if (bytes.Length - byteIndex < byteCount) - throw new ArgumentOutOfRangeException("bytes", + throw new ArgumentOutOfRangeException(nameof(bytes), Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); Contract.EndContractBlock(); @@ -230,17 +224,16 @@ namespace System.Text // This is the version that uses pointers. We call the base encoding worker function // after setting our appropriate internal variables. This is getting bytes - [System.Security.SecurityCritical] // auto-generated public override unsafe void Convert(char* chars, int charCount, byte* bytes, int byteCount, bool flush, out int charsUsed, out int bytesUsed, out bool completed) { // Validate input parameters if (bytes == null || chars == null) - throw new ArgumentNullException(bytes == null ? "bytes" : "chars", + throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), Environment.GetResourceString("ArgumentNull_Array")); if (charCount < 0 || byteCount < 0) - throw new ArgumentOutOfRangeException((charCount<0 ? "charCount" : "byteCount"), + throw new ArgumentOutOfRangeException((charCount<0 ? nameof(charCount) : nameof(byteCount)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/Text/EncoderReplacementFallback.cs b/src/mscorlib/src/System/Text/EncoderReplacementFallback.cs index 15dfee8..604cddf 100644 --- a/src/mscorlib/src/System/Text/EncoderReplacementFallback.cs +++ b/src/mscorlib/src/System/Text/EncoderReplacementFallback.cs @@ -6,6 +6,7 @@ namespace System.Text { using System; using System.Runtime; + using System.Diagnostics; using System.Diagnostics.Contracts; [Serializable] @@ -23,7 +24,7 @@ namespace System.Text { // Must not be null if (replacement == null) - throw new ArgumentNullException("replacement"); + throw new ArgumentNullException(nameof(replacement)); Contract.EndContractBlock(); // Make sure it doesn't have bad surrogate pairs @@ -60,7 +61,7 @@ namespace System.Text break; } if (bFoundHigh) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex", "replacement")); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex", nameof(replacement))); strDefault = replacement; } @@ -147,7 +148,7 @@ namespace System.Text { // Double check input surrogate pair if (!Char.IsHighSurrogate(charUnknownHigh)) - throw new ArgumentOutOfRangeException("charUnknownHigh", + throw new ArgumentOutOfRangeException(nameof(charUnknownHigh), Environment.GetResourceString("ArgumentOutOfRange_Range", 0xD800, 0xDBFF)); @@ -189,7 +190,7 @@ namespace System.Text } // Now make sure its in the expected range - Contract.Assert(fallbackIndex < strDefault.Length && fallbackIndex >= 0, + Debug.Assert(fallbackIndex < strDefault.Length && fallbackIndex >= 0, "Index exceeds buffer range"); return strDefault[fallbackIndex]; @@ -220,7 +221,6 @@ namespace System.Text } // Clear the buffer - [System.Security.SecuritySafeCritical] // auto-generated public override unsafe void Reset() { fallbackCount = -1; diff --git a/src/mscorlib/src/System/Text/Encoding.cs b/src/mscorlib/src/System/Text/Encoding.cs index 8533016..658bdbb 100644 --- a/src/mscorlib/src/System/Text/Encoding.cs +++ b/src/mscorlib/src/System/Text/Encoding.cs @@ -15,6 +15,7 @@ namespace System.Text using System.Security.Permissions; using System.Threading; using System.Text; + using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; using Win32Native = Microsoft.Win32.Win32Native; @@ -189,7 +190,7 @@ namespace System.Text // Validate code page if (codePage < 0) { - throw new ArgumentOutOfRangeException("codePage"); + throw new ArgumentOutOfRangeException(nameof(codePage)); } Contract.EndContractBlock(); @@ -208,7 +209,7 @@ namespace System.Text // Validate code page if (codePage < 0) { - throw new ArgumentOutOfRangeException("codePage"); + throw new ArgumentOutOfRangeException(nameof(codePage)); } Contract.EndContractBlock(); @@ -275,7 +276,7 @@ namespace System.Text internal void DeserializeEncoding(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // All versions have a code page @@ -314,7 +315,7 @@ namespace System.Text internal void SerializeEncoding(SerializationInfo info, StreamingContext context) { // Any Info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // These are new V2.0 Whidbey stuff @@ -344,7 +345,7 @@ namespace System.Text public static byte[] Convert(Encoding srcEncoding, Encoding dstEncoding, byte[] bytes) { if (bytes==null) - throw new ArgumentNullException("bytes"); + throw new ArgumentNullException(nameof(bytes)); Contract.Ensures(Contract.Result() != null); return Convert(srcEncoding, dstEncoding, bytes, 0, bytes.Length); @@ -359,11 +360,11 @@ namespace System.Text public static byte[] Convert(Encoding srcEncoding, Encoding dstEncoding, byte[] bytes, int index, int count) { if (srcEncoding == null || dstEncoding == null) { - throw new ArgumentNullException((srcEncoding == null ? "srcEncoding" : "dstEncoding"), + throw new ArgumentNullException((srcEncoding == null ? nameof(srcEncoding) : nameof(dstEncoding)), Environment.GetResourceString("ArgumentNull_Array")); } if (bytes == null) { - throw new ArgumentNullException("bytes", + throw new ArgumentNullException(nameof(bytes), Environment.GetResourceString("ArgumentNull_Array")); } Contract.Ensures(Contract.Result() != null); @@ -389,9 +390,6 @@ namespace System.Text private static volatile Hashtable encodings; #endif -#if !FEATURE_CORECLR - [System.Security.SecurityCritical] -#endif public static void RegisterProvider(EncodingProvider provider) { // Parameters validated inside EncodingProvider @@ -399,9 +397,6 @@ namespace System.Text } [Pure] -#if !FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // auto-generated -#endif public static Encoding GetEncoding(int codepage) { Encoding result = EncodingProvider.GetEncodingFromProvider(codepage); @@ -416,7 +411,7 @@ namespace System.Text // if (codepage < 0 || codepage > 65535) { throw new ArgumentOutOfRangeException( - "codepage", Environment.GetResourceString("ArgumentOutOfRange_Range", + nameof(codepage), Environment.GetResourceString("ArgumentOutOfRange_Range", 0, 65535)); } @@ -443,7 +438,7 @@ namespace System.Text case CodePageNoThread: // 3 CP_THREAD_ACP case CodePageNoSymbol: // 42 CP_SYMBOL throw new ArgumentException(Environment.GetResourceString( - "Argument_CodepageNotSupported", codepage), "codepage"); + "Argument_CodepageNotSupported", codepage), nameof(codepage)); } #if FEATURE_CODEPAGES_FILE @@ -478,7 +473,7 @@ namespace System.Text result = GetEncodingCodePage(codepage) ?? GetEncodingRare(codepage); } - Contract.Assert(result != null, "result != null"); + Debug.Assert(result != null, "result != null"); encodings.Add(key, result); } @@ -516,10 +511,9 @@ namespace System.Text return fallbackEncoding; } #if FEATURE_CODEPAGES_FILE - [System.Security.SecurityCritical] // auto-generated private static Encoding GetEncodingRare(int codepage) { - Contract.Assert(codepage != 0 && codepage != 1200 && codepage != 1201 && codepage != 65001, + Debug.Assert(codepage != 0 && codepage != 1200 && codepage != 1201 && codepage != 65001, "[Encoding.GetEncodingRare]This code page (" + codepage + ") isn't supported by GetEncodingRare!"); Encoding result; switch (codepage) @@ -585,7 +579,6 @@ namespace System.Text return result; } - [System.Security.SecurityCritical] // auto-generated private static Encoding GetEncodingCodePage(int CodePage) { // Single Byte or Double Byte Code Page? (0 if not found) @@ -795,7 +788,7 @@ namespace System.Text throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); Contract.EndContractBlock(); encoderFallback = value; @@ -817,7 +810,7 @@ namespace System.Text throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); if (value == null) - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); Contract.EndContractBlock(); decoderFallback = value; @@ -865,7 +858,7 @@ namespace System.Text { if (chars == null) { - throw new ArgumentNullException("chars", + throw new ArgumentNullException(nameof(chars), Environment.GetResourceString("ArgumentNull_Array")); } Contract.EndContractBlock(); @@ -876,8 +869,8 @@ namespace System.Text [Pure] public virtual int GetByteCount(String s) { - if (s==null) - throw new ArgumentNullException("s"); + if (s == null) + throw new ArgumentNullException(nameof(s)); Contract.EndContractBlock(); char[] chars = s.ToCharArray(); @@ -891,23 +884,50 @@ namespace System.Text [Pure] public abstract int GetByteCount(char[] chars, int index, int count); + // Returns the number of bytes required to encode a string range. + // + [Pure] + public int GetByteCount(string s, int index, int count) + { + if (s == null) + throw new ArgumentNullException(nameof(s), + Environment.GetResourceString("ArgumentNull_String")); + if (index < 0) + throw new ArgumentOutOfRangeException(nameof(index), + Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + if (count < 0) + throw new ArgumentOutOfRangeException(nameof(count), + Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + if (index > s.Length - count) + throw new ArgumentOutOfRangeException(nameof(index), + Environment.GetResourceString("ArgumentOutOfRange_IndexCount")); + Contract.EndContractBlock(); + + unsafe + { + fixed (char* pChar = s) + { + return GetByteCount(pChar + index, count); + } + } + } + // We expect this to be the workhorse for NLS encodings // unfortunately for existing overrides, it has to call the [] version, // which is really slow, so this method should be avoided if you're calling // a 3rd party encoding. [Pure] - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public virtual unsafe int GetByteCount(char* chars, int count) { // Validate input parameters if (chars == null) - throw new ArgumentNullException("chars", + throw new ArgumentNullException(nameof(chars), Environment.GetResourceString("ArgumentNull_Array")); if (count < 0) - throw new ArgumentOutOfRangeException("count", + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -922,7 +942,6 @@ namespace System.Text // For NLS Encodings, workhorse takes an encoder (may be null) // Always validate parameters before calling internal version, which will only assert. - [System.Security.SecurityCritical] // auto-generated internal virtual unsafe int GetByteCount(char* chars, int count, EncoderNLS encoder) { Contract.Requires(chars != null); @@ -939,7 +958,7 @@ namespace System.Text { if (chars == null) { - throw new ArgumentNullException("chars", + throw new ArgumentNullException(nameof(chars), Environment.GetResourceString("ArgumentNull_Array")); } Contract.EndContractBlock(); @@ -976,29 +995,67 @@ namespace System.Text public virtual byte[] GetBytes(String s) { if (s == null) - throw new ArgumentNullException("s", + throw new ArgumentNullException(nameof(s), Environment.GetResourceString("ArgumentNull_String")); Contract.EndContractBlock(); int byteCount = GetByteCount(s); byte[] bytes = new byte[byteCount]; int bytesReceived = GetBytes(s, 0, s.Length, bytes, 0); - Contract.Assert(byteCount == bytesReceived); + Debug.Assert(byteCount == bytesReceived); return bytes; } + // Returns a byte array containing the encoded representation of the given + // string range. + // + [Pure] + public byte[] GetBytes(string s, int index, int count) + { + if (s == null) + throw new ArgumentNullException(nameof(s), + Environment.GetResourceString("ArgumentNull_String")); + if (index < 0) + throw new ArgumentOutOfRangeException(nameof(index), + Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + if (count < 0) + throw new ArgumentOutOfRangeException(nameof(count), + Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + if (index > s.Length - count) + throw new ArgumentOutOfRangeException(nameof(index), + Environment.GetResourceString("ArgumentOutOfRange_IndexCount")); + Contract.EndContractBlock(); + + unsafe + { + fixed (char* pChar = s) + { + int byteCount = GetByteCount(pChar + index, count); + if (byteCount == 0) + return Array.Empty(); + + byte[] bytes = new byte[byteCount]; + fixed (byte* pBytes = &bytes[0]) + { + int bytesReceived = GetBytes(pChar + index, count, pBytes, byteCount); + Debug.Assert(byteCount == bytesReceived); + } + return bytes; + } + } + } + public virtual int GetBytes(String s, int charIndex, int charCount, byte[] bytes, int byteIndex) { - if (s==null) - throw new ArgumentNullException("s"); + if (s == null) + throw new ArgumentNullException(nameof(s)); Contract.EndContractBlock(); return GetBytes(s.ToCharArray(), charIndex, charCount, bytes, byteIndex); } // This is our internal workhorse // Always validate parameters before calling internal version, which will only assert. - [System.Security.SecurityCritical] // auto-generated internal virtual unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS encoder) { @@ -1022,7 +1079,6 @@ namespace System.Text // could easily overflow our output buffer. Therefore we do an extra test // when we copy the buffer so that we don't overflow byteCount either. - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public virtual unsafe int GetBytes(char* chars, int charCount, @@ -1030,11 +1086,11 @@ namespace System.Text { // Validate input parameters if (bytes == null || chars == null) - throw new ArgumentNullException(bytes == null ? "bytes" : "chars", + throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), Environment.GetResourceString("ArgumentNull_Array")); if (charCount < 0 || byteCount < 0) - throw new ArgumentOutOfRangeException((charCount<0 ? "charCount" : "byteCount"), + throw new ArgumentOutOfRangeException((charCount<0 ? nameof(charCount) : nameof(byteCount)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -1051,7 +1107,7 @@ namespace System.Text // Do the work int result = GetBytes(arrChar, 0, charCount, arrByte, 0); - Contract.Assert(result <= byteCount, "[Encoding.GetBytes]Returned more bytes than we have space for"); + Debug.Assert(result <= byteCount, "[Encoding.GetBytes]Returned more bytes than we have space for"); // Copy the byte array // WARNING: We MUST make sure that we don't copy too many bytes. We can't @@ -1076,7 +1132,7 @@ namespace System.Text { if (bytes == null) { - throw new ArgumentNullException("bytes", + throw new ArgumentNullException(nameof(bytes), Environment.GetResourceString("ArgumentNull_Array")); } Contract.EndContractBlock(); @@ -1092,18 +1148,17 @@ namespace System.Text // We expect this to be the workhorse for NLS Encodings, but for existing // ones we need a working (if slow) default implimentation) [Pure] - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public virtual unsafe int GetCharCount(byte* bytes, int count) { // Validate input parameters if (bytes == null) - throw new ArgumentNullException("bytes", + throw new ArgumentNullException(nameof(bytes), Environment.GetResourceString("ArgumentNull_Array")); if (count < 0) - throw new ArgumentOutOfRangeException("count", + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -1118,7 +1173,6 @@ namespace System.Text // This is our internal workhorse // Always validate parameters before calling internal version, which will only assert. - [System.Security.SecurityCritical] // auto-generated internal virtual unsafe int GetCharCount(byte* bytes, int count, DecoderNLS decoder) { return GetCharCount(bytes, count); @@ -1132,7 +1186,7 @@ namespace System.Text { if (bytes == null) { - throw new ArgumentNullException("bytes", + throw new ArgumentNullException(nameof(bytes), Environment.GetResourceString("ArgumentNull_Array")); } Contract.EndContractBlock(); @@ -1181,7 +1235,6 @@ namespace System.Text // could easily overflow our output buffer. Therefore we do an extra test // when we copy the buffer so that we don't overflow charCount either. - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public virtual unsafe int GetChars(byte* bytes, int byteCount, @@ -1189,11 +1242,11 @@ namespace System.Text { // Validate input parameters if (chars == null || bytes == null) - throw new ArgumentNullException(chars == null ? "chars" : "bytes", + throw new ArgumentNullException(chars == null ? nameof(chars) : nameof(bytes), Environment.GetResourceString("ArgumentNull_Array")); if (byteCount < 0 || charCount < 0) - throw new ArgumentOutOfRangeException((byteCount<0 ? "byteCount" : "charCount"), + throw new ArgumentOutOfRangeException((byteCount<0 ? nameof(byteCount) : nameof(charCount)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -1210,7 +1263,7 @@ namespace System.Text // Do the work int result = GetChars(arrByte, 0, byteCount, arrChar, 0); - Contract.Assert(result <= charCount, "[Encoding.GetChars]Returned more chars than we have space for"); + Debug.Assert(result <= charCount, "[Encoding.GetChars]Returned more chars than we have space for"); // Copy the char array // WARNING: We MUST make sure that we don't copy too many chars. We can't @@ -1230,7 +1283,6 @@ namespace System.Text // This is our internal workhorse // Always validate parameters before calling internal version, which will only assert. - [System.Security.SecurityCritical] // auto-generated internal virtual unsafe int GetChars(byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS decoder) { @@ -1238,16 +1290,15 @@ namespace System.Text } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public unsafe string GetString(byte* bytes, int byteCount) { if (bytes == null) - throw new ArgumentNullException("bytes", Environment.GetResourceString("ArgumentNull_Array")); + throw new ArgumentNullException(nameof(bytes), Environment.GetResourceString("ArgumentNull_Array")); if (byteCount < 0) - throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); return String.CreateStringFromEncoding(bytes, byteCount, this); @@ -1306,7 +1357,6 @@ namespace System.Text return new DefaultDecoder(this); } - [System.Security.SecuritySafeCritical] private static Encoding CreateDefaultEncoding() { // defaultEncoding should be null if we get here, but we can't @@ -1391,7 +1441,7 @@ namespace System.Text public virtual String GetString(byte[] bytes) { if (bytes == null) - throw new ArgumentNullException("bytes", + throw new ArgumentNullException(nameof(bytes), Environment.GetResourceString("ArgumentNull_Array")); Contract.EndContractBlock(); @@ -1482,7 +1532,6 @@ namespace System.Text EncodingName, EncoderFallback.GetType()), "bytes"); } - [System.Security.SecurityCritical] // auto-generated internal void ThrowBytesOverflow(EncoderNLS encoder, bool nothingEncoded) { if (encoder == null || encoder.m_throwOnOverflow || nothingEncoded) @@ -1507,7 +1556,6 @@ namespace System.Text EncodingName, DecoderFallback.GetType()), "chars"); } - [System.Security.SecurityCritical] // auto-generated internal void ThrowCharsOverflow(DecoderNLS decoder, bool nothingDecoded) { if (decoder == null || decoder.m_throwOnOverflow || nothingDecoded) @@ -1541,7 +1589,7 @@ namespace System.Text // Constructor called by serialization, have to handle deserializing from Everett internal DefaultEncoder(SerializationInfo info, StreamingContext context) { - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // All we have is our encoding @@ -1558,7 +1606,6 @@ namespace System.Text } // Just get it from GetEncoding - [System.Security.SecurityCritical] // auto-generated public Object GetRealObject(StreamingContext context) { // upon deserialization since the DefaultEncoder implement IObjectReference the @@ -1584,11 +1631,10 @@ namespace System.Text } // ISerializable implementation, get data for this object - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // All we have is our encoding @@ -1608,7 +1654,6 @@ namespace System.Text return m_encoding.GetByteCount(chars, index, count); } - [System.Security.SecurityCritical] // auto-generated [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. public unsafe override int GetByteCount(char* chars, int count, bool flush) { @@ -1641,7 +1686,6 @@ namespace System.Text return m_encoding.GetBytes(chars, charIndex, charCount, bytes, byteIndex); } - [System.Security.SecurityCritical] // auto-generated [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. public unsafe override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, bool flush) @@ -1667,7 +1711,7 @@ namespace System.Text internal DefaultDecoder(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // All we have is our encoding @@ -1684,7 +1728,6 @@ namespace System.Text } // Just get it from GetEncoding - [System.Security.SecurityCritical] // auto-generated public Object GetRealObject(StreamingContext context) { // upon deserialization since the DefaultEncoder implement IObjectReference the @@ -1705,11 +1748,10 @@ namespace System.Text } // ISerializable implementation, get data for this object - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // All we have is our encoding @@ -1733,7 +1775,6 @@ namespace System.Text return m_encoding.GetCharCount(bytes, index, count); } - [System.Security.SecurityCritical] // auto-generated [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. public unsafe override int GetCharCount(byte* bytes, int count, bool flush) { @@ -1770,7 +1811,6 @@ namespace System.Text return m_encoding.GetChars(bytes, byteIndex, byteCount, chars, charIndex); } - [System.Security.SecurityCritical] // auto-generated [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount, bool flush) @@ -1782,24 +1822,17 @@ namespace System.Text internal class EncodingCharBuffer { - [SecurityCritical] unsafe char* chars; - [SecurityCritical] unsafe char* charStart; - [SecurityCritical] unsafe char* charEnd; int charCountResult = 0; Encoding enc; DecoderNLS decoder; - [SecurityCritical] unsafe byte* byteStart; - [SecurityCritical] unsafe byte* byteEnd; - [SecurityCritical] unsafe byte* bytes; DecoderFallbackBuffer fallbackBuffer; - [System.Security.SecurityCritical] // auto-generated internal unsafe EncodingCharBuffer(Encoding enc, DecoderNLS decoder, char* charStart, int charCount, byte* byteStart, int byteCount) { @@ -1821,12 +1854,11 @@ namespace System.Text // If we're getting chars or getting char count we don't expect to have // to remember fallbacks between calls (so it should be empty) - Contract.Assert(fallbackBuffer.Remaining == 0, + Debug.Assert(fallbackBuffer.Remaining == 0, "[Encoding.EncodingCharBuffer.EncodingCharBuffer]Expected empty fallback buffer for getchars/charcount"); fallbackBuffer.InternalInitialize(bytes, charEnd); } - [System.Security.SecurityCritical] // auto-generated internal unsafe bool AddChar(char ch, int numBytes) { if (chars != null) @@ -1845,14 +1877,12 @@ namespace System.Text return true; } - [System.Security.SecurityCritical] // auto-generated internal unsafe bool AddChar(char ch) { return AddChar(ch,1); } - [System.Security.SecurityCritical] // auto-generated internal unsafe bool AddChar(char ch1, char ch2, int numBytes) { // Need room for 2 chars @@ -1866,7 +1896,6 @@ namespace System.Text return AddChar(ch1, numBytes) && AddChar(ch2, numBytes); } - [System.Security.SecurityCritical] // auto-generated internal unsafe void AdjustBytes(int count) { bytes += count; @@ -1874,7 +1903,6 @@ namespace System.Text internal unsafe bool MoreData { - [System.Security.SecurityCritical] // auto-generated get { return bytes < byteEnd; @@ -1882,7 +1910,6 @@ namespace System.Text } // Do we have count more bytes? - [System.Security.SecurityCritical] // auto-generated internal unsafe bool EvenMoreData(int count) { return (bytes <= byteEnd - count); @@ -1890,10 +1917,9 @@ namespace System.Text // GetNextByte shouldn't be called unless the caller's already checked more data or even more data, // but we'll double check just to make sure. - [System.Security.SecurityCritical] // auto-generated internal unsafe byte GetNextByte() { - Contract.Assert(bytes < byteEnd, "[EncodingCharBuffer.GetNextByte]Expected more date"); + Debug.Assert(bytes < byteEnd, "[EncodingCharBuffer.GetNextByte]Expected more date"); if (bytes >= byteEnd) return 0; return *(bytes++); @@ -1901,14 +1927,12 @@ namespace System.Text internal unsafe int BytesUsed { - [System.Security.SecurityCritical] // auto-generated get { return (int)(bytes - byteStart); } } - [System.Security.SecurityCritical] // auto-generated internal unsafe bool Fallback(byte fallbackByte) { // Build our buffer @@ -1918,7 +1942,6 @@ namespace System.Text return Fallback(byteBuffer); } - [System.Security.SecurityCritical] // auto-generated internal unsafe bool Fallback(byte byte1, byte byte2) { // Build our buffer @@ -1928,7 +1951,6 @@ namespace System.Text return Fallback(byteBuffer); } - [System.Security.SecurityCritical] // auto-generated internal unsafe bool Fallback(byte byte1, byte byte2, byte byte3, byte byte4) { // Build our buffer @@ -1938,7 +1960,6 @@ namespace System.Text return Fallback(byteBuffer); } - [System.Security.SecurityCritical] // auto-generated internal unsafe bool Fallback(byte[] byteBuffer) { // Do the fallback and add the data. @@ -1974,24 +1995,17 @@ namespace System.Text internal class EncodingByteBuffer { - [SecurityCritical] unsafe byte* bytes; - [SecurityCritical] unsafe byte* byteStart; - [SecurityCritical] unsafe byte* byteEnd; - [SecurityCritical] unsafe char* chars; - [SecurityCritical] unsafe char* charStart; - [SecurityCritical] unsafe char* charEnd; int byteCountResult = 0; Encoding enc; EncoderNLS encoder; internal EncoderFallbackBuffer fallbackBuffer; - [System.Security.SecurityCritical] // auto-generated internal unsafe EncodingByteBuffer(Encoding inEncoding, EncoderNLS inEncoder, byte* inByteStart, int inByteCount, char* inCharStart, int inCharCount) { @@ -2020,10 +2034,9 @@ namespace System.Text fallbackBuffer.InternalInitialize(chars, charEnd, encoder, bytes != null); } - [System.Security.SecurityCritical] // auto-generated internal unsafe bool AddByte(byte b, int moreBytesExpected) { - Contract.Assert(moreBytesExpected >= 0, "[EncodingByteBuffer.AddByte]expected non-negative moreBytesExpected"); + Debug.Assert(moreBytesExpected >= 0, "[EncodingByteBuffer.AddByte]expected non-negative moreBytesExpected"); if (bytes != null) { if (bytes >= byteEnd - moreBytesExpected) @@ -2039,31 +2052,26 @@ namespace System.Text return true; } - [System.Security.SecurityCritical] // auto-generated internal unsafe bool AddByte(byte b1) { return (AddByte(b1, 0)); } - [System.Security.SecurityCritical] // auto-generated internal unsafe bool AddByte(byte b1, byte b2) { return (AddByte(b1, b2, 0)); } - [System.Security.SecurityCritical] // auto-generated internal unsafe bool AddByte(byte b1, byte b2, int moreBytesExpected) { return (AddByte(b1, 1 + moreBytesExpected) && AddByte(b2, moreBytesExpected)); } - [System.Security.SecurityCritical] // auto-generated internal unsafe bool AddByte(byte b1, byte b2, byte b3) { return AddByte(b1, b2, b3, (int)0); } - [System.Security.SecurityCritical] // auto-generated internal unsafe bool AddByte(byte b1, byte b2, byte b3, int moreBytesExpected) { return (AddByte(b1, 2 + moreBytesExpected) && @@ -2071,7 +2079,6 @@ namespace System.Text AddByte(b3, moreBytesExpected)); } - [System.Security.SecurityCritical] // auto-generated internal unsafe bool AddByte(byte b1, byte b2, byte b3, byte b4) { return (AddByte(b1, 3) && @@ -2080,14 +2087,13 @@ namespace System.Text AddByte(b4, 0)); } - [System.Security.SecurityCritical] // auto-generated internal unsafe void MovePrevious(bool bThrow) { if (fallbackBuffer.bFallingBack) fallbackBuffer.MovePrevious(); // don't use last fallback else { - Contract.Assert(chars > charStart || + Debug.Assert(chars > charStart || ((bThrow == true) && (bytes == byteStart)), "[EncodingByteBuffer.MovePrevious]expected previous data or throw"); if (chars > charStart) @@ -2098,7 +2104,6 @@ namespace System.Text enc.ThrowBytesOverflow(encoder, bytes == byteStart); // Throw? (and reset fallback if not converting) } - [System.Security.SecurityCritical] // auto-generated internal unsafe bool Fallback(char charFallback) { // Do the fallback @@ -2107,7 +2112,6 @@ namespace System.Text internal unsafe bool MoreData { - [System.Security.SecurityCritical] // auto-generated get { // See if fallbackBuffer is not empty or if there's data left in chars buffer. @@ -2115,7 +2119,6 @@ namespace System.Text } } - [System.Security.SecurityCritical] // auto-generated internal unsafe char GetNextChar() { // See if there's something in our fallback buffer @@ -2133,7 +2136,6 @@ namespace System.Text internal unsafe int CharsUsed { - [System.Security.SecurityCritical] // auto-generated get { return (int)(chars - charStart); diff --git a/src/mscorlib/src/System/Text/EncodingForwarder.cs b/src/mscorlib/src/System/Text/EncodingForwarder.cs index d4bcf80..9a8dd26 100644 --- a/src/mscorlib/src/System/Text/EncodingForwarder.cs +++ b/src/mscorlib/src/System/Text/EncodingForwarder.cs @@ -2,6 +2,7 @@ // 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.Diagnostics; using System.Diagnostics.Contracts; using System.Security; @@ -31,23 +32,22 @@ namespace System.Text // the parameter, it will call the same method again, which will eventually // lead to a StackOverflowException. - [SecuritySafeCritical] public unsafe static int GetByteCount(Encoding encoding, char[] chars, int index, int count) { // Validate parameters - Contract.Assert(encoding != null); // this parameter should only be affected internally, so just do a debug check here + Debug.Assert(encoding != null); // this parameter should only be affected internally, so just do a debug check here if (chars == null) { - throw new ArgumentNullException("chars", Environment.GetResourceString("ArgumentNull_Array")); + throw new ArgumentNullException(nameof(chars), Environment.GetResourceString("ArgumentNull_Array")); } if (index < 0 || count < 0) { - throw new ArgumentOutOfRangeException(index < 0 ? "index" : "count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(index < 0 ? nameof(index) : nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (chars.Length - index < count) { - throw new ArgumentOutOfRangeException("chars", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); + throw new ArgumentOutOfRangeException(nameof(chars), Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); } Contract.EndContractBlock(); @@ -60,13 +60,12 @@ namespace System.Text return encoding.GetByteCount(pChars + index, count, encoder: null); } - [SecuritySafeCritical] public unsafe static int GetByteCount(Encoding encoding, string s) { - Contract.Assert(encoding != null); + Debug.Assert(encoding != null); if (s == null) { - string paramName = encoding is ASCIIEncoding ? "chars" : "s"; // ASCIIEncoding calls the string chars + string paramName = encoding is ASCIIEncoding ? "chars" : nameof(s); // ASCIIEncoding calls the string chars // UTF8Encoding does this as well, but it originally threw an ArgumentNull for "s" so don't check for that throw new ArgumentNullException(paramName); } @@ -84,17 +83,16 @@ namespace System.Text return encoding.GetByteCount(pChars, s.Length, encoder: null); } - [SecurityCritical] public unsafe static int GetByteCount(Encoding encoding, char* chars, int count) { - Contract.Assert(encoding != null); + Debug.Assert(encoding != null); if (chars == null) { - throw new ArgumentNullException("chars", Environment.GetResourceString("ArgumentNull_Array")); + throw new ArgumentNullException(nameof(chars), Environment.GetResourceString("ArgumentNull_Array")); } if (count < 0) { - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.EndContractBlock(); @@ -102,28 +100,27 @@ namespace System.Text return encoding.GetByteCount(chars, count, encoder: null); } - [SecuritySafeCritical] public unsafe static int GetBytes(Encoding encoding, string s, int charIndex, int charCount, byte[] bytes, int byteIndex) { - Contract.Assert(encoding != null); + Debug.Assert(encoding != null); if (s == null || bytes == null) { - string stringName = encoding is ASCIIEncoding ? "chars" : "s"; // ASCIIEncoding calls the first parameter chars - throw new ArgumentNullException(s == null ? stringName : "bytes", Environment.GetResourceString("ArgumentNull_Array")); + string stringName = encoding is ASCIIEncoding ? "chars" : nameof(s); // ASCIIEncoding calls the first parameter chars + throw new ArgumentNullException(s == null ? stringName : nameof(bytes), Environment.GetResourceString("ArgumentNull_Array")); } if (charIndex < 0 || charCount < 0) { - throw new ArgumentOutOfRangeException(charIndex < 0 ? "charIndex" : "charCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(charIndex < 0 ? nameof(charIndex) : nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (s.Length - charIndex < charCount) { - string stringName = encoding is ASCIIEncoding ? "chars" : "s"; // ASCIIEncoding calls the first parameter chars + string stringName = encoding is ASCIIEncoding ? "chars" : nameof(s); // ASCIIEncoding calls the first parameter chars // Duplicate the above check since we don't want the overhead of a type check on the general path throw new ArgumentOutOfRangeException(stringName, Environment.GetResourceString("ArgumentOutOfRange_IndexCount")); } if (byteIndex < 0 || byteIndex > bytes.Length) { - throw new ArgumentOutOfRangeException("byteIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(byteIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); } Contract.EndContractBlock(); @@ -139,25 +136,24 @@ namespace System.Text } } - [SecuritySafeCritical] public unsafe static int GetBytes(Encoding encoding, char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex) { - Contract.Assert(encoding != null); + Debug.Assert(encoding != null); if (chars == null || bytes == null) { - throw new ArgumentNullException(chars == null ? "chars" : "bytes", Environment.GetResourceString("ArgumentNull_Array")); + throw new ArgumentNullException(chars == null ? nameof(chars) : nameof(bytes), Environment.GetResourceString("ArgumentNull_Array")); } if (charIndex < 0 || charCount < 0) { - throw new ArgumentOutOfRangeException(charIndex < 0 ? "charIndex" : "charCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(charIndex < 0 ? nameof(charIndex) : nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (chars.Length - charIndex < charCount) { - throw new ArgumentOutOfRangeException("chars", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); + throw new ArgumentOutOfRangeException(nameof(chars), Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); } if (byteIndex < 0 || byteIndex > bytes.Length) { - throw new ArgumentOutOfRangeException("byteIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(byteIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); } Contract.EndContractBlock(); @@ -180,38 +176,36 @@ namespace System.Text } } - [SecurityCritical] public unsafe static int GetBytes(Encoding encoding, char* chars, int charCount, byte* bytes, int byteCount) { - Contract.Assert(encoding != null); + Debug.Assert(encoding != null); if (bytes == null || chars == null) { - throw new ArgumentNullException(bytes == null ? "bytes" : "chars", Environment.GetResourceString("ArgumentNull_Array")); + throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), Environment.GetResourceString("ArgumentNull_Array")); } if (charCount < 0 || byteCount < 0) { - throw new ArgumentOutOfRangeException(charCount < 0 ? "charCount" : "byteCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(charCount < 0 ? nameof(charCount) : nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.EndContractBlock(); return encoding.GetBytes(chars, charCount, bytes, byteCount, encoder: null); } - [SecuritySafeCritical] public unsafe static int GetCharCount(Encoding encoding, byte[] bytes, int index, int count) { - Contract.Assert(encoding != null); + Debug.Assert(encoding != null); if (bytes == null) { - throw new ArgumentNullException("bytes", Environment.GetResourceString("ArgumentNull_Array")); + throw new ArgumentNullException(nameof(bytes), Environment.GetResourceString("ArgumentNull_Array")); } if (index < 0 || count < 0) { - throw new ArgumentOutOfRangeException(index < 0 ? "index" : "count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(index < 0 ? nameof(index) : nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (bytes.Length - index < count) { - throw new ArgumentOutOfRangeException("bytes", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); + throw new ArgumentOutOfRangeException(nameof(bytes), Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); } Contract.EndContractBlock(); @@ -224,42 +218,40 @@ namespace System.Text return encoding.GetCharCount(pBytes + index, count, decoder: null); } - [SecurityCritical] public unsafe static int GetCharCount(Encoding encoding, byte* bytes, int count) { - Contract.Assert(encoding != null); + Debug.Assert(encoding != null); if (bytes == null) { - throw new ArgumentNullException("bytes", Environment.GetResourceString("ArgumentNull_Array")); + throw new ArgumentNullException(nameof(bytes), Environment.GetResourceString("ArgumentNull_Array")); } if (count < 0) { - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.EndContractBlock(); return encoding.GetCharCount(bytes, count, decoder: null); } - [SecuritySafeCritical] public unsafe static int GetChars(Encoding encoding, byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) { - Contract.Assert(encoding != null); + Debug.Assert(encoding != null); if (bytes == null || chars == null) { - throw new ArgumentNullException(bytes == null ? "bytes" : "chars", Environment.GetResourceString("ArgumentNull_Array")); + throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), Environment.GetResourceString("ArgumentNull_Array")); } if (byteIndex < 0 || byteCount < 0) { - throw new ArgumentOutOfRangeException(byteIndex < 0 ? "byteIndex" : "byteCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (bytes.Length - byteIndex < byteCount) { - throw new ArgumentOutOfRangeException("bytes", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); + throw new ArgumentOutOfRangeException(nameof(bytes), Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); } if (charIndex < 0 || charIndex > chars.Length) { - throw new ArgumentOutOfRangeException("charIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(charIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); } Contract.EndContractBlock(); @@ -280,42 +272,40 @@ namespace System.Text } } - [SecurityCritical] public unsafe static int GetChars(Encoding encoding, byte* bytes, int byteCount, char* chars, int charCount) { - Contract.Assert(encoding != null); + Debug.Assert(encoding != null); if (bytes == null || chars == null) { - throw new ArgumentNullException(bytes == null ? "bytes" : "chars", Environment.GetResourceString("ArgumentNull_Array")); + throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), Environment.GetResourceString("ArgumentNull_Array")); } if (charCount < 0 || byteCount < 0) { - throw new ArgumentOutOfRangeException(charCount < 0 ? "charCount" : "byteCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(charCount < 0 ? nameof(charCount) : nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.EndContractBlock(); return encoding.GetChars(bytes, byteCount, chars, charCount, decoder: null); } - [SecuritySafeCritical] public unsafe static string GetString(Encoding encoding, byte[] bytes, int index, int count) { - Contract.Assert(encoding != null); + Debug.Assert(encoding != null); if (bytes == null) { - throw new ArgumentNullException("bytes", Environment.GetResourceString("ArgumentNull_Array")); + throw new ArgumentNullException(nameof(bytes), Environment.GetResourceString("ArgumentNull_Array")); } if (index < 0 || count < 0) { // ASCIIEncoding has different names for its parameters here (byteIndex, byteCount) bool ascii = encoding is ASCIIEncoding; - string indexName = ascii ? "byteIndex" : "index"; - string countName = ascii ? "byteCount" : "count"; + string indexName = ascii ? "byteIndex" : nameof(index); + string countName = ascii ? "byteCount" : nameof(count); throw new ArgumentOutOfRangeException(index < 0 ? indexName : countName, Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (bytes.Length - index < count) { - throw new ArgumentOutOfRangeException("bytes", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); + throw new ArgumentOutOfRangeException(nameof(bytes), Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer")); } Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/Text/EncodingNLS.cs b/src/mscorlib/src/System/Text/EncodingNLS.cs index d670d6d..fbddf37 100644 --- a/src/mscorlib/src/System/Text/EncodingNLS.cs +++ b/src/mscorlib/src/System/Text/EncodingNLS.cs @@ -50,7 +50,6 @@ namespace System.Text return EncodingForwarder.GetByteCount(this, s); } - [System.Security.SecurityCritical] // auto-generated public override unsafe int GetByteCount(char* chars, int count) { return EncodingForwarder.GetByteCount(this, chars, count); @@ -77,7 +76,6 @@ namespace System.Text return EncodingForwarder.GetBytes(this, chars, charIndex, charCount, bytes, byteIndex); } - [System.Security.SecurityCritical] // auto-generated public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount) { return EncodingForwarder.GetBytes(this, chars, charCount, bytes, byteCount); @@ -91,7 +89,6 @@ namespace System.Text return EncodingForwarder.GetCharCount(this, bytes, index, count); } - [System.Security.SecurityCritical] // auto-generated public override unsafe int GetCharCount(byte* bytes, int count) { return EncodingForwarder.GetCharCount(this, bytes, count); @@ -103,7 +100,6 @@ namespace System.Text return EncodingForwarder.GetChars(this, bytes, byteIndex, byteCount, chars, charIndex); } - [System.Security.SecurityCritical] // auto-generated public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount) { return EncodingForwarder.GetChars(this, bytes, byteCount, chars, charCount); diff --git a/src/mscorlib/src/System/Text/EncodingProvider.cs b/src/mscorlib/src/System/Text/EncodingProvider.cs index b1dea2c..a7f745a 100644 --- a/src/mscorlib/src/System/Text/EncodingProvider.cs +++ b/src/mscorlib/src/System/Text/EncodingProvider.cs @@ -45,7 +45,7 @@ namespace System.Text internal static void AddProvider(EncodingProvider provider) { if (provider == null) - throw new ArgumentNullException("provider"); + throw new ArgumentNullException(nameof(provider)); lock (s_InternalSyncObject) { diff --git a/src/mscorlib/src/System/Text/GB18030Encoding.cs b/src/mscorlib/src/System/Text/GB18030Encoding.cs index 98746fc..8ed52a6 100644 --- a/src/mscorlib/src/System/Text/GB18030Encoding.cs +++ b/src/mscorlib/src/System/Text/GB18030Encoding.cs @@ -85,6 +85,7 @@ namespace System.Text { using System; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Text; using System.Runtime.InteropServices; @@ -107,10 +108,8 @@ namespace System.Text // This is the table of 4 byte conversions. private const int GBLast4ByteCode = 0x99FB; [NonSerialized] - [SecurityCritical] unsafe internal char* map4BytesToUnicode = null; // new char[GBLast4ByteCode + 1]; // Need to map all 4 byte sequences to Unicode [NonSerialized] - [SecurityCritical] unsafe internal byte* mapUnicodeTo4BytesFlags = null; // new byte[0x10000 / 8]; // Need 1 bit for each code point to say if its 4 byte or not private const int GB18030 = 54936; @@ -120,37 +119,33 @@ namespace System.Text private const int GBLastSurrogateOffset = 0x12E247; // GBE3329A35 // We have to load the 936 code page tables, so impersonate 936 as our base - [System.Security.SecurityCritical] // auto-generated internal GB18030Encoding() : base(GB18030, 936) { } // Constructor called by serialization. - [System.Security.SecurityCritical] // auto-generated internal GB18030Encoding(SerializationInfo info, StreamingContext context) : base(GB18030, 936) { // Set up our base, also throws if info was empty DeserializeEncoding(info, context); - Contract.Assert(info!=null, "[GB18030Encoding(Serialization...)] Expected null info to throw"); + Debug.Assert(info!=null, "[GB18030Encoding(Serialization...)] Expected null info to throw"); // Already build our code page, fallbacks & read only, so we're good to go! } // ISerializable implementation - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { // Make sure to get the base stuff too This throws if info is null SerializeEncoding(info, context); - Contract.Assert(info!=null, "[GB18030.GetObjectData] Expected null info to throw"); + Debug.Assert(info!=null, "[GB18030.GetObjectData] Expected null info to throw"); // Everett doesn't need more than the basics } // This loads our base 936 code page and then applys the changes from the tableUnicodeToGBDiffs table. // See table comments for table format. - [System.Security.SecurityCritical] // auto-generated protected override unsafe void LoadManagedCodePage() { // Use base code page loading algorithm. @@ -199,7 +194,7 @@ namespace System.Text // It was GB 18030 4 byte data, next characters are 4 byte sequences. while (data > 0) { - Contract.Assert(count4Byte <= GBLast4ByteCode, + Debug.Assert(count4Byte <= GBLast4ByteCode, "[GB18030Encoding.LoadManagedCodePage] Found too many 4 byte codes in data table."); // Set the 4 byte -> Unicode value @@ -217,11 +212,11 @@ namespace System.Text } // unicodeCount should've wrapped back to 0 - Contract.Assert(unicodeCount == 0, + Debug.Assert(unicodeCount == 0, "[GB18030Encoding.LoadManagedCodePage] Expected unicodeCount to wrap around to 0 as all chars were processed"); // We should've read in GBLast4ByteCode 4 byte sequences - Contract.Assert(count4Byte == GBLast4ByteCode + 1, + Debug.Assert(count4Byte == GBLast4ByteCode + 1, "[GB18030Encoding.LoadManagedCodePage] Expected 0x99FB to be last 4 byte offset, found 0x" + count4Byte.ToString("X4", CultureInfo.InvariantCulture)); // Need to flag ourselves saying we've built this CP. @@ -238,7 +233,6 @@ namespace System.Text // Is4Byte // Checks the 4 byte table and returns true if this is a 4 byte code. // Its a 4 byte code if the flag is set in mapUnicodeTo4BytesFlags - [System.Security.SecurityCritical] // auto-generated internal unsafe bool Is4Byte(char charTest) { // See what kind it is @@ -247,26 +241,24 @@ namespace System.Text } // GetByteCount - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS encoder) { // Just call GetBytes() with null bytes return GetBytes(chars, count, null, 0, encoder); } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS encoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already // We'll allow null bytes as a count -// Contract.Assert(bytes != null, "[GB18030Encoding.GetBytes]bytes is null"); - Contract.Assert(byteCount >= 0, "[GB18030Encoding.GetBytes]byteCount is negative"); - Contract.Assert(chars != null, "[GB18030Encoding.GetBytes]chars is null"); - Contract.Assert(charCount >= 0, "[GB18030Encoding.GetBytes]charCount is negative"); +// Debug.Assert(bytes != null, "[GB18030Encoding.GetBytes]bytes is null"); + Debug.Assert(byteCount >= 0, "[GB18030Encoding.GetBytes]byteCount is negative"); + Debug.Assert(chars != null, "[GB18030Encoding.GetBytes]chars is null"); + Debug.Assert(charCount >= 0, "[GB18030Encoding.GetBytes]charCount is negative"); // Assert because we shouldn't be able to have a null encoder. - Contract.Assert(encoderFallback != null, "[GB18030Encoding.GetBytes]Attempting to use null encoder fallback"); + Debug.Assert(encoderFallback != null, "[GB18030Encoding.GetBytes]Attempting to use null encoder fallback"); // Get any left over characters char charLeftOver = (char)0; @@ -289,7 +281,7 @@ namespace System.Text // Have to check for charLeftOver if (charLeftOver != 0) { - Contract.Assert(Char.IsHighSurrogate(charLeftOver), + Debug.Assert(Char.IsHighSurrogate(charLeftOver), "[GB18030Encoding.GetBytes] leftover character should be high surrogate, not 0x" + ((int)charLeftOver).ToString("X4", CultureInfo.InvariantCulture)); // If our next char isn't a low surrogate, then we need to do fallback. @@ -319,7 +311,7 @@ namespace System.Text offset /= 0x7e; byte byte2 = (byte)((offset % 0x0a) + 0x30); offset /= 0x0a; - Contract.Assert(offset < 0x6f, + Debug.Assert(offset < 0x6f, "[GB18030Encoding.GetBytes](1) Expected offset < 0x6f, not 0x" + offset.ToString("X2", CultureInfo.InvariantCulture)); charLeftOver = (char)0; @@ -369,7 +361,7 @@ namespace System.Text iBytes /= 0x7e; byte byte2 = (byte)((iBytes % 0x0a) + 0x30); iBytes /= 0x0a; - Contract.Assert(iBytes < 0x7e, + Debug.Assert(iBytes < 0x7e, "[GB18030Encoding.GetBytes]Expected iBytes < 0x7e, not 0x" + iBytes.ToString("X2", CultureInfo.InvariantCulture)); if (!buffer.AddByte((byte)(iBytes + 0x81), byte2, byte3, byte4)) break; @@ -436,23 +428,21 @@ namespace System.Text } // This is internal and called by something else, - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder) { // Just call GetChars() with null chars to count return GetChars(bytes, count, null, 0, baseDecoder); } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetChars(byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already // We'll allow null chars as a count - Contract.Assert(bytes != null, "[GB18030Encoding.GetChars]bytes is null"); - Contract.Assert(byteCount >= 0, "[GB18030Encoding.GetChars]byteCount is negative"); -// Contract.Assert(chars != null, "[GB18030Encoding.GetChars]chars is null"); - Contract.Assert(charCount >= 0, "[GB18030Encoding.GetChars]charCount is negative"); + Debug.Assert(bytes != null, "[GB18030Encoding.GetChars]bytes is null"); + Debug.Assert(byteCount >= 0, "[GB18030Encoding.GetChars]byteCount is negative"); +// Debug.Assert(chars != null, "[GB18030Encoding.GetChars]chars is null"); + Debug.Assert(charCount >= 0, "[GB18030Encoding.GetChars]charCount is negative"); // Fix our decoder GB18030Decoder decoder = (GB18030Decoder)baseDecoder; @@ -793,7 +783,7 @@ namespace System.Text public override int GetMaxByteCount(int charCount) { if (charCount < 0) - throw new ArgumentOutOfRangeException("charCount", + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -807,7 +797,7 @@ namespace System.Text byteCount *= 4; if (byteCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); return (int)byteCount; } @@ -815,7 +805,7 @@ namespace System.Text public override int GetMaxCharCount(int byteCount) { if (byteCount < 0) - throw new ArgumentOutOfRangeException("byteCount", + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -828,7 +818,7 @@ namespace System.Text charCount *= DecoderFallback.MaxCharCount; if (charCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow")); return (int)charCount; } @@ -852,11 +842,10 @@ namespace System.Text } // Constructor called by serialization, have to handle deserializing from Everett - [System.Security.SecurityCritical] // auto-generated internal GB18030Decoder(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); try @@ -879,11 +868,10 @@ namespace System.Text } // ISerializable implementation, get data for this object - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // Save Whidbey data diff --git a/src/mscorlib/src/System/Text/ISCIIEncoding.cs b/src/mscorlib/src/System/Text/ISCIIEncoding.cs index 89d9c99..751b821 100644 --- a/src/mscorlib/src/System/Text/ISCIIEncoding.cs +++ b/src/mscorlib/src/System/Text/ISCIIEncoding.cs @@ -9,6 +9,7 @@ namespace System.Text { using System; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Globalization; using System.Runtime.Serialization; @@ -72,13 +73,13 @@ namespace System.Text defaultCodePage = codePage - 57000; // Legal windows code pages are between Devanagari and Punjabi - Contract.Assert(defaultCodePage >= CodeDevanagari && defaultCodePage <= CodePunjabi, + Debug.Assert(defaultCodePage >= CodeDevanagari && defaultCodePage <= CodePunjabi, "[ISCIIEncoding] Code page (" + codePage + " isn't supported by ISCIIEncoding!"); // This shouldn't really be possible if (defaultCodePage < CodeDevanagari || defaultCodePage > CodePunjabi) throw new ArgumentException(Environment.GetResourceString( - "Argument_CodepageNotSupported", codePage), "codePage"); + "Argument_CodepageNotSupported", codePage), nameof(codePage)); } // Constructor called by serialization. @@ -86,17 +87,16 @@ namespace System.Text { // Actually this can't ever get called, MLangCodePageEncoding is our proxy // (In Everett this was done by MLang) - Contract.Assert(false, "Didn't expect to make it to ISCIIEncoding serialization constructor"); + Debug.Assert(false, "Didn't expect to make it to ISCIIEncoding serialization constructor"); throw new ArgumentException(Environment.GetResourceString("Arg_ExecutionEngineException")); } // ISerializable implementation - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { // Make sure to get the base stuff too This throws if info is null SerializeEncoding(info, context); - Contract.Assert(info!=null, "[ISCIIEncoding.GetObjectData] Expected null info to throw"); + Debug.Assert(info!=null, "[ISCIIEncoding.GetObjectData] Expected null info to throw"); // Just need Everett MLangCodePageEncoding maxCharSize info.AddValue("m_maxByteSize", 2); @@ -111,7 +111,7 @@ namespace System.Text public override int GetMaxByteCount(int charCount) { if (charCount < 0) - throw new ArgumentOutOfRangeException("charCount", + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -125,7 +125,7 @@ namespace System.Text byteCount *= 4; if (byteCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); return (int)byteCount; } @@ -135,7 +135,7 @@ namespace System.Text public override int GetMaxCharCount(int byteCount) { if (byteCount < 0) - throw new ArgumentOutOfRangeException("byteCount", + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -149,13 +149,12 @@ namespace System.Text charCount *= DecoderFallback.MaxCharCount; if (charCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow")); return (int)charCount; } // Our workhorse version - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS baseEncoder) { // Use null pointer to ask GetBytes for count @@ -163,15 +162,14 @@ namespace System.Text } // Workhorse - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetBytes(char *chars, int charCount, byte* bytes, int byteCount, EncoderNLS baseEncoder) { // Allow null bytes for counting - Contract.Assert(chars != null, "[ISCIIEncoding.GetBytes]chars!=null"); -// Contract.Assert(bytes != null, "[ISCIIEncoding.GetBytes]bytes!=null"); - Contract.Assert(charCount >=0, "[ISCIIEncoding.GetBytes]charCount >=0"); - Contract.Assert(byteCount >=0, "[ISCIIEncoding.GetBytes]byteCount >=0"); + Debug.Assert(chars != null, "[ISCIIEncoding.GetBytes]chars!=null"); +// Debug.Assert(bytes != null, "[ISCIIEncoding.GetBytes]bytes!=null"); + Debug.Assert(charCount >=0, "[ISCIIEncoding.GetBytes]charCount >=0"); + Debug.Assert(byteCount >=0, "[ISCIIEncoding.GetBytes]byteCount >=0"); // Need the ISCII Encoder ISCIIEncoder encoder = (ISCIIEncoder) baseEncoder; @@ -268,7 +266,7 @@ namespace System.Text // See if our code page ("font" in ISCII spec) has to change // (This if doesn't add character, just changes character set) - Contract.Assert(indicScript!=0, "[ISCIIEncoding.GetBytes]expected an indic script value"); + Debug.Assert(indicScript!=0, "[ISCIIEncoding.GetBytes]expected an indic script value"); if (indicScript != currentCodePage) { // It changed, spit out the ATR @@ -279,7 +277,7 @@ namespace System.Text currentCodePage = indicScript; // We only know how to map from Unicode to pages from Devanagari to Punjabi (2 to 11) - Contract.Assert(currentCodePage >= CodeDevanagari && currentCodePage <= CodePunjabi, + Debug.Assert(currentCodePage >= CodeDevanagari && currentCodePage <= CodePunjabi, "[ISCIIEncoding.GetBytes]Code page (" + currentCodePage + " shouldn't appear in ISCII from Unicode table!"); } @@ -294,7 +292,7 @@ namespace System.Text if (indicTwoBytes != 0) { // This one needs another byte - Contract.Assert((indicTwoBytes >> 12) > 0 && (indicTwoBytes >> 12) <= 3, + Debug.Assert((indicTwoBytes >> 12) > 0 && (indicTwoBytes >> 12) <= 3, "[ISCIIEncoding.GetBytes]Expected indicTwoBytes from 1-3, not " + (indicTwoBytes >> 12)); // Already did buffer checking, but... @@ -341,7 +339,6 @@ namespace System.Text } // Workhorse - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder) { // Just call GetChars with null chars saying we want count @@ -354,16 +351,15 @@ namespace System.Text // Devenagari F0, B8 -> \u0952 // Devenagari F0, BF -> \u0970 // Some characters followed by E9 become a different character instead. - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetChars(byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already // Allow null chars for counting - Contract.Assert(bytes != null, "[ISCIIEncoding.GetChars]bytes is null"); - Contract.Assert(byteCount >= 0, "[ISCIIEncoding.GetChars]byteCount is negative"); -// Contract.Assert(chars != null, "[ISCIIEncoding.GetChars]chars is null"); - Contract.Assert(charCount >= 0, "[ISCIIEncoding.GetChars]charCount is negative"); + Debug.Assert(bytes != null, "[ISCIIEncoding.GetChars]bytes is null"); + Debug.Assert(byteCount >= 0, "[ISCIIEncoding.GetChars]byteCount is negative"); +// Debug.Assert(chars != null, "[ISCIIEncoding.GetChars]chars is null"); + Debug.Assert(charCount >= 0, "[ISCIIEncoding.GetChars]charCount is negative"); // Need the ISCII Decoder ISCIIDecoder decoder = (ISCIIDecoder) baseDecoder; @@ -395,7 +391,7 @@ namespace System.Text // Get our current code page index (some code pages are dups) int currentCodePageIndex = -1; - Contract.Assert(currentCodePage >= CodeDevanagari && currentCodePage <= CodePunjabi, + Debug.Assert(currentCodePage >= CodeDevanagari && currentCodePage <= CodePunjabi, "[ISCIIEncoding.GetChars]Decoder code page must be >= Devanagari and <= Punjabi, not " + currentCodePage); if (currentCodePage >= CodeDevanagari && currentCodePage <= CodePunjabi) @@ -415,7 +411,7 @@ namespace System.Text bLastSpecial = false; // One and only one of our flags should be set - Contract.Assert(((bLastVirama ? 1 : 0) + (bLastATR ? 1 : 0) + + Debug.Assert(((bLastVirama ? 1 : 0) + (bLastATR ? 1 : 0) + (bLastDevenagariStressAbbr ? 1 : 0) + ((cLastCharForNextNukta > 0) ? 1 : 0)) == 1, String.Format(CultureInfo.InvariantCulture, @@ -476,10 +472,10 @@ namespace System.Text bLastATR = false; // we know we can't have any of these other modes - Contract.Assert(bLastVirama == false, "[ISCIIEncoding.GetChars] Expected no bLastVirama in bLastATR mode"); - Contract.Assert(bLastDevenagariStressAbbr == false, "[ISCIIEncoding.GetChars] Expected no bLastDevenagariStressAbbr in bLastATR mode"); - Contract.Assert(cLastCharForNextNukta == (char)0, "[ISCIIEncoding.GetChars] Expected no cLastCharForNextNukta in bLastATR mode"); - Contract.Assert(cLastCharForNoNextNukta == (char)0, "[ISCIIEncoding.GetChars] Expected no cLastCharForNoNextNukta in bLastATR mode"); + Debug.Assert(bLastVirama == false, "[ISCIIEncoding.GetChars] Expected no bLastVirama in bLastATR mode"); + Debug.Assert(bLastDevenagariStressAbbr == false, "[ISCIIEncoding.GetChars] Expected no bLastDevenagariStressAbbr in bLastATR mode"); + Debug.Assert(cLastCharForNextNukta == (char)0, "[ISCIIEncoding.GetChars] Expected no cLastCharForNextNukta in bLastATR mode"); + Debug.Assert(cLastCharForNoNextNukta == (char)0, "[ISCIIEncoding.GetChars] Expected no cLastCharForNoNextNukta in bLastATR mode"); // Keep processing this byte } @@ -508,10 +504,10 @@ namespace System.Text bLastVirama = false; // We know we can't have any of these other modes - Contract.Assert(bLastATR == false, "[ISCIIEncoding.GetChars] Expected no bLastATR in bLastVirama mode"); - Contract.Assert(bLastDevenagariStressAbbr == false, "[ISCIIEncoding.GetChars] Expected no bLastDevenagariStressAbbr in bLastVirama mode"); - Contract.Assert(cLastCharForNextNukta == (char)0, "[ISCIIEncoding.GetChars] Expected no cLastCharForNextNukta in bLastVirama mode"); - Contract.Assert(cLastCharForNoNextNukta == (char)0, "[ISCIIEncoding.GetChars] Expected no cLastCharForNoNextNukta in bLastVirama mode"); + Debug.Assert(bLastATR == false, "[ISCIIEncoding.GetChars] Expected no bLastATR in bLastVirama mode"); + Debug.Assert(bLastDevenagariStressAbbr == false, "[ISCIIEncoding.GetChars] Expected no bLastDevenagariStressAbbr in bLastVirama mode"); + Debug.Assert(cLastCharForNextNukta == (char)0, "[ISCIIEncoding.GetChars] Expected no cLastCharForNextNukta in bLastVirama mode"); + Debug.Assert(cLastCharForNoNextNukta == (char)0, "[ISCIIEncoding.GetChars] Expected no cLastCharForNoNextNukta in bLastVirama mode"); } else if (bLastDevenagariStressAbbr) { @@ -544,15 +540,15 @@ namespace System.Text // (last character was added when mode was set) bLastDevenagariStressAbbr = false; - Contract.Assert(bLastATR == false, "[ISCIIEncoding.GetChars] Expected no bLastATR in bLastDevenagariStressAbbr mode"); - Contract.Assert(bLastVirama == false, "[ISCIIEncoding.GetChars] Expected no bLastVirama in bLastDevenagariStressAbbr mode"); - Contract.Assert(cLastCharForNextNukta == (char)0, "[ISCIIEncoding.GetChars] Expected no cLastCharForNextNukta in bLastDevenagariStressAbbr mode"); - Contract.Assert(cLastCharForNoNextNukta == (char)0, "[ISCIIEncoding.GetChars] Expected no cLastCharForNoNextNukta in bLastDevenagariStressAbbr mode"); + Debug.Assert(bLastATR == false, "[ISCIIEncoding.GetChars] Expected no bLastATR in bLastDevenagariStressAbbr mode"); + Debug.Assert(bLastVirama == false, "[ISCIIEncoding.GetChars] Expected no bLastVirama in bLastDevenagariStressAbbr mode"); + Debug.Assert(cLastCharForNextNukta == (char)0, "[ISCIIEncoding.GetChars] Expected no cLastCharForNextNukta in bLastDevenagariStressAbbr mode"); + Debug.Assert(cLastCharForNoNextNukta == (char)0, "[ISCIIEncoding.GetChars] Expected no cLastCharForNoNextNukta in bLastDevenagariStressAbbr mode"); } else { // We were checking for next char being a nukta - Contract.Assert(cLastCharForNextNukta > 0 && cLastCharForNoNextNukta > 0, + Debug.Assert(cLastCharForNextNukta > 0 && cLastCharForNoNextNukta > 0, "[ISCIIEncoding.GetChars]No other special case found, but cLastCharFor(No)NextNukta variable(s) aren't set."); // We'll either add combined char or last char @@ -574,14 +570,14 @@ namespace System.Text // Keep processing this byte, turn off mode. cLastCharForNextNukta = cLastCharForNoNextNukta = '\0'; - Contract.Assert(bLastATR == false, "[ISCIIEncoding.GetChars] Expected no bLastATR in cLastCharForNextNukta mode"); - Contract.Assert(bLastVirama == false, "[ISCIIEncoding.GetChars] Expected no bLastVirama in cLastCharForNextNukta mode"); - Contract.Assert(bLastDevenagariStressAbbr == false, "[ISCIIEncoding.GetChars] Expected no bLastDevenagariStressAbbr in cLastCharForNextNukta mode"); + Debug.Assert(bLastATR == false, "[ISCIIEncoding.GetChars] Expected no bLastATR in cLastCharForNextNukta mode"); + Debug.Assert(bLastVirama == false, "[ISCIIEncoding.GetChars] Expected no bLastVirama in cLastCharForNextNukta mode"); + Debug.Assert(bLastDevenagariStressAbbr == false, "[ISCIIEncoding.GetChars] Expected no bLastDevenagariStressAbbr in cLastCharForNextNukta mode"); } } // Now bLastSpecial should be false and all flags false. - Contract.Assert (!bLastSpecial && !bLastDevenagariStressAbbr && !bLastVirama && !bLastATR && + Debug.Assert (!bLastSpecial && !bLastDevenagariStressAbbr && !bLastVirama && !bLastATR && cLastCharForNextNukta == '\0', "[ISCIIEncoding.GetChars]No special state for last code point should exist at this point."); @@ -600,7 +596,7 @@ namespace System.Text continue; } - Contract.Assert (currentCodePageIndex != -1, "[ISCIIEncoding.GetChars]Expected valid currentCodePageIndex != -1"); + Debug.Assert (currentCodePageIndex != -1, "[ISCIIEncoding.GetChars]Expected valid currentCodePageIndex != -1"); char ch = IndicMapping[currentCodePageIndex, 0, b - MultiByteBegin]; char cAlt = IndicMapping[currentCodePageIndex, 1, b - MultiByteBegin]; @@ -646,7 +642,7 @@ namespace System.Text } // We must be the Devenagari special case for F0, B8 & F0, BF - Contract.Assert(currentCodePage == CodeDevanagari && b == DevenagariExt, + Debug.Assert(currentCodePage == CodeDevanagari && b == DevenagariExt, String.Format(CultureInfo.InvariantCulture, "[ISCIIEncoding.GetChars] Devenagari special case must {0} not {1} or in Devanagari code page {2} not {3}.", DevenagariExt, b, CodeDevanagari, currentCodePage)); @@ -701,7 +697,7 @@ namespace System.Text cLastCharForNoNextNukta != '\0' || bLastATR || bLastDevenagariStressAbbr) { // Either not flushing or had state (from convert) - Contract.Assert(!decoder.MustFlush || !decoder.m_throwOnOverflow, + Debug.Assert(!decoder.MustFlush || !decoder.m_throwOnOverflow, "[ISCIIEncoding.GetChars]Expected no state or not converting or not flushing"); decoder.currentCodePage = currentCodePage; decoder.bLastVirama = bLastVirama; diff --git a/src/mscorlib/src/System/Text/ISO2022Encoding.cs b/src/mscorlib/src/System/Text/ISO2022Encoding.cs index fe57e7c..fca579f 100644 --- a/src/mscorlib/src/System/Text/ISO2022Encoding.cs +++ b/src/mscorlib/src/System/Text/ISO2022Encoding.cs @@ -28,6 +28,7 @@ namespace System.Text { using System.Globalization; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Text; using System.Runtime.InteropServices; @@ -53,7 +54,6 @@ namespace System.Text // We have to load the 936 code page tables, so impersonate 936 as our base // This pretends to be other code pages as far as memory sections are concerned. - [System.Security.SecurityCritical] // auto-generated internal ISO2022Encoding(int codePage) : base(codePage, tableBaseCodePages[codePage % 10]) { this.m_bUseMlangTypeForSerialization = true; @@ -61,11 +61,10 @@ namespace System.Text // Constructor called by serialization. // Note: We use the base GetObjectData however - [System.Security.SecurityCritical] // auto-generated internal ISO2022Encoding(SerializationInfo info, StreamingContext context) : base(info, context) { // Actually this can't ever get called, CodePageEncoding is our proxy - Contract.Assert(false, "Didn't expect to make it to DBCSCodePageEncoding serialization constructor"); + Debug.Assert(false, "Didn't expect to make it to DBCSCodePageEncoding serialization constructor"); throw new ArgumentException(Environment.GetResourceString("Arg_ExecutionEngineException")); } @@ -102,7 +101,6 @@ namespace System.Text ModeNOOP = -3 } - [System.Security.SecurityCritical] // auto-generated protected unsafe override String GetMemorySectionName() { int iUseCodePage = this.bFlagDataTable ? dataTableCodePage : CodePage; @@ -123,7 +121,7 @@ namespace System.Text strFormat = "CodePage_{0}_{1}_{2}_{3}_{4}_HZ"; break; default: - Contract.Assert(false, "[ISO2022Encoding.GetMemorySectionName] Don't expect to get here for code page " + this.CodePage); + Debug.Assert(false, "[ISO2022Encoding.GetMemorySectionName] Don't expect to get here for code page " + this.CodePage); strFormat = "CodePage_{0}_{1}_{2}_{3}_{4}"; break; } @@ -263,28 +261,26 @@ namespace System.Text } // GetByteCount - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS baseEncoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already - Contract.Assert(count >= 0, "[ISO2022Encoding.GetByteCount]count is negative"); - Contract.Assert(chars != null, "[ISO2022Encoding.GetByteCount]chars is null"); + Debug.Assert(count >= 0, "[ISO2022Encoding.GetByteCount]count is negative"); + Debug.Assert(chars != null, "[ISO2022Encoding.GetByteCount]chars is null"); // Just call GetBytes with null byte* to get count return GetBytes(chars, count, null, 0, baseEncoder); } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS baseEncoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already - Contract.Assert(chars != null, "[ISO2022Encoding.GetBytes]chars is null"); - Contract.Assert(byteCount >= 0, "[ISO2022Encoding.GetBytes]byteCount is negative"); - Contract.Assert(charCount >= 0, "[ISO2022Encoding.GetBytes]charCount is negative"); + Debug.Assert(chars != null, "[ISO2022Encoding.GetBytes]chars is null"); + Debug.Assert(byteCount >= 0, "[ISO2022Encoding.GetBytes]byteCount is negative"); + Debug.Assert(charCount >= 0, "[ISO2022Encoding.GetBytes]charCount is negative"); // Assert because we shouldn't be able to have a null encoder. - Contract.Assert(encoderFallback != null, "[ISO2022Encoding.GetBytes]Attempting to use null encoder fallback"); + Debug.Assert(encoderFallback != null, "[ISO2022Encoding.GetBytes]Attempting to use null encoder fallback"); // Fix our encoder ISO2022Encoder encoder = (ISO2022Encoder)baseEncoder; @@ -316,25 +312,23 @@ namespace System.Text } // This is internal and called by something else, - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder) { // Just assert, we're called internally so these should be safe, checked already - Contract.Assert(bytes != null, "[ISO2022Encoding.GetCharCount]bytes is null"); - Contract.Assert(count >= 0, "[ISO2022Encoding.GetCharCount]byteCount is negative"); + Debug.Assert(bytes != null, "[ISO2022Encoding.GetCharCount]bytes is null"); + Debug.Assert(count >= 0, "[ISO2022Encoding.GetCharCount]byteCount is negative"); // Just call getChars with null char* to get count return GetChars(bytes, count, null, 0, baseDecoder); } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetChars(byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already - Contract.Assert(bytes != null, "[ISO2022Encoding.GetChars]bytes is null"); - Contract.Assert(byteCount >= 0, "[ISO2022Encoding.GetChars]byteCount is negative"); - Contract.Assert(charCount >= 0, "[ISO2022Encoding.GetChars]charCount is negative"); + Debug.Assert(bytes != null, "[ISO2022Encoding.GetChars]bytes is null"); + Debug.Assert(byteCount >= 0, "[ISO2022Encoding.GetChars]byteCount is negative"); + Debug.Assert(charCount >= 0, "[ISO2022Encoding.GetChars]charCount is negative"); // Fix our decoder ISO2022Decoder decoder = (ISO2022Decoder)baseDecoder; @@ -358,7 +352,7 @@ namespace System.Text iCount = GetCharsCP52936( bytes, byteCount, chars, charCount, decoder); break; default: - Contract.Assert(false, "[ISO2022Encoding.GetChars] had unexpected code page"); + Debug.Assert(false, "[ISO2022Encoding.GetChars] had unexpected code page"); break; } @@ -399,7 +393,6 @@ namespace System.Text // undefined, so we maintain that behavior when decoding. We will never generate characters using // that technique, but the decoder will process them. // - [System.Security.SecurityCritical] // auto-generated private unsafe int GetBytesCP5022xJP(char* chars, int charCount, byte* bytes, int byteCount, ISO2022Encoder encoder) { @@ -422,7 +415,7 @@ namespace System.Text // We may have a left over character from last time, try and process it. if (charLeftOver > 0) { - Contract.Assert(Char.IsHighSurrogate(charLeftOver), "[ISO2022Encoding.GetBytesCP5022xJP]leftover character should be high surrogate"); + Debug.Assert(Char.IsHighSurrogate(charLeftOver), "[ISO2022Encoding.GetBytesCP5022xJP]leftover character should be high surrogate"); // It has to be a high surrogate, which we don't support, so it has to be a fallback buffer.Fallback(charLeftOver); @@ -483,7 +476,7 @@ namespace System.Text else { // 50221 does halfwidth katakana by escape sequence - Contract.Assert(CodePage == 50221, "[ISO2022Encoding.GetBytesCP5022xJP]Expected Code Page 50221"); + Debug.Assert(CodePage == 50221, "[ISO2022Encoding.GetBytesCP5022xJP]Expected Code Page 50221"); // Add our escape sequence if (!buffer.AddByte(ESCAPE, unchecked((byte)'('), unchecked((byte)'I'))) @@ -642,7 +635,6 @@ namespace System.Text // Also Mlang always assumed KR mode, even if the designator wasn't found yet, so we do that as // well. So basically we just ignore $)C when decoding. // - [System.Security.SecurityCritical] // auto-generated private unsafe int GetBytesCP50225KR(char* chars, int charCount, byte* bytes, int byteCount, ISO2022Encoder encoder) { @@ -665,7 +657,7 @@ namespace System.Text // We may have a l left over character from last time, try and process it. if (charLeftOver > 0) { - Contract.Assert(Char.IsHighSurrogate(charLeftOver), "[ISO2022Encoding.GetBytesCP50225KR]leftover character should be high surrogate"); + Debug.Assert(Char.IsHighSurrogate(charLeftOver), "[ISO2022Encoding.GetBytesCP50225KR]leftover character should be high surrogate"); // It has to be a high surrogate, which we don't support, so it has to be a fallback buffer.Fallback(charLeftOver); @@ -765,7 +757,7 @@ namespace System.Text if (!encoder.MustFlush || encoder.charLeftOver != (char)0) { // We should be not flushing or converting - Contract.Assert(!encoder.MustFlush || !encoder.m_throwOnOverflow, + Debug.Assert(!encoder.MustFlush || !encoder.m_throwOnOverflow, "[ISO2022Encoding.GetBytesCP50225KR]Expected no left over data or not flushing or not converting"); encoder.shiftInOutMode = shiftOutMode; } @@ -793,7 +785,6 @@ namespace System.Text // // This encoding is designed for transmission by e-mail and news. No bytes should have high bit set. // (all bytes <= 0x7f) - [System.Security.SecurityCritical] // auto-generated private unsafe int GetBytesCP52936(char* chars, int charCount, byte* bytes, int byteCount, ISO2022Encoder encoder) { @@ -813,7 +804,7 @@ namespace System.Text // We may have a left over character from last time, try and process it. if (charLeftOver > 0) { - Contract.Assert(Char.IsHighSurrogate(charLeftOver), "[ISO2022Encoding.GetBytesCP52936]leftover character should be high surrogate"); + Debug.Assert(Char.IsHighSurrogate(charLeftOver), "[ISO2022Encoding.GetBytesCP52936]leftover character should be high surrogate"); // It has to be a high surrogate, which we don't support, so it has to be a fallback buffer.Fallback(charLeftOver); @@ -928,7 +919,6 @@ namespace System.Text return buffer.Count; } - [System.Security.SecurityCritical] // auto-generated private unsafe int GetCharsCP5022xJP(byte* bytes, int byteCount, char* chars, int charCount, ISO2022Decoder decoder) { @@ -1139,7 +1129,7 @@ namespace System.Text if (!decoder.MustFlush || escapeCount != 0) { // Either not flushing or had state (from convert) - Contract.Assert(!decoder.MustFlush || !decoder.m_throwOnOverflow, + Debug.Assert(!decoder.MustFlush || !decoder.m_throwOnOverflow, "[ISO2022Encoding.GetCharsCP5022xJP]Expected no state or not converting or not flushing"); decoder.currentMode = currentMode; @@ -1233,7 +1223,7 @@ namespace System.Text private byte DecrementEscapeBytes(ref byte[] bytes, ref int count) { - Contract.Assert(count > 0, "[ISO2022Encoding.DecrementEscapeBytes]count > 0"); + Debug.Assert(count > 0, "[ISO2022Encoding.DecrementEscapeBytes]count > 0"); // Decrement our count count--; @@ -1256,7 +1246,6 @@ namespace System.Text // Note that in DBCS mode mlang passed through ' ', '\t' and '\n' as SBCS characters // probably to allow mailer formatting without too much extra work. - [System.Security.SecurityCritical] // auto-generated private unsafe int GetCharsCP50225KR(byte* bytes, int byteCount, char* chars, int charCount, ISO2022Decoder decoder) { @@ -1441,7 +1430,7 @@ namespace System.Text if (!decoder.MustFlush || escapeCount != 0) { // Either not flushing or had state (from convert) - Contract.Assert(!decoder.MustFlush || !decoder.m_throwOnOverflow, + Debug.Assert(!decoder.MustFlush || !decoder.m_throwOnOverflow, "[ISO2022Encoding.GetCharsCP50225KR]Expected no state or not converting or not flushing"); decoder.currentMode = currentMode; @@ -1496,12 +1485,11 @@ namespace System.Text // // This encoding is designed for transmission by e-mail and news. No bytes should have high bit set. // (all bytes <= 0x7f) - [System.Security.SecurityCritical] // auto-generated private unsafe int GetCharsCP52936(byte* bytes, int byteCount, char* chars, int charCount, ISO2022Decoder decoder) { - Contract.Assert(byteCount >=0, "[ISO2022Encoding.GetCharsCP52936]count >=0"); - Contract.Assert(bytes!=null, "[ISO2022Encoding.GetCharsCP52936]bytes!=null"); + Debug.Assert(byteCount >=0, "[ISO2022Encoding.GetCharsCP52936]count >=0"); + Debug.Assert(bytes!=null, "[ISO2022Encoding.GetCharsCP52936]bytes!=null"); // Get our info. Encoding.EncodingCharBuffer buffer = new Encoding.EncodingCharBuffer( @@ -1612,7 +1600,7 @@ namespace System.Text if (currentMode != ISO2022Modes.ModeASCII) { // Should be ModeHZ - Contract.Assert(currentMode == ISO2022Modes.ModeHZ, "[ISO2022Encoding.GetCharsCP52936]Expected ModeHZ"); + Debug.Assert(currentMode == ISO2022Modes.ModeHZ, "[ISO2022Encoding.GetCharsCP52936]Expected ModeHZ"); char cm; // Everett allowed characters < 0x20 to be passed as if they were ASCII @@ -1737,7 +1725,7 @@ namespace System.Text else { // Either not flushing or had state (from convert) - Contract.Assert(!decoder.MustFlush || !decoder.m_throwOnOverflow, + Debug.Assert(!decoder.MustFlush || !decoder.m_throwOnOverflow, "[ISO2022Encoding.GetCharsCP52936]Expected no state or not converting or not flushing"); decoder.currentMode = currentMode; @@ -1754,7 +1742,7 @@ namespace System.Text public override int GetMaxByteCount(int charCount) { if (charCount < 0) - throw new ArgumentOutOfRangeException("charCount", + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -1801,7 +1789,7 @@ namespace System.Text byteCount += extraStart + extraEnd; if (byteCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); return (int)byteCount; } @@ -1809,7 +1797,7 @@ namespace System.Text public override int GetMaxCharCount(int byteCount) { if (byteCount < 0) - throw new ArgumentOutOfRangeException("byteCount", + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -1839,7 +1827,7 @@ namespace System.Text charCount *= DecoderFallback.MaxCharCount; if (charCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow")); return (int)charCount; } diff --git a/src/mscorlib/src/System/Text/Latin1Encoding.cs b/src/mscorlib/src/System/Text/Latin1Encoding.cs index a24f9c0..56a6c1f 100644 --- a/src/mscorlib/src/System/Text/Latin1Encoding.cs +++ b/src/mscorlib/src/System/Text/Latin1Encoding.cs @@ -5,6 +5,7 @@ namespace System.Text { using System; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Globalization; using System.Runtime.InteropServices; @@ -43,12 +44,11 @@ namespace System.Text } // ISerializable implementation, serialize it as a CodePageEncoding - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { // Make sure to get the base stuff too This throws if info is null SerializeEncoding(info, context); - Contract.Assert(info!=null, "[Latin1Encoding.GetObjectData] Expected null info to throw"); + Debug.Assert(info!=null, "[Latin1Encoding.GetObjectData] Expected null info to throw"); // In Everett this is a CodePageEncoding, so it needs maxCharSize info.AddValue("CodePageEncoding+maxCharSize", 1); @@ -61,15 +61,14 @@ namespace System.Text // GetByteCount // Note: We start by assuming that the output will be the same as count. Having // an encoder or fallback may change that assumption - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetByteCount(char* chars, int charCount, EncoderNLS encoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already - Contract.Assert(charCount >= 0, "[Latin1Encoding.GetByteCount]count is negative"); - Contract.Assert(chars != null, "[Latin1Encoding.GetByteCount]chars is null"); + Debug.Assert(charCount >= 0, "[Latin1Encoding.GetByteCount]count is negative"); + Debug.Assert(chars != null, "[Latin1Encoding.GetByteCount]chars is null"); // Assert because we shouldn't be able to have a null encoder. - Contract.Assert(encoderFallback != null, "[Latin1Encoding.GetByteCount]Attempting to use null fallback encoder"); + Debug.Assert(encoderFallback != null, "[Latin1Encoding.GetByteCount]Attempting to use null fallback encoder"); char charLeftOver = (char)0; @@ -79,13 +78,13 @@ namespace System.Text if (encoder != null) { charLeftOver = encoder.charLeftOver; - Contract.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver), + Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver), "[Latin1Encoding.GetByteCount]leftover character should be high surrogate"); fallback = encoder.Fallback as EncoderReplacementFallback; // Verify that we have no fallbackbuffer, for Latin1 its always empty, so just assert - Contract.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer || + Debug.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer || encoder.FallbackBuffer.Remaining == 0, "[Latin1CodePageEncoding.GetByteCount]Expected empty fallback buffer"); } @@ -122,7 +121,7 @@ namespace System.Text if (charLeftOver > 0) { // Initialize the buffer - Contract.Assert(encoder != null, + Debug.Assert(encoder != null, "[Latin1Encoding.GetByteCount]Expected encoder if we have charLeftOver"); fallbackBuffer = encoder.FallbackBuffer; fallbackBuffer.InternalInitialize(chars, charEnd, encoder, false); @@ -171,24 +170,23 @@ namespace System.Text byteCount++; } - Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, + Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[Latin1Encoding.GetByteCount]Expected Empty fallback buffer"); return byteCount; } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS encoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already - Contract.Assert(bytes != null, "[Latin1Encoding.GetBytes]bytes is null"); - Contract.Assert(byteCount >= 0, "[Latin1Encoding.GetBytes]byteCount is negative"); - Contract.Assert(chars != null, "[Latin1Encoding.GetBytes]chars is null"); - Contract.Assert(charCount >= 0, "[Latin1Encoding.GetBytes]charCount is negative"); + Debug.Assert(bytes != null, "[Latin1Encoding.GetBytes]bytes is null"); + Debug.Assert(byteCount >= 0, "[Latin1Encoding.GetBytes]byteCount is negative"); + Debug.Assert(chars != null, "[Latin1Encoding.GetBytes]chars is null"); + Debug.Assert(charCount >= 0, "[Latin1Encoding.GetBytes]charCount is negative"); // Assert because we shouldn't be able to have a null encoder. - Contract.Assert(encoderFallback != null, "[Latin1Encoding.GetBytes]Attempting to use null encoder fallback"); + Debug.Assert(encoderFallback != null, "[Latin1Encoding.GetBytes]Attempting to use null encoder fallback"); // Get any left over characters & check fast or slower fallback type char charLeftOver = (char)0; @@ -197,11 +195,11 @@ namespace System.Text { charLeftOver = encoder.charLeftOver; fallback = encoder.Fallback as EncoderReplacementFallback; - Contract.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver), + Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver), "[Latin1Encoding.GetBytes]leftover character should be high surrogate"); // Verify that we have no fallbackbuffer, for ASCII its always empty, so just assert - Contract.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer || + Debug.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer || encoder.FallbackBuffer.Remaining == 0, "[Latin1CodePageEncoding.GetBytes]Expected empty fallback buffer"); } @@ -284,7 +282,7 @@ namespace System.Text { // Since left over char was a surrogate, it'll have to be fallen back. // Get Fallback - Contract.Assert(encoder != null, + Debug.Assert(encoder != null, "[Latin1Encoding.GetBytes]Expected encoder if we have charLeftOver"); fallbackBuffer = encoder.FallbackBuffer; fallbackBuffer.InternalInitialize(chars, charEnd, encoder, true); @@ -338,7 +336,7 @@ namespace System.Text { // Didn't use this char, throw it. Chars should've advanced by now // If we had encoder fallback data it would've thrown before the loop - Contract.Assert(chars > charStart, + Debug.Assert(chars > charStart, "[Latin1Encoding.GetBytes]Expected chars to have advanced (fallback case)"); chars--; fallbackBuffer.InternalReset(); @@ -356,11 +354,11 @@ namespace System.Text if (bytes >= byteEnd) { // didn't use this char, we'll throw or use buffer - Contract.Assert(fallbackBuffer == null || fallbackBuffer.bFallingBack == false, + Debug.Assert(fallbackBuffer == null || fallbackBuffer.bFallingBack == false, "[Latin1Encoding.GetBytes]Expected fallback to have throw initially if insufficient space"); if (fallbackBuffer == null || fallbackBuffer.bFallingBack == false) { - Contract.Assert(chars > charStart, + Debug.Assert(chars > charStart, "[Latin1Encoding.GetBytes]Expected chars to have advanced (fallback case)"); chars--; // don't use last char } @@ -385,34 +383,32 @@ namespace System.Text encoder.m_charsUsed = (int)(chars - charStart); } - Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, + Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[Latin1Encoding.GetBytes]Expected Empty fallback buffer"); return (int)(bytes - byteStart); } // This is internal and called by something else, - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS decoder) { // Just assert, we're called internally so these should be safe, checked already - Contract.Assert(bytes != null, "[Latin1Encoding.GetCharCount]bytes is null"); - Contract.Assert(count >= 0, "[Latin1Encoding.GetCharCount]byteCount is negative"); + Debug.Assert(bytes != null, "[Latin1Encoding.GetCharCount]bytes is null"); + Debug.Assert(count >= 0, "[Latin1Encoding.GetCharCount]byteCount is negative"); // Just return length, SBCS stay the same length because they don't map to surrogate // pairs and we don't have to fallback because all latin1Encoding code points are unicode return count; } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetChars(byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS decoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already - Contract.Assert(bytes != null, "[Latin1Encoding.GetChars]bytes is null"); - Contract.Assert(byteCount >= 0, "[Latin1Encoding.GetChars]byteCount is negative"); - Contract.Assert(chars != null, "[Latin1Encoding.GetChars]chars is null"); - Contract.Assert(charCount >= 0, "[Latin1Encoding.GetChars]charCount is negative"); + Debug.Assert(bytes != null, "[Latin1Encoding.GetChars]bytes is null"); + Debug.Assert(byteCount >= 0, "[Latin1Encoding.GetChars]byteCount is negative"); + Debug.Assert(chars != null, "[Latin1Encoding.GetChars]chars is null"); + Debug.Assert(charCount >= 0, "[Latin1Encoding.GetChars]charCount is negative"); // Need byteCount chars, otherwise too small buffer if (charCount < byteCount) @@ -446,7 +442,7 @@ namespace System.Text public override int GetMaxByteCount(int charCount) { if (charCount < 0) - throw new ArgumentOutOfRangeException("charCount", + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -459,14 +455,14 @@ namespace System.Text // 1 to 1 for most characters. Only surrogates with fallbacks have less. if (byteCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); return (int)byteCount; } public override int GetMaxCharCount(int byteCount) { if (byteCount < 0) - throw new ArgumentOutOfRangeException("byteCount", + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -478,7 +474,7 @@ namespace System.Text charCount *= DecoderFallback.MaxCharCount; if (charCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow")); return (int)charCount; } diff --git a/src/mscorlib/src/System/Text/MLangCodePageEncoding.cs b/src/mscorlib/src/System/Text/MLangCodePageEncoding.cs index 53924a9..a82db91 100644 --- a/src/mscorlib/src/System/Text/MLangCodePageEncoding.cs +++ b/src/mscorlib/src/System/Text/MLangCodePageEncoding.cs @@ -13,6 +13,7 @@ namespace System.Text using System; using System.Runtime.Serialization; using System.Security.Permissions; + using System.Diagnostics; using System.Diagnostics.Contracts; /*=================================MLangCodePageEncoding================================== @@ -46,7 +47,7 @@ namespace System.Text internal MLangCodePageEncoding(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // All versions have a code page @@ -76,7 +77,6 @@ namespace System.Text } // Just get it from GetEncoding - [System.Security.SecurityCritical] // auto-generated public Object GetRealObject(StreamingContext context) { // Get our encoding (Note: This has default fallbacks for readonly and everett cases) @@ -95,11 +95,10 @@ namespace System.Text } // ISerializable implementation - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { // We cannot ever call this. - Contract.Assert(false, "Didn't expect to make it to MLangCodePageEncoding ISerializable.GetObjectData"); + Debug.Assert(false, "Didn't expect to make it to MLangCodePageEncoding ISerializable.GetObjectData"); throw new ArgumentException(Environment.GetResourceString("Arg_ExecutionEngineException")); } @@ -115,25 +114,23 @@ namespace System.Text internal MLangEncoder(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); this.realEncoding = (Encoding)info.GetValue("m_encoding", typeof(Encoding)); } // Just get it from GetEncoder - [System.Security.SecurityCritical] // auto-generated public Object GetRealObject(StreamingContext context) { return this.realEncoding.GetEncoder(); } // ISerializable implementation, get data for this object - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { // We cannot ever call this. - Contract.Assert(false, "Didn't expect to make it to MLangCodePageEncoding.MLangEncoder.GetObjectData"); + Debug.Assert(false, "Didn't expect to make it to MLangCodePageEncoding.MLangEncoder.GetObjectData"); throw new ArgumentException(Environment.GetResourceString("Arg_ExecutionEngineException")); } } @@ -151,25 +148,23 @@ namespace System.Text internal MLangDecoder(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); this.realEncoding = (Encoding)info.GetValue("m_encoding", typeof(Encoding)); } // Just get it from GetDecoder - [System.Security.SecurityCritical] // auto-generated public Object GetRealObject(StreamingContext context) { return this.realEncoding.GetDecoder(); } // ISerializable implementation, get data for this object - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { // We cannot ever call this. - Contract.Assert(false, "Didn't expect to make it to MLangCodePageEncoding.MLangDecoder.GetObjectData"); + Debug.Assert(false, "Didn't expect to make it to MLangCodePageEncoding.MLangDecoder.GetObjectData"); throw new ArgumentException(Environment.GetResourceString("Arg_ExecutionEngineException")); } } diff --git a/src/mscorlib/src/System/Text/Normalization.Unix.cs b/src/mscorlib/src/System/Text/Normalization.Unix.cs new file mode 100644 index 0000000..d49bdc6 --- /dev/null +++ b/src/mscorlib/src/System/Text/Normalization.Unix.cs @@ -0,0 +1,123 @@ +// 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.Security; +using System.Text; + +namespace System.Text +{ + static partial class Normalization + { + public static bool IsNormalized(this string strInput, NormalizationForm normalizationForm) + { + ValidateArguments(strInput, normalizationForm); + + int ret = Interop.GlobalizationInterop.IsNormalized(normalizationForm, strInput, strInput.Length); + + if (ret == -1) + { + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex"), nameof(strInput)); + } + + return ret == 1; + } + + public static string Normalize(this string strInput, NormalizationForm normalizationForm) + { + ValidateArguments(strInput, normalizationForm); + + char[] buf = new char[strInput.Length]; + + for (int attempts = 2; attempts > 0; attempts--) + { + int realLen = Interop.GlobalizationInterop.NormalizeString(normalizationForm, strInput, strInput.Length, buf, buf.Length); + + if (realLen == -1) + { + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex"), nameof(strInput)); + } + + if (realLen <= buf.Length) + { + return new string(buf, 0, realLen); + } + + buf = new char[realLen]; + } + + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex"), nameof(strInput)); + } + + // ----------------------------- + // ---- PAL layer ends here ---- + // ----------------------------- + + private static void ValidateArguments(string strInput, NormalizationForm normalizationForm) + { + if (strInput == null) + { + throw new ArgumentNullException(nameof(strInput)); + } + + if (normalizationForm != NormalizationForm.FormC && normalizationForm != NormalizationForm.FormD && + normalizationForm != NormalizationForm.FormKC && normalizationForm != NormalizationForm.FormKD) + { + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNormalizationForm"), nameof(normalizationForm)); + } + + if (HasInvalidUnicodeSequence(strInput)) + { + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex"), nameof(strInput)); + } + } + + /// + /// ICU does not signal an error during normalization if the input string has invalid unicode, + /// unlike Windows (which uses the ERROR_NO_UNICODE_TRANSLATION error value to signal an error). + /// + /// We walk the string ourselves looking for these bad sequences so we can continue to throw + /// ArgumentException in these cases. + /// + private static bool HasInvalidUnicodeSequence(string s) + { + for (int i = 0; i < s.Length; i++) + { + char c = s[i]; + + if (c < '\ud800') + { + continue; + } + + if (c == '\uFFFE') + { + return true; + } + + // If we see low surrogate before a high one, the string is invalid. + if (char.IsLowSurrogate(c)) + { + return true; + } + + if (char.IsHighSurrogate(c)) + { + if (i + 1 >= s.Length || !char.IsLowSurrogate(s[i + 1])) + { + // A high surrogate at the end of the string or a high surrogate + // not followed by a low surrogate + return true; + } + else + { + i++; // consume the low surrogate. + continue; + } + } + } + + return false; + } + } +} diff --git a/src/mscorlib/src/System/Text/Normalization.Windows.cs b/src/mscorlib/src/System/Text/Normalization.Windows.cs new file mode 100644 index 0000000..b2faf0d --- /dev/null +++ b/src/mscorlib/src/System/Text/Normalization.Windows.cs @@ -0,0 +1,286 @@ +// 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. + +namespace System.Text +{ + using System; + using System.Security; + using System.Globalization; + using System.Text; + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Runtime.Versioning; + using System.Diagnostics; + using System.Diagnostics.Contracts; + + // This internal class wraps up our normalization behavior + + internal class Normalization + { + // + // Flags that track whether given normalization form was initialized + // +#if !FEATURE_NORM_IDNA_ONLY + private static volatile bool NFC; + private static volatile bool NFD; + private static volatile bool NFKC; + private static volatile bool NFKD; +#endif // !FEATURE_NORM_IDNA_ONLY + private static volatile bool IDNA; +#if !FEATURE_NORM_IDNA_ONLY + private static volatile bool NFCDisallowUnassigned; + private static volatile bool NFDDisallowUnassigned; + private static volatile bool NFKCDisallowUnassigned; + private static volatile bool NFKDDisallowUnassigned; +#endif // !FEATURE_NORM_IDNA_ONLY + private static volatile bool IDNADisallowUnassigned; + private static volatile bool Other; + + // These are error codes we get back from the Normalization DLL + private const int ERROR_SUCCESS = 0; + private const int ERROR_NOT_ENOUGH_MEMORY = 8; + private const int ERROR_INVALID_PARAMETER = 87; + private const int ERROR_INSUFFICIENT_BUFFER = 122; + private const int ERROR_NO_UNICODE_TRANSLATION = 1113; + + static private unsafe void InitializeForm(NormalizationForm form, String strDataFile) + { + byte* pTables = null; + + // Normalization uses OS on Win8 + if (!Environment.IsWindows8OrAbove) + { + if (strDataFile == null) + { + // They were supposed to have a form that we know about! + throw new ArgumentException( + Environment.GetResourceString("Argument_InvalidNormalizationForm")); + } + + // Tell the DLL where to find our data + pTables = GlobalizationAssembly.GetGlobalizationResourceBytePtr( + typeof(Normalization).Assembly, strDataFile); + if (pTables == null) + { + // Unable to load the specified normalizationForm, + // tables not loaded from file + throw new ArgumentException( + Environment.GetResourceString("Argument_InvalidNormalizationForm")); + } + } + + nativeNormalizationInitNormalization(form, pTables); + } + + static private void EnsureInitialized(NormalizationForm form) + { + switch ((ExtendedNormalizationForms)form) + { +#if !FEATURE_NORM_IDNA_ONLY + case ExtendedNormalizationForms.FormC: + if (NFC) return; + InitializeForm(form, "normnfc.nlp"); + NFC = true; + break; + + case ExtendedNormalizationForms.FormD: + if (NFD) return; + InitializeForm(form, "normnfd.nlp"); + NFD = true; + break; + + case ExtendedNormalizationForms.FormKC: + if (NFKC) return; + InitializeForm(form, "normnfkc.nlp"); + NFKC = true; + break; + + case ExtendedNormalizationForms.FormKD: + if (NFKD) return; + InitializeForm(form, "normnfkd.nlp"); + NFKD = true; + break; +#endif // !FEATURE_NORM_IDNA_ONLY + + case ExtendedNormalizationForms.FormIdna: + if (IDNA) return; + InitializeForm(form, "normidna.nlp"); + IDNA = true; + break; + +#if !FEATURE_NORM_IDNA_ONLY + case ExtendedNormalizationForms.FormCDisallowUnassigned: + if (NFCDisallowUnassigned) return; + InitializeForm(form, "normnfc.nlp"); + NFCDisallowUnassigned = true; + break; + + case ExtendedNormalizationForms.FormDDisallowUnassigned: + if (NFDDisallowUnassigned) return; + InitializeForm(form, "normnfd.nlp"); + NFDDisallowUnassigned = true; + break; + + case ExtendedNormalizationForms.FormKCDisallowUnassigned: + if (NFKCDisallowUnassigned) return; + InitializeForm(form, "normnfkc.nlp"); + NFKCDisallowUnassigned = true; + break; + + case ExtendedNormalizationForms.FormKDDisallowUnassigned: + if (NFKDDisallowUnassigned) return; + InitializeForm(form, "normnfkd.nlp"); + NFKDDisallowUnassigned = true; + break; +#endif // !FEATURE_NORM_IDNA_ONLY + + case ExtendedNormalizationForms.FormIdnaDisallowUnassigned: + if (IDNADisallowUnassigned) return; + InitializeForm(form, "normidna.nlp"); + IDNADisallowUnassigned = true; + break; + + default: + if (Other) return; + InitializeForm(form, null); + Other = true; + break; + } + } + + internal static bool IsNormalized(String strInput, NormalizationForm normForm) + { + Contract.Requires(strInput != null); + + EnsureInitialized(normForm); + + int iError = ERROR_SUCCESS; + bool result = nativeNormalizationIsNormalizedString( + normForm, + ref iError, + strInput, + strInput.Length); + + switch(iError) + { + // Success doesn't need to do anything + case ERROR_SUCCESS: + break; + + // Do appropriate stuff for the individual errors: + case ERROR_INVALID_PARAMETER: + case ERROR_NO_UNICODE_TRANSLATION: + throw new ArgumentException( + Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex" ), + nameof(strInput)); + case ERROR_NOT_ENOUGH_MEMORY: + throw new OutOfMemoryException( + Environment.GetResourceString("Arg_OutOfMemoryException")); + default: + throw new InvalidOperationException( + Environment.GetResourceString("UnknownError_Num", iError)); + } + + return result; + } + + internal static String Normalize(String strInput, NormalizationForm normForm) + { + Contract.Requires(strInput != null); + + EnsureInitialized(normForm); + + int iError = ERROR_SUCCESS; + + // Guess our buffer size first + int iLength = nativeNormalizationNormalizeString(normForm, ref iError, strInput, strInput.Length, null, 0); + + // Could have an error (actually it'd be quite hard to have an error here) + if (iError != ERROR_SUCCESS) + { + if (iError == ERROR_INVALID_PARAMETER) + throw new ArgumentException( + Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex" ), + nameof(strInput)); + + // We shouldn't really be able to get here..., guessing length is + // a trivial math function... + // Can't really be Out of Memory, but just in case: + if (iError == ERROR_NOT_ENOUGH_MEMORY) + throw new OutOfMemoryException( + Environment.GetResourceString("Arg_OutOfMemoryException")); + + // Who knows what happened? Not us! + throw new InvalidOperationException( + Environment.GetResourceString("UnknownError_Num", iError)); + } + + // Don't break for empty strings (only possible for D & KD and not really possible at that) + if (iLength == 0) return String.Empty; + + // Someplace to stick our buffer + char[] cBuffer = null; + + for (;;) + { + // (re)allocation buffer and normalize string + cBuffer = new char[iLength]; + + iLength = nativeNormalizationNormalizeString( + normForm, + ref iError, + strInput, + strInput.Length, + cBuffer, + cBuffer.Length); + + if (iError == ERROR_SUCCESS) + break; + + // Could have an error (actually it'd be quite hard to have an error here) + switch(iError) + { + // Do appropriate stuff for the individual errors: + case ERROR_INSUFFICIENT_BUFFER: + Debug.Assert(iLength > cBuffer.Length, "Buffer overflow should have iLength > cBuffer.Length"); + continue; + + case ERROR_INVALID_PARAMETER: + case ERROR_NO_UNICODE_TRANSLATION: + // Illegal code point or order found. Ie: FFFE or D800 D800, etc. + throw new ArgumentException( + Environment.GetResourceString("Argument_InvalidCharSequence", iLength ), + nameof(strInput)); + case ERROR_NOT_ENOUGH_MEMORY: + throw new OutOfMemoryException( + Environment.GetResourceString("Arg_OutOfMemoryException")); + + default: + // We shouldn't get here... + throw new InvalidOperationException( + Environment.GetResourceString("UnknownError_Num", iError)); + } + } + + // Copy our buffer into our new string, which will be the appropriate size + return new String(cBuffer, 0, iLength); + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + unsafe private static extern int nativeNormalizationNormalizeString( + NormalizationForm normForm, ref int iError, + String lpSrcString, int cwSrcLength, + char[] lpDstString, int cwDstLength); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + unsafe private static extern bool nativeNormalizationIsNormalizedString( + NormalizationForm normForm, ref int iError, + String lpString, int cwLength); + + [SuppressUnmanagedCodeSecurity] + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] + unsafe private static extern void nativeNormalizationInitNormalization( + NormalizationForm normForm, byte* pTableData); + } +} diff --git a/src/mscorlib/src/System/Text/Normalization.cs b/src/mscorlib/src/System/Text/Normalization.cs index ce3c0c8..e7e733a 100644 --- a/src/mscorlib/src/System/Text/Normalization.cs +++ b/src/mscorlib/src/System/Text/Normalization.cs @@ -4,15 +4,6 @@ namespace System.Text { - using System; - using System.Security; - using System.Globalization; - using System.Text; - using System.Runtime.CompilerServices; - using System.Runtime.InteropServices; - using System.Runtime.Versioning; - using System.Diagnostics.Contracts; - // This is the enumeration for Normalization Forms [System.Runtime.InteropServices.ComVisible(true)] public enum NormalizationForm @@ -42,309 +33,4 @@ namespace System.Text #endif // !FEATURE_NORM_IDNA_ONLY FormIdnaDisallowUnassigned = 0x10d } - - // This internal class wraps up our normalization behavior - - internal class Normalization - { - // - // Flags that track whether given normalization form was initialized - // -#if !FEATURE_NORM_IDNA_ONLY - private static volatile bool NFC; - private static volatile bool NFD; - private static volatile bool NFKC; - private static volatile bool NFKD; -#endif // !FEATURE_NORM_IDNA_ONLY - private static volatile bool IDNA; -#if !FEATURE_NORM_IDNA_ONLY - private static volatile bool NFCDisallowUnassigned; - private static volatile bool NFDDisallowUnassigned; - private static volatile bool NFKCDisallowUnassigned; - private static volatile bool NFKDDisallowUnassigned; -#endif // !FEATURE_NORM_IDNA_ONLY - private static volatile bool IDNADisallowUnassigned; - private static volatile bool Other; - - // These are error codes we get back from the Normalization DLL - private const int ERROR_SUCCESS = 0; - private const int ERROR_NOT_ENOUGH_MEMORY = 8; - private const int ERROR_INVALID_PARAMETER = 87; - private const int ERROR_INSUFFICIENT_BUFFER = 122; - private const int ERROR_NO_UNICODE_TRANSLATION = 1113; - - [System.Security.SecurityCritical] // auto-generated - static private unsafe void InitializeForm(NormalizationForm form, String strDataFile) - { -#if FEATURE_COREFX_GLOBALIZATION - //TODO: Implement this fully. We might need a PAL here. - throw new NotImplementedException(); -#else - byte* pTables = null; - - // Normalization uses OS on Win8 - if (!Environment.IsWindows8OrAbove) - { - if (strDataFile == null) - { - // They were supposed to have a form that we know about! - throw new ArgumentException( - Environment.GetResourceString("Argument_InvalidNormalizationForm")); - } - - // Tell the DLL where to find our data - pTables = GlobalizationAssembly.GetGlobalizationResourceBytePtr( - typeof(Normalization).Assembly, strDataFile); - if (pTables == null) - { - // Unable to load the specified normalizationForm, - // tables not loaded from file - throw new ArgumentException( - Environment.GetResourceString("Argument_InvalidNormalizationForm")); - } - } - - nativeNormalizationInitNormalization(form, pTables); -#endif - } - - [System.Security.SecurityCritical] // auto-generated - static private void EnsureInitialized(NormalizationForm form) - { - switch ((ExtendedNormalizationForms)form) - { -#if !FEATURE_NORM_IDNA_ONLY - case ExtendedNormalizationForms.FormC: - if (NFC) return; - InitializeForm(form, "normnfc.nlp"); - NFC = true; - break; - - case ExtendedNormalizationForms.FormD: - if (NFD) return; - InitializeForm(form, "normnfd.nlp"); - NFD = true; - break; - - case ExtendedNormalizationForms.FormKC: - if (NFKC) return; - InitializeForm(form, "normnfkc.nlp"); - NFKC = true; - break; - - case ExtendedNormalizationForms.FormKD: - if (NFKD) return; - InitializeForm(form, "normnfkd.nlp"); - NFKD = true; - break; -#endif // !FEATURE_NORM_IDNA_ONLY - - case ExtendedNormalizationForms.FormIdna: - if (IDNA) return; - InitializeForm(form, "normidna.nlp"); - IDNA = true; - break; - -#if !FEATURE_NORM_IDNA_ONLY - case ExtendedNormalizationForms.FormCDisallowUnassigned: - if (NFCDisallowUnassigned) return; - InitializeForm(form, "normnfc.nlp"); - NFCDisallowUnassigned = true; - break; - - case ExtendedNormalizationForms.FormDDisallowUnassigned: - if (NFDDisallowUnassigned) return; - InitializeForm(form, "normnfd.nlp"); - NFDDisallowUnassigned = true; - break; - - case ExtendedNormalizationForms.FormKCDisallowUnassigned: - if (NFKCDisallowUnassigned) return; - InitializeForm(form, "normnfkc.nlp"); - NFKCDisallowUnassigned = true; - break; - - case ExtendedNormalizationForms.FormKDDisallowUnassigned: - if (NFKDDisallowUnassigned) return; - InitializeForm(form, "normnfkd.nlp"); - NFKDDisallowUnassigned = true; - break; -#endif // !FEATURE_NORM_IDNA_ONLY - - case ExtendedNormalizationForms.FormIdnaDisallowUnassigned: - if (IDNADisallowUnassigned) return; - InitializeForm(form, "normidna.nlp"); - IDNADisallowUnassigned = true; - break; - - default: - if (Other) return; - InitializeForm(form, null); - Other = true; - break; - } - } - - [System.Security.SecurityCritical] - internal static bool IsNormalized(String strInput, NormalizationForm normForm) - { - Contract.Requires(strInput != null); - - EnsureInitialized(normForm); - - int iError = ERROR_SUCCESS; - bool result = nativeNormalizationIsNormalizedString( - normForm, - ref iError, - strInput, - strInput.Length); - - switch(iError) - { - // Success doesn't need to do anything - case ERROR_SUCCESS: - break; - - // Do appropriate stuff for the individual errors: - case ERROR_INVALID_PARAMETER: - case ERROR_NO_UNICODE_TRANSLATION: - throw new ArgumentException( - Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex" ), - "strInput"); - case ERROR_NOT_ENOUGH_MEMORY: - throw new OutOfMemoryException( - Environment.GetResourceString("Arg_OutOfMemoryException")); - default: - throw new InvalidOperationException( - Environment.GetResourceString("UnknownError_Num", iError)); - } - - return result; - } - - [System.Security.SecurityCritical] - internal static String Normalize(String strInput, NormalizationForm normForm) - { - Contract.Requires(strInput != null); - - EnsureInitialized(normForm); - - int iError = ERROR_SUCCESS; - - // Guess our buffer size first - int iLength = nativeNormalizationNormalizeString(normForm, ref iError, strInput, strInput.Length, null, 0); - - // Could have an error (actually it'd be quite hard to have an error here) - if (iError != ERROR_SUCCESS) - { - if (iError == ERROR_INVALID_PARAMETER) - throw new ArgumentException( - Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex" ), - "strInput"); - - // We shouldn't really be able to get here..., guessing length is - // a trivial math function... - // Can't really be Out of Memory, but just in case: - if (iError == ERROR_NOT_ENOUGH_MEMORY) - throw new OutOfMemoryException( - Environment.GetResourceString("Arg_OutOfMemoryException")); - - // Who knows what happened? Not us! - throw new InvalidOperationException( - Environment.GetResourceString("UnknownError_Num", iError)); - } - - // Don't break for empty strings (only possible for D & KD and not really possible at that) - if (iLength == 0) return String.Empty; - - // Someplace to stick our buffer - char[] cBuffer = null; - - for (;;) - { - // (re)allocation buffer and normalize string - cBuffer = new char[iLength]; - - iLength = nativeNormalizationNormalizeString( - normForm, - ref iError, - strInput, - strInput.Length, - cBuffer, - cBuffer.Length); - - if (iError == ERROR_SUCCESS) - break; - - // Could have an error (actually it'd be quite hard to have an error here) - switch(iError) - { - // Do appropriate stuff for the individual errors: - case ERROR_INSUFFICIENT_BUFFER: - Contract.Assert(iLength > cBuffer.Length, "Buffer overflow should have iLength > cBuffer.Length"); - continue; - - case ERROR_INVALID_PARAMETER: - case ERROR_NO_UNICODE_TRANSLATION: - // Illegal code point or order found. Ie: FFFE or D800 D800, etc. - throw new ArgumentException( - Environment.GetResourceString("Argument_InvalidCharSequence", iLength ), - "strInput"); - case ERROR_NOT_ENOUGH_MEMORY: - throw new OutOfMemoryException( - Environment.GetResourceString("Arg_OutOfMemoryException")); - - default: - // We shouldn't get here... - throw new InvalidOperationException( - Environment.GetResourceString("UnknownError_Num", iError)); - } - } - - // Copy our buffer into our new string, which will be the appropriate size - return new String(cBuffer, 0, iLength); - } - -#if !FEATURE_COREFX_GLOBALIZATION - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - unsafe private static extern int nativeNormalizationNormalizeString( - NormalizationForm normForm, ref int iError, - String lpSrcString, int cwSrcLength, - char[] lpDstString, int cwDstLength); - - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - unsafe private static extern bool nativeNormalizationIsNormalizedString( - NormalizationForm normForm, ref int iError, - String lpString, int cwLength); - - [System.Security.SecurityCritical] // auto-generated - [SuppressUnmanagedCodeSecurity] - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - unsafe private static extern void nativeNormalizationInitNormalization( - NormalizationForm normForm, byte* pTableData); -#else - unsafe private static int nativeNormalizationNormalizeString( - NormalizationForm normForm, ref int iError, - String lpSrcString, int cwSrcLength, - char[] lpDstString, int cwDstLength) - { - throw new NotImplementedException(); - } - - unsafe private static bool nativeNormalizationIsNormalizedString( - NormalizationForm normForm, ref int iError, - String lpString, int cwLength) - { - throw new NotImplementedException(); - } - - unsafe private static void nativeNormalizationInitNormalization( - NormalizationForm normForm, byte* pTableData) - { - throw new NotImplementedException(); - } -#endif - } } diff --git a/src/mscorlib/src/System/Text/SBCSCodePageEncoding.cs b/src/mscorlib/src/System/Text/SBCSCodePageEncoding.cs index ce611d8..8b07149 100644 --- a/src/mscorlib/src/System/Text/SBCSCodePageEncoding.cs +++ b/src/mscorlib/src/System/Text/SBCSCodePageEncoding.cs @@ -6,6 +6,7 @@ namespace System.Text { using System; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Text; using System.Threading; @@ -20,13 +21,10 @@ namespace System.Text { // Pointers to our memory section parts [NonSerialized] - [SecurityCritical] unsafe char* mapBytesToUnicode = null; // char 256 [NonSerialized] - [SecurityCritical] unsafe byte* mapUnicodeToBytes = null; // byte 65536 [NonSerialized] - [SecurityCritical] unsafe int* mapCodePageCached = null; // to remember which CP is cached const char UNKNOWN_CHAR=(char)0xFFFD; @@ -37,23 +35,20 @@ namespace System.Text [NonSerialized] char charUnknown; - [System.Security.SecurityCritical] // auto-generated public SBCSCodePageEncoding(int codePage) : this(codePage, codePage) { } - [System.Security.SecurityCritical] // auto-generated internal SBCSCodePageEncoding(int codePage, int dataCodePage) : base(codePage, dataCodePage) { } // Constructor called by serialization. // Note: We use the base GetObjectData however - [System.Security.SecurityCritical] // auto-generated internal SBCSCodePageEncoding(SerializationInfo info, StreamingContext context) : base(0) { // Actually this can't ever get called, CodePageEncoding is our proxy - Contract.Assert(false, "Didn't expect to make it to SBCSCodePageEncoding serialization constructor"); + Debug.Assert(false, "Didn't expect to make it to SBCSCodePageEncoding serialization constructor"); throw new ArgumentNullException("this"); } @@ -69,11 +64,10 @@ namespace System.Text // byte < 0x20 means skip the next n positions. (Where n is the byte #) // byte == 1 means that next word is another unicode code point # // byte == 0 is unknown. (doesn't override initial WCHAR[256] table! - [System.Security.SecurityCritical] // auto-generated protected override unsafe void LoadManagedCodePage() { // Should be loading OUR code page - Contract.Assert(pCodePage->CodePage == this.dataTableCodePage, + Debug.Assert(pCodePage->CodePage == this.dataTableCodePage, "[SBCSCodePageEncoding.LoadManagedCodePage]Expected to load data table code page"); // Make sure we're really a 1 byte code page @@ -96,7 +90,7 @@ namespace System.Text // If its cached (& filled in) we don't have to do anything else if (*mapCodePageCached != 0) { - Contract.Assert(*mapCodePageCached == this.dataTableCodePage, + Debug.Assert(*mapCodePageCached == this.dataTableCodePage, "[DBCSCodePageEncoding.LoadManagedCodePage]Expected mapped section cached page to be same as data table code page. Cached : " + *mapCodePageCached + " Expected:" + this.dataTableCodePage); @@ -151,7 +145,6 @@ namespace System.Text } // Read in our best fit table - [System.Security.SecurityCritical] // auto-generated protected unsafe override void ReadBestFitTable() { // Lock so we don't confuse ourselves. @@ -180,7 +173,7 @@ namespace System.Text while ((byteTemp = *((ushort*)pData)) != 0) { - Contract.Assert(arrayTemp[byteTemp] == UNKNOWN_CHAR, String.Format(CultureInfo.InvariantCulture, + Debug.Assert(arrayTemp[byteTemp] == UNKNOWN_CHAR, String.Format(CultureInfo.InvariantCulture, "[SBCSCodePageEncoding::ReadBestFitTable] Expected unallocated byte (not 0x{2:X2}) for best fit byte at 0x{0:X2} for code page {1}", byteTemp, CodePage, (int)arrayTemp[byteTemp])); pData += 2; @@ -281,7 +274,7 @@ namespace System.Text arrayTemp[iBestFitCount++] = mapBytesToUnicode[input]; // This won't work if it won't round trip. - Contract.Assert(arrayTemp[iBestFitCount-1] != (char)0, + Debug.Assert(arrayTemp[iBestFitCount-1] != (char)0, String.Format(CultureInfo.InvariantCulture, "[SBCSCodePageEncoding.ReadBestFitTable] No valid Unicode value {0:X4} for round trip bytes {1:X4}, encoding {2}", (int)mapBytesToUnicode[input], (int)input, CodePage)); @@ -299,15 +292,14 @@ namespace System.Text // GetByteCount // Note: We start by assuming that the output will be the same as count. Having // an encoder or fallback may change that assumption - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS encoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already - Contract.Assert(count >= 0, "[SBCSCodePageEncoding.GetByteCount]count is negative"); - Contract.Assert(chars != null, "[SBCSCodePageEncoding.GetByteCount]chars is null"); + Debug.Assert(count >= 0, "[SBCSCodePageEncoding.GetByteCount]count is negative"); + Debug.Assert(chars != null, "[SBCSCodePageEncoding.GetByteCount]chars is null"); // Assert because we shouldn't be able to have a null encoder. - Contract.Assert(encoderFallback != null, "[SBCSCodePageEncoding.GetByteCount]Attempting to use null fallback"); + Debug.Assert(encoderFallback != null, "[SBCSCodePageEncoding.GetByteCount]Attempting to use null fallback"); CheckMemorySection(); @@ -319,12 +311,12 @@ namespace System.Text if (encoder != null) { charLeftOver = encoder.charLeftOver; - Contract.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver), + Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver), "[SBCSCodePageEncoding.GetByteCount]leftover character should be high surrogate"); fallback = encoder.Fallback as EncoderReplacementFallback; // Verify that we have no fallbackbuffer, actually for SBCS this is always empty, so just assert - Contract.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer || + Debug.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer || encoder.FallbackBuffer.Remaining == 0, "[SBCSCodePageEncoding.GetByteCount]Expected empty fallback buffer at start"); } @@ -363,7 +355,7 @@ namespace System.Text { // Since left over char was a surrogate, it'll have to be fallen back. // Get Fallback - Contract.Assert(encoder != null, "[SBCSCodePageEncoding.GetByteCount]Expect to have encoder if we have a charLeftOver"); + Debug.Assert(encoder != null, "[SBCSCodePageEncoding.GetByteCount]Expect to have encoder if we have a charLeftOver"); fallbackBuffer = encoder.FallbackBuffer; fallbackBuffer.InternalInitialize(chars, charEnd, encoder, false); @@ -414,24 +406,23 @@ namespace System.Text byteCount++; } - Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, + Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[SBCSEncoding.GetByteCount]Expected Empty fallback buffer at end"); return (int)byteCount; } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS encoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already - Contract.Assert(bytes != null, "[SBCSCodePageEncoding.GetBytes]bytes is null"); - Contract.Assert(byteCount >= 0, "[SBCSCodePageEncoding.GetBytes]byteCount is negative"); - Contract.Assert(chars != null, "[SBCSCodePageEncoding.GetBytes]chars is null"); - Contract.Assert(charCount >= 0, "[SBCSCodePageEncoding.GetBytes]charCount is negative"); + Debug.Assert(bytes != null, "[SBCSCodePageEncoding.GetBytes]bytes is null"); + Debug.Assert(byteCount >= 0, "[SBCSCodePageEncoding.GetBytes]byteCount is negative"); + Debug.Assert(chars != null, "[SBCSCodePageEncoding.GetBytes]chars is null"); + Debug.Assert(charCount >= 0, "[SBCSCodePageEncoding.GetBytes]charCount is negative"); // Assert because we shouldn't be able to have a null encoder. - Contract.Assert(encoderFallback != null, "[SBCSCodePageEncoding.GetBytes]Attempting to use null encoder fallback"); + Debug.Assert(encoderFallback != null, "[SBCSCodePageEncoding.GetBytes]Attempting to use null encoder fallback"); CheckMemorySection(); @@ -443,12 +434,12 @@ namespace System.Text if (encoder != null) { charLeftOver = encoder.charLeftOver; - Contract.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver), + Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver), "[SBCSCodePageEncoding.GetBytes]leftover character should be high surrogate"); fallback = encoder.Fallback as EncoderReplacementFallback; // Verify that we have no fallbackbuffer, for SBCS its always empty, so just assert - Contract.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer || + Debug.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer || encoder.FallbackBuffer.Remaining == 0, "[SBCSCodePageEncoding.GetBytes]Expected empty fallback buffer at start"); // if (encoder.m_throwOnOverflow && encoder.InternalHasFallbackBuffer && @@ -545,7 +536,7 @@ namespace System.Text { // Since left over char was a surrogate, it'll have to be fallen back. // Get Fallback - Contract.Assert(encoder != null, "[SBCSCodePageEncoding.GetBytes]Expect to have encoder if we have a charLeftOver"); + Debug.Assert(encoder != null, "[SBCSCodePageEncoding.GetBytes]Expect to have encoder if we have a charLeftOver"); fallbackBuffer = encoder.FallbackBuffer; fallbackBuffer.InternalInitialize(chars, charEnd, encoder, true); @@ -598,7 +589,7 @@ namespace System.Text if (fallbackBuffer.Remaining > byteEnd - bytes) { // Didn't use this char, reset it - Contract.Assert(chars > charStart, + Debug.Assert(chars > charStart, "[SBCSCodePageEncoding.GetBytes]Expected chars to have advanced (fallback)"); chars--; fallbackBuffer.InternalReset(); @@ -615,11 +606,11 @@ namespace System.Text if (bytes >= byteEnd) { // didn't use this char, we'll throw or use buffer - Contract.Assert(fallbackBuffer == null || fallbackBuffer.bFallingBack == false, + Debug.Assert(fallbackBuffer == null || fallbackBuffer.bFallingBack == false, "[SBCSCodePageEncoding.GetBytes]Expected to NOT be falling back"); if (fallbackBuffer == null || fallbackBuffer.bFallingBack == false) { - Contract.Assert(chars > charStart, + Debug.Assert(chars > charStart, "[SBCSCodePageEncoding.GetBytes]Expected chars to have advanced (normal)"); chars--; // don't use last char } @@ -645,19 +636,18 @@ namespace System.Text } // Expect Empty fallback buffer for SBCS - Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, + Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[SBCSEncoding.GetBytes]Expected Empty fallback buffer at end"); return (int)(bytes - byteStart); } // This is internal and called by something else, - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS decoder) { // Just assert, we're called internally so these should be safe, checked already - Contract.Assert(bytes != null, "[SBCSCodePageEncoding.GetCharCount]bytes is null"); - Contract.Assert(count >= 0, "[SBCSCodePageEncoding.GetCharCount]byteCount is negative"); + Debug.Assert(bytes != null, "[SBCSCodePageEncoding.GetCharCount]bytes is null"); + Debug.Assert(count >= 0, "[SBCSCodePageEncoding.GetCharCount]byteCount is negative"); CheckMemorySection(); @@ -676,7 +666,7 @@ namespace System.Text { fallback = decoder.Fallback as DecoderReplacementFallback; bUseBestFit = decoder.Fallback.IsMicrosoftBestFitFallback; - Contract.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer || + Debug.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[SBCSCodePageEncoding.GetChars]Expected empty fallback buffer at start"); } @@ -729,22 +719,21 @@ namespace System.Text } // Fallback buffer must be empty - Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, + Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[SBCSEncoding.GetCharCount]Expected Empty fallback buffer at end"); // Converted sequence is same length as input return charCount; } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetChars(byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS decoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already - Contract.Assert(bytes != null, "[SBCSCodePageEncoding.GetChars]bytes is null"); - Contract.Assert(byteCount >= 0, "[SBCSCodePageEncoding.GetChars]byteCount is negative"); - Contract.Assert(chars != null, "[SBCSCodePageEncoding.GetChars]chars is null"); - Contract.Assert(charCount >= 0, "[SBCSCodePageEncoding.GetChars]charCount is negative"); + Debug.Assert(bytes != null, "[SBCSCodePageEncoding.GetChars]bytes is null"); + Debug.Assert(byteCount >= 0, "[SBCSCodePageEncoding.GetChars]byteCount is negative"); + Debug.Assert(chars != null, "[SBCSCodePageEncoding.GetChars]chars is null"); + Debug.Assert(charCount >= 0, "[SBCSCodePageEncoding.GetChars]charCount is negative"); CheckMemorySection(); @@ -768,7 +757,7 @@ namespace System.Text { fallback = decoder.Fallback as DecoderReplacementFallback; bUseBestFit = decoder.Fallback.IsMicrosoftBestFitFallback; - Contract.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer || + Debug.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[SBCSCodePageEncoding.GetChars]Expected empty fallback buffer at start"); } @@ -848,7 +837,7 @@ namespace System.Text } // Use fallback buffer - Contract.Assert(bytes > byteStart, + Debug.Assert(bytes > byteStart, "[SBCSCodePageEncoding.GetChars]Expected bytes to have advanced already (unknown byte)"); byteBuffer[0] = *(bytes - 1); // Fallback adds fallback to chars, but doesn't increment chars unless the whole thing fits. @@ -866,7 +855,7 @@ namespace System.Text // Make sure we have buffer space if (chars >= charEnd) { - Contract.Assert(bytes > byteStart, + Debug.Assert(bytes > byteStart, "[SBCSCodePageEncoding.GetChars]Expected bytes to have advanced already (known byte)"); bytes--; // unused byte ThrowCharsOverflow(decoder, bytes == byteStart); // throw? @@ -883,7 +872,7 @@ namespace System.Text decoder.m_bytesUsed = (int)(bytes - byteStart); // Expect Empty fallback buffer for GetChars - Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, + Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[SBCSEncoding.GetChars]Expected Empty fallback buffer at end"); return (int)(chars - charStart); @@ -892,7 +881,7 @@ namespace System.Text public override int GetMaxByteCount(int charCount) { if (charCount < 0) - throw new ArgumentOutOfRangeException("charCount", + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -905,14 +894,14 @@ namespace System.Text // 1 to 1 for most characters. Only surrogates with fallbacks have less. if (byteCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); return (int)byteCount; } public override int GetMaxCharCount(int byteCount) { if (byteCount < 0) - throw new ArgumentOutOfRangeException("byteCount", + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -924,7 +913,7 @@ namespace System.Text charCount *= DecoderFallback.MaxCharCount; if (charCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow")); return (int)charCount; } diff --git a/src/mscorlib/src/System/Text/StringBuilder.cs b/src/mscorlib/src/System/Text/StringBuilder.cs index 8026c98..f20146f 100644 --- a/src/mscorlib/src/System/Text/StringBuilder.cs +++ b/src/mscorlib/src/System/Text/StringBuilder.cs @@ -20,7 +20,9 @@ namespace System.Text { using System.Security; using System.Threading; using System.Globalization; + using System.Diagnostics; using System.Diagnostics.Contracts; + using System.Collections.Generic; // This class represents a mutable string. It is convenient for situations in // which it is desirable to modify a string, perhaps by removing, replacing, or @@ -55,7 +57,7 @@ namespace System.Text { internal char[] m_ChunkChars; // The characters in this block internal StringBuilder m_ChunkPrevious; // Link to the block logically before this block internal int m_ChunkLength; // The index in m_ChunkChars that represent the end of the block - internal int m_ChunkOffset; // The logial offset (sum of all characters in previous blocks) + internal int m_ChunkOffset; // The logical offset (sum of all characters in previous blocks) internal int m_MaxCapacity = 0; // @@ -117,18 +119,17 @@ namespace System.Text { // Creates a new string builder from the specifed substring with the specified // capacity. The maximum number of characters is set by capacity. // - [System.Security.SecuritySafeCritical] // auto-generated public StringBuilder(String value, int startIndex, int length, int capacity) { if (capacity<0) { - throw new ArgumentOutOfRangeException("capacity", - Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", "capacity")); + throw new ArgumentOutOfRangeException(nameof(capacity), + Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", nameof(capacity))); } if (length<0) { - throw new ArgumentOutOfRangeException("length", - Environment.GetResourceString("ArgumentOutOfRange_MustBeNonNegNum", "length")); + throw new ArgumentOutOfRangeException(nameof(length), + Environment.GetResourceString("ArgumentOutOfRange_MustBeNonNegNum", nameof(length))); } if (startIndex<0) { - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); } Contract.EndContractBlock(); @@ -136,7 +137,7 @@ namespace System.Text { value = String.Empty; } if (startIndex > value.Length - length) { - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_IndexLength")); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_IndexLength")); } m_MaxCapacity = Int32.MaxValue; if (capacity == 0) { @@ -158,14 +159,14 @@ namespace System.Text { // and a maximum capacity of maxCapacity. public StringBuilder(int capacity, int maxCapacity) { if (capacity>maxCapacity) { - throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_Capacity")); + throw new ArgumentOutOfRangeException(nameof(capacity), Environment.GetResourceString("ArgumentOutOfRange_Capacity")); } if (maxCapacity<1) { - throw new ArgumentOutOfRangeException("maxCapacity", Environment.GetResourceString("ArgumentOutOfRange_SmallMaxCapacity")); + throw new ArgumentOutOfRangeException(nameof(maxCapacity), Environment.GetResourceString("ArgumentOutOfRange_SmallMaxCapacity")); } if (capacity<0) { - throw new ArgumentOutOfRangeException("capacity", - Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", "capacity")); + throw new ArgumentOutOfRangeException(nameof(capacity), + Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", nameof(capacity))); } Contract.EndContractBlock(); @@ -177,10 +178,9 @@ namespace System.Text { m_ChunkChars = new char[capacity]; } - [System.Security.SecurityCritical] // auto-generated private StringBuilder(SerializationInfo info, StreamingContext context) { if (info == null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); int persistedCapacity = 0; @@ -240,11 +240,10 @@ namespace System.Text { VerifyClassInvariant(); } - [System.Security.SecurityCritical] // auto-generated void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); @@ -264,21 +263,21 @@ namespace System.Text { for (; ; ) { // All blocks have copy of the maxCapacity. - Contract.Assert(currentBlock.m_MaxCapacity == maxCapacity, "Bad maxCapacity"); - Contract.Assert(currentBlock.m_ChunkChars != null, "Empty Buffer"); + Debug.Assert(currentBlock.m_MaxCapacity == maxCapacity, "Bad maxCapacity"); + Debug.Assert(currentBlock.m_ChunkChars != null, "Empty Buffer"); - Contract.Assert(currentBlock.m_ChunkLength <= currentBlock.m_ChunkChars.Length, "Out of range length"); - Contract.Assert(currentBlock.m_ChunkLength >= 0, "Negative length"); - Contract.Assert(currentBlock.m_ChunkOffset >= 0, "Negative offset"); + Debug.Assert(currentBlock.m_ChunkLength <= currentBlock.m_ChunkChars.Length, "Out of range length"); + Debug.Assert(currentBlock.m_ChunkLength >= 0, "Negative length"); + Debug.Assert(currentBlock.m_ChunkOffset >= 0, "Negative offset"); StringBuilder prevBlock = currentBlock.m_ChunkPrevious; if (prevBlock == null) { - Contract.Assert(currentBlock.m_ChunkOffset == 0, "First chunk's offset is not 0"); + Debug.Assert(currentBlock.m_ChunkOffset == 0, "First chunk's offset is not 0"); break; } // There are no gaps in the blocks. - Contract.Assert(currentBlock.m_ChunkOffset == prevBlock.m_ChunkOffset + prevBlock.m_ChunkLength, "There is a gap between chunks!"); + Debug.Assert(currentBlock.m_ChunkOffset == prevBlock.m_ChunkOffset + prevBlock.m_ChunkLength, "There is a gap between chunks!"); currentBlock = prevBlock; } } @@ -287,13 +286,13 @@ namespace System.Text { get { return m_ChunkChars.Length + m_ChunkOffset; } set { if (value < 0) { - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NegativeCapacity")); + throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_NegativeCapacity")); } if (value > MaxCapacity) { - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_Capacity")); + throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_Capacity")); } if (value < Length) { - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity")); + throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity")); } Contract.EndContractBlock(); @@ -317,7 +316,7 @@ namespace System.Text { // public int EnsureCapacity(int capacity) { if (capacity < 0) { - throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_NegativeCapacity")); + throw new ArgumentOutOfRangeException(nameof(capacity), Environment.GetResourceString("ArgumentOutOfRange_NegativeCapacity")); } Contract.EndContractBlock(); @@ -326,7 +325,6 @@ namespace System.Text { return Capacity; } - [System.Security.SecuritySafeCritical] // auto-generated public override String ToString() { Contract.Ensures(Contract.Result() != null); @@ -357,7 +355,7 @@ namespace System.Text { } else { - throw new ArgumentOutOfRangeException("chunkLength", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(chunkLength), Environment.GetResourceString("ArgumentOutOfRange_Index")); } } chunk = chunk.m_ChunkPrevious; @@ -370,26 +368,25 @@ namespace System.Text { // Converts a substring of this string builder to a String. - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(int startIndex, int length) { Contract.Ensures(Contract.Result() != null); int currentLength = this.Length; if (startIndex < 0) { - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); } if (startIndex > currentLength) { - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndexLargerThanLength")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_StartIndexLargerThanLength")); } if (length < 0) { - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NegativeLength")); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_NegativeLength")); } if (startIndex > (currentLength - length)) { - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_IndexLength")); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_IndexLength")); } VerifyClassInvariant(); @@ -433,7 +430,7 @@ namespace System.Text { } else { - throw new ArgumentOutOfRangeException("chunkCount", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(chunkCount), Environment.GetResourceString("ArgumentOutOfRange_Index")); } } } @@ -463,11 +460,11 @@ namespace System.Text { set { //If the new length is less than 0 or greater than our Maximum capacity, bail. if (value<0) { - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NegativeLength")); + throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_NegativeLength")); } if (value>MaxCapacity) { - throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity")); + throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity")); } Contract.EndContractBlock(); @@ -477,7 +474,7 @@ namespace System.Text { { m_ChunkLength = 0; m_ChunkOffset = 0; - Contract.Assert(Capacity >= originalCapacity, "setting the Length should never decrease the Capacity"); + Debug.Assert(Capacity >= originalCapacity, "setting the Length should never decrease the Capacity"); return; } @@ -499,7 +496,7 @@ namespace System.Text { int newLen = originalCapacity - chunk.m_ChunkOffset; char[] newArray = new char[newLen]; - Contract.Assert(newLen > chunk.m_ChunkChars.Length, "the new chunk should be larger than the one it is replacing"); + Debug.Assert(newLen > chunk.m_ChunkChars.Length, "the new chunk should be larger than the one it is replacing"); Array.Copy(chunk.m_ChunkChars, newArray, chunk.m_ChunkLength); m_ChunkChars = newArray; @@ -509,7 +506,7 @@ namespace System.Text { m_ChunkLength = value - chunk.m_ChunkOffset; VerifyClassInvariant(); } - Contract.Assert(Capacity >= originalCapacity, "setting the Length should never decrease the Capacity"); + Debug.Assert(Capacity >= originalCapacity, "setting the Length should never decrease the Capacity"); } } @@ -539,13 +536,13 @@ namespace System.Text { if (indexInBlock >= 0) { if (indexInBlock >= chunk.m_ChunkLength) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); chunk.m_ChunkChars[indexInBlock] = value; return; } chunk = chunk.m_ChunkPrevious; if (chunk == null) - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); } } } @@ -553,7 +550,7 @@ namespace System.Text { // Appends a character at the end of this string builder. The capacity is adjusted as needed. public StringBuilder Append(char value, int repeatCount) { if (repeatCount<0) { - throw new ArgumentOutOfRangeException("repeatCount", Environment.GetResourceString("ArgumentOutOfRange_NegativeCount")); + throw new ArgumentOutOfRangeException(nameof(repeatCount), Environment.GetResourceString("ArgumentOutOfRange_NegativeCount")); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -561,6 +558,14 @@ namespace System.Text { if (repeatCount==0) { return this; } + + // this is where we can check if the repeatCount will put us over m_MaxCapacity + // We are doing the check here to prevent the corruption of the StringBuilder. + int newLength = Length + repeatCount; + if (newLength > m_MaxCapacity || newLength < repeatCount) { + throw new ArgumentOutOfRangeException(nameof(repeatCount), Environment.GetResourceString("ArgumentOutOfRange_LengthGreaterThanCapacity")); + } + int idx = m_ChunkLength; while (repeatCount > 0) { @@ -573,7 +578,7 @@ namespace System.Text { { m_ChunkLength = idx; ExpandByABlock(repeatCount); - Contract.Assert(m_ChunkLength == 0, "Expand should create a new block"); + Debug.Assert(m_ChunkLength == 0, "Expand should create a new block"); idx = 0; } } @@ -583,10 +588,9 @@ namespace System.Text { } // Appends an array of characters at the end of this string builder. The capacity is adjusted as needed. - [System.Security.SecuritySafeCritical] // auto-generated public StringBuilder Append(char[] value, int startIndex, int charCount) { if (startIndex < 0) { - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); } if (charCount<0) { throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); @@ -598,7 +602,7 @@ namespace System.Text { if (startIndex == 0 && charCount == 0) { return this; } - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } if (charCount > value.Length - startIndex) { throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Index")); @@ -620,7 +624,6 @@ namespace System.Text { // Appends a copy of this string at the end of this string builder. - [System.Security.SecuritySafeCritical] // auto-generated public StringBuilder Append(String value) { Contract.Ensures(Contract.Result() != null); @@ -659,7 +662,6 @@ namespace System.Text { // We put this fixed in its own helper to avoid the cost zero initing valueChars in the // case we don't actually use it. - [System.Security.SecuritySafeCritical] // auto-generated private void AppendHelper(string value) { unsafe { fixed (char* valueChars = value) @@ -668,23 +670,20 @@ namespace System.Text { } [MethodImplAttribute(MethodImplOptions.InternalCall)] - [SecurityCritical] internal unsafe extern void ReplaceBufferInternal(char* newBuffer, int newLength); [MethodImplAttribute(MethodImplOptions.InternalCall)] - [SecurityCritical] internal unsafe extern void ReplaceBufferAnsiInternal(sbyte* newBuffer, int newLength); // Appends a copy of the characters in value from startIndex to startIndex + // count at the end of this string builder. - [System.Security.SecuritySafeCritical] // auto-generated public StringBuilder Append(String value, int startIndex, int count) { if (startIndex < 0) { - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); } if (count < 0) { - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_GenericPositive")); } Contract.Ensures(Contract.Result() != null); @@ -694,7 +693,7 @@ namespace System.Text { if (startIndex == 0 && count == 0) { return this; } - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } if (count == 0) { @@ -702,7 +701,7 @@ namespace System.Text { } if (startIndex > value.Length - count) { - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); } unsafe @@ -730,19 +729,18 @@ namespace System.Text { } [System.Runtime.InteropServices.ComVisible(false)] - [SecuritySafeCritical] public void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count) { if (destination == null) { - throw new ArgumentNullException("destination"); + throw new ArgumentNullException(nameof(destination)); } if (count < 0) { - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("Arg_NegativeArgCount")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("Arg_NegativeArgCount")); } if (destinationIndex < 0) { - throw new ArgumentOutOfRangeException("destinationIndex", - Environment.GetResourceString("ArgumentOutOfRange_MustBeNonNegNum", "destinationIndex")); + throw new ArgumentOutOfRangeException(nameof(destinationIndex), + Environment.GetResourceString("ArgumentOutOfRange_MustBeNonNegNum", nameof(destinationIndex))); } if (destinationIndex > destination.Length - count) { @@ -750,7 +748,7 @@ namespace System.Text { } if ((uint)sourceIndex > (uint)Length) { - throw new ArgumentOutOfRangeException("sourceIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(sourceIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); } if (sourceIndex > Length - count) { @@ -794,10 +792,9 @@ namespace System.Text { // The capacity is adjusted as needed. If value equals String.Empty, this // string builder is not changed. // - [System.Security.SecuritySafeCritical] // auto-generated public StringBuilder Insert(int index, String value, int count) { if (count < 0) { - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -805,7 +802,7 @@ namespace System.Text { //Range check the index. int currentLength = Length; if ((uint)index > (uint)currentLength) { - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); } //If value is null, empty or count is 0, do nothing. This is ECMA standard. @@ -819,7 +816,7 @@ namespace System.Text { if (insertingChars > MaxCapacity - this.Length) { throw new OutOfMemoryException(); } - Contract.Assert(insertingChars + this.Length < Int32.MaxValue); + Debug.Assert(insertingChars + this.Length < Int32.MaxValue); StringBuilder chunk; int indexInChunk; @@ -843,11 +840,11 @@ namespace System.Text { // public StringBuilder Remove(int startIndex, int length) { if (length<0) { - throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NegativeLength")); + throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_NegativeLength")); } if (startIndex<0) { - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); } if (length > Length - startIndex) { @@ -989,7 +986,6 @@ namespace System.Text { } // Appends all of the characters in value to the current instance. - [System.Security.SecuritySafeCritical] // auto-generated public StringBuilder Append(char[] value) { Contract.Ensures(Contract.Result() != null); @@ -1003,6 +999,88 @@ namespace System.Text { return this; } + // Append joined values with a separator between each value. + public unsafe StringBuilder AppendJoin(char separator, params T[] values) + { + // Defer argument validation to the internal function + return AppendJoinCore(&separator, 1, values); + } + + public unsafe StringBuilder AppendJoin(string separator, params T[] values) + { + separator = separator ?? string.Empty; + fixed (char* pSeparator = separator) + { + // Defer argument validation to the internal function + return AppendJoinCore(pSeparator, separator.Length, values); + } + } + + public unsafe StringBuilder AppendJoin(char separator, IEnumerable values) + { + // Defer argument validation to the internal function + return AppendJoinCore(&separator, 1, values); + } + + public unsafe StringBuilder AppendJoin(string separator, IEnumerable values) + { + separator = separator ?? string.Empty; + fixed (char* pSeparator = separator) + { + // Defer argument validation to the internal function + return AppendJoinCore(pSeparator, separator.Length, values); + } + } + + private unsafe StringBuilder AppendJoinCore(char* separator, int separatorLength, params T[] values) + { + if (values == null) + throw new ArgumentNullException(nameof(values)); + Contract.Ensures(Contract.Result() != null); + + if (values.Length == 0) + return this; + + var value = values[0]; + if (value != null) + Append(value.ToString()); + + for (var i = 1; i < values.Length; i++) + { + Append(separator, separatorLength); + value = values[i]; + if (value != null) + Append(value.ToString()); + } + return this; + } + + private unsafe StringBuilder AppendJoinCore(char* separator, int separatorLength, IEnumerable values) + { + if (values == null) + throw new ArgumentNullException(nameof(values)); + Contract.Ensures(Contract.Result() != null); + + using (var en = values.GetEnumerator()) + { + if (!en.MoveNext()) + return this; + + var value = en.Current; + if (value != null) + Append(value.ToString()); + + while (en.MoveNext()) + { + Append(separator, separatorLength); + value = en.Current; + if (value != null) + Append(value.ToString()); + } + } + return this; + } + /*====================================Insert==================================== ** ==============================================================================*/ @@ -1012,10 +1090,9 @@ namespace System.Text { // The capacity is adjusted as needed. If value equals String.Empty, the // StringBuilder is not changed. // - [System.Security.SecuritySafeCritical] // auto-generated public StringBuilder Insert(int index, String value) { if ((uint)index > (uint)Length) { - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -1075,7 +1152,6 @@ namespace System.Text { // the buffer at index. Existing characters are shifted to make room for the new text. // The capacity is adjusted as needed. If value equals String.Empty, the // StringBuilder is not changed. - [SecuritySafeCritical] public StringBuilder Insert(int index, char value) { Contract.Ensures(Contract.Result() != null); @@ -1092,7 +1168,7 @@ namespace System.Text { // public StringBuilder Insert(int index, char[] value) { if ((uint)index > (uint)Length) { - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -1106,13 +1182,12 @@ namespace System.Text { // value inserted into the buffer at index. Existing characters are shifted // to make room for the new text and capacity is adjusted as required. If value is null, the StringBuilder // is unchanged. Characters are taken from value starting at position startIndex. - [System.Security.SecuritySafeCritical] // auto-generated public StringBuilder Insert(int index, char[] value, int startIndex, int charCount) { Contract.Ensures(Contract.Result() != null); int currentLength = Length; if ((uint)index > (uint)currentLength) { - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); } //If they passed in a null char array, just jump out quickly. @@ -1121,12 +1196,12 @@ namespace System.Text { { return this; } - throw new ArgumentNullException("value", Environment.GetResourceString("ArgumentNull_String")); + throw new ArgumentNullException(nameof(value), Environment.GetResourceString("ArgumentNull_String")); } //Range check the array. if (startIndex < 0) { - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_StartIndex")); } if (charCount < 0) { @@ -1134,7 +1209,7 @@ namespace System.Text { } if (startIndex > value.Length - charCount) { - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); } if (charCount > 0) @@ -1255,7 +1330,7 @@ namespace System.Text { { // To preserve the original exception behavior, throw an exception about format if both // args and format are null. The actual null check for format is in AppendFormatHelper. - throw new ArgumentNullException((format == null) ? "format" : "args"); + throw new ArgumentNullException((format == null) ? nameof(format) : nameof(args)); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -1283,7 +1358,7 @@ namespace System.Text { { // To preserve the original exception behavior, throw an exception about format if both // args and format are null. The actual null check for format is in AppendFormatHelper. - throw new ArgumentNullException((format == null) ? "format" : "args"); + throw new ArgumentNullException((format == null) ? nameof(format) : nameof(args)); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -1301,7 +1376,7 @@ namespace System.Text { internal StringBuilder AppendFormatHelper(IFormatProvider provider, String format, ParamsArray args) { if (format == null) { - throw new ArgumentNullException("format"); + throw new ArgumentNullException(nameof(format)); } Contract.Ensures(Contract.Result() != null); Contract.EndContractBlock(); @@ -1582,19 +1657,19 @@ namespace System.Text { int currentLength = Length; if ((uint)startIndex > (uint)currentLength) { - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); } if (count < 0 || startIndex > currentLength - count) { - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Index")); } if (oldValue == null) { - throw new ArgumentNullException("oldValue"); + throw new ArgumentNullException(nameof(oldValue)); } if (oldValue.Length == 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "oldValue"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(oldValue)); } if (newValue == null) @@ -1648,7 +1723,7 @@ namespace System.Text { chunk = FindChunkForIndex(index); indexInChunk = index - chunk.m_ChunkOffset; - Contract.Assert(chunk != null || count == 0, "Chunks ended prematurely"); + Debug.Assert(chunk != null || count == 0, "Chunks ended prematurely"); } } VerifyClassInvariant(); @@ -1668,11 +1743,11 @@ namespace System.Text { int currentLength = Length; if ((uint)startIndex > (uint)currentLength) { - throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); } if (count < 0 || startIndex > currentLength - count) { - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Index")); } int endIndex = startIndex + count; @@ -1702,14 +1777,20 @@ namespace System.Text { /// /// Appends 'value' of length 'count' to the stringBuilder. /// - [SecurityCritical] [System.CLSCompliantAttribute(false)] public unsafe StringBuilder Append(char* value, int valueCount) { // We don't check null value as this case will throw null reference exception anyway if (valueCount < 0) { - throw new ArgumentOutOfRangeException("valueCount", Environment.GetResourceString("ArgumentOutOfRange_NegativeCount")); + throw new ArgumentOutOfRangeException(nameof(valueCount), Environment.GetResourceString("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. + int newLength = Length + valueCount; + if (newLength > m_MaxCapacity || newLength < valueCount) { + throw new ArgumentOutOfRangeException(nameof(valueCount), Environment.GetResourceString("ArgumentOutOfRange_LengthGreaterThanCapacity")); } // This case is so common we want to optimize for it heavily. @@ -1732,7 +1813,7 @@ namespace System.Text { // Expand the builder to add another chunk. int restLength = valueCount - firstLength; ExpandByABlock(restLength); - Contract.Assert(m_ChunkLength == 0, "Expand did not make a new block"); + Debug.Assert(m_ChunkLength == 0, "Expand did not make a new block"); // Copy the second chunk ThreadSafeCopy(value + firstLength, m_ChunkChars, 0, restLength); @@ -1745,12 +1826,11 @@ namespace System.Text { /// /// Inserts 'value' of length 'cou /// - [SecurityCritical] unsafe private void Insert(int index, char* value, int valueCount) { if ((uint)index > (uint)Length) { - throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); } if (valueCount > 0) @@ -1768,7 +1848,6 @@ namespace System.Text { /// replacements in bulk (and therefore very efficiently. /// with the string 'value'. /// - [System.Security.SecuritySafeCritical] // auto-generated private void ReplaceAllInChunk(int[] replacements, int replacementsCount, StringBuilder sourceChunk, int removeCount, string value) { if (replacementsCount <= 0) @@ -1798,9 +1877,9 @@ namespace System.Text { break; int gapEnd = replacements[i]; - Contract.Assert(gapStart < sourceChunk.m_ChunkChars.Length, "gap starts at end of buffer. Should not happen"); - Contract.Assert(gapStart <= gapEnd, "negative gap size"); - Contract.Assert(gapEnd <= sourceChunk.m_ChunkLength, "gap too big"); + 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 the next replacement @@ -1810,7 +1889,7 @@ namespace System.Text { else { targetIndexInChunk += gapEnd - gapStart; - Contract.Assert(targetIndexInChunk <= targetChunk.m_ChunkLength, "gap not in chunk"); + Debug.Assert(targetIndexInChunk <= targetChunk.m_ChunkLength, "gap not in chunk"); } } @@ -1855,7 +1934,6 @@ namespace System.Text { /// point at the end of the characters just copyied (thus you can splice in strings from multiple /// places by calling this mulitple times. /// - [SecurityCritical] unsafe private void ReplaceInPlaceAtChunk(ref StringBuilder chunk, ref int indexInChunk, char* value, int count) { if (count != 0) @@ -1863,7 +1941,7 @@ namespace System.Text { for (; ; ) { int lengthInChunk = chunk.m_ChunkLength - indexInChunk; - Contract.Assert(lengthInChunk >= 0, "index not in chunk"); + Debug.Assert(lengthInChunk >= 0, "index not in chunk"); int lengthToCopy = Math.Min(lengthInChunk, count); ThreadSafeCopy(value, chunk.m_ChunkChars, indexInChunk, lengthToCopy); @@ -1888,7 +1966,6 @@ namespace System.Text { /// The only way to do this is to copy all interesting variables out of the heap and then do the /// bounds check. This is what we do here. /// - [SecurityCritical] unsafe private static void ThreadSafeCopy(char* sourcePtr, char[] destination, int destinationIndex, int count) { if (count > 0) @@ -1900,11 +1977,10 @@ namespace System.Text { } else { - throw new ArgumentOutOfRangeException("destinationIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(destinationIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); } } } - [SecurityCritical] private static void ThreadSafeCopy(char[] source, int sourceIndex, char[] destination, int destinationIndex, int count) { if (count > 0) @@ -1918,13 +1994,12 @@ namespace System.Text { } else { - throw new ArgumentOutOfRangeException("sourceIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + throw new ArgumentOutOfRangeException(nameof(sourceIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); } } } // Copies the source StringBuilder to the destination IntPtr memory allocated with len bytes. - [System.Security.SecurityCritical] // auto-generated internal unsafe void InternalCopy(IntPtr dest, int len) { if(len ==0) return; @@ -1957,13 +2032,13 @@ namespace System.Text { /// private StringBuilder FindChunkForIndex(int index) { - Contract.Assert(0 <= index && index <= Length, "index not in string"); + Debug.Assert(0 <= index && index <= Length, "index not in string"); StringBuilder ret = this; while (ret.m_ChunkOffset > index) ret = ret.m_ChunkPrevious; - Contract.Assert(ret != null, "index not in string"); + Debug.Assert(ret != null, "index not in string"); return ret; } @@ -1974,13 +2049,13 @@ namespace System.Text { /// private StringBuilder FindChunkForByte(int byteIndex) { - Contract.Assert(0 <= byteIndex && byteIndex <= Length*sizeof(char), "Byte Index not in string"); + Debug.Assert(0 <= byteIndex && byteIndex <= Length*sizeof(char), "Byte Index not in string"); StringBuilder ret = this; while (ret.m_ChunkOffset*sizeof(char) > byteIndex) ret = ret.m_ChunkPrevious; - Contract.Assert(ret != null, "Byte Index not in string"); + Debug.Assert(ret != null, "Byte Index not in string"); return ret; } @@ -2063,12 +2138,11 @@ namespace System.Text { /// If dontMoveFollowingChars is true, then the room must be made by inserting a chunk BEFORE the /// current chunk (this is what it does most of the time anyway) /// - [System.Security.SecuritySafeCritical] // auto-generated private void MakeRoom(int index, int count, out StringBuilder chunk, out int indexInChunk, bool doneMoveFollowingChars) { VerifyClassInvariant(); - Contract.Assert(count > 0, "Count must be strictly positive"); - Contract.Assert(index >= 0, "Index can't be negative"); + Debug.Assert(count > 0, "Count must be strictly positive"); + Debug.Assert(index >= 0, "Index can't be negative"); if (count + Length > m_MaxCapacity || count + Length < count) throw new ArgumentOutOfRangeException("requiredLength", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity")); @@ -2133,8 +2207,8 @@ namespace System.Text { /// private StringBuilder(int size, int maxCapacity, StringBuilder previousBlock) { - Contract.Assert(size > 0, "size not positive"); - Contract.Assert(maxCapacity > 0, "maxCapacity not positive"); + Debug.Assert(size > 0, "size not positive"); + Debug.Assert(maxCapacity > 0, "maxCapacity not positive"); m_ChunkChars = new char[size]; m_MaxCapacity = maxCapacity; m_ChunkPrevious = previousBlock; @@ -2147,11 +2221,10 @@ namespace System.Text { /// Removes 'count' characters from the logical index 'startIndex' and returns the chunk and /// index in the chunk of that logical index in the out parameters. /// - [SecuritySafeCritical] private void Remove(int startIndex, int count, out StringBuilder chunk, out int indexInChunk) { VerifyClassInvariant(); - Contract.Assert(startIndex >= 0 && startIndex < Length, "startIndex not in string"); + Debug.Assert(startIndex >= 0 && startIndex < Length, "startIndex not in string"); int endIndex = startIndex + count; @@ -2180,7 +2253,7 @@ namespace System.Text { } chunk = chunk.m_ChunkPrevious; } - Contract.Assert(chunk != null, "fell off beginning of string!"); + Debug.Assert(chunk != null, "fell off beginning of string!"); int copyTargetIndexInChunk = indexInChunk; int copyCount = endChunk.m_ChunkLength - endIndexInChunk; @@ -2210,7 +2283,7 @@ namespace System.Text { if (copyTargetIndexInChunk != endIndexInChunk) // Sometimes no move is necessary ThreadSafeCopy(endChunk.m_ChunkChars, endIndexInChunk, endChunk.m_ChunkChars, copyTargetIndexInChunk, copyCount); - Contract.Assert(chunk != null, "fell off beginning of string!"); + Debug.Assert(chunk != null, "fell off beginning of string!"); VerifyClassInvariant(); } } diff --git a/src/mscorlib/src/System/Text/SurrogateEncoder.cs b/src/mscorlib/src/System/Text/SurrogateEncoder.cs index 409e8a3..bbfa180 100644 --- a/src/mscorlib/src/System/Text/SurrogateEncoder.cs +++ b/src/mscorlib/src/System/Text/SurrogateEncoder.cs @@ -12,6 +12,7 @@ namespace System.Text using System; using System.Runtime.Serialization; using System.Security.Permissions; + using System.Diagnostics; using System.Diagnostics.Contracts; /*=================================SurrogateEncoder================================== @@ -30,7 +31,7 @@ namespace System.Text internal SurrogateEncoder(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // All versions have a code page @@ -38,7 +39,6 @@ namespace System.Text } // Just get it from GetEncoding - [System.Security.SecurityCritical] // auto-generated public Object GetRealObject(StreamingContext context) { // Need to get our Encoding's Encoder @@ -46,11 +46,10 @@ namespace System.Text } // ISerializable implementation - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { // We cannot ever call this. - Contract.Assert(false, "Didn't expect to make it to SurrogateEncoder.GetObjectData"); + Debug.Assert(false, "Didn't expect to make it to SurrogateEncoder.GetObjectData"); throw new ArgumentException(Environment.GetResourceString("Arg_ExecutionEngineException")); } } diff --git a/src/mscorlib/src/System/Text/UTF32Encoding.cs b/src/mscorlib/src/System/Text/UTF32Encoding.cs index 0bdbaef..a7ac1d8 100644 --- a/src/mscorlib/src/System/Text/UTF32Encoding.cs +++ b/src/mscorlib/src/System/Text/UTF32Encoding.cs @@ -10,6 +10,7 @@ namespace System.Text { using System; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Globalization; // Encodes text into and out of UTF-32. UTF-32 is a way of writing @@ -109,7 +110,6 @@ namespace System.Text return EncodingForwarder.GetByteCount(this, s); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] public override unsafe int GetByteCount(char* chars, int count) { @@ -137,7 +137,6 @@ namespace System.Text return EncodingForwarder.GetBytes(this, chars, charIndex, charCount, bytes, byteIndex); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount) { @@ -152,7 +151,6 @@ namespace System.Text return EncodingForwarder.GetCharCount(this, bytes, index, count); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] public override unsafe int GetCharCount(byte* bytes, int count) { @@ -165,7 +163,6 @@ namespace System.Text return EncodingForwarder.GetChars(this, bytes, byteIndex, byteCount, chars, charIndex); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount) { @@ -182,11 +179,10 @@ namespace System.Text // End of overridden methods which use EncodingForwarder - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetByteCount(char *chars, int count, EncoderNLS encoder) { - Contract.Assert(chars!=null, "[UTF32Encoding.GetByteCount]chars!=null"); - Contract.Assert(count >=0, "[UTF32Encoding.GetByteCount]count >=0"); + Debug.Assert(chars!=null, "[UTF32Encoding.GetByteCount]chars!=null"); + Debug.Assert(count >=0, "[UTF32Encoding.GetByteCount]count >=0"); char* end = chars + count; char* charStart = chars; @@ -248,7 +244,7 @@ namespace System.Text // We are missing our low surrogate, decrement chars and fallback the high surrogate // The high surrogate may have come from the encoder, but nothing else did. - Contract.Assert(chars > charStart, + Debug.Assert(chars > charStart, "[UTF32Encoding.GetByteCount]Expected chars to have advanced if no low surrogate"); chars--; @@ -296,26 +292,25 @@ namespace System.Text // Check for overflows. if (byteCount < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString( + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString( "ArgumentOutOfRange_GetByteCountOverflow")); // Shouldn't have anything in fallback buffer for GetByteCount // (don't have to check m_throwOnOverflow for count) - Contract.Assert(fallbackBuffer.Remaining == 0, + Debug.Assert(fallbackBuffer.Remaining == 0, "[UTF32Encoding.GetByteCount]Expected empty fallback buffer at end"); // Return our count return byteCount; } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetBytes(char *chars, int charCount, byte* bytes, int byteCount, EncoderNLS encoder) { - Contract.Assert(chars!=null, "[UTF32Encoding.GetBytes]chars!=null"); - Contract.Assert(bytes!=null, "[UTF32Encoding.GetBytes]bytes!=null"); - Contract.Assert(byteCount >=0, "[UTF32Encoding.GetBytes]byteCount >=0"); - Contract.Assert(charCount >=0, "[UTF32Encoding.GetBytes]charCount >=0"); + Debug.Assert(chars!=null, "[UTF32Encoding.GetBytes]chars!=null"); + Debug.Assert(bytes!=null, "[UTF32Encoding.GetBytes]bytes!=null"); + Debug.Assert(byteCount >=0, "[UTF32Encoding.GetBytes]byteCount >=0"); + Debug.Assert(charCount >=0, "[UTF32Encoding.GetBytes]charCount >=0"); char* charStart = chars; char* charEnd = chars + charCount; @@ -384,7 +379,7 @@ namespace System.Text { // If we don't have enough room, then either we should've advanced a while // or we should have bytes==byteStart and throw below - Contract.Assert(chars > charStart + 1 || bytes == byteStart, + Debug.Assert(chars > charStart + 1 || bytes == byteStart, "[UnicodeEncoding.GetBytes]Expected chars to have when no room to add surrogate pair"); chars-=2; // Aren't using those 2 chars } @@ -412,7 +407,7 @@ namespace System.Text // We are missing our low surrogate, decrement chars and fallback the high surrogate // The high surrogate may have come from the encoder, but nothing else did. - Contract.Assert(chars > charStart, + Debug.Assert(chars > charStart, "[UTF32Encoding.GetBytes]Expected chars to have advanced if no low surrogate"); chars--; @@ -453,7 +448,7 @@ namespace System.Text else { // Must've advanced already - Contract.Assert(chars > charStart, + Debug.Assert(chars > charStart, "[UTF32Encoding.GetBytes]Expected chars to have advanced if normal character"); chars--; // Aren't using this char } @@ -487,7 +482,7 @@ namespace System.Text } // Fix our encoder if we have one - Contract.Assert(highSurrogate == 0 || (encoder != null && !encoder.MustFlush), + Debug.Assert(highSurrogate == 0 || (encoder != null && !encoder.MustFlush), "[UTF32Encoding.GetBytes]Expected encoder to be flushed."); if (encoder != null) @@ -503,11 +498,10 @@ namespace System.Text return (int)(bytes - byteStart); } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder) { - Contract.Assert(bytes!=null, "[UTF32Encoding.GetCharCount]bytes!=null"); - Contract.Assert(count >=0, "[UTF32Encoding.GetCharCount]count >=0"); + Debug.Assert(bytes!=null, "[UTF32Encoding.GetCharCount]bytes!=null"); + Debug.Assert(count >=0, "[UTF32Encoding.GetCharCount]count >=0"); UTF32Decoder decoder = (UTF32Decoder)baseDecoder; @@ -532,7 +526,7 @@ namespace System.Text // Shouldn't have anything in fallback buffer for GetCharCount // (don't have to check m_throwOnOverflow for chars or count) - Contract.Assert(fallbackBuffer.Remaining == 0, + Debug.Assert(fallbackBuffer.Remaining == 0, "[UTF32Encoding.GetCharCount]Expected empty fallback buffer at start"); } else @@ -635,25 +629,24 @@ namespace System.Text // Check for overflows. if (charCount < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); // Shouldn't have anything in fallback buffer for GetCharCount // (don't have to check m_throwOnOverflow for chars or count) - Contract.Assert(fallbackBuffer.Remaining == 0, + Debug.Assert(fallbackBuffer.Remaining == 0, "[UTF32Encoding.GetCharCount]Expected empty fallback buffer at end"); // Return our count return charCount; } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetChars(byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder) { - Contract.Assert(chars!=null, "[UTF32Encoding.GetChars]chars!=null"); - Contract.Assert(bytes!=null, "[UTF32Encoding.GetChars]bytes!=null"); - Contract.Assert(byteCount >=0, "[UTF32Encoding.GetChars]byteCount >=0"); - Contract.Assert(charCount >=0, "[UTF32Encoding.GetChars]charCount >=0"); + Debug.Assert(chars!=null, "[UTF32Encoding.GetChars]chars!=null"); + Debug.Assert(bytes!=null, "[UTF32Encoding.GetChars]bytes!=null"); + Debug.Assert(byteCount >=0, "[UTF32Encoding.GetChars]byteCount >=0"); + Debug.Assert(charCount >=0, "[UTF32Encoding.GetChars]charCount >=0"); UTF32Decoder decoder = (UTF32Decoder)baseDecoder; @@ -680,7 +673,7 @@ namespace System.Text // Shouldn't have anything in fallback buffer for GetChars // (don't have to check m_throwOnOverflow for chars) - Contract.Assert(fallbackBuffer.Remaining == 0, + Debug.Assert(fallbackBuffer.Remaining == 0, "[UTF32Encoding.GetChars]Expected empty fallback buffer at start"); } else @@ -741,7 +734,7 @@ namespace System.Text // Couldn't fallback, throw or wait til next time // We either read enough bytes for bytes-=4 to work, or we're // going to throw in ThrowCharsOverflow because chars == charStart - Contract.Assert(bytes >= byteStart + 4 || chars == charStart, + Debug.Assert(bytes >= byteStart + 4 || chars == charStart, "[UTF32Encoding.GetChars]Expected to have consumed bytes or throw (bad surrogate)"); bytes-=4; // get back to where we were iChar=0; // Remembering nothing @@ -765,7 +758,7 @@ namespace System.Text // Throwing or stopping // We either read enough bytes for bytes-=4 to work, or we're // going to throw in ThrowCharsOverflow because chars == charStart - Contract.Assert(bytes >= byteStart + 4 || chars == charStart, + Debug.Assert(bytes >= byteStart + 4 || chars == charStart, "[UTF32Encoding.GetChars]Expected to have consumed bytes or throw (surrogate)"); bytes-=4; // get back to where we were iChar=0; // Remembering nothing @@ -782,7 +775,7 @@ namespace System.Text // Throwing or stopping // We either read enough bytes for bytes-=4 to work, or we're // going to throw in ThrowCharsOverflow because chars == charStart - Contract.Assert(bytes >= byteStart + 4 || chars == charStart, + Debug.Assert(bytes >= byteStart + 4 || chars == charStart, "[UTF32Encoding.GetChars]Expected to have consumed bytes or throw (normal char)"); bytes-=4; // get back to where we were iChar=0; // Remembering nothing @@ -846,7 +839,7 @@ namespace System.Text // Shouldn't have anything in fallback buffer for GetChars // (don't have to check m_throwOnOverflow for chars) - Contract.Assert(fallbackBuffer.Remaining == 0, + Debug.Assert(fallbackBuffer.Remaining == 0, "[UTF32Encoding.GetChars]Expected empty fallback buffer at end"); // Return our count @@ -885,7 +878,7 @@ namespace System.Text public override int GetMaxByteCount(int charCount) { if (charCount < 0) - throw new ArgumentOutOfRangeException("charCount", + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -899,7 +892,7 @@ namespace System.Text byteCount *= 4; if (byteCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); return (int)byteCount; } @@ -908,7 +901,7 @@ namespace System.Text public override int GetMaxCharCount(int byteCount) { if (byteCount < 0) - throw new ArgumentOutOfRangeException("byteCount", + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -929,7 +922,7 @@ namespace System.Text } if (charCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow")); return (int)charCount; } diff --git a/src/mscorlib/src/System/Text/UTF7Encoding.cs b/src/mscorlib/src/System/Text/UTF7Encoding.cs index 654fb8b..624ca73 100644 --- a/src/mscorlib/src/System/Text/UTF7Encoding.cs +++ b/src/mscorlib/src/System/Text/UTF7Encoding.cs @@ -11,6 +11,7 @@ namespace System.Text using System; using System.Runtime.Serialization; using System.Security.Permissions; + using System.Diagnostics; using System.Diagnostics.Contracts; @@ -175,7 +176,6 @@ namespace System.Text return EncodingForwarder.GetByteCount(this, s); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public override unsafe int GetByteCount(char* chars, int count) @@ -205,7 +205,6 @@ namespace System.Text return EncodingForwarder.GetBytes(this, chars, charIndex, charCount, bytes, byteIndex); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount) @@ -221,7 +220,6 @@ namespace System.Text return EncodingForwarder.GetCharCount(this, bytes, index, count); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public override unsafe int GetCharCount(byte* bytes, int count) @@ -235,7 +233,6 @@ namespace System.Text return EncodingForwarder.GetChars(this, bytes, byteIndex, byteCount, chars, charIndex); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount) @@ -254,23 +251,21 @@ namespace System.Text // End of overridden methods which use EncodingForwarder - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS baseEncoder) { - Contract.Assert(chars!=null, "[UTF7Encoding.GetByteCount]chars!=null"); - Contract.Assert(count >=0, "[UTF7Encoding.GetByteCount]count >=0"); + Debug.Assert(chars!=null, "[UTF7Encoding.GetByteCount]chars!=null"); + Debug.Assert(count >=0, "[UTF7Encoding.GetByteCount]count >=0"); // Just call GetBytes with bytes == null return GetBytes(chars, count, null, 0, baseEncoder); } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS baseEncoder) { - Contract.Assert(byteCount >=0, "[UTF7Encoding.GetBytes]byteCount >=0"); - Contract.Assert(chars!=null, "[UTF7Encoding.GetBytes]chars!=null"); - Contract.Assert(charCount >=0, "[UTF7Encoding.GetBytes]charCount >=0"); + Debug.Assert(byteCount >=0, "[UTF7Encoding.GetBytes]byteCount >=0"); + Debug.Assert(chars!=null, "[UTF7Encoding.GetBytes]chars!=null"); + Debug.Assert(charCount >=0, "[UTF7Encoding.GetBytes]charCount >=0"); // Get encoder info UTF7Encoding.Encoder encoder = (UTF7Encoding.Encoder)baseEncoder; @@ -405,23 +400,21 @@ namespace System.Text return buffer.Count; } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder) { - Contract.Assert(count >=0, "[UTF7Encoding.GetCharCount]count >=0"); - Contract.Assert(bytes!=null, "[UTF7Encoding.GetCharCount]bytes!=null"); + Debug.Assert(count >=0, "[UTF7Encoding.GetCharCount]count >=0"); + Debug.Assert(bytes!=null, "[UTF7Encoding.GetCharCount]bytes!=null"); // Just call GetChars with null char* to do counting return GetChars(bytes, count, null, 0, baseDecoder); } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetChars(byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder) { - Contract.Assert(byteCount >=0, "[UTF7Encoding.GetChars]byteCount >=0"); - Contract.Assert(bytes!=null, "[UTF7Encoding.GetChars]bytes!=null"); - Contract.Assert(charCount >=0, "[UTF7Encoding.GetChars]charCount >=0"); + Debug.Assert(byteCount >=0, "[UTF7Encoding.GetChars]byteCount >=0"); + Debug.Assert(bytes!=null, "[UTF7Encoding.GetChars]bytes!=null"); + Debug.Assert(charCount >=0, "[UTF7Encoding.GetChars]charCount >=0"); // Might use a decoder UTF7Encoding.Decoder decoder = (UTF7Encoding.Decoder) baseDecoder; @@ -440,7 +433,7 @@ namespace System.Text bitCount = decoder.bitCount; firstByte = decoder.firstByte; - Contract.Assert(firstByte == false || decoder.bitCount <= 0, + Debug.Assert(firstByte == false || decoder.bitCount <= 0, "[UTF7Encoding.GetChars]If remembered bits, then first byte flag shouldn't be set"); } @@ -599,7 +592,7 @@ namespace System.Text public override int GetMaxByteCount(int charCount) { if (charCount < 0) - throw new ArgumentOutOfRangeException("charCount", + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -623,7 +616,7 @@ namespace System.Text // check for overflow if (byteCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); return (int)byteCount; } @@ -632,7 +625,7 @@ namespace System.Text public override int GetMaxCharCount(int byteCount) { if (byteCount < 0) - throw new ArgumentOutOfRangeException("byteCount", + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -663,7 +656,7 @@ namespace System.Text internal Decoder(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // Get common info @@ -674,11 +667,10 @@ namespace System.Text } // ISerializable implementation, get data for this object - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // Save Whidbey data @@ -727,7 +719,7 @@ namespace System.Text internal Encoder(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // Get common info @@ -737,11 +729,10 @@ namespace System.Text } // ISerializable implementation, get data for this object - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // Save Whidbey data @@ -825,8 +816,8 @@ namespace System.Text public override bool Fallback(byte[] bytesUnknown, int index) { // We expect no previous fallback in our buffer - Contract.Assert(iCount < 0, "[DecoderUTF7FallbackBuffer.Fallback] Can't have recursive fallbacks"); - Contract.Assert(bytesUnknown.Length == 1, "[DecoderUTF7FallbackBuffer.Fallback] Only possible fallback case should be 1 unknown byte"); + Debug.Assert(iCount < 0, "[DecoderUTF7FallbackBuffer.Fallback] Can't have recursive fallbacks"); + Debug.Assert(bytesUnknown.Length == 1, "[DecoderUTF7FallbackBuffer.Fallback] Only possible fallback case should be 1 unknown byte"); // Go ahead and get our fallback cFallback = (char)bytesUnknown[0]; @@ -872,7 +863,6 @@ namespace System.Text } // Clear the buffer - [System.Security.SecuritySafeCritical] // overrides public transparent member public override unsafe void Reset() { iCount = -1; @@ -880,13 +870,12 @@ namespace System.Text } // This version just counts the fallback and doesn't actually copy anything. - [System.Security.SecurityCritical] // auto-generated internal unsafe override int InternalFallback(byte[] bytes, byte* pBytes) // Right now this has both bytes and bytes[], since we might have extra bytes, hence the // array, and we might need the index, hence the byte* { // We expect no previous fallback in our buffer - Contract.Assert(iCount < 0, "[DecoderUTF7FallbackBuffer.InternalFallback] Can't have recursive fallbacks"); + Debug.Assert(iCount < 0, "[DecoderUTF7FallbackBuffer.InternalFallback] Can't have recursive fallbacks"); if (bytes.Length != 1) { throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex")); diff --git a/src/mscorlib/src/System/Text/UTF8Encoding.cs b/src/mscorlib/src/System/Text/UTF8Encoding.cs index a527de7..ba19649 100644 --- a/src/mscorlib/src/System/Text/UTF8Encoding.cs +++ b/src/mscorlib/src/System/Text/UTF8Encoding.cs @@ -21,6 +21,7 @@ namespace System.Text using System.Globalization; using System.Runtime.Serialization; using System.Security.Permissions; + using System.Diagnostics; using System.Diagnostics.Contracts; // Encodes text into and out of UTF-8. UTF-8 is a way of writing @@ -129,7 +130,6 @@ namespace System.Text return EncodingForwarder.GetByteCount(this, chars); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public override unsafe int GetByteCount(char* chars, int count) @@ -158,7 +158,6 @@ namespace System.Text return EncodingForwarder.GetBytes(this, chars, charIndex, charCount, bytes, byteIndex); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount) @@ -174,7 +173,6 @@ namespace System.Text return EncodingForwarder.GetCharCount(this, bytes, index, count); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public override unsafe int GetCharCount(byte* bytes, int count) @@ -188,7 +186,6 @@ namespace System.Text return EncodingForwarder.GetChars(this, bytes, byteIndex, byteCount, chars, charIndex); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount) @@ -209,7 +206,6 @@ namespace System.Text // To simplify maintenance, the structure of GetByteCount and GetBytes should be // kept the same as much as possible - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetByteCount(char *chars, int count, EncoderNLS baseEncoder) { // For fallback we may need a fallback buffer. @@ -254,7 +250,7 @@ namespace System.Text } else { // Case of surrogates in the fallback. if (fallbackBuffer != null && fallbackBuffer.bFallingBack) { - Contract.Assert(ch >= 0xD800 && ch <= 0xDBFF, + Debug.Assert(ch >= 0xD800 && ch <= 0xDBFF, "[UTF8Encoding.GetBytes]expected high surrogate, not 0x" + ((int)ch).ToString("X4", CultureInfo.InvariantCulture)); ch = fallbackBuffer.InternalGetNextChar(); @@ -286,7 +282,7 @@ namespace System.Text } if (ch > 0) { - Contract.Assert(ch >= 0xD800 && ch <= 0xDBFF, + Debug.Assert(ch >= 0xD800 && ch <= 0xDBFF, "[UTF8Encoding.GetBytes]expected high surrogate, not 0x" + ((int)ch).ToString("X4", CultureInfo.InvariantCulture)); // use separate helper variables for local contexts so that the jit optimizations @@ -557,7 +553,7 @@ namespace System.Text } #endif - Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, + Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[UTF8Encoding.GetByteCount]Expected Empty fallback buffer"); return byteCount; @@ -566,14 +562,12 @@ namespace System.Text // diffs two char pointers using unsigned arithmetic. The unsigned arithmetic // is good enough for us, and it tends to generate better code than the signed // arithmetic generated by default - [System.Security.SecurityCritical] // auto-generated unsafe private static int PtrDiff(char *a, char* b) { return (int)(((uint)((byte*)a - (byte*)b)) >> 1); } // byte* flavor just for parity - [System.Security.SecurityCritical] // auto-generated unsafe private static int PtrDiff(byte* a, byte* b) { return (int)(a - b); @@ -586,14 +580,13 @@ namespace System.Text // Our workhorse // Note: We ignore mismatched surrogates, unless the exception flag is set in which case we throw - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS baseEncoder) { - Contract.Assert(chars!=null, "[UTF8Encoding.GetBytes]chars!=null"); - Contract.Assert(byteCount >=0, "[UTF8Encoding.GetBytes]byteCount >=0"); - Contract.Assert(charCount >=0, "[UTF8Encoding.GetBytes]charCount >=0"); - Contract.Assert(bytes!=null, "[UTF8Encoding.GetBytes]bytes!=null"); + Debug.Assert(chars!=null, "[UTF8Encoding.GetBytes]chars!=null"); + Debug.Assert(byteCount >=0, "[UTF8Encoding.GetBytes]byteCount >=0"); + Debug.Assert(charCount >=0, "[UTF8Encoding.GetBytes]charCount >=0"); + Debug.Assert(bytes!=null, "[UTF8Encoding.GetBytes]bytes!=null"); UTF8Encoder encoder = null; @@ -642,7 +635,7 @@ namespace System.Text } else { // Case of leftover surrogates in the fallback buffer if (fallbackBuffer != null && fallbackBuffer.bFallingBack) { - Contract.Assert(ch >= 0xD800 && ch <= 0xDBFF, + Debug.Assert(ch >= 0xD800 && ch <= 0xDBFF, "[UTF8Encoding.GetBytes]expected high surrogate, not 0x" + ((int)ch).ToString("X4", CultureInfo.InvariantCulture)); int cha = ch; @@ -670,7 +663,7 @@ namespace System.Text if (ch > 0) { // We have a high surrogate left over from a previous loop. - Contract.Assert(ch >= 0xD800 && ch <= 0xDBFF, + Debug.Assert(ch >= 0xD800 && ch <= 0xDBFF, "[UTF8Encoding.GetBytes]expected high surrogate, not 0x" + ((int)ch).ToString("X4", CultureInfo.InvariantCulture)); // use separate helper variables for local contexts so that the jit optimizations @@ -767,7 +760,7 @@ namespace System.Text if (ch > 0xFFFF) pSrc--; // Was surrogate, didn't use 2nd part either } - Contract.Assert(pSrc >= chars || pTarget == bytes, + Debug.Assert(pSrc >= chars || pTarget == bytes, "[UTF8Encoding.GetBytes]Expected pSrc to be within buffer or to throw with insufficient room."); ThrowBytesOverflow(encoder, pTarget == bytes); // Throw if we must ch = 0; // Nothing left over (we backed up to start of pair if supplimentary) @@ -989,7 +982,7 @@ namespace System.Text pTarget++; } - Contract.Assert(pTarget <= pAllocatedBufferEnd, "[UTF8Encoding.GetBytes]pTarget <= pAllocatedBufferEnd"); + Debug.Assert(pTarget <= pAllocatedBufferEnd, "[UTF8Encoding.GetBytes]pTarget <= pAllocatedBufferEnd"); #endif // FASTLOOP @@ -1000,14 +993,14 @@ namespace System.Text // Do we have to set the encoder bytes? if (encoder != null) { - Contract.Assert(!encoder.MustFlush || ch == 0, + Debug.Assert(!encoder.MustFlush || ch == 0, "[UTF8Encoding.GetBytes] Expected no mustflush or 0 leftover ch " + ch.ToString("X2", CultureInfo.InvariantCulture)); encoder.surrogateChar = ch; encoder.m_charsUsed = (int)(pSrc - chars); } - Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0 || + Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0 || baseEncoder == null || !baseEncoder.m_throwOnOverflow, "[UTF8Encoding.GetBytes]Expected empty fallback buffer if not converting"); @@ -1029,11 +1022,10 @@ namespace System.Text // // To simplify maintenance, the structure of GetCharCount and GetChars should be // kept the same as much as possible - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder) { - Contract.Assert(count >=0, "[UTF8Encoding.GetCharCount]count >=0"); - Contract.Assert(bytes!=null, "[UTF8Encoding.GetCharCount]bytes!=null"); + Debug.Assert(count >=0, "[UTF8Encoding.GetCharCount]count >=0"); + Debug.Assert(bytes!=null, "[UTF8Encoding.GetCharCount]bytes!=null"); // Initialize stuff byte *pSrc = bytes; @@ -1052,7 +1044,7 @@ namespace System.Text // Shouldn't have anything in fallback buffer for GetCharCount // (don't have to check m_throwOnOverflow for count) - Contract.Assert(!decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, + Debug.Assert(!decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[UTF8Encoding.GetCharCount]Expected empty fallback buffer at start"); } @@ -1087,7 +1079,7 @@ namespace System.Text ch = (ch << 6) | (cha & 0x3F); if ((ch & FinalByte) == 0) { - Contract.Assert( (ch & (SupplimentarySeq | ThreeByteSeq)) != 0, + Debug.Assert( (ch & (SupplimentarySeq | ThreeByteSeq)) != 0, "[UTF8Encoding.GetChars]Invariant volation"); if ((ch & SupplimentarySeq) != 0) { @@ -1408,7 +1400,7 @@ namespace System.Text // Shouldn't have anything in fallback buffer for GetCharCount // (don't have to check m_throwOnOverflow for count) - Contract.Assert(fallback == null || fallback.Remaining == 0, + Debug.Assert(fallback == null || fallback.Remaining == 0, "[UTF8Encoding.GetCharCount]Expected empty fallback buffer at end"); return charCount; @@ -1424,14 +1416,13 @@ namespace System.Text // // To simplify maintenance, the structure of GetCharCount and GetChars should be // kept the same as much as possible - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetChars(byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder) { - Contract.Assert(chars!=null, "[UTF8Encoding.GetChars]chars!=null"); - Contract.Assert(byteCount >=0, "[UTF8Encoding.GetChars]count >=0"); - Contract.Assert(charCount >=0, "[UTF8Encoding.GetChars]charCount >=0"); - Contract.Assert(bytes!=null, "[UTF8Encoding.GetChars]bytes!=null"); + Debug.Assert(chars!=null, "[UTF8Encoding.GetChars]chars!=null"); + Debug.Assert(byteCount >=0, "[UTF8Encoding.GetChars]count >=0"); + Debug.Assert(charCount >=0, "[UTF8Encoding.GetChars]charCount >=0"); + Debug.Assert(bytes!=null, "[UTF8Encoding.GetChars]bytes!=null"); byte *pSrc = bytes; char *pTarget = chars; @@ -1448,7 +1439,7 @@ namespace System.Text // Shouldn't have anything in fallback buffer for GetChars // (don't have to check m_throwOnOverflow for chars, we always use all or none so always should be empty) - Contract.Assert(!decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, + Debug.Assert(!decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[UTF8Encoding.GetChars]Expected empty fallback buffer at start"); } @@ -1483,7 +1474,7 @@ namespace System.Text if ((ch & FinalByte) == 0) { // Not at last byte yet - Contract.Assert( (ch & (SupplimentarySeq | ThreeByteSeq)) != 0, + Debug.Assert( (ch & (SupplimentarySeq | ThreeByteSeq)) != 0, "[UTF8Encoding.GetChars]Invariant volation"); if ((ch & SupplimentarySeq) != 0) { @@ -1546,14 +1537,14 @@ namespace System.Text { // Ran out of buffer space // Need to throw an exception? - Contract.Assert(pSrc >= bytes || pTarget == chars, + Debug.Assert(pSrc >= bytes || pTarget == chars, "[UTF8Encoding.GetChars]Expected to throw or remain in byte buffer after fallback"); fallback.InternalReset(); ThrowCharsOverflow(baseDecoder, pTarget == chars); ch = 0; break; } - Contract.Assert(pSrc >= bytes, + Debug.Assert(pSrc >= bytes, "[UTF8Encoding.GetChars]Expected invalid byte sequence to have remained within the byte array"); ch = 0; continue; @@ -1639,7 +1630,7 @@ namespace System.Text // Throw that we don't have enough room (pSrc could be < chars if we had started to process // a 4 byte sequence alredy) - Contract.Assert(pSrc >= bytes || pTarget == chars, + Debug.Assert(pSrc >= bytes || pTarget == chars, "[UTF8Encoding.GetChars]Expected pSrc to be within input buffer or throw due to no output]"); ThrowCharsOverflow(baseDecoder, pTarget == chars); @@ -1893,7 +1884,7 @@ namespace System.Text } #endif // FASTLOOP - Contract.Assert(pTarget <= pAllocatedBufferEnd, "[UTF8Encoding.GetChars]pTarget <= pAllocatedBufferEnd"); + Debug.Assert(pTarget <= pAllocatedBufferEnd, "[UTF8Encoding.GetChars]pTarget <= pAllocatedBufferEnd"); // no pending bits at this point ch = 0; @@ -1920,7 +1911,7 @@ namespace System.Text // This'll back us up the appropriate # of bytes if we didn't get anywhere if (!FallbackInvalidByteSequence(ref pSrc, ch, fallback, ref pTarget)) { - Contract.Assert(pSrc >= bytes || pTarget == chars, + Debug.Assert(pSrc >= bytes || pTarget == chars, "[UTF8Encoding.GetChars]Expected to throw or remain in byte buffer while flushing"); // Ran out of buffer space @@ -1928,7 +1919,7 @@ namespace System.Text fallback.InternalReset(); ThrowCharsOverflow(baseDecoder, pTarget == chars); } - Contract.Assert(pSrc >= bytes, + Debug.Assert(pSrc >= bytes, "[UTF8Encoding.GetChars]Expected flushing invalid byte sequence to have remained within the byte array"); ch = 0; } @@ -1939,7 +1930,7 @@ namespace System.Text // If we're storing flush data we expect all bits to be used or else // we're stuck in the middle of a conversion - Contract.Assert(!baseDecoder.MustFlush || ch == 0 || !baseDecoder.m_throwOnOverflow, + Debug.Assert(!baseDecoder.MustFlush || ch == 0 || !baseDecoder.m_throwOnOverflow, "[UTF8Encoding.GetChars]Expected no must flush or no left over bits or no throw on overflow."); // Remember our leftover bits. @@ -1950,7 +1941,7 @@ namespace System.Text // Shouldn't have anything in fallback buffer for GetChars // (don't have to check m_throwOnOverflow for chars) - Contract.Assert(fallback == null || fallback.Remaining == 0, + Debug.Assert(fallback == null || fallback.Remaining == 0, "[UTF8Encoding.GetChars]Expected empty fallback buffer at end"); return PtrDiff(pTarget, chars); @@ -1959,7 +1950,6 @@ namespace System.Text // During GetChars we had an invalid byte sequence // pSrc is backed up to the start of the bad sequence if we didn't have room to // fall it back. Otherwise pSrc remains wher it is. - [System.Security.SecurityCritical] // auto-generated private unsafe bool FallbackInvalidByteSequence( ref byte* pSrc, int ch, DecoderFallbackBuffer fallback, ref char* pTarget) { @@ -1982,7 +1972,6 @@ namespace System.Text // During GetCharCount we had an invalid byte sequence // pSrc is used to find the index that points to the invalid bytes, // however the byte[] contains the fallback bytes (in case the index is -1) - [System.Security.SecurityCritical] // auto-generated private unsafe int FallbackInvalidByteSequence( byte* pSrc, int ch, DecoderFallbackBuffer fallback) { @@ -2001,7 +1990,6 @@ namespace System.Text // Note that some of these bytes may have come from a previous fallback, so we cannot // just decrement the pointer and use the values we read. In those cases we have // to regenerate the original values. - [System.Security.SecurityCritical] // auto-generated private unsafe byte[] GetBytesUnknown(ref byte* pSrc, int ch) { // Get our byte[] @@ -2085,7 +2073,7 @@ namespace System.Text public override int GetMaxByteCount(int charCount) { if (charCount < 0) - throw new ArgumentOutOfRangeException("charCount", + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -2099,7 +2087,7 @@ namespace System.Text byteCount *= 3; if (byteCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); return (int)byteCount; } @@ -2108,7 +2096,7 @@ namespace System.Text public override int GetMaxCharCount(int byteCount) { if (byteCount < 0) - throw new ArgumentOutOfRangeException("byteCount", + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -2123,7 +2111,7 @@ namespace System.Text } if (charCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow")); return (int)charCount; } @@ -2174,7 +2162,7 @@ namespace System.Text internal UTF8Encoder(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // Get common info @@ -2194,11 +2182,10 @@ namespace System.Text } // ISerializable implementation, get data for this object - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // Save Whidbey data @@ -2247,7 +2234,7 @@ namespace System.Text internal UTF8Decoder(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // Get common info @@ -2268,11 +2255,10 @@ namespace System.Text } // ISerializable implementation, get data for this object - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // Save new Whidbey data diff --git a/src/mscorlib/src/System/Text/UnicodeEncoding.cs b/src/mscorlib/src/System/Text/UnicodeEncoding.cs index 41d4f3b..25255c3 100644 --- a/src/mscorlib/src/System/Text/UnicodeEncoding.cs +++ b/src/mscorlib/src/System/Text/UnicodeEncoding.cs @@ -12,6 +12,7 @@ namespace System.Text using System.Globalization; using System.Runtime.Serialization; using System.Security.Permissions; + using System.Diagnostics; using System.Diagnostics.Contracts; @@ -109,7 +110,6 @@ namespace System.Text return EncodingForwarder.GetByteCount(this, s); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public override unsafe int GetByteCount(char* chars, int count) @@ -138,7 +138,6 @@ namespace System.Text return EncodingForwarder.GetBytes(this, chars, charIndex, charCount, bytes, byteIndex); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount) @@ -154,7 +153,6 @@ namespace System.Text return EncodingForwarder.GetCharCount(this, bytes, index, count); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public override unsafe int GetCharCount(byte* bytes, int count) @@ -168,7 +166,6 @@ namespace System.Text return EncodingForwarder.GetChars(this, bytes, byteIndex, byteCount, chars, charIndex); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(false)] public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount) @@ -187,11 +184,10 @@ namespace System.Text // End of overridden methods which use EncodingForwarder - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS encoder) { - Contract.Assert(chars!=null, "[UnicodeEncoding.GetByteCount]chars!=null"); - Contract.Assert(count >= 0, "[UnicodeEncoding.GetByteCount]count >=0"); + Debug.Assert(chars!=null, "[UnicodeEncoding.GetByteCount]chars!=null"); + Debug.Assert(count >= 0, "[UnicodeEncoding.GetByteCount]count >=0"); // Start by assuming each char gets 2 bytes int byteCount = count << 1; @@ -200,7 +196,7 @@ namespace System.Text // (If they were all invalid chars, this would actually be wrong, // but that's a ridiculously large # so we're not concerned about that case) if (byteCount < 0) - throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); char* charStart = chars; char* charEnd = chars + count; @@ -340,7 +336,7 @@ namespace System.Text // Unwind the current character, this should be safe because we // don't have leftover data in the fallback, so chars must have // advanced already. - Contract.Assert(chars > charStart, + Debug.Assert(chars > charStart, "[UnicodeEncoding.GetByteCount]Expected chars to have advanced in unexpected high surrogate"); chars--; @@ -407,7 +403,7 @@ namespace System.Text // Rewind the current character, fallback previous character. // this should be safe because we don't have leftover data in the // fallback, so chars must have advanced already. - Contract.Assert(chars > charStart, + Debug.Assert(chars > charStart, "[UnicodeEncoding.GetByteCount]Expected chars to have advanced when expected low surrogate"); chars--; @@ -448,7 +444,7 @@ namespace System.Text // Throw it, using our complete character throw new ArgumentException( Environment.GetResourceString("Argument_RecursiveFallback", - charLeftOver), "chars"); + charLeftOver), nameof(chars)); } else { @@ -473,21 +469,20 @@ namespace System.Text // Shouldn't have anything in fallback buffer for GetByteCount // (don't have to check m_throwOnOverflow for count) - Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, + Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[UnicodeEncoding.GetByteCount]Expected empty fallback buffer at end"); // Don't remember fallbackBuffer.encoder for counting return byteCount; } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS encoder) { - Contract.Assert(chars!=null, "[UnicodeEncoding.GetBytes]chars!=null"); - Contract.Assert(byteCount >=0, "[UnicodeEncoding.GetBytes]byteCount >=0"); - Contract.Assert(charCount >=0, "[UnicodeEncoding.GetBytes]charCount >=0"); - Contract.Assert(bytes!=null, "[UnicodeEncoding.GetBytes]bytes!=null"); + Debug.Assert(chars!=null, "[UnicodeEncoding.GetBytes]chars!=null"); + Debug.Assert(byteCount >=0, "[UnicodeEncoding.GetBytes]byteCount >=0"); + Debug.Assert(charCount >=0, "[UnicodeEncoding.GetBytes]charCount >=0"); + Debug.Assert(bytes!=null, "[UnicodeEncoding.GetBytes]bytes!=null"); char charLeftOver = (char)0; char ch; @@ -691,7 +686,7 @@ namespace System.Text // Unwind the current character, this should be safe because we // don't have leftover data in the fallback, so chars must have // advanced already. - Contract.Assert(chars > charStart, + Debug.Assert(chars > charStart, "[UnicodeEncoding.GetBytes]Expected chars to have advanced in unexpected high surrogate"); chars--; @@ -757,7 +752,7 @@ namespace System.Text { // If we don't have enough room, then either we should've advanced a while // or we should have bytes==byteStart and throw below - Contract.Assert(chars > charStart + 1 || bytes == byteStart, + Debug.Assert(chars > charStart + 1 || bytes == byteStart, "[UnicodeEncoding.GetBytes]Expected chars to have when no room to add surrogate pair"); chars-=2; // Didn't use either surrogate } @@ -786,7 +781,7 @@ namespace System.Text // Rewind the current character, fallback previous character. // this should be safe because we don't have leftover data in the // fallback, so chars must have advanced already. - Contract.Assert(chars > charStart, + Debug.Assert(chars > charStart, "[UnicodeEncoding.GetBytes]Expected chars to have advanced after expecting low surrogate"); chars--; @@ -820,7 +815,7 @@ namespace System.Text { // Lonely charLeftOver (from previous call) would've been caught up above, // so this must be a case where we've already read an input char. - Contract.Assert(chars > charStart, + Debug.Assert(chars > charStart, "[UnicodeEncoding.GetBytes]Expected chars to have advanced for failed fallback"); chars--; // Not using this char } @@ -851,7 +846,7 @@ namespace System.Text // Throw it, using our complete character throw new ArgumentException( Environment.GetResourceString("Argument_RecursiveFallback", - charLeftOver), "chars"); + charLeftOver), nameof(chars)); } else { @@ -888,10 +883,10 @@ namespace System.Text // Remember charLeftOver if we must, or clear it if we're flushing // (charLeftOver should be 0 if we're flushing) - Contract.Assert((encoder != null && !encoder.MustFlush) || charLeftOver == (char)0, + Debug.Assert((encoder != null && !encoder.MustFlush) || charLeftOver == (char)0, "[UnicodeEncoding.GetBytes] Expected no left over characters if flushing"); - Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0 || + Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0 || encoder == null || !encoder.m_throwOnOverflow, "[UnicodeEncoding.GetBytes]Expected empty fallback buffer if not converting"); @@ -901,11 +896,10 @@ namespace System.Text return (int)(bytes - byteStart); } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder) { - Contract.Assert(bytes!=null, "[UnicodeEncoding.GetCharCount]bytes!=null"); - Contract.Assert(count >= 0, "[UnicodeEncoding.GetCharCount]count >=0"); + Debug.Assert(bytes!=null, "[UnicodeEncoding.GetCharCount]bytes!=null"); + Debug.Assert(count >= 0, "[UnicodeEncoding.GetCharCount]count >=0"); UnicodeEncoding.Decoder decoder = (UnicodeEncoding.Decoder)baseDecoder; @@ -944,7 +938,7 @@ namespace System.Text // Shouldn't have anything in fallback buffer for GetCharCount // (don't have to check m_throwOnOverflow for count) - Contract.Assert(!decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, + Debug.Assert(!decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[UnicodeEncoding.GetCharCount]Expected empty fallback buffer at start"); } @@ -1234,20 +1228,19 @@ namespace System.Text // Shouldn't have anything in fallback buffer for GetCharCount // (don't have to check m_throwOnOverflow for count) - Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, + Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[UnicodeEncoding.GetCharCount]Expected empty fallback buffer at end"); return charCount; } - [System.Security.SecurityCritical] // auto-generated internal override unsafe int GetChars(byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder ) { - Contract.Assert(chars!=null, "[UnicodeEncoding.GetChars]chars!=null"); - Contract.Assert(byteCount >=0, "[UnicodeEncoding.GetChars]byteCount >=0"); - Contract.Assert(charCount >=0, "[UnicodeEncoding.GetChars]charCount >=0"); - Contract.Assert(bytes!=null, "[UnicodeEncoding.GetChars]bytes!=null"); + Debug.Assert(chars!=null, "[UnicodeEncoding.GetChars]chars!=null"); + Debug.Assert(byteCount >=0, "[UnicodeEncoding.GetChars]byteCount >=0"); + Debug.Assert(charCount >=0, "[UnicodeEncoding.GetChars]charCount >=0"); + Debug.Assert(bytes!=null, "[UnicodeEncoding.GetChars]bytes!=null"); UnicodeEncoding.Decoder decoder = (UnicodeEncoding.Decoder)baseDecoder; @@ -1263,7 +1256,7 @@ namespace System.Text // Shouldn't have anything in fallback buffer for GetChars // (don't have to check m_throwOnOverflow for chars) - Contract.Assert(!decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, + Debug.Assert(!decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[UnicodeEncoding.GetChars]Expected empty fallback buffer at start"); } @@ -1421,7 +1414,7 @@ namespace System.Text { // couldn't fall back lonely surrogate // We either advanced bytes or chars should == charStart and throw below - Contract.Assert(bytes >= byteStart + 2 || chars == charStart, + Debug.Assert(bytes >= byteStart + 2 || chars == charStart, "[UnicodeEncoding.GetChars]Expected bytes to have advanced or no output (bad surrogate)"); bytes-=2; // didn't use these 2 bytes fallbackBuffer.InternalReset(); @@ -1470,7 +1463,7 @@ namespace System.Text { // couldn't fall back lonely surrogate // We either advanced bytes or chars should == charStart and throw below - Contract.Assert(bytes >= byteStart + 2 || chars == charStart, + Debug.Assert(bytes >= byteStart + 2 || chars == charStart, "[UnicodeEncoding.GetChars]Expected bytes to have advanced or no output (lonely surrogate)"); bytes-=2; // didn't use these 2 bytes fallbackBuffer.InternalReset(); @@ -1487,7 +1480,7 @@ namespace System.Text { // couldn't find room for this surrogate pair // We either advanced bytes or chars should == charStart and throw below - Contract.Assert(bytes >= byteStart + 2 || chars == charStart, + Debug.Assert(bytes >= byteStart + 2 || chars == charStart, "[UnicodeEncoding.GetChars]Expected bytes to have advanced or no output (surrogate pair)"); bytes-=2; // didn't use these 2 bytes ThrowCharsOverflow(decoder, chars == charStart);// Might throw, if no chars output @@ -1529,7 +1522,7 @@ namespace System.Text { // couldn't fall back high surrogate, or char that would be next // We either advanced bytes or chars should == charStart and throw below - Contract.Assert(bytes >= byteStart + 2 || chars == charStart, + Debug.Assert(bytes >= byteStart + 2 || chars == charStart, "[UnicodeEncoding.GetChars]Expected bytes to have advanced or no output (no low surrogate)"); bytes-=2; // didn't use these 2 bytes fallbackBuffer.InternalReset(); @@ -1546,7 +1539,7 @@ namespace System.Text { // 2 bytes couldn't fall back // We either advanced bytes or chars should == charStart and throw below - Contract.Assert(bytes >= byteStart + 2 || chars == charStart, + Debug.Assert(bytes >= byteStart + 2 || chars == charStart, "[UnicodeEncoding.GetChars]Expected bytes to have advanced or no output (normal)"); bytes-=2; // didn't use these bytes ThrowCharsOverflow(decoder, chars == charStart);// Might throw, if no chars output @@ -1591,7 +1584,7 @@ namespace System.Text { // 2 bytes couldn't fall back // We either advanced bytes or chars should == charStart and throw below - Contract.Assert(bytes >= byteStart + 2 || chars == charStart, + Debug.Assert(bytes >= byteStart + 2 || chars == charStart, "[UnicodeEncoding.GetChars]Expected bytes to have advanced or no output (decoder)"); bytes-=2; // didn't use these bytes if (lastByte >= 0) @@ -1644,7 +1637,7 @@ namespace System.Text // Remember our decoder if we must if (decoder != null) { - Contract.Assert((decoder.MustFlush == false) || ((lastChar == (char)0) && (lastByte == -1)), + Debug.Assert((decoder.MustFlush == false) || ((lastChar == (char)0) && (lastByte == -1)), "[UnicodeEncoding.GetChars] Expected no left over chars or bytes if flushing" // + " " + ((int)lastChar).ToString("X4") + " " + lastByte.ToString("X2") ); @@ -1659,7 +1652,7 @@ namespace System.Text // Shouldn't have anything in fallback buffer for GetChars // (don't have to check m_throwOnOverflow for count or chars) - Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, + Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[UnicodeEncoding.GetChars]Expected empty fallback buffer at end"); return (int)(chars - charStart); @@ -1697,7 +1690,7 @@ namespace System.Text public override int GetMaxByteCount(int charCount) { if (charCount < 0) - throw new ArgumentOutOfRangeException("charCount", + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -1711,7 +1704,7 @@ namespace System.Text byteCount <<= 1; if (byteCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(charCount), Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow")); return (int)byteCount; } @@ -1720,7 +1713,7 @@ namespace System.Text public override int GetMaxCharCount(int byteCount) { if (byteCount < 0) - throw new ArgumentOutOfRangeException("byteCount", + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); @@ -1735,7 +1728,7 @@ namespace System.Text charCount *= DecoderFallback.MaxCharCount; if (charCount > 0x7fffffff) - throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow")); + throw new ArgumentOutOfRangeException(nameof(byteCount), Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow")); return (int)charCount; } @@ -1781,7 +1774,7 @@ namespace System.Text internal Decoder(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // Get Common Info @@ -1803,11 +1796,10 @@ namespace System.Text } // ISerializable implementation, get data for this object - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { // Any info? - if (info==null) throw new ArgumentNullException("info"); + if (info==null) throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); // Save Whidbey data diff --git a/src/mscorlib/src/System/Threading/AsyncLocal.cs b/src/mscorlib/src/System/Threading/AsyncLocal.cs index 264f2a6..6ed1545 100644 --- a/src/mscorlib/src/System/Threading/AsyncLocal.cs +++ b/src/mscorlib/src/System/Threading/AsyncLocal.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Security; @@ -40,7 +41,6 @@ namespace System.Threading // public sealed class AsyncLocal : IAsyncLocal { - [SecurityCritical] // critical because this action will terminate the process if it throws. private readonly Action> m_valueChangedHandler; // @@ -54,7 +54,6 @@ namespace System.Threading // Constructs an AsyncLocal with a delegate that is called whenever the current value changes // on any thread. // - [SecurityCritical] public AsyncLocal(Action> valueChangedHandler) { m_valueChangedHandler = valueChangedHandler; @@ -62,23 +61,20 @@ namespace System.Threading public T Value { - [SecuritySafeCritical] get { object obj = ExecutionContext.GetLocalValue(this); return (obj == null) ? default(T) : (T)obj; } - [SecuritySafeCritical] set { ExecutionContext.SetLocalValue(this, value, m_valueChangedHandler != null); } } - [SecurityCritical] void IAsyncLocal.OnValueChanged(object previousValueObj, object currentValueObj, bool contextChanged) { - Contract.Assert(m_valueChangedHandler != null); + Debug.Assert(m_valueChangedHandler != null); T previousValue = previousValueObj == null ? default(T) : (T)previousValueObj; T currentValue = currentValueObj == null ? default(T) : (T)currentValueObj; m_valueChangedHandler(new AsyncLocalValueChangedArgs(previousValue, currentValue, contextChanged)); @@ -90,7 +86,6 @@ namespace System.Threading // internal interface IAsyncLocal { - [SecurityCritical] void OnValueChanged(object previousValue, object currentValue, bool contextChanged); } @@ -113,4 +108,382 @@ namespace System.Threading ThreadContextChanged = contextChanged; } } + + // + // Interface used to store an IAsyncLocal => object mapping in ExecutionContext. + // Implementations are specialized based on the number of elements in the immutable + // map in order to minimize memory consumption and look-up times. + // + interface IAsyncLocalValueMap + { + bool TryGetValue(IAsyncLocal key, out object value); + IAsyncLocalValueMap Set(IAsyncLocal key, object value); + } + + // + // Utility functions for getting/creating instances of IAsyncLocalValueMap + // + internal static class AsyncLocalValueMap + { + public static IAsyncLocalValueMap Empty { get; } = new EmptyAsyncLocalValueMap(); + + public static IAsyncLocalValueMap Create(IAsyncLocal key, object value) => new OneElementAsyncLocalValueMap(key, value); + + // Instance without any key/value pairs. Used as a singleton/ + private sealed class EmptyAsyncLocalValueMap : IAsyncLocalValueMap + { + public IAsyncLocalValueMap Set(IAsyncLocal key, object value) + { + // If the value isn't null, then create a new one-element map to store + // the key/value pair. If it is null, then we're still empty. + return value != null ? + new OneElementAsyncLocalValueMap(key, value) : + (IAsyncLocalValueMap)this; + } + + public bool TryGetValue(IAsyncLocal key, out object value) + { + value = null; + return false; + } + } + + // Instance with one key/value pair. + private sealed class OneElementAsyncLocalValueMap : IAsyncLocalValueMap + { + private readonly IAsyncLocal _key1; + private readonly object _value1; + + public OneElementAsyncLocalValueMap(IAsyncLocal key, object value) + { + _key1 = key; _value1 = value; + } + + public IAsyncLocalValueMap Set(IAsyncLocal key, object value) + { + if (value != null) + { + // The value is non-null. If the key matches one already contained in this map, + // then create a new one-element map with the updated value, otherwise create + // a two-element map with the additional key/value. + return ReferenceEquals(key, _key1) ? + new OneElementAsyncLocalValueMap(key, value) : + (IAsyncLocalValueMap)new TwoElementAsyncLocalValueMap(_key1, _value1, key, value); + } + else + { + // The value is null. If the key exists in this map, remove it by downgrading to an empty map. + // Otherwise, there's nothing to add or remove, so just return this map. + return ReferenceEquals(key, _key1) ? + Empty : + (IAsyncLocalValueMap)this; + } + } + + public bool TryGetValue(IAsyncLocal key, out object value) + { + if (ReferenceEquals(key, _key1)) + { + value = _value1; + return true; + } + else + { + value = null; + return false; + } + } + } + + // Instance with two key/value pairs. + private sealed class TwoElementAsyncLocalValueMap : IAsyncLocalValueMap + { + private readonly IAsyncLocal _key1, _key2; + private readonly object _value1, _value2; + + public TwoElementAsyncLocalValueMap(IAsyncLocal key1, object value1, IAsyncLocal key2, object value2) + { + _key1 = key1; _value1 = value1; + _key2 = key2; _value2 = value2; + } + + public IAsyncLocalValueMap Set(IAsyncLocal key, object value) + { + if (value != null) + { + // The value is non-null. If the key matches one already contained in this map, + // then create a new two-element map with the updated value, otherwise create + // a three-element map with the additional key/value. + return + ReferenceEquals(key, _key1) ? new TwoElementAsyncLocalValueMap(key, value, _key2, _value2) : + ReferenceEquals(key, _key2) ? new TwoElementAsyncLocalValueMap(_key1, _value1, key, value) : + (IAsyncLocalValueMap)new ThreeElementAsyncLocalValueMap(_key1, _value1, _key2, _value2, key, value); + } + else + { + // The value is null. If the key exists in this map, remove it by downgrading to a one-element map + // without the key. Otherwise, there's nothing to add or remove, so just return this map. + return + ReferenceEquals(key, _key1) ? new OneElementAsyncLocalValueMap(_key2, _value2) : + ReferenceEquals(key, _key2) ? new OneElementAsyncLocalValueMap(_key1, _value1) : + (IAsyncLocalValueMap)this; + } + } + + public bool TryGetValue(IAsyncLocal key, out object value) + { + if (ReferenceEquals(key, _key1)) + { + value = _value1; + return true; + } + else if (ReferenceEquals(key, _key2)) + { + value = _value2; + return true; + } + else + { + value = null; + return false; + } + } + } + + // Instance with three key/value pairs. + private sealed class ThreeElementAsyncLocalValueMap : IAsyncLocalValueMap + { + private readonly IAsyncLocal _key1, _key2, _key3; + private readonly object _value1, _value2, _value3; + + public ThreeElementAsyncLocalValueMap(IAsyncLocal key1, object value1, IAsyncLocal key2, object value2, IAsyncLocal key3, object value3) + { + _key1 = key1; _value1 = value1; + _key2 = key2; _value2 = value2; + _key3 = key3; _value3 = value3; + } + + public IAsyncLocalValueMap Set(IAsyncLocal key, object value) + { + if (value != null) + { + // The value is non-null. If the key matches one already contained in this map, + // then create a new three-element map with the updated value. + if (ReferenceEquals(key, _key1)) return new ThreeElementAsyncLocalValueMap(key, value, _key2, _value2, _key3, _value3); + if (ReferenceEquals(key, _key2)) return new ThreeElementAsyncLocalValueMap(_key1, _value1, key, value, _key3, _value3); + if (ReferenceEquals(key, _key3)) return new ThreeElementAsyncLocalValueMap(_key1, _value1, _key2, _value2, key, value); + + // The key doesn't exist in this map, so upgrade to a multi map that contains + // the additional key/value pair. + var multi = new MultiElementAsyncLocalValueMap(4); + multi.UnsafeStore(0, _key1, _value1); + multi.UnsafeStore(1, _key2, _value2); + multi.UnsafeStore(2, _key3, _value3); + multi.UnsafeStore(3, key, value); + return multi; + } + else + { + // The value is null. If the key exists in this map, remove it by downgrading to a two-element map + // without the key. Otherwise, there's nothing to add or remove, so just return this map. + return + ReferenceEquals(key, _key1) ? new TwoElementAsyncLocalValueMap(_key2, _value2, _key3, _value3) : + ReferenceEquals(key, _key2) ? new TwoElementAsyncLocalValueMap(_key1, _value1, _key3, _value3) : + ReferenceEquals(key, _key3) ? new TwoElementAsyncLocalValueMap(_key1, _value1, _key2, _value2) : + (IAsyncLocalValueMap)this; + } + } + + public bool TryGetValue(IAsyncLocal key, out object value) + { + if (ReferenceEquals(key, _key1)) + { + value = _value1; + return true; + } + else if (ReferenceEquals(key, _key2)) + { + value = _value2; + return true; + } + else if (ReferenceEquals(key, _key3)) + { + value = _value3; + return true; + } + else + { + value = null; + return false; + } + } + } + + // Instance with up to 16 key/value pairs. + private sealed class MultiElementAsyncLocalValueMap : IAsyncLocalValueMap + { + internal const int MaxMultiElements = 16; + private readonly KeyValuePair[] _keyValues; + + internal MultiElementAsyncLocalValueMap(int count) + { + Debug.Assert(count <= MaxMultiElements); + _keyValues = new KeyValuePair[count]; + } + + internal void UnsafeStore(int index, IAsyncLocal key, object value) + { + Debug.Assert(index < _keyValues.Length); + _keyValues[index] = new KeyValuePair(key, value); + } + + public IAsyncLocalValueMap Set(IAsyncLocal key, object value) + { + // Find the key in this map. + for (int i = 0; i < _keyValues.Length; i++) + { + if (ReferenceEquals(key, _keyValues[i].Key)) + { + // The key is in the map. If the value isn't null, then create a new map of the same + // size that has all of the same pairs, with this new key/value pair overwriting the old. + if (value != null) + { + var multi = new MultiElementAsyncLocalValueMap(_keyValues.Length); + Array.Copy(_keyValues, 0, multi._keyValues, 0, _keyValues.Length); + multi._keyValues[i] = new KeyValuePair(key, value); + return multi; + } + else if (_keyValues.Length == 4) + { + // The value is null, and we only have four elements, one of which we're removing, + // so downgrade to a three-element map, without the matching element. + return + i == 0 ? new ThreeElementAsyncLocalValueMap(_keyValues[1].Key, _keyValues[1].Value, _keyValues[2].Key, _keyValues[2].Value, _keyValues[3].Key, _keyValues[3].Value) : + i == 1 ? new ThreeElementAsyncLocalValueMap(_keyValues[0].Key, _keyValues[0].Value, _keyValues[2].Key, _keyValues[2].Value, _keyValues[3].Key, _keyValues[3].Value) : + i == 2 ? new ThreeElementAsyncLocalValueMap(_keyValues[0].Key, _keyValues[0].Value, _keyValues[1].Key, _keyValues[1].Value, _keyValues[3].Key, _keyValues[3].Value) : + (IAsyncLocalValueMap)new ThreeElementAsyncLocalValueMap(_keyValues[0].Key, _keyValues[0].Value, _keyValues[1].Key, _keyValues[1].Value, _keyValues[2].Key, _keyValues[2].Value); + } + else + { + // The value is null, and we have enough elements remaining to warrant a multi map. + // Create a new one and copy all of the elements from this one, except the one to be removed. + var multi = new MultiElementAsyncLocalValueMap(_keyValues.Length - 1); + if (i != 0) Array.Copy(_keyValues, 0, multi._keyValues, 0, i); + if (i != _keyValues.Length - 1) Array.Copy(_keyValues, i + 1, multi._keyValues, i, _keyValues.Length - i - 1); + return multi; + } + } + } + + // The key does not already exist in this map. + + // If the value is null, then we can simply return this same map, as there's nothing to add or remove. + if (value == null) + { + return this; + } + + // We need to create a new map that has the additional key/value pair. + // If with the addition we can still fit in a multi map, create one. + if (_keyValues.Length < MaxMultiElements) + { + var multi = new MultiElementAsyncLocalValueMap(_keyValues.Length + 1); + Array.Copy(_keyValues, 0, multi._keyValues, 0, _keyValues.Length); + multi._keyValues[_keyValues.Length] = new KeyValuePair(key, value); + return multi; + } + + // Otherwise, upgrade to a many map. + var many = new ManyElementAsyncLocalValueMap(MaxMultiElements + 1); + foreach (KeyValuePair pair in _keyValues) + { + many[pair.Key] = pair.Value; + } + many[key] = value; + return many; + } + + public bool TryGetValue(IAsyncLocal key, out object value) + { + foreach (KeyValuePair pair in _keyValues) + { + if (ReferenceEquals(key, pair.Key)) + { + value = pair.Value; + return true; + } + } + value = null; + return false; + } + } + + // Instance with any number of key/value pairs. + private sealed class ManyElementAsyncLocalValueMap : Dictionary, IAsyncLocalValueMap + { + public ManyElementAsyncLocalValueMap(int capacity) : base(capacity) { } + + public IAsyncLocalValueMap Set(IAsyncLocal key, object value) + { + int count = Count; + bool containsKey = ContainsKey(key); + + // If the value being set exists, create a new many map, copy all of the elements from this one, + // and then store the new key/value pair into it. This is the most common case. + if (value != null) + { + var map = new ManyElementAsyncLocalValueMap(count + (containsKey ? 0 : 1)); + foreach (KeyValuePair pair in this) + { + map[pair.Key] = pair.Value; + } + map[key] = value; + return map; + } + + // Otherwise, the value is null, which means null is being stored into an AsyncLocal.Value. + // Since there's no observable difference at the API level between storing null and the key + // not existing at all, we can downgrade to a smaller map rather than storing null. + + // If the key is contained in this map, we're going to create a new map that's one pair smaller. + if (containsKey) + { + // If the new count would be within range of a multi map instead of a many map, + // downgrade to the many map, which uses less memory and is faster to access. + // Otherwise, just create a new many map that's missing this key. + if (count == MultiElementAsyncLocalValueMap.MaxMultiElements + 1) + { + var multi = new MultiElementAsyncLocalValueMap(MultiElementAsyncLocalValueMap.MaxMultiElements); + int index = 0; + foreach (KeyValuePair pair in this) + { + if (!ReferenceEquals(key, pair.Key)) + { + multi.UnsafeStore(index++, pair.Key, pair.Value); + } + } + Debug.Assert(index == MultiElementAsyncLocalValueMap.MaxMultiElements); + return multi; + } + else + { + var map = new ManyElementAsyncLocalValueMap(count - 1); + foreach (KeyValuePair pair in this) + { + if (!ReferenceEquals(key, pair.Key)) + { + map[pair.Key] = pair.Value; + } + } + Debug.Assert(map.Count == count - 1); + return map; + } + } + + // We were storing null, but the key wasn't in the map, so there's nothing to change. + // Just return this instance. + return this; + } + } + } } diff --git a/src/mscorlib/src/System/Threading/AutoResetEvent.cs b/src/mscorlib/src/System/Threading/AutoResetEvent.cs index 6fe6c06..78a6fa1 100644 --- a/src/mscorlib/src/System/Threading/AutoResetEvent.cs +++ b/src/mscorlib/src/System/Threading/AutoResetEvent.cs @@ -17,7 +17,6 @@ namespace System.Threading { using System.Security.Permissions; using System.Runtime.InteropServices; - [HostProtection(Synchronization=true, ExternalThreading=true)] [System.Runtime.InteropServices.ComVisible(true)] public sealed class AutoResetEvent : EventWaitHandle { diff --git a/src/mscorlib/src/System/Threading/CancellationToken.cs b/src/mscorlib/src/System/Threading/CancellationToken.cs index 48a2344..5b78f20 100644 --- a/src/mscorlib/src/System/Threading/CancellationToken.cs +++ b/src/mscorlib/src/System/Threading/CancellationToken.cs @@ -8,9 +8,9 @@ #pragma warning disable 0420 // turn off 'a reference to a volatile field will not be treated as volatile' during CAS. using System; -using System.Diagnostics; using System.Runtime.InteropServices; using System.Security.Permissions; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime; using System.Runtime.CompilerServices; @@ -39,7 +39,6 @@ namespace System.Threading /// /// [ComVisible(false)] - [HostProtection(Synchronization = true, ExternalThreading = true)] [DebuggerDisplay("IsCancellationRequested = {IsCancellationRequested}")] public struct CancellationToken { @@ -167,7 +166,7 @@ namespace System.Threading private static void ActionToActionObjShunt(object obj) { Action action = obj as Action; - Contract.Assert(action != null, "Expected an Action here"); + Debug.Assert(action != null, "Expected an Action here"); action(); } @@ -192,7 +191,7 @@ namespace System.Threading public CancellationTokenRegistration Register(Action callback) { if (callback == null) - throw new ArgumentNullException("callback"); + throw new ArgumentNullException(nameof(callback)); return Register( s_ActionToActionObjShunt, @@ -227,7 +226,7 @@ namespace System.Threading public CancellationTokenRegistration Register(Action callback, bool useSynchronizationContext) { if (callback == null) - throw new ArgumentNullException("callback"); + throw new ArgumentNullException(nameof(callback)); return Register( s_ActionToActionObjShunt, @@ -260,7 +259,7 @@ namespace System.Threading public CancellationTokenRegistration Register(Action callback, Object state) { if (callback == null) - throw new ArgumentNullException("callback"); + throw new ArgumentNullException(nameof(callback)); return Register( callback, @@ -318,14 +317,13 @@ namespace System.Threading } // the real work.. - [SecuritySafeCritical] [MethodImpl(MethodImplOptions.NoInlining)] private CancellationTokenRegistration Register(Action callback, Object state, bool useSynchronizationContext, bool useExecutionContext) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; if (callback == null) - throw new ArgumentNullException("callback"); + throw new ArgumentNullException(nameof(callback)); if (CanBeCanceled == false) { diff --git a/src/mscorlib/src/System/Threading/CancellationTokenRegistration.cs b/src/mscorlib/src/System/Threading/CancellationTokenRegistration.cs index 34e0bb0a..ac27fe3 100644 --- a/src/mscorlib/src/System/Threading/CancellationTokenRegistration.cs +++ b/src/mscorlib/src/System/Threading/CancellationTokenRegistration.cs @@ -17,7 +17,6 @@ namespace System.Threading /// /// To unregister a callback, dispose the corresponding Registration instance. /// - [HostProtection(Synchronization = true, ExternalThreading = true)] public struct CancellationTokenRegistration : IEquatable, IDisposable { private readonly CancellationCallbackInfo m_callbackInfo; diff --git a/src/mscorlib/src/System/Threading/CancellationTokenSource.cs b/src/mscorlib/src/System/Threading/CancellationTokenSource.cs index 954cd38..fe9e0de 100644 --- a/src/mscorlib/src/System/Threading/CancellationTokenSource.cs +++ b/src/mscorlib/src/System/Threading/CancellationTokenSource.cs @@ -11,6 +11,7 @@ using System.Security; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Security.Permissions; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime; @@ -35,7 +36,6 @@ namespace System.Threading /// /// [ComVisible(false)] - [HostProtection(Synchronization = true, ExternalThreading = true)] public class CancellationTokenSource : IDisposable { @@ -275,7 +275,7 @@ namespace System.Threading long totalMilliseconds = (long)delay.TotalMilliseconds; if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue) { - throw new ArgumentOutOfRangeException("delay"); + throw new ArgumentOutOfRangeException(nameof(delay)); } InitializeWithTimer((int)totalMilliseconds); @@ -304,7 +304,7 @@ namespace System.Threading { if (millisecondsDelay < -1) { - throw new ArgumentOutOfRangeException("millisecondsDelay"); + throw new ArgumentOutOfRangeException(nameof(millisecondsDelay)); } InitializeWithTimer(millisecondsDelay); @@ -414,7 +414,7 @@ namespace System.Threading long totalMilliseconds = (long)delay.TotalMilliseconds; if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue) { - throw new ArgumentOutOfRangeException("delay"); + throw new ArgumentOutOfRangeException(nameof(delay)); } CancelAfter((int)totalMilliseconds); @@ -450,7 +450,7 @@ namespace System.Threading if (millisecondsDelay < -1) { - throw new ArgumentOutOfRangeException("millisecondsDelay"); + throw new ArgumentOutOfRangeException(nameof(millisecondsDelay)); } if (IsCancellationRequested) return; @@ -629,7 +629,7 @@ namespace System.Threading } // the CancellationToken has already checked that the token is cancelable before calling this method. - Contract.Assert(CanBeCanceled, "Cannot register for uncancelable token src"); + Debug.Assert(CanBeCanceled, "Cannot register for uncancelable token src"); // if not canceled, register the event handlers // if canceled already, run the callback synchronously @@ -730,7 +730,7 @@ namespace System.Threading // - After transition, no more delegates will be added to the // - list of handlers, and hence it can be consumed and cleared at leisure by ExecuteCallbackHandlers. ExecuteCallbackHandlers(throwOnFirstException); - Contract.Assert(IsCancellationCompleted, "Expected cancellation to have finished"); + Debug.Assert(IsCancellationCompleted, "Expected cancellation to have finished"); } } @@ -742,8 +742,8 @@ namespace System.Threading /// private void ExecuteCallbackHandlers(bool throwOnFirstException) { - Contract.Assert(IsCancellationRequested, "ExecuteCallbackHandlers should only be called after setting IsCancellationRequested->true"); - Contract.Assert(ThreadIDExecutingCallbacks != -1, "ThreadIDExecutingCallbacks should have been set."); + Debug.Assert(IsCancellationRequested, "ExecuteCallbackHandlers should only be called after setting IsCancellationRequested->true"); + Debug.Assert(ThreadIDExecutingCallbacks != -1, "ThreadIDExecutingCallbacks should have been set."); // Design decision: call the delegates in LIFO order so that callbacks fire 'deepest first'. // This is intended to help with nesting scenarios so that child enlisters cancel before their parents. @@ -791,7 +791,7 @@ namespace System.Threading var wsc = m_executingCallback as CancellationCallbackInfo.WithSyncContext; if (wsc != null) { - Contract.Assert(wsc.TargetSyncContext != null, "Should only have derived CCI if non-null SyncCtx"); + Debug.Assert(wsc.TargetSyncContext != null, "Should only have derived CCI if non-null SyncCtx"); wsc.TargetSyncContext.Send(CancellationCallbackCoreWork_OnSyncContext, args); // CancellationCallbackCoreWork_OnSyncContext may have altered ThreadIDExecutingCallbacks, so reset it. ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId; @@ -828,7 +828,7 @@ namespace System.Threading if (exceptionList != null) { - Contract.Assert(exceptionList.Count > 0, "Expected exception count > 0"); + Debug.Assert(exceptionList.Count > 0, "Expected exception count > 0"); throw new AggregateException(exceptionList); } } @@ -882,7 +882,7 @@ namespace System.Threading public static CancellationTokenSource CreateLinkedTokenSource(params CancellationToken[] tokens) { if (tokens == null) - throw new ArgumentNullException("tokens"); + throw new ArgumentNullException(nameof(tokens)); if (tokens.Length == 0) throw new ArgumentException(Environment.GetResourceString("CancellationToken_CreateLinkedToken_TokensIsEmpty")); @@ -1029,14 +1029,12 @@ namespace System.Threading } // Cached callback delegate that's lazily initialized due to ContextCallback being SecurityCritical - [SecurityCritical] private static ContextCallback s_executionContextCallback; /// /// InternalExecuteCallbackSynchronously_GeneralPath /// This will be called on the target synchronization context, however, we still need to restore the required execution context /// - [SecuritySafeCritical] internal void ExecuteCallback() { if (TargetExecutionContext != null) @@ -1059,11 +1057,10 @@ namespace System.Threading // the worker method to actually run the callback // The signature is such that it can be used as a 'ContextCallback' - [SecurityCritical] private static void ExecutionContextCallback(object obj) { CancellationCallbackInfo callbackInfo = obj as CancellationCallbackInfo; - Contract.Assert(callbackInfo != null); + Debug.Assert(callbackInfo != null); callbackInfo.Callback(callbackInfo.StateForCallback); } } @@ -1147,14 +1144,14 @@ namespace System.Threading start = 0; curr.m_freeCount--; // Too many free elements; fix up. } - Contract.Assert(start >= 0 && start < c, "start is outside of bounds"); + Debug.Assert(start >= 0 && start < c, "start is outside of bounds"); // Now walk the array until we find a free slot (or reach the end). for (int i = 0; i < c; i++) { // If the slot is null, try to CAS our element into it. int tryIndex = (start + i) % c; - Contract.Assert(tryIndex >= 0 && tryIndex < curr.m_elements.Length, "tryIndex is outside of bounds"); + Debug.Assert(tryIndex >= 0 && tryIndex < curr.m_elements.Length, "tryIndex is outside of bounds"); if (curr.m_elements[tryIndex] == null && Interlocked.CompareExchange(ref curr.m_elements[tryIndex], element, null) == null) { @@ -1193,8 +1190,8 @@ namespace System.Threading internal SparselyPopulatedArrayAddInfo(SparselyPopulatedArrayFragment source, int index) { - Contract.Assert(source != null); - Contract.Assert(index >= 0 && index < source.Length); + Debug.Assert(source != null); + Debug.Assert(index >= 0 && index < source.Length); m_source = source; m_index = index; } diff --git a/src/mscorlib/src/System/Threading/CountdownEvent.cs b/src/mscorlib/src/System/Threading/CountdownEvent.cs index 1374766..d86a2cc 100644 --- a/src/mscorlib/src/System/Threading/CountdownEvent.cs +++ b/src/mscorlib/src/System/Threading/CountdownEvent.cs @@ -11,10 +11,10 @@ // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- using System; -using System.Diagnostics; using System.Security.Permissions; using System.Runtime.InteropServices; using System.Threading; +using System.Diagnostics; using System.Diagnostics.Contracts; namespace System.Threading @@ -32,7 +32,6 @@ namespace System.Threading /// [ComVisible(false)] [DebuggerDisplay("Initial Count={InitialCount}, Current Count={CurrentCount}")] - [HostProtection(Synchronization = true, ExternalThreading = true)] public class CountdownEvent : IDisposable { // CountdownEvent is a simple synchronization primitive used for fork/join parallelism. We create a @@ -59,7 +58,7 @@ namespace System.Threading { if (initialCount < 0) { - throw new ArgumentOutOfRangeException("initialCount"); + throw new ArgumentOutOfRangeException(nameof(initialCount)); } m_initialCount = initialCount; @@ -186,7 +185,7 @@ namespace System.Threading public bool Signal() { ThrowIfDisposed(); - Contract.Assert(m_event != null); + Debug.Assert(m_event != null); if (m_currentCount <= 0) { @@ -229,11 +228,11 @@ namespace System.Threading { if (signalCount <= 0) { - throw new ArgumentOutOfRangeException("signalCount"); + throw new ArgumentOutOfRangeException(nameof(signalCount)); } ThrowIfDisposed(); - Contract.Assert(m_event != null); + Debug.Assert(m_event != null); int observedCount; SpinWait spin = new SpinWait(); @@ -267,7 +266,7 @@ namespace System.Threading return true; } - Contract.Assert(m_currentCount >= 0, "latch was decremented below zero"); + Debug.Assert(m_currentCount >= 0, "latch was decremented below zero"); return false; } @@ -340,7 +339,7 @@ namespace System.Threading { if (signalCount <= 0) { - throw new ArgumentOutOfRangeException("signalCount"); + throw new ArgumentOutOfRangeException(nameof(signalCount)); } ThrowIfDisposed(); @@ -409,7 +408,7 @@ namespace System.Threading if (count < 0) { - throw new ArgumentOutOfRangeException("count"); + throw new ArgumentOutOfRangeException(nameof(count)); } m_currentCount = count; @@ -481,7 +480,7 @@ namespace System.Threading long totalMilliseconds = (long)timeout.TotalMilliseconds; if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue) { - throw new ArgumentOutOfRangeException("timeout"); + throw new ArgumentOutOfRangeException(nameof(timeout)); } return Wait((int)totalMilliseconds, new CancellationToken()); @@ -511,7 +510,7 @@ namespace System.Threading long totalMilliseconds = (long)timeout.TotalMilliseconds; if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue) { - throw new ArgumentOutOfRangeException("timeout"); + throw new ArgumentOutOfRangeException(nameof(timeout)); } return Wait((int)totalMilliseconds, cancellationToken); @@ -555,7 +554,7 @@ namespace System.Threading { if (millisecondsTimeout < -1) { - throw new ArgumentOutOfRangeException("millisecondsTimeout"); + throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout)); } ThrowIfDisposed(); diff --git a/src/mscorlib/src/System/Threading/EventWaitHandle.cs b/src/mscorlib/src/System/Threading/EventWaitHandle.cs index f56da1f..4b1611c 100644 --- a/src/mscorlib/src/System/Threading/EventWaitHandle.cs +++ b/src/mscorlib/src/System/Threading/EventWaitHandle.cs @@ -13,7 +13,6 @@ =============================================================================*/ -#if !FEATURE_MACL namespace System.Security.AccessControl { public class EventWaitHandleSecurity @@ -23,7 +22,6 @@ namespace System.Security.AccessControl { } } -#endif namespace System.Threading { @@ -39,14 +37,11 @@ namespace System.Threading using System.Security.AccessControl; using System.Diagnostics.Contracts; - [HostProtection(Synchronization=true, ExternalThreading=true)] [ComVisibleAttribute(true)] public class EventWaitHandle : WaitHandle { - [System.Security.SecuritySafeCritical] // auto-generated public EventWaitHandle(bool initialState, EventResetMode mode) : this(initialState,mode,null) { } - [System.Security.SecurityCritical] // auto-generated_required public EventWaitHandle(bool initialState, EventResetMode mode, string name) { if(name != null) @@ -56,7 +51,7 @@ namespace System.Threading #else if (System.IO.Path.MaxPath < name.Length) { - throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), nameof(name)); } #endif } @@ -89,13 +84,11 @@ namespace System.Threading SetHandleInternal(_handle); } - [System.Security.SecurityCritical] // auto-generated_required public EventWaitHandle(bool initialState, EventResetMode mode, string name, out bool createdNew) : this(initialState, mode, name, out createdNew, null) { } - [System.Security.SecurityCritical] // auto-generated_required public unsafe EventWaitHandle(bool initialState, EventResetMode mode, string name, out bool createdNew, EventWaitHandleSecurity eventSecurity) { if(name != null) @@ -105,24 +98,12 @@ namespace System.Threading #else if (System.IO.Path.MaxPath < name.Length) { - throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), nameof(name)); } #endif } Contract.EndContractBlock(); Win32Native.SECURITY_ATTRIBUTES secAttrs = null; -#if FEATURE_MACL - // For ACL's, get the security descriptor from the EventWaitHandleSecurity. - if (eventSecurity != null) { - secAttrs = new Win32Native.SECURITY_ATTRIBUTES(); - secAttrs.nLength = (int)Marshal.SizeOf(secAttrs); - - byte[] sd = eventSecurity.GetSecurityDescriptorBinaryForm(); - byte* pSecDescriptor = stackalloc byte[sd.Length]; - Buffer.Memcpy(pSecDescriptor, 0, sd, 0, sd.Length); - secAttrs.pSecurityDescriptor = pSecDescriptor; - } -#endif SafeWaitHandle _handle = null; Boolean isManualReset; @@ -155,23 +136,16 @@ namespace System.Threading SetHandleInternal(_handle); } - [System.Security.SecurityCritical] // auto-generated private EventWaitHandle(SafeWaitHandle handle) { SetHandleInternal(handle); } - [System.Security.SecurityCritical] // auto-generated_required public static EventWaitHandle OpenExisting(string name) { -#if !FEATURE_MACL return OpenExisting(name, (EventWaitHandleRights)0); -#else - return OpenExisting(name, EventWaitHandleRights.Modify | EventWaitHandleRights.Synchronize); -#endif } - [System.Security.SecurityCritical] // auto-generated_required public static EventWaitHandle OpenExisting(string name, EventWaitHandleRights rights) { EventWaitHandle result; @@ -192,23 +166,16 @@ namespace System.Threading } } - [System.Security.SecurityCritical] // auto-generated_required public static bool TryOpenExisting(string name, out EventWaitHandle result) { -#if !FEATURE_MACL return OpenExistingWorker(name, (EventWaitHandleRights)0, out result) == OpenExistingResult.Success; -#else - return OpenExistingWorker(name, EventWaitHandleRights.Modify | EventWaitHandleRights.Synchronize, out result) == OpenExistingResult.Success; -#endif } - [System.Security.SecurityCritical] // auto-generated_required public static bool TryOpenExisting(string name, EventWaitHandleRights rights, out EventWaitHandle result) { return OpenExistingWorker(name, rights, out result) == OpenExistingResult.Success; } - [System.Security.SecurityCritical] // auto-generated_required private static OpenExistingResult OpenExistingWorker(string name, EventWaitHandleRights rights, out EventWaitHandle result) { #if PLATFORM_UNIX @@ -216,29 +183,25 @@ namespace System.Threading #else if (name == null) { - throw new ArgumentNullException("name", Environment.GetResourceString("ArgumentNull_WithParamName")); + throw new ArgumentNullException(nameof(name), Environment.GetResourceString("ArgumentNull_WithParamName")); } if(name.Length == 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(name)); } if(null != name && System.IO.Path.MaxPath < name.Length) { - throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), nameof(name)); } Contract.EndContractBlock(); result = null; -#if FEATURE_MACL - SafeWaitHandle myHandle = Win32Native.OpenEvent((int) rights, false, name); -#else SafeWaitHandle myHandle = Win32Native.OpenEvent(Win32Native.EVENT_MODIFY_STATE | Win32Native.SYNCHRONIZE, false, name); -#endif - + if (myHandle.IsInvalid) { int errorCode = Marshal.GetLastWin32Error(); @@ -256,7 +219,6 @@ namespace System.Threading return OpenExistingResult.Success; #endif } - [System.Security.SecuritySafeCritical] // auto-generated public bool Reset() { bool res = Win32Native.ResetEvent(safeWaitHandle); @@ -264,7 +226,6 @@ namespace System.Threading __Error.WinIOError(); return res; } - [System.Security.SecuritySafeCritical] // auto-generated public bool Set() { bool res = Win32Native.SetEvent(safeWaitHandle); @@ -274,24 +235,6 @@ namespace System.Threading return res; } - -#if FEATURE_MACL - [System.Security.SecuritySafeCritical] // auto-generated - public EventWaitHandleSecurity GetAccessControl() - { - return new EventWaitHandleSecurity(safeWaitHandle, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public void SetAccessControl(EventWaitHandleSecurity eventSecurity) - { - if (eventSecurity == null) - throw new ArgumentNullException("eventSecurity"); - Contract.EndContractBlock(); - - eventSecurity.Persist(safeWaitHandle); - } -#endif } } diff --git a/src/mscorlib/src/System/Threading/ExecutionContext.cs b/src/mscorlib/src/System/Threading/ExecutionContext.cs index 0440368..5ea9942 100644 --- a/src/mscorlib/src/System/Threading/ExecutionContext.cs +++ b/src/mscorlib/src/System/Threading/ExecutionContext.cs @@ -14,33 +14,22 @@ namespace System.Threading using System; using System.Security; using System.Runtime.Remoting; -#if FEATURE_IMPERSONATION - using System.Security.Principal; -#endif using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Runtime.ExceptionServices; using System.Runtime.Serialization; using System.Security.Permissions; -#if FEATURE_REMOTING - using System.Runtime.Remoting.Messaging; -#endif // FEATURE_REMOTING using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Diagnostics.CodeAnalysis; -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif [System.Runtime.InteropServices.ComVisible(true)] public delegate void ContextCallback(Object state); -#if FEATURE_CORECLR - - [SecurityCritical] internal struct ExecutionContextSwitcher { internal ExecutionContext m_ec; @@ -48,7 +37,7 @@ namespace System.Threading internal void Undo(Thread currentThread) { - Contract.Assert(currentThread == Thread.CurrentThread); + Debug.Assert(currentThread == Thread.CurrentThread); // The common case is that these have not changed, so avoid the cost of a write if not needed. if (currentThread.SynchronizationContext != m_sc) @@ -63,32 +52,108 @@ namespace System.Threading } } - public sealed class ExecutionContext : IDisposable + [Serializable] + public sealed class ExecutionContext : IDisposable, ISerializable { private static readonly ExecutionContext Default = new ExecutionContext(); - private readonly Dictionary m_localValues; + private readonly IAsyncLocalValueMap m_localValues; private readonly IAsyncLocal[] m_localChangeNotifications; + private readonly bool m_isFlowSuppressed; private ExecutionContext() { - m_localValues = new Dictionary(); + m_localValues = AsyncLocalValueMap.Empty; m_localChangeNotifications = Array.Empty(); } - private ExecutionContext(Dictionary localValues, IAsyncLocal[] localChangeNotifications) + private ExecutionContext( + IAsyncLocalValueMap localValues, + IAsyncLocal[] localChangeNotifications, + bool isFlowSuppressed) { m_localValues = localValues; m_localChangeNotifications = localChangeNotifications; + m_isFlowSuppressed = isFlowSuppressed; + } + + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + if (info == null) + { + throw new ArgumentNullException(nameof(info)); + } + Contract.EndContractBlock(); + } + + private ExecutionContext(SerializationInfo info, StreamingContext context) + { } - [SecuritySafeCritical] public static ExecutionContext Capture() { - return Thread.CurrentThread.ExecutionContext ?? ExecutionContext.Default; + ExecutionContext executionContext = Thread.CurrentThread.ExecutionContext; + if (executionContext == null) + { + return Default; + } + if (executionContext.m_isFlowSuppressed) + { + // Prevent ExecutionContext.Run on a suppressed-flow context for desktop framework compatibility + return null; + } + return executionContext; + } + + private ExecutionContext ShallowClone(bool isFlowSuppressed) + { + Debug.Assert(isFlowSuppressed != m_isFlowSuppressed); + + if (!isFlowSuppressed && + m_localValues == Default.m_localValues && + m_localChangeNotifications == Default.m_localChangeNotifications) + { + return null; // implies the default context + } + return new ExecutionContext(m_localValues, m_localChangeNotifications, isFlowSuppressed); + } + + public static AsyncFlowControl SuppressFlow() + { + Thread currentThread = Thread.CurrentThread; + ExecutionContext executionContext = currentThread.ExecutionContext ?? Default; + if (executionContext.m_isFlowSuppressed) + { + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotSupressFlowMultipleTimes")); + } + Contract.EndContractBlock(); + + executionContext = executionContext.ShallowClone(isFlowSuppressed: true); + var asyncFlowControl = new AsyncFlowControl(); + currentThread.ExecutionContext = executionContext; + asyncFlowControl.Initialize(currentThread); + return asyncFlowControl; + } + + public static void RestoreFlow() + { + Thread currentThread = Thread.CurrentThread; + ExecutionContext executionContext = currentThread.ExecutionContext; + if (executionContext == null || !executionContext.m_isFlowSuppressed) + { + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotRestoreUnsupressedFlow")); + } + Contract.EndContractBlock(); + + currentThread.ExecutionContext = executionContext.ShallowClone(isFlowSuppressed: false); + } + + public static bool IsFlowSuppressed() + { + ExecutionContext executionContext = Thread.CurrentThread.ExecutionContext; + return executionContext != null && executionContext.m_isFlowSuppressed; } - [SecurityCritical] [HandleProcessCorruptedStateExceptions] public static void Run(ExecutionContext executionContext, ContextCallback callback, Object state) { @@ -115,10 +180,9 @@ namespace System.Threading ecsw.Undo(currentThread); } - [SecurityCritical] internal static void Restore(Thread currentThread, ExecutionContext executionContext) { - Contract.Assert(currentThread == Thread.CurrentThread); + Debug.Assert(currentThread == Thread.CurrentThread); ExecutionContext previous = currentThread.ExecutionContext ?? Default; currentThread.ExecutionContext = executionContext; @@ -133,22 +197,20 @@ namespace System.Threading } } - [SecurityCritical] static internal void EstablishCopyOnWriteScope(Thread currentThread, ref ExecutionContextSwitcher ecsw) { - Contract.Assert(currentThread == Thread.CurrentThread); + Debug.Assert(currentThread == Thread.CurrentThread); ecsw.m_ec = currentThread.ExecutionContext; ecsw.m_sc = currentThread.SynchronizationContext; } - [SecurityCritical] [HandleProcessCorruptedStateExceptions] private static void OnContextChanged(ExecutionContext previous, ExecutionContext current) { - Contract.Assert(previous != null); - Contract.Assert(current != null); - Contract.Assert(previous != current); + Debug.Assert(previous != null); + Debug.Assert(current != null); + Debug.Assert(previous != current); foreach (IAsyncLocal local in previous.m_localChangeNotifications) { @@ -189,7 +251,6 @@ namespace System.Threading } } - [SecurityCritical] internal static object GetLocalValue(IAsyncLocal local) { ExecutionContext current = Thread.CurrentThread.ExecutionContext; @@ -201,7 +262,6 @@ namespace System.Threading return value; } - [SecurityCritical] internal static void SetLocalValue(IAsyncLocal local, object newValue, bool needChangeNotifications) { ExecutionContext current = Thread.CurrentThread.ExecutionContext ?? ExecutionContext.Default; @@ -212,16 +272,7 @@ namespace System.Threading if (previousValue == newValue) return; - // - // Allocate a new Dictionary containing a copy of the old values, plus the new value. We have to do this manually to - // minimize allocations of IEnumerators, etc. - // - Dictionary newValues = new Dictionary(current.m_localValues.Count + (hadPreviousValue ? 0 : 1)); - - foreach (KeyValuePair pair in current.m_localValues) - newValues.Add(pair.Key, pair.Value); - - newValues[local] = newValue; + IAsyncLocalValueMap newValues = current.m_localValues.Set(local, newValue); // // Either copy the change notification array, or create a new one, depending on whether we need to add a new item. @@ -231,7 +282,7 @@ namespace System.Threading { if (hadPreviousValue) { - Contract.Assert(Array.IndexOf(newChangeNotifications, local) >= 0); + Debug.Assert(Array.IndexOf(newChangeNotifications, local) >= 0); } else { @@ -241,7 +292,8 @@ namespace System.Threading } } - Thread.CurrentThread.ExecutionContext = new ExecutionContext(newValues, newChangeNotifications); + Thread.CurrentThread.ExecutionContext = + new ExecutionContext(newValues, newChangeNotifications, current.m_isFlowSuppressed); if (needChangeNotifications) { @@ -259,33 +311,28 @@ namespace System.Threading OptimizeDefaultCase = 0x02, } - [SecurityCritical] internal static ExecutionContext Capture(ref StackCrawlMark stackMark, CaptureOptions captureOptions) { return Capture(); } - [SecuritySafeCritical] [FriendAccessAllowed] internal static ExecutionContext FastCapture() { return Capture(); } - [SecurityCritical] [FriendAccessAllowed] internal static void Run(ExecutionContext executionContext, ContextCallback callback, Object state, bool preserveSyncCtx) { Run(executionContext, callback, state); } - [SecurityCritical] internal bool IsDefaultFTContext(bool ignoreSyncCtx) { return this == Default; } - [SecuritySafeCritical] public ExecutionContext CreateCopy() { return this; // since CoreCLR's ExecutionContext is immutable, we don't need to create copies. @@ -296,14 +343,8 @@ namespace System.Threading // For CLR compat only } - public static bool IsFlowSuppressed() - { - return false; - } - internal static ExecutionContext PreAllocatedDefault { - [SecuritySafeCritical] get { return ExecutionContext.Default; } } @@ -315,1084 +356,77 @@ namespace System.Threading #endregion } -#else // FEATURE_CORECLR - - // Legacy desktop ExecutionContext implementation - - internal struct ExecutionContextSwitcher + public struct AsyncFlowControl : IDisposable { - internal ExecutionContext.Reader outerEC; // previous EC we need to restore on Undo - internal bool outerECBelongsToScope; -#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - internal SecurityContextSwitcher scsw; -#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - internal Object hecsw; -#if FEATURE_IMPERSONATION - internal WindowsIdentity wi; - internal bool cachedAlwaysFlowImpersonationPolicy; - internal bool wiIsValid; -#endif - internal Thread thread; - - [System.Security.SecurityCritical] // auto-generated - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] -#if FEATURE_CORRUPTING_EXCEPTIONS - [HandleProcessCorruptedStateExceptions] -#endif // FEATURE_CORRUPTING_EXCEPTIONS - internal bool UndoNoThrow(Thread currentThread) - { - try - { - Undo(currentThread); - } - catch - { - return false; - } - return true; - } - - [System.Security.SecurityCritical] // auto-generated - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - internal void Undo(Thread currentThread) - { - // - // Don't use an uninitialized switcher, or one that's already been used. - // - if (thread == null) - return; // Don't do anything - - Contract.Assert(Thread.CurrentThread == this.thread); - - // - // Restore the HostExecutionContext before restoring the ExecutionContext. - // -#if FEATURE_CAS_POLICY - if (hecsw != null) - HostExecutionContextSwitcher.Undo(hecsw); -#endif // FEATURE_CAS_POLICY - - // - // restore the saved Execution Context. Note that this will also restore the - // SynchronizationContext, Logical/IllogicalCallContext, etc. - // - ExecutionContext.Reader innerEC = currentThread.GetExecutionContextReader(); - currentThread.SetExecutionContext(outerEC, outerECBelongsToScope); - -#if DEBUG - try - { - currentThread.ForbidExecutionContextMutation = true; -#endif - - // - // Tell the SecurityContext to do the side-effects of restoration. - // -#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - if (scsw.currSC != null) - { - // Any critical failure inside scsw will cause FailFast - scsw.Undo(); - } -#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - -#if FEATURE_IMPERSONATION - if (wiIsValid) - SecurityContext.RestoreCurrentWI(outerEC, innerEC, wi, cachedAlwaysFlowImpersonationPolicy); -#endif - - thread = null; // this will prevent the switcher object being used again -#if DEBUG - } - finally - { - currentThread.ForbidExecutionContextMutation = false; - } -#endif - ExecutionContext.OnAsyncLocalContextChanged(innerEC.DangerousGetRawExecutionContext(), outerEC.DangerousGetRawExecutionContext()); - } - } - - - public struct AsyncFlowControl: IDisposable - { - private bool useEC; - private ExecutionContext _ec; -#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - private SecurityContext _sc; -#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK private Thread _thread; -#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - [SecurityCritical] - internal void Setup(SecurityContextDisableFlow flags) - { - useEC = false; - Thread currentThread = Thread.CurrentThread; - _sc = currentThread.GetMutableExecutionContext().SecurityContext; - _sc._disableFlow = flags; - _thread = currentThread; - } -#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - [SecurityCritical] - internal void Setup() + + internal void Initialize(Thread currentThread) { - useEC = true; - Thread currentThread = Thread.CurrentThread; - _ec = currentThread.GetMutableExecutionContext(); - _ec.isFlowSuppressed = true; + Debug.Assert(currentThread == Thread.CurrentThread); _thread = currentThread; } - - public void Dispose() - { - Undo(); - } - - [SecuritySafeCritical] + public void Undo() { if (_thread == null) { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotUseAFCMultiple")); - } - if (_thread != Thread.CurrentThread) - { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotUseAFCOtherThread")); - } - if (useEC) - { - if (Thread.CurrentThread.GetMutableExecutionContext() != _ec) - { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsyncFlowCtrlCtxMismatch")); - } - ExecutionContext.RestoreFlow(); - } -#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - else - { - if (!Thread.CurrentThread.GetExecutionContextReader().SecurityContext.IsSame(_sc)) - { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsyncFlowCtrlCtxMismatch")); - } - SecurityContext.RestoreFlow(); - } -#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - _thread = null; - } - - public override int GetHashCode() - { - return _thread == null ? ToString().GetHashCode() : _thread.GetHashCode(); - } - - public override bool Equals(Object obj) - { - if (obj is AsyncFlowControl) - return Equals((AsyncFlowControl)obj); - else - return false; - } - - public bool Equals(AsyncFlowControl obj) - { - return obj.useEC == useEC && obj._ec == _ec && -#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - obj._sc == _sc && -#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - obj._thread == _thread; - } - - public static bool operator ==(AsyncFlowControl a, AsyncFlowControl b) - { - return a.Equals(b); - } - - public static bool operator !=(AsyncFlowControl a, AsyncFlowControl b) - { - return !(a == b); - } - - } - - -#if FEATURE_SERIALIZATION - [Serializable] -#endif - public sealed class ExecutionContext : IDisposable, ISerializable - { - /*========================================================================= - ** Data accessed from managed code that needs to be defined in - ** ExecutionContextObject to maintain alignment between the two classes. - ** DON'T CHANGE THESE UNLESS YOU MODIFY ExecutionContextObject in vm\object.h - =========================================================================*/ -#if FEATURE_CAS_POLICY - private HostExecutionContext _hostExecutionContext; -#endif // FEATURE_CAS_POLICY - private SynchronizationContext _syncContext; - private SynchronizationContext _syncContextNoFlow; -#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - private SecurityContext _securityContext; -#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK -#if FEATURE_REMOTING - [System.Security.SecurityCritical] // auto-generated - private LogicalCallContext _logicalCallContext; - private IllogicalCallContext _illogicalCallContext; // this call context follows the physical thread -#endif // #if FEATURE_REMOTING - - enum Flags - { - None = 0x0, - IsNewCapture = 0x1, - IsFlowSuppressed = 0x2, - IsPreAllocatedDefault = 0x4 - } - private Flags _flags; - - private Dictionary _localValues; - private List _localChangeNotifications; - - internal bool isNewCapture - { - get - { - return (_flags & (Flags.IsNewCapture | Flags.IsPreAllocatedDefault)) != Flags.None; - } - set - { - Contract.Assert(!IsPreAllocatedDefault); - if (value) - _flags |= Flags.IsNewCapture; - else - _flags &= ~Flags.IsNewCapture; - } - } - internal bool isFlowSuppressed - { - get - { - return (_flags & Flags.IsFlowSuppressed) != Flags.None; - } - set - { - Contract.Assert(!IsPreAllocatedDefault); - if (value) - _flags |= Flags.IsFlowSuppressed; - else - _flags &= ~Flags.IsFlowSuppressed; - } - } - - - private static readonly ExecutionContext s_dummyDefaultEC = new ExecutionContext(isPreAllocatedDefault: true); - - static internal ExecutionContext PreAllocatedDefault - { - [SecuritySafeCritical] - get { return s_dummyDefaultEC; } - } - - internal bool IsPreAllocatedDefault - { - get - { - // we use _flags instead of a direct comparison w/ s_dummyDefaultEC to avoid the static access on - // hot code paths. - if ((_flags & Flags.IsPreAllocatedDefault) != Flags.None) - { - Contract.Assert(this == s_dummyDefaultEC); - return true; - } - else - { - return false; - } - } - } - - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - internal ExecutionContext() - { - } - - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - internal ExecutionContext(bool isPreAllocatedDefault) - { - if (isPreAllocatedDefault) - _flags = Flags.IsPreAllocatedDefault; - } - - // Read-only wrapper around ExecutionContext. This enables safe reading of an ExecutionContext without accidentally modifying it. - internal struct Reader - { - ExecutionContext m_ec; - - public Reader(ExecutionContext ec) { m_ec = ec; } - - public ExecutionContext DangerousGetRawExecutionContext() { return m_ec; } - - public bool IsNull { get { return m_ec == null; } } - [SecurityCritical] - public bool IsDefaultFTContext(bool ignoreSyncCtx) { return m_ec.IsDefaultFTContext(ignoreSyncCtx); } - public bool IsFlowSuppressed - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { return IsNull ? false : m_ec.isFlowSuppressed; } - } - //public Thread Thread { get { return m_ec._thread; } } - public bool IsSame(ExecutionContext.Reader other) { return m_ec == other.m_ec; } - - public SynchronizationContext SynchronizationContext { get { return IsNull ? null : m_ec.SynchronizationContext; } } - public SynchronizationContext SynchronizationContextNoFlow { get { return IsNull ? null : m_ec.SynchronizationContextNoFlow; } } - -#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - public SecurityContext.Reader SecurityContext - { - [SecurityCritical] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { return new SecurityContext.Reader(IsNull ? null : m_ec.SecurityContext); } - } -#endif - -#if FEATURE_REMOTING - public LogicalCallContext.Reader LogicalCallContext - { - [SecurityCritical] - get { return new LogicalCallContext.Reader(IsNull ? null : m_ec.LogicalCallContext); } - } - - public IllogicalCallContext.Reader IllogicalCallContext - { - [SecurityCritical] - get { return new IllogicalCallContext.Reader(IsNull ? null : m_ec.IllogicalCallContext); } - } -#endif - - [SecurityCritical] - public object GetLocalValue(IAsyncLocal local) - { - if (IsNull) - return null; - - if (m_ec._localValues == null) - return null; - - object value; - m_ec._localValues.TryGetValue(local, out value); - return value; - } - - [SecurityCritical] - public bool HasSameLocalValues(ExecutionContext other) - { - var thisLocalValues = IsNull ? null : m_ec._localValues; - var otherLocalValues = other == null ? null : other._localValues; - return thisLocalValues == otherLocalValues; - } - - [SecurityCritical] - public bool HasLocalValues() - { - return !this.IsNull && m_ec._localValues != null; - } - } - - [SecurityCritical] - internal static object GetLocalValue(IAsyncLocal local) - { - return Thread.CurrentThread.GetExecutionContextReader().GetLocalValue(local); - } - - [SecurityCritical] - internal static void SetLocalValue(IAsyncLocal local, object newValue, bool needChangeNotifications) - { - ExecutionContext current = Thread.CurrentThread.GetMutableExecutionContext(); - - object previousValue = null; - bool hadPreviousValue = current._localValues != null && current._localValues.TryGetValue(local, out previousValue); - - if (previousValue == newValue) - return; - - if (current._localValues == null) - current._localValues = new Dictionary(); - else - current._localValues = new Dictionary(current._localValues); - - current._localValues[local] = newValue; - - if (needChangeNotifications) - { - if (hadPreviousValue) - { - Contract.Assert(current._localChangeNotifications != null); - Contract.Assert(current._localChangeNotifications.Contains(local)); - } - else - { - if (current._localChangeNotifications == null) - current._localChangeNotifications = new List(); - else - current._localChangeNotifications = new List(current._localChangeNotifications); - - current._localChangeNotifications.Add(local); - } - - local.OnValueChanged(previousValue, newValue, false); - } - } - - [SecurityCritical] - [HandleProcessCorruptedStateExceptions] - internal static void OnAsyncLocalContextChanged(ExecutionContext previous, ExecutionContext current) - { - List previousLocalChangeNotifications = (previous == null) ? null : previous._localChangeNotifications; - if (previousLocalChangeNotifications != null) - { - foreach (IAsyncLocal local in previousLocalChangeNotifications) - { - object previousValue = null; - if (previous != null && previous._localValues != null) - previous._localValues.TryGetValue(local, out previousValue); - - object currentValue = null; - if (current != null && current._localValues != null) - current._localValues.TryGetValue(local, out currentValue); - - if (previousValue != currentValue) - local.OnValueChanged(previousValue, currentValue, true); - } - } - - List currentLocalChangeNotifications = (current == null) ? null : current._localChangeNotifications; - if (currentLocalChangeNotifications != null && currentLocalChangeNotifications != previousLocalChangeNotifications) - { - try - { - foreach (IAsyncLocal local in currentLocalChangeNotifications) - { - // If the local has a value in the previous context, we already fired the event for that local - // in the code above. - object previousValue = null; - if (previous == null || - previous._localValues == null || - !previous._localValues.TryGetValue(local, out previousValue)) - { - object currentValue = null; - if (current != null && current._localValues != null) - current._localValues.TryGetValue(local, out currentValue); - - if (previousValue != currentValue) - local.OnValueChanged(previousValue, currentValue, true); - } - } - } - catch (Exception ex) - { - Environment.FailFast( - Environment.GetResourceString("ExecutionContext_ExceptionInAsyncLocalNotification"), - ex); - } - } - } - - -#if FEATURE_REMOTING - internal LogicalCallContext LogicalCallContext - { - [System.Security.SecurityCritical] // auto-generated - get - { - if (_logicalCallContext == null) - { - _logicalCallContext = new LogicalCallContext(); - } - return _logicalCallContext; - } - [System.Security.SecurityCritical] // auto-generated - set - { - Contract.Assert(this != s_dummyDefaultEC); - _logicalCallContext = value; - } - } - - internal IllogicalCallContext IllogicalCallContext - { - get - { - if (_illogicalCallContext == null) - { - _illogicalCallContext = new IllogicalCallContext(); - } - return _illogicalCallContext; - } - set - { - Contract.Assert(this != s_dummyDefaultEC); - _illogicalCallContext = value; - } - } -#endif // #if FEATURE_REMOTING - - internal SynchronizationContext SynchronizationContext - { - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - get - { - return _syncContext; - } - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - set - { - Contract.Assert(this != s_dummyDefaultEC); - _syncContext = value; - } - } - - internal SynchronizationContext SynchronizationContextNoFlow - { - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - get - { - return _syncContextNoFlow; - } - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - set - { - Contract.Assert(this != s_dummyDefaultEC); - _syncContextNoFlow = value; - } - } - -#if FEATURE_CAS_POLICY - internal HostExecutionContext HostExecutionContext - { - get - { - return _hostExecutionContext; } - set + if (Thread.CurrentThread != _thread) { - Contract.Assert(this != s_dummyDefaultEC); - _hostExecutionContext = value; - } - } -#endif // FEATURE_CAS_POLICY -#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - internal SecurityContext SecurityContext - { - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - get - { - return _securityContext; - } - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - set - { - Contract.Assert(this != s_dummyDefaultEC); - // store the new security context - _securityContext = value; - // perform the reverse link too - if (value != null) - _securityContext.ExecutionContext = this; - } - } -#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - - - public void Dispose() - { - if(this.IsPreAllocatedDefault) - return; //Do nothing if this is the default context -#if FEATURE_CAS_POLICY - if (_hostExecutionContext != null) - _hostExecutionContext.Dispose(); -#endif // FEATURE_CAS_POLICY -#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - if (_securityContext != null) - _securityContext.Dispose(); -#endif //FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - } - - [DynamicSecurityMethod] - [System.Security.SecurityCritical] // auto-generated_required - public static void Run(ExecutionContext executionContext, ContextCallback callback, Object state) - { - if (executionContext == null) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NullContext")); - if (!executionContext.isNewCapture) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotNewCaptureContext")); - - Run(executionContext, callback, state, false); - } - - // This method is special from a security perspective - the VM will not allow a stack walk to - // continue past the call to ExecutionContext.Run. If you change the signature to this method, make - // sure to update SecurityStackWalk::IsSpecialRunFrame in the VM to search for the new signature. - [DynamicSecurityMethod] - [SecurityCritical] - [FriendAccessAllowed] - internal static void Run(ExecutionContext executionContext, ContextCallback callback, Object state, bool preserveSyncCtx) - { - RunInternal(executionContext, callback, state, preserveSyncCtx); - } - - // Actual implementation of Run is here, in a non-DynamicSecurityMethod, because the JIT seems to refuse to inline callees into - // a DynamicSecurityMethod. - [SecurityCritical] - [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")] - [HandleProcessCorruptedStateExceptions] - internal static void RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, bool preserveSyncCtx) - { - Contract.Assert(executionContext != null); - if (executionContext.IsPreAllocatedDefault) - { - Contract.Assert(executionContext.IsDefaultFTContext(preserveSyncCtx)); - } - else - { - Contract.Assert(executionContext.isNewCapture); - executionContext.isNewCapture = false; - } - - Thread currentThread = Thread.CurrentThread; - ExecutionContextSwitcher ecsw = default(ExecutionContextSwitcher); - - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - ExecutionContext.Reader ec = currentThread.GetExecutionContextReader(); - if ( (ec.IsNull || ec.IsDefaultFTContext(preserveSyncCtx)) && - #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - SecurityContext.CurrentlyInDefaultFTSecurityContext(ec) && - #endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - executionContext.IsDefaultFTContext(preserveSyncCtx) && - ec.HasSameLocalValues(executionContext) - ) - { - // Neither context is interesting, so we don't need to set the context. - // We do need to reset any changes made by the user's callback, - // so here we establish a "copy-on-write scope". Any changes will - // result in a copy of the context being made, preserving the original - // context. - EstablishCopyOnWriteScope(currentThread, true, ref ecsw); - } - else - { - if (executionContext.IsPreAllocatedDefault) - executionContext = new ExecutionContext(); - ecsw = SetExecutionContext(executionContext, preserveSyncCtx); - } - - // - // Call the user's callback - // - callback(state); - } - finally - { - ecsw.Undo(currentThread); - } - } - - [SecurityCritical] - static internal void EstablishCopyOnWriteScope(Thread currentThread, ref ExecutionContextSwitcher ecsw) - { - EstablishCopyOnWriteScope(currentThread, false, ref ecsw); - } - - [SecurityCritical] - static private void EstablishCopyOnWriteScope(Thread currentThread, bool knownNullWindowsIdentity, ref ExecutionContextSwitcher ecsw) - { - Contract.Assert(currentThread == Thread.CurrentThread); - - ecsw.outerEC = currentThread.GetExecutionContextReader(); - ecsw.outerECBelongsToScope = currentThread.ExecutionContextBelongsToCurrentScope; - -#if FEATURE_IMPERSONATION - ecsw.cachedAlwaysFlowImpersonationPolicy = SecurityContext.AlwaysFlowImpersonationPolicy; - if (knownNullWindowsIdentity) - Contract.Assert(SecurityContext.GetCurrentWI(ecsw.outerEC, ecsw.cachedAlwaysFlowImpersonationPolicy) == null); - else - ecsw.wi = SecurityContext.GetCurrentWI(ecsw.outerEC, ecsw.cachedAlwaysFlowImpersonationPolicy); - ecsw.wiIsValid = true; -#endif - currentThread.ExecutionContextBelongsToCurrentScope = false; - ecsw.thread = currentThread; - } - - - // Sets the given execution context object on the thread. - // Returns the previous one. - [System.Security.SecurityCritical] // auto-generated - [DynamicSecurityMethodAttribute()] - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable -#if FEATURE_CORRUPTING_EXCEPTIONS - [HandleProcessCorruptedStateExceptions] -#endif // FEATURE_CORRUPTING_EXCEPTIONS - internal static ExecutionContextSwitcher SetExecutionContext(ExecutionContext executionContext, bool preserveSyncCtx) - { -#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; -#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - - Contract.Assert(executionContext != null); - Contract.Assert(executionContext != s_dummyDefaultEC); - - // Set up the switcher object to return; - ExecutionContextSwitcher ecsw = new ExecutionContextSwitcher(); - - Thread currentThread = Thread.CurrentThread; - ExecutionContext.Reader outerEC = currentThread.GetExecutionContextReader(); - - ecsw.thread = currentThread; - ecsw.outerEC = outerEC; - ecsw.outerECBelongsToScope = currentThread.ExecutionContextBelongsToCurrentScope; - - if (preserveSyncCtx) - executionContext.SynchronizationContext = outerEC.SynchronizationContext; - executionContext.SynchronizationContextNoFlow = outerEC.SynchronizationContextNoFlow; - - currentThread.SetExecutionContext(executionContext, belongsToCurrentScope: true); - - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - OnAsyncLocalContextChanged(outerEC.DangerousGetRawExecutionContext(), executionContext); - -#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - //set the security context - SecurityContext sc = executionContext.SecurityContext; - if (sc != null) - { - // non-null SC: needs to be set - SecurityContext.Reader prevSeC = outerEC.SecurityContext; - ecsw.scsw = SecurityContext.SetSecurityContext(sc, prevSeC, false, ref stackMark); - } - else if (!SecurityContext.CurrentlyInDefaultFTSecurityContext(ecsw.outerEC)) - { - // null incoming SC, but we're currently not in FT: use static FTSC to set - SecurityContext.Reader prevSeC = outerEC.SecurityContext; - ecsw.scsw = SecurityContext.SetSecurityContext(SecurityContext.FullTrustSecurityContext, prevSeC, false, ref stackMark); - } -#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK -#if FEATURE_CAS_POLICY - // set the Host Context - HostExecutionContext hostContext = executionContext.HostExecutionContext; - if (hostContext != null) - { - ecsw.hecsw = HostExecutionContextManager.SetHostExecutionContextInternal(hostContext); - } -#endif // FEATURE_CAS_POLICY - } - catch - { - ecsw.UndoNoThrow(currentThread); - throw; - } - return ecsw; - } - - // - // Public CreateCopy. Used to copy captured ExecutionContexts so they can be reused multiple times. - // This should only copy the portion of the context that we actually capture. - // - [SecuritySafeCritical] - public ExecutionContext CreateCopy() - { - if (!isNewCapture) - { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotCopyUsedContext")); - } - ExecutionContext ec = new ExecutionContext(); - ec.isNewCapture = true; - ec._syncContext = _syncContext == null ? null : _syncContext.CreateCopy(); - ec._localValues = _localValues; - ec._localChangeNotifications = _localChangeNotifications; -#if FEATURE_CAS_POLICY - // capture the host execution context - ec._hostExecutionContext = _hostExecutionContext == null ? null : _hostExecutionContext.CreateCopy(); -#endif // FEATURE_CAS_POLICY -#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - if (_securityContext != null) - { - ec._securityContext = _securityContext.CreateCopy(); - ec._securityContext.ExecutionContext = ec; + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotUseAFCOtherThread")); } -#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - -#if FEATURE_REMOTING - if (this._logicalCallContext != null) - ec.LogicalCallContext = (LogicalCallContext)this.LogicalCallContext.Clone(); - - Contract.Assert(this._illogicalCallContext == null); -#endif // #if FEATURE_REMOTING - - return ec; - } - - // - // Creates a complete copy, used for copy-on-write. - // - [SecuritySafeCritical] - internal ExecutionContext CreateMutableCopy() - { - Contract.Assert(!this.isNewCapture); - - ExecutionContext ec = new ExecutionContext(); - // We don't deep-copy the SyncCtx, since we're still in the same context after copy-on-write. - ec._syncContext = this._syncContext; - ec._syncContextNoFlow = this._syncContextNoFlow; - -#if FEATURE_CAS_POLICY - // capture the host execution context - ec._hostExecutionContext = this._hostExecutionContext == null ? null : _hostExecutionContext.CreateCopy(); -#endif // FEATURE_CAS_POLICY - -#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - if (_securityContext != null) + // An async flow control cannot be undone when a different execution context is applied. The desktop framework + // mutates the execution context when its state changes, and only changes the instance when an execution context + // is applied (for instance, through ExecutionContext.Run). The framework prevents a suppressed-flow execution + // context from being applied by returning null from ExecutionContext.Capture, so the only type of execution + // context that can be applied is one whose flow is not suppressed. After suppressing flow and changing an async + // local's value, the desktop framework verifies that a different execution context has not been applied by + // checking the execution context instance against the one saved from when flow was suppressed. In .NET Core, + // since the execution context instance will change after changing the async local's value, it verifies that a + // different execution context has not been applied, by instead ensuring that the current execution context's + // flow is suppressed. + if (!ExecutionContext.IsFlowSuppressed()) { - ec._securityContext = this._securityContext.CreateMutableCopy(); - ec._securityContext.ExecutionContext = ec; - } -#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - -#if FEATURE_REMOTING - if (this._logicalCallContext != null) - ec.LogicalCallContext = (LogicalCallContext)this.LogicalCallContext.Clone(); - - if (this._illogicalCallContext != null) - ec.IllogicalCallContext = (IllogicalCallContext)this.IllogicalCallContext.CreateCopy(); -#endif // #if FEATURE_REMOTING - - ec._localValues = this._localValues; - ec._localChangeNotifications = this._localChangeNotifications; - ec.isFlowSuppressed = this.isFlowSuppressed; - - return ec; - } - - [System.Security.SecurityCritical] // auto-generated_required - public static AsyncFlowControl SuppressFlow() - { - if (IsFlowSuppressed()) - { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotSupressFlowMultipleTimes")); + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsyncFlowCtrlCtxMismatch")); } Contract.EndContractBlock(); - AsyncFlowControl afc = new AsyncFlowControl(); - afc.Setup(); - return afc; - } - - [SecuritySafeCritical] - public static void RestoreFlow() - { - ExecutionContext ec = Thread.CurrentThread.GetMutableExecutionContext(); - if (!ec.isFlowSuppressed) - { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotRestoreUnsupressedFlow")); - } - ec.isFlowSuppressed = false; - } - [Pure] - public static bool IsFlowSuppressed() - { - return Thread.CurrentThread.GetExecutionContextReader().IsFlowSuppressed; + _thread = null; + ExecutionContext.RestoreFlow(); } - [System.Security.SecuritySafeCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - public static ExecutionContext Capture() + public void Dispose() { - // set up a stack mark for finding the caller - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return ExecutionContext.Capture(ref stackMark, CaptureOptions.None); + Undo(); } - // - // Captures an ExecutionContext with optimization for the "default" case, and captures a "null" synchronization context. - // When calling ExecutionContext.Run on the returned context, specify ignoreSyncCtx = true - // - [System.Security.SecuritySafeCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - [FriendAccessAllowed] - internal static ExecutionContext FastCapture() + public override bool Equals(object obj) { - // set up a stack mark for finding the caller - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return ExecutionContext.Capture(ref stackMark, CaptureOptions.IgnoreSyncCtx | CaptureOptions.OptimizeDefaultCase); + return obj is AsyncFlowControl && Equals((AsyncFlowControl)obj); } - - [Flags] - internal enum CaptureOptions + public bool Equals(AsyncFlowControl obj) { - None = 0x00, - - IgnoreSyncCtx = 0x01, //Don't flow SynchronizationContext - - OptimizeDefaultCase = 0x02, //Faster in the typical case, but can't show the result to users - // because they could modify the shared default EC. - // Use this only if you won't be exposing the captured EC to users. + return _thread == obj._thread; } - // internal helper to capture the current execution context using a passed in stack mark - [System.Security.SecurityCritical] // auto-generated - static internal ExecutionContext Capture(ref StackCrawlMark stackMark, CaptureOptions options) + public override int GetHashCode() { - ExecutionContext.Reader ecCurrent = Thread.CurrentThread.GetExecutionContextReader(); - - // check to see if Flow is suppressed - if (ecCurrent.IsFlowSuppressed) - return null; - - // - // Attempt to capture context. There may be nothing to capture... - // - -#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - // capture the security context - SecurityContext secCtxNew = SecurityContext.Capture(ecCurrent, ref stackMark); -#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK -#if FEATURE_CAS_POLICY - // capture the host execution context - HostExecutionContext hostCtxNew = HostExecutionContextManager.CaptureHostExecutionContext(); -#endif // FEATURE_CAS_POLICY - - SynchronizationContext syncCtxNew = null; - -#if FEATURE_REMOTING - LogicalCallContext logCtxNew = null; -#endif - - if (!ecCurrent.IsNull) - { - // capture the sync context - if (0 == (options & CaptureOptions.IgnoreSyncCtx)) - syncCtxNew = (ecCurrent.SynchronizationContext == null) ? null : ecCurrent.SynchronizationContext.CreateCopy(); - -#if FEATURE_REMOTING - // copy over the Logical Call Context - if (ecCurrent.LogicalCallContext.HasInfo) - logCtxNew = ecCurrent.LogicalCallContext.Clone(); -#endif // #if FEATURE_REMOTING - } - - Dictionary localValues = null; - List localChangeNotifications = null; - if (!ecCurrent.IsNull) - { - localValues = ecCurrent.DangerousGetRawExecutionContext()._localValues; - localChangeNotifications = ecCurrent.DangerousGetRawExecutionContext()._localChangeNotifications; - } - - // - // If we didn't get anything but defaults, and we're allowed to return the - // dummy default EC, don't bother allocating a new context. - // - if (0 != (options & CaptureOptions.OptimizeDefaultCase) && -#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - secCtxNew == null && -#endif -#if FEATURE_CAS_POLICY - hostCtxNew == null && -#endif // FEATURE_CAS_POLICY - syncCtxNew == null && -#if FEATURE_REMOTING - (logCtxNew == null || !logCtxNew.HasInfo) && -#endif // #if FEATURE_REMOTING - localValues == null && - localChangeNotifications == null - ) - { - return s_dummyDefaultEC; - } - - // - // Allocate the new context, and fill it in. - // - ExecutionContext ecNew = new ExecutionContext(); -#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - ecNew.SecurityContext = secCtxNew; - if (ecNew.SecurityContext != null) - ecNew.SecurityContext.ExecutionContext = ecNew; -#endif -#if FEATURE_CAS_POLICY - ecNew._hostExecutionContext = hostCtxNew; -#endif // FEATURE_CAS_POLICY - ecNew._syncContext = syncCtxNew; -#if FEATURE_REMOTING - ecNew.LogicalCallContext = logCtxNew; -#endif // #if FEATURE_REMOTING - ecNew._localValues = localValues; - ecNew._localChangeNotifications = localChangeNotifications; - ecNew.isNewCapture = true; - - return ecNew; + return _thread?.GetHashCode() ?? 0; } - // - // Implementation of ISerializable - // - - [System.Security.SecurityCritical] // auto-generated_required - public void GetObjectData(SerializationInfo info, StreamingContext context) + public static bool operator ==(AsyncFlowControl a, AsyncFlowControl b) { - if (info==null) - throw new ArgumentNullException("info"); - Contract.EndContractBlock(); - -#if FEATURE_REMOTING - if (_logicalCallContext != null) - { - info.AddValue("LogicalCallContext", _logicalCallContext, typeof(LogicalCallContext)); - } -#endif // #if FEATURE_REMOTING + return a.Equals(b); } - [System.Security.SecurityCritical] // auto-generated - private ExecutionContext(SerializationInfo info, StreamingContext context) - { - SerializationInfoEnumerator e = info.GetEnumerator(); - while (e.MoveNext()) - { -#if FEATURE_REMOTING - if (e.Name.Equals("LogicalCallContext")) - { - _logicalCallContext = (LogicalCallContext) e.Value; - } -#endif // #if FEATURE_REMOTING - } - } // ObjRef .ctor - - - [System.Security.SecurityCritical] // auto-generated - internal bool IsDefaultFTContext(bool ignoreSyncCtx) + public static bool operator !=(AsyncFlowControl a, AsyncFlowControl b) { -#if FEATURE_CAS_POLICY - if (_hostExecutionContext != null) - return false; -#endif // FEATURE_CAS_POLICY - if (!ignoreSyncCtx && _syncContext != null) - return false; -#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK - if (_securityContext != null && !_securityContext.IsDefaultFTSecurityContext()) - return false; -#endif //#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK -#if FEATURE_REMOTING - if (_logicalCallContext != null && _logicalCallContext.HasInfo) - return false; - if (_illogicalCallContext != null && _illogicalCallContext.HasUserData) - return false; -#endif //#if FEATURE_REMOTING - return true; + return !(a == b); } - } // class ExecutionContext - -#endif //FEATURE_CORECLR + } } diff --git a/src/mscorlib/src/System/Threading/Interlocked.cs b/src/mscorlib/src/System/Threading/Interlocked.cs index 50cc766..8a0b527 100644 --- a/src/mscorlib/src/System/Threading/Interlocked.cs +++ b/src/mscorlib/src/System/Threading/Interlocked.cs @@ -66,34 +66,27 @@ namespace System.Threading [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [System.Security.SecuritySafeCritical] public static extern int Exchange(ref int location1, int value); [MethodImplAttribute(MethodImplOptions.InternalCall)] - [System.Security.SecuritySafeCritical] public static extern long Exchange(ref long location1, long value); [MethodImplAttribute(MethodImplOptions.InternalCall)] - [System.Security.SecuritySafeCritical] public static extern float Exchange(ref float location1, float value); [MethodImplAttribute(MethodImplOptions.InternalCall)] - [System.Security.SecuritySafeCritical] public static extern double Exchange(ref double location1, double value); [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [System.Security.SecuritySafeCritical] public static extern Object Exchange(ref Object location1, Object value); [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [System.Security.SecuritySafeCritical] public static extern IntPtr Exchange(ref IntPtr location1, IntPtr value); [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [System.Runtime.InteropServices.ComVisible(false)] - [System.Security.SecuritySafeCritical] public static T Exchange(ref T location1, T value) where T : class { _Exchange(__makeref(location1), __makeref(value)); @@ -106,7 +99,6 @@ namespace System.Threading [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [System.Security.SecuritySafeCritical] private static extern void _Exchange(TypedReference location1, TypedReference value); /****************************** @@ -121,29 +113,23 @@ namespace System.Threading [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [System.Security.SecuritySafeCritical] public static extern int CompareExchange(ref int location1, int value, int comparand); [MethodImplAttribute(MethodImplOptions.InternalCall)] - [System.Security.SecuritySafeCritical] public static extern long CompareExchange(ref long location1, long value, long comparand); [MethodImplAttribute(MethodImplOptions.InternalCall)] - [System.Security.SecuritySafeCritical] public static extern float CompareExchange(ref float location1, float value, float comparand); [MethodImplAttribute(MethodImplOptions.InternalCall)] - [System.Security.SecuritySafeCritical] public static extern double CompareExchange(ref double location1, double value, double comparand); [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [System.Security.SecuritySafeCritical] public static extern Object CompareExchange(ref Object location1, Object value, Object comparand); [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [System.Security.SecuritySafeCritical] public static extern IntPtr CompareExchange(ref IntPtr location1, IntPtr value, IntPtr comparand); /***************************************************************** @@ -172,7 +158,6 @@ namespace System.Threading [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [System.Runtime.InteropServices.ComVisible(false)] - [System.Security.SecuritySafeCritical] public static T CompareExchange(ref T location1, T value, T comparand) where T : class { // _CompareExchange() passes back the value read from location1 via local named 'value' @@ -182,13 +167,11 @@ namespace System.Threading [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [System.Security.SecuritySafeCritical] private static extern void _CompareExchange(TypedReference location1, TypedReference value, Object comparand); // BCL-internal overload that returns success via a ref bool param, useful for reliable spin locks. [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [System.Security.SecuritySafeCritical] internal static extern int CompareExchange(ref int location1, int value, int comparand, ref bool succeeded); /****************************** diff --git a/src/mscorlib/src/System/Threading/LazyInitializer.cs b/src/mscorlib/src/System/Threading/LazyInitializer.cs index c8e74e3..238cc89 100644 --- a/src/mscorlib/src/System/Threading/LazyInitializer.cs +++ b/src/mscorlib/src/System/Threading/LazyInitializer.cs @@ -12,6 +12,7 @@ using System.Security.Permissions; +using System.Diagnostics; using System.Diagnostics.Contracts; namespace System.Threading { @@ -54,7 +55,6 @@ namespace System.Threading /// These routines avoid needing to allocate a dedicated, lazy-initialization instance, instead using /// references to ensure targets have been initialized as they are accessed. /// - [HostProtection(Synchronization = true, ExternalThreading = true)] public static class LazyInitializer { /// @@ -149,7 +149,7 @@ namespace System.Threading } Interlocked.CompareExchange(ref target, value, null); - Contract.Assert(target != null); + Debug.Assert(target != null); return target; } diff --git a/src/mscorlib/src/System/Threading/LockRecursionException.cs b/src/mscorlib/src/System/Threading/LockRecursionException.cs index c5e3146..ab95e70 100644 --- a/src/mscorlib/src/System/Threading/LockRecursionException.cs +++ b/src/mscorlib/src/System/Threading/LockRecursionException.cs @@ -20,9 +20,6 @@ namespace System.Threading [Serializable] [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] -#if !FEATURE_CORECLR - [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] -#endif public class LockRecursionException : System.Exception { public LockRecursionException() { } diff --git a/src/mscorlib/src/System/Threading/ManualResetEvent.cs b/src/mscorlib/src/System/Threading/ManualResetEvent.cs index 504cfb4..0004156 100644 --- a/src/mscorlib/src/System/Threading/ManualResetEvent.cs +++ b/src/mscorlib/src/System/Threading/ManualResetEvent.cs @@ -17,7 +17,6 @@ namespace System.Threading { using System.Security.Permissions; using System.Runtime.InteropServices; - [HostProtection(Synchronization=true, ExternalThreading=true)] [System.Runtime.InteropServices.ComVisible(true)] public sealed class ManualResetEvent : EventWaitHandle { diff --git a/src/mscorlib/src/System/Threading/ManualResetEventSlim.cs b/src/mscorlib/src/System/Threading/ManualResetEventSlim.cs index b6114ef..509af5b 100644 --- a/src/mscorlib/src/System/Threading/ManualResetEventSlim.cs +++ b/src/mscorlib/src/System/Threading/ManualResetEventSlim.cs @@ -13,10 +13,10 @@ // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- using System; -using System.Diagnostics; using System.Security.Permissions; using System.Threading; using System.Runtime.InteropServices; +using System.Diagnostics; using System.Diagnostics.Contracts; namespace System.Threading @@ -47,7 +47,6 @@ namespace System.Threading /// [ComVisible(false)] [DebuggerDisplay("Set = {IsSet}")] - [HostProtection(Synchronization = true, ExternalThreading = true)] public class ManualResetEventSlim : IDisposable { // These are the default spin counts we use on single-proc and MP machines. @@ -144,8 +143,8 @@ namespace System.Threading private set { - Contract.Assert(value >= 0, "SpinCount is a restricted-width integer. The value supplied is outside the legal range."); - Contract.Assert(value <= SpinCountState_MaxValue, "SpinCount is a restricted-width integer. The value supplied is outside the legal range."); + Debug.Assert(value >= 0, "SpinCount is a restricted-width integer. The value supplied is outside the legal range."); + Debug.Assert(value <= SpinCountState_MaxValue, "SpinCount is a restricted-width integer. The value supplied is outside the legal range."); // Don't worry about thread safety because it's set one time from the constructor m_combinedState = (m_combinedState & ~SpinCountState_BitMask) | (value << SpinCountState_ShiftCount); } @@ -164,7 +163,7 @@ namespace System.Threading set { //setting to <0 would indicate an internal flaw, hence Assert is appropriate. - Contract.Assert(value >= 0, "NumWaiters should never be less than zero. This indicates an internal error."); + Debug.Assert(value >= 0, "NumWaiters should never be less than zero. This indicates an internal error."); // it is possible for the max number of waiters to be exceeded via user-code, hence we use a real exception here. if (value >= NumWaitersState_MaxValue) @@ -218,13 +217,13 @@ namespace System.Threading { if (spinCount < 0) { - throw new ArgumentOutOfRangeException("spinCount"); + throw new ArgumentOutOfRangeException(nameof(spinCount)); } if (spinCount > SpinCountState_MaxValue) { throw new ArgumentOutOfRangeException( - "spinCount", + nameof(spinCount), String.Format(Environment.GetResourceString("ManualResetEventSlim_ctor_SpinCountOutOfRange"), SpinCountState_MaxValue)); } @@ -242,8 +241,8 @@ namespace System.Threading this.m_combinedState = initialState ? (1 << SignalledState_ShiftCount) : 0; //the spinCount argument has been validated by the ctors. //but we now sanity check our predefined constants. - Contract.Assert(DEFAULT_SPIN_SP >= 0, "Internal error - DEFAULT_SPIN_SP is outside the legal range."); - Contract.Assert(DEFAULT_SPIN_SP <= SpinCountState_MaxValue, "Internal error - DEFAULT_SPIN_SP is outside the legal range."); + Debug.Assert(DEFAULT_SPIN_SP >= 0, "Internal error - DEFAULT_SPIN_SP is outside the legal range."); + Debug.Assert(DEFAULT_SPIN_SP <= SpinCountState_MaxValue, "Internal error - DEFAULT_SPIN_SP is outside the legal range."); SpinCount = PlatformHelper.IsSingleProcessor ? DEFAULT_SPIN_SP : spinCount; @@ -295,7 +294,7 @@ namespace System.Threading bool currentIsSet = IsSet; if (currentIsSet != preInitializeIsSet) { - Contract.Assert(currentIsSet, + Debug.Assert(currentIsSet, "The only safe concurrent transition is from unset->set: detected set->unset."); // We saw it as unsignaled, but it has since become set. @@ -337,7 +336,7 @@ namespace System.Threading // If there are waiting threads, we need to pulse them. if (Waiters > 0) { - Contract.Assert(m_lock != null); //if waiters>0, then m_lock has already been created. + Debug.Assert(m_lock != null); //if waiters>0, then m_lock has already been created. lock (m_lock) { @@ -464,7 +463,7 @@ namespace System.Threading long totalMilliseconds = (long)timeout.TotalMilliseconds; if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue) { - throw new ArgumentOutOfRangeException("timeout"); + throw new ArgumentOutOfRangeException(nameof(timeout)); } return Wait((int)totalMilliseconds, new CancellationToken()); @@ -495,7 +494,7 @@ namespace System.Threading long totalMilliseconds = (long)timeout.TotalMilliseconds; if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue) { - throw new ArgumentOutOfRangeException("timeout"); + throw new ArgumentOutOfRangeException(nameof(timeout)); } return Wait((int)totalMilliseconds, cancellationToken); @@ -544,7 +543,7 @@ namespace System.Threading if (millisecondsTimeout < -1) { - throw new ArgumentOutOfRangeException("millisecondsTimeout"); + throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout)); } if (!IsSet) @@ -738,8 +737,8 @@ namespace System.Threading private static void CancellationTokenCallback(object obj) { ManualResetEventSlim mre = obj as ManualResetEventSlim; - Contract.Assert(mre != null, "Expected a ManualResetEventSlim"); - Contract.Assert(mre.m_lock != null); //the lock should have been created before this callback is registered for use. + Debug.Assert(mre != null, "Expected a ManualResetEventSlim"); + Debug.Assert(mre.m_lock != null); //the lock should have been created before this callback is registered for use. lock (mre.m_lock) { Monitor.PulseAll(mre.m_lock); // awaken all waiters @@ -759,7 +758,7 @@ namespace System.Threading { SpinWait sw = new SpinWait(); - Contract.Assert((newBits | updateBitsMask) == updateBitsMask, "newBits do not fall within the updateBitsMask."); + Debug.Assert((newBits | updateBitsMask) == updateBitsMask, "newBits do not fall within the updateBitsMask."); do { diff --git a/src/mscorlib/src/System/Threading/Monitor.cs b/src/mscorlib/src/System/Threading/Monitor.cs index 415948b..94dec13 100644 --- a/src/mscorlib/src/System/Threading/Monitor.cs +++ b/src/mscorlib/src/System/Threading/Monitor.cs @@ -24,9 +24,9 @@ namespace System.Threading { using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; - [HostProtection(Synchronization=true, ExternalThreading=true)] [System.Runtime.InteropServices.ComVisible(true)] public static class Monitor { @@ -38,7 +38,6 @@ namespace System.Threading { ** ** Exceptions: ArgumentNullException if object is null. =========================================================================*/ - [System.Security.SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern void Enter(Object obj); @@ -54,7 +53,7 @@ namespace System.Threading { ThrowLockTakenException(); ReliableEnter(obj, ref lockTaken); - Contract.Assert(lockTaken); + Debug.Assert(lockTaken); } private static void ThrowLockTakenException() @@ -62,7 +61,6 @@ namespace System.Threading { throw new ArgumentException(Environment.GetResourceString("Argument_MustBeFalse"), "lockTaken"); } - [System.Security.SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void ReliableEnter(Object obj, ref bool lockTaken); @@ -77,7 +75,6 @@ namespace System.Threading { ** SynchronizationLockException if the current thread does not ** own the lock. =========================================================================*/ - [System.Security.SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static extern void Exit(Object obj); @@ -127,7 +124,7 @@ namespace System.Threading { { long tm = (long)timeout.TotalMilliseconds; if (tm < -1 || tm > (long)Int32.MaxValue) - throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(timeout), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); return (int)tm; } @@ -154,20 +151,17 @@ namespace System.Threading { ReliableEnterTimeout(obj, MillisecondsTimeoutFromTimeSpan(timeout), ref lockTaken); } - [System.Security.SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void ReliableEnterTimeout(Object obj, int timeout, ref bool lockTaken); - [System.Security.SecuritySafeCritical] public static bool IsEntered(object obj) { if (obj == null) - throw new ArgumentNullException("obj"); + throw new ArgumentNullException(nameof(obj)); return IsEnteredNative(obj); } - [System.Security.SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool IsEnteredNative(Object obj); @@ -182,15 +176,13 @@ namespace System.Threading { ** ** Exceptions: ArgumentNullException if object is null. ========================================================================*/ - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool ObjWait(bool exitContext, int millisecondsTimeout, Object obj); - [System.Security.SecuritySafeCritical] // auto-generated public static bool Wait(Object obj, int millisecondsTimeout, bool exitContext) { if (obj == null) - throw (new ArgumentNullException("obj")); + throw (new ArgumentNullException(nameof(obj))); return ObjWait(exitContext, millisecondsTimeout, obj); } @@ -219,16 +211,14 @@ namespace System.Threading { * Exceptions: SynchronizationLockException if this method is not called inside * a synchronized block of code. ========================================================================*/ - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void ObjPulse(Object obj); - [System.Security.SecuritySafeCritical] // auto-generated public static void Pulse(Object obj) { if (obj == null) { - throw new ArgumentNullException("obj"); + throw new ArgumentNullException(nameof(obj)); } Contract.EndContractBlock(); @@ -237,16 +227,14 @@ namespace System.Threading { /*======================================================================== ** Sends a notification to all waiting objects. ========================================================================*/ - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void ObjPulseAll(Object obj); - [System.Security.SecuritySafeCritical] // auto-generated public static void PulseAll(Object obj) { if (obj == null) { - throw new ArgumentNullException("obj"); + throw new ArgumentNullException(nameof(obj)); } Contract.EndContractBlock(); diff --git a/src/mscorlib/src/System/Threading/Mutex.cs b/src/mscorlib/src/System/Threading/Mutex.cs index 2e9b681..506abb7 100644 --- a/src/mscorlib/src/System/Threading/Mutex.cs +++ b/src/mscorlib/src/System/Threading/Mutex.cs @@ -24,31 +24,24 @@ namespace System.Threading using System.Runtime.ConstrainedExecution; using System.Runtime.Versioning; using System.Security; + using System.Diagnostics; using System.Diagnostics.Contracts; - -#if FEATURE_MACL - using System.Security.AccessControl; -#endif - [HostProtection(Synchronization=true, ExternalThreading=true)] [ComVisible(true)] public sealed class Mutex : WaitHandle { static bool dummyBool; -#if !FEATURE_MACL - public class MutexSecurity { + public class MutexSecurity + { } -#endif - [System.Security.SecurityCritical] // auto-generated_required [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public Mutex(bool initiallyOwned, String name, out bool createdNew) : this(initiallyOwned, name, out createdNew, (MutexSecurity)null) { } - [System.Security.SecurityCritical] // auto-generated_required [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public unsafe Mutex(bool initiallyOwned, String name, out bool createdNew, MutexSecurity mutexSecurity) { @@ -60,29 +53,15 @@ namespace System.Threading #if !PLATFORM_UNIX if (name != null && System.IO.Path.MaxPath < name.Length) { - throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), nameof(name)); } #endif Contract.EndContractBlock(); Win32Native.SECURITY_ATTRIBUTES secAttrs = null; -#if FEATURE_MACL - // For ACL's, get the security descriptor from the MutexSecurity. - if (mutexSecurity != null) { - - secAttrs = new Win32Native.SECURITY_ATTRIBUTES(); - secAttrs.nLength = (int)Marshal.SizeOf(secAttrs); - - byte[] sd = mutexSecurity.GetSecurityDescriptorBinaryForm(); - byte* pSecDescriptor = stackalloc byte[sd.Length]; - Buffer.Memcpy(pSecDescriptor, 0, sd, 0, sd.Length); - secAttrs.pSecurityDescriptor = pSecDescriptor; - } -#endif CreateMutexWithGuaranteedCleanup(initiallyOwned, name, out createdNew, secAttrs); } - [System.Security.SecurityCritical] // auto-generated_required [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal Mutex(bool initiallyOwned, String name, out bool createdNew, Win32Native.SECURITY_ATTRIBUTES secAttrs) { @@ -94,7 +73,7 @@ namespace System.Threading #if !PLATFORM_UNIX if (name != null && System.IO.Path.MaxPath < name.Length) { - throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), nameof(name)); } #endif Contract.EndContractBlock(); @@ -102,7 +81,6 @@ namespace System.Threading CreateMutexWithGuaranteedCleanup(initiallyOwned, name, out createdNew, secAttrs); } - [System.Security.SecurityCritical] // auto-generated_required [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal void CreateMutexWithGuaranteedCleanup(bool initiallyOwned, String name, out bool createdNew, Win32Native.SECURITY_ATTRIBUTES secAttrs) { @@ -123,15 +101,13 @@ namespace System.Threading MutexCleanupInfo m_cleanupInfo; internal bool m_newMutex; String m_name; - [System.Security.SecurityCritical] // auto-generated Win32Native.SECURITY_ATTRIBUTES m_secAttrs; Mutex m_mutex; - [System.Security.SecurityCritical] // auto-generated [PrePrepareMethod] internal MutexTryCodeHelper(bool initiallyOwned,MutexCleanupInfo cleanupInfo, String name, Win32Native.SECURITY_ATTRIBUTES secAttrs, Mutex mutex) { - Contract.Assert(name == null || name.Length != 0); + Debug.Assert(name == null || name.Length != 0); m_initiallyOwned = initiallyOwned; m_cleanupInfo = cleanupInfo; @@ -140,7 +116,6 @@ namespace System.Threading m_mutex = mutex; } - [System.Security.SecurityCritical] // auto-generated [PrePrepareMethod] internal void MutexTryCode(object userData) { @@ -155,14 +130,10 @@ namespace System.Threading if (m_initiallyOwned) { m_cleanupInfo.inCriticalRegion = true; -#if !FEATURE_CORECLR - Thread.BeginThreadAffinity(); - Thread.BeginCriticalRegion(); -#endif //!FEATURE_CORECLR } } - int errorCode = 0; + int errorCode = 0; RuntimeHelpers.PrepareConstrainedRegions(); try { @@ -182,7 +153,7 @@ namespace System.Threading #if PLATFORM_UNIX case Win32Native.ERROR_FILENAME_EXCED_RANGE: // On Unix, length validation is done by CoreCLR's PAL after converting to utf-8 - throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPathComponentLength), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", PathInternal.MaxComponentLength), "name"); #endif case Win32Native.ERROR_INVALID_HANDLE: @@ -199,38 +170,27 @@ namespace System.Threading } } - [System.Security.SecurityCritical] // auto-generated [PrePrepareMethod] private void MutexCleanupCode(Object userData, bool exceptionThrown) { MutexCleanupInfo cleanupInfo = (MutexCleanupInfo) userData; // If hasThreadAffinity isn't true, we've thrown an exception in the above try, and we must free the mutex - // on this OS thread before ending our thread affninity. + // on this OS thread before ending our thread affninity. if(!hasThreadAffinity) { if (cleanupInfo.mutexHandle != null && !cleanupInfo.mutexHandle.IsInvalid) { if( cleanupInfo.inCriticalRegion) { - Win32Native.ReleaseMutex(cleanupInfo.mutexHandle); + Win32Native.ReleaseMutex(cleanupInfo.mutexHandle); } - cleanupInfo.mutexHandle.Dispose(); - + cleanupInfo.mutexHandle.Dispose(); } - - if( cleanupInfo.inCriticalRegion) { -#if !FEATURE_CORECLR - Thread.EndCriticalRegion(); - Thread.EndThreadAffinity(); -#endif - } } } internal class MutexCleanupInfo { - [System.Security.SecurityCritical] // auto-generated internal SafeWaitHandle mutexHandle; internal bool inCriticalRegion; - [System.Security.SecurityCritical] // auto-generated internal MutexCleanupInfo(SafeWaitHandle mutexHandle, bool inCriticalRegion) { this.mutexHandle = mutexHandle; @@ -238,24 +198,20 @@ namespace System.Threading } } - [System.Security.SecurityCritical] // auto-generated_required [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public Mutex(bool initiallyOwned, String name) : this(initiallyOwned, name, out dummyBool) { } - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public Mutex(bool initiallyOwned) : this(initiallyOwned, null, out dummyBool) { } - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public Mutex() : this(false, null, out dummyBool) { } - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] private Mutex(SafeWaitHandle handle) { @@ -263,23 +219,15 @@ namespace System.Threading hasThreadAffinity = true; } - [System.Security.SecurityCritical] // auto-generated_required public static Mutex OpenExisting(string name) { -#if !FEATURE_MACL return OpenExisting(name, (MutexRights) 0); -#else // FEATURE_MACL - return OpenExisting(name, MutexRights.Modify | MutexRights.Synchronize); -#endif // FEATURE_MACL } -#if !FEATURE_MACL public enum MutexRights { } -#endif - [System.Security.SecurityCritical] // auto-generated_required public static Mutex OpenExisting(string name, MutexRights rights) { Mutex result; @@ -300,38 +248,31 @@ namespace System.Threading } } - [System.Security.SecurityCritical] // auto-generated_required public static bool TryOpenExisting(string name, out Mutex result) { -#if !FEATURE_MACL return OpenExistingWorker(name, (MutexRights)0, out result) == OpenExistingResult.Success; -#else // FEATURE_MACL - return OpenExistingWorker(name, MutexRights.Modify | MutexRights.Synchronize, out result) == OpenExistingResult.Success; -#endif // FEATURE_MACL } - [System.Security.SecurityCritical] // auto-generated_required public static bool TryOpenExisting(string name, MutexRights rights, out Mutex result) { return OpenExistingWorker(name, rights, out result) == OpenExistingResult.Success; } - [System.Security.SecurityCritical] private static OpenExistingResult OpenExistingWorker(string name, MutexRights rights, out Mutex result) { if (name == null) { - throw new ArgumentNullException("name", Environment.GetResourceString("ArgumentNull_WithParamName")); + throw new ArgumentNullException(nameof(name), Environment.GetResourceString("ArgumentNull_WithParamName")); } if(name.Length == 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(name)); } #if !PLATFORM_UNIX if(System.IO.Path.MaxPath < name.Length) { - throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), nameof(name)); } #endif Contract.EndContractBlock(); @@ -342,11 +283,7 @@ namespace System.Threading // with parameters to allow us to view & edit the ACL. This will // fail if we don't have permission to view or edit the ACL's. // If that happens, ask for less permissions. -#if FEATURE_MACL - SafeWaitHandle myHandle = Win32Native.OpenMutex((int) rights, false, name); -#else SafeWaitHandle myHandle = Win32Native.OpenMutex(Win32Native.MUTEX_MODIFY_STATE | Win32Native.SYNCHRONIZE, false, name); -#endif int errorCode = 0; if (myHandle.IsInvalid) @@ -357,7 +294,7 @@ namespace System.Threading if (name != null && errorCode == Win32Native.ERROR_FILENAME_EXCED_RANGE) { // On Unix, length validation is done by CoreCLR's PAL after converting to utf-8 - throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPathComponentLength), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", PathInternal.MaxComponentLength), nameof(name)); } #endif @@ -379,110 +316,51 @@ namespace System.Threading // Note: To call ReleaseMutex, you must have an ACL granting you // MUTEX_MODIFY_STATE rights (0x0001). The other interesting value // in a Mutex's ACL is MUTEX_ALL_ACCESS (0x1F0001). - [System.Security.SecuritySafeCritical] // auto-generated - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public void ReleaseMutex() { if (Win32Native.ReleaseMutex(safeWaitHandle)) { -#if !FEATURE_CORECLR - Thread.EndCriticalRegion(); - Thread.EndThreadAffinity(); -#endif } else { -#if FEATURE_CORECLR throw new Exception(Environment.GetResourceString("Arg_SynchronizationLockException")); -#else - throw new ApplicationException(Environment.GetResourceString("Arg_SynchronizationLockException")); -#endif // FEATURE_CORECLR - } + } } - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - static int CreateMutexHandle(bool initiallyOwned, String name, Win32Native.SECURITY_ATTRIBUTES securityAttribute, out SafeWaitHandle mutexHandle) { - int errorCode; - bool fAffinity = false; - - while(true) { + static int CreateMutexHandle(bool initiallyOwned, String name, Win32Native.SECURITY_ATTRIBUTES securityAttribute, out SafeWaitHandle mutexHandle) + { + int errorCode; + + while (true) + { mutexHandle = Win32Native.CreateMutex(securityAttribute, initiallyOwned, name); - errorCode = Marshal.GetLastWin32Error(); - if( !mutexHandle.IsInvalid) { - break; - } + errorCode = Marshal.GetLastWin32Error(); + if (!mutexHandle.IsInvalid) break; - if( errorCode == Win32Native.ERROR_ACCESS_DENIED) { - // If a mutex with the name already exists, OS will try to open it with FullAccess. - // It might fail if we don't have enough access. In that case, we try to open the mutex will modify and synchronize access. - // - - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - try - { - } - finally - { -#if !FEATURE_CORECLR - Thread.BeginThreadAffinity(); -#endif - fAffinity = true; - } - mutexHandle = Win32Native.OpenMutex(Win32Native.MUTEX_MODIFY_STATE | Win32Native.SYNCHRONIZE, false, name); - if(!mutexHandle.IsInvalid) - { - errorCode = Win32Native.ERROR_ALREADY_EXISTS; - } - else - { - errorCode = Marshal.GetLastWin32Error(); - } - } - finally - { - if (fAffinity) { -#if !FEATURE_CORECLR - Thread.EndThreadAffinity(); -#endif - } - } + if (errorCode != Win32Native.ERROR_ACCESS_DENIED) break; - // There could be a race condition here, the other owner of the mutex can free the mutex, - // We need to retry creation in that case. - if( errorCode != Win32Native.ERROR_FILE_NOT_FOUND) { - if( errorCode == Win32Native.ERROR_SUCCESS) { - errorCode = Win32Native.ERROR_ALREADY_EXISTS; - } - break; - } - } - else { + // If a mutex with the name already exists, OS will try to open it with FullAccess. + // It might fail if we don't have enough access. In that case, we try to open the mutex will modify and synchronize access. + RuntimeHelpers.PrepareConstrainedRegions(); + + mutexHandle = Win32Native.OpenMutex( + Win32Native.MUTEX_MODIFY_STATE | Win32Native.SYNCHRONIZE, + false, + name); + + errorCode = !mutexHandle.IsInvalid ? Win32Native.ERROR_ALREADY_EXISTS : Marshal.GetLastWin32Error(); + + // There could be a race condition here, the other owner of the mutex can free the mutex, + // We need to retry creation in that case. + if (errorCode != Win32Native.ERROR_FILE_NOT_FOUND) + { + if (errorCode == Win32Native.ERROR_SUCCESS) errorCode = Win32Native.ERROR_ALREADY_EXISTS; break; } - } + } return errorCode; } - -#if FEATURE_MACL - [System.Security.SecuritySafeCritical] // auto-generated - public MutexSecurity GetAccessControl() - { - return new MutexSecurity(safeWaitHandle, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group); - } - - [System.Security.SecuritySafeCritical] // auto-generated - public void SetAccessControl(MutexSecurity mutexSecurity) - { - if (mutexSecurity == null) - throw new ArgumentNullException("mutexSecurity"); - Contract.EndContractBlock(); - - mutexSecurity.Persist(safeWaitHandle); - } -#endif - } } diff --git a/src/mscorlib/src/System/Threading/Overlapped.cs b/src/mscorlib/src/System/Threading/Overlapped.cs index 3f9fbc4..2b192c7 100644 --- a/src/mscorlib/src/System/Threading/Overlapped.cs +++ b/src/mscorlib/src/System/Threading/Overlapped.cs @@ -33,6 +33,7 @@ namespace System.Threading using System.Security; using System.Security.Permissions; using System.Runtime.ConstrainedExecution; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Collections.Concurrent; @@ -60,20 +61,16 @@ namespace System.Threading unsafe internal class _IOCompletionCallback { - [System.Security.SecurityCritical] // auto-generated IOCompletionCallback _ioCompletionCallback; ExecutionContext _executionContext; uint _errorCode; // Error code uint _numBytes; // No. of bytes transferred - [SecurityCritical] NativeOverlapped* _pOVERLAP; - [System.Security.SecuritySafeCritical] // auto-generated static _IOCompletionCallback() { } - [System.Security.SecurityCritical] // auto-generated internal _IOCompletionCallback(IOCompletionCallback ioCompletionCallback, ref StackCrawlMark stackMark) { _ioCompletionCallback = ioCompletionCallback; @@ -83,21 +80,16 @@ namespace System.Threading ExecutionContext.CaptureOptions.IgnoreSyncCtx | ExecutionContext.CaptureOptions.OptimizeDefaultCase); } // Context callback: same sig for SendOrPostCallback and ContextCallback - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #endif static internal ContextCallback _ccb = new ContextCallback(IOCompletionCallback_Context); - [System.Security.SecurityCritical] static internal void IOCompletionCallback_Context(Object state) { _IOCompletionCallback helper = (_IOCompletionCallback)state; - Contract.Assert(helper != null,"_IOCompletionCallback cannot be null"); + Debug.Assert(helper != null,"_IOCompletionCallback cannot be null"); helper._ioCompletionCallback(helper._errorCode, helper._numBytes, helper._pOVERLAP); } // call back helper - [System.Security.SecurityCritical] // auto-generated static unsafe internal void PerformIOCompletionCallback(uint errorCode, // Error code uint numBytes, // No. of bytes transferred NativeOverlapped* pOVERLAP // ptr to OVERLAP structure @@ -146,7 +138,6 @@ namespace System.Threading // ! If you make any change to the layout here, you need to make matching change // ! to OverlappedObject in vm\nativeoverlapped.h internal IAsyncResult m_asyncResult; - [System.Security.SecurityCritical] // auto-generated internal IOCompletionCallback m_iocb; internal _IOCompletionCallback m_iocbHelper; internal Overlapped m_overlapped; @@ -162,14 +153,9 @@ namespace System.Threading #pragma warning restore 169 internal NativeOverlapped m_nativeOverlapped; -#if FEATURE_CORECLR // Adding an empty default ctor for annotation purposes - [System.Security.SecuritySafeCritical] // auto-generated internal OverlappedData(){} -#endif // FEATURE_CORECLR - - [System.Security.SecurityCritical] internal void ReInitialize() { m_asyncResult = null; @@ -177,10 +163,10 @@ namespace System.Threading m_iocbHelper = null; m_overlapped = null; m_userObject = null; - Contract.Assert(m_pinSelf.IsNull(), "OverlappedData has not been freed: m_pinSelf"); + Debug.Assert(m_pinSelf.IsNull(), "OverlappedData has not been freed: m_pinSelf"); m_pinSelf = (IntPtr)0; m_userObjectInternal = (IntPtr)0; - Contract.Assert(m_AppDomainId == 0 || m_AppDomainId == AppDomain.CurrentDomain.Id, "OverlappedData is not in the current domain"); + Debug.Assert(m_AppDomainId == 0 || m_AppDomainId == AppDomain.CurrentDomain.Id, "OverlappedData is not in the current domain"); m_AppDomainId = 0; m_nativeOverlapped.EventHandle = (IntPtr)0; m_isArray = 0; @@ -188,7 +174,6 @@ namespace System.Threading m_nativeOverlapped.InternalHigh = (IntPtr)0; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable unsafe internal NativeOverlapped* Pack(IOCompletionCallback iocb, Object userData) { @@ -222,7 +207,6 @@ namespace System.Threading return AllocateNativeOverlapped(); } - [System.Security.SecurityCritical] // auto-generated_required unsafe internal NativeOverlapped* UnsafePack(IOCompletionCallback iocb, Object userData) { if (!m_pinSelf.IsNull()) { @@ -252,19 +236,15 @@ namespace System.Threading set { m_nativeOverlapped.EventHandle = value; } } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] unsafe private extern NativeOverlapped* AllocateNativeOverlapped(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] unsafe internal static extern void FreeNativeOverlapped(NativeOverlapped* nativeOverlappedPtr); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] unsafe internal static extern OverlappedData GetOverlappedFromNative(NativeOverlapped* nativeOverlappedPtr); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] unsafe internal static extern void CheckVMForIOPacket(out NativeOverlapped* pOVERLAP, out uint errorCode, out uint numBytes); } @@ -281,9 +261,6 @@ namespace System.Threading private OverlappedData m_overlappedData; private static PinnableBufferCache s_overlappedDataCache = new PinnableBufferCache("System.Threading.OverlappedData", ()=> new OverlappedData()); -#if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // auto-generated -#endif public Overlapped() { m_overlappedData = (OverlappedData) s_overlappedDataCache.Allocate(); @@ -344,7 +321,6 @@ namespace System.Threading internal IOCompletionCallback UserCallback { - [System.Security.SecurityCritical] get { return m_overlappedData.m_iocb; } } @@ -353,7 +329,6 @@ namespace System.Threading * Roots the iocb and stores it in the ReservedCOR field of native Overlapped * Pins the native Overlapped struct and returns the pinned index. ====================================================================*/ - [System.Security.SecurityCritical] // auto-generated [Obsolete("This method is not safe. Use Pack (iocb, userData) instead. http://go.microsoft.com/fwlink/?linkid=14202")] [CLSCompliant(false)] unsafe public NativeOverlapped* Pack(IOCompletionCallback iocb) @@ -361,14 +336,12 @@ namespace System.Threading return Pack (iocb, null); } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false),ComVisible(false)] unsafe public NativeOverlapped* Pack(IOCompletionCallback iocb, Object userData) { return m_overlappedData.Pack(iocb, userData); } - [System.Security.SecurityCritical] // auto-generated_required [Obsolete("This method is not safe. Use UnsafePack (iocb, userData) instead. http://go.microsoft.com/fwlink/?linkid=14202")] [CLSCompliant(false)] unsafe public NativeOverlapped* UnsafePack(IOCompletionCallback iocb) @@ -376,7 +349,6 @@ namespace System.Threading return UnsafePack (iocb, null); } - [System.Security.SecurityCritical] // auto-generated_required [CLSCompliant(false), ComVisible(false)] unsafe public NativeOverlapped* UnsafePack(IOCompletionCallback iocb, Object userData) { @@ -387,12 +359,11 @@ namespace System.Threading * Unpacks an unmanaged native Overlapped struct. * Unpins the native Overlapped struct ====================================================================*/ - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] unsafe public static Overlapped Unpack(NativeOverlapped* nativeOverlappedPtr) { if (nativeOverlappedPtr == null) - throw new ArgumentNullException("nativeOverlappedPtr"); + throw new ArgumentNullException(nameof(nativeOverlappedPtr)); Contract.EndContractBlock(); Overlapped overlapped = OverlappedData.GetOverlappedFromNative(nativeOverlappedPtr).m_overlapped; @@ -400,12 +371,11 @@ namespace System.Threading return overlapped; } - [System.Security.SecurityCritical] // auto-generated [CLSCompliant(false)] unsafe public static void Free(NativeOverlapped* nativeOverlappedPtr) { if (nativeOverlappedPtr == null) - throw new ArgumentNullException("nativeOverlappedPtr"); + throw new ArgumentNullException(nameof(nativeOverlappedPtr)); Contract.EndContractBlock(); Overlapped overlapped = OverlappedData.GetOverlappedFromNative(nativeOverlappedPtr).m_overlapped; diff --git a/src/mscorlib/src/System/Threading/ReaderWriterLock.cs b/src/mscorlib/src/System/Threading/ReaderWriterLock.cs index 8cead1a..e35ac76 100644 --- a/src/mscorlib/src/System/Threading/ReaderWriterLock.cs +++ b/src/mscorlib/src/System/Threading/ReaderWriterLock.cs @@ -25,14 +25,12 @@ namespace System.Threading { using System.Runtime.Versioning; using System.Diagnostics.Contracts; - [HostProtection(Synchronization=true, ExternalThreading=true)] [ComVisible(true)] public sealed class ReaderWriterLock: CriticalFinalizerObject { /* * Constructor */ - [System.Security.SecuritySafeCritical] // auto-generated public ReaderWriterLock() { PrivateInitialize(); @@ -41,7 +39,6 @@ namespace System.Threading { /* * Destructor */ - [System.Security.SecuritySafeCritical] // auto-generated ~ReaderWriterLock() { PrivateDestruct(); @@ -52,7 +49,6 @@ namespace System.Threading { * by the current thread */ public bool IsReaderLockHeld { - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] get { return(PrivateGetIsReaderLockHeld()); @@ -64,7 +60,6 @@ namespace System.Threading { * by the current thread */ public bool IsWriterLockHeld { - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] get { return(PrivateGetIsWriterLockHeld()); @@ -77,7 +72,6 @@ namespace System.Threading { * meaningful results */ public int WriterSeqNum { - [System.Security.SecuritySafeCritical] // auto-generated get { return(PrivateGetWriterSeqNum()); } @@ -87,23 +81,20 @@ namespace System.Threading { * Acquires reader lock. The thread will block if a different * thread has writer lock. */ - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern void AcquireReaderLockInternal(int millisecondsTimeout); - [System.Security.SecuritySafeCritical] // auto-generated public void AcquireReaderLock(int millisecondsTimeout) { AcquireReaderLockInternal(millisecondsTimeout); } - [System.Security.SecuritySafeCritical] // auto-generated public void AcquireReaderLock(TimeSpan timeout) { long tm = (long)timeout.TotalMilliseconds; if (tm < -1 || tm > (long) Int32.MaxValue) - throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(timeout), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); AcquireReaderLockInternal((int)tm); } @@ -113,22 +104,19 @@ namespace System.Threading { * has reader lock. Use UpgardeToWriterLock when you are not * sure if the thread has reader lock */ - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern void AcquireWriterLockInternal(int millisecondsTimeout); - [System.Security.SecuritySafeCritical] // auto-generated public void AcquireWriterLock(int millisecondsTimeout) { AcquireWriterLockInternal(millisecondsTimeout); } - [System.Security.SecuritySafeCritical] // auto-generated public void AcquireWriterLock(TimeSpan timeout) { long tm = (long)timeout.TotalMilliseconds; if (tm < -1 || tm > (long) Int32.MaxValue) - throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(timeout), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); AcquireWriterLockInternal((int)tm); } @@ -136,12 +124,10 @@ namespace System.Threading { /* * Releases reader lock. */ - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] private extern void ReleaseReaderLockInternal(); - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public void ReleaseReaderLock() { @@ -151,12 +137,10 @@ namespace System.Threading { /* * Releases writer lock. */ - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] private extern void ReleaseWriterLockInternal(); - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public void ReleaseWriterLock() { @@ -168,7 +152,6 @@ namespace System.Threading { * reader, it is possible that the reader lock was * released before writer lock was acquired. */ - [System.Security.SecuritySafeCritical] // auto-generated public LockCookie UpgradeToWriterLock(int millisecondsTimeout) { LockCookie result = new LockCookie (); @@ -176,7 +159,6 @@ namespace System.Threading { return result; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern void FCallUpgradeToWriterLock(ref LockCookie result, int millisecondsTimeout); @@ -184,7 +166,7 @@ namespace System.Threading { { long tm = (long)timeout.TotalMilliseconds; if (tm < -1 || tm > (long) Int32.MaxValue) - throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(timeout), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); return UpgradeToWriterLock((int)tm); } @@ -192,11 +174,9 @@ namespace System.Threading { * Restores the lock status of the thread to the one it was * in when it called UpgradeToWriterLock. */ - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern void DowngradeFromWriterLockInternal(ref LockCookie lockCookie); - [System.Security.SecuritySafeCritical] // auto-generated public void DowngradeFromWriterLock(ref LockCookie lockCookie) { DowngradeFromWriterLockInternal(ref lockCookie); @@ -206,7 +186,6 @@ namespace System.Threading { * Releases the lock irrespective of the number of times the thread * acquired the lock */ - [System.Security.SecuritySafeCritical] // auto-generated public LockCookie ReleaseLock() { LockCookie result = new LockCookie (); @@ -214,7 +193,6 @@ namespace System.Threading { return result; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern void FCallReleaseLock(ref LockCookie result); @@ -222,11 +200,9 @@ namespace System.Threading { * Restores the lock status of the thread to the one it was * in when it called ReleaseLock. */ - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern void RestoreLockInternal(ref LockCookie lockCookie); - [System.Security.SecuritySafeCritical] // auto-generated public void RestoreLock(ref LockCookie lockCookie) { RestoreLockInternal(ref lockCookie); @@ -236,7 +212,6 @@ namespace System.Threading { * Internal helper that returns TRUE if the reader lock is held * by the current thread */ - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] private extern bool PrivateGetIsReaderLockHeld(); @@ -245,7 +220,6 @@ namespace System.Threading { * Internal helper that returns TRUE if the writer lock is held * by the current thread */ - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] private extern bool PrivateGetIsWriterLockHeld(); @@ -255,7 +229,6 @@ namespace System.Threading { * number. The caller should be a reader or writer for getting * meaningful results */ - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern int PrivateGetWriterSeqNum(); @@ -264,17 +237,14 @@ namespace System.Threading { * sequence number was obtained. The caller should be * a reader or writer for getting meaningful results */ - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern bool AnyWritersSince(int seqNum); // Initialize state kept inside the lock - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern void PrivateInitialize(); // Destruct resource associated with the lock - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern void PrivateDestruct(); diff --git a/src/mscorlib/src/System/Threading/Semaphore.cs b/src/mscorlib/src/System/Threading/Semaphore.cs index 303593b..1eac4aa 100644 --- a/src/mscorlib/src/System/Threading/Semaphore.cs +++ b/src/mscorlib/src/System/Threading/Semaphore.cs @@ -4,6 +4,7 @@ using Microsoft.Win32; using Microsoft.Win32.SafeHandles; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.IO; using System.Runtime.InteropServices; @@ -13,20 +14,18 @@ namespace System.Threading { public sealed partial class Semaphore : WaitHandle { - [SecuritySafeCritical] public Semaphore(int initialCount, int maximumCount) : this(initialCount, maximumCount, null) { } - [SecurityCritical] public Semaphore(int initialCount, int maximumCount, string name) { if (initialCount < 0) { - throw new ArgumentOutOfRangeException("initialCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(initialCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (maximumCount < 1) { - throw new ArgumentOutOfRangeException("maximumCount", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); + throw new ArgumentOutOfRangeException(nameof(maximumCount), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); } if (initialCount > maximumCount) @@ -49,17 +48,16 @@ namespace System.Threading this.SafeWaitHandle = myHandle; } - [SecurityCritical] public Semaphore(int initialCount, int maximumCount, string name, out bool createdNew) { if (initialCount < 0) { - throw new ArgumentOutOfRangeException("initialCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(initialCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (maximumCount < 1) { - throw new ArgumentOutOfRangeException("maximumCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(maximumCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } if (initialCount > maximumCount) @@ -81,13 +79,11 @@ namespace System.Threading this.SafeWaitHandle = myHandle; } - [SecurityCritical] private Semaphore(SafeWaitHandle handle) { this.SafeWaitHandle = handle; } - [SecurityCritical] private static SafeWaitHandle CreateSemaphone(int initialCount, int maximumCount, string name) { if (name != null) @@ -96,19 +92,17 @@ namespace System.Threading throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_NamedSynchronizationPrimitives")); #else if (name.Length > Path.MaxPath) - throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), nameof(name)); #endif } - Contract.Assert(initialCount >= 0); - Contract.Assert(maximumCount >= 1); - Contract.Assert(initialCount <= maximumCount); + Debug.Assert(initialCount >= 0); + Debug.Assert(maximumCount >= 1); + Debug.Assert(initialCount <= maximumCount); return Win32Native.CreateSemaphore(null, initialCount, maximumCount, name); } - [SecurityCritical] - public static Semaphore OpenExisting(string name) { Semaphore result; @@ -125,24 +119,22 @@ namespace System.Threading } } - [SecurityCritical] public static bool TryOpenExisting(string name, out Semaphore result) { return OpenExistingWorker(name, out result) == OpenExistingResult.Success; } - [SecurityCritical] private static OpenExistingResult OpenExistingWorker(string name, out Semaphore result) { #if PLATFORM_UNIX throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_NamedSynchronizationPrimitives")); #else if (name == null) - throw new ArgumentNullException("name", Environment.GetResourceString("ArgumentNull_WithParamName")); + throw new ArgumentNullException(nameof(name), Environment.GetResourceString("ArgumentNull_WithParamName")); if (name.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), nameof(name)); if (name.Length > Path.MaxPath) - throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), "name"); + throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), nameof(name)); const int SYNCHRONIZE = 0x00100000; const int SEMAPHORE_MODIFY_STATE = 0x00000002; @@ -177,12 +169,11 @@ namespace System.Threading } // increase the count on a semaphore, returns previous count - [SecuritySafeCritical] public int Release(int releaseCount) { if (releaseCount < 1) { - throw new ArgumentOutOfRangeException("releaseCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(releaseCount), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); } //If ReleaseSempahore returns false when the specified value would cause diff --git a/src/mscorlib/src/System/Threading/SemaphoreFullException.cs b/src/mscorlib/src/System/Threading/SemaphoreFullException.cs index e1928e0..01c5040 100644 --- a/src/mscorlib/src/System/Threading/SemaphoreFullException.cs +++ b/src/mscorlib/src/System/Threading/SemaphoreFullException.cs @@ -9,9 +9,6 @@ namespace System.Threading { [Serializable] [ComVisibleAttribute(false)] -#if !FEATURE_CORECLR - [System.Runtime.CompilerServices.TypeForwardedFrom("System, Version=2.0.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] -#endif public class SemaphoreFullException : SystemException { public SemaphoreFullException() : base(Environment.GetResourceString("Threading_SemaphoreFullException")){ diff --git a/src/mscorlib/src/System/Threading/SemaphoreSlim.cs b/src/mscorlib/src/System/Threading/SemaphoreSlim.cs index c2dcbb3..92d760d 100644 --- a/src/mscorlib/src/System/Threading/SemaphoreSlim.cs +++ b/src/mscorlib/src/System/Threading/SemaphoreSlim.cs @@ -40,7 +40,6 @@ namespace System.Threading /// /// [ComVisible(false)] - [HostProtection(Synchronization = true, ExternalThreading = true)] [DebuggerDisplay("Current Count = {m_currentCount}")] public class SemaphoreSlim : IDisposable { @@ -89,14 +88,12 @@ namespace System.Threading internal TaskNode Prev, Next; internal TaskNode() : base() {} - [SecurityCritical] void IThreadPoolWorkItem.ExecuteWorkItem() { bool setSuccessfully = TrySetResult(true); - Contract.Assert(setSuccessfully, "Should have been able to complete task"); + Debug.Assert(setSuccessfully, "Should have been able to complete task"); } - [SecurityCritical] void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae) { /* nop */ } } #endregion @@ -182,13 +179,13 @@ namespace System.Threading if (initialCount < 0 || initialCount > maxCount) { throw new ArgumentOutOfRangeException( - "initialCount", initialCount, GetResourceString("SemaphoreSlim_ctor_InitialCountWrong")); + nameof(initialCount), initialCount, GetResourceString("SemaphoreSlim_ctor_InitialCountWrong")); } //validate input if (maxCount <= 0) { - throw new ArgumentOutOfRangeException("maxCount", maxCount, GetResourceString("SemaphoreSlim_ctor_MaxCountWrong")); + throw new ArgumentOutOfRangeException(nameof(maxCount), maxCount, GetResourceString("SemaphoreSlim_ctor_MaxCountWrong")); } m_maxCount = maxCount; @@ -245,7 +242,7 @@ namespace System.Threading if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue) { throw new System.ArgumentOutOfRangeException( - "timeout", timeout, GetResourceString("SemaphoreSlim_Wait_TimeoutWrong")); + nameof(timeout), timeout, GetResourceString("SemaphoreSlim_Wait_TimeoutWrong")); } // Call wait with the timeout milliseconds @@ -275,7 +272,7 @@ namespace System.Threading if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue) { throw new System.ArgumentOutOfRangeException( - "timeout", timeout, GetResourceString("SemaphoreSlim_Wait_TimeoutWrong")); + nameof(timeout), timeout, GetResourceString("SemaphoreSlim_Wait_TimeoutWrong")); } // Call wait with the timeout milliseconds @@ -372,7 +369,7 @@ namespace System.Threading // then block on (once we've released the lock). if (m_asyncHead != null) { - Contract.Assert(m_asyncTail != null, "tail should not be null if head isn't"); + Debug.Assert(m_asyncTail != null, "tail should not be null if head isn't"); asyncWaitTask = WaitAsync(millisecondsTimeout, cancellationToken); } // There are no async waiters, so we can proceed with normal synchronous waiting. @@ -404,7 +401,7 @@ namespace System.Threading // defer to synchronous waiters in priority, which means that if it's possible an asynchronous // waiter didn't get released because a synchronous waiter was present, we need to ensure // that synchronous waiter succeeds so that they have a chance to release. - Contract.Assert(!waitSuccessful || m_currentCount > 0, + Debug.Assert(!waitSuccessful || m_currentCount > 0, "If the wait was successful, there should be count available."); if (m_currentCount > 0) { @@ -579,7 +576,7 @@ namespace System.Threading if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue) { throw new System.ArgumentOutOfRangeException( - "timeout", timeout, GetResourceString("SemaphoreSlim_Wait_TimeoutWrong")); + nameof(timeout), timeout, GetResourceString("SemaphoreSlim_Wait_TimeoutWrong")); } // Call wait with the timeout milliseconds @@ -638,7 +635,7 @@ namespace System.Threading // the semaphore or when the timeout expired or cancellation was requested. else { - Contract.Assert(m_currentCount == 0, "m_currentCount should never be negative"); + Debug.Assert(m_currentCount == 0, "m_currentCount should never be negative"); var asyncWaiter = CreateAndAddAsyncWaiter(); return (millisecondsTimeout == Timeout.Infinite && !cancellationToken.CanBeCanceled) ? asyncWaiter : @@ -651,7 +648,7 @@ namespace System.Threading /// The created task. private TaskNode CreateAndAddAsyncWaiter() { - Contract.Assert(Monitor.IsEntered(m_lockObj), "Requires the lock be held"); + Debug.Assert(Monitor.IsEntered(m_lockObj), "Requires the lock be held"); // Create the task var task = new TaskNode(); @@ -659,13 +656,13 @@ namespace System.Threading // Add it to the linked list if (m_asyncHead == null) { - Contract.Assert(m_asyncTail == null, "If head is null, so too should be tail"); + Debug.Assert(m_asyncTail == null, "If head is null, so too should be tail"); m_asyncHead = task; m_asyncTail = task; } else { - Contract.Assert(m_asyncTail != null, "If head is not null, neither should be tail"); + Debug.Assert(m_asyncTail != null, "If head is not null, neither should be tail"); m_asyncTail.Next = task; task.Prev = m_asyncTail; m_asyncTail = task; @@ -681,7 +678,7 @@ namespace System.Threading private bool RemoveAsyncWaiter(TaskNode task) { Contract.Requires(task != null, "Expected non-null task"); - Contract.Assert(Monitor.IsEntered(m_lockObj), "Requires the lock be held"); + Debug.Assert(Monitor.IsEntered(m_lockObj), "Requires the lock be held"); // Is the task in the list? To be in the list, either it's the head or it has a predecessor that's in the list. bool wasInList = m_asyncHead == task || task.Prev != null; @@ -691,7 +688,7 @@ namespace System.Threading if (task.Prev != null) task.Prev.Next = task.Next; if (m_asyncHead == task) m_asyncHead = task.Next; if (m_asyncTail == task) m_asyncTail = task.Prev; - Contract.Assert((m_asyncHead == null) == (m_asyncTail == null), "Head is null iff tail is null"); + Debug.Assert((m_asyncHead == null) == (m_asyncTail == null), "Head is null iff tail is null"); // Make sure not to leak task.Next = task.Prev = null; @@ -706,8 +703,8 @@ namespace System.Threading /// The task to return to the caller. private async Task WaitUntilCountOrTimeoutAsync(TaskNode asyncWaiter, int millisecondsTimeout, CancellationToken cancellationToken) { - Contract.Assert(asyncWaiter != null, "Waiter should have been constructed"); - Contract.Assert(Monitor.IsEntered(m_lockObj), "Requires the lock be held"); + Debug.Assert(asyncWaiter != null, "Waiter should have been constructed"); + Debug.Assert(Monitor.IsEntered(m_lockObj), "Requires the lock be held"); // Wait until either the task is completed, timeout occurs, or cancellation is requested. // We need to ensure that the Task.Delay task is appropriately cleaned up if the await @@ -776,7 +773,7 @@ namespace System.Threading if (releaseCount < 1) { throw new ArgumentOutOfRangeException( - "releaseCount", releaseCount, GetResourceString("SemaphoreSlim_Release_CountWrong")); + nameof(releaseCount), releaseCount, GetResourceString("SemaphoreSlim_Release_CountWrong")); } int returnCount; @@ -797,14 +794,12 @@ namespace System.Threading // Signal to any synchronous waiters int waitCount = m_waitCount; - if (currentCount == 1 || waitCount == 1) + + int waitersToNotify = Math.Min(releaseCount, waitCount); + for (int i = 0; i < waitersToNotify; i++) { Monitor.Pulse(m_lockObj); } - else if (waitCount > 1) - { - Monitor.PulseAll(m_lockObj); - } // Now signal to any asynchronous waiters, if there are any. While we've already // signaled the synchronous waiters, we still hold the lock, and thus @@ -814,7 +809,7 @@ namespace System.Threading // waits are canceled, but the wait code path will handle that. if (m_asyncHead != null) { - Contract.Assert(m_asyncTail != null, "tail should not be null if head isn't null"); + Debug.Assert(m_asyncTail != null, "tail should not be null if head isn't null"); int maxAsyncToRelease = currentCount - waitCount; while (maxAsyncToRelease > 0 && m_asyncHead != null) { @@ -844,7 +839,6 @@ namespace System.Threading /// Queues a waiter task to the ThreadPool. We use this small helper method so that /// the larger Release(count) method does not need to be SecuritySafeCritical. /// - [SecuritySafeCritical] // for ThreadPool.UnsafeQueueCustomWorkItem private static void QueueWaiterTask(TaskNode waiterTask) { ThreadPool.UnsafeQueueCustomWorkItem(waiterTask, forceGlobal: false); @@ -898,7 +892,7 @@ namespace System.Threading private static void CancellationTokenCanceledEventHandler(object obj) { SemaphoreSlim semaphore = obj as SemaphoreSlim; - Contract.Assert(semaphore != null, "Expected a SemaphoreSlim"); + Debug.Assert(semaphore != null, "Expected a SemaphoreSlim"); lock (semaphore.m_lockObj) { Monitor.PulseAll(semaphore.m_lockObj); //wake up all waiters. diff --git a/src/mscorlib/src/System/Threading/SpinLock.cs b/src/mscorlib/src/System/Threading/SpinLock.cs index dea8743..1d90890 100644 --- a/src/mscorlib/src/System/Threading/SpinLock.cs +++ b/src/mscorlib/src/System/Threading/SpinLock.cs @@ -12,11 +12,11 @@ // // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- using System; -using System.Diagnostics; using System.Security.Permissions; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; +using System.Diagnostics; using System.Diagnostics.Contracts; namespace System.Threading @@ -55,7 +55,6 @@ namespace System.Threading /// /// [ComVisible(false)] - [HostProtection(Synchronization = true, ExternalThreading = true)] [DebuggerTypeProxy(typeof(SystemThreading_SpinLockDebugView))] [DebuggerDisplay("IsHeld = {IsHeld}")] public struct SpinLock @@ -107,7 +106,6 @@ namespace System.Threading // The waiters count is calculated by m_owner & WAITERS_MASK 01111....110 private static int MAXIMUM_WAITERS = WAITERS_MASK; - /// /// Initializes a new instance of the /// structure with the option to track thread IDs to improve debugging. @@ -123,11 +121,10 @@ namespace System.Threading if (!enableThreadOwnerTracking) { m_owner |= LOCK_ID_DISABLE_MASK; - Contract.Assert(!IsThreadOwnerTrackingEnabled, "property should be false by now"); + Debug.Assert(!IsThreadOwnerTrackingEnabled, "property should be false by now"); } } - /// /// Initializes a new instance of the /// structure with the option to track thread IDs to improve debugging. @@ -157,9 +154,6 @@ namespace System.Threading /// public void Enter(ref bool lockTaken) { -#if !FEATURE_CORECLR - Thread.BeginCriticalRegion(); -#endif //Try to keep the code and branching in this method as small as possible in order to inline the method int observedOwner = m_owner; if (lockTaken || //invalid parameter @@ -225,7 +219,7 @@ namespace System.Threading if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue) { throw new System.ArgumentOutOfRangeException( - "timeout", timeout, Environment.GetResourceString("SpinLock_TryEnter_ArgumentOutOfRange")); + nameof(timeout), timeout, Environment.GetResourceString("SpinLock_TryEnter_ArgumentOutOfRange")); } // Call reliable enter with the int-based timeout milliseconds @@ -256,10 +250,6 @@ namespace System.Threading /// a negative number other than -1, which represents an infinite time-out. public void TryEnter(int millisecondsTimeout, ref bool lockTaken) { -#if !FEATURE_CORECLR - Thread.BeginCriticalRegion(); -#endif - int observedOwner = m_owner; if (millisecondsTimeout < -1 || //invalid parameter lockTaken || //invalid parameter @@ -277,10 +267,6 @@ namespace System.Threading /// The lockTaken param private void ContinueTryEnter(int millisecondsTimeout, ref bool lockTaken) { - //Leave the critical region which is entered by the fast path -#if !FEATURE_CORECLR - Thread.EndCriticalRegion(); -#endif // The fast path doesn't throw any exception, so we have to validate the parameters here if (lockTaken) { @@ -291,23 +277,15 @@ namespace System.Threading if (millisecondsTimeout < -1) { throw new ArgumentOutOfRangeException( - "millisecondsTimeout", millisecondsTimeout, Environment.GetResourceString("SpinLock_TryEnter_ArgumentOutOfRange")); + nameof(millisecondsTimeout), millisecondsTimeout, Environment.GetResourceString("SpinLock_TryEnter_ArgumentOutOfRange")); } - uint startTime = 0; if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout != 0) { startTime = TimeoutHelper.GetTime(); } -#if !FEATURE_CORECLR - if (CdsSyncEtwBCLProvider.Log.IsEnabled()) - { - CdsSyncEtwBCLProvider.Log.SpinLock_FastPathFailed(m_owner); - } -#endif - if (IsThreadOwnerTrackingEnabled) { // Slow path for enabled thread tracking mode @@ -333,18 +311,22 @@ namespace System.Threading observedOwner = m_owner; if ((observedOwner & LOCK_ANONYMOUS_OWNED) == LOCK_UNOWNED) { -#if !FEATURE_CORECLR - Thread.BeginCriticalRegion(); -#endif - if (Interlocked.CompareExchange(ref m_owner, observedOwner | 1, observedOwner, ref lockTaken) == observedOwner) { + // Aquired lock return; } -#if !FEATURE_CORECLR - Thread.EndCriticalRegion(); -#endif + if (millisecondsTimeout == 0) + { + // Did not aquire lock in CompareExchange and timeout is 0 so fail fast + return; + } + } + else if (millisecondsTimeout == 0) + { + // Did not aquire lock as owned and timeout is 0 so fail fast + return; } else //failed to acquire the lock,then try to update the waiters. If the waiters count reached the maximum, jsut break the loop to avoid overflow { @@ -352,17 +334,6 @@ namespace System.Threading turn = (Interlocked.Add(ref m_owner, 2) & WAITERS_MASK) >> 1 ; } - - - // Check the timeout. - if (millisecondsTimeout == 0 || - (millisecondsTimeout != Timeout.Infinite && - TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) <= 0)) - { - DecrementWaiters(); - return; - } - //***Step 2. Spinning //lock acquired failed and waiters updated int processorCount = PlatformHelper.ProcessorCount; @@ -377,32 +348,24 @@ namespace System.Threading observedOwner = m_owner; if ((observedOwner & LOCK_ANONYMOUS_OWNED) == LOCK_UNOWNED) { -#if !FEATURE_CORECLR - Thread.BeginCriticalRegion(); -#endif - int newOwner = (observedOwner & WAITERS_MASK) == 0 ? // Gets the number of waiters, if zero observedOwner | 1 // don't decrement it. just set the lock bit, it is zzero because a previous call of Exit(false) ehich corrupted the waiters : (observedOwner - 2) | 1; // otherwise decrement the waiters and set the lock bit - Contract.Assert((newOwner & WAITERS_MASK) >= 0); + Debug.Assert((newOwner & WAITERS_MASK) >= 0); if (Interlocked.CompareExchange(ref m_owner, newOwner, observedOwner, ref lockTaken) == observedOwner) { return; } - -#if !FEATURE_CORECLR - Thread.EndCriticalRegion(); -#endif } } - } - // Check the timeout. - if (millisecondsTimeout != Timeout.Infinite && TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) <= 0) - { - DecrementWaiters(); - return; + // Check the timeout. + if (millisecondsTimeout != Timeout.Infinite && TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) <= 0) + { + DecrementWaiters(); + return; + } } //*** Step 3, Yielding @@ -413,22 +376,15 @@ namespace System.Threading observedOwner = m_owner; if ((observedOwner & LOCK_ANONYMOUS_OWNED) == LOCK_UNOWNED) { -#if !FEATURE_CORECLR - Thread.BeginCriticalRegion(); -#endif int newOwner = (observedOwner & WAITERS_MASK) == 0 ? // Gets the number of waiters, if zero observedOwner | 1 // don't decrement it. just set the lock bit, it is zzero because a previous call of Exit(false) ehich corrupted the waiters : (observedOwner - 2) | 1; // otherwise decrement the waiters and set the lock bit - Contract.Assert((newOwner & WAITERS_MASK) >= 0); + Debug.Assert((newOwner & WAITERS_MASK) >= 0); if (Interlocked.CompareExchange(ref m_owner, newOwner, observedOwner, ref lockTaken) == observedOwner) { return; } - -#if !FEATURE_CORECLR - Thread.EndCriticalRegion(); -#endif } if (yieldsoFar % SLEEP_ONE_FREQUENCY == 0) @@ -470,7 +426,7 @@ namespace System.Threading if ((observedOwner & WAITERS_MASK) == 0) return; // don't decrement the waiters if it's corrupted by previous call of Exit(false) if (Interlocked.CompareExchange(ref m_owner, observedOwner - 2, observedOwner) == observedOwner) { - Contract.Assert(!IsThreadOwnerTrackingEnabled); // Make sure the waiters never be negative which will cause the thread tracking bit to be flipped + Debug.Assert(!IsThreadOwnerTrackingEnabled); // Make sure the waiters never be negative which will cause the thread tracking bit to be flipped break; } spinner.SpinOnce(); @@ -483,7 +439,7 @@ namespace System.Threading /// private void ContinueTryEnterWithThreadTracking(int millisecondsTimeout, uint startTime, ref bool lockTaken) { - Contract.Assert(IsThreadOwnerTrackingEnabled); + Debug.Assert(IsThreadOwnerTrackingEnabled); int lockUnowned = 0; // We are using thread IDs to mark ownership. Snap the thread ID and check for recursion. @@ -510,17 +466,10 @@ namespace System.Threading if (m_owner == lockUnowned) { -#if !FEATURE_CORECLR - Thread.BeginCriticalRegion(); -#endif if (Interlocked.CompareExchange(ref m_owner, m_newOwner, lockUnowned, ref lockTaken) == lockUnowned) { return; } -#if !FEATURE_CORECLR - // The thread failed to get the lock, so we don't need to remain in a critical region. - Thread.EndCriticalRegion(); -#endif } // Check the timeout. We only RDTSC if the next spin will yield, to amortize the cost. if (millisecondsTimeout == 0 || @@ -550,11 +499,6 @@ namespace System.Threading ExitSlowPath(true); else Interlocked.Decrement(ref m_owner); - -#if !FEATURE_CORECLR - Thread.EndCriticalRegion(); -#endif - } /// @@ -586,10 +530,6 @@ namespace System.Threading } else ExitSlowPath(useMemoryBarrier); - -#if !FEATURE_CORECLR - Thread.EndCriticalRegion(); -#endif } /// diff --git a/src/mscorlib/src/System/Threading/SpinWait.cs b/src/mscorlib/src/System/Threading/SpinWait.cs index c2cd0b6..1b31407 100644 --- a/src/mscorlib/src/System/Threading/SpinWait.cs +++ b/src/mscorlib/src/System/Threading/SpinWait.cs @@ -14,6 +14,7 @@ using System; using System.Runtime.ConstrainedExecution; using System.Security.Permissions; using System.Threading; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Diagnostics.CodeAnalysis; @@ -69,7 +70,6 @@ namespace System.Threading /// threads must spin, each should use its own instance of SpinWait. /// /// - [HostProtection(Synchronization = true, ExternalThreading = true)] public struct SpinWait { @@ -132,10 +132,6 @@ namespace System.Threading // remove the thread from the scheduler's queue for 10+ms, if the system is // configured to use the (default) coarse-grained system timer. // - -#if !FEATURE_CORECLR - CdsSyncEtwBCLProvider.Log.SpinWait_NextSpinWillYield(); -#endif int yieldsSoFar = (m_count >= YIELD_THRESHOLD ? m_count - YIELD_THRESHOLD : m_count); if ((yieldsSoFar % SLEEP_1_EVERY_HOW_MANY_TIMES) == (SLEEP_1_EVERY_HOW_MANY_TIMES - 1)) @@ -197,7 +193,7 @@ namespace System.Threading #endif SpinUntil(condition, Timeout.Infinite); #if DEBUG - Contract.Assert(result); + Debug.Assert(result); #endif } @@ -220,7 +216,7 @@ namespace System.Threading if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue) { throw new System.ArgumentOutOfRangeException( - "timeout", timeout, Environment.GetResourceString("SpinWait_SpinUntil_TimeoutWrong")); + nameof(timeout), timeout, Environment.GetResourceString("SpinWait_SpinUntil_TimeoutWrong")); } // Call wait with the timeout milliseconds @@ -242,11 +238,11 @@ namespace System.Threading if (millisecondsTimeout < Timeout.Infinite) { throw new ArgumentOutOfRangeException( - "millisecondsTimeout", millisecondsTimeout, Environment.GetResourceString("SpinWait_SpinUntil_TimeoutWrong")); + nameof(millisecondsTimeout), millisecondsTimeout, Environment.GetResourceString("SpinWait_SpinUntil_TimeoutWrong")); } if (condition == null) { - throw new ArgumentNullException("condition", Environment.GetResourceString("SpinWait_SpinUntil_ArgumentNull")); + throw new ArgumentNullException(nameof(condition), Environment.GetResourceString("SpinWait_SpinUntil_ArgumentNull")); } uint startTime = 0; if (millisecondsTimeout != 0 && millisecondsTimeout != Timeout.Infinite) @@ -304,7 +300,7 @@ namespace System.Threading s_lastProcessorCountRefreshTicks = now; } - Contract.Assert(procCount > 0 && procCount <= 64, + Debug.Assert(procCount > 0 && procCount <= 64, "Processor count not within the expected range (1 - 64)."); return procCount; @@ -345,7 +341,7 @@ namespace System.Threading public static int UpdateTimeOut(uint startTime, int originalWaitMillisecondsTimeout) { // The function must be called in case the time out is not infinite - Contract.Assert(originalWaitMillisecondsTimeout != Timeout.Infinite); + Debug.Assert(originalWaitMillisecondsTimeout != Timeout.Infinite); uint elapsedMilliseconds = (GetTime() - startTime); diff --git a/src/mscorlib/src/System/Threading/SynchronizationContext.cs b/src/mscorlib/src/System/Threading/SynchronizationContext.cs index a3f28d1..5531597 100644 --- a/src/mscorlib/src/System/Threading/SynchronizationContext.cs +++ b/src/mscorlib/src/System/Threading/SynchronizationContext.cs @@ -24,6 +24,7 @@ namespace System.Threading using System.Runtime.ConstrainedExecution; using System.Reflection; using System.Security; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Diagnostics.CodeAnalysis; @@ -43,17 +44,12 @@ namespace System.Threading // I'd like this to be an interface, or at least an abstract class - but neither seems to play nice with FriendAccessAllowed. // [FriendAccessAllowed] - [SecurityCritical] internal class WinRTSynchronizationContextFactoryBase { - [SecurityCritical] public virtual SynchronizationContext Create(object coreDispatcher) {return null;} } #endif //FEATURE_COMINTEROP -#if !FEATURE_CORECLR - [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags =SecurityPermissionFlag.ControlPolicy|SecurityPermissionFlag.ControlEvidence)] -#endif public class SynchronizationContext { #if FEATURE_SYNCHRONIZATIONCONTEXT_WAIT @@ -76,7 +72,6 @@ namespace System.Threading static Type s_cachedPreparedType5; // protected so that only the derived sync context class can enable these flags - [System.Security.SecuritySafeCritical] // auto-generated [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "We never dereference s_cachedPreparedType*, so ordering is unimportant")] protected void SetWaitNotificationRequired() { @@ -143,39 +138,43 @@ namespace System.Threading } #if FEATURE_SYNCHRONIZATIONCONTEXT_WAIT - // Method called when the CLR does a wait operation - [System.Security.SecurityCritical] // auto-generated_required + // Method called when the CLR does a wait operation [CLSCompliant(false)] [PrePrepareMethod] public virtual int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout) { + return WaitHelper(waitHandles, waitAll, millisecondsTimeout); + } + + // Method that can be called by Wait overrides + [CLSCompliant(false)] + [PrePrepareMethod] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + protected static int WaitHelper(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout) + { if (waitHandles == null) { - throw new ArgumentNullException("waitHandles"); + throw new ArgumentNullException(nameof(waitHandles)); } Contract.EndContractBlock(); - return WaitHelper(waitHandles, waitAll, millisecondsTimeout); + + return WaitHelperNative(waitHandles, waitAll, millisecondsTimeout); } - - // Static helper to which the above method can delegate to in order to get the default + + // Static helper to which the above method can delegate to in order to get the default // COM behavior. - [System.Security.SecurityCritical] // auto-generated_required [CLSCompliant(false)] [PrePrepareMethod] - [MethodImplAttribute(MethodImplOptions.InternalCall)] + [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - protected static extern int WaitHelper(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout); + private static extern int WaitHelperNative(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout); #endif -#if FEATURE_CORECLR - - [System.Security.SecurityCritical] public static void SetSynchronizationContext(SynchronizationContext syncContext) { Thread.CurrentThread.SynchronizationContext = syncContext; } - [System.Security.SecurityCritical] public static void SetThreadStaticContext(SynchronizationContext syncContext) { Thread.CurrentThread.SynchronizationContext = syncContext; @@ -206,56 +205,11 @@ namespace System.Threading } } -#else //FEATURE_CORECLR - - // set SynchronizationContext on the current thread - [System.Security.SecurityCritical] // auto-generated_required - public static void SetSynchronizationContext(SynchronizationContext syncContext) - { - ExecutionContext ec = Thread.CurrentThread.GetMutableExecutionContext(); - ec.SynchronizationContext = syncContext; - ec.SynchronizationContextNoFlow = syncContext; - } - - // Get the current SynchronizationContext on the current thread - public static SynchronizationContext Current - { - get - { - return Thread.CurrentThread.GetExecutionContextReader().SynchronizationContext ?? GetThreadLocalContext(); - } - } - - // Get the last SynchronizationContext that was set explicitly (not flowed via ExecutionContext.Capture/Run) - internal static SynchronizationContext CurrentNoFlow - { - [FriendAccessAllowed] - get - { - return Thread.CurrentThread.GetExecutionContextReader().SynchronizationContextNoFlow ?? GetThreadLocalContext(); - } - } - - private static SynchronizationContext GetThreadLocalContext() - { - SynchronizationContext context = null; - -#if FEATURE_APPX - if (context == null && AppDomain.IsAppXModel()) - context = GetWinRTContext(); -#endif - - return context; - } - -#endif //FEATURE_CORECLR - #if FEATURE_APPX - [SecuritySafeCritical] private static SynchronizationContext GetWinRTContext() { - Contract.Assert(Environment.IsWinRTSupported); - Contract.Assert(AppDomain.IsAppXModel()); + Debug.Assert(Environment.IsWinRTSupported); + Debug.Assert(AppDomain.IsAppXModel()); // // We call into the VM to get the dispatcher. This is because: @@ -274,10 +228,8 @@ namespace System.Threading return null; } - [SecurityCritical] static WinRTSynchronizationContextFactoryBase s_winRTContextFactory; - [SecurityCritical] private static WinRTSynchronizationContextFactoryBase GetWinRTSynchronizationContextFactory() { // @@ -295,7 +247,6 @@ namespace System.Threading } [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SecurityCritical] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Interface)] private static extern object GetWinRTDispatcherForCurrentThread(); @@ -310,7 +261,6 @@ namespace System.Threading } #if FEATURE_SYNCHRONIZATIONCONTEXT_WAIT - [System.Security.SecurityCritical] // auto-generated private static int InvokeWaitMethodHelper(SynchronizationContext syncContext, IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout) { return syncContext.Wait(waitHandles, waitAll, millisecondsTimeout); diff --git a/src/mscorlib/src/System/Threading/Tasks/AsyncCausalityTracer.cs b/src/mscorlib/src/System/Threading/Tasks/AsyncCausalityTracer.cs index c29b11a..ec7c5aa 100644 --- a/src/mscorlib/src/System/Threading/Tasks/AsyncCausalityTracer.cs +++ b/src/mscorlib/src/System/Threading/Tasks/AsyncCausalityTracer.cs @@ -131,7 +131,6 @@ namespace System.Threading.Tasks private static Loggers f_LoggingOn; //assumes false by default // The precise static constructor will run first time somebody attempts to access this class - [SecuritySafeCritical] static AsyncCausalityTracer() { if (!Environment.IsWinRTSupported) return; @@ -153,7 +152,7 @@ namespace System.Threading.Tasks s_TracerFactory = (WFD.IAsyncCausalityTracerStatics)factory; EventRegistrationToken token = s_TracerFactory.add_TracingStatusChanged(new EventHandler(TracingStatusChangedHandler)); - Contract.Assert(token != default(EventRegistrationToken), "EventRegistrationToken is null"); + Debug.Assert(token != default(EventRegistrationToken), "EventRegistrationToken is null"); } catch (Exception ex) { @@ -165,7 +164,6 @@ namespace System.Threading.Tasks } - [SecuritySafeCritical] private static void TracingStatusChangedHandler(Object sender, WFD.TracingStatusChangedEventArgs args) { if (args.Enabled) diff --git a/src/mscorlib/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs b/src/mscorlib/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs index 05e6dbf..71eb787 100644 --- a/src/mscorlib/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs +++ b/src/mscorlib/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.IO; using System.Runtime.CompilerServices; @@ -62,9 +63,9 @@ internal sealed class BeginEndAwaitableAdapter : ICriticalNotifyCompletion { /// It expects that an BeginEndAwaitableAdapter instance was supplied to the APM Begin method as the object state. public readonly static AsyncCallback Callback = (asyncResult) => { - Contract.Assert(asyncResult != null); - Contract.Assert(asyncResult.IsCompleted); - Contract.Assert(asyncResult.AsyncState is BeginEndAwaitableAdapter); + Debug.Assert(asyncResult != null); + Debug.Assert(asyncResult.IsCompleted); + Debug.Assert(asyncResult.AsyncState is BeginEndAwaitableAdapter); // Get the adapter object supplied as the "object state" to the Begin method BeginEndAwaitableAdapter adapter = (BeginEndAwaitableAdapter) asyncResult.AsyncState; @@ -81,7 +82,7 @@ internal sealed class BeginEndAwaitableAdapter : ICriticalNotifyCompletion { Action continuation = Interlocked.Exchange(ref adapter._continuation, CALLBACK_RAN); if (continuation != null) { - Contract.Assert(continuation != CALLBACK_RAN); + Debug.Assert(continuation != CALLBACK_RAN); continuation(); } }; @@ -108,10 +109,9 @@ internal sealed class BeginEndAwaitableAdapter : ICriticalNotifyCompletion { /// Schedules the continuation to run when the operation completes. /// The continuation. - [SecurityCritical] public void UnsafeOnCompleted(Action continuation) { - Contract.Assert(continuation != null); + Debug.Assert(continuation != null); OnCompleted(continuation); } @@ -120,7 +120,7 @@ internal sealed class BeginEndAwaitableAdapter : ICriticalNotifyCompletion { /// The continuation. public void OnCompleted(Action continuation) { - Contract.Assert(continuation != null); + Debug.Assert(continuation != null); // If the continuation field is null, then set it to be the target continuation // so that when the operation completes, it'll invoke the continuation. If it's non-null, @@ -139,7 +139,7 @@ internal sealed class BeginEndAwaitableAdapter : ICriticalNotifyCompletion { /// The IAsyncResult for the operation. public IAsyncResult GetResult() { - Contract.Assert(_asyncResult != null && _asyncResult.IsCompleted); + Debug.Assert(_asyncResult != null && _asyncResult.IsCompleted); // Get the IAsyncResult IAsyncResult result = _asyncResult; diff --git a/src/mscorlib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs b/src/mscorlib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs index cb4a22b..c7a96b0 100644 --- a/src/mscorlib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs +++ b/src/mscorlib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs @@ -28,7 +28,6 @@ namespace System.Threading.Tasks /// Provides concurrent and exclusive task schedulers that coordinate to execute /// tasks while ensuring that concurrent tasks may run concurrently and exclusive tasks never do. /// - [HostProtection(Synchronization = true, ExternalThreading = true)] [DebuggerDisplay("Concurrent={ConcurrentTaskCountForDebugger}, Exclusive={ExclusiveTaskCountForDebugger}, Mode={ModeForDebugger}")] [DebuggerTypeProxy(typeof(ConcurrentExclusiveSchedulerPair.DebugView))] public class ConcurrentExclusiveSchedulerPair @@ -101,9 +100,9 @@ namespace System.Threading.Tasks public ConcurrentExclusiveSchedulerPair(TaskScheduler taskScheduler, int maxConcurrencyLevel, int maxItemsPerTask) { // Validate arguments - if (taskScheduler == null) throw new ArgumentNullException("taskScheduler"); - if (maxConcurrencyLevel == 0 || maxConcurrencyLevel < -1) throw new ArgumentOutOfRangeException("maxConcurrencyLevel"); - if (maxItemsPerTask == 0 || maxItemsPerTask < -1) throw new ArgumentOutOfRangeException("maxItemsPerTask"); + if (taskScheduler == null) throw new ArgumentNullException(nameof(taskScheduler)); + if (maxConcurrencyLevel == 0 || maxConcurrencyLevel < -1) throw new ArgumentOutOfRangeException(nameof(maxConcurrencyLevel)); + if (maxItemsPerTask == 0 || maxItemsPerTask < -1) throw new ArgumentOutOfRangeException(nameof(maxItemsPerTask)); Contract.EndContractBlock(); // Store configuration @@ -213,13 +212,13 @@ namespace System.Threading.Tasks ThreadPool.QueueUserWorkItem(state => { var localCs = (CompletionState)state; // don't use 'cs', as it'll force a closure - Contract.Assert(!localCs.Task.IsCompleted, "Completion should only happen once."); + Debug.Assert(!localCs.Task.IsCompleted, "Completion should only happen once."); var exceptions = localCs.m_exceptions; bool success = (exceptions != null && exceptions.Count > 0) ? localCs.TrySetException(exceptions) : localCs.TrySetResult(default(VoidTaskResult)); - Contract.Assert(success, "Expected to complete completion task."); + Debug.Assert(success, "Expected to complete completion task."); }, cs); } } @@ -336,7 +335,7 @@ namespace System.Threading.Tasks // Check to see if all tasks have completed and if completion has been requested. CleanupStateIfCompletingAndQuiesced(); } - else Contract.Assert(m_processingCount == EXCLUSIVE_PROCESSING_SENTINEL, "The processing count must be the sentinel if it's not >= 0."); + else Debug.Assert(m_processingCount == EXCLUSIVE_PROCESSING_SENTINEL, "The processing count must be the sentinel if it's not >= 0."); } /// @@ -351,7 +350,7 @@ namespace System.Threading.Tasks try { // Note that we're processing exclusive tasks on the current thread - Contract.Assert(!m_threadProcessingMapping.ContainsKey(Thread.CurrentThread.ManagedThreadId), + Debug.Assert(!m_threadProcessingMapping.ContainsKey(Thread.CurrentThread.ManagedThreadId), "This thread should not yet be involved in this pair's processing."); m_threadProcessingMapping[Thread.CurrentThread.ManagedThreadId] = ProcessingMode.ProcessingExclusiveTask; @@ -372,7 +371,7 @@ namespace System.Threading.Tasks // We're no longer processing exclusive tasks on the current thread ProcessingMode currentMode; m_threadProcessingMapping.TryRemove(Thread.CurrentThread.ManagedThreadId, out currentMode); - Contract.Assert(currentMode == ProcessingMode.ProcessingExclusiveTask, + Debug.Assert(currentMode == ProcessingMode.ProcessingExclusiveTask, "Somehow we ended up escaping exclusive mode."); lock (ValueLock) @@ -382,7 +381,7 @@ namespace System.Threading.Tasks // There might be more concurrent tasks available, for example, if concurrent tasks arrived // after we exited the loop, or if we exited the loop while concurrent tasks were still // available but we hit our maxItemsPerTask limit. - Contract.Assert(m_processingCount == EXCLUSIVE_PROCESSING_SENTINEL, "The processing mode should not have deviated from exclusive."); + Debug.Assert(m_processingCount == EXCLUSIVE_PROCESSING_SENTINEL, "The processing mode should not have deviated from exclusive."); m_processingCount = 0; ProcessAsyncIfNecessary(true); } @@ -400,7 +399,7 @@ namespace System.Threading.Tasks try { // Note that we're processing concurrent tasks on the current thread - Contract.Assert(!m_threadProcessingMapping.ContainsKey(Thread.CurrentThread.ManagedThreadId), + Debug.Assert(!m_threadProcessingMapping.ContainsKey(Thread.CurrentThread.ManagedThreadId), "This thread should not yet be involved in this pair's processing."); m_threadProcessingMapping[Thread.CurrentThread.ManagedThreadId] = ProcessingMode.ProcessingConcurrentTasks; @@ -432,7 +431,7 @@ namespace System.Threading.Tasks // We're no longer processing concurrent tasks on the current thread ProcessingMode currentMode; m_threadProcessingMapping.TryRemove(Thread.CurrentThread.ManagedThreadId, out currentMode); - Contract.Assert(currentMode == ProcessingMode.ProcessingConcurrentTasks, + Debug.Assert(currentMode == ProcessingMode.ProcessingConcurrentTasks, "Somehow we ended up escaping concurrent mode."); lock (ValueLock) @@ -442,7 +441,7 @@ namespace System.Threading.Tasks // There might be more concurrent tasks available, for example, if concurrent tasks arrived // after we exited the loop, or if we exited the loop while concurrent tasks were still // available but we hit our maxItemsPerTask limit. - Contract.Assert(m_processingCount > 0, "The procesing mode should not have deviated from concurrent."); + Debug.Assert(m_processingCount > 0, "The procesing mode should not have deviated from concurrent."); if (m_processingCount > 0) --m_processingCount; ProcessAsyncIfNecessary(true); } @@ -524,10 +523,9 @@ namespace System.Threading.Tasks /// Queues a task to the scheduler. /// The task to be queued. - [SecurityCritical] protected internal override void QueueTask(Task task) { - Contract.Assert(task != null, "Infrastructure should have provided a non-null task."); + Debug.Assert(task != null, "Infrastructure should have provided a non-null task."); lock (m_pair.ValueLock) { // If the scheduler has already had completion requested, no new work is allowed to be scheduled @@ -541,10 +539,9 @@ namespace System.Threading.Tasks /// Executes a task on this scheduler. /// The task to be executed. - [SecuritySafeCritical] internal void ExecuteTask(Task task) { - Contract.Assert(task != null, "Infrastructure should have provided a non-null task."); + Debug.Assert(task != null, "Infrastructure should have provided a non-null task."); base.TryExecuteTask(task); } @@ -552,10 +549,9 @@ namespace System.Threading.Tasks /// The task to execute. /// Whether the task was previously queued to the scheduler. /// true if the task could be executed; otherwise, false. - [SecurityCritical] protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) { - Contract.Assert(task != null, "Infrastructure should have provided a non-null task."); + Debug.Assert(task != null, "Infrastructure should have provided a non-null task."); // If the scheduler has had completion requested, no new work is allowed to be scheduled. // A non-locked read on m_completionRequested (in CompletionRequested) is acceptable here because: @@ -628,7 +624,7 @@ namespace System.Threading.Tasks } catch { - Contract.Assert(t.IsFaulted, "Task should be faulted due to the scheduler faulting it and throwing the exception."); + Debug.Assert(t.IsFaulted, "Task should be faulted due to the scheduler faulting it and throwing the exception."); var ignored = t.Exception; throw; } @@ -642,7 +638,6 @@ namespace System.Threading.Tasks /// This method is separated out not because of performance reasons but so that /// the SecuritySafeCritical attribute may be employed. /// - [SecuritySafeCritical] private static bool TryExecuteTaskShim(object state) { var tuple = (Tuple)state; @@ -651,7 +646,6 @@ namespace System.Threading.Tasks /// Gets for debugging purposes the tasks scheduled to this scheduler. /// An enumerable of the tasks queued. - [SecurityCritical] protected override IEnumerable GetScheduledTasks() { return m_tasks; } /// Gets the number of tasks queued to this scheduler. @@ -748,11 +742,11 @@ namespace System.Threading.Tasks exceptionThrown = false; } catch (SynchronizationLockException) { exceptionThrown = true; } - Contract.Assert(held == !exceptionThrown, "The locking scheme was not correctly followed."); + Debug.Assert(held == !exceptionThrown, "The locking scheme was not correctly followed."); } #endif #else - Contract.Assert(Monitor.IsEntered(syncObj) == held, "The locking scheme was not correctly followed."); + Debug.Assert(Monitor.IsEntered(syncObj) == held, "The locking scheme was not correctly followed."); #endif } diff --git a/src/mscorlib/src/System/Threading/Tasks/FutureFactory.cs b/src/mscorlib/src/System/Threading/Tasks/FutureFactory.cs index b1f634c..c98e219 100644 --- a/src/mscorlib/src/System/Threading/Tasks/FutureFactory.cs +++ b/src/mscorlib/src/System/Threading/Tasks/FutureFactory.cs @@ -15,6 +15,7 @@ using System.Security; using System.Security.Permissions; using System.Runtime.CompilerServices; using System.Threading; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.Versioning; @@ -38,7 +39,6 @@ namespace System.Threading.Tasks /// Task{TResult}.Factory property. /// /// - [HostProtection(Synchronization = true, ExternalThreading = true)] public class TaskFactory { // Member variables, DefaultScheduler, other properties and ctors @@ -832,32 +832,17 @@ namespace System.Threading.Tasks try { - // Do NOT change the code below. - // 4.5 relies on the fact that IAsyncResult CompletedSynchronously flag needs to be set correctly, - // sadly this has not been the case that is why the behaviour from 4.5 broke 4.0 buggy apps. Any other - // change will likely brake 4.5 behavior so if possible never touch this code again. - if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) + //This is 4.5 behaviour + //if we don't require synchronization, a faster set result path is taken + var asyncResult = beginMethod(iar => { - //This is 4.5 behaviour - //if we don't require synchronization, a faster set result path is taken - var asyncResult = beginMethod(iar => - { - if (!iar.CompletedSynchronously) - FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true); - }, state); - if (asyncResult.CompletedSynchronously) - { - Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed."); - FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false); - } - } - else - { - //This is the original 4.0 behaviour - var asyncResult = beginMethod(iar => - { + if (!iar.CompletedSynchronously) FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true); - }, state); + }, state); + if (asyncResult.CompletedSynchronously) + { + Debug.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed."); + FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false); } } catch @@ -969,31 +954,16 @@ namespace System.Threading.Tasks try { - // Do NOT change the code below. - // 4.5 relies on the fact that IAsyncResult CompletedSynchronously flag needs to be set correctly, - // sadly this has not been the case that is why the behaviour from 4.5 broke 4.0 buggy apps. Any other - // change will likely brake 4.5 behavior so if possible never touch this code again. - if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) + //if we don't require synchronization, a faster set result path is taken + var asyncResult = beginMethod(arg1, iar => { - //if we don't require synchronization, a faster set result path is taken - var asyncResult = beginMethod(arg1, iar => - { - if (!iar.CompletedSynchronously) - FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true); - }, state); - if (asyncResult.CompletedSynchronously) - { - Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed."); - FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false); - } - } - else - { - //quirk for previous versions - var asyncResult = beginMethod(arg1, iar => - { + if (!iar.CompletedSynchronously) FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true); - }, state); + }, state); + if (asyncResult.CompletedSynchronously) + { + Debug.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed."); + FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false); } } catch @@ -1114,31 +1084,16 @@ namespace System.Threading.Tasks try { - // Do NOT change the code below. - // 4.5 relies on the fact that IAsyncResult CompletedSynchronously flag needs to be set correctly, - // sadly this has not been the case that is why the behaviour from 4.5 broke 4.0 buggy apps. Any other - // change will likely brake 4.5 behavior so if possible never touch this code again. - if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) + //if we don't require synchronization, a faster set result path is taken + var asyncResult = beginMethod(arg1, arg2, iar => { - //if we don't require synchronization, a faster set result path is taken - var asyncResult = beginMethod(arg1, arg2, iar => - { - if (!iar.CompletedSynchronously) - FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true); - }, state); - if (asyncResult.CompletedSynchronously) - { - Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed."); - FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false); - } - } - else - { - //quirk for previous versions - var asyncResult = beginMethod(arg1, arg2, iar => - { + if (!iar.CompletedSynchronously) FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true); - }, state); + }, state); + if (asyncResult.CompletedSynchronously) + { + Debug.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed."); + FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false); } } catch @@ -1266,31 +1221,16 @@ namespace System.Threading.Tasks try { - // Do NOT change the code below. - // 4.5 relies on the fact that IAsyncResult CompletedSynchronously flag needs to be set correctly, - // sadly this has not been the case that is why the behaviour from 4.5 broke 4.0 buggy apps. Any other - // change will likely brake 4.5 behavior so if possible never touch this code again. - if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) + //if we don't require synchronization, a faster set result path is taken + var asyncResult = beginMethod(arg1, arg2, arg3, iar => { - //if we don't require synchronization, a faster set result path is taken - var asyncResult = beginMethod(arg1, arg2, arg3, iar => - { - if (!iar.CompletedSynchronously) - FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true); - }, state); - if (asyncResult.CompletedSynchronously) - { - Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed."); - FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false); - } - } - else - { - //quirk for previous versions - var asyncResult = beginMethod(arg1, arg2, arg3, iar => - { + if (!iar.CompletedSynchronously) FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true); - }, state); + }, state); + if (asyncResult.CompletedSynchronously) + { + Debug.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed."); + FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false); } } catch @@ -1330,9 +1270,9 @@ namespace System.Threading.Tasks where TInstance : class { // Validate arguments, but only with asserts, as this is an internal only implementation. - Contract.Assert(thisRef != null, "Expected a non-null thisRef"); - Contract.Assert(beginMethod != null, "Expected a non-null beginMethod"); - Contract.Assert(endMethod != null, "Expected a non-null endMethod"); + Debug.Assert(thisRef != null, "Expected a non-null thisRef"); + Debug.Assert(beginMethod != null, "Expected a non-null beginMethod"); + Debug.Assert(endMethod != null, "Expected a non-null endMethod"); // Create the promise and start the operation. // No try/catch is necessary here as we want exceptions to bubble out, and because @@ -1345,7 +1285,7 @@ namespace System.Threading.Tasks // If it completed synchronously, we'll handle that here. if (asyncResult.CompletedSynchronously) { - Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed."); + Debug.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed."); promise.Complete(thisRef, endMethod, asyncResult, requiresSynchronization: false); } @@ -1425,7 +1365,7 @@ namespace System.Threading.Tasks TInstance thisRef, Func endMethod, IAsyncResult asyncResult, bool requiresSynchronization) { - Contract.Assert(!IsCompleted, "The task should not have been completed yet."); + Debug.Assert(!IsCompleted, "The task should not have been completed yet."); // Run the end method and complete the task bool successfullySet = false; @@ -1454,7 +1394,7 @@ namespace System.Threading.Tasks { successfullySet = TrySetException(exc); } - Contract.Assert(successfullySet, "Expected the task to not yet be completed"); + Debug.Assert(successfullySet, "Expected the task to not yet be completed"); } } @@ -1801,7 +1741,7 @@ namespace System.Threading.Tasks } else { - Contract.Assert(continuationAction != null); + Debug.Assert(continuationAction != null); return starter.ContinueWith( // use a cached delegate @@ -1854,7 +1794,7 @@ namespace System.Threading.Tasks } else { - Contract.Assert(continuationAction != null); + Debug.Assert(continuationAction != null); return starter.ContinueWith( //the following delegate avoids closure capture as much as possible //completedTasks.Result == tasksCopy; @@ -2200,7 +2140,7 @@ namespace System.Threading.Tasks } else { - Contract.Assert(continuationAction != null); + Debug.Assert(continuationAction != null); return starter.ContinueWith( //the following delegate avoids closure capture as much as possible //completedTask.Result is the winning task; state == continuationAction @@ -2246,7 +2186,7 @@ namespace System.Threading.Tasks } else { - Contract.Assert(continuationAction != null); + Debug.Assert(continuationAction != null); return starter.ContinueWith( // Use a cached delegate GenericDelegateCache.CWAnyActionDelegate, diff --git a/src/mscorlib/src/System/Threading/Tasks/Parallel.cs b/src/mscorlib/src/System/Threading/Tasks/Parallel.cs index 5ec2ae3..7808943 100644 --- a/src/mscorlib/src/System/Threading/Tasks/Parallel.cs +++ b/src/mscorlib/src/System/Threading/Tasks/Parallel.cs @@ -98,7 +98,7 @@ namespace System.Threading.Tasks set { if ((value == 0) || (value < -1)) - throw new ArgumentOutOfRangeException("MaxDegreeOfParallelism"); + throw new ArgumentOutOfRangeException(nameof(MaxDegreeOfParallelism)); m_maxDegreeOfParallelism = value; } } @@ -142,7 +142,6 @@ namespace System.Threading.Tasks /// The class provides library-based data parallel replacements /// for common operations such as for loops, for each loops, and execution of a set of statements. /// - [HostProtection(Synchronization = true, ExternalThreading = true)] public static class Parallel { // static counter for generating unique Fork/Join Context IDs to be used in ETW events @@ -208,11 +207,11 @@ namespace System.Threading.Tasks { if (actions == null) { - throw new ArgumentNullException("actions"); + throw new ArgumentNullException(nameof(actions)); } if (parallelOptions == null) { - throw new ArgumentNullException("parallelOptions"); + throw new ArgumentNullException(nameof(parallelOptions)); } // Throw an ODE if we're passed a disposed CancellationToken. @@ -423,7 +422,7 @@ namespace System.Threading.Tasks { if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } return ForWorker( @@ -452,7 +451,7 @@ namespace System.Threading.Tasks { if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } return ForWorker64( @@ -491,11 +490,11 @@ namespace System.Threading.Tasks { if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (parallelOptions == null) { - throw new ArgumentNullException("parallelOptions"); + throw new ArgumentNullException(nameof(parallelOptions)); } return ForWorker( @@ -534,11 +533,11 @@ namespace System.Threading.Tasks { if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (parallelOptions == null) { - throw new ArgumentNullException("parallelOptions"); + throw new ArgumentNullException(nameof(parallelOptions)); } return ForWorker64( @@ -590,7 +589,7 @@ namespace System.Threading.Tasks { if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } return ForWorker( @@ -620,7 +619,7 @@ namespace System.Threading.Tasks { if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } return ForWorker64( @@ -661,11 +660,11 @@ namespace System.Threading.Tasks { if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (parallelOptions == null) { - throw new ArgumentNullException("parallelOptions"); + throw new ArgumentNullException(nameof(parallelOptions)); } return ForWorker( @@ -707,11 +706,11 @@ namespace System.Threading.Tasks { if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (parallelOptions == null) { - throw new ArgumentNullException("parallelOptions"); + throw new ArgumentNullException(nameof(parallelOptions)); } return ForWorker64( @@ -765,15 +764,15 @@ namespace System.Threading.Tasks { if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (localInit == null) { - throw new ArgumentNullException("localInit"); + throw new ArgumentNullException(nameof(localInit)); } if (localFinally == null) { - throw new ArgumentNullException("localFinally"); + throw new ArgumentNullException(nameof(localFinally)); } return ForWorker( @@ -827,15 +826,15 @@ namespace System.Threading.Tasks { if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (localInit == null) { - throw new ArgumentNullException("localInit"); + throw new ArgumentNullException(nameof(localInit)); } if (localFinally == null) { - throw new ArgumentNullException("localFinally"); + throw new ArgumentNullException(nameof(localFinally)); } return ForWorker64( @@ -900,19 +899,19 @@ namespace System.Threading.Tasks { if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (localInit == null) { - throw new ArgumentNullException("localInit"); + throw new ArgumentNullException(nameof(localInit)); } if (localFinally == null) { - throw new ArgumentNullException("localFinally"); + throw new ArgumentNullException(nameof(localFinally)); } if (parallelOptions == null) { - throw new ArgumentNullException("parallelOptions"); + throw new ArgumentNullException(nameof(parallelOptions)); } return ForWorker( @@ -977,19 +976,19 @@ namespace System.Threading.Tasks { if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (localInit == null) { - throw new ArgumentNullException("localInit"); + throw new ArgumentNullException(nameof(localInit)); } if (localFinally == null) { - throw new ArgumentNullException("localFinally"); + throw new ArgumentNullException(nameof(localFinally)); } if (parallelOptions == null) { - throw new ArgumentNullException("parallelOptions"); + throw new ArgumentNullException(nameof(parallelOptions)); } @@ -1031,9 +1030,9 @@ namespace System.Threading.Tasks Func bodyWithLocal, Func localInit, Action localFinally) { - Contract.Assert(((body == null ? 0 : 1) + (bodyWithState == null ? 0 : 1) + (bodyWithLocal == null ? 0 : 1)) == 1, + Debug.Assert(((body == null ? 0 : 1) + (bodyWithState == null ? 0 : 1) + (bodyWithLocal == null ? 0 : 1)) == 1, "expected exactly one body function to be supplied"); - Contract.Assert(bodyWithLocal != null || (localInit == null && localFinally == null), + Debug.Assert(bodyWithLocal != null || (localInit == null && localFinally == null), "thread local functions should only be supplied for loops w/ thread local bodies"); // Instantiate our result. Specifics will be filled in later. @@ -1157,12 +1156,12 @@ namespace System.Threading.Tasks if (bodyWithState != null) { - Contract.Assert(sharedPStateFlags != null); + Debug.Assert(sharedPStateFlags != null); state = new ParallelLoopState32(sharedPStateFlags); } else if (bodyWithLocal != null) { - Contract.Assert(sharedPStateFlags != null); + Debug.Assert(sharedPStateFlags != null); state = new ParallelLoopState32(sharedPStateFlags); if (localInit != null) { @@ -1346,9 +1345,9 @@ namespace System.Threading.Tasks Func bodyWithLocal, Func localInit, Action localFinally) { - Contract.Assert(((body == null ? 0 : 1) + (bodyWithState == null ? 0 : 1) + (bodyWithLocal == null ? 0 : 1)) == 1, + Debug.Assert(((body == null ? 0 : 1) + (bodyWithState == null ? 0 : 1) + (bodyWithLocal == null ? 0 : 1)) == 1, "expected exactly one body function to be supplied"); - Contract.Assert(bodyWithLocal != null || (localInit == null && localFinally == null), + Debug.Assert(bodyWithLocal != null || (localInit == null && localFinally == null), "thread local functions should only be supplied for loops w/ thread local bodies"); // Instantiate our result. Specifics will be filled in later. @@ -1471,12 +1470,12 @@ namespace System.Threading.Tasks if (bodyWithState != null) { - Contract.Assert(sharedPStateFlags != null); + Debug.Assert(sharedPStateFlags != null); state = new ParallelLoopState64(sharedPStateFlags); } else if (bodyWithLocal != null) { - Contract.Assert(sharedPStateFlags != null); + Debug.Assert(sharedPStateFlags != null); state = new ParallelLoopState64(sharedPStateFlags); // If a thread-local selector was supplied, invoke it. Otherwise, use the default. @@ -1656,11 +1655,11 @@ namespace System.Threading.Tasks { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } return ForEachWorker( @@ -1701,15 +1700,15 @@ namespace System.Threading.Tasks { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (parallelOptions == null) { - throw new ArgumentNullException("parallelOptions"); + throw new ArgumentNullException(nameof(parallelOptions)); } return ForEachWorker( @@ -1741,11 +1740,11 @@ namespace System.Threading.Tasks { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } return ForEachWorker( @@ -1788,15 +1787,15 @@ namespace System.Threading.Tasks { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (parallelOptions == null) { - throw new ArgumentNullException("parallelOptions"); + throw new ArgumentNullException(nameof(parallelOptions)); } return ForEachWorker( @@ -1828,11 +1827,11 @@ namespace System.Threading.Tasks { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } return ForEachWorker( @@ -1875,15 +1874,15 @@ namespace System.Threading.Tasks { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (parallelOptions == null) { - throw new ArgumentNullException("parallelOptions"); + throw new ArgumentNullException(nameof(parallelOptions)); } return ForEachWorker( @@ -1936,19 +1935,19 @@ namespace System.Threading.Tasks { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (localInit == null) { - throw new ArgumentNullException("localInit"); + throw new ArgumentNullException(nameof(localInit)); } if (localFinally == null) { - throw new ArgumentNullException("localFinally"); + throw new ArgumentNullException(nameof(localFinally)); } return ForEachWorker( @@ -2013,23 +2012,23 @@ namespace System.Threading.Tasks { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (localInit == null) { - throw new ArgumentNullException("localInit"); + throw new ArgumentNullException(nameof(localInit)); } if (localFinally == null) { - throw new ArgumentNullException("localFinally"); + throw new ArgumentNullException(nameof(localFinally)); } if (parallelOptions == null) { - throw new ArgumentNullException("parallelOptions"); + throw new ArgumentNullException(nameof(parallelOptions)); } return ForEachWorker( @@ -2082,19 +2081,19 @@ namespace System.Threading.Tasks { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (localInit == null) { - throw new ArgumentNullException("localInit"); + throw new ArgumentNullException(nameof(localInit)); } if (localFinally == null) { - throw new ArgumentNullException("localFinally"); + throw new ArgumentNullException(nameof(localFinally)); } return ForEachWorker( @@ -2158,23 +2157,23 @@ namespace System.Threading.Tasks { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (localInit == null) { - throw new ArgumentNullException("localInit"); + throw new ArgumentNullException(nameof(localInit)); } if (localFinally == null) { - throw new ArgumentNullException("localFinally"); + throw new ArgumentNullException(nameof(localFinally)); } if (parallelOptions == null) { - throw new ArgumentNullException("parallelOptions"); + throw new ArgumentNullException(nameof(parallelOptions)); } return ForEachWorker( @@ -2214,10 +2213,10 @@ namespace System.Threading.Tasks Func bodyWithEverything, Func localInit, Action localFinally) { - Contract.Assert(((body == null ? 0 : 1) + (bodyWithState == null ? 0 : 1) + + Debug.Assert(((body == null ? 0 : 1) + (bodyWithState == null ? 0 : 1) + (bodyWithStateAndIndex == null ? 0 : 1) + (bodyWithStateAndLocal == null ? 0 : 1) + (bodyWithEverything == null ? 0 : 1)) == 1, "expected exactly one body function to be supplied"); - Contract.Assert((bodyWithStateAndLocal != null) || (bodyWithEverything != null) || (localInit == null && localFinally == null), + Debug.Assert((bodyWithStateAndLocal != null) || (bodyWithEverything != null) || (localInit == null && localFinally == null), "thread local functions should only be supplied for loops w/ thread local bodies"); // Before getting started, do a quick peek to see if we have been canceled already @@ -2278,8 +2277,8 @@ namespace System.Threading.Tasks Func bodyWithEverything, Func localInit, Action localFinally) { - Contract.Assert(array != null); - Contract.Assert(parallelOptions != null, "ForEachWorker(array): parallelOptions is null"); + Debug.Assert(array != null); + Debug.Assert(parallelOptions != null, "ForEachWorker(array): parallelOptions is null"); int from = array.GetLowerBound(0); int to = array.GetUpperBound(0) + 1; @@ -2337,8 +2336,8 @@ namespace System.Threading.Tasks Func bodyWithEverything, Func localInit, Action localFinally) { - Contract.Assert(list != null); - Contract.Assert(parallelOptions != null, "ForEachWorker(list): parallelOptions is null"); + Debug.Assert(list != null); + Debug.Assert(parallelOptions != null, "ForEachWorker(list): parallelOptions is null"); if (body != null) { @@ -2416,11 +2415,11 @@ namespace System.Threading.Tasks { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } return PartitionerForEachWorker(source, s_defaultParallelOptions, body, null, null, null, null, null, null); @@ -2475,11 +2474,11 @@ namespace System.Threading.Tasks { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } return PartitionerForEachWorker(source, s_defaultParallelOptions, null, body, null, null, null, null, null); @@ -2537,11 +2536,11 @@ namespace System.Threading.Tasks { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (!source.KeysNormalized) @@ -2621,19 +2620,19 @@ namespace System.Threading.Tasks { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (localInit == null) { - throw new ArgumentNullException("localInit"); + throw new ArgumentNullException(nameof(localInit)); } if (localFinally == null) { - throw new ArgumentNullException("localFinally"); + throw new ArgumentNullException(nameof(localFinally)); } return PartitionerForEachWorker(source, s_defaultParallelOptions, null, null, null, body, null, localInit, localFinally); @@ -2711,19 +2710,19 @@ namespace System.Threading.Tasks { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (localInit == null) { - throw new ArgumentNullException("localInit"); + throw new ArgumentNullException(nameof(localInit)); } if (localFinally == null) { - throw new ArgumentNullException("localFinally"); + throw new ArgumentNullException(nameof(localFinally)); } if (!source.KeysNormalized) @@ -2793,15 +2792,15 @@ namespace System.Threading.Tasks { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (parallelOptions == null) { - throw new ArgumentNullException("parallelOptions"); + throw new ArgumentNullException(nameof(parallelOptions)); } return PartitionerForEachWorker(source, parallelOptions, body, null, null, null, null, null, null); @@ -2868,15 +2867,15 @@ namespace System.Threading.Tasks { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (parallelOptions == null) { - throw new ArgumentNullException("parallelOptions"); + throw new ArgumentNullException(nameof(parallelOptions)); } return PartitionerForEachWorker(source, parallelOptions, null, body, null, null, null, null, null); @@ -2946,15 +2945,15 @@ namespace System.Threading.Tasks { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (parallelOptions == null) { - throw new ArgumentNullException("parallelOptions"); + throw new ArgumentNullException(nameof(parallelOptions)); } if (!source.KeysNormalized) @@ -3046,23 +3045,23 @@ namespace System.Threading.Tasks { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (localInit == null) { - throw new ArgumentNullException("localInit"); + throw new ArgumentNullException(nameof(localInit)); } if (localFinally == null) { - throw new ArgumentNullException("localFinally"); + throw new ArgumentNullException(nameof(localFinally)); } if (parallelOptions == null) { - throw new ArgumentNullException("parallelOptions"); + throw new ArgumentNullException(nameof(parallelOptions)); } return PartitionerForEachWorker(source, parallelOptions, null, null, null, body, null, localInit, localFinally); @@ -3152,23 +3151,23 @@ namespace System.Threading.Tasks { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (body == null) { - throw new ArgumentNullException("body"); + throw new ArgumentNullException(nameof(body)); } if (localInit == null) { - throw new ArgumentNullException("localInit"); + throw new ArgumentNullException(nameof(localInit)); } if (localFinally == null) { - throw new ArgumentNullException("localFinally"); + throw new ArgumentNullException(nameof(localFinally)); } if (parallelOptions == null) { - throw new ArgumentNullException("parallelOptions"); + throw new ArgumentNullException(nameof(parallelOptions)); } if (!source.KeysNormalized) @@ -3191,14 +3190,14 @@ namespace System.Threading.Tasks Func localInit, Action localFinally) { - Contract.Assert(((simpleBody == null ? 0 : 1) + (bodyWithState == null ? 0 : 1) + + Debug.Assert(((simpleBody == null ? 0 : 1) + (bodyWithState == null ? 0 : 1) + (bodyWithStateAndIndex == null ? 0 : 1) + (bodyWithStateAndLocal == null ? 0 : 1) + (bodyWithEverything == null ? 0 : 1)) == 1, "PartitionForEach: expected exactly one body function to be supplied"); - Contract.Assert((bodyWithStateAndLocal != null) || (bodyWithEverything != null) || (localInit == null && localFinally == null), + Debug.Assert((bodyWithStateAndLocal != null) || (bodyWithEverything != null) || (localInit == null && localFinally == null), "PartitionForEach: thread local functions should only be supplied for loops w/ thread local bodies"); OrderablePartitioner orderedSource = source as OrderablePartitioner; - Contract.Assert((orderedSource != null) || (bodyWithStateAndIndex == null && bodyWithEverything == null), + Debug.Assert((orderedSource != null) || (bodyWithStateAndIndex == null && bodyWithEverything == null), "PartitionForEach: bodies with indices are only allowable for OrderablePartitioner"); if (!source.SupportsDynamicPartitions) @@ -3401,7 +3400,7 @@ namespace System.Threading.Tasks else if (bodyWithStateAndLocal != null) localValue = bodyWithStateAndLocal(t, state, localValue); else - Contract.Assert(false, "PartitionerForEach: illegal body type in Partitioner handler"); + Debug.Assert(false, "PartitionerForEach: illegal body type in Partitioner handler"); // Any break, stop or exception causes us to halt @@ -3576,7 +3575,7 @@ namespace System.Threading.Tasks public bool LimitExceeded() { - Contract.Assert(m_timeLimit != 0, "Probably the default initializer for LoopTimer was used somewhere"); + Debug.Assert(m_timeLimit != 0, "Probably the default initializer for LoopTimer was used somewhere"); // comparing against the next expected time saves an addition operation here // Also we omit the comparison for wrap around here. The only side effect is one extra early yield every 38 days. diff --git a/src/mscorlib/src/System/Threading/Tasks/ParallelLoopState.cs b/src/mscorlib/src/System/Threading/Tasks/ParallelLoopState.cs index 4db3a9d..6a62cf8 100644 --- a/src/mscorlib/src/System/Threading/Tasks/ParallelLoopState.cs +++ b/src/mscorlib/src/System/Threading/Tasks/ParallelLoopState.cs @@ -26,7 +26,6 @@ namespace System.Threading.Tasks /// Enables iterations of loops to interact with /// other iterations. /// - [HostProtection(Synchronization = true, ExternalThreading = true)] [DebuggerDisplay("ShouldExitCurrentIteration = {ShouldExitCurrentIteration}")] public class ParallelLoopState { @@ -47,7 +46,7 @@ namespace System.Threading.Tasks { get { - Contract.Assert(false); + Debug.Assert(false); throw new NotSupportedException( Environment.GetResourceString("ParallelState_NotSupportedException_UnsupportedMethod")); } @@ -104,7 +103,7 @@ namespace System.Threading.Tasks { get { - Contract.Assert(false); + Debug.Assert(false); throw new NotSupportedException( Environment.GetResourceString("ParallelState_NotSupportedException_UnsupportedMethod")); } @@ -152,7 +151,7 @@ namespace System.Threading.Tasks // Internal/virtual support for Break(). internal virtual void InternalBreak() { - Contract.Assert(false); + Debug.Assert(false); throw new NotSupportedException( Environment.GetResourceString("ParallelState_NotSupportedException_UnsupportedMethod")); } diff --git a/src/mscorlib/src/System/Threading/Tasks/ParallelRangeManager.cs b/src/mscorlib/src/System/Threading/Tasks/ParallelRangeManager.cs index c4b66c4..49f61a6 100644 --- a/src/mscorlib/src/System/Threading/Tasks/ParallelRangeManager.cs +++ b/src/mscorlib/src/System/Threading/Tasks/ParallelRangeManager.cs @@ -12,6 +12,7 @@ using System; using System.Threading; +using System.Diagnostics; using System.Diagnostics.Contracts; #pragma warning disable 0420 @@ -160,7 +161,7 @@ namespace System.Threading.Tasks bool bRetVal = FindNewWork(out nFromInclusiveLocal, out nToExclusiveLocal); - Contract.Assert((nFromInclusiveLocal <= Int32.MaxValue) && (nFromInclusiveLocal >= Int32.MinValue) && + Debug.Assert((nFromInclusiveLocal <= Int32.MaxValue) && (nFromInclusiveLocal >= Int32.MinValue) && (nToExclusiveLocal <= Int32.MaxValue) && (nToExclusiveLocal >= Int32.MinValue)); // convert to 32 bit before returning @@ -218,7 +219,7 @@ namespace System.Threading.Tasks // // find the actual number of index ranges we will need // - Contract.Assert((uSpan / uRangeSize) < Int32.MaxValue); + Debug.Assert((uSpan / uRangeSize) < Int32.MaxValue); int nNumRanges = (int)(uSpan / uRangeSize); @@ -251,7 +252,7 @@ namespace System.Threading.Tasks nCurrentIndex > nToExclusive) { // this should only happen at the last index - Contract.Assert(i == nNumRanges - 1); + Debug.Assert(i == nNumRanges - 1); nCurrentIndex = nToExclusive; } @@ -267,7 +268,7 @@ namespace System.Threading.Tasks /// internal RangeWorker RegisterNewWorker() { - Contract.Assert(m_indexRanges != null && m_indexRanges.Length != 0); + Debug.Assert(m_indexRanges != null && m_indexRanges.Length != 0); int nInitialRange = (Interlocked.Increment(ref m_nCurrentIndexRangeToAssign) - 1) % m_indexRanges.Length; diff --git a/src/mscorlib/src/System/Threading/Tasks/ProducerConsumerQueues.cs b/src/mscorlib/src/System/Threading/Tasks/ProducerConsumerQueues.cs index 462ee0a..6b9dfbb 100644 --- a/src/mscorlib/src/System/Threading/Tasks/ProducerConsumerQueues.cs +++ b/src/mscorlib/src/System/Threading/Tasks/ProducerConsumerQueues.cs @@ -140,10 +140,10 @@ namespace System.Threading.Tasks internal SingleProducerSingleConsumerQueue() { // Validate constants in ctor rather than in an explicit cctor that would cause perf degradation - Contract.Assert(INIT_SEGMENT_SIZE > 0, "Initial segment size must be > 0."); - Contract.Assert((INIT_SEGMENT_SIZE & (INIT_SEGMENT_SIZE - 1)) == 0, "Initial segment size must be a power of 2"); - Contract.Assert(INIT_SEGMENT_SIZE <= MAX_SEGMENT_SIZE, "Initial segment size should be <= maximum."); - Contract.Assert(MAX_SEGMENT_SIZE < Int32.MaxValue / 2, "Max segment size * 2 must be < Int32.MaxValue, or else overflow could occur."); + Debug.Assert(INIT_SEGMENT_SIZE > 0, "Initial segment size must be > 0."); + Debug.Assert((INIT_SEGMENT_SIZE & (INIT_SEGMENT_SIZE - 1)) == 0, "Initial segment size must be a power of 2"); + Debug.Assert(INIT_SEGMENT_SIZE <= MAX_SEGMENT_SIZE, "Initial segment size should be <= maximum."); + Debug.Assert(MAX_SEGMENT_SIZE < Int32.MaxValue / 2, "Max segment size * 2 must be < Int32.MaxValue, or else overflow could occur."); // Initialize the queue m_head = m_tail = new Segment(INIT_SEGMENT_SIZE); @@ -183,7 +183,7 @@ namespace System.Threading.Tasks } int newSegmentSize = m_tail.m_array.Length << 1; // double size - Contract.Assert(newSegmentSize > 0, "The max size should always be small enough that we don't overflow."); + Debug.Assert(newSegmentSize > 0, "The max size should always be small enough that we don't overflow."); if (newSegmentSize > MAX_SEGMENT_SIZE) newSegmentSize = MAX_SEGMENT_SIZE; var newSegment = new Segment(newSegmentSize); @@ -456,7 +456,7 @@ namespace System.Threading.Tasks /// The Count is not thread safe, so we need to acquire the lock. int IProducerConsumerQueue.GetCountSafe(object syncObj) { - Contract.Assert(syncObj != null, "The syncObj parameter is null."); + Debug.Assert(syncObj != null, "The syncObj parameter is null."); lock (syncObj) { return Count; diff --git a/src/mscorlib/src/System/Threading/Tasks/TPLETWProvider.cs b/src/mscorlib/src/System/Threading/Tasks/TPLETWProvider.cs index 5f79f30..325aa91 100644 --- a/src/mscorlib/src/System/Threading/Tasks/TPLETWProvider.cs +++ b/src/mscorlib/src/System/Threading/Tasks/TPLETWProvider.cs @@ -216,7 +216,6 @@ namespace System.Threading.Tasks /// The kind of fork/join operation. /// The lower bound of the loop. /// The upper bound of the loop. - [SecuritySafeCritical] [Event(PARALLELLOOPBEGIN_ID, Level = EventLevel.Informational, ActivityOptions=EventActivityOptions.Recursive, Task = TplEtwProvider.Tasks.Loop, Opcode = EventOpcode.Start)] public void ParallelLoopBegin( @@ -261,7 +260,6 @@ namespace System.Threading.Tasks /// The task ID. /// The loop ID. /// the total number of iterations processed. - [SecuritySafeCritical] [Event(PARALLELLOOPEND_ID, Level = EventLevel.Informational, Task = TplEtwProvider.Tasks.Loop, Opcode = EventOpcode.Stop)] public void ParallelLoopEnd( int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER @@ -298,7 +296,6 @@ namespace System.Threading.Tasks /// The invoke ID. /// The kind of fork/join operation. /// The number of actions being invoked. - [SecuritySafeCritical] [Event(PARALLELINVOKEBEGIN_ID, Level = EventLevel.Informational, ActivityOptions=EventActivityOptions.Recursive, Task = TplEtwProvider.Tasks.Invoke, Opcode = EventOpcode.Start)] public void ParallelInvokeBegin( @@ -412,7 +409,6 @@ namespace System.Threading.Tasks /// The task ID. /// The task ID /// The options used to create the task. - [SecuritySafeCritical] [Event(TASKSCHEDULED_ID, Task = Tasks.TaskScheduled, Version=1, Opcode = EventOpcode.Send, Level = EventLevel.Informational, Keywords = Keywords.TaskTransfer|Keywords.Tasks)] public void TaskScheduled( @@ -475,7 +471,6 @@ namespace System.Threading.Tasks /// The task ID. /// The task ID. /// Whether the task completed due to an error. - [SecuritySafeCritical] [Event(TASKCOMPLETED_ID, Version=1, Level = EventLevel.Informational, Keywords = Keywords.TaskStops)] public void TaskCompleted( @@ -513,7 +508,6 @@ namespace System.Threading.Tasks /// If known, if 'TaskID' has a 'continueWith' task, mention give its ID here. /// 0 means unknown. This allows better visualization of the common sequential chaining case. /// - [SecuritySafeCritical] [Event(TASKWAITBEGIN_ID, Version=3, Task = TplEtwProvider.Tasks.TaskWait, Opcode = EventOpcode.Send, Level = EventLevel.Informational, Keywords = Keywords.TaskTransfer|Keywords.Tasks)] public void TaskWaitBegin( @@ -600,7 +594,6 @@ namespace System.Threading.Tasks /// The scheduler ID. /// The task ID. /// The activityId for the continuation. - [SecuritySafeCritical] [Event(AWAITTASKCONTINUATIONSCHEDULED_ID, Task = Tasks.AwaitTaskContinuationScheduled, Opcode = EventOpcode.Send, Level = EventLevel.Informational, Keywords = Keywords.TaskTransfer|Keywords.Tasks)] public void AwaitTaskContinuationScheduled( @@ -629,7 +622,6 @@ namespace System.Threading.Tasks } } - [SecuritySafeCritical] [Event(TRACEOPERATIONSTART_ID, Version=1, Level = EventLevel.Informational, Keywords = Keywords.AsyncCausalityOperation)] public void TraceOperationBegin(int TaskID, string OperationName, long RelatedContext) @@ -655,7 +647,6 @@ namespace System.Threading.Tasks } } - [SecuritySafeCritical] [Event(TRACEOPERATIONRELATION_ID, Version=1, Level = EventLevel.Informational, Keywords = Keywords.AsyncCausalityRelation)] public void TraceOperationRelation(int TaskID, CausalityRelation Relation) @@ -664,7 +655,6 @@ namespace System.Threading.Tasks WriteEvent(TRACEOPERATIONRELATION_ID, TaskID,(int) Relation); // optmized overload for this exists } - [SecuritySafeCritical] [Event(TRACEOPERATIONSTOP_ID, Version=1, Level = EventLevel.Informational, Keywords = Keywords.AsyncCausalityOperation)] public void TraceOperationEnd(int TaskID, AsyncCausalityStatus Status) @@ -673,7 +663,6 @@ namespace System.Threading.Tasks WriteEvent(TRACEOPERATIONSTOP_ID, TaskID,(int) Status); // optmized overload for this exists } - [SecuritySafeCritical] [Event(TRACESYNCHRONOUSWORKSTART_ID, Version=1, Level = EventLevel.Informational, Keywords = Keywords.AsyncCausalitySynchronousWork)] public void TraceSynchronousWorkBegin(int TaskID, CausalitySynchronousWork Work) @@ -682,7 +671,6 @@ namespace System.Threading.Tasks WriteEvent(TRACESYNCHRONOUSWORKSTART_ID, TaskID,(int) Work); // optmized overload for this exists } - [SecuritySafeCritical] [Event(TRACESYNCHRONOUSWORKSTOP_ID, Version=1, Level = EventLevel.Informational, Keywords = Keywords.AsyncCausalitySynchronousWork)] public void TraceSynchronousWorkEnd(CausalitySynchronousWork Work) diff --git a/src/mscorlib/src/System/Threading/Tasks/Task.cs b/src/mscorlib/src/System/Threading/Tasks/Task.cs index 36f8401..cf081f7 100644 --- a/src/mscorlib/src/System/Threading/Tasks/Task.cs +++ b/src/mscorlib/src/System/Threading/Tasks/Task.cs @@ -137,7 +137,6 @@ namespace System.Threading.Tasks /// InternalWait method serves a potential marker for when a Task is entering a wait operation. /// /// - [HostProtection(Synchronization = true, ExternalThreading = true)] [DebuggerTypeProxy(typeof(SystemThreadingTasks_TaskDebugView))] [DebuggerDisplay("Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription}")] public class Task : IThreadPoolWorkItem, IAsyncResult, IDisposable @@ -152,7 +151,7 @@ namespace System.Threading.Tasks private volatile int m_taskId; // this task's unique ID. initialized only if it is ever requested - internal object m_action; // The body of the task. Might be Action, Action or Action. Or possibly a Func. + internal Delegate m_action; // The body of the task. Might be Action, Action or Action. Or possibly a Func. // If m_action is set to null it will indicate that we operate in the // "externally triggered completion" mode, which is exclusively meant // for the signalling Task (aka. promise). In this mode, @@ -339,7 +338,7 @@ namespace System.Threading.Tasks // (action,TCO). It should always be true. internal Task(object state, TaskCreationOptions creationOptions, bool promiseStyle) { - Contract.Assert(promiseStyle, "Promise CTOR: promiseStyle was false"); + Debug.Assert(promiseStyle, "Promise CTOR: promiseStyle was false"); // Check the creationOptions. We allow the AttachedToParent option to be specified for promise tasks. // Also allow RunContinuationsAsynchronously because this is the constructor called by TCS @@ -580,7 +579,7 @@ namespace System.Threading.Tasks /// A CancellationToken for the Task. /// Options to customize behavior of Task. /// Internal options to customize behavior of Task. - internal void TaskConstructorCore(object action, object state, CancellationToken cancellationToken, + internal void TaskConstructorCore(Delegate action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler) { m_action = action; @@ -609,7 +608,7 @@ namespace System.Threading.Tasks InternalTaskOptions.ContinuationTask | InternalTaskOptions.LazyCancellation | InternalTaskOptions.QueuedByRuntime)); - Contract.Assert(illegalInternalOptions == 0, "TaskConstructorCore: Illegal internal options"); + Debug.Assert(illegalInternalOptions == 0, "TaskConstructorCore: Illegal internal options"); #endif // Throw exception if the user specifies both LongRunning and SelfReplicating @@ -620,8 +619,8 @@ namespace System.Threading.Tasks } // Assign options to m_stateAndOptionsFlag. - Contract.Assert(m_stateFlags == 0, "TaskConstructorCore: non-zero m_stateFlags"); - Contract.Assert((((int)creationOptions) | OptionsMask) == OptionsMask, "TaskConstructorCore: options take too many bits"); + Debug.Assert(m_stateFlags == 0, "TaskConstructorCore: non-zero m_stateFlags"); + Debug.Assert((((int)creationOptions) | OptionsMask) == OptionsMask, "TaskConstructorCore: options take too many bits"); var tmpFlags = (int)creationOptions | (int)internalOptions; if ((m_action == null) || ((internalOptions & InternalTaskOptions.ContinuationTask) != 0)) { @@ -649,7 +648,7 @@ namespace System.Threading.Tasks // we need to do this as the very last thing in the construction path, because the CT registration could modify m_stateFlags if (cancellationToken.CanBeCanceled) { - Contract.Assert((internalOptions & + Debug.Assert((internalOptions & (InternalTaskOptions.ChildReplica | InternalTaskOptions.SelfReplicating | InternalTaskOptions.ContinuationTask)) == 0, "TaskConstructorCore: Did not expect to see cancelable token for replica/replicating or continuation task."); @@ -743,7 +742,7 @@ namespace System.Threading.Tasks antecedentTask.RemoveContinuation(continuation); } } - Contract.Assert(targetTask != null, + Debug.Assert(targetTask != null, "targetTask should have been non-null, with the supplied argument being a task or a tuple containing one"); targetTask.InternalCancel(false); } @@ -753,7 +752,7 @@ namespace System.Threading.Tasks { get { - Delegate d = (Delegate)m_action; + Delegate d = m_action; return d != null ? d.Method.ToString() : "{null}"; } } @@ -764,10 +763,9 @@ namespace System.Threading.Tasks /// /// A stack crawl mark pointing to the frame of the caller. - [SecuritySafeCritical] internal void PossiblyCaptureContext(ref StackCrawlMark stackMark) { - Contract.Assert(m_contingentProperties == null || m_contingentProperties.m_capturedContext == null, + Debug.Assert(m_contingentProperties == null || m_contingentProperties.m_capturedContext == null, "Captured an ExecutionContext when one was already captured."); // In the legacy .NET 3.5 build, we don't have the optimized overload of Capture() @@ -791,7 +789,7 @@ namespace System.Threading.Tasks // a read of the volatile m_stateFlags field. internal static TaskCreationOptions OptionsMethod(int flags) { - Contract.Assert((OptionsMask & 1) == 1, "OptionsMask needs a shift in Options.get"); + Debug.Assert((OptionsMask & 1) == 1, "OptionsMask needs a shift in Options.get"); return (TaskCreationOptions)(flags & OptionsMask); } @@ -841,7 +839,7 @@ namespace System.Threading.Tasks /// true to set the bit; false to unset the bit. internal void SetNotificationForWaitCompletion(bool enabled) { - Contract.Assert((Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0, + Debug.Assert((Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0, "Should only be used for promise-style tasks"); // hasn't been vetted on other kinds as there hasn't been a need if (enabled) @@ -849,7 +847,7 @@ namespace System.Threading.Tasks // Atomically set the END_AWAIT_NOTIFICATION bit bool success = AtomicStateUpdate(TASK_STATE_WAIT_COMPLETION_NOTIFICATION, TASK_STATE_COMPLETED_MASK | TASK_STATE_COMPLETION_RESERVED); - Contract.Assert(success, "Tried to set enabled on completed Task"); + Debug.Assert(success, "Tried to set enabled on completed Task"); } else { @@ -886,7 +884,7 @@ namespace System.Threading.Tasks /// true if any of the tasks require notification; otherwise, false. internal static bool AnyTaskRequiresNotifyDebuggerOfWaitCompletion(Task[] tasks) { - Contract.Assert(tasks != null, "Expected non-null array of tasks"); + Debug.Assert(tasks != null, "Expected non-null array of tasks"); foreach (var task in tasks) { if (task != null && @@ -926,7 +924,7 @@ namespace System.Threading.Tasks // bit was unset between the time that it was checked and this method was called. // It's so remote a chance that it's worth having the assert to protect against misuse. bool isWaitNotificationEnabled = IsWaitNotificationEnabled; - Contract.Assert(isWaitNotificationEnabled, "Should only be called if the wait completion bit is set."); + Debug.Assert(isWaitNotificationEnabled, "Should only be called if the wait completion bit is set."); return isWaitNotificationEnabled; } } @@ -946,7 +944,7 @@ namespace System.Threading.Tasks // It's theoretically possible but extremely rare that this assert could fire because the // bit was unset between the time that it was checked and this method was called. // It's so remote a chance that it's worth having the assert to protect against misuse. - Contract.Assert(IsWaitNotificationEnabled, "Should only be called if the wait completion bit is set."); + Debug.Assert(IsWaitNotificationEnabled, "Should only be called if the wait completion bit is set."); // Now that we're notifying the debugger, clear the bit. The debugger should do this anyway, // but this adds a bit of protection in case it fails to, and given that the debugger is involved, @@ -991,7 +989,7 @@ namespace System.Threading.Tasks /// internal void AddNewChild() { - Contract.Assert(Task.InternalCurrent == this || this.IsSelfReplicatingRoot, "Task.AddNewChild(): Called from an external context"); + Debug.Assert(Task.InternalCurrent == this || this.IsSelfReplicatingRoot, "Task.AddNewChild(): Called from an external context"); var props = EnsureContingentPropertiesInitialized(); @@ -1014,10 +1012,10 @@ namespace System.Threading.Tasks // We need to subtract that child from m_completionCountdown, or the parent will never complete. internal void DisregardChild() { - Contract.Assert(Task.InternalCurrent == this, "Task.DisregardChild(): Called from an external context"); + Debug.Assert(Task.InternalCurrent == this, "Task.DisregardChild(): Called from an external context"); var props = EnsureContingentPropertiesInitialized(); - Contract.Assert(props.m_completionCountdown >= 2, "Task.DisregardChild(): Expected parent count to be >= 2"); + Debug.Assert(props.m_completionCountdown >= 2, "Task.DisregardChild(): Expected parent count to be >= 2"); Interlocked.Decrement(ref props.m_completionCountdown); } @@ -1161,7 +1159,6 @@ namespace System.Threading.Tasks // // Internal version of RunSynchronously that allows not waiting for completion. // - [SecuritySafeCritical] // Needed for QueueTask internal void InternalRunSynchronously(TaskScheduler scheduler, bool waitForCompletion) { Contract.Requires(scheduler != null, "Task.InternalRunSynchronously(): null TaskScheduler"); @@ -1235,7 +1232,7 @@ namespace System.Threading.Tasks // Mark ourselves as "handled" to avoid crashing the finalizer thread if the caller neglects to // call Wait() on this task. // m_contingentProperties.m_exceptionsHolder *should* already exist after AddException() - Contract.Assert( + Debug.Assert( (m_contingentProperties != null) && (m_contingentProperties.m_exceptionsHolder != null) && (m_contingentProperties.m_exceptionsHolder.ContainsFaultList), @@ -1252,7 +1249,7 @@ namespace System.Threading.Tasks } else { - Contract.Assert((m_stateFlags & TASK_STATE_CANCELED) != 0, "Task.RunSynchronously: expected TASK_STATE_CANCELED to be set"); + Debug.Assert((m_stateFlags & TASK_STATE_CANCELED) != 0, "Task.RunSynchronously: expected TASK_STATE_CANCELED to be set"); // Can't call this method on canceled task. ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Task_RunSynchronously_TaskCompleted); } @@ -1403,7 +1400,7 @@ namespace System.Threading.Tasks // Only return an exception in faulted state (skip manufactured exceptions) // A "benevolent" race condition makes it possible to return null when IsFaulted is // true (i.e., if IsFaulted is set just after the check to IsFaulted above). - Contract.Assert((e == null) || IsFaulted, "Task.Exception_get(): returning non-null value when not Faulted"); + Debug.Assert((e == null) || IsFaulted, "Task.Exception_get(): returning non-null value when not Faulted"); return e; } @@ -1884,11 +1881,10 @@ namespace System.Threading.Tasks /// underneath us. If false, TASK_STATE_STARTED bit is OR-ed right in. This /// allows us to streamline things a bit for StartNew(), where competing cancellations /// are not a problem. - [SecuritySafeCritical] // Needed for QueueTask internal void ScheduleAndStart(bool needsProtection) { - Contract.Assert(m_taskScheduler != null, "expected a task scheduler to have been selected"); - Contract.Assert((m_stateFlags & TASK_STATE_STARTED) == 0, "task has already started"); + Debug.Assert(m_taskScheduler != null, "expected a task scheduler to have been selected"); + Debug.Assert((m_stateFlags & TASK_STATE_STARTED) == 0, "task has already started"); // Set the TASK_STATE_STARTED bit if (needsProtection) @@ -1912,7 +1908,7 @@ namespace System.Threading.Tasks if (AsyncCausalityTracer.LoggingOn && (Options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) == 0) { //For all other task than TaskContinuations we want to log. TaskContinuations log in their constructor - AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Id, "Task: "+((Delegate)m_action).Method.Name, 0); + AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Id, "Task: " + m_action.Method.Name, 0); } @@ -1942,7 +1938,7 @@ namespace System.Threading.Tasks if ((Options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) == 0) { // m_contingentProperties.m_exceptionsHolder *should* already exist after AddException() - Contract.Assert( + Debug.Assert( (m_contingentProperties != null) && (m_contingentProperties.m_exceptionsHolder != null) && (m_contingentProperties.m_exceptionsHolder.ContainsFaultList), @@ -1981,13 +1977,13 @@ namespace System.Threading.Tasks var eoAsEdi = exceptionObject as ExceptionDispatchInfo; var eoAsEnumerableEdi = exceptionObject as IEnumerable; - Contract.Assert( + Debug.Assert( eoAsException != null || eoAsEnumerableException != null || eoAsEdi != null || eoAsEnumerableEdi != null, "Task.AddException: Expected an Exception, ExceptionDispatchInfo, or an IEnumerable<> of one of those"); var eoAsOce = exceptionObject as OperationCanceledException; - Contract.Assert( + Debug.Assert( !representsCancellation || eoAsOce != null || (eoAsEdi != null && eoAsEdi.SourceException is OperationCanceledException), @@ -2078,7 +2074,7 @@ namespace System.Threading.Tasks { // There are exceptions; get the aggregate and optionally add the canceled // exception to the aggregate (if applicable). - Contract.Assert(m_contingentProperties != null); // ExceptionRecorded ==> m_contingentProperties != null + Debug.Assert(m_contingentProperties != null); // ExceptionRecorded ==> m_contingentProperties != null // No need to lock around this, as other logic prevents the consumption of exceptions // before they have been completely processed. @@ -2097,7 +2093,7 @@ namespace System.Threading.Tasks internal ReadOnlyCollection GetExceptionDispatchInfos() { bool exceptionsAvailable = IsFaulted && ExceptionRecorded; - Contract.Assert(exceptionsAvailable, "Must only be used when the task has faulted with exceptions."); + Debug.Assert(exceptionsAvailable, "Must only be used when the task has faulted with exceptions."); return exceptionsAvailable ? m_contingentProperties.m_exceptionsHolder.GetExceptionDispatchInfos() : new ReadOnlyCollection(new ExceptionDispatchInfo[0]); @@ -2107,7 +2103,7 @@ namespace System.Threading.Tasks /// The ExceptionDispatchInfo. May be null if no OCE was stored for the task. internal ExceptionDispatchInfo GetCancellationExceptionDispatchInfo() { - Contract.Assert(IsCanceled, "Must only be used when the task has canceled."); + Debug.Assert(IsCanceled, "Must only be used when the task has canceled."); return Volatile.Read(ref m_contingentProperties)?.m_exceptionsHolder?.GetCancellationExceptionDispatchInfo(); // may be null } @@ -2344,7 +2340,7 @@ namespace System.Threading.Tasks Contract.Requires(childTask != null); Contract.Requires(childTask.IsCompleted, "ProcessChildCompletion was called for an uncompleted task"); - Contract.Assert(childTask.m_contingentProperties?.m_parent == this, "ProcessChildCompletion should only be called for a child of this task"); + Debug.Assert(childTask.m_contingentProperties?.m_parent == this, "ProcessChildCompletion should only be called for a child of this task"); var props = Volatile.Read(ref m_contingentProperties); @@ -2404,11 +2400,11 @@ namespace System.Threading.Tasks { // Ensure any exceptions thrown by children are added to the parent. // In doing this, we are implicitly marking children as being "handled". - Contract.Assert(task.IsCompleted, "Expected all tasks in list to be completed"); + Debug.Assert(task.IsCompleted, "Expected all tasks in list to be completed"); if (task.IsFaulted && !task.IsExceptionObservedByParent) { TaskExceptionHolder exceptionHolder = Volatile.Read(ref task.m_contingentProperties).m_exceptionsHolder; - Contract.Assert(exceptionHolder != null); + Debug.Assert(exceptionHolder != null); // No locking necessary since child task is finished adding exceptions // and concurrent CreateExceptionObject() calls do not constitute @@ -2435,7 +2431,7 @@ namespace System.Threading.Tasks /// Whether the delegate was executed. internal void FinishThreadAbortedTask(bool bTAEAddedToExceptionHolder, bool delegateRan) { - Contract.Assert(!bTAEAddedToExceptionHolder || m_contingentProperties?.m_exceptionsHolder != null, + Debug.Assert(!bTAEAddedToExceptionHolder || m_contingentProperties?.m_exceptionsHolder != null, "FinishThreadAbortedTask() called on a task whose exception holder wasn't initialized"); // this will only be false for non-root self replicating task copies, because all of their exceptions go to the root task. @@ -2671,7 +2667,6 @@ namespace System.Threading.Tasks /// IThreadPoolWorkItem override, which is the entry function for this task when the TP scheduler decides to run it. /// /// - [SecurityCritical] void IThreadPoolWorkItem.ExecuteWorkItem() { ExecuteEntry(false); @@ -2681,7 +2676,6 @@ namespace System.Threading.Tasks /// The ThreadPool calls this if a ThreadAbortException is thrown while trying to execute this workitem. This may occur /// before Task would otherwise be able to observe it. /// - [SecurityCritical] void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae) { // If the task has marked itself as Completed, then it either a) already observed this exception (so we shouldn't handle it here) @@ -2700,7 +2694,6 @@ namespace System.Threading.Tasks /// /// Performs atomic updates to prevent double execution. Should only be set to true /// in codepaths servicing user provided TaskSchedulers. The ConcRT or ThreadPool schedulers don't need this. - [SecuritySafeCritical] internal bool ExecuteEntry(bool bPreventDoubleExecution) { if (bPreventDoubleExecution || ((Options & (TaskCreationOptions)InternalTaskOptions.SelfReplicating) != 0)) @@ -2742,7 +2735,6 @@ namespace System.Threading.Tasks } // A trick so we can refer to the TLS slot with a byref. - [SecurityCritical] private void ExecuteWithThreadLocal(ref Task currentTaskSlot) { // Remember the current task so we can restore it after running, and then @@ -2819,14 +2811,12 @@ namespace System.Threading.Tasks } // Cached callback delegate that's lazily initialized due to ContextCallback being SecurityCritical - [SecurityCritical] private static ContextCallback s_ecCallback; - [SecurityCritical] private static void ExecutionContextCallback(object obj) { Task task = obj as Task; - Contract.Assert(task != null, "expected a task object"); + Debug.Assert(task != null, "expected a task object"); task.Execute(); } @@ -2837,7 +2827,7 @@ namespace System.Threading.Tasks internal virtual void InnerInvoke() { // Invoke the delegate - Contract.Assert(m_action != null, "Null action in InnerInvoke()"); + Debug.Assert(m_action != null, "Null action in InnerInvoke()"); var action = m_action as Action; if (action != null) { @@ -2850,7 +2840,7 @@ namespace System.Threading.Tasks actionWithState(m_stateObject); return; } - Contract.Assert(false, "Invalid m_action in Task"); + Debug.Assert(false, "Invalid m_action in Task"); } /// @@ -2929,7 +2919,6 @@ namespace System.Threading.Tasks /// Whether to flow ExecutionContext across the await. /// A stack crawl mark tied to execution context. /// The awaiter was not properly initialized. - [SecurityCritical] internal void SetContinuationForAwait( Action continuationAction, bool continueOnCapturedContext, bool flowExecutionContext, ref StackCrawlMark stackMark) { @@ -2986,7 +2975,7 @@ namespace System.Threading.Tasks } else { - Contract.Assert(!flowExecutionContext, "We already determined we're not required to flow context."); + Debug.Assert(!flowExecutionContext, "We already determined we're not required to flow context."); if (!AddTaskContinuation(continuationAction, addBeforeOthers: false)) AwaitTaskContinuation.UnsafeScheduleAction(continuationAction, this); } @@ -3019,7 +3008,7 @@ namespace System.Threading.Tasks Wait(Timeout.Infinite, default(CancellationToken)); #if DEBUG - Contract.Assert(waitResult, "expected wait to succeed"); + Debug.Assert(waitResult, "expected wait to succeed"); #endif } @@ -3154,7 +3143,7 @@ namespace System.Threading.Tasks ThrowIfExceptional(true); } - Contract.Assert((m_stateFlags & TASK_STATE_FAULTED) == 0, "Task.Wait() completing when in Faulted state."); + Debug.Assert((m_stateFlags & TASK_STATE_FAULTED) == 0, "Task.Wait() completing when in Faulted state."); return true; } @@ -3230,7 +3219,7 @@ namespace System.Threading.Tasks } } - Contract.Assert(IsCompleted || millisecondsTimeout != Timeout.Infinite); + Debug.Assert(IsCompleted || millisecondsTimeout != Timeout.Infinite); // ETW event for Task Wait End if (etwIsEnabled) @@ -3358,7 +3347,6 @@ namespace System.Threading.Tasks /// For custom schedulers we also attempt an atomic state transition. /// /// true if the task was successfully canceled; otherwise, false. - [SecuritySafeCritical] internal bool InternalCancel(bool bCancelNonExecutingOnly) { Contract.Requires((Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) == 0, "Task.InternalCancel() did not expect promise-style task"); @@ -3426,7 +3414,7 @@ namespace System.Threading.Tasks if (bPopSucceeded) { // hitting this would mean something wrong with the AtomicStateUpdate above - Contract.Assert(!mustCleanup, "Possibly an invalid state transition call was made in InternalCancel()"); + Debug.Assert(!mustCleanup, "Possibly an invalid state transition call was made in InternalCancel()"); // Include TASK_STATE_DELEGATE_INVOKED in "illegal" bits to protect against the situation where // TS.TryDequeue() returns true but the task is still left on the queue. @@ -3466,8 +3454,8 @@ namespace System.Threading.Tasks { RecordInternalCancellationRequest(); - Contract.Assert((Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0, "Task.RecordInternalCancellationRequest(CancellationToken) only valid for promise-style task"); - Contract.Assert(m_contingentProperties.m_cancellationToken == default(CancellationToken)); + Debug.Assert((Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0, "Task.RecordInternalCancellationRequest(CancellationToken) only valid for promise-style task"); + Debug.Assert(m_contingentProperties.m_cancellationToken == default(CancellationToken)); // Store the supplied cancellation token as this task's token. // Waiting on this task will then result in an OperationCanceledException containing this token. @@ -3492,11 +3480,11 @@ namespace System.Threading.Tasks if (oce == null) { var edi = cancellationException as ExceptionDispatchInfo; - Contract.Assert(edi != null, "Expected either an OCE or an EDI"); + Debug.Assert(edi != null, "Expected either an OCE or an EDI"); oce = edi.SourceException as OperationCanceledException; - Contract.Assert(oce != null, "Expected EDI to contain an OCE"); + Debug.Assert(oce != null, "Expected EDI to contain an OCE"); } - Contract.Assert(oce.CancellationToken == tokenToRecord, + Debug.Assert(oce.CancellationToken == tokenToRecord, "Expected OCE's token to match the provided token."); #endif AddException(cancellationException, representsCancellation: true); @@ -3507,10 +3495,10 @@ namespace System.Threading.Tasks // And this method should be called at most once per task. internal void CancellationCleanupLogic() { - Contract.Assert((m_stateFlags & (TASK_STATE_CANCELED | TASK_STATE_COMPLETION_RESERVED)) != 0, "Task.CancellationCleanupLogic(): Task not canceled or reserved."); + Debug.Assert((m_stateFlags & (TASK_STATE_CANCELED | TASK_STATE_COMPLETION_RESERVED)) != 0, "Task.CancellationCleanupLogic(): Task not canceled or reserved."); // I'd like to do this, but there is a small window for a race condition. If someone calls Wait() between InternalCancel() and // here, that will set m_completionEvent, leading to a meaningless/harmless assertion. - //Contract.Assert((m_completionEvent == null) || !m_completionEvent.IsSet, "Task.CancellationCleanupLogic(): Completion event already set."); + //Debug.Assert((m_completionEvent == null) || !m_completionEvent.IsSet, "Task.CancellationCleanupLogic(): Completion event already set."); // This may have been set already, but we need to make sure. Interlocked.Exchange(ref m_stateFlags, m_stateFlags | TASK_STATE_CANCELED); @@ -3541,8 +3529,8 @@ namespace System.Threading.Tasks /// private void SetCancellationAcknowledged() { - Contract.Assert(this == Task.InternalCurrent, "SetCancellationAcknowledged() should only be called while this is still the current task"); - Contract.Assert(IsCancellationRequested, "SetCancellationAcknowledged() should not be called if the task's CT wasn't signaled"); + Debug.Assert(this == Task.InternalCurrent, "SetCancellationAcknowledged() should only be called while this is still the current task"); + Debug.Assert(IsCancellationRequested, "SetCancellationAcknowledged() should not be called if the task's CT wasn't signaled"); m_stateFlags |= TASK_STATE_CANCELLATIONACKNOWLEDGED; } @@ -3558,7 +3546,6 @@ namespace System.Threading.Tasks /// /// Runs all of the continuations, as appropriate. /// - [SecuritySafeCritical] // for AwaitTaskContinuation.RunOrScheduleAction internal void FinishContinuations() { // Atomically store the fact that this task is completing. From this point on, the adding of continuations will @@ -3684,7 +3671,7 @@ namespace System.Threading.Tasks // Otherwise, it must be an ITaskCompletionAction, so invoke it. else { - Contract.Assert(currentContinuation is ITaskCompletionAction, "Expected continuation element to be Action, TaskContinuation, or ITaskContinuationAction"); + Debug.Assert(currentContinuation is ITaskCompletionAction, "Expected continuation element to be Action, TaskContinuation, or ITaskContinuationAction"); var action = (ITaskCompletionAction)currentContinuation; if (bCanInlineContinuations || !action.InvokeMayRunArbitraryCode) @@ -4730,7 +4717,7 @@ namespace System.Threading.Tasks // m_continuationObject is guaranteed at this point to be either a List or // s_taskCompletionSentinel. List list = m_continuationObject as List; - Contract.Assert((list != null) || (m_continuationObject == s_taskCompletionSentinel), + Debug.Assert((list != null) || (m_continuationObject == s_taskCompletionSentinel), "Expected m_continuationObject to be list or sentinel"); // If list is null, it can only mean that s_taskCompletionSentinel has been exchanged @@ -4873,7 +4860,7 @@ namespace System.Threading.Tasks WaitAll(tasks, Timeout.Infinite); #if DEBUG - Contract.Assert(waitResult, "expected wait to succeed"); + Debug.Assert(waitResult, "expected wait to succeed"); #endif } @@ -5134,7 +5121,7 @@ namespace System.Threading.Tasks // Now gather up and throw all of the exceptions. foreach (var task in tasks) AddExceptionsForCompletedTask(ref exceptions, task); - Contract.Assert(exceptions != null, "Should have seen at least one exception"); + Debug.Assert(exceptions != null, "Should have seen at least one exception"); ThrowHelper.ThrowAggregateException(exceptions); } @@ -5159,8 +5146,8 @@ namespace System.Threading.Tasks /// true if all of the tasks completed; otherwise, false. private static bool WaitAllBlockingCore(List tasks, int millisecondsTimeout, CancellationToken cancellationToken) { - Contract.Assert(tasks != null, "Expected a non-null list of tasks"); - Contract.Assert(tasks.Count > 0, "Expected at least one task"); + Debug.Assert(tasks != null, "Expected a non-null list of tasks"); + Debug.Assert(tasks.Count > 0, "Expected at least one task"); bool waitCompleted = false; var mres = new SetOnCountdownMres(tasks.Count); @@ -5206,14 +5193,14 @@ namespace System.Threading.Tasks internal SetOnCountdownMres(int count) { - Contract.Assert(count > 0, "Expected count > 0"); + Debug.Assert(count > 0, "Expected count > 0"); _count = count; } public void Invoke(Task completingTask) { if (Interlocked.Decrement(ref _count) == 0) Set(); - Contract.Assert(_count >= 0, "Count should never go below 0"); + Debug.Assert(_count >= 0, "Count should never go below 0"); } public bool InvokeMayRunArbitraryCode { get { return false; } } @@ -5304,7 +5291,7 @@ namespace System.Threading.Tasks public static int WaitAny(params Task[] tasks) { int waitResult = WaitAny(tasks, Timeout.Infinite); - Contract.Assert(tasks.Length == 0 || waitResult != -1, "expected wait to succeed"); + Debug.Assert(tasks.Length == 0 || waitResult != -1, "expected wait to succeed"); return waitResult; } @@ -5475,9 +5462,9 @@ namespace System.Threading.Tasks bool waitCompleted = firstCompleted.Wait(millisecondsTimeout, cancellationToken); if (waitCompleted) { - Contract.Assert(firstCompleted.Status == TaskStatus.RanToCompletion); + Debug.Assert(firstCompleted.Status == TaskStatus.RanToCompletion); signaledTaskIndex = Array.IndexOf(tasks, firstCompleted.Result); - Contract.Assert(signaledTaskIndex >= 0); + Debug.Assert(signaledTaskIndex >= 0); } } @@ -5521,7 +5508,7 @@ namespace System.Threading.Tasks var task = new Task(); bool succeeded = task.TrySetException(exception); - Contract.Assert(succeeded, "This should always succeed on a new task."); + Debug.Assert(succeeded, "This should always succeed on a new task."); return task; } @@ -5559,7 +5546,7 @@ namespace System.Threading.Tasks var task = new Task(); bool succeeded = task.TrySetCanceled(exception.CancellationToken, exception); - Contract.Assert(succeeded, "This should always succeed on a new task."); + Debug.Assert(succeeded, "This should always succeed on a new task."); return task; } @@ -6124,7 +6111,7 @@ namespace System.Threading.Tasks for (int i = 0; i < m_tasks.Length; i++) { var task = m_tasks[i]; - Contract.Assert(task != null, "Constituent task in WhenAll should never be null"); + Debug.Assert(task != null, "Constituent task in WhenAll should never be null"); if (task.IsFaulted) { @@ -6144,7 +6131,7 @@ namespace System.Threading.Tasks if (observedExceptions != null) { - Contract.Assert(observedExceptions.Count > 0, "Expected at least one exception"); + Debug.Assert(observedExceptions.Count > 0, "Expected at least one exception"); //We don't need to TraceOperationCompleted here because TrySetException will call Finish and we'll log it there @@ -6166,7 +6153,7 @@ namespace System.Threading.Tasks TrySetResult(default(VoidTaskResult)); } } - Contract.Assert(m_count >= 0, "Count should never go below 0"); + Debug.Assert(m_count >= 0, "Count should never go below 0"); } public bool InvokeMayRunArbitraryCode { get { return true; } } @@ -6371,7 +6358,7 @@ namespace System.Threading.Tasks for (int i = 0; i < m_tasks.Length; i++) { Task task = m_tasks[i]; - Contract.Assert(task != null, "Constituent task in WhenAll should never be null"); + Debug.Assert(task != null, "Constituent task in WhenAll should never be null"); if (task.IsFaulted) { @@ -6384,7 +6371,7 @@ namespace System.Threading.Tasks } else { - Contract.Assert(task.Status == TaskStatus.RanToCompletion); + Debug.Assert(task.Status == TaskStatus.RanToCompletion); results[i] = task.GetResultCore(waitCompletionNotification: false); // avoid Result, which would triggering debug notification } @@ -6396,7 +6383,7 @@ namespace System.Threading.Tasks if (observedExceptions != null) { - Contract.Assert(observedExceptions.Count > 0, "Expected at least one exception"); + Debug.Assert(observedExceptions.Count > 0, "Expected at least one exception"); //We don't need to TraceOperationCompleted here because TrySetException will call Finish and we'll log it there @@ -6418,7 +6405,7 @@ namespace System.Threading.Tasks TrySetResult(results); } } - Contract.Assert(m_count >= 0, "Count should never go below 0"); + Debug.Assert(m_count >= 0, "Count should never go below 0"); } public bool InvokeMayRunArbitraryCode { get { return true; } } @@ -6612,7 +6599,7 @@ namespace System.Threading.Tasks Task continuationTask = continuationObject as Task; if (continuationTask != null) { - Contract.Assert(continuationTask.m_action == null); + Debug.Assert(continuationTask.m_action == null); Delegate[] delegates = continuationTask.GetDelegateContinuationsForDebugger(); if (delegates != null) return delegates; @@ -6677,13 +6664,11 @@ namespace System.Threading.Tasks m_completingTask = completingTask; } - [SecurityCritical] void IThreadPoolWorkItem.ExecuteWorkItem() { m_action.Invoke(m_completingTask); } - [SecurityCritical] void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae) { /* NOP */ @@ -6999,25 +6984,12 @@ namespace System.Threading.Tasks // that can SO in 20 inlines on a typical 1MB stack size probably needs to be revisited anyway. private const int MAX_UNCHECKED_INLINING_DEPTH = 20; -#if !FEATURE_CORECLR - - private UInt64 m_lastKnownWatermark; - private static int s_pageSize; - - // We are conservative here. We assume that the platform needs a whole 64KB to - // respond to stack overflow. This means that for very small stacks (e.g. 128KB) - // we'll fail a lot of stack checks incorrectly. - private const long STACK_RESERVED_SPACE = 4096 * 16; - -#endif // !FEATURE_CORECLR - /// /// This method needs to be called before attempting inline execution on the current thread. /// If false is returned, it means we are too close to the end of the stack and should give up inlining. /// Each call to TryBeginInliningScope() that returns true must be matched with a /// call to EndInliningScope() regardless of whether inlining actually took place. /// - [SecuritySafeCritical] internal bool TryBeginInliningScope() { // If we're still under the 'safe' limit we'll just skip the stack probe to save p/invoke calls @@ -7037,59 +7009,15 @@ namespace System.Threading.Tasks internal void EndInliningScope() { m_inliningDepth--; - Contract.Assert(m_inliningDepth >= 0, "Inlining depth count should never go negative."); + Debug.Assert(m_inliningDepth >= 0, "Inlining depth count should never go negative."); // do the right thing just in case... if (m_inliningDepth < 0) m_inliningDepth = 0; } - [SecurityCritical] private unsafe bool CheckForSufficientStack() { -#if FEATURE_CORECLR return RuntimeHelpers.TryEnsureSufficientExecutionStack(); -#else - // see if we already have the system page size info recorded - int pageSize = s_pageSize; - if (pageSize == 0) - { - // If not we need to query it from GetSystemInfo() - // Note that this happens only once for the process lifetime - Win32Native.SYSTEM_INFO sysInfo = new Win32Native.SYSTEM_INFO(); - Win32Native.GetSystemInfo(ref sysInfo); - - s_pageSize = pageSize = sysInfo.dwPageSize; - } - - Win32Native.MEMORY_BASIC_INFORMATION stackInfo = new Win32Native.MEMORY_BASIC_INFORMATION(); - - // We subtract one page for our request. VirtualQuery rounds UP to the next page. - // Unfortunately, the stack grows down. If we're on the first page (last page in the - // VirtualAlloc), we'll be moved to the next page, which is off the stack! - - UIntPtr currentAddr = new UIntPtr(&stackInfo - pageSize); - UInt64 current64 = currentAddr.ToUInt64(); - - // Check whether we previously recorded a deeper stack than where we currently are, - // If so we don't need to do the P/Invoke to VirtualQuery - if (m_lastKnownWatermark != 0 && current64 > m_lastKnownWatermark) - return true; - - // Actual stack probe. P/Invoke to query for the current stack allocation information. - Win32Native.VirtualQuery(currentAddr.ToPointer(), ref stackInfo, (UIntPtr)(sizeof(Win32Native.MEMORY_BASIC_INFORMATION))); - - // If the current address minus the base (remember: the stack grows downward in the - // address space) is greater than the number of bytes requested plus the reserved - // space at the end, the request has succeeded. - - if ((current64 - ((UIntPtr)stackInfo.AllocationBase).ToUInt64()) > STACK_RESERVED_SPACE) - { - m_lastKnownWatermark = current64; - return true; - } - - return false; -#endif } } @@ -7204,16 +7132,15 @@ namespace System.Threading.Tasks case STATE_WAITING_ON_INNER_TASK: bool result = TrySetFromTask(completingTask, lookForOce: false); _state = STATE_DONE; // bump the state - Contract.Assert(result, "Expected TrySetFromTask from inner task to succeed"); + Debug.Assert(result, "Expected TrySetFromTask from inner task to succeed"); break; default: - Contract.Assert(false, "UnwrapPromise in illegal state"); + Debug.Assert(false, "UnwrapPromise in illegal state"); break; } } // Calls InvokeCore asynchronously. - [SecuritySafeCritical] private void InvokeCoreAsync(Task completingTask) { // Queue a call to Invoke. If we're so deep on the stack that we're at risk of overflowing, @@ -7233,7 +7160,7 @@ namespace System.Threading.Tasks private void ProcessCompletedOuterTask(Task task) { Contract.Requires(task != null && task.IsCompleted, "Expected non-null, completed outer task"); - Contract.Assert(_state == STATE_WAITING_ON_OUTER_TASK, "We're in the wrong state!"); + Debug.Assert(_state == STATE_WAITING_ON_OUTER_TASK, "We're in the wrong state!"); // Bump our state before proceeding any further _state = STATE_WAITING_ON_INNER_TASK; @@ -7245,7 +7172,7 @@ namespace System.Threading.Tasks case TaskStatus.Canceled: case TaskStatus.Faulted: bool result = TrySetFromTask(task, _lookForOce); - Contract.Assert(result, "Expected TrySetFromTask from outer task to succeed"); + Debug.Assert(result, "Expected TrySetFromTask from outer task to succeed"); break; // Otherwise, process the inner task it returned. diff --git a/src/mscorlib/src/System/Threading/Tasks/TaskCompletionSource.cs b/src/mscorlib/src/System/Threading/Tasks/TaskCompletionSource.cs index 8b1dd2a..320f704 100644 --- a/src/mscorlib/src/System/Threading/Tasks/TaskCompletionSource.cs +++ b/src/mscorlib/src/System/Threading/Tasks/TaskCompletionSource.cs @@ -12,6 +12,7 @@ // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- using System; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Collections.Generic; using System.Runtime.CompilerServices; @@ -47,7 +48,6 @@ namespace System.Threading.Tasks /// /// The type of the result value assocatied with this . - [HostProtection(Synchronization = true, ExternalThreading = true)] public class TaskCompletionSource { private readonly Task m_task; @@ -209,9 +209,9 @@ namespace System.Threading.Tasks /// Unlike the public methods, this method doesn't currently validate that its arguments are correct. internal bool TrySetException(IEnumerable exceptions) { - Contract.Assert(exceptions != null); + Debug.Assert(exceptions != null); #if DEBUG - foreach(var edi in exceptions) Contract.Assert(edi != null, "Contents must be non-null"); + foreach(var edi in exceptions) Debug.Assert(edi != null, "Contents must be non-null"); #endif bool rval = m_task.TrySetException(exceptions); diff --git a/src/mscorlib/src/System/Threading/Tasks/TaskContinuation.cs b/src/mscorlib/src/System/Threading/Tasks/TaskContinuation.cs index 4c035df..70b9418d 100644 --- a/src/mscorlib/src/System/Threading/Tasks/TaskContinuation.cs +++ b/src/mscorlib/src/System/Threading/Tasks/TaskContinuation.cs @@ -11,6 +11,7 @@ // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- using System.Security; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.ExceptionServices; using System.Runtime.CompilerServices; @@ -45,7 +46,7 @@ namespace System.Threading.Tasks // Get and null out the antecedent. This is crucial to avoid a memory // leak with long chains of continuations. var antecedent = m_antecedent; - Contract.Assert(antecedent != null, + Debug.Assert(antecedent != null, "No antecedent was set for the ContinuationTaskFromTask."); m_antecedent = null; @@ -53,7 +54,7 @@ namespace System.Threading.Tasks antecedent.NotifyDebuggerOfWaitCompletionIfNecessary(); // Invoke the delegate - Contract.Assert(m_action != null); + Debug.Assert(m_action != null); var action = m_action as Action; if (action != null) { @@ -66,7 +67,7 @@ namespace System.Threading.Tasks actionWithState(antecedent, m_stateObject); return; } - Contract.Assert(false, "Invalid m_action in ContinuationTaskFromTask"); + Debug.Assert(false, "Invalid m_action in ContinuationTaskFromTask"); } } @@ -93,7 +94,7 @@ namespace System.Threading.Tasks // Get and null out the antecedent. This is crucial to avoid a memory // leak with long chains of continuations. var antecedent = m_antecedent; - Contract.Assert(antecedent != null, + Debug.Assert(antecedent != null, "No antecedent was set for the ContinuationResultTaskFromTask."); m_antecedent = null; @@ -101,7 +102,7 @@ namespace System.Threading.Tasks antecedent.NotifyDebuggerOfWaitCompletionIfNecessary(); // Invoke the delegate - Contract.Assert(m_action != null); + Debug.Assert(m_action != null); var func = m_action as Func; if (func != null) { @@ -114,7 +115,7 @@ namespace System.Threading.Tasks m_result = funcWithState(antecedent, m_stateObject); return; } - Contract.Assert(false, "Invalid m_action in ContinuationResultTaskFromTask"); + Debug.Assert(false, "Invalid m_action in ContinuationResultTaskFromTask"); } } @@ -141,7 +142,7 @@ namespace System.Threading.Tasks // Get and null out the antecedent. This is crucial to avoid a memory // leak with long chains of continuations. var antecedent = m_antecedent; - Contract.Assert(antecedent != null, + Debug.Assert(antecedent != null, "No antecedent was set for the ContinuationTaskFromResultTask."); m_antecedent = null; @@ -149,7 +150,7 @@ namespace System.Threading.Tasks antecedent.NotifyDebuggerOfWaitCompletionIfNecessary(); // Invoke the delegate - Contract.Assert(m_action != null); + Debug.Assert(m_action != null); var action = m_action as Action>; if (action != null) { @@ -162,7 +163,7 @@ namespace System.Threading.Tasks actionWithState(antecedent, m_stateObject); return; } - Contract.Assert(false, "Invalid m_action in ContinuationTaskFromResultTask"); + Debug.Assert(false, "Invalid m_action in ContinuationTaskFromResultTask"); } } @@ -189,7 +190,7 @@ namespace System.Threading.Tasks // Get and null out the antecedent. This is crucial to avoid a memory // leak with long chains of continuations. var antecedent = m_antecedent; - Contract.Assert(antecedent != null, + Debug.Assert(antecedent != null, "No antecedent was set for the ContinuationResultTaskFromResultTask."); m_antecedent = null; @@ -197,7 +198,7 @@ namespace System.Threading.Tasks antecedent.NotifyDebuggerOfWaitCompletionIfNecessary(); // Invoke the delegate - Contract.Assert(m_action != null); + Debug.Assert(m_action != null); var func = m_action as Func, TResult>; if (func != null) { @@ -210,7 +211,7 @@ namespace System.Threading.Tasks m_result = funcWithState(antecedent, m_stateObject); return; } - Contract.Assert(false, "Invalid m_action in ContinuationResultTaskFromResultTask"); + Debug.Assert(false, "Invalid m_action in ContinuationResultTaskFromResultTask"); } } @@ -235,11 +236,10 @@ namespace System.Threading.Tasks /// /// true if we need to protect against multiple threads racing to start/cancel the task; otherwise, false. /// - [SecuritySafeCritical] protected static void InlineIfPossibleOrElseQueue(Task task, bool needsProtection) { Contract.Requires(task != null); - Contract.Assert(task.m_taskScheduler != null); + Debug.Assert(task.m_taskScheduler != null); // Set the TASK_STATE_STARTED flag. This only needs to be done // if the task may be canceled or if someone else has a reference to it @@ -305,7 +305,7 @@ namespace System.Threading.Tasks m_options = options; m_taskScheduler = scheduler; if (AsyncCausalityTracer.LoggingOn) - AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, m_task.Id, "Task.ContinueWith: " + ((Delegate)task.m_action).Method.Name, 0); + AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, m_task.Id, "Task.ContinueWith: " + task.m_action.Method.Name, 0); if (Task.s_asyncDebuggingEnabled) { @@ -318,8 +318,8 @@ namespace System.Threading.Tasks /// Whether the continuation can be inlined. internal override void Run(Task completedTask, bool bCanInlineContinuationTask) { - Contract.Assert(completedTask != null); - Contract.Assert(completedTask.IsCompleted, "ContinuationTask.Run(): completedTask not completed"); + Debug.Assert(completedTask != null); + Debug.Assert(completedTask.IsCompleted, "ContinuationTask.Run(): completedTask not completed"); // Check if the completion status of the task works with the desired // activation criteria of the TaskContinuationOptions. @@ -374,7 +374,7 @@ namespace System.Threading.Tasks return m_task.GetDelegateContinuationsForDebugger(); } - return new Delegate[] { m_task.m_action as Delegate }; + return new Delegate[] { m_task.m_action }; } } @@ -384,7 +384,6 @@ namespace System.Threading.Tasks /// SendOrPostCallback delegate to invoke the action. private readonly static SendOrPostCallback s_postCallback = state => ((Action)state)(); // can't use InvokeAction as it's SecurityCritical /// Cached delegate for PostAction - [SecurityCritical] private static ContextCallback s_postActionCallback; /// The context with which to run the action. private readonly SynchronizationContext m_syncContext; @@ -394,19 +393,17 @@ namespace System.Threading.Tasks /// The action to invoke. Must not be null. /// Whether to capture and restore ExecutionContext. /// The captured stack mark. - [SecurityCritical] internal SynchronizationContextAwaitTaskContinuation( SynchronizationContext context, Action action, bool flowExecutionContext, ref StackCrawlMark stackMark) : base(action, flowExecutionContext, ref stackMark) { - Contract.Assert(context != null); + Debug.Assert(context != null); m_syncContext = context; } /// Inlines or schedules the continuation. /// The antecedent task, which is ignored. /// true if inlining is permitted; otherwise, false. - [SecuritySafeCritical] internal sealed override void Run(Task task, bool canInlineContinuationTask) { // If we're allowed to inline, run the action on this thread. @@ -431,7 +428,6 @@ namespace System.Threading.Tasks /// Calls InvokeOrPostAction(false) on the supplied SynchronizationContextAwaitTaskContinuation. /// The SynchronizationContextAwaitTaskContinuation. - [SecurityCritical] private static void PostAction(object state) { var c = (SynchronizationContextAwaitTaskContinuation)state; @@ -465,7 +461,6 @@ namespace System.Threading.Tasks /// to be passed as state. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - [SecurityCritical] private static ContextCallback GetPostActionCallback() { ContextCallback callback = s_postActionCallback; @@ -485,12 +480,11 @@ namespace System.Threading.Tasks /// The action to invoke. Must not be null. /// Whether to capture and restore ExecutionContext. /// The captured stack mark. - [SecurityCritical] internal TaskSchedulerAwaitTaskContinuation( TaskScheduler scheduler, Action action, bool flowExecutionContext, ref StackCrawlMark stackMark) : base(action, flowExecutionContext, ref stackMark) { - Contract.Assert(scheduler != null); + Debug.Assert(scheduler != null); m_scheduler = scheduler; } @@ -550,7 +544,6 @@ namespace System.Threading.Tasks /// The action to invoke. Must not be null. /// Whether to capture and restore ExecutionContext. /// The captured stack mark with which to construct an ExecutionContext. - [SecurityCritical] internal AwaitTaskContinuation(Action action, bool flowExecutionContext, ref StackCrawlMark stackMark) { Contract.Requires(action != null); @@ -566,7 +559,6 @@ namespace System.Threading.Tasks /// Initializes the continuation. /// The action to invoke. Must not be null. /// Whether to capture and restore ExecutionContext. - [SecurityCritical] internal AwaitTaskContinuation(Action action, bool flowExecutionContext) { Contract.Requires(action != null); @@ -598,7 +590,6 @@ namespace System.Threading.Tasks /// Inlines or schedules the continuation onto the default scheduler. /// The antecedent task, which is ignored. /// true if inlining is permitted; otherwise, false. - [SecuritySafeCritical] internal override void Run(Task task, bool canInlineContinuationTask) { // For the base AwaitTaskContinuation, we allow inlining if our caller allows it @@ -657,7 +648,6 @@ namespace System.Threading.Tasks } /// IThreadPoolWorkItem override, which is the entry function for this when the ThreadPool scheduler decides to run it. - [SecurityCritical] void ExecuteWorkItemHelper() { var etwLog = TplEtwProvider.Log; @@ -696,7 +686,6 @@ namespace System.Threading.Tasks } } - [SecurityCritical] void IThreadPoolWorkItem.ExecuteWorkItem() { // inline the fast path @@ -714,20 +703,16 @@ namespace System.Threading.Tasks /// /// The ThreadPool calls this if a ThreadAbortException is thrown while trying to execute this workitem. /// - [SecurityCritical] void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae) { /* nop */ } /// Cached delegate that invokes an Action passed as an object parameter. - [SecurityCritical] private static ContextCallback s_invokeActionCallback; /// Runs an action provided as an object parameter. /// The Action to invoke. - [SecurityCritical] private static void InvokeAction(object state) { ((Action)state)(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [SecurityCritical] protected static ContextCallback GetInvokeActionCallback() { ContextCallback callback = s_invokeActionCallback; @@ -739,11 +724,10 @@ namespace System.Threading.Tasks /// The callback to run. /// The state to pass to the callback. /// A reference to Task.t_currentTask. - [SecurityCritical] protected void RunCallback(ContextCallback callback, object state, ref Task currentTask) { Contract.Requires(callback != null); - Contract.Assert(currentTask == Task.t_currentTask); + Debug.Assert(currentTask == Task.t_currentTask); // Pretend there's no current task, so that no task is seen as a parent // and TaskScheduler.Current does not reflect false information @@ -787,10 +771,9 @@ namespace System.Threading.Tasks /// only happens in Task.SetContinuationForAwait if execution context flow was disabled /// via using TaskAwaiter.UnsafeOnCompleted or a similar path. /// - [SecurityCritical] internal static void RunOrScheduleAction(Action action, bool allowInlining, ref Task currentTask) { - Contract.Assert(currentTask == Task.t_currentTask); + Debug.Assert(currentTask == Task.t_currentTask); // If we're not allowed to run here, schedule the action if (!allowInlining || !IsValidLocationForInlining) @@ -818,7 +801,6 @@ namespace System.Threading.Tasks /// Schedules the action to be executed. No ExecutionContext work is performed used. /// The action to invoke or queue. - [SecurityCritical] internal static void UnsafeScheduleAction(Action action, Task task) { AwaitTaskContinuation atc = new AwaitTaskContinuation(action, flowExecutionContext: false); @@ -859,7 +841,7 @@ namespace System.Threading.Tasks internal override Delegate[] GetDelegateContinuationsForDebugger() { - Contract.Assert(m_action != null); + Debug.Assert(m_action != null); return new Delegate[] { AsyncMethodBuilderCore.TryGetStateMachineForDebugger(m_action) }; } } diff --git a/src/mscorlib/src/System/Threading/Tasks/TaskExceptionHolder.cs b/src/mscorlib/src/System/Threading/Tasks/TaskExceptionHolder.cs index 198db8e..45817da 100644 --- a/src/mscorlib/src/System/Threading/Tasks/TaskExceptionHolder.cs +++ b/src/mscorlib/src/System/Threading/Tasks/TaskExceptionHolder.cs @@ -18,6 +18,7 @@ namespace System.Threading.Tasks using System; using System.Collections.Generic; using System.Collections.ObjectModel; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.ExceptionServices; using System.Security; @@ -62,14 +63,9 @@ namespace System.Threading.Tasks EnsureADUnloadCallbackRegistered(); } - [SecuritySafeCritical] private static bool ShouldFailFastOnUnobservedException() { - bool shouldFailFast = false; - #if !FEATURE_CORECLR - shouldFailFast = System.CLRConfig.CheckThrowUnobservedTaskExceptions(); - #endif - return shouldFailFast; + return false; } private static void EnsureADUnloadCallbackRegistered() @@ -202,12 +198,12 @@ namespace System.Threading.Tasks { Contract.Requires(exceptionObject != null, "Expected exceptionObject to be non-null."); - Contract.Assert(m_cancellationException == null, + Debug.Assert(m_cancellationException == null, "Expected SetCancellationException to be called only once."); // Breaking this assumption will overwrite a previously OCE, // and implies something may be wrong elsewhere, since there should only ever be one. - Contract.Assert(m_faultExceptions == null, + Debug.Assert(m_faultExceptions == null, "Expected SetCancellationException to be called before any faults were added."); // Breaking this assumption shouldn't hurt anything here, but it implies something may be wrong elsewhere. // If this changes, make sure to only conditionally mark as handled below. @@ -221,7 +217,7 @@ namespace System.Threading.Tasks else { var edi = exceptionObject as ExceptionDispatchInfo; - Contract.Assert(edi != null && edi.SourceException is OperationCanceledException, + Debug.Assert(edi != null && edi.SourceException is OperationCanceledException, "Expected an OCE or an EDI that contained an OCE"); m_cancellationException = edi; } @@ -242,7 +238,7 @@ namespace System.Threading.Tasks // Initialize the exceptions list if necessary. The list should be non-null iff it contains exceptions. var exceptions = m_faultExceptions; if (exceptions == null) m_faultExceptions = exceptions = new List(1); - else Contract.Assert(exceptions.Count > 0, "Expected existing exceptions list to have > 0 exceptions."); + else Debug.Assert(exceptions.Count > 0, "Expected existing exceptions list to have > 0 exceptions."); // Handle Exception by capturing it into an ExceptionDispatchInfo and storing that var exception = exceptionObject as Exception; @@ -270,13 +266,13 @@ namespace System.Threading.Tasks foreach (var exc in exColl) { #if DEBUG - Contract.Assert(exc != null, "No exceptions should be null"); + Debug.Assert(exc != null, "No exceptions should be null"); numExceptions++; #endif exceptions.Add(ExceptionDispatchInfo.Capture(exc)); } #if DEBUG - Contract.Assert(numExceptions > 0, "Collection should contain at least one exception."); + Debug.Assert(numExceptions > 0, "Collection should contain at least one exception."); #endif } else @@ -287,17 +283,17 @@ namespace System.Threading.Tasks { exceptions.AddRange(ediColl); #if DEBUG - Contract.Assert(exceptions.Count > 0, "There should be at least one dispatch info."); + Debug.Assert(exceptions.Count > 0, "There should be at least one dispatch info."); foreach(var tmp in exceptions) { - Contract.Assert(tmp != null, "No dispatch infos should be null"); + Debug.Assert(tmp != null, "No dispatch infos should be null"); } #endif } // Anything else is a programming error else { - throw new ArgumentException(Environment.GetResourceString("TaskExceptionHolder_UnknownExceptionType"), "exceptionObject"); + throw new ArgumentException(Environment.GetResourceString("TaskExceptionHolder_UnknownExceptionType"), nameof(exceptionObject)); } } } @@ -370,8 +366,8 @@ namespace System.Threading.Tasks internal AggregateException CreateExceptionObject(bool calledFromFinalizer, Exception includeThisException) { var exceptions = m_faultExceptions; - Contract.Assert(exceptions != null, "Expected an initialized list."); - Contract.Assert(exceptions.Count > 0, "Expected at least one exception."); + Debug.Assert(exceptions != null, "Expected an initialized list."); + Debug.Assert(exceptions.Count > 0, "Expected at least one exception."); // Mark as handled and aggregate the exceptions. MarkAsHandled(calledFromFinalizer); @@ -400,8 +396,8 @@ namespace System.Threading.Tasks internal ReadOnlyCollection GetExceptionDispatchInfos() { var exceptions = m_faultExceptions; - Contract.Assert(exceptions != null, "Expected an initialized list."); - Contract.Assert(exceptions.Count > 0, "Expected at least one exception."); + Debug.Assert(exceptions != null, "Expected an initialized list."); + Debug.Assert(exceptions.Count > 0, "Expected at least one exception."); MarkAsHandled(false); return new ReadOnlyCollection(exceptions); } @@ -416,7 +412,7 @@ namespace System.Threading.Tasks internal ExceptionDispatchInfo GetCancellationExceptionDispatchInfo() { var edi = m_cancellationException; - Contract.Assert(edi == null || edi.SourceException is OperationCanceledException, + Debug.Assert(edi == null || edi.SourceException is OperationCanceledException, "Expected the EDI to be for an OperationCanceledException"); return edi; } diff --git a/src/mscorlib/src/System/Threading/Tasks/TaskFactory.cs b/src/mscorlib/src/System/Threading/Tasks/TaskFactory.cs index 52b4716..aa4c2df 100644 --- a/src/mscorlib/src/System/Threading/Tasks/TaskFactory.cs +++ b/src/mscorlib/src/System/Threading/Tasks/TaskFactory.cs @@ -18,6 +18,7 @@ using System.Security; using System.Security.Permissions; using System.Runtime.CompilerServices; using System.Threading; +using System.Diagnostics; using System.Diagnostics.Contracts; namespace System.Threading.Tasks @@ -37,7 +38,6 @@ namespace System.Threading.Tasks /// Task.Factory property. /// /// - [HostProtection(Synchronization = true, ExternalThreading = true)] public class TaskFactory { // member variables @@ -225,7 +225,7 @@ namespace System.Threading.Tasks TaskCreationOptions.PreferFairness | TaskCreationOptions.RunContinuationsAsynchronously)) != 0) { - throw new ArgumentOutOfRangeException("creationOptions"); + throw new ArgumentOutOfRangeException(nameof(creationOptions)); } Contract.EndContractBlock(); } @@ -1593,9 +1593,9 @@ namespace System.Threading.Tasks { // Options detected here cause exceptions in FromAsync methods that take beginMethod as a parameter if ((creationOptions & TaskCreationOptions.LongRunning) != 0) - throw new ArgumentOutOfRangeException("creationOptions", Environment.GetResourceString("Task_FromAsync_LongRunning")); + throw new ArgumentOutOfRangeException(nameof(creationOptions), Environment.GetResourceString("Task_FromAsync_LongRunning")); if ((creationOptions & TaskCreationOptions.PreferFairness) != 0) - throw new ArgumentOutOfRangeException("creationOptions", Environment.GetResourceString("Task_FromAsync_PreferFairness")); + throw new ArgumentOutOfRangeException(nameof(creationOptions), Environment.GetResourceString("Task_FromAsync_PreferFairness")); } // Check for general validity of options @@ -1606,7 +1606,7 @@ namespace System.Threading.Tasks TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning)) != 0) { - throw new ArgumentOutOfRangeException("creationOptions"); + throw new ArgumentOutOfRangeException(nameof(creationOptions)); } } @@ -1666,7 +1666,7 @@ namespace System.Threading.Tasks TrySetResult(_tasks); } - Contract.Assert(_count >= 0, "Count should never go below 0"); + Debug.Assert(_count >= 0, "Count should never go below 0"); } public bool InvokeMayRunArbitraryCode { get { return true; } } @@ -1746,7 +1746,7 @@ namespace System.Threading.Tasks TrySetResult(_tasks); } - Contract.Assert(_count >= 0, "Count should never go below 0"); + Debug.Assert(_count >= 0, "Count should never go below 0"); } public bool InvokeMayRunArbitraryCode { get { return true; } } @@ -1801,7 +1801,7 @@ namespace System.Threading.Tasks [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable public Task ContinueWhenAll(Task[] tasks, Action continuationAction) { - if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -1833,7 +1833,7 @@ namespace System.Threading.Tasks [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable public Task ContinueWhenAll(Task[] tasks, Action continuationAction, CancellationToken cancellationToken) { - if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -1870,7 +1870,7 @@ namespace System.Threading.Tasks [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable public Task ContinueWhenAll(Task[] tasks, Action continuationAction, TaskContinuationOptions continuationOptions) { - if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -1918,7 +1918,7 @@ namespace System.Threading.Tasks public Task ContinueWhenAll(Task[] tasks, Action continuationAction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { - if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -1945,7 +1945,7 @@ namespace System.Threading.Tasks [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable public Task ContinueWhenAll(Task[] tasks, Action[]> continuationAction) { - if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -1979,7 +1979,7 @@ namespace System.Threading.Tasks public Task ContinueWhenAll(Task[] tasks, Action[]> continuationAction, CancellationToken cancellationToken) { - if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2018,7 +2018,7 @@ namespace System.Threading.Tasks public Task ContinueWhenAll(Task[] tasks, Action[]> continuationAction, TaskContinuationOptions continuationOptions) { - if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2067,7 +2067,7 @@ namespace System.Threading.Tasks public Task ContinueWhenAll(Task[] tasks, Action[]> continuationAction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { - if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2097,7 +2097,7 @@ namespace System.Threading.Tasks [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable public Task ContinueWhenAll(Task[] tasks, Func continuationFunction) { - if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2133,7 +2133,7 @@ namespace System.Threading.Tasks [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable public Task ContinueWhenAll(Task[] tasks, Func continuationFunction, CancellationToken cancellationToken) { - if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2174,7 +2174,7 @@ namespace System.Threading.Tasks [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable public Task ContinueWhenAll(Task[] tasks, Func continuationFunction, TaskContinuationOptions continuationOptions) { - if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2226,7 +2226,7 @@ namespace System.Threading.Tasks public Task ContinueWhenAll(Task[] tasks, Func continuationFunction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { - if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2258,7 +2258,7 @@ namespace System.Threading.Tasks [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable public Task ContinueWhenAll(Task[] tasks, Func[], TResult> continuationFunction) { - if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2295,7 +2295,7 @@ namespace System.Threading.Tasks public Task ContinueWhenAll(Task[] tasks, Func[], TResult> continuationFunction, CancellationToken cancellationToken) { - if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2338,7 +2338,7 @@ namespace System.Threading.Tasks public Task ContinueWhenAll(Task[] tasks, Func[], TResult> continuationFunction, TaskContinuationOptions continuationOptions) { - if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2391,7 +2391,7 @@ namespace System.Threading.Tasks public Task ContinueWhenAll(Task[] tasks, Func[], TResult> continuationFunction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { - if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2448,7 +2448,7 @@ namespace System.Threading.Tasks } bool success = TrySetResult(completingTask); - Contract.Assert(success, "Only one task should have gotten to this point, and thus this must be successful."); + Debug.Assert(success, "Only one task should have gotten to this point, and thus this must be successful."); // We need to remove continuations that may be left straggling on other tasks. // Otherwise, repeated calls to WhenAny using the same task could leak actions. @@ -2489,7 +2489,7 @@ namespace System.Threading.Tasks for(int i=0; i continuationAction) { - if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2562,7 +2562,7 @@ namespace System.Threading.Tasks [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable public Task ContinueWhenAny(Task[] tasks, Action continuationAction, CancellationToken cancellationToken) { - if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2599,7 +2599,7 @@ namespace System.Threading.Tasks [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable public Task ContinueWhenAny(Task[] tasks, Action continuationAction, TaskContinuationOptions continuationOptions) { - if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2647,7 +2647,7 @@ namespace System.Threading.Tasks public Task ContinueWhenAny(Task[] tasks, Action continuationAction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { - if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2678,7 +2678,7 @@ namespace System.Threading.Tasks [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable public Task ContinueWhenAny(Task[] tasks, Func continuationFunction) { - if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2713,7 +2713,7 @@ namespace System.Threading.Tasks [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable public Task ContinueWhenAny(Task[] tasks, Func continuationFunction, CancellationToken cancellationToken) { - if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2754,7 +2754,7 @@ namespace System.Threading.Tasks [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable public Task ContinueWhenAny(Task[] tasks, Func continuationFunction, TaskContinuationOptions continuationOptions) { - if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2806,7 +2806,7 @@ namespace System.Threading.Tasks public Task ContinueWhenAny(Task[] tasks, Func continuationFunction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { - if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2838,7 +2838,7 @@ namespace System.Threading.Tasks public Task ContinueWhenAny(Task[] tasks, Func, TResult> continuationFunction) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction)); return TaskFactory.ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark); } @@ -2872,7 +2872,7 @@ namespace System.Threading.Tasks public Task ContinueWhenAny(Task[] tasks, Func, TResult> continuationFunction, CancellationToken cancellationToken) { - if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2915,7 +2915,7 @@ namespace System.Threading.Tasks public Task ContinueWhenAny(Task[] tasks, Func, TResult> continuationFunction, TaskContinuationOptions continuationOptions) { - if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2968,7 +2968,7 @@ namespace System.Threading.Tasks public Task ContinueWhenAny(Task[] tasks, Func, TResult> continuationFunction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { - if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -2996,7 +2996,7 @@ namespace System.Threading.Tasks [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable public Task ContinueWhenAny(Task[] tasks, Action> continuationAction) { - if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -3029,7 +3029,7 @@ namespace System.Threading.Tasks public Task ContinueWhenAny(Task[] tasks, Action> continuationAction, CancellationToken cancellationToken) { - if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -3068,7 +3068,7 @@ namespace System.Threading.Tasks public Task ContinueWhenAny(Task[] tasks, Action> continuationAction, TaskContinuationOptions continuationOptions) { - if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -3117,7 +3117,7 @@ namespace System.Threading.Tasks public Task ContinueWhenAny(Task[] tasks, Action> continuationAction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { - if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction)); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -3129,9 +3129,9 @@ namespace System.Threading.Tasks internal static Task[] CheckMultiContinuationTasksAndCopy(Task[] tasks) { if (tasks == null) - throw new ArgumentNullException("tasks"); + throw new ArgumentNullException(nameof(tasks)); if (tasks.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_EmptyTaskList"), "tasks"); + throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_EmptyTaskList"), nameof(tasks)); Contract.EndContractBlock(); Task[] tasksCopy = new Task[tasks.Length]; @@ -3140,7 +3140,7 @@ namespace System.Threading.Tasks tasksCopy[i] = tasks[i]; if (tasksCopy[i] == null) - throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_NullTask"), "tasks"); + throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_NullTask"), nameof(tasks)); } return tasksCopy; @@ -3149,9 +3149,9 @@ namespace System.Threading.Tasks internal static Task[] CheckMultiContinuationTasksAndCopy(Task[] tasks) { if (tasks == null) - throw new ArgumentNullException("tasks"); + throw new ArgumentNullException(nameof(tasks)); if (tasks.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_EmptyTaskList"), "tasks"); + throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_EmptyTaskList"), nameof(tasks)); Contract.EndContractBlock(); Task[] tasksCopy = new Task[tasks.Length]; @@ -3160,7 +3160,7 @@ namespace System.Threading.Tasks tasksCopy[i] = tasks[i]; if (tasksCopy[i] == null) - throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_NullTask"), "tasks"); + throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_NullTask"), nameof(tasks)); } return tasksCopy; @@ -3179,7 +3179,7 @@ namespace System.Threading.Tasks const TaskContinuationOptions illegalMask = TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.LongRunning; if ((continuationOptions & illegalMask) == illegalMask) { - throw new ArgumentOutOfRangeException("continuationOptions", Environment.GetResourceString("Task_ContinueWith_ESandLR")); + throw new ArgumentOutOfRangeException(nameof(continuationOptions), Environment.GetResourceString("Task_ContinueWith_ESandLR")); } // Check that no nonsensical options are specified. @@ -3193,12 +3193,12 @@ namespace System.Threading.Tasks NotOnAny | TaskContinuationOptions.ExecuteSynchronously)) != 0) { - throw new ArgumentOutOfRangeException("continuationOptions"); + throw new ArgumentOutOfRangeException(nameof(continuationOptions)); } // Check that no "fire" options are specified. if ((continuationOptions & NotOnAny) != 0) - throw new ArgumentOutOfRangeException("continuationOptions", Environment.GetResourceString("Task_MultiTaskContinuation_FireOptions")); + throw new ArgumentOutOfRangeException(nameof(continuationOptions), Environment.GetResourceString("Task_MultiTaskContinuation_FireOptions")); Contract.EndContractBlock(); } } diff --git a/src/mscorlib/src/System/Threading/Tasks/TaskScheduler.cs b/src/mscorlib/src/System/Threading/Tasks/TaskScheduler.cs index f824924..fad3fc0 100644 --- a/src/mscorlib/src/System/Threading/Tasks/TaskScheduler.cs +++ b/src/mscorlib/src/System/Threading/Tasks/TaskScheduler.cs @@ -41,10 +41,6 @@ namespace System.Threading.Tasks /// [DebuggerDisplay("Id={Id}")] [DebuggerTypeProxy(typeof(SystemThreadingTasks_TaskSchedulerDebugView))] - [HostProtection(Synchronization = true, ExternalThreading = true)] -#pragma warning disable 618 - [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)] -#pragma warning restore 618 public abstract class TaskScheduler { //////////////////////////////////////////////////////////// @@ -70,7 +66,6 @@ namespace System.Threading.Tasks /// /// The Task to be queued. /// The argument is null. - [SecurityCritical] protected internal abstract void QueueTask(Task task); /// @@ -113,7 +108,6 @@ namespace System.Threading.Tasks /// null. /// The was already /// executed. - [SecurityCritical] protected abstract bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued); /// @@ -157,7 +151,6 @@ namespace System.Threading.Tasks /// /// This scheduler is unable to generate a list of queued tasks at this time. /// - [SecurityCritical] protected abstract IEnumerable GetScheduledTasks(); /// @@ -185,7 +178,6 @@ namespace System.Threading.Tasks /// True if the task may have been previously queued, /// false if the task was absolutely not previously queued. /// True if it ran, false otherwise. - [SecuritySafeCritical] internal bool TryRunInline(Task task, bool taskWasPreviouslyQueued) { // Do not inline unstarted tasks (i.e., task.ExecutingTaskScheduler == null). @@ -237,7 +229,6 @@ namespace System.Threading.Tasks /// The Task to be dequeued. /// A Boolean denoting whether the argument was successfully dequeued. /// The argument is null. - [SecurityCritical] protected internal virtual bool TryDequeue(Task task) { return false; @@ -262,7 +253,6 @@ namespace System.Threading.Tasks /// /// Calls QueueTask() after performing any needed firing of events /// - [SecurityCritical] internal void InternalQueueTask(Task task) { Contract.Requires(task != null); @@ -444,7 +434,6 @@ namespace System.Threading.Tasks /// A Boolean that is true if was successfully executed, false if it /// was not. A common reason for execution failure is that the task had previously been executed or /// is in the process of being executed by another thread. - [SecurityCritical] protected bool TryExecuteTask(Task task) { if (task.ExecutingTaskScheduler != this) @@ -475,7 +464,6 @@ namespace System.Threading.Tasks /// public static event EventHandler UnobservedTaskException { - [System.Security.SecurityCritical] add { if (value != null) @@ -485,7 +473,6 @@ namespace System.Threading.Tasks } } - [System.Security.SecurityCritical] remove { lock (_unobservedTaskExceptionLockObject) _unobservedTaskException -= value; @@ -531,7 +518,6 @@ namespace System.Threading.Tasks /// /// This scheduler is unable to generate a list of queued tasks at this time. /// - [SecurityCritical] internal Task[] GetScheduledTasksForDebugger() { // this can throw InvalidOperationException indicating that they are unable to provide the info @@ -566,7 +552,6 @@ namespace System.Threading.Tasks /// It should not be called by any other codepaths. /// /// An array of TaskScheduler instances. - [SecurityCritical] internal static TaskScheduler[] GetTaskSchedulersForDebugger() { if (s_activeTaskSchedulers == null) @@ -587,7 +572,7 @@ namespace System.Threading.Tasks schedulers.CopyTo(arr, 0); foreach (var scheduler in arr) { - Contract.Assert(scheduler != null, "Table returned an incorrect Count or CopyTo failed"); + Debug.Assert(scheduler != null, "Table returned an incorrect Count or CopyTo failed"); int tmp = scheduler.Id; // force Ids for debugger } return arr; @@ -613,7 +598,6 @@ namespace System.Threading.Tasks // returns the scheduler’s GetScheduledTasks public IEnumerable ScheduledTasks { - [SecurityCritical] get { return m_taskScheduler.GetScheduledTasks(); } } } @@ -656,7 +640,6 @@ namespace System.Threading.Tasks /// Simply posts the tasks to be executed on the associated . /// /// - [SecurityCritical] protected internal override void QueueTask(Task task) { m_synchronizationContext.Post(s_postCallback, (object)task); @@ -670,7 +653,6 @@ namespace System.Threading.Tasks /// /// /// - [SecurityCritical] protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) { if (SynchronizationContext.Current == m_synchronizationContext) @@ -682,7 +664,6 @@ namespace System.Threading.Tasks } // not implemented - [SecurityCritical] protected override IEnumerable GetScheduledTasks() { return null; diff --git a/src/mscorlib/src/System/Threading/Tasks/TaskToApm.cs b/src/mscorlib/src/System/Threading/Tasks/TaskToApm.cs index 02b130c..90743ae 100644 --- a/src/mscorlib/src/System/Threading/Tasks/TaskToApm.cs +++ b/src/mscorlib/src/System/Threading/Tasks/TaskToApm.cs @@ -22,6 +22,7 @@ // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- using System.IO; +using System.Diagnostics; using System.Diagnostics.Contracts; namespace System.Threading.Tasks @@ -76,7 +77,7 @@ namespace System.Threading.Tasks if (twar != null) { task = twar.Task; - Contract.Assert(task != null, "TaskWrapperAsyncResult should never wrap a null Task."); + Debug.Assert(task != null, "TaskWrapperAsyncResult should never wrap a null Task."); } // Otherwise, the IAsyncResult should be a Task. else @@ -101,7 +102,7 @@ namespace System.Threading.Tasks if (twar != null) { task = twar.Task as Task; - Contract.Assert(twar.Task != null, "TaskWrapperAsyncResult should never wrap a null Task."); + Debug.Assert(twar.Task != null, "TaskWrapperAsyncResult should never wrap a null Task."); } // Otherwise, the IAsyncResult should be a Task. else diff --git a/src/mscorlib/src/System/Threading/Tasks/ThreadPoolTaskScheduler.cs b/src/mscorlib/src/System/Threading/Tasks/ThreadPoolTaskScheduler.cs index dd4cbc9..5c6ca9b 100644 --- a/src/mscorlib/src/System/Threading/Tasks/ThreadPoolTaskScheduler.cs +++ b/src/mscorlib/src/System/Threading/Tasks/ThreadPoolTaskScheduler.cs @@ -13,6 +13,7 @@ using System; using System.Security; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Collections.Generic; using System.Text; @@ -39,7 +40,7 @@ namespace System.Threading.Tasks { Contract.Requires(obj != null, "TaskScheduler.LongRunningThreadWork: obj is null"); Task t = obj as Task; - Contract.Assert(t != null, "TaskScheduler.LongRunningThreadWork: t is null"); + Debug.Assert(t != null, "TaskScheduler.LongRunningThreadWork: t is null"); t.ExecuteEntry(false); } @@ -47,7 +48,6 @@ namespace System.Threading.Tasks /// Schedules a task to the ThreadPool. /// /// The task to schedule. - [SecurityCritical] protected internal override void QueueTask(Task task) { if ((task.Options & TaskCreationOptions.LongRunning) != 0) @@ -73,7 +73,6 @@ namespace System.Threading.Tasks /// IMPORTANT NOTE: TryExecuteTaskInline will NOT throw task exceptions itself. Any wait code path using this function needs /// to account for exceptions that need to be propagated, and throw themselves accordingly. /// - [SecurityCritical] protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) { // If the task was previously scheduled, and we can't pop it, then return false. @@ -95,14 +94,12 @@ namespace System.Threading.Tasks return rval; } - [SecurityCritical] protected internal override bool TryDequeue(Task task) { // just delegate to TP return ThreadPool.TryPopCustomWorkItem(task); } - [SecurityCritical] protected override IEnumerable GetScheduledTasks() { return FilterTasksFromWorkItems(ThreadPool.GetQueuedWorkItems()); diff --git a/src/mscorlib/src/System/Threading/Tasks/future.cs b/src/mscorlib/src/System/Threading/Tasks/future.cs index 39e6ca1..0c3fec8 100644 --- a/src/mscorlib/src/System/Threading/Tasks/future.cs +++ b/src/mscorlib/src/System/Threading/Tasks/future.cs @@ -65,7 +65,6 @@ namespace System.Threading.Tasks /// and may be used from multiple threads concurrently. /// /// - [HostProtection(Synchronization = true, ExternalThreading = true)] [DebuggerTypeProxy(typeof(SystemThreadingTasks_FutureDebugView<>))] [DebuggerDisplay("Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription}, Result = {DebuggerDisplayResultDescription}")] public class Task : Task @@ -447,7 +446,7 @@ namespace System.Threading.Tasks { get { - Delegate d = (Delegate)m_action; + Delegate d = m_action; return d != null ? d.Method.ToString() : "{null}"; } } @@ -457,7 +456,7 @@ namespace System.Threading.Tasks internal bool TrySetResult(TResult result) { if (IsCompleted) return false; - Contract.Assert(m_action == null, "Task.TrySetResult(): non-null m_action"); + Debug.Assert(m_action == null, "Task.TrySetResult(): non-null m_action"); // "Reserve" the completion for this task, while making sure that: (1) No prior reservation // has been made, (2) The result has not already been set, (3) An exception has not previously @@ -497,7 +496,7 @@ namespace System.Threading.Tasks // the task, avoiding expensive completion paths, before the task is actually given to anyone. internal void DangerousSetResult(TResult result) { - Contract.Assert(!IsCompleted, "The promise must not yet be completed."); + Debug.Assert(!IsCompleted, "The promise must not yet be completed."); // If we have a parent, we need to notify it of the completion. Take the slow path to handle that. if (m_contingentProperties?.m_parent != null) @@ -505,7 +504,7 @@ namespace System.Threading.Tasks bool success = TrySetResult(result); // Nobody else has had a chance to complete this Task yet, so we should succeed. - Contract.Assert(success); + Debug.Assert(success); } else { @@ -539,7 +538,7 @@ namespace System.Threading.Tasks { get { - Contract.Assert(!IsWaitNotificationEnabledOrNotRanToCompletion, + Debug.Assert(!IsWaitNotificationEnabledOrNotRanToCompletion, "Should only be used when the task completed successfully and there's no wait notification enabled"); return m_result; } @@ -558,7 +557,7 @@ namespace System.Threading.Tasks if (!IsRanToCompletion) ThrowIfExceptional(includeTaskCanceledExceptions: true); // We shouldn't be here if the result has not been set. - Contract.Assert(IsRanToCompletion, "Task.Result getter: Expected result to have been set."); + Debug.Assert(IsRanToCompletion, "Task.Result getter: Expected result to have been set."); return m_result; } @@ -572,13 +571,13 @@ namespace System.Threading.Tasks // Called from TaskCompletionSource.SetException(IEnumerable). internal bool TrySetException(object exceptionObject) { - Contract.Assert(m_action == null, "Task.TrySetException(): non-null m_action"); + Debug.Assert(m_action == null, "Task.TrySetException(): non-null m_action"); // TCS.{Try}SetException() should have checked for this - Contract.Assert(exceptionObject != null, "Expected non-null exceptionObject argument"); + Debug.Assert(exceptionObject != null, "Expected non-null exceptionObject argument"); // Only accept these types. - Contract.Assert( + Debug.Assert( (exceptionObject is Exception) || (exceptionObject is IEnumerable) || (exceptionObject is ExceptionDispatchInfo) || (exceptionObject is IEnumerable), "Expected exceptionObject to be either Exception, ExceptionDispatchInfo, or IEnumerable<> of one of those"); @@ -620,10 +619,10 @@ namespace System.Threading.Tasks // This method is only valid for promise tasks. internal bool TrySetCanceled(CancellationToken tokenToRecord, object cancellationException) { - Contract.Assert(m_action == null, "Task.TrySetCanceled(): non-null m_action"); + Debug.Assert(m_action == null, "Task.TrySetCanceled(): non-null m_action"); #if DEBUG var ceAsEdi = cancellationException as ExceptionDispatchInfo; - Contract.Assert( + Debug.Assert( cancellationException == null || cancellationException is OperationCanceledException || (ceAsEdi != null && ceAsEdi.SourceException is OperationCanceledException), @@ -669,7 +668,7 @@ namespace System.Threading.Tasks internal override void InnerInvoke() { // Invoke the delegate - Contract.Assert(m_action != null); + Debug.Assert(m_action != null); var func = m_action as Func; if (func != null) { @@ -682,7 +681,7 @@ namespace System.Threading.Tasks m_result = funcWithState(m_stateObject); return; } - Contract.Assert(false, "Invalid m_action in Task"); + Debug.Assert(false, "Invalid m_action in Task"); } #region Await Support diff --git a/src/mscorlib/src/System/Threading/Thread.cs b/src/mscorlib/src/System/Threading/Thread.cs index e62cfae..8294c20 100644 --- a/src/mscorlib/src/System/Threading/Thread.cs +++ b/src/mscorlib/src/System/Threading/Thread.cs @@ -12,16 +12,13 @@ ** =============================================================================*/ +using Internal.Runtime.Augments; + namespace System.Threading { using System.Threading; using System.Runtime; using System.Runtime.InteropServices; -#if FEATURE_REMOTING - using System.Runtime.Remoting.Contexts; - using System.Runtime.Remoting.Messaging; -#endif using System; - using System.Diagnostics; using System.Security.Permissions; using System.Security.Principal; using System.Globalization; @@ -31,13 +28,13 @@ namespace System.Threading { using System.Runtime.ConstrainedExecution; using System.Security; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; internal delegate Object InternalCrossContextDelegate(Object[] args); internal class ThreadHelper { - [System.Security.SecuritySafeCritical] static ThreadHelper() {} Delegate _start; @@ -53,10 +50,8 @@ namespace System.Threading { _executionContext = ec; } - [System.Security.SecurityCritical] static internal ContextCallback _ccb = new ContextCallback(ThreadStart_Context); - [System.Security.SecurityCritical] static private void ThreadStart_Context(Object state) { ThreadHelper t = (ThreadHelper)state; @@ -71,11 +66,6 @@ namespace System.Threading { } // call back helper - #if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // auto-generated - #else - [System.Security.SecurityCritical] - #endif internal void ThreadStart(object obj) { _startArg = obj; @@ -90,11 +80,6 @@ namespace System.Threading { } // call back helper - #if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // auto-generated - #else - [System.Security.SecurityCritical] - #endif internal void ThreadStart() { if (_executionContext != null) @@ -121,25 +106,20 @@ namespace System.Threading { // deliberately not [serializable] [ClassInterface(ClassInterfaceType.None)] [ComDefaultInterface(typeof(_Thread))] -[System.Runtime.InteropServices.ComVisible(true)] - public sealed class Thread : CriticalFinalizerObject, _Thread + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class Thread : RuntimeThread, _Thread { /*========================================================================= ** Data accessed from managed code that needs to be defined in ** ThreadBaseObject to maintain alignment between the two classes. ** DON'T CHANGE THESE UNLESS YOU MODIFY ThreadBaseObject in vm\object.h =========================================================================*/ -#if FEATURE_REMOTING - private Context m_Context; -#endif private ExecutionContext m_ExecutionContext; // this call context follows the logical thread -#if FEATURE_CORECLR private SynchronizationContext m_SynchronizationContext; // On CoreCLR, this is maintained separately from ExecutionContext -#endif private String m_Name; private Delegate m_Delegate; // Delegate - + #if FEATURE_LEAK_CULTURE_INFO private CultureInfo m_CurrentCulture; private CultureInfo m_CurrentUICulture; @@ -212,11 +192,8 @@ namespace System.Threading { #endif // FEATURE_LEAK_CULTURE_INFO } -#if FEATURE_CORECLR // Adding an empty default ctor for annotation purposes - [System.Security.SecuritySafeCritical] // auto-generated internal Thread(){} -#endif // FEATURE_CORECLR /*========================================================================= ** Creates a new Thread object which will begin execution at @@ -224,41 +201,37 @@ namespace System.Threading { ** ** Exceptions: ArgumentNullException if start == null. =========================================================================*/ - [System.Security.SecuritySafeCritical] // auto-generated public Thread(ThreadStart start) { if (start == null) { - throw new ArgumentNullException("start"); + throw new ArgumentNullException(nameof(start)); } Contract.EndContractBlock(); SetStartHelper((Delegate)start,0); //0 will setup Thread with default stackSize } - [System.Security.SecuritySafeCritical] // auto-generated public Thread(ThreadStart start, int maxStackSize) { if (start == null) { - throw new ArgumentNullException("start"); + throw new ArgumentNullException(nameof(start)); } if (0 > maxStackSize) - throw new ArgumentOutOfRangeException("maxStackSize",Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(maxStackSize),Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); SetStartHelper((Delegate)start, maxStackSize); } - [System.Security.SecuritySafeCritical] // auto-generated public Thread(ParameterizedThreadStart start) { if (start == null) { - throw new ArgumentNullException("start"); + throw new ArgumentNullException(nameof(start)); } Contract.EndContractBlock(); SetStartHelper((Delegate)start, 0); } - [System.Security.SecuritySafeCritical] // auto-generated public Thread(ParameterizedThreadStart start, int maxStackSize) { if (start == null) { - throw new ArgumentNullException("start"); + throw new ArgumentNullException(nameof(start)); } if (0 > maxStackSize) - throw new ArgumentOutOfRangeException("maxStackSize",Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(maxStackSize),Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.EndContractBlock(); SetStartHelper((Delegate)start, maxStackSize); } @@ -269,11 +242,10 @@ namespace System.Threading { return m_ManagedThreadId; } - extern public int ManagedThreadId + extern public new int ManagedThreadId { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [MethodImplAttribute(MethodImplOptions.InternalCall)] - [System.Security.SecuritySafeCritical] // auto-generated get; } @@ -299,17 +271,15 @@ namespace System.Threading { ** ** Exceptions: ThreadStateException if the thread has already been started. =========================================================================*/ - [HostProtection(Synchronization=true,ExternalThreading=true)] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - public void Start() + public new void Start() { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; Start(ref stackMark); } - [HostProtection(Synchronization=true,ExternalThreading=true)] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - public void Start(object parameter) + public new void Start(object parameter) { //In the case of a null delegate (second call to start on same thread) // StartInternal method will take care of the error reporting @@ -325,7 +295,6 @@ namespace System.Threading { Start(ref stackMark); } - [System.Security.SecuritySafeCritical] private void Start(ref StackCrawlMark stackMark) { #if FEATURE_COMINTEROP_APARTMENT_SUPPORT @@ -346,16 +315,11 @@ namespace System.Threading { ExecutionContext.CaptureOptions.IgnoreSyncCtx); t.SetExecutionContextHelper(ec); } -#if FEATURE_IMPERSONATION - IPrincipal principal = (IPrincipal)CallContext.Principal; -#else + IPrincipal principal = null; -#endif StartInternal(principal, ref stackMark); } - -#if FEATURE_CORECLR internal ExecutionContext ExecutionContext { get { return m_ExecutionContext; } @@ -366,89 +330,12 @@ namespace System.Threading { { get { return m_SynchronizationContext; } set { m_SynchronizationContext = value; } - } -#else // !FEATURE_CORECLR - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - internal ExecutionContext.Reader GetExecutionContextReader() - { - return new ExecutionContext.Reader(m_ExecutionContext); - } - - internal bool ExecutionContextBelongsToCurrentScope - { - get { return !m_ExecutionContextBelongsToOuterScope; } - set { m_ExecutionContextBelongsToOuterScope = !value; } - } - -#if DEBUG - internal bool ForbidExecutionContextMutation - { - set { m_ForbidExecutionContextMutation = value; } - } -#endif - - // note: please don't access this directly from mscorlib. Use GetMutableExecutionContext or GetExecutionContextReader instead. - public ExecutionContext ExecutionContext - { - [SecuritySafeCritical] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - get - { - ExecutionContext result; - if (this == Thread.CurrentThread) - result = GetMutableExecutionContext(); - else - result = m_ExecutionContext; - - return result; - } } - [SecurityCritical] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - internal ExecutionContext GetMutableExecutionContext() - { - Contract.Assert(Thread.CurrentThread == this); -#if DEBUG - Contract.Assert(!m_ForbidExecutionContextMutation); -#endif - if (m_ExecutionContext == null) - { - m_ExecutionContext = new ExecutionContext(); - } - else if (!ExecutionContextBelongsToCurrentScope) - { - ExecutionContext copy = m_ExecutionContext.CreateMutableCopy(); - m_ExecutionContext = copy; - } - - ExecutionContextBelongsToCurrentScope = true; - return m_ExecutionContext; - } - - [SecurityCritical] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - internal void SetExecutionContext(ExecutionContext value, bool belongsToCurrentScope) - { - m_ExecutionContext = value; - ExecutionContextBelongsToCurrentScope = belongsToCurrentScope; - } - - [SecurityCritical] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - internal void SetExecutionContext(ExecutionContext.Reader value, bool belongsToCurrentScope) - { - m_ExecutionContext = value.DangerousGetRawExecutionContext(); - ExecutionContextBelongsToCurrentScope = belongsToCurrentScope; - } -#endif //!FEATURE_CORECLR - - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern void StartInternal(IPrincipal principal, ref StackCrawlMark stackMark); #if FEATURE_COMPRESSEDSTACK /// - [System.Security.SecurityCritical] // auto-generated_required [DynamicSecurityMethodAttribute()] [Obsolete("Thread.SetCompressedStack is no longer supported. Please use the System.Threading.CompressedStack class")] public void SetCompressedStack( CompressedStack stack ) @@ -456,17 +343,14 @@ namespace System.Threading { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ThreadAPIsNotSupported")); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal extern IntPtr SetAppDomainStack( SafeCompressedStackHandle csHandle); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal extern void RestoreAppDomainStack( IntPtr appDomainStack); /// - [System.Security.SecurityCritical] // auto-generated_required [Obsolete("Thread.GetCompressedStack is no longer supported. Please use the System.Threading.CompressedStack class")] public CompressedStack GetCompressedStack() { @@ -478,7 +362,6 @@ namespace System.Threading { // Helper method to get a logical thread ID for StringBuilder (for // correctness) and for FileStream's async code path (for perf, to // avoid creating a Thread instance). - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static IntPtr InternalGetCurrentThread(); @@ -497,34 +380,6 @@ namespace System.Threading { ** If Abort is called twice on the same thread, a DuplicateThreadAbort ** exception is thrown. =========================================================================*/ - -#if !FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread=true)] - public void Abort(Object stateInfo) - { - // If two aborts come at the same time, it is possible that the state info - // gets set by one, and the actual abort gets delivered by another. But this - // is not distinguishable by an application. - // The accessor helper will only set the value if it isn't already set, - // and that particular bit of native code can test much faster than this - // code could, because testing might cause a cross-appdomain marshalling. - AbortReason = stateInfo; - - // Note: we demand ControlThread permission, then call AbortInternal directly - // rather than delegating to the Abort() function below. We do this to ensure - // that only callers with ControlThread are allowed to change the AbortReason - // of the thread. We call AbortInternal directly to avoid demanding the same - // permission twice. - AbortInternal(); - } -#endif - - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif #pragma warning disable 618 [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)] #pragma warning restore 618 @@ -535,152 +390,14 @@ namespace System.Threading { // Internal helper (since we can't place security demands on // ecalls/fcalls). - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern void AbortInternal(); -#if !FEATURE_CORECLR - /*========================================================================= - ** Resets a thread abort. - ** Should be called by trusted code only - =========================================================================*/ - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread=true)] - public static void ResetAbort() - { - Thread thread = Thread.CurrentThread; - if ((thread.ThreadState & ThreadState.AbortRequested) == 0) - throw new ThreadStateException(Environment.GetResourceString("ThreadState_NoAbortRequested")); - thread.ResetAbortNative(); - thread.ClearAbortReason(); - } - - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern void ResetAbortNative(); - - /*========================================================================= - ** Suspends the thread. If the thread is already suspended, this call has - ** no effect. - ** - ** Exceptions: ThreadStateException if the thread has not been started or - ** it is dead. - =========================================================================*/ - [System.Security.SecuritySafeCritical] // auto-generated - [Obsolete("Thread.Suspend has been deprecated. Please use other classes in System.Threading, such as Monitor, Mutex, Event, and Semaphore, to synchronize Threads or protect resources. http://go.microsoft.com/fwlink/?linkid=14202", false)][SecurityPermission(SecurityAction.Demand, ControlThread=true)] - [SecurityPermission(SecurityAction.Demand, ControlThread=true)] - public void Suspend() { SuspendInternal(); } - - // Internal helper (since we can't place security demands on - // ecalls/fcalls). - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern void SuspendInternal(); - - /*========================================================================= - ** Resumes a thread that has been suspended. - ** - ** Exceptions: ThreadStateException if the thread has not been started or - ** it is dead or it isn't in the suspended state. - =========================================================================*/ - [System.Security.SecuritySafeCritical] // auto-generated - [Obsolete("Thread.Resume has been deprecated. Please use other classes in System.Threading, such as Monitor, Mutex, Event, and Semaphore, to synchronize Threads or protect resources. http://go.microsoft.com/fwlink/?linkid=14202", false)] - [SecurityPermission(SecurityAction.Demand, ControlThread=true)] - public void Resume() { ResumeInternal(); } - - // Internal helper (since we can't place security demands on - // ecalls/fcalls). - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern void ResumeInternal(); - - /*========================================================================= - ** Interrupts a thread that is inside a Wait(), Sleep() or Join(). If that - ** thread is not currently blocked in that manner, it will be interrupted - ** when it next begins to block. - =========================================================================*/ - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermission(SecurityAction.Demand, ControlThread=true)] - public void Interrupt() { InterruptInternal(); } - - // Internal helper (since we can't place security demands on - // ecalls/fcalls). - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern void InterruptInternal(); -#endif - - /*========================================================================= - ** Returns the priority of the thread. - ** - ** Exceptions: ThreadStateException if the thread is dead. - =========================================================================*/ - - public ThreadPriority Priority { - [System.Security.SecuritySafeCritical] // auto-generated - get { return (ThreadPriority)GetPriorityNative(); } - [System.Security.SecuritySafeCritical] // auto-generated - [HostProtection(SelfAffectingThreading=true)] - set { SetPriorityNative((int)value); } - } - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern int GetPriorityNative(); - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern void SetPriorityNative(int priority); - - /*========================================================================= - ** Returns true if the thread has been started and is not dead. - =========================================================================*/ - public extern bool IsAlive { - [System.Security.SecuritySafeCritical] // auto-generated - [MethodImpl(MethodImplOptions.InternalCall)] - get; - } - - /*========================================================================= - ** Returns true if the thread is a threadpool thread. - =========================================================================*/ - public extern bool IsThreadPoolThread { - [System.Security.SecuritySafeCritical] // auto-generated - [MethodImpl(MethodImplOptions.InternalCall)] - get; - } - - /*========================================================================= - ** Waits for the thread to die or for timeout milliseconds to elapse. - ** Returns true if the thread died, or false if the wait timed out. If - ** Timeout.Infinite is given as the parameter, no timeout will occur. - ** - ** Exceptions: ArgumentException if timeout < 0. - ** ThreadInterruptedException if the thread is interrupted while waiting. - ** ThreadStateException if the thread has not been started yet. - =========================================================================*/ - [System.Security.SecurityCritical] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern bool JoinInternal(int millisecondsTimeout); - - [System.Security.SecuritySafeCritical] - [HostProtection(Synchronization=true, ExternalThreading=true)] - public void Join() - { - JoinInternal(Timeout.Infinite); - } - - [System.Security.SecuritySafeCritical] - [HostProtection(Synchronization=true, ExternalThreading=true)] - public bool Join(int millisecondsTimeout) - { - return JoinInternal(millisecondsTimeout); - } - - [HostProtection(Synchronization=true, ExternalThreading=true)] public bool Join(TimeSpan timeout) { long tm = (long)timeout.TotalMilliseconds; if (tm < -1 || tm > (long) Int32.MaxValue) - throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(timeout), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); return Join((int)tm); } @@ -693,12 +410,10 @@ namespace System.Threading { ** Exceptions: ArgumentException if timeout < 0. ** ThreadInterruptedException if the thread is interrupted while sleeping. =========================================================================*/ - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void SleepInternal(int millisecondsTimeout); - [System.Security.SecuritySafeCritical] // auto-generated - public static void Sleep(int millisecondsTimeout) + public static new void Sleep(int millisecondsTimeout) { SleepInternal(millisecondsTimeout); // Ensure we don't return to app code when the pause is underway @@ -710,7 +425,7 @@ namespace System.Threading { { long tm = (long)timeout.TotalMilliseconds; if (tm < -1 || tm > (long) Int32.MaxValue) - throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(timeout), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); Sleep((int)tm); } @@ -719,69 +434,41 @@ namespace System.Threading { only take a few machine instructions. Calling this API is preferable to coding a explict busy loop because the hardware can be informed that it is busy waiting. */ - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] - [HostProtection(Synchronization=true,ExternalThreading=true)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] private static extern void SpinWaitInternal(int iterations); - [System.Security.SecuritySafeCritical] // auto-generated - [HostProtection(Synchronization=true,ExternalThreading=true)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - public static void SpinWait(int iterations) + public static new void SpinWait(int iterations) { SpinWaitInternal(iterations); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] - [HostProtection(Synchronization = true, ExternalThreading = true)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] private static extern bool YieldInternal(); - [System.Security.SecuritySafeCritical] // auto-generated - [HostProtection(Synchronization = true, ExternalThreading = true)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - public static bool Yield() + public static new bool Yield() { return YieldInternal(); } - public static Thread CurrentThread { - [System.Security.SecuritySafeCritical] // auto-generated + public static new Thread CurrentThread { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] get { Contract.Ensures(Contract.Result() != null); return GetCurrentThreadNative(); } } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] private static extern Thread GetCurrentThreadNative(); - [System.Security.SecurityCritical] // auto-generated private void SetStartHelper(Delegate start, int maxStackSize) { -#if FEATURE_CORECLR // We only support default stacks in CoreCLR - Contract.Assert(maxStackSize == 0); -#else - // Only fully-trusted code is allowed to create "large" stacks. Partial-trust falls back to - // the default stack size. - ulong defaultStackSize = GetProcessDefaultStackSize(); - if ((ulong)(uint)maxStackSize > defaultStackSize) - { - try - { - SecurityPermission.Demand(PermissionType.FullTrust); - } - catch (SecurityException) - { - maxStackSize = (int)Math.Min(defaultStackSize, (ulong)(uint)int.MaxValue); - } - } -#endif + Debug.Assert(maxStackSize == 0); ThreadHelper threadStartCallBack = new ThreadHelper(start); if(start is ThreadStart) @@ -794,7 +481,6 @@ namespace System.Threading { } } - [SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern ulong GetProcessDefaultStackSize(); @@ -803,14 +489,12 @@ namespace System.Threading { ** PRIVATE Sets the IThreadable interface for the thread. Assumes that ** start != null. =========================================================================*/ - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern void SetStart(Delegate start, int maxStackSize); /*========================================================================= ** Clean up the thread when it goes away. =========================================================================*/ - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] ~Thread() { @@ -818,52 +502,10 @@ namespace System.Threading { InternalFinalize(); } - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern void InternalFinalize(); -#if FEATURE_COMINTEROP - [System.Security.SecurityCritical] // auto-generated - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - public extern void DisableComObjectEagerCleanup(); -#endif //FEATURE_COMINTEROP - - /*========================================================================= - ** Return whether or not this thread is a background thread. Background - ** threads do not affect when the Execution Engine shuts down. - ** - ** Exceptions: ThreadStateException if the thread is dead. - =========================================================================*/ - public bool IsBackground { - [System.Security.SecuritySafeCritical] // auto-generated - get { return IsBackgroundNative(); } - [System.Security.SecuritySafeCritical] // auto-generated - [HostProtection(SelfAffectingThreading=true)] - set { SetBackgroundNative(value); } - } - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern bool IsBackgroundNative(); - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern void SetBackgroundNative(bool isBackground); - - - /*========================================================================= - ** Return the thread state as a consistent set of bits. This is more - ** general then IsAlive or IsBackground. - =========================================================================*/ - public ThreadState ThreadState { - [System.Security.SecuritySafeCritical] // auto-generated - get { return (ThreadState)GetThreadStateNative(); } - } - - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern int GetThreadStateNative(); - #if FEATURE_COMINTEROP_APARTMENT_SUPPORT /*========================================================================= ** An unstarted thread can be marked to indicate that it will host a @@ -875,35 +517,17 @@ namespace System.Threading { [Obsolete("The ApartmentState property has been deprecated. Use GetApartmentState, SetApartmentState or TrySetApartmentState instead.", false)] public ApartmentState ApartmentState { - [System.Security.SecuritySafeCritical] // auto-generated get { return (ApartmentState)GetApartmentStateNative(); } - [System.Security.SecuritySafeCritical] // auto-generated - [HostProtection(Synchronization=true, SelfAffectingThreading=true)] set { SetApartmentStateNative((int)value, true); } } - [System.Security.SecuritySafeCritical] // auto-generated - public ApartmentState GetApartmentState() - { - return (ApartmentState)GetApartmentStateNative(); - } - - [System.Security.SecuritySafeCritical] // auto-generated - [HostProtection(Synchronization=true, SelfAffectingThreading=true)] - public bool TrySetApartmentState(ApartmentState state) - { - return SetApartmentStateHelper(state, false); - } - - [System.Security.SecuritySafeCritical] // auto-generated - [HostProtection(Synchronization=true, SelfAffectingThreading=true)] public void SetApartmentState(ApartmentState state) { bool result = SetApartmentStateHelper(state, true); @@ -911,31 +535,6 @@ namespace System.Threading { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ApartmentStateSwitchFailed")); } - [System.Security.SecurityCritical] // auto-generated - private bool SetApartmentStateHelper(ApartmentState state, bool fireMDAOnMismatch) - { - ApartmentState retState = (ApartmentState)SetApartmentStateNative((int)state, fireMDAOnMismatch); - - // Special case where we pass in Unknown and get back MTA. - // Once we CoUninitialize the thread, the OS will still - // report the thread as implicitly in the MTA if any - // other thread in the process is CoInitialized. - if ((state == System.Threading.ApartmentState.Unknown) && (retState == System.Threading.ApartmentState.MTA)) - return true; - - if (retState != state) - return false; - - return true; - } - - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern int GetApartmentStateNative(); - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern int SetApartmentStateNative(int state, bool fireMDAOnMismatch); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern void StartupSetApartmentStateInternal(); #endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT @@ -944,7 +543,6 @@ namespace System.Threading { ** Allocates an un-named data slot. The slot is allocated on ALL the ** threads. =========================================================================*/ - [HostProtection(SharedState=true, ExternalThreading=true)] public static LocalDataStoreSlot AllocateDataSlot() { return LocalDataStoreManager.AllocateDataSlot(); @@ -955,7 +553,6 @@ namespace System.Threading { ** threads. Named data slots are "public" and can be manipulated by ** anyone. =========================================================================*/ - [HostProtection(SharedState=true, ExternalThreading=true)] public static LocalDataStoreSlot AllocateNamedDataSlot(String name) { return LocalDataStoreManager.AllocateNamedDataSlot(name); @@ -966,7 +563,6 @@ namespace System.Threading { ** allocated. Named data slots are "public" and can be manipulated by ** anyone. =========================================================================*/ - [HostProtection(SharedState=true, ExternalThreading=true)] public static LocalDataStoreSlot GetNamedDataSlot(String name) { return LocalDataStoreManager.GetNamedDataSlot(name); @@ -977,7 +573,6 @@ namespace System.Threading { ** threads. Named data slots are "public" and can be manipulated by ** anyone. =========================================================================*/ - [HostProtection(SharedState=true, ExternalThreading=true)] public static void FreeNamedDataSlot(String name) { LocalDataStoreManager.FreeNamedDataSlot(name); @@ -986,7 +581,6 @@ namespace System.Threading { /*========================================================================= ** Retrieves the value from the specified slot on the current thread, for that thread's current domain. =========================================================================*/ - [HostProtection(SharedState=true, ExternalThreading=true)] public static Object GetData(LocalDataStoreSlot slot) { LocalDataStoreHolder dls = s_LocalDataStore; @@ -1003,7 +597,6 @@ namespace System.Threading { /*========================================================================= ** Sets the data in the specified slot on the currently running thread, for that thread's current domain. =========================================================================*/ - [HostProtection(SharedState=true, ExternalThreading=true)] public static void SetData(LocalDataStoreSlot slot, Object data) { LocalDataStoreHolder dls = s_LocalDataStore; @@ -1044,7 +637,6 @@ namespace System.Threading { // default domain to lookup resources. See Environment.cs for more details. // #if FEATURE_LEAK_CULTURE_INFO - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] static extern private bool nativeGetSafeCulture(Thread t, int appDomainId, bool isUI, ref CultureInfo safeCulture); #endif // FEATURE_LEAK_CULTURE_INFO @@ -1075,11 +667,9 @@ namespace System.Threading { } } - [System.Security.SecuritySafeCritical] // auto-generated - [HostProtection(ExternalThreading=true)] set { if (value == null) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); @@ -1119,7 +709,6 @@ namespace System.Threading { } #if FEATURE_LEAK_CULTURE_INFO - [System.Security.SecuritySafeCritical] // auto-generated #endif internal CultureInfo GetCurrentUICultureNoAppX() { @@ -1152,7 +741,6 @@ namespace System.Threading { // This returns the exposed context for a given context ID. #if FEATURE_LEAK_CULTURE_INFO - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] static extern private bool nativeSetThreadUILocale(String locale); #endif @@ -1184,13 +772,11 @@ namespace System.Threading { } } - [System.Security.SecuritySafeCritical] // auto-generated #if FEATURE_LEAK_CULTURE_INFO - [SecurityPermission(SecurityAction.Demand, ControlThread = true)] #endif set { if (null==value) { - throw new ArgumentNullException("value"); + throw new ArgumentNullException(nameof(value)); } Contract.EndContractBlock(); @@ -1225,7 +811,6 @@ namespace System.Threading { } #if FEATURE_LEAK_CULTURE_INFO - [System.Security.SecuritySafeCritical] // auto-generated #endif private CultureInfo GetCurrentCultureNoAppX() { @@ -1255,114 +840,21 @@ namespace System.Threading { #endif } -#if! FEATURE_LEAK_CULTURE_INFO - [System.Security.SecurityCritical] // auto-generated +#if !FEATURE_LEAK_CULTURE_INFO [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void nativeInitCultureAccessors(); #endif - /*=============================================================*/ - - /*====================================================================== - ** Current thread context is stored in a slot in the thread local store - ** CurrentContext gets the Context from the slot. - ======================================================================*/ -#if FEATURE_REMOTING - public static Context CurrentContext - { - [System.Security.SecurityCritical] // auto-generated_required - get - { - return CurrentThread.GetCurrentContextInternal(); - } - } - - [System.Security.SecurityCritical] // auto-generated - internal Context GetCurrentContextInternal() - { - if (m_Context == null) - { - m_Context = Context.DefaultContext; - } - return m_Context; - } -#endif - - -#if FEATURE_IMPERSONATION - // Get and set thread's current principal (for role based security). - public static IPrincipal CurrentPrincipal - { - [System.Security.SecuritySafeCritical] // auto-generated - get - { - lock (CurrentThread) - { - IPrincipal principal = (IPrincipal) - CallContext.Principal; - if (principal == null) - { - principal = GetDomain().GetThreadPrincipal(); - CallContext.Principal = principal; - } - return principal; - } - } - - [System.Security.SecuritySafeCritical] // auto-generated - [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPrincipal)] - set - { - CallContext.Principal = value; - } - } - - // Private routine called from unmanaged code to set an initial - // principal for a newly created thread. - [System.Security.SecurityCritical] // auto-generated - private void SetPrincipalInternal(IPrincipal principal) - { - GetMutableExecutionContext().LogicalCallContext.SecurityData.Principal = principal; - } -#endif // FEATURE_IMPERSONATION - -#if FEATURE_REMOTING - - // This returns the exposed context for a given context ID. - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern Context GetContextInternal(IntPtr id); - - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal extern Object InternalCrossContextCallback(Context ctx, IntPtr ctxID, Int32 appDomainID, InternalCrossContextDelegate ftnToCall, Object[] args); - - [System.Security.SecurityCritical] // auto-generated - internal Object InternalCrossContextCallback(Context ctx, InternalCrossContextDelegate ftnToCall, Object[] args) - { - return InternalCrossContextCallback(ctx, ctx.InternalContextID, 0, ftnToCall, args); - } - - // CompleteCrossContextCallback is called by the EE after transitioning to the requested context - private static Object CompleteCrossContextCallback(InternalCrossContextDelegate ftnToCall, Object[] args) - { - return ftnToCall(args); - } -#endif // FEATURE_REMOTING - /*====================================================================== ** Returns the current domain in which current thread is running. ======================================================================*/ - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern AppDomain GetDomainInternal(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern AppDomain GetFastDomainInternal(); - [System.Security.SecuritySafeCritical] // auto-generated public static AppDomain GetDomain() { Contract.Ensures(Contract.Result() != null); @@ -1373,9 +865,6 @@ namespace System.Threading { if (ad == null) ad = GetDomainInternal(); -#if FEATURE_REMOTING - Contract.Assert(CurrentThread.m_Context == null || CurrentThread.m_Context.AppDomain == ad, "AppDomains on the managed & unmanaged threads should match"); -#endif return ad; } @@ -1391,13 +880,10 @@ namespace System.Threading { // Retrieves the name of the thread. // - public String Name { + public new String Name { get { return m_Name; - } - [System.Security.SecuritySafeCritical] // auto-generated - [HostProtection(ExternalThreading=true)] set { lock(this) { if (m_Name != null) @@ -1409,13 +895,11 @@ namespace System.Threading { } } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void InformThreadNameChange(ThreadHandle t, String name, int len); internal Object AbortReason { - [System.Security.SecurityCritical] // auto-generated get { object result = null; try @@ -1428,46 +912,9 @@ namespace System.Threading { } return result; } - [System.Security.SecurityCritical] // auto-generated set { SetAbortReason(value); } } -#if !FEATURE_CORECLR - /* - * This marks the beginning of a critical code region. - */ - [System.Security.SecuritySafeCritical] // auto-generated - [HostProtection(Synchronization=true, ExternalThreading=true)] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - public static extern void BeginCriticalRegion(); - - /* - * This marks the end of a critical code region. - */ - [System.Security.SecuritySafeCritical] // auto-generated - [HostProtection(Synchronization=true, ExternalThreading=true)] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - public static extern void EndCriticalRegion(); - - /* - * This marks the beginning of a code region that requires thread affinity. - */ - [System.Security.SecurityCritical] // auto-generated_required - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - public static extern void BeginThreadAffinity(); - - /* - * This marks the end of a code region that requires thread affinity. - */ - [System.Security.SecurityCritical] // auto-generated_required - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - public static extern void EndThreadAffinity(); -#endif // !FEATURE_CORECLR - /*========================================================================= ** Volatile Read & Write and MemoryBarrier methods. ** Provides the ability to read and write values ensuring that the values @@ -1679,7 +1126,6 @@ namespace System.Threading { address = value; } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern void MemoryBarrier(); @@ -1696,45 +1142,20 @@ namespace System.Threading { } } -#if !FEATURE_CORECLR - void _Thread.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _Thread.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _Thread.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - void _Thread.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } -#endif - // Helper function to set the AbortReason for a thread abort. // Checks that they're not alredy set, and then atomically updates // the reason info (object + ADID). - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern void SetAbortReason(Object o); // Helper function to retrieve the AbortReason from a thread // abort. Will perform cross-AppDomain marshalling if the object // lives in a different AppDomain from the requester. - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern Object GetAbortReason(); // Helper function to clear the AbortReason. Takes care of // AppDomain related cleanup if required. - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern void ClearAbortReason(); diff --git a/src/mscorlib/src/System/Threading/ThreadAbortException.cs b/src/mscorlib/src/System/Threading/ThreadAbortException.cs index 11c8744..09ad4e1 100644 --- a/src/mscorlib/src/System/Threading/ThreadAbortException.cs +++ b/src/mscorlib/src/System/Threading/ThreadAbortException.cs @@ -39,7 +39,6 @@ namespace System.Threading public Object ExceptionState { - [System.Security.SecuritySafeCritical] // auto-generated get {return Thread.CurrentThread.AbortReason;} } } diff --git a/src/mscorlib/src/System/Threading/ThreadLocal.cs b/src/mscorlib/src/System/Threading/ThreadLocal.cs index b4cf12a..2b996cb 100644 --- a/src/mscorlib/src/System/Threading/ThreadLocal.cs +++ b/src/mscorlib/src/System/Threading/ThreadLocal.cs @@ -15,9 +15,9 @@ // // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -using System.Diagnostics; using System.Collections.Generic; using System.Security.Permissions; +using System.Diagnostics; using System.Diagnostics.Contracts; namespace System.Threading @@ -35,7 +35,6 @@ namespace System.Threading /// [DebuggerTypeProxy(typeof(SystemThreading_ThreadLocalDebugView<>))] [DebuggerDisplay("IsValueCreated={IsValueCreated}, Value={ValueForDebugDisplay}, Count={ValuesCountForDebugDisplay}")] - [HostProtection(Synchronization = true, ExternalThreading = true)] public class ThreadLocal : IDisposable { @@ -107,7 +106,7 @@ namespace System.Threading public ThreadLocal(Func valueFactory) { if (valueFactory == null) - throw new ArgumentNullException("valueFactory"); + throw new ArgumentNullException(nameof(valueFactory)); Initialize(valueFactory, false); } @@ -127,7 +126,7 @@ namespace System.Threading public ThreadLocal(Func valueFactory, bool trackAllValues) { if (valueFactory == null) - throw new ArgumentNullException("valueFactory"); + throw new ArgumentNullException(nameof(valueFactory)); Initialize(valueFactory, trackAllValues); } @@ -193,7 +192,7 @@ namespace System.Threading if (id < 0 || !m_initialized) { - Contract.Assert(id >= 0 || !m_initialized, "expected id >= 0 if initialized"); + Debug.Assert(id >= 0 || !m_initialized, "expected id >= 0 if initialized"); // Handle double Dispose calls or disposal of an instance whose constructor threw an exception. return; @@ -550,7 +549,7 @@ namespace System.Threading /// private void GrowTable(ref LinkedSlotVolatile[] table, int minLength) { - Contract.Assert(table.Length < minLength); + Debug.Assert(table.Length < minLength); // Determine the size of the new table and allocate it. int newLen = GetNewTableSize(minLength); @@ -588,7 +587,7 @@ namespace System.Threading // Intentionally return a value that will result in an OutOfMemoryException return int.MaxValue; } - Contract.Assert(minSize > 0); + Debug.Assert(minSize > 0); // // Round up the size to the next power of 2 @@ -737,7 +736,7 @@ namespace System.Threading ~FinalizationHelper() { LinkedSlotVolatile[] slotArray = SlotArray; - Contract.Assert(slotArray != null); + Debug.Assert(slotArray != null); for (int i = 0; i < slotArray.Length; i++) { @@ -765,7 +764,7 @@ namespace System.Threading } // Since the list uses a dummy head node, the Previous reference should never be null. - Contract.Assert(linkedSlot.Previous != null); + Debug.Assert(linkedSlot.Previous != null); linkedSlot.Previous.Next = linkedSlot.Next; } } diff --git a/src/mscorlib/src/System/Threading/ThreadPool.cs b/src/mscorlib/src/System/Threading/ThreadPool.cs index 09fe93c..451b15d 100644 --- a/src/mscorlib/src/System/Threading/ThreadPool.cs +++ b/src/mscorlib/src/System/Threading/ThreadPool.cs @@ -29,15 +29,14 @@ namespace System.Threading { using System.Security; - using System.Runtime.Remoting; using System.Security.Permissions; using System; using Microsoft.Win32; using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; - using System.Runtime.Versioning; using System.Collections.Generic; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Tracing; @@ -46,19 +45,17 @@ namespace System.Threading { //Per-appDomain quantum (in ms) for which the thread keeps processing //requests in the current domain. - public static uint tpQuantum = 30U; + public const uint TP_QUANTUM = 30U; - public static int processorCount = Environment.ProcessorCount; + public static readonly int processorCount = Environment.ProcessorCount; - public static bool tpHosted = ThreadPool.IsThreadPoolHosted(); + public static readonly bool tpHosted = ThreadPool.IsThreadPoolHosted(); public static volatile bool vmTpInitialized; public static bool enableWorkerTracking; - [SecurityCritical] - public static ThreadPoolWorkQueue workQueue = new ThreadPoolWorkQueue(); + public static readonly ThreadPoolWorkQueue workQueue = new ThreadPoolWorkQueue(); - [System.Security.SecuritySafeCritical] // static constructors should be safe to call static ThreadPoolGlobals() { } @@ -173,7 +170,7 @@ namespace System.Threading // m_headIndex = m_headIndex & m_mask; m_tailIndex = tail = m_tailIndex & m_mask; - Contract.Assert(m_headIndex <= m_tailIndex); + Debug.Assert(m_headIndex <= m_tailIndex); } } finally @@ -235,7 +232,7 @@ namespace System.Threading IThreadPoolWorkItem unused; if (LocalPop(out unused)) { - Contract.Assert(unused == obj); + Debug.Assert(unused == obj); return true; } return false; @@ -434,23 +431,23 @@ namespace System.Threading upper = (i >> 16) & SixteenBits; lower = i & SixteenBits; - Contract.Assert(upper >= lower); - Contract.Assert(upper <= nodes.Length); - Contract.Assert(lower <= nodes.Length); - Contract.Assert(upper >= 0); - Contract.Assert(lower >= 0); + Debug.Assert(upper >= lower); + Debug.Assert(upper <= nodes.Length); + Debug.Assert(lower <= nodes.Length); + Debug.Assert(upper >= 0); + Debug.Assert(lower >= 0); } bool CompareExchangeIndexes(ref int prevUpper, int newUpper, ref int prevLower, int newLower) { - Contract.Assert(newUpper >= newLower); - Contract.Assert(newUpper <= nodes.Length); - Contract.Assert(newLower <= nodes.Length); - Contract.Assert(newUpper >= 0); - Contract.Assert(newLower >= 0); - Contract.Assert(newUpper >= prevUpper); - Contract.Assert(newLower >= prevLower); - Contract.Assert(newUpper == prevUpper ^ newLower == prevLower); + Debug.Assert(newUpper >= newLower); + Debug.Assert(newUpper <= nodes.Length); + Debug.Assert(newLower <= nodes.Length); + Debug.Assert(newUpper >= 0); + Debug.Assert(newLower >= 0); + Debug.Assert(newUpper >= prevUpper); + Debug.Assert(newLower >= prevLower); + Debug.Assert(newUpper == prevUpper ^ newLower == prevLower); int oldIndexes = (prevUpper << 16) | (prevLower & SixteenBits); int newIndexes = (newUpper << 16) | (newLower & SixteenBits); @@ -463,7 +460,7 @@ namespace System.Threading [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public QueueSegment() { - Contract.Assert(QueueSegmentLength <= SixteenBits); + Debug.Assert(QueueSegmentLength <= SixteenBits); nodes = new IThreadPoolWorkItem[QueueSegmentLength]; } @@ -486,7 +483,7 @@ namespace System.Threading // with a busy-wait loop, waiting for the element to become non-null. This implies // that we can never store null nodes in this data structure. // - Contract.Assert(null != node); + Debug.Assert(null != node); int upper, lower; GetIndexes(out upper, out lower); @@ -498,7 +495,7 @@ namespace System.Threading if (CompareExchangeIndexes(ref upper, upper + 1, ref lower, lower)) { - Contract.Assert(Volatile.Read(ref nodes[upper]) == null); + Debug.Assert(Volatile.Read(ref nodes[upper]) == null); Volatile.Write(ref nodes[upper], node); return true; } @@ -546,7 +543,7 @@ namespace System.Threading internal volatile QueueSegment queueTail; internal bool loggingEnabled; - internal static SparseArray allThreadQueues = new SparseArray(16); + internal static readonly SparseArray allThreadQueues = new SparseArray(16); private volatile int numOutstandingThreadRequests = 0; @@ -556,7 +553,6 @@ namespace System.Threading loggingEnabled = FrameworkEventSource.Log.IsEnabled(EventLevel.Verbose, FrameworkEventSource.Keywords.ThreadPool|FrameworkEventSource.Keywords.ThreadTransfer); } - [SecurityCritical] public ThreadPoolWorkQueueThreadLocals EnsureCurrentThreadHasQueue() { if (null == ThreadPoolWorkQueueThreadLocals.threadLocals) @@ -564,7 +560,6 @@ namespace System.Threading return ThreadPoolWorkQueueThreadLocals.threadLocals; } - [SecurityCritical] internal void EnsureThreadRequested() { // @@ -585,7 +580,6 @@ namespace System.Threading } } - [SecurityCritical] internal void MarkThreadRequestSatisfied() { // @@ -606,7 +600,6 @@ namespace System.Threading } } - [SecurityCritical] public void Enqueue(IThreadPoolWorkItem callback, bool forceGlobal) { ThreadPoolWorkQueueThreadLocals tl = null; @@ -639,7 +632,6 @@ namespace System.Threading EnsureThreadRequested(); } - [SecurityCritical] internal bool LocalFindAndPop(IThreadPoolWorkItem callback) { ThreadPoolWorkQueueThreadLocals tl = ThreadPoolWorkQueueThreadLocals.threadLocals; @@ -649,7 +641,6 @@ namespace System.Threading return tl.workStealingQueue.LocalFindAndPop(callback); } - [SecurityCritical] public void Dequeue(ThreadPoolWorkQueueThreadLocals tl, out IThreadPoolWorkItem callback, out bool missedSteal) { callback = null; @@ -657,7 +648,7 @@ namespace System.Threading WorkStealingQueue wsq = tl.workStealingQueue; if (wsq.LocalPop(out callback)) - Contract.Assert(null != callback); + Debug.Assert(null != callback); if (null == callback) { @@ -666,7 +657,7 @@ namespace System.Threading { if (tail.TryDequeue(out callback)) { - Contract.Assert(null != callback); + Debug.Assert(null != callback); break; } @@ -696,7 +687,7 @@ namespace System.Threading otherQueue != wsq && otherQueue.TrySteal(out callback, ref missedSteal)) { - Contract.Assert(null != callback); + Debug.Assert(null != callback); break; } c--; @@ -704,12 +695,11 @@ namespace System.Threading } } - [SecurityCritical] static internal bool Dispatch() { var workQueue = ThreadPoolGlobals.workQueue; // - // The clock is ticking! We have ThreadPoolGlobals.tpQuantum milliseconds to get some work done, and then + // The clock is ticking! We have ThreadPoolGlobals.TP_QUANTUM milliseconds to get some work done, and then // we need to return to the VM. // int quantumStartTime = Environment.TickCount; @@ -743,7 +733,7 @@ namespace System.Threading // // Loop until our quantum expires. // - while ((Environment.TickCount - quantumStartTime) < ThreadPoolGlobals.tpQuantum) + while ((Environment.TickCount - quantumStartTime) < ThreadPoolGlobals.TP_QUANTUM) { // // Dequeue and EnsureThreadRequested must be protected from ThreadAbortException. @@ -855,7 +845,7 @@ namespace System.Threading } // we can never reach this point, but the C# compiler doesn't know that, because it doesn't know the ThreadAbortException will be reraised above. - Contract.Assert(false); + Debug.Assert(false); return true; } } @@ -864,7 +854,6 @@ namespace System.Threading internal sealed class ThreadPoolWorkQueueThreadLocals { [ThreadStatic] - [SecurityCritical] public static ThreadPoolWorkQueueThreadLocals threadLocals; public readonly ThreadPoolWorkQueue workQueue; @@ -878,7 +867,6 @@ namespace System.Threading ThreadPoolWorkQueue.allThreadQueues.Add(workStealingQueue); } - [SecurityCritical] private void CleanUp() { if (null != workStealingQueue) @@ -895,7 +883,7 @@ namespace System.Threading IThreadPoolWorkItem cb = null; if (workStealingQueue.LocalPop(out cb)) { - Contract.Assert(null != cb); + Debug.Assert(null != cb); workQueue.Enqueue(cb, true); } else @@ -910,7 +898,6 @@ namespace System.Threading } } - [SecuritySafeCritical] ~ThreadPoolWorkQueueThreadLocals() { // Since the purpose of calling CleanUp is to transfer any pending workitems into the global @@ -927,7 +914,6 @@ namespace System.Threading { private static IntPtr InvalidHandle { - [System.Security.SecuritySafeCritical] // auto-generated get { return Win32Native.INVALID_HANDLE_VALUE; @@ -938,9 +924,6 @@ namespace System.Threading private bool bReleaseNeeded = false; private volatile int m_lock = 0; - #if FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // auto-generated - #endif internal RegisteredWaitHandleSafe() { registeredWaitHandle = InvalidHandle; @@ -956,7 +939,6 @@ namespace System.Threading registeredWaitHandle = handle; } - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal void SetWaitObject(WaitHandle waitObject) { @@ -975,7 +957,6 @@ namespace System.Threading } } - [System.Security.SecurityCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal bool Unregister( WaitHandle waitObject // object to be notified when all callbacks to delegates have completed @@ -1033,7 +1014,6 @@ namespace System.Threading return (registeredWaitHandle != InvalidHandle && registeredWaitHandle != IntPtr.Zero); } - [System.Security.SecuritySafeCritical] // auto-generated ~RegisteredWaitHandleSafe() { // if the app has already unregistered the wait, there is nothing to cleanup @@ -1084,21 +1064,15 @@ namespace System.Threading } } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void WaitHandleCleanupNative(IntPtr handle); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool UnregisterWaitNative(IntPtr handle, SafeHandle waitObject); } [System.Runtime.InteropServices.ComVisible(true)] -#if FEATURE_REMOTING public sealed class RegisteredWaitHandle : MarshalByRefObject { -#else // FEATURE_REMOTING - public sealed class RegisteredWaitHandle { -#endif // FEATURE_REMOTING private RegisteredWaitHandleSafe internalRegisteredWait; internal RegisteredWaitHandle() @@ -1111,14 +1085,12 @@ namespace System.Threading internalRegisteredWait.SetHandle(handle); } - [System.Security.SecurityCritical] // auto-generated internal void SetWaitObject(WaitHandle waitObject) { internalRegisteredWait.SetWaitObject(waitObject); } -[System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.InteropServices.ComVisible(true)] // This is the only public method on this class public bool Unregister( @@ -1143,7 +1115,6 @@ namespace System.Threading // internal static class _ThreadPoolWaitCallback { - [System.Security.SecurityCritical] static internal bool PerformWaitCallback() { return ThreadPoolWorkQueue.Dispatch(); @@ -1161,15 +1132,12 @@ namespace System.Threading // internal interface IThreadPoolWorkItem { - [SecurityCritical] void ExecuteWorkItem(); - [SecurityCritical] void MarkAborted(ThreadAbortException tae); } internal sealed class QueueUserWorkItemCallback : IThreadPoolWorkItem { - [System.Security.SecuritySafeCritical] static QueueUserWorkItemCallback() {} private WaitCallback callback; @@ -1181,7 +1149,7 @@ namespace System.Threading ~QueueUserWorkItemCallback() { - Contract.Assert( + Debug.Assert( executed != 0 || Environment.HasShutdownStarted || AppDomain.CurrentDomain.IsFinalizingForUnload(), "A QueueUserWorkItemCallback was never called!"); } @@ -1189,13 +1157,12 @@ namespace System.Threading void MarkExecuted(bool aborted) { GC.SuppressFinalize(this); - Contract.Assert( + Debug.Assert( 0 == Interlocked.Exchange(ref executed, 1) || aborted, "A QueueUserWorkItemCallback was called twice!"); } #endif - [SecurityCritical] internal QueueUserWorkItemCallback(WaitCallback waitCallback, Object stateObj, ExecutionContext ec) { callback = waitCallback; @@ -1203,7 +1170,6 @@ namespace System.Threading context = ec; } - [SecurityCritical] void IThreadPoolWorkItem.ExecuteWorkItem() { #if DEBUG @@ -1222,7 +1188,6 @@ namespace System.Threading } } - [SecurityCritical] void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae) { #if DEBUG @@ -1232,22 +1197,19 @@ namespace System.Threading #endif } - [System.Security.SecurityCritical] static internal ContextCallback ccb = new ContextCallback(WaitCallback_Context); - [System.Security.SecurityCritical] static private void WaitCallback_Context(Object state) { QueueUserWorkItemCallback obj = (QueueUserWorkItemCallback)state; WaitCallback wc = obj.callback as WaitCallback; - Contract.Assert(null != wc); + Debug.Assert(null != wc); wc(obj.state); } } internal sealed class QueueUserWorkItemCallbackDefaultContext : IThreadPoolWorkItem { - [System.Security.SecuritySafeCritical] static QueueUserWorkItemCallbackDefaultContext() { } private WaitCallback callback; @@ -1258,7 +1220,7 @@ namespace System.Threading ~QueueUserWorkItemCallbackDefaultContext() { - Contract.Assert( + Debug.Assert( executed != 0 || Environment.HasShutdownStarted || AppDomain.CurrentDomain.IsFinalizingForUnload(), "A QueueUserWorkItemCallbackDefaultContext was never called!"); } @@ -1266,20 +1228,18 @@ namespace System.Threading void MarkExecuted(bool aborted) { GC.SuppressFinalize(this); - Contract.Assert( + Debug.Assert( 0 == Interlocked.Exchange(ref executed, 1) || aborted, "A QueueUserWorkItemCallbackDefaultContext was called twice!"); } #endif - [SecurityCritical] internal QueueUserWorkItemCallbackDefaultContext(WaitCallback waitCallback, Object stateObj) { callback = waitCallback; state = stateObj; } - [SecurityCritical] void IThreadPoolWorkItem.ExecuteWorkItem() { #if DEBUG @@ -1288,7 +1248,6 @@ namespace System.Threading ExecutionContext.Run(ExecutionContext.PreAllocatedDefault, ccb, this, true); } - [SecurityCritical] void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae) { #if DEBUG @@ -1298,15 +1257,13 @@ namespace System.Threading #endif } - [System.Security.SecurityCritical] static internal ContextCallback ccb = new ContextCallback(WaitCallback_Context); - [System.Security.SecurityCritical] static private void WaitCallback_Context(Object state) { QueueUserWorkItemCallbackDefaultContext obj = (QueueUserWorkItemCallbackDefaultContext)state; WaitCallback wc = obj.callback as WaitCallback; - Contract.Assert(null != wc); + Debug.Assert(null != wc); obj.callback = null; wc(obj.state); } @@ -1314,18 +1271,14 @@ namespace System.Threading internal class _ThreadPoolWaitOrTimerCallback { - [System.Security.SecuritySafeCritical] static _ThreadPoolWaitOrTimerCallback() {} WaitOrTimerCallback _waitOrTimerCallback; ExecutionContext _executionContext; Object _state; - [System.Security.SecurityCritical] static private ContextCallback _ccbt = new ContextCallback(WaitOrTimerCallback_Context_t); - [System.Security.SecurityCritical] static private ContextCallback _ccbf = new ContextCallback(WaitOrTimerCallback_Context_f); - [System.Security.SecurityCritical] // auto-generated internal _ThreadPoolWaitOrTimerCallback(WaitOrTimerCallback waitOrTimerCallback, Object state, bool compressStack, ref StackCrawlMark stackMark) { _waitOrTimerCallback = waitOrTimerCallback; @@ -1340,13 +1293,11 @@ namespace System.Threading } } - [System.Security.SecurityCritical] static private void WaitOrTimerCallback_Context_t(Object state) { WaitOrTimerCallback_Context(state, true); } - [System.Security.SecurityCritical] static private void WaitOrTimerCallback_Context_f(Object state) { WaitOrTimerCallback_Context(state, false); @@ -1359,11 +1310,10 @@ namespace System.Threading } // call back helper - [System.Security.SecurityCritical] // auto-generated static internal void PerformWaitOrTimerCallback(Object state, bool timedOut) { _ThreadPoolWaitOrTimerCallback helper = (_ThreadPoolWaitOrTimerCallback)state; - Contract.Assert(helper != null, "Null state passed to PerformWaitOrTimerCallback!"); + Debug.Assert(helper != null, "Null state passed to PerformWaitOrTimerCallback!"); // call directly if it is an unsafe call OR EC flow is suppressed if (helper._executionContext == null) { @@ -1384,7 +1334,6 @@ namespace System.Threading } - [System.Security.SecurityCritical] [CLSCompliant(false)] [System.Runtime.InteropServices.ComVisible(true)] unsafe public delegate void IOCompletionCallback(uint errorCode, // Error code @@ -1392,55 +1341,34 @@ namespace System.Threading NativeOverlapped* pOVERLAP // ptr to OVERLAP structure ); - [HostProtection(Synchronization=true, ExternalThreading=true)] public static class ThreadPool { - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif -#pragma warning disable 618 - [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)] -#pragma warning restore 618 public static bool SetMaxThreads(int workerThreads, int completionPortThreads) { return SetMaxThreadsNative(workerThreads, completionPortThreads); } - [System.Security.SecuritySafeCritical] // auto-generated public static void GetMaxThreads(out int workerThreads, out int completionPortThreads) { GetMaxThreadsNative(out workerThreads, out completionPortThreads); } - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif -#pragma warning disable 618 - [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)] -#pragma warning restore 618 public static bool SetMinThreads(int workerThreads, int completionPortThreads) { return SetMinThreadsNative(workerThreads, completionPortThreads); } - [System.Security.SecuritySafeCritical] // auto-generated public static void GetMinThreads(out int workerThreads, out int completionPortThreads) { GetMinThreadsNative(out workerThreads, out completionPortThreads); } - [System.Security.SecuritySafeCritical] // auto-generated public static void GetAvailableThreads(out int workerThreads, out int completionPortThreads) { GetAvailableThreadsNative(out workerThreads, out completionPortThreads); } - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static RegisteredWaitHandle RegisterWaitForSingleObject( // throws RegisterWaitException @@ -1455,7 +1383,6 @@ namespace System.Threading return RegisterWaitForSingleObject(waitObject,callBack,state,millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,true); } - [System.Security.SecurityCritical] // auto-generated_required [CLSCompliant(false)] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject( // throws RegisterWaitException @@ -1471,7 +1398,6 @@ namespace System.Threading } - [System.Security.SecurityCritical] // auto-generated private static RegisteredWaitHandle RegisterWaitForSingleObject( // throws RegisterWaitException WaitHandle waitObject, WaitOrTimerCallback callBack, @@ -1482,12 +1408,6 @@ namespace System.Threading bool compressStack ) { -#if FEATURE_REMOTING - if (RemotingServices.IsTransparentProxy(waitObject)) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WaitOnTransparentProxy")); - Contract.EndContractBlock(); -#endif - RegisteredWaitHandle registeredWaitHandle = new RegisteredWaitHandle(); if (callBack != null) @@ -1508,13 +1428,12 @@ namespace System.Threading } else { - throw new ArgumentNullException("WaitOrTimerCallback"); + throw new ArgumentNullException(nameof(WaitOrTimerCallback)); } return registeredWaitHandle; } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static RegisteredWaitHandle RegisterWaitForSingleObject( // throws RegisterWaitException WaitHandle waitObject, @@ -1525,13 +1444,12 @@ namespace System.Threading ) { if (millisecondsTimeOutInterval < -1) - throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(millisecondsTimeOutInterval), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,true); } - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject( // throws RegisterWaitException WaitHandle waitObject, @@ -1542,13 +1460,12 @@ namespace System.Threading ) { if (millisecondsTimeOutInterval < -1) - throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(millisecondsTimeOutInterval), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,false); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static RegisteredWaitHandle RegisterWaitForSingleObject( // throws RegisterWaitException WaitHandle waitObject, @@ -1559,13 +1476,12 @@ namespace System.Threading ) { if (millisecondsTimeOutInterval < -1) - throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(millisecondsTimeOutInterval), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,true); } - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject( // throws RegisterWaitException WaitHandle waitObject, @@ -1576,13 +1492,12 @@ namespace System.Threading ) { if (millisecondsTimeOutInterval < -1) - throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(millisecondsTimeOutInterval), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,false); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static RegisteredWaitHandle RegisterWaitForSingleObject( WaitHandle waitObject, @@ -1594,14 +1509,13 @@ namespace System.Threading { long tm = (long)timeout.TotalMilliseconds; if (tm < -1) - throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(timeout), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); if (tm > (long) Int32.MaxValue) - throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_LessEqualToIntegerMaxVal")); + throw new ArgumentOutOfRangeException(nameof(timeout), Environment.GetResourceString("ArgumentOutOfRange_LessEqualToIntegerMaxVal")); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)tm,executeOnlyOnce,ref stackMark,true); } - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject( WaitHandle waitObject, @@ -1613,14 +1527,13 @@ namespace System.Threading { long tm = (long)timeout.TotalMilliseconds; if (tm < -1) - throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(timeout), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); if (tm > (long) Int32.MaxValue) - throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_LessEqualToIntegerMaxVal")); + throw new ArgumentOutOfRangeException(nameof(timeout), Environment.GetResourceString("ArgumentOutOfRange_LessEqualToIntegerMaxVal")); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)tm,executeOnlyOnce,ref stackMark,false); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static bool QueueUserWorkItem( WaitCallback callBack, // NOTE: we do not expose options that allow the callback to be queued as an APC @@ -1631,7 +1544,6 @@ namespace System.Threading return QueueUserWorkItemHelper(callBack,state,ref stackMark,true); } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static bool QueueUserWorkItem( WaitCallback callBack // NOTE: we do not expose options that allow the callback to be queued as an APC @@ -1641,7 +1553,6 @@ namespace System.Threading return QueueUserWorkItemHelper(callBack,null,ref stackMark,true); } - [System.Security.SecurityCritical] // auto-generated_required [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static bool UnsafeQueueUserWorkItem( WaitCallback callBack, // NOTE: we do not expose options that allow the callback to be queued as an APC @@ -1655,7 +1566,6 @@ namespace System.Threading //ThreadPool has per-appdomain managed queue of work-items. The VM is //responsible for just scheduling threads into appdomains. After that //work-items are dispatched from the managed queue. - [System.Security.SecurityCritical] // auto-generated private static bool QueueUserWorkItemHelper(WaitCallback callBack, Object state, ref StackCrawlMark stackMark, bool compressStack ) { bool success = true; @@ -1690,15 +1600,14 @@ namespace System.Threading } else { - throw new ArgumentNullException("WaitCallback"); + throw new ArgumentNullException(nameof(WaitCallback)); } return success; } - [SecurityCritical] internal static void UnsafeQueueCustomWorkItem(IThreadPoolWorkItem workItem, bool forceGlobal) { - Contract.Assert(null != workItem); + Debug.Assert(null != workItem); EnsureVMInitialized(); // @@ -1712,17 +1621,15 @@ namespace System.Threading } // This method tries to take the target callback out of the current thread's queue. - [SecurityCritical] internal static bool TryPopCustomWorkItem(IThreadPoolWorkItem workItem) { - Contract.Assert(null != workItem); + Debug.Assert(null != workItem); if (!ThreadPoolGlobals.vmTpInitialized) return false; //Not initialized, so there's no way this workitem was ever queued. return ThreadPoolGlobals.workQueue.LocalFindAndPop(workItem); } // Get all workitems. Called by TaskScheduler in its debugger hooks. - [SecurityCritical] internal static IEnumerable GetQueuedWorkItems() { return EnumerateQueuedWorkItems(ThreadPoolWorkQueue.allThreadQueues.Current, ThreadPoolGlobals.workQueue.queueTail); @@ -1766,13 +1673,11 @@ namespace System.Threading } } - [SecurityCritical] internal static IEnumerable GetLocallyQueuedWorkItems() { return EnumerateQueuedWorkItems(new ThreadPoolWorkQueue.WorkStealingQueue[] { ThreadPoolWorkQueueThreadLocals.threadLocals.workStealingQueue }, null); } - [SecurityCritical] internal static IEnumerable GetGloballyQueuedWorkItems() { return EnumerateQueuedWorkItems(null, ThreadPoolGlobals.workQueue.queueTail); @@ -1800,41 +1705,34 @@ namespace System.Threading // This is the method the debugger will actually call, if it ends up calling // into ThreadPool directly. Tests can use this to simulate a debugger, as well. - [SecurityCritical] internal static object[] GetQueuedWorkItemsForDebugger() { return ToObjectArray(GetQueuedWorkItems()); } - [SecurityCritical] internal static object[] GetGloballyQueuedWorkItemsForDebugger() { return ToObjectArray(GetGloballyQueuedWorkItems()); } - [SecurityCritical] internal static object[] GetLocallyQueuedWorkItemsForDebugger() { return ToObjectArray(GetLocallyQueuedWorkItems()); } - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern bool RequestWorkerThread(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] unsafe private static extern bool PostQueuedCompletionStatus(NativeOverlapped* overlapped); - [System.Security.SecurityCritical] // auto-generated_required [CLSCompliant(false)] unsafe public static bool UnsafeQueueNativeOverlapped(NativeOverlapped* overlapped) { return PostQueuedCompletionStatus(overlapped); } - [SecurityCritical] private static void EnsureVMInitialized() { if (!ThreadPoolGlobals.vmTpInitialized) @@ -1846,35 +1744,27 @@ namespace System.Threading // Native methods: - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool SetMinThreadsNative(int workerThreads, int completionPortThreads); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool SetMaxThreadsNative(int workerThreads, int completionPortThreads); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void GetMinThreadsNative(out int workerThreads, out int completionPortThreads); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void GetMaxThreadsNative(out int workerThreads, out int completionPortThreads); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void GetAvailableThreadsNative(out int workerThreads, out int completionPortThreads); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool NotifyWorkItemComplete(); - [System.Security.SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void ReportThreadStatus(bool isWorking); - [System.Security.SecuritySafeCritical] internal static void NotifyWorkItemProgress() { if (!ThreadPoolGlobals.vmTpInitialized) @@ -1882,20 +1772,16 @@ namespace System.Threading NotifyWorkItemProgressNative(); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void NotifyWorkItemProgressNative(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool IsThreadPoolHosted(); - [System.Security.SecurityCritical] // auto-generated [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void InitializeVMTp(ref bool enableWorkerTracking); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern IntPtr RegisterWaitForSingleObjectNative( WaitHandle waitHandle, @@ -1907,30 +1793,19 @@ namespace System.Threading bool compressStack ); -#if !FEATURE_CORECLR - [System.Security.SecuritySafeCritical] // auto-generated + [Obsolete("ThreadPool.BindHandle(IntPtr) has been deprecated. Please use ThreadPool.BindHandle(SafeHandle) instead.", false)] - [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] public static bool BindHandle( IntPtr osHandle ) { return BindIOCompletionCallbackNative(osHandle); } -#endif - #if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated - #else - [System.Security.SecuritySafeCritical] - #endif -#pragma warning disable 618 - [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] -#pragma warning restore 618 public static bool BindHandle(SafeHandle osHandle) { if (osHandle == null) - throw new ArgumentNullException("osHandle"); + throw new ArgumentNullException(nameof(osHandle)); bool ret = false; bool mustReleaseSafeHandle = false; @@ -1946,7 +1821,6 @@ namespace System.Threading return ret; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] private static extern bool BindIOCompletionCallbackNative(IntPtr fileHandle); diff --git a/src/mscorlib/src/System/Threading/Timer.cs b/src/mscorlib/src/System/Threading/Timer.cs index cb08c6e..5bfefcc 100644 --- a/src/mscorlib/src/System/Threading/Timer.cs +++ b/src/mscorlib/src/System/Threading/Timer.cs @@ -14,6 +14,7 @@ namespace System.Threading using System.Runtime.InteropServices; using System.Runtime.ConstrainedExecution; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Diagnostics.Tracing; using Microsoft.Win32.SafeHandles; @@ -76,7 +77,6 @@ namespace System.Threading // private static int TickCount { - [SecuritySafeCritical] get { #if !FEATURE_PAL @@ -102,7 +102,6 @@ namespace System.Threading // // We use a SafeHandle to ensure that the native timer is destroyed when the AppDomain is unloaded. // - [SecurityCritical] class AppDomainTimerSafeHandle : SafeHandleZeroOrMinusOneIsInvalid { public AppDomainTimerSafeHandle() @@ -110,7 +109,6 @@ namespace System.Threading { } - [SecurityCritical] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] protected override bool ReleaseHandle() { @@ -118,14 +116,12 @@ namespace System.Threading } } - [SecurityCritical] AppDomainTimerSafeHandle m_appDomainTimer; bool m_isAppDomainTimerScheduled; int m_currentAppDomainTimerStartTicks; uint m_currentAppDomainTimerDuration; - [SecuritySafeCritical] private bool EnsureAppDomainTimerFiresBy(uint requestedDuration) { // @@ -154,14 +150,14 @@ namespace System.Threading // A later update during resume will re-schedule if(m_pauseTicks != 0) { - Contract.Assert(!m_isAppDomainTimerScheduled); - Contract.Assert(m_appDomainTimer == null); + Debug.Assert(!m_isAppDomainTimerScheduled); + Debug.Assert(m_appDomainTimer == null); return true; } if (m_appDomainTimer == null || m_appDomainTimer.IsInvalid) { - Contract.Assert(!m_isAppDomainTimerScheduled); + Debug.Assert(!m_isAppDomainTimerScheduled); m_appDomainTimer = CreateAppDomainTimer(actualDuration); if (!m_appDomainTimer.IsInvalid) @@ -195,23 +191,19 @@ namespace System.Threading // // The VM calls this when the native timer fires. // - [SecuritySafeCritical] internal static void AppDomainTimerCallback() { Instance.FireNextTimers(); } - [System.Security.SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] static extern AppDomainTimerSafeHandle CreateAppDomainTimer(uint dueTime); - [System.Security.SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] static extern bool ChangeAppDomainTimer(AppDomainTimerSafeHandle handle, uint dueTime); - [System.Security.SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] @@ -229,7 +221,6 @@ namespace System.Threading volatile int m_pauseTicks = 0; // Time when Pause was called - [SecurityCritical] internal void Pause() { lock(this) @@ -245,7 +236,6 @@ namespace System.Threading } } - [SecurityCritical] internal void Resume() { // @@ -269,8 +259,8 @@ namespace System.Threading TimerQueueTimer timer = m_timers; while (timer != null) { - Contract.Assert(timer.m_dueTime != Timeout.UnsignedInfinite); - Contract.Assert(resumedTicks >= timer.m_startTicks); + Debug.Assert(timer.m_dueTime != Timeout.UnsignedInfinite); + Debug.Assert(resumedTicks >= timer.m_startTicks); uint elapsed; // How much of the timer dueTime has already elapsed @@ -343,7 +333,7 @@ namespace System.Threading TimerQueueTimer timer = m_timers; while (timer != null) { - Contract.Assert(timer.m_dueTime != Timeout.UnsignedInfinite); + Debug.Assert(timer.m_dueTime != Timeout.UnsignedInfinite); uint elapsed = (uint)(nowTicks - timer.m_startTicks); if (elapsed >= timer.m_dueTime) @@ -413,7 +403,6 @@ namespace System.Threading timerToFireOnThisThread.Fire(); } - [SecuritySafeCritical] private static void QueueTimerCompletion(TimerQueueTimer timer) { WaitCallback callback = s_fireQueuedTimerCompletion; @@ -523,7 +512,6 @@ namespace System.Threading volatile WaitHandle m_notifyWhenNoCallbacksRunning; - [SecurityCritical] internal TimerQueueTimer(TimerCallback timerCallback, object state, uint dueTime, uint period, ref StackCrawlMark stackMark) { m_timerCallback = timerCallback; @@ -673,13 +661,11 @@ namespace System.Threading SignalNoCallbacksRunning(); } - [SecuritySafeCritical] internal void SignalNoCallbacksRunning() { Win32Native.SetEvent(m_notifyWhenNoCallbacksRunning.SafeWaitHandle); } - [SecuritySafeCritical] internal void CallCallback() { if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.ThreadTransfer)) @@ -708,10 +694,8 @@ namespace System.Threading } } - [SecurityCritical] private static ContextCallback s_callCallbackInContext; - [SecurityCritical] private static void CallCallbackInContext(object state) { TimerQueueTimer t = (TimerQueueTimer)state; @@ -772,19 +756,13 @@ namespace System.Threading } - [HostProtection(Synchronization=true, ExternalThreading=true)] [System.Runtime.InteropServices.ComVisible(true)] -#if FEATURE_REMOTING public sealed class Timer : MarshalByRefObject, IDisposable -#else // FEATURE_REMOTING - public sealed class Timer : IDisposable -#endif // FEATURE_REMOTING { private const UInt32 MAX_SUPPORTED_TIMEOUT = (uint)0xfffffffe; private TimerHolder m_timer; - [SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public Timer(TimerCallback callback, Object state, @@ -792,16 +770,15 @@ namespace System.Threading int period) { if (dueTime < -1) - throw new ArgumentOutOfRangeException("dueTime", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(dueTime), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); if (period < -1 ) - throw new ArgumentOutOfRangeException("period", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(period), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; TimerSetup(callback,state,(UInt32)dueTime,(UInt32)period,ref stackMark); } - [SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public Timer(TimerCallback callback, Object state, @@ -810,22 +787,21 @@ namespace System.Threading { long dueTm = (long)dueTime.TotalMilliseconds; if (dueTm < -1) - throw new ArgumentOutOfRangeException("dueTm",Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(dueTm),Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); if (dueTm > MAX_SUPPORTED_TIMEOUT) - throw new ArgumentOutOfRangeException("dueTm",Environment.GetResourceString("ArgumentOutOfRange_TimeoutTooLarge")); + throw new ArgumentOutOfRangeException(nameof(dueTm),Environment.GetResourceString("ArgumentOutOfRange_TimeoutTooLarge")); long periodTm = (long)period.TotalMilliseconds; if (periodTm < -1) - throw new ArgumentOutOfRangeException("periodTm",Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(periodTm),Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); if (periodTm > MAX_SUPPORTED_TIMEOUT) - throw new ArgumentOutOfRangeException("periodTm",Environment.GetResourceString("ArgumentOutOfRange_PeriodTooLarge")); + throw new ArgumentOutOfRangeException(nameof(periodTm),Environment.GetResourceString("ArgumentOutOfRange_PeriodTooLarge")); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; TimerSetup(callback,state,(UInt32)dueTm,(UInt32)periodTm,ref stackMark); } [CLSCompliant(false)] - [SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public Timer(TimerCallback callback, Object state, @@ -836,7 +812,6 @@ namespace System.Threading TimerSetup(callback,state,dueTime,period,ref stackMark); } - [SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public Timer(TimerCallback callback, Object state, @@ -844,19 +819,18 @@ namespace System.Threading long period) { if (dueTime < -1) - throw new ArgumentOutOfRangeException("dueTime",Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(dueTime),Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); if (period < -1) - throw new ArgumentOutOfRangeException("period",Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(period),Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); if (dueTime > MAX_SUPPORTED_TIMEOUT) - throw new ArgumentOutOfRangeException("dueTime",Environment.GetResourceString("ArgumentOutOfRange_TimeoutTooLarge")); + throw new ArgumentOutOfRangeException(nameof(dueTime),Environment.GetResourceString("ArgumentOutOfRange_TimeoutTooLarge")); if (period > MAX_SUPPORTED_TIMEOUT) - throw new ArgumentOutOfRangeException("period",Environment.GetResourceString("ArgumentOutOfRange_PeriodTooLarge")); + throw new ArgumentOutOfRangeException(nameof(period),Environment.GetResourceString("ArgumentOutOfRange_PeriodTooLarge")); Contract.EndContractBlock(); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; TimerSetup(callback,state,(UInt32) dueTime, (UInt32) period,ref stackMark); } - [SecuritySafeCritical] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public Timer(TimerCallback callback) { @@ -869,7 +843,6 @@ namespace System.Threading TimerSetup(callback, this, (UInt32)dueTime, (UInt32)period, ref stackMark); } - [SecurityCritical] private void TimerSetup(TimerCallback callback, Object state, UInt32 dueTime, @@ -877,19 +850,17 @@ namespace System.Threading ref StackCrawlMark stackMark) { if (callback == null) - throw new ArgumentNullException("TimerCallback"); + throw new ArgumentNullException(nameof(TimerCallback)); Contract.EndContractBlock(); m_timer = new TimerHolder(new TimerQueueTimer(callback, state, dueTime, period, ref stackMark)); } - [SecurityCritical] internal static void Pause() { TimerQueue.Instance.Pause(); } - [SecurityCritical] internal static void Resume() { TimerQueue.Instance.Resume(); @@ -898,9 +869,9 @@ namespace System.Threading public bool Change(int dueTime, int period) { if (dueTime < -1 ) - throw new ArgumentOutOfRangeException("dueTime",Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(dueTime),Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); if (period < -1) - throw new ArgumentOutOfRangeException("period",Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(period),Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); Contract.EndContractBlock(); return m_timer.m_timer.Change((UInt32)dueTime, (UInt32)period); @@ -920,13 +891,13 @@ namespace System.Threading public bool Change(long dueTime, long period) { if (dueTime < -1 ) - throw new ArgumentOutOfRangeException("dueTime", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(dueTime), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); if (period < -1) - throw new ArgumentOutOfRangeException("period", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(period), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); if (dueTime > MAX_SUPPORTED_TIMEOUT) - throw new ArgumentOutOfRangeException("dueTime", Environment.GetResourceString("ArgumentOutOfRange_TimeoutTooLarge")); + throw new ArgumentOutOfRangeException(nameof(dueTime), Environment.GetResourceString("ArgumentOutOfRange_TimeoutTooLarge")); if (period > MAX_SUPPORTED_TIMEOUT) - throw new ArgumentOutOfRangeException("period", Environment.GetResourceString("ArgumentOutOfRange_PeriodTooLarge")); + throw new ArgumentOutOfRangeException(nameof(period), Environment.GetResourceString("ArgumentOutOfRange_PeriodTooLarge")); Contract.EndContractBlock(); return m_timer.m_timer.Change((UInt32)dueTime, (UInt32)period); @@ -935,7 +906,7 @@ namespace System.Threading public bool Dispose(WaitHandle notifyObject) { if (notifyObject==null) - throw new ArgumentNullException("notifyObject"); + throw new ArgumentNullException(nameof(notifyObject)); Contract.EndContractBlock(); return m_timer.Close(notifyObject); diff --git a/src/mscorlib/src/System/Threading/Volatile.cs b/src/mscorlib/src/System/Threading/Volatile.cs index af687fb..3894b43 100644 --- a/src/mscorlib/src/System/Threading/Volatile.cs +++ b/src/mscorlib/src/System/Threading/Volatile.cs @@ -129,7 +129,6 @@ namespace System.Threading [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [CLSCompliant(false)] [System.Runtime.Versioning.NonVersionable] - [SecuritySafeCritical] // to match 32-bit version public static ulong Read(ref ulong location) { // @@ -154,7 +153,6 @@ namespace System.Threading [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [CLSCompliant(false)] - [SecuritySafeCritical] // contains unsafe code public static ulong Read(ref ulong location) { unsafe @@ -222,7 +220,6 @@ namespace System.Threading } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [SecuritySafeCritical] //the intrinsic implementation of this method contains unverifiable code [System.Runtime.Versioning.NonVersionable] public static T Read(ref T location) where T : class { @@ -332,7 +329,6 @@ namespace System.Threading [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [CLSCompliant(false)] [System.Runtime.Versioning.NonVersionable] - [SecuritySafeCritical] // to match 32-bit version public static void Write(ref ulong location, ulong value) { // @@ -356,7 +352,6 @@ namespace System.Threading [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [CLSCompliant(false)] - [SecuritySafeCritical] // contains unsafe code public static void Write(ref ulong location, ulong value) { // @@ -427,7 +422,6 @@ namespace System.Threading } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [SecuritySafeCritical] //the intrinsic implementation of this method contains unverifiable code [System.Runtime.Versioning.NonVersionable] public static void Write(ref T location, T value) where T : class { diff --git a/src/mscorlib/src/System/Threading/WaitHandle.cs b/src/mscorlib/src/System/Threading/WaitHandle.cs index 9980c82..7638c8b 100644 --- a/src/mscorlib/src/System/Threading/WaitHandle.cs +++ b/src/mscorlib/src/System/Threading/WaitHandle.cs @@ -27,12 +27,8 @@ namespace System.Threading using System.Diagnostics.CodeAnalysis; using Win32Native = Microsoft.Win32.Win32Native; -[System.Runtime.InteropServices.ComVisible(true)] -#if FEATURE_REMOTING + [System.Runtime.InteropServices.ComVisible(true)] public abstract class WaitHandle : MarshalByRefObject, IDisposable { -#else // FEATURE_REMOTING - public abstract class WaitHandle : IDisposable { -#endif // FEATURE_REMOTING public const int WaitTimeout = 0x102; private const int MAX_WAITHANDLES = 64; @@ -41,12 +37,10 @@ namespace System.Threading private IntPtr waitHandle; // !!! DO NOT MOVE THIS FIELD. (See defn of WAITHANDLEREF in object.h - has hardcoded access to this field.) #pragma warning restore 414 - [System.Security.SecurityCritical] // auto-generated internal volatile SafeWaitHandle safeWaitHandle; internal bool hasThreadAffinity; - [System.Security.SecuritySafeCritical] // auto-generated private static IntPtr GetInvalidHandle() { return Win32Native.INVALID_HANDLE_VALUE; @@ -70,7 +64,6 @@ namespace System.Threading Init(); } - [System.Security.SecuritySafeCritical] // auto-generated private void Init() { safeWaitHandle = null; @@ -82,13 +75,7 @@ namespace System.Threading [Obsolete("Use the SafeWaitHandle property instead.")] public virtual IntPtr Handle { - [System.Security.SecuritySafeCritical] // auto-generated get { return safeWaitHandle == null ? InvalidHandle : safeWaitHandle.DangerousGetHandle();} - - [System.Security.SecurityCritical] // auto-generated_required -#if !FEATURE_CORECLR - [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] -#endif set { if (value == InvalidHandle) @@ -113,13 +100,8 @@ namespace System.Threading } } - public SafeWaitHandle SafeWaitHandle { - [System.Security.SecurityCritical] // auto-generated_required -#if !FEATURE_CORECLR - [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] -#endif [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] get { @@ -129,11 +111,7 @@ namespace System.Threading } return safeWaitHandle; } - - [System.Security.SecurityCritical] // auto-generated_required -#if !FEATURE_CORECLR - [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] -#endif + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] set { @@ -168,7 +146,6 @@ namespace System.Threading // FileStream, which will then call Sethandle, which requires a link time // security check.). While security has fixed that problem, we still // don't need to do a linktime check here. - [System.Security.SecurityCritical] // auto-generated internal void SetHandleInternal(SafeWaitHandle handle) { safeWaitHandle = handle; @@ -179,7 +156,7 @@ namespace System.Threading { if (millisecondsTimeout < -1) { - throw new ArgumentOutOfRangeException("millisecondsTimeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); } Contract.EndContractBlock(); return WaitOne((long)millisecondsTimeout,exitContext); @@ -190,7 +167,7 @@ namespace System.Threading long tm = (long)timeout.TotalMilliseconds; if (-1 > tm || (long) Int32.MaxValue < tm) { - throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(timeout), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); } return WaitOne(tm,exitContext); } @@ -211,14 +188,12 @@ namespace System.Threading return WaitOne(timeout, false); } - [System.Security.SecuritySafeCritical] // auto-generated [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread-safety.")] private bool WaitOne(long timeout, bool exitContext) { return InternalWaitOne(safeWaitHandle, timeout, hasThreadAffinity, exitContext); } - [System.Security.SecurityCritical] // auto-generated internal static bool InternalWaitOne(SafeHandle waitableSafeHandle, long millisecondsTimeout, bool hasThreadAffinity, bool exitContext) { if (waitableSafeHandle == null) @@ -238,7 +213,6 @@ namespace System.Threading return (ret != WaitTimeout); } - [System.Security.SecurityCritical] internal bool WaitOneWithoutFAS() { // version of waitone without fast application switch (FAS) support @@ -258,7 +232,6 @@ namespace System.Threading return (ret != WaitTimeout); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern int WaitOneNative(SafeHandle waitableSafeHandle, uint millisecondsTimeout, bool hasThreadAffinity, bool exitContext); @@ -271,17 +244,15 @@ namespace System.Threading ** (if in a synchronized context) is exited before the wait and reacquired ========================================================================*/ - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] private static extern int WaitMultiple(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext, bool WaitAll); - [System.Security.SecuritySafeCritical] // auto-generated public static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext) { if (waitHandles == null) { - throw new ArgumentNullException("waitHandles", Environment.GetResourceString("ArgumentNull_Waithandles")); + throw new ArgumentNullException(nameof(waitHandles), Environment.GetResourceString("ArgumentNull_Waithandles")); } if(waitHandles.Length == 0) { @@ -294,11 +265,7 @@ namespace System.Threading // in CoreCLR, and ArgumentNullException in the desktop CLR. This is ugly, but so is breaking // user code. // -#if FEATURE_CORECLR throw new ArgumentException(Environment.GetResourceString("Argument_EmptyWaithandleArray")); -#else - throw new ArgumentNullException("waitHandles", Environment.GetResourceString("Argument_EmptyWaithandleArray")); -#endif } if (waitHandles.Length > MAX_WAITHANDLES) { @@ -306,7 +273,7 @@ namespace System.Threading } if (-1 > millisecondsTimeout) { - throw new ArgumentOutOfRangeException("millisecondsTimeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); } Contract.EndContractBlock(); WaitHandle[] internalWaitHandles = new WaitHandle[waitHandles.Length]; @@ -317,11 +284,6 @@ namespace System.Threading if (waitHandle == null) throw new ArgumentNullException("waitHandles[" + i + "]", Environment.GetResourceString("ArgumentNull_ArrayElement")); -#if FEATURE_REMOTING - if (RemotingServices.IsTransparentProxy(waitHandle)) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WaitOnTransparentProxy")); -#endif - internalWaitHandles[i] = waitHandle; } #if _DEBUG @@ -354,7 +316,7 @@ namespace System.Threading long tm = (long)timeout.TotalMilliseconds; if (-1 > tm || (long) Int32.MaxValue < tm) { - throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(timeout), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); } return WaitAll(waitHandles,(int)tm, exitContext); } @@ -388,13 +350,12 @@ namespace System.Threading ** (if in a synchronized context) is exited before the wait and reacquired ========================================================================*/ - [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext) { if (waitHandles==null) { - throw new ArgumentNullException("waitHandles", Environment.GetResourceString("ArgumentNull_Waithandles")); + throw new ArgumentNullException(nameof(waitHandles), Environment.GetResourceString("ArgumentNull_Waithandles")); } if(waitHandles.Length == 0) { @@ -406,7 +367,7 @@ namespace System.Threading } if (-1 > millisecondsTimeout) { - throw new ArgumentOutOfRangeException("millisecondsTimeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); } Contract.EndContractBlock(); WaitHandle[] internalWaitHandles = new WaitHandle[waitHandles.Length]; @@ -417,11 +378,6 @@ namespace System.Threading if (waitHandle == null) throw new ArgumentNullException("waitHandles[" + i + "]", Environment.GetResourceString("ArgumentNull_ArrayElement")); -#if FEATURE_REMOTING - if (RemotingServices.IsTransparentProxy(waitHandle)) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WaitOnTransparentProxy")); -#endif - internalWaitHandles[i] = waitHandle; } #if _DEBUG @@ -459,7 +415,7 @@ namespace System.Threading long tm = (long)timeout.TotalMilliseconds; if (-1 > tm || (long) Int32.MaxValue < tm) { - throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(timeout), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); } return WaitAny(waitHandles,(int)tm, exitContext); } @@ -491,7 +447,6 @@ namespace System.Threading == ==================================================*/ - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern int SignalAndWaitOne(SafeWaitHandle waitHandleToSignal,SafeWaitHandle waitHandleToWaitOn, int millisecondsTimeout, bool hasThreadAffinity, bool exitContext); @@ -519,13 +474,12 @@ namespace System.Threading long tm = (long)timeout.TotalMilliseconds; if (-1 > tm || (long) Int32.MaxValue < tm) { - throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(timeout), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); } return SignalAndWait(toSignal,toWaitOn,(int)tm,exitContext); #endif } - [System.Security.SecuritySafeCritical] // auto-generated [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread-safety.")] public static bool SignalAndWait( WaitHandle toSignal, @@ -538,15 +492,15 @@ namespace System.Threading #else if(null == toSignal) { - throw new ArgumentNullException("toSignal"); + throw new ArgumentNullException(nameof(toSignal)); } if(null == toWaitOn) { - throw new ArgumentNullException("toWaitOn"); + throw new ArgumentNullException(nameof(toWaitOn)); } if (-1 > millisecondsTimeout) { - throw new ArgumentOutOfRangeException("millisecondsTimeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); + throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); } Contract.EndContractBlock(); @@ -554,14 +508,6 @@ namespace System.Threading int ret = SignalAndWaitOne(toSignal.safeWaitHandle,toWaitOn.safeWaitHandle,millisecondsTimeout, toWaitOn.hasThreadAffinity,exitContext); -#if !FEATURE_CORECLR - if(WAIT_FAILED != ret && toSignal.hasThreadAffinity) - { - Thread.EndCriticalRegion(); - Thread.EndThreadAffinity(); - } -#endif - if(WAIT_ABANDONED == ret) { ThrowAbandonedMutexException(); @@ -599,7 +545,6 @@ namespace System.Threading GC.SuppressFinalize(this); } - [System.Security.SecuritySafeCritical] // auto-generated protected virtual void Dispose(bool explicitDisposing) { if (safeWaitHandle != null) diff --git a/src/mscorlib/src/System/Threading/WaitHandleCannotBeOpenedException.cs b/src/mscorlib/src/System/Threading/WaitHandleCannotBeOpenedException.cs index f873057..68445a7 100644 --- a/src/mscorlib/src/System/Threading/WaitHandleCannotBeOpenedException.cs +++ b/src/mscorlib/src/System/Threading/WaitHandleCannotBeOpenedException.cs @@ -12,11 +12,7 @@ namespace System.Threading [Serializable] [ComVisibleAttribute(false)] -#if FEATURE_CORECLR - public class WaitHandleCannotBeOpenedException : Exception { -#else public class WaitHandleCannotBeOpenedException : ApplicationException { -#endif // FEATURE_CORECLR public WaitHandleCannotBeOpenedException() : base(Environment.GetResourceString("Threading.WaitHandleCannotBeOpenedException")) { SetErrorCode(__HResults.COR_E_WAITHANDLECANNOTBEOPENED); diff --git a/src/mscorlib/src/System/Threading/WaitHandleExtensions.cs b/src/mscorlib/src/System/Threading/WaitHandleExtensions.cs deleted file mode 100644 index 76c3feb..0000000 --- a/src/mscorlib/src/System/Threading/WaitHandleExtensions.cs +++ /dev/null @@ -1,46 +0,0 @@ -// 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 Microsoft.Win32.SafeHandles; -using System.Security; - -namespace System.Threading -{ - public static class WaitHandleExtensions - { - /// - /// Gets the native operating system handle. - /// - /// The to operate on. - /// A representing the native operating system handle. - [SecurityCritical] - public static SafeWaitHandle GetSafeWaitHandle(this WaitHandle waitHandle) - { - if (waitHandle == null) - { - throw new ArgumentNullException("waitHandle"); - } - - return waitHandle.SafeWaitHandle; - } - - /// - /// Sets the native operating system handle - /// - /// The to operate on. - /// A representing the native operating system handle. - [SecurityCritical] - public static void SetSafeWaitHandle(this WaitHandle waitHandle, SafeWaitHandle value) - { - if (waitHandle == null) - { - throw new ArgumentNullException("waitHandle"); - } - - waitHandle.SafeWaitHandle = value; - } - } -} diff --git a/src/mscorlib/src/System/ThrowHelper.cs b/src/mscorlib/src/System/ThrowHelper.cs index 3105d56..a534dec 100644 --- a/src/mscorlib/src/System/ThrowHelper.cs +++ b/src/mscorlib/src/System/ThrowHelper.cs @@ -10,7 +10,7 @@ namespace System { // The old way to throw an exception generates quite a lot IL code and assembly code. // Following is an example: // C# source - // throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key")); + // throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key")); // IL code: // IL_0003: ldstr "key" // IL_0008: ldstr "ArgumentNull_Key" @@ -39,112 +39,206 @@ namespace System { using Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.Serialization; + using System.Diagnostics; using System.Diagnostics.Contracts; [Pure] internal static class ThrowHelper { +#if FEATURE_SPAN_OF_T + internal static void ThrowArrayTypeMismatchException() { + throw new ArrayTypeMismatchException(); + } + + internal static void ThrowInvalidTypeWithPointersNotSupported(Type targetType) { + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidTypeWithPointersNotSupported", targetType)); + } + + internal static void ThrowIndexOutOfRangeException() { + throw new IndexOutOfRangeException(); + } + + internal static void ThrowArgumentOutOfRangeException() { + throw new ArgumentOutOfRangeException(); + } + + internal static void ThrowArgumentException_DestinationTooShort() { + throw new ArgumentException(Environment.GetResourceString("Argument_DestinationTooShort")); + } + + internal static void ThrowNotSupportedException_CannotCallEqualsOnSpan() { + throw new NotSupportedException(Environment.GetResourceString("NotSupported_CannotCallEqualsOnSpan")); + } + + internal static void ThrowNotSupportedException_CannotCallGetHashCodeOnSpan() { + throw new NotSupportedException(Environment.GetResourceString("NotSupported_CannotCallGetHashCodeOnSpan")); + } +#endif + internal static void ThrowArgumentOutOfRange_IndexException() { - throw new ArgumentOutOfRangeException(GetArgumentName(ExceptionArgument.index), - Environment.GetResourceString(GetResourceName(ExceptionResource.ArgumentOutOfRange_Index))); + throw GetArgumentOutOfRangeException(ExceptionArgument.index, + ExceptionResource.ArgumentOutOfRange_Index); } internal static void ThrowIndexArgumentOutOfRange_NeedNonNegNumException() { - throw new ArgumentOutOfRangeException( - GetArgumentName(ExceptionArgument.index), - Environment.GetResourceString(GetResourceName(ExceptionResource.ArgumentOutOfRange_NeedNonNegNum))); + throw GetArgumentOutOfRangeException(ExceptionArgument.index, + ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + + internal static void ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum() { + throw GetArgumentOutOfRangeException(ExceptionArgument.length, + ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + + internal static void ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index() { + throw GetArgumentOutOfRangeException(ExceptionArgument.startIndex, + ExceptionResource.ArgumentOutOfRange_Index); + } + + internal static void ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count() { + throw GetArgumentOutOfRangeException(ExceptionArgument.count, + ExceptionResource.ArgumentOutOfRange_Count); } internal static void ThrowWrongKeyTypeArgumentException(object key, Type targetType) { - throw new ArgumentException(Environment.GetResourceString("Arg_WrongType", key, targetType), "key"); + throw GetWrongKeyTypeArgumentException(key, targetType); } internal static void ThrowWrongValueTypeArgumentException(object value, Type targetType) { - throw new ArgumentException(Environment.GetResourceString("Arg_WrongType", value, targetType), "value"); + throw GetWrongValueTypeArgumentException(value, targetType); + } + + private static ArgumentException GetAddingDuplicateWithKeyArgumentException(object key) { + return new ArgumentException(Environment.GetResourceString("Argument_AddingDuplicateWithKey", key)); } -#if FEATURE_CORECLR internal static void ThrowAddingDuplicateWithKeyArgumentException(object key) { - throw new ArgumentException(Environment.GetResourceString("Argument_AddingDuplicateWithKey", key)); + throw GetAddingDuplicateWithKeyArgumentException(key); } -#endif internal static void ThrowKeyNotFoundException() { throw new System.Collections.Generic.KeyNotFoundException(); } internal static void ThrowArgumentException(ExceptionResource resource) { - throw new ArgumentException(Environment.GetResourceString(GetResourceName(resource))); + throw GetArgumentException(resource); } internal static void ThrowArgumentException(ExceptionResource resource, ExceptionArgument argument) { - throw new ArgumentException(Environment.GetResourceString(GetResourceName(resource)), GetArgumentName(argument)); + throw GetArgumentException(resource, argument); } internal static void ThrowArgumentNullException(ExceptionArgument argument) { throw new ArgumentNullException(GetArgumentName(argument)); } + internal static void ThrowArgumentNullException(ExceptionResource resource) { + throw new ArgumentNullException(GetResourceString(resource)); + } + internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument) { throw new ArgumentOutOfRangeException(GetArgumentName(argument)); } internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource) { - throw new ArgumentOutOfRangeException(GetArgumentName(argument), - Environment.GetResourceString(GetResourceName(resource))); + throw GetArgumentOutOfRangeException(argument, resource); } internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument, int paramNumber, ExceptionResource resource) { - throw new ArgumentOutOfRangeException(GetArgumentName(argument) + "[" + paramNumber.ToString() + "]", - Environment.GetResourceString(GetResourceName(resource))); + throw GetArgumentOutOfRangeException(argument, paramNumber, resource); } internal static void ThrowInvalidOperationException(ExceptionResource resource) { - throw new InvalidOperationException(Environment.GetResourceString(GetResourceName(resource))); + throw GetInvalidOperationException(resource); } internal static void ThrowInvalidOperationException(ExceptionResource resource, Exception e) { - throw new InvalidOperationException(Environment.GetResourceString(GetResourceName(resource)), e); + throw new InvalidOperationException(GetResourceString(resource), e); } internal static void ThrowSerializationException(ExceptionResource resource) { - throw new SerializationException(Environment.GetResourceString(GetResourceName(resource))); + throw new SerializationException(GetResourceString(resource)); } internal static void ThrowSecurityException(ExceptionResource resource) { - throw new System.Security.SecurityException(Environment.GetResourceString(GetResourceName(resource))); + throw new System.Security.SecurityException(GetResourceString(resource)); } internal static void ThrowRankException(ExceptionResource resource) { - throw new RankException(Environment.GetResourceString(GetResourceName(resource))); + throw new RankException(GetResourceString(resource)); } internal static void ThrowNotSupportedException(ExceptionResource resource) { - throw new NotSupportedException(Environment.GetResourceString(GetResourceName(resource))); + throw new NotSupportedException(GetResourceString(resource)); } internal static void ThrowUnauthorizedAccessException(ExceptionResource resource) { - throw new UnauthorizedAccessException(Environment.GetResourceString(GetResourceName(resource))); + throw new UnauthorizedAccessException(GetResourceString(resource)); } internal static void ThrowObjectDisposedException(string objectName, ExceptionResource resource) { - throw new ObjectDisposedException(objectName, Environment.GetResourceString(GetResourceName(resource))); + throw new ObjectDisposedException(objectName, GetResourceString(resource)); } - internal static void ThrowObjectDisposedException(ExceptionResource resource) - { - throw new ObjectDisposedException(null, Environment.GetResourceString(GetResourceName(resource))); + internal static void ThrowObjectDisposedException(ExceptionResource resource) { + throw new ObjectDisposedException(null, GetResourceString(resource)); } - internal static void ThrowNotSupportedException() - { + internal static void ThrowNotSupportedException() { throw new NotSupportedException(); } - internal static void ThrowAggregateException(List exceptions) - { + internal static void ThrowAggregateException(List exceptions) { throw new AggregateException(exceptions); } + internal static void ThrowArgumentException_Argument_InvalidArrayType() { + throw GetArgumentException(ExceptionResource.Argument_InvalidArrayType); + } + + internal static void ThrowInvalidOperationException_InvalidOperation_EnumNotStarted() { + throw GetInvalidOperationException(ExceptionResource.InvalidOperation_EnumNotStarted); + } + + internal static void ThrowInvalidOperationException_InvalidOperation_EnumEnded() { + throw GetInvalidOperationException(ExceptionResource.InvalidOperation_EnumEnded); + } + + internal static void ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion() { + throw GetInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); + } + + internal static void ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen() { + throw GetInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen); + } + + private static ArgumentException GetArgumentException(ExceptionResource resource) { + return new ArgumentException(GetResourceString(resource)); + } + + private static InvalidOperationException GetInvalidOperationException(ExceptionResource resource) { + return new InvalidOperationException(GetResourceString(resource)); + } + + private static ArgumentException GetWrongKeyTypeArgumentException(object key, Type targetType) { + return new ArgumentException(Environment.GetResourceString("Arg_WrongType", key, targetType), nameof(key)); + } + + private static ArgumentException GetWrongValueTypeArgumentException(object value, Type targetType) { + return new ArgumentException(Environment.GetResourceString("Arg_WrongType", value, targetType), nameof(value)); + } + + private static ArgumentOutOfRangeException GetArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource) { + return new ArgumentOutOfRangeException(GetArgumentName(argument), GetResourceString(resource)); + } + + private static ArgumentException GetArgumentException(ExceptionResource resource, ExceptionArgument argument) { + return new ArgumentException(GetResourceString(resource), GetArgumentName(argument)); + } + + private static ArgumentOutOfRangeException GetArgumentOutOfRangeException(ExceptionArgument argument, int paramNumber, ExceptionResource resource) { + return new ArgumentOutOfRangeException(GetArgumentName(argument) + "[" + paramNumber.ToString() + "]", GetResourceString(resource)); + } + // Allow nulls for reference types and Nullable, but not for value types. // Aggressively inline so the jit evaluates the if in place and either drops the call altogether // Or just leaves null test and call to the Non-returning ThrowHelper.ThrowArgumentNullException @@ -155,26 +249,43 @@ namespace System { ThrowHelper.ThrowArgumentNullException(argName); } - // // This function will convert an ExceptionArgument enum value to the argument name string. - // - internal static string GetArgumentName(ExceptionArgument argument) { - Contract.Assert(Enum.IsDefined(typeof(ExceptionArgument), argument), + private static string GetArgumentName(ExceptionArgument argument) { + // This is indirected through a second NoInlining function it has a special meaning + // in System.Private.CoreLib of indicatating it takes a StackMark which cause + // the caller to also be not inlined; so we can't mark it directly. + // So is the effect of marking this function as non-inlining in a regular situation. + return GetArgumentNameInner(argument); + } + + // This function will convert an ExceptionArgument enum value to the argument name string. + // Second function in chain so as to not propergate the non-inlining to outside caller + [MethodImpl(MethodImplOptions.NoInlining)] + private static string GetArgumentNameInner(ExceptionArgument argument) { + Debug.Assert(Enum.IsDefined(typeof(ExceptionArgument), argument), "The enum value is not defined, please check the ExceptionArgument Enum."); return argument.ToString(); } - // // This function will convert an ExceptionResource enum value to the resource string. - // - internal static string GetResourceName(ExceptionResource resource) { - Contract.Assert(Enum.IsDefined(typeof(ExceptionResource), resource), + private static string GetResourceString(ExceptionResource resource) { + // This is indirected through a second NoInlining function it has a special meaning + // in System.Private.CoreLib of indicatating it takes a StackMark which cause + // the caller to also be not inlined; so we can't mark it directly. + // So is the effect of marking this function as non-inlining in a regular situation. + return GetResourceStringInner(resource); + } + + // This function will convert an ExceptionResource enum value to the resource string. + // Second function in chain so as to not propergate the non-inlining to outside caller + [MethodImpl(MethodImplOptions.NoInlining)] + private static string GetResourceStringInner(ExceptionResource resource) { + Debug.Assert(Enum.IsDefined(typeof(ExceptionResource), resource), "The enum value is not defined, please check the ExceptionResource Enum."); - return resource.ToString(); + return Environment.GetResourceString(resource.ToString()); } - } // @@ -247,6 +358,11 @@ namespace System { beginMethod, continuationOptions, continuationAction, + valueFactory, + addValueFactory, + updateValueFactory, + concurrencyLevel, + text, } @@ -341,6 +457,17 @@ namespace System { TaskCompletionSourceT_TrySetException_NullException, TaskCompletionSourceT_TrySetException_NoExceptions, InvalidOperation_WrongAsyncResultOrEndCalledMultiple, + ConcurrentDictionary_ConcurrencyLevelMustBePositive, + ConcurrentDictionary_CapacityMustNotBeNegative, + ConcurrentDictionary_TypeOfValueIncorrect, + ConcurrentDictionary_TypeOfKeyIncorrect, + ConcurrentDictionary_SourceContainsDuplicateKeys, + ConcurrentDictionary_KeyAlreadyExisted, + ConcurrentDictionary_ItemKeyIsNull, + ConcurrentDictionary_IndexIsNegative, + ConcurrentDictionary_ArrayNotLargeEnough, + ConcurrentDictionary_ArrayIncorrectType, + ConcurrentCollection_SyncRoot_NotSupported, } } diff --git a/src/mscorlib/src/System/TimeSpan.cs b/src/mscorlib/src/System/TimeSpan.cs index c9cfc08..a594da2 100644 --- a/src/mscorlib/src/System/TimeSpan.cs +++ b/src/mscorlib/src/System/TimeSpan.cs @@ -28,7 +28,7 @@ namespace System { // details of this type should change, or new fields added, we need to remember to add // an appropriate custom ILMarshaler to keep WInRT interop scenarios enabled. // -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] [Serializable] public struct TimeSpan : IComparable , IComparable, IEquatable, IFormattable { @@ -289,11 +289,11 @@ namespace System { return TimeSpanParse.ParseExactMultiple(input, formats, formatProvider, TimeSpanStyles.None); } public static TimeSpan ParseExact(String input, String format, IFormatProvider formatProvider, TimeSpanStyles styles) { - TimeSpanParse.ValidateStyles(styles, "styles"); + TimeSpanParse.ValidateStyles(styles, nameof(styles)); return TimeSpanParse.ParseExact(input, format, formatProvider, styles); } public static TimeSpan ParseExact(String input, String[] formats, IFormatProvider formatProvider, TimeSpanStyles styles) { - TimeSpanParse.ValidateStyles(styles, "styles"); + TimeSpanParse.ValidateStyles(styles, nameof(styles)); return TimeSpanParse.ParseExactMultiple(input, formats, formatProvider, styles); } public static Boolean TryParse(String s, out TimeSpan result) { @@ -309,11 +309,11 @@ namespace System { return TimeSpanParse.TryParseExactMultiple(input, formats, formatProvider, TimeSpanStyles.None, out result); } public static Boolean TryParseExact(String input, String format, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result) { - TimeSpanParse.ValidateStyles(styles, "styles"); + TimeSpanParse.ValidateStyles(styles, nameof(styles)); return TimeSpanParse.TryParseExact(input, format, formatProvider, styles, out result); } public static Boolean TryParseExact(String input, String[] formats, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result) { - TimeSpanParse.ValidateStyles(styles, "styles"); + TimeSpanParse.ValidateStyles(styles, nameof(styles)); return TimeSpanParse.TryParseExactMultiple(input, formats, formatProvider, styles, out result); } public override String ToString() { @@ -406,26 +406,8 @@ namespace System { // [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework] // "TimeSpan_LegacyFormatMode"=dword:00000001 // -#if !FEATURE_CORECLR - [System.Security.SecurityCritical] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern bool LegacyFormatMode(); -#endif // !FEATURE_CORECLR - // - // In Silverlight v4, specifying the APP_EARLIER_THAN_SL4.0 quirks mode allows applications to - // run in v2 - v3 legacy behavior. - // -#if !FEATURE_CORECLR - [System.Security.SecuritySafeCritical] -#endif private static bool GetLegacyFormatMode() { -#if !FEATURE_CORECLR - if (LegacyFormatMode()) // FCALL to check COMPlus_TimeSpan_LegacyFormatMode - return true; - return CompatibilitySwitches.IsNetFx40TimeSpanLegacyFormatMode; -#else return false; -#endif // !FEATURE_CORECLR } private static volatile bool _legacyConfigChecked; diff --git a/src/mscorlib/src/System/TimeZone.cs b/src/mscorlib/src/System/TimeZone.cs index 602e86a..c0a369f 100644 --- a/src/mscorlib/src/System/TimeZone.cs +++ b/src/mscorlib/src/System/TimeZone.cs @@ -26,10 +26,8 @@ namespace System { using System.Globalization; [Serializable] -[System.Runtime.InteropServices.ComVisible(true)] -#if FEATURE_CORECLR + [System.Runtime.InteropServices.ComVisible(true)] [Obsolete("System.TimeZone has been deprecated. Please investigate the use of System.TimeZoneInfo instead.")] -#endif public abstract class TimeZone { private static volatile TimeZone currentTimeZone = null; diff --git a/src/mscorlib/src/System/TimeZoneInfo.cs b/src/mscorlib/src/System/TimeZoneInfo.cs index a9d194a..72fc28f 100644 --- a/src/mscorlib/src/System/TimeZoneInfo.cs +++ b/src/mscorlib/src/System/TimeZoneInfo.cs @@ -49,22 +49,18 @@ namespace System { NoThrowOnInvalidTime = 2 }; - [Serializable] [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] -#if !FEATURE_CORECLR - [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] -#endif sealed public class TimeZoneInfo : IEquatable, ISerializable, IDeserializationCallback { // ---- SECTION: members supporting exposed properties -------------* - private String m_id; - private String m_displayName; - private String m_standardDisplayName; - private String m_daylightDisplayName; - private TimeSpan m_baseUtcOffset; - private Boolean m_supportsDaylightSavingTime; - private AdjustmentRule[] m_adjustmentRules; + private readonly String m_id; + private readonly String m_displayName; + private readonly String m_standardDisplayName; + private readonly String m_daylightDisplayName; + private readonly TimeSpan m_baseUtcOffset; + private readonly Boolean m_supportsDaylightSavingTime; + private readonly AdjustmentRule[] m_adjustmentRules; // ---- SECTION: members for internal support ---------* private enum TimeZoneInfoResult { @@ -115,6 +111,8 @@ namespace System { private const long c_ticksPerDay = c_ticksPerHour * 24; private const long c_ticksPerDayRange = c_ticksPerDay - c_ticksPerMillisecond; + private static readonly TimeZoneInfo s_utcTimeZone = CreateCustomTimeZone(c_utcId, TimeSpan.Zero, c_utcId, c_utcId); + // // All cached data are encapsulated in a helper class to allow consistent view even when the data are refreshed using ClearCachedData() // @@ -125,7 +123,6 @@ namespace System { class CachedData { private volatile TimeZoneInfo m_localTimeZone; - private volatile TimeZoneInfo m_utcTimeZone; private TimeZoneInfo CreateLocal() { @@ -163,31 +160,6 @@ namespace System { } } - private TimeZoneInfo CreateUtc() - { - lock (this) - { - TimeZoneInfo timeZone = m_utcTimeZone; - if (timeZone == null) { - timeZone = CreateCustomTimeZone(c_utcId, TimeSpan.Zero, c_utcId, c_utcId); - m_utcTimeZone = timeZone; - } - return timeZone; - } - } - - public TimeZoneInfo Utc { - get { - Contract.Ensures(Contract.Result() != null); - - TimeZoneInfo timeZone = m_utcTimeZone; - if (timeZone == null) { - timeZone = CreateUtc(); - } - return timeZone; - } - } - // // GetCorrespondingKind- // @@ -215,7 +187,7 @@ namespace System { // in this example. Only when the user passes in TimeZoneInfo.Local or // TimeZoneInfo.Utc to the ConvertTime(...) methods will this check succeed. // - if ((object)timeZone == (object)m_utcTimeZone) { + if ((object)timeZone == (object)s_utcTimeZone) { kind = DateTimeKind.Utc; } else if ((object)timeZone == (object)m_localTimeZone) { @@ -233,7 +205,6 @@ namespace System { public bool m_allSystemTimeZonesRead; #if FEATURE_WIN32_REGISTRY - [System.Security.SecuritySafeCritical] private static TimeZoneInfo GetCurrentOneYearLocal() { // load the data from the OS TimeZoneInfo match; @@ -319,24 +290,58 @@ namespace System { } } +#if PLATFORM_UNIX + // The rules we use in Unix cares mostly about the start and end dates but doesn’t fill the transition start and end info. + // as the rules now is public, we should fill it properly so the caller doesn’t have to know how we use it internally + // and can use it as it is used in Windows - // ---- SECTION: public methods --------------* + private AdjustmentRule[] GetFilledRules() + { + Debug.Assert(m_adjustmentRules != null, "m_adjustmentRules expected to be not null"); + AdjustmentRule[] rules = new AdjustmentRule[m_adjustmentRules.Length]; + + for (int i = 0; i < m_adjustmentRules.Length; i++) + { + var rule = m_adjustmentRules[i]; + var start = rule.DateStart.Kind == DateTimeKind.Utc ? + new DateTime(TimeZoneInfo.ConvertTime(rule.DateStart, this).Ticks, DateTimeKind.Unspecified) : + rule.DateStart; + var end = rule.DateEnd.Kind == DateTimeKind.Utc ? + new DateTime(TimeZoneInfo.ConvertTime(rule.DateEnd, this).Ticks - 1, DateTimeKind.Unspecified) : + rule.DateEnd; + + var startTransition = TimeZoneInfo.TransitionTime.CreateFixedDateRule(new DateTime(1, 1, 1, start.Hour, start.Minute, start.Second), start.Month, start.Day); + var endTransition = TimeZoneInfo.TransitionTime.CreateFixedDateRule(new DateTime(1, 1, 1, end.Hour, end.Minute, end.Second), end.Month, end.Day); + + rules[i] = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(start.Date, end.Date, rule.DaylightDelta, startTransition, endTransition); + } + + return rules; + } +#endif // PLATFORM_UNIX + // ---- SECTION: public methods --------------* // // GetAdjustmentRules - // // returns a cloned array of AdjustmentRule objects // - public AdjustmentRule [] GetAdjustmentRules() { - if (m_adjustmentRules == null) { - return new AdjustmentRule[0]; + public AdjustmentRule [] GetAdjustmentRules() + { + if (m_adjustmentRules == null) + { + return Array.Empty(); } - else { - return (AdjustmentRule[])m_adjustmentRules.Clone(); + else + { +#if PLATFORM_UNIX + return GetFilledRules(); +#else + return (AdjustmentRule[]) m_adjustmentRules.Clone(); +#endif // PLATFORM_UNIX } } - // // GetAmbiguousTimeOffsets - // @@ -345,7 +350,7 @@ namespace System { // public TimeSpan[] GetAmbiguousTimeOffsets(DateTimeOffset dateTimeOffset) { if (!SupportsDaylightSavingTime) { - throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeOffsetIsNotAmbiguous"), "dateTimeOffset"); + throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeOffsetIsNotAmbiguous"), nameof(dateTimeOffset)); } Contract.EndContractBlock(); @@ -354,12 +359,12 @@ namespace System { Boolean isAmbiguous = false; AdjustmentRule rule = GetAdjustmentRuleForAmbiguousOffsets(adjustedTime); if (rule != null && rule.HasDaylightSaving) { - DaylightTime daylightTime = GetDaylightTime(adjustedTime.Year, rule); + DaylightTimeStruct daylightTime = GetDaylightTime(adjustedTime.Year, rule); isAmbiguous = GetIsAmbiguousTime(adjustedTime, rule, daylightTime); } if (!isAmbiguous) { - throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeOffsetIsNotAmbiguous"), "dateTimeOffset"); + throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeOffsetIsNotAmbiguous"), nameof(dateTimeOffset)); } // the passed in dateTime is ambiguous in this TimeZoneInfo instance @@ -382,7 +387,7 @@ namespace System { public TimeSpan[] GetAmbiguousTimeOffsets(DateTime dateTime) { if (!SupportsDaylightSavingTime) { - throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeIsNotAmbiguous"), "dateTime"); + throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeIsNotAmbiguous"), nameof(dateTime)); } Contract.EndContractBlock(); @@ -393,7 +398,7 @@ namespace System { } else if (dateTime.Kind == DateTimeKind.Utc) { CachedData cachedData = s_cachedData; - adjustedTime = TimeZoneInfo.ConvertTime(dateTime, cachedData.Utc, this, TimeZoneInfoOptions.None, cachedData); + adjustedTime = TimeZoneInfo.ConvertTime(dateTime, s_utcTimeZone, this, TimeZoneInfoOptions.None, cachedData); } else { adjustedTime = dateTime; @@ -402,12 +407,12 @@ namespace System { Boolean isAmbiguous = false; AdjustmentRule rule = GetAdjustmentRuleForAmbiguousOffsets(adjustedTime); if (rule != null && rule.HasDaylightSaving) { - DaylightTime daylightTime = GetDaylightTime(adjustedTime.Year, rule); + DaylightTimeStruct daylightTime = GetDaylightTime(adjustedTime.Year, rule); isAmbiguous = GetIsAmbiguousTime(adjustedTime, rule, daylightTime); } if (!isAmbiguous) { - throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeIsNotAmbiguous"), "dateTime"); + throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeIsNotAmbiguous"), nameof(dateTime)); } // the passed in dateTime is ambiguous in this TimeZoneInfo instance @@ -491,7 +496,7 @@ namespace System { // // normal case of converting from Local to Utc and then getting the offset from the UTC DateTime // - DateTime adjustedTime = TimeZoneInfo.ConvertTime(dateTime, cachedData.Local, cachedData.Utc, flags); + DateTime adjustedTime = TimeZoneInfo.ConvertTime(dateTime, cachedData.Local, s_utcTimeZone, flags); return GetUtcOffsetFromUtc(adjustedTime, this); } @@ -558,7 +563,7 @@ namespace System { } else if (dateTime.Kind == DateTimeKind.Utc) { CachedData cachedData = s_cachedData; - adjustedTime = TimeZoneInfo.ConvertTime(dateTime, cachedData.Utc, this, flags, cachedData); + adjustedTime = TimeZoneInfo.ConvertTime(dateTime, s_utcTimeZone, this, flags, cachedData); } else { adjustedTime = dateTime; @@ -566,7 +571,7 @@ namespace System { AdjustmentRule rule = GetAdjustmentRuleForTime(adjustedTime); if (rule != null && rule.HasDaylightSaving) { - DaylightTime daylightTime = GetDaylightTime(adjustedTime.Year, rule); + DaylightTimeStruct daylightTime = GetDaylightTime(adjustedTime.Year, rule); return GetIsAmbiguousTime(adjustedTime, rule, daylightTime); } return false; @@ -644,7 +649,7 @@ namespace System { // AdjustmentRule rule = GetAdjustmentRuleForTime(adjustedTime); if (rule != null && rule.HasDaylightSaving) { - DaylightTime daylightTime = GetDaylightTime(adjustedTime.Year, rule); + DaylightTimeStruct daylightTime = GetDaylightTime(adjustedTime.Year, rule); return GetIsDaylightSavings(adjustedTime, rule, daylightTime, flags); } else { @@ -668,7 +673,7 @@ namespace System { AdjustmentRule rule = GetAdjustmentRuleForTime(dateTime); if (rule != null && rule.HasDaylightSaving) { - DaylightTime daylightTime = GetDaylightTime(dateTime.Year, rule); + DaylightTimeStruct daylightTime = GetDaylightTime(dateTime.Year, rule); isInvalid = GetIsInvalidTime(dateTime, rule, daylightTime); } else { @@ -690,22 +695,25 @@ namespace System { s_cachedData = new CachedData(); } -#if FEATURE_WIN32_REGISTRY // // ConvertTimeBySystemTimeZoneId - // // Converts the value of a DateTime object from sourceTimeZone to destinationTimeZone // - static public DateTimeOffset ConvertTimeBySystemTimeZoneId(DateTimeOffset dateTimeOffset, String destinationTimeZoneId) { + static public DateTimeOffset ConvertTimeBySystemTimeZoneId(DateTimeOffset dateTimeOffset, String destinationTimeZoneId) + { return ConvertTime(dateTimeOffset, FindSystemTimeZoneById(destinationTimeZoneId)); } - static public DateTime ConvertTimeBySystemTimeZoneId(DateTime dateTime, String destinationTimeZoneId) { + static public DateTime ConvertTimeBySystemTimeZoneId(DateTime dateTime, String destinationTimeZoneId) + { return ConvertTime(dateTime, FindSystemTimeZoneById(destinationTimeZoneId)); } - static public DateTime ConvertTimeBySystemTimeZoneId(DateTime dateTime, String sourceTimeZoneId, String destinationTimeZoneId) { - if (dateTime.Kind == DateTimeKind.Local && String.Compare(sourceTimeZoneId, TimeZoneInfo.Local.Id, StringComparison.OrdinalIgnoreCase) == 0) { + static public DateTime ConvertTimeBySystemTimeZoneId(DateTime dateTime, String sourceTimeZoneId, String destinationTimeZoneId) + { + if (dateTime.Kind == DateTimeKind.Local && String.Compare(sourceTimeZoneId, TimeZoneInfo.Local.Id, StringComparison.OrdinalIgnoreCase) == 0) + { // TimeZoneInfo.Local can be cleared by another thread calling TimeZoneInfo.ClearCachedData. // Take snapshot of cached data to guarantee this method will not be impacted by the ClearCachedData call. // Without the snapshot, there is a chance that ConvertTime will throw since 'source' won't @@ -714,21 +722,21 @@ namespace System { CachedData cachedData = s_cachedData; return ConvertTime(dateTime, cachedData.Local, FindSystemTimeZoneById(destinationTimeZoneId), TimeZoneInfoOptions.None, cachedData); } - else if (dateTime.Kind == DateTimeKind.Utc && String.Compare(sourceTimeZoneId, TimeZoneInfo.Utc.Id, StringComparison.OrdinalIgnoreCase) == 0) { + else if (dateTime.Kind == DateTimeKind.Utc && String.Compare(sourceTimeZoneId, TimeZoneInfo.Utc.Id, StringComparison.OrdinalIgnoreCase) == 0) + { // TimeZoneInfo.Utc can be cleared by another thread calling TimeZoneInfo.ClearCachedData. // Take snapshot of cached data to guarantee this method will not be impacted by the ClearCachedData call. // Without the snapshot, there is a chance that ConvertTime will throw since 'source' won't // be reference equal to the new TimeZoneInfo.Utc // CachedData cachedData = s_cachedData; - return ConvertTime(dateTime, cachedData.Utc, FindSystemTimeZoneById(destinationTimeZoneId), TimeZoneInfoOptions.None, cachedData); + return ConvertTime(dateTime, s_utcTimeZone, FindSystemTimeZoneById(destinationTimeZoneId), TimeZoneInfoOptions.None, cachedData); } - else { + else + { return ConvertTime(dateTime, FindSystemTimeZoneById(sourceTimeZoneId), FindSystemTimeZoneById(destinationTimeZoneId)); } } -#endif // FEATURE_WIN32_REGISTRY - // // ConvertTime - @@ -738,7 +746,7 @@ namespace System { static public DateTimeOffset ConvertTime(DateTimeOffset dateTimeOffset, TimeZoneInfo destinationTimeZone) { if (destinationTimeZone == null) { - throw new ArgumentNullException("destinationTimeZone"); + throw new ArgumentNullException(nameof(destinationTimeZone)); } Contract.EndContractBlock(); @@ -762,7 +770,7 @@ namespace System { static public DateTime ConvertTime(DateTime dateTime, TimeZoneInfo destinationTimeZone) { if (destinationTimeZone == null) { - throw new ArgumentNullException("destinationTimeZone"); + throw new ArgumentNullException(nameof(destinationTimeZone)); } Contract.EndContractBlock(); @@ -772,7 +780,7 @@ namespace System { } CachedData cachedData = s_cachedData; if (dateTime.Kind == DateTimeKind.Utc) { - return ConvertTime(dateTime, cachedData.Utc, destinationTimeZone, TimeZoneInfoOptions.None, cachedData); + return ConvertTime(dateTime, s_utcTimeZone, destinationTimeZone, TimeZoneInfoOptions.None, cachedData); } else { return ConvertTime(dateTime, cachedData.Local, destinationTimeZone, TimeZoneInfoOptions.None, cachedData); @@ -790,17 +798,17 @@ namespace System { static private DateTime ConvertTime(DateTime dateTime, TimeZoneInfo sourceTimeZone, TimeZoneInfo destinationTimeZone, TimeZoneInfoOptions flags, CachedData cachedData) { if (sourceTimeZone == null) { - throw new ArgumentNullException("sourceTimeZone"); + throw new ArgumentNullException(nameof(sourceTimeZone)); } if (destinationTimeZone == null) { - throw new ArgumentNullException("destinationTimeZone"); + throw new ArgumentNullException(nameof(destinationTimeZone)); } Contract.EndContractBlock(); DateTimeKind sourceKind = cachedData.GetCorrespondingKind(sourceTimeZone); if ( ((flags & TimeZoneInfoOptions.NoThrowOnInvalidTime) == 0) && (dateTime.Kind != DateTimeKind.Unspecified) && (dateTime.Kind != sourceKind) ) { - throw new ArgumentException(Environment.GetResourceString("Argument_ConvertMismatch"), "sourceTimeZone"); + throw new ArgumentException(Environment.GetResourceString("Argument_ConvertMismatch"), nameof(sourceTimeZone)); } // @@ -818,12 +826,12 @@ namespace System { sourceOffset = sourceOffset + sourceRule.BaseUtcOffsetDelta; if (sourceRule.HasDaylightSaving) { Boolean sourceIsDaylightSavings = false; - DaylightTime sourceDaylightTime = sourceTimeZone.GetDaylightTime(dateTime.Year, sourceRule); + DaylightTimeStruct sourceDaylightTime = sourceTimeZone.GetDaylightTime(dateTime.Year, sourceRule); // 'dateTime' might be in an invalid time range since it is in an AdjustmentRule // period that supports DST if (((flags & TimeZoneInfoOptions.NoThrowOnInvalidTime) == 0) && GetIsInvalidTime(dateTime, sourceRule, sourceDaylightTime)) { - throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeIsInvalid"), "dateTime"); + throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeIsInvalid"), nameof(dateTime)); } sourceIsDaylightSavings = GetIsDaylightSavings(dateTime, sourceRule, sourceDaylightTime, flags); @@ -866,7 +874,7 @@ namespace System { // static public DateTime ConvertTimeFromUtc(DateTime dateTime, TimeZoneInfo destinationTimeZone) { CachedData cachedData = s_cachedData; - return ConvertTime(dateTime, cachedData.Utc, destinationTimeZone, TimeZoneInfoOptions.None, cachedData); + return ConvertTime(dateTime, s_utcTimeZone, destinationTimeZone, TimeZoneInfoOptions.None, cachedData); } @@ -880,7 +888,7 @@ namespace System { return dateTime; } CachedData cachedData = s_cachedData; - return ConvertTime(dateTime, cachedData.Local, cachedData.Utc, TimeZoneInfoOptions.None, cachedData); + return ConvertTime(dateTime, cachedData.Local, s_utcTimeZone, TimeZoneInfoOptions.None, cachedData); } @@ -889,12 +897,12 @@ namespace System { return dateTime; } CachedData cachedData = s_cachedData; - return ConvertTime(dateTime, cachedData.Local, cachedData.Utc, flags, cachedData); + return ConvertTime(dateTime, cachedData.Local, s_utcTimeZone, flags, cachedData); } static public DateTime ConvertTimeToUtc(DateTime dateTime, TimeZoneInfo sourceTimeZone) { CachedData cachedData = s_cachedData; - return ConvertTime(dateTime, sourceTimeZone, cachedData.Utc, TimeZoneInfoOptions.None, cachedData); + return ConvertTime(dateTime, sourceTimeZone, s_utcTimeZone, TimeZoneInfoOptions.None, cachedData); } @@ -909,11 +917,7 @@ namespace System { } public override bool Equals(object obj) { - TimeZoneInfo tzi = obj as TimeZoneInfo; - if (null == tzi) { - return false; - } - return Equals(tzi); + return Equals(obj as TimeZoneInfo); } // @@ -921,10 +925,10 @@ namespace System { // static public TimeZoneInfo FromSerializedString(string source) { if (source == null) { - throw new ArgumentNullException("source"); + throw new ArgumentNullException(nameof(source)); } if (source.Length == 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidSerializedString", source), "source"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidSerializedString", source), nameof(source)); } Contract.EndContractBlock(); @@ -936,7 +940,7 @@ namespace System { // GetHashCode - // public override int GetHashCode() { - return m_id.ToUpper(CultureInfo.InvariantCulture).GetHashCode(); + return StringComparer.OrdinalIgnoreCase.GetHashCode(m_id); } // @@ -952,7 +956,6 @@ namespace System { // // // - [System.Security.SecuritySafeCritical] // auto-generated static public ReadOnlyCollection GetSystemTimeZones() { CachedData cachedData = s_cachedData; @@ -973,7 +976,12 @@ namespace System { } // sort and copy the TimeZoneInfo's into a ReadOnlyCollection for the user - list.Sort(new TimeZoneInfoComparer()); + list.Sort((x, y) => + { + // sort by BaseUtcOffset first and by DisplayName second - this is similar to the Windows Date/Time control panel + int comparison = x.BaseUtcOffset.CompareTo(y.BaseUtcOffset); + return comparison == 0 ? string.CompareOrdinal(x.DisplayName, y.DisplayName) : comparison; + }); cachedData.m_readOnlySystemTimeZones = new ReadOnlyCollection(list); } @@ -981,26 +989,19 @@ namespace System { return cachedData.m_readOnlySystemTimeZones; } - [SecuritySafeCritical] private static void PopulateAllSystemTimeZones(CachedData cachedData) { #if FEATURE_WIN32_REGISTRY PermissionSet permSet = new PermissionSet(PermissionState.None); permSet.AddPermission(new RegistryPermission(RegistryPermissionAccess.Read, c_timeZonesRegistryHivePermissionList)); permSet.Assert(); - - using (RegistryKey reg = Registry.LocalMachine.OpenSubKey( - c_timeZonesRegistryHive, -#if FEATURE_MACL - RegistryKeyPermissionCheck.Default, - System.Security.AccessControl.RegistryRights.ReadKey -#else - false -#endif - )) { - if (reg != null) { - foreach (string keyName in reg.GetSubKeyNames()) { + using (RegistryKey reg = Registry.LocalMachine.OpenSubKey(c_timeZonesRegistryHive, false)) + { + if (reg != null) + { + foreach (string keyName in reg.GetSubKeyNames()) + { TimeZoneInfo value; Exception ex; TryGetTimeZone(keyName, false, out value, out ex, cachedData); // populate the cache @@ -1025,7 +1026,7 @@ namespace System { // public Boolean HasSameRules(TimeZoneInfo other) { if (other == null) { - throw new ArgumentNullException("other"); + throw new ArgumentNullException(nameof(other)); } // check the utcOffset and supportsDaylightSavingTime members @@ -1118,7 +1119,7 @@ namespace System { static public TimeZoneInfo Utc { get { Contract.Ensures(Contract.Result() != null); - return s_cachedData.Utc; + return s_utcTimeZone; } } @@ -1130,7 +1131,6 @@ namespace System { // private ctor // #if FEATURE_WIN32_REGISTRY - [System.Security.SecurityCritical] // auto-generated private TimeZoneInfo(Win32Native.TimeZoneInformation zone, Boolean dstDisabled) { if (String.IsNullOrEmpty(zone.StandardName)) { @@ -1262,16 +1262,13 @@ namespace System { Boolean adjustmentRulesSupportDst; ValidateTimeZoneInfo(id, baseUtcOffset, adjustmentRules, out adjustmentRulesSupportDst); - if (!disableDaylightSavingTime && adjustmentRules != null && adjustmentRules.Length > 0) { - m_adjustmentRules = (AdjustmentRule[])adjustmentRules.Clone(); - } - m_id = id; m_baseUtcOffset = baseUtcOffset; m_displayName = displayName; m_standardDisplayName = standardDisplayName; m_daylightDisplayName = (disableDaylightSavingTime ? null : daylightDisplayName); m_supportsDaylightSavingTime = adjustmentRulesSupportDst && !disableDaylightSavingTime; + m_adjustmentRules = adjustmentRules; } // -------- SECTION: factory methods -----------------* @@ -1312,7 +1309,7 @@ namespace System { String daylightDisplayName, AdjustmentRule [] adjustmentRules) { - return new TimeZoneInfo( + return CreateCustomTimeZone( id, baseUtcOffset, displayName, @@ -1341,7 +1338,11 @@ namespace System { AdjustmentRule [] adjustmentRules, Boolean disableDaylightSavingTime) { - return new TimeZoneInfo( + if (!disableDaylightSavingTime && adjustmentRules?.Length > 0) { + adjustmentRules = (AdjustmentRule[])adjustmentRules.Clone(); + } + + return new TimeZoneInfo( id, baseUtcOffset, displayName, @@ -1373,10 +1374,9 @@ namespace System { } - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); @@ -1392,7 +1392,7 @@ namespace System { TimeZoneInfo(SerializationInfo info, StreamingContext context) { if (info == null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } m_id = (String)info.GetValue("Id", typeof(String)); @@ -1554,7 +1554,6 @@ namespace System { // // This check is only meant to be used for "Local". // - [System.Security.SecurityCritical] // auto-generated static private Boolean CheckDaylightSavingTimeNotSupported(Win32Native.TimeZoneInformation timeZone) { return ( timeZone.DaylightDate.Year == timeZone.StandardDate.Year && timeZone.DaylightDate.Month == timeZone.StandardDate.Month @@ -1612,7 +1611,6 @@ namespace System { // // Converts a Win32Native.RegistryTimeZoneInformation (REG_TZI_FORMAT struct) to an AdjustmentRule // - [System.Security.SecurityCritical] // auto-generated static private AdjustmentRule CreateAdjustmentRuleFromTimeZoneInformation(Win32Native.RegistryTimeZoneInformation timeZoneInformation, DateTime startDate, DateTime endDate, int defaultBaseUtcOffset) { AdjustmentRule rule; bool supportsDst = (timeZoneInformation.StandardDate.Month != 0); @@ -1670,7 +1668,6 @@ namespace System { // Helper function that searches the registry for a time zone entry // that matches the TimeZoneInformation struct // - [System.Security.SecuritySafeCritical] // auto-generated static private String FindIdFromTimeZoneInformation(Win32Native.TimeZoneInformation timeZone, out Boolean dstDisabled) { dstDisabled = false; @@ -1679,21 +1676,16 @@ namespace System { permSet.AddPermission(new RegistryPermission(RegistryPermissionAccess.Read, c_timeZonesRegistryHivePermissionList)); permSet.Assert(); - using (RegistryKey key = Registry.LocalMachine.OpenSubKey( - c_timeZonesRegistryHive, -#if FEATURE_MACL - RegistryKeyPermissionCheck.Default, - System.Security.AccessControl.RegistryRights.ReadKey -#else - false -#endif - )) { - - if (key == null) { + using (RegistryKey key = Registry.LocalMachine.OpenSubKey(c_timeZonesRegistryHive, false)) + { + if (key == null) + { return null; } - foreach (string keyName in key.GetSubKeyNames()) { - if (TryCompareTimeZoneInformationToRegistry(timeZone, keyName, out dstDisabled)) { + foreach (string keyName in key.GetSubKeyNames()) + { + if (TryCompareTimeZoneInformationToRegistry(timeZone, keyName, out dstDisabled)) + { return keyName; } } @@ -1712,7 +1704,7 @@ namespace System { // // Helper function that returns a DaylightTime from a year and AdjustmentRule // - private DaylightTime GetDaylightTime(Int32 year, AdjustmentRule rule) { + private DaylightTimeStruct GetDaylightTime(Int32 year, AdjustmentRule rule) { TimeSpan delta = rule.DaylightDelta; DateTime startTime; DateTime endTime; @@ -1733,7 +1725,7 @@ namespace System { startTime = TransitionTimeToDateTime(year, rule.DaylightTransitionStart); endTime = TransitionTimeToDateTime(year, rule.DaylightTransitionEnd); } - return new DaylightTime(startTime, endTime, delta); + return new DaylightTimeStruct(startTime, endTime, delta); } // @@ -1742,7 +1734,7 @@ namespace System { // Helper function that checks if a given dateTime is in Daylight Saving Time (DST) // This function assumes the dateTime and AdjustmentRule are both in the same time zone // - static private Boolean GetIsDaylightSavings(DateTime time, AdjustmentRule rule, DaylightTime daylightTime, TimeZoneInfoOptions flags) { + static private Boolean GetIsDaylightSavings(DateTime time, AdjustmentRule rule, DaylightTimeStruct daylightTime, TimeZoneInfoOptions flags) { if (rule == null) { return false; } @@ -1837,7 +1829,7 @@ namespace System { // Get the daylight changes for the year of the specified time. - DaylightTime daylightTime = zone.GetDaylightTime(Year, rule); + DaylightTimeStruct daylightTime = zone.GetDaylightTime(Year, rule); // The start and end times represent the range of universal times that are in DST for that year. // Within that there is an ambiguous hour, usually right at the end, but at the beginning in @@ -1856,7 +1848,7 @@ namespace System { if (rule.IsStartDateMarkerForBeginningOfYear() && daylightTime.Start.Year > DateTime.MinValue.Year) { AdjustmentRule previousYearRule = zone.GetAdjustmentRuleForTime(new DateTime(daylightTime.Start.Year - 1, 12, 31)); if (previousYearRule != null && previousYearRule.IsEndDateMarkerForEndOfYear()) { - DaylightTime previousDaylightTime = zone.GetDaylightTime(daylightTime.Start.Year - 1, previousYearRule); + DaylightTimeStruct previousDaylightTime = zone.GetDaylightTime(daylightTime.Start.Year - 1, previousYearRule); startTime = previousDaylightTime.Start - utc - previousYearRule.BaseUtcOffsetDelta; ignoreYearAdjustment = true; } else { @@ -1874,7 +1866,7 @@ namespace System { if (nextYearRule.IsEndDateMarkerForEndOfYear()) {// next year end with daylight saving on too endTime = new DateTime(daylightTime.End.Year + 1, 12, 31) - utc - nextYearRule.BaseUtcOffsetDelta - nextYearRule.DaylightDelta; } else { - DaylightTime nextdaylightTime = zone.GetDaylightTime(daylightTime.End.Year + 1, nextYearRule); + DaylightTimeStruct nextdaylightTime = zone.GetDaylightTime(daylightTime.End.Year + 1, nextYearRule); endTime = nextdaylightTime.End - utc - nextYearRule.BaseUtcOffsetDelta - nextYearRule.DaylightDelta; } ignoreYearAdjustment = true; @@ -1980,7 +1972,7 @@ namespace System { // In this example, any DateTime values that fall into the [1AM - 1:59:59AM] range // are ambiguous; as it is unclear if these times are in Daylight Saving Time. // - static private Boolean GetIsAmbiguousTime(DateTime time, AdjustmentRule rule, DaylightTime daylightTime) { + static private Boolean GetIsAmbiguousTime(DateTime time, AdjustmentRule rule, DaylightTimeStruct daylightTime) { Boolean isAmbiguous = false; if (rule == null || rule.DaylightDelta == TimeSpan.Zero) { return isAmbiguous; @@ -2044,7 +2036,7 @@ namespace System { // A "time hole" is not limited to only occurring at the start of DST, and may occur at // the end of DST as well. // - static private Boolean GetIsInvalidTime(DateTime time, AdjustmentRule rule, DaylightTime daylightTime) { + static private Boolean GetIsInvalidTime(DateTime time, AdjustmentRule rule, DaylightTimeStruct daylightTime) { Boolean isInvalid = false; if (rule == null || rule.DaylightDelta == TimeSpan.Zero) { return isInvalid; @@ -2112,7 +2104,6 @@ namespace System { // assumes cachedData lock is taken // - [System.Security.SecuritySafeCritical] // auto-generated static private TimeZoneInfo GetLocalTimeZone(CachedData cachedData) { @@ -2280,7 +2271,6 @@ namespace System { /// 3. Look for the data in GetTimeZoneDirectory()/localtime. /// 4. Use UTC if all else fails. /// - [SecurityCritical] private static bool TryGetLocalTzFile(out byte[] rawData, out string id) { rawData = null; @@ -2360,7 +2350,6 @@ namespace System { /// Finds the time zone id by using 'readlink' on the path to see if tzFilePath is /// a symlink to a file /// - [SecuritySafeCritical] private static string FindTimeZoneIdUsingReadLink(string tzFilePath) { string id = null; @@ -2476,7 +2465,6 @@ namespace System { // // The TryGetLocalTzFile() call returns a Byte[] containing the compiled tzfile. // - [System.Security.SecurityCritical] static private TimeZoneInfo GetLocalTimeZoneFromTzFile() { byte[] rawData; @@ -2539,7 +2527,6 @@ namespace System { // try/catch logic for handling the TimeZoneInfo private constructor that takes // a Win32Native.TimeZoneInformation structure. // - [System.Security.SecurityCritical] // auto-generated static private TimeZoneInfo GetLocalTimeZoneFromWin32Data(Win32Native.TimeZoneInformation timeZoneInformation, Boolean dstDisabled) { // first try to create the TimeZoneInfo with the original 'dstDisabled' flag try { @@ -2582,7 +2569,7 @@ namespace System { } if (id == null) { - throw new ArgumentNullException("id"); + throw new ArgumentNullException(nameof(id)); } else if (!IsValidSystemTimeZoneId(id)) { throw new TimeZoneNotFoundException(Environment.GetResourceString("TimeZoneNotFound_MissingData", id)); @@ -2606,7 +2593,7 @@ namespace System { #if FEATURE_WIN32_REGISTRY throw new InvalidTimeZoneException(Environment.GetResourceString("InvalidTimeZone_InvalidRegistryData", id), e); #elif PLATFORM_UNIX - Contract.Assert(e is InvalidTimeZoneException, + Debug.Assert(e is InvalidTimeZoneException, "TryGetTimeZone must create an InvalidTimeZoneException when it returns TimeZoneInfoResult.InvalidTimeZoneException"); throw e; #endif @@ -2647,7 +2634,7 @@ namespace System { if (rule != null) { baseOffset = baseOffset + rule.BaseUtcOffsetDelta; if (rule.HasDaylightSaving) { - DaylightTime daylightTime = zone.GetDaylightTime(time.Year, rule); + DaylightTimeStruct daylightTime = zone.GetDaylightTime(time.Year, rule); Boolean isDaylightSavings = GetIsDaylightSavings(time, rule, daylightTime, flags); baseOffset += (isDaylightSavings ? rule.DaylightDelta : TimeSpan.Zero /* FUTURE: rule.StandardDelta */); } @@ -2719,7 +2706,7 @@ namespace System { // As we get the associated rule using the adjusted targetTime, we should use the adjusted year (targetTime.Year) too as after adding the baseOffset, // sometimes the year value can change if the input datetime was very close to the beginning or the end of the year. Examples of such cases: - // “Libya Standard Time” when used with the date 2011-12-31T23:59:59.9999999Z + // Libya Standard Time when used with the date 2011-12-31T23:59:59.9999999Z // "W. Australia Standard Time" used with date 2005-12-31T23:59:00.0000000Z DateTime targetTime = time + baseOffset; year = targetTime.Year; @@ -2745,7 +2732,6 @@ namespace System { // * when the argument 'readStart' is true the corresponding daylightTransitionTimeStart field is read // * when the argument 'readStart' is false the corresponding dayightTransitionTimeEnd field is read // - [System.Security.SecurityCritical] // auto-generated static private bool TransitionTimeFromTimeZoneInformation(Win32Native.RegistryTimeZoneInformation timeZoneInformation, out TransitionTime transitionTime, bool readStartDate) { // // SYSTEMTIME - @@ -2856,7 +2842,7 @@ namespace System { // // Helper function that converts a year and TransitionTime into a DateTime // - static private DateTime TransitionTimeToDateTime(Int32 year, TransitionTime transitionTime) { + internal static DateTime TransitionTimeToDateTime(Int32 year, TransitionTime transitionTime) { DateTime value; DateTime timeOfDay = transitionTime.TimeOfDay; @@ -2951,33 +2937,27 @@ namespace System { // // This method expects that its caller has already Asserted RegistryPermission.Read // - [System.Security.SecurityCritical] // auto-generated static private bool TryCreateAdjustmentRules(string id, Win32Native.RegistryTimeZoneInformation defaultTimeZoneInformation, out AdjustmentRule[] rules, out Exception e, int defaultBaseUtcOffset) { e = null; try { using (RegistryKey dynamicKey = Registry.LocalMachine.OpenSubKey( - String.Format(CultureInfo.InvariantCulture, "{0}\\{1}\\Dynamic DST", - c_timeZonesRegistryHive, id), -#if FEATURE_MACL - RegistryKeyPermissionCheck.Default, - System.Security.AccessControl.RegistryRights.ReadKey -#else - false -#endif - )) { + c_timeZonesRegistryHive + "\\" + id + "\\Dynamic DST", + false)) { if (dynamicKey == null) { AdjustmentRule rule = CreateAdjustmentRuleFromTimeZoneInformation( defaultTimeZoneInformation, DateTime.MinValue.Date, DateTime.MaxValue.Date, defaultBaseUtcOffset); - if (rule == null) { + if (rule == null) + { rules = null; } - else { + else + { rules = new AdjustmentRule[1]; rules[0] = rule; } - + return true; } @@ -2992,7 +2972,8 @@ namespace System { Int32 first = (Int32)dynamicKey.GetValue(c_firstEntryValue, -1, RegistryValueOptions.None); Int32 last = (Int32)dynamicKey.GetValue(c_lastEntryValue, -1, RegistryValueOptions.None); - if (first == -1 || last == -1 || first > last) { + if (first == -1 || last == -1 || first > last) + { rules = null; return false; } @@ -3000,20 +2981,24 @@ namespace System { // read the first year entry Win32Native.RegistryTimeZoneInformation dtzi; Byte[] regValue = dynamicKey.GetValue(first.ToString(CultureInfo.InvariantCulture), null, RegistryValueOptions.None) as Byte[]; - if (regValue == null || regValue.Length != c_regByteLength) { + if (regValue == null || regValue.Length != c_regByteLength) + { rules = null; return false; } dtzi = new Win32Native.RegistryTimeZoneInformation(regValue); - if (first == last) { + if (first == last) + { // there is just 1 dynamic rule for this time zone. - AdjustmentRule rule = CreateAdjustmentRuleFromTimeZoneInformation(dtzi, DateTime.MinValue.Date, DateTime.MaxValue.Date, defaultBaseUtcOffset); + AdjustmentRule rule = CreateAdjustmentRuleFromTimeZoneInformation(dtzi, DateTime.MinValue.Date, DateTime.MaxValue.Date, defaultBaseUtcOffset); - if (rule == null) { + if (rule == null) + { rules = null; } - else { + else + { rules = new AdjustmentRule[1]; rules[0] = rule; } @@ -3023,20 +3008,23 @@ namespace System { List rulesList = new List(1); - // there are more than 1 dynamic rules for this time zone. + // there are more than 1 dynamic rules for this time zone. AdjustmentRule firstRule = CreateAdjustmentRuleFromTimeZoneInformation( dtzi, DateTime.MinValue.Date, // MinValue new DateTime(first, 12, 31), // December 31, - defaultBaseUtcOffset); - if (firstRule != null) { + defaultBaseUtcOffset); + if (firstRule != null) + { rulesList.Add(firstRule); } // read the middle year entries - for (Int32 i = first + 1; i < last; i++) { + for (Int32 i = first + 1; i < last; i++) + { regValue = dynamicKey.GetValue(i.ToString(CultureInfo.InvariantCulture), null, RegistryValueOptions.None) as Byte[]; - if (regValue == null || regValue.Length != c_regByteLength) { + if (regValue == null || regValue.Length != c_regByteLength) + { rules = null; return false; } @@ -3046,14 +3034,16 @@ namespace System { new DateTime(i, 1, 1), // January 01, new DateTime(i, 12, 31), // December 31, defaultBaseUtcOffset); - if (middleRule != null) { + if (middleRule != null) + { rulesList.Add(middleRule); } } // read the last year entry regValue = dynamicKey.GetValue(last.ToString(CultureInfo.InvariantCulture), null, RegistryValueOptions.None) as Byte[]; dtzi = new Win32Native.RegistryTimeZoneInformation(regValue); - if (regValue == null || regValue.Length != c_regByteLength) { + if (regValue == null || regValue.Length != c_regByteLength) + { rules = null; return false; } @@ -3062,13 +3052,15 @@ namespace System { new DateTime(last, 1, 1), // January 01, DateTime.MaxValue.Date, // MaxValue defaultBaseUtcOffset); - if (lastRule != null) { + if (lastRule != null) + { rulesList.Add(lastRule); } // convert the ArrayList to an AdjustmentRule array rules = rulesList.ToArray(); - if (rules != null && rules.Length == 0) { + if (rules != null && rules.Length == 0) + { rules = null; } } // end of: using (RegistryKey dynamicKey... @@ -3098,7 +3090,6 @@ namespace System { // Helper function that compares the StandardBias and StandardDate portion a // TimeZoneInformation struct to a time zone registry entry // - [System.Security.SecurityCritical] // auto-generated static private Boolean TryCompareStandardDate(Win32Native.TimeZoneInformation timeZone, Win32Native.RegistryTimeZoneInformation registryTimeZoneInfo) { return timeZone.Bias == registryTimeZoneInfo.Bias && timeZone.StandardBias == registryTimeZoneInfo.StandardBias @@ -3117,9 +3108,8 @@ namespace System { // // Helper function that compares a TimeZoneInformation struct to a time zone registry entry // - [System.Security.SecuritySafeCritical] // auto-generated - static private Boolean TryCompareTimeZoneInformationToRegistry(Win32Native.TimeZoneInformation timeZone, string id, out Boolean dstDisabled) { - + static private Boolean TryCompareTimeZoneInformationToRegistry(Win32Native.TimeZoneInformation timeZone, string id, out Boolean dstDisabled) + { dstDisabled = false; try { PermissionSet permSet = new PermissionSet(PermissionState.None); @@ -3127,15 +3117,9 @@ namespace System { permSet.Assert(); using (RegistryKey key = Registry.LocalMachine.OpenSubKey( - String.Format(CultureInfo.InvariantCulture, "{0}\\{1}", - c_timeZonesRegistryHive, id), -#if FEATURE_MACL - RegistryKeyPermissionCheck.Default, - System.Security.AccessControl.RegistryRights.ReadKey -#else - false -#endif - )) { + c_timeZonesRegistryHive + "\\" + id, + false)) + { if (key == null) { return false; @@ -3152,7 +3136,8 @@ namespace System { // Boolean result = TryCompareStandardDate(timeZone, registryTimeZoneInfo); - if (!result) { + if (!result) + { return false; } @@ -3161,14 +3146,14 @@ namespace System { // since Daylight Saving Time is not "disabled", do a straight comparision between // the Win32 API data and the registry data ... // - ||( timeZone.DaylightBias == registryTimeZoneInfo.DaylightBias - && timeZone.DaylightDate.Year == registryTimeZoneInfo.DaylightDate.Year - && timeZone.DaylightDate.Month == registryTimeZoneInfo.DaylightDate.Month - && timeZone.DaylightDate.DayOfWeek == registryTimeZoneInfo.DaylightDate.DayOfWeek - && timeZone.DaylightDate.Day == registryTimeZoneInfo.DaylightDate.Day - && timeZone.DaylightDate.Hour == registryTimeZoneInfo.DaylightDate.Hour - && timeZone.DaylightDate.Minute == registryTimeZoneInfo.DaylightDate.Minute - && timeZone.DaylightDate.Second == registryTimeZoneInfo.DaylightDate.Second + || (timeZone.DaylightBias == registryTimeZoneInfo.DaylightBias + && timeZone.DaylightDate.Year == registryTimeZoneInfo.DaylightDate.Year + && timeZone.DaylightDate.Month == registryTimeZoneInfo.DaylightDate.Month + && timeZone.DaylightDate.DayOfWeek == registryTimeZoneInfo.DaylightDate.DayOfWeek + && timeZone.DaylightDate.Day == registryTimeZoneInfo.DaylightDate.Day + && timeZone.DaylightDate.Hour == registryTimeZoneInfo.DaylightDate.Hour + && timeZone.DaylightDate.Minute == registryTimeZoneInfo.DaylightDate.Minute + && timeZone.DaylightDate.Second == registryTimeZoneInfo.DaylightDate.Second && timeZone.DaylightDate.Milliseconds == registryTimeZoneInfo.DaylightDate.Milliseconds); // Finally compare the "StandardName" string value... @@ -3176,11 +3161,12 @@ namespace System { // we do not compare "DaylightName" as this TimeZoneInformation field may contain // either "StandardName" or "DaylightName" depending on the time of year and current machine settings // - if (result) { + if (result) + { String registryStandardName = key.GetValue(c_standardValue, String.Empty, RegistryValueOptions.None) as String; result = String.Compare(registryStandardName, timeZone.StandardName, StringComparison.Ordinal) == 0; } - return result; + return result; } } finally { @@ -3204,10 +3190,6 @@ namespace System { // // // - [System.Security.SecuritySafeCritical] // auto-generated -#if !FEATURE_CORECLR - [FileIOPermissionAttribute(SecurityAction.Assert, AllLocalFiles = FileIOPermissionAccess.PathDiscovery)] -#endif static private string TryGetLocalizedNameByMuiNativeResource(string resource) { if (String.IsNullOrEmpty(resource)) { return String.Empty; @@ -3277,7 +3259,6 @@ namespace System { // "resource.dll" is a language-specific resource DLL. // If the localized resource DLL exists, LoadString(resource) is returned. // - [SecurityCritical] static private string TryGetLocalizedNameByNativeResource(string filePath, int resource) { using (SafeLibraryHandle handle = UnsafeNativeMethods.LoadLibraryEx(filePath, IntPtr.Zero, Win32Native.LOAD_LIBRARY_AS_DATAFILE)) { @@ -3308,9 +3289,6 @@ namespace System { // // This method expects that its caller has already Asserted RegistryPermission.Read // -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif static private Boolean TryGetLocalizedNamesByRegistryKey(RegistryKey key, out String displayName, out String standardName, out String daylightName) { displayName = String.Empty; standardName = String.Empty; @@ -3387,7 +3365,6 @@ namespace System { // * TZI, REG_BINARY REG_TZI_FORMAT // See Win32Native.RegistryTimeZoneInformation // - [System.Security.SecuritySafeCritical] // auto-generated static private TimeZoneInfoResult TryGetTimeZoneByRegistryKey(string id, out TimeZoneInfo value, out Exception e) { e = null; @@ -3397,15 +3374,8 @@ namespace System { permSet.Assert(); using (RegistryKey key = Registry.LocalMachine.OpenSubKey( - String.Format(CultureInfo.InvariantCulture, "{0}\\{1}", - c_timeZonesRegistryHive, id), -#if FEATURE_MACL - RegistryKeyPermissionCheck.Default, - System.Security.AccessControl.RegistryRights.ReadKey -#else - false -#endif - )) { + c_timeZonesRegistryHive + "\\" + id, + false)) { if (key == null) { value = null; @@ -4204,7 +4174,6 @@ namespace System { // Converts an array of bytes into an int - always using standard byte order (Big Endian) // per TZif file standard - [System.Security.SecuritySafeCritical] // auto-generated static private unsafe int TZif_ToInt32 (byte[]value, int startIndex) { fixed( byte * pbyte = &value[startIndex]) { return (*pbyte << 24) | (*(pbyte + 1) << 16) | (*(pbyte + 2) << 8) | (*(pbyte + 3)); @@ -4213,7 +4182,6 @@ namespace System { // Converts an array of bytes into a long - always using standard byte order (Big Endian) // per TZif file standard - [System.Security.SecuritySafeCritical] // auto-generated static private unsafe long TZif_ToInt64(byte[] value, int startIndex) { fixed (byte* pbyte = &value[startIndex]) @@ -4386,20 +4354,20 @@ namespace System { out Boolean adjustmentRulesSupportDst) { if (id == null) { - throw new ArgumentNullException("id"); + throw new ArgumentNullException(nameof(id)); } if (id.Length == 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidId", id), "id"); + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidId", id), nameof(id)); } if (UtcOffsetOutOfRange(baseUtcOffset)) { - throw new ArgumentOutOfRangeException("baseUtcOffset", Environment.GetResourceString("ArgumentOutOfRange_UtcOffset")); + throw new ArgumentOutOfRangeException(nameof(baseUtcOffset), Environment.GetResourceString("ArgumentOutOfRange_UtcOffset")); } if (baseUtcOffset.Ticks % TimeSpan.TicksPerMinute != 0) { - throw new ArgumentException(Environment.GetResourceString("Argument_TimeSpanHasSeconds"), "baseUtcOffset"); + throw new ArgumentException(Environment.GetResourceString("Argument_TimeSpanHasSeconds"), nameof(baseUtcOffset)); } Contract.EndContractBlock(); @@ -4454,20 +4422,17 @@ namespace System { ============================================================*/ [Serializable] [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] -#if !FEATURE_CORECLR - [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] -#endif sealed public class AdjustmentRule : IEquatable, ISerializable, IDeserializationCallback { // ---- SECTION: members supporting exposed properties -------------* - private DateTime m_dateStart; - private DateTime m_dateEnd; - private TimeSpan m_daylightDelta; - private TransitionTime m_daylightTransitionStart; - private TransitionTime m_daylightTransitionEnd; - private TimeSpan m_baseUtcOffsetDelta; // delta from the default Utc offset (utcOffset = defaultUtcOffset + m_baseUtcOffsetDelta) - private bool m_noDaylightTransitions; + private readonly DateTime m_dateStart; + private readonly DateTime m_dateEnd; + private readonly TimeSpan m_daylightDelta; + private readonly TransitionTime m_daylightTransitionStart; + private readonly TransitionTime m_daylightTransitionEnd; + private readonly TimeSpan m_baseUtcOffsetDelta; // delta from the default Utc offset (utcOffset = defaultUtcOffset + m_baseUtcOffsetDelta) + private readonly bool m_noDaylightTransitions; // ---- SECTION: public properties --------------* public DateTime DateStart { @@ -4534,16 +4499,13 @@ namespace System { // IEquatable public bool Equals(AdjustmentRule other) { - bool equals = (other != null - && this.m_dateStart == other.m_dateStart - && this.m_dateEnd == other.m_dateEnd - && this.m_daylightDelta == other.m_daylightDelta - && this.m_baseUtcOffsetDelta == other.m_baseUtcOffsetDelta); - - equals = equals && this.m_daylightTransitionEnd.Equals(other.m_daylightTransitionEnd) - && this.m_daylightTransitionStart.Equals(other.m_daylightTransitionStart); - - return equals; + return other != null + && m_dateStart == other.m_dateStart + && m_dateEnd == other.m_dateEnd + && m_daylightDelta == other.m_daylightDelta + && m_baseUtcOffsetDelta == other.m_baseUtcOffsetDelta + && m_daylightTransitionEnd.Equals(other.m_daylightTransitionEnd) + && m_daylightTransitionStart.Equals(other.m_daylightTransitionStart); } @@ -4555,33 +4517,29 @@ namespace System { // -------- SECTION: constructors -----------------* - private AdjustmentRule() { } - - - // -------- SECTION: factory methods -----------------* - - static internal AdjustmentRule CreateAdjustmentRule( - DateTime dateStart, - DateTime dateEnd, - TimeSpan daylightDelta, - TransitionTime daylightTransitionStart, - TransitionTime daylightTransitionEnd, - bool noDaylightTransitions) { + private AdjustmentRule( + DateTime dateStart, + DateTime dateEnd, + TimeSpan daylightDelta, + TransitionTime daylightTransitionStart, + TransitionTime daylightTransitionEnd, + TimeSpan baseUtcOffsetDelta, + bool noDaylightTransitions) + { ValidateAdjustmentRule(dateStart, dateEnd, daylightDelta, daylightTransitionStart, daylightTransitionEnd, noDaylightTransitions); - AdjustmentRule rule = new AdjustmentRule(); + m_dateStart = dateStart; + m_dateEnd = dateEnd; + m_daylightDelta = daylightDelta; + m_daylightTransitionStart = daylightTransitionStart; + m_daylightTransitionEnd = daylightTransitionEnd; + m_baseUtcOffsetDelta = baseUtcOffsetDelta; + m_noDaylightTransitions = noDaylightTransitions; + } - rule.m_dateStart = dateStart; - rule.m_dateEnd = dateEnd; - rule.m_daylightDelta = daylightDelta; - rule.m_daylightTransitionStart = daylightTransitionStart; - rule.m_daylightTransitionEnd = daylightTransitionEnd; - rule.m_baseUtcOffsetDelta = TimeSpan.Zero; - rule.m_noDaylightTransitions = noDaylightTransitions; - return rule; - } + // -------- SECTION: factory methods -----------------* static public AdjustmentRule CreateAdjustmentRule( DateTime dateStart, @@ -4590,8 +4548,14 @@ namespace System { TransitionTime daylightTransitionStart, TransitionTime daylightTransitionEnd) { - return CreateAdjustmentRule(dateStart, dateEnd, daylightDelta, - daylightTransitionStart, daylightTransitionEnd, noDaylightTransitions: false); + return new AdjustmentRule( + dateStart, + dateEnd, + daylightDelta, + daylightTransitionStart, + daylightTransitionEnd, + baseUtcOffsetDelta: TimeSpan.Zero, + noDaylightTransitions: false); } static internal AdjustmentRule CreateAdjustmentRule( @@ -4601,12 +4565,16 @@ namespace System { TransitionTime daylightTransitionStart, TransitionTime daylightTransitionEnd, TimeSpan baseUtcOffsetDelta, - bool noDaylightTransitions) { - AdjustmentRule rule = CreateAdjustmentRule(dateStart, dateEnd, daylightDelta, - daylightTransitionStart, daylightTransitionEnd, noDaylightTransitions); - - rule.m_baseUtcOffsetDelta = baseUtcOffsetDelta; - return rule; + bool noDaylightTransitions) + { + return new AdjustmentRule( + dateStart, + dateEnd, + daylightDelta, + daylightTransitionStart, + daylightTransitionEnd, + baseUtcOffsetDelta, + noDaylightTransitions); } // ----- SECTION: internal utility methods ----------------* @@ -4649,21 +4617,21 @@ namespace System { if (dateStart.Kind != DateTimeKind.Unspecified && dateStart.Kind != DateTimeKind.Utc) { - throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeKindMustBeUnspecifiedOrUtc"), "dateStart"); + throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeKindMustBeUnspecifiedOrUtc"), nameof(dateStart)); } if (dateEnd.Kind != DateTimeKind.Unspecified && dateEnd.Kind != DateTimeKind.Utc) { - throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeKindMustBeUnspecifiedOrUtc"), "dateEnd"); + throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeKindMustBeUnspecifiedOrUtc"), nameof(dateEnd)); } if (daylightTransitionStart.Equals(daylightTransitionEnd) && !noDaylightTransitions) { throw new ArgumentException(Environment.GetResourceString("Argument_TransitionTimesAreIdentical"), - "daylightTransitionEnd"); + nameof(daylightTransitionEnd)); } if (dateStart > dateEnd) { - throw new ArgumentException(Environment.GetResourceString("Argument_OutOfOrderDateTimes"), "dateStart"); + throw new ArgumentException(Environment.GetResourceString("Argument_OutOfOrderDateTimes"), nameof(dateStart)); } // This cannot use UtcOffsetOutOfRange to account for the scenario where Samoa moved across the International Date Line, @@ -4671,23 +4639,23 @@ namespace System { // So when trying to describe DaylightDeltas for those times, the DaylightDelta needs // to be -23 (what it takes to go from UTC+13 to UTC-10) if (daylightDelta.TotalHours < -23.0 || daylightDelta.TotalHours > 14.0) { - throw new ArgumentOutOfRangeException("daylightDelta", daylightDelta, + throw new ArgumentOutOfRangeException(nameof(daylightDelta), daylightDelta, Environment.GetResourceString("ArgumentOutOfRange_UtcOffset")); } if (daylightDelta.Ticks % TimeSpan.TicksPerMinute != 0) { throw new ArgumentException(Environment.GetResourceString("Argument_TimeSpanHasSeconds"), - "daylightDelta"); + nameof(daylightDelta)); } if (dateStart != DateTime.MinValue && dateStart.Kind == DateTimeKind.Unspecified && dateStart.TimeOfDay != TimeSpan.Zero) { throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeHasTimeOfDay"), - "dateStart"); + nameof(dateStart)); } if (dateEnd != DateTime.MaxValue && dateEnd.Kind == DateTimeKind.Unspecified && dateEnd.TimeOfDay != TimeSpan.Zero) { throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeHasTimeOfDay"), - "dateEnd"); + nameof(dateEnd)); } Contract.EndContractBlock(); } @@ -4709,10 +4677,9 @@ namespace System { } } - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); @@ -4727,7 +4694,7 @@ namespace System { AdjustmentRule(SerializationInfo info, StreamingContext context) { if (info == null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } m_dateStart = (DateTime)info.GetValue("DateStart", typeof(DateTime)); @@ -4764,18 +4731,15 @@ namespace System { ============================================================*/ [Serializable] [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] -#if !FEATURE_CORECLR - [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] -#endif public struct TransitionTime : IEquatable, ISerializable, IDeserializationCallback { // ---- SECTION: members supporting exposed properties -------------* - private DateTime m_timeOfDay; - private byte m_month; - private byte m_week; - private byte m_day; - private DayOfWeek m_dayOfWeek; - private Boolean m_isFixedDateRule; + private readonly DateTime m_timeOfDay; + private readonly byte m_month; + private readonly byte m_week; + private readonly byte m_day; + private readonly DayOfWeek m_dayOfWeek; + private readonly Boolean m_isFixedDateRule; // ---- SECTION: public properties --------------* @@ -4859,16 +4823,24 @@ namespace System { // -------- SECTION: constructors -----------------* -/* - private TransitionTime() { - m_timeOfDay = new DateTime(); - m_month = 0; - m_week = 0; - m_day = 0; - m_dayOfWeek = DayOfWeek.Sunday; - m_isFixedDateRule = false; + + private TransitionTime( + DateTime timeOfDay, + Int32 month, + Int32 week, + Int32 day, + DayOfWeek dayOfWeek, + Boolean isFixedDateRule) + { + ValidateTransitionTime(timeOfDay, month, week, day, dayOfWeek); + + m_timeOfDay = timeOfDay; + m_month = (byte)month; + m_week = (byte)week; + m_day = (byte)day; + m_dayOfWeek = dayOfWeek; + m_isFixedDateRule = isFixedDateRule; } -*/ // -------- SECTION: factory methods -----------------* @@ -4879,7 +4851,7 @@ namespace System { Int32 month, Int32 day) { - return CreateTransitionTime(timeOfDay, month, 1, day, DayOfWeek.Sunday, true); + return new TransitionTime(timeOfDay, month, 1, day, DayOfWeek.Sunday, isFixedDateRule: true); } @@ -4889,29 +4861,7 @@ namespace System { Int32 week, DayOfWeek dayOfWeek) { - return CreateTransitionTime(timeOfDay, month, week, 1, dayOfWeek, false); - } - - - static private TransitionTime CreateTransitionTime( - DateTime timeOfDay, - Int32 month, - Int32 week, - Int32 day, - DayOfWeek dayOfWeek, - Boolean isFixedDateRule) { - - ValidateTransitionTime(timeOfDay, month, week, day, dayOfWeek); - - TransitionTime t = new TransitionTime(); - t.m_isFixedDateRule = isFixedDateRule; - t.m_timeOfDay = timeOfDay; - t.m_dayOfWeek = dayOfWeek; - t.m_day = (byte)day; - t.m_week = (byte)week; - t.m_month = (byte)month; - - return t; + return new TransitionTime(timeOfDay, month, week, 1, dayOfWeek, isFixedDateRule: false); } @@ -4930,33 +4880,33 @@ namespace System { DayOfWeek dayOfWeek) { if (timeOfDay.Kind != DateTimeKind.Unspecified) { - throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeKindMustBeUnspecified"), "timeOfDay"); + throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeKindMustBeUnspecified"), nameof(timeOfDay)); } // Month range 1-12 if (month < 1 || month > 12) { - throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_MonthParam")); + throw new ArgumentOutOfRangeException(nameof(month), Environment.GetResourceString("ArgumentOutOfRange_MonthParam")); } // Day range 1-31 if (day < 1 || day > 31) { - throw new ArgumentOutOfRangeException("day", Environment.GetResourceString("ArgumentOutOfRange_DayParam")); + throw new ArgumentOutOfRangeException(nameof(day), Environment.GetResourceString("ArgumentOutOfRange_DayParam")); } // Week range 1-5 if (week < 1 || week > 5) { - throw new ArgumentOutOfRangeException("week", Environment.GetResourceString("ArgumentOutOfRange_Week")); + throw new ArgumentOutOfRangeException(nameof(week), Environment.GetResourceString("ArgumentOutOfRange_Week")); } // DayOfWeek range 0-6 if ((int)dayOfWeek < 0 || (int)dayOfWeek > 6) { - throw new ArgumentOutOfRangeException("dayOfWeek", Environment.GetResourceString("ArgumentOutOfRange_DayOfWeek")); + throw new ArgumentOutOfRangeException(nameof(dayOfWeek), Environment.GetResourceString("ArgumentOutOfRange_DayOfWeek")); } Contract.EndContractBlock(); if (timeOfDay.Year != 1 || timeOfDay.Month != 1 || timeOfDay.Day != 1 || (timeOfDay.Ticks % TimeSpan.TicksPerMillisecond != 0)) { - throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeHasTicks"), "timeOfDay"); + throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeHasTicks"), nameof(timeOfDay)); } } @@ -4973,10 +4923,9 @@ namespace System { } - [System.Security.SecurityCritical] // auto-generated_required void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); @@ -4990,7 +4939,7 @@ namespace System { TransitionTime(SerializationInfo info, StreamingContext context) { if (info == null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } m_timeOfDay = (DateTime)info.GetValue("TimeOfDay", typeof(DateTime)); @@ -5125,7 +5074,7 @@ namespace System { AdjustmentRule[] rules = s.GetNextAdjustmentRuleArrayValue(false); try { - return TimeZoneInfo.CreateCustomTimeZone(id, baseUtcOffset, displayName, standardName, daylightName, rules); + return new TimeZoneInfo(id, baseUtcOffset, displayName, standardName, daylightName, rules, disableDaylightSavingTime: false); } catch (ArgumentException ex) { throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"), ex); @@ -5653,14 +5602,6 @@ namespace System { } } - private class TimeZoneInfoComparer : System.Collections.Generic.IComparer { - int System.Collections.Generic.IComparer.Compare(TimeZoneInfo x, TimeZoneInfo y) { - // sort by BaseUtcOffset first and by DisplayName second - this is similar to the Windows Date/Time control panel - int comparison = x.BaseUtcOffset.CompareTo(y.BaseUtcOffset); - return comparison == 0 ? String.Compare(x.DisplayName, y.DisplayName, StringComparison.Ordinal) : comparison; - } - } - #if PLATFORM_UNIX private struct TZifType { @@ -5681,7 +5622,7 @@ namespace System { { if (data == null || data.Length < index + c_len) { - throw new ArgumentException(Environment.GetResourceString("Argument_TimeZoneInfoInvalidTZif"), "data"); + throw new ArgumentException(Environment.GetResourceString("Argument_TimeZoneInfoInvalidTZif"), nameof(data)); } Contract.EndContractBlock(); UtcOffset = new TimeSpan(0, 0, TZif_ToInt32(data, index + 00)); @@ -5705,7 +5646,7 @@ namespace System { { if (data == null || data.Length < c_len) { - throw new ArgumentException("bad data", "data"); + throw new ArgumentException("bad data", nameof(data)); } Contract.EndContractBlock(); @@ -5714,7 +5655,7 @@ namespace System { if (Magic != 0x545A6966) { // 0x545A6966 = {0x54, 0x5A, 0x69, 0x66} = "TZif" - throw new ArgumentException(Environment.GetResourceString("Argument_TimeZoneInfoBadTZif"), "data"); + throw new ArgumentException(Environment.GetResourceString("Argument_TimeZoneInfoBadTZif"), nameof(data)); } byte version = data[index + 04]; diff --git a/src/mscorlib/src/System/TimeZoneNotFoundException.cs b/src/mscorlib/src/System/TimeZoneNotFoundException.cs index 5f8b919..cabcc15 100644 --- a/src/mscorlib/src/System/TimeZoneNotFoundException.cs +++ b/src/mscorlib/src/System/TimeZoneNotFoundException.cs @@ -7,9 +7,6 @@ namespace System { using System.Runtime.CompilerServices; [Serializable] -#if !FEATURE_CORECLR - [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] -#endif [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] public class TimeZoneNotFoundException : Exception { public TimeZoneNotFoundException(String message) diff --git a/src/mscorlib/src/System/Tuple.cs b/src/mscorlib/src/System/Tuple.cs index 99164bc..037b2ce 100644 --- a/src/mscorlib/src/System/Tuple.cs +++ b/src/mscorlib/src/System/Tuple.cs @@ -5,8 +5,13 @@ using System; using System.Text; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; +// +// Note: F# compiler depends on the exact tuple hashing algorithm. Do not ever change it. +// + namespace System { /// @@ -119,7 +124,7 @@ namespace System { Tuple objTuple = other as Tuple; if (objTuple == null) { - throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), "other"); + throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), nameof(other)); } return comparer.Compare(m_Item1, objTuple.m_Item1); @@ -195,7 +200,7 @@ namespace System { Tuple objTuple = other as Tuple; if (objTuple == null) { - throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), "other"); + throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), nameof(other)); } int c = 0; @@ -282,7 +287,7 @@ namespace System { Tuple objTuple = other as Tuple; if (objTuple == null) { - throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), "other"); + throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), nameof(other)); } int c = 0; @@ -378,7 +383,7 @@ namespace System { Tuple objTuple = other as Tuple; if (objTuple == null) { - throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), "other"); + throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), nameof(other)); } int c = 0; @@ -483,7 +488,7 @@ namespace System { Tuple objTuple = other as Tuple; if (objTuple == null) { - throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), "other"); + throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), nameof(other)); } int c = 0; @@ -597,7 +602,7 @@ namespace System { Tuple objTuple = other as Tuple; if (objTuple == null) { - throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), "other"); + throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), nameof(other)); } int c = 0; @@ -720,7 +725,7 @@ namespace System { Tuple objTuple = other as Tuple; if (objTuple == null) { - throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), "other"); + throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), nameof(other)); } int c = 0; @@ -856,7 +861,7 @@ namespace System { Tuple objTuple = other as Tuple; if (objTuple == null) { - throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), "other"); + throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), nameof(other)); } int c = 0; @@ -919,7 +924,7 @@ namespace System { case 7: return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5), comparer.GetHashCode(m_Item6), comparer.GetHashCode(m_Item7), t.GetHashCode(comparer)); } - Contract.Assert(false, "Missed all cases for computing Tuple hash code"); + Debug.Assert(false, "Missed all cases for computing Tuple hash code"); return -1; } diff --git a/src/mscorlib/src/System/Type.cs b/src/mscorlib/src/System/Type.cs index 7300033..2d30c4c 100644 --- a/src/mscorlib/src/System/Type.cs +++ b/src/mscorlib/src/System/Type.cs @@ -9,8 +9,8 @@ // // ====================================================================================== -namespace System { - +namespace System +{ using System; using System.Reflection; using System.Threading; @@ -154,7 +154,6 @@ namespace System { // param progID: the progID of the class to retrieve // returns: the class object associated to the progID //// - [System.Security.SecurityCritical] // auto-generated_required public static Type GetTypeFromProgID(String progID) { return RuntimeType.GetTypeFromProgIDImpl(progID, null, false); @@ -169,19 +168,16 @@ namespace System { // param progID: the progID of the class to retrieve // returns: the class object associated to the progID //// - [System.Security.SecurityCritical] // auto-generated_required public static Type GetTypeFromProgID(String progID, bool throwOnError) { return RuntimeType.GetTypeFromProgIDImpl(progID, null, throwOnError); } - [System.Security.SecurityCritical] // auto-generated_required public static Type GetTypeFromProgID(String progID, String server) { return RuntimeType.GetTypeFromProgIDImpl(progID, server, false); } - [System.Security.SecurityCritical] // auto-generated_required public static Type GetTypeFromProgID(String progID, String server, bool throwOnError) { return RuntimeType.GetTypeFromProgIDImpl(progID, server, throwOnError); @@ -194,25 +190,21 @@ namespace System { // param CLSID: the CLSID of the class to retrieve // returns: the class object associated to the CLSID //// - [System.Security.SecuritySafeCritical] // auto-generated public static Type GetTypeFromCLSID(Guid clsid) { return RuntimeType.GetTypeFromCLSIDImpl(clsid, null, false); } - [System.Security.SecuritySafeCritical] // auto-generated public static Type GetTypeFromCLSID(Guid clsid, bool throwOnError) { return RuntimeType.GetTypeFromCLSIDImpl(clsid, null, throwOnError); } - [System.Security.SecuritySafeCritical] // auto-generated public static Type GetTypeFromCLSID(Guid clsid, String server) { return RuntimeType.GetTypeFromCLSIDImpl(clsid, server, false); } - [System.Security.SecuritySafeCritical] // auto-generated public static Type GetTypeFromCLSID(Guid clsid, String server, bool throwOnError) { return RuntimeType.GetTypeFromCLSIDImpl(clsid, server, throwOnError); @@ -338,12 +330,10 @@ namespace System { } // Given a class handle, this will return the class for that handle. - [System.Security.SecurityCritical] [MethodImpl(MethodImplOptions.InternalCall)] internal static extern RuntimeType GetTypeFromHandleUnsafe(IntPtr handle); [Pure] - [System.Security.SecuritySafeCritical] // auto-generated [MethodImpl(MethodImplOptions.InternalCall)] public static extern Type GetTypeFromHandle(RuntimeTypeHandle handle); @@ -395,11 +385,11 @@ namespace System { { // Must provide some types (Type[0] for nothing) if (types == null) - throw new ArgumentNullException("types"); + throw new ArgumentNullException(nameof(types)); Contract.EndContractBlock(); for (int i=0;i assemblyResolver, @@ -79,7 +71,7 @@ namespace System ref StackCrawlMark stackMark) { if (typeName == null) - throw new ArgumentNullException("typeName"); + throw new ArgumentNullException(nameof(typeName)); if (typeName.Length > 0 && typeName[0] == '\0') throw new ArgumentException(Environment.GetResourceString("Format_StringZeroLength")); Contract.EndContractBlock(); @@ -103,19 +95,16 @@ namespace System #endregion #region Private Data Members - [SecurityCritical] private SafeTypeNameParserHandle m_NativeParser; private static readonly char[] SPECIAL_CHARS = {',', '[', ']', '&', '*', '+', '\\'}; /* see typeparse.h */ #endregion #region Constructor and Disposer - [SecuritySafeCritical] private TypeNameParser(SafeTypeNameParserHandle handle) { m_NativeParser = handle; } - [SecuritySafeCritical] public void Dispose() { m_NativeParser.Dispose(); @@ -123,7 +112,6 @@ namespace System #endregion #region private Members - [SecuritySafeCritical] private unsafe Type ConstructType( Func assemblyResolver, Func typeResolver, @@ -136,7 +124,7 @@ namespace System string asmName = GetAssemblyName(); // GetAssemblyName never returns null - Contract.Assert(asmName != null); + Debug.Assert(asmName != null); if (asmName.Length > 0) { @@ -164,7 +152,7 @@ namespace System if (baseType == null) { // Cannot resolve the type. If throwOnError is true we should have already thrown. - Contract.Assert(throwOnError == false); + Debug.Assert(throwOnError == false); return null; } @@ -176,7 +164,7 @@ namespace System types = new Type[typeArguments.Length]; for (int i = 0; i < typeArguments.Length; i++) { - Contract.Assert(typeArguments[i] != null); + Debug.Assert(typeArguments[i] != null); using (TypeNameParser argParser = new TypeNameParser(typeArguments[i])) { @@ -186,7 +174,7 @@ namespace System if (types[i] == null) { // If throwOnError is true argParser.ConstructType should have already thrown. - Contract.Assert(throwOnError == false); + Debug.Assert(throwOnError == false); return null; } } @@ -201,7 +189,6 @@ namespace System } } - [SecuritySafeCritical] private static Assembly ResolveAssembly(string asmName, Func assemblyResolver, bool throwOnError, ref StackCrawlMark stackMark) { Contract.Requires(asmName != null && asmName.Length > 0); @@ -316,7 +303,6 @@ namespace System return StringBuilderCache.GetStringAndRelease(sb); } - [SecuritySafeCritical] private static SafeTypeNameParserHandle CreateTypeNameParser(string typeName, bool throwOnError) { SafeTypeNameParserHandle retHandle = null; @@ -325,7 +311,6 @@ namespace System return retHandle; } - [SecuritySafeCritical] private string[] GetNames() { string[] names = null; @@ -334,7 +319,6 @@ namespace System return names; } - [SecuritySafeCritical] private SafeTypeNameParserHandle[] GetTypeArguments() { SafeTypeNameParserHandle[] arguments = null; @@ -343,7 +327,6 @@ namespace System return arguments; } - [SecuritySafeCritical] private int[] GetModifiers() { int[] modifiers = null; @@ -352,7 +335,6 @@ namespace System return modifiers; } - [SecuritySafeCritical] private string GetAssemblyName() { string assemblyName = null; diff --git a/src/mscorlib/src/System/TypedReference.cs b/src/mscorlib/src/System/TypedReference.cs index 7c68c41..b65652e 100644 --- a/src/mscorlib/src/System/TypedReference.cs +++ b/src/mscorlib/src/System/TypedReference.cs @@ -23,13 +23,12 @@ namespace System { private IntPtr Value; private IntPtr Type; - [System.Security.SecurityCritical] // auto-generated_required [CLSCompliant(false)] public static TypedReference MakeTypedReference(Object target, FieldInfo[] flds) { if (target == null) - throw new ArgumentNullException("target"); + throw new ArgumentNullException(nameof(target)); if (flds == null) - throw new ArgumentNullException("flds"); + throw new ArgumentNullException(nameof(flds)); Contract.EndContractBlock(); if (flds.Length == 0) throw new ArgumentException(Environment.GetResourceString("Arg_ArrayZeroError")); @@ -71,7 +70,6 @@ namespace System { return result; } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] // reference to TypedReference is banned, so have to pass result as pointer private unsafe static extern void InternalMakeTypedReference(void* result, Object target, IntPtr[] flds, RuntimeType lastFieldType); @@ -89,13 +87,11 @@ namespace System { throw new NotSupportedException(Environment.GetResourceString("NotSupported_NYI")); } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe static Object ToObject(TypedReference value) { return InternalToObject(&value); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal unsafe extern static Object InternalToObject(void * value); @@ -118,14 +114,12 @@ namespace System { } // This may cause the type to be changed. - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] public unsafe static void SetTypedReference(TypedReference target, Object value) { InternalSetTypedReference(&target, value); } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal unsafe extern static void InternalSetTypedReference(void * target, Object value); } diff --git a/src/mscorlib/src/System/UInt16.cs b/src/mscorlib/src/System/UInt16.cs index dba7f97..399ef02 100644 --- a/src/mscorlib/src/System/UInt16.cs +++ b/src/mscorlib/src/System/UInt16.cs @@ -68,26 +68,22 @@ namespace System { } // Converts the current value to a String in base-10 with no extra padding. - [System.Security.SecuritySafeCritical] // auto-generated public override String ToString() { Contract.Ensures(Contract.Result() != null); return Number.FormatUInt32(m_value, null, NumberFormatInfo.CurrentInfo); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(IFormatProvider provider) { Contract.Ensures(Contract.Result() != null); return Number.FormatUInt32(m_value, null, NumberFormatInfo.GetInstance(provider)); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(String format) { Contract.Ensures(Contract.Result() != null); return Number.FormatUInt32(m_value, format, NumberFormatInfo.CurrentInfo); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(String format, IFormatProvider provider) { Contract.Ensures(Contract.Result() != null); return Number.FormatUInt32(m_value, format, NumberFormatInfo.GetInstance(provider)); diff --git a/src/mscorlib/src/System/UInt32.cs b/src/mscorlib/src/System/UInt32.cs index 7010dae..f3d6009 100644 --- a/src/mscorlib/src/System/UInt32.cs +++ b/src/mscorlib/src/System/UInt32.cs @@ -79,25 +79,21 @@ namespace System { } // The base 10 representation of the number with no extra padding. - [System.Security.SecuritySafeCritical] // auto-generated public override String ToString() { Contract.Ensures(Contract.Result() != null); return Number.FormatUInt32(m_value, null, NumberFormatInfo.CurrentInfo); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(IFormatProvider provider) { Contract.Ensures(Contract.Result() != null); return Number.FormatUInt32(m_value, null, NumberFormatInfo.GetInstance(provider)); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(String format) { Contract.Ensures(Contract.Result() != null); return Number.FormatUInt32(m_value, format, NumberFormatInfo.CurrentInfo); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(String format, IFormatProvider provider) { Contract.Ensures(Contract.Result() != null); return Number.FormatUInt32(m_value, format, NumberFormatInfo.GetInstance(provider)); diff --git a/src/mscorlib/src/System/UInt64.cs b/src/mscorlib/src/System/UInt64.cs index 83549cf..b55cd7c 100644 --- a/src/mscorlib/src/System/UInt64.cs +++ b/src/mscorlib/src/System/UInt64.cs @@ -75,25 +75,21 @@ namespace System { return ((int)m_value) ^ (int)(m_value >> 32); } - [System.Security.SecuritySafeCritical] // auto-generated public override String ToString() { Contract.Ensures(Contract.Result() != null); return Number.FormatUInt64(m_value, null, NumberFormatInfo.CurrentInfo); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(IFormatProvider provider) { Contract.Ensures(Contract.Result() != null); return Number.FormatUInt64(m_value, null, NumberFormatInfo.GetInstance(provider)); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(String format) { Contract.Ensures(Contract.Result() != null); return Number.FormatUInt64(m_value, format, NumberFormatInfo.CurrentInfo); } - [System.Security.SecuritySafeCritical] // auto-generated public String ToString(String format, IFormatProvider provider) { Contract.Ensures(Contract.Result() != null); return Number.FormatUInt64(m_value, format, NumberFormatInfo.GetInstance(provider)); diff --git a/src/mscorlib/src/System/UIntPtr.cs b/src/mscorlib/src/System/UIntPtr.cs index ac3b811..eab424f 100644 --- a/src/mscorlib/src/System/UIntPtr.cs +++ b/src/mscorlib/src/System/UIntPtr.cs @@ -24,20 +24,17 @@ namespace System { [System.Runtime.InteropServices.ComVisible(true)] public struct UIntPtr : IEquatable, ISerializable { - [SecurityCritical] unsafe private void* m_value; public static readonly UIntPtr Zero; - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.Versioning.NonVersionable] public unsafe UIntPtr(uint value) { m_value = (void *)value; } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.Versioning.NonVersionable] public unsafe UIntPtr(ulong value) { @@ -48,7 +45,6 @@ namespace System { #endif } - [System.Security.SecurityCritical] [CLSCompliant(false)] [System.Runtime.Versioning.NonVersionable] public unsafe UIntPtr(void* value) @@ -56,7 +52,6 @@ namespace System { m_value = value; } - [System.Security.SecurityCritical] // auto-generated private unsafe UIntPtr(SerializationInfo info, StreamingContext context) { ulong l = info.GetUInt64("value"); @@ -67,17 +62,15 @@ namespace System { m_value = (void *)l; } - [System.Security.SecurityCritical] unsafe void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); info.AddValue("value", (ulong)m_value); } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe override bool Equals(Object obj) { if (obj is UIntPtr) { return (m_value == ((UIntPtr)obj).m_value); @@ -85,27 +78,20 @@ namespace System { return false; } - [SecuritySafeCritical] unsafe bool IEquatable.Equals(UIntPtr other) { return m_value == other.m_value; } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe override int GetHashCode() { -#if FEATURE_CORECLR #if BIT64 ulong l = (ulong)m_value; return (unchecked((int)l) ^ (int)(l >> 32)); #else // 32 return unchecked((int)m_value); #endif -#else - return unchecked((int)((long)m_value)) & 0x7fffffff; -#endif } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.Versioning.NonVersionable] public unsafe uint ToUInt32() { #if BIT64 @@ -115,13 +101,11 @@ namespace System { #endif } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.Versioning.NonVersionable] public unsafe ulong ToUInt64() { return (ulong)m_value; } - [System.Security.SecuritySafeCritical] // auto-generated public unsafe override String ToString() { Contract.Ensures(Contract.Result() != null); @@ -144,7 +128,6 @@ namespace System { return new UIntPtr(value); } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.Versioning.NonVersionable] public unsafe static explicit operator uint(UIntPtr value) { @@ -155,14 +138,12 @@ namespace System { #endif } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.Versioning.NonVersionable] public unsafe static explicit operator ulong (UIntPtr value) { return (ulong)value.m_value; } - [System.Security.SecurityCritical] [CLSCompliant(false)] [System.Runtime.Versioning.NonVersionable] public static unsafe explicit operator UIntPtr (void* value) @@ -170,7 +151,6 @@ namespace System { return new UIntPtr(value); } - [System.Security.SecurityCritical] [CLSCompliant(false)] [System.Runtime.Versioning.NonVersionable] public static unsafe explicit operator void* (UIntPtr value) @@ -179,7 +159,6 @@ namespace System { } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.Versioning.NonVersionable] public unsafe static bool operator == (UIntPtr value1, UIntPtr value2) { @@ -187,7 +166,6 @@ namespace System { } - [System.Security.SecuritySafeCritical] // auto-generated [System.Runtime.Versioning.NonVersionable] public unsafe static bool operator != (UIntPtr value1, UIntPtr value2) { @@ -235,7 +213,6 @@ namespace System { } } - [System.Security.SecuritySafeCritical] // auto-generated [CLSCompliant(false)] [System.Runtime.Versioning.NonVersionable] public unsafe void* ToPointer() diff --git a/src/mscorlib/src/System/UnSafeCharBuffer.cs b/src/mscorlib/src/System/UnSafeCharBuffer.cs deleted file mode 100644 index 78059b6..0000000 --- a/src/mscorlib/src/System/UnSafeCharBuffer.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -/*============================================================ -** -** -** Purpose: A class to detect incorrect usage of UnSafeBuffer -** -** -===========================================================*/ - -namespace System { - using System.Security; - using System.Diagnostics; - using System.Diagnostics.Contracts; - - unsafe internal struct UnSafeCharBuffer{ - [SecurityCritical] - char * m_buffer; - int m_totalSize; - int m_length; - - [System.Security.SecurityCritical] // auto-generated - public UnSafeCharBuffer( char *buffer, int bufferSize) { - Contract.Assert( buffer != null, "buffer pointer can't be null." ); - Contract.Assert( bufferSize >= 0, "buffer size can't be negative." ); - m_buffer = buffer; - m_totalSize = bufferSize; - m_length = 0; - } - - [System.Security.SecuritySafeCritical] // auto-generated - public void AppendString(string stringToAppend) { - if( String.IsNullOrEmpty( stringToAppend ) ) { - return; - } - - if ( (m_totalSize - m_length) < stringToAppend.Length ) { - throw new IndexOutOfRangeException(); - } - - fixed( char* pointerToString = stringToAppend ) { - Buffer.Memcpy( (byte*) (m_buffer + m_length), (byte *) pointerToString, stringToAppend.Length * sizeof(char)); - } - - m_length += stringToAppend.Length; - Contract.Assert(m_length <= m_totalSize, "Buffer has been overflowed!"); - } - - public int Length { - get { - return m_length; - } - } - } -} diff --git a/src/mscorlib/src/System/UnhandledExceptionEventHandler.cs b/src/mscorlib/src/System/UnhandledExceptionEventHandler.cs index 7d65319..8c27982 100644 --- a/src/mscorlib/src/System/UnhandledExceptionEventHandler.cs +++ b/src/mscorlib/src/System/UnhandledExceptionEventHandler.cs @@ -5,9 +5,6 @@ namespace System { using System; -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif [Serializable] [System.Runtime.InteropServices.ComVisible(true)] public delegate void UnhandledExceptionEventHandler(Object sender, UnhandledExceptionEventArgs e); diff --git a/src/mscorlib/src/System/UnitySerializationHolder.cs b/src/mscorlib/src/System/UnitySerializationHolder.cs index ec32fce..712391a 100644 --- a/src/mscorlib/src/System/UnitySerializationHolder.cs +++ b/src/mscorlib/src/System/UnitySerializationHolder.cs @@ -166,7 +166,7 @@ namespace System { internal UnitySerializationHolder(SerializationInfo info, StreamingContext context) { if (info == null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); m_unityType = info.GetInt32("UnityType"); @@ -204,7 +204,6 @@ namespace System { #endregion #region ISerializable - [System.Security.SecurityCritical] // auto-generated public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnitySerHolder")); @@ -212,7 +211,6 @@ namespace System { #endregion #region IObjectReference - [System.Security.SecurityCritical] // auto-generated public virtual Object GetRealObject(StreamingContext context) { // GetRealObject uses the data we have in m_data and m_unityType to do a lookup on the correct diff --git a/src/mscorlib/src/System/ValueType.cs b/src/mscorlib/src/System/ValueType.cs index ae08b7d..102a0d2 100644 --- a/src/mscorlib/src/System/ValueType.cs +++ b/src/mscorlib/src/System/ValueType.cs @@ -20,7 +20,6 @@ namespace System { [System.Runtime.InteropServices.ComVisible(true)] public abstract class ValueType { - [System.Security.SecuritySafeCritical] public override bool Equals (Object obj) { BCLDebug.Perf(false, "ValueType::Equals is not fast. "+this.GetType().FullName+" should override Equals(Object)"); if (null==obj) { @@ -60,11 +59,9 @@ namespace System { return true; } - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool CanCompareBits(Object obj); - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool FastEqualsCheck(Object a, Object b); @@ -78,7 +75,6 @@ namespace System { **Arguments: None. **Exceptions: None. ==============================================================================*/ - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern override int GetHashCode(); diff --git a/src/mscorlib/src/System/Variant.cs b/src/mscorlib/src/System/Variant.cs index 26e2e4a..2a9593c 100644 --- a/src/mscorlib/src/System/Variant.cs +++ b/src/mscorlib/src/System/Variant.cs @@ -19,6 +19,7 @@ namespace System { using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; [Serializable] @@ -118,19 +119,14 @@ namespace System { // // Native Methods // - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern double GetR8FromVar(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern float GetR4FromVar(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern void SetFieldsR4(float val); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern void SetFieldsR8(double val); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern void SetFieldsObject(Object val); @@ -224,7 +220,6 @@ namespace System { m_data2 = (int)(val >> 32); } - [System.Security.SecuritySafeCritical] // auto-generated public Variant(float val) { m_objref=null; m_flags=CV_R4; @@ -233,7 +228,6 @@ namespace System { SetFieldsR4(val); } - [System.Security.SecurityCritical] // auto-generated public Variant(double val) { m_objref=null; m_flags=CV_R8; @@ -257,7 +251,6 @@ namespace System { m_data2=0; } - [System.Security.SecuritySafeCritical] // auto-generated public Variant(Object obj) { m_data1=0; m_data2=0; @@ -317,13 +310,13 @@ namespace System { { vt = VarEnum.VT_ERROR; obj = (Object)(((ErrorWrapper)obj).ErrorCode); - Contract.Assert(obj != null, "obj != null"); + Debug.Assert(obj != null, "obj != null"); } else if (obj is CurrencyWrapper) { vt = VarEnum.VT_CY; obj = (Object)(((CurrencyWrapper)obj).WrappedObject); - Contract.Assert(obj != null, "obj != null"); + Debug.Assert(obj != null, "obj != null"); } else if (obj is BStrWrapper) { @@ -342,12 +335,11 @@ namespace System { } - [System.Security.SecurityCritical] // auto-generated unsafe public Variant(void* voidPointer,Type pointerType) { if (pointerType == null) - throw new ArgumentNullException("pointerType"); + throw new ArgumentNullException(nameof(pointerType)); if (!pointerType.IsPointer) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBePointer"),"pointerType"); + throw new ArgumentException(Environment.GetResourceString("Arg_MustBePointer"),nameof(pointerType)); Contract.EndContractBlock(); m_objref = pointerType; @@ -365,7 +357,6 @@ namespace System { } } - [System.Security.SecuritySafeCritical] // auto-generated public Object ToObject() { switch (CVType) { case CV_EMPTY: @@ -413,21 +404,16 @@ namespace System { } // This routine will return an boxed enum. - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern Object BoxEnum(); // Helper code for marshaling managed objects to VARIANT's (we use // managed variants as an intermediate type. - [System.Security.SecuritySafeCritical] // auto-generated internal static void MarshalHelperConvertObjectToVariant(Object o, ref Variant v) { -#if FEATURE_REMOTING - IConvertible ic = System.Runtime.Remoting.RemotingServices.IsTransparentProxy(o) ? null : o as IConvertible; -#else IConvertible ic = o as IConvertible; -#endif + if (o == null) { v = Empty; @@ -532,7 +518,6 @@ namespace System { // Helper code: on the back propagation path where a VT_BYREF VARIANT* // is marshaled to a "ref Object", we use this helper to force the // updated object back to the original type. - [System.Security.SecurityCritical] // auto-generated internal static void MarshalHelperCastVariant(Object pValue, int vt, ref Variant v) { IConvertible iv = pValue as IConvertible; diff --git a/src/mscorlib/src/System/Version.cs b/src/mscorlib/src/System/Version.cs index f3520b8..f2ef5d4 100644 --- a/src/mscorlib/src/System/Version.cs +++ b/src/mscorlib/src/System/Version.cs @@ -12,6 +12,7 @@ ===========================================================*/ namespace System { + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Text; using CultureInfo = System.Globalization.CultureInfo; @@ -29,24 +30,24 @@ namespace System { , IComparable, IEquatable { // AssemblyName depends on the order staying the same - private int _Major; - private int _Minor; - private int _Build = -1; - private int _Revision = -1; + private readonly int _Major; + private readonly int _Minor; + private readonly int _Build = -1; + private readonly int _Revision = -1; private static readonly char[] SeparatorsArray = new char[] { '.' }; public Version(int major, int minor, int build, int revision) { if (major < 0) - throw new ArgumentOutOfRangeException("major",Environment.GetResourceString("ArgumentOutOfRange_Version")); + throw new ArgumentOutOfRangeException(nameof(major),Environment.GetResourceString("ArgumentOutOfRange_Version")); if (minor < 0) - throw new ArgumentOutOfRangeException("minor",Environment.GetResourceString("ArgumentOutOfRange_Version")); + throw new ArgumentOutOfRangeException(nameof(minor),Environment.GetResourceString("ArgumentOutOfRange_Version")); if (build < 0) - throw new ArgumentOutOfRangeException("build",Environment.GetResourceString("ArgumentOutOfRange_Version")); + throw new ArgumentOutOfRangeException(nameof(build),Environment.GetResourceString("ArgumentOutOfRange_Version")); if (revision < 0) - throw new ArgumentOutOfRangeException("revision",Environment.GetResourceString("ArgumentOutOfRange_Version")); + throw new ArgumentOutOfRangeException(nameof(revision),Environment.GetResourceString("ArgumentOutOfRange_Version")); Contract.EndContractBlock(); _Major = major; @@ -57,13 +58,13 @@ namespace System { public Version(int major, int minor, int build) { if (major < 0) - throw new ArgumentOutOfRangeException("major",Environment.GetResourceString("ArgumentOutOfRange_Version")); + throw new ArgumentOutOfRangeException(nameof(major),Environment.GetResourceString("ArgumentOutOfRange_Version")); if (minor < 0) - throw new ArgumentOutOfRangeException("minor",Environment.GetResourceString("ArgumentOutOfRange_Version")); + throw new ArgumentOutOfRangeException(nameof(minor),Environment.GetResourceString("ArgumentOutOfRange_Version")); if (build < 0) - throw new ArgumentOutOfRangeException("build",Environment.GetResourceString("ArgumentOutOfRange_Version")); + throw new ArgumentOutOfRangeException(nameof(build),Environment.GetResourceString("ArgumentOutOfRange_Version")); Contract.EndContractBlock(); @@ -74,10 +75,10 @@ namespace System { public Version(int major, int minor) { if (major < 0) - throw new ArgumentOutOfRangeException("major",Environment.GetResourceString("ArgumentOutOfRange_Version")); + throw new ArgumentOutOfRangeException(nameof(major),Environment.GetResourceString("ArgumentOutOfRange_Version")); if (minor < 0) - throw new ArgumentOutOfRangeException("minor",Environment.GetResourceString("ArgumentOutOfRange_Version")); + throw new ArgumentOutOfRangeException(nameof(minor),Environment.GetResourceString("ArgumentOutOfRange_Version")); Contract.EndContractBlock(); _Major = major; @@ -98,6 +99,16 @@ namespace System { _Minor = 0; } + private Version(Version version) + { + Debug.Assert(version != null); + + _Major = version._Major; + _Minor = version._Minor; + _Build = version._Build; + _Revision = version._Revision; + } + // Properties for setting and getting version numbers public int Major { get { return _Major; } @@ -124,12 +135,7 @@ namespace System { } public Object Clone() { - Version v = new Version(); - v._Major = _Major; - v._Minor = _Minor; - v._Build = _Build; - v._Revision = _Revision; - return(v); + return new Version(this); } public int CompareTo(Object version) @@ -145,93 +151,33 @@ namespace System { throw new ArgumentException(Environment.GetResourceString("Arg_MustBeVersion")); } - if (this._Major != v._Major) - if (this._Major > v._Major) - return 1; - else - return -1; - - if (this._Minor != v._Minor) - if (this._Minor > v._Minor) - return 1; - else - return -1; - - if (this._Build != v._Build) - if (this._Build > v._Build) - return 1; - else - return -1; - - if (this._Revision != v._Revision) - if (this._Revision > v._Revision) - return 1; - else - return -1; - - return 0; + return CompareTo(v); } public int CompareTo(Version value) { - if (value == null) - return 1; - - if (this._Major != value._Major) - if (this._Major > value._Major) - return 1; - else - return -1; - - if (this._Minor != value._Minor) - if (this._Minor > value._Minor) - return 1; - else - return -1; - - if (this._Build != value._Build) - if (this._Build > value._Build) - return 1; - else - return -1; - - if (this._Revision != value._Revision) - if (this._Revision > value._Revision) - return 1; - else - return -1; - - return 0; + return + object.ReferenceEquals(value, this) ? 0 : + object.ReferenceEquals(value, null) ? 1 : + _Major != value._Major ? (_Major > value._Major ? 1 : -1) : + _Minor != value._Minor ? (_Minor > value._Minor ? 1 : -1) : + _Build != value._Build ? (_Build > value._Build ? 1 : -1) : + _Revision != value._Revision ? (_Revision > value._Revision ? 1 : -1) : + 0; } public override bool Equals(Object obj) { - Version v = obj as Version; - if (v == null) - return false; - - // check that major, minor, build & revision numbers match - if ((this._Major != v._Major) || - (this._Minor != v._Minor) || - (this._Build != v._Build) || - (this._Revision != v._Revision)) - return false; - - return true; + return Equals(obj as Version); } public bool Equals(Version obj) { - if (obj == null) - return false; - - // check that major, minor, build & revision numbers match - if ((this._Major != obj._Major) || - (this._Minor != obj._Minor) || - (this._Build != obj._Build) || - (this._Revision != obj._Revision)) - return false; - - return true; + return object.ReferenceEquals(obj, this) || + (!object.ReferenceEquals(obj, null) && + _Major == obj._Major && + _Minor == obj._Minor && + _Build == obj._Build && + _Revision == obj._Revision); } public override int GetHashCode() @@ -270,7 +216,7 @@ namespace System { return StringBuilderCache.GetStringAndRelease(sb); default: if (_Build == -1) - throw new ArgumentException(Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper", "0", "2"), "fieldCount"); + throw new ArgumentException(Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper", "0", "2"), nameof(fieldCount)); if (fieldCount == 3) { @@ -284,7 +230,7 @@ namespace System { } if (_Revision == -1) - throw new ArgumentException(Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper", "0", "3"), "fieldCount"); + throw new ArgumentException(Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper", "0", "3"), nameof(fieldCount)); if (fieldCount == 4) { @@ -299,7 +245,7 @@ namespace System { return StringBuilderCache.GetStringAndRelease(sb); } - throw new ArgumentException(Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper", "0", "4"), "fieldCount"); + throw new ArgumentException(Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper", "0", "4"), nameof(fieldCount)); } } @@ -307,12 +253,12 @@ namespace System { // AppendPositiveNumber is an optimization to append a number to a StringBuilder object without // doing any boxing and not even creating intermediate string. // Note: as we always have positive numbers then it is safe to convert the number to string - // regardless of the current culture as we’ll not have any punctuation marks in the number + // regardless of the current culture as we'll not have any punctuation marks in the number // private const int ZERO_CHAR_VALUE = (int) '0'; private static void AppendPositiveNumber(int num, StringBuilder sb) { - Contract.Assert(num >= 0, "AppendPositiveNumber expect positive numbers"); + Debug.Assert(num >= 0, "AppendPositiveNumber expect positive numbers"); int index = sb.Length; int reminder; @@ -327,12 +273,12 @@ namespace System { public static Version Parse(string input) { if (input == null) { - throw new ArgumentNullException("input"); + throw new ArgumentNullException(nameof(input)); } Contract.EndContractBlock(); VersionResult r = new VersionResult(); - r.Init("input", true); + r.Init(nameof(input), true); if (!TryParseVersion(input, ref r)) { throw r.GetVersionParseException(); } @@ -341,7 +287,7 @@ namespace System { public static bool TryParse(string input, out Version result) { VersionResult r = new VersionResult(); - r.Init("input", false); + r.Init(nameof(input), false); bool b = TryParseVersion(input, ref r); result = r.m_parsedVersion; return b; @@ -362,11 +308,11 @@ namespace System { return false; } - if (!TryParseComponent(parsedComponents[0], "version", ref result, out major)) { + if (!TryParseComponent(parsedComponents[0], nameof(version), ref result, out major)) { return false; } - if (!TryParseComponent(parsedComponents[1], "version", ref result, out minor)) { + if (!TryParseComponent(parsedComponents[1], nameof(version), ref result, out minor)) { return false; } @@ -423,14 +369,14 @@ namespace System { public static bool operator <(Version v1, Version v2) { if ((Object) v1 == null) - throw new ArgumentNullException("v1"); + throw new ArgumentNullException(nameof(v1)); Contract.EndContractBlock(); return (v1.CompareTo(v2) < 0); } public static bool operator <=(Version v1, Version v2) { if ((Object) v1 == null) - throw new ArgumentNullException("v1"); + throw new ArgumentNullException(nameof(v1)); Contract.EndContractBlock(); return (v1.CompareTo(v2) <= 0); } @@ -491,10 +437,10 @@ namespace System { } catch (OverflowException e) { return e; } - Contract.Assert(false, "Int32.Parse() did not throw exception but TryParse failed: " + m_exceptionArgument); + Debug.Assert(false, "Int32.Parse() did not throw exception but TryParse failed: " + m_exceptionArgument); return new FormatException(Environment.GetResourceString("Format_InvalidString")); default: - Contract.Assert(false, "Unmatched case in Version.GetVersionParseException() for value: " + m_failure); + Debug.Assert(false, "Unmatched case in Version.GetVersionParseException() for value: " + m_failure); return new ArgumentException(Environment.GetResourceString("Arg_VersionString")); } } diff --git a/src/mscorlib/src/System/WeakReference.cs b/src/mscorlib/src/System/WeakReference.cs index d12ca3e..d564852 100644 --- a/src/mscorlib/src/System/WeakReference.cs +++ b/src/mscorlib/src/System/WeakReference.cs @@ -16,11 +16,10 @@ namespace System { using System.Security.Permissions; using System.Runtime.CompilerServices; using System.Runtime.Versioning; + using System.Diagnostics; using System.Diagnostics.Contracts; + [System.Runtime.InteropServices.ComVisible(true)] -#if !FEATURE_CORECLR - [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] // Don't call Object::MemberwiseClone. -#endif [Serializable] public class WeakReference : ISerializable { @@ -28,15 +27,12 @@ namespace System { // This field is not a regular GC handle. It can have a special values that are used to prevent a race condition between setting the target and finalization. internal IntPtr m_handle; - -#if FEATURE_CORECLR + // Migrating InheritanceDemands requires this default ctor, so we can mark it SafeCritical - [SecuritySafeCritical] protected WeakReference() { - Contract.Assert(false, "WeakReference's protected default ctor should never be used!"); + Debug.Assert(false, "WeakReference's protected default ctor should never be used!"); throw new NotImplementedException(); } -#endif // Creates a new WeakReference that keeps track of target. // Assumes a Short Weak Reference (ie TrackResurrection is false.) @@ -53,7 +49,7 @@ namespace System { protected WeakReference(SerializationInfo info, StreamingContext context) { if (info==null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); @@ -68,7 +64,6 @@ namespace System { // public extern virtual bool IsAlive { [MethodImplAttribute(MethodImplOptions.InternalCall)] - [SecuritySafeCritical] get; } @@ -85,10 +80,8 @@ namespace System { // public extern virtual Object Target { [MethodImplAttribute(MethodImplOptions.InternalCall)] - [SecuritySafeCritical] get; [MethodImplAttribute(MethodImplOptions.InternalCall)] - [SecuritySafeCritical] set; } @@ -99,14 +92,12 @@ namespace System { // This is needed for subclasses deriving from WeakReference, however. // Additionally, there may be some cases during shutdown when we run this finalizer. [MethodImplAttribute(MethodImplOptions.InternalCall)] - [SecuritySafeCritical] extern ~WeakReference(); - [SecurityCritical] public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { if (info==null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); info.AddValue("TrackedObject", Target, typeof(Object)); @@ -114,11 +105,9 @@ namespace System { } [MethodImplAttribute(MethodImplOptions.InternalCall)] - [SecuritySafeCritical] private extern void Create(Object target, bool trackResurrection); [MethodImplAttribute(MethodImplOptions.InternalCall)] - [SecuritySafeCritical] private extern bool IsTrackResurrection(); } diff --git a/src/mscorlib/src/System/WeakReferenceOfT.cs b/src/mscorlib/src/System/WeakReferenceOfT.cs index b8195df..0972e5f 100644 --- a/src/mscorlib/src/System/WeakReferenceOfT.cs +++ b/src/mscorlib/src/System/WeakReferenceOfT.cs @@ -46,7 +46,7 @@ namespace System internal WeakReference(SerializationInfo info, StreamingContext context) { if (info == null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); @@ -81,10 +81,8 @@ namespace System private extern T Target { [MethodImplAttribute(MethodImplOptions.InternalCall)] - [SecuritySafeCritical] get; [MethodImplAttribute(MethodImplOptions.InternalCall)] - [SecuritySafeCritical] set; } @@ -95,14 +93,12 @@ namespace System // This is needed for subclasses deriving from WeakReference, however. // Additionally, there may be some cases during shutdown when we run this finalizer. [MethodImplAttribute(MethodImplOptions.InternalCall)] - [SecuritySafeCritical] extern ~WeakReference(); - [SecurityCritical] public void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) { - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); } Contract.EndContractBlock(); @@ -111,11 +107,9 @@ namespace System } [MethodImplAttribute(MethodImplOptions.InternalCall)] - [SecuritySafeCritical] private extern void Create(T target, bool trackResurrection); [MethodImplAttribute(MethodImplOptions.InternalCall)] - [SecuritySafeCritical] private extern bool IsTrackResurrection(); } } diff --git a/src/mscorlib/src/System/_LocalDataStore.cs b/src/mscorlib/src/System/_LocalDataStore.cs index a3a312f..a1fa488 100644 --- a/src/mscorlib/src/System/_LocalDataStore.cs +++ b/src/mscorlib/src/System/_LocalDataStore.cs @@ -17,6 +17,7 @@ namespace System { using System; using System.Threading; using System.Runtime.CompilerServices; + using System.Diagnostics; using System.Diagnostics.Contracts; // Helper class to aid removal of LocalDataStore from the LocalDataStoreMgr @@ -197,7 +198,6 @@ namespace System { /*========================================================================= ** Method used to expand the capacity of the local data store. =========================================================================*/ - [System.Security.SecuritySafeCritical] // auto-generated private LocalDataStoreElement PopulateElement(LocalDataStoreSlot slot) { bool tookLock = false; @@ -215,7 +215,7 @@ namespace System { int capacity = m_Manager.GetSlotTableLength(); // Validate that the specified capacity is larger than the current one. - Contract.Assert(capacity >= m_DataTable.Length, "LocalDataStore corrupted: capacity >= m_DataTable.Length"); + Debug.Assert(capacity >= m_DataTable.Length, "LocalDataStore corrupted: capacity >= m_DataTable.Length"); // Allocate the new data table. LocalDataStoreElement[] NewDataTable = new LocalDataStoreElement[capacity]; @@ -228,7 +228,7 @@ namespace System { } // Validate that there is enough space in the local data store now - Contract.Assert(slotIdx < m_DataTable.Length, "LocalDataStore corrupted: slotIdx < m_DataTable.Length"); + Debug.Assert(slotIdx < m_DataTable.Length, "LocalDataStore corrupted: slotIdx < m_DataTable.Length"); if (m_DataTable[slotIdx] == null) m_DataTable[slotIdx] = new LocalDataStoreElement(slot.Cookie); diff --git a/src/mscorlib/src/System/_LocalDataStoreMgr.cs b/src/mscorlib/src/System/_LocalDataStoreMgr.cs index 6154138..8f60d6f 100644 --- a/src/mscorlib/src/System/_LocalDataStoreMgr.cs +++ b/src/mscorlib/src/System/_LocalDataStoreMgr.cs @@ -58,7 +58,7 @@ namespace System { get { return m_cookie; - } + } } // Release the slot reserved by this object when this object goes away. @@ -70,8 +70,8 @@ namespace System { int slot = m_slot; - // Mark the slot as free. - m_slot = -1; + // Mark the slot as free. + m_slot = -1; mgr.FreeDataSlot(slot, m_cookie); } @@ -89,7 +89,6 @@ namespace System { ** list. The initial size of the new store matches the number of slots ** allocated in this manager. =========================================================================*/ - [System.Security.SecuritySafeCritical] // auto-generated public LocalDataStoreHolder CreateLocalDataStore() { // Create a new local data store. @@ -115,7 +114,6 @@ namespace System { /*========================================================================= * Remove the specified store from the list of managed stores.. =========================================================================*/ - [System.Security.SecuritySafeCritical] // auto-generated public void DeleteLocalDataStore(LocalDataStore store) { bool tookLock = false; @@ -138,7 +136,6 @@ namespace System { ** an object to prevent clients from manipulating it directly, allowing us ** to make assumptions its integrity. =========================================================================*/ - [System.Security.SecuritySafeCritical] // auto-generated public LocalDataStoreSlot AllocateDataSlot() { bool tookLock = false; @@ -208,7 +205,6 @@ namespace System { /*========================================================================= ** Allocate a slot and associate a name with it. =========================================================================*/ - [System.Security.SecuritySafeCritical] // auto-generated public LocalDataStoreSlot AllocateNamedDataSlot(String name) { bool tookLock = false; @@ -235,7 +231,6 @@ namespace System { ** Retrieve the slot associated with a name, allocating it if no such ** association has been defined. =========================================================================*/ - [System.Security.SecuritySafeCritical] // auto-generated public LocalDataStoreSlot GetNamedDataSlot(String name) { bool tookLock = false; @@ -264,7 +259,6 @@ namespace System { ** Eliminate the association of a name with a slot. The actual slot will ** be reclaimed when the finalizer for the slot object runs. =========================================================================*/ - [System.Security.SecuritySafeCritical] // auto-generated public void FreeNamedDataSlot(String name) { bool tookLock = false; @@ -285,7 +279,6 @@ namespace System { /*========================================================================= ** Free's a previously allocated data slot on ALL the managed data stores. =========================================================================*/ - [System.Security.SecuritySafeCritical] // auto-generated internal void FreeDataSlot(int slot, long cookie) { bool tookLock = false; diff --git a/src/mscorlib/src/System/__ComObject.cs b/src/mscorlib/src/System/__ComObject.cs index a592370..9f9bac6 100644 --- a/src/mscorlib/src/System/__ComObject.cs +++ b/src/mscorlib/src/System/__ComObject.cs @@ -12,8 +12,8 @@ ** ** ===========================================================*/ -namespace System { - +namespace System +{ using System; using System.Collections; using System.Threading; @@ -59,7 +59,6 @@ namespace System { return base.ToString(); } - [System.Security.SecurityCritical] // auto-generated internal IntPtr GetIUnknown(out bool fIsURTAggregated) { fIsURTAggregated = !GetType().IsDefined(typeof(ComImportAttribute), false); @@ -118,7 +117,6 @@ namespace System { // This method is called from within the EE and releases all the // cached data for the __ComObject. //==================================================================== - [System.Security.SecurityCritical] // auto-generated internal void ReleaseAllData() { // Synchronize access to the map. @@ -154,7 +152,6 @@ namespace System { // This method is called from within the EE and is used to handle // calls on methods of event interfaces. //==================================================================== - [System.Security.SecurityCritical] // auto-generated internal Object GetEventProvider(RuntimeType t) { // Check to see if we already have a cached event provider for this type. @@ -167,22 +164,16 @@ namespace System { return EvProvider; } - [System.Security.SecurityCritical] // auto-generated internal int ReleaseSelf() { return Marshal.InternalReleaseComObject(this); } - [System.Security.SecurityCritical] // auto-generated internal void FinalReleaseSelf() { Marshal.InternalFinalReleaseComObject(this); } - [System.Security.SecurityCritical] // auto-generated -#if !FEATURE_CORECLR - [ReflectionPermissionAttribute(SecurityAction.Assert, MemberAccess=true)] -#endif private Object CreateEventProvider(RuntimeType t) { // Create the event provider for the specified type. diff --git a/src/mscorlib/src/System/cominterfaces.cs b/src/mscorlib/src/System/cominterfaces.cs index 7d3620a..a83943d 100644 --- a/src/mscorlib/src/System/cominterfaces.cs +++ b/src/mscorlib/src/System/cominterfaces.cs @@ -2,23 +2,13 @@ // 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.Globalization; -using System.IO; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Runtime.Serialization; -using System.Security.Permissions; -using System.Security.Policy; - namespace System.Runtime.InteropServices { [GuidAttribute("03973551-57A1-3900-A2B5-9083E3FF2943")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Activator))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _Activator { void GetTypeInfoCount(out uint pcTInfo); @@ -34,35 +24,17 @@ namespace System.Runtime.InteropServices [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Attribute))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _Attribute { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); -#endif } [GuidAttribute("C281C7F1-4AA9-3517-961A-463CFED57E75")] [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] [CLSCompliant(false)] [TypeLibImportClassAttribute(typeof(System.Threading.Thread))] -[System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.InteropServices.ComVisible(true)] public interface _Thread { -#if !FEATURE_CORECLR - void GetTypeInfoCount(out uint pcTInfo); - - void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo); - - void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId); - - void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr); -#endif } } diff --git a/src/mscorlib/src/System/mda.cs b/src/mscorlib/src/System/mda.cs index 089039c..f750e99 100644 --- a/src/mscorlib/src/System/mda.cs +++ b/src/mscorlib/src/System/mda.cs @@ -18,7 +18,6 @@ namespace System private static volatile int _captureAllocatedCallStackState; internal static bool Enabled { - [System.Security.SecuritySafeCritical] // auto-generated get { if (_enabledState == 0) { if (Mda.IsStreamWriterBufferedDataLostEnabled()) @@ -32,7 +31,6 @@ namespace System } internal static bool CaptureAllocatedCallStack { - [System.Security.SecuritySafeCritical] // auto-generated get { if (_captureAllocatedCallStackState == 0) { if (Mda.IsStreamWriterBufferedDataLostCaptureAllocatedCallStack()) @@ -45,42 +43,33 @@ namespace System } } - [System.Security.SecuritySafeCritical] // auto-generated internal static void ReportError(String text) { Mda.ReportStreamWriterBufferedDataLost(text); } } - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void ReportStreamWriterBufferedDataLost(String text); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool IsStreamWriterBufferedDataLostEnabled(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool IsStreamWriterBufferedDataLostCaptureAllocatedCallStack(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void MemberInfoCacheCreation(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void DateTimeInvalidLocalFormat(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool IsInvalidGCHandleCookieProbeEnabled(); - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void FireInvalidGCHandleCookieProbe(IntPtr cookie); - [System.Security.SecurityCritical] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void ReportErrorSafeHandleRelease(Exception ex); } diff --git a/src/mscorlib/src/mscorlib.Friends.cs b/src/mscorlib/src/mscorlib.Friends.cs index fc8ed53..0e55301 100644 --- a/src/mscorlib/src/mscorlib.Friends.cs +++ b/src/mscorlib/src/mscorlib.Friends.cs @@ -3,10 +3,8 @@ // See the LICENSE file in the project root for more information. using System.Runtime.CompilerServices; -#if FEATURE_CORECLR // We need this to be able to typeforward to internal types [assembly: InternalsVisibleTo("mscorlib, PublicKey=00240000048000009400000006020000002400005253413100040000010001008d56c76f9e8649383049f383c44be0ec204181822a6c31cf5eb7ef486944d032188ea1d3920763712ccb12d75fb77e9811149e6148e5d32fbaab37611c1878ddc19e20ef135d0cb2cff2bfec3d115810c3d9069638fe4be215dbf795861920e5ab6f7db2e2ceef136ac23d5dd2bf031700aec232f6c6b1c785b4305c123b37ab", AllInternalsVisible=false)] -#endif // For now we are only moving to using this file over AssemblyAttributes.cspp in CoreSys, ideally we would move away from the centralized // AssemblyAttributes.cspp model for the other build types at a future point in time. diff --git a/src/mscorlib/src/mscorlib.txt b/src/mscorlib/src/mscorlib.txt deleted file mode 100644 index 01d593b..0000000 --- a/src/mscorlib/src/mscorlib.txt +++ /dev/null @@ -1,3494 +0,0 @@ -; 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. - -; These are the managed resources for mscorlib.dll. -; See those first three bytes in the file? This is in UTF-8. Leave the -; Unicode byte order mark (U+FEFF) written in UTF-8 at the start of this file. - -; For resource info, see the ResourceManager documentation and the ResGen tool, -; which is a managed app using ResourceWriter. -; ResGen now supports limited preprocessing of txt files, you can use -; #if SYMBOL and #if !SYMBOL to control what sets of resources are included in -; the resulting resources. - -; The naming scheme is: [Namespace.] ExceptionName _ Reason -; We'll suppress "System." where possible. -; Examples: -; Argument_Null -; Reflection.TargetInvokation_someReason - -; Usage Notes: -; * Keep exceptions in alphabetical order by package -; * A single space may exist on either side of the equal sign. -; * Follow the naming conventions. -; * Any lines starting with a '#' or ';' are ignored -; * Equal signs aren't legal characters for keys, but may occur in values. -; * Correctly punctuate all sentences. Most resources should end in a period. -; Remember, your mother will probably read some of these messages. -; * You may use " (quote), \n and \t. Use \\ for a single '\' character. -; * String inserts work. i.e., BadNumber_File = Wrong number in file "{0}". - -; Real words, used by code like Environment.StackTrace -#if INCLUDE_RUNTIME -Word_At = at -StackTrace_InFileLineNumber = in {0}:line {1} -UnknownError_Num = Unknown error "{0}". -AllocatedFrom = Allocated from: - -; Note this one is special, used as a divider between stack traces! -Exception_EndOfInnerExceptionStack = --- End of inner exception stack trace --- -Exception_WasThrown = Exception of type '{0}' was thrown. - -; The following are used in the implementation of ExceptionDispatchInfo -Exception_EndStackTraceFromPreviousThrow = --- End of stack trace from previous location where exception was thrown --- - -Arg_ParamName_Name = Parameter name: {0} -ArgumentOutOfRange_ActualValue = Actual value was {0}. - -NoDebugResources = [{0}]\r\nArguments: {1}\r\nDebugging resource strings are unavailable. Often the key and arguments provide sufficient information to diagnose the problem. See http://go.microsoft.com/fwlink/?linkid=106663&Version={2}&File={3}&Key={4} -#endif // INCLUDE_RUNTIME - -#if !FEATURE_CORECLR -UnknownError = Unknown error. -#endif // !FEATURE_CORECLR - -#if INCLUDE_DEBUG - -; For code contracts -AssumptionFailed = Assumption failed. -AssumptionFailed_Cnd = Assumption failed: {0} -AssertionFailed = Assertion failed. -AssertionFailed_Cnd = Assertion failed: {0} -PreconditionFailed = Precondition failed. -PreconditionFailed_Cnd = Precondition failed: {0} -PostconditionFailed = Postcondition failed. -PostconditionFailed_Cnd = Postcondition failed: {0} -PostconditionOnExceptionFailed = Postcondition failed after throwing an exception. -PostconditionOnExceptionFailed_Cnd = Postcondition failed after throwing an exception: {0} -InvariantFailed = Invariant failed. -InvariantFailed_Cnd = Invariant failed: {0} -MustUseCCRewrite = An assembly (probably "{1}") must be rewritten using the code contracts binary rewriter (CCRewrite) because it is calling Contract.{0} and the CONTRACTS_FULL symbol is defined. Remove any explicit definitions of the CONTRACTS_FULL symbol from your project and rebuild. CCRewrite can be downloaded from http://go.microsoft.com/fwlink/?LinkID=169180. \r\nAfter the rewriter is installed, it can be enabled in Visual Studio from the project's Properties page on the Code Contracts pane. Ensure that "Perform Runtime Contract Checking" is enabled, which will define CONTRACTS_FULL. - -; Access Control -#if FEATURE_MACL -AccessControl_MustSpecifyContainerAcl = The named parameter must be a container ACL. -AccessControl_MustSpecifyLeafObjectAcl = The named parameter must be a non-container ACL. -AccessControl_AclTooLong = Length of the access control list exceed the allowed maximum. -AccessControl_MustSpecifyDirectoryObjectAcl = The named parameter must be a directory-object ACL. -AccessControl_MustSpecifyNonDirectoryObjectAcl = The named parameter must be a non-directory-object ACL. -AccessControl_InvalidSecurityDescriptorRevision = Security descriptor with revision other than '1' are not legal. -AccessControl_InvalidSecurityDescriptorSelfRelativeForm = Security descriptor must be in the self-relative form. -AccessControl_NoAssociatedSecurity = Unable to perform a security operation on an object that has no associated security. This can happen when trying to get an ACL of an anonymous kernel object. -AccessControl_InvalidHandle = The supplied handle is invalid. This can happen when trying to set an ACL on an anonymous kernel object. -AccessControl_UnexpectedError = Method failed with unexpected error code {0}. -AccessControl_InvalidSidInSDDLString = The SDDL string contains an invalid sid or a sid that cannot be translated. -AccessControl_InvalidOwner = The security identifier is not allowed to be the owner of this object. -AccessControl_InvalidGroup = The security identifier is not allowed to be the primary group of this object. -AccessControl_InvalidAccessRuleType = The access rule is not the correct type. -AccessControl_InvalidAuditRuleType = The audit rule is not the correct type. -#endif // FEATURE_MACL - -; Identity Reference Library -#if FEATURE_IDENTITY_REFERENCE -IdentityReference_IdentityNotMapped = Some or all identity references could not be translated. -IdentityReference_MustBeIdentityReference = The targetType parameter must be of IdentityReference type. -IdentityReference_AccountNameTooLong = Account name is too long. -IdentityReference_DomainNameTooLong = Domain name is too long. -IdentityReference_InvalidNumberOfSubauthorities = The number of sub-authorities must not exceed {0}. -IdentityReference_IdentifierAuthorityTooLarge = The size of the identifier authority must not exceed 6 bytes. -IdentityReference_InvalidSidRevision = SIDs with revision other than '1' are not supported. -IdentityReference_CannotCreateLogonIdsSid = Well-known SIDs of type LogonIdsSid cannot be created. -IdentityReference_DomainSidRequired = The domainSid parameter must be specified for creating well-known SID of type {0}. -IdentityReference_NotAWindowsDomain = The domainSid parameter is not a valid Windows domain SID. -#endif // FEATURE_IDENTITY_REFERENCE - -; AccessException -Acc_CreateGeneric = Cannot create a type for which Type.ContainsGenericParameters is true. -Acc_CreateAbst = Cannot create an abstract class. -Acc_CreateInterface = Cannot create an instance of an interface. -Acc_NotClassInit = Type initializer was not callable. -Acc_CreateGenericEx = Cannot create an instance of {0} because Type.ContainsGenericParameters is true. -Acc_CreateArgIterator = Cannot dynamically create an instance of ArgIterator. -Acc_CreateAbstEx = Cannot create an instance of {0} because it is an abstract class. -Acc_CreateInterfaceEx = Cannot create an instance of {0} because it is an interface. -Acc_CreateVoid = Cannot dynamically create an instance of System.Void. -Acc_ReadOnly = Cannot set a constant field. -Acc_RvaStatic = SkipVerification permission is needed to modify an image-based (RVA) static field. -Access_Void = Cannot create an instance of void. - -; ArgumentException -Arg_TypedReference_Null = The TypedReference must be initialized. -Argument_AddingDuplicate__ = Item has already been added. Key in dictionary: '{0}' Key being added: '{1}' -Argument_AddingDuplicate = An item with the same key has already been added. -#if FEATURE_CORECLR -Argument_AddingDuplicateWithKey = An item with the same key has already been added. Key: {0} -#endif // FEATURE_CORECLR -Argument_MethodDeclaringTypeGenericLcg = Method '{0}' has a generic declaring type '{1}'. Explicitly provide the declaring type to GetTokenFor. -Argument_MethodDeclaringTypeGeneric = Cannot resolve method {0} because the declaring type of the method handle {1} is generic. Explicitly provide the declaring type to GetMethodFromHandle. -Argument_FieldDeclaringTypeGeneric = Cannot resolve field {0} because the declaring type of the field handle {1} is generic. Explicitly provide the declaring type to GetFieldFromHandle. -Argument_ApplicationTrustShouldHaveIdentity = An ApplicationTrust must have an application identity before it can be persisted. -Argument_ConversionOverflow = Conversion buffer overflow. -Argument_CodepageNotSupported = {0} is not a supported code page. -Argument_CultureNotSupported = Culture is not supported. -Argument_CultureInvalidIdentifier = {0} is an invalid culture identifier. -Argument_OneOfCulturesNotSupported = Culture name {0} or {1} is not supported. -Argument_CultureIetfNotSupported = Culture IETF Name {0} is not a recognized IETF name. -Argument_CultureIsNeutral = Culture ID {0} (0x{0:X4}) is a neutral culture; a region cannot be created from it. -Argument_InvalidNeutralRegionName = The region name {0} should not correspond to neutral culture; a specific culture name is required. -Argument_InvalidGenericInstArray = Generic arguments must be provided for each generic parameter and each generic argument must be a RuntimeType. -Argument_GenericArgsCount = The number of generic arguments provided doesn't equal the arity of the generic type definition. -Argument_CultureInvalidFormat = Culture '{0}' is a neutral culture. It cannot be used in formatting and parsing and therefore cannot be set as the thread's current culture. -Argument_CompareOptionOrdinal = CompareOption.Ordinal cannot be used with other options. -Argument_CustomCultureCannotBePassedByNumber = Customized cultures cannot be passed by LCID, only by name. -Argument_EncodingConversionOverflowChars = The output char buffer is too small to contain the decoded characters, encoding '{0}' fallback '{1}'. -Argument_EncodingConversionOverflowBytes = The output byte buffer is too small to contain the encoded data, encoding '{0}' fallback '{1}'. -Argument_EncoderFallbackNotEmpty = Must complete Convert() operation or call Encoder.Reset() before calling GetBytes() or GetByteCount(). Encoder '{0}' fallback '{1}'. -Argument_EmptyFileName = Empty file name is not legal. -Argument_EmptyPath = Empty path name is not legal. -Argument_EmptyName = Empty name is not legal. -Argument_ImplementIComparable = At least one object must implement IComparable. -Argument_InvalidType = The type of arguments passed into generic comparer methods is invalid. -Argument_InvalidTypeForCA=Cannot build type parameter for custom attribute with a type that does not support the AssemblyQualifiedName property. The type instance supplied was of type '{0}'. -Argument_IllegalEnvVarName = Environment variable name cannot contain equal character. -Argument_IllegalAppId = Application identity does not have same number of components as manifest paths. -Argument_IllegalAppBase = The application base specified is not valid. -Argument_UnableToParseManifest = Unexpected error while parsing the specified manifest. -Argument_IllegalAppIdMismatch = Application identity does not match identities in manifests. -Argument_InvalidAppId = Invalid identity: no deployment or application identity specified. -Argument_InvalidGenericArg = The generic type parameter was not valid -Argument_InvalidArrayLength = Length of the array must be {0}. -Argument_InvalidArrayType = Target array type is not compatible with the type of items in the collection. -Argument_InvalidAppendMode = Append access can be requested only in write-only mode. -Argument_InvalidEnumValue = The value '{0}' is not valid for this usage of the type {1}. -Argument_EnumIsNotIntOrShort = The underlying type of enum argument must be Int32 or Int16. -Argument_InvalidEnum = The Enum type should contain one and only one instance field. -Argument_InvalidKeyStore = '{0}' is not a valid KeyStore name. -Argument_InvalidFileMode&AccessCombo = Combining FileMode: {0} with FileAccess: {1} is invalid. -Argument_InvalidFileMode&RightsCombo = Combining FileMode: {0} with FileSystemRights: {1} is invalid. -Argument_InvalidFileModeTruncate&RightsCombo = Combining FileMode: {0} with FileSystemRights: {1} is invalid. FileMode.Truncate is valid only when used with FileSystemRights.Write. -Argument_InvalidFlag = Value of flags is invalid. -Argument_InvalidAnyFlag = No flags can be set. -Argument_InvalidHandle = The handle is invalid. -Argument_InvalidRegistryKeyPermissionCheck = The specified RegistryKeyPermissionCheck value is invalid. -Argument_InvalidRegistryOptionsCheck = The specified RegistryOptions value is invalid. -Argument_InvalidRegistryViewCheck = The specified RegistryView value is invalid. -Argument_InvalidSubPath = The directory specified, '{0}', is not a subdirectory of '{1}'. -Argument_NoRegionInvariantCulture = There is no region associated with the Invariant Culture (Culture ID: 0x7F). -Argument_ResultCalendarRange = The result is out of the supported range for this calendar. The result should be between {0} (Gregorian date) and {1} (Gregorian date), inclusive. -Argument_ResultIslamicCalendarRange = The date is out of the supported range for the Islamic calendar. The date should be greater than July 18th, 622 AD (Gregorian date). -Argument_NeverValidGenericArgument = The type '{0}' may not be used as a type argument. -Argument_NotEnoughGenArguments = The type or method has {1} generic parameter(s), but {0} generic argument(s) were provided. A generic argument must be provided for each generic parameter. -Argument_NullFullTrustAssembly = A null StrongName was found in the full trust assembly list. -Argument_GenConstraintViolation = GenericArguments[{0}], '{1}', on '{2}' violates the constraint of type '{3}'. -Argument_InvalidToken = Token {0:x} is not valid in the scope of module {1}. -Argument_InvalidTypeToken = Token {0:x} is not a valid Type token. -Argument_ResolveType = Token {0:x} is not a valid Type token in the scope of module {1}. -Argument_ResolveMethod = Token {0:x} is not a valid MethodBase token in the scope of module {1}. -Argument_ResolveField = Token {0:x} is not a valid FieldInfo token in the scope of module {1}. -Argument_ResolveMember = Token {0:x} is not a valid MemberInfo token in the scope of module {1}. -Argument_ResolveString = Token {0:x} is not a valid string token in the scope of module {1}. -Argument_ResolveModuleType = Token {0} resolves to the special module type representing this module. -Argument_ResolveMethodHandle = Type handle '{0}' and method handle with declaring type '{1}' are incompatible. Get RuntimeMethodHandle and declaring RuntimeTypeHandle off the same MethodBase. -Argument_ResolveFieldHandle = Type handle '{0}' and field handle with declaring type '{1}' are incompatible. Get RuntimeFieldHandle and declaring RuntimeTypeHandle off the same FieldInfo. -Argument_ResourceScopeWrongDirection = Resource type in the ResourceScope enum is going from a more restrictive resource type to a more general one. From: "{0}" To: "{1}" -Argument_BadResourceScopeTypeBits = Unknown value for the ResourceScope: {0} Too many resource type bits may be set. -Argument_BadResourceScopeVisibilityBits = Unknown value for the ResourceScope: {0} Too many resource visibility bits may be set. -Argument_WaitHandleNameTooLong = The name can be no more than 260 characters in length. -Argument_EnumTypeDoesNotMatch = The argument type, '{0}', is not the same as the enum type '{1}'. -InvalidOperation_MethodBuilderBaked = The signature of the MethodBuilder can no longer be modified because an operation on the MethodBuilder caused the methodDef token to be created. For example, a call to SetCustomAttribute requires the methodDef token to emit the CustomAttribute token. -InvalidOperation_GenericParametersAlreadySet = The generic parameters are already defined on this MethodBuilder. -Arg_AccessException = Cannot access member. -Arg_AppDomainUnloadedException = Attempted to access an unloaded AppDomain. -Arg_ApplicationException = Error in the application. -Arg_ArgumentOutOfRangeException = Specified argument was out of the range of valid values. -Arg_ArithmeticException = Overflow or underflow in the arithmetic operation. -Arg_ArrayLengthsDiffer = Array lengths must be the same. -Arg_ArrayPlusOffTooSmall = Destination array is not long enough to copy all the items in the collection. Check array index and length. -Arg_ArrayTypeMismatchException = Attempted to access an element as a type incompatible with the array. -Arg_BadImageFormatException = Format of the executable (.exe) or library (.dll) is invalid. -Argument_BadImageFormatExceptionResolve = A BadImageFormatException has been thrown while parsing the signature. This is likely due to lack of a generic context. Ensure genericTypeArguments and genericMethodArguments are provided and contain enough context. -Arg_BufferTooSmall = Not enough space available in the buffer. -Arg_CATypeResolutionFailed = Failed to resolve type from string "{0}" which was embedded in custom attribute blob. -Arg_CannotHaveNegativeValue = String cannot contain a minus sign if the base is not 10. -Arg_CannotUnloadAppDomainException = Attempt to unload the AppDomain failed. -Arg_CannotMixComparisonInfrastructure = The usage of IKeyComparer and IHashCodeProvider/IComparer interfaces cannot be mixed; use one or the other. -Arg_ContextMarshalException = Attempted to marshal an object across a context boundary. -Arg_DataMisalignedException = A datatype misalignment was detected in a load or store instruction. -Arg_DevicesNotSupported = FileStream will not open Win32 devices such as disk partitions and tape drives. Avoid use of "\\\\.\\" in the path. -Arg_DuplicateWaitObjectException = Duplicate objects in argument. -Arg_EntryPointNotFoundException = Entry point was not found. -Arg_DllNotFoundException = Dll was not found. -Arg_ExecutionEngineException = Internal error in the runtime. -Arg_FieldAccessException = Attempted to access a field that is not accessible by the caller. -Arg_FileIsDirectory_Name = The target file "{0}" is a directory, not a file. -Arg_FormatException = One of the identified items was in an invalid format. -Arg_IndexOutOfRangeException = Index was outside the bounds of the array. -Arg_InsufficientExecutionStackException = Insufficient stack to continue executing the program safely. This can happen from having too many functions on the call stack or function on the stack using too much stack space. -Arg_InvalidCastException = Specified cast is not valid. -Arg_InvalidOperationException = Operation is not valid due to the current state of the object. -Arg_CorruptedCustomCultureFile = The file of the custom culture {0} is corrupt. Try to unregister this culture. -Arg_InvokeMember = InvokeMember can be used only for COM objects. -Arg_InvalidNeutralResourcesLanguage_Asm_Culture = The NeutralResourcesLanguageAttribute on the assembly "{0}" specifies an invalid culture name: "{1}". -Arg_InvalidNeutralResourcesLanguage_FallbackLoc = The NeutralResourcesLanguageAttribute specifies an invalid or unrecognized ultimate resource fallback location: "{0}". -Arg_InvalidSatelliteContract_Asm_Ver = Satellite contract version attribute on the assembly '{0}' specifies an invalid version: {1}. -Arg_MethodAccessException = Attempt to access the method failed. -Arg_MethodAccessException_WithMethodName = Attempt to access the method "{0}" on type "{1}" failed. -Arg_MethodAccessException_WithCaller = Attempt by security transparent method '{0}' to access security critical method '{1}' failed. -Arg_MissingFieldException = Attempted to access a non-existing field. -Arg_MissingMemberException = Attempted to access a missing member. -Arg_MissingMethodException = Attempted to access a missing method. -Arg_MulticastNotSupportedException = Attempted to add multiple callbacks to a delegate that does not support multicast. -Arg_NotFiniteNumberException = Number encountered was not a finite quantity. -Arg_NotSupportedException = Specified method is not supported. -Arg_UnboundGenParam = Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true. -Arg_UnboundGenField = Late bound operations cannot be performed on fields with types for which Type.ContainsGenericParameters is true. -Arg_NotGenericParameter = Method may only be called on a Type for which Type.IsGenericParameter is true. -Arg_GenericParameter = Method must be called on a Type for which Type.IsGenericParameter is false. -Arg_NotGenericTypeDefinition = {0} is not a GenericTypeDefinition. MakeGenericType may only be called on a type for which Type.IsGenericTypeDefinition is true. -Arg_NotGenericMethodDefinition = {0} is not a GenericMethodDefinition. MakeGenericMethod may only be called on a method for which MethodBase.IsGenericMethodDefinition is true. -Arg_BadLiteralFormat = Encountered an invalid type for a default value. -Arg_MissingActivationArguments = The AppDomainSetup must specify the activation arguments for this call. -Argument_BadParameterTypeForCAB = Cannot emit a CustomAttribute with argument of type {0}. -Argument_InvalidMemberForNamedArgument = The member must be either a field or a property. -Argument_InvalidTypeName = The name of the type is invalid. - -; Note - don't change the NullReferenceException default message. This was -; negotiated carefully with the VB team to avoid saying "null" or "nothing". -Arg_NullReferenceException = Object reference not set to an instance of an object. - -Arg_AccessViolationException = Attempted to read or write protected memory. This is often an indication that other memory is corrupt. -Arg_OverflowException = Arithmetic operation resulted in an overflow. -Arg_PathGlobalRoot = Paths that begin with \\\\?\\GlobalRoot are internal to the kernel and should not be opened by managed applications. -Arg_PathIllegal = The path is not of a legal form. -Arg_PathIllegalUNC = The UNC path should be of the form \\\\server\\share. -Arg_RankException = Attempted to operate on an array with the incorrect number of dimensions. -Arg_RankMultiDimNotSupported = Only single dimensional arrays are supported for the requested action. -Arg_NonZeroLowerBound = The lower bound of target array must be zero. -Arg_RegSubKeyValueAbsent = No value exists with that name. -Arg_ResourceFileUnsupportedVersion = The ResourceReader class does not know how to read this version of .resources files. Expected version: {0} This file: {1} -Arg_ResourceNameNotExist = The specified resource name "{0}" does not exist in the resource file. -Arg_SecurityException = Security error. -Arg_SerializationException = Serialization error. -Arg_StackOverflowException = Operation caused a stack overflow. -Arg_SurrogatesNotAllowedAsSingleChar = Unicode surrogate characters must be written out as pairs together in the same call, not individually. Consider passing in a character array instead. -Arg_SynchronizationLockException = Object synchronization method was called from an unsynchronized block of code. -Arg_RWLockRestoreException = ReaderWriterLock.RestoreLock was called without releasing all locks acquired since the call to ReleaseLock. -Arg_SystemException = System error. -Arg_TimeoutException = The operation has timed out. -Arg_UnauthorizedAccessException = Attempted to perform an unauthorized operation. -Arg_ArgumentException = Value does not fall within the expected range. -Arg_DirectoryNotFoundException = Attempted to access a path that is not on the disk. -Arg_DriveNotFoundException = Attempted to access a drive that is not available. -Arg_EndOfStreamException = Attempted to read past the end of the stream. -Arg_HexStyleNotSupported = The number style AllowHexSpecifier is not supported on floating point data types. -Arg_IOException = I/O error occurred. -Arg_InvalidHexStyle = With the AllowHexSpecifier bit set in the enum bit field, the only other valid bits that can be combined into the enum value must be a subset of those in HexNumber. -Arg_KeyNotFound = The given key was not present in the dictionary. -Argument_InvalidNumberStyles = An undefined NumberStyles value is being used. -Argument_InvalidDateTimeStyles = An undefined DateTimeStyles value is being used. -Argument_InvalidTimeSpanStyles = An undefined TimeSpanStyles value is being used. -Argument_DateTimeOffsetInvalidDateTimeStyles = The DateTimeStyles value 'NoCurrentDateDefault' is not allowed when parsing DateTimeOffset. -Argument_NativeResourceAlreadyDefined = Native resource has already been defined. -Argument_BadObjRef = Invalid ObjRef provided to '{0}'. -Argument_InvalidCultureName = Culture name '{0}' is not supported. -Argument_NameTooLong = The name '{0}' is too long to be a Culture or Region name, which is limited to {1} characters. -Argument_NameContainsInvalidCharacters = The name '{0}' contains characters that are not valid for a Culture or Region. -Argument_InvalidRegionName = Region name '{0}' is not supported. -Argument_CannotCreateTypedReference = Cannot use function evaluation to create a TypedReference object. -Arg_ArrayZeroError = Array must not be of length zero. -Arg_BogusIComparer = Unable to sort because the IComparer.Compare() method returns inconsistent results. Either a value does not compare equal to itself, or one value repeatedly compared to another value yields different results. IComparer: '{0}'. -Arg_CreatInstAccess = Cannot specify both CreateInstance and another access type. -Arg_CryptographyException = Error occurred during a cryptographic operation. -Arg_DateTimeRange = Combination of arguments to the DateTime constructor is out of the legal range. -Arg_DecBitCtor = Decimal byte array constructor requires an array of length four containing valid decimal bytes. -Arg_DlgtTargMeth = Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type. -Arg_DlgtTypeMis = Delegates must be of the same type. -Arg_DlgtNullInst = Delegate to an instance method cannot have null 'this'. -Arg_DllInitFailure = One machine may not have remote administration enabled, or both machines may not be running the remote registry service. -Arg_EmptyArray = Array may not be empty. -Arg_EmptyOrNullArray = Array may not be empty or null. -Arg_EmptyCollection = Collection must not be empty. -Arg_EmptyOrNullString = String may not be empty or null. -Argument_ItemNotExist = The specified item does not exist in this KeyedCollection. -Argument_EncodingNotSupported = '{0}' is not a supported encoding name. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method. -Argument_FallbackBufferNotEmpty = Cannot change fallback when buffer is not empty. Previous Convert() call left data in the fallback buffer. -Argument_InvalidCodePageConversionIndex = Unable to translate Unicode character \\u{0:X4} at index {1} to specified code page. -Argument_InvalidCodePageBytesIndex = Unable to translate bytes {0} at index {1} from specified code page to Unicode. -Argument_RecursiveFallback = Recursive fallback not allowed for character \\u{0:X4}. -Argument_RecursiveFallbackBytes = Recursive fallback not allowed for bytes {0}. -Arg_EnumAndObjectMustBeSameType = Object must be the same type as the enum. The type passed in was '{0}'; the enum type was '{1}'. -Arg_EnumIllegalVal = Illegal enum value: {0}. -Arg_EnumNotSingleFlag = Must set exactly one flag. -Arg_EnumAtLeastOneFlag = Must set at least one flag. -Arg_EnumUnderlyingTypeAndObjectMustBeSameType = Enum underlying type and the object must be same type or object must be a String. Type passed in was '{0}'; the enum underlying type was '{1}'. -Arg_EnumFormatUnderlyingTypeAndObjectMustBeSameType = Enum underlying type and the object must be same type or object. Type passed in was '{0}'; the enum underlying type was '{1}'. -Arg_EnumMustHaveUnderlyingValueField = All enums must have an underlying value__ field. -Arg_COMAccess = Must specify property Set or Get or method call for a COM Object. -Arg_COMPropSetPut = Only one of the following binding flags can be set: BindingFlags.SetProperty, BindingFlags.PutDispProperty, BindingFlags.PutRefDispProperty. -Arg_FldSetGet = Cannot specify both Get and Set on a field. -Arg_PropSetGet = Cannot specify both Get and Set on a property. -Arg_CannotBeNaN = TimeSpan does not accept floating point Not-a-Number values. -Arg_FldGetPropSet = Cannot specify both GetField and SetProperty. -Arg_FldSetPropGet = Cannot specify both SetField and GetProperty. -Arg_FldSetInvoke = Cannot specify Set on a Field and Invoke on a method. -Arg_FldGetArgErr = No arguments can be provided to Get a field value. -Arg_FldSetArgErr = Only the field value can be specified to set a field value. -Arg_GetMethNotFnd = Property Get method was not found. -Arg_GuidArrayCtor = Byte array for GUID must be exactly {0} bytes long. -Arg_HandleNotAsync = Handle does not support asynchronous operations. The parameters to the FileStream constructor may need to be changed to indicate that the handle was opened synchronously (that is, it was not opened for overlapped I/O). -Arg_HandleNotSync = Handle does not support synchronous operations. The parameters to the FileStream constructor may need to be changed to indicate that the handle was opened asynchronously (that is, it was opened explicitly for overlapped I/O). -Arg_HTCapacityOverflow = Hashtable's capacity overflowed and went negative. Check load factor, capacity and the current size of the table. -Arg_IndexMustBeInt = All indexes must be of type Int32. -Arg_InvalidConsoleColor = The ConsoleColor enum value was not defined on that enum. Please use a defined color from the enum. -Arg_InvalidFileAttrs = Invalid File or Directory attributes value. -Arg_InvalidHandle = Invalid handle. -Arg_InvalidTypeInSignature = The signature Type array contains some invalid type (i.e. null, void) -Arg_InvalidTypeInRetType = The return Type contains some invalid type (i.e. null, ByRef) -Arg_EHClauseNotFilter = This ExceptionHandlingClause is not a filter. -Arg_EHClauseNotClause = This ExceptionHandlingClause is not a clause. -Arg_ReflectionOnlyCA = It is illegal to reflect on the custom attributes of a Type loaded via ReflectionOnlyGetType (see Assembly.ReflectionOnly) -- use CustomAttributeData instead. -Arg_ReflectionOnlyInvoke = It is illegal to invoke a method on a Type loaded via ReflectionOnlyGetType. -Arg_ReflectionOnlyField = It is illegal to get or set the value on a field on a Type loaded via ReflectionOnlyGetType. -Arg_MemberInfoNullModule = The Module object containing the member cannot be null. -Arg_ParameterInfoNullMember = The MemberInfo object defining the parameter cannot be null. -Arg_ParameterInfoNullModule = The Module object containing the parameter cannot be null. -Arg_AssemblyNullModule = The manifest module of the assembly cannot be null. -Arg_LongerThanSrcArray = Source array was not long enough. Check srcIndex and length, and the array's lower bounds. -Arg_LongerThanDestArray = Destination array was not long enough. Check destIndex and length, and the array's lower bounds. -Arg_LowerBoundsMustMatch = The arrays' lower bounds must be identical. -Arg_MustBeBoolean = Object must be of type Boolean. -Arg_MustBeByte = Object must be of type Byte. -Arg_MustBeChar = Object must be of type Char. -Arg_MustBeDateTime = Object must be of type DateTime. -Arg_MustBeDateTimeOffset = Object must be of type DateTimeOffset. -Arg_MustBeDecimal = Object must be of type Decimal. -Arg_MustBeDelegate = Type must derive from Delegate. -Arg_MustBeDouble = Object must be of type Double. -Arg_MustBeDriveLetterOrRootDir = Object must be a root directory ("C:\\") or a drive letter ("C"). -Arg_MustBeEnum = Type provided must be an Enum. -Arg_MustBeEnumBaseTypeOrEnum = The value passed in must be an enum base or an underlying type for an enum, such as an Int32. -Arg_MustBeGuid = Object must be of type GUID. -Arg_MustBeIdentityReferenceType = Type must be an IdentityReference, such as NTAccount or SecurityIdentifier. -Arg_MustBeInterface = Type passed must be an interface. -Arg_MustBeInt16 = Object must be of type Int16. -Arg_MustBeInt32 = Object must be of type Int32. -Arg_MustBeInt64 = Object must be of type Int64. -Arg_MustBePrimArray = Object must be an array of primitives. -Arg_MustBePointer = Type must be a Pointer. -Arg_MustBeStatic = Method must be a static method. -Arg_MustBeString = Object must be of type String. -Arg_MustBeStringPtrNotAtom = The pointer passed in as a String must not be in the bottom 64K of the process's address space. -Arg_MustBeSByte = Object must be of type SByte. -Arg_MustBeSingle = Object must be of type Single. -Arg_MustBeTimeSpan = Object must be of type TimeSpan. -Arg_MustBeType = Type must be a type provided by the runtime. -Arg_MustBeUInt16 = Object must be of type UInt16. -Arg_MustBeUInt32 = Object must be of type UInt32. -Arg_MustBeUInt64 = Object must be of type UInt64. -Arg_MustBeVersion = Object must be of type Version. -Arg_MustBeTrue = Argument must be true. -Arg_MustAllBeRuntimeType = At least one type argument is not a runtime type. -Arg_NamedParamNull = Named parameter value must not be null. -Arg_NamedParamTooBig = Named parameter array cannot be bigger than argument array. -Arg_Need1DArray = Array was not a one-dimensional array. -Arg_Need2DArray = Array was not a two-dimensional array. -Arg_Need3DArray = Array was not a three-dimensional array. -Arg_NeedAtLeast1Rank = Must provide at least one rank. -Arg_NoDefCTor = No parameterless constructor defined for this object. -Arg_BitArrayTypeUnsupported = Only supported array types for CopyTo on BitArrays are Boolean[], Int32[] and Byte[]. -Arg_DivideByZero = Attempted to divide by zero. -Arg_NoAccessSpec = Must specify binding flags describing the invoke operation required (BindingFlags.InvokeMethod CreateInstance GetField SetField GetProperty SetProperty). -Arg_NoStaticVirtual = Method cannot be both static and virtual. -Arg_NotFoundIFace = Interface not found. -Arg_ObjObjEx = Object of type '{0}' cannot be converted to type '{1}'. -Arg_ObjObj = Object type cannot be converted to target type. -Arg_FieldDeclTarget = Field '{0}' defined on type '{1}' is not a field on the target object which is of type '{2}'. -Arg_OleAutDateInvalid = Not a legal OleAut date. -Arg_OleAutDateScale = OleAut date did not convert to a DateTime correctly. -Arg_PlatformNotSupported = Operation is not supported on this platform. -Arg_PlatformSecureString = SecureString is only supported on Windows 2000 SP3 and higher platforms. -Arg_ParmCnt = Parameter count mismatch. -Arg_ParmArraySize = Must specify one or more parameters. -Arg_Path2IsRooted = Second path fragment must not be a drive or UNC name. -Arg_PathIsVolume = Path must not be a drive. -Arg_PrimWiden = Cannot widen from source type to target type either because the source type is a not a primitive type or the conversion cannot be accomplished. -Arg_NullIndex = Arrays indexes must be set to an object instance. -Arg_VarMissNull = Missing parameter does not have a default value. -Arg_PropSetInvoke = Cannot specify Set on a property and Invoke on a method. -Arg_PropNotFound = Could not find the specified property. -Arg_RankIndices = Indices length does not match the array rank. -Arg_RanksAndBounds = Number of lengths and lowerBounds must match. -Arg_RegSubKeyAbsent = Cannot delete a subkey tree because the subkey does not exist. -Arg_RemoveArgNotFound = Cannot remove the specified item because it was not found in the specified Collection. -Arg_RegKeyDelHive = Cannot delete a registry hive's subtree. -Arg_RegKeyNoRemoteConnect = No remote connection to '{0}' while trying to read the registry. -Arg_RegKeyOutOfRange = Registry HKEY was out of the legal range. -Arg_RegKeyNotFound = The specified registry key does not exist. -Arg_RegKeyStrLenBug = Registry key names should not be greater than 255 characters. -Arg_RegValStrLenBug = Registry value names should not be greater than 16,383 characters. -Arg_RegBadKeyKind = The specified RegistryValueKind is an invalid value. -Arg_RegGetOverflowBug = RegistryKey.GetValue does not allow a String that has a length greater than Int32.MaxValue. -Arg_RegSetMismatchedKind = The type of the value object did not match the specified RegistryValueKind or the object could not be properly converted. -Arg_RegSetBadArrType = RegistryKey.SetValue does not support arrays of type '{0}'. Only Byte[] and String[] are supported. -Arg_RegSetStrArrNull = RegistryKey.SetValue does not allow a String[] that contains a null String reference. -Arg_RegInvalidKeyName = Registry key name must start with a valid base key name. -Arg_ResMgrNotResSet = Type parameter must refer to a subclass of ResourceSet. -Arg_SetMethNotFnd = Property set method not found. -Arg_TypeRefPrimitve = TypedReferences cannot be redefined as primitives. -Arg_UnknownTypeCode = Unknown TypeCode value. -Arg_VersionString = Version string portion was too short or too long. -Arg_NoITypeInfo = Specified TypeInfo was invalid because it did not support the ITypeInfo interface. -Arg_NoITypeLib = Specified TypeLib was invalid because it did not support the ITypeLib interface. -Arg_NoImporterCallback = Specified type library importer callback was invalid because it did not support the ITypeLibImporterNotifySink interface. -Arg_ImporterLoadFailure = The type library importer encountered an error during type verification. Try importing without class members. -Arg_InvalidBase = Invalid Base. -Arg_EnumValueNotFound = Requested value '{0}' was not found. -Arg_EnumLitValueNotFound = Literal value was not found. -Arg_MustContainEnumInfo = Must specify valid information for parsing in the string. -Arg_InvalidSearchPattern = Search pattern cannot contain ".." to move up directories and can be contained only internally in file/directory names, as in "a..b". -Arg_NegativeArgCount = Argument count must not be negative. -Arg_InvalidAccessEntry = Specified access entry is invalid because it is unrestricted. The global flags should be specified instead. -Arg_InvalidFileName = Specified file name was invalid. -Arg_InvalidFileExtension = Specified file extension was not a valid extension. -Arg_COMException = Error HRESULT E_FAIL has been returned from a call to a COM component. -Arg_ExternalException = External component has thrown an exception. -Arg_InvalidComObjectException = Attempt has been made to use a COM object that does not have a backing class factory. -Arg_InvalidOleVariantTypeException = Specified OLE variant was invalid. -Arg_MarshalDirectiveException = Marshaling directives are invalid. -Arg_MarshalAsAnyRestriction = AsAny cannot be used on return types, ByRef parameters, ArrayWithOffset, or parameters passed from unmanaged to managed. -Arg_NDirectBadObject = No PInvoke conversion exists for value passed to Object-typed parameter. -Arg_SafeArrayTypeMismatchException = Specified array was not of the expected type. -Arg_VTableCallsNotSupportedException = Attempted to make an early bound call on a COM dispatch-only interface. -Arg_SafeArrayRankMismatchException = Specified array was not of the expected rank. -Arg_AmbiguousMatchException = Ambiguous match found. -Arg_CustomAttributeFormatException = Binary format of the specified custom attribute was invalid. -Arg_InvalidFilterCriteriaException = Specified filter criteria was invalid. -Arg_TypeLoadNullStr = A null or zero length string does not represent a valid Type. -Arg_TargetInvocationException = Exception has been thrown by the target of an invocation. -Arg_TargetParameterCountException = Number of parameters specified does not match the expected number. -Arg_TypeAccessException = Attempt to access the type failed. -Arg_TypeLoadException = Failure has occurred while loading a type. -Arg_TypeUnloadedException = Type had been unloaded. -Arg_ThreadStateException = Thread was in an invalid state for the operation being executed. -Arg_ThreadStartException = Thread failed to start. -Arg_WrongAsyncResult = IAsyncResult object did not come from the corresponding async method on this type. -Arg_WrongType = The value "{0}" is not of type "{1}" and cannot be used in this generic collection. -Argument_InvalidArgumentForComparison = Type of argument is not compatible with the generic comparer. -Argument_ALSInvalidCapacity = Specified capacity must not be less than the current capacity. -Argument_ALSInvalidSlot = Specified slot number was invalid. -Argument_IdnIllegalName = Decoded string is not a valid IDN name. -Argument_IdnBadBidi = Left to right characters may not be mixed with right to left characters in IDN labels. -Argument_IdnBadLabelSize = IDN labels must be between 1 and 63 characters long. -Argument_IdnBadNameSize = IDN names must be between 1 and {0} characters long. -Argument_IdnBadPunycode = Invalid IDN encoded string. -Argument_IdnBadStd3 = Label contains character '{0}' not allowed with UseStd3AsciiRules -Arg_InvalidANSIString = The ANSI string passed in could not be converted from the default ANSI code page to Unicode. -Arg_InvalidUTF8String = The UTF8 string passed in could not be converted to Unicode. -Argument_InvalidCharSequence = Invalid Unicode code point found at index {0}. -Argument_InvalidCharSequenceNoIndex = String contains invalid Unicode code points. -Argument_InvalidCalendar = Not a valid calendar for the given culture. -Argument_InvalidNormalizationForm = Invalid or unsupported normalization form. -Argument_InvalidPathChars = Illegal characters in path. -Argument_InvalidOffLen = 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. -Argument_InvalidSeekOrigin = Invalid seek origin. -Argument_SeekOverflow = The specified seek offset '{0}' would result in a negative Stream position. -Argument_InvalidUnity = Invalid Unity type. -Argument_LongEnvVarName = Environment variable name cannot contain 1024 or more characters. -Argument_LongEnvVarValue = Environment variable name or value is too long. -Argument_StringFirstCharIsZero = The first char in the string is the null character. -Argument_OnlyMscorlib = Only mscorlib's assembly is valid. -Argument_PathEmpty = Path cannot be the empty string or all whitespace. -Argument_PathFormatNotSupported = The given path's format is not supported. -Argument_PathUriFormatNotSupported = URI formats are not supported. -Argument_TypeNameTooLong = Type name was too long. The fully qualified type name must be less than 1,024 characters. -Argument_StreamNotReadable = Stream was not readable. -Argument_StreamNotWritable = Stream was not writable. -Argument_InvalidNumberOfMembers = MemberData contains an invalid number of members. -Argument_InvalidValue = Value was invalid. -Argument_InvalidKey = Key was invalid. -Argument_MinMaxValue = '{0}' cannot be greater than {1}. -Argument_InvalidGroupSize = Every element in the value array should be between one and nine, except for the last element, which can be zero. -Argument_MustHaveAttributeBaseClass = Type passed in must be derived from System.Attribute or System.Attribute itself. -Argument_NoUninitializedStrings = Uninitialized Strings cannot be created. -Argument_UnequalMembers = Supplied MemberInfo does not match the expected type. -Argument_BadFormatSpecifier = Format specifier was invalid. -Argument_InvalidHighSurrogate = Found a high surrogate char without a following low surrogate at index: {0}. The input may not be in this encoding, or may not contain valid Unicode (UTF-16) characters. -Argument_InvalidLowSurrogate = Found a low surrogate char without a preceding high surrogate at index: {0}. The input may not be in this encoding, or may not contain valid Unicode (UTF-16) characters. -Argument_UnmatchingSymScope = Non-matching symbol scope. -Argument_NotInExceptionBlock = Not currently in an exception block. -Argument_BadExceptionCodeGen = Incorrect code generation for exception block. -Argument_NotExceptionType = Does not extend Exception. -Argument_DuplicateResourceName = Duplicate resource name within an assembly. -Argument_BadPersistableModuleInTransientAssembly = Cannot have a persistable module in a transient assembly. -Argument_InvalidPermissionState = Invalid permission state. -Argument_UnrestrictedIdentityPermission = Identity permissions cannot be unrestricted. -Argument_WrongType = Operation on type '{0}' attempted with target of incorrect type. -Argument_IllegalZone = Illegal security permission zone specified. -Argument_HasToBeArrayClass = Must be an array type. -Argument_InvalidDirectory = Invalid directory, '{0}'. -Argument_DataLengthDifferent = Parameters 'members' and 'data' must have the same length. -Argument_SigIsFinalized = Completed signature cannot be modified. -Argument_ArraysInvalid = Array or pointer types are not valid. -Argument_GenericsInvalid = Generic types are not valid. -Argument_LargeInteger = Integer or token was too large to be encoded. -Argument_BadSigFormat = Incorrect signature format. -Argument_UnmatchedMethodForLocal = Local passed in does not belong to this ILGenerator. -Argument_DuplicateName = Tried to add NamedPermissionSet with non-unique name. -Argument_InvalidXMLElement = Invalid XML. Missing required tag <{0}> for type '{1}'. -Argument_InvalidXMLMissingAttr = Invalid XML. Missing required attribute '{0}'. -Argument_CannotGetTypeTokenForByRef = Cannot get TypeToken for a ByRef type. -Argument_NotASimpleNativeType = The UnmanagedType passed to DefineUnmanagedMarshal is not a simple type. None of the following values may be used: UnmanagedType.ByValTStr, UnmanagedType.SafeArray, UnmanagedType.ByValArray, UnmanagedType.LPArray, UnmanagedType.CustomMarshaler. -Argument_NotACustomMarshaler = Not a custom marshal. -Argument_NoUnmanagedElementCount = Unmanaged marshal does not have ElementCount. -Argument_NoNestedMarshal = Only LPArray or SafeArray has nested unmanaged marshal. -Argument_InvalidXML = Invalid Xml. -Argument_NoUnderlyingCCW = The object has no underlying COM data associated with it. -Argument_BadFieldType = Bad field type in defining field. -Argument_InvalidXMLBadVersion = Invalid Xml - can only parse elements of version one. -Argument_NotAPermissionElement = 'elem' was not a permission element. -Argument_NPMSInvalidName = Name can be neither null nor empty. -Argument_InvalidElementTag = Invalid element tag '{0}'. -Argument_InvalidElementText = Invalid element text '{0}'. -Argument_InvalidElementName = Invalid element name '{0}'. -Argument_InvalidElementValue = Invalid element value '{0}'. -Argument_AttributeNamesMustBeUnique = Attribute names must be unique. -#if FEATURE_CAS_POLICY -Argument_UninitializedCertificate = Uninitialized certificate object. -Argument_MembershipConditionElement = Element must be a element. -Argument_ReservedNPMS = Cannot remove or modify reserved permissions set '{0}'. -Argument_NPMSInUse = Permission set '{0}' was in use and could not be deleted. -Argument_StrongNameGetPublicKey = Unable to obtain public key for StrongNameKeyPair. -Argument_SiteCannotBeNull = Site name must be specified. -Argument_BlobCannotBeNull = Public key must be specified. -Argument_ZoneCannotBeNull = Zone must be specified. -Argument_UrlCannotBeNull = URL must be specified. -Argument_NoNPMS = Unable to find a permission set with the provided name. -Argument_FailedCodeGroup = Failed to create a code group of type '{0}'. -Argument_CodeGroupChildrenMustBeCodeGroups = All objects in the input list must have a parent type of 'CodeGroup'. -#endif // FEATURE_CAS_POLICY -#if FEATURE_IMPERSONATION -Argument_InvalidPrivilegeName = Privilege '{0}' is not valid on this system. -Argument_TokenZero = Token cannot be zero. -Argument_InvalidImpersonationToken = Invalid token for impersonation - it cannot be duplicated. -Argument_ImpersonateUser = Unable to impersonate user. -#endif // FEATURE_IMPERSONATION -Argument_InvalidHexFormat = Improperly formatted hex string. -Argument_InvalidSite = Invalid site. -Argument_InterfaceMap = 'this' type cannot be an interface itself. -Argument_ArrayGetInterfaceMap = Interface maps for generic interfaces on arrays cannot be retrieved. -Argument_InvalidName = Invalid name. -Argument_InvalidDirectoryOnUrl = Invalid directory on URL. -Argument_InvalidUrl = Invalid URL. -Argument_InvalidKindOfTypeForCA = This type cannot be represented as a custom attribute. -Argument_MustSupplyContainer = When supplying a FieldInfo for fixing up a nested type, a valid ID for that containing object must also be supplied. -Argument_MustSupplyParent = When supplying the ID of a containing object, the FieldInfo that identifies the current field within that object must also be supplied. -Argument_NoClass = Element does not specify a class. -Argument_WrongElementType = '{0}' element required. -Argument_UnableToGeneratePermissionSet = Unable to generate permission set; input XML may be malformed. -Argument_NoEra = No Era was supplied. -Argument_AssemblyAlreadyFullTrust = Assembly was already fully trusted. -Argument_AssemblyNotFullTrust = Assembly was not fully trusted. -Argument_AssemblyWinMD = Assembly must not be a Windows Runtime assembly. -Argument_MemberAndArray = Cannot supply both a MemberInfo and an Array to indicate the parent of a value type. -Argument_ObjNotComObject = The object's type must be __ComObject or derived from __ComObject. -Argument_ObjIsWinRTObject = The object's type must not be a Windows Runtime type. -Argument_TypeNotComObject = The type must be __ComObject or be derived from __ComObject. -Argument_TypeIsWinRTType = The type must not be a Windows Runtime type. -Argument_CantCallSecObjFunc = Cannot evaluate a security function. -Argument_StructMustNotBeValueClass = The structure must not be a value class. -Argument_NoSpecificCulture = Please select a specific culture, such as zh-CN, zh-HK, zh-TW, zh-MO, zh-SG. -Argument_InvalidResourceCultureName = The given culture name '{0}' cannot be used to locate a resource file. Resource filenames must consist of only letters, numbers, hyphens or underscores. -Argument_InvalidParamInfo = Invalid type for ParameterInfo member in Attribute class. -Argument_EmptyDecString = Decimal separator cannot be the empty string. -Argument_OffsetOfFieldNotFound = Field passed in is not a marshaled member of the type '{0}'. -Argument_EmptyStrongName = StrongName cannot have an empty string for the assembly name. -Argument_NotSerializable = Argument passed in is not serializable. -Argument_EmptyApplicationName = ApplicationId cannot have an empty string for the name. -Argument_NoDomainManager = The domain manager specified by the host could not be instantiated. -Argument_NoMain = Main entry point not defined. -Argument_InvalidDateTimeKind = Invalid DateTimeKind value. -Argument_ConflictingDateTimeStyles = The DateTimeStyles values AssumeLocal and AssumeUniversal cannot be used together. -Argument_ConflictingDateTimeRoundtripStyles = The DateTimeStyles value RoundtripKind cannot be used with the values AssumeLocal, AssumeUniversal or AdjustToUniversal. -Argument_InvalidDigitSubstitution = The DigitSubstitution property must be of a valid member of the DigitShapes enumeration. Valid entries include Context, NativeNational or None. -Argument_InvalidNativeDigitCount = The NativeDigits array must contain exactly ten members. -Argument_InvalidNativeDigitValue = Each member of the NativeDigits array must be a single text element (one or more UTF16 code points) with a Unicode Nd (Number, Decimal Digit) property indicating it is a digit. -ArgumentException_InvalidAceBinaryForm = The binary form of an ACE object is invalid. -ArgumentException_InvalidAclBinaryForm = The binary form of an ACL object is invalid. -ArgumentException_InvalidSDSddlForm = The SDDL form of a security descriptor object is invalid. -Argument_InvalidSafeHandle = The SafeHandle is invalid. -Argument_CannotPrepareAbstract = Abstract methods cannot be prepared. -Argument_ArrayTooLarge = The input array length must not exceed Int32.MaxValue / {0}. Otherwise BitArray.Length would exceed Int32.MaxValue. -Argument_RelativeUrlMembershipCondition = UrlMembershipCondition requires an absolute URL. -Argument_EmptyWaithandleArray = Waithandle array may not be empty. -Argument_InvalidSafeBufferOffLen = Offset and length were greater than the size of the SafeBuffer. -Argument_NotEnoughBytesToRead = There are not enough bytes remaining in the accessor to read at this position. -Argument_NotEnoughBytesToWrite = There are not enough bytes remaining in the accessor to write at this position. -Argument_OffsetAndLengthOutOfBounds = 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. -Argument_OffsetAndCapacityOutOfBounds = Offset and capacity were greater than the size of the view. -Argument_UnmanagedMemAccessorWrapAround = The UnmanagedMemoryAccessor capacity and offset would wrap around the high end of the address space. -Argument_UnrecognizedLoaderOptimization = Unrecognized LOADER_OPTIMIZATION property value. Supported values may include "SingleDomain", "MultiDomain", "MultiDomainHost", and "NotSpecified". -ArgumentException_NotAllCustomSortingFuncsDefined = Implementations of all the NLS functions must be provided. -ArgumentException_MinSortingVersion = The runtime does not support a version of "{0}" less than {1}. - -; -; ===================================================== -; Reflection Emit resource strings -Arugment_EmitMixedContext1 = Type '{0}' was loaded in the ReflectionOnly context but the AssemblyBuilder was not created as AssemblyBuilderAccess.ReflectionOnly. -Arugment_EmitMixedContext2 = Type '{0}' was not loaded in the ReflectionOnly context but the AssemblyBuilder was created as AssemblyBuilderAccess.ReflectionOnly. -Argument_BadSizeForData = Data size must be > 0 and < 0x3f0000 -Argument_InvalidLabel = Invalid Label. -Argument_RedefinedLabel = Label multiply defined. -Argument_UnclosedExceptionBlock = The IL Generator cannot be used while there are unclosed exceptions. -Argument_MissingDefaultConstructor = was missing default constructor. -Argument_TooManyFinallyClause = Exception blocks may have at most one finally clause. -Argument_NotInTheSameModuleBuilder = The argument passed in was not from the same ModuleBuilder. -Argument_BadCurrentLocalVariable = Bad current local variable for setting symbol information. -Argument_DuplicateModuleName = Duplicate dynamic module name within an assembly. -Argument_DuplicateTypeName = Duplicate type name within an assembly. -Argument_InvalidAssemblyName = Assembly names may not begin with whitespace or contain the characters '/', or '\\' or ':'. -Argument_InvalidGenericInstantiation = The given generic instantiation was invalid. -Argument_DuplicatedFileName = Duplicate file names. -Argument_GlobalFunctionHasToBeStatic = Global members must be static. -Argument_BadPInvokeOnInterface = PInvoke methods cannot exist on interfaces. -Argument_BadPInvokeMethod = PInvoke methods must be static and native and cannot be abstract. -Argument_MethodRedefined = Method has been already defined. -Argument_BadTypeAttrAbstractNFinal = Bad type attributes. A type cannot be both abstract and final. -Argument_BadTypeAttrNestedVisibilityOnNonNestedType = Bad type attributes. Nested visibility flag set on a non-nested type. -Argument_BadTypeAttrNonNestedVisibilityNestedType = Bad type attributes. Non-nested visibility flag set on a nested type. -Argument_BadTypeAttrInvalidLayout = Bad type attributes. Invalid layout attribute specified. -Argument_BadTypeAttrReservedBitsSet = Bad type attributes. Reserved bits set on the type. -Argument_BadFieldSig = Field signatures do not have return types. -Argument_ShouldOnlySetVisibilityFlags = Should only set visibility flags when creating EnumBuilder. -Argument_BadNestedTypeFlags = Visibility of interfaces must be one of the following: NestedAssembly, NestedFamANDAssem, NestedFamily, NestedFamORAssem, NestedPrivate or NestedPublic. -Argument_ShouldNotSpecifyExceptionType = Should not specify exception type for catch clause for filter block. -Argument_BadLabel = Bad label in ILGenerator. -Argument_BadLabelContent = Bad label content in ILGenerator. -Argument_EmitWriteLineType = EmitWriteLine does not support this field or local type. -Argument_ConstantNull = Null is not a valid constant value for this type. -Argument_ConstantDoesntMatch = Constant does not match the defined type. -Argument_ConstantNotSupported = {0} is not a supported constant type. -Argument_BadConstructor = Cannot have private or static constructor. -Argument_BadConstructorCallConv = Constructor must have standard calling convention. -Argument_BadPropertyForConstructorBuilder = Property must be on the same type of the given ConstructorInfo. -Argument_NotAWritableProperty = Not a writable property. -Argument_BadFieldForConstructorBuilder = Field must be on the same type of the given ConstructorInfo. -Argument_BadAttributeOnInterfaceMethod = Interface method must be abstract and virtual. -ArgumentException_BadMethodImplBody = MethodOverride's body must be from this type. -Argument_BadParameterCountsForConstructor = Parameter count does not match passed in argument value count. -Argument_BadParameterTypeForConstructor = Passed in argument value at index {0} does not match the parameter type. -Argument_BadTypeInCustomAttribute = An invalid type was used as a custom attribute constructor argument, field or property. -Argument_DateTimeBadBinaryData = The binary data must result in a DateTime with ticks between DateTime.MinValue.Ticks and DateTime.MaxValue.Ticks. -Argument_VerStringTooLong = The unmanaged Version information is too large to persist. -Argument_UnknownUnmanagedCallConv = Unknown unmanaged calling convention for function signature. -Argument_BadConstantValue = Bad default value. -Argument_IllegalName = Illegal name. -Argument_cvtres_NotFound = Cannot find cvtres.exe -Argument_BadCAForUnmngRSC = Bad '{0}' while generating unmanaged resource information. -Argument_MustBeInterfaceMethod = The MemberInfo must be an interface method. -Argument_CORDBBadVarArgCallConv = Cannot evaluate a VarArgs function. -Argument_CORDBBadMethod = Cannot find the method on the object instance. -Argument_InvalidOpCodeOnDynamicMethod = Ldtoken, Ldftn and Ldvirtftn OpCodes cannot target DynamicMethods. -Argument_InvalidTypeForDynamicMethod = Invalid type owner for DynamicMethod. -Argument_NeedGenericMethodDefinition = Method must represent a generic method definition on a generic type definition. -Argument_MethodNeedGenericDeclaringType = The specified method cannot be dynamic or global and must be declared on a generic type definition. -Argument_ConstructorNeedGenericDeclaringType = The specified constructor must be declared on a generic type definition. -Argument_FieldNeedGenericDeclaringType = The specified field must be declared on a generic type definition. -Argument_InvalidMethodDeclaringType = The specified method must be declared on the generic type definition of the specified type. -Argument_InvalidConstructorDeclaringType = The specified constructor must be declared on the generic type definition of the specified type. -Argument_InvalidFieldDeclaringType = The specified field must be declared on the generic type definition of the specified type. -Argument_NeedNonGenericType = The specified Type must not be a generic type definition. -Argument_MustBeTypeBuilder = 'type' must contain a TypeBuilder as a generic argument. -Argument_CannotSetParentToInterface = Cannot set parent to an interface. -Argument_MismatchedArrays = Two arrays, {0} and {1}, must be of the same size. -Argument_NeedNonGenericObject = The specified object must not be an instance of a generic type. -Argument_NeedStructWithNoRefs = The specified Type must be a struct containing no references. -Argument_NotMethodCallOpcode = The specified opcode cannot be passed to EmitCall. - -; ===================================================== -; -Argument_ModuleAlreadyLoaded = The specified module has already been loaded. -Argument_MustHaveLayoutOrBeBlittable = The specified structure must be blittable or have layout information. -Argument_NotSimpleFileName = The filename must not include a path specification. -Argument_TypeMustBeVisibleFromCom = The specified type must be visible from COM. -Argument_TypeMustBeComCreatable = The type must be creatable from COM. -Argument_TypeMustNotBeComImport = The type must not be imported from COM. -Argument_PolicyFileDoesNotExist = The requested policy file does not exist. -Argument_NonNullObjAndCtx = Either obj or ctx must be null. -Argument_NoModuleFileExtension = Module file name '{0}' must have file extension. -Argument_TypeDoesNotContainMethod = Type does not contain the given method. -Argument_StringZeroLength = String cannot be of zero length. -Argument_MustBeString = String is too long or has invalid contents. -Argument_AbsolutePathRequired = Absolute path information is required. -Argument_ManifestFileDoesNotExist = The specified manifest file does not exist. -Argument_MustBeRuntimeType = Type must be a runtime Type object. -Argument_TypeNotValid = The Type object is not valid. -Argument_MustBeRuntimeMethodInfo = MethodInfo must be a runtime MethodInfo object. -Argument_MustBeRuntimeFieldInfo = FieldInfo must be a runtime FieldInfo object. -Argument_InvalidFieldInfo = The FieldInfo object is not valid. -Argument_InvalidConstructorInfo = The ConstructorInfo object is not valid. -Argument_MustBeRuntimeAssembly = Assembly must be a runtime Assembly object. -Argument_MustBeRuntimeModule = Module must be a runtime Module object. -Argument_MustBeRuntimeParameterInfo = ParameterInfo must be a runtime ParameterInfo object. -Argument_InvalidParameterInfo = The ParameterInfo object is not valid. -Argument_MustBeRuntimeReflectionObject = The object must be a runtime Reflection object. -Argument_InvalidMarshalByRefObject = The MarshalByRefObject is not valid. -Argument_TypedReferenceInvalidField = Field in TypedReferences cannot be static or init only. -Argument_HandleLeak = Cannot pass a GCHandle across AppDomains. -Argument_ArgumentZero = Argument cannot be zero. -Argument_ImproperType = Improper types in collection. -Argument_NotAMembershipCondition = The type does not implement IMembershipCondition -Argument_NotAPermissionType = The type does not implement IPermission -Argument_NotACodeGroupType = The type does not inherit from CodeGroup -Argument_NotATP = Type must be a TransparentProxy -Argument_AlreadyACCW = The object already has a CCW associated with it. -Argument_OffsetLocalMismatch = The UTC Offset of the local dateTime parameter does not match the offset argument. -Argument_OffsetUtcMismatch = The UTC Offset for Utc DateTime instances must be 0. -Argument_UTCOutOfRange = The UTC time represented when the offset is applied must be between year 0 and 10,000. -Argument_OffsetOutOfRange = Offset must be within plus or minus 14 hours. -Argument_OffsetPrecision = Offset must be specified in whole minutes. -Argument_FlagNotSupported = One or more flags are not supported. -Argument_MustBeFalse = Argument must be initialized to false -Argument_ToExclusiveLessThanFromExclusive = fromInclusive must be less than or equal to toExclusive. -Argument_FrameworkNameTooShort=FrameworkName cannot have less than two components or more than three components. -Argument_FrameworkNameInvalid=FrameworkName is invalid. -Argument_FrameworkNameMissingVersion=FrameworkName version component is missing. -#if FEATURE_COMINTEROP -Argument_TypeNotActivatableViaWindowsRuntime = Type '{0}' does not have an activation factory because it is not activatable by Windows Runtime. -Argument_WinRTSystemRuntimeType = Cannot marshal type '{0}' to Windows Runtime. Only 'System.RuntimeType' is supported. -Argument_Unexpected_TypeSource = Unexpected TypeKind when marshaling Windows.Foundation.TypeName. -#endif // FEATURE_COMINTEROP - -; ArgumentNullException -ArgumentNull_Array = Array cannot be null. -ArgumentNull_ArrayValue = Found a null value within an array. -ArgumentNull_ArrayElement = At least one element in the specified array was null. -ArgumentNull_Assembly = Assembly cannot be null. -ArgumentNull_AssemblyName = AssemblyName cannot be null. -ArgumentNull_AssemblyNameName = AssemblyName.Name cannot be null or an empty string. -ArgumentNull_Buffer = Buffer cannot be null. -ArgumentNull_Collection = Collection cannot be null. -ArgumentNull_CultureInfo = CultureInfo cannot be null. -ArgumentNull_Dictionary = Dictionary cannot be null. -ArgumentNull_FileName = File name cannot be null. -ArgumentNull_Key = Key cannot be null. -ArgumentNull_Graph = Object Graph cannot be null. -ArgumentNull_Path = Path cannot be null. -ArgumentNull_Stream = Stream cannot be null. -ArgumentNull_String = String reference not set to an instance of a String. -ArgumentNull_Type = Type cannot be null. -ArgumentNull_Obj = Object cannot be null. -ArgumentNull_GUID = GUID cannot be null. -ArgumentNull_NullMember = Member at position {0} was null. -ArgumentNull_Generic = Value cannot be null. -ArgumentNull_WithParamName = Parameter '{0}' cannot be null. -ArgumentNull_Child = Cannot have a null child. -ArgumentNull_SafeHandle = SafeHandle cannot be null. -ArgumentNull_CriticalHandle = CriticalHandle cannot be null. -ArgumentNull_TypedRefType = Type in TypedReference cannot be null. -ArgumentNull_ApplicationTrust = The application trust cannot be null. -ArgumentNull_TypeRequiredByResourceScope = The type parameter cannot be null when scoping the resource's visibility to Private or Assembly. -ArgumentNull_Waithandles = The waitHandles parameter cannot be null. - -; ArgumentOutOfRangeException -ArgumentOutOfRange_AddressSpace = The number of bytes cannot exceed the virtual address space on a 32 bit machine. -ArgumentOutOfRange_ArrayLB = Number was less than the array's lower bound in the first dimension. -ArgumentOutOfRange_ArrayLBAndLength = Higher indices will exceed Int32.MaxValue because of large lower bound and/or length. -ArgumentOutOfRange_ArrayLength = The length of the array must be between {0} and {1}, inclusive. -ArgumentOutOfRange_ArrayLengthMultiple = The length of the array must be a multiple of {0}. -ArgumentOutOfRange_ArrayListInsert = Insertion index was out of range. Must be non-negative and less than or equal to size. -ArgumentOutOfRange_ArrayTooSmall = Destination array is not long enough to copy all the required data. Check array length and offset. -ArgumentOutOfRange_BeepFrequency = Console.Beep's frequency must be between {0} and {1}. -ArgumentOutOfRange_BiggerThanCollection = Larger than collection size. -ArgumentOutOfRange_Bounds_Lower_Upper = Argument must be between {0} and {1}. -ArgumentOutOfRange_Count = Count must be positive and count must refer to a location within the string/array/collection. -ArgumentOutOfRange_CalendarRange = Specified time is not supported in this calendar. It should be between {0} (Gregorian date) and {1} (Gregorian date), inclusive. -ArgumentOutOfRange_ConsoleBufferBoundaries = The value must be greater than or equal to zero and less than the console's buffer size in that dimension. -ArgumentOutOfRange_ConsoleBufferLessThanWindowSize = The console buffer size must not be less than the current size and position of the console window, nor greater than or equal to Int16.MaxValue. -ArgumentOutOfRange_ConsoleWindowBufferSize = The new console window size would force the console buffer size to be too large. -ArgumentOutOfRange_ConsoleTitleTooLong = The console title is too long. -ArgumentOutOfRange_ConsoleWindowPos = The window position must be set such that the current window size fits within the console's buffer, and the numbers must not be negative. -ArgumentOutOfRange_ConsoleWindowSize_Size = The value must be less than the console's current maximum window size of {0} in that dimension. Note that this value depends on screen resolution and the console font. -ArgumentOutOfRange_ConsoleKey = Console key values must be between 0 and 255. -ArgumentOutOfRange_CursorSize = The cursor size is invalid. It must be a percentage between 1 and 100. -ArgumentOutOfRange_BadYearMonthDay = Year, Month, and Day parameters describe an un-representable DateTime. -ArgumentOutOfRange_BadHourMinuteSecond = Hour, Minute, and Second parameters describe an un-representable DateTime. -ArgumentOutOfRange_DateArithmetic = The added or subtracted value results in an un-representable DateTime. -ArgumentOutOfRange_DateTimeBadMonths = Months value must be between +/-120000. -ArgumentOutOfRange_DateTimeBadYears = Years value must be between +/-10000. -ArgumentOutOfRange_DateTimeBadTicks = Ticks must be between DateTime.MinValue.Ticks and DateTime.MaxValue.Ticks. -ArgumentOutOfRange_Day = Day must be between 1 and {0} for month {1}. -ArgumentOutOfRange_DecimalRound = Decimal can only round to between 0 and 28 digits of precision. -ArgumentOutOfRange_DecimalScale = Decimal's scale value must be between 0 and 28, inclusive. -ArgumentOutOfRange_Era = Time value was out of era range. -ArgumentOutOfRange_Enum = Enum value was out of legal range. -ArgumentOutOfRange_FileLengthTooBig = Specified file length was too large for the file system. -ArgumentOutOfRange_FileTimeInvalid = Not a valid Win32 FileTime. -ArgumentOutOfRange_GetByteCountOverflow = Too many characters. The resulting number of bytes is larger than what can be returned as an int. -ArgumentOutOfRange_GetCharCountOverflow = Too many bytes. The resulting number of chars is larger than what can be returned as an int. -ArgumentOutOfRange_HashtableLoadFactor = Load factor needs to be between 0.1 and 1.0. -ArgumentOutOfRange_HugeArrayNotSupported = Arrays larger than 2GB are not supported. -ArgumentOutOfRange_InvalidHighSurrogate = A valid high surrogate character is between 0xd800 and 0xdbff, inclusive. -ArgumentOutOfRange_InvalidLowSurrogate = A valid low surrogate character is between 0xdc00 and 0xdfff, inclusive. -ArgumentOutOfRange_InvalidEraValue = Era value was not valid. -ArgumentOutOfRange_InvalidUserDefinedAceType = User-defined ACEs must not have a well-known ACE type. -ArgumentOutOfRange_InvalidUTF32 = A valid UTF32 value is between 0x000000 and 0x10ffff, inclusive, and should not include surrogate codepoint values (0x00d800 ~ 0x00dfff). -ArgumentOutOfRange_Index = Index was out of range. Must be non-negative and less than the size of the collection. -ArgumentOutOfRange_IndexString = Index was out of range. Must be non-negative and less than the length of the string. -ArgumentOutOfRange_StreamLength = Stream length must be non-negative and less than 2^31 - 1 - origin. -ArgumentOutOfRange_LessEqualToIntegerMaxVal = Argument must be less than or equal to 2^31 - 1 milliseconds. -ArgumentOutOfRange_Month = Month must be between one and twelve. -ArgumentOutOfRange_MustBeNonNegInt32 = Value must be non-negative and less than or equal to Int32.MaxValue. -ArgumentOutOfRange_NeedNonNegNum = Non-negative number required. -ArgumentOutOfRange_NeedNonNegOrNegative1 = Number must be either non-negative and less than or equal to Int32.MaxValue or -1. -ArgumentOutOfRange_NeedPosNum = Positive number required. -ArgumentOutOfRange_NegativeCapacity = Capacity must be positive. -ArgumentOutOfRange_NegativeCount = Count cannot be less than zero. -ArgumentOutOfRange_NegativeLength = Length cannot be less than zero. -ArgumentOutOfRange_NegFileSize = Length must be non-negative. -ArgumentOutOfRange_ObjectID = objectID cannot be less than or equal to zero. -ArgumentOutOfRange_SmallCapacity = capacity was less than the current size. -ArgumentOutOfRange_QueueGrowFactor = Queue grow factor must be between {0} and {1}. -ArgumentOutOfRange_RoundingDigits = Rounding digits must be between 0 and 15, inclusive. -ArgumentOutOfRange_StartIndex = StartIndex cannot be less than zero. -ArgumentOutOfRange_MustBePositive = '{0}' must be greater than zero. -ArgumentOutOfRange_MustBeNonNegNum = '{0}' must be non-negative. -ArgumentOutOfRange_LengthGreaterThanCapacity = The length cannot be greater than the capacity. -ArgumentOutOfRange_ListInsert = Index must be within the bounds of the List. -ArgumentOutOfRange_StartIndexLessThanLength = startIndex must be less than length of string. -ArgumentOutOfRange_StartIndexLargerThanLength = startIndex cannot be larger than length of string. -ArgumentOutOfRange_EndIndexStartIndex = endIndex cannot be greater than startIndex. -ArgumentOutOfRange_IndexCount = Index and count must refer to a location within the string. -ArgumentOutOfRange_IndexCountBuffer = Index and count must refer to a location within the buffer. -ArgumentOutOfRange_IndexLength = Index and length must refer to a location within the string. -ArgumentOutOfRange_InvalidThreshold = The specified threshold for creating dictionary is out of range. -ArgumentOutOfRange_Capacity = Capacity exceeds maximum capacity. -ArgumentOutOfRange_Length = The specified length exceeds maximum capacity of SecureString. -ArgumentOutOfRange_LengthTooLarge = The specified length exceeds the maximum value of {0}. -ArgumentOutOfRange_SmallMaxCapacity = MaxCapacity must be one or greater. -ArgumentOutOfRange_GenericPositive = Value must be positive. -ArgumentOutOfRange_Range = Valid values are between {0} and {1}, inclusive. -ArgumentOutOfRange_AddValue = Value to add was out of range. -ArgumentOutOfRange_OffsetLength = Offset and length must refer to a position in the string. -ArgumentOutOfRange_OffsetOut = Either offset did not refer to a position in the string, or there is an insufficient length of destination character array. -ArgumentOutOfRange_PartialWCHAR = Pointer startIndex and length do not refer to a valid string. -ArgumentOutOfRange_ParamSequence = The specified parameter index is not in range. -ArgumentOutOfRange_Version = Version's parameters must be greater than or equal to zero. -ArgumentOutOfRange_TimeoutTooLarge = Time-out interval must be less than 2^32-2. -ArgumentOutOfRange_UIntPtrMax-1 = The length of the buffer must be less than the maximum UIntPtr value for your platform. -ArgumentOutOfRange_UnmanagedMemStreamLength = UnmanagedMemoryStream length must be non-negative and less than 2^63 - 1 - baseAddress. -ArgumentOutOfRange_UnmanagedMemStreamWrapAround = The UnmanagedMemoryStream capacity would wrap around the high end of the address space. -ArgumentOutOfRange_PeriodTooLarge = Period must be less than 2^32-2. -ArgumentOutOfRange_Year = Year must be between 1 and 9999. -ArgumentOutOfRange_BinaryReaderFillBuffer = The number of bytes requested does not fit into BinaryReader's internal buffer. -ArgumentOutOfRange_PositionLessThanCapacityRequired = The position may not be greater or equal to the capacity of the accessor. - -; ArithmeticException -Arithmetic_NaN = Function does not accept floating point Not-a-Number values. - -; ArrayTypeMismatchException -ArrayTypeMismatch_CantAssignType = Source array type cannot be assigned to destination array type. -ArrayTypeMismatch_ConstrainedCopy = Array.ConstrainedCopy will only work on array types that are provably compatible, without any form of boxing, unboxing, widening, or casting of each array element. Change the array types (i.e., copy a Derived[] to a Base[]), or use a mitigation strategy in the CER for Array.Copy's less powerful reliability contract, such as cloning the array or throwing away the potentially corrupt destination array. - -; BadImageFormatException -BadImageFormat_ResType&SerBlobMismatch = The type serialized in the .resources file was not the same type that the .resources file said it contained. Expected '{0}' but read '{1}'. -BadImageFormat_ResourcesIndexTooLong = Corrupt .resources file. String for name index '{0}' extends past the end of the file. -BadImageFormat_ResourcesNameTooLong = Corrupt .resources file. Resource name extends past the end of the file. -BadImageFormat_ResourcesNameInvalidOffset = Corrupt .resources file. Invalid offset '{0}' into name section. -BadImageFormat_ResourcesHeaderCorrupted = Corrupt .resources file. Unable to read resources from this file because of invalid header information. Try regenerating the .resources file. -BadImageFormat_ResourceNameCorrupted = Corrupt .resources file. A resource name extends past the end of the stream. -BadImageFormat_ResourceNameCorrupted_NameIndex = Corrupt .resources file. The resource name for name index {0} extends past the end of the stream. -BadImageFormat_ResourceDataLengthInvalid = Corrupt .resources file. The specified data length '{0}' is not a valid position in the stream. -BadImageFormat_TypeMismatch = Corrupt .resources file. The specified type doesn't match the available data in the stream. -BadImageFormat_InvalidType = Corrupt .resources file. The specified type doesn't exist. -BadImageFormat_ResourcesIndexInvalid = Corrupt .resources file. The resource index '{0}' is outside the valid range. -BadImageFormat_StreamPositionInvalid = Corrupt .resources file. The specified position '{0}' is not a valid position in the stream. -BadImageFormat_ResourcesDataInvalidOffset = Corrupt .resources file. Invalid offset '{0}' into data section. -BadImageFormat_NegativeStringLength = Corrupt .resources file. String length must be non-negative. -BadImageFormat_ParameterSignatureMismatch = The parameters and the signature of the method don't match. - -; Cryptography -; These strings still appear in bcl.small but should go away eventually -Cryptography_CSSM_Error = Error 0x{0} from the operating system security framework: '{1}'. -Cryptography_CSSM_Error_Unknown = Error 0x{0} from the operating system security framework. -Cryptography_InvalidDSASignatureSize = Length of the DSA signature was not 40 bytes. -Cryptography_InvalidHandle = {0} is an invalid handle. -Cryptography_InvalidOID = Object identifier (OID) is unknown. -Cryptography_OAEPDecoding = Error occurred while decoding OAEP padding. -Cryptography_PasswordDerivedBytes_InvalidIV = The Initialization vector should have the same length as the algorithm block size in bytes. -Cryptography_SSE_InvalidDataSize = Length of the data to encrypt is invalid. -Cryptography_X509_ExportFailed = The certificate export operation failed. -Cryptography_X509_InvalidContentType = Invalid content type. -Cryptography_CryptoStream_FlushFinalBlockTwice = FlushFinalBlock() method was called twice on a CryptoStream. It can only be called once. -Cryptography_HashKeySet = Hash key cannot be changed after the first write to the stream. -Cryptography_HashNotYetFinalized = Hash must be finalized before the hash value is retrieved. -Cryptography_InsufficientBuffer = Input buffer contains insufficient data. -Cryptography_InvalidBlockSize = Specified block size is not valid for this algorithm. -Cryptography_InvalidCipherMode = Specified cipher mode is not valid for this algorithm. -Cryptography_InvalidIVSize = Specified initialization vector (IV) does not match the block size for this algorithm. -Cryptography_InvalidKeySize = Specified key is not a valid size for this algorithm. -Cryptography_PasswordDerivedBytes_FewBytesSalt = Salt is not at least eight bytes. -Cryptography_PKCS7_InvalidPadding = Padding is invalid and cannot be removed. -Cryptography_UnknownHashAlgorithm='{0}' is not a known hash algorithm. - -#if FEATURE_CRYPTO -Cryptography_Config_EncodedOIDError = Encoded OID length is too large (greater than 0x7f bytes). -Cryptography_CSP_AlgKeySizeNotAvailable = Algorithm implementation does not support a key size of {0}. -Cryptography_CSP_AlgorithmNotAvailable = Cryptographic service provider (CSP) could not be found for this algorithm. -Cryptography_CSP_CFBSizeNotSupported = Feedback size for the cipher feedback mode (CFB) must be 8 bits. -Cryptography_CSP_NotFound = The requested key container was not found. -Cryptography_CSP_NoPrivateKey = Object contains only the public half of a key pair. A private key must also be provided. -Cryptography_CSP_OFBNotSupported = Output feedback mode (OFB) is not supported by this implementation. -Cryptography_CSP_WrongKeySpec = The specified cryptographic service provider (CSP) does not support this key algorithm. -Cryptography_HashNameSet = Hash name cannot be changed after the first write to the stream. -Cryptography_HashAlgorithmNameNullOrEmpty = The hash algorithm name cannot be null or empty. -Cryptography_InvalidHashSize = {0} algorithm hash size is {1} bytes. -Cryptography_InvalidKey_Weak = Specified key is a known weak key for '{0}' and cannot be used. -Cryptography_InvalidKey_SemiWeak = Specified key is a known semi-weak key for '{0}' and cannot be used. -Cryptography_InvalidKeyParameter = Parameter '{0}' is not a valid key parameter. -Cryptography_InvalidFeedbackSize = Specified feedback size is invalid. -Cryptography_InvalidOperation = This operation is not supported for this class. -Cryptography_InvalidPaddingMode = Specified padding mode is not valid for this algorithm. -Cryptography_InvalidFromXmlString = Input string does not contain a valid encoding of the '{0}' '{1}' parameter. -Cryptography_MissingKey = No asymmetric key object has been associated with this formatter object. -Cryptography_MissingOID = Required object identifier (OID) cannot be found. -Cryptography_NotInteractive = The current session is not interactive. -Cryptography_NonCompliantFIPSAlgorithm = This implementation is not part of the Windows Platform FIPS validated cryptographic algorithms. -Cryptography_Padding_Win2KEnhOnly = Direct Encryption and decryption using RSA are not available on this platform. -Cryptography_Padding_EncDataTooBig = The data to be encrypted exceeds the maximum for this modulus of {0} bytes. -Cryptography_Padding_DecDataTooBig = The data to be decrypted exceeds the maximum for this modulus of {0} bytes. -Cryptography_PasswordDerivedBytes_ValuesFixed = Value of '{0}' cannot be changed after the bytes have been retrieved. -Cryptography_PasswordDerivedBytes_TooManyBytes = Requested number of bytes exceeds the maximum. -Cryptography_PasswordDerivedBytes_InvalidAlgorithm = Algorithm is unavailable or is not supported for this operation. -Cryptography_PKCS1Decoding = Error occurred while decoding PKCS1 padding. -Cryptography_RC2_EKSKS = EffectiveKeySize value must be at least as large as the KeySize value. -Cryptography_RC2_EKSKS2 = EffectiveKeySize must be the same as KeySize in this implementation. -Cryptography_RC2_EKS40 = EffectiveKeySize value must be at least 40 bits. -Cryptography_SSD_InvalidDataSize = Length of the data to decrypt is invalid. -Cryptography_AddNullOrEmptyName = CryptoConfig cannot add a mapping for a null or empty name. -Cryptography_AlgorithmTypesMustBeVisible = Algorithms added to CryptoConfig must be accessable from outside their assembly. -#endif // FEATURE_CRYPTO - -; EventSource -EventSource_ToString = EventSource({0}, {1}) -EventSource_EventSourceGuidInUse = An instance of EventSource with Guid {0} already exists. -EventSource_KeywordNeedPowerOfTwo = Value {0} for keyword {1} needs to be a power of 2. -EventSource_UndefinedKeyword = Use of undefined keyword value {0} for event {1}. -EventSource_UnsupportedEventTypeInManifest = Unsupported type {0} in event source. -EventSource_ListenerNotFound = Listener not found. -EventSource_ListenerCreatedInsideCallback = Creating an EventListener inside a EventListener callback. -EventSource_AttributeOnNonVoid = Event attribute placed on method {0} which does not return 'void'. -EventSource_NeedPositiveId = Event IDs must be positive integers. -EventSource_ReservedOpcode = Opcode values less than 11 are reserved for system use. -EventSource_ReservedKeywords = Keywords values larger than 0x0000100000000000 are reserved for system use -EventSource_PayloadTooBig=The payload for a single event is too large. -EventSource_NoFreeBuffers=No Free Buffers available from the operating system (e.g. event rate too fast). -EventSource_NullInput=Null passed as a event argument. -EventSource_TooManyArgs=Too many arguments. -EventSource_SessionIdError=Bit position in AllKeywords ({0}) must equal the command argument named "EtwSessionKeyword" ({1}). -EventSource_EnumKindMismatch = The type of {0} is not expected in {1}. -EventSource_MismatchIdToWriteEvent = Event {0} is givien event ID {1} but {2} was passed to WriteEvent. -EventSource_EventIdReused = Event {0} has ID {1} which is already in use. -EventSource_EventNameReused = Event name {0} used more than once. If you wish to overload a method, the overloaded method should have a NonEvent attribute. -EventSource_UndefinedChannel = Use of undefined channel value {0} for event {1}. -EventSource_UndefinedOpcode = Use of undefined opcode value {0} for event {1}. -ArgumentOutOfRange_MaxArgExceeded = The total number of parameters must not exceed {0}. -ArgumentOutOfRange_MaxStringsExceeded = The number of String parameters must not exceed {0}. -ArgumentOutOfRange_NeedValidId = The ID parameter must be in the range {0} through {1}. -EventSource_NeedGuid = The Guid of an EventSource must be non zero. -EventSource_NeedName = The name of an EventSource must not be null. -EventSource_EtwAlreadyRegistered = The provider has already been registered with the operating system. -EventSource_ListenerWriteFailure = An error occurred when writing to a listener. -EventSource_TypeMustDeriveFromEventSource = Event source types must derive from EventSource. -EventSource_TypeMustBeSealedOrAbstract = Event source types must be sealed or abstract. -EventSource_TaskOpcodePairReused = Event {0} (with ID {1}) has the same task/opcode pair as event {2} (with ID {3}). -EventSource_EventMustHaveTaskIfNonDefaultOpcode = Event {0} (with ID {1}) has a non-default opcode but not a task. -EventSource_EventNameDoesNotEqualTaskPlusOpcode = Event {0} (with ID {1}) has a name that is not the concatenation of its task name and opcode. -EventSource_PeriodIllegalInProviderName = Period character ('.') is illegal in an ETW provider name ({0}). -EventSource_IllegalOpcodeValue = Opcode {0} has a value of {1} which is outside the legal range (11-238). -EventSource_OpcodeCollision = Opcodes {0} and {1} are defined with the same value ({2}). -EventSource_IllegalTaskValue = Task {0} has a value of {1} which is outside the legal range (1-65535). -EventSource_TaskCollision = Tasks {0} and {1} are defined with the same value ({2}). -EventSource_IllegalKeywordsValue = Keyword {0} has a value of {1} which is outside the legal range (0-0x0000080000000000). -EventSource_KeywordCollision = Keywords {0} and {1} are defined with the same value ({2}). -EventSource_EventChannelOutOfRange = Channel {0} has a value of {1} which is outside the legal range (16-254). -EventSource_ChannelTypeDoesNotMatchEventChannelValue = Channel {0} does not match event channel value {1}. -EventSource_MaxChannelExceeded = Attempt to define more than the maximum limit of 8 channels for a provider. -EventSource_DuplicateStringKey = Multiple definitions for string "{0}". -EventSource_EventWithAdminChannelMustHaveMessage = Event {0} specifies an Admin channel {1}. It must specify a Message property. -EventSource_UnsupportedMessageProperty = Event {0} specifies an illegal or unsupported formatting message ("{1}"). -EventSource_AbstractMustNotDeclareKTOC = Abstract event source must not declare {0} nested type. -EventSource_AbstractMustNotDeclareEventMethods = Abstract event source must not declare event methods ({0} with ID {1}). -EventSource_EventMustNotBeExplicitImplementation = Event method {0} (with ID {1}) is an explicit interface method implementation. Re-write method as implicit implementation. -EventSource_EventParametersMismatch = Event {0} was called with {1} argument(s), but it is defined with {2} parameter(s). -EventSource_InvalidCommand = Invalid command value. -EventSource_InvalidEventFormat = Can't specify both etw event format flags. -EventSource_AddScalarOutOfRange = Getting out of bounds during scalar addition. -EventSource_PinArrayOutOfRange = Pins are out of range. -EventSource_DataDescriptorsOutOfRange = Data descriptors are out of range. -EventSource_NotSupportedArrayOfNil = Arrays of Nil are not supported. -EventSource_NotSupportedArrayOfBinary = Arrays of Binary are not supported. -EventSource_NotSupportedArrayOfNullTerminatedString = Arrays of null-terminated string are not supported. -EventSource_TooManyFields = Too many fields in structure. -EventSource_RecursiveTypeDefinition = Recursive type definition is not supported. -EventSource_NotSupportedEnumType = Enum type {0} underlying type {1} is not supported for serialization. -EventSource_NonCompliantTypeError = The API supports only anonymous types or types decorated with the EventDataAttribute. Non-compliant type: {0} dataType. -EventSource_NotSupportedNestedArraysEnums = Nested arrays/enumerables are not supported. -EventSource_IncorrentlyAuthoredTypeInfo = Incorrectly-authored TypeInfo - a type should be serialized as one field or as one group -EventSource_NotSupportedCustomSerializedData = Enumerables of custom-serialized data are not supported -EventSource_StopsFollowStarts = An event with stop suffix must follow a corresponding event with a start suffix. -EventSource_NoRelatedActivityId = EventSource expects the first parameter of the Event method to be of type Guid and to be named "relatedActivityId" when calling WriteEventWithRelatedActivityId. -EventSource_VarArgsParameterMismatch = The parameters to the Event method do not match the parameters to the WriteEvent method. This may cause the event to be displayed incorrectly. - -; ExecutionEngineException -ExecutionEngine_InvalidAttribute = Attribute cannot have multiple definitions. -ExecutionEngine_MissingSecurityDescriptor = Unable to retrieve security descriptor for this frame. - -;;ExecutionContext -ExecutionContext_UndoFailed = Undo operation on a component context threw an exception -ExecutionContext_ExceptionInAsyncLocalNotification = An exception was not handled in an AsyncLocal notification callback. - - -; FieldAccessException -FieldAccess_InitOnly = InitOnly (aka ReadOnly) fields can only be initialized in the type/instance constructor. - -; FormatException -Format_AttributeUsage = Duplicate AttributeUsageAttribute found on attribute type {0}. -Format_Bad7BitInt32 = Too many bytes in what should have been a 7 bit encoded Int32. -Format_BadBase = Invalid digits for the specified base. -Format_BadBase64Char = The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters. -Format_BadBase64CharArrayLength = Invalid length for a Base-64 char array or string. -Format_BadBoolean = String was not recognized as a valid Boolean. -Format_BadDateTime = String was not recognized as a valid DateTime. -Format_BadDateTimeCalendar = The DateTime represented by the string is not supported in calendar {0}. -Format_BadDayOfWeek = String was not recognized as a valid DateTime because the day of week was incorrect. -Format_DateOutOfRange = The DateTime represented by the string is out of range. -Format_BadDatePattern = Could not determine the order of year, month, and date from '{0}'. -Format_BadFormatSpecifier = Format specifier was invalid. -Format_BadTimeSpan = String was not recognized as a valid TimeSpan. -Format_BadQuote = Cannot find a matching quote character for the character '{0}'. -Format_EmptyInputString = Input string was either empty or contained only whitespace. -Format_ExtraJunkAtEnd = Additional non-parsable characters are at the end of the string. -Format_GuidBrace = Expected {0xdddddddd, etc}. -Format_GuidComma = Could not find a comma, or the length between the previous token and the comma was zero (i.e., '0x,'etc.). -Format_GuidBraceAfterLastNumber = Could not find a brace, or the length between the previous token and the brace was zero (i.e., '0x,'etc.). -Format_GuidDashes = Dashes are in the wrong position for GUID parsing. -Format_GuidEndBrace = Could not find the ending brace. -Format_GuidHexPrefix = Expected hex 0x in '{0}'. -Format_GuidInvLen = Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx). -Format_GuidInvalidChar = Guid string should only contain hexadecimal characters. -Format_GuidUnrecognized = Unrecognized Guid format. -Format_InvalidEnumFormatSpecification = Format String can be only "G", "g", "X", "x", "F", "f", "D" or "d". -Format_InvalidGuidFormatSpecification = Format String can be only "D", "d", "N", "n", "P", "p", "B", "b", "X" or "x". -Format_InvalidString = Input string was not in a correct format. -Format_IndexOutOfRange = Index (zero based) must be greater than or equal to zero and less than the size of the argument list. -Format_UnknowDateTimeWord = The string was not recognized as a valid DateTime. There is an unknown word starting at index {0}. -Format_NeedSingleChar = String must be exactly one character long. -Format_NoParsibleDigits = Could not find any recognizable digits. -Format_RepeatDateTimePattern = DateTime pattern '{0}' appears more than once with different values. -Format_StringZeroLength = String cannot have zero length. -Format_TwoTimeZoneSpecifiers = The String being parsed cannot contain two TimeZone specifiers. -Format_UTCOutOfRange= The UTC representation of the date falls outside the year range 1-9999. -Format_OffsetOutOfRange=The time zone offset must be within plus or minus 14 hours. -Format_MissingIncompleteDate=There must be at least a partial date with a year present in the input. - -; IndexOutOfRangeException -IndexOutOfRange_ArrayRankIndex = Array does not have that many dimensions. -IndexOutOfRange_IORaceCondition = Probable I/O race condition detected while copying memory. The I/O package is not thread safe by default. In multithreaded applications, a stream must be accessed in a thread-safe way, such as a thread-safe wrapper returned by TextReader's or TextWriter's Synchronized methods. This also applies to classes like StreamWriter and StreamReader. -IndexOutOfRange_UMSPosition = Unmanaged memory stream position was beyond the capacity of the stream. - -; InsufficientMemoryException -InsufficientMemory_MemFailPoint = Insufficient available memory to meet the expected demands of an operation at this time. Please try again later. -InsufficientMemory_MemFailPoint_TooBig = Insufficient memory to meet the expected demands of an operation, and this system is likely to never satisfy this request. If this is a 32 bit system, consider booting in 3 GB mode. -InsufficientMemory_MemFailPoint_VAFrag = Insufficient available memory to meet the expected demands of an operation at this time, possibly due to virtual address space fragmentation. Please try again later. - - -; InvalidCastException -InvalidCast_DBNull = Object cannot be cast to DBNull. -InvalidCast_DownCastArrayElement = At least one element in the source array could not be cast down to the destination array type. -InvalidCast_Empty = Object cannot be cast to Empty. -InvalidCast_FromDBNull = Object cannot be cast from DBNull to other types. -InvalidCast_FromTo = Invalid cast from '{0}' to '{1}'. -InvalidCast_IConvertible = Object must implement IConvertible. -InvalidCast_OATypeMismatch = OleAut reported a type mismatch. -InvalidCast_StoreArrayElement = Object cannot be stored in an array of this type. -InvalidCast_CannotCoerceByRefVariant = Object cannot be coerced to the original type of the ByRef VARIANT it was obtained from. -InvalidCast_CannotCastNullToValueType = Null object cannot be converted to a value type. -#if FEATURE_COMINTEROP -InvalidCast_WinRTIPropertyValueElement = Object in an IPropertyValue is of type '{0}', which cannot be converted to a '{1}'. -InvalidCast_WinRTIPropertyValueCoersion = Object in an IPropertyValue is of type '{0}' with value '{1}', which cannot be converted to a '{2}'. -InvalidCast_WinRTIPropertyValueArrayCoersion = Object in an IPropertyValue is of type '{0}' which cannot be convereted to a '{1}' due to array element '{2}': {3}. -#endif // FEATURE_COMINTEROP - -; InvalidOperationException -InvalidOperation_ActivationArgsAppTrustMismatch = The activation arguments and application trust for the AppDomain must correspond to the same application identity. -InvalidOperation_AddContextFrozen = Attempted to add properties to a frozen context. -InvalidOperation_AppDomainSandboxAPINeedsExplicitAppBase = This API requires the ApplicationBase to be specified explicitly in the AppDomainSetup parameter. -InvalidOperation_CantCancelCtrlBreak = Applications may not prevent control-break from terminating their process. -InvalidOperation_CalledTwice = The method cannot be called twice on the same instance. -InvalidOperation_CollectionCorrupted = A prior operation on this collection was interrupted by an exception. Collection's state is no longer trusted. -InvalidOperation_CriticalTransparentAreMutuallyExclusive = SecurityTransparent and SecurityCritical attributes cannot be applied to the assembly scope at the same time. -InvalidOperation_SubclassedObject = Cannot set sub-classed {0} object to {1} object. -InvalidOperation_ExceptionStateCrossAppDomain = Thread.ExceptionState cannot access an ExceptionState from a different AppDomain. -InvalidOperation_DebuggerLaunchFailed = Debugger unable to launch. -InvalidOperation_ApartmentStateSwitchFailed = Failed to set the specified COM apartment state. -InvalidOperation_EmptyQueue = Queue empty. -InvalidOperation_EmptyStack = Stack empty. -InvalidOperation_CannotRemoveFromStackOrQueue = Removal is an invalid operation for Stack or Queue. -InvalidOperation_EnumEnded = Enumeration already finished. -InvalidOperation_EnumFailedVersion = Collection was modified; enumeration operation may not execute. -InvalidOperation_EnumNotStarted = Enumeration has not started. Call MoveNext. -InvalidOperation_EnumOpCantHappen = Enumeration has either not started or has already finished. -InvalidOperation_ModifyRONumFmtInfo = Unable to modify a read-only NumberFormatInfo object. -#if FEATURE_CAS_POLICY -InvalidOperation_ModifyROPermSet = ReadOnlyPermissionSet objects may not be modified. -#endif // FEATURE_CAS_POLICY -InvalidOperation_MustBeSameThread = This operation must take place on the same thread on which the object was created. -InvalidOperation_MustRevertPrivilege = Must revert the privilege prior to attempting this operation. -InvalidOperation_ReadOnly = Instance is read-only. -InvalidOperation_RegRemoveSubKey = Registry key has subkeys and recursive removes are not supported by this method. -InvalidOperation_IComparerFailed = Failed to compare two elements in the array. -InvalidOperation_InternalState = Invalid internal state. -InvalidOperation_DuplicatePropertyName = Another property by this name already exists. -InvalidOperation_NotCurrentDomain = You can only define a dynamic assembly on the current AppDomain. -InvalidOperation_ContextAlreadyFrozen = Context is already frozen. -InvalidOperation_WriteOnce = This property has already been set and cannot be modified. -InvalidOperation_MethodBaked = Type definition of the method is complete. -InvalidOperation_MethodHasBody = Method already has a body. -InvalidOperation_ModificationOfNonCanonicalAcl = This access control list is not in canonical form and therefore cannot be modified. -InvalidOperation_Method = This method is not supported by the current object. -InvalidOperation_NotADebugModule = Not a debug ModuleBuilder. -InvalidOperation_NoMultiModuleAssembly = You cannot have more than one dynamic module in each dynamic assembly in this version of the runtime. -InvalidOperation_OpenLocalVariableScope = Local variable scope was not properly closed. -InvalidOperation_SetVolumeLabelFailed = Volume labels can only be set for writable local volumes. -InvalidOperation_SetData = An additional permission should not be supplied for setting loader information. -InvalidOperation_SetData_OnlyOnce = SetData can only be used to set the value of a given name once. -InvalidOperation_SetData_OnlyLocationURI = SetData cannot be used to set the value for '{0}'. -InvalidOperation_TypeHasBeenCreated = Unable to change after type has been created. -InvalidOperation_TypeNotCreated = Type has not been created. -InvalidOperation_NoUnderlyingTypeOnEnum = Underlying type information on enumeration is not specified. -InvalidOperation_ResMgrBadResSet_Type = '{0}': ResourceSet derived classes must provide a constructor that takes a String file name and a constructor that takes a Stream. -InvalidOperation_AssemblyHasBeenSaved = Assembly '{0}' has been saved. -InvalidOperation_ModuleHasBeenSaved = Module '{0}' has been saved. -InvalidOperation_CannotAlterAssembly = Unable to alter assembly information. -InvalidOperation_BadTransientModuleReference = Unable to make a reference to a transient module from a non-transient module. -InvalidOperation_BadILGeneratorUsage = ILGenerator usage is invalid. -InvalidOperation_BadInstructionOrIndexOutOfBound = MSIL instruction is invalid or index is out of bounds. -InvalidOperation_ShouldNotHaveMethodBody = Method body should not exist. -InvalidOperation_EntryMethodNotDefinedInAssembly = Entry method is not defined in the same assembly. -InvalidOperation_CantSaveTransientAssembly = Cannot save a transient assembly. -InvalidOperation_BadResourceContainer = Unable to add resource to transient module or transient assembly. -InvalidOperation_CantInstantiateAbstractClass = Instances of abstract classes cannot be created. -InvalidOperation_CantInstantiateFunctionPointer = Instances of function pointers cannot be created. -InvalidOperation_BadTypeAttributesNotAbstract = Type must be declared abstract if any of its methods are abstract. -InvalidOperation_BadInterfaceNotAbstract = Interface must be declared abstract. -InvalidOperation_ConstructorNotAllowedOnInterface = Interface cannot have constructors. -InvalidOperation_BadMethodBody = Method '{0}' cannot have a method body. -InvalidOperation_MetaDataError = Metadata operation failed. -InvalidOperation_BadEmptyMethodBody = Method '{0}' does not have a method body. -InvalidOperation_EndInvokeCalledMultiple = EndInvoke can only be called once for each asynchronous operation. -InvalidOperation_EndReadCalledMultiple = EndRead can only be called once for each asynchronous operation. -InvalidOperation_EndWriteCalledMultiple = EndWrite can only be called once for each asynchronous operation. -InvalidOperation_AsmLoadedForReflectionOnly = Assembly has been loaded as ReflectionOnly. This API requires an assembly capable of execution. -InvalidOperation_NoAsmName = Assembly does not have an assembly name. In order to be registered for use by COM, an assembly must have a valid assembly name. -InvalidOperation_NoAsmCodeBase = Assembly does not have a code base. -InvalidOperation_HandleIsNotInitialized = Handle is not initialized. -InvalidOperation_HandleIsNotPinned = Handle is not pinned. -InvalidOperation_SlotHasBeenFreed = LocalDataStoreSlot storage has been freed. -InvalidOperation_GlobalsHaveBeenCreated = Type definition of the global function has been completed. -InvalidOperation_NotAVarArgCallingConvention = Calling convention must be VarArgs. -InvalidOperation_CannotImportGlobalFromDifferentModule = Unable to import a global method or field from a different module. -InvalidOperation_NonStaticComRegFunction = COM register function must be static. -InvalidOperation_NonStaticComUnRegFunction = COM unregister function must be static. -InvalidOperation_InvalidComRegFunctionSig = COM register function must have a System.Type parameter and a void return type. -InvalidOperation_InvalidComUnRegFunctionSig = COM unregister function must have a System.Type parameter and a void return type. -InvalidOperation_MultipleComRegFunctions = Type '{0}' has more than one COM registration function. -InvalidOperation_MultipleComUnRegFunctions = Type '{0}' has more than one COM unregistration function. -InvalidOperation_MustCallInitialize = You must call Initialize on this object instance before using it. -InvalidOperation_MustLockForReadOrWrite = Object must be locked for read or write. -InvalidOperation_MustLockForWrite = Object must be locked for read. -InvalidOperation_NoValue = Nullable object must have a value. -InvalidOperation_ResourceNotStream_Name = Resource '{0}' was not a Stream - call GetObject instead. -InvalidOperation_ResourceNotString_Name = Resource '{0}' was not a String - call GetObject instead. -InvalidOperation_ResourceNotString_Type = Resource was of type '{0}' instead of String - call GetObject instead. -InvalidOperation_ResourceWriterSaved = The resource writer has already been closed and cannot be edited. -InvalidOperation_UnderlyingArrayListChanged = This range in the underlying list is invalid. A possible cause is that elements were removed. -InvalidOperation_AnonymousCannotImpersonate = An anonymous identity cannot perform an impersonation. -InvalidOperation_DefaultConstructorILGen = Unable to access ILGenerator on a constructor created with DefineDefaultConstructor. -InvalidOperation_DefaultConstructorDefineBody = The method body of the default constructor cannot be changed. -InvalidOperation_ComputerName = Computer name could not be obtained. -InvalidOperation_MismatchedAsyncResult = The IAsyncResult object provided does not match this delegate. -InvalidOperation_PIAMustBeStrongNamed = Primary interop assemblies must be strongly named. -InvalidOperation_HashInsertFailed = Hashtable insert failed. Load factor too high. The most common cause is multiple threads writing to the Hashtable simultaneously. -InvalidOperation_UnknownEnumType = Unknown enum type. -InvalidOperation_GetVersion = OSVersion's call to GetVersionEx failed. -InvalidOperation_DateTimeParsing = Internal Error in DateTime and Calendar operations. -InvalidOperation_UserDomainName = UserDomainName native call failed. -InvalidOperation_WaitOnTransparentProxy = Cannot wait on a transparent proxy. -InvalidOperation_NoPublicAddMethod = Cannot add the event handler since no public add method exists for the event. -InvalidOperation_NoPublicRemoveMethod = Cannot remove the event handler since no public remove method exists for the event. -InvalidOperation_NotSupportedOnWinRTEvent = Adding or removing event handlers dynamically is not supported on WinRT events. -InvalidOperation_ConsoleKeyAvailableOnFile = Cannot see if a key has been pressed when either application does not have a console or when console input has been redirected from a file. Try Console.In.Peek. -InvalidOperation_ConsoleReadKeyOnFile = Cannot read keys when either application does not have a console or when console input has been redirected from a file. Try Console.Read. -InvalidOperation_ThreadWrongThreadStart = The thread was created with a ThreadStart delegate that does not accept a parameter. -InvalidOperation_ThreadAPIsNotSupported = Use CompressedStack.(Capture/Run) or ExecutionContext.(Capture/Run) APIs instead. -InvalidOperation_NotNewCaptureContext = Cannot apply a context that has been marshaled across AppDomains, that was not acquired through a Capture operation or that has already been the argument to a Set call. -InvalidOperation_NullContext = Cannot call Set on a null context -InvalidOperation_CannotCopyUsedContext = Only newly captured contexts can be copied -InvalidOperation_CannotUseSwitcherOtherThread = Undo operation must be performed on the thread where the corresponding context was Set. -InvalidOperation_SwitcherCtxMismatch = The Undo operation encountered a context that is different from what was applied in the corresponding Set operation. The possible cause is that a context was Set on the thread and not reverted(undone). -InvalidOperation_CannotOverrideSetWithoutRevert = Must override both HostExecutionContextManager.SetHostExecutionContext and HostExecutionContextManager.Revert. -InvalidOperation_CannotUseAFCOtherThread = AsyncFlowControl object must be used on the thread where it was created. -InvalidOperation_CannotRestoreUnsupressedFlow = Cannot restore context flow when it is not suppressed. -InvalidOperation_CannotSupressFlowMultipleTimes = Context flow is already suppressed. -InvalidOperation_CannotUseAFCMultiple = AsyncFlowControl object can be used only once to call Undo(). -InvalidOperation_AsyncFlowCtrlCtxMismatch = AsyncFlowControl objects can be used to restore flow only on the Context that had its flow suppressed. -InvalidOperation_TimeoutsNotSupported = Timeouts are not supported on this stream. -InvalidOperation_Overlapped_Pack = Cannot pack a packed Overlapped again. -InvalidOperation_OnlyValidForDS = Adding ACEs with Object Flags and Object GUIDs is only valid for directory-object ACLs. -InvalidOperation_WrongAsyncResultOrEndReadCalledMultiple = Either the IAsyncResult object did not come from the corresponding async method on this type, or EndRead was called multiple times with the same IAsyncResult. -InvalidOperation_WrongAsyncResultOrEndWriteCalledMultiple = Either the IAsyncResult object did not come from the corresponding async method on this type, or EndWrite was called multiple times with the same IAsyncResult. -InvalidOperation_WrongAsyncResultOrEndCalledMultiple = Either the IAsyncResult object did not come from the corresponding async method on this type, or the End method was called multiple times with the same IAsyncResult. -InvalidOperation_NoSecurityDescriptor = The object does not contain a security descriptor. -InvalidOperation_NotAllowedInReflectionOnly = The requested operation is invalid in the ReflectionOnly context. -InvalidOperation_NotAllowedInDynamicMethod = The requested operation is invalid for DynamicMethod. -InvalidOperation_PropertyInfoNotAvailable = This API does not support PropertyInfo tokens. -InvalidOperation_EventInfoNotAvailable = This API does not support EventInfo tokens. -InvalidOperation_UnexpectedWin32Error = Unexpected error when calling an operating system function. The returned error code is 0x{0:x}. -InvalidOperation_AssertTransparentCode = Cannot perform CAS Asserts in Security Transparent methods -InvalidOperation_NullModuleHandle = The requested operation is invalid when called on a null ModuleHandle. -InvalidOperation_NotWithConcurrentGC = This API is not available when the concurrent GC is enabled. -InvalidOperation_WithoutARM = This API is not available when AppDomain Resource Monitoring is not turned on. -InvalidOperation_NotGenericType = This operation is only valid on generic types. -InvalidOperation_TypeCannotBeBoxed = The given type cannot be boxed. -InvalidOperation_HostModifiedSecurityState = The security state of an AppDomain was modified by an AppDomainManager configured with the NoSecurityChanges flag. -InvalidOperation_StrongNameKeyPairRequired = A strong name key pair is required to emit a strong-named dynamic assembly. -#if FEATURE_COMINTEROP -InvalidOperation_EventTokenTableRequiresDelegate = Type '{0}' is not a delegate type. EventTokenTable may only be used with delegate types. -#endif // FEATURE_COMINTEROP -InvalidOperation_NullArray = The underlying array is null. -;system.security.claims -InvalidOperation_ClaimCannotBeRemoved = The Claim '{0}' was not able to be removed. It is either not part of this Identity or it is a claim that is owned by the Principal that contains this Identity. For example, the Principal will own the claim when creating a GenericPrincipal with roles. The roles will be exposed through the Identity that is passed in the constructor, but not actually owned by the Identity. Similar logic exists for a RolePrincipal. -InvalidOperationException_ActorGraphCircular = Actor cannot be set so that circular directed graph will exist chaining the subjects together. -InvalidOperation_AsyncIOInProgress = The stream is currently in use by a previous operation on the stream. -InvalidOperation_APIInvalidForCurrentContext = The API '{0}' cannot be used on the current platform. See http://go.microsoft.com/fwlink/?LinkId=248273 for more information. - -; InvalidProgramException -InvalidProgram_Default = Common Language Runtime detected an invalid program. - -; Isolated Storage -#if FEATURE_ISOSTORE -IsolatedStorage_AssemblyMissingIdentity = Unable to determine assembly of the caller. -IsolatedStorage_ApplicationMissingIdentity = Unable to determine application identity of the caller. -IsolatedStorage_DomainMissingIdentity = Unable to determine domain of the caller. -IsolatedStorage_AssemblyGrantSet = Unable to determine granted permission for assembly. -IsolatedStorage_DomainGrantSet = Unable to determine granted permission for domain. -IsolatedStorage_ApplicationGrantSet = Unable to determine granted permission for application. -IsolatedStorage_Init = Initialization failed. -IsolatedStorage_ApplicationNoEvidence = Unable to determine identity of application. -IsolatedStorage_AssemblyNoEvidence = Unable to determine identity of assembly. -IsolatedStorage_DomainNoEvidence = Unable to determine the identity of domain. -IsolatedStorage_DeleteDirectories = Unable to delete; directory or files in the directory could be in use. -IsolatedStorage_DeleteFile = Unable to delete file. -IsolatedStorage_CreateDirectory = Unable to create directory. -IsolatedStorage_DeleteDirectory = Unable to delete, directory not empty or does not exist. -IsolatedStorage_Operation_ISFS = Operation not permitted on IsolatedStorageFileStream. -IsolatedStorage_Operation = Operation not permitted. -IsolatedStorage_Path = Path must be a valid file name. -IsolatedStorage_FileOpenMode = Invalid mode, see System.IO.FileMode. -IsolatedStorage_SeekOrigin = Invalid origin, see System.IO.SeekOrigin. -IsolatedStorage_Scope_U_R_M = Invalid scope, expected User, User|Roaming or Machine. -IsolatedStorage_Scope_Invalid = Invalid scope. -IsolatedStorage_Exception = An error occurred while accessing IsolatedStorage. -IsolatedStorage_QuotaIsUndefined = {0} is not defined for this store. An operation was performed that requires access to {0}. Stores obtained using enumeration APIs do not have a well-defined {0}, since partial evidence is used to open the store. -IsolatedStorage_CurrentSizeUndefined = Current size cannot be determined for this store. -IsolatedStorage_DomainUndefined = Domain cannot be determined on an Assembly or Application store. -IsolatedStorage_ApplicationUndefined = Application cannot be determined on an Assembly or Domain store. -IsolatedStorage_AssemblyUndefined = Assembly cannot be determined for an Application store. -IsolatedStorage_StoreNotOpen = Store must be open for this operation. -IsolatedStorage_OldQuotaLarger = The new quota must be larger than the old quota. -IsolatedStorage_UsageWillExceedQuota = There is not enough free space to perform the operation. -IsolatedStorage_NotValidOnDesktop = The Site scope is currently not supported. -IsolatedStorage_OnlyIncreaseUserApplicationStore = Increasing the quota of this scope is not supported. Only the user application scope’s quota can be increased. -#endif // FEATURE_ISOSTORE - -; Verification Exception -Verification_Exception = Operation could destabilize the runtime. - -; IL stub marshaler exceptions -Marshaler_StringTooLong = Marshaler restriction: Excessively long string. - -; Missing (General) -MissingConstructor_Name = Constructor on type '{0}' not found. -MissingField = Field not found. -MissingField_Name = Field '{0}' not found. -MissingMember = Member not found. -MissingMember_Name = Member '{0}' not found. -MissingMethod_Name = Method '{0}' not found. -MissingModule = Module '{0}' not found. -MissingType = Type '{0}' not found. - -; MissingManifestResourceException -Arg_MissingManifestResourceException = Unable to find manifest resource. -MissingManifestResource_LooselyLinked = Could not find a manifest resource entry called "{0}" in assembly "{1}". Please check spelling, capitalization, and build rules to ensure "{0}" is being linked into the assembly. -MissingManifestResource_NoNeutralAsm = Could not find any resources appropriate for the specified culture or the neutral culture. Make sure "{0}" was correctly embedded or linked into assembly "{1}" at compile time, or that all the satellite assemblies required are loadable and fully signed. -MissingManifestResource_NoNeutralDisk = Could not find any resources appropriate for the specified culture (or the neutral culture) on disk. -MissingManifestResource_MultipleBlobs = A case-insensitive lookup for resource file "{0}" in assembly "{1}" found multiple entries. Remove the duplicates or specify the exact case. -MissingManifestResource_ResWFileNotLoaded = Unable to load resources for resource file "{0}" in package "{1}". -MissingManifestResource_NoPRIresources = Unable to open Package Resource Index. - -; MissingMember -MissingMemberTypeRef = FieldInfo does not match the target Type. -MissingMemberNestErr = TypedReference can only be made on nested value Types. - -; MissingSatelliteAssemblyException -MissingSatelliteAssembly_Default = Resource lookup fell back to the ultimate fallback resources in a satellite assembly, but that satellite either was not found or could not be loaded. Please consider reinstalling or repairing the application. -MissingSatelliteAssembly_Culture_Name = The satellite assembly named "{1}" for fallback culture "{0}" either could not be found or could not be loaded. This is generally a setup problem. Please consider reinstalling or repairing the application. - -; MulticastNotSupportedException -Multicast_Combine = Delegates that are not of type MulticastDelegate may not be combined. - -; NotImplementedException -Arg_NotImplementedException = The method or operation is not implemented. -NotImplemented_ResourcesLongerThan2^63 = Resource files longer than 2^63 bytes are not currently implemented. - -; NotSupportedException -NotSupported_NYI = This feature is not currently implemented. -NotSupported_AbstractNonCLS = This non-CLS method is not implemented. -NotSupported_ChangeType = ChangeType operation is not supported. -NotSupported_ByRefLike = Cannot create boxed ByRef-like values. -NotSupported_ByRefLike[] = Cannot create arrays of ByRef-like values. -NotSupported_OpenType = Cannot create arrays of open type. -NotSupported_DBNullSerial = Only one DBNull instance may exist, and calls to DBNull deserialization methods are not allowed. -NotSupported_DelegateSerHolderSerial = DelegateSerializationHolder objects are designed to represent a delegate during serialization and are not serializable themselves. -NotSupported_DelegateCreationFromPT = Application code cannot use Activator.CreateInstance to create types that derive from System.Delegate. Delegate.CreateDelegate can be used instead. -NotSupported_EncryptionNeedsNTFS = File encryption support only works on NTFS partitions. -NotSupported_FileStreamOnNonFiles = FileStream was asked to open a device that was not a file. For support for devices like 'com1:' or 'lpt1:', call CreateFile, then use the FileStream constructors that take an OS handle as an IntPtr. -NotSupported_FixedSizeCollection = Collection was of a fixed size. -NotSupported_KeyCollectionSet = Mutating a key collection derived from a dictionary is not allowed. -NotSupported_ValueCollectionSet = Mutating a value collection derived from a dictionary is not allowed. -NotSupported_MemStreamNotExpandable = Memory stream is not expandable. -NotSupported_ObsoleteResourcesFile = Found an obsolete .resources file in assembly '{0}'. Rebuild that .resources file then rebuild that assembly. -NotSupported_OleAutBadVarType = The given Variant type is not supported by this OleAut function. -NotSupported_PopulateData = This Surrogate does not support PopulateData(). -NotSupported_ReadOnlyCollection = Collection is read-only. -NotSupported_RangeCollection = The specified operation is not supported on Ranges. -NotSupported_SortedListNestedWrite = This operation is not supported on SortedList nested types because they require modifying the original SortedList. -NotSupported_SubclassOverride = Derived classes must provide an implementation. -NotSupported_TypeCannotDeserialized = Direct deserialization of type '{0}' is not supported. -NotSupported_UnreadableStream = Stream does not support reading. -NotSupported_UnseekableStream = Stream does not support seeking. -NotSupported_UnwritableStream = Stream does not support writing. -NotSupported_CannotWriteToBufferedStreamIfReadBufferCannotBeFlushed = Cannot write to a BufferedStream while the read buffer is not empty if the underlying stream is not seekable. Ensure that the stream underlying this BufferedStream can seek or avoid interleaving read and write operations on this BufferedStream. -NotSupported_Method = Method is not supported. -NotSupported_Constructor = Object cannot be created through this constructor. -NotSupported_DynamicModule = The invoked member is not supported in a dynamic module. -NotSupported_TypeNotYetCreated = The invoked member is not supported before the type is created. -NotSupported_SymbolMethod = Not supported in an array method of a type definition that is not complete. -NotSupported_NotDynamicModule = The MethodRental.SwapMethodBody method can only be called to swap the method body of a method in a dynamic module. -NotSupported_DynamicAssembly = The invoked member is not supported in a dynamic assembly. -NotSupported_NotAllTypesAreBaked = Type '{0}' was not completed. -NotSupported_CannotSaveModuleIndividually = Unable to save a ModuleBuilder if it was created underneath an AssemblyBuilder. Call Save on the AssemblyBuilder instead. -NotSupported_MaxWaitHandles = The number of WaitHandles must be less than or equal to 64. -NotSupported_IllegalOneByteBranch = Illegal one-byte branch at position: {0}. Requested branch was: {1}. -NotSupported_OutputStreamUsingTypeBuilder = Output streams do not support TypeBuilders. -NotSupported_ValueClassCM = Custom marshalers for value types are not currently supported. -NotSupported_Void[] = Arrays of System.Void are not supported. -NotSupported_NoParentDefaultConstructor = Parent does not have a default constructor. The default constructor must be explicitly defined. -NotSupported_NonReflectedType = Not supported in a non-reflected type. -NotSupported_GlobalFunctionNotBaked = The type definition of the global function is not completed. -NotSupported_SecurityPermissionUnion = Union is not implemented. -NotSupported_UnitySerHolder = The UnitySerializationHolder object is designed to transmit information about other types and is not serializable itself. -NotSupported_UnknownTypeCode = TypeCode '{0}' was not valid. -NotSupported_WaitAllSTAThread = WaitAll for multiple handles on a STA thread is not supported. -NotSupported_SignalAndWaitSTAThread = SignalAndWait on a STA thread is not supported. -NotSupported_CreateInstanceWithTypeBuilder = CreateInstance cannot be used with an object of type TypeBuilder. -NotSupported_NonUrlAttrOnMBR = UrlAttribute is the only attribute supported for MarshalByRefObject. -NotSupported_ActivAttrOnNonMBR = Activation Attributes are not supported for types not deriving from MarshalByRefObject. -NotSupported_ActivForCom = Activation Attributes not supported for COM Objects. -NotSupported_NoCodepageData = No data is available for encoding {0}. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method. -NotSupported_CodePage50229 = The ISO-2022-CN Encoding (Code page 50229) is not supported. -NotSupported_DynamicAssemblyNoRunAccess = Cannot execute code on a dynamic assembly without run access. -NotSupported_IDispInvokeDefaultMemberWithNamedArgs = Invoking default method with named arguments is not supported. -NotSupported_Type = Type is not supported. -NotSupported_GetMethod = The 'get' method is not supported on this property. -NotSupported_SetMethod = The 'set' method is not supported on this property. -NotSupported_DeclarativeUnion = Declarative unionizing of these permissions is not supported. -NotSupported_StringComparison = The string comparison type passed in is currently not supported. -NotSupported_WrongResourceReader_Type = This .resources file should not be read with this reader. The resource reader type is "{0}". -NotSupported_MustBeModuleBuilder = Module argument must be a ModuleBuilder. -NotSupported_CallToVarArg = Vararg calling convention not supported. -NotSupported_TooManyArgs = Stack size too deep. Possibly too many arguments. -NotSupported_DeclSecVarArg = Assert, Deny, and PermitOnly are not supported on methods with a Vararg calling convention. -NotSupported_AmbiguousIdentity = The operation is ambiguous because the permission represents multiple identities. -NotSupported_DynamicMethodFlags = Wrong MethodAttributes or CallingConventions for DynamicMethod. Only public, static, standard supported -NotSupported_GlobalMethodSerialization = Serialization of global methods (including implicit serialization via the use of asynchronous delegates) is not supported. -NotSupported_InComparableType = A type must implement IComparable or IComparable to support comparison. -NotSupported_ManagedActivation = Cannot create uninitialized instances of types requiring managed activation. -NotSupported_ByRefReturn = ByRef return value not supported in reflection invocation. -NotSupported_DelegateMarshalToWrongDomain = Delegates cannot be marshaled from native code into a domain other than their home domain. -NotSupported_ResourceObjectSerialization = Cannot read resources that depend on serialization. -NotSupported_One = The arithmetic type '{0}' cannot represent the number one. -NotSupported_Zero = The arithmetic type '{0}' cannot represent the number zero. -NotSupported_MaxValue = The arithmetic type '{0}' does not have a maximum value. -NotSupported_MinValue = The arithmetic type '{0}' does not have a minimum value. -NotSupported_PositiveInfinity = The arithmetic type '{0}' cannot represent positive infinity. -NotSupported_NegativeInfinity = The arithmetic type '{0}' cannot represent negative infinity. -NotSupported_UmsSafeBuffer = This operation is not supported for an UnmanagedMemoryStream created from a SafeBuffer. -NotSupported_Reading = Accessor does not support reading. -NotSupported_Writing = Accessor does not support writing. -NotSupported_UnsafePointer = This accessor was created with a SafeBuffer; use the SafeBuffer to gain access to the pointer. -NotSupported_CollectibleCOM = COM Interop is not supported for collectible types. -NotSupported_CollectibleAssemblyResolve = Resolving to a collectible assembly is not supported. -NotSupported_CollectibleBoundNonCollectible = A non-collectible assembly may not reference a collectible assembly. -NotSupported_CollectibleDelegateMarshal = Delegate marshaling for types within collectible assemblies is not supported. -NotSupported_NonStaticMethod = Non-static methods with NativeCallableAttribute are not supported. -NotSupported_NativeCallableTarget = Methods with NativeCallableAttribute cannot be used as delegate target. -NotSupported_GenericMethod = Generic methods with NativeCallableAttribute are not supported. -NotSupported_NonBlittableTypes = Non-blittable parameter types are not supported for NativeCallable methods. - -#if FEATURE_WINDOWSPHONE -NotSupported_UserDllImport = DllImport cannot be used on user-defined methods. -NotSupported_UserCOM = COM Interop is not supported for user-defined types. -#endif //FEATURE_WINDOWSPHONE -#if FEATURE_CAS_POLICY -NotSupported_RequiresCasPolicyExplicit = This method explicitly uses CAS policy, which has been obsoleted by the .NET Framework. In order to enable CAS policy for compatibility reasons, please use the NetFx40_LegacySecurityPolicy configuration switch. Please see http://go.microsoft.com/fwlink/?LinkID=155570 for more information. -NotSupported_RequiresCasPolicyImplicit = This method implicitly uses CAS policy, which has been obsoleted by the .NET Framework. In order to enable CAS policy for compatibility reasons, please use the NetFx40_LegacySecurityPolicy configuration switch. Please see http://go.microsoft.com/fwlink/?LinkID=155570 for more information. -NotSupported_CasDeny = The Deny stack modifier has been obsoleted by the .NET Framework. Please see http://go.microsoft.com/fwlink/?LinkId=155571 for more information. -NotSupported_SecurityContextSourceAppDomainInHeterogenous = SecurityContextSource.CurrentAppDomain is not supported in heterogenous AppDomains. -#endif // FEATURE_CAS_POLICY -#if FEATURE_APPX -NotSupported_AppX = {0} is not supported in AppX. -LoadOfFxAssemblyNotSupported_AppX = {0} of .NET Framework assemblies is not supported in AppX. -#endif -#if FEATURE_COMINTEROP -NotSupported_WinRT_PartialTrust = Windows Runtime is not supported in partial trust. -#endif // FEATURE_COMINTEROP -; ReflectionTypeLoadException -ReflectionTypeLoad_LoadFailed = Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information. -#if !FEATURE_CORECLR -NotSupported_NoTypeInfo = Cannot resolve {0} to a TypeInfo object. -#endif -#if FEATURE_COMINTEROP -NotSupported_PIAInAppxProcess = A Primary Interop Assembly is not supported in AppX. -#endif -#if FEATURE_WINDOWSPHONE -; Not referring to "Windows Phone" in the messages, as FEATURE_WINDOWSPHONE is defined for .NET Core as well. -NotSupported_WindowsPhone = {0} is not supported. -NotSupported_AssemblyLoadCodeBase = Assembly.Load with a Codebase is not supported. -#endif - -; TypeLoadException -TypeLoad_ResolveType = Could not resolve type '{0}'. -TypeLoad_ResolveTypeFromAssembly = Could not resolve type '{0}' in assembly '{1}'. -TypeLoad_ResolveNestedType = Could not resolve nested type '{0}' in type "{1}'. -FileNotFound_ResolveAssembly = Could not resolve assembly '{0}'. - -; NullReferenceException -NullReference_This = The pointer for this method was null. - -; ObjectDisposedException -ObjectDisposed_Generic = Cannot access a disposed object. -ObjectDisposed_FileClosed = Cannot access a closed file. -ObjectDisposed_ObjectName_Name = Object name: '{0}'. -ObjectDisposed_ReaderClosed = Cannot read from a closed TextReader. -ObjectDisposed_ResourceSet = Cannot access a closed resource set. -ObjectDisposed_RegKeyClosed = Cannot access a closed registry key. -ObjectDisposed_StreamClosed = Cannot access a closed Stream. -ObjectDisposed_WriterClosed = Cannot write to a closed TextWriter. -ObjectDisposed_ViewAccessorClosed = Cannot access a closed accessor. - -; OperationCanceledException -OperationCanceled = The operation was canceled. - -; OutOfMemoryException -OutOfMemory_GCHandleMDA = The GCHandle MDA has run out of available cookies. - -; OverflowException -Overflow_Byte = Value was either too large or too small for an unsigned byte. -Overflow_Char = Value was either too large or too small for a character. -Overflow_Currency = Value was either too large or too small for a Currency. -Overflow_Decimal = Value was either too large or too small for a Decimal. -Overflow_Int16 = Value was either too large or too small for an Int16. -Overflow_Int32 = Value was either too large or too small for an Int32. -Overflow_Int64 = Value was either too large or too small for an Int64. -Overflow_NegateTwosCompNum = Negating the minimum value of a twos complement number is invalid. -Overflow_NegativeUnsigned = The string was being parsed as an unsigned number and could not have a negative sign. -Overflow_SByte = Value was either too large or too small for a signed byte. -Overflow_Single = Value was either too large or too small for a Single. -Overflow_Double = Value was either too large or too small for a Double. -Overflow_TimeSpanTooLong = TimeSpan overflowed because the duration is too long. -Overflow_TimeSpanElementTooLarge = The TimeSpan could not be parsed because at least one of the numeric components is out of range or contains too many digits. -Overflow_Duration = The duration cannot be returned for TimeSpan.MinValue because the absolute value of TimeSpan.MinValue exceeds the value of TimeSpan.MaxValue. -Overflow_UInt16 = Value was either too large or too small for a UInt16. -Overflow_UInt32 = Value was either too large or too small for a UInt32. -Overflow_UInt64 = Value was either too large or too small for a UInt64. - -; PlatformNotsupportedException -PlatformNotSupported_RequiresLonghorn = This operation is only supported on Windows Vista and above. -PlatformNotSupported_RequiresNT = This operation is only supported on Windows 2000, Windows XP, and higher. -PlatformNotSupported_RequiresW2kSP3 = This operation is only supported on Windows 2000 SP3 or later operating systems. -#if FEATURE_COMINTEROP -PlatformNotSupported_WinRT = Windows Runtime is not supported on this operating system. -#endif // FEATURE_COMINTEROP - -; PolicyException -; This still appears in bcl.small but should go away eventually -Policy_Default = Error occurred while performing a policy operation. -Policy_CannotLoadSemiTrustAssembliesDuringInit = All assemblies loaded as part of AppDomain initialization must be fully trusted. -#if FEATURE_IMPERSONATION -Policy_PrincipalTwice = Default principal object cannot be set twice. -#endif // FEATURE_IMPERSONATION -#if FEATURE_CAS_POLICY -Policy_PolicyAlreadySet = Policy for this domain cannot be set twice. -Policy_NoExecutionPermission = Execution permission cannot be acquired. -Policy_NoRequiredPermission = Required permissions cannot be acquired. -Policy_MultipleExclusive = More than one exclusive group is not allowed. -Policy_RecoverNotFileBased = PolicyLevel object not based on a file cannot be recovered. -Policy_RecoverNoConfigFile = No old configuration file exists to recover. -Policy_UnableToSave = Policy level '{0}' could not be saved: {1}. -Policy_BadXml = Policy configuration XML is invalid. The required tag '{0}' is missing. -Policy_NonFullTrustAssembly = Policy references an assembly not in the full trust assemblies list. -Policy_MissingActivationContextInAppEvidence = The application evidence does not contain a Fusion activation context. -Policy_NoTrustManager = A trust manager could not be loaded for this application. -Policy_GrantSetDoesNotMatchDomain = An assembly was provided an invalid grant set by runtime host '{0}'. In a homogenous AppDomain, the only valid grant sets are FullTrust and the AppDomain's sandbox grant set. -#endif // FEATURE_CAS_POLICY -Policy_SaveNotFileBased = PolicyLevel object not based on a file cannot be saved. -Policy_AppTrustMustGrantAppRequest = ApplicationTrust grant set does not contain ActivationContext's minimum request set. - -Error_SecurityPolicyFileParse = Error occurred while parsing the '{0}' policy level. The default policy level was used instead. -Error_SecurityPolicyFileParseEx = Error '{1}' occurred while parsing the '{0}' policy level. The default policy level was used instead. - -#if FEATURE_CAS_POLICY -Policy_EvidenceMustBeSerializable = Objects used as evidence must be serializable. -Policy_DuplicateEvidence = The evidence collection already contains evidence of type '{0}'. Multiple pieces of the same type of evidence are not allowed. -Policy_IncorrectHostEvidence = Runtime host '{0}' returned evidence of type '{1}' from a request for evidence of type '{2}'. -Policy_NullHostEvidence = Runtime host '{0}' returned null when asked for assembly evidence for assembly '{1}'. -Policy_NullHostGrantSet = Runtime host '{0}' returned a null grant set from ResolvePolicy. -#endif // FEATURE_CAS_POLICY - -; Policy codegroup and permission set names and descriptions -#if FEATURE_CAS_POLICY -Policy_AllCode_Name = All_Code -Policy_AllCode_DescriptionFullTrust = Code group grants all code full trust and forms the root of the code group tree. -Policy_AllCode_DescriptionNothing = Code group grants no permissions and forms the root of the code group tree. -Policy_MyComputer_Name = My_Computer_Zone -Policy_MyComputer_Description = Code group grants full trust to all code originating on the local computer -Policy_Intranet_Name = LocalIntranet_Zone -Policy_Intranet_Description = Code group grants the intranet permission set to code from the intranet zone. This permission set grants intranet code the right to use isolated storage, full UI access, some capability to do reflection, and limited access to environment variables. -Policy_IntranetNet_Name = Intranet_Same_Site_Access -Policy_IntranetNet_Description = All intranet code gets the right to connect back to the site of its origin. -Policy_IntranetFile_Name = Intranet_Same_Directory_Access -Policy_IntranetFile_Description = All intranet code gets the right to read from its install directory. -Policy_Internet_Name = Internet_Zone -Policy_Internet_Description = Code group grants code from the Internet zone the Internet permission set. This permission set grants Internet code the right to use isolated storage and limited UI access. -Policy_InternetNet_Name = Internet_Same_Site_Access -Policy_InternetNet_Description = All Internet code gets the right to connect back to the site of its origin. -Policy_Trusted_Name = Trusted_Zone -Policy_Trusted_Description = Code from a trusted zone is granted the Internet permission set. This permission set grants the right to use isolated storage and limited UI access. -Policy_TrustedNet_Name = Trusted_Same_Site_Access -Policy_TrustedNet_Description = All Trusted Code gets the right to connect back to the site of its origin. -Policy_Untrusted_Name = Restricted_Zone -Policy_Untrusted_Description = Code coming from a restricted zone does not receive any permissions. -Policy_Microsoft_Name = Microsoft_Strong_Name -Policy_Microsoft_Description = Code group grants full trust to code signed with the Microsoft strong name. -Policy_Ecma_Name = ECMA_Strong_Name -Policy_Ecma_Description = Code group grants full trust to code signed with the ECMA strong name. - -; Policy permission set descriptions -Policy_PS_FullTrust = Allows full access to all resources -Policy_PS_Everything = Allows unrestricted access to all resources covered by built-in permissions -Policy_PS_Nothing = Denies all resources, including the right to execute -Policy_PS_Execution = Permits execution -Policy_PS_SkipVerification = Grants right to bypass the verification -Policy_PS_Internet = Default rights given to Internet applications -Policy_PS_LocalIntranet = Default rights given to applications on the local intranet - -; default Policy level names -Policy_PL_Enterprise = Enterprise -Policy_PL_Machine = Machine -Policy_PL_User = User -Policy_PL_AppDomain = AppDomain -#endif // FEATURE_CAS_POLICY - -; RankException -Rank_MultiDimNotSupported = Only single dimension arrays are supported here. -Rank_MustMatch = The specified arrays must have the same number of dimensions. - -; TypeInitializationException -TypeInitialization_Default = Type constructor threw an exception. -TypeInitialization_Type = The type initializer for '{0}' threw an exception. - -; TypeLoadException - - -; -; Reflection exceptions -; -RtType.InvalidCaller = Caller is not a friend. - -;CustomAttributeFormatException -RFLCT.InvalidPropFail = '{0}' property specified was not found. -RFLCT.InvalidFieldFail = '{0}' field specified was not found. - -;InvalidFilterCriteriaException -RFLCT.FltCritString = A String must be provided for the filter criteria. -RFLCT.FltCritInt = An Int32 must be provided for the filter criteria. - -; TargetException -RFLCT.Targ_ITargMismatch = Object does not match target type. -RFLCT.Targ_StatMethReqTarg = Non-static method requires a target. -RFLCT.Targ_StatFldReqTarg = Non-static field requires a target. - -;AmbiguousMatchException -RFLCT.Ambiguous = Ambiguous match found. -RFLCT.AmbigCust = Multiple custom attributes of the same type found. - -; -; Remoting exceptions -; -Remoting_AppDomainUnloaded_ThreadUnwound = The application domain in which the thread was running has been unloaded. -Remoting_AppDomainUnloaded = The target application domain has been unloaded. -Remoting_CantRemotePointerType = Pointer types cannot be passed in a remote call. -Remoting_TypeCantBeRemoted = The given type cannot be passed in a remote call. -Remoting_Delegate_TooManyTargets = The delegate must have only one target. -Remoting_InvalidContext = The context is not valid. -Remoting_InvalidValueTypeFieldAccess = An attempt was made to calculate the address of a value type field on a remote object. This was likely caused by an attempt to directly get or set the value of a field within this embedded value type. Avoid this and instead provide and use access methods for each field in the object that will be accessed remotely. -Remoting_Message_BadRetValOrOutArg = Bad return value or out-argument inside the return message. -Remoting_NonPublicOrStaticCantBeCalledRemotely = Permission denied: cannot call non-public or static methods remotely. -Remoting_Proxy_ProxyTypeIsNotMBR = classToProxy argument must derive from MarshalByRef type. -Remoting_TP_NonNull = The transparent proxy field of a real proxy must be null. -#if FEATURE_REMOTING -Remoting_Activation_BadAttribute = Activation attribute does not implement the IContextAttribute interface. -Remoting_Activation_BadObject = Proxy Attribute returned an incompatible object when constructing an instance of type {0}. -Remoting_Activation_MBR_ProxyAttribute = Proxy Attributes are supported on ContextBound types only. -Remoting_Activation_ConnectFailed = An attempt to connect to the remote activator failed with exception '{0}'. -Remoting_Activation_Failed = Activation failed due to an unknown reason. -Remoting_Activation_InconsistentState = Inconsistent state during activation; there may be two proxies for the same object. -Remoting_Activation_MissingRemoteAppEntry = Cannot find an entry for remote application '{0}'. -Remoting_Activation_NullReturnValue = Return value of construction call was null. -Remoting_Activation_NullFromInternalUnmarshal = InternalUnmarshal of returned ObjRef from activation call returned null. -Remoting_Activation_WellKnownCTOR = Cannot run a non-default constructor when connecting to well-known objects. -Remoting_Activation_PermissionDenied = Type '{0}' is not registered for activation. -Remoting_Activation_PropertyUnhappy = A context property did not approve the candidate context for activating the object. -Remoting_Activation_AsyncUnsupported = Async Activation not supported. -Remoting_AmbiguousCTOR = Cannot resolve the invocation to the correct constructor. -Remoting_AmbiguousMethod = Cannot resolve the invocation to the correct method. -Remoting_AppDomains_NYI = This feature is not yet supported for cross-application domain. -Remoting_AppDomainsCantBeCalledRemotely = Permission denied: cannot call methods on the AppDomain class remotely. -Remoting_AssemblyLoadFailed = Cannot load assembly '{0}'. -Remoting_Attribute_UseAttributeNotsettable = UseAttribute not allowed in SoapTypeAttribute. -Remoting_BadType = Cannot load type '{0}'. -Remoting_BadField = Remoting cannot find field '{0}' on type '{1}'. -Remoting_BadInternalState_ActivationFailure = Invalid internal state: Activation service failed to initialize. -Remoting_BadInternalState_ProxySameAppDomain = Invalid internal state: A marshal by ref object should not have a proxy in its own AppDomain. -Remoting_BadInternalState_FailEnvoySink = Invalid internal state: Failed to create an envoy sink for the object. -Remoting_CantDisconnectClientProxy = Cannot call disconnect on a proxy. -Remoting_CantInvokeIRemoteDispatch = Cannot invoke methods on IRemoteDispatch. -Remoting_ChannelNameAlreadyRegistered = The channel '{0}' is already registered. -Remoting_ChannelNotRegistered = The channel '{0}' is not registered with remoting services. -Remoting_Channel_PopOnEmptySinkStack = Tried to pop data from an empty channel sink stack. -Remoting_Channel_PopFromSinkStackWithoutPush = A channel sink tried to pop data from the stack without first pushing data onto the stack. -Remoting_Channel_StoreOnEmptySinkStack = A channel sink called the Store method when the sink stack was empty. -Remoting_Channel_StoreOnSinkStackWithoutPush = A channel sink called the Store method on the sink stack without first pushing data onto the stack. -Remoting_Channel_CantCallAPRWhenStackEmpty = Cannot call the AsyncProcessResponse method on the previous channel sink because the stack is empty. -Remoting_Channel_CantCallFRSWhenStackEmtpy = Called FlipRememberedStack() when stack was not null. -Remoting_Channel_CantCallGetResponseStreamWhenStackEmpty = Cannot call the GetResponseStream method on the previous channel sink because the stack is empty. -Remoting_Channel_DispatchSinkMessageMissing = No message was deserialized prior to calling the DispatchChannelSink. -Remoting_Channel_DispatchSinkWantsNullRequestStream = The request stream should be null when the DispatchChannelSink is called. -Remoting_Channel_CannotBeSecured = Channel {0} cannot be secured. Please consider using a channel that implements ISecurableChannel -Remoting_Config_ChannelMissingCtor = To be used from a .config file, the channel type '{0}' must have a constructor of the form '{1}' -Remoting_Config_SinkProviderMissingCtor = To be used from a .config file, the sink provider type '{0}' must have a constructor of the form '{1}' -Remoting_Config_SinkProviderNotFormatter = A sink provider of type '{0}' is incorrectly labeled as a 'formatter'. -Remoting_Config_ConfigurationFailure = Remoting configuration failed with the exception '{0}'. -Remoting_Config_InvalidTimeFormat = Invalid time format '{0}'. Examples of valid time formats include 7D, 10H, 5M, 30S, or 20MS. -Remoting_Config_AppNameSet = The remoting application name, '{0}', had already been set. -Remoting_Config_ErrorsModeSet = The remoting custom errors mode had already been set. -Remoting_Config_CantRedirectActivationOfWellKnownService = Attempt to redirect activation for type '{0}, {1}'. This is not allowed since either a well-known service type has already been registered with that type or that type has been registered has a activated service type. -Remoting_Config_CantUseRedirectedTypeForWellKnownService = Attempt to register a well-known or activated service type of type '{0}, {1}'. This is not allowed since the type has already been redirected to activate elsewhere. -Remoting_Config_InvalidChannelType = '{0}' does not implement IChannelReceiver or IChannelSender. All channels must implement one of these interfaces. -Remoting_Config_InvalidSinkProviderType = Unable to use '{0}' as a channel sink provider. It does not implement '{1}'. -Remoting_Config_MissingWellKnownModeAttribute = Well-known service entries must contain a 'mode' attribute with a value of 'Singleton' or 'SingleCall'. -Remoting_Config_MissingTypeAttribute = '{0}' entries must contain a '{1}' attribute of the form 'typeName, assemblyName'. -Remoting_Config_MissingXmlTypeAttribute = '{0}' entries must contain a '{1}' attribute of the form 'xmlTypeName, xmlTypeNamespace'. -Remoting_Config_NoAppName = Improper remoting configuration: missing ApplicationName property. -Remoting_Config_NonTemplateIdAttribute = Only '{0}' templates can have an 'id' attribute. -Remoting_Config_PreloadRequiresTypeOrAssembly = Preload entries require a type or assembly attribute. -Remoting_Config_ProviderNeedsElementName = Sink providers must have an element name of 'formatter' or 'provider'. -Remoting_Config_RequiredXmlAttribute = '{0}' entries require a '{1}' attribute. -Remoting_Config_ReadFailure = .Config file '{0}' cannot be read successfully due to exception '{1}'. -Remoting_Config_NodeMustBeUnique = There can be only one '{0}' node in the '{1}' section of a config file. -Remoting_Config_TemplateCannotReferenceTemplate = A '{0}' template cannot reference another '{0}' template. -Remoting_Config_TypeAlreadyRedirected = Attempt to redirect activation of type '{0}, {1}' which is already redirected. -Remoting_Config_UnknownValue = Unknown value {1} was found on the {0} node. -Remoting_Config_UnableToResolveTemplate = Cannot resolve '{0}' template reference: '{1}'. -Remoting_Config_VersionPresent = Version information is present in the assembly name '{0}' which is not allowed for '{1}' entries. -Remoting_Contexts_BadProperty = A property that contributed a bad sink to the chain was found. -Remoting_Contexts_NoProperty = A property with the name '{0}' was not found. -Remoting_Contexts_ContextNotFrozenForCallBack = Context should be frozen before calling the DoCallBack method. -Remoting_Default = Unknown remoting error. -Remoting_HandlerNotRegistered = The tracking handler of type '{0}' is not registered with Remoting Services. -Remoting_InvalidMsg = Invalid Message Object. -Remoting_InvalidCallingType = Attempted to call a method declared on type '{0}' on an object which exposes '{1}'. -Remoting_InvalidRequestedType = The server object type cannot be cast to the requested type '{0}'. -Remoting_InternalError = Server encountered an internal error. For more information, turn off customErrors in the server's .config file. -Remoting_Lifetime_ILeaseReturn = Expected a return object of type ILease, but received '{0}'. -Remoting_Lifetime_InitialStateInitialLeaseTime = InitialLeaseTime property can only be set when the lease is in initial state. The state is '{0}'. -Remoting_Lifetime_InitialStateRenewOnCall = RenewOnCallTime property can only be set when the lease is in initial state. The state is '{0}'. -Remoting_Lifetime_InitialStateSponsorshipTimeout = SponsorshipTimeout property can only be set when the lease is in initial state. State is '{0}'. -Remoting_Lifetime_SetOnce = '{0}' can only be set once within an AppDomain. -Remoting_Message_ArgMismatch = {2} arguments were passed to '{0}::{1}'. {3} arguments were expected by this method. -Remoting_Message_BadAsyncResult = The async result object is null or of an unexpected type. -Remoting_Message_BadType = The method was called with a Message of an unexpected type. -Remoting_Message_CoercionFailed = The argument type '{0}' cannot be converted into parameter type '{1}'. -Remoting_Message_MissingArgValue = Expecting an instance of type '{0}' at pos {1} in the args array. -Remoting_Message_BadSerialization = Invalid or malformed serialization information for the message object. -Remoting_NoIdentityEntry = No remoting information was found for this object. -Remoting_NotRemotableByReference = Trying to create a proxy to an unbound type. -Remoting_NullMessage = The method was called with a null message. -Remoting_Proxy_BadType = The proxy is of an unsupported type. -Remoting_ResetURI = Attempt to reset the URI for an object from '{0}' to '{1}'. -Remoting_ServerObjectNotFound = The server object for URI '{0}' is not registered with the remoting infrastructure (it may have been disconnected). -Remoting_SetObjectUriForMarshal__ObjectNeedsToBeLocal = SetObjectUriForMarshal method should only be called for MarshalByRefObjects that exist in the current AppDomain. -Remoting_SetObjectUriForMarshal__UriExists = SetObjectUriForMarshal method has already been called on this object or the object has already been marshaled. -Remoting_Proxy_BadReturnType = Return argument has an invalid type. -Remoting_Proxy_ReturnValueTypeCannotBeNull = ByRef value type parameter cannot be null. -Remoting_Proxy_BadReturnTypeForActivation = Bad return type for activation call via Invoke: must be of type IConstructionReturnMessage. -Remoting_Proxy_BadTypeForActivation = Type mismatch between proxy type '{0}' and activation type '{1}'. -Remoting_Proxy_ExpectedOriginalMessage = The message passed to Invoke should be passed to PropagateOutParameters. -Remoting_Proxy_InvalidCall = Trying to call proxy while constructor call is in progress. -Remoting_Proxy_InvalidState = Channel sink does not exist. Failed to dispatch async call. -Remoting_Proxy_NoChannelSink = This remoting proxy has no channel sink which means either the server has no registered server channels that are listening, or this application has no suitable client channel to talk to the server. -Remoting_Proxy_InvalidCallType = Only the synchronous call type is supported for messages that are not of type Message. -Remoting_Proxy_WrongContext = ExecuteMessage can be called only from the native context of the object. -Remoting_SOAPInteropxsdInvalid = Soap Parse error, xsd:type '{0}' invalid {1} -Remoting_SOAPQNameNamespace = SoapQName missing a Namespace value '{0}'. -Remoting_ThreadAffinity_InvalidFlag = The specified flag '{0}' does not have one of the valid values. -Remoting_TrackingHandlerAlreadyRegistered = The handler has already been registered with TrackingServices. -Remoting_URIClash = Found two different objects associated with the same URI, '{0}'. -Remoting_URIExists = The remoted object already has an associated URI. -Remoting_URIToProxy = Trying to associate the URI with a proxy. -Remoting_WellKnown_MustBeMBR = Attempted to create well-known object of type '{0}'. Well-known objects must derive from the MarshalByRefObject class. -Remoting_WellKnown_CtorCantMarshal = '{0}': A well-known object cannot marshal itself in its constructor, or perform any action that would cause it to be marshaled (such as passing the 'this' pointer as a parameter to a remote method). -Remoting_WellKnown_CantDirectlyConnect = Attempt to connect to a server using its object URI: '{0}'. A valid, complete URL must be used. -Remoting_Connect_CantCreateChannelSink = Cannot create channel sink to connect to URL '{0}'. An appropriate channel has probably not been registered. -Remoting_UnexpectedNullTP = Failed to create a transparent proxy. If a custom RealProxy is being used ensure it sets the proxy type. -; The following remoting exception messages appear in native resources too (mscorrc.rc) -Remoting_Disconnected = Object '{0}' has been disconnected or does not exist at the server. -Remoting_Message_MethodMissing = The method '{0}' was not found on the interface/type '{1}'. -#endif // FEATURE_REMOTING - -; Resources exceptions -; -Resources_StreamNotValid = Stream is not a valid resource file. -ResourceReaderIsClosed = ResourceReader is closed. - -; RuntimeWrappedException -RuntimeWrappedException = An object that does not derive from System.Exception has been wrapped in a RuntimeWrappedException. - -; UnauthorizedAccessException -UnauthorizedAccess_MemStreamBuffer = MemoryStream's internal buffer cannot be accessed. -UnauthorizedAccess_IODenied_Path = Access to the path '{0}' is denied. -UnauthorizedAccess_IODenied_NoPathName = Access to the path is denied. -UnauthorizedAccess_RegistryKeyGeneric_Key = Access to the registry key '{0}' is denied. -UnauthorizedAccess_RegistryNoWrite = Cannot write to the registry key. -UnauthorizedAccess_SystemDomain = Cannot execute an assembly in the system domain. - -; -; Security exceptions -; - -;SecurityException -; These still appear in bcl.small but should go away eventually -Security_Generic = Request for the permission of type '{0}' failed. -Security_GenericNoType = Request failed. -Security_NoAPTCA = That assembly does not allow partially trusted callers. -Security_RegistryPermission = Requested registry access is not allowed. -Security_MustRevertOverride = Stack walk modifier must be reverted before another modification of the same type can be performed. -#if FEATURE_CAS_POLICY -Security_CannotGenerateHash = Hash for the assembly cannot be generated. -Security_CannotGetRawData = Assembly bytes could not be retrieved. -Security_PrincipalPermission = Request for principal permission failed. -Security_Action = The action that failed was: -Security_TypeFirstPermThatFailed = The type of the first permission that failed was: -Security_FirstPermThatFailed = The first permission that failed was: -Security_Demanded = The demand was for: -Security_GrantedSet = The granted set of the failing assembly was: -Security_RefusedSet = The refused set of the failing assembly was: -Security_Denied = The denied permissions were: -Security_PermitOnly = The only permitted permissions were: -Security_Assembly = The assembly or AppDomain that failed was: -Security_Method = The method that caused the failure was: -Security_Zone = The Zone of the assembly that failed was: -Security_Url = The Url of the assembly that failed was: -Security_AnonymouslyHostedDynamicMethodCheckFailed = The demand failed due to the code access security information captured during the creation of an anonymously hosted dynamic method. In order for this operation to succeed, ensure that the demand would have succeeded at the time the method was created. See http://go.microsoft.com/fwlink/?LinkId=288746 for more information. -#endif // FEATURE_CAS_POLICY - -; -; HostProtection exceptions -; - -HostProtection_HostProtection = Attempted to perform an operation that was forbidden by the CLR host. -HostProtection_ProtectedResources = The protected resources (only available with full trust) were: -HostProtection_DemandedResources = The demanded resources were: - -; -; IO exceptions -; - -; EOFException -IO.EOF_ReadBeyondEOF = Unable to read beyond the end of the stream. - -; FileNotFoundException -IO.FileNotFound = Unable to find the specified file. -IO.FileNotFound_FileName = Could not find file '{0}'. -IO.FileName_Name = File name: '{0}' -IO.FileLoad = Could not load the specified file. - -; IOException -IO.IO_AlreadyExists_Name = Cannot create "{0}" because a file or directory with the same name already exists. -IO.IO_BindHandleFailed = BindHandle for ThreadPool failed on this handle. -IO.IO_FileExists_Name = The file '{0}' already exists. -IO.IO_FileStreamHandlePosition = The OS handle's position is not what FileStream expected. Do not use a handle simultaneously in one FileStream and in Win32 code or another FileStream. This may cause data loss. -IO.IO_FileTooLong2GB = The file is too long. This operation is currently limited to supporting files less than 2 gigabytes in size. -IO.IO_FileTooLongOrHandleNotSync = IO operation will not work. Most likely the file will become too long or the handle was not opened to support synchronous IO operations. -IO.IO_FixedCapacity = Unable to expand length of this stream beyond its capacity. -IO.IO_InvalidStringLen_Len = BinaryReader encountered an invalid string length of {0} characters. -IO.IO_NoConsole = There is no console. -IO.IO_NoPermissionToDirectoryName = -IO.IO_SeekBeforeBegin = An attempt was made to move the position before the beginning of the stream. -IO.IO_SeekAppendOverwrite = Unable seek backward to overwrite data that previously existed in a file opened in Append mode. -IO.IO_SetLengthAppendTruncate = Unable to truncate data that previously existed in a file opened in Append mode. -IO.IO_SharingViolation_File = The process cannot access the file '{0}' because it is being used by another process. -IO.IO_SharingViolation_NoFileName = The process cannot access the file because it is being used by another process. -IO.IO_StreamTooLong = Stream was too long. -IO.IO_CannotCreateDirectory = The specified directory '{0}' cannot be created. -IO.IO_SourceDestMustBeDifferent = Source and destination path must be different. -IO.IO_SourceDestMustHaveSameRoot = Source and destination path must have identical roots. Move will not work across volumes. - -; DirectoryNotFoundException -IO.DriveNotFound_Drive = Could not find the drive '{0}'. The drive might not be ready or might not be mapped. -IO.PathNotFound_Path = Could not find a part of the path '{0}'. -IO.PathNotFound_NoPathName = Could not find a part of the path. - -; PathTooLongException -IO.PathTooLong = The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters. - -#if FEATURE_CORECLR -; SecurityException -FileSecurityState_OperationNotPermitted = File operation not permitted. Access to path '{0}' is denied. -#endif - -; PrivilegeNotHeldException -PrivilegeNotHeld_Default = The process does not possess some privilege required for this operation. -PrivilegeNotHeld_Named = The process does not possess the '{0}' privilege which is required for this operation. - -; General strings used in the IO package -IO_UnknownFileName = [Unknown] -IO_StreamWriterBufferedDataLost = A StreamWriter was not closed and all buffered data within that StreamWriter was not flushed to the underlying stream. (This was detected when the StreamWriter was finalized with data in its buffer.) A portion of the data was lost. Consider one of calling Close(), Flush(), setting the StreamWriter's AutoFlush property to true, or allocating the StreamWriter with a "using" statement. Stream type: {0}\r\nFile name: {1}\r\nAllocated from:\r\n {2} -IO_StreamWriterBufferedDataLostCaptureAllocatedFromCallstackNotEnabled = callstack information is not captured by default for performance reasons. Please enable captureAllocatedCallStack config switch for streamWriterBufferedDataLost MDA (refer to MSDN MDA documentation for how to do this). - -; -; Serialization Exceptions -; -; SerializationException -Serialization_InvalidData=An error occurred while deserializing the object. The serialized data is corrupt. -Serialization_InvalidPtrValue = An IntPtr or UIntPtr with an eight byte value cannot be deserialized on a machine with a four byte word size. -Serialization_MemberTypeNotRecognized = Unknown member type. -Serialization_InsufficientState = Insufficient state to return the real object. -Serialization_InvalidFieldState = Object fields may not be properly initialized. -Serialization_MissField = Field {0} is missing. -Serialization_NullSignature = The method signature cannot be null. -Serialization_UnknownMember = Cannot get the member '{0}'. -Serialization_InsufficientDeserializationState = Insufficient state to deserialize the object. Missing field '{0}'. More information is needed. -Serialization_UnableToFindModule = The given module {0} cannot be found within the assembly {1}. -Serialization_InvalidOnDeser = OnDeserialization method was called while the object was not being deserialized. -Serialization_MissingKeys = The Keys for this Hashtable are missing. -Serialization_MissingValues = The values for this dictionary are missing. -Serialization_NullKey = One of the serialized keys is null. -Serialization_KeyValueDifferentSizes = The keys and values arrays have different sizes. -Serialization_SameNameTwice = Cannot add the same member twice to a SerializationInfo object. -Serialization_BadParameterInfo = Non existent ParameterInfo. Position bigger than member's parameters length. -Serialization_NoParameterInfo = Serialized member does not have a ParameterInfo. -Serialization_NotFound = Member '{0}' was not found. -Serialization_StringBuilderMaxCapacity = The serialized MaxCapacity property of StringBuilder must be positive and greater than or equal to the String length. -Serialization_StringBuilderCapacity = The serialized Capacity property of StringBuilder must be positive, less than or equal to MaxCapacity and greater than or equal to the String length. -Serialization_InvalidDelegateType = Cannot serialize delegates over unmanaged function pointers, dynamic methods or methods outside the delegate creator's assembly. -Serialization_OptionalFieldVersionValue = Version value must be positive. -Serialization_MissingDateTimeData = Invalid serialized DateTime data. Unable to find 'ticks' or 'dateData'. -Serialization_DateTimeTicksOutOfRange = Invalid serialized DateTime data. Ticks must be between DateTime.MinValue.Ticks and DateTime.MaxValue.Ticks. -; The following serialization exception messages appear in native resources too (mscorrc.rc) -Serialization_MemberOutOfRange = The deserialized value of the member "{0}" in the class "{1}" is out of range. - -#if FEATURE_SERIALIZATION -Serialization_NoID = Object has never been assigned an objectID. -Serialization_UnknownMemberInfo = Only FieldInfo, PropertyInfo, and SerializationMemberInfo are recognized. -Serialization_UnableToFixup = Cannot perform fixup. -Serialization_NoType = Object does not specify a type. -Serialization_ValueTypeFixup = ValueType fixup on Arrays is not implemented. -Serialization_PartialValueTypeFixup = Fixing up a partially available ValueType chain is not implemented. -Serialization_InvalidID = Object specifies an invalid ID. -Serialization_DuplicateSelector = Selector is already on the list of checked selectors. -Serialization_NoBaseType = Object does not specify a base type. -Serialization_ArrayNoLength = Array does not specify a length. -Serialization_CannotGetType = Cannot get the type '{0}'. -Serialization_AssemblyNotFound = Unable to find assembly '{0}'. -Serialization_ArrayInvalidLength = Array specifies an invalid length. -Serialization_MalformedArray = The array information in the stream is invalid. -Serialization_MultipleMembers = Cannot resolve multiple members with the same name. -Serialization_ObjectUsedBeforeDeserCallback = An object was used before its deserialization callback ran, which may break higher-level consistency guarantees in the application. -Serialization_RegisterTwice = An object cannot be registered twice. -Serialization_IdTooSmall = Object IDs must be greater than zero. -Serialization_TooManyReferences = The implementation of the IObjectReference interface returns too many nested references to other objects that implement IObjectReference. -Serialization_NotISer = The given object does not implement the ISerializable interface. -Serialization_MissingKeyValuePairs = The KeyValuePairs for this Dictionary are missing. -Serialization_SurrogateCycleInArgument = Selector contained a cycle. -Serialization_SurrogateCycle = Adding selector will introduce a cycle. -Serialization_NeverSeen = A fixup is registered to the object with ID {0}, but the object does not appear in the graph. -Serialization_IORIncomplete = The object with ID {0} implements the IObjectReference interface for which all dependencies cannot be resolved. The likely cause is two instances of IObjectReference that have a mutual dependency on each other. -Serialization_NotCyclicallyReferenceableSurrogate = {0}.SetObjectData returns a value that is neither null nor equal to the first parameter. Such Surrogates cannot be part of cyclical reference. -Serialization_ObjectNotSupplied = The object with ID {0} was referenced in a fixup but does not exist. -Serialization_TooManyElements = The internal array cannot expand to greater than Int32.MaxValue elements. -Serialization_InvalidType = Only system-provided types can be passed to the GetUninitializedObject method. '{0}' is not a valid instance of a type. -Serialization_MissingObject = The object with ID {0} was referenced in a fixup but has not been registered. -Serialization_InvalidFixupType = A member fixup was registered for an object which implements ISerializable or has a surrogate. In this situation, a delayed fixup must be used. -Serialization_InvalidFixupDiscovered = A fixup on an object implementing ISerializable or having a surrogate was discovered for an object which does not have a SerializationInfo available. -Serialization_InvalidFormat = The input stream is not a valid binary format. The starting contents (in bytes) are: {0} ... -Serialization_ParentChildIdentical = The ID of the containing object cannot be the same as the object ID. -Serialization_IncorrectNumberOfFixups = The ObjectManager found an invalid number of fixups. This usually indicates a problem in the Formatter. -; The following serialization exception messages appear in native resources too (mscorrc.rc) -Serialization_NonSerType = Type '{0}' in Assembly '{1}' is not marked as serializable. -Serialization_ConstructorNotFound = The constructor to deserialize an object of type '{0}' was not found. - -; SerializationException used by Formatters -Serialization_ArrayType = Invalid array type '{0}'. -Serialization_ArrayTypeObject = Array element type is Object, 'dt' attribute is null. -Serialization_Assembly = No assembly information is available for object on the wire, '{0}'. -Serialization_AssemblyId = No assembly ID for object type '{0}'. -Serialization_BinaryHeader = Binary stream '{0}' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization. -Serialization_CrossAppDomainError = Cross-AppDomain BinaryFormatter error; expected '{0}' but received '{1}'. -Serialization_CorruptedStream = Invalid BinaryFormatter stream. -Serialization_HeaderReflection = Header reflection error: number of value members: {0}. -Serialization_ISerializableTypes = Types not available for ISerializable object '{0}'. -Serialization_ISerializableMemberInfo = MemberInfo requested for ISerializable type. -Serialization_MBRAsMBV = Type {0} must be marshaled by reference in this context. -Serialization_Map = No map for object '{0}'. -Serialization_MemberInfo = MemberInfo cannot be obtained for ISerialized Object '{0}'. -Serialization_Method = Invalid MethodCall or MethodReturn stream format. -Serialization_MissingMember = Member '{0}' in class '{1}' is not present in the serialized stream and is not marked with {2}. -Serialization_NoMemberInfo = No MemberInfo for Object {0}. -Serialization_ObjNoID = Object {0} has never been assigned an objectID. -Serialization_ObjectTypeEnum = Invalid ObjectTypeEnum {0}. -Serialization_ParseError = Parse error. Current element is not compatible with the next element, {0}. -Serialization_SerMemberInfo = MemberInfo type {0} cannot be serialized. -Serialization_Stream = Attempting to deserialize an empty stream. -Serialization_StreamEnd = End of Stream encountered before parsing was completed. -Serialization_TopObject = No top object. -Serialization_TopObjectInstantiate = Top object cannot be instantiated for element '{0}'. -Serialization_TypeCode = Invalid type code in stream '{0}'. -Serialization_TypeExpected = Invalid expected type. -Serialization_TypeMissing = Type is missing for member of type Object '{0}'. -Serialization_TypeRead = Invalid read type request '{0}'. -Serialization_TypeSecurity = Type {0} and the types derived from it (such as {1}) are not permitted to be deserialized at this security level. -Serialization_TypeWrite = Invalid write type request '{0}'. -Serialization_XMLElement = Invalid element '{0}'. -Serialization_Security = Because of security restrictions, the type {0} cannot be accessed. -Serialization_TypeLoadFailure = Unable to load type {0} required for deserialization. -Serialization_RequireFullTrust = A type '{0}' that is defined in a partially trusted assembly cannot be type forwarded from an assembly with a different Public Key Token or without a public key token. To fix this, please either turn on unsafeTypeForwarding flag in the configuration file or remove the TypeForwardedFrom attribute. -; The following serialization exception messages appear in native resources too (mscorrc.rc) -Serialization_TypeResolved = Type is not resolved for member '{0}'. -#endif // FEATURE_SERIALIZATION - -; -; StringBuilder Exceptions -; -Arg_LongerThanSrcString = Source string was not long enough. Check sourceIndex and count. - - -; -; System.Threading -; - -; -; Thread Exceptions -; -ThreadState_NoAbortRequested = Unable to reset abort because no abort was requested. -Threading.WaitHandleTooManyPosts = The WaitHandle cannot be signaled because it would exceed its maximum count. -; -; WaitHandleCannotBeOpenedException -; -Threading.WaitHandleCannotBeOpenedException = No handle of the given name exists. -Threading.WaitHandleCannotBeOpenedException_InvalidHandle = A WaitHandle with system-wide name '{0}' cannot be created. A WaitHandle of a different type might have the same name. - -; -; AbandonedMutexException -; -Threading.AbandonedMutexException = The wait completed due to an abandoned mutex. - -; AggregateException -AggregateException_ctor_DefaultMessage=One or more errors occurred. -AggregateException_ctor_InnerExceptionNull=An element of innerExceptions was null. -AggregateException_DeserializationFailure=The serialization stream contains no inner exceptions. -AggregateException_ToString={0}{1}---> (Inner Exception #{2}) {3}{4}{5} - -; Cancellation -CancellationToken_CreateLinkedToken_TokensIsEmpty=No tokens were supplied. -CancellationTokenSource_Disposed=The CancellationTokenSource has been disposed. -CancellationToken_SourceDisposed=The CancellationTokenSource associated with this CancellationToken has been disposed. - -; Exceptions shared by all concurrent collection -ConcurrentCollection_SyncRoot_NotSupported=The SyncRoot property may not be used for the synchronization of concurrent collections. - -; Exceptions shared by ConcurrentStack and ConcurrentQueue -ConcurrentStackQueue_OnDeserialization_NoData=The serialization stream contains no elements. - -; ConcurrentStack -ConcurrentStack_PushPopRange_StartOutOfRange=The startIndex argument must be greater than or equal to zero. -ConcurrentStack_PushPopRange_CountOutOfRange=The count argument must be greater than or equal to zero. -ConcurrentStack_PushPopRange_InvalidCount=The sum of the startIndex and count arguments must be less than or equal to the collection's Count. - -; ConcurrentDictionary -ConcurrentDictionary_ItemKeyIsNull=TKey is a reference type and item.Key is null. -ConcurrentDictionary_SourceContainsDuplicateKeys=The source argument contains duplicate keys. -ConcurrentDictionary_IndexIsNegative=The index argument is less than zero. -ConcurrentDictionary_ConcurrencyLevelMustBePositive=The concurrencyLevel argument must be positive. -ConcurrentDictionary_CapacityMustNotBeNegative=The capacity argument must be greater than or equal to zero. -ConcurrentDictionary_ArrayNotLargeEnough=The index is equal to or greater than the length of the array, or the number of elements in the dictionary is greater than the available space from index to the end of the destination array. -ConcurrentDictionary_ArrayIncorrectType=The array is multidimensional, or the type parameter for the set cannot be cast automatically to the type of the destination array. -ConcurrentDictionary_KeyAlreadyExisted=The key already existed in the dictionary. -ConcurrentDictionary_TypeOfKeyIncorrect=The key was of an incorrect type for this dictionary. -ConcurrentDictionary_TypeOfValueIncorrect=The value was of an incorrect type for this dictionary. - -; Partitioner -Partitioner_DynamicPartitionsNotSupported=Dynamic partitions are not supported by this partitioner. - -; OrderablePartitioner -OrderablePartitioner_GetPartitions_WrongNumberOfPartitions=GetPartitions returned an incorrect number of partitions. - -; PartitionerStatic -PartitionerStatic_CurrentCalledBeforeMoveNext=MoveNext must be called at least once before calling Current. -PartitionerStatic_CanNotCallGetEnumeratorAfterSourceHasBeenDisposed=Can not call GetEnumerator on partitions after the source enumerable is disposed - -; CDSCollectionETWBCLProvider events -event_ConcurrentStack_FastPushFailed=Push to ConcurrentStack spun {0} time(s). -event_ConcurrentStack_FastPopFailed=Pop from ConcurrentStack spun {0} time(s). -event_ConcurrentDictionary_AcquiringAllLocks=ConcurrentDictionary acquiring all locks on {0} bucket(s). -event_ConcurrentBag_TryTakeSteals=ConcurrentBag stealing in TryTake. -event_ConcurrentBag_TryPeekSteals=ConcurrentBag stealing in TryPeek. - -; CountdownEvent -CountdownEvent_Decrement_BelowZero=Invalid attempt made to decrement the event's count below zero. -CountdownEvent_Increment_AlreadyZero=The event is already signaled and cannot be incremented. -CountdownEvent_Increment_AlreadyMax=The increment operation would cause the CurrentCount to overflow. - -; Parallel -Parallel_Invoke_ActionNull=One of the actions was null. -Parallel_ForEach_OrderedPartitionerKeysNotNormalized=This method requires the use of an OrderedPartitioner with the KeysNormalized property set to true. -Parallel_ForEach_PartitionerNotDynamic=The Partitioner used here must support dynamic partitioning. -Parallel_ForEach_PartitionerReturnedNull=The Partitioner used here returned a null partitioner source. -Parallel_ForEach_NullEnumerator=The Partitioner source returned a null enumerator. - -; Semaphore -Argument_SemaphoreInitialMaximum=The initial count for the semaphore must be greater than or equal to zero and less than the maximum count. - -; SemaphoreFullException -Threading_SemaphoreFullException=Adding the specified count to the semaphore would cause it to exceed its maximum count. - -; Lazy -Lazy_ctor_ValueSelectorNull=The valueSelector argument is null. -Lazy_ctor_InfoNull=The info argument is null. -Lazy_ctor_deserialization_ValueInvalid=The Value cannot be null. -Lazy_ctor_ModeInvalid=The mode argument specifies an invalid value. -Lazy_CreateValue_NoParameterlessCtorForT=The lazily-initialized type does not have a public, parameterless constructor. -Lazy_StaticInit_InvalidOperation=ValueFactory returned null. -Lazy_Value_RecursiveCallsToValue=ValueFactory attempted to access the Value property of this instance. -Lazy_ToString_ValueNotCreated=Value is not created. - - -;ThreadLocal -ThreadLocal_Value_RecursiveCallsToValue=ValueFactory attempted to access the Value property of this instance. -ThreadLocal_Disposed=The ThreadLocal object has been disposed. -ThreadLocal_ValuesNotAvailable=The ThreadLocal object is not tracking values. To use the Values property, use a ThreadLocal constructor that accepts the trackAllValues parameter and set the parameter to true. - -; SemaphoreSlim -SemaphoreSlim_ctor_InitialCountWrong=The initialCount argument must be non-negative and less than or equal to the maximumCount. -SemaphoreSlim_ctor_MaxCountWrong=The maximumCount argument must be a positive number. If a maximum is not required, use the constructor without a maxCount parameter. -SemaphoreSlim_Wait_TimeoutWrong=The timeout must represent a value between -1 and Int32.MaxValue, inclusive. -SemaphoreSlim_Release_CountWrong=The releaseCount argument must be greater than zero. -SemaphoreSlim_Disposed=The semaphore has been disposed. - -; ManualResetEventSlim -ManualResetEventSlim_ctor_SpinCountOutOfRange=The spinCount argument must be in the range 0 to {0}, inclusive. -ManualResetEventSlim_ctor_TooManyWaiters=There are too many threads currently waiting on the event. A maximum of {0} waiting threads are supported. -ManualResetEventSlim_Disposed=The event has been disposed. - -; SpinLock -SpinLock_TryEnter_ArgumentOutOfRange=The timeout must be a value between -1 and Int32.MaxValue, inclusive. -SpinLock_TryEnter_LockRecursionException=The calling thread already holds the lock. -SpinLock_TryReliableEnter_ArgumentException=The tookLock argument must be set to false before calling this method. -SpinLock_Exit_SynchronizationLockException=The calling thread does not hold the lock. -SpinLock_IsHeldByCurrentThread=Thread tracking is disabled. - -; SpinWait -SpinWait_SpinUntil_TimeoutWrong=The timeout must represent a value between -1 and Int32.MaxValue, inclusive. -SpinWait_SpinUntil_ArgumentNull=The condition argument is null. - -; CdsSyncEtwBCLProvider events -event_SpinLock_FastPathFailed=SpinLock beginning to spin. -event_SpinWait_NextSpinWillYield=Next spin will yield. -event_Barrier_PhaseFinished=Barrier finishing phase {1}. - -#if PLATFORM_UNIX -; Unix threading -PlatformNotSupported_NamedSynchronizationPrimitives=The named version of this synchronization primitive is not supported on this platform. -PlatformNotSupported_NamedSyncObjectWaitAnyWaitAll=Wait operations on multiple wait handles including a named synchronization primitive are not supported on this platform. -#endif - -; -; System.Threading.Tasks -; - -; AsyncMethodBuilder -AsyncMethodBuilder_InstanceNotInitialized=The builder was not properly initialized. - -; TaskAwaiter and YieldAwaitable -AwaitableAwaiter_InstanceNotInitialized=The awaitable or awaiter was not properly initialized. -TaskAwaiter_TaskNotCompleted=The awaited task has not yet completed. - -; Task -TaskT_SetException_HasAnInitializer=A task's Exception may only be set directly if the task was created without a function. -TaskT_TransitionToFinal_AlreadyCompleted=An attempt was made to transition a task to a final state when it had already completed. -TaskT_ctor_SelfReplicating=It is invalid to specify TaskCreationOptions.SelfReplicating for a Task. -TaskT_DebuggerNoResult={Not yet computed} - -; Task -Task_ctor_LRandSR=(Internal)An attempt was made to create a LongRunning SelfReplicating task. -Task_ThrowIfDisposed=The task has been disposed. -Task_Dispose_NotCompleted=A task may only be disposed if it is in a completion state (RanToCompletion, Faulted or Canceled). -Task_Start_Promise=Start may not be called on a promise-style task. -Task_Start_AlreadyStarted=Start may not be called on a task that was already started. -Task_Start_TaskCompleted=Start may not be called on a task that has completed. -Task_Start_ContinuationTask=Start may not be called on a continuation task. -Task_RunSynchronously_AlreadyStarted=RunSynchronously may not be called on a task that was already started. -Task_RunSynchronously_TaskCompleted=RunSynchronously may not be called on a task that has already completed. -Task_RunSynchronously_Promise=RunSynchronously may not be called on a task not bound to a delegate, such as the task returned from an asynchronous method. -Task_RunSynchronously_Continuation=RunSynchronously may not be called on a continuation task. -Task_ContinueWith_NotOnAnything=The specified TaskContinuationOptions excluded all continuation kinds. -Task_ContinueWith_ESandLR=The specified TaskContinuationOptions combined LongRunning and ExecuteSynchronously. Synchronous continuations should not be long running. -Task_MultiTaskContinuation_NullTask=The tasks argument included a null value. -Task_MultiTaskContinuation_FireOptions=It is invalid to exclude specific continuation kinds for continuations off of multiple tasks. -Task_MultiTaskContinuation_EmptyTaskList=The tasks argument contains no tasks. -Task_FromAsync_TaskManagerShutDown=FromAsync was called with a TaskManager that had already shut down. -Task_FromAsync_SelfReplicating=It is invalid to specify TaskCreationOptions.SelfReplicating in calls to FromAsync. -Task_FromAsync_LongRunning=It is invalid to specify TaskCreationOptions.LongRunning in calls to FromAsync. -Task_FromAsync_PreferFairness=It is invalid to specify TaskCreationOptions.PreferFairness in calls to FromAsync. -Task_WaitMulti_NullTask=The tasks array included at least one null element. -Task_Delay_InvalidMillisecondsDelay=The value needs to be either -1 (signifying an infinite timeout), 0 or a positive integer. -Task_Delay_InvalidDelay=The value needs to translate in milliseconds to -1 (signifying an infinite timeout), 0 or a positive integer less than or equal to Int32.MaxValue. - -; TaskCanceledException -TaskCanceledException_ctor_DefaultMessage=A task was canceled. - -;TaskCompletionSource -TaskCompletionSourceT_TrySetException_NullException=The exceptions collection included at least one null element. -TaskCompletionSourceT_TrySetException_NoExceptions=The exceptions collection was empty. - -;TaskExceptionHolder -TaskExceptionHolder_UnknownExceptionType=(Internal)Expected an Exception or an IEnumerable -TaskExceptionHolder_UnhandledException=A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. - -; TaskScheduler -TaskScheduler_ExecuteTask_TaskAlreadyExecuted=ExecuteTask may not be called for a task which was already executed. -TaskScheduler_ExecuteTask_WrongTaskScheduler=ExecuteTask may not be called for a task which was previously queued to a different TaskScheduler. -TaskScheduler_InconsistentStateAfterTryExecuteTaskInline=The TryExecuteTaskInline call to the underlying scheduler succeeded, but the task body was not invoked. -TaskScheduler_FromCurrentSynchronizationContext_NoCurrent=The current SynchronizationContext may not be used as a TaskScheduler. - -; TaskSchedulerException -TaskSchedulerException_ctor_DefaultMessage=An exception was thrown by a TaskScheduler. - -; -; ParallelState ( used in Parallel.For(), Parallel.ForEach() ) -ParallelState_Break_InvalidOperationException_BreakAfterStop=Break was called after Stop was called. -ParallelState_Stop_InvalidOperationException_StopAfterBreak=Stop was called after Break was called. -ParallelState_NotSupportedException_UnsupportedMethod=This method is not supported. - -; -; TPLETWProvider events -event_ParallelLoopBegin=Beginning {3} loop {2} from Task {1}. -event_ParallelLoopEnd=Ending loop {2} after {3} iterations. -event_ParallelInvokeBegin=Beginning ParallelInvoke {2} from Task {1} for {4} actions. -event_ParallelInvokeEnd=Ending ParallelInvoke {2}. -event_ParallelFork=Task {1} entering fork/join {2}. -event_ParallelJoin=Task {1} leaving fork/join {2}. -event_TaskScheduled=Task {2} scheduled to TaskScheduler {0}. -event_TaskStarted=Task {2} executing. -event_TaskCompleted=Task {2} completed. -event_TaskWaitBegin=Beginning wait ({3}) on Task {2}. -event_TaskWaitEnd=Ending wait on Task {2}. - - -; -; Weak Reference Exception -; -WeakReference_NoLongerValid = The weak reference is no longer valid. - - -; -; Interop Exceptions -; -Interop.COM_TypeMismatch = Type mismatch between source and destination types. -Interop_Marshal_Unmappable_Char = Cannot marshal: Encountered unmappable character. - -#if FEATURE_COMINTEROP_WINRT_DESKTOP_HOST -WinRTHostDomainName = Windows Runtime Object Host Domain for '{0}' -#endif - -; -; Loader Exceptions -; -Loader_InvalidPath = Relative path must be a string that contains the substring, "..", or does not contain a root directory. -Loader_Name = Name: -Loader_NoContextPolicies = There are no context policies. -Loader_ContextPolicies = Context Policies: - -; -; AppDomain Exceptions -AppDomain_RequireApplicationName = ApplicationName must be set before the DynamicBase can be set. -AppDomain_AppBaseNotSet = The ApplicationBase must be set before retrieving this property. - -#if FEATURE_HOST_ASSEMBLY_RESOLVER -AppDomain_BindingModelIsLocked = Binding model is already locked for the AppDomain and cannot be reset. -Argument_CustomAssemblyLoadContextRequestedNameMismatch = Resolved assembly's simple name should be the same as of the requested assembly. -#endif // FEATURE_HOST_ASSEMBLY_RESOLVER -; -; XMLSyntaxExceptions -XMLSyntax_UnexpectedEndOfFile = Unexpected end of file. -XMLSyntax_ExpectedCloseBracket = Expected > character. -XMLSyntax_ExpectedSlashOrString = Expected / character or string. -XMLSyntax_UnexpectedCloseBracket = Unexpected > character. -XMLSyntax_SyntaxError = Invalid syntax on line {0}. -XMLSyntax_SyntaxErrorEx = Invalid syntax on line {0} - '{1}'. -XMLSyntax_InvalidSyntax = Invalid syntax. -XML_Syntax_InvalidSyntaxInFile = Invalid XML in file '{0}' near element '{1}'. -XMLSyntax_InvalidSyntaxSatAssemTag = Invalid XML in file "{0}" near element "{1}". The section only supports tags. -XMLSyntax_InvalidSyntaxSatAssemTagBadAttr = Invalid XML in file "{0}" near "{1}" and "{2}". In the section, the tag must have exactly 1 attribute called 'name', whose value is a fully-qualified assembly name. -XMLSyntax_InvalidSyntaxSatAssemTagNoAttr = Invalid XML in file "{0}". In the section, the tag must have exactly 1 attribute called 'name', whose value is a fully-qualified assembly name. - -; CodeGroup -#if FEATURE_CAS_POLICY -NetCodeGroup_PermissionSet = Same site Web -MergeLogic_Union = Union -MergeLogic_FirstMatch = First Match -FileCodeGroup_PermissionSet = Same directory FileIO - '{0}' -#endif // FEATURE_CAS_POLICY - -; MembershipConditions -StrongName_ToString = StrongName - {0}{1}{2} -StrongName_Name = name = {0} -StrongName_Version = version = {0} -Site_ToString = Site -Publisher_ToString = Publisher -Hash_ToString = Hash - {0} = {1} -ApplicationDirectory_ToString = ApplicationDirectory -Zone_ToString = Zone - {0} -All_ToString = All code -Url_ToString = Url -GAC_ToString = GAC -#if FEATURE_CAS_POLICY -Site_ToStringArg = Site - {0} -Publisher_ToStringArg = Publisher - {0} -Url_ToStringArg = Url - {0} -#endif // FEATURE_CAS_POLICY - - -; Interop non exception strings. -TypeLibConverter_ImportedTypeLibProductName = Assembly imported from type library '{0}'. - -; -; begin System.TimeZoneInfo ArgumentException's -; -Argument_AdjustmentRulesNoNulls = The AdjustmentRule array cannot contain null elements. -Argument_AdjustmentRulesOutOfOrder = The elements of the AdjustmentRule array must be in chronological order and must not overlap. -Argument_AdjustmentRulesAmbiguousOverlap = The elements of the AdjustmentRule array must not contain ambiguous time periods that extend beyond the DateStart or DateEnd properties of the element. -Argument_AdjustmentRulesrDaylightSavingTimeOverlap = The elements of the AdjustmentRule array must not contain Daylight Saving Time periods that overlap adjacent elements in such a way as to cause invalid or ambiguous time periods. -Argument_AdjustmentRulesrDaylightSavingTimeOverlapNonRuleRange = The elements of the AdjustmentRule array must not contain Daylight Saving Time periods that overlap the DateStart or DateEnd properties in such a way as to cause invalid or ambiguous time periods. -Argument_AdjustmentRulesInvalidOverlap = The elements of the AdjustmentRule array must not contain invalid time periods that extend beyond the DateStart or DateEnd properties of the element. -Argument_ConvertMismatch = The conversion could not be completed because the supplied DateTime did not have the Kind property set correctly. For example, when the Kind property is DateTimeKind.Local, the source time zone must be TimeZoneInfo.Local. -Argument_DateTimeHasTimeOfDay = The supplied DateTime includes a TimeOfDay setting. This is not supported. -Argument_DateTimeIsInvalid = The supplied DateTime represents an invalid time. For example, when the clock is adjusted forward, any time in the period that is skipped is invalid. -Argument_DateTimeIsNotAmbiguous = The supplied DateTime is not in an ambiguous time range. -Argument_DateTimeOffsetIsNotAmbiguous = The supplied DateTimeOffset is not in an ambiguous time range. -Argument_DateTimeKindMustBeUnspecifiedOrUtc = The supplied DateTime must have the Kind property set to DateTimeKind.Unspecified or DateTimeKind.Utc. -Argument_DateTimeHasTicks = The supplied DateTime must have the Year, Month, and Day properties set to 1. The time cannot be specified more precisely than whole milliseconds. -Argument_InvalidId = The specified ID parameter '{0}' is not supported. -Argument_InvalidSerializedString = The specified serialized string '{0}' is not supported. -Argument_InvalidREG_TZI_FORMAT = The REG_TZI_FORMAT structure is corrupt. -Argument_OutOfOrderDateTimes = The DateStart property must come before the DateEnd property. -Argument_TimeSpanHasSeconds = The TimeSpan parameter cannot be specified more precisely than whole minutes. -Argument_TimeZoneInfoBadTZif = The tzfile does not begin with the magic characters 'TZif'. Please verify that the file is not corrupt. -Argument_TimeZoneInfoInvalidTZif = The TZif data structure is corrupt. -Argument_TransitionTimesAreIdentical = The DaylightTransitionStart property must not equal the DaylightTransitionEnd property. -; -; begin System.TimeZoneInfo ArgumentOutOfRangeException's -; -ArgumentOutOfRange_DayParam = The Day parameter must be in the range 1 through 31. -ArgumentOutOfRange_DayOfWeek = The DayOfWeek enumeration must be in the range 0 through 6. -ArgumentOutOfRange_MonthParam = The Month parameter must be in the range 1 through 12. -ArgumentOutOfRange_UtcOffset = The TimeSpan parameter must be within plus or minus 14.0 hours. -ArgumentOutOfRange_UtcOffsetAndDaylightDelta = The sum of the BaseUtcOffset and DaylightDelta properties must within plus or minus 14.0 hours. -ArgumentOutOfRange_Week = The Week parameter must be in the range 1 through 5. -; -; begin System.TimeZoneInfo InvalidTimeZoneException's -; -InvalidTimeZone_InvalidRegistryData = The time zone ID '{0}' was found on the local computer, but the registry information was corrupt. -InvalidTimeZone_InvalidFileData = The time zone ID '{0}' was found on the local computer, but the file at '{1}' was corrupt. -InvalidTimeZone_InvalidWin32APIData = The Local time zone was found on the local computer, but the data was corrupt. -InvalidTimeZone_NoTTInfoStructures = There are no ttinfo structures in the tzfile. At least one ttinfo structure is required in order to construct a TimeZoneInfo object. -InvalidTimeZone_UnparseablePosixMDateString = '{0}' is not a valid POSIX-TZ-environment-variable MDate rule. A valid rule has the format 'Mm.w.d'. -InvalidTimeZone_JulianDayNotSupported = Julian dates in POSIX strings are unsupported. -; -; begin System.TimeZoneInfo SecurityException's -; -Security_CannotReadRegistryData = The time zone ID '{0}' was found on the local computer, but the application does not have permission to read the registry information. -Security_CannotReadFileData = The time zone ID '{0}' was found on the local computer, but the application does not have permission to read the file. -; -; begin System.TimeZoneInfo SerializationException's -; -Serialization_CorruptField = The value of the field '{0}' is invalid. The serialized data is corrupt. -Serialization_InvalidEscapeSequence = The serialized data contained an invalid escape sequence '\\{0}'. -; -; begin System.TimeZoneInfo TimeZoneNotFoundException's -; -TimeZoneNotFound_MissingData = The time zone ID '{0}' was not found on the local computer. -; -; end System.TimeZoneInfo -; - - -; Tuple -ArgumentException_TupleIncorrectType=Argument must be of type {0}. -ArgumentException_TupleNonIComparableElement=The tuple contains an element of type {0} which does not implement the IComparable interface. -ArgumentException_TupleLastArgumentNotATuple=The last element of an eight element tuple must be a Tuple. -ArgumentException_OtherNotArrayOfCorrectLength=Object is not a array with the same number of elements as the array to compare it to. - -; WinRT collection adapters -Argument_IndexOutOfArrayBounds=The specified index is out of bounds of the specified array. -Argument_InsufficientSpaceToCopyCollection=The specified space is not sufficient to copy the elements from this Collection. -ArgumentOutOfRange_IndexLargerThanMaxValue=This collection cannot work with indices larger than Int32.MaxValue - 1 (0x7FFFFFFF - 1). -ArgumentOutOfRange_IndexOutOfRange=The specified index is outside the current index range of this collection. -InvalidOperation_CollectionBackingListTooLarge=The collection backing this List contains too many elements. -InvalidOperation_CollectionBackingDictionaryTooLarge=The collection backing this Dictionary contains too many elements. -InvalidOperation_CannotRemoveLastFromEmptyCollection=Cannot remove the last element from an empty collection. - -; Globalization resources -;------------------ - -#if !FEATURE_CORECLR -Globalization.LegacyModifier = Legacy - -; -;Total items: 809 -; -Globalization.ci_ = Invariant Language (Invariant Country) -Globalization.ci_aa = Afar -Globalization.ci_aa-DJ = Afar (Djibouti) -Globalization.ci_aa-ER = Afar (Eritrea) -Globalization.ci_aa-ET = Afar (Ethiopia) -Globalization.ci_af = Afrikaans -Globalization.ci_af-NA = Afrikaans (Namibia) -Globalization.ci_af-ZA = Afrikaans (South Africa) -Globalization.ci_agq = Aghem -Globalization.ci_agq-CM = Aghem (Cameroon) -Globalization.ci_ak = Akan -Globalization.ci_ak-GH = Akan (Ghana) -Globalization.ci_am = Amharic -Globalization.ci_am-ET = Amharic (Ethiopia) -Globalization.ci_ar = Arabic -Globalization.ci_ar-001 = Arabic (World) -Globalization.ci_ar-AE = Arabic (U.A.E.) -Globalization.ci_ar-BH = Arabic (Bahrain) -Globalization.ci_ar-DJ = Arabic (Djibouti) -Globalization.ci_ar-DZ = Arabic (Algeria) -Globalization.ci_ar-EG = Arabic (Egypt) -Globalization.ci_ar-ER = Arabic (Eritrea) -Globalization.ci_ar-IL = Arabic (Israel) -Globalization.ci_ar-IQ = Arabic (Iraq) -Globalization.ci_ar-JO = Arabic (Jordan) -Globalization.ci_ar-KM = Arabic (Comoros) -Globalization.ci_ar-KW = Arabic (Kuwait) -Globalization.ci_ar-LB = Arabic (Lebanon) -Globalization.ci_ar-LY = Arabic (Libya) -Globalization.ci_ar-MA = Arabic (Morocco) -Globalization.ci_ar-MR = Arabic (Mauritania) -Globalization.ci_ar-OM = Arabic (Oman) -Globalization.ci_ar-PS = Arabic (Palestinian Authority) -Globalization.ci_ar-QA = Arabic (Qatar) -Globalization.ci_ar-SA = Arabic (Saudi Arabia) -Globalization.ci_ar-SD = Arabic (Sudan) -Globalization.ci_ar-SO = Arabic (Somalia) -Globalization.ci_ar-SS = Arabic (South Sudan) -Globalization.ci_ar-SY = Arabic (Syria) -Globalization.ci_ar-TD = Arabic (Chad) -Globalization.ci_ar-TN = Arabic (Tunisia) -Globalization.ci_ar-YE = Arabic (Yemen) -Globalization.ci_arn = Mapudungun -Globalization.ci_arn-CL = Mapudungun (Chile) -Globalization.ci_as = Assamese -Globalization.ci_as-IN = Assamese (India) -Globalization.ci_asa = Asu -Globalization.ci_asa-TZ = Asu (Tanzania) -Globalization.ci_ast = Asturian -Globalization.ci_ast-ES = Asturian (Spain) -Globalization.ci_az = Azerbaijani -Globalization.ci_az-Cyrl = Azerbaijani (Cyrillic) -Globalization.ci_az-Cyrl-AZ = Azerbaijani (Cyrillic, Azerbaijan) -Globalization.ci_az-Latn = Azerbaijani (Latin) -Globalization.ci_az-Latn-AZ = Azerbaijani (Latin, Azerbaijan) -Globalization.ci_ba = Bashkir -Globalization.ci_ba-RU = Bashkir (Russia) -Globalization.ci_bas = Basaa -Globalization.ci_bas-CM = Basaa (Cameroon) -Globalization.ci_be = Belarusian -Globalization.ci_be-BY = Belarusian (Belarus) -Globalization.ci_bem = Bemba -Globalization.ci_bem-ZM = Bemba (Zambia) -Globalization.ci_bez = Bena -Globalization.ci_bez-TZ = Bena (Tanzania) -Globalization.ci_bg = Bulgarian -Globalization.ci_bg-BG = Bulgarian (Bulgaria) -Globalization.ci_bm = Bambara -Globalization.ci_bm-Latn = Bambara (Latin) -Globalization.ci_bm-Latn-ML = Bambara (Latin, Mali) -Globalization.ci_bm-ML = Bamanankan (Latin, Mali) -Globalization.ci_bn = Bangla -Globalization.ci_bn-BD = Bangla (Bangladesh) -Globalization.ci_bn-IN = Bangla (India) -Globalization.ci_bo = Tibetan -Globalization.ci_bo-CN = Tibetan (PRC) -Globalization.ci_bo-IN = Tibetan (India) -Globalization.ci_br = Breton -Globalization.ci_br-FR = Breton (France) -Globalization.ci_brx = Bodo -Globalization.ci_brx-IN = Bodo (India) -Globalization.ci_bs = Bosnian -Globalization.ci_bs-Cyrl = Bosnian (Cyrillic) -Globalization.ci_bs-Cyrl-BA = Bosnian (Cyrillic, Bosnia and Herzegovina) -Globalization.ci_bs-Latn = Bosnian (Latin) -Globalization.ci_bs-Latn-BA = Bosnian (Latin, Bosnia and Herzegovina) -Globalization.ci_byn = Blin -Globalization.ci_byn-ER = Blin (Eritrea) -Globalization.ci_ca = Catalan -Globalization.ci_ca-AD = Catalan (Andorra) -Globalization.ci_ca-ES = Catalan (Catalan) -Globalization.ci_ca-ES-valencia = Valencian (Spain) -Globalization.ci_ca-FR = Catalan (France) -Globalization.ci_ca-IT = Catalan (Italy) -Globalization.ci_cgg = Chiga -Globalization.ci_cgg-UG = Chiga (Uganda) -Globalization.ci_chr = Cherokee -Globalization.ci_chr-Cher = Cherokee (Cherokee) -Globalization.ci_chr-Cher-US = Cherokee (Cherokee) -Globalization.ci_co = Corsican -Globalization.ci_co-FR = Corsican (France) -Globalization.ci_cs = Czech -Globalization.ci_cs-CZ = Czech (Czech Republic) -Globalization.ci_cy = Welsh -Globalization.ci_cy-GB = Welsh (United Kingdom) -Globalization.ci_da = Danish -Globalization.ci_da-DK = Danish (Denmark) -Globalization.ci_da-GL = Danish (Greenland) -Globalization.ci_dav = Taita -Globalization.ci_dav-KE = Taita (Kenya) -Globalization.ci_de = German -Globalization.ci_de-AT = German (Austria) -Globalization.ci_de-BE = German (Belgium) -Globalization.ci_de-CH = German (Switzerland) -Globalization.ci_de-DE = German (Germany) -Globalization.ci_de-DE_phoneb = German (Germany) -Globalization.ci_de-LI = German (Liechtenstein) -Globalization.ci_de-LU = German (Luxembourg) -Globalization.ci_dje = Zarma -Globalization.ci_dje-NE = Zarma (Niger) -Globalization.ci_dsb = Lower Sorbian -Globalization.ci_dsb-DE = Lower Sorbian (Germany) -Globalization.ci_dua = Duala -Globalization.ci_dua-CM = Duala (Cameroon) -Globalization.ci_dv = Divehi -Globalization.ci_dv-MV = Divehi (Maldives) -Globalization.ci_dyo = Jola-Fonyi -Globalization.ci_dyo-SN = Jola-Fonyi (Senegal) -Globalization.ci_dz = Dzongkha -Globalization.ci_dz-BT = Dzongkha (Bhutan) -Globalization.ci_ebu = Embu -Globalization.ci_ebu-KE = Embu (Kenya) -Globalization.ci_ee = Ewe -Globalization.ci_ee-GH = Ewe (Ghana) -Globalization.ci_ee-TG = Ewe (Togo) -Globalization.ci_el = Greek -Globalization.ci_el-CY = Greek (Cyprus) -Globalization.ci_el-GR = Greek (Greece) -Globalization.ci_en = English -Globalization.ci_en-001 = English (World) -Globalization.ci_en-029 = English (Caribbean) -Globalization.ci_en-150 = English (Europe) -Globalization.ci_en-AG = English (Antigua and Barbuda) -Globalization.ci_en-AI = English (Anguilla) -Globalization.ci_en-AS = English (American Samoa) -Globalization.ci_en-AU = English (Australia) -Globalization.ci_en-BB = English (Barbados) -Globalization.ci_en-BE = English (Belgium) -Globalization.ci_en-BM = English (Bermuda) -Globalization.ci_en-BS = English (Bahamas) -Globalization.ci_en-BW = English (Botswana) -Globalization.ci_en-BZ = English (Belize) -Globalization.ci_en-CA = English (Canada) -Globalization.ci_en-CC = English (Cocos [Keeling] Islands) -Globalization.ci_en-CK = English (Cook Islands) -Globalization.ci_en-CM = English (Cameroon) -Globalization.ci_en-CX = English (Christmas Island) -Globalization.ci_en-DM = English (Dominica) -Globalization.ci_en-ER = English (Eritrea) -Globalization.ci_en-FJ = English (Fiji) -Globalization.ci_en-FK = English (Falkland Islands) -Globalization.ci_en-FM = English (Micronesia) -Globalization.ci_en-GB = English (United Kingdom) -Globalization.ci_en-GD = English (Grenada) -Globalization.ci_en-GG = English (Guernsey) -Globalization.ci_en-GH = English (Ghana) -Globalization.ci_en-GI = English (Gibraltar) -Globalization.ci_en-GM = English (Gambia) -Globalization.ci_en-GU = English (Guam) -Globalization.ci_en-GY = English (Guyana) -Globalization.ci_en-HK = English (Hong Kong SAR) -Globalization.ci_en-IE = English (Ireland) -Globalization.ci_en-IM = English (Isle of Man) -Globalization.ci_en-IN = English (India) -Globalization.ci_en-IO = English (British Indian Ocean Territory) -Globalization.ci_en-JE = English (Jersey) -Globalization.ci_en-JM = English (Jamaica) -Globalization.ci_en-KE = English (Kenya) -Globalization.ci_en-KI = English (Kiribati) -Globalization.ci_en-KN = English (Saint Kitts and Nevis) -Globalization.ci_en-KY = English (Cayman Islands) -Globalization.ci_en-LC = English (Saint Lucia) -Globalization.ci_en-LR = English (Liberia) -Globalization.ci_en-LS = English (Lesotho) -Globalization.ci_en-MG = English (Madagascar) -Globalization.ci_en-MH = English (Marshall Islands) -Globalization.ci_en-MO = English (Macao SAR) -Globalization.ci_en-MP = English (Northern Mariana Islands) -Globalization.ci_en-MS = English (Montserrat) -Globalization.ci_en-MT = English (Malta) -Globalization.ci_en-MU = English (Mauritius) -Globalization.ci_en-MW = English (Malawi) -Globalization.ci_en-MY = English (Malaysia) -Globalization.ci_en-NA = English (Namibia) -Globalization.ci_en-NF = English (Norfolk Island) -Globalization.ci_en-NG = English (Nigeria) -Globalization.ci_en-NR = English (Nauru) -Globalization.ci_en-NU = English (Niue) -Globalization.ci_en-NZ = English (New Zealand) -Globalization.ci_en-PG = English (Papua New Guinea) -Globalization.ci_en-PH = English (Republic of the Philippines) -Globalization.ci_en-PK = English (Pakistan) -Globalization.ci_en-PN = English (Pitcairn Islands) -Globalization.ci_en-PR = English (Puerto Rico) -Globalization.ci_en-PW = English (Palau) -Globalization.ci_en-RW = English (Rwanda) -Globalization.ci_en-SB = English (Solomon Islands) -Globalization.ci_en-SC = English (Seychelles) -Globalization.ci_en-SD = English (Sudan) -Globalization.ci_en-SG = English (Singapore) -Globalization.ci_en-SH = English (St Helena, Ascension, Tristan da Cunha) -Globalization.ci_en-SL = English (Sierra Leone) -Globalization.ci_en-SS = English (South Sudan) -Globalization.ci_en-SX = English (Sint Maarten) -Globalization.ci_en-SZ = English (Swaziland) -Globalization.ci_en-TC = English (Turks and Caicos Islands) -Globalization.ci_en-TK = English (Tokelau) -Globalization.ci_en-TO = English (Tonga) -Globalization.ci_en-TT = English (Trinidad and Tobago) -Globalization.ci_en-TV = English (Tuvalu) -Globalization.ci_en-TZ = English (Tanzania) -Globalization.ci_en-UG = English (Uganda) -Globalization.ci_en-UM = English (US Minor Outlying Islands) -Globalization.ci_en-US = English (United States) -Globalization.ci_en-VC = English (Saint Vincent and the Grenadines) -Globalization.ci_en-VG = English (British Virgin Islands) -Globalization.ci_en-VI = English (US Virgin Islands) -Globalization.ci_en-VU = English (Vanuatu) -Globalization.ci_en-WS = English (Samoa) -Globalization.ci_en-ZA = English (South Africa) -Globalization.ci_en-ZM = English (Zambia) -Globalization.ci_en-ZW = English (Zimbabwe) -Globalization.ci_eo = Esperanto -Globalization.ci_eo-001 = Esperanto (World) -Globalization.ci_es = Spanish -Globalization.ci_es-419 = Spanish (Latin America) -Globalization.ci_es-AR = Spanish (Argentina) -Globalization.ci_es-BO = Spanish (Bolivia) -Globalization.ci_es-CL = Spanish (Chile) -Globalization.ci_es-CO = Spanish (Colombia) -Globalization.ci_es-CR = Spanish (Costa Rica) -Globalization.ci_es-CU = Spanish (Cuba) -Globalization.ci_es-DO = Spanish (Dominican Republic) -Globalization.ci_es-EC = Spanish (Ecuador) -Globalization.ci_es-ES = Spanish (Spain) -Globalization.ci_es-ES_tradnl = Spanish (Spain) -Globalization.ci_es-GQ = Spanish (Equatorial Guinea) -Globalization.ci_es-GT = Spanish (Guatemala) -Globalization.ci_es-HN = Spanish (Honduras) -Globalization.ci_es-MX = Spanish (Mexico) -Globalization.ci_es-NI = Spanish (Nicaragua) -Globalization.ci_es-PA = Spanish (Panama) -Globalization.ci_es-PE = Spanish (Peru) -Globalization.ci_es-PH = Spanish (Philippines) -Globalization.ci_es-PR = Spanish (Puerto Rico) -Globalization.ci_es-PY = Spanish (Paraguay) -Globalization.ci_es-SV = Spanish (El Salvador) -Globalization.ci_es-US = Spanish (United States) -Globalization.ci_es-UY = Spanish (Uruguay) -Globalization.ci_es-VE = Spanish (Bolivarian Republic of Venezuela) -Globalization.ci_et = Estonian -Globalization.ci_et-EE = Estonian (Estonia) -Globalization.ci_eu = Basque -Globalization.ci_eu-ES = Basque (Basque) -Globalization.ci_ewo = Ewondo -Globalization.ci_ewo-CM = Ewondo (Cameroon) -Globalization.ci_fa = Persian -Globalization.ci_fa-AF = Persian (Afghanistan) -Globalization.ci_fa-IR = Persian (Iran) -Globalization.ci_ff = Fulah -Globalization.ci_ff-CM = Fulah (Cameroon) -Globalization.ci_ff-GN = Fulah (Guinea) -Globalization.ci_ff-Latn = Fulah (Latin) -Globalization.ci_ff-Latn-SN = Fulah (Latin, Senegal) -Globalization.ci_ff-MR = Fulah (Mauritania) -Globalization.ci_fi = Finnish -Globalization.ci_fi-FI = Finnish (Finland) -Globalization.ci_fil = Filipino -Globalization.ci_fil-PH = Filipino (Philippines) -Globalization.ci_fo = Faroese -Globalization.ci_fo-FO = Faroese (Faroe Islands) -Globalization.ci_fr = French -Globalization.ci_fr-BE = French (Belgium) -Globalization.ci_fr-BF = French (Burkina Faso) -Globalization.ci_fr-BI = French (Burundi) -Globalization.ci_fr-BJ = French (Benin) -Globalization.ci_fr-BL = French (Saint Barthélemy) -Globalization.ci_fr-CA = French (Canada) -Globalization.ci_fr-CD = French (Congo DRC) -Globalization.ci_fr-CF = French (Central African Republic) -Globalization.ci_fr-CG = French (Congo) -Globalization.ci_fr-CH = French (Switzerland) -Globalization.ci_fr-CI = French (Côte d’Ivoire) -Globalization.ci_fr-CM = French (Cameroon) -Globalization.ci_fr-DJ = French (Djibouti) -Globalization.ci_fr-DZ = French (Algeria) -Globalization.ci_fr-FR = French (France) -Globalization.ci_fr-GA = French (Gabon) -Globalization.ci_fr-GF = French (French Guiana) -Globalization.ci_fr-GN = French (Guinea) -Globalization.ci_fr-GP = French (Guadeloupe) -Globalization.ci_fr-GQ = French (Equatorial Guinea) -Globalization.ci_fr-HT = French (Haiti) -Globalization.ci_fr-KM = French (Comoros) -Globalization.ci_fr-LU = French (Luxembourg) -Globalization.ci_fr-MA = French (Morocco) -Globalization.ci_fr-MC = French (Monaco) -Globalization.ci_fr-MF = French (Saint Martin) -Globalization.ci_fr-MG = French (Madagascar) -Globalization.ci_fr-ML = French (Mali) -Globalization.ci_fr-MQ = French (Martinique) -Globalization.ci_fr-MR = French (Mauritania) -Globalization.ci_fr-MU = French (Mauritius) -Globalization.ci_fr-NC = French (New Caledonia) -Globalization.ci_fr-NE = French (Niger) -Globalization.ci_fr-PF = French (French Polynesia) -Globalization.ci_fr-PM = French (Saint Pierre and Miquelon) -Globalization.ci_fr-RE = French (Reunion) -Globalization.ci_fr-RW = French (Rwanda) -Globalization.ci_fr-SC = French (Seychelles) -Globalization.ci_fr-SN = French (Senegal) -Globalization.ci_fr-SY = French (Syria) -Globalization.ci_fr-TD = French (Chad) -Globalization.ci_fr-TG = French (Togo) -Globalization.ci_fr-TN = French (Tunisia) -Globalization.ci_fr-VU = French (Vanuatu) -Globalization.ci_fr-WF = French (Wallis and Futuna) -Globalization.ci_fr-YT = French (Mayotte) -Globalization.ci_fur = Friulian -Globalization.ci_fur-IT = Friulian (Italy) -Globalization.ci_fy = Frisian -Globalization.ci_fy-NL = Frisian (Netherlands) -Globalization.ci_ga = Irish -Globalization.ci_ga-IE = Irish (Ireland) -Globalization.ci_gd = Scottish Gaelic -Globalization.ci_gd-GB = Scottish Gaelic (United Kingdom) -Globalization.ci_gl = Galician -Globalization.ci_gl-ES = Galician (Galician) -Globalization.ci_gn = Guarani -Globalization.ci_gn-PY = Guarani (Paraguay) -Globalization.ci_gsw = Alsatian -Globalization.ci_gsw-CH = Alsatian (Switzerland) -Globalization.ci_gsw-FR = Alsatian (France) -Globalization.ci_gsw-LI = Alsatian (Liechtenstein) -Globalization.ci_gu = Gujarati -Globalization.ci_gu-IN = Gujarati (India) -Globalization.ci_guz = Gusii -Globalization.ci_guz-KE = Gusii (Kenya) -Globalization.ci_gv = Manx -Globalization.ci_gv-IM = Manx (Isle of Man) -Globalization.ci_ha = Hausa -Globalization.ci_ha-Latn = Hausa (Latin) -Globalization.ci_ha-Latn-GH = Hausa (Latin, Ghana) -Globalization.ci_ha-Latn-NE = Hausa (Latin, Niger) -Globalization.ci_ha-Latn-NG = Hausa (Latin, Nigeria) -Globalization.ci_haw = Hawaiian -Globalization.ci_haw-US = Hawaiian (United States) -Globalization.ci_he = Hebrew -Globalization.ci_he-IL = Hebrew (Israel) -Globalization.ci_hi = Hindi -Globalization.ci_hi-IN = Hindi (India) -Globalization.ci_hr = Croatian -Globalization.ci_hr-BA = Croatian (Latin, Bosnia and Herzegovina) -Globalization.ci_hr-HR = Croatian (Croatia) -Globalization.ci_hsb = Upper Sorbian -Globalization.ci_hsb-DE = Upper Sorbian (Germany) -Globalization.ci_hu = Hungarian -Globalization.ci_hu-HU = Hungarian (Hungary) -Globalization.ci_hu-HU_technl = Hungarian (Hungary) -Globalization.ci_hy = Armenian -Globalization.ci_hy-AM = Armenian (Armenia) -Globalization.ci_ia = Interlingua -Globalization.ci_ia-001 = Interlingua (World) -Globalization.ci_ia-FR = Interlingua (France) -Globalization.ci_id = Indonesian -Globalization.ci_id-ID = Indonesian (Indonesia) -Globalization.ci_ig = Igbo -Globalization.ci_ig-NG = Igbo (Nigeria) -Globalization.ci_ii = Yi -Globalization.ci_ii-CN = Yi (PRC) -Globalization.ci_is = Icelandic -Globalization.ci_is-IS = Icelandic (Iceland) -Globalization.ci_it = Italian -Globalization.ci_it-CH = Italian (Switzerland) -Globalization.ci_it-IT = Italian (Italy) -Globalization.ci_it-SM = Italian (San Marino) -Globalization.ci_iu = Inuktitut -Globalization.ci_iu-Cans = Inuktitut (Syllabics) -Globalization.ci_iu-Cans-CA = Inuktitut (Syllabics, Canada) -Globalization.ci_iu-Latn = Inuktitut (Latin) -Globalization.ci_iu-Latn-CA = Inuktitut (Latin, Canada) -Globalization.ci_ja = Japanese -Globalization.ci_ja-JP = Japanese (Japan) -Globalization.ci_ja-JP_radstr = Japanese (Japan) -Globalization.ci_jgo = Ngomba -Globalization.ci_jgo-CM = Ngomba (Cameroon) -Globalization.ci_jmc = Machame -Globalization.ci_jmc-TZ = Machame (Tanzania) -Globalization.ci_jv = Javanese -Globalization.ci_jv-Latn = Javanese -Globalization.ci_jv-Latn-ID = Javanese (Indonesia) -Globalization.ci_ka = Georgian -Globalization.ci_ka-GE = Georgian (Georgia) -Globalization.ci_ka-GE_modern = Georgian (Georgia) -Globalization.ci_kab = Kabyle -Globalization.ci_kab-DZ = Kabyle (Algeria) -Globalization.ci_kam = Kamba -Globalization.ci_kam-KE = Kamba (Kenya) -Globalization.ci_kde = Makonde -Globalization.ci_kde-TZ = Makonde (Tanzania) -Globalization.ci_kea = Kabuverdianu -Globalization.ci_kea-CV = Kabuverdianu (Cabo Verde) -Globalization.ci_khq = Koyra Chiini -Globalization.ci_khq-ML = Koyra Chiini (Mali) -Globalization.ci_ki = Kikuyu -Globalization.ci_ki-KE = Kikuyu (Kenya) -Globalization.ci_kk = Kazakh -Globalization.ci_kk-KZ = Kazakh (Kazakhstan) -Globalization.ci_kkj = Kako -Globalization.ci_kkj-CM = Kako (Cameroon) -Globalization.ci_kl = Greenlandic -Globalization.ci_kl-GL = Greenlandic (Greenland) -Globalization.ci_kln = Kalenjin -Globalization.ci_kln-KE = Kalenjin (Kenya) -Globalization.ci_km = Khmer -Globalization.ci_km-KH = Khmer (Cambodia) -Globalization.ci_kn = Kannada -Globalization.ci_kn-IN = Kannada (India) -Globalization.ci_ko = Korean -Globalization.ci_ko-KR = Korean (Korea) -Globalization.ci_kok = Konkani -Globalization.ci_kok-IN = Konkani (India) -Globalization.ci_ks = Kashmiri -Globalization.ci_ks-Arab = Kashmiri (Perso-Arabic) -Globalization.ci_ks-Arab-IN = Kashmiri (Perso-Arabic) -Globalization.ci_ksb = Shambala -Globalization.ci_ksb-TZ = Shambala (Tanzania) -Globalization.ci_ksf = Bafia -Globalization.ci_ksf-CM = Bafia (Cameroon) -Globalization.ci_ksh = Colognian -Globalization.ci_ksh-DE = Ripuarian (Germany) -Globalization.ci_ku = Central Kurdish -Globalization.ci_ku-Arab = Central Kurdish (Arabic) -Globalization.ci_ku-Arab-IQ = Central Kurdish (Iraq) -Globalization.ci_kw = Cornish -Globalization.ci_kw-GB = Cornish (United Kingdom) -Globalization.ci_ky = Kyrgyz -Globalization.ci_ky-KG = Kyrgyz (Kyrgyzstan) -Globalization.ci_lag = Langi -Globalization.ci_lag-TZ = Langi (Tanzania) -Globalization.ci_lb = Luxembourgish -Globalization.ci_lb-LU = Luxembourgish (Luxembourg) -Globalization.ci_lg = Ganda -Globalization.ci_lg-UG = Ganda (Uganda) -Globalization.ci_lkt = Lakota -Globalization.ci_lkt-US = Lakota (United States) -Globalization.ci_ln = Lingala -Globalization.ci_ln-AO = Lingala (Angola) -Globalization.ci_ln-CD = Lingala (Congo DRC) -Globalization.ci_ln-CF = Lingala (Central African Republic) -Globalization.ci_ln-CG = Lingala (Congo) -Globalization.ci_lo = Lao -Globalization.ci_lo-LA = Lao (Lao P.D.R.) -Globalization.ci_lt = Lithuanian -Globalization.ci_lt-LT = Lithuanian (Lithuania) -Globalization.ci_lu = Luba-Katanga -Globalization.ci_lu-CD = Luba-Katanga (Congo DRC) -Globalization.ci_luo = Luo -Globalization.ci_luo-KE = Luo (Kenya) -Globalization.ci_luy = Luyia -Globalization.ci_luy-KE = Luyia (Kenya) -Globalization.ci_lv = Latvian -Globalization.ci_lv-LV = Latvian (Latvia) -Globalization.ci_mas = Masai -Globalization.ci_mas-KE = Masai (Kenya) -Globalization.ci_mas-TZ = Masai (Tanzania) -Globalization.ci_mer = Meru -Globalization.ci_mer-KE = Meru (Kenya) -Globalization.ci_mfe = Morisyen -Globalization.ci_mfe-MU = Morisyen (Mauritius) -Globalization.ci_mg = Malagasy -Globalization.ci_mg-MG = Malagasy (Madagascar) -Globalization.ci_mgh = Makhuwa-Meetto -Globalization.ci_mgh-MZ = Makhuwa-Meetto (Mozambique) -Globalization.ci_mgo = Meta' -Globalization.ci_mgo-CM = Meta' (Cameroon) -Globalization.ci_mi = Maori -Globalization.ci_mi-NZ = Maori (New Zealand) -Globalization.ci_mk = Macedonian (FYROM) -Globalization.ci_mk-MK = Macedonian (Former Yugoslav Republic of Macedonia) -Globalization.ci_ml = Malayalam -Globalization.ci_ml-IN = Malayalam (India) -Globalization.ci_mn = Mongolian -Globalization.ci_mn-Cyrl = Mongolian (Cyrillic) -Globalization.ci_mn-MN = Mongolian (Cyrillic, Mongolia) -Globalization.ci_mn-Mong = Mongolian (Traditional Mongolian) -Globalization.ci_mn-Mong-CN = Mongolian (Traditional Mongolian, PRC) -Globalization.ci_mn-Mong-MN = Mongolian (Traditional Mongolian, Mongolia) -Globalization.ci_moh = Mohawk -Globalization.ci_moh-CA = Mohawk (Mohawk) -Globalization.ci_mr = Marathi -Globalization.ci_mr-IN = Marathi (India) -Globalization.ci_ms = Malay -Globalization.ci_ms-BN = Malay (Brunei Darussalam) -Globalization.ci_ms-MY = Malay (Malaysia) -Globalization.ci_ms-SG = Malay (Latin, Singapore) -Globalization.ci_mt = Maltese -Globalization.ci_mt-MT = Maltese (Malta) -Globalization.ci_mua = Mundang -Globalization.ci_mua-CM = Mundang (Cameroon) -Globalization.ci_my = Burmese -Globalization.ci_my-MM = Burmese (Myanmar) -Globalization.ci_naq = Nama -Globalization.ci_naq-NA = Nama (Namibia) -Globalization.ci_nb = Norwegian (BokmÃ¥l) -Globalization.ci_nb-NO = Norwegian, BokmÃ¥l (Norway) -Globalization.ci_nb-SJ = Norwegian, BokmÃ¥l (Svalbard and Jan Mayen) -Globalization.ci_nd = North Ndebele -Globalization.ci_nd-ZW = North Ndebele (Zimbabwe) -Globalization.ci_ne = Nepali -Globalization.ci_ne-IN = Nepali (India) -Globalization.ci_ne-NP = Nepali (Nepal) -Globalization.ci_nl = Dutch -Globalization.ci_nl-AW = Dutch (Aruba) -Globalization.ci_nl-BE = Dutch (Belgium) -Globalization.ci_nl-BQ = Dutch (Bonaire, Sint Eustatius and Saba) -Globalization.ci_nl-CW = Dutch (Curaçao) -Globalization.ci_nl-NL = Dutch (Netherlands) -Globalization.ci_nl-SR = Dutch (Suriname) -Globalization.ci_nl-SX = Dutch (Sint Maarten) -Globalization.ci_nmg = Kwasio -Globalization.ci_nmg-CM = Kwasio (Cameroon) -Globalization.ci_nn = Norwegian (Nynorsk) -Globalization.ci_nn-NO = Norwegian, Nynorsk (Norway) -Globalization.ci_nnh = Ngiemboon -Globalization.ci_nnh-CM = Ngiemboon (Cameroon) -Globalization.ci_no = Norwegian -Globalization.ci_nqo = N'ko -Globalization.ci_nqo-GN = N'ko (Guinea) -Globalization.ci_nr = South Ndebele -Globalization.ci_nr-ZA = South Ndebele (South Africa) -Globalization.ci_nso = Sesotho sa Leboa -Globalization.ci_nso-ZA = Sesotho sa Leboa (South Africa) -Globalization.ci_nus = Nuer -Globalization.ci_nus-SD = Nuer (Sudan) -Globalization.ci_nyn = Nyankole -Globalization.ci_nyn-UG = Nyankole (Uganda) -Globalization.ci_oc = Occitan -Globalization.ci_oc-FR = Occitan (France) -Globalization.ci_om = Oromo -Globalization.ci_om-ET = Oromo (Ethiopia) -Globalization.ci_om-KE = Oromo (Kenya) -Globalization.ci_or = Odia -Globalization.ci_or-IN = Odia (India) -Globalization.ci_os = Ossetic -Globalization.ci_os-GE = Ossetian (Cyrillic, Georgia) -Globalization.ci_os-RU = Ossetian (Cyrillic, Russia) -Globalization.ci_pa = Punjabi -Globalization.ci_pa-Arab = Punjabi (Arabic) -Globalization.ci_pa-Arab-PK = Punjabi (Islamic Republic of Pakistan) -Globalization.ci_pa-IN = Punjabi (India) -Globalization.ci_pl = Polish -Globalization.ci_pl-PL = Polish (Poland) -Globalization.ci_prs = Dari -Globalization.ci_prs-AF = Dari (Afghanistan) -Globalization.ci_ps = Pashto -Globalization.ci_ps-AF = Pashto (Afghanistan) -Globalization.ci_pt = Portuguese -Globalization.ci_pt-AO = Portuguese (Angola) -Globalization.ci_pt-BR = Portuguese (Brazil) -Globalization.ci_pt-CV = Portuguese (Cabo Verde) -Globalization.ci_pt-GW = Portuguese (Guinea-Bissau) -Globalization.ci_pt-MO = Portuguese (Macao SAR) -Globalization.ci_pt-MZ = Portuguese (Mozambique) -Globalization.ci_pt-PT = Portuguese (Portugal) -Globalization.ci_pt-ST = Portuguese (São Tomé and Príncipe) -Globalization.ci_pt-TL = Portuguese (Timor-Leste) -Globalization.ci_qps-ploc = Pseudo Language (Pseudo) -Globalization.ci_qps-ploca = Pseudo Language (Pseudo Asia) -Globalization.ci_qps-plocm = Pseudo Language (Pseudo Mirrored) -Globalization.ci_qu = Quechua -Globalization.ci_qu-BO = Quechua (Bolivia) -Globalization.ci_qu-EC = Quechua (Ecuador) -Globalization.ci_qu-PE = Quechua (Peru) -Globalization.ci_quc = K'iche' -Globalization.ci_quc-Latn = K'iche' -Globalization.ci_quc-Latn-GT = K'iche' (Guatemala) -Globalization.ci_qut = K'iche -Globalization.ci_qut-GT = K'iche (Guatemala) -Globalization.ci_quz = Quechua -Globalization.ci_quz-BO = Quechua (Bolivia) -Globalization.ci_quz-EC = Quechua (Ecuador) -Globalization.ci_quz-PE = Quechua (Peru) -Globalization.ci_rm = Romansh -Globalization.ci_rm-CH = Romansh (Switzerland) -Globalization.ci_rn = Rundi -Globalization.ci_rn-BI = Rundi (Burundi) -Globalization.ci_ro = Romanian -Globalization.ci_ro-MD = Romanian (Moldova) -Globalization.ci_ro-RO = Romanian (Romania) -Globalization.ci_rof = Rombo -Globalization.ci_rof-TZ = Rombo (Tanzania) -Globalization.ci_ru = Russian -Globalization.ci_ru-BY = Russian (Belarus) -Globalization.ci_ru-KG = Russian (Kyrgyzstan) -Globalization.ci_ru-KZ = Russian (Kazakhstan) -Globalization.ci_ru-MD = Russian (Moldova) -Globalization.ci_ru-RU = Russian (Russia) -Globalization.ci_ru-UA = Russian (Ukraine) -Globalization.ci_rw = Kinyarwanda -Globalization.ci_rw-RW = Kinyarwanda (Rwanda) -Globalization.ci_rwk = Rwa -Globalization.ci_rwk-TZ = Rwa (Tanzania) -Globalization.ci_sa = Sanskrit -Globalization.ci_sa-IN = Sanskrit (India) -Globalization.ci_sah = Sakha -Globalization.ci_sah-RU = Sakha (Russia) -Globalization.ci_saq = Samburu -Globalization.ci_saq-KE = Samburu (Kenya) -Globalization.ci_sbp = Sangu -Globalization.ci_sbp-TZ = Sangu (Tanzania) -Globalization.ci_sd = Sindhi -Globalization.ci_sd-Arab = Sindhi (Arabic) -Globalization.ci_sd-Arab-PK = Sindhi (Islamic Republic of Pakistan) -Globalization.ci_se = Sami (Northern) -Globalization.ci_se-FI = Sami, Northern (Finland) -Globalization.ci_se-NO = Sami, Northern (Norway) -Globalization.ci_se-SE = Sami, Northern (Sweden) -Globalization.ci_seh = Sena -Globalization.ci_seh-MZ = Sena (Mozambique) -Globalization.ci_ses = Koyraboro Senni -Globalization.ci_ses-ML = Koyraboro Senni (Mali) -Globalization.ci_sg = Sango -Globalization.ci_sg-CF = Sango (Central African Republic) -Globalization.ci_shi = Tachelhit -Globalization.ci_shi-Latn = Tachelhit (Latin) -Globalization.ci_shi-Latn-MA = Tachelhit (Latin, Morocco) -Globalization.ci_shi-Tfng = Tachelhit (Tifinagh) -Globalization.ci_shi-Tfng-MA = Tachelhit (Tifinagh, Morocco) -Globalization.ci_si = Sinhala -Globalization.ci_si-LK = Sinhala (Sri Lanka) -Globalization.ci_sk = Slovak -Globalization.ci_sk-SK = Slovak (Slovakia) -Globalization.ci_sl = Slovenian -Globalization.ci_sl-SI = Slovenian (Slovenia) -Globalization.ci_sma = Sami (Southern) -Globalization.ci_sma-NO = Sami, Southern (Norway) -Globalization.ci_sma-SE = Sami, Southern (Sweden) -Globalization.ci_smj = Sami (Lule) -Globalization.ci_smj-NO = Sami, Lule (Norway) -Globalization.ci_smj-SE = Sami, Lule (Sweden) -Globalization.ci_smn = Sami (Inari) -Globalization.ci_smn-FI = Sami, Inari (Finland) -Globalization.ci_sms = Sami (Skolt) -Globalization.ci_sms-FI = Sami, Skolt (Finland) -Globalization.ci_sn = Shona -Globalization.ci_sn-Latn = Shona (Latin) -Globalization.ci_sn-Latn-ZW = Shona (Latin, Zimbabwe) -Globalization.ci_so = Somali -Globalization.ci_so-DJ = Somali (Djibouti) -Globalization.ci_so-ET = Somali (Ethiopia) -Globalization.ci_so-KE = Somali (Kenya) -Globalization.ci_so-SO = Somali (Somalia) -Globalization.ci_sq = Albanian -Globalization.ci_sq-AL = Albanian (Albania) -Globalization.ci_sq-MK = Albanian (Macedonia, FYRO) -Globalization.ci_sr = Serbian -Globalization.ci_sr-Cyrl = Serbian (Cyrillic) -Globalization.ci_sr-Cyrl-BA = Serbian (Cyrillic, Bosnia and Herzegovina) -Globalization.ci_sr-Cyrl-CS = Serbian (Cyrillic, Serbia and Montenegro (Former)) -Globalization.ci_sr-Cyrl-ME = Serbian (Cyrillic, Montenegro) -Globalization.ci_sr-Cyrl-RS = Serbian (Cyrillic, Serbia) -Globalization.ci_sr-Latn = Serbian (Latin) -Globalization.ci_sr-Latn-BA = Serbian (Latin, Bosnia and Herzegovina) -Globalization.ci_sr-Latn-CS = Serbian (Latin, Serbia and Montenegro (Former)) -Globalization.ci_sr-Latn-ME = Serbian (Latin, Montenegro) -Globalization.ci_sr-Latn-RS = Serbian (Latin, Serbia) -Globalization.ci_ss = Swati -Globalization.ci_ss-SZ = Swati (Swaziland) -Globalization.ci_ss-ZA = Swati (South Africa) -Globalization.ci_ssy = Saho -Globalization.ci_ssy-ER = Saho (Eritrea) -Globalization.ci_st = Southern Sotho -Globalization.ci_st-LS = Sesotho (Lesotho) -Globalization.ci_st-ZA = Southern Sotho (South Africa) -Globalization.ci_sv = Swedish -Globalization.ci_sv-AX = Swedish (Åland Islands) -Globalization.ci_sv-FI = Swedish (Finland) -Globalization.ci_sv-SE = Swedish (Sweden) -Globalization.ci_sw = Kiswahili -Globalization.ci_sw-KE = Kiswahili (Kenya) -Globalization.ci_sw-TZ = Kiswahili (Tanzania) -Globalization.ci_sw-UG = Kiswahili (Uganda) -Globalization.ci_swc = Congo Swahili -Globalization.ci_swc-CD = Congo Swahili (Congo DRC) -Globalization.ci_syr = Syriac -Globalization.ci_syr-SY = Syriac (Syria) -Globalization.ci_ta = Tamil -Globalization.ci_ta-IN = Tamil (India) -Globalization.ci_ta-LK = Tamil (Sri Lanka) -Globalization.ci_ta-MY = Tamil (Malaysia) -Globalization.ci_ta-SG = Tamil (Singapore) -Globalization.ci_te = Telugu -Globalization.ci_te-IN = Telugu (India) -Globalization.ci_teo = Teso -Globalization.ci_teo-KE = Teso (Kenya) -Globalization.ci_teo-UG = Teso (Uganda) -Globalization.ci_tg = Tajik -Globalization.ci_tg-Cyrl = Tajik (Cyrillic) -Globalization.ci_tg-Cyrl-TJ = Tajik (Cyrillic, Tajikistan) -Globalization.ci_th = Thai -Globalization.ci_th-TH = Thai (Thailand) -Globalization.ci_ti = Tigrinya -Globalization.ci_ti-ER = Tigrinya (Eritrea) -Globalization.ci_ti-ET = Tigrinya (Ethiopia) -Globalization.ci_tig = Tigre -Globalization.ci_tig-ER = Tigre (Eritrea) -Globalization.ci_tk = Turkmen -Globalization.ci_tk-TM = Turkmen (Turkmenistan) -Globalization.ci_tn = Setswana -Globalization.ci_tn-BW = Setswana (Botswana) -Globalization.ci_tn-ZA = Setswana (South Africa) -Globalization.ci_to = Tongan -Globalization.ci_to-TO = Tongan (Tonga) -Globalization.ci_tr = Turkish -Globalization.ci_tr-CY = Turkish (Cyprus) -Globalization.ci_tr-TR = Turkish (Turkey) -Globalization.ci_ts = Tsonga -Globalization.ci_ts-ZA = Tsonga (South Africa) -Globalization.ci_tt = Tatar -Globalization.ci_tt-RU = Tatar (Russia) -Globalization.ci_twq = Tasawaq -Globalization.ci_twq-NE = Tasawaq (Niger) -Globalization.ci_tzm = Tamazight -Globalization.ci_tzm-Latn = Tamazight (Latin) -Globalization.ci_tzm-Latn-DZ = Tamazight (Latin, Algeria) -Globalization.ci_tzm-Latn-MA = Central Atlas Tamazight (Latin, Morocco) -Globalization.ci_tzm-Tfng = Tamazight (Tifinagh) -Globalization.ci_tzm-Tfng-MA = Central Atlas Tamazight (Tifinagh, Morocco) -Globalization.ci_ug = Uyghur -Globalization.ci_ug-CN = Uyghur (PRC) -Globalization.ci_uk = Ukrainian -Globalization.ci_uk-UA = Ukrainian (Ukraine) -Globalization.ci_ur = Urdu -Globalization.ci_ur-IN = Urdu (India) -Globalization.ci_ur-PK = Urdu (Islamic Republic of Pakistan) -Globalization.ci_uz = Uzbek -Globalization.ci_uz-Arab = Uzbek (Perso-Arabic) -Globalization.ci_uz-Arab-AF = Uzbek (Perso-Arabic, Afghanistan) -Globalization.ci_uz-Cyrl = Uzbek (Cyrillic) -Globalization.ci_uz-Cyrl-UZ = Uzbek (Cyrillic, Uzbekistan) -Globalization.ci_uz-Latn = Uzbek (Latin) -Globalization.ci_uz-Latn-UZ = Uzbek (Latin, Uzbekistan) -Globalization.ci_vai = Vai -Globalization.ci_vai-Latn = Vai (Latin) -Globalization.ci_vai-Latn-LR = Vai (Latin, Liberia) -Globalization.ci_vai-Vaii = Vai (Vai) -Globalization.ci_vai-Vaii-LR = Vai (Vai, Liberia) -Globalization.ci_ve = Venda -Globalization.ci_ve-ZA = Venda (South Africa) -Globalization.ci_vi = Vietnamese -Globalization.ci_vi-VN = Vietnamese (Vietnam) -Globalization.ci_vo = Volapük -Globalization.ci_vo-001 = Volapük (World) -Globalization.ci_vun = Vunjo -Globalization.ci_vun-TZ = Vunjo (Tanzania) -Globalization.ci_wae = Walser -Globalization.ci_wae-CH = Walser (Switzerland) -Globalization.ci_wal = Wolaytta -Globalization.ci_wal-ET = Wolaytta (Ethiopia) -Globalization.ci_wo = Wolof -Globalization.ci_wo-SN = Wolof (Senegal) -Globalization.ci_x-IV = Invariant Language (Invariant Country) -Globalization.ci_x-IV_mathan = Invariant Language (Invariant Country) -Globalization.ci_xh = isiXhosa -Globalization.ci_xh-ZA = isiXhosa (South Africa) -Globalization.ci_xog = Soga -Globalization.ci_xog-UG = Soga (Uganda) -Globalization.ci_yav = Yangben -Globalization.ci_yav-CM = Yangben (Cameroon) -Globalization.ci_yi = Yiddish -Globalization.ci_yi-001 = Yiddish (World) -Globalization.ci_yo = Yoruba -Globalization.ci_yo-BJ = Yoruba (Benin) -Globalization.ci_yo-NG = Yoruba (Nigeria) -Globalization.ci_zgh = Standard Moroccan Tamazight -Globalization.ci_zgh-Tfng = Standard Moroccan Tamazight (Tifinagh) -Globalization.ci_zgh-Tfng-MA = Standard Moroccan Tamazight (Tifinagh, Morocco) -Globalization.ci_zh = Chinese -Globalization.ci_zh-CHS = Chinese (Simplified) Legacy -Globalization.ci_zh-CHT = Chinese (Traditional) Legacy -Globalization.ci_zh-CN = Chinese (Simplified, PRC) -Globalization.ci_zh-CN_stroke = Chinese (Simplified, PRC) -Globalization.ci_zh-Hans = Chinese (Simplified) -Globalization.ci_zh-Hant = Chinese (Traditional) -Globalization.ci_zh-HK = Chinese (Traditional, Hong Kong S.A.R.) -Globalization.ci_zh-HK_radstr = Chinese (Traditional, Hong Kong S.A.R.) -Globalization.ci_zh-MO = Chinese (Traditional, Macao S.A.R.) -Globalization.ci_zh-MO_radstr = Chinese (Traditional, Macao S.A.R.) -Globalization.ci_zh-MO_stroke = Chinese (Traditional, Macao S.A.R.) -Globalization.ci_zh-SG = Chinese (Simplified, Singapore) -Globalization.ci_zh-SG_stroke = Chinese (Simplified, Singapore) -Globalization.ci_zh-TW = Chinese (Traditional, Taiwan) -Globalization.ci_zh-TW_pronun = Chinese (Traditional, Taiwan) -Globalization.ci_zh-TW_radstr = Chinese (Traditional, Taiwan) -Globalization.ci_zu = isiZulu -Globalization.ci_zu-ZA = isiZulu (South Africa) -;------------------ -; -;Total items: 129 -; -Globalization.ri_029 = Caribbean -Globalization.ri_AE = U.A.E. -Globalization.ri_AF = Afghanistan -Globalization.ri_AL = Albania -Globalization.ri_AM = Armenia -Globalization.ri_AR = Argentina -Globalization.ri_AT = Austria -Globalization.ri_AU = Australia -Globalization.ri_AZ = Azerbaijan -Globalization.ri_BA = Bosnia and Herzegovina -Globalization.ri_BD = Bangladesh -Globalization.ri_BE = Belgium -Globalization.ri_BG = Bulgaria -Globalization.ri_BH = Bahrain -Globalization.ri_BN = Brunei Darussalam -Globalization.ri_BO = Bolivia -Globalization.ri_BR = Brazil -Globalization.ri_BY = Belarus -Globalization.ri_BZ = Belize -Globalization.ri_CA = Canada -Globalization.ri_CH = Switzerland -Globalization.ri_CL = Chile -Globalization.ri_CN = People's Republic of China -Globalization.ri_CO = Colombia -Globalization.ri_CR = Costa Rica -Globalization.ri_CS = Serbia and Montenegro (Former) -Globalization.ri_CZ = Czech Republic -Globalization.ri_DE = Germany -Globalization.ri_DK = Denmark -Globalization.ri_DO = Dominican Republic -Globalization.ri_DZ = Algeria -Globalization.ri_EC = Ecuador -Globalization.ri_EE = Estonia -Globalization.ri_EG = Egypt -Globalization.ri_ER = Eritrea -Globalization.ri_ES = Spain -Globalization.ri_ET = Ethiopia -Globalization.ri_FI = Finland -Globalization.ri_FO = Faroe Islands -Globalization.ri_FR = France -Globalization.ri_GB = United Kingdom -Globalization.ri_GE = Georgia -Globalization.ri_GL = Greenland -Globalization.ri_GR = Greece -Globalization.ri_GT = Guatemala -Globalization.ri_HK = Hong Kong S.A.R. -Globalization.ri_HN = Honduras -Globalization.ri_HR = Croatia -Globalization.ri_HU = Hungary -Globalization.ri_ID = Indonesia -Globalization.ri_IE = Ireland -Globalization.ri_IL = Israel -Globalization.ri_IN = India -Globalization.ri_IQ = Iraq -Globalization.ri_IR = Iran -Globalization.ri_IS = Iceland -Globalization.ri_IT = Italy -Globalization.ri_IV = Invariant Country -Globalization.ri_JM = Jamaica -Globalization.ri_JO = Jordan -Globalization.ri_JP = Japan -Globalization.ri_KE = Kenya -Globalization.ri_KG = Kyrgyzstan -Globalization.ri_KH = Cambodia -Globalization.ri_KR = Korea -Globalization.ri_KW = Kuwait -Globalization.ri_KZ = Kazakhstan -Globalization.ri_LA = Lao P.D.R. -Globalization.ri_LB = Lebanon -Globalization.ri_LI = Liechtenstein -Globalization.ri_LK = Sri Lanka -Globalization.ri_LT = Lithuania -Globalization.ri_LU = Luxembourg -Globalization.ri_LV = Latvia -Globalization.ri_LY = Libya -Globalization.ri_MA = Morocco -Globalization.ri_MC = Principality of Monaco -Globalization.ri_ME = Montenegro -Globalization.ri_MK = Macedonia (FYROM) -Globalization.ri_MN = Mongolia -Globalization.ri_MO = Macao S.A.R. -Globalization.ri_MT = Malta -Globalization.ri_MV = Maldives -Globalization.ri_MX = Mexico -Globalization.ri_MY = Malaysia -Globalization.ri_NG = Nigeria -Globalization.ri_NI = Nicaragua -Globalization.ri_NL = Netherlands -Globalization.ri_NO = Norway -Globalization.ri_NP = Nepal -Globalization.ri_NZ = New Zealand -Globalization.ri_OM = Oman -Globalization.ri_PA = Panama -Globalization.ri_PE = Peru -Globalization.ri_PH = Philippines -Globalization.ri_PK = Islamic Republic of Pakistan -Globalization.ri_PL = Poland -Globalization.ri_PR = Puerto Rico -Globalization.ri_PT = Portugal -Globalization.ri_PY = Paraguay -Globalization.ri_QA = Qatar -Globalization.ri_RO = Romania -Globalization.ri_RS = Serbia -Globalization.ri_RU = Russia -Globalization.ri_RW = Rwanda -Globalization.ri_SA = Saudi Arabia -Globalization.ri_SE = Sweden -Globalization.ri_SG = Singapore -Globalization.ri_SI = Slovenia -Globalization.ri_SK = Slovakia -Globalization.ri_SN = Senegal -Globalization.ri_SV = El Salvador -Globalization.ri_SY = Syria -Globalization.ri_TH = Thailand -Globalization.ri_TJ = Tajikistan -Globalization.ri_TM = Turkmenistan -Globalization.ri_TN = Tunisia -Globalization.ri_TR = Turkey -Globalization.ri_TT = Trinidad and Tobago -Globalization.ri_TW = Taiwan -Globalization.ri_UA = Ukraine -Globalization.ri_US = United States -Globalization.ri_UY = Uruguay -Globalization.ri_UZ = Uzbekistan -Globalization.ri_VE = Bolivarian Republic of Venezuela -Globalization.ri_VN = Vietnam -Globalization.ri_YE = Yemen -Globalization.ri_ZA = South Africa -Globalization.ri_ZW = Zimbabwe -#endif //!FEATURE_CORECLR - -;------------------ -; Encoding names: -; -;Total items: 147 -; -Globalization.cp_1200 = Unicode -Globalization.cp_1201 = Unicode (Big-Endian) -Globalization.cp_65001 = Unicode (UTF-8) -Globalization.cp_65000 = Unicode (UTF-7) -Globalization.cp_12000 = Unicode (UTF-32) -Globalization.cp_12001 = Unicode (UTF-32 Big-Endian) -Globalization.cp_20127 = US-ASCII -Globalization.cp_28591 = Western European (ISO) - -#if FEATURE_NON_UNICODE_CODE_PAGES -Globalization.cp_37 = IBM EBCDIC (US-Canada) -Globalization.cp_437 = OEM United States -Globalization.cp_500 = IBM EBCDIC (International) -Globalization.cp_708 = Arabic (ASMO 708) -Globalization.cp_720 = Arabic (DOS) -Globalization.cp_737 = Greek (DOS) -Globalization.cp_775 = Baltic (DOS) -Globalization.cp_850 = Western European (DOS) -Globalization.cp_852 = Central European (DOS) -Globalization.cp_855 = OEM Cyrillic -Globalization.cp_857 = Turkish (DOS) -Globalization.cp_858 = OEM Multilingual Latin I -Globalization.cp_860 = Portuguese (DOS) -Globalization.cp_861 = Icelandic (DOS) -Globalization.cp_862 = Hebrew (DOS) -Globalization.cp_863 = French Canadian (DOS) -Globalization.cp_864 = Arabic (864) -Globalization.cp_865 = Nordic (DOS) -Globalization.cp_866 = Cyrillic (DOS) -Globalization.cp_869 = Greek, Modern (DOS) -Globalization.cp_870 = IBM EBCDIC (Multilingual Latin-2) -Globalization.cp_874 = Thai (Windows) -Globalization.cp_875 = IBM EBCDIC (Greek Modern) -Globalization.cp_932 = Japanese (Shift-JIS) -Globalization.cp_936 = Chinese Simplified (GB2312) -Globalization.cp_949 = Korean -Globalization.cp_950 = Chinese Traditional (Big5) -Globalization.cp_1026 = IBM EBCDIC (Turkish Latin-5) -Globalization.cp_1047 = IBM Latin-1 -Globalization.cp_1140 = IBM EBCDIC (US-Canada-Euro) -Globalization.cp_1141 = IBM EBCDIC (Germany-Euro) -Globalization.cp_1142 = IBM EBCDIC (Denmark-Norway-Euro) -Globalization.cp_1143 = IBM EBCDIC (Finland-Sweden-Euro) -Globalization.cp_1144 = IBM EBCDIC (Italy-Euro) -Globalization.cp_1145 = IBM EBCDIC (Spain-Euro) -Globalization.cp_1146 = IBM EBCDIC (UK-Euro) -Globalization.cp_1147 = IBM EBCDIC (France-Euro) -Globalization.cp_1148 = IBM EBCDIC (International-Euro) -Globalization.cp_1149 = IBM EBCDIC (Icelandic-Euro) -Globalization.cp_1250 = Central European (Windows) -Globalization.cp_1251 = Cyrillic (Windows) -Globalization.cp_1252 = Western European (Windows) -Globalization.cp_1253 = Greek (Windows) -Globalization.cp_1254 = Turkish (Windows) -Globalization.cp_1255 = Hebrew (Windows) -Globalization.cp_1256 = Arabic (Windows) -Globalization.cp_1257 = Baltic (Windows) -Globalization.cp_1258 = Vietnamese (Windows) -Globalization.cp_1361 = Korean (Johab) -Globalization.cp_10000 = Western European (Mac) -Globalization.cp_10001 = Japanese (Mac) -Globalization.cp_10002 = Chinese Traditional (Mac) -Globalization.cp_10003 = Korean (Mac) -Globalization.cp_10004 = Arabic (Mac) -Globalization.cp_10005 = Hebrew (Mac) -Globalization.cp_10006 = Greek (Mac) -Globalization.cp_10007 = Cyrillic (Mac) -Globalization.cp_10008 = Chinese Simplified (Mac) -Globalization.cp_10010 = Romanian (Mac) -Globalization.cp_10017 = Ukrainian (Mac) -Globalization.cp_10021 = Thai (Mac) -Globalization.cp_10029 = Central European (Mac) -Globalization.cp_10079 = Icelandic (Mac) -Globalization.cp_10081 = Turkish (Mac) -Globalization.cp_10082 = Croatian (Mac) -Globalization.cp_20000 = Chinese Traditional (CNS) -Globalization.cp_20001 = TCA Taiwan -Globalization.cp_20002 = Chinese Traditional (Eten) -Globalization.cp_20003 = IBM5550 Taiwan -Globalization.cp_20004 = TeleText Taiwan -Globalization.cp_20005 = Wang Taiwan -Globalization.cp_20105 = Western European (IA5) -Globalization.cp_20106 = German (IA5) -Globalization.cp_20107 = Swedish (IA5) -Globalization.cp_20108 = Norwegian (IA5) -Globalization.cp_20261 = T.61 -Globalization.cp_20269 = ISO-6937 -Globalization.cp_20273 = IBM EBCDIC (Germany) -Globalization.cp_20277 = IBM EBCDIC (Denmark-Norway) -Globalization.cp_20278 = IBM EBCDIC (Finland-Sweden) -Globalization.cp_20280 = IBM EBCDIC (Italy) -Globalization.cp_20284 = IBM EBCDIC (Spain) -Globalization.cp_20285 = IBM EBCDIC (UK) -Globalization.cp_20290 = IBM EBCDIC (Japanese katakana) -Globalization.cp_20297 = IBM EBCDIC (France) -Globalization.cp_20420 = IBM EBCDIC (Arabic) -Globalization.cp_20423 = IBM EBCDIC (Greek) -Globalization.cp_20424 = IBM EBCDIC (Hebrew) -Globalization.cp_20833 = IBM EBCDIC (Korean Extended) -Globalization.cp_20838 = IBM EBCDIC (Thai) -Globalization.cp_20866 = Cyrillic (KOI8-R) -Globalization.cp_20871 = IBM EBCDIC (Icelandic) -Globalization.cp_20880 = IBM EBCDIC (Cyrillic Russian) -Globalization.cp_20905 = IBM EBCDIC (Turkish) -Globalization.cp_20924 = IBM Latin-1 -Globalization.cp_20932 = Japanese (JIS 0208-1990 and 0212-1990) -Globalization.cp_20936 = Chinese Simplified (GB2312-80) -Globalization.cp_20949 = Korean Wansung -Globalization.cp_21025 = IBM EBCDIC (Cyrillic Serbian-Bulgarian) -Globalization.cp_21027 = Ext Alpha Lowercase -Globalization.cp_21866 = Cyrillic (KOI8-U) -Globalization.cp_28592 = Central European (ISO) -Globalization.cp_28593 = Latin 3 (ISO) -Globalization.cp_28594 = Baltic (ISO) -Globalization.cp_28595 = Cyrillic (ISO) -Globalization.cp_28596 = Arabic (ISO) -Globalization.cp_28597 = Greek (ISO) -Globalization.cp_28598 = Hebrew (ISO-Visual) -Globalization.cp_28599 = Turkish (ISO) -Globalization.cp_28603 = Estonian (ISO) -Globalization.cp_28605 = Latin 9 (ISO) -Globalization.cp_29001 = Europa -Globalization.cp_38598 = Hebrew (ISO-Logical) -Globalization.cp_50000 = User Defined -Globalization.cp_50220 = Japanese (JIS) -Globalization.cp_50221 = Japanese (JIS-Allow 1 byte Kana) -Globalization.cp_50222 = Japanese (JIS-Allow 1 byte Kana - SO/SI) -Globalization.cp_50225 = Korean (ISO) -Globalization.cp_50227 = Chinese Simplified (ISO-2022) -Globalization.cp_50229 = Chinese Traditional (ISO-2022) -Globalization.cp_50930 = IBM EBCDIC (Japanese and Japanese Katakana) -Globalization.cp_50931 = IBM EBCDIC (Japanese and US-Canada) -Globalization.cp_50933 = IBM EBCDIC (Korean and Korean Extended) -Globalization.cp_50935 = IBM EBCDIC (Simplified Chinese) -Globalization.cp_50937 = IBM EBCDIC (Traditional Chinese) -Globalization.cp_50939 = IBM EBCDIC (Japanese and Japanese-Latin) -Globalization.cp_51932 = Japanese (EUC) -Globalization.cp_51936 = Chinese Simplified (EUC) -Globalization.cp_51949 = Korean (EUC) -Globalization.cp_52936 = Chinese Simplified (HZ) -Globalization.cp_54936 = Chinese Simplified (GB18030) -Globalization.cp_57002 = ISCII Devanagari -Globalization.cp_57003 = ISCII Bengali -Globalization.cp_57004 = ISCII Tamil -Globalization.cp_57005 = ISCII Telugu -Globalization.cp_57006 = ISCII Assamese -Globalization.cp_57007 = ISCII Oriya -Globalization.cp_57008 = ISCII Kannada -Globalization.cp_57009 = ISCII Malayalam -Globalization.cp_57010 = ISCII Gujarati -Globalization.cp_57011 = ISCII Punjabi -#endif // FEATURE_NON_UNICODE_CODE_PAGES -#endif // INCLUDE_DEBUG - -;------------------ - diff --git a/src/nativeresources/resourcestring.cpp b/src/nativeresources/resourcestring.cpp index 13d5aee..236a2a3 100644 --- a/src/nativeresources/resourcestring.cpp +++ b/src/nativeresources/resourcestring.cpp @@ -42,11 +42,11 @@ int LoadNativeStringResource(const NativeStringResourceTable &nativeStringResour else { // The resource ID wasn't found in our array. Fall back on returning the ID as a string. - len = _snwprintf(szBuffer, iMax - 1, W("[Undefined resource string ID:0x%X]"), iResourceID); - if ((len < 0) || (len == (iMax - 1))) - { - // Add string terminator if the result of _snwprintf didn't fit the buffer. - szBuffer[iMax - 1] = W('\0'); + len = _snwprintf_s(szBuffer, iMax, _TRUNCATE, W("[Undefined resource string ID:0x%X]"), iResourceID); + if (len < 0) + { + // The only possible failure is that that string didn't fit the buffer. So the buffer contains + // partial string terminated by '\0' len = iMax - 1; } } diff --git a/src/pal/inc/mbusafecrt.h b/src/pal/inc/mbusafecrt.h index c25676c..8cf050f 100644 --- a/src/pal/inc/mbusafecrt.h +++ b/src/pal/inc/mbusafecrt.h @@ -31,16 +31,6 @@ typedef int errno_t; // define the return value for success #define SAFECRT_SUCCESS 0 -/* - * Sizes for buffers used by the _makepath() and _splitpath() functions. - * note that the sizes include space for 0-terminator - */ -//#define _MAX_PATH 260 /* max. length of full pathname */ -//#define _MAX_DRIVE 3 /* max. length of drive component */ -//#define _MAX_DIR 256 /* max. length of path component */ -//#define _MAX_FNAME 256 /* max. length of file name component */ -//#define _MAX_EXT 256 /* max. length of extension component */ - #ifdef __cplusplus extern "C" { #endif @@ -65,7 +55,7 @@ extern WCHAR* wcstok_s( WCHAR* inString, const WCHAR* inControl, WCHAR** ioConte // strnlen is not required unless the source string is completely untrusted (e.g. anonymous input on a website) #ifndef SUPPRESS_STRNLEN - extern size_t strnlen( const char* inString, size_t inMaxSize ); + extern size_t PAL_strnlen( const char* inString, size_t inMaxSize ); extern size_t wcsnlen( const WCHAR* inString, size_t inMaxSize ); #endif @@ -96,10 +86,10 @@ extern int swprintf_s( WCHAR *string, size_t sizeInWords, const WCHAR *format, . extern int _snprintf_s( char *string, size_t sizeInBytes, size_t count, const char *format, ... ); extern int _snwprintf_s( WCHAR *string, size_t sizeInWords, size_t count, const WCHAR *format, ... ); -extern int _vsprintf_s( char* string, size_t sizeInBytes, const char* format, va_list arglist ); +extern int vsprintf_s( char* string, size_t sizeInBytes, const char* format, va_list arglist ); extern int _vsnprintf_s( char* string, size_t sizeInBytes, size_t count, const char* format, va_list arglist ); -extern int _vswprintf_s( WCHAR* string, size_t sizeInWords, const WCHAR* format, va_list arglist ); +extern int vswprintf_s( WCHAR* string, size_t sizeInWords, const WCHAR* format, va_list arglist ); extern int _vsnwprintf_s( WCHAR* string, size_t sizeInWords, size_t count, const WCHAR* format, va_list arglist ); extern int sscanf_s( const char *string, const char *format, ... ); diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h index 2605282..0d7c89e 100644 --- a/src/pal/inc/pal.h +++ b/src/pal/inc/pal.h @@ -331,7 +331,7 @@ typedef char * va_list; PALIMPORT BOOL PALAPI -PAL_IsDebuggerPresent(); +PAL_IsDebuggerPresent(VOID); #define MAXIMUM_SUSPEND_COUNT MAXCHAR @@ -507,7 +507,7 @@ PAL_Initialize( PALIMPORT int PALAPI -PAL_InitializeDLL(); +PAL_InitializeDLL(VOID); PALIMPORT DWORD @@ -581,7 +581,7 @@ PAL_UnregisterForRuntimeStartup( PALIMPORT BOOL PALAPI -PAL_NotifyRuntimeStarted(); +PAL_NotifyRuntimeStarted(VOID); static const int MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH = 64; @@ -648,6 +648,13 @@ PAL_DeleteExecWatchpoint( #endif +PALIMPORT +BOOL +PALAPI +PAL_ProbeMemory( + PVOID pBuffer, + DWORD cbBuffer, + BOOL fWriteAccess); /******************* winuser.h Entrypoints *******************************/ @@ -671,28 +678,6 @@ CharNextExA( #endif -PALIMPORT -int -PALAPIV -wsprintfA( - OUT LPSTR, - IN LPCSTR, - ...); - -PALIMPORT -int -PALAPIV -wsprintfW( - OUT LPWSTR, - IN LPCWSTR, - ...); - -#ifdef UNICODE -#define wsprintf wsprintfW -#else -#define wsprintf wsprintfA -#endif - #define MB_OK 0x00000000L #define MB_OKCANCEL 0x00000001L #define MB_ABORTRETRYIGNORE 0x00000002L @@ -1853,6 +1838,13 @@ QueueUserAPC( #define MAXIMUM_SUPPORTED_EXTENSION 512 +#define CONTEXT_XSTATE (CONTEXT_i386 | 0x40L) + +#define CONTEXT_EXCEPTION_ACTIVE 0x8000000L +#define CONTEXT_SERVICE_ACTIVE 0x10000000L +#define CONTEXT_EXCEPTION_REQUEST 0x40000000L +#define CONTEXT_EXCEPTION_REPORTING 0x80000000L + typedef struct _FLOATING_SAVE_AREA { DWORD ControlWord; DWORD StatusWord; @@ -1911,6 +1903,16 @@ typedef struct _CONTEXT { // support any other values in the ExtendedRegisters) but we might as well be as accurate as we can. #define CONTEXT_EXREG_XMM_OFFSET 160 +typedef struct _KNONVOLATILE_CONTEXT_POINTERS { + + // TODO WIP x86/Linux, need to fix this. + PDWORD Ebx; + PDWORD Esi; + PDWORD Edi; + PDWORD Ebp; + +} KNONVOLATILE_CONTEXT_POINTERS, *PKNONVOLATILE_CONTEXT_POINTERS; + #elif defined(_PPC_) // @@ -3256,22 +3258,22 @@ TlsFree( PALIMPORT void * PALAPI -PAL_GetStackBase(); +PAL_GetStackBase(VOID); PALIMPORT void * PALAPI -PAL_GetStackLimit(); +PAL_GetStackLimit(VOID); PALIMPORT DWORD PALAPI -PAL_GetLogicalCpuCountFromOS(); +PAL_GetLogicalCpuCountFromOS(VOID); PALIMPORT size_t PALAPI -PAL_GetLogicalProcessorCacheSizeFromOS(); +PAL_GetLogicalProcessorCacheSizeFromOS(VOID); typedef BOOL (*ReadMemoryWordCallback)(SIZE_T address, SIZE_T *value); @@ -3304,6 +3306,8 @@ PALIMPORT BOOL PALAPI PAL_VirtualUnwindOutOfProc(CONTEXT *context, #define PAL_CS_NATIVE_DATA_SIZE 80 #elif defined(__linux__) && defined(_ARM64_) #define PAL_CS_NATIVE_DATA_SIZE 116 +#elif defined(__linux__) && defined(__i386__) +#define PAL_CS_NATIVE_DATA_SIZE 76 #elif defined(__linux__) && defined(__x86_64__) #define PAL_CS_NATIVE_DATA_SIZE 96 #elif defined(__NetBSD__) && defined(__amd64__) @@ -3656,16 +3660,6 @@ VirtualQuery( IN SIZE_T dwLength); PALIMPORT -BOOL -PALAPI -ReadProcessMemory( - IN HANDLE hProcess, - IN LPCVOID lpBaseAddress, - OUT LPVOID lpBuffer, - IN SIZE_T nSize, - OUT SIZE_T * lpNumberOfBytesRead); - -PALIMPORT VOID PALAPI RtlMoveMemory( @@ -4712,19 +4706,12 @@ enum { // typedef struct _RUNTIME_FUNCTION { DWORD BeginAddress; +#ifdef _AMD64_ DWORD EndAddress; +#endif DWORD UnwindData; } RUNTIME_FUNCTION, *PRUNTIME_FUNCTION; -PALIMPORT -BOOL -PALAPI -WriteProcessMemory(IN HANDLE hProcess, - IN LPVOID lpBaseAddress, - IN LPCVOID lpBuffer, - IN SIZE_T nSize, - OUT SIZE_T * lpNumberOfBytesWritten); - #define STANDARD_RIGHTS_REQUIRED (0x000F0000L) #define SYNCHRONIZE (0x00100000L) #define READ_CONTROL (0x00020000L) @@ -4801,28 +4788,6 @@ DebugBreak( VOID); PALIMPORT -LPWSTR -PALAPI -lstrcatW( - IN OUT LPWSTR lpString1, - IN LPCWSTR lpString2); - -#ifdef UNICODE -#define lstrcat lstrcatW -#endif - -PALIMPORT -LPWSTR -PALAPI -lstrcpyW( - OUT LPWSTR lpString1, - IN LPCWSTR lpString2); - -#ifdef UNICODE -#define lstrcpy lstrcpyW -#endif - -PALIMPORT int PALAPI lstrlenA( @@ -4841,19 +4806,6 @@ lstrlenW( #endif PALIMPORT -LPWSTR -PALAPI -lstrcpynW( - OUT LPWSTR lpString1, - IN LPCWSTR lpString2, - IN int iMaxLength); - -#ifdef UNICODE -#define lstrcpyn lstrcpynW -#endif - - -PALIMPORT DWORD PALAPI GetEnvironmentVariableW( @@ -4937,7 +4889,7 @@ GetTickCount( PALIMPORT ULONGLONG PALAPI -GetTickCount64(); +GetTickCount64(VOID); PALIMPORT BOOL @@ -5377,7 +5329,7 @@ YieldProcessor( PALIMPORT DWORD PALAPI -GetCurrentProcessorNumber(); +GetCurrentProcessorNumber(VOID); /*++ Function: @@ -5389,7 +5341,7 @@ Checks if GetCurrentProcessorNumber is available in the current environment PALIMPORT BOOL PALAPI -PAL_HasGetCurrentProcessorNumber(); +PAL_HasGetCurrentProcessorNumber(VOID); #define FORMAT_MESSAGE_ALLOCATE_BUFFER 0x00000100 #define FORMAT_MESSAGE_IGNORE_INSERTS 0x00000200 @@ -5475,7 +5427,7 @@ ResetWriteWatch( PALIMPORT VOID PALAPI -FlushProcessWriteBuffers(); +FlushProcessWriteBuffers(VOID); typedef void (*PAL_ActivationFunction)(CONTEXT *context); typedef BOOL (*PAL_SafeActivationCheckFunction)(SIZE_T ip, BOOL checkingCurrentThread); @@ -5715,9 +5667,7 @@ CoCreateGuid(OUT GUID * pguid); #define printf PAL_printf #define vprintf PAL_vprintf #define wprintf PAL_wprintf -#define sprintf PAL_sprintf #define swprintf PAL_swprintf -#define sscanf PAL_sscanf #define wcsspn PAL_wcsspn #define wcstod PAL_wcstod #define wcstol PAL_wcstol @@ -5791,6 +5741,13 @@ CoCreateGuid(OUT GUID * pguid); #define log PAL_log #define log10 PAL_log10 #define pow PAL_pow +#define acosf PAL_acosf +#define asinf PAL_asinf +#define atan2f PAL_atan2f +#define expf PAL_expf +#define logf PAL_logf +#define log10f PAL_log10f +#define powf PAL_powf #define malloc PAL_malloc #define free PAL_free #define mkstemp PAL_mkstemp @@ -5802,6 +5759,7 @@ CoCreateGuid(OUT GUID * pguid); #define _wcstoui64 PAL__wcstoui64 #define _flushall PAL__flushall #define _vsnprintf PAL__vsnprintf +#define strnlen PAL_strnlen #ifdef _AMD64_ #define _mm_getcsr PAL__mm_getcsr @@ -5878,9 +5836,7 @@ PALIMPORT char * __cdecl strstr(const char *, const char *); PALIMPORT char * __cdecl strtok(char *, const char *); PALIMPORT size_t __cdecl strspn(const char *, const char *); PALIMPORT size_t __cdecl strcspn(const char *, const char *); -PALIMPORT int __cdecl sprintf(char *, const char *, ...); PALIMPORT int __cdecl vsprintf(char *, const char *, va_list); -PALIMPORT int __cdecl sscanf(const char *, const char *, ...); PALIMPORT int __cdecl atoi(const char *); PALIMPORT LONG __cdecl atol(const char *); PALIMPORT ULONG __cdecl strtoul(const char *, char **, int); @@ -5899,23 +5855,35 @@ PALIMPORT int __cdecl toupper(int); #endif // PAL_STDCPP_COMPAT +/* _TRUNCATE */ +#if !defined(_TRUNCATE) +#define _TRUNCATE ((size_t)-1) +#endif + PALIMPORT errno_t __cdecl memcpy_s(void *, size_t, const void *, size_t); PALIMPORT errno_t __cdecl memmove_s(void *, size_t, const void *, size_t); PALIMPORT char * __cdecl _strlwr(char *); PALIMPORT int __cdecl _stricmp(const char *, const char *); -PALIMPORT int __cdecl _snprintf(char *, size_t, const char *, ...); +PALIMPORT int __cdecl vsprintf_s(char *, size_t, const char *, va_list); PALIMPORT char * __cdecl _gcvt_s(char *, int, double, int); PALIMPORT char * __cdecl _ecvt(double, int, int *, int *); PALIMPORT int __cdecl __iscsym(int); -PALIMPORT size_t __cdecl _mbslen(const unsigned char *); PALIMPORT unsigned char * __cdecl _mbsinc(const unsigned char *); PALIMPORT unsigned char * __cdecl _mbsninc(const unsigned char *, size_t); PALIMPORT unsigned char * __cdecl _mbsdec(const unsigned char *, const unsigned char *); PALIMPORT int __cdecl _wcsicmp(const WCHAR *, const WCHAR*); PALIMPORT int __cdecl _wcsnicmp(const WCHAR *, const WCHAR *, size_t); PALIMPORT int __cdecl _vsnprintf(char *, size_t, const char *, va_list); -PALIMPORT int __cdecl _vsnwprintf(WCHAR *, size_t, const WCHAR *, va_list); -PALIMPORT WCHAR * __cdecl _itow(int, WCHAR *, int); +PALIMPORT int __cdecl _vsnprintf_s(char *, size_t, size_t, const char *, va_list); +PALIMPORT int __cdecl _vsnwprintf_s(WCHAR *, size_t, size_t, const WCHAR *, va_list); +PALIMPORT int __cdecl _snwprintf_s(WCHAR *, size_t, size_t, const WCHAR *, ...); +PALIMPORT int __cdecl _snprintf_s(char *, size_t, size_t, const char *, ...); +PALIMPORT int __cdecl sprintf_s(char *, size_t, const char *, ... ); +PALIMPORT int __cdecl swprintf_s(WCHAR *, size_t, const WCHAR *, ... ); +PALIMPORT int __cdecl _snwprintf_s(WCHAR *, size_t, size_t, const WCHAR *, ...); +PALIMPORT int __cdecl vswprintf_s( WCHAR *, size_t, const WCHAR *, va_list); +PALIMPORT int __cdecl sscanf_s(const char *, const char *, ...); +PALIMPORT errno_t __cdecl _itow_s(int, WCHAR *, size_t, int); PALIMPORT size_t __cdecl PAL_wcslen(const WCHAR *); PALIMPORT int __cdecl PAL_wcscmp(const WCHAR*, const WCHAR*); @@ -5933,7 +5901,6 @@ PALIMPORT 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__vsnprintf(LPSTR Buffer, size_t Count, LPCSTR Format, va_list ap); -PALIMPORT int __cdecl _snwprintf(WCHAR *, size_t, const WCHAR *, ...); PALIMPORT int __cdecl PAL_swscanf(const WCHAR *, const WCHAR *, ...); PALIMPORT LONG __cdecl PAL_wcstol(const WCHAR *, WCHAR **, int); PALIMPORT ULONG __cdecl PAL_wcstoul(const WCHAR *, WCHAR **, int); @@ -5950,8 +5917,7 @@ PALIMPORT WCHAR __cdecl PAL_towupper(WCHAR); PALIMPORT WCHAR * __cdecl _wcslwr(WCHAR *); PALIMPORT ULONGLONG _wcstoui64(const WCHAR *, WCHAR **, int); -PALIMPORT WCHAR * __cdecl _i64tow(__int64, WCHAR *, int); -PALIMPORT WCHAR * __cdecl _ui64tow(unsigned __int64, WCHAR *, int); +PALIMPORT errno_t __cdecl _i64tow_s(long long, WCHAR *, size_t, int); PALIMPORT int __cdecl _wtoi(const WCHAR *); #ifdef __cplusplus @@ -6039,9 +6005,29 @@ PALIMPORT double __cdecl sqrt(double); PALIMPORT double __cdecl tan(double); PALIMPORT double __cdecl tanh(double); +PALIMPORT int __cdecl _finitef(float); +PALIMPORT int __cdecl _isnanf(float); +PALIMPORT float __cdecl _copysignf(float, float); +PALIMPORT float __cdecl acosf(float); +PALIMPORT float __cdecl asinf(float); +PALIMPORT float __cdecl atanf(float); +PALIMPORT float __cdecl atan2f(float, float); +PALIMPORT float __cdecl ceilf(float); +PALIMPORT float __cdecl cosf(float); +PALIMPORT float __cdecl coshf(float); +PALIMPORT float __cdecl expf(float); PALIMPORT float __cdecl fabsf(float); +PALIMPORT float __cdecl floorf(float); PALIMPORT float __cdecl fmodf(float, float); +PALIMPORT float __cdecl logf(float); +PALIMPORT float __cdecl log10f(float); PALIMPORT float __cdecl modff(float, float*); +PALIMPORT float __cdecl powf(float, float); +PALIMPORT float __cdecl sinf(float); +PALIMPORT float __cdecl sinhf(float); +PALIMPORT float __cdecl sqrtf(float); +PALIMPORT float __cdecl tanf(float); +PALIMPORT float __cdecl tanhf(float); #ifndef PAL_STDCPP_COMPAT @@ -6086,14 +6072,8 @@ PALIMPORT void __cdecl qsort(void *, size_t, size_t, int (__cdecl *)(const void PALIMPORT void * __cdecl bsearch(const void *, const void *, size_t, size_t, int (__cdecl *)(const void *, const void *)); -PALIMPORT void __cdecl _splitpath(const char *, char *, char *, char *, char *); -PALIMPORT void __cdecl _wsplitpath(const WCHAR *, WCHAR *, WCHAR *, WCHAR *, WCHAR *); -PALIMPORT void __cdecl _makepath(char *, const char *, const char *, const char *, const char *); -PALIMPORT void __cdecl _wmakepath(WCHAR *, const WCHAR *, const WCHAR *, const WCHAR *, const WCHAR *); PALIMPORT char * __cdecl _fullpath(char *, const char *, size_t); -PALIMPORT void __cdecl _swab(char *, char *, int); - #ifndef PAL_STDCPP_COMPAT PALIMPORT time_t __cdecl time(time_t *); @@ -6307,14 +6287,14 @@ PAL_Enter(PAL_Boundary boundary); PALIMPORT BOOL PALAPI -PAL_HasEntered(); +PAL_HasEntered(VOID); // Equivalent to PAL_Enter(PAL_BoundaryTop) and is for stub // code generation use. PALIMPORT DWORD PALAPI -PAL_EnterTop(); +PAL_EnterTop(VOID); // This function needs to be called on a thread when it enters // a region of code that depends on this instance of the PAL @@ -6349,14 +6329,14 @@ PAL_Leave(PAL_Boundary boundary); PALIMPORT VOID PALAPI -PAL_LeaveBottom(); +PAL_LeaveBottom(VOID); // This function is equivalent to PAL_Leave(PAL_BoundaryTop) // and is available to limit the creation of stub code. PALIMPORT VOID PALAPI -PAL_LeaveTop(); +PAL_LeaveTop(VOID); #ifdef __cplusplus // diff --git a/src/pal/inc/pal_char16.h b/src/pal/inc/pal_char16.h index b118e98..4600cc7 100644 --- a/src/pal/inc/pal_char16.h +++ b/src/pal/inc/pal_char16.h @@ -37,7 +37,8 @@ This file is used to define the wchar_t type as a 16-bit type on Unix. // Set up the wchar_t type (which got preprocessed to __wchar_16_cpp__). // In C++11, the standard gives us char16_t, which is what we want (and matches types with u"") // In C, this doesn't exist, so use unsigned short. - +// **** WARNING: Linking C and C++ objects will break with -fstrict-aliasing with GCC/Clang +// due to conditional typedef #if !defined(_WCHAR_T_DEFINED) || !defined(_MSC_VER) #if defined (PLATFORM_UNIX) #if defined(__cplusplus) diff --git a/src/pal/inc/pal_mstypes.h b/src/pal/inc/pal_mstypes.h index df17767..b9c3ac2 100644 --- a/src/pal/inc/pal_mstypes.h +++ b/src/pal/inc/pal_mstypes.h @@ -56,12 +56,6 @@ extern "C" { #define CDECL __cdecl #endif -#ifndef PAL_STDCPP_COMPAT -#undef __fastcall -#define __fastcall __stdcall -#undef _fastcall -#define _fastcall __fastcall -#endif // PAL_STDCPP_COMPAT #else // !defined(__i386__) @@ -215,6 +209,9 @@ extern "C" { // Defined in gnu's types.h. For non PAL_IMPLEMENTATION system // includes are not included, so we need to define them. #ifndef PAL_IMPLEMENTATION + +// OS X already defines these types in 64 bit +#if !defined(_TARGET_MAC64) typedef __int64 int64_t; typedef unsigned __int64 uint64_t; typedef __int32 int32_t; @@ -223,6 +220,8 @@ typedef __int16 int16_t; typedef unsigned __int16 uint16_t; typedef __int8 int8_t; typedef unsigned __int8 uint8_t; +#endif + #endif // PAL_IMPLEMENTATION #ifndef _MSC_VER diff --git a/src/pal/inc/rt/palrt.h b/src/pal/inc/rt/palrt.h index 336a13f..c181f38 100644 --- a/src/pal/inc/rt/palrt.h +++ b/src/pal/inc/rt/palrt.h @@ -834,7 +834,6 @@ enum tagMIMECONTF { // note: diff in NULL handing and calling convetion #define StrCpyW PAL_wcscpy -#define StrCpyNW lstrcpynW // note: can't be wcsncpy! #define StrCatW PAL_wcscat #define StrChrW (WCHAR*)PAL_wcschr #define StrCmpW PAL_wcscmp @@ -850,12 +849,9 @@ STDAPI_(LPWSTR) StrCatBuffW(LPWSTR pszDest, LPCWSTR pszSrc, int cchDestBuffSize) #define lstrcmpW PAL_wcscmp #define lstrcmpiW _wcsicmp -#define wnsprintfW _snwprintf // note: not 100% compatible (wsprintf should be subset of sprintf...) -#define wvnsprintfW _vsnwprintf // note: not 100% compatible (wsprintf should be subset of sprintf...) #ifdef UNICODE #define StrCpy StrCpyW -#define StrCpyN StrCpyNW #define StrCat StrCatW #define StrNCat StrNCatW #define StrChr StrChrW @@ -871,7 +867,6 @@ STDAPI_(LPWSTR) StrCatBuffW(LPWSTR pszDest, LPCWSTR pszSrc, int cchDestBuffSize) #define lstrcmp lstrcmpW #define lstrcmpi lstrcmpiW -#define wnsprintf wnsprintfW #endif @@ -898,12 +893,8 @@ Remember to fix the errcode defintion in safecrt.h. */ #define _wcslwr_s _wcslwr_unsafe -#define _snwprintf_s _snwprintf_unsafe -#define _vsnwprintf_s _vsnwprintf_unsafe #define _snprintf_s _snprintf_unsafe -#define _vsnprintf_s _vsnprintf_unsafe #define swscanf_s swscanf -#define sscanf_s sscanf #define _wfopen_s _wfopen_unsafe #define fopen_s _fopen_unsafe @@ -911,12 +902,8 @@ Remember to fix the errcode defintion in safecrt.h. #define _strlwr_s _strlwr_unsafe #define _vscprintf _vscprintf_unsafe -#define _vscwprintf _vscwprintf_unsafe -#define sprintf_s _snprintf -#define swprintf_s _snwprintf #define vsprintf_s _vsnprintf -#define vswprintf_s _vsnwprintf extern "C++" { @@ -982,51 +969,6 @@ inline int __cdecl _vscprintf_unsafe(const char *_Format, va_list _ArgList) } } -inline int __cdecl _vscwprintf_unsafe(const WCHAR *_Format, va_list _ArgList) -{ - int guess = 256; - - for (;;) - { - WCHAR *buf = (WCHAR *)malloc(guess * sizeof(WCHAR)); - if (buf == nullptr) - return 0; - - va_list apcopy; - va_copy(apcopy, _ArgList); - int ret = _vsnwprintf(buf, guess, _Format, apcopy); - free(buf); - va_end(apcopy); - - if ((ret != -1) && (ret < guess)) - return ret; - - guess *= 2; - } -} - -inline int __cdecl _vsnwprintf_unsafe(WCHAR *_Dst, size_t _SizeInWords, size_t _Count, const WCHAR *_Format, va_list _ArgList) -{ - if (_Count == _TRUNCATE) _Count = _SizeInWords - 1; - int ret = _vsnwprintf(_Dst, _Count, _Format, _ArgList); - _Dst[_SizeInWords - 1] = L'\0'; - if (ret < 0 && errno == 0) - { - errno = ERANGE; - } - return ret; -} - -inline int __cdecl _snwprintf_unsafe(WCHAR *_Dst, size_t _SizeInWords, size_t _Count, const WCHAR *_Format, ...) -{ - int ret; - va_list _ArgList; - va_start(_ArgList, _Format); - ret = _vsnwprintf_unsafe(_Dst, _SizeInWords, _Count, _Format, _ArgList); - va_end(_ArgList); - return ret; -} - inline int __cdecl _vsnprintf_unsafe(char *_Dst, size_t _SizeInWords, size_t _Count, const char *_Format, va_list _ArgList) { if (_Count == _TRUNCATE) _Count = _SizeInWords - 1; @@ -1071,100 +1013,6 @@ inline errno_t __cdecl _fopen_unsafe(PAL_FILE * *ff, const char *fileName, const } } -/* _itow_s */ -_SAFECRT__EXTERN_C -errno_t __cdecl _itow_s(int _Value, WCHAR *_Dst, size_t _SizeInWords, int _Radix); - -#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS -template -inline -errno_t __cdecl _itow_s(int _Value, WCHAR (&_Dst)[_SizeInWords], int _Radix) -{ - return _itow_s(_Value, _Dst, _SizeInWords, _Radix); -} -#endif - -#if _SAFECRT_USE_INLINES - -__inline -errno_t __cdecl _itow_s(int _Value, WCHAR *_Dst, size_t _SizeInWords, int _Radix) -{ - /* validation section */ - _SAFECRT__VALIDATE_STRING(_Dst, _SizeInWords); - - /* TODO: do not write past buffer size */ - _itow(_Value, _Dst, _Radix); - return 0; -} - -#endif - -/* _i64tow_s */ -_SAFECRT__EXTERN_C -errno_t __cdecl _i64tow_s(__int64 _Value, WCHAR *_Dst, size_t _SizeInWords, int _Radix); - -#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS -template -inline -errno_t __cdecl _i64tow_s(__int64 _Value, WCHAR (&_Dst)[_SizeInWords], int _Radix) -{ - return _i64tow_s(_Value, _Dst, _SizeInWords, _Radix); -} -#endif - -#if _SAFECRT_USE_INLINES - -__inline -errno_t __cdecl _i64tow_s(__int64 _Value, WCHAR *_Dst, size_t _SizeInWords, int _Radix) -{ - /* validation section */ - _SAFECRT__VALIDATE_STRING(_Dst, _SizeInWords); - - /* TODO: do not write past buffer size */ - _i64tow(_Value, _Dst, _Radix); - return 0; -} - -#endif - -/* getenv_s */ -/* - * _ReturnValue indicates if the variable has been found and size needed - */ -_SAFECRT__EXTERN_C -errno_t __cdecl getenv_s(size_t *_ReturnValue, char *_Dst, size_t _SizeInWords, const char *_Name); - -#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS -template -inline -errno_t __cdecl getenv_s(size_t *_ReturnValue, char *_Dst, size_t _SizeInWords, const char *_Name) -{ - return getenv_s(_ReturnValue, _Dst, _SizeInWords, _Name); -} -#endif - -#if _SAFECRT_USE_INLINES - -__inline -errno_t __cdecl getenv_s(size_t *_ReturnValue, char *_Dst, size_t _SizeInWords, const char *_Name) -{ - char *szFound; - - /* validation section */ - _SAFECRT__VALIDATE_STRING(_Dst, _SizeInWords); - - szFound = getenv(_Name); - if (szFound == nullptr) - { - *_ReturnValue = 0; - return 0; - } - *_ReturnValue = strlen(szFound) + 1; - return strcpy_s(_Dst, _SizeInWords, szFound); -} - -#endif - } #endif /* __cplusplus */ @@ -1247,6 +1095,7 @@ namespace std typedef decltype(nullptr) nullptr_t; } +extern "C++" template< class T > typename std::remove_reference::type&& move( T&& t ); #endif // __cplusplus @@ -1327,7 +1176,7 @@ typedef VOID (__stdcall *WAITORTIMERCALLBACK)(PVOID, BOOLEAN); // The message in these two macros should not contain any keywords like TODO // or NYI. It should be just the brief description of the problem. -#if defined(_TARGET_X86_) +#ifdef PORTABILITY_CHECK // Finished ports - compile-time errors #define PORTABILITY_WARNING(message) NEED_TO_PORT_THIS_ONE(NEED_TO_PORT_THIS_ONE) #define PORTABILITY_ASSERT(message) NEED_TO_PORT_THIS_ONE(NEED_TO_PORT_THIS_ONE) @@ -1666,7 +1515,7 @@ typedef struct _DISPATCHER_CONTEXT { ULONG64 Reserved; } DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; -#else +#elif defined(_AMD64_) typedef struct _DISPATCHER_CONTEXT { ULONG64 ControlPc; @@ -1680,6 +1529,29 @@ typedef struct _DISPATCHER_CONTEXT { PUNWIND_HISTORY_TABLE HistoryTable; } DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; +#elif defined(_X86_) + +typedef struct _EXCEPTION_REGISTRATION_RECORD { + struct _EXCEPTION_REGISTRATION_RECORD *Next; + PEXCEPTION_ROUTINE Handler; +} EXCEPTION_REGISTRATION_RECORD; + +typedef struct _DISPATCHER_CONTEXT { + DWORD ControlPc; + DWORD ImageBase; + PRUNTIME_FUNCTION FunctionEntry; + DWORD EstablisherFrame; + DWORD TargetIp; + PCONTEXT ContextRecord; + PEXCEPTION_ROUTINE LanguageHandler; + PVOID HandlerData; + PUNWIND_HISTORY_TABLE HistoryTable; +} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; + +#else + +#error Unknown architecture for defining DISPATCHER_CONTEXT. + #endif // #endif // !defined(_TARGET_MAC64) diff --git a/src/pal/inc/rt/safecrt.h b/src/pal/inc/rt/safecrt.h index 6b95e28..3cc10ce 100644 --- a/src/pal/inc/rt/safecrt.h +++ b/src/pal/inc/rt/safecrt.h @@ -409,7 +409,6 @@ void __cdecl _invalid_parameter(const WCHAR *_Message, const WCHAR *_FunctionNam #define _tmakepath_s _makepath_s #define _tsplitpath_s _splitpath_s #define _stprintf_s sprintf_s -#define _vstprintf_s vsprintf_s #define _sntprintf_s _snprintf_s #define _vsntprintf_s _vsnprintf_s #define _tscanf_s scanf_s @@ -428,8 +427,6 @@ void __cdecl _invalid_parameter(const WCHAR *_Message, const WCHAR *_FunctionNam #define _tmakepath_s _wmakepath_s #define _tsplitpath_s _wsplitpath_s #define _stprintf_s swprintf_s -#define _vstprintf_s vswprintf_s -#define _sntprintf_s _snwprintf_s #define _vsntprintf_s _vsnwprintf_s #define _tscanf_s wscanf_s #define _tsscanf_s swscanf_s @@ -447,9 +444,7 @@ void __cdecl _invalid_parameter(const WCHAR *_Message, const WCHAR *_FunctionNam #define _tmakepath_s _makepath_s #define _tsplitpath_s _splitpath_s #define _stprintf_s sprintf_s -#define _vstprintf_s vsprintf_s #define _sntprintf_s _snprintf_s -#define _vsntprintf_s _vsnprintf_s #define _tscanf_s scanf_s #define _tsscanf_s sscanf_s #define _tsnscanf_s _snscanf_s @@ -3222,7 +3217,7 @@ int __cdecl vswprintf_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Format, #if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS template inline -int __cdecl swprintf_s(char (&_Dst)[_SizeInWords], const char *_Format, ...) +int __cdecl swprintf_s(WCHAR (&_Dst)[_SizeInWords], const WCHAR *_Format, ...) { int ret; va_list _ArgList; @@ -3234,7 +3229,7 @@ int __cdecl swprintf_s(char (&_Dst)[_SizeInWords], const char *_Format, ...) template inline -int __cdecl vswprintf_s(char (&_Dst)[_SizeInWords], const char *_Format, va_list _ArgList) +int __cdecl vswprintf_s(WCHAR (&_Dst)[_SizeInWords], const WCHAR *_Format, va_list _ArgList) { return vswprintf_s(_Dst, _SizeInWords, _Format, _ArgList); } @@ -3288,14 +3283,12 @@ int __cdecl _vsnprintf_s(char (&_Dst)[_SizeInBytes], size_t _Count, const char * /* _snwprintf_s, _vsnwprintf_s */ _SAFECRT__EXTERN_C -int __cdecl _snwprintf_s(WCHAR *_Dst, size_t _SizeInWords, size_t _Count, const WCHAR *_Format, ...); -_SAFECRT__EXTERN_C int __cdecl _vsnwprintf_s(WCHAR *_Dst, size_t _SizeInWords, size_t _Count, const WCHAR *_Format, va_list _ArgList); #if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS template inline -int __cdecl _snwprintf_s(char (&_Dst)[_SizeInWords], size_t _Count, const char *_Format, ...) +int __cdecl _snwprintf_s(WCHAR (&_Dst)[_SizeInWords], size_t _Count, const WCHAR *_Format, ...) { int ret; va_list _ArgList; diff --git a/src/pal/inc/strsafe.h b/src/pal/inc/strsafe.h index 5a9f0ed..58749f2 100644 --- a/src/pal/inc/strsafe.h +++ b/src/pal/inc/strsafe.h @@ -32,7 +32,7 @@ #define _vsnprintf vsnprintf #endif // defined(PLATFORM_UNIX) && !defined (FEATURE_PAL) -#include // for _vsnprintf, _vsnwprintf, getc, getwc +#include // for _vsnprintf, getc, getwc #include // for memset #include // for va_start, etc. @@ -146,10 +146,6 @@ STRSAFEAPI StringCatNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, STRSAFEAPI StringCatNWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchMaxAppend); STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); STRSAFEAPI StringCatNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, size_t cchMaxAppend, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); -STRSAFEAPI StringVPrintfWorkerA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList); -STRSAFEAPI StringVPrintfWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszFormat, va_list argList); -STRSAFEAPI StringVPrintfExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList); -STRSAFEAPI StringVPrintfExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const WCHAR* pszFormat, va_list argList); STRSAFEAPI StringLengthWorkerA(const char* psz, size_t cchMax, size_t* pcch); STRSAFEAPI StringLengthWorkerW(const WCHAR* psz, size_t cchMax, size_t* pcch); #endif // STRSAFE_INLINE @@ -2356,1124 +2352,6 @@ STRSAFEAPI StringCbCatNExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, s #ifndef STRSAFE_NO_CCH_FUNCTIONS /*++ -STDAPI StringCchVPrintf(LPTSTR pszDest, - size_t cchDest, - LPCTSTR pszFormat, - va_list argList); - -Routine Description: - - This routine is a safer version of the C built-in function 'vsprintf'. - The size of the destination buffer (in characters) is a parameter and - this function will not write past the end of this buffer and it will - ALWAYS null terminate the destination buffer (unless it is zero length). - - This function returns a hresult, and not a pointer. It returns a S_OK - if the string was printed without truncation and null terminated, otherwise - it will return a failure code. In failure cases it will return a truncated - version of the ideal result. - -Arguments: - - pszDest - destination string - - cchDest - size of destination buffer in characters - length must be sufficient to hold the resulting formatted - string, including the null terminator. - - pszFormat - format string which must be null terminated - - argList - va_list from the variable arguments according to the - stdarg.h convention - -Notes: - Behavior is undefined if destination, format strings or any arguments - strings overlap. - - pszDest and pszFormat should not be NULL. See StringCchVPrintfEx if you - require the handling of NULL values. - -Return Value: - - S_OK - if there was sufficient space in the dest buffer for - the resultant string and it was null terminated. - - failure - you can use the macro HRESULT_CODE() to get a win32 error - code for all falure cases - - STRSAFE_E_INSUFFICIENT_BUFFER / - HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - - this return value is an indication that the print operation - failed due to insufficient space. When this error occurs, - the destination buffer is modified to contain a truncated - version of the ideal result and is null terminated. This - is useful for situations where truncation is ok. - - It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the - return value of this function - ---*/ - -STRSAFEAPI StringCchVPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList); -STRSAFEAPI StringCchVPrintfW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszFormat, va_list argList); -#ifdef UNICODE -#define StringCchVPrintf StringCchVPrintfW -#else -#define StringCchVPrintf StringCchVPrintfA -#endif // !UNICODE - -#ifdef STRSAFE_INLINE -STRSAFEAPI StringCchVPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList) -{ - HRESULT hr; - - if (cchDest > STRSAFE_MAX_CCH) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - hr = StringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList); - } - - return hr; -} - -#if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX) -STRSAFEAPI StringCchVPrintfW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszFormat, va_list argList) -{ - HRESULT hr; - - if (cchDest > STRSAFE_MAX_CCH) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - hr = StringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList); - } - - return hr; -} -#endif // FEATURE_PAL || !PLATFORM_UNIX -#endif // STRSAFE_INLINE -#endif // !STRSAFE_NO_CCH_FUNCTIONS - - -#ifndef STRSAFE_NO_CB_FUNCTIONS -/*++ - -STDAPI StringCbVPrintf(LPTSTR pszDest, - size_t cbDest, - LPCTSTR pszFormat, - va_list argList); - -Routine Description: - - This routine is a safer version of the C built-in function 'vsprintf'. - The size of the destination buffer (in bytes) is a parameter and - this function will not write past the end of this buffer and it will - ALWAYS null terminate the destination buffer (unless it is zero length). - - This function returns a hresult, and not a pointer. It returns a S_OK - if the string was printed without truncation and null terminated, otherwise - it will return a failure code. In failure cases it will return a truncated - version of the ideal result. - -Arguments: - - pszDest - destination string - - cbDest - size of destination buffer in bytes - length must be sufficient to hold the resulting formatted - string, including the null terminator. - - pszFormat - format string which must be null terminated - - argList - va_list from the variable arguments according to the - stdarg.h convention - -Notes: - Behavior is undefined if destination, format strings or any arguments - strings overlap. - - pszDest and pszFormat should not be NULL. See StringCbVPrintfEx if you - require the handling of NULL values. - - -Return Value: - - S_OK - if there was sufficient space in the dest buffer for - the resultant string and it was null terminated. - - failure - you can use the macro HRESULT_CODE() to get a win32 error - code for all falure cases - - STRSAFE_E_INSUFFICIENT_BUFFER / - HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - - this return value is an indication that the print operation - failed due to insufficient space. When this error occurs, - the destination buffer is modified to contain a truncated - version of the ideal result and is null terminated. This - is useful for situations where truncation is ok. - - It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the - return value of this function - ---*/ - -STRSAFEAPI StringCbVPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, va_list argList); -STRSAFEAPI StringCbVPrintfW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszFormat, va_list argList); -#ifdef UNICODE -#define StringCbVPrintf StringCbVPrintfW -#else -#define StringCbVPrintf StringCbVPrintfA -#endif // !UNICODE - -#ifdef STRSAFE_INLINE -STRSAFEAPI StringCbVPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, va_list argList) -{ - HRESULT hr; - size_t cchDest; - - cchDest = cbDest / sizeof(char); - - if (cchDest > STRSAFE_MAX_CCH) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - hr = StringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList); - } - - return hr; -} - -#if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX) -STRSAFEAPI StringCbVPrintfW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszFormat, va_list argList) -{ - HRESULT hr; - size_t cchDest; - - cchDest = cbDest / sizeof(WCHAR); - - if (cchDest > STRSAFE_MAX_CCH) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - hr = StringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList); - } - - return hr; -} -#endif // FEATURE_PAL || !PLATFORM_UNIX -#endif // STRSAFE_INLINE -#endif // !STRSAFE_NO_CB_FUNCTIONS - - -#ifndef STRSAFE_NO_CCH_FUNCTIONS -/*++ - -STDAPI StringCchPrintf(LPTSTR pszDest, - size_t cchDest, - LPCTSTR pszFormat, - ...); - -Routine Description: - - This routine is a safer version of the C built-in function 'sprintf'. - The size of the destination buffer (in characters) is a parameter and - this function will not write past the end of this buffer and it will - ALWAYS null terminate the destination buffer (unless it is zero length). - - This function returns a hresult, and not a pointer. It returns a S_OK - if the string was printed without truncation and null terminated, otherwise - it will return a failure code. In failure cases it will return a truncated - version of the ideal result. - -Arguments: - - pszDest - destination string - - cchDest - size of destination buffer in characters - length must be sufficient to hold the resulting formatted - string, including the null terminator. - - pszFormat - format string which must be null terminated - - ... - additional parameters to be formatted according to - the format string - -Notes: - Behavior is undefined if destination, format strings or any arguments - strings overlap. - - pszDest and pszFormat should not be NULL. See StringCchPrintfEx if you - require the handling of NULL values. - -Return Value: - - S_OK - if there was sufficient space in the dest buffer for - the resultant string and it was null terminated. - - failure - you can use the macro HRESULT_CODE() to get a win32 error - code for all falure cases - - STRSAFE_E_INSUFFICIENT_BUFFER / - HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - - this return value is an indication that the print operation - failed due to insufficient space. When this error occurs, - the destination buffer is modified to contain a truncated - version of the ideal result and is null terminated. This - is useful for situations where truncation is ok. - - It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the - return value of this function - ---*/ - -STRSAFEAPI StringCchPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, ...); -STRSAFEAPI StringCchPrintfW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszFormat, ...); -#ifdef UNICODE -#define StringCchPrintf StringCchPrintfW -#else -#define StringCchPrintf StringCchPrintfA -#endif // !UNICODE - -#ifdef STRSAFE_INLINE -STRSAFEAPI StringCchPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, ...) -{ - HRESULT hr; - - if (cchDest > STRSAFE_MAX_CCH) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - va_list argList; - - va_start(argList, pszFormat); - - hr = StringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList); - - va_end(argList); - } - - return hr; -} - -#if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX) -STRSAFEAPI StringCchPrintfW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszFormat, ...) -{ - HRESULT hr; - - if (cchDest > STRSAFE_MAX_CCH) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - va_list argList; - - va_start(argList, pszFormat); - - hr = StringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList); - - va_end(argList); - } - - return hr; -} -#endif // FEATURE_PAL || !PLATFORM_UNIX -#endif // STRSAFE_INLINE -#endif // !STRSAFE_NO_CCH_FUNCTIONS - - -#ifndef STRSAFE_NO_CB_FUNCTIONS -/*++ - -STDAPI StringCbPrintf(LPTSTR pszDest, - size_t cbDest, - LPCTSTR pszFormat, - ...); - -Routine Description: - - This routine is a safer version of the C built-in function 'sprintf'. - The size of the destination buffer (in bytes) is a parameter and - this function will not write past the end of this buffer and it will - ALWAYS null terminate the destination buffer (unless it is zero length). - - This function returns a hresult, and not a pointer. It returns a S_OK - if the string was printed without truncation and null terminated, otherwise - it will return a failure code. In failure cases it will return a truncated - version of the ideal result. - -Arguments: - - pszDest - destination string - - cbDest - size of destination buffer in bytes - length must be sufficient to hold the resulting formatted - string, including the null terminator. - - pszFormat - format string which must be null terminated - - ... - additional parameters to be formatted according to - the format string - -Notes: - Behavior is undefined if destination, format strings or any arguments - strings overlap. - - pszDest and pszFormat should not be NULL. See StringCbPrintfEx if you - require the handling of NULL values. - - -Return Value: - - S_OK - if there was sufficient space in the dest buffer for - the resultant string and it was null terminated. - - failure - you can use the macro HRESULT_CODE() to get a win32 error - code for all falure cases - - STRSAFE_E_INSUFFICIENT_BUFFER / - HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - - this return value is an indication that the print operation - failed due to insufficient space. When this error occurs, - the destination buffer is modified to contain a truncated - version of the ideal result and is null terminated. This - is useful for situations where truncation is ok. - - It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the - return value of this function - ---*/ - -STRSAFEAPI StringCbPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, ...); -STRSAFEAPI StringCbPrintfW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszFormat, ...); -#ifdef UNICODE -#define StringCbPrintf StringCbPrintfW -#else -#define StringCbPrintf StringCbPrintfA -#endif // !UNICODE - -#ifdef STRSAFE_INLINE -STRSAFEAPI StringCbPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, ...) -{ - HRESULT hr; - size_t cchDest; - - cchDest = cbDest / sizeof(char); - - if (cchDest > STRSAFE_MAX_CCH) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - va_list argList; - - va_start(argList, pszFormat); - - hr = StringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList); - - va_end(argList); - } - - return hr; -} - -#if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX) -STRSAFEAPI StringCbPrintfW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszFormat, ...) -{ - HRESULT hr; - size_t cchDest; - - cchDest = cbDest / sizeof(WCHAR); - - if (cchDest > STRSAFE_MAX_CCH) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - va_list argList; - - va_start(argList, pszFormat); - - hr = StringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList); - - va_end(argList); - } - - return hr; -} -#endif // FEATURE_PAL || !PLATFORM_UNIX -#endif // STRSAFE_INLINE -#endif // !STRSAFE_NO_CB_FUNCTIONS - - -#ifndef STRSAFE_NO_CCH_FUNCTIONS -/*++ - -STDAPI StringCchPrintfEx(LPTSTR pszDest, - size_t cchDest, - LPTSTR* ppszDestEnd, - size_t* pcchRemaining, - DWORD dwFlags, - LPCTSTR pszFormat, - ...); - -Routine Description: - - This routine is a safer version of the C built-in function 'sprintf' with - some additional parameters. In addition to functionality provided by - StringCchPrintf, this routine also returns a pointer to the end of the - destination string and the number of characters left in the destination string - including the null terminator. The flags parameter allows additional controls. - -Arguments: - - pszDest - destination string - - cchDest - size of destination buffer in characters. - length must be sufficient to contain the resulting - formatted string plus the null terminator. - - ppszDestEnd - if ppszDestEnd is non-null, the function will return a - pointer to the end of the destination string. If the - function printed any data, the result will point to the - null termination character - - pcchRemaining - if pcchRemaining is non-null, the function will return - the number of characters left in the destination string, - including the null terminator - - dwFlags - controls some details of the string copy: - - STRSAFE_FILL_BEHIND_NULL - if the function succeeds, the low byte of dwFlags will be - used to fill the uninitialize part of destination buffer - behind the null terminator - - STRSAFE_IGNORE_NULLS - treat NULL string pointers like empty strings (TEXT("")) - - STRSAFE_FILL_ON_FAILURE - if the function fails, the low byte of dwFlags will be - used to fill all of the destination buffer, and it will - be null terminated. This will overwrite any truncated - string returned when the failure is - STRSAFE_E_INSUFFICIENT_BUFFER - - STRSAFE_NO_TRUNCATION / - STRSAFE_NULL_ON_FAILURE - if the function fails, the destination buffer will be set - to the empty string. This will overwrite any truncated string - returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. - - pszFormat - format string which must be null terminated - - ... - additional parameters to be formatted according to - the format string - -Notes: - Behavior is undefined if destination, format strings or any arguments - strings overlap. - - pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS - flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and - pszFormat may be NULL. An error may still be returned even though NULLS - are ignored due to insufficient space. - -Return Value: - - S_OK - if there was source data and it was all concatenated and the - resultant dest string was null terminated - - failure - you can use the macro HRESULT_CODE() to get a win32 error - code for all falure cases - - STRSAFE_E_INSUFFICIENT_BUFFER / - HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - - this return value is an indication that the print operation - failed due to insufficient space. When this error occurs, - the destination buffer is modified to contain a truncated - version of the ideal result and is null terminated. This - is useful for situations where truncation is ok. - - It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the - return value of this function - ---*/ - -STRSAFEAPI StringCchPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, ...); -STRSAFEAPI StringCchPrintfExW(WCHAR* pszDest, size_t cchDest, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const WCHAR* pszFormat, ...); -#ifdef UNICODE -#define StringCchPrintfEx StringCchPrintfExW -#else -#define StringCchPrintfEx StringCchPrintfExA -#endif // !UNICODE - -#ifdef STRSAFE_INLINE -STRSAFEAPI StringCchPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, ...) -{ - HRESULT hr; - - if (cchDest > STRSAFE_MAX_CCH) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - size_t cbDest; - va_list argList; - - // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 - cbDest = cchDest * sizeof(char); - va_start(argList, pszFormat); - - hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList); - - va_end(argList); - } - - return hr; -} - -#if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX) -STRSAFEAPI StringCchPrintfExW(WCHAR* pszDest, size_t cchDest, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const WCHAR* pszFormat, ...) -{ - HRESULT hr; - - if (cchDest > STRSAFE_MAX_CCH) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - size_t cbDest; - va_list argList; - - // safe to multiply cchDest * sizeof(WCHAR) since cchDest < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2 - cbDest = cchDest * sizeof(WCHAR); - va_start(argList, pszFormat); - - hr = StringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList); - - va_end(argList); - } - - return hr; -} -#endif // FEATURE_PAL || !PLATFORM_UNIX -#endif // STRSAFE_INLINE -#endif // !STRSAFE_NO_CCH_FUNCTIONS - - -#ifndef STRSAFE_NO_CB_FUNCTIONS -/*++ - -STDAPI StringCbPrintfEx(LPTSTR pszDest, - size_t cbDest, - LPTSTR* ppszDestEnd, - size_t* pcbRemaining, - DWORD dwFlags, - LPCTSTR pszFormat, - ...); - -Routine Description: - - This routine is a safer version of the C built-in function 'sprintf' with - some additional parameters. In addition to functionality provided by - StringCbPrintf, this routine also returns a pointer to the end of the - destination string and the number of bytes left in the destination string - including the null terminator. The flags parameter allows additional controls. - -Arguments: - - pszDest - destination string - - cbDest - size of destination buffer in bytes. - length must be sufficient to contain the resulting - formatted string plus the null terminator. - - ppszDestEnd - if ppszDestEnd is non-null, the function will return a - pointer to the end of the destination string. If the - function printed any data, the result will point to the - null termination character - - pcbRemaining - if pcbRemaining is non-null, the function will return - the number of bytes left in the destination string, - including the null terminator - - dwFlags - controls some details of the string copy: - - STRSAFE_FILL_BEHIND_NULL - if the function succeeds, the low byte of dwFlags will be - used to fill the uninitialize part of destination buffer - behind the null terminator - - STRSAFE_IGNORE_NULLS - treat NULL string pointers like empty strings (TEXT("")) - - STRSAFE_FILL_ON_FAILURE - if the function fails, the low byte of dwFlags will be - used to fill all of the destination buffer, and it will - be null terminated. This will overwrite any truncated - string returned when the failure is - STRSAFE_E_INSUFFICIENT_BUFFER - - STRSAFE_NO_TRUNCATION / - STRSAFE_NULL_ON_FAILURE - if the function fails, the destination buffer will be set - to the empty string. This will overwrite any truncated string - returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. - - pszFormat - format string which must be null terminated - - ... - additional parameters to be formatted according to - the format string - -Notes: - Behavior is undefined if destination, format strings or any arguments - strings overlap. - - pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS - flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and - pszFormat may be NULL. An error may still be returned even though NULLS - are ignored due to insufficient space. - -Return Value: - - S_OK - if there was source data and it was all concatenated and the - resultant dest string was null terminated - - failure - you can use the macro HRESULT_CODE() to get a win32 error - code for all falure cases - - STRSAFE_E_INSUFFICIENT_BUFFER / - HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - - this return value is an indication that the print operation - failed due to insufficient space. When this error occurs, - the destination buffer is modified to contain a truncated - version of the ideal result and is null terminated. This - is useful for situations where truncation is ok. - - It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the - return value of this function - ---*/ - -STRSAFEAPI StringCbPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, ...); -STRSAFEAPI StringCbPrintfExW(WCHAR* pszDest, size_t cbDest, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const WCHAR* pszFormat, ...); -#ifdef UNICODE -#define StringCbPrintfEx StringCbPrintfExW -#else -#define StringCbPrintfEx StringCbPrintfExA -#endif // !UNICODE - -#ifdef STRSAFE_INLINE -STRSAFEAPI StringCbPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, ...) -{ - HRESULT hr; - size_t cchDest; - size_t cchRemaining = 0; - - cchDest = cbDest / sizeof(char); - - if (cchDest > STRSAFE_MAX_CCH) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - va_list argList; - - va_start(argList, pszFormat); - - hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList); - - va_end(argList); - } - - if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) - { - if (pcbRemaining) - { - // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 - *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); - } - } - - return hr; -} - -#if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX) -STRSAFEAPI StringCbPrintfExW(WCHAR* pszDest, size_t cbDest, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const WCHAR* pszFormat, ...) -{ - HRESULT hr; - size_t cchDest; - size_t cchRemaining = 0; - - cchDest = cbDest / sizeof(WCHAR); - - if (cchDest > STRSAFE_MAX_CCH) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - va_list argList; - - va_start(argList, pszFormat); - - hr = StringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList); - - va_end(argList); - } - - if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) - { - if (pcbRemaining) - { - // safe to multiply cchRemaining * sizeof(WCHAR) since cchRemaining < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2 - *pcbRemaining = (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)); - } - } - - return hr; -} -#endif // FEATURE_PAL || !PLATFORM_UNIX -#endif // STRSAFE_INLINE -#endif // !STRSAFE_NO_CB_FUNCTIONS - - -#ifndef STRSAFE_NO_CCH_FUNCTIONS -/*++ - -STDAPI StringCchVPrintfEx(LPTSTR pszDest, - size_t cchDest, - LPTSTR* ppszDestEnd, - size_t* pcchRemaining, - DWORD dwFlags, - LPCTSTR pszFormat, - va_list argList); - -Routine Description: - - This routine is a safer version of the C built-in function 'vsprintf' with - some additional parameters. In addition to functionality provided by - StringCchVPrintf, this routine also returns a pointer to the end of the - destination string and the number of characters left in the destination string - including the null terminator. The flags parameter allows additional controls. - -Arguments: - - pszDest - destination string - - cchDest - size of destination buffer in characters. - length must be sufficient to contain the resulting - formatted string plus the null terminator. - - ppszDestEnd - if ppszDestEnd is non-null, the function will return a - pointer to the end of the destination string. If the - function printed any data, the result will point to the - null termination character - - pcchRemaining - if pcchRemaining is non-null, the function will return - the number of characters left in the destination string, - including the null terminator - - dwFlags - controls some details of the string copy: - - STRSAFE_FILL_BEHIND_NULL - if the function succeeds, the low byte of dwFlags will be - used to fill the uninitialize part of destination buffer - behind the null terminator - - STRSAFE_IGNORE_NULLS - treat NULL string pointers like empty strings (TEXT("")) - - STRSAFE_FILL_ON_FAILURE - if the function fails, the low byte of dwFlags will be - used to fill all of the destination buffer, and it will - be null terminated. This will overwrite any truncated - string returned when the failure is - STRSAFE_E_INSUFFICIENT_BUFFER - - STRSAFE_NO_TRUNCATION / - STRSAFE_NULL_ON_FAILURE - if the function fails, the destination buffer will be set - to the empty string. This will overwrite any truncated string - returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. - - pszFormat - format string which must be null terminated - - argList - va_list from the variable arguments according to the - stdarg.h convention - -Notes: - Behavior is undefined if destination, format strings or any arguments - strings overlap. - - pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS - flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and - pszFormat may be NULL. An error may still be returned even though NULLS - are ignored due to insufficient space. - -Return Value: - - S_OK - if there was source data and it was all concatenated and the - resultant dest string was null terminated - - failure - you can use the macro HRESULT_CODE() to get a win32 error - code for all falure cases - - STRSAFE_E_INSUFFICIENT_BUFFER / - HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - - this return value is an indication that the print operation - failed due to insufficient space. When this error occurs, - the destination buffer is modified to contain a truncated - version of the ideal result and is null terminated. This - is useful for situations where truncation is ok. - - It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the - return value of this function - ---*/ - -STRSAFEAPI StringCchVPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList); -STRSAFEAPI StringCchVPrintfExW(WCHAR* pszDest, size_t cchDest, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const WCHAR* pszFormat, va_list argList); -#ifdef UNICODE -#define StringCchVPrintfEx StringCchVPrintfExW -#else -#define StringCchVPrintfEx StringCchVPrintfExA -#endif // !UNICODE - -#ifdef STRSAFE_INLINE -STRSAFEAPI StringCchVPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList) -{ - HRESULT hr; - - if (cchDest > STRSAFE_MAX_CCH) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - size_t cbDest; - - // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 - cbDest = cchDest * sizeof(char); - - hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList); - } - - return hr; -} - -#if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX) -STRSAFEAPI StringCchVPrintfExW(WCHAR* pszDest, size_t cchDest, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const WCHAR* pszFormat, va_list argList) -{ - HRESULT hr; - - if (cchDest > STRSAFE_MAX_CCH) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - size_t cbDest; - - // safe to multiply cchDest * sizeof(WCHAR) since cchDest < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2 - cbDest = cchDest * sizeof(WCHAR); - - hr = StringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList); - } - - return hr; -} -#endif // FEATURE_PAL || !PLATFORM_UNIX -#endif // STRSAFE_INLINE -#endif // !STRSAFE_NO_CCH_FUNCTIONS - - -#ifndef STRSAFE_NO_CB_FUNCTIONS -/*++ - -STDAPI StringCbVPrintfEx(LPTSTR pszDest, - size_t cbDest, - LPTSTR* ppszDestEnd, - size_t* pcbRemaining, - DWORD dwFlags, - LPCTSTR pszFormat, - va_list argList); - -Routine Description: - - This routine is a safer version of the C built-in function 'vsprintf' with - some additional parameters. In addition to functionality provided by - StringCbVPrintf, this routine also returns a pointer to the end of the - destination string and the number of characters left in the destination string - including the null terminator. The flags parameter allows additional controls. - -Arguments: - - pszDest - destination string - - cbDest - size of destination buffer in bytes. - length must be sufficient to contain the resulting - formatted string plus the null terminator. - - ppszDestEnd - if ppszDestEnd is non-null, the function will return - a pointer to the end of the destination string. If the - function printed any data, the result will point to the - null termination character - - pcbRemaining - if pcbRemaining is non-null, the function will return - the number of bytes left in the destination string, - including the null terminator - - dwFlags - controls some details of the string copy: - - STRSAFE_FILL_BEHIND_NULL - if the function succeeds, the low byte of dwFlags will be - used to fill the uninitialize part of destination buffer - behind the null terminator - - STRSAFE_IGNORE_NULLS - treat NULL string pointers like empty strings (TEXT("")) - - STRSAFE_FILL_ON_FAILURE - if the function fails, the low byte of dwFlags will be - used to fill all of the destination buffer, and it will - be null terminated. This will overwrite any truncated - string returned when the failure is - STRSAFE_E_INSUFFICIENT_BUFFER - - STRSAFE_NO_TRUNCATION / - STRSAFE_NULL_ON_FAILURE - if the function fails, the destination buffer will be set - to the empty string. This will overwrite any truncated string - returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. - - pszFormat - format string which must be null terminated - - argList - va_list from the variable arguments according to the - stdarg.h convention - -Notes: - Behavior is undefined if destination, format strings or any arguments - strings overlap. - - pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS - flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and - pszFormat may be NULL. An error may still be returned even though NULLS - are ignored due to insufficient space. - -Return Value: - - S_OK - if there was source data and it was all concatenated and the - resultant dest string was null terminated - - failure - you can use the macro HRESULT_CODE() to get a win32 error - code for all falure cases - - STRSAFE_E_INSUFFICIENT_BUFFER / - HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER - - this return value is an indication that the print operation - failed due to insufficient space. When this error occurs, - the destination buffer is modified to contain a truncated - version of the ideal result and is null terminated. This - is useful for situations where truncation is ok. - - It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the - return value of this function - ---*/ - -STRSAFEAPI StringCbVPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList); -STRSAFEAPI StringCbVPrintfExW(WCHAR* pszDest, size_t cbDest, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const WCHAR* pszFormat, va_list argList); -#ifdef UNICODE -#define StringCbVPrintfEx StringCbVPrintfExW -#else -#define StringCbVPrintfEx StringCbVPrintfExA -#endif // !UNICODE - -#ifdef STRSAFE_INLINE -STRSAFEAPI StringCbVPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList) -{ - HRESULT hr; - size_t cchDest; - size_t cchRemaining = 0; - - cchDest = cbDest / sizeof(char); - - if (cchDest > STRSAFE_MAX_CCH) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList); - } - - if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) - { - if (pcbRemaining) - { - // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 - *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); - } - } - - return hr; -} - -#if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX) -STRSAFEAPI StringCbVPrintfExW(WCHAR* pszDest, size_t cbDest, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const WCHAR* pszFormat, va_list argList) -{ - HRESULT hr; - size_t cchDest; - size_t cchRemaining = 0; - - cchDest = cbDest / sizeof(WCHAR); - - if (cchDest > STRSAFE_MAX_CCH) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - hr = StringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList); - } - - if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) - { - if (pcbRemaining) - { - // safe to multiply cchRemaining * sizeof(WCHAR) since cchRemaining < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2 - *pcbRemaining = (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)); - } - } - - return hr; -} -#endif // FEATURE_PAL || !PLATFORM_UNIX -#endif // STRSAFE_INLINE -#endif // !STRSAFE_NO_CB_FUNCTIONS - - -#ifndef STRSAFE_NO_CCH_FUNCTIONS -/*++ - STDAPI StringCchGets(LPTSTR pszDest, size_t cchDest); @@ -4119,423 +2997,83 @@ Return Value: S_OK - psz is non-null and the length including the null terminator is less than or equal to cbMax bytes - failure - you can use the macro HRESULT_CODE() to get a win32 error - code for all hresult falure cases - - It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the - return value of this function. - ---*/ - -STRSAFEAPI StringCbLengthA(const char* psz, size_t cchMax, size_t* pcch); -STRSAFEAPI StringCbLengthW(const WCHAR* psz, size_t cchMax, size_t* pcch); -#ifdef UNICODE -#define StringCbLength StringCbLengthW -#else -#define StringCbLength StringCbLengthA -#endif // !UNICODE - -#ifdef STRSAFE_INLINE -STRSAFEAPI StringCbLengthA(const char* psz, size_t cbMax, size_t* pcb) -{ - HRESULT hr; - size_t cchMax; - size_t cch = 0; - - cchMax = cbMax / sizeof(char); - - if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - hr = StringLengthWorkerA(psz, cchMax, &cch); - } - - if (SUCCEEDED(hr) && pcb) - { - // safe to multiply cch * sizeof(char) since cch < STRSAFE_MAX_CCH and sizeof(char) is 1 - *pcb = cch * sizeof(char); - } - - return hr; -} - -#if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX) -STRSAFEAPI StringCbLengthW(const WCHAR* psz, size_t cbMax, size_t* pcb) -{ - HRESULT hr; - size_t cchMax; - size_t cch = 0; - - cchMax = cbMax / sizeof(WCHAR); - - if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - hr = StringLengthWorkerW(psz, cchMax, &cch); - } - - if (SUCCEEDED(hr) && pcb) - { - // safe to multiply cch * sizeof(WCHAR) since cch < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2 - *pcb = cch * sizeof(WCHAR); - } - - return hr; -} -#endif // FEATURE_PAL || !PLATFORM_UNIX -#endif // STRSAFE_INLINE -#endif // !STRSAFE_NO_CB_FUNCTIONS - - -// these are the worker functions that actually do the work -#ifdef STRSAFE_INLINE -STRSAFEAPI StringCopyWorkerA(char* pszDest, size_t cchDest, const char* pszSrc) -{ - HRESULT hr = S_OK; - - if (cchDest == 0) - { - // can not null terminate a zero-byte dest buffer - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - while (cchDest && (*pszSrc != '\0')) - { - *pszDest++ = *pszSrc++; - cchDest--; - } - - if (cchDest == 0) - { - // we are going to truncate pszDest - pszDest--; - hr = STRSAFE_E_INSUFFICIENT_BUFFER; - } - - *pszDest= '\0'; - } - - return hr; -} - -#if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX) -STRSAFEAPI StringCopyWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc) -{ - HRESULT hr = S_OK; - - if (cchDest == 0) - { - // can not null terminate a zero-byte dest buffer - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - while (cchDest && (*pszSrc != L'\0')) - { - *pszDest++ = *pszSrc++; - cchDest--; - } - - if (cchDest == 0) - { - // we are going to truncate pszDest - pszDest--; - hr = STRSAFE_E_INSUFFICIENT_BUFFER; - } - - *pszDest= L'\0'; - } - - return hr; -} -#endif // FEATURE_PAL || !PLATFORM_UNIX - -STRSAFEAPI StringCopyExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) -{ - HRESULT hr = S_OK; - char* pszDestEnd = pszDest; - size_t cchRemaining = 0; - - // ASSERT(cbDest == (cchDest * sizeof(char)) || - // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); - - // only accept valid flags - if (dwFlags & (~STRSAFE_VALID_FLAGS)) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - if (dwFlags & STRSAFE_IGNORE_NULLS) - { - if (pszDest == NULL) - { - if ((cchDest != 0) || (cbDest != 0)) - { - // NULL pszDest and non-zero cchDest/cbDest is invalid - hr = STRSAFE_E_INVALID_PARAMETER; - } - } - - if (pszSrc == NULL) - { - pszSrc = ""; - } - } - - if (SUCCEEDED(hr)) - { - if (cchDest == 0) - { - pszDestEnd = pszDest; - cchRemaining = 0; - - // only fail if there was actually src data to copy - if (*pszSrc != '\0') - { - if (pszDest == NULL) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - hr = STRSAFE_E_INSUFFICIENT_BUFFER; - } - } - } - else - { - pszDestEnd = pszDest; - cchRemaining = cchDest; - - while (cchRemaining && (*pszSrc != '\0')) - { - *pszDestEnd++= *pszSrc++; - cchRemaining--; - } - - if (cchRemaining > 0) - { - if (dwFlags & STRSAFE_FILL_BEHIND_NULL) - { - memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char))); - } - } - else - { - // we are going to truncate pszDest - pszDestEnd--; - cchRemaining++; - - hr = STRSAFE_E_INSUFFICIENT_BUFFER; - } - - *pszDestEnd = '\0'; - } - } - } - - if (FAILED(hr)) - { - if (pszDest) - { - if (dwFlags & STRSAFE_FILL_ON_FAILURE) - { - memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); - - if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) - { - pszDestEnd = pszDest; - cchRemaining = cchDest; - } - else if (cchDest > 0) - { - pszDestEnd = pszDest + cchDest - 1; - cchRemaining = 1; - - // null terminate the end of the string - *pszDestEnd = '\0'; - } - } - - if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) - { - if (cchDest > 0) - { - pszDestEnd = pszDest; - cchRemaining = cchDest; - - // null terminate the beginning of the string - *pszDestEnd = '\0'; - } - } - } - } + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all hresult falure cases - if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) - { - if (ppszDestEnd) - { - *ppszDestEnd = pszDestEnd; - } + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. - if (pcchRemaining) - { - *pcchRemaining = cchRemaining; - } - } +--*/ - return hr; -} +STRSAFEAPI StringCbLengthA(const char* psz, size_t cchMax, size_t* pcch); +STRSAFEAPI StringCbLengthW(const WCHAR* psz, size_t cchMax, size_t* pcch); +#ifdef UNICODE +#define StringCbLength StringCbLengthW +#else +#define StringCbLength StringCbLengthA +#endif // !UNICODE -#if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX) -STRSAFEAPI StringCopyExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbLengthA(const char* psz, size_t cbMax, size_t* pcb) { - HRESULT hr = S_OK; - WCHAR* pszDestEnd = pszDest; - size_t cchRemaining = 0; + HRESULT hr; + size_t cchMax; + size_t cch = 0; - // ASSERT(cbDest == (cchDest * sizeof(WCHAR)) || - // cbDest == (cchDest * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR))); - - // only accept valid flags - if (dwFlags & (~STRSAFE_VALID_FLAGS)) + cchMax = cbMax / sizeof(char); + + if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) { hr = STRSAFE_E_INVALID_PARAMETER; } else { - if (dwFlags & STRSAFE_IGNORE_NULLS) - { - if (pszDest == NULL) - { - if ((cchDest != 0) || (cbDest != 0)) - { - // NULL pszDest and non-zero cchDest/cbDest is invalid - hr = STRSAFE_E_INVALID_PARAMETER; - } - } - - if (pszSrc == NULL) - { - pszSrc = u""; - } - } + hr = StringLengthWorkerA(psz, cchMax, &cch); + } - if (SUCCEEDED(hr)) - { - if (cchDest == 0) - { - pszDestEnd = pszDest; - cchRemaining = 0; + if (SUCCEEDED(hr) && pcb) + { + // safe to multiply cch * sizeof(char) since cch < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcb = cch * sizeof(char); + } - // only fail if there was actually src data to copy - if (*pszSrc != u'\0') - { - if (pszDest == NULL) - { - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - hr = STRSAFE_E_INSUFFICIENT_BUFFER; - } - } - } - else - { - pszDestEnd = pszDest; - cchRemaining = cchDest; + return hr; +} - while (cchRemaining && (*pszSrc != u'\0')) - { - *pszDestEnd++= *pszSrc++; - cchRemaining--; - } - - if (cchRemaining > 0) - { - if (dwFlags & STRSAFE_FILL_BEHIND_NULL) - { - memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR))); - } - } - else - { - // we are going to truncate pszDest - pszDestEnd--; - cchRemaining++; +#if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX) +STRSAFEAPI StringCbLengthW(const WCHAR* psz, size_t cbMax, size_t* pcb) +{ + HRESULT hr; + size_t cchMax; + size_t cch = 0; - hr = STRSAFE_E_INSUFFICIENT_BUFFER; - } + cchMax = cbMax / sizeof(WCHAR); - *pszDestEnd = u'\0'; - } - } + if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; } - - if (FAILED(hr)) + else { - if (pszDest) - { - if (dwFlags & STRSAFE_FILL_ON_FAILURE) - { - memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); - - if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) - { - pszDestEnd = pszDest; - cchRemaining = cchDest; - } - else if (cchDest > 0) - { - pszDestEnd = pszDest + cchDest - 1; - cchRemaining = 1; - - // null terminate the end of the string - *pszDestEnd = L'\0'; - } - } - - if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) - { - if (cchDest > 0) - { - pszDestEnd = pszDest; - cchRemaining = cchDest; - - // null terminate the beginning of the string - *pszDestEnd = L'\0'; - } - } - } + hr = StringLengthWorkerW(psz, cchMax, &cch); } - if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + if (SUCCEEDED(hr) && pcb) { - if (ppszDestEnd) - { - *ppszDestEnd = pszDestEnd; - } - - if (pcchRemaining) - { - *pcchRemaining = cchRemaining; - } + // safe to multiply cch * sizeof(WCHAR) since cch < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2 + *pcb = cch * sizeof(WCHAR); } return hr; } #endif // FEATURE_PAL || !PLATFORM_UNIX +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS -STRSAFEAPI StringCopyNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc) + +// these are the worker functions that actually do the work +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCopyWorkerA(char* pszDest, size_t cchDest, const char* pszSrc) { HRESULT hr = S_OK; @@ -4546,11 +3084,10 @@ STRSAFEAPI StringCopyNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, } else { - while (cchDest && cchSrc && (*pszSrc != '\0')) + while (cchDest && (*pszSrc != '\0')) { - *pszDest++= *pszSrc++; + *pszDest++ = *pszSrc++; cchDest--; - cchSrc--; } if (cchDest == 0) @@ -4567,7 +3104,7 @@ STRSAFEAPI StringCopyNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, } #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX) -STRSAFEAPI StringCopyNWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchSrc) +STRSAFEAPI StringCopyWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc) { HRESULT hr = S_OK; @@ -4578,11 +3115,10 @@ STRSAFEAPI StringCopyNWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSr } else { - while (cchDest && cchSrc && (*pszSrc != L'\0')) + while (cchDest && (*pszSrc != L'\0')) { - *pszDest++= *pszSrc++; + *pszDest++ = *pszSrc++; cchDest--; - cchSrc--; } if (cchDest == 0) @@ -4599,7 +3135,7 @@ STRSAFEAPI StringCopyNWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSr } #endif // FEATURE_PAL || !PLATFORM_UNIX -STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +STRSAFEAPI StringCopyExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) { HRESULT hr = S_OK; char* pszDestEnd = pszDest; @@ -4657,11 +3193,10 @@ STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, co pszDestEnd = pszDest; cchRemaining = cchDest; - while (cchRemaining && cchSrc && (*pszSrc != '\0')) + while (cchRemaining && (*pszSrc != '\0')) { *pszDestEnd++= *pszSrc++; cchRemaining--; - cchSrc--; } if (cchRemaining > 0) @@ -4739,7 +3274,7 @@ STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, co } #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX) -STRSAFEAPI StringCopyNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, size_t cchSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +STRSAFEAPI StringCopyExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) { HRESULT hr = S_OK; WCHAR* pszDestEnd = pszDest; @@ -4780,7 +3315,7 @@ STRSAFEAPI StringCopyNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, c cchRemaining = 0; // only fail if there was actually src data to copy - if (*pszSrc != L'\0') + if (*pszSrc != u'\0') { if (pszDest == NULL) { @@ -4797,11 +3332,10 @@ STRSAFEAPI StringCopyNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, c pszDestEnd = pszDest; cchRemaining = cchDest; - while (cchRemaining && cchSrc && (*pszSrc != L'\0')) + while (cchRemaining && (*pszSrc != u'\0')) { *pszDestEnd++= *pszSrc++; cchRemaining--; - cchSrc--; } if (cchRemaining > 0) @@ -4820,7 +3354,7 @@ STRSAFEAPI StringCopyNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, c hr = STRSAFE_E_INSUFFICIENT_BUFFER; } - *pszDestEnd = L'\0'; + *pszDestEnd = u'\0'; } } } @@ -4832,7 +3366,7 @@ STRSAFEAPI StringCopyNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, c if (dwFlags & STRSAFE_FILL_ON_FAILURE) { memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); - + if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) { pszDestEnd = pszDest; @@ -4879,43 +3413,71 @@ STRSAFEAPI StringCopyNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, c } #endif // FEATURE_PAL || !PLATFORM_UNIX -STRSAFEAPI StringCatWorkerA(char* pszDest, size_t cchDest, const char* pszSrc) +STRSAFEAPI StringCopyNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc) { - HRESULT hr; - size_t cchDestCurrent; + HRESULT hr = S_OK; - hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + if (cchDest == 0) + { + // can not null terminate a zero-byte dest buffer + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + while (cchDest && cchSrc && (*pszSrc != '\0')) + { + *pszDest++= *pszSrc++; + cchDest--; + cchSrc--; + } - if (SUCCEEDED(hr)) - { - hr = StringCopyWorkerA(pszDest + cchDestCurrent, - cchDest - cchDestCurrent, - pszSrc); - } + if (cchDest == 0) + { + // we are going to truncate pszDest + pszDest--; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } - return hr; + *pszDest= '\0'; + } + + return hr; } #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX) -STRSAFEAPI StringCatWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc) -{ - HRESULT hr; - size_t cchDestCurrent; +STRSAFEAPI StringCopyNWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchSrc) +{ + HRESULT hr = S_OK; - hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + if (cchDest == 0) + { + // can not null terminate a zero-byte dest buffer + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + while (cchDest && cchSrc && (*pszSrc != L'\0')) + { + *pszDest++= *pszSrc++; + cchDest--; + cchSrc--; + } - if (SUCCEEDED(hr)) - { - hr = StringCopyWorkerW(pszDest + cchDestCurrent, - cchDest - cchDestCurrent, - pszSrc); - } + if (cchDest == 0) + { + // we are going to truncate pszDest + pszDest--; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } - return hr; + *pszDest= L'\0'; + } + + return hr; } #endif // FEATURE_PAL || !PLATFORM_UNIX -STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) { HRESULT hr = S_OK; char* pszDestEnd = pszDest; @@ -4923,7 +3485,7 @@ STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, cons // ASSERT(cbDest == (cchDest * sizeof(char)) || // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); - + // only accept valid flags if (dwFlags & (~STRSAFE_VALID_FLAGS)) { @@ -4931,54 +3493,31 @@ STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, cons } else { - size_t cchDestCurrent; - if (dwFlags & STRSAFE_IGNORE_NULLS) { if (pszDest == NULL) { - if ((cchDest == 0) && (cbDest == 0)) - { - cchDestCurrent = 0; - } - else + if ((cchDest != 0) || (cbDest != 0)) { // NULL pszDest and non-zero cchDest/cbDest is invalid hr = STRSAFE_E_INVALID_PARAMETER; } } - else - { - hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); - - if (SUCCEEDED(hr)) - { - pszDestEnd = pszDest + cchDestCurrent; - cchRemaining = cchDest - cchDestCurrent; - } - } if (pszSrc == NULL) { pszSrc = ""; } } - else - { - hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); - - if (SUCCEEDED(hr)) - { - pszDestEnd = pszDest + cchDestCurrent; - cchRemaining = cchDest - cchDestCurrent; - } - } if (SUCCEEDED(hr)) { if (cchDest == 0) { - // only fail if there was actually src data to append + pszDestEnd = pszDest; + cchRemaining = 0; + + // only fail if there was actually src data to copy if (*pszSrc != '\0') { if (pszDest == NULL) @@ -4993,36 +3532,51 @@ STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, cons } else { - // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass - // those flags through - hr = StringCopyExWorkerA(pszDestEnd, - cchRemaining, - (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)), - pszSrc, - &pszDestEnd, - &cchRemaining, - dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); + pszDestEnd = pszDest; + cchRemaining = cchDest; + + while (cchRemaining && cchSrc && (*pszSrc != '\0')) + { + *pszDestEnd++= *pszSrc++; + cchRemaining--; + cchSrc--; + } + + if (cchRemaining > 0) + { + if (dwFlags & STRSAFE_FILL_BEHIND_NULL) + { + memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char))); + } + } + else + { + // we are going to truncate pszDest + pszDestEnd--; + cchRemaining++; + + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + + *pszDestEnd = '\0'; } } } - + if (FAILED(hr)) { if (pszDest) { - // STRSAFE_NO_TRUNCATION is taken care of by StringCopyExWorkerA() - if (dwFlags & STRSAFE_FILL_ON_FAILURE) { memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); - + if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) { pszDestEnd = pszDest; cchRemaining = cchDest; } - else - if (cchDest > 0) + else if (cchDest > 0) { pszDestEnd = pszDest + cchDest - 1; cchRemaining = 1; @@ -5032,7 +3586,7 @@ STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, cons } } - if (dwFlags & STRSAFE_NULL_ON_FAILURE) + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) { if (cchDest > 0) { @@ -5063,7 +3617,7 @@ STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, cons } #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX) -STRSAFEAPI StringCatExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +STRSAFEAPI StringCopyNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, size_t cchSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) { HRESULT hr = S_OK; WCHAR* pszDestEnd = pszDest; @@ -5071,7 +3625,7 @@ STRSAFEAPI StringCatExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, con // ASSERT(cbDest == (cchDest * sizeof(WCHAR)) || // cbDest == (cchDest * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR))); - + // only accept valid flags if (dwFlags & (~STRSAFE_VALID_FLAGS)) { @@ -5079,54 +3633,31 @@ STRSAFEAPI StringCatExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, con } else { - size_t cchDestCurrent; - if (dwFlags & STRSAFE_IGNORE_NULLS) { if (pszDest == NULL) { - if ((cchDest == 0) && (cbDest == 0)) - { - cchDestCurrent = 0; - } - else + if ((cchDest != 0) || (cbDest != 0)) { // NULL pszDest and non-zero cchDest/cbDest is invalid hr = STRSAFE_E_INVALID_PARAMETER; } } - else - { - hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); - - if (SUCCEEDED(hr)) - { - pszDestEnd = pszDest + cchDestCurrent; - cchRemaining = cchDest - cchDestCurrent; - } - } if (pszSrc == NULL) { pszSrc = u""; } } - else - { - hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); - - if (SUCCEEDED(hr)) - { - pszDestEnd = pszDest + cchDestCurrent; - cchRemaining = cchDest - cchDestCurrent; - } - } if (SUCCEEDED(hr)) { if (cchDest == 0) { - // only fail if there was actually src data to append + pszDestEnd = pszDest; + cchRemaining = 0; + + // only fail if there was actually src data to copy if (*pszSrc != L'\0') { if (pszDest == NULL) @@ -5141,15 +3672,33 @@ STRSAFEAPI StringCatExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, con } else { - // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass - // those flags through - hr = StringCopyExWorkerW(pszDestEnd, - cchRemaining, - (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)), - pszSrc, - &pszDestEnd, - &cchRemaining, - dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); + pszDestEnd = pszDest; + cchRemaining = cchDest; + + while (cchRemaining && cchSrc && (*pszSrc != L'\0')) + { + *pszDestEnd++= *pszSrc++; + cchRemaining--; + cchSrc--; + } + + if (cchRemaining > 0) + { + if (dwFlags & STRSAFE_FILL_BEHIND_NULL) + { + memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR))); + } + } + else + { + // we are going to truncate pszDest + pszDestEnd--; + cchRemaining++; + + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + + *pszDestEnd = L'\0'; } } } @@ -5158,8 +3707,6 @@ STRSAFEAPI StringCatExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, con { if (pszDest) { - // STRSAFE_NO_TRUNCATION is taken care of by StringCopyExWorkerW() - if (dwFlags & STRSAFE_FILL_ON_FAILURE) { memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); @@ -5179,7 +3726,7 @@ STRSAFEAPI StringCatExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, con } } - if (dwFlags & STRSAFE_NULL_ON_FAILURE) + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) { if (cchDest > 0) { @@ -5210,50 +3757,47 @@ STRSAFEAPI StringCatExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, con } #endif // FEATURE_PAL || !PLATFORM_UNIX -STRSAFEAPI StringCatNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend) +STRSAFEAPI StringCatWorkerA(char* pszDest, size_t cchDest, const char* pszSrc) { - HRESULT hr; - size_t cchDestCurrent; + HRESULT hr; + size_t cchDestCurrent; - hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); - if (SUCCEEDED(hr)) - { - hr = StringCopyNWorkerA(pszDest + cchDestCurrent, - cchDest - cchDestCurrent, - pszSrc, - cchMaxAppend); - } + if (SUCCEEDED(hr)) + { + hr = StringCopyWorkerA(pszDest + cchDestCurrent, + cchDest - cchDestCurrent, + pszSrc); + } - return hr; + return hr; } #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX) -STRSAFEAPI StringCatNWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchMaxAppend) +STRSAFEAPI StringCatWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc) { - HRESULT hr; - size_t cchDestCurrent; + HRESULT hr; + size_t cchDestCurrent; - hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); - if (SUCCEEDED(hr)) - { - hr = StringCopyNWorkerW(pszDest + cchDestCurrent, - cchDest - cchDestCurrent, - pszSrc, - cchMaxAppend); - } + if (SUCCEEDED(hr)) + { + hr = StringCopyWorkerW(pszDest + cchDestCurrent, + cchDest - cchDestCurrent, + pszSrc); + } - return hr; + return hr; } #endif // FEATURE_PAL || !PLATFORM_UNIX -STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) { HRESULT hr = S_OK; char* pszDestEnd = pszDest; size_t cchRemaining = 0; - size_t cchDestCurrent = 0; // ASSERT(cbDest == (cchDest * sizeof(char)) || // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); @@ -5265,6 +3809,8 @@ STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, con } else { + size_t cchDestCurrent; + if (dwFlags & STRSAFE_IGNORE_NULLS) { if (pszDest == NULL) @@ -5324,26 +3870,25 @@ STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, con } } else - { - // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass - // those flags through - hr = StringCopyNExWorkerA(pszDestEnd, - cchRemaining, - (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)), - pszSrc, - cchMaxAppend, - &pszDestEnd, - &cchRemaining, - dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); + { + // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass + // those flags through + hr = StringCopyExWorkerA(pszDestEnd, + cchRemaining, + (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)), + pszSrc, + &pszDestEnd, + &cchRemaining, + dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); } } } - + if (FAILED(hr)) { if (pszDest) { - // STRSAFE_NO_TRUNCATION is taken care of by StringCopyNExWorkerA() + // STRSAFE_NO_TRUNCATION is taken care of by StringCopyExWorkerA() if (dwFlags & STRSAFE_FILL_ON_FAILURE) { @@ -5354,7 +3899,8 @@ STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, con pszDestEnd = pszDest; cchRemaining = cchDest; } - else if (cchDest > 0) + else + if (cchDest > 0) { pszDestEnd = pszDest + cchDest - 1; cchRemaining = 1; @@ -5364,7 +3910,7 @@ STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, con } } - if (dwFlags & (STRSAFE_NULL_ON_FAILURE)) + if (dwFlags & STRSAFE_NULL_ON_FAILURE) { if (cchDest > 0) { @@ -5380,7 +3926,7 @@ STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, con if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) { - if (ppszDestEnd) + if (ppszDestEnd) { *ppszDestEnd = pszDestEnd; } @@ -5395,13 +3941,11 @@ STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, con } #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX) -STRSAFEAPI StringCatNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, size_t cchMaxAppend, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +STRSAFEAPI StringCatExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) { HRESULT hr = S_OK; WCHAR* pszDestEnd = pszDest; size_t cchRemaining = 0; - size_t cchDestCurrent = 0; - // ASSERT(cbDest == (cchDest * sizeof(WCHAR)) || // cbDest == (cchDest * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR))); @@ -5413,6 +3957,8 @@ STRSAFEAPI StringCatNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, co } else { + size_t cchDestCurrent; + if (dwFlags & STRSAFE_IGNORE_NULLS) { if (pszDest == NULL) @@ -5475,14 +4021,13 @@ STRSAFEAPI StringCatNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, co { // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass // those flags through - hr = StringCopyNExWorkerW(pszDestEnd, - cchRemaining, - (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)), - pszSrc, - cchMaxAppend, - &pszDestEnd, - &cchRemaining, - dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); + hr = StringCopyExWorkerW(pszDestEnd, + cchRemaining, + (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)), + pszSrc, + &pszDestEnd, + &cchRemaining, + dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); } } } @@ -5491,12 +4036,12 @@ STRSAFEAPI StringCatNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, co { if (pszDest) { - // STRSAFE_NO_TRUNCATION is taken care of by StringCopyNExWorkerW() + // STRSAFE_NO_TRUNCATION is taken care of by StringCopyExWorkerW() if (dwFlags & STRSAFE_FILL_ON_FAILURE) { memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); - + if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) { pszDestEnd = pszDest; @@ -5512,7 +4057,7 @@ STRSAFEAPI StringCatNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, co } } - if (dwFlags & (STRSAFE_NULL_ON_FAILURE)) + if (dwFlags & STRSAFE_NULL_ON_FAILURE) { if (cchDest > 0) { @@ -5528,7 +4073,7 @@ STRSAFEAPI StringCatNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, co if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) { - if (ppszDestEnd) + if (ppszDestEnd) { *ppszDestEnd = pszDestEnd; } @@ -5543,93 +4088,50 @@ STRSAFEAPI StringCatNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, co } #endif // FEATURE_PAL || !PLATFORM_UNIX -STRSAFEAPI StringVPrintfWorkerA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList) +STRSAFEAPI StringCatNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend) { - HRESULT hr = S_OK; - - if (cchDest == 0) - { - // can not null terminate a zero-byte dest buffer - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - int iRet; - size_t cchMax; - - // leave the last space for the null terminator - cchMax = cchDest - 1; - - iRet = _vsnprintf(pszDest, cchMax, pszFormat, argList); - // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax)); + HRESULT hr; + size_t cchDestCurrent; - if ((iRet < 0) || (((size_t)iRet) > cchMax)) - { - // need to null terminate the string - pszDest += cchMax; - *pszDest = '\0'; + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); - // we have truncated pszDest - hr = STRSAFE_E_INSUFFICIENT_BUFFER; - } - else if (((size_t)iRet) == cchMax) - { - // need to null terminate the string - pszDest += cchMax; - *pszDest = '\0'; - } - } + if (SUCCEEDED(hr)) + { + hr = StringCopyNWorkerA(pszDest + cchDestCurrent, + cchDest - cchDestCurrent, + pszSrc, + cchMaxAppend); + } return hr; } #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX) -STRSAFEAPI StringVPrintfWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszFormat, va_list argList) +STRSAFEAPI StringCatNWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchMaxAppend) { - HRESULT hr = S_OK; - - if (cchDest == 0) - { - // can not null terminate a zero-byte dest buffer - hr = STRSAFE_E_INVALID_PARAMETER; - } - else - { - int iRet; - size_t cchMax; - - // leave the last space for the null terminator - cchMax = cchDest - 1; - - iRet = _vsnwprintf(pszDest, cchMax, pszFormat, argList); - // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax)); + HRESULT hr; + size_t cchDestCurrent; - if ((iRet < 0) || (((size_t)iRet) > cchMax)) - { - // need to null terminate the string - pszDest += cchMax; - *pszDest = L'\0'; + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); - // we have truncated pszDest - hr = STRSAFE_E_INSUFFICIENT_BUFFER; - } - else if (((size_t)iRet) == cchMax) - { - // need to null terminate the string - pszDest += cchMax; - *pszDest = L'\0'; - } + if (SUCCEEDED(hr)) + { + hr = StringCopyNWorkerW(pszDest + cchDestCurrent, + cchDest - cchDestCurrent, + pszSrc, + cchMaxAppend); } return hr; } #endif // FEATURE_PAL || !PLATFORM_UNIX -STRSAFEAPI StringVPrintfExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList) +STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) { HRESULT hr = S_OK; char* pszDestEnd = pszDest; size_t cchRemaining = 0; + size_t cchDestCurrent = 0; // ASSERT(cbDest == (cchDest * sizeof(char)) || // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); @@ -5645,28 +4147,49 @@ STRSAFEAPI StringVPrintfExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, { if (pszDest == NULL) { - if ((cchDest != 0) || (cbDest != 0)) + if ((cchDest == 0) && (cbDest == 0)) + { + cchDestCurrent = 0; + } + else { // NULL pszDest and non-zero cchDest/cbDest is invalid hr = STRSAFE_E_INVALID_PARAMETER; } } + else + { + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } - if (pszFormat == NULL) + if (pszSrc == NULL) { - pszFormat = ""; + pszSrc = ""; } } - + else + { + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + if (SUCCEEDED(hr)) { if (cchDest == 0) { - pszDestEnd = pszDest; - cchRemaining = 0; - - // only fail if there was actually a non-empty format string - if (*pszFormat != '\0') + // only fail if there was actually src data to append + if (*pszSrc != '\0') { if (pszDest == NULL) { @@ -5680,46 +4203,16 @@ STRSAFEAPI StringVPrintfExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, } else { - int iRet; - size_t cchMax; - - // leave the last space for the null terminator - cchMax = cchDest - 1; - - iRet = _vsnprintf(pszDest, cchMax, pszFormat, argList); - // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax)); - - if ((iRet < 0) || (((size_t)iRet) > cchMax)) - { - // we have truncated pszDest - pszDestEnd = pszDest + cchMax; - cchRemaining = 1; - - // need to null terminate the string - *pszDestEnd = '\0'; - - hr = STRSAFE_E_INSUFFICIENT_BUFFER; - } - else if (((size_t)iRet) == cchMax) - { - // string fit perfectly - pszDestEnd = pszDest + cchMax; - cchRemaining = 1; - - // need to null terminate the string - *pszDestEnd = '\0'; - } - else if (((size_t)iRet) < cchMax) - { - // there is extra room - pszDestEnd = pszDest + iRet; - cchRemaining = cchDest - iRet; - - if (dwFlags & STRSAFE_FILL_BEHIND_NULL) - { - memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char))); - } - } + // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass + // those flags through + hr = StringCopyNExWorkerA(pszDestEnd, + cchRemaining, + (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)), + pszSrc, + cchMaxAppend, + &pszDestEnd, + &cchRemaining, + dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); } } } @@ -5728,6 +4221,8 @@ STRSAFEAPI StringVPrintfExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, { if (pszDest) { + // STRSAFE_NO_TRUNCATION is taken care of by StringCopyNExWorkerA() + if (dwFlags & STRSAFE_FILL_ON_FAILURE) { memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); @@ -5747,7 +4242,7 @@ STRSAFEAPI StringVPrintfExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, } } - if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + if (dwFlags & (STRSAFE_NULL_ON_FAILURE)) { if (cchDest > 0) { @@ -5763,7 +4258,7 @@ STRSAFEAPI StringVPrintfExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) { - if (ppszDestEnd) + if (ppszDestEnd) { *ppszDestEnd = pszDestEnd; } @@ -5778,11 +4273,13 @@ STRSAFEAPI StringVPrintfExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, } #if defined(FEATURE_PAL) || !defined(PLATFORM_UNIX) -STRSAFEAPI StringVPrintfExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const WCHAR* pszFormat, va_list argList) +STRSAFEAPI StringCatNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, size_t cchMaxAppend, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) { HRESULT hr = S_OK; WCHAR* pszDestEnd = pszDest; size_t cchRemaining = 0; + size_t cchDestCurrent = 0; + // ASSERT(cbDest == (cchDest * sizeof(WCHAR)) || // cbDest == (cchDest * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR))); @@ -5798,16 +4295,40 @@ STRSAFEAPI StringVPrintfExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, { if (pszDest == NULL) { - if ((cchDest != 0) || (cbDest != 0)) + if ((cchDest == 0) && (cbDest == 0)) + { + cchDestCurrent = 0; + } + else { // NULL pszDest and non-zero cchDest/cbDest is invalid hr = STRSAFE_E_INVALID_PARAMETER; } } + else + { + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (pszSrc == NULL) + { + pszSrc = u""; + } + } + else + { + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); - if (pszFormat == NULL) + if (SUCCEEDED(hr)) { - pszFormat = u""; + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; } } @@ -5815,11 +4336,8 @@ STRSAFEAPI StringVPrintfExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, { if (cchDest == 0) { - pszDestEnd = pszDest; - cchRemaining = 0; - - // only fail if there was actually a non-empty format string - if (*pszFormat != L'\0') + // only fail if there was actually src data to append + if (*pszSrc != L'\0') { if (pszDest == NULL) { @@ -5833,54 +4351,26 @@ STRSAFEAPI StringVPrintfExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, } else { - int iRet; - size_t cchMax; - - // leave the last space for the null terminator - cchMax = cchDest - 1; - - iRet = _vsnwprintf(pszDest, cchMax, pszFormat, argList); - // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax)); - - if ((iRet < 0) || (((size_t)iRet) > cchMax)) - { - // we have truncated pszDest - pszDestEnd = pszDest + cchMax; - cchRemaining = 1; - - // need to null terminate the string - *pszDestEnd = L'\0'; - - hr = STRSAFE_E_INSUFFICIENT_BUFFER; - } - else if (((size_t)iRet) == cchMax) - { - // string fit perfectly - pszDestEnd = pszDest + cchMax; - cchRemaining = 1; - - // need to null terminate the string - *pszDestEnd = L'\0'; - } - else if (((size_t)iRet) < cchMax) - { - // there is extra room - pszDestEnd = pszDest + iRet; - cchRemaining = cchDest - iRet; - - if (dwFlags & STRSAFE_FILL_BEHIND_NULL) - { - memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR))); - } - } + // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass + // those flags through + hr = StringCopyNExWorkerW(pszDestEnd, + cchRemaining, + (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)), + pszSrc, + cchMaxAppend, + &pszDestEnd, + &cchRemaining, + dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); } } } - + if (FAILED(hr)) { if (pszDest) { + // STRSAFE_NO_TRUNCATION is taken care of by StringCopyNExWorkerW() + if (dwFlags & STRSAFE_FILL_ON_FAILURE) { memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); @@ -5900,7 +4390,7 @@ STRSAFEAPI StringVPrintfExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, } } - if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + if (dwFlags & (STRSAFE_NULL_ON_FAILURE)) { if (cchDest > 0) { @@ -5916,7 +4406,7 @@ STRSAFEAPI StringVPrintfExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) { - if (ppszDestEnd) + if (ppszDestEnd) { *ppszDestEnd = pszDestEnd; } diff --git a/src/pal/inc/unixasmmacros.inc b/src/pal/inc/unixasmmacros.inc index 7186645..e7a5eba 100644 --- a/src/pal/inc/unixasmmacros.inc +++ b/src/pal/inc/unixasmmacros.inc @@ -28,7 +28,9 @@ .equiv \New, \Old .endm -#if defined(_AMD64_) +#if defined(_X86_) +#include "unixasmmacrosx86.inc" +#elif defined(_AMD64_) #include "unixasmmacrosamd64.inc" #elif defined(_ARM_) #include "unixasmmacrosarm.inc" diff --git a/src/pal/inc/unixasmmacrosamd64.inc b/src/pal/inc/unixasmmacrosamd64.inc index f221b44..c3321ce 100644 --- a/src/pal/inc/unixasmmacrosamd64.inc +++ b/src/pal/inc/unixasmmacrosamd64.inc @@ -8,7 +8,7 @@ #if defined(__APPLE__) .cfi_personality 0x9b, C_FUNC(\Handler) // 0x9b == DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4 #else - .cfi_personality 0, C_FUNC(\Handler) // 0 == DW_EH_PE_absptr + .cfi_personality 0x1b, C_FUNC(\Handler) // 0x1b == DW_EH_PE_pcrel | DW_EH_PE_sdata4 #endif .endif .endm diff --git a/src/pal/inc/unixasmmacrosarm.inc b/src/pal/inc/unixasmmacrosarm.inc index 14b0b41..76ea5eb 100644 --- a/src/pal/inc/unixasmmacrosarm.inc +++ b/src/pal/inc/unixasmmacrosarm.inc @@ -229,7 +229,8 @@ C_FUNC(\Name\()_End): .endm .macro EPILOG_STACK_RESTORE_OFFSET Register, Offset - sub sp, \Register, \Offset + sub \Register, \Offset + mov sp, \Register .endm .macro EPILOG_BRANCH Target diff --git a/src/pal/inc/unixasmmacrosarm64.inc b/src/pal/inc/unixasmmacrosarm64.inc index ae60db4..6014205 100644 --- a/src/pal/inc/unixasmmacrosarm64.inc +++ b/src/pal/inc/unixasmmacrosarm64.inc @@ -5,7 +5,7 @@ .macro NESTED_ENTRY Name, Section, Handler LEAF_ENTRY \Name, \Section .ifnc \Handler, NoHandler - .cfi_personality 0, C_FUNC(\Handler) // 0 == DW_EH_PE_absptr + .cfi_personality 0x1b, C_FUNC(\Handler) // 0x1b == DW_EH_PE_pcrel | DW_EH_PE_sdata4 .endif .endm diff --git a/src/pal/inc/unixasmmacrosx86.inc b/src/pal/inc/unixasmmacrosx86.inc new file mode 100644 index 0000000..77b3a63 --- /dev/null +++ b/src/pal/inc/unixasmmacrosx86.inc @@ -0,0 +1,87 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +.macro NESTED_ENTRY Name, Section, Handler + LEAF_ENTRY \Name, \Section + .ifnc \Handler, NoHandler + .cfi_personality 0x1b, C_FUNC(\Handler) // 0x1b == DW_EH_PE_pcrel | DW_EH_PE_sdata4 + .endif +.endm + +.macro NESTED_END Name, Section + LEAF_END \Name, \Section +.endm + +.macro LEAF_ENTRY Name, Section + .global C_FUNC(\Name) + .type \Name, %function +C_FUNC(\Name): + .cfi_startproc +.endm + +.macro PATCH_LABEL Name + .global C_FUNC(\Name) +C_FUNC(\Name): +.endm + +.macro LEAF_END Name, Section + .size \Name, .-\Name + .cfi_endproc +.endm + +.macro LEAF_END_MARKED Name, Section +C_FUNC(\Name\()_End): + .global C_FUNC(\Name\()_End) + LEAF_END \Name, \Section +.endm + +.macro PROLOG_BEG + push ebp + .cfi_def_cfa_offset 8 + .cfi_offset ebp, -8 + mov ebp, esp +.endm + +.macro PROLOG_PUSH Reg + push \Reg + .cfi_adjust_cfa_offset 4 + .cfi_rel_offset \Reg, 0 +.endm + +.macro PROLOG_END + .cfi_def_cfa_register ebp + .cfi_def_cfa_offset 8 +.endm + +.macro EPILOG_BEG +.endm + +.macro EPILOG_POP Reg + pop \Reg + .cfi_restore \Reg +.endm + +.macro EPILOG_END + pop ebp +.endm + +.macro PREPARE_EXTERNAL_VAR Name, Reg +.att_syntax + call 0f +0: + popl %\Reg +1: + addl $_GLOBAL_OFFSET_TABLE_ + (1b - 0b), %\Reg + movl C_FUNC(\Name)@GOT(%\Reg), %\Reg +.intel_syntax noprefix +.endm + +.macro CHECK_STACK_ALIGNMENT +#ifdef _DEBUG + test esp, 0Fh + je 0f + int3 +0: +#endif // _DEBUG +.endm diff --git a/src/pal/prebuilt/idl/clrdata_i.c b/src/pal/prebuilt/idl/clrdata_i.cpp similarity index 100% rename from src/pal/prebuilt/idl/clrdata_i.c rename to src/pal/prebuilt/idl/clrdata_i.cpp diff --git a/src/pal/prebuilt/idl/clrinternal_i.c b/src/pal/prebuilt/idl/clrinternal_i.cpp similarity index 100% rename from src/pal/prebuilt/idl/clrinternal_i.c rename to src/pal/prebuilt/idl/clrinternal_i.cpp diff --git a/src/pal/prebuilt/idl/clrprivappxhosting_i.c b/src/pal/prebuilt/idl/clrprivappxhosting_i.cpp similarity index 100% rename from src/pal/prebuilt/idl/clrprivappxhosting_i.c rename to src/pal/prebuilt/idl/clrprivappxhosting_i.cpp diff --git a/src/pal/prebuilt/idl/clrprivbinding_i.c b/src/pal/prebuilt/idl/clrprivbinding_i.cpp similarity index 100% rename from src/pal/prebuilt/idl/clrprivbinding_i.c rename to src/pal/prebuilt/idl/clrprivbinding_i.cpp diff --git a/src/pal/prebuilt/idl/clrprivhosting_i.c b/src/pal/prebuilt/idl/clrprivhosting_i.cpp similarity index 100% rename from src/pal/prebuilt/idl/clrprivhosting_i.c rename to src/pal/prebuilt/idl/clrprivhosting_i.cpp diff --git a/src/pal/prebuilt/idl/clrprivruntimebinders_i.c b/src/pal/prebuilt/idl/clrprivruntimebinders_i.cpp similarity index 100% rename from src/pal/prebuilt/idl/clrprivruntimebinders_i.c rename to src/pal/prebuilt/idl/clrprivruntimebinders_i.cpp diff --git a/src/pal/prebuilt/idl/cordebug_i.c b/src/pal/prebuilt/idl/cordebug_i.c deleted file mode 100644 index e3c8d2e..0000000 --- a/src/pal/prebuilt/idl/cordebug_i.c +++ /dev/null @@ -1,451 +0,0 @@ - - -/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ - -/* link this file in with the server and any clients */ - - - /* File created by MIDL compiler version 8.00.0613 */ -/* at Mon Jan 18 19:14:07 2038 - */ -/* Compiler settings for C:/ssd/coreclr/src/inc/cordebug.idl: - Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.00.0613 - protocol : dce , ms_ext, c_ext, robust - error checks: allocation ref bounds_check enum stub_data - VC __declspec() decoration level: - __declspec(uuid()), __declspec(selectany), __declspec(novtable) - DECLSPEC_UUID(), MIDL_INTERFACE() -*/ -/* @@MIDL_FILE_HEADING( ) */ - -#pragma warning( disable: 4049 ) /* more than 64k source lines */ - - -#ifdef __cplusplus -extern "C"{ -#endif - - -#include -#include - -#ifdef _MIDL_USE_GUIDDEF_ - -#ifndef INITGUID -#define INITGUID -#include -#undef INITGUID -#else -#include -#endif - -#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ - DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) - -#else // !_MIDL_USE_GUIDDEF_ - -#ifndef __IID_DEFINED__ -#define __IID_DEFINED__ - -typedef struct _IID -{ - unsigned long x; - unsigned short s1; - unsigned short s2; - unsigned char c[8]; -} IID; - -#endif // __IID_DEFINED__ - -#ifndef CLSID_DEFINED -#define CLSID_DEFINED -typedef IID CLSID; -#endif // CLSID_DEFINED - -#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ - const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} - -#endif !_MIDL_USE_GUIDDEF_ - -MIDL_DEFINE_GUID(IID, IID_ICorDebugDataTarget,0xFE06DC28,0x49FB,0x4636,0xA4,0xA3,0xE8,0x0D,0xB4,0xAE,0x11,0x6C); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugStaticFieldSymbol,0xCBF9DA63,0xF68D,0x4BBB,0xA2,0x1C,0x15,0xA4,0x5E,0xAA,0xDF,0x5B); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugInstanceFieldSymbol,0xA074096B,0x3ADC,0x4485,0x81,0xDA,0x68,0xC7,0xA4,0xEA,0x52,0xDB); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugVariableSymbol,0x707E8932,0x1163,0x48D9,0x8A,0x93,0xF5,0xB1,0xF4,0x80,0xFB,0xB7); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugMemoryBuffer,0x677888B3,0xD160,0x4B8C,0xA7,0x3B,0xD7,0x9E,0x6A,0xAA,0x1D,0x13); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugMergedAssemblyRecord,0xFAA8637B,0x3BBE,0x4671,0x8E,0x26,0x3B,0x59,0x87,0x5B,0x92,0x2A); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugSymbolProvider,0x3948A999,0xFD8A,0x4C38,0xA7,0x08,0x8A,0x71,0xE9,0xB0,0x4D,0xBB); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugSymbolProvider2,0xF9801807,0x4764,0x4330,0x9E,0x67,0x4F,0x68,0x50,0x94,0x16,0x5E); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugVirtualUnwinder,0xF69126B7,0xC787,0x4F6B,0xAE,0x96,0xA5,0x69,0x78,0x6F,0xC6,0x70); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugDataTarget2,0x2eb364da,0x605b,0x4e8d,0xb3,0x33,0x33,0x94,0xc4,0x82,0x8d,0x41); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugLoadedModule,0x817F343A,0x6630,0x4578,0x96,0xC5,0xD1,0x1B,0xC0,0xEC,0x5E,0xE2); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugDataTarget3,0xD05E60C3,0x848C,0x4E7D,0x89,0x4E,0x62,0x33,0x20,0xFF,0x6A,0xFA); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugDataTarget4,0xE799DC06,0xE099,0x4713,0xBD,0xD9,0x90,0x6D,0x3C,0xC0,0x2C,0xF2); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugMutableDataTarget,0xA1B8A756,0x3CB6,0x4CCB,0x97,0x9F,0x3D,0xF9,0x99,0x67,0x3A,0x59); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugMetaDataLocator,0x7cef8ba9,0x2ef7,0x42bf,0x97,0x3f,0x41,0x71,0x47,0x4f,0x87,0xd9); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugManagedCallback,0x3d6f5f60,0x7538,0x11d3,0x8d,0x5b,0x00,0x10,0x4b,0x35,0xe7,0xef); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugManagedCallback3,0x264EA0FC,0x2591,0x49AA,0x86,0x8E,0x83,0x5E,0x65,0x15,0x32,0x3F); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugManagedCallback2,0x250E5EEA,0xDB5C,0x4C76,0xB6,0xF3,0x8C,0x46,0xF1,0x2E,0x32,0x03); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugUnmanagedCallback,0x5263E909,0x8CB5,0x11d3,0xBD,0x2F,0x00,0x00,0xF8,0x08,0x49,0xBD); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebug,0x3d6f5f61,0x7538,0x11d3,0x8d,0x5b,0x00,0x10,0x4b,0x35,0xe7,0xef); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugRemoteTarget,0xC3ED8383,0x5A49,0x4cf5,0xB4,0xB7,0x01,0x86,0x4D,0x9E,0x58,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugRemote,0xD5EBB8E2,0x7BBE,0x4c1d,0x98,0xA6,0xA3,0xC0,0x4C,0xBD,0xEF,0x64); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebug2,0xECCCCF2E,0xB286,0x4b3e,0xA9,0x83,0x86,0x0A,0x87,0x93,0xD1,0x05); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugController,0x3d6f5f62,0x7538,0x11d3,0x8d,0x5b,0x00,0x10,0x4b,0x35,0xe7,0xef); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugAppDomain,0x3d6f5f63,0x7538,0x11d3,0x8d,0x5b,0x00,0x10,0x4b,0x35,0xe7,0xef); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugAppDomain2,0x096E81D5,0xECDA,0x4202,0x83,0xF5,0xC6,0x59,0x80,0xA9,0xEF,0x75); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugEnum,0xCC7BCB01,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugGuidToTypeEnum,0x6164D242,0x1015,0x4BD6,0x8C,0xBE,0xD0,0xDB,0xD4,0xB8,0x27,0x5A); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugAppDomain3,0x8CB96A16,0xB588,0x42E2,0xB7,0x1C,0xDD,0x84,0x9F,0xC2,0xEC,0xCC); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugAppDomain4,0xFB99CC40,0x83BE,0x4724,0xAB,0x3B,0x76,0x8E,0x79,0x6E,0xBA,0xC2); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugAssembly,0xdf59507c,0xd47a,0x459e,0xbc,0xe2,0x64,0x27,0xea,0xc8,0xfd,0x06); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugAssembly2,0x426d1f9e,0x6dd4,0x44c8,0xae,0xc7,0x26,0xcd,0xba,0xf4,0xe3,0x98); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugAssembly3,0x76361AB2,0x8C86,0x4FE9,0x96,0xF2,0xF7,0x3D,0x88,0x43,0x57,0x0A); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugHeapEnum,0x76D7DAB8,0xD044,0x11DF,0x9A,0x15,0x7E,0x29,0xDF,0xD7,0x20,0x85); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugHeapSegmentEnum,0xA2FA0F8E,0xD045,0x11DF,0xAC,0x8E,0xCE,0x2A,0xDF,0xD7,0x20,0x85); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugGCReferenceEnum,0x7F3C24D3,0x7E1D,0x4245,0xAC,0x3A,0xF7,0x2F,0x88,0x59,0xC8,0x0C); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess,0x3d6f5f64,0x7538,0x11d3,0x8d,0x5b,0x00,0x10,0x4b,0x35,0xe7,0xef); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess2,0xAD1B3588,0x0EF0,0x4744,0xA4,0x96,0xAA,0x09,0xA9,0xF8,0x03,0x71); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess3,0x2EE06488,0xC0D4,0x42B1,0xB2,0x6D,0xF3,0x79,0x5E,0xF6,0x06,0xFB); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess5,0x21e9d9c0,0xfcb8,0x11df,0x8c,0xff,0x08,0x00,0x20,0x0c,0x9a,0x66); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugDebugEvent,0x41BD395D,0xDE99,0x48F1,0xBF,0x7A,0xCC,0x0F,0x44,0xA6,0xD2,0x81); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess6,0x11588775,0x7205,0x4CEB,0xA4,0x1A,0x93,0x75,0x3C,0x31,0x53,0xE9); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess7,0x9B2C54E4,0x119F,0x4D6F,0xB4,0x02,0x52,0x76,0x03,0x26,0x6D,0x69); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess8,0x2E6F28C1,0x85EB,0x4141,0x80,0xAD,0x0A,0x90,0x94,0x4B,0x96,0x39); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugModuleDebugEvent,0x51A15E8D,0x9FFF,0x4864,0x9B,0x87,0xF4,0xFB,0xDE,0xA7,0x47,0xA2); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugExceptionDebugEvent,0xAF79EC94,0x4752,0x419C,0xA6,0x26,0x5F,0xB1,0xCC,0x1A,0x5A,0xB7); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugBreakpoint,0xCC7BCAE8,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugFunctionBreakpoint,0xCC7BCAE9,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugModuleBreakpoint,0xCC7BCAEA,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugValueBreakpoint,0xCC7BCAEB,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugStepper,0xCC7BCAEC,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugStepper2,0xC5B6E9C3,0xE7D1,0x4a8e,0x87,0x3B,0x7F,0x04,0x7F,0x07,0x06,0xF7); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugRegisterSet,0xCC7BCB0B,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugRegisterSet2,0x6DC7BA3F,0x89BA,0x4459,0x9E,0xC1,0x9D,0x60,0x93,0x7B,0x46,0x8D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugThread,0x938c6d66,0x7fb6,0x4f69,0xb3,0x89,0x42,0x5b,0x89,0x87,0x32,0x9b); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugThread2,0x2BD956D9,0x7B07,0x4bef,0x8A,0x98,0x12,0xAA,0x86,0x24,0x17,0xC5); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugThread3,0xF8544EC3,0x5E4E,0x46c7,0x8D,0x3E,0xA5,0x2B,0x84,0x05,0xB1,0xF5); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugThread4,0x1A1F204B,0x1C66,0x4637,0x82,0x3F,0x3E,0xE6,0xC7,0x44,0xA6,0x9C); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugStackWalk,0xA0647DE9,0x55DE,0x4816,0x92,0x9C,0x38,0x52,0x71,0xC6,0x4C,0xF7); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugChain,0xCC7BCAEE,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugFrame,0xCC7BCAEF,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugInternalFrame,0xB92CC7F7,0x9D2D,0x45c4,0xBC,0x2B,0x62,0x1F,0xCC,0x9D,0xFB,0xF4); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugInternalFrame2,0xC0815BDC,0xCFAB,0x447e,0xA7,0x79,0xC1,0x16,0xB4,0x54,0xEB,0x5B); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugILFrame,0x03E26311,0x4F76,0x11d3,0x88,0xC6,0x00,0x60,0x97,0x94,0x54,0x18); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugILFrame2,0x5D88A994,0x6C30,0x479b,0x89,0x0F,0xBC,0xEF,0x88,0xB1,0x29,0xA5); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugILFrame3,0x9A9E2ED6,0x04DF,0x4FE0,0xBB,0x50,0xCA,0xB6,0x41,0x26,0xAD,0x24); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugILFrame4,0xAD914A30,0xC6D1,0x4AC5,0x9C,0x5E,0x57,0x7F,0x3B,0xAA,0x8A,0x45); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugNativeFrame,0x03E26314,0x4F76,0x11d3,0x88,0xC6,0x00,0x60,0x97,0x94,0x54,0x18); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugNativeFrame2,0x35389FF1,0x3684,0x4c55,0xA2,0xEE,0x21,0x0F,0x26,0xC6,0x0E,0x5E); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugModule3,0x86F012BF,0xFF15,0x4372,0xBD,0x30,0xB6,0xF1,0x1C,0xAA,0xE1,0xDD); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugRuntimeUnwindableFrame,0x879CAC0A,0x4A53,0x4668,0xB8,0xE3,0xCB,0x84,0x73,0xCB,0x18,0x7F); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugModule,0xdba2d8c1,0xe5c5,0x4069,0x8c,0x13,0x10,0xa7,0xc6,0xab,0xf4,0x3d); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugModule2,0x7FCC5FB5,0x49C0,0x41de,0x99,0x38,0x3B,0x88,0xB5,0xB9,0xAD,0xD7); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugFunction,0xCC7BCAF3,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugFunction2,0xEF0C490B,0x94C3,0x4e4d,0xB6,0x29,0xDD,0xC1,0x34,0xC5,0x32,0xD8); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugFunction3,0x09B70F28,0xE465,0x482D,0x99,0xE0,0x81,0xA1,0x65,0xEB,0x05,0x32); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugCode,0xCC7BCAF4,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugCode2,0x5F696509,0x452F,0x4436,0xA3,0xFE,0x4D,0x11,0xFE,0x7E,0x23,0x47); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugCode3,0xD13D3E88,0xE1F2,0x4020,0xAA,0x1D,0x3D,0x16,0x2D,0xCB,0xE9,0x66); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugILCode,0x598D46C2,0xC877,0x42A7,0x89,0xD2,0x3D,0x0C,0x7F,0x1C,0x12,0x64); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugILCode2,0x46586093,0xD3F5,0x4DB6,0xAC,0xDB,0x95,0x5B,0xCE,0x22,0x8C,0x15); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugClass,0xCC7BCAF5,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugClass2,0xB008EA8D,0x7AB1,0x43f7,0xBB,0x20,0xFB,0xB5,0xA0,0x40,0x38,0xAE); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugEval,0xCC7BCAF6,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugEval2,0xFB0D9CE7,0xBE66,0x4683,0x9D,0x32,0xA4,0x2A,0x04,0xE2,0xFD,0x91); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugValue,0xCC7BCAF7,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugValue2,0x5E0B54E7,0xD88A,0x4626,0x94,0x20,0xA6,0x91,0xE0,0xA7,0x8B,0x49); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugValue3,0x565005FC,0x0F8A,0x4F3E,0x9E,0xDB,0x83,0x10,0x2B,0x15,0x65,0x95); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugGenericValue,0xCC7BCAF8,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugReferenceValue,0xCC7BCAF9,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugHeapValue,0xCC7BCAFA,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugHeapValue2,0xE3AC4D6C,0x9CB7,0x43e6,0x96,0xCC,0xB2,0x15,0x40,0xE5,0x08,0x3C); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugHeapValue3,0xA69ACAD8,0x2374,0x46e9,0x9F,0xF8,0xB1,0xF1,0x41,0x20,0xD2,0x96); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugObjectValue,0x18AD3D6E,0xB7D2,0x11d2,0xBD,0x04,0x00,0x00,0xF8,0x08,0x49,0xBD); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugObjectValue2,0x49E4A320,0x4A9B,0x4eca,0xB1,0x05,0x22,0x9F,0xB7,0xD5,0x00,0x9F); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugBoxValue,0xCC7BCAFC,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugStringValue,0xCC7BCAFD,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugArrayValue,0x0405B0DF,0xA660,0x11d2,0xBD,0x02,0x00,0x00,0xF8,0x08,0x49,0xBD); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugHandleValue,0x029596E8,0x276B,0x46a1,0x98,0x21,0x73,0x2E,0x96,0xBB,0xB0,0x0B); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugContext,0xCC7BCB00,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugComObjectValue,0x5F69C5E5,0x3E12,0x42DF,0xB3,0x71,0xF9,0xD7,0x61,0xD6,0xEE,0x24); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugObjectEnum,0xCC7BCB02,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugBreakpointEnum,0xCC7BCB03,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugStepperEnum,0xCC7BCB04,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugProcessEnum,0xCC7BCB05,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugThreadEnum,0xCC7BCB06,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugFrameEnum,0xCC7BCB07,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugChainEnum,0xCC7BCB08,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugModuleEnum,0xCC7BCB09,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugValueEnum,0xCC7BCB0A,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugCodeEnum,0x55E96461,0x9645,0x45e4,0xA2,0xFF,0x03,0x67,0x87,0x7A,0xBC,0xDE); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugTypeEnum,0x10F27499,0x9DF2,0x43ce,0x83,0x33,0xA3,0x21,0xD7,0xC9,0x9C,0xB4); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugType,0xD613F0BB,0xACE1,0x4c19,0xBD,0x72,0xE4,0xC0,0x8D,0x5D,0xA7,0xF5); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugErrorInfoEnum,0xF0E18809,0x72B5,0x11d2,0x97,0x6F,0x00,0xA0,0xC9,0xB4,0xD5,0x0C); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugAppDomainEnum,0x63ca1b24,0x4359,0x4883,0xbd,0x57,0x13,0xf8,0x15,0xf5,0x87,0x44); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugAssemblyEnum,0x4a2a1ec9,0x85ec,0x4bfb,0x9f,0x15,0xa8,0x9f,0xdf,0xe0,0xfe,0x83); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugBlockingObjectEnum,0x976A6278,0x134A,0x4a81,0x81,0xA3,0x8F,0x27,0x79,0x43,0xF4,0xC3); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugMDA,0xCC726F2F,0x1DB7,0x459b,0xB0,0xEC,0x05,0xF0,0x1D,0x84,0x1B,0x42); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugEditAndContinueErrorInfo,0x8D600D41,0xF4F6,0x4cb3,0xB7,0xEC,0x7B,0xD1,0x64,0x94,0x40,0x36); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugEditAndContinueSnapshot,0x6DC3FA01,0xD7CB,0x11d2,0x8A,0x95,0x00,0x80,0xC7,0x92,0xE5,0xD8); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugExceptionObjectCallStackEnum,0xED775530,0x4DC4,0x41F7,0x86,0xD0,0x9E,0x2D,0xEF,0x7D,0xFC,0x66); - - -MIDL_DEFINE_GUID(IID, IID_ICorDebugExceptionObjectValue,0xAE4CA65D,0x59DD,0x42A2,0x83,0xA5,0x57,0xE8,0xA0,0x8D,0x87,0x19); - - -MIDL_DEFINE_GUID(IID, LIBID_CORDBLib,0x53D13620,0xF417,0x11d1,0x97,0x62,0xA6,0x38,0x26,0xA4,0xF2,0x55); - - -MIDL_DEFINE_GUID(CLSID, CLSID_CorDebug,0x6fef44d0,0x39e7,0x4c77,0xbe,0x8e,0xc9,0xf8,0xcf,0x98,0x86,0x30); - - -MIDL_DEFINE_GUID(CLSID, CLSID_EmbeddedCLRCorDebug,0x211f1254,0xbc7e,0x4af5,0xb9,0xaa,0x06,0x73,0x08,0xd8,0x3d,0xd1); - -#undef MIDL_DEFINE_GUID - -#ifdef __cplusplus -} -#endif - - - diff --git a/src/pal/prebuilt/idl/cordebug_i.cpp b/src/pal/prebuilt/idl/cordebug_i.cpp new file mode 100644 index 0000000..dd69e57 --- /dev/null +++ b/src/pal/prebuilt/idl/cordebug_i.cpp @@ -0,0 +1,463 @@ + + +/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ + +/* link this file in with the server and any clients */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* at Fri Sep 23 15:43:16 2016 + */ +/* Compiler settings for cordebug.idl: + Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.00.0603 + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +#ifdef __cplusplus +extern "C"{ +#endif + + +#include +#include + +#ifdef _MIDL_USE_GUIDDEF_ + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) + +#else // !_MIDL_USE_GUIDDEF_ + +#ifndef __IID_DEFINED__ +#define __IID_DEFINED__ + +typedef struct _IID +{ + unsigned long x; + unsigned short s1; + unsigned short s2; + unsigned char c[8]; +} IID; + +#endif // __IID_DEFINED__ + +#ifndef CLSID_DEFINED +#define CLSID_DEFINED +typedef IID CLSID; +#endif // CLSID_DEFINED + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} + +#endif !_MIDL_USE_GUIDDEF_ + +MIDL_DEFINE_GUID(IID, IID_ICorDebugDataTarget,0xFE06DC28,0x49FB,0x4636,0xA4,0xA3,0xE8,0x0D,0xB4,0xAE,0x11,0x6C); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugStaticFieldSymbol,0xCBF9DA63,0xF68D,0x4BBB,0xA2,0x1C,0x15,0xA4,0x5E,0xAA,0xDF,0x5B); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugInstanceFieldSymbol,0xA074096B,0x3ADC,0x4485,0x81,0xDA,0x68,0xC7,0xA4,0xEA,0x52,0xDB); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugVariableSymbol,0x707E8932,0x1163,0x48D9,0x8A,0x93,0xF5,0xB1,0xF4,0x80,0xFB,0xB7); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugMemoryBuffer,0x677888B3,0xD160,0x4B8C,0xA7,0x3B,0xD7,0x9E,0x6A,0xAA,0x1D,0x13); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugMergedAssemblyRecord,0xFAA8637B,0x3BBE,0x4671,0x8E,0x26,0x3B,0x59,0x87,0x5B,0x92,0x2A); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugSymbolProvider,0x3948A999,0xFD8A,0x4C38,0xA7,0x08,0x8A,0x71,0xE9,0xB0,0x4D,0xBB); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugSymbolProvider2,0xF9801807,0x4764,0x4330,0x9E,0x67,0x4F,0x68,0x50,0x94,0x16,0x5E); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugVirtualUnwinder,0xF69126B7,0xC787,0x4F6B,0xAE,0x96,0xA5,0x69,0x78,0x6F,0xC6,0x70); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugDataTarget2,0x2eb364da,0x605b,0x4e8d,0xb3,0x33,0x33,0x94,0xc4,0x82,0x8d,0x41); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugLoadedModule,0x817F343A,0x6630,0x4578,0x96,0xC5,0xD1,0x1B,0xC0,0xEC,0x5E,0xE2); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugDataTarget3,0xD05E60C3,0x848C,0x4E7D,0x89,0x4E,0x62,0x33,0x20,0xFF,0x6A,0xFA); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugDataTarget4,0xE799DC06,0xE099,0x4713,0xBD,0xD9,0x90,0x6D,0x3C,0xC0,0x2C,0xF2); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugMutableDataTarget,0xA1B8A756,0x3CB6,0x4CCB,0x97,0x9F,0x3D,0xF9,0x99,0x67,0x3A,0x59); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugMetaDataLocator,0x7cef8ba9,0x2ef7,0x42bf,0x97,0x3f,0x41,0x71,0x47,0x4f,0x87,0xd9); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugManagedCallback,0x3d6f5f60,0x7538,0x11d3,0x8d,0x5b,0x00,0x10,0x4b,0x35,0xe7,0xef); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugManagedCallback3,0x264EA0FC,0x2591,0x49AA,0x86,0x8E,0x83,0x5E,0x65,0x15,0x32,0x3F); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugManagedCallback2,0x250E5EEA,0xDB5C,0x4C76,0xB6,0xF3,0x8C,0x46,0xF1,0x2E,0x32,0x03); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugUnmanagedCallback,0x5263E909,0x8CB5,0x11d3,0xBD,0x2F,0x00,0x00,0xF8,0x08,0x49,0xBD); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebug,0x3d6f5f61,0x7538,0x11d3,0x8d,0x5b,0x00,0x10,0x4b,0x35,0xe7,0xef); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugRemoteTarget,0xC3ED8383,0x5A49,0x4cf5,0xB4,0xB7,0x01,0x86,0x4D,0x9E,0x58,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugRemote,0xD5EBB8E2,0x7BBE,0x4c1d,0x98,0xA6,0xA3,0xC0,0x4C,0xBD,0xEF,0x64); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebug2,0xECCCCF2E,0xB286,0x4b3e,0xA9,0x83,0x86,0x0A,0x87,0x93,0xD1,0x05); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugController,0x3d6f5f62,0x7538,0x11d3,0x8d,0x5b,0x00,0x10,0x4b,0x35,0xe7,0xef); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugAppDomain,0x3d6f5f63,0x7538,0x11d3,0x8d,0x5b,0x00,0x10,0x4b,0x35,0xe7,0xef); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugAppDomain2,0x096E81D5,0xECDA,0x4202,0x83,0xF5,0xC6,0x59,0x80,0xA9,0xEF,0x75); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugEnum,0xCC7BCB01,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugGuidToTypeEnum,0x6164D242,0x1015,0x4BD6,0x8C,0xBE,0xD0,0xDB,0xD4,0xB8,0x27,0x5A); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugAppDomain3,0x8CB96A16,0xB588,0x42E2,0xB7,0x1C,0xDD,0x84,0x9F,0xC2,0xEC,0xCC); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugAppDomain4,0xFB99CC40,0x83BE,0x4724,0xAB,0x3B,0x76,0x8E,0x79,0x6E,0xBA,0xC2); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugAssembly,0xdf59507c,0xd47a,0x459e,0xbc,0xe2,0x64,0x27,0xea,0xc8,0xfd,0x06); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugAssembly2,0x426d1f9e,0x6dd4,0x44c8,0xae,0xc7,0x26,0xcd,0xba,0xf4,0xe3,0x98); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugAssembly3,0x76361AB2,0x8C86,0x4FE9,0x96,0xF2,0xF7,0x3D,0x88,0x43,0x57,0x0A); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugHeapEnum,0x76D7DAB8,0xD044,0x11DF,0x9A,0x15,0x7E,0x29,0xDF,0xD7,0x20,0x85); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugHeapSegmentEnum,0xA2FA0F8E,0xD045,0x11DF,0xAC,0x8E,0xCE,0x2A,0xDF,0xD7,0x20,0x85); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugGCReferenceEnum,0x7F3C24D3,0x7E1D,0x4245,0xAC,0x3A,0xF7,0x2F,0x88,0x59,0xC8,0x0C); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess,0x3d6f5f64,0x7538,0x11d3,0x8d,0x5b,0x00,0x10,0x4b,0x35,0xe7,0xef); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess2,0xAD1B3588,0x0EF0,0x4744,0xA4,0x96,0xAA,0x09,0xA9,0xF8,0x03,0x71); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess3,0x2EE06488,0xC0D4,0x42B1,0xB2,0x6D,0xF3,0x79,0x5E,0xF6,0x06,0xFB); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess5,0x21e9d9c0,0xfcb8,0x11df,0x8c,0xff,0x08,0x00,0x20,0x0c,0x9a,0x66); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugDebugEvent,0x41BD395D,0xDE99,0x48F1,0xBF,0x7A,0xCC,0x0F,0x44,0xA6,0xD2,0x81); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess6,0x11588775,0x7205,0x4CEB,0xA4,0x1A,0x93,0x75,0x3C,0x31,0x53,0xE9); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess7,0x9B2C54E4,0x119F,0x4D6F,0xB4,0x02,0x52,0x76,0x03,0x26,0x6D,0x69); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugProcess8,0x2E6F28C1,0x85EB,0x4141,0x80,0xAD,0x0A,0x90,0x94,0x4B,0x96,0x39); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugModuleDebugEvent,0x51A15E8D,0x9FFF,0x4864,0x9B,0x87,0xF4,0xFB,0xDE,0xA7,0x47,0xA2); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugExceptionDebugEvent,0xAF79EC94,0x4752,0x419C,0xA6,0x26,0x5F,0xB1,0xCC,0x1A,0x5A,0xB7); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugBreakpoint,0xCC7BCAE8,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugFunctionBreakpoint,0xCC7BCAE9,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugModuleBreakpoint,0xCC7BCAEA,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugValueBreakpoint,0xCC7BCAEB,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugStepper,0xCC7BCAEC,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugStepper2,0xC5B6E9C3,0xE7D1,0x4a8e,0x87,0x3B,0x7F,0x04,0x7F,0x07,0x06,0xF7); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugRegisterSet,0xCC7BCB0B,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugRegisterSet2,0x6DC7BA3F,0x89BA,0x4459,0x9E,0xC1,0x9D,0x60,0x93,0x7B,0x46,0x8D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugThread,0x938c6d66,0x7fb6,0x4f69,0xb3,0x89,0x42,0x5b,0x89,0x87,0x32,0x9b); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugThread2,0x2BD956D9,0x7B07,0x4bef,0x8A,0x98,0x12,0xAA,0x86,0x24,0x17,0xC5); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugThread3,0xF8544EC3,0x5E4E,0x46c7,0x8D,0x3E,0xA5,0x2B,0x84,0x05,0xB1,0xF5); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugThread4,0x1A1F204B,0x1C66,0x4637,0x82,0x3F,0x3E,0xE6,0xC7,0x44,0xA6,0x9C); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugStackWalk,0xA0647DE9,0x55DE,0x4816,0x92,0x9C,0x38,0x52,0x71,0xC6,0x4C,0xF7); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugChain,0xCC7BCAEE,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugFrame,0xCC7BCAEF,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugInternalFrame,0xB92CC7F7,0x9D2D,0x45c4,0xBC,0x2B,0x62,0x1F,0xCC,0x9D,0xFB,0xF4); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugInternalFrame2,0xC0815BDC,0xCFAB,0x447e,0xA7,0x79,0xC1,0x16,0xB4,0x54,0xEB,0x5B); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugILFrame,0x03E26311,0x4F76,0x11d3,0x88,0xC6,0x00,0x60,0x97,0x94,0x54,0x18); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugILFrame2,0x5D88A994,0x6C30,0x479b,0x89,0x0F,0xBC,0xEF,0x88,0xB1,0x29,0xA5); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugILFrame3,0x9A9E2ED6,0x04DF,0x4FE0,0xBB,0x50,0xCA,0xB6,0x41,0x26,0xAD,0x24); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugILFrame4,0xAD914A30,0xC6D1,0x4AC5,0x9C,0x5E,0x57,0x7F,0x3B,0xAA,0x8A,0x45); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugNativeFrame,0x03E26314,0x4F76,0x11d3,0x88,0xC6,0x00,0x60,0x97,0x94,0x54,0x18); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugNativeFrame2,0x35389FF1,0x3684,0x4c55,0xA2,0xEE,0x21,0x0F,0x26,0xC6,0x0E,0x5E); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugModule3,0x86F012BF,0xFF15,0x4372,0xBD,0x30,0xB6,0xF1,0x1C,0xAA,0xE1,0xDD); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugRuntimeUnwindableFrame,0x879CAC0A,0x4A53,0x4668,0xB8,0xE3,0xCB,0x84,0x73,0xCB,0x18,0x7F); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugModule,0xdba2d8c1,0xe5c5,0x4069,0x8c,0x13,0x10,0xa7,0xc6,0xab,0xf4,0x3d); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugModule2,0x7FCC5FB5,0x49C0,0x41de,0x99,0x38,0x3B,0x88,0xB5,0xB9,0xAD,0xD7); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugFunction,0xCC7BCAF3,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugFunction2,0xEF0C490B,0x94C3,0x4e4d,0xB6,0x29,0xDD,0xC1,0x34,0xC5,0x32,0xD8); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugFunction3,0x09B70F28,0xE465,0x482D,0x99,0xE0,0x81,0xA1,0x65,0xEB,0x05,0x32); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugCode,0xCC7BCAF4,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugCode2,0x5F696509,0x452F,0x4436,0xA3,0xFE,0x4D,0x11,0xFE,0x7E,0x23,0x47); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugCode3,0xD13D3E88,0xE1F2,0x4020,0xAA,0x1D,0x3D,0x16,0x2D,0xCB,0xE9,0x66); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugCode4,0x18221fa4,0x20cb,0x40fa,0xb1,0x9d,0x9f,0x91,0xc4,0xfa,0x8c,0x14); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugILCode,0x598D46C2,0xC877,0x42A7,0x89,0xD2,0x3D,0x0C,0x7F,0x1C,0x12,0x64); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugILCode2,0x46586093,0xD3F5,0x4DB6,0xAC,0xDB,0x95,0x5B,0xCE,0x22,0x8C,0x15); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugClass,0xCC7BCAF5,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugClass2,0xB008EA8D,0x7AB1,0x43f7,0xBB,0x20,0xFB,0xB5,0xA0,0x40,0x38,0xAE); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugEval,0xCC7BCAF6,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugEval2,0xFB0D9CE7,0xBE66,0x4683,0x9D,0x32,0xA4,0x2A,0x04,0xE2,0xFD,0x91); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugValue,0xCC7BCAF7,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugValue2,0x5E0B54E7,0xD88A,0x4626,0x94,0x20,0xA6,0x91,0xE0,0xA7,0x8B,0x49); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugValue3,0x565005FC,0x0F8A,0x4F3E,0x9E,0xDB,0x83,0x10,0x2B,0x15,0x65,0x95); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugGenericValue,0xCC7BCAF8,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugReferenceValue,0xCC7BCAF9,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugHeapValue,0xCC7BCAFA,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugHeapValue2,0xE3AC4D6C,0x9CB7,0x43e6,0x96,0xCC,0xB2,0x15,0x40,0xE5,0x08,0x3C); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugHeapValue3,0xA69ACAD8,0x2374,0x46e9,0x9F,0xF8,0xB1,0xF1,0x41,0x20,0xD2,0x96); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugObjectValue,0x18AD3D6E,0xB7D2,0x11d2,0xBD,0x04,0x00,0x00,0xF8,0x08,0x49,0xBD); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugObjectValue2,0x49E4A320,0x4A9B,0x4eca,0xB1,0x05,0x22,0x9F,0xB7,0xD5,0x00,0x9F); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugBoxValue,0xCC7BCAFC,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugStringValue,0xCC7BCAFD,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugArrayValue,0x0405B0DF,0xA660,0x11d2,0xBD,0x02,0x00,0x00,0xF8,0x08,0x49,0xBD); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugVariableHome,0x50847b8d,0xf43f,0x41b0,0x92,0x4c,0x63,0x83,0xa5,0xf2,0x27,0x8b); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugHandleValue,0x029596E8,0x276B,0x46a1,0x98,0x21,0x73,0x2E,0x96,0xBB,0xB0,0x0B); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugContext,0xCC7BCB00,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugComObjectValue,0x5F69C5E5,0x3E12,0x42DF,0xB3,0x71,0xF9,0xD7,0x61,0xD6,0xEE,0x24); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugObjectEnum,0xCC7BCB02,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugBreakpointEnum,0xCC7BCB03,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugStepperEnum,0xCC7BCB04,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugProcessEnum,0xCC7BCB05,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugThreadEnum,0xCC7BCB06,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugFrameEnum,0xCC7BCB07,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugChainEnum,0xCC7BCB08,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugModuleEnum,0xCC7BCB09,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugValueEnum,0xCC7BCB0A,0x8A68,0x11d2,0x98,0x3C,0x00,0x00,0xF8,0x08,0x34,0x2D); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugVariableHomeEnum,0xe76b7a57,0x4f7a,0x4309,0x85,0xa7,0x5d,0x91,0x8c,0x3d,0xea,0xf7); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugCodeEnum,0x55E96461,0x9645,0x45e4,0xA2,0xFF,0x03,0x67,0x87,0x7A,0xBC,0xDE); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugTypeEnum,0x10F27499,0x9DF2,0x43ce,0x83,0x33,0xA3,0x21,0xD7,0xC9,0x9C,0xB4); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugType,0xD613F0BB,0xACE1,0x4c19,0xBD,0x72,0xE4,0xC0,0x8D,0x5D,0xA7,0xF5); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugType2,0xe6e91d79,0x693d,0x48bc,0xb4,0x17,0x82,0x84,0xb4,0xf1,0x0f,0xb5); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugErrorInfoEnum,0xF0E18809,0x72B5,0x11d2,0x97,0x6F,0x00,0xA0,0xC9,0xB4,0xD5,0x0C); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugAppDomainEnum,0x63ca1b24,0x4359,0x4883,0xbd,0x57,0x13,0xf8,0x15,0xf5,0x87,0x44); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugAssemblyEnum,0x4a2a1ec9,0x85ec,0x4bfb,0x9f,0x15,0xa8,0x9f,0xdf,0xe0,0xfe,0x83); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugBlockingObjectEnum,0x976A6278,0x134A,0x4a81,0x81,0xA3,0x8F,0x27,0x79,0x43,0xF4,0xC3); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugMDA,0xCC726F2F,0x1DB7,0x459b,0xB0,0xEC,0x05,0xF0,0x1D,0x84,0x1B,0x42); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugEditAndContinueErrorInfo,0x8D600D41,0xF4F6,0x4cb3,0xB7,0xEC,0x7B,0xD1,0x64,0x94,0x40,0x36); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugEditAndContinueSnapshot,0x6DC3FA01,0xD7CB,0x11d2,0x8A,0x95,0x00,0x80,0xC7,0x92,0xE5,0xD8); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugExceptionObjectCallStackEnum,0xED775530,0x4DC4,0x41F7,0x86,0xD0,0x9E,0x2D,0xEF,0x7D,0xFC,0x66); + + +MIDL_DEFINE_GUID(IID, IID_ICorDebugExceptionObjectValue,0xAE4CA65D,0x59DD,0x42A2,0x83,0xA5,0x57,0xE8,0xA0,0x8D,0x87,0x19); + + +MIDL_DEFINE_GUID(IID, LIBID_CORDBLib,0x53D13620,0xF417,0x11d1,0x97,0x62,0xA6,0x38,0x26,0xA4,0xF2,0x55); + + +MIDL_DEFINE_GUID(CLSID, CLSID_CorDebug,0x6fef44d0,0x39e7,0x4c77,0xbe,0x8e,0xc9,0xf8,0xcf,0x98,0x86,0x30); + + +MIDL_DEFINE_GUID(CLSID, CLSID_EmbeddedCLRCorDebug,0x211f1254,0xbc7e,0x4af5,0xb9,0xaa,0x06,0x73,0x08,0xd8,0x3d,0xd1); + +#undef MIDL_DEFINE_GUID + +#ifdef __cplusplus +} +#endif + + + diff --git a/src/pal/prebuilt/idl/corprof_i.c b/src/pal/prebuilt/idl/corprof_i.c deleted file mode 100644 index 4686c76..0000000 --- a/src/pal/prebuilt/idl/corprof_i.c +++ /dev/null @@ -1,134 +0,0 @@ -// 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. - -/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ - -/* link this file in with the server and any clients */ - - - /* File created by MIDL compiler version 8.00.0603 */ -/* @@MIDL_FILE_HEADING( ) */ - -#pragma warning( disable: 4049 ) /* more than 64k source lines */ - - -#ifdef __cplusplus -extern "C"{ -#endif - - -#include -#include - -#ifdef _MIDL_USE_GUIDDEF_ - -#ifndef INITGUID -#define INITGUID -#include -#undef INITGUID -#else -#include -#endif - -#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ - DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) - -#else // !_MIDL_USE_GUIDDEF_ - -#ifndef __IID_DEFINED__ -#define __IID_DEFINED__ - -typedef struct _IID -{ - unsigned long x; - unsigned short s1; - unsigned short s2; - unsigned char c[8]; -} IID; - -#endif // __IID_DEFINED__ - -#ifndef CLSID_DEFINED -#define CLSID_DEFINED -typedef IID CLSID; -#endif // CLSID_DEFINED - -#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ - const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} - -#endif !_MIDL_USE_GUIDDEF_ - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback,0x176FBED1,0xA55C,0x4796,0x98,0xCA,0xA9,0xDA,0x0E,0xF8,0x83,0xE7); - - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback2,0x8A8CC829,0xCCF2,0x49fe,0xBB,0xAE,0x0F,0x02,0x22,0x28,0x07,0x1A); - - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback3,0x4FD2ED52,0x7731,0x4b8d,0x94,0x69,0x03,0xD2,0xCC,0x30,0x86,0xC5); - - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback4,0x7B63B2E3,0x107D,0x4d48,0xB2,0xF6,0xF6,0x1E,0x22,0x94,0x70,0xD2); - - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback5,0x8DFBA405,0x8C9F,0x45F8,0xBF,0xFA,0x83,0xB1,0x4C,0xEF,0x78,0xB5); - - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback6,0xFC13DF4B,0x4448,0x4F4F,0x95,0x0C,0xBA,0x8D,0x19,0xD0,0x0C,0x36); - - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback7,0xF76A2DBA,0x1D52,0x4539,0x86,0x6C,0x2A,0xA5,0x18,0xF9,0xEF,0xC3); - - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo,0x28B5557D,0x3F3F,0x48b4,0x90,0xB2,0x5F,0x9E,0xEA,0x2F,0x6C,0x48); - - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo2,0xCC0935CD,0xA518,0x487d,0xB0,0xBB,0xA9,0x32,0x14,0xE6,0x54,0x78); - - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo3,0xB555ED4F,0x452A,0x4E54,0x8B,0x39,0xB5,0x36,0x0B,0xAD,0x32,0xA0); - - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerObjectEnum,0x2C6269BD,0x2D13,0x4321,0xAE,0x12,0x66,0x86,0x36,0x5F,0xD6,0xAF); - - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerFunctionEnum,0xFF71301A,0xB994,0x429D,0xA1,0x0B,0xB3,0x45,0xA6,0x52,0x80,0xEF); - - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerModuleEnum,0xb0266d75,0x2081,0x4493,0xaf,0x7f,0x02,0x8b,0xa3,0x4d,0xb8,0x91); - - -MIDL_DEFINE_GUID(IID, IID_IMethodMalloc,0xA0EFB28B,0x6EE2,0x4d7b,0xB9,0x83,0xA7,0x5E,0xF7,0xBE,0xED,0xB8); - - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerFunctionControl,0xF0963021,0xE1EA,0x4732,0x85,0x81,0xE0,0x1B,0x0B,0xD3,0xC0,0xC6); - - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo4,0x0d8fdcaa,0x6257,0x47bf,0xb1,0xbf,0x94,0xda,0xc8,0x84,0x66,0xee); - - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo5,0x07602928,0xCE38,0x4B83,0x81,0xE7,0x74,0xAD,0xAF,0x78,0x12,0x14); - - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo6,0xF30A070D,0xBFFB,0x46A7,0xB1,0xD8,0x87,0x81,0xEF,0x7B,0x69,0x8A); - - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo7,0x9AEECC0D,0x63E0,0x4187,0x8C,0x00,0xE3,0x12,0xF5,0x03,0xF6,0x63); - - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerMethodEnum,0xFCCEE788,0x0088,0x454B,0xA8,0x11,0xC9,0x9F,0x29,0x8D,0x19,0x42); - - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerThreadEnum,0x571194f7,0x25ed,0x419f,0xaa,0x8b,0x70,0x16,0xb3,0x15,0x97,0x01); - - -MIDL_DEFINE_GUID(IID, IID_ICorProfilerAssemblyReferenceProvider,0x66A78C24,0x2EEF,0x4F65,0xB4,0x5F,0xDD,0x1D,0x80,0x38,0xBF,0x3C); - -#undef MIDL_DEFINE_GUID - -#ifdef __cplusplus -} -#endif - - - diff --git a/src/pal/prebuilt/idl/corprof_i.cpp b/src/pal/prebuilt/idl/corprof_i.cpp new file mode 100644 index 0000000..3758da0 --- /dev/null +++ b/src/pal/prebuilt/idl/corprof_i.cpp @@ -0,0 +1,140 @@ +// 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. + +/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ + +/* link this file in with the server and any clients */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +#ifdef __cplusplus +extern "C"{ +#endif + + +#include +#include + +#ifdef _MIDL_USE_GUIDDEF_ + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) + +#else // !_MIDL_USE_GUIDDEF_ + +#ifndef __IID_DEFINED__ +#define __IID_DEFINED__ + +typedef struct _IID +{ + unsigned long x; + unsigned short s1; + unsigned short s2; + unsigned char c[8]; +} IID; + +#endif // __IID_DEFINED__ + +#ifndef CLSID_DEFINED +#define CLSID_DEFINED +typedef IID CLSID; +#endif // CLSID_DEFINED + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} + +#endif !_MIDL_USE_GUIDDEF_ + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback,0x176FBED1,0xA55C,0x4796,0x98,0xCA,0xA9,0xDA,0x0E,0xF8,0x83,0xE7); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback2,0x8A8CC829,0xCCF2,0x49fe,0xBB,0xAE,0x0F,0x02,0x22,0x28,0x07,0x1A); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback3,0x4FD2ED52,0x7731,0x4b8d,0x94,0x69,0x03,0xD2,0xCC,0x30,0x86,0xC5); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback4,0x7B63B2E3,0x107D,0x4d48,0xB2,0xF6,0xF6,0x1E,0x22,0x94,0x70,0xD2); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback5,0x8DFBA405,0x8C9F,0x45F8,0xBF,0xFA,0x83,0xB1,0x4C,0xEF,0x78,0xB5); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback6,0xFC13DF4B,0x4448,0x4F4F,0x95,0x0C,0xBA,0x8D,0x19,0xD0,0x0C,0x36); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback7,0xF76A2DBA,0x1D52,0x4539,0x86,0x6C,0x2A,0xA5,0x18,0xF9,0xEF,0xC3); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback8,0x5BED9B15,0xC079,0x4D47,0xBF,0xE2,0x21,0x5A,0x14,0x0C,0x07,0xE0); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo,0x28B5557D,0x3F3F,0x48b4,0x90,0xB2,0x5F,0x9E,0xEA,0x2F,0x6C,0x48); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo2,0xCC0935CD,0xA518,0x487d,0xB0,0xBB,0xA9,0x32,0x14,0xE6,0x54,0x78); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo3,0xB555ED4F,0x452A,0x4E54,0x8B,0x39,0xB5,0x36,0x0B,0xAD,0x32,0xA0); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerObjectEnum,0x2C6269BD,0x2D13,0x4321,0xAE,0x12,0x66,0x86,0x36,0x5F,0xD6,0xAF); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerFunctionEnum,0xFF71301A,0xB994,0x429D,0xA1,0x0B,0xB3,0x45,0xA6,0x52,0x80,0xEF); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerModuleEnum,0xb0266d75,0x2081,0x4493,0xaf,0x7f,0x02,0x8b,0xa3,0x4d,0xb8,0x91); + + +MIDL_DEFINE_GUID(IID, IID_IMethodMalloc,0xA0EFB28B,0x6EE2,0x4d7b,0xB9,0x83,0xA7,0x5E,0xF7,0xBE,0xED,0xB8); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerFunctionControl,0xF0963021,0xE1EA,0x4732,0x85,0x81,0xE0,0x1B,0x0B,0xD3,0xC0,0xC6); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo4,0x0d8fdcaa,0x6257,0x47bf,0xb1,0xbf,0x94,0xda,0xc8,0x84,0x66,0xee); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo5,0x07602928,0xCE38,0x4B83,0x81,0xE7,0x74,0xAD,0xAF,0x78,0x12,0x14); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo6,0xF30A070D,0xBFFB,0x46A7,0xB1,0xD8,0x87,0x81,0xEF,0x7B,0x69,0x8A); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo7,0x9AEECC0D,0x63E0,0x4187,0x8C,0x00,0xE3,0x12,0xF5,0x03,0xF6,0x63); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo8,0xC5AC80A6,0x782E,0x4716,0x80,0x44,0x39,0x59,0x8C,0x60,0xCF,0xBF); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerMethodEnum,0xFCCEE788,0x0088,0x454B,0xA8,0x11,0xC9,0x9F,0x29,0x8D,0x19,0x42); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerThreadEnum,0x571194f7,0x25ed,0x419f,0xaa,0x8b,0x70,0x16,0xb3,0x15,0x97,0x01); + + +MIDL_DEFINE_GUID(IID, IID_ICorProfilerAssemblyReferenceProvider,0x66A78C24,0x2EEF,0x4F65,0xB4,0x5F,0xDD,0x1D,0x80,0x38,0xBF,0x3C); + +#undef MIDL_DEFINE_GUID + +#ifdef __cplusplus +} +#endif + + + diff --git a/src/pal/prebuilt/idl/corpub_i.c b/src/pal/prebuilt/idl/corpub_i.cpp similarity index 100% rename from src/pal/prebuilt/idl/corpub_i.c rename to src/pal/prebuilt/idl/corpub_i.cpp diff --git a/src/pal/prebuilt/idl/corsym_i.c b/src/pal/prebuilt/idl/corsym_i.cpp similarity index 100% rename from src/pal/prebuilt/idl/corsym_i.c rename to src/pal/prebuilt/idl/corsym_i.cpp diff --git a/src/pal/prebuilt/idl/fusionpriv_i.c b/src/pal/prebuilt/idl/fusionpriv_i.cpp similarity index 100% rename from src/pal/prebuilt/idl/fusionpriv_i.c rename to src/pal/prebuilt/idl/fusionpriv_i.cpp diff --git a/src/pal/prebuilt/idl/gchost_i.c b/src/pal/prebuilt/idl/gchost_i.cpp similarity index 100% rename from src/pal/prebuilt/idl/gchost_i.c rename to src/pal/prebuilt/idl/gchost_i.cpp diff --git a/src/pal/prebuilt/idl/ivalidator_i.c b/src/pal/prebuilt/idl/ivalidator_i.cpp similarity index 100% rename from src/pal/prebuilt/idl/ivalidator_i.c rename to src/pal/prebuilt/idl/ivalidator_i.cpp diff --git a/src/pal/prebuilt/idl/ivehandler_i.c b/src/pal/prebuilt/idl/ivehandler_i.cpp similarity index 100% rename from src/pal/prebuilt/idl/ivehandler_i.c rename to src/pal/prebuilt/idl/ivehandler_i.cpp diff --git a/src/pal/prebuilt/idl/mscorsvc_i.c b/src/pal/prebuilt/idl/mscorsvc_i.cpp similarity index 100% rename from src/pal/prebuilt/idl/mscorsvc_i.c rename to src/pal/prebuilt/idl/mscorsvc_i.cpp diff --git a/src/pal/prebuilt/idl/sospriv_i.c b/src/pal/prebuilt/idl/sospriv_i.c deleted file mode 100644 index 7fee909..0000000 --- a/src/pal/prebuilt/idl/sospriv_i.c +++ /dev/null @@ -1,100 +0,0 @@ - - -/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ - -/* link this file in with the server and any clients */ - - - /* File created by MIDL compiler version 8.00.0613 */ -/* at Mon Jan 18 19:14:07 2038 - */ -/* Compiler settings for C:/ssd/coreclr/src/inc/sospriv.idl: - Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.00.0613 - protocol : dce , ms_ext, c_ext, robust - error checks: allocation ref bounds_check enum stub_data - VC __declspec() decoration level: - __declspec(uuid()), __declspec(selectany), __declspec(novtable) - DECLSPEC_UUID(), MIDL_INTERFACE() -*/ -/* @@MIDL_FILE_HEADING( ) */ - -#pragma warning( disable: 4049 ) /* more than 64k source lines */ - - -#ifdef __cplusplus -extern "C"{ -#endif - - -#include -#include - -#ifdef _MIDL_USE_GUIDDEF_ - -#ifndef INITGUID -#define INITGUID -#include -#undef INITGUID -#else -#include -#endif - -#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ - DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) - -#else // !_MIDL_USE_GUIDDEF_ - -#ifndef __IID_DEFINED__ -#define __IID_DEFINED__ - -typedef struct _IID -{ - unsigned long x; - unsigned short s1; - unsigned short s2; - unsigned char c[8]; -} IID; - -#endif // __IID_DEFINED__ - -#ifndef CLSID_DEFINED -#define CLSID_DEFINED -typedef IID CLSID; -#endif // CLSID_DEFINED - -#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ - const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} - -#endif !_MIDL_USE_GUIDDEF_ - -MIDL_DEFINE_GUID(IID, IID_ISOSEnum,0x286CA186,0xE763,0x4F61,0x97,0x60,0x48,0x7D,0x43,0xAE,0x43,0x41); - - -MIDL_DEFINE_GUID(IID, IID_ISOSHandleEnum,0x3E269830,0x4A2B,0x4301,0x8E,0xE2,0xD6,0x80,0x5B,0x29,0xB2,0xFA); - - -MIDL_DEFINE_GUID(IID, IID_ISOSStackRefErrorEnum,0x774F4E1B,0xFB7B,0x491B,0x97,0x6D,0xA8,0x13,0x0F,0xE3,0x55,0xE9); - - -MIDL_DEFINE_GUID(IID, IID_ISOSStackRefEnum,0x8FA642BD,0x9F10,0x4799,0x9A,0xA3,0x51,0x2A,0xE7,0x8C,0x77,0xEE); - - -MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface,0x436f00f2,0xb42a,0x4b9f,0x87,0x0c,0xe7,0x3d,0xb6,0x6a,0xe9,0x30); - - -MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface2,0xA16026EC,0x96F4,0x40BA,0x87,0xFB,0x55,0x75,0x98,0x6F,0xB7,0xAF); - - -MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface3,0xB08C5CDC,0xFD8A,0x49C5,0xAB,0x38,0x5F,0xEE,0xF3,0x52,0x35,0xB4); - - -MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface4,0x74B9D34C,0xA612,0x4B07,0x93,0xDD,0x54,0x62,0x17,0x8F,0xCE,0x11); - -#undef MIDL_DEFINE_GUID - -#ifdef __cplusplus -} -#endif - - - diff --git a/src/pal/prebuilt/idl/sospriv_i.cpp b/src/pal/prebuilt/idl/sospriv_i.cpp new file mode 100644 index 0000000..3584b76 --- /dev/null +++ b/src/pal/prebuilt/idl/sospriv_i.cpp @@ -0,0 +1,98 @@ + + +/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ + +/* link this file in with the server and any clients */ + + + /* File created by MIDL compiler version 8.00.0613 */ +/* at Mon Jan 18 19:14:07 2038 + */ +/* Compiler settings for C:/ssd/coreclr/src/inc/sospriv.idl: + Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.00.0613 + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + +#include +#include + +#ifdef __cplusplus +extern "C"{ +#endif + +#ifdef _MIDL_USE_GUIDDEF_ + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) + +#else // !_MIDL_USE_GUIDDEF_ + +#ifndef __IID_DEFINED__ +#define __IID_DEFINED__ + +typedef struct _IID +{ + unsigned long x; + unsigned short s1; + unsigned short s2; + unsigned char c[8]; +} IID; + +#endif // __IID_DEFINED__ + +#ifndef CLSID_DEFINED +#define CLSID_DEFINED +typedef IID CLSID; +#endif // CLSID_DEFINED + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} + +#endif !_MIDL_USE_GUIDDEF_ + +MIDL_DEFINE_GUID(IID, IID_ISOSEnum,0x286CA186,0xE763,0x4F61,0x97,0x60,0x48,0x7D,0x43,0xAE,0x43,0x41); + + +MIDL_DEFINE_GUID(IID, IID_ISOSHandleEnum,0x3E269830,0x4A2B,0x4301,0x8E,0xE2,0xD6,0x80,0x5B,0x29,0xB2,0xFA); + + +MIDL_DEFINE_GUID(IID, IID_ISOSStackRefErrorEnum,0x774F4E1B,0xFB7B,0x491B,0x97,0x6D,0xA8,0x13,0x0F,0xE3,0x55,0xE9); + + +MIDL_DEFINE_GUID(IID, IID_ISOSStackRefEnum,0x8FA642BD,0x9F10,0x4799,0x9A,0xA3,0x51,0x2A,0xE7,0x8C,0x77,0xEE); + + +MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface,0x436f00f2,0xb42a,0x4b9f,0x87,0x0c,0xe7,0x3d,0xb6,0x6a,0xe9,0x30); + + +MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface2,0xA16026EC,0x96F4,0x40BA,0x87,0xFB,0x55,0x75,0x98,0x6F,0xB7,0xAF); + + +MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface3,0xB08C5CDC,0xFD8A,0x49C5,0xAB,0x38,0x5F,0xEE,0xF3,0x52,0x35,0xB4); + + +MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface4,0x74B9D34C,0xA612,0x4B07,0x93,0xDD,0x54,0x62,0x17,0x8F,0xCE,0x11); + +#undef MIDL_DEFINE_GUID + +#ifdef __cplusplus +} +#endif + + + diff --git a/src/pal/prebuilt/idl/tlbimpexp_i.c b/src/pal/prebuilt/idl/tlbimpexp_i.cpp similarity index 100% rename from src/pal/prebuilt/idl/tlbimpexp_i.c rename to src/pal/prebuilt/idl/tlbimpexp_i.cpp diff --git a/src/pal/prebuilt/idl/xclrdata_i.c b/src/pal/prebuilt/idl/xclrdata_i.cpp similarity index 100% rename from src/pal/prebuilt/idl/xclrdata_i.c rename to src/pal/prebuilt/idl/xclrdata_i.cpp diff --git a/src/pal/prebuilt/idl/xcordebug_i.c b/src/pal/prebuilt/idl/xcordebug_i.cpp similarity index 100% rename from src/pal/prebuilt/idl/xcordebug_i.c rename to src/pal/prebuilt/idl/xcordebug_i.cpp diff --git a/src/pal/prebuilt/inc/cordebug.h b/src/pal/prebuilt/inc/cordebug.h index a5a5cf2..3931040 100644 --- a/src/pal/prebuilt/inc/cordebug.h +++ b/src/pal/prebuilt/inc/cordebug.h @@ -4,9 +4,9 @@ /* File created by MIDL compiler version 8.00.0603 */ -/* at Fri Jul 15 18:01:08 2016 +/* at Fri Sep 23 15:43:16 2016 */ -/* Compiler settings for E:/git/coreclr/src/inc/cordebug.idl: +/* Compiler settings for cordebug.idl: Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.00.0603 protocol : dce , ms_ext, c_ext, robust error checks: allocation ref bounds_check enum stub_data @@ -598,6 +598,13 @@ typedef interface ICorDebugCode3 ICorDebugCode3; #endif /* __ICorDebugCode3_FWD_DEFINED__ */ +#ifndef __ICorDebugCode4_FWD_DEFINED__ +#define __ICorDebugCode4_FWD_DEFINED__ +typedef interface ICorDebugCode4 ICorDebugCode4; + +#endif /* __ICorDebugCode4_FWD_DEFINED__ */ + + #ifndef __ICorDebugILCode_FWD_DEFINED__ #define __ICorDebugILCode_FWD_DEFINED__ typedef interface ICorDebugILCode ICorDebugILCode; @@ -731,6 +738,13 @@ typedef interface ICorDebugArrayValue ICorDebugArrayValue; #endif /* __ICorDebugArrayValue_FWD_DEFINED__ */ +#ifndef __ICorDebugVariableHome_FWD_DEFINED__ +#define __ICorDebugVariableHome_FWD_DEFINED__ +typedef interface ICorDebugVariableHome ICorDebugVariableHome; + +#endif /* __ICorDebugVariableHome_FWD_DEFINED__ */ + + #ifndef __ICorDebugHandleValue_FWD_DEFINED__ #define __ICorDebugHandleValue_FWD_DEFINED__ typedef interface ICorDebugHandleValue ICorDebugHandleValue; @@ -815,6 +829,13 @@ typedef interface ICorDebugValueEnum ICorDebugValueEnum; #endif /* __ICorDebugValueEnum_FWD_DEFINED__ */ +#ifndef __ICorDebugVariableHomeEnum_FWD_DEFINED__ +#define __ICorDebugVariableHomeEnum_FWD_DEFINED__ +typedef interface ICorDebugVariableHomeEnum ICorDebugVariableHomeEnum; + +#endif /* __ICorDebugVariableHomeEnum_FWD_DEFINED__ */ + + #ifndef __ICorDebugCodeEnum_FWD_DEFINED__ #define __ICorDebugCodeEnum_FWD_DEFINED__ typedef interface ICorDebugCodeEnum ICorDebugCodeEnum; @@ -836,6 +857,13 @@ typedef interface ICorDebugType ICorDebugType; #endif /* __ICorDebugType_FWD_DEFINED__ */ +#ifndef __ICorDebugType2_FWD_DEFINED__ +#define __ICorDebugType2_FWD_DEFINED__ +typedef interface ICorDebugType2 ICorDebugType2; + +#endif /* __ICorDebugType2_FWD_DEFINED__ */ + + #ifndef __ICorDebugErrorInfoEnum_FWD_DEFINED__ #define __ICorDebugErrorInfoEnum_FWD_DEFINED__ typedef interface ICorDebugErrorInfoEnum ICorDebugErrorInfoEnum; @@ -1321,6 +1349,7 @@ enum CorDebugNGENPolicy + #pragma warning(pop) typedef ULONG64 CORDB_ADDRESS; @@ -12423,6 +12452,86 @@ EXTERN_C const IID IID_ICorDebugCode3; #endif /* __ICorDebugCode3_INTERFACE_DEFINED__ */ +#ifndef __ICorDebugCode4_INTERFACE_DEFINED__ +#define __ICorDebugCode4_INTERFACE_DEFINED__ + +/* interface ICorDebugCode4 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugCode4; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("18221fa4-20cb-40fa-b19d-9f91c4fa8c14") + ICorDebugCode4 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE EnumerateVariableHomes( + /* [out] */ ICorDebugVariableHomeEnum **ppEnum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugCode4Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugCode4 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugCode4 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugCode4 * This); + + HRESULT ( STDMETHODCALLTYPE *EnumerateVariableHomes )( + ICorDebugCode4 * This, + /* [out] */ ICorDebugVariableHomeEnum **ppEnum); + + END_INTERFACE + } ICorDebugCode4Vtbl; + + interface ICorDebugCode4 + { + CONST_VTBL struct ICorDebugCode4Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugCode4_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugCode4_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugCode4_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugCode4_EnumerateVariableHomes(This,ppEnum) \ + ( (This)->lpVtbl -> EnumerateVariableHomes(This,ppEnum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugCode4_INTERFACE_DEFINED__ */ + + #ifndef __ICorDebugILCode_INTERFACE_DEFINED__ #define __ICorDebugILCode_INTERFACE_DEFINED__ @@ -14382,15 +14491,15 @@ EXTERN_C const IID IID_ICorDebugBoxValue; #endif /* __ICorDebugBoxValue_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_cordebug_0000_0095 */ +/* interface __MIDL_itf_cordebug_0000_0096 */ /* [local] */ #pragma warning(push) #pragma warning(disable:28718) -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0095_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0095_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0096_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0096_v0_0_s_ifspec; #ifndef __ICorDebugStringValue_INTERFACE_DEFINED__ #define __ICorDebugStringValue_INTERFACE_DEFINED__ @@ -14530,14 +14639,14 @@ EXTERN_C const IID IID_ICorDebugStringValue; #endif /* __ICorDebugStringValue_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_cordebug_0000_0096 */ +/* interface __MIDL_itf_cordebug_0000_0097 */ /* [local] */ #pragma warning(pop) -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0096_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0096_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0097_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0097_v0_0_s_ifspec; #ifndef __ICorDebugArrayValue_INTERFACE_DEFINED__ #define __ICorDebugArrayValue_INTERFACE_DEFINED__ @@ -14743,6 +14852,156 @@ EXTERN_C const IID IID_ICorDebugArrayValue; #endif /* __ICorDebugArrayValue_INTERFACE_DEFINED__ */ +#ifndef __ICorDebugVariableHome_INTERFACE_DEFINED__ +#define __ICorDebugVariableHome_INTERFACE_DEFINED__ + +/* interface ICorDebugVariableHome */ +/* [unique][uuid][local][object] */ + +typedef +enum VariableLocationType + { + VLT_REGISTER = 0, + VLT_REGISTER_RELATIVE = ( VLT_REGISTER + 1 ) , + VLT_INVALID = ( VLT_REGISTER_RELATIVE + 1 ) + } VariableLocationType; + + +EXTERN_C const IID IID_ICorDebugVariableHome; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("50847b8d-f43f-41b0-924c-6383a5f2278b") + ICorDebugVariableHome : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetCode( + /* [out] */ ICorDebugCode **ppCode) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSlotIndex( + /* [out] */ ULONG32 *pSlotIndex) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetArgumentIndex( + /* [out] */ ULONG32 *pArgumentIndex) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLiveRange( + /* [out] */ ULONG32 *pStartOffset, + /* [out] */ ULONG32 *pEndOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLocationType( + /* [out] */ VariableLocationType *pLocationType) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRegister( + /* [out] */ CorDebugRegister *pRegister) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetOffset( + /* [out] */ LONG *pOffset) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugVariableHomeVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugVariableHome * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugVariableHome * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugVariableHome * This); + + HRESULT ( STDMETHODCALLTYPE *GetCode )( + ICorDebugVariableHome * This, + /* [out] */ ICorDebugCode **ppCode); + + HRESULT ( STDMETHODCALLTYPE *GetSlotIndex )( + ICorDebugVariableHome * This, + /* [out] */ ULONG32 *pSlotIndex); + + HRESULT ( STDMETHODCALLTYPE *GetArgumentIndex )( + ICorDebugVariableHome * This, + /* [out] */ ULONG32 *pArgumentIndex); + + HRESULT ( STDMETHODCALLTYPE *GetLiveRange )( + ICorDebugVariableHome * This, + /* [out] */ ULONG32 *pStartOffset, + /* [out] */ ULONG32 *pEndOffset); + + HRESULT ( STDMETHODCALLTYPE *GetLocationType )( + ICorDebugVariableHome * This, + /* [out] */ VariableLocationType *pLocationType); + + HRESULT ( STDMETHODCALLTYPE *GetRegister )( + ICorDebugVariableHome * This, + /* [out] */ CorDebugRegister *pRegister); + + HRESULT ( STDMETHODCALLTYPE *GetOffset )( + ICorDebugVariableHome * This, + /* [out] */ LONG *pOffset); + + END_INTERFACE + } ICorDebugVariableHomeVtbl; + + interface ICorDebugVariableHome + { + CONST_VTBL struct ICorDebugVariableHomeVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugVariableHome_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugVariableHome_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugVariableHome_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugVariableHome_GetCode(This,ppCode) \ + ( (This)->lpVtbl -> GetCode(This,ppCode) ) + +#define ICorDebugVariableHome_GetSlotIndex(This,pSlotIndex) \ + ( (This)->lpVtbl -> GetSlotIndex(This,pSlotIndex) ) + +#define ICorDebugVariableHome_GetArgumentIndex(This,pArgumentIndex) \ + ( (This)->lpVtbl -> GetArgumentIndex(This,pArgumentIndex) ) + +#define ICorDebugVariableHome_GetLiveRange(This,pStartOffset,pEndOffset) \ + ( (This)->lpVtbl -> GetLiveRange(This,pStartOffset,pEndOffset) ) + +#define ICorDebugVariableHome_GetLocationType(This,pLocationType) \ + ( (This)->lpVtbl -> GetLocationType(This,pLocationType) ) + +#define ICorDebugVariableHome_GetRegister(This,pRegister) \ + ( (This)->lpVtbl -> GetRegister(This,pRegister) ) + +#define ICorDebugVariableHome_GetOffset(This,pOffset) \ + ( (This)->lpVtbl -> GetOffset(This,pOffset) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugVariableHome_INTERFACE_DEFINED__ */ + + #ifndef __ICorDebugHandleValue_INTERFACE_DEFINED__ #define __ICorDebugHandleValue_INTERFACE_DEFINED__ @@ -16154,6 +16413,118 @@ EXTERN_C const IID IID_ICorDebugValueEnum; #endif /* __ICorDebugValueEnum_INTERFACE_DEFINED__ */ +#ifndef __ICorDebugVariableHomeEnum_INTERFACE_DEFINED__ +#define __ICorDebugVariableHomeEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugVariableHomeEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugVariableHomeEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("e76b7a57-4f7a-4309-85a7-5d918c3deaf7") + ICorDebugVariableHomeEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugVariableHome *homes[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugVariableHomeEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugVariableHomeEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugVariableHomeEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugVariableHomeEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugVariableHomeEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugVariableHomeEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugVariableHomeEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugVariableHomeEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugVariableHomeEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugVariableHome *homes[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugVariableHomeEnumVtbl; + + interface ICorDebugVariableHomeEnum + { + CONST_VTBL struct ICorDebugVariableHomeEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugVariableHomeEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugVariableHomeEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugVariableHomeEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugVariableHomeEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugVariableHomeEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugVariableHomeEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugVariableHomeEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugVariableHomeEnum_Next(This,celt,homes,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,homes,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugVariableHomeEnum_INTERFACE_DEFINED__ */ + + #ifndef __ICorDebugCodeEnum_INTERFACE_DEFINED__ #define __ICorDebugCodeEnum_INTERFACE_DEFINED__ @@ -16522,6 +16893,86 @@ EXTERN_C const IID IID_ICorDebugType; #endif /* __ICorDebugType_INTERFACE_DEFINED__ */ +#ifndef __ICorDebugType2_INTERFACE_DEFINED__ +#define __ICorDebugType2_INTERFACE_DEFINED__ + +/* interface ICorDebugType2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugType2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("e6e91d79-693d-48bc-b417-8284b4f10fb5") + ICorDebugType2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetTypeID( + /* [out] */ COR_TYPEID *id) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugType2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugType2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugType2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugType2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeID )( + ICorDebugType2 * This, + /* [out] */ COR_TYPEID *id); + + END_INTERFACE + } ICorDebugType2Vtbl; + + interface ICorDebugType2 + { + CONST_VTBL struct ICorDebugType2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugType2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugType2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugType2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugType2_GetTypeID(This,id) \ + ( (This)->lpVtbl -> GetTypeID(This,id) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugType2_INTERFACE_DEFINED__ */ + + #ifndef __ICorDebugErrorInfoEnum_INTERFACE_DEFINED__ #define __ICorDebugErrorInfoEnum_INTERFACE_DEFINED__ @@ -16970,15 +17421,15 @@ EXTERN_C const IID IID_ICorDebugBlockingObjectEnum; #endif /* __ICorDebugBlockingObjectEnum_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_cordebug_0000_0117 */ +/* interface __MIDL_itf_cordebug_0000_0121 */ /* [local] */ #pragma warning(push) #pragma warning(disable:28718) -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0117_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0117_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0121_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0121_v0_0_s_ifspec; #ifndef __ICorDebugMDA_INTERFACE_DEFINED__ #define __ICorDebugMDA_INTERFACE_DEFINED__ @@ -17118,7 +17569,7 @@ EXTERN_C const IID IID_ICorDebugMDA; #endif /* __ICorDebugMDA_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_cordebug_0000_0118 */ +/* interface __MIDL_itf_cordebug_0000_0122 */ /* [local] */ #pragma warning(pop) @@ -17126,8 +17577,8 @@ EXTERN_C const IID IID_ICorDebugMDA; #pragma warning(disable:28718) -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0118_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0118_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0122_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0122_v0_0_s_ifspec; #ifndef __ICorDebugEditAndContinueErrorInfo_INTERFACE_DEFINED__ #define __ICorDebugEditAndContinueErrorInfo_INTERFACE_DEFINED__ @@ -17243,14 +17694,14 @@ EXTERN_C const IID IID_ICorDebugEditAndContinueErrorInfo; #endif /* __ICorDebugEditAndContinueErrorInfo_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_cordebug_0000_0119 */ +/* interface __MIDL_itf_cordebug_0000_0123 */ /* [local] */ #pragma warning(pop) -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0119_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0119_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0123_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0123_v0_0_s_ifspec; #ifndef __ICorDebugEditAndContinueSnapshot_INTERFACE_DEFINED__ #define __ICorDebugEditAndContinueSnapshot_INTERFACE_DEFINED__ diff --git a/src/pal/prebuilt/inc/corprof.h b/src/pal/prebuilt/inc/corprof.h index 70b7e77..6778fb5 100644 --- a/src/pal/prebuilt/inc/corprof.h +++ b/src/pal/prebuilt/inc/corprof.h @@ -5,7 +5,7 @@ /* this ALWAYS GENERATED file contains the definitions for the interfaces */ - /* File created by MIDL compiler version 8.00.0603 */ + /* File created by MIDL compiler version 8.01.0620 */ /* @@MIDL_FILE_HEADING( ) */ #pragma warning( disable: 4049 ) /* more than 64k source lines */ @@ -21,7 +21,7 @@ #ifndef __RPCNDR_H_VERSION__ #error this stub requires an updated version of -#endif // __RPCNDR_H_VERSION__ +#endif /* __RPCNDR_H_VERSION__ */ #ifndef COM_NO_WINDOWS_H #include "windows.h" @@ -86,6 +86,13 @@ typedef interface ICorProfilerCallback7 ICorProfilerCallback7; #endif /* __ICorProfilerCallback7_FWD_DEFINED__ */ +#ifndef __ICorProfilerCallback8_FWD_DEFINED__ +#define __ICorProfilerCallback8_FWD_DEFINED__ +typedef interface ICorProfilerCallback8 ICorProfilerCallback8; + +#endif /* __ICorProfilerCallback8_FWD_DEFINED__ */ + + #ifndef __ICorProfilerInfo_FWD_DEFINED__ #define __ICorProfilerInfo_FWD_DEFINED__ typedef interface ICorProfilerInfo ICorProfilerInfo; @@ -170,6 +177,13 @@ typedef interface ICorProfilerInfo7 ICorProfilerInfo7; #endif /* __ICorProfilerInfo7_FWD_DEFINED__ */ +#ifndef __ICorProfilerInfo8_FWD_DEFINED__ +#define __ICorProfilerInfo8_FWD_DEFINED__ +typedef interface ICorProfilerInfo8 ICorProfilerInfo8; + +#endif /* __ICorProfilerInfo8_FWD_DEFINED__ */ + + #ifndef __ICorProfilerMethodEnum_FWD_DEFINED__ #define __ICorProfilerMethodEnum_FWD_DEFINED__ typedef interface ICorProfilerMethodEnum ICorProfilerMethodEnum; @@ -244,6 +258,12 @@ typedef const BYTE *LPCBYTE; typedef BYTE *LPBYTE; +typedef BYTE COR_SIGNATURE; + +typedef COR_SIGNATURE *PCOR_SIGNATURE; + +typedef const COR_SIGNATURE *PCCOR_SIGNATURE; + #ifndef _COR_IL_MAP #define _COR_IL_MAP typedef struct _COR_IL_MAP @@ -5807,408 +5827,482 @@ EXTERN_C const IID IID_ICorProfilerCallback7; #endif /* __ICorProfilerCallback7_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_corprof_0000_0007 */ -/* [local] */ - -typedef /* [public] */ -enum __MIDL___MIDL_itf_corprof_0000_0007_0001 - { - COR_PRF_CODEGEN_DISABLE_INLINING = 0x1, - COR_PRF_CODEGEN_DISABLE_ALL_OPTIMIZATIONS = 0x2 - } COR_PRF_CODEGEN_FLAGS; - - - -extern RPC_IF_HANDLE __MIDL_itf_corprof_0000_0007_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_corprof_0000_0007_v0_0_s_ifspec; - -#ifndef __ICorProfilerInfo_INTERFACE_DEFINED__ -#define __ICorProfilerInfo_INTERFACE_DEFINED__ +#ifndef __ICorProfilerCallback8_INTERFACE_DEFINED__ +#define __ICorProfilerCallback8_INTERFACE_DEFINED__ -/* interface ICorProfilerInfo */ +/* interface ICorProfilerCallback8 */ /* [local][unique][uuid][object] */ -EXTERN_C const IID IID_ICorProfilerInfo; +EXTERN_C const IID IID_ICorProfilerCallback8; #if defined(__cplusplus) && !defined(CINTERFACE) - MIDL_INTERFACE("28B5557D-3F3F-48b4-90B2-5F9EEA2F6C48") - ICorProfilerInfo : public IUnknown + MIDL_INTERFACE("5BED9B15-C079-4D47-BFE2-215A140C07E0") + ICorProfilerCallback8 : public ICorProfilerCallback7 { public: - virtual HRESULT STDMETHODCALLTYPE GetClassFromObject( - /* [in] */ ObjectID objectId, - /* [out] */ ClassID *pClassId) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetClassFromToken( - /* [in] */ ModuleID moduleId, - /* [in] */ mdTypeDef typeDef, - /* [out] */ ClassID *pClassId) = 0; + virtual HRESULT STDMETHODCALLTYPE DynamicMethodJITCompilationStarted( + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fIsSafeToBlock, + /* [in] */ LPCBYTE pILHeader, + /* [in] */ ULONG cbILHeader) = 0; - virtual HRESULT STDMETHODCALLTYPE GetCodeInfo( + virtual HRESULT STDMETHODCALLTYPE DynamicMethodJITCompilationFinished( /* [in] */ FunctionID functionId, - /* [out] */ LPCBYTE *pStart, - /* [out] */ ULONG *pcSize) = 0; + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock) = 0; - virtual HRESULT STDMETHODCALLTYPE GetEventMask( - /* [out] */ DWORD *pdwEvents) = 0; + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerCallback8Vtbl + { + BEGIN_INTERFACE - virtual HRESULT STDMETHODCALLTYPE GetFunctionFromIP( - /* [in] */ LPCBYTE ip, - /* [out] */ FunctionID *pFunctionId) = 0; + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerCallback8 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); - virtual HRESULT STDMETHODCALLTYPE GetFunctionFromToken( - /* [in] */ ModuleID moduleId, - /* [in] */ mdToken token, - /* [out] */ FunctionID *pFunctionId) = 0; + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerCallback8 * This); - virtual HRESULT STDMETHODCALLTYPE GetHandleFromThread( - /* [in] */ ThreadID threadId, - /* [out] */ HANDLE *phThread) = 0; + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerCallback8 * This); - virtual HRESULT STDMETHODCALLTYPE GetObjectSize( - /* [in] */ ObjectID objectId, - /* [out] */ ULONG *pcSize) = 0; + HRESULT ( STDMETHODCALLTYPE *Initialize )( + ICorProfilerCallback8 * This, + /* [in] */ IUnknown *pICorProfilerInfoUnk); - virtual HRESULT STDMETHODCALLTYPE IsArrayClass( - /* [in] */ ClassID classId, - /* [out] */ CorElementType *pBaseElemType, - /* [out] */ ClassID *pBaseClassId, - /* [out] */ ULONG *pcRank) = 0; + HRESULT ( STDMETHODCALLTYPE *Shutdown )( + ICorProfilerCallback8 * This); - virtual HRESULT STDMETHODCALLTYPE GetThreadInfo( - /* [in] */ ThreadID threadId, - /* [out] */ DWORD *pdwWin32ThreadId) = 0; + HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( + ICorProfilerCallback8 * This, + /* [in] */ AppDomainID appDomainId); - virtual HRESULT STDMETHODCALLTYPE GetCurrentThreadID( - /* [out] */ ThreadID *pThreadId) = 0; + HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( + ICorProfilerCallback8 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus); - virtual HRESULT STDMETHODCALLTYPE GetClassIDInfo( - /* [in] */ ClassID classId, - /* [out] */ ModuleID *pModuleId, - /* [out] */ mdTypeDef *pTypeDefToken) = 0; + HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( + ICorProfilerCallback8 * This, + /* [in] */ AppDomainID appDomainId); - virtual HRESULT STDMETHODCALLTYPE GetFunctionInfo( - /* [in] */ FunctionID functionId, - /* [out] */ ClassID *pClassId, - /* [out] */ ModuleID *pModuleId, - /* [out] */ mdToken *pToken) = 0; + HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( + ICorProfilerCallback8 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus); - virtual HRESULT STDMETHODCALLTYPE SetEventMask( - /* [in] */ DWORD dwEvents) = 0; + HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( + ICorProfilerCallback8 * This, + /* [in] */ AssemblyID assemblyId); - virtual HRESULT STDMETHODCALLTYPE SetEnterLeaveFunctionHooks( - /* [in] */ FunctionEnter *pFuncEnter, - /* [in] */ FunctionLeave *pFuncLeave, - /* [in] */ FunctionTailcall *pFuncTailcall) = 0; + HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( + ICorProfilerCallback8 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus); - virtual HRESULT STDMETHODCALLTYPE SetFunctionIDMapper( - /* [in] */ FunctionIDMapper *pFunc) = 0; + HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( + ICorProfilerCallback8 * This, + /* [in] */ AssemblyID assemblyId); - virtual HRESULT STDMETHODCALLTYPE GetTokenAndMetaDataFromFunction( - /* [in] */ FunctionID functionId, - /* [in] */ REFIID riid, - /* [out] */ IUnknown **ppImport, - /* [out] */ mdToken *pToken) = 0; + HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( + ICorProfilerCallback8 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus); - virtual HRESULT STDMETHODCALLTYPE GetModuleInfo( - /* [in] */ ModuleID moduleId, - /* [out] */ LPCBYTE *ppBaseLoadAddress, - /* [in] */ ULONG cchName, - /* [out] */ ULONG *pcchName, - /* [annotation][out] */ - _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], - /* [out] */ AssemblyID *pAssemblyId) = 0; + HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( + ICorProfilerCallback8 * This, + /* [in] */ ModuleID moduleId); - virtual HRESULT STDMETHODCALLTYPE GetModuleMetaData( + HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( + ICorProfilerCallback8 * This, /* [in] */ ModuleID moduleId, - /* [in] */ DWORD dwOpenFlags, - /* [in] */ REFIID riid, - /* [out] */ IUnknown **ppOut) = 0; + /* [in] */ HRESULT hrStatus); - virtual HRESULT STDMETHODCALLTYPE GetILFunctionBody( - /* [in] */ ModuleID moduleId, - /* [in] */ mdMethodDef methodId, - /* [out] */ LPCBYTE *ppMethodHeader, - /* [out] */ ULONG *pcbMethodSize) = 0; + HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( + ICorProfilerCallback8 * This, + /* [in] */ ModuleID moduleId); - virtual HRESULT STDMETHODCALLTYPE GetILFunctionBodyAllocator( + HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( + ICorProfilerCallback8 * This, /* [in] */ ModuleID moduleId, - /* [out] */ IMethodMalloc **ppMalloc) = 0; + /* [in] */ HRESULT hrStatus); - virtual HRESULT STDMETHODCALLTYPE SetILFunctionBody( + HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( + ICorProfilerCallback8 * This, /* [in] */ ModuleID moduleId, - /* [in] */ mdMethodDef methodid, - /* [in] */ LPCBYTE pbNewILMethodHeader) = 0; + /* [in] */ AssemblyID AssemblyId); - virtual HRESULT STDMETHODCALLTYPE GetAppDomainInfo( - /* [in] */ AppDomainID appDomainId, - /* [in] */ ULONG cchName, - /* [out] */ ULONG *pcchName, - /* [annotation][out] */ - _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], - /* [out] */ ProcessID *pProcessId) = 0; + HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( + ICorProfilerCallback8 * This, + /* [in] */ ClassID classId); - virtual HRESULT STDMETHODCALLTYPE GetAssemblyInfo( - /* [in] */ AssemblyID assemblyId, - /* [in] */ ULONG cchName, - /* [out] */ ULONG *pcchName, - /* [annotation][out] */ - _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], - /* [out] */ AppDomainID *pAppDomainId, - /* [out] */ ModuleID *pModuleId) = 0; + HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( + ICorProfilerCallback8 * This, + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus); - virtual HRESULT STDMETHODCALLTYPE SetFunctionReJIT( - /* [in] */ FunctionID functionId) = 0; + HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( + ICorProfilerCallback8 * This, + /* [in] */ ClassID classId); - virtual HRESULT STDMETHODCALLTYPE ForceGC( void) = 0; + HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( + ICorProfilerCallback8 * This, + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus); - virtual HRESULT STDMETHODCALLTYPE SetILInstrumentedCodeMap( + HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( + ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId, - /* [in] */ BOOL fStartJit, - /* [in] */ ULONG cILMapEntries, - /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]) = 0; + /* [in] */ BOOL fIsSafeToBlock); - virtual HRESULT STDMETHODCALLTYPE GetInprocInspectionInterface( - /* [out] */ IUnknown **ppicd) = 0; + HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock); - virtual HRESULT STDMETHODCALLTYPE GetInprocInspectionIThisThread( - /* [out] */ IUnknown **ppicd) = 0; + HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId, + /* [out] */ BOOL *pbUseCachedFunction); - virtual HRESULT STDMETHODCALLTYPE GetThreadContext( - /* [in] */ ThreadID threadId, - /* [out] */ ContextID *pContextId) = 0; + HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_JIT_CACHE result); - virtual HRESULT STDMETHODCALLTYPE BeginInprocDebugging( - /* [in] */ BOOL fThisThreadOnly, - /* [out] */ DWORD *pdwProfilerContext) = 0; + HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId); - virtual HRESULT STDMETHODCALLTYPE EndInprocDebugging( - /* [in] */ DWORD dwProfilerContext) = 0; + HRESULT ( STDMETHODCALLTYPE *JITInlining )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID callerId, + /* [in] */ FunctionID calleeId, + /* [out] */ BOOL *pfShouldInline); - virtual HRESULT STDMETHODCALLTYPE GetILToNativeMapping( - /* [in] */ FunctionID functionId, - /* [in] */ ULONG32 cMap, - /* [out] */ ULONG32 *pcMap, - /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]) = 0; + HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( + ICorProfilerCallback8 * This, + /* [in] */ ThreadID threadId); - }; - - -#else /* C style interface */ - - typedef struct ICorProfilerInfoVtbl - { - BEGIN_INTERFACE + HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( + ICorProfilerCallback8 * This, + /* [in] */ ThreadID threadId); - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - ICorProfilerInfo * This, - /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ - _COM_Outptr_ void **ppvObject); + HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( + ICorProfilerCallback8 * This, + /* [in] */ ThreadID managedThreadId, + /* [in] */ DWORD osThreadId); - ULONG ( STDMETHODCALLTYPE *AddRef )( - ICorProfilerInfo * This); + HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( + ICorProfilerCallback8 * This); - ULONG ( STDMETHODCALLTYPE *Release )( - ICorProfilerInfo * This); + HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( + ICorProfilerCallback8 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); - HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( - ICorProfilerInfo * This, - /* [in] */ ObjectID objectId, - /* [out] */ ClassID *pClassId); + HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( + ICorProfilerCallback8 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); - HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( - ICorProfilerInfo * This, - /* [in] */ ModuleID moduleId, - /* [in] */ mdTypeDef typeDef, - /* [out] */ ClassID *pClassId); + HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( + ICorProfilerCallback8 * This); - HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( - ICorProfilerInfo * This, + HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( + ICorProfilerCallback8 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( + ICorProfilerCallback8 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( + ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId, - /* [out] */ LPCBYTE *pStart, - /* [out] */ ULONG *pcSize); + /* [in] */ COR_PRF_TRANSITION_REASON reason); - HRESULT ( STDMETHODCALLTYPE *GetEventMask )( - ICorProfilerInfo * This, - /* [out] */ DWORD *pdwEvents); + HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason); - HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( - ICorProfilerInfo * This, - /* [in] */ LPCBYTE ip, - /* [out] */ FunctionID *pFunctionId); + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( + ICorProfilerCallback8 * This, + /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); - HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( - ICorProfilerInfo * This, - /* [in] */ ModuleID moduleId, - /* [in] */ mdToken token, - /* [out] */ FunctionID *pFunctionId); + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( + ICorProfilerCallback8 * This); - HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( - ICorProfilerInfo * This, - /* [in] */ ThreadID threadId, - /* [out] */ HANDLE *phThread); + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( + ICorProfilerCallback8 * This); - HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( - ICorProfilerInfo * This, - /* [in] */ ObjectID objectId, - /* [out] */ ULONG *pcSize); + HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( + ICorProfilerCallback8 * This); - HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( - ICorProfilerInfo * This, - /* [in] */ ClassID classId, - /* [out] */ CorElementType *pBaseElemType, - /* [out] */ ClassID *pBaseClassId, - /* [out] */ ULONG *pcRank); + HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( + ICorProfilerCallback8 * This); - HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( - ICorProfilerInfo * This, - /* [in] */ ThreadID threadId, - /* [out] */ DWORD *pdwWin32ThreadId); + HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( + ICorProfilerCallback8 * This, + /* [in] */ ThreadID threadId); - HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( - ICorProfilerInfo * This, - /* [out] */ ThreadID *pThreadId); + HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( + ICorProfilerCallback8 * This, + /* [in] */ ThreadID threadId); - HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( - ICorProfilerInfo * This, - /* [in] */ ClassID classId, - /* [out] */ ModuleID *pModuleId, - /* [out] */ mdTypeDef *pTypeDefToken); + HRESULT ( STDMETHODCALLTYPE *MovedReferences )( + ICorProfilerCallback8 * This, + /* [in] */ ULONG cMovedObjectIDRanges, + /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], + /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); - HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( - ICorProfilerInfo * This, - /* [in] */ FunctionID functionId, - /* [out] */ ClassID *pClassId, - /* [out] */ ModuleID *pModuleId, - /* [out] */ mdToken *pToken); + HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( + ICorProfilerCallback8 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId); - HRESULT ( STDMETHODCALLTYPE *SetEventMask )( - ICorProfilerInfo * This, - /* [in] */ DWORD dwEvents); + HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( + ICorProfilerCallback8 * This, + /* [in] */ ULONG cClassCount, + /* [size_is][in] */ ClassID classIds[ ], + /* [size_is][in] */ ULONG cObjects[ ]); - HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( - ICorProfilerInfo * This, - /* [in] */ FunctionEnter *pFuncEnter, - /* [in] */ FunctionLeave *pFuncLeave, - /* [in] */ FunctionTailcall *pFuncTailcall); + HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( + ICorProfilerCallback8 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId, + /* [in] */ ULONG cObjectRefs, + /* [size_is][in] */ ObjectID objectRefIds[ ]); - HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( - ICorProfilerInfo * This, - /* [in] */ FunctionIDMapper *pFunc); + HRESULT ( STDMETHODCALLTYPE *RootReferences )( + ICorProfilerCallback8 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ]); - HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( - ICorProfilerInfo * This, - /* [in] */ FunctionID functionId, - /* [in] */ REFIID riid, - /* [out] */ IUnknown **ppImport, - /* [out] */ mdToken *pToken); + HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( + ICorProfilerCallback8 * This, + /* [in] */ ObjectID thrownObjectId); - HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( - ICorProfilerInfo * This, - /* [in] */ ModuleID moduleId, - /* [out] */ LPCBYTE *ppBaseLoadAddress, - /* [in] */ ULONG cchName, - /* [out] */ ULONG *pcchName, - /* [annotation][out] */ - _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], - /* [out] */ AssemblyID *pAssemblyId); + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId); - HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( - ICorProfilerInfo * This, - /* [in] */ ModuleID moduleId, - /* [in] */ DWORD dwOpenFlags, - /* [in] */ REFIID riid, - /* [out] */ IUnknown **ppOut); + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( + ICorProfilerCallback8 * This); - HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( - ICorProfilerInfo * This, - /* [in] */ ModuleID moduleId, - /* [in] */ mdMethodDef methodId, - /* [out] */ LPCBYTE *ppMethodHeader, - /* [out] */ ULONG *pcbMethodSize); + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId); - HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( - ICorProfilerInfo * This, - /* [in] */ ModuleID moduleId, - /* [out] */ IMethodMalloc **ppMalloc); + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( + ICorProfilerCallback8 * This); - HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( - ICorProfilerInfo * This, - /* [in] */ ModuleID moduleId, - /* [in] */ mdMethodDef methodid, - /* [in] */ LPCBYTE pbNewILMethodHeader); + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId); - HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( - ICorProfilerInfo * This, - /* [in] */ AppDomainID appDomainId, - /* [in] */ ULONG cchName, - /* [out] */ ULONG *pcchName, - /* [annotation][out] */ - _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], - /* [out] */ ProcessID *pProcessId); + HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( + ICorProfilerCallback8 * This, + /* [in] */ UINT_PTR __unused); - HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( - ICorProfilerInfo * This, - /* [in] */ AssemblyID assemblyId, - /* [in] */ ULONG cchName, - /* [out] */ ULONG *pcchName, - /* [annotation][out] */ - _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], - /* [out] */ AppDomainID *pAppDomainId, - /* [out] */ ModuleID *pModuleId); + HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( + ICorProfilerCallback8 * This, + /* [in] */ UINT_PTR __unused); - HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( - ICorProfilerInfo * This, + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( + ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId); - HRESULT ( STDMETHODCALLTYPE *ForceGC )( - ICorProfilerInfo * This); + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( + ICorProfilerCallback8 * This); - HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( - ICorProfilerInfo * This, + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( + ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId, - /* [in] */ BOOL fStartJit, - /* [in] */ ULONG cILMapEntries, - /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); + /* [in] */ ObjectID objectId); - HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( - ICorProfilerInfo * This, - /* [out] */ IUnknown **ppicd); + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( + ICorProfilerCallback8 * This); - HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( - ICorProfilerInfo * This, - /* [out] */ IUnknown **ppicd); + HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( + ICorProfilerCallback8 * This, + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable, + /* [in] */ ULONG cSlots); - HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( - ICorProfilerInfo * This, + HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( + ICorProfilerCallback8 * This, + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *ThreadNameChanged )( + ICorProfilerCallback8 * This, /* [in] */ ThreadID threadId, - /* [out] */ ContextID *pContextId); + /* [in] */ ULONG cchName, + /* [annotation][in] */ + _In_reads_opt_(cchName) WCHAR name[ ]); - HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( - ICorProfilerInfo * This, - /* [in] */ BOOL fThisThreadOnly, - /* [out] */ DWORD *pdwProfilerContext); + HRESULT ( STDMETHODCALLTYPE *GarbageCollectionStarted )( + ICorProfilerCallback8 * This, + /* [in] */ int cGenerations, + /* [size_is][in] */ BOOL generationCollected[ ], + /* [in] */ COR_PRF_GC_REASON reason); - HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( - ICorProfilerInfo * This, - /* [in] */ DWORD dwProfilerContext); + HRESULT ( STDMETHODCALLTYPE *SurvivingReferences )( + ICorProfilerCallback8 * This, + /* [in] */ ULONG cSurvivingObjectIDRanges, + /* [size_is][in] */ ObjectID objectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); - HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( - ICorProfilerInfo * This, - /* [in] */ FunctionID functionId, - /* [in] */ ULONG32 cMap, - /* [out] */ ULONG32 *pcMap, - /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + HRESULT ( STDMETHODCALLTYPE *GarbageCollectionFinished )( + ICorProfilerCallback8 * This); - END_INTERFACE - } ICorProfilerInfoVtbl; - - interface ICorProfilerInfo - { - CONST_VTBL struct ICorProfilerInfoVtbl *lpVtbl; + HRESULT ( STDMETHODCALLTYPE *FinalizeableObjectQueued )( + ICorProfilerCallback8 * This, + /* [in] */ DWORD finalizerFlags, + /* [in] */ ObjectID objectID); + + HRESULT ( STDMETHODCALLTYPE *RootReferences2 )( + ICorProfilerCallback8 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ], + /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], + /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], + /* [size_is][in] */ UINT_PTR rootIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *HandleCreated )( + ICorProfilerCallback8 * This, + /* [in] */ GCHandleID handleId, + /* [in] */ ObjectID initialObjectId); + + HRESULT ( STDMETHODCALLTYPE *HandleDestroyed )( + ICorProfilerCallback8 * This, + /* [in] */ GCHandleID handleId); + + HRESULT ( STDMETHODCALLTYPE *InitializeForAttach )( + ICorProfilerCallback8 * This, + /* [in] */ IUnknown *pCorProfilerInfoUnk, + /* [in] */ void *pvClientData, + /* [in] */ UINT cbClientData); + + HRESULT ( STDMETHODCALLTYPE *ProfilerAttachComplete )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *ProfilerDetachSucceeded )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *ReJITCompilationStarted )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID rejitId, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *GetReJITParameters )( + ICorProfilerCallback8 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [in] */ ICorProfilerFunctionControl *pFunctionControl); + + HRESULT ( STDMETHODCALLTYPE *ReJITCompilationFinished )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID rejitId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *ReJITError )( + ICorProfilerCallback8 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *MovedReferences2 )( + ICorProfilerCallback8 * This, + /* [in] */ ULONG cMovedObjectIDRanges, + /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], + /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], + /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *SurvivingReferences2 )( + ICorProfilerCallback8 * This, + /* [in] */ ULONG cSurvivingObjectIDRanges, + /* [size_is][in] */ ObjectID objectIDRangeStart[ ], + /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *ConditionalWeakTableElementReferences )( + ICorProfilerCallback8 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID keyRefIds[ ], + /* [size_is][in] */ ObjectID valueRefIds[ ], + /* [size_is][in] */ GCHandleID rootIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyReferences )( + ICorProfilerCallback8 * This, + /* [string][in] */ const WCHAR *wszAssemblyPath, + /* [in] */ ICorProfilerAssemblyReferenceProvider *pAsmRefProvider); + + HRESULT ( STDMETHODCALLTYPE *ModuleInMemorySymbolsUpdated )( + ICorProfilerCallback8 * This, + ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *DynamicMethodJITCompilationStarted )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fIsSafeToBlock, + /* [in] */ LPCBYTE pILHeader, + /* [in] */ ULONG cbILHeader); + + HRESULT ( STDMETHODCALLTYPE *DynamicMethodJITCompilationFinished )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock); + + END_INTERFACE + } ICorProfilerCallback8Vtbl; + + interface ICorProfilerCallback8 + { + CONST_VTBL struct ICorProfilerCallback8Vtbl *lpVtbl; }; @@ -6216,380 +6310,608 @@ EXTERN_C const IID IID_ICorProfilerInfo; #ifdef COBJMACROS -#define ICorProfilerInfo_QueryInterface(This,riid,ppvObject) \ +#define ICorProfilerCallback8_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ICorProfilerInfo_AddRef(This) \ +#define ICorProfilerCallback8_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) -#define ICorProfilerInfo_Release(This) \ +#define ICorProfilerCallback8_Release(This) \ ( (This)->lpVtbl -> Release(This) ) -#define ICorProfilerInfo_GetClassFromObject(This,objectId,pClassId) \ - ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) +#define ICorProfilerCallback8_Initialize(This,pICorProfilerInfoUnk) \ + ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) -#define ICorProfilerInfo_GetClassFromToken(This,moduleId,typeDef,pClassId) \ - ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) +#define ICorProfilerCallback8_Shutdown(This) \ + ( (This)->lpVtbl -> Shutdown(This) ) -#define ICorProfilerInfo_GetCodeInfo(This,functionId,pStart,pcSize) \ - ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) +#define ICorProfilerCallback8_AppDomainCreationStarted(This,appDomainId) \ + ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) -#define ICorProfilerInfo_GetEventMask(This,pdwEvents) \ - ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) +#define ICorProfilerCallback8_AppDomainCreationFinished(This,appDomainId,hrStatus) \ + ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) -#define ICorProfilerInfo_GetFunctionFromIP(This,ip,pFunctionId) \ - ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) +#define ICorProfilerCallback8_AppDomainShutdownStarted(This,appDomainId) \ + ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) -#define ICorProfilerInfo_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ - ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) +#define ICorProfilerCallback8_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ + ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) -#define ICorProfilerInfo_GetHandleFromThread(This,threadId,phThread) \ - ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) +#define ICorProfilerCallback8_AssemblyLoadStarted(This,assemblyId) \ + ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) -#define ICorProfilerInfo_GetObjectSize(This,objectId,pcSize) \ - ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) +#define ICorProfilerCallback8_AssemblyLoadFinished(This,assemblyId,hrStatus) \ + ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) -#define ICorProfilerInfo_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ - ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) +#define ICorProfilerCallback8_AssemblyUnloadStarted(This,assemblyId) \ + ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) -#define ICorProfilerInfo_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ - ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) +#define ICorProfilerCallback8_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ + ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) -#define ICorProfilerInfo_GetCurrentThreadID(This,pThreadId) \ - ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) +#define ICorProfilerCallback8_ModuleLoadStarted(This,moduleId) \ + ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) -#define ICorProfilerInfo_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ - ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) +#define ICorProfilerCallback8_ModuleLoadFinished(This,moduleId,hrStatus) \ + ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) -#define ICorProfilerInfo_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ - ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) +#define ICorProfilerCallback8_ModuleUnloadStarted(This,moduleId) \ + ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) -#define ICorProfilerInfo_SetEventMask(This,dwEvents) \ - ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) +#define ICorProfilerCallback8_ModuleUnloadFinished(This,moduleId,hrStatus) \ + ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) -#define ICorProfilerInfo_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ - ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) +#define ICorProfilerCallback8_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ + ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) -#define ICorProfilerInfo_SetFunctionIDMapper(This,pFunc) \ - ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) +#define ICorProfilerCallback8_ClassLoadStarted(This,classId) \ + ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) -#define ICorProfilerInfo_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ - ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) +#define ICorProfilerCallback8_ClassLoadFinished(This,classId,hrStatus) \ + ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) -#define ICorProfilerInfo_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ - ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) +#define ICorProfilerCallback8_ClassUnloadStarted(This,classId) \ + ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) -#define ICorProfilerInfo_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ - ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) +#define ICorProfilerCallback8_ClassUnloadFinished(This,classId,hrStatus) \ + ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) -#define ICorProfilerInfo_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ - ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) +#define ICorProfilerCallback8_FunctionUnloadStarted(This,functionId) \ + ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) -#define ICorProfilerInfo_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ - ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) +#define ICorProfilerCallback8_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ + ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) -#define ICorProfilerInfo_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ - ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) +#define ICorProfilerCallback8_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ + ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) -#define ICorProfilerInfo_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ - ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) +#define ICorProfilerCallback8_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ + ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) -#define ICorProfilerInfo_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ - ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) +#define ICorProfilerCallback8_JITCachedFunctionSearchFinished(This,functionId,result) \ + ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) -#define ICorProfilerInfo_SetFunctionReJIT(This,functionId) \ - ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) +#define ICorProfilerCallback8_JITFunctionPitched(This,functionId) \ + ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) -#define ICorProfilerInfo_ForceGC(This) \ - ( (This)->lpVtbl -> ForceGC(This) ) +#define ICorProfilerCallback8_JITInlining(This,callerId,calleeId,pfShouldInline) \ + ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) -#define ICorProfilerInfo_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ - ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) +#define ICorProfilerCallback8_ThreadCreated(This,threadId) \ + ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) -#define ICorProfilerInfo_GetInprocInspectionInterface(This,ppicd) \ - ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) +#define ICorProfilerCallback8_ThreadDestroyed(This,threadId) \ + ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) -#define ICorProfilerInfo_GetInprocInspectionIThisThread(This,ppicd) \ - ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) +#define ICorProfilerCallback8_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ + ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) -#define ICorProfilerInfo_GetThreadContext(This,threadId,pContextId) \ - ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) +#define ICorProfilerCallback8_RemotingClientInvocationStarted(This) \ + ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) -#define ICorProfilerInfo_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ - ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) +#define ICorProfilerCallback8_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) -#define ICorProfilerInfo_EndInprocDebugging(This,dwProfilerContext) \ - ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) +#define ICorProfilerCallback8_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) -#define ICorProfilerInfo_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ - ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) +#define ICorProfilerCallback8_RemotingClientInvocationFinished(This) \ + ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) -#endif /* COBJMACROS */ +#define ICorProfilerCallback8_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) +#define ICorProfilerCallback8_RemotingServerInvocationStarted(This) \ + ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) -#endif /* C style interface */ +#define ICorProfilerCallback8_RemotingServerInvocationReturned(This) \ + ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) +#define ICorProfilerCallback8_RemotingServerSendingReply(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) +#define ICorProfilerCallback8_UnmanagedToManagedTransition(This,functionId,reason) \ + ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) +#define ICorProfilerCallback8_ManagedToUnmanagedTransition(This,functionId,reason) \ + ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) -#endif /* __ICorProfilerInfo_INTERFACE_DEFINED__ */ +#define ICorProfilerCallback8_RuntimeSuspendStarted(This,suspendReason) \ + ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) +#define ICorProfilerCallback8_RuntimeSuspendFinished(This) \ + ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) -#ifndef __ICorProfilerInfo2_INTERFACE_DEFINED__ -#define __ICorProfilerInfo2_INTERFACE_DEFINED__ +#define ICorProfilerCallback8_RuntimeSuspendAborted(This) \ + ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) -/* interface ICorProfilerInfo2 */ -/* [local][unique][uuid][object] */ +#define ICorProfilerCallback8_RuntimeResumeStarted(This) \ + ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) +#define ICorProfilerCallback8_RuntimeResumeFinished(This) \ + ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) -EXTERN_C const IID IID_ICorProfilerInfo2; +#define ICorProfilerCallback8_RuntimeThreadSuspended(This,threadId) \ + ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("CC0935CD-A518-487d-B0BB-A93214E65478") - ICorProfilerInfo2 : public ICorProfilerInfo - { - public: - virtual HRESULT STDMETHODCALLTYPE DoStackSnapshot( - /* [in] */ ThreadID thread, - /* [in] */ StackSnapshotCallback *callback, - /* [in] */ ULONG32 infoFlags, - /* [in] */ void *clientData, - /* [size_is][in] */ BYTE context[ ], - /* [in] */ ULONG32 contextSize) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetEnterLeaveFunctionHooks2( - /* [in] */ FunctionEnter2 *pFuncEnter, - /* [in] */ FunctionLeave2 *pFuncLeave, - /* [in] */ FunctionTailcall2 *pFuncTailcall) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFunctionInfo2( - /* [in] */ FunctionID funcId, - /* [in] */ COR_PRF_FRAME_INFO frameInfo, - /* [out] */ ClassID *pClassId, - /* [out] */ ModuleID *pModuleId, - /* [out] */ mdToken *pToken, - /* [in] */ ULONG32 cTypeArgs, - /* [out] */ ULONG32 *pcTypeArgs, - /* [out] */ ClassID typeArgs[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetStringLayout( - /* [out] */ ULONG *pBufferLengthOffset, - /* [out] */ ULONG *pStringLengthOffset, - /* [out] */ ULONG *pBufferOffset) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetClassLayout( - /* [in] */ ClassID classID, - /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], - /* [in] */ ULONG cFieldOffset, - /* [out] */ ULONG *pcFieldOffset, - /* [out] */ ULONG *pulClassSize) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetClassIDInfo2( - /* [in] */ ClassID classId, - /* [out] */ ModuleID *pModuleId, - /* [out] */ mdTypeDef *pTypeDefToken, - /* [out] */ ClassID *pParentClassId, - /* [in] */ ULONG32 cNumTypeArgs, - /* [out] */ ULONG32 *pcNumTypeArgs, - /* [out] */ ClassID typeArgs[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCodeInfo2( - /* [in] */ FunctionID functionID, - /* [in] */ ULONG32 cCodeInfos, - /* [out] */ ULONG32 *pcCodeInfos, - /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]) = 0; +#define ICorProfilerCallback8_RuntimeThreadResumed(This,threadId) \ + ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) + +#define ICorProfilerCallback8_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback8_ObjectAllocated(This,objectId,classId) \ + ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) + +#define ICorProfilerCallback8_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ + ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) + +#define ICorProfilerCallback8_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ + ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) + +#define ICorProfilerCallback8_RootReferences(This,cRootRefs,rootRefIds) \ + ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) + +#define ICorProfilerCallback8_ExceptionThrown(This,thrownObjectId) \ + ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) + +#define ICorProfilerCallback8_ExceptionSearchFunctionEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) + +#define ICorProfilerCallback8_ExceptionSearchFunctionLeave(This) \ + ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) + +#define ICorProfilerCallback8_ExceptionSearchFilterEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) + +#define ICorProfilerCallback8_ExceptionSearchFilterLeave(This) \ + ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) + +#define ICorProfilerCallback8_ExceptionSearchCatcherFound(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) + +#define ICorProfilerCallback8_ExceptionOSHandlerEnter(This,__unused) \ + ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) + +#define ICorProfilerCallback8_ExceptionOSHandlerLeave(This,__unused) \ + ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) + +#define ICorProfilerCallback8_ExceptionUnwindFunctionEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) + +#define ICorProfilerCallback8_ExceptionUnwindFunctionLeave(This) \ + ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) + +#define ICorProfilerCallback8_ExceptionUnwindFinallyEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) + +#define ICorProfilerCallback8_ExceptionUnwindFinallyLeave(This) \ + ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) + +#define ICorProfilerCallback8_ExceptionCatcherEnter(This,functionId,objectId) \ + ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) + +#define ICorProfilerCallback8_ExceptionCatcherLeave(This) \ + ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) + +#define ICorProfilerCallback8_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ + ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) + +#define ICorProfilerCallback8_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ + ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) + +#define ICorProfilerCallback8_ExceptionCLRCatcherFound(This) \ + ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) + +#define ICorProfilerCallback8_ExceptionCLRCatcherExecute(This) \ + ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) + + +#define ICorProfilerCallback8_ThreadNameChanged(This,threadId,cchName,name) \ + ( (This)->lpVtbl -> ThreadNameChanged(This,threadId,cchName,name) ) + +#define ICorProfilerCallback8_GarbageCollectionStarted(This,cGenerations,generationCollected,reason) \ + ( (This)->lpVtbl -> GarbageCollectionStarted(This,cGenerations,generationCollected,reason) ) + +#define ICorProfilerCallback8_SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback8_GarbageCollectionFinished(This) \ + ( (This)->lpVtbl -> GarbageCollectionFinished(This) ) + +#define ICorProfilerCallback8_FinalizeableObjectQueued(This,finalizerFlags,objectID) \ + ( (This)->lpVtbl -> FinalizeableObjectQueued(This,finalizerFlags,objectID) ) + +#define ICorProfilerCallback8_RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) \ + ( (This)->lpVtbl -> RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) ) + +#define ICorProfilerCallback8_HandleCreated(This,handleId,initialObjectId) \ + ( (This)->lpVtbl -> HandleCreated(This,handleId,initialObjectId) ) + +#define ICorProfilerCallback8_HandleDestroyed(This,handleId) \ + ( (This)->lpVtbl -> HandleDestroyed(This,handleId) ) + + +#define ICorProfilerCallback8_InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) \ + ( (This)->lpVtbl -> InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) ) + +#define ICorProfilerCallback8_ProfilerAttachComplete(This) \ + ( (This)->lpVtbl -> ProfilerAttachComplete(This) ) + +#define ICorProfilerCallback8_ProfilerDetachSucceeded(This) \ + ( (This)->lpVtbl -> ProfilerDetachSucceeded(This) ) + + +#define ICorProfilerCallback8_ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) \ + ( (This)->lpVtbl -> ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) ) + +#define ICorProfilerCallback8_GetReJITParameters(This,moduleId,methodId,pFunctionControl) \ + ( (This)->lpVtbl -> GetReJITParameters(This,moduleId,methodId,pFunctionControl) ) + +#define ICorProfilerCallback8_ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) \ + ( (This)->lpVtbl -> ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) ) + +#define ICorProfilerCallback8_ReJITError(This,moduleId,methodId,functionId,hrStatus) \ + ( (This)->lpVtbl -> ReJITError(This,moduleId,methodId,functionId,hrStatus) ) + +#define ICorProfilerCallback8_MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback8_SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) + + +#define ICorProfilerCallback8_ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) \ + ( (This)->lpVtbl -> ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) ) + + +#define ICorProfilerCallback8_GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) \ + ( (This)->lpVtbl -> GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) ) + + +#define ICorProfilerCallback8_ModuleInMemorySymbolsUpdated(This,moduleId) \ + ( (This)->lpVtbl -> ModuleInMemorySymbolsUpdated(This,moduleId) ) + + +#define ICorProfilerCallback8_DynamicMethodJITCompilationStarted(This,functionId,fIsSafeToBlock,pILHeader,cbILHeader) \ + ( (This)->lpVtbl -> DynamicMethodJITCompilationStarted(This,functionId,fIsSafeToBlock,pILHeader,cbILHeader) ) + +#define ICorProfilerCallback8_DynamicMethodJITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ + ( (This)->lpVtbl -> DynamicMethodJITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerCallback8_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_corprof_0000_0008 */ +/* [local] */ + +typedef /* [public] */ +enum __MIDL___MIDL_itf_corprof_0000_0008_0001 + { + COR_PRF_CODEGEN_DISABLE_INLINING = 0x1, + COR_PRF_CODEGEN_DISABLE_ALL_OPTIMIZATIONS = 0x2 + } COR_PRF_CODEGEN_FLAGS; + + + +extern RPC_IF_HANDLE __MIDL_itf_corprof_0000_0008_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_corprof_0000_0008_v0_0_s_ifspec; + +#ifndef __ICorProfilerInfo_INTERFACE_DEFINED__ +#define __ICorProfilerInfo_INTERFACE_DEFINED__ + +/* interface ICorProfilerInfo */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerInfo; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("28B5557D-3F3F-48b4-90B2-5F9EEA2F6C48") + ICorProfilerInfo : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetClassFromObject( + /* [in] */ ObjectID objectId, + /* [out] */ ClassID *pClassId) = 0; - virtual HRESULT STDMETHODCALLTYPE GetClassFromTokenAndTypeArgs( - /* [in] */ ModuleID moduleID, + virtual HRESULT STDMETHODCALLTYPE GetClassFromToken( + /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, - /* [in] */ ULONG32 cTypeArgs, - /* [size_is][in] */ ClassID typeArgs[ ], - /* [out] */ ClassID *pClassID) = 0; + /* [out] */ ClassID *pClassId) = 0; - virtual HRESULT STDMETHODCALLTYPE GetFunctionFromTokenAndTypeArgs( - /* [in] */ ModuleID moduleID, - /* [in] */ mdMethodDef funcDef, - /* [in] */ ClassID classId, - /* [in] */ ULONG32 cTypeArgs, - /* [size_is][in] */ ClassID typeArgs[ ], - /* [out] */ FunctionID *pFunctionID) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCodeInfo( + /* [in] */ FunctionID functionId, + /* [out] */ LPCBYTE *pStart, + /* [out] */ ULONG *pcSize) = 0; - virtual HRESULT STDMETHODCALLTYPE EnumModuleFrozenObjects( - /* [in] */ ModuleID moduleID, - /* [out] */ ICorProfilerObjectEnum **ppEnum) = 0; + virtual HRESULT STDMETHODCALLTYPE GetEventMask( + /* [out] */ DWORD *pdwEvents) = 0; - virtual HRESULT STDMETHODCALLTYPE GetArrayObjectInfo( - /* [in] */ ObjectID objectId, - /* [in] */ ULONG32 cDimensions, - /* [size_is][out] */ ULONG32 pDimensionSizes[ ], - /* [size_is][out] */ int pDimensionLowerBounds[ ], - /* [out] */ BYTE **ppData) = 0; + virtual HRESULT STDMETHODCALLTYPE GetFunctionFromIP( + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId) = 0; - virtual HRESULT STDMETHODCALLTYPE GetBoxClassLayout( - /* [in] */ ClassID classId, - /* [out] */ ULONG32 *pBufferOffset) = 0; + virtual HRESULT STDMETHODCALLTYPE GetFunctionFromToken( + /* [in] */ ModuleID moduleId, + /* [in] */ mdToken token, + /* [out] */ FunctionID *pFunctionId) = 0; - virtual HRESULT STDMETHODCALLTYPE GetThreadAppDomain( + virtual HRESULT STDMETHODCALLTYPE GetHandleFromThread( /* [in] */ ThreadID threadId, - /* [out] */ AppDomainID *pAppDomainId) = 0; + /* [out] */ HANDLE *phThread) = 0; - virtual HRESULT STDMETHODCALLTYPE GetRVAStaticAddress( - /* [in] */ ClassID classId, - /* [in] */ mdFieldDef fieldToken, - /* [out] */ void **ppAddress) = 0; + virtual HRESULT STDMETHODCALLTYPE GetObjectSize( + /* [in] */ ObjectID objectId, + /* [out] */ ULONG *pcSize) = 0; - virtual HRESULT STDMETHODCALLTYPE GetAppDomainStaticAddress( + virtual HRESULT STDMETHODCALLTYPE IsArrayClass( /* [in] */ ClassID classId, - /* [in] */ mdFieldDef fieldToken, - /* [in] */ AppDomainID appDomainId, - /* [out] */ void **ppAddress) = 0; + /* [out] */ CorElementType *pBaseElemType, + /* [out] */ ClassID *pBaseClassId, + /* [out] */ ULONG *pcRank) = 0; - virtual HRESULT STDMETHODCALLTYPE GetThreadStaticAddress( - /* [in] */ ClassID classId, - /* [in] */ mdFieldDef fieldToken, + virtual HRESULT STDMETHODCALLTYPE GetThreadInfo( /* [in] */ ThreadID threadId, - /* [out] */ void **ppAddress) = 0; + /* [out] */ DWORD *pdwWin32ThreadId) = 0; - virtual HRESULT STDMETHODCALLTYPE GetContextStaticAddress( - /* [in] */ ClassID classId, - /* [in] */ mdFieldDef fieldToken, - /* [in] */ ContextID contextId, - /* [out] */ void **ppAddress) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCurrentThreadID( + /* [out] */ ThreadID *pThreadId) = 0; - virtual HRESULT STDMETHODCALLTYPE GetStaticFieldInfo( + virtual HRESULT STDMETHODCALLTYPE GetClassIDInfo( /* [in] */ ClassID classId, - /* [in] */ mdFieldDef fieldToken, - /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo) = 0; + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken) = 0; - virtual HRESULT STDMETHODCALLTYPE GetGenerationBounds( - /* [in] */ ULONG cObjectRanges, - /* [out] */ ULONG *pcObjectRanges, - /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]) = 0; + virtual HRESULT STDMETHODCALLTYPE GetFunctionInfo( + /* [in] */ FunctionID functionId, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken) = 0; - virtual HRESULT STDMETHODCALLTYPE GetObjectGeneration( - /* [in] */ ObjectID objectId, - /* [out] */ COR_PRF_GC_GENERATION_RANGE *range) = 0; + virtual HRESULT STDMETHODCALLTYPE SetEventMask( + /* [in] */ DWORD dwEvents) = 0; - virtual HRESULT STDMETHODCALLTYPE GetNotifiedExceptionClauseInfo( - /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo) = 0; + virtual HRESULT STDMETHODCALLTYPE SetEnterLeaveFunctionHooks( + /* [in] */ FunctionEnter *pFuncEnter, + /* [in] */ FunctionLeave *pFuncLeave, + /* [in] */ FunctionTailcall *pFuncTailcall) = 0; - }; - - -#else /* C style interface */ - - typedef struct ICorProfilerInfo2Vtbl - { - BEGIN_INTERFACE + virtual HRESULT STDMETHODCALLTYPE SetFunctionIDMapper( + /* [in] */ FunctionIDMapper *pFunc) = 0; - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - ICorProfilerInfo2 * This, + virtual HRESULT STDMETHODCALLTYPE GetTokenAndMetaDataFromFunction( + /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ - _COM_Outptr_ void **ppvObject); + /* [out] */ IUnknown **ppImport, + /* [out] */ mdToken *pToken) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetModuleInfo( + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetModuleMetaData( + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD dwOpenFlags, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppOut) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetILFunctionBody( + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [out] */ LPCBYTE *ppMethodHeader, + /* [out] */ ULONG *pcbMethodSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetILFunctionBodyAllocator( + /* [in] */ ModuleID moduleId, + /* [out] */ IMethodMalloc **ppMalloc) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetILFunctionBody( + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodid, + /* [in] */ LPCBYTE pbNewILMethodHeader) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAppDomainInfo( + /* [in] */ AppDomainID appDomainId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ ProcessID *pProcessId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAssemblyInfo( + /* [in] */ AssemblyID assemblyId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AppDomainID *pAppDomainId, + /* [out] */ ModuleID *pModuleId) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetFunctionReJIT( + /* [in] */ FunctionID functionId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ForceGC( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetILInstrumentedCodeMap( + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fStartJit, + /* [in] */ ULONG cILMapEntries, + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetInprocInspectionInterface( + /* [out] */ IUnknown **ppicd) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetInprocInspectionIThisThread( + /* [out] */ IUnknown **ppicd) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThreadContext( + /* [in] */ ThreadID threadId, + /* [out] */ ContextID *pContextId) = 0; + + virtual HRESULT STDMETHODCALLTYPE BeginInprocDebugging( + /* [in] */ BOOL fThisThreadOnly, + /* [out] */ DWORD *pdwProfilerContext) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndInprocDebugging( + /* [in] */ DWORD dwProfilerContext) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetILToNativeMapping( + /* [in] */ FunctionID functionId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerInfoVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerInfo * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( - ICorProfilerInfo2 * This); + ICorProfilerInfo * This); ULONG ( STDMETHODCALLTYPE *Release )( - ICorProfilerInfo2 * This); + ICorProfilerInfo * This); HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [out] */ DWORD *pdwEvents); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread); HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank); HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId); HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [out] */ ThreadID *pThreadId); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *SetEventMask )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ DWORD dwEvents); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ FunctionIDMapper *pFunc); HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, @@ -6599,32 +6921,32 @@ EXTERN_C const IID IID_ICorProfilerInfo2; /* [out] */ AssemblyID *pAssemblyId); HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc); HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader); HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ AppDomainID appDomainId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, @@ -6633,7 +6955,7 @@ EXTERN_C const IID IID_ICorProfilerInfo2; /* [out] */ ProcessID *pProcessId); HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ AssemblyID assemblyId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, @@ -6643,199 +6965,54 @@ EXTERN_C const IID IID_ICorProfilerInfo2; /* [out] */ ModuleID *pModuleId); HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ForceGC )( - ICorProfilerInfo2 * This); + ICorProfilerInfo * This); HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId); HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext); HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ DWORD dwProfilerContext); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( - ICorProfilerInfo2 * This, + ICorProfilerInfo * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); - HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( - ICorProfilerInfo2 * This, - /* [in] */ ThreadID thread, - /* [in] */ StackSnapshotCallback *callback, - /* [in] */ ULONG32 infoFlags, - /* [in] */ void *clientData, - /* [size_is][in] */ BYTE context[ ], - /* [in] */ ULONG32 contextSize); - - HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( - ICorProfilerInfo2 * This, - /* [in] */ FunctionEnter2 *pFuncEnter, - /* [in] */ FunctionLeave2 *pFuncLeave, - /* [in] */ FunctionTailcall2 *pFuncTailcall); - - HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( - ICorProfilerInfo2 * This, - /* [in] */ FunctionID funcId, - /* [in] */ COR_PRF_FRAME_INFO frameInfo, - /* [out] */ ClassID *pClassId, - /* [out] */ ModuleID *pModuleId, - /* [out] */ mdToken *pToken, - /* [in] */ ULONG32 cTypeArgs, - /* [out] */ ULONG32 *pcTypeArgs, - /* [out] */ ClassID typeArgs[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( - ICorProfilerInfo2 * This, - /* [out] */ ULONG *pBufferLengthOffset, - /* [out] */ ULONG *pStringLengthOffset, - /* [out] */ ULONG *pBufferOffset); - - HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( - ICorProfilerInfo2 * This, - /* [in] */ ClassID classID, - /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], - /* [in] */ ULONG cFieldOffset, - /* [out] */ ULONG *pcFieldOffset, - /* [out] */ ULONG *pulClassSize); - - HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( - ICorProfilerInfo2 * This, - /* [in] */ ClassID classId, - /* [out] */ ModuleID *pModuleId, - /* [out] */ mdTypeDef *pTypeDefToken, - /* [out] */ ClassID *pParentClassId, - /* [in] */ ULONG32 cNumTypeArgs, - /* [out] */ ULONG32 *pcNumTypeArgs, - /* [out] */ ClassID typeArgs[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( - ICorProfilerInfo2 * This, - /* [in] */ FunctionID functionID, - /* [in] */ ULONG32 cCodeInfos, - /* [out] */ ULONG32 *pcCodeInfos, - /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( - ICorProfilerInfo2 * This, - /* [in] */ ModuleID moduleID, - /* [in] */ mdTypeDef typeDef, - /* [in] */ ULONG32 cTypeArgs, - /* [size_is][in] */ ClassID typeArgs[ ], - /* [out] */ ClassID *pClassID); - - HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( - ICorProfilerInfo2 * This, - /* [in] */ ModuleID moduleID, - /* [in] */ mdMethodDef funcDef, - /* [in] */ ClassID classId, - /* [in] */ ULONG32 cTypeArgs, - /* [size_is][in] */ ClassID typeArgs[ ], - /* [out] */ FunctionID *pFunctionID); - - HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( - ICorProfilerInfo2 * This, - /* [in] */ ModuleID moduleID, - /* [out] */ ICorProfilerObjectEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( - ICorProfilerInfo2 * This, - /* [in] */ ObjectID objectId, - /* [in] */ ULONG32 cDimensions, - /* [size_is][out] */ ULONG32 pDimensionSizes[ ], - /* [size_is][out] */ int pDimensionLowerBounds[ ], - /* [out] */ BYTE **ppData); - - HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( - ICorProfilerInfo2 * This, - /* [in] */ ClassID classId, - /* [out] */ ULONG32 *pBufferOffset); - - HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( - ICorProfilerInfo2 * This, - /* [in] */ ThreadID threadId, - /* [out] */ AppDomainID *pAppDomainId); - - HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( - ICorProfilerInfo2 * This, - /* [in] */ ClassID classId, - /* [in] */ mdFieldDef fieldToken, - /* [out] */ void **ppAddress); - - HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( - ICorProfilerInfo2 * This, - /* [in] */ ClassID classId, - /* [in] */ mdFieldDef fieldToken, - /* [in] */ AppDomainID appDomainId, - /* [out] */ void **ppAddress); - - HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( - ICorProfilerInfo2 * This, - /* [in] */ ClassID classId, - /* [in] */ mdFieldDef fieldToken, - /* [in] */ ThreadID threadId, - /* [out] */ void **ppAddress); - - HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( - ICorProfilerInfo2 * This, - /* [in] */ ClassID classId, - /* [in] */ mdFieldDef fieldToken, - /* [in] */ ContextID contextId, - /* [out] */ void **ppAddress); - - HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( - ICorProfilerInfo2 * This, - /* [in] */ ClassID classId, - /* [in] */ mdFieldDef fieldToken, - /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); - - HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( - ICorProfilerInfo2 * This, - /* [in] */ ULONG cObjectRanges, - /* [out] */ ULONG *pcObjectRanges, - /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( - ICorProfilerInfo2 * This, - /* [in] */ ObjectID objectId, - /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); - - HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( - ICorProfilerInfo2 * This, - /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); - END_INTERFACE - } ICorProfilerInfo2Vtbl; + } ICorProfilerInfoVtbl; - interface ICorProfilerInfo2 + interface ICorProfilerInfo { - CONST_VTBL struct ICorProfilerInfo2Vtbl *lpVtbl; + CONST_VTBL struct ICorProfilerInfoVtbl *lpVtbl; }; @@ -6843,179 +7020,115 @@ EXTERN_C const IID IID_ICorProfilerInfo2; #ifdef COBJMACROS -#define ICorProfilerInfo2_QueryInterface(This,riid,ppvObject) \ +#define ICorProfilerInfo_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ICorProfilerInfo2_AddRef(This) \ +#define ICorProfilerInfo_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) -#define ICorProfilerInfo2_Release(This) \ +#define ICorProfilerInfo_Release(This) \ ( (This)->lpVtbl -> Release(This) ) -#define ICorProfilerInfo2_GetClassFromObject(This,objectId,pClassId) \ +#define ICorProfilerInfo_GetClassFromObject(This,objectId,pClassId) \ ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) -#define ICorProfilerInfo2_GetClassFromToken(This,moduleId,typeDef,pClassId) \ +#define ICorProfilerInfo_GetClassFromToken(This,moduleId,typeDef,pClassId) \ ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) -#define ICorProfilerInfo2_GetCodeInfo(This,functionId,pStart,pcSize) \ +#define ICorProfilerInfo_GetCodeInfo(This,functionId,pStart,pcSize) \ ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) -#define ICorProfilerInfo2_GetEventMask(This,pdwEvents) \ +#define ICorProfilerInfo_GetEventMask(This,pdwEvents) \ ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) -#define ICorProfilerInfo2_GetFunctionFromIP(This,ip,pFunctionId) \ +#define ICorProfilerInfo_GetFunctionFromIP(This,ip,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) -#define ICorProfilerInfo2_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ +#define ICorProfilerInfo_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) -#define ICorProfilerInfo2_GetHandleFromThread(This,threadId,phThread) \ +#define ICorProfilerInfo_GetHandleFromThread(This,threadId,phThread) \ ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) -#define ICorProfilerInfo2_GetObjectSize(This,objectId,pcSize) \ +#define ICorProfilerInfo_GetObjectSize(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) -#define ICorProfilerInfo2_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ +#define ICorProfilerInfo_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) -#define ICorProfilerInfo2_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ +#define ICorProfilerInfo_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) -#define ICorProfilerInfo2_GetCurrentThreadID(This,pThreadId) \ +#define ICorProfilerInfo_GetCurrentThreadID(This,pThreadId) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) -#define ICorProfilerInfo2_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ +#define ICorProfilerInfo_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) -#define ICorProfilerInfo2_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ +#define ICorProfilerInfo_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) -#define ICorProfilerInfo2_SetEventMask(This,dwEvents) \ +#define ICorProfilerInfo_SetEventMask(This,dwEvents) \ ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) -#define ICorProfilerInfo2_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ +#define ICorProfilerInfo_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) -#define ICorProfilerInfo2_SetFunctionIDMapper(This,pFunc) \ +#define ICorProfilerInfo_SetFunctionIDMapper(This,pFunc) \ ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) -#define ICorProfilerInfo2_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ +#define ICorProfilerInfo_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) -#define ICorProfilerInfo2_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ +#define ICorProfilerInfo_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) -#define ICorProfilerInfo2_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ +#define ICorProfilerInfo_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) -#define ICorProfilerInfo2_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ +#define ICorProfilerInfo_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) -#define ICorProfilerInfo2_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ +#define ICorProfilerInfo_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) -#define ICorProfilerInfo2_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ +#define ICorProfilerInfo_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) -#define ICorProfilerInfo2_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ +#define ICorProfilerInfo_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) -#define ICorProfilerInfo2_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ +#define ICorProfilerInfo_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) -#define ICorProfilerInfo2_SetFunctionReJIT(This,functionId) \ +#define ICorProfilerInfo_SetFunctionReJIT(This,functionId) \ ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) -#define ICorProfilerInfo2_ForceGC(This) \ +#define ICorProfilerInfo_ForceGC(This) \ ( (This)->lpVtbl -> ForceGC(This) ) -#define ICorProfilerInfo2_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ +#define ICorProfilerInfo_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) -#define ICorProfilerInfo2_GetInprocInspectionInterface(This,ppicd) \ +#define ICorProfilerInfo_GetInprocInspectionInterface(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) -#define ICorProfilerInfo2_GetInprocInspectionIThisThread(This,ppicd) \ +#define ICorProfilerInfo_GetInprocInspectionIThisThread(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) -#define ICorProfilerInfo2_GetThreadContext(This,threadId,pContextId) \ +#define ICorProfilerInfo_GetThreadContext(This,threadId,pContextId) \ ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) -#define ICorProfilerInfo2_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ +#define ICorProfilerInfo_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) -#define ICorProfilerInfo2_EndInprocDebugging(This,dwProfilerContext) \ +#define ICorProfilerInfo_EndInprocDebugging(This,dwProfilerContext) \ ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) -#define ICorProfilerInfo2_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ +#define ICorProfilerInfo_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) - -#define ICorProfilerInfo2_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ - ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) - -#define ICorProfilerInfo2_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ - ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) - -#define ICorProfilerInfo2_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ - ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) - -#define ICorProfilerInfo2_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ - ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) - -#define ICorProfilerInfo2_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ - ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) - -#define ICorProfilerInfo2_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ - ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) - -#define ICorProfilerInfo2_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ - ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) - -#define ICorProfilerInfo2_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ - ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) - -#define ICorProfilerInfo2_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ - ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) - -#define ICorProfilerInfo2_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ - ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) - -#define ICorProfilerInfo2_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ - ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) - -#define ICorProfilerInfo2_GetBoxClassLayout(This,classId,pBufferOffset) \ - ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) - -#define ICorProfilerInfo2_GetThreadAppDomain(This,threadId,pAppDomainId) \ - ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) - -#define ICorProfilerInfo2_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ - ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) - -#define ICorProfilerInfo2_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ - ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) - -#define ICorProfilerInfo2_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ - ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) - -#define ICorProfilerInfo2_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ - ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) - -#define ICorProfilerInfo2_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ - ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) - -#define ICorProfilerInfo2_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ - ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) - -#define ICorProfilerInfo2_GetObjectGeneration(This,objectId,range) \ - ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) - -#define ICorProfilerInfo2_GetNotifiedExceptionClauseInfo(This,pinfo) \ - ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) - #endif /* COBJMACROS */ @@ -7024,219 +7137,263 @@ EXTERN_C const IID IID_ICorProfilerInfo2; -#endif /* __ICorProfilerInfo2_INTERFACE_DEFINED__ */ +#endif /* __ICorProfilerInfo_INTERFACE_DEFINED__ */ -#ifndef __ICorProfilerInfo3_INTERFACE_DEFINED__ -#define __ICorProfilerInfo3_INTERFACE_DEFINED__ +#ifndef __ICorProfilerInfo2_INTERFACE_DEFINED__ +#define __ICorProfilerInfo2_INTERFACE_DEFINED__ -/* interface ICorProfilerInfo3 */ +/* interface ICorProfilerInfo2 */ /* [local][unique][uuid][object] */ -EXTERN_C const IID IID_ICorProfilerInfo3; +EXTERN_C const IID IID_ICorProfilerInfo2; #if defined(__cplusplus) && !defined(CINTERFACE) - MIDL_INTERFACE("B555ED4F-452A-4E54-8B39-B5360BAD32A0") - ICorProfilerInfo3 : public ICorProfilerInfo2 + MIDL_INTERFACE("CC0935CD-A518-487d-B0BB-A93214E65478") + ICorProfilerInfo2 : public ICorProfilerInfo { public: - virtual HRESULT STDMETHODCALLTYPE EnumJITedFunctions( - /* [out] */ ICorProfilerFunctionEnum **ppEnum) = 0; + virtual HRESULT STDMETHODCALLTYPE DoStackSnapshot( + /* [in] */ ThreadID thread, + /* [in] */ StackSnapshotCallback *callback, + /* [in] */ ULONG32 infoFlags, + /* [in] */ void *clientData, + /* [size_is][in] */ BYTE context[ ], + /* [in] */ ULONG32 contextSize) = 0; - virtual HRESULT STDMETHODCALLTYPE RequestProfilerDetach( - /* [in] */ DWORD dwExpectedCompletionMilliseconds) = 0; + virtual HRESULT STDMETHODCALLTYPE SetEnterLeaveFunctionHooks2( + /* [in] */ FunctionEnter2 *pFuncEnter, + /* [in] */ FunctionLeave2 *pFuncLeave, + /* [in] */ FunctionTailcall2 *pFuncTailcall) = 0; - virtual HRESULT STDMETHODCALLTYPE SetFunctionIDMapper2( - /* [in] */ FunctionIDMapper2 *pFunc, - /* [in] */ void *clientData) = 0; + virtual HRESULT STDMETHODCALLTYPE GetFunctionInfo2( + /* [in] */ FunctionID funcId, + /* [in] */ COR_PRF_FRAME_INFO frameInfo, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken, + /* [in] */ ULONG32 cTypeArgs, + /* [out] */ ULONG32 *pcTypeArgs, + /* [out] */ ClassID typeArgs[ ]) = 0; - virtual HRESULT STDMETHODCALLTYPE GetStringLayout2( + virtual HRESULT STDMETHODCALLTYPE GetStringLayout( + /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset) = 0; - virtual HRESULT STDMETHODCALLTYPE SetEnterLeaveFunctionHooks3( - /* [in] */ FunctionEnter3 *pFuncEnter3, - /* [in] */ FunctionLeave3 *pFuncLeave3, - /* [in] */ FunctionTailcall3 *pFuncTailcall3) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetEnterLeaveFunctionHooks3WithInfo( - /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, - /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, - /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo) = 0; + virtual HRESULT STDMETHODCALLTYPE GetClassLayout( + /* [in] */ ClassID classID, + /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], + /* [in] */ ULONG cFieldOffset, + /* [out] */ ULONG *pcFieldOffset, + /* [out] */ ULONG *pulClassSize) = 0; - virtual HRESULT STDMETHODCALLTYPE GetFunctionEnter3Info( - /* [in] */ FunctionID functionId, - /* [in] */ COR_PRF_ELT_INFO eltInfo, - /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, - /* [out][in] */ ULONG *pcbArgumentInfo, - /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo) = 0; + virtual HRESULT STDMETHODCALLTYPE GetClassIDInfo2( + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken, + /* [out] */ ClassID *pParentClassId, + /* [in] */ ULONG32 cNumTypeArgs, + /* [out] */ ULONG32 *pcNumTypeArgs, + /* [out] */ ClassID typeArgs[ ]) = 0; - virtual HRESULT STDMETHODCALLTYPE GetFunctionLeave3Info( - /* [in] */ FunctionID functionId, - /* [in] */ COR_PRF_ELT_INFO eltInfo, - /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, - /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCodeInfo2( + /* [in] */ FunctionID functionID, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]) = 0; - virtual HRESULT STDMETHODCALLTYPE GetFunctionTailcall3Info( - /* [in] */ FunctionID functionId, - /* [in] */ COR_PRF_ELT_INFO eltInfo, - /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo) = 0; + virtual HRESULT STDMETHODCALLTYPE GetClassFromTokenAndTypeArgs( + /* [in] */ ModuleID moduleID, + /* [in] */ mdTypeDef typeDef, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ ClassID *pClassID) = 0; - virtual HRESULT STDMETHODCALLTYPE EnumModules( - /* [out] */ ICorProfilerModuleEnum **ppEnum) = 0; + virtual HRESULT STDMETHODCALLTYPE GetFunctionFromTokenAndTypeArgs( + /* [in] */ ModuleID moduleID, + /* [in] */ mdMethodDef funcDef, + /* [in] */ ClassID classId, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ FunctionID *pFunctionID) = 0; - virtual HRESULT STDMETHODCALLTYPE GetRuntimeInformation( - /* [out] */ USHORT *pClrInstanceId, - /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, - /* [out] */ USHORT *pMajorVersion, - /* [out] */ USHORT *pMinorVersion, - /* [out] */ USHORT *pBuildNumber, - /* [out] */ USHORT *pQFEVersion, - /* [in] */ ULONG cchVersionString, - /* [out] */ ULONG *pcchVersionString, - /* [annotation][out] */ - _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]) = 0; + virtual HRESULT STDMETHODCALLTYPE EnumModuleFrozenObjects( + /* [in] */ ModuleID moduleID, + /* [out] */ ICorProfilerObjectEnum **ppEnum) = 0; - virtual HRESULT STDMETHODCALLTYPE GetThreadStaticAddress2( + virtual HRESULT STDMETHODCALLTYPE GetArrayObjectInfo( + /* [in] */ ObjectID objectId, + /* [in] */ ULONG32 cDimensions, + /* [size_is][out] */ ULONG32 pDimensionSizes[ ], + /* [size_is][out] */ int pDimensionLowerBounds[ ], + /* [out] */ BYTE **ppData) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetBoxClassLayout( + /* [in] */ ClassID classId, + /* [out] */ ULONG32 *pBufferOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThreadAppDomain( + /* [in] */ ThreadID threadId, + /* [out] */ AppDomainID *pAppDomainId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRVAStaticAddress( + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ void **ppAddress) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAppDomainStaticAddress( /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, + /* [out] */ void **ppAddress) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThreadStaticAddress( + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress) = 0; - virtual HRESULT STDMETHODCALLTYPE GetAppDomainsContainingModule( - /* [in] */ ModuleID moduleId, - /* [in] */ ULONG32 cAppDomainIds, - /* [out] */ ULONG32 *pcAppDomainIds, - /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]) = 0; + virtual HRESULT STDMETHODCALLTYPE GetContextStaticAddress( + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ContextID contextId, + /* [out] */ void **ppAddress) = 0; - virtual HRESULT STDMETHODCALLTYPE GetModuleInfo2( - /* [in] */ ModuleID moduleId, - /* [out] */ LPCBYTE *ppBaseLoadAddress, - /* [in] */ ULONG cchName, - /* [out] */ ULONG *pcchName, - /* [annotation][out] */ - _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], - /* [out] */ AssemblyID *pAssemblyId, - /* [out] */ DWORD *pdwModuleFlags) = 0; + virtual HRESULT STDMETHODCALLTYPE GetStaticFieldInfo( + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetGenerationBounds( + /* [in] */ ULONG cObjectRanges, + /* [out] */ ULONG *pcObjectRanges, + /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetObjectGeneration( + /* [in] */ ObjectID objectId, + /* [out] */ COR_PRF_GC_GENERATION_RANGE *range) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNotifiedExceptionClauseInfo( + /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo) = 0; }; #else /* C style interface */ - typedef struct ICorProfilerInfo3Vtbl + typedef struct ICorProfilerInfo2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( - ICorProfilerInfo3 * This); + ICorProfilerInfo2 * This); ULONG ( STDMETHODCALLTYPE *Release )( - ICorProfilerInfo3 * This); + ICorProfilerInfo2 * This); HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [out] */ DWORD *pdwEvents); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread); HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank); HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId); HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [out] */ ThreadID *pThreadId); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *SetEventMask )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ DWORD dwEvents); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ FunctionIDMapper *pFunc); HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, @@ -7246,32 +7403,32 @@ EXTERN_C const IID IID_ICorProfilerInfo3; /* [out] */ AssemblyID *pAssemblyId); HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc); HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader); HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, @@ -7280,7 +7437,7 @@ EXTERN_C const IID IID_ICorProfilerInfo3; /* [out] */ ProcessID *pProcessId); HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, @@ -7290,50 +7447,50 @@ EXTERN_C const IID IID_ICorProfilerInfo3; /* [out] */ ModuleID *pModuleId); HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ForceGC )( - ICorProfilerInfo3 * This); + ICorProfilerInfo2 * This); HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId); HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext); HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ DWORD dwProfilerContext); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ThreadID thread, /* [in] */ StackSnapshotCallback *callback, /* [in] */ ULONG32 infoFlags, @@ -7342,13 +7499,13 @@ EXTERN_C const IID IID_ICorProfilerInfo3; /* [in] */ ULONG32 contextSize); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ FunctionEnter2 *pFuncEnter, /* [in] */ FunctionLeave2 *pFuncLeave, /* [in] */ FunctionTailcall2 *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ FunctionID funcId, /* [in] */ COR_PRF_FRAME_INFO frameInfo, /* [out] */ ClassID *pClassId, @@ -7359,13 +7516,13 @@ EXTERN_C const IID IID_ICorProfilerInfo3; /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ClassID classID, /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], /* [in] */ ULONG cFieldOffset, @@ -7373,7 +7530,7 @@ EXTERN_C const IID IID_ICorProfilerInfo3; /* [out] */ ULONG *pulClassSize); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken, @@ -7383,14 +7540,14 @@ EXTERN_C const IID IID_ICorProfilerInfo3; /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ FunctionID functionID, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdTypeDef typeDef, /* [in] */ ULONG32 cTypeArgs, @@ -7398,7 +7555,7 @@ EXTERN_C const IID IID_ICorProfilerInfo3; /* [out] */ ClassID *pClassID); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdMethodDef funcDef, /* [in] */ ClassID classId, @@ -7407,12 +7564,12 @@ EXTERN_C const IID IID_ICorProfilerInfo3; /* [out] */ FunctionID *pFunctionID); HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ModuleID moduleID, /* [out] */ ICorProfilerObjectEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ObjectID objectId, /* [in] */ ULONG32 cDimensions, /* [size_is][out] */ ULONG32 pDimensionSizes[ ], @@ -7420,163 +7577,69 @@ EXTERN_C const IID IID_ICorProfilerInfo3; /* [out] */ BYTE **ppData); HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ClassID classId, /* [out] */ ULONG32 *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ThreadID threadId, /* [out] */ AppDomainID *pAppDomainId); HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ContextID contextId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ULONG cObjectRanges, /* [out] */ ULONG *pcObjectRanges, /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [in] */ ObjectID objectId, /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( - ICorProfilerInfo3 * This, + ICorProfilerInfo2 * This, /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); - HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( - ICorProfilerInfo3 * This, - /* [out] */ ICorProfilerFunctionEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( - ICorProfilerInfo3 * This, - /* [in] */ DWORD dwExpectedCompletionMilliseconds); - - HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( - ICorProfilerInfo3 * This, - /* [in] */ FunctionIDMapper2 *pFunc, - /* [in] */ void *clientData); - - HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( - ICorProfilerInfo3 * This, - /* [out] */ ULONG *pStringLengthOffset, - /* [out] */ ULONG *pBufferOffset); - - HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( - ICorProfilerInfo3 * This, - /* [in] */ FunctionEnter3 *pFuncEnter3, - /* [in] */ FunctionLeave3 *pFuncLeave3, - /* [in] */ FunctionTailcall3 *pFuncTailcall3); - - HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( - ICorProfilerInfo3 * This, - /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, - /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, - /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); - - HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( - ICorProfilerInfo3 * This, - /* [in] */ FunctionID functionId, - /* [in] */ COR_PRF_ELT_INFO eltInfo, - /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, - /* [out][in] */ ULONG *pcbArgumentInfo, - /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); - - HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( - ICorProfilerInfo3 * This, - /* [in] */ FunctionID functionId, - /* [in] */ COR_PRF_ELT_INFO eltInfo, - /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, - /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); - - HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( - ICorProfilerInfo3 * This, - /* [in] */ FunctionID functionId, - /* [in] */ COR_PRF_ELT_INFO eltInfo, - /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); - - HRESULT ( STDMETHODCALLTYPE *EnumModules )( - ICorProfilerInfo3 * This, - /* [out] */ ICorProfilerModuleEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( - ICorProfilerInfo3 * This, - /* [out] */ USHORT *pClrInstanceId, - /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, - /* [out] */ USHORT *pMajorVersion, - /* [out] */ USHORT *pMinorVersion, - /* [out] */ USHORT *pBuildNumber, - /* [out] */ USHORT *pQFEVersion, - /* [in] */ ULONG cchVersionString, - /* [out] */ ULONG *pcchVersionString, - /* [annotation][out] */ - _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( - ICorProfilerInfo3 * This, - /* [in] */ ClassID classId, - /* [in] */ mdFieldDef fieldToken, - /* [in] */ AppDomainID appDomainId, - /* [in] */ ThreadID threadId, - /* [out] */ void **ppAddress); - - HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( - ICorProfilerInfo3 * This, - /* [in] */ ModuleID moduleId, - /* [in] */ ULONG32 cAppDomainIds, - /* [out] */ ULONG32 *pcAppDomainIds, - /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( - ICorProfilerInfo3 * This, - /* [in] */ ModuleID moduleId, - /* [out] */ LPCBYTE *ppBaseLoadAddress, - /* [in] */ ULONG cchName, - /* [out] */ ULONG *pcchName, - /* [annotation][out] */ - _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], - /* [out] */ AssemblyID *pAssemblyId, - /* [out] */ DWORD *pdwModuleFlags); - END_INTERFACE - } ICorProfilerInfo3Vtbl; + } ICorProfilerInfo2Vtbl; - interface ICorProfilerInfo3 + interface ICorProfilerInfo2 { - CONST_VTBL struct ICorProfilerInfo3Vtbl *lpVtbl; + CONST_VTBL struct ICorProfilerInfo2Vtbl *lpVtbl; }; @@ -7584,222 +7647,179 @@ EXTERN_C const IID IID_ICorProfilerInfo3; #ifdef COBJMACROS -#define ICorProfilerInfo3_QueryInterface(This,riid,ppvObject) \ +#define ICorProfilerInfo2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ICorProfilerInfo3_AddRef(This) \ +#define ICorProfilerInfo2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) -#define ICorProfilerInfo3_Release(This) \ +#define ICorProfilerInfo2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) -#define ICorProfilerInfo3_GetClassFromObject(This,objectId,pClassId) \ +#define ICorProfilerInfo2_GetClassFromObject(This,objectId,pClassId) \ ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) -#define ICorProfilerInfo3_GetClassFromToken(This,moduleId,typeDef,pClassId) \ +#define ICorProfilerInfo2_GetClassFromToken(This,moduleId,typeDef,pClassId) \ ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) -#define ICorProfilerInfo3_GetCodeInfo(This,functionId,pStart,pcSize) \ +#define ICorProfilerInfo2_GetCodeInfo(This,functionId,pStart,pcSize) \ ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) -#define ICorProfilerInfo3_GetEventMask(This,pdwEvents) \ +#define ICorProfilerInfo2_GetEventMask(This,pdwEvents) \ ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) -#define ICorProfilerInfo3_GetFunctionFromIP(This,ip,pFunctionId) \ +#define ICorProfilerInfo2_GetFunctionFromIP(This,ip,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) -#define ICorProfilerInfo3_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ +#define ICorProfilerInfo2_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) -#define ICorProfilerInfo3_GetHandleFromThread(This,threadId,phThread) \ +#define ICorProfilerInfo2_GetHandleFromThread(This,threadId,phThread) \ ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) -#define ICorProfilerInfo3_GetObjectSize(This,objectId,pcSize) \ +#define ICorProfilerInfo2_GetObjectSize(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) -#define ICorProfilerInfo3_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ +#define ICorProfilerInfo2_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) -#define ICorProfilerInfo3_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ +#define ICorProfilerInfo2_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) -#define ICorProfilerInfo3_GetCurrentThreadID(This,pThreadId) \ +#define ICorProfilerInfo2_GetCurrentThreadID(This,pThreadId) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) -#define ICorProfilerInfo3_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ +#define ICorProfilerInfo2_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) -#define ICorProfilerInfo3_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ +#define ICorProfilerInfo2_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) -#define ICorProfilerInfo3_SetEventMask(This,dwEvents) \ +#define ICorProfilerInfo2_SetEventMask(This,dwEvents) \ ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) -#define ICorProfilerInfo3_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ +#define ICorProfilerInfo2_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) -#define ICorProfilerInfo3_SetFunctionIDMapper(This,pFunc) \ +#define ICorProfilerInfo2_SetFunctionIDMapper(This,pFunc) \ ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) -#define ICorProfilerInfo3_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ +#define ICorProfilerInfo2_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) -#define ICorProfilerInfo3_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ +#define ICorProfilerInfo2_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) -#define ICorProfilerInfo3_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ +#define ICorProfilerInfo2_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) -#define ICorProfilerInfo3_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ +#define ICorProfilerInfo2_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) -#define ICorProfilerInfo3_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ +#define ICorProfilerInfo2_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) -#define ICorProfilerInfo3_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ +#define ICorProfilerInfo2_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) -#define ICorProfilerInfo3_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ +#define ICorProfilerInfo2_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) -#define ICorProfilerInfo3_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ +#define ICorProfilerInfo2_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) -#define ICorProfilerInfo3_SetFunctionReJIT(This,functionId) \ +#define ICorProfilerInfo2_SetFunctionReJIT(This,functionId) \ ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) -#define ICorProfilerInfo3_ForceGC(This) \ +#define ICorProfilerInfo2_ForceGC(This) \ ( (This)->lpVtbl -> ForceGC(This) ) -#define ICorProfilerInfo3_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ +#define ICorProfilerInfo2_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) -#define ICorProfilerInfo3_GetInprocInspectionInterface(This,ppicd) \ +#define ICorProfilerInfo2_GetInprocInspectionInterface(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) -#define ICorProfilerInfo3_GetInprocInspectionIThisThread(This,ppicd) \ +#define ICorProfilerInfo2_GetInprocInspectionIThisThread(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) -#define ICorProfilerInfo3_GetThreadContext(This,threadId,pContextId) \ +#define ICorProfilerInfo2_GetThreadContext(This,threadId,pContextId) \ ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) -#define ICorProfilerInfo3_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ +#define ICorProfilerInfo2_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) -#define ICorProfilerInfo3_EndInprocDebugging(This,dwProfilerContext) \ +#define ICorProfilerInfo2_EndInprocDebugging(This,dwProfilerContext) \ ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) -#define ICorProfilerInfo3_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ +#define ICorProfilerInfo2_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) -#define ICorProfilerInfo3_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ +#define ICorProfilerInfo2_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) -#define ICorProfilerInfo3_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ +#define ICorProfilerInfo2_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) -#define ICorProfilerInfo3_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ +#define ICorProfilerInfo2_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) -#define ICorProfilerInfo3_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ +#define ICorProfilerInfo2_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) -#define ICorProfilerInfo3_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ +#define ICorProfilerInfo2_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) -#define ICorProfilerInfo3_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ +#define ICorProfilerInfo2_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) -#define ICorProfilerInfo3_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ +#define ICorProfilerInfo2_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) -#define ICorProfilerInfo3_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ +#define ICorProfilerInfo2_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) -#define ICorProfilerInfo3_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ +#define ICorProfilerInfo2_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) -#define ICorProfilerInfo3_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ +#define ICorProfilerInfo2_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) -#define ICorProfilerInfo3_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ +#define ICorProfilerInfo2_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) -#define ICorProfilerInfo3_GetBoxClassLayout(This,classId,pBufferOffset) \ +#define ICorProfilerInfo2_GetBoxClassLayout(This,classId,pBufferOffset) \ ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) -#define ICorProfilerInfo3_GetThreadAppDomain(This,threadId,pAppDomainId) \ +#define ICorProfilerInfo2_GetThreadAppDomain(This,threadId,pAppDomainId) \ ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) -#define ICorProfilerInfo3_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ +#define ICorProfilerInfo2_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) -#define ICorProfilerInfo3_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ +#define ICorProfilerInfo2_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) -#define ICorProfilerInfo3_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ +#define ICorProfilerInfo2_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) -#define ICorProfilerInfo3_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ +#define ICorProfilerInfo2_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) -#define ICorProfilerInfo3_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ +#define ICorProfilerInfo2_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) -#define ICorProfilerInfo3_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ +#define ICorProfilerInfo2_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) -#define ICorProfilerInfo3_GetObjectGeneration(This,objectId,range) \ +#define ICorProfilerInfo2_GetObjectGeneration(This,objectId,range) \ ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) -#define ICorProfilerInfo3_GetNotifiedExceptionClauseInfo(This,pinfo) \ +#define ICorProfilerInfo2_GetNotifiedExceptionClauseInfo(This,pinfo) \ ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) - -#define ICorProfilerInfo3_EnumJITedFunctions(This,ppEnum) \ - ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) - -#define ICorProfilerInfo3_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ - ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) - -#define ICorProfilerInfo3_SetFunctionIDMapper2(This,pFunc,clientData) \ - ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) - -#define ICorProfilerInfo3_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ - ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) - -#define ICorProfilerInfo3_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ - ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) - -#define ICorProfilerInfo3_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ - ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) - -#define ICorProfilerInfo3_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ - ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) - -#define ICorProfilerInfo3_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ - ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) - -#define ICorProfilerInfo3_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ - ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) - -#define ICorProfilerInfo3_EnumModules(This,ppEnum) \ - ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) - -#define ICorProfilerInfo3_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ - ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) - -#define ICorProfilerInfo3_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ - ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) - -#define ICorProfilerInfo3_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ - ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) - -#define ICorProfilerInfo3_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ - ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) - #endif /* COBJMACROS */ @@ -7808,210 +7828,1919 @@ EXTERN_C const IID IID_ICorProfilerInfo3; -#endif /* __ICorProfilerInfo3_INTERFACE_DEFINED__ */ +#endif /* __ICorProfilerInfo2_INTERFACE_DEFINED__ */ -#ifndef __ICorProfilerObjectEnum_INTERFACE_DEFINED__ -#define __ICorProfilerObjectEnum_INTERFACE_DEFINED__ +#ifndef __ICorProfilerInfo3_INTERFACE_DEFINED__ +#define __ICorProfilerInfo3_INTERFACE_DEFINED__ -/* interface ICorProfilerObjectEnum */ +/* interface ICorProfilerInfo3 */ /* [local][unique][uuid][object] */ -EXTERN_C const IID IID_ICorProfilerObjectEnum; +EXTERN_C const IID IID_ICorProfilerInfo3; #if defined(__cplusplus) && !defined(CINTERFACE) - MIDL_INTERFACE("2C6269BD-2D13-4321-AE12-6686365FD6AF") - ICorProfilerObjectEnum : public IUnknown + MIDL_INTERFACE("B555ED4F-452A-4E54-8B39-B5360BAD32A0") + ICorProfilerInfo3 : public ICorProfilerInfo2 { public: - virtual HRESULT STDMETHODCALLTYPE Skip( - /* [in] */ ULONG celt) = 0; - - virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + virtual HRESULT STDMETHODCALLTYPE EnumJITedFunctions( + /* [out] */ ICorProfilerFunctionEnum **ppEnum) = 0; - virtual HRESULT STDMETHODCALLTYPE Clone( - /* [out] */ ICorProfilerObjectEnum **ppEnum) = 0; + virtual HRESULT STDMETHODCALLTYPE RequestProfilerDetach( + /* [in] */ DWORD dwExpectedCompletionMilliseconds) = 0; - virtual HRESULT STDMETHODCALLTYPE GetCount( - /* [out] */ ULONG *pcelt) = 0; + virtual HRESULT STDMETHODCALLTYPE SetFunctionIDMapper2( + /* [in] */ FunctionIDMapper2 *pFunc, + /* [in] */ void *clientData) = 0; - virtual HRESULT STDMETHODCALLTYPE Next( - /* [in] */ ULONG celt, - /* [length_is][size_is][out] */ ObjectID objects[ ], - /* [out] */ ULONG *pceltFetched) = 0; + virtual HRESULT STDMETHODCALLTYPE GetStringLayout2( + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetEnterLeaveFunctionHooks3( + /* [in] */ FunctionEnter3 *pFuncEnter3, + /* [in] */ FunctionLeave3 *pFuncLeave3, + /* [in] */ FunctionTailcall3 *pFuncTailcall3) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetEnterLeaveFunctionHooks3WithInfo( + /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, + /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, + /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunctionEnter3Info( + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out][in] */ ULONG *pcbArgumentInfo, + /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunctionLeave3Info( + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunctionTailcall3Info( + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumModules( + /* [out] */ ICorProfilerModuleEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRuntimeInformation( + /* [out] */ USHORT *pClrInstanceId, + /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, + /* [out] */ USHORT *pMajorVersion, + /* [out] */ USHORT *pMinorVersion, + /* [out] */ USHORT *pBuildNumber, + /* [out] */ USHORT *pQFEVersion, + /* [in] */ ULONG cchVersionString, + /* [out] */ ULONG *pcchVersionString, + /* [annotation][out] */ + _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThreadStaticAddress2( + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAppDomainsContainingModule( + /* [in] */ ModuleID moduleId, + /* [in] */ ULONG32 cAppDomainIds, + /* [out] */ ULONG32 *pcAppDomainIds, + /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetModuleInfo2( + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId, + /* [out] */ DWORD *pdwModuleFlags) = 0; }; #else /* C style interface */ - typedef struct ICorProfilerObjectEnumVtbl + typedef struct ICorProfilerInfo3Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - ICorProfilerObjectEnum * This, + ICorProfilerInfo3 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( - ICorProfilerObjectEnum * This); + ICorProfilerInfo3 * This); ULONG ( STDMETHODCALLTYPE *Release )( - ICorProfilerObjectEnum * This); + ICorProfilerInfo3 * This); - HRESULT ( STDMETHODCALLTYPE *Skip )( - ICorProfilerObjectEnum * This, - /* [in] */ ULONG celt); + HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( + ICorProfilerInfo3 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdTypeDef typeDef, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID functionId, + /* [out] */ LPCBYTE *pStart, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask )( + ICorProfilerInfo3 * This, + /* [out] */ DWORD *pdwEvents); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( + ICorProfilerInfo3 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdToken token, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( + ICorProfilerInfo3 * This, + /* [in] */ ThreadID threadId, + /* [out] */ HANDLE *phThread); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( + ICorProfilerInfo3 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classId, + /* [out] */ CorElementType *pBaseElemType, + /* [out] */ ClassID *pBaseClassId, + /* [out] */ ULONG *pcRank); + + HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( + ICorProfilerInfo3 * This, + /* [in] */ ThreadID threadId, + /* [out] */ DWORD *pdwWin32ThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( + ICorProfilerInfo3 * This, + /* [out] */ ThreadID *pThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID functionId, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask )( + ICorProfilerInfo3 * This, + /* [in] */ DWORD dwEvents); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionEnter *pFuncEnter, + /* [in] */ FunctionLeave *pFuncLeave, + /* [in] */ FunctionTailcall *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionIDMapper *pFunc); + + HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID functionId, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppImport, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId); + + HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD dwOpenFlags, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppOut); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [out] */ LPCBYTE *ppMethodHeader, + /* [out] */ ULONG *pcbMethodSize); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ IMethodMalloc **ppMalloc); + + HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodid, + /* [in] */ LPCBYTE pbNewILMethodHeader); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( + ICorProfilerInfo3 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ ProcessID *pProcessId); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( + ICorProfilerInfo3 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AppDomainID *pAppDomainId, + /* [out] */ ModuleID *pModuleId); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ForceGC )( + ICorProfilerInfo3 * This); + + HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fStartJit, + /* [in] */ ULONG cILMapEntries, + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( + ICorProfilerInfo3 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( + ICorProfilerInfo3 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICorProfilerInfo3 * This, + /* [in] */ ThreadID threadId, + /* [out] */ ContextID *pContextId); + + HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( + ICorProfilerInfo3 * This, + /* [in] */ BOOL fThisThreadOnly, + /* [out] */ DWORD *pdwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( + ICorProfilerInfo3 * This, + /* [in] */ DWORD dwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( + ICorProfilerInfo3 * This, + /* [in] */ ThreadID thread, + /* [in] */ StackSnapshotCallback *callback, + /* [in] */ ULONG32 infoFlags, + /* [in] */ void *clientData, + /* [size_is][in] */ BYTE context[ ], + /* [in] */ ULONG32 contextSize); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionEnter2 *pFuncEnter, + /* [in] */ FunctionLeave2 *pFuncLeave, + /* [in] */ FunctionTailcall2 *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID funcId, + /* [in] */ COR_PRF_FRAME_INFO frameInfo, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken, + /* [in] */ ULONG32 cTypeArgs, + /* [out] */ ULONG32 *pcTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( + ICorProfilerInfo3 * This, + /* [out] */ ULONG *pBufferLengthOffset, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classID, + /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], + /* [in] */ ULONG cFieldOffset, + /* [out] */ ULONG *pcFieldOffset, + /* [out] */ ULONG *pulClassSize); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken, + /* [out] */ ClassID *pParentClassId, + /* [in] */ ULONG32 cNumTypeArgs, + /* [out] */ ULONG32 *pcNumTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdTypeDef typeDef, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ ClassID *pClassID); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdMethodDef funcDef, + /* [in] */ ClassID classId, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ FunctionID *pFunctionID); + + HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleID, + /* [out] */ ICorProfilerObjectEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( + ICorProfilerInfo3 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ULONG32 cDimensions, + /* [size_is][out] */ ULONG32 pDimensionSizes[ ], + /* [size_is][out] */ int pDimensionLowerBounds[ ], + /* [out] */ BYTE **ppData); + + HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classId, + /* [out] */ ULONG32 *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( + ICorProfilerInfo3 * This, + /* [in] */ ThreadID threadId, + /* [out] */ AppDomainID *pAppDomainId); + + HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ContextID contextId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); + + HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( + ICorProfilerInfo3 * This, + /* [in] */ ULONG cObjectRanges, + /* [out] */ ULONG *pcObjectRanges, + /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( + ICorProfilerInfo3 * This, + /* [in] */ ObjectID objectId, + /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); + + HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( + ICorProfilerInfo3 * This, + /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( + ICorProfilerInfo3 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( + ICorProfilerInfo3 * This, + /* [in] */ DWORD dwExpectedCompletionMilliseconds); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionIDMapper2 *pFunc, + /* [in] */ void *clientData); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( + ICorProfilerInfo3 * This, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionEnter3 *pFuncEnter3, + /* [in] */ FunctionLeave3 *pFuncLeave3, + /* [in] */ FunctionTailcall3 *pFuncTailcall3); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, + /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, + /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out][in] */ ULONG *pcbArgumentInfo, + /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); + + HRESULT ( STDMETHODCALLTYPE *EnumModules )( + ICorProfilerInfo3 * This, + /* [out] */ ICorProfilerModuleEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( + ICorProfilerInfo3 * This, + /* [out] */ USHORT *pClrInstanceId, + /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, + /* [out] */ USHORT *pMajorVersion, + /* [out] */ USHORT *pMinorVersion, + /* [out] */ USHORT *pBuildNumber, + /* [out] */ USHORT *pQFEVersion, + /* [in] */ ULONG cchVersionString, + /* [out] */ ULONG *pcchVersionString, + /* [annotation][out] */ + _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ ULONG32 cAppDomainIds, + /* [out] */ ULONG32 *pcAppDomainIds, + /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId, + /* [out] */ DWORD *pdwModuleFlags); + + END_INTERFACE + } ICorProfilerInfo3Vtbl; + + interface ICorProfilerInfo3 + { + CONST_VTBL struct ICorProfilerInfo3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerInfo3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerInfo3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerInfo3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerInfo3_GetClassFromObject(This,objectId,pClassId) \ + ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) + +#define ICorProfilerInfo3_GetClassFromToken(This,moduleId,typeDef,pClassId) \ + ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) + +#define ICorProfilerInfo3_GetCodeInfo(This,functionId,pStart,pcSize) \ + ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) + +#define ICorProfilerInfo3_GetEventMask(This,pdwEvents) \ + ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) + +#define ICorProfilerInfo3_GetFunctionFromIP(This,ip,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) + +#define ICorProfilerInfo3_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) + +#define ICorProfilerInfo3_GetHandleFromThread(This,threadId,phThread) \ + ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) + +#define ICorProfilerInfo3_GetObjectSize(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) + +#define ICorProfilerInfo3_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ + ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) + +#define ICorProfilerInfo3_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ + ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) + +#define ICorProfilerInfo3_GetCurrentThreadID(This,pThreadId) \ + ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) + +#define ICorProfilerInfo3_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ + ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) + +#define ICorProfilerInfo3_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ + ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) + +#define ICorProfilerInfo3_SetEventMask(This,dwEvents) \ + ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) + +#define ICorProfilerInfo3_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo3_SetFunctionIDMapper(This,pFunc) \ + ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) + +#define ICorProfilerInfo3_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ + ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) + +#define ICorProfilerInfo3_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ + ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) + +#define ICorProfilerInfo3_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ + ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) + +#define ICorProfilerInfo3_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ + ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) + +#define ICorProfilerInfo3_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ + ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) + +#define ICorProfilerInfo3_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ + ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) + +#define ICorProfilerInfo3_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ + ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) + +#define ICorProfilerInfo3_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ + ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) + +#define ICorProfilerInfo3_SetFunctionReJIT(This,functionId) \ + ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) + +#define ICorProfilerInfo3_ForceGC(This) \ + ( (This)->lpVtbl -> ForceGC(This) ) + +#define ICorProfilerInfo3_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ + ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) + +#define ICorProfilerInfo3_GetInprocInspectionInterface(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) + +#define ICorProfilerInfo3_GetInprocInspectionIThisThread(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) + +#define ICorProfilerInfo3_GetThreadContext(This,threadId,pContextId) \ + ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) + +#define ICorProfilerInfo3_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ + ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) + +#define ICorProfilerInfo3_EndInprocDebugging(This,dwProfilerContext) \ + ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) + +#define ICorProfilerInfo3_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) + + +#define ICorProfilerInfo3_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ + ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) + +#define ICorProfilerInfo3_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo3_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) + +#define ICorProfilerInfo3_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo3_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ + ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) + +#define ICorProfilerInfo3_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) + +#define ICorProfilerInfo3_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo3_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ + ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) + +#define ICorProfilerInfo3_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ + ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) + +#define ICorProfilerInfo3_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ + ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) + +#define ICorProfilerInfo3_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ + ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) + +#define ICorProfilerInfo3_GetBoxClassLayout(This,classId,pBufferOffset) \ + ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) + +#define ICorProfilerInfo3_GetThreadAppDomain(This,threadId,pAppDomainId) \ + ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) + +#define ICorProfilerInfo3_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ + ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) + +#define ICorProfilerInfo3_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ + ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) + +#define ICorProfilerInfo3_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) + +#define ICorProfilerInfo3_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ + ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) + +#define ICorProfilerInfo3_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ + ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) + +#define ICorProfilerInfo3_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ + ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) + +#define ICorProfilerInfo3_GetObjectGeneration(This,objectId,range) \ + ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) + +#define ICorProfilerInfo3_GetNotifiedExceptionClauseInfo(This,pinfo) \ + ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) + + +#define ICorProfilerInfo3_EnumJITedFunctions(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) + +#define ICorProfilerInfo3_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ + ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) + +#define ICorProfilerInfo3_SetFunctionIDMapper2(This,pFunc,clientData) \ + ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) + +#define ICorProfilerInfo3_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo3_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) + +#define ICorProfilerInfo3_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) + +#define ICorProfilerInfo3_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ + ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) + +#define ICorProfilerInfo3_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ + ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) + +#define ICorProfilerInfo3_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ + ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) + +#define ICorProfilerInfo3_EnumModules(This,ppEnum) \ + ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) + +#define ICorProfilerInfo3_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ + ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) + +#define ICorProfilerInfo3_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) + +#define ICorProfilerInfo3_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ + ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) + +#define ICorProfilerInfo3_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ + ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerInfo3_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerObjectEnum_INTERFACE_DEFINED__ +#define __ICorProfilerObjectEnum_INTERFACE_DEFINED__ + +/* interface ICorProfilerObjectEnum */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerObjectEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2C6269BD-2D13-4321-AE12-6686365FD6AF") + ICorProfilerObjectEnum : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ ICorProfilerObjectEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCount( + /* [out] */ ULONG *pcelt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ObjectID objects[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerObjectEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerObjectEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerObjectEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerObjectEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorProfilerObjectEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorProfilerObjectEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorProfilerObjectEnum * This, + /* [out] */ ICorProfilerObjectEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorProfilerObjectEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorProfilerObjectEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ObjectID objects[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorProfilerObjectEnumVtbl; + + interface ICorProfilerObjectEnum + { + CONST_VTBL struct ICorProfilerObjectEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerObjectEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerObjectEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerObjectEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerObjectEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorProfilerObjectEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorProfilerObjectEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorProfilerObjectEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + +#define ICorProfilerObjectEnum_Next(This,celt,objects,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerObjectEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerFunctionEnum_INTERFACE_DEFINED__ +#define __ICorProfilerFunctionEnum_INTERFACE_DEFINED__ + +/* interface ICorProfilerFunctionEnum */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerFunctionEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("FF71301A-B994-429D-A10B-B345A65280EF") + ICorProfilerFunctionEnum : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ ICorProfilerFunctionEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCount( + /* [out] */ ULONG *pcelt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ COR_PRF_FUNCTION ids[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerFunctionEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerFunctionEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerFunctionEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerFunctionEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorProfilerFunctionEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorProfilerFunctionEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorProfilerFunctionEnum * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorProfilerFunctionEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorProfilerFunctionEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ COR_PRF_FUNCTION ids[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorProfilerFunctionEnumVtbl; + + interface ICorProfilerFunctionEnum + { + CONST_VTBL struct ICorProfilerFunctionEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerFunctionEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerFunctionEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerFunctionEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerFunctionEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorProfilerFunctionEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorProfilerFunctionEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorProfilerFunctionEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + +#define ICorProfilerFunctionEnum_Next(This,celt,ids,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,ids,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerFunctionEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerModuleEnum_INTERFACE_DEFINED__ +#define __ICorProfilerModuleEnum_INTERFACE_DEFINED__ + +/* interface ICorProfilerModuleEnum */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerModuleEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("b0266d75-2081-4493-af7f-028ba34db891") + ICorProfilerModuleEnum : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ ICorProfilerModuleEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCount( + /* [out] */ ULONG *pcelt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ModuleID ids[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerModuleEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerModuleEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerModuleEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerModuleEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorProfilerModuleEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorProfilerModuleEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorProfilerModuleEnum * This, + /* [out] */ ICorProfilerModuleEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorProfilerModuleEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorProfilerModuleEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ModuleID ids[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorProfilerModuleEnumVtbl; + + interface ICorProfilerModuleEnum + { + CONST_VTBL struct ICorProfilerModuleEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerModuleEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerModuleEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerModuleEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerModuleEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorProfilerModuleEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorProfilerModuleEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorProfilerModuleEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + +#define ICorProfilerModuleEnum_Next(This,celt,ids,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,ids,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerModuleEnum_INTERFACE_DEFINED__ */ + + +#ifndef __IMethodMalloc_INTERFACE_DEFINED__ +#define __IMethodMalloc_INTERFACE_DEFINED__ + +/* interface IMethodMalloc */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_IMethodMalloc; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("A0EFB28B-6EE2-4d7b-B983-A75EF7BEEDB8") + IMethodMalloc : public IUnknown + { + public: + virtual PVOID STDMETHODCALLTYPE Alloc( + /* [in] */ ULONG cb) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IMethodMallocVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IMethodMalloc * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IMethodMalloc * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IMethodMalloc * This); + + PVOID ( STDMETHODCALLTYPE *Alloc )( + IMethodMalloc * This, + /* [in] */ ULONG cb); + + END_INTERFACE + } IMethodMallocVtbl; + + interface IMethodMalloc + { + CONST_VTBL struct IMethodMallocVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IMethodMalloc_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IMethodMalloc_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IMethodMalloc_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IMethodMalloc_Alloc(This,cb) \ + ( (This)->lpVtbl -> Alloc(This,cb) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IMethodMalloc_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerFunctionControl_INTERFACE_DEFINED__ +#define __ICorProfilerFunctionControl_INTERFACE_DEFINED__ + +/* interface ICorProfilerFunctionControl */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerFunctionControl; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("F0963021-E1EA-4732-8581-E01B0BD3C0C6") + ICorProfilerFunctionControl : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetCodegenFlags( + /* [in] */ DWORD flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetILFunctionBody( + /* [in] */ ULONG cbNewILMethodHeader, + /* [size_is][in] */ LPCBYTE pbNewILMethodHeader) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetILInstrumentedCodeMap( + /* [in] */ ULONG cILMapEntries, + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerFunctionControlVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerFunctionControl * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerFunctionControl * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerFunctionControl * This); + + HRESULT ( STDMETHODCALLTYPE *SetCodegenFlags )( + ICorProfilerFunctionControl * This, + /* [in] */ DWORD flags); + + HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( + ICorProfilerFunctionControl * This, + /* [in] */ ULONG cbNewILMethodHeader, + /* [size_is][in] */ LPCBYTE pbNewILMethodHeader); + + HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( + ICorProfilerFunctionControl * This, + /* [in] */ ULONG cILMapEntries, + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); + + END_INTERFACE + } ICorProfilerFunctionControlVtbl; + + interface ICorProfilerFunctionControl + { + CONST_VTBL struct ICorProfilerFunctionControlVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerFunctionControl_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerFunctionControl_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerFunctionControl_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerFunctionControl_SetCodegenFlags(This,flags) \ + ( (This)->lpVtbl -> SetCodegenFlags(This,flags) ) + +#define ICorProfilerFunctionControl_SetILFunctionBody(This,cbNewILMethodHeader,pbNewILMethodHeader) \ + ( (This)->lpVtbl -> SetILFunctionBody(This,cbNewILMethodHeader,pbNewILMethodHeader) ) + +#define ICorProfilerFunctionControl_SetILInstrumentedCodeMap(This,cILMapEntries,rgILMapEntries) \ + ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,cILMapEntries,rgILMapEntries) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerFunctionControl_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerInfo4_INTERFACE_DEFINED__ +#define __ICorProfilerInfo4_INTERFACE_DEFINED__ + +/* interface ICorProfilerInfo4 */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerInfo4; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("0d8fdcaa-6257-47bf-b1bf-94dac88466ee") + ICorProfilerInfo4 : public ICorProfilerInfo3 + { + public: + virtual HRESULT STDMETHODCALLTYPE EnumThreads( + /* [out] */ ICorProfilerThreadEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE InitializeCurrentThread( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE RequestReJIT( + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE RequestRevert( + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ], + /* [size_is][out] */ HRESULT status[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCodeInfo3( + /* [in] */ FunctionID functionID, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunctionFromIP2( + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId, + /* [out] */ ReJITID *pReJitId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetReJITIDs( + /* [in] */ FunctionID functionId, + /* [in] */ ULONG cReJitIds, + /* [out] */ ULONG *pcReJitIds, + /* [length_is][size_is][out] */ ReJITID reJitIds[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetILToNativeMapping2( + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumJITedFunctions2( + /* [out] */ ICorProfilerFunctionEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetObjectSize2( + /* [in] */ ObjectID objectId, + /* [out] */ SIZE_T *pcSize) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerInfo4Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerInfo4 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerInfo4 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerInfo4 * This); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( + ICorProfilerInfo4 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdTypeDef typeDef, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId, + /* [out] */ LPCBYTE *pStart, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask )( + ICorProfilerInfo4 * This, + /* [out] */ DWORD *pdwEvents); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( + ICorProfilerInfo4 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdToken token, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( + ICorProfilerInfo4 * This, + /* [in] */ ThreadID threadId, + /* [out] */ HANDLE *phThread); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( + ICorProfilerInfo4 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classId, + /* [out] */ CorElementType *pBaseElemType, + /* [out] */ ClassID *pBaseClassId, + /* [out] */ ULONG *pcRank); + + HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( + ICorProfilerInfo4 * This, + /* [in] */ ThreadID threadId, + /* [out] */ DWORD *pdwWin32ThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( + ICorProfilerInfo4 * This, + /* [out] */ ThreadID *pThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask )( + ICorProfilerInfo4 * This, + /* [in] */ DWORD dwEvents); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionEnter *pFuncEnter, + /* [in] */ FunctionLeave *pFuncLeave, + /* [in] */ FunctionTailcall *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionIDMapper *pFunc); + + HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppImport, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId); + + HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD dwOpenFlags, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppOut); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [out] */ LPCBYTE *ppMethodHeader, + /* [out] */ ULONG *pcbMethodSize); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ IMethodMalloc **ppMalloc); + + HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodid, + /* [in] */ LPCBYTE pbNewILMethodHeader); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( + ICorProfilerInfo4 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ ProcessID *pProcessId); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( + ICorProfilerInfo4 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AppDomainID *pAppDomainId, + /* [out] */ ModuleID *pModuleId); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ForceGC )( + ICorProfilerInfo4 * This); + + HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fStartJit, + /* [in] */ ULONG cILMapEntries, + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( + ICorProfilerInfo4 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( + ICorProfilerInfo4 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICorProfilerInfo4 * This, + /* [in] */ ThreadID threadId, + /* [out] */ ContextID *pContextId); + + HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( + ICorProfilerInfo4 * This, + /* [in] */ BOOL fThisThreadOnly, + /* [out] */ DWORD *pdwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( + ICorProfilerInfo4 * This, + /* [in] */ DWORD dwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( + ICorProfilerInfo4 * This, + /* [in] */ ThreadID thread, + /* [in] */ StackSnapshotCallback *callback, + /* [in] */ ULONG32 infoFlags, + /* [in] */ void *clientData, + /* [size_is][in] */ BYTE context[ ], + /* [in] */ ULONG32 contextSize); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionEnter2 *pFuncEnter, + /* [in] */ FunctionLeave2 *pFuncLeave, + /* [in] */ FunctionTailcall2 *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID funcId, + /* [in] */ COR_PRF_FRAME_INFO frameInfo, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken, + /* [in] */ ULONG32 cTypeArgs, + /* [out] */ ULONG32 *pcTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( + ICorProfilerInfo4 * This, + /* [out] */ ULONG *pBufferLengthOffset, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classID, + /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], + /* [in] */ ULONG cFieldOffset, + /* [out] */ ULONG *pcFieldOffset, + /* [out] */ ULONG *pulClassSize); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken, + /* [out] */ ClassID *pParentClassId, + /* [in] */ ULONG32 cNumTypeArgs, + /* [out] */ ULONG32 *pcNumTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdTypeDef typeDef, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ ClassID *pClassID); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdMethodDef funcDef, + /* [in] */ ClassID classId, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ FunctionID *pFunctionID); + + HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleID, + /* [out] */ ICorProfilerObjectEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( + ICorProfilerInfo4 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ULONG32 cDimensions, + /* [size_is][out] */ ULONG32 pDimensionSizes[ ], + /* [size_is][out] */ int pDimensionLowerBounds[ ], + /* [out] */ BYTE **ppData); + + HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classId, + /* [out] */ ULONG32 *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( + ICorProfilerInfo4 * This, + /* [in] */ ThreadID threadId, + /* [out] */ AppDomainID *pAppDomainId); + + HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ContextID contextId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); + + HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( + ICorProfilerInfo4 * This, + /* [in] */ ULONG cObjectRanges, + /* [out] */ ULONG *pcObjectRanges, + /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( + ICorProfilerInfo4 * This, + /* [in] */ ObjectID objectId, + /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); + + HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( + ICorProfilerInfo4 * This, + /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( + ICorProfilerInfo4 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( + ICorProfilerInfo4 * This, + /* [in] */ DWORD dwExpectedCompletionMilliseconds); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionIDMapper2 *pFunc, + /* [in] */ void *clientData); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( + ICorProfilerInfo4 * This, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionEnter3 *pFuncEnter3, + /* [in] */ FunctionLeave3 *pFuncLeave3, + /* [in] */ FunctionTailcall3 *pFuncTailcall3); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, + /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, + /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out][in] */ ULONG *pcbArgumentInfo, + /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); - HRESULT ( STDMETHODCALLTYPE *Reset )( - ICorProfilerObjectEnum * This); + HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); - HRESULT ( STDMETHODCALLTYPE *Clone )( - ICorProfilerObjectEnum * This, - /* [out] */ ICorProfilerObjectEnum **ppEnum); + HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); - HRESULT ( STDMETHODCALLTYPE *GetCount )( - ICorProfilerObjectEnum * This, - /* [out] */ ULONG *pcelt); + HRESULT ( STDMETHODCALLTYPE *EnumModules )( + ICorProfilerInfo4 * This, + /* [out] */ ICorProfilerModuleEnum **ppEnum); - HRESULT ( STDMETHODCALLTYPE *Next )( - ICorProfilerObjectEnum * This, - /* [in] */ ULONG celt, - /* [length_is][size_is][out] */ ObjectID objects[ ], - /* [out] */ ULONG *pceltFetched); + HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( + ICorProfilerInfo4 * This, + /* [out] */ USHORT *pClrInstanceId, + /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, + /* [out] */ USHORT *pMajorVersion, + /* [out] */ USHORT *pMinorVersion, + /* [out] */ USHORT *pBuildNumber, + /* [out] */ USHORT *pQFEVersion, + /* [in] */ ULONG cchVersionString, + /* [out] */ ULONG *pcchVersionString, + /* [annotation][out] */ + _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); - END_INTERFACE - } ICorProfilerObjectEnumVtbl; - - interface ICorProfilerObjectEnum - { - CONST_VTBL struct ICorProfilerObjectEnumVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define ICorProfilerObjectEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) - -#define ICorProfilerObjectEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) - -#define ICorProfilerObjectEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) - - -#define ICorProfilerObjectEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) - -#define ICorProfilerObjectEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) - -#define ICorProfilerObjectEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) - -#define ICorProfilerObjectEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) - -#define ICorProfilerObjectEnum_Next(This,celt,objects,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - - -#endif /* __ICorProfilerObjectEnum_INTERFACE_DEFINED__ */ - - -#ifndef __ICorProfilerFunctionEnum_INTERFACE_DEFINED__ -#define __ICorProfilerFunctionEnum_INTERFACE_DEFINED__ - -/* interface ICorProfilerFunctionEnum */ -/* [local][unique][uuid][object] */ - - -EXTERN_C const IID IID_ICorProfilerFunctionEnum; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("FF71301A-B994-429D-A10B-B345A65280EF") - ICorProfilerFunctionEnum : public IUnknown - { - public: - virtual HRESULT STDMETHODCALLTYPE Skip( - /* [in] */ ULONG celt) = 0; + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); - virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ ULONG32 cAppDomainIds, + /* [out] */ ULONG32 *pcAppDomainIds, + /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); - virtual HRESULT STDMETHODCALLTYPE Clone( - /* [out] */ ICorProfilerFunctionEnum **ppEnum) = 0; + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId, + /* [out] */ DWORD *pdwModuleFlags); - virtual HRESULT STDMETHODCALLTYPE GetCount( - /* [out] */ ULONG *pcelt) = 0; + HRESULT ( STDMETHODCALLTYPE *EnumThreads )( + ICorProfilerInfo4 * This, + /* [out] */ ICorProfilerThreadEnum **ppEnum); - virtual HRESULT STDMETHODCALLTYPE Next( - /* [in] */ ULONG celt, - /* [length_is][size_is][out] */ COR_PRF_FUNCTION ids[ ], - /* [out] */ ULONG *pceltFetched) = 0; + HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( + ICorProfilerInfo4 * This); - }; - - -#else /* C style interface */ - - typedef struct ICorProfilerFunctionEnumVtbl - { - BEGIN_INTERFACE + HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( + ICorProfilerInfo4 * This, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ]); - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - ICorProfilerFunctionEnum * This, - /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ - _COM_Outptr_ void **ppvObject); + HRESULT ( STDMETHODCALLTYPE *RequestRevert )( + ICorProfilerInfo4 * This, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ], + /* [size_is][out] */ HRESULT status[ ]); - ULONG ( STDMETHODCALLTYPE *AddRef )( - ICorProfilerFunctionEnum * This); + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); - ULONG ( STDMETHODCALLTYPE *Release )( - ICorProfilerFunctionEnum * This); + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( + ICorProfilerInfo4 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId, + /* [out] */ ReJITID *pReJitId); - HRESULT ( STDMETHODCALLTYPE *Skip )( - ICorProfilerFunctionEnum * This, - /* [in] */ ULONG celt); + HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG cReJitIds, + /* [out] */ ULONG *pcReJitIds, + /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); - HRESULT ( STDMETHODCALLTYPE *Reset )( - ICorProfilerFunctionEnum * This); + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); - HRESULT ( STDMETHODCALLTYPE *Clone )( - ICorProfilerFunctionEnum * This, + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( + ICorProfilerInfo4 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); - HRESULT ( STDMETHODCALLTYPE *GetCount )( - ICorProfilerFunctionEnum * This, - /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( - ICorProfilerFunctionEnum * This, - /* [in] */ ULONG celt, - /* [length_is][size_is][out] */ COR_PRF_FUNCTION ids[ ], - /* [out] */ ULONG *pceltFetched); + HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( + ICorProfilerInfo4 * This, + /* [in] */ ObjectID objectId, + /* [out] */ SIZE_T *pcSize); END_INTERFACE - } ICorProfilerFunctionEnumVtbl; + } ICorProfilerInfo4Vtbl; - interface ICorProfilerFunctionEnum + interface ICorProfilerInfo4 { - CONST_VTBL struct ICorProfilerFunctionEnumVtbl *lpVtbl; + CONST_VTBL struct ICorProfilerInfo4Vtbl *lpVtbl; }; @@ -8019,336 +9748,252 @@ EXTERN_C const IID IID_ICorProfilerFunctionEnum; #ifdef COBJMACROS -#define ICorProfilerFunctionEnum_QueryInterface(This,riid,ppvObject) \ +#define ICorProfilerInfo4_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ICorProfilerFunctionEnum_AddRef(This) \ +#define ICorProfilerInfo4_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) -#define ICorProfilerFunctionEnum_Release(This) \ +#define ICorProfilerInfo4_Release(This) \ ( (This)->lpVtbl -> Release(This) ) -#define ICorProfilerFunctionEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) +#define ICorProfilerInfo4_GetClassFromObject(This,objectId,pClassId) \ + ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) -#define ICorProfilerFunctionEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) +#define ICorProfilerInfo4_GetClassFromToken(This,moduleId,typeDef,pClassId) \ + ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) -#define ICorProfilerFunctionEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) +#define ICorProfilerInfo4_GetCodeInfo(This,functionId,pStart,pcSize) \ + ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) -#define ICorProfilerFunctionEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) +#define ICorProfilerInfo4_GetEventMask(This,pdwEvents) \ + ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) -#define ICorProfilerFunctionEnum_Next(This,celt,ids,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,ids,pceltFetched) ) +#define ICorProfilerInfo4_GetFunctionFromIP(This,ip,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) + +#define ICorProfilerInfo4_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) -#endif /* COBJMACROS */ +#define ICorProfilerInfo4_GetHandleFromThread(This,threadId,phThread) \ + ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) +#define ICorProfilerInfo4_GetObjectSize(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) -#endif /* C style interface */ +#define ICorProfilerInfo4_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ + ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) +#define ICorProfilerInfo4_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ + ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) +#define ICorProfilerInfo4_GetCurrentThreadID(This,pThreadId) \ + ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) +#define ICorProfilerInfo4_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ + ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) -#endif /* __ICorProfilerFunctionEnum_INTERFACE_DEFINED__ */ +#define ICorProfilerInfo4_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ + ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) +#define ICorProfilerInfo4_SetEventMask(This,dwEvents) \ + ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) -#ifndef __ICorProfilerModuleEnum_INTERFACE_DEFINED__ -#define __ICorProfilerModuleEnum_INTERFACE_DEFINED__ +#define ICorProfilerInfo4_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) -/* interface ICorProfilerModuleEnum */ -/* [local][unique][uuid][object] */ +#define ICorProfilerInfo4_SetFunctionIDMapper(This,pFunc) \ + ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) +#define ICorProfilerInfo4_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ + ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) -EXTERN_C const IID IID_ICorProfilerModuleEnum; +#define ICorProfilerInfo4_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ + ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("b0266d75-2081-4493-af7f-028ba34db891") - ICorProfilerModuleEnum : public IUnknown - { - public: - virtual HRESULT STDMETHODCALLTYPE Skip( - /* [in] */ ULONG celt) = 0; - - virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE Clone( - /* [out] */ ICorProfilerModuleEnum **ppEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCount( - /* [out] */ ULONG *pcelt) = 0; - - virtual HRESULT STDMETHODCALLTYPE Next( - /* [in] */ ULONG celt, - /* [length_is][size_is][out] */ ModuleID ids[ ], - /* [out] */ ULONG *pceltFetched) = 0; - - }; - - -#else /* C style interface */ +#define ICorProfilerInfo4_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ + ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) - typedef struct ICorProfilerModuleEnumVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - ICorProfilerModuleEnum * This, - /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ - _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - ICorProfilerModuleEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - ICorProfilerModuleEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( - ICorProfilerModuleEnum * This, - /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( - ICorProfilerModuleEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( - ICorProfilerModuleEnum * This, - /* [out] */ ICorProfilerModuleEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( - ICorProfilerModuleEnum * This, - /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( - ICorProfilerModuleEnum * This, - /* [in] */ ULONG celt, - /* [length_is][size_is][out] */ ModuleID ids[ ], - /* [out] */ ULONG *pceltFetched); - - END_INTERFACE - } ICorProfilerModuleEnumVtbl; +#define ICorProfilerInfo4_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ + ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) - interface ICorProfilerModuleEnum - { - CONST_VTBL struct ICorProfilerModuleEnumVtbl *lpVtbl; - }; +#define ICorProfilerInfo4_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ + ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) - +#define ICorProfilerInfo4_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ + ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) -#ifdef COBJMACROS +#define ICorProfilerInfo4_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ + ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) +#define ICorProfilerInfo4_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ + ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) -#define ICorProfilerModuleEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) +#define ICorProfilerInfo4_SetFunctionReJIT(This,functionId) \ + ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) -#define ICorProfilerModuleEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) +#define ICorProfilerInfo4_ForceGC(This) \ + ( (This)->lpVtbl -> ForceGC(This) ) -#define ICorProfilerModuleEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) +#define ICorProfilerInfo4_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ + ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) +#define ICorProfilerInfo4_GetInprocInspectionInterface(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) -#define ICorProfilerModuleEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) +#define ICorProfilerInfo4_GetInprocInspectionIThisThread(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) -#define ICorProfilerModuleEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) +#define ICorProfilerInfo4_GetThreadContext(This,threadId,pContextId) \ + ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) -#define ICorProfilerModuleEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) +#define ICorProfilerInfo4_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ + ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) -#define ICorProfilerModuleEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) +#define ICorProfilerInfo4_EndInprocDebugging(This,dwProfilerContext) \ + ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) -#define ICorProfilerModuleEnum_Next(This,celt,ids,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,ids,pceltFetched) ) +#define ICorProfilerInfo4_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) -#endif /* COBJMACROS */ +#define ICorProfilerInfo4_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ + ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) -#endif /* C style interface */ +#define ICorProfilerInfo4_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) +#define ICorProfilerInfo4_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) +#define ICorProfilerInfo4_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) +#define ICorProfilerInfo4_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ + ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) -#endif /* __ICorProfilerModuleEnum_INTERFACE_DEFINED__ */ +#define ICorProfilerInfo4_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) +#define ICorProfilerInfo4_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) -#ifndef __IMethodMalloc_INTERFACE_DEFINED__ -#define __IMethodMalloc_INTERFACE_DEFINED__ +#define ICorProfilerInfo4_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ + ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) -/* interface IMethodMalloc */ -/* [local][unique][uuid][object] */ +#define ICorProfilerInfo4_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ + ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) +#define ICorProfilerInfo4_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ + ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) -EXTERN_C const IID IID_IMethodMalloc; +#define ICorProfilerInfo4_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ + ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("A0EFB28B-6EE2-4d7b-B983-A75EF7BEEDB8") - IMethodMalloc : public IUnknown - { - public: - virtual PVOID STDMETHODCALLTYPE Alloc( - /* [in] */ ULONG cb) = 0; - - }; - - -#else /* C style interface */ +#define ICorProfilerInfo4_GetBoxClassLayout(This,classId,pBufferOffset) \ + ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) - typedef struct IMethodMallocVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IMethodMalloc * This, - /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ - _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IMethodMalloc * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IMethodMalloc * This); - - PVOID ( STDMETHODCALLTYPE *Alloc )( - IMethodMalloc * This, - /* [in] */ ULONG cb); - - END_INTERFACE - } IMethodMallocVtbl; +#define ICorProfilerInfo4_GetThreadAppDomain(This,threadId,pAppDomainId) \ + ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) - interface IMethodMalloc - { - CONST_VTBL struct IMethodMallocVtbl *lpVtbl; - }; +#define ICorProfilerInfo4_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ + ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) - +#define ICorProfilerInfo4_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ + ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) -#ifdef COBJMACROS +#define ICorProfilerInfo4_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) +#define ICorProfilerInfo4_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ + ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) -#define IMethodMalloc_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) +#define ICorProfilerInfo4_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ + ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) -#define IMethodMalloc_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) +#define ICorProfilerInfo4_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ + ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) -#define IMethodMalloc_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) +#define ICorProfilerInfo4_GetObjectGeneration(This,objectId,range) \ + ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) +#define ICorProfilerInfo4_GetNotifiedExceptionClauseInfo(This,pinfo) \ + ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) -#define IMethodMalloc_Alloc(This,cb) \ - ( (This)->lpVtbl -> Alloc(This,cb) ) -#endif /* COBJMACROS */ +#define ICorProfilerInfo4_EnumJITedFunctions(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) +#define ICorProfilerInfo4_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ + ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) -#endif /* C style interface */ +#define ICorProfilerInfo4_SetFunctionIDMapper2(This,pFunc,clientData) \ + ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) +#define ICorProfilerInfo4_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) +#define ICorProfilerInfo4_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) +#define ICorProfilerInfo4_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) -#endif /* __IMethodMalloc_INTERFACE_DEFINED__ */ +#define ICorProfilerInfo4_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ + ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) +#define ICorProfilerInfo4_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ + ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) -#ifndef __ICorProfilerFunctionControl_INTERFACE_DEFINED__ -#define __ICorProfilerFunctionControl_INTERFACE_DEFINED__ +#define ICorProfilerInfo4_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ + ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) -/* interface ICorProfilerFunctionControl */ -/* [local][unique][uuid][object] */ +#define ICorProfilerInfo4_EnumModules(This,ppEnum) \ + ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) +#define ICorProfilerInfo4_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ + ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) -EXTERN_C const IID IID_ICorProfilerFunctionControl; +#define ICorProfilerInfo4_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("F0963021-E1EA-4732-8581-E01B0BD3C0C6") - ICorProfilerFunctionControl : public IUnknown - { - public: - virtual HRESULT STDMETHODCALLTYPE SetCodegenFlags( - /* [in] */ DWORD flags) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetILFunctionBody( - /* [in] */ ULONG cbNewILMethodHeader, - /* [size_is][in] */ LPCBYTE pbNewILMethodHeader) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetILInstrumentedCodeMap( - /* [in] */ ULONG cILMapEntries, - /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]) = 0; - - }; - - -#else /* C style interface */ +#define ICorProfilerInfo4_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ + ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) - typedef struct ICorProfilerFunctionControlVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - ICorProfilerFunctionControl * This, - /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ - _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - ICorProfilerFunctionControl * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - ICorProfilerFunctionControl * This); - - HRESULT ( STDMETHODCALLTYPE *SetCodegenFlags )( - ICorProfilerFunctionControl * This, - /* [in] */ DWORD flags); - - HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( - ICorProfilerFunctionControl * This, - /* [in] */ ULONG cbNewILMethodHeader, - /* [size_is][in] */ LPCBYTE pbNewILMethodHeader); - - HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( - ICorProfilerFunctionControl * This, - /* [in] */ ULONG cILMapEntries, - /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); - - END_INTERFACE - } ICorProfilerFunctionControlVtbl; +#define ICorProfilerInfo4_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ + ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) - interface ICorProfilerFunctionControl - { - CONST_VTBL struct ICorProfilerFunctionControlVtbl *lpVtbl; - }; - +#define ICorProfilerInfo4_EnumThreads(This,ppEnum) \ + ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) -#ifdef COBJMACROS +#define ICorProfilerInfo4_InitializeCurrentThread(This) \ + ( (This)->lpVtbl -> InitializeCurrentThread(This) ) +#define ICorProfilerInfo4_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ + ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) -#define ICorProfilerFunctionControl_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) +#define ICorProfilerInfo4_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ + ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) -#define ICorProfilerFunctionControl_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) +#define ICorProfilerInfo4_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) -#define ICorProfilerFunctionControl_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) +#define ICorProfilerInfo4_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ + ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) +#define ICorProfilerInfo4_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ + ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) -#define ICorProfilerFunctionControl_SetCodegenFlags(This,flags) \ - ( (This)->lpVtbl -> SetCodegenFlags(This,flags) ) +#define ICorProfilerInfo4_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) -#define ICorProfilerFunctionControl_SetILFunctionBody(This,cbNewILMethodHeader,pbNewILMethodHeader) \ - ( (This)->lpVtbl -> SetILFunctionBody(This,cbNewILMethodHeader,pbNewILMethodHeader) ) +#define ICorProfilerInfo4_EnumJITedFunctions2(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) -#define ICorProfilerFunctionControl_SetILInstrumentedCodeMap(This,cILMapEntries,rgILMapEntries) \ - ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,cILMapEntries,rgILMapEntries) ) +#define ICorProfilerInfo4_GetObjectSize2(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) #endif /* COBJMACROS */ @@ -8358,187 +10003,147 @@ EXTERN_C const IID IID_ICorProfilerFunctionControl; -#endif /* __ICorProfilerFunctionControl_INTERFACE_DEFINED__ */ +#endif /* __ICorProfilerInfo4_INTERFACE_DEFINED__ */ -#ifndef __ICorProfilerInfo4_INTERFACE_DEFINED__ -#define __ICorProfilerInfo4_INTERFACE_DEFINED__ +#ifndef __ICorProfilerInfo5_INTERFACE_DEFINED__ +#define __ICorProfilerInfo5_INTERFACE_DEFINED__ -/* interface ICorProfilerInfo4 */ +/* interface ICorProfilerInfo5 */ /* [local][unique][uuid][object] */ -EXTERN_C const IID IID_ICorProfilerInfo4; +EXTERN_C const IID IID_ICorProfilerInfo5; #if defined(__cplusplus) && !defined(CINTERFACE) - MIDL_INTERFACE("0d8fdcaa-6257-47bf-b1bf-94dac88466ee") - ICorProfilerInfo4 : public ICorProfilerInfo3 + MIDL_INTERFACE("07602928-CE38-4B83-81E7-74ADAF781214") + ICorProfilerInfo5 : public ICorProfilerInfo4 { public: - virtual HRESULT STDMETHODCALLTYPE EnumThreads( - /* [out] */ ICorProfilerThreadEnum **ppEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE InitializeCurrentThread( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE RequestReJIT( - /* [in] */ ULONG cFunctions, - /* [size_is][in] */ ModuleID moduleIds[ ], - /* [size_is][in] */ mdMethodDef methodIds[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE RequestRevert( - /* [in] */ ULONG cFunctions, - /* [size_is][in] */ ModuleID moduleIds[ ], - /* [size_is][in] */ mdMethodDef methodIds[ ], - /* [size_is][out] */ HRESULT status[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCodeInfo3( - /* [in] */ FunctionID functionID, - /* [in] */ ReJITID reJitId, - /* [in] */ ULONG32 cCodeInfos, - /* [out] */ ULONG32 *pcCodeInfos, - /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFunctionFromIP2( - /* [in] */ LPCBYTE ip, - /* [out] */ FunctionID *pFunctionId, - /* [out] */ ReJITID *pReJitId) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetReJITIDs( - /* [in] */ FunctionID functionId, - /* [in] */ ULONG cReJitIds, - /* [out] */ ULONG *pcReJitIds, - /* [length_is][size_is][out] */ ReJITID reJitIds[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetILToNativeMapping2( - /* [in] */ FunctionID functionId, - /* [in] */ ReJITID reJitId, - /* [in] */ ULONG32 cMap, - /* [out] */ ULONG32 *pcMap, - /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumJITedFunctions2( - /* [out] */ ICorProfilerFunctionEnum **ppEnum) = 0; + virtual HRESULT STDMETHODCALLTYPE GetEventMask2( + /* [out] */ DWORD *pdwEventsLow, + /* [out] */ DWORD *pdwEventsHigh) = 0; - virtual HRESULT STDMETHODCALLTYPE GetObjectSize2( - /* [in] */ ObjectID objectId, - /* [out] */ SIZE_T *pcSize) = 0; + virtual HRESULT STDMETHODCALLTYPE SetEventMask2( + /* [in] */ DWORD dwEventsLow, + /* [in] */ DWORD dwEventsHigh) = 0; }; #else /* C style interface */ - typedef struct ICorProfilerInfo4Vtbl + typedef struct ICorProfilerInfo5Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( - ICorProfilerInfo4 * This); + ICorProfilerInfo5 * This); ULONG ( STDMETHODCALLTYPE *Release )( - ICorProfilerInfo4 * This); + ICorProfilerInfo5 * This); HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [out] */ DWORD *pdwEvents); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread); HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank); HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId); HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [out] */ ThreadID *pThreadId); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *SetEventMask )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ DWORD dwEvents); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ FunctionIDMapper *pFunc); HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, @@ -8548,32 +10153,32 @@ EXTERN_C const IID IID_ICorProfilerInfo4; /* [out] */ AssemblyID *pAssemblyId); HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc); HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader); HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, @@ -8582,7 +10187,7 @@ EXTERN_C const IID IID_ICorProfilerInfo4; /* [out] */ ProcessID *pProcessId); HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, @@ -8592,50 +10197,50 @@ EXTERN_C const IID IID_ICorProfilerInfo4; /* [out] */ ModuleID *pModuleId); HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ForceGC )( - ICorProfilerInfo4 * This); + ICorProfilerInfo5 * This); HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId); HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext); HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ DWORD dwProfilerContext); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ThreadID thread, /* [in] */ StackSnapshotCallback *callback, /* [in] */ ULONG32 infoFlags, @@ -8644,13 +10249,13 @@ EXTERN_C const IID IID_ICorProfilerInfo4; /* [in] */ ULONG32 contextSize); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ FunctionEnter2 *pFuncEnter, /* [in] */ FunctionLeave2 *pFuncLeave, /* [in] */ FunctionTailcall2 *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ FunctionID funcId, /* [in] */ COR_PRF_FRAME_INFO frameInfo, /* [out] */ ClassID *pClassId, @@ -8661,13 +10266,13 @@ EXTERN_C const IID IID_ICorProfilerInfo4; /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ClassID classID, /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], /* [in] */ ULONG cFieldOffset, @@ -8675,7 +10280,7 @@ EXTERN_C const IID IID_ICorProfilerInfo4; /* [out] */ ULONG *pulClassSize); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken, @@ -8685,14 +10290,14 @@ EXTERN_C const IID IID_ICorProfilerInfo4; /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ FunctionID functionID, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdTypeDef typeDef, /* [in] */ ULONG32 cTypeArgs, @@ -8700,7 +10305,7 @@ EXTERN_C const IID IID_ICorProfilerInfo4; /* [out] */ ClassID *pClassID); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdMethodDef funcDef, /* [in] */ ClassID classId, @@ -8709,12 +10314,12 @@ EXTERN_C const IID IID_ICorProfilerInfo4; /* [out] */ FunctionID *pFunctionID); HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleID, /* [out] */ ICorProfilerObjectEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ObjectID objectId, /* [in] */ ULONG32 cDimensions, /* [size_is][out] */ ULONG32 pDimensionSizes[ ], @@ -8722,95 +10327,95 @@ EXTERN_C const IID IID_ICorProfilerInfo4; /* [out] */ BYTE **ppData); HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ClassID classId, /* [out] */ ULONG32 *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ThreadID threadId, /* [out] */ AppDomainID *pAppDomainId); HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ContextID contextId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ULONG cObjectRanges, /* [out] */ ULONG *pcObjectRanges, /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ObjectID objectId, /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ DWORD dwExpectedCompletionMilliseconds); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ FunctionIDMapper2 *pFunc, /* [in] */ void *clientData); HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ FunctionEnter3 *pFuncEnter3, /* [in] */ FunctionLeave3 *pFuncLeave3, /* [in] */ FunctionTailcall3 *pFuncTailcall3); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, @@ -8818,24 +10423,24 @@ EXTERN_C const IID IID_ICorProfilerInfo4; /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); HRESULT ( STDMETHODCALLTYPE *EnumModules )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [out] */ ICorProfilerModuleEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [out] */ USHORT *pClrInstanceId, /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, /* [out] */ USHORT *pMajorVersion, @@ -8848,7 +10453,7 @@ EXTERN_C const IID IID_ICorProfilerInfo4; _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, @@ -8856,14 +10461,14 @@ EXTERN_C const IID IID_ICorProfilerInfo4; /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleId, /* [in] */ ULONG32 cAppDomainIds, /* [out] */ ULONG32 *pcAppDomainIds, /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, @@ -8874,27 +10479,27 @@ EXTERN_C const IID IID_ICorProfilerInfo4; /* [out] */ DWORD *pdwModuleFlags); HRESULT ( STDMETHODCALLTYPE *EnumThreads )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [out] */ ICorProfilerThreadEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( - ICorProfilerInfo4 * This); + ICorProfilerInfo5 * This); HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]); HRESULT ( STDMETHODCALLTYPE *RequestRevert )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ], /* [size_is][out] */ HRESULT status[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ FunctionID functionID, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cCodeInfos, @@ -8902,20 +10507,20 @@ EXTERN_C const IID IID_ICorProfilerInfo4; /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId, /* [out] */ ReJITID *pReJitId); HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG cReJitIds, /* [out] */ ULONG *pcReJitIds, /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cMap, @@ -8923,20 +10528,30 @@ EXTERN_C const IID IID_ICorProfilerInfo4; /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( - ICorProfilerInfo4 * This, + ICorProfilerInfo5 * This, /* [in] */ ObjectID objectId, /* [out] */ SIZE_T *pcSize); + HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( + ICorProfilerInfo5 * This, + /* [out] */ DWORD *pdwEventsLow, + /* [out] */ DWORD *pdwEventsHigh); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( + ICorProfilerInfo5 * This, + /* [in] */ DWORD dwEventsLow, + /* [in] */ DWORD dwEventsHigh); + END_INTERFACE - } ICorProfilerInfo4Vtbl; + } ICorProfilerInfo5Vtbl; - interface ICorProfilerInfo4 + interface ICorProfilerInfo5 { - CONST_VTBL struct ICorProfilerInfo4Vtbl *lpVtbl; + CONST_VTBL struct ICorProfilerInfo5Vtbl *lpVtbl; }; @@ -8944,253 +10559,260 @@ EXTERN_C const IID IID_ICorProfilerInfo4; #ifdef COBJMACROS -#define ICorProfilerInfo4_QueryInterface(This,riid,ppvObject) \ +#define ICorProfilerInfo5_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ICorProfilerInfo4_AddRef(This) \ +#define ICorProfilerInfo5_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) -#define ICorProfilerInfo4_Release(This) \ +#define ICorProfilerInfo5_Release(This) \ ( (This)->lpVtbl -> Release(This) ) -#define ICorProfilerInfo4_GetClassFromObject(This,objectId,pClassId) \ +#define ICorProfilerInfo5_GetClassFromObject(This,objectId,pClassId) \ ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) -#define ICorProfilerInfo4_GetClassFromToken(This,moduleId,typeDef,pClassId) \ +#define ICorProfilerInfo5_GetClassFromToken(This,moduleId,typeDef,pClassId) \ ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) -#define ICorProfilerInfo4_GetCodeInfo(This,functionId,pStart,pcSize) \ +#define ICorProfilerInfo5_GetCodeInfo(This,functionId,pStart,pcSize) \ ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) -#define ICorProfilerInfo4_GetEventMask(This,pdwEvents) \ +#define ICorProfilerInfo5_GetEventMask(This,pdwEvents) \ ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) -#define ICorProfilerInfo4_GetFunctionFromIP(This,ip,pFunctionId) \ +#define ICorProfilerInfo5_GetFunctionFromIP(This,ip,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) -#define ICorProfilerInfo4_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ +#define ICorProfilerInfo5_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) -#define ICorProfilerInfo4_GetHandleFromThread(This,threadId,phThread) \ +#define ICorProfilerInfo5_GetHandleFromThread(This,threadId,phThread) \ ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) -#define ICorProfilerInfo4_GetObjectSize(This,objectId,pcSize) \ +#define ICorProfilerInfo5_GetObjectSize(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) -#define ICorProfilerInfo4_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ +#define ICorProfilerInfo5_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) -#define ICorProfilerInfo4_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ +#define ICorProfilerInfo5_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) -#define ICorProfilerInfo4_GetCurrentThreadID(This,pThreadId) \ +#define ICorProfilerInfo5_GetCurrentThreadID(This,pThreadId) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) -#define ICorProfilerInfo4_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ +#define ICorProfilerInfo5_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) -#define ICorProfilerInfo4_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ +#define ICorProfilerInfo5_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) -#define ICorProfilerInfo4_SetEventMask(This,dwEvents) \ +#define ICorProfilerInfo5_SetEventMask(This,dwEvents) \ ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) -#define ICorProfilerInfo4_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ +#define ICorProfilerInfo5_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) -#define ICorProfilerInfo4_SetFunctionIDMapper(This,pFunc) \ +#define ICorProfilerInfo5_SetFunctionIDMapper(This,pFunc) \ ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) -#define ICorProfilerInfo4_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ +#define ICorProfilerInfo5_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) -#define ICorProfilerInfo4_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ +#define ICorProfilerInfo5_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) -#define ICorProfilerInfo4_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ +#define ICorProfilerInfo5_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) -#define ICorProfilerInfo4_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ +#define ICorProfilerInfo5_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) -#define ICorProfilerInfo4_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ +#define ICorProfilerInfo5_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) -#define ICorProfilerInfo4_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ +#define ICorProfilerInfo5_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) -#define ICorProfilerInfo4_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ +#define ICorProfilerInfo5_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) -#define ICorProfilerInfo4_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ +#define ICorProfilerInfo5_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) -#define ICorProfilerInfo4_SetFunctionReJIT(This,functionId) \ +#define ICorProfilerInfo5_SetFunctionReJIT(This,functionId) \ ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) -#define ICorProfilerInfo4_ForceGC(This) \ +#define ICorProfilerInfo5_ForceGC(This) \ ( (This)->lpVtbl -> ForceGC(This) ) -#define ICorProfilerInfo4_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ +#define ICorProfilerInfo5_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) -#define ICorProfilerInfo4_GetInprocInspectionInterface(This,ppicd) \ +#define ICorProfilerInfo5_GetInprocInspectionInterface(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) -#define ICorProfilerInfo4_GetInprocInspectionIThisThread(This,ppicd) \ +#define ICorProfilerInfo5_GetInprocInspectionIThisThread(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) -#define ICorProfilerInfo4_GetThreadContext(This,threadId,pContextId) \ +#define ICorProfilerInfo5_GetThreadContext(This,threadId,pContextId) \ ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) -#define ICorProfilerInfo4_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ +#define ICorProfilerInfo5_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) -#define ICorProfilerInfo4_EndInprocDebugging(This,dwProfilerContext) \ +#define ICorProfilerInfo5_EndInprocDebugging(This,dwProfilerContext) \ ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) -#define ICorProfilerInfo4_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ +#define ICorProfilerInfo5_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) -#define ICorProfilerInfo4_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ +#define ICorProfilerInfo5_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) -#define ICorProfilerInfo4_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ +#define ICorProfilerInfo5_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) -#define ICorProfilerInfo4_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ +#define ICorProfilerInfo5_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) -#define ICorProfilerInfo4_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ +#define ICorProfilerInfo5_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) -#define ICorProfilerInfo4_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ +#define ICorProfilerInfo5_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) -#define ICorProfilerInfo4_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ +#define ICorProfilerInfo5_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) -#define ICorProfilerInfo4_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ +#define ICorProfilerInfo5_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) -#define ICorProfilerInfo4_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ +#define ICorProfilerInfo5_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) -#define ICorProfilerInfo4_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ +#define ICorProfilerInfo5_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) -#define ICorProfilerInfo4_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ +#define ICorProfilerInfo5_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) -#define ICorProfilerInfo4_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ +#define ICorProfilerInfo5_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) -#define ICorProfilerInfo4_GetBoxClassLayout(This,classId,pBufferOffset) \ +#define ICorProfilerInfo5_GetBoxClassLayout(This,classId,pBufferOffset) \ ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) -#define ICorProfilerInfo4_GetThreadAppDomain(This,threadId,pAppDomainId) \ +#define ICorProfilerInfo5_GetThreadAppDomain(This,threadId,pAppDomainId) \ ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) -#define ICorProfilerInfo4_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ +#define ICorProfilerInfo5_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) -#define ICorProfilerInfo4_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ +#define ICorProfilerInfo5_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) -#define ICorProfilerInfo4_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ +#define ICorProfilerInfo5_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) -#define ICorProfilerInfo4_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ +#define ICorProfilerInfo5_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) -#define ICorProfilerInfo4_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ +#define ICorProfilerInfo5_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) -#define ICorProfilerInfo4_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ +#define ICorProfilerInfo5_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) -#define ICorProfilerInfo4_GetObjectGeneration(This,objectId,range) \ +#define ICorProfilerInfo5_GetObjectGeneration(This,objectId,range) \ ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) -#define ICorProfilerInfo4_GetNotifiedExceptionClauseInfo(This,pinfo) \ +#define ICorProfilerInfo5_GetNotifiedExceptionClauseInfo(This,pinfo) \ ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) -#define ICorProfilerInfo4_EnumJITedFunctions(This,ppEnum) \ +#define ICorProfilerInfo5_EnumJITedFunctions(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) -#define ICorProfilerInfo4_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ +#define ICorProfilerInfo5_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) -#define ICorProfilerInfo4_SetFunctionIDMapper2(This,pFunc,clientData) \ +#define ICorProfilerInfo5_SetFunctionIDMapper2(This,pFunc,clientData) \ ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) -#define ICorProfilerInfo4_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ +#define ICorProfilerInfo5_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) -#define ICorProfilerInfo4_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ +#define ICorProfilerInfo5_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) -#define ICorProfilerInfo4_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ +#define ICorProfilerInfo5_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) -#define ICorProfilerInfo4_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ +#define ICorProfilerInfo5_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) -#define ICorProfilerInfo4_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ +#define ICorProfilerInfo5_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) -#define ICorProfilerInfo4_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ +#define ICorProfilerInfo5_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) -#define ICorProfilerInfo4_EnumModules(This,ppEnum) \ +#define ICorProfilerInfo5_EnumModules(This,ppEnum) \ ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) -#define ICorProfilerInfo4_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ +#define ICorProfilerInfo5_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) -#define ICorProfilerInfo4_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ +#define ICorProfilerInfo5_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) -#define ICorProfilerInfo4_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ +#define ICorProfilerInfo5_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) -#define ICorProfilerInfo4_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ +#define ICorProfilerInfo5_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) -#define ICorProfilerInfo4_EnumThreads(This,ppEnum) \ +#define ICorProfilerInfo5_EnumThreads(This,ppEnum) \ ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) -#define ICorProfilerInfo4_InitializeCurrentThread(This) \ +#define ICorProfilerInfo5_InitializeCurrentThread(This) \ ( (This)->lpVtbl -> InitializeCurrentThread(This) ) -#define ICorProfilerInfo4_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ +#define ICorProfilerInfo5_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) -#define ICorProfilerInfo4_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ +#define ICorProfilerInfo5_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) -#define ICorProfilerInfo4_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ +#define ICorProfilerInfo5_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) -#define ICorProfilerInfo4_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ +#define ICorProfilerInfo5_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) -#define ICorProfilerInfo4_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ +#define ICorProfilerInfo5_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) -#define ICorProfilerInfo4_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ +#define ICorProfilerInfo5_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) -#define ICorProfilerInfo4_EnumJITedFunctions2(This,ppEnum) \ +#define ICorProfilerInfo5_EnumJITedFunctions2(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) -#define ICorProfilerInfo4_GetObjectSize2(This,objectId,pcSize) \ +#define ICorProfilerInfo5_GetObjectSize2(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) + +#define ICorProfilerInfo5_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ + ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) + +#define ICorProfilerInfo5_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ + ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) + #endif /* COBJMACROS */ @@ -9199,147 +10821,146 @@ EXTERN_C const IID IID_ICorProfilerInfo4; -#endif /* __ICorProfilerInfo4_INTERFACE_DEFINED__ */ +#endif /* __ICorProfilerInfo5_INTERFACE_DEFINED__ */ -#ifndef __ICorProfilerInfo5_INTERFACE_DEFINED__ -#define __ICorProfilerInfo5_INTERFACE_DEFINED__ +#ifndef __ICorProfilerInfo6_INTERFACE_DEFINED__ +#define __ICorProfilerInfo6_INTERFACE_DEFINED__ -/* interface ICorProfilerInfo5 */ +/* interface ICorProfilerInfo6 */ /* [local][unique][uuid][object] */ -EXTERN_C const IID IID_ICorProfilerInfo5; +EXTERN_C const IID IID_ICorProfilerInfo6; #if defined(__cplusplus) && !defined(CINTERFACE) - MIDL_INTERFACE("07602928-CE38-4B83-81E7-74ADAF781214") - ICorProfilerInfo5 : public ICorProfilerInfo4 + MIDL_INTERFACE("F30A070D-BFFB-46A7-B1D8-8781EF7B698A") + ICorProfilerInfo6 : public ICorProfilerInfo5 { public: - virtual HRESULT STDMETHODCALLTYPE GetEventMask2( - /* [out] */ DWORD *pdwEventsLow, - /* [out] */ DWORD *pdwEventsHigh) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetEventMask2( - /* [in] */ DWORD dwEventsLow, - /* [in] */ DWORD dwEventsHigh) = 0; + virtual HRESULT STDMETHODCALLTYPE EnumNgenModuleMethodsInliningThisMethod( + /* [in] */ ModuleID inlinersModuleId, + /* [in] */ ModuleID inlineeModuleId, + /* [in] */ mdMethodDef inlineeMethodId, + /* [out] */ BOOL *incompleteData, + /* [out] */ ICorProfilerMethodEnum **ppEnum) = 0; }; #else /* C style interface */ - typedef struct ICorProfilerInfo5Vtbl + typedef struct ICorProfilerInfo6Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( - ICorProfilerInfo5 * This); + ICorProfilerInfo6 * This); ULONG ( STDMETHODCALLTYPE *Release )( - ICorProfilerInfo5 * This); + ICorProfilerInfo6 * This); HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [out] */ DWORD *pdwEvents); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread); HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank); HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId); HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [out] */ ThreadID *pThreadId); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *SetEventMask )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ DWORD dwEvents); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ FunctionIDMapper *pFunc); HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, @@ -9349,32 +10970,32 @@ EXTERN_C const IID IID_ICorProfilerInfo5; /* [out] */ AssemblyID *pAssemblyId); HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc); HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader); HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, @@ -9383,7 +11004,7 @@ EXTERN_C const IID IID_ICorProfilerInfo5; /* [out] */ ProcessID *pProcessId); HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, @@ -9393,50 +11014,50 @@ EXTERN_C const IID IID_ICorProfilerInfo5; /* [out] */ ModuleID *pModuleId); HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ForceGC )( - ICorProfilerInfo5 * This); + ICorProfilerInfo6 * This); HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId); HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext); HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ DWORD dwProfilerContext); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ThreadID thread, /* [in] */ StackSnapshotCallback *callback, /* [in] */ ULONG32 infoFlags, @@ -9445,13 +11066,13 @@ EXTERN_C const IID IID_ICorProfilerInfo5; /* [in] */ ULONG32 contextSize); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ FunctionEnter2 *pFuncEnter, /* [in] */ FunctionLeave2 *pFuncLeave, /* [in] */ FunctionTailcall2 *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ FunctionID funcId, /* [in] */ COR_PRF_FRAME_INFO frameInfo, /* [out] */ ClassID *pClassId, @@ -9462,13 +11083,13 @@ EXTERN_C const IID IID_ICorProfilerInfo5; /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ClassID classID, /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], /* [in] */ ULONG cFieldOffset, @@ -9476,7 +11097,7 @@ EXTERN_C const IID IID_ICorProfilerInfo5; /* [out] */ ULONG *pulClassSize); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken, @@ -9486,14 +11107,14 @@ EXTERN_C const IID IID_ICorProfilerInfo5; /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ FunctionID functionID, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdTypeDef typeDef, /* [in] */ ULONG32 cTypeArgs, @@ -9501,7 +11122,7 @@ EXTERN_C const IID IID_ICorProfilerInfo5; /* [out] */ ClassID *pClassID); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdMethodDef funcDef, /* [in] */ ClassID classId, @@ -9510,12 +11131,12 @@ EXTERN_C const IID IID_ICorProfilerInfo5; /* [out] */ FunctionID *pFunctionID); HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleID, /* [out] */ ICorProfilerObjectEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ObjectID objectId, /* [in] */ ULONG32 cDimensions, /* [size_is][out] */ ULONG32 pDimensionSizes[ ], @@ -9523,95 +11144,95 @@ EXTERN_C const IID IID_ICorProfilerInfo5; /* [out] */ BYTE **ppData); HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ClassID classId, /* [out] */ ULONG32 *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ThreadID threadId, /* [out] */ AppDomainID *pAppDomainId); HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ContextID contextId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ULONG cObjectRanges, /* [out] */ ULONG *pcObjectRanges, /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ObjectID objectId, /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ DWORD dwExpectedCompletionMilliseconds); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ FunctionIDMapper2 *pFunc, /* [in] */ void *clientData); HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ FunctionEnter3 *pFuncEnter3, /* [in] */ FunctionLeave3 *pFuncLeave3, /* [in] */ FunctionTailcall3 *pFuncTailcall3); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, @@ -9619,24 +11240,24 @@ EXTERN_C const IID IID_ICorProfilerInfo5; /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); HRESULT ( STDMETHODCALLTYPE *EnumModules )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [out] */ ICorProfilerModuleEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [out] */ USHORT *pClrInstanceId, /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, /* [out] */ USHORT *pMajorVersion, @@ -9649,7 +11270,7 @@ EXTERN_C const IID IID_ICorProfilerInfo5; _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, @@ -9657,14 +11278,14 @@ EXTERN_C const IID IID_ICorProfilerInfo5; /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleId, /* [in] */ ULONG32 cAppDomainIds, /* [out] */ ULONG32 *pcAppDomainIds, /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, @@ -9675,27 +11296,27 @@ EXTERN_C const IID IID_ICorProfilerInfo5; /* [out] */ DWORD *pdwModuleFlags); HRESULT ( STDMETHODCALLTYPE *EnumThreads )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [out] */ ICorProfilerThreadEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( - ICorProfilerInfo5 * This); + ICorProfilerInfo6 * This); HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]); HRESULT ( STDMETHODCALLTYPE *RequestRevert )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ], /* [size_is][out] */ HRESULT status[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ FunctionID functionID, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cCodeInfos, @@ -9703,20 +11324,20 @@ EXTERN_C const IID IID_ICorProfilerInfo5; /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId, /* [out] */ ReJITID *pReJitId); HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG cReJitIds, /* [out] */ ULONG *pcReJitIds, /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cMap, @@ -9724,30 +11345,38 @@ EXTERN_C const IID IID_ICorProfilerInfo5; /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ ObjectID objectId, /* [out] */ SIZE_T *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [out] */ DWORD *pdwEventsLow, /* [out] */ DWORD *pdwEventsHigh); HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( - ICorProfilerInfo5 * This, + ICorProfilerInfo6 * This, /* [in] */ DWORD dwEventsLow, /* [in] */ DWORD dwEventsHigh); + HRESULT ( STDMETHODCALLTYPE *EnumNgenModuleMethodsInliningThisMethod )( + ICorProfilerInfo6 * This, + /* [in] */ ModuleID inlinersModuleId, + /* [in] */ ModuleID inlineeModuleId, + /* [in] */ mdMethodDef inlineeMethodId, + /* [out] */ BOOL *incompleteData, + /* [out] */ ICorProfilerMethodEnum **ppEnum); + END_INTERFACE - } ICorProfilerInfo5Vtbl; + } ICorProfilerInfo6Vtbl; - interface ICorProfilerInfo5 + interface ICorProfilerInfo6 { - CONST_VTBL struct ICorProfilerInfo5Vtbl *lpVtbl; + CONST_VTBL struct ICorProfilerInfo6Vtbl *lpVtbl; }; @@ -9755,260 +11384,264 @@ EXTERN_C const IID IID_ICorProfilerInfo5; #ifdef COBJMACROS -#define ICorProfilerInfo5_QueryInterface(This,riid,ppvObject) \ +#define ICorProfilerInfo6_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ICorProfilerInfo5_AddRef(This) \ +#define ICorProfilerInfo6_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) -#define ICorProfilerInfo5_Release(This) \ +#define ICorProfilerInfo6_Release(This) \ ( (This)->lpVtbl -> Release(This) ) -#define ICorProfilerInfo5_GetClassFromObject(This,objectId,pClassId) \ +#define ICorProfilerInfo6_GetClassFromObject(This,objectId,pClassId) \ ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) -#define ICorProfilerInfo5_GetClassFromToken(This,moduleId,typeDef,pClassId) \ +#define ICorProfilerInfo6_GetClassFromToken(This,moduleId,typeDef,pClassId) \ ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) -#define ICorProfilerInfo5_GetCodeInfo(This,functionId,pStart,pcSize) \ +#define ICorProfilerInfo6_GetCodeInfo(This,functionId,pStart,pcSize) \ ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) -#define ICorProfilerInfo5_GetEventMask(This,pdwEvents) \ +#define ICorProfilerInfo6_GetEventMask(This,pdwEvents) \ ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) -#define ICorProfilerInfo5_GetFunctionFromIP(This,ip,pFunctionId) \ +#define ICorProfilerInfo6_GetFunctionFromIP(This,ip,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) -#define ICorProfilerInfo5_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ +#define ICorProfilerInfo6_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) -#define ICorProfilerInfo5_GetHandleFromThread(This,threadId,phThread) \ +#define ICorProfilerInfo6_GetHandleFromThread(This,threadId,phThread) \ ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) -#define ICorProfilerInfo5_GetObjectSize(This,objectId,pcSize) \ +#define ICorProfilerInfo6_GetObjectSize(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) -#define ICorProfilerInfo5_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ +#define ICorProfilerInfo6_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) -#define ICorProfilerInfo5_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ +#define ICorProfilerInfo6_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) -#define ICorProfilerInfo5_GetCurrentThreadID(This,pThreadId) \ +#define ICorProfilerInfo6_GetCurrentThreadID(This,pThreadId) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) -#define ICorProfilerInfo5_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ +#define ICorProfilerInfo6_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) -#define ICorProfilerInfo5_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ +#define ICorProfilerInfo6_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) -#define ICorProfilerInfo5_SetEventMask(This,dwEvents) \ +#define ICorProfilerInfo6_SetEventMask(This,dwEvents) \ ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) -#define ICorProfilerInfo5_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ +#define ICorProfilerInfo6_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) -#define ICorProfilerInfo5_SetFunctionIDMapper(This,pFunc) \ +#define ICorProfilerInfo6_SetFunctionIDMapper(This,pFunc) \ ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) -#define ICorProfilerInfo5_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ +#define ICorProfilerInfo6_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) -#define ICorProfilerInfo5_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ +#define ICorProfilerInfo6_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) -#define ICorProfilerInfo5_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ +#define ICorProfilerInfo6_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) -#define ICorProfilerInfo5_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ +#define ICorProfilerInfo6_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) -#define ICorProfilerInfo5_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ +#define ICorProfilerInfo6_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) -#define ICorProfilerInfo5_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ +#define ICorProfilerInfo6_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) -#define ICorProfilerInfo5_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ +#define ICorProfilerInfo6_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) -#define ICorProfilerInfo5_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ +#define ICorProfilerInfo6_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) -#define ICorProfilerInfo5_SetFunctionReJIT(This,functionId) \ +#define ICorProfilerInfo6_SetFunctionReJIT(This,functionId) \ ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) -#define ICorProfilerInfo5_ForceGC(This) \ +#define ICorProfilerInfo6_ForceGC(This) \ ( (This)->lpVtbl -> ForceGC(This) ) -#define ICorProfilerInfo5_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ +#define ICorProfilerInfo6_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) -#define ICorProfilerInfo5_GetInprocInspectionInterface(This,ppicd) \ +#define ICorProfilerInfo6_GetInprocInspectionInterface(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) -#define ICorProfilerInfo5_GetInprocInspectionIThisThread(This,ppicd) \ +#define ICorProfilerInfo6_GetInprocInspectionIThisThread(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) -#define ICorProfilerInfo5_GetThreadContext(This,threadId,pContextId) \ +#define ICorProfilerInfo6_GetThreadContext(This,threadId,pContextId) \ ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) -#define ICorProfilerInfo5_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ +#define ICorProfilerInfo6_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) -#define ICorProfilerInfo5_EndInprocDebugging(This,dwProfilerContext) \ +#define ICorProfilerInfo6_EndInprocDebugging(This,dwProfilerContext) \ ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) -#define ICorProfilerInfo5_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ +#define ICorProfilerInfo6_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) -#define ICorProfilerInfo5_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ +#define ICorProfilerInfo6_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) -#define ICorProfilerInfo5_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ +#define ICorProfilerInfo6_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) -#define ICorProfilerInfo5_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ +#define ICorProfilerInfo6_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) -#define ICorProfilerInfo5_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ +#define ICorProfilerInfo6_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) -#define ICorProfilerInfo5_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ +#define ICorProfilerInfo6_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) -#define ICorProfilerInfo5_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ +#define ICorProfilerInfo6_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) -#define ICorProfilerInfo5_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ +#define ICorProfilerInfo6_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) -#define ICorProfilerInfo5_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ +#define ICorProfilerInfo6_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) -#define ICorProfilerInfo5_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ +#define ICorProfilerInfo6_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) -#define ICorProfilerInfo5_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ +#define ICorProfilerInfo6_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) -#define ICorProfilerInfo5_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ +#define ICorProfilerInfo6_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) -#define ICorProfilerInfo5_GetBoxClassLayout(This,classId,pBufferOffset) \ +#define ICorProfilerInfo6_GetBoxClassLayout(This,classId,pBufferOffset) \ ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) -#define ICorProfilerInfo5_GetThreadAppDomain(This,threadId,pAppDomainId) \ +#define ICorProfilerInfo6_GetThreadAppDomain(This,threadId,pAppDomainId) \ ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) -#define ICorProfilerInfo5_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ +#define ICorProfilerInfo6_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) -#define ICorProfilerInfo5_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ +#define ICorProfilerInfo6_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) -#define ICorProfilerInfo5_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ +#define ICorProfilerInfo6_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) -#define ICorProfilerInfo5_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ +#define ICorProfilerInfo6_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) -#define ICorProfilerInfo5_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ +#define ICorProfilerInfo6_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) -#define ICorProfilerInfo5_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ +#define ICorProfilerInfo6_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) -#define ICorProfilerInfo5_GetObjectGeneration(This,objectId,range) \ +#define ICorProfilerInfo6_GetObjectGeneration(This,objectId,range) \ ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) -#define ICorProfilerInfo5_GetNotifiedExceptionClauseInfo(This,pinfo) \ +#define ICorProfilerInfo6_GetNotifiedExceptionClauseInfo(This,pinfo) \ ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) -#define ICorProfilerInfo5_EnumJITedFunctions(This,ppEnum) \ +#define ICorProfilerInfo6_EnumJITedFunctions(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) -#define ICorProfilerInfo5_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ +#define ICorProfilerInfo6_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) -#define ICorProfilerInfo5_SetFunctionIDMapper2(This,pFunc,clientData) \ +#define ICorProfilerInfo6_SetFunctionIDMapper2(This,pFunc,clientData) \ ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) -#define ICorProfilerInfo5_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ +#define ICorProfilerInfo6_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) -#define ICorProfilerInfo5_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ +#define ICorProfilerInfo6_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) -#define ICorProfilerInfo5_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ +#define ICorProfilerInfo6_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) -#define ICorProfilerInfo5_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ +#define ICorProfilerInfo6_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) -#define ICorProfilerInfo5_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ +#define ICorProfilerInfo6_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) -#define ICorProfilerInfo5_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ +#define ICorProfilerInfo6_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) -#define ICorProfilerInfo5_EnumModules(This,ppEnum) \ +#define ICorProfilerInfo6_EnumModules(This,ppEnum) \ ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) -#define ICorProfilerInfo5_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ +#define ICorProfilerInfo6_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) -#define ICorProfilerInfo5_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ +#define ICorProfilerInfo6_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) -#define ICorProfilerInfo5_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ +#define ICorProfilerInfo6_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) -#define ICorProfilerInfo5_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ +#define ICorProfilerInfo6_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) -#define ICorProfilerInfo5_EnumThreads(This,ppEnum) \ +#define ICorProfilerInfo6_EnumThreads(This,ppEnum) \ ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) -#define ICorProfilerInfo5_InitializeCurrentThread(This) \ +#define ICorProfilerInfo6_InitializeCurrentThread(This) \ ( (This)->lpVtbl -> InitializeCurrentThread(This) ) -#define ICorProfilerInfo5_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ +#define ICorProfilerInfo6_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) -#define ICorProfilerInfo5_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ +#define ICorProfilerInfo6_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) -#define ICorProfilerInfo5_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ +#define ICorProfilerInfo6_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) -#define ICorProfilerInfo5_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ +#define ICorProfilerInfo6_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) -#define ICorProfilerInfo5_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ +#define ICorProfilerInfo6_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) -#define ICorProfilerInfo5_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ +#define ICorProfilerInfo6_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) -#define ICorProfilerInfo5_EnumJITedFunctions2(This,ppEnum) \ +#define ICorProfilerInfo6_EnumJITedFunctions2(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) -#define ICorProfilerInfo5_GetObjectSize2(This,objectId,pcSize) \ +#define ICorProfilerInfo6_GetObjectSize2(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) -#define ICorProfilerInfo5_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ +#define ICorProfilerInfo6_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) -#define ICorProfilerInfo5_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ +#define ICorProfilerInfo6_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) + +#define ICorProfilerInfo6_EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) \ + ( (This)->lpVtbl -> EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) ) + #endif /* COBJMACROS */ @@ -10017,146 +11650,153 @@ EXTERN_C const IID IID_ICorProfilerInfo5; -#endif /* __ICorProfilerInfo5_INTERFACE_DEFINED__ */ +#endif /* __ICorProfilerInfo6_INTERFACE_DEFINED__ */ -#ifndef __ICorProfilerInfo6_INTERFACE_DEFINED__ -#define __ICorProfilerInfo6_INTERFACE_DEFINED__ +#ifndef __ICorProfilerInfo7_INTERFACE_DEFINED__ +#define __ICorProfilerInfo7_INTERFACE_DEFINED__ -/* interface ICorProfilerInfo6 */ +/* interface ICorProfilerInfo7 */ /* [local][unique][uuid][object] */ -EXTERN_C const IID IID_ICorProfilerInfo6; +EXTERN_C const IID IID_ICorProfilerInfo7; #if defined(__cplusplus) && !defined(CINTERFACE) - MIDL_INTERFACE("F30A070D-BFFB-46A7-B1D8-8781EF7B698A") - ICorProfilerInfo6 : public ICorProfilerInfo5 + MIDL_INTERFACE("9AEECC0D-63E0-4187-8C00-E312F503F663") + ICorProfilerInfo7 : public ICorProfilerInfo6 { public: - virtual HRESULT STDMETHODCALLTYPE EnumNgenModuleMethodsInliningThisMethod( - /* [in] */ ModuleID inlinersModuleId, - /* [in] */ ModuleID inlineeModuleId, - /* [in] */ mdMethodDef inlineeMethodId, - /* [out] */ BOOL *incompleteData, - /* [out] */ ICorProfilerMethodEnum **ppEnum) = 0; + virtual HRESULT STDMETHODCALLTYPE ApplyMetaData( + /* [in] */ ModuleID moduleId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetInMemorySymbolsLength( + /* [in] */ ModuleID moduleId, + /* [out] */ DWORD *pCountSymbolBytes) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReadInMemorySymbols( + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD symbolsReadOffset, + /* [out] */ BYTE *pSymbolBytes, + /* [in] */ DWORD countSymbolBytes, + /* [out] */ DWORD *pCountSymbolBytesRead) = 0; }; #else /* C style interface */ - typedef struct ICorProfilerInfo6Vtbl + typedef struct ICorProfilerInfo7Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( - ICorProfilerInfo6 * This); + ICorProfilerInfo7 * This); ULONG ( STDMETHODCALLTYPE *Release )( - ICorProfilerInfo6 * This); + ICorProfilerInfo7 * This); HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [out] */ DWORD *pdwEvents); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread); HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank); HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId); HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [out] */ ThreadID *pThreadId); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *SetEventMask )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ DWORD dwEvents); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ FunctionIDMapper *pFunc); HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, @@ -10166,32 +11806,32 @@ EXTERN_C const IID IID_ICorProfilerInfo6; /* [out] */ AssemblyID *pAssemblyId); HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc); HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader); HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, @@ -10200,7 +11840,7 @@ EXTERN_C const IID IID_ICorProfilerInfo6; /* [out] */ ProcessID *pProcessId); HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, @@ -10210,50 +11850,50 @@ EXTERN_C const IID IID_ICorProfilerInfo6; /* [out] */ ModuleID *pModuleId); HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ForceGC )( - ICorProfilerInfo6 * This); + ICorProfilerInfo7 * This); HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId); HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext); HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ DWORD dwProfilerContext); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ThreadID thread, /* [in] */ StackSnapshotCallback *callback, /* [in] */ ULONG32 infoFlags, @@ -10262,13 +11902,13 @@ EXTERN_C const IID IID_ICorProfilerInfo6; /* [in] */ ULONG32 contextSize); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ FunctionEnter2 *pFuncEnter, /* [in] */ FunctionLeave2 *pFuncLeave, /* [in] */ FunctionTailcall2 *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ FunctionID funcId, /* [in] */ COR_PRF_FRAME_INFO frameInfo, /* [out] */ ClassID *pClassId, @@ -10279,13 +11919,13 @@ EXTERN_C const IID IID_ICorProfilerInfo6; /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ClassID classID, /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], /* [in] */ ULONG cFieldOffset, @@ -10293,7 +11933,7 @@ EXTERN_C const IID IID_ICorProfilerInfo6; /* [out] */ ULONG *pulClassSize); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken, @@ -10303,14 +11943,14 @@ EXTERN_C const IID IID_ICorProfilerInfo6; /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ FunctionID functionID, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdTypeDef typeDef, /* [in] */ ULONG32 cTypeArgs, @@ -10318,7 +11958,7 @@ EXTERN_C const IID IID_ICorProfilerInfo6; /* [out] */ ClassID *pClassID); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdMethodDef funcDef, /* [in] */ ClassID classId, @@ -10327,12 +11967,12 @@ EXTERN_C const IID IID_ICorProfilerInfo6; /* [out] */ FunctionID *pFunctionID); HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleID, /* [out] */ ICorProfilerObjectEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ObjectID objectId, /* [in] */ ULONG32 cDimensions, /* [size_is][out] */ ULONG32 pDimensionSizes[ ], @@ -10340,95 +11980,95 @@ EXTERN_C const IID IID_ICorProfilerInfo6; /* [out] */ BYTE **ppData); HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ClassID classId, /* [out] */ ULONG32 *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ThreadID threadId, /* [out] */ AppDomainID *pAppDomainId); HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ContextID contextId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ULONG cObjectRanges, /* [out] */ ULONG *pcObjectRanges, /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ObjectID objectId, /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ DWORD dwExpectedCompletionMilliseconds); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ FunctionIDMapper2 *pFunc, /* [in] */ void *clientData); HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ FunctionEnter3 *pFuncEnter3, /* [in] */ FunctionLeave3 *pFuncLeave3, /* [in] */ FunctionTailcall3 *pFuncTailcall3); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, @@ -10436,24 +12076,24 @@ EXTERN_C const IID IID_ICorProfilerInfo6; /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); HRESULT ( STDMETHODCALLTYPE *EnumModules )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [out] */ ICorProfilerModuleEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [out] */ USHORT *pClrInstanceId, /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, /* [out] */ USHORT *pMajorVersion, @@ -10466,7 +12106,7 @@ EXTERN_C const IID IID_ICorProfilerInfo6; _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, @@ -10474,14 +12114,14 @@ EXTERN_C const IID IID_ICorProfilerInfo6; /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId, /* [in] */ ULONG32 cAppDomainIds, /* [out] */ ULONG32 *pcAppDomainIds, /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, @@ -10492,27 +12132,27 @@ EXTERN_C const IID IID_ICorProfilerInfo6; /* [out] */ DWORD *pdwModuleFlags); HRESULT ( STDMETHODCALLTYPE *EnumThreads )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [out] */ ICorProfilerThreadEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( - ICorProfilerInfo6 * This); + ICorProfilerInfo7 * This); HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]); HRESULT ( STDMETHODCALLTYPE *RequestRevert )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ], /* [size_is][out] */ HRESULT status[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ FunctionID functionID, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cCodeInfos, @@ -10520,20 +12160,20 @@ EXTERN_C const IID IID_ICorProfilerInfo6; /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId, /* [out] */ ReJITID *pReJitId); HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG cReJitIds, /* [out] */ ULONG *pcReJitIds, /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cMap, @@ -10541,38 +12181,55 @@ EXTERN_C const IID IID_ICorProfilerInfo6; /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ObjectID objectId, /* [out] */ SIZE_T *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [out] */ DWORD *pdwEventsLow, /* [out] */ DWORD *pdwEventsHigh); HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ DWORD dwEventsLow, /* [in] */ DWORD dwEventsHigh); HRESULT ( STDMETHODCALLTYPE *EnumNgenModuleMethodsInliningThisMethod )( - ICorProfilerInfo6 * This, + ICorProfilerInfo7 * This, /* [in] */ ModuleID inlinersModuleId, /* [in] */ ModuleID inlineeModuleId, /* [in] */ mdMethodDef inlineeMethodId, /* [out] */ BOOL *incompleteData, /* [out] */ ICorProfilerMethodEnum **ppEnum); + HRESULT ( STDMETHODCALLTYPE *ApplyMetaData )( + ICorProfilerInfo7 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *GetInMemorySymbolsLength )( + ICorProfilerInfo7 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ DWORD *pCountSymbolBytes); + + HRESULT ( STDMETHODCALLTYPE *ReadInMemorySymbols )( + ICorProfilerInfo7 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD symbolsReadOffset, + /* [out] */ BYTE *pSymbolBytes, + /* [in] */ DWORD countSymbolBytes, + /* [out] */ DWORD *pCountSymbolBytesRead); + END_INTERFACE - } ICorProfilerInfo6Vtbl; + } ICorProfilerInfo7Vtbl; - interface ICorProfilerInfo6 + interface ICorProfilerInfo7 { - CONST_VTBL struct ICorProfilerInfo6Vtbl *lpVtbl; + CONST_VTBL struct ICorProfilerInfo7Vtbl *lpVtbl; }; @@ -10580,264 +12237,274 @@ EXTERN_C const IID IID_ICorProfilerInfo6; #ifdef COBJMACROS -#define ICorProfilerInfo6_QueryInterface(This,riid,ppvObject) \ +#define ICorProfilerInfo7_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ICorProfilerInfo6_AddRef(This) \ +#define ICorProfilerInfo7_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) -#define ICorProfilerInfo6_Release(This) \ +#define ICorProfilerInfo7_Release(This) \ ( (This)->lpVtbl -> Release(This) ) -#define ICorProfilerInfo6_GetClassFromObject(This,objectId,pClassId) \ +#define ICorProfilerInfo7_GetClassFromObject(This,objectId,pClassId) \ ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) -#define ICorProfilerInfo6_GetClassFromToken(This,moduleId,typeDef,pClassId) \ +#define ICorProfilerInfo7_GetClassFromToken(This,moduleId,typeDef,pClassId) \ ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) -#define ICorProfilerInfo6_GetCodeInfo(This,functionId,pStart,pcSize) \ +#define ICorProfilerInfo7_GetCodeInfo(This,functionId,pStart,pcSize) \ ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) -#define ICorProfilerInfo6_GetEventMask(This,pdwEvents) \ +#define ICorProfilerInfo7_GetEventMask(This,pdwEvents) \ ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) -#define ICorProfilerInfo6_GetFunctionFromIP(This,ip,pFunctionId) \ +#define ICorProfilerInfo7_GetFunctionFromIP(This,ip,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) -#define ICorProfilerInfo6_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ +#define ICorProfilerInfo7_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) -#define ICorProfilerInfo6_GetHandleFromThread(This,threadId,phThread) \ +#define ICorProfilerInfo7_GetHandleFromThread(This,threadId,phThread) \ ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) -#define ICorProfilerInfo6_GetObjectSize(This,objectId,pcSize) \ +#define ICorProfilerInfo7_GetObjectSize(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) -#define ICorProfilerInfo6_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ +#define ICorProfilerInfo7_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) -#define ICorProfilerInfo6_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ +#define ICorProfilerInfo7_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) -#define ICorProfilerInfo6_GetCurrentThreadID(This,pThreadId) \ +#define ICorProfilerInfo7_GetCurrentThreadID(This,pThreadId) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) -#define ICorProfilerInfo6_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ +#define ICorProfilerInfo7_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) -#define ICorProfilerInfo6_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ +#define ICorProfilerInfo7_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) -#define ICorProfilerInfo6_SetEventMask(This,dwEvents) \ +#define ICorProfilerInfo7_SetEventMask(This,dwEvents) \ ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) -#define ICorProfilerInfo6_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ +#define ICorProfilerInfo7_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) -#define ICorProfilerInfo6_SetFunctionIDMapper(This,pFunc) \ +#define ICorProfilerInfo7_SetFunctionIDMapper(This,pFunc) \ ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) -#define ICorProfilerInfo6_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ +#define ICorProfilerInfo7_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) -#define ICorProfilerInfo6_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ +#define ICorProfilerInfo7_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) -#define ICorProfilerInfo6_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ +#define ICorProfilerInfo7_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) -#define ICorProfilerInfo6_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ +#define ICorProfilerInfo7_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) -#define ICorProfilerInfo6_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ +#define ICorProfilerInfo7_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) -#define ICorProfilerInfo6_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ +#define ICorProfilerInfo7_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) -#define ICorProfilerInfo6_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ +#define ICorProfilerInfo7_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) -#define ICorProfilerInfo6_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ +#define ICorProfilerInfo7_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) -#define ICorProfilerInfo6_SetFunctionReJIT(This,functionId) \ +#define ICorProfilerInfo7_SetFunctionReJIT(This,functionId) \ ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) -#define ICorProfilerInfo6_ForceGC(This) \ +#define ICorProfilerInfo7_ForceGC(This) \ ( (This)->lpVtbl -> ForceGC(This) ) -#define ICorProfilerInfo6_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ +#define ICorProfilerInfo7_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) -#define ICorProfilerInfo6_GetInprocInspectionInterface(This,ppicd) \ +#define ICorProfilerInfo7_GetInprocInspectionInterface(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) -#define ICorProfilerInfo6_GetInprocInspectionIThisThread(This,ppicd) \ +#define ICorProfilerInfo7_GetInprocInspectionIThisThread(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) -#define ICorProfilerInfo6_GetThreadContext(This,threadId,pContextId) \ +#define ICorProfilerInfo7_GetThreadContext(This,threadId,pContextId) \ ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) -#define ICorProfilerInfo6_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ +#define ICorProfilerInfo7_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) -#define ICorProfilerInfo6_EndInprocDebugging(This,dwProfilerContext) \ +#define ICorProfilerInfo7_EndInprocDebugging(This,dwProfilerContext) \ ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) -#define ICorProfilerInfo6_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ +#define ICorProfilerInfo7_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) -#define ICorProfilerInfo6_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ +#define ICorProfilerInfo7_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) -#define ICorProfilerInfo6_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ +#define ICorProfilerInfo7_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) -#define ICorProfilerInfo6_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ +#define ICorProfilerInfo7_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) -#define ICorProfilerInfo6_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ +#define ICorProfilerInfo7_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) -#define ICorProfilerInfo6_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ +#define ICorProfilerInfo7_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) -#define ICorProfilerInfo6_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ +#define ICorProfilerInfo7_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) -#define ICorProfilerInfo6_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ +#define ICorProfilerInfo7_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) -#define ICorProfilerInfo6_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ +#define ICorProfilerInfo7_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) -#define ICorProfilerInfo6_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ +#define ICorProfilerInfo7_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) -#define ICorProfilerInfo6_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ +#define ICorProfilerInfo7_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) -#define ICorProfilerInfo6_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ +#define ICorProfilerInfo7_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) -#define ICorProfilerInfo6_GetBoxClassLayout(This,classId,pBufferOffset) \ +#define ICorProfilerInfo7_GetBoxClassLayout(This,classId,pBufferOffset) \ ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) -#define ICorProfilerInfo6_GetThreadAppDomain(This,threadId,pAppDomainId) \ +#define ICorProfilerInfo7_GetThreadAppDomain(This,threadId,pAppDomainId) \ ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) -#define ICorProfilerInfo6_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ +#define ICorProfilerInfo7_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) -#define ICorProfilerInfo6_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ +#define ICorProfilerInfo7_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) -#define ICorProfilerInfo6_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ +#define ICorProfilerInfo7_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) -#define ICorProfilerInfo6_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ +#define ICorProfilerInfo7_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) -#define ICorProfilerInfo6_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ +#define ICorProfilerInfo7_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) -#define ICorProfilerInfo6_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ +#define ICorProfilerInfo7_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) -#define ICorProfilerInfo6_GetObjectGeneration(This,objectId,range) \ +#define ICorProfilerInfo7_GetObjectGeneration(This,objectId,range) \ ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) -#define ICorProfilerInfo6_GetNotifiedExceptionClauseInfo(This,pinfo) \ +#define ICorProfilerInfo7_GetNotifiedExceptionClauseInfo(This,pinfo) \ ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) -#define ICorProfilerInfo6_EnumJITedFunctions(This,ppEnum) \ +#define ICorProfilerInfo7_EnumJITedFunctions(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) -#define ICorProfilerInfo6_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ +#define ICorProfilerInfo7_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) -#define ICorProfilerInfo6_SetFunctionIDMapper2(This,pFunc,clientData) \ +#define ICorProfilerInfo7_SetFunctionIDMapper2(This,pFunc,clientData) \ ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) -#define ICorProfilerInfo6_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ +#define ICorProfilerInfo7_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) -#define ICorProfilerInfo6_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ +#define ICorProfilerInfo7_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) -#define ICorProfilerInfo6_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ +#define ICorProfilerInfo7_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) -#define ICorProfilerInfo6_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ +#define ICorProfilerInfo7_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) -#define ICorProfilerInfo6_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ +#define ICorProfilerInfo7_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) -#define ICorProfilerInfo6_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ +#define ICorProfilerInfo7_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) -#define ICorProfilerInfo6_EnumModules(This,ppEnum) \ +#define ICorProfilerInfo7_EnumModules(This,ppEnum) \ ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) -#define ICorProfilerInfo6_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ +#define ICorProfilerInfo7_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) -#define ICorProfilerInfo6_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ +#define ICorProfilerInfo7_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) -#define ICorProfilerInfo6_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ +#define ICorProfilerInfo7_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) -#define ICorProfilerInfo6_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ +#define ICorProfilerInfo7_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) -#define ICorProfilerInfo6_EnumThreads(This,ppEnum) \ +#define ICorProfilerInfo7_EnumThreads(This,ppEnum) \ ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) -#define ICorProfilerInfo6_InitializeCurrentThread(This) \ +#define ICorProfilerInfo7_InitializeCurrentThread(This) \ ( (This)->lpVtbl -> InitializeCurrentThread(This) ) -#define ICorProfilerInfo6_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ +#define ICorProfilerInfo7_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) -#define ICorProfilerInfo6_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ +#define ICorProfilerInfo7_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) -#define ICorProfilerInfo6_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ +#define ICorProfilerInfo7_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) -#define ICorProfilerInfo6_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ +#define ICorProfilerInfo7_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) -#define ICorProfilerInfo6_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ +#define ICorProfilerInfo7_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) -#define ICorProfilerInfo6_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ +#define ICorProfilerInfo7_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) -#define ICorProfilerInfo6_EnumJITedFunctions2(This,ppEnum) \ +#define ICorProfilerInfo7_EnumJITedFunctions2(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) -#define ICorProfilerInfo6_GetObjectSize2(This,objectId,pcSize) \ +#define ICorProfilerInfo7_GetObjectSize2(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) -#define ICorProfilerInfo6_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ +#define ICorProfilerInfo7_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) -#define ICorProfilerInfo6_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ +#define ICorProfilerInfo7_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) -#define ICorProfilerInfo6_EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) \ +#define ICorProfilerInfo7_EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) \ ( (This)->lpVtbl -> EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) ) + +#define ICorProfilerInfo7_ApplyMetaData(This,moduleId) \ + ( (This)->lpVtbl -> ApplyMetaData(This,moduleId) ) + +#define ICorProfilerInfo7_GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) \ + ( (This)->lpVtbl -> GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) ) + +#define ICorProfilerInfo7_ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) \ + ( (This)->lpVtbl -> ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) ) + #endif /* COBJMACROS */ @@ -10846,153 +12513,157 @@ EXTERN_C const IID IID_ICorProfilerInfo6; -#endif /* __ICorProfilerInfo6_INTERFACE_DEFINED__ */ +#endif /* __ICorProfilerInfo7_INTERFACE_DEFINED__ */ -#ifndef __ICorProfilerInfo7_INTERFACE_DEFINED__ -#define __ICorProfilerInfo7_INTERFACE_DEFINED__ +#ifndef __ICorProfilerInfo8_INTERFACE_DEFINED__ +#define __ICorProfilerInfo8_INTERFACE_DEFINED__ -/* interface ICorProfilerInfo7 */ +/* interface ICorProfilerInfo8 */ /* [local][unique][uuid][object] */ -EXTERN_C const IID IID_ICorProfilerInfo7; +EXTERN_C const IID IID_ICorProfilerInfo8; #if defined(__cplusplus) && !defined(CINTERFACE) - MIDL_INTERFACE("9AEECC0D-63E0-4187-8C00-E312F503F663") - ICorProfilerInfo7 : public ICorProfilerInfo6 + MIDL_INTERFACE("C5AC80A6-782E-4716-8044-39598C60CFBF") + ICorProfilerInfo8 : public ICorProfilerInfo7 { public: - virtual HRESULT STDMETHODCALLTYPE ApplyMetaData( - /* [in] */ ModuleID moduleId) = 0; + virtual HRESULT STDMETHODCALLTYPE IsFunctionDynamic( + /* [in] */ FunctionID functionId, + /* [out] */ BOOL *isDynamic) = 0; - virtual HRESULT STDMETHODCALLTYPE GetInMemorySymbolsLength( - /* [in] */ ModuleID moduleId, - /* [out] */ DWORD *pCountSymbolBytes) = 0; + virtual HRESULT STDMETHODCALLTYPE GetFunctionFromIP3( + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *functionId, + /* [out] */ ReJITID *pReJitId) = 0; - virtual HRESULT STDMETHODCALLTYPE ReadInMemorySymbols( - /* [in] */ ModuleID moduleId, - /* [in] */ DWORD symbolsReadOffset, - /* [out] */ BYTE *pSymbolBytes, - /* [in] */ DWORD countSymbolBytes, - /* [out] */ DWORD *pCountSymbolBytesRead) = 0; + virtual HRESULT STDMETHODCALLTYPE GetDynamicFunctionInfo( + /* [in] */ FunctionID functionId, + /* [out] */ ModuleID *moduleId, + /* [out] */ PCCOR_SIGNATURE *ppvSig, + /* [out] */ ULONG *pbSig, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [out] */ WCHAR wszName[ ]) = 0; }; #else /* C style interface */ - typedef struct ICorProfilerInfo7Vtbl + typedef struct ICorProfilerInfo8Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( - ICorProfilerInfo7 * This); + ICorProfilerInfo8 * This); ULONG ( STDMETHODCALLTYPE *Release )( - ICorProfilerInfo7 * This); + ICorProfilerInfo8 * This); HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [out] */ DWORD *pdwEvents); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread); HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank); HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId); HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [out] */ ThreadID *pThreadId); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *SetEventMask )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ DWORD dwEvents); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ FunctionIDMapper *pFunc); HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, @@ -11002,32 +12673,32 @@ EXTERN_C const IID IID_ICorProfilerInfo7; /* [out] */ AssemblyID *pAssemblyId); HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc); HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader); HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, @@ -11036,7 +12707,7 @@ EXTERN_C const IID IID_ICorProfilerInfo7; /* [out] */ ProcessID *pProcessId); HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, @@ -11046,50 +12717,50 @@ EXTERN_C const IID IID_ICorProfilerInfo7; /* [out] */ ModuleID *pModuleId); HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ForceGC )( - ICorProfilerInfo7 * This); + ICorProfilerInfo8 * This); HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId); HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext); HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ DWORD dwProfilerContext); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ThreadID thread, /* [in] */ StackSnapshotCallback *callback, /* [in] */ ULONG32 infoFlags, @@ -11098,13 +12769,13 @@ EXTERN_C const IID IID_ICorProfilerInfo7; /* [in] */ ULONG32 contextSize); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ FunctionEnter2 *pFuncEnter, /* [in] */ FunctionLeave2 *pFuncLeave, /* [in] */ FunctionTailcall2 *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ FunctionID funcId, /* [in] */ COR_PRF_FRAME_INFO frameInfo, /* [out] */ ClassID *pClassId, @@ -11115,13 +12786,13 @@ EXTERN_C const IID IID_ICorProfilerInfo7; /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ClassID classID, /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], /* [in] */ ULONG cFieldOffset, @@ -11129,7 +12800,7 @@ EXTERN_C const IID IID_ICorProfilerInfo7; /* [out] */ ULONG *pulClassSize); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken, @@ -11139,14 +12810,14 @@ EXTERN_C const IID IID_ICorProfilerInfo7; /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ FunctionID functionID, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdTypeDef typeDef, /* [in] */ ULONG32 cTypeArgs, @@ -11154,7 +12825,7 @@ EXTERN_C const IID IID_ICorProfilerInfo7; /* [out] */ ClassID *pClassID); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdMethodDef funcDef, /* [in] */ ClassID classId, @@ -11163,12 +12834,12 @@ EXTERN_C const IID IID_ICorProfilerInfo7; /* [out] */ FunctionID *pFunctionID); HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleID, /* [out] */ ICorProfilerObjectEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ObjectID objectId, /* [in] */ ULONG32 cDimensions, /* [size_is][out] */ ULONG32 pDimensionSizes[ ], @@ -11176,95 +12847,95 @@ EXTERN_C const IID IID_ICorProfilerInfo7; /* [out] */ BYTE **ppData); HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ClassID classId, /* [out] */ ULONG32 *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ThreadID threadId, /* [out] */ AppDomainID *pAppDomainId); HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ContextID contextId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ULONG cObjectRanges, /* [out] */ ULONG *pcObjectRanges, /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ObjectID objectId, /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ DWORD dwExpectedCompletionMilliseconds); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ FunctionIDMapper2 *pFunc, /* [in] */ void *clientData); HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ FunctionEnter3 *pFuncEnter3, /* [in] */ FunctionLeave3 *pFuncLeave3, /* [in] */ FunctionTailcall3 *pFuncTailcall3); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, @@ -11272,24 +12943,24 @@ EXTERN_C const IID IID_ICorProfilerInfo7; /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); HRESULT ( STDMETHODCALLTYPE *EnumModules )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [out] */ ICorProfilerModuleEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [out] */ USHORT *pClrInstanceId, /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, /* [out] */ USHORT *pMajorVersion, @@ -11302,7 +12973,7 @@ EXTERN_C const IID IID_ICorProfilerInfo7; _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, @@ -11310,14 +12981,14 @@ EXTERN_C const IID IID_ICorProfilerInfo7; /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [in] */ ULONG32 cAppDomainIds, /* [out] */ ULONG32 *pcAppDomainIds, /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, @@ -11328,27 +12999,27 @@ EXTERN_C const IID IID_ICorProfilerInfo7; /* [out] */ DWORD *pdwModuleFlags); HRESULT ( STDMETHODCALLTYPE *EnumThreads )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [out] */ ICorProfilerThreadEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( - ICorProfilerInfo7 * This); + ICorProfilerInfo8 * This); HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]); HRESULT ( STDMETHODCALLTYPE *RequestRevert )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ], /* [size_is][out] */ HRESULT status[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ FunctionID functionID, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cCodeInfos, @@ -11356,20 +13027,20 @@ EXTERN_C const IID IID_ICorProfilerInfo7; /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId, /* [out] */ ReJITID *pReJitId); HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG cReJitIds, /* [out] */ ULONG *pcReJitIds, /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cMap, @@ -11377,26 +13048,26 @@ EXTERN_C const IID IID_ICorProfilerInfo7; /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ObjectID objectId, /* [out] */ SIZE_T *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [out] */ DWORD *pdwEventsLow, /* [out] */ DWORD *pdwEventsHigh); HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ DWORD dwEventsLow, /* [in] */ DWORD dwEventsHigh); HRESULT ( STDMETHODCALLTYPE *EnumNgenModuleMethodsInliningThisMethod )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ModuleID inlinersModuleId, /* [in] */ ModuleID inlineeModuleId, /* [in] */ mdMethodDef inlineeMethodId, @@ -11404,28 +13075,49 @@ EXTERN_C const IID IID_ICorProfilerInfo7; /* [out] */ ICorProfilerMethodEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *ApplyMetaData )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *GetInMemorySymbolsLength )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [out] */ DWORD *pCountSymbolBytes); HRESULT ( STDMETHODCALLTYPE *ReadInMemorySymbols )( - ICorProfilerInfo7 * This, + ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD symbolsReadOffset, /* [out] */ BYTE *pSymbolBytes, /* [in] */ DWORD countSymbolBytes, /* [out] */ DWORD *pCountSymbolBytesRead); + HRESULT ( STDMETHODCALLTYPE *IsFunctionDynamic )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionID functionId, + /* [out] */ BOOL *isDynamic); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP3 )( + ICorProfilerInfo8 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *functionId, + /* [out] */ ReJITID *pReJitId); + + HRESULT ( STDMETHODCALLTYPE *GetDynamicFunctionInfo )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionID functionId, + /* [out] */ ModuleID *moduleId, + /* [out] */ PCCOR_SIGNATURE *ppvSig, + /* [out] */ ULONG *pbSig, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [out] */ WCHAR wszName[ ]); + END_INTERFACE - } ICorProfilerInfo7Vtbl; + } ICorProfilerInfo8Vtbl; - interface ICorProfilerInfo7 + interface ICorProfilerInfo8 { - CONST_VTBL struct ICorProfilerInfo7Vtbl *lpVtbl; + CONST_VTBL struct ICorProfilerInfo8Vtbl *lpVtbl; }; @@ -11433,274 +13125,284 @@ EXTERN_C const IID IID_ICorProfilerInfo7; #ifdef COBJMACROS -#define ICorProfilerInfo7_QueryInterface(This,riid,ppvObject) \ +#define ICorProfilerInfo8_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ICorProfilerInfo7_AddRef(This) \ +#define ICorProfilerInfo8_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) -#define ICorProfilerInfo7_Release(This) \ +#define ICorProfilerInfo8_Release(This) \ ( (This)->lpVtbl -> Release(This) ) -#define ICorProfilerInfo7_GetClassFromObject(This,objectId,pClassId) \ +#define ICorProfilerInfo8_GetClassFromObject(This,objectId,pClassId) \ ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) -#define ICorProfilerInfo7_GetClassFromToken(This,moduleId,typeDef,pClassId) \ +#define ICorProfilerInfo8_GetClassFromToken(This,moduleId,typeDef,pClassId) \ ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) -#define ICorProfilerInfo7_GetCodeInfo(This,functionId,pStart,pcSize) \ +#define ICorProfilerInfo8_GetCodeInfo(This,functionId,pStart,pcSize) \ ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) -#define ICorProfilerInfo7_GetEventMask(This,pdwEvents) \ +#define ICorProfilerInfo8_GetEventMask(This,pdwEvents) \ ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) -#define ICorProfilerInfo7_GetFunctionFromIP(This,ip,pFunctionId) \ +#define ICorProfilerInfo8_GetFunctionFromIP(This,ip,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) -#define ICorProfilerInfo7_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ +#define ICorProfilerInfo8_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) -#define ICorProfilerInfo7_GetHandleFromThread(This,threadId,phThread) \ +#define ICorProfilerInfo8_GetHandleFromThread(This,threadId,phThread) \ ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) -#define ICorProfilerInfo7_GetObjectSize(This,objectId,pcSize) \ +#define ICorProfilerInfo8_GetObjectSize(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) -#define ICorProfilerInfo7_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ +#define ICorProfilerInfo8_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) -#define ICorProfilerInfo7_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ +#define ICorProfilerInfo8_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) -#define ICorProfilerInfo7_GetCurrentThreadID(This,pThreadId) \ +#define ICorProfilerInfo8_GetCurrentThreadID(This,pThreadId) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) -#define ICorProfilerInfo7_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ +#define ICorProfilerInfo8_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) -#define ICorProfilerInfo7_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ +#define ICorProfilerInfo8_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) -#define ICorProfilerInfo7_SetEventMask(This,dwEvents) \ +#define ICorProfilerInfo8_SetEventMask(This,dwEvents) \ ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) -#define ICorProfilerInfo7_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ +#define ICorProfilerInfo8_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) -#define ICorProfilerInfo7_SetFunctionIDMapper(This,pFunc) \ +#define ICorProfilerInfo8_SetFunctionIDMapper(This,pFunc) \ ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) -#define ICorProfilerInfo7_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ +#define ICorProfilerInfo8_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) -#define ICorProfilerInfo7_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ +#define ICorProfilerInfo8_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) -#define ICorProfilerInfo7_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ +#define ICorProfilerInfo8_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) -#define ICorProfilerInfo7_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ +#define ICorProfilerInfo8_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) -#define ICorProfilerInfo7_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ +#define ICorProfilerInfo8_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) -#define ICorProfilerInfo7_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ +#define ICorProfilerInfo8_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) -#define ICorProfilerInfo7_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ +#define ICorProfilerInfo8_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) -#define ICorProfilerInfo7_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ +#define ICorProfilerInfo8_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) -#define ICorProfilerInfo7_SetFunctionReJIT(This,functionId) \ +#define ICorProfilerInfo8_SetFunctionReJIT(This,functionId) \ ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) -#define ICorProfilerInfo7_ForceGC(This) \ +#define ICorProfilerInfo8_ForceGC(This) \ ( (This)->lpVtbl -> ForceGC(This) ) -#define ICorProfilerInfo7_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ +#define ICorProfilerInfo8_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) -#define ICorProfilerInfo7_GetInprocInspectionInterface(This,ppicd) \ +#define ICorProfilerInfo8_GetInprocInspectionInterface(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) -#define ICorProfilerInfo7_GetInprocInspectionIThisThread(This,ppicd) \ +#define ICorProfilerInfo8_GetInprocInspectionIThisThread(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) -#define ICorProfilerInfo7_GetThreadContext(This,threadId,pContextId) \ +#define ICorProfilerInfo8_GetThreadContext(This,threadId,pContextId) \ ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) -#define ICorProfilerInfo7_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ +#define ICorProfilerInfo8_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) -#define ICorProfilerInfo7_EndInprocDebugging(This,dwProfilerContext) \ +#define ICorProfilerInfo8_EndInprocDebugging(This,dwProfilerContext) \ ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) -#define ICorProfilerInfo7_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ +#define ICorProfilerInfo8_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) -#define ICorProfilerInfo7_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ +#define ICorProfilerInfo8_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) -#define ICorProfilerInfo7_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ +#define ICorProfilerInfo8_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) -#define ICorProfilerInfo7_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ +#define ICorProfilerInfo8_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) -#define ICorProfilerInfo7_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ +#define ICorProfilerInfo8_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) -#define ICorProfilerInfo7_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ +#define ICorProfilerInfo8_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) -#define ICorProfilerInfo7_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ +#define ICorProfilerInfo8_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) -#define ICorProfilerInfo7_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ +#define ICorProfilerInfo8_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) -#define ICorProfilerInfo7_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ +#define ICorProfilerInfo8_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) -#define ICorProfilerInfo7_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ +#define ICorProfilerInfo8_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) -#define ICorProfilerInfo7_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ +#define ICorProfilerInfo8_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) -#define ICorProfilerInfo7_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ +#define ICorProfilerInfo8_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) -#define ICorProfilerInfo7_GetBoxClassLayout(This,classId,pBufferOffset) \ +#define ICorProfilerInfo8_GetBoxClassLayout(This,classId,pBufferOffset) \ ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) -#define ICorProfilerInfo7_GetThreadAppDomain(This,threadId,pAppDomainId) \ +#define ICorProfilerInfo8_GetThreadAppDomain(This,threadId,pAppDomainId) \ ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) -#define ICorProfilerInfo7_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ +#define ICorProfilerInfo8_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) -#define ICorProfilerInfo7_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ +#define ICorProfilerInfo8_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) -#define ICorProfilerInfo7_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ +#define ICorProfilerInfo8_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) -#define ICorProfilerInfo7_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ +#define ICorProfilerInfo8_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) -#define ICorProfilerInfo7_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ +#define ICorProfilerInfo8_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) -#define ICorProfilerInfo7_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ +#define ICorProfilerInfo8_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) -#define ICorProfilerInfo7_GetObjectGeneration(This,objectId,range) \ +#define ICorProfilerInfo8_GetObjectGeneration(This,objectId,range) \ ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) -#define ICorProfilerInfo7_GetNotifiedExceptionClauseInfo(This,pinfo) \ +#define ICorProfilerInfo8_GetNotifiedExceptionClauseInfo(This,pinfo) \ ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) -#define ICorProfilerInfo7_EnumJITedFunctions(This,ppEnum) \ +#define ICorProfilerInfo8_EnumJITedFunctions(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) -#define ICorProfilerInfo7_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ +#define ICorProfilerInfo8_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) -#define ICorProfilerInfo7_SetFunctionIDMapper2(This,pFunc,clientData) \ +#define ICorProfilerInfo8_SetFunctionIDMapper2(This,pFunc,clientData) \ ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) -#define ICorProfilerInfo7_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ +#define ICorProfilerInfo8_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) -#define ICorProfilerInfo7_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ +#define ICorProfilerInfo8_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) -#define ICorProfilerInfo7_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ +#define ICorProfilerInfo8_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) -#define ICorProfilerInfo7_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ +#define ICorProfilerInfo8_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) -#define ICorProfilerInfo7_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ +#define ICorProfilerInfo8_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) -#define ICorProfilerInfo7_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ +#define ICorProfilerInfo8_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) -#define ICorProfilerInfo7_EnumModules(This,ppEnum) \ +#define ICorProfilerInfo8_EnumModules(This,ppEnum) \ ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) -#define ICorProfilerInfo7_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ +#define ICorProfilerInfo8_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) -#define ICorProfilerInfo7_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ +#define ICorProfilerInfo8_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) -#define ICorProfilerInfo7_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ +#define ICorProfilerInfo8_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) -#define ICorProfilerInfo7_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ +#define ICorProfilerInfo8_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) -#define ICorProfilerInfo7_EnumThreads(This,ppEnum) \ +#define ICorProfilerInfo8_EnumThreads(This,ppEnum) \ ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) -#define ICorProfilerInfo7_InitializeCurrentThread(This) \ +#define ICorProfilerInfo8_InitializeCurrentThread(This) \ ( (This)->lpVtbl -> InitializeCurrentThread(This) ) -#define ICorProfilerInfo7_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ +#define ICorProfilerInfo8_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) -#define ICorProfilerInfo7_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ +#define ICorProfilerInfo8_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) -#define ICorProfilerInfo7_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ +#define ICorProfilerInfo8_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) -#define ICorProfilerInfo7_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ +#define ICorProfilerInfo8_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) -#define ICorProfilerInfo7_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ +#define ICorProfilerInfo8_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) -#define ICorProfilerInfo7_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ +#define ICorProfilerInfo8_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) -#define ICorProfilerInfo7_EnumJITedFunctions2(This,ppEnum) \ +#define ICorProfilerInfo8_EnumJITedFunctions2(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) -#define ICorProfilerInfo7_GetObjectSize2(This,objectId,pcSize) \ +#define ICorProfilerInfo8_GetObjectSize2(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) -#define ICorProfilerInfo7_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ +#define ICorProfilerInfo8_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) -#define ICorProfilerInfo7_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ +#define ICorProfilerInfo8_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) -#define ICorProfilerInfo7_EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) \ +#define ICorProfilerInfo8_EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) \ ( (This)->lpVtbl -> EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) ) -#define ICorProfilerInfo7_ApplyMetaData(This,moduleId) \ +#define ICorProfilerInfo8_ApplyMetaData(This,moduleId) \ ( (This)->lpVtbl -> ApplyMetaData(This,moduleId) ) -#define ICorProfilerInfo7_GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) \ +#define ICorProfilerInfo8_GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) \ ( (This)->lpVtbl -> GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) ) -#define ICorProfilerInfo7_ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) \ +#define ICorProfilerInfo8_ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) \ ( (This)->lpVtbl -> ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) ) + +#define ICorProfilerInfo8_IsFunctionDynamic(This,functionId,isDynamic) \ + ( (This)->lpVtbl -> IsFunctionDynamic(This,functionId,isDynamic) ) + +#define ICorProfilerInfo8_GetFunctionFromIP3(This,ip,functionId,pReJitId) \ + ( (This)->lpVtbl -> GetFunctionFromIP3(This,ip,functionId,pReJitId) ) + +#define ICorProfilerInfo8_GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) \ + ( (This)->lpVtbl -> GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) ) + #endif /* COBJMACROS */ @@ -11709,7 +13411,7 @@ EXTERN_C const IID IID_ICorProfilerInfo7; -#endif /* __ICorProfilerInfo7_INTERFACE_DEFINED__ */ +#endif /* __ICorProfilerInfo8_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerMethodEnum_INTERFACE_DEFINED__ diff --git a/src/pal/prebuilt/inc/xclrdata.h b/src/pal/prebuilt/inc/xclrdata.h index 3f46c31..da7acb3 100644 --- a/src/pal/prebuilt/inc/xclrdata.h +++ b/src/pal/prebuilt/inc/xclrdata.h @@ -1017,7 +1017,7 @@ EXTERN_C const IID IID_IXCLRDataDisplay; IXCLRDataDisplay : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE ErrorPrintF( + virtual HRESULT STDMETHODVCALLTYPE ErrorPrintF( const char *const fmt, ...) = 0; @@ -1063,11 +1063,11 @@ EXTERN_C const IID IID_IXCLRDataDisplay; virtual HRESULT STDMETHODCALLTYPE EndTextElement( void) = 0; - virtual HRESULT STDMETHODCALLTYPE WriteXmlText( + virtual HRESULT STDMETHODVCALLTYPE WriteXmlText( const char *const fmt, ...) = 0; - virtual HRESULT STDMETHODCALLTYPE WriteXmlTextBlock( + virtual HRESULT STDMETHODVCALLTYPE WriteXmlTextBlock( const char *const fmt, ...) = 0; @@ -1258,7 +1258,7 @@ EXTERN_C const IID IID_IXCLRDataDisplay; ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataDisplay * This); - HRESULT ( STDMETHODCALLTYPE *ErrorPrintF )( + HRESULT ( STDMETHODVCALLTYPE *ErrorPrintF )( IXCLRDataDisplay * This, const char *const fmt, ...); @@ -1319,12 +1319,12 @@ EXTERN_C const IID IID_IXCLRDataDisplay; HRESULT ( STDMETHODCALLTYPE *EndTextElement )( IXCLRDataDisplay * This); - HRESULT ( STDMETHODCALLTYPE *WriteXmlText )( + HRESULT ( STDMETHODVCALLTYPE *WriteXmlText )( IXCLRDataDisplay * This, const char *const fmt, ...); - HRESULT ( STDMETHODCALLTYPE *WriteXmlTextBlock )( + HRESULT ( STDMETHODVCALLTYPE *WriteXmlTextBlock )( IXCLRDataDisplay * This, const char *const fmt, ...); diff --git a/src/pal/src/CMakeLists.txt b/src/pal/src/CMakeLists.txt index 7df0aaf..28ee83a 100644 --- a/src/pal/src/CMakeLists.txt +++ b/src/pal/src/CMakeLists.txt @@ -2,13 +2,6 @@ cmake_minimum_required(VERSION 2.8.12.2) include_directories(SYSTEM /usr/local/include) -# set kernel version to detect Alpine -EXEC_PROGRAM(uname ARGS -v OUTPUT_VARIABLE CMAKE_SYSTEM_KERNEL_VERSION) -string(FIND "${CMAKE_SYSTEM_KERNEL_VERSION}" "Alpine" PAL_SYSTEM_ALPINE) -if(PAL_SYSTEM_ALPINE EQUAL -1) - unset(PAL_SYSTEM_ALPINE) -endif() - include(configure.cmake) project(coreclrpal) @@ -39,16 +32,20 @@ elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l) elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64) set(PAL_CMAKE_PLATFORM_ARCH_ARM64 1) add_definitions(-D_ARM64_) +elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL i686) + set(CLR_CMAKE_PLATFORM_ARCH_I386 1) + add_definitions(-D_X86_) else() message(FATAL_ERROR "Only ARM and AMD64 is supported") endif() if(CMAKE_SYSTEM_NAME STREQUAL Darwin) add_definitions(-D_TARGET_MAC64) + add_definitions(-DXSTATE_SUPPORTED) set(PLATFORM_SOURCES - arch/i386/activationhandlerwrapper.S - arch/i386/context.S - arch/i386/dispatchexceptionwrapper.S + arch/amd64/activationhandlerwrapper.S + arch/amd64/context.S + arch/amd64/dispatchexceptionwrapper.S exception/machexception.cpp exception/machmessage.cpp ) @@ -68,8 +65,20 @@ elseif(PAL_CMAKE_PLATFORM_ARCH_ARM) elseif(PAL_CMAKE_PLATFORM_ARCH_ARM64) add_definitions(-DBIT64=1) add_definitions(-D_WIN64=1) +elseif(CLR_CMAKE_PLATFORM_ARCH_I386) + add_definitions(-DBIT32=1) endif() +if(CMAKE_SYSTEM_NAME STREQUAL Linux AND NOT CLR_CMAKE_PLATFORM_ALPINE_LINUX) + # Currently the _xstate is not available on Alpine Linux + add_definitions(-DXSTATE_SUPPORTED) +endif(CMAKE_SYSTEM_NAME STREQUAL Linux AND NOT CLR_CMAKE_PLATFORM_ALPINE_LINUX) + +if(CLR_CMAKE_PLATFORM_ALPINE_LINUX) + # Setting RLIMIT_NOFILE breaks debugging of coreclr on Alpine Linux for some reason + add_definitions(-DDONT_SET_RLIMIT_NOFILE) +endif(CLR_CMAKE_PLATFORM_ALPINE_LINUX) + # turn off capability to remove unused functions (which was enabled in debug build with sanitizers) set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -Wl,--no-gc-sections") @@ -77,10 +86,10 @@ add_compile_options(-fPIC) if(PAL_CMAKE_PLATFORM_ARCH_AMD64) set(ARCH_SOURCES - arch/i386/context2.S - arch/i386/debugbreak.S - arch/i386/exceptionhelper.S - arch/i386/processor.cpp + arch/amd64/context2.S + arch/amd64/debugbreak.S + arch/amd64/exceptionhelper.S + arch/amd64/processor.cpp ) elseif(PAL_CMAKE_PLATFORM_ARCH_ARM) set(ARCH_SOURCES @@ -96,6 +105,13 @@ elseif(PAL_CMAKE_PLATFORM_ARCH_ARM64) arch/arm64/exceptionhelper.S arch/arm64/processor.cpp ) +elseif(CLR_CMAKE_PLATFORM_ARCH_I386) + set(ARCH_SOURCES + arch/i386/context2.S + arch/i386/debugbreak.S + arch/i386/exceptionhelper.S + arch/i386/processor.cpp + ) endif() if(PAL_CMAKE_PLATFORM_ARCH_ARM) @@ -160,37 +176,37 @@ set(SOURCES objmgr/palobjbase.cpp objmgr/shmobject.cpp objmgr/shmobjectmanager.cpp - safecrt/makepath_s.c - safecrt/memcpy_s.c - safecrt/memmove_s.c - safecrt/mbusafecrt.c - safecrt/safecrt_input_s.c - safecrt/safecrt_output_l.c - safecrt/safecrt_output_s.c - safecrt/safecrt_winput_s.c - safecrt/safecrt_woutput_s.c - safecrt/splitpath_s.c - safecrt/sprintf.c - safecrt/sscanf.c - safecrt/strcat_s.c - safecrt/strcpy_s.c - safecrt/strlen_s.c - safecrt/strncat_s.c - safecrt/strncpy_s.c - safecrt/strtok_s.c - safecrt/swprintf.c - safecrt/vsprintf.c - safecrt/vswprint.c - safecrt/wcscat_s.c - safecrt/wcscpy_s.c - safecrt/wcslen_s.c - safecrt/wcsncat_s.c - safecrt/wcsncpy_s.c - safecrt/wcstok_s.c - safecrt/wmakepath_s.c - safecrt/wsplitpath_s.c - safecrt/xtoa_s.c - safecrt/xtow_s.c + safecrt/makepath_s.cpp + safecrt/memcpy_s.cpp + safecrt/memmove_s.cpp + safecrt/mbusafecrt.cpp + safecrt/safecrt_input_s.cpp + safecrt/safecrt_output_l.cpp + safecrt/safecrt_output_s.cpp + safecrt/safecrt_winput_s.cpp + safecrt/safecrt_woutput_s.cpp + safecrt/splitpath_s.cpp + safecrt/sprintf_s.cpp + safecrt/sscanf_s.cpp + safecrt/strcat_s.cpp + safecrt/strcpy_s.cpp + safecrt/strlen_s.cpp + safecrt/strncat_s.cpp + safecrt/strncpy_s.cpp + safecrt/strtok_s.cpp + safecrt/swprintf.cpp + safecrt/vsprintf.cpp + safecrt/vswprint.cpp + safecrt/wcscat_s.cpp + safecrt/wcscpy_s.cpp + safecrt/wcslen_s.cpp + safecrt/wcsncat_s.cpp + safecrt/wcsncpy_s.cpp + safecrt/wcstok_s.cpp + safecrt/wmakepath_s.cpp + safecrt/wsplitpath_s.cpp + safecrt/xtoa_s.cpp + safecrt/xtow_s.cpp sharedmemory/sharedmemory.cpp shmemory/shmemory.cpp sync/cs.cpp @@ -252,7 +268,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL Linux) find_library(UNWIND_ARCH NAMES unwind-x86_64) endif() - if(PAL_SYSTEM_ALPINE) + if(CLR_CMAKE_PLATFORM_ALPINE_LINUX) find_library(INTL intl) endif() diff --git a/src/pal/src/arch/i386/activationhandlerwrapper.S b/src/pal/src/arch/amd64/activationhandlerwrapper.S similarity index 100% rename from src/pal/src/arch/i386/activationhandlerwrapper.S rename to src/pal/src/arch/amd64/activationhandlerwrapper.S diff --git a/src/pal/src/arch/amd64/asmconstants.h b/src/pal/src/arch/amd64/asmconstants.h new file mode 100644 index 0000000..182c119 --- /dev/null +++ b/src/pal/src/arch/amd64/asmconstants.h @@ -0,0 +1,106 @@ +// 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. + +#ifdef BIT64 + +#define CONTEXT_AMD64 0x100000 + +#define CONTEXT_CONTROL 1 // SegSs, Rsp, SegCs, Rip, and EFlags +#define CONTEXT_INTEGER 2 // Rax, Rcx, Rdx, Rbx, Rbp, Rsi, Rdi, R8-R15 +#define CONTEXT_SEGMENTS 4 // SegDs, SegEs, SegFs, SegGs +#define CONTEXT_FLOATING_POINT 8 +#define CONTEXT_DEBUG_REGISTERS 16 // Dr0-Dr3 and Dr6-Dr7 + +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) + +#define CONTEXT_XSTATE 64 + +#define CONTEXT_ContextFlags 6*8 +#define CONTEXT_SegCs CONTEXT_ContextFlags+8 +#define CONTEXT_SegDs CONTEXT_SegCs+2 +#define CONTEXT_SegEs CONTEXT_SegDs+2 +#define CONTEXT_SegFs CONTEXT_SegEs+2 +#define CONTEXT_SegGs CONTEXT_SegFs+2 +#define CONTEXT_SegSs CONTEXT_SegGs+2 +#define CONTEXT_EFlags CONTEXT_SegSs+2 +#define CONTEXT_Dr0 CONTEXT_EFlags+4 +#define CONTEXT_Dr1 CONTEXT_Dr0+8 +#define CONTEXT_Dr2 CONTEXT_Dr1+8 +#define CONTEXT_Dr3 CONTEXT_Dr2+8 +#define CONTEXT_Dr6 CONTEXT_Dr3+8 +#define CONTEXT_Dr7 CONTEXT_Dr6+8 +#define CONTEXT_Rax CONTEXT_Dr7+8 +#define CONTEXT_Rcx CONTEXT_Rax+8 +#define CONTEXT_Rdx CONTEXT_Rcx+8 +#define CONTEXT_Rbx CONTEXT_Rdx+8 +#define CONTEXT_Rsp CONTEXT_Rbx+8 +#define CONTEXT_Rbp CONTEXT_Rsp+8 +#define CONTEXT_Rsi CONTEXT_Rbp+8 +#define CONTEXT_Rdi CONTEXT_Rsi+8 +#define CONTEXT_R8 CONTEXT_Rdi+8 +#define CONTEXT_R9 CONTEXT_R8+8 +#define CONTEXT_R10 CONTEXT_R9+8 +#define CONTEXT_R11 CONTEXT_R10+8 +#define CONTEXT_R12 CONTEXT_R11+8 +#define CONTEXT_R13 CONTEXT_R12+8 +#define CONTEXT_R14 CONTEXT_R13+8 +#define CONTEXT_R15 CONTEXT_R14+8 +#define CONTEXT_Rip CONTEXT_R15+8 +#define CONTEXT_FltSave CONTEXT_Rip+8 +#define FLOATING_SAVE_AREA_SIZE 4*8+24*16+96 +#define CONTEXT_Xmm0 CONTEXT_FltSave+10*16 +#define CONTEXT_Xmm1 CONTEXT_Xmm0+16 +#define CONTEXT_Xmm2 CONTEXT_Xmm1+16 +#define CONTEXT_Xmm3 CONTEXT_Xmm2+16 +#define CONTEXT_Xmm4 CONTEXT_Xmm3+16 +#define CONTEXT_Xmm5 CONTEXT_Xmm4+16 +#define CONTEXT_Xmm6 CONTEXT_Xmm5+16 +#define CONTEXT_Xmm7 CONTEXT_Xmm6+16 +#define CONTEXT_Xmm8 CONTEXT_Xmm7+16 +#define CONTEXT_Xmm9 CONTEXT_Xmm8+16 +#define CONTEXT_Xmm10 CONTEXT_Xmm9+16 +#define CONTEXT_Xmm11 CONTEXT_Xmm10+16 +#define CONTEXT_Xmm12 CONTEXT_Xmm11+16 +#define CONTEXT_Xmm13 CONTEXT_Xmm12+16 +#define CONTEXT_Xmm14 CONTEXT_Xmm13+16 +#define CONTEXT_Xmm15 CONTEXT_Xmm14+16 +#define CONTEXT_VectorRegister CONTEXT_FltSave+FLOATING_SAVE_AREA_SIZE +#define CONTEXT_VectorControl CONTEXT_VectorRegister+16*26 +#define CONTEXT_DebugControl CONTEXT_VectorControl+8 +#define CONTEXT_LastBranchToRip CONTEXT_DebugControl+8 +#define CONTEXT_LastBranchFromRip CONTEXT_LastBranchToRip+8 +#define CONTEXT_LastExceptionToRip CONTEXT_LastBranchFromRip+8 +#define CONTEXT_LastExceptionFromRip CONTEXT_LastExceptionToRip+8 +#define CONTEXT_Size CONTEXT_LastExceptionFromRip+8 + +#else // BIT64 + +#define CONTEXT_ContextFlags 0 +#define CONTEXT_FLOATING_POINT 8 +#define CONTEXT_FloatSave 7*4 +#define FLOATING_SAVE_AREA_SIZE 8*4+80 +#define CONTEXT_Edi CONTEXT_FloatSave + FLOATING_SAVE_AREA_SIZE + 4*4 +#define CONTEXT_Esi CONTEXT_Edi+4 +#define CONTEXT_Ebx CONTEXT_Esi+4 +#define CONTEXT_Edx CONTEXT_Ebx+4 +#define CONTEXT_Ecx CONTEXT_Edx+4 +#define CONTEXT_Eax CONTEXT_Ecx+4 +#define CONTEXT_Ebp CONTEXT_Eax+4 +#define CONTEXT_Eip CONTEXT_Ebp+4 +#define CONTEXT_SegCs CONTEXT_Eip+4 +#define CONTEXT_EFlags CONTEXT_SegCs+4 +#define CONTEXT_Esp CONTEXT_EFlags+4 +#define CONTEXT_SegSs CONTEXT_Esp+4 +#define CONTEXT_EXTENDED_REGISTERS 32 +#define CONTEXT_ExtendedRegisters CONTEXT_SegSs+4 +#define CONTEXT_Xmm0 CONTEXT_ExtendedRegisters+160 +#define CONTEXT_Xmm1 CONTEXT_Xmm0+16 +#define CONTEXT_Xmm2 CONTEXT_Xmm1+16 +#define CONTEXT_Xmm3 CONTEXT_Xmm2+16 +#define CONTEXT_Xmm4 CONTEXT_Xmm3+16 +#define CONTEXT_Xmm5 CONTEXT_Xmm4+16 +#define CONTEXT_Xmm6 CONTEXT_Xmm5+16 +#define CONTEXT_Xmm7 CONTEXT_Xmm6+16 + +#endif // BIT64 diff --git a/src/pal/src/arch/i386/context.S b/src/pal/src/arch/amd64/context.S similarity index 100% rename from src/pal/src/arch/i386/context.S rename to src/pal/src/arch/amd64/context.S diff --git a/src/pal/src/arch/amd64/context2.S b/src/pal/src/arch/amd64/context2.S new file mode 100644 index 0000000..0e93e81 --- /dev/null +++ b/src/pal/src/arch/amd64/context2.S @@ -0,0 +1,259 @@ +// 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. +// +// Implementation of _CONTEXT_CaptureContext for the Intel x86 platform. +// This function is processor dependent. It is used by exception handling, +// and is always apply to the current thread. +// + +.intel_syntax noprefix +#include "unixasmmacros.inc" +#include "asmconstants.h" + +#ifdef BIT64 + +#define IRETFRAME_Rip 0 +#define IRETFRAME_SegCs IRETFRAME_Rip+8 +#define IRETFRAME_EFlags IRETFRAME_SegCs+8 +#define IRETFRAME_Rsp IRETFRAME_EFlags+8 +#define IRETFRAME_SegSs IRETFRAME_Rsp+8 +#define IRetFrameLength IRETFRAME_SegSs+8 +#define IRetFrameLengthAligned 16*((IRetFrameLength+8)/16) + +// Incoming: +// RDI: Context* +// +LEAF_ENTRY CONTEXT_CaptureContext, _TEXT + // Save processor flags before calling any of the following 'test' instructions + // because they will modify state of some flags + push_eflags + END_PROLOGUE + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_INTEGER + je LOCAL_LABEL(Done_CONTEXT_INTEGER) + mov [rdi + CONTEXT_Rdi], rdi + mov [rdi + CONTEXT_Rsi], rsi + mov [rdi + CONTEXT_Rbx], rbx + mov [rdi + CONTEXT_Rdx], rdx + mov [rdi + CONTEXT_Rcx], rcx + mov [rdi + CONTEXT_Rax], rax + mov [rdi + CONTEXT_Rbp], rbp + mov [rdi + CONTEXT_R8], r8 + mov [rdi + CONTEXT_R9], r9 + mov [rdi + CONTEXT_R10], r10 + mov [rdi + CONTEXT_R11], r11 + mov [rdi + CONTEXT_R12], r12 + mov [rdi + CONTEXT_R13], r13 + mov [rdi + CONTEXT_R14], r14 + mov [rdi + CONTEXT_R15], r15 +LOCAL_LABEL(Done_CONTEXT_INTEGER): + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_CONTROL + je LOCAL_LABEL(Done_CONTEXT_CONTROL) + + // Return address is @ (RSP + 8) + mov rdx, [rsp + 8] + mov [rdi + CONTEXT_Rip], rdx +.att_syntax + mov %cs, CONTEXT_SegCs(%rdi) +.intel_syntax noprefix + // Get the value of EFlags that was pushed on stack at the beginning of the function + mov rdx, [rsp] + mov [rdi + CONTEXT_EFlags], edx + lea rdx, [rsp + 16] + mov [rdi + CONTEXT_Rsp], rdx +.att_syntax + mov %ss, CONTEXT_SegSs(%rdi) +.intel_syntax noprefix +LOCAL_LABEL(Done_CONTEXT_CONTROL): + + // Need to double check this is producing the right result + // also that FFSXR (fast save/restore) is not turned on + // otherwise it omits the xmm registers. + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT + je LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT) + fxsave [rdi + CONTEXT_FltSave] +LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT): + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_DEBUG_REGISTERS + je LOCAL_LABEL(Done_CONTEXT_DEBUG_REGISTERS) + mov rdx, dr0 + mov [rdi + CONTEXT_Dr0], rdx + mov rdx, dr1 + mov [rdi + CONTEXT_Dr1], rdx + mov rdx, dr2 + mov [rdi + CONTEXT_Dr2], rdx + mov rdx, dr3 + mov [rdi + CONTEXT_Dr3], rdx + mov rdx, dr6 + mov [rdi + CONTEXT_Dr6], rdx + mov rdx, dr7 + mov [rdi + CONTEXT_Dr7], rdx +LOCAL_LABEL(Done_CONTEXT_DEBUG_REGISTERS): + + free_stack 8 + ret +LEAF_END CONTEXT_CaptureContext, _TEXT + +LEAF_ENTRY RtlCaptureContext, _TEXT + mov DWORD PTR [rdi + CONTEXT_ContextFlags], (CONTEXT_AMD64 | CONTEXT_FULL | CONTEXT_SEGMENTS) + jmp C_FUNC(CONTEXT_CaptureContext) +LEAF_END RtlCaptureContext, _TEXT + +LEAF_ENTRY RtlRestoreContext, _TEXT + push_nonvol_reg rbp + alloc_stack (IRetFrameLengthAligned) + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_DEBUG_REGISTERS + je LOCAL_LABEL(Done_Restore_CONTEXT_DEBUG_REGISTERS) + mov rdx, [rdi + CONTEXT_Dr0] + mov dr0, rdx + mov rdx, [rdi + CONTEXT_Dr1] + mov dr1, rdx + mov rdx, [rdi + CONTEXT_Dr2] + mov dr2, rdx + mov rdx, [rdi + CONTEXT_Dr3] + mov dr3, rdx + mov rdx, [rdi + CONTEXT_Dr6] + mov dr6, rdx + mov rdx, [rdi + CONTEXT_Dr7] + mov dr7, rdx +LOCAL_LABEL(Done_Restore_CONTEXT_DEBUG_REGISTERS): + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT + je LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT) + fxrstor [rdi + CONTEXT_FltSave] +LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT): + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_XSTATE + je LOCAL_LABEL(Done_Restore_CONTEXT_XSTATE) + + // Restore the extended state (for now, this is just the upper halves of YMM registers) + vinsertf128 ymm0, ymm0, xmmword ptr [rdi + (CONTEXT_VectorRegister + 0 * 16)], 1 + vinsertf128 ymm1, ymm1, xmmword ptr [rdi + (CONTEXT_VectorRegister + 1 * 16)], 1 + vinsertf128 ymm2, ymm2, xmmword ptr [rdi + (CONTEXT_VectorRegister + 2 * 16)], 1 + vinsertf128 ymm3, ymm3, xmmword ptr [rdi + (CONTEXT_VectorRegister + 3 * 16)], 1 + vinsertf128 ymm4, ymm4, xmmword ptr [rdi + (CONTEXT_VectorRegister + 4 * 16)], 1 + vinsertf128 ymm5, ymm5, xmmword ptr [rdi + (CONTEXT_VectorRegister + 5 * 16)], 1 + vinsertf128 ymm6, ymm6, xmmword ptr [rdi + (CONTEXT_VectorRegister + 6 * 16)], 1 + vinsertf128 ymm7, ymm7, xmmword ptr [rdi + (CONTEXT_VectorRegister + 7 * 16)], 1 + vinsertf128 ymm8, ymm8, xmmword ptr [rdi + (CONTEXT_VectorRegister + 8 * 16)], 1 + vinsertf128 ymm9, ymm9, xmmword ptr [rdi + (CONTEXT_VectorRegister + 9 * 16)], 1 + vinsertf128 ymm10, ymm10, xmmword ptr [rdi + (CONTEXT_VectorRegister + 10 * 16)], 1 + vinsertf128 ymm11, ymm11, xmmword ptr [rdi + (CONTEXT_VectorRegister + 11 * 16)], 1 + vinsertf128 ymm12, ymm12, xmmword ptr [rdi + (CONTEXT_VectorRegister + 12 * 16)], 1 + vinsertf128 ymm13, ymm13, xmmword ptr [rdi + (CONTEXT_VectorRegister + 13 * 16)], 1 + vinsertf128 ymm14, ymm14, xmmword ptr [rdi + (CONTEXT_VectorRegister + 14 * 16)], 1 + vinsertf128 ymm15, ymm15, xmmword ptr [rdi + (CONTEXT_VectorRegister + 15 * 16)], 1 +LOCAL_LABEL(Done_Restore_CONTEXT_XSTATE): + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_CONTROL + je LOCAL_LABEL(Done_Restore_CONTEXT_CONTROL) + + // The control registers are restored via the iret instruction + // so we build the frame for the iret on the stack. +#ifdef __APPLE__ +.att_syntax + // On OSX, we cannot read SS via the thread_get_context and RtlRestoreContext + // needs to be used on context extracted by thread_get_context. So we + // don't change the SS. + mov %ss, %ax +.intel_syntax noprefix +#else + mov ax, [rdi + CONTEXT_SegSs] +#endif + mov [rsp + IRETFRAME_SegSs], ax + mov rax, [rdi + CONTEXT_Rsp] + mov [rsp + IRETFRAME_Rsp], rax + mov eax, [rdi + CONTEXT_EFlags] + mov [rsp + IRETFRAME_EFlags], eax + mov ax, [rdi + CONTEXT_SegCs] + mov [rsp + IRETFRAME_SegCs], ax + mov rax, [rdi + CONTEXT_Rip] + mov [rsp + IRETFRAME_Rip], rax + +LOCAL_LABEL(Done_Restore_CONTEXT_CONTROL): + // Remember the result of the test for the CONTEXT_CONTROL + push_eflags + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_INTEGER + je LOCAL_LABEL(Done_Restore_CONTEXT_INTEGER) + mov rsi, [rdi + CONTEXT_Rsi] + mov rbx, [rdi + CONTEXT_Rbx] + mov rdx, [rdi + CONTEXT_Rdx] + mov rcx, [rdi + CONTEXT_Rcx] + mov rax, [rdi + CONTEXT_Rax] + mov rbp, [rdi + CONTEXT_Rbp] + mov r8, [rdi + CONTEXT_R8] + mov r9, [rdi + CONTEXT_R9] + mov r10, [rdi + CONTEXT_R10] + mov r11, [rdi + CONTEXT_R11] + mov r12, [rdi + CONTEXT_R12] + mov r13, [rdi + CONTEXT_R13] + mov r14, [rdi + CONTEXT_R14] + mov r15, [rdi + CONTEXT_R15] + mov rdi, [rdi + CONTEXT_Rdi] +LOCAL_LABEL(Done_Restore_CONTEXT_INTEGER): + + // Restore the result of the test for the CONTEXT_CONTROL + pop_eflags + je LOCAL_LABEL(No_Restore_CONTEXT_CONTROL) + // The function was asked to restore the control registers, so + // we perform iretq that restores them all. + // We don't return to the caller in this case. + iretq +LOCAL_LABEL(No_Restore_CONTEXT_CONTROL): + + // The function was not asked to restore the control registers + // so we return back to the caller. + free_stack (IRetFrameLengthAligned) + pop_nonvol_reg rbp + ret +LEAF_END RtlRestoreContext, _TEXT + +#else + + .globl C_FUNC(CONTEXT_CaptureContext) +C_FUNC(CONTEXT_CaptureContext): + push %eax + mov 8(%esp), %eax + mov %edi, CONTEXT_Edi(%eax) + mov %esi, CONTEXT_Esi(%eax) + mov %ebx, CONTEXT_Ebx(%eax) + mov %edx, CONTEXT_Edx(%eax) + mov %ecx, CONTEXT_Ecx(%eax) + pop %ecx + mov %ecx, CONTEXT_Eax(%eax) + mov %ebp, CONTEXT_Ebp(%eax) + mov (%esp), %edx + mov %edx, CONTEXT_Eip(%eax) + push %cs + pop %edx + mov %edx, CONTEXT_SegCs(%eax) + pushf + pop %edx + mov %edx, CONTEXT_EFlags(%eax) + lea 4(%esp), %edx + mov %edx, CONTEXT_Esp(%eax) + push %ss + pop %edx + mov %edx, CONTEXT_SegSs(%eax) + testb $CONTEXT_FLOATING_POINT, CONTEXT_ContextFlags(%eax) + je 0f + fnsave CONTEXT_FloatSave(%eax) + frstor CONTEXT_FloatSave(%eax) +0: + testb $CONTEXT_EXTENDED_REGISTERS, CONTEXT_ContextFlags(%eax) + je 2f + movdqu %xmm0, CONTEXT_Xmm0(%eax) + movdqu %xmm1, CONTEXT_Xmm1(%eax) + movdqu %xmm2, CONTEXT_Xmm2(%eax) + movdqu %xmm3, CONTEXT_Xmm3(%eax) + movdqu %xmm4, CONTEXT_Xmm4(%eax) + movdqu %xmm5, CONTEXT_Xmm5(%eax) + movdqu %xmm6, CONTEXT_Xmm6(%eax) + movdqu %xmm7, CONTEXT_Xmm7(%eax) +2: + ret + +#endif diff --git a/src/pal/src/arch/amd64/debugbreak.S b/src/pal/src/arch/amd64/debugbreak.S new file mode 100644 index 0000000..3065e40 --- /dev/null +++ b/src/pal/src/arch/amd64/debugbreak.S @@ -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. +// See the LICENSE file in the project root for more information. + +.intel_syntax noprefix +#include "unixasmmacros.inc" + +LEAF_ENTRY DBG_DebugBreak, _TEXT + int3 + ret +LEAF_END_MARKED DBG_DebugBreak, _TEXT + diff --git a/src/pal/src/arch/i386/dispatchexceptionwrapper.S b/src/pal/src/arch/amd64/dispatchexceptionwrapper.S similarity index 100% rename from src/pal/src/arch/i386/dispatchexceptionwrapper.S rename to src/pal/src/arch/amd64/dispatchexceptionwrapper.S diff --git a/src/pal/src/arch/amd64/exceptionhelper.S b/src/pal/src/arch/amd64/exceptionhelper.S new file mode 100644 index 0000000..b7b34ac --- /dev/null +++ b/src/pal/src/arch/amd64/exceptionhelper.S @@ -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. +// See the LICENSE file in the project root for more information. + +.intel_syntax noprefix +#include "unixasmmacros.inc" +#include "asmconstants.h" + +////////////////////////////////////////////////////////////////////////// +// +// This function creates a stack frame right below the target frame, restores all callee +// saved registers from the passed in context, sets the RSP to that frame and sets the +// return address to the target frame's RIP. +// Then it uses the ThrowExceptionHelper to throw the passed in exception from that context. +// EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); +LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT + // Save the RBP to the stack so that the unwind can work at the instruction after + // loading the RBP from the context, but before loading the RSP from the context. + push_nonvol_reg rbp + mov r12, [rdi + CONTEXT_R12] + mov r13, [rdi + CONTEXT_R13] + mov r14, [rdi + CONTEXT_R14] + mov r15, [rdi + CONTEXT_R15] + mov rbx, [rdi + CONTEXT_Rbx] + mov rbp, [rdi + CONTEXT_Rbp] + mov rsp, [rdi + CONTEXT_Rsp] + // The RSP was set to the target frame's value, so the current function's + // CFA is now right at the RSP. + .cfi_def_cfa_offset 0 + + // Indicate that now that we have moved the RSP to the target address, + // the RBP is no longer saved in the current stack frame. + .cfi_restore rbp + + mov rax, [rdi + CONTEXT_Rip] + + // Store return address to the stack + push_register rax + // The PAL_SEHException pointer + mov rdi, rsi + jmp EXTERNAL_C_FUNC(ThrowExceptionHelper) +LEAF_END ThrowExceptionFromContextInternal, _TEXT diff --git a/src/pal/src/arch/amd64/optimizedtls.cpp b/src/pal/src/arch/amd64/optimizedtls.cpp new file mode 100644 index 0000000..cd89db6 --- /dev/null +++ b/src/pal/src/arch/amd64/optimizedtls.cpp @@ -0,0 +1,237 @@ +// 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. + +/*++ + + + +Module Name: + + optimizedtls.cpp + +Abstract: + + Implementation of platform-specific Thread local storage functions. + + + +--*/ + +#include "pal/thread.hpp" +#include "pal/malloc.hpp" + +#include + +#include "pal/dbgmsg.h" +#include "pal/misc.h" +#include "pal/debug.h" + +#include + +using namespace CorUnix; + +SET_DEFAULT_DEBUG_CHANNEL(THREAD); + +#if defined(USE_OPTIMIZEDTLSGETTER) + +#define PAL_safe_offsetof(s,m) ((size_t)((ptrdiff_t)&(char&)(((s *)64)->m))-64) + +/*++ +Function: + CorUnix::TLSMakeOptimizedGetter + + Creates a platform-optimized version of TlsGetValue compiled + for a particular index. + + Generates the hot part of CorUnix::InternalGetCurrentThread + as a chunk of highly optimized machine-specific code at runtime. + + Check the difference between CorUnix::InternalGetCurrentThread and + CorUnix::InternalGetCurrentThreadSlow to see the C/C++ code that matches + the code generated by this function. +--*/ +PAL_POPTIMIZEDTLSGETTER +CorUnix::TLSMakeOptimizedGetter( + IN CPalThread* pThread, + IN DWORD dwTlsIndex) +{ +#ifdef BIT64 +#pragma unused(pThread, dwTlsIndex) + ERROR("TLSMakeOptimizedGetter not rewritten for amd64 yet."); + return NULL; +#else + PAL_POPTIMIZEDTLSGETTER Ret = NULL; + BYTE* p; + int i = 0; + +#ifdef __APPLE__ +#define TLS_OPTIMIZED_GETTER_SIZE 118 +#else +#define TLS_OPTIMIZED_GETTER_SIZE 115 +#endif + + p = (BYTE*)InternalMalloc(pThread, TLS_OPTIMIZED_GETTER_SIZE * sizeof(BYTE)); + + if (p == NULL) + { + return Ret; + } + + // Need to preserve %ecx, %edx, and %esi registers as specified in + // GetThreadGeneric(void) in vm/amd64/asmhelpers.s + p[i++] = 0x51; // push %ecx + p[i++] = 0x52; // push %edx + p[i++] = 0x89; // mov %esp,%eax // %eax = sp; + p[i++] = 0xe0; + p[i++] = 0xc1; // shr $0x11,%eax // sp >> 17; + p[i++] = 0xe8; + p[i++] = 0x11; + p[i++] = 0x89; // mov %eax,%edx // key = sp >> 17; + p[i++] = 0xc2; + p[i++] = 0xc1; // sar $0x7,%edx // key >> 7; + p[i++] = 0xfa; + p[i++] = 0x07; + p[i++] = 0x29; // sub %edx,%eax // key -= key >> 7; + p[i++] = 0xd0; + p[i++] = 0x89; // mov %eax,%edx + p[i++] = 0xc2; + p[i++] = 0xc1; // sar $0x5,%edx // key >> 5; + p[i++] = 0xfa; + p[i++] = 0x05; + p[i++] = 0x29; // sub %edx,%eax // key -= key >> 5; + p[i++] = 0xd0; + p[i++] = 0x89; // mov %eax,%edx + p[i++] = 0xc2; + p[i++] = 0xc1; // sar $0x3,%edx // key >> 3; + p[i++] = 0xfa; + p[i++] = 0x03; + p[i++] = 0x29; // sub %edx,%eax // key -= key >> 3; + p[i++] = 0xd0; + p[i++] = 0x25; // and $0xff,%eax // key &= 0xFF; + p[i++] = 0xff; + p[i++] = 0x00; + p[i++] = 0x00; + p[i++] = 0x00; + p[i++] = 0x8b; // mov (flush_counter),%ecx // %ecx = counter = flush_counter; + p[i++] = 0x0d; + *((DWORD*) &p[i]) = (DWORD)&flush_counter; + i += sizeof(DWORD); + p[i++] = 0x8b; // mov (thread_hints,%eax,4),%eax // %edx = pThread = thread_hints[key]; + p[i++] = 0x14; + p[i++] = 0x85; + *((DWORD*) &p[i]) = (DWORD)&thread_hints; + i += sizeof(DWORD); + p[i++] = 0x39; // cmp %esp,offsetof(CPalThread,tlsInfo)+offsetof(CThreadTLSInfo,minStack)(%edx) + // if ((size_t)pThread->tlsInfo.minStack <= sp) + p[i++] = 0xa2; + *((DWORD*) &p[i]) = (DWORD)(PAL_safe_offsetof(CPalThread,tlsInfo)+PAL_safe_offsetof(CThreadTLSInfo,minStack)); + i += sizeof(DWORD); + p[i++] = 0x77; // ja CallInternalGetCurrentThreadSlow: + p[i++] = 0x19; + p[i++] = 0x3b; // cmp offsetof(CPalThread,tlsInfo)+offsetof(CThreadTLSInfo,maxStack)(%edx),%esp + // if (sp < (size_t)pThread->tlsInfo.maxStack) + p[i++] = 0xa2; + *((DWORD*) &p[i]) = (DWORD)(PAL_safe_offsetof(CPalThread,tlsInfo)+PAL_safe_offsetof(CThreadTLSInfo,maxStack)); + i += sizeof(DWORD); + p[i++] = 0x73; // jae CallInternalGetCurrentThreadSlow: + p[i++] = 0x11; + p[i++] = 0x39; // cmp (flush_counter),%ecx // if (counter == flush_counter) + p[i++] = 0x0d; + *((DWORD*) &p[i]) = (DWORD)&flush_counter; + i += sizeof(DWORD); + p[i++] = 0x75; // jne CallInternalGetCurrentThreadSlow: + p[i++] = 0x09; + if (dwTlsIndex != THREAD_OBJECT_TLS_INDEX) + { + p[i++] = 0x8b; // mov offsetof(pThread->tlsSlots[dwTlsIndex])(%edx),%eax // %eax = pThread->tlsSlots[dwTlsIndex]; + p[i++] = 0x82; + *((DWORD*) &p[i]) = (DWORD)(PAL_safe_offsetof(CPalThread,tlsInfo)+PAL_safe_offsetof(CThreadTLSInfo,tlsSlots[dwTlsIndex])); + i += sizeof(DWORD); + } + else + { + p[i++] = 0x89; // mov %edx,%eax // %eax = pThread; + p[i++] = 0xd0; + p[i++] = 0x90; // nop + p[i++] = 0x90; // nop + p[i++] = 0x90; // nop + p[i++] = 0x90; // nop + } + p[i++] = 0x5a; // pop %edx + p[i++] = 0x59; // pop %ecx + p[i++] = 0xc3; // ret + // CallInternalGetCurrentThreadSlow: + p[i++] = 0x5a; // pop %edx + p[i++] = 0x59; // pop %ecx + p[i++] = 0x8d; // lea (thread_hints,%eax,4),%eax // %eax = &thread_hints[key]; + p[i++] = 0x04; + p[i++] = 0x85; + *((DWORD*) &p[i]) = (DWORD)&thread_hints; + i += sizeof(DWORD); + p[i++] = 0x55; // push %ebp + p[i++] = 0x89; // mov %esp,%ebp + p[i++] = 0xe5; + p[i++] = 0x51; // push %ecx + p[i++] = 0x89; // mov %esp,%ecx // this is the reference esp - need to match the reference esp used in the fast path. + p[i++] = 0xe1; + p[i++] = 0x52; // push %edx +#ifdef __APPLE__ + // establish 16-byte stack alignment + p[i++] = 0x83; // subl $8,%esp + p[i++] = 0xec; + p[i++] = 0x08; +#endif + p[i++] = 0x50; // push %eax // store &thread_hints[key] on stack as 2nd argument; + p[i++] = 0x51; // push %ecx // reference esp - The 1st argument for call to InternalGetCurrentThreadSlow. + p[i++] = 0xe8; // call InternalGetCurrentThreadSlow + *((DWORD*) &p[i]) = (DWORD)&InternalGetCurrentThreadSlow - (DWORD)(&p[i+sizeof(DWORD)]); + i += sizeof(DWORD); +#ifdef __APPLE__ + p[i++] = 0x83; // addl $16,%esp + p[i++] = 0xc4; + p[i++] = 0x10; +#else + p[i++] = 0x83; // addl $8,%esp + p[i++] = 0xc4; + p[i++] = 0x08; +#endif + if (dwTlsIndex != THREAD_OBJECT_TLS_INDEX) + { + p[i++] = 0x8b; // mov offsetof(pThread->tlsSlots[dwTlsIndex])(%eax),%eax // %eax = pThread->tlsSlots[dwTlsIndex]; + p[i++] = 0x80; + *((DWORD*) &p[i]) = (DWORD)(PAL_safe_offsetof(CPalThread,tlsInfo)+PAL_safe_offsetof(CThreadTLSInfo,tlsSlots[dwTlsIndex])); + i += sizeof(DWORD); + } + p[i++] = 0x5a; // pop %edx + p[i++] = 0x59; // pop %ecx + p[i++] = 0xc9; // leave + p[i++] = 0xc3; // ret + + if (i > TLS_OPTIMIZED_GETTER_SIZE) + { + ASSERT("Invalid TLS_OPTIMIZED_GETTER_SIZE %d\n", i); + } + + DBG_FlushInstructionCache(p, TLS_OPTIMIZED_GETTER_SIZE * sizeof(BYTE)); + + Ret = (PAL_POPTIMIZEDTLSGETTER)p; + + return Ret; +#endif // BIT64 else +} + +/*++ +Function: + TLSFreeOptimizedGetter + + Frees a function created by MakeOptimizedTlsGetter(). +--*/ +VOID +CorUnix::TLSFreeOptimizedGetter( + IN PAL_POPTIMIZEDTLSGETTER pOptimizedTlsGetter) +{ + InternalFree(InternalGetCurrentThread(), (void *)pOptimizedTlsGetter); +} + +#endif // USE_OPTIMIZEDTLSGETTER diff --git a/src/pal/src/arch/amd64/processor.cpp b/src/pal/src/arch/amd64/processor.cpp new file mode 100644 index 0000000..ac3d448 --- /dev/null +++ b/src/pal/src/arch/amd64/processor.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. +// See the LICENSE file in the project root for more information. + +/*++ + + + +Module Name: + + processor.cpp + +Abstract: + + Implementation of processor related functions for the Intel x86/x64 + platforms. These functions are processor dependent. + + + +--*/ + +#include "pal/palinternal.h" + +/*++ +Function: +YieldProcessor + +The YieldProcessor function signals to the processor to give resources +to threads that are waiting for them. This macro is only effective on +processors that support technology allowing multiple threads running +on a single processor, such as Intel's Hyper-Threading technology. + +--*/ +void +PALAPI +YieldProcessor( + VOID) +{ + __asm__ __volatile__ ( + "rep\n" + "nop" + ); +} + +/*++ +Function: +XmmYmmStateSupport + +Check if OS has enabled both XMM and YMM state support + +Return value: +1 if XMM and YMM are enabled, 0 otherwise +--*/ +extern "C" unsigned int XmmYmmStateSupport() +{ + unsigned int eax; + __asm(" xgetbv\n" \ + : "=a"(eax) /*output in eax*/\ + : "c"(0) /*inputs - 0 in ecx*/\ + : "eax", "edx" /* registers that are clobbered*/ + ); + // Check OS has enabled both XMM and YMM state support + return ((eax & 0x06) == 0x06) ? 1 : 0; +} diff --git a/src/pal/src/arch/arm/exceptionhelper.S b/src/pal/src/arch/arm/exceptionhelper.S index ed1c9c3..76cdcba 100644 --- a/src/pal/src/arch/arm/exceptionhelper.S +++ b/src/pal/src/arch/arm/exceptionhelper.S @@ -10,7 +10,7 @@ // EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT - // Ported from src/pal/src/arch/i386/exceptionhelper.S + // Ported from src/pal/src/arch/amd64/exceptionhelper.S push_nonvol_reg {r7} /* FP. x64-RBP */ ldr r4, [r0, #(CONTEXT_R4)] diff --git a/src/pal/src/arch/i386/asmconstants.h b/src/pal/src/arch/i386/asmconstants.h index 182c119..ff763ef 100644 --- a/src/pal/src/arch/i386/asmconstants.h +++ b/src/pal/src/arch/i386/asmconstants.h @@ -2,80 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#ifdef BIT64 - -#define CONTEXT_AMD64 0x100000 - -#define CONTEXT_CONTROL 1 // SegSs, Rsp, SegCs, Rip, and EFlags -#define CONTEXT_INTEGER 2 // Rax, Rcx, Rdx, Rbx, Rbp, Rsi, Rdi, R8-R15 -#define CONTEXT_SEGMENTS 4 // SegDs, SegEs, SegFs, SegGs -#define CONTEXT_FLOATING_POINT 8 -#define CONTEXT_DEBUG_REGISTERS 16 // Dr0-Dr3 and Dr6-Dr7 - -#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) - -#define CONTEXT_XSTATE 64 - -#define CONTEXT_ContextFlags 6*8 -#define CONTEXT_SegCs CONTEXT_ContextFlags+8 -#define CONTEXT_SegDs CONTEXT_SegCs+2 -#define CONTEXT_SegEs CONTEXT_SegDs+2 -#define CONTEXT_SegFs CONTEXT_SegEs+2 -#define CONTEXT_SegGs CONTEXT_SegFs+2 -#define CONTEXT_SegSs CONTEXT_SegGs+2 -#define CONTEXT_EFlags CONTEXT_SegSs+2 -#define CONTEXT_Dr0 CONTEXT_EFlags+4 -#define CONTEXT_Dr1 CONTEXT_Dr0+8 -#define CONTEXT_Dr2 CONTEXT_Dr1+8 -#define CONTEXT_Dr3 CONTEXT_Dr2+8 -#define CONTEXT_Dr6 CONTEXT_Dr3+8 -#define CONTEXT_Dr7 CONTEXT_Dr6+8 -#define CONTEXT_Rax CONTEXT_Dr7+8 -#define CONTEXT_Rcx CONTEXT_Rax+8 -#define CONTEXT_Rdx CONTEXT_Rcx+8 -#define CONTEXT_Rbx CONTEXT_Rdx+8 -#define CONTEXT_Rsp CONTEXT_Rbx+8 -#define CONTEXT_Rbp CONTEXT_Rsp+8 -#define CONTEXT_Rsi CONTEXT_Rbp+8 -#define CONTEXT_Rdi CONTEXT_Rsi+8 -#define CONTEXT_R8 CONTEXT_Rdi+8 -#define CONTEXT_R9 CONTEXT_R8+8 -#define CONTEXT_R10 CONTEXT_R9+8 -#define CONTEXT_R11 CONTEXT_R10+8 -#define CONTEXT_R12 CONTEXT_R11+8 -#define CONTEXT_R13 CONTEXT_R12+8 -#define CONTEXT_R14 CONTEXT_R13+8 -#define CONTEXT_R15 CONTEXT_R14+8 -#define CONTEXT_Rip CONTEXT_R15+8 -#define CONTEXT_FltSave CONTEXT_Rip+8 -#define FLOATING_SAVE_AREA_SIZE 4*8+24*16+96 -#define CONTEXT_Xmm0 CONTEXT_FltSave+10*16 -#define CONTEXT_Xmm1 CONTEXT_Xmm0+16 -#define CONTEXT_Xmm2 CONTEXT_Xmm1+16 -#define CONTEXT_Xmm3 CONTEXT_Xmm2+16 -#define CONTEXT_Xmm4 CONTEXT_Xmm3+16 -#define CONTEXT_Xmm5 CONTEXT_Xmm4+16 -#define CONTEXT_Xmm6 CONTEXT_Xmm5+16 -#define CONTEXT_Xmm7 CONTEXT_Xmm6+16 -#define CONTEXT_Xmm8 CONTEXT_Xmm7+16 -#define CONTEXT_Xmm9 CONTEXT_Xmm8+16 -#define CONTEXT_Xmm10 CONTEXT_Xmm9+16 -#define CONTEXT_Xmm11 CONTEXT_Xmm10+16 -#define CONTEXT_Xmm12 CONTEXT_Xmm11+16 -#define CONTEXT_Xmm13 CONTEXT_Xmm12+16 -#define CONTEXT_Xmm14 CONTEXT_Xmm13+16 -#define CONTEXT_Xmm15 CONTEXT_Xmm14+16 -#define CONTEXT_VectorRegister CONTEXT_FltSave+FLOATING_SAVE_AREA_SIZE -#define CONTEXT_VectorControl CONTEXT_VectorRegister+16*26 -#define CONTEXT_DebugControl CONTEXT_VectorControl+8 -#define CONTEXT_LastBranchToRip CONTEXT_DebugControl+8 -#define CONTEXT_LastBranchFromRip CONTEXT_LastBranchToRip+8 -#define CONTEXT_LastExceptionToRip CONTEXT_LastBranchFromRip+8 -#define CONTEXT_LastExceptionFromRip CONTEXT_LastExceptionToRip+8 -#define CONTEXT_Size CONTEXT_LastExceptionFromRip+8 - -#else // BIT64 - #define CONTEXT_ContextFlags 0 #define CONTEXT_FLOATING_POINT 8 #define CONTEXT_FloatSave 7*4 @@ -102,5 +28,3 @@ #define CONTEXT_Xmm5 CONTEXT_Xmm4+16 #define CONTEXT_Xmm6 CONTEXT_Xmm5+16 #define CONTEXT_Xmm7 CONTEXT_Xmm6+16 - -#endif // BIT64 diff --git a/src/pal/src/arch/i386/context2.S b/src/pal/src/arch/i386/context2.S index 0e93e81..16cbcc8 100644 --- a/src/pal/src/arch/i386/context2.S +++ b/src/pal/src/arch/i386/context2.S @@ -1,259 +1,151 @@ // 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. -// -// Implementation of _CONTEXT_CaptureContext for the Intel x86 platform. -// This function is processor dependent. It is used by exception handling, -// and is always apply to the current thread. -// .intel_syntax noprefix #include "unixasmmacros.inc" #include "asmconstants.h" -#ifdef BIT64 - -#define IRETFRAME_Rip 0 -#define IRETFRAME_SegCs IRETFRAME_Rip+8 -#define IRETFRAME_EFlags IRETFRAME_SegCs+8 -#define IRETFRAME_Rsp IRETFRAME_EFlags+8 -#define IRETFRAME_SegSs IRETFRAME_Rsp+8 -#define IRetFrameLength IRETFRAME_SegSs+8 -#define IRetFrameLengthAligned 16*((IRetFrameLength+8)/16) - -// Incoming: -// RDI: Context* +// +// Implementation of CONTEXT_CaptureContext for the Intel x86 platform. +// +// extern void CONTEXT_CaptureContext(LPCONTEXT lpContext); +// +// This function is processor-dependent. It is used by exception handling, +// and is always apply to the current thread. // LEAF_ENTRY CONTEXT_CaptureContext, _TEXT - // Save processor flags before calling any of the following 'test' instructions - // because they will modify state of some flags - push_eflags - END_PROLOGUE + // Store + push eax + push ebx + + // The stack will contain the following elements on the top of + // the caller's stack + // [ebx] / esp + 00 + // [eax] / esp + 04 + // [ret] / esp + 08 + // [arg0: lpContext] / esp + 12 + + mov eax, [esp + 12] // eax will point to lpContext + + // Capture INTEGER registers + mov ebx, [esp + 4] + mov [eax + CONTEXT_Eax], ebx + mov ebx, [esp] + mov [eax + CONTEXT_Ebx], ebx + mov [eax + CONTEXT_Ecx], ecx + mov [eax + CONTEXT_Edx], edx + mov [eax + CONTEXT_Esi], esi + mov [eax + CONTEXT_Edi], edi + + // Capture CONTROL registers + mov [eax + CONTEXT_Ebp], ebp + lea ebx, [esp + 12] + mov [eax + CONTEXT_Esp], ebx + mov ebx, [esp + 8] + mov [eax + CONTEXT_Eip], ebx + + push cs + xor ebx, ebx + pop bx + mov [eax + CONTEXT_SegCs], ebx + + push ss + xor ebx, ebx + pop bx + mov [eax + CONTEXT_SegSs], ebx - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_INTEGER - je LOCAL_LABEL(Done_CONTEXT_INTEGER) - mov [rdi + CONTEXT_Rdi], rdi - mov [rdi + CONTEXT_Rsi], rsi - mov [rdi + CONTEXT_Rbx], rbx - mov [rdi + CONTEXT_Rdx], rdx - mov [rdi + CONTEXT_Rcx], rcx - mov [rdi + CONTEXT_Rax], rax - mov [rdi + CONTEXT_Rbp], rbp - mov [rdi + CONTEXT_R8], r8 - mov [rdi + CONTEXT_R9], r9 - mov [rdi + CONTEXT_R10], r10 - mov [rdi + CONTEXT_R11], r11 - mov [rdi + CONTEXT_R12], r12 - mov [rdi + CONTEXT_R13], r13 - mov [rdi + CONTEXT_R14], r14 - mov [rdi + CONTEXT_R15], r15 -LOCAL_LABEL(Done_CONTEXT_INTEGER): - - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_CONTROL - je LOCAL_LABEL(Done_CONTEXT_CONTROL) - - // Return address is @ (RSP + 8) - mov rdx, [rsp + 8] - mov [rdi + CONTEXT_Rip], rdx -.att_syntax - mov %cs, CONTEXT_SegCs(%rdi) -.intel_syntax noprefix - // Get the value of EFlags that was pushed on stack at the beginning of the function - mov rdx, [rsp] - mov [rdi + CONTEXT_EFlags], edx - lea rdx, [rsp + 16] - mov [rdi + CONTEXT_Rsp], rdx -.att_syntax - mov %ss, CONTEXT_SegSs(%rdi) -.intel_syntax noprefix -LOCAL_LABEL(Done_CONTEXT_CONTROL): + pushf + xor ebx, ebx + pop bx + mov [eax + CONTEXT_EFlags], ebx - // Need to double check this is producing the right result - // also that FFSXR (fast save/restore) is not turned on - // otherwise it omits the xmm registers. - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT + test BYTE PTR [eax + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT je LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT) - fxsave [rdi + CONTEXT_FltSave] + // Capture FPU status + fnsave [eax + CONTEXT_FloatSave] + frstor [eax + CONTEXT_FloatSave] LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT): - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_DEBUG_REGISTERS - je LOCAL_LABEL(Done_CONTEXT_DEBUG_REGISTERS) - mov rdx, dr0 - mov [rdi + CONTEXT_Dr0], rdx - mov rdx, dr1 - mov [rdi + CONTEXT_Dr1], rdx - mov rdx, dr2 - mov [rdi + CONTEXT_Dr2], rdx - mov rdx, dr3 - mov [rdi + CONTEXT_Dr3], rdx - mov rdx, dr6 - mov [rdi + CONTEXT_Dr6], rdx - mov rdx, dr7 - mov [rdi + CONTEXT_Dr7], rdx -LOCAL_LABEL(Done_CONTEXT_DEBUG_REGISTERS): - - free_stack 8 - ret + test BYTE PTR [eax + CONTEXT_ContextFlags], CONTEXT_EXTENDED_REGISTERS + je LOCAL_LABEL(Done_CONTEXT_EXTENDED_REGISTERS) + movdqu [eax + CONTEXT_Xmm0], xmm0 + movdqu [eax + CONTEXT_Xmm1], xmm1 + movdqu [eax + CONTEXT_Xmm2], xmm2 + movdqu [eax + CONTEXT_Xmm3], xmm3 + movdqu [eax + CONTEXT_Xmm4], xmm4 + movdqu [eax + CONTEXT_Xmm5], xmm5 + movdqu [eax + CONTEXT_Xmm6], xmm6 + movdqu [eax + CONTEXT_Xmm7], xmm7 +LOCAL_LABEL(Done_CONTEXT_EXTENDED_REGISTERS): + + // Restore + pop ebx + pop eax + ret 4 LEAF_END CONTEXT_CaptureContext, _TEXT LEAF_ENTRY RtlCaptureContext, _TEXT - mov DWORD PTR [rdi + CONTEXT_ContextFlags], (CONTEXT_AMD64 | CONTEXT_FULL | CONTEXT_SEGMENTS) + push eax + mov eax, [esp + 8] + mov DWORD PTR [eax + CONTEXT_ContextFlags], (CONTEXT_FLOATING_POINT) + pop eax jmp C_FUNC(CONTEXT_CaptureContext) LEAF_END RtlCaptureContext, _TEXT LEAF_ENTRY RtlRestoreContext, _TEXT - push_nonvol_reg rbp - alloc_stack (IRetFrameLengthAligned) - - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_DEBUG_REGISTERS - je LOCAL_LABEL(Done_Restore_CONTEXT_DEBUG_REGISTERS) - mov rdx, [rdi + CONTEXT_Dr0] - mov dr0, rdx - mov rdx, [rdi + CONTEXT_Dr1] - mov dr1, rdx - mov rdx, [rdi + CONTEXT_Dr2] - mov dr2, rdx - mov rdx, [rdi + CONTEXT_Dr3] - mov dr3, rdx - mov rdx, [rdi + CONTEXT_Dr6] - mov dr6, rdx - mov rdx, [rdi + CONTEXT_Dr7] - mov dr7, rdx -LOCAL_LABEL(Done_Restore_CONTEXT_DEBUG_REGISTERS): + mov eax, [esp + 4] - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT + test BYTE PTR [eax + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT je LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT) - fxrstor [rdi + CONTEXT_FltSave] + frstor [eax + CONTEXT_FloatSave] LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT): - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_XSTATE - je LOCAL_LABEL(Done_Restore_CONTEXT_XSTATE) - - // Restore the extended state (for now, this is just the upper halves of YMM registers) - vinsertf128 ymm0, ymm0, xmmword ptr [rdi + (CONTEXT_VectorRegister + 0 * 16)], 1 - vinsertf128 ymm1, ymm1, xmmword ptr [rdi + (CONTEXT_VectorRegister + 1 * 16)], 1 - vinsertf128 ymm2, ymm2, xmmword ptr [rdi + (CONTEXT_VectorRegister + 2 * 16)], 1 - vinsertf128 ymm3, ymm3, xmmword ptr [rdi + (CONTEXT_VectorRegister + 3 * 16)], 1 - vinsertf128 ymm4, ymm4, xmmword ptr [rdi + (CONTEXT_VectorRegister + 4 * 16)], 1 - vinsertf128 ymm5, ymm5, xmmword ptr [rdi + (CONTEXT_VectorRegister + 5 * 16)], 1 - vinsertf128 ymm6, ymm6, xmmword ptr [rdi + (CONTEXT_VectorRegister + 6 * 16)], 1 - vinsertf128 ymm7, ymm7, xmmword ptr [rdi + (CONTEXT_VectorRegister + 7 * 16)], 1 - vinsertf128 ymm8, ymm8, xmmword ptr [rdi + (CONTEXT_VectorRegister + 8 * 16)], 1 - vinsertf128 ymm9, ymm9, xmmword ptr [rdi + (CONTEXT_VectorRegister + 9 * 16)], 1 - vinsertf128 ymm10, ymm10, xmmword ptr [rdi + (CONTEXT_VectorRegister + 10 * 16)], 1 - vinsertf128 ymm11, ymm11, xmmword ptr [rdi + (CONTEXT_VectorRegister + 11 * 16)], 1 - vinsertf128 ymm12, ymm12, xmmword ptr [rdi + (CONTEXT_VectorRegister + 12 * 16)], 1 - vinsertf128 ymm13, ymm13, xmmword ptr [rdi + (CONTEXT_VectorRegister + 13 * 16)], 1 - vinsertf128 ymm14, ymm14, xmmword ptr [rdi + (CONTEXT_VectorRegister + 14 * 16)], 1 - vinsertf128 ymm15, ymm15, xmmword ptr [rdi + (CONTEXT_VectorRegister + 15 * 16)], 1 -LOCAL_LABEL(Done_Restore_CONTEXT_XSTATE): - - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_CONTROL - je LOCAL_LABEL(Done_Restore_CONTEXT_CONTROL) - - // The control registers are restored via the iret instruction - // so we build the frame for the iret on the stack. -#ifdef __APPLE__ -.att_syntax - // On OSX, we cannot read SS via the thread_get_context and RtlRestoreContext - // needs to be used on context extracted by thread_get_context. So we - // don't change the SS. - mov %ss, %ax -.intel_syntax noprefix -#else - mov ax, [rdi + CONTEXT_SegSs] -#endif - mov [rsp + IRETFRAME_SegSs], ax - mov rax, [rdi + CONTEXT_Rsp] - mov [rsp + IRETFRAME_Rsp], rax - mov eax, [rdi + CONTEXT_EFlags] - mov [rsp + IRETFRAME_EFlags], eax - mov ax, [rdi + CONTEXT_SegCs] - mov [rsp + IRETFRAME_SegCs], ax - mov rax, [rdi + CONTEXT_Rip] - mov [rsp + IRETFRAME_Rip], rax - -LOCAL_LABEL(Done_Restore_CONTEXT_CONTROL): - // Remember the result of the test for the CONTEXT_CONTROL - push_eflags - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_INTEGER - je LOCAL_LABEL(Done_Restore_CONTEXT_INTEGER) - mov rsi, [rdi + CONTEXT_Rsi] - mov rbx, [rdi + CONTEXT_Rbx] - mov rdx, [rdi + CONTEXT_Rdx] - mov rcx, [rdi + CONTEXT_Rcx] - mov rax, [rdi + CONTEXT_Rax] - mov rbp, [rdi + CONTEXT_Rbp] - mov r8, [rdi + CONTEXT_R8] - mov r9, [rdi + CONTEXT_R9] - mov r10, [rdi + CONTEXT_R10] - mov r11, [rdi + CONTEXT_R11] - mov r12, [rdi + CONTEXT_R12] - mov r13, [rdi + CONTEXT_R13] - mov r14, [rdi + CONTEXT_R14] - mov r15, [rdi + CONTEXT_R15] - mov rdi, [rdi + CONTEXT_Rdi] -LOCAL_LABEL(Done_Restore_CONTEXT_INTEGER): - - // Restore the result of the test for the CONTEXT_CONTROL - pop_eflags - je LOCAL_LABEL(No_Restore_CONTEXT_CONTROL) - // The function was asked to restore the control registers, so - // we perform iretq that restores them all. - // We don't return to the caller in this case. - iretq -LOCAL_LABEL(No_Restore_CONTEXT_CONTROL): - - // The function was not asked to restore the control registers - // so we return back to the caller. - free_stack (IRetFrameLengthAligned) - pop_nonvol_reg rbp - ret + test BYTE PTR [eax + CONTEXT_ContextFlags], CONTEXT_EXTENDED_REGISTERS + je LOCAL_LABEL(Done_Restore_CONTEXT_EXTENDED_REGISTERS) + movdqu xmm0, [eax + CONTEXT_Xmm0] + movdqu xmm1, [eax + CONTEXT_Xmm1] + movdqu xmm2, [eax + CONTEXT_Xmm2] + movdqu xmm3, [eax + CONTEXT_Xmm3] + movdqu xmm4, [eax + CONTEXT_Xmm4] + movdqu xmm5, [eax + CONTEXT_Xmm5] + movdqu xmm6, [eax + CONTEXT_Xmm6] + movdqu xmm7, [eax + CONTEXT_Xmm7] +LOCAL_LABEL(Done_Restore_CONTEXT_EXTENDED_REGISTERS): + + // Restore CONTROL register(s) + mov ecx, [eax + CONTEXT_Eip] + mov [esp], ecx + + mov ecx, [eax + CONTEXT_Esp] + push ecx + mov ecx, [eax + CONTEXT_Ebp] + push ecx + + pop ebp + pop esp + + // Restore INTEGER register(s) + mov ecx, [eax + CONTEXT_Edi] + push ecx + mov ecx, [eax + CONTEXT_Esi] + push ecx + mov ecx, [eax + CONTEXT_Edx] + push ecx + mov ecx, [eax + CONTEXT_Ecx] + push ecx + mov ecx, [eax + CONTEXT_Ebx] + push ecx + mov ecx, [eax + CONTEXT_Eax] + push ecx + + pop eax + pop ebx + pop ecx + pop edx + pop esi + pop edi + + ret 8 LEAF_END RtlRestoreContext, _TEXT -#else - - .globl C_FUNC(CONTEXT_CaptureContext) -C_FUNC(CONTEXT_CaptureContext): - push %eax - mov 8(%esp), %eax - mov %edi, CONTEXT_Edi(%eax) - mov %esi, CONTEXT_Esi(%eax) - mov %ebx, CONTEXT_Ebx(%eax) - mov %edx, CONTEXT_Edx(%eax) - mov %ecx, CONTEXT_Ecx(%eax) - pop %ecx - mov %ecx, CONTEXT_Eax(%eax) - mov %ebp, CONTEXT_Ebp(%eax) - mov (%esp), %edx - mov %edx, CONTEXT_Eip(%eax) - push %cs - pop %edx - mov %edx, CONTEXT_SegCs(%eax) - pushf - pop %edx - mov %edx, CONTEXT_EFlags(%eax) - lea 4(%esp), %edx - mov %edx, CONTEXT_Esp(%eax) - push %ss - pop %edx - mov %edx, CONTEXT_SegSs(%eax) - testb $CONTEXT_FLOATING_POINT, CONTEXT_ContextFlags(%eax) - je 0f - fnsave CONTEXT_FloatSave(%eax) - frstor CONTEXT_FloatSave(%eax) -0: - testb $CONTEXT_EXTENDED_REGISTERS, CONTEXT_ContextFlags(%eax) - je 2f - movdqu %xmm0, CONTEXT_Xmm0(%eax) - movdqu %xmm1, CONTEXT_Xmm1(%eax) - movdqu %xmm2, CONTEXT_Xmm2(%eax) - movdqu %xmm3, CONTEXT_Xmm3(%eax) - movdqu %xmm4, CONTEXT_Xmm4(%eax) - movdqu %xmm5, CONTEXT_Xmm5(%eax) - movdqu %xmm6, CONTEXT_Xmm6(%eax) - movdqu %xmm7, CONTEXT_Xmm7(%eax) -2: - ret - -#endif diff --git a/src/pal/src/arch/i386/exceptionhelper.S b/src/pal/src/arch/i386/exceptionhelper.S index b7b34ac..2061be2 100644 --- a/src/pal/src/arch/i386/exceptionhelper.S +++ b/src/pal/src/arch/i386/exceptionhelper.S @@ -8,35 +8,36 @@ ////////////////////////////////////////////////////////////////////////// // -// This function creates a stack frame right below the target frame, restores all callee -// saved registers from the passed in context, sets the RSP to that frame and sets the -// return address to the target frame's RIP. -// Then it uses the ThrowExceptionHelper to throw the passed in exception from that context. // EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); +// +// This function creates a stack frame right below the target frame, restores all callee +// saved registers from the passed in context, sets the SP to that frame and sets the +// return address to the target frame's IP. +// Then it uses the ThrowExceptionHelper to throw the passed in exception from that context. +// +////////////////////////////////////////////////////////////////////////// + LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT - // Save the RBP to the stack so that the unwind can work at the instruction after - // loading the RBP from the context, but before loading the RSP from the context. - push_nonvol_reg rbp - mov r12, [rdi + CONTEXT_R12] - mov r13, [rdi + CONTEXT_R13] - mov r14, [rdi + CONTEXT_R14] - mov r15, [rdi + CONTEXT_R15] - mov rbx, [rdi + CONTEXT_Rbx] - mov rbp, [rdi + CONTEXT_Rbp] - mov rsp, [rdi + CONTEXT_Rsp] - // The RSP was set to the target frame's value, so the current function's - // CFA is now right at the RSP. + push ebp + mov eax, [esp + 12] // ebx: PAL_SEHException * + mov ebx, [esp + 8] // eax: CONTEXT * + + mov ebp, [ebx + CONTEXT_Ebp] + mov esp, [ebx + CONTEXT_Esp] + + // The ESP is re-initialized as the target frame's value, so the current function's + // CFA is now right at the ESP. .cfi_def_cfa_offset 0 - // Indicate that now that we have moved the RSP to the target address, - // the RBP is no longer saved in the current stack frame. - .cfi_restore rbp + // Indicate that now that we have moved the RSP to the target address, + // the EBP is no longer saved in the current stack frame. + .cfi_restore ebp - mov rax, [rdi + CONTEXT_Rip] + // Store PAL_SEHException as the first argument + push eax // Store return address to the stack - push_register rax - // The PAL_SEHException pointer - mov rdi, rsi + mov ebx, [ebx + CONTEXT_Eip] + push ebx jmp EXTERNAL_C_FUNC(ThrowExceptionHelper) LEAF_END ThrowExceptionFromContextInternal, _TEXT diff --git a/src/pal/src/arch/i386/optimizedtls.cpp b/src/pal/src/arch/i386/optimizedtls.cpp deleted file mode 100644 index 910a6eb..0000000 --- a/src/pal/src/arch/i386/optimizedtls.cpp +++ /dev/null @@ -1,237 +0,0 @@ -// 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. - -/*++ - - - -Module Name: - - optimizedtls.cpp - -Abstract: - - Implementation of platform-specific Thread local storage functions. - - - ---*/ - -#include "pal/thread.hpp" -#include "pal/malloc.hpp" - -#include - -#include "pal/dbgmsg.h" -#include "pal/misc.h" -#include "pal/debug.h" - -#include - -using namespace CorUnix; - -SET_DEFAULT_DEBUG_CHANNEL(THREAD); - -#if defined(USE_OPTIMIZEDTLSGETTER) - -#define PAL_safe_offsetof(s,m) ((size_t)((ptrdiff_t)&(char&)(((s *)64)->m))-64) - -/*++ -Function: - CorUnix::TLSMakeOptimizedGetter - - Creates a platform-optimized version of TlsGetValue compiled - for a particular index. - - Generates the hot part of CorUnix::InternalGetCurrentThread - as a chunk of highly optimized machine-specific code at runtime. - - Check the difference between CorUnix::InternalGetCurrentThread and - CorUnix::InternalGetCurrentThreadSlow to see the C/C++ code that matches - the code generated by this function. ---*/ -PAL_POPTIMIZEDTLSGETTER -CorUnix::TLSMakeOptimizedGetter( - IN CPalThread* pThread, - IN DWORD dwTlsIndex) -{ -#ifdef BIT64 -#pragma unused(pThread, dwTlsIndex) - ERROR("TLSMakeOptimizedGetter not rewritten for amd64 yet."); - return NULL; -#else - PAL_POPTIMIZEDTLSGETTER Ret = NULL; - BYTE* p; - int i = 0; - -#ifdef __APPLE__ -#define TLS_OPTIMIZED_GETTER_SIZE 118 -#else -#define TLS_OPTIMIZED_GETTER_SIZE 115 -#endif - - p = (BYTE*)InternalMalloc(pThread, TLS_OPTIMIZED_GETTER_SIZE * sizeof(BYTE)); - - if (p == NULL) - { - return Ret; - } - - // Need to preserve %ecx, %edx, and %esi registers as specified in - // GetThreadGeneric(void) in vm/i386/asmhelpers.s - p[i++] = 0x51; // push %ecx - p[i++] = 0x52; // push %edx - p[i++] = 0x89; // mov %esp,%eax // %eax = sp; - p[i++] = 0xe0; - p[i++] = 0xc1; // shr $0x11,%eax // sp >> 17; - p[i++] = 0xe8; - p[i++] = 0x11; - p[i++] = 0x89; // mov %eax,%edx // key = sp >> 17; - p[i++] = 0xc2; - p[i++] = 0xc1; // sar $0x7,%edx // key >> 7; - p[i++] = 0xfa; - p[i++] = 0x07; - p[i++] = 0x29; // sub %edx,%eax // key -= key >> 7; - p[i++] = 0xd0; - p[i++] = 0x89; // mov %eax,%edx - p[i++] = 0xc2; - p[i++] = 0xc1; // sar $0x5,%edx // key >> 5; - p[i++] = 0xfa; - p[i++] = 0x05; - p[i++] = 0x29; // sub %edx,%eax // key -= key >> 5; - p[i++] = 0xd0; - p[i++] = 0x89; // mov %eax,%edx - p[i++] = 0xc2; - p[i++] = 0xc1; // sar $0x3,%edx // key >> 3; - p[i++] = 0xfa; - p[i++] = 0x03; - p[i++] = 0x29; // sub %edx,%eax // key -= key >> 3; - p[i++] = 0xd0; - p[i++] = 0x25; // and $0xff,%eax // key &= 0xFF; - p[i++] = 0xff; - p[i++] = 0x00; - p[i++] = 0x00; - p[i++] = 0x00; - p[i++] = 0x8b; // mov (flush_counter),%ecx // %ecx = counter = flush_counter; - p[i++] = 0x0d; - *((DWORD*) &p[i]) = (DWORD)&flush_counter; - i += sizeof(DWORD); - p[i++] = 0x8b; // mov (thread_hints,%eax,4),%eax // %edx = pThread = thread_hints[key]; - p[i++] = 0x14; - p[i++] = 0x85; - *((DWORD*) &p[i]) = (DWORD)&thread_hints; - i += sizeof(DWORD); - p[i++] = 0x39; // cmp %esp,offsetof(CPalThread,tlsInfo)+offsetof(CThreadTLSInfo,minStack)(%edx) - // if ((size_t)pThread->tlsInfo.minStack <= sp) - p[i++] = 0xa2; - *((DWORD*) &p[i]) = (DWORD)(PAL_safe_offsetof(CPalThread,tlsInfo)+PAL_safe_offsetof(CThreadTLSInfo,minStack)); - i += sizeof(DWORD); - p[i++] = 0x77; // ja CallInternalGetCurrentThreadSlow: - p[i++] = 0x19; - p[i++] = 0x3b; // cmp offsetof(CPalThread,tlsInfo)+offsetof(CThreadTLSInfo,maxStack)(%edx),%esp - // if (sp < (size_t)pThread->tlsInfo.maxStack) - p[i++] = 0xa2; - *((DWORD*) &p[i]) = (DWORD)(PAL_safe_offsetof(CPalThread,tlsInfo)+PAL_safe_offsetof(CThreadTLSInfo,maxStack)); - i += sizeof(DWORD); - p[i++] = 0x73; // jae CallInternalGetCurrentThreadSlow: - p[i++] = 0x11; - p[i++] = 0x39; // cmp (flush_counter),%ecx // if (counter == flush_counter) - p[i++] = 0x0d; - *((DWORD*) &p[i]) = (DWORD)&flush_counter; - i += sizeof(DWORD); - p[i++] = 0x75; // jne CallInternalGetCurrentThreadSlow: - p[i++] = 0x09; - if (dwTlsIndex != THREAD_OBJECT_TLS_INDEX) - { - p[i++] = 0x8b; // mov offsetof(pThread->tlsSlots[dwTlsIndex])(%edx),%eax // %eax = pThread->tlsSlots[dwTlsIndex]; - p[i++] = 0x82; - *((DWORD*) &p[i]) = (DWORD)(PAL_safe_offsetof(CPalThread,tlsInfo)+PAL_safe_offsetof(CThreadTLSInfo,tlsSlots[dwTlsIndex])); - i += sizeof(DWORD); - } - else - { - p[i++] = 0x89; // mov %edx,%eax // %eax = pThread; - p[i++] = 0xd0; - p[i++] = 0x90; // nop - p[i++] = 0x90; // nop - p[i++] = 0x90; // nop - p[i++] = 0x90; // nop - } - p[i++] = 0x5a; // pop %edx - p[i++] = 0x59; // pop %ecx - p[i++] = 0xc3; // ret - // CallInternalGetCurrentThreadSlow: - p[i++] = 0x5a; // pop %edx - p[i++] = 0x59; // pop %ecx - p[i++] = 0x8d; // lea (thread_hints,%eax,4),%eax // %eax = &thread_hints[key]; - p[i++] = 0x04; - p[i++] = 0x85; - *((DWORD*) &p[i]) = (DWORD)&thread_hints; - i += sizeof(DWORD); - p[i++] = 0x55; // push %ebp - p[i++] = 0x89; // mov %esp,%ebp - p[i++] = 0xe5; - p[i++] = 0x51; // push %ecx - p[i++] = 0x89; // mov %esp,%ecx // this is the reference esp - need to match the reference esp used in the fast path. - p[i++] = 0xe1; - p[i++] = 0x52; // push %edx -#ifdef __APPLE__ - // establish 16-byte stack alignment - p[i++] = 0x83; // subl $8,%esp - p[i++] = 0xec; - p[i++] = 0x08; -#endif - p[i++] = 0x50; // push %eax // store &thread_hints[key] on stack as 2nd argument; - p[i++] = 0x51; // push %ecx // reference esp - The 1st argument for call to InternalGetCurrentThreadSlow. - p[i++] = 0xe8; // call InternalGetCurrentThreadSlow - *((DWORD*) &p[i]) = (DWORD)&InternalGetCurrentThreadSlow - (DWORD)(&p[i+sizeof(DWORD)]); - i += sizeof(DWORD); -#ifdef __APPLE__ - p[i++] = 0x83; // addl $16,%esp - p[i++] = 0xc4; - p[i++] = 0x10; -#else - p[i++] = 0x83; // addl $8,%esp - p[i++] = 0xc4; - p[i++] = 0x08; -#endif - if (dwTlsIndex != THREAD_OBJECT_TLS_INDEX) - { - p[i++] = 0x8b; // mov offsetof(pThread->tlsSlots[dwTlsIndex])(%eax),%eax // %eax = pThread->tlsSlots[dwTlsIndex]; - p[i++] = 0x80; - *((DWORD*) &p[i]) = (DWORD)(PAL_safe_offsetof(CPalThread,tlsInfo)+PAL_safe_offsetof(CThreadTLSInfo,tlsSlots[dwTlsIndex])); - i += sizeof(DWORD); - } - p[i++] = 0x5a; // pop %edx - p[i++] = 0x59; // pop %ecx - p[i++] = 0xc9; // leave - p[i++] = 0xc3; // ret - - if (i > TLS_OPTIMIZED_GETTER_SIZE) - { - ASSERT("Invalid TLS_OPTIMIZED_GETTER_SIZE %d\n", i); - } - - DBG_FlushInstructionCache(p, TLS_OPTIMIZED_GETTER_SIZE * sizeof(BYTE)); - - Ret = (PAL_POPTIMIZEDTLSGETTER)p; - - return Ret; -#endif // BIT64 else -} - -/*++ -Function: - TLSFreeOptimizedGetter - - Frees a function created by MakeOptimizedTlsGetter(). ---*/ -VOID -CorUnix::TLSFreeOptimizedGetter( - IN PAL_POPTIMIZEDTLSGETTER pOptimizedTlsGetter) -{ - InternalFree(InternalGetCurrentThread(), (void *)pOptimizedTlsGetter); -} - -#endif // USE_OPTIMIZEDTLSGETTER diff --git a/src/pal/src/config.h.in b/src/pal/src/config.h.in index 7a53c8c..4d21fb7 100644 --- a/src/pal/src/config.h.in +++ b/src/pal/src/config.h.in @@ -43,7 +43,6 @@ #cmakedefine01 HAVE_LOCALTIME_R #cmakedefine01 HAVE_GMTIME_R #cmakedefine01 HAVE_TIMEGM -#cmakedefine01 HAVE__SNWPRINTF #cmakedefine01 HAVE_POLL #cmakedefine01 HAVE_STATVFS #cmakedefine01 HAVE_THREAD_SELF diff --git a/src/pal/src/configure.cmake b/src/pal/src/configure.cmake index cc38bc8..a53e0db 100644 --- a/src/pal/src/configure.cmake +++ b/src/pal/src/configure.cmake @@ -13,7 +13,7 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL SunOS) set(CMAKE_REQUIRED_INCLUDES /opt/local/include) endif() if(NOT CMAKE_SYSTEM_NAME STREQUAL Darwin AND NOT CMAKE_SYSTEM_NAME STREQUAL FreeBSD AND NOT CMAKE_SYSTEM_NAME STREQUAL NetBSD) - set(CMAKE_REQUIRED_DEFINITIONS "-D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L") + set(CMAKE_REQUIRED_DEFINITIONS "-D_BSD_SOURCE -D_SVID_SOURCE -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L") endif() list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_FILE_OFFSET_BITS=64) @@ -33,7 +33,15 @@ check_include_files(sys/lwp.h HAVE_SYS_LWP_H) check_include_files(lwp.h HAVE_LWP_H) check_include_files(libunwind.h HAVE_LIBUNWIND_H) check_include_files(runetype.h HAVE_RUNETYPE_H) + +if(NOT CMAKE_SYSTEM_NAME STREQUAL FreeBSD AND NOT CMAKE_SYSTEM_NAME STREQUAL NetBSD) + set(CMAKE_REQUIRED_FLAGS "-ldl") +endif() check_include_files(lttng/tracepoint.h HAVE_LTTNG_TRACEPOINT_H) +if(NOT CMAKE_SYSTEM_NAME STREQUAL FreeBSD AND NOT CMAKE_SYSTEM_NAME STREQUAL NetBSD) + unset(CMAKE_REQUIRED_FLAGS) +endif() + check_include_files(uuid/uuid.h HAVE_LIBUUID_H) check_include_files(sys/sysctl.h HAVE_SYS_SYSCTL_H) check_include_files(gnu/lib-names.h HAVE_GNU_LIBNAMES_H) @@ -62,7 +70,6 @@ check_function_exists(sysconf HAVE_SYSCONF) check_function_exists(localtime_r HAVE_LOCALTIME_R) check_function_exists(gmtime_r HAVE_GMTIME_R) check_function_exists(timegm HAVE_TIMEGM) -check_function_exists(_snwprintf HAVE__SNWPRINTF) check_function_exists(poll HAVE_POLL) check_function_exists(statvfs HAVE_STATVFS) check_function_exists(thread_self HAVE_THREAD_SELF) diff --git a/src/pal/src/cruntime/lstr.cpp b/src/pal/src/cruntime/lstr.cpp index 2267d84..4502b02 100644 --- a/src/pal/src/cruntime/lstr.cpp +++ b/src/pal/src/cruntime/lstr.cpp @@ -24,141 +24,6 @@ Abstract: SET_DEFAULT_DEBUG_CHANNEL(CRT); - -/*++ -Function: - lstrcatW - -The lstrcat function appends one string to another. - -Parameters - -lpString1 [in/out] Pointer to a null-terminated string. The buffer must be large - enough to contain both strings. -lpString2 [in] Pointer to the null-terminated string to be appended to the - string specified in the lpString1 parameter. - -Return Values - -If the function succeeds, the return value is a pointer to the buffer. -If the function fails, the return value is NULL. - ---*/ -LPWSTR -PALAPI -lstrcatW( - IN OUT LPWSTR lpString1, - IN LPCWSTR lpString2) -{ - LPWSTR lpStart = lpString1; - - PERF_ENTRY(lstrcatW); - ENTRY("lstrcatW (lpString1=%p (%S), lpString2=%p (%S))\n", - lpString1?lpString1:W16_NULLSTRING, - lpString1?lpString1:W16_NULLSTRING, lpString2?lpString2:W16_NULLSTRING, lpString2?lpString2:W16_NULLSTRING); - - if (lpString1 == NULL) - { - ERROR("invalid lpString1 argument\n"); - LOGEXIT("lstrcatW returning LPWSTR NULL\n"); - PERF_EXIT(lstrcatW); - return NULL; - } - - if (lpString2 == NULL) - { - ERROR("invalid lpString2 argument\n"); - LOGEXIT("lstrcatW returning LPWSTR NULL\n"); - PERF_EXIT(lstrcatW); - return NULL; - } - - /* find end of source string */ - while (*lpString1) - { - lpString1++; - } - - /* concatenate new string */ - while(*lpString2) - { - *lpString1++ = *lpString2++; - } - - /* add terminating null */ - *lpString1 = '\0'; - - LOGEXIT("lstrcatW returning LPWSTR %p (%S)\n", lpStart, lpStart); - PERF_EXIT(lstrcatW); - return lpStart; -} - - -/*++ -Function: - lstrcpyW - -The lstrcpy function copies a string to a buffer. - -To copy a specified number of characters, use the lstrcpyn function. - -Parameters - -lpString1 [out] Pointer to a buffer to receive the contents of the string pointed - to by the lpString2 parameter. The buffer must be large enough to - contain the string, including the terminating null character. - -lpString2 [in] Pointer to the null-terminated string to be copied. - -Return Values - -If the function succeeds, the return value is a pointer to the buffer. -If the function fails, the return value is NULL. - ---*/ -LPWSTR -PALAPI -lstrcpyW( - OUT LPWSTR lpString1, - IN LPCWSTR lpString2) -{ - LPWSTR lpStart = lpString1; - - PERF_ENTRY(lstrcpyW); - ENTRY("lstrcpyW (lpString1=%p, lpString2=%p (%S))\n", - lpString1?lpString1:W16_NULLSTRING, lpString2?lpString2:W16_NULLSTRING, lpString2?lpString2:W16_NULLSTRING); - - if (lpString1 == NULL) - { - ERROR("invalid lpString1 argument\n"); - LOGEXIT("lstrcpyW returning LPWSTR NULL\n"); - PERF_EXIT(lstrcpyW); - return NULL; - } - - if (lpString2 == NULL) - { - ERROR("invalid lpString2 argument\n"); - LOGEXIT("lstrcpyW returning LPWSTR NULL\n"); - PERF_EXIT(lstrcpyW); - return NULL; - } - - /* copy source string to destination string */ - while(*lpString2) - { - *lpString1++ = *lpString2++; - } - - /* add terminating null */ - *lpString1 = '\0'; - - LOGEXIT("lstrcpyW returning LPWSTR %p (%S)\n", lpStart, lpStart); - PERF_EXIT(lstrcpyW); - return lpStart; -} - - /*++ Function: lstrlenA @@ -239,78 +104,3 @@ lstrlenW( PERF_EXIT(lstrlenW); return nChar; } - - -/*++ -Function: - lstrcpynW - -The lstrcpyn function copies a specified number of characters from a -source string into a buffer. - -Parameters - -lpString1 [out] Pointer to a buffer into which the function copies characters. - The buffer must be large enough to contain the number of TCHARs - specified by iMaxLength, including room for a terminating null character. -lpString2 [in] Pointer to a null-terminated string from which the function copies - characters. -iMaxLength [in] Specifies the number of TCHARs to be copied from the string pointed - to by lpString2 into the buffer pointed to by lpString1, including a - terminating null character. - -Return Values - -If the function succeeds, the return value is a pointer to the buffer. -If the function fails, the return value is NULL. - ---*/ -LPWSTR -PALAPI -lstrcpynW( - OUT LPWSTR lpString1, - IN LPCWSTR lpString2, - IN int iMaxLength) -{ - LPWSTR lpStart = lpString1; - - PERF_ENTRY(lstrcpynW); - ENTRY("lstrcpynW (lpString1=%p, lpString2=%p (%S), iMaxLength=%d)\n", - lpString1?lpString1:W16_NULLSTRING, lpString2?lpString2:W16_NULLSTRING, lpString2?lpString2:W16_NULLSTRING, iMaxLength); - - if (lpString1 == NULL) - { - ERROR("invalid lpString1 argument\n"); - LOGEXIT("lstrcpynW returning LPWSTR NULL\n"); - PERF_EXIT(lstrcpynW); - return NULL; - } - - if (lpString2 == NULL) - { - ERROR("invalid lpString2 argument\n"); - LOGEXIT("lstrcpynW returning LPWSTR NULL\n"); - PERF_EXIT(lstrcpynW); - return NULL; - } - - /* copy source string to destination string */ - while(iMaxLength > 1 && *lpString2) - { - *lpString1++ = *lpString2++; - iMaxLength--; - } - - /* add terminating null */ - if (iMaxLength > 0) - { - *lpString1 = '\0'; - } - - LOGEXIT("lstrcpynW returning LPWSTR %p (%S)\n", lpStart, lpStart); - PERF_EXIT(lstrcpynW); - return lpStart; - -} - - diff --git a/src/pal/src/cruntime/math.cpp b/src/pal/src/cruntime/math.cpp index 7075fd6..08f4192 100644 --- a/src/pal/src/cruntime/math.cpp +++ b/src/pal/src/cruntime/math.cpp @@ -35,6 +35,12 @@ Abstract: #define IS_DBL_NEGZERO(x) (((*((INT64*)((void*)&x))) & I64(0xFFFFFFFFFFFFFFFF)) == I64(0x8000000000000000)) +#define PAL_NAN_FLT sqrtf(-1.0f) +#define PAL_POSINF_FLT -logf(0.0f) +#define PAL_NEGINF_FLT logf(0.0f) + +#define IS_FLT_NEGZERO(x) (((*((INT32*)((void*)&x))) & 0xFFFFFFFF) == 0x80000000) + SET_DEFAULT_DEBUG_CHANNEL(CRT); /*++ @@ -422,3 +428,364 @@ PALIMPORT double __cdecl PAL_pow(double x, double y) PERF_EXIT(pow); return ret; } + +/*++ +Function: + _finitef + +Determines whether given single-precision floating point value is finite. + +Return Value + +_finitef returns a nonzero value (TRUE) if its argument x is not +infinite, that is, if -INF < x < +INF. It returns 0 (FALSE) if the +argument is infinite or a NaN. + +Parameter + +x Single-precision floating-point value + +--*/ +int __cdecl _finitef(float x) +{ + int ret; + PERF_ENTRY(_finitef); + ENTRY("_finitef (x=%f)\n", x); + +#if defined(_IA64_) && defined (_HPUX_) + ret = !isnan(x) && (x != PAL_POSINF_FLT) && (x != PAL_NEGINF_FLT); +#else + ret = isfinite(x); +#endif + + LOGEXIT("_finitef returns int %d\n", ret); + PERF_EXIT(_finitef); + return ret; +} + +/*++ +Function: + _isnanf + +See MSDN doc +--*/ +int __cdecl _isnanf(float x) +{ + int ret; + PERF_ENTRY(_isnanf); + ENTRY("_isnanf (x=%f)\n", x); + + ret = isnan(x); + + LOGEXIT("_isnanf returns int %d\n", ret); + PERF_EXIT(_isnanf); + return ret; +} + +/*++ +Function: + _copysignf + +See MSDN doc +--*/ +float __cdecl _copysignf(float x, float y) +{ + float ret; + PERF_ENTRY(_copysignf); + ENTRY("_copysignf (x=%f, y=%f)\n", x, y); + + ret = copysign(x, y); + + LOGEXIT("_copysignf returns float %f\n", ret); + PERF_EXIT(_copysignf); + return ret; +} + +/*++ +Function: + acosf + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_acosf(float x) +{ + float ret; + PERF_ENTRY(acosf); + ENTRY("acosf (x=%f)\n", x); + +#if !HAVE_COMPATIBLE_ACOS + errno = 0; +#endif // HAVE_COMPATIBLE_ACOS + + ret = acosf(x); + +#if !HAVE_COMPATIBLE_ACOS + if (errno == EDOM) + { + ret = PAL_NAN_FLT; // NaN + } +#endif // HAVE_COMPATIBLE_ACOS + + LOGEXIT("acosf returns float %f\n", ret); + PERF_EXIT(acosf); + return ret; +} + +/*++ +Function: + asinf + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_asinf(float x) +{ + float ret; + PERF_ENTRY(asinf); + ENTRY("asinf (x=%f)\n", x); + +#if !HAVE_COMPATIBLE_ASIN + errno = 0; +#endif // HAVE_COMPATIBLE_ASIN + + ret = asinf(x); + +#if !HAVE_COMPATIBLE_ASIN + if (errno == EDOM) + { + ret = PAL_NAN_FLT; // NaN + } +#endif // HAVE_COMPATIBLE_ASIN + + LOGEXIT("asinf returns float %f\n", ret); + PERF_EXIT(asinf); + return ret; +} + +/*++ +Function: + atan2f + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_atan2f(float y, float x) +{ + float ret; + PERF_ENTRY(atan2f); + ENTRY("atan2f (y=%f, x=%f)\n", y, x); + +#if !HAVE_COMPATIBLE_ATAN2 + errno = 0; +#endif // !HAVE_COMPATIBLE_ATAN2 + + ret = atan2f(y, x); + +#if !HAVE_COMPATIBLE_ATAN2 + if ((errno == EDOM) && (x == 0.0f) && (y == 0.0f)) + { + const float sign_x = copysign(1.0f, x); + const float sign_y = copysign(1.0f, y); + + if (sign_x > 0) + { + ret = copysign(0.0f, sign_y); + } + else + { + ret = copysign(atan2f(0.0f, -1.0f), sign_y); + } + } +#endif // !HAVE_COMPATIBLE_ATAN2 + + LOGEXIT("atan2f returns float %f\n", ret); + PERF_EXIT(atan2f); + return ret; +} + +/*++ +Function: + expf + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_expf(float x) +{ + float ret; + PERF_ENTRY(expf); + ENTRY("expf (x=%f)\n", x); + +#if !HAVE_COMPATIBLE_EXP + if (x == 1.0f) + { + ret = M_E; + } + else + { +#endif // HAVE_COMPATIBLE_EXP + + ret = expf(x); + +#if !HAVE_COMPATIBLE_EXP + } +#endif // HAVE_COMPATIBLE_EXP + + LOGEXIT("expf returns float %f\n", ret); + PERF_EXIT(expf); + return ret; +} + +/*++ +Function: + logf + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_logf(float x) +{ + float ret; + PERF_ENTRY(logf); + ENTRY("logf (x=%f)\n", x); + +#if !HAVE_COMPATIBLE_LOG + errno = 0; +#endif // !HAVE_COMPATIBLE_LOG + + ret = logf(x); + +#if !HAVE_COMPATIBLE_LOG + if ((errno == EDOM) && (x < 0)) + { + ret = PAL_NAN_FLT; // NaN + } +#endif // !HAVE_COMPATIBLE_LOG + + LOGEXIT("logf returns float %f\n", ret); + PERF_EXIT(logf); + return ret; +} + +/*++ +Function: + log10f + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_log10f(float x) +{ + float ret; + PERF_ENTRY(log10f); + ENTRY("log10f (x=%f)\n", x); + +#if !HAVE_COMPATIBLE_LOG10 + errno = 0; +#endif // !HAVE_COMPATIBLE_LOG10 + + ret = log10f(x); + +#if !HAVE_COMPATIBLE_LOG10 + if ((errno == EDOM) && (x < 0)) + { + ret = PAL_NAN_FLT; // NaN + } +#endif // !HAVE_COMPATIBLE_LOG10 + + LOGEXIT("log10f returns float %f\n", ret); + PERF_EXIT(log10f); + return ret; +} + +/*++ +Function: + powf + +See MSDN. +--*/ +PALIMPORT float __cdecl PAL_powf(float x, float y) +{ + float ret; + PERF_ENTRY(powf); + ENTRY("powf (x=%f, y=%f)\n", x, y); + +#if !HAVE_COMPATIBLE_POW + if ((y == PAL_POSINF_FLT) && !isnan(x)) // +Inf + { + if (x == 1.0f) + { + ret = x; + } + else if (x == -1.0f) + { + ret = PAL_NAN_FLT; // NaN + } + else if ((x > -1.0f) && (x < 1.0f)) + { + ret = 0.0f; + } + else + { + ret = PAL_POSINF_FLT; // +Inf + } + } + else if ((y == PAL_NEGINF_FLT) && !isnan(x)) // -Inf + { + if (x == 1.0f) + { + ret = x; + } + else if (x == -1.0f) + { + ret = PAL_NAN_FLT; // NaN + } + else if ((x > -1.0f) && (x < 1.0f)) + { + ret = PAL_POSINF_FLT; // +Inf + } + else + { + ret = 0.0f; + } + } + else if (IS_FLT_NEGZERO(x) && (y == -1.0f)) + { + ret = PAL_NEGINF_FLT; // -Inf + } + else if ((x == 0.0f) && (y < 0.0f)) + { + ret = PAL_POSINF_FLT; // +Inf + } + else +#endif // !HAVE_COMPATIBLE_POW + + if ((y == 0.0f) && isnan(x)) + { + // Windows returns NaN for powf(NaN, 0), but POSIX specifies + // a return value of 1 for that case. We need to return + // the same result as Windows. + ret = PAL_NAN_FLT; + } + else + { + ret = powf(x, y); + } + +#if !HAVE_VALID_NEGATIVE_INF_POW + if ((ret == PAL_POSINF_FLT) && (x < 0) && isfinite(x) && (ceilf(y / 2) != floorf(y / 2))) + { + ret = PAL_NEGINF_FLT; // -Inf + } +#endif // !HAVE_VALID_NEGATIVE_INF_POW + +#if !HAVE_VALID_POSITIVE_INF_POW + /* + * The (ceil(y/2) == floor(y/2)) test is slower, but more robust for platforms where large y + * will return the wrong result for ((long) y % 2 == 0). See PAL_pow(double) above for more details. + */ + if ((ret == PAL_NEGINF_FLT) && (x < 0) && isfinite(x) && (ceilf(y / 2) == floorf(y / 2))) + { + ret = PAL_POSINF_FLT; // +Inf + } +#endif // !HAVE_VALID_POSITIVE_INF_POW + + LOGEXIT("powf returns float %f\n", ret); + PERF_EXIT(powf); + return ret; +} diff --git a/src/pal/src/cruntime/mbstring.cpp b/src/pal/src/cruntime/mbstring.cpp index dd4bcbb..ace2aa5 100644 --- a/src/pal/src/cruntime/mbstring.cpp +++ b/src/pal/src/cruntime/mbstring.cpp @@ -37,60 +37,6 @@ SET_DEFAULT_DEBUG_CHANNEL(CRT); /*++ Function: - _mbslen - -Determines the number of characters (code points) in a multibyte -character string. - -Parameters - -string Points to a multibyte character string. - -Return Values - -The mbslen subroutine returns the number of multibyte characters in a -multibyte character string. It returns 0 if the string parameter -points to a null character or if a character cannot be formed from the -string pointed to by this parameter. - ---*/ -size_t -__cdecl -_mbslen( - const unsigned char *string) -{ - size_t ret = 0; - CPINFO cpinfo; - PERF_ENTRY(_mbslen); - ENTRY("_mbslen (string=%p (%s))\n", string, string); - - if (string) - { - if (GetCPInfo(CP_ACP, &cpinfo) && cpinfo.MaxCharSize == 1) - { - ret = strlen((const char*)string); - } - else - { - while (*string) - { - if (IsDBCSLeadByteEx(CP_ACP, *string)) - { - ++string; - } - ++string; - ++ret; - } - } - } - - LOGEXIT("_mbslen returning size_t %u\n", ret); - PERF_EXIT(_mbslen); - return ret; -} - -/*++ -Function: _mbsinc Return Value diff --git a/src/pal/src/cruntime/path.cpp b/src/pal/src/cruntime/path.cpp index e5b955e..4925af5 100644 --- a/src/pal/src/cruntime/path.cpp +++ b/src/pal/src/cruntime/path.cpp @@ -33,488 +33,6 @@ Revision History: SET_DEFAULT_DEBUG_CHANNEL(CRT); - -/* ON_ERROR. A Helper macro for _?splitpath functions. */ -#define ON_ERROR if ( drive ) \ - {\ - drive[0] = 0;\ - }\ - if(dir)\ - {\ - dir[0] = 0;\ - }\ - if(fname)\ - {\ - fname[0] = 0;\ - }\ - if(ext)\ - {\ - ext[0] = 0;\ - }\ - goto done;\ - -/*++ -Function: - _wsplitpath - -See MSDN doc. - -Notes : - This implementation ignores drive letters as they should not be - present. If the drive argument is non-NULL, it always returns an empty - string. - File names in which the only period is at the beginning (like .bashrc, but - not .bashrc.bak), the file is treated as having no extension - (fname is ".bashrc", ext is "") - ---*/ -void -__cdecl -_wsplitpath( - const wchar_16 *dospath, - wchar_16 *drive, - wchar_16 *dir, - wchar_16 *fname, - wchar_16 *ext) -{ - WCHAR path[_MAX_PATH+1]; - LPCWSTR slash_ptr = NULL; - LPCWSTR period_ptr = NULL; - INT size = 0; - - PERF_ENTRY(_wsplitpath); - ENTRY("_wsplitpath (path=%p (%S), drive=%p, dir=%p, fname=%p, ext=%p)\n", - dospath?dospath:W16_NULLSTRING, - dospath?dospath:W16_NULLSTRING, drive, dir, fname, ext); - - /* Do performance intensive error checking only in debug builds. - - NOTE: This function must fail predictably across all platforms. - Under Windows this function throw an access violation if NULL - was passed in as the value for path. - - */ -#if _DEBUG - if ( !dospath ) - { - ERROR( "path cannot be NULL!\n" ); - } -#endif - - if( lstrlenW( dospath ) >= _MAX_PATH ) - { - ERROR("Path length is > _MAX_PATH (%d)!\n", _MAX_PATH); - ON_ERROR; - } - - - PAL_wcscpy(path, dospath); - FILEDosToUnixPathW(path); - - /* no drive letters in the PAL */ - if( drive != NULL ) - { - drive[0] = 0; - } - - /* find last path separator char */ - slash_ptr = PAL_wcsrchr(path, '/'); - - if( slash_ptr == NULL ) - { - TRACE("No path separator in path\n"); - slash_ptr = path - 1; - } - /* find extension separator, if any */ - period_ptr = PAL_wcsrchr(path, '.'); - - /* make sure we only consider periods after the last path separator */ - if( period_ptr < slash_ptr ) - { - period_ptr = NULL; - } - - /* if the only period in the file is a leading period (denoting a hidden - file), don't treat what follows as an extension */ - if( period_ptr == slash_ptr+1 ) - { - period_ptr = NULL; - } - - if( period_ptr == NULL ) - { - TRACE("No extension in path\n"); - period_ptr = path + lstrlenW(path); - } - - size = slash_ptr - path + 1; - if( dir != NULL ) - { - INT i; - - if( (size + 1 ) > _MAX_DIR ) - { - ERROR("Directory component needs %d characters, _MAX_DIR is %d\n", - size+1, _MAX_DIR); - ON_ERROR; - } - - memcpy(dir, path, size*sizeof(WCHAR)); - dir[size] = 0; - - /* only allow / separators in returned path */ - i = 0; - while( dir[ i ] ) - { - if( dir[ i ] == '\\' ) - { - dir[i]='/'; - } - i++; - } - } - - size = period_ptr-slash_ptr-1; - if( fname != NULL ) - { - if( (size+1) > _MAX_FNAME ) - { - ERROR("Filename component needs %d characters, _MAX_FNAME is %d\n", - size+1, _MAX_FNAME); - ON_ERROR; - } - memcpy(fname, slash_ptr+1, size*sizeof(WCHAR)); - fname[size] = 0; - } - - size = 1 + lstrlenW( period_ptr ); - if( ext != NULL ) - { - if( size > _MAX_EXT ) - { - ERROR("Extension component needs %d characters, _MAX_EXT is %d\n", - size, _MAX_EXT); - ON_ERROR; - } - memcpy(ext, period_ptr, size*sizeof(WCHAR)); - ext[size-1] = 0; - } - - TRACE("Path components are '%S' '%S' '%S'\n", dir, fname, ext); - -done: - - LOGEXIT("_wsplitpath returns.\n"); - PERF_EXIT(_wsplitpath); -} - - -/*++ -Function: - _splitpath - -See description above for _wsplitpath. - ---*/ -void -__cdecl -_splitpath( - const char *path, - char *drive, - char *dir, - char *fname, - char *ext) -{ - WCHAR w_path[_MAX_PATH]; - WCHAR w_dir[_MAX_DIR]; - WCHAR w_fname[_MAX_FNAME]; - WCHAR w_ext[_MAX_EXT]; - - PERF_ENTRY(_splitpath); - ENTRY("_splitpath (path=%p (%s), drive=%p, dir=%p, fname=%p, ext=%p)\n", - path?path:"NULL", - path?path:"NULL", drive, dir, fname, ext); - - /* Do performance intensive error checking only in debug builds. - - NOTE: This function must fail predictably across all platforms. - Under Windows this function throw an access violation if NULL - was passed in as the value for path. - - */ -#if _DEBUG - if ( !path ) - { - ERROR( "path cannot be NULL!\n" ); - } - - if( strlen( path ) >= _MAX_PATH ) - { - ERROR( "Path length is > _MAX_PATH (%d)!\n", _MAX_PATH); - } -#endif - - /* no drive letters in the PAL */ - if(drive) - { - drive[0] = '\0'; - } - - if(0 == MultiByteToWideChar(CP_ACP, 0, path, -1, w_path, _MAX_PATH)) - { - ASSERT("MultiByteToWideChar failed!\n"); - ON_ERROR; - } - - /* Call up to Unicode version; pass NULL for parameters the caller doesn't - care about */ - _wsplitpath(w_path, NULL, dir?w_dir:NULL, - fname?w_fname:NULL, ext?w_ext:NULL); - - /* Convert result back to MultiByte; report conversion errors but don't - stop because of them */ - - if(dir) - { - if(0 == WideCharToMultiByte(CP_ACP, 0, w_dir, -1, dir, _MAX_DIR, - NULL, NULL)) - { - ASSERT("WideCharToMultiByte failed!\n"); - ON_ERROR; - } - } - if(fname) - { - if(0 == WideCharToMultiByte(CP_ACP, 0, w_fname, -1, fname, _MAX_FNAME, - NULL, NULL)) - { - ASSERT("WideCharToMultiByte failed!\n"); - ON_ERROR; - } - } - if(ext) - { - if(0 == WideCharToMultiByte(CP_ACP, 0, w_ext, -1, ext, _MAX_EXT, - NULL, NULL)) - { - ASSERT("WideCharToMultiByte failed!\n"); - ON_ERROR; - } - } - -done: - LOGEXIT("_splitpath returns.\n"); - PERF_EXIT(_splitpath); -} - - - -/*++ -Function: - _makepath - -See MSDN doc. - ---*/ -void -__cdecl -_makepath( - char *path, - const char *drive, - const char *dir, - const char *fname, - const char *ext) -{ - UINT Length = 0; - - PERF_ENTRY(_makepath); - ENTRY( "_makepath (path=%p, drive=%p (%s), dir=%p (%s), fname=%p (%s), ext=%p (%s))\n", - path, drive ? drive:"NULL", drive ? drive:"NULL", dir ? dir:"NULL", dir ? dir:"NULL", fname ? fname:"NULL", fname ? fname:"NULL", - ext ? ext:"NULL", - ext ? ext:"NULL"); - - path[ 0 ] = '\0'; - - /* According to the pal documentation, host operating systems that - don't support drive letters, the "drive" parameter must always be null. */ - if ( drive != NULL && drive[0] != '\0' ) - { - ASSERT( "The drive parameter must always be NULL on systems that don't" - "support drive letters. drive is being ignored!.\n" ); - } - - if ( dir != NULL && dir[ 0 ] != '\0' ) - { - UINT DirLength = strlen( dir ); - Length += DirLength ; - - if ( Length < _MAX_PATH ) - { - strncat( path, dir, DirLength ); - if ( dir[ DirLength - 1 ] != '/' && dir[ DirLength - 1 ] != '\\' ) - { - if ( Length + 1 < _MAX_PATH ) - { - path[ Length ] = '/'; - Length++; - path[ Length ] = '\0'; - } - else - { - goto Max_Path_Error; - } - } - } - else - { - goto Max_Path_Error; - } - } - - if ( fname != NULL && fname[ 0 ] != '\0' ) - { - UINT fNameLength = strlen( fname ); - Length += fNameLength; - - if ( Length < _MAX_PATH ) - { - strncat( path, fname, fNameLength ); - } - else - { - goto Max_Path_Error; - } - } - - if ( ext != NULL && ext[ 0 ] != '\0' ) - { - UINT ExtLength = strlen( ext ); - Length += ExtLength; - - if ( ext[ 0 ] != '.' ) - { - /* Add a '.' */ - if ( Length + 1 < _MAX_PATH ) - { - path[ Length - ExtLength ] = '.'; - Length++; - path[ Length - ExtLength ] = '\0'; - strncat( path, ext, ExtLength ); - } - else - { - goto Max_Path_Error; - } - } - else - { - /* Already has a '.' */ - if ( Length < _MAX_PATH ) - { - strncat( path, ext, ExtLength ); - } - else - { - goto Max_Path_Error; - } - } - } - - FILEDosToUnixPathA( path ); - LOGEXIT( "_makepath returning void.\n" ); - PERF_EXIT(_makepath); - return; - -Max_Path_Error: - - ERROR( "path cannot be greater then _MAX_PATH\n" ); - path[ 0 ] = '\0'; - LOGEXIT( "_makepath returning void \n" ); - PERF_EXIT(_makepath); - return; -} - -/*++ -Function: - _wmakepath - -See MSDN doc. - ---*/ -void -__cdecl -_wmakepath( - wchar_16 *path, - const wchar_16 *drive, - const wchar_16 *dir, - const wchar_16 *fname, - const wchar_16 *ext) -{ - CHAR Dir[ _MAX_DIR ]={0}; - CHAR FileName[ _MAX_FNAME ]={0}; - CHAR Ext[ _MAX_EXT ]={0}; - CHAR Path[ _MAX_PATH ]={0}; - - PERF_ENTRY(_wmakepath); - ENTRY("_wmakepath (path=%p, drive=%p (%S), dir=%p (%S), fname=%p (%S), ext=%p (%S))\n", - path, drive ? drive:W16_NULLSTRING, drive ? drive:W16_NULLSTRING, dir ? dir:W16_NULLSTRING, dir ? dir:W16_NULLSTRING, - fname ? fname:W16_NULLSTRING, - fname ? fname:W16_NULLSTRING, ext ? ext:W16_NULLSTRING, ext ? ext:W16_NULLSTRING); - - /* According to the pal documentation, host operating systems that - don't support drive letters, the "drive" parameter must always be null. */ - if ( drive != NULL && drive[0] != '\0' ) - { - ASSERT( "The drive parameter must always be NULL on systems that don't" - "support drive letters. drive is being ignored!.\n" ); - } - - if ((dir != NULL) && WideCharToMultiByte( CP_ACP, 0, dir, -1, Dir, - _MAX_DIR, NULL, NULL ) == 0 ) - { - ASSERT( "An error occurred while converting dir to multibyte." - "Possible error: Length of dir is greater than _MAX_DIR.\n" ); - goto error; - } - - if ((fname != NULL) && WideCharToMultiByte( CP_ACP, 0, fname, -1, FileName, - _MAX_FNAME, NULL, NULL ) == 0 ) - { - ASSERT( "An error occurred while converting fname to multibyte." - "Possible error: Length of fname is greater than _MAX_FNAME.\n" ); - goto error; - } - - if ((ext != NULL) && WideCharToMultiByte( CP_ACP, 0, ext, -1, Ext, - _MAX_EXT, NULL, NULL ) == 0 ) - { - ASSERT( "An error occurred while converting ext to multibyte." - "Possible error: Length of ext is greater than _MAX_EXT.\n" ); - goto error; - } - - /* Call up to the ANSI _makepath. */ - _makepath_s( Path, sizeof(Path), NULL, Dir, FileName, Ext ); - - if ( MultiByteToWideChar( CP_ACP, 0, Path, -1, path, _MAX_PATH ) == 0 ) - { - ASSERT( "An error occurred while converting the back wide char." - "Possible error: The length of combined path is greater " - "than _MAX_PATH.\n" ); - goto error; - } - - LOGEXIT("_wmakepath returns void\n"); - PERF_EXIT(_wmakepath); - return; - -error: - *path = '\0'; - LOGEXIT("_wmakepath returns void\n"); - PERF_EXIT(_wmakepath); -} - - /*++ Function: _fullpath diff --git a/src/pal/src/cruntime/printf.cpp b/src/pal/src/cruntime/printf.cpp index 2d9d6e4..c437b8e 100644 --- a/src/pal/src/cruntime/printf.cpp +++ b/src/pal/src/cruntime/printf.cpp @@ -277,124 +277,6 @@ PAL_vprintf( /*++ Function: - wsprintfA - -See MSDN doc. ---*/ -int -PALAPIV -wsprintfA( - OUT LPSTR buffer, - IN LPCSTR format, - ...) -{ - LONG Length; - va_list ap; - - PERF_ENTRY(wsprintfA); - ENTRY("wsprintfA (buffer=%p, format=%p (%s))\n", buffer, format, format); - - va_start(ap, format); - Length = InternalVsnprintf(CorUnix::InternalGetCurrentThread(), buffer, 1024, format, ap); - va_end(ap); - - LOGEXIT("wsprintfA returns int %d\n", Length); - PERF_EXIT(wsprintfA); - return Length; -} - -/*++ -Function: - wsprintfW - -See MSDN doc. ---*/ -int -PALAPIV -wsprintfW( - OUT LPWSTR buffer, - IN LPCWSTR format, - ...) -{ - LONG Length; - va_list ap; - - PERF_ENTRY(wsprintfW); - ENTRY("wsprintfW (buffer=%p, format=%p (%S))\n", buffer, format, format); - - va_start(ap, format); - Length = PAL__wvsnprintf(buffer, 1024, format, ap); - va_end(ap); - - LOGEXIT("wsprintfW returns int %d\n", Length); - PERF_EXIT(wsprintfW); - return Length; -} - - -/*++ -Function: - _snprintf - -See MSDN doc. ---*/ -int -__cdecl -_snprintf( - char *buffer, - size_t count, - const char *format, - ...) -{ - LONG Length; - va_list ap; - - PERF_ENTRY(_snprintf); - ENTRY("_snprintf (buffer=%p, count=%lu, format=%p (%s))\n", - buffer, (unsigned long) count, format, format); - - va_start(ap, format); - Length = InternalVsnprintf(CorUnix::InternalGetCurrentThread(), buffer, count, format, ap); - va_end(ap); - - LOGEXIT("_snprintf returns int %d\n", Length); - PERF_EXIT(_snprintf); - return Length; -} - - -/*++ -Function: - _snwprintf - -See MSDN doc. ---*/ -int -__cdecl -_snwprintf( - wchar_16 *buffer, - size_t count, - const wchar_16 *format, - ...) -{ - LONG Length; - va_list ap; - - PERF_ENTRY(_snwprintf); - ENTRY("_snwprintf (buffer=%p, count=%lu, format=%p (%S))\n", - buffer, (unsigned long) count, format, format); - - va_start(ap, format); - Length = PAL__wvsnprintf(buffer, count, format, ap); - va_end(ap); - - LOGEXIT("_snwprintf returns int %d\n", Length); - PERF_EXIT(_snwprintf); - return Length; -} - -/*++ -Function: fwprintf See MSDN doc. @@ -1483,63 +1365,6 @@ int PAL_wvsscanf(LPCWSTR Buffer, LPCWSTR Format, va_list ap) /*++ Function: - PAL_sscanf - -See MSDN doc. ---*/ -int -__cdecl -PAL_sscanf( - const char *buffer, - const char *format, - ...) -{ - int Length; - va_list ap; - - PERF_ENTRY(sscanf); - ENTRY("PAL_sscanf (buffer=%p (%s), format=%p (%s))\n", buffer, buffer, format, format); - - va_start(ap, format); - Length = PAL_vsscanf(buffer, format, ap); - va_end(ap); - - LOGEXIT("PAL_sscanf returns int %d\n", Length); - PERF_EXIT(sscanf); - return Length; -} - -/*++ -Function: - PAL_sprintf - -See MSDN doc. ---*/ -int -__cdecl -PAL_sprintf( - char *buffer, - const char *format, - ...) -{ - LONG Length; - va_list ap; - - PERF_ENTRY(sprintf); - ENTRY("PAL_sprintf (buffer=%p, format=%p (%s))\n", buffer, format, format); - - va_start(ap, format); - Length = InternalVsnprintf(CorUnix::InternalGetCurrentThread(), buffer, 0x7fffffff, format, ap); - va_end(ap); - - LOGEXIT("PAL_sprintf returns int %d\n", Length); - PERF_EXIT(sprintf); - return Length; -} - - -/*++ -Function: PAL_swprintf See MSDN doc. @@ -1649,33 +1474,6 @@ PAL_vswprintf(wchar_16 *buffer, } -/*++ -Function: - _vsnwprintf - -See MSDN doc. ---*/ -int -__cdecl -_vsnwprintf(wchar_16 *buffer, - size_t count, - const wchar_16 *format, - va_list argptr) -{ - LONG Length; - - PERF_ENTRY(_vsnwprintf); - ENTRY("_vsnwprintf (buffer=%p, count=%lu, format=%p (%S), argptr=%p)\n", - buffer, (unsigned long) count, format, format, argptr); - - Length = PAL__wvsnprintf(buffer, count, format, argptr); - - LOGEXIT("_vsnwprintf returns int %d\n", Length); - PERF_EXIT(_vsnwprintf); - - return Length; -} - #if SSCANF_CANNOT_HANDLE_MISSING_EXPONENT /*++ Function: diff --git a/src/pal/src/cruntime/string.cpp b/src/pal/src/cruntime/string.cpp index 23781d8..abe6d13 100644 --- a/src/pal/src/cruntime/string.cpp +++ b/src/pal/src/cruntime/string.cpp @@ -151,61 +151,6 @@ _strlwr( return orig; } - -/*++ -Function: - _swab - -Swaps bytes. - -Return Value - -None - -Parameters - -src Data to be copied and swapped -dest Storage location for swapped data -n Number of bytes to be copied and swapped - -Remarks - -The _swab function copies n bytes from src, swaps each pair of -adjacent bytes, and stores the result at dest. The integer n should be -an even number to allow for swapping. _swab is typically used to -prepare binary data for transfer to a machine that uses a different -byte order. - -Example - -char from[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; -char to[] = ".........................."; - -printf("Before:\n%s\n%s\n\n", from, to); -_swab(from, to, strlen(from)); -printf("After:\n%s\n%s\n\n", from, to); - -Before: -ABCDEFGHIJKLMNOPQRSTUVWXYZ -.......................... - -After: -ABCDEFGHIJKLMNOPQRSTUVWXYZ -BADCFEHGJILKNMPORQTSVUXWZY - ---*/ -void -__cdecl -_swab(char *src, char *dest, int n) -{ - PERF_ENTRY(_swab); - ENTRY("_swab (src=%p (%s), dest=%p (%s), n=%d)\n", src?src:"NULL", src?src:"NULL", dest?dest:"NULL", dest?dest:"NULL", n); - swab(src, dest, n); - LOGEXIT("_swab returning\n"); - PERF_EXIT(_swab); -} - - /*++ Function: PAL_strtoul diff --git a/src/pal/src/cruntime/wchar.cpp b/src/pal/src/cruntime/wchar.cpp index 2d244a6..3de065e 100644 --- a/src/pal/src/cruntime/wchar.cpp +++ b/src/pal/src/cruntime/wchar.cpp @@ -73,146 +73,6 @@ wtolower(wchar_16 c) } -/******************************************************************************* -Function: - Internal_i64tow - -Parameters: - value - - INT64 value to be converted to a string - string - - out buffer to place interger string - radix - - numeric base to convert to - isI64 - - TRUE if value is INT64, FALSE if value is a long - -Note: - - only a radix of ten (and value < 0) will result in a negative - sign in the output buffer -*******************************************************************************/ -LPWSTR Internal_i64tow(INT64 value, LPWSTR string, int radix, BOOL isI64) -{ - int length = 0; - int n; - int r; - UINT64 uval = value; - LPWSTR stringPtr = string; - int start = 0; - int end; - WCHAR tempCh; - - if (radix < 2 || radix > 36) - { - ASSERT( "Invalid radix, radix must be between 2 and 36\n" ); - SetLastError(ERROR_INVALID_PARAMETER); - return string; - } - if (FALSE == isI64) - { - uval = (ULONG) uval; - } - if (10 == radix && value < 0) - { - uval = value * -1; - } - if(0 == uval) - { - ++length; - *stringPtr++ = '0'; - } - else while (uval > 0) - { - ++length; - n = uval / radix; - r = uval - (n * radix); - uval /= radix; - if (r > 9) - { - *stringPtr++ = r + 87; - } - else - { - *stringPtr++ = r + 48; - } - } - if (10 == radix && value < 0) - { - *stringPtr++ = '-'; - ++length; - } - *stringPtr = 0; /* end the string */ - - /* reverse the string */ - end = length - 1; - while (start < end) - { - tempCh = string[start]; - string[start] = string[end]; - string[end] = tempCh; - ++start; - --end; - } - - return string; -} - -/*-- -Function: - _itow - -16-bit wide character version of the ANSI tolower() function. - - --*/ -wchar_16 * -__cdecl -_itow( - int value, - wchar_16 *string, - int radix) -{ - wchar_16 *ret; - - PERF_ENTRY(_itow); - ENTRY("_itow (value=%d, string=%p, radix=%d)\n", - value, string, radix); - - ret = Internal_i64tow(value, string, radix, FALSE); - - LOGEXIT("_itow returns wchar_t* %p\n", ret); - PERF_EXIT(_itow); - - return ret; -} - -/*-- -Function: - _i64tow - -See MSDN doc ---*/ -wchar_16 * - __cdecl -_i64tow( - __int64 value, - wchar_16 *string, - int radix) -{ - wchar_16 *ret; - - PERF_ENTRY(_i64tow); - ENTRY("_i64tow (value=%ld, string=%p, radix=%d)\n", - value, string, radix); - - ret = Internal_i64tow(value, string, radix, TRUE); - - LOGEXIT("_i64tow returns wchar_t* %p\n", ret); - PERF_EXIT(_i64tow); - - return ret; -} - - /*-- Function: _wtoi @@ -1558,77 +1418,6 @@ PAL_wcstod( const wchar_16 * nptr, wchar_16 **endptr ) } /*++ -Function : - - _ui64tow - -See MSDN for more details. ---*/ -wchar_16 * -__cdecl -_ui64tow( unsigned __int64 value , wchar_16 * string , int radix ) -{ - UINT ReversedIndex = 0; - WCHAR ReversedString[ 65 ]; - LPWSTR lpString = string; - UINT Index = 0; - - PERF_ENTRY(_ui64tow); - ENTRY( "_ui64tow( value=%I64d, string=%p (%S), radix=%d )\n", - value, string, string, radix ); - - if ( !string ) - { - ERROR( "string has to be a valid pointer.\n" ); - LOGEXIT( "_ui64tow returning NULL.\n" ); - PERF_EXIT(_ui64tow); - return NULL; - } - if ( radix < 2 || radix > 36 ) - { - ERROR( "radix has to be between 2 and 36.\n" ); - LOGEXIT( "_ui64tow returning NULL.\n" ); - PERF_EXIT(_ui64tow); - return NULL; - } - - if(0 == value) - { - ReversedString[0] = '0'; - Index++; - } - else while ( value ) - { - int temp = value % radix; - value /= radix; - - if ( temp < 10 ) - { - ReversedString[ Index ] = temp + '0'; - Index++; - } - else - { - ReversedString[ Index ] = temp - 10 + 'a'; - Index++; - } - } - - /* Reverse the string. */ - ReversedIndex = Index; - for ( Index = 0; ReversedIndex > 0; ReversedIndex--, Index++ ) - { - string[ Index ] = ReversedString[ ReversedIndex - 1 ]; - } - - string[ Index ] = '\0'; - LOGEXIT( "_ui64tow returning %p (%S).\n", lpString , lpString ); - PERF_EXIT(_ui64tow); - return lpString; -} - - -/*++ Function: iswdigit diff --git a/src/pal/src/debug/debug.cpp b/src/pal/src/debug/debug.cpp index 5461ac6..2f7d17c 100644 --- a/src/pal/src/debug/debug.cpp +++ b/src/pal/src/debug/debug.cpp @@ -92,29 +92,6 @@ static const char PAL_OUTPUTDEBUGSTRING[] = "PAL_OUTPUTDEBUGSTRING"; static const char PAL_RUN_ON_DEBUG_BREAK[] = "PAL_RUN_ON_DEBUG_BREAK"; #endif // ENABLE_RUN_ON_DEBUG_BREAK -/* ------------------- Static function prototypes ----------------------------*/ - -#if !HAVE_VM_READ && !HAVE_PROCFS_CTL && !HAVE_TTRACE -static int -DBGWriteProcMem_Int(DWORD processId, int *addr, int data); -static int -DBGWriteProcMem_IntWithMask(DWORD processId, int *addr, int data, - unsigned int mask); -#endif // !HAVE_VM_READ && !HAVE_PROCFS_CTL && !HAVE_TTRACE - -#if !HAVE_VM_READ && !HAVE_PROCFS_CTL - -static BOOL -DBGAttachProcess(CPalThread *pThread, HANDLE hProcess, DWORD dwProcessId); - -static BOOL -DBGDetachProcess(CPalThread *pThread, HANDLE hProcess, DWORD dwProcessId); - -static int -DBGSetProcessAttached(CPalThread *pThread, HANDLE hProcess, BOOL bAttach); - -#endif // !HAVE_VM_READ && !HAVE_PROCFS_CTL - extern "C" { /*++ @@ -566,457 +543,6 @@ SetThreadContext( return ret; } -#if !HAVE_VM_READ && !HAVE_PROCFS_CTL && !HAVE_TTRACE -/*++ -Function: - DBGWriteProcMem_Int - -Abstract - write one int to a process memory address - -Parameter - processId : process handle - addr : memory address where the int should be written - data : int to be written in addr - -Return - Return 1 if it succeeds, or 0 if it's fails ---*/ -static -int -DBGWriteProcMem_Int(IN DWORD processId, - IN int *addr, - IN int data) -{ - if (PAL_PTRACE( PAL_PT_WRITE_D, processId, addr, data ) == -1) - { - if (errno == EFAULT) - { - ERROR("ptrace(PT_WRITE_D, pid:%d caddr_t:%p data:%x) failed " - "errno:%d (%s)\n", processId, addr, data, errno, strerror(errno)); - SetLastError(ERROR_INVALID_ADDRESS); - } - else - { - ASSERT("ptrace(PT_WRITE_D, pid:%d caddr_t:%p data:%x) failed " - "errno:%d (%s)\n", processId, addr, data, errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - return 0; - } - - return 1; -} - -/*++ -Function: - DBGWriteProcMem_IntWithMask - -Abstract - write one int to a process memory address space using mask - -Parameter - processId : process ID - addr : memory address where the int should be written - data : int to be written in addr - mask : the mask used to write only a parts of data - -Return - Return 1 if it succeeds, or 0 if it's fails ---*/ -static -int -DBGWriteProcMem_IntWithMask(IN DWORD processId, - IN int *addr, - IN int data, - IN unsigned int mask ) -{ - int readInt; - - if (mask != ~0) - { - errno = 0; - if (((readInt = PAL_PTRACE( PAL_PT_READ_D, processId, addr, 0 )) == -1) - && errno) - { - if (errno == EFAULT) - { - ERROR("ptrace(PT_READ_D, pid:%d, caddr_t:%p, 0) failed " - "errno:%d (%s)\n", processId, addr, errno, strerror(errno)); - SetLastError(ERROR_INVALID_ADDRESS); - } - else - { - ASSERT("ptrace(PT_READ_D, pid:%d, caddr_t:%p, 0) failed " - "errno:%d (%s)\n", processId, addr, errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - - return 0; - } - data = (data & mask) | (readInt & ~mask); - } - return DBGWriteProcMem_Int(processId, addr, data); -} -#endif // !HAVE_VM_READ && !HAVE_PROCFS_CTL && !HAVE_TTRACE - -#if !HAVE_VM_READ && !HAVE_PROCFS_CTL - -/*++ -Function: - DBGAttachProcess - -Abstract - - Attach the indicated process to the current process. - - if the indicated process is already attached by the current process, then - increment the number of attachment pending. if ot, attach it to the current - process (with PT_ATTACH). - -Parameter - hProcess : handle to process to attach to - processId : process ID to attach -Return - Return true if it succeeds, or false if it's fails ---*/ -static -BOOL -DBGAttachProcess( - CPalThread *pThread, - HANDLE hProcess, - DWORD processId - ) -{ - int attchmentCount; - int savedErrno; -#if HAVE_PROCFS_CTL - int fd = -1; - char ctlPath[1024]; -#endif // HAVE_PROCFS_CTL - - attchmentCount = - DBGSetProcessAttached(pThread, hProcess, DBG_ATTACH); - - if (attchmentCount == -1) - { - /* Failed to set the process as attached */ - goto EXIT; - } - - if (attchmentCount == 1) - { -#if HAVE_PROCFS_CTL - struct timespec waitTime; - - // FreeBSD has some trouble when a series of attach/detach sequences - // occurs too close together. When this happens, we'll be able to - // attach to the process, but waiting for the process to stop - // (either via writing "wait" to /proc//ctl or via waitpid) - // will hang. If we pause for a very short amount of time before - // trying to attach, we don't run into this situation. - waitTime.tv_sec = 0; - waitTime.tv_nsec = 50000000; - nanosleep(&waitTime, NULL); - - sprintf_s(ctlPath, sizeof(ctlPath), "/proc/%d/ctl", processId); - fd = InternalOpen(ctlPath, O_WRONLY); - if (fd == -1) - { - ERROR("Failed to open %s: errno is %d (%s)\n", ctlPath, - errno, strerror(errno)); - goto DETACH1; - } - - if (write(fd, CTL_ATTACH, sizeof(CTL_ATTACH)) < (int)sizeof(CTL_ATTACH)) - { - ERROR("Failed to attach to %s: errno is %d (%s)\n", ctlPath, - errno, strerror(errno)); - close(fd); - goto DETACH1; - } - - if (write(fd, CTL_WAIT, sizeof(CTL_WAIT)) < (int)sizeof(CTL_WAIT)) - { - ERROR("Failed to wait for %s: errno is %d (%s)\n", ctlPath, - errno, strerror(errno)); - goto DETACH2; - } - - close(fd); -#elif HAVE_TTRACE - if (ttrace(TT_PROC_ATTACH, processId, 0, TT_DETACH_ON_EXIT, TT_VERSION, 0) == -1) - { - if (errno != ESRCH) - { - ASSERT("ttrace(TT_PROC_ATTACH, pid:%d) failed errno:%d (%s)\n", - processId, errno, strerror(errno)); - } - goto DETACH1; - } -#else // HAVE_TTRACE - if (PAL_PTRACE( PAL_PT_ATTACH, processId, 0, 0 ) == -1) - { - if (errno != ESRCH) - { - ASSERT("ptrace(PT_ATTACH, pid:%d) failed errno:%d (%s)\n", - processId, errno, strerror(errno)); - } - goto DETACH1; - } - - if (waitpid(processId, NULL, WUNTRACED) == -1) - { - if (errno != ESRCH) - { - ASSERT("waitpid(pid:%d, NULL, WUNTRACED) failed.errno:%d" - " (%s)\n", processId, errno, strerror(errno)); - } - goto DETACH2; - } -#endif // HAVE_PROCFS_CTL - } - - return TRUE; - -#if HAVE_PROCFS_CTL -DETACH2: - if (write(fd, CTL_DETACH, sizeof(CTL_DETACH)) < (int)sizeof(CTL_DETACH)) - { - ASSERT("Failed to detach from %s: errno is %d (%s)\n", ctlPath, - errno, strerror(errno)); - } - close(fd); -#elif !HAVE_TTRACE -DETACH2: - if (PAL_PTRACE(PAL_PT_DETACH, processId, 0, 0) == -1) - { - ASSERT("ptrace(PT_DETACH, pid:%d) failed. errno:%d (%s)\n", processId, - errno, strerror(errno)); - } -#endif // HAVE_PROCFS_CTL - -DETACH1: - savedErrno = errno; - DBGSetProcessAttached(pThread, hProcess, DBG_DETACH); - errno = savedErrno; -EXIT: - if (errno == ESRCH || errno == ENOENT || errno == EBADF) - { - ERROR("Invalid process ID:%d\n", processId); - SetLastError(ERROR_INVALID_PARAMETER); - } - else - { - SetLastError(ERROR_INTERNAL_ERROR); - } - return FALSE; -} - -/*++ -Function: - DBGDetachProcess - -Abstract - Detach the indicated process from the current process. - - if the indicated process is already attached by the current process, then - decrement the number of attachment pending and detach it from the current - process (with PT_DETACH) if there's no more attachment left. - -Parameter - hProcess : process handle - processId : process ID - -Return - Return true if it succeeds, or true if it's fails ---*/ -static -BOOL -DBGDetachProcess( - CPalThread *pThread, - HANDLE hProcess, - DWORD processId - ) -{ - int nbAttachLeft; -#if HAVE_PROCFS_CTL - int fd = -1; - char ctlPath[1024]; -#endif // HAVE_PROCFS_CTL - - nbAttachLeft = DBGSetProcessAttached(pThread, hProcess, DBG_DETACH); - - if (nbAttachLeft == -1) - { - /* Failed to set the process as detached */ - return FALSE; - } - - /* check if there's no more attachment left on processId */ - if (nbAttachLeft == 0) - { -#if HAVE_PROCFS_CTL - sprintf(ctlPath, sizeof(ctlPath), "/proc/%d/ctl", processId); - fd = InternalOpen(pThread, ctlPath, O_WRONLY); - if (fd == -1) - { - if (errno == ENOENT) - { - ERROR("Invalid process ID: %d\n", processId); - SetLastError(ERROR_INVALID_PARAMETER); - } - else - { - ERROR("Failed to open %s: errno is %d (%s)\n", ctlPath, - errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - return FALSE; - } - - if (write(fd, CTL_DETACH, sizeof(CTL_DETACH)) < (int)sizeof(CTL_DETACH)) - { - ERROR("Failed to detach from %s: errno is %d (%s)\n", ctlPath, - errno, strerror(errno)); - close(fd); - return FALSE; - } - close(fd); - -#elif HAVE_TTRACE - if (ttrace(TT_PROC_DETACH, processId, 0, 0, 0, 0) == -1) - { - if (errno == ESRCH) - { - ERROR("Invalid process ID: %d\n", processId); - SetLastError(ERROR_INVALID_PARAMETER); - } - else - { - ASSERT("ttrace(TT_PROC_DETACH, pid:%d) failed. errno:%d (%s)\n", - processId, errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - return FALSE; - } -#else // HAVE_TTRACE - if (PAL_PTRACE(PAL_PT_DETACH, processId, 1, 0) == -1) - { - if (errno == ESRCH) - { - ERROR("Invalid process ID: %d\n", processId); - SetLastError(ERROR_INVALID_PARAMETER); - } - else - { - ASSERT("ptrace(PT_DETACH, pid:%d) failed. errno:%d (%s)\n", - processId, errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - return FALSE; - } -#endif // HAVE_PROCFS_CTL - -#if !HAVE_TTRACE - if (kill(processId, SIGCONT) == -1) - { - ERROR("Failed to continue the detached process:%d errno:%d (%s)\n", - processId, errno, strerror(errno)); - return FALSE; - } -#endif // !HAVE_TTRACE - } - return TRUE; -} - -/*++ -Function: - DBGSetProcessAttached - -Abstract - saves the current process Id in the attached process structure - -Parameter - hProcess : process handle - bAttach : true (false) to set the process as attached (as detached) -Return - returns the number of attachment left on attachedProcId, or -1 if it fails ---*/ -static int -DBGSetProcessAttached( - CPalThread *pThread, - HANDLE hProcess, - BOOL bAttach - ) -{ - PAL_ERROR palError = NO_ERROR; - IPalObject *pobjProcess = NULL; - IDataLock *pDataLock = NULL; - CProcProcessLocalData *pLocalData = NULL; - int ret = -1; - CAllowedObjectTypes aotProcess(otiProcess); - - palError = g_pObjectManager->ReferenceObjectByHandle( - pThread, - hProcess, - &aotProcess, - 0, - &pobjProcess - ); - - if (NO_ERROR != palError) - { - goto DBGSetProcessAttachedExit; - } - - palError = pobjProcess->GetProcessLocalData( - pThread, - WriteLock, - &pDataLock, - reinterpret_cast(&pLocalData) - ); - - if (NO_ERROR != palError) - { - goto DBGSetProcessAttachedExit; - } - - if (bAttach) - { - pLocalData->lAttachCount += 1; - } - else - { - pLocalData->lAttachCount -= 1; - - if (pLocalData->lAttachCount < 0) - { - ASSERT("pLocalData->lAttachCount < 0 check for extra DBGDetachProcess calls\n"); - palError = ERROR_INTERNAL_ERROR; - goto DBGSetProcessAttachedExit; - } - } - - ret = pLocalData->lAttachCount; - -DBGSetProcessAttachedExit: - - if (NULL != pDataLock) - { - pDataLock->ReleaseLock(pThread, TRUE); - } - - if (NULL != pobjProcess) - { - pobjProcess->ReleaseReference(pThread); - } - - return ret; -} - -#endif // !HAVE_VM_READ && !HAVE_PROCFS_CTL - /*++ Function: PAL_CreateExecWatchpoint @@ -1240,605 +766,64 @@ PAL_DeleteExecWatchpointExit: return dwError; } -// We want to enable hardware exception handling for ReadProcessMemory -// and WriteProcessMemory in all cases since it is acceptable if they -// hit AVs, so redefine HardwareExceptionHolder for these two functions -// (here to the end of the file). -#undef HardwareExceptionHolder -#define HardwareExceptionHolder CatchHardwareExceptionHolder __catchHardwareException; - -/*++ -Function: - ReadProcessMemory - -See MSDN doc. ---*/ -BOOL -PALAPI -ReadProcessMemory( - IN HANDLE hProcess, - IN LPCVOID lpBaseAddress, - IN LPVOID lpBuffer, - IN SIZE_T nSize, - OUT SIZE_T * lpNumberOfBytesRead - ) +__attribute__((noinline)) +__attribute__((optnone)) +void +ProbeMemory(volatile PBYTE pbBuffer, DWORD cbBuffer, bool fWriteAccess) { - CPalThread *pThread; - DWORD processId; - Volatile ret = FALSE; - Volatile numberOfBytesRead = 0; -#if HAVE_VM_READ - kern_return_t result; - vm_map_t task; - LONG_PTR bytesToRead; -#elif HAVE_PROCFS_CTL - int fd = -1; - char memPath[64]; - off_t offset; -#elif !HAVE_TTRACE - SIZE_T nbInts; - int* ptrInt; - int* lpTmpBuffer; -#endif -#if !HAVE_PROCFS_CTL && !HAVE_TTRACE - int* lpBaseAddressAligned; - SIZE_T offset; -#endif // !HAVE_PROCFS_CTL && !HAVE_TTRACE - - PERF_ENTRY(ReadProcessMemory); - ENTRY("ReadProcessMemory (hProcess=%p,lpBaseAddress=%p, lpBuffer=%p, " - "nSize=%u, lpNumberOfBytesRead=%p)\n",hProcess,lpBaseAddress, - lpBuffer, (unsigned int)nSize, lpNumberOfBytesRead); - - pThread = InternalGetCurrentThread(); - - if (!(processId = PROCGetProcessIDFromHandle(hProcess))) - { - ERROR("Invalid process handler hProcess:%p.",hProcess); - SetLastError(ERROR_INVALID_HANDLE); - goto EXIT; - } - - // Check if the read request is for the current process. - // We don't need ptrace in that case. - if (GetCurrentProcessId() == processId) + // Need an throw in this function to fool the C++ runtime into handling the + // possible h/w exception below. + if (pbBuffer == NULL) { - TRACE("We are in the same process, so ptrace is not needed\n"); - - struct Param - { - LPCVOID lpBaseAddress; - LPVOID lpBuffer; - SIZE_T nSize; - SIZE_T numberOfBytesRead; - BOOL ret; - } param; - param.lpBaseAddress = lpBaseAddress; - param.lpBuffer = lpBuffer; - param.nSize = nSize; - param.numberOfBytesRead = numberOfBytesRead; - param.ret = ret; - - PAL_TRY(Param *, pParam, ¶m) - { - SIZE_T i; - - // Seg fault in memcpy can't be caught - // so we simulate the memcpy here - - for (i = 0; inSize; i++) - { - *((char*)(pParam->lpBuffer)+i) = *((char*)(pParam->lpBaseAddress)+i); - } - - pParam->numberOfBytesRead = pParam->nSize; - pParam->ret = TRUE; - } - PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - SetLastError(ERROR_ACCESS_DENIED); - } - PAL_ENDTRY - - numberOfBytesRead = param.numberOfBytesRead; - ret = param.ret; - goto EXIT; + throw PAL_SEHException(); } -#if HAVE_VM_READ - result = task_for_pid(mach_task_self(), processId, &task); - if (result != KERN_SUCCESS) + // Simple one byte at a time probing + while (cbBuffer > 0) { - ERROR("No Mach task for pid %d: %d\n", processId, ret.Load()); - SetLastError(ERROR_INVALID_HANDLE); - goto EXIT; - } - // vm_read_overwrite usually requires that the address be page-aligned - // and the size be a multiple of the page size. We can't differentiate - // between the cases in which that's required and those in which it - // isn't, so we do it all the time. - lpBaseAddressAligned = (int*)((SIZE_T) lpBaseAddress & ~VIRTUAL_PAGE_MASK); - offset = ((SIZE_T) lpBaseAddress & VIRTUAL_PAGE_MASK); - char *data; - data = (char*)alloca(VIRTUAL_PAGE_SIZE); - while (nSize > 0) - { - vm_size_t bytesRead; - - bytesToRead = VIRTUAL_PAGE_SIZE - offset; - if (bytesToRead > (LONG_PTR)nSize) - { - bytesToRead = nSize; - } - bytesRead = VIRTUAL_PAGE_SIZE; - result = vm_read_overwrite(task, (vm_address_t) lpBaseAddressAligned, - VIRTUAL_PAGE_SIZE, (vm_address_t) data, &bytesRead); - if (result != KERN_SUCCESS || bytesRead != VIRTUAL_PAGE_SIZE) + volatile BYTE read = *pbBuffer; + if (fWriteAccess) { - ERROR("vm_read_overwrite failed for %d bytes from %p in %d: %d\n", - VIRTUAL_PAGE_SIZE, (char *) lpBaseAddressAligned, task, result); - if (result <= KERN_RETURN_MAX) - { - SetLastError(ERROR_INVALID_ACCESS); - } - else - { - SetLastError(ERROR_INTERNAL_ERROR); - } - goto EXIT; + *pbBuffer = read; } - memcpy((LPSTR)lpBuffer + numberOfBytesRead, data + offset, bytesToRead); - numberOfBytesRead.Store(numberOfBytesRead.Load() + bytesToRead); - lpBaseAddressAligned = (int*)((char*)lpBaseAddressAligned + VIRTUAL_PAGE_SIZE); - nSize -= bytesToRead; - offset = 0; + ++pbBuffer; + --cbBuffer; } - ret = TRUE; -#else // HAVE_VM_READ -#if HAVE_PROCFS_CTL - snprintf(memPath, sizeof(memPath), "/proc/%u/%s", processId, PROCFS_MEM_NAME); - fd = InternalOpen(memPath, O_RDONLY); - if (fd == -1) - { - ERROR("Failed to open %s\n", memPath); - SetLastError(ERROR_INVALID_ACCESS); - goto PROCFSCLEANUP; - } - - // - // off_t may be greater in size than void*, so first cast to - // an unsigned type to ensure that no sign extension takes place - // - - offset = (off_t) (UINT_PTR) lpBaseAddress; - - if (lseek(fd, offset, SEEK_SET) == -1) - { - ERROR("Failed to seek to base address\n"); - SetLastError(ERROR_INVALID_ACCESS); - goto PROCFSCLEANUP; - } - - numberOfBytesRead = read(fd, lpBuffer, nSize); - ret = TRUE; - -#else // HAVE_PROCFS_CTL - // Attach the process before calling ttrace/ptrace otherwise it fails. - if (DBGAttachProcess(pThread, hProcess, processId)) - { -#if HAVE_TTRACE - if (ttrace(TT_PROC_RDDATA, processId, 0, (__uint64_t)lpBaseAddress, (__uint64_t)nSize, (__uint64_t)lpBuffer) == -1) - { - if (errno == EFAULT) - { - ERROR("ttrace(TT_PROC_RDDATA, pid:%d, 0, addr:%p, data:%d, addr2:%d) failed" - " errno=%d (%s)\n", processId, lpBaseAddress, (int)nSize, lpBuffer, - errno, strerror(errno)); - - SetLastError(ERROR_ACCESS_DENIED); - } - else - { - ASSERT("ttrace(TT_PROC_RDDATA, pid:%d, 0, addr:%p, data:%d, addr2:%d) failed" - " errno=%d (%s)\n", processId, lpBaseAddress, (int)nSize, lpBuffer, - errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - - goto CLEANUP1; - } - - numberOfBytesRead = nSize; - ret = TRUE; - -#else // HAVE_TTRACE - - offset = (SIZE_T)lpBaseAddress % sizeof(int); - lpBaseAddressAligned = (int*)((char*)lpBaseAddress - offset); - nbInts = (nSize + offset)/sizeof(int) + - ((nSize + offset)%sizeof(int) ? 1:0); - - /* before transferring any data to lpBuffer we should make sure that all - data is accessible for read. so we need to use a temp buffer for that.*/ - if (!(lpTmpBuffer = (int*)InternalMalloc((nbInts * sizeof(int))))) - { - ERROR("Insufficient memory available !\n"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto CLEANUP1; - } - - for (ptrInt = lpTmpBuffer; nbInts; ptrInt++, - lpBaseAddressAligned++, nbInts--) - { - errno = 0; - *ptrInt = - PAL_PTRACE(PAL_PT_READ_D, processId, lpBaseAddressAligned, 0); - if (*ptrInt == -1 && errno) - { - if (errno == EFAULT) - { - ERROR("ptrace(PT_READ_D, pid:%d, addr:%p, data:0) failed" - " errno=%d (%s)\n", processId, lpBaseAddressAligned, - errno, strerror(errno)); - - SetLastError(ptrInt == lpTmpBuffer ? ERROR_ACCESS_DENIED : - ERROR_PARTIAL_COPY); - } - else - { - ASSERT("ptrace(PT_READ_D, pid:%d, addr:%p, data:0) failed" - " errno=%d (%s)\n", processId, lpBaseAddressAligned, - errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - - goto CLEANUP2; - } - } - - /* transfer data from temp buffer to lpBuffer */ - memcpy( (char *)lpBuffer, ((char*)lpTmpBuffer) + offset, nSize); - numberOfBytesRead = nSize; - ret = TRUE; -#endif // HAVE_TTRACE - } - else - { - /* Failed to attach processId */ - goto EXIT; - } -#endif // HAVE_PROCFS_CTL - -#if HAVE_PROCFS_CTL -PROCFSCLEANUP: - if (fd != -1) - { - close(fd); - } -#elif !HAVE_TTRACE -CLEANUP2: - if (lpTmpBuffer) - { - free(lpTmpBuffer); - } -#endif // !HAVE_TTRACE - -#if !HAVE_PROCFS_CTL -CLEANUP1: - if (!DBGDetachProcess(pThread, hProcess, processId)) - { - /* Failed to detach processId */ - ret = FALSE; - } -#endif // HAVE_PROCFS_CTL -#endif // HAVE_VM_READ - -EXIT: - if (lpNumberOfBytesRead) - { - *lpNumberOfBytesRead = numberOfBytesRead; - } - LOGEXIT("ReadProcessMemory returns BOOL %d\n", ret.Load()); - PERF_EXIT(ReadProcessMemory); - return ret; } /*++ Function: - WriteProcessMemory + PAL_ProbeMemory -See MSDN doc. +Abstract + +Parameter + pBuffer : address of memory to validate + cbBuffer : size of memory region to validate + fWriteAccess : if true, validate writable access, else just readable. + +Return + true if memory is valid, false if not. --*/ BOOL PALAPI -WriteProcessMemory( - IN HANDLE hProcess, - IN LPVOID lpBaseAddress, - IN LPCVOID lpBuffer, - IN SIZE_T nSize, - OUT SIZE_T * lpNumberOfBytesWritten - ) - +PAL_ProbeMemory( + PVOID pBuffer, + DWORD cbBuffer, + BOOL fWriteAccess) { - CPalThread *pThread; - DWORD processId; - Volatile ret = FALSE; - Volatile numberOfBytesWritten = 0; -#if HAVE_VM_READ - kern_return_t result; - vm_map_t task; -#elif HAVE_PROCFS_CTL - int fd = -1; - char memPath[64]; - LONG_PTR bytesWritten; - off_t offset; -#elif !HAVE_TTRACE - SIZE_T FirstIntOffset; - SIZE_T LastIntOffset; - unsigned int FirstIntMask; - unsigned int LastIntMask; - SIZE_T nbInts; - int *lpTmpBuffer = 0, *lpInt; - int* lpBaseAddressAligned; -#endif - - PERF_ENTRY(WriteProcessMemory); - ENTRY("WriteProcessMemory (hProcess=%p,lpBaseAddress=%p, lpBuffer=%p, " - "nSize=%u, lpNumberOfBytesWritten=%p)\n", - hProcess,lpBaseAddress, lpBuffer, (unsigned int)nSize, lpNumberOfBytesWritten); - - pThread = InternalGetCurrentThread(); - - if (!(nSize && (processId = PROCGetProcessIDFromHandle(hProcess)))) - { - ERROR("Invalid nSize:%u number or invalid process handler " - "hProcess:%p\n", (unsigned int)nSize, hProcess); - SetLastError(ERROR_INVALID_PARAMETER); - goto EXIT; - } - - // Check if the write request is for the current process. - // In that case we don't need ptrace. - if (GetCurrentProcessId() == processId) - { - TRACE("We are in the same process so we don't need ptrace\n"); - - struct Param - { - LPVOID lpBaseAddress; - LPCVOID lpBuffer; - SIZE_T nSize; - SIZE_T numberOfBytesWritten; - BOOL ret; - } param; - param.lpBaseAddress = lpBaseAddress; - param.lpBuffer = lpBuffer; - param.nSize = nSize; - param.numberOfBytesWritten = numberOfBytesWritten; - param.ret = ret; - - PAL_TRY(Param *, pParam, ¶m) - { - SIZE_T i; - - // Seg fault in memcpy can't be caught - // so we simulate the memcpy here - - for (i = 0; inSize; i++) - { - *((char*)(pParam->lpBaseAddress)+i) = *((char*)(pParam->lpBuffer)+i); - } - - pParam->numberOfBytesWritten = pParam->nSize; - pParam->ret = TRUE; - } - PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - SetLastError(ERROR_ACCESS_DENIED); - } - PAL_ENDTRY - - numberOfBytesWritten = param.numberOfBytesWritten; - ret = param.ret; - goto EXIT; - } - -#if HAVE_VM_READ - result = task_for_pid(mach_task_self(), processId, &task); - if (result != KERN_SUCCESS) - { - ERROR("No Mach task for pid %d: %d\n", processId, ret.Load()); - SetLastError(ERROR_INVALID_HANDLE); - goto EXIT; - } - result = vm_write(task, (vm_address_t) lpBaseAddress, - (vm_address_t) lpBuffer, nSize); - if (result != KERN_SUCCESS) - { - ERROR("vm_write failed for %d bytes from %p in %d: %d\n", - (int)nSize, lpBaseAddress, task, result); - if (result <= KERN_RETURN_MAX) - { - SetLastError(ERROR_ACCESS_DENIED); - } - else - { - SetLastError(ERROR_INTERNAL_ERROR); - } - goto EXIT; - } - numberOfBytesWritten = nSize; - ret = TRUE; -#else // HAVE_VM_READ -#if HAVE_PROCFS_CTL - snprintf(memPath, sizeof(memPath), "/proc/%u/%s", processId, PROCFS_MEM_NAME); - fd = InternalOpen(memPath, O_WRONLY); - if (fd == -1) + try { - ERROR("Failed to open %s\n", memPath); - SetLastError(ERROR_INVALID_ACCESS); - goto PROCFSCLEANUP; - } - - // - // off_t may be greater in size than void*, so first cast to - // an unsigned type to ensure that no sign extension takes place - // - - offset = (off_t) (UINT_PTR) lpBaseAddress; + // Need to explicit h/w exception holder so to catch them in ProbeMemory + CatchHardwareExceptionHolder __catchHardwareException; - if (lseek(fd, offset, SEEK_SET) == -1) - { - ERROR("Failed to seek to base address\n"); - SetLastError(ERROR_INVALID_ACCESS); - goto PROCFSCLEANUP; + ProbeMemory((PBYTE)pBuffer, cbBuffer, fWriteAccess); } - - bytesWritten = write(fd, lpBuffer, nSize); - if (bytesWritten < 0) - { - ERROR("Failed to write to %s\n", memPath); - SetLastError(ERROR_INVALID_ACCESS); - goto PROCFSCLEANUP; - } - - numberOfBytesWritten = bytesWritten; - ret = TRUE; - -#else // HAVE_PROCFS_CTL - /* Attach the process before calling ptrace otherwise it fails */ - if (DBGAttachProcess(pThread, hProcess, processId)) + catch(...) { -#if HAVE_TTRACE - if (ttrace(TT_PROC_WRDATA, processId, 0, (__uint64_t)lpBaseAddress, (__uint64_t)nSize, (__uint64_t)lpBuffer) == -1) - { - if (errno == EFAULT) - { - ERROR("ttrace(TT_PROC_WRDATA, pid:%d, addr:%p, data:%d, addr2:%d) failed" - " errno=%d (%s)\n", processId, lpBaseAddress, nSize, lpBuffer, - errno, strerror(errno)); - - SetLastError(ERROR_ACCESS_DENIED); - } - else - { - ASSERT("ttrace(TT_PROC_WRDATA, pid:%d, addr:%p, data:%d, addr2:%d) failed" - " errno=%d (%s)\n", processId, lpBaseAddress, nSize, lpBuffer, - errno, strerror(errno)); - SetLastError(ERROR_INTERNAL_ERROR); - } - - goto CLEANUP1; - } - - numberOfBytesWritten = nSize; - ret = TRUE; - -#else // HAVE_TTRACE - - FirstIntOffset = (SIZE_T)lpBaseAddress % sizeof(int); - FirstIntMask = -1; - FirstIntMask <<= (FirstIntOffset * 8); - - nbInts = (nSize + FirstIntOffset) / sizeof(int) + - (((nSize + FirstIntOffset)%sizeof(int)) ? 1:0); - lpBaseAddressAligned = (int*)((char*)lpBaseAddress - FirstIntOffset); - - if ((lpTmpBuffer = (int*)InternalMalloc((nbInts * sizeof(int)))) == NULL) - { - ERROR("Insufficient memory available !\n"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto CLEANUP1; - } - - memcpy((char *)lpTmpBuffer + FirstIntOffset, (char *)lpBuffer, nSize); - lpInt = lpTmpBuffer; - - LastIntOffset = (nSize + FirstIntOffset) % sizeof(int); - LastIntMask = -1; - LastIntMask >>= ((sizeof(int) - LastIntOffset) * 8); - - if (nbInts == 1) - { - if (DBGWriteProcMem_IntWithMask(processId, lpBaseAddressAligned, - *lpInt, - LastIntMask & FirstIntMask) - == 0) - { - goto CLEANUP2; - } - numberOfBytesWritten = nSize; - ret = TRUE; - goto CLEANUP2; - } - - if (DBGWriteProcMem_IntWithMask(processId, - lpBaseAddressAligned++, - *lpInt++, FirstIntMask) - == 0) - { - goto CLEANUP2; - } - - while (--nbInts > 1) - { - if (DBGWriteProcMem_Int(processId, lpBaseAddressAligned++, - *lpInt++) == 0) - { - goto CLEANUP2; - } - } - - if (DBGWriteProcMem_IntWithMask(processId, lpBaseAddressAligned, - *lpInt, LastIntMask ) == 0) - { - goto CLEANUP2; - } - - numberOfBytesWritten = nSize; - ret = TRUE; -#endif // HAVE_TTRACE - } - else - { - /* Failed to attach processId */ - goto EXIT; - } -#endif // HAVE_PROCFS_CTL - -#if HAVE_PROCFS_CTL -PROCFSCLEANUP: - if (fd != -1) - { - close(fd); - } -#elif !HAVE_TTRACE -CLEANUP2: - if (lpTmpBuffer) - { - free(lpTmpBuffer); - } -#endif // !HAVE_TTRACE - -#if !HAVE_PROCFS_CTL -CLEANUP1: - if (!DBGDetachProcess(pThread, hProcess, processId)) - { - /* Failed to detach processId */ - ret = FALSE; - } -#endif // !HAVE_PROCFS_CTL -#endif // HAVE_VM_READ - -EXIT: - if (lpNumberOfBytesWritten) - { - *lpNumberOfBytesWritten = numberOfBytesWritten; + return FALSE; } - - LOGEXIT("WriteProcessMemory returns BOOL %d\n", ret.Load()); - PERF_EXIT(WriteProcessMemory); - return ret; + return TRUE; } } // extern "C" diff --git a/src/pal/src/examples/CMakeLists.txt b/src/pal/src/examples/CMakeLists.txt index 2cef914..3797d89 100644 --- a/src/pal/src/examples/CMakeLists.txt +++ b/src/pal/src/examples/CMakeLists.txt @@ -4,7 +4,7 @@ project(palexmpl) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - example1.c + example1.cpp ) add_executable(palexmpl diff --git a/src/pal/src/examples/example1.c b/src/pal/src/examples/example1.cpp similarity index 100% rename from src/pal/src/examples/example1.c rename to src/pal/src/examples/example1.cpp diff --git a/src/pal/src/exception/machexception.cpp b/src/pal/src/exception/machexception.cpp index 8b0d7f2..5328e1f 100644 --- a/src/pal/src/exception/machexception.cpp +++ b/src/pal/src/exception/machexception.cpp @@ -1518,6 +1518,7 @@ ActivationHandler(CONTEXT* context) extern "C" void ActivationHandlerWrapper(); extern "C" int ActivationHandlerReturnOffset; +extern "C" unsigned int XmmYmmStateSupport(); /*++ Function : @@ -1581,6 +1582,12 @@ InjectActivationInternal(CPalThread* pThread) // after the activation function returns. CONTEXT *pContext = (CONTEXT *)contextAddress; pContext->ContextFlags = CONTEXT_FULL | CONTEXT_SEGMENTS; +#ifdef XSTATE_SUPPORTED + if (XmmYmmStateSupport() == 1) + { + pContext->ContextFlags |= CONTEXT_XSTATE; + } +#endif MachRet = CONTEXT_GetThreadContextFromPort(threadPort, pContext); _ASSERT_MSG(MachRet == KERN_SUCCESS, "CONTEXT_GetThreadContextFromPort\n"); diff --git a/src/pal/src/exception/machmessage.cpp b/src/pal/src/exception/machmessage.cpp index a6f7e57..b786960 100644 --- a/src/pal/src/exception/machmessage.cpp +++ b/src/pal/src/exception/machmessage.cpp @@ -1069,7 +1069,7 @@ thread_act_t MachMessage::GetThreadFromState(thread_state_flavor_t eFlavor, thre NONPAL_RETAIL_ASSERT("Failed to locate thread from state."); } -// Transform a exception handler behavior type into the corresponding Mach message ID for the notification. +// Transform an exception handler behavior type into the corresponding Mach message ID for the notification. mach_msg_id_t MachMessage::MapBehaviorToNotificationType(exception_behavior_t eBehavior) { switch ((uint)eBehavior) diff --git a/src/pal/src/exception/machmessage.h b/src/pal/src/exception/machmessage.h index 244396c..abc583f 100644 --- a/src/pal/src/exception/machmessage.h +++ b/src/pal/src/exception/machmessage.h @@ -36,7 +36,7 @@ using namespace CorUnix; if (machret != KERN_SUCCESS) \ { \ char _szError[1024]; \ - sprintf(_szError, "%s: %u: %s", __FUNCTION__, __LINE__, _msg); \ + snprintf(_szError, _countof(_szError), "%s: %u: %s", __FUNCTION__, __LINE__, _msg); \ mach_error(_szError, machret); \ abort(); \ } \ @@ -395,7 +395,7 @@ private: // x86_THREAD_STATE and x86_THREAD_STATE32 state flavors are supported. thread_act_t GetThreadFromState(thread_state_flavor_t eFlavor, thread_state_t pState); - // Transform a exception handler behavior type into the corresponding Mach message ID for the + // Transform an exception handler behavior type into the corresponding Mach message ID for the // notification. mach_msg_id_t MapBehaviorToNotificationType(exception_behavior_t eBehavior); diff --git a/src/pal/src/exception/seh-unwind.cpp b/src/pal/src/exception/seh-unwind.cpp index 24eebbb..fa2f109 100644 --- a/src/pal/src/exception/seh-unwind.cpp +++ b/src/pal/src/exception/seh-unwind.cpp @@ -73,6 +73,14 @@ Abstract: ASSIGN_REG(X26) \ ASSIGN_REG(X27) \ ASSIGN_REG(X28) +#elif defined(_X86_) +#define ASSIGN_UNWIND_REGS \ + ASSIGN_REG(Eip) \ + ASSIGN_REG(Esp) \ + ASSIGN_REG(Ebp) \ + ASSIGN_REG(Ebx) \ + ASSIGN_REG(Esi) \ + ASSIGN_REG(Edi) #else #error unsupported architecture #endif @@ -122,6 +130,13 @@ static void WinContextToUnwindCursor(CONTEXT *winContext, unw_cursor_t *cursor) unw_set_reg(cursor, UNW_X86_64_R13, winContext->R13); unw_set_reg(cursor, UNW_X86_64_R14, winContext->R14); unw_set_reg(cursor, UNW_X86_64_R15, winContext->R15); +#elif defined(_X86_) + unw_set_reg(cursor, UNW_REG_IP, winContext->Eip); + unw_set_reg(cursor, UNW_REG_SP, winContext->Esp); + unw_set_reg(cursor, UNW_X86_EBP, winContext->Ebp); + unw_set_reg(cursor, UNW_X86_EBX, winContext->Ebx); + unw_set_reg(cursor, UNW_X86_ESI, winContext->Esi); + unw_set_reg(cursor, UNW_X86_EDI, winContext->Edi); #endif } #endif @@ -137,6 +152,13 @@ static void UnwindContextToWinContext(unw_cursor_t *cursor, CONTEXT *winContext) unw_get_reg(cursor, UNW_X86_64_R13, (unw_word_t *) &winContext->R13); unw_get_reg(cursor, UNW_X86_64_R14, (unw_word_t *) &winContext->R14); unw_get_reg(cursor, UNW_X86_64_R15, (unw_word_t *) &winContext->R15); +#elif defined(_X86_) + unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Eip); + unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Esp); + unw_get_reg(cursor, UNW_X86_EBP, (unw_word_t *) &winContext->Ebp); + unw_get_reg(cursor, UNW_X86_EBX, (unw_word_t *) &winContext->Ebx); + unw_get_reg(cursor, UNW_X86_ESI, (unw_word_t *) &winContext->Esi); + unw_get_reg(cursor, UNW_X86_EDI, (unw_word_t *) &winContext->Edi); #elif defined(_ARM_) unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Sp); unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Pc); @@ -196,6 +218,11 @@ static void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, GetContextPointer(cursor, unwContext, UNW_X86_64_R13, &contextPointers->R13); GetContextPointer(cursor, unwContext, UNW_X86_64_R14, &contextPointers->R14); GetContextPointer(cursor, unwContext, UNW_X86_64_R15, &contextPointers->R15); +#elif defined(_X86_) + GetContextPointer(cursor, unwContext, UNW_X86_EBX, &contextPointers->Ebx); + GetContextPointer(cursor, unwContext, UNW_X86_EBP, &contextPointers->Ebp); + GetContextPointer(cursor, unwContext, UNW_X86_ESI, &contextPointers->Esi); + GetContextPointer(cursor, unwContext, UNW_X86_EDI, &contextPointers->Edi); #elif defined(_ARM_) GetContextPointer(cursor, unwContext, UNW_ARM_R4, &contextPointers->R4); GetContextPointer(cursor, unwContext, UNW_ARM_R5, &contextPointers->R5); @@ -221,15 +248,34 @@ static void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, #endif } +extern int g_common_signal_handler_context_locvar_offset; + BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers) { int st; unw_context_t unwContext; unw_cursor_t cursor; -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(_ARM64_) || defined(_ARM_) - DWORD64 curPc; -#endif + 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 native_context_t of the hardware + // exception and return that. This skips the hardware signal handler trampoline that the libunwind + // cannot cross on some systems. + if ((void*)curPc == g_SEHProcessExceptionReturnAddress) + { + ULONG contextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT | CONTEXT_EXCEPTION_ACTIVE; + + #if defined(_AMD64_) + contextFlags |= CONTEXT_XSTATE; + #endif + size_t nativeContext = *(size_t*)(CONTEXTGetFP(context) + g_common_signal_handler_context_locvar_offset); + CONTEXTFromNativeContext((const native_context_t *)nativeContext, context, contextFlags); + + return TRUE; + } +#endif if ((context->ContextFlags & CONTEXT_EXCEPTION_ACTIVE) != 0) { @@ -240,7 +286,7 @@ BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextP // So we compensate it by incrementing the PC before passing it to the unwinder. // Without it, the unwinder would not find unwind info if the hardware exception // happened in the first instruction of a function. - CONTEXTSetPC(context, CONTEXTGetPC(context) + 1); + CONTEXTSetPC(context, curPc + 1); } #if !UNWIND_CONTEXT_IS_UCONTEXT_T @@ -264,18 +310,6 @@ BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextP WinContextToUnwindCursor(context, &cursor); #endif -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(_ARM64_) || defined(_ARM_) - // FreeBSD, NetBSD and OSX appear to do two different things when unwinding - // 1: If it reaches where it cannot unwind anymore, say a - // managed frame. It wil return 0, but also update the $pc - // 2: If it unwinds all the way to _start it will return - // 0 from the step, but $pc will stay the same. - // The behaviour of libunwind from nongnu.org is to null the PC - // So we bank the original PC here, so we can compare it after - // the step - curPc = CONTEXTGetPC(context); -#endif - st = unw_step(&cursor); if (st < 0) { @@ -303,12 +337,18 @@ BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextP // Update the passed in windows context to reflect the unwind // UnwindContextToWinContext(&cursor, context); -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(_ARM64_) || defined(_ARM_) + + // FreeBSD, NetBSD, OSX and Alpine appear to do two different things when unwinding + // 1: If it reaches where it cannot unwind anymore, say a + // managed frame. It will return 0, but also update the $pc + // 2: If it unwinds all the way to _start it will return + // 0 from the step, but $pc will stay the same. + // So we detect that here and set the $pc to NULL in that case. + // This is the default behavior of the libunwind on Linux. if (st == 0 && CONTEXTGetPC(context) == curPc) { CONTEXTSetPC(context, 0); } -#endif if (contextPointers != NULL) { diff --git a/src/pal/src/exception/seh.cpp b/src/pal/src/exception/seh.cpp index 38779bf..ad09e02 100644 --- a/src/pal/src/exception/seh.cpp +++ b/src/pal/src/exception/seh.cpp @@ -88,6 +88,10 @@ PHARDWARE_EXCEPTION_SAFETY_CHECK_FUNCTION g_safeExceptionCheckFunction = NULL; PGET_GCMARKER_EXCEPTION_CODE g_getGcMarkerExceptionCode = NULL; +// Return address of the SEHProcessException, which is used to enable walking over +// the signal handler trampoline on some Unixes where the libunwind cannot do that. +void* g_SEHProcessExceptionReturnAddress = NULL; + /* Internal function definitions **********************************************/ /*++ @@ -245,6 +249,8 @@ Return value: BOOL SEHProcessException(PAL_SEHException* exception) { + g_SEHProcessExceptionReturnAddress = __builtin_return_address(0); + CONTEXT* contextRecord = exception->GetContextRecord(); EXCEPTION_RECORD* exceptionRecord = exception->GetExceptionRecord(); @@ -268,7 +274,7 @@ SEHProcessException(PAL_SEHException* exception) { // The exception happened in the page right below the stack limit, // so it is a stack overflow - write(STDERR_FILENO, StackOverflowMessage, sizeof(StackOverflowMessage) - 1); + (void)write(STDERR_FILENO, StackOverflowMessage, sizeof(StackOverflowMessage) - 1); PROCAbort(); } } diff --git a/src/pal/src/exception/signal.cpp b/src/pal/src/exception/signal.cpp index c2c2179..26e2a01 100644 --- a/src/pal/src/exception/signal.cpp +++ b/src/pal/src/exception/signal.cpp @@ -100,6 +100,10 @@ static bool registered_sigterm_handler = false; struct sigaction g_previous_activation; #endif +// Offset of the local variable containing native context in the common_signal_handler function. +// This offset is relative to the frame pointer. +int g_common_signal_handler_context_locvar_offset = 0; + /* public function definitions ************************************************/ /*++ @@ -582,6 +586,7 @@ Note: the "pointers" parameter should contain a valid exception record pointer, but the ContextRecord pointer will be overwritten. --*/ +__attribute__((noinline)) static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext, int numParams, ...) { sigset_t signal_set; @@ -590,6 +595,7 @@ static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext native_context_t *ucontext; ucontext = (native_context_t *)sigcontext; + g_common_signal_handler_context_locvar_offset = (int)((char*)&ucontext - (char*)__builtin_frame_address(0)); AllocateExceptionRecords(&exceptionRecord, &contextRecord); diff --git a/src/pal/src/file/find.cpp b/src/pal/src/file/find.cpp index 18639d3..18bf8c4 100644 --- a/src/pal/src/file/find.cpp +++ b/src/pal/src/file/find.cpp @@ -383,7 +383,7 @@ FindNextFileA( // Split the path into a dir and filename. if (_splitpath_s(path, NULL, 0, find_data->dir, _MAX_DIR, find_data->fname, _MAX_PATH, ext, _MAX_EXT) != 0) { - ASSERT("_splitpath failed on %s\n", path); + ASSERT("_splitpath_s failed on %s\n", path); dwLastError = ERROR_INTERNAL_ERROR; goto done; } @@ -716,7 +716,7 @@ Simple helper function to insert backslashes before square brackets to prevent glob from using them as wildcards. note: this functions assumes all backslashes have previously been - converted into forwardslashes by _splitpath. + converted into forwardslashes by _splitpath_s. --*/ static void FILEEscapeSquareBrackets(char *pattern, char *escaped_pattern) { @@ -750,7 +750,7 @@ Function: FILEGlobFromSplitPath Simple wrapper function around glob(3), except that the pattern is accepted -in broken-down form like _splitpath produces. +in broken-down form like _splitpath_s produces. ie. calling splitpath on a pattern then calling this function should produce the same result as just calling glob() on the pattern. @@ -874,12 +874,12 @@ static BOOL FILEDosGlobA( CPalThread *pthrCurrent, _splitpath_s( pattern, NULL, 0, Dir, _MAX_DIR, Filename, _MAX_FNAME+1, Ext, _MAX_EXT); - /* check to see if _splitpath failed */ + /* check to see if _splitpath_s failed */ if ( Filename[0] == 0 ) { if ( Dir[0] == 0 ) { - ERROR("_splitpath failed on path [%s]\n", pattern); + ERROR("_splitpath_s failed on path [%s]\n", pattern); } else { diff --git a/src/pal/src/include/pal/context.h b/src/pal/src/include/pal/context.h index 5e37894..6857c13 100644 --- a/src/pal/src/include/pal/context.h +++ b/src/pal/src/include/pal/context.h @@ -139,6 +139,8 @@ typedef ucontext_t native_context_t; ///////////////////// // Extended state +#ifdef XSTATE_SUPPORTED + inline _fpx_sw_bytes *FPREG_FpxSwBytes(const ucontext_t *uc) { // Bytes 464..511 in the FXSAVE format are available for software to use for any purpose. In this case, they are used to @@ -185,6 +187,8 @@ inline void *FPREG_Xstate_Ymmh(const ucontext_t *uc) return reinterpret_cast<_xstate *>(FPREG_Fpstate(uc))->ymmh.ymmh_space; } +#endif // XSTATE_SUPPORTED + ///////////////////// #else // BIT64 @@ -450,6 +454,8 @@ inline static DWORD64 CONTEXTGetPC(LPCONTEXT pContext) { #if defined(_AMD64_) return pContext->Rip; +#elif defined(_X86_) + return pContext->Eip; #elif defined(_ARM64_) || defined(_ARM_) return pContext->Pc; #else @@ -461,6 +467,8 @@ inline static void CONTEXTSetPC(LPCONTEXT pContext, DWORD64 pc) { #if defined(_AMD64_) pContext->Rip = pc; +#elif defined(_X86_) + pContext->Eip = pc; #elif defined(_ARM64_) || defined(_ARM_) pContext->Pc = pc; #else @@ -468,6 +476,21 @@ inline static void CONTEXTSetPC(LPCONTEXT pContext, DWORD64 pc) #endif } +inline static DWORD64 CONTEXTGetFP(LPCONTEXT pContext) +{ +#if defined(_AMD64_) + return pContext->Rbp; +#elif defined(_X86_) + return pContext->Ebp; +#elif defined(_ARM_) + return pContext->R7; +#elif defined(_ARM64_) + return pContext->Fp; +#else +#error don't know how to get the frame pointer for this architecture +#endif +} + /*++ Function : CONTEXT_CaptureContext @@ -481,6 +504,7 @@ Parameters : --*/ void +PALAPI CONTEXT_CaptureContext( LPCONTEXT lpContext ); diff --git a/src/pal/src/include/pal/palinternal.h b/src/pal/src/include/pal/palinternal.h index 7348192..f7856be 100644 --- a/src/pal/src/include/pal/palinternal.h +++ b/src/pal/src/include/pal/palinternal.h @@ -169,7 +169,6 @@ function_name() to call the system's implementation #define memmove DUMMY_memmove #define memchr DUMMY_memchr #define strlen DUMMY_strlen -#define strnlen DUMMY_strnlen #define stricmp DUMMY_stricmp #define strstr DUMMY_strstr #define strcmp DUMMY_strcmp @@ -184,12 +183,6 @@ function_name() to call the system's implementation #define strpbrk DUMMY_strpbrk #define strtod DUMMY_strtod #define strspn DUMMY_strspn -#if HAVE__SNPRINTF -#define _snprintf DUMMY__snprintf -#endif /* HAVE__SNPRINTF */ -#if HAVE__SNWPRINTF -#define _snwprintf DUMMY__snwprintf -#endif /* HAVE__SNWPRINTF */ #define tolower DUMMY_tolower #define toupper DUMMY_toupper #define islower DUMMY_islower @@ -217,9 +210,18 @@ function_name() to call the system's implementation #define sqrt DUMMY_sqrt #define tan DUMMY_tan #define tanh DUMMY_tanh +#define ceilf DUMMY_ceilf +#define cosf DUMMY_cosf +#define coshf DUMMY_coshf #define fabsf DUMMY_fabsf +#define floorf DUMMY_floorf #define fmodf DUMMY_fmodf #define modff DUMMY_modff +#define sinf DUMMY_sinf +#define sinhf DUMMY_sinhf +#define sqrtf DUMMY_sqrtf +#define tanf DUMMY_tanf +#define tanhf DUMMY_tanhf /* RAND_MAX needed to be renamed to avoid duplicate definition when including stdlib.h header files. PAL_RAND_MAX should have the same value as RAND_MAX @@ -349,9 +351,7 @@ function_name() to call the system's implementation #undef atexit #undef div #undef div_t -#if !defined(_DEBUG) #undef memcpy -#endif //!defined(_DEBUG) #undef memcmp #undef memset #undef memmove @@ -460,9 +460,26 @@ function_name() to call the system's implementation #undef sqrt #undef tan #undef tanh +#undef acosf +#undef asinf +#undef atanf +#undef atan2f +#undef ceilf +#undef cosf +#undef coshf +#undef expf #undef fabsf +#undef floorf #undef fmodf +#undef logf +#undef log10f #undef modff +#undef powf +#undef sinf +#undef sinhf +#undef sqrtf +#undef tanf +#undef tanhf #undef rand #undef srand #undef errno @@ -485,13 +502,7 @@ function_name() to call the system's implementation #undef vfwprintf #undef vprintf #undef wprintf -#undef sprintf #undef swprintf -#undef _snprintf -#if HAVE__SNWPRINTF -#undef _snwprintf -#endif /* HAVE__SNWPRINTF */ -#undef sscanf #undef wcstod #undef wcstol #undef wcstoul @@ -502,7 +513,6 @@ function_name() to call the system's implementation #undef wcsncmp #undef wcschr #undef wcsrchr -#undef wsprintf #undef swscanf #undef wcspbrk #undef wcsstr @@ -518,7 +528,6 @@ function_name() to call the system's implementation #undef vsprintf #undef vswprintf #undef _vsnprintf -#undef _vsnwprintf #undef vsnprintf #undef wvsnprintf @@ -689,7 +698,7 @@ inline T* InterlockedCompareExchangePointerT( #include "volatile.h" -const char StackOverflowMessage[] = "Process is terminated due to StackOverflowException.\n"; +const char StackOverflowMessage[] = "Process is terminating due to StackOverflowException.\n"; #endif // __cplusplus diff --git a/src/pal/src/init/pal.cpp b/src/pal/src/init/pal.cpp index a5edb36..0bda276 100644 --- a/src/pal/src/init/pal.cpp +++ b/src/pal/src/init/pal.cpp @@ -992,6 +992,7 @@ Return value: --*/ static BOOL INIT_IncreaseDescriptorLimit(void) { +#ifndef DONT_SET_RLIMIT_NOFILE struct rlimit rlp; int result; @@ -1008,7 +1009,7 @@ static BOOL INIT_IncreaseDescriptorLimit(void) { return FALSE; } - +#endif // !DONT_SET_RLIMIT_NOFILE return TRUE; } diff --git a/src/pal/src/map/virtual.cpp b/src/pal/src/map/virtual.cpp index 4b52096..4a55de9 100644 --- a/src/pal/src/map/virtual.cpp +++ b/src/pal/src/map/virtual.cpp @@ -1096,6 +1096,7 @@ VIRTUALCommitMemory( } StartBoundary = pInformation->startBoundary + runStart * VIRTUAL_PAGE_SIZE; + pRetVal = (void *)StartBoundary; MemSize = runLength * VIRTUAL_PAGE_SIZE; if (allocationType != MEM_COMMIT) @@ -1156,10 +1157,10 @@ error: pRetVal = NULL; goto done; } - pInformation = NULL; - pRetVal = NULL; } + pInformation = NULL; + pRetVal = NULL; done: LogVaOperation( diff --git a/src/pal/src/misc/sysinfo.cpp b/src/pal/src/misc/sysinfo.cpp index 515ccf1..e7589e8 100644 --- a/src/pal/src/misc/sysinfo.cpp +++ b/src/pal/src/misc/sysinfo.cpp @@ -172,7 +172,7 @@ GetSystemInfo( #ifdef VM_MAXUSER_ADDRESS lpSystemInfo->lpMaximumApplicationAddress = (PVOID) VM_MAXUSER_ADDRESS; #elif defined(__sun__) || defined(_AIX) || defined(__hppa__) || ( defined (_IA64_) && defined (_HPUX_) ) || defined(__linux__) - lpSystemInfo->lpMaximumApplicationAddress = (PVOID) -1; + lpSystemInfo->lpMaximumApplicationAddress = (PVOID) (1ull << 47); #elif defined(USERLIMIT) lpSystemInfo->lpMaximumApplicationAddress = (PVOID) USERLIMIT; #elif defined(_WIN64) diff --git a/src/pal/src/safecrt/input.inl b/src/pal/src/safecrt/input.inl index eaad174..25c4541 100644 --- a/src/pal/src/safecrt/input.inl +++ b/src/pal/src/safecrt/input.inl @@ -671,7 +671,7 @@ scanit: #endif /* _SECURE_SCANF */ #ifndef _UNICODE if (fl_wchar_arg) { - wctemp = L'?'; + wctemp = W('?'); char temp[2]; temp[0] = (char) ch; #if 0 // we are not supporting multibyte input strings @@ -682,7 +682,7 @@ scanit: #endif /* 0 */ _MBTOWC(&wctemp, temp, MB_CUR_MAX); *(wchar_t UNALIGNED *)pointer = wctemp; - /* just copy L'?' if mbtowc fails, errno is set by mbtowc */ + /* just copy W('?') if mbtowc fails, errno is set by mbtowc */ pointer = (wchar_t *)pointer + 1; #ifdef _SECURE_SCANF --array_width; diff --git a/src/pal/src/safecrt/makepath_s.c b/src/pal/src/safecrt/makepath_s.cpp similarity index 100% rename from src/pal/src/safecrt/makepath_s.c rename to src/pal/src/safecrt/makepath_s.cpp diff --git a/src/pal/src/safecrt/mbusafecrt.c b/src/pal/src/safecrt/mbusafecrt.c deleted file mode 100644 index ca853d9..0000000 --- a/src/pal/src/safecrt/mbusafecrt.c +++ /dev/null @@ -1,254 +0,0 @@ -// 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. - -/*** -* mbusafecrt.c - implementaion of support functions and data for MBUSafeCRT -* - -* -* Purpose: -* This file contains the implementation of support functions and -* data for MBUSafeCRT declared in mbusafecrt.h and mbusafecrt_internal.h. -****/ - -#include "pal/palinternal.h" -#include -#include -#include - -#include "mbusafecrt_internal.h" - -/* global data */ -tSafeCRT_AssertFuncPtr sMBUSafeCRTAssertFunc = NULL; - -/*** -* MBUSafeCRTSetAssertFunc - Set the function called when an assert fails. -****/ - -void MBUSafeCRTSetAssertFunc( tSafeCRT_AssertFuncPtr inAssertFuncPtr ) -{ - /* set it */ - sMBUSafeCRTAssertFunc = inAssertFuncPtr; -} - -/*** -* _putc_nolock - putc for the miniFILE stream. -****/ - -int _putc_nolock( char inChar, miniFILE* inStream ) -{ - int returnValue = EOF; - - inStream->_cnt -= sizeof( char ); - - if ( ( inStream->_cnt ) >= 0 ) - { - *( inStream->_ptr ) = inChar; - inStream->_ptr += sizeof( char ); - returnValue = ( int )inChar; - } - - return returnValue; -} - -/*** -* _putwc_nolock - putwc for the miniFILE stream. -****/ - -int _putwc_nolock( wchar_t inChar, miniFILE* inStream ) -{ - int returnValue = WEOF; - - inStream->_cnt -= sizeof( wchar_t ); - - if ( ( inStream->_cnt ) >= 0 ) - { - *( ( wchar_t* )( inStream->_ptr ) ) = inChar; - inStream->_ptr += sizeof( wchar_t ); - returnValue = ( int )inChar; - } - - return returnValue; -} - -/*** -* _getc_nolock - getc for the miniFILE stream. -****/ - -int _getc_nolock( miniFILE* inStream ) -{ - int returnValue = EOF; - - if ( ( inStream->_cnt ) >= ( int )( sizeof( char ) ) ) - { - inStream->_cnt -= sizeof( char ); - returnValue = ( int )( *( inStream->_ptr ) ); - inStream->_ptr += sizeof( char ); - } - - return returnValue; -} - -/*** -* _getwc_nolock - getc for the miniFILE stream. -****/ - -int _getwc_nolock( miniFILE* inStream ) -{ - int returnValue = EOF; - - if ( ( inStream->_cnt ) >= ( int )( sizeof( wchar_t ) ) ) - { - inStream->_cnt -= sizeof( wchar_t ); - returnValue = ( int )( *( ( wchar_t* )( inStream->_ptr ) ) ); - inStream->_ptr += sizeof( wchar_t ); - } - - return returnValue; -} - -/*** -* _ungetc_nolock - ungetc for the miniFILE stream. -****/ - -int _ungetc_nolock( char inChar, miniFILE* inStream ) -{ - int returnValue = EOF; - - if ( ( size_t )( ( inStream->_ptr ) - ( inStream->_base ) ) >= ( sizeof( char ) ) ) - { - inStream->_cnt += sizeof( char ); - inStream->_ptr -= sizeof( char ); - return ( int )inChar; - } - - return returnValue; -} - -/*** -* _ungetwc_nolock - ungetwc for the miniFILE stream. -****/ - -int _ungetwc_nolock( wchar_t inChar, miniFILE* inStream ) -{ - int returnValue = WEOF; - - if ( ( size_t )( ( inStream->_ptr ) - ( inStream->_base ) ) >= ( sizeof( wchar_t ) ) ) - { - inStream->_cnt += sizeof( wchar_t ); - inStream->_ptr -= sizeof( wchar_t ); - returnValue = ( unsigned short )inChar; - } - - return returnValue; -} - - -/*** -* _safecrt_cfltcvt - convert a float to an ascii string. -* Uses sprintf - this usage is OK. -****/ - -/* routine used for floating-point output */ -#define FORMATSIZE 30 - -#define _snprintf snprintf - -// taken from output.inl -#define FL_ALTERNATE 0x00080 /* alternate form requested */ - -errno_t _safecrt_cfltcvt(double *arg, char *buffer, size_t sizeInBytes, int type, int precision, int flags) -{ - char format[FORMATSIZE]; - size_t formatlen = 0; - int retvalue; - - if (flags & 1) - { - type -= 'a' - 'A'; - } - formatlen = 0; - format[formatlen++] = '%'; - if (flags & FL_ALTERNATE) - { - format[formatlen++] = '#'; - } - format[formatlen++] = '.'; - _itoa_s(precision, format + formatlen, FORMATSIZE - formatlen, 10); - formatlen = strlen(format); - format[formatlen++] = (char)type; - format[formatlen] = 0; - - buffer[sizeInBytes - 1] = 0; - retvalue = _snprintf(buffer, sizeInBytes, format, *arg); - if (buffer[sizeInBytes - 1] != 0 || retvalue <= 0) - { - buffer[0] = 0; - return EINVAL; - } - return 0; -} - - -/*** -* _safecrt_fassign - convert a string into a float or double. -****/ - -void _safecrt_fassign(int flag, void* argument, char* number ) -{ - if ( flag != 0 ) // double - { - double dblValue = 0.0; - (void)sscanf( number, "%lf", &dblValue ); - *( ( double* )argument ) = dblValue; - } - else // float - { - float fltValue = 0.0; - (void)sscanf( number, "%f", &fltValue ); - *( ( float* )argument ) = fltValue; - } -} - - -/*** -* _safecrt_wfassign - convert a wchar_t string into a float or double. -****/ - -void _safecrt_wfassign(int flag, void* argument, wchar_t* number ) -{ - // We cannot use system functions for this - they - // assume that wchar_t is four bytes, while we assume - // two. So, we need to convert to a regular char string - // without using any system functions. To do this, - // we'll assume that the numbers are in the 0-9 range and - // do a simple conversion. - - char* numberAsChars = ( char* )number; - int position = 0; - - // do the convert - while ( number[ position ] != 0 ) - { - numberAsChars[ position ] = ( char )( number[ position ] & 0x00FF ); - position++; - } - numberAsChars[ position ] = ( char )( number[ position ] & 0x00FF ); - - // call the normal char version - _safecrt_fassign( flag, argument, numberAsChars ); -} - - -/*** -* _minimal_chartowchar - do a simple char to wchar conversion. -****/ - -int _minimal_chartowchar( wchar_t* outWChar, const char* inChar ) -{ - *outWChar = ( wchar_t )( ( unsigned short )( ( unsigned char )( *inChar ) ) ); - return 1; -} - - diff --git a/src/pal/src/safecrt/mbusafecrt.cpp b/src/pal/src/safecrt/mbusafecrt.cpp new file mode 100644 index 0000000..4446f77 --- /dev/null +++ b/src/pal/src/safecrt/mbusafecrt.cpp @@ -0,0 +1,249 @@ +// 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. + +/*** +* mbusafecrt.c - implementaion of support functions and data for MBUSafeCRT +* + +* +* Purpose: +* This file contains the implementation of support functions and +* data for MBUSafeCRT declared in mbusafecrt.h and mbusafecrt_internal.h. +****/ + +#include "pal/palinternal.h" +#include +#include +#include + +#include "mbusafecrt_internal.h" + +/* global data */ +tSafeCRT_AssertFuncPtr sMBUSafeCRTAssertFunc = NULL; + +/*** +* MBUSafeCRTSetAssertFunc - Set the function called when an assert fails. +****/ + +void MBUSafeCRTSetAssertFunc( tSafeCRT_AssertFuncPtr inAssertFuncPtr ) +{ + /* set it */ + sMBUSafeCRTAssertFunc = inAssertFuncPtr; +} + +/*** +* _putc_nolock - putc for the miniFILE stream. +****/ + +int _putc_nolock( char inChar, miniFILE* inStream ) +{ + int returnValue = EOF; + + inStream->_cnt -= sizeof( char ); + + if ( ( inStream->_cnt ) >= 0 ) + { + *( inStream->_ptr ) = inChar; + inStream->_ptr += sizeof( char ); + returnValue = ( int )inChar; + } + + return returnValue; +} + +/*** +* _putwc_nolock - putwc for the miniFILE stream. +****/ + +int _putwc_nolock( wchar_t inChar, miniFILE* inStream ) +{ + int returnValue = WEOF; + + inStream->_cnt -= sizeof( wchar_t ); + + if ( ( inStream->_cnt ) >= 0 ) + { + *( ( wchar_t* )( inStream->_ptr ) ) = inChar; + inStream->_ptr += sizeof( wchar_t ); + returnValue = ( int )inChar; + } + + return returnValue; +} + +/*** +* _getc_nolock - getc for the miniFILE stream. +****/ + +int _getc_nolock( miniFILE* inStream ) +{ + int returnValue = EOF; + + if ( ( inStream->_cnt ) >= ( int )( sizeof( char ) ) ) + { + inStream->_cnt -= sizeof( char ); + returnValue = ( int )( *( inStream->_ptr ) ); + inStream->_ptr += sizeof( char ); + } + + return returnValue; +} + +/*** +* _getwc_nolock - getc for the miniFILE stream. +****/ + +int _getwc_nolock( miniFILE* inStream ) +{ + int returnValue = EOF; + + if ( ( inStream->_cnt ) >= ( int )( sizeof( wchar_t ) ) ) + { + inStream->_cnt -= sizeof( wchar_t ); + returnValue = ( int )( *( ( wchar_t* )( inStream->_ptr ) ) ); + inStream->_ptr += sizeof( wchar_t ); + } + + return returnValue; +} + +/*** +* _ungetc_nolock - ungetc for the miniFILE stream. +****/ + +int _ungetc_nolock( char inChar, miniFILE* inStream ) +{ + int returnValue = EOF; + + if ( ( size_t )( ( inStream->_ptr ) - ( inStream->_base ) ) >= ( sizeof( char ) ) ) + { + inStream->_cnt += sizeof( char ); + inStream->_ptr -= sizeof( char ); + return ( int )inChar; + } + + return returnValue; +} + +/*** +* _ungetwc_nolock - ungetwc for the miniFILE stream. +****/ + +int _ungetwc_nolock( wchar_t inChar, miniFILE* inStream ) +{ + int returnValue = WEOF; + + if ( ( size_t )( ( inStream->_ptr ) - ( inStream->_base ) ) >= ( sizeof( wchar_t ) ) ) + { + inStream->_cnt += sizeof( wchar_t ); + inStream->_ptr -= sizeof( wchar_t ); + returnValue = ( unsigned short )inChar; + } + + return returnValue; +} + + +/*** +* _safecrt_cfltcvt - convert a float to an ascii string. +****/ + +/* routine used for floating-point output */ +#define FORMATSIZE 30 + +// taken from output.inl +#define FL_ALTERNATE 0x00080 /* alternate form requested */ + +errno_t _safecrt_cfltcvt(double *arg, char *buffer, size_t sizeInBytes, int type, int precision, int flags) +{ + char format[FORMATSIZE]; + size_t formatlen = 0; + int retvalue; + + if (flags & 1) + { + type -= 'a' - 'A'; + } + formatlen = 0; + format[formatlen++] = '%'; + if (flags & FL_ALTERNATE) + { + format[formatlen++] = '#'; + } + format[formatlen++] = '.'; + _itoa_s(precision, format + formatlen, FORMATSIZE - formatlen, 10); + formatlen = strlen(format); + format[formatlen++] = (char)type; + format[formatlen] = 0; + + buffer[sizeInBytes - 1] = 0; + retvalue = snprintf(buffer, sizeInBytes, format, *arg); + if (buffer[sizeInBytes - 1] != 0 || retvalue <= 0) + { + buffer[0] = 0; + return EINVAL; + } + return 0; +} + + +/*** +* _safecrt_fassign - convert a string into a float or double. +****/ + +void _safecrt_fassign(int flag, void* argument, char* number ) +{ + if ( flag != 0 ) // double + { + double dblValue = strtod(number, NULL); + *( ( double* )argument ) = dblValue; + } + else // float + { + float fltValue = strtof(number, NULL); + *( ( float* )argument ) = fltValue; + } +} + + +/*** +* _safecrt_wfassign - convert a wchar_t string into a float or double. +****/ + +void _safecrt_wfassign(int flag, void* argument, wchar_t* number ) +{ + // We cannot use system functions for this - they + // assume that wchar_t is four bytes, while we assume + // two. So, we need to convert to a regular char string + // without using any system functions. To do this, + // we'll assume that the numbers are in the 0-9 range and + // do a simple conversion. + + char* numberAsChars = ( char* )number; + int position = 0; + + // do the convert + while ( number[ position ] != 0 ) + { + numberAsChars[ position ] = ( char )( number[ position ] & 0x00FF ); + position++; + } + numberAsChars[ position ] = ( char )( number[ position ] & 0x00FF ); + + // call the normal char version + _safecrt_fassign( flag, argument, numberAsChars ); +} + + +/*** +* _minimal_chartowchar - do a simple char to wchar conversion. +****/ + +int _minimal_chartowchar( wchar_t* outWChar, const char* inChar ) +{ + *outWChar = ( wchar_t )( ( unsigned short )( ( unsigned char )( *inChar ) ) ); + return 1; +} + + diff --git a/src/pal/src/safecrt/memcpy_s.c b/src/pal/src/safecrt/memcpy_s.cpp similarity index 100% rename from src/pal/src/safecrt/memcpy_s.c rename to src/pal/src/safecrt/memcpy_s.cpp diff --git a/src/pal/src/safecrt/memmove_s.c b/src/pal/src/safecrt/memmove_s.cpp similarity index 100% rename from src/pal/src/safecrt/memmove_s.c rename to src/pal/src/safecrt/memmove_s.cpp diff --git a/src/pal/src/safecrt/output.inl b/src/pal/src/safecrt/output.inl index ae0692e..5b86cf2 100644 --- a/src/pal/src/safecrt/output.inl +++ b/src/pal/src/safecrt/output.inl @@ -857,6 +857,12 @@ int __cdecl _output ( flags |= FL_LONG; /* 'l' => long int or wchar_t */ } break; + case _T('L'): + if (*format == _T('p')) + { + flags |= FL_LONG; + } + break; case _T('I'): /* @@ -956,7 +962,11 @@ int __cdecl _output ( #else /* _UNICODE */ if (flags & (FL_LONG|FL_WIDECHAR)) { wchar = (wchar_t) get_int_arg(&argptr); - no_output = 1; + textlen = snprintf(buffer.sz, BUFFERSIZE, "%lc", wchar); + if (textlen == 0) + { + no_output = 1; + } } else { /* format multibyte character */ /* this is an extension of ANSI */ @@ -1172,7 +1182,15 @@ int __cdecl _output ( precision = 2 * sizeof(void *); /* number of hex digits needed */ #if PTR_IS_INT64 - flags |= FL_I64; /* assume we're converting an int64 */ + if (flags & (FL_LONG | FL_SHORT)) + { + /* %lp, %Lp or %hp - these print 8 hex digits*/ + precision = 2 * sizeof(int32_t); + } + else + { + flags |= FL_I64; /* assume we're converting an int64 */ + } #elif !PTR_IS_INT flags |= FL_LONG; /* assume we're converting a long */ #endif /* !PTR_IS_INT */ @@ -1371,7 +1389,22 @@ int __cdecl _output ( /* write text */ #ifndef _UNICODE if (bufferiswide && (textlen > 0)) { - charsout = -1; + const WCHAR *p; + int mbCharCount; + int count; + char mbStr[5]; + + p = text.wz; + count = textlen; + while (count-- > 0) { + mbCharCount = snprintf(mbStr, sizeof(mbStr), "%lc", *p); + if (mbCharCount == 0) { + charsout = -1; + break; + } + WRITE_STRING(mbStr, mbCharCount, &charsout); + p++; + } } else { WRITE_STRING(text.sz, textlen, &charsout); } diff --git a/src/pal/src/safecrt/safecrt_input_s.c b/src/pal/src/safecrt/safecrt_input_s.cpp similarity index 100% rename from src/pal/src/safecrt/safecrt_input_s.c rename to src/pal/src/safecrt/safecrt_input_s.cpp diff --git a/src/pal/src/safecrt/safecrt_output_l.c b/src/pal/src/safecrt/safecrt_output_l.cpp similarity index 100% rename from src/pal/src/safecrt/safecrt_output_l.c rename to src/pal/src/safecrt/safecrt_output_l.cpp diff --git a/src/pal/src/safecrt/safecrt_output_s.c b/src/pal/src/safecrt/safecrt_output_s.cpp similarity index 100% rename from src/pal/src/safecrt/safecrt_output_s.c rename to src/pal/src/safecrt/safecrt_output_s.cpp diff --git a/src/pal/src/safecrt/safecrt_winput_s.c b/src/pal/src/safecrt/safecrt_winput_s.cpp similarity index 100% rename from src/pal/src/safecrt/safecrt_winput_s.c rename to src/pal/src/safecrt/safecrt_winput_s.cpp diff --git a/src/pal/src/safecrt/safecrt_woutput_s.c b/src/pal/src/safecrt/safecrt_woutput_s.cpp similarity index 100% rename from src/pal/src/safecrt/safecrt_woutput_s.c rename to src/pal/src/safecrt/safecrt_woutput_s.cpp diff --git a/src/pal/src/safecrt/snprintf.c b/src/pal/src/safecrt/snprintf.c deleted file mode 100644 index c892d1a..0000000 --- a/src/pal/src/safecrt/snprintf.c +++ /dev/null @@ -1,18 +0,0 @@ -// 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. - -/*** -*snprintf.c - "Count" version of sprintf -* - -* -*Purpose: -* The _snprintf() flavor takes a count argument that is -* the max number of bytes that should be written to the -* user's buffer. -* -*******************************************************************************/ - -#define _COUNT_ 1 -#include "sprintf.c" diff --git a/src/pal/src/safecrt/snprintf.cpp b/src/pal/src/safecrt/snprintf.cpp new file mode 100644 index 0000000..dea8716 --- /dev/null +++ b/src/pal/src/safecrt/snprintf.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*** +*snprintf.c - "Count" version of sprintf +* + +* +*Purpose: +* The sprintf_s() flavor takes a count argument that is +* the max number of bytes that should be written to the +* user's buffer. +* +*******************************************************************************/ + +#define _COUNT_ 1 +#include "sprintf.c" diff --git a/src/pal/src/safecrt/splitpath_s.c b/src/pal/src/safecrt/splitpath_s.cpp similarity index 100% rename from src/pal/src/safecrt/splitpath_s.c rename to src/pal/src/safecrt/splitpath_s.cpp diff --git a/src/pal/src/safecrt/sprintf.c b/src/pal/src/safecrt/sprintf.c deleted file mode 100644 index 5454179..0000000 --- a/src/pal/src/safecrt/sprintf.c +++ /dev/null @@ -1,98 +0,0 @@ -// 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. - -/*** -*sprintf.c - print formatted to string -* - -* -*Purpose: -* defines sprintf() and _snprintf() - print formatted data to string -* -*******************************************************************************/ - -#include -#include -#include -#include "internal_securecrt.h" - -#include "mbusafecrt_internal.h" - - -/*** -*ifndef _COUNT_ -*int sprintf(string, format, ...) - print formatted data to string -*else -*int _snprintf(string, cnt, format, ...) - print formatted data to string -*endif -* -*Purpose: -* Prints formatted data to the using the format string to -* format data and getting as many arguments as called for -* Sets up a FILE so file i/o operations can be used, make -* string look like a huge buffer to it, but _flsbuf will -* refuse to flush it if it fills up. Appends '\0' to make -* it a true string. _output does the real work here -* -* Allocate the 'fake' _iob[] entry statically instead of on -* the stack so that other routines can assume that _iob[] -* entries are in are in DGROUP and, thus, are near. -* -*ifdef _COUNT_ -* The _snprintf() flavor takes a count argument that is -* the max number of bytes that should be written to the -* user's buffer. -*endif -* -* Multi-thread: (1) Since there is no stream, this routine must -* never try to get the stream lock (i.e., there is no stream -* lock either). (2) Also, since there is only one statically -* allocated 'fake' iob, we must lock/unlock to prevent collisions. -* -*Entry: -* char *string - pointer to place to put output -*ifdef _COUNT_ -* size_t count - max number of bytes to put in buffer -*endif -* char *format - format string to control data format/number -* of arguments followed by list of arguments, number and type -* controlled by format string -* -*Exit: -* returns number of characters printed -* -*Exceptions: -* -*******************************************************************************/ - -int sprintf_s ( - char *string, - size_t sizeInBytes, - const char *format, - ... - ) -{ - int ret; - va_list arglist; - va_start(arglist, format); - ret = _vsprintf_s(string, sizeInBytes, format, arglist); - va_end(arglist); - return ret; -} - -int _snprintf_s ( - char *string, - size_t sizeInBytes, - size_t count, - const char *format, - ... - ) -{ - int ret; - va_list arglist; - va_start(arglist, format); - ret = _vsnprintf_s(string, sizeInBytes, count, format, arglist); - va_end(arglist); - return ret; -} diff --git a/src/pal/src/safecrt/sprintf_s.cpp b/src/pal/src/safecrt/sprintf_s.cpp new file mode 100644 index 0000000..edfb768 --- /dev/null +++ b/src/pal/src/safecrt/sprintf_s.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*** +*sprintf_s.c - print formatted to string +* + +* +*Purpose: +* defines sprintf_s() and _snprintf_s() - print formatted data to string +* +*******************************************************************************/ + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + + +/*** +*ifndef _COUNT_ +*int sprintf_s(string, format, ...) - print formatted data to string +*else +*int _snprintf_s(string, cnt, format, ...) - print formatted data to string +*endif +* +*Purpose: +* Prints formatted data to the using the format string to +* format data and getting as many arguments as called for +* Sets up a FILE so file i/o operations can be used, make +* string look like a huge buffer to it, but _flsbuf will +* refuse to flush it if it fills up. Appends '\0' to make +* it a true string. _output does the real work here +* +* Allocate the 'fake' _iob[] entry statically instead of on +* the stack so that other routines can assume that _iob[] +* entries are in are in DGROUP and, thus, are near. +* +*ifdef _COUNT_ +* The _snprintf_s() flavor takes a count argument that is +* the max number of bytes that should be written to the +* user's buffer. +*endif +* +* Multi-thread: (1) Since there is no stream, this routine must +* never try to get the stream lock (i.e., there is no stream +* lock either). (2) Also, since there is only one statically +* allocated 'fake' iob, we must lock/unlock to prevent collisions. +* +*Entry: +* char *string - pointer to place to put output +*ifdef _COUNT_ +* size_t count - max number of bytes to put in buffer +*endif +* char *format - format string to control data format/number +* of arguments followed by list of arguments, number and type +* controlled by format string +* +*Exit: +* returns number of characters printed +* +*Exceptions: +* +*******************************************************************************/ + +int sprintf_s ( + char *string, + size_t sizeInBytes, + const char *format, + ... + ) +{ + int ret; + va_list arglist; + va_start(arglist, format); + ret = vsprintf_s(string, sizeInBytes, format, arglist); + va_end(arglist); + return ret; +} + +int _snprintf_s ( + char *string, + size_t sizeInBytes, + size_t count, + const char *format, + ... + ) +{ + int ret; + va_list arglist; + va_start(arglist, format); + ret = _vsnprintf_s(string, sizeInBytes, count, format, arglist); + va_end(arglist); + return ret; +} diff --git a/src/pal/src/safecrt/sscanf.c b/src/pal/src/safecrt/sscanf.c deleted file mode 100644 index 94b5148..0000000 --- a/src/pal/src/safecrt/sscanf.c +++ /dev/null @@ -1,249 +0,0 @@ -// 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. - -/*** -*sscanf.c - read formatted data from string -* - -* -*Purpose: -* defines scanf() - reads formatted data from string -* -*******************************************************************************/ - -#include -#include -#include -#include "internal_securecrt.h" - -#include "mbusafecrt_internal.h" - -typedef int (*INPUTFN)(miniFILE *, const unsigned char*, va_list); -typedef int (*WINPUTFN)(miniFILE *, const unsigned short*, va_list); - - -/*** -*static int v[nw]scan_fn([w]inputfn, string, [count], format, ...) -* -*Purpose: -* this is a helper function which is called by the other functions -* in this file - sscanf/swscanf/snscanf etc. It calls either _(w)input or -* _(w)input_s depending on the first parameter. -* -*******************************************************************************/ - -static int __cdecl vscan_fn ( - INPUTFN inputfn, - const char *string, - const char *format, - va_list arglist - ) -{ - miniFILE str; - miniFILE *infile = &str; - int retval; - size_t count = strlen(string); - - _VALIDATE_RETURN( (string != NULL), EINVAL, EOF); - _VALIDATE_RETURN( (format != NULL), EINVAL, EOF); - - infile->_flag = _IOREAD|_IOSTRG|_IOMYBUF; - infile->_ptr = infile->_base = (char *) string; - - if(count>(INT_MAX/sizeof(char))) - { - /* old-style functions allow any large value to mean unbounded */ - infile->_cnt = INT_MAX; - } - else - { - infile->_cnt = (int)count*sizeof(char); - } - - retval = (inputfn(infile, ( const unsigned char* )format, arglist)); - - return(retval); -} - -static int __cdecl vnscan_fn ( - INPUTFN inputfn, - const char *string, - size_t count, - const char *format, - va_list arglist - ) -{ - miniFILE str; - miniFILE *infile = &str; - int retval; - size_t length = strlen(string); - - _VALIDATE_RETURN( (string != NULL), EINVAL, EOF); - _VALIDATE_RETURN( (format != NULL), EINVAL, EOF); - - infile->_flag = _IOREAD|_IOSTRG|_IOMYBUF; - infile->_ptr = infile->_base = (char *) string; - - if ( count > length ) - { - count = length; - } - - if(count>(INT_MAX/sizeof(char))) - { - /* old-style functions allow any large value to mean unbounded */ - infile->_cnt = INT_MAX; - } - else - { - infile->_cnt = (int)count*sizeof(char); - } - - retval = (inputfn(infile, ( const unsigned char* )format, arglist)); - - return(retval); -} - -static int __cdecl vwscan_fn ( - WINPUTFN inputfn, - const wchar_t *string, - const wchar_t *format, - va_list arglist - ) -{ - miniFILE str; - miniFILE *infile = &str; - int retval; - size_t count = wcsnlen(string, INT_MAX); - - _VALIDATE_RETURN( (string != NULL), EINVAL, EOF); - _VALIDATE_RETURN( (format != NULL), EINVAL, EOF); - - infile->_flag = _IOREAD|_IOSTRG|_IOMYBUF; - infile->_ptr = infile->_base = (char *) string; - - if(count>(INT_MAX/sizeof(wchar_t))) - { - /* old-style functions allow any large value to mean unbounded */ - infile->_cnt = INT_MAX; - } - else - { - infile->_cnt = (int)count*sizeof(wchar_t); - } - - retval = (inputfn(infile, format, arglist)); - - return(retval); -} - -static int __cdecl vnwscan_fn ( - WINPUTFN inputfn, - const wchar_t *string, - size_t count, - const wchar_t *format, - va_list arglist - ) -{ - miniFILE str; - miniFILE *infile = &str; - int retval; - size_t length = wcsnlen(string, INT_MAX); - - _VALIDATE_RETURN( (string != NULL), EINVAL, EOF); - _VALIDATE_RETURN( (format != NULL), EINVAL, EOF); - - infile->_flag = _IOREAD|_IOSTRG|_IOMYBUF; - infile->_ptr = infile->_base = (char *) string; - - if ( count > length ) - { - count = length; - } - - if(count>(INT_MAX/sizeof(wchar_t))) - { - /* old-style functions allow any large value to mean unbounded */ - infile->_cnt = INT_MAX; - } - else - { - infile->_cnt = (int)count*sizeof(wchar_t); - } - - retval = (inputfn(infile, format, arglist)); - - return(retval); -} - - -/*** -*int sscanf_s(string, format, ...) -* Same as sscanf above except that it calls _input_s to do the real work. -* -*int snscanf_s(string, size, format, ...) -* Same as snscanf above except that it calls _input_s to do the real work. -* -* _input_s has a size check for array parameters. -* -*******************************************************************************/ - -int __cdecl sscanf_s ( - const char *string, - const char *format, - ... - ) -{ - int ret; - va_list arglist; - va_start(arglist, format); - ret = vscan_fn(__tinput_s, string, format, arglist); - va_end(arglist); - return ret; -} - -int __cdecl _snscanf_s ( - const char *string, - size_t count, - const char *format, - ... - ) -{ - int ret; - va_list arglist; - va_start(arglist, format); - ret = vnscan_fn(__tinput_s, string, count, format, arglist); - va_end(arglist); - return ret; -} - -int __cdecl swscanf_s ( - const wchar_t *string, - const wchar_t *format, - ... - ) -{ - int ret; - va_list arglist; - va_start(arglist, format); - ret = vwscan_fn(__twinput_s, string, format, arglist); - va_end(arglist); - return ret; -} - -int __cdecl _snwscanf_s ( - const wchar_t *string, - size_t count, - const wchar_t *format, - ... - ) -{ - int ret; - va_list arglist; - va_start(arglist, format); - ret = vnwscan_fn(__twinput_s, string, count, format, arglist); - va_end(arglist); - return ret; -} - diff --git a/src/pal/src/safecrt/sscanf_s.cpp b/src/pal/src/safecrt/sscanf_s.cpp new file mode 100644 index 0000000..4f548bc --- /dev/null +++ b/src/pal/src/safecrt/sscanf_s.cpp @@ -0,0 +1,249 @@ +// 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. + +/*** +*sscanf_s.c - read formatted data from string +* + +* +*Purpose: +* defines scanf() - reads formatted data from string +* +*******************************************************************************/ + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +typedef int (*INPUTFN)(miniFILE *, const unsigned char*, va_list); +typedef int (*WINPUTFN)(miniFILE *, const wchar_t*, va_list); + + +/*** +*static int v[nw]scan_fn([w]inputfn, string, [count], format, ...) +* +*Purpose: +* this is a helper function which is called by the other functions +* in this file - sscanf/swscanf/snscanf etc. It calls either _(w)input or +* _(w)input_s depending on the first parameter. +* +*******************************************************************************/ + +static int __cdecl vscan_fn ( + INPUTFN inputfn, + const char *string, + const char *format, + va_list arglist + ) +{ + miniFILE str; + miniFILE *infile = &str; + int retval; + size_t count = strlen(string); + + _VALIDATE_RETURN( (string != NULL), EINVAL, EOF); + _VALIDATE_RETURN( (format != NULL), EINVAL, EOF); + + infile->_flag = _IOREAD|_IOSTRG|_IOMYBUF; + infile->_ptr = infile->_base = (char *) string; + + if(count>(INT_MAX/sizeof(char))) + { + /* old-style functions allow any large value to mean unbounded */ + infile->_cnt = INT_MAX; + } + else + { + infile->_cnt = (int)count*sizeof(char); + } + + retval = (inputfn(infile, ( const unsigned char* )format, arglist)); + + return(retval); +} + +static int __cdecl vnscan_fn ( + INPUTFN inputfn, + const char *string, + size_t count, + const char *format, + va_list arglist + ) +{ + miniFILE str; + miniFILE *infile = &str; + int retval; + size_t length = strlen(string); + + _VALIDATE_RETURN( (string != NULL), EINVAL, EOF); + _VALIDATE_RETURN( (format != NULL), EINVAL, EOF); + + infile->_flag = _IOREAD|_IOSTRG|_IOMYBUF; + infile->_ptr = infile->_base = (char *) string; + + if ( count > length ) + { + count = length; + } + + if(count>(INT_MAX/sizeof(char))) + { + /* old-style functions allow any large value to mean unbounded */ + infile->_cnt = INT_MAX; + } + else + { + infile->_cnt = (int)count*sizeof(char); + } + + retval = (inputfn(infile, ( const unsigned char* )format, arglist)); + + return(retval); +} + +static int __cdecl vwscan_fn ( + WINPUTFN inputfn, + const wchar_t *string, + const wchar_t *format, + va_list arglist + ) +{ + miniFILE str; + miniFILE *infile = &str; + int retval; + size_t count = wcsnlen(string, INT_MAX); + + _VALIDATE_RETURN( (string != NULL), EINVAL, EOF); + _VALIDATE_RETURN( (format != NULL), EINVAL, EOF); + + infile->_flag = _IOREAD|_IOSTRG|_IOMYBUF; + infile->_ptr = infile->_base = (char *) string; + + if(count>(INT_MAX/sizeof(wchar_t))) + { + /* old-style functions allow any large value to mean unbounded */ + infile->_cnt = INT_MAX; + } + else + { + infile->_cnt = (int)count*sizeof(wchar_t); + } + + retval = (inputfn(infile, format, arglist)); + + return(retval); +} + +static int __cdecl vnwscan_fn ( + WINPUTFN inputfn, + const wchar_t *string, + size_t count, + const wchar_t *format, + va_list arglist + ) +{ + miniFILE str; + miniFILE *infile = &str; + int retval; + size_t length = wcsnlen(string, INT_MAX); + + _VALIDATE_RETURN( (string != NULL), EINVAL, EOF); + _VALIDATE_RETURN( (format != NULL), EINVAL, EOF); + + infile->_flag = _IOREAD|_IOSTRG|_IOMYBUF; + infile->_ptr = infile->_base = (char *) string; + + if ( count > length ) + { + count = length; + } + + if(count>(INT_MAX/sizeof(wchar_t))) + { + /* old-style functions allow any large value to mean unbounded */ + infile->_cnt = INT_MAX; + } + else + { + infile->_cnt = (int)count*sizeof(wchar_t); + } + + retval = (inputfn(infile, format, arglist)); + + return(retval); +} + + +/*** +*int sscanf_s(string, format, ...) +* Same as sscanf above except that it calls _input_s to do the real work. +* +*int snscanf_s(string, size, format, ...) +* Same as snscanf above except that it calls _input_s to do the real work. +* +* _input_s has a size check for array parameters. +* +*******************************************************************************/ + +int __cdecl sscanf_s ( + const char *string, + const char *format, + ... + ) +{ + int ret; + va_list arglist; + va_start(arglist, format); + ret = vscan_fn(__tinput_s, string, format, arglist); + va_end(arglist); + return ret; +} + +int __cdecl _snscanf_s ( + const char *string, + size_t count, + const char *format, + ... + ) +{ + int ret; + va_list arglist; + va_start(arglist, format); + ret = vnscan_fn(__tinput_s, string, count, format, arglist); + va_end(arglist); + return ret; +} + +int __cdecl swscanf_s ( + const wchar_t *string, + const wchar_t *format, + ... + ) +{ + int ret; + va_list arglist; + va_start(arglist, format); + ret = vwscan_fn(__twinput_s, string, format, arglist); + va_end(arglist); + return ret; +} + +int __cdecl _snwscanf_s ( + const wchar_t *string, + size_t count, + const wchar_t *format, + ... + ) +{ + int ret; + va_list arglist; + va_start(arglist, format); + ret = vnwscan_fn(__twinput_s, string, count, format, arglist); + va_end(arglist); + return ret; +} + diff --git a/src/pal/src/safecrt/strcat_s.c b/src/pal/src/safecrt/strcat_s.cpp similarity index 100% rename from src/pal/src/safecrt/strcat_s.c rename to src/pal/src/safecrt/strcat_s.cpp diff --git a/src/pal/src/safecrt/strcpy_s.c b/src/pal/src/safecrt/strcpy_s.cpp similarity index 100% rename from src/pal/src/safecrt/strcpy_s.c rename to src/pal/src/safecrt/strcpy_s.cpp diff --git a/src/pal/src/safecrt/strlen_s.c b/src/pal/src/safecrt/strlen_s.c deleted file mode 100644 index 34c1308..0000000 --- a/src/pal/src/safecrt/strlen_s.c +++ /dev/null @@ -1,58 +0,0 @@ -// 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. - -/*** -*strlen_s.c - contains strnlen() routine -* - -* -*Purpose: -* strnlen returns the length of a null-terminated string, -* not including the null byte itself, up to the specified max size -* -*******************************************************************************/ - - -#include -#include -#include -#include "internal_securecrt.h" - -#include "mbusafecrt_internal.h" - -/*** -*strnlen - return the length of a null-terminated string -* -*Purpose: -* Finds the length in bytes of the given string, not including -* the final null character. Only the first maxsize characters -* are inspected: if the null character is not found, maxsize is -* returned. -* -*Entry: -* const char * str - string whose length is to be computed -* size_t maxsize -* -*Exit: -* Length of the string "str", exclusive of the final null byte, or -* maxsize if the null character is not found. -* -*Exceptions: -* -*******************************************************************************/ - -size_t __cdecl strnlen(const char *str, size_t maxsize) -{ - size_t n; - - /* Note that we do not check if str == NULL, because we do not - * return errno_t... - */ - - for (n = 0; n < maxsize && *str; n++, str++) - ; - - return n; -} - diff --git a/src/pal/src/safecrt/strlen_s.cpp b/src/pal/src/safecrt/strlen_s.cpp new file mode 100644 index 0000000..3f1e1cf --- /dev/null +++ b/src/pal/src/safecrt/strlen_s.cpp @@ -0,0 +1,58 @@ +// 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. + +/*** +*strlen_s.c - contains strnlen() routine +* + +* +*Purpose: +* strnlen returns the length of a null-terminated string, +* not including the null byte itself, up to the specified max size +* +*******************************************************************************/ + + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +/*** +*strnlen - return the length of a null-terminated string +* +*Purpose: +* Finds the length in bytes of the given string, not including +* the final null character. Only the first maxsize characters +* are inspected: if the null character is not found, maxsize is +* returned. +* +*Entry: +* const char * str - string whose length is to be computed +* size_t maxsize +* +*Exit: +* Length of the string "str", exclusive of the final null byte, or +* maxsize if the null character is not found. +* +*Exceptions: +* +*******************************************************************************/ + +size_t __cdecl PAL_strnlen(const char *str, size_t maxsize) +{ + size_t n; + + /* Note that we do not check if str == NULL, because we do not + * return errno_t... + */ + + for (n = 0; n < maxsize && *str; n++, str++) + ; + + return n; +} + diff --git a/src/pal/src/safecrt/strncat_s.c b/src/pal/src/safecrt/strncat_s.cpp similarity index 100% rename from src/pal/src/safecrt/strncat_s.c rename to src/pal/src/safecrt/strncat_s.cpp diff --git a/src/pal/src/safecrt/strncpy_s.c b/src/pal/src/safecrt/strncpy_s.cpp similarity index 100% rename from src/pal/src/safecrt/strncpy_s.c rename to src/pal/src/safecrt/strncpy_s.cpp diff --git a/src/pal/src/safecrt/strtok_s.c b/src/pal/src/safecrt/strtok_s.cpp similarity index 100% rename from src/pal/src/safecrt/strtok_s.c rename to src/pal/src/safecrt/strtok_s.cpp diff --git a/src/pal/src/safecrt/swprintf.c b/src/pal/src/safecrt/swprintf.c deleted file mode 100644 index 75004ea..0000000 --- a/src/pal/src/safecrt/swprintf.c +++ /dev/null @@ -1,120 +0,0 @@ -// 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. - -/*** -*swprintf.c - print formatted to string -* -*Purpose: -* defines _swprintf(), _swprintf_c and _snwprintf() - print formatted data -* to string -* -*******************************************************************************/ - -#include -#include -#include -#include "internal_securecrt.h" - -#include "mbusafecrt_internal.h" - -/*** -*ifndef _COUNT_ -*int _swprintf(string, format, ...) - print formatted data to string -*else -*ifndef _SWPRINTFS_ERROR_RETURN_FIX -*int _snwprintf(string, cnt, format, ...) - print formatted data to string -*else -*int _swprintf_c(string, cnt, format, ...) - print formatted data to string -*endif -*endif -* -*Purpose: -* Prints formatted data to the using the format string to -* format data and getting as many arguments as called for -* Sets up a FILE so file i/o operations can be used, make -* string look like a huge buffer to it, but _flsbuf will -* refuse to flush it if it fills up. Appends '\0' to make -* it a true string. _output does the real work here -* -* Allocate the 'fake' _iob[] entry statically instead of on -* the stack so that other routines can assume that _iob[] -* entries are in are in DGROUP and, thus, are near. -* -* We alias swprintf to _swprintf -* -*ifdef _COUNT_ -*ifndef _SWPRINTFS_ERROR_RETURN_FIX -* The _snwprintf() flavor takes a count argument that is -* the max number of wide characters that should be written to the -* user's buffer. -* We don't expose this function directly in the headers. -*else -* The _swprintf_c() flavor does the same thing as the _snwprintf -* above, but, it also fixes a issue in the return value in the case -* when there isn't enough space to write the null terminator -* We don't fix this issue in _snwprintf because of backward -* compatibility. In new code, however, _snwprintf is #defined to -* _swprintf_c so users get the fix. -* -*endif -* -* Multi-thread: (1) Since there is no stream, this routine must -* never try to get the stream lock (i.e., there is no stream -* lock either). (2) Also, since there is only one statically -* allocated 'fake' iob, we must lock/unlock to prevent collisions. -* -*Entry: -* wchar_t *string - pointer to place to put output -*ifdef _COUNT_ -* size_t count - max number of wide characters to put in buffer -*endif -* wchar_t *format - format string to control data format/number -* of arguments followed by list of arguments, number and type -* controlled by format string -* -*Exit: -* returns number of wide characters printed -* -*Exceptions: -* -*******************************************************************************/ - -int __cdecl swprintf_s ( - wchar_t *string, - size_t sizeInWords, - const wchar_t *format, - ... - ) -{ - int ret; - va_list arglist; - - va_start(arglist, format); - - ret = _vswprintf_s(string, sizeInWords, format, arglist); - - va_end(arglist); - - return ret; -} - -int __cdecl _snwprintf_s ( - wchar_t *string, - size_t sizeInWords, - size_t count, - const wchar_t *format, - ... - ) -{ - int ret; - va_list arglist; - - va_start(arglist, format); - - ret = _vsnwprintf_s(string, sizeInWords, count, format, arglist); - - va_end(arglist); - - return ret; -} diff --git a/src/pal/src/safecrt/swprintf.cpp b/src/pal/src/safecrt/swprintf.cpp new file mode 100644 index 0000000..2fbfcfa --- /dev/null +++ b/src/pal/src/safecrt/swprintf.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*** +*swprintf.c - print formatted to string +* +*Purpose: +* defines _swprintf(), _swprintf_c and _snwprintf() - print formatted data +* to string +* +*******************************************************************************/ + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +/*** +*ifndef _COUNT_ +*int _swprintf(string, format, ...) - print formatted data to string +*else +*ifndef _SWPRINTFS_ERROR_RETURN_FIX +*int _snwprintf(string, cnt, format, ...) - print formatted data to string +*else +*int _swprintf_c(string, cnt, format, ...) - print formatted data to string +*endif +*endif +* +*Purpose: +* Prints formatted data to the using the format string to +* format data and getting as many arguments as called for +* Sets up a FILE so file i/o operations can be used, make +* string look like a huge buffer to it, but _flsbuf will +* refuse to flush it if it fills up. Appends '\0' to make +* it a true string. _output does the real work here +* +* Allocate the 'fake' _iob[] entry statically instead of on +* the stack so that other routines can assume that _iob[] +* entries are in are in DGROUP and, thus, are near. +* +* We alias swprintf to _swprintf +* +*ifdef _COUNT_ +*ifndef _SWPRINTFS_ERROR_RETURN_FIX +* The _snwprintf() flavor takes a count argument that is +* the max number of wide characters that should be written to the +* user's buffer. +* We don't expose this function directly in the headers. +*else +* The _swprintf_c() flavor does the same thing as the _snwprintf +* above, but, it also fixes a issue in the return value in the case +* when there isn't enough space to write the null terminator +* We don't fix this issue in _snwprintf because of backward +* compatibility. In new code, however, _snwprintf is #defined to +* _swprintf_c so users get the fix. +* +*endif +* +* Multi-thread: (1) Since there is no stream, this routine must +* never try to get the stream lock (i.e., there is no stream +* lock either). (2) Also, since there is only one statically +* allocated 'fake' iob, we must lock/unlock to prevent collisions. +* +*Entry: +* wchar_t *string - pointer to place to put output +*ifdef _COUNT_ +* size_t count - max number of wide characters to put in buffer +*endif +* wchar_t *format - format string to control data format/number +* of arguments followed by list of arguments, number and type +* controlled by format string +* +*Exit: +* returns number of wide characters printed +* +*Exceptions: +* +*******************************************************************************/ + +int __cdecl swprintf_s ( + wchar_t *string, + size_t sizeInWords, + const wchar_t *format, + ... + ) +{ + int ret; + va_list arglist; + + va_start(arglist, format); + + ret = vswprintf_s(string, sizeInWords, format, arglist); + + va_end(arglist); + + return ret; +} + +int __cdecl _snwprintf_s ( + wchar_t *string, + size_t sizeInWords, + size_t count, + const wchar_t *format, + ... + ) +{ + int ret; + va_list arglist; + + va_start(arglist, format); + + ret = _vsnwprintf_s(string, sizeInWords, count, format, arglist); + + va_end(arglist); + + return ret; +} diff --git a/src/pal/src/safecrt/vsprintf.c b/src/pal/src/safecrt/vsprintf.c deleted file mode 100644 index 4f2bd9f..0000000 --- a/src/pal/src/safecrt/vsprintf.c +++ /dev/null @@ -1,268 +0,0 @@ -// 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. - -/*** -*vsprintf.c - print formatted data into a string from var arg list -* - -* -*Purpose: -* defines vsprintf(), _vsnprintf() and _vsnprintf_s() - print formatted output to -* a string, get the data from an argument ptr instead of explicit -* arguments. -* -*******************************************************************************/ - -#include -#include -#include -#include "internal_securecrt.h" - -#include "mbusafecrt_internal.h" - -typedef int (*OUTPUTFN)(miniFILE *, const char *, va_list); - -static int _vsnprintf_helper( OUTPUTFN outfn, char *string, size_t count, const char *format, va_list ap ); -static int _vscprintf_helper ( OUTPUTFN outfn, const char *format, va_list ap); - -/*** -*ifndef _COUNT_ -*int vsprintf(string, format, ap) - print formatted data to string from arg ptr -*else -*int _vsnprintf(string, cnt, format, ap) - print formatted data to string from arg ptr -*endif -* -*Purpose: -* Prints formatted data, but to a string and gets data from an argument -* pointer. -* Sets up a FILE so file i/o operations can be used, make string look -* like a huge buffer to it, but _flsbuf will refuse to flush it if it -* fills up. Appends '\0' to make it a true string. -* -* Allocate the 'fake' _iob[] entryit statically instead of on -* the stack so that other routines can assume that _iob[] entries are in -* are in DGROUP and, thus, are near. -* -*ifdef _COUNT_ -* The _vsnprintf() flavor takes a count argument that is -* the max number of bytes that should be written to the -* user's buffer. -*endif -* -* Multi-thread: (1) Since there is no stream, this routine must never try -* to get the stream lock (i.e., there is no stream lock either). (2) -* Also, since there is only one staticly allocated 'fake' iob, we must -* lock/unlock to prevent collisions. -* -*Entry: -* char *string - place to put destination string -*ifdef _COUNT_ -* size_t count - max number of bytes to put in buffer -*endif -* char *format - format string, describes format of data -* va_list ap - varargs argument pointer -* -*Exit: -* returns number of characters in string -* returns -2 if the string has been truncated (only in _vsnprintf_helper) -* returns -1 in other error cases -* -*Exceptions: -* -*******************************************************************************/ - -int __cdecl _vsnprintf_helper ( - OUTPUTFN outfn, - char *string, - size_t count, - const char *format, - va_list ap - ) -{ - miniFILE str; - miniFILE *outfile = &str; - int retval; - - _VALIDATE_RETURN( (format != NULL), EINVAL, -1); - - _VALIDATE_RETURN( (count == 0) || (string != NULL), EINVAL, -1 ); - - if(count>INT_MAX) - { - /* old-style functions allow any large value to mean unbounded */ - outfile->_cnt = INT_MAX; - } - else - { - outfile->_cnt = (int)count; - } - - outfile->_flag = _IOWRT|_IOSTRG; - outfile->_ptr = outfile->_base = string; - - retval = outfn(outfile, format, ap ); - - if ( string==NULL) - return(retval); - - if((retval >= 0) && (_putc_nolock('\0',outfile) != EOF)) - return(retval); - - string[count - 1] = 0; - - if (outfile->_cnt < 0) - { - /* the buffer was too small; we return -2 to indicate truncation */ - return -2; - } - return -1; -} - -int __cdecl _vsprintf_s ( - char *string, - size_t sizeInBytes, - const char *format, - va_list ap - ) -{ - int retvalue = -1; - - /* validation section */ - _VALIDATE_RETURN(format != NULL, EINVAL, -1); - _VALIDATE_RETURN(string != NULL && sizeInBytes > 0, EINVAL, -1); - - retvalue = _vsnprintf_helper(_output_s, string, sizeInBytes, format, ap); - if (retvalue < 0) - { - string[0] = 0; - _SECURECRT__FILL_STRING(string, sizeInBytes, 1); - } - if (retvalue == -2) - { - _VALIDATE_RETURN(("Buffer too small" && 0), ERANGE, -1); - } - if (retvalue >= 0) - { - _SECURECRT__FILL_STRING(string, sizeInBytes, retvalue + 1); - } - - return retvalue; -} - -int __cdecl _vsnprintf_s ( - char *string, - size_t sizeInBytes, - size_t count, - const char *format, - va_list ap - ) -{ - int retvalue = -1; - errno_t save_errno = 0; - - /* validation section */ - _VALIDATE_RETURN(format != NULL, EINVAL, -1); - if (count == 0 && string == NULL && sizeInBytes == 0) - { - /* this case is allowed; nothing to do */ - return 0; - } - _VALIDATE_RETURN(string != NULL && sizeInBytes > 0, EINVAL, -1); - - if (sizeInBytes > count) - { - save_errno = errno; - retvalue = _vsnprintf_helper(_output_s, string, count + 1, format, ap); - if (retvalue == -2) - { - /* the string has been truncated, return -1 */ - _SECURECRT__FILL_STRING(string, sizeInBytes, count + 1); - if (errno == ERANGE) - { - errno = save_errno; - } - return -1; - } - } - else /* sizeInBytes <= count */ - { - save_errno = errno; - retvalue = _vsnprintf_helper(_output_s, string, sizeInBytes, format, ap); - string[sizeInBytes - 1] = 0; - /* we allow truncation if count == _TRUNCATE */ - if (retvalue == -2 && count == _TRUNCATE) - { - if (errno == ERANGE) - { - errno = save_errno; - } - return -1; - } - } - - if (retvalue < 0) - { - string[0] = 0; - _SECURECRT__FILL_STRING(string, sizeInBytes, 1); - if (retvalue == -2) - { - _VALIDATE_RETURN(("Buffer too small" && 0), ERANGE, -1); - } - return -1; - } - - _SECURECRT__FILL_STRING(string, sizeInBytes, retvalue + 1); - - return (retvalue < 0 ? -1 : retvalue); -} - -/*** -* _vscprintf() - counts the number of character needed to print the formatted -* data -* -*Purpose: -* Counts the number of characters in the fotmatted data. -* -*Entry: -* char *format - format string, describes format of data -* va_list ap - varargs argument pointer -* -*Exit: -* returns number of characters needed to print formatted data. -* -*Exceptions: -* -*******************************************************************************/ - -#ifndef _COUNT_ - -int __cdecl _vscprintf_helper ( - OUTPUTFN outfn, - const char *format, - va_list ap - ) -{ - miniFILE str; - miniFILE *outfile = &str; - int retval; - - _VALIDATE_RETURN( (format != NULL), EINVAL, -1); - - outfile->_cnt = INT_MAX; //MAXSTR; - outfile->_flag = _IOWRT|_IOSTRG; - outfile->_ptr = outfile->_base = NULL; - - retval = outfn(outfile, format, ap); - return(retval); -} - -int __cdecl _vscprintf ( - const char *format, - va_list ap - ) -{ - return _vscprintf_helper(_output, format, ap); -} - -#endif /* _COUNT_ */ diff --git a/src/pal/src/safecrt/vsprintf.cpp b/src/pal/src/safecrt/vsprintf.cpp new file mode 100644 index 0000000..e1a94d0 --- /dev/null +++ b/src/pal/src/safecrt/vsprintf.cpp @@ -0,0 +1,268 @@ +// 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. + +/*** +*vsprintf.c - print formatted data into a string from var arg list +* + +* +*Purpose: +* defines vsprintf(), _vsnprintf() and _vsnprintf_s() - print formatted output to +* a string, get the data from an argument ptr instead of explicit +* arguments. +* +*******************************************************************************/ + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +typedef int (*OUTPUTFN)(miniFILE *, const char *, va_list); + +static int _vsnprintf_helper( OUTPUTFN outfn, char *string, size_t count, const char *format, va_list ap ); +static int _vscprintf_helper ( OUTPUTFN outfn, const char *format, va_list ap); + +/*** +*ifndef _COUNT_ +*int vsprintf(string, format, ap) - print formatted data to string from arg ptr +*else +*int _vsnprintf(string, cnt, format, ap) - print formatted data to string from arg ptr +*endif +* +*Purpose: +* Prints formatted data, but to a string and gets data from an argument +* pointer. +* Sets up a FILE so file i/o operations can be used, make string look +* like a huge buffer to it, but _flsbuf will refuse to flush it if it +* fills up. Appends '\0' to make it a true string. +* +* Allocate the 'fake' _iob[] entryit statically instead of on +* the stack so that other routines can assume that _iob[] entries are in +* are in DGROUP and, thus, are near. +* +*ifdef _COUNT_ +* The _vsnprintf() flavor takes a count argument that is +* the max number of bytes that should be written to the +* user's buffer. +*endif +* +* Multi-thread: (1) Since there is no stream, this routine must never try +* to get the stream lock (i.e., there is no stream lock either). (2) +* Also, since there is only one staticly allocated 'fake' iob, we must +* lock/unlock to prevent collisions. +* +*Entry: +* char *string - place to put destination string +*ifdef _COUNT_ +* size_t count - max number of bytes to put in buffer +*endif +* char *format - format string, describes format of data +* va_list ap - varargs argument pointer +* +*Exit: +* returns number of characters in string +* returns -2 if the string has been truncated (only in _vsnprintf_helper) +* returns -1 in other error cases +* +*Exceptions: +* +*******************************************************************************/ + +int __cdecl _vsnprintf_helper ( + OUTPUTFN outfn, + char *string, + size_t count, + const char *format, + va_list ap + ) +{ + miniFILE str; + miniFILE *outfile = &str; + int retval; + + _VALIDATE_RETURN( (format != NULL), EINVAL, -1); + + _VALIDATE_RETURN( (count == 0) || (string != NULL), EINVAL, -1 ); + + if(count>INT_MAX) + { + /* old-style functions allow any large value to mean unbounded */ + outfile->_cnt = INT_MAX; + } + else + { + outfile->_cnt = (int)count; + } + + outfile->_flag = _IOWRT|_IOSTRG; + outfile->_ptr = outfile->_base = string; + + retval = outfn(outfile, format, ap ); + + if ( string==NULL) + return(retval); + + if((retval >= 0) && (_putc_nolock('\0',outfile) != EOF)) + return(retval); + + string[count - 1] = 0; + + if (outfile->_cnt < 0) + { + /* the buffer was too small; we return -2 to indicate truncation */ + return -2; + } + return -1; +} + +int __cdecl vsprintf_s ( + char *string, + size_t sizeInBytes, + const char *format, + va_list ap + ) +{ + int retvalue = -1; + + /* validation section */ + _VALIDATE_RETURN(format != NULL, EINVAL, -1); + _VALIDATE_RETURN(string != NULL && sizeInBytes > 0, EINVAL, -1); + + retvalue = _vsnprintf_helper(_output_s, string, sizeInBytes, format, ap); + if (retvalue < 0) + { + string[0] = 0; + _SECURECRT__FILL_STRING(string, sizeInBytes, 1); + } + if (retvalue == -2) + { + _VALIDATE_RETURN(("Buffer too small" && 0), ERANGE, -1); + } + if (retvalue >= 0) + { + _SECURECRT__FILL_STRING(string, sizeInBytes, retvalue + 1); + } + + return retvalue; +} + +int __cdecl _vsnprintf_s ( + char *string, + size_t sizeInBytes, + size_t count, + const char *format, + va_list ap + ) +{ + int retvalue = -1; + errno_t save_errno = 0; + + /* validation section */ + _VALIDATE_RETURN(format != NULL, EINVAL, -1); + if (count == 0 && string == NULL && sizeInBytes == 0) + { + /* this case is allowed; nothing to do */ + return 0; + } + _VALIDATE_RETURN(string != NULL && sizeInBytes > 0, EINVAL, -1); + + if (sizeInBytes > count) + { + save_errno = errno; + retvalue = _vsnprintf_helper(_output_s, string, count + 1, format, ap); + if (retvalue == -2) + { + /* the string has been truncated, return -1 */ + _SECURECRT__FILL_STRING(string, sizeInBytes, count + 1); + if (errno == ERANGE) + { + errno = save_errno; + } + return -1; + } + } + else /* sizeInBytes <= count */ + { + save_errno = errno; + retvalue = _vsnprintf_helper(_output_s, string, sizeInBytes, format, ap); + string[sizeInBytes - 1] = 0; + /* we allow truncation if count == _TRUNCATE */ + if (retvalue == -2 && count == _TRUNCATE) + { + if (errno == ERANGE) + { + errno = save_errno; + } + return -1; + } + } + + if (retvalue < 0) + { + string[0] = 0; + _SECURECRT__FILL_STRING(string, sizeInBytes, 1); + if (retvalue == -2) + { + _VALIDATE_RETURN(("Buffer too small" && 0), ERANGE, -1); + } + return -1; + } + + _SECURECRT__FILL_STRING(string, sizeInBytes, retvalue + 1); + + return (retvalue < 0 ? -1 : retvalue); +} + +/*** +* _vscprintf() - counts the number of character needed to print the formatted +* data +* +*Purpose: +* Counts the number of characters in the fotmatted data. +* +*Entry: +* char *format - format string, describes format of data +* va_list ap - varargs argument pointer +* +*Exit: +* returns number of characters needed to print formatted data. +* +*Exceptions: +* +*******************************************************************************/ + +#ifndef _COUNT_ + +int __cdecl _vscprintf_helper ( + OUTPUTFN outfn, + const char *format, + va_list ap + ) +{ + miniFILE str; + miniFILE *outfile = &str; + int retval; + + _VALIDATE_RETURN( (format != NULL), EINVAL, -1); + + outfile->_cnt = INT_MAX; //MAXSTR; + outfile->_flag = _IOWRT|_IOSTRG; + outfile->_ptr = outfile->_base = NULL; + + retval = outfn(outfile, format, ap); + return(retval); +} + +int __cdecl _vscprintf ( + const char *format, + va_list ap + ) +{ + return _vscprintf_helper(_output, format, ap); +} + +#endif /* _COUNT_ */ diff --git a/src/pal/src/safecrt/vswprint.c b/src/pal/src/safecrt/vswprint.c deleted file mode 100644 index 77c79b8..0000000 --- a/src/pal/src/safecrt/vswprint.c +++ /dev/null @@ -1,282 +0,0 @@ -// 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. - -/*** -*vswprint.c - print formatted data into a string from var arg list -* -*Purpose: -* defines vswprintf(), _vswprintf_c and _vsnwprintf() - print formatted output to -* a string, get the data from an argument ptr instead of explicit -* arguments. -* -*******************************************************************************/ - - -#include -#include -#include -#include "internal_securecrt.h" - -#include "mbusafecrt_internal.h" - -typedef int (*WOUTPUTFN)(miniFILE *, const wchar_t *, va_list); - -static int _vswprintf_helper( WOUTPUTFN outfn, wchar_t *string, size_t count, const wchar_t *format, va_list ap ); -static int _vscwprintf_helper (WOUTPUTFN outfn, const wchar_t *format, va_list ap ); - -/*** -*ifndef _COUNT_ -*int _vswprintf(string, format, ap) - print formatted data to string from arg ptr -*else -*ifndef _SWPRINTFS_ERROR_RETURN_FIX -*int _vsnwprintf(string, cnt, format, ap) - print formatted data to string from arg ptr -*else -*int _vswprintf_c(string, cnt, format, ...) - print formatted data to string -*endif -*endif -* -*Purpose: -* Prints formatted data, but to a string and gets data from an argument -* pointer. -* Sets up a FILE so file i/o operations can be used, make string look -* like a huge buffer to it, but _flsbuf will refuse to flush it if it -* fills up. Appends '\0' to make it a true string. -* -* Allocate the 'fake' _iob[] entryit statically instead of on -* the stack so that other routines can assume that _iob[] entries are in -* are in DGROUP and, thus, are near. -* -*ifdef _COUNT_ -*ifndef _SWPRINTFS_ERROR_RETURN_FIX -* The _vsnwprintf() flavor takes a count argument that is -* the max number of bytes that should be written to the -* user's buffer. -* We don't expose this function directly in the headers. -*else -* The _vswprintf_c() flavor does the same thing as the _snwprintf -* above, but, it also fixes an issue in the return value in the case -* when there isn't enough space to write the null terminator -* We don't fix this issue in _vsnwprintf because of backward -* compatibility. In new code, however, _vsnwprintf is #defined to -* _vswprintf_c so users get the fix. -* -*endif -* -* Multi-thread: (1) Since there is no stream, this routine must never try -* to get the stream lock (i.e., there is no stream lock either). (2) -* Also, since there is only one statically allocated 'fake' iob, we must -* lock/unlock to prevent collisions. -* -*Entry: -* wchar_t *string - place to put destination string -*ifdef _COUNT_ -* size_t count - max number of bytes to put in buffer -*endif -* wchar_t *format - format string, describes format of data -* va_list ap - varargs argument pointer -* -*Exit: -* returns number of wide characters in string -* returns -2 if the string has been truncated (only in _vsnprintf_helper) -* returns -1 in other error cases -* -*Exceptions: -* -*******************************************************************************/ - -int __cdecl _vswprintf_helper ( - WOUTPUTFN woutfn, - wchar_t *string, - size_t count, - const wchar_t *format, - va_list ap - ) -{ - miniFILE str; - miniFILE *outfile = &str; - int retval; - - _VALIDATE_RETURN( (format != NULL), EINVAL, -1); - - _VALIDATE_RETURN( (count == 0) || (string != NULL), EINVAL, -1 ); - - outfile->_flag = _IOWRT|_IOSTRG; - outfile->_ptr = outfile->_base = (char *) string; - - if(count>(INT_MAX/sizeof(wchar_t))) - { - /* old-style functions allow any large value to mean unbounded */ - outfile->_cnt = INT_MAX; - } - else - { - outfile->_cnt = (int)(count*sizeof(wchar_t)); - } - - retval = woutfn(outfile, format, ap ); - - if(string==NULL) - { - return retval; - } - - if((retval >= 0) && (_putc_nolock('\0',outfile) != EOF) && (_putc_nolock('\0',outfile) != EOF)) - return(retval); - - string[count - 1] = 0; - if (outfile->_cnt < 0) - { - /* the buffer was too small; we return -2 to indicate truncation */ - return -2; - } - return -1; -} - -int __cdecl _vswprintf_s ( - wchar_t *string, - size_t sizeInWords, - const wchar_t *format, - va_list ap - ) -{ - int retvalue = -1; - - /* validation section */ - _VALIDATE_RETURN(format != NULL, EINVAL, -1); - _VALIDATE_RETURN(string != NULL && sizeInWords > 0, EINVAL, -1); - - retvalue = _vswprintf_helper(_woutput_s, string, sizeInWords, format, ap); - if (retvalue < 0) - { - string[0] = 0; - _SECURECRT__FILL_STRING(string, sizeInWords, 1); - } - if (retvalue == -2) - { - _VALIDATE_RETURN(("Buffer too small" && 0), ERANGE, -1); - } - if (retvalue >= 0) - { - _SECURECRT__FILL_STRING(string, sizeInWords, retvalue + 1); - } - - return retvalue; -} - -int __cdecl _vsnwprintf_s ( - wchar_t *string, - size_t sizeInWords, - size_t count, - const wchar_t *format, - va_list ap - ) -{ - int retvalue = -1; - errno_t save_errno = 0; - - /* validation section */ - _VALIDATE_RETURN(format != NULL, EINVAL, -1); - if (count == 0 && string == NULL && sizeInWords == 0) - { - /* this case is allowed; nothing to do */ - return 0; - } - _VALIDATE_RETURN(string != NULL && sizeInWords > 0, EINVAL, -1); - - if (sizeInWords > count) - { - save_errno = errno; - retvalue = _vswprintf_helper(_woutput_s, string, count + 1, format, ap); - if (retvalue == -2) - { - /* the string has been truncated, return -1 */ - _SECURECRT__FILL_STRING(string, sizeInWords, count + 1); - if (errno == ERANGE) - { - errno = save_errno; - } - return -1; - } - } - else /* sizeInWords <= count */ - { - save_errno = errno; - retvalue = _vswprintf_helper(_woutput_s, string, sizeInWords, format, ap); - string[sizeInWords - 1] = 0; - /* we allow truncation if count == _TRUNCATE */ - if (retvalue == -2 && count == _TRUNCATE) - { - if (errno == ERANGE) - { - errno = save_errno; - } - return -1; - } - } - - if (retvalue < 0) - { - string[0] = 0; - _SECURECRT__FILL_STRING(string, sizeInWords, 1); - if (retvalue == -2) - { - _VALIDATE_RETURN(("Buffer too small" && 0), ERANGE, -1); - } - return -1; - } - - _SECURECRT__FILL_STRING(string, sizeInWords, retvalue + 1); - - return (retvalue < 0 ? -1 : retvalue); -} - -/*** -* _vscwprintf() - counts the number of character needed to print the formatted -* data -* -*Purpose: -* Counts the number of characters in the fotmatted data. -* -*Entry: -* wchar_t *format - format string, describes format of data -* va_list ap - varargs argument pointer -* -*Exit: -* returns number of characters needed to print formatted data. -* -*Exceptions: -* -*******************************************************************************/ - -#ifndef _COUNT_ - -int __cdecl _vscwprintf_helper ( - WOUTPUTFN woutfn, - const wchar_t *format, - va_list ap - ) -{ - miniFILE str; - miniFILE *outfile = &str; - int retval; - - _VALIDATE_RETURN( (format != NULL), EINVAL, -1); - - outfile->_cnt = INT_MAX; //MAXSTR; - outfile->_flag = _IOWRT|_IOSTRG; - outfile->_ptr = outfile->_base = NULL; - - retval = woutfn(outfile, format, ap); - return(retval); -} - -int __cdecl _vscwprintf ( - const wchar_t *format, - va_list ap - ) -{ - return _vscwprintf_helper(_woutput_s, format, ap); -} - -#endif /* _COUNT_ */ diff --git a/src/pal/src/safecrt/vswprint.cpp b/src/pal/src/safecrt/vswprint.cpp new file mode 100644 index 0000000..b9940a6 --- /dev/null +++ b/src/pal/src/safecrt/vswprint.cpp @@ -0,0 +1,211 @@ +// 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. + +/*** +*vswprint.c - print formatted data into a string from var arg list +* +*Purpose: +* defines vswprintf_s() and _vsnwprintf_s() - print formatted output to +* a string, get the data from an argument ptr instead of explicit +* arguments. +* +*******************************************************************************/ + + +#include +#include +#include +#include "internal_securecrt.h" + +#include "mbusafecrt_internal.h" + +typedef int (*WOUTPUTFN)(miniFILE *, const wchar_t *, va_list); + +static int _vswprintf_helper( WOUTPUTFN outfn, wchar_t *string, size_t count, const wchar_t *format, va_list ap ); + +/*** +*int vswprintf_s(string, sizeInWords, format, ap) - print formatted data to string from arg ptr +*int _vsnwprintf_s(string, sizeInWords, cnt, format, ap) - print formatted data to string from arg ptr +*Purpose: +* Prints formatted data, but to a string and gets data from an argument +* pointer. +* Sets up a FILE so file i/o operations can be used, make string look +* like a huge buffer to it, but _flsbuf will refuse to flush it if it +* fills up. Appends '\0' to make it a true string. +* +* Allocate the 'fake' _iob[] entryit statically instead of on +* the stack so that other routines can assume that _iob[] entries are in +* are in DGROUP and, thus, are near. +* +* The _vsnwprintf_s() flavor takes a count argument that is +* the max number of bytes that should be written to the +* user's buffer. +* We don't expose this function directly in the headers. +* +* Multi-thread: (1) Since there is no stream, this routine must never try +* to get the stream lock (i.e., there is no stream lock either). (2) +* Also, since there is only one statically allocated 'fake' iob, we must +* lock/unlock to prevent collisions. +* +*Entry: +* wchar_t *string - place to put destination string +* size_t sizeInWords - size of the string buffer in wchar_t units +* size_t count - max number of bytes to put in buffer +* wchar_t *format - format string, describes format of data +* va_list ap - varargs argument pointer +* +*Exit: +* returns number of wide characters in string +* returns -2 if the string has been truncated (only in _vsnprintf_helper) +* returns -1 in other error cases +* +*Exceptions: +* +*******************************************************************************/ + +int __cdecl _vswprintf_helper ( + WOUTPUTFN woutfn, + wchar_t *string, + size_t count, + const wchar_t *format, + va_list ap + ) +{ + miniFILE str; + miniFILE *outfile = &str; + int retval; + + _VALIDATE_RETURN( (format != NULL), EINVAL, -1); + + _VALIDATE_RETURN( (count == 0) || (string != NULL), EINVAL, -1 ); + + outfile->_flag = _IOWRT|_IOSTRG; + outfile->_ptr = outfile->_base = (char *) string; + + if(count>(INT_MAX/sizeof(wchar_t))) + { + /* old-style functions allow any large value to mean unbounded */ + outfile->_cnt = INT_MAX; + } + else + { + outfile->_cnt = (int)(count*sizeof(wchar_t)); + } + + retval = woutfn(outfile, format, ap ); + + if(string==NULL) + { + return retval; + } + + if((retval >= 0) && (_putc_nolock('\0',outfile) != EOF) && (_putc_nolock('\0',outfile) != EOF)) + return(retval); + + string[count - 1] = 0; + if (outfile->_cnt < 0) + { + /* the buffer was too small; we return -2 to indicate truncation */ + return -2; + } + return -1; +} + +int __cdecl vswprintf_s ( + wchar_t *string, + size_t sizeInWords, + const wchar_t *format, + va_list ap + ) +{ + int retvalue = -1; + + /* validation section */ + _VALIDATE_RETURN(format != NULL, EINVAL, -1); + _VALIDATE_RETURN(string != NULL && sizeInWords > 0, EINVAL, -1); + + retvalue = _vswprintf_helper(_woutput_s, string, sizeInWords, format, ap); + if (retvalue < 0) + { + string[0] = 0; + _SECURECRT__FILL_STRING(string, sizeInWords, 1); + } + if (retvalue == -2) + { + _VALIDATE_RETURN(("Buffer too small" && 0), ERANGE, -1); + } + if (retvalue >= 0) + { + _SECURECRT__FILL_STRING(string, sizeInWords, retvalue + 1); + } + + return retvalue; +} + +int __cdecl _vsnwprintf_s ( + wchar_t *string, + size_t sizeInWords, + size_t count, + const wchar_t *format, + va_list ap + ) +{ + int retvalue = -1; + errno_t save_errno = 0; + + /* validation section */ + _VALIDATE_RETURN(format != NULL, EINVAL, -1); + if (count == 0 && string == NULL && sizeInWords == 0) + { + /* this case is allowed; nothing to do */ + return 0; + } + _VALIDATE_RETURN(string != NULL && sizeInWords > 0, EINVAL, -1); + + if (sizeInWords > count) + { + save_errno = errno; + retvalue = _vswprintf_helper(_woutput_s, string, count + 1, format, ap); + if (retvalue == -2) + { + /* the string has been truncated, return -1 */ + _SECURECRT__FILL_STRING(string, sizeInWords, count + 1); + if (errno == ERANGE) + { + errno = save_errno; + } + return -1; + } + } + else /* sizeInWords <= count */ + { + save_errno = errno; + retvalue = _vswprintf_helper(_woutput_s, string, sizeInWords, format, ap); + string[sizeInWords - 1] = 0; + /* we allow truncation if count == _TRUNCATE */ + if (retvalue == -2 && count == _TRUNCATE) + { + if (errno == ERANGE) + { + errno = save_errno; + } + return -1; + } + } + + if (retvalue < 0) + { + string[0] = 0; + _SECURECRT__FILL_STRING(string, sizeInWords, 1); + if (retvalue == -2) + { + _VALIDATE_RETURN(("Buffer too small" && 0), ERANGE, -1); + } + return -1; + } + + _SECURECRT__FILL_STRING(string, sizeInWords, retvalue + 1); + + return (retvalue < 0 ? -1 : retvalue); +} diff --git a/src/pal/src/safecrt/wcscat_s.c b/src/pal/src/safecrt/wcscat_s.cpp similarity index 100% rename from src/pal/src/safecrt/wcscat_s.c rename to src/pal/src/safecrt/wcscat_s.cpp diff --git a/src/pal/src/safecrt/wcscpy_s.c b/src/pal/src/safecrt/wcscpy_s.cpp similarity index 100% rename from src/pal/src/safecrt/wcscpy_s.c rename to src/pal/src/safecrt/wcscpy_s.cpp diff --git a/src/pal/src/safecrt/wcslen_s.c b/src/pal/src/safecrt/wcslen_s.cpp similarity index 100% rename from src/pal/src/safecrt/wcslen_s.c rename to src/pal/src/safecrt/wcslen_s.cpp diff --git a/src/pal/src/safecrt/wcsncat_s.c b/src/pal/src/safecrt/wcsncat_s.cpp similarity index 100% rename from src/pal/src/safecrt/wcsncat_s.c rename to src/pal/src/safecrt/wcsncat_s.cpp diff --git a/src/pal/src/safecrt/wcsncpy_s.c b/src/pal/src/safecrt/wcsncpy_s.cpp similarity index 100% rename from src/pal/src/safecrt/wcsncpy_s.c rename to src/pal/src/safecrt/wcsncpy_s.cpp diff --git a/src/pal/src/safecrt/wcstok_s.c b/src/pal/src/safecrt/wcstok_s.cpp similarity index 100% rename from src/pal/src/safecrt/wcstok_s.c rename to src/pal/src/safecrt/wcstok_s.cpp diff --git a/src/pal/src/safecrt/wmakepath_s.c b/src/pal/src/safecrt/wmakepath_s.cpp similarity index 100% rename from src/pal/src/safecrt/wmakepath_s.c rename to src/pal/src/safecrt/wmakepath_s.cpp diff --git a/src/pal/src/safecrt/wsplitpath_s.c b/src/pal/src/safecrt/wsplitpath_s.cpp similarity index 100% rename from src/pal/src/safecrt/wsplitpath_s.c rename to src/pal/src/safecrt/wsplitpath_s.cpp diff --git a/src/pal/src/safecrt/xtoa_s.c b/src/pal/src/safecrt/xtoa_s.cpp similarity index 100% rename from src/pal/src/safecrt/xtoa_s.c rename to src/pal/src/safecrt/xtoa_s.cpp diff --git a/src/pal/src/safecrt/xtow_s.c b/src/pal/src/safecrt/xtow_s.cpp similarity index 100% rename from src/pal/src/safecrt/xtow_s.c rename to src/pal/src/safecrt/xtow_s.cpp diff --git a/src/pal/src/safecrt/xtox_s.inl b/src/pal/src/safecrt/xtox_s.inl index e07d87a..7c8b2f2 100644 --- a/src/pal/src/safecrt/xtox_s.inl +++ b/src/pal/src/safecrt/xtox_s.inl @@ -21,12 +21,9 @@ #define _i64tox_s _i64tow_s #define _ui64tox_s _ui64tow_s #define xtox xtow -#define _itox _itow #define _ltox _ltow #define _ultox _ultow #define x64tox x64tow -#define _i64tox _i64tow -#define _ui64tox _ui64tow #else /* _UNICODE */ #define xtox_s xtoa_s #define _itox_s _itoa_s @@ -36,12 +33,9 @@ #define _i64tox_s _i64toa_s #define _ui64tox_s _ui64toa_s #define xtox xtoa -#define _itox _itoa #define _ltox _ltoa #define _ultox _ultoa #define x64tox x64toa -#define _i64tox _i64toa -#define _ui64tox _ui64toa #endif /* _UNICODE */ /*** @@ -224,19 +218,6 @@ errno_t __cdecl _ultox_s ( /* Actual functions just call conversion helper with neg flag set correctly, and return pointer to buffer. */ -TCHAR * __cdecl _itox ( - int val, - TCHAR *buf, - int radix - ) -{ - if (radix == 10 && val < 0) - xtox((unsigned long)val, buf, radix, 1); - else - xtox((unsigned long)(unsigned int)val, buf, radix, 0); - return buf; -} - TCHAR * __cdecl _ltox ( long val, TCHAR *buf, @@ -425,16 +406,6 @@ errno_t __cdecl _ui64tox_s ( /* Actual functions just call conversion helper with neg flag set correctly, and return pointer to buffer. */ -TCHAR * __cdecl _i64tox ( - __int64 val, - TCHAR *buf, - int radix - ) -{ - x64tox((unsigned __int64)val, buf, radix, (radix == 10 && val < 0)); - return buf; -} - TCHAR * __cdecl _ui64tox ( unsigned __int64 val, TCHAR *buf, diff --git a/src/pal/src/synchmgr/synchmanager.cpp b/src/pal/src/synchmgr/synchmanager.cpp index 473918c..3aec140 100644 --- a/src/pal/src/synchmgr/synchmanager.cpp +++ b/src/pal/src/synchmgr/synchmanager.cpp @@ -1648,7 +1648,7 @@ namespace CorUnix } // Entry point routine for the thread that initiates process termination. - DWORD TerminationRequestHandlingRoutine(LPVOID pArg) + DWORD PALAPI TerminationRequestHandlingRoutine(LPVOID pArg) { // Call the termination request handler if one is registered. if (g_terminationRequestHandler != NULL) diff --git a/src/pal/src/thread/context.cpp b/src/pal/src/thread/context.cpp index f832015..0449df5 100644 --- a/src/pal/src/thread/context.cpp +++ b/src/pal/src/thread/context.cpp @@ -33,9 +33,7 @@ SET_DEFAULT_DEBUG_CHANNEL(THREAD); // some headers have code with asserts, so do extern PGET_GCMARKER_EXCEPTION_CODE g_getGcMarkerExceptionCode; -// in context2.S -extern void CONTEXT_CaptureContext(LPCONTEXT lpContext); - +#define CONTEXT_AREA_MASK 0xffff #ifdef _X86_ #define CONTEXT_ALL_FLOATING (CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS) #elif defined(_AMD64_) @@ -288,7 +286,7 @@ CONTEXT_GetThreadContext( } if (lpContext->ContextFlags & - (CONTEXT_CONTROL | CONTEXT_INTEGER)) + (CONTEXT_CONTROL | CONTEXT_INTEGER) & CONTEXT_AREA_MASK) { if (CONTEXT_GetRegisters(dwProcessId, lpContext) == FALSE) { @@ -348,7 +346,7 @@ CONTEXT_SetThreadContext( } if (lpContext->ContextFlags & - (CONTEXT_CONTROL | CONTEXT_INTEGER)) + (CONTEXT_CONTROL | CONTEXT_INTEGER) & CONTEXT_AREA_MASK) { #if HAVE_PT_REGS if (ptrace((__ptrace_request)PT_GETREGS, dwProcessId, (caddr_t)&ptrace_registers, 0) == -1) @@ -371,11 +369,11 @@ CONTEXT_SetThreadContext( ASSERT("Don't know how to set the context of another process on this platform!"); return FALSE; #endif - if (lpContext->ContextFlags & CONTEXT_CONTROL) + if (lpContext->ContextFlags & CONTEXT_CONTROL & CONTEXT_AREA_MASK) { ASSIGN_CONTROL_REGS } - if (lpContext->ContextFlags & CONTEXT_INTEGER) + if (lpContext->ContextFlags & CONTEXT_INTEGER & CONTEXT_AREA_MASK) { ASSIGN_INTEGER_REGS } @@ -467,13 +465,13 @@ void CONTEXTToNativeContext(CONST CONTEXT *lpContext, native_context_t *native) } // TODO: Enable for all Unix systems -#if defined(_AMD64_) && defined(__linux__) +#if defined(_AMD64_) && defined(XSTATE_SUPPORTED) if ((lpContext->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE) { _ASSERTE(FPREG_HasExtendedState(native)); memcpy_s(FPREG_Xstate_Ymmh(native), sizeof(M128A) * 16, lpContext->VectorRegister, sizeof(M128A) * 16); } -#endif // _AMD64_ +#endif //_AMD64_ && XSTATE_SUPPORTED } /*++ @@ -564,22 +562,24 @@ void CONTEXTFromNativeContext(const native_context_t *native, LPCONTEXT lpContex #endif } - // TODO: Enable for all Unix systems -#if defined(_AMD64_) && defined(__linux__) +#ifdef _AMD64_ if ((contextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE) { + // TODO: Enable for all Unix systems +#if XSTATE_SUPPORTED if (FPREG_HasExtendedState(native)) { memcpy_s(lpContext->VectorRegister, sizeof(M128A) * 16, FPREG_Xstate_Ymmh(native), sizeof(M128A) * 16); } else +#endif // XSTATE_SUPPORTED { // Reset the CONTEXT_XSTATE bit(s) so it's clear that the extended state data in // the CONTEXT is not valid. const ULONG xstateFlags = CONTEXT_XSTATE & ~(CONTEXT_CONTROL & CONTEXT_INTEGER); lpContext->ContextFlags &= ~xstateFlags; } - } + } #endif // _AMD64_ } @@ -855,7 +855,7 @@ CONTEXT_GetThreadContextFromPort( mach_msg_type_number_t StateCount; thread_state_flavor_t StateFlavor; - if (lpContext->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS)) + if (lpContext->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS) & CONTEXT_AREA_MASK) { #ifdef _X86_ x86_thread_state32_t State; @@ -877,7 +877,7 @@ CONTEXT_GetThreadContextFromPort( CONTEXT_GetThreadContextFromThreadState(StateFlavor, (thread_state_t)&State, lpContext); } - if (lpContext->ContextFlags & CONTEXT_ALL_FLOATING) { + if (lpContext->ContextFlags & CONTEXT_ALL_FLOATING & CONTEXT_AREA_MASK) { #ifdef _X86_ x86_float_state32_t State; StateFlavor = x86_FLOAT_STATE32; @@ -898,6 +898,22 @@ CONTEXT_GetThreadContextFromPort( CONTEXT_GetThreadContextFromThreadState(StateFlavor, (thread_state_t)&State, lpContext); } +#if defined(_AMD64_) && defined(XSTATE_SUPPORTED) + if (lpContext->ContextFlags & CONTEXT_XSTATE & CONTEXT_AREA_MASK) { + x86_avx_state64_t State; + StateFlavor = x86_AVX_STATE64; + StateCount = sizeof(State) / sizeof(natural_t); + MachRet = thread_get_state(Port, StateFlavor, (thread_state_t)&State, &StateCount); + if (MachRet != KERN_SUCCESS) + { + ASSERT("thread_get_state(XSTATE) failed: %d\n", MachRet); + goto exit; + } + + CONTEXT_GetThreadContextFromThreadState(StateFlavor, (thread_state_t)&State, lpContext); + } +#endif + exit: return MachRet; } @@ -917,7 +933,7 @@ CONTEXT_GetThreadContextFromThreadState( { #ifdef _X86_ case x86_THREAD_STATE32: - if (lpContext->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS)) + if (lpContext->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS) & CONTEXT_AREA_MASK) { x86_thread_state32_t *pState = (x86_thread_state32_t *)threadState; @@ -944,7 +960,7 @@ CONTEXT_GetThreadContextFromThreadState( { x86_float_state32_t *pState = (x86_float_state32_t *)threadState; - if (lpContext->ContextFlags & CONTEXT_FLOATING_POINT) + if (lpContext->ContextFlags & CONTEXT_FLOATING_POINT & CONTEXT_AREA_MASK) { lpContext->FloatSave.ControlWord = *(DWORD*)&pState->fpu_fcw; lpContext->FloatSave.StatusWord = *(DWORD*)&pState->fpu_fsw; @@ -963,7 +979,7 @@ CONTEXT_GetThreadContextFromThreadState( memcpy(&lpContext->FloatSave.RegisterArea[i * 10], (&pState->fpu_stmm0)[i].mmst_reg, 10); } - if (lpContext->ContextFlags & CONTEXT_EXTENDED_REGISTERS) + if (lpContext->ContextFlags & CONTEXT_EXTENDED_REGISTERS & CONTEXT_AREA_MASK) { // The only extended register information that Mach will tell us about are the xmm register values. // Both Windows and Mach store the registers in a packed layout (each of the 8 registers is 16 bytes) @@ -975,7 +991,7 @@ CONTEXT_GetThreadContextFromThreadState( #elif defined(_AMD64_) case x86_THREAD_STATE64: - if (lpContext->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS)) + if (lpContext->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS) & CONTEXT_AREA_MASK) { x86_thread_state64_t *pState = (x86_thread_state64_t *)threadState; @@ -1009,7 +1025,7 @@ CONTEXT_GetThreadContextFromThreadState( break; case x86_FLOAT_STATE64: - if (lpContext->ContextFlags & CONTEXT_FLOATING_POINT) + if (lpContext->ContextFlags & CONTEXT_FLOATING_POINT & CONTEXT_AREA_MASK) { x86_float_state64_t *pState = (x86_float_state64_t *)threadState; @@ -1031,9 +1047,19 @@ CONTEXT_GetThreadContextFromThreadState( memcpy(&lpContext->FltSave.FloatRegisters[i], (&pState->__fpu_stmm0)[i].__mmst_reg, 10); // AMD64's FLOATING_POINT includes the xmm registers. - memcpy(&lpContext->Xmm0, &pState->__fpu_xmm0, 8 * 16); + memcpy(&lpContext->Xmm0, &pState->__fpu_xmm0, 16 * 16); + } + break; + +#ifdef XSTATE_SUPPORTED + case x86_AVX_STATE64: + if (lpContext->ContextFlags & CONTEXT_XSTATE & CONTEXT_AREA_MASK) + { + x86_avx_state64_t *pState = (x86_avx_state64_t *)threadState; + memcpy(&lpContext->VectorRegister, &pState->__fpu_ymmh0, 16 * 16); } break; +#endif #else #error Unexpected architecture. #endif @@ -1120,7 +1146,7 @@ CONTEXT_SetThreadContextOnPort( mach_msg_type_number_t StateCount; thread_state_flavor_t StateFlavor; - if (lpContext->ContextFlags & (CONTEXT_CONTROL|CONTEXT_INTEGER)) + if (lpContext->ContextFlags & (CONTEXT_CONTROL|CONTEXT_INTEGER) & CONTEXT_AREA_MASK) { #ifdef _X86_ x86_thread_state32_t State; @@ -1187,21 +1213,42 @@ CONTEXT_SetThreadContextOnPort( } } - if (lpContext->ContextFlags & CONTEXT_ALL_FLOATING) + if (lpContext->ContextFlags & CONTEXT_ALL_FLOATING & CONTEXT_AREA_MASK) { #ifdef _X86_ x86_float_state32_t State; StateFlavor = x86_FLOAT_STATE32; + StateCount = sizeof(State) / sizeof(natural_t); #elif defined(_AMD64_) +#ifdef XSTATE_SUPPORTED + // We're relying on the fact that the initial portion of + // x86_avx_state64_t is identical to x86_float_state64_t. + // Check a few fields to make sure the assumption is correct. + static_assert_no_msg(sizeof(x86_avx_state64_t) > sizeof(x86_float_state64_t)); + static_assert_no_msg(offsetof(x86_avx_state64_t, __fpu_fcw) == offsetof(x86_float_state64_t, __fpu_fcw)); + static_assert_no_msg(offsetof(x86_avx_state64_t, __fpu_xmm0) == offsetof(x86_float_state64_t, __fpu_xmm0)); + + x86_avx_state64_t State; + if (lpContext->ContextFlags & CONTEXT_XSTATE & CONTEXT_AREA_MASK) + { + StateFlavor = x86_AVX_STATE64; + StateCount = sizeof(State) / sizeof(natural_t); + } + else + { + StateFlavor = x86_FLOAT_STATE64; + StateCount = sizeof(x86_float_state64_t) / sizeof(natural_t); + } +#else x86_float_state64_t State; StateFlavor = x86_FLOAT_STATE64; + StateCount = sizeof(State) / sizeof(natural_t); +#endif #else #error Unexpected architecture. #endif - StateCount = sizeof(State) / sizeof(natural_t); - // If we're setting only one of the floating point or extended registers (of which Mach supports only // the xmm values) then we don't have values for the other set. This is a problem since Mach only // supports setting both groups as a single unit. So in this case we'll need to fetch the current @@ -1222,7 +1269,7 @@ CONTEXT_SetThreadContextOnPort( _ASSERTE(StateCountGet == StateCount); } - if (lpContext->ContextFlags & CONTEXT_FLOATING_POINT) + if (lpContext->ContextFlags & CONTEXT_FLOATING_POINT & CONTEXT_AREA_MASK) { #ifdef _X86_ *(DWORD*)&State.fpu_fcw = lpContext->FloatSave.ControlWord; @@ -1258,14 +1305,14 @@ CONTEXT_SetThreadContextOnPort( for (int i = 0; i < 8; i++) memcpy((&State.__fpu_stmm0)[i].__mmst_reg, &lpContext->FltSave.FloatRegisters[i], 10); - memcpy(&State.__fpu_xmm0, &lpContext->Xmm0, 8 * 16); + memcpy(&State.__fpu_xmm0, &lpContext->Xmm0, 16 * 16); #else #error Unexpected architecture. #endif } #ifdef _X86_ - if (lpContext->ContextFlags & CONTEXT_EXTENDED_REGISTERS) + if (lpContext->ContextFlags & CONTEXT_EXTENDED_REGISTERS & CONTEXT_AREA_MASK) { // The only extended register information that Mach will tell us about are the xmm register // values. Both Windows and Mach store the registers in a packed layout (each of the 8 registers @@ -1274,6 +1321,13 @@ CONTEXT_SetThreadContextOnPort( } #endif // _X86_ +#if defined(_AMD64_) && defined(XSTATE_SUPPORTED) + if (lpContext->ContextFlags & CONTEXT_XSTATE & CONTEXT_AREA_MASK) + { + memcpy(&State.__fpu_ymmh0, lpContext->VectorRegister, 16 * 16); + } +#endif + MachRet = thread_set_state(Port, StateFlavor, (thread_state_t)&State, diff --git a/src/pal/src/thread/process.cpp b/src/pal/src/thread/process.cpp index 315145d..a64bfb8 100644 --- a/src/pal/src/thread/process.cpp +++ b/src/pal/src/thread/process.cpp @@ -2049,18 +2049,18 @@ GetProcessIdDisambiguationKey(DWORD processId, UINT64 *disambiguationKey) // According to `man proc`, the second field in the stat file is the filename of the executable, // in parentheses. Tokenizing the stat file using spaces as separators breaks when that name - // has spaces in it, so we start using sscanf after skipping everything up to and including the + // has spaces in it, so we start using sscanf_s after skipping everything up to and including the // last closing paren and the space after it. char *scanStartPosition = strrchr(line, ')') + 2; // All the format specifiers for the fields in the stat file are provided by 'man proc'. - int sscanfRet = sscanf(scanStartPosition, + int sscanfRet = sscanf_s(scanStartPosition, "%*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %*lu %*lu %*ld %*ld %*ld %*ld %*ld %*ld %llu \n", &starttime); if (sscanfRet != 1) { - _ASSERTE(!"Failed to parse stat file contents with sscanf."); + _ASSERTE(!"Failed to parse stat file contents with sscanf_s."); return FALSE; } @@ -2095,7 +2095,7 @@ PAL_GetTransportPipeName(char *name, DWORD id, const char *suffix) // also try to use 0 as the value. _ASSERTE(ret == TRUE || disambiguationKey == 0); - int chars = _snprintf(name, MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH, PipeNameFormat, id, disambiguationKey, suffix); + int chars = snprintf(name, MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH, PipeNameFormat, id, disambiguationKey, suffix); _ASSERTE(chars > 0 && chars < MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH); } @@ -2690,7 +2690,7 @@ CreateProcessModules( char moduleName[PATH_MAX]; int size; - if (sscanf(line, "__TEXT %p-%p [ %dK] %*[-/rwxsp] SM=%*[A-Z] %s\n", &startAddress, &endAddress, &size, moduleName) == 4) + if (sscanf_s(line, "__TEXT %p-%p [ %dK] %*[-/rwxsp] SM=%*[A-Z] %s\n", &startAddress, &endAddress, &size, moduleName, _countof(moduleName)) == 4) { bool dup = false; for (ProcessModules *entry = listHead; entry != NULL; entry = entry->Next) @@ -2768,7 +2768,7 @@ exit: int devHi, devLo, inode; char moduleName[PATH_MAX]; - if (sscanf(line, "%p-%p %*[-rwxsp] %p %x:%x %d %s\n", &startAddress, &endAddress, &offset, &devHi, &devLo, &inode, moduleName) == 7) + if (sscanf_s(line, "%p-%p %*[-rwxsp] %p %x:%x %d %s\n", &startAddress, &endAddress, &offset, &devHi, &devLo, &inode, moduleName, _countof(moduleName)) == 7) { if (inode != 0) { diff --git a/src/pal/tests/CMakeLists.txt b/src/pal/tests/CMakeLists.txt index a6d1ba4..39d5852 100644 --- a/src/pal/tests/CMakeLists.txt +++ b/src/pal/tests/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 2.8.12.2) -if(CLR_CMAKE_PLATFORM_ARCH_AMD64) +if(CLR_CMAKE_PLATFORM_ARCH_I386) + set(PAL_CMAKE_PLATFORM_ARCH_I386 1) +elseif(CLR_CMAKE_PLATFORM_ARCH_AMD64) set(PAL_CMAKE_PLATFORM_ARCH_AMD64 1) elseif(CLR_CMAKE_PLATFORM_ARCH_ARM) set(PAL_CMAKE_PLATFORM_ARCH_ARM 1) @@ -14,7 +16,9 @@ add_definitions(-DLP64COMPATIBLE=1) add_definitions(-DFEATURE_PAL=1) add_definitions(-DCORECLR=1) add_definitions(-DPIC=1) -if(PAL_CMAKE_PLATFORM_ARCH_AMD64) +if(PAL_CMAKE_PLATFORM_ARCH_I386) + add_definitions(-DBIT32=1) +elseif(PAL_CMAKE_PLATFORM_ARCH_AMD64) add_definitions(-DBIT64=1) add_definitions(-D_WIN64=1) elseif(PAL_CMAKE_PLATFORM_ARCH_ARM) @@ -23,10 +27,15 @@ elseif(PAL_CMAKE_PLATFORM_ARCH_ARM64) add_definitions(-DBIT64=1) add_definitions(-D_WIN64=1) else() - message(FATAL_ERROR "Only ARM, ARM64 and AMD64 is supported") + message(FATAL_ERROR "Only ARM, ARM64, I386, and AMD64 is supported") endif() +# C++ emits errors and warnings for c-string literal fed into char* parameter +# this is just to take care of the warnings +add_compile_options(-Wno-writable-strings) + add_compile_options(-Wno-empty-body) add_subdirectory(palsuite) + diff --git a/src/pal/tests/palsuite/c_runtime/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/CMakeLists.txt index 533454c..cf06253 100644 --- a/src/pal/tests/palsuite/c_runtime/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/CMakeLists.txt @@ -2,16 +2,23 @@ cmake_minimum_required(VERSION 2.8.12.2) add_subdirectory(abs) add_subdirectory(acos) +add_subdirectory(acosf) add_subdirectory(asin) +add_subdirectory(asinf) add_subdirectory(atan) add_subdirectory(atan2) +add_subdirectory(atan2f) +add_subdirectory(atanf) add_subdirectory(atof) add_subdirectory(atoi) add_subdirectory(atol) add_subdirectory(bsearch) add_subdirectory(ceil) +add_subdirectory(ceilf) add_subdirectory(cos) +add_subdirectory(cosf) add_subdirectory(cosh) +add_subdirectory(coshf) # TODO: make this test compile # add_subdirectory(ctime) @@ -19,6 +26,7 @@ add_subdirectory(cosh) add_subdirectory(errno) add_subdirectory(exit) add_subdirectory(exp) +add_subdirectory(expf) add_subdirectory(fabs) add_subdirectory(fabsf) add_subdirectory(fclose) @@ -27,6 +35,7 @@ add_subdirectory(ferror) add_subdirectory(fflush) add_subdirectory(fgets) add_subdirectory(floor) +add_subdirectory(floorf) add_subdirectory(fmod) add_subdirectory(fmodf) add_subdirectory(fopen) @@ -57,6 +66,8 @@ add_subdirectory(llabs) add_subdirectory(localtime) add_subdirectory(log) add_subdirectory(log10) +add_subdirectory(log10f) +add_subdirectory(logf) add_subdirectory(malloc) add_subdirectory(memchr) add_subdirectory(memcmp) @@ -66,15 +77,19 @@ add_subdirectory(memset) add_subdirectory(modf) add_subdirectory(modff) add_subdirectory(pow) +add_subdirectory(powf) add_subdirectory(printf) add_subdirectory(qsort) add_subdirectory(rand_srand) add_subdirectory(realloc) add_subdirectory(sin) +add_subdirectory(sinf) add_subdirectory(sinh) -add_subdirectory(sprintf) +add_subdirectory(sinhf) +add_subdirectory(sprintf_s) add_subdirectory(sqrt) -add_subdirectory(sscanf) +add_subdirectory(sqrtf) +add_subdirectory(sscanf_s) add_subdirectory(strcat) add_subdirectory(strchr) add_subdirectory(strcmp) @@ -94,7 +109,9 @@ add_subdirectory(strtoul) add_subdirectory(swprintf) add_subdirectory(swscanf) add_subdirectory(tan) +add_subdirectory(tanf) add_subdirectory(tanh) +add_subdirectory(tanhf) add_subdirectory(time) add_subdirectory(tolower) add_subdirectory(toupper) @@ -125,6 +142,7 @@ add_subdirectory(_alloca) add_subdirectory(_ecvt) add_subdirectory(_fdopen) add_subdirectory(_finite) +add_subdirectory(_finitef) add_subdirectory(_fullpath) # TODO: make this test compile @@ -132,31 +150,26 @@ add_subdirectory(_fullpath) add_subdirectory(_getw) add_subdirectory(_isnan) +add_subdirectory(_isnanf) add_subdirectory(_itow) -add_subdirectory(_makepath) add_subdirectory(_mbsdec) add_subdirectory(_mbsinc) -add_subdirectory(_mbslen) add_subdirectory(_mbsninc) add_subdirectory(_open_osfhandle) add_subdirectory(_putenv) add_subdirectory(_putw) add_subdirectory(_rotl) add_subdirectory(_rotr) -add_subdirectory(_snprintf) -add_subdirectory(_snwprintf) -add_subdirectory(_splitpath) +add_subdirectory(_snprintf_s) +add_subdirectory(_snwprintf_s) add_subdirectory(_stricmp) add_subdirectory(_strlwr) add_subdirectory(_strnicmp) -add_subdirectory(_swab) add_subdirectory(_vsnprintf) -add_subdirectory(_vsnwprintf) +add_subdirectory(_vsnwprintf_s) add_subdirectory(_wcsicmp) add_subdirectory(_wcslwr) add_subdirectory(_wcsnicmp) add_subdirectory(_wfopen) -add_subdirectory(_wmakepath) -add_subdirectory(_wsplitpath) add_subdirectory(_wtoi) add_subdirectory(__iscsym) diff --git a/src/pal/tests/palsuite/c_runtime/__iscsym/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/__iscsym/test1/CMakeLists.txt index a283161..b4421e7 100644 --- a/src/pal/tests/palsuite/c_runtime/__iscsym/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/__iscsym/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - __iscsym.c + __iscsym.cpp ) add_executable(paltest_iscsym_test1 diff --git a/src/pal/tests/palsuite/c_runtime/__iscsym/test1/__iscsym.c b/src/pal/tests/palsuite/c_runtime/__iscsym/test1/__iscsym.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/__iscsym/test1/__iscsym.c rename to src/pal/tests/palsuite/c_runtime/__iscsym/test1/__iscsym.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_alloca/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_alloca/test1/CMakeLists.txt index 236b356..434633b 100644 --- a/src/pal/tests/palsuite/c_runtime/_alloca/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_alloca/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_alloca_test1 diff --git a/src/pal/tests/palsuite/c_runtime/_alloca/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_alloca/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_alloca/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/_alloca/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_ecvt/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_ecvt/test1/CMakeLists.txt index 86f4547..e78a802 100644 --- a/src/pal/tests/palsuite/c_runtime/_ecvt/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_ecvt/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_ecvt_test1 diff --git a/src/pal/tests/palsuite/c_runtime/_ecvt/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_ecvt/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_ecvt/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/_ecvt/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_fdopen/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_fdopen/test1/CMakeLists.txt index 441d32b..60b036f 100644 --- a/src/pal/tests/palsuite/c_runtime/_fdopen/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_fdopen/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_fdopen_test1 diff --git a/src/pal/tests/palsuite/c_runtime/_fdopen/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_fdopen/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_fdopen/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/_fdopen/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_finite/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_finite/test1/CMakeLists.txt index 8aca58a..ac2f25d 100644 --- a/src/pal/tests/palsuite/c_runtime/_finite/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_finite/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_finite_test1 diff --git a/src/pal/tests/palsuite/c_runtime/_finite/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_finite/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_finite/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/_finite/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_finitef/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_finitef/CMakeLists.txt new file mode 100644 index 0000000..5e1ef7f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_finitef/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) diff --git a/src/pal/tests/palsuite/c_runtime/_finitef/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_finitef/test1/CMakeLists.txt new file mode 100644 index 0000000..9ef630f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_finitef/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_finitef_test1 + ${SOURCES} +) + +add_dependencies(paltest_finitef_test1 coreclrpal) + +target_link_libraries(paltest_finitef_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_finitef/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_finitef/test1/test1.c new file mode 100644 index 0000000..f9a1109 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_finitef/test1/test1.c @@ -0,0 +1,119 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Checks that _finitef correctly classifies all types +** of floating point numbers (NaN, -Infinity, Infinity, +** finite nonzero, unnormalized, 0, and -0) +** +**==========================================================================*/ + +#include + +/* +The IEEE single precision floating point standard looks like this: + + S EEEEEEEE FFFFFFFFFFFFFFFFFFFFFFF + 0 1 8 9 31 + +S is the sign bit. The E bits are the exponent, and the 23 F bits are +the fraction. These represent a value, V. + +If E=255 and F is nonzero, then V=NaN ("Not a number") +If E=255 and F is zero and S is 1, then V=-Infinity +If E=255 and F is zero and S is 0, then V=Infinity +If 0 + +#define TO_FLOAT(x) (*((float*)((void*)&x))) +#define TO_I32(x) (*((INT32*)((void*)&x))) + +/* + * NaN: any float with maximum exponent (0x7f8) and non-zero fraction + */ +int __cdecl main(int argc, char *argv[]) +{ + /* + * Initialize the PAL and return FAIL if this fails + */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + /* + * Try some trivial values + */ + if (_isnanf(0.0f)) + { + Fail("_isnanf() incorrectly identified %f as NaN!\n", 0.0f); + } + + if (_isnanf(1.234567f)) + { + Fail("_isnanf() incorrectly identified %f as NaN!\n", 1.234567f); + } + + if (_isnanf(42.0f)) + { + Fail("_isnanf() incorrectly identified %f as NaN!\n", 42.0f); + } + + UINT32 lneginf = 0xff800000u; + UINT32 lposinf = 0x7f800000u; + + float neginf = TO_FLOAT(lneginf); + float posinf = TO_FLOAT(lposinf); + + /* + * Try positive and negative infinity + */ + if (_isnanf(neginf)) + { + Fail("_isnanf() incorrectly identified negative infinity as NaN!\n"); + } + + if (_isnanf(posinf)) + { + Fail("_isnanf() incorrectly identified infinity as NaN!\n"); + } + + /* + * Try setting the least significant bit of the fraction, + * positive and negative + */ + UINT32 lsnan = 0xff800001u; + float snan = TO_FLOAT(lsnan); + + if (!_isnanf(snan)) + { + Fail("_isnanf() failed to identify %I32x as NaN!\n", lsnan); + } + + UINT32 lqnan = 0x7f800001u; + float qnan = TO_FLOAT(lqnan); + + if (!_isnanf(qnan)) + { + Fail("_isnanf() failed to identify %I32x as NaN!\n", lqnan); + } + + /* + * Try setting the most significant bit of the fraction, + * positive and negative + */ + lsnan = 0xffc00000u; + snan = TO_FLOAT(lsnan); + + if (!_isnanf(snan)) + { + Fail ("_isnanf() failed to identify %I32x as NaN!\n", lsnan); + } + + lqnan = 0x7fc00000u; + qnan = TO_FLOAT(lqnan); + + if (!_isnanf(qnan)) + { + Fail ("_isnanf() failed to identify %I32x as NaN!\n", lqnan); + } + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_isnanf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_isnanf/test1/testinfo.dat new file mode 100644 index 0000000..22b0edb --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_isnanf/test1/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = _isnanf +Name = Test #1 for _isnanf +TYPE = DEFAULT +EXE1 = test1 +Description += Test _isnanf with a number of trivial values, to ensure they indicated that += they are numbers. Then try with Positive/Negative Infinite, which should += also be numbers. Finally set the least and most significant bits of += the fraction to positive and negative, at which point it should return += the true value. diff --git a/src/pal/tests/palsuite/c_runtime/_itow/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_itow/test1/CMakeLists.txt index bd37f31..2c5d57b 100644 --- a/src/pal/tests/palsuite/c_runtime/_itow/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_itow/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_itow_test1 diff --git a/src/pal/tests/palsuite/c_runtime/_itow/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_itow/test1/test1.c deleted file mode 100644 index 745ce4a..0000000 --- a/src/pal/tests/palsuite/c_runtime/_itow/test1/test1.c +++ /dev/null @@ -1,102 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: test1.c -** -** Purpose: Tests the PAL implementation of the _itow function. -** Test a number of ints with different radix on each, -** to ensure that the string returned is correct. -** -** -**===================================================================*/ - -#define UNICODE - -#include - -struct testCase -{ - wchar_t *CorrectResult; - int value; - int radix; -}; - -int __cdecl main(int argc, char **argv) -{ - - wchar_t result[20]; - wchar_t *pResult = NULL; - char *PrintResult = NULL; /* Use with convertC so we can */ - char *PrintCorrectResult = NULL; /* print out the results */ - int i = 0; - - WCHAR case1[] = {'5','0','\0'}; - WCHAR case2[] = {'5','5','5','\0'}; - WCHAR case3[] = {'1','0','1','0','\0'}; - WCHAR case4[] = {'2','2','\0'}; - WCHAR case5[] = {'a','\0'}; - WCHAR case6[] = {'c','g','\0'}; - - /* Correct Result, Value to Convert, Radix to use */ - struct testCase testCases[] = - { - {case1, 50, 10}, - {case2,555,10}, - {case3,10,2}, - {case4,10,4}, - {case5,10,16}, - {case6,400,32} - }; - - /* - * Initialize the PAL and return FAIL if this fails - */ - if (0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* Loop through each case. Convert the ints to strings. Check - to ensure they were converted properly. - */ - - for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) - { - pResult = _itow(testCases[i].value,result,testCases[i].radix); - - if(pResult != &result[0]) - { - Fail("ERROR: _itow didn't return a correct pointer to the " - "newly formed string.\n"); - } - - if (0 != wcscmp(testCases[i].CorrectResult,pResult)) - { - PrintResult = convertC(pResult); - PrintCorrectResult = convertC(testCases[i].CorrectResult); - Fail("ERROR: _itow was called on %i, returning the string %s " - "when it should have returned the string %s.\n" - , testCases[i].value, PrintResult, PrintCorrectResult); - } - - } - - PAL_Terminate(); - return PASS; -} - - - - - - - - - - - - - diff --git a/src/pal/tests/palsuite/c_runtime/_itow/test1/test1.cpp b/src/pal/tests/palsuite/c_runtime/_itow/test1/test1.cpp new file mode 100644 index 0000000..01f32f2 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_itow/test1/test1.cpp @@ -0,0 +1,101 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests the PAL implementation of the _itow_s function. +** Test a number of ints with different radix on each, +** to ensure that the string returned is correct. +** +** +**===================================================================*/ + +#define UNICODE + +#include + +struct testCase +{ + wchar_t *CorrectResult; + int value; + int radix; +}; + +int __cdecl main(int argc, char **argv) +{ + + wchar_t result[20]; + wchar_t *pResult = NULL; + char *PrintResult = NULL; /* Use with convertC so we can */ + char *PrintCorrectResult = NULL; /* print out the results */ + int i = 0; + + WCHAR case1[] = {'5','0','\0'}; + WCHAR case2[] = {'5','5','5','\0'}; + WCHAR case3[] = {'1','0','1','0','\0'}; + WCHAR case4[] = {'2','2','\0'}; + WCHAR case5[] = {'a','\0'}; + WCHAR case6[] = {'c','g','\0'}; + + /* Correct Result, Value to Convert, Radix to use */ + struct testCase testCases[] = + { + {case1, 50, 10}, + {case2,555,10}, + {case3,10,2}, + {case4,10,4}, + {case5,10,16}, + {case6,400,32} + }; + + /* + * Initialize the PAL and return FAIL if this fails + */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Loop through each case. Convert the ints to strings. Check + to ensure they were converted properly. + */ + + for(i = 0; i < sizeof(testCases) / sizeof(struct testCase); i++) + { + errno_t err = _itow_s(testCases[i].value, result, sizeof(result) / sizeof(result[0]), testCases[i].radix); + + if(err != 0) + { + Fail("ERROR: _itow_s didn't return success, error code %d.\n", err); + } + + if (0 != wcscmp(testCases[i].CorrectResult, result)) + { + PrintResult = convertC(pResult); + PrintCorrectResult = convertC(testCases[i].CorrectResult); + Fail("ERROR: _itow_s was called on %i, returning the string %s " + "when it should have returned the string %s.\n" + , testCases[i].value, PrintResult, PrintCorrectResult); + } + + } + + PAL_Terminate(); + return PASS; +} + + + + + + + + + + + + + diff --git a/src/pal/tests/palsuite/c_runtime/_itow/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_itow/test1/testinfo.dat index 394c34d..91f0e62 100644 --- a/src/pal/tests/palsuite/c_runtime/_itow/test1/testinfo.dat +++ b/src/pal/tests/palsuite/c_runtime/_itow/test1/testinfo.dat @@ -4,12 +4,12 @@ Version = 1.0 Section = C Runtime -Function = _itow -Name = Positive Test for _itow +Function = _itow_s +Name = Positive Test for _itow_s TYPE = DEFAULT EXE1 = test1 Description -= Tests the PAL implementation of the _itow function. += Tests the PAL implementation of the _itow_s function. = Test a number of ints with different radix on each, to ensure that the = string returned is correct. diff --git a/src/pal/tests/palsuite/c_runtime/_makepath/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_makepath/CMakeLists.txt deleted file mode 100644 index f6aa0cb..0000000 --- a/src/pal/tests/palsuite/c_runtime/_makepath/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -add_subdirectory(test1) - diff --git a/src/pal/tests/palsuite/c_runtime/_makepath/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_makepath/test1/CMakeLists.txt deleted file mode 100644 index 9fd81cc..0000000 --- a/src/pal/tests/palsuite/c_runtime/_makepath/test1/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test1.c -) - -add_executable(paltest_makepath_test1 - ${SOURCES} -) - -add_dependencies(paltest_makepath_test1 coreclrpal) - -target_link_libraries(paltest_makepath_test1 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_makepath/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_makepath/test1/test1.c deleted file mode 100644 index 94b366a..0000000 --- a/src/pal/tests/palsuite/c_runtime/_makepath/test1/test1.c +++ /dev/null @@ -1,65 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: test1.c -** -** Purpose: Tests the PAL implementation of the _makepath function. -** Create a path, and ensure that it builds how it is -** supposed to. -** -** -** -**===================================================================*/ - -#if WIN32 -#define PATHNAME "C:\\test\\test.txt" -#else -#define PATHNAME "/test/test.txt" -#endif - -#include - -int __cdecl main(int argc, char **argv) -{ - char FullPath[128]; - - /* - * Initialize the PAL and return FAIL if this fails - */ - if (0 != (PAL_Initialize(argc,argv))) - { - return FAIL; - } - -#if WIN32 - _makepath(FullPath,"C","\\test","test","txt"); -#else - _makepath(FullPath,NULL,"/test","test","txt"); -#endif - - if(strcmp(FullPath,PATHNAME) != 0) - { - Fail("ERROR: The pathname which was created turned out to be %s " - "when it was supposed to be %s.\n",FullPath,PATHNAME); - } - - - PAL_Terminate(); - return PASS; -} - - - - - - - - - - - - - diff --git a/src/pal/tests/palsuite/c_runtime/_makepath/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_makepath/test1/testinfo.dat deleted file mode 100644 index 2aed8e5..0000000 --- a/src/pal/tests/palsuite/c_runtime/_makepath/test1/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _makepath -Name = Positive Test for _makepath -TYPE = DEFAULT -EXE1 = test1 -Description -= Purpose: Tests the PAL implementation of the _makepath function. -= Create a path, and ensure that it builds how it is supposed to. - diff --git a/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/CMakeLists.txt index 064f241..b016f27 100644 --- a/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_mbsdec_test1 diff --git a/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_mbsdec/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_mbsdec/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/_mbsdec/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/CMakeLists.txt index 531ba8e..c7325b9 100644 --- a/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_mbsinc_test1 diff --git a/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_mbsinc/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_mbsinc/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/_mbsinc/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_mbslen/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_mbslen/CMakeLists.txt deleted file mode 100644 index f6aa0cb..0000000 --- a/src/pal/tests/palsuite/c_runtime/_mbslen/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -add_subdirectory(test1) - diff --git a/src/pal/tests/palsuite/c_runtime/_mbslen/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_mbslen/test1/CMakeLists.txt deleted file mode 100644 index 38aa6fb..0000000 --- a/src/pal/tests/palsuite/c_runtime/_mbslen/test1/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test1.c -) - -add_executable(paltest_mbslen_test1 - ${SOURCES} -) - -add_dependencies(paltest_mbslen_test1 coreclrpal) - -target_link_libraries(paltest_mbslen_test1 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_mbslen/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_mbslen/test1/test1.c deleted file mode 100644 index fa24c77..0000000 --- a/src/pal/tests/palsuite/c_runtime/_mbslen/test1/test1.c +++ /dev/null @@ -1,66 +0,0 @@ -// 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. - -/*======================================================================== -** -** Source: test1.c -** -** Purpose: -** Check the length of a number of arrays. The first is a normal string -** which should return its length. The second has two bytes and a null -** character, which only returns a size of 2, and the last is just a NULL -** array which should return 0. -** -** -**========================================================================*/ - -#include - -/* - * Note: it seems like these functions would only be useful if they - * didn't assume a character was equivalent to a single byte. Be that - * as it may, I haven't seen a way to get it to behave otherwise - * (eg locale) - */ - -int __cdecl main(int argc, char *argv[]) -{ - unsigned char *str1 = (unsigned char*) "foo"; - unsigned char str2[] = {0xC0, 0x80, 0}; /* the char U+0080 */ - unsigned char str3[] = {0}; - int ret=0; - - /* - * Initialize the PAL and return FAIL if this fails - */ - if (0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - ret = _mbslen(str1); - if (ret != 3) - { - Fail ("ERROR: _mbslen(\"%s\") returned %d. Expected %d\n", - str1, ret, 3); - } - - ret = _mbslen(str2); - if (ret != 2) - { - Fail ("ERROR: _mbslen(\"%s\") returned %d. Expected %d\n", - str2, ret, 2); - } - - ret = _mbslen(str3); - if (ret != 0) - { - Fail ("ERROR: _mbslen(\"%s\") returned %d. Expected %d\n", - str3, ret, 0); - } - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/_mbslen/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_mbslen/test1/testinfo.dat deleted file mode 100644 index cf830a7..0000000 --- a/src/pal/tests/palsuite/c_runtime/_mbslen/test1/testinfo.dat +++ /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. -# See the LICENSE file in the project root for more information. - -Version = 1.0 -Section = C Runtime -Function = _mbsinc -Name = Positive Test for _mbslen -TYPE = DEFAULT -EXE1 = test1 -Description -= Check the length of a number of arrays. The first is a normal string -= which should return its length. The second has two bytes and a null -= character, which only returns a size of 2, and the last is just a NULL -= array which should return 0. diff --git a/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/CMakeLists.txt index 7285ce2..81c6c23 100644 --- a/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_mbsninc_test1 diff --git a/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_mbsninc/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_mbsninc/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/_mbsninc/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/CMakeLists.txt index e9a3e29..f4fedb6 100644 --- a/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_open_osfhandle_test1 diff --git a/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/_open_osfhandle/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/CMakeLists.txt index 1031ec1..6086868 100644 --- a/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_open_osfhandle_test2 diff --git a/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/test2.c b/src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/_open_osfhandle/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_putenv/test1/CMakeLists.txt index 0a75b41..9096bc1 100644 --- a/src/pal/tests/palsuite/c_runtime/_putenv/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_putenv/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_putenv_test1 diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_putenv/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_putenv/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/_putenv/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_putenv/test2/CMakeLists.txt index e053968..ad99eba 100644 --- a/src/pal/tests/palsuite/c_runtime/_putenv/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_putenv/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_putenv_test2 diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/test2/test2.c b/src/pal/tests/palsuite/c_runtime/_putenv/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_putenv/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/_putenv/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_putenv/test3/CMakeLists.txt index a672410..fc97b95 100644 --- a/src/pal/tests/palsuite/c_runtime/_putenv/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_putenv/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_putenv_test3 diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/test3/test3.c b/src/pal/tests/palsuite/c_runtime/_putenv/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_putenv/test3/test3.c rename to src/pal/tests/palsuite/c_runtime/_putenv/test3/test3.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_putenv/test4/CMakeLists.txt index 518282c..3881626 100644 --- a/src/pal/tests/palsuite/c_runtime/_putenv/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_putenv/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_putenv_test4 diff --git a/src/pal/tests/palsuite/c_runtime/_putenv/test4/test4.c b/src/pal/tests/palsuite/c_runtime/_putenv/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_putenv/test4/test4.c rename to src/pal/tests/palsuite/c_runtime/_putenv/test4/test4.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_putw/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_putw/test1/CMakeLists.txt index c3018ad..78833d4 100644 --- a/src/pal/tests/palsuite/c_runtime/_putw/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_putw/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_putw_test1 diff --git a/src/pal/tests/palsuite/c_runtime/_putw/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_putw/test1/test1.c deleted file mode 100644 index ecfc904..0000000 --- a/src/pal/tests/palsuite/c_runtime/_putw/test1/test1.c +++ /dev/null @@ -1,112 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: Writes a series of integers to a file, test.dat, -** then verifies the results. -** -** Dependency: fopen(...) -** fclose(...) -** CloseHandle(...) -** DeleteFileA(...) -** _getw(...) -** -** -** -**==========================================================================*/ - - -#include - -const char testFileName[] = "test.dat"; - -static void Cleanup(HANDLE hFile) -{ - if (fclose(hFile)) - { - Trace("_putw: ERROR -> Unable to close file \"%s\".\n", - testFileName); - } - if (!DeleteFileA(testFileName)) - { - Trace("_putw: ERROR -> Unable to delete file \"%s\". ", - "GetLastError returned %u.\n", - testFileName, - GetLastError()); - } -} - - -int __cdecl main(int argc, char **argv) -{ - - FILE * pfTest = NULL; - int testArray[] = {0,1,-1,0x7FFFFFFF,0x80000000,0xFFFFFFFF,0xFFFFAAAA}; - int i = 0; - int retValue = 0; - - /* - * Initialize the PAL and return FAIL if this fails - */ - if (0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /*write the file that we will use to test */ - pfTest = fopen(testFileName, "w"); - if (pfTest == NULL) - { - Fail ("Unable to write test file.\n"); - } - - for (i = 0; i < sizeof(testArray)/sizeof(int) ; i++) - { - _putw(testArray[i], pfTest); - - if( ferror( pfTest ) ) - { - Cleanup(pfTest); - Fail( "Error:in _putw -> error has occurred in the " - "stream while writing to the file: \"test.dat\"\n"); - } - - } - - if (fclose(pfTest) != 0) - { - Cleanup(pfTest); - Fail ("Error closing file after writing with _putw(..).\n"); - } - - /*open the new test file and compare*/ - pfTest = fopen(testFileName, "r"); - if (pfTest == NULL) - { - Fail ("Error opening \"%s\", which is odd, since I just finished " - "creating that file.\n", testFileName); - } - retValue =_getw( pfTest ); - i = 0; - while(retValue != EOF) - { - if(retValue != testArray[i]) - { - Cleanup(pfTest); - Fail ("Integers written by _putw are not in the correct format\n", - testFileName); - } - retValue = _getw( pfTest ); - i++ ; - } - - Cleanup(pfTest); - PAL_Terminate(); - return PASS; -} - - diff --git a/src/pal/tests/palsuite/c_runtime/_putw/test1/test1.cpp b/src/pal/tests/palsuite/c_runtime/_putw/test1/test1.cpp new file mode 100644 index 0000000..02b7cc7 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_putw/test1/test1.cpp @@ -0,0 +1,112 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Writes a series of integers to a file, test.dat, +** then verifies the results. +** +** Dependency: fopen(...) +** fclose(...) +** CloseHandle(...) +** DeleteFileA(...) +** _getw(...) +** +** +** +**==========================================================================*/ + + +#include + +const char testFileName[] = "test.dat"; + +static void Cleanup(HANDLE hFile) +{ + if (fclose((PAL_FILE*)hFile)) + { + Trace("_putw: ERROR -> Unable to close file \"%s\".\n", + testFileName); + } + if (!DeleteFileA(testFileName)) + { + Trace("_putw: ERROR -> Unable to delete file \"%s\". ", + "GetLastError returned %u.\n", + testFileName, + GetLastError()); + } +} + + +int __cdecl main(int argc, char **argv) +{ + + FILE * pfTest = NULL; + int testArray[] = {0,1,-1,0x7FFFFFFF,0x80000000,0xFFFFFFFF,0xFFFFAAAA}; + int i = 0; + int retValue = 0; + + /* + * Initialize the PAL and return FAIL if this fails + */ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /*write the file that we will use to test */ + pfTest = fopen(testFileName, "w"); + if (pfTest == NULL) + { + Fail ("Unable to write test file.\n"); + } + + for (i = 0; i < sizeof(testArray)/sizeof(int) ; i++) + { + _putw(testArray[i], pfTest); + + if( ferror( pfTest ) ) + { + Cleanup(pfTest); + Fail( "Error:in _putw -> error has occurred in the " + "stream while writing to the file: \"test.dat\"\n"); + } + + } + + if (fclose(pfTest) != 0) + { + Cleanup(pfTest); + Fail ("Error closing file after writing with _putw(..).\n"); + } + + /*open the new test file and compare*/ + pfTest = fopen(testFileName, "r"); + if (pfTest == NULL) + { + Fail ("Error opening \"%s\", which is odd, since I just finished " + "creating that file.\n", testFileName); + } + retValue =_getw( pfTest ); + i = 0; + while(retValue != EOF) + { + if(retValue != testArray[i]) + { + Cleanup(pfTest); + Fail ("Integers written by _putw are not in the correct format\n", + testFileName); + } + retValue = _getw( pfTest ); + i++ ; + } + + Cleanup(pfTest); + PAL_Terminate(); + return PASS; +} + + diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/CMakeLists.txt deleted file mode 100644 index cafb953..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -add_subdirectory(test1) -add_subdirectory(test10) -add_subdirectory(test11) -add_subdirectory(test12) -add_subdirectory(test13) -add_subdirectory(test14) -add_subdirectory(test15) -add_subdirectory(test16) -add_subdirectory(test17) -add_subdirectory(test18) -add_subdirectory(test19) -add_subdirectory(test2) -add_subdirectory(test3) -add_subdirectory(test4) -add_subdirectory(test5) -add_subdirectory(test6) -add_subdirectory(test7) -add_subdirectory(test8) -add_subdirectory(test9) - diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/_snprintf.h b/src/pal/tests/palsuite/c_runtime/_snprintf/_snprintf.h deleted file mode 100644 index 84abf62..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/_snprintf.h +++ /dev/null @@ -1,194 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: _snprintf.h -** -** Purpose: Containts common testing functions for _snprintf -** -** -**==========================================================================*/ - -#ifndef __STRINGTEST_H__ -#define __STRINGTEST_H__ - -void DoStrTest(char *formatstr, char* param, char *checkstr) -{ - char buf[256] = { 0 }; - - _snprintf(buf, 256, formatstr, param); - if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) - { - Fail("ERROR: failed to insert string \"%s\" into \"%s\"\n" - "Expected \"%s\" got \"%s\".\n", - param, formatstr, checkstr, buf); - } -} - -void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr) -{ - char buf[256] = { 0 }; - - _snprintf(buf, 256, formatstr, param); - if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) - { - Fail("ERROR: failed to insert wide string \"%s\" into \"%s\"\n" - "Expected \"%s\" got \"%s\".\n", - convertC(param), formatstr, checkstr, buf); - } -} - - -void DoPointerTest(char *formatstr, void* param, char* paramstr, char - *checkstr1) -{ - char buf[256] = { 0 }; - - _snprintf(buf, 256, formatstr, param); - if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0) - { - Fail("ERROR: failed to insert %s into \"%s\"\n" - "Expected \"%s\", got \"%s\".\n", - paramstr, formatstr, checkstr1, buf); - } -} - -void DoCountTest(char *formatstr, int param, char *checkstr) -{ - char buf[512] = { 0 }; - int n = -1; - - _snprintf(buf, 512, formatstr, &n); - - if (n != param) - { - Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", - param, n); - } - if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) - { - Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf); - } -} - -void DoShortCountTest(char *formatstr, int param, char *checkstr) -{ - char buf[256] = { 0 }; - short int n = -1; - - _snprintf(buf, 256, formatstr, &n); - - if (n != param) - { - Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", - param, n); - } - if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) - { - Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf); - } -} - -void DoCharTest(char *formatstr, char param, char *checkstr) -{ - char buf[256] = { 0 }; - - _snprintf(buf, 256, formatstr, param); - if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) - { - Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n" - "Expected \"%s\" got \"%s\".\n", - param, param, formatstr, checkstr, buf); - } -} - -void DoWCharTest(char *formatstr, WCHAR param, char *checkstr) -{ - char buf[256] = { 0 }; - - _snprintf(buf, 256, formatstr, param); - if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) - { - Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n" - "Expected \"%s\" got \"%s\".\n", - (char)param, param, formatstr, checkstr, buf); - } -} - -void DoNumTest(char *formatstr, int value, char *checkstr) -{ - char buf[256] = { 0 }; - - _snprintf(buf, 256, formatstr, value); - if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) - { - Fail("ERROR: failed to insert %#x into \"%s\"\n" - "Expected \"%s\" got \"%s\".\n", - value, formatstr, checkstr, buf); - } -} - -void DoI64Test(char *formatstr, INT64 value, char *valuestr, char *checkstr1) -{ - char buf[256] = { 0 }; - - _snprintf(buf, 256, formatstr, value); - if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0) - { - Fail("ERROR: failed to insert %s into \"%s\"\n" - "Expected \"%s\", got \"%s\".\n", - valuestr, formatstr, checkstr1, buf); - } -} - -void DoDoubleTest(char *formatstr, double value, char *checkstr1, char -*checkstr2) -{ - char buf[256] = { 0 }; - - _snprintf(buf, 256, formatstr, value); - if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 - && memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) - { - Fail("ERROR: failed to insert %f into \"%s\"\n" - "Expected \"%s\" or \"%s\", got \"%s\".\n", - value, formatstr, checkstr1, checkstr2, buf); - } -} - -void DoArgumentPrecTest(char *formatstr, int precision, void *param, char -*paramstr, char *checkstr1, char*checkstr2) -{ - char buf[256]; - - _snprintf(buf, 256, formatstr, precision, param); - if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && - memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) - { - Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" - "Expected \"%s\" or \"%s\", got \"%s\".\n", - paramstr, formatstr, precision, checkstr1, checkstr2, buf); - } - -} - -void DoArgumentPrecDoubleTest(char *formatstr, int precision, double param, -char *checkstr1, char *checkstr2) -{ - char buf[256]; - - _snprintf(buf, 256, formatstr, precision, param); - if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && - memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) - { - Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" - "Expected \"%s\" or \"%s\", got \"%s\".\n", - param, formatstr, precision, checkstr1, checkstr2, buf); - } - -} - -#endif - diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test1/CMakeLists.txt deleted file mode 100644 index ab126fc..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test1/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test1.c -) - -add_executable(paltest_snprintf_test1 - ${SOURCES} -) - -add_dependencies(paltest_snprintf_test1 coreclrpal) - -target_link_libraries(paltest_snprintf_test1 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test1/test1.c deleted file mode 100644 index eef7406..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test1/test1.c +++ /dev/null @@ -1,58 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: General test to see if _snprintf works correctly -** -** -**==========================================================================*/ - - - -#include -#include "../_snprintf.h" - -/* - * Notes: memcmp is used, as is strlen. - */ - -int __cdecl main(int argc, char *argv[]) -{ - char checkstr[] = "hello world"; - char buf[256] = { 0 }; - int ret; - - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - _snprintf(buf, 256, "hello world"); - if (memcmp(checkstr, buf, strlen(checkstr)+1) != 0) - { - Fail("ERROR: expected \"%s\" (up to %d chars), got \"%s\"\n", - checkstr, 256, buf); - } - - _snprintf(buf, 256, "xxxxxxxxxxxxxxxxx"); - ret = _snprintf(buf, 8, "hello world"); - - if (ret >= 0) - { - Fail("ERROR: expected negative return value, got %d", ret); - } - if (memcmp(checkstr, buf, 8) != 0 || buf[8] != 'x') - { - Fail("ERROR: expected %s (up to %d chars), got %s\n", - checkstr, 8, buf); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test1/testinfo.dat deleted file mode 100644 index c15ce1d..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test1/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snprintf -Name = Positive Test for _snprintf -TYPE = DEFAULT -EXE1 = test1 -Description -= General test to see if _snprintf works correctly diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test10/CMakeLists.txt deleted file mode 100644 index e8e9308..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test10/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test10.c -) - -add_executable(paltest_snprintf_test10 - ${SOURCES} -) - -add_dependencies(paltest_snprintf_test10 coreclrpal) - -target_link_libraries(paltest_snprintf_test10 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test10/test10.c deleted file mode 100644 index 9191cce..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test10/test10.c +++ /dev/null @@ -1,55 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test10.c -** -** Purpose: Tests _snprintf with octal numbers -** -** -**==========================================================================*/ - - - - -#include -#include "../_snprintf.h" - -/* - * Notes: memcmp is used, as is strlen. - */ - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 42; - INT64 l = 42; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoNumTest("foo %o", pos, "foo 52"); - DoNumTest("foo %lo", 0xFFFF, "foo 177777"); - DoNumTest("foo %ho", 0xFFFF, "foo 177777"); - DoNumTest("foo %Lo", pos, "foo 52"); - DoI64Test("foo %I64o", l, "42", "foo 52"); - DoNumTest("foo %3o", pos, "foo 52"); - DoNumTest("foo %-3o", pos, "foo 52 "); - DoNumTest("foo %.1o", pos, "foo 52"); - DoNumTest("foo %.3o", pos, "foo 052"); - DoNumTest("foo %03o", pos, "foo 052"); - DoNumTest("foo %#o", pos, "foo 052"); - DoNumTest("foo %+o", pos, "foo 52"); - DoNumTest("foo % o", pos, "foo 52"); - DoNumTest("foo %+o", neg, "foo 37777777726"); - DoNumTest("foo % o", neg, "foo 37777777726"); - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test10/testinfo.dat deleted file mode 100644 index 44ff48e..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test10/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snprintf -Name = Positive Test for _snprintf -TYPE = DEFAULT -EXE1 = test10 -Description -= Tests _snprintf with octal numbers diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test11/CMakeLists.txt deleted file mode 100644 index ccf3dc2..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test11/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test11.c -) - -add_executable(paltest_snprintf_test11 - ${SOURCES} -) - -add_dependencies(paltest_snprintf_test11 coreclrpal) - -target_link_libraries(paltest_snprintf_test11 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test11/test11.c deleted file mode 100644 index 9d9302d..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test11/test11.c +++ /dev/null @@ -1,54 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test11.c -** -** Purpose: Tests _snprintf with unsigned numbers -** -** -**==========================================================================*/ - - - -#include -#include "../_snprintf.h" - -/* - * Notes: memcmp is used, as is strlen. - */ - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 42; - INT64 l = 42; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoNumTest("foo %u", pos, "foo 42"); - DoNumTest("foo %lu", 0xFFFF, "foo 65535"); - DoNumTest("foo %hu", 0xFFFF, "foo 65535"); - DoNumTest("foo %Lu", pos, "foo 42"); - DoI64Test("foo %I64u", l, "42", "foo 42"); - DoNumTest("foo %3u", pos, "foo 42"); - DoNumTest("foo %-3u", pos, "foo 42 "); - DoNumTest("foo %.1u", pos, "foo 42"); - DoNumTest("foo %.3u", pos, "foo 042"); - DoNumTest("foo %03u", pos, "foo 042"); - DoNumTest("foo %#u", pos, "foo 42"); - DoNumTest("foo %+u", pos, "foo 42"); - DoNumTest("foo % u", pos, "foo 42"); - DoNumTest("foo %+u", neg, "foo 4294967254"); - DoNumTest("foo % u", neg, "foo 4294967254"); - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test11/testinfo.dat deleted file mode 100644 index 1a77077..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test11/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snprintf -Name = Positive Test for _snprintf -TYPE = DEFAULT -EXE1 = test11 -Description -= Tests _snprintf with unsigned numbers diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test12/CMakeLists.txt deleted file mode 100644 index 68b442f..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test12/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test12.c -) - -add_executable(paltest_snprintf_test12 - ${SOURCES} -) - -add_dependencies(paltest_snprintf_test12 coreclrpal) - -target_link_libraries(paltest_snprintf_test12 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test12/test12.c deleted file mode 100644 index d782fce..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test12/test12.c +++ /dev/null @@ -1,55 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test12.c -** -** Purpose: Tests _snprintf with hex numbers (lowercase) -** -** -**==========================================================================*/ - - - -#include -#include "../_snprintf.h" - -/* - * Notes: memcmp is used, as is strlen. - */ - - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 0x1234ab; - INT64 l = I64(0x1234567887654321); - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoNumTest("foo %x", pos, "foo 1234ab"); - DoNumTest("foo %lx", pos, "foo 1234ab"); - DoNumTest("foo %hx", pos, "foo 34ab"); - DoNumTest("foo %Lx", pos, "foo 1234ab"); - DoI64Test("foo %I64x", l, "0x1234567887654321", "foo 1234567887654321"); - DoNumTest("foo %7x", pos, "foo 1234ab"); - DoNumTest("foo %-7x", pos, "foo 1234ab "); - DoNumTest("foo %.1x", pos, "foo 1234ab"); - DoNumTest("foo %.7x", pos, "foo 01234ab"); - DoNumTest("foo %07x", pos, "foo 01234ab"); - DoNumTest("foo %#x", pos, "foo 0x1234ab"); - DoNumTest("foo %+x", pos, "foo 1234ab"); - DoNumTest("foo % x", pos, "foo 1234ab"); - DoNumTest("foo %+x", neg, "foo ffffffd6"); - DoNumTest("foo % x", neg, "foo ffffffd6"); - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test12/testinfo.dat deleted file mode 100644 index 6801c74..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test12/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snprintf -Name = Positive Test for _snprintf -TYPE = DEFAULT -EXE1 = test12 -Description -= Tests _snprintf with hex numbers (lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test13/CMakeLists.txt deleted file mode 100644 index 832b3fe..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test13/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test13.c -) - -add_executable(paltest_snprintf_test13 - ${SOURCES} -) - -add_dependencies(paltest_snprintf_test13 coreclrpal) - -target_link_libraries(paltest_snprintf_test13 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test13/test13.c deleted file mode 100644 index 68ba554..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test13/test13.c +++ /dev/null @@ -1,55 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test13.c -** -** Purpose: Tests _snprintf with hex numbers (uppercase) -** -** -**==========================================================================*/ - - - -#include -#include "../_snprintf.h" - -/* - * Notes: memcmp is used, as is strlen. - */ - - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 0x1234AB; - INT64 l = I64(0x1234567887654321); - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoNumTest("foo %X", pos, "foo 1234AB"); - DoNumTest("foo %lX", pos, "foo 1234AB"); - DoNumTest("foo %hX", pos, "foo 34AB"); - DoNumTest("foo %LX", pos, "foo 1234AB"); - DoI64Test("foo %I64X", l, "0x1234567887654321", "foo 1234567887654321"); - DoNumTest("foo %7X", pos, "foo 1234AB"); - DoNumTest("foo %-7X", pos, "foo 1234AB "); - DoNumTest("foo %.1X", pos, "foo 1234AB"); - DoNumTest("foo %.7X", pos, "foo 01234AB"); - DoNumTest("foo %07X", pos, "foo 01234AB"); - DoNumTest("foo %#X", pos, "foo 0X1234AB"); - DoNumTest("foo %+X", pos, "foo 1234AB"); - DoNumTest("foo % X", pos, "foo 1234AB"); - DoNumTest("foo %+X", neg, "foo FFFFFFD6"); - DoNumTest("foo % X", neg, "foo FFFFFFD6"); - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test13/testinfo.dat deleted file mode 100644 index 6901589..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test13/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snprintf -Name = Positive Test for _snprintf -TYPE = DEFAULT -EXE1 = test13 -Description -= Tests _snprintf with hex numbers (uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test14/CMakeLists.txt deleted file mode 100644 index c2e3be1..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test14/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test14.c -) - -add_executable(paltest_snprintf_test14 - ${SOURCES} -) - -add_dependencies(paltest_snprintf_test14 coreclrpal) - -target_link_libraries(paltest_snprintf_test14 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test14/test14.c deleted file mode 100644 index d874690..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test14/test14.c +++ /dev/null @@ -1,57 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test14.c -** -** Purpose: Tests _snprintf with exponential format doubles (lowercase) -** -** -**==========================================================================*/ - - - -#include -#include "../_snprintf.h" - -/* - * Notes: memcmp is used, as is strlen. - */ - - -int __cdecl main(int argc, char *argv[]) -{ - double val = 256.0; - double neg = -256.0; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoDoubleTest("foo %e", val, "foo 2.560000e+002", "foo 2.560000e+02"); - DoDoubleTest("foo %le", val, "foo 2.560000e+002", "foo 2.560000e+02"); - DoDoubleTest("foo %he", val, "foo 2.560000e+002", "foo 2.560000e+02"); - DoDoubleTest("foo %Le", val, "foo 2.560000e+002", "foo 2.560000e+02"); - DoDoubleTest("foo %I64e", val, "foo 2.560000e+002", "foo 2.560000e+02"); - DoDoubleTest("foo %14e", val, "foo 2.560000e+002", - "foo 2.560000e+02"); - DoDoubleTest("foo %-14e", val, "foo 2.560000e+002 ", - "foo 2.560000e+02 "); - DoDoubleTest("foo %.1e", val, "foo 2.6e+002", "foo 2.6e+02"); - DoDoubleTest("foo %.8e", val, "foo 2.56000000e+002", - "foo 2.56000000e+02"); - DoDoubleTest("foo %014e", val, "foo 02.560000e+002", - "foo 002.560000e+02"); - DoDoubleTest("foo %#e", val, "foo 2.560000e+002", "foo 2.560000e+02"); - DoDoubleTest("foo %+e", val, "foo +2.560000e+002", "foo +2.560000e+02"); - DoDoubleTest("foo % e", val, "foo 2.560000e+002", "foo 2.560000e+02"); - DoDoubleTest("foo %+e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); - DoDoubleTest("foo % e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test14/testinfo.dat deleted file mode 100644 index 0f32b9b..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test14/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snprintf -Name = Positive Test for _snprintf -TYPE = DEFAULT -EXE1 = test14 -Description -= Tests _snprintf with exponential format doubles (lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test15/CMakeLists.txt deleted file mode 100644 index 1bd24d5..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test15/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test15.c -) - -add_executable(paltest_snprintf_test15 - ${SOURCES} -) - -add_dependencies(paltest_snprintf_test15 coreclrpal) - -target_link_libraries(paltest_snprintf_test15 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test15/test15.c deleted file mode 100644 index a637a70..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test15/test15.c +++ /dev/null @@ -1,56 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test15.c -** -** Purpose: Tests _snprintf with exponential format doubles (uppercase) -** -** -**==========================================================================*/ - - - -#include -#include "../_snprintf.h" - -/* - * Notes: memcmp is used, as is strlen. - */ - -int __cdecl main(int argc, char *argv[]) -{ - double val = 256.0; - double neg = -256.0; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoDoubleTest("foo %E", val, "foo 2.560000E+002", "foo 2.560000E+02"); - DoDoubleTest("foo %lE", val, "foo 2.560000E+002", "foo 2.560000E+02"); - DoDoubleTest("foo %hE", val, "foo 2.560000E+002", "foo 2.560000E+02"); - DoDoubleTest("foo %LE", val, "foo 2.560000E+002", "foo 2.560000E+02"); - DoDoubleTest("foo %I64E", val, "foo 2.560000E+002", "foo 2.560000E+02"); - DoDoubleTest("foo %14E", val, "foo 2.560000E+002", - "foo 2.560000E+02"); - DoDoubleTest("foo %-14E", val, "foo 2.560000E+002 ", - "foo 2.560000E+02 "); - DoDoubleTest("foo %.1E", val, "foo 2.6E+002", "foo 2.6E+02"); - DoDoubleTest("foo %.8E", val, "foo 2.56000000E+002", - "foo 2.56000000E+02"); - DoDoubleTest("foo %014E", val, "foo 02.560000E+002", - "foo 002.560000E+02"); - DoDoubleTest("foo %#E", val, "foo 2.560000E+002", "foo 2.560000E+02"); - DoDoubleTest("foo %+E", val, "foo +2.560000E+002", "foo +2.560000E+02"); - DoDoubleTest("foo % E", val, "foo 2.560000E+002", "foo 2.560000E+02"); - DoDoubleTest("foo %+E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); - DoDoubleTest("foo % E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test15/testinfo.dat deleted file mode 100644 index 8008cff..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test15/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snprintf -Name = Positive Test for _snprintf -TYPE = DEFAULT -EXE1 = test15 -Description -= Tests _snprintf with exponential format doubles (uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test16/CMakeLists.txt deleted file mode 100644 index 952192e..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test16/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test16.c -) - -add_executable(paltest_snprintf_test16 - ${SOURCES} -) - -add_dependencies(paltest_snprintf_test16 coreclrpal) - -target_link_libraries(paltest_snprintf_test16 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test16/test16.c deleted file mode 100644 index 6793019..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test16/test16.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test16.c -** -** Purpose: Test #15 for the _snprintf function -** -** -**==========================================================================*/ - - - -#include -#include "../_snprintf.h" - -/* - * Notes: memcmp is used, as is strlen. - */ - -int __cdecl main(int argc, char *argv[]) -{ - double val = 2560.001; - double neg = -2560.001; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoDoubleTest("foo %f", val, "foo 2560.001000", "foo 2560.001000"); - DoDoubleTest("foo %lf", val, "foo 2560.001000", "foo 2560.001000"); - DoDoubleTest("foo %hf", val, "foo 2560.001000", "foo 2560.001000"); - DoDoubleTest("foo %Lf", val, "foo 2560.001000", "foo 2560.001000"); - DoDoubleTest("foo %I64f", val, "foo 2560.001000", "foo 2560.001000"); - DoDoubleTest("foo %12f", val, "foo 2560.001000", "foo 2560.001000"); - DoDoubleTest("foo %-12f", val, "foo 2560.001000 ", "foo 2560.001000 "); - DoDoubleTest("foo %.1f", val, "foo 2560.0", "foo 2560.0"); - DoDoubleTest("foo %.8f", val, "foo 2560.00100000", "foo 2560.00100000"); - DoDoubleTest("foo %012f", val, "foo 02560.001000", "foo 02560.001000"); - DoDoubleTest("foo %#f", val, "foo 2560.001000", "foo 2560.001000"); - DoDoubleTest("foo %+f", val, "foo +2560.001000", "foo +2560.001000"); - DoDoubleTest("foo % f", val, "foo 2560.001000", "foo 2560.001000"); - DoDoubleTest("foo %+f", neg, "foo -2560.001000", "foo -2560.001000"); - DoDoubleTest("foo % f", neg, "foo -2560.001000", "foo -2560.001000"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test16/testinfo.dat deleted file mode 100644 index e7a7df8..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test16/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snprintf -Name = Positive Test for _snprintf -TYPE = DEFAULT -EXE1 = test16 -Description -= Tests _snprintf with decimal point format doubles diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test17/CMakeLists.txt deleted file mode 100644 index ce5cc16..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test17/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test17.c -) - -add_executable(paltest_snprintf_test17 - ${SOURCES} -) - -add_dependencies(paltest_snprintf_test17 coreclrpal) - -target_link_libraries(paltest_snprintf_test17 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test17/test17.c deleted file mode 100644 index 9981b44..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test17/test17.c +++ /dev/null @@ -1,53 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test17.c -** -** Purpose: Tests _snprintf with compact format doubles (lowercase) -** -** -**==========================================================================*/ - - - -#include -#include "../_snprintf.h" - -/* - * Notes: memcmp is used, as is strlen. - */ - -int __cdecl main(int argc, char *argv[]) -{ - double val = 2560.001; - double neg = -2560.001; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoDoubleTest("foo %g", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %lg", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %hg", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %Lg", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %I64g", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %5g", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %-5g", val, "foo 2560 ", "foo 2560 "); - DoDoubleTest("foo %.1g", val, "foo 3e+003", "foo 3e+03"); - DoDoubleTest("foo %.2g", val, "foo 2.6e+003", "foo 2.6e+03"); - DoDoubleTest("foo %.12g", val, "foo 2560.001", "foo 2560.001"); - DoDoubleTest("foo %06g", val, "foo 002560", "foo 002560"); - DoDoubleTest("foo %#g", val, "foo 2560.00", "foo 2560.00"); - DoDoubleTest("foo %+g", val, "foo +2560", "foo +2560"); - DoDoubleTest("foo % g", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %+g", neg, "foo -2560", "foo -2560"); - DoDoubleTest("foo % g", neg, "foo -2560", "foo -2560"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test17/testinfo.dat deleted file mode 100644 index 4756bd0..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test17/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snprintf -Name = Positive Test for _snprintf -TYPE = DEFAULT -EXE1 = test17 -Description -= Tests _snprintf with compact format doubles (lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test18/CMakeLists.txt deleted file mode 100644 index bb9c9c3..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test18/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test18.c -) - -add_executable(paltest_snprintf_test18 - ${SOURCES} -) - -add_dependencies(paltest_snprintf_test18 coreclrpal) - -target_link_libraries(paltest_snprintf_test18 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test18/test18.c deleted file mode 100644 index d28aec5..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test18/test18.c +++ /dev/null @@ -1,53 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test18.c -** -** Purpose: Tests _snprintf with compact format doubles (uppercase) -** -** -**==========================================================================*/ - - - -#include -#include "../_snprintf.h" - -/* - * Notes: memcmp is used, as is strlen. - */ - -int __cdecl main(int argc, char *argv[]) -{ - double val = 2560.001; - double neg = -2560.001; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoDoubleTest("foo %G", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %lG", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %hG", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %LG", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %I64G", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %5G", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %-5G", val, "foo 2560 ", "foo 2560 "); - DoDoubleTest("foo %.1G", val, "foo 3E+003", "foo 3E+03"); - DoDoubleTest("foo %.2G", val, "foo 2.6E+003", "foo 2.6E+03"); - DoDoubleTest("foo %.12G", val, "foo 2560.001", "foo 2560.001"); - DoDoubleTest("foo %06G", val, "foo 002560", "foo 002560"); - DoDoubleTest("foo %#G", val, "foo 2560.00", "foo 2560.00"); - DoDoubleTest("foo %+G", val, "foo +2560", "foo +2560"); - DoDoubleTest("foo % G", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %+G", neg, "foo -2560", "foo -2560"); - DoDoubleTest("foo % G", neg, "foo -2560", "foo -2560"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test18/testinfo.dat deleted file mode 100644 index 819d28c..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test18/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snprintf -Name = Positive Test for _snprintf -TYPE = DEFAULT -EXE1 = test18 -Description -= Tests _snprintf with compact format doubles (uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test19/CMakeLists.txt deleted file mode 100644 index f3fbb95..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test19/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test19.c -) - -add_executable(paltest_snprintf_test19 - ${SOURCES} -) - -add_dependencies(paltest_snprintf_test19 coreclrpal) - -target_link_libraries(paltest_snprintf_test19 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test19/test19.c deleted file mode 100644 index 26dffd9..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test19/test19.c +++ /dev/null @@ -1,76 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test19.c -** -** Purpose:Tests _snprintf with argument specified precision -** -** -**==========================================================================*/ - - - -#include -#include "../_snprintf.h" - -/* - * Notes: memcmp is used, as is strlen. - */ - - -int __cdecl main(int argc, char *argv[]) -{ - int n = -1; - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - DoArgumentPrecTest("%.*s", 2, "bar", "bar", "ba", "ba"); - DoArgumentPrecTest("%.*S", 2, convert("bar"), "bar", "ba", "ba"); - DoArgumentPrecTest("%.*n", 3, &n, "pointer to int", "", ""); - if (n != 0) - { - Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", - 0, n); - } - - DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); - DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); - DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); - DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); - DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42") ; - DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); - - - DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); - DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); - DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); - DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); - DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); - DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); - DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); - DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); - DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); - DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test19/testinfo.dat deleted file mode 100644 index 875abf7..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test19/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snprintf -Name = Positive Test for _snprintf -TYPE = DEFAULT -EXE1 = test19 -Description -= Tests _snprintf with argument specified precision diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test2/CMakeLists.txt deleted file mode 100644 index 8c617df..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test2/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test2.c -) - -add_executable(paltest_snprintf_test2 - ${SOURCES} -) - -add_dependencies(paltest_snprintf_test2 coreclrpal) - -target_link_libraries(paltest_snprintf_test2 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test2/test2.c deleted file mode 100644 index 3ccb66c..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test2/test2.c +++ /dev/null @@ -1,44 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test2.c -** -** Purpose:Tests _snprintf with strings -** -** -**==========================================================================*/ - - - -#include -#include "../_snprintf.h" -/* - * Notes: memcmp is used, as is strlen. - */ - -int __cdecl main(int argc, char *argv[]) -{ - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - DoStrTest("foo %s", "bar", "foo bar"); - DoStrTest("foo %hs", "bar", "foo bar"); - DoWStrTest("foo %ls", convert("bar"), "foo bar"); - DoWStrTest("foo %ws", convert("bar"), "foo bar"); - DoStrTest("foo %Ls", "bar", "foo bar"); - DoStrTest("foo %I64s", "bar", "foo bar"); - DoStrTest("foo %5s", "bar", "foo bar"); - DoStrTest("foo %.2s", "bar", "foo ba"); - DoStrTest("foo %5.2s", "bar", "foo ba"); - DoStrTest("foo %-5s", "bar", "foo bar "); - DoStrTest("foo %05s", "bar", "foo 00bar"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test2/testinfo.dat deleted file mode 100644 index 40a1ede..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test2/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snprintf -Name = Positive Test for _snprintf -TYPE = DEFAULT -EXE1 = test2 -Description -= Tests _snprintf with strings diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test3/CMakeLists.txt deleted file mode 100644 index 1333046..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test3/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test3.c -) - -add_executable(paltest_snprintf_test3 - ${SOURCES} -) - -add_dependencies(paltest_snprintf_test3 coreclrpal) - -target_link_libraries(paltest_snprintf_test3 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test3/test3.c deleted file mode 100644 index 496159c..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test3/test3.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test3.c -** -** Purpose: Tests _snprintf with wide strings -** -** -**==========================================================================*/ - - - -#include -#include "../_snprintf.h" - -/* - * Notes: memcmp is used, as is strlen. - */ - -int __cdecl main(int argc, char *argv[]) -{ - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - DoWStrTest("foo %S", convert("bar"), "foo bar"); - DoStrTest("foo %hS", "bar", "foo bar"); - DoWStrTest("foo %lS", convert("bar"), "foo bar"); - DoWStrTest("foo %wS", convert("bar"), "foo bar"); - DoWStrTest("foo %LS", convert("bar"), "foo bar"); - DoWStrTest("foo %I64S", convert("bar"), "foo bar"); - DoWStrTest("foo %5S", convert("bar"), "foo bar"); - DoWStrTest("foo %.2S", convert("bar"), "foo ba"); - DoWStrTest("foo %5.2S", convert("bar"), "foo ba"); - DoWStrTest("foo %-5S", convert("bar"), "foo bar "); - DoWStrTest("foo %05S", convert("bar"), "foo 00bar"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test3/testinfo.dat deleted file mode 100644 index fa53224..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test3/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snprintf -Name = Positive Test for _snprintf -TYPE = DEFAULT -EXE1 = test3 -Description -= Tests _snprintf with wide strings diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test4/CMakeLists.txt deleted file mode 100644 index 5132aa0..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test4/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test4.c -) - -add_executable(paltest_snprintf_test4 - ${SOURCES} -) - -add_dependencies(paltest_snprintf_test4 coreclrpal) - -target_link_libraries(paltest_snprintf_test4 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test4/test4.c deleted file mode 100644 index 8c39f22..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test4/test4.c +++ /dev/null @@ -1,69 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test4.c -** -** Purpose: Tests _snprintf with pointers -** -** -**==========================================================================*/ - - - -#include -#include "../_snprintf.h" - -/* - * Notes: memcmp is used, as is strlen. - */ - - -int __cdecl main(int argc, char *argv[]) -{ - void *ptr = (void*) 0x123456; - INT64 lptr = I64(0x1234567887654321); - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - /* - ** Run only on 64 bit platforms - */ - #if defined(BIT64) && defined(PLATFORM_UNIX) - Trace("Testing for 64 Bit Platforms \n"); - DoPointerTest("%p", NULL, "NULL", "0000000000000000"); - DoPointerTest("%p", ptr, "pointer to 0x123456", "0000000000123456"); - DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); - DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); - DoPointerTest("%-17p", ptr, "pointer to 0x123456", "0000000000123456 "); - DoPointerTest("%+p", ptr, "pointer to 0x123456", "0000000000123456"); - DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X0000000000123456"); - DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); - DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); - DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); - DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321", - "1234567887654321"); - #else - Trace("Testing for Non 64 Bit Platforms \n"); - DoPointerTest("%p", NULL, "NULL", "00000000"); - DoPointerTest("%p", ptr, "pointer to 0x123456", "00123456"); - DoPointerTest("%9p", ptr, "pointer to 0x123456", " 00123456"); - DoPointerTest("%09p", ptr, "pointer to 0x123456", " 00123456"); - DoPointerTest("%-9p", ptr, "pointer to 0x123456", "00123456 "); - DoPointerTest("%+p", ptr, "pointer to 0x123456", "00123456"); - DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X00123456"); - DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); - DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); - DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); - DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321", - "1234567887654321"); - #endif //defined(BIT64) && defined(PLATFORM_UNIX) - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test4/testinfo.dat deleted file mode 100644 index 5d822d1..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test4/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snprintf -Name = Positive Test for _snprintf -TYPE = DEFAULT -EXE1 = test4 -Description -= Tests _snprintf with pointers diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test5/CMakeLists.txt deleted file mode 100644 index 07e441c..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test5/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test5.c -) - -add_executable(paltest_snprintf_test5 - ${SOURCES} -) - -add_dependencies(paltest_snprintf_test5 coreclrpal) - -target_link_libraries(paltest_snprintf_test5 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test5/test5.c deleted file mode 100644 index 46ab1dd..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test5/test5.c +++ /dev/null @@ -1,61 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test5.c -** -** Purpose: Tests _snprintf with the count specifier -** -** -**==========================================================================*/ - - - -#include -#include "../_snprintf.h" - -/* - * Notes: memcmp is used, as is strlen. - */ - - -int __cdecl main(int argc, char *argv[]) -{ - char *longStr = - "really-long-string-that-just-keeps-going-on-and-on-and-on.." - "..................useless-filler.................................." - "..................useless-filler.................................." - "..................useless-filler.................................." - "%n bar"; - char *longResult = - "really-long-string-that-just-keeps-going-on-and-on-and-on.." - "..................useless-filler.................................." - "..................useless-filler.................................." - "..................useless-filler.................................." - " bar"; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - DoCountTest("foo %n bar", 4, "foo bar"); - DoCountTest(longStr, 257, longResult); - DoCountTest("fo%n bar", 2, "fo bar"); - DoCountTest("%n", 0, ""); - DoCountTest("foo %#n bar", 4, "foo bar"); - DoCountTest("foo % n bar", 4, "foo bar"); - DoCountTest("foo %+n bar", 4, "foo bar"); - DoCountTest("foo %-n bar", 4, "foo bar"); - DoCountTest("foo %0n bar", 4, "foo bar"); - DoShortCountTest("foo %hn bar", 4, "foo bar"); - DoCountTest("foo %ln bar", 4, "foo bar"); - DoCountTest("foo %Ln bar", 4, "foo bar"); - DoCountTest("foo %I64n bar", 4, "foo bar"); - DoCountTest("foo %20.3n bar", 4, "foo bar"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test5/testinfo.dat deleted file mode 100644 index 33056de..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test5/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snprintf -Name = Positive Test for _snprintf -TYPE = DEFAULT -EXE1 = test5 -Description -= Tests _snprintf with the count specifier diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test6/CMakeLists.txt deleted file mode 100644 index 9ee5d90..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test6/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test6.c -) - -add_executable(paltest_snprintf_test6 - ${SOURCES} -) - -add_dependencies(paltest_snprintf_test6 coreclrpal) - -target_link_libraries(paltest_snprintf_test6 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test6/test6.c deleted file mode 100644 index 32001c2..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test6/test6.c +++ /dev/null @@ -1,47 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test6.c -** -** Purpose: Tests _snprintf with characters -** -** -**==========================================================================*/ - - - -#include -#include "../_snprintf.h" - -/* - * Notes: memcmp is used, as is strlen. - */ - -int __cdecl main(int argc, char *argv[]) -{ - WCHAR wc = (WCHAR) 'c'; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoCharTest("foo %c", 'b', "foo b"); - DoCharTest("foo %hc", 'b', "foo b"); - DoWCharTest("foo %lc", wc, "foo c"); - DoCharTest("foo %Lc", 'b', "foo b"); - DoCharTest("foo %I64c", 'b', "foo b"); - DoCharTest("foo %5c", 'b', "foo b"); - DoCharTest("foo %.0c", 'b', "foo b"); - DoCharTest("foo %-5c", 'b', "foo b "); - DoCharTest("foo %05c", 'b', "foo 0000b"); - DoCharTest("foo % c", 'b', "foo b"); - DoCharTest("foo %#c", 'b', "foo b"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test6/testinfo.dat deleted file mode 100644 index ba2ff81..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test6/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snprintf -Name =Positive Test for _snprintf -TYPE = DEFAULT -EXE1 = test6 -Description -= Tests _snprintf with characters diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test7/CMakeLists.txt deleted file mode 100644 index f765121..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test7/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test7.c -) - -add_executable(paltest_snprintf_test7 - ${SOURCES} -) - -add_dependencies(paltest_snprintf_test7 coreclrpal) - -target_link_libraries(paltest_snprintf_test7 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test7/test7.c deleted file mode 100644 index bfd5c3f..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test7/test7.c +++ /dev/null @@ -1,47 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test7.c -** -** Purpose: Tests _snprintf with wide characters -** -** -**==========================================================================*/ - - - -#include -#include "../_snprintf.h" -/* - * Notes: memcmp is used, as is strlen. - */ - - -int __cdecl main(int argc, char *argv[]) -{ - WCHAR wb = (WCHAR) 'b'; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoWCharTest("foo %C", wb, "foo b"); - DoWCharTest("foo %hC", wb, "foo b"); - DoCharTest("foo %lC", 'c', "foo c"); - DoWCharTest("foo %LC", wb, "foo b"); - DoWCharTest("foo %I64C", wb, "foo b"); - DoWCharTest("foo %5C", wb, "foo b"); - DoWCharTest("foo %.0C", wb, "foo b"); - DoWCharTest("foo %-5C", wb, "foo b "); - DoWCharTest("foo %05C", wb, "foo 0000b"); - DoWCharTest("foo % C", wb, "foo b"); - DoWCharTest("foo %#C", wb, "foo b"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test7/testinfo.dat deleted file mode 100644 index 5c2406c..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test7/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snprintf -Name = Positive Test for _snprintf -TYPE = DEFAULT -EXE1 = test7 -Description -= Tests _snprintf with wide characters diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test8/CMakeLists.txt deleted file mode 100644 index 26af119..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test8/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test8.c -) - -add_executable(paltest_snprintf_test8 - ${SOURCES} -) - -add_dependencies(paltest_snprintf_test8 coreclrpal) - -target_link_libraries(paltest_snprintf_test8 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test8/test8.c deleted file mode 100644 index 60ff1b0..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test8/test8.c +++ /dev/null @@ -1,56 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test8.c -** -** Purpose: Tests _snprintf with decimal numbers -** -** -**==========================================================================*/ - - - -#include -#include "../_snprintf.h" - -/* - * Notes: memcmp is used, as is strlen. - */ - - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 42; - INT64 l = 42; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoNumTest("foo %d", pos, "foo 42"); - DoNumTest("foo %ld", 0xFFFF, "foo 65535"); - DoNumTest("foo %hd", 0xFFFF, "foo -1"); - DoNumTest("foo %Ld", pos, "foo 42"); - DoI64Test("foo %I64d", l, "42", "foo 42"); - DoNumTest("foo %3d", pos, "foo 42"); - DoNumTest("foo %-3d", pos, "foo 42 "); - DoNumTest("foo %.1d", pos, "foo 42"); - DoNumTest("foo %.3d", pos, "foo 042"); - DoNumTest("foo %03d", pos, "foo 042"); - DoNumTest("foo %#d", pos, "foo 42"); - DoNumTest("foo %+d", pos, "foo +42"); - DoNumTest("foo % d", pos, "foo 42"); - DoNumTest("foo %+d", neg, "foo -42"); - DoNumTest("foo % d", neg, "foo -42"); - - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test8/testinfo.dat deleted file mode 100644 index f6520d8..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test8/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snprintf -Name = Positive Test for _snprintf -TYPE = DEFAULT -EXE1 = test8 -Description -= Tests _snprintf with decimal numbers diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf/test9/CMakeLists.txt deleted file mode 100644 index 4840759..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test9/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test9.c -) - -add_executable(paltest_snprintf_test9 - ${SOURCES} -) - -add_dependencies(paltest_snprintf_test9 coreclrpal) - -target_link_libraries(paltest_snprintf_test9 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/_snprintf/test9/test9.c deleted file mode 100644 index e836bca..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test9/test9.c +++ /dev/null @@ -1,55 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test9.c -** -** Purpose: Tests _snprintf with integer numbers -** -** -**==========================================================================*/ - - - -#include -#include "../_snprintf.h" - -/* - * Notes: memcmp is used, as is strlen. - */ - - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 42; - INT64 l = 42; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoNumTest("foo %i", pos, "foo 42"); - DoNumTest("foo %li", 0xFFFF, "foo 65535"); - DoNumTest("foo %hi", 0xFFFF, "foo -1"); - DoNumTest("foo %Li", pos, "foo 42"); - DoI64Test("foo %I64i", l, "42", "foo 42"); - DoNumTest("foo %3i", pos, "foo 42"); - DoNumTest("foo %-3i", pos, "foo 42 "); - DoNumTest("foo %.1i", pos, "foo 42"); - DoNumTest("foo %.3i", pos, "foo 042"); - DoNumTest("foo %03i", pos, "foo 042"); - DoNumTest("foo %#i", pos, "foo 42"); - DoNumTest("foo %+i", pos, "foo +42"); - DoNumTest("foo % i", pos, "foo 42"); - DoNumTest("foo %+i", neg, "foo -42"); - DoNumTest("foo % i", neg, "foo -42"); - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf/test9/testinfo.dat deleted file mode 100644 index 2a64b26..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snprintf/test9/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snprintf -Name = Positive Test for _snprintf -TYPE = DEFAULT -EXE1 = test9 -Description -= Tests _snprintf with integer numbers diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf_s/CMakeLists.txt new file mode 100644 index 0000000..8fe1cb6 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) +add_subdirectory(test10) +add_subdirectory(test11) +add_subdirectory(test12) +add_subdirectory(test13) +add_subdirectory(test14) +add_subdirectory(test15) +add_subdirectory(test16) +add_subdirectory(test17) +add_subdirectory(test18) +add_subdirectory(test19) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/_snprintf_s.h b/src/pal/tests/palsuite/c_runtime/_snprintf_s/_snprintf_s.h new file mode 100644 index 0000000..9ed5209 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/_snprintf_s.h @@ -0,0 +1,194 @@ +// 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. + +/*============================================================================ +** +** Source: sprintf_s.h +** +** Purpose: Containts common testing functions for sprintf_s +** +** +**==========================================================================*/ + +#ifndef __STRINGTEST_H__ +#define __STRINGTEST_H__ + +void DoStrTest(const char *formatstr, char* param, const char *checkstr) +{ + char buf[256] = { 0 }; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, param); + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert string \"%s\" into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + param, formatstr, checkstr, buf); + } +} + +void DoWStrTest(const char *formatstr, WCHAR* param, const char *checkstr) +{ + char buf[256] = { 0 }; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, param); + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert wide string \"%s\" into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + convertC(param), formatstr, checkstr, buf); + } +} + + +void DoPointerTest(const char *formatstr, void* param, char* paramstr, char + *checkstr1) +{ + char buf[256] = { 0 }; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, param); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\", got \"%s\".\n", + paramstr, formatstr, checkstr1, buf); + } +} + +void DoCountTest(const char *formatstr, int param, const char *checkstr) +{ + char buf[512] = { 0 }; + int n = -1; + + sprintf_s(buf, 512, formatstr, &n); + + if (n != param) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + param, n); + } + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf); + } +} + +void DoShortCountTest(const char *formatstr, int param, const char *checkstr) +{ + char buf[256] = { 0 }; + short int n = -1; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, &n); + + if (n != param) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + param, n); + } + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf); + } +} + +void DoCharTest(const char *formatstr, char param, const char *checkstr) +{ + char buf[256] = { 0 }; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, param); + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + param, param, formatstr, checkstr, buf); + } +} + +void DoWCharTest(const char *formatstr, WCHAR param, const char *checkstr) +{ + char buf[256] = { 0 }; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, param); + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + (char)param, param, formatstr, checkstr, buf); + } +} + +void DoNumTest(const char *formatstr, int value, const char *checkstr) +{ + char buf[256] = { 0 }; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, value); + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert %#x into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + value, formatstr, checkstr, buf); + } +} + +void DoI64Test(const char *formatstr, INT64 value, char *valuestr, const char *checkstr1) +{ + char buf[256] = { 0 }; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, value); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\", got \"%s\".\n", + valuestr, formatstr, checkstr1, buf); + } +} + +void DoDoubleTest(const char *formatstr, double value, const char *checkstr1, char +*checkstr2) +{ + char buf[256] = { 0 }; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, value); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 + && memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\"\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + value, formatstr, checkstr1, checkstr2, buf); + } +} + +void DoArgumentPrecTest(const char *formatstr, int precision, void *param, char +*paramstr, const char *checkstr1, const char *checkstr2) +{ + char buf[256]; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, precision, param); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + paramstr, formatstr, precision, checkstr1, checkstr2, buf); + } + +} + +void DoArgumentPrecDoubleTest(const char *formatstr, int precision, double param, +const char *checkstr1, const char *checkstr2) +{ + char buf[256]; + + _snprintf_s(buf, 256, _TRUNCATE, formatstr, precision, param); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + param, formatstr, precision, checkstr1, checkstr2, buf); + } + +} + +#endif + diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/CMakeLists.txt new file mode 100644 index 0000000..9e4c671 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.cpp +) + +add_executable(paltest_snprintf_test1 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test1 coreclrpal) + +target_link_libraries(paltest_snprintf_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/test1.cpp b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/test1.cpp new file mode 100644 index 0000000..d180b05 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/test1.cpp @@ -0,0 +1,58 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: General test to see if sprintf_s works correctly +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + char checkstr[] = "hello world"; + char buf[256] = { 0 }; + int ret; + + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + _snprintf_s(buf, 256, _TRUNCATE, "hello world"); + if (memcmp(checkstr, buf, strlen(checkstr)+1) != 0) + { + Fail("ERROR: expected \"%s\" (up to %d chars), got \"%s\"\n", + checkstr, 256, buf); + } + + _snprintf_s(buf, 256, _TRUNCATE, "xxxxxxxxxxxxxxxxx"); + ret = _snprintf_s(buf, 8, _TRUNCATE, "hello world"); + + if (ret >= 0) + { + Fail("ERROR: expected negative return value, got %d", ret); + } + if (memcmp(checkstr, buf, 7) != 0 || buf[7] != 0 || buf[8] != 'x') + { + Fail("ERROR: expected %s (up to %d chars), got %s\n", + checkstr, 8, buf); + } + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/testinfo.dat new file mode 100644 index 0000000..255c534 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test1/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test1 +Description += General test to see if sprintf_s works correctly diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/CMakeLists.txt new file mode 100644 index 0000000..57e7fb1 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test10.cpp +) + +add_executable(paltest_snprintf_test10 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test10 coreclrpal) + +target_link_libraries(paltest_snprintf_test10 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/test10.cpp b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/test10.cpp new file mode 100644 index 0000000..7ecb910 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/test10.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test10.c +** +** Purpose: Tests sprintf_s with octal numbers +** +** +**==========================================================================*/ + + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %o", pos, "foo 52"); + DoNumTest("foo %lo", 0xFFFF, "foo 177777"); + DoNumTest("foo %ho", 0xFFFF, "foo 177777"); + DoNumTest("foo %Lo", pos, "foo 52"); + DoI64Test("foo %I64o", l, "42", "foo 52"); + DoNumTest("foo %3o", pos, "foo 52"); + DoNumTest("foo %-3o", pos, "foo 52 "); + DoNumTest("foo %.1o", pos, "foo 52"); + DoNumTest("foo %.3o", pos, "foo 052"); + DoNumTest("foo %03o", pos, "foo 052"); + DoNumTest("foo %#o", pos, "foo 052"); + DoNumTest("foo %+o", pos, "foo 52"); + DoNumTest("foo % o", pos, "foo 52"); + DoNumTest("foo %+o", neg, "foo 37777777726"); + DoNumTest("foo % o", neg, "foo 37777777726"); + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/testinfo.dat new file mode 100644 index 0000000..25ed554 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test10/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test10 +Description += Tests sprintf_s with octal numbers diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/CMakeLists.txt new file mode 100644 index 0000000..4fc179c --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test11.cpp +) + +add_executable(paltest_snprintf_test11 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test11 coreclrpal) + +target_link_libraries(paltest_snprintf_test11 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/test11.cpp b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/test11.cpp new file mode 100644 index 0000000..c2ac015 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/test11.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test11.c +** +** Purpose: Tests sprintf_s with unsigned numbers +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %u", pos, "foo 42"); + DoNumTest("foo %lu", 0xFFFF, "foo 65535"); + DoNumTest("foo %hu", 0xFFFF, "foo 65535"); + DoNumTest("foo %Lu", pos, "foo 42"); + DoI64Test("foo %I64u", l, "42", "foo 42"); + DoNumTest("foo %3u", pos, "foo 42"); + DoNumTest("foo %-3u", pos, "foo 42 "); + DoNumTest("foo %.1u", pos, "foo 42"); + DoNumTest("foo %.3u", pos, "foo 042"); + DoNumTest("foo %03u", pos, "foo 042"); + DoNumTest("foo %#u", pos, "foo 42"); + DoNumTest("foo %+u", pos, "foo 42"); + DoNumTest("foo % u", pos, "foo 42"); + DoNumTest("foo %+u", neg, "foo 4294967254"); + DoNumTest("foo % u", neg, "foo 4294967254"); + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/testinfo.dat new file mode 100644 index 0000000..3144f12 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test11/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test11 +Description += Tests sprintf_s with unsigned numbers diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/CMakeLists.txt new file mode 100644 index 0000000..a35609e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test12.cpp +) + +add_executable(paltest_snprintf_test12 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test12 coreclrpal) + +target_link_libraries(paltest_snprintf_test12 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/test12.cpp b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/test12.cpp new file mode 100644 index 0000000..5217183 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/test12.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test12.c +** +** Purpose: Tests sprintf_s with hex numbers (lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %x", pos, "foo 1234ab"); + DoNumTest("foo %lx", pos, "foo 1234ab"); + DoNumTest("foo %hx", pos, "foo 34ab"); + DoNumTest("foo %Lx", pos, "foo 1234ab"); + DoI64Test("foo %I64x", l, "0x1234567887654321", "foo 1234567887654321"); + DoNumTest("foo %7x", pos, "foo 1234ab"); + DoNumTest("foo %-7x", pos, "foo 1234ab "); + DoNumTest("foo %.1x", pos, "foo 1234ab"); + DoNumTest("foo %.7x", pos, "foo 01234ab"); + DoNumTest("foo %07x", pos, "foo 01234ab"); + DoNumTest("foo %#x", pos, "foo 0x1234ab"); + DoNumTest("foo %+x", pos, "foo 1234ab"); + DoNumTest("foo % x", pos, "foo 1234ab"); + DoNumTest("foo %+x", neg, "foo ffffffd6"); + DoNumTest("foo % x", neg, "foo ffffffd6"); + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/testinfo.dat new file mode 100644 index 0000000..ed91cec --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test12/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test12 +Description += Tests sprintf_s with hex numbers (lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/CMakeLists.txt new file mode 100644 index 0000000..3bf986e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test13.cpp +) + +add_executable(paltest_snprintf_test13 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test13 coreclrpal) + +target_link_libraries(paltest_snprintf_test13 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/test13.cpp b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/test13.cpp new file mode 100644 index 0000000..15e4755 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/test13.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test13.c +** +** Purpose: Tests sprintf_s with hex numbers (uppercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234AB; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %X", pos, "foo 1234AB"); + DoNumTest("foo %lX", pos, "foo 1234AB"); + DoNumTest("foo %hX", pos, "foo 34AB"); + DoNumTest("foo %LX", pos, "foo 1234AB"); + DoI64Test("foo %I64X", l, "0x1234567887654321", "foo 1234567887654321"); + DoNumTest("foo %7X", pos, "foo 1234AB"); + DoNumTest("foo %-7X", pos, "foo 1234AB "); + DoNumTest("foo %.1X", pos, "foo 1234AB"); + DoNumTest("foo %.7X", pos, "foo 01234AB"); + DoNumTest("foo %07X", pos, "foo 01234AB"); + DoNumTest("foo %#X", pos, "foo 0X1234AB"); + DoNumTest("foo %+X", pos, "foo 1234AB"); + DoNumTest("foo % X", pos, "foo 1234AB"); + DoNumTest("foo %+X", neg, "foo FFFFFFD6"); + DoNumTest("foo % X", neg, "foo FFFFFFD6"); + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/testinfo.dat new file mode 100644 index 0000000..fd5f530 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test13/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test13 +Description += Tests sprintf_s with hex numbers (uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/CMakeLists.txt new file mode 100644 index 0000000..985303e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test14.cpp +) + +add_executable(paltest_snprintf_test14 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test14 coreclrpal) + +target_link_libraries(paltest_snprintf_test14 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/test14.cpp b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/test14.cpp new file mode 100644 index 0000000..331475e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/test14.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test14.c +** +** Purpose: Tests sprintf_s with exponential format doubles (lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest("foo %e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %le", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %he", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %Le", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %I64e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %14e", val, "foo 2.560000e+002", + "foo 2.560000e+02"); + DoDoubleTest("foo %-14e", val, "foo 2.560000e+002 ", + "foo 2.560000e+02 "); + DoDoubleTest("foo %.1e", val, "foo 2.6e+002", "foo 2.6e+02"); + DoDoubleTest("foo %.8e", val, "foo 2.56000000e+002", + "foo 2.56000000e+02"); + DoDoubleTest("foo %014e", val, "foo 02.560000e+002", + "foo 002.560000e+02"); + DoDoubleTest("foo %#e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %+e", val, "foo +2.560000e+002", "foo +2.560000e+02"); + DoDoubleTest("foo % e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %+e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); + DoDoubleTest("foo % e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/testinfo.dat new file mode 100644 index 0000000..23cf423 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test14/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test14 +Description += Tests sprintf_s with exponential format doubles (lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/CMakeLists.txt new file mode 100644 index 0000000..c7f5796 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test15.cpp +) + +add_executable(paltest_snprintf_test15 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test15 coreclrpal) + +target_link_libraries(paltest_snprintf_test15 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/test15.cpp b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/test15.cpp new file mode 100644 index 0000000..d43613b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/test15.cpp @@ -0,0 +1,56 @@ +// 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. + +/*============================================================================ +** +** Source: test15.c +** +** Purpose: Tests sprintf_s with exponential format doubles (uppercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest("foo %E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %lE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %hE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %LE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %I64E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %14E", val, "foo 2.560000E+002", + "foo 2.560000E+02"); + DoDoubleTest("foo %-14E", val, "foo 2.560000E+002 ", + "foo 2.560000E+02 "); + DoDoubleTest("foo %.1E", val, "foo 2.6E+002", "foo 2.6E+02"); + DoDoubleTest("foo %.8E", val, "foo 2.56000000E+002", + "foo 2.56000000E+02"); + DoDoubleTest("foo %014E", val, "foo 02.560000E+002", + "foo 002.560000E+02"); + DoDoubleTest("foo %#E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %+E", val, "foo +2.560000E+002", "foo +2.560000E+02"); + DoDoubleTest("foo % E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %+E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); + DoDoubleTest("foo % E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/testinfo.dat new file mode 100644 index 0000000..537e6d1 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test15/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test15 +Description += Tests sprintf_s with exponential format doubles (uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/CMakeLists.txt new file mode 100644 index 0000000..9a224bc --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test16.cpp +) + +add_executable(paltest_snprintf_test16 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test16 coreclrpal) + +target_link_libraries(paltest_snprintf_test16 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/test16.cpp b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/test16.cpp new file mode 100644 index 0000000..21cbb1e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/test16.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test16.c +** +** Purpose: Test #15 for the sprintf_s function +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest("foo %f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %lf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %hf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %Lf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %I64f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %12f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %-12f", val, "foo 2560.001000 ", "foo 2560.001000 "); + DoDoubleTest("foo %.1f", val, "foo 2560.0", "foo 2560.0"); + DoDoubleTest("foo %.8f", val, "foo 2560.00100000", "foo 2560.00100000"); + DoDoubleTest("foo %012f", val, "foo 02560.001000", "foo 02560.001000"); + DoDoubleTest("foo %#f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %+f", val, "foo +2560.001000", "foo +2560.001000"); + DoDoubleTest("foo % f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %+f", neg, "foo -2560.001000", "foo -2560.001000"); + DoDoubleTest("foo % f", neg, "foo -2560.001000", "foo -2560.001000"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/testinfo.dat new file mode 100644 index 0000000..4e98ecc --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test16/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test16 +Description += Tests sprintf_s with decimal point format doubles diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/CMakeLists.txt new file mode 100644 index 0000000..3a8a349 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test17.cpp +) + +add_executable(paltest_snprintf_test17 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test17 coreclrpal) + +target_link_libraries(paltest_snprintf_test17 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/test17.cpp b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/test17.cpp new file mode 100644 index 0000000..d161270 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/test17.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test17.c +** +** Purpose: Tests sprintf_s with compact format doubles (lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest("foo %g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %lg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %hg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %Lg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %I64g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %5g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %-5g", val, "foo 2560 ", "foo 2560 "); + DoDoubleTest("foo %.1g", val, "foo 3e+003", "foo 3e+03"); + DoDoubleTest("foo %.2g", val, "foo 2.6e+003", "foo 2.6e+03"); + DoDoubleTest("foo %.12g", val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest("foo %06g", val, "foo 002560", "foo 002560"); + DoDoubleTest("foo %#g", val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest("foo %+g", val, "foo +2560", "foo +2560"); + DoDoubleTest("foo % g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %+g", neg, "foo -2560", "foo -2560"); + DoDoubleTest("foo % g", neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/testinfo.dat new file mode 100644 index 0000000..5e41e20 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test17/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test17 +Description += Tests sprintf_s with compact format doubles (lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/CMakeLists.txt new file mode 100644 index 0000000..96e39e8 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test18.cpp +) + +add_executable(paltest_snprintf_test18 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test18 coreclrpal) + +target_link_libraries(paltest_snprintf_test18 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/test18.cpp b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/test18.cpp new file mode 100644 index 0000000..46ec287 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/test18.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test18.c +** +** Purpose: Tests sprintf_s with compact format doubles (uppercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest("foo %G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %lG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %hG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %LG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %I64G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %5G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %-5G", val, "foo 2560 ", "foo 2560 "); + DoDoubleTest("foo %.1G", val, "foo 3E+003", "foo 3E+03"); + DoDoubleTest("foo %.2G", val, "foo 2.6E+003", "foo 2.6E+03"); + DoDoubleTest("foo %.12G", val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest("foo %06G", val, "foo 002560", "foo 002560"); + DoDoubleTest("foo %#G", val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest("foo %+G", val, "foo +2560", "foo +2560"); + DoDoubleTest("foo % G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %+G", neg, "foo -2560", "foo -2560"); + DoDoubleTest("foo % G", neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/testinfo.dat new file mode 100644 index 0000000..06ae3a6 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test18/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test18 +Description += Tests sprintf_s with compact format doubles (uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/CMakeLists.txt new file mode 100644 index 0000000..be3570f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test19.cpp +) + +add_executable(paltest_snprintf_test19 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test19 coreclrpal) + +target_link_libraries(paltest_snprintf_test19 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/test19.cpp b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/test19.cpp new file mode 100644 index 0000000..91b1dae --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/test19.cpp @@ -0,0 +1,70 @@ +// 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. + +/*============================================================================ +** +** Source: test19.c +** +** Purpose:Tests sprintf_s with argument specified precision +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + int n = -1; + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + DoArgumentPrecTest("%.*s", 2, (void*)"bar", "bar", "ba", "ba"); + DoArgumentPrecTest("%.*S", 2, (void*)convert("bar"), "bar", "ba", "ba"); + + DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); + DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); + DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); + DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42") ; + DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); + + + DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); + DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); + DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); + DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); + DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); + DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); + DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); + DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); + DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); + DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/testinfo.dat new file mode 100644 index 0000000..7064c01 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test19/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test19 +Description += Tests sprintf_s with argument specified precision diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/CMakeLists.txt new file mode 100644 index 0000000..11d18e6 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test2.cpp +) + +add_executable(paltest_snprintf_test2 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test2 coreclrpal) + +target_link_libraries(paltest_snprintf_test2 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/test2.cpp b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/test2.cpp new file mode 100644 index 0000000..e586694 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/test2.cpp @@ -0,0 +1,44 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose:Tests sprintf_s with strings +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + DoStrTest("foo %s", "bar", "foo bar"); + DoStrTest("foo %hs", "bar", "foo bar"); + DoWStrTest("foo %ls", convert("bar"), "foo bar"); + DoWStrTest("foo %ws", convert("bar"), "foo bar"); + DoStrTest("foo %Ls", "bar", "foo bar"); + DoStrTest("foo %I64s", "bar", "foo bar"); + DoStrTest("foo %5s", "bar", "foo bar"); + DoStrTest("foo %.2s", "bar", "foo ba"); + DoStrTest("foo %5.2s", "bar", "foo ba"); + DoStrTest("foo %-5s", "bar", "foo bar "); + DoStrTest("foo %05s", "bar", "foo 00bar"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/testinfo.dat new file mode 100644 index 0000000..cce2dc6 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test2/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test2 +Description += Tests sprintf_s with strings diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/CMakeLists.txt new file mode 100644 index 0000000..b8d4178 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test3.cpp +) + +add_executable(paltest_snprintf_test3 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test3 coreclrpal) + +target_link_libraries(paltest_snprintf_test3 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/test3.cpp b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/test3.cpp new file mode 100644 index 0000000..3c52b44 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/test3.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test3.c +** +** Purpose: Tests sprintf_s with wide strings +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + DoWStrTest("foo %S", convert("bar"), "foo bar"); + DoStrTest("foo %hS", "bar", "foo bar"); + DoWStrTest("foo %lS", convert("bar"), "foo bar"); + DoWStrTest("foo %wS", convert("bar"), "foo bar"); + DoWStrTest("foo %LS", convert("bar"), "foo bar"); + DoWStrTest("foo %I64S", convert("bar"), "foo bar"); + DoWStrTest("foo %5S", convert("bar"), "foo bar"); + DoWStrTest("foo %.2S", convert("bar"), "foo ba"); + DoWStrTest("foo %5.2S", convert("bar"), "foo ba"); + DoWStrTest("foo %-5S", convert("bar"), "foo bar "); + DoWStrTest("foo %05S", convert("bar"), "foo 00bar"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/testinfo.dat new file mode 100644 index 0000000..cc8de0e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test3/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test3 +Description += Tests sprintf_s with wide strings diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/CMakeLists.txt new file mode 100644 index 0000000..568b712 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test4.cpp +) + +add_executable(paltest_snprintf_test4 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test4 coreclrpal) + +target_link_libraries(paltest_snprintf_test4 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/test4.cpp b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/test4.cpp new file mode 100644 index 0000000..216557f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/test4.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test4.c +** +** Purpose: Tests sprintf_s with pointers +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + void *ptr = (void*) 0x123456; + INT64 lptr = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + /* + ** Run only on 64 bit platforms + */ + #if defined(BIT64) && defined(PLATFORM_UNIX) + Trace("Testing for 64 Bit Platforms \n"); + DoPointerTest("%p", NULL, "NULL", "0000000000000000"); + DoPointerTest("%p", ptr, "pointer to 0x123456", "0000000000123456"); + DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); + DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); + DoPointerTest("%-17p", ptr, "pointer to 0x123456", "0000000000123456 "); + DoPointerTest("%+p", ptr, "pointer to 0x123456", "0000000000123456"); + DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X0000000000123456"); + DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); + DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); + DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321", + "1234567887654321"); + #else + Trace("Testing for Non 64 Bit Platforms \n"); + DoPointerTest("%p", NULL, "NULL", "00000000"); + DoPointerTest("%p", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%9p", ptr, "pointer to 0x123456", " 00123456"); + DoPointerTest("%09p", ptr, "pointer to 0x123456", " 00123456"); + DoPointerTest("%-9p", ptr, "pointer to 0x123456", "00123456 "); + DoPointerTest("%+p", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X00123456"); + DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); + DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); + DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321", + "1234567887654321"); + #endif //defined(BIT64) && defined(PLATFORM_UNIX) + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/testinfo.dat new file mode 100644 index 0000000..f53f784 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test4/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test4 +Description += Tests sprintf_s with pointers diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/CMakeLists.txt new file mode 100644 index 0000000..820cc66 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test6.cpp +) + +add_executable(paltest_snprintf_test6 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test6 coreclrpal) + +target_link_libraries(paltest_snprintf_test6 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/test6.cpp b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/test6.cpp new file mode 100644 index 0000000..45c9e2b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/test6.cpp @@ -0,0 +1,47 @@ +// 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. + +/*============================================================================ +** +** Source: test6.c +** +** Purpose: Tests sprintf_s with characters +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wc = (WCHAR) 'c'; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoCharTest("foo %c", 'b', "foo b"); + DoCharTest("foo %hc", 'b', "foo b"); + DoWCharTest("foo %lc", wc, "foo c"); + DoCharTest("foo %Lc", 'b', "foo b"); + DoCharTest("foo %I64c", 'b', "foo b"); + DoCharTest("foo %5c", 'b', "foo b"); + DoCharTest("foo %.0c", 'b', "foo b"); + DoCharTest("foo %-5c", 'b', "foo b "); + DoCharTest("foo %05c", 'b', "foo 0000b"); + DoCharTest("foo % c", 'b', "foo b"); + DoCharTest("foo %#c", 'b', "foo b"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/testinfo.dat new file mode 100644 index 0000000..06e31e8 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test6/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name =Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test6 +Description += Tests sprintf_s with characters diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/CMakeLists.txt new file mode 100644 index 0000000..a2af7c4 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test7.cpp +) + +add_executable(paltest_snprintf_test7 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test7 coreclrpal) + +target_link_libraries(paltest_snprintf_test7 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/test7.cpp b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/test7.cpp new file mode 100644 index 0000000..5c10fc8 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/test7.cpp @@ -0,0 +1,47 @@ +// 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. + +/*============================================================================ +** +** Source: test7.c +** +** Purpose: Tests sprintf_s with wide characters +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wb = (WCHAR) 'b'; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoWCharTest("foo %C", wb, "foo b"); + DoWCharTest("foo %hC", wb, "foo b"); + DoCharTest("foo %lC", 'c', "foo c"); + DoWCharTest("foo %LC", wb, "foo b"); + DoWCharTest("foo %I64C", wb, "foo b"); + DoWCharTest("foo %5C", wb, "foo b"); + DoWCharTest("foo %.0C", wb, "foo b"); + DoWCharTest("foo %-5C", wb, "foo b "); + DoWCharTest("foo %05C", wb, "foo 0000b"); + DoWCharTest("foo % C", wb, "foo b"); + DoWCharTest("foo %#C", wb, "foo b"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/testinfo.dat new file mode 100644 index 0000000..647c9d8 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test7/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test7 +Description += Tests sprintf_s with wide characters diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/CMakeLists.txt new file mode 100644 index 0000000..53545c5 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test8.cpp +) + +add_executable(paltest_snprintf_test8 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test8 coreclrpal) + +target_link_libraries(paltest_snprintf_test8 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/test8.cpp b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/test8.cpp new file mode 100644 index 0000000..416e357 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/test8.cpp @@ -0,0 +1,56 @@ +// 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. + +/*============================================================================ +** +** Source: test8.c +** +** Purpose: Tests sprintf_s with decimal numbers +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %d", pos, "foo 42"); + DoNumTest("foo %ld", 0xFFFF, "foo 65535"); + DoNumTest("foo %hd", 0xFFFF, "foo -1"); + DoNumTest("foo %Ld", pos, "foo 42"); + DoI64Test("foo %I64d", l, "42", "foo 42"); + DoNumTest("foo %3d", pos, "foo 42"); + DoNumTest("foo %-3d", pos, "foo 42 "); + DoNumTest("foo %.1d", pos, "foo 42"); + DoNumTest("foo %.3d", pos, "foo 042"); + DoNumTest("foo %03d", pos, "foo 042"); + DoNumTest("foo %#d", pos, "foo 42"); + DoNumTest("foo %+d", pos, "foo +42"); + DoNumTest("foo % d", pos, "foo 42"); + DoNumTest("foo %+d", neg, "foo -42"); + DoNumTest("foo % d", neg, "foo -42"); + + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/testinfo.dat new file mode 100644 index 0000000..524834e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test8/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test8 +Description += Tests sprintf_s with decimal numbers diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/CMakeLists.txt new file mode 100644 index 0000000..33ca9db --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test9.cpp +) + +add_executable(paltest_snprintf_test9 + ${SOURCES} +) + +add_dependencies(paltest_snprintf_test9 coreclrpal) + +target_link_libraries(paltest_snprintf_test9 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/test9.cpp b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/test9.cpp new file mode 100644 index 0000000..18b1cb7 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/test9.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test9.c +** +** Purpose: Tests sprintf_s with integer numbers +** +** +**==========================================================================*/ + + + +#include +#include "../_snprintf_s.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %i", pos, "foo 42"); + DoNumTest("foo %li", 0xFFFF, "foo 65535"); + DoNumTest("foo %hi", 0xFFFF, "foo -1"); + DoNumTest("foo %Li", pos, "foo 42"); + DoI64Test("foo %I64i", l, "42", "foo 42"); + DoNumTest("foo %3i", pos, "foo 42"); + DoNumTest("foo %-3i", pos, "foo 42 "); + DoNumTest("foo %.1i", pos, "foo 42"); + DoNumTest("foo %.3i", pos, "foo 042"); + DoNumTest("foo %03i", pos, "foo 042"); + DoNumTest("foo %#i", pos, "foo 42"); + DoNumTest("foo %+i", pos, "foo +42"); + DoNumTest("foo % i", pos, "foo 42"); + DoNumTest("foo %+i", neg, "foo -42"); + DoNumTest("foo % i", neg, "foo -42"); + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/testinfo.dat new file mode 100644 index 0000000..7c51443 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snprintf_s/test9/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test9 +Description += Tests sprintf_s with integer numbers diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/CMakeLists.txt deleted file mode 100644 index cafb953..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -add_subdirectory(test1) -add_subdirectory(test10) -add_subdirectory(test11) -add_subdirectory(test12) -add_subdirectory(test13) -add_subdirectory(test14) -add_subdirectory(test15) -add_subdirectory(test16) -add_subdirectory(test17) -add_subdirectory(test18) -add_subdirectory(test19) -add_subdirectory(test2) -add_subdirectory(test3) -add_subdirectory(test4) -add_subdirectory(test5) -add_subdirectory(test6) -add_subdirectory(test7) -add_subdirectory(test8) -add_subdirectory(test9) - diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/_snwprintf.h b/src/pal/tests/palsuite/c_runtime/_snwprintf/_snwprintf.h deleted file mode 100644 index 73bf4d6..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/_snwprintf.h +++ /dev/null @@ -1,199 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: _snwprintf.h -** -** Purpose: Containts common testing functions for _snwprintf -** -** -**==========================================================================*/ - -#ifndef ___SNWPRINTF_H__ -#define ___SNWPRINTF_H__ - -void DoWStrTest(WCHAR *formatstr, WCHAR *param, WCHAR *checkstr) -{ - WCHAR buf[256] = { 0 }; - - _snwprintf(buf, 256, formatstr, param); - - if (memcmp(buf, checkstr, wcslen(checkstr) * 2 + 2) != 0) - { - Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n" - "Expected \"%s\", got \"%s\".\n", convertC(param), - convertC(formatstr), convertC(checkstr), convertC(buf)); - } -} - -void DoStrTest(WCHAR *formatstr, char *param, WCHAR *checkstr) -{ - WCHAR buf[256] = { 0 }; - - _snwprintf(buf, 256, formatstr, param); - - if (memcmp(buf, checkstr, wcslen(checkstr) * 2 + 2) != 0) - { - Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n" - "Expected \"%s\", got \"%s\".\n", - param, convertC(formatstr), convertC(checkstr), convertC(buf)); - } -} - -void DoPointerTest(WCHAR *formatstr, void* param, WCHAR *checkstr1) -{ - WCHAR buf[256] = { 0 }; - - _snwprintf(buf, 256, formatstr, param); - if (memcmp(buf, checkstr1, wcslen(checkstr1)*2 + 2) != 0) - { - Fail("ERROR: failed to insert pointer to %#p into \"%s\"\n" - "Expected \"%s\", got \"%s\".\n", param, convertC(formatstr), - convertC(checkstr1), convertC(buf)); - } -} - -void DoCountTest(WCHAR *formatstr, int param, WCHAR *checkstr) -{ - WCHAR buf[512] = { 0 }; - int n = -1; - - _snwprintf(buf, 512, formatstr, &n); - - if (n != param) - { - Fail("ERROR: Expected count parameter to resolve to %d, got %d\n", - param, n); - } - - if (memcmp(buf, checkstr, wcslen(checkstr)*2 + 2) != 0) - { - Fail("ERROR: Expected \"%s\" got \"%s\".\n", - convertC(checkstr), convertC(buf)); - } -} - -void DoShortCountTest(WCHAR *formatstr, int param, WCHAR *checkstr) -{ - WCHAR buf[256] = { 0 }; - short int n = -1; - - _snwprintf(buf, 256, formatstr, &n); - - if (n != param) - { - Fail("ERROR: Expected count parameter to resolve to %d, got %d\n", - param, n); - } - - if (memcmp(buf, checkstr, wcslen(checkstr)*2 + 2) != 0) - { - Fail("ERROR: Expected \"%s\" got \"%s\".\n", - convertC(checkstr), convertC(buf)); - } -} - -void DoCharTest(WCHAR *formatstr, char param, WCHAR *checkstr) -{ - WCHAR buf[256] = { 0 }; - - _snwprintf(buf, 256, formatstr, param); - if (memcmp(buf, checkstr, wcslen(checkstr)*2 + 2) != 0) - { - Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n" - "Expected \"%s\" got \"%s\".\n", param, param, - convertC(formatstr), convertC(checkstr), convertC(buf)); - } -} - -void DoWCharTest(WCHAR *formatstr, WCHAR param, WCHAR *checkstr) -{ - WCHAR buf[256] = { 0 }; - - _snwprintf(buf, 256, formatstr, param); - if (memcmp(buf, checkstr, wcslen(checkstr)*2 + 2) != 0) - { - Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n" - "Expected \"%s\" got \"%s\".\n", (char) param, param, - convertC(formatstr), convertC(checkstr), convertC(buf)); - } -} - -void DoNumTest(WCHAR *formatstr, int value, WCHAR*checkstr) -{ - WCHAR buf[256] = { 0 }; - - _snwprintf(buf, 256, formatstr, value); - if (memcmp(buf, checkstr, wcslen(checkstr)* 2 + 2) != 0) - { - Fail("ERROR: failed to insert %#x into \"%s\"\n" - "Expected \"%s\" got \"%s\".\n", value, convertC(formatstr), - convertC(checkstr), convertC(buf)); - } -} - - -void DoI64Test(WCHAR *formatstr, INT64 param, char *paramdesc, - WCHAR *checkstr1) -{ - WCHAR buf[256] = { 0 }; - - _snwprintf(buf, 256, formatstr, param); - if (memcmp(buf, checkstr1, wcslen(checkstr1)*2 + 2) != 0) - { - Fail("ERROR: failed to insert %s into \"%s\"\n" - "Expected \"%s\", got \"%s\".\n", paramdesc, - convertC(formatstr), convertC(checkstr1), convertC(buf)); - } -} - -void DoDoubleTest(WCHAR *formatstr, double value, WCHAR *checkstr1, - WCHAR *checkstr2) -{ - WCHAR buf[256] = { 0 }; - - _snwprintf(buf, 256, formatstr, value); - if (memcmp(buf, checkstr1, wcslen(checkstr1)*2 + 2) != 0 && - memcmp(buf, checkstr2, wcslen(checkstr2)*2 + 2) != 0) - { - Fail("ERROR: failed to insert %f into \"%s\"\n" - "Expected \"%s\" or \"%s\", got \"%s\".\n", - value, convertC(formatstr), convertC(checkstr1), - convertC(checkstr2), convertC(buf)); - } -} - -void DoArgumentPrecTest(WCHAR *formatstr, int precision, void *param, - char *paramstr, WCHAR *checkstr1, WCHAR *checkstr2) -{ - WCHAR buf[256]; - - _snwprintf(buf, 256, formatstr, precision, param); - if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 && - memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0) - { - Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" - "Expected \"%s\" or \"%s\", got \"%s\".\n", - paramstr, convertC(formatstr), precision, - convertC(checkstr1), convertC(checkstr2) ,convertC(buf)); - } -} - -void DoArgumentPrecDoubleTest(WCHAR *formatstr, int precision, double param, - WCHAR *checkstr) -{ - WCHAR buf[256]; - - _snwprintf(buf, 256, formatstr, precision, param); - if (memcmp(buf, checkstr, wcslen(checkstr) + 2) != 0) - { - Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" - "Expected \"%s\", got \"%s\".\n", param, convertC(formatstr), - precision, convertC(checkstr), convertC(buf)); - } -} - -#endif - diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test1/CMakeLists.txt deleted file mode 100644 index b4ab6d5..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test1/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test1.c -) - -add_executable(paltest_snwprintf_test1 - ${SOURCES} -) - -add_dependencies(paltest_snwprintf_test1 coreclrpal) - -target_link_libraries(paltest_snwprintf_test1 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test1/test1.c deleted file mode 100644 index 5d13aaf..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test1/test1.c +++ /dev/null @@ -1,62 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: General test to see if _snwprintf works correctly -** -** -**==========================================================================*/ - - - -#include -#include "../_snwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - - -int __cdecl main(int argc, char *argv[]) -{ - WCHAR *checkstr; - WCHAR buf[256] = { 0 }; - int ret; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - checkstr = convert("hello world"); - _snwprintf(buf, 256, checkstr); - if (memcmp(checkstr, buf, wcslen(checkstr)*2+2) != 0) - { - Fail("ERROR: Expected \"%s\", got \"%s\"\n", - convertC(checkstr), convertC(buf)); - } - - _snwprintf(buf, 256, convert("xxxxxxxxxxxxxxxxx")); - ret = _snwprintf(buf, 8, checkstr); - if (memcmp(checkstr, buf, 16) != 0) - { - Fail("ERROR: Expected \"%8s\", got \"%8s\"\n", - convertC(checkstr), convertC(buf)); - } - if (ret >= 0) - { - Fail("ERROR: Expected negative return value, got %d.\n", ret); - } - if (buf[8] != (WCHAR) 'x') - { - Fail("ERROR: buffer overflow using \"%s\" with length 8.\n", - convertC(checkstr)); - } - - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test1/testinfo.dat deleted file mode 100644 index 079a3b3..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test1/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snwprintf -Name = Positive Test for _snwprintf -TYPE = DEFAULT -EXE1 = test1 -Description -= General test to see if _snwprintf works correctly diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test10/CMakeLists.txt deleted file mode 100644 index 27aaca3..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test10/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test10.c -) - -add_executable(paltest_snwprintf_test10 - ${SOURCES} -) - -add_dependencies(paltest_snwprintf_test10 coreclrpal) - -target_link_libraries(paltest_snwprintf_test10 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test10/test10.c deleted file mode 100644 index e8a6d93..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test10/test10.c +++ /dev/null @@ -1,54 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test10.c -** -** Purpose: Tests _snwprintf with octal numbers -** -** -**==========================================================================*/ - - - -#include -#include "../_snwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 42; - INT64 l = 42; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoNumTest(convert("foo %o"), pos, convert("foo 52")); - DoNumTest(convert("foo %lo"), 0xFFFF, convert("foo 177777")); - DoNumTest(convert("foo %ho"), 0xFFFF, convert("foo 177777")); - DoNumTest(convert("foo %Lo"), pos, convert("foo 52")); - DoI64Test(convert("foo %I64o"), l, "42", convert("foo 52")); - DoNumTest(convert("foo %3o"), pos, convert("foo 52")); - DoNumTest(convert("foo %-3o"), pos, convert("foo 52 ")); - DoNumTest(convert("foo %.1o"), pos, convert("foo 52")); - DoNumTest(convert("foo %.3o"), pos, convert("foo 052")); - DoNumTest(convert("foo %03o"), pos, convert("foo 052")); - DoNumTest(convert("foo %#o"), pos, convert("foo 052")); - DoNumTest(convert("foo %+o"), pos, convert("foo 52")); - DoNumTest(convert("foo % o"), pos, convert("foo 52")); - DoNumTest(convert("foo %+o"), neg, convert("foo 37777777726")); - DoNumTest(convert("foo % o"), neg, convert("foo 37777777726")); - - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test10/testinfo.dat deleted file mode 100644 index 2c07cc6..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test10/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snwprintf -Name = Positive Test for _snwprintf -TYPE = DEFAULT -EXE1 = test10 -Description -= Tests _snwprintf with octal numbers diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test11/CMakeLists.txt deleted file mode 100644 index e18ad4a..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test11/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test11.c -) - -add_executable(paltest_snwprintf_test11 - ${SOURCES} -) - -add_dependencies(paltest_snwprintf_test11 coreclrpal) - -target_link_libraries(paltest_snwprintf_test11 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test11/test11.c deleted file mode 100644 index 95f7f53..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test11/test11.c +++ /dev/null @@ -1,54 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test11.c -** -** Purpose: Tests _snwprintf with unsigned numbers -** -** -**==========================================================================*/ - - - -#include -#include "../_snwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 42; - INT64 l = 42; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoNumTest(convert("foo %u"), pos, convert("foo 42")); - DoNumTest(convert("foo %lu"), 0xFFFF, convert("foo 65535")); - DoNumTest(convert("foo %hu"), 0xFFFF, convert("foo 65535")); - DoNumTest(convert("foo %Lu"), pos, convert("foo 42")); - DoI64Test(convert("foo %I64u"), l, "42", convert("foo 42")); - DoNumTest(convert("foo %3u"), pos, convert("foo 42")); - DoNumTest(convert("foo %-3u"), pos, convert("foo 42 ")); - DoNumTest(convert("foo %.1u"), pos, convert("foo 42")); - DoNumTest(convert("foo %.3u"), pos, convert("foo 042")); - DoNumTest(convert("foo %03u"), pos, convert("foo 042")); - DoNumTest(convert("foo %#u"), pos, convert("foo 42")); - DoNumTest(convert("foo %+u"), pos, convert("foo 42")); - DoNumTest(convert("foo % u"), pos, convert("foo 42")); - DoNumTest(convert("foo %+u"), neg, convert("foo 4294967254")); - DoNumTest(convert("foo % u"), neg, convert("foo 4294967254")); - - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test11/testinfo.dat deleted file mode 100644 index f81a786..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test11/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snwprintf -Name = Positive Test for _snwprintf -TYPE = DEFAULT -EXE1 = test11 -Description -= Tests _snwprintf with unsigned numbers diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test12/CMakeLists.txt deleted file mode 100644 index f2ae07c..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test12/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test12.c -) - -add_executable(paltest_snwprintf_test12 - ${SOURCES} -) - -add_dependencies(paltest_snwprintf_test12 coreclrpal) - -target_link_libraries(paltest_snwprintf_test12 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test12/test12.c deleted file mode 100644 index ab58fa3..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test12/test12.c +++ /dev/null @@ -1,54 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test12.c -** -** Purpose: Tests _snwprintf with hex numbers (lowercase) -** -** -**==========================================================================*/ - - - -#include -#include "../_snwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 0x1234ab; - INT64 l = I64(0x1234567887654321); - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoNumTest(convert("foo %x"), pos, convert("foo 1234ab")); - DoNumTest(convert("foo %lx"), pos, convert("foo 1234ab")); - DoNumTest(convert("foo %hx"), pos, convert("foo 34ab")); - DoNumTest(convert("foo %Lx"), pos, convert("foo 1234ab")); - DoI64Test(convert("foo %I64x"), l, "0x1234567887654321", - convert("foo 1234567887654321")); - DoNumTest(convert("foo %7x"), pos, convert("foo 1234ab")); - DoNumTest(convert("foo %-7x"), pos, convert("foo 1234ab ")); - DoNumTest(convert("foo %.1x"), pos, convert("foo 1234ab")); - DoNumTest(convert("foo %.7x"), pos, convert("foo 01234ab")); - DoNumTest(convert("foo %07x"), pos, convert("foo 01234ab")); - DoNumTest(convert("foo %#x"), pos, convert("foo 0x1234ab")); - DoNumTest(convert("foo %+x"), pos, convert("foo 1234ab")); - DoNumTest(convert("foo % x"), pos, convert("foo 1234ab")); - DoNumTest(convert("foo %+x"), neg, convert("foo ffffffd6")); - DoNumTest(convert("foo % x"), neg, convert("foo ffffffd6")); - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test12/testinfo.dat deleted file mode 100644 index 653baba..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test12/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snwprintf -Name = Positive Test for _snwprintf -TYPE = DEFAULT -EXE1 = test12 -Description -= Tests _snwprintf with hex numbers (lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test13/CMakeLists.txt deleted file mode 100644 index 42847b6..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test13/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test13.c -) - -add_executable(paltest_snwprintf_test13 - ${SOURCES} -) - -add_dependencies(paltest_snwprintf_test13 coreclrpal) - -target_link_libraries(paltest_snwprintf_test13 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test13/test13.c deleted file mode 100644 index 5a3e228..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test13/test13.c +++ /dev/null @@ -1,54 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test13.c -** -** Purpose: Tests _snwprintf with hex numbers (uppercase) -** -** -**==========================================================================*/ - - - -#include -#include "../_snwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 0x1234ab; - INT64 l = I64(0x1234567887654321); - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoNumTest(convert("foo %X"), pos, convert("foo 1234AB")); - DoNumTest(convert("foo %lX"), pos, convert("foo 1234AB")); - DoNumTest(convert("foo %hX"), pos, convert("foo 34AB")); - DoNumTest(convert("foo %LX"), pos, convert("foo 1234AB")); - DoI64Test(convert("foo %I64X"), l, "0x1234567887654321", - convert("foo 1234567887654321")); - DoNumTest(convert("foo %7X"), pos, convert("foo 1234AB")); - DoNumTest(convert("foo %-7X"), pos, convert("foo 1234AB ")); - DoNumTest(convert("foo %.1X"), pos, convert("foo 1234AB")); - DoNumTest(convert("foo %.7X"), pos, convert("foo 01234AB")); - DoNumTest(convert("foo %07X"), pos, convert("foo 01234AB")); - DoNumTest(convert("foo %#X"), pos, convert("foo 0X1234AB")); - DoNumTest(convert("foo %+X"), pos, convert("foo 1234AB")); - DoNumTest(convert("foo % X"), pos, convert("foo 1234AB")); - DoNumTest(convert("foo %+X"), neg, convert("foo FFFFFFD6")); - DoNumTest(convert("foo % X"), neg, convert("foo FFFFFFD6")); - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test13/testinfo.dat deleted file mode 100644 index cdeced6..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test13/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snwprintf -Name = Positive Test for _snwprintf -TYPE = DEFAULT -EXE1 = test13 -Description -= Tests _snwprintf with hex numbers (uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test14/CMakeLists.txt deleted file mode 100644 index e5cdbfa..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test14/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test14.c -) - -add_executable(paltest_snwprintf_test14 - ${SOURCES} -) - -add_dependencies(paltest_snwprintf_test14 coreclrpal) - -target_link_libraries(paltest_snwprintf_test14 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test14/test14.c deleted file mode 100644 index c348752..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test14/test14.c +++ /dev/null @@ -1,66 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test14.c -** -** Purpose: Tests _snwprintf with exponential format doubles (lowercase) -** -** -**==========================================================================*/ - - - -#include -#include "../_snwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - double val = 256.0; - double neg = -256.0; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoDoubleTest(convert("foo %e"), val, convert("foo 2.560000e+002"), - convert("foo 2.560000e+02")); - DoDoubleTest(convert("foo %le"), val, convert("foo 2.560000e+002"), - convert("foo 2.560000e+02")); - DoDoubleTest(convert("foo %he"), val, convert("foo 2.560000e+002"), - convert("foo 2.560000e+02")); - DoDoubleTest(convert("foo %Le"), val, convert("foo 2.560000e+002"), - convert("foo 2.560000e+02")); - DoDoubleTest(convert("foo %I64e"), val, convert("foo 2.560000e+002"), - convert("foo 2.560000e+02")); - DoDoubleTest(convert("foo %14e"), val, convert("foo 2.560000e+002"), - convert("foo 2.560000e+02")); - DoDoubleTest(convert("foo %-14e"), val, convert("foo 2.560000e+002 "), - convert("foo 2.560000e+02 ")); - DoDoubleTest(convert("foo %.1e"), val, convert("foo 2.6e+002"), - convert("foo 2.6e+02")); - DoDoubleTest(convert("foo %.8e"), val, convert("foo 2.56000000e+002"), - convert("foo 2.56000000e+02")); - DoDoubleTest(convert("foo %014e"), val, convert("foo 02.560000e+002"), - convert("foo 002.560000e+02")); - DoDoubleTest(convert("foo %#e"), val, convert("foo 2.560000e+002"), - convert("foo 2.560000e+02")); - DoDoubleTest(convert("foo %+e"), val, convert("foo +2.560000e+002"), - convert("foo +2.560000e+02")); - DoDoubleTest(convert("foo % e"), val, convert("foo 2.560000e+002"), - convert("foo 2.560000e+02")); - DoDoubleTest(convert("foo %+e"), neg, convert("foo -2.560000e+002"), - convert("foo -2.560000e+02")); - DoDoubleTest(convert("foo % e"), neg, convert("foo -2.560000e+002"), - convert("foo -2.560000e+02")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test14/testinfo.dat deleted file mode 100644 index b47611a..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test14/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snwprintf -Name = Positive Test for _snwprintf -TYPE = DEFAULT -EXE1 = test14 -Description -= Tests _snwprintf with exponential format doubles (lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test15/CMakeLists.txt deleted file mode 100644 index dc7b4d6..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test15/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test15.c -) - -add_executable(paltest_snwprintf_test15 - ${SOURCES} -) - -add_dependencies(paltest_snwprintf_test15 coreclrpal) - -target_link_libraries(paltest_snwprintf_test15 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test15/test15.c deleted file mode 100644 index f45005b..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test15/test15.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test15.c -** -** Purpose: Tests _snwprintf with exponential format doubles (uppercase) -** -** -**==========================================================================*/ - - - -#include -#include "../_snwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - - -int __cdecl main(int argc, char *argv[]) -{ - double val = 256.0; - double neg = -256.0; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoDoubleTest(convert("foo %E"), val, convert("foo 2.560000E+002"), - convert("foo 2.560000E+02")); - DoDoubleTest(convert("foo %lE"), val, convert("foo 2.560000E+002"), - convert("foo 2.560000E+02")); - DoDoubleTest(convert("foo %hE"), val, convert("foo 2.560000E+002"), - convert("foo 2.560000E+02")); - DoDoubleTest(convert("foo %LE"), val, convert("foo 2.560000E+002"), - convert("foo 2.560000E+02")); - DoDoubleTest(convert("foo %I64E"), val, convert("foo 2.560000E+002"), - convert("foo 2.560000E+02")); - DoDoubleTest(convert("foo %14E"), val, convert("foo 2.560000E+002"), - convert("foo 2.560000E+02")); - DoDoubleTest(convert("foo %-14E"), val, convert("foo 2.560000E+002 "), - convert("foo 2.560000E+02 ")); - DoDoubleTest(convert("foo %.1E"), val, convert("foo 2.6E+002"), - convert("foo 2.6E+02")); - DoDoubleTest(convert("foo %.8E"), val, convert("foo 2.56000000E+002"), - convert("foo 2.56000000E+02")); - DoDoubleTest(convert("foo %014E"), val, convert("foo 02.560000E+002"), - convert("foo 002.560000E+02")); - DoDoubleTest(convert("foo %#E"), val, convert("foo 2.560000E+002"), - convert("foo 2.560000E+02")); - DoDoubleTest(convert("foo %+E"), val, convert("foo +2.560000E+002"), - convert("foo +2.560000E+02")); - DoDoubleTest(convert("foo % E"), val, convert("foo 2.560000E+002"), - convert("foo 2.560000E+02")); - DoDoubleTest(convert("foo %+E"), neg, convert("foo -2.560000E+002"), - convert("foo -2.560000E+02")); - DoDoubleTest(convert("foo % E"), neg, convert("foo -2.560000E+002"), - convert("foo -2.560000E+02")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test15/testinfo.dat deleted file mode 100644 index 2c81391..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test15/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snwprintf -Name = Positive Test for _snwprintf -TYPE = DEFAULT -EXE1 = test15 -Description -= Tests _snwprintf with exponential format doubles (uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test16/CMakeLists.txt deleted file mode 100644 index f147ad7..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test16/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test16.c -) - -add_executable(paltest_snwprintf_test16 - ${SOURCES} -) - -add_dependencies(paltest_snwprintf_test16 coreclrpal) - -target_link_libraries(paltest_snwprintf_test16 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test16/test16.c deleted file mode 100644 index 88f55bd..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test16/test16.c +++ /dev/null @@ -1,65 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test16.c -** -** Purpose: Tests _snwprintf with decimal point format doubles -** -** -**==========================================================================*/ - - -#include -#include "../_snwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - double val = 2560.001; - double neg = -2560.001; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoDoubleTest(convert("foo %f"), val, convert("foo 2560.001000"), - convert("foo 2560.001000")); - DoDoubleTest(convert("foo %lf"), val, convert("foo 2560.001000"), - convert("foo 2560.001000")); - DoDoubleTest(convert("foo %hf"), val, convert("foo 2560.001000"), - convert("foo 2560.001000")); - DoDoubleTest(convert("foo %Lf"), val, convert("foo 2560.001000"), - convert("foo 2560.001000")); - DoDoubleTest(convert("foo %I64f"), val, convert("foo 2560.001000"), - convert("foo 2560.001000")); - DoDoubleTest(convert("foo %12f"), val, convert("foo 2560.001000"), - convert("foo 2560.001000")); - DoDoubleTest(convert("foo %-12f"), val, convert("foo 2560.001000 "), - convert("foo 2560.001000 ")); - DoDoubleTest(convert("foo %.1f"), val, convert("foo 2560.0"), - convert("foo 2560.0")); - DoDoubleTest(convert("foo %.8f"), val, convert("foo 2560.00100000"), - convert("foo 2560.00100000")); - DoDoubleTest(convert("foo %012f"), val, convert("foo 02560.001000"), - convert("foo 02560.001000")); - DoDoubleTest(convert("foo %#f"), val, convert("foo 2560.001000"), - convert("foo 2560.001000")); - DoDoubleTest(convert("foo %+f"), val, convert("foo +2560.001000"), - convert("foo +2560.001000")); - DoDoubleTest(convert("foo % f"), val, convert("foo 2560.001000"), - convert("foo 2560.001000")); - DoDoubleTest(convert("foo %+f"), neg, convert("foo -2560.001000"), - convert("foo -2560.001000")); - DoDoubleTest(convert("foo % f"), neg, convert("foo -2560.001000"), - convert("foo -2560.001000")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test16/testinfo.dat deleted file mode 100644 index 8d844e0..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test16/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snwprintf -Name = Positive Test for _snwprintf -TYPE = DEFAULT -EXE1 = test16 -Description -= Tests _snwprintf with decimal point format doubles diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test17/CMakeLists.txt deleted file mode 100644 index e40d3f4..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test17/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test17.c -) - -add_executable(paltest_snwprintf_test17 - ${SOURCES} -) - -add_dependencies(paltest_snwprintf_test17 coreclrpal) - -target_link_libraries(paltest_snwprintf_test17 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test17/test17.c deleted file mode 100644 index 82f2330..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test17/test17.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test17.c -** -** Purpose: Tests _snwprintf with compact format doubles (lowercase) -** -** -**==========================================================================*/ - - - -#include -#include "../_snwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - double val = 2560.001; - double neg = -2560.001; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoDoubleTest(convert("foo %g"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %lg"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %hg"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %Lg"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %I64g"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %5g"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %-5g"), val, convert("foo 2560 "), - convert("foo 2560 ")); - DoDoubleTest(convert("foo %.1g"), val, convert("foo 3e+003"), - convert("foo 3e+03")); - DoDoubleTest(convert("foo %.2g"), val, convert("foo 2.6e+003"), - convert("foo 2.6e+03")); - DoDoubleTest(convert("foo %.12g"), val, convert("foo 2560.001"), - convert("foo 2560.001")); - DoDoubleTest(convert("foo %06g"), val, convert("foo 002560"), - convert("foo 002560")); - DoDoubleTest(convert("foo %#g"), val, convert("foo 2560.00"), - convert("foo 2560.00")); - DoDoubleTest(convert("foo %+g"), val, convert("foo +2560"), - convert("foo +2560")); - DoDoubleTest(convert("foo % g"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %+g"), neg, convert("foo -2560"), - convert("foo -2560")); - DoDoubleTest(convert("foo % g"), neg, convert("foo -2560"), - convert("foo -2560")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test17/testinfo.dat deleted file mode 100644 index 6b01fb3..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test17/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snwprintf -Name = Positive Test for _snwprintf -TYPE = DEFAULT -EXE1 = test17 -Description -= Tests _snwprintf with compact format doubles (lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test18/CMakeLists.txt deleted file mode 100644 index 68a014c..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test18/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test18.c -) - -add_executable(paltest_snwprintf_test18 - ${SOURCES} -) - -add_dependencies(paltest_snwprintf_test18 coreclrpal) - -target_link_libraries(paltest_snwprintf_test18 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test18/test18.c deleted file mode 100644 index dbb6233..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test18/test18.c +++ /dev/null @@ -1,69 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test18.c -** -** Purpose: Tests _snwprintf with compact format doubles (uppercase) -** -** -**==========================================================================*/ - - - - -#include -#include "../_snwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - double val = 2560.001; - double neg = -2560.001; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoDoubleTest(convert("foo %G"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %lG"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %hG"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %LG"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %I64G"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %5G"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %-5G"), val, convert("foo 2560 "), - convert("foo 2560 ")); - DoDoubleTest(convert("foo %.1G"), val, convert("foo 3E+003"), - convert("foo 3E+03")); - DoDoubleTest(convert("foo %.2G"), val, convert("foo 2.6E+003"), - convert("foo 2.6E+03")); - DoDoubleTest(convert("foo %.12G"), val, convert("foo 2560.001"), - convert("foo 2560.001")); - DoDoubleTest(convert("foo %06G"), val, convert("foo 002560"), - convert("foo 002560")); - DoDoubleTest(convert("foo %#G"), val, convert("foo 2560.00"), - convert("foo 2560.00")); - DoDoubleTest(convert("foo %+G"), val, convert("foo +2560"), - convert("foo +2560")); - DoDoubleTest(convert("foo % G"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %+G"), neg, convert("foo -2560"), - convert("foo -2560")); - DoDoubleTest(convert("foo % G"), neg, convert("foo -2560"), - convert("foo -2560")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test18/testinfo.dat deleted file mode 100644 index 480087f..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test18/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snwprintf -Name = Positive Test for _snwprintf -TYPE = DEFAULT -EXE1 = test18 -Description -= Tests _snwprintf with compact format doubles (uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test19/CMakeLists.txt deleted file mode 100644 index 6dc30b4..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test19/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test19.c -) - -add_executable(paltest_snwprintf_test19 - ${SOURCES} -) - -add_dependencies(paltest_snwprintf_test19 coreclrpal) - -target_link_libraries(paltest_snwprintf_test19 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test19/test19.c deleted file mode 100644 index efb222c..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test19/test19.c +++ /dev/null @@ -1,90 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test19.c -** -** Purpose: Tests _snwprintf with argument specified precision -** -** -**==========================================================================*/ - - - -#include -#include "../_snwprintf.h" - -int __cdecl main(int argc, char *argv[]) -{ - int n = -1; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - DoArgumentPrecTest(convert("%.*s"), 2, convert("bar"), "bar", - convert("ba"), convert("ba")); - DoArgumentPrecTest(convert("%.*S"), 2, "bar", "bar", - convert("ba"), convert("ba")); - DoArgumentPrecTest(convert("%.*n"), 3, &n, "pointer to int", - convert(""), convert("")); - if (n != 0) - { - Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", - 0, n); - } - - DoArgumentPrecTest(convert("%.*c"), 0, (void*)'a', "a", - convert("a"), convert("a")); - DoArgumentPrecTest(convert("%.*c"), 4, (void*)'a', "a", - convert("a"), convert("a")); - DoArgumentPrecTest(convert("%.*C"), 0, (void*)'a', "a", - convert("a"), convert("a")); - DoArgumentPrecTest(convert("%.*C"), 4, (void*)'a', "a", - convert("a"), convert("a")); - DoArgumentPrecTest(convert("%.*d"), 1, (void*)42, "42", - convert("42"), convert("42")); - DoArgumentPrecTest(convert("%.*d"), 3, (void*)42, "42", - convert("042"), convert("042")); - DoArgumentPrecTest(convert("%.*i"), 1, (void*)42, "42", - convert("42"), convert("42")); - DoArgumentPrecTest(convert("%.*i"), 3, (void*)42, "42", - convert("042"), convert("042")); - DoArgumentPrecTest(convert("%.*o"), 1, (void*)42, "42", - convert("52"), convert("52")); - DoArgumentPrecTest(convert("%.*o"), 3, (void*)42, "42", - convert("052"), convert("052")); - DoArgumentPrecTest(convert("%.*u"), 1, (void*)42, "42", - convert("42"), convert("42")); - DoArgumentPrecTest(convert("%.*u"), 3, (void*)42, "42", - convert("042"), convert("042")); - DoArgumentPrecTest(convert("%.*x"), 1, (void*)0x42, "0x42", - convert("42"), convert("42")); - DoArgumentPrecTest(convert("%.*x"), 3, (void*)0x42, "0x42", - convert("042"), convert("042")); - DoArgumentPrecTest(convert("%.*X"), 1, (void*)0x42, "0x42", - convert("42"), convert("42")); - DoArgumentPrecTest(convert("%.*X"), 3, (void*)0x42, "0x42", - convert("042"), convert("042")); - DoArgumentPrecDoubleTest(convert("%.*e"), 1, 2.01, convert("2.0e+000")); - DoArgumentPrecDoubleTest(convert("%.*e"), 3, 2.01, convert("2.010e+000")); - DoArgumentPrecDoubleTest(convert("%.*E"), 1, 2.01, convert("2.0E+000")); - DoArgumentPrecDoubleTest(convert("%.*E"), 3, 2.01, convert("2.010E+000")); - DoArgumentPrecDoubleTest(convert("%.*f"), 1, 2.01, convert("2.0")); - DoArgumentPrecDoubleTest(convert("%.*f"), 3, 2.01, convert("2.010")); - DoArgumentPrecDoubleTest(convert("%.*g"), 1, 256.01, convert("3e+002")); - DoArgumentPrecDoubleTest(convert("%.*g"), 3, 256.01, convert("256")); - DoArgumentPrecDoubleTest(convert("%.*g"), 4, 256.01, convert("256")); - DoArgumentPrecDoubleTest(convert("%.*g"), 6, 256.01, convert("256.01")); - DoArgumentPrecDoubleTest(convert("%.*G"), 1, 256.01, convert("3E+002")); - DoArgumentPrecDoubleTest(convert("%.*G"), 3, 256.01, convert("256")); - DoArgumentPrecDoubleTest(convert("%.*G"), 4, 256.01, convert("256")); - DoArgumentPrecDoubleTest(convert("%.*G"), 6, 256.01, convert("256.01")); - - PAL_Terminate(); - return PASS; - -} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test19/testinfo.dat deleted file mode 100644 index 376cbc8..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test19/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snwprintf -Name = Positive Test for _snwprintf -TYPE = DEFAULT -EXE1 = test19 -Description -= Tests _snwprintf with argument specified precision diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test2/CMakeLists.txt deleted file mode 100644 index 9e0d950..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test2/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test2.c -) - -add_executable(paltest_snwprintf_test2 - ${SOURCES} -) - -add_dependencies(paltest_snwprintf_test2 coreclrpal) - -target_link_libraries(paltest_snwprintf_test2 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test2/test2.c deleted file mode 100644 index 974b796..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test2/test2.c +++ /dev/null @@ -1,44 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test2.c -** -** Purpose:Tests _snwprintf with strings -** -** -**==========================================================================*/ - - - -#include -#include "../_snwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - - -int __cdecl main(int argc, char *argv[]) -{ - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - DoWStrTest(convert("foo %s"), convert("bar"), convert("foo bar")); - DoStrTest(convert("foo %hs"), "bar", convert("foo bar")); - DoWStrTest(convert("foo %ls"), convert("bar"), convert("foo bar")); - DoWStrTest(convert("foo %ws"), convert("bar"), convert("foo bar")); - DoWStrTest(convert("foo %Ls"), convert("bar"), convert("foo bar")); - DoWStrTest(convert("foo %I64s"), convert("bar"), convert("foo bar")); - DoWStrTest(convert("foo %5s"), convert("bar"), convert("foo bar")); - DoWStrTest(convert("foo %.2s"), convert("bar"), convert("foo ba")); - DoWStrTest(convert("foo %5.2s"), convert("bar"), convert("foo ba")); - DoWStrTest(convert("foo %-5s"), convert("bar"), convert("foo bar ")); - DoWStrTest(convert("foo %05s"), convert("bar"), convert("foo 00bar")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test2/testinfo.dat deleted file mode 100644 index 9c65c93..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test2/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snwprintf -Name = Positive Test for _snwprintf -TYPE = DEFAULT -EXE1 = test2 -Description -= Tests _snwprintf with strings diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test3/CMakeLists.txt deleted file mode 100644 index 4d5a28b..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test3/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test3.c -) - -add_executable(paltest_snwprintf_test3 - ${SOURCES} -) - -add_dependencies(paltest_snwprintf_test3 coreclrpal) - -target_link_libraries(paltest_snwprintf_test3 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test3/test3.c deleted file mode 100644 index bfb75ce..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test3/test3.c +++ /dev/null @@ -1,44 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test3.c -** -** Purpose: Tests _snwprintf with wide strings -** -** -**==========================================================================*/ - - - -#include -#include "../_snwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - - -int __cdecl main(int argc, char *argv[]) -{ - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - DoStrTest(convert("foo %S"), "bar", convert("foo bar")); - DoStrTest(convert("foo %hS"), "bar", convert("foo bar")); - DoWStrTest(convert("foo %lS"), convert("bar"), convert("foo bar")); - DoWStrTest(convert("foo %wS"), convert("bar"), convert("foo bar")); - DoStrTest(convert("foo %LS"), "bar", convert("foo bar")); - DoStrTest(convert("foo %I64S"), "bar", convert("foo bar")); - DoStrTest(convert("foo %5S"), "bar", convert("foo bar")); - DoStrTest(convert("foo %.2S"), "bar", convert("foo ba")); - DoStrTest(convert("foo %5.2S"), "bar", convert("foo ba")); - DoStrTest(convert("foo %-5S"), "bar", convert("foo bar ")); - DoStrTest(convert("foo %05S"), "bar", convert("foo 00bar")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test3/testinfo.dat deleted file mode 100644 index b39f4f5..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test3/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snwprintf -Name = Positive Test for _snwprintf -TYPE = DEFAULT -EXE1 = test3 -Description -= Tests _snwprintf with wide strings diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test4/CMakeLists.txt deleted file mode 100644 index 0102b0a..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test4/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test4.c -) - -add_executable(paltest_snwprintf_test4 - ${SOURCES} -) - -add_dependencies(paltest_snwprintf_test4 coreclrpal) - -target_link_libraries(paltest_snwprintf_test4 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test4/test4.c deleted file mode 100644 index 28f7998..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test4/test4.c +++ /dev/null @@ -1,71 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test4.c -** -** Purpose: Tests _snwprintf with pointers -** -** -**==========================================================================*/ - - - -#include -#include "../_snwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - - -int __cdecl main(int argc, char *argv[]) -{ - void *ptr = (void*) 0x123456; - INT64 lptr = I64(0x1234567887654321); - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - -/* -** Run only on 64 bit platforms -*/ -#if defined(BIT64) && defined(PLATFORM_UNIX) - Trace("Testing for 64 Bit Platforms \n"); - DoPointerTest(convert("%p"), NULL, convert("0000000000000000")); - DoPointerTest(convert("%p"), ptr, convert("0000000000123456")); - DoPointerTest(convert("%17p"), ptr, convert(" 0000000000123456")); - DoPointerTest(convert("%17p"), ptr, convert(" 0000000000123456")); - DoPointerTest(convert("%-17p"), ptr, convert("0000000000123456 ")); - DoPointerTest(convert("%+p"), ptr, convert("0000000000123456")); - DoPointerTest(convert("% p"), ptr, convert("0000000000123456")); - DoPointerTest(convert("%#p"), ptr, convert("0X0000000000123456")); - DoPointerTest(convert("%lp"), ptr, convert("00123456")); - DoPointerTest(convert("%hp"), ptr, convert("00003456")); - DoPointerTest(convert("%Lp"), ptr, convert("00123456")); - DoI64Test(convert("%I64p"), lptr, "1234567887654321", - convert("1234567887654321")); -#else - Trace("Testing for Non 64 Bit Platforms \n"); - DoPointerTest(convert("%p"), NULL, convert("00000000")); - DoPointerTest(convert("%p"), ptr, convert("00123456")); - DoPointerTest(convert("%9p"), ptr, convert(" 00123456")); - DoPointerTest(convert("%09p"), ptr, convert(" 00123456")); - DoPointerTest(convert("%-9p"), ptr, convert("00123456 ")); - DoPointerTest(convert("%+p"), ptr, convert("00123456")); - DoPointerTest(convert("% p"), ptr, convert("00123456")); - DoPointerTest(convert("%#p"), ptr, convert("0X00123456")); - DoPointerTest(convert("%lp"), ptr, convert("00123456")); - DoPointerTest(convert("%hp"), ptr, convert("00003456")); - DoPointerTest(convert("%Lp"), ptr, convert("00123456")); - DoI64Test(convert("%I64p"), lptr, "1234567887654321", - convert("1234567887654321")); -#endif - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test4/testinfo.dat deleted file mode 100644 index 3f36001..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test4/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snwprintf -Name = Positive Test for _snwprintf -TYPE = DEFAULT -EXE1 = test4 -Description -= Tests _snwprintf with pointers diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test5/CMakeLists.txt deleted file mode 100644 index c835c94..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test5/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test5.c -) - -add_executable(paltest_snwprintf_test5 - ${SOURCES} -) - -add_dependencies(paltest_snwprintf_test5 coreclrpal) - -target_link_libraries(paltest_snwprintf_test5 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test5/test5.c deleted file mode 100644 index bbe4597..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test5/test5.c +++ /dev/null @@ -1,63 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test5.c -** -** Purpose: Tests _snwprintf with the count specifier -** -** -**==========================================================================*/ - - - -#include -#include "../_snwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - WCHAR *longStr; - WCHAR *longResult; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - longStr = convert("really-long-string-that-just-keeps-going-on-and-on-and-on.." - "..................useless-filler.................................." - "..................useless-filler.................................." - "..................useless-filler.................................." - "%n bar"); - longResult = convert("really-long-string-that-just-keeps-going-on-and-on-and-on.." - "..................useless-filler.................................." - "..................useless-filler.................................." - "..................useless-filler.................................." - " bar"); - DoCountTest(convert("foo %n bar"), 4, convert("foo bar")); - DoCountTest(longStr, 257, longResult); - DoCountTest(convert("fo%n bar"), 2, convert("fo bar")); - DoCountTest(convert("%n"), 0, convert("")); - DoCountTest(convert("foo %#n bar"), 4, convert("foo bar")); - DoCountTest(convert("foo % n bar"), 4, convert("foo bar")); - DoCountTest(convert("foo %+n bar"), 4, convert("foo bar")); - DoCountTest(convert("foo %-n bar"), 4, convert("foo bar")); - DoCountTest(convert("foo %0n bar"), 4, convert("foo bar")); - DoShortCountTest(convert("foo %hn bar"), 4, convert("foo bar")); - DoCountTest(convert("foo %ln bar"), 4, convert("foo bar")); - DoCountTest(convert("foo %Ln bar"), 4, convert("foo bar")); - DoCountTest(convert("foo %I64n bar"), 4, convert("foo bar")); - DoCountTest(convert("foo %20.3n bar"), 4, convert("foo bar")); - - free(longStr); - free(longResult); - - PAL_Terminate(); - - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test5/testinfo.dat deleted file mode 100644 index 2180b81..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test5/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snwprintf -Name = Positive Test for _snwprintf -TYPE = DEFAULT -EXE1 = test5 -Description -= Tests _snwprintf with the count specifier diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test6/CMakeLists.txt deleted file mode 100644 index 37a415e..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test6/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test6.c -) - -add_executable(paltest_snwprintf_test6 - ${SOURCES} -) - -add_dependencies(paltest_snwprintf_test6 coreclrpal) - -target_link_libraries(paltest_snwprintf_test6 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test6/test6.c deleted file mode 100644 index 3d4ed3f..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test6/test6.c +++ /dev/null @@ -1,46 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test6.c -** -** Purpose: Tests _snwprintf with characters -** -** -**==========================================================================*/ - - - -#include -#include "../_snwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - WCHAR wc = (WCHAR) 'c'; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoWCharTest(convert("foo %c"), wc, convert("foo c")); - DoCharTest(convert("foo %hc"), 'b', convert("foo b")); - DoWCharTest(convert("foo %lc"), wc, convert("foo c")); - DoWCharTest(convert("foo %Lc"), wc, convert("foo c")); - DoWCharTest(convert("foo %I64c"), wc, convert("foo c")); - DoWCharTest(convert("foo %5c"), wc, convert("foo c")); - DoWCharTest(convert("foo %.0c"), wc, convert("foo c")); - DoWCharTest(convert("foo %-5c"), wc, convert("foo c ")); - DoWCharTest(convert("foo %05c"), wc, convert("foo 0000c")); - DoWCharTest(convert("foo % c"), wc, convert("foo c")); - DoWCharTest(convert("foo %#c"), wc, convert("foo c")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test6/testinfo.dat deleted file mode 100644 index 6a170cd..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test6/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snwprintf -Name = Positive Test for _snwprintf -TYPE = DEFAULT -EXE1 = test6 -Description -= Tests _snwprintf with characters diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test7/CMakeLists.txt deleted file mode 100644 index b1a07ee..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test7/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test7.c -) - -add_executable(paltest_snwprintf_test7 - ${SOURCES} -) - -add_dependencies(paltest_snwprintf_test7 coreclrpal) - -target_link_libraries(paltest_snwprintf_test7 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test7/test7.c deleted file mode 100644 index 7954ff7..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test7/test7.c +++ /dev/null @@ -1,46 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test7.c -** -** Purpose: Tests _snwprintf with wide characters -** -** -**==========================================================================*/ - - - -#include -#include "../_snwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - WCHAR wc = (WCHAR) 'c'; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoCharTest(convert("foo %C"), 'b', convert("foo b")); - DoWCharTest(convert("foo %hC"), wc, convert("foo c")); - DoCharTest(convert("foo %lC"), 'b', convert("foo b")); - DoCharTest(convert("foo %LC"), 'b', convert("foo b")); - DoCharTest(convert("foo %I64C"), 'b', convert("foo b")); - DoCharTest(convert("foo %5C"), 'b', convert("foo b")); - DoCharTest(convert("foo %.0C"), 'b', convert("foo b")); - DoCharTest(convert("foo %-5C"), 'b', convert("foo b ")); - DoCharTest(convert("foo %05C"), 'b', convert("foo 0000b")); - DoCharTest(convert("foo % C"), 'b', convert("foo b")); - DoCharTest(convert("foo %#C"), 'b', convert("foo b")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test7/testinfo.dat deleted file mode 100644 index 5749539..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test7/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snwprintf -Name = Positive Test for _snwprintf -TYPE = DEFAULT -EXE1 = test7 -Description -= Tests _snwprintf with wide characters diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test8/CMakeLists.txt deleted file mode 100644 index 063ee2b..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test8/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test8.c -) - -add_executable(paltest_snwprintf_test8 - ${SOURCES} -) - -add_dependencies(paltest_snwprintf_test8 coreclrpal) - -target_link_libraries(paltest_snwprintf_test8 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test8/test8.c deleted file mode 100644 index 91c2820..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test8/test8.c +++ /dev/null @@ -1,53 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test8.c -** -** Purpose: Tests _snwprintf with decimal numbers -** -** -**==========================================================================*/ - - - -#include -#include "../_snwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 42; - INT64 l = 42; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoNumTest(convert("foo %d"), pos, convert("foo 42")); - DoNumTest(convert("foo %ld"), 0xFFFF, convert("foo 65535")); - DoNumTest(convert("foo %hd"), 0xFFFF, convert("foo -1")); - DoNumTest(convert("foo %Ld"), pos, convert("foo 42")); - DoI64Test(convert("foo %I64d"), l, "42", convert("foo 42")); - DoNumTest(convert("foo %3d"), pos, convert("foo 42")); - DoNumTest(convert("foo %-3d"), pos, convert("foo 42 ")); - DoNumTest(convert("foo %.1d"), pos, convert("foo 42")); - DoNumTest(convert("foo %.3d"), pos, convert("foo 042")); - DoNumTest(convert("foo %03d"), pos, convert("foo 042")); - DoNumTest(convert("foo %#d"), pos, convert("foo 42")); - DoNumTest(convert("foo %+d"), pos, convert("foo +42")); - DoNumTest(convert("foo % d"), pos, convert("foo 42")); - DoNumTest(convert("foo %+d"), neg, convert("foo -42")); - DoNumTest(convert("foo % d"), neg, convert("foo -42")); - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test8/testinfo.dat deleted file mode 100644 index 6398f60..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test8/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snwprintf -Name = Positive Test for _snwprintf -TYPE = DEFAULT -EXE1 = test8 -Description -= Tests _snwprintf with decimal numbers diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf/test9/CMakeLists.txt deleted file mode 100644 index 8d5e411..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test9/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test9.c -) - -add_executable(paltest_snwprintf_test9 - ${SOURCES} -) - -add_dependencies(paltest_snwprintf_test9 coreclrpal) - -target_link_libraries(paltest_snwprintf_test9 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/_snwprintf/test9/test9.c deleted file mode 100644 index f8f994f..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test9/test9.c +++ /dev/null @@ -1,53 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test9.c -** -** Purpose: Tests _snwprintf with integer numbers -** -** -**==========================================================================*/ - - - -#include -#include "../_snwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 42; - INT64 l = 42; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoNumTest(convert("foo %i"), pos, convert("foo 42")); - DoNumTest(convert("foo %li"), 0xFFFF, convert("foo 65535")); - DoNumTest(convert("foo %hi"), 0xFFFF, convert("foo -1")); - DoNumTest(convert("foo %Li"), pos, convert("foo 42")); - DoI64Test(convert("foo %I64i"), l, "42", convert("foo 42")); - DoNumTest(convert("foo %3i"), pos, convert("foo 42")); - DoNumTest(convert("foo %-3i"), pos, convert("foo 42 ")); - DoNumTest(convert("foo %.1i"), pos, convert("foo 42")); - DoNumTest(convert("foo %.3i"), pos, convert("foo 042")); - DoNumTest(convert("foo %03i"), pos, convert("foo 042")); - DoNumTest(convert("foo %#i"), pos, convert("foo 42")); - DoNumTest(convert("foo %+i"), pos, convert("foo +42")); - DoNumTest(convert("foo % i"), pos, convert("foo 42")); - DoNumTest(convert("foo %+i"), neg, convert("foo -42")); - DoNumTest(convert("foo % i"), neg, convert("foo -42")); - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf/test9/testinfo.dat deleted file mode 100644 index 287de4a..0000000 --- a/src/pal/tests/palsuite/c_runtime/_snwprintf/test9/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _snwprintf -Name = Positive Test for _snwprintf -TYPE = DEFAULT -EXE1 = test9 -Description -= Tests _snwprintf with integer numbers diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/CMakeLists.txt new file mode 100644 index 0000000..8fe1cb6 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) +add_subdirectory(test10) +add_subdirectory(test11) +add_subdirectory(test12) +add_subdirectory(test13) +add_subdirectory(test14) +add_subdirectory(test15) +add_subdirectory(test16) +add_subdirectory(test17) +add_subdirectory(test18) +add_subdirectory(test19) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/_snwprintf_s.h b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/_snwprintf_s.h new file mode 100644 index 0000000..19d1921 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/_snwprintf_s.h @@ -0,0 +1,199 @@ +// 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. + +/*============================================================================ +** +** Source: swprintf_s.h +** +** Purpose: Containts common testing functions for swprintf_s +** +** +**==========================================================================*/ + +#ifndef ___SNWPRINTF_H__ +#define ___SNWPRINTF_H__ + +void DoWStrTest(const WCHAR *formatstr, WCHAR *param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, param); + + if (memcmp(buf, checkstr, wcslen(checkstr) * 2 + 2) != 0) + { + Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n" + "Expected \"%s\", got \"%s\".\n", convertC(param), + convertC(formatstr), convertC(checkstr), convertC(buf)); + } +} + +void DoStrTest(const WCHAR *formatstr, char *param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, param); + + if (memcmp(buf, checkstr, wcslen(checkstr) * 2 + 2) != 0) + { + Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n" + "Expected \"%s\", got \"%s\".\n", + param, convertC(formatstr), convertC(checkstr), convertC(buf)); + } +} + +void DoPointerTest(const WCHAR *formatstr, void* param, const WCHAR *checkstr1) +{ + WCHAR buf[256] = { 0 }; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, param); + if (memcmp(buf, checkstr1, wcslen(checkstr1)*2 + 2) != 0) + { + Fail("ERROR: failed to insert pointer to %#p into \"%s\"\n" + "Expected \"%s\", got \"%s\".\n", param, convertC(formatstr), + convertC(checkstr1), convertC(buf)); + } +} + +void DoCountTest(const WCHAR *formatstr, int param, const WCHAR *checkstr) +{ + WCHAR buf[512] = { 0 }; + int n = -1; + + swprintf_s(buf, 512, formatstr, &n); + + if (n != param) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %d\n", + param, n); + } + + if (memcmp(buf, checkstr, wcslen(checkstr)*2 + 2) != 0) + { + Fail("ERROR: Expected \"%s\" got \"%s\".\n", + convertC(checkstr), convertC(buf)); + } +} + +void DoShortCountTest(const WCHAR *formatstr, int param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + short int n = -1; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, &n); + + if (n != param) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %d\n", + param, n); + } + + if (memcmp(buf, checkstr, wcslen(checkstr)*2 + 2) != 0) + { + Fail("ERROR: Expected \"%s\" got \"%s\".\n", + convertC(checkstr), convertC(buf)); + } +} + +void DoCharTest(const WCHAR *formatstr, char param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, param); + if (memcmp(buf, checkstr, wcslen(checkstr)*2 + 2) != 0) + { + Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", param, param, + convertC(formatstr), convertC(checkstr), convertC(buf)); + } +} + +void DoWCharTest(const WCHAR *formatstr, WCHAR param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, param); + if (memcmp(buf, checkstr, wcslen(checkstr)*2 + 2) != 0) + { + Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", (char) param, param, + convertC(formatstr), convertC(checkstr), convertC(buf)); + } +} + +void DoNumTest(const WCHAR *formatstr, int value, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, value); + if (memcmp(buf, checkstr, wcslen(checkstr)* 2 + 2) != 0) + { + Fail("ERROR: failed to insert %#x into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", value, convertC(formatstr), + convertC(checkstr), convertC(buf)); + } +} + + +void DoI64Test(const WCHAR *formatstr, INT64 param, char *paramdesc, + const WCHAR *checkstr1) +{ + WCHAR buf[256] = { 0 }; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, param); + if (memcmp(buf, checkstr1, wcslen(checkstr1)*2 + 2) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\", got \"%s\".\n", paramdesc, + convertC(formatstr), convertC(checkstr1), convertC(buf)); + } +} + +void DoDoubleTest(const WCHAR *formatstr, double value, const WCHAR *checkstr1, + const WCHAR *checkstr2) +{ + WCHAR buf[256] = { 0 }; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, value); + if (memcmp(buf, checkstr1, wcslen(checkstr1)*2 + 2) != 0 && + memcmp(buf, checkstr2, wcslen(checkstr2)*2 + 2) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\"\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + value, convertC(formatstr), convertC(checkstr1), + convertC(checkstr2), convertC(buf)); + } +} + +void DoArgumentPrecTest(const WCHAR *formatstr, int precision, void *param, + char *paramstr, const WCHAR *checkstr1, const WCHAR *checkstr2) +{ + WCHAR buf[256]; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, precision, param); + if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 && + memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + paramstr, convertC(formatstr), precision, + convertC(checkstr1), convertC(checkstr2) ,convertC(buf)); + } +} + +void DoArgumentPrecDoubleTest(const WCHAR *formatstr, int precision, double param, + const WCHAR *checkstr) +{ + WCHAR buf[256]; + + _snwprintf_s(buf, 256, _TRUNCATE, formatstr, precision, param); + if (memcmp(buf, checkstr, wcslen(checkstr) + 2) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" + "Expected \"%s\", got \"%s\".\n", param, convertC(formatstr), + precision, convertC(checkstr), convertC(buf)); + } +} + +#endif + diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/CMakeLists.txt new file mode 100644 index 0000000..eac86f3 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.cpp +) + +add_executable(paltest_snwprintf_test1 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test1 coreclrpal) + +target_link_libraries(paltest_snwprintf_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/test1.cpp b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/test1.cpp new file mode 100644 index 0000000..ba85103 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/test1.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: General test to see if swprintf_s works correctly +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR *checkstr; + WCHAR buf[256] = { 0 }; + int ret; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + checkstr = convert("hello world"); + _snwprintf_s(buf, 256, _TRUNCATE, checkstr); + if (memcmp(checkstr, buf, wcslen(checkstr)*2+2) != 0) + { + Fail("ERROR: Expected \"%s\", got \"%s\"\n", + convertC(checkstr), convertC(buf)); + } + + _snwprintf_s(buf, 256, _TRUNCATE, convert("xxxxxxxxxxxxxxxxx")); + ret = _snwprintf_s(buf, 8, _TRUNCATE, checkstr); + if ((memcmp(checkstr, buf, 14) != 0) || (buf[7] != 0)) + { + Fail("ERROR: Expected \"%8s\", got \"%8s\"\n", + convertC(checkstr), convertC(buf)); + } + if (ret >= 0) + { + Fail("ERROR: Expected negative return value, got %d.\n", ret); + } + if (buf[8] != (WCHAR) 'x') + { + Fail("ERROR: buffer overflow using \"%s\" with length 8.\n", + convertC(checkstr)); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/testinfo.dat new file mode 100644 index 0000000..96d7914 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test1/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test1 +Description += General test to see if swprintf_s works correctly diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/CMakeLists.txt new file mode 100644 index 0000000..82ee739 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test10.cpp +) + +add_executable(paltest_snwprintf_test10 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test10 coreclrpal) + +target_link_libraries(paltest_snwprintf_test10 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/test10.cpp b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/test10.cpp new file mode 100644 index 0000000..298f82b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/test10.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test10.c +** +** Purpose: Tests swprintf_s with octal numbers +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest(convert("foo %o"), pos, convert("foo 52")); + DoNumTest(convert("foo %lo"), 0xFFFF, convert("foo 177777")); + DoNumTest(convert("foo %ho"), 0xFFFF, convert("foo 177777")); + DoNumTest(convert("foo %Lo"), pos, convert("foo 52")); + DoI64Test(convert("foo %I64o"), l, "42", convert("foo 52")); + DoNumTest(convert("foo %3o"), pos, convert("foo 52")); + DoNumTest(convert("foo %-3o"), pos, convert("foo 52 ")); + DoNumTest(convert("foo %.1o"), pos, convert("foo 52")); + DoNumTest(convert("foo %.3o"), pos, convert("foo 052")); + DoNumTest(convert("foo %03o"), pos, convert("foo 052")); + DoNumTest(convert("foo %#o"), pos, convert("foo 052")); + DoNumTest(convert("foo %+o"), pos, convert("foo 52")); + DoNumTest(convert("foo % o"), pos, convert("foo 52")); + DoNumTest(convert("foo %+o"), neg, convert("foo 37777777726")); + DoNumTest(convert("foo % o"), neg, convert("foo 37777777726")); + + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/testinfo.dat new file mode 100644 index 0000000..887bbf7 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test10/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test10 +Description += Tests swprintf_s with octal numbers diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/CMakeLists.txt new file mode 100644 index 0000000..f7d7845 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test11.cpp +) + +add_executable(paltest_snwprintf_test11 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test11 coreclrpal) + +target_link_libraries(paltest_snwprintf_test11 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/test11.cpp b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/test11.cpp new file mode 100644 index 0000000..5196687 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/test11.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test11.c +** +** Purpose: Tests swprintf_s with unsigned numbers +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest(convert("foo %u"), pos, convert("foo 42")); + DoNumTest(convert("foo %lu"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %hu"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %Lu"), pos, convert("foo 42")); + DoI64Test(convert("foo %I64u"), l, "42", convert("foo 42")); + DoNumTest(convert("foo %3u"), pos, convert("foo 42")); + DoNumTest(convert("foo %-3u"), pos, convert("foo 42 ")); + DoNumTest(convert("foo %.1u"), pos, convert("foo 42")); + DoNumTest(convert("foo %.3u"), pos, convert("foo 042")); + DoNumTest(convert("foo %03u"), pos, convert("foo 042")); + DoNumTest(convert("foo %#u"), pos, convert("foo 42")); + DoNumTest(convert("foo %+u"), pos, convert("foo 42")); + DoNumTest(convert("foo % u"), pos, convert("foo 42")); + DoNumTest(convert("foo %+u"), neg, convert("foo 4294967254")); + DoNumTest(convert("foo % u"), neg, convert("foo 4294967254")); + + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/testinfo.dat new file mode 100644 index 0000000..3bda85e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test11/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test11 +Description += Tests swprintf_s with unsigned numbers diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/CMakeLists.txt new file mode 100644 index 0000000..5b926fb --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test12.cpp +) + +add_executable(paltest_snwprintf_test12 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test12 coreclrpal) + +target_link_libraries(paltest_snwprintf_test12 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/test12.cpp b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/test12.cpp new file mode 100644 index 0000000..52780af --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/test12.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test12.c +** +** Purpose: Tests swprintf_s with hex numbers (lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest(convert("foo %x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %lx"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %hx"), pos, convert("foo 34ab")); + DoNumTest(convert("foo %Lx"), pos, convert("foo 1234ab")); + DoI64Test(convert("foo %I64x"), l, "0x1234567887654321", + convert("foo 1234567887654321")); + DoNumTest(convert("foo %7x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %-7x"), pos, convert("foo 1234ab ")); + DoNumTest(convert("foo %.1x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %.7x"), pos, convert("foo 01234ab")); + DoNumTest(convert("foo %07x"), pos, convert("foo 01234ab")); + DoNumTest(convert("foo %#x"), pos, convert("foo 0x1234ab")); + DoNumTest(convert("foo %+x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo % x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %+x"), neg, convert("foo ffffffd6")); + DoNumTest(convert("foo % x"), neg, convert("foo ffffffd6")); + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/testinfo.dat new file mode 100644 index 0000000..d808a3b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test12/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test12 +Description += Tests swprintf_s with hex numbers (lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/CMakeLists.txt new file mode 100644 index 0000000..52a3c75 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test13.cpp +) + +add_executable(paltest_snwprintf_test13 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test13 coreclrpal) + +target_link_libraries(paltest_snwprintf_test13 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/test13.cpp b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/test13.cpp new file mode 100644 index 0000000..fa948b3 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/test13.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test13.c +** +** Purpose: Tests swprintf_s with hex numbers (uppercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest(convert("foo %X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %lX"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %hX"), pos, convert("foo 34AB")); + DoNumTest(convert("foo %LX"), pos, convert("foo 1234AB")); + DoI64Test(convert("foo %I64X"), l, "0x1234567887654321", + convert("foo 1234567887654321")); + DoNumTest(convert("foo %7X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %-7X"), pos, convert("foo 1234AB ")); + DoNumTest(convert("foo %.1X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %.7X"), pos, convert("foo 01234AB")); + DoNumTest(convert("foo %07X"), pos, convert("foo 01234AB")); + DoNumTest(convert("foo %#X"), pos, convert("foo 0X1234AB")); + DoNumTest(convert("foo %+X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo % X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %+X"), neg, convert("foo FFFFFFD6")); + DoNumTest(convert("foo % X"), neg, convert("foo FFFFFFD6")); + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/testinfo.dat new file mode 100644 index 0000000..2e5800e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test13/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test13 +Description += Tests swprintf_s with hex numbers (uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/CMakeLists.txt new file mode 100644 index 0000000..d557a30 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test14.cpp +) + +add_executable(paltest_snwprintf_test14 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test14 coreclrpal) + +target_link_libraries(paltest_snwprintf_test14 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/test14.cpp b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/test14.cpp new file mode 100644 index 0000000..aea289d --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/test14.cpp @@ -0,0 +1,66 @@ +// 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. + +/*============================================================================ +** +** Source: test14.c +** +** Purpose: Tests swprintf_s with exponential format doubles (lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest(convert("foo %e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %le"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %he"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %Le"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %I64e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %14e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %-14e"), val, convert("foo 2.560000e+002 "), + convert("foo 2.560000e+02 ")); + DoDoubleTest(convert("foo %.1e"), val, convert("foo 2.6e+002"), + convert("foo 2.6e+02")); + DoDoubleTest(convert("foo %.8e"), val, convert("foo 2.56000000e+002"), + convert("foo 2.56000000e+02")); + DoDoubleTest(convert("foo %014e"), val, convert("foo 02.560000e+002"), + convert("foo 002.560000e+02")); + DoDoubleTest(convert("foo %#e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %+e"), val, convert("foo +2.560000e+002"), + convert("foo +2.560000e+02")); + DoDoubleTest(convert("foo % e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %+e"), neg, convert("foo -2.560000e+002"), + convert("foo -2.560000e+02")); + DoDoubleTest(convert("foo % e"), neg, convert("foo -2.560000e+002"), + convert("foo -2.560000e+02")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/testinfo.dat new file mode 100644 index 0000000..25bd509 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test14/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test14 +Description += Tests swprintf_s with exponential format doubles (lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/CMakeLists.txt new file mode 100644 index 0000000..2e5ee36 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test15.cpp +) + +add_executable(paltest_snwprintf_test15 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test15 coreclrpal) + +target_link_libraries(paltest_snwprintf_test15 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/test15.cpp b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/test15.cpp new file mode 100644 index 0000000..14db14b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/test15.cpp @@ -0,0 +1,67 @@ +// 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. + +/*============================================================================ +** +** Source: test15.c +** +** Purpose: Tests swprintf_s with exponential format doubles (uppercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest(convert("foo %E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %lE"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %hE"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %LE"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %I64E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %14E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %-14E"), val, convert("foo 2.560000E+002 "), + convert("foo 2.560000E+02 ")); + DoDoubleTest(convert("foo %.1E"), val, convert("foo 2.6E+002"), + convert("foo 2.6E+02")); + DoDoubleTest(convert("foo %.8E"), val, convert("foo 2.56000000E+002"), + convert("foo 2.56000000E+02")); + DoDoubleTest(convert("foo %014E"), val, convert("foo 02.560000E+002"), + convert("foo 002.560000E+02")); + DoDoubleTest(convert("foo %#E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %+E"), val, convert("foo +2.560000E+002"), + convert("foo +2.560000E+02")); + DoDoubleTest(convert("foo % E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %+E"), neg, convert("foo -2.560000E+002"), + convert("foo -2.560000E+02")); + DoDoubleTest(convert("foo % E"), neg, convert("foo -2.560000E+002"), + convert("foo -2.560000E+02")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/testinfo.dat new file mode 100644 index 0000000..95d90e8 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test15/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test15 +Description += Tests swprintf_s with exponential format doubles (uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/CMakeLists.txt new file mode 100644 index 0000000..f4ce409 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test16.cpp +) + +add_executable(paltest_snwprintf_test16 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test16 coreclrpal) + +target_link_libraries(paltest_snwprintf_test16 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/test16.cpp b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/test16.cpp new file mode 100644 index 0000000..4d9a717 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/test16.cpp @@ -0,0 +1,65 @@ +// 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. + +/*============================================================================ +** +** Source: test16.c +** +** Purpose: Tests swprintf_s with decimal point format doubles +** +** +**==========================================================================*/ + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest(convert("foo %f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %lf"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %hf"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %Lf"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %I64f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %12f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %-12f"), val, convert("foo 2560.001000 "), + convert("foo 2560.001000 ")); + DoDoubleTest(convert("foo %.1f"), val, convert("foo 2560.0"), + convert("foo 2560.0")); + DoDoubleTest(convert("foo %.8f"), val, convert("foo 2560.00100000"), + convert("foo 2560.00100000")); + DoDoubleTest(convert("foo %012f"), val, convert("foo 02560.001000"), + convert("foo 02560.001000")); + DoDoubleTest(convert("foo %#f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %+f"), val, convert("foo +2560.001000"), + convert("foo +2560.001000")); + DoDoubleTest(convert("foo % f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %+f"), neg, convert("foo -2560.001000"), + convert("foo -2560.001000")); + DoDoubleTest(convert("foo % f"), neg, convert("foo -2560.001000"), + convert("foo -2560.001000")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/testinfo.dat new file mode 100644 index 0000000..b81c847 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test16/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test16 +Description += Tests swprintf_s with decimal point format doubles diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/CMakeLists.txt new file mode 100644 index 0000000..159e15d --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test17.cpp +) + +add_executable(paltest_snwprintf_test17 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test17 coreclrpal) + +target_link_libraries(paltest_snwprintf_test17 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/test17.cpp b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/test17.cpp new file mode 100644 index 0000000..6af1815 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/test17.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test17.c +** +** Purpose: Tests swprintf_s with compact format doubles (lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest(convert("foo %g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %lg"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %hg"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %Lg"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %I64g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %5g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %-5g"), val, convert("foo 2560 "), + convert("foo 2560 ")); + DoDoubleTest(convert("foo %.1g"), val, convert("foo 3e+003"), + convert("foo 3e+03")); + DoDoubleTest(convert("foo %.2g"), val, convert("foo 2.6e+003"), + convert("foo 2.6e+03")); + DoDoubleTest(convert("foo %.12g"), val, convert("foo 2560.001"), + convert("foo 2560.001")); + DoDoubleTest(convert("foo %06g"), val, convert("foo 002560"), + convert("foo 002560")); + DoDoubleTest(convert("foo %#g"), val, convert("foo 2560.00"), + convert("foo 2560.00")); + DoDoubleTest(convert("foo %+g"), val, convert("foo +2560"), + convert("foo +2560")); + DoDoubleTest(convert("foo % g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %+g"), neg, convert("foo -2560"), + convert("foo -2560")); + DoDoubleTest(convert("foo % g"), neg, convert("foo -2560"), + convert("foo -2560")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/testinfo.dat new file mode 100644 index 0000000..d643667 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test17/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test17 +Description += Tests swprintf_s with compact format doubles (lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/CMakeLists.txt new file mode 100644 index 0000000..5964e84 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test18.cpp +) + +add_executable(paltest_snwprintf_test18 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test18 coreclrpal) + +target_link_libraries(paltest_snwprintf_test18 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/test18.cpp b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/test18.cpp new file mode 100644 index 0000000..020a885 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/test18.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test18.c +** +** Purpose: Tests swprintf_s with compact format doubles (uppercase) +** +** +**==========================================================================*/ + + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest(convert("foo %G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %lG"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %hG"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %LG"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %I64G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %5G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %-5G"), val, convert("foo 2560 "), + convert("foo 2560 ")); + DoDoubleTest(convert("foo %.1G"), val, convert("foo 3E+003"), + convert("foo 3E+03")); + DoDoubleTest(convert("foo %.2G"), val, convert("foo 2.6E+003"), + convert("foo 2.6E+03")); + DoDoubleTest(convert("foo %.12G"), val, convert("foo 2560.001"), + convert("foo 2560.001")); + DoDoubleTest(convert("foo %06G"), val, convert("foo 002560"), + convert("foo 002560")); + DoDoubleTest(convert("foo %#G"), val, convert("foo 2560.00"), + convert("foo 2560.00")); + DoDoubleTest(convert("foo %+G"), val, convert("foo +2560"), + convert("foo +2560")); + DoDoubleTest(convert("foo % G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %+G"), neg, convert("foo -2560"), + convert("foo -2560")); + DoDoubleTest(convert("foo % G"), neg, convert("foo -2560"), + convert("foo -2560")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/testinfo.dat new file mode 100644 index 0000000..dfc2cd5 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test18/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test18 +Description += Tests swprintf_s with compact format doubles (uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/CMakeLists.txt new file mode 100644 index 0000000..5d84847 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test19.cpp +) + +add_executable(paltest_snwprintf_test19 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test19 coreclrpal) + +target_link_libraries(paltest_snwprintf_test19 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/test19.cpp b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/test19.cpp new file mode 100644 index 0000000..d335d1d --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/test19.cpp @@ -0,0 +1,82 @@ +// 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. + +/*============================================================================ +** +** Source: test19.c +** +** Purpose: Tests swprintf_s with argument specified precision +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + int n = -1; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + DoArgumentPrecTest(convert("%.*s"), 2, (void*)convert("bar"), "bar", + convert("ba"), convert("ba")); + DoArgumentPrecTest(convert("%.*S"), 2, (void*)"bar", "bar", + convert("ba"), convert("ba")); + DoArgumentPrecTest(convert("%.*c"), 0, (void*)'a', "a", + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*c"), 4, (void*)'a', "a", + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*C"), 0, (void*)'a', "a", + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*C"), 4, (void*)'a', "a", + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*d"), 1, (void*)42, "42", + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*d"), 3, (void*)42, "42", + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*i"), 1, (void*)42, "42", + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*i"), 3, (void*)42, "42", + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*o"), 1, (void*)42, "42", + convert("52"), convert("52")); + DoArgumentPrecTest(convert("%.*o"), 3, (void*)42, "42", + convert("052"), convert("052")); + DoArgumentPrecTest(convert("%.*u"), 1, (void*)42, "42", + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*u"), 3, (void*)42, "42", + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*x"), 1, (void*)0x42, "0x42", + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*x"), 3, (void*)0x42, "0x42", + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*X"), 1, (void*)0x42, "0x42", + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*X"), 3, (void*)0x42, "0x42", + convert("042"), convert("042")); + DoArgumentPrecDoubleTest(convert("%.*e"), 1, 2.01, convert("2.0e+000")); + DoArgumentPrecDoubleTest(convert("%.*e"), 3, 2.01, convert("2.010e+000")); + DoArgumentPrecDoubleTest(convert("%.*E"), 1, 2.01, convert("2.0E+000")); + DoArgumentPrecDoubleTest(convert("%.*E"), 3, 2.01, convert("2.010E+000")); + DoArgumentPrecDoubleTest(convert("%.*f"), 1, 2.01, convert("2.0")); + DoArgumentPrecDoubleTest(convert("%.*f"), 3, 2.01, convert("2.010")); + DoArgumentPrecDoubleTest(convert("%.*g"), 1, 256.01, convert("3e+002")); + DoArgumentPrecDoubleTest(convert("%.*g"), 3, 256.01, convert("256")); + DoArgumentPrecDoubleTest(convert("%.*g"), 4, 256.01, convert("256")); + DoArgumentPrecDoubleTest(convert("%.*g"), 6, 256.01, convert("256.01")); + DoArgumentPrecDoubleTest(convert("%.*G"), 1, 256.01, convert("3E+002")); + DoArgumentPrecDoubleTest(convert("%.*G"), 3, 256.01, convert("256")); + DoArgumentPrecDoubleTest(convert("%.*G"), 4, 256.01, convert("256")); + DoArgumentPrecDoubleTest(convert("%.*G"), 6, 256.01, convert("256.01")); + + PAL_Terminate(); + return PASS; + +} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/testinfo.dat new file mode 100644 index 0000000..95269cd --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test19/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test19 +Description += Tests swprintf_s with argument specified precision diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/CMakeLists.txt new file mode 100644 index 0000000..ea33d48 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test2.cpp +) + +add_executable(paltest_snwprintf_test2 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test2 coreclrpal) + +target_link_libraries(paltest_snwprintf_test2 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/test2.cpp b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/test2.cpp new file mode 100644 index 0000000..86bfdc9 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/test2.cpp @@ -0,0 +1,44 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose:Tests swprintf_s with strings +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + DoWStrTest(convert("foo %s"), convert("bar"), convert("foo bar")); + DoStrTest(convert("foo %hs"), "bar", convert("foo bar")); + DoWStrTest(convert("foo %ls"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %ws"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %Ls"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %I64s"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %5s"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %.2s"), convert("bar"), convert("foo ba")); + DoWStrTest(convert("foo %5.2s"), convert("bar"), convert("foo ba")); + DoWStrTest(convert("foo %-5s"), convert("bar"), convert("foo bar ")); + DoWStrTest(convert("foo %05s"), convert("bar"), convert("foo 00bar")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/testinfo.dat new file mode 100644 index 0000000..88f1981 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test2/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test2 +Description += Tests swprintf_s with strings diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/CMakeLists.txt new file mode 100644 index 0000000..5095b1a --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test3.cpp +) + +add_executable(paltest_snwprintf_test3 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test3 coreclrpal) + +target_link_libraries(paltest_snwprintf_test3 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/test3.cpp b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/test3.cpp new file mode 100644 index 0000000..f6db6f2 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/test3.cpp @@ -0,0 +1,44 @@ +// 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. + +/*============================================================================ +** +** Source: test3.c +** +** Purpose: Tests swprintf_s with wide strings +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + DoStrTest(convert("foo %S"), "bar", convert("foo bar")); + DoStrTest(convert("foo %hS"), "bar", convert("foo bar")); + DoWStrTest(convert("foo %lS"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %wS"), convert("bar"), convert("foo bar")); + DoStrTest(convert("foo %LS"), "bar", convert("foo bar")); + DoStrTest(convert("foo %I64S"), "bar", convert("foo bar")); + DoStrTest(convert("foo %5S"), "bar", convert("foo bar")); + DoStrTest(convert("foo %.2S"), "bar", convert("foo ba")); + DoStrTest(convert("foo %5.2S"), "bar", convert("foo ba")); + DoStrTest(convert("foo %-5S"), "bar", convert("foo bar ")); + DoStrTest(convert("foo %05S"), "bar", convert("foo 00bar")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/testinfo.dat new file mode 100644 index 0000000..5ed59e6 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test3/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test3 +Description += Tests swprintf_s with wide strings diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/CMakeLists.txt new file mode 100644 index 0000000..9cf81ea --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test4.cpp +) + +add_executable(paltest_snwprintf_test4 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test4 coreclrpal) + +target_link_libraries(paltest_snwprintf_test4 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/test4.cpp b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/test4.cpp new file mode 100644 index 0000000..02d4781 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/test4.cpp @@ -0,0 +1,71 @@ +// 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. + +/*============================================================================ +** +** Source: test4.c +** +** Purpose: Tests swprintf_s with pointers +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + void *ptr = (void*) 0x123456; + INT64 lptr = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + +/* +** Run only on 64 bit platforms +*/ +#if defined(BIT64) && defined(PLATFORM_UNIX) + Trace("Testing for 64 Bit Platforms \n"); + DoPointerTest(convert("%p"), NULL, convert("0000000000000000")); + DoPointerTest(convert("%p"), ptr, convert("0000000000123456")); + DoPointerTest(convert("%17p"), ptr, convert(" 0000000000123456")); + DoPointerTest(convert("%17p"), ptr, convert(" 0000000000123456")); + DoPointerTest(convert("%-17p"), ptr, convert("0000000000123456 ")); + DoPointerTest(convert("%+p"), ptr, convert("0000000000123456")); + DoPointerTest(convert("% p"), ptr, convert("0000000000123456")); + DoPointerTest(convert("%#p"), ptr, convert("0X0000000000123456")); + DoPointerTest(convert("%lp"), ptr, convert("00123456")); + DoPointerTest(convert("%hp"), ptr, convert("00003456")); + DoPointerTest(convert("%Lp"), ptr, convert("00123456")); + DoI64Test(convert("%I64p"), lptr, "1234567887654321", + convert("1234567887654321")); +#else + Trace("Testing for Non 64 Bit Platforms \n"); + DoPointerTest(convert("%p"), NULL, convert("00000000")); + DoPointerTest(convert("%p"), ptr, convert("00123456")); + DoPointerTest(convert("%9p"), ptr, convert(" 00123456")); + DoPointerTest(convert("%09p"), ptr, convert(" 00123456")); + DoPointerTest(convert("%-9p"), ptr, convert("00123456 ")); + DoPointerTest(convert("%+p"), ptr, convert("00123456")); + DoPointerTest(convert("% p"), ptr, convert("00123456")); + DoPointerTest(convert("%#p"), ptr, convert("0X00123456")); + DoPointerTest(convert("%lp"), ptr, convert("00123456")); + DoPointerTest(convert("%hp"), ptr, convert("00003456")); + DoPointerTest(convert("%Lp"), ptr, convert("00123456")); + DoI64Test(convert("%I64p"), lptr, "1234567887654321", + convert("1234567887654321")); +#endif + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/testinfo.dat new file mode 100644 index 0000000..2b35f2d --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test4/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test4 +Description += Tests swprintf_s with pointers diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/CMakeLists.txt new file mode 100644 index 0000000..4996c77 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test6.cpp +) + +add_executable(paltest_snwprintf_test6 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test6 coreclrpal) + +target_link_libraries(paltest_snwprintf_test6 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/test6.cpp b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/test6.cpp new file mode 100644 index 0000000..576e061 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/test6.cpp @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test6.c +** +** Purpose: Tests swprintf_s with characters +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wc = (WCHAR) 'c'; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoWCharTest(convert("foo %c"), wc, convert("foo c")); + DoCharTest(convert("foo %hc"), 'b', convert("foo b")); + DoWCharTest(convert("foo %lc"), wc, convert("foo c")); + DoWCharTest(convert("foo %Lc"), wc, convert("foo c")); + DoWCharTest(convert("foo %I64c"), wc, convert("foo c")); + DoWCharTest(convert("foo %5c"), wc, convert("foo c")); + DoWCharTest(convert("foo %.0c"), wc, convert("foo c")); + DoWCharTest(convert("foo %-5c"), wc, convert("foo c ")); + DoWCharTest(convert("foo %05c"), wc, convert("foo 0000c")); + DoWCharTest(convert("foo % c"), wc, convert("foo c")); + DoWCharTest(convert("foo %#c"), wc, convert("foo c")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/testinfo.dat new file mode 100644 index 0000000..d8db7f8 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test6/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test6 +Description += Tests swprintf_s with characters diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/CMakeLists.txt new file mode 100644 index 0000000..0e55fbf --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test7.cpp +) + +add_executable(paltest_snwprintf_test7 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test7 coreclrpal) + +target_link_libraries(paltest_snwprintf_test7 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/test7.cpp b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/test7.cpp new file mode 100644 index 0000000..54dd32b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/test7.cpp @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test7.c +** +** Purpose: Tests swprintf_s with wide characters +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wc = (WCHAR) 'c'; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoCharTest(convert("foo %C"), 'b', convert("foo b")); + DoWCharTest(convert("foo %hC"), wc, convert("foo c")); + DoCharTest(convert("foo %lC"), 'b', convert("foo b")); + DoCharTest(convert("foo %LC"), 'b', convert("foo b")); + DoCharTest(convert("foo %I64C"), 'b', convert("foo b")); + DoCharTest(convert("foo %5C"), 'b', convert("foo b")); + DoCharTest(convert("foo %.0C"), 'b', convert("foo b")); + DoCharTest(convert("foo %-5C"), 'b', convert("foo b ")); + DoCharTest(convert("foo %05C"), 'b', convert("foo 0000b")); + DoCharTest(convert("foo % C"), 'b', convert("foo b")); + DoCharTest(convert("foo %#C"), 'b', convert("foo b")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/testinfo.dat new file mode 100644 index 0000000..fa5bd30 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test7/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test7 +Description += Tests swprintf_s with wide characters diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/CMakeLists.txt new file mode 100644 index 0000000..8f7fbda --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test8.cpp +) + +add_executable(paltest_snwprintf_test8 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test8 coreclrpal) + +target_link_libraries(paltest_snwprintf_test8 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/test8.cpp b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/test8.cpp new file mode 100644 index 0000000..9f1b555 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/test8.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test8.c +** +** Purpose: Tests swprintf_s with decimal numbers +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest(convert("foo %d"), pos, convert("foo 42")); + DoNumTest(convert("foo %ld"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %hd"), 0xFFFF, convert("foo -1")); + DoNumTest(convert("foo %Ld"), pos, convert("foo 42")); + DoI64Test(convert("foo %I64d"), l, "42", convert("foo 42")); + DoNumTest(convert("foo %3d"), pos, convert("foo 42")); + DoNumTest(convert("foo %-3d"), pos, convert("foo 42 ")); + DoNumTest(convert("foo %.1d"), pos, convert("foo 42")); + DoNumTest(convert("foo %.3d"), pos, convert("foo 042")); + DoNumTest(convert("foo %03d"), pos, convert("foo 042")); + DoNumTest(convert("foo %#d"), pos, convert("foo 42")); + DoNumTest(convert("foo %+d"), pos, convert("foo +42")); + DoNumTest(convert("foo % d"), pos, convert("foo 42")); + DoNumTest(convert("foo %+d"), neg, convert("foo -42")); + DoNumTest(convert("foo % d"), neg, convert("foo -42")); + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/testinfo.dat new file mode 100644 index 0000000..d76a421 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test8/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test8 +Description += Tests swprintf_s with decimal numbers diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/CMakeLists.txt new file mode 100644 index 0000000..f769c9e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test9.cpp +) + +add_executable(paltest_snwprintf_test9 + ${SOURCES} +) + +add_dependencies(paltest_snwprintf_test9 coreclrpal) + +target_link_libraries(paltest_snwprintf_test9 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/test9.cpp b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/test9.cpp new file mode 100644 index 0000000..76d6063 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/test9.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test9.c +** +** Purpose: Tests swprintf_s with integer numbers +** +** +**==========================================================================*/ + + + +#include +#include "../_snwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest(convert("foo %i"), pos, convert("foo 42")); + DoNumTest(convert("foo %li"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %hi"), 0xFFFF, convert("foo -1")); + DoNumTest(convert("foo %Li"), pos, convert("foo 42")); + DoI64Test(convert("foo %I64i"), l, "42", convert("foo 42")); + DoNumTest(convert("foo %3i"), pos, convert("foo 42")); + DoNumTest(convert("foo %-3i"), pos, convert("foo 42 ")); + DoNumTest(convert("foo %.1i"), pos, convert("foo 42")); + DoNumTest(convert("foo %.3i"), pos, convert("foo 042")); + DoNumTest(convert("foo %03i"), pos, convert("foo 042")); + DoNumTest(convert("foo %#i"), pos, convert("foo 42")); + DoNumTest(convert("foo %+i"), pos, convert("foo +42")); + DoNumTest(convert("foo % i"), pos, convert("foo 42")); + DoNumTest(convert("foo %+i"), neg, convert("foo -42")); + DoNumTest(convert("foo % i"), neg, convert("foo -42")); + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/testinfo.dat new file mode 100644 index 0000000..b2a038d --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_snwprintf_s/test9/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = swprintf_s +Name = Positive Test for swprintf_s +TYPE = DEFAULT +EXE1 = test9 +Description += Tests swprintf_s with integer numbers diff --git a/src/pal/tests/palsuite/c_runtime/_splitpath/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_splitpath/CMakeLists.txt deleted file mode 100644 index f6aa0cb..0000000 --- a/src/pal/tests/palsuite/c_runtime/_splitpath/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -add_subdirectory(test1) - diff --git a/src/pal/tests/palsuite/c_runtime/_splitpath/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_splitpath/test1/CMakeLists.txt deleted file mode 100644 index 361b908..0000000 --- a/src/pal/tests/palsuite/c_runtime/_splitpath/test1/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test1.c -) - -add_executable(paltest_splitpath_test1 - ${SOURCES} -) - -add_dependencies(paltest_splitpath_test1 coreclrpal) - -target_link_libraries(paltest_splitpath_test1 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_splitpath/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_splitpath/test1/test1.c deleted file mode 100644 index e98354c..0000000 --- a/src/pal/tests/palsuite/c_runtime/_splitpath/test1/test1.c +++ /dev/null @@ -1,108 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: Passes _splitpath() a series of sample paths and checks that it -** parses them as expected. -** -** -**==========================================================================*/ - - -#include - -struct testCase -{ - const char path[_MAX_PATH]; /* The path to parse. */ - const char drive[_MAX_DRIVE]; /* The expected values... */ - const char dir[_MAX_DIR]; - const char fname[_MAX_FNAME]; - const char ext[_MAX_EXT]; -}; - - -int __cdecl main(int argc, char **argv) -{ - struct testCase testCases[] = - { -#if WIN32 - {"c:\\foo\\bar\\foo.bar", "c:", "\\foo\\bar\\", "foo", ".bar"}, - {"c:/foo/bar/foo.bar", "c:", "/foo/bar/", "foo", ".bar"}, - {"c:/foo/bar/foo", "c:", "/foo/bar/", "foo", ""}, - {"c:/foo/bar/.bar", "c:", "/foo/bar/", "", ".bar"}, - {"c:/foo/bar/", "c:", "/foo/bar/", "", ""}, - {"/foo/bar/foo.bar", "", "/foo/bar/", "foo", ".bar"}, - {"c:foo.bar", "c:", "", "foo", ".bar"} -#else - {"c:\\foo\\bar\\foo.bar", "","c:/foo/bar/", "foo", ".bar"}, - {"c:/foo/bar/foo.bar", "", "c:/foo/bar/", "foo", ".bar"}, - {"c:/foo/bar/foo", "", "c:/foo/bar/", "foo", ""}, - {"c:/foo/bar/.bar", "", "c:/foo/bar/", ".bar", ""}, - {"c:/foo/bar/", "", "c:/foo/bar/", "", ""}, - {"/foo/bar/foo.bar", "", "/foo/bar/", "foo", ".bar"}, - {"c:foo.bar", "", "", "c:foo", ".bar"} -#endif - }; - char drive[_MAX_DRIVE]; - char dir[_MAX_DIR]; - char fname[_MAX_FNAME]; - char ext[_MAX_EXT]; - - int i=0; - - /* - * Initialize the PAL and return FAIL if this fails - */ - if (0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - for (i = 0; i < sizeof(testCases)/sizeof(struct testCase); i++) - { - _splitpath(testCases[i].path, drive, dir, fname, ext); - - - /*on platforms that don't support drive letters, the drive - returned should always be "" */ - if (strcmp(drive, testCases[i].drive) != 0) - { - Fail("_splitpath read the path \"%s\" and thought the drive was " - "\"%s\" instead of \"%s\"\n" - , testCases[i].path, drive, testCases[i].drive); - } - - if (strcmp(dir, testCases[i].dir) != 0) - { - Fail("_splitpath read the path \"%s\" and thought the directory " - "was \"%s\" instead of \"%s\"\n" - , testCases[i].path, dir, testCases[i].dir); - } - - if (strcmp(fname, testCases[i].fname) != 0) - { - Fail("_splitpath read the path \"%s\" and thought the filename " - "was \"%s\" instead of \"%s\"\n" - , testCases[i].path, fname, testCases[i].fname); - } - - if (strcmp(ext, testCases[i].ext) != 0) - { - Fail("_splitpath read the path \"%s\" and thought the file " - "extension was \"%s\" instead of \"%s\"\n" - , testCases[i].path, ext, testCases[i].ext); - } - } - PAL_Terminate(); - return PASS; -} - - - - - - diff --git a/src/pal/tests/palsuite/c_runtime/_splitpath/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_splitpath/test1/testinfo.dat deleted file mode 100644 index 0a93e27..0000000 --- a/src/pal/tests/palsuite/c_runtime/_splitpath/test1/testinfo.dat +++ /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. -# See the LICENSE file in the project root for more information. - -Version = 1.0 -Section = C Runtime -Function = _splitpath -Name = Positive Test for _splitpath -TYPE = DEFAULT -EXE1 = test1 -Description -= Passes _splitpath() a series of sample paths and checks that it -= parses them as expected. - - diff --git a/src/pal/tests/palsuite/c_runtime/_stricmp/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_stricmp/test1/CMakeLists.txt index 766660c..03aa3a5 100644 --- a/src/pal/tests/palsuite/c_runtime/_stricmp/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_stricmp/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_stricmp_test1 diff --git a/src/pal/tests/palsuite/c_runtime/_stricmp/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_stricmp/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_stricmp/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/_stricmp/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_strlwr/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_strlwr/test1/CMakeLists.txt index 3a9394c..ca26961 100644 --- a/src/pal/tests/palsuite/c_runtime/_strlwr/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_strlwr/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_strlwr_test1 diff --git a/src/pal/tests/palsuite/c_runtime/_strlwr/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_strlwr/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_strlwr/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/_strlwr/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/CMakeLists.txt index 6a38747..03f9992 100644 --- a/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_strnicmp_test1 diff --git a/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_strnicmp/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_strnicmp/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/_strnicmp/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_swab/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_swab/CMakeLists.txt deleted file mode 100644 index f6aa0cb..0000000 --- a/src/pal/tests/palsuite/c_runtime/_swab/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -add_subdirectory(test1) - diff --git a/src/pal/tests/palsuite/c_runtime/_swab/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_swab/test1/CMakeLists.txt deleted file mode 100644 index fc7fbef..0000000 --- a/src/pal/tests/palsuite/c_runtime/_swab/test1/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test1.c -) - -add_executable(paltest_swab_test1 - ${SOURCES} -) - -add_dependencies(paltest_swab_test1 coreclrpal) - -target_link_libraries(paltest_swab_test1 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_swab/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_swab/test1/test1.c deleted file mode 100644 index 203e3b3..0000000 --- a/src/pal/tests/palsuite/c_runtime/_swab/test1/test1.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: Calls _swab on a buffer, and checks that it has correctly -** swapped adjacent bytes -** -** -**==========================================================================*/ - -#include - -int __cdecl main(int argc, char **argv) -{ - char before[] = "abcdefghijklmn"; - char after[] = "--------------"; - const char check[] = "badcfehgjilknm"; - - /* - * Initialize the PAL and return FAIL if this fails - */ - if (0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - _swab(before, after, sizeof(before)); - if (memcmp(after, check, sizeof(after)) != 0) - { - Fail ("_swab did not correctly swap adjacent bytes in a buffer.\n"); - } - - PAL_Terminate(); - return PASS; - -} - - - - - diff --git a/src/pal/tests/palsuite/c_runtime/_swab/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_swab/test1/testinfo.dat deleted file mode 100644 index c59b017..0000000 --- a/src/pal/tests/palsuite/c_runtime/_swab/test1/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _swab -Name = Positive Test for _swab -TYPE = DEFAULT -EXE1 = test1 -Description -= Calls _swab on a buffer, and checks that it has correctly swapped -= adjacent bytes - diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/_vsnprintf.h b/src/pal/tests/palsuite/c_runtime/_vsnprintf/_vsnprintf.h index 240a72f..30e7064 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/_vsnprintf.h +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/_vsnprintf.h @@ -28,7 +28,7 @@ int Testvsnprintf(char* buf, size_t count, const char* format, ...) } -void DoStrTest(char *formatstr, char* param, char *checkstr) +void DoStrTest(const char *formatstr, char* param, const char *checkstr) { char buf[256] = { 0 }; @@ -41,7 +41,7 @@ void DoStrTest(char *formatstr, char* param, char *checkstr) } } -void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr) +void DoWStrTest(const char *formatstr, WCHAR* param, const char *checkstr) { char buf[256] = { 0 }; @@ -55,7 +55,7 @@ void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr) } -void DoCharTest(char *formatstr, char param, char *checkstr) +void DoCharTest(const char *formatstr, char param, const char *checkstr) { char buf[256] = { 0 }; @@ -68,7 +68,7 @@ void DoCharTest(char *formatstr, char param, char *checkstr) } } -void DoWCharTest(char *formatstr, WCHAR param, char *checkstr) +void DoWCharTest(const char *formatstr, WCHAR param, const char *checkstr) { char buf[256] = { 0 }; @@ -81,7 +81,7 @@ void DoWCharTest(char *formatstr, WCHAR param, char *checkstr) } } -void DoNumTest(char *formatstr, int value, char *checkstr) +void DoNumTest(const char *formatstr, int value, const char *checkstr) { char buf[256] = { 0 }; @@ -94,7 +94,7 @@ void DoNumTest(char *formatstr, int value, char *checkstr) } } -void DoI64Test(char *formatstr, INT64 value, char *valuestr, char *checkstr) +void DoI64Test(const char *formatstr, INT64 value, char *valuestr, const char *checkstr) { char buf[256] = { 0 }; @@ -106,7 +106,7 @@ void DoI64Test(char *formatstr, INT64 value, char *valuestr, char *checkstr) valuestr, formatstr, checkstr, buf); } } -void DoDoubleTest(char *formatstr, double value, char *checkstr1, char +void DoDoubleTest(const char *formatstr, double value, const char *checkstr1, char *checkstr2) { char buf[256] = { 0 }; diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/CMakeLists.txt index 7c346a4..489b7bf 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_vsnprintf_test1 diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/testinfo.dat index 0e97856..f96bf08 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/testinfo.dat +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test1/testinfo.dat @@ -10,4 +10,4 @@ TYPE = DEFAULT EXE1 = test1 Description = Tests the PAL implementation of the _vsnprintf function. -= This test is modeled after _snprintf. += This test is modeled after sprintf_s. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/CMakeLists.txt index 00dccc2..bc35dbd 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test10.c + test10.cpp ) add_executable(paltest_vsnprintf_test10 diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/test10.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/test10.c rename to src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/test10.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/testinfo.dat index 1399afa..a3d8eca 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/testinfo.dat +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test10/testinfo.dat @@ -11,4 +11,4 @@ EXE1 = test10 Description = Tests the PAL implementation of the _vsnprintf function. = Tests _vsnprintf with octal numbers. -= This test is modeled after _snprintf. += This test is modeled after sprintf_s. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/CMakeLists.txt index fd709f2..bf3dd9a 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test11.c + test11.cpp ) add_executable(paltest_vsnprintf_test11 diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/test11.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/test11.c rename to src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/test11.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/testinfo.dat index faa7428..17e9f04 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/testinfo.dat +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test11/testinfo.dat @@ -11,4 +11,4 @@ EXE1 = test11 Description = Tests the PAL implementation of the _vsnprintf function. = Tests _vsnprintf with unsigned numbers. -= This test is modeled after _snprintf. += This test is modeled after sprintf_s. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/CMakeLists.txt index 02dac0c..9fceeaf 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test12.c + test12.cpp ) add_executable(paltest_vsnprintf_test12 diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/test12.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/test12.c rename to src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/test12.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/testinfo.dat index d48a5cc..82f58e4 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/testinfo.dat +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test12/testinfo.dat @@ -11,4 +11,4 @@ EXE1 = test12 Description = Tests the PAL implementation of the _vsnprintf function. = Tests _vsnprintf with hex numbers (lowercase). -= This test is modeled after _snprintf. += This test is modeled after sprintf_s. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/CMakeLists.txt index 52562c9..7e805f6 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test13.c + test13.cpp ) add_executable(paltest_vsnprintf_test13 diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/test13.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/test13.c rename to src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/test13.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/testinfo.dat index a3f14c2..d308edf 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/testinfo.dat +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test13/testinfo.dat @@ -11,4 +11,4 @@ EXE1 = test13 Description = Tests the PAL implementation of the _vsnprintf function. = Tests _vsnprintf with hex numbers (uppercase). -= This test is modeled after _snprintf. += This test is modeled after sprintf_s. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/CMakeLists.txt index 3fc8c81..6e4566b 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test14.c + test14.cpp ) add_executable(paltest_vsnprintf_test14 diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/test14.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/test14.c rename to src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/test14.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/testinfo.dat index f4d921c..8d11b1d 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/testinfo.dat +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test14/testinfo.dat @@ -11,4 +11,4 @@ EXE1 = test14 Description = Tests the PAL implementation of the _vsnprintf function. = Tests _vsnprintf with exponential format doubles (lowercase). -= This test is modeled after _snprintf. += This test is modeled after sprintf_s. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/CMakeLists.txt index f6bdc83..d9039b3 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test15.c + test15.cpp ) add_executable(paltest_vsnprintf_test15 diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/test15.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/test15.c rename to src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/test15.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/testinfo.dat index 3a6620b..9139125 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/testinfo.dat +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test15/testinfo.dat @@ -11,4 +11,4 @@ EXE1 = test15 Description = Tests the PAL implementation of the _vsnprintf function. = Tests _vsnprintf with exponential format doubles (uppercase). -= This test is modeled after _snprintf. += This test is modeled after sprintf_s. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/CMakeLists.txt index b7b06d1..b298df3 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test16.c + test16.cpp ) add_executable(paltest_vsnprintf_test16 diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/test16.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/test16.c rename to src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/test16.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/testinfo.dat index 6363f29..fc2f130 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/testinfo.dat +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test16/testinfo.dat @@ -11,4 +11,4 @@ EXE1 = test16 Description = Tests the PAL implementation of the _vsnprintf function. = Tests _vsnprintf with decimal point format doubles. -= This test is modeled after _snprintf. += This test is modeled after sprintf_s. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/CMakeLists.txt index 2c91ccc..b195f33 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test17.c + test17.cpp ) add_executable(paltest_vsnprintf_test17 diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/test17.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/test17.c rename to src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/test17.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/testinfo.dat index ecec515..aeb9244 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/testinfo.dat +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test17/testinfo.dat @@ -11,4 +11,4 @@ EXE1 = test17 Description = Tests the PAL implementation of the _vsnprintf function. = Tests _vsnprintf with compact format doubles (lowercase). -= This test is modeled after _snprintf. += This test is modeled after sprintf_s. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/CMakeLists.txt index 1a06ce0..f0f6d11 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test18.c + test18.cpp ) add_executable(paltest_vsnprintf_test18 diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/test18.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/test18.c rename to src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/test18.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/testinfo.dat index 34fd7ae..57aaed5 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/testinfo.dat +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test18/testinfo.dat @@ -11,4 +11,4 @@ EXE1 = test18 Description = Tests the PAL implementation of the _vsnprintf function. = Tests _vsnprintf with compact format doubles (uppercase). -= This test is modeled after _snprintf. += This test is modeled after sprintf_s. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/CMakeLists.txt index 6f2e42c..44b3890 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test19.c + test19.cpp ) add_executable(paltest_vsnprintf_test19 diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/test19.c deleted file mode 100644 index 075a528..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/test19.c +++ /dev/null @@ -1,103 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: test19.c -** -** Purpose: Test #19 for the _vsnprintf function. -** -** -**===================================================================*/ - -#include -#include "../_vsnprintf.h" - -/* - * Notes: memcmp is used, as is strlen. - */ - -#define DOTEST(a,b,c,d,e) DoTest(a,b,(void*)c,d,e) - -void DoArgumentPrecTest(char *formatstr, int precision, void *param, - char *paramstr, char *checkstr1, char *checkstr2) -{ - char buf[256]; - - Testvsnprintf(buf,256,formatstr, precision, param); - if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && - memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) - { - Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" - "Expected \"%s\" or \"%s\", got \"%s\".\n", - paramstr, formatstr, precision, checkstr1, checkstr2, buf); - } - -} - -void DoArgumentPrecDoubleTest(char *formatstr, int precision, double param, - char *checkstr1, char *checkstr2) -{ - char buf[256]; - - Testvsnprintf(buf,256,formatstr, precision, param); - if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && - memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) - { - Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" - "Expected \"%s\" or \"%s\", got \"%s\".\n", - param, formatstr, precision, checkstr1, checkstr2, buf); - } - -} - - - -int __cdecl main(int argc, char *argv[]) -{ - - if (PAL_Initialize(argc, argv) != 0) - { - return(FAIL); - } - - - DoArgumentPrecTest("%.*s", 2, "bar", "bar", "ba", "ba"); - DoArgumentPrecTest("%.*S", 2, convert("bar"), "bar", "ba", "ba"); - DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); - DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); - DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); - DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); - DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42"); - DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); - - - DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); - DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); - DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); - DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); - DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); - DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); - DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); - DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); - DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); - DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/test19.cpp b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/test19.cpp new file mode 100644 index 0000000..211354b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/test19.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*===================================================================== +** +** Source: test19.c +** +** Purpose: Test #19 for the _vsnprintf function. +** +** +**===================================================================*/ + +#include +#include "../_vsnprintf.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +#define DOTEST(a,b,c,d,e) DoTest(a,b,(void*)c,d,e) + +void DoArgumentPrecTest(char *formatstr, int precision, void *param, + char *paramstr, char *checkstr1, char *checkstr2) +{ + char buf[256]; + + Testvsnprintf(buf,256,formatstr, precision, param); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + paramstr, formatstr, precision, checkstr1, checkstr2, buf); + } + +} + +void DoArgumentPrecDoubleTest(char *formatstr, int precision, double param, + char *checkstr1, char *checkstr2) +{ + char buf[256]; + + Testvsnprintf(buf,256,formatstr, precision, param); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + param, formatstr, precision, checkstr1, checkstr2, buf); + } + +} + + + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + + DoArgumentPrecTest("%.*s", 2, (void*)"bar", "bar", "ba", "ba"); + DoArgumentPrecTest("%.*S", 2, (void*)convert("bar"), "bar", "ba", "ba"); + DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); + DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); + DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); + DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); + + + DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); + DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); + DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); + DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); + DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); + DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); + DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); + DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); + DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); + DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/testinfo.dat index 05f4b5b..cda8966 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/testinfo.dat +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test19/testinfo.dat @@ -11,4 +11,4 @@ EXE1 = test19 Description = Tests the PAL implementation of the _vsnprintf function. = Tests _vsnprintf with argument specified precision. -= This test is modeled after _snprintf. += This test is modeled after sprintf_s. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/CMakeLists.txt index a3871d6..1d3910e 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_vsnprintf_test2 diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/testinfo.dat index 5ee925e..6e8f03e 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/testinfo.dat +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test2/testinfo.dat @@ -11,4 +11,4 @@ EXE1 = test2 Description = Tests the PAL implementation of the _vsnprintf function. = Tests _vsnprintf with strings. -= This test is modeled after _snprintf. += This test is modeled after sprintf_s. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/CMakeLists.txt index 1beae06..62d765e 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_vsnprintf_test3 diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/test3.c rename to src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/test3.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/testinfo.dat index 626949c..638cef6 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/testinfo.dat +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test3/testinfo.dat @@ -11,4 +11,4 @@ EXE1 = test3 Description = Tests the PAL implementation of the _vsnprintf function. = Tests _vsnprintf with wide strings. -= This test is modeled after _snprintf. += This test is modeled after sprintf_s. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/CMakeLists.txt index daf7757..5662bd5 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_vsnprintf_test4 diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/test4.c rename to src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/test4.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/testinfo.dat index bdfdef8..03ff293 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/testinfo.dat +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test4/testinfo.dat @@ -11,4 +11,4 @@ EXE1 = test4 Description = Tests the PAL implementation of the _vsnprintf function. = Tests _vsnprintf with pointers. -= This test is modeled after _snprintf. += This test is modeled after sprintf_s. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/CMakeLists.txt index c255b07..9254054 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_vsnprintf_test5 diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/test5.c rename to src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/test5.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/testinfo.dat index 3cd3f7e..c384882 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/testinfo.dat +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test5/testinfo.dat @@ -11,4 +11,4 @@ EXE1 = test5 Description = Tests the PAL implementation of the _vsnprintf function. = Tests _vsnprintf with the count specifier. -= This test is modeled after _snprintf. += This test is modeled after sprintf_s. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/CMakeLists.txt index 8e041f4..d80d433 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test6.c + test6.cpp ) add_executable(paltest_vsnprintf_test6 diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/test6.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/test6.c rename to src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/test6.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/testinfo.dat index e379e0b..e375f92 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/testinfo.dat +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test6/testinfo.dat @@ -11,4 +11,4 @@ EXE1 = test6 Description = Tests the PAL implementation of the _vsnprintf function. = Tests _vsnprintf with characters. -= This test is modeled after _snprintf. += This test is modeled after sprintf_s. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/CMakeLists.txt index 01f9620..a1dc0a7 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test7.c + test7.cpp ) add_executable(paltest_vsnprintf_test7 diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/test7.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/test7.c rename to src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/test7.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/testinfo.dat index 9074940..09eb481 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/testinfo.dat +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test7/testinfo.dat @@ -11,4 +11,4 @@ EXE1 = test7 Description = Tests the PAL implementation of the _vsnprintf function. = Tests _vsnprintf with wide characters. -= This test is modeled after _snprintf. += This test is modeled after sprintf_s. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/CMakeLists.txt index 9c525de..1ca4732 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test8.c + test8.cpp ) add_executable(paltest_vsnprintf_test8 diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/test8.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/test8.c rename to src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/test8.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/testinfo.dat index 0afc334..1bdf411 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/testinfo.dat +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test8/testinfo.dat @@ -11,4 +11,4 @@ EXE1 = test8 Description = Tests the PAL implementation of the _vsnprintf function. = Tests _vsnprintf with decimal numbers. -= This test is modeled after _snprintf. += This test is modeled after sprintf_s. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/CMakeLists.txt index bfe2572..583971f 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test9.c + test9.cpp ) add_executable(paltest_vsnprintf_test9 diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/test9.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/test9.c rename to src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/test9.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/testinfo.dat index 125724a..bdaae87 100644 --- a/src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/testinfo.dat +++ b/src/pal/tests/palsuite/c_runtime/_vsnprintf/test9/testinfo.dat @@ -11,4 +11,4 @@ EXE1 = test9 Description = Tests the PAL implementation of the _vsnprintf function. = Tests _vsnprintf with integer numbers. -= This test is modeled after _snprintf. += This test is modeled after sprintf_s. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/CMakeLists.txt deleted file mode 100644 index cafb953..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -add_subdirectory(test1) -add_subdirectory(test10) -add_subdirectory(test11) -add_subdirectory(test12) -add_subdirectory(test13) -add_subdirectory(test14) -add_subdirectory(test15) -add_subdirectory(test16) -add_subdirectory(test17) -add_subdirectory(test18) -add_subdirectory(test19) -add_subdirectory(test2) -add_subdirectory(test3) -add_subdirectory(test4) -add_subdirectory(test5) -add_subdirectory(test6) -add_subdirectory(test7) -add_subdirectory(test8) -add_subdirectory(test9) - diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/_vsnwprintf.h b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/_vsnwprintf.h deleted file mode 100644 index a3a932f..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/_vsnwprintf.h +++ /dev/null @@ -1,133 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: _vsnwprintf.h -** -** Purpose: Containts common testing functions for _vsnwprintf -** -** -**==========================================================================*/ - -#ifndef ___VSNWPRINTF_H__ -#define ___VSNWPRINTF_H__ - -/* These functions leaks memory like crazy. C'est la vie. */ -int TestVsnwprintf(wchar_t* buf, size_t count, const wchar_t* format, ...) -{ - int retVal = 0; - va_list arglist; - - va_start(arglist, format); - retVal = _vsnwprintf(buf, count, format, arglist); - va_end(arglist); - - return( retVal); -} - - -void DoWStrTest(WCHAR *formatstr, WCHAR *param, WCHAR *checkstr) -{ - WCHAR buf[256] = { 0 }; - - TestVsnwprintf(buf, 256, formatstr, param); - - if (memcmp(buf, checkstr, wcslen(buf) * 2 + 2) != 0) - { - Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n" - "Expected \"%s\", got \"%s\".\n", - convertC(param), convertC(formatstr), - convertC(checkstr), convertC(buf)); - } -} - -void DoStrTest(WCHAR *formatstr, char *param, WCHAR *checkstr) -{ - WCHAR buf[256] = { 0 }; - - TestVsnwprintf(buf, 256, formatstr, param); - - if (memcmp(buf, checkstr, wcslen(buf) * 2 + 2) != 0) - { - Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n" - "Expected \"%s\", got \"%s\".\n", - param, convertC(formatstr), convertC(checkstr), - convertC(buf)); - } -} - -void DoCharTest(WCHAR *formatstr, char param, WCHAR *checkstr) -{ - WCHAR buf[256] = { 0 }; - - TestVsnwprintf(buf, 256, formatstr, param); - if (memcmp(buf, checkstr, wcslen(buf)*2 + 2) != 0) - { - Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n" - "Expected \"%s\" got \"%s\".\n", - param, param, convertC(formatstr), convertC(checkstr), - convertC(buf)); - } -} - -void DoWCharTest(WCHAR *formatstr, WCHAR param, WCHAR *checkstr) -{ - WCHAR buf[256] = { 0 }; - - TestVsnwprintf(buf, 256, formatstr, param); - if (memcmp(buf, checkstr, wcslen(buf)*2 + 2) != 0) - { - Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n" - "Expected \"%s\" got \"%s\".\n", - (char) param, param, convertC(formatstr), - convertC(checkstr), convertC(buf)); - } -} - -void DoNumTest(WCHAR *formatstr, int value, WCHAR*checkstr) -{ - WCHAR buf[256] = { 0 }; - - TestVsnwprintf(buf, 256, formatstr, value); - if (memcmp(buf, checkstr, wcslen(buf)* 2 + 2) != 0) - { - Fail("ERROR: failed to insert %#x into \"%s\"\n" - "Expected \"%s\" got \"%s\".\n", value, convertC(formatstr), - convertC(checkstr), convertC(buf)); - } -} - -void DoI64NumTest(WCHAR *formatstr, INT64 value, char *valuestr, WCHAR*checkstr) -{ - WCHAR buf[256] = { 0 }; - - TestVsnwprintf(buf, 256, formatstr, value); - if (memcmp(buf, checkstr, wcslen(buf)* 2 + 2) != 0) - { - Fail("ERROR: failed to insert %s into \"%s\"\n" - "Expected \"%s\" got \"%s\".\n", valuestr, convertC(formatstr), - convertC(checkstr), convertC(buf)); - } -} -void DoDoubleTest(WCHAR *formatstr, double value, - WCHAR *checkstr1, WCHAR *checkstr2) -{ - WCHAR buf[256] = { 0 }; - - TestVsnwprintf(buf, 256, formatstr, value); - if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 && - memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0) - { - Fail("ERROR: failed to insert %f into \"%s\"\n" - "Expected \"%s\" or \"%s\", got \"%s\".\n", - value, - convertC(formatstr), - convertC(checkstr1), - convertC(checkstr2), - convertC(buf)); - } -} - -#endif diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/CMakeLists.txt deleted file mode 100644 index 52c442d..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test1.c -) - -add_executable(paltest_vsnwprintf_test1 - ${SOURCES} -) - -add_dependencies(paltest_vsnwprintf_test1 coreclrpal) - -target_link_libraries(paltest_vsnwprintf_test1 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/test1.c deleted file mode 100644 index 0238e42..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/test1.c +++ /dev/null @@ -1,60 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: test1.c -** -** Purpose: Test #1 for the _vsnwprintf function. -** -** -**===================================================================*/ - -#include -#include "../_vsnwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - - -int __cdecl main(int argc, char *argv[]) -{ - WCHAR *checkstr; - WCHAR buf[256] = { 0 }; - int ret; - - if (PAL_Initialize(argc, argv) != 0) - { - return(FAIL); - } - - checkstr = convert("hello world"); - TestVsnwprintf(buf, 256, checkstr); - if (memcmp(checkstr, buf, wcslen(checkstr)*2+2) != 0) - { - Fail("ERROR: Expected \"%s\", got \"%s\"\n", - convertC(checkstr), convertC(buf)); - } - - TestVsnwprintf(buf, 256, convert("xxxxxxxxxxxxxxxxx")); - ret = TestVsnwprintf(buf, 8, checkstr); - if (memcmp(checkstr, buf, 16) != 0) - { - Fail("ERROR: Expected \"%8s\", got \"%8s\"\n", - convertC(checkstr), convertC(buf)); - } - if (ret >= 0) - { - Fail("ERROR: Expected negative return value, got %d.\n", ret); - } - if (buf[8] != (WCHAR) 'x') - { - Fail("ERROR: buffer overflow using \"%s\" with length 8.\n", - convertC(checkstr)); - } - - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/testinfo.dat deleted file mode 100644 index d806fb8..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test1/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _vsnwprintf -Name = Positive Test for _vsnwprintf -TYPE = DEFAULT -EXE1 = test1 -Description -= Tests the PAL implementation of the _vsnwprintf function. -= General test to see if _vsnwprintf works correctly. -= This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/CMakeLists.txt deleted file mode 100644 index 86ea1a3..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test10.c -) - -add_executable(paltest_vsnwprintf_test10 - ${SOURCES} -) - -add_dependencies(paltest_vsnwprintf_test10 coreclrpal) - -target_link_libraries(paltest_vsnwprintf_test10 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/test10.c deleted file mode 100644 index 6e188e5..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/test10.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*===================================================================== -** -** Source: test10.c -** -** Purpose: Test #10 for the _vsnwprintf function. -** -** -**===================================================================*/ - -#include -#include "../_vsnwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 42; - INT64 l = 42; - - if (PAL_Initialize(argc, argv) != 0) - { - return(FAIL); - } - - DoNumTest(convert("foo %o"), pos, convert("foo 52")); - DoNumTest(convert("foo %lo"), 0xFFFF, convert("foo 177777")); - DoNumTest(convert("foo %ho"), 0xFFFF, convert("foo 177777")); - DoNumTest(convert("foo %Lo"), pos, convert("foo 52")); - DoI64NumTest(convert("foo %I64o"), l, "42", convert("foo 52")); - DoNumTest(convert("foo %3o"), pos, convert("foo 52")); - DoNumTest(convert("foo %-3o"), pos, convert("foo 52 ")); - DoNumTest(convert("foo %.1o"), pos, convert("foo 52")); - DoNumTest(convert("foo %.3o"), pos, convert("foo 052")); - DoNumTest(convert("foo %03o"), pos, convert("foo 052")); - DoNumTest(convert("foo %#o"), pos, convert("foo 052")); - DoNumTest(convert("foo %+o"), pos, convert("foo 52")); - DoNumTest(convert("foo % o"), pos, convert("foo 52")); - DoNumTest(convert("foo %+o"), neg, convert("foo 37777777726")); - DoNumTest(convert("foo % o"), neg, convert("foo 37777777726")); - - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/testinfo.dat deleted file mode 100644 index beb5b41..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test10/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _vsnwprintf -Name = Positive Test for _vsnwprintf -TYPE = DEFAULT -EXE1 = test10 -Description -= Tests the PAL implementation of the _vsnwprintf function. -= Tests _vsnwprintf with octal numbers. -= This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/CMakeLists.txt deleted file mode 100644 index c6011dc..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test11.c -) - -add_executable(paltest_vsnwprintf_test11 - ${SOURCES} -) - -add_dependencies(paltest_vsnwprintf_test11 coreclrpal) - -target_link_libraries(paltest_vsnwprintf_test11 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/test11.c deleted file mode 100644 index af54985..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/test11.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*===================================================================== -** -** Source: test11.c -** -** Purpose: Test #11 for the _vsnwprintf function. -** -** -**===================================================================*/ - -#include -#include "../_vsnwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 42; - INT64 l = 42; - - if (PAL_Initialize(argc, argv) != 0) - { - return(FAIL); - } - - DoNumTest(convert("foo %u"), pos, convert("foo 42")); - DoNumTest(convert("foo %lu"), 0xFFFF, convert("foo 65535")); - DoNumTest(convert("foo %hu"), 0xFFFF, convert("foo 65535")); - DoNumTest(convert("foo %Lu"), pos, convert("foo 42")); - DoI64NumTest(convert("foo %I64u"), l, "42", convert("foo 42")); - DoNumTest(convert("foo %3u"), pos, convert("foo 42")); - DoNumTest(convert("foo %-3u"), pos, convert("foo 42 ")); - DoNumTest(convert("foo %.1u"), pos, convert("foo 42")); - DoNumTest(convert("foo %.3u"), pos, convert("foo 042")); - DoNumTest(convert("foo %03u"), pos, convert("foo 042")); - DoNumTest(convert("foo %#u"), pos, convert("foo 42")); - DoNumTest(convert("foo %+u"), pos, convert("foo 42")); - DoNumTest(convert("foo % u"), pos, convert("foo 42")); - DoNumTest(convert("foo %+u"), neg, convert("foo 4294967254")); - DoNumTest(convert("foo % u"), neg, convert("foo 4294967254")); - - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/testinfo.dat deleted file mode 100644 index 083b0fa..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test11/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _vsnwprintf -Name = Positive Test for _vsnwprintf -TYPE = DEFAULT -EXE1 = test11 -Description -= Tests the PAL implementation of the _vsnwprintf function. -= Tests _vsnwprintf with unsigned numbers. -= This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/CMakeLists.txt deleted file mode 100644 index bd9652c..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test12.c -) - -add_executable(paltest_vsnwprintf_test12 - ${SOURCES} -) - -add_dependencies(paltest_vsnwprintf_test12 coreclrpal) - -target_link_libraries(paltest_vsnwprintf_test12 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/test12.c deleted file mode 100644 index b593a82..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/test12.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*===================================================================== -** -** Source: test12.c -** -** Purpose: Test #12 for the _vsnwprintf function. -** -** -**===================================================================*/ - -#include -#include "../_vsnwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 0x1234ab; - INT64 l = I64(0x1234567887654321); - - if (PAL_Initialize(argc, argv) != 0) - { - return(FAIL); - } - - DoNumTest(convert("foo %x"), pos, convert("foo 1234ab")); - DoNumTest(convert("foo %lx"), pos, convert("foo 1234ab")); - DoNumTest(convert("foo %hx"), pos, convert("foo 34ab")); - DoNumTest(convert("foo %Lx"), pos, convert("foo 1234ab")); - DoI64NumTest(convert("foo %I64x"), l, "0x1234567887654321", - convert("foo 1234567887654321")); - DoNumTest(convert("foo %7x"), pos, convert("foo 1234ab")); - DoNumTest(convert("foo %-7x"), pos, convert("foo 1234ab ")); - DoNumTest(convert("foo %.1x"), pos, convert("foo 1234ab")); - DoNumTest(convert("foo %.7x"), pos, convert("foo 01234ab")); - DoNumTest(convert("foo %07x"), pos, convert("foo 01234ab")); - DoNumTest(convert("foo %#x"), pos, convert("foo 0x1234ab")); - DoNumTest(convert("foo %+x"), pos, convert("foo 1234ab")); - DoNumTest(convert("foo % x"), pos, convert("foo 1234ab")); - DoNumTest(convert("foo %+x"), neg, convert("foo ffffffd6")); - DoNumTest(convert("foo % x"), neg, convert("foo ffffffd6")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/testinfo.dat deleted file mode 100644 index a4450ed..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test12/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _vsnwprintf -Name = Positive Test for _vsnwprintf -TYPE = DEFAULT -EXE1 = test12 -Description -= Tests the PAL implementation of the _vsnwprintf function. -= Tests _vsnwprintf with hex numbers (lowercase). -= This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/CMakeLists.txt deleted file mode 100644 index c608ab8..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test13.c -) - -add_executable(paltest_vsnwprintf_test13 - ${SOURCES} -) - -add_dependencies(paltest_vsnwprintf_test13 coreclrpal) - -target_link_libraries(paltest_vsnwprintf_test13 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/test13.c deleted file mode 100644 index 59a9dc4..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/test13.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*===================================================================== -** -** Source: test13.c -** -** Purpose: Test #13 for the _vsnwprintf function. -** -** -**===================================================================*/ - -#include -#include "../_vsnwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 0x1234ab; - INT64 l = I64(0x1234567887654321); - - if (PAL_Initialize(argc, argv) != 0) - { - return(FAIL); - } - - DoNumTest(convert("foo %X"), pos, convert("foo 1234AB")); - DoNumTest(convert("foo %lX"), pos, convert("foo 1234AB")); - DoNumTest(convert("foo %hX"), pos, convert("foo 34AB")); - DoNumTest(convert("foo %LX"), pos, convert("foo 1234AB")); - DoI64NumTest(convert("foo %I64X"), l, "0x1234567887654321", - convert("foo 1234567887654321")); - DoNumTest(convert("foo %7X"), pos, convert("foo 1234AB")); - DoNumTest(convert("foo %-7X"), pos, convert("foo 1234AB ")); - DoNumTest(convert("foo %.1X"), pos, convert("foo 1234AB")); - DoNumTest(convert("foo %.7X"), pos, convert("foo 01234AB")); - DoNumTest(convert("foo %07X"), pos, convert("foo 01234AB")); - DoNumTest(convert("foo %#X"), pos, convert("foo 0X1234AB")); - DoNumTest(convert("foo %+X"), pos, convert("foo 1234AB")); - DoNumTest(convert("foo % X"), pos, convert("foo 1234AB")); - DoNumTest(convert("foo %+X"), neg, convert("foo FFFFFFD6")); - DoNumTest(convert("foo % X"), neg, convert("foo FFFFFFD6")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/testinfo.dat deleted file mode 100644 index fa54ae8..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test13/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _vsnwprintf -Name = Positive Test for _vsnwprintf -TYPE = DEFAULT -EXE1 = test13 -Description -= Tests the PAL implementation of the _vsnwprintf function. -= Tests _vsnwprintf with hex numbers (uppercase). -= This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/CMakeLists.txt deleted file mode 100644 index 3bf157a..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test14.c -) - -add_executable(paltest_vsnwprintf_test14 - ${SOURCES} -) - -add_dependencies(paltest_vsnwprintf_test14 coreclrpal) - -target_link_libraries(paltest_vsnwprintf_test14 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/test14.c deleted file mode 100644 index 633f9d6..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/test14.c +++ /dev/null @@ -1,63 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -/*===================================================================== -** -** Source: test14.c -** -** Purpose: Test #14 for the _vsnwprintf function. -** -** -**===================================================================*/ - -#include -#include "../_vsnwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - double val = 256.0; - double neg = -256.0; - - if (PAL_Initialize(argc, argv) != 0) - { - return(FAIL); - } - - DoDoubleTest(convert("foo %e"), val, convert("foo 2.560000e+002"), - convert("foo 2.560000e+02")); - DoDoubleTest(convert("foo %le"), val, convert("foo 2.560000e+002"), - convert("foo 2.560000e+02")); - DoDoubleTest(convert("foo %he"), val, convert("foo 2.560000e+002"), - convert("foo 2.560000e+02")); - DoDoubleTest(convert("foo %Le"), val, convert("foo 2.560000e+002"), - convert("foo 2.560000e+02")); - DoDoubleTest(convert("foo %I64e"), val, convert("foo 2.560000e+002"), - convert("foo 2.560000e+02")); - DoDoubleTest(convert("foo %14e"), val, convert("foo 2.560000e+002"), - convert("foo 2.560000e+02")); - DoDoubleTest(convert("foo %-14e"), val, convert("foo 2.560000e+002 "), - convert("foo 2.560000e+02 ")); - DoDoubleTest(convert("foo %.1e"), val, convert("foo 2.6e+002"), - convert("foo 2.6e+02")); - DoDoubleTest(convert("foo %.8e"), val, convert("foo 2.56000000e+002"), - convert("foo 2.56000000e+02")); - DoDoubleTest(convert("foo %014e"), val, convert("foo 02.560000e+002"), - convert("foo 002.560000e+02")); - DoDoubleTest(convert("foo %#e"), val, convert("foo 2.560000e+002"), - convert("foo 2.560000e+02")); - DoDoubleTest(convert("foo %+e"), val, convert("foo +2.560000e+002"), - convert("foo +2.560000e+02")); - DoDoubleTest(convert("foo % e"), val, convert("foo 2.560000e+002"), - convert("foo 2.560000e+02")); - DoDoubleTest(convert("foo %+e"), neg, convert("foo -2.560000e+002"), - convert("foo -2.560000e+02")); - DoDoubleTest(convert("foo % e"), neg, convert("foo -2.560000e+002"), - convert("foo -2.560000e+02")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/testinfo.dat deleted file mode 100644 index 0796f5e..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test14/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _vsnwprintf -Name = Positive Test for _vsnwprintf -TYPE = DEFAULT -EXE1 = test14 -Description -= Tests the PAL implementation of the _vsnwprintf function. -= Tests _vsnwprintf with exponential format doubles (lowercase). -= This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/CMakeLists.txt deleted file mode 100644 index eedc7bb..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test15.c -) - -add_executable(paltest_vsnwprintf_test15 - ${SOURCES} -) - -add_dependencies(paltest_vsnwprintf_test15 coreclrpal) - -target_link_libraries(paltest_vsnwprintf_test15 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/test15.c deleted file mode 100644 index 0af41fe..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/test15.c +++ /dev/null @@ -1,64 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: test15.c -** -** Purpose: Test #15 for the _vsnwprintf function. -** -** -**===================================================================*/ - -#include -#include "../_vsnwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - - -int __cdecl main(int argc, char *argv[]) -{ - double val = 256.0; - double neg = -256.0; - - if (PAL_Initialize(argc, argv) != 0) - { - return(FAIL); - } - - DoDoubleTest(convert("foo %E"), val, convert("foo 2.560000E+002"), - convert("foo 2.560000E+02")); - DoDoubleTest(convert("foo %lE"), val, convert("foo 2.560000E+002"), - convert("foo 2.560000E+02")); - DoDoubleTest(convert("foo %hE"), val, convert("foo 2.560000E+002"), - convert("foo 2.560000E+02")); - DoDoubleTest(convert("foo %LE"), val, convert("foo 2.560000E+002"), - convert("foo 2.560000E+02")); - DoDoubleTest(convert("foo %I64E"), val, convert("foo 2.560000E+002"), - convert("foo 2.560000E+02")); - DoDoubleTest(convert("foo %14E"), val, convert("foo 2.560000E+002"), - convert("foo 2.560000E+02")); - DoDoubleTest(convert("foo %-14E"), val, convert("foo 2.560000E+002 "), - convert("foo 2.560000E+02 ")); - DoDoubleTest(convert("foo %.1E"), val, convert("foo 2.6E+002"), - convert("foo 2.6E+02")); - DoDoubleTest(convert("foo %.8E"), val, convert("foo 2.56000000E+002"), - convert("foo 2.56000000E+02")); - DoDoubleTest(convert("foo %014E"), val, convert("foo 02.560000E+002"), - convert("foo 002.560000E+02")); - DoDoubleTest(convert("foo %#E"), val, convert("foo 2.560000E+002"), - convert("foo 2.560000E+02")); - DoDoubleTest(convert("foo %+E"), val, convert("foo +2.560000E+002"), - convert("foo +2.560000E+02")); - DoDoubleTest(convert("foo % E"), val, convert("foo 2.560000E+002"), - convert("foo 2.560000E+02")); - DoDoubleTest(convert("foo %+E"), neg, convert("foo -2.560000E+002"), - convert("foo -2.560000E+02")); - DoDoubleTest(convert("foo % E"), neg, convert("foo -2.560000E+002"), - convert("foo -2.560000E+002")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/testinfo.dat deleted file mode 100644 index 9de3c83..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test15/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _vsnwprintf -Name = Positive Test for _vsnwprintf -TYPE = DEFAULT -EXE1 = test15 -Description -= Tests the PAL implementation of the _vsnwprintf function. -= Tests _vsnwprintf with exponential format doubles (uppercase). -= This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/CMakeLists.txt deleted file mode 100644 index a469c49..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test16.c -) - -add_executable(paltest_vsnwprintf_test16 - ${SOURCES} -) - -add_dependencies(paltest_vsnwprintf_test16 coreclrpal) - -target_link_libraries(paltest_vsnwprintf_test16 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/test16.c deleted file mode 100644 index 77571b0..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/test16.c +++ /dev/null @@ -1,63 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -/*===================================================================== -** -** Source: test16.c -** -** Purpose: Test #16 for the _vsnwprintf function. -** -** -**===================================================================*/ - -#include -#include "../_vsnwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - double val = 2560.001; - double neg = -2560.001; - - if (PAL_Initialize(argc, argv) != 0) - { - return(FAIL); - } - - DoDoubleTest(convert("foo %f"), val, convert("foo 2560.001000"), - convert("foo 2560.001000")); - DoDoubleTest(convert("foo %lf"), val, convert("foo 2560.001000"), - convert("foo 2560.001000")); - DoDoubleTest(convert("foo %hf"), val, convert("foo 2560.001000"), - convert("foo 2560.001000")); - DoDoubleTest(convert("foo %Lf"), val, convert("foo 2560.001000"), - convert("foo 2560.001000")); - DoDoubleTest(convert("foo %I64f"), val, convert("foo 2560.001000"), - convert("foo 2560.001000")); - DoDoubleTest(convert("foo %12f"), val, convert("foo 2560.001000"), - convert("foo 2560.001000")); - DoDoubleTest(convert("foo %-12f"), val, convert("foo 2560.001000 "), - convert("foo 2560.001000 ")); - DoDoubleTest(convert("foo %.1f"), val, convert("foo 2560.0"), - convert("foo 2560.0")); - DoDoubleTest(convert("foo %.8f"), val, convert("foo 2560.00100000"), - convert("foo 2560.00100000")); - DoDoubleTest(convert("foo %012f"), val, convert("foo 02560.001000"), - convert("foo 02560.001000")); - DoDoubleTest(convert("foo %#f"), val, convert("foo 2560.001000"), - convert("foo 2560.001000")); - DoDoubleTest(convert("foo %+f"), val, convert("foo +2560.001000"), - convert("foo +2560.001000")); - DoDoubleTest(convert("foo % f"), val, convert("foo 2560.001000"), - convert("foo 2560.001000")); - DoDoubleTest(convert("foo %+f"), neg, convert("foo -2560.001000"), - convert("foo -2560.001000")); - DoDoubleTest(convert("foo % f"), neg, convert("foo -2560.001000"), - convert("foo -2560.001000")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/testinfo.dat deleted file mode 100644 index b7134c7..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test16/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _vsnwprintf -Name = Positive Test for _vsnwprintf -TYPE = DEFAULT -EXE1 = test16 -Description -= Tests the PAL implementation of the _vsnwprintf function. -= Tests _vsnwprintf with decimal point format doubles. -= This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/CMakeLists.txt deleted file mode 100644 index f429e94..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test17.c -) - -add_executable(paltest_vsnwprintf_test17 - ${SOURCES} -) - -add_dependencies(paltest_vsnwprintf_test17 coreclrpal) - -target_link_libraries(paltest_vsnwprintf_test17 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/test17.c deleted file mode 100644 index 3a9d70a..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/test17.c +++ /dev/null @@ -1,65 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: test17.c -** -** Purpose: Test #17 for the _vsnwprintf function. -** -** -**===================================================================*/ - -#include -#include "../_vsnwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - double val = 2560.001; - double neg = -2560.001; - - if (PAL_Initialize(argc, argv) != 0) - { - return(FAIL); - } - - DoDoubleTest(convert("foo %g"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %lg"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %hg"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %Lg"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %I64g"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %5g"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %-5g"), val, convert("foo 2560 "), - convert("foo 2560 ")); - DoDoubleTest(convert("foo %.1g"), val, convert("foo 3e+003"), - convert("foo 3e+03")); - DoDoubleTest(convert("foo %.2g"), val, convert("foo 2.6e+003"), - convert("foo 2.6e+03")); - DoDoubleTest(convert("foo %.12g"), val, convert("foo 2560.001"), - convert("foo 2560.001")); - DoDoubleTest(convert("foo %06g"), val, convert("foo 002560"), - convert("foo 002560")); - DoDoubleTest(convert("foo %#g"), val, convert("foo 2560.00"), - convert("foo 2560.00")); - DoDoubleTest(convert("foo %+g"), val, convert("foo +2560"), - convert("foo +2560")); - DoDoubleTest(convert("foo % g"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %+g"), neg, convert("foo -2560"), - convert("foo -2560")); - DoDoubleTest(convert("foo % g"), neg, convert("foo -2560"), - convert("foo -2560")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/testinfo.dat deleted file mode 100644 index 5d55531..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test17/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _vsnwprintf -Name = Positive Test for _vsnwprintf -TYPE = DEFAULT -EXE1 = test17 -Description -= Tests the PAL implementation of the _vsnwprintf function. -= Tests _vsnwprintf with compact format doubles (lowercase). -= This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/CMakeLists.txt deleted file mode 100644 index 25dd6a2..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test18.c -) - -add_executable(paltest_vsnwprintf_test18 - ${SOURCES} -) - -add_dependencies(paltest_vsnwprintf_test18 coreclrpal) - -target_link_libraries(paltest_vsnwprintf_test18 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/test18.c deleted file mode 100644 index 03f9870..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/test18.c +++ /dev/null @@ -1,65 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: test18.c -** -** Purpose: Test #18 for the _vsnwprintf function. -** -** -**===================================================================*/ - -#include -#include "../_vsnwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - double val = 2560.001; - double neg = -2560.001; - - if (PAL_Initialize(argc, argv) != 0) - { - return(FAIL); - } - - DoDoubleTest(convert("foo %G"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %lG"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %hG"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %LG"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %I64G"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %5G"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %-5G"), val, convert("foo 2560 "), - convert("foo 2560 ")); - DoDoubleTest(convert("foo %.1G"), val, convert("foo 3E+003"), - convert("foo 3E+03")); - DoDoubleTest(convert("foo %.2G"), val, convert("foo 2.6E+003"), - convert("foo 2.6E+03")); - DoDoubleTest(convert("foo %.12G"), val, convert("foo 2560.001"), - convert("foo 2560.001")); - DoDoubleTest(convert("foo %06G"), val, convert("foo 002560"), - convert("foo 002560")); - DoDoubleTest(convert("foo %#G"), val, convert("foo 2560.00"), - convert("foo 2560.00")); - DoDoubleTest(convert("foo %+G"), val, convert("foo +2560"), - convert("foo +2560")); - DoDoubleTest(convert("foo % G"), val, convert("foo 2560"), - convert("foo 2560")); - DoDoubleTest(convert("foo %+G"), neg, convert("foo -2560"), - convert("foo -2560")); - DoDoubleTest(convert("foo % G"), neg, convert("foo -2560"), - convert("foo -2560")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/testinfo.dat deleted file mode 100644 index f56c809..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test18/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _vsnwprintf -Name = Positive Test for _vsnwprintf -TYPE = DEFAULT -EXE1 = test18 -Description -= Tests the PAL implementation of the _vsnwprintf function. -= Tests _vsnwprintf with compact format doubles (uppercase). -= This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/CMakeLists.txt deleted file mode 100644 index 9c636b8..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test19.c -) - -add_executable(paltest_vsnwprintf_test19 - ${SOURCES} -) - -add_dependencies(paltest_vsnwprintf_test19 coreclrpal) - -target_link_libraries(paltest_vsnwprintf_test19 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/test19.c deleted file mode 100644 index fea275a..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/test19.c +++ /dev/null @@ -1,139 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: test18.c -** -** Purpose: Test #18 for the _vsnwprintf function. -** -** -**===================================================================*/ - -#include -#include "../_vsnwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -#define DOTEST(a,b,c,d,e) DoTest(a,b,(void*)c,d,e) - -void DoArgumentPrecTest(WCHAR *formatstr, int precision, void *param, - WCHAR *paramstr, WCHAR *checkstr1, WCHAR *checkstr2) -{ - WCHAR buf[256]; - - TestVsnwprintf(buf, 256, formatstr, precision, param); - if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 && - memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0) - { - Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" - "Expected \"%s\" or \"%s\", got \"%s\".\n", - paramstr, - convertC(formatstr), - precision, - convertC(checkstr1), - convertC(checkstr2), - convertC(buf)); - } -} -void DoArgumentPrecDoubleTest(WCHAR *formatstr, int precision, double param, - WCHAR *checkstr1, WCHAR *checkstr2) -{ - WCHAR buf[256]; - - TestVsnwprintf(buf, 256, formatstr, precision, param); - if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 && - memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0) - { - Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" - "Expected \"%s\" or \"%s\", got \"%s\".\n", - param, convertC(formatstr), - precision, - convertC(checkstr1), - convertC(checkstr2), - convertC(buf)); - } -} - -/* - * Uses memcmp & wcslen - */ - -int __cdecl main(int argc, char *argv[]) -{ - - if (PAL_Initialize(argc, argv) != 0) - { - return(FAIL); - } - - DoArgumentPrecTest(convert("%.*s"), 2, convert("bar"), convert("bar"), - convert("ba"), convert("ba")); - DoArgumentPrecTest(convert("%.*c"), 0, (void*)'a', convert("a"), - convert("a"), convert("a")); - DoArgumentPrecTest(convert("%.*c"), 4, (void*)'a', convert("a"), - convert("a"), convert("a")); - DoArgumentPrecTest(convert("%.*C"), 0, (void*)'a', convert("a"), - convert("a"), convert("a")); - DoArgumentPrecTest(convert("%.*C"), 4, (void*)'a', convert("a"), - convert("a"), convert("a")); - DoArgumentPrecTest(convert("%.*d"), 1, (void*)42, convert("42"), - convert("42"), convert("42")); - DoArgumentPrecTest(convert("%.*d"), 3, (void*)42, convert("42"), - convert("042"), convert("042")); - DoArgumentPrecTest(convert("%.*i"), 1, (void*)42, convert("42"), - convert("42"), convert("42")); - DoArgumentPrecTest(convert("%.*i"), 3, (void*)42, convert("42"), - convert("042"), convert("042")); - DoArgumentPrecTest(convert("%.*o"), 1, (void*)42, convert("42"), - convert("52"), convert("52")); - DoArgumentPrecTest(convert("%.*o"), 3, (void*)42, convert("42"), - convert("052"), convert("052")); - DoArgumentPrecTest(convert("%.*u"), 1, (void*)42, convert("42"), - convert("42"), convert("42")); - DoArgumentPrecTest(convert("%.*u"), 3, (void*)42, convert("42"), - convert("042"), convert("042")); - DoArgumentPrecTest(convert("%.*x"), 1, (void*)0x42, convert("0x42"), - convert("42"), convert("42")); - DoArgumentPrecTest(convert("%.*x"), 3, (void*)0x42, convert("0x42"), - convert("042"), convert("042")); - DoArgumentPrecTest(convert("%.*X"), 1, (void*)0x42, convert("0x42"), - convert("42"), convert("42")); - DoArgumentPrecTest(convert("%.*X"), 3, (void*)0x42, convert("0x42"), - convert("042"), convert("042")); - - - DoArgumentPrecDoubleTest(convert("%.*e"), 1, 2.01, convert("2.0e+000"), - convert("2.0e+00")); - DoArgumentPrecDoubleTest(convert("%.*e"), 3, 2.01, convert("2.010e+000"), - convert("2.010e+00")); - DoArgumentPrecDoubleTest(convert("%.*E"), 1, 2.01, convert("2.0E+000"), - convert("2.0E+00")); - DoArgumentPrecDoubleTest(convert("%.*E"), 3, 2.01, convert("2.010E+000"), - convert("2.010E+00")); - DoArgumentPrecDoubleTest(convert("%.*f"), 1, 2.01, convert("2.0"), - convert("2.0")); - DoArgumentPrecDoubleTest(convert("%.*f"), 3, 2.01, convert("2.010"), - convert("2.010")); - DoArgumentPrecDoubleTest(convert("%.*g"), 1, 256.01, convert("3e+002"), - convert("3e+02")); - DoArgumentPrecDoubleTest(convert("%.*g"), 3, 256.01, convert("256"), - convert("256")); - DoArgumentPrecDoubleTest(convert("%.*g"), 4, 256.01, convert("256"), - convert("256")); - DoArgumentPrecDoubleTest(convert("%.*g"), 6, 256.01, convert("256.01"), - convert("256.01")); - DoArgumentPrecDoubleTest(convert("%.*G"), 1, 256.01, convert("3E+002"), - convert("3E+02")); - DoArgumentPrecDoubleTest(convert("%.*G"), 3, 256.01, convert("256"), - convert("256")); - DoArgumentPrecDoubleTest(convert("%.*G"), 4, 256.01, convert("256"), - convert("256")); - DoArgumentPrecDoubleTest(convert("%.*G"), 6, 256.01, convert("256.01"), - convert("256.01")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/testinfo.dat deleted file mode 100644 index 77178f1..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test19/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _vsnwprintf -Name = Positive Test for _vsnwprintf -TYPE = DEFAULT -EXE1 = test19 -Description -= Tests the PAL implementation of the _vsnwprintf function. -= Tests _vsnwprintf with argument specified precision. -= This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/CMakeLists.txt deleted file mode 100644 index 817657e..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test2.c -) - -add_executable(paltest_vsnwprintf_test2 - ${SOURCES} -) - -add_dependencies(paltest_vsnwprintf_test2 coreclrpal) - -target_link_libraries(paltest_vsnwprintf_test2 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/test2.c deleted file mode 100644 index 2049995..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/test2.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*===================================================================== -** -** Source: test2.c -** -** Purpose: Test #2 for the _vsnwprintf function. -** -** -**===================================================================*/ - -#include -#include "../_vsnwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - - -int __cdecl main(int argc, char *argv[]) -{ - if (PAL_Initialize(argc, argv) != 0) - return(FAIL); - - DoWStrTest(convert("foo %s"), convert("bar"), convert("foo bar")); - DoStrTest(convert("foo %hs"), "bar", convert("foo bar")); - DoWStrTest(convert("foo %ls"), convert("bar"), convert("foo bar")); - DoWStrTest(convert("foo %ws"), convert("bar"), convert("foo bar")); - DoWStrTest(convert("foo %Ls"), convert("bar"), convert("foo bar")); - DoWStrTest(convert("foo %I64s"), convert("bar"), convert("foo bar")); - DoWStrTest(convert("foo %5s"), convert("bar"), convert("foo bar")); - DoWStrTest(convert("foo %.2s"), convert("bar"), convert("foo ba")); - DoWStrTest(convert("foo %5.2s"), convert("bar"), convert("foo ba")); - DoWStrTest(convert("foo %-5s"), convert("bar"), convert("foo bar ")); - DoWStrTest(convert("foo %05s"), convert("bar"), convert("foo 00bar")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/testinfo.dat deleted file mode 100644 index 429911b..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test2/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _vsnwprintf -Name = Positive Test for _vsnwprintf -TYPE = DEFAULT -EXE1 = test2 -Description -= Tests the PAL implementation of the _vsnwprintf function. -= Tests _vsnwprintf with strings. -= This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/CMakeLists.txt deleted file mode 100644 index 4af3e36..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test3.c -) - -add_executable(paltest_vsnwprintf_test3 - ${SOURCES} -) - -add_dependencies(paltest_vsnwprintf_test3 coreclrpal) - -target_link_libraries(paltest_vsnwprintf_test3 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/test3.c deleted file mode 100644 index 9a37d3f..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/test3.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*===================================================================== -** -** Source: test3.c -** -** Purpose: Test #3 for the _vsnwprintf function. -** -** -**===================================================================*/ - -#include -#include "../_vsnwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - - -int __cdecl main(int argc, char *argv[]) -{ - if (PAL_Initialize(argc, argv) != 0) - return(FAIL); - - DoStrTest(convert("foo %S"), "bar", convert("foo bar")); - DoStrTest(convert("foo %hS"), "bar", convert("foo bar")); - DoWStrTest(convert("foo %lS"), convert("bar"), convert("foo bar")); - DoWStrTest(convert("foo %wS"), convert("bar"), convert("foo bar")); - DoStrTest(convert("foo %LS"), "bar", convert("foo bar")); - DoStrTest(convert("foo %I64S"), "bar", convert("foo bar")); - DoStrTest(convert("foo %5S"), "bar", convert("foo bar")); - DoStrTest(convert("foo %.2S"), "bar", convert("foo ba")); - DoStrTest(convert("foo %5.2S"), "bar", convert("foo ba")); - DoStrTest(convert("foo %-5S"), "bar", convert("foo bar ")); - DoStrTest(convert("foo %05S"), "bar", convert("foo 00bar")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/testinfo.dat deleted file mode 100644 index d4e2686..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test3/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _vsnwprintf -Name = Positive Test for _vsnwprintf -TYPE = DEFAULT -EXE1 = test3 -Description -= Tests the PAL implementation of the _vsnwprintf function. -= Tests _vsnwprintf with wide strings. -= This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/CMakeLists.txt deleted file mode 100644 index b7ff9e7..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test4.c -) - -add_executable(paltest_vsnwprintf_test4 - ${SOURCES} -) - -add_dependencies(paltest_vsnwprintf_test4 coreclrpal) - -target_link_libraries(paltest_vsnwprintf_test4 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/test4.c deleted file mode 100644 index 6f39be2..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/test4.c +++ /dev/null @@ -1,121 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: test4.c -** -** Purpose: Test #4 for the _vsnwprintf function. -** -** -**===================================================================*/ - -#include -#include "../_vsnwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ -static void DoPointerTest(WCHAR *formatstr, void* param, WCHAR* paramstr, - WCHAR *checkstr1) -{ - WCHAR buf[256] = { 0 }; - - TestVsnwprintf(buf, 256, formatstr, param); - if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0) - - { - Fail("ERROR: failed to insert pointer to %#p into \"%s\"\n" - "Expected \"%s\" got \"%s\".\n", - paramstr, - convertC(formatstr), - convertC(checkstr1), - convertC(buf)); - } -} - -static void DoI64DoubleTest(WCHAR *formatstr, INT64 value, WCHAR *valuestr, - WCHAR *checkstr1) -{ - WCHAR buf[256] = { 0 }; - - TestVsnwprintf(buf, 256, formatstr, value); - if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0) - { - Fail("ERROR: failed to insert %s into \"%s\"\n" - "Expected \"%s\", got \"%s\".\n", - value, - convertC(formatstr), - convertC(checkstr1), - convertC(buf)); - } -} - -int __cdecl main(int argc, char *argv[]) -{ - void *ptr = (void*) 0x123456; - INT64 lptr = I64(0x1234567887654321); - - if (PAL_Initialize(argc, argv) != 0) - { - return(FAIL); - } - -/* -** Run only on 64 bit platforms -*/ -#if defined(BIT64) && defined(PLATFORM_UNIX) - Trace("Testing for 64 Bit Platforms \n"); - DoPointerTest(convert("%p"), NULL, convert("NULL"), convert("00000000")); - DoPointerTest(convert("%p"), ptr, convert("pointer to 0x123456"), - convert("0000000000123456")); - DoPointerTest(convert("%17p"), ptr, convert("pointer to 0x123456"), - convert(" 0000000000123456")); - DoPointerTest(convert("%17p"), ptr, convert("pointer to 0x123456"), - convert(" 0000000000123456")); - DoPointerTest(convert("%-17p"), ptr, convert("pointer to 0x123456"), - convert("0000000000123456 ")); - DoPointerTest(convert("%+p"), ptr, convert("pointer to 0x123456"), - convert("0000000000123456")); - DoPointerTest(convert("%#p"), ptr, convert("pointer to 0x123456"), - convert("0X0000000000123456")); - DoPointerTest(convert("%lp"), ptr, convert("pointer to 0x123456"), - convert("00123456")); - DoPointerTest(convert("%hp"), ptr, convert("pointer to 0x123456"), - convert("00003456")); - DoPointerTest(convert("%Lp"), ptr, convert("pointer to 0x123456"), - convert("00123456")); - DoI64DoubleTest(convert("%I64p"), lptr, - convert("pointer to 0x1234567887654321"), - convert("1234567887654321")); - -#else - Trace("Testing for Non 64 Bit Platforms \n"); - DoPointerTest(convert("%p"), NULL, convert("NULL"), convert("00000000")); - DoPointerTest(convert("%p"), ptr, convert("pointer to 0x123456"), - convert("00123456")); - DoPointerTest(convert("%9p"), ptr, convert("pointer to 0x123456"), - convert(" 00123456")); - DoPointerTest(convert("%09p"), ptr, convert("pointer to 0x123456"), - convert(" 00123456")); - DoPointerTest(convert("%-9p"), ptr, convert("pointer to 0x123456"), - convert("00123456 ")); - DoPointerTest(convert("%+p"), ptr, convert("pointer to 0x123456"), - convert("00123456")); - DoPointerTest(convert("%#p"), ptr, convert("pointer to 0x123456"), - convert("0X00123456")); - DoPointerTest(convert("%lp"), ptr, convert("pointer to 0x123456"), - convert("00123456")); - DoPointerTest(convert("%hp"), ptr, convert("pointer to 0x123456"), - convert("00003456")); - DoPointerTest(convert("%Lp"), ptr, convert("pointer to 0x123456"), - convert("00123456")); - DoI64DoubleTest(convert("%I64p"), lptr, - convert("pointer to 0x1234567887654321"), - convert("1234567887654321")); -#endif - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/testinfo.dat deleted file mode 100644 index 56f488a..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test4/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _vsnwprintf -Name = Positive Test for _vsnwprintf -TYPE = DEFAULT -EXE1 = test4 -Description -= Tests the PAL implementation of the _vsnwprintf function. -= Tests _vsnwprintf with pointers. -= This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/CMakeLists.txt deleted file mode 100644 index 9b316b9..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test5.c -) - -add_executable(paltest_vsnwprintf_test5 - ${SOURCES} -) - -add_dependencies(paltest_vsnwprintf_test5 coreclrpal) - -target_link_libraries(paltest_vsnwprintf_test5 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/test5.c deleted file mode 100644 index 224db76..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/test5.c +++ /dev/null @@ -1,81 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: test5.c -** -** Purpose: Test #5 for the _vsnwprintf function. -** -** -**===================================================================*/ - -#include -#include "../_vsnwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -static void DoTest(WCHAR *formatstr, int param, WCHAR *checkstr) -{ - WCHAR buf[256] = { 0 }; - int n = -1; - - TestVsnwprintf(buf, 256, formatstr, &n); - - if (n != param) - { - Fail("ERROR: Expected count parameter to resolve to %d, got %d\n", - param, n); - } - - if (memcmp(buf, checkstr, wcslen(buf)*2 + 2) != 0) - { - Fail("ERROR: Expected \"%s\" got \"%s\".\n", - convertC(checkstr), convertC(buf)); - } -} - -static void DoShortTest(WCHAR *formatstr, int param, WCHAR *checkstr) -{ - WCHAR buf[256] = { 0 }; - short int n = -1; - - TestVsnwprintf(buf, 256, formatstr, &n); - - if (n != param) - { - Fail("ERROR: Expected count parameter to resolve to %d, got %d\n", - param, n); - } - - if (memcmp(buf, checkstr, wcslen(buf)*2 + 2) != 0) - { - Fail("ERROR: Expected \"%s\" got \"%s\".\n", - convertC(checkstr), convertC(buf)); - } -} - -int __cdecl main(int argc, char *argv[]) -{ - if (PAL_Initialize(argc, argv) != 0) - { - return(FAIL); - } - - DoTest(convert("foo %n bar"), 4, convert("foo bar")); - DoTest(convert("foo %#n bar"), 4, convert("foo bar")); - DoTest(convert("foo % n bar"), 4, convert("foo bar")); - DoTest(convert("foo %+n bar"), 4, convert("foo bar")); - DoTest(convert("foo %-n bar"), 4, convert("foo bar")); - DoTest(convert("foo %0n bar"), 4, convert("foo bar")); - DoShortTest(convert("foo %hn bar"), 4, convert("foo bar")); - DoTest(convert("foo %ln bar"), 4, convert("foo bar")); - DoTest(convert("foo %Ln bar"), 4, convert("foo bar")); - DoTest(convert("foo %I64n bar"), 4, convert("foo bar")); - DoTest(convert("foo %20.3n bar"), 4, convert("foo bar")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/testinfo.dat deleted file mode 100644 index 35d3816..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test5/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _vsnwprintf -Name = Positive Test for _vsnwprintf -TYPE = DEFAULT -EXE1 = test5 -Description -= Tests the PAL implementation of the _vsnwprintf function. -= Tests _vsnwprintf with the count specifier. -= This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/CMakeLists.txt deleted file mode 100644 index d3fad03..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test6.c -) - -add_executable(paltest_vsnwprintf_test6 - ${SOURCES} -) - -add_dependencies(paltest_vsnwprintf_test6 coreclrpal) - -target_link_libraries(paltest_vsnwprintf_test6 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/test6.c deleted file mode 100644 index 1bd83ea..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/test6.c +++ /dev/null @@ -1,43 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: test6.c -** -** Purpose: Test #6 for the _vsnwprintf function. -** -** -**===================================================================*/ - -#include -#include "../_vsnwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - WCHAR wc = (WCHAR) 'c'; - - if (PAL_Initialize(argc, argv) != 0) - { - return(FAIL); - } - - DoWCharTest(convert("foo %c"), wc, convert("foo c")); - DoCharTest(convert("foo %hc"), 'b', convert("foo b")); - DoWCharTest(convert("foo %lc"), wc, convert("foo c")); - DoWCharTest(convert("foo %Lc"), wc, convert("foo c")); - DoWCharTest(convert("foo %I64c"), wc, convert("foo c")); - DoWCharTest(convert("foo %5c"), wc, convert("foo c")); - DoWCharTest(convert("foo %.0c"), wc, convert("foo c")); - DoWCharTest(convert("foo %-5c"), wc, convert("foo c ")); - DoWCharTest(convert("foo %05c"), wc, convert("foo 0000c")); - DoWCharTest(convert("foo % c"), wc, convert("foo c")); - DoWCharTest(convert("foo %#c"), wc, convert("foo c")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/testinfo.dat deleted file mode 100644 index 6afe96d..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test6/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _vsnwprintf -Name = Positive Test for _vsnwprintf -TYPE = DEFAULT -EXE1 = test6 -Description -= Tests the PAL implementation of the _vsnwprintf function. -= Tests _vsnwprintf with characters. -= This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/CMakeLists.txt deleted file mode 100644 index cede861..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test7.c -) - -add_executable(paltest_vsnwprintf_test7 - ${SOURCES} -) - -add_dependencies(paltest_vsnwprintf_test7 coreclrpal) - -target_link_libraries(paltest_vsnwprintf_test7 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/test7.c deleted file mode 100644 index e13798b..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/test7.c +++ /dev/null @@ -1,43 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: test7.c -** -** Purpose: Test #7 for the _vsnwprintf function. -** -** -**===================================================================*/ - -#include -#include "../_vsnwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - WCHAR wc = (WCHAR) 'c'; - - if (PAL_Initialize(argc, argv) != 0) - { - return(FAIL); - } - - DoCharTest(convert("foo %C"), 'b', convert("foo b")); - DoWCharTest(convert("foo %hC"), wc, convert("foo c")); - DoCharTest(convert("foo %lC"), 'b', convert("foo b")); - DoCharTest(convert("foo %LC"), 'b', convert("foo b")); - DoCharTest(convert("foo %I64C"), 'b', convert("foo b")); - DoCharTest(convert("foo %5C"), 'b', convert("foo b")); - DoCharTest(convert("foo %.0C"), 'b', convert("foo b")); - DoCharTest(convert("foo %-5C"), 'b', convert("foo b ")); - DoCharTest(convert("foo %05C"), 'b', convert("foo 0000b")); - DoCharTest(convert("foo % C"), 'b', convert("foo b")); - DoCharTest(convert("foo %#C"), 'b', convert("foo b")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/testinfo.dat deleted file mode 100644 index ece40aa..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test7/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _vsnwprintf -Name = Positive Test for _vsnwprintf -TYPE = DEFAULT -EXE1 = test7 -Description -= Tests the PAL implementation of the _vsnwprintf function. -= Tests _vsnwprintf with wide characters. -= This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/CMakeLists.txt deleted file mode 100644 index 846e7b9..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test8.c -) - -add_executable(paltest_vsnwprintf_test8 - ${SOURCES} -) - -add_dependencies(paltest_vsnwprintf_test8 coreclrpal) - -target_link_libraries(paltest_vsnwprintf_test8 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/test8.c deleted file mode 100644 index 8f02412..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/test8.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*===================================================================== -** -** Source: test8.c -** -** Purpose: Test #8 for the _vsnwprintf function. -** -** -**===================================================================*/ - -#include -#include "../_vsnwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 42; - INT64 l = 42; - - if (PAL_Initialize(argc, argv) != 0) - { - return(FAIL); - } - - DoNumTest(convert("foo %d"), pos, convert("foo 42")); - DoNumTest(convert("foo %ld"), 0xFFFF, convert("foo 65535")); - DoNumTest(convert("foo %hd"), 0xFFFF, convert("foo -1")); - DoNumTest(convert("foo %Ld"), pos, convert("foo 42")); - DoI64NumTest(convert("foo %I64d"), l, "42", convert("foo 42")); - DoNumTest(convert("foo %3d"), pos, convert("foo 42")); - DoNumTest(convert("foo %-3d"), pos, convert("foo 42 ")); - DoNumTest(convert("foo %.1d"), pos, convert("foo 42")); - DoNumTest(convert("foo %.3d"), pos, convert("foo 042")); - DoNumTest(convert("foo %03d"), pos, convert("foo 042")); - DoNumTest(convert("foo %#d"), pos, convert("foo 42")); - DoNumTest(convert("foo %+d"), pos, convert("foo +42")); - DoNumTest(convert("foo % d"), pos, convert("foo 42")); - DoNumTest(convert("foo %+d"), neg, convert("foo -42")); - DoNumTest(convert("foo % d"), neg, convert("foo -42")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/testinfo.dat deleted file mode 100644 index d7a567a..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test8/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _vsnwprintf -Name = Positive Test for _vsnwprintf -TYPE = DEFAULT -EXE1 = test8 -Description -= Tests the PAL implementation of the _vsnwprintf function. -= Tests _vsnwprintf with decimal numbers. -= This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/CMakeLists.txt deleted file mode 100644 index e25eded..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test9.c -) - -add_executable(paltest_vsnwprintf_test9 - ${SOURCES} -) - -add_dependencies(paltest_vsnwprintf_test9 coreclrpal) - -target_link_libraries(paltest_vsnwprintf_test9 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/test9.c deleted file mode 100644 index 7b5b6cd..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/test9.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*===================================================================== -** -** Source: test9.c -** -** Purpose: Test #9 for the _vsnwprintf function. -** -** -**===================================================================*/ - -#include -#include "../_vsnwprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 42; - INT64 l = 42; - - if (PAL_Initialize(argc, argv) != 0) - { - return(FAIL); - } - - DoNumTest(convert("foo %i"), pos, convert("foo 42")); - DoNumTest(convert("foo %li"), 0xFFFF, convert("foo 65535")); - DoNumTest(convert("foo %hi"), 0xFFFF, convert("foo -1")); - DoNumTest(convert("foo %Li"), pos, convert("foo 42")); - DoI64NumTest(convert("foo %I64i"), l, "42", convert("foo 42")); - DoNumTest(convert("foo %3i"), pos, convert("foo 42")); - DoNumTest(convert("foo %-3i"), pos, convert("foo 42 ")); - DoNumTest(convert("foo %.1i"), pos, convert("foo 42")); - DoNumTest(convert("foo %.3i"), pos, convert("foo 042")); - DoNumTest(convert("foo %03i"), pos, convert("foo 042")); - DoNumTest(convert("foo %#i"), pos, convert("foo 42")); - DoNumTest(convert("foo %+i"), pos, convert("foo +42")); - DoNumTest(convert("foo % i"), pos, convert("foo 42")); - DoNumTest(convert("foo %+i"), neg, convert("foo -42")); - DoNumTest(convert("foo % i"), neg, convert("foo -42")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/testinfo.dat deleted file mode 100644 index 726b060..0000000 --- a/src/pal/tests/palsuite/c_runtime/_vsnwprintf/test9/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _vsnwprintf -Name = Positive Test for _vsnwprintf -TYPE = DEFAULT -EXE1 = test9 -Description -= Tests the PAL implementation of the _vsnwprintf function. -= Tests _vsnwprintf with integer numbers -= This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/CMakeLists.txt new file mode 100644 index 0000000..8fe1cb6 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) +add_subdirectory(test10) +add_subdirectory(test11) +add_subdirectory(test12) +add_subdirectory(test13) +add_subdirectory(test14) +add_subdirectory(test15) +add_subdirectory(test16) +add_subdirectory(test17) +add_subdirectory(test18) +add_subdirectory(test19) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/_vsnwprintf_s.h b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/_vsnwprintf_s.h new file mode 100644 index 0000000..34cf411 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/_vsnwprintf_s.h @@ -0,0 +1,133 @@ +// 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. + +/*============================================================================ +** +** Source: _vsnwprintf_s.h +** +** Purpose: Containts common testing functions for _vsnwprintf_s +** +** +**==========================================================================*/ + +#ifndef ___VSNWPRINTF_H__ +#define ___VSNWPRINTF_H__ + +/* These functions leaks memory like crazy. C'est la vie. */ +int TestVsnwprintf_s(wchar_t* buf, size_t count, const wchar_t* format, ...) +{ + int retVal = 0; + va_list arglist; + + va_start(arglist, format); + retVal = _vsnwprintf_s(buf, count, _TRUNCATE, format, arglist); + va_end(arglist); + + return( retVal); +} + + +void DoWStrTest(const WCHAR *formatstr, WCHAR *param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + TestVsnwprintf_s(buf, 256, formatstr, param); + + if (memcmp(buf, checkstr, wcslen(buf) * 2 + 2) != 0) + { + Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n" + "Expected \"%s\", got \"%s\".\n", + convertC(param), convertC(formatstr), + convertC(checkstr), convertC(buf)); + } +} + +void DoStrTest(const WCHAR *formatstr, char *param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + TestVsnwprintf_s(buf, 256, formatstr, param); + + if (memcmp(buf, checkstr, wcslen(buf) * 2 + 2) != 0) + { + Fail("ERROR: failed to insert wide string \"%s\" into \"%s\".\n" + "Expected \"%s\", got \"%s\".\n", + param, convertC(formatstr), convertC(checkstr), + convertC(buf)); + } +} + +void DoCharTest(const WCHAR *formatstr, char param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + TestVsnwprintf_s(buf, 256, formatstr, param); + if (memcmp(buf, checkstr, wcslen(buf)*2 + 2) != 0) + { + Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + param, param, convertC(formatstr), convertC(checkstr), + convertC(buf)); + } +} + +void DoWCharTest(const WCHAR *formatstr, WCHAR param, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + TestVsnwprintf_s(buf, 256, formatstr, param); + if (memcmp(buf, checkstr, wcslen(buf)*2 + 2) != 0) + { + Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + (char) param, param, convertC(formatstr), + convertC(checkstr), convertC(buf)); + } +} + +void DoNumTest(const WCHAR *formatstr, int value, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + TestVsnwprintf_s(buf, 256, formatstr, value); + if (memcmp(buf, checkstr, wcslen(buf)* 2 + 2) != 0) + { + Fail("ERROR: failed to insert %#x into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", value, convertC(formatstr), + convertC(checkstr), convertC(buf)); + } +} + +void DoI64NumTest(const WCHAR *formatstr, INT64 value, char *valuestr, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + + TestVsnwprintf_s(buf, 256, formatstr, value); + if (memcmp(buf, checkstr, wcslen(buf)* 2 + 2) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", valuestr, convertC(formatstr), + convertC(checkstr), convertC(buf)); + } +} +void DoDoubleTest(const WCHAR *formatstr, double value, + const WCHAR *checkstr1, const WCHAR *checkstr2) +{ + WCHAR buf[256] = { 0 }; + + TestVsnwprintf_s(buf, 256, formatstr, value); + if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 && + memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\"\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + value, + convertC(formatstr), + convertC(checkstr1), + convertC(checkstr2), + convertC(buf)); + } +} + +#endif diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/CMakeLists.txt new file mode 100644 index 0000000..d124516 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.cpp +) + +add_executable(paltest_vsnwprintf_test1 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test1 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/test1.cpp b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/test1.cpp new file mode 100644 index 0000000..4a7a02e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/test1.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Test #1 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR *checkstr; + WCHAR buf[256] = { 0 }; + int ret; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + checkstr = convert("hello world"); + TestVsnwprintf_s(buf, 256, checkstr); + if (memcmp(checkstr, buf, wcslen(checkstr)*2+2) != 0) + { + Fail("ERROR: Expected \"%s\", got \"%s\"\n", + convertC(checkstr), convertC(buf)); + } + + TestVsnwprintf_s(buf, 256, convert("xxxxxxxxxxxxxxxxx")); + ret = TestVsnwprintf_s(buf, 8, checkstr); + if ((memcmp(checkstr, buf, 14)) != 0 || (buf[7] != 0)) + { + Fail("ERROR: Expected \"%8s\", got \"%8s\"\n", + convertC(checkstr), convertC(buf)); + } + if (ret >= 0) + { + Fail("ERROR: Expected negative return value, got %d.\n", ret); + } + if (buf[8] != (WCHAR) 'x') + { + Fail("ERROR: buffer overflow using \"%s\" with length 8.\n", + convertC(checkstr)); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/testinfo.dat new file mode 100644 index 0000000..450c5b9 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test1/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test1 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += General test to see if _vsnwprintf_s works correctly. += This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/CMakeLists.txt new file mode 100644 index 0000000..6367964 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test10.cpp +) + +add_executable(paltest_vsnwprintf_test10 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test10 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test10 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/test10.cpp b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/test10.cpp new file mode 100644 index 0000000..e33f228 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/test10.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*===================================================================== +** +** Source: test10.c +** +** Purpose: Test #10 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest(convert("foo %o"), pos, convert("foo 52")); + DoNumTest(convert("foo %lo"), 0xFFFF, convert("foo 177777")); + DoNumTest(convert("foo %ho"), 0xFFFF, convert("foo 177777")); + DoNumTest(convert("foo %Lo"), pos, convert("foo 52")); + DoI64NumTest(convert("foo %I64o"), l, "42", convert("foo 52")); + DoNumTest(convert("foo %3o"), pos, convert("foo 52")); + DoNumTest(convert("foo %-3o"), pos, convert("foo 52 ")); + DoNumTest(convert("foo %.1o"), pos, convert("foo 52")); + DoNumTest(convert("foo %.3o"), pos, convert("foo 052")); + DoNumTest(convert("foo %03o"), pos, convert("foo 052")); + DoNumTest(convert("foo %#o"), pos, convert("foo 052")); + DoNumTest(convert("foo %+o"), pos, convert("foo 52")); + DoNumTest(convert("foo % o"), pos, convert("foo 52")); + DoNumTest(convert("foo %+o"), neg, convert("foo 37777777726")); + DoNumTest(convert("foo % o"), neg, convert("foo 37777777726")); + + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/testinfo.dat new file mode 100644 index 0000000..59af082 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test10/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test10 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with octal numbers. += This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/CMakeLists.txt new file mode 100644 index 0000000..b45fd0e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test11.cpp +) + +add_executable(paltest_vsnwprintf_test11 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test11 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test11 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/test11.cpp b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/test11.cpp new file mode 100644 index 0000000..4e860bb --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/test11.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*===================================================================== +** +** Source: test11.c +** +** Purpose: Test #11 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest(convert("foo %u"), pos, convert("foo 42")); + DoNumTest(convert("foo %lu"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %hu"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %Lu"), pos, convert("foo 42")); + DoI64NumTest(convert("foo %I64u"), l, "42", convert("foo 42")); + DoNumTest(convert("foo %3u"), pos, convert("foo 42")); + DoNumTest(convert("foo %-3u"), pos, convert("foo 42 ")); + DoNumTest(convert("foo %.1u"), pos, convert("foo 42")); + DoNumTest(convert("foo %.3u"), pos, convert("foo 042")); + DoNumTest(convert("foo %03u"), pos, convert("foo 042")); + DoNumTest(convert("foo %#u"), pos, convert("foo 42")); + DoNumTest(convert("foo %+u"), pos, convert("foo 42")); + DoNumTest(convert("foo % u"), pos, convert("foo 42")); + DoNumTest(convert("foo %+u"), neg, convert("foo 4294967254")); + DoNumTest(convert("foo % u"), neg, convert("foo 4294967254")); + + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/testinfo.dat new file mode 100644 index 0000000..10c0014 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test11/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test11 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with unsigned numbers. += This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/CMakeLists.txt new file mode 100644 index 0000000..2a15b19 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test12.cpp +) + +add_executable(paltest_vsnwprintf_test12 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test12 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test12 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/test12.cpp b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/test12.cpp new file mode 100644 index 0000000..2dcfcf5 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/test12.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*===================================================================== +** +** Source: test12.c +** +** Purpose: Test #12 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest(convert("foo %x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %lx"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %hx"), pos, convert("foo 34ab")); + DoNumTest(convert("foo %Lx"), pos, convert("foo 1234ab")); + DoI64NumTest(convert("foo %I64x"), l, "0x1234567887654321", + convert("foo 1234567887654321")); + DoNumTest(convert("foo %7x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %-7x"), pos, convert("foo 1234ab ")); + DoNumTest(convert("foo %.1x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %.7x"), pos, convert("foo 01234ab")); + DoNumTest(convert("foo %07x"), pos, convert("foo 01234ab")); + DoNumTest(convert("foo %#x"), pos, convert("foo 0x1234ab")); + DoNumTest(convert("foo %+x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo % x"), pos, convert("foo 1234ab")); + DoNumTest(convert("foo %+x"), neg, convert("foo ffffffd6")); + DoNumTest(convert("foo % x"), neg, convert("foo ffffffd6")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/testinfo.dat new file mode 100644 index 0000000..de08989 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test12/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test12 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with hex numbers (lowercase). += This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/CMakeLists.txt new file mode 100644 index 0000000..01ab97c --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test13.cpp +) + +add_executable(paltest_vsnwprintf_test13 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test13 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test13 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/test13.cpp b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/test13.cpp new file mode 100644 index 0000000..c95278a --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/test13.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*===================================================================== +** +** Source: test13.c +** +** Purpose: Test #13 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest(convert("foo %X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %lX"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %hX"), pos, convert("foo 34AB")); + DoNumTest(convert("foo %LX"), pos, convert("foo 1234AB")); + DoI64NumTest(convert("foo %I64X"), l, "0x1234567887654321", + convert("foo 1234567887654321")); + DoNumTest(convert("foo %7X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %-7X"), pos, convert("foo 1234AB ")); + DoNumTest(convert("foo %.1X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %.7X"), pos, convert("foo 01234AB")); + DoNumTest(convert("foo %07X"), pos, convert("foo 01234AB")); + DoNumTest(convert("foo %#X"), pos, convert("foo 0X1234AB")); + DoNumTest(convert("foo %+X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo % X"), pos, convert("foo 1234AB")); + DoNumTest(convert("foo %+X"), neg, convert("foo FFFFFFD6")); + DoNumTest(convert("foo % X"), neg, convert("foo FFFFFFD6")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/testinfo.dat new file mode 100644 index 0000000..94479d5 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test13/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test13 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with hex numbers (uppercase). += This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/CMakeLists.txt new file mode 100644 index 0000000..c6c9903 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test14.cpp +) + +add_executable(paltest_vsnwprintf_test14 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test14 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test14 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/test14.cpp b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/test14.cpp new file mode 100644 index 0000000..cab1b24 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/test14.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*===================================================================== +** +** Source: test14.c +** +** Purpose: Test #14 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest(convert("foo %e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %le"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %he"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %Le"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %I64e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %14e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %-14e"), val, convert("foo 2.560000e+002 "), + convert("foo 2.560000e+02 ")); + DoDoubleTest(convert("foo %.1e"), val, convert("foo 2.6e+002"), + convert("foo 2.6e+02")); + DoDoubleTest(convert("foo %.8e"), val, convert("foo 2.56000000e+002"), + convert("foo 2.56000000e+02")); + DoDoubleTest(convert("foo %014e"), val, convert("foo 02.560000e+002"), + convert("foo 002.560000e+02")); + DoDoubleTest(convert("foo %#e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %+e"), val, convert("foo +2.560000e+002"), + convert("foo +2.560000e+02")); + DoDoubleTest(convert("foo % e"), val, convert("foo 2.560000e+002"), + convert("foo 2.560000e+02")); + DoDoubleTest(convert("foo %+e"), neg, convert("foo -2.560000e+002"), + convert("foo -2.560000e+02")); + DoDoubleTest(convert("foo % e"), neg, convert("foo -2.560000e+002"), + convert("foo -2.560000e+02")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/testinfo.dat new file mode 100644 index 0000000..0d46d97 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test14/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test14 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with exponential format doubles (lowercase). += This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/CMakeLists.txt new file mode 100644 index 0000000..e1a32b1 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test15.cpp +) + +add_executable(paltest_vsnwprintf_test15 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test15 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test15 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/test15.cpp b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/test15.cpp new file mode 100644 index 0000000..d573899 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/test15.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. +// See the LICENSE file in the project root for more information. + +/*===================================================================== +** +** Source: test15.c +** +** Purpose: Test #15 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest(convert("foo %E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %lE"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %hE"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %LE"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %I64E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %14E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %-14E"), val, convert("foo 2.560000E+002 "), + convert("foo 2.560000E+02 ")); + DoDoubleTest(convert("foo %.1E"), val, convert("foo 2.6E+002"), + convert("foo 2.6E+02")); + DoDoubleTest(convert("foo %.8E"), val, convert("foo 2.56000000E+002"), + convert("foo 2.56000000E+02")); + DoDoubleTest(convert("foo %014E"), val, convert("foo 02.560000E+002"), + convert("foo 002.560000E+02")); + DoDoubleTest(convert("foo %#E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %+E"), val, convert("foo +2.560000E+002"), + convert("foo +2.560000E+02")); + DoDoubleTest(convert("foo % E"), val, convert("foo 2.560000E+002"), + convert("foo 2.560000E+02")); + DoDoubleTest(convert("foo %+E"), neg, convert("foo -2.560000E+002"), + convert("foo -2.560000E+02")); + DoDoubleTest(convert("foo % E"), neg, convert("foo -2.560000E+002"), + convert("foo -2.560000E+002")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/testinfo.dat new file mode 100644 index 0000000..7737f49 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test15/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test15 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with exponential format doubles (uppercase). += This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/CMakeLists.txt new file mode 100644 index 0000000..9e2b25b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test16.cpp +) + +add_executable(paltest_vsnwprintf_test16 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test16 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test16 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/test16.cpp b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/test16.cpp new file mode 100644 index 0000000..72c546e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/test16.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*===================================================================== +** +** Source: test16.c +** +** Purpose: Test #16 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest(convert("foo %f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %lf"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %hf"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %Lf"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %I64f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %12f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %-12f"), val, convert("foo 2560.001000 "), + convert("foo 2560.001000 ")); + DoDoubleTest(convert("foo %.1f"), val, convert("foo 2560.0"), + convert("foo 2560.0")); + DoDoubleTest(convert("foo %.8f"), val, convert("foo 2560.00100000"), + convert("foo 2560.00100000")); + DoDoubleTest(convert("foo %012f"), val, convert("foo 02560.001000"), + convert("foo 02560.001000")); + DoDoubleTest(convert("foo %#f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %+f"), val, convert("foo +2560.001000"), + convert("foo +2560.001000")); + DoDoubleTest(convert("foo % f"), val, convert("foo 2560.001000"), + convert("foo 2560.001000")); + DoDoubleTest(convert("foo %+f"), neg, convert("foo -2560.001000"), + convert("foo -2560.001000")); + DoDoubleTest(convert("foo % f"), neg, convert("foo -2560.001000"), + convert("foo -2560.001000")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/testinfo.dat new file mode 100644 index 0000000..9aec1c0 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test16/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test16 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with decimal point format doubles. += This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/CMakeLists.txt new file mode 100644 index 0000000..2d8ba31 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test17.cpp +) + +add_executable(paltest_vsnwprintf_test17 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test17 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test17 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/test17.cpp b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/test17.cpp new file mode 100644 index 0000000..e6860b9 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/test17.cpp @@ -0,0 +1,65 @@ +// 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. + +/*===================================================================== +** +** Source: test17.c +** +** Purpose: Test #17 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest(convert("foo %g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %lg"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %hg"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %Lg"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %I64g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %5g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %-5g"), val, convert("foo 2560 "), + convert("foo 2560 ")); + DoDoubleTest(convert("foo %.1g"), val, convert("foo 3e+003"), + convert("foo 3e+03")); + DoDoubleTest(convert("foo %.2g"), val, convert("foo 2.6e+003"), + convert("foo 2.6e+03")); + DoDoubleTest(convert("foo %.12g"), val, convert("foo 2560.001"), + convert("foo 2560.001")); + DoDoubleTest(convert("foo %06g"), val, convert("foo 002560"), + convert("foo 002560")); + DoDoubleTest(convert("foo %#g"), val, convert("foo 2560.00"), + convert("foo 2560.00")); + DoDoubleTest(convert("foo %+g"), val, convert("foo +2560"), + convert("foo +2560")); + DoDoubleTest(convert("foo % g"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %+g"), neg, convert("foo -2560"), + convert("foo -2560")); + DoDoubleTest(convert("foo % g"), neg, convert("foo -2560"), + convert("foo -2560")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/testinfo.dat new file mode 100644 index 0000000..1487b7a --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test17/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test17 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with compact format doubles (lowercase). += This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/CMakeLists.txt new file mode 100644 index 0000000..503856c --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test18.cpp +) + +add_executable(paltest_vsnwprintf_test18 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test18 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test18 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/test18.cpp b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/test18.cpp new file mode 100644 index 0000000..a164edb --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/test18.cpp @@ -0,0 +1,65 @@ +// 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. + +/*===================================================================== +** +** Source: test18.c +** +** Purpose: Test #18 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoDoubleTest(convert("foo %G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %lG"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %hG"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %LG"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %I64G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %5G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %-5G"), val, convert("foo 2560 "), + convert("foo 2560 ")); + DoDoubleTest(convert("foo %.1G"), val, convert("foo 3E+003"), + convert("foo 3E+03")); + DoDoubleTest(convert("foo %.2G"), val, convert("foo 2.6E+003"), + convert("foo 2.6E+03")); + DoDoubleTest(convert("foo %.12G"), val, convert("foo 2560.001"), + convert("foo 2560.001")); + DoDoubleTest(convert("foo %06G"), val, convert("foo 002560"), + convert("foo 002560")); + DoDoubleTest(convert("foo %#G"), val, convert("foo 2560.00"), + convert("foo 2560.00")); + DoDoubleTest(convert("foo %+G"), val, convert("foo +2560"), + convert("foo +2560")); + DoDoubleTest(convert("foo % G"), val, convert("foo 2560"), + convert("foo 2560")); + DoDoubleTest(convert("foo %+G"), neg, convert("foo -2560"), + convert("foo -2560")); + DoDoubleTest(convert("foo % G"), neg, convert("foo -2560"), + convert("foo -2560")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/testinfo.dat new file mode 100644 index 0000000..54c4e87 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test18/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test18 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with compact format doubles (uppercase). += This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/CMakeLists.txt new file mode 100644 index 0000000..68485ef --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test19.cpp +) + +add_executable(paltest_vsnwprintf_test19 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test19 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test19 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/test19.cpp b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/test19.cpp new file mode 100644 index 0000000..c2a8547 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/test19.cpp @@ -0,0 +1,139 @@ +// 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. + +/*===================================================================== +** +** Source: test18.c +** +** Purpose: Test #18 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +#define DOTEST(a,b,c,d,e) DoTest(a,b,(void*)c,d,e) + +void DoArgumentPrecTest(WCHAR *formatstr, int precision, void *param, + WCHAR *paramstr, WCHAR *checkstr1, WCHAR *checkstr2) +{ + WCHAR buf[256]; + + TestVsnwprintf_s(buf, 256, formatstr, precision, param); + if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 && + memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + paramstr, + convertC(formatstr), + precision, + convertC(checkstr1), + convertC(checkstr2), + convertC(buf)); + } +} +void DoArgumentPrecDoubleTest(WCHAR *formatstr, int precision, double param, + WCHAR *checkstr1, WCHAR *checkstr2) +{ + WCHAR buf[256]; + + TestVsnwprintf_s(buf, 256, formatstr, precision, param); + if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 && + memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + param, convertC(formatstr), + precision, + convertC(checkstr1), + convertC(checkstr2), + convertC(buf)); + } +} + +/* + * Uses memcmp & wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoArgumentPrecTest(convert("%.*s"), 2, (void*)convert("bar"), convert("bar"), + convert("ba"), convert("ba")); + DoArgumentPrecTest(convert("%.*c"), 0, (void*)'a', convert("a"), + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*c"), 4, (void*)'a', convert("a"), + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*C"), 0, (void*)'a', convert("a"), + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*C"), 4, (void*)'a', convert("a"), + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*d"), 1, (void*)42, convert("42"), + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*d"), 3, (void*)42, convert("42"), + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*i"), 1, (void*)42, convert("42"), + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*i"), 3, (void*)42, convert("42"), + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*o"), 1, (void*)42, convert("42"), + convert("52"), convert("52")); + DoArgumentPrecTest(convert("%.*o"), 3, (void*)42, convert("42"), + convert("052"), convert("052")); + DoArgumentPrecTest(convert("%.*u"), 1, (void*)42, convert("42"), + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*u"), 3, (void*)42, convert("42"), + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*x"), 1, (void*)0x42, convert("0x42"), + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*x"), 3, (void*)0x42, convert("0x42"), + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*X"), 1, (void*)0x42, convert("0x42"), + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*X"), 3, (void*)0x42, convert("0x42"), + convert("042"), convert("042")); + + + DoArgumentPrecDoubleTest(convert("%.*e"), 1, 2.01, convert("2.0e+000"), + convert("2.0e+00")); + DoArgumentPrecDoubleTest(convert("%.*e"), 3, 2.01, convert("2.010e+000"), + convert("2.010e+00")); + DoArgumentPrecDoubleTest(convert("%.*E"), 1, 2.01, convert("2.0E+000"), + convert("2.0E+00")); + DoArgumentPrecDoubleTest(convert("%.*E"), 3, 2.01, convert("2.010E+000"), + convert("2.010E+00")); + DoArgumentPrecDoubleTest(convert("%.*f"), 1, 2.01, convert("2.0"), + convert("2.0")); + DoArgumentPrecDoubleTest(convert("%.*f"), 3, 2.01, convert("2.010"), + convert("2.010")); + DoArgumentPrecDoubleTest(convert("%.*g"), 1, 256.01, convert("3e+002"), + convert("3e+02")); + DoArgumentPrecDoubleTest(convert("%.*g"), 3, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*g"), 4, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*g"), 6, 256.01, convert("256.01"), + convert("256.01")); + DoArgumentPrecDoubleTest(convert("%.*G"), 1, 256.01, convert("3E+002"), + convert("3E+02")); + DoArgumentPrecDoubleTest(convert("%.*G"), 3, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*G"), 4, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*G"), 6, 256.01, convert("256.01"), + convert("256.01")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/testinfo.dat new file mode 100644 index 0000000..2913e30 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test19/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test19 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with argument specified precision. += This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/CMakeLists.txt new file mode 100644 index 0000000..a512be6 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test2.cpp +) + +add_executable(paltest_vsnwprintf_test2 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test2 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test2 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/test2.cpp b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/test2.cpp new file mode 100644 index 0000000..18e5adf --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/test2.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*===================================================================== +** +** Source: test2.c +** +** Purpose: Test #2 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoWStrTest(convert("foo %s"), convert("bar"), convert("foo bar")); + DoStrTest(convert("foo %hs"), "bar", convert("foo bar")); + DoWStrTest(convert("foo %ls"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %ws"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %Ls"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %I64s"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %5s"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %.2s"), convert("bar"), convert("foo ba")); + DoWStrTest(convert("foo %5.2s"), convert("bar"), convert("foo ba")); + DoWStrTest(convert("foo %-5s"), convert("bar"), convert("foo bar ")); + DoWStrTest(convert("foo %05s"), convert("bar"), convert("foo 00bar")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/testinfo.dat new file mode 100644 index 0000000..5b9b629 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test2/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test2 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with strings. += This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/CMakeLists.txt new file mode 100644 index 0000000..7991c25 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test3.cpp +) + +add_executable(paltest_vsnwprintf_test3 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test3 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test3 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/test3.cpp b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/test3.cpp new file mode 100644 index 0000000..5e2bfa2 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/test3.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*===================================================================== +** +** Source: test3.c +** +** Purpose: Test #3 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoStrTest(convert("foo %S"), "bar", convert("foo bar")); + DoStrTest(convert("foo %hS"), "bar", convert("foo bar")); + DoWStrTest(convert("foo %lS"), convert("bar"), convert("foo bar")); + DoWStrTest(convert("foo %wS"), convert("bar"), convert("foo bar")); + DoStrTest(convert("foo %LS"), "bar", convert("foo bar")); + DoStrTest(convert("foo %I64S"), "bar", convert("foo bar")); + DoStrTest(convert("foo %5S"), "bar", convert("foo bar")); + DoStrTest(convert("foo %.2S"), "bar", convert("foo ba")); + DoStrTest(convert("foo %5.2S"), "bar", convert("foo ba")); + DoStrTest(convert("foo %-5S"), "bar", convert("foo bar ")); + DoStrTest(convert("foo %05S"), "bar", convert("foo 00bar")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/testinfo.dat new file mode 100644 index 0000000..6216069 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test3/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test3 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with wide strings. += This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/CMakeLists.txt new file mode 100644 index 0000000..18f5d02 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test4.cpp +) + +add_executable(paltest_vsnwprintf_test4 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test4 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test4 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/test4.cpp b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/test4.cpp new file mode 100644 index 0000000..3627ff8 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/test4.cpp @@ -0,0 +1,121 @@ +// 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. + +/*===================================================================== +** +** Source: test4.c +** +** Purpose: Test #4 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ +static void DoPointerTest(WCHAR *formatstr, void* param, WCHAR* paramstr, + WCHAR *checkstr1) +{ + WCHAR buf[256] = { 0 }; + + TestVsnwprintf_s(buf, 256, formatstr, param); + if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0) + + { + Fail("ERROR: failed to insert pointer to %#p into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + paramstr, + convertC(formatstr), + convertC(checkstr1), + convertC(buf)); + } +} + +static void DoI64DoubleTest(WCHAR *formatstr, INT64 value, WCHAR *valuestr, + WCHAR *checkstr1) +{ + WCHAR buf[256] = { 0 }; + + TestVsnwprintf_s(buf, 256, formatstr, value); + if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\", got \"%s\".\n", + value, + convertC(formatstr), + convertC(checkstr1), + convertC(buf)); + } +} + +int __cdecl main(int argc, char *argv[]) +{ + void *ptr = (void*) 0x123456; + INT64 lptr = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + +/* +** Run only on 64 bit platforms +*/ +#if defined(BIT64) && defined(PLATFORM_UNIX) + Trace("Testing for 64 Bit Platforms \n"); + DoPointerTest(convert("%p"), NULL, convert("NULL"), convert("00000000")); + DoPointerTest(convert("%p"), ptr, convert("pointer to 0x123456"), + convert("0000000000123456")); + DoPointerTest(convert("%17p"), ptr, convert("pointer to 0x123456"), + convert(" 0000000000123456")); + DoPointerTest(convert("%17p"), ptr, convert("pointer to 0x123456"), + convert(" 0000000000123456")); + DoPointerTest(convert("%-17p"), ptr, convert("pointer to 0x123456"), + convert("0000000000123456 ")); + DoPointerTest(convert("%+p"), ptr, convert("pointer to 0x123456"), + convert("0000000000123456")); + DoPointerTest(convert("%#p"), ptr, convert("pointer to 0x123456"), + convert("0X0000000000123456")); + DoPointerTest(convert("%lp"), ptr, convert("pointer to 0x123456"), + convert("00123456")); + DoPointerTest(convert("%hp"), ptr, convert("pointer to 0x123456"), + convert("00003456")); + DoPointerTest(convert("%Lp"), ptr, convert("pointer to 0x123456"), + convert("00123456")); + DoI64DoubleTest(convert("%I64p"), lptr, + convert("pointer to 0x1234567887654321"), + convert("1234567887654321")); + +#else + Trace("Testing for Non 64 Bit Platforms \n"); + DoPointerTest(convert("%p"), NULL, convert("NULL"), convert("00000000")); + DoPointerTest(convert("%p"), ptr, convert("pointer to 0x123456"), + convert("00123456")); + DoPointerTest(convert("%9p"), ptr, convert("pointer to 0x123456"), + convert(" 00123456")); + DoPointerTest(convert("%09p"), ptr, convert("pointer to 0x123456"), + convert(" 00123456")); + DoPointerTest(convert("%-9p"), ptr, convert("pointer to 0x123456"), + convert("00123456 ")); + DoPointerTest(convert("%+p"), ptr, convert("pointer to 0x123456"), + convert("00123456")); + DoPointerTest(convert("%#p"), ptr, convert("pointer to 0x123456"), + convert("0X00123456")); + DoPointerTest(convert("%lp"), ptr, convert("pointer to 0x123456"), + convert("00123456")); + DoPointerTest(convert("%hp"), ptr, convert("pointer to 0x123456"), + convert("00003456")); + DoPointerTest(convert("%Lp"), ptr, convert("pointer to 0x123456"), + convert("00123456")); + DoI64DoubleTest(convert("%I64p"), lptr, + convert("pointer to 0x1234567887654321"), + convert("1234567887654321")); +#endif + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/testinfo.dat new file mode 100644 index 0000000..9fbfcba --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test4/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test4 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with pointers. += This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/CMakeLists.txt new file mode 100644 index 0000000..c431da4 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test6.cpp +) + +add_executable(paltest_vsnwprintf_test6 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test6 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test6 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/test6.cpp b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/test6.cpp new file mode 100644 index 0000000..ecba585 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/test6.cpp @@ -0,0 +1,43 @@ +// 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. + +/*===================================================================== +** +** Source: test6.c +** +** Purpose: Test #6 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wc = (WCHAR) 'c'; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoWCharTest(convert("foo %c"), wc, convert("foo c")); + DoCharTest(convert("foo %hc"), 'b', convert("foo b")); + DoWCharTest(convert("foo %lc"), wc, convert("foo c")); + DoWCharTest(convert("foo %Lc"), wc, convert("foo c")); + DoWCharTest(convert("foo %I64c"), wc, convert("foo c")); + DoWCharTest(convert("foo %5c"), wc, convert("foo c")); + DoWCharTest(convert("foo %.0c"), wc, convert("foo c")); + DoWCharTest(convert("foo %-5c"), wc, convert("foo c ")); + DoWCharTest(convert("foo %05c"), wc, convert("foo 0000c")); + DoWCharTest(convert("foo % c"), wc, convert("foo c")); + DoWCharTest(convert("foo %#c"), wc, convert("foo c")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/testinfo.dat new file mode 100644 index 0000000..1b411d7 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test6/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test6 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with characters. += This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/CMakeLists.txt new file mode 100644 index 0000000..5759b83 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test7.cpp +) + +add_executable(paltest_vsnwprintf_test7 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test7 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test7 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/test7.cpp b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/test7.cpp new file mode 100644 index 0000000..519657a --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/test7.cpp @@ -0,0 +1,43 @@ +// 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. + +/*===================================================================== +** +** Source: test7.c +** +** Purpose: Test #7 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wc = (WCHAR) 'c'; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoCharTest(convert("foo %C"), 'b', convert("foo b")); + DoWCharTest(convert("foo %hC"), wc, convert("foo c")); + DoCharTest(convert("foo %lC"), 'b', convert("foo b")); + DoCharTest(convert("foo %LC"), 'b', convert("foo b")); + DoCharTest(convert("foo %I64C"), 'b', convert("foo b")); + DoCharTest(convert("foo %5C"), 'b', convert("foo b")); + DoCharTest(convert("foo %.0C"), 'b', convert("foo b")); + DoCharTest(convert("foo %-5C"), 'b', convert("foo b ")); + DoCharTest(convert("foo %05C"), 'b', convert("foo 0000b")); + DoCharTest(convert("foo % C"), 'b', convert("foo b")); + DoCharTest(convert("foo %#C"), 'b', convert("foo b")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/testinfo.dat new file mode 100644 index 0000000..8f2ccf0 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test7/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test7 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with wide characters. += This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/CMakeLists.txt new file mode 100644 index 0000000..5e8a628 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test8.cpp +) + +add_executable(paltest_vsnwprintf_test8 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test8 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test8 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/test8.cpp b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/test8.cpp new file mode 100644 index 0000000..15641f7 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/test8.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*===================================================================== +** +** Source: test8.c +** +** Purpose: Test #8 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest(convert("foo %d"), pos, convert("foo 42")); + DoNumTest(convert("foo %ld"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %hd"), 0xFFFF, convert("foo -1")); + DoNumTest(convert("foo %Ld"), pos, convert("foo 42")); + DoI64NumTest(convert("foo %I64d"), l, "42", convert("foo 42")); + DoNumTest(convert("foo %3d"), pos, convert("foo 42")); + DoNumTest(convert("foo %-3d"), pos, convert("foo 42 ")); + DoNumTest(convert("foo %.1d"), pos, convert("foo 42")); + DoNumTest(convert("foo %.3d"), pos, convert("foo 042")); + DoNumTest(convert("foo %03d"), pos, convert("foo 042")); + DoNumTest(convert("foo %#d"), pos, convert("foo 42")); + DoNumTest(convert("foo %+d"), pos, convert("foo +42")); + DoNumTest(convert("foo % d"), pos, convert("foo 42")); + DoNumTest(convert("foo %+d"), neg, convert("foo -42")); + DoNumTest(convert("foo % d"), neg, convert("foo -42")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/testinfo.dat new file mode 100644 index 0000000..905740c --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test8/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test8 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with decimal numbers. += This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/CMakeLists.txt new file mode 100644 index 0000000..323365d --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test9.cpp +) + +add_executable(paltest_vsnwprintf_test9 + ${SOURCES} +) + +add_dependencies(paltest_vsnwprintf_test9 coreclrpal) + +target_link_libraries(paltest_vsnwprintf_test9 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/test9.cpp b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/test9.cpp new file mode 100644 index 0000000..38f6be2 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/test9.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*===================================================================== +** +** Source: test9.c +** +** Purpose: Test #9 for the _vsnwprintf_s function. +** +** +**===================================================================*/ + +#include +#include "../_vsnwprintf_s.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoNumTest(convert("foo %i"), pos, convert("foo 42")); + DoNumTest(convert("foo %li"), 0xFFFF, convert("foo 65535")); + DoNumTest(convert("foo %hi"), 0xFFFF, convert("foo -1")); + DoNumTest(convert("foo %Li"), pos, convert("foo 42")); + DoI64NumTest(convert("foo %I64i"), l, "42", convert("foo 42")); + DoNumTest(convert("foo %3i"), pos, convert("foo 42")); + DoNumTest(convert("foo %-3i"), pos, convert("foo 42 ")); + DoNumTest(convert("foo %.1i"), pos, convert("foo 42")); + DoNumTest(convert("foo %.3i"), pos, convert("foo 042")); + DoNumTest(convert("foo %03i"), pos, convert("foo 042")); + DoNumTest(convert("foo %#i"), pos, convert("foo 42")); + DoNumTest(convert("foo %+i"), pos, convert("foo +42")); + DoNumTest(convert("foo % i"), pos, convert("foo 42")); + DoNumTest(convert("foo %+i"), neg, convert("foo -42")); + DoNumTest(convert("foo % i"), neg, convert("foo -42")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/testinfo.dat new file mode 100644 index 0000000..974efdb --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/_vsnwprintf_s/test9/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = _vsnwprintf_s +Name = Positive Test for _vsnwprintf_s +TYPE = DEFAULT +EXE1 = test9 +Description += Tests the PAL implementation of the _vsnwprintf_s function. += Tests _vsnwprintf_s with integer numbers += This test is modeled after _snwprintf. diff --git a/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/CMakeLists.txt index 5f085cc..023b777 100644 --- a/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wcsicmp_test1 diff --git a/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/_wcsicmp/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/CMakeLists.txt index a78098f..b9df132 100644 --- a/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wcslwr_test1 diff --git a/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_wcslwr/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_wcslwr/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/_wcslwr/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/CMakeLists.txt index afd3560..ea22daa 100644 --- a/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wcsnicmp_test1 diff --git a/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/_wcsnicmp/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wfopen/test1/CMakeLists.txt index 96df58e..f7aa22d 100644 --- a/src/pal/tests/palsuite/c_runtime/_wfopen/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wfopen_test1 diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_wfopen/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_wfopen/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/_wfopen/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wfopen/test2/CMakeLists.txt index 47203d8..3159889 100644 --- a/src/pal/tests/palsuite/c_runtime/_wfopen/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_wfopen_test2 diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test2/test2.c b/src/pal/tests/palsuite/c_runtime/_wfopen/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_wfopen/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/_wfopen/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wfopen/test3/CMakeLists.txt index deec8bb..06d0941 100644 --- a/src/pal/tests/palsuite/c_runtime/_wfopen/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_wfopen_test3 diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test3/test3.c b/src/pal/tests/palsuite/c_runtime/_wfopen/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_wfopen/test3/test3.c rename to src/pal/tests/palsuite/c_runtime/_wfopen/test3/test3.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wfopen/test4/CMakeLists.txt index e93cdd5..8253d75 100644 --- a/src/pal/tests/palsuite/c_runtime/_wfopen/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_wfopen_test4 diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test4/test4.c b/src/pal/tests/palsuite/c_runtime/_wfopen/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_wfopen/test4/test4.c rename to src/pal/tests/palsuite/c_runtime/_wfopen/test4/test4.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wfopen/test5/CMakeLists.txt index 1530416..8b3d064 100644 --- a/src/pal/tests/palsuite/c_runtime/_wfopen/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_wfopen_test5 diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test5/test5.c b/src/pal/tests/palsuite/c_runtime/_wfopen/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_wfopen/test5/test5.c rename to src/pal/tests/palsuite/c_runtime/_wfopen/test5/test5.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wfopen/test6/CMakeLists.txt index c401c6f..bf1eaec 100644 --- a/src/pal/tests/palsuite/c_runtime/_wfopen/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test6.c + test6.cpp ) add_executable(paltest_wfopen_test6 diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test6/test6.c b/src/pal/tests/palsuite/c_runtime/_wfopen/test6/test6.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_wfopen/test6/test6.c rename to src/pal/tests/palsuite/c_runtime/_wfopen/test6/test6.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wfopen/test7/CMakeLists.txt index 47f4804..5d04528 100644 --- a/src/pal/tests/palsuite/c_runtime/_wfopen/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_wfopen/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test7.c + test7.cpp ) add_executable(paltest_wfopen_test7 diff --git a/src/pal/tests/palsuite/c_runtime/_wfopen/test7/test7.c b/src/pal/tests/palsuite/c_runtime/_wfopen/test7/test7.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_wfopen/test7/test7.c rename to src/pal/tests/palsuite/c_runtime/_wfopen/test7/test7.cpp diff --git a/src/pal/tests/palsuite/c_runtime/_wmakepath/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wmakepath/CMakeLists.txt deleted file mode 100644 index f6aa0cb..0000000 --- a/src/pal/tests/palsuite/c_runtime/_wmakepath/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -add_subdirectory(test1) - diff --git a/src/pal/tests/palsuite/c_runtime/_wmakepath/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wmakepath/test1/CMakeLists.txt deleted file mode 100644 index 343cb41..0000000 --- a/src/pal/tests/palsuite/c_runtime/_wmakepath/test1/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test1.c -) - -add_executable(paltest_wmakepath_test1 - ${SOURCES} -) - -add_dependencies(paltest_wmakepath_test1 coreclrpal) - -target_link_libraries(paltest_wmakepath_test1 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_wmakepath/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_wmakepath/test1/test1.c deleted file mode 100644 index eb79dc6..0000000 --- a/src/pal/tests/palsuite/c_runtime/_wmakepath/test1/test1.c +++ /dev/null @@ -1,76 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: test1.c -** -** Purpose: Tests the PAL implementation of the _wmakepath function. -** Create a path, and ensure that it builds how it is -** supposed to. -** -** -**===================================================================*/ - -#define UNICODE - -#include - -int __cdecl main(int argc, char **argv) -{ - WCHAR FullPath[128]; - WCHAR File[] = {'t','e','s','t','\0'}; - WCHAR Ext[] = {'t','x','t','\0'}; - char * PrintResult=NULL; /* Used for printing out errors */ - char * PrintCorrect=NULL; - -#if WIN32 - WCHAR Drive[] = {'C','\0'}; - WCHAR Dir[] = {'\\','t','e','s','t','\0'}; - WCHAR PathName[] = - {'C',':','\\','t','e','s','t','\\','t','e', - 's','t','.','t','x','t','\0'}; -#else - WCHAR *Drive = NULL; - WCHAR Dir[] = {'/','t','e','s','t','\0'}; - WCHAR PathName[] = - {'/','t','e','s','t','/','t','e','s','t','.','t','x','t','\0'}; -#endif - - /* - * Initialize the PAL and return FAIL if this fails - */ - if (0 != (PAL_Initialize(argc,argv))) - { - return FAIL; - } - - _wmakepath(FullPath, Drive, Dir, File, Ext); - - if(wcscmp(FullPath,PathName) != 0) - { - PrintResult = convertC(FullPath); - PrintCorrect = convertC(PathName); - - Fail("ERROR: The pathname which was created turned out to be %s " - "when it was supposed to be %s.\n",PrintResult,PrintCorrect); - } - - - PAL_Terminate(); - return PASS; -} - - - - - - - - - - - - - diff --git a/src/pal/tests/palsuite/c_runtime/_wmakepath/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_wmakepath/test1/testinfo.dat deleted file mode 100644 index 6720d34..0000000 --- a/src/pal/tests/palsuite/c_runtime/_wmakepath/test1/testinfo.dat +++ /dev/null @@ -1,13 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = _wmakepath -Name = Positive Test for _wmakepath -TYPE = DEFAULT -EXE1 = test1 -Description -= Purpose: Tests the PAL implementation of the _wmakepath function. -= Create a path, and ensure that it builds how it is supposed to. diff --git a/src/pal/tests/palsuite/c_runtime/_wsplitpath/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wsplitpath/CMakeLists.txt deleted file mode 100644 index f6aa0cb..0000000 --- a/src/pal/tests/palsuite/c_runtime/_wsplitpath/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -add_subdirectory(test1) - diff --git a/src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/CMakeLists.txt deleted file mode 100644 index ee9a7a8..0000000 --- a/src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test1.c -) - -add_executable(paltest_wsplitpath_test1 - ${SOURCES} -) - -add_dependencies(paltest_wsplitpath_test1 coreclrpal) - -target_link_libraries(paltest_wsplitpath_test1 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/test1.c deleted file mode 100644 index 305768e..0000000 --- a/src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/test1.c +++ /dev/null @@ -1,151 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: Passes _wsplitpath() a series of sample paths and checks -** that it parses them as expected. -** -** -**==========================================================================*/ - - -#include - -struct testCase -{ - char path[_MAX_PATH]; /* The path to parse. */ - char drive[_MAX_DRIVE]; /* The expected values... */ - char dir[_MAX_DIR]; - char fname[_MAX_FNAME]; - char ext[_MAX_EXT]; -}; - -struct wTestCase -{ - WCHAR *path; /* The path to parse. */ - WCHAR *drive; /* The expected values... */ - WCHAR *dir; - WCHAR *fname; - WCHAR *ext; -}; - - - -int __cdecl main(int argc, char **argv) -{ - struct testCase testCases[] = - { -#if WIN32 - {"c:\\foo\\bar\\foo.bar", "c:", "\\foo\\bar\\", "foo", ".bar"}, - {"c:/foo/bar/foo.bar", "c:", "/foo/bar/", "foo", ".bar"}, - {"c:/foo/bar/foo", "c:", "/foo/bar/", "foo", ""}, - {"c:/foo/bar/.bar", "c:", "/foo/bar/", "", ".bar"}, - {"c:/foo/bar/", "c:", "/foo/bar/", "", ""}, - {"/foo/bar/foo.bar", "", "/foo/bar/", "foo", ".bar"}, - {"c:foo.bar", "c:", "", "foo", ".bar"} -#else - {"c:\\foo\\bar\\foo.bar", "","c:/foo/bar/", "foo", ".bar"}, - {"c:/foo/bar/foo.bar", "", "c:/foo/bar/", "foo", ".bar"}, - {"c:/foo/bar/foo", "", "c:/foo/bar/", "foo", ""}, - {"c:/foo/bar/.bar", "", "c:/foo/bar/", ".bar", ""}, - {"c:/foo/bar/", "", "c:/foo/bar/", "", ""}, - {"/foo/bar/foo.bar", "", "/foo/bar/", "foo", ".bar"}, - {"c:foo.bar", "", "", "c:foo", ".bar"} -#endif - }; - - struct wTestCase wTestCases[sizeof(testCases)/sizeof(struct testCase)]; - - wchar_t wDrive[_MAX_DRIVE]; - wchar_t wDir[_MAX_DIR]; - wchar_t wFname[_MAX_FNAME]; - wchar_t wExt[_MAX_EXT]; - - char *drive; - char *dir; - char *fname; - char *ext; - - int i; - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - /*create wide character versions of the test cases*/ - for(i = 0; i < sizeof(testCases)/sizeof(struct testCase); i ++) - { - wTestCases[i].path = convert(testCases[i].path); - wTestCases[i].drive = convert(testCases[i].drive); - wTestCases[i].dir = convert(testCases[i].dir); - wTestCases[i].fname = convert(testCases[i].fname); - wTestCases[i].ext = convert(testCases[i].ext); - } - - - for (i = 0; i < sizeof(wTestCases)/sizeof(struct wTestCase); i++) - { - _wsplitpath(wTestCases[i].path, wDrive, wDir, wFname, wExt); - - /*Convert the results to regular ANSI strings.*/ - drive = convertC(wDrive); - dir = convertC(wDir); - fname = convertC(wFname); - ext = convertC(wExt); - - - /*on platforms that don't support drive letters, the drive - returned should always be "" */ - if (wcscmp(wDrive, wTestCases[i].drive) != 0) - { - Fail("_wsplitpath read the path \"%s\" and thought the drive was " - "\"%s\" instead of \"%s\"" - , testCases[i].path, drive, testCases[i].drive); - } - - if (wcscmp(wDir, wTestCases[i].dir) != 0) - { - Fail("_wsplitpath read the path \"%s\" and thought the directory " - "was \"%s\" instead of \"%s\"" - , testCases[i].path, dir, testCases[i].dir); - } - - if (wcscmp(wFname, wTestCases[i].fname) != 0) - { - Fail("_wsplitpath read the path \"%s\" and thought the filename " - "was \"%s\" instead of \"%s\"" - , testCases[i].path, fname, testCases[i].fname); - } - - if (wcscmp(wExt, wTestCases[i].ext) != 0) - { - Fail("_wsplitpath read the path \"%s\" and thought the file " - "extension was \"%s\" instead of \"%s\"" - , testCases[i].path, ext, testCases[i].ext); - } - - free(drive); - free(dir); - free(fname); - free(ext); - } - - for(i = 0; i < sizeof(testCases)/sizeof(struct testCase); i++) - { - free(wTestCases[i].path); - free(wTestCases[i].drive); - free(wTestCases[i].dir); - free(wTestCases[i].fname); - free(wTestCases[i].ext); - } - - PAL_Terminate(); - - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/testinfo.dat deleted file mode 100644 index 30be680..0000000 --- a/src/pal/tests/palsuite/c_runtime/_wsplitpath/test1/testinfo.dat +++ /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. -# See the LICENSE file in the project root for more information. - -Version = 1.0 -Section = C Runtime -Function = _wsplitpath -Name = Positive Test for _wsplitpath -TYPE = DEFAULT -EXE1 = test1 -Description -= Passes _wsplitpath() a series of sample paths and checks that it -= parses them as expected. - - diff --git a/src/pal/tests/palsuite/c_runtime/_wtoi/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/_wtoi/test1/CMakeLists.txt index 9e6610f..ed02fec 100644 --- a/src/pal/tests/palsuite/c_runtime/_wtoi/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/_wtoi/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wtoi_test1 diff --git a/src/pal/tests/palsuite/c_runtime/_wtoi/test1/test1.c b/src/pal/tests/palsuite/c_runtime/_wtoi/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/_wtoi/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/_wtoi/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/abs/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/abs/test1/CMakeLists.txt index c8a8595..b01d97f 100644 --- a/src/pal/tests/palsuite/c_runtime/abs/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/abs/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - abs.c + abs.cpp ) add_executable(paltest_abs_test1 diff --git a/src/pal/tests/palsuite/c_runtime/abs/test1/abs.c b/src/pal/tests/palsuite/c_runtime/abs/test1/abs.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/abs/test1/abs.c rename to src/pal/tests/palsuite/c_runtime/abs/test1/abs.cpp diff --git a/src/pal/tests/palsuite/c_runtime/acos/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/acos/test1/CMakeLists.txt index 978ab42..5bd3ae0 100644 --- a/src/pal/tests/palsuite/c_runtime/acos/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/acos/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_acos_test1 diff --git a/src/pal/tests/palsuite/c_runtime/acos/test1/test1.c b/src/pal/tests/palsuite/c_runtime/acos/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/acos/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/acos/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/acosf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/acosf/CMakeLists.txt new file mode 100644 index 0000000..5e1ef7f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/acosf/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) diff --git a/src/pal/tests/palsuite/c_runtime/acosf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/acosf/test1/CMakeLists.txt new file mode 100644 index 0000000..2643647 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/acosf/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_acosf_test1 + ${SOURCES} +) + +add_dependencies(paltest_acosf_test1 coreclrpal) + +target_link_libraries(paltest_acosf_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/acosf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/acosf/test1/test1.c new file mode 100644 index 0000000..3d8668c --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/acosf/test1/test1.c @@ -0,0 +1,129 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that acosf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = acosf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("acosf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = acosf(value); + + if (!_isnanf(result)) + { + Fail("acosf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { -1, 3.14159265f, PAL_EPSILON * 10 }, // expected: pi + { -0.911733915f, 2.71828183f, PAL_EPSILON * 10 }, // expected: e + { -0.668201510f, 2.30258509f, PAL_EPSILON * 10 }, // expected: ln(10) + { 0, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + { 0.127751218f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e) + { 0.155943695f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2) + { 0.428125148f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi) + { 0.540302306f, 1, PAL_EPSILON * 10 }, + { 0.707106781f, 0.785398163f, PAL_EPSILON }, // expected: pi / 4, value: 1 / sqrtf(2) + { 0.760244597f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2) + { 0.769238901f, 0.693147181f, PAL_EPSILON }, // expected: ln(2) + { 0.804109828f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi + { 0.907167129f, 0.434294482f, PAL_EPSILON }, // expected: logf10f(e) + { 0.949765715f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi + { 1, 0, PAL_EPSILON }, + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + validate_isnan(PAL_POSINF); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/acosf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/acosf/test1/testinfo.dat new file mode 100644 index 0000000..41cead3 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/acosf/test1/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = acosf +Name = Positive Test for acosf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes a series of values to the acosf() function, += checking each for the expfected result. Also checks += for proper handling of out-of-range values. diff --git a/src/pal/tests/palsuite/c_runtime/asin/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/asin/test1/CMakeLists.txt index a3aec3f..510b543 100644 --- a/src/pal/tests/palsuite/c_runtime/asin/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/asin/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_asin_test1 diff --git a/src/pal/tests/palsuite/c_runtime/asin/test1/test1.c b/src/pal/tests/palsuite/c_runtime/asin/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/asin/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/asin/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/asinf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/asinf/CMakeLists.txt new file mode 100644 index 0000000..5e1ef7f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/asinf/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) diff --git a/src/pal/tests/palsuite/c_runtime/asinf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/asinf/test1/CMakeLists.txt new file mode 100644 index 0000000..b167bd8 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/asinf/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_asinf_test1 + ${SOURCES} +) + +add_dependencies(paltest_asinf_test1 coreclrpal) + +target_link_libraries(paltest_asinf_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/asinf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/asinf/test1/test1.c new file mode 100644 index 0000000..773015e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/asinf/test1/test1.c @@ -0,0 +1,145 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that asinf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = asinf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("asinf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = asinf(value); + + if (!_isnanf(result)) + { + Fail("asinf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * validate + * + * test validation function for values returning +INF + */ +void __cdecl validate_isinf_positive(float value) +{ + float result = asinf(value); + + if (result != PAL_POSINF) + { + Fail("asinf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_POSINF); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.312961796f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi + { 0.410781291f, 0.423310825f, PAL_EPSILON }, // expected: pi - e + { 0.420770483f, 0.434294482f, PAL_EPSILON }, // expected: logf10f(e) + { 0.594480769f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi + { 0.638961276f, 0.693147181f, PAL_EPSILON }, // expected: ln(2) + { 0.649636939f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2) + { 0.707106781f, 0.785398163f, PAL_EPSILON }, // expected: pi / 4, value: 1 / sqrtf(2) + { 0.743980337f, 0.839007561f, PAL_EPSILON }, // expected: pi - ln(10) + { 0.841470985f, 1, PAL_EPSILON * 10 }, + { 0.903719457f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi) + { 0.987765946f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2) + { 0.991806244f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e) + { 1, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + validate_isnan(PAL_POSINF); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/asinf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/asinf/test1/testinfo.dat new file mode 100644 index 0000000..ca2dd42 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/asinf/test1/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = asinf +Name = Positive Test for asinf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes a series of values to the asinf() function, += checking each for the expected result. Also checks += for proper handling of out-of-range values. diff --git a/src/pal/tests/palsuite/c_runtime/atan/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atan/test1/CMakeLists.txt index b0b84e7..ace64e4 100644 --- a/src/pal/tests/palsuite/c_runtime/atan/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/atan/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_atan_test1 diff --git a/src/pal/tests/palsuite/c_runtime/atan/test1/test1.c b/src/pal/tests/palsuite/c_runtime/atan/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/atan/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/atan/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/atan2/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atan2/test1/CMakeLists.txt index 8bd69da..cafa09f 100644 --- a/src/pal/tests/palsuite/c_runtime/atan2/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/atan2/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_atan2_test1 diff --git a/src/pal/tests/palsuite/c_runtime/atan2/test1/test1.c b/src/pal/tests/palsuite/c_runtime/atan2/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/atan2/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/atan2/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/atan2f/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atan2f/CMakeLists.txt new file mode 100644 index 0000000..5e1ef7f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/atan2f/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) diff --git a/src/pal/tests/palsuite/c_runtime/atan2f/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atan2f/test1/CMakeLists.txt new file mode 100644 index 0000000..d71a61b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/atan2f/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_atan2f_test1 + ${SOURCES} +) + +add_dependencies(paltest_atan2f_test1 coreclrpal) + +target_link_libraries(paltest_atan2f_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/atan2f/test1/test1.c b/src/pal/tests/palsuite/c_runtime/atan2f/test1/test1.c new file mode 100644 index 0000000..2ee641e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/atan2f/test1/test1.c @@ -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. +// See the LICENSE file in the project root for more information. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests that atan2f returns correct values for a subset of values. +** Tests with positive and negative values of x and y to ensure +** atan2f is returning results from the correct quadrant. +** +**===================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +struct test +{ + float y; /* second component of the value to test the function with */ + float x; /* first component of the value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float y, float x, float expected, float variance) +{ + float result = atan2f(y, x); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("atan2f(%g, %g) returned %10.9g when it should have returned %10.9g", + y, x, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float y, float x) +{ + float result = atan2f(y, x); + + if (!_isnanf(result)) + { + Fail("atan2f(%g, %g) returned %10.9g when it should have returned %10.9g", + y, x, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* y x expected variance */ + { 0, PAL_POSINF, 0, PAL_EPSILON }, + { 0, 0, 0, PAL_EPSILON }, + { 0.312961796f, 0.949765715f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi + { 0.420770483f, 0.907167129f, 0.434294482f, PAL_EPSILON }, // expected: logf10f(e) + { 0.594480769f, 0.804109828f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi + { 0.638961276f, 0.769238901f, 0.693147181f, PAL_EPSILON }, // expected: ln(2) + { 0.649636939f, 0.760244597f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2) + { 0.707106781f, 0.707106781f, 0.785398163f, PAL_EPSILON }, // expected: pi / 4, value: 1 / sqrtf(2) + { 1, 1, 0.785398163f, PAL_EPSILON }, // expected: pi / 4 + { PAL_POSINF, PAL_POSINF, 0.785398163f, PAL_EPSILON }, // expected: pi / 4 + { 0.841470985f, 0.540302306f, 1, PAL_EPSILON * 10 }, + { 0.903719457f, 0.428125148f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi) + { 0.987765946f, 0.155943695f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2) + { 0.991806244f, 0.127751218f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e) + { 1, 0, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + { PAL_POSINF, 0, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + { PAL_POSINF, 1, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + { 0.743980337f, -0.668201510f, 2.30258509f, PAL_EPSILON * 10 }, // expected: ln(10) + { 0.410781291f, -0.911733915f, 2.71828183f, PAL_EPSILON * 10 }, // expected: e + { 0, -1, 3.14159265f, PAL_EPSILON * 10 }, // expected: pi + { 1, PAL_POSINF, 0, PAL_EPSILON }, + }; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + const float pi = 3.14159265f; + + validate( tests[i].y, tests[i].x, tests[i].expected, tests[i].variance); + validate(-tests[i].y, tests[i].x, -tests[i].expected, tests[i].variance); + validate( tests[i].y, -tests[i].x, pi - tests[i].expected, tests[i].variance); + validate(-tests[i].y, -tests[i].x, tests[i].expected - pi, tests[i].variance); + } + + validate_isnan(PAL_NEGINF, PAL_NAN); + validate_isnan(PAL_NAN, PAL_NEGINF); + validate_isnan(PAL_NAN, PAL_POSINF); + validate_isnan(PAL_POSINF, PAL_NAN); + + validate_isnan(PAL_NAN, -1); + validate_isnan(PAL_NAN, -0.0f); + validate_isnan(PAL_NAN, 0); + validate_isnan(PAL_NAN, 1); + + validate_isnan(-1, PAL_NAN); + validate_isnan(-0.0f, PAL_NAN); + validate_isnan( 0, PAL_NAN); + validate_isnan( 1, PAL_NAN); + + validate_isnan(PAL_NAN, PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/atan2f/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/atan2f/test1/testinfo.dat new file mode 100644 index 0000000..bd9a9d9 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/atan2f/test1/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = atan2f +Name = Test #1 for atan2f +Type = DEFAULT +EXE1 = test1 +Description +=Tests that atan2f returns correct values for a subset of values. +=Tests with positive and negative values of x and y to ensure +=atan2f is returning results from the correct quadrant. diff --git a/src/pal/tests/palsuite/c_runtime/atanf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atanf/CMakeLists.txt new file mode 100644 index 0000000..5e1ef7f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/atanf/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) diff --git a/src/pal/tests/palsuite/c_runtime/atanf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atanf/test1/CMakeLists.txt new file mode 100644 index 0000000..b71b1cf --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/atanf/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_atanf_test1 + ${SOURCES} +) + +add_dependencies(paltest_atanf_test1 coreclrpal) + +target_link_libraries(paltest_atanf_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/atanf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/atanf/test1/test1.c new file mode 100644 index 0000000..543a0a8 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/atanf/test1/test1.c @@ -0,0 +1,127 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that atanf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = atanf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("atanf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = atanf(value); + + if (!_isnanf(result)) + { + Fail("atanf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.329514733f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi + { 0.450549534f, 0.423310825f, PAL_EPSILON }, // expected: pi - e + { 0.463829067f, 0.434294482f, PAL_EPSILON }, // expected: logf10f(e) + { 0.739302950f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi + { 0.830640878f, 0.693147181f, PAL_EPSILON }, // expected: ln(2) + { 0.854510432f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2) + { 1, 0.785398163f, PAL_EPSILON }, // expected: pi / 4 + { 1.11340715f, 0.839007561f, PAL_EPSILON }, // expected: pi - ln(10) + { 1.55740772f, 1, PAL_EPSILON * 10 }, + { 2.11087684f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi) + { 6.33411917f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2) + { 7.76357567f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e) + { PAL_POSINF, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/atanf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/atanf/test1/testinfo.dat new file mode 100644 index 0000000..0d18427 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/atanf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = atanf +Name = Positive Test for atanf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes a series of values to the atanf() function, += checking each for the expected result. diff --git a/src/pal/tests/palsuite/c_runtime/atof/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atof/test1/CMakeLists.txt index 1f34b7e..12e584b 100644 --- a/src/pal/tests/palsuite/c_runtime/atof/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/atof/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_atof_test1 diff --git a/src/pal/tests/palsuite/c_runtime/atof/test1/test1.c b/src/pal/tests/palsuite/c_runtime/atof/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/atof/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/atof/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/atoi/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atoi/test1/CMakeLists.txt index 3549aca..2250522 100644 --- a/src/pal/tests/palsuite/c_runtime/atoi/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/atoi/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_atoi_test1 diff --git a/src/pal/tests/palsuite/c_runtime/atoi/test1/test1.c b/src/pal/tests/palsuite/c_runtime/atoi/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/atoi/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/atoi/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/atol/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/atol/test1/CMakeLists.txt index 4fea187..29643aa 100644 --- a/src/pal/tests/palsuite/c_runtime/atol/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/atol/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_atol_test1 diff --git a/src/pal/tests/palsuite/c_runtime/atol/test1/test1.c b/src/pal/tests/palsuite/c_runtime/atol/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/atol/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/atol/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/bsearch/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/bsearch/test1/CMakeLists.txt index d2018f3..c5aab7b 100644 --- a/src/pal/tests/palsuite/c_runtime/bsearch/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/bsearch/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_bsearch_test1 diff --git a/src/pal/tests/palsuite/c_runtime/bsearch/test1/test1.c b/src/pal/tests/palsuite/c_runtime/bsearch/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/bsearch/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/bsearch/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/bsearch/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/bsearch/test2/CMakeLists.txt index dc65560..7ad33b1 100644 --- a/src/pal/tests/palsuite/c_runtime/bsearch/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/bsearch/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_bsearch_test2 diff --git a/src/pal/tests/palsuite/c_runtime/bsearch/test2/test2.c b/src/pal/tests/palsuite/c_runtime/bsearch/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/bsearch/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/bsearch/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/ceil/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ceil/test1/CMakeLists.txt index c73ad1d..f834914 100644 --- a/src/pal/tests/palsuite/c_runtime/ceil/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/ceil/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_ceil_test1 diff --git a/src/pal/tests/palsuite/c_runtime/ceil/test1/test1.c b/src/pal/tests/palsuite/c_runtime/ceil/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/ceil/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/ceil/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/ceilf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ceilf/CMakeLists.txt new file mode 100644 index 0000000..5e1ef7f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/ceilf/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) diff --git a/src/pal/tests/palsuite/c_runtime/ceilf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ceilf/test1/CMakeLists.txt new file mode 100644 index 0000000..64f14cd --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/ceilf/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_ceilf_test1 + ${SOURCES} +) + +add_dependencies(paltest_ceilf_test1 coreclrpal) + +target_link_libraries(paltest_ceilf_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/ceilf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/ceilf/test1/test1.c new file mode 100644 index 0000000..4939fb7 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/ceilf/test1/test1.c @@ -0,0 +1,131 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests ceilf with simple positive and negative values. Also tests +** extreme cases like extremely small values and positive and +** negative infinity. Makes sure that calling ceilf on NaN returns +** NaN +** +**==========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = ceilf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("ceilf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = ceilf(value); + + if (!_isnanf(result)) + { + Fail("ceilf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char *argv[]) +{ + struct test tests[] = + { + /* value expected variance */ + { 0.318309886f, 1, PAL_EPSILON * 10 }, // value: 1 / pi + { 0.434294482f, 1, PAL_EPSILON * 10 }, // value: log10f(e) + { 0.636619772f, 1, PAL_EPSILON * 10 }, // value: 2 / pi + { 0.693147181f, 1, PAL_EPSILON * 10 }, // value: ln(2) + { 0.707106781f, 1, PAL_EPSILON * 10 }, // value: 1 / sqrtf(2) + { 0.785398163f, 1, PAL_EPSILON * 10 }, // value: pi / 4 + { 1.12837917f, 2, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi) + { 1.41421356f, 2, PAL_EPSILON * 10 }, // value: sqrtf(2) + { 1.44269504f, 2, PAL_EPSILON * 10 }, // value: logf2(e) + { 1.57079633f, 2, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.30258509f, 3, PAL_EPSILON * 10 }, // value: ln(10) + { 2.71828183f, 3, PAL_EPSILON * 10 }, // value: e + { 3.14159265f, 4, PAL_EPSILON * 10 }, // value: pi + { PAL_POSINF, PAL_POSINF, 0 } + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + validate( 0, 0, PAL_EPSILON); + validate(-0.0f, 0, PAL_EPSILON); + + validate( 1, 1, PAL_EPSILON * 10); + validate(-1.0f, -1, PAL_EPSILON * 10); + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, 1 - tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/ceilf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/ceilf/test1/testinfo.dat new file mode 100644 index 0000000..095b8b2 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/ceilf/test1/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = ceilf +Name = Test #1 for ceilf +TYPE = DEFAULT +EXE1 = test1 +Description +=Tests ceilf with simple positive and negative values. Also tests +=extreme cases like extremely small values and positive and negative +=infinity. Makes sure that calling ceilf on NaN returns NaN diff --git a/src/pal/tests/palsuite/c_runtime/cos/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/cos/test1/CMakeLists.txt index 1dda9a2..536664c 100644 --- a/src/pal/tests/palsuite/c_runtime/cos/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/cos/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_cos_test1 diff --git a/src/pal/tests/palsuite/c_runtime/cos/test1/test1.c b/src/pal/tests/palsuite/c_runtime/cos/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/cos/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/cos/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/cosf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/cosf/CMakeLists.txt new file mode 100644 index 0000000..5e1ef7f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/cosf/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) diff --git a/src/pal/tests/palsuite/c_runtime/cosf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/cosf/test1/CMakeLists.txt new file mode 100644 index 0000000..b3a18ea --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/cosf/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_cosf_test1 + ${SOURCES} +) + +add_dependencies(paltest_cosf_test1 coreclrpal) + +target_link_libraries(paltest_cosf_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/cosf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/cosf/test1/test1.c new file mode 100644 index 0000000..210851a --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/cosf/test1/test1.c @@ -0,0 +1,130 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that cosf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = cosf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("cosf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = cosf(value); + + if (!_isnanf(result)) + { + Fail("cosf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 1, PAL_EPSILON * 10 }, + { 0.318309886f, 0.949765715f, PAL_EPSILON }, // value: 1 / pi + { 0.434294482f, 0.907167129f, PAL_EPSILON }, // value: log10f(e) + { 0.636619772f, 0.804109828f, PAL_EPSILON }, // value: 2 / pi + { 0.693147181f, 0.769238901f, PAL_EPSILON }, // value: ln(2) + { 0.707106781f, 0.760244597f, PAL_EPSILON }, // value: 1 / sqrtf(2) + { 0.785398163f, 0.707106781f, PAL_EPSILON }, // value: pi / 4, expected: 1 / sqrtf(2) + { 1, 0.540302306f, PAL_EPSILON }, + { 1.12837917f, 0.428125148f, PAL_EPSILON }, // value: 2 / sqrtf(pi) + { 1.41421356f, 0.155943695f, PAL_EPSILON }, // value: sqrtf(2) + { 1.44269504f, 0.127751218f, PAL_EPSILON }, // value: logf2(e) + { 1.57079633f, 0, PAL_EPSILON }, // value: pi / 2 + { 2.30258509f, -0.668201510f, PAL_EPSILON }, // value: ln(10) + { 2.71828183f, -0.911733918f, PAL_EPSILON }, // value: e + { 3.14159265f, -1, PAL_EPSILON * 10 }, // value: pi + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + validate_isnan(PAL_POSINF); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/cosf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/cosf/test1/testinfo.dat new file mode 100644 index 0000000..a0265ad --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/cosf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = cosf +Name = Positive Test for cosf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to cosf() a series of angle value, checking that += each one return the correct value. diff --git a/src/pal/tests/palsuite/c_runtime/cosh/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/cosh/test1/CMakeLists.txt index bea7b7a..e1fff0e 100644 --- a/src/pal/tests/palsuite/c_runtime/cosh/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/cosh/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_cosh_test1 diff --git a/src/pal/tests/palsuite/c_runtime/cosh/test1/test1.c b/src/pal/tests/palsuite/c_runtime/cosh/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/cosh/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/cosh/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/coshf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/coshf/CMakeLists.txt new file mode 100644 index 0000000..5e1ef7f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/coshf/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) diff --git a/src/pal/tests/palsuite/c_runtime/coshf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/coshf/test1/CMakeLists.txt new file mode 100644 index 0000000..92fcfde --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/coshf/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_coshf_test1 + ${SOURCES} +) + +add_dependencies(paltest_coshf_test1 coreclrpal) + +target_link_libraries(paltest_coshf_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/coshf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/coshf/test1/test1.c new file mode 100644 index 0000000..e1ab745 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/coshf/test1/test1.c @@ -0,0 +1,129 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that coshf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = coshf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("coshf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning PAL_NAN + */ +void __cdecl validate_isnan(float value) +{ + float result = coshf(value); + + if (!_isnanf(result)) + { + Fail("coshf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 1, PAL_EPSILON * 10 }, + { 0.318309886f, 1.05108979f, PAL_EPSILON * 10 }, // value: 1 / pi + { 0.434294482f, 1.09579746f, PAL_EPSILON * 10 }, // value: log10f(e) + { 0.636619772f, 1.20957949f, PAL_EPSILON * 10 }, // value: 2 / pi + { 0.693147181f, 1.25f, PAL_EPSILON * 10 }, // value: ln(2) + { 0.707106781f, 1.26059184f, PAL_EPSILON * 10 }, // value: 1 / sqrtf(2) + { 0.785398163f, 1.32460909f, PAL_EPSILON * 10 }, // value: pi / 4 + { 1, 1.54308063f, PAL_EPSILON * 10 }, + { 1.12837917f, 1.70710014f, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi) + { 1.41421356f, 2.17818356f, PAL_EPSILON * 10 }, // value: sqrtf(2) + { 1.44269504f, 2.23418810f, PAL_EPSILON * 10 }, // value: logf2(e) + { 1.57079633f, 2.50917848f, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.30258509f, 5.05f, PAL_EPSILON * 10 }, // value: ln(10) + { 2.71828183f, 7.61012514f, PAL_EPSILON * 10 }, // value: e + { 3.14159265f, 11.5919533f, PAL_EPSILON * 100 }, // value: pi + { PAL_POSINF, PAL_POSINF, 0 }, + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/coshf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/coshf/test1/testinfo.dat new file mode 100644 index 0000000..814ed98 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/coshf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = coshf +Name = Positive Test for coshf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to coshf() a series of angle value, checking that += each one return to correct value. diff --git a/src/pal/tests/palsuite/c_runtime/ctime/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ctime/test1/CMakeLists.txt index aa64a71..3eeffb0 100644 --- a/src/pal/tests/palsuite/c_runtime/ctime/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/ctime/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_ctime_test1 diff --git a/src/pal/tests/palsuite/c_runtime/ctime/test1/test1.c b/src/pal/tests/palsuite/c_runtime/ctime/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/ctime/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/ctime/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/errno/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/errno/test1/CMakeLists.txt index 89b25a4..91b8d09 100644 --- a/src/pal/tests/palsuite/c_runtime/errno/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/errno/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_errno_test1 diff --git a/src/pal/tests/palsuite/c_runtime/errno/test1/test1.c b/src/pal/tests/palsuite/c_runtime/errno/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/errno/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/errno/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/errno/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/errno/test2/CMakeLists.txt index edd4cf7..ab7c4a2 100644 --- a/src/pal/tests/palsuite/c_runtime/errno/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/errno/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_errno_test2 diff --git a/src/pal/tests/palsuite/c_runtime/errno/test2/test2.c b/src/pal/tests/palsuite/c_runtime/errno/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/errno/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/errno/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/exit/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/exit/test1/CMakeLists.txt index eb9ca4e..bb2cbcc 100644 --- a/src/pal/tests/palsuite/c_runtime/exit/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/exit/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_exit_test1 diff --git a/src/pal/tests/palsuite/c_runtime/exit/test1/test1.c b/src/pal/tests/palsuite/c_runtime/exit/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/exit/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/exit/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/exit/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/exit/test2/CMakeLists.txt index 47d3a44..8a74e75 100644 --- a/src/pal/tests/palsuite/c_runtime/exit/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/exit/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_exit_test2 diff --git a/src/pal/tests/palsuite/c_runtime/exit/test2/test2.c b/src/pal/tests/palsuite/c_runtime/exit/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/exit/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/exit/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/exp/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/exp/test1/CMakeLists.txt index 9cdd4ec..3377ed2 100644 --- a/src/pal/tests/palsuite/c_runtime/exp/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/exp/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_exp_test1 diff --git a/src/pal/tests/palsuite/c_runtime/exp/test1/test1.c b/src/pal/tests/palsuite/c_runtime/exp/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/exp/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/exp/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/expf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/expf/CMakeLists.txt new file mode 100644 index 0000000..5e1ef7f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/expf/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) diff --git a/src/pal/tests/palsuite/c_runtime/expf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/expf/test1/CMakeLists.txt new file mode 100644 index 0000000..fb12b65 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/expf/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_expf_test1 + ${SOURCES} +) + +add_dependencies(paltest_expf_test1 coreclrpal) + +target_link_libraries(paltest_expf_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/expf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/expf/test1/test1.c new file mode 100644 index 0000000..32f4e8d --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/expf/test1/test1.c @@ -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. +// See the LICENSE file in the project root for more information. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests expf with a normal set of values. +** +**===================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = expf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("expf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = expf(value); + + if (!_isnanf(result)) + { + Fail("expf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { PAL_NEGINF, 0, PAL_EPSILON }, + { -3.14159265f, 0.0432139183f, PAL_EPSILON / 10 }, // value: -(pi) + { -2.71828183f, 0.0659880358f, PAL_EPSILON / 10 }, // value: -(e) + { -2.30258509f, 0.1f, PAL_EPSILON }, // value: -(ln(10)) + { -1.57079633f, 0.207879576f, PAL_EPSILON }, // value: -(pi / 2) + { -1.44269504f, 0.236290088f, PAL_EPSILON }, // value: -(logf2(e)) + { -1.41421356f, 0.243116734f, PAL_EPSILON }, // value: -(sqrtf(2)) + { -1.12837917f, 0.323557264f, PAL_EPSILON }, // value: -(2 / sqrtf(pi)) + { -1, 0.367879441f, PAL_EPSILON }, // value: -(1) + { -0.785398163f, 0.455938128f, PAL_EPSILON }, // value: -(pi / 4) + { -0.707106781f, 0.493068691f, PAL_EPSILON }, // value: -(1 / sqrtf(2)) + { -0.693147181f, 0.5f, PAL_EPSILON }, // value: -(ln(2)) + { -0.636619772f, 0.529077808f, PAL_EPSILON }, // value: -(2 / pi) + { -0.434294482f, 0.647721485f, PAL_EPSILON }, // value: -(log10f(e)) + { -0.318309886f, 0.727377349f, PAL_EPSILON }, // value: -(1 / pi) + { 0, 1, PAL_EPSILON * 10 }, + { 0.318309886f, 1.37480223f, PAL_EPSILON * 10 }, // value: 1 / pi + { 0.434294482f, 1.54387344f, PAL_EPSILON * 10 }, // value: log10f(e) + { 0.636619772f, 1.89008116f, PAL_EPSILON * 10 }, // value: 2 / pi + { 0.693147181f, 2, PAL_EPSILON * 10 }, // value: ln(2) + { 0.707106781f, 2.02811498f, PAL_EPSILON * 10 }, // value: 1 / sqrtf(2) + { 0.785398163f, 2.19328005f, PAL_EPSILON * 10 }, // value: pi / 4 + { 1, 2.71828183f, PAL_EPSILON * 10 }, // expected: e + { 1.12837917f, 3.09064302f, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi) + { 1.41421356f, 4.11325038f, PAL_EPSILON * 10 }, // value: sqrtf(2) + { 1.44269504f, 4.23208611f, PAL_EPSILON * 10 }, // value: logf2(e) + { 1.57079633f, 4.81047738f, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.30258509f, 10, PAL_EPSILON * 100 }, // value: ln(10) + { 2.71828183f, 15.1542622f, PAL_EPSILON * 100 }, // value: e + { 3.14159265f, 23.1406926f, PAL_EPSILON * 100 }, // value: pi + { PAL_POSINF, PAL_POSINF, 0 }, + }; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/expf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/expf/test1/testinfo.dat new file mode 100644 index 0000000..c359285 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/expf/test1/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = expf +Name = Test #1 for expf +Type = DEFAULT +EXE1 = test1 +Description +=Tests expf with a normal set of values. diff --git a/src/pal/tests/palsuite/c_runtime/fabs/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fabs/test1/CMakeLists.txt index ab27230..fa01a34 100644 --- a/src/pal/tests/palsuite/c_runtime/fabs/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fabs/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_fabs_test1 diff --git a/src/pal/tests/palsuite/c_runtime/fabs/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fabs/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fabs/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/fabs/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fabsf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fabsf/test1/CMakeLists.txt index 06512eb..a1823e2 100644 --- a/src/pal/tests/palsuite/c_runtime/fabsf/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fabsf/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_fabsf_test1 diff --git a/src/pal/tests/palsuite/c_runtime/fabsf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fabsf/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fabsf/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/fabsf/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fclose/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fclose/test1/CMakeLists.txt index 55ed7c6..64cfef0 100644 --- a/src/pal/tests/palsuite/c_runtime/fclose/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fclose/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_fclose_test1 diff --git a/src/pal/tests/palsuite/c_runtime/fclose/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fclose/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fclose/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/fclose/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fclose/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fclose/test2/CMakeLists.txt index 178dc7d..3b55386 100644 --- a/src/pal/tests/palsuite/c_runtime/fclose/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fclose/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_fclose_test2 diff --git a/src/pal/tests/palsuite/c_runtime/fclose/test2/test2.c b/src/pal/tests/palsuite/c_runtime/fclose/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fclose/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/fclose/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/feof/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/feof/test1/CMakeLists.txt index ee1389d..9f68950 100644 --- a/src/pal/tests/palsuite/c_runtime/feof/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/feof/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_feof_test1 diff --git a/src/pal/tests/palsuite/c_runtime/feof/test1/test1.c b/src/pal/tests/palsuite/c_runtime/feof/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/feof/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/feof/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/ferror/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ferror/test1/CMakeLists.txt index 2ab12b5..cd1fe52 100644 --- a/src/pal/tests/palsuite/c_runtime/ferror/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/ferror/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_ferror_test1 diff --git a/src/pal/tests/palsuite/c_runtime/ferror/test1/test1.c b/src/pal/tests/palsuite/c_runtime/ferror/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/ferror/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/ferror/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/ferror/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ferror/test2/CMakeLists.txt index 077dde0..05bd7fd 100644 --- a/src/pal/tests/palsuite/c_runtime/ferror/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/ferror/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_ferror_test2 diff --git a/src/pal/tests/palsuite/c_runtime/ferror/test2/test2.c b/src/pal/tests/palsuite/c_runtime/ferror/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/ferror/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/ferror/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fflush/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fflush/test1/CMakeLists.txt index 743f1d2..58c7c5a 100644 --- a/src/pal/tests/palsuite/c_runtime/fflush/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fflush/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_fflush_test1 diff --git a/src/pal/tests/palsuite/c_runtime/fflush/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fflush/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fflush/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/fflush/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fgets/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fgets/test1/CMakeLists.txt index 672d910..d327d68 100644 --- a/src/pal/tests/palsuite/c_runtime/fgets/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fgets/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_fgets_test1 diff --git a/src/pal/tests/palsuite/c_runtime/fgets/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fgets/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fgets/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/fgets/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fgets/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fgets/test2/CMakeLists.txt index d394015..23bcdef 100644 --- a/src/pal/tests/palsuite/c_runtime/fgets/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fgets/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_fgets_test2 diff --git a/src/pal/tests/palsuite/c_runtime/fgets/test2/test2.c b/src/pal/tests/palsuite/c_runtime/fgets/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fgets/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/fgets/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fgets/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fgets/test3/CMakeLists.txt index 50f0901..0833ad0 100644 --- a/src/pal/tests/palsuite/c_runtime/fgets/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fgets/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_fgets_test3 diff --git a/src/pal/tests/palsuite/c_runtime/fgets/test3/test3.c b/src/pal/tests/palsuite/c_runtime/fgets/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fgets/test3/test3.c rename to src/pal/tests/palsuite/c_runtime/fgets/test3/test3.cpp diff --git a/src/pal/tests/palsuite/c_runtime/floor/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/floor/test1/CMakeLists.txt index dbc5abd..3222ed8 100644 --- a/src/pal/tests/palsuite/c_runtime/floor/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/floor/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_floor_test1 diff --git a/src/pal/tests/palsuite/c_runtime/floor/test1/test1.c b/src/pal/tests/palsuite/c_runtime/floor/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/floor/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/floor/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/floorf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/floorf/CMakeLists.txt new file mode 100644 index 0000000..5e1ef7f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/floorf/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) diff --git a/src/pal/tests/palsuite/c_runtime/floorf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/floorf/test1/CMakeLists.txt new file mode 100644 index 0000000..f6e24ad --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/floorf/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_floorf_test1 + ${SOURCES} +) + +add_dependencies(paltest_floorf_test1 coreclrpal) + +target_link_libraries(paltest_floorf_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/floorf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/floorf/test1/test1.c new file mode 100644 index 0000000..57dca21 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/floorf/test1/test1.c @@ -0,0 +1,131 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests floorf with simple positive and negative values. Also tests +** extreme cases like extremely small values and positive and +** negative infinity. Makes sure that calling floorf on NaN returns +** NaN +** +**==========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = floorf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("floorf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = floorf(value); + + if (!_isnanf(result)) + { + Fail("floorf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char *argv[]) +{ + struct test tests[] = + { + /* value expected variance */ + { 0.318309886f, 0, PAL_EPSILON }, // value: 1 / pi + { 0.434294482f, 0, PAL_EPSILON }, // value: log10f(e) + { 0.636619772f, 0, PAL_EPSILON }, // value: 2 / pi + { 0.693147181f, 0, PAL_EPSILON }, // value: ln(2) + { 0.707106781f, 0, PAL_EPSILON }, // value: 1 / sqrtf(2) + { 0.785398163f, 0, PAL_EPSILON }, // value: pi / 4 + { 1.12837917f, 1, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi) + { 1.41421356f, 1, PAL_EPSILON * 10 }, // value: sqrtf(2) + { 1.44269504f, 1, PAL_EPSILON * 10 }, // value: logf2(e) + { 1.57079633f, 1, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.30258509f, 2, PAL_EPSILON * 10 }, // value: ln(10) + { 2.71828183f, 2, PAL_EPSILON * 10 }, // value: e + { 3.14159265f, 3, PAL_EPSILON * 10 }, // value: pi + { PAL_POSINF, PAL_POSINF, 0 } + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + validate( 0, 0, PAL_EPSILON); + validate(-0.0f, 0, PAL_EPSILON); + + validate( 1, 1, PAL_EPSILON * 10); + validate(-1.0f, -1, PAL_EPSILON * 10); + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -(tests[i].expected + 1), tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/floorf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/floorf/test1/testinfo.dat new file mode 100644 index 0000000..0065401 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/floorf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = floorf +Name = Positive Test for floorf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to floorf() a series of value, checking that += each one return to correct value. diff --git a/src/pal/tests/palsuite/c_runtime/fmod/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fmod/test1/CMakeLists.txt index c76df1f..33fbfb2 100644 --- a/src/pal/tests/palsuite/c_runtime/fmod/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fmod/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_fmod_test1 diff --git a/src/pal/tests/palsuite/c_runtime/fmod/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fmod/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fmod/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/fmod/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fmodf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fmodf/test1/CMakeLists.txt index d1ea238..487b3ad 100644 --- a/src/pal/tests/palsuite/c_runtime/fmodf/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fmodf/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_fmodf_test1 diff --git a/src/pal/tests/palsuite/c_runtime/fmodf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fmodf/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fmodf/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/fmodf/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fopen/test1/CMakeLists.txt index 6578c43..7603fc6 100644 --- a/src/pal/tests/palsuite/c_runtime/fopen/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fopen/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_fopen_test1 diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fopen/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fopen/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/fopen/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fopen/test2/CMakeLists.txt index 4458ed2..b856992 100644 --- a/src/pal/tests/palsuite/c_runtime/fopen/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fopen/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_fopen_test2 diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test2/test2.c b/src/pal/tests/palsuite/c_runtime/fopen/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fopen/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/fopen/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fopen/test3/CMakeLists.txt index 2c80f72..5b28caf 100644 --- a/src/pal/tests/palsuite/c_runtime/fopen/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fopen/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_fopen_test3 diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test3/test3.c b/src/pal/tests/palsuite/c_runtime/fopen/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fopen/test3/test3.c rename to src/pal/tests/palsuite/c_runtime/fopen/test3/test3.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fopen/test4/CMakeLists.txt index 92e0ef0..db5779f 100644 --- a/src/pal/tests/palsuite/c_runtime/fopen/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fopen/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_fopen_test4 diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test4/test4.c b/src/pal/tests/palsuite/c_runtime/fopen/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fopen/test4/test4.c rename to src/pal/tests/palsuite/c_runtime/fopen/test4/test4.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fopen/test5/CMakeLists.txt index 82529b9..6341e4a 100644 --- a/src/pal/tests/palsuite/c_runtime/fopen/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fopen/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_fopen_test5 diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test5/test5.c b/src/pal/tests/palsuite/c_runtime/fopen/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fopen/test5/test5.c rename to src/pal/tests/palsuite/c_runtime/fopen/test5/test5.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fopen/test6/CMakeLists.txt index 9a01cfb..39cf915 100644 --- a/src/pal/tests/palsuite/c_runtime/fopen/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fopen/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test6.c + test6.cpp ) add_executable(paltest_fopen_test6 diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test6/test6.c b/src/pal/tests/palsuite/c_runtime/fopen/test6/test6.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fopen/test6/test6.c rename to src/pal/tests/palsuite/c_runtime/fopen/test6/test6.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fopen/test7/CMakeLists.txt index 168a5af..ee22e34 100644 --- a/src/pal/tests/palsuite/c_runtime/fopen/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fopen/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test7.c + test7.cpp ) add_executable(paltest_fopen_test7 diff --git a/src/pal/tests/palsuite/c_runtime/fopen/test7/test7.c b/src/pal/tests/palsuite/c_runtime/fopen/test7/test7.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fopen/test7/test7.c rename to src/pal/tests/palsuite/c_runtime/fopen/test7/test7.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/fprintf.h b/src/pal/tests/palsuite/c_runtime/fprintf/fprintf.h index 380eb0a..87ee0d1 100644 --- a/src/pal/tests/palsuite/c_runtime/fprintf/fprintf.h +++ b/src/pal/tests/palsuite/c_runtime/fprintf/fprintf.h @@ -11,7 +11,7 @@ function with this as a return type. #ifndef __FPRINTF_H__ #define __FPRINTF_H__ -void DoStrTest(char *formatstr, char* param, char *checkstr) +void DoStrTest(const char *formatstr, char* param, const char *checkstr) { FILE *fp; char buf[256] = { 0 }; @@ -34,7 +34,7 @@ void DoStrTest(char *formatstr, char* param, char *checkstr) fclose(fp); } -void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr) +void DoWStrTest(const char *formatstr, WCHAR* param, const char *checkstr) { FILE *fp; char buf[256] = { 0 }; @@ -58,7 +58,7 @@ void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr) } -void DoCharTest(char *formatstr, char param, char *checkstr) +void DoCharTest(const char *formatstr, char param, const char *checkstr) { FILE *fp; char buf[256] = { 0 }; @@ -81,7 +81,7 @@ void DoCharTest(char *formatstr, char param, char *checkstr) fclose(fp); } -void DoWCharTest(char *formatstr, WCHAR param, char *checkstr) +void DoWCharTest(const char *formatstr, WCHAR param, const char *checkstr) { FILE *fp; char buf[256] = { 0 }; @@ -104,7 +104,7 @@ void DoWCharTest(char *formatstr, WCHAR param, char *checkstr) fclose(fp); } -void DoNumTest(char *formatstr, int value, char *checkstr) +void DoNumTest(const char *formatstr, int value, const char *checkstr) { FILE *fp; char buf[256] = { 0 }; @@ -127,7 +127,7 @@ void DoNumTest(char *formatstr, int value, char *checkstr) fclose(fp); } -void DoI64Test(char *formatstr, INT64 value, char *valuestr, char *checkstr1, char *checkstr2) +void DoI64Test(const char *formatstr, INT64 value, char *valuestr, const char *checkstr1, const char *checkstr2) { FILE *fp; char buf[256] = { 0 }; @@ -151,7 +151,7 @@ void DoI64Test(char *formatstr, INT64 value, char *valuestr, char *checkstr1, ch fclose(fp); } -void DoDoubleTest(char *formatstr, double value, char *checkstr1, char *checkstr2) +void DoDoubleTest(const char *formatstr, double value, const char *checkstr1, const char *checkstr2) { FILE *fp; char buf[256] = { 0 }; diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test1/CMakeLists.txt index ab41765..60ffd49 100644 --- a/src/pal/tests/palsuite/c_runtime/fprintf/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fprintf/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_fprintf_test1 diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fprintf/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fprintf/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/fprintf/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test10/CMakeLists.txt index f718ad7..3fb57c2 100644 --- a/src/pal/tests/palsuite/c_runtime/fprintf/test10/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fprintf/test10/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test10.c + test10.cpp ) add_executable(paltest_fprintf_test10 diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/fprintf/test10/test10.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fprintf/test10/test10.c rename to src/pal/tests/palsuite/c_runtime/fprintf/test10/test10.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test11/CMakeLists.txt index 6ccd58d..d325ce2 100644 --- a/src/pal/tests/palsuite/c_runtime/fprintf/test11/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fprintf/test11/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test11.c + test11.cpp ) add_executable(paltest_fprintf_test11 diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/fprintf/test11/test11.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fprintf/test11/test11.c rename to src/pal/tests/palsuite/c_runtime/fprintf/test11/test11.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test12/CMakeLists.txt index 17bc7f1..8bd3970 100644 --- a/src/pal/tests/palsuite/c_runtime/fprintf/test12/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fprintf/test12/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test12.c + test12.cpp ) add_executable(paltest_fprintf_test12 diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/fprintf/test12/test12.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fprintf/test12/test12.c rename to src/pal/tests/palsuite/c_runtime/fprintf/test12/test12.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test13/CMakeLists.txt index c6eb0f9..702058b 100644 --- a/src/pal/tests/palsuite/c_runtime/fprintf/test13/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fprintf/test13/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test13.c + test13.cpp ) add_executable(paltest_fprintf_test13 diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/fprintf/test13/test13.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fprintf/test13/test13.c rename to src/pal/tests/palsuite/c_runtime/fprintf/test13/test13.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test14/CMakeLists.txt index 6bb281b..b92ede7 100644 --- a/src/pal/tests/palsuite/c_runtime/fprintf/test14/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fprintf/test14/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test14.c + test14.cpp ) add_executable(paltest_fprintf_test14 diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/fprintf/test14/test14.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fprintf/test14/test14.c rename to src/pal/tests/palsuite/c_runtime/fprintf/test14/test14.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test15/CMakeLists.txt index ce1a8b6..20f1e42 100644 --- a/src/pal/tests/palsuite/c_runtime/fprintf/test15/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fprintf/test15/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test15.c + test15.cpp ) add_executable(paltest_fprintf_test15 diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/fprintf/test15/test15.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fprintf/test15/test15.c rename to src/pal/tests/palsuite/c_runtime/fprintf/test15/test15.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test16/CMakeLists.txt index 011cd13..8d72421 100644 --- a/src/pal/tests/palsuite/c_runtime/fprintf/test16/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fprintf/test16/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test16.c + test16.cpp ) add_executable(paltest_fprintf_test16 diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/fprintf/test16/test16.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fprintf/test16/test16.c rename to src/pal/tests/palsuite/c_runtime/fprintf/test16/test16.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test17/CMakeLists.txt index 4516f4b..82d1f84 100644 --- a/src/pal/tests/palsuite/c_runtime/fprintf/test17/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fprintf/test17/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test17.c + test17.cpp ) add_executable(paltest_fprintf_test17 diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/fprintf/test17/test17.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fprintf/test17/test17.c rename to src/pal/tests/palsuite/c_runtime/fprintf/test17/test17.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test18/CMakeLists.txt index fc03502..1ca54e4 100644 --- a/src/pal/tests/palsuite/c_runtime/fprintf/test18/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fprintf/test18/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test18.c + test18.cpp ) add_executable(paltest_fprintf_test18 diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/fprintf/test18/test18.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fprintf/test18/test18.c rename to src/pal/tests/palsuite/c_runtime/fprintf/test18/test18.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test19/CMakeLists.txt index 3781b42..2c66239 100644 --- a/src/pal/tests/palsuite/c_runtime/fprintf/test19/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fprintf/test19/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test19.c + test19.cpp ) add_executable(paltest_fprintf_test19 diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/fprintf/test19/test19.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fprintf/test19/test19.c rename to src/pal/tests/palsuite/c_runtime/fprintf/test19/test19.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test2/CMakeLists.txt index 0ef44b6..ae1d9dc 100644 --- a/src/pal/tests/palsuite/c_runtime/fprintf/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fprintf/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_fprintf_test2 diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/fprintf/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fprintf/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/fprintf/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test3/CMakeLists.txt index adfd36f..4b10c4c 100644 --- a/src/pal/tests/palsuite/c_runtime/fprintf/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fprintf/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_fprintf_test3 diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/fprintf/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fprintf/test3/test3.c rename to src/pal/tests/palsuite/c_runtime/fprintf/test3/test3.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test4/CMakeLists.txt index 7d471b1..292bdb6 100644 --- a/src/pal/tests/palsuite/c_runtime/fprintf/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fprintf/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_fprintf_test4 diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/fprintf/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fprintf/test4/test4.c rename to src/pal/tests/palsuite/c_runtime/fprintf/test4/test4.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test5/CMakeLists.txt index 1e3a568..370ed33 100644 --- a/src/pal/tests/palsuite/c_runtime/fprintf/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fprintf/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_fprintf_test5 diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/fprintf/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fprintf/test5/test5.c rename to src/pal/tests/palsuite/c_runtime/fprintf/test5/test5.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test6/CMakeLists.txt index 89620dd..bd1cbda 100644 --- a/src/pal/tests/palsuite/c_runtime/fprintf/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fprintf/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test6.c + test6.cpp ) add_executable(paltest_fprintf_test6 diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/fprintf/test6/test6.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fprintf/test6/test6.c rename to src/pal/tests/palsuite/c_runtime/fprintf/test6/test6.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test7/CMakeLists.txt index 3dc10dd..38429e7 100644 --- a/src/pal/tests/palsuite/c_runtime/fprintf/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fprintf/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test7.c + test7.cpp ) add_executable(paltest_fprintf_test7 diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/fprintf/test7/test7.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fprintf/test7/test7.c rename to src/pal/tests/palsuite/c_runtime/fprintf/test7/test7.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test8/CMakeLists.txt index f6dd984..990eca2 100644 --- a/src/pal/tests/palsuite/c_runtime/fprintf/test8/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fprintf/test8/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test8.c + test8.cpp ) add_executable(paltest_fprintf_test8 diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/fprintf/test8/test8.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fprintf/test8/test8.c rename to src/pal/tests/palsuite/c_runtime/fprintf/test8/test8.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fprintf/test9/CMakeLists.txt index 62aa85e..715d38a 100644 --- a/src/pal/tests/palsuite/c_runtime/fprintf/test9/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fprintf/test9/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test9.c + test9.cpp ) add_executable(paltest_fprintf_test9 diff --git a/src/pal/tests/palsuite/c_runtime/fprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/fprintf/test9/test9.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fprintf/test9/test9.c rename to src/pal/tests/palsuite/c_runtime/fprintf/test9/test9.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fputs/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fputs/test1/CMakeLists.txt index e4a92d5..d0f1aca 100644 --- a/src/pal/tests/palsuite/c_runtime/fputs/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fputs/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_fputs_test1 diff --git a/src/pal/tests/palsuite/c_runtime/fputs/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fputs/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fputs/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/fputs/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fputs/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fputs/test2/CMakeLists.txt index 6e939f3..9242ea1 100644 --- a/src/pal/tests/palsuite/c_runtime/fputs/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fputs/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_fputs_test2 diff --git a/src/pal/tests/palsuite/c_runtime/fputs/test2/test2.c b/src/pal/tests/palsuite/c_runtime/fputs/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fputs/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/fputs/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fread/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fread/test1/CMakeLists.txt index a2e0957..1bd84b5 100644 --- a/src/pal/tests/palsuite/c_runtime/fread/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fread/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_fread_test1 diff --git a/src/pal/tests/palsuite/c_runtime/fread/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fread/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fread/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/fread/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fread/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fread/test2/CMakeLists.txt index 0538e0c..93e0394 100644 --- a/src/pal/tests/palsuite/c_runtime/fread/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fread/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_fread_test2 diff --git a/src/pal/tests/palsuite/c_runtime/fread/test2/test2.c b/src/pal/tests/palsuite/c_runtime/fread/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fread/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/fread/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fread/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fread/test3/CMakeLists.txt index f3c636f..285608b 100644 --- a/src/pal/tests/palsuite/c_runtime/fread/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fread/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_fread_test3 diff --git a/src/pal/tests/palsuite/c_runtime/fread/test3/test3.c b/src/pal/tests/palsuite/c_runtime/fread/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fread/test3/test3.c rename to src/pal/tests/palsuite/c_runtime/fread/test3/test3.cpp diff --git a/src/pal/tests/palsuite/c_runtime/free/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/free/test1/CMakeLists.txt index bd94cb5..92ee989 100644 --- a/src/pal/tests/palsuite/c_runtime/free/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/free/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_free_test1 diff --git a/src/pal/tests/palsuite/c_runtime/free/test1/test1.c b/src/pal/tests/palsuite/c_runtime/free/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/free/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/free/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fseek/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fseek/test1/CMakeLists.txt index fb55bd1..59ee8b4 100644 --- a/src/pal/tests/palsuite/c_runtime/fseek/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fseek/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_fseek_test1 diff --git a/src/pal/tests/palsuite/c_runtime/fseek/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fseek/test1/test1.c deleted file mode 100644 index 8496289..0000000 --- a/src/pal/tests/palsuite/c_runtime/fseek/test1/test1.c +++ /dev/null @@ -1,193 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: Call fseek to move a file pointer to the start of a file, -** a position offset from the start, a position offset from the -** current position, and a position offset from the end of the -** file. Check that the file pointer is at the correct position -** after each seek. -** -** -**==========================================================================*/ - -#include - -const char filename[] = "testfile.txt"; - -static BOOL Cleanup(HANDLE hFile) -{ - BOOL result= TRUE; - - if (fclose(hFile)) - { - Trace("fseek: ERROR -> Unable to close file \"%s\".\n", - filename); - result= FALSE; - } - if (!DeleteFileA(filename)) - { - result= FALSE; - Trace("fseek: ERROR -> Unable to delete file \"%s\". ", - "GetLastError returned %u.\n", - filename, - GetLastError()); - } - return result; -} - -int __cdecl main(int argc, char **argv) -{ - char outBuf[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - char inBuf[20]; - FILE * fp; - int size = ( sizeof(outBuf)/sizeof(char) ) - 1; - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - /*create the file*/ - fp = fopen(filename, "w"); - if (fp == NULL) - { - Fail("Unable to open a file for write.\n"); - } - if(fprintf(fp, outBuf) != size) - { - Trace("Unable to write to %s.\n", filename); - Cleanup(fp); - Fail(""); - } - - if (fclose(fp) != 0) - { - Trace("Unable to close newly written file.\n"); - if (!DeleteFileA(filename)) - { - Trace("fseek: ERROR -> Unable to delete file \"%s\". ", - "GetLastError returned %u.\n", - filename, - GetLastError()); - } - Fail(""); - } - - fp = fopen(filename, "r"); - if (fp == NULL) - { - if (!DeleteFileA(filename)) - { - Trace("_putw: ERROR -> Unable to delete file \"%s\". ", - "GetLastError returned %u.\n", - filename, - GetLastError()); - } - Fail("Unable to open a file for read.\n"); - } - - /*seek to the start*/ - if (fseek(fp, 0, SEEK_SET) != 0) - { - Cleanup(fp); - Fail("fseek failed when seeking the start of a file.\n"); - } - if (fgets(inBuf, 11, fp) != inBuf) - { - Cleanup(fp); - Fail("Unable to read from file after using fseek to move to the start.\n"); - } - if (strncmp(inBuf, outBuf, 10) != 0) - { - Cleanup(fp); - Fail("fseek was asked to seek the start of a file," - "but didn't get there.\n"); - } - - /*Seek with an offset from the start*/ - - if (fseek(fp, 10, SEEK_SET) != 0) - { - Cleanup(fp); - Fail("fseek failed when called with SEEK_SET and a positive offset.\n"); - } - - if (fgets(inBuf, 6, fp) != inBuf) - { - Cleanup(fp); - Fail("fgets failed after feek was called with SEEK_SET" - "and a positive offset.\n"); - } - - - if (strncmp(inBuf, "ABCDE", 5) != 0) - { - Cleanup(fp); - Fail("fseek did not move to the correct position when passed SEEK_SET" - " and a positive offset.\n"); - } - - /*now move backwards and read the same string*/ - if (fseek(fp, -5, SEEK_CUR) != 0) - { - Cleanup(fp); - Fail("fseek failed when passed SEEK_CUR and a negative offset.\n"); - } - - if (fgets(inBuf, 6, fp) != inBuf) - { - Cleanup(fp); - Fail("fgets failed after fseek was called with SEEK_CUR and a " - "negative offset.\n"); - } - - if (strncmp(inBuf, "ABCDE", 5) != 0) - { - Cleanup(fp); - Fail("fseek did not move to the correct position when called with" - " SEEK_CUR and a negative offset.\n"); - } - - /*Try seeking relative to the end of the file.*/ - if (fseek(fp, -10, SEEK_END) != 0) - { - Cleanup(fp); - Fail("fseek failed when called with SEEK_END and a negative" - " offset.\n"); - } - if (fgets(inBuf, 2, fp) != inBuf) - { - Cleanup(fp); - Fail("fgets failed after fseek was called with SEEK_END and a " - "negative offset\n"); - } - - if (strncmp(inBuf, "Q", 1) != 0) - { - Cleanup(fp); - Fail("fseek did not move to the correct position when called with " - "SEEK_END and a negative offset.\n"); - } - - - /*close the file*/ - if(!Cleanup(fp)) - { - Fail(""); - } - - PAL_Terminate(); - return PASS; -} - - - - - - diff --git a/src/pal/tests/palsuite/c_runtime/fseek/test1/test1.cpp b/src/pal/tests/palsuite/c_runtime/fseek/test1/test1.cpp new file mode 100644 index 0000000..dd1e87e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/fseek/test1/test1.cpp @@ -0,0 +1,193 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Call fseek to move a file pointer to the start of a file, +** a position offset from the start, a position offset from the +** current position, and a position offset from the end of the +** file. Check that the file pointer is at the correct position +** after each seek. +** +** +**==========================================================================*/ + +#include + +const char filename[] = "testfile.txt"; + +static BOOL Cleanup(HANDLE hFile) +{ + BOOL result= TRUE; + + if (fclose((PAL_FILE*)hFile)) + { + Trace("fseek: ERROR -> Unable to close file \"%s\".\n", + filename); + result= FALSE; + } + if (!DeleteFileA(filename)) + { + result= FALSE; + Trace("fseek: ERROR -> Unable to delete file \"%s\". ", + "GetLastError returned %u.\n", + filename, + GetLastError()); + } + return result; +} + +int __cdecl main(int argc, char **argv) +{ + char outBuf[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + char inBuf[20]; + FILE * fp; + int size = ( sizeof(outBuf)/sizeof(char) ) - 1; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + /*create the file*/ + fp = fopen(filename, "w"); + if (fp == NULL) + { + Fail("Unable to open a file for write.\n"); + } + if(fprintf(fp, outBuf) != size) + { + Trace("Unable to write to %s.\n", filename); + Cleanup(fp); + Fail(""); + } + + if (fclose(fp) != 0) + { + Trace("Unable to close newly written file.\n"); + if (!DeleteFileA(filename)) + { + Trace("fseek: ERROR -> Unable to delete file \"%s\". ", + "GetLastError returned %u.\n", + filename, + GetLastError()); + } + Fail(""); + } + + fp = fopen(filename, "r"); + if (fp == NULL) + { + if (!DeleteFileA(filename)) + { + Trace("_putw: ERROR -> Unable to delete file \"%s\". ", + "GetLastError returned %u.\n", + filename, + GetLastError()); + } + Fail("Unable to open a file for read.\n"); + } + + /*seek to the start*/ + if (fseek(fp, 0, SEEK_SET) != 0) + { + Cleanup(fp); + Fail("fseek failed when seeking the start of a file.\n"); + } + if (fgets(inBuf, 11, fp) != inBuf) + { + Cleanup(fp); + Fail("Unable to read from file after using fseek to move to the start.\n"); + } + if (strncmp(inBuf, outBuf, 10) != 0) + { + Cleanup(fp); + Fail("fseek was asked to seek the start of a file," + "but didn't get there.\n"); + } + + /*Seek with an offset from the start*/ + + if (fseek(fp, 10, SEEK_SET) != 0) + { + Cleanup(fp); + Fail("fseek failed when called with SEEK_SET and a positive offset.\n"); + } + + if (fgets(inBuf, 6, fp) != inBuf) + { + Cleanup(fp); + Fail("fgets failed after feek was called with SEEK_SET" + "and a positive offset.\n"); + } + + + if (strncmp(inBuf, "ABCDE", 5) != 0) + { + Cleanup(fp); + Fail("fseek did not move to the correct position when passed SEEK_SET" + " and a positive offset.\n"); + } + + /*now move backwards and read the same string*/ + if (fseek(fp, -5, SEEK_CUR) != 0) + { + Cleanup(fp); + Fail("fseek failed when passed SEEK_CUR and a negative offset.\n"); + } + + if (fgets(inBuf, 6, fp) != inBuf) + { + Cleanup(fp); + Fail("fgets failed after fseek was called with SEEK_CUR and a " + "negative offset.\n"); + } + + if (strncmp(inBuf, "ABCDE", 5) != 0) + { + Cleanup(fp); + Fail("fseek did not move to the correct position when called with" + " SEEK_CUR and a negative offset.\n"); + } + + /*Try seeking relative to the end of the file.*/ + if (fseek(fp, -10, SEEK_END) != 0) + { + Cleanup(fp); + Fail("fseek failed when called with SEEK_END and a negative" + " offset.\n"); + } + if (fgets(inBuf, 2, fp) != inBuf) + { + Cleanup(fp); + Fail("fgets failed after fseek was called with SEEK_END and a " + "negative offset\n"); + } + + if (strncmp(inBuf, "Q", 1) != 0) + { + Cleanup(fp); + Fail("fseek did not move to the correct position when called with " + "SEEK_END and a negative offset.\n"); + } + + + /*close the file*/ + if(!Cleanup(fp)) + { + Fail(""); + } + + PAL_Terminate(); + return PASS; +} + + + + + + diff --git a/src/pal/tests/palsuite/c_runtime/ftell/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ftell/test1/CMakeLists.txt index 7ea9a51..a1f350d 100644 --- a/src/pal/tests/palsuite/c_runtime/ftell/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/ftell/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - ftell.c + ftell.cpp ) add_executable(paltest_ftell_test1 diff --git a/src/pal/tests/palsuite/c_runtime/ftell/test1/ftell.c b/src/pal/tests/palsuite/c_runtime/ftell/test1/ftell.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/ftell/test1/ftell.c rename to src/pal/tests/palsuite/c_runtime/ftell/test1/ftell.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/fwprintf.h b/src/pal/tests/palsuite/c_runtime/fwprintf/fwprintf.h index 3675663..eed0e76 100644 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/fwprintf.h +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/fwprintf.h @@ -14,7 +14,7 @@ #ifndef __fwprintf_H__ #define __fwprintf_H__ -void DoStrTest(WCHAR *formatstr, char* param, char *checkstr) +void DoStrTest(const WCHAR *formatstr, char* param, const char *checkstr) { FILE *fp; char buf[256] = { 0 }; @@ -45,7 +45,7 @@ void DoStrTest(WCHAR *formatstr, char* param, char *checkstr) fclose(fp); } -void DoWStrTest(WCHAR *formatstr, WCHAR* param, char *checkstr) +void DoWStrTest(const WCHAR *formatstr, WCHAR* param, const char *checkstr) { FILE *fp; char buf[256] = { 0 }; @@ -77,8 +77,8 @@ void DoWStrTest(WCHAR *formatstr, WCHAR* param, char *checkstr) } -void DoPointerTest(WCHAR *formatstr, void* param, char* paramstr, - char *checkstr1, char *checkstr2) +void DoPointerTest(const WCHAR *formatstr, void* param, char* paramstr, + const char *checkstr1, const char *checkstr2) { FILE *fp; char buf[256] = { 0 }; @@ -119,7 +119,7 @@ void DoPointerTest(WCHAR *formatstr, void* param, char* paramstr, -void DoCountTest(WCHAR *formatstr, int param, char *checkstr) +void DoCountTest(const WCHAR *formatstr, int param, const char *checkstr) { FILE *fp; char buf[512] = { 0 }; @@ -162,7 +162,7 @@ void DoCountTest(WCHAR *formatstr, int param, char *checkstr) } } -void DoShortCountTest(WCHAR *formatstr, int param, char *checkstr) +void DoShortCountTest(const WCHAR *formatstr, int param, const char *checkstr) { FILE *fp; char buf[512] = { 0 }; @@ -206,7 +206,7 @@ void DoShortCountTest(WCHAR *formatstr, int param, char *checkstr) } -void DoCharTest(WCHAR *formatstr, char param, char *checkstr) +void DoCharTest(const WCHAR *formatstr, char param, const char *checkstr) { FILE *fp; char buf[256] = { 0 }; @@ -237,7 +237,7 @@ void DoCharTest(WCHAR *formatstr, char param, char *checkstr) fclose(fp); } -void DoWCharTest(WCHAR *formatstr, WCHAR param, char *checkstr) +void DoWCharTest(const WCHAR *formatstr, WCHAR param, const char *checkstr) { FILE *fp; char buf[256] = { 0 }; @@ -268,7 +268,7 @@ void DoWCharTest(WCHAR *formatstr, WCHAR param, char *checkstr) fclose(fp); } -void DoNumTest(WCHAR *formatstr, int value, char *checkstr) +void DoNumTest(const WCHAR *formatstr, int value, const char *checkstr) { FILE *fp; char buf[256] = { 0 }; @@ -299,8 +299,8 @@ void DoNumTest(WCHAR *formatstr, int value, char *checkstr) fclose(fp); } -void DoI64Test(WCHAR *formatstr, INT64 value, char *valuestr, char *checkstr1, - char *checkstr2) +void DoI64Test(const WCHAR *formatstr, INT64 value, char *valuestr, const char *checkstr1, + const char *checkstr2) { FILE *fp; char buf[256] = { 0 }; @@ -332,8 +332,8 @@ void DoI64Test(WCHAR *formatstr, INT64 value, char *valuestr, char *checkstr1, fclose(fp); } -void DoDoubleTest(WCHAR *formatstr, double value, char *checkstr1, - char *checkstr2) +void DoDoubleTest(const WCHAR *formatstr, double value, const char *checkstr1, + const char *checkstr2) { FILE *fp; char buf[256] = { 0 }; @@ -367,8 +367,8 @@ void DoDoubleTest(WCHAR *formatstr, double value, char *checkstr1, } -void DoArgumentPrecTest(WCHAR *formatstr, int precision, void *param, - char *paramstr, char *checkstr1, char *checkstr2) +void DoArgumentPrecTest(const WCHAR *formatstr, int precision, void *param, + char *paramstr, const char *checkstr1, const char *checkstr2) { FILE *fp; char buf[256]; @@ -409,8 +409,8 @@ void DoArgumentPrecTest(WCHAR *formatstr, int precision, void *param, } -void DoArgumentPrecDoubleTest(WCHAR *formatstr, int precision, double param, - char *checkstr1, char *checkstr2) +void DoArgumentPrecDoubleTest(const WCHAR *formatstr, int precision, double param, + const char *checkstr1, const char *checkstr2) { FILE *fp; char buf[256]; diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test1/CMakeLists.txt index ce4271e..519860b 100644 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_fwprintf_test1 diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fwprintf/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/fwprintf/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test10/CMakeLists.txt index a8323b4..e604e03 100644 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/test10/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test10/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test10.c + test10.cpp ) add_executable(paltest_fwprintf_test10 diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test10/test10.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fwprintf/test10/test10.c rename to src/pal/tests/palsuite/c_runtime/fwprintf/test10/test10.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test11/CMakeLists.txt index 1b79874..18be522 100644 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/test11/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test11/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test11.c + test11.cpp ) add_executable(paltest_fwprintf_test11 diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test11/test11.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fwprintf/test11/test11.c rename to src/pal/tests/palsuite/c_runtime/fwprintf/test11/test11.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test12/CMakeLists.txt index 1e43a4c..6ea739b 100644 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/test12/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test12/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test12.c + test12.cpp ) add_executable(paltest_fwprintf_test12 diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test12/test12.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fwprintf/test12/test12.c rename to src/pal/tests/palsuite/c_runtime/fwprintf/test12/test12.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test13/CMakeLists.txt index c84dc3e..8505ccb 100644 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/test13/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test13/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test13.c + test13.cpp ) add_executable(paltest_fwprintf_test13 diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test13/test13.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fwprintf/test13/test13.c rename to src/pal/tests/palsuite/c_runtime/fwprintf/test13/test13.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test14/CMakeLists.txt index 97824c7..548e60f 100644 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/test14/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test14/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test14.c + test14.cpp ) add_executable(paltest_fwprintf_test14 diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test14/test14.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fwprintf/test14/test14.c rename to src/pal/tests/palsuite/c_runtime/fwprintf/test14/test14.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test15/CMakeLists.txt index 6786c5b..c5b5346 100644 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/test15/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test15/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test15.c + test15.cpp ) add_executable(paltest_fwprintf_test15 diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test15/test15.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fwprintf/test15/test15.c rename to src/pal/tests/palsuite/c_runtime/fwprintf/test15/test15.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test16/CMakeLists.txt index be14870..51af0a0 100644 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/test16/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test16/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test16.c + test16.cpp ) add_executable(paltest_fwprintf_test16 diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test16/test16.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fwprintf/test16/test16.c rename to src/pal/tests/palsuite/c_runtime/fwprintf/test16/test16.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test17/CMakeLists.txt index b390d15..9ed8a39 100644 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/test17/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test17/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test17.c + test17.cpp ) add_executable(paltest_fwprintf_test17 diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test17/test17.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fwprintf/test17/test17.c rename to src/pal/tests/palsuite/c_runtime/fwprintf/test17/test17.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test18/CMakeLists.txt index 6f6d79b..3e3ba4e 100644 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/test18/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test18/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test18.c + test18.cpp ) add_executable(paltest_fwprintf_test18 diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test18/test18.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fwprintf/test18/test18.c rename to src/pal/tests/palsuite/c_runtime/fwprintf/test18/test18.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test19/CMakeLists.txt index bc10825..fbb7370 100644 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/test19/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test19/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test19.c + test19.cpp ) add_executable(paltest_fwprintf_test19 diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test19/test19.c deleted file mode 100644 index 4600de7..0000000 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/test19/test19.c +++ /dev/null @@ -1,81 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test19.c -** -** Purpose: Tests the variable length precision argument. -** This test is modeled after the sprintf series. -** -** -**==========================================================================*/ - -#include -#include "../fwprintf.h" - -/* - * Depends on memcmp, strlen, fopen, fseek and fgets. - */ - - - -int __cdecl main(int argc, char *argv[]) -{ - int n = -1; - - if (PAL_Initialize(argc, argv) != 0) - { - return(FAIL); - } - - DoArgumentPrecTest(convert("%.*s"), 2, convert("bar"), "bar", "ba", "ba"); - DoArgumentPrecTest(convert("%.*S"), 2, "bar", "bar", "ba", "ba"); - DoArgumentPrecTest(convert("foo %.*n"), 3, &n, "pointer to int", "foo ", - "foo "); - if (n != 4) - { - Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", - 4, n); - } - - DoArgumentPrecTest(convert("%.*c"), 0, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest(convert("%.*c"), 4, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest(convert("%.*C"), 0, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest(convert("%.*C"), 4, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest(convert("%.*d"), 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest(convert("%.*d"), 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest(convert("%.*i"), 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest(convert("%.*i"), 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest(convert("%.*o"), 1, (void*)42, "42", "52", "52"); - DoArgumentPrecTest(convert("%.*o"), 3, (void*)42, "42", "052", "052"); - DoArgumentPrecTest(convert("%.*u"), 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest(convert("%.*u"), 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest(convert("%.*x"), 1, (void*)0x42, "0x42", "42", "42"); - DoArgumentPrecTest(convert("%.*x"), 3, (void*)0x42, "0x42", "042", "042"); - DoArgumentPrecTest(convert("%.*X"), 1, (void*)0x42, "0x42", "42", "42"); - DoArgumentPrecTest(convert("%.*X"), 3, (void*)0x42, "0x42", "042", "042"); - - - DoArgumentPrecDoubleTest(convert("%.*e"), 1, 2.01, "2.0e+000", "2.0e+00"); - DoArgumentPrecDoubleTest(convert("%.*e"), 3, 2.01, "2.010e+000", - "2.010e+00"); - DoArgumentPrecDoubleTest(convert("%.*E"), 1, 2.01, "2.0E+000", "2.0E+00"); - DoArgumentPrecDoubleTest(convert("%.*E"), 3, 2.01, "2.010E+000", - "2.010E+00"); - DoArgumentPrecDoubleTest(convert("%.*f"), 1, 2.01, "2.0", "2.0"); - DoArgumentPrecDoubleTest(convert("%.*f"), 3, 2.01, "2.010", "2.010"); - DoArgumentPrecDoubleTest(convert("%.*g"), 1, 256.01, "3e+002", "3e+02"); - DoArgumentPrecDoubleTest(convert("%.*g"), 3, 256.01, "256", "256"); - DoArgumentPrecDoubleTest(convert("%.*g"), 4, 256.01, "256", "256"); - DoArgumentPrecDoubleTest(convert("%.*g"), 6, 256.01, "256.01", "256.01"); - DoArgumentPrecDoubleTest(convert("%.*G"), 1, 256.01, "3E+002", "3E+02"); - DoArgumentPrecDoubleTest(convert("%.*G"), 3, 256.01, "256", "256"); - DoArgumentPrecDoubleTest(convert("%.*G"), 4, 256.01, "256", "256"); - DoArgumentPrecDoubleTest(convert("%.*G"), 6, 256.01, "256.01", "256.01"); - - PAL_Terminate(); - - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test19/test19.cpp b/src/pal/tests/palsuite/c_runtime/fwprintf/test19/test19.cpp new file mode 100644 index 0000000..a407c9f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test19/test19.cpp @@ -0,0 +1,81 @@ +// 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. + +/*============================================================================ +** +** Source: test19.c +** +** Purpose: Tests the variable length precision argument. +** This test is modeled after the sprintf series. +** +** +**==========================================================================*/ + +#include +#include "../fwprintf.h" + +/* + * Depends on memcmp, strlen, fopen, fseek and fgets. + */ + + + +int __cdecl main(int argc, char *argv[]) +{ + int n = -1; + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + DoArgumentPrecTest(convert("%.*s"), 2, (void*)convert("bar"), "bar", "ba", "ba"); + DoArgumentPrecTest(convert("%.*S"), 2, (void*)"bar", "bar", "ba", "ba"); + DoArgumentPrecTest(convert("foo %.*n"), 3, (void*)&n, "pointer to int", "foo ", + "foo "); + if (n != 4) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + 4, n); + } + + DoArgumentPrecTest(convert("%.*c"), 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest(convert("%.*c"), 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest(convert("%.*C"), 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest(convert("%.*C"), 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest(convert("%.*d"), 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest(convert("%.*d"), 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest(convert("%.*i"), 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest(convert("%.*i"), 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest(convert("%.*o"), 1, (void*)42, "42", "52", "52"); + DoArgumentPrecTest(convert("%.*o"), 3, (void*)42, "42", "052", "052"); + DoArgumentPrecTest(convert("%.*u"), 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest(convert("%.*u"), 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest(convert("%.*x"), 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest(convert("%.*x"), 3, (void*)0x42, "0x42", "042", "042"); + DoArgumentPrecTest(convert("%.*X"), 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest(convert("%.*X"), 3, (void*)0x42, "0x42", "042", "042"); + + + DoArgumentPrecDoubleTest(convert("%.*e"), 1, 2.01, "2.0e+000", "2.0e+00"); + DoArgumentPrecDoubleTest(convert("%.*e"), 3, 2.01, "2.010e+000", + "2.010e+00"); + DoArgumentPrecDoubleTest(convert("%.*E"), 1, 2.01, "2.0E+000", "2.0E+00"); + DoArgumentPrecDoubleTest(convert("%.*E"), 3, 2.01, "2.010E+000", + "2.010E+00"); + DoArgumentPrecDoubleTest(convert("%.*f"), 1, 2.01, "2.0", "2.0"); + DoArgumentPrecDoubleTest(convert("%.*f"), 3, 2.01, "2.010", "2.010"); + DoArgumentPrecDoubleTest(convert("%.*g"), 1, 256.01, "3e+002", "3e+02"); + DoArgumentPrecDoubleTest(convert("%.*g"), 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest(convert("%.*g"), 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest(convert("%.*g"), 6, 256.01, "256.01", "256.01"); + DoArgumentPrecDoubleTest(convert("%.*G"), 1, 256.01, "3E+002", "3E+02"); + DoArgumentPrecDoubleTest(convert("%.*G"), 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest(convert("%.*G"), 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest(convert("%.*G"), 6, 256.01, "256.01", "256.01"); + + PAL_Terminate(); + + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test2/CMakeLists.txt index 6431465..e65a396 100644 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_fwprintf_test2 diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fwprintf/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/fwprintf/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test3/CMakeLists.txt index 6906722..53c4636 100644 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_fwprintf_test3 diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fwprintf/test3/test3.c rename to src/pal/tests/palsuite/c_runtime/fwprintf/test3/test3.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test4/CMakeLists.txt index b91bc87..9dbb462 100644 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_fwprintf_test4 diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fwprintf/test4/test4.c rename to src/pal/tests/palsuite/c_runtime/fwprintf/test4/test4.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test5/CMakeLists.txt index 53bf482..4e72e3c 100644 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_fwprintf_test5 diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fwprintf/test5/test5.c rename to src/pal/tests/palsuite/c_runtime/fwprintf/test5/test5.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test6/CMakeLists.txt index bf7d7cc..d57f07f 100644 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test6.c + test6.cpp ) add_executable(paltest_fwprintf_test6 diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test6/test6.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fwprintf/test6/test6.c rename to src/pal/tests/palsuite/c_runtime/fwprintf/test6/test6.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test7/CMakeLists.txt index 68bcc9c..314ca35 100644 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test7.c + test7.cpp ) add_executable(paltest_fwprintf_test7 diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test7/test7.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fwprintf/test7/test7.c rename to src/pal/tests/palsuite/c_runtime/fwprintf/test7/test7.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test8/CMakeLists.txt index e07cbb9..e818df2 100644 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/test8/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test8/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test8.c + test8.cpp ) add_executable(paltest_fwprintf_test8 diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test8/test8.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fwprintf/test8/test8.c rename to src/pal/tests/palsuite/c_runtime/fwprintf/test8/test8.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwprintf/test9/CMakeLists.txt index 898da1a..28b6b86 100644 --- a/src/pal/tests/palsuite/c_runtime/fwprintf/test9/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fwprintf/test9/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test9.c + test9.cpp ) add_executable(paltest_fwprintf_test9 diff --git a/src/pal/tests/palsuite/c_runtime/fwprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/fwprintf/test9/test9.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fwprintf/test9/test9.c rename to src/pal/tests/palsuite/c_runtime/fwprintf/test9/test9.cpp diff --git a/src/pal/tests/palsuite/c_runtime/fwrite/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/fwrite/test1/CMakeLists.txt index 701e56a..5c8b744 100644 --- a/src/pal/tests/palsuite/c_runtime/fwrite/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/fwrite/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_fwrite_test1 diff --git a/src/pal/tests/palsuite/c_runtime/fwrite/test1/test1.c b/src/pal/tests/palsuite/c_runtime/fwrite/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/fwrite/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/fwrite/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/getc/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/getc/test1/CMakeLists.txt index 2a29e8a..68ecaa9 100644 --- a/src/pal/tests/palsuite/c_runtime/getc/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/getc/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - getc.c + getc.cpp ) add_executable(paltest_getc_test1 diff --git a/src/pal/tests/palsuite/c_runtime/getc/test1/getc.c b/src/pal/tests/palsuite/c_runtime/getc/test1/getc.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/getc/test1/getc.c rename to src/pal/tests/palsuite/c_runtime/getc/test1/getc.cpp diff --git a/src/pal/tests/palsuite/c_runtime/getenv/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/getenv/test1/CMakeLists.txt index 6243c03..9c52c28 100644 --- a/src/pal/tests/palsuite/c_runtime/getenv/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/getenv/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_getenv_test1 diff --git a/src/pal/tests/palsuite/c_runtime/getenv/test1/test1.c b/src/pal/tests/palsuite/c_runtime/getenv/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/getenv/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/getenv/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/getenv/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/getenv/test2/CMakeLists.txt index 7a301a5..971a836 100644 --- a/src/pal/tests/palsuite/c_runtime/getenv/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/getenv/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_getenv_test2 diff --git a/src/pal/tests/palsuite/c_runtime/getenv/test2/test2.c b/src/pal/tests/palsuite/c_runtime/getenv/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/getenv/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/getenv/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/getenv/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/getenv/test3/CMakeLists.txt index 2cbe472..620ccd1 100644 --- a/src/pal/tests/palsuite/c_runtime/getenv/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/getenv/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_getenv_test3 diff --git a/src/pal/tests/palsuite/c_runtime/getenv/test3/test3.c b/src/pal/tests/palsuite/c_runtime/getenv/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/getenv/test3/test3.c rename to src/pal/tests/palsuite/c_runtime/getenv/test3/test3.cpp diff --git a/src/pal/tests/palsuite/c_runtime/isalnum/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isalnum/test1/CMakeLists.txt index 3879bb7..af65f32 100644 --- a/src/pal/tests/palsuite/c_runtime/isalnum/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/isalnum/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_isalnum_test1 diff --git a/src/pal/tests/palsuite/c_runtime/isalnum/test1/test1.c b/src/pal/tests/palsuite/c_runtime/isalnum/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/isalnum/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/isalnum/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/isalpha/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isalpha/test1/CMakeLists.txt index 44fb72d..82f19ad 100644 --- a/src/pal/tests/palsuite/c_runtime/isalpha/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/isalpha/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_isalpha_test1 diff --git a/src/pal/tests/palsuite/c_runtime/isalpha/test1/test1.c b/src/pal/tests/palsuite/c_runtime/isalpha/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/isalpha/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/isalpha/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/isdigit/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isdigit/test1/CMakeLists.txt index dd03b23..b96b7aa 100644 --- a/src/pal/tests/palsuite/c_runtime/isdigit/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/isdigit/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_isdigit_test1 diff --git a/src/pal/tests/palsuite/c_runtime/isdigit/test1/test1.c b/src/pal/tests/palsuite/c_runtime/isdigit/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/isdigit/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/isdigit/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/islower/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/islower/test1/CMakeLists.txt index b7f5ad0..d071d4b 100644 --- a/src/pal/tests/palsuite/c_runtime/islower/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/islower/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_islower_test1 diff --git a/src/pal/tests/palsuite/c_runtime/islower/test1/test1.c b/src/pal/tests/palsuite/c_runtime/islower/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/islower/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/islower/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/isprint/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isprint/test1/CMakeLists.txt index 365777a..91410a0 100644 --- a/src/pal/tests/palsuite/c_runtime/isprint/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/isprint/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - isprint.c + isprint.cpp ) add_executable(paltest_isprint_test1 diff --git a/src/pal/tests/palsuite/c_runtime/isprint/test1/isprint.c b/src/pal/tests/palsuite/c_runtime/isprint/test1/isprint.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/isprint/test1/isprint.c rename to src/pal/tests/palsuite/c_runtime/isprint/test1/isprint.cpp diff --git a/src/pal/tests/palsuite/c_runtime/isprint/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isprint/test2/CMakeLists.txt index a7ad75c..53ad942 100644 --- a/src/pal/tests/palsuite/c_runtime/isprint/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/isprint/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_isprint_test2 diff --git a/src/pal/tests/palsuite/c_runtime/isprint/test2/test2.c b/src/pal/tests/palsuite/c_runtime/isprint/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/isprint/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/isprint/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/isspace/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isspace/test1/CMakeLists.txt index 34ad70d..c3cc525 100644 --- a/src/pal/tests/palsuite/c_runtime/isspace/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/isspace/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_isspace_test1 diff --git a/src/pal/tests/palsuite/c_runtime/isspace/test1/test1.c b/src/pal/tests/palsuite/c_runtime/isspace/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/isspace/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/isspace/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/isupper/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isupper/test1/CMakeLists.txt index c7fc71c..e1cfa66 100644 --- a/src/pal/tests/palsuite/c_runtime/isupper/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/isupper/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_isupper_test1 diff --git a/src/pal/tests/palsuite/c_runtime/isupper/test1/test1.c b/src/pal/tests/palsuite/c_runtime/isupper/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/isupper/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/isupper/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/iswdigit/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/iswdigit/test1/CMakeLists.txt index b35dd5e..4074abb 100644 --- a/src/pal/tests/palsuite/c_runtime/iswdigit/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/iswdigit/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_iswdigit_test1 diff --git a/src/pal/tests/palsuite/c_runtime/iswdigit/test1/test1.c b/src/pal/tests/palsuite/c_runtime/iswdigit/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/iswdigit/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/iswdigit/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/iswprint/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/iswprint/test1/CMakeLists.txt index 5e436c3..d21c232 100644 --- a/src/pal/tests/palsuite/c_runtime/iswprint/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/iswprint/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_iswprint_test1 diff --git a/src/pal/tests/palsuite/c_runtime/iswprint/test1/test1.c b/src/pal/tests/palsuite/c_runtime/iswprint/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/iswprint/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/iswprint/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/iswspace/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/iswspace/test1/CMakeLists.txt index 1368e55..1f9a54f 100644 --- a/src/pal/tests/palsuite/c_runtime/iswspace/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/iswspace/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_iswspace_test1 diff --git a/src/pal/tests/palsuite/c_runtime/iswspace/test1/test1.c b/src/pal/tests/palsuite/c_runtime/iswspace/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/iswspace/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/iswspace/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/iswupper/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/iswupper/test1/CMakeLists.txt index 8b8fae6..1da5fba 100644 --- a/src/pal/tests/palsuite/c_runtime/iswupper/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/iswupper/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_iswupper_test1 diff --git a/src/pal/tests/palsuite/c_runtime/iswupper/test1/test1.c b/src/pal/tests/palsuite/c_runtime/iswupper/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/iswupper/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/iswupper/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/iswxdigit/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/iswxdigit/test1/CMakeLists.txt index 3a726ec..ae55976 100644 --- a/src/pal/tests/palsuite/c_runtime/iswxdigit/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/iswxdigit/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_iswxdigit_test1 diff --git a/src/pal/tests/palsuite/c_runtime/iswxdigit/test1/test1.c b/src/pal/tests/palsuite/c_runtime/iswxdigit/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/iswxdigit/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/iswxdigit/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/isxdigit/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/isxdigit/test1/CMakeLists.txt index 8919b36..4fd46c9 100644 --- a/src/pal/tests/palsuite/c_runtime/isxdigit/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/isxdigit/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_isxdigit_test1 diff --git a/src/pal/tests/palsuite/c_runtime/isxdigit/test1/test1.c b/src/pal/tests/palsuite/c_runtime/isxdigit/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/isxdigit/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/isxdigit/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/labs/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/labs/test1/CMakeLists.txt index cf0f099..2ffb3cd 100644 --- a/src/pal/tests/palsuite/c_runtime/labs/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/labs/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_labs_test1 diff --git a/src/pal/tests/palsuite/c_runtime/labs/test1/test1.c b/src/pal/tests/palsuite/c_runtime/labs/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/labs/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/labs/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/llabs/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/llabs/test1/CMakeLists.txt index 8f5bdbe..3adc3cc 100644 --- a/src/pal/tests/palsuite/c_runtime/llabs/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/llabs/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_llabs_test1 diff --git a/src/pal/tests/palsuite/c_runtime/llabs/test1/test1.c b/src/pal/tests/palsuite/c_runtime/llabs/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/llabs/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/llabs/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/localtime/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/localtime/test1/CMakeLists.txt index 25acf48..698699f 100644 --- a/src/pal/tests/palsuite/c_runtime/localtime/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/localtime/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_localtime_test1 diff --git a/src/pal/tests/palsuite/c_runtime/localtime/test1/test1.c b/src/pal/tests/palsuite/c_runtime/localtime/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/localtime/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/localtime/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/log/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/log/test1/CMakeLists.txt index dd19002..c8f991b 100644 --- a/src/pal/tests/palsuite/c_runtime/log/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/log/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_log_test1 diff --git a/src/pal/tests/palsuite/c_runtime/log/test1/test1.c b/src/pal/tests/palsuite/c_runtime/log/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/log/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/log/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/log10/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/log10/test1/CMakeLists.txt index 31e750d..31025fb 100644 --- a/src/pal/tests/palsuite/c_runtime/log10/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/log10/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_log10_test1 diff --git a/src/pal/tests/palsuite/c_runtime/log10/test1/test1.c b/src/pal/tests/palsuite/c_runtime/log10/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/log10/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/log10/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/log10f/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/log10f/CMakeLists.txt new file mode 100644 index 0000000..5e1ef7f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/log10f/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) diff --git a/src/pal/tests/palsuite/c_runtime/log10f/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/log10f/test1/CMakeLists.txt new file mode 100644 index 0000000..b2c0835 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/log10f/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_log10f_test1 + ${SOURCES} +) + +add_dependencies(paltest_log10f_test1 coreclrpal) + +target_link_libraries(paltest_log10f_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/log10f/test1/test1.c b/src/pal/tests/palsuite/c_runtime/log10f/test1/test1.c new file mode 100644 index 0000000..e7c8c2f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/log10f/test1/test1.c @@ -0,0 +1,144 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that log10f returns correct values. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** _isnanf +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = log10f(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("log10f(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = log10f(value); + + if (!_isnanf(result)) + { + Fail("log10f(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, PAL_NEGINF, 0 }, + { 0.000721784159f, -3.14159265f, PAL_EPSILON * 10 }, // expected: -(pi) + { 0.00191301410f, -2.71828183f, PAL_EPSILON * 10 }, // expected: -(e) + { 0.00498212830f, -2.30258509f, PAL_EPSILON * 10 }, // expected: -(ln(10)) + { 0.0268660410f, -1.57079633f, PAL_EPSILON * 10 }, // expected: -(pi / 2) + { 0.0360831928f, -1.44269504f, PAL_EPSILON * 10 }, // expected: -(logf2(e)) + { 0.0385288847f, -1.41421356f, PAL_EPSILON * 10 }, // expected: -(sqrtf(2)) + { 0.0744082059f, -1.12837917f, PAL_EPSILON * 10 }, // expected: -(2 / sqrtf(pi)) + { 0.1f, -1, PAL_EPSILON * 10 }, // expected: -(1) + { 0.163908636f, -0.785398163f, PAL_EPSILON }, // expected: -(pi / 4) + { 0.196287760f, -0.707106781f, PAL_EPSILON }, // expected: -(1 / sqrtf(2)) + { 0.202699566f, -0.693147181f, PAL_EPSILON }, // expected: -(ln(2)) + { 0.230876765f, -0.636619772f, PAL_EPSILON }, // expected: -(2 / pi) + { 0.367879441f, -0.434294482f, PAL_EPSILON }, // expected: -(log10f(e)) + { 0.480496373f, -0.318309886f, PAL_EPSILON }, // expected: -(1 / pi) + { 1, 0, PAL_EPSILON }, + { 2.08118116f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi + { 2.71828183f, 0.434294482f, PAL_EPSILON }, // expected: log10f(e) value: e + { 4.33131503f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi + { 4.93340967f, 0.693147181f, PAL_EPSILON }, // expected: ln(2) + { 5.09456117f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2) + { 6.10095980f, 0.785398163f, PAL_EPSILON }, // expected: pi / 4 + { 10, 1, PAL_EPSILON * 10 }, + { 13.4393779f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi) + { 25.9545535f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2) + { 27.7137338f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e) + { 37.2217105f, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + { 200.717432f, 2.30258509f, PAL_EPSILON * 10 }, // expected: ln(10) + { 522.735300f, 2.71828183f, PAL_EPSILON * 10 }, // expected: e + { 1385.45573f, 3.14159265f, PAL_EPSILON * 10 }, // expected: pi + { PAL_POSINF, PAL_POSINF, 0 }, + }; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/log10f/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/log10f/test1/testinfo.dat new file mode 100644 index 0000000..175ee3a --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/log10f/test1/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = log10f +Name = Positive Test for log10f +TYPE = DEFAULT +EXE1 = test1 +Description += Passes a series of values to the log10f() function, += checking each for the expected result. Also checks += for proper handling of out-of-range values. + + + diff --git a/src/pal/tests/palsuite/c_runtime/logf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/logf/CMakeLists.txt new file mode 100644 index 0000000..5e1ef7f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/logf/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) diff --git a/src/pal/tests/palsuite/c_runtime/logf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/logf/test1/CMakeLists.txt new file mode 100644 index 0000000..550f572 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/logf/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_logf_test1 + ${SOURCES} +) + +add_dependencies(paltest_logf_test1 coreclrpal) + +target_link_libraries(paltest_logf_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/logf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/logf/test1/test1.c new file mode 100644 index 0000000..499778e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/logf/test1/test1.c @@ -0,0 +1,139 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests logf with a normal set of values. +** +**===================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = logf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("logf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = logf(value); + + if (!_isnanf(result)) + { + Fail("logf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, PAL_NEGINF, 0 }, + { 0.0432139183f, -3.14159265f, PAL_EPSILON * 10 }, // expected: -(pi) + { 0.0659880358f, -2.71828183f, PAL_EPSILON * 10 }, // expected: -(e) + { 0.1f, -2.30258509f, PAL_EPSILON * 10 }, // expected: -(ln(10)) + { 0.207879576f, -1.57079633f, PAL_EPSILON * 10 }, // expected: -(pi / 2) + { 0.236290088f, -1.44269504f, PAL_EPSILON * 10 }, // expected: -(logf2(e)) + { 0.243116734f, -1.41421356f, PAL_EPSILON * 10 }, // expected: -(sqrtf(2)) + { 0.323557264f, -1.12837917f, PAL_EPSILON * 10 }, // expected: -(2 / sqrtf(pi)) + { 0.367879441f, -1, PAL_EPSILON * 10 }, // expected: -(1) + { 0.455938128f, -0.785398163f, PAL_EPSILON }, // expected: -(pi / 4) + { 0.493068691f, -0.707106781f, PAL_EPSILON }, // expected: -(1 / sqrtf(2)) + { 0.5f, -0.693147181f, PAL_EPSILON }, // expected: -(ln(2)) + { 0.529077808f, -0.636619772f, PAL_EPSILON }, // expected: -(2 / pi) + { 0.647721485f, -0.434294482f, PAL_EPSILON }, // expected: -(log10f(e)) + { 0.727377349f, -0.318309886f, PAL_EPSILON }, // expected: -(1 / pi) + { 1, 0, PAL_EPSILON }, + { 1.37480223f, 0.318309886f, PAL_EPSILON }, // expected: 1 / pi + { 1.54387344f, 0.434294482f, PAL_EPSILON }, // expected: log10f(e) + { 1.89008116f, 0.636619772f, PAL_EPSILON }, // expected: 2 / pi + { 2, 0.693147181f, PAL_EPSILON }, // expected: ln(2) + { 2.02811498f, 0.707106781f, PAL_EPSILON }, // expected: 1 / sqrtf(2) + { 2.19328005f, 0.785398163f, PAL_EPSILON }, // expected: pi / 4 + { 2.71828183f, 1, PAL_EPSILON * 10 }, // value: e + { 3.09064302f, 1.12837917f, PAL_EPSILON * 10 }, // expected: 2 / sqrtf(pi) + { 4.11325038f, 1.41421356f, PAL_EPSILON * 10 }, // expected: sqrtf(2) + { 4.23208611f, 1.44269504f, PAL_EPSILON * 10 }, // expected: logf2(e) + { 4.81047738f, 1.57079633f, PAL_EPSILON * 10 }, // expected: pi / 2 + { 10, 2.30258509f, PAL_EPSILON * 10 }, // expected: ln(10) + { 15.1542622f, 2.71828183f, PAL_EPSILON * 10 }, // expected: e + { 23.1406926f, 3.14159265f, PAL_EPSILON * 10 }, // expected: pi + { PAL_POSINF, PAL_POSINF, 0 }, + }; + + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/logf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/logf/test1/testinfo.dat new file mode 100644 index 0000000..aadfee6 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/logf/test1/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = logf +Name = Positive Test for logf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes a series of values to the logf() function, += checking each for the expected result. Also checks += for proper handling of out-of-range values. diff --git a/src/pal/tests/palsuite/c_runtime/malloc/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/malloc/test1/CMakeLists.txt index 4a388ad..f475730 100644 --- a/src/pal/tests/palsuite/c_runtime/malloc/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/malloc/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_malloc_test1 diff --git a/src/pal/tests/palsuite/c_runtime/malloc/test1/test1.c b/src/pal/tests/palsuite/c_runtime/malloc/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/malloc/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/malloc/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/malloc/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/malloc/test2/CMakeLists.txt index abbed2a..663e104 100644 --- a/src/pal/tests/palsuite/c_runtime/malloc/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/malloc/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_malloc_test2 diff --git a/src/pal/tests/palsuite/c_runtime/malloc/test2/test2.c b/src/pal/tests/palsuite/c_runtime/malloc/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/malloc/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/malloc/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/memchr/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/memchr/test1/CMakeLists.txt index 4e33a8f..959fd2a 100644 --- a/src/pal/tests/palsuite/c_runtime/memchr/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/memchr/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_memchr_test1 diff --git a/src/pal/tests/palsuite/c_runtime/memchr/test1/test1.c b/src/pal/tests/palsuite/c_runtime/memchr/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/memchr/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/memchr/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/memcmp/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/memcmp/test1/CMakeLists.txt index b61f208..43d8fdd 100644 --- a/src/pal/tests/palsuite/c_runtime/memcmp/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/memcmp/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_memcmp_test1 diff --git a/src/pal/tests/palsuite/c_runtime/memcmp/test1/test1.c b/src/pal/tests/palsuite/c_runtime/memcmp/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/memcmp/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/memcmp/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/memcpy/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/memcpy/test1/CMakeLists.txt index d846bfc..14db0df 100644 --- a/src/pal/tests/palsuite/c_runtime/memcpy/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/memcpy/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_memcpy_test1 diff --git a/src/pal/tests/palsuite/c_runtime/memcpy/test1/test1.c b/src/pal/tests/palsuite/c_runtime/memcpy/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/memcpy/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/memcpy/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/memmove/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/memmove/test1/CMakeLists.txt index cf50ec0..db6f65e 100644 --- a/src/pal/tests/palsuite/c_runtime/memmove/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/memmove/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_memmove_test1 diff --git a/src/pal/tests/palsuite/c_runtime/memmove/test1/test1.c b/src/pal/tests/palsuite/c_runtime/memmove/test1/test1.c deleted file mode 100644 index c1af871..0000000 --- a/src/pal/tests/palsuite/c_runtime/memmove/test1/test1.c +++ /dev/null @@ -1,116 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: Test that memmove correctly copies text from one buffer -** to another even when the buffers overlap. -** -** -**==========================================================================*/ - -#include - -int __cdecl main(int argc, char **argv) -{ - char testA[11] = "abcdefghij"; - char testB[15] = "aabbccddeeffgg"; - char testC[15] = "aabbccddeeffgg"; - char testD[15] = "aabbccddeeffgg"; - char insString[3] = "zzz"; - char *retVal; - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - /* move a string onto itself */ - retVal = (char *)memmove(testA + 2, testA, 8); - if (retVal != testA + 2) - { - Fail("The return value should have been the value of the destination" - "pointer, but wasn't\n"); - } - - /*Check the most likely error*/ - if (memcmp(testA, "ababababab", 11) == 0) - { - Fail("memmove should have saved the characters in the region of" - " overlap between source and destination, but didn't.\n"); - } - - if (memcmp(testA, "ababcdefgh", 11) != 0) - { - /* not sure what exactly went wrong. */ - Fail("memmove was called on a region containing the characters" - " \"abcdefghij\". It was to move the first 8 positions to" - " the last 8 positions, giving the result \"ababcdefgh\". " - " Instead, it gave the result \"%s\".\n", testA); - } - - /* move a string to the front of testB */ - retVal = (char *)memmove(testB, insString, 3); - if(retVal != testB) - { - Fail("memmove: The function did not return the correct " - "string.\n"); - } - - if(memcmp(testB, "zzzbccddeeffgg",15) != 0) - { - Fail("memmove: The function failed to move the string " - "correctly.\n"); - } - - - /* move a string to the middle of testC */ - retVal = memmove(testC+5, insString, 3); - if(retVal != testC+5) - { - Fail("memmove: The function did not return the correct " - "string.\n"); - } - - if(memcmp(testC, "aabbczzzeeffgg",15) != 0) - { - Fail("memmove: The function failed to move the string " - "correctly.\n"); - } - - - /* move a string to the end of testD */ - retVal = memmove(testD+11, insString, 3); - if(retVal != testD+11) - { - Fail("memmove: The function did not return the correct " - "string.\n"); - } - - if(memcmp(testD, "aabbccddeefzzz",15) != 0) - { - Fail("memmove: The function failed to move the string " - "correctly.\n"); - } - - PAL_Terminate(); - return PASS; - -} - - - - - - - - - - - - - - diff --git a/src/pal/tests/palsuite/c_runtime/memmove/test1/test1.cpp b/src/pal/tests/palsuite/c_runtime/memmove/test1/test1.cpp new file mode 100644 index 0000000..8279d67 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/memmove/test1/test1.cpp @@ -0,0 +1,116 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Test that memmove correctly copies text from one buffer +** to another even when the buffers overlap. +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + char testA[11] = "abcdefghij"; + char testB[15] = "aabbccddeeffgg"; + char testC[15] = "aabbccddeeffgg"; + char testD[15] = "aabbccddeeffgg"; + char insString[4] = "zzz"; + char *retVal; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* move a string onto itself */ + retVal = (char *)memmove(testA + 2, testA, 8); + if (retVal != testA + 2) + { + Fail("The return value should have been the value of the destination" + "pointer, but wasn't\n"); + } + + /*Check the most likely error*/ + if (memcmp(testA, "ababababab", 11) == 0) + { + Fail("memmove should have saved the characters in the region of" + " overlap between source and destination, but didn't.\n"); + } + + if (memcmp(testA, "ababcdefgh", 11) != 0) + { + /* not sure what exactly went wrong. */ + Fail("memmove was called on a region containing the characters" + " \"abcdefghij\". It was to move the first 8 positions to" + " the last 8 positions, giving the result \"ababcdefgh\". " + " Instead, it gave the result \"%s\".\n", testA); + } + + /* move a string to the front of testB */ + retVal = (char *)memmove(testB, insString, 3); + if(retVal != testB) + { + Fail("memmove: The function did not return the correct " + "string.\n"); + } + + if(memcmp(testB, "zzzbccddeeffgg",15) != 0) + { + Fail("memmove: The function failed to move the string " + "correctly.\n"); + } + + + /* move a string to the middle of testC */ + retVal = (char*)memmove(testC+5, insString, 3); + if(retVal != testC+5) + { + Fail("memmove: The function did not return the correct " + "string.\n"); + } + + if(memcmp(testC, "aabbczzzeeffgg",15) != 0) + { + Fail("memmove: The function failed to move the string " + "correctly.\n"); + } + + + /* move a string to the end of testD */ + retVal = (char*)memmove(testD+11, insString, 3); + if(retVal != testD+11) + { + Fail("memmove: The function did not return the correct " + "string.\n"); + } + + if(memcmp(testD, "aabbccddeefzzz",15) != 0) + { + Fail("memmove: The function failed to move the string " + "correctly.\n"); + } + + PAL_Terminate(); + return PASS; + +} + + + + + + + + + + + + + + diff --git a/src/pal/tests/palsuite/c_runtime/memset/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/memset/test1/CMakeLists.txt index 78b5a6b..bc3d625 100644 --- a/src/pal/tests/palsuite/c_runtime/memset/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/memset/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_memset_test1 diff --git a/src/pal/tests/palsuite/c_runtime/memset/test1/test1.c b/src/pal/tests/palsuite/c_runtime/memset/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/memset/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/memset/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/modf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/modf/test1/CMakeLists.txt index 4b65ba7..3fe7bc7 100644 --- a/src/pal/tests/palsuite/c_runtime/modf/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/modf/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_modf_test1 diff --git a/src/pal/tests/palsuite/c_runtime/modf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/modf/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/modf/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/modf/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/modff/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/modff/test1/CMakeLists.txt index 812cd1c..10e5e99 100644 --- a/src/pal/tests/palsuite/c_runtime/modff/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/modff/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_modff_test1 diff --git a/src/pal/tests/palsuite/c_runtime/modff/test1/test1.c b/src/pal/tests/palsuite/c_runtime/modff/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/modff/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/modff/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/pow/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/pow/test1/CMakeLists.txt index 69ba02a..f94210d 100644 --- a/src/pal/tests/palsuite/c_runtime/pow/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/pow/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_pow_test1 diff --git a/src/pal/tests/palsuite/c_runtime/pow/test1/test1.c b/src/pal/tests/palsuite/c_runtime/pow/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/pow/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/pow/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/powf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/powf/CMakeLists.txt new file mode 100644 index 0000000..5e1ef7f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/powf/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) diff --git a/src/pal/tests/palsuite/c_runtime/powf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/powf/test1/CMakeLists.txt new file mode 100644 index 0000000..8ea040f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/powf/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_powf_test1 + ${SOURCES} +) + +add_dependencies(paltest_powf_test1 coreclrpal) + +target_link_libraries(paltest_powf_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/powf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/powf/test1/test1.c new file mode 100644 index 0000000..ca738e8 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/powf/test1/test1.c @@ -0,0 +1,229 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Tests that atan2f returns correct values for a subset of values. +** Tests with positive and negative values of x and y to ensure +** atan2f is returning results from the correct quadrant. +** +**===================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float x; /* first component of the value to test the function with */ + float y; /* second component of the value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float x, float y, float expected, float variance) +{ + float result = powf(x, y); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("powf(%g, %g) returned %10.9g when it should have returned %10.9g", + x, y, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float x, float y) +{ + float result = powf(x, y); + + if (!_isnanf(result)) + { + Fail("powf(%g, %g) returned %10.9g when it should have returned %10.9g", + x, y, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* x y expected variance */ + { PAL_NEGINF, PAL_NEGINF, 0, PAL_EPSILON }, + { PAL_NEGINF, PAL_POSINF, PAL_POSINF, 0 }, + + { -10, PAL_NEGINF, 0, PAL_EPSILON }, + { -10, -1, -0.1f, PAL_EPSILON }, + { -10, 0, 1, PAL_EPSILON * 10 }, + { -10, 1, -10, PAL_EPSILON * 100 }, + { -10, PAL_POSINF, PAL_POSINF, 0 }, + + { -2.71828183f, PAL_NEGINF, 0, PAL_EPSILON }, // x: -(e) + { -2.71828183f, -1, -0.367879441f, PAL_EPSILON }, // x: -(e) + { -2.71828183f, 0, 1, PAL_EPSILON * 10 }, // x: -(e) + { -2.71828183f, 1, -2.71828183f, PAL_EPSILON * 10 }, // x: -(e) expected: e + { -2.71828183f, PAL_POSINF, PAL_POSINF, 0 }, // x: -(e) + + { -0.0, PAL_NEGINF, PAL_POSINF, 0 }, + { -0.0, -1, PAL_NEGINF, 0 }, + { -0.0f, -0.0f, 1, PAL_EPSILON * 10 }, + { -0.0f, 0, 1, PAL_EPSILON * 10 }, + { -0.0, 1, -0.0, PAL_EPSILON }, + { -0.0, PAL_POSINF, 0, PAL_EPSILON }, + + { 0.0, PAL_NEGINF, PAL_POSINF, 0 }, + { 0.0, -1, PAL_POSINF, 0 }, + { 0, -0.0f, 1, PAL_EPSILON * 10 }, + { 0, 0, 1, PAL_EPSILON * 10 }, + { 0.0, 1, 0, PAL_EPSILON }, + { 0.0, PAL_POSINF, 0, PAL_EPSILON }, + + { 1, PAL_NEGINF, 1, PAL_EPSILON * 10 }, + { 1, PAL_POSINF, 1, PAL_EPSILON * 10 }, + + { 2.71828183f, PAL_NEGINF, 0, PAL_EPSILON }, + { 2.71828183f, -3.14159265f, 0.0432139183f, PAL_EPSILON / 10 }, // x: e y: -(pi) + { 2.71828183f, -2.71828183f, 0.0659880358f, PAL_EPSILON / 10 }, // x: e y: -(e) + { 2.71828183f, -2.30258509f, 0.1f, PAL_EPSILON }, // x: e y: -(ln(10)) + { 2.71828183f, -1.57079633f, 0.207879576f, PAL_EPSILON }, // x: e y: -(pi / 2) + { 2.71828183f, -1.44269504f, 0.236290088f, PAL_EPSILON }, // x: e y: -(logf2(e)) + { 2.71828183f, -1.41421356f, 0.243116734f, PAL_EPSILON }, // x: e y: -(sqrtf(2)) + { 2.71828183f, -1.12837917f, 0.323557264f, PAL_EPSILON }, // x: e y: -(2 / sqrtf(pi)) + { 2.71828183f, -1, 0.367879441f, PAL_EPSILON }, // x: e y: -(1) + { 2.71828183f, -0.785398163f, 0.455938128f, PAL_EPSILON }, // x: e y: -(pi / 4) + { 2.71828183f, -0.707106781f, 0.493068691f, PAL_EPSILON }, // x: e y: -(1 / sqrtf(2)) + { 2.71828183f, -0.693147181f, 0.5f, PAL_EPSILON }, // x: e y: -(ln(2)) + { 2.71828183f, -0.636619772f, 0.529077808f, PAL_EPSILON }, // x: e y: -(2 / pi) + { 2.71828183f, -0.434294482f, 0.647721485f, PAL_EPSILON }, // x: e y: -(log10f(e)) + { 2.71828183f, -0.318309886f, 0.727377349f, PAL_EPSILON }, // x: e y: -(1 / pi) + { 2.71828183f, 0, 1, PAL_EPSILON * 10 }, // x: e + { 2.71828183f, 0.318309886f, 1.37480223f, PAL_EPSILON * 10 }, // x: e y: 1 / pi + { 2.71828183f, 0.434294482f, 1.54387344f, PAL_EPSILON * 10 }, // x: e y: log10f(e) + { 2.71828183f, 0.636619772f, 1.89008116f, PAL_EPSILON * 10 }, // x: e y: 2 / pi + { 2.71828183f, 0.693147181f, 2, PAL_EPSILON * 10 }, // x: e y: ln(2) + { 2.71828183f, 0.707106781f, 2.02811498f, PAL_EPSILON * 10 }, // x: e y: 1 / sqrtf(2) + { 2.71828183f, 0.785398163f, 2.19328005f, PAL_EPSILON * 10 }, // x: e y: pi / 4 + { 2.71828183f, 1, 2.71828183f, PAL_EPSILON * 10 }, // x: e expected: e + { 2.71828183f, 1.12837917f, 3.09064302f, PAL_EPSILON * 10 }, // x: e y: 2 / sqrtf(pi) + { 2.71828183f, 1.41421356f, 4.11325038f, PAL_EPSILON * 10 }, // x: e y: sqrtf(2) + { 2.71828183f, 1.44269504f, 4.23208611f, PAL_EPSILON * 10 }, // x: e y: logf2(e) + { 2.71828183f, 1.57079633f, 4.81047738f, PAL_EPSILON * 10 }, // x: e y: pi / 2 + { 2.71828183f, 2.30258509f, 10, PAL_EPSILON * 100 }, // x: e y: ln(10) + { 2.71828183f, 2.71828183f, 15.1542622f, PAL_EPSILON * 100 }, // x: e y: e + { 2.71828183f, 3.14159265f, 23.1406926f, PAL_EPSILON * 100 }, // x: e y: pi + { 2.71828183f, PAL_POSINF, PAL_POSINF, 0 }, // x: e + + { 10, PAL_NEGINF, 0, 0 }, + { 10, -3.14159265f, 0.000721784159f, PAL_EPSILON / 1000 }, // y: -(pi) + { 10, -2.71828183f, 0.00191301410f, PAL_EPSILON / 100 }, // y: -(e) + { 10, -2.30258509f, 0.00498212830f, PAL_EPSILON / 100 }, // y: -(ln(10)) + { 10, -1.57079633f, 0.0268660410f, PAL_EPSILON / 10 }, // y: -(pi / 2) + { 10, -1.44269504f, 0.0360831928f, PAL_EPSILON / 10 }, // y: -(logf2(e)) + { 10, -1.41421356f, 0.0385288847f, PAL_EPSILON / 10 }, // y: -(sqrtf(2)) + { 10, -1.12837917f, 0.0744082059f, PAL_EPSILON / 10 }, // y: -(2 / sqrtf(pi)) + { 10, -1, 0.1f, PAL_EPSILON }, // y: -(1) + { 10, -0.785398163f, 0.163908636f, PAL_EPSILON }, // y: -(pi / 4) + { 10, -0.707106781f, 0.196287760f, PAL_EPSILON }, // y: -(1 / sqrtf(2)) + { 10, -0.693147181f, 0.202699566f, PAL_EPSILON }, // y: -(ln(2)) + { 10, -0.636619772f, 0.230876765f, PAL_EPSILON }, // y: -(2 / pi) + { 10, -0.434294482f, 0.367879441f, PAL_EPSILON }, // y: -(log10f(e)) + { 10, -0.318309886f, 0.480496373f, PAL_EPSILON }, // y: -(1 / pi) + { 10, 0, 1, PAL_EPSILON * 10 }, + { 10, 0.318309886f, 2.08118116f, PAL_EPSILON * 10 }, // y: 1 / pi + { 10, 0.434294482f, 2.71828183f, PAL_EPSILON * 10 }, // y: log10f(e) expected: e + { 10, 0.636619772f, 4.33131503f, PAL_EPSILON * 10 }, // y: 2 / pi + { 10, 0.693147181f, 4.93340967f, PAL_EPSILON * 10 }, // y: ln(2) + { 10, 0.707106781f, 5.09456117f, PAL_EPSILON * 10 }, // y: 1 / sqrtf(2) + { 10, 0.785398163f, 6.10095980f, PAL_EPSILON * 10 }, // y: pi / 4 + { 10, 1, 10, PAL_EPSILON * 100 }, + { 10, 1.12837917f, 13.4393779f, PAL_EPSILON * 100 }, // y: 2 / sqrtf(pi) + { 10, 1.41421356f, 25.9545535f, PAL_EPSILON * 100 }, // y: sqrtf(2) + { 10, 1.44269504f, 27.7137338f, PAL_EPSILON * 100 }, // y: logf2(e) + { 10, 1.57079633f, 37.2217105f, PAL_EPSILON * 100 }, // y: pi / 2 + { 10, 2.30258509f, 200.717432f, PAL_EPSILON * 1000 }, // y: ln(10) + { 10, 2.71828183f, 522.735300f, PAL_EPSILON * 1000 }, // y: e + { 10, 3.14159265f, 1385.45573f, PAL_EPSILON * 10000 }, // y: pi + { 10, PAL_POSINF, PAL_POSINF, 0 }, + + { PAL_POSINF, PAL_NEGINF, 0, PAL_EPSILON }, + { PAL_POSINF, PAL_POSINF, PAL_POSINF, 0 }, + }; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].x, tests[i].y, tests[i].expected, tests[i].variance); + } + + validate_isnan(-10, -1.57079633f); // y: -(pi / 2) + validate_isnan(-10, -0.785398163f); // y: -(pi / 4) + validate_isnan(-10, 0.785398163f); // y: pi / 4 + validate_isnan(-10, 1.57079633f); // y: pi / 2 + + validate_isnan(-2.71828183f, -1.57079633f); // x: -(e) y: -(pi / 2) + validate_isnan(-2.71828183f, -0.785398163f); // x: -(e) y: -(pi / 4) + validate_isnan(-2.71828183f, 0.785398163f); // x: -(e) y: pi / 4 + validate_isnan(-2.71828183f, 1.57079633f); // x: -(e) y: pi / 2 + + validate_isnan(-1, PAL_NEGINF); + validate_isnan(-1, PAL_POSINF); + + validate_isnan(PAL_NAN, -0.0); + validate_isnan(PAL_NAN, 0); + + validate_isnan(PAL_NEGINF, PAL_NAN); + validate_isnan(PAL_NAN, PAL_NEGINF); + + validate_isnan(PAL_POSINF, PAL_NAN); + validate_isnan(PAL_NAN, PAL_POSINF); + + validate_isnan(PAL_NAN, PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/powf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/powf/test1/testinfo.dat new file mode 100644 index 0000000..778c042 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/powf/test1/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = powf +Name = Call powf with some std input/output. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the powf function with various num/expfonent pairs += that should produce std answers. + + + + diff --git a/src/pal/tests/palsuite/c_runtime/printf/printf.h b/src/pal/tests/palsuite/c_runtime/printf/printf.h index 2eaa984..8ef725f 100644 --- a/src/pal/tests/palsuite/c_runtime/printf/printf.h +++ b/src/pal/tests/palsuite/c_runtime/printf/printf.h @@ -14,7 +14,7 @@ #ifndef __printf_H__ #define __printf_H__ -void DoStrTest(char *formatstr, char* param, char *checkstr) +void DoStrTest(const char *formatstr, char* param, const char *checkstr) { int ret; @@ -26,7 +26,7 @@ void DoStrTest(char *formatstr, char* param, char *checkstr) } } -void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr) +void DoWStrTest(const char *formatstr, WCHAR* param, const char *checkstr) { int ret; @@ -38,8 +38,8 @@ void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr) } } -void DoPointerTest(char *formatstr, void* param, char* paramstr, - char *checkstr1) +void DoPointerTest(const char *formatstr, void* param, char* paramstr, + const char *checkstr1) { int ret; @@ -51,7 +51,7 @@ void DoPointerTest(char *formatstr, void* param, char* paramstr, } } -void DoCountTest(char *formatstr, int param, char *checkstr) +void DoCountTest(const char *formatstr, int param, const char *checkstr) { int ret; int n = -1; @@ -70,7 +70,7 @@ void DoCountTest(char *formatstr, int param, char *checkstr) } } -void DoShortCountTest(char *formatstr, int param, char *checkstr) +void DoShortCountTest(const char *formatstr, int param, const char *checkstr) { int ret; short int n = -1; @@ -90,7 +90,7 @@ void DoShortCountTest(char *formatstr, int param, char *checkstr) } -void DoCharTest(char *formatstr, char param, char *checkstr) +void DoCharTest(const char *formatstr, char param, const char *checkstr) { int ret; @@ -102,7 +102,7 @@ void DoCharTest(char *formatstr, char param, char *checkstr) } } -void DoWCharTest(char *formatstr, WCHAR param, char *checkstr) +void DoWCharTest(const char *formatstr, WCHAR param, const char *checkstr) { int ret; @@ -114,7 +114,7 @@ void DoWCharTest(char *formatstr, WCHAR param, char *checkstr) } } -void DoNumTest(char *formatstr, int param, char *checkstr) +void DoNumTest(const char *formatstr, int param, const char *checkstr) { int ret; @@ -126,8 +126,8 @@ void DoNumTest(char *formatstr, int param, char *checkstr) } } -void DoI64Test(char *formatstr, INT64 param, char *valuestr, - char *checkstr1) +void DoI64Test(const char *formatstr, INT64 param, char *valuestr, + const char *checkstr1) { int ret; @@ -139,8 +139,8 @@ void DoI64Test(char *formatstr, INT64 param, char *valuestr, } } -void DoDoubleTest(char *formatstr, double param, - char *checkstr1, char *checkstr2) +void DoDoubleTest(const char *formatstr, double param, + const char *checkstr1, const char *checkstr2) { int ret; @@ -152,8 +152,8 @@ void DoDoubleTest(char *formatstr, double param, } } -void DoArgumentPrecTest(char *formatstr, int precision, void *param, - char *paramstr, char *checkstr1, char *checkstr2) +void DoArgumentPrecTest(const char *formatstr, int precision, void *param, + char *paramstr, const char *checkstr1, const char *checkstr2) { int ret; @@ -165,8 +165,8 @@ void DoArgumentPrecTest(char *formatstr, int precision, void *param, } } -void DoArgumentPrecDoubleTest(char *formatstr, int precision, double param, - char *checkstr1, char *checkstr2) +void DoArgumentPrecDoubleTest(const char *formatstr, int precision, double param, + const char *checkstr1, const char *checkstr2) { int ret; diff --git a/src/pal/tests/palsuite/c_runtime/printf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test1/CMakeLists.txt index bea9151..2dace14 100644 --- a/src/pal/tests/palsuite/c_runtime/printf/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/printf/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_printf_test1 diff --git a/src/pal/tests/palsuite/c_runtime/printf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/printf/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/printf/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/printf/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/printf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test10/CMakeLists.txt index 89ff2e0..75e30c8 100644 --- a/src/pal/tests/palsuite/c_runtime/printf/test10/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/printf/test10/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test10.c + test10.cpp ) add_executable(paltest_printf_test10 diff --git a/src/pal/tests/palsuite/c_runtime/printf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/printf/test10/test10.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/printf/test10/test10.c rename to src/pal/tests/palsuite/c_runtime/printf/test10/test10.cpp diff --git a/src/pal/tests/palsuite/c_runtime/printf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test11/CMakeLists.txt index 349f154..4ee12dc 100644 --- a/src/pal/tests/palsuite/c_runtime/printf/test11/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/printf/test11/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test11.c + test11.cpp ) add_executable(paltest_printf_test11 diff --git a/src/pal/tests/palsuite/c_runtime/printf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/printf/test11/test11.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/printf/test11/test11.c rename to src/pal/tests/palsuite/c_runtime/printf/test11/test11.cpp diff --git a/src/pal/tests/palsuite/c_runtime/printf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test12/CMakeLists.txt index 0d32ee1..3b2e39d 100644 --- a/src/pal/tests/palsuite/c_runtime/printf/test12/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/printf/test12/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test12.c + test12.cpp ) add_executable(paltest_printf_test12 diff --git a/src/pal/tests/palsuite/c_runtime/printf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/printf/test12/test12.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/printf/test12/test12.c rename to src/pal/tests/palsuite/c_runtime/printf/test12/test12.cpp diff --git a/src/pal/tests/palsuite/c_runtime/printf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test13/CMakeLists.txt index 348d25b..b6af021 100644 --- a/src/pal/tests/palsuite/c_runtime/printf/test13/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/printf/test13/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test13.c + test13.cpp ) add_executable(paltest_printf_test13 diff --git a/src/pal/tests/palsuite/c_runtime/printf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/printf/test13/test13.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/printf/test13/test13.c rename to src/pal/tests/palsuite/c_runtime/printf/test13/test13.cpp diff --git a/src/pal/tests/palsuite/c_runtime/printf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test14/CMakeLists.txt index 659ea78..5a6cf8a 100644 --- a/src/pal/tests/palsuite/c_runtime/printf/test14/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/printf/test14/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test14.c + test14.cpp ) add_executable(paltest_printf_test14 diff --git a/src/pal/tests/palsuite/c_runtime/printf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/printf/test14/test14.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/printf/test14/test14.c rename to src/pal/tests/palsuite/c_runtime/printf/test14/test14.cpp diff --git a/src/pal/tests/palsuite/c_runtime/printf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test15/CMakeLists.txt index 9e4e310..b1466a3 100644 --- a/src/pal/tests/palsuite/c_runtime/printf/test15/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/printf/test15/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test15.c + test15.cpp ) add_executable(paltest_printf_test15 diff --git a/src/pal/tests/palsuite/c_runtime/printf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/printf/test15/test15.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/printf/test15/test15.c rename to src/pal/tests/palsuite/c_runtime/printf/test15/test15.cpp diff --git a/src/pal/tests/palsuite/c_runtime/printf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test16/CMakeLists.txt index 7e477a3..c81da10 100644 --- a/src/pal/tests/palsuite/c_runtime/printf/test16/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/printf/test16/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test16.c + test16.cpp ) add_executable(paltest_printf_test16 diff --git a/src/pal/tests/palsuite/c_runtime/printf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/printf/test16/test16.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/printf/test16/test16.c rename to src/pal/tests/palsuite/c_runtime/printf/test16/test16.cpp diff --git a/src/pal/tests/palsuite/c_runtime/printf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test17/CMakeLists.txt index c18450c..9d40e54 100644 --- a/src/pal/tests/palsuite/c_runtime/printf/test17/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/printf/test17/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test17.c + test17.cpp ) add_executable(paltest_printf_test17 diff --git a/src/pal/tests/palsuite/c_runtime/printf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/printf/test17/test17.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/printf/test17/test17.c rename to src/pal/tests/palsuite/c_runtime/printf/test17/test17.cpp diff --git a/src/pal/tests/palsuite/c_runtime/printf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test18/CMakeLists.txt index b046831..6ab11f4 100644 --- a/src/pal/tests/palsuite/c_runtime/printf/test18/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/printf/test18/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test18.c + test18.cpp ) add_executable(paltest_printf_test18 diff --git a/src/pal/tests/palsuite/c_runtime/printf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/printf/test18/test18.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/printf/test18/test18.c rename to src/pal/tests/palsuite/c_runtime/printf/test18/test18.cpp diff --git a/src/pal/tests/palsuite/c_runtime/printf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test19/CMakeLists.txt index efd4756..f022938 100644 --- a/src/pal/tests/palsuite/c_runtime/printf/test19/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/printf/test19/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test19.c + test19.cpp ) add_executable(paltest_printf_test19 diff --git a/src/pal/tests/palsuite/c_runtime/printf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/printf/test19/test19.c deleted file mode 100644 index 1e09398..0000000 --- a/src/pal/tests/palsuite/c_runtime/printf/test19/test19.c +++ /dev/null @@ -1,76 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test19.c -** -** Purpose: Test #19 for the printf function. Tests the variable length -** precision argument. -** -** -**==========================================================================*/ - - -#include -#include "../printf.h" - - - - -int __cdecl main(int argc, char *argv[]) -{ - int n = -1; - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - DoArgumentPrecTest("%.*s", 2, "bar", "bar", "ba", "ba"); - DoArgumentPrecTest("%.*S", 2, convert("bar"), "bar", "ba", "ba"); - - DoArgumentPrecTest("%.*n", 3, &n, "pointer to int", "", ""); - if (n != 0) - { - Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", - 0, n); - } - - DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); - DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); - DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); - DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); - DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42"); - DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); - - - DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); - DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); - DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); - DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); - DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); - DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); - DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); - DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); - DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); - DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/printf/test19/test19.cpp b/src/pal/tests/palsuite/c_runtime/printf/test19/test19.cpp new file mode 100644 index 0000000..a3ce0e7 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/printf/test19/test19.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test19.c +** +** Purpose: Test #19 for the printf function. Tests the variable length +** precision argument. +** +** +**==========================================================================*/ + + +#include +#include "../printf.h" + + + + +int __cdecl main(int argc, char *argv[]) +{ + int n = -1; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoArgumentPrecTest("%.*s", 2, (void*)"bar", "bar", "ba", "ba"); + DoArgumentPrecTest("%.*S", 2, (void*)convert("bar"), "bar", "ba", "ba"); + + DoArgumentPrecTest("%.*n", 3, (void*)&n, "pointer to int", "", ""); + if (n != 0) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + 0, n); + } + + DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); + DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); + DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); + DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); + + + DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); + DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); + DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); + DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); + DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); + DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); + DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); + DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); + DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); + DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/printf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test2/CMakeLists.txt index c303a69..e92b6b0 100644 --- a/src/pal/tests/palsuite/c_runtime/printf/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/printf/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_printf_test2 diff --git a/src/pal/tests/palsuite/c_runtime/printf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/printf/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/printf/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/printf/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/printf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test3/CMakeLists.txt index 8bc7479..fcfd779 100644 --- a/src/pal/tests/palsuite/c_runtime/printf/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/printf/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_printf_test3 diff --git a/src/pal/tests/palsuite/c_runtime/printf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/printf/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/printf/test3/test3.c rename to src/pal/tests/palsuite/c_runtime/printf/test3/test3.cpp diff --git a/src/pal/tests/palsuite/c_runtime/printf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test4/CMakeLists.txt index 55e5700..7311bbe 100644 --- a/src/pal/tests/palsuite/c_runtime/printf/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/printf/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_printf_test4 diff --git a/src/pal/tests/palsuite/c_runtime/printf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/printf/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/printf/test4/test4.c rename to src/pal/tests/palsuite/c_runtime/printf/test4/test4.cpp diff --git a/src/pal/tests/palsuite/c_runtime/printf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test5/CMakeLists.txt index d091bca..bfe185c 100644 --- a/src/pal/tests/palsuite/c_runtime/printf/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/printf/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_printf_test5 diff --git a/src/pal/tests/palsuite/c_runtime/printf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/printf/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/printf/test5/test5.c rename to src/pal/tests/palsuite/c_runtime/printf/test5/test5.cpp diff --git a/src/pal/tests/palsuite/c_runtime/printf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test6/CMakeLists.txt index c004e35..842ebfe 100644 --- a/src/pal/tests/palsuite/c_runtime/printf/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/printf/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test6.c + test6.cpp ) add_executable(paltest_printf_test6 diff --git a/src/pal/tests/palsuite/c_runtime/printf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/printf/test6/test6.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/printf/test6/test6.c rename to src/pal/tests/palsuite/c_runtime/printf/test6/test6.cpp diff --git a/src/pal/tests/palsuite/c_runtime/printf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test7/CMakeLists.txt index ff6b647..16e3919 100644 --- a/src/pal/tests/palsuite/c_runtime/printf/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/printf/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test7.c + test7.cpp ) add_executable(paltest_printf_test7 diff --git a/src/pal/tests/palsuite/c_runtime/printf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/printf/test7/test7.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/printf/test7/test7.c rename to src/pal/tests/palsuite/c_runtime/printf/test7/test7.cpp diff --git a/src/pal/tests/palsuite/c_runtime/printf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test8/CMakeLists.txt index 5ee387f..4a40fee 100644 --- a/src/pal/tests/palsuite/c_runtime/printf/test8/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/printf/test8/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test8.c + test8.cpp ) add_executable(paltest_printf_test8 diff --git a/src/pal/tests/palsuite/c_runtime/printf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/printf/test8/test8.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/printf/test8/test8.c rename to src/pal/tests/palsuite/c_runtime/printf/test8/test8.cpp diff --git a/src/pal/tests/palsuite/c_runtime/printf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/printf/test9/CMakeLists.txt index baf46c1..df8f75d 100644 --- a/src/pal/tests/palsuite/c_runtime/printf/test9/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/printf/test9/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test9.c + test9.cpp ) add_executable(paltest_printf_test9 diff --git a/src/pal/tests/palsuite/c_runtime/printf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/printf/test9/test9.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/printf/test9/test9.c rename to src/pal/tests/palsuite/c_runtime/printf/test9/test9.cpp diff --git a/src/pal/tests/palsuite/c_runtime/qsort/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/qsort/test1/CMakeLists.txt index 105a727..ff215b8 100644 --- a/src/pal/tests/palsuite/c_runtime/qsort/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/qsort/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_qsort_test1 diff --git a/src/pal/tests/palsuite/c_runtime/qsort/test1/test1.c b/src/pal/tests/palsuite/c_runtime/qsort/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/qsort/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/qsort/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/qsort/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/qsort/test2/CMakeLists.txt index 09e3f6d..cdd9642 100644 --- a/src/pal/tests/palsuite/c_runtime/qsort/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/qsort/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_qsort_test2 diff --git a/src/pal/tests/palsuite/c_runtime/qsort/test2/test2.c b/src/pal/tests/palsuite/c_runtime/qsort/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/qsort/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/qsort/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/rand_srand/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/rand_srand/test1/CMakeLists.txt index 9399146..6728f40 100644 --- a/src/pal/tests/palsuite/c_runtime/rand_srand/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/rand_srand/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_rand_srand_test1 diff --git a/src/pal/tests/palsuite/c_runtime/rand_srand/test1/test1.c b/src/pal/tests/palsuite/c_runtime/rand_srand/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/rand_srand/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/rand_srand/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/realloc/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/realloc/test1/CMakeLists.txt index 0a9f34f..62830a0 100644 --- a/src/pal/tests/palsuite/c_runtime/realloc/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/realloc/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_realloc_test1 diff --git a/src/pal/tests/palsuite/c_runtime/realloc/test1/test1.c b/src/pal/tests/palsuite/c_runtime/realloc/test1/test1.c deleted file mode 100644 index d0dd128..0000000 --- a/src/pal/tests/palsuite/c_runtime/realloc/test1/test1.c +++ /dev/null @@ -1,66 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: Uses realloc to allocate and realloate memory, checking -** that memory contents are copied when the memory is reallocated. -** -** -**==========================================================================*/ - -#include - -int __cdecl main(int argc, char **argv) -{ - char *testA; - const int len1 = 10; - const char str1[] = "aaaaaaaaaa"; - - const int len2 = 20; - const char str2[] = "bbbbbbbbbbbbbbbbbbbb"; - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - /* this should work like malloc */ - testA = (char *)realloc(NULL, len1*sizeof(char)); - memcpy(testA, str1, len1); - if (testA == NULL) - { - Fail("We ran out of memory (unlikely), or realloc is broken.\n"); - } - - if (memcmp(testA, str1, len1) != 0) - { - Fail("realloc doesn't properly allocate new memory.\n"); - } - - testA = (char *)realloc(testA, len2*sizeof(char)); - if (memcmp(testA, str1, len1) != 0) - { - Fail("realloc doesn't move the contents of the original memory " - "block to the newly allocated block.\n"); - } - - memcpy(testA, str2, len2); - if (memcmp(testA, str2, len2) != 0) - { - Fail("Couldn't write to memory allocated by realloc.\n"); - } - - /* free the buffer */ - testA = realloc(testA, 0); - if (testA != NULL) - { - Fail("Realloc didn't return NULL when called with a length " - "of zero.\n"); - } - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/realloc/test1/test1.cpp b/src/pal/tests/palsuite/c_runtime/realloc/test1/test1.cpp new file mode 100644 index 0000000..64a9270 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/realloc/test1/test1.cpp @@ -0,0 +1,66 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Uses realloc to allocate and realloate memory, checking +** that memory contents are copied when the memory is reallocated. +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char **argv) +{ + char *testA; + const int len1 = 10; + const char str1[] = "aaaaaaaaaa"; + + const int len2 = 20; + const char str2[] = "bbbbbbbbbbbbbbbbbbbb"; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* this should work like malloc */ + testA = (char *)realloc(NULL, len1*sizeof(char)); + memcpy(testA, str1, len1); + if (testA == NULL) + { + Fail("We ran out of memory (unlikely), or realloc is broken.\n"); + } + + if (memcmp(testA, str1, len1) != 0) + { + Fail("realloc doesn't properly allocate new memory.\n"); + } + + testA = (char *)realloc(testA, len2*sizeof(char)); + if (memcmp(testA, str1, len1) != 0) + { + Fail("realloc doesn't move the contents of the original memory " + "block to the newly allocated block.\n"); + } + + memcpy(testA, str2, len2); + if (memcmp(testA, str2, len2) != 0) + { + Fail("Couldn't write to memory allocated by realloc.\n"); + } + + /* free the buffer */ + testA = (char*)realloc(testA, 0); + if (testA != NULL) + { + Fail("Realloc didn't return NULL when called with a length " + "of zero.\n"); + } + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sin/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sin/test1/CMakeLists.txt index e074337..74a0e78 100644 --- a/src/pal/tests/palsuite/c_runtime/sin/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/sin/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_sin_test1 diff --git a/src/pal/tests/palsuite/c_runtime/sin/test1/test1.c b/src/pal/tests/palsuite/c_runtime/sin/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/sin/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/sin/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/sinf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sinf/CMakeLists.txt new file mode 100644 index 0000000..5e1ef7f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sinf/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) diff --git a/src/pal/tests/palsuite/c_runtime/sinf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sinf/test1/CMakeLists.txt new file mode 100644 index 0000000..0651b43 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sinf/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_sinf_test1 + ${SOURCES} +) + +add_dependencies(paltest_sinf_test1 coreclrpal) + +target_link_libraries(paltest_sinf_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sinf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/sinf/test1/test1.c new file mode 100644 index 0000000..d5bd248 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sinf/test1/test1.c @@ -0,0 +1,130 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that sinf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = sinf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("sinf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = sinf(value); + + if (!_isnanf(result)) + { + Fail("sinf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.318309886f, 0.312961796f, PAL_EPSILON }, // value: 1 / pi + { 0.434294482f, 0.420770483f, PAL_EPSILON }, // value: log10f(e) + { 0.636619772f, 0.594480769f, PAL_EPSILON }, // value: 2 / pi + { 0.693147181f, 0.638961276f, PAL_EPSILON }, // value: ln(2) + { 0.707106781f, 0.649636939f, PAL_EPSILON }, // value: 1 / sqrtf(2) + { 0.785398163f, 0.707106781f, PAL_EPSILON }, // value: pi / 4, expected: 1 / sqrtf(2) + { 1, 0.841470985f, PAL_EPSILON }, + { 1.12837917f, 0.903719457f, PAL_EPSILON }, // value: 2 / sqrtf(pi) + { 1.41421356f, 0.987765946f, PAL_EPSILON }, // value: sqrtf(2) + { 1.44269504f, 0.991806244f, PAL_EPSILON }, // value: logf2(e) + { 1.57079633f, 1, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.30258509f, 0.743980337f, PAL_EPSILON }, // value: ln(10) + { 2.71828183f, 0.410781291f, PAL_EPSILON }, // value: e + { 3.14159265f, 0, PAL_EPSILON }, // value: pi + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + validate_isnan(PAL_POSINF); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sinf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sinf/test1/testinfo.dat new file mode 100644 index 0000000..08ff602 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sinf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sinf +Name = Positive Test for sinf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to sinf() a series of angle value, checking that += each one return to correct value. diff --git a/src/pal/tests/palsuite/c_runtime/sinh/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sinh/test1/CMakeLists.txt index 66cc691..b0101ba 100644 --- a/src/pal/tests/palsuite/c_runtime/sinh/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/sinh/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_sinh_test1 diff --git a/src/pal/tests/palsuite/c_runtime/sinh/test1/test1.c b/src/pal/tests/palsuite/c_runtime/sinh/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/sinh/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/sinh/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/sinhf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sinhf/CMakeLists.txt new file mode 100644 index 0000000..5e1ef7f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sinhf/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) diff --git a/src/pal/tests/palsuite/c_runtime/sinhf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sinhf/test1/CMakeLists.txt new file mode 100644 index 0000000..72cce43 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sinhf/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_sinhf_test1 + ${SOURCES} +) + +add_dependencies(paltest_sinhf_test1 coreclrpal) + +target_link_libraries(paltest_sinhf_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sinhf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/sinhf/test1/test1.c new file mode 100644 index 0000000..4e706a2 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sinhf/test1/test1.c @@ -0,0 +1,129 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that sinhf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = sinhf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("sinhf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = sinhf(value); + + if (!_isnanf(result)) + { + Fail("sinhf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.318309886f, 0.323712439f, PAL_EPSILON }, // value: 1 / pi + { 0.434294482f, 0.448075979f, PAL_EPSILON }, // value: log10f(e) + { 0.636619772f, 0.680501678f, PAL_EPSILON }, // value: 2 / pi + { 0.693147181f, 0.75, PAL_EPSILON }, // value: ln(2) + { 0.707106781f, 0.767523145f, PAL_EPSILON }, // value: 1 / sqrtf(2) + { 0.785398163f, 0.868670961f, PAL_EPSILON }, // value: pi / 4 + { 1, 1.17520119f, PAL_EPSILON * 10 }, + { 1.12837917f, 1.38354288f, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi) + { 1.41421356f, 1.93506682f, PAL_EPSILON * 10 }, // value: sqrtf(2) + { 1.44269504f, 1.99789801f, PAL_EPSILON * 10 }, // value: logf2(e) + { 1.57079633f, 2.30129890f, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.30258509f, 4.95f, PAL_EPSILON * 10 }, // value: ln(10) + { 2.71828183f, 7.54413710f, PAL_EPSILON * 10 }, // value: e + { 3.14159265f, 11.5487394f, PAL_EPSILON * 100 }, // value: pi + { PAL_POSINF, PAL_POSINF, 0 }, + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sinhf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sinhf/test1/testinfo.dat new file mode 100644 index 0000000..cfb27f5 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sinhf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sinhf +Name = Positive Test for sinhf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to sinhf() a series of angle value, checking that += each one return to correct value. diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/CMakeLists.txt deleted file mode 100644 index cafb953..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -add_subdirectory(test1) -add_subdirectory(test10) -add_subdirectory(test11) -add_subdirectory(test12) -add_subdirectory(test13) -add_subdirectory(test14) -add_subdirectory(test15) -add_subdirectory(test16) -add_subdirectory(test17) -add_subdirectory(test18) -add_subdirectory(test19) -add_subdirectory(test2) -add_subdirectory(test3) -add_subdirectory(test4) -add_subdirectory(test5) -add_subdirectory(test6) -add_subdirectory(test7) -add_subdirectory(test8) -add_subdirectory(test9) - diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/sprintf.h b/src/pal/tests/palsuite/c_runtime/sprintf/sprintf.h deleted file mode 100644 index 411ae66..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/sprintf.h +++ /dev/null @@ -1,195 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: sprintf.h -** -** Purpose: Containts common testing functions for sprintf -** -** -**==========================================================================*/ - -#ifndef __SPRINTF_H__ -#define __SPRINTF_H__ - -void DoStrTest(char *formatstr, char* param, char *checkstr) -{ - char buf[256] = { 0 }; - - sprintf(buf, formatstr, param); - if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) - { - Fail("ERROR: failed to insert string \"%s\" into \"%s\"\n" - "Expected \"%s\" got \"%s\".\n", - param, formatstr, checkstr, buf); - } -} - -void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr) -{ - char buf[256] = { 0 }; - - sprintf(buf, formatstr, param); - if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) - { - Fail("ERROR: failed to insert wide string \"%s\" into \"%s\"\n" - "Expected \"%s\" got \"%s\".\n", - convertC(param), formatstr, checkstr, buf); - } -} - -void DoPointerTest(char *formatstr, void* param, char* paramstr, - char *checkstr1) -{ - char buf[256] = { 0 }; - - sprintf(buf, formatstr, param); - if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0) - { - Fail("ERROR: failed to insert %s into \"%s\"\n" - "Expected \"%s\" got \"%s\".\n", - paramstr, formatstr, checkstr1, buf); - } -} - -void DoCountTest(char *formatstr, int param, char *checkstr) -{ - char buf[512] = { 0 }; - int n = -1; - - sprintf(buf, formatstr, &n); - - if (n != param) - { - Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", - param, n); - } - if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) - { - Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf); - } -} - -void DoShortCountTest(char *formatstr, int param, char *checkstr) -{ - char buf[256] = { 0 }; - short int n = -1; - - sprintf(buf, formatstr, &n); - - if (n != param) - { - Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", - param, n); - } - if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) - { - Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf); - } -} - - -void DoCharTest(char *formatstr, char param, char *checkstr) -{ - char buf[256] = { 0 }; - - sprintf(buf, formatstr, param); - if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) - { - Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n" - "Expected \"%s\" got \"%s\".\n", - param, param, formatstr, checkstr, buf); - } -} - -void DoWCharTest(char *formatstr, WCHAR param, char *checkstr) -{ - char buf[256] = { 0 }; - - sprintf(buf, formatstr, param); - if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) - { - Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n" - "Expected \"%s\" got \"%s\".\n", - (char)param, param, formatstr, checkstr, buf); - } -} - -void DoNumTest(char *formatstr, int value, char *checkstr) -{ - char buf[256] = { 0 }; - - sprintf(buf, formatstr, value); - if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) - { - Fail("ERROR: failed to insert %#x into \"%s\"\n" - "Expected \"%s\" got \"%s\".\n", - value, formatstr, checkstr, buf); - } -} - -void DoI64Test(char *formatstr, INT64 value, char *valuestr, char *checkstr1) -{ - char buf[256] = { 0 }; - - sprintf(buf, formatstr, value); - if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0) - { - Fail("ERROR: failed to insert %s into \"%s\"\n" - "Expected \"%s\", got \"%s\".\n", - valuestr, formatstr, checkstr1, buf); - } -} - -void DoDoubleTest(char *formatstr, double value, char *checkstr1, - char *checkstr2) -{ - char buf[256] = { 0 }; - - sprintf(buf, formatstr, value); - if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && - memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) - { - Fail("ERROR: failed to insert %f into \"%s\"\n" - "Expected \"%s\" or \"%s\", got \"%s\".\n", - value, formatstr, checkstr1, checkstr2, buf); - } -} - -void DoArgumentPrecTest(char *formatstr, int precision, void *param, - char *paramstr, char *checkstr1, char *checkstr2) -{ - char buf[256]; - - sprintf(buf, formatstr, precision, param); - if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && - memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) - { - Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" - "Expected \"%s\" or \"%s\", got \"%s\".\n", paramstr, formatstr, - precision, checkstr1, checkstr2, buf); - } - -} - -void DoArgumentPrecDoubleTest(char *formatstr, int precision, double param, - char *checkstr1, char *checkstr2) -{ - char buf[256]; - - sprintf(buf, formatstr, precision, param); - if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && - memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) - { - Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" - "Expected \"%s\" or \"%s\", got \"%s\".\n", param, formatstr, - precision, checkstr1, checkstr2, buf); - } - -} - -#endif - - diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test1/CMakeLists.txt deleted file mode 100644 index bdec045..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test1/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test1.c -) - -add_executable(paltest_sprintf_test1 - ${SOURCES} -) - -add_dependencies(paltest_sprintf_test1 coreclrpal) - -target_link_libraries(paltest_sprintf_test1 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/sprintf/test1/test1.c deleted file mode 100644 index 42e27f2..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test1/test1.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: Test #1 for the sprintf function. A single, basic, test -** case with no formatting. -** -** -**==========================================================================*/ - - - -#include -#include "../sprintf.h" - -/* - * Depends on memcmp and strlen - */ - -int __cdecl main(int argc, char *argv[]) -{ - char checkstr[] = "hello world"; - char buf[256]; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - sprintf(buf, "hello world"); - - if (memcmp(checkstr, buf, strlen(checkstr)+1) != 0) - { - Fail("ERROR: expected %s, got %s\n", checkstr, buf); - } - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test1/testinfo.dat deleted file mode 100644 index abe0744..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test1/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sprintf -Name = Positive Test for sprintf -TYPE = DEFAULT -EXE1 = test1 -Description -= General test to see if sprintf works correctly diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test10/CMakeLists.txt deleted file mode 100644 index 91e9db8..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test10/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test10.c -) - -add_executable(paltest_sprintf_test10 - ${SOURCES} -) - -add_dependencies(paltest_sprintf_test10 coreclrpal) - -target_link_libraries(paltest_sprintf_test10 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/sprintf/test10/test10.c deleted file mode 100644 index ae7dbfb..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test10/test10.c +++ /dev/null @@ -1,55 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test10.c -** -** Purpose: Test #10 for the sprintf function. Tests the octal specifier -** (%o). -** -** -**==========================================================================*/ - - - -#include -#include "../sprintf.h" - -/* - * Depends on memcmp and strlen - */ - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 42; - INT64 l = 42; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoNumTest("foo %o", pos, "foo 52"); - DoNumTest("foo %lo", 0xFFFF, "foo 177777"); - DoNumTest("foo %ho", 0xFFFF, "foo 177777"); - DoNumTest("foo %Lo", pos, "foo 52"); - DoI64Test("foo %I64o", l, "42", "foo 52"); - DoNumTest("foo %3o", pos, "foo 52"); - DoNumTest("foo %-3o", pos, "foo 52 "); - DoNumTest("foo %.1o", pos, "foo 52"); - DoNumTest("foo %.3o", pos, "foo 052"); - DoNumTest("foo %03o", pos, "foo 052"); - DoNumTest("foo %#o", pos, "foo 052"); - DoNumTest("foo %+o", pos, "foo 52"); - DoNumTest("foo % o", pos, "foo 52"); - DoNumTest("foo %+o", neg, "foo 37777777726"); - DoNumTest("foo % o", neg, "foo 37777777726"); - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test10/testinfo.dat deleted file mode 100644 index 70b7f3a..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test10/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sprintf -Name = Positive Test for sprintf -TYPE = DEFAULT -EXE1 = test10 -Description -= Tests sprintf with octal numbers diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test11/CMakeLists.txt deleted file mode 100644 index b14c8be..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test11/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test11.c -) - -add_executable(paltest_sprintf_test11 - ${SOURCES} -) - -add_dependencies(paltest_sprintf_test11 coreclrpal) - -target_link_libraries(paltest_sprintf_test11 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/sprintf/test11/test11.c deleted file mode 100644 index 0b5b5ab..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test11/test11.c +++ /dev/null @@ -1,55 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test11.c -** -** Purpose: Test #11 for the sprintf function. Test the unsigned int -** specifier (%u). -** -** -**==========================================================================*/ - - - -#include -#include "../sprintf.h" - -/* - * Depends on memcmp and strlen - */ - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 42; - INT64 l = 42; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoNumTest("foo %u", pos, "foo 42"); - DoNumTest("foo %lu", 0xFFFF, "foo 65535"); - DoNumTest("foo %hu", 0xFFFF, "foo 65535"); - DoNumTest("foo %Lu", pos, "foo 42"); - DoI64Test("foo %I64u", l, "42", "foo 42"); - DoNumTest("foo %3u", pos, "foo 42"); - DoNumTest("foo %-3u", pos, "foo 42 "); - DoNumTest("foo %.1u", pos, "foo 42"); - DoNumTest("foo %.3u", pos, "foo 042"); - DoNumTest("foo %03u", pos, "foo 042"); - DoNumTest("foo %#u", pos, "foo 42"); - DoNumTest("foo %+u", pos, "foo 42"); - DoNumTest("foo % u", pos, "foo 42"); - DoNumTest("foo %+u", neg, "foo 4294967254"); - DoNumTest("foo % u", neg, "foo 4294967254"); - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test11/testinfo.dat deleted file mode 100644 index 852bd3e..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test11/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sprintf -Name = Positive Test for sprintf -TYPE = DEFAULT -EXE1 = test11 -Description -= Tests sprintf with unsigned numbers diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test12/CMakeLists.txt deleted file mode 100644 index 1e51749..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test12/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test12.c -) - -add_executable(paltest_sprintf_test12 - ${SOURCES} -) - -add_dependencies(paltest_sprintf_test12 coreclrpal) - -target_link_libraries(paltest_sprintf_test12 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/sprintf/test12/test12.c deleted file mode 100644 index c2e778e..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test12/test12.c +++ /dev/null @@ -1,56 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test12.c -** -** Purpose: Test #12 for the sprintf function. Tests the (lowercase) -** hexadecimal specifier (%x) -** -** -**==========================================================================*/ - - - -#include -#include "../sprintf.h" - -/* - * Depends on memcmp and strlen - */ - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 0x1234ab; - INT64 l = I64(0x1234567887654321); - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoNumTest("foo %x", pos, "foo 1234ab"); - DoNumTest("foo %lx", pos, "foo 1234ab"); - DoNumTest("foo %hx", pos, "foo 34ab"); - DoNumTest("foo %Lx", pos, "foo 1234ab"); - DoI64Test("foo %I64x", l, "0x1234567887654321", - "foo 1234567887654321"); - DoNumTest("foo %7x", pos, "foo 1234ab"); - DoNumTest("foo %-7x", pos, "foo 1234ab "); - DoNumTest("foo %.1x", pos, "foo 1234ab"); - DoNumTest("foo %.7x", pos, "foo 01234ab"); - DoNumTest("foo %07x", pos, "foo 01234ab"); - DoNumTest("foo %#x", pos, "foo 0x1234ab"); - DoNumTest("foo %+x", pos, "foo 1234ab"); - DoNumTest("foo % x", pos, "foo 1234ab"); - DoNumTest("foo %+x", neg, "foo ffffffd6"); - DoNumTest("foo % x", neg, "foo ffffffd6"); - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test12/testinfo.dat deleted file mode 100644 index 5df91d0..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test12/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sprintf -Name = Positive Test for sprintf -TYPE = DEFAULT -EXE1 = test12 -Description -= Tests sprintf with hex numbers (lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test13/CMakeLists.txt deleted file mode 100644 index 25b033f..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test13/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test13.c -) - -add_executable(paltest_sprintf_test13 - ${SOURCES} -) - -add_dependencies(paltest_sprintf_test13 coreclrpal) - -target_link_libraries(paltest_sprintf_test13 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/sprintf/test13/test13.c deleted file mode 100644 index 0b4b7ed..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test13/test13.c +++ /dev/null @@ -1,56 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test13.c -** -** Purpose: Test #13 for the sprintf function. Tests the (uppercase) -** hexadecimal specifier (%X) -** -** -**==========================================================================*/ - - - -#include -#include "../sprintf.h" - -/* - * Depends on memcmp and strlen - */ - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 0x1234AB; - INT64 l = I64(0x1234567887654321); - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoNumTest("foo %X", pos, "foo 1234AB"); - DoNumTest("foo %lX", pos, "foo 1234AB"); - DoNumTest("foo %hX", pos, "foo 34AB"); - DoNumTest("foo %LX", pos, "foo 1234AB"); - DoI64Test("foo %I64X", l, "0x1234567887654321", - "foo 1234567887654321"); - DoNumTest("foo %7X", pos, "foo 1234AB"); - DoNumTest("foo %-7X", pos, "foo 1234AB "); - DoNumTest("foo %.1X", pos, "foo 1234AB"); - DoNumTest("foo %.7X", pos, "foo 01234AB"); - DoNumTest("foo %07X", pos, "foo 01234AB"); - DoNumTest("foo %#X", pos, "foo 0X1234AB"); - DoNumTest("foo %+X", pos, "foo 1234AB"); - DoNumTest("foo % X", pos, "foo 1234AB"); - DoNumTest("foo %+X", neg, "foo FFFFFFD6"); - DoNumTest("foo % X", neg, "foo FFFFFFD6"); - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test13/testinfo.dat deleted file mode 100644 index 634817a..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test13/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sprintf -Name = Positive Test for sprintf -TYPE = DEFAULT -EXE1 = test13 -Description -= Tests sprintf with hex numbers (uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test14/CMakeLists.txt deleted file mode 100644 index 5eae306..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test14/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test14.c -) - -add_executable(paltest_sprintf_test14 - ${SOURCES} -) - -add_dependencies(paltest_sprintf_test14 coreclrpal) - -target_link_libraries(paltest_sprintf_test14 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/sprintf/test14/test14.c deleted file mode 100644 index 20e986a..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test14/test14.c +++ /dev/null @@ -1,53 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test14.c -** -** Purpose: Test #14 for the sprintf function. Tests the lowercase -** exponential notation double specifier (%e) -** -** -**==========================================================================*/ - - - -#include -#include "../sprintf.h" - -/* - * Depends on memcmp and strlen - */ - -int __cdecl main(int argc, char *argv[]) -{ - double val = 256.0; - double neg = -256.0; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoDoubleTest("foo %e", val, "foo 2.560000e+002", "foo 2.560000e+02"); - DoDoubleTest("foo %le", val, "foo 2.560000e+002", "foo 2.560000e+02"); - DoDoubleTest("foo %he", val, "foo 2.560000e+002", "foo 2.560000e+02"); - DoDoubleTest("foo %Le", val, "foo 2.560000e+002", "foo 2.560000e+02"); - DoDoubleTest("foo %I64e", val, "foo 2.560000e+002", "foo 2.560000e+02"); - DoDoubleTest("foo %14e", val, "foo 2.560000e+002", "foo 2.560000e+02"); - DoDoubleTest("foo %-14e", val, "foo 2.560000e+002 ", "foo 2.560000e+02 "); - DoDoubleTest("foo %.1e", val, "foo 2.6e+002", "foo 2.6e+02"); - DoDoubleTest("foo %.8e", val, "foo 2.56000000e+002", "foo 2.56000000e+02"); - DoDoubleTest("foo %014e", val, "foo 02.560000e+002", "foo 002.560000e+02"); - DoDoubleTest("foo %#e", val, "foo 2.560000e+002", "foo 2.560000e+02"); - DoDoubleTest("foo %+e", val, "foo +2.560000e+002", "foo +2.560000e+02"); - DoDoubleTest("foo % e", val, "foo 2.560000e+002", "foo 2.560000e+02"); - DoDoubleTest("foo %+e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); - DoDoubleTest("foo % e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test14/testinfo.dat deleted file mode 100644 index c7086ef..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test14/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sprintf -Name = Positive Test for sprintf -TYPE = DEFAULT -EXE1 = test14 -Description -= Tests sprintf with exponential format doubles (lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test15/CMakeLists.txt deleted file mode 100644 index 1fff23f..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test15/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test15.c -) - -add_executable(paltest_sprintf_test15 - ${SOURCES} -) - -add_dependencies(paltest_sprintf_test15 coreclrpal) - -target_link_libraries(paltest_sprintf_test15 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/sprintf/test15/test15.c deleted file mode 100644 index 34199b2..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test15/test15.c +++ /dev/null @@ -1,53 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test15.c -** -** Purpose: Test #15 for the sprintf function. Tests the uppercase -** exponential notation double specifier (%E) -** -** -**==========================================================================*/ - - - -#include -#include "../sprintf.h" - -/* - * Depends on memcmp and strlen - */ - -int __cdecl main(int argc, char *argv[]) -{ - double val = 256.0; - double neg = -256.0; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoDoubleTest("foo %E", val, "foo 2.560000E+002", "foo 2.560000E+02"); - DoDoubleTest("foo %lE", val, "foo 2.560000E+002", "foo 2.560000E+02"); - DoDoubleTest("foo %hE", val, "foo 2.560000E+002", "foo 2.560000E+02"); - DoDoubleTest("foo %LE", val, "foo 2.560000E+002", "foo 2.560000E+02"); - DoDoubleTest("foo %I64E", val, "foo 2.560000E+002", "foo 2.560000E+02"); - DoDoubleTest("foo %14E", val, "foo 2.560000E+002", "foo 2.560000E+02"); - DoDoubleTest("foo %-14E", val, "foo 2.560000E+002 ", "foo 2.560000E+02 "); - DoDoubleTest("foo %.1E", val, "foo 2.6E+002", "foo 2.6E+02"); - DoDoubleTest("foo %.8E", val, "foo 2.56000000E+002", "foo 2.56000000E+02"); - DoDoubleTest("foo %014E", val, "foo 02.560000E+002", "foo 002.560000E+02"); - DoDoubleTest("foo %#E", val, "foo 2.560000E+002", "foo 2.560000E+02"); - DoDoubleTest("foo %+E", val, "foo +2.560000E+002", "foo +2.560000E+02"); - DoDoubleTest("foo % E", val, "foo 2.560000E+002", "foo 2.560000E+02"); - DoDoubleTest("foo %+E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); - DoDoubleTest("foo % E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test15/testinfo.dat deleted file mode 100644 index 0a47c53..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test15/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sprintf -Name = Positive Test for sprintf -TYPE = DEFAULT -EXE1 = test15 -Description -= Tests sprintf with exponential format doubles (uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test16/CMakeLists.txt deleted file mode 100644 index 2065c57..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test16/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test16.c -) - -add_executable(paltest_sprintf_test16 - ${SOURCES} -) - -add_dependencies(paltest_sprintf_test16 coreclrpal) - -target_link_libraries(paltest_sprintf_test16 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/sprintf/test16/test16.c deleted file mode 100644 index c93b68b..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test16/test16.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test16.c -** -** Purpose: Test #16 for the sprintf function. Tests the decimal notation -** double specifier (%f) -** -** -**==========================================================================*/ - - -#include -#include "../sprintf.h" - -/* - * Depends on memcmp and strlen - */ - -int __cdecl main(int argc, char *argv[]) -{ - double val = 2560.001; - double neg = -2560.001; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoDoubleTest("foo %f", val, "foo 2560.001000", "foo 2560.001000"); - DoDoubleTest("foo %lf", val, "foo 2560.001000", "foo 2560.001000"); - DoDoubleTest("foo %hf", val, "foo 2560.001000", "foo 2560.001000"); - DoDoubleTest("foo %Lf", val, "foo 2560.001000", "foo 2560.001000"); - DoDoubleTest("foo %I64f", val, "foo 2560.001000", "foo 2560.001000"); - DoDoubleTest("foo %12f", val, "foo 2560.001000", "foo 2560.001000"); - DoDoubleTest("foo %-12f", val, "foo 2560.001000 ", "foo 2560.001000 "); - DoDoubleTest("foo %.1f", val, "foo 2560.0", "foo 2560.0"); - DoDoubleTest("foo %.8f", val, "foo 2560.00100000", "foo 2560.00100000"); - DoDoubleTest("foo %012f", val, "foo 02560.001000", "foo 02560.001000"); - DoDoubleTest("foo %#f", val, "foo 2560.001000", "foo 2560.001000"); - DoDoubleTest("foo %+f", val, "foo +2560.001000", "foo +2560.001000"); - DoDoubleTest("foo % f", val, "foo 2560.001000", "foo 2560.001000"); - DoDoubleTest("foo %+f", neg, "foo -2560.001000", "foo -2560.001000"); - DoDoubleTest("foo % f", neg, "foo -2560.001000", "foo -2560.001000"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test16/testinfo.dat deleted file mode 100644 index e18fab1..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test16/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sprintf -Name = Positive Test for sprintf -TYPE = DEFAULT -EXE1 = test16 -Description -= Tests sprintf with decimal point format doubles diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test17/CMakeLists.txt deleted file mode 100644 index ce3a8ad..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test17/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test17.c -) - -add_executable(paltest_sprintf_test17 - ${SOURCES} -) - -add_dependencies(paltest_sprintf_test17 coreclrpal) - -target_link_libraries(paltest_sprintf_test17 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/sprintf/test17/test17.c deleted file mode 100644 index 643215b..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test17/test17.c +++ /dev/null @@ -1,54 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test17.c -** -** Purpose: Test #17 for the sprintf function. Tests the lowercase -** shorthand notation double specifier (%g) -** -** -**==========================================================================*/ - - - -#include -#include "../sprintf.h" - -/* - * Depends on memcmp and strlen - */ - -int __cdecl main(int argc, char *argv[]) -{ - double val = 2560.001; - double neg = -2560.001; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoDoubleTest("foo %g", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %lg", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %hg", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %Lg", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %I64g", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %5g", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %-5g", val, "foo 2560 ", "foo 2560 "); - DoDoubleTest("foo %.1g", val, "foo 3e+003", "foo 3e+03"); - DoDoubleTest("foo %.2g", val, "foo 2.6e+003", "foo 2.6e+03"); - DoDoubleTest("foo %.12g", val, "foo 2560.001", "foo 2560.001"); - DoDoubleTest("foo %06g", val, "foo 002560", "foo 002560"); - DoDoubleTest("foo %#g", val, "foo 2560.00", "foo 2560.00"); - DoDoubleTest("foo %+g", val, "foo +2560", "foo +2560"); - DoDoubleTest("foo % g", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %+g", neg, "foo -2560", "foo -2560"); - DoDoubleTest("foo % g", neg, "foo -2560", "foo -2560"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test17/testinfo.dat deleted file mode 100644 index a723103..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test17/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sprintf -Name = Positive Test for sprintf -TYPE = DEFAULT -EXE1 = test17 -Description -= Tests sprintf with compact format doubles (lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test18/CMakeLists.txt deleted file mode 100644 index 6f69e1c..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test18/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test18.c -) - -add_executable(paltest_sprintf_test18 - ${SOURCES} -) - -add_dependencies(paltest_sprintf_test18 coreclrpal) - -target_link_libraries(paltest_sprintf_test18 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/sprintf/test18/test18.c deleted file mode 100644 index fa88152..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test18/test18.c +++ /dev/null @@ -1,53 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test18.c -** -** Purpose: Test #18 for the sprintf function. Tests the uppercase -** shorthand notation double specifier (%G) -** -** -**==========================================================================*/ - - -#include -#include "../sprintf.h" - -/* - * Depends on memcmp and strlen - */ - -int __cdecl main(int argc, char *argv[]) -{ - double val = 2560.001; - double neg = -2560.001; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoDoubleTest("foo %G", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %lG", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %hG", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %LG", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %I64G", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %5G", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %-5G", val, "foo 2560 ", "foo 2560 "); - DoDoubleTest("foo %.1G", val, "foo 3E+003", "foo 3E+03"); - DoDoubleTest("foo %.2G", val, "foo 2.6E+003", "foo 2.6E+03"); - DoDoubleTest("foo %.12G", val, "foo 2560.001", "foo 2560.001"); - DoDoubleTest("foo %06G", val, "foo 002560", "foo 002560"); - DoDoubleTest("foo %#G", val, "foo 2560.00", "foo 2560.00"); - DoDoubleTest("foo %+G", val, "foo +2560", "foo +2560"); - DoDoubleTest("foo % G", val, "foo 2560", "foo 2560"); - DoDoubleTest("foo %+G", neg, "foo -2560", "foo -2560"); - DoDoubleTest("foo % G", neg, "foo -2560", "foo -2560"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test18/testinfo.dat deleted file mode 100644 index dfafa4b..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test18/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sprintf -Name = Positive Test for sprintf -TYPE = DEFAULT -EXE1 = test18 -Description -= Tests sprintf with compact format doubles (uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test19/CMakeLists.txt deleted file mode 100644 index a2917b2..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test19/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test19.c -) - -add_executable(paltest_sprintf_test19 - ${SOURCES} -) - -add_dependencies(paltest_sprintf_test19 coreclrpal) - -target_link_libraries(paltest_sprintf_test19 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/sprintf/test19/test19.c deleted file mode 100644 index aee731c..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test19/test19.c +++ /dev/null @@ -1,78 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test19.c -** -** Purpose: Test #19 for the sprintf function. Tests the variable length -** precision argument. -** -** -**==========================================================================*/ - - -#include -#include "../sprintf.h" - -/* - * Depends on memcmp and strlen - */ - - -int __cdecl main(int argc, char *argv[]) -{ - int n = -1; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - DoArgumentPrecTest("%.*s", 2, "bar", "bar", "ba", "ba"); - DoArgumentPrecTest("%.*S", 2, convert("bar"), "bar", "ba", "ba"); - - DoArgumentPrecTest("%.*n", 3, &n, "pointer to int", "", ""); - if (n != 0) - { - Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", - 0, n); - } - - DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); - DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); - DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); - DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); - DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42"); - DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); - - - DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); - DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); - DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); - DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); - DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); - DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); - DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); - DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); - DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); - DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test19/testinfo.dat deleted file mode 100644 index ebd1302..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test19/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sprintf -Name = Positive Test for sprintf -TYPE = DEFAULT -EXE1 = test19 -Description -= Tests sprintf with argument specified precision diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test2/CMakeLists.txt deleted file mode 100644 index 8af1c53..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test2/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test2.c -) - -add_executable(paltest_sprintf_test2 - ${SOURCES} -) - -add_dependencies(paltest_sprintf_test2 coreclrpal) - -target_link_libraries(paltest_sprintf_test2 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/sprintf/test2/test2.c deleted file mode 100644 index d50679a..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test2/test2.c +++ /dev/null @@ -1,47 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test2.c -** -** Purpose: Test #2 for the sprintf function. Tests the string specifier -** (%s). -** -** -**==========================================================================*/ - - -#include -#include "../sprintf.h" - -/* - * Depends on memcmp and strlen - */ - -int __cdecl main(int argc, char *argv[]) -{ - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoStrTest("foo %s", "bar", "foo bar"); - DoStrTest("foo %hs", "bar", "foo bar"); - DoWStrTest("foo %ls", convert("bar"), "foo bar"); - DoWStrTest("foo %ws", convert("bar"), "foo bar"); - DoStrTest("foo %Ls", "bar", "foo bar"); - DoStrTest("foo %I64s", "bar", "foo bar"); - DoStrTest("foo %5s", "bar", "foo bar"); - DoStrTest("foo %.2s", "bar", "foo ba"); - DoStrTest("foo %5.2s", "bar", "foo ba"); - DoStrTest("foo %-5s", "bar", "foo bar "); - DoStrTest("foo %05s", "bar", "foo 00bar"); - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test2/testinfo.dat deleted file mode 100644 index e8d0f53..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test2/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sprintf -Name = Positive Test for sprintf -TYPE = DEFAULT -EXE1 = test2 -Description -= Tests sprintf with strings diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test3/CMakeLists.txt deleted file mode 100644 index b7b7e0a..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test3/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test3.c -) - -add_executable(paltest_sprintf_test3 - ${SOURCES} -) - -add_dependencies(paltest_sprintf_test3 coreclrpal) - -target_link_libraries(paltest_sprintf_test3 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/sprintf/test3/test3.c deleted file mode 100644 index ae52dbe..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test3/test3.c +++ /dev/null @@ -1,47 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test3.c -** -** Purpose: Test #3 for the sprintf function. Tests the wide string -** specifier (%S). -** -** -**==========================================================================*/ - - - -#include -#include "../sprintf.h" - -/* - * Depends on memcmp and strlen - */ - -int __cdecl main(int argc, char *argv[]) -{ - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - DoWStrTest("foo %S", convert("bar"), "foo bar"); - DoStrTest("foo %hS", "bar", "foo bar"); - DoWStrTest("foo %lS", convert("bar"), "foo bar"); - DoWStrTest("foo %wS", convert("bar"), "foo bar"); - DoWStrTest("foo %LS", convert("bar"), "foo bar"); - DoWStrTest("foo %I64S", convert("bar"), "foo bar"); - DoWStrTest("foo %5S", convert("bar"), "foo bar"); - DoWStrTest("foo %.2S", convert("bar"), "foo ba"); - DoWStrTest("foo %5.2S", convert("bar"), "foo ba"); - DoWStrTest("foo %-5S", convert("bar"), "foo bar "); - DoWStrTest("foo %05S", convert("bar"), "foo 00bar"); - - PAL_Terminate(); - return PASS; -} - - diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test3/testinfo.dat deleted file mode 100644 index 12e0a9c..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test3/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sprintf -Name = Positive Test for sprintf -TYPE = DEFAULT -EXE1 = test3 -Description -= Tests sprintf with wide strings diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test4/CMakeLists.txt deleted file mode 100644 index 3478867..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test4/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test4.c -) - -add_executable(paltest_sprintf_test4 - ${SOURCES} -) - -add_dependencies(paltest_sprintf_test4 coreclrpal) - -target_link_libraries(paltest_sprintf_test4 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/sprintf/test4/test4.c deleted file mode 100644 index 9660ffa..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test4/test4.c +++ /dev/null @@ -1,69 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test4.c -** -** Purpose: Test #4 for the sprintf function. Tests the pointer -** specifier (%p). -** -** -**==========================================================================*/ - - - -#include -#include "../sprintf.h" -/* - * Depends on memcmp and strlen - */ - -int __cdecl main(int argc, char *argv[]) -{ - void *ptr = (void*) 0x123456; - INT64 lptr = I64(0x1234567887654321); - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - -/* -** Run only on 64 bit platforms -*/ -#if defined(BIT64) && defined(PLATFORM_UNIX) - Trace("Testing for 64 Bit Platforms \n"); - DoPointerTest("%p", NULL, "NULL", "0000000000000000"); - DoPointerTest("%p", ptr, "pointer to 0x123456", "0000000000123456"); - DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); - DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); - DoPointerTest("%-17p", ptr, "pointer to 0x123456", "0000000000123456 "); - DoPointerTest("%+p", ptr, "pointer to 0x123456", "0000000000123456"); - DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X0000000000123456"); - DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); - DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); - DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); - DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321", - "1234567887654321"); -#else - Trace("Testing for Non 64 Bit Platforms \n"); - DoPointerTest("%p", NULL, "NULL", "00000000"); - DoPointerTest("%p", ptr, "pointer to 0x123456", "00123456"); - DoPointerTest("%9p", ptr, "pointer to 0x123456", " 00123456"); - DoPointerTest("%09p", ptr, "pointer to 0x123456", " 00123456"); - DoPointerTest("%-9p", ptr, "pointer to 0x123456", "00123456 "); - DoPointerTest("%+p", ptr, "pointer to 0x123456", "00123456"); - DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X00123456"); - DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); - DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); - DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); - DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321", - "1234567887654321"); -#endif - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test4/testinfo.dat deleted file mode 100644 index bf7236d..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test4/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sprintf -Name = Positive Test for sprintf -TYPE = DEFAULT -EXE1 = test4 -Description -= Tests sprintf with pointers diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test5/CMakeLists.txt deleted file mode 100644 index dfa7583..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test5/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test5.c -) - -add_executable(paltest_sprintf_test5 - ${SOURCES} -) - -add_dependencies(paltest_sprintf_test5 coreclrpal) - -target_link_libraries(paltest_sprintf_test5 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/sprintf/test5/test5.c deleted file mode 100644 index 1b52da7..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test5/test5.c +++ /dev/null @@ -1,62 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test5.c -** -** Purpose: Test #5 for the sprintf function. Tests the count specifier (%n). -** -** -**==========================================================================*/ - - - -#include -#include "../sprintf.h" - -/* - * Depends on memcmp and strlen - */ - - -int __cdecl main(int argc, char *argv[]) -{ - char *longStr = - "really-long-string-that-just-keeps-going-on-and-on-and-on.." - "..................useless-filler.................................." - "..................useless-filler.................................." - "..................useless-filler.................................." - "%n bar"; - char *longResult = - "really-long-string-that-just-keeps-going-on-and-on-and-on.." - "..................useless-filler.................................." - "..................useless-filler.................................." - "..................useless-filler.................................." - " bar"; - - if (PAL_Initialize(argc, argv)!= 0) - { - return FAIL; - } - - DoCountTest("foo %n bar", 4, "foo bar"); - DoCountTest(longStr, 257, longResult); - DoCountTest("fo%n bar", 2, "fo bar"); - DoCountTest("%n", 0, ""); - DoCountTest("foo %#n bar", 4, "foo bar"); - DoCountTest("foo % n bar", 4, "foo bar"); - DoCountTest("foo %+n bar", 4, "foo bar"); - DoCountTest("foo %-n bar", 4, "foo bar"); - DoCountTest("foo %0n bar", 4, "foo bar"); - DoShortCountTest("foo %hn bar", 4, "foo bar"); - DoCountTest("foo %ln bar", 4, "foo bar"); - DoCountTest("foo %Ln bar", 4, "foo bar"); - DoCountTest("foo %I64n bar", 4, "foo bar"); - DoCountTest("foo %20.3n bar", 4, "foo bar"); - - PAL_Terminate(); - - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test5/testinfo.dat deleted file mode 100644 index 31e0537..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test5/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sprintf -Name = Positive Test for sprintf -TYPE = DEFAULT -EXE1 = test5 -Description -= Tests sprintf with the count specifier diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test6/CMakeLists.txt deleted file mode 100644 index 7a9a5fc..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test6/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test6.c -) - -add_executable(paltest_sprintf_test6 - ${SOURCES} -) - -add_dependencies(paltest_sprintf_test6 coreclrpal) - -target_link_libraries(paltest_sprintf_test6 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/sprintf/test6/test6.c deleted file mode 100644 index c14e075..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test6/test6.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test6.c -** -** Purpose: Test #6 for the sprintf function. Tests the char specifier (%c). -** -** -**==========================================================================*/ - - - -#include -#include "../sprintf.h" - -/* - * Depends on memcmp and strlen - */ - -int __cdecl main(int argc, char *argv[]) -{ - WCHAR wc = (WCHAR) 'c'; - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - DoCharTest("foo %c", 'b', "foo b"); - DoCharTest("foo %hc", 'b', "foo b"); - DoWCharTest("foo %lc", wc, "foo c"); - DoCharTest("foo %Lc", 'b', "foo b"); - DoCharTest("foo %I64c", 'b', "foo b"); - DoCharTest("foo %5c", 'b', "foo b"); - DoCharTest("foo %.0c", 'b', "foo b"); - DoCharTest("foo %-5c", 'b', "foo b "); - DoCharTest("foo %05c", 'b', "foo 0000b"); - DoCharTest("foo % c", 'b', "foo b"); - DoCharTest("foo %#c", 'b', "foo b"); - - PAL_Terminate(); - return PASS; -} - - - diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test6/testinfo.dat deleted file mode 100644 index 037e410..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test6/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sprintf -Name = Positive Test for sprintf -TYPE = DEFAULT -EXE1 = test6 -Description -= Tests sprintf with characters diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test7/CMakeLists.txt deleted file mode 100644 index a539a59..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test7/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test7.c -) - -add_executable(paltest_sprintf_test7 - ${SOURCES} -) - -add_dependencies(paltest_sprintf_test7 coreclrpal) - -target_link_libraries(paltest_sprintf_test7 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/sprintf/test7/test7.c deleted file mode 100644 index 082bd20..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test7/test7.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test7.c -** -** Purpose: Test #7 for the sprintf function. Tests the wide char -** specifier (%C). -** -** -**==========================================================================*/ - - - -#include -#include "../sprintf.h" - -/* - * Depends on memcmp and strlen - */ - -int __cdecl main(int argc, char *argv[]) -{ - WCHAR wb = (WCHAR) 'b'; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoWCharTest("foo %C", wb, "foo b"); - DoWCharTest("foo %hC", wb, "foo b"); - DoCharTest("foo %lC", 'c', "foo c"); - DoWCharTest("foo %LC", wb, "foo b"); - DoWCharTest("foo %I64C", wb, "foo b"); - DoWCharTest("foo %5C", wb, "foo b"); - DoWCharTest("foo %.0C", wb, "foo b"); - DoWCharTest("foo %-5C", wb, "foo b "); - DoWCharTest("foo %05C", wb, "foo 0000b"); - DoWCharTest("foo % C", wb, "foo b"); - DoWCharTest("foo %#C", wb, "foo b"); - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test7/testinfo.dat deleted file mode 100644 index a2730bc..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test7/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sprintf -Name = Positive Test for sprintf -TYPE = DEFAULT -EXE1 = test7 -Description -= Tests sprintf with wide characters diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test8/CMakeLists.txt deleted file mode 100644 index 7a92c50..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test8/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test8.c -) - -add_executable(paltest_sprintf_test8 - ${SOURCES} -) - -add_dependencies(paltest_sprintf_test8 coreclrpal) - -target_link_libraries(paltest_sprintf_test8 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/sprintf/test8/test8.c deleted file mode 100644 index 9587c82..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test8/test8.c +++ /dev/null @@ -1,55 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test8.c -** -** Purpose: Test #8 for the sprintf function. Tests the decimal -** specifier (%d). -** -** -**==========================================================================*/ - - - -#include -#include "../sprintf.h" - -/* - * Depends on memcmp and strlen - */ - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 42; - INT64 l = 42; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoNumTest("foo %d", pos, "foo 42"); - DoNumTest("foo %ld", 0xFFFF, "foo 65535"); - DoNumTest("foo %hd", 0xFFFF, "foo -1"); - DoNumTest("foo %Ld", pos, "foo 42"); - DoI64Test("foo %I64d", l, "42", "foo 42"); - DoNumTest("foo %3d", pos, "foo 42"); - DoNumTest("foo %-3d", pos, "foo 42 "); - DoNumTest("foo %.1d", pos, "foo 42"); - DoNumTest("foo %.3d", pos, "foo 042"); - DoNumTest("foo %03d", pos, "foo 042"); - DoNumTest("foo %#d", pos, "foo 42"); - DoNumTest("foo %+d", pos, "foo +42"); - DoNumTest("foo % d", pos, "foo 42"); - DoNumTest("foo %+d", neg, "foo -42"); - DoNumTest("foo % d", neg, "foo -42"); - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test8/testinfo.dat deleted file mode 100644 index adc0b66..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test8/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sprintf -Name = Positive Test for sprintf -TYPE = DEFAULT -EXE1 = test8 -Description -= Tests sprintf with decimal numbers diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf/test9/CMakeLists.txt deleted file mode 100644 index 2a91658..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test9/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test9.c -) - -add_executable(paltest_sprintf_test9 - ${SOURCES} -) - -add_dependencies(paltest_sprintf_test9 coreclrpal) - -target_link_libraries(paltest_sprintf_test9 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/sprintf/test9/test9.c deleted file mode 100644 index 98f5db6..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test9/test9.c +++ /dev/null @@ -1,55 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test9.c -** -** Purpose: Test #9 for the sprintf function. Tests the integer -** specifier (%i). -** -** -**==========================================================================*/ - - - -#include -#include "../sprintf.h" - -/* - * Depends on memcmp and strlen - */ - -int __cdecl main(int argc, char *argv[]) -{ - int neg = -42; - int pos = 42; - INT64 l = 42; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - - DoNumTest("foo %i", pos, "foo 42"); - DoNumTest("foo %li", 0xFFFF, "foo 65535"); - DoNumTest("foo %hi", 0xFFFF, "foo -1"); - DoNumTest("foo %Li", pos, "foo 42"); - DoI64Test("foo %I64i", l, "42", "foo 42"); - DoNumTest("foo %3i", pos, "foo 42"); - DoNumTest("foo %-3i", pos, "foo 42 "); - DoNumTest("foo %.1i", pos, "foo 42"); - DoNumTest("foo %.3i", pos, "foo 042"); - DoNumTest("foo %03i", pos, "foo 042"); - DoNumTest("foo %#i", pos, "foo 42"); - DoNumTest("foo %+i", pos, "foo +42"); - DoNumTest("foo % i", pos, "foo 42"); - DoNumTest("foo %+i", neg, "foo -42"); - DoNumTest("foo % i", neg, "foo -42"); - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/sprintf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf/test9/testinfo.dat deleted file mode 100644 index e569e78..0000000 --- a/src/pal/tests/palsuite/c_runtime/sprintf/test9/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sprintf -Name = Positive Test for sprintf -TYPE = DEFAULT -EXE1 = test9 -Description -= Tests sprintf with integer numbers diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf_s/CMakeLists.txt new file mode 100644 index 0000000..8fe1cb6 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) +add_subdirectory(test10) +add_subdirectory(test11) +add_subdirectory(test12) +add_subdirectory(test13) +add_subdirectory(test14) +add_subdirectory(test15) +add_subdirectory(test16) +add_subdirectory(test17) +add_subdirectory(test18) +add_subdirectory(test19) +add_subdirectory(test2) +add_subdirectory(test3) +add_subdirectory(test4) +add_subdirectory(test6) +add_subdirectory(test7) +add_subdirectory(test8) +add_subdirectory(test9) + diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/sprintf_s.h b/src/pal/tests/palsuite/c_runtime/sprintf_s/sprintf_s.h new file mode 100644 index 0000000..129b9db --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/sprintf_s.h @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: sprintf_s.h +** +** Purpose: Containts common testing functions for sprintf_s +** +** +**==========================================================================*/ + +#ifndef __SPRINTF_S_H__ +#define __SPRINTF_S_H__ + +void DoStrTest(const char *formatstr, char* param, const char *checkstr) +{ + char buf[256] = { 0 }; + + sprintf_s(buf, _countof(buf), formatstr, param); + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert string \"%s\" into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + param, formatstr, checkstr, buf); + } +} + +void DoWStrTest(const char *formatstr, WCHAR* param, const char *checkstr) +{ + char buf[256] = { 0 }; + + sprintf_s(buf, _countof(buf), formatstr, param); + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert wide string \"%s\" into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + convertC(param), formatstr, checkstr, buf); + } +} + +void DoPointerTest(const char *formatstr, void* param, char* paramstr, + const char *checkstr1) +{ + char buf[256] = { 0 }; + + sprintf_s(buf, _countof(buf), formatstr, param); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + paramstr, formatstr, checkstr1, buf); + } +} + +void DoCountTest(const char *formatstr, int param, const char *checkstr) +{ + char buf[512] = { 0 }; + int n = -1; + + sprintf_s(buf, _countof(buf), formatstr, &n); + + if (n != param) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + param, n); + } + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf); + } +} + +void DoShortCountTest(const char *formatstr, int param, const char *checkstr) +{ + char buf[256] = { 0 }; + short int n = -1; + + sprintf_s(buf, _countof(buf), formatstr, &n); + + if (n != param) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + param, n); + } + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: Expected \"%s\" got \"%s\".\n", checkstr, buf); + } +} + + +void DoCharTest(const char *formatstr, char param, const char *checkstr) +{ + char buf[256] = { 0 }; + + sprintf_s(buf, _countof(buf), formatstr, param); + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + param, param, formatstr, checkstr, buf); + } +} + +void DoWCharTest(const char *formatstr, WCHAR param, const char *checkstr) +{ + char buf[256] = { 0 }; + + sprintf_s(buf, _countof(buf), formatstr, param); + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert wide char \'%c\' (%d) into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + (char)param, param, formatstr, checkstr, buf); + } +} + +void DoNumTest(const char *formatstr, int value, const char *checkstr) +{ + char buf[256] = { 0 }; + + sprintf_s(buf, _countof(buf), formatstr, value); + if (memcmp(buf, checkstr, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: failed to insert %#x into \"%s\"\n" + "Expected \"%s\" got \"%s\".\n", + value, formatstr, checkstr, buf); + } +} + +void DoI64Test(const char *formatstr, INT64 value, char *valuestr, const char *checkstr1) +{ + char buf[256] = { 0 }; + + sprintf_s(buf, _countof(buf), formatstr, value); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\"\n" + "Expected \"%s\", got \"%s\".\n", + valuestr, formatstr, checkstr1, buf); + } +} + +void DoDoubleTest(const char *formatstr, double value, const char *checkstr1, + const char *checkstr2) +{ + char buf[256] = { 0 }; + + sprintf_s(buf, _countof(buf), formatstr, value); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\"\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + value, formatstr, checkstr1, checkstr2, buf); + } +} + +void DoArgumentPrecTest(const char *formatstr, int precision, void *param, + char *paramstr, const char *checkstr1, const char *checkstr2) +{ + char buf[256]; + + sprintf_s(buf, _countof(buf), formatstr, precision, param); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", paramstr, formatstr, + precision, checkstr1, checkstr2, buf); + } + +} + +void DoArgumentPrecDoubleTest(const char *formatstr, int precision, double param, + const char *checkstr1, const char *checkstr2) +{ + char buf[256]; + + sprintf_s(buf, _countof(buf), formatstr, precision, param); + if (memcmp(buf, checkstr1, strlen(checkstr1) + 1) != 0 && + memcmp(buf, checkstr2, strlen(checkstr2) + 1) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", param, formatstr, + precision, checkstr1, checkstr2, buf); + } + +} + +#endif + + diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/CMakeLists.txt new file mode 100644 index 0000000..ee0d90f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.cpp +) + +add_executable(paltest_sprintf_test1 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test1 coreclrpal) + +target_link_libraries(paltest_sprintf_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/test1.cpp b/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/test1.cpp new file mode 100644 index 0000000..a289c07 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/test1.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Test #1 for the sprintf_s function. A single, basic, test +** case with no formatting. +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + char checkstr[] = "hello world"; + char buf[256]; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + sprintf_s(buf, _countof(buf), "hello world"); + + if (memcmp(checkstr, buf, strlen(checkstr)+1) != 0) + { + Fail("ERROR: expected %s, got %s\n", checkstr, buf); + } + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/testinfo.dat new file mode 100644 index 0000000..255c534 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test1/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test1 +Description += General test to see if sprintf_s works correctly diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/CMakeLists.txt new file mode 100644 index 0000000..1efad19 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test10.cpp +) + +add_executable(paltest_sprintf_test10 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test10 coreclrpal) + +target_link_libraries(paltest_sprintf_test10 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/test10.cpp b/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/test10.cpp new file mode 100644 index 0000000..bbda15a --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/test10.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test10.c +** +** Purpose: Test #10 for the sprintf_s function. Tests the octal specifier +** (%o). +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %o", pos, "foo 52"); + DoNumTest("foo %lo", 0xFFFF, "foo 177777"); + DoNumTest("foo %ho", 0xFFFF, "foo 177777"); + DoNumTest("foo %Lo", pos, "foo 52"); + DoI64Test("foo %I64o", l, "42", "foo 52"); + DoNumTest("foo %3o", pos, "foo 52"); + DoNumTest("foo %-3o", pos, "foo 52 "); + DoNumTest("foo %.1o", pos, "foo 52"); + DoNumTest("foo %.3o", pos, "foo 052"); + DoNumTest("foo %03o", pos, "foo 052"); + DoNumTest("foo %#o", pos, "foo 052"); + DoNumTest("foo %+o", pos, "foo 52"); + DoNumTest("foo % o", pos, "foo 52"); + DoNumTest("foo %+o", neg, "foo 37777777726"); + DoNumTest("foo % o", neg, "foo 37777777726"); + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/testinfo.dat new file mode 100644 index 0000000..25ed554 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test10/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test10 +Description += Tests sprintf_s with octal numbers diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/CMakeLists.txt new file mode 100644 index 0000000..f2f4da6 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test11.cpp +) + +add_executable(paltest_sprintf_test11 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test11 coreclrpal) + +target_link_libraries(paltest_sprintf_test11 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/test11.cpp b/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/test11.cpp new file mode 100644 index 0000000..7f4fca9 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/test11.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test11.c +** +** Purpose: Test #11 for the sprintf_s function. Test the unsigned int +** specifier (%u). +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %u", pos, "foo 42"); + DoNumTest("foo %lu", 0xFFFF, "foo 65535"); + DoNumTest("foo %hu", 0xFFFF, "foo 65535"); + DoNumTest("foo %Lu", pos, "foo 42"); + DoI64Test("foo %I64u", l, "42", "foo 42"); + DoNumTest("foo %3u", pos, "foo 42"); + DoNumTest("foo %-3u", pos, "foo 42 "); + DoNumTest("foo %.1u", pos, "foo 42"); + DoNumTest("foo %.3u", pos, "foo 042"); + DoNumTest("foo %03u", pos, "foo 042"); + DoNumTest("foo %#u", pos, "foo 42"); + DoNumTest("foo %+u", pos, "foo 42"); + DoNumTest("foo % u", pos, "foo 42"); + DoNumTest("foo %+u", neg, "foo 4294967254"); + DoNumTest("foo % u", neg, "foo 4294967254"); + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/testinfo.dat new file mode 100644 index 0000000..3144f12 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test11/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test11 +Description += Tests sprintf_s with unsigned numbers diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/CMakeLists.txt new file mode 100644 index 0000000..361e91f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test12.cpp +) + +add_executable(paltest_sprintf_test12 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test12 coreclrpal) + +target_link_libraries(paltest_sprintf_test12 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/test12.cpp b/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/test12.cpp new file mode 100644 index 0000000..759a411 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/test12.cpp @@ -0,0 +1,56 @@ +// 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. + +/*============================================================================ +** +** Source: test12.c +** +** Purpose: Test #12 for the sprintf_s function. Tests the (lowercase) +** hexadecimal specifier (%x) +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234ab; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %x", pos, "foo 1234ab"); + DoNumTest("foo %lx", pos, "foo 1234ab"); + DoNumTest("foo %hx", pos, "foo 34ab"); + DoNumTest("foo %Lx", pos, "foo 1234ab"); + DoI64Test("foo %I64x", l, "0x1234567887654321", + "foo 1234567887654321"); + DoNumTest("foo %7x", pos, "foo 1234ab"); + DoNumTest("foo %-7x", pos, "foo 1234ab "); + DoNumTest("foo %.1x", pos, "foo 1234ab"); + DoNumTest("foo %.7x", pos, "foo 01234ab"); + DoNumTest("foo %07x", pos, "foo 01234ab"); + DoNumTest("foo %#x", pos, "foo 0x1234ab"); + DoNumTest("foo %+x", pos, "foo 1234ab"); + DoNumTest("foo % x", pos, "foo 1234ab"); + DoNumTest("foo %+x", neg, "foo ffffffd6"); + DoNumTest("foo % x", neg, "foo ffffffd6"); + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/testinfo.dat new file mode 100644 index 0000000..ed91cec --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test12/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test12 +Description += Tests sprintf_s with hex numbers (lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/CMakeLists.txt new file mode 100644 index 0000000..d08e13b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test13.cpp +) + +add_executable(paltest_sprintf_test13 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test13 coreclrpal) + +target_link_libraries(paltest_sprintf_test13 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/test13.cpp b/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/test13.cpp new file mode 100644 index 0000000..76250d0 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/test13.cpp @@ -0,0 +1,56 @@ +// 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. + +/*============================================================================ +** +** Source: test13.c +** +** Purpose: Test #13 for the sprintf_s function. Tests the (uppercase) +** hexadecimal specifier (%X) +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 0x1234AB; + INT64 l = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %X", pos, "foo 1234AB"); + DoNumTest("foo %lX", pos, "foo 1234AB"); + DoNumTest("foo %hX", pos, "foo 34AB"); + DoNumTest("foo %LX", pos, "foo 1234AB"); + DoI64Test("foo %I64X", l, "0x1234567887654321", + "foo 1234567887654321"); + DoNumTest("foo %7X", pos, "foo 1234AB"); + DoNumTest("foo %-7X", pos, "foo 1234AB "); + DoNumTest("foo %.1X", pos, "foo 1234AB"); + DoNumTest("foo %.7X", pos, "foo 01234AB"); + DoNumTest("foo %07X", pos, "foo 01234AB"); + DoNumTest("foo %#X", pos, "foo 0X1234AB"); + DoNumTest("foo %+X", pos, "foo 1234AB"); + DoNumTest("foo % X", pos, "foo 1234AB"); + DoNumTest("foo %+X", neg, "foo FFFFFFD6"); + DoNumTest("foo % X", neg, "foo FFFFFFD6"); + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/testinfo.dat new file mode 100644 index 0000000..fd5f530 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test13/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test13 +Description += Tests sprintf_s with hex numbers (uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/CMakeLists.txt new file mode 100644 index 0000000..60ac292 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test14.cpp +) + +add_executable(paltest_sprintf_test14 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test14 coreclrpal) + +target_link_libraries(paltest_sprintf_test14 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/test14.cpp b/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/test14.cpp new file mode 100644 index 0000000..668edda --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/test14.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test14.c +** +** Purpose: Test #14 for the sprintf_s function. Tests the lowercase +** exponential notation double specifier (%e) +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest("foo %e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %le", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %he", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %Le", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %I64e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %14e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %-14e", val, "foo 2.560000e+002 ", "foo 2.560000e+02 "); + DoDoubleTest("foo %.1e", val, "foo 2.6e+002", "foo 2.6e+02"); + DoDoubleTest("foo %.8e", val, "foo 2.56000000e+002", "foo 2.56000000e+02"); + DoDoubleTest("foo %014e", val, "foo 02.560000e+002", "foo 002.560000e+02"); + DoDoubleTest("foo %#e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %+e", val, "foo +2.560000e+002", "foo +2.560000e+02"); + DoDoubleTest("foo % e", val, "foo 2.560000e+002", "foo 2.560000e+02"); + DoDoubleTest("foo %+e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); + DoDoubleTest("foo % e", neg, "foo -2.560000e+002", "foo -2.560000e+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/testinfo.dat new file mode 100644 index 0000000..23cf423 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test14/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test14 +Description += Tests sprintf_s with exponential format doubles (lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/CMakeLists.txt new file mode 100644 index 0000000..57bba40 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test15.cpp +) + +add_executable(paltest_sprintf_test15 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test15 coreclrpal) + +target_link_libraries(paltest_sprintf_test15 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/test15.cpp b/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/test15.cpp new file mode 100644 index 0000000..61e0e36 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/test15.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test15.c +** +** Purpose: Test #15 for the sprintf_s function. Tests the uppercase +** exponential notation double specifier (%E) +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 256.0; + double neg = -256.0; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest("foo %E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %lE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %hE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %LE", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %I64E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %14E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %-14E", val, "foo 2.560000E+002 ", "foo 2.560000E+02 "); + DoDoubleTest("foo %.1E", val, "foo 2.6E+002", "foo 2.6E+02"); + DoDoubleTest("foo %.8E", val, "foo 2.56000000E+002", "foo 2.56000000E+02"); + DoDoubleTest("foo %014E", val, "foo 02.560000E+002", "foo 002.560000E+02"); + DoDoubleTest("foo %#E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %+E", val, "foo +2.560000E+002", "foo +2.560000E+02"); + DoDoubleTest("foo % E", val, "foo 2.560000E+002", "foo 2.560000E+02"); + DoDoubleTest("foo %+E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); + DoDoubleTest("foo % E", neg, "foo -2.560000E+002", "foo -2.560000E+02"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/testinfo.dat new file mode 100644 index 0000000..537e6d1 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test15/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test15 +Description += Tests sprintf_s with exponential format doubles (uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/CMakeLists.txt new file mode 100644 index 0000000..fc93e1a --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test16.cpp +) + +add_executable(paltest_sprintf_test16 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test16 coreclrpal) + +target_link_libraries(paltest_sprintf_test16 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/test16.cpp b/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/test16.cpp new file mode 100644 index 0000000..b237c98 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/test16.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test16.c +** +** Purpose: Test #16 for the sprintf_s function. Tests the decimal notation +** double specifier (%f) +** +** +**==========================================================================*/ + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest("foo %f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %lf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %hf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %Lf", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %I64f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %12f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %-12f", val, "foo 2560.001000 ", "foo 2560.001000 "); + DoDoubleTest("foo %.1f", val, "foo 2560.0", "foo 2560.0"); + DoDoubleTest("foo %.8f", val, "foo 2560.00100000", "foo 2560.00100000"); + DoDoubleTest("foo %012f", val, "foo 02560.001000", "foo 02560.001000"); + DoDoubleTest("foo %#f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %+f", val, "foo +2560.001000", "foo +2560.001000"); + DoDoubleTest("foo % f", val, "foo 2560.001000", "foo 2560.001000"); + DoDoubleTest("foo %+f", neg, "foo -2560.001000", "foo -2560.001000"); + DoDoubleTest("foo % f", neg, "foo -2560.001000", "foo -2560.001000"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/testinfo.dat new file mode 100644 index 0000000..4e98ecc --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test16/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test16 +Description += Tests sprintf_s with decimal point format doubles diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/CMakeLists.txt new file mode 100644 index 0000000..dc5ff2b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test17.cpp +) + +add_executable(paltest_sprintf_test17 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test17 coreclrpal) + +target_link_libraries(paltest_sprintf_test17 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/test17.cpp b/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/test17.cpp new file mode 100644 index 0000000..220555e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/test17.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test17.c +** +** Purpose: Test #17 for the sprintf_s function. Tests the lowercase +** shorthand notation double specifier (%g) +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest("foo %g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %lg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %hg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %Lg", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %I64g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %5g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %-5g", val, "foo 2560 ", "foo 2560 "); + DoDoubleTest("foo %.1g", val, "foo 3e+003", "foo 3e+03"); + DoDoubleTest("foo %.2g", val, "foo 2.6e+003", "foo 2.6e+03"); + DoDoubleTest("foo %.12g", val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest("foo %06g", val, "foo 002560", "foo 002560"); + DoDoubleTest("foo %#g", val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest("foo %+g", val, "foo +2560", "foo +2560"); + DoDoubleTest("foo % g", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %+g", neg, "foo -2560", "foo -2560"); + DoDoubleTest("foo % g", neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/testinfo.dat new file mode 100644 index 0000000..5e41e20 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test17/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test17 +Description += Tests sprintf_s with compact format doubles (lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/CMakeLists.txt new file mode 100644 index 0000000..f6e1b09 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test18.cpp +) + +add_executable(paltest_sprintf_test18 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test18 coreclrpal) + +target_link_libraries(paltest_sprintf_test18 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/test18.cpp b/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/test18.cpp new file mode 100644 index 0000000..2135a6f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/test18.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test18.c +** +** Purpose: Test #18 for the sprintf_s function. Tests the uppercase +** shorthand notation double specifier (%G) +** +** +**==========================================================================*/ + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + double val = 2560.001; + double neg = -2560.001; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoDoubleTest("foo %G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %lG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %hG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %LG", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %I64G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %5G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %-5G", val, "foo 2560 ", "foo 2560 "); + DoDoubleTest("foo %.1G", val, "foo 3E+003", "foo 3E+03"); + DoDoubleTest("foo %.2G", val, "foo 2.6E+003", "foo 2.6E+03"); + DoDoubleTest("foo %.12G", val, "foo 2560.001", "foo 2560.001"); + DoDoubleTest("foo %06G", val, "foo 002560", "foo 002560"); + DoDoubleTest("foo %#G", val, "foo 2560.00", "foo 2560.00"); + DoDoubleTest("foo %+G", val, "foo +2560", "foo +2560"); + DoDoubleTest("foo % G", val, "foo 2560", "foo 2560"); + DoDoubleTest("foo %+G", neg, "foo -2560", "foo -2560"); + DoDoubleTest("foo % G", neg, "foo -2560", "foo -2560"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/testinfo.dat new file mode 100644 index 0000000..06ae3a6 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test18/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test18 +Description += Tests sprintf_s with compact format doubles (uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/CMakeLists.txt new file mode 100644 index 0000000..757288b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test19.cpp +) + +add_executable(paltest_sprintf_test19 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test19 coreclrpal) + +target_link_libraries(paltest_sprintf_test19 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/test19.cpp b/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/test19.cpp new file mode 100644 index 0000000..483c716 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/test19.cpp @@ -0,0 +1,71 @@ +// 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. + +/*============================================================================ +** +** Source: test19.c +** +** Purpose: Test #19 for the sprintf_s function. Tests the variable length +** precision argument. +** +** +**==========================================================================*/ + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + + +int __cdecl main(int argc, char *argv[]) +{ + int n = -1; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + DoArgumentPrecTest("%.*s", 2, (void*)"bar", "bar", "ba", "ba"); + DoArgumentPrecTest("%.*S", 2, (void*)convert("bar"), "bar", "ba", "ba"); + + DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); + DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); + DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); + DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); + + + DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); + DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); + DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); + DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); + DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); + DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); + DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); + DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); + DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); + DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/testinfo.dat new file mode 100644 index 0000000..7064c01 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test19/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test19 +Description += Tests sprintf_s with argument specified precision diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/CMakeLists.txt new file mode 100644 index 0000000..d569263 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test2.cpp +) + +add_executable(paltest_sprintf_test2 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test2 coreclrpal) + +target_link_libraries(paltest_sprintf_test2 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/test2.cpp b/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/test2.cpp new file mode 100644 index 0000000..990f4f0 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/test2.cpp @@ -0,0 +1,47 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose: Test #2 for the sprintf_s function. Tests the string specifier +** (%s). +** +** +**==========================================================================*/ + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoStrTest("foo %s", "bar", "foo bar"); + DoStrTest("foo %hs", "bar", "foo bar"); + DoWStrTest("foo %ls", convert("bar"), "foo bar"); + DoWStrTest("foo %ws", convert("bar"), "foo bar"); + DoStrTest("foo %Ls", "bar", "foo bar"); + DoStrTest("foo %I64s", "bar", "foo bar"); + DoStrTest("foo %5s", "bar", "foo bar"); + DoStrTest("foo %.2s", "bar", "foo ba"); + DoStrTest("foo %5.2s", "bar", "foo ba"); + DoStrTest("foo %-5s", "bar", "foo bar "); + DoStrTest("foo %05s", "bar", "foo 00bar"); + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/testinfo.dat new file mode 100644 index 0000000..cce2dc6 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test2/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test2 +Description += Tests sprintf_s with strings diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/CMakeLists.txt new file mode 100644 index 0000000..518c3f8 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test3.cpp +) + +add_executable(paltest_sprintf_test3 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test3 coreclrpal) + +target_link_libraries(paltest_sprintf_test3 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/test3.cpp b/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/test3.cpp new file mode 100644 index 0000000..c0dc8e1 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/test3.cpp @@ -0,0 +1,47 @@ +// 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. + +/*============================================================================ +** +** Source: test3.c +** +** Purpose: Test #3 for the sprintf_s function. Tests the wide string +** specifier (%S). +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + DoWStrTest("foo %S", convert("bar"), "foo bar"); + DoStrTest("foo %hS", "bar", "foo bar"); + DoWStrTest("foo %lS", convert("bar"), "foo bar"); + DoWStrTest("foo %wS", convert("bar"), "foo bar"); + DoWStrTest("foo %LS", convert("bar"), "foo bar"); + DoWStrTest("foo %I64S", convert("bar"), "foo bar"); + DoWStrTest("foo %5S", convert("bar"), "foo bar"); + DoWStrTest("foo %.2S", convert("bar"), "foo ba"); + DoWStrTest("foo %5.2S", convert("bar"), "foo ba"); + DoWStrTest("foo %-5S", convert("bar"), "foo bar "); + DoWStrTest("foo %05S", convert("bar"), "foo 00bar"); + + PAL_Terminate(); + return PASS; +} + + diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/testinfo.dat new file mode 100644 index 0000000..cc8de0e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test3/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test3 +Description += Tests sprintf_s with wide strings diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/CMakeLists.txt new file mode 100644 index 0000000..260def4 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test4.cpp +) + +add_executable(paltest_sprintf_test4 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test4 coreclrpal) + +target_link_libraries(paltest_sprintf_test4 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/test4.cpp b/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/test4.cpp new file mode 100644 index 0000000..46115ad --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/test4.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test4.c +** +** Purpose: Test #4 for the sprintf_s function. Tests the pointer +** specifier (%p). +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + void *ptr = (void*) 0x123456; + INT64 lptr = I64(0x1234567887654321); + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + +/* +** Run only on 64 bit platforms +*/ +#if defined(BIT64) && defined(PLATFORM_UNIX) + Trace("Testing for 64 Bit Platforms \n"); + DoPointerTest("%p", NULL, "NULL", "0000000000000000"); + DoPointerTest("%p", ptr, "pointer to 0x123456", "0000000000123456"); + DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); + DoPointerTest("%17p", ptr, "pointer to 0x123456", " 0000000000123456"); + DoPointerTest("%-17p", ptr, "pointer to 0x123456", "0000000000123456 "); + DoPointerTest("%+p", ptr, "pointer to 0x123456", "0000000000123456"); + DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X0000000000123456"); + DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); + DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); + DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321", + "1234567887654321"); +#else + Trace("Testing for Non 64 Bit Platforms \n"); + DoPointerTest("%p", NULL, "NULL", "00000000"); + DoPointerTest("%p", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%9p", ptr, "pointer to 0x123456", " 00123456"); + DoPointerTest("%09p", ptr, "pointer to 0x123456", " 00123456"); + DoPointerTest("%-9p", ptr, "pointer to 0x123456", "00123456 "); + DoPointerTest("%+p", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%#p", ptr, "pointer to 0x123456", "0X00123456"); + DoPointerTest("%lp", ptr, "pointer to 0x123456", "00123456"); + DoPointerTest("%hp", ptr, "pointer to 0x123456", "00003456"); + DoPointerTest("%Lp", ptr, "pointer to 0x123456", "00123456"); + DoI64Test("%I64p", lptr, "pointer to 0x1234567887654321", + "1234567887654321"); +#endif + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/testinfo.dat new file mode 100644 index 0000000..f53f784 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test4/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test4 +Description += Tests sprintf_s with pointers diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/CMakeLists.txt new file mode 100644 index 0000000..fce1f20 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test6.cpp +) + +add_executable(paltest_sprintf_test6 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test6 coreclrpal) + +target_link_libraries(paltest_sprintf_test6 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/test6.cpp b/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/test6.cpp new file mode 100644 index 0000000..c5fc804 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/test6.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test6.c +** +** Purpose: Test #6 for the sprintf_s function. Tests the char specifier (%c). +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wc = (WCHAR) 'c'; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoCharTest("foo %c", 'b', "foo b"); + DoCharTest("foo %hc", 'b', "foo b"); + DoWCharTest("foo %lc", wc, "foo c"); + DoCharTest("foo %Lc", 'b', "foo b"); + DoCharTest("foo %I64c", 'b', "foo b"); + DoCharTest("foo %5c", 'b', "foo b"); + DoCharTest("foo %.0c", 'b', "foo b"); + DoCharTest("foo %-5c", 'b', "foo b "); + DoCharTest("foo %05c", 'b', "foo 0000b"); + DoCharTest("foo % c", 'b', "foo b"); + DoCharTest("foo %#c", 'b', "foo b"); + + PAL_Terminate(); + return PASS; +} + + + diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/testinfo.dat new file mode 100644 index 0000000..c5b93fc --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test6/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test6 +Description += Tests sprintf_s with characters diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/CMakeLists.txt new file mode 100644 index 0000000..72a831e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test7.cpp +) + +add_executable(paltest_sprintf_test7 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test7 coreclrpal) + +target_link_libraries(paltest_sprintf_test7 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/test7.cpp b/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/test7.cpp new file mode 100644 index 0000000..fd46ae9 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/test7.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test7.c +** +** Purpose: Test #7 for the sprintf_s function. Tests the wide char +** specifier (%C). +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR wb = (WCHAR) 'b'; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoWCharTest("foo %C", wb, "foo b"); + DoWCharTest("foo %hC", wb, "foo b"); + DoCharTest("foo %lC", 'c', "foo c"); + DoWCharTest("foo %LC", wb, "foo b"); + DoWCharTest("foo %I64C", wb, "foo b"); + DoWCharTest("foo %5C", wb, "foo b"); + DoWCharTest("foo %.0C", wb, "foo b"); + DoWCharTest("foo %-5C", wb, "foo b "); + DoWCharTest("foo %05C", wb, "foo 0000b"); + DoWCharTest("foo % C", wb, "foo b"); + DoWCharTest("foo %#C", wb, "foo b"); + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/testinfo.dat new file mode 100644 index 0000000..647c9d8 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test7/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test7 +Description += Tests sprintf_s with wide characters diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/CMakeLists.txt new file mode 100644 index 0000000..c9522c1 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test8.cpp +) + +add_executable(paltest_sprintf_test8 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test8 coreclrpal) + +target_link_libraries(paltest_sprintf_test8 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/test8.cpp b/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/test8.cpp new file mode 100644 index 0000000..db02627 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/test8.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test8.c +** +** Purpose: Test #8 for the sprintf_s function. Tests the decimal +** specifier (%d). +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %d", pos, "foo 42"); + DoNumTest("foo %ld", 0xFFFF, "foo 65535"); + DoNumTest("foo %hd", 0xFFFF, "foo -1"); + DoNumTest("foo %Ld", pos, "foo 42"); + DoI64Test("foo %I64d", l, "42", "foo 42"); + DoNumTest("foo %3d", pos, "foo 42"); + DoNumTest("foo %-3d", pos, "foo 42 "); + DoNumTest("foo %.1d", pos, "foo 42"); + DoNumTest("foo %.3d", pos, "foo 042"); + DoNumTest("foo %03d", pos, "foo 042"); + DoNumTest("foo %#d", pos, "foo 42"); + DoNumTest("foo %+d", pos, "foo +42"); + DoNumTest("foo % d", pos, "foo 42"); + DoNumTest("foo %+d", neg, "foo -42"); + DoNumTest("foo % d", neg, "foo -42"); + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/testinfo.dat new file mode 100644 index 0000000..524834e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test8/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test8 +Description += Tests sprintf_s with decimal numbers diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/CMakeLists.txt new file mode 100644 index 0000000..e76fed4 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test9.cpp +) + +add_executable(paltest_sprintf_test9 + ${SOURCES} +) + +add_dependencies(paltest_sprintf_test9 coreclrpal) + +target_link_libraries(paltest_sprintf_test9 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/test9.cpp b/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/test9.cpp new file mode 100644 index 0000000..2e1c78c --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/test9.cpp @@ -0,0 +1,55 @@ +// 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. + +/*============================================================================ +** +** Source: test9.c +** +** Purpose: Test #9 for the sprintf_s function. Tests the integer +** specifier (%i). +** +** +**==========================================================================*/ + + + +#include +#include "../sprintf_s.h" + +/* + * Depends on memcmp and strlen + */ + +int __cdecl main(int argc, char *argv[]) +{ + int neg = -42; + int pos = 42; + INT64 l = 42; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + + DoNumTest("foo %i", pos, "foo 42"); + DoNumTest("foo %li", 0xFFFF, "foo 65535"); + DoNumTest("foo %hi", 0xFFFF, "foo -1"); + DoNumTest("foo %Li", pos, "foo 42"); + DoI64Test("foo %I64i", l, "42", "foo 42"); + DoNumTest("foo %3i", pos, "foo 42"); + DoNumTest("foo %-3i", pos, "foo 42 "); + DoNumTest("foo %.1i", pos, "foo 42"); + DoNumTest("foo %.3i", pos, "foo 042"); + DoNumTest("foo %03i", pos, "foo 042"); + DoNumTest("foo %#i", pos, "foo 42"); + DoNumTest("foo %+i", pos, "foo +42"); + DoNumTest("foo % i", pos, "foo 42"); + DoNumTest("foo %+i", neg, "foo -42"); + DoNumTest("foo % i", neg, "foo -42"); + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/testinfo.dat new file mode 100644 index 0000000..7c51443 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sprintf_s/test9/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sprintf_s +Name = Positive Test for sprintf_s +TYPE = DEFAULT +EXE1 = test9 +Description += Tests sprintf_s with integer numbers diff --git a/src/pal/tests/palsuite/c_runtime/sqrt/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sqrt/test1/CMakeLists.txt index 4347c44..d4aefe6 100644 --- a/src/pal/tests/palsuite/c_runtime/sqrt/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/sqrt/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_sqrt_test1 diff --git a/src/pal/tests/palsuite/c_runtime/sqrt/test1/test1.c b/src/pal/tests/palsuite/c_runtime/sqrt/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/sqrt/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/sqrt/test1/test1.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcpynW/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sqrtf/CMakeLists.txt similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/lstrcpynW/CMakeLists.txt rename to src/pal/tests/palsuite/c_runtime/sqrtf/CMakeLists.txt diff --git a/src/pal/tests/palsuite/c_runtime/sqrtf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sqrtf/test1/CMakeLists.txt new file mode 100644 index 0000000..96b6ffa --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sqrtf/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_sqrtf_test1 + ${SOURCES} +) + +add_dependencies(paltest_sqrtf_test1 coreclrpal) + +target_link_libraries(paltest_sqrtf_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sqrtf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/sqrtf/test1/test1.c new file mode 100644 index 0000000..cb1ac9e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sqrtf/test1/test1.c @@ -0,0 +1,122 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c +** +** Purpose: Call the sqrtf function on a positive value, a positive value +** with a decimal and on the maxium possible float value. +** +** +**===================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = sqrtf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("sqrtf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = sqrtf(value); + + if (!_isnanf(result)) + { + Fail("sqrtf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0.318309886f, 0.564189584f, PAL_EPSILON }, // value: 1 / pi + { 0.434294482f, 0.659010229f, PAL_EPSILON }, // value: log10f(e) + { 0.636619772f, 0.797884561f, PAL_EPSILON }, // value: 2 / pi + { 0.693147181f, 0.832554611f, PAL_EPSILON }, // value: ln(2) + { 0.707106781f, 0.840896415f, PAL_EPSILON }, // value: 1 / sqrtf(2) + { 0.785398163f, 0.886226925f, PAL_EPSILON }, // value: pi / 4 + { 1, 1, PAL_EPSILON * 10 }, + { 1.12837917f, 1.06225193f, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi) + { 1.41421356f, 1.18920712f, PAL_EPSILON * 10 }, // value: sqrtf(2) + { 1.44269504f, 1.20112241f, PAL_EPSILON * 10 }, // value: logf2(e) + { 1.57079633f, 1.25331414f, PAL_EPSILON * 10 }, // value: pi / 2 + { 2.30258509f, 1.51742713f, PAL_EPSILON * 10 }, // value: ln(10) + { 2.71828183f, 1.64872127f, PAL_EPSILON * 10 }, // value: e + { 3.14159265f, 1.77245385F, PAL_EPSILON * 10 }, // value: pi + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + validate(-0.0f, -0.0f, PAL_EPSILON); + validate( 0.0f, 0.0f, PAL_EPSILON); + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate(tests[i].value, tests[i].expected, tests[i].variance); + validate_isnan(-tests[i].value); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sqrtf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sqrtf/test1/testinfo.dat new file mode 100644 index 0000000..00d8ab2 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sqrtf/test1/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sqrtf +Name = Call sqrtf on positive values and zero. +TYPE = DEFAULT +EXE1 = test1 +Description += Call the sqrtf function on a positive value, a positive value += with a decimal and on the maxium possible float value. + + + + diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/sscanf.h b/src/pal/tests/palsuite/c_runtime/sscanf/sscanf.h deleted file mode 100644 index 675a67a..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/sscanf.h +++ /dev/null @@ -1,246 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: sscanf.h -** -** Purpose: Contains common testing functions for sscanf.h -** -** -**==========================================================================*/ - -#ifndef __SSCANF_H__ -#define __SSCANF_H__ - -void DoVoidTest(char *inputstr, char *formatstr) -{ - char buf[256] = { 0 }; - int i; - int ret; - - ret = sscanf(inputstr, formatstr, buf); - if (ret != 0) - { - Fail("ERROR: Expected sscanf to return 0, got %d.\n" - "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); - } - - for (i=0; i<256; i++) - { - if (buf[i] != 0) - { - Fail("ERROR: Parameter unexpectedly modified scanning \"%s\" " - "using \"%s\".\n", inputstr, formatstr); - } - } - -} - -void DoStrTest(char *inputstr, char *formatstr, char *checkstr) -{ - char buf[256] = { 0 }; - int ret; - - ret = sscanf(inputstr, formatstr, buf); - if (ret != 1) - { - Fail("ERROR: Expected sscanf to return 1, got %d.\n" - "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); - } - - if (memcmp(checkstr, buf, strlen(checkstr) + 1) != 0) - { - Fail("ERROR: scanned string incorrectly from \"%s\" using \"%s\".\n" - "Expected \"%s\", got \"%s\".\n", inputstr, formatstr, checkstr, - buf); - } - -} - -void DoWStrTest(char *inputstr, char *formatstr, WCHAR *checkstr) -{ - WCHAR buf[256] = { 0 }; - int ret; - - ret = sscanf(inputstr, formatstr, buf); - if (ret != 1) - { - Fail("ERROR: Expected sscanf to return 1, got %d.\n" - "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); - } - - if (memcmp(checkstr, buf, wcslen(checkstr)*2 + 2) != 0) - { - Fail("ERROR: scanned wide string incorrectly from \"%s\" using \"%s\".\n" - "Expected \"%s\", got \"%s\".\n", inputstr, formatstr, - convertC(checkstr), convertC(buf)); - } - -} - -void DoNumTest(char *inputstr, char *formatstr, int checknum) -{ - int num; - int ret; - - ret = sscanf(inputstr, formatstr, &num); - if (ret != 1) - { - Fail("ERROR: Expected sscanf to return 1, got %d.\n" - "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); - } - - if (checknum != num) - { - Fail("ERROR: scanned number incorrectly from \"%s\" using \"%s\".\n" - "Expected %d, got %d.\n", inputstr, formatstr, checknum, num); - } -} - -void DoShortNumTest(char *inputstr, char *formatstr, short checknum) -{ - short num; - int ret; - - ret = sscanf(inputstr, formatstr, &num); - if (ret != 1) - { - Fail("ERROR: Expected sscanf to return 1, got %d.\n" - "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); - } - - if (checknum != num) - { - Fail("ERROR: scanned number incorrectly from \"%s\" using \"%s\".\n" - "Expected %hd, got %hd.\n", inputstr, formatstr, checknum, num); - } -} - -void DoI64NumTest(char *inputstr, char *formatstr, INT64 checknum) -{ - char buf[256]; - char check[256]; - INT64 num; - int ret; - - ret = sscanf(inputstr, formatstr, &num); - if (ret != 1) - { - Fail("ERROR: Expected sscanf to return 1, got %d.\n" - "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); - } - - if (checknum != num) - { - sprintf(buf, "%I64d", num); - sprintf(check, "%I64d", checknum); - Fail("ERROR: scanned I64 number incorrectly from \"%s\" using \"%s\".\n" - "Expected %s, got %s.\n", inputstr, formatstr, check, buf); - } -} - -void DoCharTest(char *inputstr, char *formatstr, char* checkchars, int numchars) -{ - char buf[256]; - int ret; - int i; - - for (i=0; i<256; i++) - buf[i] = (char)-1; - - ret = sscanf(inputstr, formatstr, buf); - if (ret != 1) - { - Fail("ERROR: Expected sscanf to return 1, got %d.\n" - "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); - } - - if (memcmp(buf, checkchars, numchars) != 0) - { - buf[numchars] = 0; - - Fail("ERROR: scanned character(s) incorrectly from \"%s\" using \"%s\".\n" - "Expected %s, got %s.\n", inputstr, formatstr, checkchars, - buf); - } - - if (buf[numchars] != (char)-1) - { - Fail("ERROR: overflow occurred in scanning character(s) from \"%s\" " - "using \"%s\".\nExpected %d character(s)\n", inputstr, formatstr, - numchars); - } -} - -void DoWCharTest(char *inputstr, char *formatstr, WCHAR* checkchars, int numchars) -{ - WCHAR buf[256]; - int ret; - int i; - - for (i=0; i<256; i++) - buf[i] = (WCHAR)-1; - - ret = sscanf(inputstr, formatstr, buf); - if (ret != 1) - { - Fail("ERROR: Expected sscanf to return 1, got %d.\n" - "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); - } - - if (memcmp(buf, checkchars, numchars) != 0) - { - buf[numchars] = 0; - - Fail("ERROR: scanned wide character(s) incorrectly from \"%s\" using \"%s\".\n" - "Expected %s, got %s.\n", inputstr, formatstr, convertC(checkchars), - convertC(buf)); - } - - if (buf[numchars] != (WCHAR)-1) - { - Fail("ERROR: overflow occurred in scanning wide character(s) from \"%s\" " - "using \"%s\".\nExpected %d character(s)\n", inputstr, formatstr, - numchars); - } -} - - -void DoFloatTest(char *inputstr, char *formatstr, float checkval) -{ - char buf[256] = { 0 }; - float val; - int ret; - int i; - - for (i=0; i<256; i++) - buf[i] = (char)-1; - - ret = sscanf(inputstr, formatstr, buf); - val = *(float*)buf; - - if (ret != 1) - { - Fail("ERROR: Expected sscanf to return 1, got %d.\n" - "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); - } - - if (val != checkval) - { - Fail("ERROR: scanned float incorrectly from \"%s\" using \"%s\".\n" - "Expected \"%f\", got \"%f\".\n", inputstr, formatstr, checkval, - val); - } - - if (buf[4] != (char)-1) - { - Fail("ERROR: overflow occurred in scanning float from \"%s\" " - "using \"%s\".\n", inputstr, formatstr); - - } -} - - -#endif diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test1/CMakeLists.txt deleted file mode 100644 index dce6d1d..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test1/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test1.c -) - -add_executable(paltest_sscanf_test1 - ${SOURCES} -) - -add_dependencies(paltest_sscanf_test1 coreclrpal) - -target_link_libraries(paltest_sscanf_test1 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/sscanf/test1/test1.c deleted file mode 100644 index c6f66a1..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test1/test1.c +++ /dev/null @@ -1,53 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: General test of sscanf -** -** -**==========================================================================*/ - - - -#include -#include "../sscanf.h" - - -int __cdecl main(int argc, char *argv[]) -{ - int num; - int ret; - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - DoVoidTest("foo bar", "foo "); - DoVoidTest("foo bar", "baz"); - DoVoidTest("foo bar", "foo %*s"); - - DoStrTest("foo % bar", "foo %% %s", "bar"); - DoStrTest("foo bar baz", "foo %bar %s", "baz"); - - DoVoidTest("foo bar baz", "foo % bar %s"); - DoVoidTest("foo baz bar", "foo% baz %s"); - - ret = sscanf("foo bar baz", "foo bar %n", &num); - if (ret != 0 || num != 8) - { - Fail("ERROR: Got incorrect values in scanning \"%s\" using \"%s\".\n" - "Expected to get a value of %d with return value of %d, " - "got %d with return %d\n", "foo bar baz", "foo bar %n", 8, 0, - num, ret); - - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test1/testinfo.dat deleted file mode 100644 index ef33ba9..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test1/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sscanf -Name = Positive Test for sscanf -TYPE = DEFAULT -EXE1 = test1 -Description -= General test of sscanf diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test10/CMakeLists.txt deleted file mode 100644 index c27e4ce..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test10/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test10.c -) - -add_executable(paltest_sscanf_test10 - ${SOURCES} -) - -add_dependencies(paltest_sscanf_test10 coreclrpal) - -target_link_libraries(paltest_sscanf_test10 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/sscanf/test10/test10.c deleted file mode 100644 index aac5be4..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test10/test10.c +++ /dev/null @@ -1,37 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test10.c -** -** Purpose: Tests sscanf with wide charactersn -** -** -**==========================================================================*/ - - - -#include -#include "../sscanf.h" - -int __cdecl main(int argc, char *argv[]) -{ - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - DoWCharTest("1234d", "%C", convert("1"), 1); - DoWCharTest("1234d", "%C", convert("1"), 1); - DoWCharTest("abc", "%2C", convert("ab"), 2); - DoWCharTest(" ab", "%C", convert(" "), 1); - DoCharTest("ab", "%hC", "a", 1); - DoWCharTest("ab", "%lC", convert("a"), 1); - DoWCharTest("ab", "%LC", convert("a"), 1); - DoWCharTest("ab", "%I64C", convert("a"), 1); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test10/testinfo.dat deleted file mode 100644 index 7e854ed..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test10/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sscanf -Name = Positive Test for sscanf -TYPE = DEFAULT -EXE1 = test10 -Description -= Tests sscanf with wide characters diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test11/CMakeLists.txt deleted file mode 100644 index 7570e99..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test11/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test11.c -) - -add_executable(paltest_sscanf_test11 - ${SOURCES} -) - -add_dependencies(paltest_sscanf_test11 coreclrpal) - -target_link_libraries(paltest_sscanf_test11 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/sscanf/test11/test11.c deleted file mode 100644 index 0e3db6c..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test11/test11.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test11.c -** -** Purpose: Tests sscanf with strings -** -** -**==========================================================================*/ - - - -#include -#include "../sscanf.h" - -int __cdecl main(int argc, char *argv[]) -{ - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - DoStrTest("foo bar", "foo %s", "bar"); - DoStrTest("foo bar", "foo %2s", "ba"); - DoStrTest("foo bar", "foo %hs", "bar"); - DoWStrTest("foo bar", "foo %ls", convert("bar")); - DoStrTest("foo bar", "foo %Ls", "bar"); - DoStrTest("foo bar", "foo %I64s", "bar"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test11/testinfo.dat deleted file mode 100644 index 60f5cc4..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test11/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sscanf -Name = Positive Test for sscanf -TYPE = DEFAULT -EXE1 = test11 -Description -= Tests sscanf with strings diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test12/CMakeLists.txt deleted file mode 100644 index b6509e4..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test12/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test12.c -) - -add_executable(paltest_sscanf_test12 - ${SOURCES} -) - -add_dependencies(paltest_sscanf_test12 coreclrpal) - -target_link_libraries(paltest_sscanf_test12 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/sscanf/test12/test12.c deleted file mode 100644 index f800e45..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test12/test12.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test12.c -** -** Purpose: Tests sscanf with wide strings -** -** -**==========================================================================*/ - - - -#include -#include "../sscanf.h" - -int __cdecl main(int argc, char *argv[]) -{ - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - DoWStrTest("foo bar", "foo %S", convert("bar")); - DoWStrTest("foo bar", "foo %2S", convert("ba")); - DoStrTest("foo bar", "foo %hS", "bar"); - DoWStrTest("foo bar", "foo %lS", convert("bar")); - DoWStrTest("foo bar", "foo %LS", convert("bar")); - DoWStrTest("foo bar", "foo %I64S", convert("bar")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test12/testinfo.dat deleted file mode 100644 index 3c453bf..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test12/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sscanf -Name = Positive Test for sscanf -TYPE = DEFAULT -EXE1 = test12 -Description -= Tests sscanf with wide strings diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test13/CMakeLists.txt deleted file mode 100644 index 6fb4094..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test13/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test13.c -) - -add_executable(paltest_sscanf_test13 - ${SOURCES} -) - -add_dependencies(paltest_sscanf_test13 coreclrpal) - -target_link_libraries(paltest_sscanf_test13 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/sscanf/test13/test13.c deleted file mode 100644 index 314604e..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test13/test13.c +++ /dev/null @@ -1,37 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test13.c -** -** Purpose: Tests sscanf with floats (decimal notation) -** -** -**==========================================================================*/ - - - -#include -#include "../sscanf.h" - -int __cdecl main(int argc, char *argv[]) -{ - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - DoFloatTest("123.0", "%f", 123.0f); - DoFloatTest("123.0", "%2f", 12.0f); - DoFloatTest("10E1", "%f", 100.0f); - DoFloatTest("-12.01e-2", "%f", -0.1201f); - DoFloatTest("+12.01e-2", "%f", 0.1201f); - DoFloatTest("-12.01e+2", "%f", -1201.0f); - DoFloatTest("+12.01e+2", "%f", 1201.0f); - DoFloatTest("1234567890.0123456789f", "%f", 1234567936); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test13/testinfo.dat deleted file mode 100644 index 1c4c2fc..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test13/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sscanf -Name = Positive Test for sscanf -TYPE = DEFAULT -EXE1 = test13 -Description -= Tests sscanf with floats (decimal notation) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test14/CMakeLists.txt deleted file mode 100644 index 373a75f..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test14/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test14.c -) - -add_executable(paltest_sscanf_test14 - ${SOURCES} -) - -add_dependencies(paltest_sscanf_test14 coreclrpal) - -target_link_libraries(paltest_sscanf_test14 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/sscanf/test14/test14.c deleted file mode 100644 index d1291a3..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test14/test14.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test14.c -** -** Purpose: Tests sscanf with floats (exponential notation, lowercase) -** -** -**==========================================================================*/ - - - -#include -#include "../sscanf.h" - -int __cdecl main(int argc, char *argv[]) -{ - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - DoFloatTest("123.0", "%e", 123.0f); - DoFloatTest("123.0", "%2e", 12.0f); - DoFloatTest("10E1", "%e", 100.0f); - DoFloatTest("-12.01e-2", "%e", -0.1201f); - DoFloatTest("+12.01e-2", "%e", 0.1201f); - DoFloatTest("-12.01e+2", "%e", -1201.0f); - DoFloatTest("+12.01e+2", "%e", 1201.0f); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test14/testinfo.dat deleted file mode 100644 index 97db6e4..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test14/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sscanf -Name = Positive Test for sscanf -TYPE = DEFAULT -EXE1 = test14 -Description -= Tests sscanf with floats (exponential notation, lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test15/CMakeLists.txt deleted file mode 100644 index d500901..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test15/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test15.c -) - -add_executable(paltest_sscanf_test15 - ${SOURCES} -) - -add_dependencies(paltest_sscanf_test15 coreclrpal) - -target_link_libraries(paltest_sscanf_test15 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/sscanf/test15/test15.c deleted file mode 100644 index fa51467..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test15/test15.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test15.c -** -** Purpose: Tests sscanf with floats (exponential notation, uppercase -** -** -**==========================================================================*/ - - - -#include -#include "../sscanf.h" - -int __cdecl main(int argc, char *argv[]) -{ - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - DoFloatTest("123.0", "%E", 123.0f); - DoFloatTest("123.0", "%2E", 12.0f); - DoFloatTest("10E1", "%E", 100.0f); - DoFloatTest("-12.01e-2", "%E", -0.1201f); - DoFloatTest("+12.01e-2", "%E", 0.1201f); - DoFloatTest("-12.01e+2", "%E", -1201.0f); - DoFloatTest("+12.01e+2", "%E", 1201.0f); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test15/testinfo.dat deleted file mode 100644 index 30c2cf4..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test15/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sscanf -Name = Positive Test for sscanf -TYPE = DEFAULT -EXE1 = test15 -Description -= Tests sscanf with floats (exponential notation, uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test16/CMakeLists.txt deleted file mode 100644 index c5e18ec..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test16/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test16.c -) - -add_executable(paltest_sscanf_test16 - ${SOURCES} -) - -add_dependencies(paltest_sscanf_test16 coreclrpal) - -target_link_libraries(paltest_sscanf_test16 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/sscanf/test16/test16.c deleted file mode 100644 index 787b72e..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test16/test16.c +++ /dev/null @@ -1,37 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test16.c -** -** Purpose:Tests sscanf with floats (compact notation, lowercase) -** -** -**==========================================================================*/ - - - -#include -#include "../sscanf.h" - -int __cdecl main(int argc, char *argv[]) -{ - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - DoFloatTest("123.0", "%g", 123.0f); - DoFloatTest("123.0", "%2g", 12.0f); - DoFloatTest("10E1", "%g", 100.0f); - DoFloatTest("-12.01e-2", "%g", -0.1201f); - DoFloatTest("+12.01e-2", "%g", 0.1201f); - DoFloatTest("-12.01e+2", "%g", -1201.0f); - DoFloatTest("+12.01e+2", "%g", 1201.0f); - DoFloatTest("1234567890.0123456789g", "%g", 1234567936); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test16/testinfo.dat deleted file mode 100644 index 2c1dd42..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test16/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sscanf -Name = Positive Test for sscanf -TYPE = DEFAULT -EXE1 = test16 -Description -= Tests sscanf with floats (compact notation, lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test17/CMakeLists.txt deleted file mode 100644 index 7d908ab..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test17/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test17.c -) - -add_executable(paltest_sscanf_test17 - ${SOURCES} -) - -add_dependencies(paltest_sscanf_test17 coreclrpal) - -target_link_libraries(paltest_sscanf_test17 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/sscanf/test17/test17.c deleted file mode 100644 index c0dfd16..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test17/test17.c +++ /dev/null @@ -1,37 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test17.c -** -** Purpose: Tests sscanf with floats (compact notation, uppercase) -** -** -**==========================================================================*/ - - - -#include -#include "../sscanf.h" - -int __cdecl main(int argc, char *argv[]) -{ - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - DoFloatTest("123.0", "%G", 123.0f); - DoFloatTest("123.0", "%2G", 12.0f); - DoFloatTest("10E1", "%G", 100.0f); - DoFloatTest("-12.01e-2", "%G", -0.1201f); - DoFloatTest("+12.01e-2", "%G", 0.1201f); - DoFloatTest("-12.01e+2", "%G", -1201.0f); - DoFloatTest("+12.01e+2", "%G", 1201.0f); - DoFloatTest("1234567890.0123456789G", "%G", 1234567936); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test17/testinfo.dat deleted file mode 100644 index e23be85..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test17/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sscanf -Name = Positive Test for sscanf -TYPE = DEFAULT -EXE1 = test17 -Description -= Tests sscanf with floats (compact notation, uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test2/CMakeLists.txt deleted file mode 100644 index 571d773..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test2/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test2.c -) - -add_executable(paltest_sscanf_test2 - ${SOURCES} -) - -add_dependencies(paltest_sscanf_test2 coreclrpal) - -target_link_libraries(paltest_sscanf_test2 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/sscanf/test2/test2.c deleted file mode 100644 index 1221124..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test2/test2.c +++ /dev/null @@ -1,44 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test2.c -** -** Purpose: Test to see if sscanf handles whitespace correctly -** -** -**==========================================================================*/ - - - -#include -#include "../sscanf.h" - - -/* - * Tests out how it handles whitespace. Seems to accept anything that qualifies - * as isspace (space, tab, vertical tab, line feed, carriage return and form - * feed), even if it says it only wants spaces tabs and newlines. - */ - -int __cdecl main(int argc, char *argv[]) -{ - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - DoStrTest("foo bar", "foo %s", "bar"); - DoStrTest("foo\tbar", "foo %s", "bar"); - DoStrTest("foo\nbar", "foo %s", "bar"); - DoStrTest("foo\rbar", "foo %s", "bar"); - DoStrTest("foo\vbar", "foo %s", "bar"); - DoStrTest("foo\fbar", "foo %s", "bar"); - DoStrTest("foo \t\n\r\v\fbar", "foo %s", "bar"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test2/testinfo.dat deleted file mode 100644 index f5ee4b5..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test2/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sscanf -Name = Positive Test for sscanf -TYPE = DEFAULT -EXE1 = test2 -Description -= Test to see if sscanf handles whitespace correctly diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test3/CMakeLists.txt deleted file mode 100644 index ced8d5f..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test3/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test3.c -) - -add_executable(paltest_sscanf_test3 - ${SOURCES} -) - -add_dependencies(paltest_sscanf_test3 coreclrpal) - -target_link_libraries(paltest_sscanf_test3 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/sscanf/test3/test3.c deleted file mode 100644 index 9d18991..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test3/test3.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test3.c -** -** Purpose: Tests sscanf with bracketed set strings -** -** -**==========================================================================*/ - - - -#include -#include "../sscanf.h" - -int __cdecl main(int argc, char *argv[]) -{ - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - DoStrTest("bar1", "%[a-z]", "bar"); - DoStrTest("bar1", "%[z-a]", "bar"); - DoStrTest("bar1", "%[ab]", "ba"); - DoStrTest("bar1", "%[ar1b]", "bar1"); - DoStrTest("bar1", "%[^4]", "bar1"); - DoStrTest("bar1", "%[^4a]", "b"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test3/testinfo.dat deleted file mode 100644 index c38a498..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test3/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sscanf -Name = Positive Test for sscanf -TYPE = DEFAULT -EXE1 = test3 -Description -= Tests sscanf with bracketed set strings diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test4/CMakeLists.txt deleted file mode 100644 index 3e70d6d..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test4/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test4.c -) - -add_executable(paltest_sscanf_test4 - ${SOURCES} -) - -add_dependencies(paltest_sscanf_test4 coreclrpal) - -target_link_libraries(paltest_sscanf_test4 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/sscanf/test4/test4.c deleted file mode 100644 index dd0538b..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test4/test4.c +++ /dev/null @@ -1,44 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test4.c -** -** Purpose: Tests sscanf with decimal numbers -** -** -**==========================================================================*/ - - - -#include -#include "../sscanf.h" - - -int __cdecl main(int argc, char *argv[]) -{ - int n65535 = 65535; /* Walkaround compiler strictness */ - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - DoNumTest("1234d", "%d", 1234); - DoNumTest("1234d", "%2d", 12); - DoNumTest("-1", "%d", -1); - DoNumTest("0x1234", "%d", 0); - DoNumTest("012", "%d", 12); - DoShortNumTest("-1", "%hd", n65535); - DoShortNumTest("65536", "%hd", 0); - DoNumTest("-1", "%ld", -1); - DoNumTest("65536", "%ld", 65536); - DoNumTest("-1", "%Ld", -1); - DoNumTest("65536", "%Ld", 65536); - DoI64NumTest("4294967296", "%I64d", I64(4294967296)); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test4/testinfo.dat deleted file mode 100644 index 868056a..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test4/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sscanf -Name = Positive Test for sscanf -TYPE = DEFAULT -EXE1 = test4 -Description -= Tests sscanf with decimal numbers diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test5/CMakeLists.txt deleted file mode 100644 index 391e51b..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test5/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test5.c -) - -add_executable(paltest_sscanf_test5 - ${SOURCES} -) - -add_dependencies(paltest_sscanf_test5 coreclrpal) - -target_link_libraries(paltest_sscanf_test5 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/sscanf/test5/test5.c deleted file mode 100644 index 0d45248..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test5/test5.c +++ /dev/null @@ -1,43 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test5.c -** -** Purpose: Tests sscanf with integer numbers -** -** -**==========================================================================*/ - - - -#include -#include "../sscanf.h" - -int __cdecl main(int argc, char *argv[]) -{ - int n65535 = 65535; /* Walkaround compiler strictness */ - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - DoNumTest("1234d", "%i", 1234); - DoNumTest("1234d", "%2i", 12); - DoNumTest("-1", "%i", -1); - DoNumTest("0x1234", "%i", 0x1234); - DoNumTest("012", "%i", 10); - DoShortNumTest("-1", "%hi", n65535); - DoShortNumTest("65536", "%hi", 0); - DoNumTest("-1", "%li", -1); - DoNumTest("65536", "%li", 65536); - DoNumTest("-1", "%Li", -1); - DoNumTest("65536", "%Li", 65536); - DoI64NumTest("4294967296", "%I64i", I64(4294967296)); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test5/testinfo.dat deleted file mode 100644 index 8678dc8..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test5/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sscanf -Name = Positive Test for sscanf -TYPE = DEFAULT -EXE1 = test5 -Description -= Tests sscanf with integer numbers diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test6/CMakeLists.txt deleted file mode 100644 index c0b21bf..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test6/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test6.c -) - -add_executable(paltest_sscanf_test6 - ${SOURCES} -) - -add_dependencies(paltest_sscanf_test6 coreclrpal) - -target_link_libraries(paltest_sscanf_test6 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/sscanf/test6/test6.c deleted file mode 100644 index c45ea31..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test6/test6.c +++ /dev/null @@ -1,43 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test6.c -** -** Purpose: Tests sscanf with octal numbers -** -** -**==========================================================================*/ - - - -#include -#include "../sscanf.h" - -int __cdecl main(int argc, char *argv[]) -{ - int n65535 = 65535; /* Walkaround compiler strictness */ - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - DoNumTest("1234d", "%o", 668); - DoNumTest("1234d", "%2o", 10); - DoNumTest("-1", "%o", -1); - DoNumTest("0x1234", "%o", 0); - DoNumTest("012", "%o", 10); - DoShortNumTest("-1", "%ho", n65535); - DoShortNumTest("200000", "%ho", 0); - DoNumTest("-1", "%lo", -1); - DoNumTest("200000", "%lo", 65536); - DoNumTest("-1", "%Lo", -1); - DoNumTest("200000", "%Lo", 65536); - DoI64NumTest("40000000000", "%I64o", I64(4294967296)); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test6/testinfo.dat deleted file mode 100644 index b2547a7..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test6/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sscanf -Name = Positive Test for sscanf -TYPE = DEFAULT -EXE1 = test6 -Description -= Tests sscanf with octal numbers diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test7/CMakeLists.txt deleted file mode 100644 index bcbd268..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test7/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test7.c -) - -add_executable(paltest_sscanf_test7 - ${SOURCES} -) - -add_dependencies(paltest_sscanf_test7 coreclrpal) - -target_link_libraries(paltest_sscanf_test7 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/sscanf/test7/test7.c deleted file mode 100644 index 0899671..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test7/test7.c +++ /dev/null @@ -1,43 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test7.c -** -** Purpose: Tests sscanf with hex numbers (lowercase) -** -** -**==========================================================================*/ - - - -#include -#include "../sscanf.h" - -int __cdecl main(int argc, char *argv[]) -{ - int n65535 = 65535; /* Walkaround compiler strictness */ - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - DoNumTest("1234i", "%x", 0x1234); - DoNumTest("1234i", "%2x", 0x12); - DoNumTest("-1", "%x", -1); - DoNumTest("0x1234", "%x", 0x1234); - DoNumTest("012", "%x", 0x12); - DoShortNumTest("-1", "%hx", n65535); - DoShortNumTest("10000", "%hx", 0); - DoNumTest("-1", "%lx", -1); - DoNumTest("10000", "%lx", 65536); - DoNumTest("-1", "%Lx", -1); - DoNumTest("10000", "%Lx", 65536); - DoI64NumTest("100000000", "%I64x", I64(4294967296)); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test7/testinfo.dat deleted file mode 100644 index 614333e..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test7/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sscanf -Name = Positive Test for sscanf -TYPE = DEFAULT -EXE1 = test7 -Description -= Tests sscanf with hex numbers (lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test8/CMakeLists.txt deleted file mode 100644 index 211e9e4..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test8/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test8.c -) - -add_executable(paltest_sscanf_test8 - ${SOURCES} -) - -add_dependencies(paltest_sscanf_test8 coreclrpal) - -target_link_libraries(paltest_sscanf_test8 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/sscanf/test8/test8.c deleted file mode 100644 index 53252f8..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test8/test8.c +++ /dev/null @@ -1,43 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test8.c -** -** Purpose:Tests sscanf with unsigned number -** -** -**==========================================================================*/ - - - -#include -#include "../sscanf.h" - -int __cdecl main(int argc, char *argv[]) -{ - int n65535 = 65535; /* Walkaround compiler strictness */ - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - DoNumTest("1234d", "%u", 1234); - DoNumTest("1234d", "%2u", 12); - DoNumTest("-1", "%u", -1); - DoNumTest("0x1234", "%u", 0); - DoNumTest("012", "%u", 12); - DoShortNumTest("-1", "%hu", n65535); - DoShortNumTest("65536", "%hu", 0); - DoNumTest("-1", "%lu", -1); - DoNumTest("65536", "%lu", 65536); - DoNumTest("-1", "%Lu", -1); - DoNumTest("65536", "%Lu", 65536); - DoI64NumTest("4294967296", "%I64u", I64(4294967296)); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test8/testinfo.dat deleted file mode 100644 index 2cbc31a..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test8/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = C Runtime -Function = sscanf -Name = Positive Test for sscanf -TYPE = DEFAULT -EXE1 = test8 -Description -= Tests sscanf with unsigned numbers diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf/test9/CMakeLists.txt deleted file mode 100644 index 77c269a..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test9/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test9.c -) - -add_executable(paltest_sscanf_test9 - ${SOURCES} -) - -add_dependencies(paltest_sscanf_test9 coreclrpal) - -target_link_libraries(paltest_sscanf_test9 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/sscanf/test9/test9.c deleted file mode 100644 index c5a2e0d..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test9/test9.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test9.c -** -** Purpose: Tests sscanf with characters -** -** -**==========================================================================*/ - - - -#include -#include "../sscanf.h" - - -int __cdecl main(int argc, char *argv[]) -{ - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - DoCharTest("1234d", "%c", "1", 1); - DoCharTest("1234d", "%c", "1", 1); - DoCharTest("abc", "%2c", "ab", 2); - DoCharTest(" ab", "%c", " ", 1); - DoCharTest("ab", "%hc", "a", 1); - DoWCharTest("ab", "%lc", convert("a"), 1); - DoCharTest("ab", "%Lc", "a", 1); - DoCharTest("ab", "%I64c", "a", 1); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf/test9/testinfo.dat deleted file mode 100644 index c0ccc8a..0000000 --- a/src/pal/tests/palsuite/c_runtime/sscanf/test9/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section =C Runtime -Function = sscanf -Name = Positive Test for sscanf -TYPE = DEFAULT -EXE1 = test9 -Description -= Tests sscanf with characters diff --git a/src/pal/tests/palsuite/c_runtime/sscanf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf_s/CMakeLists.txt similarity index 100% rename from src/pal/tests/palsuite/c_runtime/sscanf/CMakeLists.txt rename to src/pal/tests/palsuite/c_runtime/sscanf_s/CMakeLists.txt diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/sscanf_s.h b/src/pal/tests/palsuite/c_runtime/sscanf_s/sscanf_s.h new file mode 100644 index 0000000..8a99d87 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/sscanf_s.h @@ -0,0 +1,246 @@ +// 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. + +/*============================================================================ +** +** Source: sscanf_s.h +** +** Purpose: Contains common testing functions for sscanf_s +** +** +**==========================================================================*/ + +#ifndef __SSCANF_S_H__ +#define __SSCANF_S_H__ + +void DoVoidTest(char *inputstr, const char *formatstr) +{ + char buf[256] = { 0 }; + int i; + int ret; + + ret = sscanf_s(inputstr, formatstr, buf); + if (ret != 0) + { + Fail("ERROR: Expected sscanf_s to return 0, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); + } + + for (i=0; i<256; i++) + { + if (buf[i] != 0) + { + Fail("ERROR: Parameter unexpectedly modified scanning \"%s\" " + "using \"%s\".\n", inputstr, formatstr); + } + } + +} + +void DoStrTest(char *inputstr, const char *formatstr, const char *checkstr) +{ + char buf[256] = { 0 }; + int ret; + + ret = sscanf_s(inputstr, formatstr, buf, _countof(buf)); + if (ret != 1) + { + Fail("ERROR: Expected sscanf_s to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); + } + + if (memcmp(checkstr, buf, strlen(checkstr) + 1) != 0) + { + Fail("ERROR: scanned string incorrectly from \"%s\" using \"%s\".\n" + "Expected \"%s\", got \"%s\".\n", inputstr, formatstr, checkstr, + buf); + } + +} + +void DoWStrTest(char *inputstr, const char *formatstr, const WCHAR *checkstr) +{ + WCHAR buf[256] = { 0 }; + int ret; + + ret = sscanf_s(inputstr, formatstr, buf, _countof(buf)); + if (ret != 1) + { + Fail("ERROR: Expected sscanf_s to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); + } + + if (memcmp(checkstr, buf, wcslen(checkstr)*2 + 2) != 0) + { + Fail("ERROR: scanned wide string incorrectly from \"%s\" using \"%s\".\n" + "Expected \"%s\", got \"%s\".\n", inputstr, formatstr, + convertC(checkstr), convertC(buf)); + } + +} + +void DoNumTest(char *inputstr, const char *formatstr, int checknum) +{ + int num; + int ret; + + ret = sscanf_s(inputstr, formatstr, &num); + if (ret != 1) + { + Fail("ERROR: Expected sscanf_s to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); + } + + if (checknum != num) + { + Fail("ERROR: scanned number incorrectly from \"%s\" using \"%s\".\n" + "Expected %d, got %d.\n", inputstr, formatstr, checknum, num); + } +} + +void DoShortNumTest(char *inputstr, const char *formatstr, short checknum) +{ + short num; + int ret; + + ret = sscanf_s(inputstr, formatstr, &num); + if (ret != 1) + { + Fail("ERROR: Expected sscanf_s to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); + } + + if (checknum != num) + { + Fail("ERROR: scanned number incorrectly from \"%s\" using \"%s\".\n" + "Expected %hd, got %hd.\n", inputstr, formatstr, checknum, num); + } +} + +void DoI64NumTest(char *inputstr, const char *formatstr, INT64 checknum) +{ + char buf[256]; + char check[256]; + INT64 num; + int ret; + + ret = sscanf_s(inputstr, formatstr, &num); + if (ret != 1) + { + Fail("ERROR: Expected sscanf_s to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); + } + + if (checknum != num) + { + sprintf_s(buf, _countof(buf), "%I64d", num); + sprintf_s(check, _countof(check), "%I64d", checknum); + Fail("ERROR: scanned I64 number incorrectly from \"%s\" using \"%s\".\n" + "Expected %s, got %s.\n", inputstr, formatstr, check, buf); + } +} + +void DoCharTest(char *inputstr, const char *formatstr, char* checkchars, int numchars) +{ + char buf[256]; + int ret; + int i; + + for (i=0; i<256; i++) + buf[i] = (char)-1; + + ret = sscanf_s(inputstr, formatstr, buf, _countof(buf)); + if (ret != 1) + { + Fail("ERROR: Expected sscanf_s to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); + } + + if (memcmp(buf, checkchars, numchars) != 0) + { + buf[numchars] = 0; + + Fail("ERROR: scanned character(s) incorrectly from \"%s\" using \"%s\".\n" + "Expected %s, got %s.\n", inputstr, formatstr, checkchars, + buf); + } + + if (buf[numchars] != (char)-1) + { + Fail("ERROR: overflow occurred in scanning character(s) from \"%s\" " + "using \"%s\".\nExpected %d character(s)\n", inputstr, formatstr, + numchars); + } +} + +void DoWCharTest(char *inputstr, const char *formatstr, WCHAR* checkchars, int numchars) +{ + WCHAR buf[256]; + int ret; + int i; + + for (i=0; i<256; i++) + buf[i] = (WCHAR)-1; + + ret = sscanf_s(inputstr, formatstr, buf, _countof(buf)); + if (ret != 1) + { + Fail("ERROR: Expected sscanf_s to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); + } + + if (memcmp(buf, checkchars, numchars) != 0) + { + buf[numchars] = 0; + + Fail("ERROR: scanned wide character(s) incorrectly from \"%s\" using \"%s\".\n" + "Expected %s, got %s.\n", inputstr, formatstr, convertC(checkchars), + convertC(buf)); + } + + if (buf[numchars] != (WCHAR)-1) + { + Fail("ERROR: overflow occurred in scanning wide character(s) from \"%s\" " + "using \"%s\".\nExpected %d character(s)\n", inputstr, formatstr, + numchars); + } +} + + +void DoFloatTest(char *inputstr, const char *formatstr, float checkval) +{ + char buf[256] = { 0 }; + float val; + int ret; + int i; + + for (i=0; i<256; i++) + buf[i] = (char)-1; + + ret = sscanf_s(inputstr, formatstr, buf); + val = *(float*)buf; + + if (ret != 1) + { + Fail("ERROR: Expected sscanf_s to return 1, got %d.\n" + "Using \"%s\" in \"%s\".\n", ret, inputstr, formatstr); + } + + if (val != checkval) + { + Fail("ERROR: scanned float incorrectly from \"%s\" using \"%s\".\n" + "Expected \"%f\", got \"%f\".\n", inputstr, formatstr, checkval, + val); + } + + if (buf[4] != (char)-1) + { + Fail("ERROR: overflow occurred in scanning float from \"%s\" " + "using \"%s\".\n", inputstr, formatstr); + + } +} + + +#endif diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/CMakeLists.txt new file mode 100644 index 0000000..97b8f57 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.cpp +) + +add_executable(paltest_sscanf_test1 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test1 coreclrpal) + +target_link_libraries(paltest_sscanf_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/test1.cpp b/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/test1.cpp new file mode 100644 index 0000000..6131314 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/test1.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: General test of sscanf_s +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + + +int __cdecl main(int argc, char *argv[]) +{ + int num; + int ret; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + DoVoidTest("foo bar", "foo "); + DoVoidTest("foo bar", "baz"); + DoVoidTest("foo bar", "foo %*s"); + + DoStrTest("foo % bar", "foo %% %s", "bar"); + DoStrTest("foo bar baz", "foo %bar %s", "baz"); + + DoVoidTest("foo bar baz", "foo % bar %s"); + DoVoidTest("foo baz bar", "foo% baz %s"); + + ret = sscanf_s("foo bar baz", "foo bar %n", &num); + if (ret != 0 || num != 8) + { + Fail("ERROR: Got incorrect values in scanning \"%s\" using \"%s\".\n" + "Expected to get a value of %d with return value of %d, " + "got %d with return %d\n", "foo bar baz", "foo bar %n", 8, 0, + num, ret); + + } + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/testinfo.dat new file mode 100644 index 0000000..76f5927 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test1/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test1 +Description += General test of sscanf_s diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/CMakeLists.txt new file mode 100644 index 0000000..afda216 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test10.cpp +) + +add_executable(paltest_sscanf_test10 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test10 coreclrpal) + +target_link_libraries(paltest_sscanf_test10 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/test10.cpp b/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/test10.cpp new file mode 100644 index 0000000..0c63c86 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/test10.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test10.c +** +** Purpose: Tests sscanf_s with wide characters +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoWCharTest("1234d", "%C", convert("1"), 1); + DoWCharTest("1234d", "%C", convert("1"), 1); + DoWCharTest("abc", "%2C", convert("ab"), 2); + DoWCharTest(" ab", "%C", convert(" "), 1); + DoCharTest("ab", "%hC", "a", 1); + DoWCharTest("ab", "%lC", convert("a"), 1); + DoWCharTest("ab", "%LC", convert("a"), 1); + DoWCharTest("ab", "%I64C", convert("a"), 1); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/testinfo.dat new file mode 100644 index 0000000..e048e70 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test10/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test10 +Description += Tests sscanf_s with wide characters diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/CMakeLists.txt new file mode 100644 index 0000000..c8f98ae --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test11.cpp +) + +add_executable(paltest_sscanf_test11 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test11 coreclrpal) + +target_link_libraries(paltest_sscanf_test11 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/test11.cpp b/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/test11.cpp new file mode 100644 index 0000000..8279f4b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/test11.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test11.c +** +** Purpose: Tests sscanf_s with strings +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoStrTest("foo bar", "foo %s", "bar"); + DoStrTest("foo bar", "foo %2s", "ba"); + DoStrTest("foo bar", "foo %hs", "bar"); + DoWStrTest("foo bar", "foo %ls", convert("bar")); + DoStrTest("foo bar", "foo %Ls", "bar"); + DoStrTest("foo bar", "foo %I64s", "bar"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/testinfo.dat new file mode 100644 index 0000000..5a906dd --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test11/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test11 +Description += Tests sscanf_s with strings diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/CMakeLists.txt new file mode 100644 index 0000000..0ecedc3 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test12.cpp +) + +add_executable(paltest_sscanf_test12 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test12 coreclrpal) + +target_link_libraries(paltest_sscanf_test12 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/test12.cpp b/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/test12.cpp new file mode 100644 index 0000000..e599534 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/test12.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test12.c +** +** Purpose: Tests sscanf_s with wide strings +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoWStrTest("foo bar", "foo %S", convert("bar")); + DoWStrTest("foo bar", "foo %2S", convert("ba")); + DoStrTest("foo bar", "foo %hS", "bar"); + DoWStrTest("foo bar", "foo %lS", convert("bar")); + DoWStrTest("foo bar", "foo %LS", convert("bar")); + DoWStrTest("foo bar", "foo %I64S", convert("bar")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/testinfo.dat new file mode 100644 index 0000000..569be98 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test12/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test12 +Description += Tests sscanf_s with wide strings diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/CMakeLists.txt new file mode 100644 index 0000000..4566ec3 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test13.cpp +) + +add_executable(paltest_sscanf_test13 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test13 coreclrpal) + +target_link_libraries(paltest_sscanf_test13 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/test13.cpp b/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/test13.cpp new file mode 100644 index 0000000..4fc12bb --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/test13.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test13.c +** +** Purpose: Tests sscanf_s with floats (decimal notation) +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoFloatTest("123.0", "%f", 123.0f); + DoFloatTest("123.0", "%2f", 12.0f); + DoFloatTest("10E1", "%f", 100.0f); + DoFloatTest("-12.01e-2", "%f", -0.1201f); + DoFloatTest("+12.01e-2", "%f", 0.1201f); + DoFloatTest("-12.01e+2", "%f", -1201.0f); + DoFloatTest("+12.01e+2", "%f", 1201.0f); + DoFloatTest("1234567890.0123456789f", "%f", 1234567936); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/testinfo.dat new file mode 100644 index 0000000..651577b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test13/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test13 +Description += Tests sscanf_s with floats (decimal notation) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/CMakeLists.txt new file mode 100644 index 0000000..557acf5 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test14.cpp +) + +add_executable(paltest_sscanf_test14 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test14 coreclrpal) + +target_link_libraries(paltest_sscanf_test14 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/test14.cpp b/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/test14.cpp new file mode 100644 index 0000000..fc2fa2e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/test14.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test14.c +** +** Purpose: Tests sscanf_s with floats (exponential notation, lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoFloatTest("123.0", "%e", 123.0f); + DoFloatTest("123.0", "%2e", 12.0f); + DoFloatTest("10E1", "%e", 100.0f); + DoFloatTest("-12.01e-2", "%e", -0.1201f); + DoFloatTest("+12.01e-2", "%e", 0.1201f); + DoFloatTest("-12.01e+2", "%e", -1201.0f); + DoFloatTest("+12.01e+2", "%e", 1201.0f); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/testinfo.dat new file mode 100644 index 0000000..8e7338f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test14/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test14 +Description += Tests sscanf_s with floats (exponential notation, lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/CMakeLists.txt new file mode 100644 index 0000000..efde5c4 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test15.cpp +) + +add_executable(paltest_sscanf_test15 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test15 coreclrpal) + +target_link_libraries(paltest_sscanf_test15 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/test15.cpp b/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/test15.cpp new file mode 100644 index 0000000..1eff995 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/test15.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test15.c +** +** Purpose: Tests sscanf_s with floats (exponential notation, uppercase +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoFloatTest("123.0", "%E", 123.0f); + DoFloatTest("123.0", "%2E", 12.0f); + DoFloatTest("10E1", "%E", 100.0f); + DoFloatTest("-12.01e-2", "%E", -0.1201f); + DoFloatTest("+12.01e-2", "%E", 0.1201f); + DoFloatTest("-12.01e+2", "%E", -1201.0f); + DoFloatTest("+12.01e+2", "%E", 1201.0f); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/testinfo.dat new file mode 100644 index 0000000..d713a73 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test15/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test15 +Description += Tests sscanf_s with floats (exponential notation, uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/CMakeLists.txt new file mode 100644 index 0000000..6757b0d --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test16.cpp +) + +add_executable(paltest_sscanf_test16 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test16 coreclrpal) + +target_link_libraries(paltest_sscanf_test16 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/test16.cpp b/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/test16.cpp new file mode 100644 index 0000000..f202767 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/test16.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test16.c +** +** Purpose:Tests sscanf_s with floats (compact notation, lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoFloatTest("123.0", "%g", 123.0f); + DoFloatTest("123.0", "%2g", 12.0f); + DoFloatTest("10E1", "%g", 100.0f); + DoFloatTest("-12.01e-2", "%g", -0.1201f); + DoFloatTest("+12.01e-2", "%g", 0.1201f); + DoFloatTest("-12.01e+2", "%g", -1201.0f); + DoFloatTest("+12.01e+2", "%g", 1201.0f); + DoFloatTest("1234567890.0123456789g", "%g", 1234567936); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/testinfo.dat new file mode 100644 index 0000000..6696119 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test16/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test16 +Description += Tests sscanf_s with floats (compact notation, lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/CMakeLists.txt new file mode 100644 index 0000000..8ea4d5e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test17.cpp +) + +add_executable(paltest_sscanf_test17 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test17 coreclrpal) + +target_link_libraries(paltest_sscanf_test17 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/test17.cpp b/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/test17.cpp new file mode 100644 index 0000000..a18c3ca --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/test17.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test17.c +** +** Purpose: Tests sscanf_s with floats (compact notation, uppercase) +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoFloatTest("123.0", "%G", 123.0f); + DoFloatTest("123.0", "%2G", 12.0f); + DoFloatTest("10E1", "%G", 100.0f); + DoFloatTest("-12.01e-2", "%G", -0.1201f); + DoFloatTest("+12.01e-2", "%G", 0.1201f); + DoFloatTest("-12.01e+2", "%G", -1201.0f); + DoFloatTest("+12.01e+2", "%G", 1201.0f); + DoFloatTest("1234567890.0123456789G", "%G", 1234567936); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/testinfo.dat new file mode 100644 index 0000000..8ce4e93 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test17/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test17 +Description += Tests sscanf_s with floats (compact notation, uppercase) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/CMakeLists.txt new file mode 100644 index 0000000..4e36223 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test2.cpp +) + +add_executable(paltest_sscanf_test2 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test2 coreclrpal) + +target_link_libraries(paltest_sscanf_test2 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/test2.cpp b/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/test2.cpp new file mode 100644 index 0000000..c9c79f6 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/test2.cpp @@ -0,0 +1,44 @@ +// 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. + +/*============================================================================ +** +** Source: test2.c +** +** Purpose: Test to see if sscanf_s handles whitespace correctly +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + + +/* + * Tests out how it handles whitespace. Seems to accept anything that qualifies + * as isspace (space, tab, vertical tab, line feed, carriage return and form + * feed), even if it says it only wants spaces tabs and newlines. + */ + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoStrTest("foo bar", "foo %s", "bar"); + DoStrTest("foo\tbar", "foo %s", "bar"); + DoStrTest("foo\nbar", "foo %s", "bar"); + DoStrTest("foo\rbar", "foo %s", "bar"); + DoStrTest("foo\vbar", "foo %s", "bar"); + DoStrTest("foo\fbar", "foo %s", "bar"); + DoStrTest("foo \t\n\r\v\fbar", "foo %s", "bar"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/testinfo.dat new file mode 100644 index 0000000..85fed24 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test2/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test2 +Description += Test to see if sscanf_s handles whitespace correctly diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/CMakeLists.txt new file mode 100644 index 0000000..053a96c --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test3.cpp +) + +add_executable(paltest_sscanf_test3 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test3 coreclrpal) + +target_link_libraries(paltest_sscanf_test3 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/test3.cpp b/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/test3.cpp new file mode 100644 index 0000000..e1e45bd --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/test3.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test3.c +** +** Purpose: Tests sscanf_s with bracketed set strings +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoStrTest("bar1", "%[a-z]", "bar"); + DoStrTest("bar1", "%[z-a]", "bar"); + DoStrTest("bar1", "%[ab]", "ba"); + DoStrTest("bar1", "%[ar1b]", "bar1"); + DoStrTest("bar1", "%[^4]", "bar1"); + DoStrTest("bar1", "%[^4a]", "b"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/testinfo.dat new file mode 100644 index 0000000..523d31e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test3/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test3 +Description += Tests sscanf_s with bracketed set strings diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/CMakeLists.txt new file mode 100644 index 0000000..ae04bfe --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test4.cpp +) + +add_executable(paltest_sscanf_test4 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test4 coreclrpal) + +target_link_libraries(paltest_sscanf_test4 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/test4.cpp b/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/test4.cpp new file mode 100644 index 0000000..f8413ea --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/test4.cpp @@ -0,0 +1,44 @@ +// 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. + +/*============================================================================ +** +** Source: test4.c +** +** Purpose: Tests sscanf_s with decimal numbers +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + + +int __cdecl main(int argc, char *argv[]) +{ + int n65535 = 65535; /* Walkaround compiler strictness */ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoNumTest("1234d", "%d", 1234); + DoNumTest("1234d", "%2d", 12); + DoNumTest("-1", "%d", -1); + DoNumTest("0x1234", "%d", 0); + DoNumTest("012", "%d", 12); + DoShortNumTest("-1", "%hd", n65535); + DoShortNumTest("65536", "%hd", 0); + DoNumTest("-1", "%ld", -1); + DoNumTest("65536", "%ld", 65536); + DoNumTest("-1", "%Ld", -1); + DoNumTest("65536", "%Ld", 65536); + DoI64NumTest("4294967296", "%I64d", I64(4294967296)); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/testinfo.dat new file mode 100644 index 0000000..2065f2b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test4/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test4 +Description += Tests sscanf_s with decimal numbers diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/CMakeLists.txt new file mode 100644 index 0000000..33dcaff --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test5.cpp +) + +add_executable(paltest_sscanf_test5 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test5 coreclrpal) + +target_link_libraries(paltest_sscanf_test5 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/test5.cpp b/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/test5.cpp new file mode 100644 index 0000000..cdfefd8 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/test5.cpp @@ -0,0 +1,43 @@ +// 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. + +/*============================================================================ +** +** Source: test5.c +** +** Purpose: Tests sscanf_s with integer numbers +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + int n65535 = 65535; /* Walkaround compiler strictness */ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoNumTest("1234d", "%i", 1234); + DoNumTest("1234d", "%2i", 12); + DoNumTest("-1", "%i", -1); + DoNumTest("0x1234", "%i", 0x1234); + DoNumTest("012", "%i", 10); + DoShortNumTest("-1", "%hi", n65535); + DoShortNumTest("65536", "%hi", 0); + DoNumTest("-1", "%li", -1); + DoNumTest("65536", "%li", 65536); + DoNumTest("-1", "%Li", -1); + DoNumTest("65536", "%Li", 65536); + DoI64NumTest("4294967296", "%I64i", I64(4294967296)); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/testinfo.dat new file mode 100644 index 0000000..cb687c1 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test5/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test5 +Description += Tests sscanf_s with integer numbers diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/CMakeLists.txt new file mode 100644 index 0000000..1dd23c3 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test6.cpp +) + +add_executable(paltest_sscanf_test6 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test6 coreclrpal) + +target_link_libraries(paltest_sscanf_test6 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/test6.cpp b/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/test6.cpp new file mode 100644 index 0000000..507b100 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/test6.cpp @@ -0,0 +1,43 @@ +// 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. + +/*============================================================================ +** +** Source: test6.c +** +** Purpose: Tests sscanf_s with octal numbers +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + int n65535 = 65535; /* Walkaround compiler strictness */ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoNumTest("1234d", "%o", 668); + DoNumTest("1234d", "%2o", 10); + DoNumTest("-1", "%o", -1); + DoNumTest("0x1234", "%o", 0); + DoNumTest("012", "%o", 10); + DoShortNumTest("-1", "%ho", n65535); + DoShortNumTest("200000", "%ho", 0); + DoNumTest("-1", "%lo", -1); + DoNumTest("200000", "%lo", 65536); + DoNumTest("-1", "%Lo", -1); + DoNumTest("200000", "%Lo", 65536); + DoI64NumTest("40000000000", "%I64o", I64(4294967296)); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/testinfo.dat new file mode 100644 index 0000000..9e518dd --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test6/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test6 +Description += Tests sscanf_s with octal numbers diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/CMakeLists.txt new file mode 100644 index 0000000..015a27b --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test7.cpp +) + +add_executable(paltest_sscanf_test7 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test7 coreclrpal) + +target_link_libraries(paltest_sscanf_test7 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/test7.cpp b/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/test7.cpp new file mode 100644 index 0000000..4093e00 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/test7.cpp @@ -0,0 +1,43 @@ +// 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. + +/*============================================================================ +** +** Source: test7.c +** +** Purpose: Tests sscanf_s with hex numbers (lowercase) +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + int n65535 = 65535; /* Walkaround compiler strictness */ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoNumTest("1234i", "%x", 0x1234); + DoNumTest("1234i", "%2x", 0x12); + DoNumTest("-1", "%x", -1); + DoNumTest("0x1234", "%x", 0x1234); + DoNumTest("012", "%x", 0x12); + DoShortNumTest("-1", "%hx", n65535); + DoShortNumTest("10000", "%hx", 0); + DoNumTest("-1", "%lx", -1); + DoNumTest("10000", "%lx", 65536); + DoNumTest("-1", "%Lx", -1); + DoNumTest("10000", "%Lx", 65536); + DoI64NumTest("100000000", "%I64x", I64(4294967296)); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/testinfo.dat new file mode 100644 index 0000000..8d6c182 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test7/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test7 +Description += Tests sscanf_s with hex numbers (lowercase) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/CMakeLists.txt new file mode 100644 index 0000000..aa41ab4 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test8.cpp +) + +add_executable(paltest_sscanf_test8 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test8 coreclrpal) + +target_link_libraries(paltest_sscanf_test8 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/test8.cpp b/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/test8.cpp new file mode 100644 index 0000000..23ef22a --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/test8.cpp @@ -0,0 +1,43 @@ +// 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. + +/*============================================================================ +** +** Source: test8.c +** +** Purpose:Tests sscanf_s with unsigned number +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + +int __cdecl main(int argc, char *argv[]) +{ + int n65535 = 65535; /* Walkaround compiler strictness */ + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoNumTest("1234d", "%u", 1234); + DoNumTest("1234d", "%2u", 12); + DoNumTest("-1", "%u", -1); + DoNumTest("0x1234", "%u", 0); + DoNumTest("012", "%u", 12); + DoShortNumTest("-1", "%hu", n65535); + DoShortNumTest("65536", "%hu", 0); + DoNumTest("-1", "%lu", -1); + DoNumTest("65536", "%lu", 65536); + DoNumTest("-1", "%Lu", -1); + DoNumTest("65536", "%Lu", 65536); + DoI64NumTest("4294967296", "%I64u", I64(4294967296)); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/testinfo.dat new file mode 100644 index 0000000..0287a49 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test8/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test8 +Description += Tests sscanf_s with unsigned numbers diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/CMakeLists.txt new file mode 100644 index 0000000..b631fd4 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test9.cpp +) + +add_executable(paltest_sscanf_test9 + ${SOURCES} +) + +add_dependencies(paltest_sscanf_test9 coreclrpal) + +target_link_libraries(paltest_sscanf_test9 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/test9.cpp b/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/test9.cpp new file mode 100644 index 0000000..2c99c40 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/test9.cpp @@ -0,0 +1,38 @@ +// 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. + +/*============================================================================ +** +** Source: test9.c +** +** Purpose: Tests sscanf_s with characters +** +** +**==========================================================================*/ + + + +#include +#include "../sscanf_s.h" + + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoCharTest("1234d", "%c", "1", 1); + DoCharTest("1234d", "%c", "1", 1); + DoCharTest("abc", "%2c", "ab", 2); + DoCharTest(" ab", "%c", " ", 1); + DoCharTest("ab", "%hc", "a", 1); + DoWCharTest("ab", "%lc", convert("a"), 1); + DoCharTest("ab", "%Lc", "a", 1); + DoCharTest("ab", "%I64c", "a", 1); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/testinfo.dat b/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/testinfo.dat new file mode 100644 index 0000000..95f6c74 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/sscanf_s/test9/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section =C Runtime +Function = sscanf_s +Name = Positive Test for sscanf_s +TYPE = DEFAULT +EXE1 = test9 +Description += Tests sscanf_s with characters diff --git a/src/pal/tests/palsuite/c_runtime/strcat/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strcat/test1/CMakeLists.txt index 4a0f0be..fd62627 100644 --- a/src/pal/tests/palsuite/c_runtime/strcat/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/strcat/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_strcat_test1 diff --git a/src/pal/tests/palsuite/c_runtime/strcat/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strcat/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/strcat/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/strcat/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/strchr/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strchr/test1/CMakeLists.txt index 1d248f3..f3ffe3b 100644 --- a/src/pal/tests/palsuite/c_runtime/strchr/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/strchr/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_strchr_test1 diff --git a/src/pal/tests/palsuite/c_runtime/strchr/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strchr/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/strchr/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/strchr/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/strcmp/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strcmp/test1/CMakeLists.txt index b953dfa..3b0f89c 100644 --- a/src/pal/tests/palsuite/c_runtime/strcmp/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/strcmp/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_strcmp_test1 diff --git a/src/pal/tests/palsuite/c_runtime/strcmp/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strcmp/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/strcmp/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/strcmp/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/strcpy/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strcpy/test1/CMakeLists.txt index 043ec57..4369d37 100644 --- a/src/pal/tests/palsuite/c_runtime/strcpy/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/strcpy/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_strcpy_test1 diff --git a/src/pal/tests/palsuite/c_runtime/strcpy/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strcpy/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/strcpy/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/strcpy/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/strcspn/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strcspn/test1/CMakeLists.txt index a38761c..717e18f 100644 --- a/src/pal/tests/palsuite/c_runtime/strcspn/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/strcspn/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_strcspn_test1 diff --git a/src/pal/tests/palsuite/c_runtime/strcspn/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strcspn/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/strcspn/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/strcspn/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/strlen/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strlen/test1/CMakeLists.txt index c61828a..4afeb59 100644 --- a/src/pal/tests/palsuite/c_runtime/strlen/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/strlen/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_strlen_test1 diff --git a/src/pal/tests/palsuite/c_runtime/strlen/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strlen/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/strlen/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/strlen/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/strncat/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strncat/test1/CMakeLists.txt index 7595f66..f8080ec 100644 --- a/src/pal/tests/palsuite/c_runtime/strncat/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/strncat/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_strncat_test1 diff --git a/src/pal/tests/palsuite/c_runtime/strncat/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strncat/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/strncat/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/strncat/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/strncmp/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strncmp/test1/CMakeLists.txt index 4a0337a..34b53e2 100644 --- a/src/pal/tests/palsuite/c_runtime/strncmp/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/strncmp/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_strncmp_test1 diff --git a/src/pal/tests/palsuite/c_runtime/strncmp/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strncmp/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/strncmp/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/strncmp/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/strncpy/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strncpy/test1/CMakeLists.txt index 6e0250b..fb737c8 100644 --- a/src/pal/tests/palsuite/c_runtime/strncpy/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/strncpy/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_strncpy_test1 diff --git a/src/pal/tests/palsuite/c_runtime/strncpy/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strncpy/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/strncpy/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/strncpy/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/strpbrk/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strpbrk/test1/CMakeLists.txt index eac9ac9..9e76436 100644 --- a/src/pal/tests/palsuite/c_runtime/strpbrk/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/strpbrk/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_strpbrk_test1 diff --git a/src/pal/tests/palsuite/c_runtime/strpbrk/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strpbrk/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/strpbrk/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/strpbrk/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/strrchr/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strrchr/test1/CMakeLists.txt index 5c099b0..bb69160 100644 --- a/src/pal/tests/palsuite/c_runtime/strrchr/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/strrchr/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_strrchr_test1 diff --git a/src/pal/tests/palsuite/c_runtime/strrchr/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strrchr/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/strrchr/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/strrchr/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/strspn/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strspn/test1/CMakeLists.txt index 45caaf1..c72fd0f 100644 --- a/src/pal/tests/palsuite/c_runtime/strspn/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/strspn/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_strspn_test1 diff --git a/src/pal/tests/palsuite/c_runtime/strspn/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strspn/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/strspn/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/strspn/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/strstr/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strstr/test1/CMakeLists.txt index 17e6ae8..004b9a5 100644 --- a/src/pal/tests/palsuite/c_runtime/strstr/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/strstr/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_strstr_test1 diff --git a/src/pal/tests/palsuite/c_runtime/strstr/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strstr/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/strstr/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/strstr/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/strtod/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strtod/test1/CMakeLists.txt index d3a9d61..09884f3 100644 --- a/src/pal/tests/palsuite/c_runtime/strtod/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/strtod/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_strtod_test1 diff --git a/src/pal/tests/palsuite/c_runtime/strtod/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strtod/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/strtod/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/strtod/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/strtod/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strtod/test2/CMakeLists.txt index 6f407c5..8729cc5 100644 --- a/src/pal/tests/palsuite/c_runtime/strtod/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/strtod/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_strtod_test2 diff --git a/src/pal/tests/palsuite/c_runtime/strtod/test2/test2.c b/src/pal/tests/palsuite/c_runtime/strtod/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/strtod/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/strtod/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/strtok/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strtok/test1/CMakeLists.txt index 1d5fc04..422c4e9 100644 --- a/src/pal/tests/palsuite/c_runtime/strtok/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/strtok/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_strtok_test1 diff --git a/src/pal/tests/palsuite/c_runtime/strtok/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strtok/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/strtok/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/strtok/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/strtoul/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/strtoul/test1/CMakeLists.txt index 61dbd4f..009e85f 100644 --- a/src/pal/tests/palsuite/c_runtime/strtoul/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/strtoul/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_strtoul_test1 diff --git a/src/pal/tests/palsuite/c_runtime/strtoul/test1/test1.c b/src/pal/tests/palsuite/c_runtime/strtoul/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/strtoul/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/strtoul/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/swprintf.h b/src/pal/tests/palsuite/c_runtime/swprintf/swprintf.h index 5229506..6f4c914 100644 --- a/src/pal/tests/palsuite/c_runtime/swprintf/swprintf.h +++ b/src/pal/tests/palsuite/c_runtime/swprintf/swprintf.h @@ -14,7 +14,7 @@ #ifndef __SWPRINTF_H__ #define __SWPRINTF_H__ -void DoWStrTest(WCHAR *formatstr, WCHAR *param, WCHAR *checkstr) +void DoWStrTest(const WCHAR *formatstr, WCHAR *param, const WCHAR *checkstr) { WCHAR buf[256] = { 0 }; @@ -29,7 +29,7 @@ void DoWStrTest(WCHAR *formatstr, WCHAR *param, WCHAR *checkstr) } } -void DoStrTest(WCHAR *formatstr, char *param, WCHAR *checkstr) +void DoStrTest(const WCHAR *formatstr, char *param, const WCHAR *checkstr) { WCHAR buf[256] = { 0 }; @@ -44,7 +44,7 @@ void DoStrTest(WCHAR *formatstr, char *param, WCHAR *checkstr) } } -void DoPointerTest(WCHAR *formatstr, void* param, WCHAR *checkstr1) +void DoPointerTest(const WCHAR *formatstr, void* param, const WCHAR *checkstr1) { WCHAR buf[256] = { 0 }; @@ -57,7 +57,7 @@ void DoPointerTest(WCHAR *formatstr, void* param, WCHAR *checkstr1) } } -void DoCountTest(WCHAR *formatstr, int param, WCHAR *checkstr) +void DoCountTest(const WCHAR *formatstr, int param, const WCHAR *checkstr) { WCHAR buf[512] = { 0 }; int n = -1; @@ -77,7 +77,7 @@ void DoCountTest(WCHAR *formatstr, int param, WCHAR *checkstr) } } -void DoShortCountTest(WCHAR *formatstr, int param, WCHAR *checkstr) +void DoShortCountTest(const WCHAR *formatstr, int param, const WCHAR *checkstr) { WCHAR buf[256] = { 0 }; short int n = -1; @@ -97,7 +97,7 @@ void DoShortCountTest(WCHAR *formatstr, int param, WCHAR *checkstr) } } -void DoCharTest(WCHAR *formatstr, char param, WCHAR *checkstr) +void DoCharTest(const WCHAR *formatstr, char param, const WCHAR *checkstr) { WCHAR buf[256] = { 0 }; @@ -110,7 +110,7 @@ void DoCharTest(WCHAR *formatstr, char param, WCHAR *checkstr) } } -void DoWCharTest(WCHAR *formatstr, WCHAR param, WCHAR *checkstr) +void DoWCharTest(const WCHAR *formatstr, WCHAR param, const WCHAR *checkstr) { WCHAR buf[256] = { 0 }; @@ -123,7 +123,7 @@ void DoWCharTest(WCHAR *formatstr, WCHAR param, WCHAR *checkstr) } } -void DoNumTest(WCHAR *formatstr, int value, WCHAR*checkstr) +void DoNumTest(const WCHAR *formatstr, int value, const WCHAR *checkstr) { WCHAR buf[256] = { 0 }; @@ -136,8 +136,8 @@ void DoNumTest(WCHAR *formatstr, int value, WCHAR*checkstr) } } -void DoI64Test(WCHAR *formatstr, INT64 param, char *paramdesc, - WCHAR *checkstr1) +void DoI64Test(const WCHAR *formatstr, INT64 param, char *paramdesc, + const WCHAR *checkstr1) { WCHAR buf[256] = { 0 }; @@ -150,8 +150,8 @@ void DoI64Test(WCHAR *formatstr, INT64 param, char *paramdesc, } } -void DoDoubleTest(WCHAR *formatstr, double value, WCHAR *checkstr1, - WCHAR *checkstr2) +void DoDoubleTest(const WCHAR *formatstr, double value, const WCHAR *checkstr1, + const WCHAR *checkstr2) { WCHAR buf[256] = { 0 }; @@ -166,8 +166,8 @@ void DoDoubleTest(WCHAR *formatstr, double value, WCHAR *checkstr1, } } -void DoArgumentPrecTest(WCHAR *formatstr, int precision, void *param, - char *paramstr, WCHAR *checkstr1, WCHAR *checkstr2) +void DoArgumentPrecTest(const WCHAR *formatstr, int precision, void *param, + char *paramstr, const WCHAR *checkstr1, const WCHAR *checkstr2) { WCHAR buf[256]; @@ -182,8 +182,8 @@ void DoArgumentPrecTest(WCHAR *formatstr, int precision, void *param, } } -void DoArgumentPrecDoubleTest(WCHAR *formatstr, int precision, double param, - WCHAR *checkstr1, WCHAR *checkstr2) +void DoArgumentPrecDoubleTest(const WCHAR *formatstr, int precision, double param, + const WCHAR *checkstr1, const WCHAR *checkstr2) { WCHAR buf[256]; diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test1/CMakeLists.txt index fcf8160..c9be8c3 100644 --- a/src/pal/tests/palsuite/c_runtime/swprintf/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swprintf/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_swprintf_test1 diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/swprintf/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swprintf/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/swprintf/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test10/CMakeLists.txt index 302c5e5..2221083 100644 --- a/src/pal/tests/palsuite/c_runtime/swprintf/test10/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swprintf/test10/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test10.c + test10.cpp ) add_executable(paltest_swprintf_test10 diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/swprintf/test10/test10.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swprintf/test10/test10.c rename to src/pal/tests/palsuite/c_runtime/swprintf/test10/test10.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test11/CMakeLists.txt index 484d57e..96222a5 100644 --- a/src/pal/tests/palsuite/c_runtime/swprintf/test11/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swprintf/test11/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test11.c + test11.cpp ) add_executable(paltest_swprintf_test11 diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/swprintf/test11/test11.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swprintf/test11/test11.c rename to src/pal/tests/palsuite/c_runtime/swprintf/test11/test11.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test12/CMakeLists.txt index 6d45ee4..1ffe620 100644 --- a/src/pal/tests/palsuite/c_runtime/swprintf/test12/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swprintf/test12/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test12.c + test12.cpp ) add_executable(paltest_swprintf_test12 diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/swprintf/test12/test12.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swprintf/test12/test12.c rename to src/pal/tests/palsuite/c_runtime/swprintf/test12/test12.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test13/CMakeLists.txt index 20f6f0d..8699589 100644 --- a/src/pal/tests/palsuite/c_runtime/swprintf/test13/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swprintf/test13/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test13.c + test13.cpp ) add_executable(paltest_swprintf_test13 diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/swprintf/test13/test13.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swprintf/test13/test13.c rename to src/pal/tests/palsuite/c_runtime/swprintf/test13/test13.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test14/CMakeLists.txt index a052f60..2a4b848 100644 --- a/src/pal/tests/palsuite/c_runtime/swprintf/test14/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swprintf/test14/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test14.c + test14.cpp ) add_executable(paltest_swprintf_test14 diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/swprintf/test14/test14.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swprintf/test14/test14.c rename to src/pal/tests/palsuite/c_runtime/swprintf/test14/test14.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test15/CMakeLists.txt index 7bc2da1..22382bc 100644 --- a/src/pal/tests/palsuite/c_runtime/swprintf/test15/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swprintf/test15/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test15.c + test15.cpp ) add_executable(paltest_swprintf_test15 diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/swprintf/test15/test15.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swprintf/test15/test15.c rename to src/pal/tests/palsuite/c_runtime/swprintf/test15/test15.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test16/CMakeLists.txt index e6ad3ab..462f080 100644 --- a/src/pal/tests/palsuite/c_runtime/swprintf/test16/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swprintf/test16/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test16.c + test16.cpp ) add_executable(paltest_swprintf_test16 diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/swprintf/test16/test16.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swprintf/test16/test16.c rename to src/pal/tests/palsuite/c_runtime/swprintf/test16/test16.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test17/CMakeLists.txt index 401285b..c5b4d44 100644 --- a/src/pal/tests/palsuite/c_runtime/swprintf/test17/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swprintf/test17/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test17.c + test17.cpp ) add_executable(paltest_swprintf_test17 diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/swprintf/test17/test17.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swprintf/test17/test17.c rename to src/pal/tests/palsuite/c_runtime/swprintf/test17/test17.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test18/CMakeLists.txt index 210ab2c..6cdf576 100644 --- a/src/pal/tests/palsuite/c_runtime/swprintf/test18/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swprintf/test18/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test18.c + test18.cpp ) add_executable(paltest_swprintf_test18 diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/swprintf/test18/test18.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swprintf/test18/test18.c rename to src/pal/tests/palsuite/c_runtime/swprintf/test18/test18.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test19/CMakeLists.txt index b9d44a3..334b7b4 100644 --- a/src/pal/tests/palsuite/c_runtime/swprintf/test19/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swprintf/test19/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test19.c + test19.cpp ) add_executable(paltest_swprintf_test19 diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/swprintf/test19/test19.c deleted file mode 100644 index 5199cc3..0000000 --- a/src/pal/tests/palsuite/c_runtime/swprintf/test19/test19.c +++ /dev/null @@ -1,109 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test19.c -** -** Purpose: Tests swprintf with argument specified precision -** -** -**==========================================================================*/ - - - -#include -#include "../swprintf.h" - -/* - * Uses memcmp & wcslen - */ - -int __cdecl main(int argc, char *argv[]) -{ - int n = -1; - - if (PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - DoArgumentPrecTest(convert("%.*s"), 2, convert("bar"), "bar", - convert("ba"), convert("ba")); - DoArgumentPrecTest(convert("%.*S"), 2, "bar", "bar", convert("ba"), - convert("ba")); - DoArgumentPrecTest(convert("%.*n"), 3, &n, "pointer to int", convert(""), - convert("")); - if (n != 0) - { - Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", - 0, n); - } - - DoArgumentPrecTest(convert("%.*c"), 0, (void*)'a', "a", convert("a"), - convert("a")); - DoArgumentPrecTest(convert("%.*c"), 4, (void*)'a', "a", convert("a"), - convert("a")); - DoArgumentPrecTest(convert("%.*C"), 0, (void*)'a', "a", convert("a"), - convert("a")); - DoArgumentPrecTest(convert("%.*C"), 4, (void*)'a', "a", convert("a"), - convert("a")); - DoArgumentPrecTest(convert("%.*d"), 1, (void*)42, "42", convert("42"), - convert("42")); - DoArgumentPrecTest(convert("%.*d"), 3, (void*)42, "42", convert("042"), - convert("042")); - DoArgumentPrecTest(convert("%.*i"), 1, (void*)42, "42", convert("42"), - convert("42")); - DoArgumentPrecTest(convert("%.*i"), 3, (void*)42, "42", convert("042"), - convert("042")); - DoArgumentPrecTest(convert("%.*o"), 1, (void*)42, "42", convert("52"), - convert("52")); - DoArgumentPrecTest(convert("%.*o"), 3, (void*)42, "42", convert("052"), - convert("052")); - DoArgumentPrecTest(convert("%.*u"), 1, (void*)42, "42", convert("42"), - convert("42")); - DoArgumentPrecTest(convert("%.*u"), 3, (void*)42, "42", convert("042"), - convert("042")); - DoArgumentPrecTest(convert("%.*x"), 1, (void*)0x42, "0x42", convert("42"), - convert("42")); - DoArgumentPrecTest(convert("%.*x"), 3, (void*)0x42, "0x42", convert("042"), - convert("042")); - DoArgumentPrecTest(convert("%.*X"), 1, (void*)0x42, "0x42", convert("42"), - convert("42")); - DoArgumentPrecTest(convert("%.*X"), 3, (void*)0x42, "0x42", convert("042"), - convert("042")); - - - DoArgumentPrecDoubleTest(convert("%.*e"), 1, 2.01, convert("2.0e+000"), - convert("2.0e+000")); - DoArgumentPrecDoubleTest(convert("%.*e"), 3, 2.01, convert("2.010e+000"), - convert("2.010e+000")); - DoArgumentPrecDoubleTest(convert("%.*E"), 1, 2.01, convert("2.0E+000"), - convert("2.0E+000")); - DoArgumentPrecDoubleTest(convert("%.*E"), 3, 2.01, convert("2.010E+000"), - convert("2.010E+000")); - DoArgumentPrecDoubleTest(convert("%.*f"), 1, 2.01, convert("2.0"), - convert("2.0")); - DoArgumentPrecDoubleTest(convert("%.*f"), 3, 2.01, convert("2.010"), - convert("2.010")); - DoArgumentPrecDoubleTest(convert("%.*g"), 1, 256.01, convert("3e+002"), - convert("3e+002")); - DoArgumentPrecDoubleTest(convert("%.*g"), 3, 256.01, convert("256"), - convert("256")); - DoArgumentPrecDoubleTest(convert("%.*g"), 4, 256.01, convert("256"), - convert("256")); - DoArgumentPrecDoubleTest(convert("%.*g"), 6, 256.01, convert("256.01"), - convert("256.01")); - DoArgumentPrecDoubleTest(convert("%.*G"), 1, 256.01, convert("3E+002"), - convert("3E+002")); - DoArgumentPrecDoubleTest(convert("%.*G"), 3, 256.01, convert("256"), - convert("256")); - DoArgumentPrecDoubleTest(convert("%.*G"), 4, 256.01, convert("256"), - convert("256")); - DoArgumentPrecDoubleTest(convert("%.*G"), 6, 256.01, convert("256.01"), - convert("256.01")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test19/test19.cpp b/src/pal/tests/palsuite/c_runtime/swprintf/test19/test19.cpp new file mode 100644 index 0000000..c034603 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/swprintf/test19/test19.cpp @@ -0,0 +1,109 @@ +// 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. + +/*============================================================================ +** +** Source: test19.c +** +** Purpose: Tests swprintf with argument specified precision +** +** +**==========================================================================*/ + + + +#include +#include "../swprintf.h" + +/* + * Uses memcmp & wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + int n = -1; + + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + DoArgumentPrecTest(convert("%.*s"), 2, (void*)convert("bar"), "bar", + convert("ba"), convert("ba")); + DoArgumentPrecTest(convert("%.*S"), 2, (void*)"bar", "bar", convert("ba"), + convert("ba")); + DoArgumentPrecTest(convert("%.*n"), 3, (void*)&n, "pointer to int", convert(""), + convert("")); + if (n != 0) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + 0, n); + } + + DoArgumentPrecTest(convert("%.*c"), 0, (void*)'a', "a", convert("a"), + convert("a")); + DoArgumentPrecTest(convert("%.*c"), 4, (void*)'a', "a", convert("a"), + convert("a")); + DoArgumentPrecTest(convert("%.*C"), 0, (void*)'a', "a", convert("a"), + convert("a")); + DoArgumentPrecTest(convert("%.*C"), 4, (void*)'a', "a", convert("a"), + convert("a")); + DoArgumentPrecTest(convert("%.*d"), 1, (void*)42, "42", convert("42"), + convert("42")); + DoArgumentPrecTest(convert("%.*d"), 3, (void*)42, "42", convert("042"), + convert("042")); + DoArgumentPrecTest(convert("%.*i"), 1, (void*)42, "42", convert("42"), + convert("42")); + DoArgumentPrecTest(convert("%.*i"), 3, (void*)42, "42", convert("042"), + convert("042")); + DoArgumentPrecTest(convert("%.*o"), 1, (void*)42, "42", convert("52"), + convert("52")); + DoArgumentPrecTest(convert("%.*o"), 3, (void*)42, "42", convert("052"), + convert("052")); + DoArgumentPrecTest(convert("%.*u"), 1, (void*)42, "42", convert("42"), + convert("42")); + DoArgumentPrecTest(convert("%.*u"), 3, (void*)42, "42", convert("042"), + convert("042")); + DoArgumentPrecTest(convert("%.*x"), 1, (void*)0x42, "0x42", convert("42"), + convert("42")); + DoArgumentPrecTest(convert("%.*x"), 3, (void*)0x42, "0x42", convert("042"), + convert("042")); + DoArgumentPrecTest(convert("%.*X"), 1, (void*)0x42, "0x42", convert("42"), + convert("42")); + DoArgumentPrecTest(convert("%.*X"), 3, (void*)0x42, "0x42", convert("042"), + convert("042")); + + + DoArgumentPrecDoubleTest(convert("%.*e"), 1, 2.01, convert("2.0e+000"), + convert("2.0e+000")); + DoArgumentPrecDoubleTest(convert("%.*e"), 3, 2.01, convert("2.010e+000"), + convert("2.010e+000")); + DoArgumentPrecDoubleTest(convert("%.*E"), 1, 2.01, convert("2.0E+000"), + convert("2.0E+000")); + DoArgumentPrecDoubleTest(convert("%.*E"), 3, 2.01, convert("2.010E+000"), + convert("2.010E+000")); + DoArgumentPrecDoubleTest(convert("%.*f"), 1, 2.01, convert("2.0"), + convert("2.0")); + DoArgumentPrecDoubleTest(convert("%.*f"), 3, 2.01, convert("2.010"), + convert("2.010")); + DoArgumentPrecDoubleTest(convert("%.*g"), 1, 256.01, convert("3e+002"), + convert("3e+002")); + DoArgumentPrecDoubleTest(convert("%.*g"), 3, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*g"), 4, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*g"), 6, 256.01, convert("256.01"), + convert("256.01")); + DoArgumentPrecDoubleTest(convert("%.*G"), 1, 256.01, convert("3E+002"), + convert("3E+002")); + DoArgumentPrecDoubleTest(convert("%.*G"), 3, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*G"), 4, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*G"), 6, 256.01, convert("256.01"), + convert("256.01")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test2/CMakeLists.txt index 84446d5..af2b13e 100644 --- a/src/pal/tests/palsuite/c_runtime/swprintf/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swprintf/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_swprintf_test2 diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/swprintf/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swprintf/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/swprintf/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test3/CMakeLists.txt index 6dbd8a3..14b81f4 100644 --- a/src/pal/tests/palsuite/c_runtime/swprintf/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swprintf/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_swprintf_test3 diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/swprintf/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swprintf/test3/test3.c rename to src/pal/tests/palsuite/c_runtime/swprintf/test3/test3.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test4/CMakeLists.txt index a665948..e153e6b 100644 --- a/src/pal/tests/palsuite/c_runtime/swprintf/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swprintf/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_swprintf_test4 diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/swprintf/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swprintf/test4/test4.c rename to src/pal/tests/palsuite/c_runtime/swprintf/test4/test4.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test5/CMakeLists.txt index 8268ec2..967ccbb 100644 --- a/src/pal/tests/palsuite/c_runtime/swprintf/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swprintf/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_swprintf_test5 diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/swprintf/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swprintf/test5/test5.c rename to src/pal/tests/palsuite/c_runtime/swprintf/test5/test5.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test6/CMakeLists.txt index 6a90c0b..806211a 100644 --- a/src/pal/tests/palsuite/c_runtime/swprintf/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swprintf/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test6.c + test6.cpp ) add_executable(paltest_swprintf_test6 diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/swprintf/test6/test6.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swprintf/test6/test6.c rename to src/pal/tests/palsuite/c_runtime/swprintf/test6/test6.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test7/CMakeLists.txt index 2b1c30c..cf56379 100644 --- a/src/pal/tests/palsuite/c_runtime/swprintf/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swprintf/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test7.c + test7.cpp ) add_executable(paltest_swprintf_test7 diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/swprintf/test7/test7.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swprintf/test7/test7.c rename to src/pal/tests/palsuite/c_runtime/swprintf/test7/test7.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test8/CMakeLists.txt index 281e6df..e8fcf66 100644 --- a/src/pal/tests/palsuite/c_runtime/swprintf/test8/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swprintf/test8/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test8.c + test8.cpp ) add_executable(paltest_swprintf_test8 diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/swprintf/test8/test8.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swprintf/test8/test8.c rename to src/pal/tests/palsuite/c_runtime/swprintf/test8/test8.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swprintf/test9/CMakeLists.txt index 054b40a..c616348 100644 --- a/src/pal/tests/palsuite/c_runtime/swprintf/test9/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swprintf/test9/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test9.c + test9.cpp ) add_executable(paltest_swprintf_test9 diff --git a/src/pal/tests/palsuite/c_runtime/swprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/swprintf/test9/test9.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swprintf/test9/test9.c rename to src/pal/tests/palsuite/c_runtime/swprintf/test9/test9.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/swscanf.h b/src/pal/tests/palsuite/c_runtime/swscanf/swscanf.h index 1cac450..6349b7d 100644 --- a/src/pal/tests/palsuite/c_runtime/swscanf/swscanf.h +++ b/src/pal/tests/palsuite/c_runtime/swscanf/swscanf.h @@ -14,7 +14,7 @@ #ifndef __SWSCANF_H__ #define __SWSCANF_H__ -void DoVoidTest(WCHAR *inputstr, WCHAR *formatstr) +void DoVoidTest(WCHAR *inputstr, const WCHAR *formatstr) { char buf[256] = { 0 }; int i; @@ -40,7 +40,7 @@ void DoVoidTest(WCHAR *inputstr, WCHAR *formatstr) } -void DoStrTest(WCHAR *inputstr, WCHAR *formatstr, char *checkstr) +void DoStrTest(WCHAR *inputstr, const WCHAR *formatstr, const char *checkstr) { char buf[256] = { 0 }; int ret; @@ -63,7 +63,7 @@ void DoStrTest(WCHAR *inputstr, WCHAR *formatstr, char *checkstr) } -void DoWStrTest(WCHAR *inputstr, WCHAR *formatstr, WCHAR *checkstr) +void DoWStrTest(WCHAR *inputstr, const WCHAR *formatstr, const WCHAR *checkstr) { WCHAR buf[256] = { 0 }; int ret; @@ -86,7 +86,7 @@ void DoWStrTest(WCHAR *inputstr, WCHAR *formatstr, WCHAR *checkstr) } -void DoNumTest(WCHAR *inputstr, WCHAR *formatstr, int checknum) +void DoNumTest(WCHAR *inputstr, const WCHAR *formatstr, int checknum) { int num = 0; int ret; @@ -107,7 +107,7 @@ void DoNumTest(WCHAR *inputstr, WCHAR *formatstr, int checknum) } } -void DoShortNumTest(WCHAR *inputstr, WCHAR *formatstr, short checknum) +void DoShortNumTest(WCHAR *inputstr, const WCHAR *formatstr, short checknum) { short num = 0; int ret; @@ -128,7 +128,7 @@ void DoShortNumTest(WCHAR *inputstr, WCHAR *formatstr, short checknum) } } -void DoI64NumTest(WCHAR *inputstr, WCHAR *formatstr, INT64 checknum) +void DoI64NumTest(WCHAR *inputstr, const WCHAR *formatstr, INT64 checknum) { char buf[256]; char check[256]; @@ -145,15 +145,15 @@ void DoI64NumTest(WCHAR *inputstr, WCHAR *formatstr, INT64 checknum) if (checknum != num) { - sprintf(buf, "%I64d", num); - sprintf(check, "%I64d", checknum); + sprintf_s(buf, _countof(buf), "%I64d", num); + sprintf_s(check, _countof(check), "%I64d", checknum); Fail("ERROR: scanned I64 number incorrectly from \"%s\" using \"%s\".\n" "Expected %s, got %s.\n", convertC(inputstr), convertC(formatstr), check, buf); } } -void DoCharTest(WCHAR *inputstr, WCHAR*formatstr, char* checkchars, int numchars) +void DoCharTest(WCHAR *inputstr, const WCHAR *formatstr, char* checkchars, int numchars) { char buf[256]; int ret; @@ -187,7 +187,7 @@ void DoCharTest(WCHAR *inputstr, WCHAR*formatstr, char* checkchars, int numchars } } -void DoWCharTest(WCHAR *inputstr, WCHAR *formatstr, WCHAR *checkchars, int numchars) +void DoWCharTest(WCHAR *inputstr, const WCHAR *formatstr, const WCHAR *checkchars, int numchars) { WCHAR buf[256]; int ret; @@ -223,7 +223,7 @@ void DoWCharTest(WCHAR *inputstr, WCHAR *formatstr, WCHAR *checkchars, int numch } -void DoFloatTest(WCHAR *inputstr, WCHAR *formatstr, float checkval) +void DoFloatTest(WCHAR *inputstr, const WCHAR *formatstr, float checkval) { char buf[256] = { 0 }; float val; diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test1/CMakeLists.txt index 030aaaf..44b8939 100644 --- a/src/pal/tests/palsuite/c_runtime/swscanf/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swscanf/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_swscanf_test1 diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/swscanf/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swscanf/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/swscanf/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test10/CMakeLists.txt index f7c8b28..27d4211 100644 --- a/src/pal/tests/palsuite/c_runtime/swscanf/test10/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swscanf/test10/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test10.c + test10.cpp ) add_executable(paltest_swscanf_test10 diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/swscanf/test10/test10.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swscanf/test10/test10.c rename to src/pal/tests/palsuite/c_runtime/swscanf/test10/test10.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test11/CMakeLists.txt index 17066f3..1ca9224 100644 --- a/src/pal/tests/palsuite/c_runtime/swscanf/test11/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swscanf/test11/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test11.c + test11.cpp ) add_executable(paltest_swscanf_test11 diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/swscanf/test11/test11.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swscanf/test11/test11.c rename to src/pal/tests/palsuite/c_runtime/swscanf/test11/test11.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test12/CMakeLists.txt index 95f5174..44d70f4 100644 --- a/src/pal/tests/palsuite/c_runtime/swscanf/test12/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swscanf/test12/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test12.c + test12.cpp ) add_executable(paltest_swscanf_test12 diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/swscanf/test12/test12.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swscanf/test12/test12.c rename to src/pal/tests/palsuite/c_runtime/swscanf/test12/test12.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test13/CMakeLists.txt index 47abc50..add0cbf 100644 --- a/src/pal/tests/palsuite/c_runtime/swscanf/test13/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swscanf/test13/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test13.c + test13.cpp ) add_executable(paltest_swscanf_test13 diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/swscanf/test13/test13.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swscanf/test13/test13.c rename to src/pal/tests/palsuite/c_runtime/swscanf/test13/test13.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test14/CMakeLists.txt index a470436..126e087 100644 --- a/src/pal/tests/palsuite/c_runtime/swscanf/test14/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swscanf/test14/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test14.c + test14.cpp ) add_executable(paltest_swscanf_test14 diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/swscanf/test14/test14.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swscanf/test14/test14.c rename to src/pal/tests/palsuite/c_runtime/swscanf/test14/test14.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test15/CMakeLists.txt index d89650b..7c2da2b 100644 --- a/src/pal/tests/palsuite/c_runtime/swscanf/test15/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swscanf/test15/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test15.c + test15.cpp ) add_executable(paltest_swscanf_test15 diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/swscanf/test15/test15.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swscanf/test15/test15.c rename to src/pal/tests/palsuite/c_runtime/swscanf/test15/test15.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test16/CMakeLists.txt index a2a00f1..ba28c4d 100644 --- a/src/pal/tests/palsuite/c_runtime/swscanf/test16/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swscanf/test16/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test16.c + test16.cpp ) add_executable(paltest_swscanf_test16 diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/swscanf/test16/test16.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swscanf/test16/test16.c rename to src/pal/tests/palsuite/c_runtime/swscanf/test16/test16.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test17/CMakeLists.txt index c224f5d..225ce86 100644 --- a/src/pal/tests/palsuite/c_runtime/swscanf/test17/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swscanf/test17/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test17.c + test17.cpp ) add_executable(paltest_swscanf_test17 diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/swscanf/test17/test17.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swscanf/test17/test17.c rename to src/pal/tests/palsuite/c_runtime/swscanf/test17/test17.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test2/CMakeLists.txt index a5335dd..15411ec 100644 --- a/src/pal/tests/palsuite/c_runtime/swscanf/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swscanf/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_swscanf_test2 diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/swscanf/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swscanf/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/swscanf/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test3/CMakeLists.txt index 5c229c2..9270261 100644 --- a/src/pal/tests/palsuite/c_runtime/swscanf/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swscanf/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_swscanf_test3 diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/swscanf/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swscanf/test3/test3.c rename to src/pal/tests/palsuite/c_runtime/swscanf/test3/test3.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test4/CMakeLists.txt index 5e281aa..eec7016 100644 --- a/src/pal/tests/palsuite/c_runtime/swscanf/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swscanf/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_swscanf_test4 diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/swscanf/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swscanf/test4/test4.c rename to src/pal/tests/palsuite/c_runtime/swscanf/test4/test4.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test5/CMakeLists.txt index 8b259aa..3f022db 100644 --- a/src/pal/tests/palsuite/c_runtime/swscanf/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swscanf/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_swscanf_test5 diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/swscanf/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swscanf/test5/test5.c rename to src/pal/tests/palsuite/c_runtime/swscanf/test5/test5.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test6/CMakeLists.txt index c3fd869..c55666d 100644 --- a/src/pal/tests/palsuite/c_runtime/swscanf/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swscanf/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test6.c + test6.cpp ) add_executable(paltest_swscanf_test6 diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/swscanf/test6/test6.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swscanf/test6/test6.c rename to src/pal/tests/palsuite/c_runtime/swscanf/test6/test6.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test7/CMakeLists.txt index 0054130..adb0abe 100644 --- a/src/pal/tests/palsuite/c_runtime/swscanf/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swscanf/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test7.c + test7.cpp ) add_executable(paltest_swscanf_test7 diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/swscanf/test7/test7.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swscanf/test7/test7.c rename to src/pal/tests/palsuite/c_runtime/swscanf/test7/test7.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test8/CMakeLists.txt index d6aa631..a69c552 100644 --- a/src/pal/tests/palsuite/c_runtime/swscanf/test8/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swscanf/test8/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test8.c + test8.cpp ) add_executable(paltest_swscanf_test8 diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/swscanf/test8/test8.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swscanf/test8/test8.c rename to src/pal/tests/palsuite/c_runtime/swscanf/test8/test8.cpp diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/swscanf/test9/CMakeLists.txt index 4f7595a..70a9fe2 100644 --- a/src/pal/tests/palsuite/c_runtime/swscanf/test9/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/swscanf/test9/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test9.c + test9.cpp ) add_executable(paltest_swscanf_test9 diff --git a/src/pal/tests/palsuite/c_runtime/swscanf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/swscanf/test9/test9.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/swscanf/test9/test9.c rename to src/pal/tests/palsuite/c_runtime/swscanf/test9/test9.cpp diff --git a/src/pal/tests/palsuite/c_runtime/tan/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/tan/test1/CMakeLists.txt index 665fc22..cea661f 100644 --- a/src/pal/tests/palsuite/c_runtime/tan/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/tan/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_tan_test1 diff --git a/src/pal/tests/palsuite/c_runtime/tan/test1/test1.c b/src/pal/tests/palsuite/c_runtime/tan/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/tan/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/tan/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/tanf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/tanf/CMakeLists.txt new file mode 100644 index 0000000..5e1ef7f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/tanf/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) diff --git a/src/pal/tests/palsuite/c_runtime/tanf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/tanf/test1/CMakeLists.txt new file mode 100644 index 0000000..cd588ea --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/tanf/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_tanf_test1 + ${SOURCES} +) + +add_dependencies(paltest_tanf_test1 coreclrpal) + +target_link_libraries(paltest_tanf_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/tanf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/tanf/test1/test1.c new file mode 100644 index 0000000..18d5c4e --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/tanf/test1/test1.c @@ -0,0 +1,136 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that tanf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = tanf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("tanf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = tanf(value); + + if (!_isnanf(result)) + { + Fail("tanf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.318309886f, 0.329514733f, PAL_EPSILON }, // value: 1 / pi + { 0.434294482f, 0.463829067f, PAL_EPSILON }, // value: log10f(e) + { 0.636619772f, 0.739302950f, PAL_EPSILON }, // value: 2 / pi + { 0.693147181f, 0.830640878f, PAL_EPSILON }, // value: ln(2) + { 0.707106781f, 0.854510432f, PAL_EPSILON }, // value: 1 / sqrtf(2) + { 0.785398163f, 1, PAL_EPSILON * 10 }, // value: pi / 4 + { 1, 1.55740772f, PAL_EPSILON * 10 }, + { 1.12837917f, 2.11087684f, PAL_EPSILON * 10 }, // value: 2 / sqrtf(pi) + { 1.41421356f, 6.33411917f, PAL_EPSILON * 10 }, // value: sqrtf(2) + { 1.44269504f, 7.76357567f, PAL_EPSILON * 10 }, // value: logf2(e) + // SEE BELOW -- { 1.57079633f, PAL_POSINF, 0 }, // value: pi / 2 + { 2.30258509f, -1.11340715f, PAL_EPSILON * 10 }, // value: ln(10) + { 2.71828183f, -0.450549534f, PAL_EPSILON }, // value: e + { 3.14159265f, 0, PAL_EPSILON }, // value: pi + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + // -- SPECIAL CASE -- + // Normally, tanf(pi / 2) would return PAL_POSINF (atan2f(PAL_POSINF) does return (pi / 2)). + // However, it seems instead (on all supported systems), we get a different number entirely. + validate( 1.57079633f, -22877332.0, PAL_EPSILON * 100000000); + validate(-1.57079633f, 22877332.0, PAL_EPSILON * 100000000); + + validate_isnan(PAL_NEGINF); + validate_isnan(PAL_NAN); + validate_isnan(PAL_POSINF); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/tanf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/tanf/test1/testinfo.dat new file mode 100644 index 0000000..aa33232 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/tanf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = tanf +Name = Positive Test for tanf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to tanf() a series of angle value, checking that += each one return to correct value. diff --git a/src/pal/tests/palsuite/c_runtime/tanh/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/tanh/test1/CMakeLists.txt index f8e439d..9fe926d 100644 --- a/src/pal/tests/palsuite/c_runtime/tanh/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/tanh/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_tanh_test1 diff --git a/src/pal/tests/palsuite/c_runtime/tanh/test1/test1.c b/src/pal/tests/palsuite/c_runtime/tanh/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/tanh/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/tanh/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/tanhf/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/tanhf/CMakeLists.txt new file mode 100644 index 0000000..5e1ef7f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/tanhf/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) diff --git a/src/pal/tests/palsuite/c_runtime/tanhf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/tanhf/test1/CMakeLists.txt new file mode 100644 index 0000000..fd0af2a --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/tanhf/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_tanhf_test1 + ${SOURCES} +) + +add_dependencies(paltest_tanhf_test1 coreclrpal) + +target_link_libraries(paltest_tanhf_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/c_runtime/tanhf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/tanhf/test1/test1.c new file mode 100644 index 0000000..904729a --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/tanhf/test1/test1.c @@ -0,0 +1,129 @@ +// 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. + +/*============================================================================= +** +** Source: test1.c +** +** Purpose: Test to ensure that tanhf return the correct values +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** fabs +** +**===========================================================================*/ + +#include + +// binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this +// is slightly too accurate when writing tests meant to run against libm implementations +// for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. +// +// The tests themselves will take PAL_EPSILON and adjust it according to the expected result +// so that the delta used for comparison will compare the most significant digits and ignore +// any digits that are outside the double precision range (6-9 digits). + +// For example, a test with an expect result in the format of 0.xxxxxxxxx will use PAL_EPSILON +// for the variance, while an expected result in the format of 0.0xxxxxxxxx will use +// PAL_EPSILON / 10 and and expected result in the format of x.xxxxxx will use PAL_EPSILON * 10. +#define PAL_EPSILON 4.76837158e-07 + +#define PAL_NAN sqrtf(-1.0f) +#define PAL_POSINF -logf(0.0f) +#define PAL_NEGINF logf(0.0f) + +/** + * Helper test structure + */ +struct test +{ + float value; /* value to test the function with */ + float expected; /* expected result */ + float variance; /* maximum delta between the expected and actual result */ +}; + +/** + * validate + * + * test validation function + */ +void __cdecl validate(float value, float expected, float variance) +{ + float result = tanhf(value); + + /* + * The test is valid when the difference between result + * and expected is less than or equal to variance + */ + float delta = fabsf(result - expected); + + if (delta > variance) + { + Fail("tanhf(%g) returned %10.9g when it should have returned %10.9g", + value, result, expected); + } +} + +/** + * validate + * + * test validation function for values returning NaN + */ +void __cdecl validate_isnan(float value) +{ + float result = tanhf(value); + + if (!_isnanf(result)) + { + Fail("tanhf(%g) returned %10.9g when it should have returned %10.9g", + value, result, PAL_NAN); + } +} + +/** + * main + * + * executable entry point + */ +int __cdecl main(int argc, char **argv) +{ + struct test tests[] = + { + /* value expected variance */ + { 0, 0, PAL_EPSILON }, + { 0.318309886f, 0.307977913f, PAL_EPSILON }, // value: 1 / pi + { 0.434294482f, 0.408904012f, PAL_EPSILON }, // value: log10f(e) + { 0.636619772f, 0.562593600f, PAL_EPSILON }, // value: 2 / pi + { 0.693147181f, 0.6f, PAL_EPSILON }, // value: ln(2) + { 0.707106781f, 0.608859365f, PAL_EPSILON }, // value: 1 / sqrtf(2) + { 0.785398163f, 0.655794203f, PAL_EPSILON }, // value: pi / 4 + { 1, 0.761594156f, PAL_EPSILON }, + { 1.12837917f, 0.810463806f, PAL_EPSILON }, // value: 2 / sqrtf(pi) + { 1.41421356f, 0.888385562f, PAL_EPSILON }, // value: sqrtf(2) + { 1.44269504f, 0.894238946f, PAL_EPSILON }, // value: logf2(e) + { 1.57079633f, 0.917152336f, PAL_EPSILON }, // value: pi / 2 + { 2.30258509f, 0.980198020f, PAL_EPSILON }, // value: ln(10) + { 2.71828183f, 0.991328916f, PAL_EPSILON }, // value: e + { 3.14159265f, 0.996272076f, PAL_EPSILON }, // value: pi + { PAL_POSINF, 1, PAL_EPSILON * 10 } + }; + + /* PAL initialization */ + if (PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) + { + validate( tests[i].value, tests[i].expected, tests[i].variance); + validate(-tests[i].value, -tests[i].expected, tests[i].variance); + } + + validate_isnan(PAL_NAN); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/tanhf/test1/testinfo.dat b/src/pal/tests/palsuite/c_runtime/tanhf/test1/testinfo.dat new file mode 100644 index 0000000..6c7594f --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/tanhf/test1/testinfo.dat @@ -0,0 +1,13 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = C Runtime +Function = tanhf +Name = Positive Test for tanhf +TYPE = DEFAULT +EXE1 = test1 +Description += Passes to tanhf() a series of angle value, checking that += each one return to correct value. diff --git a/src/pal/tests/palsuite/c_runtime/time/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/time/test1/CMakeLists.txt index d495266..64df144 100644 --- a/src/pal/tests/palsuite/c_runtime/time/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/time/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_time_test1 diff --git a/src/pal/tests/palsuite/c_runtime/time/test1/test1.c b/src/pal/tests/palsuite/c_runtime/time/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/time/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/time/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/tolower/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/tolower/test1/CMakeLists.txt index 537f239..214a509 100644 --- a/src/pal/tests/palsuite/c_runtime/tolower/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/tolower/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_tolower_test1 diff --git a/src/pal/tests/palsuite/c_runtime/tolower/test1/test1.c b/src/pal/tests/palsuite/c_runtime/tolower/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/tolower/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/tolower/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/toupper/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/toupper/test1/CMakeLists.txt index e5aa375..3dd536c 100644 --- a/src/pal/tests/palsuite/c_runtime/toupper/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/toupper/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_toupper_test1 diff --git a/src/pal/tests/palsuite/c_runtime/toupper/test1/test1.c b/src/pal/tests/palsuite/c_runtime/toupper/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/toupper/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/toupper/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/towlower/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/towlower/test1/CMakeLists.txt index 2a3e6a0..77a4634 100644 --- a/src/pal/tests/palsuite/c_runtime/towlower/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/towlower/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_towlower_test1 diff --git a/src/pal/tests/palsuite/c_runtime/towlower/test1/test1.c b/src/pal/tests/palsuite/c_runtime/towlower/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/towlower/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/towlower/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/towupper/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/towupper/test1/CMakeLists.txt index 537efbe..6a2f813 100644 --- a/src/pal/tests/palsuite/c_runtime/towupper/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/towupper/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_towupper_test1 diff --git a/src/pal/tests/palsuite/c_runtime/towupper/test1/test1.c b/src/pal/tests/palsuite/c_runtime/towupper/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/towupper/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/towupper/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/ungetc/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ungetc/test1/CMakeLists.txt index da19397..0286f99 100644 --- a/src/pal/tests/palsuite/c_runtime/ungetc/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/ungetc/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - ungetc.c + ungetc.cpp ) add_executable(paltest_ungetc_test1 diff --git a/src/pal/tests/palsuite/c_runtime/ungetc/test1/ungetc.c b/src/pal/tests/palsuite/c_runtime/ungetc/test1/ungetc.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/ungetc/test1/ungetc.c rename to src/pal/tests/palsuite/c_runtime/ungetc/test1/ungetc.cpp diff --git a/src/pal/tests/palsuite/c_runtime/ungetc/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/ungetc/test2/CMakeLists.txt index 7b63423..0710074 100644 --- a/src/pal/tests/palsuite/c_runtime/ungetc/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/ungetc/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - ungetc.c + ungetc.cpp ) add_executable(paltest_ungetc_test2 diff --git a/src/pal/tests/palsuite/c_runtime/ungetc/test2/ungetc.c b/src/pal/tests/palsuite/c_runtime/ungetc/test2/ungetc.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/ungetc/test2/ungetc.c rename to src/pal/tests/palsuite/c_runtime/ungetc/test2/ungetc.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test1/CMakeLists.txt index 4c967fb..fcff4a2 100644 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_vfprintf_test1 diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vfprintf/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/vfprintf/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test10/CMakeLists.txt index e154107..97c7b16 100644 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/test10/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test10/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test10.c + test10.cpp ) add_executable(paltest_vfprintf_test10 diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test10/test10.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vfprintf/test10/test10.c rename to src/pal/tests/palsuite/c_runtime/vfprintf/test10/test10.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test11/CMakeLists.txt index f51f379..9250eb9 100644 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/test11/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test11/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test11.c + test11.cpp ) add_executable(paltest_vfprintf_test11 diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test11/test11.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vfprintf/test11/test11.c rename to src/pal/tests/palsuite/c_runtime/vfprintf/test11/test11.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test12/CMakeLists.txt index 3ef68cf..53d3488 100644 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/test12/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test12/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test12.c + test12.cpp ) add_executable(paltest_vfprintf_test12 diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test12/test12.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vfprintf/test12/test12.c rename to src/pal/tests/palsuite/c_runtime/vfprintf/test12/test12.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test13/CMakeLists.txt index cd34f66..c35813b 100644 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/test13/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test13/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test13.c + test13.cpp ) add_executable(paltest_vfprintf_test13 diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test13/test13.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vfprintf/test13/test13.c rename to src/pal/tests/palsuite/c_runtime/vfprintf/test13/test13.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test14/CMakeLists.txt index 396a463..bd91f50 100644 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/test14/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test14/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test14.c + test14.cpp ) add_executable(paltest_vfprintf_test14 diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test14/test14.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vfprintf/test14/test14.c rename to src/pal/tests/palsuite/c_runtime/vfprintf/test14/test14.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test15/CMakeLists.txt index b9ddbe3..30003b8 100644 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/test15/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test15/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test15.c + test15.cpp ) add_executable(paltest_vfprintf_test15 diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test15/test15.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vfprintf/test15/test15.c rename to src/pal/tests/palsuite/c_runtime/vfprintf/test15/test15.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test16/CMakeLists.txt index 0fd4177..a287f12 100644 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/test16/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test16/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test16.c + test16.cpp ) add_executable(paltest_vfprintf_test16 diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test16/test16.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vfprintf/test16/test16.c rename to src/pal/tests/palsuite/c_runtime/vfprintf/test16/test16.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test17/CMakeLists.txt index afc0b38..cf1afd9 100644 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/test17/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test17/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test17.c + test17.cpp ) add_executable(paltest_vfprintf_test17 diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test17/test17.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vfprintf/test17/test17.c rename to src/pal/tests/palsuite/c_runtime/vfprintf/test17/test17.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test18/CMakeLists.txt index 9e373b9..143eade 100644 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/test18/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test18/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test18.c + test18.cpp ) add_executable(paltest_vfprintf_test18 diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test18/test18.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vfprintf/test18/test18.c rename to src/pal/tests/palsuite/c_runtime/vfprintf/test18/test18.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test19/CMakeLists.txt index 3120c91..452d929 100644 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/test19/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test19/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test19.c + test19.cpp ) add_executable(paltest_vfprintf_test19 diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test19/test19.c deleted file mode 100644 index e88ce23..0000000 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/test19/test19.c +++ /dev/null @@ -1,76 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test19.c -** -** Purpose: Test #19 for the vfprintf function. Tests the variable length -** precision argument. -** -** -**==========================================================================*/ - - -#include -#include "../vfprintf.h" - - - - -int __cdecl main(int argc, char *argv[]) -{ - int n = -1; - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - DoArgumentPrecTest("%.*s", 2, "bar", "bar", "ba", "ba"); - DoArgumentPrecTest("%.*S", 2, convert("bar"), "bar", "ba", "ba"); - - DoArgumentPrecTest("%.*n ", 3, &n, "pointer to int", " ", " "); - if (n != 0) - { - Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", - 0, n); - } - - DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); - DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); - DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); - DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); - DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42"); - DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); - - - DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); - DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); - DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); - DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); - DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); - DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); - DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); - DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); - DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); - DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test19/test19.cpp b/src/pal/tests/palsuite/c_runtime/vfprintf/test19/test19.cpp new file mode 100644 index 0000000..d8e8f93 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test19/test19.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test19.c +** +** Purpose: Test #19 for the vfprintf function. Tests the variable length +** precision argument. +** +** +**==========================================================================*/ + + +#include +#include "../vfprintf.h" + + + + +int __cdecl main(int argc, char *argv[]) +{ + int n = -1; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoArgumentPrecTest("%.*s", 2, (void*)"bar", "bar", "ba", "ba"); + DoArgumentPrecTest("%.*S", 2, (void*)convert("bar"), "bar", "ba", "ba"); + + DoArgumentPrecTest("%.*n ", 3, (void*)&n, "pointer to int", " ", " "); + if (n != 0) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + 0, n); + } + + DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); + DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); + DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); + DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); + + + DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); + DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); + DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); + DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); + DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); + DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); + DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); + DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); + DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); + DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test2/CMakeLists.txt index 6e70009..b18fb71 100644 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_vfprintf_test2 diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vfprintf/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/vfprintf/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test3/CMakeLists.txt index 1a14d85..a8f7eb1 100644 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_vfprintf_test3 diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vfprintf/test3/test3.c rename to src/pal/tests/palsuite/c_runtime/vfprintf/test3/test3.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test4/CMakeLists.txt index c128594..60c3169 100644 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_vfprintf_test4 diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vfprintf/test4/test4.c rename to src/pal/tests/palsuite/c_runtime/vfprintf/test4/test4.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test5/CMakeLists.txt index 0cccdfd..5f516fe 100644 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_vfprintf_test5 diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vfprintf/test5/test5.c rename to src/pal/tests/palsuite/c_runtime/vfprintf/test5/test5.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test6/CMakeLists.txt index 2c036a4..7f0cc71 100644 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test6.c + test6.cpp ) add_executable(paltest_vfprintf_test6 diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test6/test6.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vfprintf/test6/test6.c rename to src/pal/tests/palsuite/c_runtime/vfprintf/test6/test6.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test7/CMakeLists.txt index ca483af..a2cd9a2 100644 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test7.c + test7.cpp ) add_executable(paltest_vfprintf_test7 diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test7/test7.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vfprintf/test7/test7.c rename to src/pal/tests/palsuite/c_runtime/vfprintf/test7/test7.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test8/CMakeLists.txt index 89459b4..a7b20ee 100644 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/test8/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test8/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test8.c + test8.cpp ) add_executable(paltest_vfprintf_test8 diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test8/test8.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vfprintf/test8/test8.c rename to src/pal/tests/palsuite/c_runtime/vfprintf/test8/test8.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vfprintf/test9/CMakeLists.txt index 3e3b5b9..242b635 100644 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/test9/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/test9/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test9.c + test9.cpp ) add_executable(paltest_vfprintf_test9 diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/vfprintf/test9/test9.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vfprintf/test9/test9.c rename to src/pal/tests/palsuite/c_runtime/vfprintf/test9/test9.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vfprintf/vfprintf.h b/src/pal/tests/palsuite/c_runtime/vfprintf/vfprintf.h index f4ae7a5..7901b08 100644 --- a/src/pal/tests/palsuite/c_runtime/vfprintf/vfprintf.h +++ b/src/pal/tests/palsuite/c_runtime/vfprintf/vfprintf.h @@ -14,7 +14,7 @@ #ifndef __vfprintf_H__ #define __vfprintf_H__ -int DoVfprintf(FILE *fp, char *format, ...) +int DoVfprintf(FILE *fp, const char *format, ...) { int retVal; va_list arglist; @@ -26,7 +26,7 @@ int DoVfprintf(FILE *fp, char *format, ...) return (retVal); } -void DoStrTest(char *formatstr, char* param, char *checkstr) +void DoStrTest(const char *formatstr, char* param, const char *checkstr) { FILE *fp; char buf[256] = { 0 }; @@ -57,7 +57,7 @@ void DoStrTest(char *formatstr, char* param, char *checkstr) fclose(fp); } -void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr) +void DoWStrTest(const char *formatstr, WCHAR* param, const char *checkstr) { FILE *fp; char buf[256] = { 0 }; @@ -89,8 +89,8 @@ void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr) } -void DoPointerTest(char *formatstr, void* param, char* paramstr, - char *checkstr1) +void DoPointerTest(const char *formatstr, void* param, char* paramstr, + const char *checkstr1) { FILE *fp; char buf[256] = { 0 }; @@ -130,7 +130,7 @@ void DoPointerTest(char *formatstr, void* param, char* paramstr, -void DoCountTest(char *formatstr, int param, char *checkstr) +void DoCountTest(const char *formatstr, int param, const char *checkstr) { FILE *fp; char buf[512] = { 0 }; @@ -173,7 +173,7 @@ void DoCountTest(char *formatstr, int param, char *checkstr) } } -void DoShortCountTest(char *formatstr, int param, char *checkstr) +void DoShortCountTest(const char *formatstr, int param, const char *checkstr) { FILE *fp; char buf[512] = { 0 }; @@ -217,7 +217,7 @@ void DoShortCountTest(char *formatstr, int param, char *checkstr) } -void DoCharTest(char *formatstr, char param, char *checkstr) +void DoCharTest(const char *formatstr, char param, const char *checkstr) { FILE *fp; char buf[256] = { 0 }; @@ -248,7 +248,7 @@ void DoCharTest(char *formatstr, char param, char *checkstr) fclose(fp); } -void DoWCharTest(char *formatstr, WCHAR param, char *checkstr) +void DoWCharTest(const char *formatstr, WCHAR param, const char *checkstr) { FILE *fp; char buf[256] = { 0 }; @@ -279,7 +279,7 @@ void DoWCharTest(char *formatstr, WCHAR param, char *checkstr) fclose(fp); } -void DoNumTest(char *formatstr, int value, char *checkstr) +void DoNumTest(const char *formatstr, int value, const char *checkstr) { FILE *fp; char buf[256] = { 0 }; @@ -310,7 +310,7 @@ void DoNumTest(char *formatstr, int value, char *checkstr) fclose(fp); } -void DoI64Test(char *formatstr, INT64 value, char *valuestr, char *checkstr1) +void DoI64Test(const char *formatstr, INT64 value, char *valuestr, const char *checkstr1) { FILE *fp; char buf[256] = { 0 }; @@ -341,8 +341,8 @@ void DoI64Test(char *formatstr, INT64 value, char *valuestr, char *checkstr1) fclose(fp); } -void DoDoubleTest(char *formatstr, double value, char *checkstr1, - char *checkstr2) +void DoDoubleTest(const char *formatstr, double value, const char *checkstr1, + const char *checkstr2) { FILE *fp; char buf[256] = { 0 }; @@ -376,8 +376,8 @@ void DoDoubleTest(char *formatstr, double value, char *checkstr1, } -void DoArgumentPrecTest(char *formatstr, int precision, void *param, - char *paramstr, char *checkstr1, char *checkstr2) +void DoArgumentPrecTest(const char *formatstr, int precision, void *param, + char *paramstr, const char *checkstr1, const char *checkstr2) { FILE *fp; char buf[256]; @@ -418,8 +418,8 @@ void DoArgumentPrecTest(char *formatstr, int precision, void *param, } -void DoArgumentPrecDoubleTest(char *formatstr, int precision, double param, - char *checkstr1, char *checkstr2) +void DoArgumentPrecDoubleTest(const char *formatstr, int precision, double param, + const char *checkstr1, const char *checkstr2) { FILE *fp; char buf[256]; diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test1/CMakeLists.txt index eabdf87..9d866e1 100644 --- a/src/pal/tests/palsuite/c_runtime/vprintf/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vprintf/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_vprintf_test1 diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/vprintf/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vprintf/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/vprintf/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test10/CMakeLists.txt index 47a21d9..4ed04b4 100644 --- a/src/pal/tests/palsuite/c_runtime/vprintf/test10/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vprintf/test10/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test10.c + test10.cpp ) add_executable(paltest_vprintf_test10 diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/vprintf/test10/test10.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vprintf/test10/test10.c rename to src/pal/tests/palsuite/c_runtime/vprintf/test10/test10.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test11/CMakeLists.txt index 4c750b7..5dc3c6d 100644 --- a/src/pal/tests/palsuite/c_runtime/vprintf/test11/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vprintf/test11/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test11.c + test11.cpp ) add_executable(paltest_vprintf_test11 diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/vprintf/test11/test11.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vprintf/test11/test11.c rename to src/pal/tests/palsuite/c_runtime/vprintf/test11/test11.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test12/CMakeLists.txt index 1feb886..a810429 100644 --- a/src/pal/tests/palsuite/c_runtime/vprintf/test12/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vprintf/test12/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test12.c + test12.cpp ) add_executable(paltest_vprintf_test12 diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/vprintf/test12/test12.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vprintf/test12/test12.c rename to src/pal/tests/palsuite/c_runtime/vprintf/test12/test12.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test13/CMakeLists.txt index cd7535a..df98081 100644 --- a/src/pal/tests/palsuite/c_runtime/vprintf/test13/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vprintf/test13/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test13.c + test13.cpp ) add_executable(paltest_vprintf_test13 diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/vprintf/test13/test13.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vprintf/test13/test13.c rename to src/pal/tests/palsuite/c_runtime/vprintf/test13/test13.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test14/CMakeLists.txt index 82cfd68..b903d4e 100644 --- a/src/pal/tests/palsuite/c_runtime/vprintf/test14/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vprintf/test14/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test14.c + test14.cpp ) add_executable(paltest_vprintf_test14 diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/vprintf/test14/test14.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vprintf/test14/test14.c rename to src/pal/tests/palsuite/c_runtime/vprintf/test14/test14.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test15/CMakeLists.txt index 29a134d..659ed9c 100644 --- a/src/pal/tests/palsuite/c_runtime/vprintf/test15/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vprintf/test15/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test15.c + test15.cpp ) add_executable(paltest_vprintf_test15 diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/vprintf/test15/test15.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vprintf/test15/test15.c rename to src/pal/tests/palsuite/c_runtime/vprintf/test15/test15.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test16/CMakeLists.txt index 7fbf43a..b2f7fe8 100644 --- a/src/pal/tests/palsuite/c_runtime/vprintf/test16/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vprintf/test16/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test16.c + test16.cpp ) add_executable(paltest_vprintf_test16 diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/vprintf/test16/test16.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vprintf/test16/test16.c rename to src/pal/tests/palsuite/c_runtime/vprintf/test16/test16.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test17/CMakeLists.txt index 25970cb..76cfc9a 100644 --- a/src/pal/tests/palsuite/c_runtime/vprintf/test17/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vprintf/test17/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test17.c + test17.cpp ) add_executable(paltest_vprintf_test17 diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/vprintf/test17/test17.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vprintf/test17/test17.c rename to src/pal/tests/palsuite/c_runtime/vprintf/test17/test17.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test18/CMakeLists.txt index 45676b9..633fb7e 100644 --- a/src/pal/tests/palsuite/c_runtime/vprintf/test18/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vprintf/test18/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test18.c + test18.cpp ) add_executable(paltest_vprintf_test18 diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/vprintf/test18/test18.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vprintf/test18/test18.c rename to src/pal/tests/palsuite/c_runtime/vprintf/test18/test18.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test19/CMakeLists.txt index 25bc2fc..1a6256a 100644 --- a/src/pal/tests/palsuite/c_runtime/vprintf/test19/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vprintf/test19/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test19.c + test19.cpp ) add_executable(paltest_vprintf_test19 diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/vprintf/test19/test19.c deleted file mode 100644 index d79f2e2..0000000 --- a/src/pal/tests/palsuite/c_runtime/vprintf/test19/test19.c +++ /dev/null @@ -1,76 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test19.c -** -** Purpose: Test #19 for the vprintf function. Tests the variable length -** precision argument. -** -** -**==========================================================================*/ - - -#include -#include "../vprintf.h" - - - - -int __cdecl main(int argc, char *argv[]) -{ - int n = -1; - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - DoArgumentPrecTest("%.*s", 2, "bar", "bar", "ba", "ba"); - DoArgumentPrecTest("%.*S", 2, convert("bar"), "bar", "ba", "ba"); - - DoArgumentPrecTest("%.*n", 3, &n, "pointer to int", "", ""); - if (n != 0) - { - Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", - 0, n); - } - - DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); - DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); - DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); - DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); - DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42"); - DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); - - - DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); - DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); - DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); - DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); - DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); - DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); - DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); - DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); - DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); - DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test19/test19.cpp b/src/pal/tests/palsuite/c_runtime/vprintf/test19/test19.cpp new file mode 100644 index 0000000..a3e0877 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/vprintf/test19/test19.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================================ +** +** Source: test19.c +** +** Purpose: Test #19 for the vprintf function. Tests the variable length +** precision argument. +** +** +**==========================================================================*/ + + +#include +#include "../vprintf.h" + + + + +int __cdecl main(int argc, char *argv[]) +{ + int n = -1; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + DoArgumentPrecTest("%.*s", 2, (void*)"bar", "bar", "ba", "ba"); + DoArgumentPrecTest("%.*S", 2, (void*)convert("bar"), "bar", "ba", "ba"); + + DoArgumentPrecTest("%.*n", 3, (void*)&n, "pointer to int", "", ""); + if (n != 0) + { + Fail("ERROR: Expected count parameter to resolve to %d, got %X\n", + 0, n); + } + + DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); + DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); + DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); + DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); + + + DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); + DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); + DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); + DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); + DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); + DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); + DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); + DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); + DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); + DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test2/CMakeLists.txt index 6820069..41e2073 100644 --- a/src/pal/tests/palsuite/c_runtime/vprintf/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vprintf/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_vprintf_test2 diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/vprintf/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vprintf/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/vprintf/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test3/CMakeLists.txt index 676d19b..8570666 100644 --- a/src/pal/tests/palsuite/c_runtime/vprintf/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vprintf/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_vprintf_test3 diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/vprintf/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vprintf/test3/test3.c rename to src/pal/tests/palsuite/c_runtime/vprintf/test3/test3.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test4/CMakeLists.txt index 9ddb087..06b582b 100644 --- a/src/pal/tests/palsuite/c_runtime/vprintf/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vprintf/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_vprintf_test4 diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/vprintf/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vprintf/test4/test4.c rename to src/pal/tests/palsuite/c_runtime/vprintf/test4/test4.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test5/CMakeLists.txt index f453bb6..3a1828a 100644 --- a/src/pal/tests/palsuite/c_runtime/vprintf/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vprintf/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_vprintf_test5 diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/vprintf/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vprintf/test5/test5.c rename to src/pal/tests/palsuite/c_runtime/vprintf/test5/test5.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test6/CMakeLists.txt index 1ce8d5a..2dac770 100644 --- a/src/pal/tests/palsuite/c_runtime/vprintf/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vprintf/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test6.c + test6.cpp ) add_executable(paltest_vprintf_test6 diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/vprintf/test6/test6.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vprintf/test6/test6.c rename to src/pal/tests/palsuite/c_runtime/vprintf/test6/test6.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test7/CMakeLists.txt index 5627fe4..5a52004 100644 --- a/src/pal/tests/palsuite/c_runtime/vprintf/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vprintf/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test7.c + test7.cpp ) add_executable(paltest_vprintf_test7 diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/vprintf/test7/test7.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vprintf/test7/test7.c rename to src/pal/tests/palsuite/c_runtime/vprintf/test7/test7.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test8/CMakeLists.txt index 0131e49..18e4e3a 100644 --- a/src/pal/tests/palsuite/c_runtime/vprintf/test8/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vprintf/test8/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test8.c + test8.cpp ) add_executable(paltest_vprintf_test8 diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/vprintf/test8/test8.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vprintf/test8/test8.c rename to src/pal/tests/palsuite/c_runtime/vprintf/test8/test8.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vprintf/test9/CMakeLists.txt index c70631f..8bcbe81 100644 --- a/src/pal/tests/palsuite/c_runtime/vprintf/test9/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vprintf/test9/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test9.c + test9.cpp ) add_executable(paltest_vprintf_test9 diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/vprintf/test9/test9.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vprintf/test9/test9.c rename to src/pal/tests/palsuite/c_runtime/vprintf/test9/test9.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vprintf/vprintf.h b/src/pal/tests/palsuite/c_runtime/vprintf/vprintf.h index 477db32..fcd8f80 100644 --- a/src/pal/tests/palsuite/c_runtime/vprintf/vprintf.h +++ b/src/pal/tests/palsuite/c_runtime/vprintf/vprintf.h @@ -14,7 +14,7 @@ #ifndef __vprintf_H__ #define __vprintf_H__ -int DoVprintf(char *format, ...) +int DoVprintf(const char *format, ...) { int retVal; va_list arglist; @@ -26,7 +26,7 @@ int DoVprintf(char *format, ...) return (retVal); } -void DoStrTest(char *formatstr, char* param, char *checkstr) +void DoStrTest(const char *formatstr, char* param, const char *checkstr) { int ret; @@ -38,7 +38,7 @@ void DoStrTest(char *formatstr, char* param, char *checkstr) } } -void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr) +void DoWStrTest(const char *formatstr, WCHAR* param, const char *checkstr) { int ret; @@ -50,8 +50,8 @@ void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr) } } -void DoPointerTest(char *formatstr, void* param, char* paramstr, - char *checkstr1) +void DoPointerTest(const char *formatstr, void* param, char* paramstr, + const char *checkstr1) { int ret; @@ -63,7 +63,7 @@ void DoPointerTest(char *formatstr, void* param, char* paramstr, } } -void DoCountTest(char *formatstr, int param, char *checkstr) +void DoCountTest(const char *formatstr, int param, const char *checkstr) { int ret; int n = -1; @@ -82,7 +82,7 @@ void DoCountTest(char *formatstr, int param, char *checkstr) } } -void DoShortCountTest(char *formatstr, int param, char *checkstr) +void DoShortCountTest(const char *formatstr, int param, const char *checkstr) { int ret; short int n = -1; @@ -102,7 +102,7 @@ void DoShortCountTest(char *formatstr, int param, char *checkstr) } -void DoCharTest(char *formatstr, char param, char *checkstr) +void DoCharTest(const char *formatstr, char param, const char *checkstr) { int ret; @@ -114,7 +114,7 @@ void DoCharTest(char *formatstr, char param, char *checkstr) } } -void DoWCharTest(char *formatstr, WCHAR param, char *checkstr) +void DoWCharTest(const char *formatstr, WCHAR param, const char *checkstr) { int ret; @@ -126,7 +126,7 @@ void DoWCharTest(char *formatstr, WCHAR param, char *checkstr) } } -void DoNumTest(char *formatstr, int param, char *checkstr) +void DoNumTest(const char *formatstr, int param, const char *checkstr) { int ret; @@ -138,7 +138,7 @@ void DoNumTest(char *formatstr, int param, char *checkstr) } } -void DoI64Test(char *formatstr, INT64 param, char *valuestr, char *checkstr1) +void DoI64Test(const char *formatstr, INT64 param, char *valuestr, const char *checkstr1) { int ret; @@ -150,8 +150,8 @@ void DoI64Test(char *formatstr, INT64 param, char *valuestr, char *checkstr1) } } -void DoDoubleTest(char *formatstr, double param, char *checkstr1, - char *checkstr2) +void DoDoubleTest(const char *formatstr, double param, const char *checkstr1, + const char *checkstr2) { int ret; @@ -163,8 +163,8 @@ void DoDoubleTest(char *formatstr, double param, char *checkstr1, } } -void DoArgumentPrecTest(char *formatstr, int precision, void *param, - char *paramstr, char *checkstr1, char *checkstr2) +void DoArgumentPrecTest(const char *formatstr, int precision, void *param, + char *paramstr, const char *checkstr1, const char *checkstr2) { int ret; @@ -176,8 +176,8 @@ void DoArgumentPrecTest(char *formatstr, int precision, void *param, } } -void DoArgumentPrecDoubleTest(char *formatstr, int precision, double param, - char *checkstr1, char *checkstr2) +void DoArgumentPrecDoubleTest(const char *formatstr, int precision, double param, + const char *checkstr1, const char *checkstr2) { int ret; diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test1/CMakeLists.txt index 4f0872e..6861157 100644 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_vsprintf_test1 diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vsprintf/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/vsprintf/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test10/CMakeLists.txt index d32de01..6f535a5 100644 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/test10/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test10/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test10.c + test10.cpp ) add_executable(paltest_vsprintf_test10 diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test10/test10.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vsprintf/test10/test10.c rename to src/pal/tests/palsuite/c_runtime/vsprintf/test10/test10.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test11/CMakeLists.txt index ce67444..3fa628f 100644 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/test11/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test11/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test11.c + test11.cpp ) add_executable(paltest_vsprintf_test11 diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test11/test11.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vsprintf/test11/test11.c rename to src/pal/tests/palsuite/c_runtime/vsprintf/test11/test11.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test12/CMakeLists.txt index fe6ccb8..f34f76a 100644 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/test12/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test12/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test12.c + test12.cpp ) add_executable(paltest_vsprintf_test12 diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test12/test12.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vsprintf/test12/test12.c rename to src/pal/tests/palsuite/c_runtime/vsprintf/test12/test12.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test13/CMakeLists.txt index 97fdf8c..df23693 100644 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/test13/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test13/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test13.c + test13.cpp ) add_executable(paltest_vsprintf_test13 diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test13/test13.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vsprintf/test13/test13.c rename to src/pal/tests/palsuite/c_runtime/vsprintf/test13/test13.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test14/CMakeLists.txt index 2851a88..394b5ab 100644 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/test14/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test14/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test14.c + test14.cpp ) add_executable(paltest_vsprintf_test14 diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test14/test14.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vsprintf/test14/test14.c rename to src/pal/tests/palsuite/c_runtime/vsprintf/test14/test14.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test15/CMakeLists.txt index 6fb1d32..4793b45 100644 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/test15/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test15/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test15.c + test15.cpp ) add_executable(paltest_vsprintf_test15 diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test15/test15.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vsprintf/test15/test15.c rename to src/pal/tests/palsuite/c_runtime/vsprintf/test15/test15.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test16/CMakeLists.txt index ccc2137..6a0a52d 100644 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/test16/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test16/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test16.c + test16.cpp ) add_executable(paltest_vsprintf_test16 diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test16/test16.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vsprintf/test16/test16.c rename to src/pal/tests/palsuite/c_runtime/vsprintf/test16/test16.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test17/CMakeLists.txt index 4c9dcd9..4e220da 100644 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/test17/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test17/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test17.c + test17.cpp ) add_executable(paltest_vsprintf_test17 diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test17/test17.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vsprintf/test17/test17.c rename to src/pal/tests/palsuite/c_runtime/vsprintf/test17/test17.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test18/CMakeLists.txt index 2e8610d..4dd68c2 100644 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/test18/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test18/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test18.c + test18.cpp ) add_executable(paltest_vsprintf_test18 diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test18/test18.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vsprintf/test18/test18.c rename to src/pal/tests/palsuite/c_runtime/vsprintf/test18/test18.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test19/CMakeLists.txt index 92e39ab..3156a59 100644 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/test19/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test19/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test19.c + test19.cpp ) add_executable(paltest_vsprintf_test19 diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test19/test19.c deleted file mode 100644 index 18590ed..0000000 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/test19/test19.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*===================================================================== -** -** Source: test19.c -** -** Purpose: Test #19 for the vsprintf function. -** -** -**===================================================================*/ - -#include -#include "../vsprintf.h" - -/* - * Notes: memcmp is used, as is strlen. - */ - -int __cdecl main(int argc, char *argv[]) -{ - - if (PAL_Initialize(argc, argv) != 0) - { - return(FAIL); - } - - - DoArgumentPrecTest("%.*s", 2, "bar", "bar", "ba", "ba"); - DoArgumentPrecTest("%.*S", 2, convert("bar"), "bar", "ba", "ba"); - DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); - DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); - DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); - DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); - DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); - DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); - DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); - DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42"); - DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); - - - DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); - DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); - DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); - DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); - DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); - DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); - DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); - DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); - DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); - DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); - DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test19/test19.cpp b/src/pal/tests/palsuite/c_runtime/vsprintf/test19/test19.cpp new file mode 100644 index 0000000..698ff36 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test19/test19.cpp @@ -0,0 +1,67 @@ +// 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. + +/*===================================================================== +** +** Source: test19.c +** +** Purpose: Test #19 for the vsprintf function. +** +** +**===================================================================*/ + +#include +#include "../vsprintf.h" + +/* + * Notes: memcmp is used, as is strlen. + */ + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + { + return(FAIL); + } + + + DoArgumentPrecTest("%.*s", 2, (void*)"bar", "bar", "ba", "ba"); + DoArgumentPrecTest("%.*S", 2, (void*)convert("bar"), "bar", "ba", "ba"); + DoArgumentPrecTest("%.*c", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*c", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 0, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*C", 4, (void*)'a', "a", "a", "a"); + DoArgumentPrecTest("%.*d", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*d", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*i", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*i", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*o", 1, (void*)42, "42", "52", "52"); + DoArgumentPrecTest("%.*o", 3, (void*)42, "42", "052", "052"); + DoArgumentPrecTest("%.*u", 1, (void*)42, "42", "42", "42"); + DoArgumentPrecTest("%.*u", 3, (void*)42, "42", "042", "042"); + DoArgumentPrecTest("%.*x", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*x", 3, (void*)0x42, "0x42", "042", "042"); + DoArgumentPrecTest("%.*X", 1, (void*)0x42, "0x42", "42", "42"); + DoArgumentPrecTest("%.*X", 3, (void*)0x42, "0x42", "042", "042"); + + + DoArgumentPrecDoubleTest("%.*e", 1, 2.01, "2.0e+000", "2.0e+00"); + DoArgumentPrecDoubleTest("%.*e", 3, 2.01, "2.010e+000", "2.010e+00"); + DoArgumentPrecDoubleTest("%.*E", 1, 2.01, "2.0E+000", "2.0E+00"); + DoArgumentPrecDoubleTest("%.*E", 3, 2.01, "2.010E+000", "2.010E+00"); + DoArgumentPrecDoubleTest("%.*f", 1, 2.01, "2.0", "2.0"); + DoArgumentPrecDoubleTest("%.*f", 3, 2.01, "2.010", "2.010"); + DoArgumentPrecDoubleTest("%.*g", 1, 256.01, "3e+002", "3e+02"); + DoArgumentPrecDoubleTest("%.*g", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*g", 6, 256.01, "256.01", "256.01"); + DoArgumentPrecDoubleTest("%.*G", 1, 256.01, "3E+002", "3E+02"); + DoArgumentPrecDoubleTest("%.*G", 3, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 4, 256.01, "256", "256"); + DoArgumentPrecDoubleTest("%.*G", 6, 256.01, "256.01", "256.01"); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test2/CMakeLists.txt index 2308bc2..210224f 100644 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_vsprintf_test2 diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vsprintf/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/vsprintf/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test3/CMakeLists.txt index aef2417..5581051 100644 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_vsprintf_test3 diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vsprintf/test3/test3.c rename to src/pal/tests/palsuite/c_runtime/vsprintf/test3/test3.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test4/CMakeLists.txt index 9570255..88817fc 100644 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_vsprintf_test4 diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vsprintf/test4/test4.c rename to src/pal/tests/palsuite/c_runtime/vsprintf/test4/test4.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test5/CMakeLists.txt index 34a3e62..6d14bf7 100644 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_vsprintf_test5 diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vsprintf/test5/test5.c rename to src/pal/tests/palsuite/c_runtime/vsprintf/test5/test5.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test6/CMakeLists.txt index dccca0b..606fe3b 100644 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test6.c + test6.cpp ) add_executable(paltest_vsprintf_test6 diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test6/test6.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vsprintf/test6/test6.c rename to src/pal/tests/palsuite/c_runtime/vsprintf/test6/test6.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test7/CMakeLists.txt index 7f18de0..2dee276 100644 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test7.c + test7.cpp ) add_executable(paltest_vsprintf_test7 diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test7/test7.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vsprintf/test7/test7.c rename to src/pal/tests/palsuite/c_runtime/vsprintf/test7/test7.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test8/CMakeLists.txt index 34c92e1..8dac76f 100644 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/test8/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test8/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test8.c + test8.cpp ) add_executable(paltest_vsprintf_test8 diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test8/test8.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vsprintf/test8/test8.c rename to src/pal/tests/palsuite/c_runtime/vsprintf/test8/test8.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vsprintf/test9/CMakeLists.txt index 1fe177d..95f0faa 100644 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/test9/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/test9/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test9.c + test9.cpp ) add_executable(paltest_vsprintf_test9 diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/vsprintf/test9/test9.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vsprintf/test9/test9.c rename to src/pal/tests/palsuite/c_runtime/vsprintf/test9/test9.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vsprintf/vsprintf.h b/src/pal/tests/palsuite/c_runtime/vsprintf/vsprintf.h index 10648d8..7b04a77 100644 --- a/src/pal/tests/palsuite/c_runtime/vsprintf/vsprintf.h +++ b/src/pal/tests/palsuite/c_runtime/vsprintf/vsprintf.h @@ -26,7 +26,7 @@ int testvsp(char* buf, const char* format, ...) return (retVal); } -void DoStrTest(char *formatstr, char* param, char *checkstr) +void DoStrTest(const char *formatstr, char* param, const char *checkstr) { char buf[256] = { 0 }; @@ -39,7 +39,7 @@ void DoStrTest(char *formatstr, char* param, char *checkstr) } } -void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr) +void DoWStrTest(const char *formatstr, WCHAR* param, const char *checkstr) { char buf[256] = { 0 }; @@ -53,7 +53,7 @@ void DoWStrTest(char *formatstr, WCHAR* param, char *checkstr) } -void DoCharTest(char *formatstr, char param, char *checkstr) +void DoCharTest(const char *formatstr, char param, const char *checkstr) { char buf[256] = { 0 }; @@ -66,7 +66,7 @@ void DoCharTest(char *formatstr, char param, char *checkstr) } } -void DoWCharTest(char *formatstr, WCHAR param, char *checkstr) +void DoWCharTest(const char *formatstr, WCHAR param, const char *checkstr) { char buf[256] = { 0 }; @@ -79,7 +79,7 @@ void DoWCharTest(char *formatstr, WCHAR param, char *checkstr) } } -void DoNumTest(char *formatstr, int value, char *checkstr) +void DoNumTest(const char *formatstr, int value, const char *checkstr) { char buf[256] = { 0 }; @@ -92,7 +92,7 @@ void DoNumTest(char *formatstr, int value, char *checkstr) } } -void DoI64Test(char *formatstr, INT64 value, char *valuestr, char *checkstr) +void DoI64Test(const char *formatstr, INT64 value, char *valuestr, const char *checkstr) { char buf[256] = { 0 }; @@ -104,7 +104,7 @@ void DoI64Test(char *formatstr, INT64 value, char *valuestr, char *checkstr) valuestr, formatstr, checkstr, buf); } } -void DoDoubleTest(char *formatstr, double value, char *checkstr1, char +void DoDoubleTest(const char *formatstr, double value, const char *checkstr1, char *checkstr2) { char buf[256] = { 0 }; @@ -119,8 +119,8 @@ void DoDoubleTest(char *formatstr, double value, char *checkstr1, char } } /*FROM TEST 9*/ -void DoArgumentPrecTest(char *formatstr, int precision, void *param, - char *paramstr, char *checkstr1, char *checkstr2) +void DoArgumentPrecTest(const char *formatstr, int precision, void *param, + char *paramstr, const char *checkstr1, const char *checkstr2) { char buf[256]; @@ -135,8 +135,8 @@ void DoArgumentPrecTest(char *formatstr, int precision, void *param, } -void DoArgumentPrecDoubleTest(char *formatstr, int precision, double param, - char *checkstr1, char *checkstr2) +void DoArgumentPrecDoubleTest(const char *formatstr, int precision, double param, + const char *checkstr1, const char *checkstr2) { char buf[256]; @@ -150,8 +150,8 @@ void DoArgumentPrecDoubleTest(char *formatstr, int precision, double param, } } /*FROM TEST4*/ -void DoPointerTest(char *formatstr, void* param, char* paramstr, - char *checkstr1) +void DoPointerTest(const char *formatstr, void* param, char* paramstr, + const char *checkstr1) { char buf[256] = { 0 }; @@ -164,8 +164,8 @@ void DoPointerTest(char *formatstr, void* param, char* paramstr, } } -void DoI64DoubleTest(char *formatstr, INT64 value, char *valuestr, - char *checkstr1) +void DoI64DoubleTest(const char *formatstr, INT64 value, char *valuestr, + const char *checkstr1) { char buf[256] = { 0 }; @@ -178,7 +178,7 @@ void DoI64DoubleTest(char *formatstr, INT64 value, char *valuestr, } } -void DoTest(char *formatstr, int param, char *checkstr) +void DoTest(const char *formatstr, int param, const char *checkstr) { char buf[256] = { 0 }; int n = -1; @@ -196,7 +196,7 @@ void DoTest(char *formatstr, int param, char *checkstr) } } -void DoShortTest(char *formatstr, int param, char *checkstr) +void DoShortTest(const char *formatstr, int param, const char *checkstr) { char buf[256] = { 0 }; short int n = -1; diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test1/CMakeLists.txt index 97fbeb4..1d62337 100644 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_vswprintf_test1 diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vswprintf/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/vswprintf/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test10/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test10/CMakeLists.txt index 06c11f6..e530142 100644 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/test10/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test10/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test10.c + test10.cpp ) add_executable(paltest_vswprintf_test10 diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test10/test10.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test10/test10.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vswprintf/test10/test10.c rename to src/pal/tests/palsuite/c_runtime/vswprintf/test10/test10.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test11/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test11/CMakeLists.txt index 5237ba4..1cfadb9 100644 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/test11/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test11/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test11.c + test11.cpp ) add_executable(paltest_vswprintf_test11 diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test11/test11.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test11/test11.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vswprintf/test11/test11.c rename to src/pal/tests/palsuite/c_runtime/vswprintf/test11/test11.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test12/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test12/CMakeLists.txt index 26199c3..f5a582a 100644 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/test12/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test12/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test12.c + test12.cpp ) add_executable(paltest_vswprintf_test12 diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test12/test12.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test12/test12.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vswprintf/test12/test12.c rename to src/pal/tests/palsuite/c_runtime/vswprintf/test12/test12.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test13/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test13/CMakeLists.txt index d0acd98..5571d73 100644 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/test13/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test13/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test13.c + test13.cpp ) add_executable(paltest_vswprintf_test13 diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test13/test13.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test13/test13.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vswprintf/test13/test13.c rename to src/pal/tests/palsuite/c_runtime/vswprintf/test13/test13.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test14/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test14/CMakeLists.txt index 06c1267..234029e 100644 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/test14/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test14/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test14.c + test14.cpp ) add_executable(paltest_vswprintf_test14 diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test14/test14.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test14/test14.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vswprintf/test14/test14.c rename to src/pal/tests/palsuite/c_runtime/vswprintf/test14/test14.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test15/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test15/CMakeLists.txt index 05dc41b..b705268 100644 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/test15/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test15/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test15.c + test15.cpp ) add_executable(paltest_vswprintf_test15 diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test15/test15.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test15/test15.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vswprintf/test15/test15.c rename to src/pal/tests/palsuite/c_runtime/vswprintf/test15/test15.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test16/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test16/CMakeLists.txt index 3c42755..da296bc 100644 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/test16/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test16/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test16.c + test16.cpp ) add_executable(paltest_vswprintf_test16 diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test16/test16.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test16/test16.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vswprintf/test16/test16.c rename to src/pal/tests/palsuite/c_runtime/vswprintf/test16/test16.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test17/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test17/CMakeLists.txt index b94c466..02234c1 100644 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/test17/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test17/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test17.c + test17.cpp ) add_executable(paltest_vswprintf_test17 diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test17/test17.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test17/test17.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vswprintf/test17/test17.c rename to src/pal/tests/palsuite/c_runtime/vswprintf/test17/test17.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test18/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test18/CMakeLists.txt index 57cc8cc..0c0e5b5 100644 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/test18/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test18/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test18.c + test18.cpp ) add_executable(paltest_vswprintf_test18 diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test18/test18.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test18/test18.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vswprintf/test18/test18.c rename to src/pal/tests/palsuite/c_runtime/vswprintf/test18/test18.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test19/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test19/CMakeLists.txt index 2187b58..066db8a 100644 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/test19/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test19/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test19.c + test19.cpp ) add_executable(paltest_vswprintf_test19 diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test19/test19.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test19/test19.c deleted file mode 100644 index c00185b..0000000 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/test19/test19.c +++ /dev/null @@ -1,137 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: test18.c -** -** Purpose: Test #18 for the vswprintf function. -** -** -**===================================================================*/ - -#include -#include "../vswprintf.h" - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with wcslen */ - -#define DOTEST(a,b,c,d,e) DoTest(a,b,(void*)c,d,e) - -void DoArgumentPrecTest(WCHAR *formatstr, int precision, void *param, - WCHAR *paramstr, WCHAR *checkstr1, WCHAR *checkstr2) -{ - WCHAR buf[256]; - - testvswp(buf, formatstr, precision, param); - if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 && - memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0) - { - Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" - "Expected \"%s\" or \"%s\", got \"%s\".\n", - paramstr, - convertC(formatstr), - precision, - convertC(checkstr1), - convertC(checkstr2), - convertC(buf)); - } -} -void DoArgumentPrecDoubleTest(WCHAR *formatstr, int precision, double param, - WCHAR *checkstr1, WCHAR *checkstr2) -{ - WCHAR buf[256]; - - testvswp(buf, formatstr, precision, param); - if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 && - memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0) - { - Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" - "Expected \"%s\" or \"%s\", got \"%s\".\n", - param, convertC(formatstr), - precision, - convertC(checkstr1), - convertC(checkstr2), - convertC(buf)); - } -} - -/* - * Uses memcmp & wcslen - */ - -int __cdecl main(int argc, char *argv[]) -{ - - if (PAL_Initialize(argc, argv) != 0) - return(FAIL); - - DoArgumentPrecTest(convert("%.*s"), 2, convert("bar"), convert("bar"), - convert("ba"), convert("ba")); - DoArgumentPrecTest(convert("%.*c"), 0, (void*)'a', convert("a"), - convert("a"), convert("a")); - DoArgumentPrecTest(convert("%.*c"), 4, (void*)'a', convert("a"), - convert("a"), convert("a")); - DoArgumentPrecTest(convert("%.*C"), 0, (void*)'a', convert("a"), - convert("a"), convert("a")); - DoArgumentPrecTest(convert("%.*C"), 4, (void*)'a', convert("a"), - convert("a"), convert("a")); - DoArgumentPrecTest(convert("%.*d"), 1, (void*)42, convert("42"), - convert("42"), convert("42")); - DoArgumentPrecTest(convert("%.*d"), 3, (void*)42, convert("42"), - convert("042"), convert("042")); - DoArgumentPrecTest(convert("%.*i"), 1, (void*)42, convert("42"), - convert("42"), convert("42")); - DoArgumentPrecTest(convert("%.*i"), 3, (void*)42, convert("42"), - convert("042"), convert("042")); - DoArgumentPrecTest(convert("%.*o"), 1, (void*)42, convert("42"), - convert("52"), convert("52")); - DoArgumentPrecTest(convert("%.*o"), 3, (void*)42, convert("42"), - convert("052"), convert("052")); - DoArgumentPrecTest(convert("%.*u"), 1, (void*)42, convert("42"), - convert("42"), convert("42")); - DoArgumentPrecTest(convert("%.*u"), 3, (void*)42, convert("42"), - convert("042"), convert("042")); - DoArgumentPrecTest(convert("%.*x"), 1, (void*)0x42, convert("0x42"), - convert("42"), convert("42")); - DoArgumentPrecTest(convert("%.*x"), 3, (void*)0x42, convert("0x42"), - convert("042"), convert("042")); - DoArgumentPrecTest(convert("%.*X"), 1, (void*)0x42, convert("0x42"), - convert("42"), convert("42")); - DoArgumentPrecTest(convert("%.*X"), 3, (void*)0x42, convert("0x42"), - convert("042"), convert("042")); - - - DoArgumentPrecDoubleTest(convert("%.*e"), 1, 2.01, convert("2.0e+000"), - convert("2.0e+00")); - DoArgumentPrecDoubleTest(convert("%.*e"), 3, 2.01, convert("2.010e+000"), - convert("2.010e+00")); - DoArgumentPrecDoubleTest(convert("%.*E"), 1, 2.01, convert("2.0E+000"), - convert("2.0E+00")); - DoArgumentPrecDoubleTest(convert("%.*E"), 3, 2.01, convert("2.010E+000"), - convert("2.010E+00")); - DoArgumentPrecDoubleTest(convert("%.*f"), 1, 2.01, convert("2.0"), - convert("2.0")); - DoArgumentPrecDoubleTest(convert("%.*f"), 3, 2.01, convert("2.010"), - convert("2.010")); - DoArgumentPrecDoubleTest(convert("%.*g"), 1, 256.01, convert("3e+002"), - convert("3e+02")); - DoArgumentPrecDoubleTest(convert("%.*g"), 3, 256.01, convert("256"), - convert("256")); - DoArgumentPrecDoubleTest(convert("%.*g"), 4, 256.01, convert("256"), - convert("256")); - DoArgumentPrecDoubleTest(convert("%.*g"), 6, 256.01, convert("256.01"), - convert("256.01")); - DoArgumentPrecDoubleTest(convert("%.*G"), 1, 256.01, convert("3E+002"), - convert("3E+02")); - DoArgumentPrecDoubleTest(convert("%.*G"), 3, 256.01, convert("256"), - convert("256")); - DoArgumentPrecDoubleTest(convert("%.*G"), 4, 256.01, convert("256"), - convert("256")); - DoArgumentPrecDoubleTest(convert("%.*G"), 6, 256.01, convert("256.01"), - convert("256.01")); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test19/test19.cpp b/src/pal/tests/palsuite/c_runtime/vswprintf/test19/test19.cpp new file mode 100644 index 0000000..1d1c565 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test19/test19.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*===================================================================== +** +** Source: test18.c +** +** Purpose: Test #18 for the vswprintf function. +** +** +**===================================================================*/ + +#include +#include "../vswprintf.h" + +/* memcmp is used to verify the results, so this test is dependent on it. */ +/* ditto with wcslen */ + +#define DOTEST(a,b,c,d,e) DoTest(a,b,(void*)c,d,e) + +void DoArgumentPrecTest(WCHAR *formatstr, int precision, void *param, + WCHAR *paramstr, WCHAR *checkstr1, WCHAR *checkstr2) +{ + WCHAR buf[256]; + + testvswp(buf, formatstr, precision, param); + if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 && + memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0) + { + Fail("ERROR: failed to insert %s into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + paramstr, + convertC(formatstr), + precision, + convertC(checkstr1), + convertC(checkstr2), + convertC(buf)); + } +} +void DoArgumentPrecDoubleTest(WCHAR *formatstr, int precision, double param, + WCHAR *checkstr1, WCHAR *checkstr2) +{ + WCHAR buf[256]; + + testvswp(buf, formatstr, precision, param); + if (memcmp(buf, checkstr1, wcslen(checkstr1) + 2) != 0 && + memcmp(buf, checkstr2, wcslen(checkstr2) + 2) != 0) + { + Fail("ERROR: failed to insert %f into \"%s\" with precision %d\n" + "Expected \"%s\" or \"%s\", got \"%s\".\n", + param, convertC(formatstr), + precision, + convertC(checkstr1), + convertC(checkstr2), + convertC(buf)); + } +} + +/* + * Uses memcmp & wcslen + */ + +int __cdecl main(int argc, char *argv[]) +{ + + if (PAL_Initialize(argc, argv) != 0) + return(FAIL); + + DoArgumentPrecTest(convert("%.*s"), 2, (void*)convert("bar"), convert("bar"), + convert("ba"), convert("ba")); + DoArgumentPrecTest(convert("%.*c"), 0, (void*)'a', convert("a"), + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*c"), 4, (void*)'a', convert("a"), + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*C"), 0, (void*)'a', convert("a"), + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*C"), 4, (void*)'a', convert("a"), + convert("a"), convert("a")); + DoArgumentPrecTest(convert("%.*d"), 1, (void*)42, convert("42"), + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*d"), 3, (void*)42, convert("42"), + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*i"), 1, (void*)42, convert("42"), + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*i"), 3, (void*)42, convert("42"), + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*o"), 1, (void*)42, convert("42"), + convert("52"), convert("52")); + DoArgumentPrecTest(convert("%.*o"), 3, (void*)42, convert("42"), + convert("052"), convert("052")); + DoArgumentPrecTest(convert("%.*u"), 1, (void*)42, convert("42"), + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*u"), 3, (void*)42, convert("42"), + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*x"), 1, (void*)0x42, convert("0x42"), + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*x"), 3, (void*)0x42, convert("0x42"), + convert("042"), convert("042")); + DoArgumentPrecTest(convert("%.*X"), 1, (void*)0x42, convert("0x42"), + convert("42"), convert("42")); + DoArgumentPrecTest(convert("%.*X"), 3, (void*)0x42, convert("0x42"), + convert("042"), convert("042")); + + + DoArgumentPrecDoubleTest(convert("%.*e"), 1, 2.01, convert("2.0e+000"), + convert("2.0e+00")); + DoArgumentPrecDoubleTest(convert("%.*e"), 3, 2.01, convert("2.010e+000"), + convert("2.010e+00")); + DoArgumentPrecDoubleTest(convert("%.*E"), 1, 2.01, convert("2.0E+000"), + convert("2.0E+00")); + DoArgumentPrecDoubleTest(convert("%.*E"), 3, 2.01, convert("2.010E+000"), + convert("2.010E+00")); + DoArgumentPrecDoubleTest(convert("%.*f"), 1, 2.01, convert("2.0"), + convert("2.0")); + DoArgumentPrecDoubleTest(convert("%.*f"), 3, 2.01, convert("2.010"), + convert("2.010")); + DoArgumentPrecDoubleTest(convert("%.*g"), 1, 256.01, convert("3e+002"), + convert("3e+02")); + DoArgumentPrecDoubleTest(convert("%.*g"), 3, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*g"), 4, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*g"), 6, 256.01, convert("256.01"), + convert("256.01")); + DoArgumentPrecDoubleTest(convert("%.*G"), 1, 256.01, convert("3E+002"), + convert("3E+02")); + DoArgumentPrecDoubleTest(convert("%.*G"), 3, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*G"), 4, 256.01, convert("256"), + convert("256")); + DoArgumentPrecDoubleTest(convert("%.*G"), 6, 256.01, convert("256.01"), + convert("256.01")); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test2/CMakeLists.txt index 295448c..abfceca 100644 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_vswprintf_test2 diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vswprintf/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/vswprintf/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test3/CMakeLists.txt index 1fb6272..7f4798d 100644 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_vswprintf_test3 diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test3/test3.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vswprintf/test3/test3.c rename to src/pal/tests/palsuite/c_runtime/vswprintf/test3/test3.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test4/CMakeLists.txt index cae0806..05701ac 100644 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_vswprintf_test4 diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test4/test4.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vswprintf/test4/test4.c rename to src/pal/tests/palsuite/c_runtime/vswprintf/test4/test4.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test5/CMakeLists.txt index 7c48045..888ce27 100644 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_vswprintf_test5 diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test5/test5.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vswprintf/test5/test5.c rename to src/pal/tests/palsuite/c_runtime/vswprintf/test5/test5.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test6/CMakeLists.txt index d7de580..bfbb17c 100644 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test6.c + test6.cpp ) add_executable(paltest_vswprintf_test6 diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test6/test6.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test6/test6.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vswprintf/test6/test6.c rename to src/pal/tests/palsuite/c_runtime/vswprintf/test6/test6.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test7/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test7/CMakeLists.txt index eb07ee2..8b98058 100644 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test7.c + test7.cpp ) add_executable(paltest_vswprintf_test7 diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test7/test7.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test7/test7.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vswprintf/test7/test7.c rename to src/pal/tests/palsuite/c_runtime/vswprintf/test7/test7.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test8/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test8/CMakeLists.txt index ed35ea8..07ba473 100644 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/test8/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test8/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test8.c + test8.cpp ) add_executable(paltest_vswprintf_test8 diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test8/test8.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test8/test8.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vswprintf/test8/test8.c rename to src/pal/tests/palsuite/c_runtime/vswprintf/test8/test8.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test9/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/vswprintf/test9/CMakeLists.txt index 7098da3..11c7778 100644 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/test9/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/test9/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test9.c + test9.cpp ) add_executable(paltest_vswprintf_test9 diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/test9/test9.c b/src/pal/tests/palsuite/c_runtime/vswprintf/test9/test9.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/vswprintf/test9/test9.c rename to src/pal/tests/palsuite/c_runtime/vswprintf/test9/test9.cpp diff --git a/src/pal/tests/palsuite/c_runtime/vswprintf/vswprintf.h b/src/pal/tests/palsuite/c_runtime/vswprintf/vswprintf.h index a79c9bb..37a3792 100644 --- a/src/pal/tests/palsuite/c_runtime/vswprintf/vswprintf.h +++ b/src/pal/tests/palsuite/c_runtime/vswprintf/vswprintf.h @@ -27,7 +27,7 @@ int testvswp(wchar_t* buf, const wchar_t* format, ...) return( retVal); } -void DoWStrTest(WCHAR *formatstr, WCHAR *param, WCHAR *checkstr) +void DoWStrTest(const WCHAR *formatstr, WCHAR *param, const WCHAR *checkstr) { WCHAR buf[256] = { 0 }; @@ -42,7 +42,7 @@ void DoWStrTest(WCHAR *formatstr, WCHAR *param, WCHAR *checkstr) } } -void DoStrTest(WCHAR *formatstr, char *param, WCHAR *checkstr) +void DoStrTest(const WCHAR *formatstr, char *param, const WCHAR *checkstr) { WCHAR buf[256] = { 0 }; @@ -57,7 +57,7 @@ void DoStrTest(WCHAR *formatstr, char *param, WCHAR *checkstr) } } -void DoCharTest(WCHAR *formatstr, char param, WCHAR *checkstr) +void DoCharTest(const WCHAR *formatstr, char param, const WCHAR *checkstr) { WCHAR buf[256] = { 0 }; @@ -71,7 +71,7 @@ void DoCharTest(WCHAR *formatstr, char param, WCHAR *checkstr) } } -void DoWCharTest(WCHAR *formatstr, WCHAR param, WCHAR *checkstr) +void DoWCharTest(const WCHAR *formatstr, WCHAR param, const WCHAR *checkstr) { WCHAR buf[256] = { 0 }; @@ -85,7 +85,7 @@ void DoWCharTest(WCHAR *formatstr, WCHAR param, WCHAR *checkstr) } } -void DoNumTest(WCHAR *formatstr, int value, WCHAR*checkstr) +void DoNumTest(const WCHAR *formatstr, int value, const WCHAR *checkstr) { WCHAR buf[256] = { 0 }; @@ -98,7 +98,7 @@ void DoNumTest(WCHAR *formatstr, int value, WCHAR*checkstr) } } -void DoI64NumTest(WCHAR *formatstr, INT64 value, char *valuestr, WCHAR*checkstr) +void DoI64NumTest(const WCHAR *formatstr, INT64 value, char *valuestr, const WCHAR *checkstr) { WCHAR buf[256] = { 0 }; @@ -110,7 +110,7 @@ void DoI64NumTest(WCHAR *formatstr, INT64 value, char *valuestr, WCHAR*checkstr) convertC(checkstr), convertC(buf)); } } -void DoDoubleTest(WCHAR *formatstr, double value, WCHAR *checkstr1, WCHAR +void DoDoubleTest(const WCHAR *formatstr, double value, const WCHAR *checkstr1, WCHAR *checkstr2) { WCHAR buf[256] = { 0 }; diff --git a/src/pal/tests/palsuite/c_runtime/wcscat/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcscat/test1/CMakeLists.txt index 34dfee0..815c585 100644 --- a/src/pal/tests/palsuite/c_runtime/wcscat/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcscat/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wcscat_test1 diff --git a/src/pal/tests/palsuite/c_runtime/wcscat/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcscat/test1/test1.c deleted file mode 100644 index 789eebf..0000000 --- a/src/pal/tests/palsuite/c_runtime/wcscat/test1/test1.c +++ /dev/null @@ -1,71 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: -** Test to that wcscat correctly concatanates wide strings, including placing -** null pointers. -** -** -**==========================================================================*/ - - - -#include - -/* - * Notes: uses memcmp and the (pal) sprintf - */ - -int __cdecl main(int argc, char *argv[]) -{ - WCHAR dest[80]; - WCHAR test[] = {'f','o','o',' ','b','a','r',' ','b','a','z',0}; - WCHAR str1[] = {'f','o','o',' ',0}; - WCHAR str2[] = {'b','a','r',' ',0}; - WCHAR str3[] = {'b','a','z',0}; - WCHAR *ptr; - char buffer[256]; - - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - dest[0] = 0; - - ptr = wcscat(dest, str1); - if (ptr != dest) - { - Fail("ERROR: Expected wcscat to return ptr to %p, got %p", dest, ptr); - } - - ptr = wcscat(dest, str2); - if (ptr != dest) - { - Fail("ERROR: Expected wcscat to return ptr to %p, got %p", dest, ptr); - } - - ptr = wcscat(dest, str3); - if (ptr != dest) - { - Fail("ERROR: Expected wcscat to return ptr to %p, got %p", dest, ptr); - } - - if (memcmp(dest, test, sizeof(test)) != 0) - { - sprintf(buffer, "%S", dest); - Fail("ERROR: Expected wcscat to give \"%s\", got \"%s\"\n", - "foo bar baz", buffer); - } - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/c_runtime/wcscat/test1/test1.cpp b/src/pal/tests/palsuite/c_runtime/wcscat/test1/test1.cpp new file mode 100644 index 0000000..e9a79d3 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/wcscat/test1/test1.cpp @@ -0,0 +1,71 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: +** Test to that wcscat correctly concatanates wide strings, including placing +** null pointers. +** +** +**==========================================================================*/ + + + +#include + +/* + * Notes: uses memcmp and the (pal) sprintf_s + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR dest[80]; + WCHAR test[] = {'f','o','o',' ','b','a','r',' ','b','a','z',0}; + WCHAR str1[] = {'f','o','o',' ',0}; + WCHAR str2[] = {'b','a','r',' ',0}; + WCHAR str3[] = {'b','a','z',0}; + WCHAR *ptr; + char buffer[256]; + + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + dest[0] = 0; + + ptr = wcscat(dest, str1); + if (ptr != dest) + { + Fail("ERROR: Expected wcscat to return ptr to %p, got %p", dest, ptr); + } + + ptr = wcscat(dest, str2); + if (ptr != dest) + { + Fail("ERROR: Expected wcscat to return ptr to %p, got %p", dest, ptr); + } + + ptr = wcscat(dest, str3); + if (ptr != dest) + { + Fail("ERROR: Expected wcscat to return ptr to %p, got %p", dest, ptr); + } + + if (memcmp(dest, test, sizeof(test)) != 0) + { + sprintf_s(buffer, _countof(buffer), "%S", dest); + Fail("ERROR: Expected wcscat to give \"%s\", got \"%s\"\n", + "foo bar baz", buffer); + } + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/c_runtime/wcschr/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcschr/test1/CMakeLists.txt index 542d70b..9cf0a91 100644 --- a/src/pal/tests/palsuite/c_runtime/wcschr/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcschr/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wcschr_test1 diff --git a/src/pal/tests/palsuite/c_runtime/wcschr/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcschr/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcschr/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/wcschr/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcscmp/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcscmp/test1/CMakeLists.txt index 009e48e..98c0535 100644 --- a/src/pal/tests/palsuite/c_runtime/wcscmp/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcscmp/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wcscmp_test1 diff --git a/src/pal/tests/palsuite/c_runtime/wcscmp/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcscmp/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcscmp/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/wcscmp/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcscpy/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcscpy/test1/CMakeLists.txt index 5f21b82..872b2de 100644 --- a/src/pal/tests/palsuite/c_runtime/wcscpy/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcscpy/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wcscpy_test1 diff --git a/src/pal/tests/palsuite/c_runtime/wcscpy/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcscpy/test1/test1.c deleted file mode 100644 index 4e45c86..0000000 --- a/src/pal/tests/palsuite/c_runtime/wcscpy/test1/test1.c +++ /dev/null @@ -1,47 +0,0 @@ -// 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. - -/*============================================================================ -** -** Source: test1.c -** -** Purpose: Tests that wcscpy correctly copies a null-terminated wide string. -** -** -**==========================================================================*/ - - -#include - -/* - * Notes: uses memcmp and sprintf. - */ - -int __cdecl main(int argc, char *argv[]) -{ - WCHAR str[] = {'f','o','o',0,'b','a','r',0}; - WCHAR dest[80]; - WCHAR result[] = {'f','o','o',0}; - WCHAR *ret; - char buffer[256]; - - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - - ret = wcscpy(dest, str); - - if (ret != dest || memcmp(dest, result, sizeof(result)) != 0) - { - sprintf(buffer, "%S", dest); - Fail("Expected wcscpy to give \"%s\" with a return value of %p, got \"%s\" " - "with a return value of %p.\n", "foo", dest, buffer, ret); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/c_runtime/wcscpy/test1/test1.cpp b/src/pal/tests/palsuite/c_runtime/wcscpy/test1/test1.cpp new file mode 100644 index 0000000..2ecafa8 --- /dev/null +++ b/src/pal/tests/palsuite/c_runtime/wcscpy/test1/test1.cpp @@ -0,0 +1,47 @@ +// 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. + +/*============================================================================ +** +** Source: test1.c +** +** Purpose: Tests that wcscpy correctly copies a null-terminated wide string. +** +** +**==========================================================================*/ + + +#include + +/* + * Notes: uses memcmp and sprintf_s. + */ + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR str[] = {'f','o','o',0,'b','a','r',0}; + WCHAR dest[80]; + WCHAR result[] = {'f','o','o',0}; + WCHAR *ret; + char buffer[256]; + + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + + ret = wcscpy(dest, str); + + if (ret != dest || memcmp(dest, result, sizeof(result)) != 0) + { + sprintf_s(buffer, _countof(buffer), "%S", dest); + Fail("Expected wcscpy to give \"%s\" with a return value of %p, got \"%s\" " + "with a return value of %p.\n", "foo", dest, buffer, ret); + } + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/c_runtime/wcslen/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcslen/test1/CMakeLists.txt index de0f1c2..b641a83 100644 --- a/src/pal/tests/palsuite/c_runtime/wcslen/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcslen/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wcslen_test1 diff --git a/src/pal/tests/palsuite/c_runtime/wcslen/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcslen/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcslen/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/wcslen/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcsncat/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcsncat/test1/CMakeLists.txt index 12c286a..e90e2b7 100644 --- a/src/pal/tests/palsuite/c_runtime/wcsncat/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcsncat/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wcsncat_test1 diff --git a/src/pal/tests/palsuite/c_runtime/wcsncat/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcsncat/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcsncat/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/wcsncat/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/CMakeLists.txt index 56c9b25..f5511a8 100644 --- a/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wcsncmp_test1 diff --git a/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcsncmp/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcsncmp/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/wcsncmp/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/CMakeLists.txt index 1c1d70b..a7254a7 100644 --- a/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wcsncpy_test1 diff --git a/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcsncpy/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcsncpy/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/wcsncpy/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/CMakeLists.txt index c6a3f87..14c1fe8 100644 --- a/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wcspbrk_test1 diff --git a/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcspbrk/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcspbrk/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/wcspbrk/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/CMakeLists.txt index 80513af..abdd6d5 100644 --- a/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wcsrchr_test1 diff --git a/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcsrchr/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcsrchr/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/wcsrchr/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcsstr/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcsstr/test1/CMakeLists.txt index e426193..0e1e0b4 100644 --- a/src/pal/tests/palsuite/c_runtime/wcsstr/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcsstr/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wcsstr_test1 diff --git a/src/pal/tests/palsuite/c_runtime/wcsstr/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcsstr/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcsstr/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/wcsstr/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcstod/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstod/test1/CMakeLists.txt index cf585d0..cca01ca 100644 --- a/src/pal/tests/palsuite/c_runtime/wcstod/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcstod/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wcstod_test1 diff --git a/src/pal/tests/palsuite/c_runtime/wcstod/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcstod/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcstod/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/wcstod/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcstod/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstod/test2/CMakeLists.txt index 43d5bf8..ae74508 100644 --- a/src/pal/tests/palsuite/c_runtime/wcstod/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcstod/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_wcstod_test2 diff --git a/src/pal/tests/palsuite/c_runtime/wcstod/test2/test2.c b/src/pal/tests/palsuite/c_runtime/wcstod/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcstod/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/wcstod/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcstok/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstok/test1/CMakeLists.txt index 863f5d8..6b5bed9 100644 --- a/src/pal/tests/palsuite/c_runtime/wcstok/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcstok/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wcstok_test1 diff --git a/src/pal/tests/palsuite/c_runtime/wcstok/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcstok/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcstok/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/wcstok/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstol/test1/CMakeLists.txt index 25e96e7..f76018f 100644 --- a/src/pal/tests/palsuite/c_runtime/wcstol/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcstol/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wcstol_test1 diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcstol/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcstol/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/wcstol/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstol/test2/CMakeLists.txt index ea33ec8..8dc2ab6 100644 --- a/src/pal/tests/palsuite/c_runtime/wcstol/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcstol/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_wcstol_test2 diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test2/test2.c b/src/pal/tests/palsuite/c_runtime/wcstol/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcstol/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/wcstol/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstol/test3/CMakeLists.txt index 509feca..310f97d 100644 --- a/src/pal/tests/palsuite/c_runtime/wcstol/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcstol/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_wcstol_test3 diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test3/test3.c b/src/pal/tests/palsuite/c_runtime/wcstol/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcstol/test3/test3.c rename to src/pal/tests/palsuite/c_runtime/wcstol/test3/test3.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstol/test4/CMakeLists.txt index 043c562..23928aa 100644 --- a/src/pal/tests/palsuite/c_runtime/wcstol/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcstol/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_wcstol_test4 diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test4/test4.c b/src/pal/tests/palsuite/c_runtime/wcstol/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcstol/test4/test4.c rename to src/pal/tests/palsuite/c_runtime/wcstol/test4/test4.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstol/test5/CMakeLists.txt index c887369..16c709f 100644 --- a/src/pal/tests/palsuite/c_runtime/wcstol/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcstol/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_wcstol_test5 diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test5/test5.c b/src/pal/tests/palsuite/c_runtime/wcstol/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcstol/test5/test5.c rename to src/pal/tests/palsuite/c_runtime/wcstol/test5/test5.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstol/test6/CMakeLists.txt index d328161..80ccaf6 100644 --- a/src/pal/tests/palsuite/c_runtime/wcstol/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcstol/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test6.c + test6.cpp ) add_executable(paltest_wcstol_test6 diff --git a/src/pal/tests/palsuite/c_runtime/wcstol/test6/test6.c b/src/pal/tests/palsuite/c_runtime/wcstol/test6/test6.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcstol/test6/test6.c rename to src/pal/tests/palsuite/c_runtime/wcstol/test6/test6.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstoul/test1/CMakeLists.txt index b24523e..58f002a 100644 --- a/src/pal/tests/palsuite/c_runtime/wcstoul/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wcstoul_test1 diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wcstoul/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcstoul/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/wcstoul/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstoul/test2/CMakeLists.txt index e262078..2c8d012 100644 --- a/src/pal/tests/palsuite/c_runtime/wcstoul/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_wcstoul_test2 diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test2/test2.c b/src/pal/tests/palsuite/c_runtime/wcstoul/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcstoul/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/wcstoul/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test3/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstoul/test3/CMakeLists.txt index aae268a..353df07 100644 --- a/src/pal/tests/palsuite/c_runtime/wcstoul/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_wcstoul_test3 diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test3/test3.c b/src/pal/tests/palsuite/c_runtime/wcstoul/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcstoul/test3/test3.c rename to src/pal/tests/palsuite/c_runtime/wcstoul/test3/test3.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test4/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstoul/test4/CMakeLists.txt index bd80730..e1e7d55 100644 --- a/src/pal/tests/palsuite/c_runtime/wcstoul/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_wcstoul_test4 diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test4/test4.c b/src/pal/tests/palsuite/c_runtime/wcstoul/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcstoul/test4/test4.c rename to src/pal/tests/palsuite/c_runtime/wcstoul/test4/test4.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test5/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstoul/test5/CMakeLists.txt index 1451e6a..9e83c60 100644 --- a/src/pal/tests/palsuite/c_runtime/wcstoul/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_wcstoul_test5 diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test5/test5.c b/src/pal/tests/palsuite/c_runtime/wcstoul/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcstoul/test5/test5.c rename to src/pal/tests/palsuite/c_runtime/wcstoul/test5/test5.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test6/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wcstoul/test6/CMakeLists.txt index 15518bd..8352d0c 100644 --- a/src/pal/tests/palsuite/c_runtime/wcstoul/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wcstoul/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test6.c + test6.cpp ) add_executable(paltest_wcstoul_test6 diff --git a/src/pal/tests/palsuite/c_runtime/wcstoul/test6/test6.c b/src/pal/tests/palsuite/c_runtime/wcstoul/test6/test6.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wcstoul/test6/test6.c rename to src/pal/tests/palsuite/c_runtime/wcstoul/test6/test6.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wprintf/test1/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wprintf/test1/CMakeLists.txt index 701bbe4..f95fc12 100644 --- a/src/pal/tests/palsuite/c_runtime/wprintf/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wprintf/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_wprintf_test1 diff --git a/src/pal/tests/palsuite/c_runtime/wprintf/test1/test1.c b/src/pal/tests/palsuite/c_runtime/wprintf/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wprintf/test1/test1.c rename to src/pal/tests/palsuite/c_runtime/wprintf/test1/test1.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wprintf/test2/CMakeLists.txt b/src/pal/tests/palsuite/c_runtime/wprintf/test2/CMakeLists.txt index 55c3d11..325e804 100644 --- a/src/pal/tests/palsuite/c_runtime/wprintf/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/c_runtime/wprintf/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_wprintf_test2 diff --git a/src/pal/tests/palsuite/c_runtime/wprintf/test2/test2.c b/src/pal/tests/palsuite/c_runtime/wprintf/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/c_runtime/wprintf/test2/test2.c rename to src/pal/tests/palsuite/c_runtime/wprintf/test2/test2.cpp diff --git a/src/pal/tests/palsuite/c_runtime/wprintf/wprintf.h b/src/pal/tests/palsuite/c_runtime/wprintf/wprintf.h index 7d3caf1..3a96248 100644 --- a/src/pal/tests/palsuite/c_runtime/wprintf/wprintf.h +++ b/src/pal/tests/palsuite/c_runtime/wprintf/wprintf.h @@ -14,7 +14,7 @@ #ifndef __wprintf_H__ #define __wprintf_H__ -void DoStrTest(WCHAR *formatstr, WCHAR* param, WCHAR *checkstr) +void DoStrTest(const WCHAR *formatstr, const WCHAR *param, const WCHAR *checkstr) { int ret; @@ -27,8 +27,8 @@ void DoStrTest(WCHAR *formatstr, WCHAR* param, WCHAR *checkstr) } -void DoPointerTest(WCHAR *formatstr, void* param, WCHAR* paramstr, - WCHAR *checkstr1) +void DoPointerTest(const WCHAR *formatstr, void* param, WCHAR* paramstr, + const WCHAR *checkstr1) { int ret; @@ -40,7 +40,7 @@ void DoPointerTest(WCHAR *formatstr, void* param, WCHAR* paramstr, } } -void DoCountTest(WCHAR *formatstr, int param, WCHAR *checkstr) +void DoCountTest(const WCHAR *formatstr, int param, const WCHAR *checkstr) { int ret; int n = -1; @@ -59,7 +59,7 @@ void DoCountTest(WCHAR *formatstr, int param, WCHAR *checkstr) } } -void DoShortCountTest(WCHAR *formatstr, int param, WCHAR *checkstr) +void DoShortCountTest(const WCHAR *formatstr, int param, const WCHAR *checkstr) { int ret; short int n = -1; @@ -79,7 +79,7 @@ void DoShortCountTest(WCHAR *formatstr, int param, WCHAR *checkstr) } -void DoCharTest(WCHAR *formatstr, WCHAR param, WCHAR *checkstr) +void DoCharTest(const WCHAR *formatstr, WCHAR param, const WCHAR *checkstr) { int ret; @@ -91,7 +91,7 @@ void DoCharTest(WCHAR *formatstr, WCHAR param, WCHAR *checkstr) } } -void DoWCharTest(WCHAR *formatstr, WCHAR param, WCHAR *checkstr) +void DoWCharTest(const WCHAR *formatstr, WCHAR param, const WCHAR *checkstr) { int ret; @@ -103,7 +103,7 @@ void DoWCharTest(WCHAR *formatstr, WCHAR param, WCHAR *checkstr) } } -void DoNumTest(WCHAR *formatstr, int param, WCHAR *checkstr) +void DoNumTest(const WCHAR *formatstr, int param, const WCHAR *checkstr) { int ret; @@ -115,8 +115,8 @@ void DoNumTest(WCHAR *formatstr, int param, WCHAR *checkstr) } } -void DoI64Test(WCHAR *formatstr, INT64 param, WCHAR *valuestr, - WCHAR *checkstr1) +void DoI64Test(const WCHAR *formatstr, INT64 param, const WCHAR *valuestr, + const WCHAR *checkstr1) { int ret; @@ -128,8 +128,8 @@ void DoI64Test(WCHAR *formatstr, INT64 param, WCHAR *valuestr, } } -void DoDoubleTest(WCHAR *formatstr, double param, - WCHAR *checkstr1, WCHAR *checkstr2) +void DoDoubleTest(const WCHAR *formatstr, double param, + const WCHAR *checkstr1, const WCHAR *checkstr2) { int ret; @@ -141,8 +141,8 @@ void DoDoubleTest(WCHAR *formatstr, double param, } } -void DoArgumentPrecTest(WCHAR *formatstr, int precision, void *param, - WCHAR *paramstr, WCHAR *checkstr1, WCHAR *checkstr2) +void DoArgumentPrecTest(const WCHAR *formatstr, int precision, void *param, + WCHAR *paramstr, const WCHAR *checkstr1, const WCHAR *checkstr2) { int ret; @@ -154,8 +154,8 @@ void DoArgumentPrecTest(WCHAR *formatstr, int precision, void *param, } } -void DoArgumentPrecDoubleTest(WCHAR *formatstr, int precision, double param, - WCHAR *checkstr1, WCHAR *checkstr2) +void DoArgumentPrecDoubleTest(const WCHAR *formatstr, int precision, double param, + const WCHAR *checkstr1, const WCHAR *checkstr2) { int ret; diff --git a/src/pal/tests/palsuite/common/palsuite.h b/src/pal/tests/palsuite/common/palsuite.h index ef644ad..b77ca2e 100644 --- a/src/pal/tests/palsuite/common/palsuite.h +++ b/src/pal/tests/palsuite/common/palsuite.h @@ -133,9 +133,9 @@ inline ULONG VAL32(ULONG x) #define th_htons(w) (((w) >> 8) | ((w) << 8)) #endif // BIGENDIAN +#define _countof(_array) (sizeof(_array)/sizeof(_array[0])) - -WCHAR* convert(char * aString) +WCHAR* convert(const char * aString) { int size; WCHAR* wideBuffer; @@ -150,7 +150,7 @@ WCHAR* convert(char * aString) return wideBuffer; } -char* convertC(WCHAR * wString) +char* convertC(const WCHAR * wString) { int size; char * MultiBuffer = NULL; diff --git a/src/pal/tests/palsuite/composite/object_management/event/nonshared/CMakeLists.txt b/src/pal/tests/palsuite/composite/object_management/event/nonshared/CMakeLists.txt index c6c0037..b336c03 100644 --- a/src/pal/tests/palsuite/composite/object_management/event/nonshared/CMakeLists.txt +++ b/src/pal/tests/palsuite/composite/object_management/event/nonshared/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - event.c - main.c + event.cpp + main.cpp ) add_executable(paltest_event_nonshared diff --git a/src/pal/tests/palsuite/composite/object_management/event/nonshared/event.c b/src/pal/tests/palsuite/composite/object_management/event/nonshared/event.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/object_management/event/nonshared/event.c rename to src/pal/tests/palsuite/composite/object_management/event/nonshared/event.cpp diff --git a/src/pal/tests/palsuite/composite/object_management/event/nonshared/main.c b/src/pal/tests/palsuite/composite/object_management/event/nonshared/main.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/object_management/event/nonshared/main.c rename to src/pal/tests/palsuite/composite/object_management/event/nonshared/main.cpp diff --git a/src/pal/tests/palsuite/composite/object_management/event/shared/CMakeLists.txt b/src/pal/tests/palsuite/composite/object_management/event/shared/CMakeLists.txt index d326e3a..8618879 100644 --- a/src/pal/tests/palsuite/composite/object_management/event/shared/CMakeLists.txt +++ b/src/pal/tests/palsuite/composite/object_management/event/shared/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - event.c - main.c + event.cpp + main.cpp ) add_executable(paltest_event_shared diff --git a/src/pal/tests/palsuite/composite/object_management/event/shared/event.c b/src/pal/tests/palsuite/composite/object_management/event/shared/event.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/object_management/event/shared/event.c rename to src/pal/tests/palsuite/composite/object_management/event/shared/event.cpp diff --git a/src/pal/tests/palsuite/composite/object_management/event/shared/main.c b/src/pal/tests/palsuite/composite/object_management/event/shared/main.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/object_management/event/shared/main.c rename to src/pal/tests/palsuite/composite/object_management/event/shared/main.cpp diff --git a/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/CMakeLists.txt b/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/CMakeLists.txt index 7859cd4..03d5efa 100644 --- a/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/CMakeLists.txt +++ b/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - main.c - mutex.c + main.cpp + mutex.cpp ) add_executable(paltest_mutex_nonshared diff --git a/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/main.c b/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/main.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/object_management/mutex/nonshared/main.c rename to src/pal/tests/palsuite/composite/object_management/mutex/nonshared/main.cpp diff --git a/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/mutex.c b/src/pal/tests/palsuite/composite/object_management/mutex/nonshared/mutex.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/object_management/mutex/nonshared/mutex.c rename to src/pal/tests/palsuite/composite/object_management/mutex/nonshared/mutex.cpp diff --git a/src/pal/tests/palsuite/composite/object_management/mutex/shared/CMakeLists.txt b/src/pal/tests/palsuite/composite/object_management/mutex/shared/CMakeLists.txt index cf33d0b..d4b50cd 100644 --- a/src/pal/tests/palsuite/composite/object_management/mutex/shared/CMakeLists.txt +++ b/src/pal/tests/palsuite/composite/object_management/mutex/shared/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - main.c - mutex.c + main.cpp + mutex.cpp ) add_executable(paltest_mutex_shared diff --git a/src/pal/tests/palsuite/composite/object_management/mutex/shared/main.c b/src/pal/tests/palsuite/composite/object_management/mutex/shared/main.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/object_management/mutex/shared/main.c rename to src/pal/tests/palsuite/composite/object_management/mutex/shared/main.cpp diff --git a/src/pal/tests/palsuite/composite/object_management/mutex/shared/mutex.c b/src/pal/tests/palsuite/composite/object_management/mutex/shared/mutex.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/object_management/mutex/shared/mutex.c rename to src/pal/tests/palsuite/composite/object_management/mutex/shared/mutex.cpp diff --git a/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/CMakeLists.txt b/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/CMakeLists.txt index 6efa228..9ed4535 100644 --- a/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/CMakeLists.txt +++ b/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - main.c - semaphore.c + main.cpp + semaphore.cpp ) add_executable(paltest_semaphore_nonshared diff --git a/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/main.c b/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/main.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/main.c rename to src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/main.cpp diff --git a/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/semaphore.c b/src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/semaphore.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/semaphore.c rename to src/pal/tests/palsuite/composite/object_management/semaphore/nonshared/semaphore.cpp diff --git a/src/pal/tests/palsuite/composite/object_management/semaphore/shared/CMakeLists.txt b/src/pal/tests/palsuite/composite/object_management/semaphore/shared/CMakeLists.txt index 12d3ca8..5c7f932 100644 --- a/src/pal/tests/palsuite/composite/object_management/semaphore/shared/CMakeLists.txt +++ b/src/pal/tests/palsuite/composite/object_management/semaphore/shared/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - main.c - semaphore.c + main.cpp + semaphore.cpp ) add_executable(paltest_semaphore_shared diff --git a/src/pal/tests/palsuite/composite/object_management/semaphore/shared/main.c b/src/pal/tests/palsuite/composite/object_management/semaphore/shared/main.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/object_management/semaphore/shared/main.c rename to src/pal/tests/palsuite/composite/object_management/semaphore/shared/main.cpp diff --git a/src/pal/tests/palsuite/composite/object_management/semaphore/shared/semaphore.c b/src/pal/tests/palsuite/composite/object_management/semaphore/shared/semaphore.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/object_management/semaphore/shared/semaphore.c rename to src/pal/tests/palsuite/composite/object_management/semaphore/shared/semaphore.cpp diff --git a/src/pal/tests/palsuite/composite/synchronization/criticalsection/CMakeLists.txt b/src/pal/tests/palsuite/composite/synchronization/criticalsection/CMakeLists.txt index 936c0fe..fc357ed 100644 --- a/src/pal/tests/palsuite/composite/synchronization/criticalsection/CMakeLists.txt +++ b/src/pal/tests/palsuite/composite/synchronization/criticalsection/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - criticalsection.c - mainWrapper.c + criticalsection.cpp + mainWrapper.cpp ) add_executable(paltest_synchronization_criticalsection diff --git a/src/pal/tests/palsuite/composite/synchronization/criticalsection/criticalsection.c b/src/pal/tests/palsuite/composite/synchronization/criticalsection/criticalsection.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/synchronization/criticalsection/criticalsection.c rename to src/pal/tests/palsuite/composite/synchronization/criticalsection/criticalsection.cpp diff --git a/src/pal/tests/palsuite/composite/synchronization/criticalsection/mainWrapper.c b/src/pal/tests/palsuite/composite/synchronization/criticalsection/mainWrapper.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/synchronization/criticalsection/mainWrapper.c rename to src/pal/tests/palsuite/composite/synchronization/criticalsection/mainWrapper.cpp diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/CMakeLists.txt b/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/CMakeLists.txt index d01b106..9a02993 100644 --- a/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/CMakeLists.txt +++ b/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/CMakeLists.txt @@ -4,7 +4,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES mtx_critsect.cpp - pal_composite_native_cs.c + pal_composite_native_cs.cpp resultbuffer.cpp ) diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/pal_composite_native_cs.c b/src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/pal_composite_native_cs.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/pal_composite_native_cs.c rename to src/pal/tests/palsuite/composite/synchronization/nativecriticalsection/pal_composite_native_cs.cpp diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/CMakeLists.txt b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/CMakeLists.txt index c4567f6..717bdd6 100644 --- a/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/CMakeLists.txt +++ b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/CMakeLists.txt @@ -5,7 +5,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES interlocked.cpp mtx_critsect.cpp - pal_composite_native_cs.c + pal_composite_native_cs.cpp resultbuffer.cpp ) diff --git a/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/pal_composite_native_cs.c b/src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/pal_composite_native_cs.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/pal_composite_native_cs.c rename to src/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/pal_composite_native_cs.cpp diff --git a/src/pal/tests/palsuite/composite/threading/threadsuspension/CMakeLists.txt b/src/pal/tests/palsuite/composite/threading/threadsuspension/CMakeLists.txt index 134cce0..d396d2f 100644 --- a/src/pal/tests/palsuite/composite/threading/threadsuspension/CMakeLists.txt +++ b/src/pal/tests/palsuite/composite/threading/threadsuspension/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - mainWrapper.c - threadsuspension.c + mainWrapper.cpp + threadsuspension.cpp ) add_executable(paltest_threading_threadsuspension diff --git a/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/mainWrapper.c b/src/pal/tests/palsuite/composite/threading/threadsuspension/mainWrapper.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/mainWrapper.c rename to src/pal/tests/palsuite/composite/threading/threadsuspension/mainWrapper.cpp diff --git a/src/pal/tests/palsuite/composite/threading/threadsuspension/threadsuspension.c b/src/pal/tests/palsuite/composite/threading/threadsuspension/threadsuspension.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/threading/threadsuspension/threadsuspension.c rename to src/pal/tests/palsuite/composite/threading/threadsuspension/threadsuspension.cpp diff --git a/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/CMakeLists.txt b/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/CMakeLists.txt index 5361a1c..2c88092 100644 --- a/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/CMakeLists.txt +++ b/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - mainWrapper.c - threadsuspension.c + mainWrapper.cpp + threadsuspension.cpp ) add_executable(paltest_threading_threadsuspension_switchthread diff --git a/src/pal/tests/palsuite/composite/threading/threadsuspension/mainWrapper.c b/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/mainWrapper.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/threading/threadsuspension/mainWrapper.c rename to src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/mainWrapper.cpp diff --git a/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/threadsuspension.c b/src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/threadsuspension.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/threadsuspension.c rename to src/pal/tests/palsuite/composite/threading/threadsuspension_switchthread/threadsuspension.cpp diff --git a/src/pal/tests/palsuite/composite/wfmo/CMakeLists.txt b/src/pal/tests/palsuite/composite/wfmo/CMakeLists.txt index 7dbddbc..5e10310 100644 --- a/src/pal/tests/palsuite/composite/wfmo/CMakeLists.txt +++ b/src/pal/tests/palsuite/composite/wfmo/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - main.c - mutex.c + main.cpp + mutex.cpp ) add_executable(paltest_composite_wfmo diff --git a/src/pal/tests/palsuite/composite/wfmo/main.c b/src/pal/tests/palsuite/composite/wfmo/main.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/wfmo/main.c rename to src/pal/tests/palsuite/composite/wfmo/main.cpp diff --git a/src/pal/tests/palsuite/composite/wfmo/mutex.c b/src/pal/tests/palsuite/composite/wfmo/mutex.cpp similarity index 100% rename from src/pal/tests/palsuite/composite/wfmo/mutex.c rename to src/pal/tests/palsuite/composite/wfmo/mutex.cpp diff --git a/src/pal/tests/palsuite/debug_api/DebugBreak/test1/CMakeLists.txt b/src/pal/tests/palsuite/debug_api/DebugBreak/test1/CMakeLists.txt index db66cbe..1b2ae53 100644 --- a/src/pal/tests/palsuite/debug_api/DebugBreak/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/debug_api/DebugBreak/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_debugbreak_test1 diff --git a/src/pal/tests/palsuite/debug_api/DebugBreak/test1/test1.c b/src/pal/tests/palsuite/debug_api/DebugBreak/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/debug_api/DebugBreak/test1/test1.c rename to src/pal/tests/palsuite/debug_api/DebugBreak/test1/test1.cpp diff --git a/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/CMakeLists.txt b/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/CMakeLists.txt index 5bc7fdb..3000734 100644 --- a/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - test1.c + test1.cpp ) add_executable(paltest_outputdebugstringa_test1 @@ -20,7 +20,7 @@ target_link_libraries(paltest_outputdebugstringa_test1 set(HELPERSOURCES - helper.c + helper.cpp ) add_executable(paltest_outputdebugstringa_test1_helper diff --git a/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/helper.c b/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/helper.cpp similarity index 100% rename from src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/helper.c rename to src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/helper.cpp diff --git a/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/test1.c b/src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/test1.c rename to src/pal/tests/palsuite/debug_api/OutputDebugStringA/test1/test1.cpp diff --git a/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/CMakeLists.txt b/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/CMakeLists.txt index 9202bae..4a93f0e 100644 --- a/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_outputdebugstringw_test1 diff --git a/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/test1.c b/src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/test1.c rename to src/pal/tests/palsuite/debug_api/OutputDebugStringW/test1/test1.cpp diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/CMakeLists.txt b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/CMakeLists.txt index 39130aa..afd581f 100644 --- a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - test1.c + test1.cpp ) add_executable(paltest_writeprocessmemory_test1 @@ -20,7 +20,7 @@ target_link_libraries(paltest_writeprocessmemory_test1 set(HELPERSOURCES - helper.c + helper.cpp ) add_executable(paltest_writeprocessmemory_test1_helper diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/helper.c b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/helper.c deleted file mode 100644 index 1a73189..0000000 --- a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/helper.c +++ /dev/null @@ -1,243 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: helper.c -** -** Purpose: This helper process sets up a several blocks of memory, -** then uses a file to tell its parent process where that memory is -** So it can do a WriteProcessMemory on it. When the parent process is done -** we check here that it was written properly. -** -** -**============================================================*/ - -#include "commonconsts.h" - -#include - -struct allhandles_t -{ - HANDLE hEvToHelper; - HANDLE hEvFromHelper; - char *valuesFileName; -}; - - -/* function: wpmDoIt - * - * This is a general WriteProcessMemory testing function that sets up - * the RAM pointed to and tells the companion process on the other end - * of the handles in 'Comms' to attempt to alter 'lenDest' bytes at - * '*pDest'. - * - * '*pBuffer'[0..'lenBuffer'] is expected to be a guard region - * surrounding the '*pDest'[0..'lenDest'] region so that this function - * can verify that only the proper bytes were altered. - */ - -int wpmDoIt(struct allhandles_t Comms, - char * pBuffer, unsigned int lenBuffer, - char * pDest, unsigned int lenDest, - const char* storageDescription) -{ - char *pCurr; - FILE *commsFile; - DWORD dwRet; - - if (pBuffer > pDest || lenDest > lenBuffer) - { - Trace("WriteProcessMemory::DoIt() test implementation: " - "(pBuffer > pDest || lenDest > lenBuffer)\n"); - return FALSE; - } - - /* set up the storage */ - memset(pBuffer, guardValue, lenBuffer); - memset(pDest, initialValue, lenDest); - - /* tell the parent what RAM to adjust */ - if(!(commsFile = fopen(Comms.valuesFileName, "w"))) - { - Trace("WriteProcessMemory: fopen of '%S' failed (%u). \n", - Comms.valuesFileName, GetLastError()); - return FALSE; - } - if (!fprintf(commsFile, "%u %u '%s'\n", - pDest, lenDest, storageDescription)) - { - Trace("WriteProcessMemory: fprintf to '%S' failed (%u). \n", - Comms.valuesFileName, GetLastError()); - return FALSE; - } - PEDANTIC1(fclose, (commsFile)); - - /* Tell the parent the data is ready for it to adjust */ - PEDANTIC(ResetEvent, (Comms.hEvToHelper)); - PEDANTIC(SetEvent, (Comms.hEvFromHelper)); - - dwRet = WaitForSingleObject(Comms.hEvToHelper, TIMEOUT); /* parent is done */ - if (dwRet != WAIT_OBJECT_0) - { - Trace("helper WaitForSingleObjectTest: WaitForSingleObject " - "failed (%u)\n", GetLastError()); - return FALSE; - } - - /* check the stuff that SHOULD have changed */ - for (pCurr = pDest; pCurr < (pDest + lenDest); pCurr++) - { - if ( *pCurr != nextValue) - { - Trace("When testing '%s': alteration test failed " - "at %u offset %u. Found '%c' instead of '%c'\n.", - storageDescription, pDest, pCurr - pDest, *pCurr, nextValue); - Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer); - return FALSE; - } - } - /* check the stuff that should NOT have changed */ - for (pCurr = pBuffer; pCurr < pDest; pCurr++ ) - { - if ( *pCurr != guardValue) - { - Trace("When testing '%s': leading guard zone test failed " - "at %u offset %u. Found '%c' instead of '%c'\n.", - storageDescription, pDest, pCurr - pBuffer, *pCurr, guardValue); - Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer); - return FALSE; - } - } - for (pCurr = pDest + lenDest; pCurr < (pBuffer + lenBuffer); pCurr++ ) - { - if ( *pCurr != guardValue) - { - Trace("When testing '%s': trailing guard zone test failed " - "at %u offset %u. Found '%c' instead of '%c'\n.", - storageDescription, pDest + lenDest, pCurr - pBuffer, *pCurr, guardValue); - Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer); - return FALSE; - } - } - - return TRUE; -} - -int __cdecl main(int argc, char *argv[]) -{ - - BOOL success = TRUE; /* assume success */ - struct allhandles_t Comms = {0,0,0} ; - - /* variables to track storage to alter */ - char *pTarget = NULL; - unsigned int sizeTarget; - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* hook up with the events created by the parent */ - Comms.hEvToHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcToHelperEvName); - if (!Comms.hEvToHelper) - { - Fail("WriteProcessMemory: OpenEvent of '%S' failed (%u). " - "(the event should already exist!)\n", - szcToHelperEvName, GetLastError()); - } - Comms.hEvFromHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcFromHelperEvName); - if (!Comms.hEvToHelper) - { - Trace("WriteProcessMemory: OpenEvent of '%S' failed (%u). " - "(the event should already exist!)\n", - szcFromHelperEvName, GetLastError()); - success = FALSE; - goto EXIT; - } - Comms.valuesFileName = argv[1]; - - { - char autoAllocatedOnStack[51]; - - /* Get the parent process to write to the local stack */ - success &= wpmDoIt(Comms, autoAllocatedOnStack, - sizeof(autoAllocatedOnStack), - autoAllocatedOnStack + sizeof(int), - sizeof(autoAllocatedOnStack) - 2 * sizeof(int), - "const size array on stack with int sized guards"); - } - - /* Get the parent process to write to stuff on the heap */ - sizeTarget = 2 * sizeof(int) + 23 ; /* 23 is just a random prime > 16 */ - if (!(pTarget = malloc(sizeTarget))) - { - Trace("WriteProcessMemory helper: unable to allocate '%s'->%d bytes of memory" - "(%u).\n", - argv[3], sizeTarget, GetLastError()); - success = FALSE; - goto EXIT; - - } - success &= wpmDoIt(Comms, pTarget, sizeTarget, - pTarget + sizeof(int), - sizeTarget - 2 * sizeof(int), - "array on heap with int sized guards"); - - /* just to be nice try something 16 - 2 * sizeof(int) bytes long */ - { - char autoAllocatedOnStack[16]; - - /* Get the parent process to write to the local stack */ - success &= wpmDoIt(Comms, autoAllocatedOnStack, - sizeof(autoAllocatedOnStack), - autoAllocatedOnStack + sizeof(int), - sizeof(autoAllocatedOnStack) - 2 * sizeof(int), - "another 16 byte array on stack with int sized guards inside"); - } - - /* NOTE: Don't try 0 bytes long. Win32 WriteProcessMemory claims - * it writes 8 bytes in that case! */ - - /* and 1 byte long... */ - { - char autoAllocatedOnStack[1+ 2 * sizeof(int)]; - - /* Get the parent process to write to the local stack */ - success &= wpmDoIt(Comms, autoAllocatedOnStack, - sizeof(autoAllocatedOnStack), - autoAllocatedOnStack + sizeof(int), - 1, - "no bytes with int sized guards outside on stack"); - } - - -EXIT: - /* Tell the parent that we are done */ - if (!DeleteFile(Comms.valuesFileName)) - { - Trace("helper: DeleteFile failed so parent (test1) is unlikely " - "to exit cleanly\n"); - } - PEDANTIC(ResetEvent, (Comms.hEvToHelper)); - if (!SetEvent(Comms.hEvFromHelper)) - { - Trace("helper: SetEvent failed so parent (test1) is unlikely " - "to exit cleanly\n"); - } - - free(pTarget); - PEDANTIC(CloseHandle, (Comms.hEvToHelper)); - PEDANTIC(CloseHandle, (Comms.hEvFromHelper)); - - if (!success) - { - Fail(""); - } - - PAL_Terminate(); - - return success ? PASS : FAIL; -} diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/helper.cpp b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/helper.cpp new file mode 100644 index 0000000..d965ca7 --- /dev/null +++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/helper.cpp @@ -0,0 +1,243 @@ +// 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. + +/*============================================================= +** +** Source: helper.c +** +** Purpose: This helper process sets up a several blocks of memory, +** then uses a file to tell its parent process where that memory is +** So it can do a WriteProcessMemory on it. When the parent process is done +** we check here that it was written properly. +** +** +**============================================================*/ + +#include "commonconsts.h" + +#include + +struct allhandles_t +{ + HANDLE hEvToHelper; + HANDLE hEvFromHelper; + char *valuesFileName; +}; + + +/* function: wpmDoIt + * + * This is a general WriteProcessMemory testing function that sets up + * the RAM pointed to and tells the companion process on the other end + * of the handles in 'Comms' to attempt to alter 'lenDest' bytes at + * '*pDest'. + * + * '*pBuffer'[0..'lenBuffer'] is expected to be a guard region + * surrounding the '*pDest'[0..'lenDest'] region so that this function + * can verify that only the proper bytes were altered. + */ + +int wpmDoIt(struct allhandles_t Comms, + char * pBuffer, unsigned int lenBuffer, + char * pDest, unsigned int lenDest, + const char* storageDescription) +{ + char *pCurr; + FILE *commsFile; + DWORD dwRet; + + if (pBuffer > pDest || lenDest > lenBuffer) + { + Trace("WriteProcessMemory::DoIt() test implementation: " + "(pBuffer > pDest || lenDest > lenBuffer)\n"); + return FALSE; + } + + /* set up the storage */ + memset(pBuffer, guardValue, lenBuffer); + memset(pDest, initialValue, lenDest); + + /* tell the parent what RAM to adjust */ + if(!(commsFile = fopen(Comms.valuesFileName, "w"))) + { + Trace("WriteProcessMemory: fopen of '%S' failed (%u). \n", + Comms.valuesFileName, GetLastError()); + return FALSE; + } + if (!fprintf(commsFile, "%u %u '%s'\n", + pDest, lenDest, storageDescription)) + { + Trace("WriteProcessMemory: fprintf to '%S' failed (%u). \n", + Comms.valuesFileName, GetLastError()); + return FALSE; + } + PEDANTIC1(fclose, (commsFile)); + + /* Tell the parent the data is ready for it to adjust */ + PEDANTIC(ResetEvent, (Comms.hEvToHelper)); + PEDANTIC(SetEvent, (Comms.hEvFromHelper)); + + dwRet = WaitForSingleObject(Comms.hEvToHelper, TIMEOUT); /* parent is done */ + if (dwRet != WAIT_OBJECT_0) + { + Trace("helper WaitForSingleObjectTest: WaitForSingleObject " + "failed (%u)\n", GetLastError()); + return FALSE; + } + + /* check the stuff that SHOULD have changed */ + for (pCurr = pDest; pCurr < (pDest + lenDest); pCurr++) + { + if ( *pCurr != nextValue) + { + Trace("When testing '%s': alteration test failed " + "at %u offset %u. Found '%c' instead of '%c'\n.", + storageDescription, pDest, pCurr - pDest, *pCurr, nextValue); + Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer); + return FALSE; + } + } + /* check the stuff that should NOT have changed */ + for (pCurr = pBuffer; pCurr < pDest; pCurr++ ) + { + if ( *pCurr != guardValue) + { + Trace("When testing '%s': leading guard zone test failed " + "at %u offset %u. Found '%c' instead of '%c'\n.", + storageDescription, pDest, pCurr - pBuffer, *pCurr, guardValue); + Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer); + return FALSE; + } + } + for (pCurr = pDest + lenDest; pCurr < (pBuffer + lenBuffer); pCurr++ ) + { + if ( *pCurr != guardValue) + { + Trace("When testing '%s': trailing guard zone test failed " + "at %u offset %u. Found '%c' instead of '%c'\n.", + storageDescription, pDest + lenDest, pCurr - pBuffer, *pCurr, guardValue); + Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer); + return FALSE; + } + } + + return TRUE; +} + +int __cdecl main(int argc, char *argv[]) +{ + + BOOL success = TRUE; /* assume success */ + struct allhandles_t Comms = {0,0,0} ; + + /* variables to track storage to alter */ + char *pTarget = NULL; + unsigned int sizeTarget; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* hook up with the events created by the parent */ + Comms.hEvToHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcToHelperEvName); + if (!Comms.hEvToHelper) + { + Fail("WriteProcessMemory: OpenEvent of '%S' failed (%u). " + "(the event should already exist!)\n", + szcToHelperEvName, GetLastError()); + } + Comms.hEvFromHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcFromHelperEvName); + if (!Comms.hEvToHelper) + { + Trace("WriteProcessMemory: OpenEvent of '%S' failed (%u). " + "(the event should already exist!)\n", + szcFromHelperEvName, GetLastError()); + success = FALSE; + goto EXIT; + } + Comms.valuesFileName = argv[1]; + + { + char autoAllocatedOnStack[51]; + + /* Get the parent process to write to the local stack */ + success &= wpmDoIt(Comms, autoAllocatedOnStack, + sizeof(autoAllocatedOnStack), + autoAllocatedOnStack + sizeof(int), + sizeof(autoAllocatedOnStack) - 2 * sizeof(int), + "const size array on stack with int sized guards"); + } + + /* Get the parent process to write to stuff on the heap */ + sizeTarget = 2 * sizeof(int) + 23 ; /* 23 is just a random prime > 16 */ + if (!(pTarget = (char*)malloc(sizeTarget))) + { + Trace("WriteProcessMemory helper: unable to allocate '%s'->%d bytes of memory" + "(%u).\n", + argv[3], sizeTarget, GetLastError()); + success = FALSE; + goto EXIT; + + } + success &= wpmDoIt(Comms, pTarget, sizeTarget, + pTarget + sizeof(int), + sizeTarget - 2 * sizeof(int), + "array on heap with int sized guards"); + + /* just to be nice try something 16 - 2 * sizeof(int) bytes long */ + { + char autoAllocatedOnStack[16]; + + /* Get the parent process to write to the local stack */ + success &= wpmDoIt(Comms, autoAllocatedOnStack, + sizeof(autoAllocatedOnStack), + autoAllocatedOnStack + sizeof(int), + sizeof(autoAllocatedOnStack) - 2 * sizeof(int), + "another 16 byte array on stack with int sized guards inside"); + } + + /* NOTE: Don't try 0 bytes long. Win32 WriteProcessMemory claims + * it writes 8 bytes in that case! */ + + /* and 1 byte long... */ + { + char autoAllocatedOnStack[1+ 2 * sizeof(int)]; + + /* Get the parent process to write to the local stack */ + success &= wpmDoIt(Comms, autoAllocatedOnStack, + sizeof(autoAllocatedOnStack), + autoAllocatedOnStack + sizeof(int), + 1, + "no bytes with int sized guards outside on stack"); + } + + +EXIT: + /* Tell the parent that we are done */ + if (!DeleteFile(Comms.valuesFileName)) + { + Trace("helper: DeleteFile failed so parent (test1) is unlikely " + "to exit cleanly\n"); + } + PEDANTIC(ResetEvent, (Comms.hEvToHelper)); + if (!SetEvent(Comms.hEvFromHelper)) + { + Trace("helper: SetEvent failed so parent (test1) is unlikely " + "to exit cleanly\n"); + } + + free(pTarget); + PEDANTIC(CloseHandle, (Comms.hEvToHelper)); + PEDANTIC(CloseHandle, (Comms.hEvFromHelper)); + + if (!success) + { + Fail(""); + } + + PAL_Terminate(); + + return success ? PASS : FAIL; +} diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/test1.c b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/test1.c deleted file mode 100644 index 8de029d..0000000 --- a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/test1.c +++ /dev/null @@ -1,189 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: test1.c -** -** Purpose: Create a child process and some events for communications with it. -** When the child gets back to us with a memory location and a length, -** Call WriteProcessMemory on this location and check to see that it -** writes successfully. -** -** -**============================================================*/ - -#define UNICODE - -#include "commonconsts.h" - -#include - -int __cdecl main(int argc, char *argv[]) -{ - - PROCESS_INFORMATION pi; - STARTUPINFO si; - HANDLE hEvToHelper; - HANDLE hEvFromHelper; - DWORD dwExitCode; - - - DWORD dwRet; - char cmdComposeBuf[MAX_PATH]; - PWCHAR uniString; - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* Create the signals we need for cross process communication */ - hEvToHelper = CreateEvent(NULL, TRUE, FALSE, szcToHelperEvName); - if (!hEvToHelper) - { - Fail("WriteProcessMemory: CreateEvent of '%S' failed. " - "GetLastError() returned %d.\n", szcToHelperEvName, - GetLastError()); - } - if (GetLastError() == ERROR_ALREADY_EXISTS) - { - Fail("WriteProcessMemory: CreateEvent of '%S' failed. " - "(already exists!)\n", szcToHelperEvName); - } - hEvFromHelper = CreateEvent(NULL, TRUE, FALSE, szcFromHelperEvName); - if (!hEvToHelper) - { - Fail("WriteProcessMemory: CreateEvent of '%S' failed. " - "GetLastError() returned %d.\n", szcFromHelperEvName, - GetLastError()); - } - if (GetLastError() == ERROR_ALREADY_EXISTS) - { - Fail("WriteProcessMemory: CreateEvent of '%S' failed. " - "(already exists!)\n", szcFromHelperEvName); - } - ResetEvent(hEvFromHelper); - ResetEvent(hEvToHelper); - - if (!sprintf(cmdComposeBuf, "helper %s", commsFileName)) - { - Fail("Could not convert command line\n"); - } - uniString = convert(cmdComposeBuf); - - ZeroMemory( &si, sizeof(si) ); - si.cb = sizeof(si); - ZeroMemory( &pi, sizeof(pi) ); - - /* Create a new process. This is the process that will ask for - * memory munging */ - if(!CreateProcess( NULL, uniString, NULL, NULL, - FALSE, 0, NULL, NULL, &si, &pi)) - { - Trace("ERROR: CreateProcess failed to load executable '%S'. " - "GetLastError() returned %u.\n", - uniString, GetLastError()); - free(uniString); - Fail(""); - } - free(uniString); - - while(1) - { - FILE *commsFile; - char* pSrcMemory; - char* pDestMemory; - int Count; - SIZE_T wpmCount; - char incomingCMDBuffer[MAX_PATH + 1]; - - /* wait until the helper tells us that it has given us - * something to do */ - dwRet = WaitForSingleObject(hEvFromHelper, TIMEOUT); - if (dwRet != WAIT_OBJECT_0) - { - Trace("test1 WaitForSingleObjectTest: WaitForSingleObject " - "failed (%u)\n", GetLastError()); - break; /* no more work incoming */ - } - - /* get the parameters to test WriteProcessMemory with */ - if (!(commsFile = fopen(commsFileName, "r"))) - { - /* no file means there is no more work */ - break; - } - if ( NULL == fgets(incomingCMDBuffer, MAX_PATH, commsFile)) - { - Fail ("unable to read from communication file %s " - "for reasons %u & %u\n", - errno, GetLastError()); - } - PEDANTIC1(fclose,(commsFile)); - sscanf(incomingCMDBuffer, "%u %u", &pDestMemory, &Count); - if (argc > 1) - { - Trace("Preparing to write to %u bytes @ %u ('%s')\n", - Count, pDestMemory, incomingCMDBuffer); - } - - /* compose some data to write to the client process */ - if (!(pSrcMemory = malloc(Count))) - { - Trace("could not dynamically allocate memory to copy from " - "for reasons %u & %u\n", - errno, GetLastError()); - goto doneIteration; - } - memset(pSrcMemory, nextValue, Count); - - /* do the work */ - dwRet = WriteProcessMemory(pi.hProcess, - pDestMemory, - pSrcMemory, - Count, - &wpmCount); - if (!dwRet) - { - Trace("%s: Problem: on a write to %u bytes @ %u ('%s')\n", - argv[0], Count, pDestMemory, incomingCMDBuffer); - Trace("test1 WriteProcessMemory returned a%u(!=0) (GLE=%u)\n", - GetLastError()); - } - if(Count != wpmCount) - { - Trace("%s: Problem: on a write to %u bytes @ %u ('%s')\n", - argv[0], Count, pDestMemory, incomingCMDBuffer); - Trace("The number of bytes written should have been " - "%u, but was reported as %u.\n", Count, wpmCount); - } - free(pSrcMemory); - - doneIteration: - PEDANTIC(ResetEvent, (hEvFromHelper)); - PEDANTIC(SetEvent, (hEvToHelper)); - } - - /* wait for the child process to complete */ - WaitForSingleObject ( pi.hProcess, TIMEOUT ); - /* this may return a failure code on a success path */ - - /* check the exit code from the process */ - if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) ) - { - Trace( "GetExitCodeProcess call failed with error code %u\n", - GetLastError() ); - dwExitCode = FAIL; - } - - - PEDANTIC(CloseHandle, (hEvToHelper)); - PEDANTIC(CloseHandle, (hEvFromHelper)); - PEDANTIC(CloseHandle, (pi.hThread)); - PEDANTIC(CloseHandle, (pi.hProcess)); - - PAL_TerminateEx(dwExitCode); - return dwExitCode; -} diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/test1.cpp b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/test1.cpp new file mode 100644 index 0000000..f390c10 --- /dev/null +++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test1/test1.cpp @@ -0,0 +1,189 @@ +// 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. + +/*============================================================= +** +** Source: test1.c +** +** Purpose: Create a child process and some events for communications with it. +** When the child gets back to us with a memory location and a length, +** Call WriteProcessMemory on this location and check to see that it +** writes successfully. +** +** +**============================================================*/ + +#define UNICODE + +#include "commonconsts.h" + +#include + +int __cdecl main(int argc, char *argv[]) +{ + + PROCESS_INFORMATION pi; + STARTUPINFO si; + HANDLE hEvToHelper; + HANDLE hEvFromHelper; + DWORD dwExitCode; + + + DWORD dwRet; + char cmdComposeBuf[MAX_PATH]; + PWCHAR uniString; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Create the signals we need for cross process communication */ + hEvToHelper = CreateEvent(NULL, TRUE, FALSE, szcToHelperEvName); + if (!hEvToHelper) + { + Fail("WriteProcessMemory: CreateEvent of '%S' failed. " + "GetLastError() returned %d.\n", szcToHelperEvName, + GetLastError()); + } + if (GetLastError() == ERROR_ALREADY_EXISTS) + { + Fail("WriteProcessMemory: CreateEvent of '%S' failed. " + "(already exists!)\n", szcToHelperEvName); + } + hEvFromHelper = CreateEvent(NULL, TRUE, FALSE, szcFromHelperEvName); + if (!hEvToHelper) + { + Fail("WriteProcessMemory: CreateEvent of '%S' failed. " + "GetLastError() returned %d.\n", szcFromHelperEvName, + GetLastError()); + } + if (GetLastError() == ERROR_ALREADY_EXISTS) + { + Fail("WriteProcessMemory: CreateEvent of '%S' failed. " + "(already exists!)\n", szcFromHelperEvName); + } + ResetEvent(hEvFromHelper); + ResetEvent(hEvToHelper); + + if (!sprintf_s(cmdComposeBuf, _countof(cmdComposeBuf), "helper %s", commsFileName)) + { + Fail("Could not convert command line\n"); + } + uniString = convert(cmdComposeBuf); + + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + ZeroMemory( &pi, sizeof(pi) ); + + /* Create a new process. This is the process that will ask for + * memory munging */ + if(!CreateProcess( NULL, uniString, NULL, NULL, + FALSE, 0, NULL, NULL, &si, &pi)) + { + Trace("ERROR: CreateProcess failed to load executable '%S'. " + "GetLastError() returned %u.\n", + uniString, GetLastError()); + free(uniString); + Fail(""); + } + free(uniString); + + while(1) + { + FILE *commsFile; + char* pSrcMemory; + char* pDestMemory; + int Count; + SIZE_T wpmCount; + char incomingCMDBuffer[MAX_PATH + 1]; + + /* wait until the helper tells us that it has given us + * something to do */ + dwRet = WaitForSingleObject(hEvFromHelper, TIMEOUT); + if (dwRet != WAIT_OBJECT_0) + { + Trace("test1 WaitForSingleObjectTest: WaitForSingleObject " + "failed (%u)\n", GetLastError()); + break; /* no more work incoming */ + } + + /* get the parameters to test WriteProcessMemory with */ + if (!(commsFile = fopen(commsFileName, "r"))) + { + /* no file means there is no more work */ + break; + } + if ( NULL == fgets(incomingCMDBuffer, MAX_PATH, commsFile)) + { + Fail ("unable to read from communication file %s " + "for reasons %u & %u\n", + errno, GetLastError()); + } + PEDANTIC1(fclose,(commsFile)); + sscanf(incomingCMDBuffer, "%u %u", &pDestMemory, &Count); + if (argc > 1) + { + Trace("Preparing to write to %u bytes @ %u ('%s')\n", + Count, pDestMemory, incomingCMDBuffer); + } + + /* compose some data to write to the client process */ + if (!(pSrcMemory = (char*)malloc(Count))) + { + Trace("could not dynamically allocate memory to copy from " + "for reasons %u & %u\n", + errno, GetLastError()); + goto doneIteration; + } + memset(pSrcMemory, nextValue, Count); + + /* do the work */ + dwRet = WriteProcessMemory(pi.hProcess, + pDestMemory, + pSrcMemory, + Count, + &wpmCount); + if (!dwRet) + { + Trace("%s: Problem: on a write to %u bytes @ %u ('%s')\n", + argv[0], Count, pDestMemory, incomingCMDBuffer); + Trace("test1 WriteProcessMemory returned a%u(!=0) (GLE=%u)\n", + GetLastError()); + } + if(Count != wpmCount) + { + Trace("%s: Problem: on a write to %u bytes @ %u ('%s')\n", + argv[0], Count, pDestMemory, incomingCMDBuffer); + Trace("The number of bytes written should have been " + "%u, but was reported as %u.\n", Count, wpmCount); + } + free(pSrcMemory); + + doneIteration: + PEDANTIC(ResetEvent, (hEvFromHelper)); + PEDANTIC(SetEvent, (hEvToHelper)); + } + + /* wait for the child process to complete */ + WaitForSingleObject ( pi.hProcess, TIMEOUT ); + /* this may return a failure code on a success path */ + + /* check the exit code from the process */ + if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) ) + { + Trace( "GetExitCodeProcess call failed with error code %u\n", + GetLastError() ); + dwExitCode = FAIL; + } + + + PEDANTIC(CloseHandle, (hEvToHelper)); + PEDANTIC(CloseHandle, (hEvFromHelper)); + PEDANTIC(CloseHandle, (pi.hThread)); + PEDANTIC(CloseHandle, (pi.hProcess)); + + PAL_TerminateEx(dwExitCode); + return dwExitCode; +} diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/CMakeLists.txt b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/CMakeLists.txt index ecc0e06..3a5067c 100644 --- a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - test3.c + test3.cpp ) add_executable(paltest_writeprocessmemory_test3 @@ -20,7 +20,7 @@ target_link_libraries(paltest_writeprocessmemory_test3 set(HELPERSOURCES - helper.c + helper.cpp ) add_executable(paltest_writeprocessmemory_test3_helper diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/helper.c b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/helper.cpp similarity index 100% rename from src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/helper.c rename to src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/helper.cpp diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/test3.c b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/test3.c deleted file mode 100644 index 063cb4c..0000000 --- a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/test3.c +++ /dev/null @@ -1,205 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: test3.c -** -** Purpose: Create a child process and debug it. When the child -** raises an exception, it sends back a memory location. Call -** WriteProcessMemory on the memory location, but attempt to write -** more than the memory allows. This should cause an error and the -** data should be unchanged. -** -** -==============================================================*/ - -#define UNICODE - -#include "commonconsts.h" - -#include - -int __cdecl main(int argc, char *argv[]) -{ - - PROCESS_INFORMATION pi; - STARTUPINFO si; - HANDLE hEvToHelper; - HANDLE hEvFromHelper; - DWORD dwExitCode; - - - DWORD dwRet; - BOOL success = TRUE; /* assume success */ - char cmdComposeBuf[MAX_PATH]; - PWCHAR uniString; - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* Create the signals we need for cross process communication */ - hEvToHelper = CreateEvent(NULL, TRUE, FALSE, szcToHelperEvName); - if (!hEvToHelper) - { - Fail("WriteProcessMemory: CreateEvent of '%S' failed. " - "GetLastError() returned %u.\n", szcToHelperEvName, - GetLastError()); - } - if (GetLastError() == ERROR_ALREADY_EXISTS) - { - Fail("WriteProcessMemory: CreateEvent of '%S' failed. " - "(already exists!)\n", szcToHelperEvName); - } - hEvFromHelper = CreateEvent(NULL, TRUE, FALSE, szcFromHelperEvName); - if (!hEvToHelper) - { - Fail("WriteProcessMemory: CreateEvent of '%S' failed. " - "GetLastError() returned %u.\n", szcFromHelperEvName, - GetLastError()); - } - if (GetLastError() == ERROR_ALREADY_EXISTS) - { - Fail("WriteProcessMemory: CreateEvent of '%S' failed. " - "(already exists!)\n", szcFromHelperEvName); - } - - if (!sprintf(cmdComposeBuf, "helper %s", commsFileName)) - { - Fail("Could not convert command line\n"); - } - uniString = convert(cmdComposeBuf); - - ZeroMemory( &si, sizeof(si) ); - si.cb = sizeof(si); - ZeroMemory( &pi, sizeof(pi) ); - - /* Create a new process. This is the process that will ask for - * memory munging */ - if(!CreateProcess( NULL, uniString, NULL, NULL, - FALSE, 0, NULL, NULL, &si, &pi)) - { - Trace("ERROR: CreateProcess failed to load executable '%S'. " - "GetLastError() returned %u.\n", - uniString, GetLastError()); - free(uniString); - Fail(""); - } - free(uniString); - - while(1) - { - FILE *commsFile; - char* pSrcMemory; - char* pDestMemory; - int Count; - SIZE_T wpmCount; - DWORD dwExpectedErrorCode; - - char incomingCMDBuffer[MAX_PATH + 1]; - - /* wait until the helper tells us that it has given us - * something to do */ - dwRet = WaitForSingleObject(hEvFromHelper, TIMEOUT); - if (dwRet != WAIT_OBJECT_0) - { - Trace("test1 WaitForSingleObjectTest: WaitForSingleObject " - "failed (%u)\n", GetLastError()); - break; /* no more work incoming */ - } - - /* get the parameters to test WriteProcessMemory with */ - if (!(commsFile = fopen(commsFileName, "r"))) - { - /* no file means there is no more work */ - break; - } - if ( NULL == fgets(incomingCMDBuffer, MAX_PATH, commsFile)) - { - Trace ("unable to read from communication file %s " - "for reasons %u & %u\n", - errno, GetLastError()); - success = FALSE; - PEDANTIC1(fclose,(commsFile)); - /* it's not worth continuing this trial */ - goto doneIteration; - } - PEDANTIC1(fclose,(commsFile)); - sscanf(incomingCMDBuffer, "%u %u %u", - &pDestMemory, &Count, &dwExpectedErrorCode); - if (argc > 1) - { - Trace("Preparing to write to %u bytes @ %u ('%s')\n", - Count, pDestMemory, incomingCMDBuffer); - } - - /* compose some data to write to the client process */ - if (!(pSrcMemory = malloc(Count))) - { - Trace("could not dynamically allocate memory to copy from " - "for reasons %u & %u\n", - errno, GetLastError()); - success = FALSE; - goto doneIteration; - } - memset(pSrcMemory, nextValue, Count); - - /* do the work */ - dwRet = WriteProcessMemory(pi.hProcess, - pDestMemory, - pSrcMemory, - Count, - &wpmCount); - - if(dwRet != 0) - { - Trace("ERROR: Situation: '%s', return code: %u, bytes 'written': %u\n", - incomingCMDBuffer, dwRet, wpmCount); - Trace("ERROR: WriteProcessMemory did not fail as it should, as " - "it attempted to write to a range of memory which was " - "not completely accessible.\n"); - success = FALSE; - } - - if(GetLastError() != dwExpectedErrorCode) - { - Trace("ERROR: GetLastError() should have returned " - "%u , but instead it returned %u.\n", - dwExpectedErrorCode, GetLastError()); - success = FALSE; - } - free(pSrcMemory); - - doneIteration: - PEDANTIC(ResetEvent, (hEvFromHelper)); - PEDANTIC(SetEvent, (hEvToHelper)); - } - - - /* wait for the child process to complete */ - WaitForSingleObject ( pi.hProcess, TIMEOUT ); - /* this may return a failure code on a success path */ - - /* check the exit code from the process */ - if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) ) - { - Trace( "GetExitCodeProcess call failed with error code %u\n", - GetLastError() ); - dwExitCode = FAIL; - } - if(!success) - { - dwExitCode = FAIL; - } - - PEDANTIC(CloseHandle, (hEvToHelper)); - PEDANTIC(CloseHandle, (hEvFromHelper)); - PEDANTIC(CloseHandle, (pi.hThread)); - PEDANTIC(CloseHandle, (pi.hProcess)); - - PAL_Terminate(dwExitCode); - return dwExitCode; -} diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/test3.cpp b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/test3.cpp new file mode 100644 index 0000000..15b4b3f --- /dev/null +++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test3/test3.cpp @@ -0,0 +1,205 @@ +// 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. + +/*============================================================= +** +** Source: test3.c +** +** Purpose: Create a child process and debug it. When the child +** raises an exception, it sends back a memory location. Call +** WriteProcessMemory on the memory location, but attempt to write +** more than the memory allows. This should cause an error and the +** data should be unchanged. +** +** +==============================================================*/ + +#define UNICODE + +#include "commonconsts.h" + +#include + +int __cdecl main(int argc, char *argv[]) +{ + + PROCESS_INFORMATION pi; + STARTUPINFO si; + HANDLE hEvToHelper; + HANDLE hEvFromHelper; + DWORD dwExitCode; + + + DWORD dwRet; + BOOL success = TRUE; /* assume success */ + char cmdComposeBuf[MAX_PATH]; + PWCHAR uniString; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Create the signals we need for cross process communication */ + hEvToHelper = CreateEvent(NULL, TRUE, FALSE, szcToHelperEvName); + if (!hEvToHelper) + { + Fail("WriteProcessMemory: CreateEvent of '%S' failed. " + "GetLastError() returned %u.\n", szcToHelperEvName, + GetLastError()); + } + if (GetLastError() == ERROR_ALREADY_EXISTS) + { + Fail("WriteProcessMemory: CreateEvent of '%S' failed. " + "(already exists!)\n", szcToHelperEvName); + } + hEvFromHelper = CreateEvent(NULL, TRUE, FALSE, szcFromHelperEvName); + if (!hEvToHelper) + { + Fail("WriteProcessMemory: CreateEvent of '%S' failed. " + "GetLastError() returned %u.\n", szcFromHelperEvName, + GetLastError()); + } + if (GetLastError() == ERROR_ALREADY_EXISTS) + { + Fail("WriteProcessMemory: CreateEvent of '%S' failed. " + "(already exists!)\n", szcFromHelperEvName); + } + + if (!sprintf_s(cmdComposeBuf, _countof(cmdComposeBuf), "helper %s", commsFileName)) + { + Fail("Could not convert command line\n"); + } + uniString = convert(cmdComposeBuf); + + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + ZeroMemory( &pi, sizeof(pi) ); + + /* Create a new process. This is the process that will ask for + * memory munging */ + if(!CreateProcess( NULL, uniString, NULL, NULL, + FALSE, 0, NULL, NULL, &si, &pi)) + { + Trace("ERROR: CreateProcess failed to load executable '%S'. " + "GetLastError() returned %u.\n", + uniString, GetLastError()); + free(uniString); + Fail(""); + } + free(uniString); + + while(1) + { + FILE *commsFile; + char* pSrcMemory; + char* pDestMemory; + int Count; + SIZE_T wpmCount; + DWORD dwExpectedErrorCode; + + char incomingCMDBuffer[MAX_PATH + 1]; + + /* wait until the helper tells us that it has given us + * something to do */ + dwRet = WaitForSingleObject(hEvFromHelper, TIMEOUT); + if (dwRet != WAIT_OBJECT_0) + { + Trace("test1 WaitForSingleObjectTest: WaitForSingleObject " + "failed (%u)\n", GetLastError()); + break; /* no more work incoming */ + } + + /* get the parameters to test WriteProcessMemory with */ + if (!(commsFile = fopen(commsFileName, "r"))) + { + /* no file means there is no more work */ + break; + } + if ( NULL == fgets(incomingCMDBuffer, MAX_PATH, commsFile)) + { + Trace ("unable to read from communication file %s " + "for reasons %u & %u\n", + errno, GetLastError()); + success = FALSE; + PEDANTIC1(fclose,(commsFile)); + /* it's not worth continuing this trial */ + goto doneIteration; + } + PEDANTIC1(fclose,(commsFile)); + sscanf(incomingCMDBuffer, "%u %u %u", + &pDestMemory, &Count, &dwExpectedErrorCode); + if (argc > 1) + { + Trace("Preparing to write to %u bytes @ %u ('%s')\n", + Count, pDestMemory, incomingCMDBuffer); + } + + /* compose some data to write to the client process */ + if (!(pSrcMemory = (char*)malloc(Count))) + { + Trace("could not dynamically allocate memory to copy from " + "for reasons %u & %u\n", + errno, GetLastError()); + success = FALSE; + goto doneIteration; + } + memset(pSrcMemory, nextValue, Count); + + /* do the work */ + dwRet = WriteProcessMemory(pi.hProcess, + pDestMemory, + pSrcMemory, + Count, + &wpmCount); + + if(dwRet != 0) + { + Trace("ERROR: Situation: '%s', return code: %u, bytes 'written': %u\n", + incomingCMDBuffer, dwRet, wpmCount); + Trace("ERROR: WriteProcessMemory did not fail as it should, as " + "it attempted to write to a range of memory which was " + "not completely accessible.\n"); + success = FALSE; + } + + if(GetLastError() != dwExpectedErrorCode) + { + Trace("ERROR: GetLastError() should have returned " + "%u , but instead it returned %u.\n", + dwExpectedErrorCode, GetLastError()); + success = FALSE; + } + free(pSrcMemory); + + doneIteration: + PEDANTIC(ResetEvent, (hEvFromHelper)); + PEDANTIC(SetEvent, (hEvToHelper)); + } + + + /* wait for the child process to complete */ + WaitForSingleObject ( pi.hProcess, TIMEOUT ); + /* this may return a failure code on a success path */ + + /* check the exit code from the process */ + if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) ) + { + Trace( "GetExitCodeProcess call failed with error code %u\n", + GetLastError() ); + dwExitCode = FAIL; + } + if(!success) + { + dwExitCode = FAIL; + } + + PEDANTIC(CloseHandle, (hEvToHelper)); + PEDANTIC(CloseHandle, (hEvFromHelper)); + PEDANTIC(CloseHandle, (pi.hThread)); + PEDANTIC(CloseHandle, (pi.hProcess)); + + PAL_Terminate(dwExitCode); + return dwExitCode; +} diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/CMakeLists.txt b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/CMakeLists.txt index cf1ce13..7cba090 100644 --- a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - test4.c + test4.cpp ) add_executable(paltest_writeprocessmemory_test4 @@ -20,7 +20,7 @@ target_link_libraries(paltest_writeprocessmemory_test4 set(HELPERSOURCES - helper.c + helper.cpp ) add_executable(paltest_writeprocessmemory_test4_helper diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/helper.c b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/helper.cpp similarity index 100% rename from src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/helper.c rename to src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/helper.cpp diff --git a/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/test4.c b/src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/test4.c rename to src/pal/tests/palsuite/debug_api/WriteProcessMemory/test4/test4.cpp diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/CMakeLists.txt index adbc8ae..4e30869 100644 --- a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - PAL_EXCEPT_FILTER.c + PAL_EXCEPT_FILTER.cpp ) add_executable(paltest_pal_except_filter_test1 diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/PAL_EXCEPT_FILTER.c b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/PAL_EXCEPT_FILTER.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/PAL_EXCEPT_FILTER.c rename to src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/PAL_EXCEPT_FILTER.cpp diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/CMakeLists.txt index 62cda70..3f979c0 100644 --- a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - pal_except_filter.c + pal_except_filter.cpp ) add_executable(paltest_pal_except_filter_test2 diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/pal_except_filter.c b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/pal_except_filter.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/pal_except_filter.c rename to src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/pal_except_filter.cpp diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/CMakeLists.txt index cc68fb0..2bdf44e 100644 --- a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - pal_except_filter.c + pal_except_filter.cpp ) add_executable(paltest_pal_except_filter_test3 diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/pal_except_filter.c b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/pal_except_filter.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/pal_except_filter.c rename to src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/pal_except_filter.cpp diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/CMakeLists.txt index 21c3b5d..cf0a5e7 100644 --- a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - PAL_EXCEPT_FILTER_EX.c + PAL_EXCEPT_FILTER_EX.cpp ) add_executable(paltest_pal_except_filter_ex_test1 diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/PAL_EXCEPT_FILTER_EX.c b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/PAL_EXCEPT_FILTER_EX.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/PAL_EXCEPT_FILTER_EX.c rename to src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/PAL_EXCEPT_FILTER_EX.cpp diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/CMakeLists.txt index 350acff..a3f82c2 100644 --- a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - pal_except_filter_ex.c + pal_except_filter_ex.cpp ) add_executable(paltest_pal_except_filter_ex_test2 diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/pal_except_filter_ex.c b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/pal_except_filter_ex.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/pal_except_filter_ex.c rename to src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/pal_except_filter_ex.cpp diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/CMakeLists.txt index 7f485c8..532b29a 100644 --- a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - pal_except_filter.c + pal_except_filter.cpp ) add_executable(paltest_pal_except_filter_ex_test3 diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/pal_except_filter.c b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/pal_except_filter.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/pal_except_filter.c rename to src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/pal_except_filter.cpp diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/CMakeLists.txt index 8a1a832..b478de6 100644 --- a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - PAL_TRY_EXCEPT.c + PAL_TRY_EXCEPT.cpp ) add_executable(paltest_pal_try_except_test1 diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/PAL_TRY_EXCEPT.c b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/PAL_TRY_EXCEPT.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/PAL_TRY_EXCEPT.c rename to src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/PAL_TRY_EXCEPT.cpp diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/CMakeLists.txt index cdf3719..0e344a9 100644 --- a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - PAL_TRY_EXCEPT.c + PAL_TRY_EXCEPT.cpp ) add_executable(paltest_pal_try_except_test2 diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/PAL_TRY_EXCEPT.c b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/PAL_TRY_EXCEPT.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/PAL_TRY_EXCEPT.c rename to src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/PAL_TRY_EXCEPT.cpp diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/CMakeLists.txt index c30877f..cced8a1 100644 --- a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - PAL_TRY_EXCEPT_EX.c + PAL_TRY_EXCEPT_EX.cpp ) add_executable(paltest_pal_try_except_ex_test1 diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/PAL_TRY_EXCEPT_EX.c b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/PAL_TRY_EXCEPT_EX.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/PAL_TRY_EXCEPT_EX.c rename to src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/PAL_TRY_EXCEPT_EX.cpp diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/CMakeLists.txt index 0d4c4db..c3549b5 100644 --- a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - PAL_TRY_EXCEPT_EX.c + PAL_TRY_EXCEPT_EX.cpp ) add_executable(paltest_pal_try_except_ex_test2 diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/PAL_TRY_EXCEPT_EX.c b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/PAL_TRY_EXCEPT_EX.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/PAL_TRY_EXCEPT_EX.c rename to src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/PAL_TRY_EXCEPT_EX.cpp diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/CMakeLists.txt index dc797f2..34790da 100644 --- a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - PAL_TRY_EXCEPT_EX.c + PAL_TRY_EXCEPT_EX.cpp ) add_executable(paltest_pal_try_except_ex_test3 diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/PAL_TRY_EXCEPT_EX.c b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/PAL_TRY_EXCEPT_EX.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/PAL_TRY_EXCEPT_EX.c rename to src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/PAL_TRY_EXCEPT_EX.cpp diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/CMakeLists.txt index a5fdd26..f004db1 100644 --- a/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - PAL_TRY_LEAVE_FINALLY.c + PAL_TRY_LEAVE_FINALLY.cpp ) add_executable(paltest_pal_try_leave_finally_test1 diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/PAL_TRY_LEAVE_FINALLY.c b/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/PAL_TRY_LEAVE_FINALLY.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/PAL_TRY_LEAVE_FINALLY.c rename to src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/PAL_TRY_LEAVE_FINALLY.cpp diff --git a/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/CMakeLists.txt index e526029..0684273 100644 --- a/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_setunhandledexceptionfilter_test1 diff --git a/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/test1.c b/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/test1.c rename to src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/test1.cpp diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test1/CMakeLists.txt index 635e35d..b219238 100644 --- a/src/pal/tests/palsuite/exception_handling/pal_except/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/pal_except/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_pal_except_test1 diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test1/test1.c b/src/pal/tests/palsuite/exception_handling/pal_except/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/pal_except/test1/test1.c rename to src/pal/tests/palsuite/exception_handling/pal_except/test1/test1.cpp diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test2/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test2/CMakeLists.txt index 813b0e6..27a7253 100644 --- a/src/pal/tests/palsuite/exception_handling/pal_except/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/pal_except/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_pal_except_test2 diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test2/test2.c b/src/pal/tests/palsuite/exception_handling/pal_except/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/pal_except/test2/test2.c rename to src/pal/tests/palsuite/exception_handling/pal_except/test2/test2.cpp diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test3/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test3/CMakeLists.txt index 5fc3b09..680341a 100644 --- a/src/pal/tests/palsuite/exception_handling/pal_except/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/pal_except/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_pal_except_test3 diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test3/test3.c b/src/pal/tests/palsuite/exception_handling/pal_except/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/pal_except/test3/test3.c rename to src/pal/tests/palsuite/exception_handling/pal_except/test3/test3.cpp diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test4/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test4/CMakeLists.txt index cc054d1..98eb7bf 100644 --- a/src/pal/tests/palsuite/exception_handling/pal_except/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/pal_except/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_pal_except_test4 diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test4/test4.c b/src/pal/tests/palsuite/exception_handling/pal_except/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/pal_except/test4/test4.c rename to src/pal/tests/palsuite/exception_handling/pal_except/test4/test4.cpp diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test5/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test5/CMakeLists.txt index 7b8f1d0..9a39e32 100644 --- a/src/pal/tests/palsuite/exception_handling/pal_except/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/pal_except/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_pal_except_test5 diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test5/test5.c b/src/pal/tests/palsuite/exception_handling/pal_except/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/pal_except/test5/test5.c rename to src/pal/tests/palsuite/exception_handling/pal_except/test5/test5.cpp diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test6/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test6/CMakeLists.txt index 7f943bf..d009128 100644 --- a/src/pal/tests/palsuite/exception_handling/pal_except/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/pal_except/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test6.c + test6.cpp ) add_executable(paltest_pal_except_test6 diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test6/test6.c b/src/pal/tests/palsuite/exception_handling/pal_except/test6/test6.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/pal_except/test6/test6.c rename to src/pal/tests/palsuite/exception_handling/pal_except/test6/test6.cpp diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test7/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test7/CMakeLists.txt index 09399c8..33fee62 100644 --- a/src/pal/tests/palsuite/exception_handling/pal_except/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/pal_except/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test7.c + test7.cpp ) add_executable(paltest_pal_except_test7 diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test7/test7.c b/src/pal/tests/palsuite/exception_handling/pal_except/test7/test7.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/pal_except/test7/test7.c rename to src/pal/tests/palsuite/exception_handling/pal_except/test7/test7.cpp diff --git a/src/pal/tests/palsuite/exception_handling/pal_finally/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_finally/test1/CMakeLists.txt index 5d947ad..67cc6c0 100644 --- a/src/pal/tests/palsuite/exception_handling/pal_finally/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/pal_finally/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - pal_finally.c + pal_finally.cpp ) add_executable(paltest_pal_finally_test1 diff --git a/src/pal/tests/palsuite/exception_handling/pal_finally/test1/pal_finally.c b/src/pal/tests/palsuite/exception_handling/pal_finally/test1/pal_finally.cpp similarity index 100% rename from src/pal/tests/palsuite/exception_handling/pal_finally/test1/pal_finally.c rename to src/pal/tests/palsuite/exception_handling/pal_finally/test1/pal_finally.cpp diff --git a/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.cpp b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.cpp index 6146908..000ed62 100644 --- a/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.cpp +++ b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.cpp @@ -20,6 +20,17 @@ int InitializeDllTest1() return PAL_InitializeDLL(); } +__attribute__((noinline,optnone)) +static void FailingFunction(volatile int *p) +{ + if (p == NULL) + { + throw PAL_SEHException(); + } + + *p = 1; // Causes an access violation exception +} + BOOL bTry = FALSE; BOOL bExcept = FALSE; @@ -33,7 +44,8 @@ int DllTest1() volatile int* p = (volatile int *)0x11; // Invalid pointer bTry = TRUE; // Indicate we hit the PAL_TRY block - *p = 1; // Causes an access violation exception + FailingFunction(p); // Throw in function to fool C++ runtime into handling + // h/w exception Fail("ERROR: code was executed after the access violation.\n"); } diff --git a/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.cpp b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.cpp index 1e85821..27fc213 100644 --- a/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.cpp +++ b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.cpp @@ -20,6 +20,17 @@ int InitializeDllTest2() return PAL_InitializeDLL(); } +__attribute__((noinline,optnone)) +static void FailingFunction(volatile int *p) +{ + if (p == NULL) + { + throw PAL_SEHException(); + } + + *p = 1; // Causes an access violation exception +} + BOOL bTry = FALSE; BOOL bExcept = FALSE; @@ -33,7 +44,8 @@ int DllTest2() volatile int* p = (volatile int *)0x22; // Invalid pointer bTry = TRUE; // Indicate we hit the PAL_TRY block - *p = 2; // Causes an access violation exception + FailingFunction(p); // Throw in function to fool C++ runtime into handling + // h/w exception Fail("ERROR: code was executed after the access violation.\n"); } diff --git a/src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/AreFileApisANSI.c b/src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/AreFileApisANSI.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/AreFileApisANSI.c rename to src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/AreFileApisANSI.cpp diff --git a/src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/CMakeLists.txt index 4f50127..e624bef 100644 --- a/src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/AreFileApisANSI/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - AreFileApisANSI.c + AreFileApisANSI.cpp ) add_executable(paltest_arefileapisansi_test1 diff --git a/src/pal/tests/palsuite/file_io/CompareFileTime/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CompareFileTime/test1/CMakeLists.txt index fdcb655..fa96a44 100644 --- a/src/pal/tests/palsuite/file_io/CompareFileTime/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/CompareFileTime/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CompareFileTime.c + CompareFileTime.cpp ) add_executable(paltest_comparefiletime_test1 diff --git a/src/pal/tests/palsuite/file_io/CompareFileTime/test1/CompareFileTime.c b/src/pal/tests/palsuite/file_io/CompareFileTime/test1/CompareFileTime.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/CompareFileTime/test1/CompareFileTime.c rename to src/pal/tests/palsuite/file_io/CompareFileTime/test1/CompareFileTime.cpp diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CopyFileA/test1/CMakeLists.txt index b52e507..13abbc0 100644 --- a/src/pal/tests/palsuite/file_io/CopyFileA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/CopyFileA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CopyFileA.c + CopyFileA.cpp ) add_executable(paltest_copyfilea_test1 diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/test1/CopyFileA.c b/src/pal/tests/palsuite/file_io/CopyFileA/test1/CopyFileA.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/CopyFileA/test1/CopyFileA.c rename to src/pal/tests/palsuite/file_io/CopyFileA/test1/CopyFileA.cpp diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CopyFileA/test2/CMakeLists.txt index 7454f32..cd0d8bc 100644 --- a/src/pal/tests/palsuite/file_io/CopyFileA/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/CopyFileA/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_copyfilea_test2 diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/test2/test2.c b/src/pal/tests/palsuite/file_io/CopyFileA/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/CopyFileA/test2/test2.c rename to src/pal/tests/palsuite/file_io/CopyFileA/test2/test2.cpp diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CopyFileA/test3/CMakeLists.txt index 986be9f..0bb41b8 100644 --- a/src/pal/tests/palsuite/file_io/CopyFileA/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/CopyFileA/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_copyfilea_test3 diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/test3/test3.c b/src/pal/tests/palsuite/file_io/CopyFileA/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/CopyFileA/test3/test3.c rename to src/pal/tests/palsuite/file_io/CopyFileA/test3/test3.cpp diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CopyFileA/test4/CMakeLists.txt index fb48c83..12f85d1 100644 --- a/src/pal/tests/palsuite/file_io/CopyFileA/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/CopyFileA/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_copyfilea_test4 diff --git a/src/pal/tests/palsuite/file_io/CopyFileA/test4/test4.c b/src/pal/tests/palsuite/file_io/CopyFileA/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/CopyFileA/test4/test4.c rename to src/pal/tests/palsuite/file_io/CopyFileA/test4/test4.cpp diff --git a/src/pal/tests/palsuite/file_io/CopyFileW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CopyFileW/test1/CMakeLists.txt index 766b120..20c8141 100644 --- a/src/pal/tests/palsuite/file_io/CopyFileW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/CopyFileW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CopyFileW.c + CopyFileW.cpp ) add_executable(paltest_copyfilew_test1 diff --git a/src/pal/tests/palsuite/file_io/CopyFileW/test1/CopyFileW.c b/src/pal/tests/palsuite/file_io/CopyFileW/test1/CopyFileW.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/CopyFileW/test1/CopyFileW.c rename to src/pal/tests/palsuite/file_io/CopyFileW/test1/CopyFileW.cpp diff --git a/src/pal/tests/palsuite/file_io/CopyFileW/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CopyFileW/test2/CMakeLists.txt index 5c0030b..4201bdc 100644 --- a/src/pal/tests/palsuite/file_io/CopyFileW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/CopyFileW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_copyfilew_test2 diff --git a/src/pal/tests/palsuite/file_io/CopyFileW/test2/test2.c b/src/pal/tests/palsuite/file_io/CopyFileW/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/CopyFileW/test2/test2.c rename to src/pal/tests/palsuite/file_io/CopyFileW/test2/test2.cpp diff --git a/src/pal/tests/palsuite/file_io/CopyFileW/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CopyFileW/test3/CMakeLists.txt index 52d9aad..d0fd94c 100644 --- a/src/pal/tests/palsuite/file_io/CopyFileW/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/CopyFileW/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_copyfilew_test3 diff --git a/src/pal/tests/palsuite/file_io/CopyFileW/test3/test3.c b/src/pal/tests/palsuite/file_io/CopyFileW/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/CopyFileW/test3/test3.c rename to src/pal/tests/palsuite/file_io/CopyFileW/test3/test3.cpp diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/CMakeLists.txt index f8cdf19..1dc87fa 100644 --- a/src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateDirectoryA.c + CreateDirectoryA.cpp ) add_executable(paltest_createdirectorya_test1 diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/CreateDirectoryA.c b/src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/CreateDirectoryA.c deleted file mode 100644 index 2bb441e..0000000 --- a/src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/CreateDirectoryA.c +++ /dev/null @@ -1,296 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: CreateDirectoryA.c -** -** Purpose: Tests the PAL implementation of the CreateDirectoryA function. -** -** Depends on: -** RemoveDirectoryW (since RemoveDirectoryA is unavailable) -** GetCurrentDirectoryA -** -** -**===================================================================*/ - -#include - - -/* apparently, under WIN32 the max path size is 248 but under - BSD it is _MAX_PATH */ -#if WIN32 -#define CREATE_MAX_PATH_SIZE 248 -#else -#define CREATE_MAX_PATH_SIZE _MAX_PATH -#endif - - -int __cdecl main(int argc, char *argv[]) -{ - const char* szTestDir = {"test_directory"}; - const char* szDotDir = {".dotDirectory"}; - BOOL bRc = FALSE; - BOOL bSuccess = FALSE; - const int buf_size = CREATE_MAX_PATH_SIZE + 10; - char szDirName[CREATE_MAX_PATH_SIZE + 10]; - char buffer[CREATE_MAX_PATH_SIZE + 10]; - WCHAR* pTemp = NULL; - DWORD curDirLen; - DWORD curDirectory = 1024; - - if (0 != PAL_Initialize(argc,argv)) - { - return FAIL; - } - - - /* directory does not exist */ - bRc = CreateDirectoryA(szTestDir, NULL); - if (bRc == FALSE) - { - Fail("CreateDirectoryA: Failed to create \"%s\" with error code %ld\n", - szTestDir, - GetLastError()); - } - - - /* directory exists should fail */ - bRc = CreateDirectoryA(szTestDir, NULL); - if (bRc == TRUE) - { - pTemp = convert((LPSTR)szTestDir); - bRc = RemoveDirectoryW(pTemp); - free(pTemp); - if (!bRc) - { - Trace("CreateDirectoryA: RemoveDirectoryW failed to remove " - "\"%s\" with the error code %ld.\n", - szTestDir, - GetLastError()); - } - Fail("CreateDirectoryA: Succeeded creating the directory" - "\"%s\" when it exists already.\n", - szTestDir); - } - else - { - pTemp = convert((LPSTR)szTestDir); - bRc = RemoveDirectoryW(pTemp); - free(pTemp); - if (!bRc) - { - Fail("CreateDirectoryA: RemoveDirectoryW failed to remove " - "\"%s\" with the error code %ld.\n", - szTestDir, - GetLastError()); - } - } - - - /* long directory names (CREATE_MAX_PATH_SIZE - 1, CREATE_MAX_PATH_SIZE - and CREATE_MAX_PATH_SIZE + 1 characters - including terminating null char) */ - - curDirLen = GetCurrentDirectoryA(0, NULL); - - memset(szDirName, 0, buf_size); - memset(szDirName, 'a', CREATE_MAX_PATH_SIZE - 2 - curDirLen); - bRc = CreateDirectoryA(szDirName, NULL); - if (bRc == FALSE) - { - Fail("CreateDirectoryA: Failed to create a directory" - " name %d chars long with the error code %ld\n", - strlen(szDirName), - GetLastError()); - } - else - { - /* Check to see if it's possible to navigate to directory */ - GetCurrentDirectoryA(curDirectory, buffer); - bSuccess = SetCurrentDirectoryA(szDirName); - if(!bSuccess) - { - Fail("CreateDirectoryA: SetCurrentDirectoryA failed to " - "navigate to the newly created directory with error " - "code %u.\n", GetLastError()); - } - - /* Set directory back to initial directory */ - SetCurrentDirectoryA(buffer); - - pTemp = convert((LPSTR)szDirName); - bRc = RemoveDirectoryW(pTemp); - free(pTemp); - if (!bRc) - { - Fail("CreateDirectoryA: RemoveDirectoryW failed to remove " - "\"%s\" with the error code %ld.\n", - szDirName, - GetLastError()); - } - } - - - memset(szDirName, 0, buf_size); - memset(szDirName, 'a', CREATE_MAX_PATH_SIZE - 1 - curDirLen); - bRc = CreateDirectoryA(szDirName, NULL); - if (bRc == FALSE) - { - Fail("CreateDirectoryA: Failed to create a directory" - " name %d chars long with error code %ld\n", - strlen(szDirName), - GetLastError()); - } - else - { - /* Check to see if it's possible to navigate to directory */ - GetCurrentDirectoryA(curDirectory, buffer); - bSuccess = SetCurrentDirectoryA(szDirName); - if(!bSuccess) - { - Fail("CreateDirectoryA: SetCurrentDirectoryA failed to " - "navigate to the newly created directory with error " - "code %u.\n", GetLastError()); - } - - /* Set Directroy back to initial directory */ - SetCurrentDirectoryA(buffer); - - pTemp = convert(szDirName); - bRc = RemoveDirectoryW(pTemp); - free(pTemp); - if (!bRc) - { - Fail("CreateDirectoryA: RemoveDirectoryW failed to remove " - "\"%s\" with the error code %ld.\n", - szDirName, - GetLastError()); - } - } - - memset(szDirName, 0, buf_size); - memset(szDirName, 'a', CREATE_MAX_PATH_SIZE - curDirLen); - bRc = CreateDirectoryA(szDirName, NULL); - if (bRc != FALSE) - { - /* Check to see if it's possible to navigate to directory */ - GetCurrentDirectoryA(curDirectory, buffer); - bSuccess = SetCurrentDirectoryA(szDirName); - if(!bSuccess) - { - Fail("CreateDirectoryA: SetCurrentDirectoryA failed to " - "navigate to the newly created directory with error " - "code %u.\n", GetLastError()); - } - - /* set directory back to initial directory */ - SetCurrentDirectoryA(buffer); - - pTemp = convert(szDirName); - bRc = RemoveDirectoryW(pTemp); - free(pTemp); - if (!bRc) - { - Trace("CreateDirectoryA: RemoveDirectoryW failed to remove " - "\"%s\" with the error code %ld.\n", - szDirName, - GetLastError()); - } - if (strlen(szDirName) > CREATE_MAX_PATH_SIZE) - { - Fail("CreateDirectoryA: Failed because it created a directory" - " name 1 character longer (%d chars) than the max dir size " - "allowed\n", - strlen(szDirName)); - } - } - - - /* long directory name CREATE_MAX_PATH_SIZE + 3 chars including "..\" - (real path length <= CREATE_MAX_PATH_SIZE) */ - memset(szDirName, 0, buf_size); - memset(szDirName, 'a', CREATE_MAX_PATH_SIZE + 3 - 1 - curDirLen); - szDirName[0] = '.'; - szDirName[1] = '.'; - szDirName[2] = '\\'; - bRc = CreateDirectoryA(szDirName, NULL); - if (bRc == FALSE) - { - Fail("CreateDirectoryA: Failed to create a directory name more " - "than %d chars long and its real path name is less " - "than %d chars, error %u\n", - CREATE_MAX_PATH_SIZE, - CREATE_MAX_PATH_SIZE, GetLastError()); - } - else - { - /* Check to see if it's possible to navigate to directory */ - GetCurrentDirectoryA(curDirectory, buffer); - bSuccess = SetCurrentDirectoryA(szDirName); - if(!bSuccess) - { - Fail("CreateDirectoryA: SetCurrentDirectoryA failed to " - "navigate to the newly created directory with error " - "code %u.\n", GetLastError()); - } - - /* set directory back to initial directory */ - SetCurrentDirectoryA(buffer); - - pTemp = convert(szDirName); - bRc = RemoveDirectoryW(pTemp); - free(pTemp); - if (!bRc) - { - Fail("CreateDirectoryA: RemoveDirectoryW failed to remove " - " \"%s\" with the error code %ld.\n", - szDirName, - GetLastError()); - } - } - - - /* directories with dots */ - memset(szDirName, 0, buf_size); - sprintf(szDirName, szDotDir); - bRc = CreateDirectoryA(szDirName, NULL); - if (bRc == FALSE) - { - Fail("CreateDirectoryA: Failed to create \"%s\" with error code %ld\n", - szDotDir, - GetLastError()); - } - else - { - - /* Check to see if it's possible to navigate to directory */ - GetCurrentDirectoryA(curDirectory, buffer); - bSuccess = SetCurrentDirectoryA(szDirName); - if(!bSuccess) - { - Fail("CreateDirectoryA: SetCurrentDirectoryA failed to " - "navigate to the newly created directory with error " - "code %u.\n", GetLastError()); - } - - /* set directory back to initial directory */ - SetCurrentDirectoryA(buffer); - - pTemp = convert((LPSTR)szDotDir); - bRc = RemoveDirectoryW(pTemp); - free(pTemp); - if (!bRc) - { - Fail("CreateDirectoryA: RemoveDirectoryW failed to remove " - " \"%s\" with the error code %ld.\n", - szDotDir, - GetLastError()); - } - } - - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/CreateDirectoryA.cpp b/src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/CreateDirectoryA.cpp new file mode 100644 index 0000000..4082d38 --- /dev/null +++ b/src/pal/tests/palsuite/file_io/CreateDirectoryA/test1/CreateDirectoryA.cpp @@ -0,0 +1,296 @@ +// 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. + +/*===================================================================== +** +** Source: CreateDirectoryA.c +** +** Purpose: Tests the PAL implementation of the CreateDirectoryA function. +** +** Depends on: +** RemoveDirectoryW (since RemoveDirectoryA is unavailable) +** GetCurrentDirectoryA +** +** +**===================================================================*/ + +#include + + +/* apparently, under WIN32 the max path size is 248 but under + BSD it is _MAX_PATH */ +#if WIN32 +#define CREATE_MAX_PATH_SIZE 248 +#else +#define CREATE_MAX_PATH_SIZE _MAX_PATH +#endif + + +int __cdecl main(int argc, char *argv[]) +{ + const char* szTestDir = {"test_directory"}; + const char* szDotDir = {".dotDirectory"}; + BOOL bRc = FALSE; + BOOL bSuccess = FALSE; + const int buf_size = CREATE_MAX_PATH_SIZE + 10; + char szDirName[CREATE_MAX_PATH_SIZE + 10]; + char buffer[CREATE_MAX_PATH_SIZE + 10]; + WCHAR* pTemp = NULL; + DWORD curDirLen; + DWORD curDirectory = 1024; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + + /* directory does not exist */ + bRc = CreateDirectoryA(szTestDir, NULL); + if (bRc == FALSE) + { + Fail("CreateDirectoryA: Failed to create \"%s\" with error code %ld\n", + szTestDir, + GetLastError()); + } + + + /* directory exists should fail */ + bRc = CreateDirectoryA(szTestDir, NULL); + if (bRc == TRUE) + { + pTemp = convert((LPSTR)szTestDir); + bRc = RemoveDirectoryW(pTemp); + free(pTemp); + if (!bRc) + { + Trace("CreateDirectoryA: RemoveDirectoryW failed to remove " + "\"%s\" with the error code %ld.\n", + szTestDir, + GetLastError()); + } + Fail("CreateDirectoryA: Succeeded creating the directory" + "\"%s\" when it exists already.\n", + szTestDir); + } + else + { + pTemp = convert((LPSTR)szTestDir); + bRc = RemoveDirectoryW(pTemp); + free(pTemp); + if (!bRc) + { + Fail("CreateDirectoryA: RemoveDirectoryW failed to remove " + "\"%s\" with the error code %ld.\n", + szTestDir, + GetLastError()); + } + } + + + /* long directory names (CREATE_MAX_PATH_SIZE - 1, CREATE_MAX_PATH_SIZE + and CREATE_MAX_PATH_SIZE + 1 characters + including terminating null char) */ + + curDirLen = GetCurrentDirectoryA(0, NULL); + + memset(szDirName, 0, buf_size); + memset(szDirName, 'a', CREATE_MAX_PATH_SIZE - 2 - curDirLen); + bRc = CreateDirectoryA(szDirName, NULL); + if (bRc == FALSE) + { + Fail("CreateDirectoryA: Failed to create a directory" + " name %d chars long with the error code %ld\n", + strlen(szDirName), + GetLastError()); + } + else + { + /* Check to see if it's possible to navigate to directory */ + GetCurrentDirectoryA(curDirectory, buffer); + bSuccess = SetCurrentDirectoryA(szDirName); + if(!bSuccess) + { + Fail("CreateDirectoryA: SetCurrentDirectoryA failed to " + "navigate to the newly created directory with error " + "code %u.\n", GetLastError()); + } + + /* Set directory back to initial directory */ + SetCurrentDirectoryA(buffer); + + pTemp = convert((LPSTR)szDirName); + bRc = RemoveDirectoryW(pTemp); + free(pTemp); + if (!bRc) + { + Fail("CreateDirectoryA: RemoveDirectoryW failed to remove " + "\"%s\" with the error code %ld.\n", + szDirName, + GetLastError()); + } + } + + + memset(szDirName, 0, buf_size); + memset(szDirName, 'a', CREATE_MAX_PATH_SIZE - 1 - curDirLen); + bRc = CreateDirectoryA(szDirName, NULL); + if (bRc == FALSE) + { + Fail("CreateDirectoryA: Failed to create a directory" + " name %d chars long with error code %ld\n", + strlen(szDirName), + GetLastError()); + } + else + { + /* Check to see if it's possible to navigate to directory */ + GetCurrentDirectoryA(curDirectory, buffer); + bSuccess = SetCurrentDirectoryA(szDirName); + if(!bSuccess) + { + Fail("CreateDirectoryA: SetCurrentDirectoryA failed to " + "navigate to the newly created directory with error " + "code %u.\n", GetLastError()); + } + + /* Set Directroy back to initial directory */ + SetCurrentDirectoryA(buffer); + + pTemp = convert(szDirName); + bRc = RemoveDirectoryW(pTemp); + free(pTemp); + if (!bRc) + { + Fail("CreateDirectoryA: RemoveDirectoryW failed to remove " + "\"%s\" with the error code %ld.\n", + szDirName, + GetLastError()); + } + } + + memset(szDirName, 0, buf_size); + memset(szDirName, 'a', CREATE_MAX_PATH_SIZE - curDirLen); + bRc = CreateDirectoryA(szDirName, NULL); + if (bRc != FALSE) + { + /* Check to see if it's possible to navigate to directory */ + GetCurrentDirectoryA(curDirectory, buffer); + bSuccess = SetCurrentDirectoryA(szDirName); + if(!bSuccess) + { + Fail("CreateDirectoryA: SetCurrentDirectoryA failed to " + "navigate to the newly created directory with error " + "code %u.\n", GetLastError()); + } + + /* set directory back to initial directory */ + SetCurrentDirectoryA(buffer); + + pTemp = convert(szDirName); + bRc = RemoveDirectoryW(pTemp); + free(pTemp); + if (!bRc) + { + Trace("CreateDirectoryA: RemoveDirectoryW failed to remove " + "\"%s\" with the error code %ld.\n", + szDirName, + GetLastError()); + } + if (strlen(szDirName) > CREATE_MAX_PATH_SIZE) + { + Fail("CreateDirectoryA: Failed because it created a directory" + " name 1 character longer (%d chars) than the max dir size " + "allowed\n", + strlen(szDirName)); + } + } + + + /* long directory name CREATE_MAX_PATH_SIZE + 3 chars including "..\" + (real path length <= CREATE_MAX_PATH_SIZE) */ + memset(szDirName, 0, buf_size); + memset(szDirName, 'a', CREATE_MAX_PATH_SIZE + 3 - 1 - curDirLen); + szDirName[0] = '.'; + szDirName[1] = '.'; + szDirName[2] = '\\'; + bRc = CreateDirectoryA(szDirName, NULL); + if (bRc == FALSE) + { + Fail("CreateDirectoryA: Failed to create a directory name more " + "than %d chars long and its real path name is less " + "than %d chars, error %u\n", + CREATE_MAX_PATH_SIZE, + CREATE_MAX_PATH_SIZE, GetLastError()); + } + else + { + /* Check to see if it's possible to navigate to directory */ + GetCurrentDirectoryA(curDirectory, buffer); + bSuccess = SetCurrentDirectoryA(szDirName); + if(!bSuccess) + { + Fail("CreateDirectoryA: SetCurrentDirectoryA failed to " + "navigate to the newly created directory with error " + "code %u.\n", GetLastError()); + } + + /* set directory back to initial directory */ + SetCurrentDirectoryA(buffer); + + pTemp = convert(szDirName); + bRc = RemoveDirectoryW(pTemp); + free(pTemp); + if (!bRc) + { + Fail("CreateDirectoryA: RemoveDirectoryW failed to remove " + " \"%s\" with the error code %ld.\n", + szDirName, + GetLastError()); + } + } + + + /* directories with dots */ + memset(szDirName, 0, buf_size); + sprintf_s(szDirName, _countof(szDirName), szDotDir); + bRc = CreateDirectoryA(szDirName, NULL); + if (bRc == FALSE) + { + Fail("CreateDirectoryA: Failed to create \"%s\" with error code %ld\n", + szDotDir, + GetLastError()); + } + else + { + + /* Check to see if it's possible to navigate to directory */ + GetCurrentDirectoryA(curDirectory, buffer); + bSuccess = SetCurrentDirectoryA(szDirName); + if(!bSuccess) + { + Fail("CreateDirectoryA: SetCurrentDirectoryA failed to " + "navigate to the newly created directory with error " + "code %u.\n", GetLastError()); + } + + /* set directory back to initial directory */ + SetCurrentDirectoryA(buffer); + + pTemp = convert((LPSTR)szDotDir); + bRc = RemoveDirectoryW(pTemp); + free(pTemp); + if (!bRc) + { + Fail("CreateDirectoryA: RemoveDirectoryW failed to remove " + " \"%s\" with the error code %ld.\n", + szDotDir, + GetLastError()); + } + } + + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/CMakeLists.txt index a50a986..3ee8abb 100644 --- a/src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - createdirectorya.c + createdirectorya.cpp ) add_executable(paltest_createdirectorya_test2 diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/createdirectorya.c b/src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/createdirectorya.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/createdirectorya.c rename to src/pal/tests/palsuite/file_io/CreateDirectoryA/test2/createdirectorya.cpp diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/CMakeLists.txt index 1981e37..f8cb584 100644 --- a/src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateDirectoryW.c + CreateDirectoryW.cpp ) add_executable(paltest_createdirectoryw_test1 diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/CreateDirectoryW.c b/src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/CreateDirectoryW.c deleted file mode 100644 index 9b020cc..0000000 --- a/src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/CreateDirectoryW.c +++ /dev/null @@ -1,347 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: CreateDirectoryW.c -** -** Purpose: Tests the PAL implementation of the CreateDirectoryW function. -** -** -**===================================================================*/ - -#include - - -/* apparently, under WIN32 the max path size is 248 but under - BSD it is _MAX_PATH */ -#if WIN32 -#define CREATE_MAX_PATH_SIZE 248 -#else -#define CREATE_MAX_PATH_SIZE _MAX_PATH -#endif - - -int __cdecl main(int argc, char *argv[]) -{ - BOOL bRc = FALSE; - BOOL bSuccess = FALSE; - const int buf_size = CREATE_MAX_PATH_SIZE + 10; - char szDirName[CREATE_MAX_PATH_SIZE + 10]; - char buffer[CREATE_MAX_PATH_SIZE + 10]; - WCHAR* pTemp = NULL; - DWORD curDirLen; - DWORD curDirectory = 1024; - - - - if (0 != PAL_Initialize(argc,argv)) - { - return FAIL; - } - - /* directory does not exist */ - pTemp = convert("test_directory"); - bRc = CreateDirectoryW(pTemp, NULL); - free(pTemp); - if (bRc == FALSE) - { - Fail("CreateDirectoryW: Failed to create \"test_directory\"\n"); - } - - /* directory exists */ - pTemp = convert("test_directory"); - bRc = CreateDirectoryW(pTemp, NULL); - if (bRc == TRUE) - { - bRc = RemoveDirectoryW(pTemp); - if(!bRc) - { - free(pTemp); - Fail("CreateDirectoryW: RemoveDirectoryW failed to " - "delete the directory with error %u.\n", - GetLastError()); - } - free(pTemp); - Fail("CreateDirectoryW: Succeeded creating the directory" - " \"test_directory\" when it exists already.\n"); - } - - bRc = RemoveDirectoryW(pTemp); - if(!bRc) - { - free(pTemp); - Fail("CreateDirectoryW: RemoveDirectoryW failed to " - "delete the directory with error %u.\n", - GetLastError()); - } - free(pTemp); - - /* long directory names (CREATE_MAX_PATH_SIZE - 1, CREATE_MAX_PATH_SIZE - and CREATE_MAX_PATH_SIZE + 1 characters - including terminating null char) */ - - curDirLen = GetCurrentDirectoryA(0, NULL); - - memset(szDirName, 0, buf_size); - memset(szDirName, 'a', CREATE_MAX_PATH_SIZE - 2 - curDirLen); - pTemp = convert((LPSTR)szDirName); - bRc = CreateDirectoryW(pTemp, NULL); - if (bRc == FALSE) - { - free(pTemp); - Fail("CreateDirectoryW: Failed to create a directory" - " name (%d) chars long with the error code %ld\n", - CREATE_MAX_PATH_SIZE - 1, - GetLastError()); - } - else - { - - /* Check to see if it's possible to navigate to directory */ - GetCurrentDirectoryA(curDirectory, buffer); - bSuccess = SetCurrentDirectoryA(szDirName); - if(!bSuccess) - { - Trace("CreateDirectoryW: SetCurrentDirectoryA failed to " - "navigate to the newly created directory with error " - "code %u.\n", GetLastError()); - bRc = RemoveDirectoryW(pTemp); - if(!bRc) - { - free(pTemp); - Fail("CreateDirectoryW: RemoveDirectoryW failed to " - "delete the directory with error %u.\n", - GetLastError()); - } - free(pTemp); - Fail(""); - - } - - /* Set directory back to initial directory */ - bRc = SetCurrentDirectoryA(buffer); - if(!bRc) - { - free(pTemp); - Fail("CreateDirectoryW: SetCurrentDirectoryA failed to " - "change the directory with error %u.\n", - GetLastError()); - } - - bRc = RemoveDirectoryW(pTemp); - if(!bRc) - { - free(pTemp); - Fail("CreateDirectoryW: RemoveDirectoryW failed to " - "delete the directory with error %u.\n", - GetLastError()); - } - free(pTemp); - } - - - memset(szDirName, 0, buf_size); - memset(szDirName, 'a', CREATE_MAX_PATH_SIZE - 1 - curDirLen); - pTemp = convert(szDirName); - bRc = CreateDirectoryW(pTemp, NULL); - if (bRc == FALSE) - { - free(pTemp); - Fail("CreateDirectoryW: Failed to create a directory" - " name %d chars long with error code %ld\n", - strlen(szDirName), - GetLastError()); - } - else - { - /* Check to see if it's possible to navigate to directory */ - GetCurrentDirectoryA(curDirectory, buffer); - bSuccess = SetCurrentDirectoryA(szDirName); - if(!bSuccess) - { - Trace("CreateDirectoryW: SetCurrentDirectoryA failed to " - "navigate to the newly created directory with error " - "code %u.\n", GetLastError()); - - bRc = RemoveDirectoryW(pTemp); - if(!bRc) - { - free(pTemp); - Fail("CreateDirectoryW: RemoveDirectoryW failed to " - "delete the directory with error %u.\n", - GetLastError()); - } - free(pTemp); - Fail(""); - } - - /* Set directory back to initial directory */ - bRc = SetCurrentDirectoryA(buffer); - if(!bRc) - { - free(pTemp); - Fail("CreateDirectoryW: SetCurrentDirectoryA failed to " - "change the directory with error %u.\n", - GetLastError()); - } - - - bRc = RemoveDirectoryW(pTemp); - if(!bRc) - { - free(pTemp); - Fail("CreateDirectoryW: RemoveDirectoryW failed to " - "delete the directory with error %u.\n", - GetLastError()); - } - free(pTemp); - } - - memset(szDirName, 0, buf_size); - memset(szDirName, 'a', CREATE_MAX_PATH_SIZE - curDirLen); - pTemp = convert(szDirName); - bRc = CreateDirectoryW(pTemp, NULL); - - if (bRc != FALSE) - { - RemoveDirectoryW(pTemp); - if(!bRc) - { - free(pTemp); - Fail("CreateDirectoryW: RemoveDirectoryW failed to " - "delete the directory with error %u.\n", - GetLastError()); - } - if (strlen(szDirName) > CREATE_MAX_PATH_SIZE) - { - free(pTemp); - Fail("CreateDirectoryW: Failed because it created a directory" - " name 1 character longer (%d chars) than the max dir size" - " allowed\n", - strlen(szDirName)); - } - } - - free(pTemp); - - /* long directory name CREATE_MAX_PATH_SIZE + 3 chars including "..\" - (real path length <= CREATE_MAX_PATH_SIZE) */ - memset(szDirName, 0, buf_size); - memset(szDirName, 'a', CREATE_MAX_PATH_SIZE + 3 - 1 - curDirLen); - szDirName[0] = '.'; - szDirName[1] = '.'; - szDirName[2] = '\\'; - pTemp = convert(szDirName); - bRc = CreateDirectoryW(pTemp, NULL); - if (bRc == FALSE) - { - free(pTemp); - Fail("CreateDirectoryW: Failed to create a directory name more " - "than %d chars long and its real path name is less " - "than %d chars\n", - CREATE_MAX_PATH_SIZE, - CREATE_MAX_PATH_SIZE); - } - else - { - /* Check to see if it's possible to navigate to directory */ - GetCurrentDirectoryA(curDirectory, buffer); - bSuccess = SetCurrentDirectoryA(szDirName); - if(!bSuccess) - { - Trace("CreateDirectoryW: SetCurrentDirectoryA failed to " - "navigate to the newly created directory with error " - "code %u.\n", GetLastError()); - bRc = RemoveDirectoryW(pTemp); - if(!bRc) - { - free(pTemp); - Fail("CreateDirectoryW: RemoveDirectoryW failed to " - "delete the directory with error %u.\n", - GetLastError()); - } - free(pTemp); - Fail(""); - } - - /* Set directory back to initial directory */ - bRc = SetCurrentDirectoryA(buffer); - if(!bRc) - { - free(pTemp); - Fail("CreateDirectoryW: SetCurrentDirectoryA failed to " - "change the directory with error %u.\n", - GetLastError()); - } - - bRc = RemoveDirectoryW(pTemp); - if(!bRc) - { - free(pTemp); - Fail("CreateDirectoryW: RemoveDirectoryW failed to " - "delete the directory with error %u.\n", - GetLastError()); - } - free(pTemp); - } - - /* directories with dots */ - memset(szDirName, 0, 252); - sprintf(szDirName, ".dotDirectory"); - pTemp = convert(szDirName); - bRc = CreateDirectoryW(pTemp, NULL); - if (bRc == FALSE) - { - free(pTemp); - Fail("CreateDirectoryW: Failed to create a dot directory\n"); - } - else - { - /* Check to see if it's possible to navigate to directory */ - GetCurrentDirectoryA(curDirectory, buffer); - bSuccess = SetCurrentDirectoryA(szDirName); - if(!bSuccess) - { - Trace("CreateDirectoryW: SetCurrentDirectoryA failed to " - "navigate to the newly created directory with error " - "code %u.\n", GetLastError()); - - bRc = RemoveDirectoryW(pTemp); - if(!bRc) - { - free(pTemp); - Fail("CreateDirectoryW: RemoveDirectoryW failed to " - "delete the directory with error %u.\n", - GetLastError()); - } - free(pTemp); - Fail(""); - } - - /* Set directory back to initial directory */ - bRc = SetCurrentDirectoryA(buffer); - if(!bRc) - { - free(pTemp); - Fail("CreateDirectoryW: SetCurrentDirectoryA failed to " - "change the directory with error %u.\n", - GetLastError()); - } - - bRc = RemoveDirectoryW(pTemp); - if(!bRc) - { - free(pTemp); - Fail("CreateDirectoryW: RemoveDirectoryW failed to " - "delete the directory with error %u.\n", - GetLastError()); - } - free(pTemp); - } - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/CreateDirectoryW.cpp b/src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/CreateDirectoryW.cpp new file mode 100644 index 0000000..bbaedda --- /dev/null +++ b/src/pal/tests/palsuite/file_io/CreateDirectoryW/test1/CreateDirectoryW.cpp @@ -0,0 +1,347 @@ +// 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. + +/*===================================================================== +** +** Source: CreateDirectoryW.c +** +** Purpose: Tests the PAL implementation of the CreateDirectoryW function. +** +** +**===================================================================*/ + +#include + + +/* apparently, under WIN32 the max path size is 248 but under + BSD it is _MAX_PATH */ +#if WIN32 +#define CREATE_MAX_PATH_SIZE 248 +#else +#define CREATE_MAX_PATH_SIZE _MAX_PATH +#endif + + +int __cdecl main(int argc, char *argv[]) +{ + BOOL bRc = FALSE; + BOOL bSuccess = FALSE; + const int buf_size = CREATE_MAX_PATH_SIZE + 10; + char szDirName[CREATE_MAX_PATH_SIZE + 10]; + char buffer[CREATE_MAX_PATH_SIZE + 10]; + WCHAR* pTemp = NULL; + DWORD curDirLen; + DWORD curDirectory = 1024; + + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* directory does not exist */ + pTemp = convert("test_directory"); + bRc = CreateDirectoryW(pTemp, NULL); + free(pTemp); + if (bRc == FALSE) + { + Fail("CreateDirectoryW: Failed to create \"test_directory\"\n"); + } + + /* directory exists */ + pTemp = convert("test_directory"); + bRc = CreateDirectoryW(pTemp, NULL); + if (bRc == TRUE) + { + bRc = RemoveDirectoryW(pTemp); + if(!bRc) + { + free(pTemp); + Fail("CreateDirectoryW: RemoveDirectoryW failed to " + "delete the directory with error %u.\n", + GetLastError()); + } + free(pTemp); + Fail("CreateDirectoryW: Succeeded creating the directory" + " \"test_directory\" when it exists already.\n"); + } + + bRc = RemoveDirectoryW(pTemp); + if(!bRc) + { + free(pTemp); + Fail("CreateDirectoryW: RemoveDirectoryW failed to " + "delete the directory with error %u.\n", + GetLastError()); + } + free(pTemp); + + /* long directory names (CREATE_MAX_PATH_SIZE - 1, CREATE_MAX_PATH_SIZE + and CREATE_MAX_PATH_SIZE + 1 characters + including terminating null char) */ + + curDirLen = GetCurrentDirectoryA(0, NULL); + + memset(szDirName, 0, buf_size); + memset(szDirName, 'a', CREATE_MAX_PATH_SIZE - 2 - curDirLen); + pTemp = convert((LPSTR)szDirName); + bRc = CreateDirectoryW(pTemp, NULL); + if (bRc == FALSE) + { + free(pTemp); + Fail("CreateDirectoryW: Failed to create a directory" + " name (%d) chars long with the error code %ld\n", + CREATE_MAX_PATH_SIZE - 1, + GetLastError()); + } + else + { + + /* Check to see if it's possible to navigate to directory */ + GetCurrentDirectoryA(curDirectory, buffer); + bSuccess = SetCurrentDirectoryA(szDirName); + if(!bSuccess) + { + Trace("CreateDirectoryW: SetCurrentDirectoryA failed to " + "navigate to the newly created directory with error " + "code %u.\n", GetLastError()); + bRc = RemoveDirectoryW(pTemp); + if(!bRc) + { + free(pTemp); + Fail("CreateDirectoryW: RemoveDirectoryW failed to " + "delete the directory with error %u.\n", + GetLastError()); + } + free(pTemp); + Fail(""); + + } + + /* Set directory back to initial directory */ + bRc = SetCurrentDirectoryA(buffer); + if(!bRc) + { + free(pTemp); + Fail("CreateDirectoryW: SetCurrentDirectoryA failed to " + "change the directory with error %u.\n", + GetLastError()); + } + + bRc = RemoveDirectoryW(pTemp); + if(!bRc) + { + free(pTemp); + Fail("CreateDirectoryW: RemoveDirectoryW failed to " + "delete the directory with error %u.\n", + GetLastError()); + } + free(pTemp); + } + + + memset(szDirName, 0, buf_size); + memset(szDirName, 'a', CREATE_MAX_PATH_SIZE - 1 - curDirLen); + pTemp = convert(szDirName); + bRc = CreateDirectoryW(pTemp, NULL); + if (bRc == FALSE) + { + free(pTemp); + Fail("CreateDirectoryW: Failed to create a directory" + " name %d chars long with error code %ld\n", + strlen(szDirName), + GetLastError()); + } + else + { + /* Check to see if it's possible to navigate to directory */ + GetCurrentDirectoryA(curDirectory, buffer); + bSuccess = SetCurrentDirectoryA(szDirName); + if(!bSuccess) + { + Trace("CreateDirectoryW: SetCurrentDirectoryA failed to " + "navigate to the newly created directory with error " + "code %u.\n", GetLastError()); + + bRc = RemoveDirectoryW(pTemp); + if(!bRc) + { + free(pTemp); + Fail("CreateDirectoryW: RemoveDirectoryW failed to " + "delete the directory with error %u.\n", + GetLastError()); + } + free(pTemp); + Fail(""); + } + + /* Set directory back to initial directory */ + bRc = SetCurrentDirectoryA(buffer); + if(!bRc) + { + free(pTemp); + Fail("CreateDirectoryW: SetCurrentDirectoryA failed to " + "change the directory with error %u.\n", + GetLastError()); + } + + + bRc = RemoveDirectoryW(pTemp); + if(!bRc) + { + free(pTemp); + Fail("CreateDirectoryW: RemoveDirectoryW failed to " + "delete the directory with error %u.\n", + GetLastError()); + } + free(pTemp); + } + + memset(szDirName, 0, buf_size); + memset(szDirName, 'a', CREATE_MAX_PATH_SIZE - curDirLen); + pTemp = convert(szDirName); + bRc = CreateDirectoryW(pTemp, NULL); + + if (bRc != FALSE) + { + RemoveDirectoryW(pTemp); + if(!bRc) + { + free(pTemp); + Fail("CreateDirectoryW: RemoveDirectoryW failed to " + "delete the directory with error %u.\n", + GetLastError()); + } + if (strlen(szDirName) > CREATE_MAX_PATH_SIZE) + { + free(pTemp); + Fail("CreateDirectoryW: Failed because it created a directory" + " name 1 character longer (%d chars) than the max dir size" + " allowed\n", + strlen(szDirName)); + } + } + + free(pTemp); + + /* long directory name CREATE_MAX_PATH_SIZE + 3 chars including "..\" + (real path length <= CREATE_MAX_PATH_SIZE) */ + memset(szDirName, 0, buf_size); + memset(szDirName, 'a', CREATE_MAX_PATH_SIZE + 3 - 1 - curDirLen); + szDirName[0] = '.'; + szDirName[1] = '.'; + szDirName[2] = '\\'; + pTemp = convert(szDirName); + bRc = CreateDirectoryW(pTemp, NULL); + if (bRc == FALSE) + { + free(pTemp); + Fail("CreateDirectoryW: Failed to create a directory name more " + "than %d chars long and its real path name is less " + "than %d chars\n", + CREATE_MAX_PATH_SIZE, + CREATE_MAX_PATH_SIZE); + } + else + { + /* Check to see if it's possible to navigate to directory */ + GetCurrentDirectoryA(curDirectory, buffer); + bSuccess = SetCurrentDirectoryA(szDirName); + if(!bSuccess) + { + Trace("CreateDirectoryW: SetCurrentDirectoryA failed to " + "navigate to the newly created directory with error " + "code %u.\n", GetLastError()); + bRc = RemoveDirectoryW(pTemp); + if(!bRc) + { + free(pTemp); + Fail("CreateDirectoryW: RemoveDirectoryW failed to " + "delete the directory with error %u.\n", + GetLastError()); + } + free(pTemp); + Fail(""); + } + + /* Set directory back to initial directory */ + bRc = SetCurrentDirectoryA(buffer); + if(!bRc) + { + free(pTemp); + Fail("CreateDirectoryW: SetCurrentDirectoryA failed to " + "change the directory with error %u.\n", + GetLastError()); + } + + bRc = RemoveDirectoryW(pTemp); + if(!bRc) + { + free(pTemp); + Fail("CreateDirectoryW: RemoveDirectoryW failed to " + "delete the directory with error %u.\n", + GetLastError()); + } + free(pTemp); + } + + /* directories with dots */ + memset(szDirName, 0, 252); + sprintf_s(szDirName, _countof(szDirName), ".dotDirectory"); + pTemp = convert(szDirName); + bRc = CreateDirectoryW(pTemp, NULL); + if (bRc == FALSE) + { + free(pTemp); + Fail("CreateDirectoryW: Failed to create a dot directory\n"); + } + else + { + /* Check to see if it's possible to navigate to directory */ + GetCurrentDirectoryA(curDirectory, buffer); + bSuccess = SetCurrentDirectoryA(szDirName); + if(!bSuccess) + { + Trace("CreateDirectoryW: SetCurrentDirectoryA failed to " + "navigate to the newly created directory with error " + "code %u.\n", GetLastError()); + + bRc = RemoveDirectoryW(pTemp); + if(!bRc) + { + free(pTemp); + Fail("CreateDirectoryW: RemoveDirectoryW failed to " + "delete the directory with error %u.\n", + GetLastError()); + } + free(pTemp); + Fail(""); + } + + /* Set directory back to initial directory */ + bRc = SetCurrentDirectoryA(buffer); + if(!bRc) + { + free(pTemp); + Fail("CreateDirectoryW: SetCurrentDirectoryA failed to " + "change the directory with error %u.\n", + GetLastError()); + } + + bRc = RemoveDirectoryW(pTemp); + if(!bRc) + { + free(pTemp); + Fail("CreateDirectoryW: RemoveDirectoryW failed to " + "delete the directory with error %u.\n", + GetLastError()); + } + free(pTemp); + } + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/CMakeLists.txt index aae4e7d..f8614ca 100644 --- a/src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - createdirectoryw.c + createdirectoryw.cpp ) add_executable(paltest_createdirectoryw_test2 diff --git a/src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/createdirectoryw.c b/src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/createdirectoryw.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/createdirectoryw.c rename to src/pal/tests/palsuite/file_io/CreateDirectoryW/test2/createdirectoryw.cpp diff --git a/src/pal/tests/palsuite/file_io/CreateFileA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CreateFileA/test1/CMakeLists.txt index 8814b22..edacdbd 100644 --- a/src/pal/tests/palsuite/file_io/CreateFileA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/CreateFileA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateFileA.c + CreateFileA.cpp ) add_executable(paltest_createfilea_test1 diff --git a/src/pal/tests/palsuite/file_io/CreateFileA/test1/CreateFileA.c b/src/pal/tests/palsuite/file_io/CreateFileA/test1/CreateFileA.c deleted file mode 100644 index a70867a..0000000 --- a/src/pal/tests/palsuite/file_io/CreateFileA/test1/CreateFileA.c +++ /dev/null @@ -1,145 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: CreateFileA.c -** -** Purpose: Test the PAL implementation of the CreateFileA function -** -** -**===================================================================*/ - -#include - -BOOL Cleanup(void) -{ - char FileName[20]; - int i; - BOOL bRet = TRUE; // assume success - - // loop through all accesses, modes, dispositions and flags - for (i=0; i<4*8*4*5; ++i) { - sprintf(FileName, "test%03d.txt", i); - if (DeleteFileA(FileName) == FALSE) { - if (GetLastError() != ERROR_FILE_NOT_FOUND) { - bRet = FALSE; - } - } - } - return bRet; -} - - -int __cdecl main(int argc, char *argv[]) -{ - BOOL bSuccess = TRUE; - int nCounter = 0; - HANDLE hFile; - char lpFileName[20]; - FILE *outFile = NULL; - char results[1024]; - int i, j, k, l; - DWORD dwDesiredAccess[4] = {0, // 0 - GENERIC_READ, // 1 - GENERIC_WRITE, // 2 - GENERIC_READ | GENERIC_WRITE}; // 3 - DWORD dwShareMode[8] = {0, // 0 - FILE_SHARE_READ, // 1 - FILE_SHARE_WRITE, // 2 - FILE_SHARE_DELETE, // 3 - FILE_SHARE_READ | FILE_SHARE_WRITE, // 4 - FILE_SHARE_READ | FILE_SHARE_DELETE, // 5 - FILE_SHARE_WRITE | FILE_SHARE_DELETE, // 6 - FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE}; // 7 - LPSECURITY_ATTRIBUTES lpAttr = NULL; - DWORD dwCreationDisp[4] = {CREATE_NEW, // 0 - CREATE_ALWAYS, // 1 - OPEN_EXISTING, // 2 - OPEN_ALWAYS}; // 3 - DWORD dwFlagsAttrib[5] = {FILE_ATTRIBUTE_NORMAL, // 0 - FILE_FLAG_SEQUENTIAL_SCAN, // 1 - FILE_FLAG_WRITE_THROUGH, // 2 - FILE_FLAG_NO_BUFFERING, // 3 - FILE_FLAG_RANDOM_ACCESS}; // 4 - HANDLE hTemplate = NULL; - - - if (0 != PAL_Initialize(argc,argv)) - { - return FAIL; - } - - if (!Cleanup()) { - Trace("Pre-test Cleanup() failed. LastError=%d\n", GetLastError()); - return FAIL; - } - - /* open the file to read the expected results */ - outFile = fopen("winoutput", "r"); - memset (results, 0, 1024); - - fgets(results, 1024, outFile); - nCounter = (int)strlen(results); - fclose(outFile); - - nCounter = 0; - - // desired access loop - for (i = 0; i < 4; i++) - { - // share mode loop - for (j = 0; j < 8; j++) - { - // security attributes loop - for (k = 0; k < 4; k++) - { - // creation disp loop - for (l = 0; l < 5; l++) - { - sprintf(lpFileName, "test%03d.txt", nCounter); - hFile = CreateFile(lpFileName, - dwDesiredAccess[i], - dwShareMode[j], - lpAttr, - dwCreationDisp[k], - dwFlagsAttrib[l], - hTemplate); - if (hFile == INVALID_HANDLE_VALUE) - { - if (results[nCounter] == '1') - { - Trace("CreateFile: ERROR: Failed when expected " - "to pass %s [%d][%d][%d][%d]\n", - lpFileName, i, j, k, l); - bSuccess = FALSE; - } - } - else - { - CloseHandle(hFile); - if (results[nCounter] == '0') - { - Trace("CreateFile: ERROR: Passed when expected " - "to fail %s [%d][%d][%d][%d]\n", - lpFileName, i, j, k, l); - bSuccess = FALSE; - } - } - nCounter ++; - } - } - } - } - - if (!Cleanup()) - { - Trace("Post-test Cleanup() failed. LastError=%d\n", GetLastError()); - return FAIL; - } - - int exitCode = bSuccess ? PASS : FAIL; - PAL_TerminateEx(exitCode); - return exitCode; -} diff --git a/src/pal/tests/palsuite/file_io/CreateFileA/test1/CreateFileA.cpp b/src/pal/tests/palsuite/file_io/CreateFileA/test1/CreateFileA.cpp new file mode 100644 index 0000000..f98fc5b --- /dev/null +++ b/src/pal/tests/palsuite/file_io/CreateFileA/test1/CreateFileA.cpp @@ -0,0 +1,145 @@ +// 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. + +/*===================================================================== +** +** Source: CreateFileA.c +** +** Purpose: Test the PAL implementation of the CreateFileA function +** +** +**===================================================================*/ + +#include + +BOOL Cleanup(void) +{ + char FileName[20]; + int i; + BOOL bRet = TRUE; // assume success + + // loop through all accesses, modes, dispositions and flags + for (i=0; i<4*8*4*5; ++i) { + sprintf_s(FileName, _countof(FileName), "test%03d.txt", i); + if (DeleteFileA(FileName) == FALSE) { + if (GetLastError() != ERROR_FILE_NOT_FOUND) { + bRet = FALSE; + } + } + } + return bRet; +} + + +int __cdecl main(int argc, char *argv[]) +{ + BOOL bSuccess = TRUE; + int nCounter = 0; + HANDLE hFile; + char lpFileName[20]; + FILE *outFile = NULL; + char results[1024]; + int i, j, k, l; + DWORD dwDesiredAccess[4] = {0, // 0 + GENERIC_READ, // 1 + GENERIC_WRITE, // 2 + GENERIC_READ | GENERIC_WRITE}; // 3 + DWORD dwShareMode[8] = {0, // 0 + FILE_SHARE_READ, // 1 + FILE_SHARE_WRITE, // 2 + FILE_SHARE_DELETE, // 3 + FILE_SHARE_READ | FILE_SHARE_WRITE, // 4 + FILE_SHARE_READ | FILE_SHARE_DELETE, // 5 + FILE_SHARE_WRITE | FILE_SHARE_DELETE, // 6 + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE}; // 7 + LPSECURITY_ATTRIBUTES lpAttr = NULL; + DWORD dwCreationDisp[4] = {CREATE_NEW, // 0 + CREATE_ALWAYS, // 1 + OPEN_EXISTING, // 2 + OPEN_ALWAYS}; // 3 + DWORD dwFlagsAttrib[5] = {FILE_ATTRIBUTE_NORMAL, // 0 + FILE_FLAG_SEQUENTIAL_SCAN, // 1 + FILE_FLAG_WRITE_THROUGH, // 2 + FILE_FLAG_NO_BUFFERING, // 3 + FILE_FLAG_RANDOM_ACCESS}; // 4 + HANDLE hTemplate = NULL; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + if (!Cleanup()) { + Trace("Pre-test Cleanup() failed. LastError=%d\n", GetLastError()); + return FAIL; + } + + /* open the file to read the expected results */ + outFile = fopen("winoutput", "r"); + memset (results, 0, 1024); + + fgets(results, 1024, outFile); + nCounter = (int)strlen(results); + fclose(outFile); + + nCounter = 0; + + // desired access loop + for (i = 0; i < 4; i++) + { + // share mode loop + for (j = 0; j < 8; j++) + { + // security attributes loop + for (k = 0; k < 4; k++) + { + // creation disp loop + for (l = 0; l < 5; l++) + { + sprintf_s(lpFileName, _countof(lpFileName), "test%03d.txt", nCounter); + hFile = CreateFile(lpFileName, + dwDesiredAccess[i], + dwShareMode[j], + lpAttr, + dwCreationDisp[k], + dwFlagsAttrib[l], + hTemplate); + if (hFile == INVALID_HANDLE_VALUE) + { + if (results[nCounter] == '1') + { + Trace("CreateFile: ERROR: Failed when expected " + "to pass %s [%d][%d][%d][%d]\n", + lpFileName, i, j, k, l); + bSuccess = FALSE; + } + } + else + { + CloseHandle(hFile); + if (results[nCounter] == '0') + { + Trace("CreateFile: ERROR: Passed when expected " + "to fail %s [%d][%d][%d][%d]\n", + lpFileName, i, j, k, l); + bSuccess = FALSE; + } + } + nCounter ++; + } + } + } + } + + if (!Cleanup()) + { + Trace("Post-test Cleanup() failed. LastError=%d\n", GetLastError()); + return FAIL; + } + + int exitCode = bSuccess ? PASS : FAIL; + PAL_TerminateEx(exitCode); + return exitCode; +} diff --git a/src/pal/tests/palsuite/file_io/CreateFileW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/CreateFileW/test1/CMakeLists.txt index 1ff0b80..820e169 100644 --- a/src/pal/tests/palsuite/file_io/CreateFileW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/CreateFileW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateFileW.c + CreateFileW.cpp ) add_executable(paltest_createfilew_test1 diff --git a/src/pal/tests/palsuite/file_io/CreateFileW/test1/CreateFileW.c b/src/pal/tests/palsuite/file_io/CreateFileW/test1/CreateFileW.c deleted file mode 100644 index 4d7d20a..0000000 --- a/src/pal/tests/palsuite/file_io/CreateFileW/test1/CreateFileW.c +++ /dev/null @@ -1,152 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: CreateFileW.c -** -** Purpose: Test the PAL implementation of the CreateFileW function -** -** -**===================================================================*/ - -#include - -BOOL Cleanup(void) -{ - char FileName[20]; - int i; - BOOL bRet = TRUE; // assume success - - // loop through all accesses, modes, dispositions and flags - for (i=0; i<4*8*4*5; ++i) { - sprintf(FileName, "test%03d.txt", i); - if (DeleteFileA(FileName) == FALSE) { - if (GetLastError() != ERROR_FILE_NOT_FOUND) { - bRet = FALSE; - } - } - } - return bRet; -} - - -int __cdecl main(int argc, char *argv[]) -{ - BOOL bSuccess = TRUE; - int nCounter = 0; - HANDLE hFile = NULL; - WCHAR *lpFileName = NULL; - char* pTemp = NULL; - char string[40]; - FILE *outFile = NULL; - char results[1024]; - int i, j, k, l; - DWORD dwDesiredAccess[4] = {0, // 0 - GENERIC_READ, // 1 - GENERIC_WRITE, // 2 - GENERIC_READ | GENERIC_WRITE}; // 3 - DWORD dwShareMode[8] = {0, // 0 - FILE_SHARE_READ, // 1 - FILE_SHARE_WRITE, // 2 - FILE_SHARE_DELETE, // 3 - FILE_SHARE_READ | FILE_SHARE_WRITE, // 4 - FILE_SHARE_READ | FILE_SHARE_DELETE, // 5 - FILE_SHARE_WRITE | FILE_SHARE_DELETE, // 6 - FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE}; // 7 - LPSECURITY_ATTRIBUTES lpAttr = NULL; - DWORD dwCreationDisp[4] = {CREATE_NEW, // 0 - CREATE_ALWAYS, // 1 - OPEN_EXISTING, // 2 - OPEN_ALWAYS}; // 3 - DWORD dwFlagsAttrib[5] = {FILE_ATTRIBUTE_NORMAL, // 0 - FILE_FLAG_SEQUENTIAL_SCAN, // 1 - FILE_FLAG_WRITE_THROUGH, // 2 - FILE_FLAG_NO_BUFFERING, // 3 - FILE_FLAG_RANDOM_ACCESS}; // 4 - HANDLE hTemplate = NULL; - - - if (0 != PAL_Initialize(argc,argv)) - { - return FAIL; - } - - if (!Cleanup()) { - Trace("Pre-test Cleanup() failed. LastError=%d\n", GetLastError()); - return FAIL; - } - - /* open the file to read the expected results */ - outFile = fopen("winoutput", "r"); - memset (results, 0, 1024); - - fgets(results, 1024, outFile); - fclose(outFile); - - nCounter = 0; - - // desired access loop - for (i = 0; i < 4; i++) - { - // share mode loop - for (j = 0; j < 8; j++) - { - // security attributes loop - for (k = 0; k < 4; k++) - { - // creation disp loop - for (l = 0; l < 5; l++) - { - sprintf(string, "test%03d.txt", nCounter); - lpFileName = convert(string); - hFile = CreateFileW(lpFileName, - dwDesiredAccess[i], - dwShareMode[j], - lpAttr, - dwCreationDisp[k], - dwFlagsAttrib[l], - hTemplate); - free(lpFileName); - if (hFile == INVALID_HANDLE_VALUE) - { - if (results[nCounter] == '1') - { - pTemp = convertC(lpFileName); - Trace("CreateFile: ERROR: Failed when expected " - "to pass %s [%d][%d][%d][%d]\n", - pTemp, i, j, k, l); - free(pTemp); - bSuccess = FALSE; - } - } - else - { - CloseHandle(hFile); - if (results[nCounter] == '0') - { - pTemp = convertC(lpFileName); - Trace("CreateFile: ERROR: Passed when expected " - "to fail %s [%d][%d][%d][%d]\n", - pTemp, i, j, k, l); - free(pTemp); - bSuccess = FALSE; - } - } - nCounter ++; - } - } - } - } - - if (!Cleanup()) - { - Trace("Post-test Cleanup() failed. LastError=%d\n", GetLastError()); - return FAIL; - } - - int exitCode = bSuccess ? PASS : FAIL; - PAL_TerminateEx(exitCode); - return exitCode; -} diff --git a/src/pal/tests/palsuite/file_io/CreateFileW/test1/CreateFileW.cpp b/src/pal/tests/palsuite/file_io/CreateFileW/test1/CreateFileW.cpp new file mode 100644 index 0000000..0619f5b --- /dev/null +++ b/src/pal/tests/palsuite/file_io/CreateFileW/test1/CreateFileW.cpp @@ -0,0 +1,152 @@ +// 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. + +/*===================================================================== +** +** Source: CreateFileW.c +** +** Purpose: Test the PAL implementation of the CreateFileW function +** +** +**===================================================================*/ + +#include + +BOOL Cleanup(void) +{ + char FileName[20]; + int i; + BOOL bRet = TRUE; // assume success + + // loop through all accesses, modes, dispositions and flags + for (i=0; i<4*8*4*5; ++i) { + sprintf_s(FileName, _countof(FileName), "test%03d.txt", i); + if (DeleteFileA(FileName) == FALSE) { + if (GetLastError() != ERROR_FILE_NOT_FOUND) { + bRet = FALSE; + } + } + } + return bRet; +} + + +int __cdecl main(int argc, char *argv[]) +{ + BOOL bSuccess = TRUE; + int nCounter = 0; + HANDLE hFile = NULL; + WCHAR *lpFileName = NULL; + char* pTemp = NULL; + char string[40]; + FILE *outFile = NULL; + char results[1024]; + int i, j, k, l; + DWORD dwDesiredAccess[4] = {0, // 0 + GENERIC_READ, // 1 + GENERIC_WRITE, // 2 + GENERIC_READ | GENERIC_WRITE}; // 3 + DWORD dwShareMode[8] = {0, // 0 + FILE_SHARE_READ, // 1 + FILE_SHARE_WRITE, // 2 + FILE_SHARE_DELETE, // 3 + FILE_SHARE_READ | FILE_SHARE_WRITE, // 4 + FILE_SHARE_READ | FILE_SHARE_DELETE, // 5 + FILE_SHARE_WRITE | FILE_SHARE_DELETE, // 6 + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE}; // 7 + LPSECURITY_ATTRIBUTES lpAttr = NULL; + DWORD dwCreationDisp[4] = {CREATE_NEW, // 0 + CREATE_ALWAYS, // 1 + OPEN_EXISTING, // 2 + OPEN_ALWAYS}; // 3 + DWORD dwFlagsAttrib[5] = {FILE_ATTRIBUTE_NORMAL, // 0 + FILE_FLAG_SEQUENTIAL_SCAN, // 1 + FILE_FLAG_WRITE_THROUGH, // 2 + FILE_FLAG_NO_BUFFERING, // 3 + FILE_FLAG_RANDOM_ACCESS}; // 4 + HANDLE hTemplate = NULL; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + if (!Cleanup()) { + Trace("Pre-test Cleanup() failed. LastError=%d\n", GetLastError()); + return FAIL; + } + + /* open the file to read the expected results */ + outFile = fopen("winoutput", "r"); + memset (results, 0, 1024); + + fgets(results, 1024, outFile); + fclose(outFile); + + nCounter = 0; + + // desired access loop + for (i = 0; i < 4; i++) + { + // share mode loop + for (j = 0; j < 8; j++) + { + // security attributes loop + for (k = 0; k < 4; k++) + { + // creation disp loop + for (l = 0; l < 5; l++) + { + sprintf_s(string, _countof(string), "test%03d.txt", nCounter); + lpFileName = convert(string); + hFile = CreateFileW(lpFileName, + dwDesiredAccess[i], + dwShareMode[j], + lpAttr, + dwCreationDisp[k], + dwFlagsAttrib[l], + hTemplate); + free(lpFileName); + if (hFile == INVALID_HANDLE_VALUE) + { + if (results[nCounter] == '1') + { + pTemp = convertC(lpFileName); + Trace("CreateFile: ERROR: Failed when expected " + "to pass %s [%d][%d][%d][%d]\n", + pTemp, i, j, k, l); + free(pTemp); + bSuccess = FALSE; + } + } + else + { + CloseHandle(hFile); + if (results[nCounter] == '0') + { + pTemp = convertC(lpFileName); + Trace("CreateFile: ERROR: Passed when expected " + "to fail %s [%d][%d][%d][%d]\n", + pTemp, i, j, k, l); + free(pTemp); + bSuccess = FALSE; + } + } + nCounter ++; + } + } + } + } + + if (!Cleanup()) + { + Trace("Post-test Cleanup() failed. LastError=%d\n", GetLastError()); + return FAIL; + } + + int exitCode = bSuccess ? PASS : FAIL; + PAL_TerminateEx(exitCode); + return exitCode; +} diff --git a/src/pal/tests/palsuite/file_io/DeleteFileW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/DeleteFileW/test1/CMakeLists.txt index 046fd35..eada614 100644 --- a/src/pal/tests/palsuite/file_io/DeleteFileW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/DeleteFileW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - DeleteFileW.c + DeleteFileW.cpp ) add_executable(paltest_deletefilew_test1 diff --git a/src/pal/tests/palsuite/file_io/DeleteFileW/test1/DeleteFileW.c b/src/pal/tests/palsuite/file_io/DeleteFileW/test1/DeleteFileW.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/DeleteFileW/test1/DeleteFileW.c rename to src/pal/tests/palsuite/file_io/DeleteFileW/test1/DeleteFileW.cpp diff --git a/src/pal/tests/palsuite/file_io/FILECanonicalizePath/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FILECanonicalizePath/CMakeLists.txt index 0c02c98..7045983 100644 --- a/src/pal/tests/palsuite/file_io/FILECanonicalizePath/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/FILECanonicalizePath/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - FILECanonicalizePath.c + FILECanonicalizePath.cpp ) add_executable(paltest_filecanonicalizepath_test1 diff --git a/src/pal/tests/palsuite/file_io/FILECanonicalizePath/FILECanonicalizePath.c b/src/pal/tests/palsuite/file_io/FILECanonicalizePath/FILECanonicalizePath.c deleted file mode 100644 index 91bac1f..0000000 --- a/src/pal/tests/palsuite/file_io/FILECanonicalizePath/FILECanonicalizePath.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*===================================================================== -** -** Source: FILECanonicalizePath.c (test 1) -** -** Purpose: Tests the PAL implementation of the FILECanonicalizePath function. -** -** -**===================================================================*/ - -#include - -extern void FILECanonicalizePath(LPSTR lpUnixPath); - -void TestCase(LPSTR input, LPSTR expectedOutput); - -int __cdecl main(int argc, char *argv[]) -{ - if (PAL_Initialize(argc,argv) != 0) - { - return FAIL; - } - - // Case 01: / should not change - TestCase("/Test", "/Test"); - - // Case 02: // should not change - TestCase("/Test/Foo", "/Test/Foo"); - - // Case 03: // transforms to / - TestCase("//", "/"); - - // Case 04: /./ transforms to / - TestCase("/./", "/"); - - // Case 05: //../ transforms to / - TestCase("/Test/../", "/"); - - // Case 06: /Test/Foo/.. transforms to /Test - TestCase("/Test/Foo/..", "/Test"); - - // Case 07: /Test/.. transforms to / - TestCase("/Test/..", "/"); - - // Case 08: /. transforms to / - TestCase("/.", "/"); - - // Case 09: / - TestCase("/Test/.", "/Test"); - - // Case 10: //../. transforms to / - TestCase("/Test/../.", "/"); - - // Case 11: /.. transforms to / - TestCase("/..", "/"); - - PAL_Terminate(); - return PASS; -} - -void TestCase(LPSTR input, LPSTR expectedOutput) -{ - // Save the input for debug logging since the input is edited in-place - char* pOriginalInput = (char*)malloc(strlen(input) * sizeof(char) + 1); - strcpy(pOriginalInput, input); - - char* pInput = (char*)malloc(strlen(input) * sizeof(char) + 1); - strcpy(pInput, pOriginalInput); - - FILECanonicalizePath(pInput); - if (strcmp(pInput, expectedOutput) != 0) - { - free(pOriginalInput); - free(pInput); - Fail("FILECanonicalizePath error: input %s did not match expected output %s; got %s instead", pOriginalInput, expectedOutput, pInput); - } - - free(pOriginalInput); - free(pInput); -} diff --git a/src/pal/tests/palsuite/file_io/FILECanonicalizePath/FILECanonicalizePath.cpp b/src/pal/tests/palsuite/file_io/FILECanonicalizePath/FILECanonicalizePath.cpp new file mode 100644 index 0000000..3a1758a --- /dev/null +++ b/src/pal/tests/palsuite/file_io/FILECanonicalizePath/FILECanonicalizePath.cpp @@ -0,0 +1,83 @@ +// 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. + +/*===================================================================== +** +** Source: FILECanonicalizePath.c (test 1) +** +** Purpose: Tests the PAL implementation of the FILECanonicalizePath function. +** +** +**===================================================================*/ + +#include + +extern "C" void FILECanonicalizePath(LPSTR lpUnixPath); + +void TestCase(LPSTR input, LPSTR expectedOutput); + +int __cdecl main(int argc, char *argv[]) +{ + if (PAL_Initialize(argc,argv) != 0) + { + return FAIL; + } + + // Case 01: / should not change + TestCase("/Test", "/Test"); + + // Case 02: // should not change + TestCase("/Test/Foo", "/Test/Foo"); + + // Case 03: // transforms to / + TestCase("//", "/"); + + // Case 04: /./ transforms to / + TestCase("/./", "/"); + + // Case 05: //../ transforms to / + TestCase("/Test/../", "/"); + + // Case 06: /Test/Foo/.. transforms to /Test + TestCase("/Test/Foo/..", "/Test"); + + // Case 07: /Test/.. transforms to / + TestCase("/Test/..", "/"); + + // Case 08: /. transforms to / + TestCase("/.", "/"); + + // Case 09: / + TestCase("/Test/.", "/Test"); + + // Case 10: //../. transforms to / + TestCase("/Test/../.", "/"); + + // Case 11: /.. transforms to / + TestCase("/..", "/"); + + PAL_Terminate(); + return PASS; +} + +void TestCase(LPSTR input, LPSTR expectedOutput) +{ + // Save the input for debug logging since the input is edited in-place + char* pOriginalInput = (char*)malloc(strlen(input) * sizeof(char) + 1); + strcpy(pOriginalInput, input); + + char* pInput = (char*)malloc(strlen(input) * sizeof(char) + 1); + strcpy(pInput, pOriginalInput); + + FILECanonicalizePath(pInput); + if (strcmp(pInput, expectedOutput) != 0) + { + free(pOriginalInput); + free(pInput); + Fail("FILECanonicalizePath error: input %s did not match expected output %s; got %s instead", pOriginalInput, expectedOutput, pInput); + } + + free(pOriginalInput); + free(pInput); +} diff --git a/src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/CMakeLists.txt index 1310542..6ec6a98 100644 --- a/src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_filetimetodosdatetime_test1 diff --git a/src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/test1.c b/src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/test1.c rename to src/pal/tests/palsuite/file_io/FileTimeToDosDateTime/test1/test1.cpp diff --git a/src/pal/tests/palsuite/file_io/FindClose/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FindClose/test1/CMakeLists.txt index 732c9f5..d97c69e 100644 --- a/src/pal/tests/palsuite/file_io/FindClose/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/FindClose/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - FindClose.c + FindClose.cpp ) add_executable(paltest_findclose_test1 diff --git a/src/pal/tests/palsuite/file_io/FindClose/test1/FindClose.c b/src/pal/tests/palsuite/file_io/FindClose/test1/FindClose.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/FindClose/test1/FindClose.c rename to src/pal/tests/palsuite/file_io/FindClose/test1/FindClose.cpp diff --git a/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/CMakeLists.txt index 6613c4d..aeac94d 100644 --- a/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - FindFirstFileA.c + FindFirstFileA.cpp ) add_executable(paltest_findfirstfilea_test1 diff --git a/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/FindFirstFileA.c b/src/pal/tests/palsuite/file_io/FindFirstFileA/test1/FindFirstFileA.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/FindFirstFileA/test1/FindFirstFileA.c rename to src/pal/tests/palsuite/file_io/FindFirstFileA/test1/FindFirstFileA.cpp diff --git a/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/CMakeLists.txt index 23e95c7..2a6ea2b 100644 --- a/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - FindFirstFileW.c + FindFirstFileW.cpp ) add_executable(paltest_findfirstfilew_test1 diff --git a/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/FindFirstFileW.c b/src/pal/tests/palsuite/file_io/FindFirstFileW/test1/FindFirstFileW.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/FindFirstFileW/test1/FindFirstFileW.c rename to src/pal/tests/palsuite/file_io/FindFirstFileW/test1/FindFirstFileW.cpp diff --git a/src/pal/tests/palsuite/file_io/FindNextFileA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FindNextFileA/test1/CMakeLists.txt index efb1655..6e97b7a 100644 --- a/src/pal/tests/palsuite/file_io/FindNextFileA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/FindNextFileA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - FindNextFileA.c + FindNextFileA.cpp ) add_executable(paltest_findnextfilea_test1 diff --git a/src/pal/tests/palsuite/file_io/FindNextFileA/test1/FindNextFileA.c b/src/pal/tests/palsuite/file_io/FindNextFileA/test1/FindNextFileA.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/FindNextFileA/test1/FindNextFileA.c rename to src/pal/tests/palsuite/file_io/FindNextFileA/test1/FindNextFileA.cpp diff --git a/src/pal/tests/palsuite/file_io/FindNextFileA/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FindNextFileA/test2/CMakeLists.txt index 96821bd..e037bd3 100644 --- a/src/pal/tests/palsuite/file_io/FindNextFileA/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/FindNextFileA/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - findnextfilea.c + findnextfilea.cpp ) add_executable(paltest_findnextfilea_test2 diff --git a/src/pal/tests/palsuite/file_io/FindNextFileA/test2/findnextfilea.c b/src/pal/tests/palsuite/file_io/FindNextFileA/test2/findnextfilea.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/FindNextFileA/test2/findnextfilea.c rename to src/pal/tests/palsuite/file_io/FindNextFileA/test2/findnextfilea.cpp diff --git a/src/pal/tests/palsuite/file_io/FindNextFileW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FindNextFileW/test1/CMakeLists.txt index 4a283dd..a7c3e7e 100644 --- a/src/pal/tests/palsuite/file_io/FindNextFileW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/FindNextFileW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - FindNextFileW.c + FindNextFileW.cpp ) add_executable(paltest_findnextfilew_test1 diff --git a/src/pal/tests/palsuite/file_io/FindNextFileW/test1/FindNextFileW.c b/src/pal/tests/palsuite/file_io/FindNextFileW/test1/FindNextFileW.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/FindNextFileW/test1/FindNextFileW.c rename to src/pal/tests/palsuite/file_io/FindNextFileW/test1/FindNextFileW.cpp diff --git a/src/pal/tests/palsuite/file_io/FindNextFileW/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FindNextFileW/test2/CMakeLists.txt index 2938afb..7b4c3c9 100644 --- a/src/pal/tests/palsuite/file_io/FindNextFileW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/FindNextFileW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - findnextfilew.c + findnextfilew.cpp ) add_executable(paltest_findnextfilew_test2 diff --git a/src/pal/tests/palsuite/file_io/FindNextFileW/test2/findnextfilew.c b/src/pal/tests/palsuite/file_io/FindNextFileW/test2/findnextfilew.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/FindNextFileW/test2/findnextfilew.c rename to src/pal/tests/palsuite/file_io/FindNextFileW/test2/findnextfilew.cpp diff --git a/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/CMakeLists.txt index e3fbccd..6c24ac7 100644 --- a/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - FlushFileBuffers.c + FlushFileBuffers.cpp ) add_executable(paltest_flushfilebuffers_test1 diff --git a/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/FlushFileBuffers.c b/src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/FlushFileBuffers.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/FlushFileBuffers.c rename to src/pal/tests/palsuite/file_io/FlushFileBuffers/test1/FlushFileBuffers.cpp diff --git a/src/pal/tests/palsuite/file_io/GetConsoleCP/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetConsoleCP/test1/CMakeLists.txt index 131f4a5..64ab6ea 100644 --- a/src/pal/tests/palsuite/file_io/GetConsoleCP/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetConsoleCP/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetConsoleCP.c + GetConsoleCP.cpp ) add_executable(paltest_getconsolecp_test1 diff --git a/src/pal/tests/palsuite/file_io/GetConsoleCP/test1/GetConsoleCP.c b/src/pal/tests/palsuite/file_io/GetConsoleCP/test1/GetConsoleCP.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetConsoleCP/test1/GetConsoleCP.c rename to src/pal/tests/palsuite/file_io/GetConsoleCP/test1/GetConsoleCP.cpp diff --git a/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/CMakeLists.txt index d19ab95..756f87b 100644 --- a/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetConsoleOutputCP.c + GetConsoleOutputCP.cpp ) add_executable(paltest_getconsoleoutputcp_test1 diff --git a/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/GetConsoleOutputCP.c b/src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/GetConsoleOutputCP.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/GetConsoleOutputCP.c rename to src/pal/tests/palsuite/file_io/GetConsoleOutputCP/test1/GetConsoleOutputCP.cpp diff --git a/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/CMakeLists.txt index f7382b0..28efc68 100644 --- a/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetCurrentDirectoryA.c + GetCurrentDirectoryA.cpp ) add_executable(paltest_getcurrentdirectorya_test1 diff --git a/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/GetCurrentDirectoryA.c b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/GetCurrentDirectoryA.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/GetCurrentDirectoryA.c rename to src/pal/tests/palsuite/file_io/GetCurrentDirectoryA/test1/GetCurrentDirectoryA.cpp diff --git a/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/CMakeLists.txt index ed84199..ee07f5e 100644 --- a/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetCurrentDirectoryW.c + GetCurrentDirectoryW.cpp ) add_executable(paltest_getcurrentdirectoryw_test1 diff --git a/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/GetCurrentDirectoryW.c b/src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/GetCurrentDirectoryW.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/GetCurrentDirectoryW.c rename to src/pal/tests/palsuite/file_io/GetCurrentDirectoryW/test1/GetCurrentDirectoryW.cpp diff --git a/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/CMakeLists.txt index 6b06376..7de0b27 100644 --- a/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetDiskFreeSpaceW.c + GetDiskFreeSpaceW.cpp ) add_executable(paltest_getdiskfreespacew_test1 diff --git a/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/GetDiskFreeSpaceW.c b/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/GetDiskFreeSpaceW.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/GetDiskFreeSpaceW.c rename to src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test1/GetDiskFreeSpaceW.cpp diff --git a/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/CMakeLists.txt index 5660b39..7bcbf55 100644 --- a/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - getdiskfreespacew.c + getdiskfreespacew.cpp ) add_executable(paltest_getdiskfreespacew_test2 diff --git a/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/getdiskfreespacew.c b/src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/getdiskfreespacew.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/getdiskfreespacew.c rename to src/pal/tests/palsuite/file_io/GetDiskFreeSpaceW/test2/getdiskfreespacew.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/CMakeLists.txt index 6bf9818..414df7f 100644 --- a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetFileAttributesA.c + GetFileAttributesA.cpp ) add_executable(paltest_getfileattributesa_test1 diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/GetFileAttributesA.c b/src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/GetFileAttributesA.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/GetFileAttributesA.c rename to src/pal/tests/palsuite/file_io/GetFileAttributesA/test1/GetFileAttributesA.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/CMakeLists.txt index 2d299d8..6ea24d9 100644 --- a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_getfileattributesexw_test1 diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/test1.c b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/test1.c rename to src/pal/tests/palsuite/file_io/GetFileAttributesExW/test1/test1.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/CMakeLists.txt index 70caac2..0faa3bd 100644 --- a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_getfileattributesexw_test2 diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/test2.c b/src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/test2.c rename to src/pal/tests/palsuite/file_io/GetFileAttributesExW/test2/test2.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/CMakeLists.txt index 7050484..bc82f36 100644 --- a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetFileAttributesW.c + GetFileAttributesW.cpp ) add_executable(paltest_getfileattributesw_test1 diff --git a/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/GetFileAttributesW.c b/src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/GetFileAttributesW.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/GetFileAttributesW.c rename to src/pal/tests/palsuite/file_io/GetFileAttributesW/test1/GetFileAttributesW.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFileSize/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileSize/test1/CMakeLists.txt index ff20de5..f192ba7 100644 --- a/src/pal/tests/palsuite/file_io/GetFileSize/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFileSize/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetFileSize.c + GetFileSize.cpp ) add_executable(paltest_getfilesize_test1 diff --git a/src/pal/tests/palsuite/file_io/GetFileSize/test1/GetFileSize.c b/src/pal/tests/palsuite/file_io/GetFileSize/test1/GetFileSize.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFileSize/test1/GetFileSize.c rename to src/pal/tests/palsuite/file_io/GetFileSize/test1/GetFileSize.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/CMakeLists.txt index 1369a5d..33a7e2f 100644 --- a/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetFileSizeEx.c + GetFileSizeEx.cpp ) add_executable(paltest_getfilesizeex_test1 diff --git a/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/GetFileSizeEx.c b/src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/GetFileSizeEx.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/GetFileSizeEx.c rename to src/pal/tests/palsuite/file_io/GetFileSizeEx/test1/GetFileSizeEx.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileTime/test1/CMakeLists.txt index 6a89846..b95267a 100644 --- a/src/pal/tests/palsuite/file_io/GetFileTime/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFileTime/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetFileTime.c + GetFileTime.cpp ) add_executable(paltest_getfiletime_test1 diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test1/GetFileTime.c b/src/pal/tests/palsuite/file_io/GetFileTime/test1/GetFileTime.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFileTime/test1/GetFileTime.c rename to src/pal/tests/palsuite/file_io/GetFileTime/test1/GetFileTime.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileTime/test2/CMakeLists.txt index 3d315e4..fe02e27 100644 --- a/src/pal/tests/palsuite/file_io/GetFileTime/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFileTime/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetFileTime.c + GetFileTime.cpp ) add_executable(paltest_getfiletime_test2 diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test2/GetFileTime.c b/src/pal/tests/palsuite/file_io/GetFileTime/test2/GetFileTime.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFileTime/test2/GetFileTime.c rename to src/pal/tests/palsuite/file_io/GetFileTime/test2/GetFileTime.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileTime/test3/CMakeLists.txt index 34f7310..bb88966 100644 --- a/src/pal/tests/palsuite/file_io/GetFileTime/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFileTime/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetFileTime.c + GetFileTime.cpp ) add_executable(paltest_getfiletime_test3 diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test3/GetFileTime.c b/src/pal/tests/palsuite/file_io/GetFileTime/test3/GetFileTime.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFileTime/test3/GetFileTime.c rename to src/pal/tests/palsuite/file_io/GetFileTime/test3/GetFileTime.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileTime/test4/CMakeLists.txt index 0c9dcf7..e43e7f9 100644 --- a/src/pal/tests/palsuite/file_io/GetFileTime/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFileTime/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetFileTime.c + GetFileTime.cpp ) add_executable(paltest_getfiletime_test4 diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test4/GetFileTime.c b/src/pal/tests/palsuite/file_io/GetFileTime/test4/GetFileTime.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFileTime/test4/GetFileTime.c rename to src/pal/tests/palsuite/file_io/GetFileTime/test4/GetFileTime.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test5/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileTime/test5/CMakeLists.txt index a82717e..4af995d 100644 --- a/src/pal/tests/palsuite/file_io/GetFileTime/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFileTime/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - getfiletime.c + getfiletime.cpp ) add_executable(paltest_getfiletime_test5 diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test5/getfiletime.c b/src/pal/tests/palsuite/file_io/GetFileTime/test5/getfiletime.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFileTime/test5/getfiletime.c rename to src/pal/tests/palsuite/file_io/GetFileTime/test5/getfiletime.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test6/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileTime/test6/CMakeLists.txt index 24992df..87c448b 100644 --- a/src/pal/tests/palsuite/file_io/GetFileTime/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFileTime/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - getfiletime.c + getfiletime.cpp ) add_executable(paltest_getfiletime_test6 diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test6/getfiletime.c b/src/pal/tests/palsuite/file_io/GetFileTime/test6/getfiletime.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFileTime/test6/getfiletime.c rename to src/pal/tests/palsuite/file_io/GetFileTime/test6/getfiletime.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test7/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileTime/test7/CMakeLists.txt index 6646fd9..cd5cde4 100644 --- a/src/pal/tests/palsuite/file_io/GetFileTime/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFileTime/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - getfiletime.c + getfiletime.cpp ) add_executable(paltest_getfiletime_test7 diff --git a/src/pal/tests/palsuite/file_io/GetFileTime/test7/getfiletime.c b/src/pal/tests/palsuite/file_io/GetFileTime/test7/getfiletime.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFileTime/test7/getfiletime.c rename to src/pal/tests/palsuite/file_io/GetFileTime/test7/getfiletime.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFileType/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileType/test1/CMakeLists.txt index 66467e9..cfaba2e 100644 --- a/src/pal/tests/palsuite/file_io/GetFileType/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFileType/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetFileType.c + GetFileType.cpp ) add_executable(paltest_getfiletype_test1 diff --git a/src/pal/tests/palsuite/file_io/GetFileType/test1/GetFileType.c b/src/pal/tests/palsuite/file_io/GetFileType/test1/GetFileType.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFileType/test1/GetFileType.c rename to src/pal/tests/palsuite/file_io/GetFileType/test1/GetFileType.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFileType/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileType/test2/CMakeLists.txt index 382b27e..07dae0b 100644 --- a/src/pal/tests/palsuite/file_io/GetFileType/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFileType/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - getfiletype.c + getfiletype.cpp ) add_executable(paltest_getfiletype_test2 diff --git a/src/pal/tests/palsuite/file_io/GetFileType/test2/getfiletype.c b/src/pal/tests/palsuite/file_io/GetFileType/test2/getfiletype.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFileType/test2/getfiletype.c rename to src/pal/tests/palsuite/file_io/GetFileType/test2/getfiletype.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFileType/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFileType/test3/CMakeLists.txt index 52b6077..9353c85 100644 --- a/src/pal/tests/palsuite/file_io/GetFileType/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFileType/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - getfiletype.c + getfiletype.cpp ) add_executable(paltest_getfiletype_test3 diff --git a/src/pal/tests/palsuite/file_io/GetFileType/test3/getfiletype.c b/src/pal/tests/palsuite/file_io/GetFileType/test3/getfiletype.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFileType/test3/getfiletype.c rename to src/pal/tests/palsuite/file_io/GetFileType/test3/getfiletype.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/CMakeLists.txt index 8c10e47..6198392 100644 --- a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetFullPathNameA.c + GetFullPathNameA.cpp ) add_executable(paltest_getfullpathnamea_test1 diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/GetFullPathNameA.c b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/GetFullPathNameA.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/GetFullPathNameA.c rename to src/pal/tests/palsuite/file_io/GetFullPathNameA/test1/GetFullPathNameA.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/CMakeLists.txt index 382b8fa..3449f2d 100644 --- a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_getfullpathnamea_test2 diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/test2.c b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/test2.c rename to src/pal/tests/palsuite/file_io/GetFullPathNameA/test2/test2.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/CMakeLists.txt index f0f8929..9d8d242 100644 --- a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_getfullpathnamea_test3 diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/test3.c b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/test3.c rename to src/pal/tests/palsuite/file_io/GetFullPathNameA/test3/test3.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/CMakeLists.txt index cf0d7ff..abf2bac 100644 --- a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_getfullpathnamea_test4 diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/test4.c b/src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/test4.c rename to src/pal/tests/palsuite/file_io/GetFullPathNameA/test4/test4.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/CMakeLists.txt index a6f354f..d455ca1 100644 --- a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetFullPathNameW.c + GetFullPathNameW.cpp ) add_executable(paltest_getfullpathnamew_test1 diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/GetFullPathNameW.c b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/GetFullPathNameW.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/GetFullPathNameW.c rename to src/pal/tests/palsuite/file_io/GetFullPathNameW/test1/GetFullPathNameW.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/CMakeLists.txt index 199aa1e..d974e94 100644 --- a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_getfullpathnamew_test2 diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/test2.c b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/test2.c rename to src/pal/tests/palsuite/file_io/GetFullPathNameW/test2/test2.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/CMakeLists.txt index 6284958..09439a6 100644 --- a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_getfullpathnamew_test3 diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/test3.c b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/test3.c rename to src/pal/tests/palsuite/file_io/GetFullPathNameW/test3/test3.cpp diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/CMakeLists.txt index d479b99..11ed958 100644 --- a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_getfullpathnamew_test4 diff --git a/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/test4.c b/src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/test4.c rename to src/pal/tests/palsuite/file_io/GetFullPathNameW/test4/test4.cpp diff --git a/src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/CMakeLists.txt index cf5dcd0..3b9f0b1 100644 --- a/src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetLongPathNameW.c + GetLongPathNameW.cpp ) add_executable(paltest_getlongpathnamew_test1 diff --git a/src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/GetLongPathNameW.c b/src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/GetLongPathNameW.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/GetLongPathNameW.c rename to src/pal/tests/palsuite/file_io/GetLongPathNameW/test1/GetLongPathNameW.cpp diff --git a/src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/CMakeLists.txt index 5746ef3..b92e431 100644 --- a/src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - getlongpathnamew.c + getlongpathnamew.cpp ) add_executable(paltest_getlongpathnamew_test2 diff --git a/src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/getlongpathnamew.c b/src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/getlongpathnamew.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/getlongpathnamew.c rename to src/pal/tests/palsuite/file_io/GetLongPathNameW/test2/getlongpathnamew.cpp diff --git a/src/pal/tests/palsuite/file_io/GetStdHandle/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetStdHandle/test1/CMakeLists.txt index 04bcc5f..eaa1721 100644 --- a/src/pal/tests/palsuite/file_io/GetStdHandle/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetStdHandle/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetStdHandle.c + GetStdHandle.cpp ) add_executable(paltest_getstdhandle_test1 diff --git a/src/pal/tests/palsuite/file_io/GetStdHandle/test1/GetStdHandle.c b/src/pal/tests/palsuite/file_io/GetStdHandle/test1/GetStdHandle.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetStdHandle/test1/GetStdHandle.c rename to src/pal/tests/palsuite/file_io/GetStdHandle/test1/GetStdHandle.cpp diff --git a/src/pal/tests/palsuite/file_io/GetStdHandle/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetStdHandle/test2/CMakeLists.txt index 97816b4..ef45aa0 100644 --- a/src/pal/tests/palsuite/file_io/GetStdHandle/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetStdHandle/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetStdHandle.c + GetStdHandle.cpp ) add_executable(paltest_getstdhandle_test2 diff --git a/src/pal/tests/palsuite/file_io/GetStdHandle/test2/GetStdHandle.c b/src/pal/tests/palsuite/file_io/GetStdHandle/test2/GetStdHandle.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetStdHandle/test2/GetStdHandle.c rename to src/pal/tests/palsuite/file_io/GetStdHandle/test2/GetStdHandle.cpp diff --git a/src/pal/tests/palsuite/file_io/GetSystemTime/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetSystemTime/test1/CMakeLists.txt index 94d5bcd..4367e88 100644 --- a/src/pal/tests/palsuite/file_io/GetSystemTime/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetSystemTime/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_getsystemtime_test1 diff --git a/src/pal/tests/palsuite/file_io/GetSystemTime/test1/test.c b/src/pal/tests/palsuite/file_io/GetSystemTime/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetSystemTime/test1/test.c rename to src/pal/tests/palsuite/file_io/GetSystemTime/test1/test.cpp diff --git a/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/CMakeLists.txt index 977a826..d149383 100644 --- a/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetSystemTimeAsFileTime.c + GetSystemTimeAsFileTime.cpp ) add_executable(paltest_getsystemtimeasfiletime_test1 diff --git a/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/GetSystemTimeAsFileTime.c b/src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/GetSystemTimeAsFileTime.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/GetSystemTimeAsFileTime.c rename to src/pal/tests/palsuite/file_io/GetSystemTimeAsFileTime/test1/GetSystemTimeAsFileTime.cpp diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/CMakeLists.txt index 1b759af..4ed0ccb 100644 --- a/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetTempFileNameA.c + GetTempFileNameA.cpp ) add_executable(paltest_gettempfilenamea_test1 diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/GetTempFileNameA.c b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/GetTempFileNameA.c deleted file mode 100644 index 8ede8ba..0000000 --- a/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/GetTempFileNameA.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*===================================================================== -** -** Source: GetTempFileNameA.c (test 1) -** -** Purpose: Tests the PAL implementation of the GetTempFileNameA function. -** -** Depends on: -** GetFileAttributesA -** DeleteFileA -** -** -**===================================================================*/ - -#include - - - -int __cdecl main(int argc, char *argv[]) -{ - UINT uiError = 0; - const UINT uUnique = 0; - const char* szDot = {"."}; - const char* szValidPrefix = {"cfr"}; - const char* szLongValidPrefix = {"cfrwxyz"}; - char szReturnedName[256]; - char szTempString[256]; - - if (0 != PAL_Initialize(argc, argv)) - { - return FAIL; - } - - /* valid path with null prefix */ - uiError = GetTempFileNameA(szDot, NULL, uUnique, szReturnedName); - if (uiError == 0) - { - Fail("GetTempFileNameA: ERROR -> Call failed with a valid path " - "with the error code: %ld\n", GetLastError()); - } - else - { - /* verify temp file was created */ - if (GetFileAttributesA(szReturnedName) == -1) - { - Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed on the " - "returned temp file \"%s\" with error code: %ld.\n", - szReturnedName, - GetLastError()); - } - if (DeleteFileA(szReturnedName) != TRUE) - { - Fail("GetTempFileNameA: ERROR -> DeleteFileW failed to delete" - "the created temp file with error code: %ld.\n", GetLastError()); - } - } - - - /* valid path with valid prefix */ - uiError = GetTempFileNameA(szDot, szValidPrefix, uUnique, szReturnedName); - if (uiError == 0) - { - Fail("GetTempFileNameA: ERROR -> Call failed with a valid path and " - "prefix with the error code: %ld\n", GetLastError()); - } - else - { - /* verify temp file was created */ - if (GetFileAttributesA(szReturnedName) == -1) - { - Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed on the " - "returned temp file \"%s\" with error code: %ld.\n", - szReturnedName, - GetLastError()); - } - if (DeleteFileA(szReturnedName) != TRUE) - { - Fail("GetTempFileNameA: ERROR -> DeleteFileW failed to delete" - "the created temp \"%s\" file with error code: %ld.\n", - szReturnedName, - GetLastError()); - } - } - - /* valid path with long prefix */ - uiError = GetTempFileNameA(szDot, szLongValidPrefix, uUnique, szReturnedName); - if (uiError == 0) - { - Fail("GetTempFileNameA: ERROR -> Call failed with a valid path and " - "prefix with the error code: %ld\n", GetLastError()); - } - else - { - /* verify temp file was created */ - if (GetFileAttributesA(szReturnedName) == -1) - { - Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed on the " - "returned temp file \"%s\" with error code: %ld.\n", - szReturnedName, - GetLastError()); - } - - /* now verify that it only used the first 3 characters of the prefix */ - sprintf(szTempString, "%s\\%s", szDot, szLongValidPrefix); - if (strncmp(szTempString, szReturnedName, 6) == 0) - { - Fail("GetTempFileNameA: ERROR -> It appears that an improper prefix " - "was used.\n"); - } - - if (DeleteFileA(szReturnedName) != TRUE) - { - Fail("GetTempFileNameA: ERROR -> DeleteFileW failed to delete" - "the created temp file \"%s\" with error code: %ld.\n", - szReturnedName, - GetLastError()); - } - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/GetTempFileNameA.cpp b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/GetTempFileNameA.cpp new file mode 100644 index 0000000..bea8e27 --- /dev/null +++ b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test1/GetTempFileNameA.cpp @@ -0,0 +1,125 @@ +// 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. + +/*===================================================================== +** +** Source: GetTempFileNameA.c (test 1) +** +** Purpose: Tests the PAL implementation of the GetTempFileNameA function. +** +** Depends on: +** GetFileAttributesA +** DeleteFileA +** +** +**===================================================================*/ + +#include + + + +int __cdecl main(int argc, char *argv[]) +{ + UINT uiError = 0; + const UINT uUnique = 0; + const char* szDot = {"."}; + const char* szValidPrefix = {"cfr"}; + const char* szLongValidPrefix = {"cfrwxyz"}; + char szReturnedName[256]; + char szTempString[256]; + + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + /* valid path with null prefix */ + uiError = GetTempFileNameA(szDot, NULL, uUnique, szReturnedName); + if (uiError == 0) + { + Fail("GetTempFileNameA: ERROR -> Call failed with a valid path " + "with the error code: %ld\n", GetLastError()); + } + else + { + /* verify temp file was created */ + if (GetFileAttributesA(szReturnedName) == -1) + { + Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed on the " + "returned temp file \"%s\" with error code: %ld.\n", + szReturnedName, + GetLastError()); + } + if (DeleteFileA(szReturnedName) != TRUE) + { + Fail("GetTempFileNameA: ERROR -> DeleteFileW failed to delete" + "the created temp file with error code: %ld.\n", GetLastError()); + } + } + + + /* valid path with valid prefix */ + uiError = GetTempFileNameA(szDot, szValidPrefix, uUnique, szReturnedName); + if (uiError == 0) + { + Fail("GetTempFileNameA: ERROR -> Call failed with a valid path and " + "prefix with the error code: %ld\n", GetLastError()); + } + else + { + /* verify temp file was created */ + if (GetFileAttributesA(szReturnedName) == -1) + { + Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed on the " + "returned temp file \"%s\" with error code: %ld.\n", + szReturnedName, + GetLastError()); + } + if (DeleteFileA(szReturnedName) != TRUE) + { + Fail("GetTempFileNameA: ERROR -> DeleteFileW failed to delete" + "the created temp \"%s\" file with error code: %ld.\n", + szReturnedName, + GetLastError()); + } + } + + /* valid path with long prefix */ + uiError = GetTempFileNameA(szDot, szLongValidPrefix, uUnique, szReturnedName); + if (uiError == 0) + { + Fail("GetTempFileNameA: ERROR -> Call failed with a valid path and " + "prefix with the error code: %ld\n", GetLastError()); + } + else + { + /* verify temp file was created */ + if (GetFileAttributesA(szReturnedName) == -1) + { + Fail("GetTempFileNameA: ERROR -> GetFileAttributes failed on the " + "returned temp file \"%s\" with error code: %ld.\n", + szReturnedName, + GetLastError()); + } + + /* now verify that it only used the first 3 characters of the prefix */ + sprintf_s(szTempString, _countof(szTempString), "%s\\%s", szDot, szLongValidPrefix); + if (strncmp(szTempString, szReturnedName, 6) == 0) + { + Fail("GetTempFileNameA: ERROR -> It appears that an improper prefix " + "was used.\n"); + } + + if (DeleteFileA(szReturnedName) != TRUE) + { + Fail("GetTempFileNameA: ERROR -> DeleteFileW failed to delete" + "the created temp file \"%s\" with error code: %ld.\n", + szReturnedName, + GetLastError()); + } + } + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/CMakeLists.txt index f4bd9b8..9d9b646 100644 --- a/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetTempFileNameA.c + GetTempFileNameA.cpp ) add_executable(paltest_gettempfilenamea_test2 diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/GetTempFileNameA.c b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/GetTempFileNameA.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/GetTempFileNameA.c rename to src/pal/tests/palsuite/file_io/GetTempFileNameA/test2/GetTempFileNameA.cpp diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/CMakeLists.txt index 9c02865..446f3cf 100644 --- a/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - gettempfilenamea.c + gettempfilenamea.cpp ) add_executable(paltest_gettempfilenamea_test3 diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/gettempfilenamea.c b/src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/gettempfilenamea.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/gettempfilenamea.c rename to src/pal/tests/palsuite/file_io/GetTempFileNameA/test3/gettempfilenamea.cpp diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/CMakeLists.txt index 1b6c599..6919cf6 100644 --- a/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetTempFileNameW.c + GetTempFileNameW.cpp ) add_executable(paltest_gettempfilenamew_test1 diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/GetTempFileNameW.c b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/GetTempFileNameW.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/GetTempFileNameW.c rename to src/pal/tests/palsuite/file_io/GetTempFileNameW/test1/GetTempFileNameW.cpp diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/CMakeLists.txt index 851030d..d077463 100644 --- a/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetTempFileNameW.c + GetTempFileNameW.cpp ) add_executable(paltest_gettempfilenamew_test2 diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/GetTempFileNameW.c b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/GetTempFileNameW.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/GetTempFileNameW.c rename to src/pal/tests/palsuite/file_io/GetTempFileNameW/test2/GetTempFileNameW.cpp diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/CMakeLists.txt index 82dd0a9..3aa0f4a 100644 --- a/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - gettempfilenamew.c + gettempfilenamew.cpp ) add_executable(paltest_gettempfilenamew_test3 diff --git a/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/gettempfilenamew.c b/src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/gettempfilenamew.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/gettempfilenamew.c rename to src/pal/tests/palsuite/file_io/GetTempFileNameW/test3/gettempfilenamew.cpp diff --git a/src/pal/tests/palsuite/file_io/GetTempPathW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/GetTempPathW/test1/CMakeLists.txt index f2979e9..04b2409 100644 --- a/src/pal/tests/palsuite/file_io/GetTempPathW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/GetTempPathW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetTempPathW.c + GetTempPathW.cpp ) add_executable(paltest_gettemppathw_test1 diff --git a/src/pal/tests/palsuite/file_io/GetTempPathW/test1/GetTempPathW.c b/src/pal/tests/palsuite/file_io/GetTempPathW/test1/GetTempPathW.c deleted file mode 100644 index 08c8807..0000000 --- a/src/pal/tests/palsuite/file_io/GetTempPathW/test1/GetTempPathW.c +++ /dev/null @@ -1,103 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: GetTempPathW.c (test 1) -** -** Purpose: Tests the PAL implementation of the GetTempPathW function. -** -** -**===================================================================*/ - -#include - -static void SetTmpDir(WCHAR path[]) -{ - DWORD result = SetEnvironmentVariableW(W("TMPDIR"), path); - if (!result) - { - Fail("ERROR -> SetEnvironmentVariableW failed with result %d and error code %d.\n", - result, GetLastError()); - } -} - -static void SetAndCompare(WCHAR tmpDirPath[], WCHAR expected[]) -{ - DWORD dwBufferLength = _MAX_DIR; - WCHAR path[dwBufferLength]; - - SetTmpDir(tmpDirPath); - - DWORD dwResultLen = GetTempPathW(dwBufferLength, path); - if (dwResultLen <= 0) - { - Fail("ERROR: GetTempPathW returned %d with error code %d.\n", dwResultLen, GetLastError()); - } - if (dwResultLen >= dwBufferLength) - { - Fail("ERROR: Buffer of length %d passed to GetTempPathA was too small to hold %d chars..\n", dwBufferLength, dwResultLen); - } - if (wcscmp(expected, path) != 0) - { - Fail("ERROR: GetTempPathW expected to get '%S' but instead got '%S'.\n", expected, path); - } - if (expected[dwResultLen - 1] != '/') - { - Fail("ERROR: GetTempPathW returned '%S', which should have ended in '/'.\n", path); - } -} - -static void SetAndCheckLength(WCHAR tmpDirPath [], int bufferLength, int expectedResultLength) -{ - WCHAR path[bufferLength]; - - SetTmpDir(tmpDirPath); - DWORD dwResultLen = GetTempPathW(bufferLength, path); - - if (dwResultLen != expectedResultLength) - { - Fail("GetTempPathW(%d, %S) expected to return %d but returned %d.\n", - bufferLength, tmpDirPath?tmpDirPath:W("NULL"), expectedResultLength, dwResultLen); - } -} - -int __cdecl main(int argc, char *argv[]) -{ - if (0 != PAL_Initialize(argc, argv)) - { - return FAIL; - } - - SetAndCompare(W("/tmp"), W("/tmp/")); - SetAndCompare(W("/tmp/"), W("/tmp/")); - SetAndCompare(W(""), W("/tmp/")); - SetAndCompare(NULL, W("/tmp/")); - SetAndCompare(W("/"), W("/")); - SetAndCompare(W("/var/tmp"), W("/var/tmp/")); - SetAndCompare(W("/var/tmp/"), W("/var/tmp/")); - SetAndCompare(W("~"), W("~/")); - SetAndCompare(W("~/"), W("~/")); - SetAndCompare(W(".tmp"), W(".tmp/")); - SetAndCompare(W("./tmp"), W("./tmp/")); - SetAndCompare(W("/home/someuser/sometempdir"), W("/home/someuser/sometempdir/")); - SetAndCompare(NULL, W("/tmp/")); - - DWORD dwResultLen = GetTempPathA(0, NULL); - if (dwResultLen != 0 || GetLastError() != ERROR_INVALID_PARAMETER) - { - Fail("GetTempPathW(NULL, ...) returned %d with error code %d but " - "should have failed with ERROR_INVALID_PARAMETER (%d).\n", - dwResultLen, GetLastError(), ERROR_INVALID_PARAMETER); - } - - SetAndCheckLength(W("abc/"), 5, 4); - SetAndCheckLength(W("abcd"), 5, 6); - SetAndCheckLength(W("abcde"), 5, 7); - SetAndCheckLength(W("abcdef/"), 5, 9); - SetAndCheckLength(NULL, 5, 6); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/file_io/GetTempPathW/test1/GetTempPathW.cpp b/src/pal/tests/palsuite/file_io/GetTempPathW/test1/GetTempPathW.cpp new file mode 100644 index 0000000..bf997de --- /dev/null +++ b/src/pal/tests/palsuite/file_io/GetTempPathW/test1/GetTempPathW.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*===================================================================== +** +** Source: GetTempPathW.c (test 1) +** +** Purpose: Tests the PAL implementation of the GetTempPathW function. +** +** +**===================================================================*/ + +#include + +static void SetTmpDir(const WCHAR path[]) +{ + DWORD result = SetEnvironmentVariableW(W("TMPDIR"), path); + if (!result) + { + Fail("ERROR -> SetEnvironmentVariableW failed with result %d and error code %d.\n", + result, GetLastError()); + } +} + +static void SetAndCompare(const WCHAR tmpDirPath[], const WCHAR expected[]) +{ + DWORD dwBufferLength = _MAX_DIR; + WCHAR path[dwBufferLength]; + + SetTmpDir(tmpDirPath); + + DWORD dwResultLen = GetTempPathW(dwBufferLength, path); + if (dwResultLen <= 0) + { + Fail("ERROR: GetTempPathW returned %d with error code %d.\n", dwResultLen, GetLastError()); + } + if (dwResultLen >= dwBufferLength) + { + Fail("ERROR: Buffer of length %d passed to GetTempPathA was too small to hold %d chars..\n", dwBufferLength, dwResultLen); + } + if (wcscmp(expected, path) != 0) + { + Fail("ERROR: GetTempPathW expected to get '%S' but instead got '%S'.\n", expected, path); + } + if (expected[dwResultLen - 1] != '/') + { + Fail("ERROR: GetTempPathW returned '%S', which should have ended in '/'.\n", path); + } +} + +static void SetAndCheckLength(const WCHAR tmpDirPath [], int bufferLength, int expectedResultLength) +{ + WCHAR path[bufferLength]; + + SetTmpDir(tmpDirPath); + DWORD dwResultLen = GetTempPathW(bufferLength, path); + + if (dwResultLen != expectedResultLength) + { + Fail("GetTempPathW(%d, %S) expected to return %d but returned %d.\n", + bufferLength, tmpDirPath?tmpDirPath:W("NULL"), expectedResultLength, dwResultLen); + } +} + +int __cdecl main(int argc, char *argv[]) +{ + if (0 != PAL_Initialize(argc, argv)) + { + return FAIL; + } + + SetAndCompare(W("/tmp"), W("/tmp/")); + SetAndCompare(W("/tmp/"), W("/tmp/")); + SetAndCompare(W(""), W("/tmp/")); + SetAndCompare(NULL, W("/tmp/")); + SetAndCompare(W("/"), W("/")); + SetAndCompare(W("/var/tmp"), W("/var/tmp/")); + SetAndCompare(W("/var/tmp/"), W("/var/tmp/")); + SetAndCompare(W("~"), W("~/")); + SetAndCompare(W("~/"), W("~/")); + SetAndCompare(W(".tmp"), W(".tmp/")); + SetAndCompare(W("./tmp"), W("./tmp/")); + SetAndCompare(W("/home/someuser/sometempdir"), W("/home/someuser/sometempdir/")); + SetAndCompare(NULL, W("/tmp/")); + + DWORD dwResultLen = GetTempPathA(0, NULL); + if (dwResultLen != 0 || GetLastError() != ERROR_INVALID_PARAMETER) + { + Fail("GetTempPathW(NULL, ...) returned %d with error code %d but " + "should have failed with ERROR_INVALID_PARAMETER (%d).\n", + dwResultLen, GetLastError(), ERROR_INVALID_PARAMETER); + } + + SetAndCheckLength(W("abc/"), 5, 4); + SetAndCheckLength(W("abcd"), 5, 6); + SetAndCheckLength(W("abcde"), 5, 7); + SetAndCheckLength(W("abcdef/"), 5, 9); + SetAndCheckLength(NULL, 5, 6); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/file_io/MoveFileA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/MoveFileA/test1/CMakeLists.txt index 9a3d006..b096a04 100644 --- a/src/pal/tests/palsuite/file_io/MoveFileA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/MoveFileA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - MoveFileA.c + MoveFileA.cpp ) add_executable(paltest_movefilea_test1 diff --git a/src/pal/tests/palsuite/file_io/MoveFileA/test1/MoveFileA.c b/src/pal/tests/palsuite/file_io/MoveFileA/test1/MoveFileA.c deleted file mode 100644 index 8d1bc0e..0000000 --- a/src/pal/tests/palsuite/file_io/MoveFileA/test1/MoveFileA.c +++ /dev/null @@ -1,469 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: MoveFileA.c -** -** Purpose: Tests the PAL implementation of the MoveFileA function. -** -** -**===================================================================*/ - -#include - -LPSTR lpSource[4] = {"src_existing.txt", - "src_non-existant.txt", - "src_dir_existing", - "src_dir_non-existant"}; -LPSTR lpDestination[4] = {"dst_existing.txt", - "dst_non-existant.txt", - "dst_dir_existing", - "dst_dir_non-existant"}; - - -/* Create all the required test files */ -int createExisting(void) -{ - FILE* tempFile = NULL; - DWORD dwError; - BOOL bRc = FALSE; - char szBuffer[100]; - - /* create the src_existing file */ - tempFile = fopen(lpSource[0], "w"); - if (tempFile != NULL) - { - fprintf(tempFile, "MoveFileA test file: src_existing.txt\n"); - fclose(tempFile); - } - else - { - Trace("ERROR: couldn't create %s\n", lpSource[0]); - return FAIL; - } - - /* create the src_dir_existing directory and files */ - bRc = CreateDirectoryA(lpSource[2], NULL); - if (bRc != TRUE) - { - Trace("MoveFileA: ERROR: couldn't create \"%s\" because of " - "error code %ld\n", - lpSource[2], - GetLastError()); - return FAIL; - } - - memset(szBuffer, 0, 100); - sprintf(szBuffer, "%s/test01.txt", lpSource[2]); - tempFile = fopen(szBuffer, "w"); - if (tempFile != NULL) - { - fprintf(tempFile, "MoveFileA test file: %s\n", szBuffer); - fclose(tempFile); - } - else - { - Trace("ERROR[%ld]:MoveFileA couldn't create %s\n", GetLastError(), szBuffer); - return FAIL; - } - - memset(szBuffer, 0, 100); - sprintf(szBuffer, "%s/test02.txt", lpSource[2]); - tempFile = fopen(szBuffer, "w"); - if (tempFile != NULL) - { - fprintf(tempFile, "MoveFileA test file: %s\n", szBuffer); - fclose(tempFile); - } - else - { - Trace("ERROR[%ld]: couldn't create %s\n", GetLastError(), szBuffer); - return FAIL; - } - - - /* create the dst_existing file */ - tempFile = fopen(lpDestination[0], "w"); - if (tempFile != NULL) - { - fprintf(tempFile, "MoveFileA test file: dst_existing.txt\n"); - fclose(tempFile); - } - else - { - Trace("ERROR[%ld]:MoveFileA couldn't create \"%s\"\n", GetLastError(), lpDestination[0]); - return FAIL; - } - - /* create the dst_dir_existing directory and files */ - bRc = CreateDirectoryA(lpDestination[2], NULL); - if (bRc != TRUE) - { - dwError = GetLastError(); - Trace("Error[%ld]:MoveFileA: couldn't create \"%s\"\n", GetLastError(), lpDestination[2]); - return FAIL; - } - - tempFile = fopen("dst_dir_existing/test01.txt", "w"); - if (tempFile != NULL) - { - fprintf(tempFile, "MoveFileA test file: dst_dir_existing/test01.txt\n"); - fclose(tempFile); - } - else - { - Trace("ERROR: couldn't create dst_dir_existing/test01.txt\n"); - return FAIL; - } - tempFile = fopen("dst_dir_existing/test02.txt", "w"); - if (tempFile != NULL) - { - fprintf(tempFile, "MoveFileA test file: dst_dir_existing/test02.txt\n"); - fclose(tempFile); - } - else - { - Trace("ERROR[%ul]: couldn't create dst_dir_existing/test02.txt\n", GetLastError()); - return FAIL; - } - - return PASS; -} - - - -void removeDirectoryHelper(LPSTR dir, int location) -{ - DWORD dwAtt = GetFileAttributesA(dir); - if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) - { - if(!RemoveDirectoryA(dir)) - { - Fail("ERROR: Failed to remove Directory [%s], Error Code [%d], location [%d]\n", dir, GetLastError(), location); - } - } -} - -void removeFileHelper(LPSTR pfile, int location) -{ - FILE *fp; - fp = fopen( pfile, "r"); - - if (fp != NULL) - { - if(fclose(fp)) - { - Fail("ERROR: Failed to close the file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location); - } - - if(!DeleteFileA(pfile)) - { - Fail("ERROR: Failed to delete file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location); - } - else - { - // Trace("Success: deleted file [%S], Error Code [%d], location [%d]\n", wfile, GetLastError(), location); - } - } - -} - - -/* remove all created files in preparation for the next test */ -void removeAll(void) -{ - char szTemp[40]; - DWORD dwAtt; - - /* get rid of source dirs and files */ - removeFileHelper(lpSource[0], 1); - removeFileHelper(lpSource[1], 2); - - dwAtt = GetFileAttributesA(lpSource[2]); - if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) - { - sprintf(szTemp, "%s/test01.txt", lpSource[2]); - removeFileHelper(szTemp, 18); - - sprintf(szTemp, "%s/test02.txt", lpSource[2]); - removeFileHelper(szTemp, 19); - removeDirectoryHelper(lpSource[2], 103); - } - else - { - removeFileHelper(lpSource[2], 17); - } - - - dwAtt = GetFileAttributesA(lpSource[3]); - if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) - { - sprintf(szTemp, "%s/test01.txt", lpSource[3]); - removeFileHelper(szTemp, 18); - - sprintf(szTemp, "%s/test02.txt", lpSource[3]); - removeFileHelper(szTemp, 19); - removeDirectoryHelper(lpSource[3], 103); - } - else - { - removeFileHelper(lpSource[3], 17); - } - - /* get rid of destination dirs and files */ - dwAtt = GetFileAttributesA(lpDestination[0]); - if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) - { - sprintf(szTemp, "%s/test01.txt", lpDestination[0]); - removeFileHelper(szTemp, 18); - - sprintf(szTemp, "%s/test02.txt", lpDestination[0]); - removeFileHelper(szTemp, 19); - removeDirectoryHelper(lpDestination[0], 103); - } - else - { - removeFileHelper(lpDestination[0], 17); - } - - dwAtt = GetFileAttributesA(lpDestination[1]); - if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) - { - sprintf(szTemp, "%s/test01.txt", lpDestination[1]); - removeFileHelper(szTemp, 18); - - sprintf(szTemp, "%s/test02.txt", lpDestination[1]); - removeFileHelper(szTemp, 19); - removeDirectoryHelper(lpDestination[1], 103); - } - else - { - removeFileHelper(lpDestination[1], 17); - } - - dwAtt = GetFileAttributesA(lpDestination[2]); - if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) - { - sprintf(szTemp, "%s/test01.txt", lpDestination[2]); - removeFileHelper(szTemp, 18); - - sprintf(szTemp, "%s/test02.txt", lpDestination[2]); - removeFileHelper(szTemp, 19); - removeDirectoryHelper(lpDestination[2], 103); - } - else - { - removeFileHelper(lpDestination[2], 17); - } - - dwAtt = GetFileAttributesA(lpDestination[3]); - if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) - { - sprintf(szTemp, "%s/test01.txt", lpDestination[3]); - removeFileHelper(szTemp, 18); - - sprintf(szTemp, "%s/test02.txt", lpDestination[3]); - removeFileHelper(szTemp, 19); - removeDirectoryHelper(lpDestination[3], 103); - } - else - { - removeFileHelper(lpDestination[3], 17); - } - -} - - - - - -int __cdecl main(int argc, char *argv[]) -{ - BOOL bRc = TRUE; - BOOL bSuccess = TRUE; - char results[40]; - FILE* resultsFile = NULL; - int nCounter = 0; - int i, j; - char tempSource[] = {'t','e','m','p','k','.','t','m','p','\0'}; - char tempDest[] = {'t','e','m','p','2','.','t','m','p','\0'}; - HANDLE hFile; - DWORD result; - - if (0 != PAL_Initialize(argc,argv)) - { - return FAIL; - } - - /* read in the expected results to compare with actual results */ - memset (results, 0, 20); - resultsFile = fopen("expectedresults.txt", "r"); - if (resultsFile == NULL) - { - Fail("MoveFileA ERROR[%ul]: Unable to open \"expectedresults.txt\"\n", GetLastError()); - } - - fgets(results, 20, resultsFile); - fclose(resultsFile); - - /* clean the slate */ - removeAll(); - - if (createExisting() != 0) - { - removeAll(); - } - - - /* lpSource loop */ - for (i = 0; i < 4; i++) - { - /* lpDestination loop */ - for (j = 0; j < 4; j++) - { - bRc = MoveFileA(lpSource[i], lpDestination[j]); - if (!( - ((bRc == TRUE) && (results[nCounter] == '1')) - || - ((bRc == FALSE ) && (results[nCounter] == '0')) ) - ) - { - Trace("MoveFileA: FAILED: test[%d][%d]: \"%s\" -> \"%s\"\n", - i, j, lpSource[i], lpDestination[j]); - bSuccess = FALSE; - } - - /* undo the last move */ - removeAll(); - createExisting(); - - nCounter++; - } - } - - removeAll(); - if (bSuccess == FALSE) - { - Fail("MoveFileA: Test Failed"); - } - - /* create the temp source file */ - hFile = CreateFileA(tempSource, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, 0); - - if( hFile == INVALID_HANDLE_VALUE ) - { - Fail("Error[%ul]:MoveFileA: CreateFile failed to " - "create the file correctly.\n", GetLastError()); - } - - bRc = CloseHandle(hFile); - if(!bRc) - { - Trace("MoveFileA: CloseHandle failed to close the " - "handle correctly. ERROR:%u\n",GetLastError()); - - /* delete the created file */ - bRc = DeleteFileA(tempSource); - if(!bRc) - { - Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the" - "file correctly.\n", GetLastError()); - } - Fail(""); - } - - /* set the file attributes to be readonly */ - bRc = SetFileAttributesA(tempSource, FILE_ATTRIBUTE_READONLY); - if(!bRc) - { - Trace("MoveFileA: SetFileAttributes failed to set file " - "attributes correctly. GetLastError returned %u\n",GetLastError()); - /* delete the created file */ - bRc = DeleteFileA(tempSource); - if(!bRc) - { - Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the" - "file correctly.\n", GetLastError()); - } - Fail(""); - } - - /* move the file to the new location */ - bRc = MoveFileA(tempSource, tempDest); - if(!bRc) - { - /* delete the created file */ - bRc = DeleteFileA(tempSource); - if(!bRc) - { - Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the" - "file correctly.\n", GetLastError()); - } - - Fail("Error[%ul]:MoveFileA(%S, %S): GetFileAttributes " - "failed to get the file's attributes.\n", - GetLastError(), tempSource, tempDest); - } - - /* check that the newly moved file has the same file attributes - as the original */ - result = GetFileAttributesA(tempDest); - if(result == 0) - { - /* delete the created file */ - bRc = DeleteFileA(tempDest); - if(!bRc) - { - Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the" - "file correctly.\n", GetLastError()); - } - - Fail("Error[%ul]:MoveFileA: GetFileAttributes failed to get " - "the file's attributes.\n", GetLastError()); - } - - if((result & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY) - { - /* delete the newly moved file */ - bRc = DeleteFileA(tempDest); - if(!bRc) - { - Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the" - "file correctly.\n", GetLastError()); - } - - Fail("Error[%ul]MoveFileA: GetFileAttributes failed to get " - "the correct file attributes.\n", GetLastError()); - } - - /* set the file attributes back to normal, to be deleted */ - bRc = SetFileAttributesA(tempDest, FILE_ATTRIBUTE_NORMAL); - if(!bRc) - { - /* delete the newly moved file */ - bRc = DeleteFileA(tempDest); - if(!bRc) - { - Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the" - "file correctly.\n", GetLastError()); - } - - Fail("Error[%ul]:MoveFileA: SetFileAttributes failed to set " - "file attributes correctly.\n", GetLastError()); - } - - /* delete the newly moved file */ - bRc = DeleteFileA(tempDest); - if(!bRc) - { - Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the" - "file correctly.\n", GetLastError()); - } - - PAL_Terminate(); - - return PASS; -} diff --git a/src/pal/tests/palsuite/file_io/MoveFileA/test1/MoveFileA.cpp b/src/pal/tests/palsuite/file_io/MoveFileA/test1/MoveFileA.cpp new file mode 100644 index 0000000..6d1337a --- /dev/null +++ b/src/pal/tests/palsuite/file_io/MoveFileA/test1/MoveFileA.cpp @@ -0,0 +1,469 @@ +// 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. + +/*===================================================================== +** +** Source: MoveFileA.c +** +** Purpose: Tests the PAL implementation of the MoveFileA function. +** +** +**===================================================================*/ + +#include + +LPSTR lpSource[4] = {"src_existing.txt", + "src_non-existant.txt", + "src_dir_existing", + "src_dir_non-existant"}; +LPSTR lpDestination[4] = {"dst_existing.txt", + "dst_non-existant.txt", + "dst_dir_existing", + "dst_dir_non-existant"}; + + +/* Create all the required test files */ +int createExisting(void) +{ + FILE* tempFile = NULL; + DWORD dwError; + BOOL bRc = FALSE; + char szBuffer[100]; + + /* create the src_existing file */ + tempFile = fopen(lpSource[0], "w"); + if (tempFile != NULL) + { + fprintf(tempFile, "MoveFileA test file: src_existing.txt\n"); + fclose(tempFile); + } + else + { + Trace("ERROR: couldn't create %s\n", lpSource[0]); + return FAIL; + } + + /* create the src_dir_existing directory and files */ + bRc = CreateDirectoryA(lpSource[2], NULL); + if (bRc != TRUE) + { + Trace("MoveFileA: ERROR: couldn't create \"%s\" because of " + "error code %ld\n", + lpSource[2], + GetLastError()); + return FAIL; + } + + memset(szBuffer, 0, 100); + sprintf_s(szBuffer, _countof(szBuffer), "%s/test01.txt", lpSource[2]); + tempFile = fopen(szBuffer, "w"); + if (tempFile != NULL) + { + fprintf(tempFile, "MoveFileA test file: %s\n", szBuffer); + fclose(tempFile); + } + else + { + Trace("ERROR[%ld]:MoveFileA couldn't create %s\n", GetLastError(), szBuffer); + return FAIL; + } + + memset(szBuffer, 0, 100); + sprintf_s(szBuffer, _countof(szBuffer), "%s/test02.txt", lpSource[2]); + tempFile = fopen(szBuffer, "w"); + if (tempFile != NULL) + { + fprintf(tempFile, "MoveFileA test file: %s\n", szBuffer); + fclose(tempFile); + } + else + { + Trace("ERROR[%ld]: couldn't create %s\n", GetLastError(), szBuffer); + return FAIL; + } + + + /* create the dst_existing file */ + tempFile = fopen(lpDestination[0], "w"); + if (tempFile != NULL) + { + fprintf(tempFile, "MoveFileA test file: dst_existing.txt\n"); + fclose(tempFile); + } + else + { + Trace("ERROR[%ld]:MoveFileA couldn't create \"%s\"\n", GetLastError(), lpDestination[0]); + return FAIL; + } + + /* create the dst_dir_existing directory and files */ + bRc = CreateDirectoryA(lpDestination[2], NULL); + if (bRc != TRUE) + { + dwError = GetLastError(); + Trace("Error[%ld]:MoveFileA: couldn't create \"%s\"\n", GetLastError(), lpDestination[2]); + return FAIL; + } + + tempFile = fopen("dst_dir_existing/test01.txt", "w"); + if (tempFile != NULL) + { + fprintf(tempFile, "MoveFileA test file: dst_dir_existing/test01.txt\n"); + fclose(tempFile); + } + else + { + Trace("ERROR: couldn't create dst_dir_existing/test01.txt\n"); + return FAIL; + } + tempFile = fopen("dst_dir_existing/test02.txt", "w"); + if (tempFile != NULL) + { + fprintf(tempFile, "MoveFileA test file: dst_dir_existing/test02.txt\n"); + fclose(tempFile); + } + else + { + Trace("ERROR[%ul]: couldn't create dst_dir_existing/test02.txt\n", GetLastError()); + return FAIL; + } + + return PASS; +} + + + +void removeDirectoryHelper(LPSTR dir, int location) +{ + DWORD dwAtt = GetFileAttributesA(dir); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + if(!RemoveDirectoryA(dir)) + { + Fail("ERROR: Failed to remove Directory [%s], Error Code [%d], location [%d]\n", dir, GetLastError(), location); + } + } +} + +void removeFileHelper(LPSTR pfile, int location) +{ + FILE *fp; + fp = fopen( pfile, "r"); + + if (fp != NULL) + { + if(fclose(fp)) + { + Fail("ERROR: Failed to close the file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location); + } + + if(!DeleteFileA(pfile)) + { + Fail("ERROR: Failed to delete file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location); + } + else + { + // Trace("Success: deleted file [%S], Error Code [%d], location [%d]\n", wfile, GetLastError(), location); + } + } + +} + + +/* remove all created files in preparation for the next test */ +void removeAll(void) +{ + char szTemp[40]; + DWORD dwAtt; + + /* get rid of source dirs and files */ + removeFileHelper(lpSource[0], 1); + removeFileHelper(lpSource[1], 2); + + dwAtt = GetFileAttributesA(lpSource[2]); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + sprintf_s(szTemp, _countof(szTemp), "%s/test01.txt", lpSource[2]); + removeFileHelper(szTemp, 18); + + sprintf_s(szTemp, _countof(szTemp), "%s/test02.txt", lpSource[2]); + removeFileHelper(szTemp, 19); + removeDirectoryHelper(lpSource[2], 103); + } + else + { + removeFileHelper(lpSource[2], 17); + } + + + dwAtt = GetFileAttributesA(lpSource[3]); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + sprintf_s(szTemp, _countof(szTemp), "%s/test01.txt", lpSource[3]); + removeFileHelper(szTemp, 18); + + sprintf_s(szTemp, _countof(szTemp), "%s/test02.txt", lpSource[3]); + removeFileHelper(szTemp, 19); + removeDirectoryHelper(lpSource[3], 103); + } + else + { + removeFileHelper(lpSource[3], 17); + } + + /* get rid of destination dirs and files */ + dwAtt = GetFileAttributesA(lpDestination[0]); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + sprintf_s(szTemp, _countof(szTemp), "%s/test01.txt", lpDestination[0]); + removeFileHelper(szTemp, 18); + + sprintf_s(szTemp, _countof(szTemp), "%s/test02.txt", lpDestination[0]); + removeFileHelper(szTemp, 19); + removeDirectoryHelper(lpDestination[0], 103); + } + else + { + removeFileHelper(lpDestination[0], 17); + } + + dwAtt = GetFileAttributesA(lpDestination[1]); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + sprintf_s(szTemp, _countof(szTemp), "%s/test01.txt", lpDestination[1]); + removeFileHelper(szTemp, 18); + + sprintf_s(szTemp, _countof(szTemp), "%s/test02.txt", lpDestination[1]); + removeFileHelper(szTemp, 19); + removeDirectoryHelper(lpDestination[1], 103); + } + else + { + removeFileHelper(lpDestination[1], 17); + } + + dwAtt = GetFileAttributesA(lpDestination[2]); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + sprintf_s(szTemp, _countof(szTemp), "%s/test01.txt", lpDestination[2]); + removeFileHelper(szTemp, 18); + + sprintf_s(szTemp, _countof(szTemp), "%s/test02.txt", lpDestination[2]); + removeFileHelper(szTemp, 19); + removeDirectoryHelper(lpDestination[2], 103); + } + else + { + removeFileHelper(lpDestination[2], 17); + } + + dwAtt = GetFileAttributesA(lpDestination[3]); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + sprintf_s(szTemp, _countof(szTemp), "%s/test01.txt", lpDestination[3]); + removeFileHelper(szTemp, 18); + + sprintf_s(szTemp, _countof(szTemp), "%s/test02.txt", lpDestination[3]); + removeFileHelper(szTemp, 19); + removeDirectoryHelper(lpDestination[3], 103); + } + else + { + removeFileHelper(lpDestination[3], 17); + } + +} + + + + + +int __cdecl main(int argc, char *argv[]) +{ + BOOL bRc = TRUE; + BOOL bSuccess = TRUE; + char results[40]; + FILE* resultsFile = NULL; + int nCounter = 0; + int i, j; + char tempSource[] = {'t','e','m','p','k','.','t','m','p','\0'}; + char tempDest[] = {'t','e','m','p','2','.','t','m','p','\0'}; + HANDLE hFile; + DWORD result; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* read in the expected results to compare with actual results */ + memset (results, 0, 20); + resultsFile = fopen("expectedresults.txt", "r"); + if (resultsFile == NULL) + { + Fail("MoveFileA ERROR[%ul]: Unable to open \"expectedresults.txt\"\n", GetLastError()); + } + + fgets(results, 20, resultsFile); + fclose(resultsFile); + + /* clean the slate */ + removeAll(); + + if (createExisting() != 0) + { + removeAll(); + } + + + /* lpSource loop */ + for (i = 0; i < 4; i++) + { + /* lpDestination loop */ + for (j = 0; j < 4; j++) + { + bRc = MoveFileA(lpSource[i], lpDestination[j]); + if (!( + ((bRc == TRUE) && (results[nCounter] == '1')) + || + ((bRc == FALSE ) && (results[nCounter] == '0')) ) + ) + { + Trace("MoveFileA: FAILED: test[%d][%d]: \"%s\" -> \"%s\"\n", + i, j, lpSource[i], lpDestination[j]); + bSuccess = FALSE; + } + + /* undo the last move */ + removeAll(); + createExisting(); + + nCounter++; + } + } + + removeAll(); + if (bSuccess == FALSE) + { + Fail("MoveFileA: Test Failed"); + } + + /* create the temp source file */ + hFile = CreateFileA(tempSource, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + + if( hFile == INVALID_HANDLE_VALUE ) + { + Fail("Error[%ul]:MoveFileA: CreateFile failed to " + "create the file correctly.\n", GetLastError()); + } + + bRc = CloseHandle(hFile); + if(!bRc) + { + Trace("MoveFileA: CloseHandle failed to close the " + "handle correctly. ERROR:%u\n",GetLastError()); + + /* delete the created file */ + bRc = DeleteFileA(tempSource); + if(!bRc) + { + Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the" + "file correctly.\n", GetLastError()); + } + Fail(""); + } + + /* set the file attributes to be readonly */ + bRc = SetFileAttributesA(tempSource, FILE_ATTRIBUTE_READONLY); + if(!bRc) + { + Trace("MoveFileA: SetFileAttributes failed to set file " + "attributes correctly. GetLastError returned %u\n",GetLastError()); + /* delete the created file */ + bRc = DeleteFileA(tempSource); + if(!bRc) + { + Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the" + "file correctly.\n", GetLastError()); + } + Fail(""); + } + + /* move the file to the new location */ + bRc = MoveFileA(tempSource, tempDest); + if(!bRc) + { + /* delete the created file */ + bRc = DeleteFileA(tempSource); + if(!bRc) + { + Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the" + "file correctly.\n", GetLastError()); + } + + Fail("Error[%ul]:MoveFileA(%S, %S): GetFileAttributes " + "failed to get the file's attributes.\n", + GetLastError(), tempSource, tempDest); + } + + /* check that the newly moved file has the same file attributes + as the original */ + result = GetFileAttributesA(tempDest); + if(result == 0) + { + /* delete the created file */ + bRc = DeleteFileA(tempDest); + if(!bRc) + { + Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the" + "file correctly.\n", GetLastError()); + } + + Fail("Error[%ul]:MoveFileA: GetFileAttributes failed to get " + "the file's attributes.\n", GetLastError()); + } + + if((result & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY) + { + /* delete the newly moved file */ + bRc = DeleteFileA(tempDest); + if(!bRc) + { + Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the" + "file correctly.\n", GetLastError()); + } + + Fail("Error[%ul]MoveFileA: GetFileAttributes failed to get " + "the correct file attributes.\n", GetLastError()); + } + + /* set the file attributes back to normal, to be deleted */ + bRc = SetFileAttributesA(tempDest, FILE_ATTRIBUTE_NORMAL); + if(!bRc) + { + /* delete the newly moved file */ + bRc = DeleteFileA(tempDest); + if(!bRc) + { + Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the" + "file correctly.\n", GetLastError()); + } + + Fail("Error[%ul]:MoveFileA: SetFileAttributes failed to set " + "file attributes correctly.\n", GetLastError()); + } + + /* delete the newly moved file */ + bRc = DeleteFileA(tempDest); + if(!bRc) + { + Fail("Error[%ul]:MoveFileA: DeleteFileA failed to delete the" + "file correctly.\n", GetLastError()); + } + + PAL_Terminate(); + + return PASS; +} diff --git a/src/pal/tests/palsuite/file_io/MoveFileExA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/MoveFileExA/test1/CMakeLists.txt index f41dd7f..ef24717 100644 --- a/src/pal/tests/palsuite/file_io/MoveFileExA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/MoveFileExA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - MoveFileExA.c + MoveFileExA.cpp ) add_executable(paltest_movefileexa_test1 diff --git a/src/pal/tests/palsuite/file_io/MoveFileExA/test1/MoveFileExA.c b/src/pal/tests/palsuite/file_io/MoveFileExA/test1/MoveFileExA.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/MoveFileExA/test1/MoveFileExA.c rename to src/pal/tests/palsuite/file_io/MoveFileExA/test1/MoveFileExA.cpp diff --git a/src/pal/tests/palsuite/file_io/MoveFileExW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/MoveFileExW/test1/CMakeLists.txt index 4c6a70f..ca6b35e 100644 --- a/src/pal/tests/palsuite/file_io/MoveFileExW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/MoveFileExW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - MoveFileExW.c + MoveFileExW.cpp ) add_executable(paltest_movefileexw_test1 diff --git a/src/pal/tests/palsuite/file_io/MoveFileExW/test1/MoveFileExW.c b/src/pal/tests/palsuite/file_io/MoveFileExW/test1/MoveFileExW.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/MoveFileExW/test1/MoveFileExW.c rename to src/pal/tests/palsuite/file_io/MoveFileExW/test1/MoveFileExW.cpp diff --git a/src/pal/tests/palsuite/file_io/MoveFileW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/MoveFileW/test1/CMakeLists.txt index 497f654..4519746 100644 --- a/src/pal/tests/palsuite/file_io/MoveFileW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/MoveFileW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - MoveFileW.c + MoveFileW.cpp ) add_executable(paltest_movefilew_test1 diff --git a/src/pal/tests/palsuite/file_io/MoveFileW/test1/MoveFileW.c b/src/pal/tests/palsuite/file_io/MoveFileW/test1/MoveFileW.c deleted file mode 100644 index 5899930..0000000 --- a/src/pal/tests/palsuite/file_io/MoveFileW/test1/MoveFileW.c +++ /dev/null @@ -1,478 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: MoveFileW.c -** -** Purpose: Tests the PAL implementation of the MoveFileW function. -** -** -**===================================================================*/ - -#include - -LPSTR lpSource[4] = {"src_existing.txt", - "src_non-existant.txt", - "src_dir_existing", - "src_dir_non-existant"}; -LPSTR lpDestination[4] = {"dst_existing.txt", - "dst_non-existant.txt", - "dst_dir_existing", - "dst_dir_non-existant"}; - - -/* Create all the required test files */ -int createExisting(void) -{ - FILE* tempFile = NULL; - DWORD dwError; - BOOL bRc = FALSE; - WCHAR* wPtr = NULL; - char szBuffer[100]; - - /* create the src_existing file */ - tempFile = fopen(lpSource[0], "w"); - if (tempFile != NULL) - { - fprintf(tempFile, "MoveFile test file: src_existing.txt\n"); - fclose(tempFile); - } - else - { - Trace("ERROR: couldn't create %s\n", lpSource[0]); - return FAIL; - } - - /* create the src_dir_existing directory and files */ - wPtr = convert(lpSource[2]); - bRc = CreateDirectoryW(wPtr, NULL); - free(wPtr); - if (bRc != TRUE) - { - Trace("MoveFileW: ERROR: couldn't create \"%s\" because of " - "error code %ld\n", - lpSource[2], - GetLastError()); - return FAIL; - } - - memset(szBuffer, 0, 100); - sprintf(szBuffer, "%s/test01.txt", lpSource[2]); - tempFile = fopen(szBuffer, "w"); - if (tempFile != NULL) - { - fprintf(tempFile, "MoveFileW test file: %s\n", szBuffer); - fclose(tempFile); - } - else - { - Trace("ERROR: couldn't create %s\n", szBuffer); - return FAIL; - } - - memset(szBuffer, 0, 100); - sprintf(szBuffer, "%s/test02.txt", lpSource[2]); - tempFile = fopen(szBuffer, "w"); - if (tempFile != NULL) - { - fprintf(tempFile, "MoveFileW test file: %s\n", szBuffer); - fclose(tempFile); - } - else - { - Trace("ERROR: couldn't create %s\n", szBuffer); - return FAIL; - } - - - /* create the dst_existing file */ - tempFile = fopen(lpDestination[0], "w"); - if (tempFile != NULL) - { - fprintf(tempFile, "MoveFileW test file: dst_existing.txt\n"); - fclose(tempFile); - } - else - { - Trace("ERROR: couldn't create \"%s\"\n", lpDestination[0]); - return FAIL; - } - - /* create the dst_dir_existing directory and files */ - wPtr = convert(lpDestination[2]); - bRc = CreateDirectoryW(wPtr, NULL); - free(wPtr); - if (bRc != TRUE) - { - dwError = GetLastError(); - Trace("MoveFileW: ERROR: couldn't create \"%s\"\n", lpDestination[2]); - return FAIL; - } - - tempFile = fopen("dst_dir_existing/test01.txt", "w"); - if (tempFile != NULL) - { - fprintf(tempFile, "MoveFileW test file: dst_dir_existing/test01.txt\n"); - fclose(tempFile); - } - else - { - Trace("ERROR: couldn't create dst_dir_existing/test01.txt\n"); - return FAIL; - } - tempFile = fopen("dst_dir_existing/test02.txt", "w"); - if (tempFile != NULL) - { - fprintf(tempFile, "MoveFileW test file: dst_dir_existing/test02.txt\n"); - fclose(tempFile); - } - else - { - Trace("ERROR: couldn't create dst_dir_existing/test02.txt\n"); - return FAIL; - } - - return PASS; -} - -void removeDirectoryHelper(LPSTR dir, int location) -{ - DWORD dwAtt = GetFileAttributesA(dir); - if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) - { - if(!RemoveDirectoryA(dir)) - { - Fail("ERROR: Failed to remove Directory [%s], Error Code [%d], location [%d]\n", dir, GetLastError(), location); - } - } -} - -void removeFileHelper(LPSTR pfile, int location) -{ - FILE *fp; - fp = fopen( pfile, "r"); - - if (fp != NULL) - { - if(fclose(fp)) - { - Fail("ERROR: Failed to close the file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location); - } - - if(!DeleteFileA(pfile)) - { - Fail("ERROR: Failed to delete file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location); - } - else - { - // Trace("Success: deleted file [%S], Error Code [%d], location [%d]\n", wfile, GetLastError(), location); - } - } - -} - -/* remove all created files in preparation for the next test */ -void removeAll(void) -{ - char szTemp[40]; - DWORD dwAtt; - - /* get rid of source dirs and files */ - removeFileHelper(lpSource[0], 1); - removeFileHelper(lpSource[1], 2); - - dwAtt = GetFileAttributesA(lpSource[2]); - if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) - { - sprintf(szTemp, "%s/test01.txt", lpSource[2]); - removeFileHelper(szTemp, 18); - - sprintf(szTemp, "%s/test02.txt", lpSource[2]); - removeFileHelper(szTemp, 19); - removeDirectoryHelper(lpSource[2], 103); - } - else - { - removeFileHelper(lpSource[2], 17); - } - - - dwAtt = GetFileAttributesA(lpSource[3]); - if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) - { - sprintf(szTemp, "%s/test01.txt", lpSource[3]); - removeFileHelper(szTemp, 18); - - sprintf(szTemp, "%s/test02.txt", lpSource[3]); - removeFileHelper(szTemp, 19); - removeDirectoryHelper(lpSource[3], 103); - } - else - { - removeFileHelper(lpSource[3], 17); - } - - /* get rid of destination dirs and files */ - dwAtt = GetFileAttributesA(lpDestination[0]); - if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) - { - sprintf(szTemp, "%s/test01.txt", lpDestination[0]); - removeFileHelper(szTemp, 18); - - sprintf(szTemp, "%s/test02.txt", lpDestination[0]); - removeFileHelper(szTemp, 19); - removeDirectoryHelper(lpDestination[0], 103); - } - else - { - removeFileHelper(lpDestination[0], 17); - } - - dwAtt = GetFileAttributesA(lpDestination[1]); - if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) - { - sprintf(szTemp, "%s/test01.txt", lpDestination[1]); - removeFileHelper(szTemp, 18); - - sprintf(szTemp, "%s/test02.txt", lpDestination[1]); - removeFileHelper(szTemp, 19); - removeDirectoryHelper(lpDestination[1], 103); - } - else - { - removeFileHelper(lpDestination[1], 17); - } - - dwAtt = GetFileAttributesA(lpDestination[2]); - if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) - { - sprintf(szTemp, "%s/test01.txt", lpDestination[2]); - removeFileHelper(szTemp, 18); - - sprintf(szTemp, "%s/test02.txt", lpDestination[2]); - removeFileHelper(szTemp, 19); - removeDirectoryHelper(lpDestination[2], 103); - } - else - { - removeFileHelper(lpDestination[2], 17); - } - - dwAtt = GetFileAttributesA(lpDestination[3]); - if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) - { - sprintf(szTemp, "%s/test01.txt", lpDestination[3]); - removeFileHelper(szTemp, 18); - - sprintf(szTemp, "%s/test02.txt", lpDestination[3]); - removeFileHelper(szTemp, 19); - removeDirectoryHelper(lpDestination[3], 103); - } - else - { - removeFileHelper(lpDestination[3], 17); - } - -} - - - - - -int __cdecl main(int argc, char *argv[]) -{ - BOOL bRc = TRUE; - BOOL bSuccess = TRUE; - char results[40]; - FILE* resultsFile = NULL; - int nCounter = 0; - int i, j; - WCHAR* wSource = NULL; - WCHAR* wDest = NULL; - WCHAR tempSource[] = {'t','e','m','p','k','.','t','m','p','\0'}; - WCHAR tempDest[] = {'t','e','m','p','2','.','t','m','p','\0'}; - HANDLE hFile; - DWORD result; - - if (0 != PAL_Initialize(argc,argv)) - { - return FAIL; - } - - /* read in the expected results to compare with actual results */ - memset (results, 0, 20); - resultsFile = fopen("expectedresults.txt", "r"); - if (resultsFile == NULL) - { - Fail("MoveFileW ERROR: Unable to open \"expectedresults.txt\"\n"); - } - - fgets(results, 20, resultsFile); - fclose(resultsFile); - - /* clean the slate */ - removeAll(); - - if (createExisting() != 0) - { - removeAll(); - } - - - /* lpSource loop */ - for (i = 0; i < 4; i++) - { - /* lpDestination loop */ - for (j = 0; j < 4; j++) - { - - wSource = convert(lpSource[i]); - wDest = convert(lpDestination[j]); - bRc = MoveFileW(wSource, wDest); - free(wSource); - free(wDest); - if (!( - ((bRc == TRUE) && (results[nCounter] == '1')) - || - ((bRc == FALSE ) && (results[nCounter] == '0')) ) - ) - { - Trace("MoveFileW: FAILED: test[%d][%d]: \"%s\" -> \"%s\"\n", - i, j, lpSource[i], lpDestination[j]); - bSuccess = FALSE; - } - - /* undo the last move */ - removeAll(); - createExisting(); - - nCounter++; - } - } - - removeAll(); - if (bSuccess == FALSE) - { - Fail("MoveFileW: Test Failed"); - } - - /* create the temp source file */ - hFile = CreateFileW(tempSource, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, 0); - - if( hFile == INVALID_HANDLE_VALUE ) - { - Fail("MoveFileW: CreateFile failed to " - "create the file correctly.\n"); - } - - bRc = CloseHandle(hFile); - if(!bRc) - { - Trace("MoveFileW: CloseHandle failed to close the " - "handle correctly. ERROR:%u\n",GetLastError()); - - /* delete the created file */ - bRc = DeleteFileW(tempSource); - if(!bRc) - { - Fail("MoveFileW: DeleteFileW failed to delete the" - "file correctly.\n"); - } - Fail(""); - } - - /* set the file attributes to be readonly */ - bRc = SetFileAttributesW(tempSource, FILE_ATTRIBUTE_READONLY); - if(!bRc) - { - Trace("MoveFileW: SetFileAttributes failed to set file " - "attributes correctly. GetLastError returned %u\n",GetLastError()); - /* delete the created file */ - bRc = DeleteFileW(tempSource); - if(!bRc) - { - Fail("MoveFileW: DeleteFileW failed to delete the" - "file correctly.\n"); - } - Fail(""); - } - - /* move the file to the new location */ - bRc = MoveFileW(tempSource, tempDest); - if(!bRc) - { - /* delete the created file */ - bRc = DeleteFileW(tempSource); - if(!bRc) - { - Fail("MoveFileW: DeleteFileW failed to delete the" - "file correctly.\n"); - } - - Fail("MoveFileW(%S, %S): GetFileAttributes " - "failed to get the file's attributes.\n", - tempSource, tempDest); - } - - /* check that the newly moved file has the same file attributes - as the original */ - result = GetFileAttributesW(tempDest); - if(result == 0) - { - /* delete the created file */ - bRc = DeleteFileW(tempDest); - if(!bRc) - { - Fail("MoveFileW: DeleteFileW failed to delete the" - "file correctly.\n"); - } - - Fail("MoveFileW: GetFileAttributes failed to get " - "the file's attributes.\n"); - } - - if((result & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY) - { - /* delete the newly moved file */ - bRc = DeleteFileW(tempDest); - if(!bRc) - { - Fail("MoveFileW: DeleteFileW failed to delete the" - "file correctly.\n"); - } - - Fail("MoveFileW: GetFileAttributes failed to get " - "the correct file attributes.\n"); - } - - /* set the file attributes back to normal, to be deleted */ - bRc = SetFileAttributesW(tempDest, FILE_ATTRIBUTE_NORMAL); - if(!bRc) - { - /* delete the newly moved file */ - bRc = DeleteFileW(tempDest); - if(!bRc) - { - Fail("MoveFileW: DeleteFileW failed to delete the" - "file correctly.\n"); - } - - Fail("MoveFileW: SetFileAttributes failed to set " - "file attributes correctly.\n"); - } - - /* delete the newly moved file */ - bRc = DeleteFileW(tempDest); - if(!bRc) - { - Fail("MoveFileW: DeleteFileW failed to delete the" - "file correctly.\n"); - } - - PAL_Terminate(); - - return PASS; -} diff --git a/src/pal/tests/palsuite/file_io/MoveFileW/test1/MoveFileW.cpp b/src/pal/tests/palsuite/file_io/MoveFileW/test1/MoveFileW.cpp new file mode 100644 index 0000000..8a7fae5 --- /dev/null +++ b/src/pal/tests/palsuite/file_io/MoveFileW/test1/MoveFileW.cpp @@ -0,0 +1,478 @@ +// 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. + +/*===================================================================== +** +** Source: MoveFileW.c +** +** Purpose: Tests the PAL implementation of the MoveFileW function. +** +** +**===================================================================*/ + +#include + +LPSTR lpSource[4] = {"src_existing.txt", + "src_non-existant.txt", + "src_dir_existing", + "src_dir_non-existant"}; +LPSTR lpDestination[4] = {"dst_existing.txt", + "dst_non-existant.txt", + "dst_dir_existing", + "dst_dir_non-existant"}; + + +/* Create all the required test files */ +int createExisting(void) +{ + FILE* tempFile = NULL; + DWORD dwError; + BOOL bRc = FALSE; + WCHAR* wPtr = NULL; + char szBuffer[100]; + + /* create the src_existing file */ + tempFile = fopen(lpSource[0], "w"); + if (tempFile != NULL) + { + fprintf(tempFile, "MoveFile test file: src_existing.txt\n"); + fclose(tempFile); + } + else + { + Trace("ERROR: couldn't create %s\n", lpSource[0]); + return FAIL; + } + + /* create the src_dir_existing directory and files */ + wPtr = convert(lpSource[2]); + bRc = CreateDirectoryW(wPtr, NULL); + free(wPtr); + if (bRc != TRUE) + { + Trace("MoveFileW: ERROR: couldn't create \"%s\" because of " + "error code %ld\n", + lpSource[2], + GetLastError()); + return FAIL; + } + + memset(szBuffer, 0, 100); + sprintf_s(szBuffer, _countof(szBuffer), "%s/test01.txt", lpSource[2]); + tempFile = fopen(szBuffer, "w"); + if (tempFile != NULL) + { + fprintf(tempFile, "MoveFileW test file: %s\n", szBuffer); + fclose(tempFile); + } + else + { + Trace("ERROR: couldn't create %s\n", szBuffer); + return FAIL; + } + + memset(szBuffer, 0, 100); + sprintf_s(szBuffer, _countof(szBuffer), "%s/test02.txt", lpSource[2]); + tempFile = fopen(szBuffer, "w"); + if (tempFile != NULL) + { + fprintf(tempFile, "MoveFileW test file: %s\n", szBuffer); + fclose(tempFile); + } + else + { + Trace("ERROR: couldn't create %s\n", szBuffer); + return FAIL; + } + + + /* create the dst_existing file */ + tempFile = fopen(lpDestination[0], "w"); + if (tempFile != NULL) + { + fprintf(tempFile, "MoveFileW test file: dst_existing.txt\n"); + fclose(tempFile); + } + else + { + Trace("ERROR: couldn't create \"%s\"\n", lpDestination[0]); + return FAIL; + } + + /* create the dst_dir_existing directory and files */ + wPtr = convert(lpDestination[2]); + bRc = CreateDirectoryW(wPtr, NULL); + free(wPtr); + if (bRc != TRUE) + { + dwError = GetLastError(); + Trace("MoveFileW: ERROR: couldn't create \"%s\"\n", lpDestination[2]); + return FAIL; + } + + tempFile = fopen("dst_dir_existing/test01.txt", "w"); + if (tempFile != NULL) + { + fprintf(tempFile, "MoveFileW test file: dst_dir_existing/test01.txt\n"); + fclose(tempFile); + } + else + { + Trace("ERROR: couldn't create dst_dir_existing/test01.txt\n"); + return FAIL; + } + tempFile = fopen("dst_dir_existing/test02.txt", "w"); + if (tempFile != NULL) + { + fprintf(tempFile, "MoveFileW test file: dst_dir_existing/test02.txt\n"); + fclose(tempFile); + } + else + { + Trace("ERROR: couldn't create dst_dir_existing/test02.txt\n"); + return FAIL; + } + + return PASS; +} + +void removeDirectoryHelper(LPSTR dir, int location) +{ + DWORD dwAtt = GetFileAttributesA(dir); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + if(!RemoveDirectoryA(dir)) + { + Fail("ERROR: Failed to remove Directory [%s], Error Code [%d], location [%d]\n", dir, GetLastError(), location); + } + } +} + +void removeFileHelper(LPSTR pfile, int location) +{ + FILE *fp; + fp = fopen( pfile, "r"); + + if (fp != NULL) + { + if(fclose(fp)) + { + Fail("ERROR: Failed to close the file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location); + } + + if(!DeleteFileA(pfile)) + { + Fail("ERROR: Failed to delete file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location); + } + else + { + // Trace("Success: deleted file [%S], Error Code [%d], location [%d]\n", wfile, GetLastError(), location); + } + } + +} + +/* remove all created files in preparation for the next test */ +void removeAll(void) +{ + char szTemp[40]; + DWORD dwAtt; + + /* get rid of source dirs and files */ + removeFileHelper(lpSource[0], 1); + removeFileHelper(lpSource[1], 2); + + dwAtt = GetFileAttributesA(lpSource[2]); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + sprintf_s(szTemp, _countof(szTemp), "%s/test01.txt", lpSource[2]); + removeFileHelper(szTemp, 18); + + sprintf_s(szTemp, _countof(szTemp), "%s/test02.txt", lpSource[2]); + removeFileHelper(szTemp, 19); + removeDirectoryHelper(lpSource[2], 103); + } + else + { + removeFileHelper(lpSource[2], 17); + } + + + dwAtt = GetFileAttributesA(lpSource[3]); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + sprintf_s(szTemp, _countof(szTemp), "%s/test01.txt", lpSource[3]); + removeFileHelper(szTemp, 18); + + sprintf_s(szTemp, _countof(szTemp), "%s/test02.txt", lpSource[3]); + removeFileHelper(szTemp, 19); + removeDirectoryHelper(lpSource[3], 103); + } + else + { + removeFileHelper(lpSource[3], 17); + } + + /* get rid of destination dirs and files */ + dwAtt = GetFileAttributesA(lpDestination[0]); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + sprintf_s(szTemp, _countof(szTemp), "%s/test01.txt", lpDestination[0]); + removeFileHelper(szTemp, 18); + + sprintf_s(szTemp, _countof(szTemp), "%s/test02.txt", lpDestination[0]); + removeFileHelper(szTemp, 19); + removeDirectoryHelper(lpDestination[0], 103); + } + else + { + removeFileHelper(lpDestination[0], 17); + } + + dwAtt = GetFileAttributesA(lpDestination[1]); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + sprintf_s(szTemp, _countof(szTemp), "%s/test01.txt", lpDestination[1]); + removeFileHelper(szTemp, 18); + + sprintf_s(szTemp, _countof(szTemp), "%s/test02.txt", lpDestination[1]); + removeFileHelper(szTemp, 19); + removeDirectoryHelper(lpDestination[1], 103); + } + else + { + removeFileHelper(lpDestination[1], 17); + } + + dwAtt = GetFileAttributesA(lpDestination[2]); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + sprintf_s(szTemp, _countof(szTemp), "%s/test01.txt", lpDestination[2]); + removeFileHelper(szTemp, 18); + + sprintf_s(szTemp, _countof(szTemp), "%s/test02.txt", lpDestination[2]); + removeFileHelper(szTemp, 19); + removeDirectoryHelper(lpDestination[2], 103); + } + else + { + removeFileHelper(lpDestination[2], 17); + } + + dwAtt = GetFileAttributesA(lpDestination[3]); + if (( dwAtt != INVALID_FILE_ATTRIBUTES ) && ( dwAtt & FILE_ATTRIBUTE_DIRECTORY) ) + { + sprintf_s(szTemp, _countof(szTemp), "%s/test01.txt", lpDestination[3]); + removeFileHelper(szTemp, 18); + + sprintf_s(szTemp, _countof(szTemp), "%s/test02.txt", lpDestination[3]); + removeFileHelper(szTemp, 19); + removeDirectoryHelper(lpDestination[3], 103); + } + else + { + removeFileHelper(lpDestination[3], 17); + } + +} + + + + + +int __cdecl main(int argc, char *argv[]) +{ + BOOL bRc = TRUE; + BOOL bSuccess = TRUE; + char results[40]; + FILE* resultsFile = NULL; + int nCounter = 0; + int i, j; + WCHAR* wSource = NULL; + WCHAR* wDest = NULL; + WCHAR tempSource[] = {'t','e','m','p','k','.','t','m','p','\0'}; + WCHAR tempDest[] = {'t','e','m','p','2','.','t','m','p','\0'}; + HANDLE hFile; + DWORD result; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* read in the expected results to compare with actual results */ + memset (results, 0, 20); + resultsFile = fopen("expectedresults.txt", "r"); + if (resultsFile == NULL) + { + Fail("MoveFileW ERROR: Unable to open \"expectedresults.txt\"\n"); + } + + fgets(results, 20, resultsFile); + fclose(resultsFile); + + /* clean the slate */ + removeAll(); + + if (createExisting() != 0) + { + removeAll(); + } + + + /* lpSource loop */ + for (i = 0; i < 4; i++) + { + /* lpDestination loop */ + for (j = 0; j < 4; j++) + { + + wSource = convert(lpSource[i]); + wDest = convert(lpDestination[j]); + bRc = MoveFileW(wSource, wDest); + free(wSource); + free(wDest); + if (!( + ((bRc == TRUE) && (results[nCounter] == '1')) + || + ((bRc == FALSE ) && (results[nCounter] == '0')) ) + ) + { + Trace("MoveFileW: FAILED: test[%d][%d]: \"%s\" -> \"%s\"\n", + i, j, lpSource[i], lpDestination[j]); + bSuccess = FALSE; + } + + /* undo the last move */ + removeAll(); + createExisting(); + + nCounter++; + } + } + + removeAll(); + if (bSuccess == FALSE) + { + Fail("MoveFileW: Test Failed"); + } + + /* create the temp source file */ + hFile = CreateFileW(tempSource, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + + if( hFile == INVALID_HANDLE_VALUE ) + { + Fail("MoveFileW: CreateFile failed to " + "create the file correctly.\n"); + } + + bRc = CloseHandle(hFile); + if(!bRc) + { + Trace("MoveFileW: CloseHandle failed to close the " + "handle correctly. ERROR:%u\n",GetLastError()); + + /* delete the created file */ + bRc = DeleteFileW(tempSource); + if(!bRc) + { + Fail("MoveFileW: DeleteFileW failed to delete the" + "file correctly.\n"); + } + Fail(""); + } + + /* set the file attributes to be readonly */ + bRc = SetFileAttributesW(tempSource, FILE_ATTRIBUTE_READONLY); + if(!bRc) + { + Trace("MoveFileW: SetFileAttributes failed to set file " + "attributes correctly. GetLastError returned %u\n",GetLastError()); + /* delete the created file */ + bRc = DeleteFileW(tempSource); + if(!bRc) + { + Fail("MoveFileW: DeleteFileW failed to delete the" + "file correctly.\n"); + } + Fail(""); + } + + /* move the file to the new location */ + bRc = MoveFileW(tempSource, tempDest); + if(!bRc) + { + /* delete the created file */ + bRc = DeleteFileW(tempSource); + if(!bRc) + { + Fail("MoveFileW: DeleteFileW failed to delete the" + "file correctly.\n"); + } + + Fail("MoveFileW(%S, %S): GetFileAttributes " + "failed to get the file's attributes.\n", + tempSource, tempDest); + } + + /* check that the newly moved file has the same file attributes + as the original */ + result = GetFileAttributesW(tempDest); + if(result == 0) + { + /* delete the created file */ + bRc = DeleteFileW(tempDest); + if(!bRc) + { + Fail("MoveFileW: DeleteFileW failed to delete the" + "file correctly.\n"); + } + + Fail("MoveFileW: GetFileAttributes failed to get " + "the file's attributes.\n"); + } + + if((result & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY) + { + /* delete the newly moved file */ + bRc = DeleteFileW(tempDest); + if(!bRc) + { + Fail("MoveFileW: DeleteFileW failed to delete the" + "file correctly.\n"); + } + + Fail("MoveFileW: GetFileAttributes failed to get " + "the correct file attributes.\n"); + } + + /* set the file attributes back to normal, to be deleted */ + bRc = SetFileAttributesW(tempDest, FILE_ATTRIBUTE_NORMAL); + if(!bRc) + { + /* delete the newly moved file */ + bRc = DeleteFileW(tempDest); + if(!bRc) + { + Fail("MoveFileW: DeleteFileW failed to delete the" + "file correctly.\n"); + } + + Fail("MoveFileW: SetFileAttributes failed to set " + "file attributes correctly.\n"); + } + + /* delete the newly moved file */ + bRc = DeleteFileW(tempDest); + if(!bRc) + { + Fail("MoveFileW: DeleteFileW failed to delete the" + "file correctly.\n"); + } + + PAL_Terminate(); + + return PASS; +} diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/ReadFile/test1/CMakeLists.txt index 7b166e1..0aceb37 100644 --- a/src/pal/tests/palsuite/file_io/ReadFile/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/ReadFile/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - ReadFile.c + ReadFile.cpp ) add_executable(paltest_readfile_test1 diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test1/ReadFile.c b/src/pal/tests/palsuite/file_io/ReadFile/test1/ReadFile.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/ReadFile/test1/ReadFile.c rename to src/pal/tests/palsuite/file_io/ReadFile/test1/ReadFile.cpp diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/ReadFile/test2/CMakeLists.txt index fc4870e..f28ac11 100644 --- a/src/pal/tests/palsuite/file_io/ReadFile/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/ReadFile/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - ReadFile.c + ReadFile.cpp ) add_executable(paltest_readfile_test2 diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test2/ReadFile.c b/src/pal/tests/palsuite/file_io/ReadFile/test2/ReadFile.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/ReadFile/test2/ReadFile.c rename to src/pal/tests/palsuite/file_io/ReadFile/test2/ReadFile.cpp diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/ReadFile/test3/CMakeLists.txt index 7739774..26cb675 100644 --- a/src/pal/tests/palsuite/file_io/ReadFile/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/ReadFile/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - ReadFile.c + ReadFile.cpp ) add_executable(paltest_readfile_test3 diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test3/ReadFile.c b/src/pal/tests/palsuite/file_io/ReadFile/test3/ReadFile.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/ReadFile/test3/ReadFile.c rename to src/pal/tests/palsuite/file_io/ReadFile/test3/ReadFile.cpp diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/ReadFile/test4/CMakeLists.txt index 37f227a..bbf1277 100644 --- a/src/pal/tests/palsuite/file_io/ReadFile/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/ReadFile/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - readfile.c + readfile.cpp ) add_executable(paltest_readfile_test4 diff --git a/src/pal/tests/palsuite/file_io/ReadFile/test4/readfile.c b/src/pal/tests/palsuite/file_io/ReadFile/test4/readfile.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/ReadFile/test4/readfile.c rename to src/pal/tests/palsuite/file_io/ReadFile/test4/readfile.cpp diff --git a/src/pal/tests/palsuite/file_io/RemoveDirectoryA/test1/RemoveDirectoryA.cpp b/src/pal/tests/palsuite/file_io/RemoveDirectoryA/test1/RemoveDirectoryA.cpp index 167af58..4eb53d0 100644 --- a/src/pal/tests/palsuite/file_io/RemoveDirectoryA/test1/RemoveDirectoryA.cpp +++ b/src/pal/tests/palsuite/file_io/RemoveDirectoryA/test1/RemoveDirectoryA.cpp @@ -48,7 +48,7 @@ int __cdecl main(int argc, char *argv[]) * remove a directory that does not exist */ szTemp = (char *) malloc (sizeof("test_directory")); - sprintf(szTemp, "test_directory"); + sprintf_s(szTemp, sizeof("test_directory"), "test_directory"); bRc = RemoveDirectoryA(szTemp); if (bRc != FALSE) { @@ -69,7 +69,7 @@ int __cdecl main(int argc, char *argv[]) } char *szSymlinkName = (char *) malloc (sizeof("test_directory_symlink")); - sprintf(szSymlinkName, "test_directory_symlink"); + sprintf_s(szSymlinkName, sizeof("test_directory_symlink"), "test_directory_symlink"); if (symlink(szTemp, szSymlinkName) != 0) { Fail("Error:RemoveDirectoryA: Failed to create a symlink to the directory \"test_directory\".\n"); @@ -140,7 +140,7 @@ int __cdecl main(int argc, char *argv[]) * directories with dots */ memset(szDirName, 0, 252); - sprintf(szDirName, ".dotDirectory"); + sprintf_s(szDirName, _countof(szDirName), ".dotDirectory"); szTemp = (char *) malloc (sizeof(szDirName)); szTemp = strncpy(szTemp, szDirName, strlen(szDirName) + 1); @@ -170,7 +170,7 @@ int __cdecl main(int argc, char *argv[]) * Try calling RemoveDirectory with a file name */ memset(szDirName, 0, 252); - sprintf(szDirName, "removedirectoryw.c"); + sprintf_s(szDirName, _countof(szDirName), "removedirectoryw.c"); szTemp = (char *) malloc (sizeof(szDirName)); szTemp = strncpy(szTemp, szDirName, strlen(szDirName) + 1); @@ -201,7 +201,7 @@ int __cdecl main(int argc, char *argv[]) } /* Create non_empty_dir */ - sprintf( szDirName, "non_empty_dir"); + sprintf_s(szDirName, _countof(szDirName), "non_empty_dir"); szTemp = (char *) malloc (sizeof(szDirName)); szTemp = strncpy(szTemp, szDirName, strlen(szDirName) + 1); bRc = CreateDirectoryA(szTemp, NULL); @@ -229,7 +229,7 @@ int __cdecl main(int argc, char *argv[]) } /* Create sub_dir */ - sprintf (szDirName, "sub_dir"); + sprintf_s(szDirName, _countof(szDirName), "sub_dir"); szTemp2 = (char *) malloc (sizeof(szDirName)); szTemp2 = strncpy(szTemp2, szDirName, strlen(szDirName) + 1); bRc = CreateDirectoryA(szTemp2, NULL); diff --git a/src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/CMakeLists.txt index 45b51ce..6223bc6 100644 --- a/src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - RemoveDirectoryW.c + RemoveDirectoryW.cpp ) add_executable(paltest_removedirectoryw_test1 diff --git a/src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/RemoveDirectoryW.c b/src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/RemoveDirectoryW.c deleted file mode 100644 index ae1dd0f..0000000 --- a/src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/RemoveDirectoryW.c +++ /dev/null @@ -1,282 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: RemoveDirectoryW.c -** -** Purpose: Tests the PAL implementation of the RemoveDirectoryW function. -** -** -**===================================================================*/ - - -#include - - -int __cdecl main(int argc, char *argv[]) -{ - BOOL bRc = FALSE; - char szDirName[252]; - DWORD curDirLen; - WCHAR *szwTemp = NULL; - WCHAR *szwTemp2 = NULL; - WCHAR szwCurrentDir[MAX_PATH]; - WCHAR szwSubDir[MAX_PATH]; - - if (0 != PAL_Initialize(argc,argv)) - { - return FAIL; - } - - /* - * remove a NULL directory - */ - bRc = RemoveDirectoryW(NULL); - if (bRc != FALSE) - { - Fail("RemoveDirectoryW: Failed since it was able to remove a" - " NULL directory name\n"); - } - - /* - * remove a directory that does not exist - */ - szwTemp = convert("test_directory"); - bRc = RemoveDirectoryW(szwTemp); - if (bRc != FALSE) - { - free(szwTemp); - Fail("RemoveDirectoryW: Failed since it was able to remove" - " the non-existant directory \"test_directory\"\n"); - } - - /* - * remove a directory that exists - */ - bRc = CreateDirectoryW(szwTemp, NULL); - if (bRc != TRUE) - { - free(szwTemp); - Fail("RemoveDirectoryW: Failed to create the directory " - "\"test_directory\" when it exists already.\n"); - } - bRc = RemoveDirectoryW(szwTemp); - if (bRc == FALSE) - { - free(szwTemp); - Fail("RemoveDirectoryW: Failed to remove the directory " - "\"test_directory\" (error code %d)\n", - GetLastError()); - } - /* Make sure the directory was removed */ - if( -1 != GetFileAttributesW(szwTemp) ) - { - free(szwTemp); - Fail("RemoveDirectoryW: Able to get the attributes of " - "the removed directory\n"); - } - free(szwTemp); - - /* - * remove long directory names (245 characters) - */ - curDirLen = GetCurrentDirectoryA(0, NULL) + 1; - memset(szDirName, 0, 252); - memset(szDirName, 'a', 245 - curDirLen); - szwTemp = convert(szDirName); - bRc = CreateDirectoryW(szwTemp, NULL); - if (bRc == FALSE) - { - free(szwTemp); - Fail("RemoveDirectoryW: Failed to create a directory name " - "245 chars long\n"); - } - bRc = RemoveDirectoryW(szwTemp); - if (bRc == FALSE) - { - free(szwTemp); - Fail("RemoveDirectoryW: Failed to remove a 245 char " - "long directory\n"); - } - - /* Make sure the directory was removed */ - if( -1 != GetFileAttributesW(szwTemp) ) - { - free(szwTemp); - Fail("RemoveDirectoryW: Able to get the attributes of " - "the removed directory\n"); - } - free(szwTemp); - - /* - * directories with dots - */ - memset(szDirName, 0, 252); - sprintf(szDirName, ".dotDirectory"); - szwTemp = convert(szDirName); - bRc = CreateDirectoryW(szwTemp, NULL); - if (bRc == FALSE) - { - free(szwTemp); - Fail("RemoveDirectoryW: Failed to create \"%s\"\n", szDirName); - } - bRc = RemoveDirectoryW(szwTemp); - if (bRc == FALSE) - { - free(szwTemp); - Fail("RemoveDirectoryW: Failed to remove \"%s\"\n", szDirName); - } - - /* Make sure the directory was removed */ - if( -1 != GetFileAttributesW(szwTemp) ) - { - free(szwTemp); - Fail("RemoveDirectoryW: Able to get the attributes of " - "the removed directory\n"); - } - free(szwTemp); - - /* - * Try calling RemoveDirectory with a file name - */ - memset(szDirName, 0, 252); - sprintf(szDirName, "removedirectoryw.c"); - szwTemp = convert(szDirName); - - bRc = RemoveDirectoryW(szwTemp); - free(szwTemp); - if (bRc != FALSE) - { - Fail("RemoveDirectoryW: should have failed when " - "called with a valid file name" ); - } - - /* - * remove a non empty directory - * - * To test that, we'll first create non_empty_dir, we'll - * set the current dir to non_empty_dir in which we'll - * create sub_dir. We'll go back to the root of non_empty_dir - * and we'll try to delete it (it shouldn't work). - * After that we'll cleanup sub_dir and non_empty_dir - */ - - /* Get the current directory so it is easy to get back - to it later */ - if( 0 == GetCurrentDirectoryW(MAX_PATH, szwCurrentDir) ) - { - Fail("RemoveDirectoryW: Failed to get current directory " - "with GetCurrentDirectoryW.\n"); - } - - /* Create non_empty_dir */ - szwTemp = convert("non_empty_dir"); - bRc = CreateDirectoryW(szwTemp, NULL); - if (bRc != TRUE) - { - free(szwTemp); - Fail("RemoveDirectoryW: Failed to create the directory " - "\"non_empty_dir\" when it exists already.\n"); - } - - if( 0 == SetCurrentDirectoryW(szwTemp) ) - { - free(szwTemp); - Fail("RemoveDirectoryW: Failed to set current directory to " - "\"non_empty_dir\" with SetCurrentDirectoryW.\n"); - } - - /* Get the directory full path so it is easy to get back - to it later */ - if( 0 == GetCurrentDirectoryW(MAX_PATH, szwSubDir) ) - { - free(szwTemp); - Fail("RemoveDirectoryW: Failed to get current directory " - "with GetCurrentDirectoryW.\n"); - } - - /* Create sub_dir */ - szwTemp2 = convert("sub_dir"); - bRc = CreateDirectoryW(szwTemp2, NULL); - if (bRc != TRUE) - { - free(szwTemp); - free(szwTemp2); - Fail("RemoveDirectoryW: Failed to create the directory " - "\"sub_dir\" when it exists already.\n"); - } - - /* Set the current dir to the parent of non_empty_dir/sub_dir */ - if( 0 == SetCurrentDirectoryW(szwCurrentDir) ) - { - free(szwTemp); - free(szwTemp2); - Fail("RemoveDirectoryW: Failed to set current directory to " - "\"non_empty_dir\" with SetCurrentDirectoryW.\n"); - } - - /* Try to remove non_empty_dir (shouldn't work) */ - bRc = RemoveDirectoryW(szwTemp); - if (bRc == TRUE) - { - free(szwTemp); - free(szwTemp2); - Fail("RemoveDirectoryW: shouldn't have been able to remove " - "the non empty directory \"non_empty_dir\"\n"); - } - - /* Go back to non_empty_dir and remove sub_dir */ - if( 0 == SetCurrentDirectoryW(szwSubDir) ) - { - free(szwTemp); - free(szwTemp2); - Fail("RemoveDirectoryW: Failed to set current directory to " - "\"non_empty_dir\" with SetCurrentDirectoryW.\n"); - } - - bRc = RemoveDirectoryW(szwTemp2); - if (bRc == FALSE) - { - free(szwTemp); - free(szwTemp2); - Fail("RemoveDirectoryW: unable to remove " - "directory \"sub_dir\"(error code %d)\n", - GetLastError()); - } - /* Make sure the directory was removed */ - if( -1 != GetFileAttributesW(szwTemp2) ) - { - Fail("RemoveDirectoryW: Able to get the attributes of " - "the removed directory\n"); - } - free(szwTemp2); - - /* Go back to parent of non_empty_dir and remove non_empty_dir */ - if( 0 == SetCurrentDirectoryW(szwCurrentDir) ) - { - free(szwTemp); - Fail("RemoveDirectoryW: Failed to set current directory to " - "\"..\non_empty_dir\" with SetCurrentDirectoryW.\n"); - } - bRc = RemoveDirectoryW(szwTemp); - if (bRc == FALSE) - { - free(szwTemp); - Fail("RemoveDirectoryW: unable to remove " - "the directory \"non_empty_dir\"(error code %d)\n", - GetLastError()); - } - /* Make sure the directory was removed */ - if( -1 != GetFileAttributesW(szwTemp) ) - { - Fail("RemoveDirectoryW: Able to get the attributes of " - "the removed directory\n"); - } - free(szwTemp); - - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/RemoveDirectoryW.cpp b/src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/RemoveDirectoryW.cpp new file mode 100644 index 0000000..ec90528 --- /dev/null +++ b/src/pal/tests/palsuite/file_io/RemoveDirectoryW/test1/RemoveDirectoryW.cpp @@ -0,0 +1,282 @@ +// 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. + +/*===================================================================== +** +** Source: RemoveDirectoryW.c +** +** Purpose: Tests the PAL implementation of the RemoveDirectoryW function. +** +** +**===================================================================*/ + + +#include + + +int __cdecl main(int argc, char *argv[]) +{ + BOOL bRc = FALSE; + char szDirName[252]; + DWORD curDirLen; + WCHAR *szwTemp = NULL; + WCHAR *szwTemp2 = NULL; + WCHAR szwCurrentDir[MAX_PATH]; + WCHAR szwSubDir[MAX_PATH]; + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* + * remove a NULL directory + */ + bRc = RemoveDirectoryW(NULL); + if (bRc != FALSE) + { + Fail("RemoveDirectoryW: Failed since it was able to remove a" + " NULL directory name\n"); + } + + /* + * remove a directory that does not exist + */ + szwTemp = convert("test_directory"); + bRc = RemoveDirectoryW(szwTemp); + if (bRc != FALSE) + { + free(szwTemp); + Fail("RemoveDirectoryW: Failed since it was able to remove" + " the non-existant directory \"test_directory\"\n"); + } + + /* + * remove a directory that exists + */ + bRc = CreateDirectoryW(szwTemp, NULL); + if (bRc != TRUE) + { + free(szwTemp); + Fail("RemoveDirectoryW: Failed to create the directory " + "\"test_directory\" when it exists already.\n"); + } + bRc = RemoveDirectoryW(szwTemp); + if (bRc == FALSE) + { + free(szwTemp); + Fail("RemoveDirectoryW: Failed to remove the directory " + "\"test_directory\" (error code %d)\n", + GetLastError()); + } + /* Make sure the directory was removed */ + if( -1 != GetFileAttributesW(szwTemp) ) + { + free(szwTemp); + Fail("RemoveDirectoryW: Able to get the attributes of " + "the removed directory\n"); + } + free(szwTemp); + + /* + * remove long directory names (245 characters) + */ + curDirLen = GetCurrentDirectoryA(0, NULL) + 1; + memset(szDirName, 0, 252); + memset(szDirName, 'a', 245 - curDirLen); + szwTemp = convert(szDirName); + bRc = CreateDirectoryW(szwTemp, NULL); + if (bRc == FALSE) + { + free(szwTemp); + Fail("RemoveDirectoryW: Failed to create a directory name " + "245 chars long\n"); + } + bRc = RemoveDirectoryW(szwTemp); + if (bRc == FALSE) + { + free(szwTemp); + Fail("RemoveDirectoryW: Failed to remove a 245 char " + "long directory\n"); + } + + /* Make sure the directory was removed */ + if( -1 != GetFileAttributesW(szwTemp) ) + { + free(szwTemp); + Fail("RemoveDirectoryW: Able to get the attributes of " + "the removed directory\n"); + } + free(szwTemp); + + /* + * directories with dots + */ + memset(szDirName, 0, 252); + sprintf_s(szDirName, _countof(szDirName), ".dotDirectory"); + szwTemp = convert(szDirName); + bRc = CreateDirectoryW(szwTemp, NULL); + if (bRc == FALSE) + { + free(szwTemp); + Fail("RemoveDirectoryW: Failed to create \"%s\"\n", szDirName); + } + bRc = RemoveDirectoryW(szwTemp); + if (bRc == FALSE) + { + free(szwTemp); + Fail("RemoveDirectoryW: Failed to remove \"%s\"\n", szDirName); + } + + /* Make sure the directory was removed */ + if( -1 != GetFileAttributesW(szwTemp) ) + { + free(szwTemp); + Fail("RemoveDirectoryW: Able to get the attributes of " + "the removed directory\n"); + } + free(szwTemp); + + /* + * Try calling RemoveDirectory with a file name + */ + memset(szDirName, 0, 252); + sprintf_s(szDirName, _countof(szDirName), "removedirectoryw.c"); + szwTemp = convert(szDirName); + + bRc = RemoveDirectoryW(szwTemp); + free(szwTemp); + if (bRc != FALSE) + { + Fail("RemoveDirectoryW: should have failed when " + "called with a valid file name" ); + } + + /* + * remove a non empty directory + * + * To test that, we'll first create non_empty_dir, we'll + * set the current dir to non_empty_dir in which we'll + * create sub_dir. We'll go back to the root of non_empty_dir + * and we'll try to delete it (it shouldn't work). + * After that we'll cleanup sub_dir and non_empty_dir + */ + + /* Get the current directory so it is easy to get back + to it later */ + if( 0 == GetCurrentDirectoryW(MAX_PATH, szwCurrentDir) ) + { + Fail("RemoveDirectoryW: Failed to get current directory " + "with GetCurrentDirectoryW.\n"); + } + + /* Create non_empty_dir */ + szwTemp = convert("non_empty_dir"); + bRc = CreateDirectoryW(szwTemp, NULL); + if (bRc != TRUE) + { + free(szwTemp); + Fail("RemoveDirectoryW: Failed to create the directory " + "\"non_empty_dir\" when it exists already.\n"); + } + + if( 0 == SetCurrentDirectoryW(szwTemp) ) + { + free(szwTemp); + Fail("RemoveDirectoryW: Failed to set current directory to " + "\"non_empty_dir\" with SetCurrentDirectoryW.\n"); + } + + /* Get the directory full path so it is easy to get back + to it later */ + if( 0 == GetCurrentDirectoryW(MAX_PATH, szwSubDir) ) + { + free(szwTemp); + Fail("RemoveDirectoryW: Failed to get current directory " + "with GetCurrentDirectoryW.\n"); + } + + /* Create sub_dir */ + szwTemp2 = convert("sub_dir"); + bRc = CreateDirectoryW(szwTemp2, NULL); + if (bRc != TRUE) + { + free(szwTemp); + free(szwTemp2); + Fail("RemoveDirectoryW: Failed to create the directory " + "\"sub_dir\" when it exists already.\n"); + } + + /* Set the current dir to the parent of non_empty_dir/sub_dir */ + if( 0 == SetCurrentDirectoryW(szwCurrentDir) ) + { + free(szwTemp); + free(szwTemp2); + Fail("RemoveDirectoryW: Failed to set current directory to " + "\"non_empty_dir\" with SetCurrentDirectoryW.\n"); + } + + /* Try to remove non_empty_dir (shouldn't work) */ + bRc = RemoveDirectoryW(szwTemp); + if (bRc == TRUE) + { + free(szwTemp); + free(szwTemp2); + Fail("RemoveDirectoryW: shouldn't have been able to remove " + "the non empty directory \"non_empty_dir\"\n"); + } + + /* Go back to non_empty_dir and remove sub_dir */ + if( 0 == SetCurrentDirectoryW(szwSubDir) ) + { + free(szwTemp); + free(szwTemp2); + Fail("RemoveDirectoryW: Failed to set current directory to " + "\"non_empty_dir\" with SetCurrentDirectoryW.\n"); + } + + bRc = RemoveDirectoryW(szwTemp2); + if (bRc == FALSE) + { + free(szwTemp); + free(szwTemp2); + Fail("RemoveDirectoryW: unable to remove " + "directory \"sub_dir\"(error code %d)\n", + GetLastError()); + } + /* Make sure the directory was removed */ + if( -1 != GetFileAttributesW(szwTemp2) ) + { + Fail("RemoveDirectoryW: Able to get the attributes of " + "the removed directory\n"); + } + free(szwTemp2); + + /* Go back to parent of non_empty_dir and remove non_empty_dir */ + if( 0 == SetCurrentDirectoryW(szwCurrentDir) ) + { + free(szwTemp); + Fail("RemoveDirectoryW: Failed to set current directory to " + "\"..\non_empty_dir\" with SetCurrentDirectoryW.\n"); + } + bRc = RemoveDirectoryW(szwTemp); + if (bRc == FALSE) + { + free(szwTemp); + Fail("RemoveDirectoryW: unable to remove " + "the directory \"non_empty_dir\"(error code %d)\n", + GetLastError()); + } + /* Make sure the directory was removed */ + if( -1 != GetFileAttributesW(szwTemp) ) + { + Fail("RemoveDirectoryW: Able to get the attributes of " + "the removed directory\n"); + } + free(szwTemp); + + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/file_io/SearchPathA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SearchPathA/test1/CMakeLists.txt index d1ac975..c020a86 100644 --- a/src/pal/tests/palsuite/file_io/SearchPathA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SearchPathA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SearchPathA.c + SearchPathA.cpp ) add_executable(paltest_searchpatha_test1 diff --git a/src/pal/tests/palsuite/file_io/SearchPathA/test1/SearchPathA.c b/src/pal/tests/palsuite/file_io/SearchPathA/test1/SearchPathA.c deleted file mode 100644 index ab9eecd..0000000 --- a/src/pal/tests/palsuite/file_io/SearchPathA/test1/SearchPathA.c +++ /dev/null @@ -1,144 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: SearchPathA.c -** -** Purpose: Tests the PAL implementation of the SearchFileA function. -** -** -** TODO: Write a test where complete path is passed (say c:\?) -**===================================================================*/ -//SearchPath -// -//The SearchPath function searches for the specified file in the specified path. -// - - -#include -char* szDir = "."; - -char* szNoFileName = "333asdf"; -char* szNoFileNameExt = ".x77t"; - -char* szFileNameExists = "searchfile"; -char* szFileNameExtExists = ".txt"; - -char* szFileNameExistsWithExt = "searchfile.txt"; -char fileloc[_MAX_PATH]; - -void removeFileHelper(LPSTR pfile, int location) -{ - FILE *fp; - fp = fopen( pfile, "r"); - - if (fp != NULL) - { - if(fclose(fp)) - { - Fail("ERROR: Failed to close the file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location); - } - - if(!DeleteFileA(pfile)) - { - Fail("ERROR: Failed to delete file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location); - } - } - -} - - -void RemoveAll() -{ - removeFileHelper(fileloc, 1); -} - -int __cdecl main(int argc, char *argv[]) { - - char* lpPath = NULL; - char* lpFileName = NULL; - char* lpExtension = NULL; - DWORD nBufferLength = 0; - char lpBuffer[_MAX_PATH]; - char** lpFilePart = NULL; - DWORD error = 0; - DWORD result = 0; - - HANDLE hsearchfile; - char fname[_MAX_FNAME]; - char ext[_MAX_EXT]; - char fullPath[_MAX_DIR]; - char drive[_MAX_DRIVE]; - char dir[_MAX_DIR]; - - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - - /* Initalize the buffer. - */ - memset(fullPath, 0, _MAX_DIR); - - /* Get the full path to the library (DLL). - */ - - if ( NULL != _fullpath( fullPath, argv[0], _MAX_DIR )) { - _splitpath(fullPath,drive,dir,fname,ext); - _makepath(fullPath,drive,dir,"",""); - } else { - Fail("ERROR: conversion from relative path \" %s \" to absolute path failed. _fullpath returned NULL\n",argv[0]); - } - - memset(fileloc, 0, _MAX_PATH); - sprintf(fileloc, "%s%s", fullPath, szFileNameExistsWithExt); - - RemoveAll(); - - hsearchfile = CreateFileA(fileloc, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, 0); - - if (hsearchfile == INVALID_HANDLE_VALUE) - { - Trace("ERROR[%ul]: couldn't create %s\n", GetLastError(), fileloc); - return FAIL; - } - - CloseHandle(hsearchfile); - - // - // find a file that doesn't exist - // - ZeroMemory( lpBuffer, sizeof(lpBuffer)); - lpPath = fullPath; - lpFileName = szNoFileName; - lpExtension = NULL; - - if( SearchPathA( lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, lpFilePart) != 0 ){ - error = GetLastError(); - Fail ("SearchPathA: ERROR1 -> Found invalid file[%s][%s][%s][%d]\n", lpPath, szNoFileName, szNoFileNameExt, error); - } - - // - // find a file that exists, when path is mentioned explicitly - // - ZeroMemory( lpBuffer, sizeof(lpBuffer)); - lpPath = fullPath; - lpFileName = szFileNameExistsWithExt; - lpExtension = NULL; - - result = SearchPathA( lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, lpFilePart); - - if( result == 0 ){ - error = GetLastError(); - Fail ("SearchPathA: ERROR2 -> Did not Find valid file[%s][%s][%d]\n", lpPath, szFileNameExistsWithExt, error); - } - - RemoveAll(); - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/file_io/SearchPathA/test1/SearchPathA.cpp b/src/pal/tests/palsuite/file_io/SearchPathA/test1/SearchPathA.cpp new file mode 100644 index 0000000..57afdef --- /dev/null +++ b/src/pal/tests/palsuite/file_io/SearchPathA/test1/SearchPathA.cpp @@ -0,0 +1,139 @@ +// 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. + +/*===================================================================== +** +** Source: SearchPathA.c +** +** Purpose: Tests the PAL implementation of the SearchFileA function. +** +** +** TODO: Write a test where complete path is passed (say c:\?) +**===================================================================*/ +//SearchPath +// +//The SearchPath function searches for the specified file in the specified path. +// + + +#include +char* szDir = "."; + +char* szNoFileName = "333asdf"; +char* szNoFileNameExt = ".x77t"; + +char* szFileNameExists = "searchfile"; +char* szFileNameExtExists = ".txt"; + +char* szFileNameExistsWithExt = "searchfile.txt"; +char fileloc[_MAX_PATH]; + +void removeFileHelper(LPSTR pfile, int location) +{ + FILE *fp; + fp = fopen( pfile, "r"); + + if (fp != NULL) + { + if(fclose(fp)) + { + Fail("ERROR: Failed to close the file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location); + } + + if(!DeleteFileA(pfile)) + { + Fail("ERROR: Failed to delete file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location); + } + } + +} + + +void RemoveAll() +{ + removeFileHelper(fileloc, 1); +} + +int __cdecl main(int argc, char *argv[]) { + + char* lpPath = NULL; + char* lpFileName = NULL; + char* lpExtension = NULL; + DWORD nBufferLength = 0; + char lpBuffer[_MAX_PATH]; + char** lpFilePart = NULL; + DWORD error = 0; + DWORD result = 0; + + HANDLE hsearchfile; + char fname[_MAX_FNAME]; + char ext[_MAX_EXT]; + char fullPath[_MAX_DIR]; + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + + /* Initalize the buffer. + */ + memset(fullPath, 0, _MAX_DIR); + + if (GetTempPathA(_MAX_DIR, fullPath) == 0) + { + Fail("ERROR: GetTempPathA failed to get a path\n"); + } + + memset(fileloc, 0, _MAX_PATH); + sprintf_s(fileloc, _countof(fileloc), "%s%s", fullPath, szFileNameExistsWithExt); + + RemoveAll(); + + hsearchfile = CreateFileA(fileloc, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + + if (hsearchfile == INVALID_HANDLE_VALUE) + { + Trace("ERROR[%ul]: couldn't create %s\n", GetLastError(), fileloc); + return FAIL; + } + + CloseHandle(hsearchfile); + + // + // find a file that doesn't exist + // + ZeroMemory( lpBuffer, sizeof(lpBuffer)); + lpPath = fullPath; + lpFileName = szNoFileName; + lpExtension = NULL; + + if( SearchPathA( lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, lpFilePart) != 0 ){ + error = GetLastError(); + Fail ("SearchPathA: ERROR1 -> Found invalid file[%s][%s][%s][%d]\n", lpPath, szNoFileName, szNoFileNameExt, error); + } + + // + // find a file that exists, when path is mentioned explicitly + // + ZeroMemory( lpBuffer, sizeof(lpBuffer)); + lpPath = fullPath; + lpFileName = szFileNameExistsWithExt; + lpExtension = NULL; + + result = SearchPathA( lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, lpFilePart); + + if( result == 0 ){ + error = GetLastError(); + Fail ("SearchPathA: ERROR2 -> Did not Find valid file[%s][%s][%d]\n", lpPath, szFileNameExistsWithExt, error); + } + + RemoveAll(); + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/file_io/SearchPathW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SearchPathW/test1/CMakeLists.txt index d0c6252..a77d875 100644 --- a/src/pal/tests/palsuite/file_io/SearchPathW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SearchPathW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SearchPathW.c + SearchPathW.cpp ) add_executable(paltest_searchpathw_test1 diff --git a/src/pal/tests/palsuite/file_io/SearchPathW/test1/SearchPathW.c b/src/pal/tests/palsuite/file_io/SearchPathW/test1/SearchPathW.c deleted file mode 100644 index 2bc7694..0000000 --- a/src/pal/tests/palsuite/file_io/SearchPathW/test1/SearchPathW.c +++ /dev/null @@ -1,198 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: SearchPathW.c -** -** Purpose: Tests the PAL implementation of the SearchFileW function. -** -** -** TODO: Write a test where complete path is passed (say c:\?) -**===================================================================*/ -//SearchPath -// -//The SearchPath function searches for the specified file in the specified path. -// -// -//DWORD SearchPath( -// LPCTSTR lpPath, -// LPCTSTR lpFileName, -// LPCTSTR lpExtension, -// DWORD nBufferLength, -// LPTSTR lpBuffer, -// LPTSTR* lpFilePart -//); -// -//Parameters -//lpPath -//[in] Pointer to a null-terminated string that specifies the path to be searched for the file. If this parameter is NULL, the function searches for a matching file in the following directories in the following sequence: -//The directory from which the application loaded. -//The current directory. -//The system directory. Use the GetSystemDirectory function to get the path of this directory. -//The 16-bit system directory. There is no function that retrieves the path of this directory, but it is searched. -//The Windows directory. Use the GetWindowsDirectory function to get the path of this directory. -//The directories that are listed in the PATH environment variable. - -//lpFileName -//[in] Pointer to a null-terminated string that specifies the name of the file to search for. - -//lpExtension -//[in] Pointer to a null-terminated string that specifies an extension to be added to the file name when searching for the file. The first character of the file name extension must be a period (.). The extension is added only if the specified file name does not end with an extension. -//If a file name extension is not required or if the file name contains an extension, this parameter can be NULL. -// -//nBufferLength -//[in] Size of the buffer that receives the valid path and file name, in TCHARs. - -//lpBuffer -//[out] Pointer to the buffer that receives the path and file name of the file found. - -//lpFilePart -//[out] Pointer to the variable that receives the address (within lpBuffer) of the last component of the valid path and file name, which is the address of the character immediately following the final backslash (\) in the path. - -//Return Values -//If the function succeeds, the value returned is the length, in TCHARs, of the string copied to the buffer, not including the terminating null character. If the return value is greater than nBufferLength, the value returned is the size of the buffer required to hold the path. -// -//If the function fails, the return value is zero. To get extended error information, call GetLastError. - - -#include -const char* szDir = "."; - -const char* szNoFileName = "333asdf"; -const char* szNoFileNameExt = ".x77t"; - -const char* szFileNameExists = "searchpathw"; -const char* szFileNameExtExists = ".c"; - -const char* szFileNameExistsWithExt = "searchpathw.c"; - -char fileloc[_MAX_PATH]; - -void removeFileHelper(LPSTR pfile, int location) -{ - FILE *fp; - fp = fopen( pfile, "r"); - - if (fp != NULL) - { - if(fclose(fp)) - { - Fail("ERROR: Failed to close the file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location); - } - - if(!DeleteFileA(pfile)) - { - Fail("ERROR: Failed to delete file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location); - } - else - { - // Trace("Success: deleted file [%S], Error Code [%d], location [%d]\n", wfile, GetLastError(), location); - } - } - -} - -void RemoveAll() -{ - removeFileHelper(fileloc, 1); -} - -int __cdecl main(int argc, char *argv[]) { - - WCHAR* lpPath = NULL; - WCHAR* lpFileName = NULL; - WCHAR* lpExtension = NULL; - DWORD nBufferLength = 0; - WCHAR lpBuffer[_MAX_PATH]; - WCHAR** lpFilePart = NULL; - DWORD error = 0; - DWORD result = 0; - - HANDLE hsearchfile; - char fname[_MAX_FNAME]; - char ext[_MAX_EXT]; - char fullPath[_MAX_DIR]; - char drive[_MAX_DRIVE]; - char dir[_MAX_DIR]; - - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* Initalize the buffer. - */ - memset(fullPath, 0, _MAX_DIR); - - /* Get the full path to the library (DLL). - */ - - if ( NULL != _fullpath( fullPath, argv[0], _MAX_DIR )) { - _splitpath(fullPath,drive,dir,fname,ext); - _makepath(fullPath,drive,dir,"",""); - } else { - Fail("ERROR: conversion from relative path \" %s \" to absolute path failed. _fullpath returned NULL\n",argv[0]); - } - - memset(fileloc, 0, _MAX_PATH); - sprintf(fileloc, "%s%s", fullPath, szFileNameExistsWithExt); - - RemoveAll(); - - hsearchfile = CreateFileA(fileloc, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, 0); - - if (hsearchfile == NULL) - { - Trace("ERROR[%ul]: couldn't create %s\n", GetLastError(), fileloc); - return FAIL; - } - - CloseHandle(hsearchfile); - - // - // find a file that doesn't exist - // - ZeroMemory( lpBuffer, sizeof(lpBuffer)); - lpPath = convert((LPSTR)fullPath); - lpFileName = convert((LPSTR)szNoFileName); - lpExtension = NULL; - - if( SearchPathW( lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, lpFilePart) != 0 ){ - error = GetLastError(); - free(lpPath); - free(lpFileName); - Fail ("SearchPathW: ERROR1 -> Found invalid file[%s][%s][%s][%d]\n", lpPath, szNoFileName, szNoFileNameExt, error); - } - - free(lpPath); - free(lpFileName); - - // - // find a file that exists, when path is mentioned explicitly - // - ZeroMemory( lpBuffer, sizeof(lpBuffer)); - lpPath = convert((LPSTR)fullPath); - lpFileName = convert((LPSTR)szFileNameExistsWithExt); - lpExtension = NULL; - - result = SearchPathW( lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, lpFilePart); - - if( result == 0 ){ - error = GetLastError(); - free(lpPath); - free(lpFileName); - Fail ("SearchPathA: ERROR2 -> Did not Find valid file[%s][%s][%d]\n", lpPath, szFileNameExistsWithExt, error); - } - - free(lpPath); - free(lpFileName); - - RemoveAll(); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/file_io/SearchPathW/test1/SearchPathW.cpp b/src/pal/tests/palsuite/file_io/SearchPathW/test1/SearchPathW.cpp new file mode 100644 index 0000000..6880a86 --- /dev/null +++ b/src/pal/tests/palsuite/file_io/SearchPathW/test1/SearchPathW.cpp @@ -0,0 +1,193 @@ +// 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. + +/*===================================================================== +** +** Source: SearchPathW.c +** +** Purpose: Tests the PAL implementation of the SearchFileW function. +** +** +** TODO: Write a test where complete path is passed (say c:\?) +**===================================================================*/ +//SearchPath +// +//The SearchPath function searches for the specified file in the specified path. +// +// +//DWORD SearchPath( +// LPCTSTR lpPath, +// LPCTSTR lpFileName, +// LPCTSTR lpExtension, +// DWORD nBufferLength, +// LPTSTR lpBuffer, +// LPTSTR* lpFilePart +//); +// +//Parameters +//lpPath +//[in] Pointer to a null-terminated string that specifies the path to be searched for the file. If this parameter is NULL, the function searches for a matching file in the following directories in the following sequence: +//The directory from which the application loaded. +//The current directory. +//The system directory. Use the GetSystemDirectory function to get the path of this directory. +//The 16-bit system directory. There is no function that retrieves the path of this directory, but it is searched. +//The Windows directory. Use the GetWindowsDirectory function to get the path of this directory. +//The directories that are listed in the PATH environment variable. + +//lpFileName +//[in] Pointer to a null-terminated string that specifies the name of the file to search for. + +//lpExtension +//[in] Pointer to a null-terminated string that specifies an extension to be added to the file name when searching for the file. The first character of the file name extension must be a period (.). The extension is added only if the specified file name does not end with an extension. +//If a file name extension is not required or if the file name contains an extension, this parameter can be NULL. +// +//nBufferLength +//[in] Size of the buffer that receives the valid path and file name, in TCHARs. + +//lpBuffer +//[out] Pointer to the buffer that receives the path and file name of the file found. + +//lpFilePart +//[out] Pointer to the variable that receives the address (within lpBuffer) of the last component of the valid path and file name, which is the address of the character immediately following the final backslash (\) in the path. + +//Return Values +//If the function succeeds, the value returned is the length, in TCHARs, of the string copied to the buffer, not including the terminating null character. If the return value is greater than nBufferLength, the value returned is the size of the buffer required to hold the path. +// +//If the function fails, the return value is zero. To get extended error information, call GetLastError. + + +#include +const char* szDir = "."; + +const char* szNoFileName = "333asdf"; +const char* szNoFileNameExt = ".x77t"; + +const char* szFileNameExists = "searchpathw"; +const char* szFileNameExtExists = ".c"; + +const char* szFileNameExistsWithExt = "searchpathw.c"; + +char fileloc[_MAX_PATH]; + +void removeFileHelper(LPSTR pfile, int location) +{ + FILE *fp; + fp = fopen( pfile, "r"); + + if (fp != NULL) + { + if(fclose(fp)) + { + Fail("ERROR: Failed to close the file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location); + } + + if(!DeleteFileA(pfile)) + { + Fail("ERROR: Failed to delete file [%s], Error Code [%d], location [%d]\n", pfile, GetLastError(), location); + } + else + { + // Trace("Success: deleted file [%S], Error Code [%d], location [%d]\n", wfile, GetLastError(), location); + } + } + +} + +void RemoveAll() +{ + removeFileHelper(fileloc, 1); +} + +int __cdecl main(int argc, char *argv[]) { + + WCHAR* lpPath = NULL; + WCHAR* lpFileName = NULL; + WCHAR* lpExtension = NULL; + DWORD nBufferLength = 0; + WCHAR lpBuffer[_MAX_PATH]; + WCHAR** lpFilePart = NULL; + DWORD error = 0; + DWORD result = 0; + + HANDLE hsearchfile; + char fname[_MAX_FNAME]; + char ext[_MAX_EXT]; + char fullPath[_MAX_DIR]; + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Initalize the buffer. + */ + memset(fullPath, 0, _MAX_DIR); + + if (GetTempPathA(_MAX_DIR, fullPath) == 0) + { + Fail("ERROR: GetTempPathA failed to get a path\n"); + } + + memset(fileloc, 0, _MAX_PATH); + sprintf_s(fileloc, _countof(fileloc), "%s%s", fullPath, szFileNameExistsWithExt); + + RemoveAll(); + + hsearchfile = CreateFileA(fileloc, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + + if (hsearchfile == NULL) + { + Trace("ERROR[%ul]: couldn't create %s\n", GetLastError(), fileloc); + return FAIL; + } + + CloseHandle(hsearchfile); + + // + // find a file that doesn't exist + // + ZeroMemory( lpBuffer, sizeof(lpBuffer)); + lpPath = convert((LPSTR)fullPath); + lpFileName = convert((LPSTR)szNoFileName); + lpExtension = NULL; + + if( SearchPathW( lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, lpFilePart) != 0 ){ + error = GetLastError(); + free(lpPath); + free(lpFileName); + Fail ("SearchPathW: ERROR1 -> Found invalid file[%s][%s][%s][%d]\n", lpPath, szNoFileName, szNoFileNameExt, error); + } + + free(lpPath); + free(lpFileName); + + // + // find a file that exists, when path is mentioned explicitly + // + ZeroMemory( lpBuffer, sizeof(lpBuffer)); + lpPath = convert((LPSTR)fullPath); + lpFileName = convert((LPSTR)szFileNameExistsWithExt); + lpExtension = NULL; + + result = SearchPathW( lpPath, lpFileName, lpExtension, nBufferLength, lpBuffer, lpFilePart); + + if( result == 0 ){ + error = GetLastError(); + free(lpPath); + free(lpFileName); + Fail ("SearchPathA: ERROR2 -> Did not Find valid file[%s][%s][%d]\n", lpPath, szFileNameExistsWithExt, error); + } + + free(lpPath); + free(lpFileName); + + RemoveAll(); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/CMakeLists.txt index 7376b22..5d0da64 100644 --- a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetCurrentDirectoryA.c + SetCurrentDirectoryA.cpp ) add_executable(paltest_setcurrentdirectorya_test1 diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/SetCurrentDirectoryA.c b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/SetCurrentDirectoryA.c deleted file mode 100644 index c07a624..0000000 --- a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/SetCurrentDirectoryA.c +++ /dev/null @@ -1,215 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: SetCurrentDirectoryA.c (test 1) -** -** Purpose: Tests the PAL implementation of the SetCurrentDirectoryA function. -** -** -**===================================================================*/ - -#include - - - -/* In order to avoid the "chicken and egg" scenario, this is another - method of getting the current directory. GetFullPathNameA is called with - a dummy file name and then the file name is stripped off leaving the - current working directory -*/ - -BOOL GetCurrentDir(char* szCurrentDir) -{ - const char* szFileName = "blah"; - DWORD dwRc = 0; - char szReturnedPath[_MAX_DIR+1]; - LPSTR pPathPtr; - size_t nCount = 0; - - /* use GetFullPathNameA to to get the current path by stripping - the file name off the end */ - memset(szReturnedPath, 0, (_MAX_DIR+1)); - dwRc = GetFullPathNameA(szFileName, - _MAX_DIR, - szReturnedPath, - &pPathPtr); - - if (dwRc == 0) - { - /* GetFullPathNameA failed */ - Trace("SetCurrentDirectoryA: ERROR -> GetFullPathNameA failed " - "with error code: %ld.\n", GetLastError()); - return(FALSE); - } - - /* now strip the file name from the full path to get the current path */ - nCount = strlen(szReturnedPath) - strlen(szFileName); - memset(szCurrentDir, 0, (_MAX_DIR+1)); - strncpy(szCurrentDir, szReturnedPath, nCount); - - return(TRUE); -} - - - -int __cdecl main(int argc, char *argv[]) -{ - const char* szDirName = "testing"; - /* directory name longer than MAX_PATH characters */ - char szLongDirName[MAX_LONGPATH+1]; - char szNewDir[_MAX_DIR+1]; - char szBuiltDir[_MAX_DIR+1]; - char szHomeDir[_MAX_DIR+1]; - WCHAR* szwPtr = NULL; - - memset(szLongDirName, 'a', MAX_LONGPATH+1); - if (0 != PAL_Initialize(argc,argv)) - { - return FAIL; - } - - /* remove the directory just in case a previous run of the test didn't */ - szwPtr = convert((LPSTR)szDirName); - - /* clean up. Remove the directory - * if it exists */ - RemoveDirectoryW(szwPtr); - - /* create a temp directory off the current directory */ - if (CreateDirectoryA(szDirName, NULL) != TRUE) - { - free(szwPtr); - Fail("SetCurrentDirectoryA: ERROR -> CreateDirectoryW failed " - "with error code: %ld.\n", GetLastError()); - } - - /* find out what the current "home" directory is */ - memset(szHomeDir, 0, (_MAX_DIR+1)); - if(GetCurrentDir(szHomeDir) != TRUE) - { - if (!RemoveDirectoryW(szwPtr)) - { - Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed " - "with error code: %ld.\n", GetLastError()); - } - free(szwPtr); - PAL_TerminateEx(FAIL); - return FAIL; - } - - /* set the current directory to the temp directory */ - - if (SetCurrentDirectoryA(szDirName) != TRUE) - { - Trace("SetCurrentDirectoryA: ERROR -> Unable to set current " - "directory. Failed with error code: %ld.\n", GetLastError()); - if (!RemoveDirectoryW(szwPtr)) - { - Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed " - "with error code: %ld.\n", GetLastError()); - } - free(szwPtr); - Fail(""); - } - - /* append the temp name to the "home" directory */ - memset(szBuiltDir, 0, (_MAX_DIR+1)); -#if WIN32 - sprintf(szBuiltDir,"%s%s\\", szHomeDir, szDirName); -#else - sprintf(szBuiltDir,"%s%s/", szHomeDir, szDirName); -#endif - - /* get the new current directory */ - memset(szNewDir, 0, (_MAX_DIR+1)); - if(GetCurrentDir(szNewDir) != TRUE) - { - if (!RemoveDirectoryW(szwPtr)) - { - Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed " - "with error code: %ld.\n", GetLastError()); - } - free(szwPtr); - PAL_TerminateEx(FAIL); - return FAIL; - } - - /*compare the new current dir to the compiled current dir */ - if (strncmp(szNewDir, szBuiltDir, strlen(szNewDir)) != 0) - { - if (!RemoveDirectoryW(szwPtr)) - { - Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed " - "with error code: %ld.\n", GetLastError()); - } - free(szwPtr); - Fail("SetCurrentDirectoryA: ERROR -> The set directory \"%s\" does not" - " compare to the built directory \"%s\".\n", - szNewDir, - szBuiltDir); - } - - - - /* set the current dir back to the original */ - if (SetCurrentDirectoryA(szHomeDir) != TRUE) - { - Trace("SetCurrentDirectoryA: ERROR -> Unable to set current " - "directory. Failed with error code: %ld.\n", GetLastError()); - if (!RemoveDirectoryW(szwPtr)) - { - Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed " - "with error code: %ld.\n", GetLastError()); - } - free(szwPtr); - Fail(""); - } - - - /* get the new current directory */ - memset(szNewDir, 0, sizeof(char)*(_MAX_DIR+1)); - if(GetCurrentDir(szNewDir) != TRUE) - { - if (!RemoveDirectoryW(szwPtr)) - { - Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed " - "with error code: %ld.\n", GetLastError()); - } - free(szwPtr); - PAL_TerminateEx(FAIL); - return FAIL; - } - - /* ensure it compares to the "home" directory which is where - we should be now */ - if (strncmp(szNewDir, szHomeDir, strlen(szNewDir)) != 0) - { - if (!RemoveDirectoryW(szwPtr)) - { - Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed " - "with error code: %ld.\n", GetLastError()); - } - free(szwPtr); - Fail("SetCurrentDirectoryA: ERROR -> The set directory does not " - "compare to the built directory.\n"); - } - - - /* clean up */ - if (!RemoveDirectoryW(szwPtr)) - { - free(szwPtr); - Fail("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed " - "with error code: %ld.\n", GetLastError()); - } - - free(szwPtr); - PAL_Terminate(); - - return PASS; -} - - diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/SetCurrentDirectoryA.cpp b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/SetCurrentDirectoryA.cpp new file mode 100644 index 0000000..f227aa3 --- /dev/null +++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test1/SetCurrentDirectoryA.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*===================================================================== +** +** Source: SetCurrentDirectoryA.c (test 1) +** +** Purpose: Tests the PAL implementation of the SetCurrentDirectoryA function. +** +** +**===================================================================*/ + +#include + + + +/* In order to avoid the "chicken and egg" scenario, this is another + method of getting the current directory. GetFullPathNameA is called with + a dummy file name and then the file name is stripped off leaving the + current working directory +*/ + +BOOL GetCurrentDir(char* szCurrentDir) +{ + const char* szFileName = "blah"; + DWORD dwRc = 0; + char szReturnedPath[_MAX_DIR+1]; + LPSTR pPathPtr; + size_t nCount = 0; + + /* use GetFullPathNameA to to get the current path by stripping + the file name off the end */ + memset(szReturnedPath, 0, (_MAX_DIR+1)); + dwRc = GetFullPathNameA(szFileName, + _MAX_DIR, + szReturnedPath, + &pPathPtr); + + if (dwRc == 0) + { + /* GetFullPathNameA failed */ + Trace("SetCurrentDirectoryA: ERROR -> GetFullPathNameA failed " + "with error code: %ld.\n", GetLastError()); + return(FALSE); + } + + /* now strip the file name from the full path to get the current path */ + nCount = strlen(szReturnedPath) - strlen(szFileName); + memset(szCurrentDir, 0, (_MAX_DIR+1)); + strncpy(szCurrentDir, szReturnedPath, nCount); + + return(TRUE); +} + + + +int __cdecl main(int argc, char *argv[]) +{ + const char* szDirName = "testing"; + /* directory name longer than MAX_PATH characters */ + char szLongDirName[MAX_LONGPATH+1]; + char szNewDir[_MAX_DIR+1]; + char szBuiltDir[_MAX_DIR+1]; + char szHomeDir[_MAX_DIR+1]; + WCHAR* szwPtr = NULL; + + memset(szLongDirName, 'a', MAX_LONGPATH+1); + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* remove the directory just in case a previous run of the test didn't */ + szwPtr = convert((LPSTR)szDirName); + + /* clean up. Remove the directory + * if it exists */ + RemoveDirectoryW(szwPtr); + + /* create a temp directory off the current directory */ + if (CreateDirectoryA(szDirName, NULL) != TRUE) + { + free(szwPtr); + Fail("SetCurrentDirectoryA: ERROR -> CreateDirectoryW failed " + "with error code: %ld.\n", GetLastError()); + } + + /* find out what the current "home" directory is */ + memset(szHomeDir, 0, (_MAX_DIR+1)); + if(GetCurrentDir(szHomeDir) != TRUE) + { + if (!RemoveDirectoryW(szwPtr)) + { + Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed " + "with error code: %ld.\n", GetLastError()); + } + free(szwPtr); + PAL_TerminateEx(FAIL); + return FAIL; + } + + /* set the current directory to the temp directory */ + + if (SetCurrentDirectoryA(szDirName) != TRUE) + { + Trace("SetCurrentDirectoryA: ERROR -> Unable to set current " + "directory. Failed with error code: %ld.\n", GetLastError()); + if (!RemoveDirectoryW(szwPtr)) + { + Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed " + "with error code: %ld.\n", GetLastError()); + } + free(szwPtr); + Fail(""); + } + + /* append the temp name to the "home" directory */ + memset(szBuiltDir, 0, (_MAX_DIR+1)); +#if WIN32 + sprintf_s(szBuiltDir, _countof(szBuiltDir),"%s%s\\", szHomeDir, szDirName); +#else + sprintf_s(szBuiltDir, _countof(szBuiltDir),"%s%s/", szHomeDir, szDirName); +#endif + + /* get the new current directory */ + memset(szNewDir, 0, (_MAX_DIR+1)); + if(GetCurrentDir(szNewDir) != TRUE) + { + if (!RemoveDirectoryW(szwPtr)) + { + Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed " + "with error code: %ld.\n", GetLastError()); + } + free(szwPtr); + PAL_TerminateEx(FAIL); + return FAIL; + } + + /*compare the new current dir to the compiled current dir */ + if (strncmp(szNewDir, szBuiltDir, strlen(szNewDir)) != 0) + { + if (!RemoveDirectoryW(szwPtr)) + { + Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed " + "with error code: %ld.\n", GetLastError()); + } + free(szwPtr); + Fail("SetCurrentDirectoryA: ERROR -> The set directory \"%s\" does not" + " compare to the built directory \"%s\".\n", + szNewDir, + szBuiltDir); + } + + + + /* set the current dir back to the original */ + if (SetCurrentDirectoryA(szHomeDir) != TRUE) + { + Trace("SetCurrentDirectoryA: ERROR -> Unable to set current " + "directory. Failed with error code: %ld.\n", GetLastError()); + if (!RemoveDirectoryW(szwPtr)) + { + Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed " + "with error code: %ld.\n", GetLastError()); + } + free(szwPtr); + Fail(""); + } + + + /* get the new current directory */ + memset(szNewDir, 0, sizeof(char)*(_MAX_DIR+1)); + if(GetCurrentDir(szNewDir) != TRUE) + { + if (!RemoveDirectoryW(szwPtr)) + { + Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed " + "with error code: %ld.\n", GetLastError()); + } + free(szwPtr); + PAL_TerminateEx(FAIL); + return FAIL; + } + + /* ensure it compares to the "home" directory which is where + we should be now */ + if (strncmp(szNewDir, szHomeDir, strlen(szNewDir)) != 0) + { + if (!RemoveDirectoryW(szwPtr)) + { + Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed " + "with error code: %ld.\n", GetLastError()); + } + free(szwPtr); + Fail("SetCurrentDirectoryA: ERROR -> The set directory does not " + "compare to the built directory.\n"); + } + + + /* clean up */ + if (!RemoveDirectoryW(szwPtr)) + { + free(szwPtr); + Fail("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed " + "with error code: %ld.\n", GetLastError()); + } + + free(szwPtr); + PAL_Terminate(); + + return PASS; +} + + diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/CMakeLists.txt index 7c9caf8..243e80b 100644 --- a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - setcurrentdirectorya.c + setcurrentdirectorya.cpp ) add_executable(paltest_setcurrentdirectorya_test2 diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/setcurrentdirectorya.c b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/setcurrentdirectorya.c deleted file mode 100644 index 415dbbf..0000000 --- a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/setcurrentdirectorya.c +++ /dev/null @@ -1,142 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: SetCurrentDirectoryA.c (test 2) -** -** Purpose: Tests the PAL implementation of the SetCurrentDirectoryA function -** by setting the current directory with ../ -** -** -**===================================================================*/ - -#include - -int __cdecl main(int argc, char *argv[]) -{ - const char szDirName[MAX_PATH] = "testing"; - char szBuiltDir[_MAX_DIR+1]; - char szHomeDirBefore[_MAX_DIR+1]; - char szHomeDirAfter[_MAX_DIR+1]; - WCHAR* szwPtr = NULL; - - - if (0 != PAL_Initialize(argc,argv)) - { - return FAIL; - } - - /* create a temp directory off the current directory */ - szwPtr = convert((LPSTR)szDirName); - - if (CreateDirectoryA(szDirName, NULL) != TRUE) - { - free(szwPtr); - Fail("Unexpected error: CreateDirectoryW failed " - "with error code: %ld.\n", - GetLastError()); - } - - /* find out what the current "home" directory is */ - memset(szHomeDirBefore, 0, (_MAX_DIR+1)); - - if( 0 == GetCurrentDirectoryA((_MAX_DIR+1), szHomeDirBefore) ) - { - Trace("Unexpected error: Unable to get current directory " - "with GetCurrentDirectoryA that returned %ld\n", - GetLastError()); - - if (!RemoveDirectoryW(szwPtr)) - { - Trace("Unexpected error: RemoveDirectoryW failed " - "with error code: %ld.\n", - GetLastError()); - } - free(szwPtr); - - Fail(""); - } - - /* append the temp name to the "home" directory */ - memset(szBuiltDir, 0, (_MAX_DIR+1)); -#if WIN32 - sprintf(szBuiltDir,"%s\\..\\", szDirName); -#else - sprintf(szBuiltDir,"%s/../", szDirName); -#endif - - - /* set the current directory to the temp directory */ - if (SetCurrentDirectoryA(szBuiltDir) != TRUE) - { - Trace("ERROR: Unable to set current " - "directory to %s. Failed with error code: %ld.\n", - szBuiltDir, - GetLastError()); - - if (!RemoveDirectoryW(szwPtr)) - { - Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed " - "with error code: %ld.\n", - GetLastError()); - } - free(szwPtr); - Fail(""); - } - - /* find out what the current "home" directory is */ - memset(szHomeDirAfter, 0, (_MAX_DIR+1)); - - if( 0 == GetCurrentDirectoryA((_MAX_DIR+1), szHomeDirAfter) ) - { - Trace("Unexpected error: Unable to get current directory " - "with GetCurrentDirectoryA that returned %ld\n", - GetLastError()); - - if (!RemoveDirectoryW(szwPtr)) - { - Trace("Unexpected error: RemoveDirectoryW failed " - "with error code: %ld.\n", - GetLastError()); - } - free(szwPtr); - - Fail(""); - } - - /*compare the new current dir to the compiled current dir */ - if (strncmp(szHomeDirBefore, szHomeDirAfter, strlen(szHomeDirBefore)) != 0) - { - Trace("ERROR: The set directory \"%s\" does not " - "compare to the built directory \"%s\".\n", - szHomeDirAfter, - szHomeDirBefore); - - if (!RemoveDirectoryW(szwPtr)) - { - Trace("Unexpected error: RemoveDirectoryW failed " - "with error code: %ld.\n", - GetLastError()); - } - free(szwPtr); - Fail(""); - } - - /* clean up */ - if (!RemoveDirectoryW(szwPtr)) - { - free(szwPtr); - Fail("Unexpected error: RemoveDirectoryW failed " - "with error code: %ld.\n", - GetLastError()); - } - - free(szwPtr); - PAL_Terminate(); - - return PASS; -} - - diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/setcurrentdirectorya.cpp b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/setcurrentdirectorya.cpp new file mode 100644 index 0000000..4b1c1c8 --- /dev/null +++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test2/setcurrentdirectorya.cpp @@ -0,0 +1,142 @@ +// 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. + +/*===================================================================== +** +** Source: SetCurrentDirectoryA.c (test 2) +** +** Purpose: Tests the PAL implementation of the SetCurrentDirectoryA function +** by setting the current directory with ../ +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + const char szDirName[MAX_PATH] = "testing"; + char szBuiltDir[_MAX_DIR+1]; + char szHomeDirBefore[_MAX_DIR+1]; + char szHomeDirAfter[_MAX_DIR+1]; + WCHAR* szwPtr = NULL; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* create a temp directory off the current directory */ + szwPtr = convert((LPSTR)szDirName); + + if (CreateDirectoryA(szDirName, NULL) != TRUE) + { + free(szwPtr); + Fail("Unexpected error: CreateDirectoryW failed " + "with error code: %ld.\n", + GetLastError()); + } + + /* find out what the current "home" directory is */ + memset(szHomeDirBefore, 0, (_MAX_DIR+1)); + + if( 0 == GetCurrentDirectoryA((_MAX_DIR+1), szHomeDirBefore) ) + { + Trace("Unexpected error: Unable to get current directory " + "with GetCurrentDirectoryA that returned %ld\n", + GetLastError()); + + if (!RemoveDirectoryW(szwPtr)) + { + Trace("Unexpected error: RemoveDirectoryW failed " + "with error code: %ld.\n", + GetLastError()); + } + free(szwPtr); + + Fail(""); + } + + /* append the temp name to the "home" directory */ + memset(szBuiltDir, 0, (_MAX_DIR+1)); +#if WIN32 + sprintf_s(szBuiltDir, _countof(szBuiltDir),"%s\\..\\", szDirName); +#else + sprintf_s(szBuiltDir, _countof(szBuiltDir),"%s/../", szDirName); +#endif + + + /* set the current directory to the temp directory */ + if (SetCurrentDirectoryA(szBuiltDir) != TRUE) + { + Trace("ERROR: Unable to set current " + "directory to %s. Failed with error code: %ld.\n", + szBuiltDir, + GetLastError()); + + if (!RemoveDirectoryW(szwPtr)) + { + Trace("SetCurrentDirectoryA: ERROR -> RemoveDirectoryW failed " + "with error code: %ld.\n", + GetLastError()); + } + free(szwPtr); + Fail(""); + } + + /* find out what the current "home" directory is */ + memset(szHomeDirAfter, 0, (_MAX_DIR+1)); + + if( 0 == GetCurrentDirectoryA((_MAX_DIR+1), szHomeDirAfter) ) + { + Trace("Unexpected error: Unable to get current directory " + "with GetCurrentDirectoryA that returned %ld\n", + GetLastError()); + + if (!RemoveDirectoryW(szwPtr)) + { + Trace("Unexpected error: RemoveDirectoryW failed " + "with error code: %ld.\n", + GetLastError()); + } + free(szwPtr); + + Fail(""); + } + + /*compare the new current dir to the compiled current dir */ + if (strncmp(szHomeDirBefore, szHomeDirAfter, strlen(szHomeDirBefore)) != 0) + { + Trace("ERROR: The set directory \"%s\" does not " + "compare to the built directory \"%s\".\n", + szHomeDirAfter, + szHomeDirBefore); + + if (!RemoveDirectoryW(szwPtr)) + { + Trace("Unexpected error: RemoveDirectoryW failed " + "with error code: %ld.\n", + GetLastError()); + } + free(szwPtr); + Fail(""); + } + + /* clean up */ + if (!RemoveDirectoryW(szwPtr)) + { + free(szwPtr); + Fail("Unexpected error: RemoveDirectoryW failed " + "with error code: %ld.\n", + GetLastError()); + } + + free(szwPtr); + PAL_Terminate(); + + return PASS; +} + + diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/CMakeLists.txt index 57d3577..8560ff0 100644 --- a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - setcurrentdirectorya.c + setcurrentdirectorya.cpp ) add_executable(paltest_setcurrentdirectorya_test3 diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/setcurrentdirectorya.c b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/setcurrentdirectorya.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/setcurrentdirectorya.c rename to src/pal/tests/palsuite/file_io/SetCurrentDirectoryA/test3/setcurrentdirectorya.cpp diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/CMakeLists.txt index a0c1dff..9149221 100644 --- a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetCurrentDirectoryW.c + SetCurrentDirectoryW.cpp ) add_executable(paltest_setcurrentdirectoryw_test1 diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/SetCurrentDirectoryW.c b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/SetCurrentDirectoryW.c deleted file mode 100644 index 257d016..0000000 --- a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/SetCurrentDirectoryW.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*===================================================================== -** -** Source: SetCurrentDirectoryW.c (test 1) -** -** Purpose: Tests the PAL implementation of the SetCurrentDirectoryW function. -** -** -**===================================================================*/ - -#include - -const char* szFileName = "blah"; -const char* szDirName = "testing"; - - -// In order to avoid the "chicken and egg" scenario, this is another -// method of getting the current directory. GetFullPathNameW is called with -// a dummy file name and then the file name is stripped off leaving the -// current working directory -BOOL GetCurrentDir(WCHAR* szwCurrentDir) -{ - DWORD dwRc = 0; - WCHAR szwReturnedPath[_MAX_DIR+1]; - LPWSTR pPathPtr; - WCHAR* szwFileName = NULL; - WCHAR* szwDirName = NULL; - int nCount = 0; - - // use GetFullPathName to to get the current path by stripping - // the file name off the end - memset(szwReturnedPath, 0, sizeof(WCHAR)*(_MAX_DIR+1)); - szwFileName = convert((char*)szFileName); - dwRc = GetFullPathNameW(szwFileName, - _MAX_DIR, - szwReturnedPath, - &pPathPtr); - - if (dwRc == 0) - { - // GetFullPathName failed - Trace("SetCurrentDirectoryW: ERROR -> GetFullPathNameW failed " - "with error code: %ld.\n", GetLastError()); - RemoveDirectoryW(szwDirName); - free(szwFileName); - return(FALSE); - } - - // now strip the file name from the full path to get the current path - nCount = lstrlenW(szwReturnedPath) - lstrlenW(szwFileName); - memset(szwCurrentDir, 0, sizeof(WCHAR)*(_MAX_DIR+1)); - lstrcpynW(szwCurrentDir, szwReturnedPath, nCount); - - free(szwFileName); - return(TRUE); -} - -int __cdecl main(int argc, char *argv[]) -{ - WCHAR* szwDirName = NULL; - WCHAR szwNewDir[_MAX_DIR+1]; - WCHAR szwBuiltDir[_MAX_DIR+1]; - WCHAR szwHomeDir[_MAX_DIR+1]; -#if WIN32 - WCHAR szwSlash[] = {'\\','\0'}; -#else - WCHAR szwSlash[] = {'/','\0'}; -#endif - - if (0 != PAL_Initialize(argc,argv)) - { - return FAIL; - } - - // remove the directory just in case a previous run of the test didn't - szwDirName = convert((char*)szDirName); - RemoveDirectoryW(szwDirName); - - // create a temp directory off the current directory - if (CreateDirectoryW(szwDirName, NULL) != TRUE) - { - Trace("SetCurrentDirectoryW: ERROR -> CreateDirectoryW failed " - "with error code: %ld.\n", GetLastError()); - RemoveDirectoryW(szwDirName); - free(szwDirName); - Fail(""); - } - - // find out what the current "home" directory is - memset(szwHomeDir, 0, sizeof(WCHAR)*(_MAX_DIR+1)); - if(GetCurrentDir(szwHomeDir) != TRUE) - { - RemoveDirectoryW(szwDirName); - free(szwDirName); - PAL_TerminateEx(FAIL); - return FAIL; - } - - // set the current directory to the temp directory - if (SetCurrentDirectoryW(szwDirName) != TRUE) - { - Trace("SetCurrentDirectoryW: ERROR -> Unable to set current " - "directory. Failed with error code: %ld.\n", GetLastError()); - RemoveDirectoryW(szwDirName); - free(szwDirName); - Fail(""); - } - - // append the temp name to the "home" directory - memset(szwBuiltDir, 0, sizeof(WCHAR)*(_MAX_DIR+1)); - wcscpy(szwBuiltDir, szwHomeDir); - wcscat(szwBuiltDir, szwSlash); - wcscat(szwBuiltDir, szwDirName); - - // get the new current directory - memset(szwNewDir, 0, sizeof(WCHAR)*(_MAX_DIR+1)); - if(GetCurrentDir(szwNewDir) != TRUE) - { - RemoveDirectoryW(szwDirName); - free(szwDirName); - PAL_TerminateEx(FAIL); - return FAIL; - } - - // compare the new current dir to the compiled current dir - if (wcsncmp(szwNewDir, szwBuiltDir, wcslen(szwNewDir)) != 0) - { - RemoveDirectoryW(szwDirName); - free(szwDirName); - Fail("SetCurrentDirectoryW: ERROR -> The set directory does not " - "compare to the built directory.\n"); - } - - - - // set the current dir back to the original - if (SetCurrentDirectoryW(szwHomeDir) != TRUE) - { - Trace("SetCurrentDirectoryW: ERROR -> Unable to set current " - "directory. Failed with error code: %ld.\n", GetLastError()); - RemoveDirectoryW(szwDirName); - free(szwDirName); - Fail(""); - } - - - // get the new current directory - memset(szwNewDir, 0, sizeof(WCHAR)*(_MAX_DIR+1)); - if(GetCurrentDir(szwNewDir) != TRUE) - { - RemoveDirectoryW(szwDirName); - free(szwDirName); - PAL_TerminateEx(FAIL); - return FAIL; - } - - // ensure it compares to the "home" directory which is where - // we should be now - if (wcsncmp(szwNewDir, szwHomeDir, wcslen(szwNewDir)) != 0) - { - RemoveDirectoryW(szwDirName); - free(szwDirName); - Fail("SetCurrentDirectoryW: ERROR -> The set directory does not " - "compare to the built directory.\n"); - } - - - RemoveDirectoryW(szwDirName); - free(szwDirName); - PAL_Terminate(); - - return PASS; -} - - diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/SetCurrentDirectoryW.cpp b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/SetCurrentDirectoryW.cpp new file mode 100644 index 0000000..e10f2ea --- /dev/null +++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test1/SetCurrentDirectoryW.cpp @@ -0,0 +1,178 @@ +// 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. + +/*===================================================================== +** +** Source: SetCurrentDirectoryW.c (test 1) +** +** Purpose: Tests the PAL implementation of the SetCurrentDirectoryW function. +** +** +**===================================================================*/ + +#include + +const char* szFileName = "blah"; +const char* szDirName = "testing"; + + +// In order to avoid the "chicken and egg" scenario, this is another +// method of getting the current directory. GetFullPathNameW is called with +// a dummy file name and then the file name is stripped off leaving the +// current working directory +BOOL GetCurrentDir(WCHAR* szwCurrentDir) +{ + DWORD dwRc = 0; + WCHAR szwReturnedPath[_MAX_DIR+1]; + LPWSTR pPathPtr; + WCHAR* szwFileName = NULL; + WCHAR* szwDirName = NULL; + int nCount = 0; + + // use GetFullPathName to to get the current path by stripping + // the file name off the end + memset(szwReturnedPath, 0, sizeof(WCHAR)*(_MAX_DIR+1)); + szwFileName = convert((char*)szFileName); + dwRc = GetFullPathNameW(szwFileName, + _MAX_DIR, + szwReturnedPath, + &pPathPtr); + + if (dwRc == 0) + { + // GetFullPathName failed + Trace("SetCurrentDirectoryW: ERROR -> GetFullPathNameW failed " + "with error code: %ld.\n", GetLastError()); + RemoveDirectoryW(szwDirName); + free(szwFileName); + return(FALSE); + } + + // now strip the file name from the full path to get the current path + nCount = lstrlenW(szwReturnedPath) - lstrlenW(szwFileName); + memset(szwCurrentDir, 0, sizeof(WCHAR)*(_MAX_DIR+1)); + wcsncpy(szwCurrentDir, szwReturnedPath, nCount - 1); + + free(szwFileName); + return(TRUE); +} + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR* szwDirName = NULL; + WCHAR szwNewDir[_MAX_DIR+1]; + WCHAR szwBuiltDir[_MAX_DIR+1]; + WCHAR szwHomeDir[_MAX_DIR+1]; +#if WIN32 + WCHAR szwSlash[] = {'\\','\0'}; +#else + WCHAR szwSlash[] = {'/','\0'}; +#endif + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + // remove the directory just in case a previous run of the test didn't + szwDirName = convert((char*)szDirName); + RemoveDirectoryW(szwDirName); + + // create a temp directory off the current directory + if (CreateDirectoryW(szwDirName, NULL) != TRUE) + { + Trace("SetCurrentDirectoryW: ERROR -> CreateDirectoryW failed " + "with error code: %ld.\n", GetLastError()); + RemoveDirectoryW(szwDirName); + free(szwDirName); + Fail(""); + } + + // find out what the current "home" directory is + memset(szwHomeDir, 0, sizeof(WCHAR)*(_MAX_DIR+1)); + if(GetCurrentDir(szwHomeDir) != TRUE) + { + RemoveDirectoryW(szwDirName); + free(szwDirName); + PAL_TerminateEx(FAIL); + return FAIL; + } + + // set the current directory to the temp directory + if (SetCurrentDirectoryW(szwDirName) != TRUE) + { + Trace("SetCurrentDirectoryW: ERROR -> Unable to set current " + "directory. Failed with error code: %ld.\n", GetLastError()); + RemoveDirectoryW(szwDirName); + free(szwDirName); + Fail(""); + } + + // append the temp name to the "home" directory + memset(szwBuiltDir, 0, sizeof(WCHAR)*(_MAX_DIR+1)); + wcscpy(szwBuiltDir, szwHomeDir); + wcscat(szwBuiltDir, szwSlash); + wcscat(szwBuiltDir, szwDirName); + + // get the new current directory + memset(szwNewDir, 0, sizeof(WCHAR)*(_MAX_DIR+1)); + if(GetCurrentDir(szwNewDir) != TRUE) + { + RemoveDirectoryW(szwDirName); + free(szwDirName); + PAL_TerminateEx(FAIL); + return FAIL; + } + + // compare the new current dir to the compiled current dir + if (wcsncmp(szwNewDir, szwBuiltDir, wcslen(szwNewDir)) != 0) + { + RemoveDirectoryW(szwDirName); + free(szwDirName); + Fail("SetCurrentDirectoryW: ERROR -> The set directory does not " + "compare to the built directory.\n"); + } + + + + // set the current dir back to the original + if (SetCurrentDirectoryW(szwHomeDir) != TRUE) + { + Trace("SetCurrentDirectoryW: ERROR -> Unable to set current " + "directory. Failed with error code: %ld.\n", GetLastError()); + RemoveDirectoryW(szwDirName); + free(szwDirName); + Fail(""); + } + + + // get the new current directory + memset(szwNewDir, 0, sizeof(WCHAR)*(_MAX_DIR+1)); + if(GetCurrentDir(szwNewDir) != TRUE) + { + RemoveDirectoryW(szwDirName); + free(szwDirName); + PAL_TerminateEx(FAIL); + return FAIL; + } + + // ensure it compares to the "home" directory which is where + // we should be now + if (wcsncmp(szwNewDir, szwHomeDir, wcslen(szwNewDir)) != 0) + { + RemoveDirectoryW(szwDirName); + free(szwDirName); + Fail("SetCurrentDirectoryW: ERROR -> The set directory does not " + "compare to the built directory.\n"); + } + + + RemoveDirectoryW(szwDirName); + free(szwDirName); + PAL_Terminate(); + + return PASS; +} + + diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/CMakeLists.txt index a032462..455ddc8 100644 --- a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - setcurrentdirectoryw.c + setcurrentdirectoryw.cpp ) add_executable(paltest_setcurrentdirectoryw_test2 diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/setcurrentdirectoryw.c b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/setcurrentdirectoryw.c deleted file mode 100644 index 7e3d7b7..0000000 --- a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/setcurrentdirectoryw.c +++ /dev/null @@ -1,147 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: SetCurrentDirectoryW.c (test 2) -** -** Purpose: Tests the PAL implementation of the SetCurrentDirectoryW function -** by setting the current directory with ../ -** -** -**===================================================================*/ - -#include - -int __cdecl main(int argc, char *argv[]) -{ - const char szDirName[MAX_PATH] = "testing"; - char szBuiltDir[MAX_PATH]; - WCHAR* szwBuiltDir = NULL; - WCHAR szwHomeDirBefore[MAX_PATH]; - WCHAR szwHomeDirAfter[MAX_PATH]; - WCHAR* szwPtr = NULL; - - - if (0 != PAL_Initialize(argc,argv)) - { - return FAIL; - } - - /* create a temp directory off the current directory */ - szwPtr = convert((LPSTR)szDirName); - - if (CreateDirectoryW(szwPtr, NULL) != TRUE) - { - free(szwPtr); - Fail("Unexpected error: CreateDirectoryW failed " - "with error code: %ld.\n", - GetLastError()); - } - - /* find out what the current "home" directory is */ - memset(szwHomeDirBefore, 0, MAX_PATH * sizeof(WCHAR)); - - if( 0 == GetCurrentDirectoryW(MAX_PATH, szwHomeDirBefore) ) - { - Trace("Unexpected error: Unable to get current directory " - "with GetCurrentDirectoryW that returned %ld\n", - GetLastError()); - - if (!RemoveDirectoryW(szwPtr)) - { - Trace("Unexpected error: RemoveDirectoryW failed " - "with error code: %ld.\n", - GetLastError()); - } - free(szwPtr); - - Fail(""); - } - - /* append the temp name to the "home" directory */ - memset(szBuiltDir, 0, MAX_PATH); -#if WIN32 - sprintf(szBuiltDir,"%s\\..\\", szDirName); -#else - sprintf(szBuiltDir,"%s/../", szDirName); -#endif - - szwBuiltDir = convert(szBuiltDir); - - /* set the current directory to the temp directory */ - if (SetCurrentDirectoryW(szwBuiltDir) != TRUE) - { - Trace("ERROR: Unable to set current " - "directory to %S. Failed with error code: %ld.\n", - szwBuiltDir, - GetLastError()); - - if (!RemoveDirectoryW(szwPtr)) - { - Trace("Unexpected error: RemoveDirectoryW failed " - "with error code: %ld.\n", - GetLastError()); - } - free(szwPtr); - free(szwBuiltDir); - Fail(""); - } - - free(szwBuiltDir); - - /* find out what the current "home" directory is */ - memset(szwHomeDirAfter, 0, MAX_PATH * sizeof(WCHAR)); - - if( 0 == GetCurrentDirectoryW(MAX_PATH, szwHomeDirAfter) ) - { - Trace("Unexpected error: Unable to get current directory " - "with GetCurrentDirectoryW that returned %ld\n", - GetLastError()); - - if (!RemoveDirectoryW(szwPtr)) - { - Trace("ERROR: RemoveDirectoryW failed " - "with error code: %ld.\n", - GetLastError()); - } - free(szwPtr); - - Fail(""); - } - - /*compare the new current dir to the compiled current dir */ - if (wcsncmp(szwHomeDirBefore, szwHomeDirAfter, wcslen(szwHomeDirBefore)) != 0) - { - Trace("ERROR:The set directory \"%S\" does not " - "compare to the built directory \"%S\".\n", - szwHomeDirAfter, - szwHomeDirBefore); - - if (!RemoveDirectoryW(szwPtr)) - { - Trace("Unexpected error: RemoveDirectoryW failed " - "with error code: %ld.\n", - GetLastError()); - } - free(szwPtr); - Fail(""); - } - - /* clean up */ - if (!RemoveDirectoryW(szwPtr)) - { - free(szwPtr); - Fail("Unexpected error: RemoveDirectoryW failed " - "with error code: %ld.\n", - GetLastError()); - } - - free(szwPtr); - PAL_Terminate(); - - return PASS; -} - - diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/setcurrentdirectoryw.cpp b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/setcurrentdirectoryw.cpp new file mode 100644 index 0000000..7f833ba --- /dev/null +++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test2/setcurrentdirectoryw.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*===================================================================== +** +** Source: SetCurrentDirectoryW.c (test 2) +** +** Purpose: Tests the PAL implementation of the SetCurrentDirectoryW function +** by setting the current directory with ../ +** +** +**===================================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + const char szDirName[MAX_PATH] = "testing"; + char szBuiltDir[MAX_PATH]; + WCHAR* szwBuiltDir = NULL; + WCHAR szwHomeDirBefore[MAX_PATH]; + WCHAR szwHomeDirAfter[MAX_PATH]; + WCHAR* szwPtr = NULL; + + + if (0 != PAL_Initialize(argc,argv)) + { + return FAIL; + } + + /* create a temp directory off the current directory */ + szwPtr = convert((LPSTR)szDirName); + + if (CreateDirectoryW(szwPtr, NULL) != TRUE) + { + free(szwPtr); + Fail("Unexpected error: CreateDirectoryW failed " + "with error code: %ld.\n", + GetLastError()); + } + + /* find out what the current "home" directory is */ + memset(szwHomeDirBefore, 0, MAX_PATH * sizeof(WCHAR)); + + if( 0 == GetCurrentDirectoryW(MAX_PATH, szwHomeDirBefore) ) + { + Trace("Unexpected error: Unable to get current directory " + "with GetCurrentDirectoryW that returned %ld\n", + GetLastError()); + + if (!RemoveDirectoryW(szwPtr)) + { + Trace("Unexpected error: RemoveDirectoryW failed " + "with error code: %ld.\n", + GetLastError()); + } + free(szwPtr); + + Fail(""); + } + + /* append the temp name to the "home" directory */ + memset(szBuiltDir, 0, MAX_PATH); +#if WIN32 + sprintf_s(szBuiltDir, _countof(szBuiltDir),"%s\\..\\", szDirName); +#else + sprintf_s(szBuiltDir, _countof(szBuiltDir),"%s/../", szDirName); +#endif + + szwBuiltDir = convert(szBuiltDir); + + /* set the current directory to the temp directory */ + if (SetCurrentDirectoryW(szwBuiltDir) != TRUE) + { + Trace("ERROR: Unable to set current " + "directory to %S. Failed with error code: %ld.\n", + szwBuiltDir, + GetLastError()); + + if (!RemoveDirectoryW(szwPtr)) + { + Trace("Unexpected error: RemoveDirectoryW failed " + "with error code: %ld.\n", + GetLastError()); + } + free(szwPtr); + free(szwBuiltDir); + Fail(""); + } + + free(szwBuiltDir); + + /* find out what the current "home" directory is */ + memset(szwHomeDirAfter, 0, MAX_PATH * sizeof(WCHAR)); + + if( 0 == GetCurrentDirectoryW(MAX_PATH, szwHomeDirAfter) ) + { + Trace("Unexpected error: Unable to get current directory " + "with GetCurrentDirectoryW that returned %ld\n", + GetLastError()); + + if (!RemoveDirectoryW(szwPtr)) + { + Trace("ERROR: RemoveDirectoryW failed " + "with error code: %ld.\n", + GetLastError()); + } + free(szwPtr); + + Fail(""); + } + + /*compare the new current dir to the compiled current dir */ + if (wcsncmp(szwHomeDirBefore, szwHomeDirAfter, wcslen(szwHomeDirBefore)) != 0) + { + Trace("ERROR:The set directory \"%S\" does not " + "compare to the built directory \"%S\".\n", + szwHomeDirAfter, + szwHomeDirBefore); + + if (!RemoveDirectoryW(szwPtr)) + { + Trace("Unexpected error: RemoveDirectoryW failed " + "with error code: %ld.\n", + GetLastError()); + } + free(szwPtr); + Fail(""); + } + + /* clean up */ + if (!RemoveDirectoryW(szwPtr)) + { + free(szwPtr); + Fail("Unexpected error: RemoveDirectoryW failed " + "with error code: %ld.\n", + GetLastError()); + } + + free(szwPtr); + PAL_Terminate(); + + return PASS; +} + + diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/CMakeLists.txt index 3b981f9..1cb1150 100644 --- a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - setcurrentdirectoryw.c + setcurrentdirectoryw.cpp ) add_executable(paltest_setcurrentdirectoryw_test3 diff --git a/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/setcurrentdirectoryw.c b/src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/setcurrentdirectoryw.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/setcurrentdirectoryw.c rename to src/pal/tests/palsuite/file_io/SetCurrentDirectoryW/test3/setcurrentdirectoryw.cpp diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/CMakeLists.txt index e77ab30..3c0fdee 100644 --- a/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetEndOfFile.c + SetEndOfFile.cpp ) add_executable(paltest_setendoffile_test1 diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/SetEndOfFile.c b/src/pal/tests/palsuite/file_io/SetEndOfFile/test1/SetEndOfFile.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetEndOfFile/test1/SetEndOfFile.c rename to src/pal/tests/palsuite/file_io/SetEndOfFile/test1/SetEndOfFile.cpp diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/CMakeLists.txt index b04dea0..57afdad 100644 --- a/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetEndOfFile.c + SetEndOfFile.cpp ) add_executable(paltest_setendoffile_test2 diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/SetEndOfFile.c b/src/pal/tests/palsuite/file_io/SetEndOfFile/test2/SetEndOfFile.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetEndOfFile/test2/SetEndOfFile.c rename to src/pal/tests/palsuite/file_io/SetEndOfFile/test2/SetEndOfFile.cpp diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/CMakeLists.txt index 1ab177d..01575ce 100644 --- a/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetEndOfFile.c + SetEndOfFile.cpp ) add_executable(paltest_setendoffile_test3 diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/SetEndOfFile.c b/src/pal/tests/palsuite/file_io/SetEndOfFile/test3/SetEndOfFile.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetEndOfFile/test3/SetEndOfFile.c rename to src/pal/tests/palsuite/file_io/SetEndOfFile/test3/SetEndOfFile.cpp diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/CMakeLists.txt index ff0b6f9..1dc4f68 100644 --- a/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - setendoffile.c + setendoffile.cpp ) add_executable(paltest_setendoffile_test4 diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/setendoffile.c b/src/pal/tests/palsuite/file_io/SetEndOfFile/test4/setendoffile.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetEndOfFile/test4/setendoffile.c rename to src/pal/tests/palsuite/file_io/SetEndOfFile/test4/setendoffile.cpp diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/CMakeLists.txt index cca7167..19f87a2 100644 --- a/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_setendoffile_test5 diff --git a/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/test5.c b/src/pal/tests/palsuite/file_io/SetEndOfFile/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetEndOfFile/test5/test5.c rename to src/pal/tests/palsuite/file_io/SetEndOfFile/test5/test5.cpp diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/CMakeLists.txt index 81e2dfd..638dd5c 100644 --- a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetFileAttributesA.c + SetFileAttributesA.cpp ) add_executable(paltest_setfileattributesa_test1 diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/SetFileAttributesA.c b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/SetFileAttributesA.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/SetFileAttributesA.c rename to src/pal/tests/palsuite/file_io/SetFileAttributesA/test1/SetFileAttributesA.cpp diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/CMakeLists.txt index 03445c1..51bee5a 100644 --- a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetFileAttributesA.c + SetFileAttributesA.cpp ) add_executable(paltest_setfileattributesa_test2 diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/SetFileAttributesA.c b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/SetFileAttributesA.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/SetFileAttributesA.c rename to src/pal/tests/palsuite/file_io/SetFileAttributesA/test2/SetFileAttributesA.cpp diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/CMakeLists.txt index 3c35172..4597e1d 100644 --- a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetFileAttributesA.c + SetFileAttributesA.cpp ) add_executable(paltest_setfileattributesa_test3 diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/SetFileAttributesA.c b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/SetFileAttributesA.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/SetFileAttributesA.c rename to src/pal/tests/palsuite/file_io/SetFileAttributesA/test3/SetFileAttributesA.cpp diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/CMakeLists.txt index f30969a..1807027 100644 --- a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetFileAttributesA.c + SetFileAttributesA.cpp ) add_executable(paltest_setfileattributesa_test4 diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/SetFileAttributesA.c b/src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/SetFileAttributesA.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/SetFileAttributesA.c rename to src/pal/tests/palsuite/file_io/SetFileAttributesA/test4/SetFileAttributesA.cpp diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/CMakeLists.txt index 35927b4..825554d 100644 --- a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetFileAttributesW.c + SetFileAttributesW.cpp ) add_executable(paltest_setfileattributesw_test1 diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/SetFileAttributesW.c b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/SetFileAttributesW.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/SetFileAttributesW.c rename to src/pal/tests/palsuite/file_io/SetFileAttributesW/test1/SetFileAttributesW.cpp diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/CMakeLists.txt index 81fa02c..fda1cec 100644 --- a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetFileAttributesW.c + SetFileAttributesW.cpp ) add_executable(paltest_setfileattributesw_test2 diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/SetFileAttributesW.c b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/SetFileAttributesW.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/SetFileAttributesW.c rename to src/pal/tests/palsuite/file_io/SetFileAttributesW/test2/SetFileAttributesW.cpp diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/CMakeLists.txt index c2cdacb..1757f88 100644 --- a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetFileAttributesW.c + SetFileAttributesW.cpp ) add_executable(paltest_setfileattributesw_test3 diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/SetFileAttributesW.c b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/SetFileAttributesW.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/SetFileAttributesW.c rename to src/pal/tests/palsuite/file_io/SetFileAttributesW/test3/SetFileAttributesW.cpp diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/CMakeLists.txt index 6a4aa8a..d1cfcdd 100644 --- a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetFileAttributesW.c + SetFileAttributesW.cpp ) add_executable(paltest_setfileattributesw_test4 diff --git a/src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/SetFileAttributesW.c b/src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/SetFileAttributesW.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/SetFileAttributesW.c rename to src/pal/tests/palsuite/file_io/SetFileAttributesW/test4/SetFileAttributesW.cpp diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFilePointer/test1/CMakeLists.txt index e352449..bb09a98 100644 --- a/src/pal/tests/palsuite/file_io/SetFilePointer/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetFilePointer.c + SetFilePointer.cpp ) add_executable(paltest_setfilepointer_test1 diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test1/SetFilePointer.c b/src/pal/tests/palsuite/file_io/SetFilePointer/test1/SetFilePointer.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetFilePointer/test1/SetFilePointer.c rename to src/pal/tests/palsuite/file_io/SetFilePointer/test1/SetFilePointer.cpp diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFilePointer/test2/CMakeLists.txt index 290a011..2e76f00 100644 --- a/src/pal/tests/palsuite/file_io/SetFilePointer/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetFilePointer.c + SetFilePointer.cpp ) add_executable(paltest_setfilepointer_test2 diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test2/SetFilePointer.c b/src/pal/tests/palsuite/file_io/SetFilePointer/test2/SetFilePointer.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetFilePointer/test2/SetFilePointer.c rename to src/pal/tests/palsuite/file_io/SetFilePointer/test2/SetFilePointer.cpp diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFilePointer/test3/CMakeLists.txt index daa7553..bcc3fac 100644 --- a/src/pal/tests/palsuite/file_io/SetFilePointer/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetFilePointer.c + SetFilePointer.cpp ) add_executable(paltest_setfilepointer_test3 diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test3/SetFilePointer.c b/src/pal/tests/palsuite/file_io/SetFilePointer/test3/SetFilePointer.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetFilePointer/test3/SetFilePointer.c rename to src/pal/tests/palsuite/file_io/SetFilePointer/test3/SetFilePointer.cpp diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFilePointer/test4/CMakeLists.txt index 1117893..3fcc406 100644 --- a/src/pal/tests/palsuite/file_io/SetFilePointer/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetFilePointer.c + SetFilePointer.cpp ) add_executable(paltest_setfilepointer_test4 diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test4/SetFilePointer.c b/src/pal/tests/palsuite/file_io/SetFilePointer/test4/SetFilePointer.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetFilePointer/test4/SetFilePointer.c rename to src/pal/tests/palsuite/file_io/SetFilePointer/test4/SetFilePointer.cpp diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test5/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFilePointer/test5/CMakeLists.txt index b37bf42..3012009 100644 --- a/src/pal/tests/palsuite/file_io/SetFilePointer/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetFilePointer.c + SetFilePointer.cpp ) add_executable(paltest_setfilepointer_test5 diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test5/SetFilePointer.c b/src/pal/tests/palsuite/file_io/SetFilePointer/test5/SetFilePointer.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetFilePointer/test5/SetFilePointer.c rename to src/pal/tests/palsuite/file_io/SetFilePointer/test5/SetFilePointer.cpp diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test6/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFilePointer/test6/CMakeLists.txt index 8f99ed2..a376acb 100644 --- a/src/pal/tests/palsuite/file_io/SetFilePointer/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetFilePointer.c + SetFilePointer.cpp ) add_executable(paltest_setfilepointer_test6 diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test6/SetFilePointer.c b/src/pal/tests/palsuite/file_io/SetFilePointer/test6/SetFilePointer.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetFilePointer/test6/SetFilePointer.c rename to src/pal/tests/palsuite/file_io/SetFilePointer/test6/SetFilePointer.cpp diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test7/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFilePointer/test7/CMakeLists.txt index c5a46a5..2b5c0bb 100644 --- a/src/pal/tests/palsuite/file_io/SetFilePointer/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetFilePointer/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetFilePointer.c + SetFilePointer.cpp ) add_executable(paltest_setfilepointer_test7 diff --git a/src/pal/tests/palsuite/file_io/SetFilePointer/test7/SetFilePointer.c b/src/pal/tests/palsuite/file_io/SetFilePointer/test7/SetFilePointer.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetFilePointer/test7/SetFilePointer.c rename to src/pal/tests/palsuite/file_io/SetFilePointer/test7/SetFilePointer.cpp diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileTime/test1/CMakeLists.txt index 4c4b5d7..b94bd05 100644 --- a/src/pal/tests/palsuite/file_io/SetFileTime/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetFileTime/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetFileTime.c + SetFileTime.cpp ) add_executable(paltest_setfiletime_test1 diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/test1/SetFileTime.c b/src/pal/tests/palsuite/file_io/SetFileTime/test1/SetFileTime.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetFileTime/test1/SetFileTime.c rename to src/pal/tests/palsuite/file_io/SetFileTime/test1/SetFileTime.cpp diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileTime/test2/CMakeLists.txt index 35c18c8..5478aa3 100644 --- a/src/pal/tests/palsuite/file_io/SetFileTime/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetFileTime/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetFileTime.c + SetFileTime.cpp ) add_executable(paltest_setfiletime_test2 diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/test2/SetFileTime.c b/src/pal/tests/palsuite/file_io/SetFileTime/test2/SetFileTime.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetFileTime/test2/SetFileTime.c rename to src/pal/tests/palsuite/file_io/SetFileTime/test2/SetFileTime.cpp diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileTime/test3/CMakeLists.txt index 0a85d30..26e178a 100644 --- a/src/pal/tests/palsuite/file_io/SetFileTime/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetFileTime/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetFileTime.c + SetFileTime.cpp ) add_executable(paltest_setfiletime_test3 diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/test3/SetFileTime.c b/src/pal/tests/palsuite/file_io/SetFileTime/test3/SetFileTime.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetFileTime/test3/SetFileTime.c rename to src/pal/tests/palsuite/file_io/SetFileTime/test3/SetFileTime.cpp diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/SetFileTime/test4/CMakeLists.txt index 086e35e..b85a92b 100644 --- a/src/pal/tests/palsuite/file_io/SetFileTime/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/SetFileTime/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - SetFileTime.c + SetFileTime.cpp ) add_executable(paltest_setfiletime_test4 diff --git a/src/pal/tests/palsuite/file_io/SetFileTime/test4/SetFileTime.c b/src/pal/tests/palsuite/file_io/SetFileTime/test4/SetFileTime.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/SetFileTime/test4/SetFileTime.c rename to src/pal/tests/palsuite/file_io/SetFileTime/test4/SetFileTime.cpp diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/WriteFile/test1/CMakeLists.txt index 0c6760a..3d5a735 100644 --- a/src/pal/tests/palsuite/file_io/WriteFile/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/WriteFile/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - WriteFile.c + WriteFile.cpp ) add_executable(paltest_writefile_test1 diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test1/WriteFile.c b/src/pal/tests/palsuite/file_io/WriteFile/test1/WriteFile.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/WriteFile/test1/WriteFile.c rename to src/pal/tests/palsuite/file_io/WriteFile/test1/WriteFile.cpp diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/WriteFile/test2/CMakeLists.txt index a9b51ef..3d7d188 100644 --- a/src/pal/tests/palsuite/file_io/WriteFile/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/WriteFile/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - WriteFile.c + WriteFile.cpp ) add_executable(paltest_writefile_test2 diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test2/WriteFile.c b/src/pal/tests/palsuite/file_io/WriteFile/test2/WriteFile.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/WriteFile/test2/WriteFile.c rename to src/pal/tests/palsuite/file_io/WriteFile/test2/WriteFile.cpp diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/WriteFile/test3/CMakeLists.txt index e16e8a4..bffcf35 100644 --- a/src/pal/tests/palsuite/file_io/WriteFile/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/WriteFile/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - WriteFile.c + WriteFile.cpp ) add_executable(paltest_writefile_test3 diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test3/WriteFile.c b/src/pal/tests/palsuite/file_io/WriteFile/test3/WriteFile.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/WriteFile/test3/WriteFile.c rename to src/pal/tests/palsuite/file_io/WriteFile/test3/WriteFile.cpp diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/WriteFile/test4/CMakeLists.txt index fff886b..402a61a 100644 --- a/src/pal/tests/palsuite/file_io/WriteFile/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/WriteFile/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - writefile.c + writefile.cpp ) add_executable(paltest_writefile_test4 diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test4/writefile.c b/src/pal/tests/palsuite/file_io/WriteFile/test4/writefile.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/WriteFile/test4/writefile.c rename to src/pal/tests/palsuite/file_io/WriteFile/test4/writefile.cpp diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test5/CMakeLists.txt b/src/pal/tests/palsuite/file_io/WriteFile/test5/CMakeLists.txt index 978eb7f..f1f5037 100644 --- a/src/pal/tests/palsuite/file_io/WriteFile/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/WriteFile/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - writefile.c + writefile.cpp ) add_executable(paltest_writefile_test5 diff --git a/src/pal/tests/palsuite/file_io/WriteFile/test5/writefile.c b/src/pal/tests/palsuite/file_io/WriteFile/test5/writefile.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/WriteFile/test5/writefile.c rename to src/pal/tests/palsuite/file_io/WriteFile/test5/writefile.cpp diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/CMakeLists.txt index 91b7db1..4c4f641 100644 --- a/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_errorpathnotfound_test1 diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/test1.c b/src/pal/tests/palsuite/file_io/errorpathnotfound/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/errorpathnotfound/test1/test1.c rename to src/pal/tests/palsuite/file_io/errorpathnotfound/test1/test1.cpp diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/CMakeLists.txt b/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/CMakeLists.txt index 7d525c2..284933f 100644 --- a/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_errorpathnotfound_test2 diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/test2.c b/src/pal/tests/palsuite/file_io/errorpathnotfound/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/errorpathnotfound/test2/test2.c rename to src/pal/tests/palsuite/file_io/errorpathnotfound/test2/test2.cpp diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/test3/CMakeLists.txt b/src/pal/tests/palsuite/file_io/errorpathnotfound/test3/CMakeLists.txt index c7434f3..b418c9d 100644 --- a/src/pal/tests/palsuite/file_io/errorpathnotfound/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/errorpathnotfound/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_errorpathnotfound_test3 diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/test3/test3.c b/src/pal/tests/palsuite/file_io/errorpathnotfound/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/errorpathnotfound/test3/test3.c rename to src/pal/tests/palsuite/file_io/errorpathnotfound/test3/test3.cpp diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/test4/CMakeLists.txt b/src/pal/tests/palsuite/file_io/errorpathnotfound/test4/CMakeLists.txt index f8062fd..e0322dd 100644 --- a/src/pal/tests/palsuite/file_io/errorpathnotfound/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/errorpathnotfound/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_errorpathnotfound_test4 diff --git a/src/pal/tests/palsuite/file_io/errorpathnotfound/test4/test4.c b/src/pal/tests/palsuite/file_io/errorpathnotfound/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/errorpathnotfound/test4/test4.c rename to src/pal/tests/palsuite/file_io/errorpathnotfound/test4/test4.cpp diff --git a/src/pal/tests/palsuite/file_io/gettemppatha/test1/CMakeLists.txt b/src/pal/tests/palsuite/file_io/gettemppatha/test1/CMakeLists.txt index 2aff599..9869c9c 100644 --- a/src/pal/tests/palsuite/file_io/gettemppatha/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/file_io/gettemppatha/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - gettemppatha.c + gettemppatha.cpp ) add_executable(paltest_gettemppatha_test1 diff --git a/src/pal/tests/palsuite/file_io/gettemppatha/test1/gettemppatha.c b/src/pal/tests/palsuite/file_io/gettemppatha/test1/gettemppatha.cpp similarity index 100% rename from src/pal/tests/palsuite/file_io/gettemppatha/test1/gettemppatha.c rename to src/pal/tests/palsuite/file_io/gettemppatha/test1/gettemppatha.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CMakeLists.txt index 3fc399f..a573dae 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/CMakeLists.txt @@ -17,7 +17,7 @@ add_subdirectory(LockFile) add_subdirectory(MapViewOfFile) add_subdirectory(OpenFileMappingA) add_subdirectory(OpenFileMappingW) -add_subdirectory(ReadProcessMemory) +add_subdirectory(ProbeMemory) add_subdirectory(RtlMoveMemory) add_subdirectory(UnlockFile) add_subdirectory(UnmapViewOfFile) diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CMakeLists.txt index 36084bf..c38015e 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateFileMapping.c + CreateFileMapping.cpp ) add_executable(paltest_createfilemappinga_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CreateFileMapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CreateFileMapping.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CreateFileMapping.c rename to src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test1/CreateFileMapping.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CMakeLists.txt index 374f8f0..fc152c8 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateFileMapping.c + CreateFileMapping.cpp ) add_executable(paltest_createfilemappinga_test3 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CreateFileMapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CreateFileMapping.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CreateFileMapping.c rename to src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test3/CreateFileMapping.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CMakeLists.txt index 665b10a..bbb4dea 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateFileMapping.c + CreateFileMapping.cpp ) add_executable(paltest_createfilemappinga_test4 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CreateFileMapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CreateFileMapping.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CreateFileMapping.c rename to src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test4/CreateFileMapping.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CMakeLists.txt index 6f7f3c3..b80aa21 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateFileMapping.c + CreateFileMapping.cpp ) add_executable(paltest_createfilemappinga_test5 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CreateFileMapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CreateFileMapping.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CreateFileMapping.c rename to src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test5/CreateFileMapping.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CMakeLists.txt index 2f5d98b..414127a 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateFileMapping.c + CreateFileMapping.cpp ) add_executable(paltest_createfilemappinga_test6 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CreateFileMapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CreateFileMapping.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CreateFileMapping.c rename to src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test6/CreateFileMapping.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/CMakeLists.txt index 4fd24a6..e40a5ad 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - createfilemapping.c + createfilemapping.cpp ) add_executable(paltest_createfilemappinga_test7 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/createfilemapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/createfilemapping.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/createfilemapping.c rename to src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test7/createfilemapping.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/CMakeLists.txt index ae3ee8d..d2e2007 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - createfilemapping.c + createfilemapping.cpp ) add_executable(paltest_createfilemappinga_test8 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/createfilemapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/createfilemapping.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/createfilemapping.c rename to src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test8/createfilemapping.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/CMakeLists.txt index a377632..3017dc4 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - createfilemapping.c + createfilemapping.cpp ) add_executable(paltest_createfilemappinga_test9 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/createfilemapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/createfilemapping.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/createfilemapping.c rename to src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingA/test9/createfilemapping.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CMakeLists.txt index a4ad343..2d24eca 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateFileMapping_neg.c + CreateFileMapping_neg.cpp ) add_executable(paltest_createfilemappingw_createfilemapping_neg1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CreateFileMapping_neg.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CreateFileMapping_neg.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CreateFileMapping_neg.c rename to src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/CreateFileMapping_neg1/CreateFileMapping_neg.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CMakeLists.txt index 0c569ec..a2fbfa3 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateFileMappingW.c + CreateFileMappingW.cpp ) add_executable(paltest_createfilemappingw_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CreateFileMappingW.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CreateFileMappingW.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CreateFileMappingW.c rename to src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test1/CreateFileMappingW.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CMakeLists.txt index 992645f..8552cc9 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateFileMappingW.c + CreateFileMappingW.cpp ) add_executable(paltest_createfilemappingw_test2 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CreateFileMappingW.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CreateFileMappingW.c deleted file mode 100644 index 11ff967..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CreateFileMappingW.c +++ /dev/null @@ -1,124 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: createfilemappingw.c -** -** Purpose: Positive test the CreateFileMapping API. -** Call CreateFileMapping to create a unnamed -** file-mapping object with PAGE_READONLY -** protection and SEC_IMAGE attribute in UNICODE -** -** -**============================================================*/ -#define UNICODE -#include - -int __cdecl main(int argc, char *argv[]) -{ - - HANDLE FileHandle; - HANDLE FileMappingHandle; - int err; - WCHAR *wpFileName = NULL; - char executableFileName[256]=""; - - - //Initialize the PAL environment - err = PAL_Initialize(argc, argv); - if(0 != err) - { - ExitProcess(FAIL); - } - -#if WIN32 - sprintf(executableFileName,"%s","executable.exe"); -#else - sprintf(executableFileName,"%s","executable"); -#endif - - //conver string to a unicode one - wpFileName = convert(executableFileName); - - - //create a file and return the file handle - FileHandle = CreateFile(wpFileName, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_ARCHIVE, - NULL); - - //free this memory - free(wpFileName); - - if(INVALID_HANDLE_VALUE == FileHandle) - { - Fail("Failed to call CreateFile to create a file\n"); - } - - //create a unnamed file-mapping object with file handle FileHandle - //and with PAGE_READONLY protection - FileMappingHandle = CreateFileMapping( - FileHandle, //File Handle - NULL, //not inherited - PAGE_READONLY|SEC_IMAGE, //access protection and section attribute - 0, //high-order of object size - 0, //low-orger of object size - NULL); //unnamed object - - - if(NULL == FileMappingHandle) - { - Trace("\nFailed to call CreateFileMapping to create a mapping object!\n"); - err = CloseHandle(FileHandle); - if(0 == err) - { - Fail("\nFailed to call CloseHandle API\n"); - } - Fail(""); - } - if(GetLastError() == ERROR_ALREADY_EXISTS) - { - Trace("\nFile mapping object already exists!\n"); - err = CloseHandle(FileHandle); - if(0 == err) - { - Trace("\nFailed to call CloseHandle API to close a file handle\n"); - err = CloseHandle(FileMappingHandle); - if(0 == err) - { - Fail("\nFailed to call CloseHandle API to close a mapping object handle\n"); - } - Fail(""); - } - err = CloseHandle(FileMappingHandle); - if(0 == err) - { - Fail("\nFailed to call CloseHandle API to close a mapping object handle\n"); - } - Fail(""); - } - err = CloseHandle(FileMappingHandle); - if(0 == err) - { - Trace("\nFailed to call CloseHandle API to close a mapping object handle\n"); - err = CloseHandle(FileHandle); - if(0 == err) - { - Fail("\nFailed to call CloseHandle API to close a file handle\n"); - } - Fail(""); - } - err = CloseHandle(FileHandle); - if(0 == err) - { - Fail("\nFailed to call CloseHandle API to close a file handle\n"); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CreateFileMappingW.cpp b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CreateFileMappingW.cpp new file mode 100644 index 0000000..5cc6d77 --- /dev/null +++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test2/CreateFileMappingW.cpp @@ -0,0 +1,124 @@ +// 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. + +/*============================================================= +** +** Source: createfilemappingw.c +** +** Purpose: Positive test the CreateFileMapping API. +** Call CreateFileMapping to create a unnamed +** file-mapping object with PAGE_READONLY +** protection and SEC_IMAGE attribute in UNICODE +** +** +**============================================================*/ +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE FileHandle; + HANDLE FileMappingHandle; + int err; + WCHAR *wpFileName = NULL; + char executableFileName[256]=""; + + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + +#if WIN32 + sprintf_s(executableFileName, _countof(executableFileName),"%s","executable.exe"); +#else + sprintf_s(executableFileName, _countof(executableFileName),"%s","executable"); +#endif + + //conver string to a unicode one + wpFileName = convert(executableFileName); + + + //create a file and return the file handle + FileHandle = CreateFile(wpFileName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_ARCHIVE, + NULL); + + //free this memory + free(wpFileName); + + if(INVALID_HANDLE_VALUE == FileHandle) + { + Fail("Failed to call CreateFile to create a file\n"); + } + + //create a unnamed file-mapping object with file handle FileHandle + //and with PAGE_READONLY protection + FileMappingHandle = CreateFileMapping( + FileHandle, //File Handle + NULL, //not inherited + PAGE_READONLY|SEC_IMAGE, //access protection and section attribute + 0, //high-order of object size + 0, //low-orger of object size + NULL); //unnamed object + + + if(NULL == FileMappingHandle) + { + Trace("\nFailed to call CreateFileMapping to create a mapping object!\n"); + err = CloseHandle(FileHandle); + if(0 == err) + { + Fail("\nFailed to call CloseHandle API\n"); + } + Fail(""); + } + if(GetLastError() == ERROR_ALREADY_EXISTS) + { + Trace("\nFile mapping object already exists!\n"); + err = CloseHandle(FileHandle); + if(0 == err) + { + Trace("\nFailed to call CloseHandle API to close a file handle\n"); + err = CloseHandle(FileMappingHandle); + if(0 == err) + { + Fail("\nFailed to call CloseHandle API to close a mapping object handle\n"); + } + Fail(""); + } + err = CloseHandle(FileMappingHandle); + if(0 == err) + { + Fail("\nFailed to call CloseHandle API to close a mapping object handle\n"); + } + Fail(""); + } + err = CloseHandle(FileMappingHandle); + if(0 == err) + { + Trace("\nFailed to call CloseHandle API to close a mapping object handle\n"); + err = CloseHandle(FileHandle); + if(0 == err) + { + Fail("\nFailed to call CloseHandle API to close a file handle\n"); + } + Fail(""); + } + err = CloseHandle(FileHandle); + if(0 == err) + { + Fail("\nFailed to call CloseHandle API to close a file handle\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CMakeLists.txt index 87832ff..97fd712 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateFileMappingW.c + CreateFileMappingW.cpp ) add_executable(paltest_createfilemappingw_test3 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CreateFileMappingW.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CreateFileMappingW.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CreateFileMappingW.c rename to src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test3/CreateFileMappingW.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CMakeLists.txt index f8a5c90..81f248e 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateFileMappingW.c + CreateFileMappingW.cpp ) add_executable(paltest_createfilemappingw_test4 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CreateFileMappingW.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CreateFileMappingW.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CreateFileMappingW.c rename to src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test4/CreateFileMappingW.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CMakeLists.txt index 8391fbd..df25e29 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateFileMappingW.c + CreateFileMappingW.cpp ) add_executable(paltest_createfilemappingw_test5 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CreateFileMappingW.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CreateFileMappingW.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CreateFileMappingW.c rename to src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test5/CreateFileMappingW.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CMakeLists.txt index abb62ad..852c508 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateFileMappingW.c + CreateFileMappingW.cpp ) add_executable(paltest_createfilemappingw_test6 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CreateFileMappingW.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CreateFileMappingW.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CreateFileMappingW.c rename to src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test6/CreateFileMappingW.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/CMakeLists.txt index b40cfea..68be449 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - createfilemapping.c + createfilemapping.cpp ) add_executable(paltest_createfilemappingw_test7 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/createfilemapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/createfilemapping.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/createfilemapping.c rename to src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test7/createfilemapping.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/CMakeLists.txt index 96658c1..4063310 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - createfilemapping.c + createfilemapping.cpp ) add_executable(paltest_createfilemappingw_test8 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/createfilemapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/createfilemapping.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/createfilemapping.c rename to src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test8/createfilemapping.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/CMakeLists.txt index 5a55e27..6d15fea 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - createfilemapping.c + createfilemapping.cpp ) add_executable(paltest_createfilemappingw_test9 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/createfilemapping.c b/src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/createfilemapping.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/createfilemapping.c rename to src/pal/tests/palsuite/filemapping_memmgt/CreateFileMappingW/test9/createfilemapping.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/CMakeLists.txt index 3807621..beaee83 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - dlltest.c - FreeLibrary.c + dlltest.cpp + FreeLibrary.cpp ) add_executable(paltest_freelibrary_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/FreeLibrary.c b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/FreeLibrary.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/FreeLibrary.c rename to src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/FreeLibrary.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/dlltest.c b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/dlltest.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/dlltest.c rename to src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test1/dlltest.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/CMakeLists.txt index 00b1eca..0a5e700 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_freelibrary_test2 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/test2.c b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/test2.c rename to src/pal/tests/palsuite/filemapping_memmgt/FreeLibrary/test2/test2.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/CMakeLists.txt index cec0835..03bfe06 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - dlltest.c - test1.c + dlltest.cpp + test1.cpp ) add_executable(paltest_freelibraryandexitthread_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/dlltest.c b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/dlltest.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/dlltest.c rename to src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/dlltest.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/test1.c b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/test1.c deleted file mode 100644 index 6aacfc8..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/test1.c +++ /dev/null @@ -1,183 +0,0 @@ -// 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. - -/*===================================================================== -** -** Source: test1.c (FreeLibraryAndExitThread) -** -** Purpose: Tests the PAL implementation of the FreeLibraryAndExitThread -** function. FreeLibraryAndExitThread when run will exit the -** process that it is called within, therefore we create a -** thread to run the API. Then test for the existance of the -** thread and access to the library. -** -** -**===================================================================*/ - -#include - -/*Define platform specific information*/ - -/* SHLEXT is defined only for Unix variants */ -#if defined(SHLEXT) -#define LibraryName "dlltest"SHLEXT -#else -#define LibraryName "dlltest" -#endif - -#define TIMEOUT 60000 - -BOOL PALAPI StartThreadTest(); -DWORD PALAPI CreateTestThread(LPVOID); -BOOL PALAPI TestDll(HMODULE, int); - -int __cdecl main(int argc, char* argv[]) -{ - /*Initialize the PAL*/ - if ((PAL_Initialize(argc, argv)) != 0) - { - return (FAIL); - } - - if (!StartThreadTest()) - { - Fail("ERROR: FreeLibraryAndExitThread test failed.\n"); - } - - /*Terminate the PAL*/ - PAL_Terminate(); - return PASS; - -} - - -BOOL PALAPI StartThreadTest() -{ - HMODULE hLib; - HANDLE hThread; - DWORD dwThreadId; - LPTHREAD_START_ROUTINE lpStartAddress = &CreateTestThread; - LPVOID lpParameter = lpStartAddress; - DWORD rc = -1; - /*Load library (DLL).*/ - hLib = LoadLibrary(LibraryName); - if(hLib == NULL) - { - Trace("ERROR: Unable to load library %s\n", LibraryName); - - return (FALSE); - } - - /*Start the test thread*/ - hThread = CreateThread(NULL, - (DWORD)0, - lpParameter, - hLib, - (DWORD)NULL, - &dwThreadId); - if(hThread == NULL) - { - Trace("ERROR:%u: Unable to create thread.\n", - GetLastError()); - - FreeLibrary(hLib); - return (FALSE); - } - - /*Wait on thread.*/ - rc = WaitForSingleObject(hThread, TIMEOUT); - if( rc != WAIT_OBJECT_0 ) - { - Trace("ERROR:%u: hThread=0x%4.4lx not exited by " - "FreeLibraryAndExitThread, RC[%d]\n", - GetLastError(), - hThread, rc); - -// There is a possibility that the other thread might -// still be using the library VSW:337893 -// FreeLibrary(hLib); - CloseHandle(hThread); - return (FALSE); - } - - /*Test access to DLL.*/ - if(!TestDll(hLib, 0)) - { - Trace("ERROR: TestDll function returned FALSE " - "expected TRUE\n."); - - CloseHandle(hThread); - return (FALSE); - } - - FreeLibrary(hLib); - /*Clean-up thread.*/ - CloseHandle(hThread); - - return (TRUE); -} - -BOOL PALAPI TestDll(HMODULE hLib, int testResult) -{ - int RetVal; - char FunctName[] = "DllTest"; - FARPROC DllAddr; - - /* Attempt to grab the proc address of the dll function. - * This one should succeed.*/ - if(testResult == 1) - { - DllAddr = GetProcAddress(hLib, FunctName); - if(DllAddr == NULL) - { - Trace("ERROR: Unable to load function \"%s\" library \"%s\"\n", - FunctName, - LibraryName); - return (FALSE); - } - /* Run the function in the DLL, - * to ensure that the DLL was loaded properly.*/ - RetVal = DllAddr(); - if (RetVal != 1) - { - Trace("ERROR: Unable to receive correct information from DLL! " - ":expected \"1\", returned \"%d\"\n", - RetVal); - return (FALSE); - } - } - - /* Attempt to grab the proc address of the dll function. - * This one should fail.*/ - if(testResult == 0) - { - DllAddr = GetProcAddress(hLib, FunctName); - if(DllAddr != NULL) - { - Trace("ERROR: Able to load function \"%s\" from free'd" - " library \"%s\"\n", - FunctName, - LibraryName); - return (FALSE); - } - } - return (TRUE); -} - -DWORD PALAPI CreateTestThread(LPVOID lpParam) -{ - /* Test access to DLL.*/ - TestDll(lpParam, 1); - - /*Free library and exit thread.*/ - FreeLibraryAndExitThread(lpParam, (DWORD)0); - - /* NOT REACHED */ - - /*Infinite loop, we should not get here.*/ - while(1); - - return (DWORD)0; -} - diff --git a/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/test1.cpp b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/test1.cpp new file mode 100644 index 0000000..58f6643 --- /dev/null +++ b/src/pal/tests/palsuite/filemapping_memmgt/FreeLibraryAndExitThread/test1/test1.cpp @@ -0,0 +1,183 @@ +// 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. + +/*===================================================================== +** +** Source: test1.c (FreeLibraryAndExitThread) +** +** Purpose: Tests the PAL implementation of the FreeLibraryAndExitThread +** function. FreeLibraryAndExitThread when run will exit the +** process that it is called within, therefore we create a +** thread to run the API. Then test for the existance of the +** thread and access to the library. +** +** +**===================================================================*/ + +#include + +/*Define platform specific information*/ + +/* SHLEXT is defined only for Unix variants */ +#if defined(SHLEXT) +#define LibraryName "dlltest"SHLEXT +#else +#define LibraryName "dlltest" +#endif + +#define TIMEOUT 60000 + +BOOL PALAPI StartThreadTest(); +DWORD PALAPI CreateTestThread(LPVOID); +BOOL PALAPI TestDll(HMODULE, int); + +int __cdecl main(int argc, char* argv[]) +{ + /*Initialize the PAL*/ + if ((PAL_Initialize(argc, argv)) != 0) + { + return (FAIL); + } + + if (!StartThreadTest()) + { + Fail("ERROR: FreeLibraryAndExitThread test failed.\n"); + } + + /*Terminate the PAL*/ + PAL_Terminate(); + return PASS; + +} + + +BOOL PALAPI StartThreadTest() +{ + HMODULE hLib; + HANDLE hThread; + DWORD dwThreadId; + LPTHREAD_START_ROUTINE lpStartAddress = &CreateTestThread; + LPVOID lpParameter = (LPVOID)lpStartAddress; + DWORD rc = -1; + /*Load library (DLL).*/ + hLib = LoadLibrary(LibraryName); + if(hLib == NULL) + { + Trace("ERROR: Unable to load library %s\n", LibraryName); + + return (FALSE); + } + + /*Start the test thread*/ + hThread = CreateThread(NULL, + (DWORD)0, + lpStartAddress, + hLib, + (DWORD)NULL, + &dwThreadId); + if(hThread == NULL) + { + Trace("ERROR:%u: Unable to create thread.\n", + GetLastError()); + + FreeLibrary(hLib); + return (FALSE); + } + + /*Wait on thread.*/ + rc = WaitForSingleObject(hThread, TIMEOUT); + if( rc != WAIT_OBJECT_0 ) + { + Trace("ERROR:%u: hThread=0x%4.4lx not exited by " + "FreeLibraryAndExitThread, RC[%d]\n", + GetLastError(), + hThread, rc); + +// There is a possibility that the other thread might +// still be using the library VSW:337893 +// FreeLibrary(hLib); + CloseHandle(hThread); + return (FALSE); + } + + /*Test access to DLL.*/ + if(!TestDll(hLib, 0)) + { + Trace("ERROR: TestDll function returned FALSE " + "expected TRUE\n."); + + CloseHandle(hThread); + return (FALSE); + } + + FreeLibrary(hLib); + /*Clean-up thread.*/ + CloseHandle(hThread); + + return (TRUE); +} + +BOOL PALAPI TestDll(HMODULE hLib, int testResult) +{ + int RetVal; + char FunctName[] = "DllTest"; + FARPROC DllAddr; + + /* Attempt to grab the proc address of the dll function. + * This one should succeed.*/ + if(testResult == 1) + { + DllAddr = GetProcAddress(hLib, FunctName); + if(DllAddr == NULL) + { + Trace("ERROR: Unable to load function \"%s\" library \"%s\"\n", + FunctName, + LibraryName); + return (FALSE); + } + /* Run the function in the DLL, + * to ensure that the DLL was loaded properly.*/ + RetVal = DllAddr(); + if (RetVal != 1) + { + Trace("ERROR: Unable to receive correct information from DLL! " + ":expected \"1\", returned \"%d\"\n", + RetVal); + return (FALSE); + } + } + + /* Attempt to grab the proc address of the dll function. + * This one should fail.*/ + if(testResult == 0) + { + DllAddr = GetProcAddress(hLib, FunctName); + if(DllAddr != NULL) + { + Trace("ERROR: Able to load function \"%s\" from free'd" + " library \"%s\"\n", + FunctName, + LibraryName); + return (FALSE); + } + } + return (TRUE); +} + +DWORD PALAPI CreateTestThread(LPVOID lpParam) +{ + /* Test access to DLL.*/ + TestDll(lpParam, 1); + + /*Free library and exit thread.*/ + FreeLibraryAndExitThread(lpParam, (DWORD)0); + + /* NOT REACHED */ + + /*Infinite loop, we should not get here.*/ + while(1); + + return (DWORD)0; +} + diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/CMakeLists.txt index a1128c6..9b7a610 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetModuleFileNameA.c + GetModuleFileNameA.cpp ) add_executable(paltest_getmodulefilenamea_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/GetModuleFileNameA.c b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/GetModuleFileNameA.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/GetModuleFileNameA.c rename to src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test1/GetModuleFileNameA.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/CMakeLists.txt index c35e9ac..1909be4 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetModuleFileNameA.c + GetModuleFileNameA.cpp ) add_executable(paltest_getmodulefilenamea_test2 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/GetModuleFileNameA.c b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/GetModuleFileNameA.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/GetModuleFileNameA.c rename to src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameA/test2/GetModuleFileNameA.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/CMakeLists.txt index c702d07..f3d92b1 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetModuleFileNameW.c + GetModuleFileNameW.cpp ) add_executable(paltest_getmodulefilenamew_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/GetModuleFileNameW.c b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/GetModuleFileNameW.c deleted file mode 100644 index 4c1c3b0..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/GetModuleFileNameW.c +++ /dev/null @@ -1,112 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: getmodulefilenamew.c -** -** Purpose: Test the GetModuleFileNameW to retrieve the specified module -** full path and file name in UNICODE. -** -** -**============================================================*/ -#define UNICODE -#include - -#define MODULENAMEBUFFERSIZE 1024 - -/* SHLEXT is defined only for Unix variants */ - -#if defined(SHLEXT) -#define ModuleName "librotor_pal"SHLEXT -#define Delimiter "/" -#else -#define ModuleName "rotor_pal.dll" -#define Delimiter "\\" -#endif - -int __cdecl main(int argc, char *argv[]) -{ - HMODULE ModuleHandle; - int err; - WCHAR *lpModuleName; - DWORD ModuleNameLength; - WCHAR *ModuleFileNameBuf; - char* TempBuf = NULL; - char* LastBuf = NULL; - char NewModuleFileNameBuf[MODULENAMEBUFFERSIZE+200] = ""; - - - //Initialize the PAL environment - err = PAL_Initialize(argc, argv); - if(0 != err) - { - ExitProcess(FAIL); - } - - ModuleFileNameBuf = malloc(MODULENAMEBUFFERSIZE*sizeof(WCHAR)); - - //convert a normal string to a wide one - lpModuleName = convert(ModuleName); - - //load a module - ModuleHandle = LoadLibrary(lpModuleName); - - //free the memory - free(lpModuleName); - - if(!ModuleHandle) - { - Fail("Failed to call LoadLibrary API!\n"); - } - - - //retrieve the specified module full path and file name - ModuleNameLength = GetModuleFileName( - ModuleHandle,//specified module handle - ModuleFileNameBuf,//buffer for module file name - MODULENAMEBUFFERSIZE); - - - - //convert a wide full path name to a normal one - strcpy(NewModuleFileNameBuf,convertC(ModuleFileNameBuf)); - - //strip out all full path - TempBuf = strtok(NewModuleFileNameBuf,Delimiter); - LastBuf = TempBuf; - while(NULL != TempBuf) - { - LastBuf = TempBuf; - TempBuf = strtok(NULL,Delimiter); - } - - - //free the memory - free(ModuleFileNameBuf); - - if(0 == ModuleNameLength || strcmp(ModuleName,LastBuf)) - { - Trace("\nFailed to all GetModuleFileName API!\n"); - err = FreeLibrary(ModuleHandle); - if(0 == err) - { - Fail("\nFailed to all FreeLibrary API!\n"); - } - Fail(""); - } - - - - //decrement the reference count of the loaded dll - err = FreeLibrary(ModuleHandle); - if(0 == err) - { - Fail("\nFailed to all FreeLibrary API!\n"); - } - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/GetModuleFileNameW.cpp b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/GetModuleFileNameW.cpp new file mode 100644 index 0000000..c122312 --- /dev/null +++ b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test1/GetModuleFileNameW.cpp @@ -0,0 +1,112 @@ +// 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. + +/*============================================================= +** +** Source: getmodulefilenamew.c +** +** Purpose: Test the GetModuleFileNameW to retrieve the specified module +** full path and file name in UNICODE. +** +** +**============================================================*/ +#define UNICODE +#include + +#define MODULENAMEBUFFERSIZE 1024 + +/* SHLEXT is defined only for Unix variants */ + +#if defined(SHLEXT) +#define ModuleName "librotor_pal"SHLEXT +#define Delimiter "/" +#else +#define ModuleName "rotor_pal.dll" +#define Delimiter "\\" +#endif + +int __cdecl main(int argc, char *argv[]) +{ + HMODULE ModuleHandle; + int err; + WCHAR *lpModuleName; + DWORD ModuleNameLength; + WCHAR *ModuleFileNameBuf; + char* TempBuf = NULL; + char* LastBuf = NULL; + char NewModuleFileNameBuf[MODULENAMEBUFFERSIZE+200] = ""; + + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + ModuleFileNameBuf = (WCHAR*)malloc(MODULENAMEBUFFERSIZE*sizeof(WCHAR)); + + //convert a normal string to a wide one + lpModuleName = convert(ModuleName); + + //load a module + ModuleHandle = LoadLibrary(lpModuleName); + + //free the memory + free(lpModuleName); + + if(!ModuleHandle) + { + Fail("Failed to call LoadLibrary API!\n"); + } + + + //retrieve the specified module full path and file name + ModuleNameLength = GetModuleFileName( + ModuleHandle,//specified module handle + ModuleFileNameBuf,//buffer for module file name + MODULENAMEBUFFERSIZE); + + + + //convert a wide full path name to a normal one + strcpy(NewModuleFileNameBuf,convertC(ModuleFileNameBuf)); + + //strip out all full path + TempBuf = strtok(NewModuleFileNameBuf,Delimiter); + LastBuf = TempBuf; + while(NULL != TempBuf) + { + LastBuf = TempBuf; + TempBuf = strtok(NULL,Delimiter); + } + + + //free the memory + free(ModuleFileNameBuf); + + if(0 == ModuleNameLength || strcmp(ModuleName,LastBuf)) + { + Trace("\nFailed to all GetModuleFileName API!\n"); + err = FreeLibrary(ModuleHandle); + if(0 == err) + { + Fail("\nFailed to all FreeLibrary API!\n"); + } + Fail(""); + } + + + + //decrement the reference count of the loaded dll + err = FreeLibrary(ModuleHandle); + if(0 == err) + { + Fail("\nFailed to all FreeLibrary API!\n"); + } + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/CMakeLists.txt index 857feb3..7b23e92 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetModuleFileNameW.c + GetModuleFileNameW.cpp ) add_executable(paltest_getmodulefilenamew_test2 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/GetModuleFileNameW.c b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/GetModuleFileNameW.c deleted file mode 100644 index 6009a9d..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/GetModuleFileNameW.c +++ /dev/null @@ -1,57 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -/*============================================================= -** -** Source: getmodulefilenamew.c -** -** Purpose: Positive test the GetModuleFileName API. -** Call GetModuleFileName to retrieve current process -** full path and file name by passing a NULL module handle -** in UNICODE -** -** -**============================================================*/ -#define UNICODE -#include - -#define MODULENAMEBUFFERSIZE 1024 - - -int __cdecl main(int argc, char *argv[]) -{ - - DWORD ModuleNameLength; - WCHAR *ModuleFileNameBuf; - int err; - - - //Initialize the PAL environment - err = PAL_Initialize(argc, argv); - if(0 != err) - { - ExitProcess(FAIL); - } - - ModuleFileNameBuf = malloc(MODULENAMEBUFFERSIZE*sizeof(WCHAR)); - - //retrieve the current process full path and file name - //by passing a NULL module handle - ModuleNameLength = GetModuleFileName( - NULL, //a NULL handle - ModuleFileNameBuf,//buffer for module file name - MODULENAMEBUFFERSIZE); - - //free the memory - free(ModuleFileNameBuf); - - if(0 == ModuleNameLength) - { - Fail("\nFailed to all GetModuleFileName API!\n"); - } - - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/GetModuleFileNameW.cpp b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/GetModuleFileNameW.cpp new file mode 100644 index 0000000..f23d97c --- /dev/null +++ b/src/pal/tests/palsuite/filemapping_memmgt/GetModuleFileNameW/test2/GetModuleFileNameW.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================= +** +** Source: getmodulefilenamew.c +** +** Purpose: Positive test the GetModuleFileName API. +** Call GetModuleFileName to retrieve current process +** full path and file name by passing a NULL module handle +** in UNICODE +** +** +**============================================================*/ +#define UNICODE +#include + +#define MODULENAMEBUFFERSIZE 1024 + + +int __cdecl main(int argc, char *argv[]) +{ + + DWORD ModuleNameLength; + WCHAR *ModuleFileNameBuf; + int err; + + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + ModuleFileNameBuf = (WCHAR*)malloc(MODULENAMEBUFFERSIZE*sizeof(WCHAR)); + + //retrieve the current process full path and file name + //by passing a NULL module handle + ModuleNameLength = GetModuleFileName( + NULL, //a NULL handle + ModuleFileNameBuf,//buffer for module file name + MODULENAMEBUFFERSIZE); + + //free the memory + free(ModuleFileNameBuf); + + if(0 == ModuleNameLength) + { + Fail("\nFailed to all GetModuleFileName API!\n"); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/CMakeLists.txt index 541ef8b..3dedba3 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c - testlib.c + test1.cpp + testlib.cpp ) add_executable(paltest_getprocaddress_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/test1.c b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/test1.c rename to src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/test1.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/testlib.c b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/testlib.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/testlib.c rename to src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test1/testlib.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/CMakeLists.txt index 60a5ba1..983c16f 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c - testlib.c + test2.cpp + testlib.cpp ) add_executable(paltest_getprocaddress_test2 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/test2.c b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/test2.c rename to src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/test2.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/testlib.c b/src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/testlib.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/testlib.c rename to src/pal/tests/palsuite/filemapping_memmgt/GetProcAddress/test2/testlib.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/CMakeLists.txt index 18871ab..3e9c725 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetProcessHeap.c + GetProcessHeap.cpp ) add_executable(paltest_getprocessheap_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/GetProcessHeap.c b/src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/GetProcessHeap.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/GetProcessHeap.c rename to src/pal/tests/palsuite/filemapping_memmgt/GetProcessHeap/test1/GetProcessHeap.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/CMakeLists.txt index 3a64a0c..b9ce32b 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - HeapAlloc.c + HeapAlloc.cpp ) add_executable(paltest_heapalloc_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/HeapAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/HeapAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/HeapAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test1/HeapAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/CMakeLists.txt index 5253110..1b9655d 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - HeapAlloc.c + HeapAlloc.cpp ) add_executable(paltest_heapalloc_test2 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/HeapAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/HeapAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/HeapAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test2/HeapAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/CMakeLists.txt index f0b8946..1c3845c 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - HeapAlloc.c + HeapAlloc.cpp ) add_executable(paltest_heapalloc_test3 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/HeapAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/HeapAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/HeapAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/HeapAlloc/test3/HeapAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/CMakeLists.txt index 898047a..0049122 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - HeapFree.c + HeapFree.cpp ) add_executable(paltest_heapfree_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/HeapFree.c b/src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/HeapFree.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/HeapFree.c rename to src/pal/tests/palsuite/filemapping_memmgt/HeapFree/test1/HeapFree.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/CMakeLists.txt index 1decb02..17e0127 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_heaprealloc_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/test1.c b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/test1.c deleted file mode 100644 index 497d208..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/test1.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================= -** -** Source: test1.c -** -** Purpose: Allocate some memory. Then reallocate that memory. Ensure the -** return values are correct, and also that data placed in the allocated -** memory carries over to the reallocated block. -** -** -**============================================================*/ - -#include - -int __cdecl main(int argc, char *argv[]) -{ - - HANDLE TheHeap; - char* TheMemory; - char* ReAllocMemory; - int i; - - if(PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - TheHeap = GetProcessHeap(); - - if(TheHeap == NULL) - { - Fail("ERROR: GetProcessHeap() returned NULL when it was called. " - "GetLastError() returned %d.",GetLastError()); - } - - /* Allocate 100 bytes on the heap */ - if((TheMemory = HeapAlloc(TheHeap, 0, 100)) == NULL) - { - Fail("ERROR: HeapAlloc returned NULL when it was called. " - "GetLastError() returned %d.",GetLastError()); - } - - /* Set each byte of that memory block to 'x' */ - memset(TheMemory, 'X', 100); - - /* Reallocate the memory */ - ReAllocMemory = HeapReAlloc(TheHeap, 0, TheMemory, 100); - - if(ReAllocMemory == NULL) - { - Fail("ERROR: HeapReAlloc failed to reallocate the 100 bytes of " - "heap memory. GetLastError returns %d.",GetLastError()); - } - - /* Check that each byte of the memory Reallocated is 'x' */ - - for(i=0; i<100; ++i) - { - if(ReAllocMemory[i] != 'X') - { - Fail("ERROR: Byte number %d of the reallocated memory block " - "is not set to 'X' as it should be.",i); - } - } - - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/test1.cpp b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/test1.cpp new file mode 100644 index 0000000..eedd45e --- /dev/null +++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test1/test1.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================= +** +** Source: test1.c +** +** Purpose: Allocate some memory. Then reallocate that memory. Ensure the +** return values are correct, and also that data placed in the allocated +** memory carries over to the reallocated block. +** +** +**============================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE TheHeap; + char* TheMemory; + char* ReAllocMemory; + int i; + + if(PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + TheHeap = GetProcessHeap(); + + if(TheHeap == NULL) + { + Fail("ERROR: GetProcessHeap() returned NULL when it was called. " + "GetLastError() returned %d.",GetLastError()); + } + + /* Allocate 100 bytes on the heap */ + if((TheMemory = (char*)HeapAlloc(TheHeap, 0, 100)) == NULL) + { + Fail("ERROR: HeapAlloc returned NULL when it was called. " + "GetLastError() returned %d.",GetLastError()); + } + + /* Set each byte of that memory block to 'x' */ + memset(TheMemory, 'X', 100); + + /* Reallocate the memory */ + ReAllocMemory = (char*)HeapReAlloc(TheHeap, 0, TheMemory, 100); + + if(ReAllocMemory == NULL) + { + Fail("ERROR: HeapReAlloc failed to reallocate the 100 bytes of " + "heap memory. GetLastError returns %d.",GetLastError()); + } + + /* Check that each byte of the memory Reallocated is 'x' */ + + for(i=0; i<100; ++i) + { + if(ReAllocMemory[i] != 'X') + { + Fail("ERROR: Byte number %d of the reallocated memory block " + "is not set to 'X' as it should be.",i); + } + } + + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/CMakeLists.txt index 6f55103..a923935 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_heaprealloc_test2 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/test2.c b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/test2.c deleted file mode 100644 index 13e789f..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/test2.c +++ /dev/null @@ -1,79 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: test2.c -** -** Purpose: Allocate some memory. Then reallocate that memory into less -** space than the original amount. Ensure the -** return values are correct, and also that data placed in the allocated -** memory carries over to the reallocated block. -** -** -**============================================================*/ - -#include - -int __cdecl main(int argc, char *argv[]) -{ - - HANDLE TheHeap; - char* TheMemory; - char* ReAllocMemory; - int i; - - if(PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - TheHeap = GetProcessHeap(); - - if(TheHeap == NULL) - { - Fail("ERROR: GetProcessHeap() returned NULL when it was called. " - "GetLastError() returned %d.",GetLastError()); - } - - /* Allocate 200 bytes on the heap */ - if((TheMemory = HeapAlloc(TheHeap, 0, 200)) == NULL) - { - Fail("ERROR: HeapAlloc returned NULL when it was called. " - "GetLastError() returned %d.",GetLastError()); - } - - /* Set the first 100 bytes to 'X' */ - memset(TheMemory, 'X', 100); - - /* Set the second 100 bytes to 'Z' */ - memset(TheMemory+100, 'Z', 100); - - /* Reallocate the memory to 100 bytes */ - ReAllocMemory = HeapReAlloc(TheHeap, 0, TheMemory, 100); - - if(ReAllocMemory == NULL) - { - Fail("ERROR: HeapReAlloc failed to reallocate the 100 bytes of " - "heap memory. GetLastError returns %d.",GetLastError()); - } - - /* Check that each of the first 100 bytes hasn't lost any data. - Anything beyond the first 100 might still be valid, but we can't - gaurentee it. - */ - - for(i=0; i<100; ++i) - { - /* Note: Cast to char* so the function knows the size is 1 */ - if(ReAllocMemory[i] != 'X') - { - Fail("ERROR: Byte number %d of the reallocated memory block " - "is not set to 'X' as it should be.",i); - } - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/test2.cpp b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/test2.cpp new file mode 100644 index 0000000..a7e3b2a --- /dev/null +++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test2/test2.cpp @@ -0,0 +1,79 @@ +// 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. + +/*============================================================= +** +** Source: test2.c +** +** Purpose: Allocate some memory. Then reallocate that memory into less +** space than the original amount. Ensure the +** return values are correct, and also that data placed in the allocated +** memory carries over to the reallocated block. +** +** +**============================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE TheHeap; + char* TheMemory; + char* ReAllocMemory; + int i; + + if(PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + TheHeap = GetProcessHeap(); + + if(TheHeap == NULL) + { + Fail("ERROR: GetProcessHeap() returned NULL when it was called. " + "GetLastError() returned %d.",GetLastError()); + } + + /* Allocate 200 bytes on the heap */ + if((TheMemory = (char*)HeapAlloc(TheHeap, 0, 200)) == NULL) + { + Fail("ERROR: HeapAlloc returned NULL when it was called. " + "GetLastError() returned %d.",GetLastError()); + } + + /* Set the first 100 bytes to 'X' */ + memset(TheMemory, 'X', 100); + + /* Set the second 100 bytes to 'Z' */ + memset(TheMemory+100, 'Z', 100); + + /* Reallocate the memory to 100 bytes */ + ReAllocMemory = (char*)HeapReAlloc(TheHeap, 0, TheMemory, 100); + + if(ReAllocMemory == NULL) + { + Fail("ERROR: HeapReAlloc failed to reallocate the 100 bytes of " + "heap memory. GetLastError returns %d.",GetLastError()); + } + + /* Check that each of the first 100 bytes hasn't lost any data. + Anything beyond the first 100 might still be valid, but we can't + gaurentee it. + */ + + for(i=0; i<100; ++i) + { + /* Note: Cast to char* so the function knows the size is 1 */ + if(ReAllocMemory[i] != 'X') + { + Fail("ERROR: Byte number %d of the reallocated memory block " + "is not set to 'X' as it should be.",i); + } + } + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/CMakeLists.txt index 7ad8367..2d82b6e 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_heaprealloc_test3 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/test3.c b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/test3.c deleted file mode 100644 index dea9de3..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/test3.c +++ /dev/null @@ -1,78 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: test3.c -** -** Purpose: Allocate some memory. Then reallocate that memory into a -** bigger space on the heap. Check that the first portion of the data is -** unchanged. Then set the new portion to a value, to ensure that it is -** properly writable memory. -** -** -**============================================================*/ - -#include - -int __cdecl main(int argc, char *argv[]) -{ - - HANDLE TheHeap; - char* TheMemory; - char* ReAllocMemory; - int i; - - if(PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - TheHeap = GetProcessHeap(); - - if(TheHeap == NULL) - { - Fail("ERROR: GetProcessHeap() returned NULL when it was called. " - "GetLastError() returned %d.",GetLastError()); - } - - /* Allocate 100 bytes on the heap */ - if((TheMemory = HeapAlloc(TheHeap, 0, 100)) == NULL) - { - Fail("ERROR: HeapAlloc returned NULL when it was called. " - "GetLastError() returned %d.",GetLastError()); - } - - /* Set the first 100 bytes to 'X' */ - memset(TheMemory, 'X', 100); - - /* Reallocate the memory to 200 bytes */ - ReAllocMemory = HeapReAlloc(TheHeap, 0, TheMemory, 200); - - if(ReAllocMemory == NULL) - { - Fail("ERROR: HeapReAlloc failed to reallocate the 100 bytes of " - "heap memory. GetLastError returns %d.",GetLastError()); - } - - /* Check that each of the first 100 bytes hasn't lost any data. */ - for(i=0; i<100; ++i) - { - - if(ReAllocMemory[i] != 'X') - { - Fail("ERROR: Byte number %d of the reallocated memory block " - "is not set to 'X' as it should be.",i); - } - } - - /* Beyond the first 100 bytes is valid free memory. We'll set all this - memory to a value -- though, even if HeapReAlloc didn't work, it might - still be possible to memset this memory without raising an exception. - */ - memset(ReAllocMemory+100, 'Z', 100); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/test3.cpp b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/test3.cpp new file mode 100644 index 0000000..d4139e8 --- /dev/null +++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test3/test3.cpp @@ -0,0 +1,78 @@ +// 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. + +/*============================================================= +** +** Source: test3.c +** +** Purpose: Allocate some memory. Then reallocate that memory into a +** bigger space on the heap. Check that the first portion of the data is +** unchanged. Then set the new portion to a value, to ensure that it is +** properly writable memory. +** +** +**============================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE TheHeap; + char* TheMemory; + char* ReAllocMemory; + int i; + + if(PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + TheHeap = GetProcessHeap(); + + if(TheHeap == NULL) + { + Fail("ERROR: GetProcessHeap() returned NULL when it was called. " + "GetLastError() returned %d.",GetLastError()); + } + + /* Allocate 100 bytes on the heap */ + if((TheMemory = (char*)HeapAlloc(TheHeap, 0, 100)) == NULL) + { + Fail("ERROR: HeapAlloc returned NULL when it was called. " + "GetLastError() returned %d.",GetLastError()); + } + + /* Set the first 100 bytes to 'X' */ + memset(TheMemory, 'X', 100); + + /* Reallocate the memory to 200 bytes */ + ReAllocMemory = (char*)HeapReAlloc(TheHeap, 0, TheMemory, 200); + + if(ReAllocMemory == NULL) + { + Fail("ERROR: HeapReAlloc failed to reallocate the 100 bytes of " + "heap memory. GetLastError returns %d.",GetLastError()); + } + + /* Check that each of the first 100 bytes hasn't lost any data. */ + for(i=0; i<100; ++i) + { + + if(ReAllocMemory[i] != 'X') + { + Fail("ERROR: Byte number %d of the reallocated memory block " + "is not set to 'X' as it should be.",i); + } + } + + /* Beyond the first 100 bytes is valid free memory. We'll set all this + memory to a value -- though, even if HeapReAlloc didn't work, it might + still be possible to memset this memory without raising an exception. + */ + memset(ReAllocMemory+100, 'Z', 100); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/CMakeLists.txt index 024a4ef..129d8a4 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_heaprealloc_test4 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/test4.c b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/test4.c rename to src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test4/test4.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/CMakeLists.txt index 3ab3ec1..ed3d390 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_heaprealloc_test5 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/test5.c b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/test5.c deleted file mode 100644 index 230e65e..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/test5.c +++ /dev/null @@ -1,69 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: test5.c -** -** Purpose: Allocate some memory. Then call HeapRealloc with 0 as the -** amount of memory to reallocate. This should work, essentially freeing -** the memory (though we can't verfiy this) -** -** -**============================================================*/ - -#include - -int __cdecl main(int argc, char *argv[]) -{ - - HANDLE TheHeap; - char* TheMemory; - char* ReAllocMemory; - char* ReAllocMemory2; - - if(PAL_Initialize(argc, argv) != 0) - { - return FAIL; - } - - TheHeap = GetProcessHeap(); - - if(TheHeap == NULL) - { - Fail("ERROR: GetProcessHeap() returned NULL when it was called. " - "GetLastError() returned %d.",GetLastError()); - } - - /* Allocate 100 bytes on the heap */ - if((TheMemory = HeapAlloc(TheHeap, 0, 100)) == NULL) - { - Fail("ERROR: HeapAlloc returned NULL when it was called. " - "GetLastError() returned %d.",GetLastError()); - } - - /* Set each byte of that memory block to 'x' */ - memset(TheMemory, 'X', 100); - - /* Reallocate the memory into 0 bytes */ - ReAllocMemory = HeapReAlloc(TheHeap, 0, TheMemory, 0); - - if(ReAllocMemory == NULL) - { - Fail("ERROR: HeapReAlloc failed to reallocate the 100 bytes of " - "heap memory. GetLastError returns %d.",GetLastError()); - } - - /* Reallocate the memory we just put into 0 bytes, into 100 bytes. */ - ReAllocMemory2 = HeapReAlloc(TheHeap, 0, ReAllocMemory, 100); - - if(ReAllocMemory2 == NULL) - { - Fail("ERROR: HeapReAlloc failed to reallocate the 0 bytes of " - "heap memory into 100. GetLastError returns %d.",GetLastError()); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/test5.cpp b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/test5.cpp new file mode 100644 index 0000000..fcd3837 --- /dev/null +++ b/src/pal/tests/palsuite/filemapping_memmgt/HeapReAlloc/test5/test5.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================= +** +** Source: test5.c +** +** Purpose: Allocate some memory. Then call HeapRealloc with 0 as the +** amount of memory to reallocate. This should work, essentially freeing +** the memory (though we can't verfiy this) +** +** +**============================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE TheHeap; + char* TheMemory; + char* ReAllocMemory; + char* ReAllocMemory2; + + if(PAL_Initialize(argc, argv) != 0) + { + return FAIL; + } + + TheHeap = GetProcessHeap(); + + if(TheHeap == NULL) + { + Fail("ERROR: GetProcessHeap() returned NULL when it was called. " + "GetLastError() returned %d.",GetLastError()); + } + + /* Allocate 100 bytes on the heap */ + if((TheMemory = (char*)HeapAlloc(TheHeap, 0, 100)) == NULL) + { + Fail("ERROR: HeapAlloc returned NULL when it was called. " + "GetLastError() returned %d.",GetLastError()); + } + + /* Set each byte of that memory block to 'x' */ + memset(TheMemory, 'X', 100); + + /* Reallocate the memory into 0 bytes */ + ReAllocMemory = (char*)HeapReAlloc(TheHeap, 0, TheMemory, 0); + + if(ReAllocMemory == NULL) + { + Fail("ERROR: HeapReAlloc failed to reallocate the 100 bytes of " + "heap memory. GetLastError returns %d.",GetLastError()); + } + + /* Reallocate the memory we just put into 0 bytes, into 100 bytes. */ + ReAllocMemory2 = (char*)HeapReAlloc(TheHeap, 0, ReAllocMemory, 100); + + if(ReAllocMemory2 == NULL) + { + Fail("ERROR: HeapReAlloc failed to reallocate the 0 bytes of " + "heap memory into 100. GetLastError returns %d.",GetLastError()); + } + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/CMakeLists.txt index c96e00a..f74e442 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - LocalAlloc.c + LocalAlloc.cpp ) add_executable(paltest_localalloc_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/LocalAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/LocalAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/LocalAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/LocalAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/CMakeLists.txt index 47ad76e..d92939c 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - LocalFree.c + LocalFree.cpp ) add_executable(paltest_localfree_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/LocalFree.c b/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/LocalFree.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/LocalFree.c rename to src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/LocalFree.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/CMakeLists.txt index ac7a11a..e087b08 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - LocalFree.c + LocalFree.cpp ) add_executable(paltest_localfree_test2 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/LocalFree.c b/src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/LocalFree.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/LocalFree.c rename to src/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/LocalFree.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/CMakeLists.txt index 0af0948..1d08065 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - test1.c + test1.cpp ) add_executable(paltest_lockfile_test1 @@ -20,7 +20,7 @@ target_link_libraries(paltest_lockfile_test1 set(HELPERSOURCES - helper.c + helper.cpp ) add_executable(paltest_lockfile_test1_helper diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/helper.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/helper.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/helper.c rename to src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/helper.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/test1.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/test1.c rename to src/pal/tests/palsuite/filemapping_memmgt/LockFile/test1/test1.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/CMakeLists.txt index 157c517..ca5e5fa 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_lockfile_test2 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/test2.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/test2.c rename to src/pal/tests/palsuite/filemapping_memmgt/LockFile/test2/test2.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/CMakeLists.txt index 69516de..117c715 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - test3.c + test3.cpp ) add_executable(paltest_lockfile_test3 @@ -20,7 +20,7 @@ target_link_libraries(paltest_lockfile_test3 set(HELPERSOURCES - helper.c + helper.cpp ) add_executable(paltest_lockfile_test3_helper diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/helper.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/helper.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/helper.c rename to src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/helper.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/test3.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/test3.c rename to src/pal/tests/palsuite/filemapping_memmgt/LockFile/test3/test3.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/CMakeLists.txt index fb8f674..aee1b1a 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_lockfile_test4 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/test4.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/test4.c rename to src/pal/tests/palsuite/filemapping_memmgt/LockFile/test4/test4.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/CMakeLists.txt index cc4548a..70e3db4 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - test5.c + test5.cpp ) add_executable(paltest_lockfile_test5 @@ -20,7 +20,7 @@ target_link_libraries(paltest_lockfile_test5 set(HELPERSOURCES - helper.c + helper.cpp ) add_executable(paltest_lockfile_test5_helper diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/helper.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/helper.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/helper.c rename to src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/helper.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/test5.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/test5.c rename to src/pal/tests/palsuite/filemapping_memmgt/LockFile/test5/test5.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/CMakeLists.txt index 5049977..255ecbc 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - test6.c + test6.cpp ) add_executable(paltest_lockfile_test6 @@ -20,7 +20,7 @@ target_link_libraries(paltest_lockfile_test6 set(HELPERSOURCES - helper.c + helper.cpp ) add_executable(paltest_lockfile_test6_helper diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/helper.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/helper.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/helper.c rename to src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/helper.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/test6.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/test6.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/test6.c rename to src/pal/tests/palsuite/filemapping_memmgt/LockFile/test6/test6.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/CMakeLists.txt index e8434cc..68a5b9f 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test7.c + test7.cpp ) add_executable(paltest_lockfile_test7 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/test7.c b/src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/test7.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/test7.c rename to src/pal/tests/palsuite/filemapping_memmgt/LockFile/test7/test7.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/CMakeLists.txt index ef9838d..01679e5 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - MapViewOfFile.c + MapViewOfFile.cpp ) add_executable(paltest_mapviewoffile_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/MapViewOfFile.c b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/MapViewOfFile.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/MapViewOfFile.c rename to src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test1/MapViewOfFile.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/CMakeLists.txt index 18a9d10..88f3344 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - MapViewOfFile.c + MapViewOfFile.cpp ) add_executable(paltest_mapviewoffile_test2 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/MapViewOfFile.c b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/MapViewOfFile.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/MapViewOfFile.c rename to src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test2/MapViewOfFile.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/CMakeLists.txt index 76bd327..e48ce13 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - MapViewOfFile.c + MapViewOfFile.cpp ) add_executable(paltest_mapviewoffile_test3 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/MapViewOfFile.c b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/MapViewOfFile.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/MapViewOfFile.c rename to src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test3/MapViewOfFile.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/CMakeLists.txt index 52381c5..7f6d905 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - mapviewoffile.c + mapviewoffile.cpp ) add_executable(paltest_mapviewoffile_test4 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/mapviewoffile.c b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/mapviewoffile.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/mapviewoffile.c rename to src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test4/mapviewoffile.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/CMakeLists.txt index f98a4b7..3911ffa 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - mapviewoffile.c + mapviewoffile.cpp ) add_executable(paltest_mapviewoffile_test5 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/mapviewoffile.c b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/mapviewoffile.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/mapviewoffile.c rename to src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test5/mapviewoffile.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/CMakeLists.txt index dad03aa..8199981 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - mapviewoffile.c + mapviewoffile.cpp ) add_executable(paltest_mapviewoffile_test6 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/mapviewoffile.c b/src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/mapviewoffile.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/mapviewoffile.c rename to src/pal/tests/palsuite/filemapping_memmgt/MapViewOfFile/test6/mapviewoffile.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/CMakeLists.txt index b286924..e4d87d5 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - OpenFileMappingA.c + OpenFileMappingA.cpp ) add_executable(paltest_openfilemappinga_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/OpenFileMappingA.c b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/OpenFileMappingA.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/OpenFileMappingA.c rename to src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test1/OpenFileMappingA.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/CMakeLists.txt index 3a0eff0..670346f 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - OpenFileMappingA.c + OpenFileMappingA.cpp ) add_executable(paltest_openfilemappinga_test2 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/OpenFileMappingA.c b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/OpenFileMappingA.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/OpenFileMappingA.c rename to src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test2/OpenFileMappingA.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/CMakeLists.txt index 599a09f..dab27b5 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - OpenFileMappingA.c + OpenFileMappingA.cpp ) add_executable(paltest_openfilemappinga_test3 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/OpenFileMappingA.c b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/OpenFileMappingA.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/OpenFileMappingA.c rename to src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingA/test3/OpenFileMappingA.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/CMakeLists.txt index 04e9e47..b2f4494 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - OpenFileMappingW.c + OpenFileMappingW.cpp ) add_executable(paltest_openfilemappingw_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/OpenFileMappingW.c b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/OpenFileMappingW.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/OpenFileMappingW.c rename to src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test1/OpenFileMappingW.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/CMakeLists.txt index 22e960b..655fa75 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - OpenFileMappingW.c + OpenFileMappingW.cpp ) add_executable(paltest_openfilemappingw_test2 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/OpenFileMappingW.c b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/OpenFileMappingW.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/OpenFileMappingW.c rename to src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test2/OpenFileMappingW.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/CMakeLists.txt index 5a54368..a7039a1 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - OpenFileMappingW.c + OpenFileMappingW.cpp ) add_executable(paltest_openfilemappingw_test3 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/OpenFileMappingW.c b/src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/OpenFileMappingW.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/OpenFileMappingW.c rename to src/pal/tests/palsuite/filemapping_memmgt/OpenFileMappingW/test3/OpenFileMappingW.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/CMakeLists.txt new file mode 100644 index 0000000..c6eddf7 --- /dev/null +++ b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(ProbeMemory_neg1) +add_subdirectory(test1) + diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/CMakeLists.txt new file mode 100644 index 0000000..e96c92e --- /dev/null +++ b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + ProbeMemory_neg.cpp +) + +add_executable(paltest_probememory_probememory_neg1 + ${SOURCES} +) + +add_dependencies(paltest_probememory_probememory_neg1 coreclrpal) + +target_link_libraries(paltest_probememory_probememory_neg1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/ProbeMemory_neg.cpp b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/ProbeMemory_neg.cpp new file mode 100644 index 0000000..80de809 --- /dev/null +++ b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/ProbeMemory_neg.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================= +** +** Source: ReadProcessMemory_neg.c +** +** Purpose: Negative test the ReadProcessMemory API. +** Call ReadProcessMemory to read unreadabel memory area +** +** +**============================================================*/ +#include + +#define REGIONSIZE 1024 + +int __cdecl main(int argc, char *argv[]) +{ + int err; + BOOL bResult; + LPVOID lpProcessAddress = NULL; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*allocate the virtual memory*/ + lpProcessAddress = VirtualAlloc( + NULL, /*system determine where to allocate the region*/ + REGIONSIZE, /*specify the size*/ + MEM_RESERVE, /*allocation type*/ + PAGE_READONLY); /*access protection*/ + + if(NULL == lpProcessAddress) + { + Fail("\nFailed to call VirtualAlloc API to allocate " + "virtual memory, error code=%u\n", GetLastError()); + } + + /*try to probe the unreadable memory area*/ + bResult = PAL_ProbeMemory( + lpProcessAddress, /*base of memory area*/ + REGIONSIZE, /*buffer length in bytes*/ + FALSE); /*read access*/ + + /*check the return value*/ + if(bResult) + { + Trace("\nProbeMemory for read didn't FAILED\n"); + + /*decommit the specified region*/ + err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API, error code=%u\n", GetLastError()); + } + + Fail(""); + } + + /*try to probe the unwriteable memory area*/ + bResult = PAL_ProbeMemory( + lpProcessAddress, /*base of memory area*/ + REGIONSIZE, /*buffer length in bytes*/ + FALSE); /*write access */ + + /*check the return value*/ + if(bResult) + { + Trace("\nProbeMemory for write didn't FAILED\n"); + + /*decommit the specified region*/ + err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API, error code=%u\n", GetLastError()); + } + + Fail(""); + } + + /*decommit the specified region*/ + err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API, error code=%u\n", GetLastError()); + } + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/testinfo.dat new file mode 100644 index 0000000..4d11a71 --- /dev/null +++ b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = Filemapping_memmgt +Function = PAL_ProbeMemory +Name = Negative test PAL_ProbeMemory API to read unreadable memory area +TYPE = DEFAULT +EXE1 = probememory_neg +Description +=Test the PAL_ProbeMemory to read unreadable memory area diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/CMakeLists.txt new file mode 100644 index 0000000..739ba62 --- /dev/null +++ b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + ProbeMemory.cpp +) + +add_executable(paltest_probememory_test1 + ${SOURCES} +) + +add_dependencies(paltest_probememory_test1 coreclrpal) + +target_link_libraries(paltest_probememory_test1 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/ProbeMemory.cpp b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/ProbeMemory.cpp new file mode 100644 index 0000000..30b358d --- /dev/null +++ b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/ProbeMemory.cpp @@ -0,0 +1,94 @@ +// 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. + +/*============================================================= +** +** Source: ReadProcessMemory.c +** +** Purpose: Positive test the ReadProcessMemory API. +** Call ReadProcessMemory to read memory contents +** inside current process. +** +** +**============================================================*/ +#include + +#define REGIONSIZE 1024 + +int __cdecl main(int argc, char *argv[]) +{ + int err; + BOOL bResult; + LPVOID lpProcessAddress = NULL; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*allocate the virtual memory*/ + lpProcessAddress = VirtualAlloc( + NULL, /*system determine where to allocate the region*/ + REGIONSIZE, /*specify the size*/ + MEM_COMMIT, /*allocation type*/ + PAGE_READWRITE); /*access protection*/ + + if(NULL == lpProcessAddress) + { + Fail("\nFailed to call VirtualAlloc API to allocate " + "virtual memory, error code=%u!\n", GetLastError()); + } + + /*probe the memory for read*/ + bResult = PAL_ProbeMemory( + lpProcessAddress, /*base of memory area*/ + REGIONSIZE, /*buffer length in bytes*/ + FALSE); /*read access*/ + + if(!bResult) + { + Trace("\nProbeMemory for read access FAILED\n"); + + /*decommit the specified region*/ + err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API, error code=%u\n", GetLastError()); + } + + Fail(""); + } + + /*probe the memory for write */ + bResult = PAL_ProbeMemory( + lpProcessAddress, /*base of memory area*/ + REGIONSIZE, /*buffer length in bytes*/ + TRUE); /*write access*/ + + if(!bResult) + { + Trace("\nProbeMemory for write access FAILED\n"); + + /*decommit the specified region*/ + err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API, error code=%u\n", GetLastError()); + } + + Fail(""); + } + + /*decommit the specified region*/ + err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); + if(0 == err) + { + Fail("\nFailed to call VirtualFree API, error code=%u\n", GetLastError()); + } + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/testinfo.dat new file mode 100644 index 0000000..512b945 --- /dev/null +++ b/src/pal/tests/palsuite/filemapping_memmgt/ProbeMemory/test1/testinfo.dat @@ -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. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = Filemapping_memmgt +Function = PAL_ProbeMemory +Name = Positive test for PAL_ProbeMemory API to probe for read/write +TYPE = DEFAULT +EXE1 = probememory +Description +=Test the PAL_ProbeMemory to probe for read and write diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/CMakeLists.txt deleted file mode 100644 index d2ae61f..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -add_subdirectory(ReadProcessMemory_neg1) -add_subdirectory(test1) -add_subdirectory(test2) - diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/CMakeLists.txt deleted file mode 100644 index 400c921..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - ReadProcessMemory_neg.c -) - -add_executable(paltest_readprocessmemory_readprocessmemory_neg1 - ${SOURCES} -) - -add_dependencies(paltest_readprocessmemory_readprocessmemory_neg1 coreclrpal) - -target_link_libraries(paltest_readprocessmemory_readprocessmemory_neg1 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/ReadProcessMemory_neg.c b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/ReadProcessMemory_neg.c deleted file mode 100644 index aecd5ad..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/ReadProcessMemory_neg.c +++ /dev/null @@ -1,127 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: ReadProcessMemory_neg.c -** -** Purpose: Negative test the ReadProcessMemory API. -** Call ReadProcessMemory to read unreadabel memory area -** -** -**============================================================*/ -#include - -#define REGIONSIZE 1024 - -int __cdecl main(int argc, char *argv[]) -{ - int err; - BOOL bResult; - HANDLE ProcessHandle; - DWORD ProcessID; - LPVOID lpProcessAddress = NULL; - char ProcessBuffer[REGIONSIZE]; - ULONG_PTR size = 0; - - - /*Initialize the PAL environment*/ - err = PAL_Initialize(argc, argv); - if(0 != err) - { - return FAIL; - } - - /*retrieve the current process ID*/ - ProcessID = GetCurrentProcessId(); - - /*retrieve the current process handle*/ - ProcessHandle = OpenProcess( - PROCESS_ALL_ACCESS, - FALSE, /*not inherited*/ - ProcessID); - - if(NULL == ProcessHandle) - { - Fail("\nFailed to call OpenProcess API to retrieve " - "current process handle error code=%u\n", - GetLastError()); - } - - - - /*allocate the virtual memory*/ - lpProcessAddress = VirtualAlloc( - NULL, /*system determine where to allocate the region*/ - REGIONSIZE, /*specify the size*/ - MEM_RESERVE, /*allocation type*/ - PAGE_READONLY); /*access protection*/ - - if(NULL == lpProcessAddress) - { - Fail("\nFailed to call VirtualAlloc API to allocate " - "virtual memory, error code=%u\n", GetLastError()); - } - - /*zero the memory*/ - memset(ProcessBuffer, 0, REGIONSIZE); - /*try to retrieve the unreadable memory area*/ - bResult = ReadProcessMemory( - ProcessHandle, /*current process handle*/ - lpProcessAddress, /*base of memory area*/ - (LPVOID)ProcessBuffer, - REGIONSIZE, /*buffer length in bytes*/ - &size); - - - /*check the return value*/ - if(0 != bResult) - { - Trace("\nFailed to call ReadProcessMemory API for a negative test, " - "Try to read an unreadable memory area will cause fail " - "but it successes\n"); - - err = CloseHandle(ProcessHandle); - if(0 == err) - { - Trace("\nFailed to call CloseHandle API, error code=%u\n", - GetLastError()); - } - - /*decommit the specified region*/ - err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); - if(0 == err) - { - Trace("\nFailed to call VirtualFree API, error code=%u\n", - GetLastError()); - } - Fail(""); - } - - err = CloseHandle(ProcessHandle); - if(0 == err) - { - Trace("\nFailed to call CloseHandle API, error code = %u\n", - GetLastError()); - - err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); - if(0 == err) - { - Trace("\nFailed to call VirtualFree API, error code=%u\n", - GetLastError()); - } - - Fail(""); - } - /*decommit the specified region*/ - err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); - if(0 == err) - { - Fail("\nFailed to call VirtualFree API, error code=%u\n", - GetLastError()); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/testinfo.dat deleted file mode 100644 index 08c8f32..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = Filemapping_memmgt -Function = ReadProcessMemory -Name = Negative test ReadProcessMemory API to read unreadable memory area -TYPE = DEFAULT -EXE1 = readprocessmemory_neg -Description -=Test the ReadProcessMemory to read unreadable memory area diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/CMakeLists.txt deleted file mode 100644 index 8c21f01..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - ReadProcessMemory.c -) - -add_executable(paltest_readprocessmemory_test1 - ${SOURCES} -) - -add_dependencies(paltest_readprocessmemory_test1 coreclrpal) - -target_link_libraries(paltest_readprocessmemory_test1 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/ReadProcessMemory.c b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/ReadProcessMemory.c deleted file mode 100644 index c9475f1..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/ReadProcessMemory.c +++ /dev/null @@ -1,126 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: ReadProcessMemory.c -** -** Purpose: Positive test the ReadProcessMemory API. -** Call ReadProcessMemory to read memory contents -** inside current process. -** -** -**============================================================*/ -#include - -#define REGIONSIZE 1024 - -int __cdecl main(int argc, char *argv[]) -{ - int err; - BOOL bResult; - HANDLE ProcessHandle; - DWORD ProcessID; - LPVOID lpProcessAddress = NULL; - char ProcessBuffer[REGIONSIZE]; - ULONG_PTR size = 0; - - - /*Initialize the PAL environment*/ - err = PAL_Initialize(argc, argv); - if(0 != err) - { - return FAIL; - } - - /*retrieve the current process ID*/ - ProcessID = GetCurrentProcessId(); - - /*retrieve the current process handle*/ - ProcessHandle = OpenProcess( - PROCESS_VM_READ,/*access flag*/ - FALSE, /*not inherited*/ - ProcessID); - - if(NULL == ProcessHandle) - { - Fail("\nFailed to call OpenProcess API to retrieve " - "current process handle error code=%u\n", - GetLastError()); - } - - /*allocate the virtual memory*/ - lpProcessAddress = VirtualAlloc( - NULL, /*system determine where to allocate the region*/ - REGIONSIZE, /*specify the size*/ - MEM_COMMIT, /*allocation type*/ - PAGE_READONLY); /*access protection*/ - - if(NULL == lpProcessAddress) - { - Fail("\nFailed to call VirtualAlloc API to allocate " - "virtual memory, error code=%u!\n", GetLastError()); - } - - /*zero the memory*/ - memset(ProcessBuffer, 0, REGIONSIZE); - - /*retrieve the memory contents*/ - bResult = ReadProcessMemory( - ProcessHandle, /*current process handle*/ - lpProcessAddress, /*base of memory area*/ - (LPVOID)ProcessBuffer, - REGIONSIZE, /*buffer length in bytes*/ - &size); - - if(!bResult || REGIONSIZE != size) - { - Trace("\nFailed to call ReadProcessMemory API " - "to retrieve the memory contents, error code=%u\n", - GetLastError()); - - err = CloseHandle(ProcessHandle); - if(0 == err) - { - Trace("\nFailed to call CloseHandle API, error code=%u\n", - GetLastError()); - } - - /*decommit the specified region*/ - err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); - if(0 == err) - { - Trace("\nFailed to call VirtualFree API, error code=%u\n", - GetLastError()); - } - Fail(""); - } - - err = CloseHandle(ProcessHandle); - if(0 == err) - { - Trace("\nFailed to call CloseHandle API, error code = %u\n", - GetLastError()); - - err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); - if(0 == err) - { - Trace("\nFailed to call VirtualFree API, error code=%u\n", - GetLastError()); - } - - Fail(""); - } - - /*decommit the specified region*/ - err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT); - if(0 == err) - { - Fail("\nFailed to call VirtualFree API, error code=%u\n", - GetLastError()); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/testinfo.dat deleted file mode 100644 index c56920d..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = Filemapping_memmgt -Function = ReadProcessMemory -Name = Positive test for ReadProcessMemory API to read memory contents -TYPE = DEFAULT -EXE1 = readprocessmemory -Description -=Test the ReadProcessMemory to read the memory contents diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/CMakeLists.txt deleted file mode 100644 index 9e0de95..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(TESTSOURCES - test2.c -) - -add_executable(paltest_readprocessmemory_test2 - ${TESTSOURCES} -) - -add_dependencies(paltest_readprocessmemory_test2 coreclrpal) - -target_link_libraries(paltest_readprocessmemory_test2 - pthread - m - coreclrpal -) - - -set(HELPERSOURCES - helper.c -) - -add_executable(paltest_readprocessmemory_test2_helper - ${HELPERSOURCES} -) - -add_dependencies(paltest_readprocessmemory_test2_helper coreclrpal) - -target_link_libraries(paltest_readprocessmemory_test2_helper - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/commonconsts.h b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/commonconsts.h deleted file mode 100644 index 433d820..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/commonconsts.h +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================= -** -** Source: commonconsts.h -** -** -**============================================================*/ - -#ifndef _COMMONCONSTS_H_ -#define _COMMONCONSTS_H_ - -#include -#define REGIONSIZE 1024 - -const int TIMEOUT = 40000; - -const WCHAR szcToHelperEvName[] = { 'T', 'o', '\0' }; -const WCHAR szcFromHelperEvName[] = { 'F', 'r', 'o', 'm', '\0' }; - -const char initialValue = '-'; -const char nextValue = '|'; -const char guardValue = '*'; -const char *commsFileName = "AddrNLen.dat"; - - -/* PEDANTIC and PEDANTIC0 is a helper macro that just grumps about any - * zero return codes in a generic way. with little typing */ -#define PEDANTIC(function, parameters) \ -{ \ - if (! (function parameters) ) \ - { \ - Trace("%s: NonFatal failure of %s%s for reasons %u and %u\n", \ - __FILE__, #function, #parameters, GetLastError(), errno); \ - } \ -} -#define PEDANTIC1(function, parameters) \ -{ \ - if ( (function parameters) ) \ - { \ - Trace("%s: NonFatal failure of %s%s for reasons %u and %u\n", \ - __FILE__, #function, #parameters, GetLastError(), errno); \ - } \ -} - -#endif diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/helper.c b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/helper.c deleted file mode 100644 index 59e882f..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/helper.c +++ /dev/null @@ -1,249 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: helper.c -** -** Purpose: This helper process sets up a several blocks of memory, -** then uses a file to tell its parent process where that memory is -** So it can do a WriteProcessMemory on it. When the parent process is done -** we check here that it was written properly. -** -** -**============================================================*/ - -#include "commonconsts.h" - -#include - -#if defined(BIT64) && defined(PLATFORM_UNIX) -#define LLFORMAT "%I64u" -#else -#define LLFORMAT "%u" -#endif - -struct allhandles_t -{ - HANDLE hEvToHelper; - HANDLE hEvFromHelper; - char *valuesFileName; -}; - - -/* function: wpmDoIt - * - * This is a general WriteProcessMemory testing function that sets up - * the RAM pointed to and tells the companion process on the other end - * of the handles in 'Comms' to attempt to alter 'lenDest' bytes at - * '*pDest'. - * - * '*pBuffer'[0..'lenBuffer'] is expected to be a guard region - * surrounding the '*pDest'[0..'lenDest'] region so that this function - * can verify that only the proper bytes were altered. - */ - -int wpmDoIt(struct allhandles_t Comms, - char * pBuffer, unsigned int lenBuffer, - char * pDest, unsigned int lenDest, - const char* storageDescription) -{ - char *pCurr; - FILE *commsFile; - DWORD dwRet; - - if (pBuffer > pDest || lenDest > lenBuffer) - { - Trace("WriteProcessMemory::DoIt() test implementation: " - "(pBuffer > pDest || lenDest > lenBuffer)\n"); - return FALSE; - } - - /* set up the storage */ - memset(pBuffer, guardValue, lenBuffer); - memset(pDest, initialValue, lenDest); - - /* tell the parent what RAM to adjust */ - if(!(commsFile = fopen(Comms.valuesFileName, "w"))) - { - Trace("WriteProcessMemory: fopen of '%S' failed (%u). \n", - Comms.valuesFileName, GetLastError()); - return FALSE; - } - if (!fprintf(commsFile, LLFORMAT " " LLFORMAT " '%s'\n", - pDest, lenDest, storageDescription)) - { - Trace("WriteProcessMemory: fprintf to '%S' failed (%u). \n", - Comms.valuesFileName, GetLastError()); - return FALSE; - } - PEDANTIC1(fclose, (commsFile)); - - /* Tell the parent the data is ready for it to adjust */ - PEDANTIC(ResetEvent, (Comms.hEvToHelper)); - PEDANTIC(SetEvent, (Comms.hEvFromHelper)); - - dwRet = WaitForSingleObject(Comms.hEvToHelper, TIMEOUT); /* parent is done */ - if (dwRet != WAIT_OBJECT_0) - { - Trace("helper WaitForSingleObjectTest: WaitForSingleObject " - "failed (%u)\n", GetLastError()); - return FALSE; - } - - /* check the stuff that SHOULD have changed */ - for (pCurr = pDest; pCurr < (pDest + lenDest); pCurr++) - { - if ( *pCurr != nextValue) - { - Trace("When testing '%s': alteration test failed " - "at " LLFORMAT " offset " LLFORMAT " Found '%c' instead of '%c'\n.", - storageDescription, pDest, pCurr - pDest, *pCurr, nextValue); - Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer); - return FALSE; - } - } - /* check the stuff that should NOT have changed */ - for (pCurr = pBuffer; pCurr < pDest; pCurr++ ) - { - if ( *pCurr != guardValue) - { - Trace("When testing '%s': leading guard zone test failed " - "at " LLFORMAT " offset " LLFORMAT ". Found '%c' instead of '%c'\n.", - storageDescription, pDest, pCurr - pBuffer, *pCurr, guardValue); - Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer); - return FALSE; - } - } - for (pCurr = pDest + lenDest; pCurr < (pBuffer + lenBuffer); pCurr++ ) - { - if ( *pCurr != guardValue) - { - Trace("When testing '%s': trailing guard zone test failed " - "at " LLFORMAT " offset " LLFORMAT ". Found '%c' instead of '%c'\n.", - storageDescription, pDest + lenDest, pCurr - pBuffer, *pCurr, guardValue); - Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer); - return FALSE; - } - } - - return TRUE; -} - -int __cdecl main(int argc, char *argv[]) -{ - - BOOL success = TRUE; /* assume success */ - struct allhandles_t Comms = {0,0,0} ; - - /* variables to track storage to alter */ - char *pTarget = NULL; - unsigned int sizeTarget; - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* hook up with the events created by the parent */ - Comms.hEvToHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcToHelperEvName); - if (!Comms.hEvToHelper) - { - Fail("WriteProcessMemory: OpenEvent of '%S' failed (%u). " - "(the event should already exist!)\n", - szcToHelperEvName, GetLastError()); - } - Comms.hEvFromHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcFromHelperEvName); - if (!Comms.hEvToHelper) - { - Trace("WriteProcessMemory: OpenEvent of '%S' failed (%u). " - "(the event should already exist!)\n", - szcFromHelperEvName, GetLastError()); - success = FALSE; - goto EXIT; - } - Comms.valuesFileName = argv[1]; - - { - char autoAllocatedOnStack[51]; - - /* Get the parent process to write to the local stack */ - success &= wpmDoIt(Comms, autoAllocatedOnStack, - sizeof(autoAllocatedOnStack), - autoAllocatedOnStack + sizeof(int), - sizeof(autoAllocatedOnStack) - 2 * sizeof(int), - "const size array on stack with int sized guards"); - } - - /* Get the parent process to write to stuff on the heap */ - sizeTarget = 2 * sizeof(int) + 23 ; /* 23 is just a random prime > 16 */ - if (!(pTarget = malloc(sizeTarget))) - { - Trace("WriteProcessMemory helper: unable to allocate '%s'->%d bytes of memory" - "(%u).\n", - argv[3], sizeTarget, GetLastError()); - success = FALSE; - goto EXIT; - - } - success &= wpmDoIt(Comms, pTarget, sizeTarget, - pTarget + sizeof(int), - sizeTarget - 2 * sizeof(int), - "array on heap with int sized guards"); - - /* just to be nice try something 16 - 2 * sizeof(int) bytes long */ - { - char autoAllocatedOnStack[16]; - - /* Get the parent process to write to the local stack */ - success &= wpmDoIt(Comms, autoAllocatedOnStack, - sizeof(autoAllocatedOnStack), - autoAllocatedOnStack + sizeof(int), - sizeof(autoAllocatedOnStack) - 2 * sizeof(int), - "another 16 byte array on stack with int sized guards inside"); - } - - /* NOTE: Don't try 0 bytes long. Win32 WriteProcessMemory claims - * it writes 8 bytes in that case! */ - - /* and 1 byte long... */ - { - char autoAllocatedOnStack[1+ 2 * sizeof(int)]; - - /* Get the parent process to write to the local stack */ - success &= wpmDoIt(Comms, autoAllocatedOnStack, - sizeof(autoAllocatedOnStack), - autoAllocatedOnStack + sizeof(int), - 1, - "no bytes with int sized guards outside on stack"); - } - - -EXIT: - /* Tell the parent that we are done */ - if (!DeleteFile(Comms.valuesFileName)) - { - Trace("helper: DeleteFile failed so parent (test1) is unlikely " - "to exit cleanly\n"); - } - PEDANTIC(ResetEvent, (Comms.hEvToHelper)); - if (!SetEvent(Comms.hEvFromHelper)) - { - Trace("helper: SetEvent failed so parent (test1) is unlikely " - "to exit cleanly\n"); - } - - free(pTarget); - PEDANTIC(CloseHandle, (Comms.hEvToHelper)); - PEDANTIC(CloseHandle, (Comms.hEvFromHelper)); - - if (!success) - { - Fail(""); - } - - PAL_Terminate(); - - return success ? PASS : FAIL; -} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/test2.c b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/test2.c deleted file mode 100644 index eda4059..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/test2.c +++ /dev/null @@ -1,258 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: test2.c -** -** Purpose: Create a child process and some events for communications with it. -** When the child gets back to us with a memory location and a length, -** Call WriteProcessMemory on this location and check to see that it -** writes successfully. Then call ReadProcessMemory to check if the -** contents read are same as those written -** -** -**============================================================*/ - -#define UNICODE - -#include "commonconsts.h" - -#include - -#if defined(BIT64) && defined(PLATFORM_UNIX) -#define LLFORMAT "%I64u" -#else -#define LLFORMAT "%u" -#endif - -int __cdecl main(int argc, char *argv[]) -{ - - PROCESS_INFORMATION pi; - STARTUPINFO si; - HANDLE hEvToHelper; - HANDLE hEvFromHelper; - DWORD dwExitCode; - - DWORD dwRet; - char cmdComposeBuf[MAX_PATH]; - PWCHAR uniString; - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* Create the signals we need for cross process communication */ - hEvToHelper = CreateEvent(NULL, TRUE, FALSE, szcToHelperEvName); - if (!hEvToHelper) - { - Fail("WriteProcessMemory: CreateEvent of '%S' failed. " - "GetLastError() returned %d.\n", szcToHelperEvName, - GetLastError()); - } - if (GetLastError() == ERROR_ALREADY_EXISTS) - { - Fail("WriteProcessMemory: CreateEvent of '%S' failed. " - "(already exists!)\n", szcToHelperEvName); - } - hEvFromHelper = CreateEvent(NULL, TRUE, FALSE, szcFromHelperEvName); - if (!hEvToHelper) - { - Fail("WriteProcessMemory: CreateEvent of '%S' failed. " - "GetLastError() returned %d.\n", szcFromHelperEvName, - GetLastError()); - } - if (GetLastError() == ERROR_ALREADY_EXISTS) - { - Fail("WriteProcessMemory: CreateEvent of '%S' failed. " - "(already exists!)\n", szcFromHelperEvName); - } - ResetEvent(hEvFromHelper); - ResetEvent(hEvToHelper); - - if (!sprintf(cmdComposeBuf, "helper %s", commsFileName)) - { - Fail("Could not convert command line\n"); - } - uniString = convert(cmdComposeBuf); - - ZeroMemory( &si, sizeof(si) ); - si.cb = sizeof(si); - ZeroMemory( &pi, sizeof(pi) ); - - /* Create a new process. This is the process that will ask for - * memory munging */ - if(!CreateProcess( NULL, uniString, NULL, NULL, - FALSE, 0, NULL, NULL, &si, &pi)) - { - Trace("ERROR: CreateProcess failed to load executable '%S'. " - "GetLastError() returned %u.\n", - uniString, GetLastError()); - free(uniString); - Fail(""); - } - free(uniString); - - - while(1) - { - FILE *commsFile; - char* pSrcMemory; - char* pDestMemory; - SIZE_T Count; - SIZE_T wpmCount; - char incomingCMDBuffer[MAX_PATH + 1]; - - int err; - HANDLE readProcessHandle; - DWORD readProcessID; - char readProcessBuffer[REGIONSIZE]; // size 1024 - BOOL bResult; - size_t size = 0; - - readProcessID = pi.dwProcessId; - - /* wait until the helper tells us that it has given us - * something to do */ - dwRet = WaitForSingleObject(hEvFromHelper, TIMEOUT); - if (dwRet != WAIT_OBJECT_0) - { - Trace("test1 WaitForSingleObjectTest: WaitForSingleObject " - "failed (%u)\n", GetLastError()); - break; /* no more work incoming */ - } - - /* get the parameters to test WriteProcessMemory with */ - if (!(commsFile = fopen(commsFileName, "r"))) - { - /* no file means there is no more work */ - break; - } - if ( NULL == fgets(incomingCMDBuffer, MAX_PATH, commsFile)) - { - Fail ("unable to read from communication file %s " - "for reasons %u & %u\n", - errno, GetLastError()); - } - PEDANTIC1(fclose,(commsFile)); - sscanf(incomingCMDBuffer, LLFORMAT " " LLFORMAT, &pDestMemory, &Count); - if (argc > 1) - { - Trace("Preparing to write to " LLFORMAT " bytes @ " LLFORMAT "('%s')\n", - Count, pDestMemory, incomingCMDBuffer); - } - - /* compose some data to write to the client process */ - if (!(pSrcMemory = malloc(Count))) - { - Trace("could not dynamically allocate memory to copy from " - "for reasons %u & %u\n", - errno, GetLastError()); - goto doneIteration; - } - memset(pSrcMemory, nextValue, Count); - Trace("Preparing to write to " LLFORMAT " bytes @ " LLFORMAT " ('%s')[%u]\n", - Count, pDestMemory, incomingCMDBuffer, pSrcMemory); - - /* do the work */ - dwRet = WriteProcessMemory(pi.hProcess, - pDestMemory, - pSrcMemory, - Count, - &wpmCount); - - if (!dwRet) - { - Trace("%s: Problem: on a write to "LLFORMAT " bytes @ " LLFORMAT " ('%s')\n", - argv[0], Count, pDestMemory, incomingCMDBuffer); - Trace("test1 WriteProcessMemory returned a (!=0) (GLE=%u)\n", - GetLastError()); - } - if(Count != wpmCount) - { - Trace("%s: Problem: on a write to " LLFORMAT " bytes @ " LLFORMAT " ('%s')\n", - argv[0], Count, pDestMemory, incomingCMDBuffer); - Trace("The number of bytes written should have been " - LLFORMAT ", but was reported as " LLFORMAT " \n", Count, wpmCount); - } - - readProcessHandle = OpenProcess( - PROCESS_VM_READ, - FALSE, - readProcessID); - - if(NULL == readProcessHandle) - { - Fail("\nFailed to call OpenProcess API to retrieve " - "current process handle error code=%u\n", - GetLastError()); - } - - /*zero the memory*/ - memset(readProcessBuffer, 0, size); - - /*retrieve the memory contents*/ - bResult = ReadProcessMemory( - readProcessHandle, /*current process handle*/ - pDestMemory, /*base of memory area*/ - (LPVOID)readProcessBuffer, - Count, /*buffer length in bytes*/ - &size); - - - if( !bResult || (Count != size) ) - { - Trace("\nFailed to call ReadProcessMemory API " - "to retrieve the memory contents, error code=%u; Bresult[%u] Count[" LLFORMAT "], Size[%d]\n", - GetLastError(), bResult, Count, size); - - err = CloseHandle(readProcessHandle); - - if(0 == err) - { - Trace("\nFailed to call CloseHandle API, error code=%u\n", - GetLastError()); - } - dwExitCode = FAIL; - } - - if( !memcmp (pDestMemory, readProcessBuffer, Count ) ) - { - Trace("Difference in memory contents, expected [%s], but received [%s]\n", pDestMemory, readProcessBuffer); - dwExitCode = FAIL; - } - - Trace("ReadProcessBuffer contains [%s]\n", readProcessBuffer); - err = CloseHandle(readProcessHandle); - - free(pSrcMemory); - - doneIteration: - PEDANTIC(ResetEvent, (hEvFromHelper)); - PEDANTIC(SetEvent, (hEvToHelper)); - } - - /* wait for the child process to complete */ - WaitForSingleObject ( pi.hProcess, TIMEOUT ); - /* this may return a failure code on a success path */ - - /* check the exit code from the process */ - if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) ) - { - Trace( "GetExitCodeProcess call failed with error code %u\n", - GetLastError() ); - dwExitCode = FAIL; - } - - - PEDANTIC(CloseHandle, (hEvToHelper)); - PEDANTIC(CloseHandle, (hEvFromHelper)); - PEDANTIC(CloseHandle, (pi.hThread)); - PEDANTIC(CloseHandle, (pi.hProcess)); - - PAL_TerminateEx(dwExitCode); - return dwExitCode; -} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/testinfo.dat deleted file mode 100644 index 58a9935..0000000 --- a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/testinfo.dat +++ /dev/null @@ -1,18 +0,0 @@ -# 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. - -Version = 1.0 -Section = Debug -Function = ReadProcessMemory -Name = Check that writing/reading text to/from process memory succeeds. -TYPE = DEFAULT -EXE1 = test2 -EXE2 = helper -Description -= Create a child process and attempt to write to its memory -= at the places and lengths it specifies via a data file. -= the child verifies that all the specified memory was altered -= with no overruns. Parent then tries to read memory from child -= and does memory compare to ensure it read memory contents -= correctly diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/CMakeLists.txt index 987c413..8aa1c80 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_rtlmovememory_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/test1.c b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/test1.c rename to src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test1/test1.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/CMakeLists.txt index 14098a8..d292cff 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_rtlmovememory_test3 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/test3.c b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/test3.c rename to src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test3/test3.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/CMakeLists.txt index 00aec7e..e8aeb0c 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_rtlmovememory_test4 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/test4.c b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/test4.c rename to src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test4/test4.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/CMakeLists.txt index f2de782..7f4986e 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_rtlmovememory_test5 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/test5.c b/src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/test5.c rename to src/pal/tests/palsuite/filemapping_memmgt/RtlMoveMemory/test5/test5.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/CMakeLists.txt index 0e6d6fe..8ed46ba 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - test1.c + test1.cpp ) add_executable(paltest_unlockfile_test1 @@ -20,7 +20,7 @@ target_link_libraries(paltest_unlockfile_test1 set(HELPERSOURCES - helper.c + helper.cpp ) add_executable(paltest_unlockfile_test1_helper diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/helper.c b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/helper.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/helper.c rename to src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/helper.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/test1.c b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/test1.c rename to src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test1/test1.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/CMakeLists.txt index 142b276..3033876 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_unlockfile_test2 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/test2.c b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/test2.c rename to src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test2/test2.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/CMakeLists.txt index b4ec37c..d46d7db 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - test3.c + test3.cpp ) add_executable(paltest_unlockfile_test3 @@ -20,7 +20,7 @@ target_link_libraries(paltest_unlockfile_test3 set(HELPERSOURCES - helper.c + helper.cpp ) add_executable(paltest_unlockfile_test3_helper diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/helper.c b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/helper.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/helper.c rename to src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/helper.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/test3.c b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/test3.c rename to src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test3/test3.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/CMakeLists.txt index d6bee30..635a1ca 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_unlockfile_test4 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/test4.c b/src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/test4.c rename to src/pal/tests/palsuite/filemapping_memmgt/UnlockFile/test4/test4.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/CMakeLists.txt index 5ebda77..1b8062f 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - UnmapViewOfFile.c + UnmapViewOfFile.cpp ) add_executable(paltest_unmapviewoffile_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/UnmapViewOfFile.c b/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/UnmapViewOfFile.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/UnmapViewOfFile.c rename to src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test1/UnmapViewOfFile.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/CMakeLists.txt index 5c12cf9..750e446 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - unmapviewoffile.c + unmapviewoffile.cpp ) add_executable(paltest_unmapviewoffile_test2 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/unmapviewoffile.c b/src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/unmapviewoffile.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/unmapviewoffile.c rename to src/pal/tests/palsuite/filemapping_memmgt/UnmapViewOfFile/test2/unmapviewoffile.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/CMakeLists.txt index eafaa66..b2cafde 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/CMakeLists.txt @@ -14,6 +14,7 @@ add_subdirectory(test19) add_subdirectory(test2) add_subdirectory(test20) add_subdirectory(test21) +add_subdirectory(test22) add_subdirectory(test3) add_subdirectory(test4) add_subdirectory(test5) diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/CMakeLists.txt index 90ba41b..f8c0645 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualAlloc.c + VirtualAlloc.cpp ) add_executable(paltest_virtualalloc_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/VirtualAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/VirtualAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test1/VirtualAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/CMakeLists.txt index 51b0e1d..1b66f0d 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualAlloc.c + VirtualAlloc.cpp ) add_executable(paltest_virtualalloc_test10 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/VirtualAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/VirtualAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test10/VirtualAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/CMakeLists.txt index adff470..95e1a06 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualAlloc.c + VirtualAlloc.cpp ) add_executable(paltest_virtualalloc_test11 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/VirtualAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/VirtualAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test11/VirtualAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/CMakeLists.txt index 26f3035..7564f96 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualAlloc.c + VirtualAlloc.cpp ) add_executable(paltest_virtualalloc_test12 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/VirtualAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/VirtualAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test12/VirtualAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/CMakeLists.txt index f85cbdc..a49dcfc 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualAlloc.c + VirtualAlloc.cpp ) add_executable(paltest_virtualalloc_test13 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/VirtualAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/VirtualAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test13/VirtualAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/CMakeLists.txt index 41ed0ca..180a48e 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualAlloc.c + VirtualAlloc.cpp ) add_executable(paltest_virtualalloc_test14 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/VirtualAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/VirtualAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test14/VirtualAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/CMakeLists.txt index 87b2910..4ba2194 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualAlloc.c + VirtualAlloc.cpp ) add_executable(paltest_virtualalloc_test15 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/VirtualAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/VirtualAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test15/VirtualAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/CMakeLists.txt index 90e3f3b..1c5f63d 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualAlloc.c + VirtualAlloc.cpp ) add_executable(paltest_virtualalloc_test16 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/VirtualAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/VirtualAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test16/VirtualAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/CMakeLists.txt index 461b48c..6523bb9 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualAlloc.c + VirtualAlloc.cpp ) add_executable(paltest_virtualalloc_test17 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/VirtualAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/VirtualAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test17/VirtualAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/CMakeLists.txt index 69823be..3fe65b4 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualAlloc.c + VirtualAlloc.cpp ) add_executable(paltest_virtualalloc_test18 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/VirtualAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/VirtualAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test18/VirtualAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/CMakeLists.txt index fa65b4f..1795b8b 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualAlloc.c + VirtualAlloc.cpp ) add_executable(paltest_virtualalloc_test19 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/VirtualAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/VirtualAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test19/VirtualAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/CMakeLists.txt index 1753b1e..20da178 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualAlloc.c + VirtualAlloc.cpp ) add_executable(paltest_virtualalloc_test2 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/VirtualAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/VirtualAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test2/VirtualAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/CMakeLists.txt index 2c55071..5c23fe2 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - virtualalloc.c + virtualalloc.cpp ) add_executable(paltest_virtualalloc_test20 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/virtualalloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/virtualalloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/virtualalloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test20/virtualalloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/CMakeLists.txt index f97c32a..96a3144 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - virtualalloc.c + virtualalloc.cpp ) add_executable(paltest_virtualalloc_test21 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/virtualalloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/virtualalloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/virtualalloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test21/virtualalloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/CMakeLists.txt new file mode 100644 index 0000000..cdad2ca --- /dev/null +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + VirtualAlloc.cpp +) + +add_executable(paltest_virtualalloc_test22 + ${SOURCES} +) + +add_dependencies(paltest_virtualalloc_test22 coreclrpal) + +target_link_libraries(paltest_virtualalloc_test22 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/VirtualAlloc.cpp b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/VirtualAlloc.cpp new file mode 100644 index 0000000..489926f --- /dev/null +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/VirtualAlloc.cpp @@ -0,0 +1,44 @@ +// 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. + +/*============================================================= +** +** Source: virtualalloc.c +** +** Purpose: Negative test the VirtualAlloc API. +** Call VirtualAlloc with MEM_COMMIT allocation type +** and PAGE_READWRITE access protection + +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + LPVOID lpVirtualAddress; + + + //Initialize the PAL environment + err = PAL_Initialize(argc, argv); + if(0 != err) + { + ExitProcess(FAIL); + } + + //Allocate the physical storage in memory or in the paging file on disk + lpVirtualAddress = VirtualAlloc(NULL,//system determine where to allocate the region + (SIZE_T)(2147483647000000), //specify the size to be int32.maxvalue mega bytes + MEM_COMMIT, //allocation type + PAGE_READWRITE); //access protection + if(NULL != lpVirtualAddress) + { + Fail("\nWelcome to the Future, where Unlimited Memory is Available, disregard this test!\n"); + } + + + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/testinfo.dat new file mode 100644 index 0000000..3d5962c --- /dev/null +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test22/testinfo.dat @@ -0,0 +1,13 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = Filemapping_memmgt +Function = VirtualAlloc +Name = Negative test for VirtualAlloc API +TYPE = DEFAULT +EXE1 = virtualalloc +Description +=Test the VirtualAlloc with MEM_COMMIT allocation type +=and PAGE_READWRITEaccess protection diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/CMakeLists.txt index 035594b..77822f7 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualAlloc.c + VirtualAlloc.cpp ) add_executable(paltest_virtualalloc_test3 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/VirtualAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/VirtualAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test3/VirtualAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/CMakeLists.txt index 5ce80bf..0e2c448 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualAlloc.c + VirtualAlloc.cpp ) add_executable(paltest_virtualalloc_test4 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/VirtualAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/VirtualAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test4/VirtualAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/CMakeLists.txt index 138d9c9..247053f 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualAlloc.c + VirtualAlloc.cpp ) add_executable(paltest_virtualalloc_test5 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/VirtualAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/VirtualAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test5/VirtualAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/CMakeLists.txt index c61add9..d19391d 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualAlloc.c + VirtualAlloc.cpp ) add_executable(paltest_virtualalloc_test6 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/VirtualAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/VirtualAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test6/VirtualAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/CMakeLists.txt index b5452a0..8c01e04 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualAlloc.c + VirtualAlloc.cpp ) add_executable(paltest_virtualalloc_test7 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/VirtualAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/VirtualAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test7/VirtualAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/CMakeLists.txt index 584a0c5..db2a744 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualAlloc.c + VirtualAlloc.cpp ) add_executable(paltest_virtualalloc_test8 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/VirtualAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/VirtualAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test8/VirtualAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/CMakeLists.txt index aee950b..254fc6f 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualAlloc.c + VirtualAlloc.cpp ) add_executable(paltest_virtualalloc_test9 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/VirtualAlloc.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/VirtualAlloc.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/VirtualAlloc.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualAlloc/test9/VirtualAlloc.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/CMakeLists.txt index 1914f76..d231950 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualFree.c + VirtualFree.cpp ) add_executable(paltest_virtualfree_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/VirtualFree.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/VirtualFree.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/VirtualFree.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test1/VirtualFree.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/CMakeLists.txt index a288b37..9a3bc7a 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualFree.c + VirtualFree.cpp ) add_executable(paltest_virtualfree_test2 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/VirtualFree.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/VirtualFree.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/VirtualFree.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test2/VirtualFree.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/CMakeLists.txt index 993189c..8484c0f 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualFree.c + VirtualFree.cpp ) add_executable(paltest_virtualfree_test3 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/VirtualFree.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/VirtualFree.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/VirtualFree.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualFree/test3/VirtualFree.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/CMakeLists.txt index 214cf46..4283398 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualProtect.c + VirtualProtect.cpp ) add_executable(paltest_virtualprotect_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/VirtualProtect.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/VirtualProtect.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/VirtualProtect.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test1/VirtualProtect.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/CMakeLists.txt index 27f4347..aed68fd 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualProtect.c + VirtualProtect.cpp ) add_executable(paltest_virtualprotect_test2 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/VirtualProtect.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/VirtualProtect.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/VirtualProtect.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test2/VirtualProtect.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/CMakeLists.txt index 994d4e2..7072859 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualProtect.c + VirtualProtect.cpp ) add_executable(paltest_virtualprotect_test3 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/VirtualProtect.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/VirtualProtect.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/VirtualProtect.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test3/VirtualProtect.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/CMakeLists.txt index 2e0fba5..5ad64a7 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualProtect.c + VirtualProtect.cpp ) add_executable(paltest_virtualprotect_test4 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/VirtualProtect.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/VirtualProtect.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/VirtualProtect.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test4/VirtualProtect.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/CMakeLists.txt index 6d6fd07..78932ef 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualProtect.c + VirtualProtect.cpp ) add_executable(paltest_virtualprotect_test6 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/VirtualProtect.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/VirtualProtect.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/VirtualProtect.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test6/VirtualProtect.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/CMakeLists.txt index 06af860..caf5ef9 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualProtect.c + VirtualProtect.cpp ) add_executable(paltest_virtualprotect_test7 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/VirtualProtect.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/VirtualProtect.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/VirtualProtect.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualProtect/test7/VirtualProtect.cpp diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/CMakeLists.txt index 4f4e4bc..17cbdee 100644 --- a/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - VirtualQuery.c + VirtualQuery.cpp ) add_executable(paltest_virtualquery_test1 diff --git a/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/VirtualQuery.c b/src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/VirtualQuery.cpp similarity index 100% rename from src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/VirtualQuery.c rename to src/pal/tests/palsuite/filemapping_memmgt/VirtualQuery/test1/VirtualQuery.cpp diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test1/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryA/test1/CMakeLists.txt index 542f8d3..62b896d 100644 --- a/src/pal/tests/palsuite/loader/LoadLibraryA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - LoadLibraryA.c + LoadLibraryA.cpp ) add_executable(paltest_loadlibrarya_test1 diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test1/LoadLibraryA.c b/src/pal/tests/palsuite/loader/LoadLibraryA/test1/LoadLibraryA.cpp similarity index 100% rename from src/pal/tests/palsuite/loader/LoadLibraryA/test1/LoadLibraryA.c rename to src/pal/tests/palsuite/loader/LoadLibraryA/test1/LoadLibraryA.cpp diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test2/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryA/test2/CMakeLists.txt index 63cfb22..48a4c36 100644 --- a/src/pal/tests/palsuite/loader/LoadLibraryA/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - LoadLibraryA.c + LoadLibraryA.cpp ) add_executable(paltest_loadlibrarya_test2 diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test2/LoadLibraryA.c b/src/pal/tests/palsuite/loader/LoadLibraryA/test2/LoadLibraryA.cpp similarity index 100% rename from src/pal/tests/palsuite/loader/LoadLibraryA/test2/LoadLibraryA.c rename to src/pal/tests/palsuite/loader/LoadLibraryA/test2/LoadLibraryA.cpp diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test2/MyModule.c b/src/pal/tests/palsuite/loader/LoadLibraryA/test2/MyModule.cpp similarity index 100% rename from src/pal/tests/palsuite/loader/LoadLibraryA/test2/MyModule.c rename to src/pal/tests/palsuite/loader/LoadLibraryA/test2/MyModule.cpp diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test3/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryA/test3/CMakeLists.txt index 143d0ec..ae05b35 100644 --- a/src/pal/tests/palsuite/loader/LoadLibraryA/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - loadlibrarya.c + loadlibrarya.cpp ) add_executable(paltest_loadlibrarya_test3 diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test3/loadlibrarya.c b/src/pal/tests/palsuite/loader/LoadLibraryA/test3/loadlibrarya.cpp similarity index 100% rename from src/pal/tests/palsuite/loader/LoadLibraryA/test3/loadlibrarya.c rename to src/pal/tests/palsuite/loader/LoadLibraryA/test3/loadlibrarya.cpp diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test5/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryA/test5/CMakeLists.txt index a9d791c..99915ee 100644 --- a/src/pal/tests/palsuite/loader/LoadLibraryA/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - loadlibrarya.c + loadlibrarya.cpp ) add_executable(paltest_loadlibrarya_test5 diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test5/loadlibrarya.c b/src/pal/tests/palsuite/loader/LoadLibraryA/test5/loadlibrarya.c deleted file mode 100644 index d1e6b6d..0000000 --- a/src/pal/tests/palsuite/loader/LoadLibraryA/test5/loadlibrarya.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================= -** -** Source: loadlibrarya.c -** -** Purpose: Negative test the LoadLibraryA API. -** Call LoadLibraryA by passing a module name -** without extension but with a trailing dot. -** -** -**============================================================*/ -#include - -int __cdecl main(int argc, char *argv[]) -{ - HMODULE ModuleHandle; - char ModuleName[_MAX_FNAME]; - int err; - - /* Initialize the PAL environment */ - err = PAL_Initialize(argc, argv); - if(0 != err) - { - return FAIL; - } - - memset(ModuleName, 0, _MAX_FNAME); - - /*Module name without extension but with a trailing dot*/ -#if WIN32 - sprintf(ModuleName, "%s", "rotor_pal."); -#else - /* Under FreeBSD */ - sprintf(ModuleName, "%s", "librotor_pal."); -#endif - - /* load a module which does not have the file extension, - * but has a trailing dot - */ - ModuleHandle = LoadLibraryA(ModuleName); - if(NULL != ModuleHandle) - { - Trace("Failed to call LoadLibraryA API for a negative test " - "call LoadLibraryA with module name which does not have " - "extension except a trailing dot, a NULL module handle is" - "expected, but no NULL module handle is returned, " - "error code = %u\n", GetLastError()); - - - /* decrement the reference count of the loaded dll */ - err = FreeLibrary(ModuleHandle); - if(0 == err) - { - Trace("\nFailed to call FreeLibrary API, " - "error code = %u\n", GetLastError()); - } - - Fail(""); - } - - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test5/loadlibrarya.cpp b/src/pal/tests/palsuite/loader/LoadLibraryA/test5/loadlibrarya.cpp new file mode 100644 index 0000000..ab38d1a --- /dev/null +++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test5/loadlibrarya.cpp @@ -0,0 +1,67 @@ +// 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. + +/*============================================================= +** +** Source: loadlibrarya.c +** +** Purpose: Negative test the LoadLibraryA API. +** Call LoadLibraryA by passing a module name +** without extension but with a trailing dot. +** +** +**============================================================*/ +#include + +int __cdecl main(int argc, char *argv[]) +{ + HMODULE ModuleHandle; + char ModuleName[_MAX_FNAME]; + int err; + + /* Initialize the PAL environment */ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + memset(ModuleName, 0, _MAX_FNAME); + + /*Module name without extension but with a trailing dot*/ +#if WIN32 + sprintf_s(ModuleName, _countof(ModuleName), "%s", "rotor_pal."); +#else + /* Under FreeBSD */ + sprintf_s(ModuleName, _countof(ModuleName), "%s", "librotor_pal."); +#endif + + /* load a module which does not have the file extension, + * but has a trailing dot + */ + ModuleHandle = LoadLibraryA(ModuleName); + if(NULL != ModuleHandle) + { + Trace("Failed to call LoadLibraryA API for a negative test " + "call LoadLibraryA with module name which does not have " + "extension except a trailing dot, a NULL module handle is" + "expected, but no NULL module handle is returned, " + "error code = %u\n", GetLastError()); + + + /* decrement the reference count of the loaded dll */ + err = FreeLibrary(ModuleHandle); + if(0 == err) + { + Trace("\nFailed to call FreeLibrary API, " + "error code = %u\n", GetLastError()); + } + + Fail(""); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test6/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryA/test6/CMakeLists.txt index bb66ade..0fac878 100644 --- a/src/pal/tests/palsuite/loader/LoadLibraryA/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - loadlibrarya.c + loadlibrarya.cpp ) add_executable(paltest_loadlibrarya_test6 @@ -20,7 +20,7 @@ target_link_libraries(paltest_loadlibrarya_test6 set(HELPERSOURCES - dlltest.c + dlltest.cpp ) add_executable(paltest_loadlibrarya_test6_dlltest diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test8/dlltest.c b/src/pal/tests/palsuite/loader/LoadLibraryA/test6/dlltest.cpp similarity index 100% rename from src/pal/tests/palsuite/loader/LoadLibraryA/test8/dlltest.c rename to src/pal/tests/palsuite/loader/LoadLibraryA/test6/dlltest.cpp diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test6/loadlibrarya.c b/src/pal/tests/palsuite/loader/LoadLibraryA/test6/loadlibrarya.cpp similarity index 100% rename from src/pal/tests/palsuite/loader/LoadLibraryA/test6/loadlibrarya.c rename to src/pal/tests/palsuite/loader/LoadLibraryA/test6/loadlibrarya.cpp diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test7/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryA/test7/CMakeLists.txt index 6c0d174..bb403c6 100644 --- a/src/pal/tests/palsuite/loader/LoadLibraryA/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - LoadLibraryA.c + LoadLibraryA.cpp ) add_executable(paltest_loadlibrarya_test7 diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test7/LoadLibraryA.c b/src/pal/tests/palsuite/loader/LoadLibraryA/test7/LoadLibraryA.cpp similarity index 100% rename from src/pal/tests/palsuite/loader/LoadLibraryA/test7/LoadLibraryA.c rename to src/pal/tests/palsuite/loader/LoadLibraryA/test7/LoadLibraryA.cpp diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test8/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryA/test8/CMakeLists.txt index b663a7b..9e34491 100644 --- a/src/pal/tests/palsuite/loader/LoadLibraryA/test8/CMakeLists.txt +++ b/src/pal/tests/palsuite/loader/LoadLibraryA/test8/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - loadlibrarya.c + loadlibrarya.cpp ) add_executable(paltest_loadlibrarya_test8 @@ -20,7 +20,7 @@ target_link_libraries(paltest_loadlibrarya_test8 set(HELPERSOURCES - dlltest.c + dlltest.cpp ) add_executable(paltest_loadlibrarya_test8_dlltest diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test6/dlltest.c b/src/pal/tests/palsuite/loader/LoadLibraryA/test8/dlltest.cpp similarity index 100% rename from src/pal/tests/palsuite/loader/LoadLibraryA/test6/dlltest.c rename to src/pal/tests/palsuite/loader/LoadLibraryA/test8/dlltest.cpp diff --git a/src/pal/tests/palsuite/loader/LoadLibraryA/test8/loadlibrarya.c b/src/pal/tests/palsuite/loader/LoadLibraryA/test8/loadlibrarya.cpp similarity index 100% rename from src/pal/tests/palsuite/loader/LoadLibraryA/test8/loadlibrarya.c rename to src/pal/tests/palsuite/loader/LoadLibraryA/test8/loadlibrarya.cpp diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test1/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryW/test1/CMakeLists.txt index 8703801..171d1d5 100644 --- a/src/pal/tests/palsuite/loader/LoadLibraryW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/loader/LoadLibraryW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - LoadLibraryW.c + LoadLibraryW.cpp ) add_executable(paltest_loadlibraryw_test1 diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test1/LoadLibraryW.c b/src/pal/tests/palsuite/loader/LoadLibraryW/test1/LoadLibraryW.cpp similarity index 100% rename from src/pal/tests/palsuite/loader/LoadLibraryW/test1/LoadLibraryW.c rename to src/pal/tests/palsuite/loader/LoadLibraryW/test1/LoadLibraryW.cpp diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test2/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryW/test2/CMakeLists.txt index 5e8486d..9873e13 100644 --- a/src/pal/tests/palsuite/loader/LoadLibraryW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/loader/LoadLibraryW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - loadlibraryw.c + loadlibraryw.cpp ) add_executable(paltest_loadlibraryw_test2 diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test2/loadlibraryw.c b/src/pal/tests/palsuite/loader/LoadLibraryW/test2/loadlibraryw.cpp similarity index 100% rename from src/pal/tests/palsuite/loader/LoadLibraryW/test2/loadlibraryw.c rename to src/pal/tests/palsuite/loader/LoadLibraryW/test2/loadlibraryw.cpp diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test3/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryW/test3/CMakeLists.txt index 2c96fa2..be75864 100644 --- a/src/pal/tests/palsuite/loader/LoadLibraryW/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/loader/LoadLibraryW/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - loadlibraryw.c + loadlibraryw.cpp ) add_executable(paltest_loadlibraryw_test3 diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test3/loadlibraryw.c b/src/pal/tests/palsuite/loader/LoadLibraryW/test3/loadlibraryw.cpp similarity index 100% rename from src/pal/tests/palsuite/loader/LoadLibraryW/test3/loadlibraryw.c rename to src/pal/tests/palsuite/loader/LoadLibraryW/test3/loadlibraryw.cpp diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test5/CMakeLists.txt b/src/pal/tests/palsuite/loader/LoadLibraryW/test5/CMakeLists.txt index 7b8931a..1ca990b 100644 --- a/src/pal/tests/palsuite/loader/LoadLibraryW/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/loader/LoadLibraryW/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - loadlibraryw.c + loadlibraryw.cpp ) add_executable(paltest_loadlibraryw_test5 diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test5/loadlibraryw.c b/src/pal/tests/palsuite/loader/LoadLibraryW/test5/loadlibraryw.c deleted file mode 100644 index acaa200..0000000 --- a/src/pal/tests/palsuite/loader/LoadLibraryW/test5/loadlibraryw.c +++ /dev/null @@ -1,71 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: loadlibraryw.c -** -** Purpose: Negative test the LoadLibraryW API. -** Call LoadLibraryW by passing a module name -** without extension but with a trailing dot. -** -** -**============================================================*/ -#define UNICODE -#include - -int __cdecl main(int argc, char *argv[]) -{ - HMODULE ModuleHandle; - int err; - WCHAR *lpModuleName; - char ModuleName[_MAX_FNAME]; - - /* Initialize the PAL environment */ - err = PAL_Initialize(argc, argv); - if(0 != err) - { - return FAIL; - } - - memset(ModuleName, 0, _MAX_FNAME); - - /*Module name without extension but with a trailing dot*/ -#if WIN32 - sprintf(ModuleName,"%s","rotor_pal."); -#else - sprintf(ModuleName,"%s","librotor_pal."); -#endif - - /* convert a normal string to a wide one */ - lpModuleName = convert(ModuleName); - - /* load a module */ - ModuleHandle = LoadLibraryW(lpModuleName); - - /* free the memory */ - free(lpModuleName); - - if(NULL != ModuleHandle) - { - Trace("Failed to call LoadLibraryW API for a negative test " - "call LoadLibraryW with module name which does not have " - "extension except a trailing dot, a NULL module handle is" - "expected, but no NULL module handle is returned, " - "error code = %u\n", GetLastError()); - - /* decrement the reference count of the loaded dll */ - err = FreeLibrary(ModuleHandle); - if(0 == err) - { - Trace("\nFailed to call FreeLibrary API, " - "error code = %u\n", GetLastError()); - } - - Fail(""); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/loader/LoadLibraryW/test5/loadlibraryw.cpp b/src/pal/tests/palsuite/loader/LoadLibraryW/test5/loadlibraryw.cpp new file mode 100644 index 0000000..6d92f02 --- /dev/null +++ b/src/pal/tests/palsuite/loader/LoadLibraryW/test5/loadlibraryw.cpp @@ -0,0 +1,71 @@ +// 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. + +/*============================================================= +** +** Source: loadlibraryw.c +** +** Purpose: Negative test the LoadLibraryW API. +** Call LoadLibraryW by passing a module name +** without extension but with a trailing dot. +** +** +**============================================================*/ +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + HMODULE ModuleHandle; + int err; + WCHAR *lpModuleName; + char ModuleName[_MAX_FNAME]; + + /* Initialize the PAL environment */ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + memset(ModuleName, 0, _MAX_FNAME); + + /*Module name without extension but with a trailing dot*/ +#if WIN32 + sprintf_s(ModuleName, _countof(ModuleName),"%s","rotor_pal."); +#else + sprintf_s(ModuleName, _countof(ModuleName),"%s","librotor_pal."); +#endif + + /* convert a normal string to a wide one */ + lpModuleName = convert(ModuleName); + + /* load a module */ + ModuleHandle = LoadLibraryW(lpModuleName); + + /* free the memory */ + free(lpModuleName); + + if(NULL != ModuleHandle) + { + Trace("Failed to call LoadLibraryW API for a negative test " + "call LoadLibraryW with module name which does not have " + "extension except a trailing dot, a NULL module handle is" + "expected, but no NULL module handle is returned, " + "error code = %u\n", GetLastError()); + + /* decrement the reference count of the loaded dll */ + err = FreeLibrary(ModuleHandle); + if(0 == err) + { + Trace("\nFailed to call FreeLibrary API, " + "error code = %u\n", GetLastError()); + } + + Fail(""); + } + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/locale_info/CompareStringA/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/CompareStringA/test1/CMakeLists.txt index 96ee18d..171d5b7 100644 --- a/src/pal/tests/palsuite/locale_info/CompareStringA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/CompareStringA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_comparestringa_test1 diff --git a/src/pal/tests/palsuite/locale_info/CompareStringA/test1/test1.c b/src/pal/tests/palsuite/locale_info/CompareStringA/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/CompareStringA/test1/test1.c rename to src/pal/tests/palsuite/locale_info/CompareStringA/test1/test1.cpp diff --git a/src/pal/tests/palsuite/locale_info/CompareStringW/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/CompareStringW/test1/CMakeLists.txt index 8652977..15a7fe7 100644 --- a/src/pal/tests/palsuite/locale_info/CompareStringW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/CompareStringW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_comparestringw_test1 diff --git a/src/pal/tests/palsuite/locale_info/CompareStringW/test1/test1.c b/src/pal/tests/palsuite/locale_info/CompareStringW/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/CompareStringW/test1/test1.c rename to src/pal/tests/palsuite/locale_info/CompareStringW/test1/test1.cpp diff --git a/src/pal/tests/palsuite/locale_info/GetACP/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetACP/test1/CMakeLists.txt index c5513da..cf4431e 100644 --- a/src/pal/tests/palsuite/locale_info/GetACP/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/GetACP/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_getacp_test1 diff --git a/src/pal/tests/palsuite/locale_info/GetACP/test1/test1.c b/src/pal/tests/palsuite/locale_info/GetACP/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/GetACP/test1/test1.c rename to src/pal/tests/palsuite/locale_info/GetACP/test1/test1.cpp diff --git a/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/CMakeLists.txt index c209b12..b4cf017 100644 --- a/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_getcpinfo_test1 diff --git a/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/test1.c b/src/pal/tests/palsuite/locale_info/GetCPInfo/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/GetCPInfo/test1/test1.c rename to src/pal/tests/palsuite/locale_info/GetCPInfo/test1/test1.cpp diff --git a/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/CMakeLists.txt index 6132e9b..b366f3c 100644 --- a/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_getcpinfo_test2 diff --git a/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/test2.c b/src/pal/tests/palsuite/locale_info/GetCPInfo/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/GetCPInfo/test2/test2.c rename to src/pal/tests/palsuite/locale_info/GetCPInfo/test2/test2.cpp diff --git a/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/CMakeLists.txt index 3e4a09b..032dd00 100644 --- a/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_getcpinfo_test3 diff --git a/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/test3.c b/src/pal/tests/palsuite/locale_info/GetCPInfo/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/GetCPInfo/test3/test3.c rename to src/pal/tests/palsuite/locale_info/GetCPInfo/test3/test3.cpp diff --git a/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/CMakeLists.txt index f373b98..4f685cb 100644 --- a/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_getlocaleinfow_test1 diff --git a/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/test1.c b/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/test1.c rename to src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test1/test1.cpp diff --git a/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/CMakeLists.txt index dd5b82e..7851b36 100644 --- a/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_getlocaleinfow_test2 diff --git a/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/test2.c b/src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/test2.c rename to src/pal/tests/palsuite/locale_info/GetLocaleInfoW/test2/test2.cpp diff --git a/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/CMakeLists.txt index 5bb7b8c..e686216 100644 --- a/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_getstringtypeexw_test1 diff --git a/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/test1.c b/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/test1.c rename to src/pal/tests/palsuite/locale_info/GetStringTypeExW/test1/test1.cpp diff --git a/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/CMakeLists.txt index 4a8fab2..e37b749 100644 --- a/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_getstringtypeexw_test2 diff --git a/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/test2.c b/src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/test2.c rename to src/pal/tests/palsuite/locale_info/GetStringTypeExW/test2/test2.cpp diff --git a/src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/CMakeLists.txt index ef87b5f..e34e183 100644 --- a/src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_getsystemdefaultlangid_test1 diff --git a/src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/test1.c b/src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/test1.c rename to src/pal/tests/palsuite/locale_info/GetSystemDefaultLangID/test1/test1.cpp diff --git a/src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/CMakeLists.txt index 8cec9d8..8abbd82 100644 --- a/src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_getthreadlocale_test1 diff --git a/src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/test1.c b/src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/test1.c rename to src/pal/tests/palsuite/locale_info/GetThreadLocale/test1/test1.cpp diff --git a/src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/CMakeLists.txt index 281f3bf..8bf0a6c 100644 --- a/src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_gettimezoneinformation_test1 diff --git a/src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/test1.c b/src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/test1.c rename to src/pal/tests/palsuite/locale_info/GetTimeZoneInformation/test1/test1.cpp diff --git a/src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/CMakeLists.txt index e039d46..b6f08b1 100644 --- a/src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_getuserdefaultlcid_test1 diff --git a/src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/test1.c b/src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/test1.c rename to src/pal/tests/palsuite/locale_info/GetUserDefaultLCID/test1/test1.cpp diff --git a/src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/CMakeLists.txt index 71fa046..8fc795a 100644 --- a/src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_getuserdefaultlangid_test1 diff --git a/src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/test1.c b/src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/test1.c rename to src/pal/tests/palsuite/locale_info/GetUserDefaultLangID/test1/test1.cpp diff --git a/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/CMakeLists.txt index ad5ad75..e9b22dc 100644 --- a/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_isdbcsleadbyte_test1 diff --git a/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/test1.c b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/test1.c rename to src/pal/tests/palsuite/locale_info/IsDBCSLeadByte/test1/test1.cpp diff --git a/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/CMakeLists.txt index 9d53ee9..f3a232b 100644 --- a/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_isdbcsleadbyteex_test1 diff --git a/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/test1.c b/src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/test1.c rename to src/pal/tests/palsuite/locale_info/IsDBCSLeadByteEx/test1/test1.cpp diff --git a/src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/CMakeLists.txt index d87e8c0..ae12b37 100644 --- a/src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_isvalidcodepage_test1 diff --git a/src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/test1.c b/src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/test1.c rename to src/pal/tests/palsuite/locale_info/IsValidCodePage/test1/test1.cpp diff --git a/src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/CMakeLists.txt index adcae86..6eeff25 100644 --- a/src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_isvalidcodepage_test2 diff --git a/src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/test2.c b/src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/test2.c rename to src/pal/tests/palsuite/locale_info/IsValidCodePage/test2/test2.cpp diff --git a/src/pal/tests/palsuite/locale_info/IsValidLocale/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/IsValidLocale/test1/CMakeLists.txt index 8fc7604..27d6169 100644 --- a/src/pal/tests/palsuite/locale_info/IsValidLocale/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/IsValidLocale/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_isvalidlocale_test1 diff --git a/src/pal/tests/palsuite/locale_info/IsValidLocale/test1/test1.c b/src/pal/tests/palsuite/locale_info/IsValidLocale/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/IsValidLocale/test1/test1.c rename to src/pal/tests/palsuite/locale_info/IsValidLocale/test1/test1.cpp diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/CMakeLists.txt index 044c477..7bf79e3 100644 --- a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_multibytetowidechar_test1 diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/test1.c b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/test1.c rename to src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test1/test1.cpp diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/CMakeLists.txt index 0367d53..b3e3f64 100644 --- a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_multibytetowidechar_test2 diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/test2.c b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/test2.c rename to src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test2/test2.cpp diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/CMakeLists.txt index 57e3d66..c6eac9b 100644 --- a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_multibytetowidechar_test3 diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/test3.c b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/test3.c rename to src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test3/test3.cpp diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/CMakeLists.txt index 3d167df..c9c9295 100644 --- a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_multibytetowidechar_test4 diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/test4.c b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/test4.c deleted file mode 100644 index 2ba606c..0000000 --- a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/test4.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test4.c -** -** Purpose: Tests MultiByteToWideChar with a UTF-8 encoding -** -** -**==========================================================================*/ - -#include - -int __cdecl main(int argc, char *argv[]) -{ - int ret; - int ret2; - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - const char * const utf8Strings[] = - { - // Correct strings - - // Empty string - "", - // 1 byte encoded 1 character long string - "A", - // 2 byte encoded 1 character long string - "\xC2\x80", - // 3 byte encoded 1 character long string - "\xE0\xA0\x80", - // 1 byte encoded characters only - "ABCDEFGHIJKLMNOPQRSTUVWXYZ", - // valid 2 byte encoded characters only - "\xC2\x80\xC3\xBF\xC7\x81\xDF\xBF", - // valid 3 byte encoded characters only - "\xE0\xA0\x80\xE1\xB6\x88\xE1\x80\x80\xEF\xBF\xBF", - // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 1 byte char - "\x41\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF\x45", - // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 1 byte char, ending with 2 byte one - "\x41\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF", - // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 2 byte char, ending with 1 byte one - "\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF\x45", - // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 2 byte char - "\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF", - // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 1 byte char - "\x41\x42\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF\x45\x46", - // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 1 byte char, ending with 2 byte one - "\x41\x42\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF", - // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 2 byte char, ending with 1 byte one - "\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF\x45\x46", - // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 2 byte char - "\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF", - // surrogates - "\xF0\x90\x80\x80\xF0\x90\x89\x80\xF3\x80\x8E\xB0\xF4\x8F\xBF\xBF", - - // Strings with errors - // Incomplete 2 byte encoded character 1 byte missing standalone - "\xC2", - // Incomplete 3 byte encoded character 1 byte missing standalone - "\xE0\xA0", - // Incomplete 3 byte encoded character 2 bytes missing standalone - "\xE0", - // Incomplete surrogate character 1 byte missing standalone - "\xF0\x90\x80", - // Incomplete surrogate character 2 bytes missing standalone - "\xF0\x90", - // Incomplete surrogate character 3 bytes missing standalone - "\xF0", - // Trailing byte with no lead byte standalone - "\x80", - // Incomplete 2 byte encoded character 1 byte missing between 1 byte chars - "\x41\xC2\x42", - // Incomplete 3 byte encoded character 1 byte missing between 1 byte chars - "\x41\xE0\xA0\x42", - // Incomplete 3 byte encoded character 2 bytes missing between 1 byte chars - "\x41\xE0\x42", - // Trailing byte with no lead byte between 1 byte chars - "\x41\x80\x42", - // Incomplete 2 byte encoded character 1 byte missing before 1 byte char - "\xC2\x42", - // Incomplete 3 byte encoded character 1 byte missing before 1 byte char - "\xE0\xA0\x42", - // Incomplete 3 byte encoded character 2 bytes missing before 1 byte char - "\xE0\x42", - // Trailing byte with no lead byte before 1 byte char - "\x80\x42", - // Incomplete 2 byte encoded character 1 byte missing after 1 byte char - "\x41\xC2", - // Incomplete 3 byte encoded character 1 byte missing after 1 byte char - "\x41\xE0\xA0", - // Incomplete 3 byte encoded character 2 bytes missing after 1 byte char - "\x41\xE0", - // Trailing byte with no lead byte after 1 byte char - "\x41\x80", - // Incomplete 2 byte encoded character 1 byte missing between 2 byte chars - "\xC2\x80\xC2\xC3\xBF", - // Incomplete 3 byte encoded character 1 byte missing between 2 byte chars - "\xC2\x80\xE0\xA0\xC3\xBF", - // Incomplete 3 byte encoded character 2 bytes missing between 2 byte chars - "\xC2\x80\xE0\xC3\xBF", - // Trailing byte with no lead byte between 2 byte chars - "\xC2\x80\x80\xC3\xBF", - // 2 byte encoded character in non-shortest form encodings (these are not allowed) - "\xC0\x80", - // 3 byte encoded character in non-shortest form encodings (these are not allowed) - "\xE0\x80\x80", - // 4 byte encoded character in non-shortest form encodings (these are not allowed) - "\xF0\x80\x80\x80", - }; - - const WCHAR * const unicodeStrings[] = - { - // Empty string - W(""), - // 1 byte encoded 1 character long string - W("A"), - // 2 byte encoded 1 character long string - W("\x0080"), - // 3 byte encoded 1 character long string - W("\x0800"), - // 1 byte encoded characters only - W("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), - // 2 byte encoded characters only - W("\x0080\x00FF\x01C1\x07FF"), - // valid 3 byte encoded characters only - W("\x0800\x1D88\x1000\xFFFF"), - // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 1 byte char - W("\x0041\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF\x0045"), - // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 1 byte char, ending with 2 byte one - W("\x0041\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF"), - // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 2 byte char, ending with 1 byte one - W("\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF\x0045"), - // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 2 byte char - W("\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF"), - // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 1 byte char - W("\x0041\x0042\x0080\x00FF\x0043\x0044\x01C1\x07FF\x0045\x0046"), - // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 1 byte char, ending with 2 byte one - W("\x0041\x0042\x0080\x00FF\x0043\x0044\x01C1\x07FF"), - // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 2 byte char, ending with 1 byte one - W("\x0080\x00FF\x0043\x0044\x01C1\x07FF\x0045\x0046"), - // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 2 byte char - W("\x0080\x00FF\x0043\x0044\x01C1\x07FF"), - // surrogates - W("\xD800\xDC00\xD800\xDE40\xDAC0\xDFB0\xDBFF\xDFFF"), - - // Strings with errors - // Incomplete 2 byte encoded character standalone - W(""), - // Incomplete 3 byte encoded character 1 byte missing standalone - W(""), - // Incomplete 3 byte encoded character 2 bytes missing standalone - W(""), - // Incomplete surrogate character 1 byte missing standalone - W(""), - // Incomplete surrogate character 2 bytes missing standalone - W(""), - // Incomplete surrogate character 3 bytes missing standalone - W(""), - // Trailing byte with no lead byte standalone - W(""), - // Incomplete 2 byte encoded character 1 byte missing between 1 byte chars - W("\x0041\x0042"), - // Incomplete 3 byte encoded character 1 byte missing between 1 byte chars - W("\x0041\x0042"), - // Incomplete 3 byte encoded character 2 bytes missing between 1 byte chars - W("\x0041\x0042"), - // Trailing byte with no lead byte between 1 byte chars - W("\x0041\x0042"), - // Incomplete 2 byte encoded character 1 byte missing before 1 byte char - W("\x0042"), - // Incomplete 3 byte encoded character 1 byte missing before 1 byte char - W("\x0042"), - // Incomplete 3 byte encoded character 2 bytes missing before 1 byte char - W("\x0042"), - // Trailing byte with no lead byte before 1 byte char - W("\x0042"), - // Incomplete 2 byte encoded character 1 byte missing after 1 byte char - W("\x0041"), - // Incomplete 3 byte encoded character 1 byte missing after 1 byte char - W("\x0041"), - // Incomplete 3 byte encoded character 2 bytes missing after 1 byte char - W("\x0041"), - // Trailing byte with no lead byte after 1 byte char - W("\x0041"), - // Incomplete 2 byte encoded character 1 byte missing between 2 byte chars - W("\x0080\x00FF"), - // Incomplete 3 byte encoded character 1 byte missing between 2 byte chars - W("\x0080\x00FF"), - // Incomplete 3 byte encoded character 2 bytes missing between 2 byte chars - W("\x0080\x00FF"), - // Trailing byte with no lead byte between 2 byte chars - W("\x0080\x00FF"), - // 2 byte encoded character in non-shortest form encodings (these are not allowed) - W(""), - // 3 byte encoded character in non-shortest form encodings (these are not allowed) - W(""), - // 4 byte encoded character in non-shortest form encodings (these are not allowed) - W(""), - }; - - for (int i = 0; i < (sizeof(utf8Strings) / sizeof(utf8Strings[0])); i++) - { - ret = MultiByteToWideChar(CP_UTF8, 0, utf8Strings[i], -1, NULL, 0); - WCHAR* wideBuffer = malloc(ret * sizeof(WCHAR)); - ret2 = MultiByteToWideChar(CP_UTF8, 0, utf8Strings[i], -1, wideBuffer, ret); - if (ret != ret2) - { - Fail("MultiByteToWideChar string %d: returned different string length for empty and real dest buffers!\n" - "Got %d for the empty one, %d for real one.\n", i, ret2, ret); - } - - if (wcscmp(wideBuffer, unicodeStrings[i]) != 0) - { - Fail("MultiByteToWideChar string %d: the resulting string doesn't match the expected one!\n", i); - } - - free(wideBuffer); - } - - PAL_Terminate(); - - return PASS; -} \ No newline at end of file diff --git a/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/test4.cpp b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/test4.cpp new file mode 100644 index 0000000..1d72346 --- /dev/null +++ b/src/pal/tests/palsuite/locale_info/MultiByteToWideChar/test4/test4.cpp @@ -0,0 +1,230 @@ +// 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. + +/*============================================================================ +** +** Source: test4.c +** +** Purpose: Tests MultiByteToWideChar with a UTF-8 encoding +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + int ret; + int ret2; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + const char * const utf8Strings[] = + { + // Correct strings + + // Empty string + "", + // 1 byte encoded 1 character long string + "A", + // 2 byte encoded 1 character long string + "\xC2\x80", + // 3 byte encoded 1 character long string + "\xE0\xA0\x80", + // 1 byte encoded characters only + "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + // valid 2 byte encoded characters only + "\xC2\x80\xC3\xBF\xC7\x81\xDF\xBF", + // valid 3 byte encoded characters only + "\xE0\xA0\x80\xE1\xB6\x88\xE1\x80\x80\xEF\xBF\xBF", + // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 1 byte char + "\x41\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF\x45", + // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 1 byte char, ending with 2 byte one + "\x41\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF", + // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 2 byte char, ending with 1 byte one + "\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF\x45", + // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 2 byte char + "\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF", + // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 1 byte char + "\x41\x42\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF\x45\x46", + // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 1 byte char, ending with 2 byte one + "\x41\x42\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF", + // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 2 byte char, ending with 1 byte one + "\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF\x45\x46", + // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 2 byte char + "\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF", + // surrogates + "\xF0\x90\x80\x80\xF0\x90\x89\x80\xF3\x80\x8E\xB0\xF4\x8F\xBF\xBF", + + // Strings with errors + // Incomplete 2 byte encoded character 1 byte missing standalone + "\xC2", + // Incomplete 3 byte encoded character 1 byte missing standalone + "\xE0\xA0", + // Incomplete 3 byte encoded character 2 bytes missing standalone + "\xE0", + // Incomplete surrogate character 1 byte missing standalone + "\xF0\x90\x80", + // Incomplete surrogate character 2 bytes missing standalone + "\xF0\x90", + // Incomplete surrogate character 3 bytes missing standalone + "\xF0", + // Trailing byte with no lead byte standalone + "\x80", + // Incomplete 2 byte encoded character 1 byte missing between 1 byte chars + "\x41\xC2\x42", + // Incomplete 3 byte encoded character 1 byte missing between 1 byte chars + "\x41\xE0\xA0\x42", + // Incomplete 3 byte encoded character 2 bytes missing between 1 byte chars + "\x41\xE0\x42", + // Trailing byte with no lead byte between 1 byte chars + "\x41\x80\x42", + // Incomplete 2 byte encoded character 1 byte missing before 1 byte char + "\xC2\x42", + // Incomplete 3 byte encoded character 1 byte missing before 1 byte char + "\xE0\xA0\x42", + // Incomplete 3 byte encoded character 2 bytes missing before 1 byte char + "\xE0\x42", + // Trailing byte with no lead byte before 1 byte char + "\x80\x42", + // Incomplete 2 byte encoded character 1 byte missing after 1 byte char + "\x41\xC2", + // Incomplete 3 byte encoded character 1 byte missing after 1 byte char + "\x41\xE0\xA0", + // Incomplete 3 byte encoded character 2 bytes missing after 1 byte char + "\x41\xE0", + // Trailing byte with no lead byte after 1 byte char + "\x41\x80", + // Incomplete 2 byte encoded character 1 byte missing between 2 byte chars + "\xC2\x80\xC2\xC3\xBF", + // Incomplete 3 byte encoded character 1 byte missing between 2 byte chars + "\xC2\x80\xE0\xA0\xC3\xBF", + // Incomplete 3 byte encoded character 2 bytes missing between 2 byte chars + "\xC2\x80\xE0\xC3\xBF", + // Trailing byte with no lead byte between 2 byte chars + "\xC2\x80\x80\xC3\xBF", + // 2 byte encoded character in non-shortest form encodings (these are not allowed) + "\xC0\x80", + // 3 byte encoded character in non-shortest form encodings (these are not allowed) + "\xE0\x80\x80", + // 4 byte encoded character in non-shortest form encodings (these are not allowed) + "\xF0\x80\x80\x80", + }; + + const WCHAR * const unicodeStrings[] = + { + // Empty string + W(""), + // 1 byte encoded 1 character long string + W("A"), + // 2 byte encoded 1 character long string + W("\x0080"), + // 3 byte encoded 1 character long string + W("\x0800"), + // 1 byte encoded characters only + W("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), + // 2 byte encoded characters only + W("\x0080\x00FF\x01C1\x07FF"), + // valid 3 byte encoded characters only + W("\x0800\x1D88\x1000\xFFFF"), + // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 1 byte char + W("\x0041\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF\x0045"), + // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 1 byte char, ending with 2 byte one + W("\x0041\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF"), + // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 2 byte char, ending with 1 byte one + W("\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF\x0045"), + // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 2 byte char + W("\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF"), + // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 1 byte char + W("\x0041\x0042\x0080\x00FF\x0043\x0044\x01C1\x07FF\x0045\x0046"), + // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 1 byte char, ending with 2 byte one + W("\x0041\x0042\x0080\x00FF\x0043\x0044\x01C1\x07FF"), + // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 2 byte char, ending with 1 byte one + W("\x0080\x00FF\x0043\x0044\x01C1\x07FF\x0045\x0046"), + // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 2 byte char + W("\x0080\x00FF\x0043\x0044\x01C1\x07FF"), + // surrogates + W("\xD800\xDC00\xD800\xDE40\xDAC0\xDFB0\xDBFF\xDFFF"), + + // Strings with errors + // Incomplete 2 byte encoded character standalone + W(""), + // Incomplete 3 byte encoded character 1 byte missing standalone + W(""), + // Incomplete 3 byte encoded character 2 bytes missing standalone + W(""), + // Incomplete surrogate character 1 byte missing standalone + W(""), + // Incomplete surrogate character 2 bytes missing standalone + W(""), + // Incomplete surrogate character 3 bytes missing standalone + W(""), + // Trailing byte with no lead byte standalone + W(""), + // Incomplete 2 byte encoded character 1 byte missing between 1 byte chars + W("\x0041\x0042"), + // Incomplete 3 byte encoded character 1 byte missing between 1 byte chars + W("\x0041\x0042"), + // Incomplete 3 byte encoded character 2 bytes missing between 1 byte chars + W("\x0041\x0042"), + // Trailing byte with no lead byte between 1 byte chars + W("\x0041\x0042"), + // Incomplete 2 byte encoded character 1 byte missing before 1 byte char + W("\x0042"), + // Incomplete 3 byte encoded character 1 byte missing before 1 byte char + W("\x0042"), + // Incomplete 3 byte encoded character 2 bytes missing before 1 byte char + W("\x0042"), + // Trailing byte with no lead byte before 1 byte char + W("\x0042"), + // Incomplete 2 byte encoded character 1 byte missing after 1 byte char + W("\x0041"), + // Incomplete 3 byte encoded character 1 byte missing after 1 byte char + W("\x0041"), + // Incomplete 3 byte encoded character 2 bytes missing after 1 byte char + W("\x0041"), + // Trailing byte with no lead byte after 1 byte char + W("\x0041"), + // Incomplete 2 byte encoded character 1 byte missing between 2 byte chars + W("\x0080\x00FF"), + // Incomplete 3 byte encoded character 1 byte missing between 2 byte chars + W("\x0080\x00FF"), + // Incomplete 3 byte encoded character 2 bytes missing between 2 byte chars + W("\x0080\x00FF"), + // Trailing byte with no lead byte between 2 byte chars + W("\x0080\x00FF"), + // 2 byte encoded character in non-shortest form encodings (these are not allowed) + W(""), + // 3 byte encoded character in non-shortest form encodings (these are not allowed) + W(""), + // 4 byte encoded character in non-shortest form encodings (these are not allowed) + W(""), + }; + + for (int i = 0; i < (sizeof(utf8Strings) / sizeof(utf8Strings[0])); i++) + { + ret = MultiByteToWideChar(CP_UTF8, 0, utf8Strings[i], -1, NULL, 0); + WCHAR* wideBuffer = (WCHAR*)malloc(ret * sizeof(WCHAR)); + ret2 = MultiByteToWideChar(CP_UTF8, 0, utf8Strings[i], -1, wideBuffer, ret); + if (ret != ret2) + { + Fail("MultiByteToWideChar string %d: returned different string length for empty and real dest buffers!\n" + "Got %d for the empty one, %d for real one.\n", i, ret2, ret); + } + + if (wcscmp(wideBuffer, unicodeStrings[i]) != 0) + { + Fail("MultiByteToWideChar string %d: the resulting string doesn't match the expected one!\n", i); + } + + free(wideBuffer); + } + + PAL_Terminate(); + + return PASS; +} diff --git a/src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/CMakeLists.txt index 85824dd..5ac7433 100644 --- a/src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_setthreadlocale_test1 diff --git a/src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/test1.c b/src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/test1.c rename to src/pal/tests/palsuite/locale_info/SetThreadLocale/test1/test1.cpp diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/CMakeLists.txt index 0d1d12b..07dae64 100644 --- a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_widechartomultibyte_test1 diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/test1.c b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/test1.c rename to src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test1/test1.cpp diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/CMakeLists.txt index bbfad2c..99c64af 100644 --- a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_widechartomultibyte_test2 diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/test2.c b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/test2.c rename to src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test2/test2.cpp diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/CMakeLists.txt index 0edfd73..70dabea 100644 --- a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_widechartomultibyte_test3 diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/test3.c b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/test3.c rename to src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test3/test3.cpp diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/CMakeLists.txt index f0ffd84..8839c19 100644 --- a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_widechartomultibyte_test4 diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/test4.c b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/test4.c rename to src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test4/test4.cpp diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/CMakeLists.txt b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/CMakeLists.txt index 6ca2a62..e006578 100644 --- a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_widechartomultibyte_test5 diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/test5.c b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/test5.c deleted file mode 100644 index 3ca0d90..0000000 --- a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/test5.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================================ -** -** Source: test4.c -** -** Purpose: Tests WideCharMultiByte with UTF-8 encoding -** -** -**==========================================================================*/ - -#include - -int __cdecl main(int argc, char *argv[]) -{ - int ret; - int ret2; - - if (PAL_Initialize(argc, argv)) - { - return FAIL; - } - - const WCHAR * const unicodeStrings[] = - { - // Correct strings - - // Empty string - W(""), - // 1 byte encoded 1 character long string - W("A"), - // 2 byte encoded 1 character long string - W("\x0080"), - // 3 byte encoded 1 character long string - W("\x0800"), - // 1 byte encoded characters only - W("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), - // 2 byte encoded characters only - W("\x0080\x00FF\x01C1\x07FF"), - // valid 3 byte encoded characters only - W("\x0800\x1D88\x1000\xFFFF"), - // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 1 byte char - W("\x0041\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF\x0045"), - // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 1 byte char, ending with 2 byte one - W("\x0041\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF"), - // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 2 byte char, ending with 1 byte one - W("\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF\x0045"), - // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 2 byte char - W("\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF"), - // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 1 byte char - W("\x0041\x0042\x0080\x00FF\x0043\x0044\x01C1\x07FF\x0045\x0046"), - // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 1 byte char, ending with 2 byte one - W("\x0041\x0042\x0080\x00FF\x0043\x0044\x01C1\x07FF"), - // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 2 byte char, ending with 1 byte one - W("\x0080\x00FF\x0043\x0044\x01C1\x07FF\x0045\x0046"), - // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 2 byte char - W("\x0080\x00FF\x0043\x0044\x01C1\x07FF"), - // Surrogates - W("\xD800\xDC00\xD800\xDE40\xDAC0\xDFB0\xDBFF\xDFFF"), - - // Strings with errors - - // Single high surrogate - W("\xD800"), - // Single low surrogate - W("\xDC00"), - // Character followed by single high surrogate - W("\x0041\xD800"), - // Character followed by single low surrogate - W("\x0041\xDC00"), - // Single high surrogate between two characters - W("\x0041\xD800\x0042"), - // Single low surrogate between two characters - W("\x0041\xDC00\x0042"), - }; - - const char * const utf8Strings[] = - { - // Correct strings - - // Empty string - "", - // 1 byte encoded 1 character long string - "A", - // 2 byte encoded 1 character long string - "\xC2\x80", - // 3 byte encoded 1 character long string - "\xE0\xA0\x80", - // 1 byte encoded characters only - "ABCDEFGHIJKLMNOPQRSTUVWXYZ", - // valid 2 byte encoded characters only - "\xC2\x80\xC3\xBF\xC7\x81\xDF\xBF", - // valid 3 byte encoded characters only - "\xE0\xA0\x80\xE1\xB6\x88\xE1\x80\x80\xEF\xBF\xBF", - // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 1 byte char - "\x41\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF\x45", - // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 1 byte char, ending with 2 byte one - "\x41\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF", - // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 2 byte char, ending with 1 byte one - "\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF\x45", - // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 2 byte char - "\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF", - // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 1 byte char - "\x41\x42\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF\x45\x46", - // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 1 byte char, ending with 2 byte one - "\x41\x42\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF", - // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 2 byte char, ending with 1 byte one - "\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF\x45\x46", - // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 2 byte char - "\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF", - // Surrogates - "\xF0\x90\x80\x80\xF0\x90\x89\x80\xF3\x80\x8E\xB0\xF4\x8F\xBF\xBF", - - // Strings with errors - - // Single high surrogate - "\xEF\xBF\xBD", - // Single low surrogate - "\xEF\xBF\xBD", - // Character followed by single high surrogate - "\x41\xEF\xBF\xBD", - // Character followed by single low surrogate - "\x41\xEF\xBF\xBD", - // Single high surrogate between two characters - "\x41\xEF\xBF\xBD\x42", - // Single low surrogate between two characters - "\x41\xEF\xBF\xBD\x42", - }; - - for (int i = 0; i < (sizeof(unicodeStrings) / sizeof(unicodeStrings[0])); i++) - { - ret = WideCharToMultiByte(CP_UTF8, 0, unicodeStrings[i], -1, NULL, 0, NULL, NULL); - CHAR* utf8Buffer = malloc(ret * sizeof(CHAR)); - ret2 = WideCharToMultiByte(CP_UTF8, 0, unicodeStrings[i], -1, utf8Buffer, ret, NULL, NULL); - if (ret != ret2) - { - Fail("WideCharToMultiByte string %d: returned different string length for empty and real dest buffers!\n" - "Got %d for the empty one, %d for real one.\n", i, ret2, ret); - } - - if (strcmp(utf8Buffer, utf8Strings[i]) != 0) - { - Fail("WideCharToMultiByte string %d: the resulting string doesn't match the expected one!\n", i); - } - - free(utf8Buffer); - } - - PAL_Terminate(); - - return PASS; -} \ No newline at end of file diff --git a/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/test5.cpp b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/test5.cpp new file mode 100644 index 0000000..393516a --- /dev/null +++ b/src/pal/tests/palsuite/locale_info/WideCharToMultiByte/test5/test5.cpp @@ -0,0 +1,154 @@ +// 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. + +/*============================================================================ +** +** Source: test4.c +** +** Purpose: Tests WideCharMultiByte with UTF-8 encoding +** +** +**==========================================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + int ret; + int ret2; + + if (PAL_Initialize(argc, argv)) + { + return FAIL; + } + + const WCHAR * const unicodeStrings[] = + { + // Correct strings + + // Empty string + W(""), + // 1 byte encoded 1 character long string + W("A"), + // 2 byte encoded 1 character long string + W("\x0080"), + // 3 byte encoded 1 character long string + W("\x0800"), + // 1 byte encoded characters only + W("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), + // 2 byte encoded characters only + W("\x0080\x00FF\x01C1\x07FF"), + // valid 3 byte encoded characters only + W("\x0800\x1D88\x1000\xFFFF"), + // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 1 byte char + W("\x0041\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF\x0045"), + // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 1 byte char, ending with 2 byte one + W("\x0041\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF"), + // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 2 byte char, ending with 1 byte one + W("\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF\x0045"), + // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 2 byte char + W("\x0080\x0042\x00FF\x0043\x01C1\x0044\x07FF"), + // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 1 byte char + W("\x0041\x0042\x0080\x00FF\x0043\x0044\x01C1\x07FF\x0045\x0046"), + // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 1 byte char, ending with 2 byte one + W("\x0041\x0042\x0080\x00FF\x0043\x0044\x01C1\x07FF"), + // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 2 byte char, ending with 1 byte one + W("\x0080\x00FF\x0043\x0044\x01C1\x07FF\x0045\x0046"), + // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 2 byte char + W("\x0080\x00FF\x0043\x0044\x01C1\x07FF"), + // Surrogates + W("\xD800\xDC00\xD800\xDE40\xDAC0\xDFB0\xDBFF\xDFFF"), + + // Strings with errors + + // Single high surrogate + W("\xD800"), + // Single low surrogate + W("\xDC00"), + // Character followed by single high surrogate + W("\x0041\xD800"), + // Character followed by single low surrogate + W("\x0041\xDC00"), + // Single high surrogate between two characters + W("\x0041\xD800\x0042"), + // Single low surrogate between two characters + W("\x0041\xDC00\x0042"), + }; + + const char * const utf8Strings[] = + { + // Correct strings + + // Empty string + "", + // 1 byte encoded 1 character long string + "A", + // 2 byte encoded 1 character long string + "\xC2\x80", + // 3 byte encoded 1 character long string + "\xE0\xA0\x80", + // 1 byte encoded characters only + "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + // valid 2 byte encoded characters only + "\xC2\x80\xC3\xBF\xC7\x81\xDF\xBF", + // valid 3 byte encoded characters only + "\xE0\xA0\x80\xE1\xB6\x88\xE1\x80\x80\xEF\xBF\xBF", + // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 1 byte char + "\x41\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF\x45", + // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 1 byte char, ending with 2 byte one + "\x41\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF", + // 1 byte and 2 byte encoded characters interleaved 1:1 starting with 2 byte char, ending with 1 byte one + "\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF\x45", + // 1 byte and 2 byte encoded characters interleaved 1:1 starting and ending with 2 byte char + "\xC2\x80\x42\xC3\xBF\x43\xC7\x81\x44\xDF\xBF", + // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 1 byte char + "\x41\x42\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF\x45\x46", + // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 1 byte char, ending with 2 byte one + "\x41\x42\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF", + // 1 byte and 2 byte encoded characters interleaved 2:2 starting with 2 byte char, ending with 1 byte one + "\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF\x45\x46", + // 1 byte and 2 byte encoded characters interleaved 2:2 starting and ending with 2 byte char + "\xC2\x80\xC3\xBF\x43\x44\xC7\x81\xDF\xBF", + // Surrogates + "\xF0\x90\x80\x80\xF0\x90\x89\x80\xF3\x80\x8E\xB0\xF4\x8F\xBF\xBF", + + // Strings with errors + + // Single high surrogate + "\xEF\xBF\xBD", + // Single low surrogate + "\xEF\xBF\xBD", + // Character followed by single high surrogate + "\x41\xEF\xBF\xBD", + // Character followed by single low surrogate + "\x41\xEF\xBF\xBD", + // Single high surrogate between two characters + "\x41\xEF\xBF\xBD\x42", + // Single low surrogate between two characters + "\x41\xEF\xBF\xBD\x42", + }; + + for (int i = 0; i < (sizeof(unicodeStrings) / sizeof(unicodeStrings[0])); i++) + { + ret = WideCharToMultiByte(CP_UTF8, 0, unicodeStrings[i], -1, NULL, 0, NULL, NULL); + CHAR* utf8Buffer = (CHAR*)malloc(ret * sizeof(CHAR)); + ret2 = WideCharToMultiByte(CP_UTF8, 0, unicodeStrings[i], -1, utf8Buffer, ret, NULL, NULL); + if (ret != ret2) + { + Fail("WideCharToMultiByte string %d: returned different string length for empty and real dest buffers!\n" + "Got %d for the empty one, %d for real one.\n", i, ret2, ret); + } + + if (strcmp(utf8Buffer, utf8Strings[i]) != 0) + { + Fail("WideCharToMultiByte string %d: the resulting string doesn't match the expected one!\n", i); + } + + free(utf8Buffer); + } + + PAL_Terminate(); + + return PASS; +} diff --git a/src/pal/tests/palsuite/miscellaneous/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/CMakeLists.txt index 86f1941..0fd4df8 100644 --- a/src/pal/tests/palsuite/miscellaneous/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/CMakeLists.txt @@ -27,9 +27,6 @@ add_subdirectory(InterLockedExchangeAdd) add_subdirectory(InterlockedExchangePointer) add_subdirectory(InterlockedIncrement) add_subdirectory(InterlockedIncrement64) -add_subdirectory(lstrcatW) -add_subdirectory(lstrcpynW) -add_subdirectory(lstrcpyW) add_subdirectory(lstrlenA) add_subdirectory(lstrlenW) add_subdirectory(queryperformancecounter) @@ -37,8 +34,5 @@ add_subdirectory(queryperformancefrequency) add_subdirectory(SetEnvironmentVariableA) add_subdirectory(SetEnvironmentVariableW) add_subdirectory(SetLastError) -add_subdirectory(wsprintfA) -add_subdirectory(wsprintfW) add_subdirectory(_i64tow) -add_subdirectory(_ui64tow) diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextA/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/CharNextA/test1/CMakeLists.txt index 8506d86..23df52b 100644 --- a/src/pal/tests/palsuite/miscellaneous/CharNextA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/CharNextA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_charnexta_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextA/test1/test.c b/src/pal/tests/palsuite/miscellaneous/CharNextA/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/CharNextA/test1/test.c rename to src/pal/tests/palsuite/miscellaneous/CharNextA/test1/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextA/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/CharNextA/test2/CMakeLists.txt index 04f4679..5f089e9 100644 --- a/src/pal/tests/palsuite/miscellaneous/CharNextA/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/CharNextA/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_charnexta_test2 diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextA/test2/test.c b/src/pal/tests/palsuite/miscellaneous/CharNextA/test2/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/CharNextA/test2/test.c rename to src/pal/tests/palsuite/miscellaneous/CharNextA/test2/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/CMakeLists.txt index bfa12b5..ae1433f 100644 --- a/src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_charnextexa_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/test.c b/src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/test.c rename to src/pal/tests/palsuite/miscellaneous/CharNextExA/test1/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/CMakeLists.txt index 556043a..1c81d1f 100644 --- a/src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_charnextexa_test2 diff --git a/src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/test.c b/src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/test.c rename to src/pal/tests/palsuite/miscellaneous/CharNextExA/test2/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/CMakeLists.txt index bbe37dd..78bb701 100644 --- a/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_closehandle_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/test.c b/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/test.c deleted file mode 100644 index 8e42229..0000000 --- a/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/test.c +++ /dev/null @@ -1,64 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for CloseHandle function -** -** -**=========================================================*/ - -/* Depends on: CreateFile and WriteFile */ - -#include - -int __cdecl main(int argc, char *argv[]) -{ - - HANDLE FileHandle = NULL; - LPDWORD WriteBuffer; /* Used with WriteFile */ - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - WriteBuffer = malloc(sizeof(WORD)); - - if ( WriteBuffer == NULL ) - { - Fail("ERROR: Failed to allocate memory for WriteBuffer pointer. " - "Can't properly exec test case without this.\n"); - } - - - /* Create a file, since this returns to us a HANDLE we can use */ - FileHandle = CreateFile("testfile", - GENERIC_READ | GENERIC_WRITE,0,NULL,CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - - /* Should be able to close this handle */ - if(CloseHandle(FileHandle) == 0) - { - free(WriteBuffer); - Fail("ERROR: (Test 1) Attempted to close a HANDLE on a file, but the " - "return value was <=0, indicating failure.\n"); - } - - free(WriteBuffer); - - PAL_Terminate(); - return PASS; -} - - - - diff --git a/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/test.cpp b/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/test.cpp new file mode 100644 index 0000000..443f89b --- /dev/null +++ b/src/pal/tests/palsuite/miscellaneous/CloseHandle/test1/test.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. +// See the LICENSE file in the project root for more information. + +/*============================================================ +** +** Source: test.c +** +** Purpose: Test for CloseHandle function +** +** +**=========================================================*/ + +/* Depends on: CreateFile and WriteFile */ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + + HANDLE FileHandle = NULL; + LPDWORD WriteBuffer; /* Used with WriteFile */ + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + WriteBuffer = (LPDWORD)malloc(sizeof(WORD)); + + if ( WriteBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for WriteBuffer pointer. " + "Can't properly exec test case without this.\n"); + } + + + /* Create a file, since this returns to us a HANDLE we can use */ + FileHandle = CreateFile("testfile", + GENERIC_READ | GENERIC_WRITE,0,NULL,CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + /* Should be able to close this handle */ + if(CloseHandle(FileHandle) == 0) + { + free(WriteBuffer); + Fail("ERROR: (Test 1) Attempted to close a HANDLE on a file, but the " + "return value was <=0, indicating failure.\n"); + } + + free(WriteBuffer); + + PAL_Terminate(); + return PASS; +} + + + + diff --git a/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/CMakeLists.txt index 75de513..18350f2 100644 --- a/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_closehandle_test2 diff --git a/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/test.c b/src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/test.c rename to src/pal/tests/palsuite/miscellaneous/CloseHandle/test2/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/CMakeLists.txt index af878cb..15a0f57 100644 --- a/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_createpipe_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/test1.c b/src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/test1.c rename to src/pal/tests/palsuite/miscellaneous/CreatePipe/test1/test1.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/CMakeLists.txt index fbd8b0f..47ee4b0 100644 --- a/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_flushinstructioncache_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/test1.c b/src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/test1.c rename to src/pal/tests/palsuite/miscellaneous/FlushInstructionCache/test1/test1.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/CMakeLists.txt index 0f242e9..df91482 100644 --- a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_formatmessagew_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/test.c rename to src/pal/tests/palsuite/miscellaneous/FormatMessageW/test1/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/CMakeLists.txt index 26092ac..818649a 100644 --- a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_formatmessagew_test2 diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/test.c b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/test.c rename to src/pal/tests/palsuite/miscellaneous/FormatMessageW/test2/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/CMakeLists.txt index b430511..516d4bc 100644 --- a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_formatmessagew_test3 diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/test.c b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/test.c rename to src/pal/tests/palsuite/miscellaneous/FormatMessageW/test3/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/CMakeLists.txt index cae8ff1..642727c 100644 --- a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_formatmessagew_test4 diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/test.c b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/test.c rename to src/pal/tests/palsuite/miscellaneous/FormatMessageW/test4/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/CMakeLists.txt index 6779f94..bae1134 100644 --- a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_formatmessagew_test5 diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/test.c b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/test.c rename to src/pal/tests/palsuite/miscellaneous/FormatMessageW/test5/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/CMakeLists.txt index 450b2b8..f403cba 100644 --- a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_formatmessagew_test6 diff --git a/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.c b/src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.c rename to src/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/CMakeLists.txt index be39b63..206707e 100644 --- a/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_freeenvironmentstringsw_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/test.c rename to src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test1/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/CMakeLists.txt index a3688dd..d8197d1 100644 --- a/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_freeenvironmentstringsw_test2 diff --git a/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/test.c b/src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/test.c rename to src/pal/tests/palsuite/miscellaneous/FreeEnvironmentStringsW/test2/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/CMakeLists.txt index e3acf40..92cabba 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetCalendarInfoW.c + GetCalendarInfoW.cpp ) add_executable(paltest_getcalendarinfow_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/GetCalendarInfoW.c b/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/GetCalendarInfoW.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/GetCalendarInfoW.c rename to src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test1/GetCalendarInfoW.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/CMakeLists.txt index cbfd1aa..0cfc967 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetCalendarInfoW.c + GetCalendarInfoW.cpp ) add_executable(paltest_getcalendarinfow_test2 diff --git a/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/GetCalendarInfoW.c b/src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/GetCalendarInfoW.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/GetCalendarInfoW.c rename to src/pal/tests/palsuite/miscellaneous/GetCalendarInfoW/test2/GetCalendarInfoW.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/CMakeLists.txt index 491fdca..d15b84a 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_getcommandlinew_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/test.c deleted file mode 100644 index d8a8174..0000000 --- a/src/pal/tests/palsuite/miscellaneous/GetCommandLineW/test1/test.c +++ /dev/null @@ -1,71 +0,0 @@ -// 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. - -/*============================================================ -** -** Source : test.c -** -** Purpose: Test for GetCommandLineW() function -** -** -**=========================================================*/ - -#define UNICODE -#include - -int __cdecl main(int argc, char *argv[]) -{ - - LPWSTR TheResult = NULL; - WCHAR *CommandLine; - int i; - WCHAR * p; - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - CommandLine = malloc(1024); - wcscpy(CommandLine,convert(argv[0])); - - for(i=1;i + +int __cdecl main(int argc, char *argv[]) +{ + + LPWSTR TheResult = NULL; + WCHAR *CommandLine; + int i; + WCHAR * p; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + CommandLine = (WCHAR*)malloc(1024); + wcscpy(CommandLine,convert(argv[0])); + + for(i=1;i - -int __cdecl main(int argc, char *argv[]) -{ - int err; - WCHAR *wpFormat; - LPCSTR lpString = "gg"; - CONST SYSTEMTIME *lpDate = NULL; - LCID DefaultLocale; - DWORD dwFlags; - int DateSize; - WCHAR *wpBuffer = NULL; - - /*Initialize the PAL environment*/ - err = PAL_Initialize(argc, argv); - if(0 != err) - { - return FAIL; - } - - /*convert to a wide character string*/ - wpFormat = convert((char *)lpString); - - dwFlags = DATE_USE_ALT_CALENDAR; /*set the flags*/ - - - DateSize = 0; - - /*retrieve the buffer size*/ - DateSize = GetDateFormatW( - DefaultLocale, /*system default locale*/ - dwFlags, /*function option*/ - (SYSTEMTIME *)lpDate, /*always is NULL*/ - wpFormat, /*pointer to a picture string*/ - wpBuffer, /*out buffer*/ - DateSize); /*buffer size*/ - - if(DateSize <= 0) - { - free(wpFormat); - Fail("\nRetrieved an invalid buffer size\n"); - } - - wpBuffer = malloc((DateSize + 1)*sizeof(WCHAR)); - if(NULL == wpBuffer) - { - free(wpFormat); - Fail("\nFailed to allocate memory to store the formatted string\n"); - } - - /*format a date by passing an invalid locale indentifier*/ - err = GetDateFormatW( - -1, /*invalid locale identifier*/ - dwFlags, /*function option*/ - (SYSTEMTIME *)lpDate, /*always is NULL, or use system date*/ - wpFormat, /*pointer to a picture string*/ - wpBuffer, /*out buffer*/ - DateSize); /*buffer size*/ - - free(wpBuffer); - free(wpFormat); - - if(0 != err || GetLastError() != ERROR_INVALID_PARAMETER) - { - Fail("\nFailed to call GetDateFormatW for a negative test by " - "passing an invalid parameter, error code=%d\n", GetLastError()); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg1/GetDateFormatW_neg.cpp b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg1/GetDateFormatW_neg.cpp new file mode 100644 index 0000000..96a4811 --- /dev/null +++ b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg1/GetDateFormatW_neg.cpp @@ -0,0 +1,85 @@ +// 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. + +/*============================================================= +** +** Source: GetDateFormatW_neg.c +** +** Purpose: Negative test the GetDateFormatW API. +** Call GetDateFormatW by passing an invalid parameter +** +** +**============================================================*/ +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + WCHAR *wpFormat; + LPCSTR lpString = "gg"; + CONST SYSTEMTIME *lpDate = NULL; + LCID DefaultLocale; + DWORD dwFlags; + int DateSize; + WCHAR *wpBuffer = NULL; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*convert to a wide character string*/ + wpFormat = convert((char *)lpString); + + dwFlags = DATE_USE_ALT_CALENDAR; /*set the flags*/ + + + DateSize = 0; + + /*retrieve the buffer size*/ + DateSize = GetDateFormatW( + DefaultLocale, /*system default locale*/ + dwFlags, /*function option*/ + (SYSTEMTIME *)lpDate, /*always is NULL*/ + wpFormat, /*pointer to a picture string*/ + wpBuffer, /*out buffer*/ + DateSize); /*buffer size*/ + + if(DateSize <= 0) + { + free(wpFormat); + Fail("\nRetrieved an invalid buffer size\n"); + } + + wpBuffer = (WCHAR*)malloc((DateSize + 1)*sizeof(WCHAR)); + if(NULL == wpBuffer) + { + free(wpFormat); + Fail("\nFailed to allocate memory to store the formatted string\n"); + } + + /*format a date by passing an invalid locale indentifier*/ + err = GetDateFormatW( + -1, /*invalid locale identifier*/ + dwFlags, /*function option*/ + (SYSTEMTIME *)lpDate, /*always is NULL, or use system date*/ + wpFormat, /*pointer to a picture string*/ + wpBuffer, /*out buffer*/ + DateSize); /*buffer size*/ + + free(wpBuffer); + free(wpFormat); + + if(0 != err || GetLastError() != ERROR_INVALID_PARAMETER) + { + Fail("\nFailed to call GetDateFormatW for a negative test by " + "passing an invalid parameter, error code=%d\n", GetLastError()); + } + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/CMakeLists.txt index 646de91..fcd56fc 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetDateFormatW_neg.c + GetDateFormatW_neg.cpp ) add_executable(paltest_getdateformatw_getdateformatw_neg2 diff --git a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/GetDateFormatW_neg.c b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/GetDateFormatW_neg.c deleted file mode 100644 index 676038f..0000000 --- a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/GetDateFormatW_neg.c +++ /dev/null @@ -1,98 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: GetDateFormatW_neg.c -** -** Purpose: Negative test the GetDateFormatW API. -** Call GetDateFormatW by passing an invalid flag -** -** -**============================================================*/ -#define UNICODE -#include - -int __cdecl main(int argc, char *argv[]) -{ - int err; - WCHAR *wpFormat; - LPCSTR lpString = "gg"; - CONST SYSTEMTIME *lpDate = NULL; - LCID DefaultLocale; - DWORD dwFlags; - int DateSize; - WCHAR *wpBuffer = NULL; - - /*Initialize the PAL environment*/ - err = PAL_Initialize(argc, argv); - if(0 != err) - { - return FAIL; - } - - /*convert to a wide character string*/ - wpFormat = convert((char *)lpString); - - /* - DefaultLocale = GetSystemDefaultLCID() which is not defined in PAL; - - LOCALE_SYSTEM_DEFAULT = MAKELCID(LANG_SYSTEM_DEFAULT, SORT_DEFAULT) - - LANG_SYSTEM_DEFAULT = MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT); - SUBLANG_SYS_DEFAULT is not defined in PAL, here use hardcoding, - the value is from winnt.h - */ - - DefaultLocale = MAKELCID(MAKELANGID(LANG_NEUTRAL, 0x02), SORT_DEFAULT); - - dwFlags = DATE_USE_ALT_CALENDAR; /*set the flags*/ - - - DateSize = 0; - - /*retrieve the buffer size*/ - DateSize = GetDateFormatW( - DefaultLocale, /*system default locale*/ - dwFlags, /*function option*/ - (SYSTEMTIME *)lpDate, /*always is NULL*/ - wpFormat, /*pointer to a picture string*/ - wpBuffer, /*out buffer*/ - DateSize); /*buffer size*/ - - if(DateSize <= 0) - { - free(wpFormat); - Fail("\nRetrieved an invalid buffer size\n"); - } - - wpBuffer = malloc((DateSize + 1)*sizeof(WCHAR)); - if(NULL == wpBuffer) - { - free(wpFormat); - Fail("\nFailed to allocate memory to store the formatted string\n"); - } - - err = GetDateFormatW( - DefaultLocale, /*system default locale*/ - 0x00000001|0x00000008,/*DATE_SHORTDATE|DATE_YEARMONTH */ - /*an invalid flag*/ - (SYSTEMTIME *)lpDate, /*always is NULL, or use system date*/ - wpFormat, /*pointer to a picture string*/ - wpBuffer, /*out buffer*/ - DateSize); /*buffer size*/ - - free(wpBuffer); - free(wpFormat); - - if(0 != err || GetLastError() != ERROR_INVALID_FLAGS) - { - Fail("\nFailed to call GetDateFormatW for a negative test by " - "passing an invalid flag, error code=%d\n", GetLastError()); - } - - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/GetDateFormatW_neg.cpp b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/GetDateFormatW_neg.cpp new file mode 100644 index 0000000..43f32cf --- /dev/null +++ b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/GetDateFormatW_neg2/GetDateFormatW_neg.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================= +** +** Source: GetDateFormatW_neg.c +** +** Purpose: Negative test the GetDateFormatW API. +** Call GetDateFormatW by passing an invalid flag +** +** +**============================================================*/ +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + WCHAR *wpFormat; + LPCSTR lpString = "gg"; + CONST SYSTEMTIME *lpDate = NULL; + LCID DefaultLocale; + DWORD dwFlags; + int DateSize; + WCHAR *wpBuffer = NULL; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*convert to a wide character string*/ + wpFormat = convert((char *)lpString); + + /* + DefaultLocale = GetSystemDefaultLCID() which is not defined in PAL; + + LOCALE_SYSTEM_DEFAULT = MAKELCID(LANG_SYSTEM_DEFAULT, SORT_DEFAULT) + + LANG_SYSTEM_DEFAULT = MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT); + SUBLANG_SYS_DEFAULT is not defined in PAL, here use hardcoding, + the value is from winnt.h + */ + + DefaultLocale = MAKELCID(MAKELANGID(LANG_NEUTRAL, 0x02), SORT_DEFAULT); + + dwFlags = DATE_USE_ALT_CALENDAR; /*set the flags*/ + + + DateSize = 0; + + /*retrieve the buffer size*/ + DateSize = GetDateFormatW( + DefaultLocale, /*system default locale*/ + dwFlags, /*function option*/ + (SYSTEMTIME *)lpDate, /*always is NULL*/ + wpFormat, /*pointer to a picture string*/ + wpBuffer, /*out buffer*/ + DateSize); /*buffer size*/ + + if(DateSize <= 0) + { + free(wpFormat); + Fail("\nRetrieved an invalid buffer size\n"); + } + + wpBuffer = (WCHAR*)malloc((DateSize + 1)*sizeof(WCHAR)); + if(NULL == wpBuffer) + { + free(wpFormat); + Fail("\nFailed to allocate memory to store the formatted string\n"); + } + + err = GetDateFormatW( + DefaultLocale, /*system default locale*/ + 0x00000001|0x00000008,/*DATE_SHORTDATE|DATE_YEARMONTH */ + /*an invalid flag*/ + (SYSTEMTIME *)lpDate, /*always is NULL, or use system date*/ + wpFormat, /*pointer to a picture string*/ + wpBuffer, /*out buffer*/ + DateSize); /*buffer size*/ + + free(wpBuffer); + free(wpFormat); + + if(0 != err || GetLastError() != ERROR_INVALID_FLAGS) + { + Fail("\nFailed to call GetDateFormatW for a negative test by " + "passing an invalid flag, error code=%d\n", GetLastError()); + } + + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/CMakeLists.txt index 8c1e4b0..bd86370 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - GetDateFormatW.c + GetDateFormatW.cpp ) add_executable(paltest_getdateformatw_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/GetDateFormatW.c b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/GetDateFormatW.c deleted file mode 100644 index 264e397..0000000 --- a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/GetDateFormatW.c +++ /dev/null @@ -1,100 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: GetDateFormatW.c -** -** Purpose: Positive test the GetDateFormatW API. -** Call GetDateFormatW to format a date string for -** a specified locale -** -** -**============================================================*/ -#define UNICODE -#include - -int __cdecl main(int argc, char *argv[]) -{ - int err; - WCHAR *wpFormat; - LPCSTR lpString = "gg"; - CONST SYSTEMTIME *lpDate = NULL; - LCID DefaultLocale; - DWORD dwFlags; - int DateSize; - WCHAR *wpBuffer = NULL; - - /*Initialize the PAL environment*/ - err = PAL_Initialize(argc, argv); - if(0 != err) - { - return FAIL; - } - - /*convert to a wide character string*/ - wpFormat = convert((char *)lpString); - - /* - DefaultLocale = GetSystemDefaultLCID() which is not defined in PAL; - - LOCALE_SYSTEM_DEFAULT = MAKELCID(LANG_SYSTEM_DEFAULT, SORT_DEFAULT) - - LANG_SYSTEM_DEFAULT = MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT); - SUBLANG_SYS_DEFAULT is not defined in PAL, here use hardcoding, - the value is from winnt.h - */ - DefaultLocale = MAKELCID(MAKELANGID(LANG_NEUTRAL, 0x02), SORT_DEFAULT); - - dwFlags = DATE_USE_ALT_CALENDAR; /*set the flags*/ - - - DateSize = 0; - - /*retrieve the buffer size*/ - DateSize = GetDateFormatW( - DefaultLocale, /*system default locale*/ - dwFlags, /*function option*/ - (SYSTEMTIME *)lpDate, /*always is NULL*/ - wpFormat, /*pointer to a picture string*/ - wpBuffer, /*out buffer*/ - DateSize); /*buffer size*/ - - if(DateSize <= 0) - { - free(wpFormat); - Fail("\nRetrieved an invalid buffer size\n"); - } - - - wpBuffer = malloc((DateSize+1)*sizeof(WCHAR)); - if(NULL == wpBuffer) - { - free(wpFormat); - Fail("\nFailed to allocate memory to store a formatted string\n"); - } - - /*retrieve the formatted string for a specified locale*/ - err = GetDateFormatW( - DefaultLocale, /*system default locale*/ - dwFlags, /*function option*/ - (SYSTEMTIME *)lpDate, /*always is NULL*/ - wpFormat, /*pointer to a picture string*/ - wpBuffer, /*out buffer*/ - DateSize); /*buffer size*/ - - if(0 == err) - { - free(wpBuffer); - free(wpFormat); - Fail("\nFailed to call GetDateFormatW to format a system data " - "as a data string for system default locale!\n"); - } - - free(wpBuffer); - free(wpFormat); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/GetDateFormatW.cpp b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/GetDateFormatW.cpp new file mode 100644 index 0000000..6e3c3b4 --- /dev/null +++ b/src/pal/tests/palsuite/miscellaneous/GetDateFormatW/test1/GetDateFormatW.cpp @@ -0,0 +1,100 @@ +// 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. + +/*============================================================= +** +** Source: GetDateFormatW.c +** +** Purpose: Positive test the GetDateFormatW API. +** Call GetDateFormatW to format a date string for +** a specified locale +** +** +**============================================================*/ +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + WCHAR *wpFormat; + LPCSTR lpString = "gg"; + CONST SYSTEMTIME *lpDate = NULL; + LCID DefaultLocale; + DWORD dwFlags; + int DateSize; + WCHAR *wpBuffer = NULL; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*convert to a wide character string*/ + wpFormat = convert((char *)lpString); + + /* + DefaultLocale = GetSystemDefaultLCID() which is not defined in PAL; + + LOCALE_SYSTEM_DEFAULT = MAKELCID(LANG_SYSTEM_DEFAULT, SORT_DEFAULT) + + LANG_SYSTEM_DEFAULT = MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT); + SUBLANG_SYS_DEFAULT is not defined in PAL, here use hardcoding, + the value is from winnt.h + */ + DefaultLocale = MAKELCID(MAKELANGID(LANG_NEUTRAL, 0x02), SORT_DEFAULT); + + dwFlags = DATE_USE_ALT_CALENDAR; /*set the flags*/ + + + DateSize = 0; + + /*retrieve the buffer size*/ + DateSize = GetDateFormatW( + DefaultLocale, /*system default locale*/ + dwFlags, /*function option*/ + (SYSTEMTIME *)lpDate, /*always is NULL*/ + wpFormat, /*pointer to a picture string*/ + wpBuffer, /*out buffer*/ + DateSize); /*buffer size*/ + + if(DateSize <= 0) + { + free(wpFormat); + Fail("\nRetrieved an invalid buffer size\n"); + } + + + wpBuffer = (WCHAR*)malloc((DateSize+1)*sizeof(WCHAR)); + if(NULL == wpBuffer) + { + free(wpFormat); + Fail("\nFailed to allocate memory to store a formatted string\n"); + } + + /*retrieve the formatted string for a specified locale*/ + err = GetDateFormatW( + DefaultLocale, /*system default locale*/ + dwFlags, /*function option*/ + (SYSTEMTIME *)lpDate, /*always is NULL*/ + wpFormat, /*pointer to a picture string*/ + wpBuffer, /*out buffer*/ + DateSize); /*buffer size*/ + + if(0 == err) + { + free(wpBuffer); + free(wpFormat); + Fail("\nFailed to call GetDateFormatW to format a system data " + "as a data string for system default locale!\n"); + } + + free(wpBuffer); + free(wpFormat); + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/CMakeLists.txt index 306400e..3a745fd 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_getenvironmentstringsw_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/test.c rename to src/pal/tests/palsuite/miscellaneous/GetEnvironmentStringsW/test1/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/CMakeLists.txt index 184a6ef..0721fd6 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_getenvironmentvariablea_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/test.c deleted file mode 100644 index 8862e82..0000000 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/test.c +++ /dev/null @@ -1,84 +0,0 @@ -// 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. - -/*============================================================ -** -** Source : test.c -** -** Purpose: Test for GetEnvironmentVariable() function -** Assign a properly sized buffer and get an environment -** variable, check to ensure it returns the correct values. -** -** -**=========================================================*/ - -#include - -int __cdecl main(int argc, char *argv[]) { - - /* Define some buffers needed for the function */ - char * pResultBuffer = NULL; - int size = 0; - - /* A place to stash the returned values */ - int ReturnValueForLargeBuffer = 0; - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* Recieve and allocate the correct amount of memory for the buffer */ - size = ReturnValueForLargeBuffer = GetEnvironmentVariable("PATH", - pResultBuffer, - 0); - pResultBuffer = malloc(size); - if ( pResultBuffer == NULL ) - { - Fail("ERROR: Failed to allocate memory for pResultBuffer pointer. " - "Can't properly exec test case without this.\n"); - } - - - /* Normal case, PATH should fit into this buffer */ - ReturnValueForLargeBuffer = GetEnvironmentVariable("PATH", - pResultBuffer, - size); - - /* Ensure that it returned a positive value */ - if(ReturnValueForLargeBuffer <= 0) - { - free(pResultBuffer); - - Fail("The return was %d, which indicates that the function failed.\n", - ReturnValueForLargeBuffer); - } - - /* Ensure that it succeeded and copied the correct number of characters. - If this is true, then the return value should be one less of the size of - the buffer. (Doesn't include that NULL byte) - */ - - if(ReturnValueForLargeBuffer != size-1) - { - free(pResultBuffer); - - Fail("The value returned was %d when it should have been %d. " - "This should be the number of characters copied, minus the " - "NULL byte.\n",ReturnValueForLargeBuffer, size-1); - } - - - free(pResultBuffer); - - PAL_Terminate(); - return PASS; -} - - - diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/test.cpp b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/test.cpp new file mode 100644 index 0000000..23e9974 --- /dev/null +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test1/test.cpp @@ -0,0 +1,84 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for GetEnvironmentVariable() function +** Assign a properly sized buffer and get an environment +** variable, check to ensure it returns the correct values. +** +** +**=========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) { + + /* Define some buffers needed for the function */ + char * pResultBuffer = NULL; + int size = 0; + + /* A place to stash the returned values */ + int ReturnValueForLargeBuffer = 0; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Recieve and allocate the correct amount of memory for the buffer */ + size = ReturnValueForLargeBuffer = GetEnvironmentVariable("PATH", + pResultBuffer, + 0); + pResultBuffer = (char*)malloc(size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer. " + "Can't properly exec test case without this.\n"); + } + + + /* Normal case, PATH should fit into this buffer */ + ReturnValueForLargeBuffer = GetEnvironmentVariable("PATH", + pResultBuffer, + size); + + /* Ensure that it returned a positive value */ + if(ReturnValueForLargeBuffer <= 0) + { + free(pResultBuffer); + + Fail("The return was %d, which indicates that the function failed.\n", + ReturnValueForLargeBuffer); + } + + /* Ensure that it succeeded and copied the correct number of characters. + If this is true, then the return value should be one less of the size of + the buffer. (Doesn't include that NULL byte) + */ + + if(ReturnValueForLargeBuffer != size-1) + { + free(pResultBuffer); + + Fail("The value returned was %d when it should have been %d. " + "This should be the number of characters copied, minus the " + "NULL byte.\n",ReturnValueForLargeBuffer, size-1); + } + + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; +} + + + diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/CMakeLists.txt index abfd73f..a9be983 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_getenvironmentvariablea_test2 diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/test.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/test.c rename to src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test2/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/CMakeLists.txt index a63c11b..1c35eba 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_getenvironmentvariablea_test3 diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/test.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/test.c rename to src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test3/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/CMakeLists.txt index 76cfdb6..331ea8c 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_getenvironmentvariablea_test4 diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/test.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/test.c deleted file mode 100644 index 1fea571..0000000 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/test.c +++ /dev/null @@ -1,75 +0,0 @@ -// 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. - -/*============================================================ -** -** Source : test.c -** -** Purpose: Test for GetEnvironmentVariable() function -** Set an Environment Variable, then use GetEnvironmentVariable to -** retrieve it -- ensure that it retrieves properly. -** -** -**=========================================================*/ - -/* Depends on SetEnvironmentVariableW (because we're implmenting - the wide version) and strcmp() -*/ - -#include - -int __cdecl main(int argc, char *argv[]) { - - /* Define some buffers needed for the function */ - char * pResultBuffer = NULL; - WCHAR SomeEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'}; - WCHAR TheEnvironmentValue[] = {'T','E','S','T','\0'}; - int size = 0; - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - SetEnvironmentVariableW(SomeEnvironmentVariable, - TheEnvironmentValue); - - - /* Normal case, PATH should fit into this buffer */ - size = GetEnvironmentVariable("PALTEST", // Variable Name - pResultBuffer, // Buffer for Value - 0); // Buffer size - - pResultBuffer = malloc(size); - if ( pResultBuffer == NULL ) - { - Fail("ERROR: Failed to allocate memory for pResultBuffer pointer. " - "Can't properly exec test case without this.\n"); - } - - - GetEnvironmentVariable("PALTEST", - pResultBuffer, - size); - - if(strcmp(pResultBuffer,"TEST") != 0) - { - free(pResultBuffer); - Fail("ERROR: The value in the buffer should have been 'TEST' but " - "was really '%s'.\n",pResultBuffer); - - } - - free(pResultBuffer); - - PAL_Terminate(); - return PASS; -} - - - diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/test.cpp b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/test.cpp new file mode 100644 index 0000000..a09eb88 --- /dev/null +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test4/test.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for GetEnvironmentVariable() function +** Set an Environment Variable, then use GetEnvironmentVariable to +** retrieve it -- ensure that it retrieves properly. +** +** +**=========================================================*/ + +/* Depends on SetEnvironmentVariableW (because we're implmenting + the wide version) and strcmp() +*/ + +#include + +int __cdecl main(int argc, char *argv[]) { + + /* Define some buffers needed for the function */ + char * pResultBuffer = NULL; + WCHAR SomeEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'}; + WCHAR TheEnvironmentValue[] = {'T','E','S','T','\0'}; + int size = 0; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + SetEnvironmentVariableW(SomeEnvironmentVariable, + TheEnvironmentValue); + + + /* Normal case, PATH should fit into this buffer */ + size = GetEnvironmentVariable("PALTEST", // Variable Name + pResultBuffer, // Buffer for Value + 0); // Buffer size + + pResultBuffer = (char*)malloc(size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer. " + "Can't properly exec test case without this.\n"); + } + + + GetEnvironmentVariable("PALTEST", + pResultBuffer, + size); + + if(strcmp(pResultBuffer,"TEST") != 0) + { + free(pResultBuffer); + Fail("ERROR: The value in the buffer should have been 'TEST' but " + "was really '%s'.\n",pResultBuffer); + + } + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; +} + + + diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/CMakeLists.txt index 548d86b..69bedf4 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_getenvironmentvariablea_test5 diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/test5.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/test5.c deleted file mode 100644 index 8d63a1a..0000000 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/test5.c +++ /dev/null @@ -1,145 +0,0 @@ -// 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. - -/*============================================================ -** Source : test5.c -** -** Purpose: Test for GetEnvironmentVariableA() function -** Create environment variables that differ only -** in case and verify that they return the appropriate -** value on the BSD environment. -** -** -===========================================================*/ - -#include - -int __cdecl main(int argc, char *argv[]) -{ - -#if WIN32 - - return PASS; - -#else - - /* Define some buffers needed for the function */ - char * pResultBuffer = NULL; - - char FirstEnvironmentVariable[] = {"PALTEST"}; - char FirstEnvironmentValue[] = {"FIRST"}; - - char SecondEnvironmentVariable[] = {"paltest"}; - char SecondEnvironmentValue[] = {"SECOND"}; - - DWORD size = 0; - BOOL bRc = TRUE; - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* Set the first environment variable */ - bRc = SetEnvironmentVariableA(FirstEnvironmentVariable, - FirstEnvironmentValue); - - if(!bRc) - { - Fail("ERROR: SetEnvironmentVariable failed to set a " - "proper environment variable with error %u.\n", GetLastError()); - } - - - /* Normal case, PATH should fit into this buffer */ - size = GetEnvironmentVariableA(FirstEnvironmentVariable, - pResultBuffer, - 0); - - /* To account for the null character at the end of the string */ - size = size + 1; - - pResultBuffer = malloc(sizeof(char)*size); - if ( pResultBuffer == NULL ) - { - Fail("ERROR: Failed to allocate memory for pResultBuffer pointer\n."); - } - - /* Try to retrieve the value of the first environment variable */ - GetEnvironmentVariableA(FirstEnvironmentVariable, - pResultBuffer, - size); - - if ( pResultBuffer == NULL ) - { - free(pResultBuffer); - Fail("ERROR: GetEnvironmentVariable failed to return a value " - "from a proper environment variable with error %u.\n", - GetLastError()); - } - - /* Compare the strings to see that the correct variable was returned */ - if(strcmp(pResultBuffer,FirstEnvironmentValue) != 0) - { - free(pResultBuffer); - Fail("ERROR: The value in the buffer should have been '%s' but " - "was really '%s'.\n",FirstEnvironmentValue, pResultBuffer); - } - - free(pResultBuffer); - - /* Set the second environment Variable */ - bRc = SetEnvironmentVariableA(SecondEnvironmentVariable, - SecondEnvironmentValue); - - if(!bRc) - { - Fail("ERROR: SetEnvironmentVariable failed to set a " - "proper environment variable with error %u.\n", - GetLastError()); - } - - /* Reallocate the memory for the string */ - pResultBuffer = malloc(sizeof(char)*size); - if ( pResultBuffer == NULL ) - { - Fail("ERROR: Failed to allocate memory for pResultBuffer pointer."); - } - - /* Try retrieving the value of the first variable, even though the - second variable has the same spelling and only differs in case */ - GetEnvironmentVariableA(FirstEnvironmentVariable, - pResultBuffer, - size); - - if ( pResultBuffer == NULL ) - { - free(pResultBuffer); - Fail("ERROR: GetEnvironmentVariable failed to return a value " - "from a proper environment variable with error %u.\n", - GetLastError()); - } - - /* Compare the two strings to confirm that the right value is returned */ - if(strcmp(pResultBuffer,FirstEnvironmentValue) != 0) - { - free(pResultBuffer); - Fail("ERROR: The value in the buffer should have been '%s' but " - "was really '%s'.\n",FirstEnvironmentValue,pResultBuffer); - } - - free(pResultBuffer); - - PAL_Terminate(); - return PASS; - -#endif -} - - - diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/test5.cpp b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/test5.cpp new file mode 100644 index 0000000..19a4d25 --- /dev/null +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test5/test5.cpp @@ -0,0 +1,145 @@ +// 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. + +/*============================================================ +** Source : test5.c +** +** Purpose: Test for GetEnvironmentVariableA() function +** Create environment variables that differ only +** in case and verify that they return the appropriate +** value on the BSD environment. +** +** +===========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + +#if WIN32 + + return PASS; + +#else + + /* Define some buffers needed for the function */ + char * pResultBuffer = NULL; + + char FirstEnvironmentVariable[] = {"PALTEST"}; + char FirstEnvironmentValue[] = {"FIRST"}; + + char SecondEnvironmentVariable[] = {"paltest"}; + char SecondEnvironmentValue[] = {"SECOND"}; + + DWORD size = 0; + BOOL bRc = TRUE; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Set the first environment variable */ + bRc = SetEnvironmentVariableA(FirstEnvironmentVariable, + FirstEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", GetLastError()); + } + + + /* Normal case, PATH should fit into this buffer */ + size = GetEnvironmentVariableA(FirstEnvironmentVariable, + pResultBuffer, + 0); + + /* To account for the null character at the end of the string */ + size = size + 1; + + pResultBuffer = (char*)malloc(sizeof(char)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer\n."); + } + + /* Try to retrieve the value of the first environment variable */ + GetEnvironmentVariableA(FirstEnvironmentVariable, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + free(pResultBuffer); + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the strings to see that the correct variable was returned */ + if(strcmp(pResultBuffer,FirstEnvironmentValue) != 0) + { + free(pResultBuffer); + Fail("ERROR: The value in the buffer should have been '%s' but " + "was really '%s'.\n",FirstEnvironmentValue, pResultBuffer); + } + + free(pResultBuffer); + + /* Set the second environment Variable */ + bRc = SetEnvironmentVariableA(SecondEnvironmentVariable, + SecondEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", + GetLastError()); + } + + /* Reallocate the memory for the string */ + pResultBuffer = (char*)malloc(sizeof(char)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer."); + } + + /* Try retrieving the value of the first variable, even though the + second variable has the same spelling and only differs in case */ + GetEnvironmentVariableA(FirstEnvironmentVariable, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + free(pResultBuffer); + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the two strings to confirm that the right value is returned */ + if(strcmp(pResultBuffer,FirstEnvironmentValue) != 0) + { + free(pResultBuffer); + Fail("ERROR: The value in the buffer should have been '%s' but " + "was really '%s'.\n",FirstEnvironmentValue,pResultBuffer); + } + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; + +#endif +} + + + diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/CMakeLists.txt index a0873bb..38c1867 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test6.c + test6.cpp ) add_executable(paltest_getenvironmentvariablea_test6 diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/test6.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/test6.c deleted file mode 100644 index 8ef7571..0000000 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/test6.c +++ /dev/null @@ -1,99 +0,0 @@ -// 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. - -/*============================================================ -** Source : test6.c -** -** Purpose: Test for GetEnvironmentVariableA() function -** Create environment variables that differ only -** in case and verify that they return the appropriate -** value on the BSD environment. -** - -** -===========================================================*/ - -#include - -int __cdecl main(int argc, char *argv[]) -{ - -#if WIN32 - - /* Define some buffers needed for the function */ - char * pResultBuffer = NULL; - - char FirstEnvironmentVariable[] = {"PALTEST"}; - char FirstEnvironmentValue[] = {"FIRST"}; - char ModifiedEnvVar[] = {"paltest"}; - - DWORD size = 0; - BOOL bRc = TRUE; - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* Set the first environment variable */ - bRc = SetEnvironmentVariableA(FirstEnvironmentVariable, - FirstEnvironmentValue); - - if(!bRc) - { - Fail("ERROR: SetEnvironmentVariable failed to set a " - "proper environment variable with error %u.\n", - GetLastError()); - } - - /* Normal case, PATH should fit into this buffer */ - size = GetEnvironmentVariableA(ModifiedEnvVar, - pResultBuffer, - 0); - - /* To account for the nul character at the end of the string */ - size = size + 1; - - pResultBuffer = malloc(sizeof(char)*size); - if ( pResultBuffer == NULL ) - { - Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); - } - - /* Try to retrieve the value of the first environment variable */ - GetEnvironmentVariableA(ModifiedEnvVar, - pResultBuffer, - size); - - if ( pResultBuffer == NULL ) - { - free(pResultBuffer); - Fail("ERROR: GetEnvironmentVariable failed to return a value " - "from a proper environment variable with error %u.\n", - GetLastError()); - } - - /* Compare the strings to see that the correct variable was returned */ - if(strcmp(pResultBuffer,FirstEnvironmentValue) != 0) - { - free(pResultBuffer); - Fail("ERROR: The value in the buffer should have been '%s' but " - "was really '%s'.\n",FirstEnvironmentValue, pResultBuffer); - } - - free(pResultBuffer); - - PAL_Terminate(); - return PASS; - - -#else - - return PASS; -#endif -} diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/test6.cpp b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/test6.cpp new file mode 100644 index 0000000..837036a --- /dev/null +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableA/test6/test6.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================ +** Source : test6.c +** +** Purpose: Test for GetEnvironmentVariableA() function +** Create environment variables that differ only +** in case and verify that they return the appropriate +** value on the BSD environment. +** + +** +===========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + +#if WIN32 + + /* Define some buffers needed for the function */ + char * pResultBuffer = NULL; + + char FirstEnvironmentVariable[] = {"PALTEST"}; + char FirstEnvironmentValue[] = {"FIRST"}; + char ModifiedEnvVar[] = {"paltest"}; + + DWORD size = 0; + BOOL bRc = TRUE; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Set the first environment variable */ + bRc = SetEnvironmentVariableA(FirstEnvironmentVariable, + FirstEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", + GetLastError()); + } + + /* Normal case, PATH should fit into this buffer */ + size = GetEnvironmentVariableA(ModifiedEnvVar, + pResultBuffer, + 0); + + /* To account for the nul character at the end of the string */ + size = size + 1; + + pResultBuffer = (char*)malloc(sizeof(char)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); + } + + /* Try to retrieve the value of the first environment variable */ + GetEnvironmentVariableA(ModifiedEnvVar, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + free(pResultBuffer); + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the strings to see that the correct variable was returned */ + if(strcmp(pResultBuffer,FirstEnvironmentValue) != 0) + { + free(pResultBuffer); + Fail("ERROR: The value in the buffer should have been '%s' but " + "was really '%s'.\n",FirstEnvironmentValue, pResultBuffer); + } + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; + + +#else + + return PASS; +#endif +} diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/CMakeLists.txt index 567c992..a3cb878 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_getenvironmentvariablew_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/test.c deleted file mode 100644 index 6c76450..0000000 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/test.c +++ /dev/null @@ -1,79 +0,0 @@ -// 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. - -/*============================================================ -** -** Source : test.c -** -** Purpose: Test for GetEnvironmentVariable() function -** -** -**=========================================================*/ - -#define UNICODE -#include - -int __cdecl main(int argc, char *argv[]) -{ - - /* Define some buffers needed for the function */ - WCHAR * pResultBuffer = NULL; - int size = 0; - - /* A place to stash the returned values */ - int ReturnValueForLargeBuffer = 0; - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* Recieve and allocate the correct amount of memory for the buffer */ - size = ReturnValueForLargeBuffer = - GetEnvironmentVariable(convert("PATH"), - pResultBuffer, - 0); - - pResultBuffer = malloc(size*sizeof(WCHAR)); - if ( pResultBuffer == NULL ) - { - Fail("ERROR: Failed to allocate memory for pResultBuffer pointer. " - "Can't properly exec test case without this.\n"); - } - - - /* Normal case, PATH should fit into this buffer */ - ReturnValueForLargeBuffer = GetEnvironmentVariable(convert("PATH"), - pResultBuffer, - size); - free(pResultBuffer); - - /* Ensure that it returned a positive value */ - if(ReturnValueForLargeBuffer <= 0) - { - Fail("The return was %d, which indicates that the function failed.\n", - ReturnValueForLargeBuffer); - } - - /* Ensure that it succeeded and copied the correct number of characters. - If this is true, then the return value should be one less of the - size of the buffer. (Doesn't include that NULL byte) - */ - if(ReturnValueForLargeBuffer != size-1) - { - Fail("The value returned was %d when it should have been %d. This " - "should be the number of characters copied, " - "minus the NULL byte.\n", ReturnValueForLargeBuffer, size-1); - } - - PAL_Terminate(); - return PASS; -} - - - diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/test.cpp b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/test.cpp new file mode 100644 index 0000000..cb5fc00 --- /dev/null +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test1/test.cpp @@ -0,0 +1,79 @@ +// 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. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for GetEnvironmentVariable() function +** +** +**=========================================================*/ + +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + + /* Define some buffers needed for the function */ + WCHAR * pResultBuffer = NULL; + int size = 0; + + /* A place to stash the returned values */ + int ReturnValueForLargeBuffer = 0; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Recieve and allocate the correct amount of memory for the buffer */ + size = ReturnValueForLargeBuffer = + GetEnvironmentVariable(convert("PATH"), + pResultBuffer, + 0); + + pResultBuffer = (WCHAR*)malloc(size*sizeof(WCHAR)); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer. " + "Can't properly exec test case without this.\n"); + } + + + /* Normal case, PATH should fit into this buffer */ + ReturnValueForLargeBuffer = GetEnvironmentVariable(convert("PATH"), + pResultBuffer, + size); + free(pResultBuffer); + + /* Ensure that it returned a positive value */ + if(ReturnValueForLargeBuffer <= 0) + { + Fail("The return was %d, which indicates that the function failed.\n", + ReturnValueForLargeBuffer); + } + + /* Ensure that it succeeded and copied the correct number of characters. + If this is true, then the return value should be one less of the + size of the buffer. (Doesn't include that NULL byte) + */ + if(ReturnValueForLargeBuffer != size-1) + { + Fail("The value returned was %d when it should have been %d. This " + "should be the number of characters copied, " + "minus the NULL byte.\n", ReturnValueForLargeBuffer, size-1); + } + + PAL_Terminate(); + return PASS; +} + + + diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/CMakeLists.txt index 7234f61..2c6ec62 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_getenvironmentvariablew_test2 diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/test.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/test.c rename to src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test2/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/CMakeLists.txt index bafd75e..6af382b 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_getenvironmentvariablew_test3 diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/test.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/test.c rename to src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test3/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/CMakeLists.txt index f870bd6..674b187 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_getenvironmentvariablew_test4 diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/test.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/test.c deleted file mode 100644 index b5894ef..0000000 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/test.c +++ /dev/null @@ -1,63 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -/*============================================================ -** -** Source : test.c -** -** Purpose: Test for GetEnvironmentVariable() function -** -** -**=========================================================*/ - -/* Depends on SetEnvironmentVariableW (because we're implmenting the wide - version) and strcmp() */ - -#define UNICODE -#include - -int __cdecl main(int argc, char *argv[]) { - - /* Define some buffers needed for the function */ - WCHAR * pResultBuffer = NULL; - WCHAR SomeEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'}; - WCHAR TheEnvironmentValue[] = {'T','E','S','T','\0'}; - int size; - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - SetEnvironmentVariable(SomeEnvironmentVariable, - TheEnvironmentValue); - - - /* Normal case, PATH should fit into this buffer */ - size = GetEnvironmentVariable(convert("PALTEST"), // Variable Name - pResultBuffer, // Buffer for Value - 0); // Buffer size - - pResultBuffer = malloc(size*sizeof(WCHAR)); - - GetEnvironmentVariable(convert("PALTEST"), - pResultBuffer, - size); - - if(wcsncmp(pResultBuffer,convert("TEST"),wcslen(pResultBuffer) * 2) != 0) - { - Fail("ERROR: The value in the buffer should have been 'TEST' but was " - "really '%s'.",convertC(pResultBuffer)); - } - - free(pResultBuffer); - - PAL_Terminate(); - return PASS; -} - diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/test.cpp b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/test.cpp new file mode 100644 index 0000000..1ee3e72 --- /dev/null +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test4/test.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================ +** +** Source : test.c +** +** Purpose: Test for GetEnvironmentVariable() function +** +** +**=========================================================*/ + +/* Depends on SetEnvironmentVariableW (because we're implmenting the wide + version) and strcmp() */ + +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) { + + /* Define some buffers needed for the function */ + WCHAR * pResultBuffer = NULL; + WCHAR SomeEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'}; + WCHAR TheEnvironmentValue[] = {'T','E','S','T','\0'}; + int size; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + SetEnvironmentVariable(SomeEnvironmentVariable, + TheEnvironmentValue); + + + /* Normal case, PATH should fit into this buffer */ + size = GetEnvironmentVariable(convert("PALTEST"), // Variable Name + pResultBuffer, // Buffer for Value + 0); // Buffer size + + pResultBuffer = (WCHAR*)malloc(size*sizeof(WCHAR)); + + GetEnvironmentVariable(convert("PALTEST"), + pResultBuffer, + size); + + if(wcsncmp(pResultBuffer,convert("TEST"),wcslen(pResultBuffer) * 2) != 0) + { + Fail("ERROR: The value in the buffer should have been 'TEST' but was " + "really '%s'.",convertC(pResultBuffer)); + } + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; +} + diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/CMakeLists.txt index ab44781..71e9747 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_getenvironmentvariablew_test5 diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/test5.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/test5.c deleted file mode 100644 index 58eba3a..0000000 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/test5.c +++ /dev/null @@ -1,144 +0,0 @@ -// 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. - -/*============================================================ -** Source : test5.c -** -** Purpose: Test for GetEnvironmentVariableW() function -** Create environment variables that differ only -** in case and verify that they return the appropriate -** value on the BSD environment. -** -** -===========================================================*/ - -#include - -int __cdecl main(int argc, char *argv[]) -{ - -#if WIN32 - - return PASS; - -#else - - /* Define some buffers needed for the function */ - WCHAR * pResultBuffer = NULL; - - WCHAR FirstEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'}; - WCHAR FirstEnvironmentValue[] = {'F','I','R','S','T','\0'}; - - WCHAR SecondEnvironmentVariable[] = {'p','a','l','t','e','s','t','\0'}; - WCHAR SecondEnvironmentValue[] = {'S','E','C','O','N','D','\0'}; - - DWORD size = 0; - BOOL bRc = TRUE; - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* Set the first environment variable */ - bRc = SetEnvironmentVariableW(FirstEnvironmentVariable, - FirstEnvironmentValue); - - if(!bRc) - { - Fail("ERROR: SetEnvironmentVariable failed to set a " - "proper environment variable with error %u.\n", GetLastError()); - } - - /* Normal case, PATH should fit into this buffer */ - size = GetEnvironmentVariableW(FirstEnvironmentVariable, - pResultBuffer, - 0); - - /* To account for the nul character at the end of the string */ - size = size + 1; - - pResultBuffer = malloc(sizeof(WCHAR)*size); - if ( pResultBuffer == NULL ) - { - Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); - } - - /* Try to retrieve the value of the first environment variable */ - GetEnvironmentVariableW(FirstEnvironmentVariable, - pResultBuffer, - size); - - if ( pResultBuffer == NULL ) - { - free(pResultBuffer); - Fail("ERROR: GetEnvironmentVariable failed to return a value " - "from a proper environment variable with error %u.\n", - GetLastError()); - } - - /* Compare the strings to see that the correct variable was returned */ - if(wcsncmp(pResultBuffer,FirstEnvironmentValue,wcslen(pResultBuffer)) != 0) - { - free(pResultBuffer); - Fail("ERROR: The value in the buffer should have been '%S' but " - "was really '%S'.\n",FirstEnvironmentValue, pResultBuffer); - } - - free(pResultBuffer); - - /* Set the second environment Variable */ - bRc = SetEnvironmentVariableW(SecondEnvironmentVariable, - SecondEnvironmentValue); - - if(!bRc) - { - Fail("ERROR: SetEnvironmentVariable failed to set a " - "proper environment variable with error %u.\n", - GetLastError()); - } - - /* Reallocate the memory for the string */ - pResultBuffer = malloc(sizeof(WCHAR)*size); - if ( pResultBuffer == NULL ) - { - Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); - } - - /* Try retrieving the value of the first variable, even though the - second variable has the same spelling and only differs in case */ - GetEnvironmentVariableW(FirstEnvironmentVariable, - pResultBuffer, - size); - - if ( pResultBuffer == NULL ) - { - free(pResultBuffer); - Fail("ERROR: GetEnvironmentVariable failed to return a value " - "from a proper environment variable with error %u.\n", - GetLastError()); - } - - /* Compare the two strings to confirm that the right value is returned */ - if(wcsncmp(pResultBuffer,FirstEnvironmentValue,wcslen(pResultBuffer)) != 0) - { - free(pResultBuffer); - Fail("ERROR: The value in the buffer should have been '%S' but " - "was really '%S'.\n",FirstEnvironmentValue,pResultBuffer); - } - - free(pResultBuffer); - - PAL_Terminate(); - return PASS; - -#endif -} - - - diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/test5.cpp b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/test5.cpp new file mode 100644 index 0000000..179fc17 --- /dev/null +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test5/test5.cpp @@ -0,0 +1,144 @@ +// 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. + +/*============================================================ +** Source : test5.c +** +** Purpose: Test for GetEnvironmentVariableW() function +** Create environment variables that differ only +** in case and verify that they return the appropriate +** value on the BSD environment. +** +** +===========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + +#if WIN32 + + return PASS; + +#else + + /* Define some buffers needed for the function */ + WCHAR * pResultBuffer = NULL; + + WCHAR FirstEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'}; + WCHAR FirstEnvironmentValue[] = {'F','I','R','S','T','\0'}; + + WCHAR SecondEnvironmentVariable[] = {'p','a','l','t','e','s','t','\0'}; + WCHAR SecondEnvironmentValue[] = {'S','E','C','O','N','D','\0'}; + + DWORD size = 0; + BOOL bRc = TRUE; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Set the first environment variable */ + bRc = SetEnvironmentVariableW(FirstEnvironmentVariable, + FirstEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", GetLastError()); + } + + /* Normal case, PATH should fit into this buffer */ + size = GetEnvironmentVariableW(FirstEnvironmentVariable, + pResultBuffer, + 0); + + /* To account for the nul character at the end of the string */ + size = size + 1; + + pResultBuffer = (WCHAR*)malloc(sizeof(WCHAR)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); + } + + /* Try to retrieve the value of the first environment variable */ + GetEnvironmentVariableW(FirstEnvironmentVariable, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + free(pResultBuffer); + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the strings to see that the correct variable was returned */ + if(wcsncmp(pResultBuffer,FirstEnvironmentValue,wcslen(pResultBuffer)) != 0) + { + free(pResultBuffer); + Fail("ERROR: The value in the buffer should have been '%S' but " + "was really '%S'.\n",FirstEnvironmentValue, pResultBuffer); + } + + free(pResultBuffer); + + /* Set the second environment Variable */ + bRc = SetEnvironmentVariableW(SecondEnvironmentVariable, + SecondEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", + GetLastError()); + } + + /* Reallocate the memory for the string */ + pResultBuffer = (WCHAR*)malloc(sizeof(WCHAR)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); + } + + /* Try retrieving the value of the first variable, even though the + second variable has the same spelling and only differs in case */ + GetEnvironmentVariableW(FirstEnvironmentVariable, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + free(pResultBuffer); + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the two strings to confirm that the right value is returned */ + if(wcsncmp(pResultBuffer,FirstEnvironmentValue,wcslen(pResultBuffer)) != 0) + { + free(pResultBuffer); + Fail("ERROR: The value in the buffer should have been '%S' but " + "was really '%S'.\n",FirstEnvironmentValue,pResultBuffer); + } + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; + +#endif +} + + + diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/CMakeLists.txt index e504c83..8771ab0 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test6.c + test6.cpp ) add_executable(paltest_getenvironmentvariablew_test6 diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/test6.c b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/test6.c deleted file mode 100644 index 85f31be..0000000 --- a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/test6.c +++ /dev/null @@ -1,99 +0,0 @@ -// 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. - -/*============================================================ -** Source : test6.c -** -** Purpose: Test for GetEnvironmentVariableW() function -** Create environment variables that differ only -** in case and verify that they return the appropriate -** value on the BSD environment. -** -** -===========================================================*/ - -#include - -int __cdecl main(int argc, char *argv[]) -{ - -#if WIN32 - - /* Define some buffers needed for the function */ - WCHAR * pResultBuffer = NULL; - - WCHAR FirstEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'}; - WCHAR FirstEnvironmentValue[] = {'F','I','R','S','T','\0'}; - - WCHAR ModifiedEnvironmentVariable[] = {'p','a','l','t','e','s','t','\0'}; - - DWORD size = 0; - BOOL bRc = TRUE; - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* Set the first environment variable */ - bRc = SetEnvironmentVariableW(FirstEnvironmentVariable, - FirstEnvironmentValue); - - if(!bRc) - { - Fail("ERROR: SetEnvironmentVariable failed to set a " - "proper environment variable with error %u.\n", - GetLastError()); - } - - /* Normal case, PATH should fit into this buffer */ - size = GetEnvironmentVariableW(ModifiedEnvironmentVariable, - pResultBuffer, - 0); - - /* To account for the nul character at the end of the string */ - size = size + 1; - - pResultBuffer = malloc(sizeof(WCHAR)*size); - if ( pResultBuffer == NULL ) - { - Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); - } - - /* Try to retrieve the value of the first environment variable */ - GetEnvironmentVariableW(ModifiedEnvironmentVariable, - pResultBuffer, - size); - - if ( pResultBuffer == NULL ) - { - free(pResultBuffer); - Fail("ERROR: GetEnvironmentVariable failed to return a value " - "from a proper environment variable with error %u.\n", - GetLastError()); - } - - /* Compare the strings to see that the correct variable was returned */ - if(wcsncmp(pResultBuffer,FirstEnvironmentValue,wcslen(pResultBuffer)) != 0) - { - free(pResultBuffer); - Fail("ERROR: The value in the buffer should have been '%S' but " - "was really '%S'.\n",FirstEnvironmentValue, pResultBuffer); - } - - free(pResultBuffer); - - PAL_Terminate(); - return PASS; - - -#else - - return PASS; -#endif -} diff --git a/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/test6.cpp b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/test6.cpp new file mode 100644 index 0000000..e376950 --- /dev/null +++ b/src/pal/tests/palsuite/miscellaneous/GetEnvironmentVariableW/test6/test6.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================ +** Source : test6.c +** +** Purpose: Test for GetEnvironmentVariableW() function +** Create environment variables that differ only +** in case and verify that they return the appropriate +** value on the BSD environment. +** +** +===========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + +#if WIN32 + + /* Define some buffers needed for the function */ + WCHAR * pResultBuffer = NULL; + + WCHAR FirstEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'}; + WCHAR FirstEnvironmentValue[] = {'F','I','R','S','T','\0'}; + + WCHAR ModifiedEnvironmentVariable[] = {'p','a','l','t','e','s','t','\0'}; + + DWORD size = 0; + BOOL bRc = TRUE; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Set the first environment variable */ + bRc = SetEnvironmentVariableW(FirstEnvironmentVariable, + FirstEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", + GetLastError()); + } + + /* Normal case, PATH should fit into this buffer */ + size = GetEnvironmentVariableW(ModifiedEnvironmentVariable, + pResultBuffer, + 0); + + /* To account for the nul character at the end of the string */ + size = size + 1; + + pResultBuffer = (WCHAR*)malloc(sizeof(WCHAR)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); + } + + /* Try to retrieve the value of the first environment variable */ + GetEnvironmentVariableW(ModifiedEnvironmentVariable, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + free(pResultBuffer); + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the strings to see that the correct variable was returned */ + if(wcsncmp(pResultBuffer,FirstEnvironmentValue,wcslen(pResultBuffer)) != 0) + { + free(pResultBuffer); + Fail("ERROR: The value in the buffer should have been '%S' but " + "was really '%S'.\n",FirstEnvironmentValue, pResultBuffer); + } + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; + + +#else + + return PASS; +#endif +} diff --git a/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/CMakeLists.txt index 09e650c..3c851c7 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_getlasterror_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetLastError/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/GetLastError/test1/test.c rename to src/pal/tests/palsuite/miscellaneous/GetLastError/test1/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/CMakeLists.txt index 960291f..9419517 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_getsysteminfo_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/test.c rename to src/pal/tests/palsuite/miscellaneous/GetSystemInfo/test1/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/CMakeLists.txt index 5c6ea26..f7be23b 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_gettickcount_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/test.c rename to src/pal/tests/palsuite/miscellaneous/GetTickCount/test1/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/CMakeLists.txt index a1d5ab2..8ed7ace 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_getusernamew_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/test.c rename to src/pal/tests/palsuite/miscellaneous/GetUserNameW/test1/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/CMakeLists.txt index b9dd711..2cb305f 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_getversionexa_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/test.c rename to src/pal/tests/palsuite/miscellaneous/GetVersionExA/test1/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/CMakeLists.txt index d7eb683..0949424 100644 --- a/src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_getversionexw_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/test.c rename to src/pal/tests/palsuite/miscellaneous/GetVersionExW/test1/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/CMakeLists.txt index d41e6bc..bc3f11b 100644 --- a/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_isbadcodeptr_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/test1.c b/src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/test1.c rename to src/pal/tests/palsuite/miscellaneous/IsBadCodePtr/test1/test1.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/CMakeLists.txt index f1e84d7..82aecef 100644 --- a/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_isbadreadptr_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/test.c b/src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/test.c rename to src/pal/tests/palsuite/miscellaneous/IsBadReadPtr/test1/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/CMakeLists.txt index 2b2e6aa..e3a0816 100644 --- a/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_isbadwriteptr_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/test.c b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/test.c rename to src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test1/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/CMakeLists.txt index c033f80..718cbaa 100644 --- a/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_isbadwriteptr_test2 diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/test2.c b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/test2.c rename to src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test2/test2.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/CMakeLists.txt index 32cb901..0efd317 100644 --- a/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_isbadwriteptr_test3 diff --git a/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/test3.c b/src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/test3.c rename to src/pal/tests/palsuite/miscellaneous/IsBadWritePtr/test3/test3.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/CMakeLists.txt index 5e77e8b..bc80853 100644 --- a/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_messageboxw_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/test.c rename to src/pal/tests/palsuite/miscellaneous/MessageBoxW/test1/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/CMakeLists.txt index 4b0af2e..b8993af 100644 --- a/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_messageboxw_test2 diff --git a/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/test.c b/src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/test.c rename to src/pal/tests/palsuite/miscellaneous/MessageBoxW/test2/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/CMakeLists.txt index b662485..5d63281 100644 --- a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_setenvironmentvariablea_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/test1.c b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/test1.c rename to src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test1/test1.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/CMakeLists.txt index c062c6d..fe05887 100644 --- a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_setenvironmentvariablea_test2 diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/test2.c b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/test2.c rename to src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test2/test2.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/CMakeLists.txt index 159f574..98c9dc0 100644 --- a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_setenvironmentvariablea_test3 diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/test3.c b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/test3.c deleted file mode 100644 index fa24275..0000000 --- a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/test3.c +++ /dev/null @@ -1,144 +0,0 @@ -// 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. - -/*============================================================ -** Source : test3.c -** -** Purpose: Test for SetEnvironmentVariableA() function -** Create environment variables that differ only -** in case and verify that they return the appropriate -** value on the BSD environment. -** -** -===========================================================*/ - -#include - -int __cdecl main(int argc, char *argv[]) -{ - -#if WIN32 - - return PASS; - -#else - - /* Define some buffers needed for the function */ - char * pResultBuffer = NULL; - - char FirstEnvironmentVariable[] = {"PALTEST"}; - char FirstEnvironmentValue[] = {"FIRST"}; - - char SecondEnvironmentVariable[] = {"paltest"}; - char SecondEnvironmentValue[] = {"SECOND"}; - - DWORD size = 0; - BOOL bRc = TRUE; - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* Set the first environment variable */ - bRc = SetEnvironmentVariableA(FirstEnvironmentVariable, - FirstEnvironmentValue); - - if(!bRc) - { - Fail("ERROR: SetEnvironmentVariable failed to set a " - "proper environment variable with error %u.\n", - GetLastError()); - } - - /* Set the second environment Variable */ - bRc = SetEnvironmentVariableA(SecondEnvironmentVariable, - SecondEnvironmentValue); - - if(!bRc) - { - Fail("ERROR: SetEnvironmentVariable failed to set a " - "proper environment variable with error %u.\n", - GetLastError()); - } - - - /* Normal case, PATH should fit into this buffer */ - size = GetEnvironmentVariableA(FirstEnvironmentVariable, - pResultBuffer, - 0); - - /* increase size to account for the null char at the end */ - size = size + 1; - - pResultBuffer = malloc(sizeof(char)*size); - if ( pResultBuffer == NULL ) - { - Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); - } - - /* Try to retrieve the value of the first environment variable */ - GetEnvironmentVariable(FirstEnvironmentVariable, - pResultBuffer, - size); - - if ( pResultBuffer == NULL ) - { - free(pResultBuffer); - Fail("ERROR: GetEnvironmentVariable failed to return a value " - "from a proper environment variable with error %u.\n", - GetLastError()); - } - - /* Compare the strings to see that the correct variable was returned */ - if(strcmp(pResultBuffer,FirstEnvironmentValue) != 0) - { - Trace("ERROR: The value in the buffer should have been '%s' but " - "was really '%s'.\n",FirstEnvironmentValue, pResultBuffer); - free(pResultBuffer); - Fail(""); - } - - free(pResultBuffer); - - /* Reallocate the memory for the string */ - pResultBuffer = malloc(sizeof(char)*size); - if ( pResultBuffer == NULL ) - { - Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); - } - - /* Try retrieving the value of the first variable, even though the - second variable has the same spelling and only differs in case */ - GetEnvironmentVariable(SecondEnvironmentVariable, - pResultBuffer, - size); - - if ( pResultBuffer == NULL ) - { - Fail("ERROR: GetEnvironmentVariable failed to return a value " - "from a proper environment variable with error %u.\n", - GetLastError()); - } - - /* Compare the two strings to confirm that the right value is returned */ - if(strcmp(pResultBuffer,SecondEnvironmentValue) != 0) - { - Trace("ERROR: The value in the buffer should have been '%s' but " - "was really '%s'.\n",SecondEnvironmentValue,pResultBuffer); - free(pResultBuffer); - Fail(""); - } - - free(pResultBuffer); - - PAL_Terminate(); - return PASS; - -#endif -} diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/test3.cpp b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/test3.cpp new file mode 100644 index 0000000..539e330 --- /dev/null +++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test3/test3.cpp @@ -0,0 +1,144 @@ +// 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. + +/*============================================================ +** Source : test3.c +** +** Purpose: Test for SetEnvironmentVariableA() function +** Create environment variables that differ only +** in case and verify that they return the appropriate +** value on the BSD environment. +** +** +===========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + +#if WIN32 + + return PASS; + +#else + + /* Define some buffers needed for the function */ + char * pResultBuffer = NULL; + + char FirstEnvironmentVariable[] = {"PALTEST"}; + char FirstEnvironmentValue[] = {"FIRST"}; + + char SecondEnvironmentVariable[] = {"paltest"}; + char SecondEnvironmentValue[] = {"SECOND"}; + + DWORD size = 0; + BOOL bRc = TRUE; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Set the first environment variable */ + bRc = SetEnvironmentVariableA(FirstEnvironmentVariable, + FirstEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", + GetLastError()); + } + + /* Set the second environment Variable */ + bRc = SetEnvironmentVariableA(SecondEnvironmentVariable, + SecondEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", + GetLastError()); + } + + + /* Normal case, PATH should fit into this buffer */ + size = GetEnvironmentVariableA(FirstEnvironmentVariable, + pResultBuffer, + 0); + + /* increase size to account for the null char at the end */ + size = size + 1; + + pResultBuffer = (char*)malloc(sizeof(char)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); + } + + /* Try to retrieve the value of the first environment variable */ + GetEnvironmentVariable(FirstEnvironmentVariable, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + free(pResultBuffer); + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the strings to see that the correct variable was returned */ + if(strcmp(pResultBuffer,FirstEnvironmentValue) != 0) + { + Trace("ERROR: The value in the buffer should have been '%s' but " + "was really '%s'.\n",FirstEnvironmentValue, pResultBuffer); + free(pResultBuffer); + Fail(""); + } + + free(pResultBuffer); + + /* Reallocate the memory for the string */ + pResultBuffer = (char*)malloc(sizeof(char)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); + } + + /* Try retrieving the value of the first variable, even though the + second variable has the same spelling and only differs in case */ + GetEnvironmentVariable(SecondEnvironmentVariable, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the two strings to confirm that the right value is returned */ + if(strcmp(pResultBuffer,SecondEnvironmentValue) != 0) + { + Trace("ERROR: The value in the buffer should have been '%s' but " + "was really '%s'.\n",SecondEnvironmentValue,pResultBuffer); + free(pResultBuffer); + Fail(""); + } + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; + +#endif +} diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/CMakeLists.txt index 29cca8d..1c53d4b 100644 --- a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_setenvironmentvariablea_test4 diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/test4.c b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/test4.c deleted file mode 100644 index 557cef7..0000000 --- a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/test4.c +++ /dev/null @@ -1,100 +0,0 @@ -// 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. - -/*============================================================ -** Source : test4.c -** -** Purpose: Test for SetEnvironmentVariableA() function -** Create environment variables that differ only -** in case and verify that they return the appropriate -** value in the WIN32 Environment -** - -** -===========================================================*/ - -#include - -int __cdecl main(int argc, char *argv[]) -{ - -#if WIN32 - - /* Define some buffers needed for the function */ - char * pResultBuffer = NULL; - - char FirstEnvironmentVariable[] = {"PALTEST"}; - char FirstEnvironmentValue[] = {"FIRST"}; - char ModifiedEnvVar[] = {"paltest"}; - - DWORD size = 0; - BOOL bRc = TRUE; - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* Set the first environment variable */ - bRc = SetEnvironmentVariableA(FirstEnvironmentVariable, - FirstEnvironmentValue); - - if(!bRc) - { - Fail("ERROR: SetEnvironmentVariable failed to set a " - "proper environment variable with error %u.\n", - GetLastError()); - } - - /* Normal case, PATH should fit into this buffer */ - size = GetEnvironmentVariableA(ModifiedEnvVar, - pResultBuffer, - 0); - - /* To account for the null character at the end of the string */ - size = size + 1; - - pResultBuffer = malloc(sizeof(char)*size); - if ( pResultBuffer == NULL ) - { - Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); - } - - /* Try to retrieve the value of the first environment variable */ - GetEnvironmentVariableA(ModifiedEnvVar, - pResultBuffer, - size); - - if ( pResultBuffer == NULL ) - { - free(pResultBuffer); - Fail("ERROR: GetEnvironmentVariable failed to return a value " - "from a proper environment variable with error %u.\n", - GetLastError()); - } - - /* Compare the strings to see that the correct variable was returned */ - if(strcmp(pResultBuffer,FirstEnvironmentValue) != 0) - { - Trace("ERROR: The value in the buffer should have been '%s' but " - "was really '%s'.\n",FirstEnvironmentValue, pResultBuffer); - free(pResultBuffer); - Fail(""); - } - - free(pResultBuffer); - - PAL_Terminate(); - return PASS; - - -#else - - return PASS; -#endif -} diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/test4.cpp b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/test4.cpp new file mode 100644 index 0000000..de3059c --- /dev/null +++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableA/test4/test4.cpp @@ -0,0 +1,100 @@ +// 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. + +/*============================================================ +** Source : test4.c +** +** Purpose: Test for SetEnvironmentVariableA() function +** Create environment variables that differ only +** in case and verify that they return the appropriate +** value in the WIN32 Environment +** + +** +===========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + +#if WIN32 + + /* Define some buffers needed for the function */ + char * pResultBuffer = NULL; + + char FirstEnvironmentVariable[] = {"PALTEST"}; + char FirstEnvironmentValue[] = {"FIRST"}; + char ModifiedEnvVar[] = {"paltest"}; + + DWORD size = 0; + BOOL bRc = TRUE; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Set the first environment variable */ + bRc = SetEnvironmentVariableA(FirstEnvironmentVariable, + FirstEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", + GetLastError()); + } + + /* Normal case, PATH should fit into this buffer */ + size = GetEnvironmentVariableA(ModifiedEnvVar, + pResultBuffer, + 0); + + /* To account for the null character at the end of the string */ + size = size + 1; + + pResultBuffer = (char*)malloc(sizeof(char)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); + } + + /* Try to retrieve the value of the first environment variable */ + GetEnvironmentVariableA(ModifiedEnvVar, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + free(pResultBuffer); + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the strings to see that the correct variable was returned */ + if(strcmp(pResultBuffer,FirstEnvironmentValue) != 0) + { + Trace("ERROR: The value in the buffer should have been '%s' but " + "was really '%s'.\n",FirstEnvironmentValue, pResultBuffer); + free(pResultBuffer); + Fail(""); + } + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; + + +#else + + return PASS; +#endif +} diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/CMakeLists.txt index 247dcee..6eb52ab 100644 --- a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_setenvironmentvariablew_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/test.c rename to src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test1/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/CMakeLists.txt index a69343c..a82d849 100644 --- a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_setenvironmentvariablew_test2 diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/test.c b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/test.c rename to src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test2/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/CMakeLists.txt index e9072c7..266231e 100644 --- a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_setenvironmentvariablew_test3 diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/test3.c b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/test3.c deleted file mode 100644 index 02d0a2d..0000000 --- a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/test3.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================ -** Source : test3.c -** -** Purpose: Test for SetEnvironmentVariableW() function -** Create environment variables that differ only -** in case and verify that they return the appropriate -** value on the BSD environment. -** -** -===========================================================*/ - -#include - -int __cdecl main(int argc, char *argv[]) -{ - -#if WIN32 - - return PASS; - -#else - - /* Define some buffers needed for the function */ - WCHAR * pResultBuffer = NULL; - - WCHAR FirstEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'}; - WCHAR FirstEnvironmentValue[] = {'F','I','R','S','T','\0'}; - - WCHAR SecondEnvironmentVariable[] = {'p','a','l','t','e','s','t','\0'}; - WCHAR SecondEnvironmentValue[] = {'S','E','C','O','N','D','\0'}; - - DWORD size = 0; - BOOL bRc = TRUE; - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* Set the first environment variable */ - bRc = SetEnvironmentVariableW(FirstEnvironmentVariable, - FirstEnvironmentValue); - - if(!bRc) - { - Fail("ERROR: SetEnvironmentVariable failed to set a " - "proper environment variable with error %u.\n", - GetLastError()); - } - - /* Set the second environment Variable */ - bRc = SetEnvironmentVariableW(SecondEnvironmentVariable, - SecondEnvironmentValue); - - if(!bRc) - { - Fail("ERROR: SetEnvironmentVariable failed to set a " - "proper environment variable with error %u.\n", - GetLastError()); - } - - - /* Normal case, PATH should fit into this buffer */ - size = GetEnvironmentVariableW(FirstEnvironmentVariable, - pResultBuffer, - 0); - - /* Increase size to account for the null char at the end */ - size = size + 1; - - pResultBuffer = malloc(sizeof(WCHAR)*size); - if ( pResultBuffer == NULL ) - { - Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); - } - - /* Try to retrieve the value of the first environment variable */ - GetEnvironmentVariableW(FirstEnvironmentVariable, - pResultBuffer, - size); - - if ( pResultBuffer == NULL ) - { - Fail("ERROR: GetEnvironmentVariable failed to return a value " - "from a proper environment variable with error %u.\n", - GetLastError()); - } - - /* Compare the strings to see that the correct variable was returned */ - if(wcscmp(pResultBuffer,FirstEnvironmentValue) != 0) - { - Trace("ERROR: The value in the buffer should have been '%S' but " - "was really '%S'.\n",FirstEnvironmentValue, pResultBuffer); - free(pResultBuffer); - Fail(""); - } - - free(pResultBuffer); - - /* Reallocate the memory for the string */ - pResultBuffer = malloc(sizeof(WCHAR)*size); - if ( pResultBuffer == NULL ) - { - Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); - } - - /* Try retrieving the value of the first variable, even though the - second variable has the same spelling and only differs in case */ - GetEnvironmentVariableW(SecondEnvironmentVariable, - pResultBuffer, - size); - - if ( pResultBuffer == NULL ) - { - Fail("ERROR: GetEnvironmentVariable failed to return a value " - "from a proper environment variable with error %u.\n", - GetLastError()); - } - - /* Compare the two strings to confirm that the right value is returned */ - if(wcscmp(pResultBuffer,SecondEnvironmentValue) != 0) - { - Trace("ERROR: The value in the buffer should have been '%S' but " - "was really '%S'.\n",SecondEnvironmentValue,pResultBuffer); - free(pResultBuffer); - Fail(""); - } - - free(pResultBuffer); - - PAL_Terminate(); - return PASS; - -#endif -} diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/test3.cpp b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/test3.cpp new file mode 100644 index 0000000..5c4d4eb --- /dev/null +++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test3/test3.cpp @@ -0,0 +1,143 @@ +// 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. + +/*============================================================ +** Source : test3.c +** +** Purpose: Test for SetEnvironmentVariableW() function +** Create environment variables that differ only +** in case and verify that they return the appropriate +** value on the BSD environment. +** +** +===========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + +#if WIN32 + + return PASS; + +#else + + /* Define some buffers needed for the function */ + WCHAR * pResultBuffer = NULL; + + WCHAR FirstEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'}; + WCHAR FirstEnvironmentValue[] = {'F','I','R','S','T','\0'}; + + WCHAR SecondEnvironmentVariable[] = {'p','a','l','t','e','s','t','\0'}; + WCHAR SecondEnvironmentValue[] = {'S','E','C','O','N','D','\0'}; + + DWORD size = 0; + BOOL bRc = TRUE; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Set the first environment variable */ + bRc = SetEnvironmentVariableW(FirstEnvironmentVariable, + FirstEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", + GetLastError()); + } + + /* Set the second environment Variable */ + bRc = SetEnvironmentVariableW(SecondEnvironmentVariable, + SecondEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", + GetLastError()); + } + + + /* Normal case, PATH should fit into this buffer */ + size = GetEnvironmentVariableW(FirstEnvironmentVariable, + pResultBuffer, + 0); + + /* Increase size to account for the null char at the end */ + size = size + 1; + + pResultBuffer = (WCHAR*)malloc(sizeof(WCHAR)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); + } + + /* Try to retrieve the value of the first environment variable */ + GetEnvironmentVariableW(FirstEnvironmentVariable, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the strings to see that the correct variable was returned */ + if(wcscmp(pResultBuffer,FirstEnvironmentValue) != 0) + { + Trace("ERROR: The value in the buffer should have been '%S' but " + "was really '%S'.\n",FirstEnvironmentValue, pResultBuffer); + free(pResultBuffer); + Fail(""); + } + + free(pResultBuffer); + + /* Reallocate the memory for the string */ + pResultBuffer = (WCHAR*)malloc(sizeof(WCHAR)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); + } + + /* Try retrieving the value of the first variable, even though the + second variable has the same spelling and only differs in case */ + GetEnvironmentVariableW(SecondEnvironmentVariable, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the two strings to confirm that the right value is returned */ + if(wcscmp(pResultBuffer,SecondEnvironmentValue) != 0) + { + Trace("ERROR: The value in the buffer should have been '%S' but " + "was really '%S'.\n",SecondEnvironmentValue,pResultBuffer); + free(pResultBuffer); + Fail(""); + } + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; + +#endif +} diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/CMakeLists.txt index f5f48ba..c82e0f0 100644 --- a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_setenvironmentvariablew_test4 diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/test4.c b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/test4.c deleted file mode 100644 index b8f7734..0000000 --- a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/test4.c +++ /dev/null @@ -1,99 +0,0 @@ -// 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. - -/*============================================================ -** Source : test4.c -** -** Purpose: Test for SetEnvironmentVariableW() function -** Create environment variables that differ only -** in case and verify that they return the appropriate -** value on the BSD environment. -** -** -===========================================================*/ - -#include - -int __cdecl main(int argc, char *argv[]) -{ - -#if WIN32 - - /* Define some buffers needed for the function */ - WCHAR * pResultBuffer = NULL; - - WCHAR FirstEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'}; - WCHAR FirstEnvironmentValue[] = {'F','I','R','S','T','\0'}; - - WCHAR ModifiedEnvironmentVariable[] = {'p','a','l','t','e','s','t','\0'}; - - DWORD size = 0; - BOOL bRc = TRUE; - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* Set the first environment variable */ - bRc = SetEnvironmentVariableW(FirstEnvironmentVariable, - FirstEnvironmentValue); - - if(!bRc) - { - Fail("ERROR: SetEnvironmentVariable failed to set a " - "proper environment variable with error %u.\n", - GetLastError()); - } - - /* Normal case, PATH should fit into this buffer */ - size = GetEnvironmentVariableW(ModifiedEnvironmentVariable, - pResultBuffer, - 0); - - /* To account for the nul character at the end of the string */ - size = size + 1; - - pResultBuffer = malloc(sizeof(WCHAR)*size); - if ( pResultBuffer == NULL ) - { - Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); - } - - /* Try to retrieve the value of the first environment variable */ - GetEnvironmentVariableW(ModifiedEnvironmentVariable, - pResultBuffer, - size); - - if ( pResultBuffer == NULL ) - { - Fail("ERROR: GetEnvironmentVariable failed to return a value " - "from a proper environment variable with error %u.\n", - GetLastError()); - } - - /* Compare the strings to see that the correct variable was returned */ - if(wcsncmp(pResultBuffer,FirstEnvironmentValue,wcslen(pResultBuffer)) != 0) - { - Trace("ERROR: The value in the buffer should have been '%S' but " - "was really '%S'.\n",FirstEnvironmentValue, pResultBuffer); - free(pResultBuffer); - Fail(""); - } - - free(pResultBuffer); - - PAL_Terminate(); - return PASS; - - -#else - - return PASS; -#endif -} diff --git a/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/test4.cpp b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/test4.cpp new file mode 100644 index 0000000..50c59d6 --- /dev/null +++ b/src/pal/tests/palsuite/miscellaneous/SetEnvironmentVariableW/test4/test4.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================ +** Source : test4.c +** +** Purpose: Test for SetEnvironmentVariableW() function +** Create environment variables that differ only +** in case and verify that they return the appropriate +** value on the BSD environment. +** +** +===========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) +{ + +#if WIN32 + + /* Define some buffers needed for the function */ + WCHAR * pResultBuffer = NULL; + + WCHAR FirstEnvironmentVariable[] = {'P','A','L','T','E','S','T','\0'}; + WCHAR FirstEnvironmentValue[] = {'F','I','R','S','T','\0'}; + + WCHAR ModifiedEnvironmentVariable[] = {'p','a','l','t','e','s','t','\0'}; + + DWORD size = 0; + BOOL bRc = TRUE; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Set the first environment variable */ + bRc = SetEnvironmentVariableW(FirstEnvironmentVariable, + FirstEnvironmentValue); + + if(!bRc) + { + Fail("ERROR: SetEnvironmentVariable failed to set a " + "proper environment variable with error %u.\n", + GetLastError()); + } + + /* Normal case, PATH should fit into this buffer */ + size = GetEnvironmentVariableW(ModifiedEnvironmentVariable, + pResultBuffer, + 0); + + /* To account for the nul character at the end of the string */ + size = size + 1; + + pResultBuffer = (WCHAR*)malloc(sizeof(WCHAR)*size); + if ( pResultBuffer == NULL ) + { + Fail("ERROR: Failed to allocate memory for pResultBuffer pointer.\n"); + } + + /* Try to retrieve the value of the first environment variable */ + GetEnvironmentVariableW(ModifiedEnvironmentVariable, + pResultBuffer, + size); + + if ( pResultBuffer == NULL ) + { + Fail("ERROR: GetEnvironmentVariable failed to return a value " + "from a proper environment variable with error %u.\n", + GetLastError()); + } + + /* Compare the strings to see that the correct variable was returned */ + if(wcsncmp(pResultBuffer,FirstEnvironmentValue,wcslen(pResultBuffer)) != 0) + { + Trace("ERROR: The value in the buffer should have been '%S' but " + "was really '%S'.\n",FirstEnvironmentValue, pResultBuffer); + free(pResultBuffer); + Fail(""); + } + + free(pResultBuffer); + + PAL_Terminate(); + return PASS; + + +#else + + return PASS; +#endif +} diff --git a/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/CMakeLists.txt index 5248d6c..40eb2ff 100644 --- a/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_setlasterror_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/test.c b/src/pal/tests/palsuite/miscellaneous/SetLastError/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/SetLastError/test1/test.c rename to src/pal/tests/palsuite/miscellaneous/SetLastError/test1/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/CMakeLists.txt index 6876d1b..c3c4b61 100644 --- a/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_i64tow_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/test1.c b/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/test1.c deleted file mode 100644 index 9a87328..0000000 --- a/src/pal/tests/palsuite/miscellaneous/_i64tow/test1/test1.c +++ /dev/null @@ -1,76 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: test1.c -** -** Purpose: Tests _i64tow with normal values and different radices, negative -** values, as well as the highest and lowest values. -** -** -**============================================================*/ - -#include - -typedef struct -{ - INT64 value; - int radix; - char *result; -} testCase; - - -int __cdecl main(int argc, char *argv[]) -{ - WCHAR buffer[256]; - WCHAR *testStr; - WCHAR *ret; - int i; - testCase testCases[] = - { - {42, 10, "42"}, - {42, 2, "101010"}, - {29, 32, "t"}, - {-1, 10, "-1"}, - {-1, 8, "1777777777777777777777"}, - {-1, 32, "fvvvvvvvvvvvv"}, - {I64(0x7FFFFFFFFFFFFFFF), 10, "9223372036854775807"}, - {I64(0x8000000000000000), 10, "-9223372036854775808"}, - {0,2,"0"}, - {0,16,"0"}, - {3,16,"3"}, - {15,16,"f"}, - {16,16,"10"}, - - }; - - - if (0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - for (i=0; i + +typedef struct +{ + INT64 value; + int radix; + char *result; +} testCase; + + +int __cdecl main(int argc, char *argv[]) +{ + WCHAR buffer[256]; + WCHAR *testStr; + WCHAR *ret; + int i; + testCase testCases[] = + { + {42, 10, "42"}, + {42, 2, "101010"}, + {29, 32, "t"}, + {-1, 10, "-1"}, + {-1, 8, "1777777777777777777777"}, + {-1, 32, "fvvvvvvvvvvvv"}, + {I64(0x7FFFFFFFFFFFFFFF), 10, "9223372036854775807"}, + {I64(0x8000000000000000), 10, "-9223372036854775808"}, + {0,2,"0"}, + {0,16,"0"}, + {3,16,"3"}, + {15,16,"f"}, + {16,16,"10"}, + + }; + + + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + for (i=0; i - -int __cdecl main(int argc, char *argv[]) -{ - int err; - WCHAR *wpBuffer = NULL; - char *pChar = NULL; - unsigned long ul = 1234567890UL; - char *pChar10 = "1234567890"; - char *pChar2 = "1001001100101100000001011010010"; - char *pChar16 = "499602d2"; - - /*Initialize the PAL environment*/ - err = PAL_Initialize(argc, argv); - if(0 != err) - { - return FAIL; - } - - wpBuffer = malloc(64 * sizeof(WCHAR)); - if(NULL == wpBuffer) - { - Fail("\nFail to allocate the buffer to save a converted " - "wide character string, error code=%d!\n", - GetLastError()); - } - - /*convert to a 10 base string*/ - _ui64tow(ul, wpBuffer, 10); - pChar = convertC(wpBuffer); - if(strcmp(pChar10, pChar)) - { - free(wpBuffer); - free(pChar); - Fail("\nFailed to call _ui64tow API to convert an interger " - "to a 10 base wide character string, error code=%d\n", - GetLastError()); - } - free(pChar); - free(wpBuffer); - - wpBuffer = malloc(64 * sizeof(WCHAR)); - if(NULL == wpBuffer) - { - Fail("\nFail to allocate the buffer to save a converted " - "wide character string, error code=%d!\n", - GetLastError()); - } - - /*convert to a 16 base string*/ - _ui64tow(ul, wpBuffer, 16); - pChar = convertC(wpBuffer); - if(strcmp(pChar16, pChar)) - { - free(wpBuffer); - free(pChar); - Fail("\nFailed to call _ui64tow API to convert an interger " - "to a 16 base wide character string, error code = %d\n", - GetLastError()); - } - free(pChar); - free(wpBuffer); - - wpBuffer = malloc(64 * sizeof(WCHAR)); - if(NULL == wpBuffer) - { - Fail("\nFail to allocate the buffer to save a converted " - "wide character string, error code=%d!\n", - GetLastError()); - } - /*convert to a 2 base string*/ - _ui64tow(ul, wpBuffer, 2); - pChar = convertC(wpBuffer); - if(strcmp(pChar2, pChar)) - { - free(wpBuffer); - free(pChar); - Fail("\nFailed to call _ui64tow API to convert an interger " - "to a 2 base wide character string, error code=%d\n", - GetLastError()); - } - free(pChar); - free(wpBuffer); - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/miscellaneous/_ui64tow/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/_ui64tow/test1/testinfo.dat deleted file mode 100644 index a60f27a..0000000 --- a/src/pal/tests/palsuite/miscellaneous/_ui64tow/test1/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = miscellaneous -Function = _ui64tow -Name = Positive test _ui64tow to convert an integer to a wide character string -TYPE = DEFAULT -EXE1 = _ui64tow -Description -=Test the _ui64tow API to convert an integer to a wide character string diff --git a/src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/CMakeLists.txt deleted file mode 100644 index b4feb4b..0000000 --- a/src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - _ui64tow.c -) - -add_executable(paltest_ui64tow_test2 - ${SOURCES} -) - -add_dependencies(paltest_ui64tow_test2 coreclrpal) - -target_link_libraries(paltest_ui64tow_test2 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/_ui64tow.c b/src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/_ui64tow.c deleted file mode 100644 index f132505..0000000 --- a/src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/_ui64tow.c +++ /dev/null @@ -1,88 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: _ui64tow.c -** -** Purpose: Tests _ui64tow with normal values and different -** radices,highest and lowest values. -** -** -**============================================================*/ - -#include - -typedef struct -{ - unsigned __int64 value; - int radix; - char* result; -} testCase; - - -int __cdecl main(int argc, char *argv[]) -{ - WCHAR buffer[256]; - WCHAR *testStr; - WCHAR *ret; - int i; - testCase testCases[] = - { - /* test limits */ - {UI64(0xFFFFFFFFFFFFFFFF), 2, - "1111111111111111111111111111111111111111111111111111111111111111"}, - {UI64(0xFFFFFFFFFFFFFFFF), 8, "1777777777777777777777"}, - {UI64(0xFFFFFFFFFFFFFFFF), 10, "18446744073709551615"}, - {UI64(0xFFFFFFFFFFFFFFFF), 16, "ffffffffffffffff"}, - {47, 2, "101111"}, - {47, 8, "57"}, - {47, 10, "47"}, - {47, 16, "2f"}, - {12, 2, "1100"}, - {12, 8, "14"}, - {12, 10, "12"}, - {12, 16, "c"}, - - /* test with 0. */ - {0, 2, "0"}, - {0, 8, "0"}, - {0, 10, "0"}, - {0, 16, "0"} - }; - - if (0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - for (i=0; i, got <%S>.\n", - i,testStr, buffer); - free(testStr); - Fail(""); - } - - free(testStr); - } - - PAL_Terminate(); - return PASS; -} - - - diff --git a/src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/testinfo.dat deleted file mode 100644 index 0abbca2..0000000 --- a/src/pal/tests/palsuite/miscellaneous/_ui64tow/test2/testinfo.dat +++ /dev/null @@ -1,13 +0,0 @@ -# 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. - -Version = 1.0 -Section = miscellaneous -Function = _ui64tow -Name = Positive test _ui64tow to convert an integer to a wide character string -TYPE = DEFAULT -EXE1 = _ui64tow -Description -=Test the _ui64tow API to convert an integer to a wide character string -=Test the limits. and 0. diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrcatW/CMakeLists.txt deleted file mode 100644 index a3847f8..0000000 --- a/src/pal/tests/palsuite/miscellaneous/lstrcatW/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -add_subdirectory(test1) -add_subdirectory(test2) -add_subdirectory(test3) -add_subdirectory(test4) - diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/CMakeLists.txt deleted file mode 100644 index aa5b0c2..0000000 --- a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_lstrcatw_test1 - ${SOURCES} -) - -add_dependencies(paltest_lstrcatw_test1 coreclrpal) - -target_link_libraries(paltest_lstrcatw_test1 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/test.c deleted file mode 100644 index ad1095e..0000000 --- a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/test.c +++ /dev/null @@ -1,59 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for lstrcatW() function -** -** -**=========================================================*/ - -#define UNICODE - -#include - -int __cdecl main(int argc, char *argv[]) { - - WCHAR FirstString[10] = {'T','E','S','T','\0'}; - const WCHAR SecondString[] = {'P','A','L','!','\0'}; - WCHAR CorrectString[] = {'T','E','S','T','P','A','L','!','\0'}; - WCHAR* ReturnedPointer = NULL; - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - ReturnedPointer = lstrcat(FirstString,SecondString); - - /* Check to see if the pointer returned points to the concat string */ - if(ReturnedPointer != &FirstString[0]) - { - Fail("ERROR: The function was supposed to return a pointer to " - "the concatentated string, but it did not.\n"); - } - - /* Check to make sure the Concat string is the same as the predetermined - 'CorrectString' */ - if(memcmp(FirstString,CorrectString, - wcslen(FirstString)*sizeof(WCHAR)) != 0) - { - Fail("ERROR: The concatenated string should be %s but %s was the " - "result.\n", - convertC(CorrectString), - convertC(FirstString)); - } - - PAL_Terminate(); - return PASS; -} - - - diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/testinfo.dat deleted file mode 100644 index 006e83b..0000000 --- a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test1/testinfo.dat +++ /dev/null @@ -1,16 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = lstrcatW -Name = Positive test of lstrcatW -TYPE = DEFAULT -EXE1 = test -Description -= Test to see that concatenating two strings works, -= and also check return values in successful and failing situations. - - - diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/CMakeLists.txt deleted file mode 100644 index 8a11c8f..0000000 --- a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test2.c -) - -add_executable(paltest_lstrcatw_test2 - ${SOURCES} -) - -add_dependencies(paltest_lstrcatw_test2 coreclrpal) - -target_link_libraries(paltest_lstrcatw_test2 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/test2.c b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/test2.c deleted file mode 100644 index 6c66bc8..0000000 --- a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/test2.c +++ /dev/null @@ -1,53 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test2.c -** -** Purpose: Negative test for lstrcatW() function -** -** -**=========================================================*/ - -#define UNICODE - -#include - -int __cdecl main(int argc, char *argv[]) { - - WCHAR FirstString[10] = {'T','E','S','T','\0'}; - const WCHAR SecondString[] = {'P','A','L','!','\0'}; - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* If either of these is NULL, function should fail and return NULL. */ - if(lstrcat(NULL,SecondString) != NULL) - { - Fail("ERROR: When NULL was passed to the first parameter of the " - "function, it should have returned " - "NULL as a result, but did not.\n"); - } - - if(lstrcat(FirstString,NULL) != NULL) - { - Fail("ERROR: When NULL was passed to the second parameter of the " - "function, it should have returned " - "NULL as a result, but did not.\n"); - } - - - PAL_Terminate(); - return PASS; -} - - - diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/testinfo.dat deleted file mode 100644 index cc1ee64..0000000 --- a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test2/testinfo.dat +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = lstrcatW -Name = Negtive test of lstrcatW -TYPE = DEFAULT -EXE1 = test2 -Description -= Test to see lstrcat reports error with failing situations. diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/CMakeLists.txt deleted file mode 100644 index 1cdeced..0000000 --- a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test3.c -) - -add_executable(paltest_lstrcatw_test3 - ${SOURCES} -) - -add_dependencies(paltest_lstrcatw_test3 coreclrpal) - -target_link_libraries(paltest_lstrcatw_test3 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/test3.c b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/test3.c deleted file mode 100644 index 49a9c57..0000000 --- a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/test3.c +++ /dev/null @@ -1,46 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test3.c -** -** Purpose: Testing lstrcatw with two NULL strings passed on -** -** -**=========================================================*/ - -#define UNICODE - -#include - -int __cdecl main(int argc, char *argv[]) -{ - - - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - - /* testing the behaviour of lstrcatW with two NULL strings */ - if( lstrcat(NULL,NULL) != NULL) - { - - Fail("lstrcat:ERROR: the function should returned NULL\n"); - - } - - PAL_Terminate(); - return PASS; -} - - - diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/testinfo.dat deleted file mode 100644 index 794bcdb..0000000 --- a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test3/testinfo.dat +++ /dev/null @@ -1,26 +0,0 @@ -# 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. - -Version = 1.0 - -Section = Miscellaneous - -Function = lstrcatW - -Name = Negative testing for lstrcatW - -TYPE = DEFAULT - -EXE1 = test3 - -Description - -= Testing the behaviour after sending two strings contained NULL - - - - - - - diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/CMakeLists.txt deleted file mode 100644 index 640c224..0000000 --- a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test4.c -) - -add_executable(paltest_lstrcatw_test4 - ${SOURCES} -) - -add_dependencies(paltest_lstrcatw_test4 coreclrpal) - -target_link_libraries(paltest_lstrcatw_test4 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/test4.c b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/test4.c deleted file mode 100644 index abc9021..0000000 --- a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/test4.c +++ /dev/null @@ -1,101 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test4.c -** -** Purpose: Testing the behaviour of lstrcatw when string2 contains -** special characters, this test case depends on: -** memcmp -** wcslen -** lstrcpyn -** -** -**=========================================================*/ - -#define UNICODE - -#include - -struct testCase -{ - WCHAR SecondString[5]; - WCHAR CorrectString[10]; -}; - -int __cdecl main(int argc, char *argv[]) -{ - - WCHAR FirstString[10] = {'T','E','S','T','\0'}; - WCHAR TestString[10] = {'T','E','S','T','\0'}; - int i = 0; - - /* - * this structure includes several strings to be tested with - * lstrcatW function and the expected results - */ - - struct testCase testCases[]= - { - {{'\t','T','A','B','\0'}, - {'T','E','S','T','\t','T','A','B','\0'}}, - {{'2','T','\?','B','\0'}, - {'T','E','S','T','2','T','\?','B','\0'}}, - {{'\v','T','E','\v','\0'}, - {'T','E','S','T','\v','T','E','\v','\0'}}, - {{'T','\a','E','\a','\0'}, - {'T','E','S','T','T','\a','E','\a','\0'}}, - {{'0','\f','Z','\f','\0'}, - {'T','E','S','T','0','\f','Z','\f','\0'}}, - {{'\r','H','I','\r','\0'}, - {'T','E','S','T','\r','H','I','\r','\0'}}, - {{'H','I','\"','\"','\0'}, - {'T','E','S','T','H','I','\"','\"','\0'}}, - {{'H','\b','I','\b','\0'}, - {'T','E','S','T','H','\b','I','\b','\0'}}, - {{'H','\n','I','\n','\0'}, - {'T','E','S','T','H','\n','I','\n','\0'}} - }; - - - - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - - /* Loop through the struct and validate the resulted string */ - for( i = 0; i < sizeof(testCases)/sizeof(struct testCase); i++) - { - - lstrcat(FirstString, testCases[i].SecondString); - - if(memcmp(FirstString,testCases[i].CorrectString, - wcslen(FirstString)*sizeof(WCHAR))) - { - - Fail("ERROR: the function failed with a special character.\n"); - } - - /* reinitialize the first string */ - lstrcpyn(FirstString,TestString,10); - - } - - - - - PAL_Terminate(); - return PASS; -} - - - diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/testinfo.dat deleted file mode 100644 index 96235fb..0000000 --- a/src/pal/tests/palsuite/miscellaneous/lstrcatW/test4/testinfo.dat +++ /dev/null @@ -1,28 +0,0 @@ -# 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. - -Version = 1.0 - -Section = Miscellaneous - -Function = lstrcatW - -Name = Positive testing for lstrcatW - -TYPE = DEFAULT - -EXE1 = test4 - -Description - -= Testing the behaviour of lstrcatw when string2 contains - -= special characters and validate the resulted string - - - - - - - diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcpyW/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrcpyW/CMakeLists.txt deleted file mode 100644 index f6aa0cb..0000000 --- a/src/pal/tests/palsuite/miscellaneous/lstrcpyW/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -add_subdirectory(test1) - diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/CMakeLists.txt deleted file mode 100644 index e39c9a6..0000000 --- a/src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_lstrcpyw_test1 - ${SOURCES} -) - -add_dependencies(paltest_lstrcpyw_test1 coreclrpal) - -target_link_libraries(paltest_lstrcpyw_test1 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/test.c deleted file mode 100644 index 881ba03..0000000 --- a/src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/test.c +++ /dev/null @@ -1,66 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for lstrcpyW() function -** -** -**=========================================================*/ - -#define UNICODE - -#include - -int __cdecl main(int argc, char *argv[]) -{ - WCHAR FirstString[5] = {'T','E','S','T','\0'}; - WCHAR ResultBuffer[5]; - WCHAR* ResultPointer = NULL; - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - ResultPointer = lstrcpy(ResultBuffer,FirstString); - - /* Check the return value */ - if(ResultPointer != &ResultBuffer[0]) - { - Fail("ERROR: The function did not return a pointer to the Result " - "Buffer after being called.\n"); - } - - /* A straight copy, the values should be equal. */ - if(memcmp(ResultBuffer,FirstString,wcslen(ResultBuffer)*2+2) != 0) - { - Fail("ERROR: The result of the copy was '%s' when it should have " - "been '%s'.\n",convertC(ResultBuffer),convertC(FirstString)); - } - - /* If either param is NULL, it should return NULL. */ - if(lstrcpy(ResultBuffer,NULL) != NULL) - { - Fail("ERROR: The second parameter was NULL, so the function should " - "fail and return NULL.\n"); - } - if(lstrcpy(NULL,FirstString) != NULL) - { - Fail("ERROR: The first parameter was NULL, so the function should " - "fail and return NULL.\n"); - } - - - PAL_Terminate(); - return PASS; -} - - diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/testinfo.dat deleted file mode 100644 index 37c9835..0000000 --- a/src/pal/tests/palsuite/miscellaneous/lstrcpyW/test1/testinfo.dat +++ /dev/null @@ -1,16 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = lstrcpyW -Name = Positive test of lstrcpyW -TYPE = DEFAULT -EXE1 = test -Description -= Ensure that a copy of a string works, and that the return values -= are correct for success and failure. - - - diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/CMakeLists.txt deleted file mode 100644 index 4344b89..0000000 --- a/src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_lstrcpynw_test1 - ${SOURCES} -) - -add_dependencies(paltest_lstrcpynw_test1 coreclrpal) - -target_link_libraries(paltest_lstrcpynw_test1 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/test.c deleted file mode 100644 index 1ae0c51..0000000 --- a/src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/test.c +++ /dev/null @@ -1,73 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for lstrcpynW() function -** -** -**=========================================================*/ - -#define UNICODE - -#include - -int __cdecl main(int argc, char *argv[]) { - - WCHAR FirstString[5] = {'T','E','S','T','\0'}; - WCHAR CorrectBuffer[3] = {'T','E','\0'}; - WCHAR ResultBuffer[5]; - WCHAR* ResultPointer = NULL; - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* A straight copy, the values should be equal. */ - ResultPointer = lstrcpyn(ResultBuffer,FirstString,3); - - /* Make sure the returned pointer is to the result buffer */ - if(ResultPointer != &ResultBuffer[0]) - { - Fail("ERROR: The function didn't return a pointer which points to the " - "location of the buffer which was copied into.\n"); - } - - /* Check to see that values are equal */ - if(memcmp(ResultBuffer, - CorrectBuffer, - wcslen(ResultBuffer)*sizeof(WCHAR)) != 0) - { - Fail("ERROR: '%s' was the result and it should have been '%s' when " - "this copy was performed.\n", - convertC(ResultBuffer),convertC(CorrectBuffer)); - } - - /* Null values should get Null results */ - if(lstrcpyn(ResultBuffer,NULL,3) != NULL) - { - Fail("ERROR: When the second parameter was set to NULL, the return " - "value should have been NULL, but it was not.\n"); - } - - if(lstrcpyn(NULL,FirstString,3) != NULL) - { - Fail("ERROR: When the first parameter was set to NULL, the return " - "value should have been NULL, but it was not.\n"); - } - - - PAL_Terminate(); - return PASS; -} - - - diff --git a/src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/testinfo.dat deleted file mode 100644 index 111a579..0000000 --- a/src/pal/tests/palsuite/miscellaneous/lstrcpynW/test1/testinfo.dat +++ /dev/null @@ -1,16 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = lstrcpynW -Name = Positive test of lstrcpynW -TYPE = DEFAULT -EXE1 = test -Description -= Ensure that a copy of a string works, and that the return values -= are correct for success and failure. - - - diff --git a/src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/CMakeLists.txt index 807a5d8..6bb5201 100644 --- a/src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_lstrlena_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/test.c b/src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/test.c rename to src/pal/tests/palsuite/miscellaneous/lstrlenA/test1/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/CMakeLists.txt index fe6fc96..4209cbe 100644 --- a/src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_lstrlenw_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/test.c rename to src/pal/tests/palsuite/miscellaneous/lstrlenW/test1/test.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/CMakeLists.txt index d76467a..ba53f42 100644 --- a/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_queryperformancecounter_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/test1.c b/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/test1.c rename to src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/test1.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/CMakeLists.txt index 352e513..bc6bd22 100644 --- a/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_queryperformancefrequency_test1 diff --git a/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/test1.c b/src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/test1.c rename to src/pal/tests/palsuite/miscellaneous/queryperformancefrequency/test1/test1.cpp diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/CMakeLists.txt deleted file mode 100644 index f40d415..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -add_subdirectory(test1) -add_subdirectory(test11) -add_subdirectory(test12) -add_subdirectory(test13) -add_subdirectory(test2) -add_subdirectory(test3) -add_subdirectory(test6) -add_subdirectory(test7) -add_subdirectory(test8) -add_subdirectory(test9) - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/CMakeLists.txt deleted file mode 100644 index ef58932..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_wsprintfa_test1 - ${SOURCES} -) - -add_dependencies(paltest_wsprintfa_test1 coreclrpal) - -target_link_libraries(paltest_wsprintfa_test1 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/test.c deleted file mode 100644 index 7222709..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/test.c +++ /dev/null @@ -1,58 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for wsprintfA() function -** -** -**=========================================================*/ - -#include - - char * ErrorMessage; - char buf[256]; - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with strlen */ - -int test1() -{ - char checkstr[] = "hello world"; - - wsprintf(buf, "hello world"); - - /* Error message */ - ErrorMessage = "ERROR: (Test 1) Failed on 'hello world' test. The " - "correct string is 'hello world' and the result returned was "; - - return (memcmp(checkstr, buf, strlen(checkstr)+1) != 0); -} - -int __cdecl main(int argc, char *argv[]) -{ - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if(test1()) - { - Fail("%s '%s'\n",ErrorMessage,buf); - } - - PAL_Terminate(); - return PASS; - -} - - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/testinfo.dat deleted file mode 100644 index c06f4c0..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test1/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = wsprintfA -Name = Positive test of wsprintfA -TYPE = DEFAULT -EXE1 = test -Description -= Test the very basic functionality of wsprintf. - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/CMakeLists.txt deleted file mode 100644 index 92c44b9..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_wsprintfa_test11 - ${SOURCES} -) - -add_dependencies(paltest_wsprintfa_test11 coreclrpal) - -target_link_libraries(paltest_wsprintfa_test11 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/test.c deleted file mode 100644 index b43299a..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/test.c +++ /dev/null @@ -1,128 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for wsprintfA() function -** -** -**=========================================================*/ - -#include - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with strlen */ - -char * ErrorMessage; -char buf[256]; - -BOOL test1() -{ - int pos = 42; - - - /* Test 1 */ - wsprintf(buf, "foo %u", pos); - if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 1) Failed. The correct string is " - "'foo 42' and the result returned was "; - return FAIL; - } - - /* Test 2 */ - wsprintf(buf, "foo %lu", 0xFFFF); - if (memcmp(buf, "foo 65535", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 2) Failed. The correct string is " - "'foo 65535' and the result returned was "; - return FAIL; - } - - /* Test 3 */ - wsprintf(buf, "foo %hu", 0xFFFF); - if (memcmp(buf, "foo 65535", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 3) Failed. The correct string is " - "'foo 65535' and the result returned was "; - return FAIL; - } - - /* Test 4 */ - wsprintf(buf, "foo %3u", pos); - if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 4) Failed. The correct string is " - "'foo 42' and the result returned was "; - return FAIL; - } - - /* Test 5 */ - wsprintf(buf, "foo %-3u", pos); - if (memcmp(buf, "foo 42 ", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 5) Failed. The correct string is " - "'foo 42' and the result returned was "; - return FAIL; - } - - /* Test 6 */ - wsprintf(buf, "foo %.1u", pos); - if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 6) Failed. The correct string is " - "'foo 42' and the result returned was "; - return FAIL; - } - - /* Test 7 */ - wsprintf(buf, "foo %.3u", pos); - if (memcmp(buf, "foo 042", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 7) Failed. The correct string is " - "'foo 042' and the result returned was "; - return FAIL; - } - - /* Test 8 */ - wsprintf(buf, "foo %03u", pos); - if (memcmp(buf, "foo 042", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 8) Failed. The correct string is " - "'foo 042' and the result returned was "; - return FAIL; - } - - /* Test 9 */ - wsprintf(buf, "foo %#u", pos); - if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 9) Failed. The correct string is " - "'foo 42' and the result returned was "; - return FAIL; - } - return PASS; -} - - -int __cdecl main(int argc, char *argv[]) -{ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if(test1()) - { - Fail("%s'%s'\n",ErrorMessage,buf); - } - - PAL_Terminate(); - return PASS; -} - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/testinfo.dat deleted file mode 100644 index c5f1ec1..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test11/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = wsprintfA -Name = Positive test of wsprintfA -TYPE = DEFAULT -EXE1 = test -Description -= Test the %u formatter. - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/CMakeLists.txt deleted file mode 100644 index e4013ad..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_wsprintfa_test12 - ${SOURCES} -) - -add_dependencies(paltest_wsprintfa_test12 coreclrpal) - -target_link_libraries(paltest_wsprintfa_test12 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/test.c deleted file mode 100644 index dcc6101..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/test.c +++ /dev/null @@ -1,119 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for wsprintfA() function -** -** -**=========================================================*/ - -#include - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with strlen */ - -char * ErrorMessage; -char buf[256]; - -BOOL test1() -{ - int pos = 0x1234ab; - - /* Test 1 */ - wsprintf(buf, "foo %x", pos); - if (memcmp(buf, "foo 1234ab", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 1) Failed. The correct " - "string is 'foo 1234ab' and the result returned was "; - return FAIL; - } - - /* Test 2 */ - wsprintf(buf, "foo %lx", pos); - if (memcmp(buf, "foo 1234ab", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 2) Failed. The correct " - "string is 'foo 1234ab' and the result returned was "; - return FAIL; - } - - - /* Test 3 */ - wsprintf(buf, "foo %7x", pos); - if (memcmp(buf, "foo 1234ab", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 3) Failed. The correct string is " - "'foo 1234ab' and the result returned was "; - return FAIL; - } - - /* Test 4 */ - wsprintf(buf, "foo %-7x", pos); - if (memcmp(buf, "foo 1234ab ", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 4) Failed. The correct string is " - "'foo 1234ab' and the result returned was "; - return FAIL; - } - - /* Test 5 */ - wsprintf(buf, "foo %.1x", pos); - if (memcmp(buf, "foo 1234ab", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 5) Failed. The correct string is " - "'foo 1234ab' and the result returned was "; - return FAIL; - } - - /* Test 6 */ - wsprintf(buf, "foo %.7x", pos); - if (memcmp(buf, "foo 01234ab", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 6) Failed. The correct string is " - "'foo 01234ab' and the result returned was "; - return FAIL; - } - - /* Test 7 */ - wsprintf(buf, "foo %07x", pos); - if (memcmp(buf, "foo 01234ab", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 7) Failed. The correct string is " - "'foo 01234ab' and the result returned was "; - return FAIL; - } - - /* Test 8 */ - wsprintf(buf, "foo %#x", pos); - if (memcmp(buf, "foo 0x1234ab", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 8) Failed. The correct string is " - "'foo 0x1234ab' and the result returned was "; - return FAIL; - } - - return PASS; -} - -int __cdecl main(int argc, char *argv[]) -{ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if(test1()) - { - Fail("%s '%s'\n",ErrorMessage,buf); - } - - PAL_Terminate(); - return PASS; -} - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/testinfo.dat deleted file mode 100644 index 71c8386..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test12/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = wsprintfA -Name = Positive test of wsprintfA -TYPE = DEFAULT -EXE1 = test -Description -= Test the %x formatter. - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/CMakeLists.txt deleted file mode 100644 index 423b05d..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_wsprintfa_test13 - ${SOURCES} -) - -add_dependencies(paltest_wsprintfa_test13 coreclrpal) - -target_link_libraries(paltest_wsprintfa_test13 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/test.c deleted file mode 100644 index e1f7d80..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/test.c +++ /dev/null @@ -1,120 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for wsprintfA() function -** -** -**=========================================================*/ - -#include - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with strlen */ - -char * ErrorMessage; -char buf[256]; - -BOOL test1() -{ - int pos = 0x1234ab; - - /* Test 1 */ - wsprintf(buf, "foo %X", pos); - if (memcmp(buf, "foo 1234AB", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 1) Failed. The correct string is " - " 'foo 1234AB' and the result returned was "; - return FAIL; - } - - /* Test 2 */ - wsprintf(buf, "foo %lX", pos); - if (memcmp(buf, "foo 1234AB", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 2) Failed. The correct string is " - "'foo 1234AB' and the result returned was "; - return FAIL; - } - - - /* Test 3 */ - wsprintf(buf, "foo %7X", pos); - if (memcmp(buf, "foo 1234AB", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 3) Failed. The correct string is " - "'foo 1234AB' and the result returned was "; - return FAIL; - } - - /* Test 4 */ - wsprintf(buf, "foo %-7X", pos); - if (memcmp(buf, "foo 1234AB ", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 4) Failed. The correct string is " - "'foo 1234AB' and the result returned was "; - return FAIL; - } - - /* Test 5 */ - wsprintf(buf, "foo %.1X", pos); - if (memcmp(buf, "foo 1234AB", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 5) Failed. The correct string is " - "'foo 1234AB' and the result returned was "; - return FAIL; - } - - /* Test 6 */ - wsprintf(buf, "foo %.7X", pos); - if (memcmp(buf, "foo 01234AB", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 6) Failed. The correct string is " - "'foo 01234AB' and the result returned was "; - return FAIL; - } - - /* Test 7 */ - wsprintf(buf, "foo %07X", pos); - if (memcmp(buf, "foo 01234AB", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 7) Failed. The correct string is " - "'foo 01234AB' and the result returned was "; - return FAIL; - } - - /* Test 8 */ - wsprintf(buf, "foo %#X", pos); - if (memcmp(buf, "foo 0X1234AB", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 8) Failed. The correct string is " - "'foo 0X1234AB' and the result returned was "; - return FAIL; - } - - return PASS; -} - -int __cdecl main(int argc, char *argv[]) -{ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if(test1()) - { - Fail("%s '%s'\n",ErrorMessage,buf); - } - - PAL_Terminate(); - return PASS; - -} - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/testinfo.dat deleted file mode 100644 index 0e0d1b4..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test13/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = wsprintfA -Name = Positive test of wsprintfA -TYPE = DEFAULT -EXE1 = test -Description -= Test the %X formatter. - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/CMakeLists.txt deleted file mode 100644 index 546a1da..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_wsprintfa_test2 - ${SOURCES} -) - -add_dependencies(paltest_wsprintfa_test2 coreclrpal) - -target_link_libraries(paltest_wsprintfa_test2 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/test.c deleted file mode 100644 index b879e54..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/test.c +++ /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. -// See the LICENSE file in the project root for more information. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for wsprintfA() function -** -** -**=========================================================*/ - -#include - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with strlen */ - -char * ErrorMessage; -char * BadResult; -char buf[256]; - -BOOL test1() -{ - - - /* Test 1 */ - wsprintf(buf, "foo %s", "bar"); - if (memcmp(buf, "foo bar", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 1) Failed. The correct string is " - "'foo bar' and the result returned was "; - BadResult = buf; - return FAIL; - } - - /* Test 2 */ - wsprintf(buf, "foo %hs", "bar"); - if (memcmp(buf, "foo bar", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 2) Failed. The correct string is " - "'foo bar' and the result returned was "; - BadResult = buf; - return FAIL; - } - - - /* Test 3 */ - wsprintf(buf, "foo %5s", "bar"); - if (memcmp(buf, "foo bar", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 3) Failed. The correct string is " - "'foo bar' and the result returned was "; - BadResult = buf; - return FAIL; - } - - /* Test 4 */ - wsprintf(buf, "foo %.2s", "bar"); - if (memcmp(buf, "foo ba", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 4) Failed. The correct string is " - "'foo ba' and the result returned was "; - BadResult = buf; - return FAIL; - } - - /* Test 5 */ - wsprintf(buf, "foo %5.2s", "bar"); - if (memcmp(buf, "foo ba", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 5) Failed. The correct string is " - "'foo ba' and the result returned was "; - BadResult = buf; - return FAIL; - } - - /* Test 6 */ - wsprintf(buf, "foo %-5s", "bar"); - if (memcmp(buf, "foo bar ", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 6) Failed. The correct string is " - "'foo bar' and the result returned was "; - BadResult = buf; - return FAIL; - } - - /* Test 7 */ - wsprintf(buf, "foo %05s", "bar"); - if (memcmp(buf, "foo 00bar", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 7) Failed. The correct string is " - "'foo 00bar' and the result returned was "; - BadResult = buf; - return FAIL; - } - return PASS; -} - - -int __cdecl main(int argc, char *argv[]) -{ - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if(test1()) - { - Fail("%s '%s'\n",ErrorMessage,BadResult); - } - - PAL_Terminate(); - return PASS; - -} - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/testinfo.dat deleted file mode 100644 index 32e51df..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test2/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = wsprintfA -Name = Positive test of wsprintfA -TYPE = DEFAULT -EXE1 = test -Description -= Test the %s and %ls formatters with various flags. - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/CMakeLists.txt deleted file mode 100644 index 8043ccd..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_wsprintfa_test3 - ${SOURCES} -) - -add_dependencies(paltest_wsprintfa_test3 coreclrpal) - -target_link_libraries(paltest_wsprintfa_test3 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/test.c deleted file mode 100644 index bb598d9..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/test.c +++ /dev/null @@ -1,121 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for wsprintfA() function -** -** -**=========================================================*/ - -#include - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with strlen */ - -char * ErrorMessage; -char buf[256]; - -BOOL test1() -{ - - /* Test 1 */ - wsprintf(buf, "foo %S", convert("bar")); - if (memcmp(buf, "foo bar", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 1) Failed. The correct string is " - "'foo bar' and the result returned was "; - return FAIL; - } - - /* Test 2 */ - wsprintf(buf, "foo %hS", "bar"); - if (memcmp(buf, "foo bar", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 2) Failed. The correct string is " - "'foo bar' and the result returned was "; - return FAIL; - } - - /* Test 3 */ - wsprintf(buf, "foo %lS", convert("bar")); - if (memcmp(buf, "foo bar", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 3) Failed. The correct string is '" - "foo bar' and the result returned was "; - return FAIL; - } - - - /* Test 4 */ - wsprintf(buf, "foo %5S", convert("bar")); - if (memcmp(buf, "foo bar", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 4) Failed. The correct string is " - "'foo bar' and the result returned was "; - return FAIL; - } - - /* Test 5 */ - wsprintf(buf, "foo %.2S", convert("bar")); - if (memcmp(buf, "foo ba", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 5) Failed. The correct string is " - "'foo ba' and the result returned was "; - return FAIL; - } - - /* Test 6 */ - wsprintf(buf, "foo %5.2S", convert("bar")); - if (memcmp(buf, "foo ba", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 6) Failed. The correct string is " - "'foo ba' and the result returned was "; - return FAIL; - } - - /* Test 7 */ - wsprintf(buf, "foo %-5S", convert("bar")); - if (memcmp(buf, "foo bar ", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 7) Failed. The correct string is " - "'foo bar ' and the result returned was "; - return FAIL; - } - - /* Test 8 */ - wsprintf(buf, "foo %05S", convert("bar")); - if (memcmp(buf, "foo 00bar", strlen(buf) + 1) != 0) { - ErrorMessage = "ERROR: (Test 8) Failed. The correct string is " - "'foo 00bar' and the result returned was "; - return FAIL; - } - return PASS; -} - -int __cdecl main(int argc, char *argv[]) -{ - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if(test1()) { - Fail("%s '%s'\n",ErrorMessage,buf); - - } - - PAL_Terminate(); - return PASS; - -} - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/testinfo.dat deleted file mode 100644 index 0660aa1..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test3/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = wsprintfA -Name = Positive test of wsprintfA -TYPE = DEFAULT -EXE1 = test -Description -= Test the %S and wide characters in general. - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/CMakeLists.txt deleted file mode 100644 index 6a5caf9..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_wsprintfa_test6 - ${SOURCES} -) - -add_dependencies(paltest_wsprintfa_test6 coreclrpal) - -target_link_libraries(paltest_wsprintfa_test6 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/test.c deleted file mode 100644 index 08d97f4..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/test.c +++ /dev/null @@ -1,114 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for wsprintfA() function -** -** -**=========================================================*/ - -#include - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with strlen */ - -char * ErrorMessage; -char buf[256]; - -BOOL test1() -{ - WCHAR wc = 'c'; - - /* Test 1 */ - wsprintf(buf, "foo %c", 'b'); - if (memcmp(buf, "foo b", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 1) Failed. The correct string is " - "'foo b' and the result returned was "; - return FAIL; - } - - /* Test 2 */ - wsprintf(buf, "foo %hc", 'b'); - if (memcmp(buf, "foo b", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 2) Failed. The correct string is " - "'foo b' and the result returned was "; - return FAIL; - } - - /* Test 3 */ - wsprintf(buf, "foo %lc", wc); - if (memcmp(buf, "foo c", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 3) Failed. The correct string is " - "'foo c' and the result returned was "; - return FAIL; - } - - - /* Test 4 */ - wsprintf(buf, "foo %5c", 'b'); - if (memcmp(buf, "foo b", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 4) Failed. The correct string is " - "'foo bar' and the result returned was "; - return FAIL; - } - - /* Test 5 */ - wsprintf(buf, "foo %-5c", 'b'); - if (memcmp(buf, "foo b ", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 5) Failed. The correct string is " - "'foo b ' and the result returned was "; - return FAIL; - } - - /* Test 6 */ - wsprintf(buf, "foo %05c", 'b'); - if (memcmp(buf, "foo 0000b", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 6) Failed. The correct string is " - "'foo 0000b' and the result returned was "; - return FAIL; - } - - /* Test 7 */ - wsprintf(buf, "foo %#c", 'b'); - if (memcmp(buf, "foo b", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 7) Failed. The correct string is " - "'foo b' and the result returned was "; - return FAIL; - } - return PASS; -} - -int __cdecl main(int argc, char *argv[]) -{ - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if(test1()) - { - Fail("%s '%s'\n",ErrorMessage,buf); - } - - PAL_Terminate(); - return PASS; - -} - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/testinfo.dat deleted file mode 100644 index 31b0f66..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test6/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = wsprintfA -Name = Positive test of wsprintfA -TYPE = DEFAULT -EXE1 = test -Description -= Test the %c formatter. - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/CMakeLists.txt deleted file mode 100644 index 0885f0f..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_wsprintfa_test7 - ${SOURCES} -) - -add_dependencies(paltest_wsprintfa_test7 coreclrpal) - -target_link_libraries(paltest_wsprintfa_test7 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/test.c deleted file mode 100644 index 6d380ef..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/test.c +++ /dev/null @@ -1,112 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for wsprintfA() function -** -** -**=========================================================*/ - -#include - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with strlen */ - -char * ErrorMessage; -char buf[256]; - -BOOL test1() -{ - WCHAR wb = 'b'; - - /* Test 1 */ - wsprintf(buf, "foo %C", wb); - if (memcmp(buf, "foo b", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 1) Failed. The correct string is " - "'foo b' and the result returned was "; - return FAIL; - } - - /* Test 2 */ - wsprintf(buf, "foo %hC", wb); - if (memcmp(buf, "foo b", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 2) Failed. The correct string is " - "'foo b' and the result returned was "; - return FAIL; - } - - /* Test 3 */ - wsprintf(buf, "foo %lC", 'c'); - if (memcmp(buf, "foo c", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 3) Failed. The correct string is " - "'foo c' and the result returned was "; - return FAIL; - } - - - /* Test 4 */ - wsprintf(buf, "foo %5C", wb); - if (memcmp(buf, "foo b", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 4) Failed. The correct string is " - "'foo b' and the result returned was "; - return FAIL; - } - - /* Test 5 */ - wsprintf(buf, "foo %-5C", wb); - if (memcmp(buf, "foo b ", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 5) Failed. The correct string is " - "'foo b ' and the result returned was "; - return FAIL; - } - - /* Test 6 */ - wsprintf(buf, "foo %05C", wb); - if (memcmp(buf, "foo 0000b", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 6) Failed. The correct string is " - "'foo 0000b' and the result returned was "; - return FAIL; - } - - /* Test 7 */ - wsprintf(buf, "foo %#C", wb); - if (memcmp(buf, "foo b", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 7) Failed. The correct string is " - "'foo b' and the result returned was "; - return FAIL; - } - return PASS; -} - -int __cdecl main(int argc, char *argv[]) -{ - - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if(test1()) - { - Fail("%s '%s'\n",ErrorMessage,buf); - - } - - PAL_Terminate(); - return PASS; - -} - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/testinfo.dat deleted file mode 100644 index 31b0f66..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test7/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = wsprintfA -Name = Positive test of wsprintfA -TYPE = DEFAULT -EXE1 = test -Description -= Test the %c formatter. - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/CMakeLists.txt deleted file mode 100644 index 3c4b5ed..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_wsprintfa_test8 - ${SOURCES} -) - -add_dependencies(paltest_wsprintfa_test8 coreclrpal) - -target_link_libraries(paltest_wsprintfa_test8 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/test.c deleted file mode 100644 index 7367461..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/test.c +++ /dev/null @@ -1,120 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for wsprintfA() function -** -** -**=========================================================*/ - -#include - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with strlen */ - -char * ErrorMessage; -char buf[256]; - -BOOL test1() -{ - int pos = 42; - - /* Test 1 */ - wsprintf(buf, "foo %d", pos); - if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 1) Failed. The correct string is " - "'foo 42' and the result returned was "; - return FAIL; - } - - /* Test 2 */ - wsprintf(buf, "foo %ld", 0xFFFF); - if (memcmp(buf, "foo 65535", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 2) Failed. The correct string is " - "'foo 65535' and the result returned was "; - return FAIL; - } - - /* Test 3 */ - wsprintf(buf, "foo %3d", pos); - if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 3) Failed. The correct string is " - "'foo 42' and the result returned was "; - return FAIL; - } - - /* Test 4 */ - wsprintf(buf, "foo %-3d", pos); - if (memcmp(buf, "foo 42 ", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 4) Failed. The correct string is " - "'foo 42 ' and the result returned was "; - return FAIL; - } - - /* Test 5 */ - wsprintf(buf, "foo %.1d", pos); - if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 5) Failed. The correct string is " - "'foo 42' and the result returned was "; - return FAIL; - } - - /* Test 6 */ - wsprintf(buf, "foo %.3d", pos); - if (memcmp(buf, "foo 042", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 6) Failed. The correct string is " - "'foo 042' and the result returned was "; - return FAIL; - } - - /* Test 7 */ - wsprintf(buf, "foo %03d", pos); - if (memcmp(buf, "foo 042", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 7) Failed. The correct string is " - "'foo 042' and the result returned was "; - return FAIL; - } - - /* Test 8 */ - wsprintf(buf, "foo %#d", pos); - if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 8) Failed. The correct string is " - "'foo 42' and the result returned was "; - return FAIL; - } - return PASS; -} - -int __cdecl main(int argc, char *argv[]) -{ - - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if(test1()) - { - Fail("%s '%s'\n",ErrorMessage,buf); - } - - PAL_Terminate(); - return PASS; - -} - - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/testinfo.dat deleted file mode 100644 index 75f4fbf..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test8/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = wsprintfA -Name = Positive test of wsprintfA -TYPE = DEFAULT -EXE1 = test -Description -= Test the %d formatter. - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/CMakeLists.txt deleted file mode 100644 index dcbb22e..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_wsprintfa_test9 - ${SOURCES} -) - -add_dependencies(paltest_wsprintfa_test9 coreclrpal) - -target_link_libraries(paltest_wsprintfa_test9 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/test.c deleted file mode 100644 index 9f123bc..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/test.c +++ /dev/null @@ -1,122 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for wsprintfA() function -** -** -**=========================================================*/ - -#include - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with strlen */ - -char * ErrorMessage; -char buf[256]; - -BOOL test1() -{ - - int pos = 42; - - - /* Test 1 */ - wsprintf(buf, "foo %i", pos); - if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 1) Failed. The correct string is " - "'foo 42' and the result returned was "; - return FAIL; - } - - /* Test 2 */ - wsprintf(buf, "foo %li", 0xFFFF); - if (memcmp(buf, "foo 65535", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 2) Failed. The correct string is " - "'foo 65535' and the result returned was "; - return FAIL; - } - - - /* Test 3 */ - wsprintf(buf, "foo %3i", pos); - if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 3) Failed. The correct string is " - "'foo 42' and the result returned was "; - return FAIL; - } - - /* Test 4 */ - wsprintf(buf, "foo %-3i", pos); - if (memcmp(buf, "foo 42 ", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 4) Failed. The correct string is " - "'foo 42 ' and the result returned was "; - return FAIL; - } - - /* Test 5 */ - wsprintf(buf, "foo %.1i", pos); - if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 5) Failed. The correct string is " - "'foo 42' and the result returned was "; - return FAIL; - } - - /* Test 6 */ - wsprintf(buf, "foo %.3i", pos); - if (memcmp(buf, "foo 042", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 6) Failed. The correct string is " - "'foo 042' and the result returned was "; - return FAIL; - } - - /* Test 7 */ - wsprintf(buf, "foo %03i", pos); - if (memcmp(buf, "foo 042", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 7) Failed. The correct string is " - "'foo 042' and the result returned was "; - return FAIL; - } - - /* Test 8 */ - wsprintf(buf, "foo %#i", pos); - if (memcmp(buf, "foo 42", strlen(buf) + 1) != 0) - { - ErrorMessage = "ERROR: (Test 8) Failed. The correct string is " - "'foo 42' and the result returned was "; - return FAIL; - } - - return PASS; -} - -int __cdecl main(int argc, char *argv[]) -{ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if(test1()) - { - Fail("%s '%s'\n",ErrorMessage,buf); - } - - PAL_Terminate(); - return PASS; - -} - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/testinfo.dat deleted file mode 100644 index 2a3689e..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfA/test9/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = wsprintfA -Name = Positive test of wsprintfA -TYPE = DEFAULT -EXE1 = test -Description -= Test the %i formatter. - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/CMakeLists.txt deleted file mode 100644 index f40d415..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -add_subdirectory(test1) -add_subdirectory(test11) -add_subdirectory(test12) -add_subdirectory(test13) -add_subdirectory(test2) -add_subdirectory(test3) -add_subdirectory(test6) -add_subdirectory(test7) -add_subdirectory(test8) -add_subdirectory(test9) - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/CMakeLists.txt deleted file mode 100644 index b1c0fb3..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_wsprintfw_test1 - ${SOURCES} -) - -add_dependencies(paltest_wsprintfw_test1 coreclrpal) - -target_link_libraries(paltest_wsprintfw_test1 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/test.c deleted file mode 100644 index 700cb13..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/test.c +++ /dev/null @@ -1,64 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for wsprintfW() function -** -** -**=========================================================*/ - -#define UNICODE -#include - - -char * ErrorMessage = NULL; -WCHAR * BadResult = NULL; - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with strlen */ - - -BOOL test1() -{ - char checkstr[] = "hello world"; - - WCHAR buf[256]; - - /* Test a simple string */ - wsprintf(buf, convert("hello world")); - - /* Error message */ - ErrorMessage = "ERROR: (Test 1) Failed on 'hello world' test. " - "The correct string is 'hello world' and the result returned was "; - BadResult = buf; - - return (memcmp(convert(checkstr), buf, wcslen(buf)*2+2) != 0); -} - -int __cdecl main(int argc, char *argv[]) { - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if(test1()) { - Fail("%s '%s'\n",ErrorMessage,convertC(BadResult)); - - } - - PAL_Terminate(); - return PASS; - -} - - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/testinfo.dat deleted file mode 100644 index f36aced..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test1/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = wsprintfW -Name = Positive test of wsprintfW -TYPE = DEFAULT -EXE1 = test -Description -= Test the very basic functionality of wsprintfW. - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/CMakeLists.txt deleted file mode 100644 index a5d73ed..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_wsprintfw_test11 - ${SOURCES} -) - -add_dependencies(paltest_wsprintfw_test11 coreclrpal) - -target_link_libraries(paltest_wsprintfw_test11 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/test.c deleted file mode 100644 index dc1e7a7..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/test.c +++ /dev/null @@ -1,139 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for wsprintfW() function -** -** -**=========================================================*/ - -#define UNICODE -#include - - - -char * ErrorMessage = NULL; -WCHAR * BadResult = NULL; -WCHAR buf[256]; - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with strlen */ - - -BOOL test1() -{ - - int pos = 42; - - wsprintf(buf, convert("foo %u"), pos); - if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 1) Failed. The correct string is" - " 'foo 42' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %lu"), 0xFFFF); - if (memcmp(buf, convert("foo 65535"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 2) Failed. The correct string is" - " 'foo 65535' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %hu"), 0xFFFF); - if (memcmp(buf, convert("foo 65535"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 3) Failed. The correct string is" - " 'foo 65535' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %3u"), pos); - if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 4) Failed. The correct string is" - " 'foo 42' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %-3u"), pos); - if (memcmp(buf, convert("foo 42 "), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 5) Failed. The correct string is" - " 'foo 42 ' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %.1u"), pos); - if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 6) Failed. The correct string is" - " 'foo 42' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %.3u"), pos); - if (memcmp(buf, convert("foo 042"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 7) Failed. The correct string is" - " 'foo 042' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %03u"), pos); - if (memcmp(buf, convert("foo 042"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 8) Failed. The correct string is" - " 'foo 042' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %#u"), pos); - if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 9) Failed. The correct string is" - " 'foo 42' and the result returned was "; - BadResult = buf; - return FAIL; - } - - return PASS; -} - -int __cdecl main(int argc, char *argv[]) -{ - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if(test1()) - { - Fail("%s '%s'\n",ErrorMessage,convertC(BadResult)); - - } - - PAL_Terminate(); - return PASS; - -} - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/testinfo.dat deleted file mode 100644 index bb85d63..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test11/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = wsprintfW -Name = Positive test of wsprintfW -TYPE = DEFAULT -EXE1 = test -Description -= Test %u formatter with wsprintfW. - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/CMakeLists.txt deleted file mode 100644 index 3811fb0..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_wsprintfw_test12 - ${SOURCES} -) - -add_dependencies(paltest_wsprintfw_test12 coreclrpal) - -target_link_libraries(paltest_wsprintfw_test12 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/test.c deleted file mode 100644 index 6ba456b..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/test.c +++ /dev/null @@ -1,128 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for wsprintfW() function -** -** -**=========================================================*/ - -#define UNICODE -#include - - -char * ErrorMessage = NULL; -WCHAR * BadResult = NULL; -WCHAR buf[256]; - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with strlen */ - -BOOL test1() -{ - int pos = 0x1234ab; - - wsprintf(buf, convert("foo %x"), pos); - if (memcmp(buf, convert("foo 1234ab"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 1) Failed. The correct string is" - " 'foo 1234ab' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %lx"), pos); - if (memcmp(buf, convert("foo 1234ab"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 2) Failed. The correct string is" - " 'foo 1234ab' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %7x"), pos); - if (memcmp(buf, convert("foo 1234ab"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 3) Failed. The correct string is" - " 'foo 1234ab' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %-7x"), pos); - if (memcmp(buf, convert("foo 1234ab "), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 4) Failed. The correct string is" - " 'foo 1234ab ' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %.1x"), pos); - if (memcmp(buf, convert("foo 1234ab"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 5) Failed. The correct string is" - " 'foo 1234ab' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %.7x"), pos); - if (memcmp(buf, convert("foo 01234ab"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 6) Failed. The correct string is" - " 'foo 01234ab' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %07x"), pos); - if (memcmp(buf, convert("foo 01234ab"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 7) Failed. The correct string is" - " 'foo 01234ab' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %#x"), pos); - if (memcmp(buf, convert("foo 0x1234ab"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 8) Failed. The correct string is" - " 'foo 0x1234ab' and the result returned was "; - BadResult = buf; - return FAIL; - } - - return PASS; -} - -int __cdecl main(int argc, char *argv[]) -{ - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if(test1()) - { - Fail("%s '%s'\n",ErrorMessage,convertC(BadResult)); - - } - - PAL_Terminate(); - return PASS; - -} - - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/testinfo.dat deleted file mode 100644 index 0d38a20..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test12/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = wsprintfW -Name = Positive test of wsprintfW -TYPE = DEFAULT -EXE1 = test -Description -= Test %x formatter with wsprintfW. - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/CMakeLists.txt deleted file mode 100644 index 617abb8..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_wsprintfw_test13 - ${SOURCES} -) - -add_dependencies(paltest_wsprintfw_test13 coreclrpal) - -target_link_libraries(paltest_wsprintfw_test13 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/test.c deleted file mode 100644 index dd0daae..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/test.c +++ /dev/null @@ -1,126 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for wsprintfW() function -** -** -**=========================================================*/ - -#define UNICODE -#include - -char * ErrorMessage = NULL; -WCHAR * BadResult = NULL; -WCHAR buf[256]; - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with strlen */ - -BOOL test1() -{ - int pos = 0x1234ab; - - wsprintf(buf, convert("foo %X"), pos); - if (memcmp(buf, convert("foo 1234AB"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 1) Failed. The correct string is" - " 'foo 1234AB' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %lX"), pos); - if (memcmp(buf, convert("foo 1234AB"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 2) Failed. The correct string is" - " 'foo 1234AB' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %7X"), pos); - if (memcmp(buf, convert("foo 1234AB"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 3) Failed. The correct string is" - " 'foo 1234AB' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %-7X"), pos); - if (memcmp(buf, convert("foo 1234AB "), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 4) Failed. The correct string is" - " 'foo 1234AB ' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %.1X"), pos); - if (memcmp(buf, convert("foo 1234AB"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 5) Failed. The correct string is" - " 'foo 1234AB' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %.7X"), pos); - if (memcmp(buf, convert("foo 01234AB"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 6) Failed. The correct string is" - " 'foo 01234AB' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %07X"), pos); - if (memcmp(buf, convert("foo 01234AB"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 7) Failed. The correct string is" - " 'foo 01234AB' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %#X"), pos); - if (memcmp(buf, convert("foo 0X1234AB"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 8) Failed. The correct string is" - " 'foo 0X1234AB' and the result returned was "; - BadResult = buf; - return FAIL; - } - - return PASS; -} - -int __cdecl main(int argc, char *argv[]) -{ - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if(test1()) - { - Fail("%s '%s'\n",ErrorMessage,convertC(BadResult)); - - } - - PAL_Terminate(); - return PASS; - -} - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/testinfo.dat deleted file mode 100644 index c16a43f..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test13/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = wsprintfW -Name = Positive test of wsprintfW -TYPE = DEFAULT -EXE1 = test -Description -= Test %X formatter with wsprintfW. - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/CMakeLists.txt deleted file mode 100644 index 00b26da..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_wsprintfw_test2 - ${SOURCES} -) - -add_dependencies(paltest_wsprintfw_test2 coreclrpal) - -target_link_libraries(paltest_wsprintfw_test2 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/test.c deleted file mode 100644 index f25ab6c..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/test.c +++ /dev/null @@ -1,108 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for wsprintfW() function -** -** -**=========================================================*/ -#define UNICODE -#include - - -char * ErrorMessage = NULL; -WCHAR * BadResult = NULL; -WCHAR buf[256]; - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with strlen */ - - -BOOL test1() -{ - - wsprintf(buf, convert("foo %s"), convert("bar")); - if (memcmp(buf, convert("foo bar"), wcslen(buf)*2+2) != 0) - { - ErrorMessage = "ERROR: (Test 1) Failed. The correct string is 'foo bar'" - " and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %ls"), convert("bar")); - if (memcmp(buf, convert("foo bar"), wcslen(buf)*2 + 2) != 0){ - ErrorMessage = "ERROR: (Test 2) Failed. The correct string is 'foo bar'" - " and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %5s"), convert("bar")); - if (memcmp(buf, convert("foo bar"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 3) Failed. The correct string is" - " 'foo bar' and the result returned was "; - BadResult = buf; - return FAIL; - } - wsprintf(buf, convert("foo %.2s"), convert("bar")); - if (memcmp(buf, convert("foo ba"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 4) Failed. The correct string is 'foo ba'" - " and the result returned was "; - BadResult = buf; - return FAIL; - } - wsprintf(buf, convert("foo %5.2s"), convert("bar")); - if (memcmp(buf, convert("foo ba"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 5) Failed. The correct string is" - " 'foo ba' and the result returned was "; - BadResult = buf; - return FAIL; - } - wsprintf(buf, convert("foo %-5s"), convert("bar")); - if (memcmp(buf, convert("foo bar "), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 6) Failed. The correct string is" - " 'foo bar ' and the result returned was "; - BadResult = buf; - return FAIL; - } - wsprintf(buf, convert("foo %05s"), convert("bar")); - if (memcmp(buf, convert("foo 00bar"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 7) Failed. The correct string is" - " 'foo 00bar' and the result returned was "; - BadResult = buf; - return FAIL; - } - - return PASS; -} - -int __cdecl main(int argc, char *argv[]) -{ - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if(test1()) - { - Fail("%s '%s'\n",ErrorMessage,convertC(BadResult)); - } - - PAL_Terminate(); - return PASS; - -} diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/testinfo.dat deleted file mode 100644 index a2a7bb2..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test2/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = wsprintfW -Name = Positive test of wsprintfW -TYPE = DEFAULT -EXE1 = test -Description -= Test %s formatter with wsprintfW. - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/CMakeLists.txt deleted file mode 100644 index 25c6185..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_wsprintfw_test3 - ${SOURCES} -) - -add_dependencies(paltest_wsprintfw_test3 coreclrpal) - -target_link_libraries(paltest_wsprintfw_test3 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/test.c deleted file mode 100644 index a52d617..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/test.c +++ /dev/null @@ -1,127 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for wsprintfW() function -** -** -**=========================================================*/ -#define UNICODE -#include - - - -char * ErrorMessage = NULL; -WCHAR * BadResult = NULL; -WCHAR buf[256]; - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with strlen */ - - -BOOL test1() -{ - - wsprintf(buf, convert("foo %S"), "bar"); - if (memcmp(buf, convert("foo bar"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 1) Failed. The correct string is" - " 'foo bar' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %hS"), "bar"); - if (memcmp(buf, convert("foo bar"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 2) Failed. The correct string is" - " 'foo bar' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %lS"), convert("bar")); - if (memcmp(buf, convert("foo bar"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 3) Failed. The correct string is" - " 'foo bar' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %5S"), "bar"); - if (memcmp(buf, convert("foo bar"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 4) Failed. The correct string is" - " 'foo bar' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %.2S"), "bar"); - if (memcmp(buf, convert("foo ba"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 5) Failed. The correct string is" - " 'foo ba' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %5.2S"), "bar"); - if (memcmp(buf, convert("foo ba"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 6) Failed. The correct string is" - " 'foo ba' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %-5S"), "bar"); - if (memcmp(buf, convert("foo bar "), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 7) Failed. The correct string is" - " 'foo bar ' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %05S"), "bar"); - if (memcmp(buf, convert("foo 00bar"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 8) Failed. The correct string is" - " 'foo 00bar' and the result returned was "; - BadResult = buf; - return FAIL; - } - - return PASS; -} - -int __cdecl main(int argc, char *argv[]) -{ - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if(test1()) - { - Fail("%s '%s'\n",ErrorMessage,convertC(BadResult)); - - } - - PAL_Terminate(); - return PASS; - -} - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/testinfo.dat deleted file mode 100644 index 46b7b74..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test3/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = wsprintfW -Name = Positive test of wsprintfW -TYPE = DEFAULT -EXE1 = test -Description -= Test %S formatter with wsprintfW. - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/CMakeLists.txt deleted file mode 100644 index c63a4d5..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_wsprintfw_test6 - ${SOURCES} -) - -add_dependencies(paltest_wsprintfw_test6 coreclrpal) - -target_link_libraries(paltest_wsprintfw_test6 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/test.c deleted file mode 100644 index 513f1f7..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/test.c +++ /dev/null @@ -1,115 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for wsprintfW() function -** -** -**=========================================================*/ -#define UNICODE -#include - - -char * ErrorMessage = NULL; -WCHAR * BadResult = NULL; -WCHAR buf[256]; - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with strlen */ - -BOOL test1() -{ - WCHAR wc = 'b'; - - wsprintf(buf, convert("foo %c"), wc); - if (memcmp(buf, convert("foo b"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 1) Failed. The correct string is" - " 'foo b' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %hc"), wc); - if (memcmp(buf, convert("foo b"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 2) Failed. The correct string is 'foo b'" - " and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %lc"), wc); - if (memcmp(buf, convert("foo b"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 3) Failed. The correct string is 'foo b'" - " and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %5c"), wc); - if (memcmp(buf, convert("foo b"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 4) Failed. The correct string is" - " 'foo b' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %-5c"), wc); - if (memcmp(buf, convert("foo b "), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 5) Failed. The correct string is" - " 'foo b ' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %05c"), wc); - if (memcmp(buf, convert("foo 0000b"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 6) Failed. The correct string is" - " 'foo 0000b' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %#c"), wc); - if (memcmp(buf, convert("foo b"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 7) Failed. The correct string is 'foo b'" - " and the result returned was "; - BadResult = buf; - return FAIL; - } - return PASS; -} -int __cdecl main(int argc, char *argv[]) -{ - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if(test1()) - { - Fail("%s '%s'\n",ErrorMessage,convertC(BadResult)); - - } - - PAL_Terminate(); - return PASS; - -} - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/testinfo.dat deleted file mode 100644 index 627b76f..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test6/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = wsprintfW -Name = Positive test of wsprintfW -TYPE = DEFAULT -EXE1 = test -Description -= Test %c formatter with wsprintfW. - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/CMakeLists.txt deleted file mode 100644 index 25e4310..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_wsprintfw_test7 - ${SOURCES} -) - -add_dependencies(paltest_wsprintfw_test7 coreclrpal) - -target_link_libraries(paltest_wsprintfw_test7 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/test.c deleted file mode 100644 index 99e73b1..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/test.c +++ /dev/null @@ -1,117 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for wsprintfW() function -** -** -**=========================================================*/ -#define UNICODE -#include - - - -char * ErrorMessage = NULL; -WCHAR * BadResult = NULL; -WCHAR buf[256]; - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with strlen */ - - -BOOL test1() -{ - WCHAR wb = 'b'; - - wsprintf(buf, convert("foo %C"), 'b'); - if (memcmp(buf, convert("foo b"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 1) Failed. The correct string is" - " 'foo b' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %hC"), 'b'); - if (memcmp(buf, convert("foo b"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 2) Failed. The correct string is" - " 'foo b' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %lC"), wb); - if (memcmp(buf, convert("foo b"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 3) Failed. The correct string is" - " 'foo b' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %5C"), 'b'); - if (memcmp(buf, convert("foo b"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 4) Failed. The correct string is" - " 'foo b' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %-5C"), 'b'); - if (memcmp(buf, convert("foo b "), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 5) Failed. The correct string is" - " 'foo b ' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %05C"), 'b'); - if (memcmp(buf, convert("foo 0000b"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 6) Failed. The correct string is" - " 'foo 0000b' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %#C"), 'b'); - if (memcmp(buf, convert("foo b"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 7) Failed. The correct string is" - " 'foo b' and the result returned was "; - BadResult = buf; - return FAIL; - } - return PASS; -} -int __cdecl main(int argc, char *argv[]) -{ - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if(test1()) - { - Fail("%s '%s'\n",ErrorMessage,convertC(BadResult)); - - } - - PAL_Terminate(); - return PASS; - -} - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/testinfo.dat deleted file mode 100644 index ffcb47a..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test7/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = wsprintfW -Name = Positive test of wsprintfW -TYPE = DEFAULT -EXE1 = test -Description -= Test %C formatter with wsprintfW. - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/CMakeLists.txt deleted file mode 100644 index a6478a2..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_wsprintfw_test8 - ${SOURCES} -) - -add_dependencies(paltest_wsprintfw_test8 coreclrpal) - -target_link_libraries(paltest_wsprintfw_test8 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/test.c deleted file mode 100644 index 63c296e..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/test.c +++ /dev/null @@ -1,128 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for wsprintfW() function -** -** -**=========================================================*/ -#define UNICODE -#include - - - -char * ErrorMessage = NULL; -WCHAR * BadResult = NULL; -WCHAR buf[256]; - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with strlen */ - - -BOOL test1() -{ - int pos = 42; - - wsprintf(buf, convert("foo %d"), pos); - if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 1) Failed. The correct string is" - " 'foo 42' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %ld"), 0xFFFF); - if (memcmp(buf, convert("foo 65535"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 2) Failed. The correct string is" - " 'foo 65535' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %3d"), pos); - if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 3) Failed. The correct string is" - " 'foo 42' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %-3d"), pos); - if (memcmp(buf, convert("foo 42 "), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 4) Failed. The correct string is" - " 'foo 42 ' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %.1d"), pos); - if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 5) Failed. The correct string is" - " 'foo 42' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %.3d"), pos); - if (memcmp(buf, convert("foo 042"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 6) Failed. The correct string is" - " 'foo 042' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %03d"), pos); - if (memcmp(buf, convert("foo 042"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 7) Failed. The correct string is" - " 'foo 042' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %#d"), pos); - if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 8) Failed. The correct string is" - " 'foo 42' and the result returned was "; - BadResult = buf; - return FAIL; - } - - return PASS; -} -int __cdecl main(int argc, char *argv[]) -{ - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if(test1()) - { - Fail("%s '%s'\n",ErrorMessage,convertC(BadResult)); - - } - - PAL_Terminate(); - return PASS; - -} - - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/testinfo.dat deleted file mode 100644 index 4238671..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test8/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = wsprintfW -Name = Positive test of wsprintfW -TYPE = DEFAULT -EXE1 = test -Description -= Test %d formatter with wsprintfW. - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/CMakeLists.txt b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/CMakeLists.txt deleted file mode 100644 index e09867b..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(SOURCES - test.c -) - -add_executable(paltest_wsprintfw_test9 - ${SOURCES} -) - -add_dependencies(paltest_wsprintfw_test9 coreclrpal) - -target_link_libraries(paltest_wsprintfw_test9 - pthread - m - coreclrpal -) diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/test.c b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/test.c deleted file mode 100644 index 0a49d9c..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/test.c +++ /dev/null @@ -1,128 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test.c -** -** Purpose: Test for wsprintfW() function -** -** -**=========================================================*/ - -#define UNICODE -#include - - -char * ErrorMessage = NULL; -WCHAR * BadResult = NULL; -WCHAR buf[256]; - -/* memcmp is used to verify the results, so this test is dependent on it. */ -/* ditto with strlen */ - - -BOOL test1() -{ - int pos = 42; - - wsprintf(buf, convert("foo %i"), pos); - if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 1) Failed. The correct string is" - " 'foo 42' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %li"), 0xFFFF); - if (memcmp(buf, convert("foo 65535"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 2) Failed. The correct string is" - " 'foo 65535' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %3i"), pos); - if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 3) Failed. The correct string is" - " 'foo 42' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %-3i"), pos); - if (memcmp(buf, convert("foo 42 "), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 4) Failed. The correct string is" - " 'foo 42 ' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %.1i"), pos); - if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 5) Failed. The correct string is" - " 'foo 42' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %.3i"), pos); - if (memcmp(buf, convert("foo 042"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 6) Failed. The correct string is" - " 'foo 042' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %03i"), pos); - if (memcmp(buf, convert("foo 042"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 7) Failed. The correct string is" - " 'foo 042' and the result returned was "; - BadResult = buf; - return FAIL; - } - - wsprintf(buf, convert("foo %#i"), pos); - if (memcmp(buf, convert("foo 42"), wcslen(buf)*2 + 2) != 0) - { - ErrorMessage = "ERROR: (Test 8) Failed. The correct string is" - " 'foo 42' and the result returned was "; - BadResult = buf; - return FAIL; - } - - return PASS; -} - -int __cdecl main(int argc, char *argv[]) -{ - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - if(test1()) - { - Fail("%s '%s'\n",ErrorMessage,convertC(BadResult)); - - } - - PAL_Terminate(); - return PASS; - -} - - diff --git a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/testinfo.dat b/src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/testinfo.dat deleted file mode 100644 index 3006aa8..0000000 --- a/src/pal/tests/palsuite/miscellaneous/wsprintfW/test9/testinfo.dat +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -Version = 1.0 -Section = Miscellaneous -Function = wsprintfW -Name = Positive test of wsprintfW -TYPE = DEFAULT -EXE1 = test -Description -= Test %i formatter with wsprintfW. - - diff --git a/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/CMakeLists.txt index bf1d3a9..515815f 100644 --- a/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - PAL_GetPALDirectoryW.c + PAL_GetPALDirectoryW.cpp ) add_executable(paltest_pal_getpaldirectoryw_test1 diff --git a/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/PAL_GetPALDirectoryW.c b/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/PAL_GetPALDirectoryW.c deleted file mode 100644 index 2c67aa4..0000000 --- a/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/PAL_GetPALDirectoryW.c +++ /dev/null @@ -1,78 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: pal_getpaldirectoryw.c -** -** Purpose: Positive test the PAL_GetPALDirectoryW API. -** Call this API to retrieve a fully-qualified -** directory name where the PAL DLL is loaded from. -** -** -**============================================================*/ -#define UNICODE -#include - -int __cdecl main(int argc, char *argv[]) -{ - int err; - BOOL bValue; - DWORD dwFileAttribute; - WCHAR *wpDirectoryName = NULL; - char *pDirectoryName = NULL; - - /*Initialize the PAL environment*/ - err = PAL_Initialize(argc, argv); - if(0 != err) - { - return FAIL; - } - - /*allocate momory to store the directory name*/ - wpDirectoryName = malloc(MAX_PATH*sizeof(WCHAR)); - if(NULL == wpDirectoryName) - { - Fail("\nFailed to allocate memory for storing directory name!\n"); - } - - UINT size = MAX_PATH; - /*retrieve the machine configuration directory*/ - bValue = PAL_GetPALDirectoryW(wpDirectoryName, &size); - if(FALSE == bValue) - { - free(wpDirectoryName); - Fail("Failed to call PAL_GetPALDirectoryW API, " - "error code =%u\n", GetLastError()); - } - - - /*convert wide char string to a standard one*/ - pDirectoryName = convertC(wpDirectoryName); - if(0 == strlen(pDirectoryName)) - { - free(wpDirectoryName); - free(pDirectoryName); - Fail("The retrieved directory name string is empty!\n"); - } - - /*free the memory*/ - free(pDirectoryName); - - /*retrieve the attribute of a file or directory*/ - dwFileAttribute = GetFileAttributesW(wpDirectoryName); - - /*free the memory*/ - free(wpDirectoryName); - - /*check if the attribute indicates a directory*/ - if(FILE_ATTRIBUTE_DIRECTORY != - (dwFileAttribute & FILE_ATTRIBUTE_DIRECTORY)) - { - Fail("The retrieved directory name is not a valid directory!\n"); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/PAL_GetPALDirectoryW.cpp b/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/PAL_GetPALDirectoryW.cpp new file mode 100644 index 0000000..856bfe8 --- /dev/null +++ b/src/pal/tests/palsuite/pal_specific/PAL_GetPALDirectoryW/test1/PAL_GetPALDirectoryW.cpp @@ -0,0 +1,78 @@ +// 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. + +/*============================================================= +** +** Source: pal_getpaldirectoryw.c +** +** Purpose: Positive test the PAL_GetPALDirectoryW API. +** Call this API to retrieve a fully-qualified +** directory name where the PAL DLL is loaded from. +** +** +**============================================================*/ +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + int err; + BOOL bValue; + DWORD dwFileAttribute; + WCHAR *wpDirectoryName = NULL; + char *pDirectoryName = NULL; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*allocate momory to store the directory name*/ + wpDirectoryName = (WCHAR*)malloc(MAX_PATH*sizeof(WCHAR)); + if(NULL == wpDirectoryName) + { + Fail("\nFailed to allocate memory for storing directory name!\n"); + } + + UINT size = MAX_PATH; + /*retrieve the machine configuration directory*/ + bValue = PAL_GetPALDirectoryW(wpDirectoryName, &size); + if(FALSE == bValue) + { + free(wpDirectoryName); + Fail("Failed to call PAL_GetPALDirectoryW API, " + "error code =%u\n", GetLastError()); + } + + + /*convert wide char string to a standard one*/ + pDirectoryName = convertC(wpDirectoryName); + if(0 == strlen(pDirectoryName)) + { + free(wpDirectoryName); + free(pDirectoryName); + Fail("The retrieved directory name string is empty!\n"); + } + + /*free the memory*/ + free(pDirectoryName); + + /*retrieve the attribute of a file or directory*/ + dwFileAttribute = GetFileAttributesW(wpDirectoryName); + + /*free the memory*/ + free(wpDirectoryName); + + /*check if the attribute indicates a directory*/ + if(FILE_ATTRIBUTE_DIRECTORY != + (dwFileAttribute & FILE_ATTRIBUTE_DIRECTORY)) + { + Fail("The retrieved directory name is not a valid directory!\n"); + } + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/CMakeLists.txt index e8d3c40..26eb1a8 100644 --- a/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - PAL_GetUserTempDirectoryW.c + PAL_GetUserTempDirectoryW.cpp ) add_executable(paltest_pal_getusertempdirectoryw_test1 diff --git a/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/PAL_GetUserTempDirectoryW.c b/src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/PAL_GetUserTempDirectoryW.cpp similarity index 100% rename from src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/PAL_GetUserTempDirectoryW.c rename to src/pal/tests/palsuite/pal_specific/PAL_GetUserTempDirectoryW/test1/PAL_GetUserTempDirectoryW.cpp diff --git a/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/CMakeLists.txt index 416439d..281efcd 100644 --- a/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - PAL_Initialize_Terminate.c + PAL_Initialize_Terminate.cpp ) add_executable(paltest_pal_initialize_terminate_test1 diff --git a/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/PAL_Initialize_Terminate.c b/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/PAL_Initialize_Terminate.cpp similarity index 100% rename from src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/PAL_Initialize_Terminate.c rename to src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test1/PAL_Initialize_Terminate.cpp diff --git a/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/CMakeLists.txt index b7661fd..46b42aa 100644 --- a/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - pal_initialize_twice.c + pal_initialize_twice.cpp ) add_executable(paltest_pal_initialize_terminate_test2 diff --git a/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/pal_initialize_twice.c b/src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/pal_initialize_twice.cpp similarity index 100% rename from src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/pal_initialize_twice.c rename to src/pal/tests/palsuite/pal_specific/PAL_Initialize_Terminate/test2/pal_initialize_twice.cpp diff --git a/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/CMakeLists.txt index 2379694..573ab38 100644 --- a/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - PAL_RegisterLibraryW_UnregisterLibraryW.c + PAL_RegisterLibraryW_UnregisterLibraryW.cpp ) add_executable(paltest_pal_registerlibraryw_unregisterlibraryw_test1 diff --git a/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/PAL_RegisterLibraryW_UnregisterLibraryW.c b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/PAL_RegisterLibraryW_UnregisterLibraryW.c deleted file mode 100644 index ff0d338..0000000 --- a/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/PAL_RegisterLibraryW_UnregisterLibraryW.c +++ /dev/null @@ -1,64 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: pal_registerlibrary_unregisterlibrary -** -** Purpose: Positive test the PAL_RegisterLibrary API and -** PAL_UnRegisterLibrary. -** Call PAL_RegisterLibrary to map a module into the calling -** process address space and call PAL_UnRegisterLibrary -** to unmap this module. -** -** -**============================================================*/ -#define UNICODE -#include - -int __cdecl main(int argc, char *argv[]) -{ - HMODULE ModuleHandle; - char ModuleName[64]; - WCHAR *wpModuleName = NULL; - int err; - - /*Initialize the PAL environment*/ - err = PAL_Initialize(argc, argv); - if(0 != err) - { - return FAIL; - } - - /*zero the buffer*/ - memset(ModuleName,0,64); - sprintf(ModuleName, "%s", "rotor_pal"); - - /*convert a normal string to a wide one*/ - wpModuleName = convert(ModuleName); - - /*load a module*/ - ModuleHandle = PAL_RegisterLibrary(wpModuleName); - - /*free the memory*/ - free(wpModuleName); - - if(!ModuleHandle) - { - Fail("Failed to call PAL_RegisterLibrary API to map a module " - "into calling process, error code=%u!\n", GetLastError()); - } - - /*decrement the reference count of the loaded DLL*/ - err = PAL_UnregisterLibrary(ModuleHandle); - if(0 == err) - { - Fail("\nFailed to call PAL_UnregisterLibrary API to " - "decrement the count of the loaded DLL module, " - "error code=%u!\n", GetLastError()); - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/PAL_RegisterLibraryW_UnregisterLibraryW.cpp b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/PAL_RegisterLibraryW_UnregisterLibraryW.cpp new file mode 100644 index 0000000..8eb8776 --- /dev/null +++ b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test1/PAL_RegisterLibraryW_UnregisterLibraryW.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. +// See the LICENSE file in the project root for more information. + +/*============================================================= +** +** Source: pal_registerlibrary_unregisterlibrary +** +** Purpose: Positive test the PAL_RegisterLibrary API and +** PAL_UnRegisterLibrary. +** Call PAL_RegisterLibrary to map a module into the calling +** process address space and call PAL_UnRegisterLibrary +** to unmap this module. +** +** +**============================================================*/ +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + HMODULE ModuleHandle; + char ModuleName[64]; + WCHAR *wpModuleName = NULL; + int err; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + /*zero the buffer*/ + memset(ModuleName,0,64); + sprintf_s(ModuleName, _countof(ModuleName), "%s", "rotor_pal"); + + /*convert a normal string to a wide one*/ + wpModuleName = convert(ModuleName); + + /*load a module*/ + ModuleHandle = PAL_RegisterLibrary(wpModuleName); + + /*free the memory*/ + free(wpModuleName); + + if(!ModuleHandle) + { + Fail("Failed to call PAL_RegisterLibrary API to map a module " + "into calling process, error code=%u!\n", GetLastError()); + } + + /*decrement the reference count of the loaded DLL*/ + err = PAL_UnregisterLibrary(ModuleHandle); + if(0 == err) + { + Fail("\nFailed to call PAL_UnregisterLibrary API to " + "decrement the count of the loaded DLL module, " + "error code=%u!\n", GetLastError()); + } + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/CMakeLists.txt index bbcb359..ef5c047 100644 --- a/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/CMakeLists.txt +++ b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - reg_unreg_libraryw_neg.c + reg_unreg_libraryw_neg.cpp ) add_executable(paltest_reg_unreg_libraryw_neg diff --git a/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/reg_unreg_libraryw_neg.c b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/reg_unreg_libraryw_neg.c deleted file mode 100644 index a15ff57..0000000 --- a/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/reg_unreg_libraryw_neg.c +++ /dev/null @@ -1,62 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: pal_registerlibraryw_unregisterlibraryw_neg.c -** -** Purpose: Negative test the PAL_RegisterLibrary API. -** Call PAL_RegisterLibrary to map a non-existant module -** into the calling process address space. -** -** -**============================================================*/ -#define UNICODE -#include - -int __cdecl main(int argc, char *argv[]) -{ - HMODULE ModuleHandle; - char ModuleName[64]; - WCHAR *wpModuleName = NULL; - int err; - - /*Initialize the PAL environment*/ - err = PAL_Initialize(argc, argv); - if(0 != err) - { - return FAIL; - } - - memset(ModuleName, 0, 64); - sprintf(ModuleName, "%s", "not_exist_module_name"); - - /*convert a normal string to a wide one*/ - wpModuleName = convert(ModuleName); - - /*load a not exist module*/ - ModuleHandle = PAL_RegisterLibrary(wpModuleName); - - /*free the memory*/ - free(wpModuleName); - - if(NULL != ModuleHandle) - { - Trace("ERROR: PAL_RegisterLibrary successfully mapped " - "a module that does not exist into the calling process\n"); - - /*decrement the reference count of the loaded DLL*/ - err = PAL_UnregisterLibrary(ModuleHandle); - if(0 == err) - { - Trace("\nFailed to call PAL_UnregisterLibrary API to decrement the " - "count of the loaded DLL module!\n"); - } - Fail(""); - - } - - PAL_Terminate(); - return PASS; -} diff --git a/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/reg_unreg_libraryw_neg.cpp b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/reg_unreg_libraryw_neg.cpp new file mode 100644 index 0000000..c6fa4ad --- /dev/null +++ b/src/pal/tests/palsuite/pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/reg_unreg_libraryw_neg.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================= +** +** Source: pal_registerlibraryw_unregisterlibraryw_neg.c +** +** Purpose: Negative test the PAL_RegisterLibrary API. +** Call PAL_RegisterLibrary to map a non-existant module +** into the calling process address space. +** +** +**============================================================*/ +#define UNICODE +#include + +int __cdecl main(int argc, char *argv[]) +{ + HMODULE ModuleHandle; + char ModuleName[64]; + WCHAR *wpModuleName = NULL; + int err; + + /*Initialize the PAL environment*/ + err = PAL_Initialize(argc, argv); + if(0 != err) + { + return FAIL; + } + + memset(ModuleName, 0, 64); + sprintf_s(ModuleName, _countof(ModuleName), "%s", "not_exist_module_name"); + + /*convert a normal string to a wide one*/ + wpModuleName = convert(ModuleName); + + /*load a not exist module*/ + ModuleHandle = PAL_RegisterLibrary(wpModuleName); + + /*free the memory*/ + free(wpModuleName); + + if(NULL != ModuleHandle) + { + Trace("ERROR: PAL_RegisterLibrary successfully mapped " + "a module that does not exist into the calling process\n"); + + /*decrement the reference count of the loaded DLL*/ + err = PAL_UnregisterLibrary(ModuleHandle); + if(0 == err) + { + Trace("\nFailed to call PAL_UnregisterLibrary API to decrement the " + "count of the loaded DLL module!\n"); + } + Fail(""); + + } + + PAL_Terminate(); + return PASS; +} diff --git a/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/CMakeLists.txt index 59922b1..d20ddd9 100644 --- a/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - PAL_errno.c + PAL_errno.cpp ) add_executable(paltest_pal_errno_test1 diff --git a/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/PAL_errno.c b/src/pal/tests/palsuite/pal_specific/PAL_errno/test1/PAL_errno.cpp similarity index 100% rename from src/pal/tests/palsuite/pal_specific/PAL_errno/test1/PAL_errno.c rename to src/pal/tests/palsuite/pal_specific/PAL_errno/test1/PAL_errno.cpp diff --git a/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/CMakeLists.txt index 3436a2d..dbedac9 100644 --- a/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - PAL_get_stderr.c + PAL_get_stderr.cpp ) add_executable(paltest_pal_get_stderr_test1 diff --git a/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/PAL_get_stderr.c b/src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/PAL_get_stderr.cpp similarity index 100% rename from src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/PAL_get_stderr.c rename to src/pal/tests/palsuite/pal_specific/PAL_get_stderr/test1/PAL_get_stderr.cpp diff --git a/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/CMakeLists.txt index 592895b..4d714a3 100644 --- a/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - PAL_get_stdin.c + PAL_get_stdin.cpp ) add_executable(paltest_pal_get_stdin_test1 diff --git a/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/PAL_get_stdin.c b/src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/PAL_get_stdin.cpp similarity index 100% rename from src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/PAL_get_stdin.c rename to src/pal/tests/palsuite/pal_specific/PAL_get_stdin/test1/PAL_get_stdin.cpp diff --git a/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/CMakeLists.txt index 865dd52..4c2f51b 100644 --- a/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - PAL_get_stdout.c + PAL_get_stdout.cpp ) add_executable(paltest_pal_get_stdout_test1 diff --git a/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/PAL_get_stdout.c b/src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/PAL_get_stdout.cpp similarity index 100% rename from src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/PAL_get_stdout.c rename to src/pal/tests/palsuite/pal_specific/PAL_get_stdout/test1/PAL_get_stdout.cpp diff --git a/src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/CMakeLists.txt index cd18b76..82ff922 100644 --- a/src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - pal_entrypoint.c + pal_entrypoint.cpp ) add_executable(paltest_pal_entrypoint_test1 diff --git a/src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/pal_entrypoint.c b/src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/pal_entrypoint.cpp similarity index 100% rename from src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/pal_entrypoint.c rename to src/pal/tests/palsuite/pal_specific/pal_entrypoint/test1/pal_entrypoint.cpp diff --git a/src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/CMakeLists.txt b/src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/CMakeLists.txt index f6e243d..56c9d02 100644 --- a/src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - pal_initializedebug.c + pal_initializedebug.cpp ) add_executable(paltest_pal_initializedebug_test1 diff --git a/src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/pal_initializedebug.c b/src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/pal_initializedebug.cpp similarity index 100% rename from src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/pal_initializedebug.c rename to src/pal/tests/palsuite/pal_specific/pal_initializedebug/test1/pal_initializedebug.cpp diff --git a/src/pal/tests/palsuite/paltestlist.txt b/src/pal/tests/palsuite/paltestlist.txt index d0a76e9..2cedca2 100644 --- a/src/pal/tests/palsuite/paltestlist.txt +++ b/src/pal/tests/palsuite/paltestlist.txt @@ -1,20 +1,28 @@ c_runtime/abs/test1/paltest_abs_test1 c_runtime/acos/test1/paltest_acos_test1 +c_runtime/acosf/test1/paltest_acosf_test1 c_runtime/asin/test1/paltest_asin_test1 +c_runtime/asinf/test1/paltest_asinf_test1 c_runtime/atan/test1/paltest_atan_test1 c_runtime/atan2/test1/paltest_atan2_test1 +c_runtime/atan2f/test1/paltest_atan2f_test1 +c_runtime/atanf/test1/paltest_atanf_test1 c_runtime/atof/test1/paltest_atof_test1 c_runtime/atoi/test1/paltest_atoi_test1 c_runtime/atol/test1/paltest_atol_test1 c_runtime/bsearch/test1/paltest_bsearch_test1 c_runtime/bsearch/test2/paltest_bsearch_test2 c_runtime/ceil/test1/paltest_ceil_test1 +c_runtime/ceilf/test1/paltest_ceilf_test1 c_runtime/cos/test1/paltest_cos_test1 +c_runtime/cosf/test1/paltest_cosf_test1 c_runtime/cosh/test1/paltest_cosh_test1 +c_runtime/coshf/test1/paltest_coshf_test1 c_runtime/errno/test1/paltest_errno_test1 c_runtime/errno/test2/paltest_errno_test2 c_runtime/exit/test1/paltest_exit_test1 c_runtime/exp/test1/paltest_exp_test1 +c_runtime/expf/test1/paltest_expf_test1 c_runtime/fabs/test1/paltest_fabs_test1 c_runtime/fabsf/test1/paltest_fabsf_test1 c_runtime/fclose/test1/paltest_fclose_test1 @@ -24,6 +32,7 @@ c_runtime/fgets/test1/paltest_fgets_test1 c_runtime/fgets/test2/paltest_fgets_test2 c_runtime/fgets/test3/paltest_fgets_test3 c_runtime/floor/test1/paltest_floor_test1 +c_runtime/floorf/test1/paltest_floorf_test1 c_runtime/fmod/test1/paltest_fmod_test1 c_runtime/fmodf/test1/paltest_fmodf_test1 c_runtime/fopen/test1/paltest_fopen_test1 @@ -94,6 +103,8 @@ c_runtime/llabs/test1/paltest_llabs_test1 c_runtime/localtime/test1/paltest_localtime_test1 c_runtime/log/test1/paltest_log_test1 c_runtime/log10/test1/paltest_log10_test1 +c_runtime/log10f/test1/paltest_log10f_test1 +c_runtime/logf/test1/paltest_logf_test1 c_runtime/malloc/test1/paltest_malloc_test1 c_runtime/malloc/test2/paltest_malloc_test2 c_runtime/memchr/test1/paltest_memchr_test1 @@ -104,6 +115,7 @@ c_runtime/memset/test1/paltest_memset_test1 c_runtime/modf/test1/paltest_modf_test1 c_runtime/modff/test1/paltest_modff_test1 c_runtime/pow/test1/paltest_pow_test1 +c_runtime/powf/test1/paltest_powf_test1 c_runtime/printf/test1/paltest_printf_test1 c_runtime/printf/test10/paltest_printf_test10 c_runtime/printf/test11/paltest_printf_test11 @@ -128,44 +140,46 @@ c_runtime/qsort/test2/paltest_qsort_test2 c_runtime/rand_srand/test1/paltest_rand_srand_test1 c_runtime/realloc/test1/paltest_realloc_test1 c_runtime/sin/test1/paltest_sin_test1 +c_runtime/sinf/test1/paltest_sinf_test1 c_runtime/sinh/test1/paltest_sinh_test1 -c_runtime/sprintf/test1/paltest_sprintf_test1 -c_runtime/sprintf/test10/paltest_sprintf_test10 -c_runtime/sprintf/test11/paltest_sprintf_test11 -c_runtime/sprintf/test12/paltest_sprintf_test12 -c_runtime/sprintf/test13/paltest_sprintf_test13 -c_runtime/sprintf/test14/paltest_sprintf_test14 -c_runtime/sprintf/test15/paltest_sprintf_test15 -c_runtime/sprintf/test16/paltest_sprintf_test16 -c_runtime/sprintf/test17/paltest_sprintf_test17 -c_runtime/sprintf/test18/paltest_sprintf_test18 -c_runtime/sprintf/test19/paltest_sprintf_test19 -c_runtime/sprintf/test2/paltest_sprintf_test2 -c_runtime/sprintf/test3/paltest_sprintf_test3 -c_runtime/sprintf/test4/paltest_sprintf_test4 -c_runtime/sprintf/test5/paltest_sprintf_test5 -c_runtime/sprintf/test6/paltest_sprintf_test6 -c_runtime/sprintf/test7/paltest_sprintf_test7 -c_runtime/sprintf/test8/paltest_sprintf_test8 -c_runtime/sprintf/test9/paltest_sprintf_test9 +c_runtime/sinhf/test1/paltest_sinhf_test1 +c_runtime/sprintf_s/test1/paltest_sprintf_test1 +c_runtime/sprintf_s/test10/paltest_sprintf_test10 +c_runtime/sprintf_s/test11/paltest_sprintf_test11 +c_runtime/sprintf_s/test12/paltest_sprintf_test12 +c_runtime/sprintf_s/test13/paltest_sprintf_test13 +c_runtime/sprintf_s/test14/paltest_sprintf_test14 +c_runtime/sprintf_s/test15/paltest_sprintf_test15 +c_runtime/sprintf_s/test16/paltest_sprintf_test16 +c_runtime/sprintf_s/test17/paltest_sprintf_test17 +c_runtime/sprintf_s/test18/paltest_sprintf_test18 +c_runtime/sprintf_s/test19/paltest_sprintf_test19 +c_runtime/sprintf_s/test2/paltest_sprintf_test2 +c_runtime/sprintf_s/test3/paltest_sprintf_test3 +c_runtime/sprintf_s/test4/paltest_sprintf_test4 +c_runtime/sprintf_s/test6/paltest_sprintf_test6 +c_runtime/sprintf_s/test7/paltest_sprintf_test7 +c_runtime/sprintf_s/test8/paltest_sprintf_test8 +c_runtime/sprintf_s/test9/paltest_sprintf_test9 c_runtime/sqrt/test1/paltest_sqrt_test1 -c_runtime/sscanf/test1/paltest_sscanf_test1 -c_runtime/sscanf/test10/paltest_sscanf_test10 -c_runtime/sscanf/test11/paltest_sscanf_test11 -c_runtime/sscanf/test12/paltest_sscanf_test12 -c_runtime/sscanf/test13/paltest_sscanf_test13 -c_runtime/sscanf/test14/paltest_sscanf_test14 -c_runtime/sscanf/test15/paltest_sscanf_test15 -c_runtime/sscanf/test16/paltest_sscanf_test16 -c_runtime/sscanf/test17/paltest_sscanf_test17 -c_runtime/sscanf/test2/paltest_sscanf_test2 -c_runtime/sscanf/test3/paltest_sscanf_test3 -c_runtime/sscanf/test4/paltest_sscanf_test4 -c_runtime/sscanf/test5/paltest_sscanf_test5 -c_runtime/sscanf/test6/paltest_sscanf_test6 -c_runtime/sscanf/test7/paltest_sscanf_test7 -c_runtime/sscanf/test8/paltest_sscanf_test8 -c_runtime/sscanf/test9/paltest_sscanf_test9 +c_runtime/sqrtf/test1/paltest_sqrtf_test1 +c_runtime/sscanf_s/test1/paltest_sscanf_test1 +c_runtime/sscanf_s/test10/paltest_sscanf_test10 +c_runtime/sscanf_s/test11/paltest_sscanf_test11 +c_runtime/sscanf_s/test12/paltest_sscanf_test12 +c_runtime/sscanf_s/test13/paltest_sscanf_test13 +c_runtime/sscanf_s/test14/paltest_sscanf_test14 +c_runtime/sscanf_s/test15/paltest_sscanf_test15 +c_runtime/sscanf_s/test16/paltest_sscanf_test16 +c_runtime/sscanf_s/test17/paltest_sscanf_test17 +c_runtime/sscanf_s/test2/paltest_sscanf_test2 +c_runtime/sscanf_s/test3/paltest_sscanf_test3 +c_runtime/sscanf_s/test4/paltest_sscanf_test4 +c_runtime/sscanf_s/test5/paltest_sscanf_test5 +c_runtime/sscanf_s/test6/paltest_sscanf_test6 +c_runtime/sscanf_s/test7/paltest_sscanf_test7 +c_runtime/sscanf_s/test8/paltest_sscanf_test8 +c_runtime/sscanf_s/test9/paltest_sscanf_test9 c_runtime/strcat/test1/paltest_strcat_test1 c_runtime/strchr/test1/paltest_strchr_test1 c_runtime/strcmp/test1/paltest_strcmp_test1 @@ -218,7 +232,9 @@ c_runtime/swscanf/test7/paltest_swscanf_test7 c_runtime/swscanf/test8/paltest_swscanf_test8 c_runtime/swscanf/test9/paltest_swscanf_test9 c_runtime/tan/test1/paltest_tan_test1 +c_runtime/tanf/test1/paltest_tanf_test1 c_runtime/tanh/test1/paltest_tanh_test1 +c_runtime/tanhf/test1/paltest_tanhf_test1 c_runtime/time/test1/paltest_time_test1 c_runtime/tolower/test1/paltest_tolower_test1 c_runtime/toupper/test1/paltest_toupper_test1 @@ -328,13 +344,13 @@ c_runtime/wprintf/test1/paltest_wprintf_test1 c_runtime/_alloca/test1/paltest_alloca_test1 c_runtime/_fdopen/test1/paltest_fdopen_test1 c_runtime/_finite/test1/paltest_finite_test1 +c_runtime/_finitef/test1/paltest_finitef_test1 c_runtime/_fullpath/test1/paltest_fullpath_test1 c_runtime/_isnan/test1/paltest_isnan_test1 +c_runtime/_isnanf/test1/paltest_isnanf_test1 c_runtime/_itow/test1/paltest_itow_test1 -c_runtime/_makepath/test1/paltest_makepath_test1 c_runtime/_mbsdec/test1/paltest_mbsdec_test1 c_runtime/_mbsinc/test1/paltest_mbsinc_test1 -c_runtime/_mbslen/test1/paltest_mbslen_test1 c_runtime/_mbsninc/test1/paltest_mbsninc_test1 c_runtime/_open_osfhandle/test1/paltest_open_osfhandle_test1 c_runtime/_open_osfhandle/test2/paltest_open_osfhandle_test2 @@ -345,47 +361,43 @@ c_runtime/_putenv/test4/paltest_putenv_test4 c_runtime/_putw/test1/paltest_putw_test1 c_runtime/_rotl/test1/paltest_rotl_test1 c_runtime/_rotr/test1/paltest_rotr_test1 -c_runtime/_snprintf/test1/paltest_snprintf_test1 -c_runtime/_snprintf/test10/paltest_snprintf_test10 -c_runtime/_snprintf/test11/paltest_snprintf_test11 -c_runtime/_snprintf/test12/paltest_snprintf_test12 -c_runtime/_snprintf/test13/paltest_snprintf_test13 -c_runtime/_snprintf/test14/paltest_snprintf_test14 -c_runtime/_snprintf/test15/paltest_snprintf_test15 -c_runtime/_snprintf/test16/paltest_snprintf_test16 -c_runtime/_snprintf/test17/paltest_snprintf_test17 -c_runtime/_snprintf/test18/paltest_snprintf_test18 -c_runtime/_snprintf/test19/paltest_snprintf_test19 -c_runtime/_snprintf/test2/paltest_snprintf_test2 -c_runtime/_snprintf/test3/paltest_snprintf_test3 -c_runtime/_snprintf/test4/paltest_snprintf_test4 -c_runtime/_snprintf/test5/paltest_snprintf_test5 -c_runtime/_snprintf/test6/paltest_snprintf_test6 -c_runtime/_snprintf/test7/paltest_snprintf_test7 -c_runtime/_snprintf/test8/paltest_snprintf_test8 -c_runtime/_snprintf/test9/paltest_snprintf_test9 -c_runtime/_snwprintf/test1/paltest_snwprintf_test1 -c_runtime/_snwprintf/test10/paltest_snwprintf_test10 -c_runtime/_snwprintf/test11/paltest_snwprintf_test11 -c_runtime/_snwprintf/test12/paltest_snwprintf_test12 -c_runtime/_snwprintf/test13/paltest_snwprintf_test13 -c_runtime/_snwprintf/test14/paltest_snwprintf_test14 -c_runtime/_snwprintf/test15/paltest_snwprintf_test15 -c_runtime/_snwprintf/test16/paltest_snwprintf_test16 -c_runtime/_snwprintf/test17/paltest_snwprintf_test17 -c_runtime/_snwprintf/test18/paltest_snwprintf_test18 -c_runtime/_snwprintf/test19/paltest_snwprintf_test19 -c_runtime/_snwprintf/test3/paltest_snwprintf_test3 -c_runtime/_snwprintf/test4/paltest_snwprintf_test4 -c_runtime/_snwprintf/test5/paltest_snwprintf_test5 -c_runtime/_snwprintf/test6/paltest_snwprintf_test6 -c_runtime/_snwprintf/test8/paltest_snwprintf_test8 -c_runtime/_snwprintf/test9/paltest_snwprintf_test9 -c_runtime/_splitpath/test1/paltest_splitpath_test1 +c_runtime/_snprintf_s/test1/paltest_snprintf_test1 +c_runtime/_snprintf_s/test10/paltest_snprintf_test10 +c_runtime/_snprintf_s/test11/paltest_snprintf_test11 +c_runtime/_snprintf_s/test12/paltest_snprintf_test12 +c_runtime/_snprintf_s/test13/paltest_snprintf_test13 +c_runtime/_snprintf_s/test14/paltest_snprintf_test14 +c_runtime/_snprintf_s/test15/paltest_snprintf_test15 +c_runtime/_snprintf_s/test16/paltest_snprintf_test16 +c_runtime/_snprintf_s/test17/paltest_snprintf_test17 +c_runtime/_snprintf_s/test18/paltest_snprintf_test18 +c_runtime/_snprintf_s/test19/paltest_snprintf_test19 +c_runtime/_snprintf_s/test2/paltest_snprintf_test2 +c_runtime/_snprintf_s/test3/paltest_snprintf_test3 +c_runtime/_snprintf_s/test4/paltest_snprintf_test4 +c_runtime/_snprintf_s/test6/paltest_snprintf_test6 +c_runtime/_snprintf_s/test7/paltest_snprintf_test7 +c_runtime/_snprintf_s/test8/paltest_snprintf_test8 +c_runtime/_snprintf_s/test9/paltest_snprintf_test9 +c_runtime/_snwprintf_s/test1/paltest_snwprintf_test1 +c_runtime/_snwprintf_s/test10/paltest_snwprintf_test10 +c_runtime/_snwprintf_s/test11/paltest_snwprintf_test11 +c_runtime/_snwprintf_s/test12/paltest_snwprintf_test12 +c_runtime/_snwprintf_s/test13/paltest_snwprintf_test13 +c_runtime/_snwprintf_s/test14/paltest_snwprintf_test14 +c_runtime/_snwprintf_s/test15/paltest_snwprintf_test15 +c_runtime/_snwprintf_s/test16/paltest_snwprintf_test16 +c_runtime/_snwprintf_s/test17/paltest_snwprintf_test17 +c_runtime/_snwprintf_s/test18/paltest_snwprintf_test18 +c_runtime/_snwprintf_s/test19/paltest_snwprintf_test19 +c_runtime/_snwprintf_s/test3/paltest_snwprintf_test3 +c_runtime/_snwprintf_s/test4/paltest_snwprintf_test4 +c_runtime/_snwprintf_s/test6/paltest_snwprintf_test6 +c_runtime/_snwprintf_s/test8/paltest_snwprintf_test8 +c_runtime/_snwprintf_s/test9/paltest_snwprintf_test9 c_runtime/_stricmp/test1/paltest_stricmp_test1 c_runtime/_strlwr/test1/paltest_strlwr_test1 c_runtime/_strnicmp/test1/paltest_strnicmp_test1 -c_runtime/_swab/test1/paltest_swab_test1 c_runtime/_vsnprintf/test1/paltest_vsnprintf_test1 c_runtime/_vsnprintf/test10/paltest_vsnprintf_test10 c_runtime/_vsnprintf/test11/paltest_vsnprintf_test11 @@ -405,23 +417,22 @@ c_runtime/_vsnprintf/test6/paltest_vsnprintf_test6 c_runtime/_vsnprintf/test7/paltest_vsnprintf_test7 c_runtime/_vsnprintf/test8/paltest_vsnprintf_test8 c_runtime/_vsnprintf/test9/paltest_vsnprintf_test9 -c_runtime/_vsnwprintf/test1/paltest_vsnwprintf_test1 -c_runtime/_vsnwprintf/test10/paltest_vsnwprintf_test10 -c_runtime/_vsnwprintf/test11/paltest_vsnwprintf_test11 -c_runtime/_vsnwprintf/test12/paltest_vsnwprintf_test12 -c_runtime/_vsnwprintf/test13/paltest_vsnwprintf_test13 -c_runtime/_vsnwprintf/test14/paltest_vsnwprintf_test14 -c_runtime/_vsnwprintf/test15/paltest_vsnwprintf_test15 -c_runtime/_vsnwprintf/test16/paltest_vsnwprintf_test16 -c_runtime/_vsnwprintf/test17/paltest_vsnwprintf_test17 -c_runtime/_vsnwprintf/test18/paltest_vsnwprintf_test18 -c_runtime/_vsnwprintf/test19/paltest_vsnwprintf_test19 -c_runtime/_vsnwprintf/test3/paltest_vsnwprintf_test3 -c_runtime/_vsnwprintf/test4/paltest_vsnwprintf_test4 -c_runtime/_vsnwprintf/test5/paltest_vsnwprintf_test5 -c_runtime/_vsnwprintf/test6/paltest_vsnwprintf_test6 -c_runtime/_vsnwprintf/test8/paltest_vsnwprintf_test8 -c_runtime/_vsnwprintf/test9/paltest_vsnwprintf_test9 +c_runtime/_vsnwprintf_s/test1/paltest_vsnwprintf_test1 +c_runtime/_vsnwprintf_s/test10/paltest_vsnwprintf_test10 +c_runtime/_vsnwprintf_s/test11/paltest_vsnwprintf_test11 +c_runtime/_vsnwprintf_s/test12/paltest_vsnwprintf_test12 +c_runtime/_vsnwprintf_s/test13/paltest_vsnwprintf_test13 +c_runtime/_vsnwprintf_s/test14/paltest_vsnwprintf_test14 +c_runtime/_vsnwprintf_s/test15/paltest_vsnwprintf_test15 +c_runtime/_vsnwprintf_s/test16/paltest_vsnwprintf_test16 +c_runtime/_vsnwprintf_s/test17/paltest_vsnwprintf_test17 +c_runtime/_vsnwprintf_s/test18/paltest_vsnwprintf_test18 +c_runtime/_vsnwprintf_s/test19/paltest_vsnwprintf_test19 +c_runtime/_vsnwprintf_s/test3/paltest_vsnwprintf_test3 +c_runtime/_vsnwprintf_s/test4/paltest_vsnwprintf_test4 +c_runtime/_vsnwprintf_s/test6/paltest_vsnwprintf_test6 +c_runtime/_vsnwprintf_s/test8/paltest_vsnwprintf_test8 +c_runtime/_vsnwprintf_s/test9/paltest_vsnwprintf_test9 c_runtime/_wcsicmp/test1/paltest_wcsicmp_test1 c_runtime/_wcslwr/test1/paltest_wcslwr_test1 c_runtime/_wcsnicmp/test1/paltest_wcsnicmp_test1 @@ -432,7 +443,6 @@ c_runtime/_wfopen/test4/paltest_wfopen_test4 c_runtime/_wfopen/test5/paltest_wfopen_test5 c_runtime/_wfopen/test6/paltest_wfopen_test6 c_runtime/_wfopen/test7/paltest_wfopen_test7 -c_runtime/_wsplitpath/test1/paltest_wsplitpath_test1 c_runtime/_wtoi/test1/paltest_wtoi_test1 c_runtime/__iscsym/test1/paltest_iscsym_test1 debug_api/OutputDebugStringW/test1/paltest_outputdebugstringw_test1 @@ -473,6 +483,8 @@ filemapping_memmgt/MapViewOfFile/test3/paltest_mapviewoffile_test3 filemapping_memmgt/MapViewOfFile/test4/paltest_mapviewoffile_test4 filemapping_memmgt/MapViewOfFile/test5/paltest_mapviewoffile_test5 filemapping_memmgt/MapViewOfFile/test6/paltest_mapviewoffile_test6 +filemapping_memmgt/ProbeMemory/test1/paltest_probememory_test1 +filemapping_memmgt/ProbeMemory/ProbeMemory_neg1/paltest_probememory_probememory_neg1 filemapping_memmgt/RtlMoveMemory/test1/paltest_rtlmovememory_test1 filemapping_memmgt/RtlMoveMemory/test3/paltest_rtlmovememory_test3 filemapping_memmgt/RtlMoveMemory/test4/paltest_rtlmovememory_test4 @@ -678,12 +690,6 @@ miscellaneous/InterlockedIncrement/test1/paltest_interlockedincrement_test1 miscellaneous/InterlockedIncrement/test2/paltest_interlockedincrement_test2 miscellaneous/InterlockedIncrement64/test1/paltest_interlockedincrement64_test1 miscellaneous/InterlockedIncrement64/test2/paltest_interlockedincrement64_test2 -miscellaneous/lstrcatW/test1/paltest_lstrcatw_test1 -miscellaneous/lstrcatW/test2/paltest_lstrcatw_test2 -miscellaneous/lstrcatW/test3/paltest_lstrcatw_test3 -miscellaneous/lstrcatW/test4/paltest_lstrcatw_test4 -miscellaneous/lstrcpynW/test1/paltest_lstrcpynw_test1 -miscellaneous/lstrcpyW/test1/paltest_lstrcpyw_test1 miscellaneous/lstrlenA/test1/paltest_lstrlena_test1 miscellaneous/lstrlenW/test1/paltest_lstrlenw_test1 miscellaneous/queryperformancecounter/test1/paltest_queryperformancecounter_test1 @@ -697,27 +703,7 @@ miscellaneous/SetEnvironmentVariableW/test2/paltest_setenvironmentvariablew_test miscellaneous/SetEnvironmentVariableW/test3/paltest_setenvironmentvariablew_test3 miscellaneous/SetEnvironmentVariableW/test4/paltest_setenvironmentvariablew_test4 miscellaneous/SetLastError/test1/paltest_setlasterror_test1 -miscellaneous/wsprintfA/test1/paltest_wsprintfa_test1 -miscellaneous/wsprintfA/test11/paltest_wsprintfa_test11 -miscellaneous/wsprintfA/test12/paltest_wsprintfa_test12 -miscellaneous/wsprintfA/test13/paltest_wsprintfa_test13 -miscellaneous/wsprintfA/test2/paltest_wsprintfa_test2 -miscellaneous/wsprintfA/test3/paltest_wsprintfa_test3 -miscellaneous/wsprintfA/test6/paltest_wsprintfa_test6 -miscellaneous/wsprintfA/test7/paltest_wsprintfa_test7 -miscellaneous/wsprintfA/test8/paltest_wsprintfa_test8 -miscellaneous/wsprintfA/test9/paltest_wsprintfa_test9 -miscellaneous/wsprintfW/test1/paltest_wsprintfw_test1 -miscellaneous/wsprintfW/test11/paltest_wsprintfw_test11 -miscellaneous/wsprintfW/test12/paltest_wsprintfw_test12 -miscellaneous/wsprintfW/test13/paltest_wsprintfw_test13 -miscellaneous/wsprintfW/test3/paltest_wsprintfw_test3 -miscellaneous/wsprintfW/test6/paltest_wsprintfw_test6 -miscellaneous/wsprintfW/test8/paltest_wsprintfw_test8 -miscellaneous/wsprintfW/test9/paltest_wsprintfw_test9 miscellaneous/_i64tow/test1/paltest_i64tow_test1 -miscellaneous/_ui64tow/test1/paltest_ui64tow_test1 -miscellaneous/_ui64tow/test2/paltest_ui64tow_test2 pal_specific/pal_entrypoint/test1/paltest_pal_entrypoint_test1 pal_specific/PAL_errno/test1/paltest_pal_errno_test1 pal_specific/pal_initializedebug/test1/paltest_pal_initializedebug_test1 diff --git a/src/pal/tests/palsuite/paltestlist_to_be_reviewed.txt b/src/pal/tests/palsuite/paltestlist_to_be_reviewed.txt index ac0a2ee..0e12ccb 100644 --- a/src/pal/tests/palsuite/paltestlist_to_be_reviewed.txt +++ b/src/pal/tests/palsuite/paltestlist_to_be_reviewed.txt @@ -26,11 +26,10 @@ c_runtime/_ecvt/test1/paltest_ecvt_test1 c_runtime/_gcvt/test1/paltest_gcvt_test1 c_runtime/_gcvt/test2/paltest_gcvt_test2 c_runtime/_getw/test1/paltest_getw_test1 -c_runtime/_snwprintf/test2/paltest_snwprintf_test2 -c_runtime/_snwprintf/test7/paltest_snwprintf_test7 -c_runtime/_vsnwprintf/test2/paltest_vsnwprintf_test2 -c_runtime/_vsnwprintf/test7/paltest_vsnwprintf_test7 -c_runtime/_wmakepath/test1/paltest_wmakepath_test1 +c_runtime/_snwprintf_s/test2/paltest_snwprintf_test2 +c_runtime/_snwprintf_s/test7/paltest_snwprintf_test7 +c_runtime/_vsnwprintf_s/test2/paltest_vsnwprintf_test2 +c_runtime/_vsnwprintf_s/test7/paltest_vsnwprintf_test7 debug_api/DebugBreak/test1/paltest_debugbreak_test1 debug_api/OutputDebugStringA/test1/paltest_outputdebugstringa_test1 debug_api/WriteProcessMemory/test1/paltest_writeprocessmemory_test1 diff --git a/src/pal/tests/palsuite/palverify.dat b/src/pal/tests/palsuite/palverify.dat index 36b48d6..d6e113b 100644 --- a/src/pal/tests/palsuite/palverify.dat +++ b/src/pal/tests/palsuite/palverify.dat @@ -7,16 +7,16 @@ c_runtime/_alloca/test1,1 c_runtime/_ecvt/test1,1 c_runtime/_fdopen/test1,1 c_runtime/_finite/test1,1 +c_runtime/_finitef/test1,1 c_runtime/_fullpath/test1,1 c_runtime/_gcvt/test1,1 c_runtime/_gcvt/test2,1 c_runtime/_getw/test1,1 c_runtime/_isnan/test1,1 +c_runtime/_isnanf/test1,1 c_runtime/_itow/test1,1 -c_runtime/_makepath/test1,1 c_runtime/_mbsdec/test1,1 c_runtime/_mbsinc/test1,1 -c_runtime/_mbslen/test1,1 c_runtime/_mbsninc/test1,1 c_runtime/_open_osfhandle/test1,1 c_runtime/_open_osfhandle/test2,1 @@ -27,49 +27,45 @@ c_runtime/_putenv/test4,1 c_runtime/_putw/test1,1 c_runtime/_rotl/test1,1 c_runtime/_rotr/test1,1 -c_runtime/_snprintf/test1,1 -c_runtime/_snprintf/test2,1 -c_runtime/_snprintf/test3,1 -c_runtime/_snprintf/test4,1 -c_runtime/_snprintf/test5,1 -c_runtime/_snprintf/test6,1 -c_runtime/_snprintf/test7,1 -c_runtime/_snprintf/test8,1 -c_runtime/_snprintf/test9,1 -c_runtime/_snprintf/test10,1 -c_runtime/_snprintf/test11,1 -c_runtime/_snprintf/test12,1 -c_runtime/_snprintf/test13,1 -c_runtime/_snprintf/test14,1 -c_runtime/_snprintf/test15,1 -c_runtime/_snprintf/test16,1 -c_runtime/_snprintf/test17,1 -c_runtime/_snprintf/test18,1 -c_runtime/_snprintf/test19,1 -c_runtime/_snwprintf/test1,1 -c_runtime/_snwprintf/test2,1 -c_runtime/_snwprintf/test3,1 -c_runtime/_snwprintf/test4,1 -c_runtime/_snwprintf/test5,1 -c_runtime/_snwprintf/test6,1 -c_runtime/_snwprintf/test7,1 -c_runtime/_snwprintf/test8,1 -c_runtime/_snwprintf/test9,1 -c_runtime/_snwprintf/test10,1 -c_runtime/_snwprintf/test11,1 -c_runtime/_snwprintf/test12,1 -c_runtime/_snwprintf/test13,1 -c_runtime/_snwprintf/test14,1 -c_runtime/_snwprintf/test15,1 -c_runtime/_snwprintf/test16,1 -c_runtime/_snwprintf/test17,1 -c_runtime/_snwprintf/test18,1 -c_runtime/_snwprintf/test19,1 -c_runtime/_splitpath/test1,1 +c_runtime/_snprintf_s/test1,1 +c_runtime/_snprintf_s/test2,1 +c_runtime/_snprintf_s/test3,1 +c_runtime/_snprintf_s/test4,1 +c_runtime/_snprintf_s/test6,1 +c_runtime/_snprintf_s/test7,1 +c_runtime/_snprintf_s/test8,1 +c_runtime/_snprintf_s/test9,1 +c_runtime/_snprintf_s/test10,1 +c_runtime/_snprintf_s/test11,1 +c_runtime/_snprintf_s/test12,1 +c_runtime/_snprintf_s/test13,1 +c_runtime/_snprintf_s/test14,1 +c_runtime/_snprintf_s/test15,1 +c_runtime/_snprintf_s/test16,1 +c_runtime/_snprintf_s/test17,1 +c_runtime/_snprintf_s/test18,1 +c_runtime/_snprintf_s/test19,1 +c_runtime/_snwprintf_s/test1,1 +c_runtime/_snwprintf_s/test2,1 +c_runtime/_snwprintf_s/test3,1 +c_runtime/_snwprintf_s/test4,1 +c_runtime/_snwprintf_s/test6,1 +c_runtime/_snwprintf_s/test7,1 +c_runtime/_snwprintf_s/test8,1 +c_runtime/_snwprintf_s/test9,1 +c_runtime/_snwprintf_s/test10,1 +c_runtime/_snwprintf_s/test11,1 +c_runtime/_snwprintf_s/test12,1 +c_runtime/_snwprintf_s/test13,1 +c_runtime/_snwprintf_s/test14,1 +c_runtime/_snwprintf_s/test15,1 +c_runtime/_snwprintf_s/test16,1 +c_runtime/_snwprintf_s/test17,1 +c_runtime/_snwprintf_s/test18,1 +c_runtime/_snwprintf_s/test19,1 c_runtime/_stricmp/test1,1 c_runtime/_strlwr/test1,1 c_runtime/_strnicmp/test1,1 -c_runtime/_swab/test1,1 c_runtime/_vsnprintf/test1,1 c_runtime/_vsnprintf/test2,1 c_runtime/_vsnprintf/test3,1 @@ -89,25 +85,25 @@ c_runtime/_vsnprintf/test16,1 c_runtime/_vsnprintf/test17,1 c_runtime/_vsnprintf/test18,1 c_runtime/_vsnprintf/test19,1 -c_runtime/_vsnwprintf/test1,1 -c_runtime/_vsnwprintf/test2,1 -c_runtime/_vsnwprintf/test3,1 -c_runtime/_vsnwprintf/test4,1 -c_runtime/_vsnwprintf/test5,1 -c_runtime/_vsnwprintf/test6,1 -c_runtime/_vsnwprintf/test7,1 -c_runtime/_vsnwprintf/test8,1 -c_runtime/_vsnwprintf/test9,1 -c_runtime/_vsnwprintf/test10,1 -c_runtime/_vsnwprintf/test11,1 -c_runtime/_vsnwprintf/test12,1 -c_runtime/_vsnwprintf/test13,1 -c_runtime/_vsnwprintf/test14,1 -c_runtime/_vsnwprintf/test15,1 -c_runtime/_vsnwprintf/test16,1 -c_runtime/_vsnwprintf/test17,1 -c_runtime/_vsnwprintf/test18,1 -c_runtime/_vsnwprintf/test19,1 +c_runtime/_vsnwprintf_s/test1,1 +c_runtime/_vsnwprintf_s/test2,1 +c_runtime/_vsnwprintf_s/test3,1 +c_runtime/_vsnwprintf_s/test4,1 +c_runtime/_vsnwprintf_s/test5,1 +c_runtime/_vsnwprintf_s/test6,1 +c_runtime/_vsnwprintf_s/test7,1 +c_runtime/_vsnwprintf_s/test8,1 +c_runtime/_vsnwprintf_s/test9,1 +c_runtime/_vsnwprintf_s/test10,1 +c_runtime/_vsnwprintf_s/test11,1 +c_runtime/_vsnwprintf_s/test12,1 +c_runtime/_vsnwprintf_s/test13,1 +c_runtime/_vsnwprintf_s/test14,1 +c_runtime/_vsnwprintf_s/test15,1 +c_runtime/_vsnwprintf_s/test16,1 +c_runtime/_vsnwprintf_s/test17,1 +c_runtime/_vsnwprintf_s/test18,1 +c_runtime/_vsnwprintf_s/test19,1 c_runtime/_wcsicmp/test1,1 c_runtime/_wcslwr/test1,1 c_runtime/_wcsnicmp/test1,1 @@ -118,27 +114,33 @@ c_runtime/_wfopen/test4,1 c_runtime/_wfopen/test5,1 c_runtime/_wfopen/test6,1 c_runtime/_wfopen/test7,1 -c_runtime/_wmakepath/test1,1 -c_runtime/_wsplitpath/test1,1 c_runtime/_wtoi/test1,1 c_runtime/abs/test1,1 c_runtime/acos/test1,1 +c_runtime/acosf/test1,1 c_runtime/asin/test1,1 +c_runtime/asinf/test1,1 c_runtime/atan/test1,1 c_runtime/atan2/test1,1 +c_runtime/atan2f/test1,1 +c_runtime/atanf/test1,1 c_runtime/atof/test1,1 c_runtime/atoi/test1,1 c_runtime/atol/test1,1 c_runtime/bsearch/test1,1 c_runtime/bsearch/test2,1 c_runtime/ceil/test1,1 +c_runtime/ceilf/test1,1 c_runtime/cos/test1,1 +c_runtime/cosf/test1,1 c_runtime/cosh/test1,1 +c_runtime/coshf/test1,1 c_runtime/ctime/test1,1 c_runtime/errno/test1,1 c_runtime/errno/test2,1 c_runtime/exit/test1,1 c_runtime/exp/test1,1 +c_runtime/expf/test1,1 c_runtime/fabs/test1,1 c_runtime/fabsf/test1,1 c_runtime/fclose/test1,1 @@ -151,6 +153,7 @@ c_runtime/fgets/test1,1 c_runtime/fgets/test2,1 c_runtime/fgets/test3,1 c_runtime/floor/test1,1 +c_runtime/floorf/test1,1 c_runtime/fmod/test1,1 c_runtime/fmodf/test1,1 c_runtime/fopen/test1,1 @@ -230,6 +233,8 @@ c_runtime/llabs/test1,1 c_runtime/localtime/test1,1 c_runtime/log/test1,1 c_runtime/log10/test1,1 +c_runtime/log10f/test1,1 +c_runtime/logf/test1,1 c_runtime/malloc/test1,1 c_runtime/memchr/test1,1 c_runtime/memcmp/test1,1 @@ -238,6 +243,7 @@ c_runtime/memmove/test1,1 c_runtime/memset/test1,1 c_runtime/modf/test1,1 c_runtime/pow/test1,1 +c_runtime/powf/test1,1 c_runtime/printf/test1,1 c_runtime/printf/test2,1 c_runtime/printf/test3,1 @@ -262,44 +268,46 @@ c_runtime/qsort/test2,1 c_runtime/rand_srand/test1,1 c_runtime/realloc/test1,1 c_runtime/sin/test1,1 +c_runtime/sinf/test1,1 c_runtime/sinh/test1,1 -c_runtime/sprintf/test1,1 -c_runtime/sprintf/test2,1 -c_runtime/sprintf/test3,1 -c_runtime/sprintf/test4,1 -c_runtime/sprintf/test5,1 -c_runtime/sprintf/test6,1 -c_runtime/sprintf/test7,1 -c_runtime/sprintf/test8,1 -c_runtime/sprintf/test9,1 -c_runtime/sprintf/test10,1 -c_runtime/sprintf/test11,1 -c_runtime/sprintf/test12,1 -c_runtime/sprintf/test13,1 -c_runtime/sprintf/test14,1 -c_runtime/sprintf/test15,1 -c_runtime/sprintf/test16,1 -c_runtime/sprintf/test17,1 -c_runtime/sprintf/test18,1 -c_runtime/sprintf/test19,1 +c_runtime/sinhf/test1,1 +c_runtime/sprintf_s/test1,1 +c_runtime/sprintf_s/test2,1 +c_runtime/sprintf_s/test3,1 +c_runtime/sprintf_s/test4,1 +c_runtime/sprintf_s/test6,1 +c_runtime/sprintf_s/test7,1 +c_runtime/sprintf_s/test8,1 +c_runtime/sprintf_s/test9,1 +c_runtime/sprintf_s/test10,1 +c_runtime/sprintf_s/test11,1 +c_runtime/sprintf_s/test12,1 +c_runtime/sprintf_s/test13,1 +c_runtime/sprintf_s/test14,1 +c_runtime/sprintf_s/test15,1 +c_runtime/sprintf_s/test16,1 +c_runtime/sprintf_s/test17,1 +c_runtime/sprintf_s/test18,1 +c_runtime/sprintf_s/test19,1 c_runtime/sqrt/test1,1 -c_runtime/sscanf/test1,1 -c_runtime/sscanf/test2,1 -c_runtime/sscanf/test3,1 -c_runtime/sscanf/test4,1 -c_runtime/sscanf/test5,1 -c_runtime/sscanf/test6,1 -c_runtime/sscanf/test7,1 -c_runtime/sscanf/test8,1 -c_runtime/sscanf/test9,1 -c_runtime/sscanf/test10,1 -c_runtime/sscanf/test11,1 -c_runtime/sscanf/test12,1 -c_runtime/sscanf/test13,1 -c_runtime/sscanf/test14,1 -c_runtime/sscanf/test15,1 -c_runtime/sscanf/test16,1 -c_runtime/sscanf/test17,1 +c_runtime/sqrtf/test1,1 +c_runtime/sscanf_s/test1,1 +c_runtime/sscanf_s/test2,1 +c_runtime/sscanf_s/test3,1 +c_runtime/sscanf_s/test4,1 +c_runtime/sscanf_s/test5,1 +c_runtime/sscanf_s/test6,1 +c_runtime/sscanf_s/test7,1 +c_runtime/sscanf_s/test8,1 +c_runtime/sscanf_s/test9,1 +c_runtime/sscanf_s/test10,1 +c_runtime/sscanf_s/test11,1 +c_runtime/sscanf_s/test12,1 +c_runtime/sscanf_s/test13,1 +c_runtime/sscanf_s/test14,1 +c_runtime/sscanf_s/test15,1 +c_runtime/sscanf_s/test16,1 +c_runtime/sscanf_s/test17,1 c_runtime/strcat/test1,1 c_runtime/strchr/test1,1 c_runtime/strcmp/test1,1 @@ -354,7 +362,9 @@ c_runtime/swscanf/test15,1 c_runtime/swscanf/test16,1 c_runtime/swscanf/test17,1 c_runtime/tan/test1,1 +c_runtime/tanf/test1,1 c_runtime/tanh/test1,1 +c_runtime/tanhf/test1,1 c_runtime/time/test1,1 c_runtime/tolower/test1,1 c_runtime/toupper/test1,1 @@ -715,8 +725,6 @@ locale_info/widechartomultibyte/test1,1 locale_info/widechartomultibyte/test2,1 locale_info/widechartomultibyte/test3,1 miscellaneous/_i64tow/test1,1 -miscellaneous/_ui64tow/test1,1 -miscellaneous/_ui64tow/test2,1 miscellaneous/charnexta/test1,1 miscellaneous/charnexta/test2,1 miscellaneous/charnextexa/test1,1 diff --git a/src/pal/tests/palsuite/samples/test1/CMakeLists.txt b/src/pal/tests/palsuite/samples/test1/CMakeLists.txt index da5892c..42f2ebd 100644 --- a/src/pal/tests/palsuite/samples/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/samples/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_samples_test1 diff --git a/src/pal/tests/palsuite/samples/test1/test.c b/src/pal/tests/palsuite/samples/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/samples/test1/test.c rename to src/pal/tests/palsuite/samples/test1/test.cpp diff --git a/src/pal/tests/palsuite/samples/test2/CMakeLists.txt b/src/pal/tests/palsuite/samples/test2/CMakeLists.txt index fdef2aa..1a7ce29 100644 --- a/src/pal/tests/palsuite/samples/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/samples/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_samples_test2 diff --git a/src/pal/tests/palsuite/samples/test2/test.c b/src/pal/tests/palsuite/samples/test2/test.cpp similarity index 100% rename from src/pal/tests/palsuite/samples/test2/test.c rename to src/pal/tests/palsuite/samples/test2/test.cpp diff --git a/src/pal/tests/palsuite/threading/CreateEventA/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateEventA/test1/CMakeLists.txt index da1232e..7be9481 100644 --- a/src/pal/tests/palsuite/threading/CreateEventA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateEventA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_createeventa_test1 diff --git a/src/pal/tests/palsuite/threading/CreateEventA/test1/test1.c b/src/pal/tests/palsuite/threading/CreateEventA/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateEventA/test1/test1.c rename to src/pal/tests/palsuite/threading/CreateEventA/test1/test1.cpp diff --git a/src/pal/tests/palsuite/threading/CreateEventA/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateEventA/test2/CMakeLists.txt index f87e5be..9725c89 100644 --- a/src/pal/tests/palsuite/threading/CreateEventA/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateEventA/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_createeventa_test2 diff --git a/src/pal/tests/palsuite/threading/CreateEventA/test2/test2.c b/src/pal/tests/palsuite/threading/CreateEventA/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateEventA/test2/test2.c rename to src/pal/tests/palsuite/threading/CreateEventA/test2/test2.cpp diff --git a/src/pal/tests/palsuite/threading/CreateEventA/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateEventA/test3/CMakeLists.txt index e33c404..b596a88 100644 --- a/src/pal/tests/palsuite/threading/CreateEventA/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateEventA/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_createeventa_test3 diff --git a/src/pal/tests/palsuite/threading/CreateEventA/test3/test3.c b/src/pal/tests/palsuite/threading/CreateEventA/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateEventA/test3/test3.c rename to src/pal/tests/palsuite/threading/CreateEventA/test3/test3.cpp diff --git a/src/pal/tests/palsuite/threading/CreateEventW/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateEventW/test1/CMakeLists.txt index 0e8ba5b..ef18312 100644 --- a/src/pal/tests/palsuite/threading/CreateEventW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateEventW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_createeventw_test1 diff --git a/src/pal/tests/palsuite/threading/CreateEventW/test1/test1.c b/src/pal/tests/palsuite/threading/CreateEventW/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateEventW/test1/test1.c rename to src/pal/tests/palsuite/threading/CreateEventW/test1/test1.cpp diff --git a/src/pal/tests/palsuite/threading/CreateEventW/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateEventW/test2/CMakeLists.txt index f624377..7f9543e 100644 --- a/src/pal/tests/palsuite/threading/CreateEventW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateEventW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_createeventw_test2 diff --git a/src/pal/tests/palsuite/threading/CreateEventW/test2/test2.c b/src/pal/tests/palsuite/threading/CreateEventW/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateEventW/test2/test2.c rename to src/pal/tests/palsuite/threading/CreateEventW/test2/test2.cpp diff --git a/src/pal/tests/palsuite/threading/CreateEventW/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateEventW/test3/CMakeLists.txt index 4493ba3..6778740 100644 --- a/src/pal/tests/palsuite/threading/CreateEventW/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateEventW/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_createeventw_test3 diff --git a/src/pal/tests/palsuite/threading/CreateEventW/test3/test3.c b/src/pal/tests/palsuite/threading/CreateEventW/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateEventW/test3/test3.c rename to src/pal/tests/palsuite/threading/CreateEventW/test3/test3.cpp diff --git a/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CMakeLists.txt index ffdf132..782c671 100644 --- a/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateMutexA.c + CreateMutexA.cpp ) add_executable(paltest_createmutexa_releasemutex_test1 diff --git a/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CreateMutexA.c b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CreateMutexA.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CreateMutexA.c rename to src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test1/CreateMutexA.cpp diff --git a/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CMakeLists.txt index 925c5d4..3540cb2 100644 --- a/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateMutexA.c + CreateMutexA.cpp ) add_executable(paltest_createmutexa_releasemutex_test2 diff --git a/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CreateMutexA.c b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CreateMutexA.c deleted file mode 100644 index 3b83ba9..0000000 --- a/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CreateMutexA.c +++ /dev/null @@ -1,331 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: CreateMutexA_ReleaseMutex/test2/CreateMutexA.c -** -** Purpose: This test case tests the following things -** - Creation of named Mutexes -** - Creating multiple handles to a single named Mutex -** - Ensuring that these handles work interchangeably -** - Setting bInitialOwnerFlag to TRUE will cause the -** initial call to a Wait function on the same Mutex -** to actually wait. -** - Waiting on a Mutex that a thread already owns does -** not block. -** - Create Named mutex with empty string ("") -** - Create Named mutex with string of MAX_LONGPATH length -** - Calling RelaseMutex with invalid Mutex handles and -** valid but unowned Mutexes. -** -** Dependencies: CreateThread -** ReleaseMutex -** WaitForSingleObject -** CloseHandle -** Sleep -** memset -** - -** -**=========================================================*/ - -#define UNICODE -#include - -const char *szMutex = "MyMutex"; -const char *szEmpty = ""; - -/* Function Prototypes */ -BOOL TestNamedMutex(const char *szMutexName); -DWORD NamedMutexThread(LPVOID lpParam); -BOOL NegativeReleaseMutexTests(); - -struct ThreadData -{ - HANDLE hMutex; - BOOL bReturnCode; -}; -typedef struct ThreadData THREADDATA; - - -int __cdecl main (int argc, char **argv) -{ - BOOL bFailures = FALSE; - char *szMaxPath; - - if(0 != (PAL_Initialize(argc, argv))) - { - return ( FAIL ); - } - - - /* - * Test named Mutexes with ordinary string - */ - - if (!TestNamedMutex(szMutex)) - { - bFailures = TRUE; - } - - - /* - * Test named Mutexes with empty ("") string - */ - - if (!TestNamedMutex(szEmpty)) - { - bFailures = TRUE; - } - - - /* - * Test named Mutexes with string of length MAX_LONGPATHPATH - */ - - szMaxPath = (char *)malloc(MAX_LONGPATH+2); - memset(szMaxPath, 'A', MAX_LONGPATH-60); - szMaxPath[MAX_LONGPATH-60] = 0; - - if (!TestNamedMutex(szMaxPath)) - { - bFailures = TRUE; - } - - free(szMaxPath); - - - /* - * Run some negative tests on ReleaseMutex - */ - - if (!NegativeReleaseMutexTests()) - { - bFailures = TRUE; - } - - - /* - * If there were any failures, then abort with a call to Fail - */ - - if (bFailures == TRUE) - { - Fail("ERROR: There some failures in the Mutex tests.\n"); - } - - PAL_Terminate(); - return ( PASS ); -} - - -/* - * Testing Function - * - * Try to get multiple handles to a named Mutex and test - * to make sure they actually refer to same Mutex object. - */ -BOOL TestNamedMutex(const char *szMutexName) -{ - DWORD dwData; - HANDLE hMutex1; - HANDLE hMutex2; - HANDLE hThread; - THREADDATA threadData; - - /* Create a mutex and take ownership immediately */ - hMutex1 = CreateMutexA (NULL, TRUE, szMutexName); - - if (NULL == hMutex1) - { - Trace("ERROR: CreateMutexA #1 failed. GetLastError returned %u\n", - GetLastError()); - return FALSE; - } - - /* Try to wait on the Mutex we just created. We should not block. */ - if (WaitForSingleObject(hMutex1, 1000) == WAIT_TIMEOUT) - { - Trace("WaitForSingleObject blocked on a Mutex that we owned.\n"); - return FALSE; - } - /* We have to call ReleaseMutex here because of the Wait */ - if (ReleaseMutex(hMutex1) == FALSE) - { - Trace("ReleaseMutex Failed.\n"); - return FALSE; - } - - /* Get a second handle to the same mutex */ - hMutex2 = CreateMutexA (NULL, FALSE, szMutexName); - - if (NULL == hMutex2) - { - Trace("ERROR: CreateMutex #2 failed. GetLastError returned %u\n", - GetLastError()); - free(szMutexName); - return FALSE; - } - - /* - * Create a thread that will Wait on the second handle. - */ - threadData.hMutex = hMutex2; - hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)NamedMutexThread, - (LPVOID)&threadData, 0, &dwData); - - if (NULL == hThread) - { - Trace("ERROR: CreateThread failed. GetLastError returned %u\n", - GetLastError()); - return FALSE; - } - - /* Give the thread a little time to execute & wait*/ - Sleep(500); - - /* Signal the the first handle */ - if (ReleaseMutex(hMutex1) == FALSE) - { - Trace("ReleaseMutex Failed.\n"); - return FALSE; - } - - /* Give the thread some time to finish */ - Sleep(2000); - - /* Clean Up */ - if (CloseHandle(hMutex1) == FALSE || - CloseHandle(hMutex2) == FALSE || - CloseHandle(hThread) == FALSE) - { - Trace("ERROR: CloseHandle failed.\n"); - return FALSE; - } - - /* Check the return code to see if signalling the first */ - /* Mutex handle woke up the thread which was Waiting on */ - /* the second handle. */ - if (threadData.bReturnCode != FALSE) - { - Trace("ERROR: The handles did not refer to the same Mutex object.\n"); - return FALSE; - } - - return TRUE; -} - - -/* - * Thread function used with above testing function. - */ -DWORD NamedMutexThread(LPVOID lpParam) -{ - BOOL bTimedOut = FALSE; - THREADDATA *lpThreadData = (THREADDATA *)lpParam; - - /* Wait on the Mutex that was passed to us */ - if (WaitForSingleObject(lpThreadData->hMutex, 10000) == WAIT_TIMEOUT) - { - /* The Mutex was not signaled in the allotted time */ - bTimedOut = TRUE; - } - if (ReleaseMutex(lpThreadData->hMutex) == FALSE) - { - Trace("ERROR: ReleaseMutex failed.\n"); - lpThreadData->bReturnCode = FALSE; - return 0; - } - - /* Indicate whether we timed out Waiting on the Mutex */ - lpThreadData->bReturnCode = bTimedOut; - - return 0; -} - - -/* - * Testing Function - * - * Try some negative tests on ReleaseMutex - */ -BOOL NegativeReleaseMutexTests() -{ - HANDLE hMutex; - BOOL bRet; - BOOL bResults = TRUE; - - - /* - * Try calling ReleaseMutex on a null handle - */ - hMutex = 0; - bRet = ReleaseMutex(hMutex); - - if (bRet != 0) - { - Trace("Error: ReleaseMutex accepted null handle.\n"); - bResults = FALSE; - } - - - /* - * Try calling ReleaseMutex on an handle that we don't own - */ - hMutex = CreateMutexA (NULL, TRUE, NULL); - if (hMutex == 0) - { - Trace("Error: CreateMutex failed.\n"); - bResults = FALSE; - } - - bRet = ReleaseMutex(hMutex); - bRet = ReleaseMutex(hMutex); - - if (bRet != FALSE) - { - Trace("Error: ReleaseMutex accepted unowned handle.\n"); - bResults = FALSE; - } - - if (CloseHandle(hMutex) == FALSE) - { - Trace("Error: CloseHandle failed.\n"); - bResults = FALSE; - } - - - - /* - * Try calling ReleaseMutex on an handle that has been closed - */ - hMutex = CreateMutexA (NULL, TRUE, NULL); - if (hMutex == 0) - { - Trace("Error: CreateMutex failed.\n"); - bResults = FALSE; - } - - if (ReleaseMutex(hMutex) == FALSE) - { - Trace("Error: ReleaseMutex failed.\n"); - bResults = FALSE; - } - if (CloseHandle(hMutex) == FALSE) - { - Trace("Error: CloseHandle failed.\n"); - bResults = FALSE; - } - - bRet = ReleaseMutex(hMutex); - - if (bRet != FALSE) - { - Trace("Error: ReleaseMutex accepted invalid handle.\n"); - bResults = FALSE; - } - - return bResults; -} diff --git a/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CreateMutexA.cpp b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CreateMutexA.cpp new file mode 100644 index 0000000..3629585 --- /dev/null +++ b/src/pal/tests/palsuite/threading/CreateMutexA_ReleaseMutex/test2/CreateMutexA.cpp @@ -0,0 +1,331 @@ +// 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. + +/*============================================================ +** +** Source: CreateMutexA_ReleaseMutex/test2/CreateMutexA.c +** +** Purpose: This test case tests the following things +** - Creation of named Mutexes +** - Creating multiple handles to a single named Mutex +** - Ensuring that these handles work interchangeably +** - Setting bInitialOwnerFlag to TRUE will cause the +** initial call to a Wait function on the same Mutex +** to actually wait. +** - Waiting on a Mutex that a thread already owns does +** not block. +** - Create Named mutex with empty string ("") +** - Create Named mutex with string of MAX_LONGPATH length +** - Calling RelaseMutex with invalid Mutex handles and +** valid but unowned Mutexes. +** +** Dependencies: CreateThread +** ReleaseMutex +** WaitForSingleObject +** CloseHandle +** Sleep +** memset +** + +** +**=========================================================*/ + +#define UNICODE +#include + +const char *szMutex = "MyMutex"; +const char *szEmpty = ""; + +/* Function Prototypes */ +BOOL TestNamedMutex(const char *szMutexName); +DWORD NamedMutexThread(LPVOID lpParam); +BOOL NegativeReleaseMutexTests(); + +struct ThreadData +{ + HANDLE hMutex; + BOOL bReturnCode; +}; +typedef struct ThreadData THREADDATA; + + +int __cdecl main (int argc, char **argv) +{ + BOOL bFailures = FALSE; + char *szMaxPath; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + + /* + * Test named Mutexes with ordinary string + */ + + if (!TestNamedMutex(szMutex)) + { + bFailures = TRUE; + } + + + /* + * Test named Mutexes with empty ("") string + */ + + if (!TestNamedMutex(szEmpty)) + { + bFailures = TRUE; + } + + + /* + * Test named Mutexes with string of length MAX_LONGPATHPATH + */ + + szMaxPath = (char *)malloc(MAX_LONGPATH+2); + memset(szMaxPath, 'A', MAX_LONGPATH-60); + szMaxPath[MAX_LONGPATH-60] = 0; + + if (!TestNamedMutex(szMaxPath)) + { + bFailures = TRUE; + } + + free((void*)szMaxPath); + + + /* + * Run some negative tests on ReleaseMutex + */ + + if (!NegativeReleaseMutexTests()) + { + bFailures = TRUE; + } + + + /* + * If there were any failures, then abort with a call to Fail + */ + + if (bFailures == TRUE) + { + Fail("ERROR: There some failures in the Mutex tests.\n"); + } + + PAL_Terminate(); + return ( PASS ); +} + + +/* + * Testing Function + * + * Try to get multiple handles to a named Mutex and test + * to make sure they actually refer to same Mutex object. + */ +BOOL TestNamedMutex(const char *szMutexName) +{ + DWORD dwData; + HANDLE hMutex1; + HANDLE hMutex2; + HANDLE hThread; + THREADDATA threadData; + + /* Create a mutex and take ownership immediately */ + hMutex1 = CreateMutexA (NULL, TRUE, szMutexName); + + if (NULL == hMutex1) + { + Trace("ERROR: CreateMutexA #1 failed. GetLastError returned %u\n", + GetLastError()); + return FALSE; + } + + /* Try to wait on the Mutex we just created. We should not block. */ + if (WaitForSingleObject(hMutex1, 1000) == WAIT_TIMEOUT) + { + Trace("WaitForSingleObject blocked on a Mutex that we owned.\n"); + return FALSE; + } + /* We have to call ReleaseMutex here because of the Wait */ + if (ReleaseMutex(hMutex1) == FALSE) + { + Trace("ReleaseMutex Failed.\n"); + return FALSE; + } + + /* Get a second handle to the same mutex */ + hMutex2 = CreateMutexA (NULL, FALSE, szMutexName); + + if (NULL == hMutex2) + { + Trace("ERROR: CreateMutex #2 failed. GetLastError returned %u\n", + GetLastError()); + free((void*)szMutexName); + return FALSE; + } + + /* + * Create a thread that will Wait on the second handle. + */ + threadData.hMutex = hMutex2; + hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)NamedMutexThread, + (LPVOID)&threadData, 0, &dwData); + + if (NULL == hThread) + { + Trace("ERROR: CreateThread failed. GetLastError returned %u\n", + GetLastError()); + return FALSE; + } + + /* Give the thread a little time to execute & wait*/ + Sleep(500); + + /* Signal the the first handle */ + if (ReleaseMutex(hMutex1) == FALSE) + { + Trace("ReleaseMutex Failed.\n"); + return FALSE; + } + + /* Give the thread some time to finish */ + Sleep(2000); + + /* Clean Up */ + if (CloseHandle(hMutex1) == FALSE || + CloseHandle(hMutex2) == FALSE || + CloseHandle(hThread) == FALSE) + { + Trace("ERROR: CloseHandle failed.\n"); + return FALSE; + } + + /* Check the return code to see if signalling the first */ + /* Mutex handle woke up the thread which was Waiting on */ + /* the second handle. */ + if (threadData.bReturnCode != FALSE) + { + Trace("ERROR: The handles did not refer to the same Mutex object.\n"); + return FALSE; + } + + return TRUE; +} + + +/* + * Thread function used with above testing function. + */ +DWORD NamedMutexThread(LPVOID lpParam) +{ + BOOL bTimedOut = FALSE; + THREADDATA *lpThreadData = (THREADDATA *)lpParam; + + /* Wait on the Mutex that was passed to us */ + if (WaitForSingleObject(lpThreadData->hMutex, 10000) == WAIT_TIMEOUT) + { + /* The Mutex was not signaled in the allotted time */ + bTimedOut = TRUE; + } + if (ReleaseMutex(lpThreadData->hMutex) == FALSE) + { + Trace("ERROR: ReleaseMutex failed.\n"); + lpThreadData->bReturnCode = FALSE; + return 0; + } + + /* Indicate whether we timed out Waiting on the Mutex */ + lpThreadData->bReturnCode = bTimedOut; + + return 0; +} + + +/* + * Testing Function + * + * Try some negative tests on ReleaseMutex + */ +BOOL NegativeReleaseMutexTests() +{ + HANDLE hMutex; + BOOL bRet; + BOOL bResults = TRUE; + + + /* + * Try calling ReleaseMutex on a null handle + */ + hMutex = 0; + bRet = ReleaseMutex(hMutex); + + if (bRet != 0) + { + Trace("Error: ReleaseMutex accepted null handle.\n"); + bResults = FALSE; + } + + + /* + * Try calling ReleaseMutex on an handle that we don't own + */ + hMutex = CreateMutexA (NULL, TRUE, NULL); + if (hMutex == 0) + { + Trace("Error: CreateMutex failed.\n"); + bResults = FALSE; + } + + bRet = ReleaseMutex(hMutex); + bRet = ReleaseMutex(hMutex); + + if (bRet != FALSE) + { + Trace("Error: ReleaseMutex accepted unowned handle.\n"); + bResults = FALSE; + } + + if (CloseHandle(hMutex) == FALSE) + { + Trace("Error: CloseHandle failed.\n"); + bResults = FALSE; + } + + + + /* + * Try calling ReleaseMutex on an handle that has been closed + */ + hMutex = CreateMutexA (NULL, TRUE, NULL); + if (hMutex == 0) + { + Trace("Error: CreateMutex failed.\n"); + bResults = FALSE; + } + + if (ReleaseMutex(hMutex) == FALSE) + { + Trace("Error: ReleaseMutex failed.\n"); + bResults = FALSE; + } + if (CloseHandle(hMutex) == FALSE) + { + Trace("Error: CloseHandle failed.\n"); + bResults = FALSE; + } + + bRet = ReleaseMutex(hMutex); + + if (bRet != FALSE) + { + Trace("Error: ReleaseMutex accepted invalid handle.\n"); + bResults = FALSE; + } + + return bResults; +} diff --git a/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CMakeLists.txt index a73ee04..aa1f783 100644 --- a/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateMutexW.c + CreateMutexW.cpp ) add_executable(paltest_createmutexw_releasemutex_test1 diff --git a/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CreateMutexW.c b/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CreateMutexW.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CreateMutexW.c rename to src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test1/CreateMutexW.cpp diff --git a/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/CMakeLists.txt index b40569b..5a9095c 100644 --- a/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateMutexW.c + CreateMutexW.cpp ) add_executable(paltest_createmutexw_releasemutex_test2 diff --git a/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/CreateMutexW.c b/src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/CreateMutexW.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/CreateMutexW.c rename to src/pal/tests/palsuite/threading/CreateMutexW_ReleaseMutex/test2/CreateMutexW.cpp diff --git a/src/pal/tests/palsuite/threading/CreateProcessA/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateProcessA/test1/CMakeLists.txt index 67e53ed..9cd0aa5 100644 --- a/src/pal/tests/palsuite/threading/CreateProcessA/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateProcessA/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - parentProcess.c + parentProcess.cpp ) add_executable(paltest_createprocessa_test1 @@ -20,7 +20,7 @@ target_link_libraries(paltest_createprocessa_test1 set(HELPERSOURCES - childProcess.c + childProcess.cpp ) add_executable(paltest_createprocessa_test1_child diff --git a/src/pal/tests/palsuite/threading/CreateProcessA/test1/childProcess.c b/src/pal/tests/palsuite/threading/CreateProcessA/test1/childProcess.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateProcessA/test1/childProcess.c rename to src/pal/tests/palsuite/threading/CreateProcessA/test1/childProcess.cpp diff --git a/src/pal/tests/palsuite/threading/CreateProcessA/test1/parentProcess.c b/src/pal/tests/palsuite/threading/CreateProcessA/test1/parentProcess.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateProcessA/test1/parentProcess.c rename to src/pal/tests/palsuite/threading/CreateProcessA/test1/parentProcess.cpp diff --git a/src/pal/tests/palsuite/threading/CreateProcessA/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateProcessA/test2/CMakeLists.txt index b81ea2e..f035f0a 100644 --- a/src/pal/tests/palsuite/threading/CreateProcessA/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateProcessA/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - parentprocess.c + parentprocess.cpp ) add_executable(paltest_createprocessa_test2 @@ -20,7 +20,7 @@ target_link_libraries(paltest_createprocessa_test2 set(HELPERSOURCES - childprocess.c + childprocess.cpp ) add_executable(paltest_createprocessa_test2_child diff --git a/src/pal/tests/palsuite/threading/CreateProcessA/test2/childprocess.c b/src/pal/tests/palsuite/threading/CreateProcessA/test2/childprocess.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateProcessA/test2/childprocess.c rename to src/pal/tests/palsuite/threading/CreateProcessA/test2/childprocess.cpp diff --git a/src/pal/tests/palsuite/threading/CreateProcessA/test2/parentprocess.c b/src/pal/tests/palsuite/threading/CreateProcessA/test2/parentprocess.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateProcessA/test2/parentprocess.c rename to src/pal/tests/palsuite/threading/CreateProcessA/test2/parentprocess.cpp diff --git a/src/pal/tests/palsuite/threading/CreateProcessW/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateProcessW/test1/CMakeLists.txt index 394b124..174d6fe 100644 --- a/src/pal/tests/palsuite/threading/CreateProcessW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateProcessW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - parentProcess.c + parentProcess.cpp ) add_executable(paltest_createprocessw_test1 @@ -20,7 +20,7 @@ target_link_libraries(paltest_createprocessw_test1 set(HELPERSOURCES - childProcess.c + childProcess.cpp ) add_executable(paltest_createprocessw_test1_child diff --git a/src/pal/tests/palsuite/threading/CreateProcessW/test1/childProcess.c b/src/pal/tests/palsuite/threading/CreateProcessW/test1/childProcess.c deleted file mode 100644 index c71f967..0000000 --- a/src/pal/tests/palsuite/threading/CreateProcessW/test1/childProcess.c +++ /dev/null @@ -1,150 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: CreateProcessW/test1/childprocess.c -** -** Purpose: Test to ensure CreateProcessW starts a new process. This test -** launches a child process, and examines a file written by the child. -** This code is the child code. -** -** Dependencies: GetCurrentDirectory -** MultiByteToWideChar -** wcslen -** strlen -** WideCharToMultiByte -** fopen -** fclose -** fprintf -** - -** -**=========================================================*/ - -#define UNICODE -#include - -const WCHAR szCommonFileW[] = - {'c','h','i','l','d','d','a','t','a','.','t','m','p','\0'}; - -const WCHAR szPathDelimW[] = {'\\','\0'}; - -const char *szCommonStringA = "058d2d057111a313aa82401c2e856002\0"; - -/* - * Take two wide strings representing file and directory names - * (dirName, fileName), join the strings with the appropriate path - * delimiter and populate a wide character buffer (absPathName) with - * the resulting string. - * - * Returns: The number of wide characters in the resulting string. - * 0 is returned on Error. - */ -int -mkAbsoluteFilenameW ( - LPWSTR dirName, - DWORD dwDirLength, - LPCWSTR fileName, - DWORD dwFileLength, - LPWSTR absPathName ) -{ - extern const WCHAR szPathDelimW[]; - - DWORD sizeDN, sizeFN, sizeAPN; - - sizeDN = wcslen( dirName ); - sizeFN = wcslen( fileName ); - sizeAPN = (sizeDN + 1 + sizeFN + 1); - - /* insure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */ - if ( sizeAPN > _MAX_PATH ) - { - return ( 0 ); - } - - wcsncpy(absPathName, dirName, dwDirLength +1); - wcsncpy(absPathName, szPathDelimW, 2); - wcsncpy(absPathName, fileName, dwFileLength +1); - - return (sizeAPN); - -} - -int __cdecl main( int argc, char **argv ) -{ - - static FILE * fp; - - DWORD dwFileLength; - DWORD dwDirLength; - DWORD dwSize; - - char *szAbsPathNameA; - WCHAR szDirNameW[_MAX_DIR]; - WCHAR szAbsPathNameW[_MAX_PATH]; - - if(0 != (PAL_Initialize(argc, argv))) - { - return ( FAIL ); - } - - dwDirLength = GetCurrentDirectory( _MAX_PATH, szDirNameW ); - - if (0 == dwDirLength) - { - Fail ("GetCurrentDirectory call failed. Could not get " - "current working directory\n. Exiting.\n"); - } - - dwFileLength = wcslen( szCommonFileW ); - - dwSize = mkAbsoluteFilenameW( szDirNameW, dwDirLength, szCommonFileW, - dwFileLength, szAbsPathNameW ); - - if (0 == dwSize) - { - Fail ("Palsuite Code: mkAbsoluteFilename() call failed. Could " - "not build absolute path name to file\n. Exiting.\n"); - } - - /* set the string length for the open call */ - szAbsPathNameA = malloc (dwSize +1); - - if (NULL == szAbsPathNameA) - { - Fail ("Unable to malloc (%d) bytes. Exiting\n", (dwSize +1) ); - } - - WideCharToMultiByte (CP_ACP, 0, szAbsPathNameW, -1, szAbsPathNameA, - (dwSize + 1), NULL, NULL); - - if ( NULL == ( fp = fopen ( szAbsPathNameA , "w+" ) ) ) - { - /* - * A return value of NULL indicates an error condition or an - * EOF condition - */ - Fail ("%s unable to open %s for writing. Exiting.\n", argv[0] - , szAbsPathNameA ); - } - - free (szAbsPathNameA); - - if ( 0 >= ( fprintf ( fp, "%s", szCommonStringA ))) - { - Fail("%s unable to write to %s. Exiting.\n", argv[0] - , szAbsPathNameA ); - } - - if (0 != (fclose ( fp ))) - { - Fail ("%s unable to close file %s. Pid may not be " - "written to file. Exiting.\n", argv[0], szAbsPathNameA ); - } - - PAL_Terminate(); - return ( PASS ); - -} diff --git a/src/pal/tests/palsuite/threading/CreateProcessW/test1/childProcess.cpp b/src/pal/tests/palsuite/threading/CreateProcessW/test1/childProcess.cpp new file mode 100644 index 0000000..a7730c6 --- /dev/null +++ b/src/pal/tests/palsuite/threading/CreateProcessW/test1/childProcess.cpp @@ -0,0 +1,150 @@ +// 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. + +/*============================================================ +** +** Source: CreateProcessW/test1/childprocess.c +** +** Purpose: Test to ensure CreateProcessW starts a new process. This test +** launches a child process, and examines a file written by the child. +** This code is the child code. +** +** Dependencies: GetCurrentDirectory +** MultiByteToWideChar +** wcslen +** strlen +** WideCharToMultiByte +** fopen +** fclose +** fprintf +** + +** +**=========================================================*/ + +#define UNICODE +#include + +const WCHAR szCommonFileW[] = + {'c','h','i','l','d','d','a','t','a','.','t','m','p','\0'}; + +const WCHAR szPathDelimW[] = {'\\','\0'}; + +const char *szCommonStringA = "058d2d057111a313aa82401c2e856002\0"; + +/* + * Take two wide strings representing file and directory names + * (dirName, fileName), join the strings with the appropriate path + * delimiter and populate a wide character buffer (absPathName) with + * the resulting string. + * + * Returns: The number of wide characters in the resulting string. + * 0 is returned on Error. + */ +int +mkAbsoluteFilenameW ( + LPWSTR dirName, + DWORD dwDirLength, + LPCWSTR fileName, + DWORD dwFileLength, + LPWSTR absPathName ) +{ + extern const WCHAR szPathDelimW[]; + + DWORD sizeDN, sizeFN, sizeAPN; + + sizeDN = wcslen( dirName ); + sizeFN = wcslen( fileName ); + sizeAPN = (sizeDN + 1 + sizeFN + 1); + + /* insure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */ + if ( sizeAPN > _MAX_PATH ) + { + return ( 0 ); + } + + wcsncpy(absPathName, dirName, dwDirLength +1); + wcsncpy(absPathName, szPathDelimW, 2); + wcsncpy(absPathName, fileName, dwFileLength +1); + + return (sizeAPN); + +} + +int __cdecl main( int argc, char **argv ) +{ + + static FILE * fp; + + DWORD dwFileLength; + DWORD dwDirLength; + DWORD dwSize; + + char *szAbsPathNameA; + WCHAR szDirNameW[_MAX_DIR]; + WCHAR szAbsPathNameW[_MAX_PATH]; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + dwDirLength = GetCurrentDirectory( _MAX_PATH, szDirNameW ); + + if (0 == dwDirLength) + { + Fail ("GetCurrentDirectory call failed. Could not get " + "current working directory\n. Exiting.\n"); + } + + dwFileLength = wcslen( szCommonFileW ); + + dwSize = mkAbsoluteFilenameW( szDirNameW, dwDirLength, szCommonFileW, + dwFileLength, szAbsPathNameW ); + + if (0 == dwSize) + { + Fail ("Palsuite Code: mkAbsoluteFilename() call failed. Could " + "not build absolute path name to file\n. Exiting.\n"); + } + + /* set the string length for the open call */ + szAbsPathNameA = (char*)malloc(dwSize +1); + + if (NULL == szAbsPathNameA) + { + Fail ("Unable to malloc (%d) bytes. Exiting\n", (dwSize +1) ); + } + + WideCharToMultiByte (CP_ACP, 0, szAbsPathNameW, -1, szAbsPathNameA, + (dwSize + 1), NULL, NULL); + + if ( NULL == ( fp = fopen ( szAbsPathNameA , "w+" ) ) ) + { + /* + * A return value of NULL indicates an error condition or an + * EOF condition + */ + Fail ("%s unable to open %s for writing. Exiting.\n", argv[0] + , szAbsPathNameA ); + } + + free (szAbsPathNameA); + + if ( 0 >= ( fprintf ( fp, "%s", szCommonStringA ))) + { + Fail("%s unable to write to %s. Exiting.\n", argv[0] + , szAbsPathNameA ); + } + + if (0 != (fclose ( fp ))) + { + Fail ("%s unable to close file %s. Pid may not be " + "written to file. Exiting.\n", argv[0], szAbsPathNameA ); + } + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/src/pal/tests/palsuite/threading/CreateProcessW/test1/parentProcess.c b/src/pal/tests/palsuite/threading/CreateProcessW/test1/parentProcess.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateProcessW/test1/parentProcess.c rename to src/pal/tests/palsuite/threading/CreateProcessW/test1/parentProcess.cpp diff --git a/src/pal/tests/palsuite/threading/CreateProcessW/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateProcessW/test2/CMakeLists.txt index 3feef21..021a0d2 100644 --- a/src/pal/tests/palsuite/threading/CreateProcessW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateProcessW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - parentprocess.c + parentprocess.cpp ) add_executable(paltest_createprocessw_test2 @@ -20,7 +20,7 @@ target_link_libraries(paltest_createprocessw_test2 set(HELPERSOURCES - childprocess.c + childprocess.cpp ) add_executable(paltest_createprocessw_test2_child diff --git a/src/pal/tests/palsuite/threading/CreateProcessW/test2/childprocess.c b/src/pal/tests/palsuite/threading/CreateProcessW/test2/childprocess.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateProcessW/test2/childprocess.c rename to src/pal/tests/palsuite/threading/CreateProcessW/test2/childprocess.cpp diff --git a/src/pal/tests/palsuite/threading/CreateProcessW/test2/parentprocess.c b/src/pal/tests/palsuite/threading/CreateProcessW/test2/parentprocess.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateProcessW/test2/parentprocess.c rename to src/pal/tests/palsuite/threading/CreateProcessW/test2/parentprocess.cpp diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CMakeLists.txt index f89e150..8a9255c 100644 --- a/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateSemaphore.c + CreateSemaphore.cpp ) add_executable(paltest_createsemaphorea_releasesemaphore_test1 diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CreateSemaphore.c b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CreateSemaphore.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CreateSemaphore.c rename to src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test1/CreateSemaphore.cpp diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CMakeLists.txt index f3e0174..6d1249b 100644 --- a/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateSemaphore.c + CreateSemaphore.cpp ) add_executable(paltest_createsemaphorea_releasesemaphore_test2 diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CreateSemaphore.c b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CreateSemaphore.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CreateSemaphore.c rename to src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test2/CreateSemaphore.cpp diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/CMakeLists.txt index 0c604d6..94998f5 100644 --- a/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - createsemaphore.c + createsemaphore.cpp ) add_executable(paltest_createsemaphorea_releasesemaphore_test3 diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/createsemaphore.c b/src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/createsemaphore.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/createsemaphore.c rename to src/pal/tests/palsuite/threading/CreateSemaphoreA_ReleaseSemaphore/test3/createsemaphore.cpp diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CMakeLists.txt index b40f269..32902cf 100644 --- a/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateSemaphore.c + CreateSemaphore.cpp ) add_executable(paltest_createsemaphorew_releasesemaphore_test1 diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CreateSemaphore.c b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CreateSemaphore.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CreateSemaphore.c rename to src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test1/CreateSemaphore.cpp diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CMakeLists.txt index b14284d..bd0a5a6 100644 --- a/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - CreateSemaphore.c + CreateSemaphore.cpp ) add_executable(paltest_createsemaphorew_releasesemaphore_test2 diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CreateSemaphore.c b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CreateSemaphore.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CreateSemaphore.c rename to src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test2/CreateSemaphore.cpp diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/CMakeLists.txt index f7f0905..d0340c6 100644 --- a/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - createsemaphore.c + createsemaphore.cpp ) add_executable(paltest_createsemaphorew_releasesemaphore_test3 diff --git a/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/createsemaphore.c b/src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/createsemaphore.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/createsemaphore.c rename to src/pal/tests/palsuite/threading/CreateSemaphoreW_ReleaseSemaphore/test3/createsemaphore.cpp diff --git a/src/pal/tests/palsuite/threading/CreateThread/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateThread/test1/CMakeLists.txt index d3921c4..b47afe4 100644 --- a/src/pal/tests/palsuite/threading/CreateThread/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateThread/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_createthread_test1 diff --git a/src/pal/tests/palsuite/threading/CreateThread/test1/test1.c b/src/pal/tests/palsuite/threading/CreateThread/test1/test1.c deleted file mode 100644 index 2dd2f6a..0000000 --- a/src/pal/tests/palsuite/threading/CreateThread/test1/test1.c +++ /dev/null @@ -1,119 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test1.c -** -** Purpose: Test for CreateThread. Call CreateThread and ensure -** that it succeeds. Also check to ensure the paramater is passed -** properly. -** -** -**=========================================================*/ - -#include - -#ifndef PLATFORM_UNIX -#define LLFORMAT "%I64u" -#else -#define LLFORMAT "%llu" -#endif - -ULONGLONG dwCreateThreadTestParameter = 0; - -DWORD PALAPI CreateThreadTestThread( LPVOID lpParameter) -{ - DWORD dwRet = 0; - - /* save parameter for test */ - dwCreateThreadTestParameter = (ULONGLONG)lpParameter; - - return dwRet; -} - -BOOL CreateThreadTest() -{ - BOOL bRet = FALSE; - DWORD dwRet = 0; - - LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL; - DWORD dwStackSize = 0; - LPTHREAD_START_ROUTINE lpStartAddress = &CreateThreadTestThread; - LPVOID lpParameter = lpStartAddress; - DWORD dwCreationFlags = 0; /* run immediately */ - DWORD dwThreadId = 0; - - HANDLE hThread = 0; - - dwCreateThreadTestParameter = 0; - - /* Create a thread, passing the appropriate paramaters as declared - above. - */ - - hThread = CreateThread( lpThreadAttributes, - dwStackSize, - lpStartAddress, - lpParameter, - dwCreationFlags, - &dwThreadId ); - - /* Ensure that the HANDLE is not invalid! */ - if (hThread != INVALID_HANDLE_VALUE) - { - dwRet = WaitForSingleObject(hThread,INFINITE); - - if (dwRet != WAIT_OBJECT_0) - { - Trace("CreateThreadTest:WaitForSingleObject " - "failed (%x)\n",GetLastError()); - } - else - { - /* Check to ensure that the parameter passed to the thread - function is the same in the function as what we passed. - */ - - if (dwCreateThreadTestParameter != (ULONGLONG)lpParameter) - { - Trace("CreateThreadTest:parameter error. The " - "parameter passed should have been " LLFORMAT " but when " - "passed to the Thread function it was " LLFORMAT " . GetLastError[%x]\n", - dwCreateThreadTestParameter,lpParameter, GetLastError()); - } - else - { - bRet = TRUE; - } - - } - CloseHandle(hThread); - } - else - { - Trace("CreateThreadTest:CreateThread failed (%x)\n",GetLastError()); - } - - return bRet; -} - - -int __cdecl main(int argc, char **argv) -{ - if(0 != (PAL_Initialize(argc, argv))) - { - return ( FAIL ); - } - - if(!CreateThreadTest()) - { - Fail ("Test failed\n"); - } - - Trace("Test Passed\n"); - PAL_Terminate(); - return ( PASS ); - -} diff --git a/src/pal/tests/palsuite/threading/CreateThread/test1/test1.cpp b/src/pal/tests/palsuite/threading/CreateThread/test1/test1.cpp new file mode 100644 index 0000000..dda25f1 --- /dev/null +++ b/src/pal/tests/palsuite/threading/CreateThread/test1/test1.cpp @@ -0,0 +1,119 @@ +// 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. + +/*============================================================ +** +** Source: test1.c +** +** Purpose: Test for CreateThread. Call CreateThread and ensure +** that it succeeds. Also check to ensure the paramater is passed +** properly. +** +** +**=========================================================*/ + +#include + +#ifndef PLATFORM_UNIX +#define LLFORMAT "%I64u" +#else +#define LLFORMAT "%llu" +#endif + +ULONGLONG dwCreateThreadTestParameter = 0; + +DWORD PALAPI CreateThreadTestThread( LPVOID lpParameter) +{ + DWORD dwRet = 0; + + /* save parameter for test */ + dwCreateThreadTestParameter = (ULONGLONG)lpParameter; + + return dwRet; +} + +BOOL CreateThreadTest() +{ + BOOL bRet = FALSE; + DWORD dwRet = 0; + + LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL; + DWORD dwStackSize = 0; + LPTHREAD_START_ROUTINE lpStartAddress = &CreateThreadTestThread; + LPVOID lpParameter = (LPVOID)lpStartAddress; + DWORD dwCreationFlags = 0; /* run immediately */ + DWORD dwThreadId = 0; + + HANDLE hThread = 0; + + dwCreateThreadTestParameter = 0; + + /* Create a thread, passing the appropriate paramaters as declared + above. + */ + + hThread = CreateThread( lpThreadAttributes, + dwStackSize, + lpStartAddress, + lpParameter, + dwCreationFlags, + &dwThreadId ); + + /* Ensure that the HANDLE is not invalid! */ + if (hThread != INVALID_HANDLE_VALUE) + { + dwRet = WaitForSingleObject(hThread,INFINITE); + + if (dwRet != WAIT_OBJECT_0) + { + Trace("CreateThreadTest:WaitForSingleObject " + "failed (%x)\n",GetLastError()); + } + else + { + /* Check to ensure that the parameter passed to the thread + function is the same in the function as what we passed. + */ + + if (dwCreateThreadTestParameter != (ULONGLONG)lpParameter) + { + Trace("CreateThreadTest:parameter error. The " + "parameter passed should have been " LLFORMAT " but when " + "passed to the Thread function it was " LLFORMAT " . GetLastError[%x]\n", + dwCreateThreadTestParameter,lpParameter, GetLastError()); + } + else + { + bRet = TRUE; + } + + } + CloseHandle(hThread); + } + else + { + Trace("CreateThreadTest:CreateThread failed (%x)\n",GetLastError()); + } + + return bRet; +} + + +int __cdecl main(int argc, char **argv) +{ + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(!CreateThreadTest()) + { + Fail ("Test failed\n"); + } + + Trace("Test Passed\n"); + PAL_Terminate(); + return ( PASS ); + +} diff --git a/src/pal/tests/palsuite/threading/CreateThread/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateThread/test2/CMakeLists.txt index 350cf66..4787760 100644 --- a/src/pal/tests/palsuite/threading/CreateThread/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateThread/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_createthread_test2 diff --git a/src/pal/tests/palsuite/threading/CreateThread/test2/test2.c b/src/pal/tests/palsuite/threading/CreateThread/test2/test2.c deleted file mode 100644 index f64c32e..0000000 --- a/src/pal/tests/palsuite/threading/CreateThread/test2/test2.c +++ /dev/null @@ -1,184 +0,0 @@ -// 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. - -/*=========================================================== -** -** Source: test2.c -** -** Purpose: Test that lpThreadId is assigned the correct -** threadId value and that lpThreadId can be NULL. -** -** -**=========================================================*/ - -#include - -#define NUM_TESTS 3 - -HANDLE hThread[NUM_TESTS]; -DWORD dwThreadId[NUM_TESTS]; -volatile BOOL bResult[NUM_TESTS]; -volatile DWORD dwThreadId1[NUM_TESTS]; - -DWORD PALAPI Thread( LPVOID lpParameter) -{ - dwThreadId1[(DWORD) lpParameter] = GetCurrentThreadId(); - bResult[(DWORD) lpParameter] = TRUE; - return (DWORD) lpParameter; -} - -struct testCase -{ - LPSECURITY_ATTRIBUTES lpThreadAttributes; - DWORD dwStackSize; - LPTHREAD_START_ROUTINE lpStartAddress; - DWORD dwCreationFlags; - LPVOID lpThreadId; -}; - -struct testCase testCases[]= -{ - {NULL, 0, &Thread, 0, NULL}, - {NULL, 0, &Thread, CREATE_SUSPENDED, NULL}, - {NULL, 0, &Thread, 0, (LPVOID) 1} -}; - -/* - * close handles - */ -BOOL cleanup(int index) -{ - int i; - BOOL bRet = TRUE; - - for (i = 0; i < index; i++) - { - if (!CloseHandle(hThread[i])) - { - bRet = FALSE; - Trace("PALSUITE ERROR: CloseHandle(%p) call failed for index %d\n", - hThread[i], i); - } - } - - return(bRet); -} - -int __cdecl main(int argc, char **argv) -{ - SIZE_T i; - DWORD dwRetWFSO; - DWORD dwRetRT; - BOOL bRet = TRUE; - - if(0 != (PAL_Initialize(argc, argv))) - { - return (FAIL); - } - - /* set results array to FALSE */ - for (i = 0; i < NUM_TESTS; i++) - { - bResult[i]=FALSE; - dwThreadId[i]=0; - } - - for (i = 0; i < NUM_TESTS; i++) - { - if (NULL != testCases[i].lpThreadId) - { - testCases[i].lpThreadId = &dwThreadId[i]; - } - /* pass the index as the thread argument */ - hThread[i] = CreateThread( testCases[i].lpThreadAttributes, - testCases[i].dwStackSize, - testCases[i].lpStartAddress, - (LPVOID) i, - testCases[i].dwCreationFlags, - testCases[i].lpThreadId); - if (hThread[i] == NULL) - { - Trace("PALSUITE ERROR: CreateThread('%p' '%d' '%p' '%p' '%d' " - "'%p') call failed.\nGetLastError returned '%u'.\n", - testCases[i].lpThreadAttributes, testCases[i].dwStackSize, - testCases[i].lpStartAddress, (LPVOID) i, - testCases[i].dwCreationFlags, - testCases[i].lpThreadId, GetLastError()); - cleanup(i - 1); - Fail(""); - } - - /* Resume suspended threads */ - if (testCases[i].dwCreationFlags == CREATE_SUSPENDED) - { - dwRetRT = ResumeThread (hThread[i]); - if (dwRetRT != 1) - { - Trace ("PALSUITE ERROR: ResumeThread(%p) " - "call returned %d it should have returned %d.\n" - "GetLastError returned %u.\n", hThread[i], dwRetRT, - 1, GetLastError()); - cleanup(i); - Fail(""); - } - } - } - - /* cleanup */ - for (i = 0; i < NUM_TESTS; i++) - { - dwRetWFSO = WaitForSingleObject(hThread[i], 10000); - if (dwRetWFSO != WAIT_OBJECT_0) - { - Trace ("PALSUITE ERROR: WaitForSingleObject('%p' '%d') " - "call returned %d instead of WAIT_OBJECT_0 ('%d').\n" - "GetLastError returned %u.\n", hThread[i], 10000, - dwRetWFSO, WAIT_OBJECT_0, GetLastError()); - cleanup(i); - Fail(""); - } - } - if(!cleanup(NUM_TESTS)) - { - Fail(""); - } - - for (i = 0; i < NUM_TESTS; i++) - { - /* - * check to see that all threads were created and were passed - * the array index as an argument. - */ - if (FALSE == bResult[i]) - { - bRet = FALSE; - Trace("PALSUITE ERROR: result[%d]=%d. It should be %d\n", i, - FALSE, TRUE); - } - /* - * check to see that lpThreadId received the correct value. - */ - if (0 != dwThreadId[i]) - { - if (dwThreadId[i] != dwThreadId1[i]) - { - bRet = FALSE; - Trace("PALSUITE ERROR: dwThreadId[%d]=%p and dwThreadId1[%d]" - "=%p\nThese values should be identical.\n", i, - dwThreadId[i], i, dwThreadId1[i]); - } - } - } - if (!bRet) - { - cleanup(NUM_TESTS); - Fail(""); - } - - PAL_Terminate(); - return (PASS); -} - - - diff --git a/src/pal/tests/palsuite/threading/CreateThread/test2/test2.cpp b/src/pal/tests/palsuite/threading/CreateThread/test2/test2.cpp new file mode 100644 index 0000000..1ee410a --- /dev/null +++ b/src/pal/tests/palsuite/threading/CreateThread/test2/test2.cpp @@ -0,0 +1,184 @@ +// 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. + +/*=========================================================== +** +** Source: test2.c +** +** Purpose: Test that lpThreadId is assigned the correct +** threadId value and that lpThreadId can be NULL. +** +** +**=========================================================*/ + +#include + +#define NUM_TESTS 3 + +HANDLE hThread[NUM_TESTS]; +DWORD dwThreadId[NUM_TESTS]; +volatile BOOL bResult[NUM_TESTS]; +volatile DWORD dwThreadId1[NUM_TESTS]; + +DWORD PALAPI Thread( LPVOID lpParameter) +{ + dwThreadId1[(DWORD) lpParameter] = GetCurrentThreadId(); + bResult[(DWORD) lpParameter] = TRUE; + return (DWORD) lpParameter; +} + +struct testCase +{ + LPSECURITY_ATTRIBUTES lpThreadAttributes; + DWORD dwStackSize; + LPTHREAD_START_ROUTINE lpStartAddress; + DWORD dwCreationFlags; + LPDWORD lpThreadId; +}; + +struct testCase testCases[]= +{ + {NULL, 0, &Thread, 0, NULL}, + {NULL, 0, &Thread, CREATE_SUSPENDED, NULL}, + {NULL, 0, &Thread, 0, (LPDWORD) 1} +}; + +/* + * close handles + */ +BOOL cleanup(int index) +{ + int i; + BOOL bRet = TRUE; + + for (i = 0; i < index; i++) + { + if (!CloseHandle(hThread[i])) + { + bRet = FALSE; + Trace("PALSUITE ERROR: CloseHandle(%p) call failed for index %d\n", + hThread[i], i); + } + } + + return(bRet); +} + +int __cdecl main(int argc, char **argv) +{ + SIZE_T i; + DWORD dwRetWFSO; + DWORD dwRetRT; + BOOL bRet = TRUE; + + if(0 != (PAL_Initialize(argc, argv))) + { + return (FAIL); + } + + /* set results array to FALSE */ + for (i = 0; i < NUM_TESTS; i++) + { + bResult[i]=FALSE; + dwThreadId[i]=0; + } + + for (i = 0; i < NUM_TESTS; i++) + { + if (NULL != testCases[i].lpThreadId) + { + testCases[i].lpThreadId = &dwThreadId[i]; + } + /* pass the index as the thread argument */ + hThread[i] = CreateThread( testCases[i].lpThreadAttributes, + testCases[i].dwStackSize, + testCases[i].lpStartAddress, + (LPVOID)i, + testCases[i].dwCreationFlags, + testCases[i].lpThreadId); + if (hThread[i] == NULL) + { + Trace("PALSUITE ERROR: CreateThread('%p' '%d' '%p' '%p' '%d' " + "'%p') call failed.\nGetLastError returned '%u'.\n", + testCases[i].lpThreadAttributes, testCases[i].dwStackSize, + testCases[i].lpStartAddress, (LPVOID)i, + testCases[i].dwCreationFlags, + testCases[i].lpThreadId, GetLastError()); + cleanup(i - 1); + Fail(""); + } + + /* Resume suspended threads */ + if (testCases[i].dwCreationFlags == CREATE_SUSPENDED) + { + dwRetRT = ResumeThread (hThread[i]); + if (dwRetRT != 1) + { + Trace ("PALSUITE ERROR: ResumeThread(%p) " + "call returned %d it should have returned %d.\n" + "GetLastError returned %u.\n", hThread[i], dwRetRT, + 1, GetLastError()); + cleanup(i); + Fail(""); + } + } + } + + /* cleanup */ + for (i = 0; i < NUM_TESTS; i++) + { + dwRetWFSO = WaitForSingleObject(hThread[i], 10000); + if (dwRetWFSO != WAIT_OBJECT_0) + { + Trace ("PALSUITE ERROR: WaitForSingleObject('%p' '%d') " + "call returned %d instead of WAIT_OBJECT_0 ('%d').\n" + "GetLastError returned %u.\n", hThread[i], 10000, + dwRetWFSO, WAIT_OBJECT_0, GetLastError()); + cleanup(i); + Fail(""); + } + } + if(!cleanup(NUM_TESTS)) + { + Fail(""); + } + + for (i = 0; i < NUM_TESTS; i++) + { + /* + * check to see that all threads were created and were passed + * the array index as an argument. + */ + if (FALSE == bResult[i]) + { + bRet = FALSE; + Trace("PALSUITE ERROR: result[%d]=%d. It should be %d\n", i, + FALSE, TRUE); + } + /* + * check to see that lpThreadId received the correct value. + */ + if (0 != dwThreadId[i]) + { + if (dwThreadId[i] != dwThreadId1[i]) + { + bRet = FALSE; + Trace("PALSUITE ERROR: dwThreadId[%d]=%p and dwThreadId1[%d]" + "=%p\nThese values should be identical.\n", i, + dwThreadId[i], i, dwThreadId1[i]); + } + } + } + if (!bRet) + { + cleanup(NUM_TESTS); + Fail(""); + } + + PAL_Terminate(); + return (PASS); +} + + + diff --git a/src/pal/tests/palsuite/threading/CreateThread/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/CreateThread/test3/CMakeLists.txt index 923d7a7..d454992 100644 --- a/src/pal/tests/palsuite/threading/CreateThread/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CreateThread/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_createthread_test3 diff --git a/src/pal/tests/palsuite/threading/CreateThread/test3/test3.c b/src/pal/tests/palsuite/threading/CreateThread/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CreateThread/test3/test3.c rename to src/pal/tests/palsuite/threading/CreateThread/test3/test3.cpp diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/CMakeLists.txt index 5ba04fd..8d2c144 100644 --- a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - InitializeCriticalSection.c + InitializeCriticalSection.cpp ) add_executable(paltest_criticalsectionfunctions_test1 diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/InitializeCriticalSection.c b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/InitializeCriticalSection.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/InitializeCriticalSection.c rename to src/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/InitializeCriticalSection.cpp diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/CMakeLists.txt index d26658c..e0f59f4 100644 --- a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_criticalsectionfunctions_test2 diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/test2.c b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/test2.c rename to src/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/test2.cpp diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/CMakeLists.txt index 8bd2a72..11555ec 100644 --- a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_criticalsectionfunctions_test3 diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/test3.c b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/test3.c rename to src/pal/tests/palsuite/threading/CriticalSectionFunctions/test3/test3.cpp diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/CMakeLists.txt b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/CMakeLists.txt index 0626631..8aa1885 100644 --- a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_criticalsectionfunctions_test4 diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.c b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.c rename to src/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.cpp diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/CMakeLists.txt b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/CMakeLists.txt index 37d709f..9474bcc 100644 --- a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_criticalsectionfunctions_test5 diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/test5.c b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/test5.c rename to src/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/test5.cpp diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/CMakeLists.txt b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/CMakeLists.txt index c580fdb..f4887ad 100644 --- a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test6.c + test6.cpp ) add_executable(paltest_criticalsectionfunctions_test6 diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/test6.c b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/test6.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/test6.c rename to src/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/test6.cpp diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/CMakeLists.txt b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/CMakeLists.txt index 0a12bfe..ceb78a0 100644 --- a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test7.c + test7.cpp ) add_executable(paltest_criticalsectionfunctions_test7 diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/test7.c b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/test7.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/test7.c rename to src/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/test7.cpp diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/CMakeLists.txt b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/CMakeLists.txt index 0d95a95..d3f271d 100644 --- a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test8.c + test8.cpp ) add_executable(paltest_criticalsectionfunctions_test8 diff --git a/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.c b/src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.c rename to src/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.cpp diff --git a/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/test1.c b/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/test1.c rename to src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/test1.cpp diff --git a/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/testlib.c b/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/testlib.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/testlib.c rename to src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/testlib.cpp diff --git a/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain1.c b/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain1.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain1.c rename to src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain1.cpp diff --git a/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain2.c b/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain2.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain2.c rename to src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/dllmain2.cpp diff --git a/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/test2.c b/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/test2.c rename to src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test2/test2.cpp diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/CMakeLists.txt index b908c12..9d5fc53 100644 --- a/src/pal/tests/palsuite/threading/DuplicateHandle/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/DuplicateHandle/CMakeLists.txt @@ -11,5 +11,4 @@ add_subdirectory(test5) add_subdirectory(test6) add_subdirectory(test7) add_subdirectory(test8) -add_subdirectory(test9) diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test1/CMakeLists.txt index 04588b7..18b1927 100644 --- a/src/pal/tests/palsuite/threading/DuplicateHandle/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_duplicatehandle_test1 diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test1/test1.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/DuplicateHandle/test1/test1.c rename to src/pal/tests/palsuite/threading/DuplicateHandle/test1/test1.cpp diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test10/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test10/CMakeLists.txt index ba16252..98c7a27 100644 --- a/src/pal/tests/palsuite/threading/DuplicateHandle/test10/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test10/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test10.c + test10.cpp ) add_executable(paltest_duplicatehandle_test10 diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test10/test10.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test10/test10.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/DuplicateHandle/test10/test10.c rename to src/pal/tests/palsuite/threading/DuplicateHandle/test10/test10.cpp diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test11/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test11/CMakeLists.txt index 68ce7b2..f47f9bc 100644 --- a/src/pal/tests/palsuite/threading/DuplicateHandle/test11/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test11/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - test11.c + test11.cpp ) add_executable(paltest_duplicatehandle_test11 @@ -20,7 +20,7 @@ target_link_libraries(paltest_duplicatehandle_test11 set(HELPERSOURCES - childprocess.c + childprocess.cpp ) add_executable(paltest_duplicatehandle_test11_child diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test11/childprocess.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test11/childprocess.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/DuplicateHandle/test11/childprocess.c rename to src/pal/tests/palsuite/threading/DuplicateHandle/test11/childprocess.cpp diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test11/test11.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test11/test11.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/DuplicateHandle/test11/test11.c rename to src/pal/tests/palsuite/threading/DuplicateHandle/test11/test11.cpp diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test12/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test12/CMakeLists.txt index 961a9c6..6a50a13 100644 --- a/src/pal/tests/palsuite/threading/DuplicateHandle/test12/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test12/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test12.c + test12.cpp ) add_executable(paltest_duplicatehandle_test12 diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test12/test12.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test12/test12.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/DuplicateHandle/test12/test12.c rename to src/pal/tests/palsuite/threading/DuplicateHandle/test12/test12.cpp diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test2/CMakeLists.txt index 06529a6..9faa58a 100644 --- a/src/pal/tests/palsuite/threading/DuplicateHandle/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_duplicatehandle_test2 diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test2/test2.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/DuplicateHandle/test2/test2.c rename to src/pal/tests/palsuite/threading/DuplicateHandle/test2/test2.cpp diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test3/CMakeLists.txt index 7f961c2..b161b92 100644 --- a/src/pal/tests/palsuite/threading/DuplicateHandle/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_duplicatehandle_test3 diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test3/test3.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/DuplicateHandle/test3/test3.c rename to src/pal/tests/palsuite/threading/DuplicateHandle/test3/test3.cpp diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test4/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test4/CMakeLists.txt index c3040d0..901151f 100644 --- a/src/pal/tests/palsuite/threading/DuplicateHandle/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_duplicatehandle_test4 diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test4/test4.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/DuplicateHandle/test4/test4.c rename to src/pal/tests/palsuite/threading/DuplicateHandle/test4/test4.cpp diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test5/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test5/CMakeLists.txt index bc468a4..94cd07f 100644 --- a/src/pal/tests/palsuite/threading/DuplicateHandle/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_duplicatehandle_test5 diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test5/test5.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/DuplicateHandle/test5/test5.c rename to src/pal/tests/palsuite/threading/DuplicateHandle/test5/test5.cpp diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test6/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test6/CMakeLists.txt index 20f7822..a0dcae8 100644 --- a/src/pal/tests/palsuite/threading/DuplicateHandle/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test6.c + test6.cpp ) add_executable(paltest_duplicatehandle_test6 diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test6/test6.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test6/test6.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/DuplicateHandle/test6/test6.c rename to src/pal/tests/palsuite/threading/DuplicateHandle/test6/test6.cpp diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test7/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test7/CMakeLists.txt index df3fdf9..a222331 100644 --- a/src/pal/tests/palsuite/threading/DuplicateHandle/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test7.c + test7.cpp ) add_executable(paltest_duplicatehandle_test7 diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test7/test7.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test7/test7.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/DuplicateHandle/test7/test7.c rename to src/pal/tests/palsuite/threading/DuplicateHandle/test7/test7.cpp diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test8/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test8/CMakeLists.txt index 15ec23d..18ed969 100644 --- a/src/pal/tests/palsuite/threading/DuplicateHandle/test8/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test8/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test8.c + test8.cpp ) add_executable(paltest_duplicatehandle_test8 diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test8/test8.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test8/test8.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/DuplicateHandle/test8/test8.c rename to src/pal/tests/palsuite/threading/DuplicateHandle/test8/test8.cpp diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test9/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test9/CMakeLists.txt index e4442e3..0383a01 100644 --- a/src/pal/tests/palsuite/threading/DuplicateHandle/test9/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test9/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test9.c + test9.cpp ) add_executable(paltest_duplicatehandle_test9 diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test9/test9.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test9/test9.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/DuplicateHandle/test9/test9.c rename to src/pal/tests/palsuite/threading/DuplicateHandle/test9/test9.cpp diff --git a/src/pal/tests/palsuite/threading/ExitProcess/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/ExitProcess/test1/CMakeLists.txt index decddb8..f2d28e0 100644 --- a/src/pal/tests/palsuite/threading/ExitProcess/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/ExitProcess/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - ExitProcess.c + ExitProcess.cpp ) add_executable(paltest_exitprocess_test1 diff --git a/src/pal/tests/palsuite/threading/ExitProcess/test1/ExitProcess.c b/src/pal/tests/palsuite/threading/ExitProcess/test1/ExitProcess.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/ExitProcess/test1/ExitProcess.c rename to src/pal/tests/palsuite/threading/ExitProcess/test1/ExitProcess.cpp diff --git a/src/pal/tests/palsuite/threading/ExitProcess/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/ExitProcess/test2/CMakeLists.txt index 881c7d0..5281a02 100644 --- a/src/pal/tests/palsuite/threading/ExitProcess/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/ExitProcess/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_exitprocess_test2 diff --git a/src/pal/tests/palsuite/threading/ExitProcess/test2/test2.c b/src/pal/tests/palsuite/threading/ExitProcess/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/ExitProcess/test2/test2.c rename to src/pal/tests/palsuite/threading/ExitProcess/test2/test2.cpp diff --git a/src/pal/tests/palsuite/threading/ExitProcess/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/ExitProcess/test3/CMakeLists.txt index 638408e..3fca087 100644 --- a/src/pal/tests/palsuite/threading/ExitProcess/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/ExitProcess/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_exitprocess_test3 diff --git a/src/pal/tests/palsuite/threading/ExitProcess/test3/test3.c b/src/pal/tests/palsuite/threading/ExitProcess/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/ExitProcess/test3/test3.c rename to src/pal/tests/palsuite/threading/ExitProcess/test3/test3.cpp diff --git a/src/pal/tests/palsuite/threading/ExitThread/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/ExitThread/test1/CMakeLists.txt index 15e0c1b..c34b525 100644 --- a/src/pal/tests/palsuite/threading/ExitThread/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/ExitThread/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_exitthread_test1 diff --git a/src/pal/tests/palsuite/threading/ExitThread/test1/test1.c b/src/pal/tests/palsuite/threading/ExitThread/test1/test1.c deleted file mode 100644 index 2963745..0000000 --- a/src/pal/tests/palsuite/threading/ExitThread/test1/test1.c +++ /dev/null @@ -1,114 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test1.c -** -** Purpose: Test for ExitThread. Create a thread and then call -** exit thread within the threading function. Ensure that it exits -** immediatly. -** -** -**=========================================================*/ - -#include - -DWORD dwExitThreadTestParameter = 0; - -DWORD PALAPI ExitThreadTestThread( LPVOID lpParameter) -{ - DWORD dwRet = 0; - - /* Save parameter for test */ - dwExitThreadTestParameter = (DWORD)lpParameter; - - /* Call the ExitThread function */ - ExitThread(dwRet); - - /* If we didn't exit, get caught in this loop. But, the - program will exit. - */ - while (!dwRet) - { - Fail("ERROR: Entered an infinite loop because ExitThread " - "failed to exit from the thread. Forcing exit from " - "the test now."); - } - - return dwRet; -} - -BOOL ExitThreadTest() -{ - BOOL bRet = FALSE; - DWORD dwRet = 0; - - LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL; - DWORD dwStackSize = 0; - LPTHREAD_START_ROUTINE lpStartAddress = &ExitThreadTestThread; - LPVOID lpParameter = lpStartAddress; - DWORD dwCreationFlags = 0; //run immediately - DWORD dwThreadId = 0; - - HANDLE hThread = 0; - - dwExitThreadTestParameter = 0; - - /* Create a Thread. We'll need this to test that we're able - to exit the thread. - */ - hThread = CreateThread( lpThreadAttributes, - dwStackSize, lpStartAddress, lpParameter, - dwCreationFlags, &dwThreadId ); - - if (hThread != INVALID_HANDLE_VALUE) - { - dwRet = WaitForSingleObject(hThread,INFINITE); - - if (dwRet != WAIT_OBJECT_0) - { - Trace("ExitThreadTest:WaitForSingleObject failed " - "(%x)\n",GetLastError()); - } - else - { - /* Check to ensure that the parameter set in the Thread - function is correct. - */ - if (dwExitThreadTestParameter != (DWORD)lpParameter) - { - Trace("ERROR: The paramater passed should have been " - "%d but turned up as %d.", - dwExitThreadTestParameter, lpParameter); - } - else - { - bRet = TRUE; - } - } - } - else - { - Trace("ExitThreadTest:CreateThread failed (%x)\n",GetLastError()); - } - - return bRet; -} - -int __cdecl main(int argc, char **argv) -{ - if(0 != (PAL_Initialize(argc, argv))) - { - return ( FAIL ); - } - - if(!ExitThreadTest()) - { - Fail ("Test failed\n"); - } - - PAL_Terminate(); - return ( PASS ); -} diff --git a/src/pal/tests/palsuite/threading/ExitThread/test1/test1.cpp b/src/pal/tests/palsuite/threading/ExitThread/test1/test1.cpp new file mode 100644 index 0000000..caf1409 --- /dev/null +++ b/src/pal/tests/palsuite/threading/ExitThread/test1/test1.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================ +** +** Source: test1.c +** +** Purpose: Test for ExitThread. Create a thread and then call +** exit thread within the threading function. Ensure that it exits +** immediatly. +** +** +**=========================================================*/ + +#include + +DWORD dwExitThreadTestParameter = 0; + +DWORD PALAPI ExitThreadTestThread( LPVOID lpParameter) +{ + DWORD dwRet = 0; + + /* Save parameter for test */ + dwExitThreadTestParameter = (DWORD)lpParameter; + + /* Call the ExitThread function */ + ExitThread(dwRet); + + /* If we didn't exit, get caught in this loop. But, the + program will exit. + */ + while (!dwRet) + { + Fail("ERROR: Entered an infinite loop because ExitThread " + "failed to exit from the thread. Forcing exit from " + "the test now."); + } + + return dwRet; +} + +BOOL ExitThreadTest() +{ + BOOL bRet = FALSE; + DWORD dwRet = 0; + + LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL; + DWORD dwStackSize = 0; + LPTHREAD_START_ROUTINE lpStartAddress = &ExitThreadTestThread; + LPVOID lpParameter = (LPVOID)lpStartAddress; + DWORD dwCreationFlags = 0; //run immediately + DWORD dwThreadId = 0; + + HANDLE hThread = 0; + + dwExitThreadTestParameter = 0; + + /* Create a Thread. We'll need this to test that we're able + to exit the thread. + */ + hThread = CreateThread( lpThreadAttributes, + dwStackSize, lpStartAddress, lpParameter, + dwCreationFlags, &dwThreadId ); + + if (hThread != INVALID_HANDLE_VALUE) + { + dwRet = WaitForSingleObject(hThread,INFINITE); + + if (dwRet != WAIT_OBJECT_0) + { + Trace("ExitThreadTest:WaitForSingleObject failed " + "(%x)\n",GetLastError()); + } + else + { + /* Check to ensure that the parameter set in the Thread + function is correct. + */ + if (dwExitThreadTestParameter != (DWORD)lpParameter) + { + Trace("ERROR: The paramater passed should have been " + "%d but turned up as %d.", + dwExitThreadTestParameter, lpParameter); + } + else + { + bRet = TRUE; + } + } + } + else + { + Trace("ExitThreadTest:CreateThread failed (%x)\n",GetLastError()); + } + + return bRet; +} + +int __cdecl main(int argc, char **argv) +{ + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(!ExitThreadTest()) + { + Fail ("Test failed\n"); + } + + PAL_Terminate(); + return ( PASS ); +} diff --git a/src/pal/tests/palsuite/threading/ExitThread/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/ExitThread/test2/CMakeLists.txt index aa05382..5e16d36 100644 --- a/src/pal/tests/palsuite/threading/ExitThread/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/ExitThread/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - test2.c + test2.cpp ) add_executable(paltest_exitthread_test2 @@ -20,7 +20,7 @@ target_link_libraries(paltest_exitthread_test2 set(HELPERSOURCES - childprocess.c + childprocess.cpp ) add_executable(paltest_exitthread_test2_child diff --git a/src/pal/tests/palsuite/threading/ExitThread/test2/childprocess.c b/src/pal/tests/palsuite/threading/ExitThread/test2/childprocess.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/ExitThread/test2/childprocess.c rename to src/pal/tests/palsuite/threading/ExitThread/test2/childprocess.cpp diff --git a/src/pal/tests/palsuite/threading/ExitThread/test2/test2.c b/src/pal/tests/palsuite/threading/ExitThread/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/ExitThread/test2/test2.c rename to src/pal/tests/palsuite/threading/ExitThread/test2/test2.cpp diff --git a/src/pal/tests/palsuite/threading/ExitThread/test3/dllmain.c b/src/pal/tests/palsuite/threading/ExitThread/test3/dllmain.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/ExitThread/test3/dllmain.c rename to src/pal/tests/palsuite/threading/ExitThread/test3/dllmain.cpp diff --git a/src/pal/tests/palsuite/threading/ExitThread/test3/test3.c b/src/pal/tests/palsuite/threading/ExitThread/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/ExitThread/test3/test3.c rename to src/pal/tests/palsuite/threading/ExitThread/test3/test3.cpp diff --git a/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/CMakeLists.txt index 4410534..af4746b 100644 --- a/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - process.c + process.cpp ) add_executable(paltest_getcurrentprocess_test1 diff --git a/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/process.c b/src/pal/tests/palsuite/threading/GetCurrentProcess/test1/process.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/GetCurrentProcess/test1/process.c rename to src/pal/tests/palsuite/threading/GetCurrentProcess/test1/process.cpp diff --git a/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/CMakeLists.txt index e5c31e6..523320a 100644 --- a/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - processId.c + processId.cpp ) add_executable(paltest_getcurrentprocessid_test1 diff --git a/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/processId.c b/src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/processId.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/processId.c rename to src/pal/tests/palsuite/threading/GetCurrentProcessId/test1/processId.cpp diff --git a/src/pal/tests/palsuite/threading/GetCurrentThread/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetCurrentThread/test1/CMakeLists.txt index 84cbccb..23af2ed 100644 --- a/src/pal/tests/palsuite/threading/GetCurrentThread/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/GetCurrentThread/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - thread.c + thread.cpp ) add_executable(paltest_getcurrentthread_test1 diff --git a/src/pal/tests/palsuite/threading/GetCurrentThread/test1/thread.c b/src/pal/tests/palsuite/threading/GetCurrentThread/test1/thread.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/GetCurrentThread/test1/thread.c rename to src/pal/tests/palsuite/threading/GetCurrentThread/test1/thread.cpp diff --git a/src/pal/tests/palsuite/threading/GetCurrentThread/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetCurrentThread/test2/CMakeLists.txt index 3fc3c3e..9da2d07 100644 --- a/src/pal/tests/palsuite/threading/GetCurrentThread/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/GetCurrentThread/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_getcurrentthread_test2 diff --git a/src/pal/tests/palsuite/threading/GetCurrentThread/test2/test2.c b/src/pal/tests/palsuite/threading/GetCurrentThread/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/GetCurrentThread/test2/test2.c rename to src/pal/tests/palsuite/threading/GetCurrentThread/test2/test2.cpp diff --git a/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/CMakeLists.txt index 490bff8..a0824ab 100644 --- a/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - threadId.c + threadId.cpp ) add_executable(paltest_getcurrentthreadid_test1 diff --git a/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/threadId.c b/src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/threadId.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/threadId.c rename to src/pal/tests/palsuite/threading/GetCurrentThreadId/test1/threadId.cpp diff --git a/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/CMakeLists.txt index adddd97..1ef9db2 100644 --- a/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - test1.c + test1.cpp ) add_executable(paltest_getexitcodeprocess_test1 @@ -20,7 +20,7 @@ target_link_libraries(paltest_getexitcodeprocess_test1 set(HELPERSOURCES - childProcess.c + childProcess.cpp ) add_executable(paltest_getexitcodeprocess_test1_child diff --git a/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/childProcess.c b/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/childProcess.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/childProcess.c rename to src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/childProcess.cpp diff --git a/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/test1.c b/src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/test1.c rename to src/pal/tests/palsuite/threading/GetExitCodeProcess/test1/test1.cpp diff --git a/src/pal/tests/palsuite/threading/GetProcessTimes/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetProcessTimes/test2/CMakeLists.txt index 0ef7260..8e90587 100644 --- a/src/pal/tests/palsuite/threading/GetProcessTimes/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/GetProcessTimes/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_getprocesstimes_test2 diff --git a/src/pal/tests/palsuite/threading/GetProcessTimes/test2/test2.c b/src/pal/tests/palsuite/threading/GetProcessTimes/test2/test2.c deleted file mode 100644 index 687facc..0000000 --- a/src/pal/tests/palsuite/threading/GetProcessTimes/test2/test2.c +++ /dev/null @@ -1,122 +0,0 @@ -// 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. - -/*============================================================================= -** -** Source: test2.c -** -** Purpose: Test to ensure GetProcessTimes works properly. -** -** Dependencies: PAL_Initialize -** PAL_Terminate -** Fail -** ZeroMemory -** CompareFileTime -** GetLastError -** - -** -**===========================================================================*/ -#include - - -int __cdecl main( int argc, char **argv ) - -{ - int i, j, k; - int *total; - - HANDLE hProcess; - FILETIME createTime; - FILETIME exitTime; - FILETIME kernelTime1; - FILETIME userTime1; - FILETIME kernelTime2; - FILETIME userTime2; - - DWORD dwError; - - /* initialize the PAL */ - if( PAL_Initialize(argc, argv) != 0 ) - { - return( FAIL ); - } - - /* get our own process handle */ - hProcess = GetCurrentProcess(); - if( hProcess == NULL ) - { - Fail( "GetCurrentProcess() returned a NULL handle.\n" ); - } - - /* zero our time structures */ - ZeroMemory( &createTime, sizeof(createTime) ); - ZeroMemory( &exitTime, sizeof(exitTime) ); - ZeroMemory( &kernelTime1, sizeof(kernelTime1) ); - ZeroMemory( &userTime1, sizeof(userTime1) ); - ZeroMemory( &kernelTime2, sizeof(kernelTime2) ); - ZeroMemory( &userTime2, sizeof(userTime2) ); - - /* check the process times for the child process */ - if( ! GetProcessTimes( hProcess, - &createTime, - &exitTime, - &kernelTime1, - &userTime1 ) ) - { - dwError = GetLastError(); - Fail( "GetProcessTimes() call failed with error code %d\n", - dwError ); - } - - - /* simulate some activity */ - for( i=0; i<1000; i++ ) - { - for( j=0; j<1000; j++ ) - { - /* do kernel work to increase system usage counters */ - total = malloc(1024 * 1024); - - *total = j * i; - for( k=0; k<1000; k++ ) - { - *total += k + i; - } - - free(total); - } - } - - /* check the process times for the child process */ - if( ! GetProcessTimes( hProcess, - &createTime, - &exitTime, - &kernelTime2, - &userTime2 ) ) - { - dwError = GetLastError(); - Fail( "GetProcessTimes() call failed with error code %d\n", - dwError ); - } - - - /* very simple logical checking of the results */ - if( CompareFileTime( &kernelTime1, &kernelTime2 ) > 0 ) - { - Fail( "Unexpected kernel time value reported.\n" ); - } - - if( CompareFileTime( &userTime1, &userTime2 ) > 0 ) - { - Fail( "Unexpected user time value reported.\n" ); - } - - - /* terminate the PAL */ - PAL_Terminate(); - - /* return success */ - return PASS; -} diff --git a/src/pal/tests/palsuite/threading/GetProcessTimes/test2/test2.cpp b/src/pal/tests/palsuite/threading/GetProcessTimes/test2/test2.cpp new file mode 100644 index 0000000..cc39de6 --- /dev/null +++ b/src/pal/tests/palsuite/threading/GetProcessTimes/test2/test2.cpp @@ -0,0 +1,122 @@ +// 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. + +/*============================================================================= +** +** Source: test2.c +** +** Purpose: Test to ensure GetProcessTimes works properly. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** ZeroMemory +** CompareFileTime +** GetLastError +** + +** +**===========================================================================*/ +#include + + +int __cdecl main( int argc, char **argv ) + +{ + int i, j, k; + int *total; + + HANDLE hProcess; + FILETIME createTime; + FILETIME exitTime; + FILETIME kernelTime1; + FILETIME userTime1; + FILETIME kernelTime2; + FILETIME userTime2; + + DWORD dwError; + + /* initialize the PAL */ + if( PAL_Initialize(argc, argv) != 0 ) + { + return( FAIL ); + } + + /* get our own process handle */ + hProcess = GetCurrentProcess(); + if( hProcess == NULL ) + { + Fail( "GetCurrentProcess() returned a NULL handle.\n" ); + } + + /* zero our time structures */ + ZeroMemory( &createTime, sizeof(createTime) ); + ZeroMemory( &exitTime, sizeof(exitTime) ); + ZeroMemory( &kernelTime1, sizeof(kernelTime1) ); + ZeroMemory( &userTime1, sizeof(userTime1) ); + ZeroMemory( &kernelTime2, sizeof(kernelTime2) ); + ZeroMemory( &userTime2, sizeof(userTime2) ); + + /* check the process times for the child process */ + if( ! GetProcessTimes( hProcess, + &createTime, + &exitTime, + &kernelTime1, + &userTime1 ) ) + { + dwError = GetLastError(); + Fail( "GetProcessTimes() call failed with error code %d\n", + dwError ); + } + + + /* simulate some activity */ + for( i=0; i<1000; i++ ) + { + for( j=0; j<1000; j++ ) + { + /* do kernel work to increase system usage counters */ + total = (int*)malloc(1024 * 1024); + + *total = j * i; + for( k=0; k<1000; k++ ) + { + *total += k + i; + } + + free(total); + } + } + + /* check the process times for the child process */ + if( ! GetProcessTimes( hProcess, + &createTime, + &exitTime, + &kernelTime2, + &userTime2 ) ) + { + dwError = GetLastError(); + Fail( "GetProcessTimes() call failed with error code %d\n", + dwError ); + } + + + /* very simple logical checking of the results */ + if( CompareFileTime( &kernelTime1, &kernelTime2 ) > 0 ) + { + Fail( "Unexpected kernel time value reported.\n" ); + } + + if( CompareFileTime( &userTime1, &userTime2 ) > 0 ) + { + Fail( "Unexpected user time value reported.\n" ); + } + + + /* terminate the PAL */ + PAL_Terminate(); + + /* return success */ + return PASS; +} diff --git a/src/pal/tests/palsuite/threading/GetThreadTimes/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/GetThreadTimes/test1/CMakeLists.txt index d7e2eb2..aa4dad1 100644 --- a/src/pal/tests/palsuite/threading/GetThreadTimes/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/GetThreadTimes/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_getthreadtimes_test1 diff --git a/src/pal/tests/palsuite/threading/GetThreadTimes/test1/test1.c b/src/pal/tests/palsuite/threading/GetThreadTimes/test1/test1.c deleted file mode 100644 index 6b62c05..0000000 --- a/src/pal/tests/palsuite/threading/GetThreadTimes/test1/test1.c +++ /dev/null @@ -1,102 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: -** -** Source : test1.c -** -** Purpose: Test for GetThreadTimes() function -** -** -**=========================================================*/ - -#include - -int __cdecl main(int argc, char *argv[]) { - int ret = FAIL; - - //Test is failing unreliably, so for now we always return pass. - if (TRUE){ - ret = PASS; - goto EXIT; - } - - FILETIME kernelTime1, userTime1, kernelTime2, userTime2; - /* Delta = .01 sec */ - LONG64 Actual, Expected, Delta = 850000000; - Actual = 0; - Expected = 0; - const ULONG64 MSEC_TO_NSEC = 1000000; - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - HANDLE cThread = GetCurrentThread(); - - int i; - /* Take 2000 tiny measurements */ - for (i = 0; i < 2000; i++){ - ULONG64 Time1, Time2; - - Sleep(1); - - /* Grab a FirstCount, then loop for a bit to make the clock increase */ - if (!GetThreadTimes(cThread, NULL, NULL, &kernelTime1, &userTime1)) - { - Fail("ERROR: GetThreadTimes returned failure.\n"); - } - LONG64 x, Init; - /* Init is in milliseconds, so we will convert later */ - Init = (ULONG64)GetTickCount(); - /* Spin for < 1 Quantum so we don't get interrupted */ - x = Init + 3; - volatile int counter; - do { - for (counter = 0; counter < 100000; counter++) - { - // spin to consume CPU time - } - - } while (x > GetTickCount()); - Expected += (GetTickCount() - Init) * MSEC_TO_NSEC; - /* Get a second count */ - if (!GetThreadTimes(cThread, NULL, NULL, &kernelTime2, &userTime2)) - { - Fail("ERROR: GetThreadTimes returned failure.\n"); - } - - Time1 = ((ULONG64)kernelTime1.dwHighDateTime << 32); - Time1 += (ULONG64)kernelTime1.dwLowDateTime; - Time1 += ((ULONG64)userTime1.dwHighDateTime << 32); - Time1 += (ULONG64)userTime1.dwLowDateTime; - - Time2 = ((ULONG64)kernelTime2.dwHighDateTime << 32); - Time2 += (ULONG64)kernelTime2.dwLowDateTime; - Time2 += ((ULONG64)userTime2.dwHighDateTime << 32); - Time2 += (ULONG64)userTime2.dwLowDateTime; - - Actual += (Time2 - Time1) * 100; - } - - if(labs(Expected - Actual) > Delta) - { - Fail("ERROR: The measured time (%llu millisecs) was not within Delta %llu " - "of the expected time (%llu millisecs).\n", - (Actual / MSEC_TO_NSEC), (Delta / MSEC_TO_NSEC), (Expected / MSEC_TO_NSEC)); - } - //printf("%llu, %llu\n", Expected, Actual); - PAL_Terminate(); - ret = PASS; - -EXIT: - return ret; -} diff --git a/src/pal/tests/palsuite/threading/GetThreadTimes/test1/test1.cpp b/src/pal/tests/palsuite/threading/GetThreadTimes/test1/test1.cpp new file mode 100644 index 0000000..e57a7d0 --- /dev/null +++ b/src/pal/tests/palsuite/threading/GetThreadTimes/test1/test1.cpp @@ -0,0 +1,102 @@ +// 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. + +/*============================================================ +** +** Source: +** +** Source : test1.c +** +** Purpose: Test for GetThreadTimes() function +** +** +**=========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) { + int ret = FAIL; + + //Test is failing unreliably, so for now we always return pass. + if (TRUE){ + ret = PASS; + goto EXIT; + } + { + FILETIME kernelTime1, userTime1, kernelTime2, userTime2; + /* Delta = .01 sec */ + LONG64 Actual, Expected, Delta = 850000000; + Actual = 0; + Expected = 0; + const ULONG64 MSEC_TO_NSEC = 1000000; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + HANDLE cThread = GetCurrentThread(); + + int i; + /* Take 2000 tiny measurements */ + for (i = 0; i < 2000; i++){ + ULONG64 Time1, Time2; + + Sleep(1); + + /* Grab a FirstCount, then loop for a bit to make the clock increase */ + if (!GetThreadTimes(cThread, NULL, NULL, &kernelTime1, &userTime1)) + { + Fail("ERROR: GetThreadTimes returned failure.\n"); + } + LONG64 x, Init; + /* Init is in milliseconds, so we will convert later */ + Init = (ULONG64)GetTickCount(); + /* Spin for < 1 Quantum so we don't get interrupted */ + x = Init + 3; + volatile int counter; + do { + for (counter = 0; counter < 100000; counter++) + { + // spin to consume CPU time + } + + } while (x > GetTickCount()); + Expected += (GetTickCount() - Init) * MSEC_TO_NSEC; + /* Get a second count */ + if (!GetThreadTimes(cThread, NULL, NULL, &kernelTime2, &userTime2)) + { + Fail("ERROR: GetThreadTimes returned failure.\n"); + } + + Time1 = ((ULONG64)kernelTime1.dwHighDateTime << 32); + Time1 += (ULONG64)kernelTime1.dwLowDateTime; + Time1 += ((ULONG64)userTime1.dwHighDateTime << 32); + Time1 += (ULONG64)userTime1.dwLowDateTime; + + Time2 = ((ULONG64)kernelTime2.dwHighDateTime << 32); + Time2 += (ULONG64)kernelTime2.dwLowDateTime; + Time2 += ((ULONG64)userTime2.dwHighDateTime << 32); + Time2 += (ULONG64)userTime2.dwLowDateTime; + + Actual += (Time2 - Time1) * 100; + } + + if(labs(Expected - Actual) > Delta) + { + Fail("ERROR: The measured time (%llu millisecs) was not within Delta %llu " + "of the expected time (%llu millisecs).\n", + (Actual / MSEC_TO_NSEC), (Delta / MSEC_TO_NSEC), (Expected / MSEC_TO_NSEC)); + } + //printf("%llu, %llu\n", Expected, Actual); + PAL_Terminate(); + ret = PASS; + } +EXIT: + return ret; +} diff --git a/src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp b/src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp index 3726214..a9d46b3 100644 --- a/src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp +++ b/src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp @@ -520,7 +520,7 @@ bool MutualExclusionTests_Parent() return true; } -DWORD MutualExclusionTests_Child(void *arg = nullptr) +DWORD PALAPI MutualExclusionTests_Child(void *arg = nullptr) { const char *testName = "MutualExclusionTests"; @@ -626,7 +626,7 @@ bool LifetimeTests_Parent() return true; } -DWORD LifetimeTests_Child(void *arg = nullptr) +DWORD PALAPI LifetimeTests_Child(void *arg = nullptr) { const char *testName = "LifetimeTests"; @@ -682,7 +682,7 @@ bool LifetimeTests() return true; } -DWORD AbandonTests_Child_TryLock(void *arg = nullptr); +DWORD PALAPI AbandonTests_Child_TryLock(void *arg = nullptr); bool AbandonTests_Parent() { @@ -751,7 +751,7 @@ bool AbandonTests_Parent() return true; } -DWORD AbandonTests_Child_GracefulExit_Close(void *arg = nullptr) +DWORD PALAPI AbandonTests_Child_GracefulExit_Close(void *arg = nullptr) { const char *testName = "AbandonTests"; @@ -837,7 +837,7 @@ DWORD AbandonTests_Child_AbruptExit(void *arg = nullptr) return 0; } -DWORD AbandonTests_Child_TryLock(void *arg) +DWORD PALAPI AbandonTests_Child_TryLock(void *arg) { const char *testName = "AbandonTests"; @@ -910,7 +910,7 @@ DWORD g_stressDurationMilliseconds = 0; LONG g_stressTestCounts[_countof(TestList)] = {0}; LONG g_stressResult = true; -DWORD StressTest(void *arg) +DWORD PALAPI StressTest(void *arg) { // Run the specified test continuously for the stress duration SIZE_T testIndex = reinterpret_cast(arg); diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/OpenEventW/test1/CMakeLists.txt index 2bb61e3..2d5698b 100644 --- a/src/pal/tests/palsuite/threading/OpenEventW/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/OpenEventW/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_openeventw_test1 diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test1/test1.c b/src/pal/tests/palsuite/threading/OpenEventW/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/OpenEventW/test1/test1.c rename to src/pal/tests/palsuite/threading/OpenEventW/test1/test1.cpp diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/OpenEventW/test2/CMakeLists.txt index 48fa1f2..bedf83b 100644 --- a/src/pal/tests/palsuite/threading/OpenEventW/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/OpenEventW/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_openeventw_test2 diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test2/test2.c b/src/pal/tests/palsuite/threading/OpenEventW/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/OpenEventW/test2/test2.c rename to src/pal/tests/palsuite/threading/OpenEventW/test2/test2.cpp diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/OpenEventW/test3/CMakeLists.txt index 433a3a2..7f7622d 100644 --- a/src/pal/tests/palsuite/threading/OpenEventW/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/OpenEventW/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - test3.c + test3.cpp ) add_executable(paltest_openeventw_test3 @@ -20,7 +20,7 @@ target_link_libraries(paltest_openeventw_test3 set(HELPERSOURCES - childprocess.c + childprocess.cpp ) add_executable(paltest_openeventw_test3_child diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test3/childprocess.c b/src/pal/tests/palsuite/threading/OpenEventW/test3/childprocess.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/OpenEventW/test3/childprocess.c rename to src/pal/tests/palsuite/threading/OpenEventW/test3/childprocess.cpp diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test3/test3.c b/src/pal/tests/palsuite/threading/OpenEventW/test3/test3.c deleted file mode 100644 index 10a678a..0000000 --- a/src/pal/tests/palsuite/threading/OpenEventW/test3/test3.c +++ /dev/null @@ -1,187 +0,0 @@ -// 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. - -/*============================================================================= -** -** Source: test3.c -** -** Purpose: Test to ensure that OpenEventW() works when -** opening an event created by another process. This test -** program launches a child process which creates a -** named, initially-unset event. The child waits up to -** 10 seconds for the parent process to open that event -** and set it, and returns PASS if the event was set or FAIL -** otherwise. The parent process checks the return value -** from the child to verify that the opened event was -** properly used across processes. -** -** Dependencies: PAL_Initialize -** PAL_Terminate -** Fail -** ZeroMemory -** GetCurrentDirectoryW -** CreateProcessW -** WaitForSingleObject -** GetExitCodeProcess -** GetLastError -** strlen -** strncpy -** -** -**===========================================================================*/ -#include - -#define TIMEOUT 60000 - -int __cdecl main( int argc, char **argv ) -{ - BOOL ret = FAIL; - LPSECURITY_ATTRIBUTES lpEventAttributes = NULL; - - STARTUPINFO si; - PROCESS_INFORMATION pi; - - DWORD dwExitCode; - - DWORD dwRet = 0; - HANDLE hEvent = NULL; - WCHAR wcName[] = {'P','A','L','R','o','c','k','s','\0'}; - LPWSTR lpName = wcName; - char lpCommandLine[MAX_PATH] = ""; - - /* initialize the PAL */ - if( PAL_Initialize(argc, argv) != 0 ) - { - return( FAIL ); - } - - /* zero our process and startup info structures */ - ZeroMemory( &si, sizeof(si) ); - si.cb = sizeof( si ); - ZeroMemory( &pi, sizeof(pi) ); - - /* create an event which we can use with SetEvent */ - hEvent = CreateEventW( lpEventAttributes, - TRUE, /* manual reset */ - FALSE, /* unsignalled */ - lpName ); - - if( hEvent == NULL ) - { - /* ERROR */ - Fail( "ERROR:%lu:CreateEventW() call failed in child\n", - GetLastError()); - } - - ZeroMemory( lpCommandLine, MAX_PATH ); - if ( _snprintf( lpCommandLine, MAX_PATH-1, "childprocess ") < 0 ) - { - Fail ("Error: Insufficient lpCommandline for\n"); - } - - /* launch the child process */ - if( !CreateProcess( NULL, /* module name to execute */ - lpCommandLine, /* command line */ - NULL, /* process handle not */ - /* inheritable */ - NULL, /* thread handle not */ - /* inheritable */ - FALSE, /* handle inheritance */ - CREATE_NEW_CONSOLE, /* dwCreationFlags */ - NULL, /* use parent's environment */ - NULL, /* use parent's starting */ - /* directory */ - &si, /* startup info struct */ - &pi ) /* process info struct */ - ) - { - Fail( "ERROR:%lu:CreateProcess call failed\n", - GetLastError() ); - } - - /* verify that the event is signalled by the child process */ - dwRet = WaitForSingleObject( hEvent, TIMEOUT ); - if( dwRet != WAIT_OBJECT_0 ) - { - ret = FAIL; - /* ERROR */ - Trace( "ERROR:WaitForSingleObject() call returned %lu, " - "expected WAIT_TIMEOUT\n", - "expected WAIT_OBJECT_0\n", - dwRet ); - - goto cleanup; - - if( !CloseHandle( hEvent ) ) - { - Trace( "ERROR:%lu:CloseHandle() call failed in child\n", - GetLastError()); - } - goto cleanup; - } - - /* wait for the child process to complete */ - dwRet = WaitForSingleObject ( pi.hProcess, TIMEOUT ); - if( dwRet != WAIT_OBJECT_0 ) - { - ret = FAIL; - Trace( "ERROR:WaitForSingleObject() returned %lu, " - "expected %lu\n", - dwRet, - WAIT_OBJECT_0 ); - goto cleanup; - } - - /* check the exit code from the process */ - if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) ) - { - ret = FAIL; - Trace( "ERROR:%lu:GetExitCodeProcess call failed\n", - GetLastError() ); - goto cleanup; - } - - /* check for success */ - ret = (dwExitCode == PASS) ? PASS : FAIL; - -cleanup: - if( hEvent != NULL ) - { - if( ! CloseHandle ( hEvent ) ) - { - Trace( "ERROR:%lu:CloseHandle call failed on event handle\n", - GetLastError() ); - ret = FAIL; - } - } - - - /* close process and thread handle */ - if( ! CloseHandle ( pi.hProcess ) ) - { - Trace( "ERROR:%lu:CloseHandle call failed on process handle\n", - GetLastError() ); - ret = FAIL; - } - - if( ! CloseHandle ( pi.hThread ) ) - { - Trace( "ERROR:%lu:CloseHandle call failed on thread handle\n", - GetLastError() ); - ret = FAIL; - } - - /* output a convenient error message and exit if we failed */ - if( ret == FAIL ) - { - Fail( "test failed\n" ); - } - - - /* terminate the PAL */ - PAL_Terminate(); - - /* return success */ - return ret; -} diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test3/test3.cpp b/src/pal/tests/palsuite/threading/OpenEventW/test3/test3.cpp new file mode 100644 index 0000000..c4edf22 --- /dev/null +++ b/src/pal/tests/palsuite/threading/OpenEventW/test3/test3.cpp @@ -0,0 +1,187 @@ +// 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. + +/*============================================================================= +** +** Source: test3.c +** +** Purpose: Test to ensure that OpenEventW() works when +** opening an event created by another process. This test +** program launches a child process which creates a +** named, initially-unset event. The child waits up to +** 10 seconds for the parent process to open that event +** and set it, and returns PASS if the event was set or FAIL +** otherwise. The parent process checks the return value +** from the child to verify that the opened event was +** properly used across processes. +** +** Dependencies: PAL_Initialize +** PAL_Terminate +** Fail +** ZeroMemory +** GetCurrentDirectoryW +** CreateProcessW +** WaitForSingleObject +** GetExitCodeProcess +** GetLastError +** strlen +** strncpy +** +** +**===========================================================================*/ +#include + +#define TIMEOUT 60000 + +int __cdecl main( int argc, char **argv ) +{ + BOOL ret = FAIL; + LPSECURITY_ATTRIBUTES lpEventAttributes = NULL; + + STARTUPINFO si; + PROCESS_INFORMATION pi; + + DWORD dwExitCode; + + DWORD dwRet = 0; + HANDLE hEvent = NULL; + WCHAR wcName[] = {'P','A','L','R','o','c','k','s','\0'}; + LPWSTR lpName = wcName; + char lpCommandLine[MAX_PATH] = ""; + + /* initialize the PAL */ + if( PAL_Initialize(argc, argv) != 0 ) + { + return( FAIL ); + } + + /* zero our process and startup info structures */ + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof( si ); + ZeroMemory( &pi, sizeof(pi) ); + + /* create an event which we can use with SetEvent */ + hEvent = CreateEventW( lpEventAttributes, + TRUE, /* manual reset */ + FALSE, /* unsignalled */ + lpName ); + + if( hEvent == NULL ) + { + /* ERROR */ + Fail( "ERROR:%lu:CreateEventW() call failed in child\n", + GetLastError()); + } + + ZeroMemory( lpCommandLine, MAX_PATH ); + if ( sprintf_s( lpCommandLine, MAX_PATH-1, "childprocess ") < 0 ) + { + Fail ("Error: Insufficient lpCommandline for\n"); + } + + /* launch the child process */ + if( !CreateProcess( NULL, /* module name to execute */ + lpCommandLine, /* command line */ + NULL, /* process handle not */ + /* inheritable */ + NULL, /* thread handle not */ + /* inheritable */ + FALSE, /* handle inheritance */ + CREATE_NEW_CONSOLE, /* dwCreationFlags */ + NULL, /* use parent's environment */ + NULL, /* use parent's starting */ + /* directory */ + &si, /* startup info struct */ + &pi ) /* process info struct */ + ) + { + Fail( "ERROR:%lu:CreateProcess call failed\n", + GetLastError() ); + } + + /* verify that the event is signalled by the child process */ + dwRet = WaitForSingleObject( hEvent, TIMEOUT ); + if( dwRet != WAIT_OBJECT_0 ) + { + ret = FAIL; + /* ERROR */ + Trace( "ERROR:WaitForSingleObject() call returned %lu, " + "expected WAIT_TIMEOUT\n", + "expected WAIT_OBJECT_0\n", + dwRet ); + + goto cleanup; + + if( !CloseHandle( hEvent ) ) + { + Trace( "ERROR:%lu:CloseHandle() call failed in child\n", + GetLastError()); + } + goto cleanup; + } + + /* wait for the child process to complete */ + dwRet = WaitForSingleObject ( pi.hProcess, TIMEOUT ); + if( dwRet != WAIT_OBJECT_0 ) + { + ret = FAIL; + Trace( "ERROR:WaitForSingleObject() returned %lu, " + "expected %lu\n", + dwRet, + WAIT_OBJECT_0 ); + goto cleanup; + } + + /* check the exit code from the process */ + if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) ) + { + ret = FAIL; + Trace( "ERROR:%lu:GetExitCodeProcess call failed\n", + GetLastError() ); + goto cleanup; + } + + /* check for success */ + ret = (dwExitCode == PASS) ? PASS : FAIL; + +cleanup: + if( hEvent != NULL ) + { + if( ! CloseHandle ( hEvent ) ) + { + Trace( "ERROR:%lu:CloseHandle call failed on event handle\n", + GetLastError() ); + ret = FAIL; + } + } + + + /* close process and thread handle */ + if( ! CloseHandle ( pi.hProcess ) ) + { + Trace( "ERROR:%lu:CloseHandle call failed on process handle\n", + GetLastError() ); + ret = FAIL; + } + + if( ! CloseHandle ( pi.hThread ) ) + { + Trace( "ERROR:%lu:CloseHandle call failed on thread handle\n", + GetLastError() ); + ret = FAIL; + } + + /* output a convenient error message and exit if we failed */ + if( ret == FAIL ) + { + Fail( "test failed\n" ); + } + + + /* terminate the PAL */ + PAL_Terminate(); + + /* return success */ + return ret; +} diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test4/CMakeLists.txt b/src/pal/tests/palsuite/threading/OpenEventW/test4/CMakeLists.txt index ff17fea..73b8904 100644 --- a/src/pal/tests/palsuite/threading/OpenEventW/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/OpenEventW/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_openeventw_test4 diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test4/test4.c b/src/pal/tests/palsuite/threading/OpenEventW/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/OpenEventW/test4/test4.c rename to src/pal/tests/palsuite/threading/OpenEventW/test4/test4.cpp diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test5/CMakeLists.txt b/src/pal/tests/palsuite/threading/OpenEventW/test5/CMakeLists.txt index b78d7fb..3bad4d9 100644 --- a/src/pal/tests/palsuite/threading/OpenEventW/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/OpenEventW/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_openeventw_test5 diff --git a/src/pal/tests/palsuite/threading/OpenEventW/test5/test5.c b/src/pal/tests/palsuite/threading/OpenEventW/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/OpenEventW/test5/test5.c rename to src/pal/tests/palsuite/threading/OpenEventW/test5/test5.cpp diff --git a/src/pal/tests/palsuite/threading/OpenProcess/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/OpenProcess/test1/CMakeLists.txt index 26d3054..dd2e305 100644 --- a/src/pal/tests/palsuite/threading/OpenProcess/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/OpenProcess/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - test1.c + test1.cpp ) add_executable(paltest_openprocess_test1 @@ -20,7 +20,7 @@ target_link_libraries(paltest_openprocess_test1 set(HELPERSOURCES - childProcess.c + childProcess.cpp ) add_executable(paltest_openprocess_test1_child diff --git a/src/pal/tests/palsuite/threading/OpenProcess/test1/childProcess.c b/src/pal/tests/palsuite/threading/OpenProcess/test1/childProcess.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/OpenProcess/test1/childProcess.c rename to src/pal/tests/palsuite/threading/OpenProcess/test1/childProcess.cpp diff --git a/src/pal/tests/palsuite/threading/OpenProcess/test1/test1.c b/src/pal/tests/palsuite/threading/OpenProcess/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/OpenProcess/test1/test1.c rename to src/pal/tests/palsuite/threading/OpenProcess/test1/test1.cpp diff --git a/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/CMakeLists.txt index ad3eec1..9a54ad1 100644 --- a/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_querythreadcycletime_test1 diff --git a/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/test1.c b/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/test1.c deleted file mode 100644 index 54f0116..0000000 --- a/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/test1.c +++ /dev/null @@ -1,98 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: -** -** Source : test1.c -** -** Purpose: Test for QueryThreadCycleTime() function -** -** -**=========================================================*/ - -#include - -int __cdecl main(int argc, char *argv[]) { - int ret = FAIL; - - //Test is failing unreliably, so for now we always return pass. - if (TRUE){ - ret = PASS; - goto EXIT; - } - - LONG64 Actual, Expected, Delta = 850000000; - Actual = 0; - Expected = 0; - const LONG64 MSEC_TO_NSEC = 1000000; - - /* - * Initialize the PAL and return FAILURE if this fails - */ - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - HANDLE cThread = GetCurrentThread(); - - int i; - /* Take 2000 tiny measurements */ - for (i = 0; i < 2000; i++){ - ULONG64 FirstCount, SecondCount; - LONG64 Init; - - Sleep(1); - - /* Grab a FirstCount, then loop for a bit to make the clock increase */ - if (!QueryThreadCycleTime(cThread, (PULONG64)&FirstCount)) - { - Fail("ERROR: QueryThreadCycleTime returned failure.\n"); - } - - LONG64 x; - /* Init is in milliseconds, so we will convert later */ - Init = (LONG64)GetTickCount(); - x = Init + 3; - volatile int counter; - do { - for (counter = 0; counter < 100000; counter++) - { - // spin to consume CPU time - } - - } while (x > GetTickCount()); - Expected += (GetTickCount() - Init) * MSEC_TO_NSEC; - /* Get a second count */ - if (!QueryThreadCycleTime(cThread, (PULONG64)&SecondCount)) - { - Fail("ERROR: QueryThreadCycleTime returned failure.\n"); - } - - LONG64 trial = (LONG64)SecondCount - (LONG64)FirstCount; - if (trial < 0){ - printf("Negative value %llu measured", trial); - } - Actual += (trial); - - } - - - - if(labs(Expected - Actual) > Delta) - { - Fail("ERROR: The measured time (%llu millisecs) was not within Delta %llu " - "of the expected time (%llu millisecs).\n", - (Actual / MSEC_TO_NSEC), (Delta / MSEC_TO_NSEC), (Expected / MSEC_TO_NSEC)); - } - //printf("%llu, %llu\n", Expected, Actual); - PAL_Terminate(); - ret = PASS; - -EXIT: - return ret; -} diff --git a/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/test1.cpp b/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/test1.cpp new file mode 100644 index 0000000..026243c --- /dev/null +++ b/src/pal/tests/palsuite/threading/QueryThreadCycleTime/test1/test1.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +/*============================================================ +** +** Source: +** +** Source : test1.c +** +** Purpose: Test for QueryThreadCycleTime() function +** +** +**=========================================================*/ + +#include + +int __cdecl main(int argc, char *argv[]) { + int ret = FAIL; + + //Test is failing unreliably, so for now we always return pass. + if (TRUE){ + ret = PASS; + goto EXIT; + } + { + LONG64 Actual, Expected, Delta = 850000000; + Actual = 0; + Expected = 0; + const LONG64 MSEC_TO_NSEC = 1000000; + + /* + * Initialize the PAL and return FAILURE if this fails + */ + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + HANDLE cThread = GetCurrentThread(); + + int i; + /* Take 2000 tiny measurements */ + for (i = 0; i < 2000; i++){ + ULONG64 FirstCount, SecondCount; + LONG64 Init; + + Sleep(1); + + /* Grab a FirstCount, then loop for a bit to make the clock increase */ + if (!QueryThreadCycleTime(cThread, (PULONG64)&FirstCount)) + { + Fail("ERROR: QueryThreadCycleTime returned failure.\n"); + } + + LONG64 x; + /* Init is in milliseconds, so we will convert later */ + Init = (LONG64)GetTickCount(); + x = Init + 3; + volatile int counter; + do { + for (counter = 0; counter < 100000; counter++) + { + // spin to consume CPU time + } + + } while (x > GetTickCount()); + Expected += (GetTickCount() - Init) * MSEC_TO_NSEC; + /* Get a second count */ + if (!QueryThreadCycleTime(cThread, (PULONG64)&SecondCount)) + { + Fail("ERROR: QueryThreadCycleTime returned failure.\n"); + } + + LONG64 trial = (LONG64)SecondCount - (LONG64)FirstCount; + if (trial < 0){ + printf("Negative value %llu measured", trial); + } + Actual += (trial); + + } + + + + if(labs(Expected - Actual) > Delta) + { + Fail("ERROR: The measured time (%llu millisecs) was not within Delta %llu " + "of the expected time (%llu millisecs).\n", + (Actual / MSEC_TO_NSEC), (Delta / MSEC_TO_NSEC), (Expected / MSEC_TO_NSEC)); + } + //printf("%llu, %llu\n", Expected, Actual); + PAL_Terminate(); + ret = PASS; + } +EXIT: + return ret; +} diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/QueueUserAPC/test1/CMakeLists.txt index 54a4d03..a99b0a6 100644 --- a/src/pal/tests/palsuite/threading/QueueUserAPC/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_queueuserapc_test1 diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test1/test1.c b/src/pal/tests/palsuite/threading/QueueUserAPC/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/QueueUserAPC/test1/test1.c rename to src/pal/tests/palsuite/threading/QueueUserAPC/test1/test1.cpp diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/QueueUserAPC/test2/CMakeLists.txt index 88cda5f..5d86efd 100644 --- a/src/pal/tests/palsuite/threading/QueueUserAPC/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_queueuserapc_test2 diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test2/test2.c b/src/pal/tests/palsuite/threading/QueueUserAPC/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/QueueUserAPC/test2/test2.c rename to src/pal/tests/palsuite/threading/QueueUserAPC/test2/test2.cpp diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/QueueUserAPC/test3/CMakeLists.txt index 8475dcb..e07ab67 100644 --- a/src/pal/tests/palsuite/threading/QueueUserAPC/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_queueuserapc_test3 diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test3/test3.c b/src/pal/tests/palsuite/threading/QueueUserAPC/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/QueueUserAPC/test3/test3.c rename to src/pal/tests/palsuite/threading/QueueUserAPC/test3/test3.cpp diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test4/CMakeLists.txt b/src/pal/tests/palsuite/threading/QueueUserAPC/test4/CMakeLists.txt index 2552738..08a5cc7 100644 --- a/src/pal/tests/palsuite/threading/QueueUserAPC/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_queueuserapc_test4 diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test4/test4.c b/src/pal/tests/palsuite/threading/QueueUserAPC/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/QueueUserAPC/test4/test4.c rename to src/pal/tests/palsuite/threading/QueueUserAPC/test4/test4.cpp diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test5/CMakeLists.txt b/src/pal/tests/palsuite/threading/QueueUserAPC/test5/CMakeLists.txt index c2fa10d..0ef65ce 100644 --- a/src/pal/tests/palsuite/threading/QueueUserAPC/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_queueuserapc_test5 diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test5/test5.c b/src/pal/tests/palsuite/threading/QueueUserAPC/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/QueueUserAPC/test5/test5.c rename to src/pal/tests/palsuite/threading/QueueUserAPC/test5/test5.cpp diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test6/CMakeLists.txt b/src/pal/tests/palsuite/threading/QueueUserAPC/test6/CMakeLists.txt index 3fd1b1a..2e71983 100644 --- a/src/pal/tests/palsuite/threading/QueueUserAPC/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test6.c + test6.cpp ) add_executable(paltest_queueuserapc_test6 diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test6/test6.c b/src/pal/tests/palsuite/threading/QueueUserAPC/test6/test6.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/QueueUserAPC/test6/test6.c rename to src/pal/tests/palsuite/threading/QueueUserAPC/test6/test6.cpp diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test7/CMakeLists.txt b/src/pal/tests/palsuite/threading/QueueUserAPC/test7/CMakeLists.txt index 751f389..c27cd7e 100644 --- a/src/pal/tests/palsuite/threading/QueueUserAPC/test7/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/QueueUserAPC/test7/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test7.c + test7.cpp ) add_executable(paltest_queueuserapc_test7 diff --git a/src/pal/tests/palsuite/threading/QueueUserAPC/test7/test7.c b/src/pal/tests/palsuite/threading/QueueUserAPC/test7/test7.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/QueueUserAPC/test7/test7.c rename to src/pal/tests/palsuite/threading/QueueUserAPC/test7/test7.cpp diff --git a/src/pal/tests/palsuite/threading/ReleaseMutex/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/ReleaseMutex/test3/CMakeLists.txt index 8e64c28..6bb3a79 100644 --- a/src/pal/tests/palsuite/threading/ReleaseMutex/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/ReleaseMutex/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - ReleaseMutex.c + ReleaseMutex.cpp ) add_executable(paltest_releasemutex_test3 diff --git a/src/pal/tests/palsuite/threading/ReleaseMutex/test3/ReleaseMutex.c b/src/pal/tests/palsuite/threading/ReleaseMutex/test3/ReleaseMutex.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/ReleaseMutex/test3/ReleaseMutex.c rename to src/pal/tests/palsuite/threading/ReleaseMutex/test3/ReleaseMutex.cpp diff --git a/src/pal/tests/palsuite/threading/ResetEvent/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/ResetEvent/test1/CMakeLists.txt index 78e84da..12c8311 100644 --- a/src/pal/tests/palsuite/threading/ResetEvent/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/ResetEvent/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_resetevent_test1 diff --git a/src/pal/tests/palsuite/threading/ResetEvent/test1/test1.c b/src/pal/tests/palsuite/threading/ResetEvent/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/ResetEvent/test1/test1.c rename to src/pal/tests/palsuite/threading/ResetEvent/test1/test1.cpp diff --git a/src/pal/tests/palsuite/threading/ResetEvent/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/ResetEvent/test2/CMakeLists.txt index ad0fe9b..1f67b5d 100644 --- a/src/pal/tests/palsuite/threading/ResetEvent/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/ResetEvent/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_resetevent_test2 diff --git a/src/pal/tests/palsuite/threading/ResetEvent/test2/test2.c b/src/pal/tests/palsuite/threading/ResetEvent/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/ResetEvent/test2/test2.c rename to src/pal/tests/palsuite/threading/ResetEvent/test2/test2.cpp diff --git a/src/pal/tests/palsuite/threading/ResetEvent/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/ResetEvent/test3/CMakeLists.txt index 3c4ea1f..fd0d6e8 100644 --- a/src/pal/tests/palsuite/threading/ResetEvent/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/ResetEvent/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_resetevent_test3 diff --git a/src/pal/tests/palsuite/threading/ResetEvent/test3/test3.c b/src/pal/tests/palsuite/threading/ResetEvent/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/ResetEvent/test3/test3.c rename to src/pal/tests/palsuite/threading/ResetEvent/test3/test3.cpp diff --git a/src/pal/tests/palsuite/threading/ResetEvent/test4/CMakeLists.txt b/src/pal/tests/palsuite/threading/ResetEvent/test4/CMakeLists.txt index 68ee20b..ca2a918 100644 --- a/src/pal/tests/palsuite/threading/ResetEvent/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/ResetEvent/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_resetevent_test4 diff --git a/src/pal/tests/palsuite/threading/ResetEvent/test4/test4.c b/src/pal/tests/palsuite/threading/ResetEvent/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/ResetEvent/test4/test4.c rename to src/pal/tests/palsuite/threading/ResetEvent/test4/test4.cpp diff --git a/src/pal/tests/palsuite/threading/ResumeThread/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/ResumeThread/test1/CMakeLists.txt index 2c83dfd..96d7edc 100644 --- a/src/pal/tests/palsuite/threading/ResumeThread/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/ResumeThread/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_resumethread_test1 diff --git a/src/pal/tests/palsuite/threading/ResumeThread/test1/test1.c b/src/pal/tests/palsuite/threading/ResumeThread/test1/test1.c deleted file mode 100644 index 037f79f..0000000 --- a/src/pal/tests/palsuite/threading/ResumeThread/test1/test1.c +++ /dev/null @@ -1,141 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: test1.c -** -** Purpose: Test for ResumeThread. Create a suspended Thread. -** First, ensure that it is indeed suspended. Then call resumethread -** and check to ensure that the function has now run. -** -** -**=========================================================*/ - -#include - -DWORD dwResumeThreadTestParameter = 0; - -DWORD PALAPI ResumeThreadTestThread( LPVOID lpParameter) -{ - DWORD dwRet = 0; - - /* Save parameter so we can check and ensure this function ran - properly. - */ - - dwResumeThreadTestParameter = (DWORD)lpParameter; - - return dwRet; -} - -BOOL ResumeThreadTest() -{ - BOOL bRet = FALSE; - DWORD dwRet = 0; - - LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL; - DWORD dwStackSize = 0; - LPTHREAD_START_ROUTINE lpStartAddress = &ResumeThreadTestThread; - LPVOID lpParameter = lpStartAddress; - DWORD dwCreationFlags = CREATE_SUSPENDED; - DWORD dwThreadId = 0; - - HANDLE hThread = 0; - - dwResumeThreadTestParameter = 0; - - /* Create a thread, with CREATE_SUSPENDED, so we can resume it! */ - - hThread = CreateThread( lpThreadAttributes, - dwStackSize, lpStartAddress, lpParameter, - dwCreationFlags, &dwThreadId ); - - if (hThread != INVALID_HANDLE_VALUE) - { - /* Wait for one second. This should return WAIT_TIMEOUT */ - dwRet = WaitForSingleObject(hThread,1000); - - if (dwRet != WAIT_TIMEOUT) - { - Trace("ResumeThreadTest:WaitForSingleObject " - "failed (%x)\n",GetLastError()); - } - else - { - /* Check to ensure the parameter hasn't changed. The - function shouldn't have occurred yet. - */ - if (dwResumeThreadTestParameter != 0) - { - Trace("ResumeThreadTest:parameter error\n"); - } - else - { - /* Call ResumeThread and ensure the return value is - correct. - */ - - dwRet = ResumeThread(hThread); - - if (dwRet != 1) - { - Trace("ResumeThreadTest:ResumeThread " - "failed (%x)\n",GetLastError()); - } - else - { - /* Wait again, now that the thread has been - resumed, and the return should be WAIT_OBJECT_0 - */ - dwRet = WaitForSingleObject(hThread,INFINITE); - - if (dwRet != WAIT_OBJECT_0) - { - Trace("ResumeThreadTest:WaitForSingleObject " - "failed (%x)\n",GetLastError()); - } - else - { - /* Check the param now and it should have been - set. - */ - if (dwResumeThreadTestParameter != (DWORD)lpParameter) - { - Trace("ResumeThreadTest:parameter error\n"); - } - else - { - bRet = TRUE; - } - } - } - } - } - } - else - { - Trace("ResumeThreadTest:CreateThread failed (%x)\n",GetLastError()); - } - - return bRet; -} - -int __cdecl main(int argc, char **argv) -{ - - if(0 != (PAL_Initialize(argc, argv))) - { - return ( FAIL ); - } - - if(!ResumeThreadTest()) - { - Fail("Test Failed\n"); - } - - PAL_Terminate(); - return (PASS); - -} diff --git a/src/pal/tests/palsuite/threading/ResumeThread/test1/test1.cpp b/src/pal/tests/palsuite/threading/ResumeThread/test1/test1.cpp new file mode 100644 index 0000000..d2be262 --- /dev/null +++ b/src/pal/tests/palsuite/threading/ResumeThread/test1/test1.cpp @@ -0,0 +1,141 @@ +// 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. + +/*============================================================ +** +** Source: test1.c +** +** Purpose: Test for ResumeThread. Create a suspended Thread. +** First, ensure that it is indeed suspended. Then call resumethread +** and check to ensure that the function has now run. +** +** +**=========================================================*/ + +#include + +DWORD dwResumeThreadTestParameter = 0; + +DWORD PALAPI ResumeThreadTestThread( LPVOID lpParameter) +{ + DWORD dwRet = 0; + + /* Save parameter so we can check and ensure this function ran + properly. + */ + + dwResumeThreadTestParameter = (DWORD)lpParameter; + + return dwRet; +} + +BOOL ResumeThreadTest() +{ + BOOL bRet = FALSE; + DWORD dwRet = 0; + + LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL; + DWORD dwStackSize = 0; + LPTHREAD_START_ROUTINE lpStartAddress = &ResumeThreadTestThread; + LPVOID lpParameter = (LPVOID)lpStartAddress; + DWORD dwCreationFlags = CREATE_SUSPENDED; + DWORD dwThreadId = 0; + + HANDLE hThread = 0; + + dwResumeThreadTestParameter = 0; + + /* Create a thread, with CREATE_SUSPENDED, so we can resume it! */ + + hThread = CreateThread( lpThreadAttributes, + dwStackSize, lpStartAddress, lpParameter, + dwCreationFlags, &dwThreadId ); + + if (hThread != INVALID_HANDLE_VALUE) + { + /* Wait for one second. This should return WAIT_TIMEOUT */ + dwRet = WaitForSingleObject(hThread,1000); + + if (dwRet != WAIT_TIMEOUT) + { + Trace("ResumeThreadTest:WaitForSingleObject " + "failed (%x)\n",GetLastError()); + } + else + { + /* Check to ensure the parameter hasn't changed. The + function shouldn't have occurred yet. + */ + if (dwResumeThreadTestParameter != 0) + { + Trace("ResumeThreadTest:parameter error\n"); + } + else + { + /* Call ResumeThread and ensure the return value is + correct. + */ + + dwRet = ResumeThread(hThread); + + if (dwRet != 1) + { + Trace("ResumeThreadTest:ResumeThread " + "failed (%x)\n",GetLastError()); + } + else + { + /* Wait again, now that the thread has been + resumed, and the return should be WAIT_OBJECT_0 + */ + dwRet = WaitForSingleObject(hThread,INFINITE); + + if (dwRet != WAIT_OBJECT_0) + { + Trace("ResumeThreadTest:WaitForSingleObject " + "failed (%x)\n",GetLastError()); + } + else + { + /* Check the param now and it should have been + set. + */ + if (dwResumeThreadTestParameter != (DWORD)lpParameter) + { + Trace("ResumeThreadTest:parameter error\n"); + } + else + { + bRet = TRUE; + } + } + } + } + } + } + else + { + Trace("ResumeThreadTest:CreateThread failed (%x)\n",GetLastError()); + } + + return bRet; +} + +int __cdecl main(int argc, char **argv) +{ + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(!ResumeThreadTest()) + { + Fail("Test Failed\n"); + } + + PAL_Terminate(); + return (PASS); + +} diff --git a/src/pal/tests/palsuite/threading/SetErrorMode/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/SetErrorMode/test1/CMakeLists.txt index cfdeb31..7c145a8 100644 --- a/src/pal/tests/palsuite/threading/SetErrorMode/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/SetErrorMode/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_seterrormode_test1 diff --git a/src/pal/tests/palsuite/threading/SetErrorMode/test1/test1.c b/src/pal/tests/palsuite/threading/SetErrorMode/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/SetErrorMode/test1/test1.c rename to src/pal/tests/palsuite/threading/SetErrorMode/test1/test1.cpp diff --git a/src/pal/tests/palsuite/threading/SetEvent/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/SetEvent/test1/CMakeLists.txt index 9be8d5a..8d9d729 100644 --- a/src/pal/tests/palsuite/threading/SetEvent/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/SetEvent/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_setevent_test1 diff --git a/src/pal/tests/palsuite/threading/SetEvent/test1/test1.c b/src/pal/tests/palsuite/threading/SetEvent/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/SetEvent/test1/test1.c rename to src/pal/tests/palsuite/threading/SetEvent/test1/test1.cpp diff --git a/src/pal/tests/palsuite/threading/SetEvent/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/SetEvent/test2/CMakeLists.txt index 87522b3..7d33b56 100644 --- a/src/pal/tests/palsuite/threading/SetEvent/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/SetEvent/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_setevent_test2 diff --git a/src/pal/tests/palsuite/threading/SetEvent/test2/test2.c b/src/pal/tests/palsuite/threading/SetEvent/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/SetEvent/test2/test2.c rename to src/pal/tests/palsuite/threading/SetEvent/test2/test2.cpp diff --git a/src/pal/tests/palsuite/threading/SetEvent/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/SetEvent/test3/CMakeLists.txt index d09239b..1c66460 100644 --- a/src/pal/tests/palsuite/threading/SetEvent/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/SetEvent/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_setevent_test3 diff --git a/src/pal/tests/palsuite/threading/SetEvent/test3/test3.c b/src/pal/tests/palsuite/threading/SetEvent/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/SetEvent/test3/test3.c rename to src/pal/tests/palsuite/threading/SetEvent/test3/test3.cpp diff --git a/src/pal/tests/palsuite/threading/SetEvent/test4/CMakeLists.txt b/src/pal/tests/palsuite/threading/SetEvent/test4/CMakeLists.txt index 3f1d344..04f1815 100644 --- a/src/pal/tests/palsuite/threading/SetEvent/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/SetEvent/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_setevent_test4 diff --git a/src/pal/tests/palsuite/threading/SetEvent/test4/test4.c b/src/pal/tests/palsuite/threading/SetEvent/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/SetEvent/test4/test4.c rename to src/pal/tests/palsuite/threading/SetEvent/test4/test4.cpp diff --git a/src/pal/tests/palsuite/threading/Sleep/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/Sleep/test1/CMakeLists.txt index b0d8db2..6017896 100644 --- a/src/pal/tests/palsuite/threading/Sleep/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/Sleep/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - Sleep.c + Sleep.cpp ) add_executable(paltest_sleep_test1 diff --git a/src/pal/tests/palsuite/threading/Sleep/test1/Sleep.c b/src/pal/tests/palsuite/threading/Sleep/test1/Sleep.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/Sleep/test1/Sleep.c rename to src/pal/tests/palsuite/threading/Sleep/test1/Sleep.cpp diff --git a/src/pal/tests/palsuite/threading/Sleep/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/Sleep/test2/CMakeLists.txt index 832e8ab..b8bc3ed 100644 --- a/src/pal/tests/palsuite/threading/Sleep/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/Sleep/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - sleep.c + sleep.cpp ) add_executable(paltest_sleep_test2 diff --git a/src/pal/tests/palsuite/threading/Sleep/test2/sleep.c b/src/pal/tests/palsuite/threading/Sleep/test2/sleep.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/Sleep/test2/sleep.c rename to src/pal/tests/palsuite/threading/Sleep/test2/sleep.cpp diff --git a/src/pal/tests/palsuite/threading/SleepEx/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/SleepEx/test1/CMakeLists.txt index de56275..b2aed83 100644 --- a/src/pal/tests/palsuite/threading/SleepEx/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/SleepEx/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_sleepex_test1 diff --git a/src/pal/tests/palsuite/threading/SleepEx/test1/test1.c b/src/pal/tests/palsuite/threading/SleepEx/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/SleepEx/test1/test1.c rename to src/pal/tests/palsuite/threading/SleepEx/test1/test1.cpp diff --git a/src/pal/tests/palsuite/threading/SleepEx/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/SleepEx/test2/CMakeLists.txt index 0ea4a44..991e9b4 100644 --- a/src/pal/tests/palsuite/threading/SleepEx/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/SleepEx/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_sleepex_test2 diff --git a/src/pal/tests/palsuite/threading/SleepEx/test2/test2.c b/src/pal/tests/palsuite/threading/SleepEx/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/SleepEx/test2/test2.c rename to src/pal/tests/palsuite/threading/SleepEx/test2/test2.cpp diff --git a/src/pal/tests/palsuite/threading/SwitchToThread/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/SwitchToThread/test1/CMakeLists.txt index 40ecc91..b9008c4 100644 --- a/src/pal/tests/palsuite/threading/SwitchToThread/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/SwitchToThread/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_switchtothread_test1 diff --git a/src/pal/tests/palsuite/threading/SwitchToThread/test1/test1.c b/src/pal/tests/palsuite/threading/SwitchToThread/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/SwitchToThread/test1/test1.c rename to src/pal/tests/palsuite/threading/SwitchToThread/test1/test1.cpp diff --git a/src/pal/tests/palsuite/threading/TLS/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/TLS/test1/CMakeLists.txt index ff1a866..fef7412 100644 --- a/src/pal/tests/palsuite/threading/TLS/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/TLS/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - TLS.c + TLS.cpp ) add_executable(paltest_tls_test1 diff --git a/src/pal/tests/palsuite/threading/TLS/test1/TLS.c b/src/pal/tests/palsuite/threading/TLS/test1/TLS.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/TLS/test1/TLS.c rename to src/pal/tests/palsuite/threading/TLS/test1/TLS.cpp diff --git a/src/pal/tests/palsuite/threading/TLS/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/TLS/test2/CMakeLists.txt index 5afe82b..10c5034 100644 --- a/src/pal/tests/palsuite/threading/TLS/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/TLS/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - TLS.c + TLS.cpp ) add_executable(paltest_tls_test2 diff --git a/src/pal/tests/palsuite/threading/TLS/test2/TLS.c b/src/pal/tests/palsuite/threading/TLS/test2/TLS.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/TLS/test2/TLS.c rename to src/pal/tests/palsuite/threading/TLS/test2/TLS.cpp diff --git a/src/pal/tests/palsuite/threading/TLS/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/TLS/test3/CMakeLists.txt index 0964d33..6bd76d3 100644 --- a/src/pal/tests/palsuite/threading/TLS/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/TLS/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - TLS.c + TLS.cpp ) add_executable(paltest_tls_test3 diff --git a/src/pal/tests/palsuite/threading/TLS/test3/TLS.c b/src/pal/tests/palsuite/threading/TLS/test3/TLS.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/TLS/test3/TLS.c rename to src/pal/tests/palsuite/threading/TLS/test3/TLS.cpp diff --git a/src/pal/tests/palsuite/threading/TLS/test4/CMakeLists.txt b/src/pal/tests/palsuite/threading/TLS/test4/CMakeLists.txt index 7e7b477..73ba496 100644 --- a/src/pal/tests/palsuite/threading/TLS/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/TLS/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_tls_test4 diff --git a/src/pal/tests/palsuite/threading/TLS/test4/test4.c b/src/pal/tests/palsuite/threading/TLS/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/TLS/test4/test4.c rename to src/pal/tests/palsuite/threading/TLS/test4/test4.cpp diff --git a/src/pal/tests/palsuite/threading/TLS/test5/CMakeLists.txt b/src/pal/tests/palsuite/threading/TLS/test5/CMakeLists.txt index 5fb5c9d..e26fcff 100644 --- a/src/pal/tests/palsuite/threading/TLS/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/TLS/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test5.c + test5.cpp ) add_executable(paltest_tls_test5 diff --git a/src/pal/tests/palsuite/threading/TLS/test5/test5.c b/src/pal/tests/palsuite/threading/TLS/test5/test5.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/TLS/test5/test5.c rename to src/pal/tests/palsuite/threading/TLS/test5/test5.cpp diff --git a/src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/CMakeLists.txt b/src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/CMakeLists.txt index 8b3a4ed..bfc7b75 100644 --- a/src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_tls_test6_optimizedtls diff --git a/src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/test.c b/src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/test.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/test.c rename to src/pal/tests/palsuite/threading/TLS/test6_optimizedtls/test.cpp diff --git a/src/pal/tests/palsuite/threading/TerminateProcess/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/TerminateProcess/test1/CMakeLists.txt index 37d5759..382e801 100644 --- a/src/pal/tests/palsuite/threading/TerminateProcess/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/TerminateProcess/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - TerminateProcess.c + TerminateProcess.cpp ) add_executable(paltest_terminateprocess_test1 diff --git a/src/pal/tests/palsuite/threading/TerminateProcess/test1/TerminateProcess.c b/src/pal/tests/palsuite/threading/TerminateProcess/test1/TerminateProcess.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/TerminateProcess/test1/TerminateProcess.c rename to src/pal/tests/palsuite/threading/TerminateProcess/test1/TerminateProcess.cpp diff --git a/src/pal/tests/palsuite/threading/ThreadPriority/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/ThreadPriority/test1/CMakeLists.txt index e341ca7..026f4ed 100644 --- a/src/pal/tests/palsuite/threading/ThreadPriority/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/ThreadPriority/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - ThreadPriority.c + ThreadPriority.cpp ) add_executable(paltest_threadpriority_test1 diff --git a/src/pal/tests/palsuite/threading/ThreadPriority/test1/ThreadPriority.c b/src/pal/tests/palsuite/threading/ThreadPriority/test1/ThreadPriority.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/ThreadPriority/test1/ThreadPriority.c rename to src/pal/tests/palsuite/threading/ThreadPriority/test1/ThreadPriority.cpp diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/CMakeLists.txt index 2b1f946..ea13c7d 100644 --- a/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_waitformultipleobjects_test1 diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/test1.c b/src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/test1.c rename to src/pal/tests/palsuite/threading/WaitForMultipleObjects/test1/test1.cpp diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/CMakeLists.txt index d035021..59d4cd8 100644 --- a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_waitformultipleobjectsex_test1 diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/test1.c b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/test1.c rename to src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test1/test1.cpp diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/CMakeLists.txt index ab47c6f..e970ec5 100644 --- a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_waitformultipleobjectsex_test2 diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.c b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.c rename to src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.cpp diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/CMakeLists.txt index 645b867..f1b76fb 100644 --- a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test3.c + test3.cpp ) add_executable(paltest_waitformultipleobjectsex_test3 diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/test3.c b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/test3.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/test3.c rename to src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test3/test3.cpp diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/CMakeLists.txt index 3cd7f72..815b2b0 100644 --- a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test4.c + test4.cpp ) add_executable(paltest_waitformultipleobjectsex_test4 diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/test4.c b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/test4.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/test4.c rename to src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test4/test4.cpp diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/CMakeLists.txt index 50147e9..730ec60 100644 --- a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - test5.c + test5.cpp ) add_executable(paltest_waitformultipleobjectsex_test5 @@ -20,7 +20,7 @@ target_link_libraries(paltest_waitformultipleobjectsex_test5 set(HELPERSOURCES - helper.c + helper.cpp ) add_executable(paltest_waitformultipleobjectsex_test5_helper diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/helper.c b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/helper.c deleted file mode 100644 index 274780a..0000000 --- a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/helper.c +++ /dev/null @@ -1,122 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: helper.c -** -** Purpose: This helper process sets up signals to communicate -** with the test thread in the parent process, and let the test -** thread signal this process when to exit. -** -** -**============================================================*/ - -#include "commonconsts.h" - -#include - -HANDLE hProcessStartEvent; -HANDLE hProcessReadyEvent; -HANDLE hProcessFinishEvent; -HANDLE hProcessCleanupEvent; - - -int __cdecl main(int argc, char *argv[]) -{ - - BOOL success = TRUE; /* assume success */ - DWORD dwRet; - DWORD dwProcessId; - char szEventName[MAX_LONGPATH]; - PWCHAR uniString; - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* Open the event to let test thread tell us to get started. */ - uniString = convert(szcHelperProcessStartEvName); - hProcessStartEvent = OpenEventW(EVENT_ALL_ACCESS, 0, uniString); - free(uniString); - if (!hProcessStartEvent) - { - Fail("helper.main: OpenEvent of '%S' failed (%u). " - "(the event should already exist!)\n", - szcHelperProcessStartEvName, GetLastError()); - } - - /* Wait for signal from test thread. */ - dwRet = WaitForSingleObject(hProcessStartEvent, TIMEOUT); - if (dwRet != WAIT_OBJECT_0) - { - Fail("helper.main: WaitForSingleObject '%s' failed\n" - "LastError:(%u)\n", szcHelperProcessStartEvName, GetLastError()); - } - - dwProcessId = GetCurrentProcessId(); - - if ( 0 >= dwProcessId ) - { - Fail ("helper.main: %s has invalid pid %d\n", argv[0], dwProcessId ); - } - - /* Open the event to tell test thread we are ready. */ - if (_snprintf(szEventName, MAX_LONGPATH-1, "%s%d", szcHelperProcessReadyEvName, dwProcessId) < 0) - { - Fail ("helper.main: Insufficient event name string length for pid=%d\n", dwProcessId); - } - - uniString = convert(szEventName); - - hProcessReadyEvent = OpenEventW(EVENT_ALL_ACCESS, 0, uniString); - free(uniString); - if (!hProcessReadyEvent) - { - Fail("helper.main: OpenEvent of '%s' failed (%u). " - "(the event should already exist!)\n", - szEventName, GetLastError()); - } - - /* Open the event to let test thread tell us to exit. */ - if (_snprintf(szEventName, MAX_LONGPATH-1, "%s%d", szcHelperProcessFinishEvName, dwProcessId) < 0) - { - Fail ("helper.main: Insufficient event name string length for pid=%d\n", dwProcessId); - } - - uniString = convert(szEventName); - - hProcessFinishEvent = OpenEventW(EVENT_ALL_ACCESS, 0, uniString); - free(uniString); - if (!hProcessFinishEvent) - { - Fail("helper.main: OpenEvent of '%s' failed LastError:(%u).\n", - szEventName, GetLastError()); - } - - /* Tell the test thread we are ready. */ - if (!SetEvent(hProcessReadyEvent)) - { - Fail("helper.main: SetEvent '%s' failed LastError:(%u)\n", - hProcessReadyEvent, GetLastError()); - } - - /* Wait for signal from test thread before exit. */ - dwRet = WaitForSingleObject(hProcessFinishEvent, TIMEOUT); - if (WAIT_OBJECT_0 != dwRet) - { - Fail("helper.main: WaitForSingleObject '%s' failed pid=%d\n" - "LastError:(%u)\n", - szcHelperProcessFinishEvName, dwProcessId, GetLastError()); - } - - PEDANTIC(CloseHandle, (hProcessStartEvent)); - PEDANTIC(CloseHandle, (hProcessReadyEvent)); - PEDANTIC(CloseHandle, (hProcessFinishEvent)); - - PAL_Terminate(); - - return success ? PASS : FAIL; -} diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/helper.cpp b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/helper.cpp new file mode 100644 index 0000000..caa0206 --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/helper.cpp @@ -0,0 +1,122 @@ +// 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. + +/*============================================================= +** +** Source: helper.c +** +** Purpose: This helper process sets up signals to communicate +** with the test thread in the parent process, and let the test +** thread signal this process when to exit. +** +** +**============================================================*/ + +#include "commonconsts.h" + +#include + +HANDLE hProcessStartEvent; +HANDLE hProcessReadyEvent; +HANDLE hProcessFinishEvent; +HANDLE hProcessCleanupEvent; + + +int __cdecl main(int argc, char *argv[]) +{ + + BOOL success = TRUE; /* assume success */ + DWORD dwRet; + DWORD dwProcessId; + char szEventName[MAX_LONGPATH]; + PWCHAR uniString; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* Open the event to let test thread tell us to get started. */ + uniString = convert(szcHelperProcessStartEvName); + hProcessStartEvent = OpenEventW(EVENT_ALL_ACCESS, 0, uniString); + free(uniString); + if (!hProcessStartEvent) + { + Fail("helper.main: OpenEvent of '%S' failed (%u). " + "(the event should already exist!)\n", + szcHelperProcessStartEvName, GetLastError()); + } + + /* Wait for signal from test thread. */ + dwRet = WaitForSingleObject(hProcessStartEvent, TIMEOUT); + if (dwRet != WAIT_OBJECT_0) + { + Fail("helper.main: WaitForSingleObject '%s' failed\n" + "LastError:(%u)\n", szcHelperProcessStartEvName, GetLastError()); + } + + dwProcessId = GetCurrentProcessId(); + + if ( 0 >= dwProcessId ) + { + Fail ("helper.main: %s has invalid pid %d\n", argv[0], dwProcessId ); + } + + /* Open the event to tell test thread we are ready. */ + if (sprintf_s(szEventName, MAX_LONGPATH-1, "%s%d", szcHelperProcessReadyEvName, dwProcessId) < 0) + { + Fail ("helper.main: Insufficient event name string length for pid=%d\n", dwProcessId); + } + + uniString = convert(szEventName); + + hProcessReadyEvent = OpenEventW(EVENT_ALL_ACCESS, 0, uniString); + free(uniString); + if (!hProcessReadyEvent) + { + Fail("helper.main: OpenEvent of '%s' failed (%u). " + "(the event should already exist!)\n", + szEventName, GetLastError()); + } + + /* Open the event to let test thread tell us to exit. */ + if (sprintf_s(szEventName, MAX_LONGPATH-1, "%s%d", szcHelperProcessFinishEvName, dwProcessId) < 0) + { + Fail ("helper.main: Insufficient event name string length for pid=%d\n", dwProcessId); + } + + uniString = convert(szEventName); + + hProcessFinishEvent = OpenEventW(EVENT_ALL_ACCESS, 0, uniString); + free(uniString); + if (!hProcessFinishEvent) + { + Fail("helper.main: OpenEvent of '%s' failed LastError:(%u).\n", + szEventName, GetLastError()); + } + + /* Tell the test thread we are ready. */ + if (!SetEvent(hProcessReadyEvent)) + { + Fail("helper.main: SetEvent '%s' failed LastError:(%u)\n", + hProcessReadyEvent, GetLastError()); + } + + /* Wait for signal from test thread before exit. */ + dwRet = WaitForSingleObject(hProcessFinishEvent, TIMEOUT); + if (WAIT_OBJECT_0 != dwRet) + { + Fail("helper.main: WaitForSingleObject '%s' failed pid=%d\n" + "LastError:(%u)\n", + szcHelperProcessFinishEvName, dwProcessId, GetLastError()); + } + + PEDANTIC(CloseHandle, (hProcessStartEvent)); + PEDANTIC(CloseHandle, (hProcessReadyEvent)); + PEDANTIC(CloseHandle, (hProcessFinishEvent)); + + PAL_Terminate(); + + return success ? PASS : FAIL; +} diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/test5.c b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/test5.c deleted file mode 100644 index d19978c..0000000 --- a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/test5.c +++ /dev/null @@ -1,506 +0,0 @@ -// 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. - -/*============================================================= -** -** Source: test5.c -** -** Purpose: Test the functionality of simultaneously waiting -** on multiple processes. Create the same number of helper -** processes and helper threads. -** Helper threads wait on helper processes to finish. -** Helper processes wait on the event signal from test -** thread before exit. -** The test thread can wake up one helper -** thread at a time by signaling the corresponding helper -** process to finish. -** The test thread can also wake up all helper threads at once -** by signaling help process 0 to exit. -** -** -**============================================================*/ - -#define UNICODE - -#include "commonconsts.h" - -#include - -/* The maximum number of objects a thread can wait is MAXIMUM_WAIT_OBJECTS. - The last helper thread in this test case will wait on all helper processes - plus a thread finish event so the maximum number of helper processes - can be created in this test case is (MAXIMUM_WAIT_OBJECTS-1). */ -#define MAX_HELPER_PROCESS (MAXIMUM_WAIT_OBJECTS-1) - -int MaxNumHelperProcess = MAX_HELPER_PROCESS; - -/* indicate how the test thread wake up helper thread. */ -typedef enum _TestCaseType { - WakeUpOneThread, /* wake up one helper thread at a time. */ - WakeUpAllThread /* wake up all helper threads at once */ -} TestCaseType; - -TestCaseType TestCase = WakeUpOneThread; - -/* When the test thread wakes up one thread at a time, - ThreadIndexOfThreadFinishEvent specifies the index of the thread that - should be waked up using hThreadFinishEvent instead of helper process. */ -DWORD ThreadIndexOfThreadFinishEvent = 0; - -struct helper_process_t -{ - PROCESS_INFORMATION pi; - HANDLE hProcessReadyEvent; - HANDLE hProcessFinishEvent; -} helper_process[MAX_HELPER_PROCESS]; - -HANDLE hProcessStartEvent; - -struct helper_thread_t -{ - HANDLE hThread; - DWORD dwThreadId; - HANDLE hThreadReadyEvent; - HANDLE hThreadFinishEvent; -} helper_thread[MAX_HELPER_PROCESS]; - -/* - * Entry Point for helper thread. - */ -DWORD PALAPI WaitForProcess(LPVOID lpParameter) -{ - DWORD index, i; - DWORD dwRet; - HANDLE handles[MAX_HELPER_PROCESS+1]; - - index = (DWORD) lpParameter; - - /* The helper thread 0 will wait for helper process 0, helper thread 1 will - wait for helper process 0 and 1, helper thread 2 will wait for helper - process 0, 1, and 2, and so on ..., and the last helper thread will wait - on all helper processes. - Each helper thread also waits on hThreadFinishEvent so that - it can exit without waiting on any process to finish. */ - - for (i = 0; i <= index; i++) - { - handles[i] = helper_process[i].pi.hProcess; - } - - handles[index+1] = helper_thread[index].hThreadFinishEvent; - - if(!SetEvent(helper_thread[index].hThreadReadyEvent)) - { - Fail("test5.WaitProcess: SetEvent of hThreadReadyEvent failed for thread %d. " - "GetLastError() returned %d.\n", index, - GetLastError()); - } - - dwRet = WaitForMultipleObjectsEx(index+2, &handles[0], FALSE, TIMEOUT, TRUE); - if (WakeUpAllThread == TestCase) - { - /* If the test thread signals helper process 0 to exit, all threads will be waked up, - and the return value must be (WAIT_OBJECT_0+0) because the handle of helper process 0 - is in handle[0]. */ - if (dwRet != (WAIT_OBJECT_0+0)) - { - Fail("test5.WaitForProcess: invalid return value %d for WakupAllThread from WaitForMultipleObjectsEx for thread %d\n" - "LastError:(%u)\n", - dwRet, index, - GetLastError()); - } - } - else if (WakeUpOneThread == TestCase) - { - /* If the test thread wakes up one helper thread at a time, - the return value must be either (WAIT_OBJECT_0+index) if the helper thread - wakes up because the corresponding help process exits, - or (index+1) if the helper thread wakes up because of hThreadReadyEvent. */ - if ((index != ThreadIndexOfThreadFinishEvent && dwRet != (WAIT_OBJECT_0+index)) || - (index == ThreadIndexOfThreadFinishEvent && dwRet != (index+1))) - { - Fail("test5.WaitForProcess: invalid return value %d for WakupOneThread from WaitForMultipleObjectsEx for thread %d\n" - "LastError:(%u)\n", - dwRet, index, - GetLastError()); - } - } - else - { - Fail("Unknown TestCase %d\n", TestCase); - } - return 0; -} - -/* - * Setup the helper processes and helper threads. - */ -void -Setup() -{ - - STARTUPINFO si; - DWORD dwRet; - int i; - - char szEventName[MAX_PATH]; - PWCHAR uniStringHelper; - PWCHAR uniString; - - /* Create the event to start helper process after it was created. */ - uniString = convert(szcHelperProcessStartEvName); - hProcessStartEvent = CreateEvent(NULL, TRUE, FALSE, uniString); - free(uniString); - if (!hProcessStartEvent) - { - Fail("test5.Setup: CreateEvent of '%s' failed. " - "GetLastError() returned %d.\n", szcHelperProcessStartEvName, - GetLastError()); - } - - /* Create the helper processes. */ - ZeroMemory( &si, sizeof(si) ); - si.cb = sizeof(si); - uniStringHelper = convert("helper"); - for (i = 0; i < MaxNumHelperProcess; i++) - { - ZeroMemory( &helper_process[i].pi, sizeof(PROCESS_INFORMATION)); - - if(!CreateProcess( NULL, uniStringHelper, NULL, NULL, - FALSE, 0, NULL, NULL, &si, &helper_process[i].pi)) - { - Fail("test5.Setup: CreateProcess failed to load executable for helper process %d. " - "GetLastError() returned %u.\n", - i, GetLastError()); - } - - /* Create the event to let helper process tell us it is ready. */ - if (_snprintf(szEventName, MAX_PATH-1, "%s%d", - szcHelperProcessReadyEvName, helper_process[i].pi.dwProcessId) < 0) - { - Fail ("test5.Setup: Insufficient event name string length for %s\n", szcHelperProcessReadyEvName); - } - - uniString = convert(szEventName); - - helper_process[i].hProcessReadyEvent = CreateEvent(NULL, FALSE, FALSE, uniString); - free(uniString); - if (!helper_process[i].hProcessReadyEvent) - { - Fail("test5.Setup: CreateEvent of '%s' failed. " - "GetLastError() returned %d.\n", szEventName, - GetLastError()); - } - - /* Create the event to tell helper process to exit. */ - if (_snprintf(szEventName, MAX_PATH-1, "%s%d", - szcHelperProcessFinishEvName, helper_process[i].pi.dwProcessId) < 0) - { - Fail ("test5.Setup: Insufficient event name string length for %s\n", szcHelperProcessFinishEvName); - } - - uniString = convert(szEventName); - - helper_process[i].hProcessFinishEvent = CreateEvent(NULL, TRUE, FALSE, uniString); - free(uniString); - if (!helper_process[i].hProcessFinishEvent) - { - Fail("test5.Setup: CreateEvent of '%s' failed. " - "GetLastError() returned %d.\n", szEventName, - GetLastError()); - } - - } - free(uniStringHelper); - - /* Signal all helper processes to start. */ - if (!SetEvent(hProcessStartEvent)) - { - Fail("test5.Setup: SetEvent '%s' failed\n", - "LastError:(%u)\n", - szcHelperProcessStartEvName, GetLastError()); - } - - /* Wait for ready signals from all helper processes. */ - for (i = 0; i < MaxNumHelperProcess; i++) - { - dwRet = WaitForSingleObject(helper_process[i].hProcessReadyEvent, TIMEOUT); - if (dwRet != WAIT_OBJECT_0) - { - Fail("test5.Setup: WaitForSingleObject %s failed for helper process %d\n" - "LastError:(%u)\n", - szcHelperProcessReadyEvName, i, GetLastError()); - } - } - - /* Create the same number of helper threads as helper processes. */ - for (i = 0; i < MaxNumHelperProcess; i++) - { - /* Create the event to let helper thread tell us it is ready. */ - helper_thread[i].hThreadReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if (!helper_thread[i].hThreadReadyEvent) - { - Fail("test5.Setup: CreateEvent of hThreadReadyEvent failed for thread %d\n" - "LastError:(%u)\n", i, GetLastError()); - } - - /* Create the event to tell helper thread to exit without waiting for helper process. */ - helper_thread[i].hThreadFinishEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if (!helper_thread[i].hThreadFinishEvent) - { - Fail("test5.Setup: CreateEvent of hThreadFinishEvent failed for thread %d\n" - "LastError:(%u)\n", i, GetLastError()); - } - - /* Create the helper thread. */ - helper_thread[i].hThread = CreateThread( NULL, - 0, - (LPTHREAD_START_ROUTINE)WaitForProcess, - (LPVOID)i, - 0, - &helper_thread[i].dwThreadId); - if (NULL == helper_thread[i].hThread) - { - Fail("test5.Setup: Unable to create the helper thread %d\n" - "LastError:(%u)\n", i, GetLastError()); - } - } - - /* Wait for ready signals from all helper threads. */ - for (i = 0; i < MaxNumHelperProcess; i++) - { - dwRet = WaitForSingleObject(helper_thread[i].hThreadReadyEvent, TIMEOUT); - if (dwRet != WAIT_OBJECT_0) - { - Fail("test5.Setup: WaitForSingleObject hThreadReadyEvent for thread %d\n" - "LastError:(%u)\n", i, GetLastError()); - } - } -} - -/* - * Cleanup the helper processes and helper threads. - */ -DWORD -Cleanup() -{ - DWORD dwExitCode; - DWORD dwRet; - int i; - - /* Wait for all helper process to finish and close their handles - and associated events. */ - for (i = 0; i < MaxNumHelperProcess; i++) - { - - /* wait for the child process to complete */ - dwRet = WaitForSingleObject ( helper_process[i].pi.hProcess, TIMEOUT ); - if (WAIT_OBJECT_0 != dwRet) - { - Fail("test5.Cleanup: WaitForSingleObject hThreadReadyEvent failed for thread %d\n" - "LastError:(%u)\n", i, GetLastError()); - } - - /* check the exit code from the process */ - if (!GetExitCodeProcess(helper_process[i].pi.hProcess, &dwExitCode)) - { - Trace( "test5.Cleanup: GetExitCodeProcess %d call failed LastError:(%u)\n", - i, GetLastError()); - dwExitCode = FAIL; - } - PEDANTIC(CloseHandle, (helper_process[i].pi.hThread)); - PEDANTIC(CloseHandle, (helper_process[i].pi.hProcess)); - PEDANTIC(CloseHandle, (helper_process[i].hProcessReadyEvent)); - PEDANTIC(CloseHandle, (helper_process[i].hProcessFinishEvent)); - } - - /* Close all helper threads' handles */ - for (i = 0; i < MaxNumHelperProcess; i++) - { - PEDANTIC(CloseHandle, (helper_thread[i].hThread)); - PEDANTIC(CloseHandle, (helper_thread[i].hThreadReadyEvent)); - PEDANTIC(CloseHandle, (helper_thread[i].hThreadFinishEvent)); - } - - /* Close all process start event. */ - PEDANTIC(CloseHandle, (hProcessStartEvent)); - - return dwExitCode; -} - -/* - * In this test case, the test thread will signal one helper - * process to exit at a time starting from the last helper - * process and then wait for the corresponding helper thread to exit. - * The ThreadIndexOfThreadFinishEvent specifies the index of the thread that - * should be waked up using hThreadFinishEvent instead of helper process. - */ -void -TestWakeupOneThread() -{ - DWORD dwRet; - int i; - - TestCase = WakeUpOneThread; - - if (((LONG)ThreadIndexOfThreadFinishEvent) < 0 || - ThreadIndexOfThreadFinishEvent >= MAX_HELPER_PROCESS) - Fail("test5.TestWaitOnOneThread: Invalid ThreadIndexOfThreadFinishEvent %d\n", ThreadIndexOfThreadFinishEvent); - - /* Since helper thread 0 waits on helper process 0, - thread 1 waits on on process 0, and 1, - thread 2 waits on process 0, 1, and 2, and so on ..., - and the last helper thread will wait on all helper processes, - the helper thread can be waked up one at a time by - waking up the help process one at a time starting from the - last helper process. */ - for (i = MaxNumHelperProcess-1; i >= 0; i--) - { - /* make sure the helper thread has not exited yet. */ - dwRet = WaitForSingleObject(helper_thread[i].hThread, 0); - if (WAIT_TIMEOUT != dwRet) - { - Fail("test5.TestWaitOnOneThread: helper thread %d already exited %d\n", i); - } - - /* Decide how to wakeup the helper thread: - using event or using helper process. */ - if (i == ThreadIndexOfThreadFinishEvent) - { - if (!SetEvent(helper_thread[i].hThreadFinishEvent)) - { - Fail("test5.TestWaitOnOneThread: SetEvent hThreadFinishEvent failed for thread %d\n", - "LastError:(%u)\n", i, GetLastError()); - } - } - else - { - if (!SetEvent(helper_process[i].hProcessFinishEvent)) - { - Fail("test5.TestWaitOnOneThread: SetEvent %s%d failed for helper process %d\n", - "LastError:(%u)\n", - szcHelperProcessFinishEvName, helper_process[i].pi.dwProcessId, i, - GetLastError()); - } - } - - dwRet = WaitForSingleObject(helper_thread[i].hThread, TIMEOUT); - if (WAIT_OBJECT_0 != dwRet) - { - Fail("test5.TestWaitOnOneThread: WaitForSingleObject helper thread %d" - "LastError:(%u)\n", - i, GetLastError()); - } - } - - /* Finally, need to wake up the helper process which the test thread - skips waking up in the last loop. */ - if (!SetEvent(helper_process[ThreadIndexOfThreadFinishEvent].hProcessFinishEvent)) - { - Fail("test5.TestWaitOnOneThread: SetEvent %s%d failed\n", - "LastError:(%u)\n", - szcHelperProcessFinishEvName, helper_process[ThreadIndexOfThreadFinishEvent].pi.dwProcessId, - GetLastError()); - } -} - -/* - * In this test case, the test thread will signal the helper - * process 0 to exit. Since all helper threads wait on process 0, - * all helper threads will wake up and exit, and the test thread - * will wait for all of them to exit. - */ -void -TestWakeupAllThread() -{ - DWORD dwRet; - int i; - - TestCase = WakeUpAllThread; - - /* make sure none of the helper thread exits. */ - for (i = 0; i < MaxNumHelperProcess; i++) - { - dwRet = WaitForSingleObject(helper_thread[i].hThread, 0); - if (WAIT_TIMEOUT != dwRet) - { - Fail("test5.TestWaitOnAllThread: helper thread %d already exited %d\n", i); - } - } - - /* Signal helper process 0 to exit. */ - if (!SetEvent(helper_process[0].hProcessFinishEvent)) - { - Fail("test5.TestWaitOnAllThread: SetEvent %s%d failed\n", - "LastError:(%u)\n", - szcHelperProcessFinishEvName, helper_process[0].pi.dwProcessId, - GetLastError()); - } - - /* Wait for all helper threads to exit. */ - for (i = 0; i < MaxNumHelperProcess; i++) - { - - dwRet = WaitForSingleObject(helper_thread[i].hThread, TIMEOUT); - if (WAIT_OBJECT_0 != dwRet) - { - Fail("test5.TestWaitOnAllThread: WaitForSingleObject failed for helper thread %d\n" - "LastError:(%u)\n", - i, GetLastError()); - } - } - - /* Signal the rest of helper processes to exit. */ - for (i = 1; i < MaxNumHelperProcess; i++) - { - if (!SetEvent(helper_process[i].hProcessFinishEvent)) - { - Fail("test5.TestWaitOnAllThread: SetEvent %s%d failed\n", - "LastError:(%u)\n", - szcHelperProcessFinishEvName, helper_process[i].pi.dwProcessId, - GetLastError()); - } - } -} - -int __cdecl main(int argc, char *argv[]) -{ - DWORD dwExitCode; - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - switch (argc) - { - case 1: - MaxNumHelperProcess = MAX_HELPER_PROCESS; - break; - case 2: - MaxNumHelperProcess = atol(argv[1]); - break; - default: - Fail("Invalid number of arguments\n"); - } - - if (MaxNumHelperProcess < 1 || - MaxNumHelperProcess > MAX_HELPER_PROCESS) - Fail("test5.main: Invalid MaxNumHelperProcess %d\n", MaxNumHelperProcess); - - Setup(); - ThreadIndexOfThreadFinishEvent = 3; - TestWakeupOneThread(); - dwExitCode = Cleanup(); - - if (PASS == dwExitCode) - { - Setup(); - TestWakeupAllThread(); - dwExitCode = Cleanup(); - } - - PAL_TerminateEx(dwExitCode); - return dwExitCode; -} diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/test5.cpp b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/test5.cpp new file mode 100644 index 0000000..a021649 --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test5/test5.cpp @@ -0,0 +1,506 @@ +// 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. + +/*============================================================= +** +** Source: test5.c +** +** Purpose: Test the functionality of simultaneously waiting +** on multiple processes. Create the same number of helper +** processes and helper threads. +** Helper threads wait on helper processes to finish. +** Helper processes wait on the event signal from test +** thread before exit. +** The test thread can wake up one helper +** thread at a time by signaling the corresponding helper +** process to finish. +** The test thread can also wake up all helper threads at once +** by signaling help process 0 to exit. +** +** +**============================================================*/ + +#define UNICODE + +#include "commonconsts.h" + +#include + +/* The maximum number of objects a thread can wait is MAXIMUM_WAIT_OBJECTS. + The last helper thread in this test case will wait on all helper processes + plus a thread finish event so the maximum number of helper processes + can be created in this test case is (MAXIMUM_WAIT_OBJECTS-1). */ +#define MAX_HELPER_PROCESS (MAXIMUM_WAIT_OBJECTS-1) + +int MaxNumHelperProcess = MAX_HELPER_PROCESS; + +/* indicate how the test thread wake up helper thread. */ +typedef enum _TestCaseType { + WakeUpOneThread, /* wake up one helper thread at a time. */ + WakeUpAllThread /* wake up all helper threads at once */ +} TestCaseType; + +TestCaseType TestCase = WakeUpOneThread; + +/* When the test thread wakes up one thread at a time, + ThreadIndexOfThreadFinishEvent specifies the index of the thread that + should be waked up using hThreadFinishEvent instead of helper process. */ +DWORD ThreadIndexOfThreadFinishEvent = 0; + +struct helper_process_t +{ + PROCESS_INFORMATION pi; + HANDLE hProcessReadyEvent; + HANDLE hProcessFinishEvent; +} helper_process[MAX_HELPER_PROCESS]; + +HANDLE hProcessStartEvent; + +struct helper_thread_t +{ + HANDLE hThread; + DWORD dwThreadId; + HANDLE hThreadReadyEvent; + HANDLE hThreadFinishEvent; +} helper_thread[MAX_HELPER_PROCESS]; + +/* + * Entry Point for helper thread. + */ +DWORD PALAPI WaitForProcess(LPVOID lpParameter) +{ + DWORD index, i; + DWORD dwRet; + HANDLE handles[MAX_HELPER_PROCESS+1]; + + index = (DWORD) lpParameter; + + /* The helper thread 0 will wait for helper process 0, helper thread 1 will + wait for helper process 0 and 1, helper thread 2 will wait for helper + process 0, 1, and 2, and so on ..., and the last helper thread will wait + on all helper processes. + Each helper thread also waits on hThreadFinishEvent so that + it can exit without waiting on any process to finish. */ + + for (i = 0; i <= index; i++) + { + handles[i] = helper_process[i].pi.hProcess; + } + + handles[index+1] = helper_thread[index].hThreadFinishEvent; + + if(!SetEvent(helper_thread[index].hThreadReadyEvent)) + { + Fail("test5.WaitProcess: SetEvent of hThreadReadyEvent failed for thread %d. " + "GetLastError() returned %d.\n", index, + GetLastError()); + } + + dwRet = WaitForMultipleObjectsEx(index+2, &handles[0], FALSE, TIMEOUT, TRUE); + if (WakeUpAllThread == TestCase) + { + /* If the test thread signals helper process 0 to exit, all threads will be waked up, + and the return value must be (WAIT_OBJECT_0+0) because the handle of helper process 0 + is in handle[0]. */ + if (dwRet != (WAIT_OBJECT_0+0)) + { + Fail("test5.WaitForProcess: invalid return value %d for WakupAllThread from WaitForMultipleObjectsEx for thread %d\n" + "LastError:(%u)\n", + dwRet, index, + GetLastError()); + } + } + else if (WakeUpOneThread == TestCase) + { + /* If the test thread wakes up one helper thread at a time, + the return value must be either (WAIT_OBJECT_0+index) if the helper thread + wakes up because the corresponding help process exits, + or (index+1) if the helper thread wakes up because of hThreadReadyEvent. */ + if ((index != ThreadIndexOfThreadFinishEvent && dwRet != (WAIT_OBJECT_0+index)) || + (index == ThreadIndexOfThreadFinishEvent && dwRet != (index+1))) + { + Fail("test5.WaitForProcess: invalid return value %d for WakupOneThread from WaitForMultipleObjectsEx for thread %d\n" + "LastError:(%u)\n", + dwRet, index, + GetLastError()); + } + } + else + { + Fail("Unknown TestCase %d\n", TestCase); + } + return 0; +} + +/* + * Setup the helper processes and helper threads. + */ +void +Setup() +{ + + STARTUPINFO si; + DWORD dwRet; + int i; + + char szEventName[MAX_PATH]; + PWCHAR uniStringHelper; + PWCHAR uniString; + + /* Create the event to start helper process after it was created. */ + uniString = convert(szcHelperProcessStartEvName); + hProcessStartEvent = CreateEvent(NULL, TRUE, FALSE, uniString); + free(uniString); + if (!hProcessStartEvent) + { + Fail("test5.Setup: CreateEvent of '%s' failed. " + "GetLastError() returned %d.\n", szcHelperProcessStartEvName, + GetLastError()); + } + + /* Create the helper processes. */ + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + uniStringHelper = convert("helper"); + for (i = 0; i < MaxNumHelperProcess; i++) + { + ZeroMemory( &helper_process[i].pi, sizeof(PROCESS_INFORMATION)); + + if(!CreateProcess( NULL, uniStringHelper, NULL, NULL, + FALSE, 0, NULL, NULL, &si, &helper_process[i].pi)) + { + Fail("test5.Setup: CreateProcess failed to load executable for helper process %d. " + "GetLastError() returned %u.\n", + i, GetLastError()); + } + + /* Create the event to let helper process tell us it is ready. */ + if (sprintf_s(szEventName, MAX_PATH-1, "%s%d", + szcHelperProcessReadyEvName, helper_process[i].pi.dwProcessId) < 0) + { + Fail ("test5.Setup: Insufficient event name string length for %s\n", szcHelperProcessReadyEvName); + } + + uniString = convert(szEventName); + + helper_process[i].hProcessReadyEvent = CreateEvent(NULL, FALSE, FALSE, uniString); + free(uniString); + if (!helper_process[i].hProcessReadyEvent) + { + Fail("test5.Setup: CreateEvent of '%s' failed. " + "GetLastError() returned %d.\n", szEventName, + GetLastError()); + } + + /* Create the event to tell helper process to exit. */ + if (sprintf_s(szEventName, MAX_PATH-1, "%s%d", + szcHelperProcessFinishEvName, helper_process[i].pi.dwProcessId) < 0) + { + Fail ("test5.Setup: Insufficient event name string length for %s\n", szcHelperProcessFinishEvName); + } + + uniString = convert(szEventName); + + helper_process[i].hProcessFinishEvent = CreateEvent(NULL, TRUE, FALSE, uniString); + free(uniString); + if (!helper_process[i].hProcessFinishEvent) + { + Fail("test5.Setup: CreateEvent of '%s' failed. " + "GetLastError() returned %d.\n", szEventName, + GetLastError()); + } + + } + free(uniStringHelper); + + /* Signal all helper processes to start. */ + if (!SetEvent(hProcessStartEvent)) + { + Fail("test5.Setup: SetEvent '%s' failed\n", + "LastError:(%u)\n", + szcHelperProcessStartEvName, GetLastError()); + } + + /* Wait for ready signals from all helper processes. */ + for (i = 0; i < MaxNumHelperProcess; i++) + { + dwRet = WaitForSingleObject(helper_process[i].hProcessReadyEvent, TIMEOUT); + if (dwRet != WAIT_OBJECT_0) + { + Fail("test5.Setup: WaitForSingleObject %s failed for helper process %d\n" + "LastError:(%u)\n", + szcHelperProcessReadyEvName, i, GetLastError()); + } + } + + /* Create the same number of helper threads as helper processes. */ + for (i = 0; i < MaxNumHelperProcess; i++) + { + /* Create the event to let helper thread tell us it is ready. */ + helper_thread[i].hThreadReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!helper_thread[i].hThreadReadyEvent) + { + Fail("test5.Setup: CreateEvent of hThreadReadyEvent failed for thread %d\n" + "LastError:(%u)\n", i, GetLastError()); + } + + /* Create the event to tell helper thread to exit without waiting for helper process. */ + helper_thread[i].hThreadFinishEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!helper_thread[i].hThreadFinishEvent) + { + Fail("test5.Setup: CreateEvent of hThreadFinishEvent failed for thread %d\n" + "LastError:(%u)\n", i, GetLastError()); + } + + /* Create the helper thread. */ + helper_thread[i].hThread = CreateThread( NULL, + 0, + (LPTHREAD_START_ROUTINE)WaitForProcess, + (LPVOID)i, + 0, + &helper_thread[i].dwThreadId); + if (NULL == helper_thread[i].hThread) + { + Fail("test5.Setup: Unable to create the helper thread %d\n" + "LastError:(%u)\n", i, GetLastError()); + } + } + + /* Wait for ready signals from all helper threads. */ + for (i = 0; i < MaxNumHelperProcess; i++) + { + dwRet = WaitForSingleObject(helper_thread[i].hThreadReadyEvent, TIMEOUT); + if (dwRet != WAIT_OBJECT_0) + { + Fail("test5.Setup: WaitForSingleObject hThreadReadyEvent for thread %d\n" + "LastError:(%u)\n", i, GetLastError()); + } + } +} + +/* + * Cleanup the helper processes and helper threads. + */ +DWORD +Cleanup() +{ + DWORD dwExitCode; + DWORD dwRet; + int i; + + /* Wait for all helper process to finish and close their handles + and associated events. */ + for (i = 0; i < MaxNumHelperProcess; i++) + { + + /* wait for the child process to complete */ + dwRet = WaitForSingleObject ( helper_process[i].pi.hProcess, TIMEOUT ); + if (WAIT_OBJECT_0 != dwRet) + { + Fail("test5.Cleanup: WaitForSingleObject hThreadReadyEvent failed for thread %d\n" + "LastError:(%u)\n", i, GetLastError()); + } + + /* check the exit code from the process */ + if (!GetExitCodeProcess(helper_process[i].pi.hProcess, &dwExitCode)) + { + Trace( "test5.Cleanup: GetExitCodeProcess %d call failed LastError:(%u)\n", + i, GetLastError()); + dwExitCode = FAIL; + } + PEDANTIC(CloseHandle, (helper_process[i].pi.hThread)); + PEDANTIC(CloseHandle, (helper_process[i].pi.hProcess)); + PEDANTIC(CloseHandle, (helper_process[i].hProcessReadyEvent)); + PEDANTIC(CloseHandle, (helper_process[i].hProcessFinishEvent)); + } + + /* Close all helper threads' handles */ + for (i = 0; i < MaxNumHelperProcess; i++) + { + PEDANTIC(CloseHandle, (helper_thread[i].hThread)); + PEDANTIC(CloseHandle, (helper_thread[i].hThreadReadyEvent)); + PEDANTIC(CloseHandle, (helper_thread[i].hThreadFinishEvent)); + } + + /* Close all process start event. */ + PEDANTIC(CloseHandle, (hProcessStartEvent)); + + return dwExitCode; +} + +/* + * In this test case, the test thread will signal one helper + * process to exit at a time starting from the last helper + * process and then wait for the corresponding helper thread to exit. + * The ThreadIndexOfThreadFinishEvent specifies the index of the thread that + * should be waked up using hThreadFinishEvent instead of helper process. + */ +void +TestWakeupOneThread() +{ + DWORD dwRet; + int i; + + TestCase = WakeUpOneThread; + + if (((LONG)ThreadIndexOfThreadFinishEvent) < 0 || + ThreadIndexOfThreadFinishEvent >= MAX_HELPER_PROCESS) + Fail("test5.TestWaitOnOneThread: Invalid ThreadIndexOfThreadFinishEvent %d\n", ThreadIndexOfThreadFinishEvent); + + /* Since helper thread 0 waits on helper process 0, + thread 1 waits on on process 0, and 1, + thread 2 waits on process 0, 1, and 2, and so on ..., + and the last helper thread will wait on all helper processes, + the helper thread can be waked up one at a time by + waking up the help process one at a time starting from the + last helper process. */ + for (i = MaxNumHelperProcess-1; i >= 0; i--) + { + /* make sure the helper thread has not exited yet. */ + dwRet = WaitForSingleObject(helper_thread[i].hThread, 0); + if (WAIT_TIMEOUT != dwRet) + { + Fail("test5.TestWaitOnOneThread: helper thread %d already exited %d\n", i); + } + + /* Decide how to wakeup the helper thread: + using event or using helper process. */ + if (i == ThreadIndexOfThreadFinishEvent) + { + if (!SetEvent(helper_thread[i].hThreadFinishEvent)) + { + Fail("test5.TestWaitOnOneThread: SetEvent hThreadFinishEvent failed for thread %d\n", + "LastError:(%u)\n", i, GetLastError()); + } + } + else + { + if (!SetEvent(helper_process[i].hProcessFinishEvent)) + { + Fail("test5.TestWaitOnOneThread: SetEvent %s%d failed for helper process %d\n", + "LastError:(%u)\n", + szcHelperProcessFinishEvName, helper_process[i].pi.dwProcessId, i, + GetLastError()); + } + } + + dwRet = WaitForSingleObject(helper_thread[i].hThread, TIMEOUT); + if (WAIT_OBJECT_0 != dwRet) + { + Fail("test5.TestWaitOnOneThread: WaitForSingleObject helper thread %d" + "LastError:(%u)\n", + i, GetLastError()); + } + } + + /* Finally, need to wake up the helper process which the test thread + skips waking up in the last loop. */ + if (!SetEvent(helper_process[ThreadIndexOfThreadFinishEvent].hProcessFinishEvent)) + { + Fail("test5.TestWaitOnOneThread: SetEvent %s%d failed\n", + "LastError:(%u)\n", + szcHelperProcessFinishEvName, helper_process[ThreadIndexOfThreadFinishEvent].pi.dwProcessId, + GetLastError()); + } +} + +/* + * In this test case, the test thread will signal the helper + * process 0 to exit. Since all helper threads wait on process 0, + * all helper threads will wake up and exit, and the test thread + * will wait for all of them to exit. + */ +void +TestWakeupAllThread() +{ + DWORD dwRet; + int i; + + TestCase = WakeUpAllThread; + + /* make sure none of the helper thread exits. */ + for (i = 0; i < MaxNumHelperProcess; i++) + { + dwRet = WaitForSingleObject(helper_thread[i].hThread, 0); + if (WAIT_TIMEOUT != dwRet) + { + Fail("test5.TestWaitOnAllThread: helper thread %d already exited %d\n", i); + } + } + + /* Signal helper process 0 to exit. */ + if (!SetEvent(helper_process[0].hProcessFinishEvent)) + { + Fail("test5.TestWaitOnAllThread: SetEvent %s%d failed\n", + "LastError:(%u)\n", + szcHelperProcessFinishEvName, helper_process[0].pi.dwProcessId, + GetLastError()); + } + + /* Wait for all helper threads to exit. */ + for (i = 0; i < MaxNumHelperProcess; i++) + { + + dwRet = WaitForSingleObject(helper_thread[i].hThread, TIMEOUT); + if (WAIT_OBJECT_0 != dwRet) + { + Fail("test5.TestWaitOnAllThread: WaitForSingleObject failed for helper thread %d\n" + "LastError:(%u)\n", + i, GetLastError()); + } + } + + /* Signal the rest of helper processes to exit. */ + for (i = 1; i < MaxNumHelperProcess; i++) + { + if (!SetEvent(helper_process[i].hProcessFinishEvent)) + { + Fail("test5.TestWaitOnAllThread: SetEvent %s%d failed\n", + "LastError:(%u)\n", + szcHelperProcessFinishEvName, helper_process[i].pi.dwProcessId, + GetLastError()); + } + } +} + +int __cdecl main(int argc, char *argv[]) +{ + DWORD dwExitCode; + + if(0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + switch (argc) + { + case 1: + MaxNumHelperProcess = MAX_HELPER_PROCESS; + break; + case 2: + MaxNumHelperProcess = atol(argv[1]); + break; + default: + Fail("Invalid number of arguments\n"); + } + + if (MaxNumHelperProcess < 1 || + MaxNumHelperProcess > MAX_HELPER_PROCESS) + Fail("test5.main: Invalid MaxNumHelperProcess %d\n", MaxNumHelperProcess); + + Setup(); + ThreadIndexOfThreadFinishEvent = 3; + TestWakeupOneThread(); + dwExitCode = Cleanup(); + + if (PASS == dwExitCode) + { + Setup(); + TestWakeupAllThread(); + dwExitCode = Cleanup(); + } + + PAL_TerminateEx(dwExitCode); + return dwExitCode; +} diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/CMakeLists.txt index ce75cad..0133182 100644 --- a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(TESTSOURCES - test6.c + test6.cpp ) add_executable(paltest_waitformultipleobjectsex_test6 @@ -20,7 +20,7 @@ target_link_libraries(paltest_waitformultipleobjectsex_test6 set(HELPERSOURCES - child6.c + child6.cpp ) add_executable(paltest_waitformultipleobjectsex_test6_child diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/child6.c b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/child6.c deleted file mode 100644 index 1a95815..0000000 --- a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test6/child6.c +++ /dev/null @@ -1,211 +0,0 @@ -// 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. - -/*============================================================ -** -** Source: child6.c -** -** Purpose: Test for WaitForMultipleObjectsEx in multiple -** scenarios - child process -** -** -**=========================================================*/ - -#include - -int __cdecl main(int argc, char **argv) -{ - int i, iRet; - BOOL bRet; - BOOL bNamedEvent = 0; - BOOL bMutex = 0; - BOOL bMutexAndNamedEvent = 0; - BOOL bSemaphore = 0; - DWORD dwRet; - HANDLE hNamedEvent; - HANDLE hMutex; - char szTestName[256]; - WCHAR wszTestName[256] = { 0 }; - char szEventName[128] = { 0 }; - char szMutexName[128] = { 0 }; - char szSemName[128] = { 0 }; - WCHAR wszEventName[128]; - WCHAR wszMutexName[128]; - WCHAR wszSemName[128]; - DWORD iExitCode = 0; - HANDLE hSemaphore; - - if(0 != (PAL_Initialize(argc, argv))) - { - return ( FAIL ); - } - - Trace("[child] Starting\n"); - - for (i=1; i + +int __cdecl main(int argc, char **argv) +{ + int i, iRet; + BOOL bRet; + BOOL bNamedEvent = 0; + BOOL bMutex = 0; + BOOL bMutexAndNamedEvent = 0; + BOOL bSemaphore = 0; + DWORD dwRet; + HANDLE hNamedEvent; + HANDLE hMutex; + char szTestName[256]; + WCHAR wszTestName[256] = { 0 }; + char szEventName[128] = { 0 }; + char szMutexName[128] = { 0 }; + char szSemName[128] = { 0 }; + WCHAR wszEventName[128]; + WCHAR wszMutexName[128]; + WCHAR wszSemName[128]; + DWORD iExitCode = 0; + HANDLE hSemaphore; + + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + Trace("[child] Starting\n"); + + for (i=1; i - -#define MAX_COUNT 10000 -#define MAX_THREADS 256 - -BOOL g_bMutex = 0; -BOOL g_bEvent = 0; -BOOL g_bNamedEvent = 0; -BOOL g_bSemaphore = 0; -BOOL g_bProcess = 0; -BOOL g_bLocalWaitAll = 0; -BOOL g_bRemoteWaitAll = 0; -BOOL g_bRandom = 0; - -int iCount = 1; -int iThreads = 1; -HANDLE hThreads[MAX_THREADS]; - -#ifndef MIN -#define MIN(a,b) (((a)<(b)) ? (a) : (b)) -#endif - -DWORD PALAPI EventTestThread(PVOID pArg) -{ - BOOL bRet; - DWORD dwRet; - HANDLE hEvent[2]; - HANDLE (*prgHandles)[] = (HANDLE (*)[])pArg; - - Trace("[EventTestThread] Starting\n"); - - bRet = DuplicateHandle(GetCurrentProcess(), (*prgHandles)[0], GetCurrentProcess(), - &hEvent[0], 0, FALSE, DUPLICATE_SAME_ACCESS); - bRet &= DuplicateHandle(GetCurrentProcess(), (*prgHandles)[1], GetCurrentProcess(), - &hEvent[1], 0, FALSE, DUPLICATE_SAME_ACCESS); - if (FALSE == bRet) - { - Fail("[EventTestThread] Failed to duplicate handles\n"); - } - - Sleep(1000); - bRet = SetEvent(hEvent[1]); - if (FALSE == bRet) - { - Fail("SetEvent failed\n"); - Fail("[EventTestThread] SetEvent failed [GetLastError()=%u]\n", - GetLastError()); - } - - dwRet = WaitForSingleObject(hEvent[1], INFINITE); - if (WAIT_FAILED == dwRet) - { - Fail("[EventTestThread] WaitForMultipleObjects failed [GetLastError()=%u]\n", - GetLastError()); - } - - Sleep(1000); - bRet = SetEvent(hEvent[0]); - if (FALSE == bRet) - { - Fail("[EventTestThread] SetEvent failed [GetLastError()=%u]\n", - GetLastError()); - } - - Sleep(1000); - bRet = SetEvent(hEvent[1]); - if (FALSE == bRet) - { - Fail("[EventTestThread] SetEvent failed [GetLastError()=%u]\n", - GetLastError()); - } - - CloseHandle(hEvent[0]); - CloseHandle(hEvent[1]); - - Trace("[EventTestThread] Done\n"); - return 0; -} - -DWORD PALAPI MutexTestThread(PVOID pArg) -{ - BOOL bRet; - DWORD dwRet; - HANDLE hMutex; - - Trace("[MutexTestThread] Starting\n"); - - bRet = DuplicateHandle(GetCurrentProcess(), (HANDLE)pArg, GetCurrentProcess(), &hMutex, - 0, FALSE, DUPLICATE_SAME_ACCESS); - if (FALSE == bRet) - { - Fail("[EventTestThread] DuplicateHandle failed [GetLastError()=%u]\n", - GetLastError()); - } - - dwRet = WaitForSingleObject(hMutex, INFINITE); - if (WAIT_FAILED == dwRet) - { - Fail("[EventTestThread] WaitForMultipleObjects failed [GetLastError()=%u]\n", - GetLastError()); - } - - Sleep(1000); - CloseHandle(hMutex); - - Trace("[MutexTestThread] Done\n"); - - return 0; -} - -DWORD PALAPI TestThread(PVOID pArg) -{ - BOOL bRet; - DWORD dwRet; - PROCESS_INFORMATION pi; - STARTUPINFO si; - HANDLE hNamedEvent; - HANDLE hEvent[2] = { 0, 0 }; - HANDLE hMutex = 0; - HANDLE hSemaphore = 0; - HANDLE hObjs[2]; - DWORD dwThreadNum; - DWORD dwSlaveThreadTid = 0; - HANDLE hThread; - int i, iCnt, iRet; - char szTestName[128]; - char szCmd[128]; - char szEventName[128] = { 0 }; - char szMutexName[128] = { 0 }; - char szSemName[128] = { 0 }; - WCHAR wszEventName[128] = { 0 }; - WCHAR wszMutexName[128] = { 0 }; - WCHAR wszSemName[128] = { 0 }; - BOOL bMutex = g_bMutex; - BOOL bEvent = g_bEvent; - BOOL bNamedEvent = g_bNamedEvent; - BOOL bSemaphore = g_bSemaphore; - BOOL bProcess = g_bProcess; - BOOL bLocalWaitAll = g_bLocalWaitAll; - BOOL bRemoteWaitAll = g_bRemoteWaitAll; - int iDesiredExitCode; - - dwThreadNum = (DWORD)pArg; - - _snprintf (szTestName, 128, "Test6_%u", dwThreadNum); - szTestName[127] = 0; - - _snprintf(szEventName, 128, "%s_Event", szTestName); - szEventName[127] = 0; - _snprintf(szMutexName, 128, "%s_Mutex", szTestName); - szMutexName[127] = 0; - _snprintf(szSemName, 128, "%s_Semaphore", szTestName); - szSemName[127] = 0; - - iRet = MultiByteToWideChar(CP_ACP, 0, szEventName, strlen(szEventName)+1, wszEventName, 128); - iRet &= MultiByteToWideChar(CP_ACP, 0, szMutexName, strlen(szMutexName)+1, wszMutexName, 128); - iRet &= MultiByteToWideChar(CP_ACP, 0, szSemName, strlen(szSemName)+1, wszSemName, 128); - - if (0 == iRet) - { - Fail("[TestThread] Failed to convert strings\n"); - } - - Trace("[TestThread] TestName=%s Event: %S, Mutex: %S, Semaphore = %S\n", - szTestName, wszEventName, wszMutexName, wszSemName); - - hEvent[0] = CreateEventA(NULL, FALSE, FALSE, NULL); - hEvent[1] = CreateEventA(NULL, FALSE, FALSE, NULL); - - hNamedEvent = CreateEventW(NULL, FALSE, FALSE, wszEventName); - hMutex = CreateMutexW(NULL, FALSE, wszMutexName); - hSemaphore = CreateSemaphoreW(NULL, 0, 256, wszSemName); - - if (NULL == hEvent[0] || NULL == hEvent[1] || NULL == hMutex || - NULL == hNamedEvent || NULL == hSemaphore) - { - Fail("[TestThread] Failed to create objects " - "[hNamedEvent=%p hMutex=%p hSemaphore=%p]\n", - (VOID*)hNamedEvent, (VOID*)hMutex, (VOID*)hSemaphore); - } - - for (iCnt=0; iCnt i+1)) - { - i++; - iCnt = atoi(argv[i]); - if (iCnt > 0 && iCnt < MAX_COUNT) - { - iCount = iCnt; - } - } - else if ((0 == strcmp(argv[i], "-threads")) && (argc > i+1)) - { - i++; - iCnt = atoi(argv[i]); - if (iCnt > 0 && iCnt <= MAX_THREADS) - { - iThreads = iCnt; - } - } - else - { - Trace("Unknown option %s ignored\n", argv[i]); - } - } - } - - - iCnt = 0; - for (i=0;i + +#define MAX_COUNT 10000 +#define MAX_THREADS 256 + +BOOL g_bMutex = 0; +BOOL g_bEvent = 0; +BOOL g_bNamedEvent = 0; +BOOL g_bSemaphore = 0; +BOOL g_bProcess = 0; +BOOL g_bLocalWaitAll = 0; +BOOL g_bRemoteWaitAll = 0; +BOOL g_bRandom = 0; + +int iCount = 1; +int iThreads = 1; +HANDLE hThreads[MAX_THREADS]; + +#ifndef MIN +#define MIN(a,b) (((a)<(b)) ? (a) : (b)) +#endif + +DWORD PALAPI EventTestThread(PVOID pArg) +{ + BOOL bRet; + DWORD dwRet; + HANDLE hEvent[2]; + HANDLE (*prgHandles)[] = (HANDLE (*)[])pArg; + + Trace("[EventTestThread] Starting\n"); + + bRet = DuplicateHandle(GetCurrentProcess(), (*prgHandles)[0], GetCurrentProcess(), + &hEvent[0], 0, FALSE, DUPLICATE_SAME_ACCESS); + bRet &= DuplicateHandle(GetCurrentProcess(), (*prgHandles)[1], GetCurrentProcess(), + &hEvent[1], 0, FALSE, DUPLICATE_SAME_ACCESS); + if (FALSE == bRet) + { + Fail("[EventTestThread] Failed to duplicate handles\n"); + } + + Sleep(1000); + bRet = SetEvent(hEvent[1]); + if (FALSE == bRet) + { + Fail("SetEvent failed\n"); + Fail("[EventTestThread] SetEvent failed [GetLastError()=%u]\n", + GetLastError()); + } + + dwRet = WaitForSingleObject(hEvent[1], INFINITE); + if (WAIT_FAILED == dwRet) + { + Fail("[EventTestThread] WaitForMultipleObjects failed [GetLastError()=%u]\n", + GetLastError()); + } + + Sleep(1000); + bRet = SetEvent(hEvent[0]); + if (FALSE == bRet) + { + Fail("[EventTestThread] SetEvent failed [GetLastError()=%u]\n", + GetLastError()); + } + + Sleep(1000); + bRet = SetEvent(hEvent[1]); + if (FALSE == bRet) + { + Fail("[EventTestThread] SetEvent failed [GetLastError()=%u]\n", + GetLastError()); + } + + CloseHandle(hEvent[0]); + CloseHandle(hEvent[1]); + + Trace("[EventTestThread] Done\n"); + return 0; +} + +DWORD PALAPI MutexTestThread(PVOID pArg) +{ + BOOL bRet; + DWORD dwRet; + HANDLE hMutex; + + Trace("[MutexTestThread] Starting\n"); + + bRet = DuplicateHandle(GetCurrentProcess(), (HANDLE)pArg, GetCurrentProcess(), &hMutex, + 0, FALSE, DUPLICATE_SAME_ACCESS); + if (FALSE == bRet) + { + Fail("[EventTestThread] DuplicateHandle failed [GetLastError()=%u]\n", + GetLastError()); + } + + dwRet = WaitForSingleObject(hMutex, INFINITE); + if (WAIT_FAILED == dwRet) + { + Fail("[EventTestThread] WaitForMultipleObjects failed [GetLastError()=%u]\n", + GetLastError()); + } + + Sleep(1000); + CloseHandle(hMutex); + + Trace("[MutexTestThread] Done\n"); + + return 0; +} + +DWORD PALAPI TestThread(PVOID pArg) +{ + BOOL bRet; + DWORD dwRet; + PROCESS_INFORMATION pi; + STARTUPINFO si; + HANDLE hNamedEvent; + HANDLE hEvent[2] = { 0, 0 }; + HANDLE hMutex = 0; + HANDLE hSemaphore = 0; + HANDLE hObjs[2]; + DWORD dwThreadNum; + DWORD dwSlaveThreadTid = 0; + HANDLE hThread; + int i, iCnt, iRet; + char szTestName[128]; + char szCmd[128]; + char szEventName[128] = { 0 }; + char szMutexName[128] = { 0 }; + char szSemName[128] = { 0 }; + WCHAR wszEventName[128] = { 0 }; + WCHAR wszMutexName[128] = { 0 }; + WCHAR wszSemName[128] = { 0 }; + BOOL bMutex = g_bMutex; + BOOL bEvent = g_bEvent; + BOOL bNamedEvent = g_bNamedEvent; + BOOL bSemaphore = g_bSemaphore; + BOOL bProcess = g_bProcess; + BOOL bLocalWaitAll = g_bLocalWaitAll; + BOOL bRemoteWaitAll = g_bRemoteWaitAll; + int iDesiredExitCode; + + dwThreadNum = (DWORD)pArg; + + sprintf_s (szTestName, 128, "Test6_%u", dwThreadNum); + szTestName[127] = 0; + + sprintf_s(szEventName, 128, "%s_Event", szTestName); + szEventName[127] = 0; + sprintf_s(szMutexName, 128, "%s_Mutex", szTestName); + szMutexName[127] = 0; + sprintf_s(szSemName, 128, "%s_Semaphore", szTestName); + szSemName[127] = 0; + + iRet = MultiByteToWideChar(CP_ACP, 0, szEventName, strlen(szEventName)+1, wszEventName, 128); + iRet &= MultiByteToWideChar(CP_ACP, 0, szMutexName, strlen(szMutexName)+1, wszMutexName, 128); + iRet &= MultiByteToWideChar(CP_ACP, 0, szSemName, strlen(szSemName)+1, wszSemName, 128); + + if (0 == iRet) + { + Fail("[TestThread] Failed to convert strings\n"); + } + + Trace("[TestThread] TestName=%s Event: %S, Mutex: %S, Semaphore = %S\n", + szTestName, wszEventName, wszMutexName, wszSemName); + + hEvent[0] = CreateEventA(NULL, FALSE, FALSE, NULL); + hEvent[1] = CreateEventA(NULL, FALSE, FALSE, NULL); + + hNamedEvent = CreateEventW(NULL, FALSE, FALSE, wszEventName); + hMutex = CreateMutexW(NULL, FALSE, wszMutexName); + hSemaphore = CreateSemaphoreW(NULL, 0, 256, wszSemName); + + if (NULL == hEvent[0] || NULL == hEvent[1] || NULL == hMutex || + NULL == hNamedEvent || NULL == hSemaphore) + { + Fail("[TestThread] Failed to create objects " + "[hNamedEvent=%p hMutex=%p hSemaphore=%p]\n", + (VOID*)hNamedEvent, (VOID*)hMutex, (VOID*)hSemaphore); + } + + for (iCnt=0; iCnt i+1)) + { + i++; + iCnt = atoi(argv[i]); + if (iCnt > 0 && iCnt < MAX_COUNT) + { + iCount = iCnt; + } + } + else if ((0 == strcmp(argv[i], "-threads")) && (argc > i+1)) + { + i++; + iCnt = atoi(argv[i]); + if (iCnt > 0 && iCnt <= MAX_THREADS) + { + iThreads = iCnt; + } + } + else + { + Trace("Unknown option %s ignored\n", argv[i]); + } + } + } + + + iCnt = 0; + for (i=0;i - - -#define NUMBER_OF_WORKER_THREADS 2 - -//Declaring Variables -HANDLE hMutex = NULL; -unsigned int globalcounter =0; -int testReturnCode = PASS; - -//Declaring Function Prototypes -DWORD WFSOMutexTest(LPVOID params); -void incrementCounter(void); - - - -int __cdecl main(int argc, char **argv) -{ - - //Declare local variables - int i =0; - - // 2 dimensional array to hold thread handles for each worker thread - HANDLE hThread[NUMBER_OF_WORKER_THREADS]; - DWORD dwThreadId=0; - int returnCode = 0; - - //Initialize PAL - if(0 != (PAL_Initialize(argc, argv))) - { - return ( FAIL ); - } - - //Create Mutex - hMutex = CreateMutex(NULL, // no security attributes - FALSE, // initially not owned - NULL); // name of mutex - - //Check for Mutex Creation - - if (hMutex == NULL) - { - Fail("Create Mutex Failed, GetLastError: %d\n", GetLastError()); - } - - - //Spawn 2 worker threads - for (i=0;i + + +#define NUMBER_OF_WORKER_THREADS 2 + +//Declaring Variables +HANDLE hMutex = NULL; +unsigned int globalcounter =0; +int testReturnCode = PASS; + +//Declaring Function Prototypes +DWORD PALAPI WFSOMutexTest(LPVOID params); +void incrementCounter(void); + + + +int __cdecl main(int argc, char **argv) +{ + + //Declare local variables + int i =0; + + // 2 dimensional array to hold thread handles for each worker thread + HANDLE hThread[NUMBER_OF_WORKER_THREADS]; + DWORD dwThreadId=0; + int returnCode = 0; + + //Initialize PAL + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + //Create Mutex + hMutex = CreateMutex(NULL, // no security attributes + FALSE, // initially not owned + NULL); // name of mutex + + //Check for Mutex Creation + + if (hMutex == NULL) + { + Fail("Create Mutex Failed, GetLastError: %d\n", GetLastError()); + } + + + //Spawn 2 worker threads + for (i=0;i - - -#define NUMBER_OF_WORKER_THREADS 2 - - -//Declaring Variables -HANDLE hSemaphore = NULL; -unsigned int globalcounter =0; -int testReturnCode = PASS; - -//Declaring Function Prototypes -DWORD WFSOSemaphoreTest(LPVOID params); -void incrementCounter(void); - -int __cdecl main(int argc, char **argv) -{ - - //Declare local variables - int i =0; - int cMax = 2; - - int returnCode = 0; - - // 2 dimensional array to hold thread handles for each worker thread - HANDLE hThread[NUMBER_OF_WORKER_THREADS]; - DWORD dwThreadId=0; - - //Initialize PAL - if(0 != (PAL_Initialize(argc, argv))) - { - return ( FAIL ); - } - - //Create Semaphore - hSemaphore = CreateSemaphore( - NULL, // no security attributes - cMax, // initial count - cMax, // maximum count - NULL); // unnamed semaphore - - if (hSemaphore == NULL) - { - // Check for error. - Fail("Create Semaphore Failed, GetLastError: %d\n", GetLastError()); - } - - - - //Spawn 2 worker threads - for (i=0;i + + +#define NUMBER_OF_WORKER_THREADS 2 + + +//Declaring Variables +HANDLE hSemaphore = NULL; +unsigned int globalcounter =0; +int testReturnCode = PASS; + +//Declaring Function Prototypes +DWORD PALAPI WFSOSemaphoreTest(LPVOID params); +void incrementCounter(void); + +int __cdecl main(int argc, char **argv) +{ + + //Declare local variables + int i =0; + int cMax = 2; + + int returnCode = 0; + + // 2 dimensional array to hold thread handles for each worker thread + HANDLE hThread[NUMBER_OF_WORKER_THREADS]; + DWORD dwThreadId=0; + + //Initialize PAL + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + //Create Semaphore + hSemaphore = CreateSemaphore( + NULL, // no security attributes + cMax, // initial count + cMax, // maximum count + NULL); // unnamed semaphore + + if (hSemaphore == NULL) + { + // Check for error. + Fail("Create Semaphore Failed, GetLastError: %d\n", GetLastError()); + } + + + + //Spawn 2 worker threads + for (i=0;i - - -//Declaring Variables -HANDLE hThread = NULL; -HANDLE hEvent = NULL; - -unsigned int globalcounter =0; - -//Declaring Function Prototypes -DWORD incrementCounter(LPVOID params); - -int __cdecl main(int argc, char **argv) -{ - - //Declare local variables - DWORD dwThreadId=0; - DWORD dwWaitResult=0; - - //Initialize PAL - if(0 != (PAL_Initialize(argc, argv))) - { - return ( FAIL ); - } - - - //Create Event - hEvent = CreateEvent(NULL,TRUE,FALSE, NULL); - if(hEvent == NULL) - { - Fail("Create Event Failed\n" - "GetLastError returned %d\n", GetLastError()); - } - - - //Create Thread - hThread = CreateThread( - NULL, - 0, - incrementCounter, - NULL, - 0, - &dwThreadId); - - if ( NULL == hThread ) - { - Fail ( "CreateThread() returned NULL. Failing test.\n" - "GetLastError returned %d\n", GetLastError()); - } - - - //Wait For Thread to signal start - dwWaitResult = WaitForSingleObject(hEvent,INFINITE); - - switch (dwWaitResult) - { - // The thread wait was successful - case WAIT_OBJECT_0: - { - - Trace ("Wait for Single Object (hEvent) was successful.\n"); - break; - } - - // Time-out. - case WAIT_TIMEOUT: - { - Fail ( "Time -out. Failing test.\n" - "GetLastError returned %d\n", GetLastError()); - return FALSE; - } - - // Got ownership of the abandoned event object. - case WAIT_ABANDONED: - { - Fail ( "Got ownership of the abandoned event object. Failing test.\n" - "GetLastError returned %d\n", GetLastError()); - return FALSE; - } - - } - - - //Wait for Thread to finish - dwWaitResult = WaitForSingleObject( - hThread, //handle to thread - 5000L); //Wait Indefinitely - - - switch (dwWaitResult) - { - // The thread wait was successful - case WAIT_OBJECT_0: - { - - Trace("Wait for thread was successful\n"); - - break; - } - - // Time-out. - case WAIT_TIMEOUT: - { - Fail ( "Time -out. Failing test.\n" - "GetLastError returned %d\n", GetLastError()); - return FALSE; - } - - // Got ownership of the abandoned thread object. - case WAIT_ABANDONED: - { - Fail ( "Got ownership of the abandoned thread object. Failing test.\n" - "GetLastError returned %d\n", GetLastError()); - return FALSE; - } - - } - - -//Close Handles -if (0==CloseHandle(hEvent)) - { - Trace("Could not Close event handle\n"); - Fail ( "GetLastError returned %d\n", GetLastError()); - } -if (0==CloseHandle(hThread)) - { - Trace("Could not Close thread handle\n"); - Fail ( "GetLastError returned %d\n", GetLastError()); - } - -PAL_Terminate(); -return ( PASS ); - -} - -DWORD incrementCounter(LPVOID params) -{ - - //Signal Event so that main thread can start to wait for thread object - if (0==SetEvent(hEvent)) - { - Fail ( "SetEvent returned Zero. Failing test.\n" - "GetLastError returned %d\n", GetLastError()); - } - - for (globalcounter=0;globalcounter<100000;globalcounter++); - - //Sleep(5000); - - Trace("Global Counter Value: %d \n", globalcounter); - return 0; -} - - - - - - diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/WFSOThreadTest.cpp b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/WFSOThreadTest.cpp new file mode 100644 index 0000000..e3c3fe2 --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/WFSOThreadTest.cpp @@ -0,0 +1,179 @@ +// 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. + +/*============================================================ +** +** Source: WFSOThreadTest.c +** +** Purpose: Test for WaitForSingleObjectTest. +** Create One Thread and do some work +** Use WFSO For the Thread to finish +** +** Test Passes if the above operations are successful +** +** +** +**=========================================================*/ + + + +#include + + +//Declaring Variables +HANDLE hThread = NULL; +HANDLE hEvent = NULL; + +unsigned int globalcounter =0; + +//Declaring Function Prototypes +DWORD PALAPI incrementCounter(LPVOID params); + +int __cdecl main(int argc, char **argv) +{ + + //Declare local variables + DWORD dwThreadId=0; + DWORD dwWaitResult=0; + + //Initialize PAL + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + + //Create Event + hEvent = CreateEvent(NULL,TRUE,FALSE, NULL); + if(hEvent == NULL) + { + Fail("Create Event Failed\n" + "GetLastError returned %d\n", GetLastError()); + } + + + //Create Thread + hThread = CreateThread( + NULL, + 0, + incrementCounter, + NULL, + 0, + &dwThreadId); + + if ( NULL == hThread ) + { + Fail ( "CreateThread() returned NULL. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + + //Wait For Thread to signal start + dwWaitResult = WaitForSingleObject(hEvent,INFINITE); + + switch (dwWaitResult) + { + // The thread wait was successful + case WAIT_OBJECT_0: + { + + Trace ("Wait for Single Object (hEvent) was successful.\n"); + break; + } + + // Time-out. + case WAIT_TIMEOUT: + { + Fail ( "Time -out. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + + // Got ownership of the abandoned event object. + case WAIT_ABANDONED: + { + Fail ( "Got ownership of the abandoned event object. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + + } + + + //Wait for Thread to finish + dwWaitResult = WaitForSingleObject( + hThread, //handle to thread + 5000L); //Wait Indefinitely + + + switch (dwWaitResult) + { + // The thread wait was successful + case WAIT_OBJECT_0: + { + + Trace("Wait for thread was successful\n"); + + break; + } + + // Time-out. + case WAIT_TIMEOUT: + { + Fail ( "Time -out. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + + // Got ownership of the abandoned thread object. + case WAIT_ABANDONED: + { + Fail ( "Got ownership of the abandoned thread object. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + + } + + +//Close Handles +if (0==CloseHandle(hEvent)) + { + Trace("Could not Close event handle\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } +if (0==CloseHandle(hThread)) + { + Trace("Could not Close thread handle\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } + +PAL_Terminate(); +return ( PASS ); + +} + +DWORD PALAPI incrementCounter(LPVOID params) +{ + + //Signal Event so that main thread can start to wait for thread object + if (0==SetEvent(hEvent)) + { + Fail ( "SetEvent returned Zero. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + for (globalcounter=0;globalcounter<100000;globalcounter++); + + //Sleep(5000); + + Trace("Global Counter Value: %d \n", globalcounter); + return 0; +} + + + + + + diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/CMakeLists.txt index 0a71330..25f3739 100644 --- a/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_waitforsingleobject_test1 diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/test1.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/WaitForSingleObject/test1/test1.c rename to src/pal/tests/palsuite/threading/WaitForSingleObject/test1/test1.cpp diff --git a/src/pal/tests/palsuite/threading/YieldProcessor/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/YieldProcessor/test1/CMakeLists.txt index 5002bf7..1c600bd 100644 --- a/src/pal/tests/palsuite/threading/YieldProcessor/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/YieldProcessor/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_yieldprocessor_test1 diff --git a/src/pal/tests/palsuite/threading/YieldProcessor/test1/test1.c b/src/pal/tests/palsuite/threading/YieldProcessor/test1/test1.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/YieldProcessor/test1/test1.c rename to src/pal/tests/palsuite/threading/YieldProcessor/test1/test1.cpp diff --git a/src/pal/tests/palsuite/threading/releasesemaphore/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/releasesemaphore/test1/CMakeLists.txt index e415f91..4f69474 100644 --- a/src/pal/tests/palsuite/threading/releasesemaphore/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/threading/releasesemaphore/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_releasesemaphore_test1 diff --git a/src/pal/tests/palsuite/threading/releasesemaphore/test1/test.c b/src/pal/tests/palsuite/threading/releasesemaphore/test1/test.cpp similarity index 100% rename from src/pal/tests/palsuite/threading/releasesemaphore/test1/test.c rename to src/pal/tests/palsuite/threading/releasesemaphore/test1/test.cpp diff --git a/src/pal/tools/gen-buildsys-clang.sh b/src/pal/tools/gen-buildsys-clang.sh index b7945f3..4054266 100755 --- a/src/pal/tools/gen-buildsys-clang.sh +++ b/src/pal/tools/gen-buildsys-clang.sh @@ -126,13 +126,20 @@ fi if [[ -n "$LLDB_INCLUDE_DIR" ]]; then cmake_extra_defines="$cmake_extra_defines -DWITH_LLDB_INCLUDES=$LLDB_INCLUDE_DIR" fi -if [[ -n "$CROSSCOMPILE" ]]; then - if ! [[ -n "$ROOTFS_DIR" ]]; then - echo "ROOTFS_DIR not set for crosscompile" - exit 1 +if [[ -n "$CROSSCOMPONENT" ]]; then + cmake_extra_defines="$cmake_extra_defines -DCLR_CROSS_COMPONENTS_BUILD=1" +else + if [[ -n "$CROSSCOMPILE" ]]; then + if ! [[ -n "$ROOTFS_DIR" ]]; then + echo "ROOTFS_DIR not set for crosscompile" + exit 1 + fi + if [[ -z $CONFIG_DIR ]]; then + CONFIG_DIR="$1/cross/$build_arch" + fi + cmake_extra_defines="$cmake_extra_defines -C $CONFIG_DIR/tryrun.cmake" + cmake_extra_defines="$cmake_extra_defines -DCMAKE_TOOLCHAIN_FILE=$CONFIG_DIR/toolchain.cmake" fi - cmake_extra_defines="$cmake_extra_defines -C $1/cross/$build_arch/tryrun.cmake" - cmake_extra_defines="$cmake_extra_defines -DCMAKE_TOOLCHAIN_FILE=$1/cross/$build_arch/toolchain.cmake" fi if [ "$build_arch" == "arm-softfp" ]; then cmake_extra_defines="$cmake_extra_defines -DARM_SOFTFP=1" diff --git a/src/pal/tools/gen-buildsys-win.bat b/src/pal/tools/gen-buildsys-win.bat index ab57fb4..f7f81fc 100644 --- a/src/pal/tools/gen-buildsys-win.bat +++ b/src/pal/tools/gen-buildsys-win.bat @@ -36,7 +36,7 @@ goto loop if defined CMakePath goto DoGen :: Eval the output from probe-win1.ps1 -for /f "delims=" %%a in ('powershell -NoProfile -ExecutionPolicy RemoteSigned "& "%basePath%\probe-win.ps1""') do %%a +for /f "delims=" %%a in ('powershell -NoProfile -ExecutionPolicy ByPass "& "%basePath%\probe-win.ps1""') do %%a :DoGen "%CMakePath%" "-DCMAKE_USER_MAKE_RULES_OVERRIDE=%basePath%\windows-compiler-override.txt" "-DCMAKE_INSTALL_PREFIX:PATH=$ENV{__CMakeBinDir}" "-DCLR_CMAKE_HOST_ARCH=%__Arch%" %__ExtraCmakeParams% -G "%__CmakeGenerator%" %__SourceDir% diff --git a/src/palrt/path.cpp b/src/palrt/path.cpp index 1d610cd..fc01183 100644 --- a/src/palrt/path.cpp +++ b/src/palrt/path.cpp @@ -11,7 +11,7 @@ // =========================================================================== #include "common.h" - +#include "strsafe.h" #define CH_SLASH W('/') @@ -355,7 +355,8 @@ STDAPI_(BOOL) PathCanonicalizeW(LPWSTR lpszDst, LPCWSTR lpszSrc) else // Everything else { // Just copy it. - lstrcpynW(lpchDst, lpchSrc, cchPC); + int cchRemainingBuffer = MAX_PATH - (lpszDst - lpchDst); + StringCchCopyNW(lpchDst, cchRemainingBuffer, lpchSrc, cchPC); lpchDst += cchPC - 1; lpchSrc += cchPC - 1; } @@ -429,11 +430,12 @@ STDAPI_(LPWSTR) PathCombineW(LPWSTR lpszDest, LPCWSTR lpszDir, LPCWSTR lpszFile) { if (!lpszFile || *lpszFile==W('\0')) { - lstrcpynW(szTemp, lpszDir, ARRAYSIZE(szTemp)); // lpszFile is empty + // lpszFile is empty + StringCchCopyNW(szTemp, ARRAYSIZE(szTemp), lpszDir, ARRAYSIZE(szTemp)); } else if (PathIsRelativeW(lpszFile)) { - lstrcpynW(szTemp, lpszDir, ARRAYSIZE(szTemp)); + StringCchCopyNW(szTemp, ARRAYSIZE(szTemp), lpszDir, ARRAYSIZE(szTemp)); pszT = PathAddBackslashW(szTemp); if (pszT) { @@ -441,7 +443,7 @@ STDAPI_(LPWSTR) PathCombineW(LPWSTR lpszDest, LPCWSTR lpszDir, LPCWSTR lpszFile) if (lstrlenW(lpszFile) < iRemaining) { - lstrcpynW(pszT, lpszFile, iRemaining); + StringCchCopyNW(pszT, iRemaining, lpszFile, iRemaining); } else { @@ -455,7 +457,7 @@ STDAPI_(LPWSTR) PathCombineW(LPWSTR lpszDest, LPCWSTR lpszDir, LPCWSTR lpszFile) } else if (IsPathSeparator(*lpszFile) && !PathIsUNCW(lpszFile)) { - lstrcpynW(szTemp, lpszDir, ARRAYSIZE(szTemp)); + StringCchCopyNW(szTemp, ARRAYSIZE(szTemp), lpszDir, ARRAYSIZE(szTemp)); // FEATURE: Note that we do not check that an actual root is returned; // it is assumed that we are given valid parameters PathStripToRootW(szTemp); @@ -466,7 +468,8 @@ STDAPI_(LPWSTR) PathCombineW(LPWSTR lpszDest, LPCWSTR lpszDir, LPCWSTR lpszFile) // Skip the backslash when copying // Note: We don't support strings longer than 4GB, but that's // okay because we already barf at MAX_PATH - lstrcpynW(pszT, lpszFile+1, (int)(ARRAYSIZE(szTemp) - (pszT - szTemp))); + int iRemaining = (int)(ARRAYSIZE(szTemp) - (pszT - szTemp)); + StringCchCopyNW(pszT, iRemaining, lpszFile+1, iRemaining); } else { @@ -475,12 +478,14 @@ STDAPI_(LPWSTR) PathCombineW(LPWSTR lpszDest, LPCWSTR lpszDir, LPCWSTR lpszFile) } else { - lstrcpynW(szTemp, lpszFile, ARRAYSIZE(szTemp)); // already fully qualified file part + // already fully qualified file part + StringCchCopyNW(szTemp, ARRAYSIZE(szTemp), lpszFile, ARRAYSIZE(szTemp)); } } else if (lpszFile && *lpszFile) { - lstrcpynW(szTemp, lpszFile, ARRAYSIZE(szTemp)); // no dir just use file. + // no dir just use file. + StringCchCopyNW(szTemp, ARRAYSIZE(szTemp), lpszFile, ARRAYSIZE(szTemp)); } // diff --git a/src/palrt/urlpars.cpp b/src/palrt/urlpars.cpp index 77b0a6e..66289b6 100644 --- a/src/palrt/urlpars.cpp +++ b/src/palrt/urlpars.cpp @@ -11,6 +11,7 @@ // =========================================================================== #include "common.h" +#include "strsafe.h" #define SLASH W('/') #define WHACK W('\\') @@ -293,14 +294,13 @@ ParseURLW( // (+ 1) for null terminator. - StrCpyNW(rgchDebugProtocol, ppu->pszProtocol, + StringCchCopyNW(rgchDebugProtocol, ARRAYSIZE(rgchDebugProtocol), ppu->pszProtocol, min(ppu->cchProtocol + 1, SIZECHARS(rgchDebugProtocol))); // (+ 1) for null terminator. - StrCpyNW(rgchDebugSuffix, ppu->pszSuffix, + StringCchCopyNW(rgchDebugSuffix, ARRAYSIZE(rgchDebugSuffix), ppu->pszSuffix, min(ppu->cchSuffix + 1, SIZECHARS(rgchDebugSuffix))); - } #endif diff --git a/src/publish.proj b/src/publish.proj index 66aeb7e..d4e4a7f 100644 --- a/src/publish.proj +++ b/src/publish.proj @@ -13,21 +13,26 @@ - $(__BuildType)/%(RecursiveDir)%(Filename)%(Extension) + $(__BuildType)/%(RecursiveDir)%(Filename)%(Extension) + $(__DistroRid)-$(__BuildArch)/$(__BuildType)/%(RecursiveDir)%(Filename)%(Extension) - $(PackagesBinDir)**\*.nupkg + $(PackagesBinDir)**\*.nupkg + $(OutputPath)\tests\src\** + Condition="'$(ContainerName)' == '' or '$(PublishTestNativeBins)' == 'true'"> - coreclr-$(PreReleaseLabel)-$(BuildNumberMajor)-$(BuildNumberMinor) + coreclr-$(PreReleaseLabel)-$(BuildNumberMajor)-$(BuildNumberMinor) + coreclr-$(PreReleaseLabel)-$(BuildNumberMajor)-$(BuildNumberMinor)-test-native-bins + $(__Container) + $(__Container)-test-native-bins diff --git a/src/strongname/api/common.h b/src/strongname/api/common.h index c83685c..c6b9b4d 100644 --- a/src/strongname/api/common.h +++ b/src/strongname/api/common.h @@ -156,7 +156,7 @@ typedef DPTR(class TypeHandle) PTR_TypeHandle; typedef VPTR(class VirtualCallStubManager) PTR_VirtualCallStubManager; typedef VPTR(class VirtualCallStubManagerManager) PTR_VirtualCallStubManagerManager; #endif -typedef VPTR(class GCHeap) PTR_GCHeap; +typedef VPTR(class IGCHeap) PTR_IGCHeap; // // _UNCHECKED_OBJECTREF is for code that can't deal with DEBUG OBJECTREFs @@ -192,7 +192,7 @@ Thread * const CURRENT_THREAD = NULL; (void)CURRENT_THREAD_AVAILABLE; /* silence "local variable initialized but not used" warning */ \ #ifndef DACCESS_COMPILE -EXTERN_C AppDomain* GetAppDomain(); +EXTERN_C AppDomain* STDCALL GetAppDomain(); #endif //!DACCESS_COMPILE inline void RetailBreak() diff --git a/src/syncAzure.proj b/src/syncAzure.proj index fbfbea0..0b71a3b 100644 --- a/src/syncAzure.proj +++ b/src/syncAzure.proj @@ -4,8 +4,11 @@ coreclr-$(PreReleaseLabel) - $(ContainerNamePrefix)-$(BuildNumberMajor)-$(BuildNumberMinor) - $(PackagesDir)AzureTransfer + $(ContainerNamePrefix)-$(BuildNumberMajor)-$(BuildNumberMinor) + $(__Container) + $(__Container)-test-native-bins + $(PackagesDir)AzureTransfer + $(PackagesDir)TestNativeBins diff --git a/src/tools/crossgen/crossgen.cpp b/src/tools/crossgen/crossgen.cpp index 960bcf5..a3e66e6 100644 --- a/src/tools/crossgen/crossgen.cpp +++ b/src/tools/crossgen/crossgen.cpp @@ -122,20 +122,21 @@ void PrintUsageHelper() W(" /in - Specifies input filename (optional)\n") W(" /out - Specifies output filename (optional)\n") #ifdef FEATURE_CORECLR - W(" /Trusted_Platform_Assemblies \n") + W(" /Trusted_Platform_Assemblies \n") W(" - List of assemblies treated as trusted platform\n") W(" - Cannot be used with Platform_Assemblies_Paths\n") - W(" /Platform_Resource_Roots \n") + W(" /Platform_Resource_Roots \n") W(" - List of paths containing localized assembly directories\n") - W(" /App_Paths - List of paths containing user-application assemblies and resources\n") + W(" /App_Paths \n") + W(" - List of paths containing user-application assemblies and resources\n") #ifndef NO_NGENPDB - W(" /App_Ni_Paths \n") + W(" /App_Ni_Paths \n") W(" - List of paths containing user-application native images\n") W(" - Must be used with /CreatePDB switch\n") #endif // NO_NGENPDB #endif // FEATURE_CORECLR - W(" /Platform_Assemblies_Paths\n") + W(" /Platform_Assemblies_Paths \n") W(" - List of paths containing target platform assemblies\n") #ifdef FEATURE_CORECLR // If Platform_Assemblies_Paths, we will use it to build the TPA list and thus, @@ -144,7 +145,7 @@ void PrintUsageHelper() #endif // FEATURE_CORECLR #ifdef FEATURE_COMINTEROP - W(" /Platform_Winmd_Paths\n") + W(" /Platform_Winmd_Paths \n") W(" - List of paths containing target platform WinMDs used\n") W(" for emulating RoResolveNamespace\n") #endif @@ -156,7 +157,7 @@ void PrintUsageHelper() W(" scenario traces, which can be used with ibcmerge.exe\n") #endif #if defined(FEATURE_CORECLR) && !defined(FEATURE_MERGE_JIT_AND_ENGINE) - W(" /JITPath\n") + W(" /JITPath \n") W(" - Specifies the absolute file path to JIT compiler to be used.\n") #endif // defined(FEATURE_CORECLR) && !defined(FEATURE_MERGE_JIT_AND_ENGINE) #ifdef FEATURE_READYTORUN_COMPILER diff --git a/src/utilcode/CMakeLists.txt b/src/utilcode/CMakeLists.txt index 9d35a7e..7c39673 100644 --- a/src/utilcode/CMakeLists.txt +++ b/src/utilcode/CMakeLists.txt @@ -41,7 +41,6 @@ set(UTILCODE_COMMON_SOURCES outstring.cpp ilformatter.cpp opinfo.cpp - dacutil.cpp sortversioning.cpp corimage.cpp format1.cpp @@ -71,6 +70,7 @@ set(UTILCODE_COMMON_SOURCES if(WIN32) list(APPEND UTILCODE_COMMON_SOURCES appxutil.cpp + dacutil.cpp dlwrap.cpp downlevel.cpp loadrc.cpp diff --git a/src/utilcode/clrhost_nodependencies.cpp b/src/utilcode/clrhost_nodependencies.cpp index da4e025..a069d24 100644 --- a/src/utilcode/clrhost_nodependencies.cpp +++ b/src/utilcode/clrhost_nodependencies.cpp @@ -745,12 +745,12 @@ void ClrFlsAssociateCallback(DWORD slot, PTLS_CALLBACK_FUNCTION callback) GetExecutionEngine()->TLS_AssociateCallback(slot, callback); } -void ** __stdcall ClrFlsGetBlockGeneric() +LPVOID *ClrFlsGetBlockGeneric() { WRAPPER_NO_CONTRACT; STATIC_CONTRACT_SO_TOLERANT; - return (void **) GetExecutionEngine()->TLS_GetDataBlock(); + return (LPVOID *) GetExecutionEngine()->TLS_GetDataBlock(); } CLRFLSGETBLOCK __ClrFlsGetBlock = ClrFlsGetBlockGeneric; diff --git a/src/utilcode/debug.cpp b/src/utilcode/debug.cpp index a96aca1..9a60645 100644 --- a/src/utilcode/debug.cpp +++ b/src/utilcode/debug.cpp @@ -76,16 +76,6 @@ BOOL ContinueOnAssert() return fNoGui.val(CLRConfig::INTERNAL_ContinueOnAssert); } -BOOL NoGuiOnAssert() -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_DEBUG_ONLY; - - static ConfigDWORD fNoGui; - return fNoGui.val(CLRConfig::INTERNAL_NoGuiOnAssert); -} - void DoRaiseExceptionOnAssert(DWORD chance) { STATIC_CONTRACT_NOTHROW; @@ -794,6 +784,16 @@ bool GetStackTraceAtContext(SString & s, CONTEXT * pContext) #endif // !defined(DACCESS_COMPILE) #endif // _DEBUG +BOOL NoGuiOnAssert() +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_DEBUG_ONLY; + + static ConfigDWORD fNoGui; + return fNoGui.val(CLRConfig::INTERNAL_NoGuiOnAssert); +} + // This helper will throw up a message box without allocating or using stack if possible, and is // appropriate for either low memory or low stack situations. int LowResourceMessageBoxHelperAnsi( diff --git a/src/utilcode/fstring.cpp b/src/utilcode/fstring.cpp index 33aa346..1165eca 100644 --- a/src/utilcode/fstring.cpp +++ b/src/utilcode/fstring.cpp @@ -73,6 +73,9 @@ HRESULT Unicode_Utf8_Length(__in_z LPCWSTR pString, __out bool * pAllAscii, __ou return HRESULT_FROM_GetLastError(); } + // Remove the count of null terminator, to be consistent with the all-ASCII case. + --*pLength; + if (*pLength > MAX_LENGTH) { return COR_E_OVERFLOW; @@ -129,7 +132,7 @@ HRESULT Unicode_Utf8(__in_z LPCWSTR pString, bool allAscii, __out_z LPSTR pBuffe } else { - length = WszWideCharToMultiByte(CP_UTF8, 0, pString, -1, pBuffer, (int) length, NULL, NULL); + length = WszWideCharToMultiByte(CP_UTF8, 0, pString, -1, pBuffer, (int) length + 1, NULL, NULL); if (length == 0) { @@ -190,6 +193,9 @@ HRESULT Utf8_Unicode_Length(__in_z LPCSTR pString, __out bool * pAllAscii, __out return HRESULT_FROM_GetLastError(); } + // Remove the count of null terminator, to be consistent with the all-ASCII case. + --*pLength; + if (* pLength > MAX_LENGTH) { return COR_E_OVERFLOW; @@ -200,7 +206,7 @@ HRESULT Utf8_Unicode_Length(__in_z LPCSTR pString, __out bool * pAllAscii, __out } -// UTF8 to ANSI +// UTF8 to Unicode HRESULT Utf8_Unicode(__in_z LPCSTR pString, bool allAscii, __out_z LPWSTR pBuffer, DWORD length) { @@ -247,7 +253,7 @@ HRESULT Utf8_Unicode(__in_z LPCSTR pString, bool allAscii, __out_z LPWSTR pBuffe } else { - length = WszMultiByteToWideChar(CP_UTF8, 0, pString, -1, pBuffer, (int) length); + length = WszMultiByteToWideChar(CP_UTF8, 0, pString, -1, pBuffer, (int) length + 1); if (length == 0) { diff --git a/src/utilcode/longfilepathwrappers.cpp b/src/utilcode/longfilepathwrappers.cpp index 9ffbf27..5272d35 100644 --- a/src/utilcode/longfilepathwrappers.cpp +++ b/src/utilcode/longfilepathwrappers.cpp @@ -19,8 +19,8 @@ private: static const WCHAR VolumeSeparatorChar; #define UNCPATHPREFIX W("\\\\") #endif //FEATURE_PAL - static const WCHAR LongFile::DirectorySeparatorChar; - static const WCHAR LongFile::AltDirectorySeparatorChar; + static const WCHAR DirectorySeparatorChar; + static const WCHAR AltDirectorySeparatorChar; public: static BOOL IsExtended(SString & path); static BOOL IsUNCExtended(SString & path); diff --git a/src/utilcode/makepath.cpp b/src/utilcode/makepath.cpp index 37b7202..701c525 100644 --- a/src/utilcode/makepath.cpp +++ b/src/utilcode/makepath.cpp @@ -17,7 +17,7 @@ #ifndef FEATURE_CORECLR /*** -*void _makepath() - build path name from components +*void MakePath() - build path name from components * *Purpose: * create a path name from its individual components diff --git a/src/utilcode/md5.cpp b/src/utilcode/md5.cpp index 1c7b31f..8d6f8a3 100644 --- a/src/utilcode/md5.cpp +++ b/src/utilcode/md5.cpp @@ -132,7 +132,7 @@ void MD5::GetHashValue(MD5HASHDATA* phash) // // but our compiler has an intrinsic! - #if defined(_ARM_) && defined(PLATFORM_UNIX) + #if (defined(_X86_) || defined(_ARM_)) && defined(PLATFORM_UNIX) #define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n)))) #define ROTATE_LEFT(x,n) (x) = ROL(x,n) #else diff --git a/src/utilcode/opinfo.cpp b/src/utilcode/opinfo.cpp index 9d5ff20..60da660 100644 --- a/src/utilcode/opinfo.cpp +++ b/src/utilcode/opinfo.cpp @@ -14,13 +14,8 @@ OpInfo::OpInfoData OpInfo::table[] = { -#ifdef _MSC_VER -#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) \ - { s, args + type, FLOW_ ## ctrl, pop, push, c }, -#else #define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) \ { s, (OPCODE_FORMAT) (args + type), FLOW_ ## ctrl, pop, push, c }, -#endif // Kind of a workaround, get the prefixes (IInternal) to return InlineOpcode instead of InlineNone #define IInternal (InlineOpcode - InlineNone) diff --git a/src/utilcode/regutil.cpp b/src/utilcode/regutil.cpp index fbc5570..d611ef9 100644 --- a/src/utilcode/regutil.cpp +++ b/src/utilcode/regutil.cpp @@ -1439,8 +1439,7 @@ void REGUTIL::InitOptionalConfigCache() s_fUseRegCache = TRUE; // Now create a cache of environment variables - WCHAR * wszStrings = WszGetEnvironmentStrings(); - if (wszStrings) + if (WCHAR * wszStrings = WszGetEnvironmentStrings()) { // GetEnvironmentStrings returns pointer to a null terminated block containing // null terminated strings diff --git a/src/utilcode/securitywrapper.cpp b/src/utilcode/securitywrapper.cpp index f949b26..0f146ab 100644 --- a/src/utilcode/securitywrapper.cpp +++ b/src/utilcode/securitywrapper.cpp @@ -412,6 +412,7 @@ HRESULT SidBuffer::InitFromProcessAppContainerSidNoThrow(DWORD pid) { HRESULT hr = S_OK; HANDLE hToken = NULL; + BOOL fIsLowBox = FALSE; HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); if (hProcess == NULL) @@ -438,7 +439,6 @@ HRESULT SidBuffer::InitFromProcessAppContainerSidNoThrow(DWORD pid) } TOKEN_APPCONTAINER_INFORMATION, *PTOKEN_APPCONTAINER_INFORMATION; DWORD size; - BOOL fIsLowBox = FALSE; if (!GetTokenInformation(hToken, (TOKEN_INFORMATION_CLASS)TokenIsAppContainer, &fIsLowBox, sizeof(fIsLowBox), &size)) { DWORD gle = GetLastError(); @@ -466,24 +466,26 @@ HRESULT SidBuffer::InitFromProcessAppContainerSidNoThrow(DWORD pid) goto exit; } - PTOKEN_APPCONTAINER_INFORMATION pTokPack = (PTOKEN_APPCONTAINER_INFORMATION)&PackSid; - PSID pLowBoxPackage = pTokPack->TokenPackage; - DWORD dwSidLen = GetLengthSid(pLowBoxPackage); - m_pBuffer = new (nothrow) BYTE[dwSidLen]; - if (m_pBuffer == NULL) - { - hr = E_OUTOFMEMORY; - goto exit; - } - else { - if (!CopySid(dwSidLen, m_pBuffer, pLowBoxPackage)) + PTOKEN_APPCONTAINER_INFORMATION pTokPack = (PTOKEN_APPCONTAINER_INFORMATION)&PackSid; + PSID pLowBoxPackage = pTokPack->TokenPackage; + DWORD dwSidLen = GetLengthSid(pLowBoxPackage); + m_pBuffer = new (nothrow) BYTE[dwSidLen]; + if (m_pBuffer == NULL) { - hr = HRESULT_FROM_GetLastError(); - delete m_pBuffer; - m_pBuffer = NULL; + hr = E_OUTOFMEMORY; goto exit; } + else + { + if (!CopySid(dwSidLen, m_pBuffer, pLowBoxPackage)) + { + hr = HRESULT_FROM_GetLastError(); + delete m_pBuffer; + m_pBuffer = NULL; + goto exit; + } + } } exit: @@ -790,6 +792,7 @@ bool IsHandleSpoofed(HANDLE handle, DWORD pid) SidBuffer sbPidOther; SidBuffer sbPidThis; + DWORD pidThis; // Is the object owner the "other" pid? sbPidOther.InitFromProcess(pid); @@ -805,7 +808,7 @@ bool IsHandleSpoofed(HANDLE handle, DWORD pid) // This can happen if the other process impersonates us. The most common case would // be if we're an admin and the other process (say some service) is impersonating Admin // when it spins up the CLR. - DWORD pidThis = GetCurrentProcessId(); + pidThis = GetCurrentProcessId(); if (pidThis != pid) { sbPidThis.InitFromProcess(pidThis); diff --git a/src/utilcode/splitpath.cpp b/src/utilcode/splitpath.cpp index f7a35fd..a5578a1 100644 --- a/src/utilcode/splitpath.cpp +++ b/src/utilcode/splitpath.cpp @@ -18,7 +18,7 @@ /*** -*_splitpath() - split a path name into its individual components +*SplitPath() - split a path name into its individual components * *Purpose: * to split a path name into its individual components @@ -214,7 +214,7 @@ void SplitPathInterior( } /*** -*_splitpath() - split a path name into its individual components +*SplitPath() - split a path name into its individual components * *Purpose: * to split a path name into its individual components diff --git a/src/utilcode/sstring.cpp b/src/utilcode/sstring.cpp index 154e9de..ce532d7 100644 --- a/src/utilcode/sstring.cpp +++ b/src/utilcode/sstring.cpp @@ -2211,7 +2211,7 @@ void SString::VPrintf(const WCHAR *format, va_list args) else if (errno!=0 && errno!=EBADF && errno!=ERANGE) { - CONSISTENCY_CHECK_MSG(FALSE, "_vsnwprintf failed. Potential globalization bug."); + CONSISTENCY_CHECK_MSG(FALSE, "_vsnwprintf_s failed. Potential globalization bug."); ThrowHR(HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION)); } } @@ -2293,7 +2293,7 @@ void SString::PVPrintf(const WCHAR *format, va_list args) else if (errno!=0 && errno!=EBADF && errno!=ERANGE) { - CONSISTENCY_CHECK_MSG(FALSE, "_vsnwprintf failed. Potential globalization bug."); + CONSISTENCY_CHECK_MSG(FALSE, "_vsnwprintf_s failed. Potential globalization bug."); ThrowHR(HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION)); } } diff --git a/src/utilcode/stacktrace.cpp b/src/utilcode/stacktrace.cpp index 7bfdb45..858fac7 100644 --- a/src/utilcode/stacktrace.cpp +++ b/src/utilcode/stacktrace.cpp @@ -208,7 +208,7 @@ typedef DWORD (_stdcall *pfnImgHlp_SymGetOptions)( struct IMGHLPFN_LOAD { - LPSTR pszFnName; + LPCSTR pszFnName; LPVOID * ppvfn; }; @@ -520,7 +520,7 @@ DWORD_PTR dwAddr } CHAR rgchUndec[256]; - CHAR * pszSymbol = NULL; + const CHAR * pszSymbol = NULL; // Name field of IMAGEHLP_SYMBOL is dynamically sized. // Pad with space for 255 characters. diff --git a/src/utilcode/stresslog.cpp b/src/utilcode/stresslog.cpp index f4b8961..d364b06 100644 --- a/src/utilcode/stresslog.cpp +++ b/src/utilcode/stresslog.cpp @@ -51,7 +51,7 @@ unsigned __int64 getTimeStamp() { #endif // _TARGET_X86_ -#if defined(_TARGET_X86_) +#if defined(_TARGET_X86_) && !defined(FEATURE_PAL) /*********************************************************************************/ /* Get the the frequency cooresponding to 'getTimeStamp'. For x86, this is the diff --git a/src/vm/CMakeLists.txt b/src/vm/CMakeLists.txt index 6f17a90..9fdddd6 100644 --- a/src/vm/CMakeLists.txt +++ b/src/vm/CMakeLists.txt @@ -70,6 +70,7 @@ set(VM_SOURCES_DAC_AND_WKS_COMMON formattype.cpp fptrstubs.cpp frames.cpp + gcheaputilities.cpp genericdict.cpp generics.cpp hash.cpp @@ -116,7 +117,6 @@ set(VM_SOURCES_DAC_AND_WKS_COMMON virtualcallstub.cpp win32threadpool.cpp zapsig.cpp - ${VM_SOURCES_GDBJIT} ) if(FEATURE_READYTORUN) @@ -155,7 +155,6 @@ set(VM_SOURCES_WKS comthreadpool.cpp comutilnative.cpp comwaithandle.cpp - constrainedexecutionregion.cpp coverage.cpp customattribute.cpp custommarshalerinfo.cpp @@ -172,7 +171,6 @@ set(VM_SOURCES_WKS frameworkexceptionloader.cpp gccover.cpp gcenv.ee.cpp - gcenv.os.cpp gchelpers.cpp genmeth.cpp hosting.cpp @@ -240,14 +238,27 @@ set(VM_SOURCES_WKS typeparse.cpp verifier.cpp weakreferencenative.cpp + ${VM_SOURCES_GDBJIT} ) +if(FEATURE_CER) + list(APPEND VM_SOURCES_WKS + constrainedexecutionregion.cpp + ) +endif(FEATURE_CER) + if(FEATURE_EVENT_TRACE) list(APPEND VM_SOURCES_WKS eventtrace.cpp ) endif(FEATURE_EVENT_TRACE) +if(NOT FEATURE_STANDALONE_GC) + list(APPEND VM_SOURCES_WKS + gcenv.os.cpp + ) +endif(NOT FEATURE_STANDALONE_GC) + if(WIN32) set(VM_SOURCES_DAC_AND_WKS_WIN32 @@ -364,6 +375,13 @@ else(WIN32) ${ARCH_SOURCES_DIR}/umthunkstub.S ${ARCH_SOURCES_DIR}/virtualcallstubamd64.S ) + elseif(CLR_CMAKE_TARGET_ARCH_I386) + set(VM_SOURCES_WKS_ARCH_ASM + ${ARCH_SOURCES_DIR}/asmhelpers.S + ${ARCH_SOURCES_DIR}/jithelp.S + ${ARCH_SOURCES_DIR}/gmsasm.S + ${ARCH_SOURCES_DIR}/umthunkstub.S + ) elseif(CLR_CMAKE_TARGET_ARCH_ARM) set(VM_SOURCES_WKS_ARCH_ASM ${ARCH_SOURCES_DIR}/asmhelpers.S @@ -412,7 +430,6 @@ elseif(CLR_CMAKE_TARGET_ARCH_I386) ) set(VM_SOURCES_WKS_ARCH - ${ARCH_SOURCES_DIR}/jithelp.asm ${ARCH_SOURCES_DIR}/jitinterfacex86.cpp ${ARCH_SOURCES_DIR}/profiler.cpp ) diff --git a/src/vm/amd64/CrtHelpers.asm b/src/vm/amd64/CrtHelpers.asm index 6ec6e4d..9d5b280 100644 --- a/src/vm/amd64/CrtHelpers.asm +++ b/src/vm/amd64/CrtHelpers.asm @@ -13,48 +13,19 @@ ; *********************************************************************** include AsmMacros.inc -include asmconstants.inc -; JIT_MemSet/JIT_MemCpy -; -; It is IMPORANT that the exception handling code is able to find these guys -; on the stack, but to keep them from being tailcalled by VC++ we need to turn -; off optimization and it ends up being a wasteful implementation. -; -; Hence these assembly helpers. -; - - -;*** -;memset.asm - set a section of memory to all one byte -; -; 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.; -; -;******************************************************************************* - -;*** ;char *memset(dst, value, count) - sets "count" bytes at "dst" to "value" ; ;Purpose: ; Sets the first "count" bytes of the memory starting ; at "dst" to the character value "value". ; -; Algorithm: -; char * -; memset (dst, value, count) -; char *dst; -; char value; -; unsigned int count; -; { -; char *start = dst; -; -; while (count--) -; *dst++ = value; -; return(start); -; } -; +;Algorithm: +;Set dst based on count as follow +; count [0, 16]: use 1/2/4/8 bytes width registers +; count [16, 128]: use 16 bytes width registers (XMM) without loop +; count [128, 512]: use 16 bytes width registers (XMM) with loops, unrolled 8 times +; count [512, upper]: use rep stosb ;Entry: ; char *dst - pointer to memory to fill with value ; char value - value to put in dst bytes @@ -69,460 +40,291 @@ include asmconstants.inc ; ;******************************************************************************* -CACHE_LIMIT_MEMSET equ 070000h ; limit for nontemporal fill - LEAF_ENTRY JIT_MemSet, _TEXT - mov rax, rcx ; save destination address - cmp r8, 8 ; check if 8 bytes to fill - jb short mset40 ; if b, less than 8 bytes to fill movzx edx, dl ; set fill pattern - mov r9, 0101010101010101h ; replicate fill over 8 bytes - imul rdx, r9 ; - cmp r8, 64 ; check if 64 bytes to fill - jb short mset20 ; if b, less than 64 bytes - -; -; Large block - fill alignment bytes. -; - -mset00: neg rcx ; compute bytes to alignment - and ecx, 7 ; - jz short mset10 ; if z, no alignment required - sub r8, rcx ; adjust remaining bytes by alignment - mov [rax], rdx ; fill alignment bytes -mset10: add rcx, rax ; compute aligned destination address - -; -; Attempt to fill 64-byte blocks -; - - mov r9, r8 ; copy count of bytes remaining - and r8, 63 ; compute remaining byte count - shr r9, 6 ; compute number of 64-byte blocks - test r9, r9 ; remove partial flag stall caused by shr - jnz short mset70 ; if nz, 64-byte blocks to fill - -; -; Fill 8-byte bytes. -; - -mset20: mov r9, r8 ; copy count of bytes remaining - and r8, 7 ; compute remaining byte count - shr r9, 3 ; compute number of 8-byte blocks - test r9, r9 ; remove partial flag stall caused by shr - jz short mset40 ; if z, no 8-byte blocks - - align ; simpler way to align instrucitons - -mset30: mov [rcx], rdx ; fill 8-byte blocks - add rcx, 8 ; advance to next 8-byte block - dec r9 ; decrement loop count - jnz short mset30 ; if nz, more 8-byte blocks - -; -; Fill residual bytes. -; - -mset40: test r8, r8 ; test if any bytes to fill - jz short mset60 ; if z, no bytes to fill -mset50: mov [rcx], dl ; fill byte - inc rcx ; advance to next byte - dec r8 ; decrement loop count - jnz short mset50 ; if nz, more bytes to fill -mset60: - ; for some reason the assembler doesn't like the REPRET macro on the same line as a label - REPRET ; return - -; -; Fill 64-byte blocks. -; - - align 16 - - db 066h, 066h, 066h, 090h - db 066h, 066h, 090h - -mset70: cmp r9, CACHE_LIMIT_MEMSET / 64 ; check if large fill - jae short mset90 ; if ae, large fill -mset80: mov [rcx], rdx ; fill 64-byte block - mov 8[rcx], rdx ; - mov 16[rcx], rdx ; - add rcx, 64 ; advance to next block - mov (24 - 64)[rcx], rdx ; - mov (32 - 64)[rcx], rdx ; - dec r9 ; decrement loop count - mov (40 - 64)[rcx], rdx ; - mov (48 - 64)[rcx], rdx ; - mov (56 - 64)[rcx], rdx ; - jnz short mset80 ; if nz, more 64-byte blocks - jmp short mset20 ; finish in common code - -; -; Fill 64-byte blocks nontemporal. -; - - align - -mset90: movnti [rcx], rdx ; fill 64-byte block - movnti 8[rcx], rdx ; - movnti 16[rcx], rdx ; - add rcx, 64 ; advance to next block - movnti (24 - 64)[rcx], rdx ; - movnti (32 - 64)[rcx], rdx ; - dec r9 ; decrement loop count - movnti (40 - 64)[rcx], rdx ; - movnti (48 - 64)[rcx], rdx ; - movnti (56 - 64)[rcx], rdx ; - jnz short mset90 ; if nz, move 64-byte blocks - lock or byte ptr [rsp], 0 ; flush data to memory - jmp mset20 ; finish in common code + mov r9, 0101010101010101h + imul rdx, r9 ; rdx is 8 bytes filler + + cmp r8, 16 + jbe mset04 + + cmp r8, 512 + jbe mset00 + + ; count > 512 + mov r10, rcx ; save dst address + mov r11, rdi ; save rdi + mov eax, edx ; eax is value + mov rdi, rcx ; rdi is dst + mov rcx, r8 ; rcx is count + rep stosb + mov rdi, r11 ; restore rdi + mov rax, r10 + ret + + align 16 +mset00: mov rax, rcx ; save dst address + movd xmm0, rdx + punpcklbw xmm0, xmm0 ; xmm0 is 16 bytes filler + + cmp r8, 128 + jbe mset02 + + ; count > 128 && count <= 512 + mov r9, r8 + shr r9, 7 ; count/128 + + align 16 +mset01: movdqu [rcx], xmm0 + movdqu 16[rcx], xmm0 + movdqu 32[rcx], xmm0 + movdqu 48[rcx], xmm0 + movdqu 64[rcx], xmm0 + movdqu 80[rcx], xmm0 + movdqu 96[rcx], xmm0 + movdqu 112[rcx], xmm0 + add rcx, 128 + dec r9 + jnz mset01 + and r8, 7fh ; and r8 with 0111 1111 + + ; the remainder is from 0 to 127 + cmp r8, 16 + jnbe mset02 + + ; the remainder <= 16 + movdqu -16[rcx + r8], xmm0 + ret + + ; count > 16 && count <= 128 for mset02 + align 16 +mset02: movdqu [rcx], xmm0 + movdqu -16[rcx + r8], xmm0 + cmp r8, 32 + jbe mset03 + + ; count > 32 && count <= 64 + movdqu 16[rcx], xmm0 + movdqu -32[rcx + r8], xmm0 + cmp r8, 64 + jbe mset03 + + ; count > 64 && count <= 128 + movdqu 32[rcx], xmm0 + movdqu 48[rcx], xmm0 + movdqu -48[rcx + r8], xmm0 + movdqu -64[rcx + r8], xmm0 +mset03: ret + + align 16 +mset04: mov rax, rcx ; save dst address + test r8b, 24 ; and r8b with 0001 1000 + jz mset05 + + ; count >= 8 && count <= 16 + mov [rcx], rdx + mov -8[rcx + r8], rdx + ret + + align 16 +mset05: test r8b, 4 ; and r8b with 0100 + jz mset06 + + ; count >= 4 && count < 8 + mov [rcx], edx + mov -4[rcx + r8], edx + ret + + ; count >= 0 && count < 4 + align 16 +mset06: test r8b, 1 ; and r8b with 0001 + jz mset07 + mov [rcx],dl +mset07: test r8b, 2 ; and r8b with 0010 + jz mset08 + mov -2[rcx + r8], dx +mset08: ret LEAF_END_MARKED JIT_MemSet, _TEXT -;******************************************************************************* -; This ensures that atomic updates of aligned fields will stay atomic. -;*** ;JIT_MemCpy - Copy source buffer to destination buffer ; ;Purpose: -;JIT_MemCpy - Copy source buffer to destination buffer -; -;Purpose: -; JIT_MemCpy() copies a source memory buffer to a destination memory -; buffer. This routine recognize overlapping buffers to avoid propogation. -; For cases where propogation is not a problem, memcpy() can be used. +; JIT_MemCpy() copies a source memory buffer to a destination memory +; buffer. This routine recognize overlapping buffers to avoid propogation. +; For cases where propogation is not a problem, memcpy() can be used. +; +;Algorithm: +;Copy to destination based on count as follow +; count [0, 64]: overlap check not needed +; count [0, 16]: use 1/2/4/8 bytes width registers +; count [16, 64]: use 16 bytes width registers (XMM) without loop +; count [64, upper]: check overlap +; non-overlap: +; count [64, 512]: use 16 bytes width registers (XMM) with loops, unrolled 4 times +; count [512, upper]: use rep movsb +; overlap:: +; use 16 bytes width registers (XMM) with loops to copy from end to beginnig ; ;Entry: -; void *dst = pointer to destination buffer -; const void *src = pointer to source buffer -; size_t count = number of bytes to copy +; void *dst = pointer to destination buffer +; const void *src = pointer to source buffer +; size_t count = number of bytes to copy ; ;Exit: -; Returns a pointer to the destination buffer in AX/DX:AX +; Returns a pointer to the destination buffer ; ;Uses: -; CX, DX ; ;Exceptions: ;******************************************************************************* -; This ensures that atomic updates of aligned fields will stay atomic. - -CACHE_LIMIT_MEMMOV equ 040000h ; limit for nontemporal fill -CACHE_BLOCK equ 01000h ; nontemporal move block size - LEAF_ENTRY JIT_MemCpy, _TEXT - mov r11, rcx ; save destination address - sub rdx, rcx ; compute offset to source buffer - jb mmov10 ; if b, destination may overlap - cmp r8, 8 ; check if 8 bytes to move - jb short mcpy40 ; if b, less than 8 bytes to move - -; -; Move alignment bytes. -; - - test cl, 7 ; test if destination aligned - jz short mcpy20 ; if z, destination aligned - test cl, 1 ; test if byte move needed - jz short mcpy00 ; if z, byte move not needed - mov al, [rcx + rdx] ; move byte - dec r8 ; decrement byte count - mov [rcx], al ; - inc rcx ; increment destination address -mcpy00: test cl, 2 ; test if word move needed - jz short mcpy10 ; if z, word move not needed - mov ax, [rcx + rdx] ; move word - sub r8, 2 ; reduce byte count - mov [rcx], ax ; - add rcx, 2 ; advance destination address -mcpy10: test cl, 4 ; test if dword move needed - jz short mcpy20 ; if z, dword move not needed - mov eax, [rcx + rdx] ; move dword - sub r8, 4 ; reduce byte count - mov [rcx], eax ; - add rcx, 4 ; advance destination address - -; -; Attempt to move 32-byte blocks. -; - -mcpy20: mov r9, r8 ; copy count of bytes remaining - shr r9, 5 ; compute number of 32-byte blocks - test r9, r9 ; v-liti, remove partial flag stall caused by shr - jnz short mcpy60 ; if nz, 32-byte blocks to fill - - align -; -; Move 8-byte blocks. -; - -mcpy25: mov r9, r8 ; copy count of bytes remaining - shr r9, 3 ; compute number of 8-byte blocks - test r9, r9 ; v-liti, remove partial flag stall caused by shr - jz short mcpy40 ; if z, no 8-byte blocks - align - -mcpy30: mov rax, [rcx + rdx] ; move 8-byte blocks - mov [rcx], rax ; - add rcx, 8 ; advance destination address - dec r9 ; decrement loop count - jnz short mcpy30 ; if nz, more 8-byte blocks - and r8, 7 ; compute remaining byte count - -; -; Test for residual bytes. -; - -mcpy40: test r8, r8 ; test if any bytes to move - jnz short mcpy50 ; if nz, residual bytes to move - mov rax, r11 ; set destination address - ret ; - -; -; Move residual bytes. -; - - align - -mcpy50: mov al, [rcx + rdx] ; move byte - mov [rcx], al ; - inc rcx ; increment destiantion address - dec r8 ; decrement loop count - jnz short mcpy50 ; if nz, more bytes to fill - mov rax, r11 ; set destination address - ret ; return + mov rax, rcx ; save dst address + cmp r8, 16 + jbe mcpy02 + + cmp r8, 64 + jnbe mcpy07 + + ; count > 16 && count <= 64 + align 16 +mcpy00: movdqu xmm0, [rdx] + movdqu xmm1, -16[rdx + r8] ; save 16 to 32 bytes src + cmp r8, 32 + jbe mcpy01 + + movdqu xmm2, 16[rdx] + movdqu xmm3, -32[rdx + r8] ; save 32 to 64 bytes src + + ;count > 32 && count <= 64 + movdqu 16[rcx], xmm2 + movdqu -32[rcx + r8], xmm3 + + ;count > 16 && count <= 32 +mcpy01: movdqu [rcx], xmm0 + movdqu -16[rcx + r8], xmm1 + ret + + ; count <= 16 + align 16 +mcpy02: test r8b, 24 ; test count with 0001 1000 + jz mcpy03 + ; count >= 8 && count <= 16 + mov r9, [rdx] + mov r10, -8[rdx + r8] + mov [rcx], r9 + mov -8[rcx + r8], r10 + ret + + align 16 +mcpy03: test r8b, 4 ; test count with 0100 + jz mcpy04 + ; count >= 4 && count < 8 + mov r9d, [rdx] + mov r10d, -4[rdx + r8] + mov [rcx], r9d + mov -4[rcx + r8], r10d + ret + + ; count >= 0 && count < 4 + align 16 +mcpy04: test r8, r8 + jz mcpy06 ; count == 1/2/3 + mov r9b, [rdx] ; save the first byte + + test r8b, 2 ; test count with 0010 + jz mcpy05 + mov r10w, -2[rdx + r8] + mov -2[rcx + r8], r10w +mcpy05: mov [rcx], r9b +mcpy06: ret + + align 16 + ; count > 64, we need to check overlap +mcpy07: mov r9, rdx ; r9 is src address + sub r9, rcx ; if src - dst < 0 jump to mcpy11 + jb mcpy11 ; if b, destination may overlap + +mcpy08: cmp r8, 512 + jnbe mcpy10 + + ; count > 64 && count <= 512 + mov r9, r8 + shr r9, 6 ; count/64 + + align 16 +mcpy09: movdqu xmm0, [rdx] + movdqu xmm1, 16[rdx] + movdqu xmm2, 32[rdx] + movdqu xmm3, 48[rdx] + movdqu [rcx], xmm0 + movdqu 16[rcx], xmm1 + movdqu 32[rcx], xmm2 + movdqu 48[rcx], xmm3 + add rdx, 64 + add rcx, 64 + dec r9 + jnz mcpy09 + + ; the remainder is from 0 to 63 + and r8, 3fh ; and with 0011 1111 + cmp r8, 16 + jnbe mcpy00 + + ; the remainder <= 16 + jmp mcpy02 + ret + + ; count > 512 + align 16 +mcpy10: mov r10, rdi ; save rdi + mov r11, rsi ; save rsi + mov rdi, rcx ; rdi is dst + mov rsi, rdx ; rsi is src + mov rcx, r8 ; rcx is count + rep movsb ; mov from rsi to rdi + mov rsi, r11 ; restore rsi + mov rdi, r10 ; restore rdi + ret -; -; Move 32 byte blocks -; - - align 16 - - db 066h, 066h, 066h, 090h - db 066h, 066h, 090h - -mcpy60: cmp r9, CACHE_LIMIT_MEMMOV / 32 ; check if large move - jae short mcpy80 ; if ae, large move -mcpy70: mov rax, [rcx + rdx] ; move 32-byte block - mov r10, 8[rcx + rdx] ; - add rcx, 32 ; advance destination address - mov (-32)[rcx], rax ; - mov (-24)[rcx], r10 ; - mov rax, (-16)[rcx + rdx] ; - mov r10, (-8)[rcx + rdx] ; - dec r9 ; - mov (-16)[rcx], rax ; - mov (-8)[rcx], r10 ; - jnz short mcpy70 ; if nz, more 32-byte blocks - and r8, 31 ; compute remaining byte count - jmp mcpy25 ; - -; -; Move 64-byte blocks nontemporal. -; - - align - - db 066h, 090h - -mcpy80: cmp rdx, CACHE_BLOCK ; check if cache block spacing - jb short mcpy70 ; if b, not cache block spaced -mcpy81: mov eax, CACHE_BLOCK / 128 ; set loop count -mcpy85: prefetchnta [rcx + rdx] ; prefetch 128 bytes - prefetchnta 64[rcx + rdx] ; - add rcx, 128 ; advance source address - dec eax ; decrement loop count - jnz short mcpy85 ; if nz, more to prefetch - sub rcx, CACHE_BLOCK ; reset source address - mov eax, CACHE_BLOCK / 64 ; set loop count -mcpy90: mov r9, [rcx + rdx] ; move 64-byte block - mov r10, 8[rcx + rdx] ; - movnti [rcx], r9 ; - movnti 8[rcx], r10 ; - mov r9, 16[rcx + rdx] ; - mov r10, 24[rcx + rdx] ; - movnti 16[rcx], r9 ; - movnti 24[rcx], r10 ; - mov r9, 32[rcx + rdx] ; - mov r10, 40[rcx + rdx] ; - add rcx, 64 ; advance destination address - movnti (32 - 64)[rcx], r9 ; - movnti (40 - 64)[rcx], r10 ; - mov r9, (48 - 64)[rcx + rdx] ; - mov r10, (56 - 64)[rcx + rdx] ; - dec eax ; - movnti (48 - 64)[rcx], r9 ; - movnti (56 - 64)[rcx], r10 ; - jnz short mcpy90 ; if nz, more 32-byte blocks - sub r8, CACHE_BLOCK ; reduce remaining length - cmp r8, CACHE_BLOCK ; check if cache block remains - jae mcpy81 ; if ae, cache block remains - lock or byte ptr [rsp], 0 ; flush data to memory - jmp mcpy20 ; - -; ; The source address is less than the destination address. -; - - align - - db 066h, 066h, 066h, 090h - db 066h, 066h, 066h, 090h - db 066h, 090h - -mmov10: add rcx, r8 ; compute ending destination address - cmp r8, 8 ; check if 8 bytes to move - jb short mmov60 ; if b, less than 8 bytes to move - -; -; Move alignment bytes. -; - - test cl, 7 ; test if destination aligned - jz short mmov30 ; if z, destination aligned - test cl, 1 ; test if byte move needed - jz short mmov15 ; if z, byte move not needed - dec rcx ; decrement destination address - mov al, [rcx + rdx] ; move byte - dec r8 ; decrement byte count - mov [rcx], al ; -mmov15: test cl, 2 ; test if word move needed - jz short mmov20 ; if z, word move not needed - sub rcx, 2 ; reduce destination address - mov ax, [rcx + rdx] ; move word - sub r8, 2 ; reduce byte count - mov [rcx], ax ; -mmov20: test cl, 4 ; test if dword move needed - jz short mmov30 ; if z, dword move not needed - sub rcx, 4 ; reduce destination address - mov eax, [rcx + rdx] ; move dword - sub r8, 4 ; reduce byte count - mov [rcx], eax ; - -; -; Attempt to move 32-byte blocks -; - -mmov30: mov r9, r8 ; copy count of bytes remaining - shr r9, 5 ; compute number of 32-byte blocks - test r9, r9 ; v-liti, remove partial flag stall caused by shr - jnz short mmov80 ; if nz, 32-byte blocks to fill - -; -; Move 8-byte blocks. -; - align - -mmov40: mov r9, r8 ; copy count of bytes remaining - shr r9, 3 ; compute number of 8-byte blocks - test r9, r9 ; v-liti, remove partial flag stall caused by shr - jz short mmov60 ; if z, no 8-byte blocks - - align - -mmov50: sub rcx, 8 ; reduce destination address - mov rax, [rcx + rdx] ; move 8-byte blocks - dec r9 ; decrement loop count - mov [rcx], rax ; - jnz short mmov50 ; if nz, more 8-byte blocks - and r8, 7 ; compute remaining byte count - -; -; Test for residual bytes. -; - -mmov60: test r8, r8 ; test if any bytes to move - jnz short mmov70 ; if nz, residual bytes to move - mov rax, r11 ; set destination address - ret ; - -; -; Move residual bytes. -; - - align -mmov70: dec rcx ; decrement destination address - mov al, [rcx + rdx] ; move byte - dec r8 ; decrement loop count - mov [rcx], al ; - jnz short mmov70 ; if nz, more bytes to fill - mov rax, r11 ; set destination address - ret ; return - -; -; Move 32 byte blocks -; - - align 16 - - db 066h, 066h, 066h, 090h - db 066h, 066h, 090h - -mmov80: cmp r9, CACHE_LIMIT_MEMMOV / 32 ; check if large move - jae short mmov93 ; if ae, large move -mmov90: mov rax, (-8)[rcx + rdx] ; move 32-byte block - mov r10, (-16)[rcx + rdx] ; - sub rcx, 32 ; reduce destination address - mov 24[rcx], rax ; - mov 16[rcx], r10 ; - mov rax, 8[rcx + rdx] ; - mov r10, [rcx + rdx] ; - dec r9 ; - mov 8[rcx], rax ; - mov [rcx], r10 ; - jnz short mmov90 ; if nz, more 32-byte blocks - and r8, 31 ; compute remaining byte count - jmp mmov40 ; - -; -; Move 64-byte blocks nontemporal. -; - - align - - db 066h, 090h - -mmov93: cmp rdx, -CACHE_BLOCK ; check if cache block spacing - ja short mmov90 ; if a, not cache block spaced -mmov94: mov eax, CACHE_BLOCK / 128 ; set loop count -mmov95: sub rcx, 128 ; reduce destination address - prefetchnta [rcx + rdx] ; prefetch 128 bytes - prefetchnta 64[rcx + rdx] ; - dec eax ; decrement loop count - jnz short mmov95 ; if nz, more to prefetch - add rcx, CACHE_BLOCK ; reset source address - mov eax, CACHE_BLOCK / 64 ; set loop count -mmov97: mov r9, (-8)[rcx + rdx] ; move 64-byte block - mov r10, (-16)[rcx + rdx] ; - movnti (-8)[rcx], r9 ; - movnti (-16)[rcx], r10 ; - mov r9, (-24)[rcx + rdx] ; - mov r10, (-32)[rcx + rdx] ; - movnti (-24)[rcx], r9 ; - movnti (-32)[rcx], r10 ; - mov r9, (-40)[rcx + rdx] ; - mov r10, (-48)[rcx + rdx] ; - sub rcx, 64 ; reduce destination address - movnti (64 - 40)[rcx], r9 ; - movnti (64 - 48)[rcx], r10 ; - mov r9, (64 - 56)[rcx + rdx] ; - mov r10, (64 - 64)[rcx + rdx] ; - dec eax ; decrement loop count - movnti (64 - 56)[rcx], r9 ; - movnti (64 - 64)[rcx], r10 ; - jnz short mmov97 ; if nz, more 32-byte blocks - sub r8, CACHE_BLOCK ; reduce remaining length - cmp r8, CACHE_BLOCK ; check if cache block remains - jae mmov94 ; if ae, cache block remains - lock or byte ptr [rsp], 0 ; flush data to memory - jmp mmov30 ; + align 16 +mcpy11: add r9, r8 ; src - dst + count + cmp r9, 0 ; src + count < = dst jump to mcpy08 + jle mcpy08 + + lea r9, [rdx + r8] ; r9 is the src + count + lea r10, [rcx + r8] ; r10 is the dst + count + + mov r11, r8 + shr r11, 6 ; count/64 + + ; count > 64 + align 16 +mcpy12: movdqu xmm0, -16[r9] + movdqu xmm1, -32[r9] + movdqu xmm2, -48[r9] + movdqu xmm3, -64[r9] + movdqu -16[r10], xmm0 + movdqu -32[r10], xmm1 + movdqu -48[r10], xmm2 + movdqu -64[r10], xmm3 + sub r9, 64 + sub r10, 64 + dec r11 + jnz mcpy12 + + ; the remainder is from 0 to 63 + and r8, 3fh ; and with 0011 1111 + cmp r8, 16 + jnbe mcpy00 + + ; the remainder <= 16 + jmp mcpy02 LEAF_END_MARKED JIT_MemCpy, _TEXT - - - end - + end \ No newline at end of file diff --git a/src/vm/amd64/asmconstants.h b/src/vm/amd64/asmconstants.h index 32b23c8..ad90dd1 100644 --- a/src/vm/amd64/asmconstants.h +++ b/src/vm/amd64/asmconstants.h @@ -164,10 +164,10 @@ ASMCONSTANTS_C_ASSERT(OFFSETOF__Thread__m_ThreadId == offsetof(Thread, m_ThreadId)); #define OFFSET__Thread__m_alloc_context__alloc_ptr 0x60 -ASMCONSTANTS_C_ASSERT(OFFSET__Thread__m_alloc_context__alloc_ptr == offsetof(Thread, m_alloc_context) + offsetof(alloc_context, alloc_ptr)); +ASMCONSTANTS_C_ASSERT(OFFSET__Thread__m_alloc_context__alloc_ptr == offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_ptr)); #define OFFSET__Thread__m_alloc_context__alloc_limit 0x68 -ASMCONSTANTS_C_ASSERT(OFFSET__Thread__m_alloc_context__alloc_limit == offsetof(Thread, m_alloc_context) + offsetof(alloc_context, alloc_limit)); +ASMCONSTANTS_C_ASSERT(OFFSET__Thread__m_alloc_context__alloc_limit == offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_limit)); #define OFFSETOF__ThreadExceptionState__m_pCurrentTracker 0x000 ASMCONSTANTS_C_ASSERT(OFFSETOF__ThreadExceptionState__m_pCurrentTracker diff --git a/src/vm/amd64/cgencpu.h b/src/vm/amd64/cgencpu.h index 258ac38..769f402 100644 --- a/src/vm/amd64/cgencpu.h +++ b/src/vm/amd64/cgencpu.h @@ -65,14 +65,16 @@ EXTERN_C void FastCallFinalizeWorker(Object *obj, PCODE funcPtr); #define CACHE_LINE_SIZE 64 // Current AMD64 processors have 64-byte cache lines as per AMD64 optmization manual #define LOG2SLOT LOG2_PTRSIZE -#define ENREGISTERED_RETURNTYPE_INTEGER_MAXSIZE 8 // bytes -#define ENREGISTERED_PARAMTYPE_MAXSIZE 8 // bytes #ifdef UNIX_AMD64_ABI +#define ENREGISTERED_RETURNTYPE_INTEGER_MAXSIZE 16 // bytes +#define ENREGISTERED_PARAMTYPE_MAXSIZE 16 // bytes #define ENREGISTERED_RETURNTYPE_MAXSIZE 16 // bytes #define CALLDESCR_ARGREGS 1 // CallDescrWorker has ArgumentRegister parameter #define CALLDESCR_FPARGREGS 1 // CallDescrWorker has FloatArgumentRegisters parameter #else +#define ENREGISTERED_RETURNTYPE_INTEGER_MAXSIZE 8 // bytes +#define ENREGISTERED_PARAMTYPE_MAXSIZE 8 // bytes #define ENREGISTERED_RETURNTYPE_MAXSIZE 8 // bytes #define COM_STUBS_SEPARATE_FP_LOCATIONS #define CALLDESCR_REGTYPEMAP 1 diff --git a/src/vm/amd64/excepamd64.cpp b/src/vm/amd64/excepamd64.cpp index 2fc553a..d4248e7 100644 --- a/src/vm/amd64/excepamd64.cpp +++ b/src/vm/amd64/excepamd64.cpp @@ -21,7 +21,7 @@ #include "comutilnative.h" #include "sigformat.h" #include "siginfo.hpp" -#include "gc.h" +#include "gcheaputilities.h" #include "eedbginterfaceimpl.h" //so we can clearexception in COMPlusThrow #include "perfcounters.h" #include "asmconstants.h" diff --git a/src/vm/amd64/jitinterfaceamd64.cpp b/src/vm/amd64/jitinterfaceamd64.cpp index 39c2e05..d5dec8e 100644 --- a/src/vm/amd64/jitinterfaceamd64.cpp +++ b/src/vm/amd64/jitinterfaceamd64.cpp @@ -390,7 +390,7 @@ bool WriteBarrierManager::NeedDifferentWriteBarrier(bool bReqUpperBoundsCheck, W } #endif - writeBarrierType = GCHeap::IsServerHeap() ? WRITE_BARRIER_SVR64 : WRITE_BARRIER_PREGROW64; + writeBarrierType = GCHeapUtilities::IsServerHeap() ? WRITE_BARRIER_SVR64 : WRITE_BARRIER_PREGROW64; continue; case WRITE_BARRIER_PREGROW64: diff --git a/src/vm/amd64/umthunkstub.S b/src/vm/amd64/umthunkstub.S index e388f15..3e60bed 100644 --- a/src/vm/amd64/umthunkstub.S +++ b/src/vm/amd64/umthunkstub.S @@ -83,7 +83,7 @@ LOCAL_LABEL(HaveThread): mov r12, rax // r12 <- Thread* - //FailFast if a native callable method invoked via ldftn and calli. + //FailFast if a native callable method is invoked via ldftn and calli. cmp dword ptr [r12 + OFFSETOF__Thread__m_fPreemptiveGCDisabled], 1 jz LOCAL_LABEL(InvalidTransition) diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp index 0ec2c5f..34da344 100644 --- a/src/vm/appdomain.cpp +++ b/src/vm/appdomain.cpp @@ -12,7 +12,7 @@ #include "strongnameinternal.h" #include "excep.h" #include "eeconfig.h" -#include "gc.h" +#include "gcheaputilities.h" #include "eventtrace.h" #ifdef FEATURE_FUSION #include "assemblysink.h" @@ -2652,8 +2652,8 @@ void AppDomain::CreateADUnloadStartEvent() // If the thread is in cooperative mode, it must have been suspended for the GC so a delete // can't happen. - _ASSERTE(GCHeap::IsGCInProgress() && - GCHeap::IsServerHeap() && + _ASSERTE(GCHeapUtilities::IsGCInProgress() && + GCHeapUtilities::IsServerHeap() && IsGCSpecialThread()); SystemDomain* sysDomain = SystemDomain::System(); @@ -2691,7 +2691,7 @@ void SystemDomain::ResetADSurvivedBytes() } CONTRACT_END; - _ASSERTE(GCHeap::IsGCInProgress()); + _ASSERTE(GCHeapUtilities::IsGCInProgress()); SystemDomain* sysDomain = SystemDomain::System(); if (sysDomain) @@ -2870,6 +2870,11 @@ void SystemDomain::LoadBaseSystemClasses() // the SZArrayHelper class here. g_pSZArrayHelperClass = MscorlibBinder::GetClass(CLASS__SZARRAYHELPER); +#ifdef FEATURE_SPAN_OF_T + // Load ByReference class + g_pByReferenceClass = MscorlibBinder::GetClass(CLASS__BYREFERENCE); +#endif + // Load Nullable class g_pNullableClass = MscorlibBinder::GetClass(CLASS__NULLABLE); @@ -2943,6 +2948,7 @@ void SystemDomain::LoadBaseSystemClasses() g_pExecutionEngineExceptionClass = MscorlibBinder::GetException(kExecutionEngineException); g_pThreadAbortExceptionClass = MscorlibBinder::GetException(kThreadAbortException); +#ifdef FEATURE_CER // Used for determining whether a class has a critical finalizer // To determine whether a class has a critical finalizer, we // currently will simply see if it's parent class has a critical @@ -2951,6 +2957,7 @@ void SystemDomain::LoadBaseSystemClasses() // here. g_pCriticalFinalizerObjectClass = MscorlibBinder::GetClass(CLASS__CRITICAL_FINALIZER_OBJECT); _ASSERTE(g_pCriticalFinalizerObjectClass->HasCriticalFinalizer()); +#endif // used by gc to handle predefined agility checking g_pThreadClass = MscorlibBinder::GetClass(CLASS__THREAD); @@ -2980,7 +2987,9 @@ void SystemDomain::LoadBaseSystemClasses() // Load a special marker method used to detect Constrained Execution Regions // at jit time. +#ifdef FEATURE_CER g_pPrepareConstrainedRegionsMethod = MscorlibBinder::GetMethod(METHOD__RUNTIME_HELPERS__PREPARE_CONSTRAINED_REGIONS); +#endif g_pExecuteBackoutCodeHelperMethod = MscorlibBinder::GetMethod(METHOD__RUNTIME_HELPERS__EXECUTE_BACKOUT_CODE_HELPER); // Make sure that FCall mapping for Monitor.Enter is initialized. We need it in case Monitor.Enter is used only as JIT helper. @@ -3824,7 +3833,7 @@ HRESULT SystemDomain::RunDllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpReser return S_OK; // ExitProcess is called while a thread is doing GC. - if (dwReason == DLL_PROCESS_DETACH && GCHeap::IsGCInProgress()) + if (dwReason == DLL_PROCESS_DETACH && GCHeapUtilities::IsGCInProgress()) return S_OK; // ExitProcess is called on a thread that we don't know about @@ -5107,7 +5116,7 @@ void AppDomain::Init() // Ref_CreateHandleTableBucket, this is because AD::Init() can race with GC // and once we add ourselves to the handle table map the GC can start walking // our handles and calling AD::RecordSurvivedBytes() which touches ARM data. - if (GCHeap::IsServerHeap()) + if (GCHeapUtilities::IsServerHeap()) m_dwNumHeaps = CPUGroupInfo::CanEnableGCCPUGroups() ? CPUGroupInfo::GetNumActiveProcessors() : GetCurrentProcessCpuCount(); @@ -8084,6 +8093,13 @@ BOOL AppDomain::IsCached(AssemblySpec *pSpec) return m_AssemblyCache.Contains(pSpec); } +#ifdef FEATURE_CORECLR +void AppDomain::GetCacheAssemblyList(SetSHash& assemblyList) +{ + CrstHolder holder(&m_DomainCacheCrst); + m_AssemblyCache.GetAllAssemblies(assemblyList); +} +#endif PEAssembly* AppDomain::FindCachedFile(AssemblySpec* pSpec, BOOL fThrow /*=TRUE*/) { @@ -8241,7 +8257,7 @@ public: } else { - IfFailRet(FString::Utf8_Unicode(szName, bIsAscii, wzBuffer, cchBuffer)); + IfFailRet(FString::Utf8_Unicode(szName, bIsAscii, wzBuffer, cchName)); if (pcchBuffer != nullptr) { *pcchBuffer = cchName; @@ -11110,7 +11126,7 @@ void AppDomain::Unload(BOOL fForceUnload) } if(bForceGC) { - GCHeap::GetGCHeap()->GarbageCollect(); + GCHeapUtilities::GetGCHeap()->GarbageCollect(); FinalizerThread::FinalizerThreadWait(); SetStage(STAGE_COLLECTED); Close(); //NOTHROW! @@ -11128,14 +11144,14 @@ void AppDomain::Unload(BOOL fForceUnload) if (takeSnapShot) { char buffer[1024]; - sprintf(buffer, "vadump -p %d -o > vadump.%d", GetCurrentProcessId(), unloadCount); + sprintf_s(buffer, _countof(buffer), "vadump -p %d -o > vadump.%d", GetCurrentProcessId(), unloadCount); system(buffer); - sprintf(buffer, "umdh -p:%d -d -i:1 -f:umdh.%d", GetCurrentProcessId(), unloadCount); + sprintf_s(buffer, _countof(buffer), "umdh -p:%d -d -i:1 -f:umdh.%d", GetCurrentProcessId(), unloadCount); system(buffer); int takeDHSnapShot = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ADTakeDHSnapShot); if (takeDHSnapShot) { - sprintf(buffer, "dh -p %d -s -g -h -b -f dh.%d", GetCurrentProcessId(), unloadCount); + sprintf_s(buffer, _countof(buffer), "dh -p %d -s -g -h -b -f dh.%d", GetCurrentProcessId(), unloadCount); system(buffer); } } @@ -11146,7 +11162,7 @@ void AppDomain::Unload(BOOL fForceUnload) { // do extra finalizer wait to remove any leftover sb entries FinalizerThread::FinalizerThreadWait(); - GCHeap::GetGCHeap()->GarbageCollect(); + GCHeapUtilities::GetGCHeap()->GarbageCollect(); FinalizerThread::FinalizerThreadWait(); LogSpewAlways("Done unload %3.3d\n", unloadCount); DumpSyncBlockCache(); @@ -11548,7 +11564,7 @@ void AppDomain::ClearGCHandles() SetStage(STAGE_HANDLETABLE_NOACCESS); - GCHeap::GetGCHeap()->WaitUntilConcurrentGCComplete(); + GCHeapUtilities::GetGCHeap()->WaitUntilConcurrentGCComplete(); // Keep async pin handles alive by moving them to default domain HandleAsyncPinHandles(); @@ -12567,11 +12583,13 @@ AppDomain::RaiseAssemblyResolveEvent( { if (pSpec->GetParentAssembly() != NULL) { +#ifndef FEATURE_CORECLR if ( pSpec->IsIntrospectionOnly() #ifdef FEATURE_FUSION || pSpec->GetParentLoadContext() == LOADCTX_TYPE_UNKNOWN #endif ) +#endif // FEATURE_CORECLR { gc.AssemblyRef=pSpec->GetParentAssembly()->GetExposedAssemblyObject(); } @@ -13516,8 +13534,8 @@ void SystemDomain::ProcessDelayedUnloadDomains() } CONTRACTL_END; - int iGCRefPoint=GCHeap::GetGCHeap()->CollectionCount(GCHeap::GetGCHeap()->GetMaxGeneration()); - if (GCHeap::GetGCHeap()->IsConcurrentGCInProgress()) + int iGCRefPoint=GCHeapUtilities::GetGCHeap()->CollectionCount(GCHeapUtilities::GetGCHeap()->GetMaxGeneration()); + if (GCHeapUtilities::GetGCHeap()->IsConcurrentGCInProgress()) iGCRefPoint--; BOOL bAppDomainToCleanup = FALSE; @@ -13695,7 +13713,6 @@ ULONG ADUnloadSink::Release() if (ulRef == 0) { delete this; - return 0; } return ulRef; }; @@ -13735,8 +13752,8 @@ void AppDomain::EnumStaticGCRefs(promote_func* fn, ScanContext* sc) } CONTRACT_END; - _ASSERTE(GCHeap::IsGCInProgress() && - GCHeap::IsServerHeap() && + _ASSERTE(GCHeapUtilities::IsGCInProgress() && + GCHeapUtilities::IsServerHeap() && IsGCSpecialThread()); AppDomain::AssemblyIterator asmIterator = IterateAssembliesEx((AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution)); diff --git a/src/vm/appdomain.hpp b/src/vm/appdomain.hpp index 97e8438..670f685 100644 --- a/src/vm/appdomain.hpp +++ b/src/vm/appdomain.hpp @@ -30,6 +30,7 @@ #include "fptrstubs.h" #include "ilstubcache.h" #include "testhookmgr.h" +#include "gcheaputilities.h" #ifdef FEATURE_VERSIONING #include "../binder/inc/applicationcontext.hpp" #endif // FEATURE_VERSIONING @@ -1295,7 +1296,7 @@ public: { WRAPPER_NO_CONTRACT; OBJECTHANDLE h = ::CreateSizedRefHandle( - m_hHandleTableBucket->pTable[GCHeap::IsServerHeap() ? (m_dwSizedRefHandles % m_iNumberOfProcessors) : GetCurrentThreadHomeHeapNumber()], + m_hHandleTableBucket->pTable[GCHeapUtilities::IsServerHeap() ? (m_dwSizedRefHandles % m_iNumberOfProcessors) : GetCurrentThreadHomeHeapNumber()], object); InterlockedIncrement((LONG*)&m_dwSizedRefHandles); return h; @@ -2430,6 +2431,9 @@ public: LPCWSTR wszCodeBase); #ifndef DACCESS_COMPILE // needs AssemblySpec + + void GetCacheAssemblyList(SetSHash& assemblyList); + //**************************************************************************************** // Returns and Inserts assemblies into a lookup cache based on the binding information // in the AssemblySpec. There can be many AssemblySpecs to a single assembly. @@ -4533,8 +4537,8 @@ public: if (m_UnloadIsAsync) { pDomain->AddRef(); - int iGCRefPoint=GCHeap::GetGCHeap()->CollectionCount(GCHeap::GetGCHeap()->GetMaxGeneration()); - if (GCHeap::GetGCHeap()->IsGCInProgress()) + int iGCRefPoint=GCHeapUtilities::GetGCHeap()->CollectionCount(GCHeapUtilities::GetGCHeap()->GetMaxGeneration()); + if (GCHeapUtilities::IsGCInProgress()) iGCRefPoint++; pDomain->SetGCRefPoint(iGCRefPoint); } @@ -4554,8 +4558,8 @@ public: pAllocator->m_pLoaderAllocatorDestroyNext=m_pDelayedUnloadListOfLoaderAllocators; m_pDelayedUnloadListOfLoaderAllocators=pAllocator; - int iGCRefPoint=GCHeap::GetGCHeap()->CollectionCount(GCHeap::GetGCHeap()->GetMaxGeneration()); - if (GCHeap::GetGCHeap()->IsGCInProgress()) + int iGCRefPoint=GCHeapUtilities::GetGCHeap()->CollectionCount(GCHeapUtilities::GetGCHeap()->GetMaxGeneration()); + if (GCHeapUtilities::IsGCInProgress()) iGCRefPoint++; pAllocator->SetGCRefPoint(iGCRefPoint); } diff --git a/src/vm/arm/asmconstants.h b/src/vm/arm/asmconstants.h index 47ebb2d..93af047 100644 --- a/src/vm/arm/asmconstants.h +++ b/src/vm/arm/asmconstants.h @@ -225,10 +225,10 @@ ASMCONSTANTS_C_ASSERT(UnmanagedToManagedFrame__m_pvDatum == offsetof(UnmanagedTo #ifndef CROSSGEN_COMPILE #define Thread__m_alloc_context__alloc_limit 0x44 -ASMCONSTANTS_C_ASSERT(Thread__m_alloc_context__alloc_limit == offsetof(Thread, m_alloc_context) + offsetof(alloc_context, alloc_limit)); +ASMCONSTANTS_C_ASSERT(Thread__m_alloc_context__alloc_limit == offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_limit)); #define Thread__m_alloc_context__alloc_ptr 0x40 -ASMCONSTANTS_C_ASSERT(Thread__m_alloc_context__alloc_ptr == offsetof(Thread, m_alloc_context) + offsetof(alloc_context, alloc_ptr)); +ASMCONSTANTS_C_ASSERT(Thread__m_alloc_context__alloc_ptr == offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_ptr)); #endif // CROSSGEN_COMPILE #define Thread__m_fPreemptiveGCDisabled 0x08 diff --git a/src/vm/arm/cgencpu.h b/src/vm/arm/cgencpu.h index 936fdab..63c578b 100644 --- a/src/vm/arm/cgencpu.h +++ b/src/vm/arm/cgencpu.h @@ -36,10 +36,12 @@ Stub * GenerateInitPInvokeFrameHelper(); EXTERN_C void checkStack(void); +#define THUMB_CODE 1 + #ifdef CROSSGEN_COMPILE #define GetEEFuncEntryPoint(pfn) 0x1001 #else -#define GetEEFuncEntryPoint(pfn) GFN_TADDR(pfn) +#define GetEEFuncEntryPoint(pfn) (GFN_TADDR(pfn) | THUMB_CODE) #endif //********************************************************************** @@ -306,8 +308,6 @@ inline PCODE decodeBackToBackJump(PCODE pBuffer) #include "stublink.h" struct ArrayOpScript; -#define THUMB_CODE 1 - inline BOOL IsThumbCode(PCODE pCode) { return (pCode & THUMB_CODE) != 0; diff --git a/src/vm/arm/stubs.cpp b/src/vm/arm/stubs.cpp index 0b069da..1309695 100644 --- a/src/vm/arm/stubs.cpp +++ b/src/vm/arm/stubs.cpp @@ -2650,7 +2650,7 @@ void InitJITHelpers1() )) { - _ASSERTE(GCHeap::UseAllocationContexts()); + _ASSERTE(GCHeapUtilities::UseAllocationContexts()); // If the TLS for Thread is low enough use the super-fast helpers if (gThreadTLSIndex < TLS_MINIMUM_AVAILABLE) { diff --git a/src/vm/assemblynative.cpp b/src/vm/assemblynative.cpp index 90c58fc..f372bcb 100644 --- a/src/vm/assemblynative.cpp +++ b/src/vm/assemblynative.cpp @@ -807,6 +807,41 @@ Assembly* AssemblyNative::LoadFromPEImage(ICLRPrivBinder* pBinderContext, PEImag RETURN pLoadedAssembly; } +/* static */ +void QCALLTYPE AssemblyNative::GetLoadedAssembliesInternal(QCall::ObjectHandleOnStack assemblies) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; + + MethodTable * pAssemblyClass = MscorlibBinder::GetClass(CLASS__ASSEMBLY); + + PTR_AppDomain pCurDomain = GetAppDomain(); + + SetSHash assemblySet; + pCurDomain->GetCacheAssemblyList(assemblySet); + size_t nArrayElems = assemblySet.GetCount(); + PTRARRAYREF AsmArray = NULL; + + GCX_COOP(); + + GCPROTECT_BEGIN(AsmArray); + AsmArray = (PTRARRAYREF) AllocateObjectArray( (DWORD)nArrayElems, pAssemblyClass); + for(auto it = assemblySet.Begin(); it != assemblySet.End(); it++) + { + PTR_DomainAssembly assem = *it; + OBJECTREF o = (OBJECTREF)assem->GetExposedAssemblyObject(); + _ASSERTE(o != NULL); + _ASSERTE(nArrayElems > 0); + AsmArray->SetAt(--nArrayElems, o); + } + + assemblies.Set(AsmArray); + + GCPROTECT_END(); + + END_QCALL; +} /* static */ void QCALLTYPE AssemblyNative::LoadFromPath(INT_PTR ptrNativeAssemblyLoadContext, LPCWSTR pwzILPath, LPCWSTR pwzNIPath, QCall::ObjectHandleOnStack retLoadedAssembly) diff --git a/src/vm/assemblynative.hpp b/src/vm/assemblynative.hpp index ca03239..99f51e9 100644 --- a/src/vm/assemblynative.hpp +++ b/src/vm/assemblynative.hpp @@ -252,6 +252,7 @@ public: static BOOL QCALLTYPE OverrideDefaultAssemblyLoadContextForCurrentDomain(INT_PTR ptrNativeAssemblyLoadContext); static BOOL QCALLTYPE CanUseAppPathAssemblyLoadContextInCurrentDomain(); static void QCALLTYPE LoadFromPath(INT_PTR ptrNativeAssemblyLoadContext, LPCWSTR pwzILPath, LPCWSTR pwzNIPath, QCall::ObjectHandleOnStack retLoadedAssembly); + static void QCALLTYPE GetLoadedAssembliesInternal(QCall::ObjectHandleOnStack assemblies); static INT_PTR QCALLTYPE InternalLoadUnmanagedDllFromPath(LPCWSTR unmanagedLibraryPath); static void QCALLTYPE LoadFromStream(INT_PTR ptrNativeAssemblyLoadContext, INT_PTR ptrAssemblyArray, INT32 cbAssemblyArrayLength, INT_PTR ptrSymbolArray, INT32 cbSymbolArrayLength, QCall::ObjectHandleOnStack retLoadedAssembly); static Assembly* LoadFromPEImage(ICLRPrivBinder* pBinderContext, PEImage *pILImage, PEImage *pNIImage); diff --git a/src/vm/assemblyspec.hpp b/src/vm/assemblyspec.hpp index a7e9c0f..d94a847 100644 --- a/src/vm/assemblyspec.hpp +++ b/src/vm/assemblyspec.hpp @@ -682,6 +682,20 @@ class AssemblySpecBindingCache WRAPPER_NO_CONTRACT; return pSpec->Hash(); } + +#if defined(FEATURE_CORECLR) && !defined(DACCESS_COMPILE) + void GetAllAssemblies(SetSHash& assemblyList) + { + PtrHashMap::PtrIterator i = m_map.begin(); + while (!i.end()) + { + AssemblyBinding *b = (AssemblyBinding*) i.GetValue(); + if(!b->IsError() && b->GetAssembly() != NULL) + assemblyList.AddOrReplace(b->GetAssembly()); + ++i; + } + } +#endif // defined(FEATURE_CORECLR) && !defined(DACCESS_COMPILE) static BOOL CompareSpecs(UPTR u1, UPTR u2); }; diff --git a/src/vm/callhelpers.cpp b/src/vm/callhelpers.cpp index 9152f71..addd519 100644 --- a/src/vm/callhelpers.cpp +++ b/src/vm/callhelpers.cpp @@ -16,6 +16,8 @@ // To include declaration of "SignatureNative" #include "runtimehandles.h" +#include "invokeutil.h" +#include "argdestination.h" #if defined(FEATURE_MULTICOREJIT) && defined(_DEBUG) @@ -536,7 +538,7 @@ void MethodDescCallSite::CallTargetWorker(const ARG_SLOT *pArguments, ARG_SLOT * } #endif - int ofs; + int ofs; for (; TransitionBlock::InvalidOffset != (ofs = m_argIt.GetNextOffset()); arg++) { #ifdef CALLDESCR_REGTYPEMAP @@ -567,46 +569,56 @@ void MethodDescCallSite::CallTargetWorker(const ARG_SLOT *pArguments, ARG_SLOT * } #endif // CHECK_APP_DOMAIN_LEAKS -#if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) - _ASSERTE(ofs != TransitionBlock::StructInRegsOffset); -#endif - PVOID pDest = pTransitionBlock + ofs; + ArgDestination argDest(pTransitionBlock, ofs, m_argIt.GetArgLocDescForStructInRegs()); UINT32 stackSize = m_argIt.GetArgSize(); - switch (stackSize) + // We need to pass in a pointer, but be careful of the ARG_SLOT calling convention. We might already have a pointer in the ARG_SLOT. + PVOID pSrc = stackSize > sizeof(ARG_SLOT) ? (LPVOID)ArgSlotToPtr(pArguments[arg]) : (LPVOID)ArgSlotEndianessFixup((ARG_SLOT*)&pArguments[arg], stackSize); + +#if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) + if (argDest.IsStructPassedInRegs()) + { + TypeHandle th; + m_argIt.GetArgType(&th); + + argDest.CopyStructToRegisters(pSrc, th.AsMethodTable()->GetNumInstanceFieldBytes(), 0); + } + else +#endif // UNIX_AMD64_ABI && FEATURE_UNIX_AMD64_STRUCT_PASSING { - case 1: - case 2: - case 4: - *((INT32*)pDest) = (INT32)pArguments[arg]; - break; - - case 8: - *((INT64*)pDest) = pArguments[arg]; - break; - - default: - // The ARG_SLOT contains a pointer to the value-type -#ifdef ENREGISTERED_PARAMTYPE_MAXSIZE - if (m_argIt.IsArgPassedByRef()) - { - // We need to pass in a pointer, but be careful of the ARG_SLOT calling convention. - // We might already have a pointer in the ARG_SLOT - *(PVOID*)pDest = stackSize>sizeof(ARG_SLOT) ? - (LPVOID)ArgSlotToPtr(pArguments[arg]) : - (LPVOID)ArgSlotEndianessFixup((ARG_SLOT*)&pArguments[arg], stackSize); - } - else -#endif // ENREGISTERED_PARAMTYPE_MAXSIZE - if (stackSize>sizeof(ARG_SLOT)) - { - CopyMemory(pDest, ArgSlotToPtr(pArguments[arg]), stackSize); - } - else - { - CopyMemory(pDest, (LPVOID) (&pArguments[arg]), stackSize); - } - break; + PVOID pDest = argDest.GetDestinationAddress(); + + switch (stackSize) + { + case 1: + case 2: + case 4: + *((INT32*)pDest) = (INT32)pArguments[arg]; + break; + + case 8: + *((INT64*)pDest) = pArguments[arg]; + break; + + default: + // The ARG_SLOT contains a pointer to the value-type + #ifdef ENREGISTERED_PARAMTYPE_MAXSIZE + if (m_argIt.IsArgPassedByRef()) + { + *(PVOID*)pDest = pSrc; + } + else + #endif // ENREGISTERED_PARAMTYPE_MAXSIZE + if (stackSize > sizeof(ARG_SLOT)) + { + CopyMemory(pDest, ArgSlotToPtr(pArguments[arg]), stackSize); + } + else + { + CopyMemory(pDest, (LPVOID) (&pArguments[arg]), stackSize); + } + break; + } } } diff --git a/src/vm/callingconvention.h b/src/vm/callingconvention.h index 3ef6be9..c9a27c2 100644 --- a/src/vm/callingconvention.h +++ b/src/vm/callingconvention.h @@ -1341,11 +1341,15 @@ void ArgIteratorTemplate::ComputeReturnFlags() break; case ELEMENT_TYPE_R4: +#ifndef ARM_SOFTFP flags |= sizeof(float) << RETURN_FP_SIZE_SHIFT; +#endif break; case ELEMENT_TYPE_R8: +#ifndef ARM_SOFTFP flags |= sizeof(double) << RETURN_FP_SIZE_SHIFT; +#endif break; case ELEMENT_TYPE_VALUETYPE: diff --git a/src/vm/ceeload.cpp b/src/vm/ceeload.cpp index 464c147..c95fbac 100644 --- a/src/vm/ceeload.cpp +++ b/src/vm/ceeload.cpp @@ -1656,6 +1656,7 @@ void Module::Destruct() m_InstMethodHashTableCrst.Destroy(); m_ISymUnmanagedReaderCrst.Destroy(); +#ifdef FEATURE_CER if (m_pCerPrepInfo) { _ASSERTE(m_pCerCrst != NULL); @@ -1672,6 +1673,7 @@ void Module::Destruct() } if (m_pCerCrst) delete m_pCerCrst; +#endif // FEATURE_CER if (m_debuggerSpecificData.m_pDynamicILCrst) { @@ -1702,8 +1704,10 @@ void Module::Destruct() } #ifdef FEATURE_PREJIT +#ifdef FEATURE_CER if (m_pCerNgenRootTable && (m_dwTransientFlags & M_CER_ROOT_TABLE_ON_HEAP)) delete m_pCerNgenRootTable; +#endif if (HasNativeImage()) { @@ -3154,6 +3158,7 @@ BOOL Module::IsPreV4Assembly() return !!(m_dwPersistedFlags & IS_PRE_V4_ASSEMBLY); } +#ifdef FEATURE_CER DWORD Module::GetReliabilityContract() { CONTRACTL @@ -3180,6 +3185,7 @@ DWORD Module::GetReliabilityContract() return m_dwReliabilityContract; } +#endif // FEATURE_CER ArrayDPTR(FixupPointer) ModuleCtorInfo::GetGCStaticMTs(DWORD index) { @@ -3427,8 +3433,8 @@ void Module::EnumRegularStaticGCRefs(AppDomain* pAppDomain, promote_func* fn, Sc } CONTRACT_END; - _ASSERTE(GCHeap::IsGCInProgress() && - GCHeap::IsServerHeap() && + _ASSERTE(GCHeapUtilities::IsGCInProgress() && + GCHeapUtilities::IsServerHeap() && IsGCSpecialThread()); @@ -6268,7 +6274,7 @@ Module *Module::GetModuleIfLoaded(mdFile kFile, BOOL onlyLoadedInAppDomain, BOOL #ifndef DACCESS_COMPILE #if defined(FEATURE_MULTIMODULE_ASSEMBLIES) // check if actually loaded, unless happens during GC (GC works only with loaded assemblies) - if (!GCHeap::IsGCInProgress() && onlyLoadedInAppDomain && pModule && !pModule->IsManifest()) + if (!GCHeapUtilities::IsGCInProgress() && onlyLoadedInAppDomain && pModule && !pModule->IsManifest()) { DomainModule *pDomainModule = pModule->FindDomainModule(GetAppDomain()); if (pDomainModule == NULL || !pDomainModule->IsLoaded()) @@ -9860,10 +9866,12 @@ void Module::PrepareTypesForSave(DataImage *image) PrepareRemotableMethodInfo(pMT); #endif // FEATURE_REMOTING +#ifdef FEATURE_CER // If this module defines any CriticalFinalizerObject derived classes, // then we'll prepare these types for Constrained Execution Regions (CER) now. // (Normally they're prepared at object instantiation time, a little too late for ngen). PrepareCriticalType(pMT); +#endif // FEATURE_CER } } @@ -9947,7 +9955,9 @@ void Module::Save(DataImage *image) // Cache values of all persisted flags computed from custom attributes IsNoStringInterning(); IsRuntimeWrapExceptions(); +#ifdef FEATURE_CER GetReliabilityContract(); +#endif IsPreV4Assembly(); HasDefaultDllImportSearchPathsAttribute(); @@ -10302,10 +10312,12 @@ void Module::Save(DataImage *image) m_nPropertyNameSet * sizeof(BYTE), DataImage::ITEM_PROPERTY_NAME_SET); +#ifdef FEATURE_CER // Save Constrained Execution Region (CER) fixup information (used to eagerly fixup trees of methods to avoid any runtime // induced failures when invoking the tree). if (m_pCerNgenRootTable != NULL) m_pCerNgenRootTable->Save(image, profileData); +#endif // Sort the list of RVA statics in an ascending order wrt the RVA // and save them. @@ -10761,6 +10773,7 @@ void Module::PlaceMethod(DataImage *image, MethodDesc *pMD, DWORD profilingFlags image->PlaceStructureForAddress(pMD, CORCOMPILE_SECTION_WRITE); } +#ifdef FEATURE_CER if (profilingFlags & (1 << ReadCerMethodList)) { // protect against stale IBC data @@ -10771,6 +10784,7 @@ void Module::PlaceMethod(DataImage *image, MethodDesc *pMD, DWORD profilingFlags image->PlaceStructureForAddress(m_pCerNgenRootTable->GetList(pMD), CORCOMPILE_SECTION_HOT); } } +#endif // FEATURE_CER if (profilingFlags & (1 << WriteMethodPrecode)) { @@ -11314,6 +11328,7 @@ void Module::Fixup(DataImage *image) image->ZeroField(m_FileReferencesMap.pTable, 0, m_FileReferencesMap.GetSize() * sizeof(void*)); +#ifdef FEATURE_CER // // Fixup Constrained Execution Regions restoration records. // @@ -11330,6 +11345,7 @@ void Module::Fixup(DataImage *image) // Zero out fields we always compute at runtime lazily. image->ZeroField(this, offsetof(Module, m_pCerPrepInfo), sizeof(m_pCerPrepInfo)); image->ZeroField(this, offsetof(Module, m_pCerCrst), sizeof(m_pCerCrst)); +#endif // FEATURE_CER image->ZeroField(this, offsetof(Module, m_debuggerSpecificData), sizeof(m_debuggerSpecificData)); @@ -15593,7 +15609,7 @@ FieldDesc *Module::LookupFieldDef(mdFieldDef token) #endif // DACCESS_COMPILE -#ifndef DACCESS_COMPILE +#if !defined(DACCESS_COMPILE) && defined(FEATURE_CER) // Access to CerPrepInfo, the structure used to track CERs prepared at runtime (as opposed to ngen time). GetCerPrepInfo will // return the structure associated with the given method desc if it exists or NULL otherwise. CreateCerPrepInfo will get the @@ -15745,7 +15761,7 @@ void Module::RestoreCer(MethodDesc *pMD) #endif // FEATURE_PREJIT -#endif // !DACCESS_COMPILE +#endif // !DACCESS_COMPILE && FEATURE_CER @@ -15911,9 +15927,9 @@ void Module::ExpandAll() pMD->GetMDImport(), &ignored)); #ifdef FEATURE_INTERPRETER - pMD->MakeJitWorker(pHeader, CORJIT_FLG_MAKEFINALCODE, 0); + pMD->MakeJitWorker(pHeader, CORJIT_FLAGS(CORJIT_FLAGS::CORJIT_FLAG_MAKEFINALCODE)); #else - pMD->MakeJitWorker(pHeader, 0, 0); + pMD->MakeJitWorker(pHeader, CORJIT_FLAGS()); #endif } } diff --git a/src/vm/ceeload.h b/src/vm/ceeload.h index ce2e76e..d15bd6b 100644 --- a/src/vm/ceeload.h +++ b/src/vm/ceeload.h @@ -96,14 +96,16 @@ class PersistentInlineTrackingMap; // The native symbol reader dll name #ifdef FEATURE_CORECLR -#if defined(_TARGET_AMD64_) +#if defined(_AMD64_) #define NATIVE_SYMBOL_READER_DLL W("Microsoft.DiaSymReader.Native.amd64.dll") -#elif defined(_TARGET_X86_) +#elif defined(_X86_) #define NATIVE_SYMBOL_READER_DLL W("Microsoft.DiaSymReader.Native.x86.dll") -#elif defined(_TARGET_ARM_) +#elif defined(_ARM_) #define NATIVE_SYMBOL_READER_DLL W("Microsoft.DiaSymReader.Native.arm.dll") -#elif defined(_TARGET_ARM64_) -#define NATIVE_SYMBOL_READER_DLL W("Microsoft.DiaSymReader.Native.arm64.dll") +#elif defined(_ARM64_) +// Use diasymreader until the package has an arm64 version - issue #7360 +//#define NATIVE_SYMBOL_READER_DLL W("Microsoft.DiaSymReader.Native.arm64.dll") +#define NATIVE_SYMBOL_READER_DLL W("diasymreader.dll") #endif #else #define NATIVE_SYMBOL_READER_DLL W("diasymreader.dll") @@ -3392,10 +3394,12 @@ public: //----------------------------------------------------------------------------------------- BOOL IsPreV4Assembly(); +#ifdef FEATURE_CER //----------------------------------------------------------------------------------------- // Get reliability contract info, see ConstrainedExecutionRegion.cpp for details. //----------------------------------------------------------------------------------------- DWORD GetReliabilityContract(); +#endif //----------------------------------------------------------------------------------------- // Parse/Return NeutralResourcesLanguageAttribute if it exists (updates Module member variables at ngen time) @@ -3404,13 +3408,15 @@ public: protected: +#ifdef FEATURE_CER Volatile m_dwReliabilityContract; +#endif // initialize Crst controlling the Dynamic IL hashtables void InitializeDynamicILCrst(); -#ifndef DACCESS_COMPILE public: +#if !defined(DACCESS_COMPILE) && defined(FEATURE_CER) // Support for getting and creating information about Constrained Execution Regions rooted in this module. @@ -3441,7 +3447,7 @@ public: LIMITED_METHOD_CONTRACT; return m_pCerCrst; } -#endif // !DACCESS_COMPILE +#endif // !DACCESS_COMPILE && FEATURE_CER #ifdef FEATURE_CORECLR void VerifyAllMethods(); @@ -3454,11 +3460,13 @@ public: } private: +#ifdef FEATURE_CER EEPtrHashTable *m_pCerPrepInfo; // Root methods prepared for Constrained Execution Regions Crst *m_pCerCrst; // Mutex protecting update access to both of the above hashes #ifdef FEATURE_PREJIT CerNgenRootTable *m_pCerNgenRootTable; // Root methods of CERs found during ngen and requiring runtime restoration #endif +#endif // This struct stores the data used by the managed debugging infrastructure. If it turns out that // the debugger is increasing the size of the Module class by too much, we can consider allocating diff --git a/src/vm/ceemain.cpp b/src/vm/ceemain.cpp index 0778126..5521d8a 100644 --- a/src/vm/ceemain.cpp +++ b/src/vm/ceemain.cpp @@ -150,7 +150,7 @@ #include "frames.h" #include "threads.h" #include "stackwalk.h" -#include "gc.h" +#include "gcheaputilities.h" #include "interoputil.h" #include "security.h" #include "fieldmarshaler.h" @@ -195,6 +195,7 @@ #include "finalizerthread.h" #include "threadsuspend.h" #include "disassembler.h" +#include "gcenv.ee.h" #ifndef FEATURE_PAL #include "dwreport.h" @@ -305,7 +306,6 @@ extern "C" HRESULT __cdecl CorDBGetInterface(DebugInterface** rcInterface); #if !defined(FEATURE_CORECLR) && !defined(CROSSGEN_COMPILE) -void* __stdcall GetCLRFunction(LPCSTR FunctionName); // Pointer to the activated CLR interface provided by the shim. ICLRRuntimeInfo *g_pCLRRuntime = NULL; @@ -640,7 +640,7 @@ void InitializeStartupFlags() g_fEnableARM = TRUE; #endif // !FEATURE_CORECLR - GCHeap::InitializeHeapType((flags & STARTUP_SERVER_GC) != 0); + InitializeHeapType((flags & STARTUP_SERVER_GC) != 0); #ifdef FEATURE_LOADER_OPTIMIZATION g_dwGlobalSharePolicy = (flags&STARTUP_LOADER_OPTIMIZATION_MASK)>>1; @@ -1932,15 +1932,17 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading) #endif #ifdef FEATURE_PREJIT - // If we're doing basic block profiling, we need to write the log files to disk. - - static BOOL fIBCLoggingDone = FALSE; - if (!fIBCLoggingDone) { - if (g_IBCLogger.InstrEnabled()) - Module::WriteAllModuleProfileData(true); + // If we're doing basic block profiling, we need to write the log files to disk. + + static BOOL fIBCLoggingDone = FALSE; + if (!fIBCLoggingDone) + { + if (g_IBCLogger.InstrEnabled()) + Module::WriteAllModuleProfileData(true); - fIBCLoggingDone = TRUE; + fIBCLoggingDone = TRUE; + } } #endif // FEATURE_PREJIT @@ -3719,7 +3721,16 @@ void InitializeGarbageCollector() g_pFreeObjectMethodTable->SetBaseSize(ObjSizeOf (ArrayBase)); g_pFreeObjectMethodTable->SetComponentSize(1); - GCHeap *pGCHeap = GCHeap::CreateGCHeap(); +#ifdef FEATURE_STANDALONE_GC + IGCToCLR* gcToClr = new (nothrow) GCToEEInterface(); + if (!gcToClr) + ThrowOutOfMemory(); +#else + IGCToCLR* gcToClr = nullptr; +#endif + + IGCHeap *pGCHeap = InitializeGarbageCollector(gcToClr); + g_pGCHeap = pGCHeap; if (!pGCHeap) ThrowOutOfMemory(); @@ -3833,7 +3844,7 @@ BOOL STDMETHODCALLTYPE EEDllMain( // TRUE on success, FALSE on error. { // GetThread() may be set to NULL for Win9x during shutdown. Thread *pThread = GetThread(); - if (GCHeap::IsGCInProgress() && + if (GCHeapUtilities::IsGCInProgress() && ( (pThread && (pThread != ThreadSuspend::GetSuspensionThread() )) || !g_fSuspendOnShutdown)) { @@ -4643,7 +4654,6 @@ VOID STDMETHODCALLTYPE LogHelp_LogAssert( LPCSTR szFile, int iLine, LPCSTR expr) } -extern BOOL NoGuiOnAssert(); extern "C" //__declspec(dllexport) BOOL STDMETHODCALLTYPE LogHelp_NoGuiOnAssert() @@ -4656,7 +4666,6 @@ BOOL STDMETHODCALLTYPE LogHelp_NoGuiOnAssert() return fRet; } -extern VOID TerminateOnAssert(); extern "C" //__declspec(dllexport) VOID STDMETHODCALLTYPE LogHelp_TerminateOnAssert() diff --git a/src/vm/cgensys.h b/src/vm/cgensys.h index 205d8a2..4dd1ee4 100644 --- a/src/vm/cgensys.h +++ b/src/vm/cgensys.h @@ -103,21 +103,22 @@ inline void GetSpecificCpuInfo(CORINFO_CPU * cpuInfo) #endif // !_TARGET_X86_ -#if defined(_TARGET_AMD64_) && !defined(CROSSGEN_COMPILE) +#if (defined(_TARGET_X86_) || defined(_TARGET_AMD64_)) && !defined(CROSSGEN_COMPILE) extern "C" DWORD __stdcall getcpuid(DWORD arg, unsigned char result[16]); -#endif // defined(_TARGET_AMD64_) +extern "C" DWORD __stdcall xmmYmmStateSupport(); +#endif inline bool TargetHasAVXSupport() { -#if defined(_TARGET_AMD64_) && !defined(CROSSGEN_COMPILE) +#if (defined(_TARGET_X86_) || defined(_TARGET_AMD64_)) && !defined(CROSSGEN_COMPILE) unsigned char buffer[16]; - // All AMD64 targets support cpuid. + // All x86/AMD64 targets support cpuid. (void) getcpuid(1, buffer); // getcpuid executes cpuid with eax set to its first argument, and ecx cleared. // It returns the resulting eax, ebx, ecx and edx (in that order) in buffer[]. // The AVX feature is ECX bit 28. return ((buffer[11] & 0x10) != 0); -#endif // defined(_TARGET_AMD64_) && !defined(CROSSGEN_COMPILE) +#endif // (defined(_TARGET_X86_) || defined(_TARGET_AMD64_)) && !defined(CROSSGEN_COMPILE) return false; } diff --git a/src/vm/class.cpp b/src/vm/class.cpp index 961df2a..cff71f3 100644 --- a/src/vm/class.cpp +++ b/src/vm/class.cpp @@ -19,6 +19,7 @@ #include "constrainedexecutionregion.h" #include "customattribute.h" #include "encee.h" +#include "typestring.h" #ifdef FEATURE_COMINTEROP #include "comcallablewrapper.h" @@ -2490,12 +2491,14 @@ MethodTable::GetSubstitutionForParent( #endif //!DACCESS_COMPILE +#ifdef FEATURE_CER //******************************************************************************* DWORD EEClass::GetReliabilityContract() { LIMITED_METHOD_CONTRACT; return HasOptionalFields() ? GetOptionalFields()->m_dwReliabilityContract : RC_NULL; } +#endif // FEATURE_CER //******************************************************************************* #ifdef FEATURE_PREJIT @@ -3065,6 +3068,7 @@ void EEClass::Fixup(DataImage *image, MethodTable *pMT) image->ZeroPointerField(this, offsetof(DelegateEEClass, m_pUMThunkMarshInfo)); image->ZeroPointerField(this, offsetof(DelegateEEClass, m_pStaticCallStub)); image->ZeroPointerField(this, offsetof(DelegateEEClass, m_pMultiCastInvokeStub)); + image->ZeroPointerField(this, offsetof(DelegateEEClass, m_pSecureDelegateInvokeStub)); image->ZeroPointerField(this, offsetof(DelegateEEClass, m_pMarshalStub)); #ifdef FEATURE_COMINTEROP diff --git a/src/vm/class.h b/src/vm/class.h index f19b981..7517863 100644 --- a/src/vm/class.h +++ b/src/vm/class.h @@ -703,7 +703,9 @@ class EEClassOptionalFields #define MODULE_NON_DYNAMIC_STATICS ((DWORD)-1) DWORD m_cbModuleDynamicID; +#ifdef FEATURE_CER DWORD m_dwReliabilityContract; +#endif SecurityProperties m_SecProps; @@ -1768,12 +1770,14 @@ public: // Cached class level reliability contract info, see ConstrainedExecutionRegion.cpp for details. DWORD GetReliabilityContract(); +#ifdef FEATURE_CER inline void SetReliabilityContract(DWORD dwValue) { LIMITED_METHOD_CONTRACT; _ASSERTE(HasOptionalFields()); GetOptionalFields()->m_dwReliabilityContract = dwValue; } +#endif #if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) // Get number of eightbytes used by a struct passed in registers. @@ -2412,6 +2416,7 @@ public: PTR_Stub m_pInstRetBuffCallStub; PTR_MethodDesc m_pInvokeMethod; PTR_Stub m_pMultiCastInvokeStub; + PTR_Stub m_pSecureDelegateInvokeStub; UMThunkMarshInfo* m_pUMThunkMarshInfo; PTR_MethodDesc m_pBeginInvokeMethod; PTR_MethodDesc m_pEndInvokeMethod; diff --git a/src/vm/class.inl b/src/vm/class.inl index 9362a83..7d5c74d 100644 --- a/src/vm/class.inl +++ b/src/vm/class.inl @@ -50,7 +50,9 @@ inline void EEClassOptionalFields::Init() m_WinRTRedirectedTypeIndex = WinMDAdapter::RedirectedTypeIndex_Invalid; #endif // FEATURE_COMINTEROP m_cbModuleDynamicID = MODULE_NON_DYNAMIC_STATICS; +#ifdef FEATURE_CER m_dwReliabilityContract = RC_NULL; +#endif m_SecProps = 0; #if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) m_numberEightBytes = 0; diff --git a/src/vm/classcompat.cpp b/src/vm/classcompat.cpp index ac81994..50c5650 100644 --- a/src/vm/classcompat.cpp +++ b/src/vm/classcompat.cpp @@ -31,7 +31,7 @@ #include "log.h" #include "fieldmarshaler.h" #include "cgensys.h" -#include "gc.h" +#include "gcheaputilities.h" #include "security.h" #include "dbginterface.h" #include "comdelegate.h" diff --git a/src/vm/classnames.h b/src/vm/classnames.h index 949c6c4..47f1fec 100644 --- a/src/vm/classnames.h +++ b/src/vm/classnames.h @@ -16,6 +16,9 @@ #define g_ArrayClassName "System.Array" #define g_NullableName "Nullable`1" +#ifdef FEATURE_SPAN_OF_T +#define g_ByReferenceName "ByReference`1" +#endif #define g_CollectionsEnumerableItfName "System.Collections.IEnumerable" #define g_CollectionsEnumeratorClassName "System.Collections.IEnumerator" diff --git a/src/vm/clrprivbinderwinrt.cpp b/src/vm/clrprivbinderwinrt.cpp index b82d46c..b4fb45c 100644 --- a/src/vm/clrprivbinderwinrt.cpp +++ b/src/vm/clrprivbinderwinrt.cpp @@ -287,7 +287,8 @@ HRESULT CLRPrivBinderWinRT::BindWinRTAssemblyByName( { STANDARD_VM_CONTRACT; HRESULT hr = S_OK; - ReleaseHolder pAssembly; + ReleaseHolder pAssembly; + LPWSTR wszFullTypeName = nullptr; #ifndef FEATURE_CORECLR NewArrayHolder wszAssemblySimpleName; #endif @@ -319,11 +320,13 @@ HRESULT CLRPrivBinderWinRT::BindWinRTAssemblyByName( IfFailGo(fusion::util::GetProperty(pAssemblyName, ASM_NAME_NAME, &wszAssemblySimpleName)); #else WCHAR wszAssemblySimpleName[_MAX_PATH]; - DWORD cchAssemblySimpleName = _MAX_PATH; - IfFailGo(pAssemblyName->GetName(&cchAssemblySimpleName, wszAssemblySimpleName)); + { + DWORD cchAssemblySimpleName = _MAX_PATH; + IfFailGo(pAssemblyName->GetName(&cchAssemblySimpleName, wszAssemblySimpleName)); + } #endif - LPWSTR wszFullTypeName = wcschr(wszAssemblySimpleName, W('!')); + wszFullTypeName = wcschr(wszAssemblySimpleName, W('!')); if (wszFullTypeName != nullptr) { diff --git a/src/vm/clsload.hpp b/src/vm/clsload.hpp index e2705ae..a3a0de3 100644 --- a/src/vm/clsload.hpp +++ b/src/vm/clsload.hpp @@ -697,7 +697,7 @@ public: // fLoadTypes=DontLoadTypes: if type isn't already in the loader's table, return NULL // fLoadTypes=LoadTypes: if type isn't already in the loader's table, then create it // Each comes in two variants, LoadXThrowing and LoadXNoThrow, the latter being just - // a exception-handling wrapper around the former. + // an exception-handling wrapper around the former. // // Each also allows types to be loaded only up to a particular level (see classloadlevel.h). // The class loader itself makes use of these levels to "break" recursion across diff --git a/src/vm/codeman.cpp b/src/vm/codeman.cpp index 89084db..98f0e53 100644 --- a/src/vm/codeman.cpp +++ b/src/vm/codeman.cpp @@ -31,6 +31,10 @@ #include "debuginfostore.h" #include "strsafe.h" +#ifdef FEATURE_CORECLR +#include "configuration.h" +#endif + #ifdef _WIN64 #define CHECK_DUPLICATED_STRUCT_LAYOUTS #include "../debug/daccess/fntableaccess.h" @@ -1183,6 +1187,7 @@ EEJitManager::EEJitManager() // CRST_TAKEN_DURING_SHUTDOWN - We take this lock during shutdown if ETW is on (to do rundown) m_CodeHeapCritSec( CrstSingleUseLock, CrstFlags(CRST_UNSAFE_ANYMODE|CRST_DEBUGGER_THREAD|CRST_TAKEN_DURING_SHUTDOWN)), + m_CPUCompileFlags(), m_EHClauseCritSec( CrstSingleUseLock ) { CONTRACTL { @@ -1196,41 +1201,34 @@ EEJitManager::EEJitManager() #ifdef _TARGET_AMD64_ m_pEmergencyJumpStubReserveList = NULL; #endif -#ifdef _TARGET_AMD64_ +#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) m_JITCompilerOther = NULL; #endif + m_fLegacyJitUsed = FALSE; + #ifdef ALLOW_SXS_JIT m_alternateJit = NULL; m_AltJITCompiler = NULL; m_AltJITRequired = false; #endif - m_dwCPUCompileFlags = 0; - m_cleanupList = NULL; } -#if defined(_TARGET_AMD64_) -extern "C" DWORD __stdcall getcpuid(DWORD arg, unsigned char result[16]); -extern "C" DWORD __stdcall xmmYmmStateSupport(); +#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) bool DoesOSSupportAVX() { + LIMITED_METHOD_CONTRACT; + #ifndef FEATURE_PAL // On Windows we have an api(GetEnabledXStateFeatures) to check if AVX is supported typedef DWORD64 (WINAPI *PGETENABLEDXSTATEFEATURES)(); PGETENABLEDXSTATEFEATURES pfnGetEnabledXStateFeatures = NULL; - // Probe ApiSet first - HMODULE hMod = WszLoadLibraryEx(W("api-ms-win-core-xstate-l2-1-0.dll"), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); - - if (hMod == NULL) - { - // On older OS's where apiset is not present probe kernel32 - hMod = WszLoadLibraryEx(WINDOWS_KERNEL32_DLLNAME_W, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); - if(hMod = NULL) - return FALSE; - } + HMODULE hMod = WszLoadLibraryEx(WINDOWS_KERNEL32_DLLNAME_W, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + if(hMod = NULL) + return FALSE; pfnGetEnabledXStateFeatures = (PGETENABLEDXSTATEFEATURES)GetProcAddress(hMod, "GetEnabledXStateFeatures"); @@ -1249,7 +1247,7 @@ bool DoesOSSupportAVX() return TRUE; } -#endif // defined(_TARGET_AMD64_) +#endif // defined(_TARGET_X86_) || defined(_TARGET_AMD64_) void EEJitManager::SetCpuInfo() { @@ -1259,7 +1257,7 @@ void EEJitManager::SetCpuInfo() // NOTE: This function needs to be kept in sync with Zapper::CompileAssembly() // - DWORD dwCPUCompileFlags = 0; + CORJIT_FLAGS CPUCompileFlags; #if defined(_TARGET_X86_) // NOTE: if you're adding any flags here, you probably should also be doing it @@ -1270,7 +1268,7 @@ void EEJitManager::SetCpuInfo() switch (CPU_X86_FAMILY(cpuInfo.dwCPUType)) { case CPU_X86_PENTIUM_4: - dwCPUCompileFlags |= CORJIT_FLG_TARGET_P4; + CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_TARGET_P4); break; default: break; @@ -1278,15 +1276,17 @@ void EEJitManager::SetCpuInfo() if (CPU_X86_USE_CMOV(cpuInfo.dwFeatures)) { - dwCPUCompileFlags |= CORJIT_FLG_USE_CMOV | - CORJIT_FLG_USE_FCOMI; + CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_CMOV); + CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_FCOMI); } if (CPU_X86_USE_SSE2(cpuInfo.dwFeatures)) { - dwCPUCompileFlags |= CORJIT_FLG_USE_SSE2; + CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_SSE2); } -#elif defined(_TARGET_AMD64_) +#endif // _TARGET_X86_ + +#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) unsigned char buffer[16]; DWORD maxCpuId = getcpuid(0, buffer); if (maxCpuId >= 0) @@ -1295,17 +1295,17 @@ void EEJitManager::SetCpuInfo() // It returns the resulting eax in buffer[0-3], ebx in buffer[4-7], ecx in buffer[8-11], // and edx in buffer[12-15]. // We will set the following flags: - // CORJIT_FLG_USE_SSE3_4 if the following feature bits are set (input EAX of 1) + // CORJIT_FLAG_USE_SSE3_4 if the following feature bits are set (input EAX of 1) // SSE3 - ECX bit 0 (buffer[8] & 0x01) // SSSE3 - ECX bit 9 (buffer[9] & 0x02) // SSE4.1 - ECX bit 19 (buffer[10] & 0x08) // SSE4.2 - ECX bit 20 (buffer[10] & 0x10) - // CORJIT_FLG_USE_AVX if the following feature bits are set (input EAX of 1), and xmmYmmStateSupport returns 1: + // CORJIT_FLAG_USE_AVX if the following feature bits are set (input EAX of 1), and xmmYmmStateSupport returns 1: // OSXSAVE - ECX bit 27 (buffer[11] & 0x08) // AVX - ECX bit 28 (buffer[11] & 0x10) - // CORJIT_FLG_USE_AVX2 if the following feature bit is set (input EAX of 0x07 and input ECX of 0): + // CORJIT_FLAG_USE_AVX2 if the following feature bit is set (input EAX of 0x07 and input ECX of 0): // AVX2 - EBX bit 5 (buffer[4] & 0x20) - // CORJIT_FLG_USE_AVX_512 is not currently set, but defined so that it can be used in future without + // CORJIT_FLAG_USE_AVX_512 is not currently set, but defined so that it can be used in future without // synchronously updating VM and JIT. (void) getcpuid(1, buffer); // If SSE2 is not enabled, there is no point in checking the rest. @@ -1318,7 +1318,7 @@ void EEJitManager::SetCpuInfo() ((buffer[10] & 0x08) != 0) && // SSE4.1 ((buffer[10] & 0x10) != 0)) // SSE4.2 { - dwCPUCompileFlags |= CORJIT_FLG_USE_SSE3_4; + CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_SSE3_4); } if ((buffer[11] & 0x18) == 0x18) { @@ -1326,13 +1326,13 @@ void EEJitManager::SetCpuInfo() { if (xmmYmmStateSupport() == 1) { - dwCPUCompileFlags |= CORJIT_FLG_USE_AVX; + CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_AVX); if (maxCpuId >= 0x07) { (void) getcpuid(0x07, buffer); if ((buffer[4] & 0x20) != 0) { - dwCPUCompileFlags |= CORJIT_FLG_USE_AVX2; + CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_AVX2); } } } @@ -1341,13 +1341,13 @@ void EEJitManager::SetCpuInfo() static ConfigDWORD fFeatureSIMD; if (fFeatureSIMD.val(CLRConfig::EXTERNAL_FeatureSIMD) != 0) { - dwCPUCompileFlags |= CORJIT_FLG_FEATURE_SIMD; + CPUCompileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_FEATURE_SIMD); } } } -#endif // defined(_TARGET_AMD64_) +#endif // defined(_TARGET_X86_) || defined(_TARGET_AMD64_) - m_dwCPUCompileFlags = dwCPUCompileFlags; + m_CPUCompileFlags = CPUCompileFlags; } // Define some data that we can use to get a better idea of what happened when we get a Watson dump that indicates the JIT failed to load. @@ -1356,7 +1356,7 @@ void EEJitManager::SetCpuInfo() enum JIT_LOAD_JIT_ID { JIT_LOAD_MAIN = 500, // The "main" JIT. Normally, this is named "clrjit.dll". Start at a number that is somewhat uncommon (i.e., not zero or 1) to help distinguish from garbage, in process dumps. - JIT_LOAD_LEGACY, // The "legacy" JIT. Normally, this is named "compatjit.dll" (aka, JIT64). This only applies to AMD64. + JIT_LOAD_LEGACY, // The "legacy" JIT. Normally, this is named "compatjit.dll". This applies to AMD64 on Windows desktop, or x86 on Windows .NET Core. JIT_LOAD_ALTJIT // An "altjit". By default, named "protojit.dll". Used both internally, as well as externally for JIT CTP builds. }; @@ -1432,33 +1432,43 @@ static void LoadAndInitializeJIT(LPCWSTR pwzJitName, OUT HINSTANCE* phJit, OUT I #ifdef FEATURE_CORECLR PathString CoreClrFolderHolder; extern HINSTANCE g_hThisInst; + bool havePath = false; #if !defined(FEATURE_MERGE_JIT_AND_ENGINE) if (g_CLRJITPath != nullptr) { - // If we have been asked to load a specific JIT binary, load it. + // If we have been asked to load a specific JIT binary, load from that path. + // The main JIT load will use exactly that name because pwzJitName will have + // been computed as the last component of g_CLRJITPath by ExecutionManager::GetJitName(). + // Non-primary JIT names (such as compatjit or altjit) will be loaded from the + // same directory. + // (Ideally, g_CLRJITPath would just be the JIT path without the filename component, + // but that's not how the JIT_PATH variable was originally defined.) CoreClrFolderHolder.Set(g_CLRJITPath); + havePath = true; } else #endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) if (WszGetModuleFileName(g_hThisInst, CoreClrFolderHolder)) { // Load JIT from next to CoreCLR binary + havePath = true; + } + + if (havePath && !CoreClrFolderHolder.IsEmpty()) + { SString::Iterator iter = CoreClrFolderHolder.End(); BOOL findSep = CoreClrFolderHolder.FindBack(iter, DIRECTORY_SEPARATOR_CHAR_W); if (findSep) { SString sJitName(pwzJitName); CoreClrFolderHolder.Replace(iter + 1, CoreClrFolderHolder.End() - (iter + 1), sJitName); - } - } - if (!CoreClrFolderHolder.IsEmpty()) - { - *phJit = CLRLoadLibrary(CoreClrFolderHolder.GetUnicode()); - if (*phJit != NULL) - { - hr = S_OK; + *phJit = CLRLoadLibrary(CoreClrFolderHolder.GetUnicode()); + if (*phJit != NULL) + { + hr = S_OK; + } } } @@ -1614,7 +1624,7 @@ BOOL EEJitManager::LoadJIT() #else // !FEATURE_MERGE_JIT_AND_ENGINE m_JITCompiler = NULL; -#ifdef _TARGET_AMD64_ +#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) m_JITCompilerOther = NULL; #endif @@ -1623,8 +1633,8 @@ BOOL EEJitManager::LoadJIT() // Set as a courtesy to code:CorCompileGetRuntimeDll s_ngenCompilerDll = m_JITCompiler; - -#if defined(_TARGET_AMD64_) && !defined(CROSSGEN_COMPILE) && !defined(FEATURE_CORECLR) + +#if (defined(_TARGET_AMD64_) && !defined(CROSSGEN_COMPILE) && !defined(FEATURE_CORECLR)) || (defined(_TARGET_X86_) && defined(FEATURE_CORECLR)) // If COMPlus_UseLegacyJit=1, then we fall back to compatjit.dll. // // This fallback mechanism was introduced for Visual Studio "14" Preview, when JIT64 (the legacy JIT) was replaced with @@ -1645,8 +1655,16 @@ BOOL EEJitManager::LoadJIT() // is set, we also must use JIT64 for all NGEN compilations as well. // // See the document "RyuJIT Compatibility Fallback Specification.docx" for details. + // + // For .NET Core 1.2, RyuJIT for x86 is the primary jit (clrjit.dll) and JIT32 for x86 is the fallback, legacy JIT (compatjit.dll). + // Thus, the COMPlus_useLegacyJit=1 mechanism has been enabled for x86 CoreCLR. This scenario does not have the UseRyuJIT + // registry key, nor the AppX binder mode. +#if defined(FEATURE_CORECLR) + bool fUseRyuJit = true; +#else bool fUseRyuJit = UseRyuJit(); +#endif if ((!IsCompilationProcess() || !fUseRyuJit) && // Use RyuJIT for all NGEN, unless we're falling back to JIT64 for everything. (newJitCompiler != nullptr)) // the main JIT must successfully load before we try loading the fallback JIT @@ -1660,7 +1678,11 @@ BOOL EEJitManager::LoadJIT() if (!fUsingCompatJit) { +#if defined(FEATURE_CORECLR) + DWORD useLegacyJit = Configuration::GetKnobBooleanValue(W("System.JIT.UseWindowsX86CoreLegacyJit"), CLRConfig::EXTERNAL_UseWindowsX86CoreLegacyJit); +#else DWORD useLegacyJit = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_UseLegacyJit); // uncached access, since this code is run no more than one time +#endif if (useLegacyJit == 1) { fUsingCompatJit = TRUE; @@ -1689,7 +1711,7 @@ BOOL EEJitManager::LoadJIT() { // Now, load the compat jit and initialize it. - LPWSTR pwzJitName = MAKEDLLNAME_W(L"compatjit"); + LPCWSTR pwzJitName = MAKEDLLNAME_W(W("compatjit")); // Note: if the compatjit fails to load, we ignore it, and continue to use the main JIT for // everything. You can imagine a policy where if the user requests the compatjit, and we fail @@ -1702,10 +1724,13 @@ BOOL EEJitManager::LoadJIT() // Tell the main JIT to fall back to the "fallback" JIT compiler, in case some // obfuscator tries to directly call the main JIT's getJit() function. newJitCompiler->setRealJit(fallbackICorJitCompiler); + + // Now, the compat JIT will be used. + m_fLegacyJitUsed = TRUE; } } } -#endif // defined(_TARGET_AMD64_) && !defined(CROSSGEN_COMPILE) && !defined(FEATURE_CORECLR) +#endif // (defined(_TARGET_AMD64_) && !defined(CROSSGEN_COMPILE) && !defined(FEATURE_CORECLR)) || (defined(_TARGET_X86_) && defined(FEATURE_CORECLR)) #endif // !FEATURE_MERGE_JIT_AND_ENGINE @@ -3397,7 +3422,7 @@ void ExecutionManager::CleanupCodeHeaps() } CONTRACTL_END; - _ASSERTE (g_fProcessDetach || (GCHeap::IsGCInProgress() && ::IsGCThread())); + _ASSERTE (g_fProcessDetach || (GCHeapUtilities::IsGCInProgress() && ::IsGCThread())); GetEEJitManager()->CleanupCodeHeaps(); } @@ -3411,7 +3436,17 @@ void EEJitManager::CleanupCodeHeaps() } CONTRACTL_END; - _ASSERTE (g_fProcessDetach || (GCHeap::IsGCInProgress() && ::IsGCThread())); + _ASSERTE (g_fProcessDetach || (GCHeapUtilities::IsGCInProgress() && ::IsGCThread())); + + // Quick out, don't even take the lock if we have not cleanup to do. + // This is important because ETW takes the CodeHeapLock when it is doing + // rundown, and if there are many JIT compiled methods, this can take a while. + // Because cleanup is called synchronously before a GC, this means GCs get + // blocked while ETW is doing rundown. By not taking the lock we avoid + // this stall most of the time since cleanup is rare, and ETW rundown is rare + // the likelihood of both is very very rare. + if (m_cleanupList == NULL) + return; CrstHolder ch(&m_CodeHeapCritSec); @@ -4359,7 +4394,22 @@ LPCWSTR ExecutionManager::GetJitName() LPCWSTR pwzJitName = NULL; -#if !defined(FEATURE_CORECLR) +#if defined(FEATURE_CORECLR) +#if !defined(CROSSGEN_COMPILE) + if (g_CLRJITPath != nullptr) + { + const wchar_t* p = wcsrchr(g_CLRJITPath, DIRECTORY_SEPARATOR_CHAR_W); + if (p != nullptr) + { + pwzJitName = p + 1; // Return just the filename, not the directory name + } + else + { + pwzJitName = g_CLRJITPath; + } + } +#endif // !defined(CROSSGEN_COMPILE) +#else // !FEATURE_CORECLR // Try to obtain a name for the jit library from the env. variable IfFailThrow(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_JitName, const_cast(&pwzJitName))); #endif // !FEATURE_CORECLR @@ -4451,7 +4501,7 @@ RangeSection* ExecutionManager::GetRangeSection(TADDR addr) // Unless we are on an MP system with many cpus // where this sort of caching actually diminishes scaling during server GC // due to many processors writing to a common location - if (g_SystemInfo.dwNumberOfProcessors < 4 || !GCHeap::IsServerHeap() || !GCHeap::IsGCInProgress()) + if (g_SystemInfo.dwNumberOfProcessors < 4 || !GCHeapUtilities::IsServerHeap() || !GCHeapUtilities::IsGCInProgress()) pHead->pLastUsed = pLast; #endif @@ -6104,12 +6154,12 @@ __forceinline bool Nirvana_PrintMethodDescWorker(__in_ecount(iBuffer) char * szB if (*pNamespace != 0) { - if(FAILED(StringCchPrintfA(szBuffer, iBuffer, "%s.%s.%s", pNamespace, pClassName, pSigString))) + if (_snprintf_s(szBuffer, iBuffer, _TRUNCATE, "%s.%s.%s", pNamespace, pClassName, pSigString) == -1) return false; } else { - if(FAILED(StringCchPrintfA(szBuffer, iBuffer, "%s.%s", pClassName, pSigString))) + if (_snprintf_s(szBuffer, iBuffer, _TRUNCATE, "%s.%s", pClassName, pSigString) == -1) return false; } diff --git a/src/vm/codeman.h b/src/vm/codeman.h index f143dd6..0fe261a 100644 --- a/src/vm/codeman.h +++ b/src/vm/codeman.h @@ -140,6 +140,10 @@ public: PTR_EE_ILEXCEPTION phdrJitEHInfo; PTR_BYTE phdrJitGCInfo; +#if defined(FEATURE_GDBJIT) + VOID* pCalledMethods; +#endif + PTR_MethodDesc phdrMDesc; #ifdef WIN64EXCEPTIONS @@ -172,6 +176,13 @@ public: SUPPORTS_DAC; return phdrMDesc; } +#if defined(FEATURE_GDBJIT) + PTR_BYTE GetCalledMethods() + { + SUPPORTS_DAC; + return pCalledMethods; + } +#endif TADDR GetCodeStartAddress() { SUPPORTS_DAC; @@ -205,6 +216,12 @@ public: { phdrMDesc = pMD; } +#if defined(FEATURE_GDBJIT) + void SetCalledMethods(VOID* pCM) + { + pCalledMethods = pCM; + } +#endif void SetStubCodeBlockKind(StubCodeBlockKind kind) { phdrMDesc = (PTR_MethodDesc)kind; @@ -248,6 +265,13 @@ public: SUPPORTS_DAC; return pRealCodeHeader->phdrMDesc; } +#if defined(FEATURE_GDBJIT) + VOID* GetCalledMethods() + { + SUPPORTS_DAC; + return pRealCodeHeader->pCalledMethods; + } +#endif TADDR GetCodeStartAddress() { SUPPORTS_DAC; @@ -286,6 +310,12 @@ public: { pRealCodeHeader->phdrMDesc = pMD; } +#if defined(FEATURE_GDBJIT) + void SetCalledMethods(VOID* pCM) + { + pRealCodeHeader->pCalledMethods = pCM; + } +#endif void SetStubCodeBlockKind(StubCodeBlockKind kind) { pRealCodeHeader = (PTR_RealCodeHeader)kind; @@ -1116,17 +1146,17 @@ public: #endif // !DACCESS_COMPILE private: - DWORD m_dwCPUCompileFlags; + CORJIT_FLAGS m_CPUCompileFlags; #if !defined CROSSGEN_COMPILE && !defined DACCESS_COMPILE void SetCpuInfo(); #endif public: - inline DWORD GetCPUCompileFlags() + inline CORJIT_FLAGS GetCPUCompileFlags() { LIMITED_METHOD_CONTRACT; - return m_dwCPUCompileFlags; + return m_CPUCompileFlags; } private : @@ -1163,10 +1193,16 @@ public: public: ICorJitCompiler * m_jit; HINSTANCE m_JITCompiler; -#ifdef _TARGET_AMD64_ +#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) HINSTANCE m_JITCompilerOther; // Stores the handle of the legacy JIT, if one is loaded. #endif + // TRUE if the legacy/compat JIT was loaded successfully and will be used. + // This is available in all builds so if COMPlus_RequireLegacyJit=1 is set in a test, + // the test will fail in any build where the legacy JIT is not loaded, even if legacy + // fallback is not available in that build. This prevents unexpected silent successes. + BOOL m_fLegacyJitUsed; + #ifdef ALLOW_SXS_JIT //put these at the end so that we don't mess up the offsets in the DAC. ICorJitCompiler * m_alternateJit; @@ -1801,7 +1837,7 @@ public: ULONG GetFixedStackSize() { WRAPPER_NO_CONTRACT; - return GetCodeManager()->GetFrameSize(GetGCInfo()); + return GetCodeManager()->GetFrameSize(GetGCInfoToken()); } #endif // WIN64EXCEPTIONS diff --git a/src/vm/comdelegate.cpp b/src/vm/comdelegate.cpp index 9ba1bdb..4c85a02 100644 --- a/src/vm/comdelegate.cpp +++ b/src/vm/comdelegate.cpp @@ -1249,7 +1249,7 @@ PCODE COMDelegate::ConvertToCallback(MethodDesc* pMD) // Get UMEntryThunk from appdomain thunkcache cache. UMEntryThunk *pUMEntryThunk = GetAppDomain()->GetUMEntryThunkCache()->GetUMEntryThunk(pMD); -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) // System.Runtime.InteropServices.NativeCallableAttribute BYTE* pData = NULL; @@ -1281,7 +1281,7 @@ PCODE COMDelegate::ConvertToCallback(MethodDesc* pMD) pUMThunkMarshalInfo->SetCallingConvention(callConv); } } -#endif //_TARGET_X86_ +#endif //_TARGET_X86_ && !FEATURE_STUBS_AS_IL pCode = (PCODE)pUMEntryThunk->GetCode(); _ASSERTE(pCode != NULL); @@ -2395,7 +2395,7 @@ PCODE COMDelegate::TheDelegateInvokeStub() } CONTRACT_END; -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) static PCODE s_pInvokeStub; if (s_pInvokeStub == NULL) @@ -2415,7 +2415,7 @@ PCODE COMDelegate::TheDelegateInvokeStub() RETURN s_pInvokeStub; #else RETURN GetEEFuncEntryPoint(SinglecastDelegateInvokeStub); -#endif // _TARGET_X86_ +#endif // _TARGET_X86_ && !FEATURE_STUBS_AS_IL } // Get the cpu stub for a delegate invoke. @@ -2931,47 +2931,61 @@ PCODE COMDelegate::GetSecureInvoke(MethodDesc* pMD) #ifdef FEATURE_CAS_POLICY #error GetSecureInvoke not implemented #else - GCX_PREEMP(); + MethodTable * pDelegateMT = pMD->GetMethodTable(); + DelegateEEClass* delegateEEClass = (DelegateEEClass*) pDelegateMT->GetClass(); + Stub *pStub = delegateEEClass->m_pSecureDelegateInvokeStub; + + if (pStub == NULL) + { + + GCX_PREEMP(); + + MetaSig sig(pMD); + + BOOL fReturnVal = !sig.IsReturnTypeVoid(); - MetaSig sig(pMD); + SigTypeContext emptyContext; + ILStubLinker sl(pMD->GetModule(), pMD->GetSignature(), &emptyContext, pMD, TRUE, TRUE, FALSE); + + ILCodeStream *pCode = sl.NewCodeStream(ILStubLinker::kDispatch); - BOOL fReturnVal = !sig.IsReturnTypeVoid(); + // Load the "real" delegate + pCode->EmitLoadThis(); + pCode->EmitLDFLD(pCode->GetToken(MscorlibBinder::GetField(FIELD__MULTICAST_DELEGATE__INVOCATION_LIST))); - SigTypeContext emptyContext; - ILStubLinker sl(pMD->GetModule(), pMD->GetSignature(), &emptyContext, pMD, TRUE, TRUE, FALSE); + // Load the arguments + UINT paramCount = 0; + while(paramCount < sig.NumFixedArgs()) + pCode->EmitLDARG(paramCount++); - ILCodeStream *pCode = sl.NewCodeStream(ILStubLinker::kDispatch); + // Call the delegate + pCode->EmitCALL(pCode->GetToken(pMD), sig.NumFixedArgs(), fReturnVal); - // Load the "real" delegate - pCode->EmitLoadThis(); - pCode->EmitLDFLD(pCode->GetToken(MscorlibBinder::GetField(FIELD__MULTICAST_DELEGATE__INVOCATION_LIST))); + // Return + pCode->EmitRET(); - // Load the arguments - UINT paramCount = 0; - while(paramCount < sig.NumFixedArgs()) - pCode->EmitLDARG(paramCount++); + PCCOR_SIGNATURE pSig; + DWORD cbSig; - // Call the delegate - pCode->EmitCALL(pCode->GetToken(pMD), sig.NumFixedArgs(), fReturnVal); + pMD->GetSig(&pSig,&cbSig); - // Return - pCode->EmitRET(); + MethodDesc* pStubMD = + ILStubCache::CreateAndLinkNewILStubMethodDesc(pMD->GetLoaderAllocator(), + pMD->GetMethodTable(), + ILSTUB_SECUREDELEGATE_INVOKE, + pMD->GetModule(), + pSig, cbSig, + NULL, + &sl); - PCCOR_SIGNATURE pSig; - DWORD cbSig; + pStub = Stub::NewStub(JitILStub(pStubMD)); - pMD->GetSig(&pSig,&cbSig); + g_IBCLogger.LogEEClassCOWTableAccess(pDelegateMT); - MethodDesc* pStubMD = - ILStubCache::CreateAndLinkNewILStubMethodDesc(pMD->GetLoaderAllocator(), - pMD->GetMethodTable(), - ILSTUB_SECUREDELEGATE_INVOKE, - pMD->GetModule(), - pSig, cbSig, - NULL, - &sl); + InterlockedCompareExchangeT(EnsureWritablePages(&delegateEEClass->m_pSecureDelegateInvokeStub), pStub, NULL); - return Stub::NewStub(JitILStub(pStubMD))->GetEntryPoint(); + } + return pStub->GetEntryPoint(); #endif } #else // FEATURE_STUBS_AS_IL @@ -2986,32 +3000,44 @@ PCODE COMDelegate::GetSecureInvoke(MethodDesc* pMD) } CONTRACT_END; - GCX_PREEMP(); - - MetaSig sig(pMD); + MethodTable * pDelegateMT = pMD->GetMethodTable(); + DelegateEEClass* delegateEEClass = (DelegateEEClass*) pDelegateMT->GetClass(); - UINT_PTR hash = CPUSTUBLINKER::HashMulticastInvoke(&sig); + Stub *pStub = delegateEEClass->m_pSecureDelegateInvokeStub; - Stub *pStub = m_pSecureDelegateStubCache->GetStub(hash); - if (!pStub) + if (pStub == NULL) { - CPUSTUBLINKER sl; + GCX_PREEMP(); - LOG((LF_CORDB,LL_INFO10000, "COMD::GIMS making a multicast delegate\n")); - sl.EmitSecureDelegateInvoke(hash); + MetaSig sig(pMD); - // The cache is process-wide, based on signature. It never unloads - Stub *pCandidate = sl.Link(SystemDomain::GetGlobalLoaderAllocator()->GetStubHeap(), NEWSTUB_FL_MULTICAST); + UINT_PTR hash = CPUSTUBLINKER::HashMulticastInvoke(&sig); - Stub *pWinner = m_pSecureDelegateStubCache->AttemptToSetStub(hash, pCandidate); - pCandidate->DecRef(); - if (!pWinner) - COMPlusThrowOM(); + pStub = m_pSecureDelegateStubCache->GetStub(hash); + if (!pStub) + { + CPUSTUBLINKER sl; - LOG((LF_CORDB,LL_INFO10000, "Putting a MC stub at 0x%x (code:0x%x)\n", - pWinner, (BYTE*)pWinner+sizeof(Stub))); + LOG((LF_CORDB,LL_INFO10000, "COMD::GIMS making a multicast delegate\n")); + sl.EmitSecureDelegateInvoke(hash); - pStub = pWinner; + // The cache is process-wide, based on signature. It never unloads + Stub *pCandidate = sl.Link(SystemDomain::GetGlobalLoaderAllocator()->GetStubHeap(), NEWSTUB_FL_MULTICAST); + + Stub *pWinner = m_pSecureDelegateStubCache->AttemptToSetStub(hash, pCandidate); + pCandidate->DecRef(); + if (!pWinner) + COMPlusThrowOM(); + + LOG((LF_CORDB,LL_INFO10000, "Putting a MC stub at 0x%x (code:0x%x)\n", + pWinner, (BYTE*)pWinner+sizeof(Stub))); + + pStub = pWinner; + } + + g_IBCLogger.LogEEClassCOWTableAccess(pDelegateMT); + EnsureWritablePages(&delegateEEClass->m_pSecureDelegateInvokeStub); + delegateEEClass->m_pSecureDelegateInvokeStub = pStub; } RETURN (pStub->GetEntryPoint()); } diff --git a/src/vm/comdependenthandle.cpp b/src/vm/comdependenthandle.cpp index 0d2cac5..6535a80 100644 --- a/src/vm/comdependenthandle.cpp +++ b/src/vm/comdependenthandle.cpp @@ -74,3 +74,24 @@ FCIMPL3(VOID, DependentHandle::nGetPrimaryAndSecondary, OBJECTHANDLE handle, Obj } FCIMPLEND +FCIMPL2(VOID, DependentHandle::nSetPrimary, OBJECTHANDLE handle, Object *_primary) +{ + FCALL_CONTRACT; + + _ASSERTE(handle != NULL); + + OBJECTREF primary(_primary); + StoreObjectInHandle(handle, primary); +} +FCIMPLEND + +FCIMPL2(VOID, DependentHandle::nSetSecondary, OBJECTHANDLE handle, Object *_secondary) +{ + FCALL_CONTRACT; + + _ASSERTE(handle != NULL); + + OBJECTREF secondary(_secondary); + SetDependentHandleSecondary(handle, secondary); +} +FCIMPLEND diff --git a/src/vm/comdependenthandle.h b/src/vm/comdependenthandle.h index 7cf5a1e..7192a4b 100644 --- a/src/vm/comdependenthandle.h +++ b/src/vm/comdependenthandle.h @@ -45,6 +45,8 @@ public: static FCDECL2(VOID, nGetPrimary, OBJECTHANDLE handle, Object **outPrimary); static FCDECL3(VOID, nGetPrimaryAndSecondary, OBJECTHANDLE handle, Object **outPrimary, Object **outSecondary); static FCDECL1(VOID, nFree, OBJECTHANDLE handle); + static FCDECL2(VOID, nSetPrimary, OBJECTHANDLE handle, Object *primary); + static FCDECL2(VOID, nSetSecondary, OBJECTHANDLE handle, Object *secondary); }; #endif diff --git a/src/vm/commemoryfailpoint.cpp b/src/vm/commemoryfailpoint.cpp index 276a9f3..4d1ed6e 100644 --- a/src/vm/commemoryfailpoint.cpp +++ b/src/vm/commemoryfailpoint.cpp @@ -26,7 +26,7 @@ FCIMPL2(void, COMMemoryFailPoint::GetMemorySettings, UINT64* pMaxGCSegmentSize, { FCALL_CONTRACT; - GCHeap * pGC = GCHeap::GetGCHeap(); + IGCHeap * pGC = GCHeapUtilities::GetGCHeap(); size_t segment_size = pGC->GetValidSegmentSize(FALSE); size_t large_segment_size = pGC->GetValidSegmentSize(TRUE); _ASSERTE(segment_size < SIZE_T_MAX && large_segment_size < SIZE_T_MAX); diff --git a/src/vm/commethodrental.cpp b/src/vm/commethodrental.cpp index 0faf470..0a5c011 100644 --- a/src/vm/commethodrental.cpp +++ b/src/vm/commethodrental.cpp @@ -102,9 +102,9 @@ void QCALLTYPE COMMethodRental::SwapMethodBody(EnregisteredTypeHandle cls, INT32 COMPlusThrowHR(VLDTR_E_MD_BADHEADER); #ifdef FEATURE_INTERPRETER - pMethodDesc->MakeJitWorker(&header, CORJIT_FLG_MAKEFINALCODE, 0); + pMethodDesc->MakeJitWorker(&header, CORJIT_FLAGS(CORJIT_FLAGS::CORJIT_FLAG_MAKEFINALCODE)); #else // !FEATURE_INTERPRETER - pMethodDesc->MakeJitWorker(&header, 0, 0); + pMethodDesc->MakeJitWorker(&header, CORJIT_FLAGS()); #endif // !FEATURE_INTERPRETER } diff --git a/src/vm/commodule.cpp b/src/vm/commodule.cpp index 44a96d3..af6dc48 100644 --- a/src/vm/commodule.cpp +++ b/src/vm/commodule.cpp @@ -768,8 +768,7 @@ mdString QCALLTYPE COMModule::GetStringConstant(QCall::ModuleHandle pModule, LPC _ASSERTE(pwzValue != NULL); HRESULT hr = pRCW->GetEmitter()->DefineUserString(pwzValue, iLength, &strRef); - if (FAILED(hr)) { - _ASSERTE(hr == E_OUTOFMEMORY || !"Unknown failure in DefineUserString"); + if (FAILED(hr)) { COMPlusThrowHR(hr); } diff --git a/src/vm/common.h b/src/vm/common.h index 1233503..9de9f35 100644 --- a/src/vm/common.h +++ b/src/vm/common.h @@ -177,7 +177,7 @@ typedef DPTR(class StringBufferObject) PTR_StringBufferObject; typedef DPTR(class TypeHandle) PTR_TypeHandle; typedef VPTR(class VirtualCallStubManager) PTR_VirtualCallStubManager; typedef VPTR(class VirtualCallStubManagerManager) PTR_VirtualCallStubManagerManager; -typedef VPTR(class GCHeap) PTR_GCHeap; +typedef VPTR(class IGCHeap) PTR_IGCHeap; // // _UNCHECKED_OBJECTREF is for code that can't deal with DEBUG OBJECTREFs diff --git a/src/vm/compile.cpp b/src/vm/compile.cpp index 0a2c75d..8710715 100644 --- a/src/vm/compile.cpp +++ b/src/vm/compile.cpp @@ -382,7 +382,6 @@ HRESULT CEECompileInfo::LoadAssemblyByPath( Assembly * pAssembly; HRESULT hrProcessLibraryBitnessMismatch = S_OK; - bool verifyingImageIsAssembly = false; // We don't want to do a LoadFrom, since they do not work with ngen. Instead, // read the metadata from the file and do a bind based on that. @@ -416,9 +415,6 @@ HRESULT CEECompileInfo::LoadAssemblyByPath( fExplicitBindToNativeImage ? MDInternalImport_NoCache : MDInternalImport_Default); } -#if defined(FEATURE_WINDOWSPHONE) - verifyingImageIsAssembly = true; -#endif // FEATURE_WINDOWSPHONE if (fExplicitBindToNativeImage && !pImage->HasReadyToRunHeader()) { pImage->VerifyIsNIAssembly(); @@ -427,8 +423,6 @@ HRESULT CEECompileInfo::LoadAssemblyByPath( { pImage->VerifyIsAssembly(); } - - verifyingImageIsAssembly = false; // Check to make sure the bitness of the assembly matches the bitness of the process // we will be loading it into and store the result. If a COR_IMAGE_ERROR gets thrown @@ -552,11 +546,7 @@ HRESULT CEECompileInfo::LoadAssemblyByPath( } EX_CATCH_HRESULT(hr); - if (verifyingImageIsAssembly && hr != S_OK) - { - hr = NGEN_E_FILE_NOT_ASSEMBLY; - } - else if ( hrProcessLibraryBitnessMismatch != S_OK && ( hr == COR_E_BADIMAGEFORMAT || hr == HRESULT_FROM_WIN32(ERROR_BAD_EXE_FORMAT) ) ) + if ( hrProcessLibraryBitnessMismatch != S_OK && ( hr == COR_E_BADIMAGEFORMAT || hr == HRESULT_FROM_WIN32(ERROR_BAD_EXE_FORMAT) ) ) { hr = hrProcessLibraryBitnessMismatch; } @@ -1497,7 +1487,7 @@ void CEECompileInfo::CompressDebugInfo( HRESULT CEECompileInfo::GetBaseJitFlags( IN CORINFO_METHOD_HANDLE hMethod, - OUT DWORD *pFlags) + OUT CORJIT_FLAGS *pFlags) { STANDARD_VM_CONTRACT; @@ -3068,6 +3058,13 @@ private: DWORD m_dwExtraData; LPCWSTR m_wszManagedPDBSearchPath; + // Currently The DiasymWriter does not use the correct PDB signature for NGEN PDBS unless + // the NGEN DLL whose symbols are being generated end in .ni.dll. Thus we copy + // to this name if it does not follow this covention (as is true with readyToRun + // dlls). This variable remembers this temp file path so we can delete it after + // Pdb generation. If DiaSymWriter is fixed, we can remove this. + SString m_tempSourceDllName; + // Interfaces for reading IL PDB info ReleaseHolder m_pBinder; ReleaseHolder m_pReader; @@ -3115,6 +3112,8 @@ public: ZeroMemory(m_wszPDBFilePath, sizeof(m_wszPDBFilePath)); } + + ~NGenModulePdbWriter(); HRESULT WritePDBData(); @@ -3415,6 +3414,13 @@ HRESULT NGenModulePdbWriter::InitILPdbData() return S_OK; } +NGenModulePdbWriter::~NGenModulePdbWriter() +{ + // Delete any temporary files we created. + if (m_tempSourceDllName.GetCount() != 0) + DeleteFileW(m_tempSourceDllName); + m_tempSourceDllName.Clear(); +} //--------------------------------------------------------------------------------------- // @@ -3449,8 +3455,32 @@ HRESULT NGenModulePdbWriter::WritePDBData() PEImageLayout * pLoadedLayout = m_pModule->GetFile()->GetLoaded(); + // Currently DiaSymReader does not work properly generating NGEN PDBS unless + // the DLL whose PDB is being generated ends in .ni.*. Unfortunately, readyToRun + // images do not follow this convention and end up producing bad PDBS. To fix + // this (without changing diasymreader.dll which ships indepdendently of .Net Core) + // we copy the file to somethign with this convention before generating the PDB + // and delete it when we are done. + SString dllPath = pLoadedLayout->GetPath(); + if (!dllPath.EndsWithCaseInsensitive(L".ni.dll") && !dllPath.EndsWithCaseInsensitive(L".ni.exe")) + { + SString::Iterator fileNameStart = dllPath.Begin(); + dllPath.FindBack(fileNameStart, '\\'); + + SString::Iterator ext = dllPath.End(); + dllPath.FindBack(ext, '.'); + + // m_tempSourceDllName = Convertion of INPUT.dll to INPUT.ni.dll where the PDB lives. + m_tempSourceDllName = m_wszPdbPath; + m_tempSourceDllName += SString(dllPath, fileNameStart, ext - fileNameStart); + m_tempSourceDllName += L".ni"; + m_tempSourceDllName += SString(dllPath, ext, dllPath.End() - ext); + CopyFileW(dllPath, m_tempSourceDllName, false); + dllPath = m_tempSourceDllName; + } + ReleaseHolder pWriter1; - hr = m_Create(pLoadedLayout->GetPath(), m_wszPdbPath, &pWriter1); + hr = m_Create(dllPath, m_wszPdbPath, &pWriter1); if (FAILED(hr)) return hr; @@ -5423,7 +5453,7 @@ static BOOL CanSatisfyConstraints(Instantiation typicalInst, Instantiation candi StackScratchBuffer buffer; thArg.GetName(candidateInstName); char output[1024]; - sprintf(output, "Generics TypeDependencyAttribute processing: Couldn't satisfy a constraint. Class with Attribute: %s Bad candidate instantiated type: %s\r\n", pMT->GetDebugClassName(), candidateInstName.GetANSI(buffer)); + _snprintf_s(output, _countof(output), _TRUNCATE, "Generics TypeDependencyAttribute processing: Couldn't satisfy a constraint. Class with Attribute: %s Bad candidate instantiated type: %s\r\n", pMT->GetDebugClassName(), candidateInstName.GetANSI(buffer)); OutputDebugStringA(output); */ #endif @@ -6573,7 +6603,9 @@ void CEEPreloader::PrePrepareMethodIfNecessary(CORINFO_METHOD_HANDLE hMethod) { STANDARD_VM_CONTRACT; +#ifdef FEATURE_CER ::PrePrepareMethodIfNecessary(hMethod); +#endif } static void SetStubMethodDescOnInteropMethodDesc(MethodDesc* pInteropMD, MethodDesc* pStubMD, bool fReverseStub) @@ -6650,9 +6682,9 @@ MethodDesc * CEEPreloader::CompileMethodStubIfNeeded( { if (!pStubMD->AsDynamicMethodDesc()->GetILStubResolver()->IsCompiled()) { - DWORD dwJitFlags = pStubMD->AsDynamicMethodDesc()->GetILStubResolver()->GetJitFlags(); + CORJIT_FLAGS jitFlags = pStubMD->AsDynamicMethodDesc()->GetILStubResolver()->GetJitFlags(); - pfnCallback(pCallbackContext, (CORINFO_METHOD_HANDLE)pStubMD, dwJitFlags); + pfnCallback(pCallbackContext, (CORINFO_METHOD_HANDLE)pStubMD, jitFlags); } #ifndef FEATURE_FULL_NGEN // Deduplication diff --git a/src/vm/compile.h b/src/vm/compile.h index 19bbac3..8ee66db 100644 --- a/src/vm/compile.h +++ b/src/vm/compile.h @@ -377,7 +377,7 @@ class CEECompileInfo : public ICorCompileInfo HRESULT GetBaseJitFlags( IN CORINFO_METHOD_HANDLE hMethod, - OUT DWORD *pFlags); + OUT CORJIT_FLAGS *pFlags); #ifdef _WIN64 SIZE_T getPersonalityValue(); diff --git a/src/vm/comsynchronizable.cpp b/src/vm/comsynchronizable.cpp index ef195bf..e62ec13 100644 --- a/src/vm/comsynchronizable.cpp +++ b/src/vm/comsynchronizable.cpp @@ -1604,7 +1604,7 @@ FCIMPL0(Object*, ThreadNative::GetDomain) } FCIMPLEND -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && defined(_MSC_VER) __declspec(naked) LPVOID __fastcall ThreadNative::FastGetDomain() { STATIC_CONTRACT_MODE_COOPERATIVE; @@ -1624,7 +1624,7 @@ done: ret } } -#else // _TARGET_X86_ +#else // _TARGET_X86_ && _MSC_VER LPVOID F_CALL_CONV ThreadNative::FastGetDomain() { CONTRACTL @@ -1650,7 +1650,7 @@ LPVOID F_CALL_CONV ThreadNative::FastGetDomain() } return NULL; } -#endif // _TARGET_X86_ +#endif // _TARGET_X86_ && _MSC_VER #ifdef FEATURE_REMOTING // This is just a helper method that lets BCL get to the managed context diff --git a/src/vm/comthreadpool.cpp b/src/vm/comthreadpool.cpp index 7f629b5..a4c7e75 100644 --- a/src/vm/comthreadpool.cpp +++ b/src/vm/comthreadpool.cpp @@ -632,6 +632,7 @@ void SetAsyncResultProperties( STATIC_CONTRACT_MODE_ANY; STATIC_CONTRACT_SO_TOLERANT; +#ifndef FEATURE_CORECLR ASYNCRESULTREF asyncResult = overlapped->m_asyncResult; // only filestream is expected to have a null delegate in which // case we do the necessary book-keeping here. However, for robustness @@ -655,6 +656,7 @@ void SetAsyncResultProperties( if ((h != NULL) && (h != (HANDLE) -1)) UnsafeSetEvent(h); } +#endif // !FEATURE_CORECLR } VOID BindIoCompletionCallBack_Worker(LPVOID args) @@ -663,11 +665,11 @@ VOID BindIoCompletionCallBack_Worker(LPVOID args) STATIC_CONTRACT_GC_TRIGGERS; STATIC_CONTRACT_MODE_ANY; STATIC_CONTRACT_SO_INTOLERANT; - + DWORD ErrorCode = ((BindIoCompletion_Args *)args)->ErrorCode; DWORD numBytesTransferred = ((BindIoCompletion_Args *)args)->numBytesTransferred; LPOVERLAPPED lpOverlapped = ((BindIoCompletion_Args *)args)->lpOverlapped; - + OVERLAPPEDDATAREF overlapped = ObjectToOVERLAPPEDDATAREF(OverlappedDataObject::GetOverlapped(lpOverlapped)); GCPROTECT_BEGIN(overlapped); @@ -682,7 +684,7 @@ VOID BindIoCompletionCallBack_Worker(LPVOID args) if (overlapped->m_iocb != NULL) { // Caution: the args are not protected, we have to garantee there's no GC from here till - PREPARE_NONVIRTUAL_CALLSITE(METHOD__IOCB_HELPER__PERFORM_IOCOMPLETION_CALLBACK); + PREPARE_NONVIRTUAL_CALLSITE(METHOD__IOCB_HELPER__PERFORM_IOCOMPLETION_CALLBACK); DECLARE_ARGHOLDER_ARRAY(arg, 3); arg[ARGNUM_0] = DWORD_TO_ARGHOLDER(ErrorCode); arg[ARGNUM_1] = DWORD_TO_ARGHOLDER(numBytesTransferred); @@ -692,21 +694,23 @@ VOID BindIoCompletionCallBack_Worker(LPVOID args) CALL_MANAGED_METHOD_NORET(arg); } else - { // no user delegate to callback + { + // no user delegate to callback _ASSERTE((overlapped->m_iocbHelper == NULL) || !"This is benign, but should be optimized"); +#ifndef FEATURE_CORECLR // we cannot do this at threadpool initialization time since mscorlib may not have been loaded if (!g_pAsyncFileStream_AsyncResultClass) { g_pAsyncFileStream_AsyncResultClass = MscorlibBinder::GetClass(CLASS__FILESTREAM_ASYNCRESULT); } +#endif // !FEATURE_CORECLR SetAsyncResultProperties(overlapped, ErrorCode, numBytesTransferred); } GCPROTECT_END(); } - void __stdcall BindIoCompletionCallbackStubEx(DWORD ErrorCode, DWORD numBytesTransferred, LPOVERLAPPED lpOverlapped, @@ -769,9 +773,6 @@ void __stdcall BindIoCompletionCallbackStubEx(DWORD ErrorCode, ManagedThreadBase::ThreadPool(ADID(overlapped->GetAppDomainId()), BindIoCompletionCallBack_Worker, &args); } - - - LOG((LF_INTEROP, LL_INFO10000, "Leaving IO_CallBackStub thread 0x%x retCode 0x%x, overlap 0x%x\n", pThread, ErrorCode, lpOverlapped)); // We should have released all locks. _ASSERTE(g_fEEShutDown || pThread->m_dwLockCount == 0 || pThread->m_fRudeAborted); diff --git a/src/vm/comutilnative.cpp b/src/vm/comutilnative.cpp index b55c635..41655cb 100644 --- a/src/vm/comutilnative.cpp +++ b/src/vm/comutilnative.cpp @@ -27,7 +27,7 @@ #include "frames.h" #include "field.h" #include "winwrap.h" -#include "gc.h" +#include "gcheaputilities.h" #include "fcall.h" #include "invokeutil.h" #include "eeconfig.h" @@ -1478,7 +1478,11 @@ FCIMPL5(VOID, Buffer::BlockCopy, ArrayBase *src, int srcOffset, ArrayBase *dst, PTR_BYTE dstPtr = dst->GetDataPtr() + dstOffset; if ((srcPtr != dstPtr) && (count > 0)) { +#if defined(_AMD64_) && !defined(PLATFORM_UNIX) + JIT_MemCpy(dstPtr, srcPtr, count); +#else memmove(dstPtr, srcPtr, count); +#endif } FC_GC_POLL(); @@ -1524,7 +1528,11 @@ FCIMPL5(VOID, Buffer::InternalBlockCopy, ArrayBase *src, int srcOffset, ArrayBas _ASSERTE(count >= 0); // Copy the data. +#if defined(_AMD64_) && !defined(PLATFORM_UNIX) + JIT_MemCpy(dst->GetDataPtr() + dstOffset, src->GetDataPtr() + srcOffset, count); +#else memmove(dst->GetDataPtr() + dstOffset, src->GetDataPtr() + srcOffset, count); +#endif FC_GC_POLL(); } @@ -1638,7 +1646,7 @@ FCIMPL0(int, GCInterface::GetGcLatencyMode) FC_GC_POLL_NOT_NEEDED(); - int result = (INT32)GCHeap::GetGCHeap()->GetGcLatencyMode(); + int result = (INT32)GCHeapUtilities::GetGCHeap()->GetGcLatencyMode(); return result; } FCIMPLEND @@ -1649,7 +1657,7 @@ FCIMPL1(int, GCInterface::SetGcLatencyMode, int newLatencyMode) FC_GC_POLL_NOT_NEEDED(); - return GCHeap::GetGCHeap()->SetGcLatencyMode(newLatencyMode); + return GCHeapUtilities::GetGCHeap()->SetGcLatencyMode(newLatencyMode); } FCIMPLEND @@ -1659,7 +1667,7 @@ FCIMPL0(int, GCInterface::GetLOHCompactionMode) FC_GC_POLL_NOT_NEEDED(); - int result = (INT32)GCHeap::GetGCHeap()->GetLOHCompactionMode(); + int result = (INT32)GCHeapUtilities::GetGCHeap()->GetLOHCompactionMode(); return result; } FCIMPLEND @@ -1670,7 +1678,7 @@ FCIMPL1(void, GCInterface::SetLOHCompactionMode, int newLOHCompactionyMode) FC_GC_POLL_NOT_NEEDED(); - GCHeap::GetGCHeap()->SetLOHCompactionMode(newLOHCompactionyMode); + GCHeapUtilities::GetGCHeap()->SetLOHCompactionMode(newLOHCompactionyMode); } FCIMPLEND @@ -1681,7 +1689,7 @@ FCIMPL2(FC_BOOL_RET, GCInterface::RegisterForFullGCNotification, UINT32 gen2Perc FC_GC_POLL_NOT_NEEDED(); - FC_RETURN_BOOL(GCHeap::GetGCHeap()->RegisterForFullGCNotification(gen2Percentage, lohPercentage)); + FC_RETURN_BOOL(GCHeapUtilities::GetGCHeap()->RegisterForFullGCNotification(gen2Percentage, lohPercentage)); } FCIMPLEND @@ -1690,7 +1698,7 @@ FCIMPL0(FC_BOOL_RET, GCInterface::CancelFullGCNotification) FCALL_CONTRACT; FC_GC_POLL_NOT_NEEDED(); - FC_RETURN_BOOL(GCHeap::GetGCHeap()->CancelFullGCNotification()); + FC_RETURN_BOOL(GCHeapUtilities::GetGCHeap()->CancelFullGCNotification()); } FCIMPLEND @@ -1711,7 +1719,7 @@ FCIMPL1(int, GCInterface::WaitForFullGCApproach, int millisecondsTimeout) HELPER_METHOD_FRAME_BEGIN_RET_0(); DWORD dwMilliseconds = ((millisecondsTimeout == -1) ? INFINITE : millisecondsTimeout); - result = GCHeap::GetGCHeap()->WaitForFullGCApproach(dwMilliseconds); + result = GCHeapUtilities::GetGCHeap()->WaitForFullGCApproach(dwMilliseconds); HELPER_METHOD_FRAME_END(); @@ -1736,7 +1744,7 @@ FCIMPL1(int, GCInterface::WaitForFullGCComplete, int millisecondsTimeout) HELPER_METHOD_FRAME_BEGIN_RET_0(); DWORD dwMilliseconds = ((millisecondsTimeout == -1) ? INFINITE : millisecondsTimeout); - result = GCHeap::GetGCHeap()->WaitForFullGCComplete(dwMilliseconds); + result = GCHeapUtilities::GetGCHeap()->WaitForFullGCComplete(dwMilliseconds); HELPER_METHOD_FRAME_END(); @@ -1757,7 +1765,7 @@ FCIMPL1(int, GCInterface::GetGeneration, Object* objUNSAFE) if (objUNSAFE == NULL) FCThrowArgumentNull(W("obj")); - int result = (INT32)GCHeap::GetGCHeap()->WhichGeneration(objUNSAFE); + int result = (INT32)GCHeapUtilities::GetGCHeap()->WhichGeneration(objUNSAFE); FC_GC_POLL_RET(); return result; } @@ -1777,7 +1785,7 @@ FCIMPL2(int, GCInterface::CollectionCount, INT32 generation, INT32 getSpecialGCC _ASSERTE(generation >= 0); //We don't need to check the top end because the GC will take care of that. - int result = (INT32)GCHeap::GetGCHeap()->CollectionCount(generation, getSpecialGCCount); + int result = (INT32)GCHeapUtilities::GetGCHeap()->CollectionCount(generation, getSpecialGCCount); FC_GC_POLL_RET(); return result; } @@ -1793,7 +1801,7 @@ int QCALLTYPE GCInterface::StartNoGCRegion(INT64 totalSize, BOOL lohSizeKnown, I GCX_COOP(); - retVal = GCHeap::GetGCHeap()->StartNoGCRegion((ULONGLONG)totalSize, + retVal = GCHeapUtilities::GetGCHeap()->StartNoGCRegion((ULONGLONG)totalSize, lohSizeKnown, (ULONGLONG)lohSize, disallowFullBlockingGC); @@ -1811,7 +1819,7 @@ int QCALLTYPE GCInterface::EndNoGCRegion() BEGIN_QCALL; - retVal = GCHeap::GetGCHeap()->EndNoGCRegion(); + retVal = GCHeapUtilities::GetGCHeap()->EndNoGCRegion(); END_QCALL; @@ -1837,7 +1845,7 @@ FCIMPL1(int, GCInterface::GetGenerationWR, LPVOID handle) if (temp == NULL) COMPlusThrowArgumentNull(W("weak handle")); - iRetVal = (INT32)GCHeap::GetGCHeap()->WhichGeneration(OBJECTREFToObject(temp)); + iRetVal = (INT32)GCHeapUtilities::GetGCHeap()->WhichGeneration(OBJECTREFToObject(temp)); HELPER_METHOD_FRAME_END(); @@ -1860,7 +1868,7 @@ INT64 QCALLTYPE GCInterface::GetTotalMemory() BEGIN_QCALL; GCX_COOP(); - iRetVal = (INT64) GCHeap::GetGCHeap()->GetTotalBytesInUse(); + iRetVal = (INT64) GCHeapUtilities::GetGCHeap()->GetTotalBytesInUse(); END_QCALL; @@ -1885,7 +1893,7 @@ void QCALLTYPE GCInterface::Collect(INT32 generation, INT32 mode) //We don't need to check the top end because the GC will take care of that. GCX_COOP(); - GCHeap::GetGCHeap()->GarbageCollect(generation, FALSE, mode); + GCHeapUtilities::GetGCHeap()->GarbageCollect(generation, FALSE, mode); END_QCALL; } @@ -1918,7 +1926,7 @@ FCIMPL0(int, GCInterface::GetMaxGeneration) { FCALL_CONTRACT; - return(INT32)GCHeap::GetGCHeap()->GetMaxGeneration(); + return(INT32)GCHeapUtilities::GetGCHeap()->GetMaxGeneration(); } FCIMPLEND @@ -1934,7 +1942,7 @@ FCIMPL0(INT64, GCInterface::GetAllocatedBytesForCurrentThread) INT64 currentAllocated = 0; Thread *pThread = GetThread(); - alloc_context* ac = pThread->GetAllocContext(); + gc_alloc_context* ac = pThread->GetAllocContext(); currentAllocated = ac->alloc_bytes + ac->alloc_bytes_loh - (ac->alloc_limit - ac->alloc_ptr); return currentAllocated; @@ -1956,7 +1964,7 @@ FCIMPL1(void, GCInterface::SuppressFinalize, Object *obj) if (!obj->GetMethodTable ()->HasFinalizer()) return; - GCHeap::GetGCHeap()->SetFinalizationRun(obj); + GCHeapUtilities::GetGCHeap()->SetFinalizationRun(obj); FC_GC_POLL(); } FCIMPLEND @@ -1977,7 +1985,7 @@ FCIMPL1(void, GCInterface::ReRegisterForFinalize, Object *obj) if (obj->GetMethodTable()->HasFinalizer()) { HELPER_METHOD_FRAME_BEGIN_1(obj); - GCHeap::GetGCHeap()->RegisterForFinalization(-1, obj); + GCHeapUtilities::GetGCHeap()->RegisterForFinalization(-1, obj); HELPER_METHOD_FRAME_END(); } } @@ -2079,7 +2087,7 @@ void GCInterface::AddMemoryPressure(UINT64 bytesAllocated) m_ulThreshold = (addMethod > multMethod) ? addMethod : multMethod; for (int i = 0; i <= 1; i++) { - if ((GCHeap::GetGCHeap()->CollectionCount(i) / RELATIVE_GC_RATIO) > GCHeap::GetGCHeap()->CollectionCount(i + 1)) + if ((GCHeapUtilities::GetGCHeap()->CollectionCount(i) / RELATIVE_GC_RATIO) > GCHeapUtilities::GetGCHeap()->CollectionCount(i + 1)) { gen_collect = i + 1; break; @@ -2089,14 +2097,14 @@ void GCInterface::AddMemoryPressure(UINT64 bytesAllocated) PREFIX_ASSUME(gen_collect <= 2); - if ((gen_collect == 0) || (m_gc_counts[gen_collect] == GCHeap::GetGCHeap()->CollectionCount(gen_collect))) + if ((gen_collect == 0) || (m_gc_counts[gen_collect] == GCHeapUtilities::GetGCHeap()->CollectionCount(gen_collect))) { GarbageCollectModeAny(gen_collect); } for (int i = 0; i < 3; i++) { - m_gc_counts [i] = GCHeap::GetGCHeap()->CollectionCount(i); + m_gc_counts [i] = GCHeapUtilities::GetGCHeap()->CollectionCount(i); } } } @@ -2115,7 +2123,7 @@ void GCInterface::CheckCollectionCount() { LIMITED_METHOD_CONTRACT; - GCHeap * pHeap = GCHeap::GetGCHeap(); + IGCHeap * pHeap = GCHeapUtilities::GetGCHeap(); if (m_gc_counts[2] != pHeap->CollectionCount(2)) { @@ -2200,7 +2208,7 @@ void GCInterface::NewAddMemoryPressure(UINT64 bytesAllocated) // If still over budget, check current managed heap size if (newMemValue >= budget) { - GCHeap *pGCHeap = GCHeap::GetGCHeap(); + IGCHeap *pGCHeap = GCHeapUtilities::GetGCHeap(); UINT64 heapOver3 = pGCHeap->GetCurrentObjSize() / 3; if (budget < heapOver3) // Max @@ -2274,7 +2282,7 @@ void GCInterface::RemoveMemoryPressure(UINT64 bytesAllocated) for (int i = 0; i < 3; i++) { - m_gc_counts [i] = GCHeap::GetGCHeap()->CollectionCount(i); + m_gc_counts [i] = GCHeapUtilities::GetGCHeap()->CollectionCount(i); } } } @@ -2348,7 +2356,7 @@ NOINLINE void GCInterface::GarbageCollectModeAny(int generation) CONTRACTL_END; GCX_COOP(); - GCHeap::GetGCHeap()->GarbageCollect(generation, FALSE, collection_non_blocking); + GCHeapUtilities::GetGCHeap()->GarbageCollect(generation, FALSE, collection_non_blocking); } // diff --git a/src/vm/constrainedexecutionregion.cpp b/src/vm/constrainedexecutionregion.cpp index d256c43..77b944c 100644 --- a/src/vm/constrainedexecutionregion.cpp +++ b/src/vm/constrainedexecutionregion.cpp @@ -1745,10 +1745,6 @@ void PrepopulateGenericHandleCache(DictionaryLayout *pDictionaryLayout, MethodDesc *pMD, MethodTable *pMT) { -#ifdef FEATURE_CORECLR - // Disable this function in CoreCLR to work around https://github.com/dotnet/corefx/issues/12412. - LIMITED_METHOD_CONTRACT; -#else CONTRACTL { THROWS; GC_TRIGGERS; @@ -1772,7 +1768,6 @@ void PrepopulateGenericHandleCache(DictionaryLayout *pDictionaryLayout, } pOverflows = pOverflows->GetNextLayout(); } -#endif // FEATURE_CORECLR } #ifdef FEATURE_PREJIT diff --git a/src/vm/constrainedexecutionregion.h b/src/vm/constrainedexecutionregion.h index 93ceb63..4b41b25 100644 --- a/src/vm/constrainedexecutionregion.h +++ b/src/vm/constrainedexecutionregion.h @@ -13,6 +13,7 @@ #ifndef __CONSTRAINED_EXECUTION_REGION_H #define __CONSTRAINED_EXECUTION_REGION_H +#ifdef FEATURE_CER #include #include @@ -560,4 +561,6 @@ private: #endif }; +#endif // FEATURE_CER + #endif diff --git a/src/vm/corhost.cpp b/src/vm/corhost.cpp index c229a0e..6091bad 100644 --- a/src/vm/corhost.cpp +++ b/src/vm/corhost.cpp @@ -5170,7 +5170,7 @@ public: HRESULT hr = S_OK; - if (Generation > (int) GCHeap::GetGCHeap()->GetMaxGeneration()) + if (Generation > (int) GCHeapUtilities::GetGCHeap()->GetMaxGeneration()) hr = E_INVALIDARG; if (SUCCEEDED(hr)) @@ -5188,7 +5188,7 @@ public: EX_TRY { STRESS_LOG0(LF_GC, LL_INFO100, "Host triggers GC\n"); - hr = GCHeap::GetGCHeap()->GarbageCollect(Generation); + hr = GCHeapUtilities::GetGCHeap()->GarbageCollect(Generation); } EX_CATCH { @@ -5354,7 +5354,7 @@ HRESULT CCLRGCManager::_SetGCSegmentSize(SIZE_T SegmentSize) HRESULT hr = S_OK; // Sanity check the value, it must be a power of two and big enough. - if (!GCHeap::IsValidSegmentSize(SegmentSize)) + if (!GCHeapUtilities::GetGCHeap()->IsValidSegmentSize(SegmentSize)) { hr = E_INVALIDARG; } @@ -5380,7 +5380,7 @@ HRESULT CCLRGCManager::_SetGCMaxGen0Size(SIZE_T MaxGen0Size) HRESULT hr = S_OK; // Sanity check the value is at least large enough. - if (!GCHeap::IsValidGen0MaxSize(MaxGen0Size)) + if (!GCHeapUtilities::GetGCHeap()->IsValidGen0MaxSize(MaxGen0Size)) { hr = E_INVALIDARG; } @@ -6408,7 +6408,7 @@ HRESULT CCLRDebugManager::SetConnectionTasks( } // Check for Finalizer thread - if (GCHeap::IsGCHeapInitialized() && (pThread == FinalizerThread::GetFinalizerThread())) + if (GCHeapUtilities::IsGCHeapInitialized() && (pThread == FinalizerThread::GetFinalizerThread())) { // _ASSERTE(!"Host should not try to schedule user code on our Finalizer Thread"); IfFailGo(E_INVALIDARG); diff --git a/src/vm/crossgen/CMakeLists.txt b/src/vm/crossgen/CMakeLists.txt index c2392a2..c6ef163 100644 --- a/src/vm/crossgen/CMakeLists.txt +++ b/src/vm/crossgen/CMakeLists.txt @@ -16,7 +16,6 @@ set(VM_CROSSGEN_SOURCES ../comdelegate.cpp ../codeman.cpp ../compile.cpp - ../constrainedexecutionregion.cpp ../custommarshalerinfo.cpp ../domainfile.cpp ../baseassemblyspec.cpp @@ -97,6 +96,12 @@ set(VM_CROSSGEN_SOURCES ../crossgencompile.cpp ) +if(FEATURE_CER) + list(APPEND VM_CROSSGEN_SOURCES + ../constrainedexecutionregion.cpp + ) +endif(FEATURE_CER) + if(FEATURE_READYTORUN) list(APPEND VM_CROSSGEN_SOURCES ../readytoruninfo.cpp diff --git a/src/vm/crossgen_mscorlib/mscorlib_crossgen.nativeproj b/src/vm/crossgen_mscorlib/mscorlib_crossgen.nativeproj index be65670..67e6f4a 100644 --- a/src/vm/crossgen_mscorlib/mscorlib_crossgen.nativeproj +++ b/src/vm/crossgen_mscorlib/mscorlib_crossgen.nativeproj @@ -1,5 +1,12 @@ + + + + + true + + diff --git a/src/vm/crossgencompile.cpp b/src/vm/crossgencompile.cpp index 85859c2..ffb025a 100644 --- a/src/vm/crossgencompile.cpp +++ b/src/vm/crossgencompile.cpp @@ -130,7 +130,7 @@ BOOL __SwitchToThread(DWORD, DWORD) // Globals and misc other // -GPTR_IMPL(GCHeap,g_pGCHeap); +GPTR_IMPL(IGCHeap,g_pGCHeap); BOOL g_fEEOtherStartup=FALSE; BOOL g_fEEComActivatedStartup=FALSE; @@ -138,7 +138,7 @@ BOOL g_fEEComActivatedStartup=FALSE; GVAL_IMPL_INIT(DWORD, g_fHostConfig, 0); #ifdef FEATURE_SVR_GC -SVAL_IMPL_INIT(uint32_t,GCHeap,gcHeapType,GCHeap::GC_HEAP_WKS); +SVAL_IMPL_INIT(uint32_t,IGCHeap,gcHeapType,IGCHeap::GC_HEAP_WKS); #endif void UpdateGCSettingFromHost() diff --git a/src/vm/crst.cpp b/src/vm/crst.cpp index a72ec9d..7bf9bd6 100644 --- a/src/vm/crst.cpp +++ b/src/vm/crst.cpp @@ -627,7 +627,7 @@ void CrstBase::PreEnter() || (pThread != NULL && pThread->PreemptiveGCDisabled()) // If GC heap has not been initialized yet, there is no need to synchronize with GC. // This check is mainly for code called from EEStartup. - || (pThread == NULL && !GCHeap::IsGCHeapInitialized()) ); + || (pThread == NULL && !GCHeapUtilities::IsGCHeapInitialized()) ); } if ((pThread != NULL) && @@ -910,7 +910,7 @@ BOOL CrstBase::IsSafeToTake() _ASSERTE(pThread == NULL || (pThread->PreemptiveGCDisabled() == ((m_dwFlags & CRST_UNSAFE_COOPGC) != 0)) || ((m_dwFlags & (CRST_UNSAFE_ANYMODE | CRST_GC_NOTRIGGER_WHEN_TAKEN)) != 0) || - (GCHeap::IsGCInProgress() && pThread == ThreadSuspend::GetSuspensionThread())); + (GCHeapUtilities::IsGCInProgress() && pThread == ThreadSuspend::GetSuspensionThread())); END_GETTHREAD_ALLOWED; if (m_holderthreadid.IsCurrentThread()) diff --git a/src/vm/customattribute.cpp b/src/vm/customattribute.cpp index 48d79a2..a83815f 100644 --- a/src/vm/customattribute.cpp +++ b/src/vm/customattribute.cpp @@ -141,58 +141,56 @@ CustomAttributeManagedValues Attribute::GetManagedCaValue(CaValue* pCaVal) CustomAttributeManagedValues gc; ZeroMemory(&gc, sizeof(gc)); - - CorSerializationType type = pCaVal->type.tag; - - if (type == SERIALIZATION_TYPE_ENUM) - { - gc.string = StringObject::NewString(pCaVal->type.szEnumName, pCaVal->type.cEnumName); - } - else if (type == SERIALIZATION_TYPE_STRING) - { - gc.string = NULL; + GCPROTECT_BEGIN(gc) + { + CorSerializationType type = pCaVal->type.tag; - if (pCaVal->str.pStr) - gc.string = StringObject::NewString(pCaVal->str.pStr, pCaVal->str.cbStr); - } - else if (type == SERIALIZATION_TYPE_TYPE) - { - gc.string = StringObject::NewString(pCaVal->str.pStr, pCaVal->str.cbStr); - } - else if (type == SERIALIZATION_TYPE_SZARRAY) - { - CorSerializationType arrayType = pCaVal->type.arrayType; - ULONG length = pCaVal->arr.length; - BOOL bAllBlittableCa = arrayType != SERIALIZATION_TYPE_ENUM; + if (type == SERIALIZATION_TYPE_ENUM) + { + gc.string = StringObject::NewString(pCaVal->type.szEnumName, pCaVal->type.cEnumName); + } + else if (type == SERIALIZATION_TYPE_STRING) + { + gc.string = NULL; + + if (pCaVal->str.pStr) + gc.string = StringObject::NewString(pCaVal->str.pStr, pCaVal->str.cbStr); + } + else if (type == SERIALIZATION_TYPE_TYPE) + { + gc.string = StringObject::NewString(pCaVal->str.pStr, pCaVal->str.cbStr); + } + else if (type == SERIALIZATION_TYPE_SZARRAY) + { + CorSerializationType arrayType = pCaVal->type.arrayType; + ULONG length = pCaVal->arr.length; + BOOL bAllBlittableCa = arrayType != SERIALIZATION_TYPE_ENUM; - if (length == (ULONG)-1) - return gc; - - gc.array = (CaValueArrayREF)AllocateValueSzArray(MscorlibBinder::GetClass(CLASS__CUSTOM_ATTRIBUTE_ENCODED_ARGUMENT), length); - CustomAttributeValue* pValues = gc.array->GetDirectPointerToNonObjectElements(); + if (arrayType == SERIALIZATION_TYPE_ENUM) + gc.string = StringObject::NewString(pCaVal->type.szEnumName, pCaVal->type.cEnumName); - for (COUNT_T i = 0; i < length; i ++) - Attribute::SetBlittableCaValue(&pValues[i], &pCaVal->arr[i], &bAllBlittableCa); + if (length != (ULONG)-1) + { + gc.array = (CaValueArrayREF)AllocateValueSzArray(MscorlibBinder::GetClass(CLASS__CUSTOM_ATTRIBUTE_ENCODED_ARGUMENT), length); + CustomAttributeValue* pValues = gc.array->GetDirectPointerToNonObjectElements(); - if (!bAllBlittableCa) - { - GCPROTECT_BEGIN(gc) - { - if (arrayType == SERIALIZATION_TYPE_ENUM) - gc.string = StringObject::NewString(pCaVal->type.szEnumName, pCaVal->type.cEnumName); - for (COUNT_T i = 0; i < length; i ++) + Attribute::SetBlittableCaValue(&pValues[i], &pCaVal->arr[i], &bAllBlittableCa); + + if (!bAllBlittableCa) { - CustomAttributeManagedValues managedCaValue = Attribute::GetManagedCaValue(&pCaVal->arr[i]); - Attribute::SetManagedValue( - managedCaValue, - &gc.array->GetDirectPointerToNonObjectElements()[i]); + for (COUNT_T i = 0; i < length; i ++) + { + CustomAttributeManagedValues managedCaValue = Attribute::GetManagedCaValue(&pCaVal->arr[i]); + Attribute::SetManagedValue( + managedCaValue, + &gc.array->GetDirectPointerToNonObjectElements()[i]); + } } } - GCPROTECT_END(); } } - + GCPROTECT_END(); return gc; } @@ -908,6 +906,7 @@ FCIMPL5(VOID, COMCustomAttribute::ParseAttributeUsageAttribute, PVOID pData, ULO } FCIMPLEND +#ifdef FEATURE_CAS_POLICY FCIMPL4(VOID, COMCustomAttribute::GetSecurityAttributes, ReflectModuleBaseObject *pModuleUNSAFE, DWORD tkToken, CLR_BOOL fAssembly, PTRARRAYREF* ppArray) { FCALL_CONTRACT; @@ -993,6 +992,7 @@ FCIMPL4(VOID, COMCustomAttribute::GetSecurityAttributes, ReflectModuleBaseObject HELPER_METHOD_FRAME_END(); } FCIMPLEND +#endif // FEATURE_CAS_POLICY FCIMPL7(void, COMCustomAttribute::GetPropertyOrFieldData, ReflectModuleBaseObject *pModuleUNSAFE, BYTE** ppBlobStart, BYTE* pBlobEnd, STRINGREF* pName, CLR_BOOL* pbIsProperty, OBJECTREF* pType, OBJECTREF* value) { diff --git a/src/vm/dac/dacwks.targets b/src/vm/dac/dacwks.targets index 82ab543..6f6b927 100644 --- a/src/vm/dac/dacwks.targets +++ b/src/vm/dac/dacwks.targets @@ -40,6 +40,7 @@ + diff --git a/src/vm/dataimage.cpp b/src/vm/dataimage.cpp index 83ff0a4..e90c7e6 100644 --- a/src/vm/dataimage.cpp +++ b/src/vm/dataimage.cpp @@ -896,8 +896,10 @@ void DataImage::FixupRVAs() FixupModuleRVAs(); FixupRvaStructure(); +#ifdef FEATURE_CER if (m_module->m_pCerNgenRootTable != NULL) m_module->m_pCerNgenRootTable->FixupRVAs(this); +#endif // Dev11 bug 181494 instrumentation if (m_Fixups.GetCount() != m_iCurrentFixup) EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); diff --git a/src/vm/debugdebugger.cpp b/src/vm/debugdebugger.cpp index 9ea5427..c8b76bf 100644 --- a/src/vm/debugdebugger.cpp +++ b/src/vm/debugdebugger.cpp @@ -22,7 +22,7 @@ #include "frames.h" #include "vars.hpp" #include "field.h" -#include "gc.h" +#include "gcheaputilities.h" #include "jitinterface.h" #include "debugdebugger.h" #include "dbginterface.h" @@ -1403,7 +1403,7 @@ FCIMPL4(INT32, DebuggerAssert::ShowDefaultAssertDialog, } msgText.Append(W("Description: ")); msgText.Append(message); - + StackSString stackTraceText; if (gc.strStackTrace != NULL) { stackTraceText.Append(W("Stack Trace:\n")); @@ -1414,25 +1414,33 @@ FCIMPL4(INT32, DebuggerAssert::ShowDefaultAssertDialog, windowTitle.Set(W("Assert Failure")); } - // We're taking a string from managed code, and we can't be sure it doesn't have stuff like %s or \n in it. - // So, pass a format string of %s and pass the text as a vararg to our message box method. - // Also, varargs and StackSString don't mix. Convert to string first. - const WCHAR* msgTextAsUnicode = msgText.GetUnicode(); - result = EEMessageBoxNonLocalizedNonFatal(W("%s"), windowTitle, stackTraceText, MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION, msgTextAsUnicode); - - // map the user's choice to the values recognized by - // the System.Diagnostics.Assert package - if (result == IDRETRY) - { - result = FailDebug; - } - else if (result == IDIGNORE) + if (NoGuiOnAssert()) { - result = FailIgnore; + fwprintf(stderr, W("%s\n%s\n%s\n"), windowTitle.GetUnicode(), msgText.GetUnicode(), stackTraceText.GetUnicode()); + result = FailTerminate; } else { - result = FailTerminate; + // We're taking a string from managed code, and we can't be sure it doesn't have stuff like %s or \n in it. + // So, pass a format string of %s and pass the text as a vararg to our message box method. + // Also, varargs and StackSString don't mix. Convert to string first. + const WCHAR* msgTextAsUnicode = msgText.GetUnicode(); + result = EEMessageBoxNonLocalizedNonFatal(W("%s"), windowTitle, stackTraceText, MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION, msgTextAsUnicode); + + // map the user's choice to the values recognized by + // the System.Diagnostics.Assert package + if (result == IDRETRY) + { + result = FailDebug; + } + else if (result == IDIGNORE) + { + result = FailIgnore; + } + else + { + result = FailTerminate; + } } HELPER_METHOD_FRAME_END(); diff --git a/src/vm/debughelp.cpp b/src/vm/debughelp.cpp index df76945..abe45d5 100644 --- a/src/vm/debughelp.cpp +++ b/src/vm/debughelp.cpp @@ -6,9 +6,9 @@ #include "common.h" /*******************************************************************/ -/* The folowing routines used to exist in all builds so they could called from the +/* The following routines used to exist in all builds so they could called from the * debugger before we had strike. - * Now most of them are only inclued in debug builds for diagnostics purposes. + * Now most of them are only included in debug builds for diagnostics purposes. */ /*******************************************************************/ @@ -24,6 +24,12 @@ BOOL isMemoryReadable(const TADDR start, unsigned len) } CONTRACTL_END; +#if !defined(DACCESS_COMPILE) && defined(FEATURE_PAL) + + return PAL_ProbeMemory((PVOID)start, len, FALSE); + +#else // !DACCESS_COMPILE && FEATURE_PAL + // // To accomplish this in a no-throw way, we have to touch each and every page // and see if it is in memory or not. @@ -87,6 +93,7 @@ BOOL isMemoryReadable(const TADDR start, unsigned len) } return 1; +#endif // !DACCESS_COMPILE && FEATURE_PAL } @@ -202,7 +209,7 @@ void *DumpEnvironmentBlock(void) return WszGetEnvironmentStrings(); } -#if defined(_TARGET_X86_) +#if defined(_TARGET_X86_) && !defined(FEATURE_PAL) /*******************************************************************/ // Dump the SEH chain to stderr void PrintSEHChain(void) @@ -1198,12 +1205,12 @@ void DumpGCInfo(MethodDesc* method) _ASSERTE(codeInfo.GetRelOffset() == 0); ICodeManager* codeMan = codeInfo.GetCodeManager(); - GCInfoToken table = codeInfo.GetGCInfoToken(); + GCInfoToken gcInfoToken = codeInfo.GetGCInfoToken(); - unsigned methodSize = (unsigned)codeMan->GetFunctionSize(table); + unsigned methodSize = (unsigned)codeMan->GetFunctionSize(gcInfoToken); - GCDump gcDump(table.Version); - PTR_CBYTE gcInfo = PTR_CBYTE(table.Info); + GCDump gcDump(gcInfoToken.Version); + PTR_CBYTE gcInfo = PTR_CBYTE(gcInfoToken.Info); gcDump.gcPrintf = printfToDbgOut; diff --git a/src/vm/dllimport.cpp b/src/vm/dllimport.cpp index f724169..a3f7f30 100644 --- a/src/vm/dllimport.cpp +++ b/src/vm/dllimport.cpp @@ -1024,7 +1024,7 @@ public: pcsUnmarshal->EmitRET(); } - DWORD dwJitFlags = CORJIT_FLG_IL_STUB; + CORJIT_FLAGS jitFlags(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB); if (m_slIL.HasInteropParamExceptionInfo()) { @@ -1049,7 +1049,7 @@ public: else { // All other IL stubs will need to use the secret parameter. - dwJitFlags |= CORJIT_FLG_PUBLISH_SECRET_PARAM; + jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PUBLISH_SECRET_PARAM); } if (SF_IsReverseStub(m_dwStubFlags)) @@ -1114,7 +1114,7 @@ public: m_slIL.GenerateCode(pbBuffer, cbCode); m_slIL.GetLocalSig(pbLocalSig, cbSig); - pResolver->SetJitFlags(dwJitFlags); + pResolver->SetJitFlags(jitFlags); #ifdef LOGGING LOG((LF_STUBS, LL_INFO1000, "---------------------------------------------------------------------\n")); @@ -1153,7 +1153,7 @@ public: LogILStubFlags(LF_STUBS, LL_INFO1000, m_dwStubFlags); - m_slIL.LogILStub(dwJitFlags); + m_slIL.LogILStub(jitFlags); } LOG((LF_STUBS, LL_INFO1000, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n")); #endif // LOGGING @@ -1170,7 +1170,7 @@ public: pStubMD, pbLocalSig, cbSig, - dwJitFlags, + jitFlags, &convertToHRTryCatch, &cleanupTryFinally, maxStack, @@ -1188,7 +1188,7 @@ public: MethodDesc * pStubMD, PCCOR_SIGNATURE pbLocalSig, DWORD cbSig, - DWORD dwJitFlags, + CORJIT_FLAGS jitFlags, ILStubEHClause * pConvertToHRTryCatchBounds, ILStubEHClause * pCleanupTryFinallyBounds, DWORD maxStack, @@ -1256,7 +1256,7 @@ public: strILStubCode.AppendPrintf(W(".maxstack %d \n"), maxStack); strILStubCode.AppendPrintf(W(".locals %s\n"), strLocalSig.GetUnicode()); - m_slIL.LogILStub(dwJitFlags, &strILStubCode); + m_slIL.LogILStub(jitFlags, &strILStubCode); if (pConvertToHRTryCatchBounds->cbTryLength != 0 && pConvertToHRTryCatchBounds->cbHandlerLength != 0) { @@ -3201,7 +3201,7 @@ void PInvokeStaticSigInfo::DllImportInit(MethodDesc* pMD, LPCUTF8 *ppLibName, LP // initialize data members to defaults PreInit(pMD); - // System.Runtime.InteropServices.DLLImportAttribute + // System.Runtime.InteropServices.DllImportAttribute IMDInternalImport *pInternalImport = pMD->GetMDImport(); CorPinvokeMap mappingFlags = pmMaxValue; mdModuleRef modref = mdModuleRefNil; @@ -4940,7 +4940,7 @@ void NDirect::PopulateNDirectMethodDesc(NDirectMethodDesc* pNMD, PInvokeStaticSi // Currently only ManagedToNativeComInteropStubAttribute is supported. // It returns NULL if no such attribute(s) can be found. // But if the attribute is found and is invalid, or something went wrong in the looking up -// process, a exception will be thrown. If everything goes well, you'll get the MethodDesc +// process, an exception will be thrown. If everything goes well, you'll get the MethodDesc // of the stub method HRESULT FindPredefinedILStubMethod(MethodDesc *pTargetMD, DWORD dwStubFlags, MethodDesc **ppRetStubMD) { @@ -5947,8 +5947,8 @@ PCODE JitILStub(MethodDesc* pStubMD) // A dynamically generated IL stub // - DWORD dwFlags = pStubMD->AsDynamicMethodDesc()->GetILStubResolver()->GetJitFlags(); - pCode = pStubMD->MakeJitWorker(NULL, dwFlags, 0); + CORJIT_FLAGS jitFlags = pStubMD->AsDynamicMethodDesc()->GetILStubResolver()->GetJitFlags(); + pCode = pStubMD->MakeJitWorker(NULL, jitFlags); _ASSERTE(pCode == pStubMD->GetNativeCode()); } diff --git a/src/vm/dllimportcallback.cpp b/src/vm/dllimportcallback.cpp index 198a007..12613cb 100644 --- a/src/vm/dllimportcallback.cpp +++ b/src/vm/dllimportcallback.cpp @@ -164,7 +164,7 @@ EXTERN_C void STDCALL UM2MDoADCallBack(UMEntryThunk *pEntryThunk, UNINSTALL_MANAGED_EXCEPTION_DISPATCHER; } -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) EXTERN_C VOID __cdecl UMThunkStubRareDisable(); EXTERN_C Thread* __stdcall CreateThreadBlockThrow(); @@ -1010,7 +1010,7 @@ Stub *UMThunkMarshInfo::CompileNExportThunk(LoaderHeap *pLoaderHeap, PInvokeStat return pcpusl->Link(pLoaderHeap); } -#else // _TARGET_X86_ +#else // _TARGET_X86_ && !FEATURE_STUBS_AS_IL PCODE UMThunkMarshInfo::GetExecStubEntryPoint() { @@ -1019,7 +1019,7 @@ PCODE UMThunkMarshInfo::GetExecStubEntryPoint() return GetEEFuncEntryPoint(UMThunkStub); } -#endif // _TARGET_X86_ +#endif // _TARGET_X86_ && !FEATURE_STUBS_AS_IL UMEntryThunkCache::UMEntryThunkCache(AppDomain *pDomain) : m_crst(CrstUMEntryThunkCache), @@ -1302,7 +1302,7 @@ UMThunkMarshInfo::~UMThunkMarshInfo() } CONTRACTL_END; -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) if (m_pExecStub) m_pExecStub->DecRef(); #endif @@ -1320,7 +1320,9 @@ MethodDesc* UMThunkMarshInfo::GetILStubMethodDesc(MethodDesc* pInvokeMD, PInvoke dwStubFlags |= NDIRECTSTUB_FL_REVERSE_INTEROP; // could be either delegate interop or not--that info is passed in from the caller #if defined(DEBUGGING_SUPPORTED) - if (GetDebuggerCompileFlags(pSigInfo->GetModule(), 0) & CORJIT_FLG_DEBUG_CODE) + // Combining the next two lines, and eliminating jitDebuggerFlags, leads to bad codegen in x86 Release builds using Visual C++ 19.00.24215.1. + CORJIT_FLAGS jitDebuggerFlags = GetDebuggerCompileFlags(pSigInfo->GetModule(), CORJIT_FLAGS()); + if (jitDebuggerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE)) { dwStubFlags |= NDIRECTSTUB_FL_GENERATEDEBUGGABLEIL; } @@ -1362,7 +1364,7 @@ VOID UMThunkMarshInfo::LoadTimeInit(Signature sig, Module * pModule, MethodDesc m_pModule = pModule; m_sig = sig; -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) INDEBUG(m_cbRetPop = 0xcccc;) #endif } @@ -1370,7 +1372,7 @@ VOID UMThunkMarshInfo::LoadTimeInit(Signature sig, Module * pModule, MethodDesc #ifndef CROSSGEN_COMPILE //---------------------------------------------------------- // This initializer finishes the init started by LoadTimeInit. -// It does stub creation and can throw a exception. +// It does stub creation and can throw an exception. // // It can safely be called multiple times and by concurrent // threads. @@ -1394,7 +1396,9 @@ VOID UMThunkMarshInfo::RunTimeInit() DWORD dwStubFlags = NDIRECTSTUB_FL_NGENEDSTUB | NDIRECTSTUB_FL_REVERSE_INTEROP | NDIRECTSTUB_FL_DELEGATE; #if defined(DEBUGGING_SUPPORTED) - if (GetDebuggerCompileFlags(GetModule(), 0) & CORJIT_FLG_DEBUG_CODE) + // Combining the next two lines, and eliminating jitDebuggerFlags, leads to bad codegen in x86 Release builds using Visual C++ 19.00.24215.1. + CORJIT_FLAGS jitDebuggerFlags = GetDebuggerCompileFlags(GetModule(), CORJIT_FLAGS()); + if (jitDebuggerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE)) { dwStubFlags |= NDIRECTSTUB_FL_GENERATEDEBUGGABLEIL; } @@ -1403,7 +1407,7 @@ VOID UMThunkMarshInfo::RunTimeInit() pFinalILStub = GetStubForInteropMethod(pMD, dwStubFlags, &pStubMD); } -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) PInvokeStaticSigInfo sigInfo; if (pMD != NULL) @@ -1454,7 +1458,7 @@ VOID UMThunkMarshInfo::RunTimeInit() pFinalExecStub->DecRef(); } -#else // _TARGET_X86_ +#else // _TARGET_X86_ && !FEATURE_STUBS_AS_IL if (pFinalILStub == NULL) { @@ -1495,7 +1499,7 @@ VOID UMThunkMarshInfo::RunTimeInit() // m_cbActualArgSize = (pStubMD != NULL) ? pStubMD->AsDynamicMethodDesc()->GetNativeStackArgSize() : pMD->SizeOfArgStack(); -#endif // _TARGET_X86_ +#endif // _TARGET_X86_ && !FEATURE_STUBS_AS_IL // Must be the last thing we set! InterlockedCompareExchangeT(&m_pILStub, pFinalILStub, (PCODE)1); diff --git a/src/vm/dllimportcallback.h b/src/vm/dllimportcallback.h index 6de87d7..c2ed6d0 100644 --- a/src/vm/dllimportcallback.h +++ b/src/vm/dllimportcallback.h @@ -110,7 +110,7 @@ public: return m_pMD; } -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) PCODE GetExecStubEntryPoint() { WRAPPER_NO_CONTRACT; @@ -199,18 +199,18 @@ public: return (UINT32)offsetof(UMThunkMarshInfo, m_pILStub); } -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) // Compiles an unmanaged to managed thunk for the given signature. The thunk // will call the stub or, if fNoStub == TRUE, directly the managed target. Stub *CompileNExportThunk(LoaderHeap *pLoaderHeap, PInvokeStaticSigInfo* pSigInfo, MetaSig *pMetaSig, BOOL fNoStub); -#endif // _TARGET_X86_ +#endif // _TARGET_X86_ && !FEATURE_STUBS_AS_IL private: PCODE m_pILStub; // IL stub for marshaling // On x86, NULL for no-marshal signatures // On non-x86, the managed entrypoint for no-delegate no-marshal signatures UINT32 m_cbActualArgSize; // caches m_pSig.SizeOfFrameArgumentArray() -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) Stub* m_pExecStub; // UMEntryThunk jumps directly here UINT16 m_cbRetPop; // stack bytes popped by callee (for UpdateRegDisplay) UINT16 m_callConv; // unmanaged calling convention and flags (CorPinvokeMap) @@ -248,7 +248,7 @@ public: static UMEntryThunk* CreateUMEntryThunk(); static VOID FreeUMEntryThunk(UMEntryThunk* p); -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) // Compiles an unmanaged to managed thunk with the given calling convention adaptation. // - psrcofsregs are stack offsets that should be loaded to argument registers (ECX, EDX) // - psrcofs are stack offsets that should be repushed for the managed target @@ -263,7 +263,7 @@ public: UINT *psrcofsregs, UINT *psrcofs, UINT retbufofs); -#endif // _TARGET_X86_ +#endif // _TARGET_X86_ && !FEATURE_STUBS_AS_IL #ifndef DACCESS_COMPILE VOID LoadTimeInit(PCODE pManagedTarget, @@ -569,12 +569,12 @@ private: AppDomain *m_pDomain; }; -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) //------------------------------------------------------------------------- // One-time creation of special prestub to initialize UMEntryThunks. //------------------------------------------------------------------------- Stub *GenerateUMThunkPrestub(); -#endif +#endif // _TARGET_X86_ && !FEATURE_STUBS_AS_IL //------------------------------------------------------------------------- // NExport stub diff --git a/src/vm/domainfile.cpp b/src/vm/domainfile.cpp index 2353712..bfb69cd 100644 --- a/src/vm/domainfile.cpp +++ b/src/vm/domainfile.cpp @@ -4140,8 +4140,8 @@ void DomainAssembly::EnumStaticGCRefs(promote_func* fn, ScanContext* sc) } CONTRACT_END; - _ASSERTE(GCHeap::IsGCInProgress() && - GCHeap::IsServerHeap() && + _ASSERTE(GCHeapUtilities::IsGCInProgress() && + GCHeapUtilities::IsServerHeap() && IsGCSpecialThread()); DomainModuleIterator i = IterateModules(kModIterIncludeLoaded); diff --git a/src/vm/dwreport.cpp b/src/vm/dwreport.cpp index 77669b2..5ae4f84 100644 --- a/src/vm/dwreport.cpp +++ b/src/vm/dwreport.cpp @@ -3212,7 +3212,7 @@ FaultReportResult DoFaultReport( // Was Watson attempted, successful? // thread under Coop mode, this will let the new generated DoFaultReportCallBack // thread trigger a deadlock. So in this case, we should directly abort the fault // report to avoid the deadlock. - ((IsGCThread() || pThread->PreemptiveGCDisabled()) && GCHeap::IsGCInProgress()) || + ((IsGCThread() || pThread->PreemptiveGCDisabled()) && GCHeapUtilities::IsGCInProgress()) || FAILED(g_pDebugInterface->RequestFavor(DoFaultReportFavorWorker, pData))) { // If we can't initialize the debugger helper thread or we are running on the debugger helper diff --git a/src/vm/ecalllist.h b/src/vm/ecalllist.h index 8d4164e..b110d0e 100644 --- a/src/vm/ecalllist.h +++ b/src/vm/ecalllist.h @@ -108,6 +108,8 @@ FCFuncStart(gDependentHandleFuncs) FCFuncElement("nGetPrimary", DependentHandle::nGetPrimary) FCFuncElement("nGetPrimaryAndSecondary", DependentHandle::nGetPrimaryAndSecondary) FCFuncElement("nFree", DependentHandle::nFree) + FCFuncElement("nSetPrimary", DependentHandle::nSetPrimary) + FCFuncElement("nSetSecondary", DependentHandle::nSetSecondary) FCFuncEnd() #ifndef FEATURE_CORECLR @@ -195,15 +197,6 @@ FCFuncStart(gTimeSpanFuncs) FCFuncEnd() #endif // !FEATURE_CORECLR -#ifndef FEATURE_CORECLR // FCalls used by System.TimeZone -FCFuncStart(gTimeZoneFuncs) - FCFuncElement("nativeGetTimeZoneMinuteOffset", COMNlsInfo::nativeGetTimeZoneMinuteOffset) - FCFuncElement("nativeGetStandardName", COMNlsInfo::nativeGetStandardName) - FCFuncElement("nativeGetDaylightName", COMNlsInfo::nativeGetDaylightName) - FCFuncElement("nativeGetDaylightChanges", COMNlsInfo::nativeGetDaylightChanges) -FCFuncEnd() -#endif // FEATURE_CORECLR - FCFuncStart(gObjectFuncs) FCIntrinsic("GetType", ObjectNative::GetClass, CORINFO_INTRINSIC_Object_GetType) FCFuncElement("MemberwiseClone", ObjectNative::Clone) @@ -297,6 +290,7 @@ FCFuncStart(gEnvironmentFuncs) FCFuncElement("GetResourceFromDefault", GetResourceFromDefault) #endif // !FEATURE_CORECLR FCFuncElement("GetCommandLineArgsNative", SystemNative::GetCommandLineArgs) + FCFuncElement("get_CurrentProcessorNumber", SystemNative::GetCurrentProcessorNumber) #if defined(FEATURE_COMINTEROP) && !defined(FEATURE_CORESYSTEM) QCFuncElement("WinRTSupported", SystemNative::WinRTSupported) @@ -650,9 +644,11 @@ FCFuncStart(gCustomAttributeEncodedArgument) FCFuncElement("ParseAttributeArguments", Attribute::ParseAttributeArguments) FCFuncEnd() +#ifdef FEATURE_CAS_POLICY FCFuncStart(gPseudoCustomAttribute) FCFuncElement("_GetSecurityAttributes", COMCustomAttribute::GetSecurityAttributes) FCFuncEnd() +#endif FCFuncStart(gCOMCustomAttributeFuncs) FCFuncElement("_ParseAttributeUsageAttribute", COMCustomAttribute::ParseAttributeUsageAttribute) @@ -1041,7 +1037,7 @@ FCFuncStart(gTypeNameBuilder) QCFuncElement("Clear", TypeNameBuilder::_Clear) FCFuncEnd() -#ifndef FEATURE_CORECLR + FCFuncStart(gSafeTypeNameParserHandle) QCFuncElement("_ReleaseTypeNameParser", TypeName::QReleaseTypeNameParser) FCFuncEnd() @@ -1053,7 +1049,6 @@ FCFuncStart(gTypeNameParser) QCFuncElement("_GetModifiers", TypeName::QGetModifiers) QCFuncElement("_GetAssemblyName", TypeName::QGetAssemblyName) FCFuncEnd() -#endif //!FEATURE_CORECLR #ifdef FEATURE_CAS_POLICY FCFuncStart(gPEFileFuncs) @@ -1146,6 +1141,7 @@ FCFuncEnd() FCFuncStart(gAssemblyLoadContextFuncs) QCFuncElement("InitializeAssemblyLoadContext", AssemblyNative::InitializeAssemblyLoadContext) QCFuncElement("LoadFromPath", AssemblyNative::LoadFromPath) + QCFuncElement("GetLoadedAssembliesInternal", AssemblyNative::GetLoadedAssembliesInternal) QCFuncElement("InternalLoadUnmanagedDllFromPath", AssemblyNative::InternalLoadUnmanagedDllFromPath) QCFuncElement("OverrideDefaultAssemblyLoadContextForCurrentDomain", AssemblyNative::OverrideDefaultAssemblyLoadContextForCurrentDomain) QCFuncElement("CanUseAppPathAssemblyLoadContextInCurrentDomain", AssemblyNative::CanUseAppPathAssemblyLoadContextInCurrentDomain) @@ -1165,9 +1161,9 @@ FCFuncStart(gAssemblyNameFuncs) FCFuncElement("nGetPublicKeyToken", AssemblyNameNative::GetPublicKeyToken) #ifndef FEATURE_CORECLR FCFuncElement("EscapeCodeBase", AssemblyNameNative::EscapeCodeBase) +#endif // !FEATURE_CORECLR FCFuncElement("ReferenceMatchesDefinitionInternal", AssemblyNameNative::ReferenceMatchesDefinition) FCFuncElement("nGetFileInformation", AssemblyNameNative::GetFileInformation) -#endif // !FEATURE_CORECLR FCFuncEnd() FCFuncStart(gLoaderAllocatorFuncs) @@ -1251,32 +1247,63 @@ FCFuncStart(gMathFuncs) FCIntrinsic("Tanh", COMDouble::Tanh, CORINFO_INTRINSIC_Tanh) FCFuncEnd() +FCFuncStart(gMathFFuncs) + FCIntrinsic("Acos", COMSingle::Acos, CORINFO_INTRINSIC_Acos) + FCIntrinsic("Asin", COMSingle::Asin, CORINFO_INTRINSIC_Asin) + FCIntrinsic("Atan", COMSingle::Atan, CORINFO_INTRINSIC_Atan) + FCIntrinsic("Atan2", COMSingle::Atan2, CORINFO_INTRINSIC_Atan2) + FCIntrinsic("Ceiling", COMSingle::Ceil, CORINFO_INTRINSIC_Ceiling) + FCIntrinsic("Cos", COMSingle::Cos, CORINFO_INTRINSIC_Cos) + FCIntrinsic("Cosh", COMSingle::Cosh, CORINFO_INTRINSIC_Cosh) + FCIntrinsic("Exp", COMSingle::Exp, CORINFO_INTRINSIC_Exp) + FCIntrinsic("Floor", COMSingle::Floor, CORINFO_INTRINSIC_Floor) + FCFuncElement("Log", COMSingle::Log) + FCIntrinsic("Log10", COMSingle::Log10, CORINFO_INTRINSIC_Log10) + FCIntrinsic("Pow", COMSingle::Pow, CORINFO_INTRINSIC_Pow) + FCIntrinsic("Round", COMSingle::Round, CORINFO_INTRINSIC_Round) + FCIntrinsic("Sin", COMSingle::Sin, CORINFO_INTRINSIC_Sin) + FCIntrinsic("Sinh", COMSingle::Sinh, CORINFO_INTRINSIC_Sinh) + FCFuncElement("SplitFractionSingle", COMSingle::ModF) + FCIntrinsic("Sqrt", COMSingle::Sqrt, CORINFO_INTRINSIC_Sqrt) + FCIntrinsic("Tan", COMSingle::Tan, CORINFO_INTRINSIC_Tan) + FCIntrinsic("Tanh", COMSingle::Tanh, CORINFO_INTRINSIC_Tanh) +FCFuncEnd() + +FCFuncStart(gRuntimeThreadFuncs) + FCFuncElement("get_IsAlive", ThreadNative::IsAlive) + FCFuncElement("IsBackgroundNative", ThreadNative::IsBackground) + FCFuncElement("SetBackgroundNative", ThreadNative::SetBackground) + FCFuncElement("get_IsThreadPoolThread", ThreadNative::IsThreadpoolThread) + FCFuncElement("GetPriorityNative", ThreadNative::GetPriority) + FCFuncElement("SetPriorityNative", ThreadNative::SetPriority) + FCFuncElement("GetThreadStateNative", ThreadNative::GetThreadState) +#ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT + FCFuncElement("GetApartmentStateNative", ThreadNative::GetApartmentState) + FCFuncElement("SetApartmentStateNative", ThreadNative::SetApartmentState) +#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT +#ifdef FEATURE_COMINTEROP + FCFuncElement("DisableComObjectEagerCleanup", ThreadNative::DisableComObjectEagerCleanup) +#endif // FEATURE_COMINTEROP + FCFuncElement("InterruptInternal", ThreadNative::Interrupt) + FCFuncElement("JoinInternal", ThreadNative::Join) +FCFuncEnd() + FCFuncStart(gThreadFuncs) FCDynamic("InternalGetCurrentThread", CORINFO_INTRINSIC_Illegal, ECall::InternalGetCurrentThread) FCFuncElement("StartInternal", ThreadNative::Start) #ifndef FEATURE_CORECLR FCFuncElement("SuspendInternal", ThreadNative::Suspend) FCFuncElement("ResumeInternal", ThreadNative::Resume) - FCFuncElement("InterruptInternal", ThreadNative::Interrupt) -#endif - FCFuncElement("get_IsAlive", ThreadNative::IsAlive) - FCFuncElement("GetThreadStateNative", ThreadNative::GetThreadState) -#ifndef FEATURE_CORECLR - FCFuncElement("GetPriorityNative", ThreadNative::GetPriority) - FCFuncElement("SetPriorityNative", ThreadNative::SetPriority) #endif #ifdef FEATURE_LEAK_CULTURE_INFO FCFuncElement("nativeGetSafeCulture", ThreadNative::nativeGetSafeCulture) #else QCFuncElement("nativeInitCultureAccessors", ThreadNative::nativeInitCultureAccessors) #endif - FCFuncElement("JoinInternal", ThreadNative::Join) #undef Sleep FCFuncElement("SleepInternal", ThreadNative::Sleep) #define Sleep(a) Dont_Use_Sleep(a) FCFuncElement("SetStart", ThreadNative::SetStart) - FCFuncElement("SetBackgroundNative", ThreadNative::SetBackground) - FCFuncElement("IsBackgroundNative", ThreadNative::IsBackground) #ifdef FEATURE_REMOTING FCFuncElement("GetContextInternal", ThreadNative::GetContextFromContextID) #endif @@ -1303,23 +1330,15 @@ FCFuncStart(gThreadFuncs) #ifndef FEATURE_CORECLR FCFuncElement("ResetAbortNative", ThreadNative::ResetAbort) #endif // FEATURE_CORECLR - FCFuncElement("get_IsThreadPoolThread", ThreadNative::IsThreadpoolThread) FCFuncElement("SpinWaitInternal", ThreadNative::SpinWait) QCFuncElement("YieldInternal", ThreadNative::YieldThread) FCIntrinsic("GetCurrentThreadNative", ThreadNative::GetCurrentThread, CORINFO_INTRINSIC_GetCurrentManagedThread) FCIntrinsic("get_ManagedThreadId", ThreadNative::GetManagedThreadId, CORINFO_INTRINSIC_GetManagedThreadId) FCFuncElement("InternalFinalize", ThreadNative::Finalize) -#if defined(FEATURE_COMINTEROP) && !defined(FEATURE_CORECLR) - FCFuncElement("DisableComObjectEagerCleanup", ThreadNative::DisableComObjectEagerCleanup) -#endif // defined(FEATURE_COMINTEROP) && !defined(FEATURE_CORECLR) #ifdef FEATURE_LEAK_CULTURE_INFO FCFuncElement("nativeSetThreadUILocale", ThreadNative::SetThreadUILocale) #endif #ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT -#ifndef FEATURE_CORECLR - FCFuncElement("SetApartmentStateNative", ThreadNative::SetApartmentState) - FCFuncElement("GetApartmentStateNative", ThreadNative::GetApartmentState) -#endif // FEATURE_CORECLR FCFuncElement("StartupSetApartmentStateInternal", ThreadNative::StartupSetApartmentState) #endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT FCIntrinsic("MemoryBarrier", ThreadNative::FCMemoryBarrier, CORINFO_INTRINSIC_MemoryBarrier) @@ -1331,10 +1350,8 @@ FCFuncStart(gThreadFuncs) FCFuncEnd() FCFuncStart(gThreadPoolFuncs) -#ifndef FEATURE_CORECLR FCFuncElement("PostQueuedCompletionStatus", ThreadPoolNative::CorPostQueuedCompletionStatus) FCFuncElement("GetAvailableThreadsNative", ThreadPoolNative::CorGetAvailableThreads) -#endif // FEATURE_CORECLR FCFuncElement("SetMinThreadsNative", ThreadPoolNative::CorSetMinThreads) FCFuncElement("GetMinThreadsNative", ThreadPoolNative::CorGetMinThreads) FCFuncElement("RegisterWaitForSingleObjectNative", ThreadPoolNative::CorRegisterWaitForSingleObject) @@ -1444,8 +1461,8 @@ FCFuncStart(gCompareInfoFuncs) QCFuncElement("InternalGetSortKey", COMNlsInfo::InternalGetSortKey) #ifndef FEATURE_CORECLR QCFuncElement("InternalGetSortVersion", COMNlsInfo::InternalGetSortVersion) - QCFuncElement("InternalGetNlsVersionEx", COMNlsInfo::InternalGetNlsVersionEx) #endif + QCFuncElement("InternalGetNlsVersionEx", COMNlsInfo::InternalGetNlsVersionEx) FCFuncEnd() FCFuncStart(gEncodingTableFuncs) @@ -1567,11 +1584,9 @@ FCFuncStart(gGCInterfaceFuncs) FCFuncElement("_GetAllocatedBytesForCurrentThread", GCInterface::GetAllocatedBytesForCurrentThread) FCFuncEnd() -#ifndef FEATURE_CORECLR FCFuncStart(gMemoryFailPointFuncs) FCFuncElement("GetMemorySettings", COMMemoryFailPoint::GetMemorySettings) FCFuncEnd() -#endif // FEATURE_CORECLR FCFuncStart(gInteropMarshalFuncs) FCFuncElement("GetLastWin32Error", MarshalNative::GetLastWin32Error) @@ -1582,10 +1597,10 @@ FCFuncStart(gInteropMarshalFuncs) FCFuncElement("DestroyStructure", MarshalNative::DestroyStructure) FCFuncElement("UnsafeAddrOfPinnedArrayElement", MarshalNative::FCUnsafeAddrOfPinnedArrayElement) FCFuncElement("GetExceptionCode", ExceptionNative::GetExceptionCode) + QCFuncElement("GetHINSTANCE", COMModule::GetHINSTANCE) #ifndef FEATURE_CORECLR QCFuncElement("InternalNumParamBytes", MarshalNative::NumParamBytes) FCFuncElement("GetExceptionPointers", ExceptionNative::GetExceptionPointers) - QCFuncElement("GetHINSTANCE", COMModule::GetHINSTANCE) FCFuncElement("GetUnmanagedThunkForManagedMethodPtr", MarshalNative::GetUnmanagedThunkForManagedMethodPtr) FCFuncElement("GetManagedThunkForUnmanagedMethodPtr", MarshalNative::GetManagedThunkForUnmanagedMethodPtr) FCFuncElement("InternalGetThreadFromFiberCookie", MarshalNative::GetThreadFromFiberCookie) @@ -1630,11 +1645,12 @@ FCFuncStart(gInteropMarshalFuncs) FCFuncElement("InternalReleaseComObject", MarshalNative::ReleaseComObject) FCFuncElement("Release", MarshalNative::Release) FCFuncElement("InitializeWrapperForWinRT", MarshalNative::InitializeWrapperForWinRT) + FCFuncElement("GetTypedObjectForIUnknown", MarshalNative::GetTypedObjectForIUnknown) + FCFuncElement("ChangeWrapperHandleStrength", MarshalNative::ChangeWrapperHandleStrength) + FCFuncElement("CleanupUnusedObjectsInCurrentContext", MarshalNative::CleanupUnusedObjectsInCurrentContext) #ifndef FEATURE_CORECLR FCFuncElement("GetLoadedTypeForGUID", MarshalNative::GetLoadedTypeForGUID) FCFuncElement("GetITypeInfoForType", MarshalNative::GetITypeInfoForType) - FCFuncElement("GetTypedObjectForIUnknown", MarshalNative::GetTypedObjectForIUnknown) - FCFuncElement("CleanupUnusedObjectsInCurrentContext", MarshalNative::CleanupUnusedObjectsInCurrentContext) FCFuncElement("IsTypeVisibleFromCom", MarshalNative::IsTypeVisibleFromCom) FCFuncElement("FCallGenerateGuidForType", MarshalNative::DoGenerateGuidForType) FCFuncElement("FCallGetTypeLibGuid", MarshalNative::DoGetTypeLibGuid) @@ -1648,7 +1664,6 @@ FCFuncStart(gInteropMarshalFuncs) FCFuncElement("InternalGetComSlotForMethodInfo", MarshalNative::GetComSlotForMethodInfo) FCFuncElement("InternalSwitchCCW", MarshalNative::SwitchCCW) FCFuncElement("InternalWrapIUnknownWithComObject", MarshalNative::WrapIUnknownWithComObject) - FCFuncElement("ChangeWrapperHandleStrength", MarshalNative::ChangeWrapperHandleStrength) QCFuncElement("_GetInspectableIids", MarshalNative::GetInspectableIIDs) QCFuncElement("_GetCachedWinRTTypes", MarshalNative::GetCachedWinRTTypes) QCFuncElement("_GetCachedWinRTTypeByIid", MarshalNative::GetCachedWinRTTypeByIID) @@ -1829,8 +1844,8 @@ FCFuncStart(gCompilerFuncs) FCFuncElement("GetObjectValue", ObjectNative::GetObjectValue) FCIntrinsic("InitializeArray", ArrayNative::InitializeArray, CORINFO_INTRINSIC_InitializeArray) FCFuncElement("_RunClassConstructor", ReflectionInvocation::RunClassConstructor) -#ifndef FEATURE_CORECLR FCFuncElement("_RunModuleConstructor", ReflectionInvocation::RunModuleConstructor) +#ifndef FEATURE_CORECLR FCFuncElement("_PrepareMethod", ReflectionInvocation::PrepareMethod) #endif // !FEATURE_CORECLR QCFuncElement("_CompileMethod", ReflectionInvocation::CompileMethod) @@ -1843,14 +1858,12 @@ FCFuncStart(gCompilerFuncs) FCFuncElement("GetHashCode", ObjectNative::GetHashCode) FCFuncElement("Equals", ObjectNative::Equals) FCFuncElement("EnsureSufficientExecutionStack", ReflectionInvocation::EnsureSufficientExecutionStack) -#ifdef FEATURE_CORECLR FCFuncElement("TryEnsureSufficientExecutionStack", ReflectionInvocation::TryEnsureSufficientExecutionStack) -#endif // FEATURE_CORECLR FCFuncEnd() FCFuncStart(gContextSynchronizationFuncs) #ifdef FEATURE_SYNCHRONIZATIONCONTEXT_WAIT - FCFuncElement("WaitHelper", SynchronizationContextNative::WaitHelper) + FCFuncElement("WaitHelperNative", SynchronizationContextNative::WaitHelper) #endif // #ifdef FEATURE_SYNCHRONIZATIONCONTEXT_WAIT #ifdef FEATURE_APPX QCFuncElement("GetWinRTDispatcherForCurrentThread", SynchronizationContextNative::GetWinRTDispatcherForCurrentThread) @@ -2191,9 +2204,6 @@ FCClassElement("CultureData", "System.Globalization", gCultureDataFuncs) FCClassElement("CultureInfo", "System.Globalization", gCultureInfoFuncs) #endif FCClassElement("Currency", "System", gCurrencyFuncs) -#ifndef FEATURE_CORECLR -FCClassElement("CurrentSystemTimeZone", "System", gTimeZoneFuncs) -#endif // FEATURE_CORECLR FCClassElement("CustomAttribute", "System.Reflection", gCOMCustomAttributeFuncs) FCClassElement("CustomAttributeEncodedArgument", "System.Reflection", gCustomAttributeEncodedArgument) FCClassElement("DateMarshaler", "System.StubHelpers", gDateMarshalerFuncs) @@ -2255,12 +2265,11 @@ FCClassElement("Marshal", "System.Runtime.InteropServices", gInteropMarshalFuncs FCClassElement("MarshalByRefObject", "System", gMarshalByRefFuncs) #endif FCClassElement("Math", "System", gMathFuncs) +FCClassElement("MathF", "System", gMathFFuncs) #ifdef MDA_SUPPORTED FCClassElement("Mda", "System", gMda) #endif -#ifndef FEATURE_CORECLR FCClassElement("MemoryFailPoint", "System.Runtime", gMemoryFailPointFuncs) -#endif // FEATURE_CORECLR #ifdef FEATURE_REMOTING FCClassElement("Message", "System.Runtime.Remoting.Messaging", gMessageFuncs) #endif @@ -2307,7 +2316,9 @@ FCClassElement("PolicyManager", "System.Security", gPolicyManagerFuncs) FCClassElement("ProfileOptimization", "System.Runtime", gProfileOptimizationFuncs) #endif // defined(FEATURE_MULTICOREJIT) && !defined(FEATURE_CORECLR) +#ifdef FEATURE_CAS_POLICY FCClassElement("PseudoCustomAttribute", "System.Reflection", gPseudoCustomAttribute) +#endif #ifdef FEATURE_CORECLR FCClassElement("PunkSafeHandle", "System.Reflection.Emit", gSymWrapperCodePunkSafeHandleFuncs) #endif @@ -2346,6 +2357,7 @@ FCClassElement("RuntimeFieldHandle", "System", gCOMFieldHandleNewFuncs) FCClassElement("RuntimeHelpers", "System.Runtime.CompilerServices", gCompilerFuncs) FCClassElement("RuntimeMethodHandle", "System", gRuntimeMethodHandle) FCClassElement("RuntimeModule", "System.Reflection", gCOMModuleFuncs) +FCClassElement("RuntimeThread", "Internal.Runtime.Augments", gRuntimeThreadFuncs) FCClassElement("RuntimeType", "System", gSystem_RuntimeType) FCClassElement("RuntimeTypeHandle", "System", gCOMTypeHandleFuncs) FCClassElement("SafeBuffer", "System.Runtime.InteropServices", gSafeBufferFuncs) @@ -2371,9 +2383,8 @@ FCClassElement("SafePEFileHandle", "Microsoft.Win32.SafeHandles", gPEFileFuncs) #ifdef FEATURE_CRYPTO FCClassElement("SafeProvHandle", "System.Security.Cryptography", gSafeProvHandleFuncs) #endif -#ifndef FEATURE_CORECLR FCClassElement("SafeTypeNameParserHandle", "System", gSafeTypeNameParserHandle) -#endif //!FEATURE_CORECLR + #if defined(FEATURE_IMPERSONATION) || defined(FEATURE_COMPRESSEDSTACK) FCClassElement("SecurityContext", "System.Security", gCOMSecurityContextFuncs) #endif // defined(FEATURE_IMPERSONATION) || defined(FEATURE_COMPRESSEDSTACK) @@ -2414,9 +2425,7 @@ FCClassElement("TypeLibConverter", "System.Runtime.InteropServices", gTypeLibCon #endif FCClassElement("TypeLoadException", "System", gTypeLoadExceptionFuncs) FCClassElement("TypeNameBuilder", "System.Reflection.Emit", gTypeNameBuilder) -#ifndef FEATURE_CORECLR FCClassElement("TypeNameParser", "System", gTypeNameParser) -#endif //!FEATURE_CORECLR FCClassElement("TypedReference", "System", gTypedReferenceFuncs) FCClassElement("URLString", "System.Security.Util", gCOMUrlStringFuncs) #ifdef FEATURE_COMINTEROP diff --git a/src/vm/eedbginterfaceimpl.cpp b/src/vm/eedbginterfaceimpl.cpp index 93decc9..ff63d84 100644 --- a/src/vm/eedbginterfaceimpl.cpp +++ b/src/vm/eedbginterfaceimpl.cpp @@ -501,9 +501,9 @@ BOOL EEDbgInterfaceImpl::IsInPrologOrEpilog(const BYTE *address, if (codeInfo.IsValid()) { - LPVOID methodInfo = codeInfo.GetGCInfo(); + GCInfoToken gcInfoToken = codeInfo.GetGCInfoToken(); - if (codeInfo.GetCodeManager()->IsInPrologOrEpilog(codeInfo.GetRelOffset(), methodInfo, prologSize)) + if (codeInfo.GetCodeManager()->IsInPrologOrEpilog(codeInfo.GetRelOffset(), gcInfoToken, prologSize)) { return TRUE; } diff --git a/src/vm/eepolicy.cpp b/src/vm/eepolicy.cpp index 8c3f2ec..236f5af 100644 --- a/src/vm/eepolicy.cpp +++ b/src/vm/eepolicy.cpp @@ -1368,7 +1368,7 @@ void DisplayStackOverflowException() LIMITED_METHOD_CONTRACT; PrintToStdErrA("\n"); - PrintToStdErrA("Process is terminated due to StackOverflowException.\n"); + PrintToStdErrA("Process is terminating due to StackOverflowException.\n"); } void DECLSPEC_NORETURN EEPolicy::HandleFatalStackOverflow(EXCEPTION_POINTERS *pExceptionInfo, BOOL fSkipDebugger) diff --git a/src/vm/eetoprofinterfaceimpl.cpp b/src/vm/eetoprofinterfaceimpl.cpp index 2ec3812..1ceed3d 100644 --- a/src/vm/eetoprofinterfaceimpl.cpp +++ b/src/vm/eetoprofinterfaceimpl.cpp @@ -414,6 +414,7 @@ EEToProfInterfaceImpl::EEToProfInterfaceImpl() : m_pCallback5(NULL), m_pCallback6(NULL), m_pCallback7(NULL), + m_pCallback8(NULL), m_hmodProfilerDLL(NULL), m_fLoadedViaAttach(FALSE), m_pProfToEE(NULL), @@ -664,21 +665,25 @@ HRESULT EEToProfInterfaceImpl::CreateProfiler( m_hmodProfilerDLL = hmodProfilerDLL.Extract(); hmodProfilerDLL = NULL; - // The profiler may optionally support ICorProfilerCallback3,4,5,6,7. Let's check. + // The profiler may optionally support ICorProfilerCallback3,4,5,6,7,8. Let's check. - ReleaseHolder pCallback7; + ReleaseHolder pCallback8; hr = m_pCallback2->QueryInterface( - IID_ICorProfilerCallback7, - (LPVOID *)&pCallback7); - if (SUCCEEDED(hr) && (pCallback7 != NULL)) + IID_ICorProfilerCallback8, + (LPVOID *)&pCallback8); + if (SUCCEEDED(hr) && (pCallback8 != NULL)) { // Nifty. Transfer ownership to this class - _ASSERTE(m_pCallback7 == NULL); - m_pCallback7 = pCallback7.Extract(); - pCallback7 = NULL; + _ASSERTE(m_pCallback8 == NULL); + m_pCallback8 = pCallback8.Extract(); + pCallback8 = NULL; - // And while we're at it, we must now also have an ICorProfilerCallback3,4,5,6 + // And while we're at it, we must now also have an ICorProfilerCallback3,4,5,6,7 // due to inheritance relationship of the interfaces + _ASSERTE(m_pCallback7 == NULL); + m_pCallback7 = static_cast(m_pCallback8); + m_pCallback7->AddRef(); + _ASSERTE(m_pCallback6 == NULL); m_pCallback6 = static_cast(m_pCallback7); m_pCallback6->AddRef(); @@ -696,6 +701,40 @@ HRESULT EEToProfInterfaceImpl::CreateProfiler( m_pCallback3->AddRef(); } + if (m_pCallback7 == NULL) + { + ReleaseHolder pCallback7; + hr = m_pCallback2->QueryInterface( + IID_ICorProfilerCallback7, + (LPVOID *)&pCallback7); + if (SUCCEEDED(hr) && (pCallback7 != NULL)) + { + // Nifty. Transfer ownership to this class + _ASSERTE(m_pCallback7 == NULL); + m_pCallback7 = pCallback7.Extract(); + pCallback7 = NULL; + + // And while we're at it, we must now also have an ICorProfilerCallback3,4,5,6 + // due to inheritance relationship of the interfaces + + _ASSERTE(m_pCallback6 == NULL); + m_pCallback6 = static_cast(m_pCallback7); + m_pCallback6->AddRef(); + + _ASSERTE(m_pCallback5 == NULL); + m_pCallback5 = static_cast(m_pCallback6); + m_pCallback5->AddRef(); + + _ASSERTE(m_pCallback4 == NULL); + m_pCallback4 = static_cast(m_pCallback5); + m_pCallback4->AddRef(); + + _ASSERTE(m_pCallback3 == NULL); + m_pCallback3 = static_cast(m_pCallback4); + m_pCallback3->AddRef(); + } + } + if (m_pCallback6 == NULL) { ReleaseHolder pCallback6; @@ -873,6 +912,13 @@ EEToProfInterfaceImpl::~EEToProfInterfaceImpl() m_pCallback7 = NULL; } + if (m_pCallback8 != NULL) + { + REMOVE_STACK_GUARD_FOR_PROFILER_CALL; + m_pCallback8->Release(); + m_pCallback8 = NULL; + } + // Only unload the V4 profiler if this is not part of shutdown. This protects // Whidbey profilers that aren't used to being FreeLibrary'd. if (fIsV4Profiler && !g_fEEShutDown) @@ -2294,7 +2340,7 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask // in this function if (g_profControlBlock.curProfStatus.Get() == kProfStatusInitializingForAttachLoad) { - if (GCHeap::GetGCHeap()->IsConcurrentGCEnabled()) + if (GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled()) { // We only allow turning off concurrent GC in the profiler attach thread inside // InitializeForAttach, otherwise we would be vulnerable to weird races such as @@ -2316,7 +2362,7 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask // Fail if concurrent GC is enabled // This should only happen for attach profilers if user didn't turn on COR_PRF_MONITOR_GC // at attach time - if (GCHeap::GetGCHeap()->IsConcurrentGCEnabled()) + if (GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled()) { return CORPROF_E_CONCURRENT_GC_NOT_PROFILABLE; } @@ -2384,7 +2430,7 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask if (fNeedToTurnOffConcurrentGC) { // Turn off concurrent GC if it is on so that user can walk the heap safely in GC callbacks - GCHeap * pGCHeap = GCHeap::GetGCHeap(); + IGCHeap * pGCHeap = GCHeapUtilities::GetGCHeap(); LOG((LF_CORPROF, LL_INFO10, "**PROF: Turning off concurrent GC at attach.\n")); @@ -3184,6 +3230,86 @@ HRESULT EEToProfInterfaceImpl::JITCompilationStarted(FunctionID functionId, } } +HRESULT EEToProfInterfaceImpl::DynamicMethodJITCompilationFinished(FunctionID functionId, + HRESULT hrStatus, + BOOL fIsSafeToBlock) +{ + CONTRACTL + { + NOTHROW; + GC_TRIGGERS; + MODE_PREEMPTIVE; + CAN_TAKE_LOCK; + + // The JIT / MethodDesc code likely hold locks while this callback is made + + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + CLR_TO_PROFILER_ENTRYPOINT((LF_CORPROF, + LL_INFO1000, + "**PROF: DynamicMethodJITCompilationFinished 0x%p.\n", + functionId)); + + _ASSERTE(functionId); + + if (m_pCallback8 == NULL) + { + return S_OK; + } + + { + // All callbacks are really NOTHROW, but that's enforced partially by the profiler, + // whose try/catch blocks aren't visible to the contract system + PERMANENT_CONTRACT_VIOLATION(ThrowsViolation, ReasonProfilerCallout); + return m_pCallback8->DynamicMethodJITCompilationFinished(functionId, hrStatus, fIsSafeToBlock); + } +} + +HRESULT EEToProfInterfaceImpl::DynamicMethodJITCompilationStarted(FunctionID functionId, + BOOL fIsSafeToBlock, + LPCBYTE pILHeader, + ULONG cbILHeader) +{ + CONTRACTL + { + NOTHROW; + GC_TRIGGERS; + MODE_PREEMPTIVE; + CAN_TAKE_LOCK; + + // The JIT / MethodDesc code likely hold locks while this callback is made + + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + CLR_TO_PROFILER_ENTRYPOINT((LF_CORPROF, + LL_INFO1000, + "**PROF: DynamicMethodJITCompilationStarted 0x%p.\n", + functionId)); + + _ASSERTE(functionId); + + // Currently DynamicMethodJITCompilationStarted is always called with fIsSafeToBlock==TRUE. If this ever changes, + // it's safe to remove this assert, but this should serve as a trigger to change our + // public documentation to state that this callback is no longer called in preemptive mode all the time. + _ASSERTE(fIsSafeToBlock); + + if (m_pCallback8 == NULL) + { + return S_OK; + } + + { + // All callbacks are really NOTHROW, but that's enforced partially by the profiler, + // whose try/catch blocks aren't visible to the contract system + PERMANENT_CONTRACT_VIOLATION(ThrowsViolation, ReasonProfilerCallout); + return m_pCallback8->DynamicMethodJITCompilationStarted(functionId, fIsSafeToBlock, pILHeader, cbILHeader); + } +} + HRESULT EEToProfInterfaceImpl::JITCachedFunctionSearchStarted( /* [in] */ FunctionID functionId, /* [out] */ BOOL *pbUseCachedFunction) @@ -5609,7 +5735,7 @@ HRESULT EEToProfInterfaceImpl::MovedReferences(GCReferencesData *pData) LL_INFO10000, "**PROF: MovedReferences.\n")); - _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled()); + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled()); if (pData->curIdx == 0) { @@ -5805,7 +5931,7 @@ HRESULT EEToProfInterfaceImpl::ObjectReference(ObjectID objId, LL_INFO100000, "**PROF: ObjectReferences.\n")); - _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled()); + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled()); { // All callbacks are really NOTHROW, but that's enforced partially by the profiler, @@ -5844,7 +5970,7 @@ HRESULT EEToProfInterfaceImpl::FinalizeableObjectQueued(BOOL isCritical, ObjectI LL_INFO100, "**PROF: Notifying profiler of finalizeable object.\n")); - _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled()); + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled()); { // All callbacks are really NOTHROW, but that's enforced partially by the profiler, @@ -5883,7 +6009,7 @@ HRESULT EEToProfInterfaceImpl::RootReferences2(GCReferencesData *pData) LL_INFO10000, "**PROF: RootReferences2.\n")); - _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled()); + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled()); HRESULT hr = S_OK; @@ -5948,7 +6074,7 @@ HRESULT EEToProfInterfaceImpl::ConditionalWeakTableElementReferences(GCReference LL_INFO10000, "**PROF: ConditionalWeakTableElementReferences.\n")); - _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled()); + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled()); HRESULT hr = S_OK; @@ -6082,7 +6208,7 @@ HRESULT EEToProfInterfaceImpl::GarbageCollectionStarted(int cGenerations, BOOL g LL_INFO10000, "**PROF: GarbageCollectionStarted.\n")); - _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled()); + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled()); { // All callbacks are really NOTHROW, but that's enforced partially by the profiler, @@ -6120,7 +6246,7 @@ HRESULT EEToProfInterfaceImpl::GarbageCollectionFinished() LL_INFO10000, "**PROF: GarbageCollectionFinished.\n")); - _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled()); + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled()); { // All callbacks are really NOTHROW, but that's enforced partially by the profiler, diff --git a/src/vm/eetoprofinterfaceimpl.h b/src/vm/eetoprofinterfaceimpl.h index 0390f94..76797fc 100644 --- a/src/vm/eetoprofinterfaceimpl.h +++ b/src/vm/eetoprofinterfaceimpl.h @@ -55,6 +55,7 @@ public: BOOL IsCallback5Supported(); BOOL IsCallback6Supported(); BOOL IsCallback7Supported(); + BOOL IsCallback8Supported(); HRESULT SetEventMask(DWORD dwEventMask, DWORD dwEventMaskHigh); @@ -169,6 +170,17 @@ public: HRESULT JITCompilationStarted( FunctionID functionId, BOOL fIsSafeToBlock); + + HRESULT DynamicMethodJITCompilationStarted( + FunctionID functionId, + BOOL fIsSafeToBlock, + LPCBYTE pILHeader, + ULONG cbILHeader); + + HRESULT DynamicMethodJITCompilationFinished( + FunctionID functionId, + HRESULT hrStatus, + BOOL fIsSafeToBlock); HRESULT JITCachedFunctionSearchStarted( /* [in] */ FunctionID functionId, @@ -529,13 +541,14 @@ private: // Pointer to the profiler's implementation of the callback interface(s). // Profilers MUST support ICorProfilerCallback2. - // Profilers MAY optionally support ICorProfilerCallback3,4,5,6,7 + // Profilers MAY optionally support ICorProfilerCallback3,4,5,6,7,8 ICorProfilerCallback2 * m_pCallback2; ICorProfilerCallback3 * m_pCallback3; ICorProfilerCallback4 * m_pCallback4; ICorProfilerCallback5 * m_pCallback5; ICorProfilerCallback6 * m_pCallback6; ICorProfilerCallback7 * m_pCallback7; + ICorProfilerCallback8 * m_pCallback8; HMODULE m_hmodProfilerDLL; BOOL m_fLoadedViaAttach; diff --git a/src/vm/eetoprofinterfaceimpl.inl b/src/vm/eetoprofinterfaceimpl.inl index 8a11118..feb81ed 100644 --- a/src/vm/eetoprofinterfaceimpl.inl +++ b/src/vm/eetoprofinterfaceimpl.inl @@ -65,6 +65,12 @@ inline BOOL EEToProfInterfaceImpl::IsCallback7Supported() return (m_pCallback7 != NULL); } +inline BOOL EEToProfInterfaceImpl::IsCallback8Supported() +{ + LIMITED_METHOD_CONTRACT; + return (m_pCallback8 != NULL); +} + inline FunctionIDMapper * EEToProfInterfaceImpl::GetFunctionIDMapper() { LIMITED_METHOD_CONTRACT; diff --git a/src/vm/eetwain.cpp b/src/vm/eetwain.cpp index 032bda7..2ce7b59 100644 --- a/src/vm/eetwain.cpp +++ b/src/vm/eetwain.cpp @@ -142,13 +142,15 @@ __forceinline int decodeSigned(PTR_CBYTE& src) /***************************************************************************** * - * Decodes the methodInfoPtr and returns the decoded information - * in the hdrInfo struct. The EIP parameter is the PC location - * within the active method. + * Decodes the X86 GcInfo header and returns the decoded information + * in the hdrInfo struct. + * curOffset is the code offset within the active method used in the + * computation of PrologOffs/EpilogOffs. + * Returns the size of the header (number of bytes decoded). */ -static size_t crackMethodInfoHdr(PTR_VOID methodInfoPtr, - unsigned curOffset, - hdrInfo * infoPtr) +static size_t DecodeGCHdrInfo(GCInfoToken gcInfoToken, + unsigned curOffset, + hdrInfo * infoPtr) { CONTRACTL { NOTHROW; @@ -157,7 +159,7 @@ static size_t crackMethodInfoHdr(PTR_VOID methodInfoPtr, SUPPORTS_DAC; } CONTRACTL_END; - PTR_CBYTE table = PTR_CBYTE(methodInfoPtr); + PTR_CBYTE table = (PTR_CBYTE) gcInfoToken.Info; #if VERIFY_GC_TABLES _ASSERTE(*castto(table, unsigned short *)++ == 0xFEEF); #endif @@ -170,7 +172,7 @@ static size_t crackMethodInfoHdr(PTR_VOID methodInfoPtr, /* Decode the InfoHdr */ InfoHdr header; - table = decodeHeader(table, &header); + table = decodeHeader(table, gcInfoToken.Version, &header); BOOL hasArgTabOffset = FALSE; if (header.untrackedCnt == HAS_UNTRACKED) @@ -199,6 +201,10 @@ static size_t crackMethodInfoHdr(PTR_VOID methodInfoPtr, _ASSERTE(header.syncStartOffset < header.syncEndOffset); } + if (header.revPInvokeOffset == HAS_REV_PINVOKE_FRAME_OFFSET) + { + header.revPInvokeOffset = fastDecodeUnsigned(table); + } /* Some sanity checks on header */ @@ -220,6 +226,7 @@ static size_t crackMethodInfoHdr(PTR_VOID methodInfoPtr, infoPtr->argSize = header.argCount * 4; infoPtr->ebpFrame = header.ebpFrame; infoPtr->interruptible = header.interruptible; + infoPtr->returnKind = (ReturnKind) header.returnKind; infoPtr->prologSize = header.prologSize; infoPtr->epilogSize = header.epilogSize; @@ -232,6 +239,7 @@ static size_t crackMethodInfoHdr(PTR_VOID methodInfoPtr, infoPtr->syncStartOffset = header.syncStartOffset; infoPtr->syncEndOffset = header.syncEndOffset; + infoPtr->revPInvokeOffset = header.revPInvokeOffset; infoPtr->doubleAlign = header.doubleAlign; infoPtr->securityCheck = header.security; @@ -352,7 +360,7 @@ static size_t crackMethodInfoHdr(PTR_VOID methodInfoPtr, (infoPtr->gsCookieOffset < infoPtr->stackSize) && ((header.gsCookieOffset % sizeof(void*)) == 0)); - return table - PTR_CBYTE(methodInfoPtr); + return table - PTR_CBYTE(gcInfoToken.Info); } /*****************************************************************************/ @@ -715,7 +723,7 @@ void EECodeManager::FixContext( ContextType ctxType, /* Extract the necessary information from the info block header */ - stateBuf->hdrInfoSize = (DWORD)crackMethodInfoHdr(pCodeInfo->GetGCInfo(), + stateBuf->hdrInfoSize = (DWORD)DecodeGCHdrInfo(pCodeInfo->GetGCInfoToken(), dwRelOffset, &stateBuf->hdrInfoBody); pState->dwIsSet = 1; @@ -836,11 +844,11 @@ HRESULT EECodeManager::FixContextForEnC(PCONTEXT pCtx, hdrInfo oldInfo, newInfo; - crackMethodInfoHdr(pOldCodeInfo->GetGCInfo(), + DecodeGCHdrInfo(pOldCodeInfo->GetGCInfoToken(), pOldCodeInfo->GetRelOffset(), &oldInfo); - crackMethodInfoHdr(pNewCodeInfo->GetGCInfo(), + DecodeGCHdrInfo(pNewCodeInfo->GetGCInfoToken(), pNewCodeInfo->GetRelOffset(), &newInfo); @@ -1545,7 +1553,7 @@ bool EECodeManager::IsGcSafe( EECodeInfo *pCodeInfo, /* Extract the necessary information from the info block header */ - table = (BYTE *)crackMethodInfoHdr(pCodeInfo->GetGCInfo(), + table = (BYTE *)DecodeGCHdrInfo(pCodeInfo->GetGCInfoToken(), dwRelOffset, &info); @@ -3905,8 +3913,9 @@ bool EECodeManager::UnwindStackFrame(PREGDISPLAY pContext, PTR_CBYTE methodStart = PTR_CBYTE(pCodeInfo->GetSavedMethodCode()); - PTR_VOID methodInfoPtr = pCodeInfo->GetGCInfo(); - DWORD curOffs = pCodeInfo->GetRelOffset(); + GCInfoToken gcInfoToken = pCodeInfo->GetGCInfoToken(); + PTR_VOID methodInfoPtr = gcInfoToken.Info; + DWORD curOffs = pCodeInfo->GetRelOffset(); _ASSERTE(sizeof(CodeManStateBuf) <= sizeof(pState->stateBuf)); CodeManStateBuf * stateBuf = (CodeManStateBuf*)pState->stateBuf; @@ -3915,7 +3924,7 @@ bool EECodeManager::UnwindStackFrame(PREGDISPLAY pContext, { /* Extract the necessary information from the info block header */ - stateBuf->hdrInfoSize = (DWORD)crackMethodInfoHdr(methodInfoPtr, + stateBuf->hdrInfoSize = (DWORD)DecodeGCHdrInfo(gcInfoToken, curOffs, &stateBuf->hdrInfoBody); } @@ -4097,7 +4106,7 @@ bool EECodeManager::EnumGcRefs( PREGDISPLAY pContext, GC_NOTRIGGER; } CONTRACTL_END; - PTR_VOID methodInfoPtr = pCodeInfo->GetGCInfo(); + GCInfoToken gcInfoToken = pCodeInfo->GetGCInfoToken(); unsigned curOffs = pCodeInfo->GetRelOffset(); unsigned EBP = *pContext->pEbp; @@ -4108,7 +4117,7 @@ bool EECodeManager::EnumGcRefs( PREGDISPLAY pContext, unsigned count; hdrInfo info; - PTR_CBYTE table = PTR_CBYTE(methodInfoPtr); + PTR_CBYTE table = PTR_CBYTE(gcInfoToken.Info); #if 0 printf("EECodeManager::EnumGcRefs - EIP = %08x ESP = %08x offset = %x GC Info is at %08x\n", *pContext->pPC, ESP, curOffs, table); #endif @@ -4116,14 +4125,14 @@ bool EECodeManager::EnumGcRefs( PREGDISPLAY pContext, /* Extract the necessary information from the info block header */ - table += crackMethodInfoHdr(methodInfoPtr, - curOffs, - &info); + table += DecodeGCHdrInfo(gcInfoToken, + curOffs, + &info); _ASSERTE( curOffs <= info.methodSize); #ifdef _DEBUG -// if ((methodInfoPtr == (void*)0x37760d0) && (curOffs == 0x264)) +// if ((gcInfoToken.Info == (void*)0x37760d0) && (curOffs == 0x264)) // __asm int 3; if (trEnumGCRefs) { @@ -4220,11 +4229,11 @@ bool EECodeManager::EnumGcRefs( PREGDISPLAY pContext, /* Extract the necessary information from the info block header */ - table = PTR_CBYTE(methodInfoPtr); + table = PTR_CBYTE(gcInfoToken.Info); - table += crackMethodInfoHdr(methodInfoPtr, - curOffs, - &info); + table += DecodeGCHdrInfo(gcInfoToken, + curOffs, + &info); } } @@ -5030,9 +5039,9 @@ OBJECTREF* EECodeManager::GetAddrOfSecurityObject(CrawlFrame *pCF) CodeManStateBuf * stateBuf = (CodeManStateBuf*)pState->stateBuf; /* Extract the necessary information from the info block header */ - stateBuf->hdrInfoSize = (DWORD)crackMethodInfoHdr(gcInfoToken.Info, // truncation - relOffset, - &stateBuf->hdrInfoBody); + stateBuf->hdrInfoSize = (DWORD)DecodeGCHdrInfo(gcInfoToken, // truncation + relOffset, + &stateBuf->hdrInfoBody); pState->dwIsSet = 1; if (stateBuf->hdrInfoBody.securityCheck) @@ -5109,10 +5118,10 @@ OBJECTREF EECodeManager::GetInstance( PREGDISPLAY pContext, } CONTRACTL_END; #ifdef _TARGET_X86_ - PTR_VOID methodInfoPtr = pCodeInfo->GetGCInfo(); - unsigned relOffset = pCodeInfo->GetRelOffset(); + GCInfoToken gcInfoToken = pCodeInfo->GetGCInfoToken(); + unsigned relOffset = pCodeInfo->GetRelOffset(); - PTR_CBYTE table = PTR_CBYTE(methodInfoPtr); + PTR_CBYTE table = PTR_CBYTE(gcInfoToken.Info); hdrInfo info; unsigned stackDepth; TADDR taArgBase; @@ -5120,9 +5129,9 @@ OBJECTREF EECodeManager::GetInstance( PREGDISPLAY pContext, /* Extract the necessary information from the info block header */ - table += crackMethodInfoHdr(methodInfoPtr, - relOffset, - &info); + table += DecodeGCHdrInfo(gcInfoToken, + relOffset, + &info); // We do not have accurate information in the prolog or the epilog if (info.prologOffs != hdrInfo::NOT_IN_PROLOG || @@ -5236,14 +5245,15 @@ GenericParamContextType EECodeManager::GetParamContextType(PREGDISPLAY pCont #ifdef _TARGET_X86_ /* Extract the necessary information from the info block header */ - PTR_VOID methodInfoPtr = pCodeInfo->GetGCInfo(); - unsigned relOffset = pCodeInfo->GetRelOffset(); + GCInfoToken gcInfoToken = pCodeInfo->GetGCInfoToken(); + PTR_VOID methodInfoPtr = pCodeInfo->GetGCInfo(); + unsigned relOffset = pCodeInfo->GetRelOffset(); hdrInfo info; - PTR_CBYTE table = PTR_CBYTE(methodInfoPtr); - table += crackMethodInfoHdr(methodInfoPtr, - relOffset, - &info); + PTR_CBYTE table = PTR_CBYTE(gcInfoToken.Info); + table += DecodeGCHdrInfo(gcInfoToken, + relOffset, + &info); if (!info.genericsContext || info.prologOffs != hdrInfo::NOT_IN_PROLOG || @@ -5300,15 +5310,16 @@ PTR_VOID EECodeManager::GetParamTypeArg(PREGDISPLAY pContext, LIMITED_METHOD_DAC_CONTRACT; #ifdef _TARGET_X86_ - PTR_VOID methodInfoPtr = pCodeInfo->GetGCInfo(); - unsigned relOffset = pCodeInfo->GetRelOffset(); + GCInfoToken gcInfoToken = pCodeInfo->GetGCInfoToken(); + PTR_VOID methodInfoPtr = pCodeInfo->GetGCInfo(); + unsigned relOffset = pCodeInfo->GetRelOffset(); /* Extract the necessary information from the info block header */ hdrInfo info; - PTR_CBYTE table = PTR_CBYTE(methodInfoPtr); - table += crackMethodInfoHdr(methodInfoPtr, - relOffset, - &info); + PTR_CBYTE table = PTR_CBYTE(gcInfoToken.Info); + table += DecodeGCHdrInfo(gcInfoToken, + relOffset, + &info); if (!info.genericsContext || info.prologOffs != hdrInfo::NOT_IN_PROLOG || @@ -5424,9 +5435,9 @@ void * EECodeManager::GetGSCookieAddr(PREGDISPLAY pContext, /* Extract the necessary information from the info block header */ hdrInfo * info = &stateBuf->hdrInfoBody; - stateBuf->hdrInfoSize = (DWORD)crackMethodInfoHdr(gcInfoToken.Info, // truncation - relOffset, - info); + stateBuf->hdrInfoSize = (DWORD)DecodeGCHdrInfo(gcInfoToken, // truncation + relOffset, + info); pState->dwIsSet = 1; @@ -5482,9 +5493,9 @@ void * EECodeManager::GetGSCookieAddr(PREGDISPLAY pContext, * * Returns true if the given IP is in the given method's prolog or epilog. */ -bool EECodeManager::IsInPrologOrEpilog(DWORD relPCoffset, - PTR_VOID methodInfoPtr, - size_t* prologSize) +bool EECodeManager::IsInPrologOrEpilog(DWORD relPCoffset, + GCInfoToken gcInfoToken, + size_t* prologSize) { CONTRACTL { NOTHROW; @@ -5494,7 +5505,7 @@ bool EECodeManager::IsInPrologOrEpilog(DWORD relPCoffset, #ifndef USE_GC_INFO_DECODER hdrInfo info; - crackMethodInfoHdr(methodInfoPtr, relPCoffset, &info); + DecodeGCHdrInfo(gcInfoToken, relPCoffset, &info); if (prologSize) *prologSize = info.prologSize; @@ -5511,10 +5522,9 @@ bool EECodeManager::IsInPrologOrEpilog(DWORD relPCoffset, * * Returns true if the given IP is in the synchronized region of the method (valid for synchronized functions only) */ -bool EECodeManager::IsInSynchronizedRegion( - DWORD relOffset, - PTR_VOID methodInfoPtr, - unsigned flags) +bool EECodeManager::IsInSynchronizedRegion(DWORD relOffset, + GCInfoToken gcInfoToken, + unsigned flags) { CONTRACTL { NOTHROW; @@ -5524,7 +5534,7 @@ bool EECodeManager::IsInSynchronizedRegion( #ifndef USE_GC_INFO_DECODER hdrInfo info; - crackMethodInfoHdr(methodInfoPtr, relOffset, &info); + DecodeGCHdrInfo(gcInfoToken, relOffset, &info); // We should be called only for synchronized methods _ASSERTE(info.syncStartOffset != INVALID_SYNC_OFFSET && info.syncEndOffset != INVALID_SYNC_OFFSET); @@ -5558,9 +5568,8 @@ size_t EECodeManager::GetFunctionSize(GCInfoToken gcInfoToken) #if defined(_TARGET_X86_) hdrInfo info; - PTR_VOID methodInfoPtr = gcInfoToken.Info; - crackMethodInfoHdr(methodInfoPtr, 0, &info); + DecodeGCHdrInfo(gcInfoToken, 0, &info); return info.methodSize; #elif defined(USE_GC_INFO_DECODER) @@ -5578,15 +5587,47 @@ size_t EECodeManager::GetFunctionSize(GCInfoToken gcInfoToken) PORTABILITY_ASSERT("EECodeManager::GetFunctionSize is not implemented on this platform."); return 0; #endif +} +/***************************************************************************** +* +* Returns the size of a given function. +*/ +ReturnKind EECodeManager::GetReturnKind(GCInfoToken gcInfoToken) +{ + CONTRACTL{ + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + } CONTRACTL_END; + if (!gcInfoToken.IsReturnKindAvailable()) + { + return RT_Illegal; + } + +#if defined(_TARGET_X86_) + hdrInfo info; + + DecodeGCHdrInfo(gcInfoToken, 0, &info); + + return info.returnKind; +#elif defined(USE_GC_INFO_DECODER) + + GcInfoDecoder gcInfoDecoder(gcInfoToken, DECODE_RETURN_KIND); + return gcInfoDecoder.GetReturnKind(); + +#else // !_TARGET_X86_ && !USE_GC_INFO_DECODER + PORTABILITY_ASSERT("EECodeManager::GetReturnKind is not implemented on this platform."); + return 0; +#endif } /***************************************************************************** * * Returns the size of the frame of the given function. */ -unsigned int EECodeManager::GetFrameSize(PTR_VOID methodInfoPtr) +unsigned int EECodeManager::GetFrameSize(GCInfoToken gcInfoToken) { CONTRACTL { NOTHROW; @@ -5596,7 +5637,7 @@ unsigned int EECodeManager::GetFrameSize(PTR_VOID methodInfoPtr) #ifndef USE_GC_INFO_DECODER hdrInfo info; - crackMethodInfoHdr(methodInfoPtr, 0, &info); + DecodeGCHdrInfo(gcInfoToken, 0, &info); // currently only used by E&C callers need to know about doubleAlign // in all likelyhood @@ -5624,10 +5665,10 @@ const BYTE* EECodeManager::GetFinallyReturnAddr(PREGDISPLAY pReg) #endif } -BOOL EECodeManager::IsInFilter(void *methodInfoPtr, - unsigned offset, - PCONTEXT pCtx, - DWORD curNestLevel) +BOOL EECodeManager::IsInFilter(GCInfoToken gcInfoToken, + unsigned offset, + PCONTEXT pCtx, + DWORD curNestLevel) { CONTRACTL { NOTHROW; @@ -5640,9 +5681,9 @@ BOOL EECodeManager::IsInFilter(void *methodInfoPtr, hdrInfo info; - crackMethodInfoHdr(methodInfoPtr, - offset, - &info); + DecodeGCHdrInfo(gcInfoToken, + offset, + &info); /* make sure that we have an ebp stack frame */ @@ -5668,7 +5709,7 @@ BOOL EECodeManager::IsInFilter(void *methodInfoPtr, } -BOOL EECodeManager::LeaveFinally(void *methodInfoPtr, +BOOL EECodeManager::LeaveFinally(GCInfoToken gcInfoToken, unsigned offset, PCONTEXT pCtx) { @@ -5681,9 +5722,9 @@ BOOL EECodeManager::LeaveFinally(void *methodInfoPtr, hdrInfo info; - crackMethodInfoHdr(methodInfoPtr, - offset, - &info); + DecodeGCHdrInfo(gcInfoToken, + offset, + &info); DWORD nestingLevel; GetHandlerFrameInfo(&info, pCtx->Ebp, pCtx->Esp, (DWORD) IGNORE_VAL, NULL, &nestingLevel); @@ -5707,7 +5748,7 @@ BOOL EECodeManager::LeaveFinally(void *methodInfoPtr, #endif } -void EECodeManager::LeaveCatch(void *methodInfoPtr, +void EECodeManager::LeaveCatch(GCInfoToken gcInfoToken, unsigned offset, PCONTEXT pCtx) { @@ -5724,7 +5765,7 @@ void EECodeManager::LeaveCatch(void *methodInfoPtr, bool hasInnerFilter; hdrInfo info; - crackMethodInfoHdr(methodInfoPtr, offset, &info); + DecodeGCHdrInfo(gcInfoToken, offset, &info); GetHandlerFrameInfo(&info, pCtx->Ebp, pCtx->Esp, (DWORD) IGNORE_VAL, &baseSP, &nestingLevel, &hasInnerFilter); // _ASSERTE(frameType == FR_HANDLER); @@ -5774,17 +5815,17 @@ TADDR EECodeManager::GetAmbientSP(PREGDISPLAY pContext, } CONTRACTL_END; #ifdef _TARGET_X86_ - PTR_VOID methodInfoPtr = pCodeInfo->GetGCInfo(); + GCInfoToken gcInfoToken = pCodeInfo->GetGCInfoToken(); _ASSERTE(sizeof(CodeManStateBuf) <= sizeof(pState->stateBuf)); CodeManStateBuf * stateBuf = (CodeManStateBuf*)pState->stateBuf; - PTR_CBYTE table = PTR_CBYTE(methodInfoPtr); + PTR_CBYTE table = PTR_CBYTE(gcInfoToken.Info); /* Extract the necessary information from the info block header */ - stateBuf->hdrInfoSize = (DWORD)crackMethodInfoHdr(methodInfoPtr, - dwRelOffset, - &stateBuf->hdrInfoBody); + stateBuf->hdrInfoSize = (DWORD)DecodeGCHdrInfo(gcInfoToken, + dwRelOffset, + &stateBuf->hdrInfoBody); table += stateBuf->hdrInfoSize; pState->dwIsSet = 1; @@ -5868,8 +5909,8 @@ ULONG32 EECodeManager::GetStackParameterSize(EECodeInfo * pCodeInfo) } CONTRACTL_END; #if defined(_TARGET_X86_) - PTR_VOID methodInfoPtr = pCodeInfo->GetGCInfo(); - unsigned dwOffset = pCodeInfo->GetRelOffset(); + GCInfoToken gcInfoToken = pCodeInfo->GetGCInfoToken(); + unsigned dwOffset = pCodeInfo->GetRelOffset(); CodeManState state; state.dwIsSet = 0; @@ -5878,7 +5919,7 @@ ULONG32 EECodeManager::GetStackParameterSize(EECodeInfo * pCodeInfo) CodeManStateBuf * pStateBuf = reinterpret_cast(state.stateBuf); hdrInfo * pHdrInfo = &(pStateBuf->hdrInfoBody); - pStateBuf->hdrInfoSize = (DWORD)crackMethodInfoHdr(methodInfoPtr, dwOffset, pHdrInfo); + pStateBuf->hdrInfoSize = (DWORD)DecodeGCHdrInfo(gcInfoToken, dwOffset, pHdrInfo); // We need to subtract 4 here because ESPIncrOnReturn() includes the stack slot containing the return // address. diff --git a/src/vm/encee.cpp b/src/vm/encee.cpp index ca4e7fe..7f12643 100644 --- a/src/vm/encee.cpp +++ b/src/vm/encee.cpp @@ -149,7 +149,11 @@ HRESULT EditAndContinueModule::ApplyEditAndContinue( HRESULT hr = S_OK; HENUMInternal enumENC; - + + BYTE *pLocalILMemory = NULL; + IMDInternalImport *pMDImport = NULL; + IMDInternalImport *pNewMDImport = NULL; + CONTRACT_VIOLATION(GCViolation); // SafeComHolder goes to preemptive mode, which will trigger a GC SafeComHolder pIMDInternalImportENC; SafeComHolder pEmitter; @@ -175,8 +179,7 @@ HRESULT EditAndContinueModule::ApplyEditAndContinue( IfFailGo(hr); // Grab the current importer. - IMDInternalImport *pMDImport = GetMDImport(); - IMDInternalImport *pNewMDImport; + pMDImport = GetMDImport(); // Apply the EnC delta to this module's metadata. IfFailGo(pMDImport->ApplyEditAndContinue(pDeltaMD, cbDeltaMD, &pNewMDImport)); @@ -195,7 +198,7 @@ HRESULT EditAndContinueModule::ApplyEditAndContinue( IfFailGo(GetMetaDataPublicInterfaceFromInternal(pMDImport, IID_IMetaDataEmit, (void **)&pEmitter)); // Copy the deltaIL into our RVAable IL memory - BYTE *pLocalILMemory = new BYTE[cbDeltaIL]; + pLocalILMemory = new BYTE[cbDeltaIL]; memcpy(pLocalILMemory, pDeltaIL, cbDeltaIL); // Enumerate all of the EnC delta tokens @@ -203,7 +206,6 @@ HRESULT EditAndContinueModule::ApplyEditAndContinue( IfFailGo(pIMDInternalImportENC->EnumDeltaTokensInit(&enumENC)); mdToken token; - FieldDesc * pField = NULL; while (pIMDInternalImportENC->EnumNext(&enumENC, &token)) { STRESS_LOG3(LF_ENC, LL_INFO100, "EACM::AEAC: updated token 0x%x; type 0x%x; rid 0x%x\n", token, TypeFromToken(token), RidFromToken(token)); @@ -248,8 +250,7 @@ HRESULT EditAndContinueModule::ApplyEditAndContinue( // FieldDef token - add a new field LOG((LF_ENC, LL_INFO10000, "EACM::AEAC: Found field 0x%x\n", token)); - pField = LookupFieldDef(token); - if (pField) + if (LookupFieldDef(token)) { // Field already exists - just ignore for now continue; diff --git a/src/vm/eventtrace.cpp b/src/vm/eventtrace.cpp index d8702a5..cec7921 100644 --- a/src/vm/eventtrace.cpp +++ b/src/vm/eventtrace.cpp @@ -431,19 +431,19 @@ ETW::SamplingLog::EtwStackWalkStatus ETW::SamplingLog::SaveCurrentStack(int skip VOID ETW::GCLog::GCSettingsEvent() { - if (GCHeap::IsGCHeapInitialized()) + if (GCHeapUtilities::IsGCHeapInitialized()) { if (ETW_TRACING_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, GCSettings)) { ETW::GCLog::ETW_GC_INFO Info; - Info.GCSettings.ServerGC = GCHeap::IsServerHeap (); - Info.GCSettings.SegmentSize = GCHeap::GetGCHeap()->GetValidSegmentSize (FALSE); - Info.GCSettings.LargeObjectSegmentSize = GCHeap::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()); } - GCHeap::GetGCHeap()->TraceGCSegments(); + GCHeapUtilities::GetGCHeap()->DiagTraceGCSegments(); } }; @@ -892,7 +892,7 @@ VOID ETW::GCLog::FireGcStartAndGenerationRanges(ETW_GC_INFO * pGcInfo) // GCStart, then retrieve it LONGLONG l64ClientSequenceNumberToLog = 0; if ((s_l64LastClientSequenceNumber != 0) && - (pGcInfo->GCStart.Depth == GCHeap::GetMaxGeneration()) && + (pGcInfo->GCStart.Depth == GCHeapUtilities::GetGCHeap()->GetMaxGeneration()) && (pGcInfo->GCStart.Reason == ETW_GC_INFO::GC_INDUCED)) { l64ClientSequenceNumberToLog = InterlockedExchange64(&s_l64LastClientSequenceNumber, 0); @@ -901,8 +901,8 @@ VOID ETW::GCLog::FireGcStartAndGenerationRanges(ETW_GC_INFO * pGcInfo) FireEtwGCStart_V2(pGcInfo->GCStart.Count, pGcInfo->GCStart.Depth, pGcInfo->GCStart.Reason, pGcInfo->GCStart.Type, GetClrInstanceId(), l64ClientSequenceNumberToLog); // Fire an event per range per generation - GCHeap *hp = GCHeap::GetGCHeap(); - hp->DescrGenerationsToProfiler(FireSingleGenerationRangeEvent, NULL /* context */); + IGCHeap *hp = GCHeapUtilities::GetGCHeap(); + hp->DiagDescrGenerations(FireSingleGenerationRangeEvent, NULL /* context */); } } @@ -928,8 +928,8 @@ VOID ETW::GCLog::FireGcEndAndGenerationRanges(ULONG Count, ULONG Depth) CLR_GC_KEYWORD)) { // Fire an event per range per generation - GCHeap *hp = GCHeap::GetGCHeap(); - hp->DescrGenerationsToProfiler(FireSingleGenerationRangeEvent, NULL /* context */); + IGCHeap *hp = GCHeapUtilities::GetGCHeap(); + hp->DiagDescrGenerations(FireSingleGenerationRangeEvent, NULL /* context */); // GCEnd FireEtwGCEnd_V1(Count, Depth, GetClrInstanceId()); @@ -938,7 +938,7 @@ VOID ETW::GCLog::FireGcEndAndGenerationRanges(ULONG Count, ULONG Depth) //--------------------------------------------------------------------------------------- // -// Callback made by GC when we call GCHeap::DescrGenerationsToProfiler(). This is +// Callback made by GC when we call GCHeapUtilities::DiagDescrGenerations(). This is // called once per range per generation, and results in a single ETW event per range per // generation. // @@ -1033,7 +1033,7 @@ HRESULT ETW::GCLog::ForceGCForDiagnostics() ForcedGCHolder forcedGCHolder; - hr = GCHeap::GetGCHeap()->GarbageCollect( + hr = GCHeapUtilities::GetGCHeap()->GarbageCollect( -1, // all generations should be collected FALSE, // low_memory_p collection_blocking); @@ -4468,6 +4468,12 @@ extern "C" BOOLEAN bIsRundownTraceHandle = (context->RegistrationHandle==Microsoft_Windows_DotNETRuntimeRundownHandle); + // TypeSystemLog needs a notification when certain keywords are modified, so + // give it a hook here. + if (g_fEEStarted && !g_fEEShutDown && bIsPublicTraceHandle) + { + ETW::TypeSystemLog::OnKeywordsChanged(); + } // A manifest based provider can be enabled to multiple event tracing sessions // As long as there is atleast 1 enabled session, IsEnabled will be TRUE @@ -4478,13 +4484,6 @@ extern "C" (ControlCode == EVENT_CONTROL_CODE_CAPTURE_STATE)); if(bEnabled) { - // TypeSystemLog needs a notification when certain keywords are modified, so - // give it a hook here. - if (g_fEEStarted && !g_fEEShutDown && bIsPublicTraceHandle) - { - ETW::TypeSystemLog::OnKeywordsChanged(); - } - if (bIsPrivateTraceHandle) { ETW::GCLog::GCSettingsEvent(); diff --git a/src/vm/eventtracepriv.h b/src/vm/eventtracepriv.h index 0932225..7aca509 100644 --- a/src/vm/eventtracepriv.h +++ b/src/vm/eventtracepriv.h @@ -23,7 +23,10 @@ #define _countof(_array) (sizeof(_array)/sizeof(_array[0])) #endif -const UINT cbMaxEtwEvent = 64 * 1024; +// ETW has a limitation of 64K for TOTAL event Size, however there is overhead associated with +// the event headers. It is unclear exactly how much that is, but 1K should be sufficiently +// far away to avoid problems without sacrificing the perf of bulk processing. +const UINT cbMaxEtwEvent = 63 * 1024; //--------------------------------------------------------------------------------------- // C++ copies of ETW structures diff --git a/src/vm/excep.cpp b/src/vm/excep.cpp index 672f315..5a6f7c6 100644 --- a/src/vm/excep.cpp +++ b/src/vm/excep.cpp @@ -20,7 +20,7 @@ #include "cgensys.h" #include "comutilnative.h" #include "siginfo.hpp" -#include "gc.h" +#include "gcheaputilities.h" #include "eedbginterfaceimpl.h" //so we can clearexception in RealCOMPlusThrow #include "perfcounters.h" #include "dllimportcallback.h" @@ -1679,7 +1679,7 @@ bool FinallyIsUnwinding(EHRangeTreeNode *pNode, BOOL LeaveCatch(ICodeManager* pEECM, Thread *pThread, CONTEXT *pCtx, - void *methodInfoPtr, + GCInfoToken gcInfoToken, unsigned offset) { CONTRACTL @@ -1690,6 +1690,7 @@ BOOL LeaveCatch(ICodeManager* pEECM, } CONTRACTL_END; +#ifndef FEATURE_PAL // We can assert these things here, and skip a call // to COMPlusCheckForAbort later. @@ -1703,10 +1704,14 @@ BOOL LeaveCatch(ICodeManager* pEECM, PopNestedExceptionRecords(esp, pCtx, pThread->GetExceptionListPtr()); // Do JIT-specific work - pEECM->LeaveCatch(methodInfoPtr, offset, pCtx); + pEECM->LeaveCatch(gcInfoToken, offset, pCtx); SetSP(pCtx, (UINT_PTR)esp); return TRUE; +#else // FEATURE_PAL + PORTABILITY_ASSERT("LeaveCatch"); + return FALSE; +#endif } #endif // WIN64EXCEPTIONS @@ -1762,7 +1767,7 @@ HRESULT IsLegalTransition(Thread *pThread, ICodeManager* pEECM, PREGDISPLAY pReg, SLOT addrStart, - void *methodInfoPtr, + GCInfoToken gcInfoToken, PCONTEXT pCtx) { CONTRACTL @@ -1875,7 +1880,7 @@ HRESULT IsLegalTransition(Thread *pThread, if (!LeaveCatch(pEECM, pThread, pFilterCtx, - methodInfoPtr, + gcInfoToken, offFrom)) return E_FAIL; } @@ -1930,7 +1935,7 @@ HRESULT IsLegalTransition(Thread *pThread, if (!fCanSetIPOnly) { - if (!pEECM->LeaveFinally(methodInfoPtr, + if (!pEECM->LeaveFinally(gcInfoToken, offFrom, pFilterCtx)) return E_FAIL; @@ -2041,7 +2046,7 @@ HRESULT SetIPFromSrcToDst(Thread *pThread, EECodeInfo codeInfo((TADDR)(addrStart)); ICodeManager * pEECM = codeInfo.GetCodeManager(); - LPVOID methodInfoPtr = codeInfo.GetGCInfo(); + GCInfoToken gcInfoToken = codeInfo.GetGCInfoToken(); // Do both checks here so compiler doesn't complain about skipping // initialization b/c of goto. @@ -2097,7 +2102,7 @@ retryForCommit: pEECM, pReg, addrStart, - methodInfoPtr, + gcInfoToken, pCtx); if (FAILED(hr)) @@ -2120,7 +2125,7 @@ retryForCommit: pEECM, pReg, addrStart, - methodInfoPtr, + gcInfoToken, pCtx); if (FAILED(hr)) @@ -2143,7 +2148,7 @@ retryForCommit: pEECM, pReg, addrStart, - methodInfoPtr, + gcInfoToken, pCtx); if (FAILED(hr)) @@ -7313,8 +7318,8 @@ AdjustContextForWriteBarrier( void* f_IP = (void *)GetIP(pContext); - if (f_IP >= (void *) JIT_WriteBarrierStart && f_IP <= (void *) JIT_WriteBarrierLast || - f_IP >= (void *) JIT_PatchedWriteBarrierStart && f_IP <= (void *) JIT_PatchedWriteBarrierLast) + if (((f_IP >= (void *) JIT_WriteBarrierStart) && (f_IP <= (void *) JIT_WriteBarrierLast)) || + ((f_IP >= (void *) JIT_PatchedWriteBarrierStart) && (f_IP <= (void *) JIT_PatchedWriteBarrierLast))) { // set the exception IP to be the instruction that called the write barrier void* callsite = (void *)GetAdjustedCallAddress(*dac_cast(GetSP(pContext))); @@ -9916,47 +9921,48 @@ PTR_EHWatsonBucketTracker GetWatsonBucketTrackerForPreallocatedException(OBJECTR goto doValidation; } - // Find the reference to the exception tracker corresponding to the preallocated exception, - // starting the search from the current exception tracker (2nd arg of NULL specifies that). -#if defined(WIN64EXCEPTIONS) - PTR_ExceptionTracker pEHTracker = NULL; - PTR_ExceptionTracker pPreviousEHTracker = NULL; + { + // Find the reference to the exception tracker corresponding to the preallocated exception, + // starting the search from the current exception tracker (2nd arg of NULL specifies that). + #if defined(WIN64EXCEPTIONS) + PTR_ExceptionTracker pEHTracker = NULL; + PTR_ExceptionTracker pPreviousEHTracker = NULL; #elif _TARGET_X86_ - PTR_ExInfo pEHTracker = NULL; - PTR_ExInfo pPreviousEHTracker = NULL; + PTR_ExInfo pEHTracker = NULL; + PTR_ExInfo pPreviousEHTracker = NULL; #else // !(_WIN64 || _TARGET_X86_) #error Unsupported platform #endif // _WIN64 - if (fStartSearchFromPreviousTracker) - { - // Get the exception tracker previous to the current one - pPreviousEHTracker = GetThread()->GetExceptionState()->GetCurrentExceptionTracker()->GetPreviousExceptionTracker(); + if (fStartSearchFromPreviousTracker) + { + // Get the exception tracker previous to the current one + pPreviousEHTracker = GetThread()->GetExceptionState()->GetCurrentExceptionTracker()->GetPreviousExceptionTracker(); + + // If there is no previous tracker to start from, then simply abort the search attempt. + // If we couldnt find the exception tracker, then buckets are not available + if (pPreviousEHTracker == NULL) + { + LOG((LF_EH, LL_INFO100, "GetWatsonBucketTrackerForPreallocatedException - Couldnt find the previous EHTracker to start the search from.\n")); + pWBTracker = NULL; + goto done; + } + } + + pEHTracker = GetEHTrackerForPreallocatedException(gc.oPreAllocThrowable, pPreviousEHTracker); - // If there is no previous tracker to start from, then simply abort the search attempt. // If we couldnt find the exception tracker, then buckets are not available - if (pPreviousEHTracker == NULL) + if (pEHTracker == NULL) { - LOG((LF_EH, LL_INFO100, "GetWatsonBucketTrackerForPreallocatedException - Couldnt find the previous EHTracker to start the search from.\n")); + LOG((LF_EH, LL_INFO100, "GetWatsonBucketTrackerForPreallocatedException - Couldnt find EHTracker for preallocated exception object.\n")); pWBTracker = NULL; goto done; } - } - pEHTracker = GetEHTrackerForPreallocatedException(gc.oPreAllocThrowable, pPreviousEHTracker); - - // If we couldnt find the exception tracker, then buckets are not available - if (pEHTracker == NULL) - { - LOG((LF_EH, LL_INFO100, "GetWatsonBucketTrackerForPreallocatedException - Couldnt find EHTracker for preallocated exception object.\n")); - pWBTracker = NULL; - goto done; + // Get the Watson Bucket Tracker from the exception tracker + pWBTracker = pEHTracker->GetWatsonBucketTracker(); } - - // Get the Watson Bucket Tracker from the exception tracker - pWBTracker = pEHTracker->GetWatsonBucketTracker(); - doValidation: _ASSERTE(pWBTracker != NULL); @@ -12196,7 +12202,7 @@ done: // CE can be caught in the VM and later reraised again. Examples of such scenarios // include AD transition, COM interop, Reflection invocation, to name a few. // In such cases, we want to mark the corruption severity for reuse upon reraise, -// implying that when the VM does a reraise of such a exception, we should use +// implying that when the VM does a reraise of such an exception, we should use // the original corruption severity for the new raised exception, instead of creating // a new one for it. /* static */ @@ -12913,15 +12919,6 @@ void ExceptionNotifications::DeliverNotificationInternal(ExceptionNotificationHa AppDomain *pCurDomain = GetAppDomain(); _ASSERTE(pCurDomain != NULL); -#ifdef FEATURE_CORECLR - if (true) - { - // On CoreCLR, we dont support enhanced exception notifications - _ASSERTE(!"CoreCLR does not support enhanced exception notifications!"); - return; - } -#endif // FEATURE_CORECLR - struct { OBJECTREF oNotificationDelegate; diff --git a/src/vm/excep.h b/src/vm/excep.h index 527e3a1..7ef1921 100644 --- a/src/vm/excep.h +++ b/src/vm/excep.h @@ -88,9 +88,11 @@ struct ThrowCallbackType MethodDesc * pProfilerNotify; // Context for profiler callbacks -- see COMPlusFrameHandler(). BOOL bReplaceStack; // Used to pass info to SaveStackTrace call BOOL bSkipLastElement;// Used to pass info to SaveStackTrace call +#ifndef FEATURE_PAL HANDLE hCallerToken; HANDLE hImpersonationToken; BOOL bImpersonationTokenSet; +#endif // !FEATURE_PAL #ifdef _DEBUG void * pCurrentExceptionRecord; void * pPrevExceptionRecord; @@ -114,9 +116,11 @@ struct ThrowCallbackType pProfilerNotify = NULL; bReplaceStack = FALSE; bSkipLastElement = FALSE; +#ifndef FEATURE_PAL hCallerToken = NULL; hImpersonationToken = NULL; bImpersonationTokenSet = FALSE; +#endif // !FEATURE_PAL #ifdef _DEBUG pCurrentExceptionRecord = 0; @@ -422,10 +426,11 @@ VOID DECLSPEC_NORETURN RealCOMPlusThrowInvalidCastException(TypeHandle thCastFro VOID DECLSPEC_NORETURN RealCOMPlusThrowInvalidCastException(OBJECTREF *pObj, TypeHandle thCastTo); +#ifdef _TARGET_X86_ + #include "eexcp.h" #include "exinfo.h" -#ifdef _TARGET_X86_ struct FrameHandlerExRecord { EXCEPTION_REGISTRATION_RECORD m_ExReg; diff --git a/src/vm/exceptionhandling.cpp b/src/vm/exceptionhandling.cpp index e59f10e..ed155eb 100644 --- a/src/vm/exceptionhandling.cpp +++ b/src/vm/exceptionhandling.cpp @@ -4730,7 +4730,7 @@ VOID DECLSPEC_NORETURN DispatchManagedException(PAL_SEHException& ex, bool isHar } } - throw ex; + throw std::move(ex); } #ifdef _AMD64_ diff --git a/src/vm/exceptmacros.h b/src/vm/exceptmacros.h index efed993..2af064c 100644 --- a/src/vm/exceptmacros.h +++ b/src/vm/exceptmacros.h @@ -334,7 +334,7 @@ VOID DECLSPEC_NORETURN DispatchManagedException(PAL_SEHException& ex, bool isHar UNREACHABLE(); \ } -#else +#else // FEATURE_PAL #define INSTALL_MANAGED_EXCEPTION_DISPATCHER #define UNINSTALL_MANAGED_EXCEPTION_DISPATCHER diff --git a/src/vm/exinfo.cpp b/src/vm/exinfo.cpp index 4cbc6d3..9e07ceb 100644 --- a/src/vm/exinfo.cpp +++ b/src/vm/exinfo.cpp @@ -76,9 +76,11 @@ void ExInfo::CopyAndClearSource(ExInfo *from) // Finally, initialize the source ExInfo. from->Init(); +#ifndef FEATURE_PAL // Clear the Watson Bucketing information as well since they // have been transferred over by the "memcpy" above. from->GetWatsonBucketTracker()->Init(); +#endif // FEATURE_PAL } void ExInfo::Init() @@ -136,8 +138,10 @@ ExInfo::ExInfo() m_hThrowable = NULL; Init(); +#ifndef FEATURE_PAL // Init the WatsonBucketTracker m_WatsonBucketTracker.Init(); +#endif // FEATURE_PAL } //******************************************************************************* @@ -206,9 +210,11 @@ void ExInfo::UnwindExInfo(VOID* limit) pPrevNestedInfo->DestroyExceptionHandle(); } + #ifndef FEATURE_PAL // Free the Watson bucket details when ExInfo // is being released pPrevNestedInfo->GetWatsonBucketTracker()->ClearWatsonBucketDetails(); + #endif // FEATURE_PAL pPrevNestedInfo->m_StackTraceInfo.FreeStackTrace(); @@ -256,8 +262,10 @@ void ExInfo::UnwindExInfo(VOID* limit) // We just do a basic Init of the current top ExInfo here. Init(); + #ifndef FEATURE_PAL // Init the Watson buckets as well GetWatsonBucketTracker()->ClearWatsonBucketDetails(); + #endif // FEATURE_PAL } } #endif // DACCESS_COMPILE diff --git a/src/vm/exinfo.h b/src/vm/exinfo.h index 72f2775..2a8030f 100644 --- a/src/vm/exinfo.h +++ b/src/vm/exinfo.h @@ -79,6 +79,7 @@ public: // void* m_StackAddress; // A pseudo or real stack location for this record. +#ifndef FEATURE_PAL private: EHWatsonBucketTracker m_WatsonBucketTracker; public: @@ -87,6 +88,7 @@ public: LIMITED_METHOD_CONTRACT; return PTR_EHWatsonBucketTracker(PTR_HOST_MEMBER_TADDR(ExInfo, this, m_WatsonBucketTracker)); } +#endif #ifdef FEATURE_CORRUPTING_EXCEPTIONS private: diff --git a/src/vm/finalizerthread.cpp b/src/vm/finalizerthread.cpp index 5d51d33..2f72b07 100644 --- a/src/vm/finalizerthread.cpp +++ b/src/vm/finalizerthread.cpp @@ -295,7 +295,7 @@ Object * FinalizerThread::FinalizeAllObjects(Object* fobj, int bitToCheck) { return NULL; } - fobj = GCHeap::GetGCHeap()->GetNextFinalizable(); + fobj = GCHeapUtilities::GetGCHeap()->GetNextFinalizable(); } Thread *pThread = GetThread(); @@ -320,7 +320,7 @@ Object * FinalizerThread::FinalizeAllObjects(Object* fobj, int bitToCheck) { return NULL; } - fobj = GCHeap::GetGCHeap()->GetNextFinalizable(); + fobj = GCHeapUtilities::GetGCHeap()->GetNextFinalizable(); } else { @@ -337,7 +337,7 @@ Object * FinalizerThread::FinalizeAllObjects(Object* fobj, int bitToCheck) { return NULL; } - fobj = GCHeap::GetGCHeap()->GetNextFinalizable(); + fobj = GCHeapUtilities::GetGCHeap()->GetNextFinalizable(); } } } @@ -533,7 +533,7 @@ void FinalizerThread::WaitForFinalizerEvent (CLREvent *event) case (WAIT_OBJECT_0 + kLowMemoryNotification): //short on memory GC immediately GetFinalizerThread()->DisablePreemptiveGC(); - GCHeap::GetGCHeap()->GarbageCollect(0, TRUE); + GCHeapUtilities::GetGCHeap()->GarbageCollect(0, TRUE); GetFinalizerThread()->EnablePreemptiveGC(); //wait only on the event for 2s switch (event->Wait(2000, FALSE)) @@ -584,7 +584,7 @@ void FinalizerThread::WaitForFinalizerEvent (CLREvent *event) if (WaitForSingleObject(MHandles[kLowMemoryNotification], 0) == WAIT_OBJECT_0) { //short on memory GC immediately GetFinalizerThread()->DisablePreemptiveGC(); - GCHeap::GetGCHeap()->GarbageCollect(0, TRUE); + GCHeapUtilities::GetGCHeap()->GarbageCollect(0, TRUE); GetFinalizerThread()->EnablePreemptiveGC(); } //wait only on the event for 2s @@ -604,7 +604,7 @@ void FinalizerThread::WaitForFinalizerEvent (CLREvent *event) if (sLastLowMemoryFromHost != 0) { GetFinalizerThread()->DisablePreemptiveGC(); - GCHeap::GetGCHeap()->GarbageCollect(0, TRUE); + GCHeapUtilities::GetGCHeap()->GarbageCollect(0, TRUE); GetFinalizerThread()->EnablePreemptiveGC(); } } @@ -677,7 +677,7 @@ VOID FinalizerThread::FinalizerThreadWorker(void *args) { s_forcedGCInProgress = true; GetFinalizerThread()->DisablePreemptiveGC(); - GCHeap::GetGCHeap()->GarbageCollect(2, FALSE, collection_blocking); + GCHeapUtilities::GetGCHeap()->GarbageCollect(2, FALSE, collection_blocking); GetFinalizerThread()->EnablePreemptiveGC(); s_forcedGCInProgress = false; @@ -710,14 +710,14 @@ VOID FinalizerThread::FinalizerThreadWorker(void *args) do { - last_gc_count = GCHeap::GetGCHeap()->CollectionCount(0); + last_gc_count = GCHeapUtilities::GetGCHeap()->CollectionCount(0); GetFinalizerThread()->m_GCOnTransitionsOK = FALSE; GetFinalizerThread()->EnablePreemptiveGC(); __SwitchToThread (0, ++dwSwitchCount); GetFinalizerThread()->DisablePreemptiveGC(); // If no GCs happended, then we assume we are quiescent GetFinalizerThread()->m_GCOnTransitionsOK = TRUE; - } while (GCHeap::GetGCHeap()->CollectionCount(0) - last_gc_count > 0); + } while (GCHeapUtilities::GetGCHeap()->CollectionCount(0) - last_gc_count > 0); } #endif //_DEBUG @@ -747,7 +747,7 @@ VOID FinalizerThread::FinalizerThreadWorker(void *args) } else if (UnloadingAppDomain == NULL) break; - else if (!GCHeap::GetGCHeap()->FinalizeAppDomain(UnloadingAppDomain, fRunFinalizersOnUnload)) + else if (!GCHeapUtilities::GetGCHeap()->FinalizeAppDomain(UnloadingAppDomain, fRunFinalizersOnUnload)) { break; } @@ -916,7 +916,7 @@ DWORD __stdcall FinalizerThread::FinalizerThreadStart(void *args) if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_FinalizeOnShutdown) != 0) { // Finalize all registered objects during shutdown, even they are still reachable. - GCHeap::GetGCHeap()->SetFinalizeQueueForShutdown(FALSE); + GCHeapUtilities::GetGCHeap()->SetFinalizeQueueForShutdown(FALSE); // This will apply any policy for swallowing exceptions during normal // processing, without allowing the finalizer thread to disappear on us. @@ -1380,7 +1380,7 @@ BOOL FinalizerThread::FinalizerThreadWatchDogHelper() } else { - prevCount = GCHeap::GetGCHeap()->GetNumberOfFinalizable(); + prevCount = GCHeapUtilities::GetGCHeap()->GetNumberOfFinalizable(); } DWORD maxTry = (DWORD)(totalWaitTimeout*1.0/FINALIZER_WAIT_TIMEOUT + 0.5); @@ -1447,11 +1447,11 @@ BOOL FinalizerThread::FinalizerThreadWatchDogHelper() } else { - curCount = GCHeap::GetGCHeap()->GetNumberOfFinalizable(); + curCount = GCHeapUtilities::GetGCHeap()->GetNumberOfFinalizable(); } if ((prevCount <= curCount) - && !GCHeap::GetGCHeap()->ShouldRestartFinalizerWatchDog() + && !GCHeapUtilities::GetGCHeap()->ShouldRestartFinalizerWatchDog() && (pThread == NULL || !(pThread->m_State & (Thread::TS_UserSuspendPending | Thread::TS_DebugSuspendPending)))){ if (nTry == maxTry) { if (!s_fRaiseExitProcessEvent) { diff --git a/src/vm/frames.cpp b/src/vm/frames.cpp index ec7e7be..04a1815 100644 --- a/src/vm/frames.cpp +++ b/src/vm/frames.cpp @@ -18,7 +18,7 @@ #include "fieldmarshaler.h" #include "objecthandle.h" #include "siginfo.hpp" -#include "gc.h" +#include "gcheaputilities.h" #include "dllimportcallback.h" #include "stackwalk.h" #include "dbginterface.h" diff --git a/src/vm/frames.h b/src/vm/frames.h index 0926f29..91ab3c3 100644 --- a/src/vm/frames.h +++ b/src/vm/frames.h @@ -113,8 +113,10 @@ // | +-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 // | // +-ContextTransitionFrame - this frame is used to mark an appdomain transition // | @@ -1905,7 +1907,7 @@ class UnmanagedToManagedFrame : public Frame { friend class CheckAsmOffsets; - VPTR_ABSTRACT_VTABLE_CLASS(UnmanagedToManagedFrame, Frame) + VPTR_ABSTRACT_VTABLE_CLASS_AND_CTOR(UnmanagedToManagedFrame, Frame) public: @@ -2897,7 +2899,7 @@ typedef DPTR(class UMThunkMarshInfo) PTR_UMThunkMarshInfo; class UMEntryThunk; typedef DPTR(class UMEntryThunk) PTR_UMEntryThunk; -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) //------------------------------------------------------------------------ // This frame guards an unmanaged->managed transition thru a UMThk //------------------------------------------------------------------------ @@ -2925,7 +2927,7 @@ protected: // Keep as last entry in class DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(UMThkCallFrame) }; -#endif // _TARGET_X86_ +#endif // _TARGET_X86_ && !FEATURE_PAL #if defined(_TARGET_X86_) //------------------------------------------------------------------------- diff --git a/src/vm/frameworkexceptionloader.cpp b/src/vm/frameworkexceptionloader.cpp index 7d01f82..a33010e 100644 --- a/src/vm/frameworkexceptionloader.cpp +++ b/src/vm/frameworkexceptionloader.cpp @@ -74,7 +74,7 @@ MethodTable* FrameworkExceptionLoader::GetException(RuntimeExceptionKind kind) { Exception *ex = GET_EXCEPTION(); - // Let non-file-not-found execeptions propagate + // Let non-file-not-found exceptions propagate if (EEFileLoadException::GetFileLoadKind(ex->GetHR()) != kFileNotFoundException) EX_RETHROW; diff --git a/src/vm/gc.h b/src/vm/gc.h deleted file mode 100644 index 825b5da..0000000 --- a/src/vm/gc.h +++ /dev/null @@ -1,5 +0,0 @@ -// 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. - -#include "../gc/gc.h" diff --git a/src/vm/gccover.cpp b/src/vm/gccover.cpp index 41dc094..d5e7b60 100644 --- a/src/vm/gccover.cpp +++ b/src/vm/gccover.cpp @@ -80,7 +80,7 @@ void SetupAndSprinkleBreakpoints( gcCover->methodRegion = methodRegionInfo; gcCover->codeMan = pCodeInfo->GetCodeManager(); - gcCover->gcInfoToken = pCodeInfo->GetGCInfoToken(); + gcCover->gcInfoToken = pCodeInfo->GetGCInfoToken(); gcCover->callerThread = 0; gcCover->doingEpilogChecks = true; @@ -583,7 +583,7 @@ void GCCoverageInfo::SprinkleBreakpoints( #ifdef _TARGET_X86_ // we will whack every instruction in the prolog and epilog to make certain // our unwinding logic works there. - if (codeMan->IsInPrologOrEpilog((cur - codeStart) + (DWORD)regionOffsetAdj, gcInfoToken.Info, NULL)) { + if (codeMan->IsInPrologOrEpilog((cur - codeStart) + (DWORD)regionOffsetAdj, gcInfoToken, NULL)) { *cur = INTERRUPT_INSTR; } #endif @@ -1234,8 +1234,8 @@ void checkAndUpdateReg(DWORD& origVal, DWORD curVal, bool gcHappened) { // the validation infrastructure has got a bug. _ASSERTE(gcHappened); // If the register values are different, a GC must have happened - _ASSERTE(GCHeap::GetGCHeap()->IsHeapPointer((BYTE*) size_t(origVal))); // And the pointers involved are on the GCHeap - _ASSERTE(GCHeap::GetGCHeap()->IsHeapPointer((BYTE*) size_t(curVal))); + _ASSERTE(GCHeapUtilities::GetGCHeap()->IsHeapPointer((BYTE*) size_t(origVal))); // And the pointers involved are on the GCHeap + _ASSERTE(GCHeapUtilities::GetGCHeap()->IsHeapPointer((BYTE*) size_t(curVal))); origVal = curVal; // this is now the best estimate of what should be returned. } @@ -1478,7 +1478,7 @@ void DoGcStress (PCONTEXT regs, MethodDesc *pMD) if (gcCover->callerThread == 0) { if (FastInterlockCompareExchangePointer(&gcCover->callerThread, pThread, 0) == 0) { gcCover->callerRegs = *regs; - gcCover->gcCount = GCHeap::GetGCHeap()->GetGcCount(); + gcCover->gcCount = GCHeapUtilities::GetGCHeap()->GetGcCount(); bShouldUpdateProlog = false; } } @@ -1527,7 +1527,7 @@ void DoGcStress (PCONTEXT regs, MethodDesc *pMD) /* are we in a prolog or epilog? If so just test the unwind logic but don't actually do a GC since the prolog and epilog are not GC safe points */ - if (gcCover->codeMan->IsInPrologOrEpilog(offset, gcCover->gcInfoToken.Info, NULL)) + if (gcCover->codeMan->IsInPrologOrEpilog(offset, gcCover->gcInfoToken, NULL)) { // We are not at a GC safe point so we can't Suspend EE (Suspend EE will yield to GC). // But we still have to update the GC Stress instruction. We do it directly without suspending @@ -1564,13 +1564,13 @@ void DoGcStress (PCONTEXT regs, MethodDesc *pMD) // instruction in the epilog (TODO: fix it for the first instr Case) _ASSERTE(pThread->PreemptiveGCDisabled()); // Epilogs should be in cooperative mode, no GC can happen right now. - bool gcHappened = gcCover->gcCount != GCHeap::GetGCHeap()->GetGcCount(); + bool gcHappened = gcCover->gcCount != GCHeapUtilities::GetGCHeap()->GetGcCount(); checkAndUpdateReg(gcCover->callerRegs.Edi, *regDisp.pEdi, gcHappened); checkAndUpdateReg(gcCover->callerRegs.Esi, *regDisp.pEsi, gcHappened); checkAndUpdateReg(gcCover->callerRegs.Ebx, *regDisp.pEbx, gcHappened); checkAndUpdateReg(gcCover->callerRegs.Ebp, *regDisp.pEbp, gcHappened); - gcCover->gcCount = GCHeap::GetGCHeap()->GetGcCount(); + gcCover->gcCount = GCHeapUtilities::GetGCHeap()->GetGcCount(); } return; @@ -1689,24 +1689,6 @@ void DoGcStress (PCONTEXT regs, MethodDesc *pMD) bool enableWhenDone = false; if (!pThread->PreemptiveGCDisabled()) { -#ifdef _TARGET_X86_ - // We are in preemtive mode in JITTed code. currently this can only - // happen in a couple of instructions when we have an inlined PINVOKE - // method. - - // Better be a CALL (direct or indirect), - // or a MOV instruction (three flavors), - // or pop ECX or add ESP xx (for cdecl pops, two flavors) - // or cmp, je (for the PINVOKE ESP checks) - // or lea (for PInvoke stack resilience) - if (!(instrVal == 0xE8 || instrVal == 0xFF || - instrVal == 0x89 || instrVal == 0x8B || instrVal == 0xC6 || - instrVal == 0x59 || instrVal == 0x81 || instrVal == 0x83 || - instrVal == 0x3B || instrVal == 0x74 || instrVal == 0x8D)) - { - _ASSERTE(!"Unexpected instruction in preemtive JITTED code"); - } -#endif // _TARGET_X86_ pThread->DisablePreemptiveGC(); enableWhenDone = true; } @@ -1777,7 +1759,7 @@ void DoGcStress (PCONTEXT regs, MethodDesc *pMD) // Do the actual stress work // - if (!GCHeap::GetGCHeap()->StressHeap()) + if (!GCHeapUtilities::GetGCHeap()->StressHeap()) UpdateGCStressInstructionWithoutGC (); // Must flush instruction cache before returning as instruction has been modified. diff --git a/src/vm/gcenv.ee.cpp b/src/vm/gcenv.ee.cpp index 2f1e4e8..3be8384 100644 --- a/src/vm/gcenv.ee.cpp +++ b/src/vm/gcenv.ee.cpp @@ -15,6 +15,12 @@ #include "gcenv.h" +#ifdef FEATURE_STANDALONE_GC +#include "gcenv.ee.h" +#else +#include "../gc/env/gcenv.ee.h" +#endif // FEATURE_STANDALONE_GC + #include "threadsuspend.h" #ifdef FEATURE_COMINTEROP @@ -125,7 +131,7 @@ inline bool SafeToReportGenericParamContext(CrawlFrame* pCF) #ifndef USE_GC_INFO_DECODER ICodeManager * pEECM = pCF->GetCodeManager(); - if (pEECM != NULL && pEECM->IsInPrologOrEpilog(pCF->GetRelOffset(), pCF->GetGCInfo(), NULL)) + if (pEECM != NULL && pEECM->IsInPrologOrEpilog(pCF->GetRelOffset(), pCF->GetGCInfoToken(), NULL)) { return false; } @@ -550,7 +556,7 @@ void GCToEEInterface::GcScanRoots(promote_func* fn, int condemned, int max_gen, STRESS_LOG1(LF_GCROOTS, LL_INFO10, "GCScan: Promotion Phase = %d\n", sc->promotion); // In server GC, we should be competing for marking the statics - if (GCHeap::MarkShouldCompeteForStatics()) + if (GCHeapUtilities::MarkShouldCompeteForStatics()) { if (condemned == max_gen && sc->promotion) { @@ -563,7 +569,7 @@ void GCToEEInterface::GcScanRoots(promote_func* fn, int condemned, int max_gen, { STRESS_LOG2(LF_GC | LF_GCROOTS, LL_INFO100, "{ Starting scan of Thread %p ID = %x\n", pThread, pThread->GetThreadId()); - if (GCHeap::GetGCHeap()->IsThreadUsingAllocationContextHeap( + if (GCHeapUtilities::GetGCHeap()->IsThreadUsingAllocationContextHeap( GCToEEInterface::GetAllocContext(pThread), sc->thread_number)) { sc->thread_under_crawl = pThread; @@ -693,7 +699,7 @@ void GCToEEInterface::SyncBlockCachePromotionsGranted(int max_gen) SyncBlockCache::GetSyncBlockCache()->GCDone(FALSE, max_gen); } -alloc_context * GCToEEInterface::GetAllocContext(Thread * pThread) +gc_alloc_context * GCToEEInterface::GetAllocContext(Thread * pThread) { WRAPPER_NO_CONTRACT; return pThread->GetAllocContext(); @@ -839,3 +845,426 @@ Thread* GCToEEInterface::CreateBackgroundThread(GCBackgroundThreadFunction threa threadStubArgs.thread->DecExternalCount(FALSE); return NULL; } + +// +// Diagnostics code +// + +#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) +inline BOOL ShouldTrackMovementForProfilerOrEtw() +{ +#ifdef GC_PROFILING + if (CORProfilerTrackGC()) + return true; +#endif + +#ifdef FEATURE_EVENT_TRACE + if (ETW::GCLog::ShouldTrackMovementForEtw()) + return true; +#endif + + return false; +} +#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) + +void ProfScanRootsHelper(Object** ppObject, ScanContext *pSC, uint32_t dwFlags) +{ +#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) + Object *pObj = *ppObject; + if (dwFlags & GC_CALL_INTERIOR) + { + pObj = GCHeapUtilities::GetGCHeap()->GetContainingObject(pObj); + } + ScanRootsHelper(pObj, ppObject, pSC, dwFlags); +#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) +} + +// TODO - at some point we would like to completely decouple profiling +// from ETW tracing using a pattern similar to this, where the +// ProfilingScanContext has flags about whether or not certain things +// should be tracked, and each one of these ProfilerShouldXYZ functions +// will check these flags and determine what to do based upon that. +// GCProfileWalkHeapWorker can, in turn, call those methods without fear +// of things being ifdef'd out. + +// Returns TRUE if GC profiling is enabled and the profiler +// should scan dependent handles, FALSE otherwise. +BOOL ProfilerShouldTrackConditionalWeakTableElements() +{ +#if defined(GC_PROFILING) + return CORProfilerTrackConditionalWeakTableElements(); +#else + return FALSE; +#endif // defined (GC_PROFILING) +} + +// If GC profiling is enabled, informs the profiler that we are done +// tracing dependent handles. +void ProfilerEndConditionalWeakTableElementReferences(void* heapId) +{ +#if defined (GC_PROFILING) + g_profControlBlock.pProfInterface->EndConditionalWeakTableElementReferences(heapId); +#else + UNREFERENCED_PARAMETER(heapId); +#endif // defined (GC_PROFILING) +} + +// If GC profiling is enabled, informs the profiler that we are done +// tracing root references. +void ProfilerEndRootReferences2(void* heapId) +{ +#if defined (GC_PROFILING) + g_profControlBlock.pProfInterface->EndRootReferences2(heapId); +#else + UNREFERENCED_PARAMETER(heapId); +#endif // defined (GC_PROFILING) +} + +void GcScanRootsForProfilerAndETW(promote_func* fn, int condemned, int max_gen, ScanContext* sc) +{ + Thread* pThread = NULL; + while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL) + { + sc->thread_under_crawl = pThread; +#ifdef FEATURE_EVENT_TRACE + sc->dwEtwRootKind = kEtwGCRootKindStack; +#endif // FEATURE_EVENT_TRACE + ScanStackRoots(pThread, fn, sc); +#ifdef FEATURE_EVENT_TRACE + sc->dwEtwRootKind = kEtwGCRootKindOther; +#endif // FEATURE_EVENT_TRACE + } +} + +void ScanHandleForProfilerAndETW(Object** pRef, Object* pSec, uint32_t flags, ScanContext* context, BOOL isDependent) +{ + ProfilingScanContext* pSC = (ProfilingScanContext*)context; + +#ifdef GC_PROFILING + // Give the profiler the objectref. + if (pSC->fProfilerPinned) + { + if (!isDependent) + { + BEGIN_PIN_PROFILER(CORProfilerTrackGC()); + g_profControlBlock.pProfInterface->RootReference2( + (uint8_t *)*pRef, + kEtwGCRootKindHandle, + (EtwGCRootFlags)flags, + pRef, + &pSC->pHeapId); + END_PIN_PROFILER(); + } + else + { + BEGIN_PIN_PROFILER(CORProfilerTrackConditionalWeakTableElements()); + g_profControlBlock.pProfInterface->ConditionalWeakTableElementReference( + (uint8_t*)*pRef, + (uint8_t*)pSec, + pRef, + &pSC->pHeapId); + END_PIN_PROFILER(); + } + } +#endif // GC_PROFILING + +#if defined(FEATURE_EVENT_TRACE) + // Notify ETW of the handle + if (ETW::GCLog::ShouldWalkHeapRootsForEtw()) + { + ETW::GCLog::RootReference( + pRef, + *pRef, // object being rooted + pSec, // pSecondaryNodeForDependentHandle + isDependent, + pSC, + 0, // dwGCFlags, + flags); // ETW handle flags + } +#endif // defined(FEATURE_EVENT_TRACE) +} + +// This is called only if we've determined that either: +// a) The Profiling API wants to do a walk of the heap, and it has pinned the +// profiler in place (so it cannot be detached), and it's thus safe to call into the +// profiler, OR +// b) ETW infrastructure wants to do a walk of the heap either to log roots, +// objects, or both. +// This can also be called to do a single walk for BOTH a) and b) simultaneously. Since +// ETW can ask for roots, but not objects +#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) +void GCProfileWalkHeapWorker(BOOL fProfilerPinned, BOOL fShouldWalkHeapRootsForEtw, BOOL fShouldWalkHeapObjectsForEtw) +{ + { + ProfilingScanContext SC(fProfilerPinned); + + // **** Scan roots: Only scan roots if profiling API wants them or ETW wants them. + if (fProfilerPinned || fShouldWalkHeapRootsForEtw) + { + GcScanRootsForProfilerAndETW(&ProfScanRootsHelper, max_generation, max_generation, &SC); + SC.dwEtwRootKind = kEtwGCRootKindFinalizer; + GCHeapUtilities::GetGCHeap()->DiagScanFinalizeQueue(&ProfScanRootsHelper, &SC); + + // Handles are kept independent of wks/svr/concurrent builds + SC.dwEtwRootKind = kEtwGCRootKindHandle; + GCHeapUtilities::GetGCHeap()->DiagScanHandles(&ScanHandleForProfilerAndETW, max_generation, &SC); + + // indicate that regular handle scanning is over, so we can flush the buffered roots + // to the profiler. (This is for profapi only. ETW will flush after the + // entire heap was is complete, via ETW::GCLog::EndHeapDump.) + if (fProfilerPinned) + { + ProfilerEndRootReferences2(&SC.pHeapId); + } + } + + // **** Scan dependent handles: only if the profiler supports it or ETW wants roots + if ((fProfilerPinned && ProfilerShouldTrackConditionalWeakTableElements()) || + fShouldWalkHeapRootsForEtw) + { + // GcScanDependentHandlesForProfiler double-checks + // CORProfilerTrackConditionalWeakTableElements() before calling into the profiler + + ProfilingScanContext* pSC = &SC; + + // we'll re-use pHeapId (which was either unused (0) or freed by EndRootReferences2 + // (-1)), so reset it to NULL + _ASSERTE((*((size_t *)(&pSC->pHeapId)) == (size_t)(-1)) || + (*((size_t *)(&pSC->pHeapId)) == (size_t)(0))); + pSC->pHeapId = NULL; + + GCHeapUtilities::GetGCHeap()->DiagScanDependentHandles(&ScanHandleForProfilerAndETW, max_generation, &SC); + + // indicate that dependent handle scanning is over, so we can flush the buffered roots + // to the profiler. (This is for profapi only. ETW will flush after the + // entire heap was is complete, via ETW::GCLog::EndHeapDump.) + if (fProfilerPinned && ProfilerShouldTrackConditionalWeakTableElements()) + { + ProfilerEndConditionalWeakTableElementReferences(&SC.pHeapId); + } + } + + ProfilerWalkHeapContext profilerWalkHeapContext(fProfilerPinned, SC.pvEtwContext); + + // **** Walk objects on heap: only if profiling API wants them or ETW wants them. + if (fProfilerPinned || fShouldWalkHeapObjectsForEtw) + { + GCHeapUtilities::GetGCHeap()->DiagWalkHeap(&HeapWalkHelper, &profilerWalkHeapContext, max_generation, TRUE /* walk the large object heap */); + } + +#ifdef FEATURE_EVENT_TRACE + // **** Done! Indicate to ETW helpers that the heap walk is done, so any buffers + // should be flushed into the ETW stream + if (fShouldWalkHeapObjectsForEtw || fShouldWalkHeapRootsForEtw) + { + ETW::GCLog::EndHeapDump(&profilerWalkHeapContext); + } +#endif // FEATURE_EVENT_TRACE + } +} +#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) + +void GCProfileWalkHeap() +{ + BOOL fWalkedHeapForProfiler = FALSE; + +#ifdef FEATURE_EVENT_TRACE + if (ETW::GCLog::ShouldWalkStaticsAndCOMForEtw()) + ETW::GCLog::WalkStaticsAndCOMForETW(); + + BOOL fShouldWalkHeapRootsForEtw = ETW::GCLog::ShouldWalkHeapRootsForEtw(); + BOOL fShouldWalkHeapObjectsForEtw = ETW::GCLog::ShouldWalkHeapObjectsForEtw(); +#else // !FEATURE_EVENT_TRACE + BOOL fShouldWalkHeapRootsForEtw = FALSE; + BOOL fShouldWalkHeapObjectsForEtw = FALSE; +#endif // FEATURE_EVENT_TRACE + +#if defined (GC_PROFILING) + { + BEGIN_PIN_PROFILER(CORProfilerTrackGC()); + GCProfileWalkHeapWorker(TRUE /* fProfilerPinned */, fShouldWalkHeapRootsForEtw, fShouldWalkHeapObjectsForEtw); + fWalkedHeapForProfiler = TRUE; + END_PIN_PROFILER(); + } +#endif // defined (GC_PROFILING) + +#if defined (GC_PROFILING) || defined(FEATURE_EVENT_TRACE) + // we need to walk the heap if one of GC_PROFILING or FEATURE_EVENT_TRACE + // is defined, since both of them make use of the walk heap worker. + if (!fWalkedHeapForProfiler && + (fShouldWalkHeapRootsForEtw || fShouldWalkHeapObjectsForEtw)) + { + GCProfileWalkHeapWorker(FALSE /* fProfilerPinned */, fShouldWalkHeapRootsForEtw, fShouldWalkHeapObjectsForEtw); + } +#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) +} + +void WalkFReachableObjects(BOOL isCritical, void* objectID) +{ + g_profControlBlock.pProfInterface->FinalizeableObjectQueued(isCritical, (ObjectID)objectID); +} + +static fq_walk_fn g_FQWalkFn = &WalkFReachableObjects; + +void GCToEEInterface::DiagGCStart(int gen, bool isInduced) +{ +#ifdef GC_PROFILING + DiagUpdateGenerationBounds(); + GarbageCollectionStartedCallback(gen, isInduced); + { + BEGIN_PIN_PROFILER(CORProfilerTrackGC()); + size_t context = 0; + + // When we're walking objects allocated by class, then we don't want to walk the large + // object heap because then it would count things that may have been around for a while. + GCHeapUtilities::GetGCHeap()->DiagWalkHeap(&AllocByClassHelper, (void *)&context, 0, FALSE); + + // Notify that we've reached the end of the Gen 0 scan + g_profControlBlock.pProfInterface->EndAllocByClass(&context); + END_PIN_PROFILER(); + } + +#endif // GC_PROFILING +} + +void GCToEEInterface::DiagUpdateGenerationBounds() +{ +#ifdef GC_PROFILING + if (CORProfilerTrackGC()) + UpdateGenerationBounds(); +#endif // GC_PROFILING +} + +void GCToEEInterface::DiagGCEnd(size_t index, int gen, int reason, bool fConcurrent) +{ +#ifdef GC_PROFILING + if (!fConcurrent) + { + GCProfileWalkHeap(); + DiagUpdateGenerationBounds(); + GarbageCollectionFinishedCallback(); + } +#endif // GC_PROFILING +} + +void GCToEEInterface::DiagWalkFReachableObjects(void* gcContext) +{ +#ifdef GC_PROFILING + if (CORProfilerTrackGC()) + { + BEGIN_PIN_PROFILER(CORProfilerPresent()); + GCHeapUtilities::GetGCHeap()->DiagWalkFinalizeQueue(gcContext, g_FQWalkFn); + END_PIN_PROFILER(); + } +#endif //GC_PROFILING +} + +// Note on last parameter: when calling this for bgc, only ETW +// should be sending these events so that existing profapi profilers +// don't get confused. +void WalkMovedReferences(uint8_t* begin, uint8_t* end, + ptrdiff_t reloc, + size_t context, + BOOL fCompacting, + BOOL fBGC) +{ + ETW::GCLog::MovedReference(begin, end, + (fCompacting ? reloc : 0), + context, + fCompacting, + !fBGC); +} + +void GCToEEInterface::DiagWalkSurvivors(void* gcContext) +{ +#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) + if (ShouldTrackMovementForProfilerOrEtw()) + { + size_t context = 0; + ETW::GCLog::BeginMovedReferences(&context); + GCHeapUtilities::GetGCHeap()->DiagWalkSurvivorsWithType(gcContext, &WalkMovedReferences, context, walk_for_gc); + ETW::GCLog::EndMovedReferences(context); + } +#endif //GC_PROFILING || FEATURE_EVENT_TRACE +} + +void GCToEEInterface::DiagWalkLOHSurvivors(void* gcContext) +{ +#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) + if (ShouldTrackMovementForProfilerOrEtw()) + { + size_t context = 0; + ETW::GCLog::BeginMovedReferences(&context); + GCHeapUtilities::GetGCHeap()->DiagWalkSurvivorsWithType(gcContext, &WalkMovedReferences, context, walk_for_loh); + ETW::GCLog::EndMovedReferences(context); + } +#endif //GC_PROFILING || FEATURE_EVENT_TRACE +} + +void GCToEEInterface::DiagWalkBGCSurvivors(void* gcContext) +{ +#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) + if (ShouldTrackMovementForProfilerOrEtw()) + { + size_t context = 0; + ETW::GCLog::BeginMovedReferences(&context); + GCHeapUtilities::GetGCHeap()->DiagWalkSurvivorsWithType(gcContext, &WalkMovedReferences, context, walk_for_bgc); + ETW::GCLog::EndMovedReferences(context); + } +#endif //GC_PROFILING || FEATURE_EVENT_TRACE +} + +void GCToEEInterface::StompWriteBarrier(WriteBarrierParameters* args) +{ + assert(args != nullptr); + switch (args->operation) + { + case WriteBarrierOp::StompResize: + // StompResize requires a new card table, a new lowest address, and + // a new highest address + assert(args->card_table != nullptr); + assert(args->lowest_address != nullptr); + assert(args->highest_address != nullptr); + g_card_table = args->card_table; + ::StompWriteBarrierResize(args->is_runtime_suspended, args->requires_upper_bounds_check); + + // We need to make sure that other threads executing checked write barriers + // will see the g_card_table update before g_lowest/highest_address updates. + // Otherwise, the checked write barrier may AV accessing the old card table + // with address that it does not cover. Write barriers access card table + // without memory barriers for performance reasons, so we need to flush + // the store buffers here. + FlushProcessWriteBuffers(); + + g_lowest_address = args->lowest_address; + VolatileStore(&g_highest_address, args->highest_address); + return; + case WriteBarrierOp::StompEphemeral: + // StompEphemeral requires a new ephemeral low and a new ephemeral high + assert(args->ephemeral_lo != nullptr); + assert(args->ephemeral_hi != nullptr); + g_ephemeral_low = args->ephemeral_lo; + g_ephemeral_high = args->ephemeral_hi; + ::StompWriteBarrierEphemeral(args->is_runtime_suspended); + return; + case WriteBarrierOp::Initialize: + // This operation should only be invoked once, upon initialization. + assert(g_card_table == nullptr); + assert(g_lowest_address == nullptr); + assert(g_highest_address == nullptr); + assert(args->card_table != nullptr); + assert(args->lowest_address != nullptr); + assert(args->highest_address != nullptr); + assert(args->is_runtime_suspended && "the runtime must be suspended here!"); + assert(!args->requires_upper_bounds_check && "the ephemeral generation must be at the top of the heap!"); + + g_card_table = args->card_table; + FlushProcessWriteBuffers(); + g_lowest_address = args->lowest_address; + VolatileStore(&g_highest_address, args->highest_address); + ::StompWriteBarrierResize(true, false); + return; + default: + assert(!"unknown WriteBarrierOp enum"); + } +} diff --git a/src/vm/gcenv.ee.h b/src/vm/gcenv.ee.h index 1d6c9bf..f431221 100644 --- a/src/vm/gcenv.ee.h +++ b/src/vm/gcenv.ee.h @@ -2,4 +2,48 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#include "../gc/env/gcenv.ee.h" +#ifndef _GCENV_EE_H_ +#define _GCENV_EE_H_ + +#include "gcinterface.h" + +#ifdef FEATURE_STANDALONE_GC + +class GCToEEInterface : public IGCToCLR { +public: + GCToEEInterface() = default; + ~GCToEEInterface() = default; + + void SuspendEE(SUSPEND_REASON reason); + void RestartEE(bool bFinishedGC); + void GcScanRoots(promote_func* fn, int condemned, int max_gen, ScanContext* sc); + void GcStartWork(int condemned, int max_gen); + void AfterGcScanRoots(int condemned, int max_gen, ScanContext* sc); + void GcBeforeBGCSweepWork(); + void GcDone(int condemned); + bool RefCountedHandleCallbacks(Object * pObject); + void SyncBlockCacheWeakPtrScan(HANDLESCANPROC scanProc, uintptr_t lp1, uintptr_t lp2); + void SyncBlockCacheDemote(int max_gen); + void SyncBlockCachePromotionsGranted(int max_gen); + bool IsPreemptiveGCDisabled(Thread * pThread); + void EnablePreemptiveGC(Thread * pThread); + void DisablePreemptiveGC(Thread * pThread); + gc_alloc_context * GetAllocContext(Thread * pThread); + bool CatchAtSafePoint(Thread * pThread); + void GcEnumAllocContexts(enum_alloc_context_func* fn, void* param); + Thread* CreateBackgroundThread(GCBackgroundThreadFunction threadStart, void* arg); + + // Diagnostics methods. + void DiagGCStart(int gen, bool isInduced); + void DiagUpdateGenerationBounds(); + void DiagGCEnd(size_t index, int gen, int reason, bool fConcurrent); + void DiagWalkFReachableObjects(void* gcContext); + void DiagWalkSurvivors(void* gcContext); + void DiagWalkLOHSurvivors(void* gcContext); + void DiagWalkBGCSurvivors(void* gcContext); + void StompWriteBarrier(WriteBarrierParameters* args); +}; + +#endif // FEATURE_STANDALONE_GC + +#endif // _GCENV_EE_H_ \ No newline at end of file diff --git a/src/vm/gcenv.h b/src/vm/gcenv.h index 08dcc71..ad5baa2 100644 --- a/src/vm/gcenv.h +++ b/src/vm/gcenv.h @@ -48,8 +48,6 @@ #include "util.hpp" -#include "gcenv.ee.h" -#include "gcenv.os.h" #include "gcenv.interlocked.h" #include "gcenv.interlocked.inl" diff --git a/src/vm/gcenv.os.cpp b/src/vm/gcenv.os.cpp index 73b21a7..52789b8 100644 --- a/src/vm/gcenv.os.cpp +++ b/src/vm/gcenv.os.cpp @@ -18,6 +18,12 @@ #include #endif +#ifdef Sleep +#undef Sleep +#endif // Sleep + +#include "env/gcenv.os.h" + #define MAX_PTR ((uint8_t*)(~(ptrdiff_t)0)) // Initialize the interface implementation @@ -160,7 +166,7 @@ void GCToOSInterface::YieldThread(uint32_t switchCount) // flags - flags to control special settings like write watching // Return: // Starting virtual address of the reserved range -void* GCToOSInterface::VirtualReserve(void* address, size_t size, size_t alignment, uint32_t flags) +void* GCToOSInterface::VirtualReserve(size_t size, size_t alignment, uint32_t flags) { LIMITED_METHOD_CONTRACT; @@ -249,7 +255,7 @@ bool GCToOSInterface::SupportsWriteWatch() // check if the OS supports write-watch. // Drawbridge does not support write-watch so we still need to do the runtime detection for them. // Otherwise, all currently supported OSes do support write-watch. - void* mem = VirtualReserve (0, g_SystemInfo.dwAllocationGranularity, 0, VirtualReserveFlags::WriteWatch); + void* mem = VirtualReserve (g_SystemInfo.dwAllocationGranularity, 0, VirtualReserveFlags::WriteWatch); if (mem != NULL) { VirtualRelease (mem, g_SystemInfo.dwAllocationGranularity); @@ -364,23 +370,6 @@ static size_t g_RestrictedPhysicalMemoryLimit = (size_t)MAX_PTR; typedef BOOL (WINAPI *PIS_PROCESS_IN_JOB)(HANDLE processHandle, HANDLE jobHandle, BOOL* result); typedef BOOL (WINAPI *PQUERY_INFORMATION_JOB_OBJECT)(HANDLE jobHandle, JOBOBJECTINFOCLASS jobObjectInfoClass, void* lpJobObjectInfo, DWORD cbJobObjectInfoLength, LPDWORD lpReturnLength); -#ifdef FEATURE_CORECLR -// For coresys we need to look for an API in some apiset dll on win8 if we can't find it -// in the traditional dll. -HINSTANCE LoadDllForAPI(WCHAR* dllTraditional, WCHAR* dllApiSet) -{ - HINSTANCE hinst = WszLoadLibrary(dllTraditional); - - if (!hinst) - { - if(RunningOnWin8()) - hinst = WszLoadLibrary(dllApiSet); - } - - return hinst; -} -#endif - static size_t GetRestrictedPhysicalMemoryLimit() { LIMITED_METHOD_CONTRACT; @@ -392,10 +381,7 @@ static size_t GetRestrictedPhysicalMemoryLimit() size_t job_physical_memory_limit = (size_t)MAX_PTR; BOOL in_job_p = FALSE; #ifdef FEATURE_CORECLR - HINSTANCE hinstApiSetPsapiOrKernel32 = 0; - // these 2 modules will need to be freed no matter what as we only use them locally in this method. - HINSTANCE hinstApiSetJob1OrKernel32 = 0; - HINSTANCE hinstApiSetJob2OrKernel32 = 0; + HINSTANCE hinstKernel32 = 0; #else HINSTANCE hinstPsapi = 0; #endif @@ -403,17 +389,7 @@ static size_t GetRestrictedPhysicalMemoryLimit() PIS_PROCESS_IN_JOB GCIsProcessInJob = 0; PQUERY_INFORMATION_JOB_OBJECT GCQueryInformationJobObject = 0; -#ifdef FEATURE_CORECLR - hinstApiSetJob1OrKernel32 = LoadDllForAPI(L"kernel32.dll", L"api-ms-win-core-job-l1-1-0.dll"); - if (!hinstApiSetJob1OrKernel32) - goto exit; - - GCIsProcessInJob = (PIS_PROCESS_IN_JOB)GetProcAddress(hinstApiSetJob1OrKernel32, "IsProcessInJob"); - if (!GCIsProcessInJob) - goto exit; -#else GCIsProcessInJob = &(::IsProcessInJob); -#endif if (!GCIsProcessInJob(GetCurrentProcess(), NULL, &in_job_p)) goto exit; @@ -421,11 +397,11 @@ static size_t GetRestrictedPhysicalMemoryLimit() if (in_job_p) { #ifdef FEATURE_CORECLR - hinstApiSetPsapiOrKernel32 = LoadDllForAPI(L"kernel32.dll", L"api-ms-win-core-psapi-l1-1-0"); - if (!hinstApiSetPsapiOrKernel32) + hinstKernel32 = WszLoadLibrary(L"kernel32.dll"); + if (!hinstKernel32) goto exit; - GCGetProcessMemoryInfo = (PGET_PROCESS_MEMORY_INFO)GetProcAddress(hinstApiSetPsapiOrKernel32, "K32GetProcessMemoryInfo"); + GCGetProcessMemoryInfo = (PGET_PROCESS_MEMORY_INFO)GetProcAddress(hinstKernel32, "K32GetProcessMemoryInfo"); #else // We need a way to get the working set in a job object and GetProcessMemoryInfo // is the way to get that. According to MSDN, we should use GetProcessMemoryInfo In order to @@ -439,15 +415,7 @@ static size_t GetRestrictedPhysicalMemoryLimit() if (!GCGetProcessMemoryInfo) goto exit; -#ifdef FEATURE_CORECLR - hinstApiSetJob2OrKernel32 = LoadDllForAPI(L"kernel32.dll", L"api-ms-win-core-job-l2-1-0"); - if (!hinstApiSetJob2OrKernel32) - goto exit; - - GCQueryInformationJobObject = (PQUERY_INFORMATION_JOB_OBJECT)GetProcAddress(hinstApiSetJob2OrKernel32, "QueryInformationJobObject"); -#else GCQueryInformationJobObject = &(::QueryInformationJobObject); -#endif if (!GCQueryInformationJobObject) goto exit; @@ -490,19 +458,12 @@ static size_t GetRestrictedPhysicalMemoryLimit() } exit: -#ifdef FEATURE_CORECLR - if (hinstApiSetJob1OrKernel32) - FreeLibrary(hinstApiSetJob1OrKernel32); - if (hinstApiSetJob2OrKernel32) - FreeLibrary(hinstApiSetJob2OrKernel32); -#endif - if (job_physical_memory_limit == (size_t)MAX_PTR) { job_physical_memory_limit = 0; #ifdef FEATURE_CORECLR - FreeLibrary(hinstApiSetPsapiOrKernel32); + FreeLibrary(hinstKernel32); #else FreeLibrary(hinstPsapi); #endif @@ -633,7 +594,7 @@ struct GCThreadStubParam }; // GC thread stub to convert GC thread function to an OS specific thread function -static DWORD GCThreadStub(void* param) +static DWORD __stdcall GCThreadStub(void* param) { WRAPPER_NO_CONTRACT; diff --git a/src/vm/gcheaputilities.cpp b/src/vm/gcheaputilities.cpp new file mode 100644 index 0000000..ac24fa3 --- /dev/null +++ b/src/vm/gcheaputilities.cpp @@ -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. +// See the LICENSE file in the project root for more information. + +#include "common.h" +#include "gcheaputilities.h" + +// These globals are variables used within the GC and maintained +// by the EE for use in write barriers. It is the responsibility +// of the GC to communicate updates to these globals to the EE through +// GCToEEInterface::StompWriteBarrierResize and GCToEEInterface::StompWriteBarrierEphemeral. +GPTR_IMPL_INIT(uint32_t, g_card_table, nullptr); +GPTR_IMPL_INIT(uint8_t, g_lowest_address, nullptr); +GPTR_IMPL_INIT(uint8_t, g_highest_address, nullptr); +uint8_t* g_ephemeral_low = (uint8_t*)1; +uint8_t* g_ephemeral_high = (uint8_t*)~0; + +// This is the global GC heap, maintained by the VM. +GPTR_IMPL(IGCHeap, g_pGCHeap); \ No newline at end of file diff --git a/src/vm/gcheaputilities.h b/src/vm/gcheaputilities.h new file mode 100644 index 0000000..e5883fc --- /dev/null +++ b/src/vm/gcheaputilities.h @@ -0,0 +1,129 @@ +// 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. + +#ifndef _GCHEAPUTILITIES_H_ +#define _GCHEAPUTILITIES_H_ + +#include "gcinterface.h" + +// The singular heap instance. +GPTR_DECL(IGCHeap, g_pGCHeap); + +// GCHeapUtilities provides a number of static methods +// that operate on the global heap instance. It can't be +// instantiated. +class GCHeapUtilities { +public: + // Retrieves the GC heap. + inline static IGCHeap* GetGCHeap() + { + LIMITED_METHOD_CONTRACT; + + assert(g_pGCHeap != nullptr); + return g_pGCHeap; + } + + // Returns true if the heap has been initialized, false otherwise. + inline static bool IsGCHeapInitialized() + { + LIMITED_METHOD_CONTRACT; + + return g_pGCHeap != nullptr; + } + + // Returns true if a the heap is initialized and a garbage collection + // is in progress, false otherwise. + inline static BOOL IsGCInProgress(BOOL bConsiderGCStart = FALSE) + { + WRAPPER_NO_CONTRACT; + + return (IsGCHeapInitialized() ? GetGCHeap()->IsGCInProgressHelper(bConsiderGCStart) : false); + } + + // Returns true if we should be competing marking for statics. This + // influences the behavior of `GCToEEInterface::GcScanRoots`. + inline static BOOL MarkShouldCompeteForStatics() + { + WRAPPER_NO_CONTRACT; + + return IsServerHeap() && g_SystemInfo.dwNumberOfProcessors >= 2; + } + + // Waits until a GC is complete, if the heap has been initialized. + inline static void WaitForGCCompletion(BOOL bConsiderGCStart = FALSE) + { + WRAPPER_NO_CONTRACT; + + if (IsGCHeapInitialized()) + GetGCHeap()->WaitUntilGCComplete(bConsiderGCStart); + } + + // Returns true if we should be using allocation contexts, false otherwise. + inline static bool UseAllocationContexts() + { + WRAPPER_NO_CONTRACT; +#ifdef FEATURE_REDHAWK + // SIMPLIFY: only use allocation contexts + return true; +#else +#if defined(_TARGET_ARM_) || defined(FEATURE_PAL) + return true; +#else + return ((IsServerHeap() ? true : (g_SystemInfo.dwNumberOfProcessors >= 2))); +#endif +#endif + } + + // Returns true if the held GC heap is a Server GC heap, false otherwise. + inline static bool IsServerHeap() + { + LIMITED_METHOD_CONTRACT; +#ifdef FEATURE_SVR_GC + _ASSERTE(IGCHeap::gcHeapType != IGCHeap::GC_HEAP_INVALID); + return (IGCHeap::gcHeapType == IGCHeap::GC_HEAP_SVR); +#else // FEATURE_SVR_GC + return false; +#endif // FEATURE_SVR_GC + } + + // Gets the maximum generation number by reading the static field + // on IGCHeap. This should only be done by the DAC code paths - all other code + // should go through IGCHeap::GetMaxGeneration. + // + // The reason for this is that, while we are in the early stages of + // decoupling the GC, the GC and the DAC still remain tightly coupled + // and, in particular, the DAC needs to know how many generations the GC + // has. However, it is not permitted to invoke virtual methods on g_pGCHeap + // while on a DAC code path. Therefore, we need to determine the max generation + // non-virtually, while still in a manner consistent with the interface - + // therefore, a static field is used. + // + // This is not without precedent - IGCHeap::gcHeapType is a static field used + // for a similar reason (the DAC needs to know what kind of heap it's looking at). + inline static unsigned GetMaxGeneration() + { + WRAPPER_NO_CONTRACT; + + return IGCHeap::maxGeneration; + } + +private: + // This class should never be instantiated. + GCHeapUtilities() = delete; +}; + +#ifndef DACCESS_COMPILE +extern "C" { +#endif // !DACCESS_COMPILE +GPTR_DECL(uint8_t,g_lowest_address); +GPTR_DECL(uint8_t,g_highest_address); +GPTR_DECL(uint32_t,g_card_table); +#ifndef DACCESS_COMPILE +} +#endif // !DACCESS_COMPILE + +extern "C" uint8_t* g_ephemeral_low; +extern "C" uint8_t* g_ephemeral_high; + +#endif // _GCHEAPUTILITIES_H_ \ No newline at end of file diff --git a/src/vm/gchelpers.cpp b/src/vm/gchelpers.cpp index bf81847..20a3a29 100644 --- a/src/vm/gchelpers.cpp +++ b/src/vm/gchelpers.cpp @@ -16,7 +16,7 @@ #include "threads.h" #include "eetwain.h" #include "eeconfig.h" -#include "gc.h" +#include "gcheaputilities.h" #include "corhost.h" #include "threads.h" #include "fieldmarshaler.h" @@ -51,15 +51,50 @@ orObject = (ArrayBase *) OBJECTREFToObject(objref); -inline alloc_context* GetThreadAllocContext() +inline gc_alloc_context* GetThreadAllocContext() { WRAPPER_NO_CONTRACT; - assert(GCHeap::UseAllocationContexts()); + assert(GCHeapUtilities::UseAllocationContexts()); return & GetThread()->m_alloc_context; } +// Checks to see if the given allocation size exceeds the +// largest object size allowed - if it does, it throws +// an OutOfMemoryException with a message indicating that +// the OOM was not from memory pressure but from an object +// being too large. +inline void CheckObjectSize(size_t alloc_size) +{ + CONTRACTL { + THROWS; + GC_TRIGGERS; + } CONTRACTL_END; + + size_t max_object_size; +#ifdef BIT64 + if (g_pConfig->GetGCAllowVeryLargeObjects()) + { + max_object_size = (INT64_MAX - 7 - min_obj_size); + } + else +#endif // BIT64 + { + max_object_size = (INT32_MAX - 7 - min_obj_size); + } + + if (alloc_size >= max_object_size) + { + if (g_pConfig->IsGCBreakOnOOMEnabled()) + { + DebugBreak(); + } + + ThrowOutOfMemoryDimensionsExceeded(); + } +} + // There are only three ways to get into allocate an object. // * Call optimized helpers that were generated on the fly. This is how JIT compiled code does most @@ -98,14 +133,21 @@ inline Object* Alloc(size_t size, BOOL bFinalize, BOOL bContainsPointers ) (bFinalize ? GC_ALLOC_FINALIZE : 0)); Object *retVal = NULL; + CheckObjectSize(size); // We don't want to throw an SO during the GC, so make sure we have plenty // of stack before calling in. INTERIOR_STACK_PROBE_FOR(GetThread(), static_cast(DEFAULT_ENTRY_PROBE_AMOUNT * 1.5)); - if (GCHeap::UseAllocationContexts()) - retVal = GCHeap::GetGCHeap()->Alloc(GetThreadAllocContext(), size, flags); + if (GCHeapUtilities::UseAllocationContexts()) + retVal = GCHeapUtilities::GetGCHeap()->Alloc(GetThreadAllocContext(), size, flags); else - retVal = GCHeap::GetGCHeap()->Alloc(size, flags); + retVal = GCHeapUtilities::GetGCHeap()->Alloc(size, flags); + + if (!retVal) + { + ThrowOutOfMemory(); + } + END_INTERIOR_STACK_PROBE; return retVal; } @@ -126,14 +168,20 @@ inline Object* AllocAlign8(size_t size, BOOL bFinalize, BOOL bContainsPointers, (bAlignBias ? GC_ALLOC_ALIGN8_BIAS : 0)); Object *retVal = NULL; + CheckObjectSize(size); // We don't want to throw an SO during the GC, so make sure we have plenty // of stack before calling in. INTERIOR_STACK_PROBE_FOR(GetThread(), static_cast(DEFAULT_ENTRY_PROBE_AMOUNT * 1.5)); - if (GCHeap::UseAllocationContexts()) - retVal = GCHeap::GetGCHeap()->AllocAlign8(GetThreadAllocContext(), size, flags); + if (GCHeapUtilities::UseAllocationContexts()) + retVal = GCHeapUtilities::GetGCHeap()->AllocAlign8(GetThreadAllocContext(), size, flags); else - retVal = GCHeap::GetGCHeap()->AllocAlign8(size, flags); + retVal = GCHeapUtilities::GetGCHeap()->AllocAlign8(size, flags); + + if (!retVal) + { + ThrowOutOfMemory(); + } END_INTERIOR_STACK_PROBE; return retVal; @@ -169,11 +217,18 @@ inline Object* AllocLHeap(size_t size, BOOL bFinalize, BOOL bContainsPointers ) (bFinalize ? GC_ALLOC_FINALIZE : 0)); Object *retVal = NULL; + CheckObjectSize(size); // We don't want to throw an SO during the GC, so make sure we have plenty // of stack before calling in. INTERIOR_STACK_PROBE_FOR(GetThread(), static_cast(DEFAULT_ENTRY_PROBE_AMOUNT * 1.5)); - retVal = GCHeap::GetGCHeap()->AllocLHeap(size, flags); + retVal = GCHeapUtilities::GetGCHeap()->AllocLHeap(size, flags); + + if (!retVal) + { + ThrowOutOfMemory(); + } + END_INTERIOR_STACK_PROBE; return retVal; } @@ -427,7 +482,7 @@ OBJECTREF AllocateArrayEx(TypeHandle arrayType, INT32 *pArgs, DWORD dwNumArgs, B if (bAllocateInLargeHeap || (totalSize >= LARGE_OBJECT_SIZE)) { - GCHeap::GetGCHeap()->PublishObject((BYTE*)orArray); + GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orArray); } #ifdef _LOGALLOC @@ -651,7 +706,7 @@ OBJECTREF FastAllocatePrimitiveArray(MethodTable* pMT, DWORD cElements, BOOL b if (bPublish) { - GCHeap::GetGCHeap()->PublishObject((BYTE*)orObject); + GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orObject); } // Notify the profiler of the allocation @@ -860,7 +915,7 @@ STRINGREF SlowAllocateString( DWORD cchStringLength ) if (ObjectSize >= LARGE_OBJECT_SIZE) { - GCHeap::GetGCHeap()->PublishObject((BYTE*)orObject); + GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orObject); } // Notify the profiler of the allocation @@ -951,8 +1006,10 @@ OBJECTREF AllocateObject(MethodTable *pMT g_IBCLogger.LogMethodTableAccess(pMT); SetTypeHandleOnThreadForAlloc(TypeHandle(pMT)); +#ifdef FEATURE_CER if (pMT->HasCriticalFinalizer()) PrepareCriticalFinalizerObject(pMT); +#endif #ifdef FEATURE_COMINTEROP #ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION @@ -1000,7 +1057,7 @@ OBJECTREF AllocateObject(MethodTable *pMT if ((baseSize >= LARGE_OBJECT_SIZE)) { orObject->SetMethodTableForLargeObject(pMT); - GCHeap::GetGCHeap()->PublishObject((BYTE*)orObject); + GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orObject); } else { @@ -1234,7 +1291,7 @@ extern "C" HCIMPL2_RAW(VOID, JIT_WriteBarrier, Object **dst, Object *ref) *dst = ref; // If the store above succeeded, "dst" should be in the heap. - assert(GCHeap::GetGCHeap()->IsHeapPointer((void*)dst)); + assert(GCHeapUtilities::GetGCHeap()->IsHeapPointer((void*)dst)); #ifdef WRITE_BARRIER_CHECK updateGCShadow(dst, ref); // support debugging write barrier @@ -1280,7 +1337,7 @@ extern "C" HCIMPL2_RAW(VOID, JIT_WriteBarrierEnsureNonHeapTarget, Object **dst, STATIC_CONTRACT_THROWS; STATIC_CONTRACT_GC_NOTRIGGER; - assert(!GCHeap::GetGCHeap()->IsHeapPointer((void*)dst)); + assert(!GCHeapUtilities::GetGCHeap()->IsHeapPointer((void*)dst)); // no HELPER_METHOD_FRAME because we are MODE_COOPERATIVE, GC_NOTRIGGER diff --git a/src/vm/gchost.cpp b/src/vm/gchost.cpp index 4f7d52f..b51f245 100644 --- a/src/vm/gchost.cpp +++ b/src/vm/gchost.cpp @@ -22,7 +22,7 @@ #include "corhost.h" #include "excep.h" #include "field.h" -#include "gc.h" +#include "gcheaputilities.h" #if !defined(FEATURE_CORECLR) inline size_t SizeInKBytes(size_t cbSize) @@ -48,7 +48,7 @@ HRESULT CorGCHost::_SetGCSegmentSize(SIZE_T SegmentSize) HRESULT hr = S_OK; // Sanity check the value, it must be a power of two and big enough. - if (!GCHeap::IsValidSegmentSize(SegmentSize)) + if (!GCHeapUtilities::GetGCHeap()->IsValidSegmentSize(SegmentSize)) { hr = E_INVALIDARG; } @@ -74,7 +74,7 @@ HRESULT CorGCHost::_SetGCMaxGen0Size(SIZE_T MaxGen0Size) HRESULT hr = S_OK; // Sanity check the value is at least large enough. - if (!GCHeap::IsValidGen0MaxSize(MaxGen0Size)) + if (!GCHeapUtilities::GetGCHeap()->IsValidGen0MaxSize(MaxGen0Size)) { hr = E_INVALIDARG; } @@ -151,7 +151,7 @@ HRESULT CorGCHost::Collect( HRESULT hr = E_FAIL; - if (Generation > (int) GCHeap::GetGCHeap()->GetMaxGeneration()) + if (Generation > (int) GCHeapUtilities::GetGCHeap()->GetMaxGeneration()) hr = E_INVALIDARG; else { @@ -170,7 +170,7 @@ HRESULT CorGCHost::Collect( EX_TRY { - hr = GCHeap::GetGCHeap()->GarbageCollect(Generation); + hr = GCHeapUtilities::GetGCHeap()->GarbageCollect(Generation); } EX_CATCH { @@ -268,7 +268,7 @@ HRESULT CorGCHost::SetVirtualMemLimit( } CONTRACTL_END; - GCHeap::GetGCHeap()->SetReservedVMLimit (sztMaxVirtualMemMB); + GCHeapUtilities::GetGCHeap()->SetReservedVMLimit (sztMaxVirtualMemMB); return (S_OK); } #endif // !defined(FEATURE_CORECLR) diff --git a/src/vm/gcinfodecoder.cpp b/src/vm/gcinfodecoder.cpp index ef237a2..89f4704 100644 --- a/src/vm/gcinfodecoder.cpp +++ b/src/vm/gcinfodecoder.cpp @@ -4,6 +4,7 @@ #include "common.h" + #include "gcinfodecoder.h" #ifdef USE_GC_INFO_DECODER @@ -17,7 +18,7 @@ #endif #ifndef GCINFODECODER_CONTRACT -#define GCINFODECODER_CONTRACT(contract) contract +#define GCINFODECODER_CONTRACT LIMITED_METHOD_CONTRACT #endif // !GCINFODECODER_CONTRACT @@ -68,7 +69,7 @@ } #endif // !LOG_PIPTR -bool GcInfoDecoder::SetIsInterruptibleCB (UINT32 startOffset, UINT32 stopOffset, LPVOID hCallback) +bool GcInfoDecoder::SetIsInterruptibleCB (UINT32 startOffset, UINT32 stopOffset, void * hCallback) { GcInfoDecoder *pThis = (GcInfoDecoder*)hCallback; @@ -282,11 +283,11 @@ GcInfoDecoder::GcInfoDecoder( if (hasReversePInvokeFrame) { - m_ReversePInvokeFrameSlot = (INT32)m_Reader.DecodeVarLengthSigned(REVERSE_PINVOKE_FRAME_ENCBASE); + m_ReversePInvokeFrameStackSlot = (INT32)m_Reader.DecodeVarLengthSigned(REVERSE_PINVOKE_FRAME_ENCBASE); } else { - m_ReversePInvokeFrameSlot = NO_REVERSE_PINVOKE_FRAME; + m_ReversePInvokeFrameStackSlot = NO_REVERSE_PINVOKE_FRAME; } @@ -426,14 +427,14 @@ UINT32 GcInfoDecoder::FindSafePoint(UINT32 breakOffset) return result; } -void GcInfoDecoder::EnumerateSafePoints(EnumerateSafePointsCallback *pCallback, LPVOID hCallback) +void GcInfoDecoder::EnumerateSafePoints(EnumerateSafePointsCallback *pCallback, void * hCallback) { if(m_NumSafePoints == 0) return; const UINT32 numBitsPerOffset = CeilOfLog2(NORMALIZE_CODE_OFFSET(m_CodeLength)); - for(UINT i = 0; i < m_NumSafePoints; i++) + for(UINT32 i = 0; i < m_NumSafePoints; i++) { UINT32 normOffset = (UINT32)m_Reader.Read(numBitsPerOffset); UINT32 offset = DENORMALIZE_CODE_OFFSET(normOffset) + 2; @@ -450,7 +451,7 @@ void GcInfoDecoder::EnumerateSafePoints(EnumerateSafePointsCallback *pCallback, void GcInfoDecoder::EnumerateInterruptibleRanges ( EnumerateInterruptibleRangesCallback *pCallback, - LPVOID hCallback) + void * hCallback) { // If no info is found for the call site, we default to fully-interruptbile LOG((LF_GCROOTS, LL_INFO1000000, "No GC info found for call site at offset %x. Defaulting to fully-interruptible information.\n", (int) m_InstructionOffset)); @@ -488,10 +489,10 @@ INT32 GcInfoDecoder::GetGSCookieStackSlot() return m_GSCookieStackSlot; } -INT32 GcInfoDecoder::GetReversePInvokeStackSlot() +INT32 GcInfoDecoder::GetReversePInvokeFrameStackSlot() { _ASSERTE(m_Flags & DECODE_REVERSE_PINVOKE_VAR); - return m_ReversePInvokeStackSlot; + return m_ReversePInvokeFrameStackSlot; } UINT32 GcInfoDecoder::GetGSCookieValidRangeStart() @@ -581,7 +582,7 @@ bool GcInfoDecoder::EnumerateLiveSlots( bool reportScratchSlots, unsigned inputFlags, GCEnumCallback pCallBack, - LPVOID hCallBack + void * hCallBack ) { @@ -615,24 +616,6 @@ bool GcInfoDecoder::EnumerateLiveSlots( UINT32 normBreakOffset = NORMALIZE_CODE_OFFSET(m_InstructionOffset); -#if 0 - // This is currently disabled because sometimes on IA64 we need - // to make call sites non-interruptible - // TODO: review this -#ifdef _DEBUG - if(!executionAborted) - { - GcInfoDecoder _decoder2( - m_GcInfoAddress, - DECODE_INTERRUPTIBILITY, - m_InstructionOffset - ); - - _ASSERTE(_decoder2.IsInterruptible()); - } -#endif -#endif - // Normalized break offset // Relative to interruptible ranges #if PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED @@ -645,48 +628,6 @@ bool GcInfoDecoder::EnumerateLiveSlots( #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED -#ifndef DISABLE_EH_VECTORS - if(m_SafePointIndex < m_NumSafePoints || executionAborted) - { - // Skip interruptibility information - for(UINT32 i=0; i= normStart && normBreakOffset < normStop) - { - _ASSERTE(pseudoBreakOffset == 0); - _ASSERTE(dbgCountIntersections++ == 0); - pseudoBreakOffset = numInterruptibleLength + normBreakOffset - normStart; - } - numInterruptibleLength += normStopDelta; - lastNormStop = normStop; - } - _ASSERTE(dbgCountIntersections == 1); - } -#else // DISABLE_EH_VECTORS if(m_SafePointIndex < m_NumSafePoints && !executionAborted) { // Skip interruptibility information @@ -736,7 +677,6 @@ bool GcInfoDecoder::EnumerateLiveSlots( goto ExitSuccess; } } -#endif // DISABLE_EH_VECTORS #else // !PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED // Skip interruptibility information @@ -778,52 +718,8 @@ bool GcInfoDecoder::EnumerateLiveSlots( if(executionAborted) { -#ifndef DISABLE_EH_VECTORS - m_Reader.Skip(m_NumSafePoints * numSlots); - - UINT32 numClauses = (UINT32) m_Reader.DecodeVarLengthUnsigned(NUM_EH_CLAUSES_ENCBASE); - - if(numClauses) - { - UINT32 numBitsPerOffset = CeilOfLog2(NORMALIZE_CODE_OFFSET(m_CodeLength)); - - for(UINT32 i = 0; i < numClauses; i++) - { - UINT32 startOffset = (UINT32) DENORMALIZE_CODE_OFFSET(m_Reader.Read(numBitsPerOffset)); - UINT32 stopOffset = (UINT32) DENORMALIZE_CODE_OFFSET(m_Reader.Read(numBitsPerOffset) + 1); - - if(m_InstructionOffset >= startOffset - && m_InstructionOffset < stopOffset) - { - for(UINT32 slotIndex = 0; slotIndex < numSlots; slotIndex++) - { - if(m_Reader.ReadOneFast()) - { - ReportSlotToGC( - slotDecoder, - slotIndex, - pRD, - reportScratchSlots, - inputFlags, - pCallBack, - hCallBack - ); - } - } - } - else - { - m_Reader.Skip(numSlots); - } - } - } - goto ReportUntracked; -#else //DISABLE_EH_VECTORS - _ASSERTE(m_NumSafePoints == 0); m_Reader.Skip(m_NumSafePoints * numSlots); - -#endif //DISABLE_EH_VECTORS } else if( m_SafePointIndex != m_NumSafePoints ) { @@ -891,15 +787,7 @@ bool GcInfoDecoder::EnumerateLiveSlots( else { m_Reader.Skip(m_NumSafePoints * numSlots); - -#ifndef DISABLE_EH_VECTORS - UINT32 numClauses = (UINT32) m_Reader.DecodeVarLengthUnsigned(NUM_EH_CLAUSES_ENCBASE); - UINT32 numBitsPerOffset = CeilOfLog2(NORMALIZE_CODE_OFFSET(m_CodeLength)); - - m_Reader.Skip((numBitsPerOffset * 2 + numSlots) * numClauses); -#endif //DISABLE_EH_VECTORS - } - + } #endif // PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED _ASSERTE(m_NumInterruptibleRanges); @@ -1069,9 +957,7 @@ ReportUntracked: ReportUntrackedSlots(slotDecoder, pRD, inputFlags, pCallBack, hCallBack); } -#ifdef DISABLE_EH_VECTORS ExitSuccess: -#endif return true; } @@ -1080,7 +966,7 @@ void GcInfoDecoder::EnumerateUntrackedSlots( PREGDISPLAY pRD, unsigned inputFlags, GCEnumCallback pCallBack, - LPVOID hCallBack + void * hCallBack ) { _ASSERTE(GC_SLOT_INTERIOR == GC_CALL_INTERIOR); @@ -1114,7 +1000,7 @@ void GcInfoDecoder::ReportUntrackedSlots( PREGDISPLAY pRD, unsigned inputFlags, GCEnumCallback pCallBack, - LPVOID hCallBack + void * hCallBack ) { for(UINT32 slotIndex = slotDecoder.GetNumTracked(); slotIndex < slotDecoder.GetNumSlots(); slotIndex++) @@ -1455,11 +1341,15 @@ OBJECTREF* GcInfoDecoder::GetRegisterSlot( _ASSERTE(regNum >= 0 && regNum <= 16); _ASSERTE(regNum != 4); // rsp +#ifdef FEATURE_REDHAWK + PTR_UIntNative* ppRax = &pRD->pRax; + if (regNum > 4) regNum--; // rsp is skipped in Redhawk RegDisplay +#else // The fields of KNONVOLATILE_CONTEXT_POINTERS are in the same order as // the processor encoding numbers. - ULONGLONG **ppRax; - ppRax = &pRD->pCurrentContextPointers->Rax; + ULONGLONG **ppRax = &pRD->pCurrentContextPointers->Rax; +#endif return (OBJECTREF*)*(ppRax + regNum); } @@ -1476,8 +1366,7 @@ OBJECTREF* GcInfoDecoder::GetCapturedRegister( // The fields of CONTEXT are in the same order as // the processor encoding numbers. - ULONGLONG *pRax; - pRax = &pRD->pCurrentContext->Rax; + ULONGLONG *pRax = &pRD->pCurrentContext->Rax; return (OBJECTREF*)(pRax + regNum); } @@ -1509,7 +1398,7 @@ bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, P #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); - ULONGLONG pSlot = (ULONGLONG) GetStackSlot(spOffset, spBase, pRD); + TADDR pSlot = (TADDR) GetStackSlot(spOffset, spBase, pRD); _ASSERTE(pSlot >= pRD->SP); return (pSlot < pRD->SP + m_SizeOfStackOutgoingAndScratchArea); @@ -1525,12 +1414,9 @@ void GcInfoDecoder::ReportRegisterToGC( // AMD64 PREGDISPLAY pRD, unsigned flags, GCEnumCallback pCallBack, - LPVOID hCallBack) + void * hCallBack) { - GCINFODECODER_CONTRACT(CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - } CONTRACTL_END); + GCINFODECODER_CONTRACT; _ASSERTE(regNum >= 0 && regNum <= 16); _ASSERTE(regNum != 4); // rsp @@ -1624,8 +1510,7 @@ OBJECTREF* GcInfoDecoder::GetCapturedRegister( // The fields of CONTEXT are in the same order as // the processor encoding numbers. - ULONG *pR0; - pR0 = &pRD->pCurrentContext->R0; + ULONG *pR0 = &pRD->pCurrentContext->R0; return (OBJECTREF*)(pR0 + regNum); } @@ -1646,7 +1531,7 @@ bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, P #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); - DWORD pSlot = (DWORD) GetStackSlot(spOffset, spBase, pRD); + TADDR pSlot = (TADDR) GetStackSlot(spOffset, spBase, pRD); _ASSERTE(pSlot >= pRD->SP); return (pSlot < pRD->SP + m_SizeOfStackOutgoingAndScratchArea); @@ -1662,12 +1547,9 @@ void GcInfoDecoder::ReportRegisterToGC( // ARM PREGDISPLAY pRD, unsigned flags, GCEnumCallback pCallBack, - LPVOID hCallBack) + void * hCallBack) { - GCINFODECODER_CONTRACT(CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - } CONTRACTL_END); + GCINFODECODER_CONTRACT; _ASSERTE(regNum >= 0 && regNum <= 14); _ASSERTE(regNum != 13); // sp @@ -1740,7 +1622,7 @@ bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, P #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); - ULONGLONG pSlot = (ULONGLONG) GetStackSlot(spOffset, spBase, pRD); + TADDR pSlot = (TADDR) GetStackSlot(spOffset, spBase, pRD); _ASSERTE(pSlot >= pRD->SP); return (pSlot < pRD->SP + m_SizeOfStackOutgoingAndScratchArea); @@ -1756,12 +1638,9 @@ void GcInfoDecoder::ReportRegisterToGC( // ARM64 PREGDISPLAY pRD, unsigned flags, GCEnumCallback pCallBack, - LPVOID hCallBack) + void * hCallBack) { - GCINFODECODER_CONTRACT(CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - } CONTRACTL_END); + GCINFODECODER_CONTRACT; _ASSERTE(regNum >= 0 && regNum <= 30); _ASSERTE(regNum != 18); @@ -1801,8 +1680,7 @@ OBJECTREF* GcInfoDecoder::GetCapturedRegister( // The fields of CONTEXT are in the same order as // the processor encoding numbers. - DWORD64 *pX0; - pX0 = &pRD->pCurrentContext->X0; + DWORD64 *pX0 = &pRD->pCurrentContext->X0; return (OBJECTREF*)(pX0 + regNum); } @@ -1837,7 +1715,7 @@ void GcInfoDecoder::ReportRegisterToGC( PREGDISPLAY pRD, unsigned flags, GCEnumCallback pCallBack, - LPVOID hCallBack) + void * hCallBack) { _ASSERTE( !"NYI" ); } @@ -1859,7 +1737,7 @@ OBJECTREF* GcInfoDecoder::GetStackSlot( if( GC_SP_REL == spBase ) { - pObjRef = (OBJECTREF*) ((SIZE_T)GetRegdisplaySP(pRD) + spOffset); + pObjRef = (OBJECTREF*) ((SIZE_T)pRD->SP + spOffset); } else if( GC_CALLER_SP_REL == spBase ) { @@ -1916,12 +1794,9 @@ void GcInfoDecoder::ReportStackSlotToGC( PREGDISPLAY pRD, unsigned flags, GCEnumCallback pCallBack, - LPVOID hCallBack) + void * hCallBack) { - GCINFODECODER_CONTRACT(CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - } CONTRACTL_END); + GCINFODECODER_CONTRACT; OBJECTREF* pObjRef = GetStackSlot(spOffset, spBase, pRD); _ASSERTE( IS_ALIGNED( pObjRef, sizeof( Object* ) ) ); diff --git a/src/vm/gcinterface.h b/src/vm/gcinterface.h new file mode 100644 index 0000000..cc70bec --- /dev/null +++ b/src/vm/gcinterface.h @@ -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. +// See the LICENSE file in the project root for more information. + +#include "../gc/gcinterface.h" \ No newline at end of file diff --git a/src/vm/gcstress.h b/src/vm/gcstress.h index 609276e..04487c6 100644 --- a/src/vm/gcstress.h +++ b/src/vm/gcstress.h @@ -280,17 +280,17 @@ namespace _GCStress // GC Trigger policy classes define how a garbage collection is triggered // This is the default GC Trigger policy that simply calls - // GCHeap::StressHeap + // IGCHeap::StressHeap class StressGcTriggerPolicy { public: FORCEINLINE static void Trigger() - { GCHeap::GetGCHeap()->StressHeap(); } + { GCHeapUtilities::GetGCHeap()->StressHeap(); } FORCEINLINE - static void Trigger(::alloc_context* acontext) - { GCHeap::GetGCHeap()->StressHeap(acontext); } + static void Trigger(::gc_alloc_context* acontext) + { GCHeapUtilities::GetGCHeap()->StressHeap(acontext); } }; // This is an overriding GC Trigger policy that triggers a GC by calling @@ -403,7 +403,7 @@ namespace _GCStress // Additionally it switches the GC mode as specified by GcModePolicy, and it // uses GcTriggerPolicy::Trigger(alloc_context*) to actually trigger the GC FORCEINLINE - static void MaybeTrigger(::alloc_context* acontext, DWORD minFastGc = 0) + static void MaybeTrigger(::gc_alloc_context* acontext, DWORD minFastGc = 0) { if (IsEnabled(minFastGc) && GCStressPolicy::IsEnabled()) { @@ -455,7 +455,7 @@ namespace _GCStress public: FORCEINLINE - static void MaybeTrigger(::alloc_context* acontext) + static void MaybeTrigger(::gc_alloc_context* acontext) { GcStressBase::MaybeTrigger(acontext); diff --git a/src/vm/gdbjit.cpp b/src/vm/gdbjit.cpp index 9f9c116..8e72883 100644 --- a/src/vm/gdbjit.cpp +++ b/src/vm/gdbjit.cpp @@ -11,16 +11,323 @@ //***************************************************************************** #include "common.h" +#include "formattype.h" #include "gdbjit.h" #include "gdbjithelpers.h" -struct DebuggerILToNativeMap +TypeInfoBase* +GetTypeInfoFromTypeHandle(TypeHandle typeHandle, NotifyGdb::PTK_TypeInfoMap pTypeMap) { - ULONG ilOffset; - ULONG nativeStartOffset; - ULONG nativeEndOffset; - ICorDebugInfo::SourceTypes source; -}; + TypeInfoBase *typeInfo = nullptr; + TypeKey key = typeHandle.GetTypeKey(); + PTR_MethodTable pMT = typeHandle.GetMethodTable(); + + if (pTypeMap->Lookup(&key, &typeInfo)) + { + return typeInfo; + } + + CorElementType corType = typeHandle.GetSignatureCorElementType(); + switch (corType) + { + case ELEMENT_TYPE_VOID: + case ELEMENT_TYPE_BOOLEAN: + case ELEMENT_TYPE_CHAR: + case ELEMENT_TYPE_I1: + case ELEMENT_TYPE_U1: + case ELEMENT_TYPE_I2: + case ELEMENT_TYPE_U2: + case ELEMENT_TYPE_I4: + case ELEMENT_TYPE_U4: + case ELEMENT_TYPE_I8: + case ELEMENT_TYPE_U8: + case ELEMENT_TYPE_R4: + case ELEMENT_TYPE_R8: + case ELEMENT_TYPE_U: + case ELEMENT_TYPE_I: + typeInfo = new (nothrow) PrimitiveTypeInfo(typeHandle, CorElementTypeToDWEncoding[corType]); + if (typeInfo == nullptr) + return nullptr; + + typeInfo->m_type_size = CorTypeInfo::Size(corType); + + break; + case ELEMENT_TYPE_VALUETYPE: + case ELEMENT_TYPE_CLASS: + { + ApproxFieldDescIterator fieldDescIterator(pMT, + pMT->IsString() ? ApproxFieldDescIterator::INSTANCE_FIELDS : ApproxFieldDescIterator::ALL_FIELDS); + ULONG cFields = fieldDescIterator.Count(); + + typeInfo = new (nothrow) ClassTypeInfo(typeHandle, cFields); + + if (typeInfo == nullptr) + return nullptr; + + typeInfo->m_type_size = typeHandle.AsMethodTable()->GetClass()->GetSize(); + + RefTypeInfo* refTypeInfo = nullptr; + if (!typeHandle.IsValueType()) + { + // name the type + refTypeInfo = new (nothrow) RefTypeInfo(typeHandle, typeInfo); + if (refTypeInfo == nullptr) + { + return nullptr; + } + refTypeInfo->m_type_size = sizeof(TADDR); + refTypeInfo->m_value_type = typeInfo; + refTypeInfo->CalculateName(); + + pTypeMap->Add(refTypeInfo->GetTypeKey(), refTypeInfo); + } + + pTypeMap->Add(typeInfo->GetTypeKey(), typeInfo); + typeInfo->CalculateName(); + + // + // Now fill in the array + // + FieldDesc *pField; + + for (ULONG i = 0; i < cFields; i++) + { + pField = fieldDescIterator.Next(); + ClassTypeInfo *info = static_cast(typeInfo); + + LPCUTF8 szName = pField->GetName(); + info->members[i].m_member_name = new char[strlen(szName) + 1]; + strcpy(info->members[i].m_member_name, szName); + if (!pField->IsStatic()) + { + info->members[i].m_member_offset = (ULONG)pField->GetOffset(); + if (!typeHandle.IsValueType()) + info->members[i].m_member_offset += Object::GetOffsetOfFirstField(); + } + else + { + PTR_BYTE base = 0; + MethodTable* pMT = pField->GetEnclosingMethodTable(); + base = pField->GetBase(); + + // TODO: add support of generics with static fields + if (pField->IsRVA() || !pMT->IsDynamicStatics()) + { + PTR_VOID pAddress = pField->GetStaticAddressHandle((PTR_VOID)dac_cast(base)); + info->members[i].m_static_member_address = dac_cast(pAddress); + } + } + + info->members[i].m_member_type = + GetTypeInfoFromTypeHandle(pField->GetExactFieldType(typeHandle), pTypeMap); + + // handle the System.String case: + // coerce type of the second field into array type + if (pMT->IsString() && i == 1) + { + TypeInfoBase* elemTypeInfo = info->members[1].m_member_type; + TypeInfoBase* arrayTypeInfo = new (nothrow) ArrayTypeInfo(typeHandle.MakeSZArray(), 0, elemTypeInfo); + if (arrayTypeInfo == nullptr) + return nullptr; + info->members[1].m_member_type = arrayTypeInfo; + } + } + if (refTypeInfo) + return refTypeInfo; + else + return typeInfo; + } + case ELEMENT_TYPE_PTR: + case ELEMENT_TYPE_BYREF: + { + TypeInfoBase* valTypeInfo = GetTypeInfoFromTypeHandle(typeHandle.GetTypeParam(), pTypeMap); + typeInfo = new (nothrow) RefTypeInfo(typeHandle, valTypeInfo); + if (typeInfo == nullptr) + return nullptr; + typeInfo->m_type_size = sizeof(TADDR); + typeInfo->m_type_offset = valTypeInfo->m_type_offset; + break; + } + case ELEMENT_TYPE_ARRAY: + case ELEMENT_TYPE_SZARRAY: + { + typeInfo = new (nothrow) ClassTypeInfo(typeHandle, 2); + if (typeInfo == nullptr) + return nullptr; + typeInfo->m_type_size = pMT->GetClass()->GetSize(); + + typeInfo->CalculateName(); + RefTypeInfo *refTypeInfo = new (nothrow) RefTypeInfo(typeHandle, typeInfo); + if (refTypeInfo == nullptr) + { + return nullptr; + } + refTypeInfo->m_type_size = sizeof(TADDR); + refTypeInfo->m_value_type = typeInfo; + refTypeInfo->CalculateName(); + + pTypeMap->Add(refTypeInfo->GetTypeKey(), refTypeInfo); + + TypeInfoBase* lengthTypeInfo = GetTypeInfoFromTypeHandle( + TypeHandle(MscorlibBinder::GetElementType(ELEMENT_TYPE_I4)), pTypeMap); + + TypeInfoBase* valTypeInfo = GetTypeInfoFromTypeHandle(typeHandle.GetTypeParam(), pTypeMap); + TypeInfoBase* arrayTypeInfo = new (nothrow) ArrayTypeInfo(typeHandle, 0, valTypeInfo); + if (arrayTypeInfo == nullptr) + return nullptr; + + ClassTypeInfo *info = static_cast(typeInfo); + + info->members[0].m_member_name = new (nothrow) char[16]; + strcpy(info->members[0].m_member_name, "m_NumComponents"); + info->members[0].m_member_offset = ArrayBase::GetOffsetOfNumComponents(); + info->members[0].m_member_type = lengthTypeInfo; + info->members[0].m_member_type->m_type_size = sizeof(DWORD); + + info->members[1].m_member_name = new (nothrow) char[7]; + strcpy(info->members[1].m_member_name, "m_Data"); + info->members[1].m_member_offset = ArrayBase::GetDataPtrOffset(pMT); + info->members[1].m_member_type = arrayTypeInfo; + info->members[1].m_member_type->m_type_size = sizeof(TADDR); + + return refTypeInfo; + } + default: + ASSERT(0 && "not implemented"); + break; + } + // name the type + if (corType == ELEMENT_TYPE_CHAR) + { + typeInfo->m_type_name = new char[9]; + strcpy(typeInfo->m_type_name, "char16_t"); + } + else + { + typeInfo->CalculateName(); + } + pTypeMap->Add(typeInfo->GetTypeKey(), typeInfo); + return typeInfo; +} + +TypeInfoBase* GetArgTypeInfo(MethodDesc* MethodDescPtr, + NotifyGdb::PTK_TypeInfoMap pTypeMap, + unsigned ilIndex) +{ + MetaSig sig(MethodDescPtr); + TypeHandle th; + if (ilIndex == 0) + { + th = sig.GetRetTypeHandleNT(); + } + else + { + while (--ilIndex) + sig.SkipArg(); + + sig.NextArg(); + th = sig.GetLastTypeHandleNT(); + } + return GetTypeInfoFromTypeHandle(th, pTypeMap); +} + +TypeInfoBase* GetLocalTypeInfo(MethodDesc *MethodDescPtr, + NotifyGdb::PTK_TypeInfoMap pTypeMap, + unsigned ilIndex) +{ + COR_ILMETHOD_DECODER method(MethodDescPtr->GetILHeader()); + if (method.GetLocalVarSigTok()) + { + DWORD cbSigLen; + PCCOR_SIGNATURE pComSig; + + if (FAILED(MethodDescPtr->GetMDImport()->GetSigFromToken(method.GetLocalVarSigTok(), &cbSigLen, &pComSig))) + { + printf("\nInvalid record"); + return nullptr; + } + + _ASSERTE(*pComSig == IMAGE_CEE_CS_CALLCONV_LOCAL_SIG); + + SigTypeContext typeContext(MethodDescPtr, TypeHandle()); + MetaSig sig(pComSig, cbSigLen, MethodDescPtr->GetModule(), &typeContext, MetaSig::sigLocalVars); + if (ilIndex > 0) + { + while (ilIndex--) + sig.SkipArg(); + } + sig.NextArg(); + TypeHandle th = sig.GetLastTypeHandleNT(); + return GetTypeInfoFromTypeHandle(th, pTypeMap); + } + return nullptr; +} + +HRESULT GetArgNameByILIndex(MethodDesc* MethodDescPtr, unsigned index, LPSTR ¶mName) +{ + IMDInternalImport* mdImport = MethodDescPtr->GetMDImport(); + mdParamDef paramToken; + USHORT seq; + DWORD attr; + HRESULT status; + + // Param indexing is 1-based. + ULONG32 mdIndex = index + 1; + + MetaSig sig(MethodDescPtr); + if (sig.HasThis()) + { + mdIndex--; + } + status = mdImport->FindParamOfMethod(MethodDescPtr->GetMemberDef(), mdIndex, ¶mToken); + if (status == S_OK) + { + LPCSTR name; + status = mdImport->GetParamDefProps(paramToken, &seq, &attr, &name); + paramName = new char[strlen(name) + 1]; + strcpy(paramName, name); + } + return status; +} + +// Copy-pasted from src/debug/di/module.cpp +HRESULT FindNativeInfoInILVariable(DWORD dwIndex, + SIZE_T ip, + ICorDebugInfo::NativeVarInfo** nativeInfoList, + unsigned int nativeInfoCount, + ICorDebugInfo::NativeVarInfo** ppNativeInfo) +{ + _ASSERTE(ppNativeInfo != NULL); + *ppNativeInfo = NULL; + int lastGoodOne = -1; + for (unsigned int i = 0; i < (unsigned)nativeInfoCount; i++) + { + if ((*nativeInfoList)[i].varNumber == dwIndex) + { + if ((lastGoodOne == -1) || ((*nativeInfoList)[lastGoodOne].startOffset < (*nativeInfoList)[i].startOffset)) + { + lastGoodOne = i; + } + + if (((*nativeInfoList)[i].startOffset <= ip) && + ((*nativeInfoList)[i].endOffset > ip)) + { + *ppNativeInfo = &((*nativeInfoList)[i]); + + return S_OK; + } + } + } + + if ((lastGoodOne > -1) && ((*nativeInfoList)[lastGoodOne].endOffset == ip)) + { + *ppNativeInfo = &((*nativeInfoList)[lastGoodOne]); + return S_OK; + } + + return CORDBG_E_IL_VAR_NOT_AVAILABLE; +} + BYTE* DebugInfoStoreNew(void * pData, size_t cBytes) { return new (nothrow) BYTE[cBytes]; @@ -30,7 +337,9 @@ BYTE* DebugInfoStoreNew(void * pData, size_t cBytes) HRESULT GetMethodNativeMap(MethodDesc* methodDesc, ULONG32* numMap, - DebuggerILToNativeMap** map) + DebuggerILToNativeMap** map, + ULONG32* pcVars, + ICorDebugInfo::NativeVarInfo** ppVars) { // Use the DebugInfoStore to get IL->Native maps. // It doesn't matter whether we're jitted, ngenned etc. @@ -48,8 +357,8 @@ GetMethodNativeMap(MethodDesc* methodDesc, NULL, // allocator &countMapCopy, &mapCopy, - NULL, - NULL); + pcVars, + ppVars); if (!success) { @@ -83,9 +392,62 @@ GetMethodNativeMap(MethodDesc* methodDesc, return S_OK; } +HRESULT FunctionMember::GetLocalsDebugInfo(NotifyGdb::PTK_TypeInfoMap pTypeMap, + LocalsInfo& locals, + int startNativeOffset) +{ + + ICorDebugInfo::NativeVarInfo* nativeVar = NULL; + int thisOffs = 0; + if (!md->IsStatic()) + { + thisOffs = 1; + } + + int i; + for (i = 0; i < m_num_args - thisOffs; i++) + { + if (FindNativeInfoInILVariable(i + thisOffs, startNativeOffset, &locals.pVars, locals.countVars, &nativeVar) == S_OK) + { + vars[i + thisOffs].m_var_type = GetArgTypeInfo(md, pTypeMap, i + 1); + GetArgNameByILIndex(md, i + thisOffs, vars[i + thisOffs].m_var_name); + vars[i + thisOffs].m_il_index = i; + vars[i + thisOffs].m_native_offset = nativeVar->loc.vlStk.vlsOffset; + vars[i + thisOffs].m_var_abbrev = 6; + } + } + //Add info about 'this' as first argument + if (thisOffs == 1) + { + if (FindNativeInfoInILVariable(0, startNativeOffset, &locals.pVars, locals.countVars, &nativeVar) == S_OK) + { + vars[0].m_var_type = GetTypeInfoFromTypeHandle(TypeHandle(md->GetMethodTable()), pTypeMap); + vars[0].m_var_name = new char[strlen("this") + 1]; + strcpy(vars[0].m_var_name, "this"); + vars[0].m_il_index = 0; + vars[0].m_native_offset = nativeVar->loc.vlStk.vlsOffset; + vars[0].m_var_abbrev = 13; + } + i++; + } + for (; i < m_num_vars; i++) + { + if (FindNativeInfoInILVariable( + i, startNativeOffset, &locals.pVars, locals.countVars, &nativeVar) == S_OK) + { + vars[i].m_var_type = GetLocalTypeInfo(md, pTypeMap, i - m_num_args); + vars[i].m_var_name = new char[strlen(locals.localsName[i - m_num_args]) + 1]; + strcpy(vars[i].m_var_name, locals.localsName[i - m_num_args]); + vars[i].m_il_index = i - m_num_args; + vars[i].m_native_offset = nativeVar->loc.vlStk.vlsOffset; + vars[i].m_var_abbrev = 5; + } + } + return S_OK; +} /* Get mapping of IL offsets to source line numbers */ HRESULT -GetDebugInfoFromPDB(MethodDesc* MethodDescPtr, SymbolsInfo** symInfo, unsigned int &symInfoLen) +GetDebugInfoFromPDB(MethodDesc* MethodDescPtr, SymbolsInfo** symInfo, unsigned int &symInfoLen, LocalsInfo &locals) { DebuggerILToNativeMap* map = NULL; @@ -93,8 +455,8 @@ GetDebugInfoFromPDB(MethodDesc* MethodDescPtr, SymbolsInfo** symInfo, unsigned i if (!getInfoForMethodDelegate) return E_FAIL; - - if (GetMethodNativeMap(MethodDescPtr, &numMap, &map) != S_OK) + + if (GetMethodNativeMap(MethodDescPtr, &numMap, &map, &locals.countVars, &locals.pVars) != S_OK) return E_FAIL; const Module* mod = MethodDescPtr->GetMethodTable()->GetModule(); @@ -105,48 +467,125 @@ GetDebugInfoFromPDB(MethodDesc* MethodDescPtr, SymbolsInfo** symInfo, unsigned i StackScratchBuffer scratch; const char* szModName = modName.GetUTF8(scratch); - MethodDebugInfo* methodDebugInfo = new (nothrow) MethodDebugInfo(); - if (methodDebugInfo == nullptr) - return E_OUTOFMEMORY; + MethodDebugInfo methodDebugInfo; - methodDebugInfo->points = (SequencePointInfo*) CoTaskMemAlloc(sizeof(SequencePointInfo) * numMap); - if (methodDebugInfo->points == nullptr) + methodDebugInfo.points = (SequencePointInfo*) CoTaskMemAlloc(sizeof(SequencePointInfo) * numMap); + if (methodDebugInfo.points == nullptr) return E_OUTOFMEMORY; - methodDebugInfo->size = numMap; + methodDebugInfo.size = numMap; - if (getInfoForMethodDelegate(szModName, MethodDescPtr->GetMemberDef(), *methodDebugInfo) == FALSE) + if (getInfoForMethodDelegate(szModName, MethodDescPtr->GetMemberDef(), methodDebugInfo) == FALSE) return E_FAIL; - symInfoLen = methodDebugInfo->size; - *symInfo = new (nothrow) SymbolsInfo[symInfoLen]; + symInfoLen = numMap; + *symInfo = new (nothrow) SymbolsInfo[numMap]; if (*symInfo == nullptr) return E_FAIL; + locals.size = methodDebugInfo.localsSize; + locals.localsName = new (nothrow) char *[locals.size]; + if (locals.localsName == nullptr) + return E_FAIL; + + for (ULONG32 i = 0; i < locals.size; i++) + { + size_t sizeRequired = WideCharToMultiByte(CP_UTF8, 0, methodDebugInfo.locals[i], -1, NULL, 0, NULL, NULL); + locals.localsName[i] = new (nothrow) char[sizeRequired]; + + int len = WideCharToMultiByte( + CP_UTF8, 0, methodDebugInfo.locals[i], -1, locals.localsName[i], sizeRequired, NULL, NULL); + } - for (ULONG32 i = 0; i < symInfoLen; i++) + for (ULONG32 j = 0; j < numMap; j++) { - for (ULONG32 j = 0; j < numMap; j++) + SymbolsInfo& s = (*symInfo)[j]; + + if (j == 0) { + s.fileName[0] = 0; + s.lineNumber = 0; + s.fileIndex = 0; + } else { + s = (*symInfo)[j - 1]; + } + s.nativeOffset = map[j].nativeStartOffset; + s.ilOffset = map[j].ilOffset; + s.source = map[j].source; + s.lineNumber = 0; + + for (ULONG32 i = 0; i < methodDebugInfo.size; i++) { - if (methodDebugInfo->points[i].ilOffset == map[j].ilOffset) - { - SymbolsInfo& s = (*symInfo)[i]; - const SequencePointInfo& sp = methodDebugInfo->points[i]; + const SequencePointInfo& sp = methodDebugInfo.points[i]; - s.nativeOffset = map[j].nativeStartOffset; - s.ilOffset = map[j].ilOffset; + if (methodDebugInfo.points[i].ilOffset == map[j].ilOffset) + { s.fileIndex = 0; - //wcscpy(s.fileName, sp.fileName); int len = WideCharToMultiByte(CP_UTF8, 0, sp.fileName, -1, s.fileName, sizeof(s.fileName), NULL, NULL); s.fileName[len] = 0; s.lineNumber = sp.lineNumber; + break; } } } - CoTaskMemFree(methodDebugInfo->points); + CoTaskMemFree(methodDebugInfo.points); return S_OK; } +/* LEB128 for 32-bit unsigned integer */ +int Leb128Encode(uint32_t num, char* buf, int size) +{ + int i = 0; + + do + { + uint8_t byte = num & 0x7F; + if (i >= size) + break; + num >>= 7; + if (num != 0) + byte |= 0x80; + buf[i++] = byte; + } + while (num != 0); + + return i; +} + +/* LEB128 for 32-bit signed integer */ +int Leb128Encode(int32_t num, char* buf, int size) +{ + int i = 0; + bool hasMore = true, isNegative = num < 0; + + while (hasMore && i < size) + { + uint8_t byte = num & 0x7F; + num >>= 7; + + if ((num == 0 && (byte & 0x40) == 0) || (num == -1 && (byte & 0x40) == 0x40)) + hasMore = false; + else + byte |= 0x80; + buf[i++] = byte; + } + + return i; +} + +int GetFrameLocation(int nativeOffset, char* bufVarLoc) +{ + char cnvBuf[16] = {0}; + int len = Leb128Encode(static_cast(nativeOffset), cnvBuf, sizeof(cnvBuf)); + bufVarLoc[0] = len + 1; + bufVarLoc[1] = DW_OP_fbreg; + for (int j = 0; j < len; j++) + { + bufVarLoc[j + 2] = cnvBuf[j]; + } + + return len + 2; // We add '2' because first 2 bytes contain length of expression and DW_OP_fbreg operation. +} + // GDB JIT interface typedef enum { @@ -185,11 +624,24 @@ struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 }; /* Predefined section names */ const char* SectionNames[] = { - "", ".text", ".shstrtab", ".debug_str", ".debug_abbrev", ".debug_info", - ".debug_pubnames", ".debug_pubtypes", ".debug_line", ".symtab", ".strtab", "" + "", + ".text", + ".shstrtab", + ".debug_str", + ".debug_abbrev", + ".debug_info", + ".debug_pubnames", + ".debug_pubtypes", + ".debug_line", + ".symtab", + ".strtab" + /* After the last (.strtab) section zero or more .thunk_* sections are generated. + + Each .thunk_* section contains a single .thunk_#. + These symbols are mapped to methods (or trampolines) called by currently compiled method. */ }; -const int SectionNamesCount = sizeof(SectionNames) / sizeof(SectionNames[0]); +const int SectionNamesCount = sizeof(SectionNames) / sizeof(SectionNames[0]); // Does not include .thunk_* sections /* Static data for section headers */ struct SectionHeader { @@ -207,11 +659,12 @@ struct SectionHeader { {SHT_PROGBITS, 0}, {SHT_SYMTAB, 0}, {SHT_STRTAB, 0}, + {SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR} }; /* Static data for .debug_str section */ const char* DebugStrings[] = { - "CoreCLR", "" /* module name */, "" /* module path */, "" /* method name */, "int" + "CoreCLR", "" /* module name */, "" /* module path */ }; const int DebugStringCount = sizeof(DebugStrings) / sizeof(DebugStrings[0]); @@ -221,11 +674,95 @@ const unsigned char AbbrevTable[] = { 1, DW_TAG_compile_unit, DW_CHILDREN_yes, DW_AT_producer, DW_FORM_strp, DW_AT_language, DW_FORM_data2, DW_AT_name, DW_FORM_strp, DW_AT_stmt_list, DW_FORM_sec_offset, 0, 0, - 2, DW_TAG_subprogram, DW_CHILDREN_no, + + 2, DW_TAG_base_type, DW_CHILDREN_no, + DW_AT_name, DW_FORM_strp, DW_AT_encoding, DW_FORM_data1, DW_AT_byte_size, DW_FORM_data1, 0, 0, + + 3, DW_TAG_typedef, DW_CHILDREN_no, DW_AT_name, DW_FORM_strp, DW_AT_decl_file, DW_FORM_data1, DW_AT_decl_line, DW_FORM_data1, - DW_AT_type, DW_FORM_ref4, DW_AT_external, DW_FORM_flag_present, 0, 0, - 3, DW_TAG_base_type, DW_CHILDREN_no, - DW_AT_name, DW_FORM_strp, DW_AT_encoding, DW_FORM_data1, DW_AT_byte_size, DW_FORM_data1,0, 0, + DW_AT_type, DW_FORM_ref4, 0, 0, + + 4, DW_TAG_subprogram, DW_CHILDREN_yes, + DW_AT_name, DW_FORM_strp, DW_AT_linkage_name, DW_FORM_strp, DW_AT_decl_file, DW_FORM_data1, DW_AT_decl_line, DW_FORM_data1, + DW_AT_type, DW_FORM_ref4, DW_AT_external, DW_FORM_flag_present, + DW_AT_low_pc, DW_FORM_addr, DW_AT_high_pc, +#if defined(_TARGET_AMD64_) + DW_FORM_data8, +#elif defined(_TARGET_ARM_) + DW_FORM_data4, +#else +#error Unsupported platform! +#endif + DW_AT_frame_base, DW_FORM_exprloc, 0, 0, + + 5, DW_TAG_variable, DW_CHILDREN_no, + DW_AT_name, DW_FORM_strp, DW_AT_decl_file, DW_FORM_data1, DW_AT_decl_line, DW_FORM_data1, DW_AT_type, + DW_FORM_ref4, DW_AT_location, DW_FORM_exprloc, 0, 0, + + 6, DW_TAG_formal_parameter, DW_CHILDREN_no, + DW_AT_name, DW_FORM_strp, DW_AT_decl_file, DW_FORM_data1, DW_AT_decl_line, DW_FORM_data1, DW_AT_type, + DW_FORM_ref4, DW_AT_location, DW_FORM_exprloc, 0, 0, + + 7, DW_TAG_class_type, DW_CHILDREN_yes, + DW_AT_name, DW_FORM_strp, DW_AT_byte_size, DW_FORM_data1, 0, 0, + + 8, DW_TAG_member, DW_CHILDREN_no, + DW_AT_name, DW_FORM_strp, DW_AT_type, DW_FORM_ref4, DW_AT_data_member_location, DW_FORM_data4, 0, 0, + + 9, DW_TAG_pointer_type, DW_CHILDREN_no, + DW_AT_type, DW_FORM_ref4, DW_AT_byte_size, DW_FORM_data1, 0, 0, + + 10, DW_TAG_array_type, DW_CHILDREN_yes, + DW_AT_type, DW_FORM_ref4, 0, 0, + + 11, DW_TAG_subrange_type, DW_CHILDREN_no, + DW_AT_upper_bound, DW_FORM_exprloc, 0, 0, + + 12, DW_TAG_subprogram, DW_CHILDREN_yes, + DW_AT_name, DW_FORM_strp, DW_AT_linkage_name, DW_FORM_strp, DW_AT_decl_file, DW_FORM_data1, DW_AT_decl_line, DW_FORM_data1, + DW_AT_type, DW_FORM_ref4, DW_AT_external, DW_FORM_flag_present, + DW_AT_low_pc, DW_FORM_addr, DW_AT_high_pc, +#if defined(_TARGET_AMD64_) + DW_FORM_data8, +#elif defined(_TARGET_ARM_) + DW_FORM_data4, +#else +#error Unsupported platform! +#endif + DW_AT_frame_base, DW_FORM_exprloc, DW_AT_object_pointer, DW_FORM_ref4, 0, 0, + + 13, DW_TAG_formal_parameter, DW_CHILDREN_no, + DW_AT_name, DW_FORM_strp, DW_AT_decl_file, DW_FORM_data1, DW_AT_decl_line, DW_FORM_data1, DW_AT_type, + DW_FORM_ref4, DW_AT_location, DW_FORM_exprloc, DW_AT_artificial, DW_FORM_flag_present, 0, 0, + + 14, DW_TAG_member, DW_CHILDREN_no, + DW_AT_name, DW_FORM_strp, DW_AT_type, DW_FORM_ref4, DW_AT_external, DW_FORM_flag_present, 0, 0, + + 15, DW_TAG_variable, DW_CHILDREN_no, DW_AT_specification, DW_FORM_ref4, DW_AT_location, DW_FORM_exprloc, + 0, 0, + + 16, DW_TAG_try_block, DW_CHILDREN_no, + DW_AT_low_pc, DW_FORM_addr, DW_AT_high_pc, +#if defined(_TARGET_AMD64_) + DW_FORM_data8, +#elif defined(_TARGET_ARM_) + DW_FORM_data4, +#else +#error Unsupported platform! +#endif + 0, 0, + + 17, DW_TAG_catch_block, DW_CHILDREN_no, + DW_AT_low_pc, DW_FORM_addr, DW_AT_high_pc, +#if defined(_TARGET_AMD64_) + DW_FORM_data8, +#elif defined(_TARGET_ARM_) + DW_FORM_data4, +#else +#error Unsupported platform! +#endif + 0, 0, + 0 }; @@ -241,73 +778,801 @@ DwarfLineNumHeader LineNumHeader = { }; /* Static data for .debug_info */ -struct __attribute__((packed)) DebugInfo +struct __attribute__((packed)) DebugInfoCU { uint8_t m_cu_abbrev; uint32_t m_prod_off; uint16_t m_lang; uint32_t m_cu_name; uint32_t m_line_num; - +} debugInfoCU = { + 1, 0, DW_LANG_C89, 0, 0 +}; + +struct __attribute__((packed)) DebugInfoTryCatchSub +{ + uint8_t m_sub_abbrev; +#if defined(_TARGET_AMD64_) + uint64_t m_sub_low_pc, m_sub_high_pc; +#elif defined(_TARGET_ARM_) + uint32_t m_sub_low_pc, m_sub_high_pc; +#else +#error Unsupported platform! +#endif +}; + +struct __attribute__((packed)) DebugInfoSub +{ uint8_t m_sub_abbrev; uint32_t m_sub_name; + uint32_t m_linkage_name; uint8_t m_file, m_line; uint32_t m_sub_type; - - uint8_t m_type_abbrev; - uint32_t m_type_name; - uint8_t m_encoding; - uint8_t m_byte_size; -} debugInfo = { - 1, 0, DW_LANG_C89, 0, 0, - 2, 0, 1, 1, 37, - 3, 0, DW_ATE_signed, 4 +#if defined(_TARGET_AMD64_) + uint64_t m_sub_low_pc, m_sub_high_pc; +#elif defined(_TARGET_ARM_) + uint32_t m_sub_low_pc, m_sub_high_pc; +#else +#error Unsupported platform! +#endif + uint8_t m_sub_loc[2]; }; -/* static data for symbol strings */ -const char* SymbolNames[] = { - "", "" +struct __attribute__((packed)) DebugInfoSubMember +{ + DebugInfoSub sub; + uint32_t m_obj_ptr; }; - -/* Create ELF/DWARF debug info for jitted method */ -void NotifyGdb::MethodCompiled(MethodDesc* MethodDescPtr) +// Holder for array of pointers to FunctionMember objects +class FunctionMemberPtrArrayHolder : public NewArrayHolder { - PCODE pCode = MethodDescPtr->GetNativeCode(); +private: + int m_cElements; - if (pCode == NULL) - return; - unsigned int symInfoLen = 0; - NewArrayHolder symInfo = nullptr; + void DeleteElements() + { + for (int i = 0; i < m_cElements; i++) + { + delete this->m_value[i]; + } + } - /* Get method name & size of jitted code */ - LPCUTF8 methodName = MethodDescPtr->GetName(); - EECodeInfo codeInfo(pCode); - TADDR codeSize = codeInfo.GetCodeManager()->GetFunctionSize(codeInfo.GetGCInfoToken()); - -#ifdef _TARGET_ARM_ - pCode &= ~1; // clear thumb flag for debug info -#endif +public: + FunctionMemberPtrArrayHolder() : + NewArrayHolder(), + m_cElements(0) + { + } - /* Get module name */ - const Module* mod = MethodDescPtr->GetMethodTable()->GetModule(); - SString modName = mod->GetFile()->GetPath(); - StackScratchBuffer scratch; - const char* szModName = modName.GetUTF8(scratch); - const char *szModulePath, *szModuleFile; - SplitPathname(szModName, szModulePath, szModuleFile); + bool Alloc(int cElements) + { + FunctionMember** value = new (nothrow) FunctionMember*[cElements]; + if (value == nullptr) + return false; + for (int i = 0; i < cElements; i++) + { + value[i] = nullptr; + } - int length = MultiByteToWideChar(CP_UTF8, 0, szModuleFile, -1, NULL, 0); - if (length == 0) - return; - NewArrayHolder wszModuleFile = new (nothrow) WCHAR[length+1]; - length = MultiByteToWideChar(CP_UTF8, 0, szModuleFile, -1, wszModuleFile, length); + // Clean previous elements + DeleteElements(); - if (length == 0) - return; + NewArrayHolder::operator=(value); + m_cElements = cElements; + return true; + } - static NewArrayHolder wszModuleNames = nullptr; + int GetCount() const + { + return m_cElements; + } + + ~FunctionMemberPtrArrayHolder() + { + DeleteElements(); + } +}; + +static FunctionMemberPtrArrayHolder method; + +struct __attribute__((packed)) DebugInfoType +{ + uint8_t m_type_abbrev; + uint32_t m_type_name; + uint8_t m_encoding; + uint8_t m_byte_size; +}; + +struct __attribute__((packed)) DebugInfoVar +{ + uint8_t m_var_abbrev; + uint32_t m_var_name; + uint8_t m_var_file, m_var_line; + uint32_t m_var_type; +}; + +struct __attribute__((packed)) DebugInfoClassType +{ + uint8_t m_type_abbrev; + uint32_t m_type_name; + uint8_t m_byte_size; +}; + +struct __attribute__((packed)) DebugInfoClassMember +{ + uint8_t m_member_abbrev; + uint32_t m_member_name; + uint32_t m_member_type; +}; + +struct __attribute__((packed)) DebugInfoStaticMember +{ + uint8_t m_member_abbrev; + uint32_t m_member_specification; +}; + + +struct __attribute__((packed)) DebugInfoRefType +{ + uint8_t m_type_abbrev; + uint32_t m_ref_type; + uint8_t m_byte_size; +}; + +struct __attribute__((packed)) DebugInfoArrayType +{ + uint8_t m_abbrev; + uint32_t m_type; +}; + +void TypeInfoBase::DumpStrings(char* ptr, int& offset) +{ + if (ptr != nullptr) + { + strcpy(ptr + offset, m_type_name); + m_type_name_offset = offset; + } + offset += strlen(m_type_name) + 1; +} + +void TypeInfoBase::CalculateName() +{ + // name the type + SString sName; + typeHandle.GetName(sName); + StackScratchBuffer buffer; + const UTF8 *utf8 = sName.GetUTF8(buffer); + m_type_name = new char[strlen(utf8) + 1]; + strcpy(m_type_name, utf8); +} + +void TypeInfoBase::SetTypeHandle(TypeHandle handle) +{ + typeHandle = handle; + typeKey = handle.GetTypeKey(); +} + +TypeHandle TypeInfoBase::GetTypeHandle() +{ + return typeHandle; +} + +TypeKey* TypeInfoBase::GetTypeKey() +{ + return &typeKey; +} + +void PrimitiveTypeInfo::DumpDebugInfo(char* ptr, int& offset) +{ + if (m_type_offset != 0) + { + return; + } + + if (ptr != nullptr) + { + DebugInfoType bufType; + bufType.m_type_abbrev = 2; + bufType.m_type_name = m_type_name_offset; + bufType.m_encoding = m_type_encoding; + bufType.m_byte_size = m_type_size; + + memcpy(ptr + offset, + &bufType, + sizeof(DebugInfoType)); + m_type_offset = offset; + } + + offset += sizeof(DebugInfoType); +} + +ClassTypeInfo::ClassTypeInfo(TypeHandle typeHandle, int num_members) + : TypeInfoBase(typeHandle), + m_num_members(num_members), + members(new TypeMember[num_members]) +{ +} + +ClassTypeInfo::~ClassTypeInfo() +{ + if (members != nullptr && m_num_members > 0) + { + delete[] members; + } +} + +void TypeMember::DumpStrings(char* ptr, int& offset) +{ + if (ptr != nullptr) + { + strcpy(ptr + offset, m_member_name); + m_member_name_offset = offset; + } + offset += strlen(m_member_name) + 1; +} + +void TypeMember::DumpDebugInfo(char* ptr, int& offset) +{ + if (ptr != nullptr) + { + DebugInfoClassMember memberEntry; + + if (m_static_member_address == 0) + memberEntry.m_member_abbrev = 8; + else + { + memberEntry.m_member_abbrev = 14; + m_member_offset = offset; + } + memberEntry.m_member_name = m_member_name_offset; + memberEntry.m_member_type = m_member_type->m_type_offset; + + memcpy(ptr + offset, &memberEntry, sizeof(DebugInfoClassMember)); + if (m_static_member_address == 0) + memcpy(ptr + offset + sizeof(DebugInfoClassMember), &m_member_offset, sizeof(m_member_offset)); + } + offset += sizeof(DebugInfoClassMember); + if (m_static_member_address == 0) + offset += sizeof(m_member_offset); +} + +void TypeMember::DumpStaticDebugInfo(char* ptr, int& offset) +{ + const int ptrSize = sizeof(TADDR); + if (ptr != nullptr) + { + DebugInfoStaticMember memberEntry; + + memberEntry.m_member_abbrev = 15; + memberEntry.m_member_specification = m_member_offset; + memcpy(ptr + offset, &memberEntry, sizeof(DebugInfoStaticMember)); + + char buf[ptrSize + 2] = {0}; + buf[0] = ptrSize + 1; + buf[1] = DW_OP_addr; + + for (int i = 0; i < ptrSize; i++) + { + buf[i + 2] = m_static_member_address >> (i * 8); + } + + memcpy(ptr + offset + sizeof(DebugInfoStaticMember), &buf, ptrSize + 2); + } + offset += sizeof(DebugInfoStaticMember); + offset += ptrSize + 2; +} + +void FunctionMember::MangleName(char *buf, int &buf_offset, const char *name) +{ + int name_length = strlen(name); + + char tmp[20]; + int tmp_len = sprintf_s(tmp, _countof(tmp), "%i", name_length); + if (tmp_len <= 0) + return; + + if (buf) + strncpy(buf + buf_offset, tmp, tmp_len); + buf_offset += tmp_len; + + if (buf) + { + for (int i = 0; i < name_length; i++) + { + char c = name[i]; + bool valid = (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9'); + *(buf + buf_offset + i) = valid ? c : '_'; + } + } + buf_offset += name_length; +} + +void FunctionMember::DumpMangledNamespaceAndMethod(char *buf, int &offset, const char *nspace, const char *mname) +{ + static const char *begin_mangled = "_ZN"; + static const char *end_mangled = "Ev"; + static const int begin_mangled_len = strlen(begin_mangled); + static const int end_mangled_len = strlen(end_mangled); + + if (buf) + strncpy(buf + offset, begin_mangled, begin_mangled_len); + offset += begin_mangled_len; + + MangleName(buf, offset, nspace); + MangleName(buf, offset, mname); + + if (buf) + strncpy(buf + offset, end_mangled, end_mangled_len); + offset += end_mangled_len; + + if (buf) + buf[offset] = '\0'; + ++offset; +} + +void FunctionMember::DumpLinkageName(char* ptr, int& offset) +{ + SString namespaceOrClassName; + SString methodName; + + md->GetMethodInfoNoSig(namespaceOrClassName, methodName); + SString utf8namespaceOrClassName; + SString utf8methodName; + namespaceOrClassName.ConvertToUTF8(utf8namespaceOrClassName); + methodName.ConvertToUTF8(utf8methodName); + + const char *nspace = utf8namespaceOrClassName.GetUTF8NoConvert(); + const char *mname = utf8methodName.GetUTF8NoConvert(); + + if (!nspace || !mname) + { + m_linkage_name_offset = 0; + return; + } + + m_linkage_name_offset = offset; + DumpMangledNamespaceAndMethod(ptr, offset, nspace, mname); +} + +void FunctionMember::DumpStrings(char* ptr, int& offset) +{ + TypeMember::DumpStrings(ptr, offset); + + for (int i = 0; i < m_num_vars; ++i) + { + vars[i].DumpStrings(ptr, offset); + } + + DumpLinkageName(ptr, offset); +} + +bool FunctionMember::GetBlockInNativeCode(int blockILOffset, int blockILLen, TADDR *startOffset, TADDR *endOffset) +{ + PCODE pCode = md->GetNativeCode(); + + const int blockILEnd = blockILOffset + blockILLen; + + *startOffset = 0; + *endOffset = 0; + + bool inBlock = false; + + for (int i = 0; i < nlines; ++i) + { + TADDR nativeOffset = lines[i].nativeOffset + pCode; + + // Limit block search to current function addresses + if (nativeOffset < m_sub_low_pc) + continue; + if (nativeOffset >= m_sub_low_pc + m_sub_high_pc) + break; + + // Skip invalid IL offsets + switch(lines[i].ilOffset) + { + case ICorDebugInfo::PROLOG: + case ICorDebugInfo::EPILOG: + case ICorDebugInfo::NO_MAPPING: + continue; + default: + break; + } + + // Check if current IL is within block + if (blockILOffset <= lines[i].ilOffset && lines[i].ilOffset < blockILEnd) + { + if (!inBlock) + { + *startOffset = lines[i].nativeOffset; + inBlock = true; + } + } + else + { + if (inBlock) + { + *endOffset = lines[i].nativeOffset; + inBlock = false; + break; + } + } + } + + if (inBlock) + { + *endOffset = m_sub_low_pc + m_sub_high_pc - pCode; + } + + return *endOffset != *startOffset; +} + +void FunctionMember::DumpTryCatchBlock(char* ptr, int& offset, int ilOffset, int ilLen, int abbrev) +{ + TADDR startOffset; + TADDR endOffset; + + if (!GetBlockInNativeCode(ilOffset, ilLen, &startOffset, &endOffset)) + return; + + if (ptr != nullptr) + { + DebugInfoTryCatchSub subEntry; + + subEntry.m_sub_abbrev = abbrev; + subEntry.m_sub_low_pc = md->GetNativeCode() + startOffset; + subEntry.m_sub_high_pc = endOffset - startOffset; + + memcpy(ptr + offset, &subEntry, sizeof(DebugInfoTryCatchSub)); + } + offset += sizeof(DebugInfoTryCatchSub); +} + +void FunctionMember::DumpTryCatchDebugInfo(char* ptr, int& offset) +{ + if (!md) + return; + + COR_ILMETHOD *pHeader = md->GetILHeader(); + COR_ILMETHOD_DECODER header(pHeader); + + unsigned ehCount = header.EHCount(); + + for (unsigned e = 0; e < ehCount; e++) + { + IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT ehBuff; + const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* ehInfo; + + ehInfo = header.EH->EHClause(e, &ehBuff); + + DumpTryCatchBlock(ptr, offset, ehInfo->TryOffset, ehInfo->TryLength, 16); + DumpTryCatchBlock(ptr, offset, ehInfo->HandlerOffset, ehInfo->HandlerLength, 17); + } +} + +void FunctionMember::DumpDebugInfo(char* ptr, int& offset) +{ + if (ptr != nullptr) + { + DebugInfoSub subEntry; + + subEntry.m_sub_abbrev = 4; + subEntry.m_sub_name = m_member_name_offset; + subEntry.m_linkage_name = m_linkage_name_offset; + subEntry.m_file = m_file; + subEntry.m_line = m_line; + subEntry.m_sub_type = m_member_type->m_type_offset; + subEntry.m_sub_low_pc = m_sub_low_pc; + subEntry.m_sub_high_pc = m_sub_high_pc; + subEntry.m_sub_loc[0] = m_sub_loc[0]; + subEntry.m_sub_loc[1] = m_sub_loc[1]; + + if (!md->IsStatic()) + { + DebugInfoSubMember subMemberEntry; + subEntry.m_sub_abbrev = 12; + subMemberEntry.sub = subEntry; + subMemberEntry.m_obj_ptr = offset+sizeof(DebugInfoSubMember); + memcpy(ptr + offset, &subMemberEntry, sizeof(DebugInfoSubMember)); + } + else + { + memcpy(ptr + offset, &subEntry, sizeof(DebugInfoSub)); + } + m_entry_offset = offset; + dumped = true; + } + + if (!md->IsStatic()) + { + offset += sizeof(DebugInfoSubMember); + } + else + { + offset += sizeof(DebugInfoSub); + } + for (int i = 0; i < m_num_vars; ++i) + { + vars[i].DumpDebugInfo(ptr, offset); + } + + DumpTryCatchDebugInfo(ptr, offset); + + // terminate children + if (ptr != nullptr) + { + ptr[offset] = 0; + } + offset++; +} + +int FunctionMember::GetArgsAndLocalsLen() +{ + int locSize = 0; + char tmpBuf[16]; + + // Format for DWARF location expression: [expression length][operation][offset in SLEB128 encoding] + for (int i = 0; i < m_num_vars; i++) + { + locSize += 2; // First byte contains expression length, second byte contains operation (DW_OP_fbreg). + locSize += Leb128Encode(static_cast(vars[i].m_native_offset), tmpBuf, sizeof(tmpBuf)); + } + return locSize; +} + +void ClassTypeInfo::DumpStrings(char* ptr, int& offset) +{ + TypeInfoBase::DumpStrings(ptr, offset); + + for (int i = 0; i < m_num_members; ++i) + { + members[i].DumpStrings(ptr, offset); + } +} + +void RefTypeInfo::DumpStrings(char* ptr, int& offset) +{ + TypeInfoBase::DumpStrings(ptr, offset); + m_value_type->DumpStrings(ptr, offset); +} + +void RefTypeInfo::DumpDebugInfo(char* ptr, int& offset) +{ + if (m_type_offset != 0) + { + return; + } + m_type_offset = offset; + offset += sizeof(DebugInfoRefType); + m_value_type->DumpDebugInfo(ptr, offset); + if (ptr != nullptr) + { + DebugInfoRefType refType; + refType.m_type_abbrev = 9; + refType.m_ref_type = m_value_type->m_type_offset; + refType.m_byte_size = m_type_size; + memcpy(ptr + m_type_offset, &refType, sizeof(DebugInfoRefType)); + } + else + { + m_type_offset = 0; + } +} +void ClassTypeInfo::DumpDebugInfo(char* ptr, int& offset) +{ + if (m_type_offset != 0) + { + return; + } + // make sure that types of all members are dumped + for (int i = 0; i < m_num_members; ++i) + { + if (members[i].m_member_type->m_type_offset == 0 && members[i].m_member_type != this) + { + members[i].m_member_type->DumpDebugInfo(ptr, offset); + } + } + + if (ptr != nullptr) + { + DebugInfoClassType bufType; + bufType.m_type_abbrev = 7; + bufType.m_type_name = m_type_name_offset; + bufType.m_byte_size = m_type_size; + + memcpy(ptr + offset, &bufType, sizeof(DebugInfoClassType)); + m_type_offset = offset; + } + offset += sizeof(DebugInfoClassType); + + for (int i = 0; i < m_num_members; ++i) + { + members[i].DumpDebugInfo(ptr, offset); + } + + for (int i = 0; i < method.GetCount(); ++i) + { + if (method[i]->md->GetMethodTable() == GetTypeHandle().GetMethodTable()) + { + // our method is part of this class, we should dump it now before terminating members + method[i]->DumpDebugInfo(ptr, offset); + } + } + + // members terminator + if (ptr != nullptr) + { + ptr[offset] = 0; + } + offset++; + + for (int i = 0; i < m_num_members; ++i) + { + if (members[i].m_static_member_address != 0) + members[i].DumpStaticDebugInfo(ptr, offset); + } + +} + +void ArrayTypeInfo::DumpDebugInfo(char* ptr, int& offset) +{ + if (m_type_offset != 0) + { + return; + } + if (m_elem_type->m_type_offset == 0) + { + m_elem_type->DumpDebugInfo(ptr, offset); + } + if (ptr != nullptr) + { + DebugInfoArrayType arrType; + + arrType.m_abbrev = 10; // DW_TAG_array_type abbrev + arrType.m_type = m_elem_type->m_type_offset; + + memcpy(ptr + offset, &arrType, sizeof(DebugInfoArrayType)); + m_type_offset = offset; + } + offset += sizeof(DebugInfoArrayType); + + char tmp[16] = { 0 }; + int len = Leb128Encode(static_cast(m_count_offset), tmp, sizeof(tmp)); + if (ptr != nullptr) + { + char buf[64]; + buf[0] = 11; // DW_TAG_subrange_type abbrev + buf[1] = len + 3; + buf[2] = DW_OP_push_object_address; + buf[3] = DW_OP_plus_uconst; + for (int j = 0; j < len; j++) + { + buf[j + 4] = tmp[j]; + } + buf[len + 4] = DW_OP_deref; + + memcpy(ptr + offset, buf, len + 5); + } + offset += (len + 5); + + if (ptr != nullptr) + { + memset(ptr + offset, 0, 1); + } + offset += 1; +} + +void VarDebugInfo::DumpStrings(char *ptr, int& offset) +{ + if (ptr != nullptr) + { + strcpy(ptr + offset, m_var_name); + m_var_name_offset = offset; + } + offset += strlen(m_var_name) + 1; +} + +void VarDebugInfo::DumpDebugInfo(char* ptr, int& offset) +{ + char bufVarLoc[16]; + int len = GetFrameLocation(m_native_offset, bufVarLoc); + if (ptr != nullptr) + { + DebugInfoVar bufVar; + + bufVar.m_var_abbrev = m_var_abbrev; + bufVar.m_var_name = m_var_name_offset; + bufVar.m_var_file = 1; + bufVar.m_var_line = 1; + bufVar.m_var_type = m_var_type->m_type_offset; + memcpy(ptr + offset, &bufVar, sizeof(DebugInfoVar)); + memcpy(ptr + offset + sizeof(DebugInfoVar), bufVarLoc, len); + } + offset += sizeof(DebugInfoVar); + offset += len; +} + +/* static data for symbol strings */ +struct Elf_Symbol { + const char* m_name; + int m_off; + TADDR m_value; + int m_section, m_size; + bool m_releaseName; + Elf_Symbol() : m_name(nullptr), m_off(0), m_value(0), m_section(0), m_size(0), m_releaseName(false) {} + ~Elf_Symbol() + { + if (m_releaseName) + delete [] m_name; + } +}; + +static int countFuncs(const SymbolsInfo *lines, int nlines) +{ + int count = 0; + for (int i = 0; i < nlines; i++) { + if (lines[i].ilOffset == ICorDebugInfo::PROLOG) + { + count++; + } + } + return count; +} + +static int getNextPrologueIndex(int from, const SymbolsInfo *lines, int nlines) +{ + for (int i = from; i < nlines; ++i) { + if (lines[i].ilOffset == ICorDebugInfo::PROLOG) + { + return i; + } + } + return -1; +} + +int SymbolCount = 0; +NewArrayHolder SymbolNames; +NotifyGdb::AddrSet codeAddrs; + +/* Create ELF/DWARF debug info for jitted method */ +void NotifyGdb::MethodCompiled(MethodDesc* MethodDescPtr) +{ + PCODE pCode = MethodDescPtr->GetNativeCode(); + if (pCode == NULL) + return; + unsigned int symInfoLen = 0; + NewArrayHolder symInfo = nullptr; + LocalsInfo locals; + + /* Get method name & size of jitted code */ + LPCUTF8 methodName = MethodDescPtr->GetName(); + EECodeInfo codeInfo(pCode); + TADDR codeSize = codeInfo.GetCodeManager()->GetFunctionSize(codeInfo.GetGCInfoToken()); + + pCode = PCODEToPINSTR(pCode); + + /* Get module name */ + const Module* mod = MethodDescPtr->GetMethodTable()->GetModule(); + SString modName = mod->GetFile()->GetPath(); + StackScratchBuffer scratch; + const char* szModName = modName.GetUTF8(scratch); + const char *szModulePath, *szModuleFile; + SplitPathname(szModName, szModulePath, szModuleFile); + + + int length = MultiByteToWideChar(CP_UTF8, 0, szModuleFile, -1, NULL, 0); + if (length == 0) + return; + NewArrayHolder wszModuleFile = new (nothrow) WCHAR[length+1]; + length = MultiByteToWideChar(CP_UTF8, 0, szModuleFile, -1, wszModuleFile, length); + + if (length == 0) + return; + + static NewArrayHolder wszModuleNames = nullptr; DWORD cCharsNeeded = 0; // Get names of interesting modules from environment @@ -356,14 +1621,81 @@ void NotifyGdb::MethodCompiled(MethodDesc* MethodDescPtr) } } - if (isUserDebug == FALSE) + if (isUserDebug == FALSE) + { + return; + } + + NewHolder pTypeMap = new TK_TypeInfoMap(); + + if (pTypeMap == nullptr) + { + return; + } + + /* Get debug info for method from portable PDB */ + HRESULT hr = GetDebugInfoFromPDB(MethodDescPtr, &symInfo, symInfoLen, locals); + if (FAILED(hr) || symInfoLen == 0) + { + return; + } + + int method_count = countFuncs(symInfo, symInfoLen); + if (!method.Alloc(method_count)) { + return; + } + + CodeHeader* pCH = (CodeHeader*)pCode - 1; + CalledMethod* pCalledMethods = reinterpret_cast(pCH->GetCalledMethods()); + /* Collect addresses of thunks called by method */ + if (!CollectCalledMethods(pCalledMethods, (TADDR)MethodDescPtr->GetNativeCode())) + { + return; + } + pCH->SetCalledMethods(NULL); + + MetaSig sig(MethodDescPtr); + int nArgsCount = sig.NumFixedArgs(); + if (sig.HasThis()) + nArgsCount++; + + unsigned int firstLineIndex = 0; + for (;firstLineIndex < symInfoLen; firstLineIndex++) { + if (symInfo[firstLineIndex].lineNumber != 0 && symInfo[firstLineIndex].lineNumber != HiddenLine) break; + } + + if (firstLineIndex >= symInfoLen) + { return; + } - /* Get debug info for method from portable PDB */ - HRESULT hr = GetDebugInfoFromPDB(MethodDescPtr, &symInfo, symInfoLen); - if (FAILED(hr) || symInfoLen == 0) + int start_index = getNextPrologueIndex(0, symInfo, symInfoLen); + + for (int method_index = 0; method_index < method.GetCount(); ++method_index) { - return; + method[method_index] = new FunctionMember(MethodDescPtr, locals.size, nArgsCount); + + int end_index = getNextPrologueIndex(start_index + 1, symInfo, symInfoLen); + + PCODE method_start = symInfo[start_index].nativeOffset; + TADDR method_size = end_index == -1 ? codeSize - method_start : symInfo[end_index].nativeOffset - method_start; + + // method return type + method[method_index]->m_member_type = GetArgTypeInfo(MethodDescPtr, pTypeMap, 0); + method[method_index]->GetLocalsDebugInfo(pTypeMap, locals, symInfo[firstLineIndex].nativeOffset); + method[method_index]->m_sub_low_pc = pCode + method_start; + method[method_index]->m_sub_high_pc = method_size; + size_t methodNameSize = strlen(methodName) + 10; + method[method_index]->m_member_name = new char[methodNameSize]; + if (method_index == 0) + sprintf_s(method[method_index]->m_member_name, methodNameSize, "%s", methodName); + else + sprintf_s(method[method_index]->m_member_name, methodNameSize, "%s_%i", methodName, method_index); + + // method's class + GetTypeInfoFromTypeHandle(TypeHandle(method[method_index]->md->GetMethodTable()), pTypeMap); + + start_index = end_index; } MemBuf elfHeader, sectHeaders, sectStr, sectSymTab, sectStrTab, dbgInfo, dbgAbbrev, dbgPubname, dbgPubType, dbgLine, @@ -374,42 +1706,52 @@ void NotifyGdb::MethodCompiled(MethodDesc* MethodDescPtr) { return; } - + /* Build .debug_line section */ - if (!BuildLineTable(dbgLine, pCode, symInfo, symInfoLen)) + if (!BuildLineTable(dbgLine, pCode, codeSize, symInfo, symInfoLen)) { return; } DebugStrings[1] = szModuleFile; - DebugStrings[3] = methodName; /* Build .debug_str section */ - if (!BuildDebugStrings(dbgStr)) + if (!BuildDebugStrings(dbgStr, pTypeMap)) { return; } /* Build .debug_info section */ - if (!BuildDebugInfo(dbgInfo)) + if (!BuildDebugInfo(dbgInfo, pTypeMap, symInfo, symInfoLen)) { return; } - + + for (int i = 0; i < locals.size; i++) + { + delete[] locals.localsName[i]; + } /* Build .debug_pubname section */ - if (!BuildDebugPub(dbgPubname, methodName, dbgInfo.MemSize, 26)) + if (!BuildDebugPub(dbgPubname, methodName, dbgInfo.MemSize, 0x28)) { return; } /* Build debug_pubtype section */ - if (!BuildDebugPub(dbgPubType, "int", dbgInfo.MemSize, 37)) + if (!BuildDebugPub(dbgPubType, "int", dbgInfo.MemSize, 0x1a)) { return; } - + /* Build .strtab section */ - SymbolNames[1] = methodName; + SymbolNames[0].m_name = ""; + for (int i = 0; i < method.GetCount(); ++i) + { + SymbolNames[1 + i].m_name = method[i]->m_member_name; + SymbolNames[1 + i].m_value = method[i]->m_sub_low_pc; + SymbolNames[1 + i].m_section = 1; + SymbolNames[1 + i].m_size = method[i]->m_sub_high_pc; + } if (!BuildStringTableSection(sectStrTab)) { return; @@ -420,15 +1762,8 @@ void NotifyGdb::MethodCompiled(MethodDesc* MethodDescPtr) return; } - - /* Build section names section */ - if (!BuildSectionNameTable(sectStr)) - { - return; - } - - /* Build section headers table */ - if (!BuildSectionTable(sectHeaders)) + /* Build section headers table and section names table */ + if (!BuildSectionTables(sectHeaders, sectStr)) { return; } @@ -470,13 +1805,21 @@ void NotifyGdb::MethodCompiled(MethodDesc* MethodDescPtr) ++pShdr; // .symtab pShdr->sh_offset = offset; pShdr->sh_size = sectSymTab.MemSize; - pShdr->sh_link = 10; + pShdr->sh_link = GetSectionIndex(".strtab"); offset += sectSymTab.MemSize; ++pShdr; // .strtab pShdr->sh_offset = offset; pShdr->sh_size = sectStrTab.MemSize; offset += sectStrTab.MemSize; - + + // .thunks + for (int i = 1 + method.GetCount(); i < SymbolCount; i++) + { + ++pShdr; + pShdr->sh_addr = PCODEToPINSTR(SymbolNames[i].m_value); + pShdr->sh_size = 8; + } + /* Build ELF header */ if (!BuildELFHeader(elfHeader)) { @@ -493,8 +1836,9 @@ void NotifyGdb::MethodCompiled(MethodDesc* MethodDescPtr) #endif header->e_shoff = offset; header->e_shentsize = sizeof(Elf_Shdr); - header->e_shnum = SectionNamesCount - 1; - header->e_shstrndx = 2; + int thunks_count = SymbolCount - method.GetCount() - 1; + header->e_shnum = SectionNamesCount + thunks_count; + header->e_shstrndx = GetSectionIndex(".shstrtab"); /* Build ELF image in memory */ elfFile.MemSize = elfHeader.MemSize + sectStr.MemSize + dbgStr.MemSize + dbgAbbrev.MemSize + dbgInfo.MemSize + @@ -531,12 +1875,14 @@ void NotifyGdb::MethodCompiled(MethodDesc* MethodDescPtr) memcpy(elfFile.MemPtr + offset, sectHeaders.MemPtr, sectHeaders.MemSize); + elfFile.MemPtr.SuppressRelease(); + #ifdef GDBJIT_DUMPELF DumpElf(methodName, elfFile); -#endif - +#endif + /* Create GDB JIT structures */ - jit_code_entry* jit_symbols = new (nothrow) jit_code_entry; + NewHolder jit_symbols = new (nothrow) jit_code_entry; if (jit_symbols == nullptr) { @@ -557,15 +1903,21 @@ void NotifyGdb::MethodCompiled(MethodDesc* MethodDescPtr) head->prev_entry = jit_symbols; } + jit_symbols.SuppressRelease(); + /* Notify the debugger */ __jit_debug_descriptor.relevant_entry = jit_symbols; __jit_debug_descriptor.action_flag = JIT_REGISTER_FN; __jit_debug_register_code(); - } void NotifyGdb::MethodDropped(MethodDesc* MethodDescPtr) { + static const int textSectionIndex = GetSectionIndex(".text"); + + if (textSectionIndex < 0) + return; + PCODE pCode = MethodDescPtr->GetNativeCode(); if (pCode == NULL) @@ -579,7 +1931,7 @@ void NotifyGdb::MethodDropped(MethodDesc* MethodDescPtr) const Elf_Ehdr* pEhdr = reinterpret_cast(ptr); const Elf_Shdr* pShdr = reinterpret_cast(ptr + pEhdr->e_shoff); - ++pShdr; // bump to .text section + pShdr += textSectionIndex; // bump to .text section if (pShdr->sh_addr == pCode) { /* Notify the debugger */ @@ -602,7 +1954,7 @@ void NotifyGdb::MethodDropped(MethodDesc* MethodDescPtr) } /* Build the DWARF .debug_line section */ -bool NotifyGdb::BuildLineTable(MemBuf& buf, PCODE startAddr, SymbolsInfo* lines, unsigned nlines) +bool NotifyGdb::BuildLineTable(MemBuf& buf, PCODE startAddr, TADDR codeSize, SymbolsInfo* lines, unsigned nlines) { MemBuf fileTable, lineProg; @@ -610,7 +1962,7 @@ bool NotifyGdb::BuildLineTable(MemBuf& buf, PCODE startAddr, SymbolsInfo* lines, if (!BuildFileTable(fileTable, lines, nlines)) return false; /* Build line info program */ - if (!BuildLineProg(lineProg, startAddr, lines, nlines)) + if (!BuildLineProg(lineProg, startAddr, codeSize, lines, nlines)) { return false; } @@ -640,7 +1992,7 @@ bool NotifyGdb::BuildLineTable(MemBuf& buf, PCODE startAddr, SymbolsInfo* lines, /* Buid the source files table for DWARF source line info */ bool NotifyGdb::BuildFileTable(MemBuf& buf, SymbolsInfo* lines, unsigned nlines) { - const char** files = nullptr; + NewArrayHolder files = nullptr; unsigned nfiles = 0; /* GetValue file names and replace them with indices in file table */ @@ -649,6 +2001,8 @@ bool NotifyGdb::BuildFileTable(MemBuf& buf, SymbolsInfo* lines, unsigned nlines) return false; for (unsigned i = 0; i < nlines; ++i) { + if (lines[i].fileName[0] == 0) + continue; const char *filePath, *fileName; SplitPathname(lines[i].fileName, filePath, fileName); @@ -686,7 +2040,6 @@ bool NotifyGdb::BuildFileTable(MemBuf& buf, SymbolsInfo* lines, unsigned nlines) if (buf.MemPtr == nullptr) { - delete[] files; return false; } @@ -704,7 +2057,6 @@ bool NotifyGdb::BuildFileTable(MemBuf& buf, SymbolsInfo* lines, unsigned nlines) // final zero byte *ptr = 0; - delete[] files; return true; } @@ -742,44 +2094,77 @@ void NotifyGdb::IssueParamCommand(char*& ptr, uint8_t command, char* param, int } } -/* Special command moves address, line number and issue one row to source line matrix */ -void NotifyGdb::IssueSpecialCommand(char*& ptr, int8_t line_shift, uint8_t addr_shift) -{ - *ptr++ = (line_shift - DWARF_LINE_BASE) + addr_shift * DWARF_LINE_RANGE + DWARF_OPCODE_BASE; -} - -/* Check to see if given shifts are fit into one byte command */ -bool NotifyGdb::FitIntoSpecialOpcode(int8_t line_shift, uint8_t addr_shift) +static void fixLineMapping(SymbolsInfo* lines, unsigned nlines) { - unsigned opcode = (line_shift - DWARF_LINE_BASE) + addr_shift * DWARF_LINE_RANGE + DWARF_OPCODE_BASE; - - return opcode < 255; + // Fix EPILOGUE line mapping + int prevLine = 0; + for (int i = 0; i < nlines; ++i) + { + if (lines[i].lineNumber == HiddenLine) + continue; + if (lines[i].ilOffset == ICorDebugInfo::PROLOG) // will be fixed in next step + { + prevLine = 0; + } + else + { + if (lines[i].lineNumber == 0) + { + lines[i].lineNumber = prevLine; + } + else + { + prevLine = lines[i].lineNumber; + } + } + } + // Fix PROLOGUE line mapping + prevLine = lines[nlines - 1].lineNumber; + for (int i = nlines - 1; i >= 0; --i) + { + if (lines[i].lineNumber == HiddenLine) + continue; + if (lines[i].lineNumber == 0) + lines[i].lineNumber = prevLine; + else + prevLine = lines[i].lineNumber; + } + // Skip HiddenLines + for (int i = 0; i < nlines; ++i) + { + if (lines[i].lineNumber == HiddenLine) + { + lines[i].lineNumber = 0; + if (i + 1 < nlines && lines[i + 1].ilOffset == ICorDebugInfo::NO_MAPPING) + lines[i + 1].lineNumber = 0; + } + } } /* Build program for DWARF source line section */ -bool NotifyGdb::BuildLineProg(MemBuf& buf, PCODE startAddr, SymbolsInfo* lines, unsigned nlines) +bool NotifyGdb::BuildLineProg(MemBuf& buf, PCODE startAddr, TADDR codeSize, SymbolsInfo* lines, unsigned nlines) { static char cnv_buf[16]; - /* reserve memory assuming worst case: one extended and one special plus advance line command for each line*/ - buf.MemSize = 3 + ADDRESS_SIZE /* initial set address command */ - + 1 /* set prolog end command */ + /* reserve memory assuming worst case: set address, advance line command, set proglogue/epilogue and copy for each line */ + buf.MemSize = + 6 /* set file command */ + nlines * 6 /* advance line commands */ - + nlines * (4 + ADDRESS_SIZE) /* 1 extended + 1 special command */ + + nlines * (3 + ADDRESS_SIZE) /* set address commands */ + + nlines * 1 /* set prologue end or epilogue begin commands */ + + nlines * 1 /* copy commands */ + + 6 /* advance PC command */ + 3; /* end of sequence command */ buf.MemPtr = new (nothrow) char[buf.MemSize]; char* ptr = buf.MemPtr; if (buf.MemPtr == nullptr) return false; - - /* set absolute start address */ - IssueSetAddress(ptr, startAddr); - IssueSimpleCommand(ptr, DW_LNS_set_prologue_end); - - int prevLine = 1, prevAddr = 0, prevFile = 0; - + + fixLineMapping(lines, nlines); + + int prevLine = 1, prevFile = 0; + for (int i = 0; i < nlines; ++i) { /* different source file */ @@ -789,26 +2174,38 @@ bool NotifyGdb::BuildLineProg(MemBuf& buf, PCODE startAddr, SymbolsInfo* lines, IssueParamCommand(ptr, DW_LNS_set_file, cnv_buf, len); prevFile = lines[i].fileIndex; } - /* too big line number shift */ - if (lines[i].lineNumber - prevLine > (DWARF_LINE_BASE + DWARF_LINE_RANGE - 1)) - { + + // GCC don't use the is_prologue_end flag to mark the first instruction after the prologue. + // Instead of it it is issueing a line table entry for the first instruction of the prologue + // and one for the first instruction after the prologue. + // We do not want to confuse the debugger so we have to avoid adding a line in such case. + if (i > 0 && lines[i - 1].nativeOffset == lines[i].nativeOffset) + continue; + + IssueSetAddress(ptr, startAddr + lines[i].nativeOffset); + + if (lines[i].lineNumber != prevLine) { int len = Leb128Encode(static_cast(lines[i].lineNumber - prevLine), cnv_buf, sizeof(cnv_buf)); IssueParamCommand(ptr, DW_LNS_advance_line, cnv_buf, len); prevLine = lines[i].lineNumber; } - /* first try special opcode */ - if (FitIntoSpecialOpcode(lines[i].lineNumber - prevLine, lines[i].nativeOffset - prevAddr)) - IssueSpecialCommand(ptr, lines[i].lineNumber - prevLine, lines[i].nativeOffset - prevAddr); - else - { - IssueSetAddress(ptr, startAddr + lines[i].nativeOffset); - IssueSpecialCommand(ptr, lines[i].lineNumber - prevLine, 0); - } - - prevLine = lines[i].lineNumber; - prevAddr = lines[i].nativeOffset; + + if (lines[i].ilOffset == ICorDebugInfo::EPILOG) + IssueSimpleCommand(ptr, DW_LNS_set_epilogue_begin); + else if (i > 0 && lines[i - 1].ilOffset == ICorDebugInfo::PROLOG) + IssueSimpleCommand(ptr, DW_LNS_set_prologue_end); + + IssueParamCommand(ptr, DW_LNS_copy, NULL, 0); } - + + int lastAddr = nlines > 0 ? lines[nlines - 1].nativeOffset : 0; + + // Advance PC to the end of function + if (lastAddr < codeSize) { + int len = Leb128Encode(static_cast(codeSize - lastAddr), cnv_buf, sizeof(cnv_buf)); + IssueParamCommand(ptr, DW_LNS_advance_pc, cnv_buf, len); + } + IssueEndOfSequence(ptr); buf.MemSize = ptr - buf.MemPtr; @@ -816,16 +2213,31 @@ bool NotifyGdb::BuildLineProg(MemBuf& buf, PCODE startAddr, SymbolsInfo* lines, } /* Build the DWARF .debug_str section */ -bool NotifyGdb::BuildDebugStrings(MemBuf& buf) +bool NotifyGdb::BuildDebugStrings(MemBuf& buf, PTK_TypeInfoMap pTypeMap) { - uint32_t totalLength = 0; - + int totalLength = 0; + /* calculate total section size */ for (int i = 0; i < DebugStringCount; ++i) { totalLength += strlen(DebugStrings[i]) + 1; } - + + for (int i = 0; i < method.GetCount(); ++i) + { + method[i]->DumpStrings(nullptr, totalLength); + } + + { + auto iter = pTypeMap->Begin(); + while (iter != pTypeMap->End()) + { + TypeInfoBase *typeInfo = iter->Value(); + typeInfo->DumpStrings(nullptr, totalLength); + iter++; + } + } + buf.MemSize = totalLength; buf.MemPtr = new (nothrow) char[totalLength]; @@ -834,12 +2246,28 @@ bool NotifyGdb::BuildDebugStrings(MemBuf& buf) /* copy strings */ char* bufPtr = buf.MemPtr; + int offset = 0; for (int i = 0; i < DebugStringCount; ++i) { - strcpy(bufPtr, DebugStrings[i]); - bufPtr += strlen(DebugStrings[i]) + 1; + strcpy(bufPtr + offset, DebugStrings[i]); + offset += strlen(DebugStrings[i]) + 1; } - + + for (int i = 0; i < method.GetCount(); ++i) + { + method[i]->DumpStrings(bufPtr, offset); + } + + { + auto iter = pTypeMap->Begin(); + while (iter != pTypeMap->End()) + { + TypeInfoBase *typeInfo = iter->Value(); + typeInfo->DumpStrings(bufPtr, offset); + iter++; + } + } + return true; } @@ -848,7 +2276,7 @@ bool NotifyGdb::BuildDebugAbbrev(MemBuf& buf) { buf.MemPtr = new (nothrow) char[AbbrevTableSize]; buf.MemSize = AbbrevTableSize; - + if (buf.MemPtr == nullptr) return false; @@ -857,31 +2285,79 @@ bool NotifyGdb::BuildDebugAbbrev(MemBuf& buf) } /* Build tge DWARF .debug_info section */ -bool NotifyGdb::BuildDebugInfo(MemBuf& buf) +bool NotifyGdb::BuildDebugInfo(MemBuf& buf, PTK_TypeInfoMap pTypeMap, SymbolsInfo* lines, unsigned nlines) { - buf.MemSize = sizeof(DwarfCompUnit) + sizeof(DebugInfo) + 1; + int totalTypeVarSubSize = 0; + { + auto iter = pTypeMap->Begin(); + while (iter != pTypeMap->End()) + { + TypeInfoBase *typeInfo = iter->Value(); + typeInfo->DumpDebugInfo(nullptr, totalTypeVarSubSize); + iter++; + } + } + + for (int i = 0; i < method.GetCount(); ++i) + { + method[i]->lines = lines; + method[i]->nlines = nlines; + method[i]->DumpDebugInfo(nullptr, totalTypeVarSubSize); + } + // Drop pointers to lines when exiting current scope + struct DropMethodLines + { + ~DropMethodLines() + { + for (int i = 0; i < method.GetCount(); ++i) + { + method[i]->lines = nullptr; + method[i]->nlines = 0; + } + } + } dropMethodLines; + + //int locSize = GetArgsAndLocalsLen(argsDebug, argsDebugSize, localsDebug, localsDebugSize); + buf.MemSize = sizeof(DwarfCompUnit) + sizeof(DebugInfoCU) + totalTypeVarSubSize + 2; buf.MemPtr = new (nothrow) char[buf.MemSize]; if (buf.MemPtr == nullptr) return false; - + int offset = 0; /* Compile uint header */ DwarfCompUnit* cu = reinterpret_cast(buf.MemPtr.GetValue()); cu->m_length = buf.MemSize - sizeof(uint32_t); cu->m_version = 4; cu->m_abbrev_offset = 0; cu->m_addr_size = ADDRESS_SIZE; - - /* copy debug information */ - DebugInfo* di = reinterpret_cast(buf.MemPtr + sizeof(DwarfCompUnit)); - memcpy(buf.MemPtr + sizeof(DwarfCompUnit), &debugInfo, sizeof(DebugInfo)); - di->m_prod_off = 0; - di->m_cu_name = strlen(DebugStrings[0]) + 1; - di->m_sub_name = strlen(DebugStrings[0]) + 1 + strlen(DebugStrings[1]) + 1 + strlen(DebugStrings[2]) + 1; - di->m_type_name = strlen(DebugStrings[0]) + 1 + strlen(DebugStrings[1]) + 1 + strlen(DebugStrings[2]) + 1 + strlen(DebugStrings[3]) + 1; - - /* zero end marker */ - buf.MemPtr[buf.MemSize-1] = 0; + offset += sizeof(DwarfCompUnit); + DebugInfoCU* diCU = + reinterpret_cast(buf.MemPtr + offset); + memcpy(buf.MemPtr + offset, &debugInfoCU, sizeof(DebugInfoCU)); + offset += sizeof(DebugInfoCU); + diCU->m_prod_off = 0; + diCU->m_cu_name = strlen(DebugStrings[0]) + 1; + { + auto iter = pTypeMap->Begin(); + while (iter != pTypeMap->End()) + { + TypeInfoBase *typeInfo = iter->Value(); + typeInfo->DumpDebugInfo(buf.MemPtr, offset); + iter++; + } + } + for (int i = 0; i < method.GetCount(); ++i) + { + if (!method[i]->IsDumped()) + { + method[i]->DumpDebugInfo(buf.MemPtr, offset); + } + else + { + method[i]->DumpDebugInfo(buf.MemPtr, method[i]->m_entry_offset); + } + } + memset(buf.MemPtr + offset, 0, buf.MemSize - offset); return true; } @@ -908,12 +2384,60 @@ bool NotifyGdb::BuildDebugPub(MemBuf& buf, const char* name, uint32_t size, uint return true; } +/* Store addresses and names of the called methods into symbol table */ +bool NotifyGdb::CollectCalledMethods(CalledMethod* pCalledMethods, TADDR nativeCode) +{ + AddrSet tmpCodeAddrs; + + if (!codeAddrs.Contains(nativeCode)) + codeAddrs.Add(nativeCode); + + CalledMethod* pList = pCalledMethods; + + /* count called methods */ + while (pList != NULL) + { + TADDR callAddr = (TADDR)pList->GetCallAddr(); + if (!tmpCodeAddrs.Contains(callAddr) && !codeAddrs.Contains(callAddr)) { + tmpCodeAddrs.Add(callAddr); + } + pList = pList->GetNext(); + } + + SymbolCount = 1 + method.GetCount() + tmpCodeAddrs.GetCount(); + SymbolNames = new (nothrow) Elf_Symbol[SymbolCount]; + + pList = pCalledMethods; + int i = 1 + method.GetCount(); + while (i < SymbolCount && pList != NULL) + { + TADDR callAddr = (TADDR)pList->GetCallAddr(); + if (!codeAddrs.Contains(callAddr)) + { + MethodDesc* pMD = pList->GetMethodDesc(); + LPCUTF8 methodName = pMD->GetName(); + int symbolNameLength = strlen(methodName) + sizeof("__thunk_"); + SymbolNames[i].m_name = new char[symbolNameLength]; + SymbolNames[i].m_releaseName = true; + sprintf_s((char*)SymbolNames[i].m_name, symbolNameLength, "__thunk_%s", methodName); + SymbolNames[i].m_value = callAddr; + ++i; + codeAddrs.Add(callAddr); + } + CalledMethod* ptr = pList; + pList = pList->GetNext(); + delete ptr; + } + SymbolCount = i; + return true; +} + /* Build ELF .strtab section */ bool NotifyGdb::BuildStringTableSection(MemBuf& buf) { int len = 0; - for (int i = 0; i < sizeof(SymbolNames) / sizeof(SymbolNames[0]); ++i) - len += strlen(SymbolNames[i]) + 1; + for (int i = 0; i < SymbolCount; ++i) + len += strlen(SymbolNames[i].m_name) + 1; len++; // end table with zero-length string buf.MemSize = len; @@ -921,10 +2445,11 @@ bool NotifyGdb::BuildStringTableSection(MemBuf& buf) if (buf.MemPtr == nullptr) return false; char* ptr = buf.MemPtr; - for (int i = 0; i < sizeof(SymbolNames) / sizeof(SymbolNames[0]); ++i) + for (int i = 0; i < SymbolCount; ++i) { - strcpy(ptr, SymbolNames[i]); - ptr += strlen(SymbolNames[i]) + 1; + SymbolNames[i].m_off = ptr - buf.MemPtr; + strcpy(ptr, SymbolNames[i].m_name); + ptr += strlen(SymbolNames[i].m_name) + 1; } buf.MemPtr[buf.MemSize-1] = 0; @@ -934,107 +2459,136 @@ bool NotifyGdb::BuildStringTableSection(MemBuf& buf) /* Build ELF .symtab section */ bool NotifyGdb::BuildSymbolTableSection(MemBuf& buf, PCODE addr, TADDR codeSize) { - buf.MemSize = 2 * sizeof(Elf_Sym); + static const int textSectionIndex = GetSectionIndex(".text"); + + buf.MemSize = SymbolCount * sizeof(Elf_Sym); buf.MemPtr = new (nothrow) char[buf.MemSize]; if (buf.MemPtr == nullptr) return false; Elf_Sym *sym = reinterpret_cast(buf.MemPtr.GetValue()); - sym->st_name = 0; - sym->st_info = 0; - sym->st_other = 0; - sym->st_value = 0; - sym->st_size = 0; - sym->st_shndx = SHN_UNDEF; - - sym++; - //sym = reinterpret_cast(buf.MemPtr.GetValue() + sizeof(Elf_Sym)); - sym->st_name = 1; - sym->setBindingAndType(STB_GLOBAL, STT_FUNC); - sym->st_other = 0; -#ifdef _TARGET_ARM_ - sym->st_value = 1; // for THUMB code -#else - sym->st_value = 0; -#endif - sym->st_shndx = 1; // .text section index - sym->st_size = codeSize; - return true; -} -/* Build ELF string section */ -bool NotifyGdb::BuildSectionNameTable(MemBuf& buf) -{ - uint32_t totalLength = 0; + sym[0].st_name = 0; + sym[0].st_info = 0; + sym[0].st_other = 0; + sym[0].st_value = 0; + sym[0].st_size = 0; + sym[0].st_shndx = SHN_UNDEF; - /* calculate total size */ - for (int i = 0; i < SectionNamesCount; ++i) + for (int i = 1; i < 1 + method.GetCount(); ++i) { - totalLength += strlen(SectionNames[i]) + 1; + sym[i].st_name = SymbolNames[i].m_off; + sym[i].setBindingAndType(STB_GLOBAL, STT_FUNC); + sym[i].st_other = 0; + sym[i].st_value = PINSTRToPCODE(SymbolNames[i].m_value - addr); + sym[i].st_shndx = textSectionIndex; + sym[i].st_size = SymbolNames[i].m_size; } - buf.MemSize = totalLength; - buf.MemPtr = new (nothrow) char[totalLength]; - if (buf.MemPtr == nullptr) - return false; - - /* copy strings */ - char* bufPtr = buf.MemPtr; - for (int i = 0; i < SectionNamesCount; ++i) + for (int i = 1 + method.GetCount(); i < SymbolCount; ++i) { - strcpy(bufPtr, SectionNames[i]); - bufPtr += strlen(SectionNames[i]) + 1; + sym[i].st_name = SymbolNames[i].m_off; + sym[i].setBindingAndType(STB_GLOBAL, STT_FUNC); + sym[i].st_other = 0; + sym[i].st_shndx = SectionNamesCount + (i - (1 + method.GetCount())); // .thunks section index + sym[i].st_size = 8; +#ifdef _TARGET_ARM_ + sym[i].st_value = 1; // for THUMB code +#else + sym[i].st_value = 0; +#endif } - return true; } -/* Build the ELF section headers table */ -bool NotifyGdb::BuildSectionTable(MemBuf& buf) +int NotifyGdb::GetSectionIndex(const char *sectName) { - Elf_Shdr* sectionHeaders = new (nothrow) Elf_Shdr[SectionNamesCount - 1]; - Elf_Shdr* pSh = sectionHeaders; + for (int i = 0; i < SectionNamesCount; ++i) + if (strcmp(SectionNames[i], sectName) == 0) + return i; + return -1; +} + +/* Build the ELF section headers table and section names table */ +bool NotifyGdb::BuildSectionTables(MemBuf& sectBuf, MemBuf& strBuf) +{ + static const int symtabSectionIndex = GetSectionIndex(".symtab"); + static const int nullSectionIndex = GetSectionIndex(""); + + const int thunks_count = SymbolCount - 1 - method.GetCount(); + + // Approximate length of single section name. + // Used only to reduce memory reallocations. + static const int SECT_NAME_LENGTH = 11; + + if (!strBuf.Resize(SECT_NAME_LENGTH * (SectionNamesCount + thunks_count))) + { + return false; + } + Elf_Shdr* sectionHeaders = new (nothrow) Elf_Shdr[SectionNamesCount + thunks_count]; if (sectionHeaders == nullptr) { return false; } - - /* NULL entry */ - pSh->sh_name = 0; - pSh->sh_type = SHT_NULL; - pSh->sh_flags = 0; - pSh->sh_addr = 0; - pSh->sh_offset = 0; - pSh->sh_size = 0; - pSh->sh_link = SHN_UNDEF; - pSh->sh_info = 0; - pSh->sh_addralign = 0; - pSh->sh_entsize = 0; - - ++pSh; - /* fill section header data */ - uint32_t sectNameOffset = 1; - for (int i = 1; i < SectionNamesCount - 1; ++i, ++pSh) + + sectBuf.MemPtr = reinterpret_cast(sectionHeaders); + sectBuf.MemSize = sizeof(Elf_Shdr) * (SectionNamesCount + thunks_count); + + Elf_Shdr* pSh = sectionHeaders; + uint32_t sectNameOffset = 0; + + // Additional memory for remaining section names, + // grows twice on each reallocation. + int addSize = SECT_NAME_LENGTH; + + // Fill section headers and names + for (int i = 0; i < SectionNamesCount + thunks_count; ++i, ++pSh) { + char thunkSectNameBuf[256]; // temporary buffer for .thunk_# section name + const char *sectName; + + bool isThunkSection = i >= SectionNamesCount; + if (isThunkSection) + { + sprintf_s(thunkSectNameBuf, _countof(thunkSectNameBuf), ".thunk_%i", i); + sectName = thunkSectNameBuf; + } + else + { + sectName = SectionNames[i]; + } + + // Ensure that there is enough memory for section name, + // reallocate if necessary. pSh->sh_name = sectNameOffset; - sectNameOffset += strlen(SectionNames[i]) + 1; - pSh->sh_type = Sections[i].m_type; - pSh->sh_flags = Sections[i].m_flags; + sectNameOffset += strlen(sectName) + 1; + if (sectNameOffset > strBuf.MemSize) + { + // Allocate more memory for remaining section names + if (!strBuf.Resize(sectNameOffset + addSize)) + return false; + addSize *= 2; + } + + strcpy(strBuf.MemPtr + pSh->sh_name, sectName); + + // All .thunk_* sections have the same type and flags + int index = isThunkSection ? SectionNamesCount : i; + pSh->sh_type = Sections[index].m_type; + pSh->sh_flags = Sections[index].m_flags; + pSh->sh_addr = 0; pSh->sh_offset = 0; pSh->sh_size = 0; pSh->sh_link = SHN_UNDEF; pSh->sh_info = 0; - pSh->sh_addralign = 1; - if (strcmp(SectionNames[i], ".symtab") == 0) - pSh->sh_entsize = sizeof(Elf_Sym); - else - pSh->sh_entsize = 0; + pSh->sh_addralign = i == nullSectionIndex ? 0 : 1; + pSh->sh_entsize = i == symtabSectionIndex ? sizeof(Elf_Sym) : 0; } - buf.MemPtr = reinterpret_cast(sectionHeaders); - buf.MemSize = sizeof(Elf_Shdr) * (SectionNamesCount - 1); + // Set actual used size to avoid garbage in ELF section + strBuf.MemSize = sectNameOffset; return true; } @@ -1042,17 +2596,18 @@ bool NotifyGdb::BuildSectionTable(MemBuf& buf) bool NotifyGdb::BuildELFHeader(MemBuf& buf) { Elf_Ehdr* header = new (nothrow) Elf_Ehdr; - buf.MemPtr = reinterpret_cast(header); - buf.MemSize = sizeof(Elf_Ehdr); - + if (header == nullptr) + { return false; - + } + + buf.MemPtr = reinterpret_cast(header); + buf.MemSize = sizeof(Elf_Ehdr); return true; - } -/* Split full path name into directory & file anmes */ +/* Split full path name into directory & file names */ void NotifyGdb::SplitPathname(const char* path, const char*& pathName, const char*& fileName) { char* pSlash = strrchr(path, '/'); @@ -1070,47 +2625,6 @@ void NotifyGdb::SplitPathname(const char* path, const char*& pathName, const cha } } -/* LEB128 for 32-bit unsigned integer */ -int NotifyGdb::Leb128Encode(uint32_t num, char* buf, int size) -{ - int i = 0; - - do - { - uint8_t byte = num & 0x7F; - if (i >= size) - break; - num >>= 7; - if (num != 0) - byte |= 0x80; - buf[i++] = byte; - } - while (num != 0); - - return i; -} - -/* LEB128 for 32-bit signed integer */ -int NotifyGdb::Leb128Encode(int32_t num, char* buf, int size) -{ - int i = 0; - bool hasMore = true, isNegative = num < 0; - - while (hasMore && i < size) - { - uint8_t byte = num & 0x7F; - num >>= 7; - - if ((num == 0 && (byte & 0x40) == 0) || (num == -1 && (byte & 0x40) == 0x40)) - hasMore = false; - else - byte |= 0x80; - buf[i++] = byte; - } - - return i; -} - #ifdef _DEBUG void NotifyGdb::DumpElf(const char* methodName, const MemBuf& elfFile) { diff --git a/src/vm/gdbjit.h b/src/vm/gdbjit.h index 467a970..3160ecc 100644 --- a/src/vm/gdbjit.h +++ b/src/vm/gdbjit.h @@ -16,6 +16,7 @@ #include #include "method.hpp" +#include "dbginterface.h" #include "../inc/llvm/ELF.h" #include "../inc/llvm/Dwarf.h" @@ -33,6 +34,46 @@ #error "Target is not supported" #endif + +static constexpr const int CorElementTypeToDWEncoding[] = +{ +/* ELEMENT_TYPE_END */ 0, +/* ELEMENT_TYPE_VOID */ DW_ATE_address, +/* ELEMENT_TYPE_BOOLEAN */ DW_ATE_boolean, +/* ELEMENT_TYPE_CHAR */ DW_ATE_UTF, +/* ELEMENT_TYPE_I1 */ DW_ATE_signed, +/* ELEMENT_TYPE_U1 */ DW_ATE_unsigned, +/* ELEMENT_TYPE_I2 */ DW_ATE_signed, +/* ELEMENT_TYPE_U2 */ DW_ATE_unsigned, +/* ELEMENT_TYPE_I4 */ DW_ATE_signed, +/* ELEMENT_TYPE_U4 */ DW_ATE_unsigned, +/* ELEMENT_TYPE_I8 */ DW_ATE_signed, +/* ELEMENT_TYPE_U8 */ DW_ATE_unsigned, +/* ELEMENT_TYPE_R4 */ DW_ATE_float, +/* ELEMENT_TYPE_R8 */ DW_ATE_float, +/* ELEMENT_TYPE_STRING */ DW_ATE_address, +/* ELEMENT_TYPE_PTR */ DW_ATE_address, +/* ELEMENT_TYPE_BYREF */ DW_ATE_address, +/* ELEMENT_TYPE_VALUETYPE */ DW_ATE_address, +/* ELEMENT_TYPE_CLASS */ DW_ATE_address, +/* ELEMENT_TYPE_VAR */ DW_ATE_address, +/* ELEMENT_TYPE_ARRAY */ DW_ATE_address, +/* ELEMENT_TYPE_GENERICINST */ DW_ATE_address, +/* ELEMENT_TYPE_TYPEDBYREF */ DW_ATE_address, +/* SKIP 17 */ DW_ATE_address, +/* ELEMENT_TYPE_I */ DW_ATE_signed, +/* ELEMENT_TYPE_U */ DW_ATE_unsigned, +/* SKIP 1a */ DW_ATE_address, +/* ELEMENT_TYPE_FNPTR */ DW_ATE_address, +/* ELEMENT_TYPE_OBJECT */ DW_ATE_address, +/* ELEMENT_TYPE_SZARRAY */ DW_ATE_address, +/* ELEMENT_TYPE_MVAR */ DW_ATE_address, +/* ELEMENT_TYPE_CMOD_REQD */ DW_ATE_address, +/* ELEMENT_TYPE_CMOD_OPT */ DW_ATE_address, +/* ELEMENT_TYPE_INTERNAL */ DW_ATE_address, +/* ELEMENT_TYPE_MAX */ DW_ATE_address, +}; + struct __attribute__((packed)) DwarfCompUnit { uint32_t m_length; @@ -64,51 +105,374 @@ struct __attribute__((packed)) DwarfLineNumHeader uint8_t m_std_num_arg[DW_LNS_MAX]; }; +const ULONG32 HiddenLine = 0x00feefee; + struct SymbolsInfo { int lineNumber, ilOffset, nativeOffset, fileIndex; char fileName[2*MAX_PATH_FNAME]; + ICorDebugInfo::SourceTypes source; +}; + +class DwarfDumpable +{ +public: + // writes all string literals this type needs to ptr + virtual void DumpStrings(char* ptr, int& offset) = 0; + + virtual void DumpDebugInfo(char* ptr, int& offset) = 0; +}; + +class LocalsInfo +{ +public: + int size; + char** localsName; + ULONG32 countVars; + ICorDebugInfo::NativeVarInfo *pVars; +}; + +class TypeMember; + +class TypeInfoBase : public DwarfDumpable +{ +public: + TypeInfoBase(TypeHandle typeHandle) + : m_type_name(nullptr), + m_type_name_offset(0), + m_type_size(0), + m_type_offset(0), + typeHandle(typeHandle), + typeKey(typeHandle.GetTypeKey()) + { + } + + virtual ~TypeInfoBase() + { + if (m_type_name != nullptr) + { + delete[] m_type_name; + } + } + + virtual void DumpStrings(char* ptr, int& offset) override; + void CalculateName(); + void SetTypeHandle(TypeHandle handle); + TypeHandle GetTypeHandle(); + TypeKey* GetTypeKey(); + + char* m_type_name; + int m_type_name_offset; + ULONG m_type_size; + int m_type_offset; +private: + TypeHandle typeHandle; + TypeKey typeKey; +}; + +class PrimitiveTypeInfo: public TypeInfoBase +{ +public: + PrimitiveTypeInfo(TypeHandle typeHandle, int encoding) + : TypeInfoBase(typeHandle), + m_type_encoding(encoding) + { + } + + void DumpDebugInfo(char* ptr, int& offset) override; + + int m_type_encoding; +}; + +class RefTypeInfo: public TypeInfoBase +{ +public: + RefTypeInfo(TypeHandle typeHandle, TypeInfoBase *value_type) + : TypeInfoBase(typeHandle), + m_value_type(value_type) + { + } + void DumpStrings(char* ptr, int& offset) override; + void DumpDebugInfo(char* ptr, int& offset) override; + TypeInfoBase *m_value_type; +}; + +class ClassTypeInfo: public TypeInfoBase +{ +public: + ClassTypeInfo(TypeHandle typeHandle, int num_members); + ~ClassTypeInfo(); + + void DumpStrings(char* ptr, int& offset) override; + void DumpDebugInfo(char* ptr, int& offset) override; + + int m_num_members; + TypeMember* members; +}; + +class TypeMember: public DwarfDumpable +{ +public: + TypeMember() + : m_member_name(nullptr), + m_member_name_offset(0), + m_member_offset(0), + m_static_member_address(0), + m_member_type(nullptr) + { + } + + ~TypeMember() + { + if (m_member_name != nullptr) + { + delete[] m_member_name; + } + } + + void DumpStrings(char* ptr, int& offset) override; + void DumpDebugInfo(char* ptr, int& offset) override; + void DumpStaticDebugInfo(char* ptr, int& offset); + + char* m_member_name; + int m_member_name_offset; + int m_member_offset; + TADDR m_static_member_address; + TypeInfoBase *m_member_type; }; +class ArrayTypeInfo: public TypeInfoBase +{ +public: + ArrayTypeInfo(TypeHandle typeHandle, int countOffset, TypeInfoBase* elemType) + : TypeInfoBase(typeHandle), + m_count_offset(countOffset), + m_elem_type(elemType) + { + } + + ~ArrayTypeInfo() + { + if (m_elem_type != nullptr) + { + delete m_elem_type; + } + } + + void DumpDebugInfo(char* ptr, int& offset) override; + + int m_count_offset; + TypeInfoBase *m_elem_type; +}; + +class VarDebugInfo: public DwarfDumpable +{ +public: + VarDebugInfo(int abbrev) + : m_var_name(nullptr), + m_var_abbrev(abbrev), + m_var_name_offset(0), + m_il_index(0), + m_native_offset(0), + m_var_type(nullptr) + { + } + + VarDebugInfo() + : m_var_name(nullptr), + m_var_abbrev(6), + m_var_name_offset(0), + m_il_index(0), + m_native_offset(0), + m_var_type(nullptr) + { + } + + virtual ~VarDebugInfo() + { + delete[] m_var_name; + } + + void DumpStrings(char* ptr, int& offset) override; + void DumpDebugInfo(char* ptr, int& offset) override; + + char* m_var_name; + int m_var_abbrev; + int m_var_name_offset; + int m_il_index; + int m_native_offset; + TypeInfoBase *m_var_type; +}; class NotifyGdb { public: static void MethodCompiled(MethodDesc* MethodDescPtr); static void MethodDropped(MethodDesc* MethodDescPtr); + template + class DeleteValuesOnDestructSHashTraits : public PARENT_TRAITS + { + public: + static inline void OnDestructPerEntryCleanupAction(typename PARENT_TRAITS::element_t e) + { + delete e.Value(); + } + static const bool s_DestructPerEntryCleanupAction = true; + }; + + template + class TypeKeyHashTraits : public DefaultSHashTraits< KeyValuePair > + { + public: + // explicitly declare local typedefs for these traits types, otherwise + // the compiler may get confused + typedef typename DefaultSHashTraits< KeyValuePair >::element_t element_t; + typedef typename DefaultSHashTraits< KeyValuePair >::count_t count_t; + typedef TypeKey* key_t; + + static key_t GetKey(element_t e) + { + LIMITED_METHOD_CONTRACT; + return e.Key(); + } + static BOOL Equals(key_t k1, key_t k2) + { + LIMITED_METHOD_CONTRACT; + return k1->Equals(k2); + } + static count_t Hash(key_t k) + { + LIMITED_METHOD_CONTRACT; + return k->ComputeHash(); + } + + static const element_t Null() { LIMITED_METHOD_CONTRACT; return element_t(key_t(),VALUE()); } + static const element_t Deleted() { LIMITED_METHOD_CONTRACT; return element_t(key_t(-1), VALUE()); } + static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e.Key() == key_t(); } + static bool IsDeleted(const element_t &e) { return e.Key() == key_t(-1); } + }; + + typedef MapSHash>> TK_TypeInfoMap; + typedef TK_TypeInfoMap* PTK_TypeInfoMap; + typedef SetSHash< TADDR, + NoRemoveSHashTraits < + NonDacAwareSHashTraits< SetSHashTraits > + > > AddrSet; private: + struct MemBuf { NewArrayHolder MemPtr; unsigned MemSize; MemBuf() : MemPtr(0), MemSize(0) {} + bool Resize(unsigned newSize) + { + if (newSize == 0) + { + MemPtr = nullptr; + MemSize = 0; + return true; + } + char *tmp = new (nothrow) char [newSize]; + if (tmp == nullptr) + return false; + memmove(tmp, MemPtr.GetValue(), newSize < MemSize ? newSize : MemSize); + MemPtr = tmp; + MemSize = newSize; + return true; + } }; + static int GetSectionIndex(const char *sectName); static bool BuildELFHeader(MemBuf& buf); - static bool BuildSectionNameTable(MemBuf& buf); - static bool BuildSectionTable(MemBuf& buf); + static bool BuildSectionTables(MemBuf& sectBuf, MemBuf& strBuf); static bool BuildSymbolTableSection(MemBuf& buf, PCODE addr, TADDR codeSize); static bool BuildStringTableSection(MemBuf& strTab); - static bool BuildDebugStrings(MemBuf& buf); - static bool BuildDebugAbbrev(MemBuf& buf); - static bool BuildDebugInfo(MemBuf& buf); + static bool BuildDebugStrings(MemBuf& buf, PTK_TypeInfoMap pTypeMap); + static bool BuildDebugAbbrev(MemBuf& buf); + static bool BuildDebugInfo(MemBuf& buf, PTK_TypeInfoMap pTypeMap, SymbolsInfo* lines, unsigned nlines); static bool BuildDebugPub(MemBuf& buf, const char* name, uint32_t size, uint32_t dieOffset); - static bool BuildLineTable(MemBuf& buf, PCODE startAddr, SymbolsInfo* lines, unsigned nlines); + static bool BuildLineTable(MemBuf& buf, PCODE startAddr, TADDR codeSize, SymbolsInfo* lines, unsigned nlines); static bool BuildFileTable(MemBuf& buf, SymbolsInfo* lines, unsigned nlines); - static bool BuildLineProg(MemBuf& buf, PCODE startAddr, SymbolsInfo* lines, unsigned nlines); - static bool FitIntoSpecialOpcode(int8_t line_shift, uint8_t addr_shift); + static bool BuildLineProg(MemBuf& buf, PCODE startAddr, TADDR codeSize, SymbolsInfo* lines, unsigned nlines); static void IssueSetAddress(char*& ptr, PCODE addr); static void IssueEndOfSequence(char*& ptr); static void IssueSimpleCommand(char*& ptr, uint8_t command); static void IssueParamCommand(char*& ptr, uint8_t command, char* param, int param_len); - static void IssueSpecialCommand(char*& ptr, int8_t line_shift, uint8_t addr_shift); static void SplitPathname(const char* path, const char*& pathName, const char*& fileName); - static int Leb128Encode(uint32_t num, char* buf, int size); - static int Leb128Encode(int32_t num, char* buf, int size); + static bool CollectCalledMethods(CalledMethod* pCM, TADDR nativeCode); #ifdef _DEBUG static void DumpElf(const char* methodName, const MemBuf& buf); #endif }; +class FunctionMember: public TypeMember +{ +public: + FunctionMember(MethodDesc *md, int num_locals, int num_args) + : TypeMember(), + md(md), + m_file(1), + m_line(1), + m_sub_low_pc(0), + m_sub_high_pc(0), + m_sub_loc(), + m_num_args(num_args), + m_num_locals(num_locals), + m_num_vars(num_args + num_locals), + m_entry_offset(0), + vars(new VarDebugInfo[m_num_vars]), + lines(NULL), + nlines(0), + m_linkage_name_offset(0), + dumped(false) + { + m_sub_loc[0] = 1; +#if defined(_TARGET_AMD64_) + m_sub_loc[1] = DW_OP_reg6; +#elif defined(_TARGET_ARM_) + m_sub_loc[1] = DW_OP_reg11; +#else +#error Unsupported platform! +#endif + } + + virtual ~FunctionMember() + { + delete[] vars; + } + + void DumpStrings(char* ptr, int& offset) override; + void DumpDebugInfo(char* ptr, int& offset) override; + void DumpTryCatchDebugInfo(char* ptr, int& offset); + HRESULT GetLocalsDebugInfo(NotifyGdb::PTK_TypeInfoMap pTypeMap, + LocalsInfo& locals, + int startNativeOffset); + BOOL IsDumped() + { + return dumped; + } + + MethodDesc *md; + uint8_t m_file, m_line; + uintptr_t m_sub_low_pc, m_sub_high_pc; + uint8_t m_sub_loc[2]; + uint8_t m_num_args; + uint8_t m_num_locals; + uint16_t m_num_vars; + int m_entry_offset; + VarDebugInfo* vars; + SymbolsInfo* lines; + unsigned nlines; + int m_linkage_name_offset; +private: + int GetArgsAndLocalsLen(); + void MangleName(char *buf, int &buf_offset, const char *name); + void DumpMangledNamespaceAndMethod(char *buf, int &offset, const char *nspace, const char *mname); + void DumpLinkageName(char* ptr, int& offset); + bool GetBlockInNativeCode(int blockILOffset, int blockILLen, TADDR *startOffset, TADDR *endOffset); + void DumpTryCatchBlock(char* ptr, int& offset, int ilOffset, int ilLen, int abbrev); + BOOL dumped; +}; #endif // #ifndef __GDBJIT_H__ diff --git a/src/vm/gdbjithelpers.h b/src/vm/gdbjithelpers.h index 1298141..3a34dd1 100644 --- a/src/vm/gdbjithelpers.h +++ b/src/vm/gdbjithelpers.h @@ -23,6 +23,8 @@ struct MethodDebugInfo { SequencePointInfo* points; int size; + char16_t** locals; + int localsSize; }; typedef BOOL (*GetInfoForMethodDelegate)(const char*, unsigned int, MethodDebugInfo& methodDebugInfo); diff --git a/src/vm/hash.cpp b/src/vm/hash.cpp index 205f736..6b6b213 100644 --- a/src/vm/hash.cpp +++ b/src/vm/hash.cpp @@ -547,8 +547,8 @@ UPTR HashMap::LookupValue(UPTR key, UPTR value) // BROKEN: This is called for the RCWCache on the GC thread // Also called by AppDomain::FindCachedAssembly to resolve AssemblyRef -- this is used by stack walking on the GC thread. - // See comments in GCHeap::RestartEE (above the call to SyncClean::CleanUp) for reason to enter COOP mode. - // However, if the current thread is the GC thread, we know we're not going to call GCHeap::RestartEE + // See comments in GCHeapUtilities::RestartEE (above the call to SyncClean::CleanUp) for reason to enter COOP mode. + // However, if the current thread is the GC thread, we know we're not going to call GCHeapUtilities::RestartEE // while accessing the HashMap, so it's safe to proceed. // (m_fAsyncMode && !IsGCThread() is the condition for entering COOP mode. I.e., enable COOP GC only if // the HashMap is in async mode and this is not a GC thread.) diff --git a/src/vm/i386/RedirectedHandledJITCase.asm b/src/vm/i386/RedirectedHandledJITCase.asm index 8034562..44a93bd 100644 --- a/src/vm/i386/RedirectedHandledJITCase.asm +++ b/src/vm/i386/RedirectedHandledJITCase.asm @@ -103,7 +103,7 @@ _ExceptionHijack@0 PROC PUBLIC ; This is where we land when we're hijacked from an IP by the debugger. ; The debugger has already pushed the args: ; - a CONTEXT - ; - a EXCEPTION_RECORD onto the stack + ; - an EXCEPTION_RECORD onto the stack ; - an DWORD to use to mulitplex the hijack ; - an arbitrary void* data parameter call _ExceptionHijackWorker@16 diff --git a/src/vm/i386/asmconstants.h b/src/vm/i386/asmconstants.h index 5fd39d6..c42b167 100644 --- a/src/vm/i386/asmconstants.h +++ b/src/vm/i386/asmconstants.h @@ -449,6 +449,24 @@ ASMCONSTANTS_C_ASSERT(CallDescrData__fpReturnSize == offsetof(CallDescrD ASMCONSTANTS_C_ASSERT(CallDescrData__pTarget == offsetof(CallDescrData, pTarget)) ASMCONSTANTS_C_ASSERT(CallDescrData__returnValue == offsetof(CallDescrData, returnValue)) +#define UMEntryThunk__m_pUMThunkMarshInfo 0x0C +ASMCONSTANTS_C_ASSERT(UMEntryThunk__m_pUMThunkMarshInfo == offsetof(UMEntryThunk, m_pUMThunkMarshInfo)) + +#define UMEntryThunk__m_dwDomainId 0x10 +ASMCONSTANTS_C_ASSERT(UMEntryThunk__m_dwDomainId == offsetof(UMEntryThunk, m_dwDomainId)) + +#define UMThunkMarshInfo__m_pILStub 0x00 +ASMCONSTANTS_C_ASSERT(UMThunkMarshInfo__m_pILStub == offsetof(UMThunkMarshInfo, m_pILStub)) + +#define UMThunkMarshInfo__m_cbActualArgSize 0x04 +ASMCONSTANTS_C_ASSERT(UMThunkMarshInfo__m_cbActualArgSize == offsetof(UMThunkMarshInfo, m_cbActualArgSize)) + +#ifndef CROSSGEN_COMPILE +#define Thread__m_pDomain 0x14 +ASMCONSTANTS_C_ASSERT(Thread__m_pDomain == offsetof(Thread, m_pDomain)); + +#endif + #undef ASMCONSTANTS_C_ASSERT #undef ASMCONSTANTS_RUNTIME_ASSERT diff --git a/src/vm/i386/asmhelpers.S b/src/vm/i386/asmhelpers.S new file mode 100644 index 0000000..1c6f0a3 --- /dev/null +++ b/src/vm/i386/asmhelpers.S @@ -0,0 +1,1140 @@ +// 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. + +.intel_syntax noprefix +#include "unixasmmacros.inc" +#include "asmconstants.h" + +// +// FramedMethodFrame prolog +// +.macro STUB_PROLOG + // push ebp-frame + PROLOG_BEG + + // save CalleeSavedRegisters + PROLOG_PUSH ebx + PROLOG_PUSH esi + PROLOG_PUSH edi + + // push ArgumentRegisters + PROLOG_PUSH ecx + PROLOG_PUSH edx + + // set frame pointer + PROLOG_END +.endm + +// +// FramedMethodFrame epilog +// +.macro STUB_EPILOG + // restore stack pointer + EPILOG_BEG + + // pop ArgumentRegisters + EPILOG_POP edx + EPILOG_POP ecx + + // pop CalleeSavedRegisters + EPILOG_POP edi + EPILOG_POP esi + EPILOG_POP ebx + + // pop ebp-frame + EPILOG_END +.endm + +// +// FramedMethodFrame epilog +// +.macro STUB_EPILOG_RETURN + // pop ArgumentRegisters + add esp, 8 + + // pop CalleeSavedRegisters + pop edi + pop esi + pop ebx + pop ebp +.endm + +.macro STUB_PROLOG_2_HIDDEN_ARGS + // + // The stub arguments are where we want to setup the TransitionBlock. We will + // setup the TransitionBlock later once we can trash them + // + // push ebp-frame + // push ebp + // mov ebp,esp + + // save CalleeSavedRegisters + // push ebx + + push esi + push edi + + // push ArgumentRegisters + push ecx + push edx + + mov ecx, [esp + 4*4] + mov edx, [esp + 5*4] + + // Setup up proper EBP frame now that the stub arguments can be trashed + mov [esp + 4*4], ebx + mov [esp + 5*4], ebp + lea ebp, [esp + 5*4] +.endm + +LEAF_ENTRY ResetCurrentContext, _TEXT + push eax + + // clear the direction flag (used for rep instructions) + cld + + // load flags into AX + fnstcw [esp - 2] + mov ax, [esp - 2] + + fninit // reset FPU + and ax, 0f00h // preserve precision and rounding control + or ax, 007fh // mask all exceptions + + // preserve precision control + mov ax, [esp - 2] + fldcw [esp - 2] + + pop eax + ret +LEAF_END ResetCurrentContext, _TEXT + +// Incoming: +// ESP+4: Pointer to buffer to which FPU state should be saved +LEAF_ENTRY CaptureFPUContext, _TEXT + mov ecx, [esp + 4] + fnstenv [ecx] + ret 4 + +LEAF_END CaptureFPUContext, _TEXT + +// Incoming: +// ESP+4: Pointer to buffer from which FPU state should be restored +LEAF_ENTRY RestoreFPUContext, _TEXT + mov ecx, [esp + 4] + fldenv [ecx] + ret 4 +LEAF_END RestoreFPUContext, _TEXT + +LEAF_ENTRY ResumeAtJitEHHelper, _TEXT + mov edx, [esp + 4] // edx = pContext (EHContext*) + + mov ebx, [edx + EHContext_Ebx] + mov esi, [edx + EHContext_Esi] + mov edi, [edx + EHContext_Edi] + mov ebp, [edx + EHContext_Ebp] + mov ecx, [edx + EHContext_Esp] + mov eax, [edx + EHContext_Eip] + mov [ecx - 4], eax + mov eax, [edx + EHContext_Eax] + mov [ecx - 8], eax + mov eax, [edx + EHContext_Ecx] + mov [ecx - 0Ch], eax + mov eax, [edx + EHContext_Edx] + mov [ecx - 10h], eax + lea esp, [ecx - 10h] + pop edx + pop ecx + pop eax + ret +LEAF_END ResumeAtJitEHHelper, _TEXT + +// int __stdcall CallJitEHFilterHelper(size_t *pShadowSP, EHContext *pContext); +// on entry, only the pContext->Esp, Ebx, Esi, Edi, Ebp, and Eip are initialized +NESTED_ENTRY CallJitEHFilterHelper, _TEXT, NoHandler + push ebp + mov ebp, esp + push ebx + push esi + push edi + + // Write esp-4 to the shadowSP slot + mov eax, [ebp + 8] // pShadowSP = [ebp+8] + test eax, eax + jz LOCAL_LABEL(DONE_SHADOWSP_FILTER) + mov ebx, esp + sub ebx, 4 + or ebx, SHADOW_SP_IN_FILTER_ASM + mov [eax], ebx + +LOCAL_LABEL(DONE_SHADOWSP_FILTER): + mov edx, [ebp + 12] // pContext = [ebp+12] + mov eax, [edx + EHContext_Eax] + mov ebx, [edx + EHContext_Ebx] + mov esi, [edx + EHContext_Esi] + mov edi, [edx + EHContext_Edi] + mov ebp, [edx + EHContext_Ebp] + + call DWORD PTR [edx + EHContext_Eip] +#ifdef _DEBUG + nop // Indicate that it is OK to call managed code directly from here +#endif // _DEBUG + + pop edi + pop esi + pop ebx + pop ebp // don't use 'leave' here, as ebp as been trashed + ret 8 +NESTED_END CallJitEHFilterHelper, _TEXT + +// void __stdcall CallJITEHFinallyHelper(size_t *pShadowSP, EHContext *pContext); +// on entry, only the pContext->Esp, Ebx, Esi, Edi, Ebp, and Eip are initialized +NESTED_ENTRY CallJitEHFinallyHelper, _TEXT, NoHandler + push ebp + mov ebp, esp + push ebx + push esi + push edi + + // Write esp-4 to the shadowSP slot + mov eax, [ebp + 8] // pShadowSP = [ebp+8] + test eax, eax + jz LOCAL_LABEL(DONE_SHADOWSP_FINALLY) + mov ebx, esp + sub ebx, 4 + mov [eax], ebx + +LOCAL_LABEL(DONE_SHADOWSP_FINALLY): + mov edx, [ebp + 12] // pContext = [ebp+12] + mov eax, [edx + EHContext_Eax] + mov ebx, [edx + EHContext_Ebx] + mov esi, [edx + EHContext_Esi] + mov edi, [edx + EHContext_Edi] + mov ebp, [edx + EHContext_Ebp] + call DWORD PTR [edx + EHContext_Eip] +#ifdef _DEBUG + nop // Indicate that it is OK to call managed code directly from here +#endif // _DEBUG + + // Reflect the changes to the context and only update non-volatile registers. + // This will be used later to update REGDISPLAY + mov edx, [esp + 12 + 12] + mov [edx + EHContext_Ebx], ebx + mov [edx + EHContext_Esi], esi + mov [edx + EHContext_Edi], edi + mov [edx + EHContext_Ebp], ebp + + pop edi + pop esi + pop ebx + pop ebp // don't use 'leave' here, as ebp as been trashed + ret 8 +NESTED_END CallJitEHFinallyHelper, _TEXT + +LEAF_ENTRY GetSpecificCpuTypeAsm, _TEXT + push ebx // ebx is trashed by the cpuid calls + + // See if the chip supports CPUID + pushfd + pop ecx // Get the EFLAGS + mov eax, ecx // Save for later testing + xor ecx, 200000h // Invert the ID bit + push ecx + popfd // Save the updated flags + pushfd + pop ecx // Retrieve the updated flags + xor ecx, eax // Test if it actually changed (bit set means yes) + push eax + popfd // Restore the flags + + test ecx, 200000h + jz LOCAL_LABEL(Assume486) + + xor eax, eax + cpuid + + test eax, eax + jz LOCAL_LABEL(Assume486) // brif CPUID1 not allowed + + mov eax, 1 + cpuid + + // filter out everything except family and model + // Note that some multi-procs have different stepping number for each proc + and eax, 0ff0h + + jmp LOCAL_LABEL(CpuTypeDone) + +LOCAL_LABEL(Assume486): + mov eax, 0400h // report 486 + +LOCAL_LABEL(CpuTypeDone): + pop ebx + ret +LEAF_END GetSpecificCpuTypeAsm, _TEXT + +// DWORD __stdcall GetSpecificCpuFeaturesAsm(DWORD *pInfo); +LEAF_ENTRY GetSpecificCpuFeaturesAsm, _TEXT + push ebx // ebx is trashed by the cpuid calls + + // See if the chip supports CPUID + pushfd + pop ecx // Get the EFLAGS + mov eax, ecx // Save for later testing + xor ecx, 200000h // Invert the ID bit. + push ecx + popfd // Save the updated flags. + pushfd + pop ecx // Retrieve the updated flags + xor ecx, eax // Test if it actually changed (bit set means yes) + push eax + popfd // Restore the flags + + test ecx, 200000h + jz LOCAL_LABEL(CpuFeaturesFail) + + xor eax, eax + cpuid + + test eax, eax + jz LOCAL_LABEL(CpuFeaturesDone) // br if CPUID1 not allowed + + mov eax, 1 + cpuid + mov eax, edx // return all feature flags + mov edx, [esp + 8] + test edx, edx + jz LOCAL_LABEL(CpuFeaturesDone) + mov [edx],ebx // return additional useful information + jmp LOCAL_LABEL(CpuFeaturesDone) + +LOCAL_LABEL(CpuFeaturesFail): + xor eax, eax // Nothing to report + +LOCAL_LABEL(CpuFeaturesDone): + pop ebx + ret 4 +LEAF_END GetSpecificCpuFeaturesAsm, _TEXT + + +// ----------------------------------------------------------------------- +// The out-of-line portion of the code to enable preemptive GC. +// After the work is done, the code jumps back to the "pRejoinPoint" +// which should be emitted right after the inline part is generated. +// +// Assumptions: +// ebx = Thread +// Preserves +// all registers except ecx. +// +// ----------------------------------------------------------------------- +NESTED_ENTRY StubRareEnable, _TEXT, NoHandler + push eax + push edx + + push ebx + call C_FUNC(StubRareEnableWorker) + + pop edx + pop eax + ret +NESTED_END StubRareEnable, _TEXT + +NESTED_ENTRY StubRareDisableTHROW, _TEXT, NoHandler + push eax + push edx + + push ebx // Thread + call C_FUNC(StubRareDisableTHROWWorker) + + pop edx + pop eax + ret +NESTED_END StubRareDisableTHROW, _TEXT + +LEAF_ENTRY InternalExceptionWorker, _TEXT + pop edx // recover RETADDR + add esp, eax // release caller's args + push edx // restore RETADDR + jmp C_FUNC(JIT_InternalThrow) +LEAF_END InternalExceptionWorker, _TEXT + +// EAX -> number of caller arg bytes on the stack that we must remove before going +// to the throw helper, which assumes the stack is clean. +LEAF_ENTRY ArrayOpStubNullException, _TEXT + // kFactorReg and kTotalReg could not have been modified, but let's pop + // them anyway for consistency and to avoid future bugs. + pop esi + pop edi + mov ecx, CORINFO_NullReferenceException_ASM + jmp C_FUNC(InternalExceptionWorker) +LEAF_END ArrayOpStubNullException, _TEXT + +// EAX -> number of caller arg bytes on the stack that we must remove before going +// to the throw helper, which assumes the stack is clean. +LEAF_ENTRY ArrayOpStubRangeException, _TEXT + // kFactorReg and kTotalReg could not have been modified, but let's pop + // them anyway for consistency and to avoid future bugs. + pop esi + pop edi + mov ecx, CORINFO_IndexOutOfRangeException_ASM + jmp C_FUNC(InternalExceptionWorker) +LEAF_END ArrayOpStubRangeException, _TEXT + +// EAX -> number of caller arg bytes on the stack that we must remove before going +// to the throw helper, which assumes the stack is clean. +LEAF_ENTRY ArrayOpStubTypeMismatchException, _TEXT + // kFactorReg and kTotalReg could not have been modified, but let's pop + // them anyway for consistency and to avoid future bugs. + pop esi + pop edi + mov ecx, CORINFO_ArrayTypeMismatchException_ASM + jmp C_FUNC(InternalExceptionWorker) +LEAF_END ArrayOpStubTypeMismatchException, _TEXT + +// ------------------------------------------------------------------------------ +// This helper routine enregisters the appropriate arguments and makes the +// actual call. +// ------------------------------------------------------------------------------ +// void STDCALL CallDescrWorkerInternal(CallDescrWorkerParams * pParams) +NESTED_ENTRY CallDescrWorkerInternal, _TEXT, NoHandler + PROLOG_BEG + PROLOG_PUSH ebx + PROLOG_END + + mov ebx, [esp + ((2 + 1) * 4)] + + // compute padding size + mov eax, esp + mov ecx, [ebx + CallDescrData__numStackSlots] + shl ecx, 2 + sub eax, ecx + and eax, 15 + // adjust stack offset + sub esp, eax + + // copy the stack + mov ecx, [ebx +CallDescrData__numStackSlots] + mov eax, [ebx +CallDescrData__pSrc] + test ecx, ecx + jz LOCAL_LABEL(donestack) + lea eax, [eax + 4*ecx - 4] // last argument + push DWORD PTR [eax] + dec ecx + jz LOCAL_LABEL(donestack) + sub eax, 4 + push DWORD PTR [eax] + dec ecx + jz LOCAL_LABEL(donestack) + +LOCAL_LABEL(stackloop): + sub eax, 4 + push DWORD PTR [eax] + dec ecx + jnz LOCAL_LABEL(stackloop) + +LOCAL_LABEL(donestack): + // now we must push each field of the ArgumentRegister structure + mov eax, [ebx + CallDescrData__pArgumentRegisters] + mov edx, DWORD PTR [eax] + mov ecx, DWORD PTR [eax + 4] + + CHECK_STACK_ALIGNMENT + call [ebx + CallDescrData__pTarget] +#ifdef _DEBUG + nop // This is a tag that we use in an assert. Fcalls expect to + // be called from Jitted code or from certain blessed call sites like + // this one. (See HelperMethodFrame::InsureInit) +#endif + + // Save FP return value if necessary + mov ecx, [ebx + CallDescrData__fpReturnSize] + cmp ecx, 0 + je LOCAL_LABEL(ReturnsInt) + + cmp ecx, 4 + je LOCAL_LABEL(ReturnsFloat) + cmp ecx, 8 + je LOCAL_LABEL(ReturnsDouble) + // unexpected + jmp LOCAL_LABEL(Epilog) + +LOCAL_LABEL(ReturnsInt): + mov [ebx + CallDescrData__returnValue], eax + mov [ebx + CallDescrData__returnValue + 4], edx + +LOCAL_LABEL(Epilog): + // restore the stake pointer + lea esp, [ebp - 4] + + EPILOG_BEG + EPILOG_POP ebx + EPILOG_END + ret 4 + +LOCAL_LABEL(ReturnsFloat): + fstp DWORD PTR [ebx + CallDescrData__returnValue] // Spill the Float return value + jmp LOCAL_LABEL(Epilog) + +LOCAL_LABEL(ReturnsDouble): + fstp QWORD PTR [ebx + CallDescrData__returnValue] // Spill the Double return value + jmp LOCAL_LABEL(Epilog) +NESTED_END CallDescrWorkerInternal, _TEXT + +#ifdef _DEBUG +// int __fastcall HelperMethodFrameRestoreState(HelperMethodFrame*, struct MachState *) +LEAF_ENTRY HelperMethodFrameRestoreState, _TEXT + mov eax, edx // eax = MachState* +#else // _DEBUG +// int __fastcall HelperMethodFrameRestoreState(struct MachState *) +LEAF_ENTRY HelperMethodFrameRestoreState, _TEXT + mov eax, ecx // eax = MachState* +#endif // _DEBUG + // restore the registers from the m_MachState stucture. Note that + // we only do this for register that where not saved on the stack + // at the time the machine state snapshot was taken. + + cmp dword ptr [eax+MachState__pRetAddr], 0 + +#ifdef _DEBUG + jnz LOCAL_LABEL(noConfirm) + push ebp + push ebx + push edi + push esi + push ecx // HelperFrame* + call C_FUNC(HelperMethodFrameConfirmState) + // on return, eax = MachState* + cmp DWORD PTR [eax + MachState__pRetAddr], 0 +LOCAL_LABEL(noConfirm): +#endif // _DEBUG + + jz LOCAL_LABEL(doRet) + + lea edx, [eax + MachState__esi] // Did we have to spill ESI + cmp [eax + MachState__pEsi], edx + jnz LOCAL_LABEL(SkipESI) + mov esi, [edx] // Then restore it + +LOCAL_LABEL(SkipESI): + lea edx, [eax + MachState__edi] // Did we have to spill EDI + cmp [eax + MachState__pEdi], edx + jnz LOCAL_LABEL(SkipEDI) + mov edi, [edx] // Then restore it + +LOCAL_LABEL(SkipEDI): + lea edx, [eax + MachState__ebx] // Did we have to spill EBX + cmp [eax + MachState__pEbx], edx + jnz LOCAL_LABEL(SkipEBX) + mov ebx, [edx] // Then restore it + +LOCAL_LABEL(SkipEBX): + lea edx, [eax + MachState__ebp] // Did we have to spill EBP + cmp [eax + MachState__pEbp], edx + jnz LOCAL_LABEL(SkipEBP) + mov ebp, [edx] // Then restore it + +LOCAL_LABEL(SkipEBP): +LOCAL_LABEL(doRet): + xor eax, eax + ret +LEAF_END HelperMethodFrameRestoreState, _TEXT + +#ifdef FEATURE_HIJACK + +// A JITted method's return address was hijacked to return to us here. +// VOID OnHijackTripThread() +NESTED_ENTRY OnHijackTripThread, _TEXT, NoHandler + // Don't fiddle with this unless you change HijackFrame::UpdateRegDisplay + // and HijackArgs + push eax // make room for the real return address (Eip) + push ebp + push eax + push ecx + push edx + push ebx + push esi + push edi + + // unused space for floating point state + sub esp,12 + + push esp + call C_FUNC(OnHijackWorker) + + // unused space for floating point state + add esp,12 + + pop edi + pop esi + pop ebx + pop edx + pop ecx + pop eax + pop ebp + ret // return to the correct place, adjusted by our caller +NESTED_END OnHijackTripThread, _TEXT + +// VOID OnHijackFPTripThread() +NESTED_ENTRY OnHijackFPTripThread, _TEXT, NoHandler + // Don't fiddle with this unless you change HijackFrame::UpdateRegDisplay + // and HijackArgs + push eax // make room for the real return address (Eip) + push ebp + push eax + push ecx + push edx + push ebx + push esi + push edi + + sub esp,12 + + // save top of the floating point stack (there is return value passed in it) + // save full 10 bytes to avoid precision loss + fstp QWORD PTR [esp] + + push esp + call C_FUNC(OnHijackWorker) + + // restore top of the floating point stack + fld QWORD PTR [esp] + + add esp,12 + + pop edi + pop esi + pop ebx + pop edx + pop ecx + pop eax + pop ebp + ret // return to the correct place, adjusted by our caller +NESTED_END OnHijackFPTripThread, _TEXT + +#endif // FEATURE_HIJACK + +// ========================================================================== +// This function is reached only via the embedded ImportThunkGlue code inside +// an NDirectMethodDesc. It's purpose is to load the DLL associated with an +// N/Direct method, then backpatch the DLL target into the methoddesc. +// +// Initial state: +// +// Preemptive GC is *enabled*: we are actually in an unmanaged state. +// +// +// [esp+...] - The *unmanaged* parameters to the DLL target. +// [esp+4] - Return address back into the JIT'ted code that made +// the DLL call. +// [esp] - Contains the "return address." Because we got here +// thru a call embedded inside a MD, this "return address" +// gives us an easy to way to find the MD (which was the +// whole purpose of the embedded call manuever.) +// +// +// +// ========================================================================== +LEAF_ENTRY NDirectImportThunk, _TEXT + // Preserve argument registers + push ecx + push edx + + // Invoke the function that does the real work. + push eax + call C_FUNC(NDirectImportWorker) + + // Restore argument registers + pop edx + pop ecx + + // If we got back from NDirectImportWorker, the MD has been successfully + // linked and "eax" contains the DLL target. Proceed to execute the + // original DLL call. + jmp eax // Jump to DLL target +LEAF_END NDirectImportThunk, _TEXT + +// ========================================================================== +// The call in fixup precode initally points to this function. +// The pupose of this function is to load the MethodDesc and forward the call the prestub. +LEAF_ENTRY PrecodeFixupThunk, _TEXT + // Pop the return address. It points right after the call instruction in the precode. + pop eax + push esi + push edi + + // Inline computation done by FixupPrecode::GetMethodDesc() + movzx esi, BYTE PTR [eax + 2] // m_PrecodeChunkIndex + movzx edi, BYTE PTR [eax + 1] // m_MethodDescChunkIndex + mov eax, DWORD PTR [eax + esi*8 +3] + lea eax, [eax + edi*4] + + pop edi + pop esi + jmp C_FUNC(ThePreStub) +LEAF_END PrecodeFixupThunk, _TEXT + +// void __stdcall UM2MThunk_WrapperHelper(void *pThunkArgs, +// int argLen, +// void *pAddr, +// UMEntryThunk *pEntryThunk, +// Thread *pThread) +NESTED_ENTRY UM2MThunk_WrapperHelper, _TEXT, NoHandler + push ebx + + mov eax, [esp + 20] // pEntryThunk + mov ecx, [esp + 24] // pThread + mov ebx, [esp + 8] // pThunkArgs + call [esp + 16] // pAddr + + pop ebx + + ret 20 +NESTED_END UM2MThunk_WrapperHelper, _TEXT + +NESTED_ENTRY UMThunkStubRareDisable, _TEXT, NoHandler + push eax + push ecx + + push eax // Push the UMEntryThunk + push ecx // Push thread + call C_FUNC(UMThunkStubRareDisableWorker) + + pop ecx + pop eax + ret +NESTED_END UMThunkStubRareDisable, _TEXT + +// +// Used to get the current instruction pointer value +// +// UINT_PTR __stdcall GetCurrentIP(void); +LEAF_ENTRY GetCurrentIP, _TEXT + mov eax, [esp] + ret +LEAF_END GetCurrentIP, _TEXT + +// LPVOID __stdcall GetCurrentSP(void); +LEAF_ENTRY GetCurrentSP, _TEXT + mov eax, esp + ret +LEAF_END GetCurrentSP, _TEXT + +// ========================================================================== +// Invoked for vararg forward P/Invoke calls as a stub. +// Except for secret return buffer, arguments come on the stack so EDX is available as scratch. +// EAX - the NDirectMethodDesc +// ECX - may be return buffer address +// [ESP + 4] - the VASigCookie +// +NESTED_ENTRY VarargPInvokeStub, _TEXT, NoHandler + // EDX <- VASigCookie + mov edx, [esp + 4] // skip retaddr + + mov edx, [edx + VASigCookie__StubOffset] + test edx, edx + + jz LOCAL_LABEL(GoCallVarargWorker) + // --------------------------------------- + + // EAX contains MD ptr for the IL stub + jmp edx + +LOCAL_LABEL(GoCallVarargWorker): + // + // MD ptr in EAX, VASigCookie ptr at [esp+4] + // + STUB_PROLOG + + mov esi, esp + + // save pMD + push eax + + push eax // pMD + push dword ptr [esi + 4*7] // pVaSigCookie + push esi // pTransitionBlock + + call C_FUNC(VarargPInvokeStubWorker) + + // restore pMD + pop eax + + STUB_EPILOG + + // jump back to the helper - this time it won't come back here as the stub already exists + jmp C_FUNC(VarargPInvokeStub) +NESTED_END VarargPInvokeStub, _TEXT + +// ========================================================================== +// Invoked for marshaling-required unmanaged CALLI calls as a stub. +// EAX - the unmanaged target +// ECX, EDX - arguments +// [ESP + 4] - the VASigCookie +// +LEAF_ENTRY GenericPInvokeCalliHelper, _TEXT + // save the target + push eax + + // EAX <- VASigCookie + mov eax, [esp + 8] // skip target and retaddr + + mov eax, [eax + VASigCookie__StubOffset] + test eax, eax + + jz LOCAL_LABEL(GoCallCalliWorker) + // --------------------------------------- + + push eax + + // stack layout at this point: + // + // | ... | + // | stack arguments | ESP + 16 + // +----------------------+ + // | VASigCookie* | ESP + 12 + // +----------------------+ + // | return address | ESP + 8 + // +----------------------+ + // | CALLI target address | ESP + 4 + // +----------------------+ + // | stub entry point | ESP + 0 + // ------------------------ + + // remove VASigCookie from the stack + mov eax, [esp + 8] + mov [esp + 12], eax + + // move stub entry point below the RA + mov eax, [esp] + mov [esp + 8], eax + + // load EAX with the target address + pop eax + pop eax + + // stack layout at this point: + // + // | ... | + // | stack arguments | ESP + 8 + // +----------------------+ + // | return address | ESP + 4 + // +----------------------+ + // | stub entry point | ESP + 0 + // ------------------------ + + // CALLI target address is in EAX + ret + +LOCAL_LABEL(GoCallCalliWorker): + // the target is on the stack and will become m_Datum of PInvokeCalliFrame + // call the stub generating worker + pop eax + + // + // target ptr in EAX, VASigCookie ptr in EDX + // + + STUB_PROLOG + + mov esi, esp + + // save target + push eax + + push eax // unmanaged target + push dword ptr [esi + 4*7] // pVaSigCookie (first stack argument) + push esi // pTransitionBlock + + call C_FUNC(GenericPInvokeCalliStubWorker) + + // restore target + pop eax + + STUB_EPILOG + + // jump back to the helper - this time it won't come back here as the stub already exists + jmp C_FUNC(GenericPInvokeCalliHelper) +LEAF_END GenericPInvokeCalliHelper, _TEXT + +#ifdef FEATURE_PREJIT + +// ========================================================================= +NESTED_ENTRY StubDispatchFixupStub, _TEXT, NoHandler + STUB_PROLOG + + mov esi, esp + + push 0 + push 0 + + push eax // siteAddrForRegisterIndirect (for tailcalls) + push esi // pTransitionBlock + + call C_FUNC(StubDispatchFixupWorker) + + STUB_EPILOG + +PATCH_LABEL StubDispatchFixupPatchLabel + // Tailcall target + jmp eax + + // This will never be executed. It is just to help out stack-walking logic + // which disassembles the epilog to unwind the stack. + ret +NESTED_END StubDispatchFixupStub, _TEXT + +// ========================================================================== +NESTED_ENTRY ExternalMethodFixupStub, _TEXT_ NoHandler + // pop off the return address to the stub + // leaving the actual caller's return address on top of the stack + pop eax + + STUB_PROLOG + + mov esi, esp + + // EAX is return address into CORCOMPILE_EXTERNAL_METHOD_THUNK. Subtract 5 to get start address. + sub eax, 5 + + push 0 + push 0 + + push eax + + // pTransitionBlock + push esi + + call C_FUNC(ExternalMethodFixupWorker) + + // eax now contains replacement stub. PreStubWorker will never return + // NULL (it throws an exception if stub creation fails.) + + // From here on, mustn't trash eax + + STUB_EPILOG + +PATCH_LABEL ExternalMethodFixupPatchLabel + // Tailcall target + jmp eax + + // This will never be executed. It is just to help out stack-walking logic + // which disassembles the epilog to unwind the stack. + ret +NESTED_END ExternalMethodFixupStub, _TEXT + +#ifdef FEATURE_READYTORUN +// ========================================================================== +NESTED_ENTRY DelayLoad_MethodCall, _TEXT, NoHandler + STUB_PROLOG_2_HIDDEN_ARGS + + mov esi, esp + + push ecx + push edx + + push eax + + // pTransitionBlock + push esi + + call C_FUNC(ExternalMethodFixupWorker) + + // eax now contains replacement stub. PreStubWorker will never return + // NULL (it throws an exception if stub creation fails.) + + // From here on, mustn't trash eax + + STUB_EPILOG + + // Share the patch label + jmp C_FUNC(ExternalMethodFixupPatchLabel) + + // This will never be executed. It is just to help out stack-walking logic + // which disassembles the epilog to unwind the stack. + ret +NESTED_END DelayLoad_MethodCall, _TEXT + +#endif // FEATURE_READYTORUN + +// ======================================================================================= +// The call in softbound vtable slots initially points to this function. +// The pupose of this function is to transfer the control to right target and +// to optionally patch the target of the jump so that we do not take this slow path again. +// +NESTED_ENTRY VirtualMethodFixupStub, _TEXT, NoHandler + // Pop the return address. It points right after the call instruction in the thunk. + pop eax + // Calculate the address of the thunk + sub eax, 5 + + // Push ebp frame to get good callstack under debugger + PROLOG_BEG + + // Preserve argument registers + PROLOG_PUSH ecx + PROLOG_PUSH edx + + // Set frame pointer + PROLOG_END + + push eax // address of the thunk + push ecx // this ptr + call C_FUNC(VirtualMethodFixupWorker) + + // Restore stack pointer + EPILOG_BEG + + // Restore argument registers + EPILOG_POP edx + EPILOG_POP ecx + + // Pop ebp frame + EPILOG_END + +PATCH_LABEL VirtualMethodFixupPatchLabel + // Proceed to execute the actual method. + jmp eax + + // This will never be executed. It is just to help out stack-walking logic + // which disassembles the epilog to unwind the stack. + ret +NESTED_END VirtualMethodFixupStub, _TEXT + +#endif // FEATURE_PREJIT + +NESTED_ENTRY ThePreStub, _TEXT, NoHandler + STUB_PROLOG + + mov esi, esp + + // Compute padding size + lea ebx, [esp - 8] + and ebx, 15 + // Adjust stack offset + sub esp, ebx + + // EAX contains MethodDesc* from the precode. Push it here as argument + // for PreStubWorker + push eax + + push esi + + CHECK_STACK_ALIGNMENT + call C_FUNC(PreStubWorker) + + // eax now contains replacement stub. PreStubWorker will never return + // NULL (it throws an exception if stub creation fails.) + + // From here on, mustn't trash eax + + // Restore stack pointer + mov esp, esi + + STUB_EPILOG + + // Tailcall target + jmp eax + + // This will never be executed. It is just to help out stack-walking logic + // which disassembles the epilog to unwind the stack. + ret +NESTED_END ThePreStub, _TEXT + +// This method does nothing. It's just a fixed function for the debugger to put a breakpoint +// on so that it can trace a call target. +LEAF_ENTRY ThePreStubPatch, _TEXT + // make sure that the basic block is unique + test eax,34 + +PATCH_LABEL ThePreStubPatchLabel + ret +LEAF_END ThePreStubPatch, _TEXT + +#ifdef FEATURE_READYTORUN +// ========================================================================== +// Define helpers for delay loading of readytorun helpers + +.macro DYNAMICHELPER frameFlags, suffix + +NESTED_ENTRY DelayLoad_Helper\suffix, _TEXT, NoHandler + STUB_PROLOG_2_HIDDEN_ARGS + + mov esi, esp + + push \frameFlags + push ecx // module + push edx // section index + + push eax // indirection cell address. + push esi // pTransitionBlock + + call C_FUNC(DynamicHelperWorker) + test eax,eax + jnz LOCAL_LABEL(TailCallDelayLoad_Helper\suffix) + + mov eax, [esi] // The result is stored in the argument area of the transition block + STUB_EPILOG_RETURN + ret + +LOCAL_LABEL(TailCallDelayLoad_Helper\suffix): + STUB_EPILOG + jmp eax +NESTED_END DelayLoad_Helper\suffix, _TEXT +.endm + +DYNAMICHELPER DynamicHelperFrameFlags_Default +DYNAMICHELPER DynamicHelperFrameFlags_ObjectArg, _Obj +DYNAMICHELPER (DynamicHelperFrameFlags_ObjectArg | DynamicHelperFrameFlags_ObjectArg2), _ObjObj + +#endif // FEATURE_READYTORUN + +NESTED_ENTRY ResolveWorkerAsmStub, _TEXT, NoHandler + // + // The stub arguments are where we want to setup the TransitionBlock. We will + // setup the TransitionBlock later once we can trash them + // + // push ebp-frame + // push ebp + // mov ebp,esp + + // save CalleeSavedRegisters + // push ebx + + push esi + push edi + + // push ArgumentRegisters + push ecx + push edx + + mov esi, esp + + push [esi + 4*4] // dispatch token + push [esi + 5*4] // siteAddrForRegisterIndirect + push esi // pTransitionBlock + + // Setup up proper EBP frame now that the stub arguments can be trashed + mov [esi + 4*4],ebx + mov [esi + 5*4],ebp + lea ebp, [esi + 5*4] + + // Make the call + call C_FUNC(VSD_ResolveWorker) + + // From here on, mustn't trash eax + + // pop ArgumentRegisters + pop edx + pop ecx + + // pop CalleeSavedRegisters + pop edi + pop esi + pop ebx + pop ebp + + // Now jump to the target + jmp eax // continue on into the method +NESTED_END ResolveWorkerAsmStub, _TEXT diff --git a/src/vm/i386/asmhelpers.asm b/src/vm/i386/asmhelpers.asm index 66a22b7..0456be8 100644 --- a/src/vm/i386/asmhelpers.asm +++ b/src/vm/i386/asmhelpers.asm @@ -43,7 +43,6 @@ TlsGetValue PROTO stdcall ifdef FEATURE_HIJACK EXTERN _OnHijackWorker@4:PROC endif ;FEATURE_HIJACK -EXTERN _COMPlusEndCatch@20:PROC EXTERN _COMPlusFrameHandler:PROC ifdef FEATURE_COMINTEROP EXTERN _COMPlusFrameHandlerRevCom:PROC @@ -1005,33 +1004,6 @@ OnHijackFPTripThread ENDP endif ; FEATURE_HIJACK -; Note that the debugger skips this entirely when doing SetIP, -; since COMPlusCheckForAbort should always return 0. Excep.cpp:LeaveCatch -; asserts that to be true. If this ends up doing more work, then the -; debugger may need additional support. -; void __stdcall JIT_EndCatch(); -JIT_EndCatch PROC stdcall public - - ; make temp storage for return address, and push the address of that - ; as the last arg to COMPlusEndCatch - mov ecx, [esp] - push ecx; - push esp; - - ; push the rest of COMPlusEndCatch's args, right-to-left - push esi - push edi - push ebx - push ebp - - call _COMPlusEndCatch@20 ; returns old esp value in eax, stores jump address - ; now eax = new esp, [esp] = new eip - - pop edx ; edx = new eip - mov esp, eax ; esp = new esp - jmp edx ; eip = new eip - -JIT_EndCatch ENDP ;========================================================================== ; This function is reached only via the embedded ImportThunkGlue code inside diff --git a/src/vm/i386/cgencpu.h b/src/vm/i386/cgencpu.h index 2da9882..99f4eb4 100644 --- a/src/vm/i386/cgencpu.h +++ b/src/vm/i386/cgencpu.h @@ -43,6 +43,10 @@ EXTERN_C void STDCALL PInvokeStackImbalanceHelper(void); EXTERN_C void STDCALL CopyCtorCallStub(void); #endif // !FEATURE_CORECLR +#ifdef FEATURE_STUBS_AS_IL +EXTERN_C void SinglecastDelegateInvokeStub(); +#endif // FEATURE_STUBS_AS_IL + BOOL Runtime_Test_For_SSE2(); #ifdef CROSSGEN_COMPILE @@ -476,7 +480,7 @@ inline BOOL IsUnmanagedValueTypeReturnedByRef(UINT sizeofvaluetype) } #include -DECLSPEC_ALIGN(4) struct UMEntryThunkCode +struct DECLSPEC_ALIGN(4) UMEntryThunkCode { BYTE m_alignpad[2]; // used to guarantee alignment of backpactched portion BYTE m_movEAX; //MOV EAX,imm32 @@ -562,6 +566,7 @@ inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode) // #define JIT_GetSharedGCStaticBaseNoCtor // #define JIT_GetSharedNonGCStaticBaseNoCtor +#ifndef FEATURE_PAL #define JIT_ChkCastClass JIT_ChkCastClass #define JIT_ChkCastClassSpecial JIT_ChkCastClassSpecial #define JIT_IsInstanceOfClass JIT_IsInstanceOfClass @@ -569,5 +574,5 @@ inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode) #define JIT_IsInstanceOfInterface JIT_IsInstanceOfInterface #define JIT_NewCrossContext JIT_NewCrossContext #define JIT_Stelem_Ref JIT_Stelem_Ref - +#endif // FEATURE_PAL #endif // __cgenx86_h__ diff --git a/src/vm/i386/cgenx86.cpp b/src/vm/i386/cgenx86.cpp index ff2f2df..08ccd01 100644 --- a/src/vm/i386/cgenx86.cpp +++ b/src/vm/i386/cgenx86.cpp @@ -760,6 +760,7 @@ 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. //------------------------------------------------------------------------- @@ -809,6 +810,7 @@ Stub *GenerateUMThunkPrestub() RETURN psl->Link(SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap()); } +#endif // _TARGET_X86_ && !FEATURE_STUBS_AS_IL Stub *GenerateInitPInvokeFrameHelper() { @@ -1593,6 +1595,7 @@ extern "C" VOID STDCALL StubRareDisableTHROWWorker(Thread *pThread) pThread->HandleThreadAbort(); } +#ifndef FEATURE_PAL // Note that this logic is copied below, in PopSEHRecords __declspec(naked) VOID __cdecl PopSEHRecords(LPVOID pTargetSP) @@ -1614,6 +1617,7 @@ VOID __cdecl PopSEHRecords(LPVOID pTargetSP) retn } } +#endif // FEATURE_PAL ////////////////////////////////////////////////////////////////////////////// // @@ -1680,9 +1684,10 @@ void ResumeAtJit(PCONTEXT pContext, LPVOID oldESP) #endif // !EnC_SUPPORTED +#ifndef FEATURE_PAL #pragma warning(push) #pragma warning(disable: 4035) -DWORD getcpuid(DWORD arg, unsigned char result[16]) +extern "C" DWORD __stdcall getcpuid(DWORD arg, unsigned char result[16]) { LIMITED_METHOD_CONTRACT @@ -1709,7 +1714,7 @@ DWORD getcpuid(DWORD arg, unsigned char result[16]) // Arg3 is a pointer to the return buffer // No need to check whether or not CPUID is supported because we have already called CPUID with success to come here. -DWORD getextcpuid(DWORD arg1, DWORD arg2, unsigned char result[16]) +extern "C" DWORD __stdcall getextcpuid(DWORD arg1, DWORD arg2, unsigned char result[16]) { LIMITED_METHOD_CONTRACT @@ -1730,8 +1735,75 @@ DWORD getextcpuid(DWORD arg1, DWORD arg2, unsigned char result[16]) } } +extern "C" DWORD __stdcall xmmYmmStateSupport() +{ + // No CONTRACT + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + + __asm + { + mov ecx, 0 ; Specify xcr0 + xgetbv ; result in EDX:EAX + and eax, 06H + cmp eax, 06H ; check OS has enabled both XMM and YMM state support + jne not_supported + mov eax, 1 + jmp done + not_supported: + mov eax, 0 + done: + } +} + #pragma warning(pop) +#else // !FEATURE_PAL + +extern "C" DWORD __stdcall getcpuid(DWORD arg, unsigned char result[16]) +{ + DWORD eax; + __asm(" xor %%ecx, %%ecx\n" \ + " cpuid\n" \ + " mov %%eax, 0(%[result])\n" \ + " mov %%ebx, 4(%[result])\n" \ + " mov %%ecx, 8(%[result])\n" \ + " mov %%edx, 12(%[result])\n" \ + : "=a"(eax) /*output in eax*/\ + : "a"(arg), [result]"r"(result) /*inputs - arg in eax, result in any register*/\ + : "eax", "rbx", "ecx", "edx", "memory" /* registers that are clobbered, *result is clobbered */ + ); + return eax; +} + +extern "C" DWORD __stdcall getextcpuid(DWORD arg1, DWORD arg2, unsigned char result[16]) +{ + DWORD eax; + __asm(" cpuid\n" \ + " mov %%eax, 0(%[result])\n" \ + " mov %%ebx, 4(%[result])\n" \ + " mov %%ecx, 8(%[result])\n" \ + " mov %%edx, 12(%[result])\n" \ + : "=a"(eax) /*output in eax*/\ + : "c"(arg1), "a"(arg2), [result]"r"(result) /*inputs - arg1 in ecx, arg2 in eax, result in any register*/\ + : "eax", "rbx", "ecx", "edx", "memory" /* registers that are clobbered, *result is clobbered */ + ); + return eax; +} + +extern "C" DWORD __stdcall xmmYmmStateSupport() +{ + DWORD eax; + __asm(" xgetbv\n" \ + : "=a"(eax) /*output in eax*/\ + : "c"(0) /*inputs - 0 in ecx*/\ + : "eax", "edx" /* registers that are clobbered*/ + ); + // check OS has enabled both XMM and YMM state support + return ((eax & 0x06) == 0x06) ? 1 : 0; +} + +#endif // !FEATURE_PAL // This function returns the number of logical processors on a given physical chip. If it cannot // determine the number of logical cpus, or the machine is not populated uniformly with the same @@ -1761,13 +1833,14 @@ DWORD GetLogicalCpuCount() PAL_TRY(Param *, pParam, ¶m) { unsigned char buffer[16]; + DWORD* dwBuffer = NULL; DWORD maxCpuId = getcpuid(0, buffer); if (maxCpuId < 1) goto lDone; - DWORD* dwBuffer = (DWORD*)buffer; + dwBuffer = (DWORD*)buffer; if (dwBuffer[1] == 'uneG') { if (dwBuffer[3] == 'Ieni') { diff --git a/src/vm/i386/excepcpu.h b/src/vm/i386/excepcpu.h index 3f2f081..ff540e7 100644 --- a/src/vm/i386/excepcpu.h +++ b/src/vm/i386/excepcpu.h @@ -28,12 +28,37 @@ class Thread; // Actually, the handler getting set is properly registered #endif +#ifdef FEATURE_PAL + +extern VOID SetSEHRecord(PEXCEPTION_REGISTRATION_RECORD record); +extern VOID ResetSEHRecord(PEXCEPTION_REGISTRATION_RECORD record); + +#define INSTALL_SEH_RECORD(record) \ + SetSEHRecord(record); \ + +#define UNINSTALL_SEH_RECORD(record) \ + ResetSEHRecord(record); + +#else // FEATURE_PAL + +#define INSTALL_SEH_RECORD(record) \ + { \ + (record)->Next = (PEXCEPTION_REGISTRATION_RECORD)__readfsdword(0); \ + __writefsdword(0, (DWORD) (record)); \ + } + +#define UNINSTALL_SEH_RECORD(record) \ + { \ + __writefsdword(0, (DWORD) ((record)->Next)); \ + } + +#endif // FEATURE_PAL + #define INSTALL_EXCEPTION_HANDLING_RECORD(record) \ { \ PEXCEPTION_REGISTRATION_RECORD __record = (record); \ _ASSERTE(__record < GetCurrentSEHRecord()); \ - __record->Next = (PEXCEPTION_REGISTRATION_RECORD)__readfsdword(0); \ - __writefsdword(0, (DWORD)__record); \ + INSTALL_SEH_RECORD(record); \ } // @@ -44,7 +69,7 @@ class Thread; { \ PEXCEPTION_REGISTRATION_RECORD __record = (record); \ _ASSERTE(__record == GetCurrentSEHRecord()); \ - __writefsdword(0, (DWORD)__record->Next); \ + UNINSTALL_SEH_RECORD(record); \ } // stackOverwriteBarrier is used to detect overwriting of stack which will mess up handler registration diff --git a/src/vm/i386/excepx86.cpp b/src/vm/i386/excepx86.cpp index 27c923b..71200f6 100644 --- a/src/vm/i386/excepx86.cpp +++ b/src/vm/i386/excepx86.cpp @@ -19,7 +19,7 @@ #include "comutilnative.h" #include "sigformat.h" #include "siginfo.hpp" -#include "gc.h" +#include "gcheaputilities.h" #include "eedbginterfaceimpl.h" //so we can clearexception in COMPlusThrow #include "perfcounters.h" #include "eventtrace.h" @@ -53,13 +53,15 @@ VOID STDCALL ResumeAtJitEHHelper(EHContext *pContext); int STDCALL CallJitEHFilterHelper(size_t *pShadowSP, EHContext *pContext); VOID STDCALL CallJitEHFinallyHelper(size_t *pShadowSP, EHContext *pContext); +typedef void (*RtlUnwindCallbackType)(void); + BOOL CallRtlUnwind(EXCEPTION_REGISTRATION_RECORD *pEstablisherFrame, - void *callback, + RtlUnwindCallbackType callback, EXCEPTION_RECORD *pExceptionRecord, void *retval); BOOL CallRtlUnwindSafe(EXCEPTION_REGISTRATION_RECORD *pEstablisherFrame, - void *callback, + RtlUnwindCallbackType callback, EXCEPTION_RECORD *pExceptionRecord, void *retval); } @@ -371,6 +373,7 @@ CPFH_AdjustContextForThreadSuspensionRace(CONTEXT *pContext, Thread *pThread) { WRAPPER_NO_CONTRACT; +#ifndef FEATURE_PAL PCODE f_IP = GetIP(pContext); if (Thread::IsAddrOfRedirectFunc((PVOID)f_IP)) { @@ -427,22 +430,13 @@ CPFH_AdjustContextForThreadSuspensionRace(CONTEXT *pContext, Thread *pThread) SetIP(pContext, GetIP(pThread->m_OSContext) - 1); STRESS_LOG1(LF_EH, LL_INFO100, "CPFH_AdjustContextForThreadSuspensionRace: Case 4 setting IP = %x\n", pContext->Eip); } +#else + PORTABILITY_ASSERT("CPFH_AdjustContextForThreadSuspensionRace"); +#endif } #endif // FEATURE_HIJACK -// We want to leave true null reference exceptions alone. But if we are -// trashing memory, we don't want the application to swallow it. The 0x100 -// below will give us false positives for debugging, if the app is accessing -// a field more than 256 bytes down an object, where the reference is null. -// -// Removed use of the IgnoreUnmanagedExceptions reg key...simply return false now. -// -static inline BOOL -CPFH_ShouldIgnoreException(EXCEPTION_RECORD *pExceptionRecord) { - LIMITED_METHOD_CONTRACT; - return FALSE; -} static inline void CPFH_UpdatePerformanceCounters() { @@ -620,7 +614,7 @@ EXCEPTION_DISPOSITION ClrDebuggerDoUnwindAndIntercept(EXCEPTION_REGISTRATION_REC // This rethrow issue does not affect COMPLUS exceptions since we always create a brand new exception // record for them in RaiseTheExceptionInternalOnly. BOOL CallRtlUnwindSafe(EXCEPTION_REGISTRATION_RECORD *pEstablisherFrame, - void *callback, + RtlUnwindCallbackType callback, EXCEPTION_RECORD *pExceptionRecord, void *retval) { @@ -1153,6 +1147,7 @@ CPFH_RealFirstPassHandler( // ExceptionContinueSearch, etc. pExInfo->m_pExceptionPointers = &exceptionPointers; +#ifndef FEATURE_PAL if (bRethrownException || bNestedException) { _ASSERTE(pExInfo->m_pPrevNestedInfo != NULL); @@ -1161,6 +1156,7 @@ CPFH_RealFirstPassHandler( // ExceptionContinueSearch, etc. SetStateForWatsonBucketing(bRethrownException, pExInfo->GetPreviousExceptionTracker()->GetThrowableAsHandle()); END_SO_INTOLERANT_CODE; } +#endif #ifdef DEBUGGING_SUPPORTED // @@ -1975,11 +1971,17 @@ PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(CONTEXT * pContext) } #if !defined(DACCESS_COMPILE) +#ifdef FEATURE_PAL +static PEXCEPTION_REGISTRATION_RECORD CurrentSEHRecord = EXCEPTION_CHAIN_END; +#endif PEXCEPTION_REGISTRATION_RECORD GetCurrentSEHRecord() { WRAPPER_NO_CONTRACT; +#ifdef FEATURE_PAL + LPVOID fs0 = CurrentSEHRecord; +#else // FEATURE_PAL LPVOID fs0 = (LPVOID)__readfsdword(0); #if 0 // This walk is too expensive considering we hit it every time we a CONTRACT(NOTHROW) @@ -2010,19 +2012,39 @@ PEXCEPTION_REGISTRATION_RECORD GetCurrentSEHRecord() pEHR = pEHR->Next; } #endif -#endif +#endif // 0 +#endif // FEATURE_PAL return (EXCEPTION_REGISTRATION_RECORD*) fs0; } +#ifdef FEATURE_PAL +VOID SetSEHRecord(PEXCEPTION_REGISTRATION_RECORD record) +{ + WRAPPER_NO_CONTRACT; + record->Next = CurrentSEHRecord; + CurrentSEHRecord = record; +} + +VOID ResetSEHRecord(PEXCEPTION_REGISTRATION_RECORD record) +{ + CurrentSEHRecord = record->Next; +} +#endif // FEATURE_PAL + PEXCEPTION_REGISTRATION_RECORD GetFirstCOMPlusSEHRecord(Thread *pThread) { WRAPPER_NO_CONTRACT; +#ifndef FEATURE_PAL EXCEPTION_REGISTRATION_RECORD *pEHR = *(pThread->GetExceptionListPtr()); if (pEHR == EXCEPTION_CHAIN_END || IsUnmanagedToManagedSEHHandler(pEHR)) { return pEHR; } else { return GetNextCOMPlusSEHRecord(pEHR); } +#else // FEATURE_PAL + PORTABILITY_ASSERT("GetFirstCOMPlusSEHRecord"); + return NULL; +#endif // FEATURE_PAL } @@ -2048,7 +2070,11 @@ PEXCEPTION_REGISTRATION_RECORD GetPrevSEHRecord(EXCEPTION_REGISTRATION_RECORD *n VOID SetCurrentSEHRecord(EXCEPTION_REGISTRATION_RECORD *pSEH) { WRAPPER_NO_CONTRACT; +#ifndef FEATURE_PAL *GetThread()->GetExceptionListPtr() = pSEH; +#else // FEATURE_PAL + _ASSERTE("NYI"); +#endif // FEATURE_PAL } @@ -2085,6 +2111,7 @@ BOOL PopNestedExceptionRecords(LPVOID pTargetSP, BOOL bCheckForUnknownHandlers) STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_SO_TOLERANT; +#ifndef FEATURE_PAL PEXCEPTION_REGISTRATION_RECORD pEHR = GetCurrentSEHRecord(); while ((LPVOID)pEHR < pTargetSP) @@ -2140,6 +2167,10 @@ BOOL PopNestedExceptionRecords(LPVOID pTargetSP, BOOL bCheckForUnknownHandlers) SetCurrentSEHRecord(pEHR); } return FALSE; +#else // FEATURE_PAL + PORTABILITY_ASSERT("PopNestedExceptionRecords"); + return FALSE; +#endif // FEATURE_PAL } // @@ -2245,6 +2276,7 @@ int COMPlusThrowCallbackHelper(IJitManager *pJitManager, int iFilt = 0; BOOL impersonating = FALSE; +#ifndef FEATURE_PAL EX_TRY { GCPROTECT_BEGIN (throwable); @@ -2295,6 +2327,10 @@ int COMPlusThrowCallbackHelper(IJitManager *pJitManager, EX_END_CATCH(SwallowAllExceptions) return iFilt; +#else // FEATURE_PAL + PORTABILITY_ASSERT("COMPlusThrowCallbackHelper"); + return EXCEPTION_CONTINUE_SEARCH; +#endif // FEATURE_PAL } //****************************************************************************** @@ -2409,6 +2445,7 @@ StackWalkAction COMPlusThrowCallback( // SWA value pData->bSkipLastElement = FALSE; } +#ifndef FEATURE_PAL // Check for any impersonation on the frame and save that for use during EH filter callbacks OBJECTREF* pRefSecDesc = pCf->GetAddrOfSecurityObject(); if (pRefSecDesc != NULL && *pRefSecDesc != NULL) @@ -2427,6 +2464,7 @@ StackWalkAction COMPlusThrowCallback( // SWA value } } } +#endif // !FEATURE_PAL // now we've got the stack trace, if we aren't allowed to catch this and we're first pass, return if (pData->bDontCatch) @@ -2604,9 +2642,9 @@ StackWalkAction COMPlusThrowCallback( // SWA value // EX_CATCH just above us. If not, the exception if ( IsFilterHandler(&EHClause) && ( offs > EHClause.FilterOffset - || offs == EHClause.FilterOffset && !start_adjust) + || (offs == EHClause.FilterOffset && !start_adjust) ) && ( offs < EHClause.HandlerStartPC - || offs == EHClause.HandlerStartPC && !end_adjust)) { + || (offs == EHClause.HandlerStartPC && !end_adjust) )) { STRESS_LOG4(LF_EH, LL_INFO100, "COMPlusThrowCallback: Fault inside filter [%d,%d] startAdj %d endAdj %d\n", EHClause.FilterOffset, EHClause.HandlerStartPC, start_adjust, end_adjust); @@ -2978,9 +3016,9 @@ StackWalkAction COMPlusUnwindCallback (CrawlFrame *pCf, ThrowCallbackType *pData if ( IsFilterHandler(&EHClause) && ( offs > EHClause.FilterOffset - || offs == EHClause.FilterOffset && !start_adjust) + || (offs == EHClause.FilterOffset && !start_adjust) ) && ( offs < EHClause.HandlerStartPC - || offs == EHClause.HandlerStartPC && !end_adjust) + || (offs == EHClause.HandlerStartPC && !end_adjust) ) ) { STRESS_LOG4(LF_EH, LL_INFO100, "COMPlusUnwindCallback: Fault inside filter [%d,%d] startAdj %d endAdj %d\n", EHClause.FilterOffset, EHClause.HandlerStartPC, start_adjust, end_adjust); @@ -3731,4 +3769,10 @@ AdjustContextForVirtualStub( return TRUE; } +#ifdef FEATURE_PAL +VOID DECLSPEC_NORETURN DispatchManagedException(PAL_SEHException& ex, bool isHardwareException) +{ + UNREACHABLE(); +} +#endif #endif // !DACCESS_COMPILE diff --git a/src/vm/i386/gmsasm.S b/src/vm/i386/gmsasm.S new file mode 100644 index 0000000..1e43fd2 --- /dev/null +++ b/src/vm/i386/gmsasm.S @@ -0,0 +1,28 @@ +// 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. + +.intel_syntax noprefix +#include "unixasmmacros.inc" +#include "asmconstants.h" + +// int __fastcall LazyMachStateCaptureState(struct LazyMachState *pState); +LEAF_ENTRY LazyMachStateCaptureState, _TEXT + // marks that this is not yet valid + mov dword ptr [ecx+MachState__pRetAddr], 0 + + // remember register values + mov [ecx+MachState__edi], edi + mov [ecx+MachState__esi], esi + mov [ecx+MachState__ebx], ebx + mov [ecx+LazyMachState_captureEbp], ebp + mov [ecx+LazyMachState_captureEsp], esp + + // capture return address + mov eax, [esp] + mov dword ptr [ecx+LazyMachState_captureEip], eax + + // return 0 + xor eax, eax + ret +LEAF_END LazyMachStateCaptureState, _TEXT diff --git a/src/vm/i386/gmsx86.cpp b/src/vm/i386/gmsx86.cpp index e7e16b7..34d6585 100644 --- a/src/vm/i386/gmsx86.cpp +++ b/src/vm/i386/gmsx86.cpp @@ -9,6 +9,11 @@ #include "common.h" #include "gmscpu.h" +#ifdef FEATURE_PAL +#define USE_EXTERNAL_UNWINDER +#endif + +#ifndef USE_EXTERNAL_UNWINDER /***************************************************************/ /* setMachState figures out what the state of the CPU will be when the function that calls 'setMachState' returns. It stores @@ -42,18 +47,31 @@ #if !defined(DACCESS_COMPILE) +#ifdef _MSC_VER #pragma optimize("gsy", on ) // optimize to insure that code generation does not have junk in it +#endif // _MSC_VER #pragma warning(disable:4717) static int __stdcall zeroFtn() { return 0; } +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Winfinite-recursion" +#endif + static int __stdcall recursiveFtn() { return recursiveFtn()+1; } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#ifdef _MSC_VER #pragma optimize("", on ) +#endif // _MSC_VER /* Has mscorwks been instrumented so that calls are morphed into push XXXX call */ @@ -670,6 +688,10 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, ip += 2; break; + case 0x34: // XOR AL, imm8 + ip += 2; + break; + case 0x31: case 0x32: case 0x33: @@ -866,6 +888,10 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, datasize = b16bit?2:4; goto decodeRM; + case 0x24: // AND AL, imm8 + ip += 2; + break; + case 0x01: // ADD mod/rm case 0x03: case 0x29: // SUB mod/rm @@ -1108,7 +1134,7 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, goto again; } #ifndef _PREFIX_ - *((int*) 0) = 1; // If you get at this error, it is because yout + *((volatile int*) 0) = 1; // If you get at this error, it is because yout // set a breakpoint in a helpermethod frame epilog // you can't do that unfortunately. Just move it // into the interior of the method to fix it @@ -1225,7 +1251,7 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, // FIX what to do here? #ifndef DACCESS_COMPILE #ifndef _PREFIX_ - *((unsigned __int8**) 0) = ip; // cause an access violation (Free Build assert) + *((volatile PTR_BYTE*) 0) = ip; // cause an access violation (Free Build assert) #endif // !_PREFIX_ #else DacNotImpl(); @@ -1243,3 +1269,109 @@ done: #ifdef _PREFAST_ #pragma warning(pop) #endif +#else // !USE_EXTERNAL_UNWINDER + +void LazyMachState::unwindLazyState(LazyMachState* baseState, + MachState* lazyState, + DWORD threadId, + int funCallDepth /* = 1 */, + HostCallPreference hostCallPreference /* = (HostCallPreference)(-1) */) +{ + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + SO_TOLERANT; + SUPPORTS_DAC; + } CONTRACTL_END; + + CONTEXT ctx; + KNONVOLATILE_CONTEXT_POINTERS nonVolRegPtrs; + + ctx.Eip = baseState->captureEip; + ctx.Esp = baseState->captureEsp; + ctx.Ebp = baseState->captureEbp; + + ctx.Edi = lazyState->_edi = baseState->_edi; + ctx.Esi = lazyState->_esi = baseState->_esi; + ctx.Ebx = lazyState->_ebx = baseState->_ebx; + + nonVolRegPtrs.Edi = &(lazyState->_edi); + nonVolRegPtrs.Esi = &(lazyState->_esi); + nonVolRegPtrs.Ebx = &(lazyState->_ebx); + nonVolRegPtrs.Ebp = &(lazyState->_ebp); + + PCODE pvControlPc; + + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK LazyMachState::unwindLazyState(ip:%p,bp:%p,sp:%p)\n", baseState->captureEip, baseState->captureEbp, baseState->captureEsp)); + + do + { +#ifdef DACCESS_COMPILE + HRESULT hr = DacVirtualUnwind(threadId, &ctx, &nonVolRegPtrs); + if (FAILED(hr)) + { + DacError(hr); + } +#else + BOOL success = PAL_VirtualUnwind(&ctx, &nonVolRegPtrs); + if (!success) + { + _ASSERTE(!"unwindLazyState: Unwinding failed"); + EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); + } +#endif // DACCESS_COMPILE + + pvControlPc = GetIP(&ctx); + + if (funCallDepth > 0) + { + --funCallDepth; + if (funCallDepth == 0) + break; + } + else + { + // Determine whether given IP resides in JITted code. (It returns nonzero in that case.) + // Use it now to see if we've unwound to managed code yet. + BOOL fFailedReaderLock = FALSE; + BOOL fIsManagedCode = ExecutionManager::IsManagedCode(pvControlPc, hostCallPreference, &fFailedReaderLock); + if (fFailedReaderLock) + { + // We don't know if we would have been able to find a JIT + // manager, because we couldn't enter the reader lock without + // yielding (and our caller doesn't want us to yield). So abort + // now. + + // Invalidate the lazyState we're returning, so the caller knows + // we aborted before we could fully unwind + lazyState->_pRetAddr = NULL; + return; + } + + if (fIsManagedCode) + break; + } + } + while(TRUE); + + lazyState->_esp = ctx.Esp; + lazyState->_pRetAddr = PTR_TADDR(lazyState->_esp - 4); + + lazyState->_edi = ctx.Edi; + lazyState->_esi = ctx.Esi; + lazyState->_ebx = ctx.Ebx; + lazyState->_ebp = ctx.Ebp; + +#ifdef DACCESS_COMPILE + lazyState->_pEdi = NULL; + lazyState->_pEsi = NULL; + lazyState->_pEbx = NULL; + lazyState->_pEbp = NULL; +#else // DACCESS_COMPILE + lazyState->_pEdi = nonVolRegPtrs.Edi; + lazyState->_pEsi = nonVolRegPtrs.Esi; + lazyState->_pEbx = nonVolRegPtrs.Ebx; + lazyState->_pEbp = nonVolRegPtrs.Ebp; +#endif // DACCESS_COMPILE +} +#endif // !USE_EXTERNAL_UNWINDER diff --git a/src/vm/i386/jithelp.S b/src/vm/i386/jithelp.S new file mode 100644 index 0000000..66ae9fb --- /dev/null +++ b/src/vm/i386/jithelp.S @@ -0,0 +1,749 @@ +// 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. + +.intel_syntax noprefix +#include "unixasmmacros.inc" +#include "asmconstants.h" + + +// *** +// JIT_WriteBarrier* - GC write barrier helper +// +// Purpose: +// Helper calls in order to assign an object to a field +// Enables book-keeping of the GC. +// +// Entry: +// EDX - address of ref-field (assigned to) +// the resp. other reg - RHS of assignment +// +// Exit: +// +// Uses: +// EDX is destroyed. +// +// Exceptions: +// +// ******************************************************************************* + +// The code here is tightly coupled with AdjustContextForWriteBarrier, if you change +// anything here, you might need to change AdjustContextForWriteBarrier as well +.macro WriteBarrierHelper rg +.align 4 + +// The entry point is the fully 'safe' one in which we check if EDX (the REF +// begin updated) is actually in the GC heap +NESTED_ENTRY JIT_CheckedWriteBarrier\rg, _TEXT, NoHandler + // check in the REF being updated is in the GC heap + push eax + PREPARE_EXTERNAL_VAR g_lowest_address, eax + cmp edx, [eax] + pop eax + jb LOCAL_LABEL(WriteBarrier_NotInHeap_\rg) + push eax + PREPARE_EXTERNAL_VAR g_highest_address, eax + cmp edx, [eax] + pop eax + jae LOCAL_LABEL(WriteBarrier_NotInHeap_\rg) + + // fall through to unchecked routine + // note that its entry point also happens to be aligned + +#ifdef WRITE_BARRIER_CHECK + // This entry point is used when you know the REF pointer being updated + // is in the GC heap +PATCH_LABEL JIT_DebugWriteBarrier\rg +#endif // WRITE_BARRIER_CHECK + +#ifdef _DEBUG + push edx + push ecx + push eax + + push \rg + push edx + call C_FUNC(WriteBarrierAssert) + + pop eax + pop ecx + pop edx +#endif // _DEBUG + + // in the !WRITE_BARRIER_CHECK case this will be the move for all + // addresses in the GCHeap, addresses outside the GCHeap will get + // taken care of below at WriteBarrier_NotInHeap_&rg + +#ifndef WRITE_BARRIER_CHECK + mov DWORD PTR [edx], \rg +#endif // !WRITE_BARRIER_CHECK + +#ifdef WRITE_BARRIER_CHECK + // Test dest here so if it is bad AV would happen before we change register/stack + // status. This makes job of AdjustContextForWriteBarrier easier. + cmp BYTE PTR [edx], 0 + // ALSO update the shadow GC heap if that is enabled + // Make ebp into the temporary src register. We need to do this so that we can use ecx + // in the calculation of the shadow GC address, but still have access to the src register + push ecx + push ebp + mov ebp, \rg + + // if g_GCShadow is 0, don't perform the check + push eax + PREPARE_EXTERNAL_VAR g_GCShadow, eax + cmp DWORD PTR [eax], 0 + pop eax + je LOCAL_LABEL(WriteBarrier_NoShadow_\rg) + + mov ecx, edx + push eax + PREPARE_EXTERNAL_VAR g_lowest_address, eax + sub ecx, [eax] + pop eax + jb LOCAL_LABEL(WriteBarrier_NoShadow_\rg) + push edx + PREPARE_EXTERNAL_VAR g_GCShadow, edx + mov [edx], edx + add ecx, [edx] + PREPARE_EXTERNAL_VAR g_GCShadowEnd, edx + mov [edx], edx + cmp ecx, [edx] + pop edx + ja LOCAL_LABEL(WriteBarrier_NoShadow_\rg) + + // TODO: In Orcas timeframe if we move to P4+ only on X86 we should enable + // mfence barriers on either side of these two writes to make sure that + // they stay as close together as possible + + // edx contains address in GC + // ecx contains address in ShadowGC + // ebp temporarially becomes the src register + + // When we're writing to the shadow GC heap we want to be careful to minimize + // the risk of a race that can occur here where the GC and ShadowGC don't match + mov DWORD PTR [edx], ebp + mov DWORD PTR [ecx], ebp + + // We need a scratch register to verify the shadow heap. We also need to + // construct a memory barrier so that the write to the shadow heap happens + // before the read from the GC heap. We can do both by using SUB/XCHG + // rather than PUSH. + // + // TODO: Should be changed to a push if the mfence described above is added. + // + sub esp, 4 + xchg [esp], eax + + // As part of our race avoidance (see above) we will now check whether the values + // in the GC and ShadowGC match. There is a possibility that we're wrong here but + // being overaggressive means we might mask a case where someone updates GC refs + // without going to a write barrier, but by its nature it will be indeterminant + // and we will find real bugs whereas the current implementation is indeterminant + // but only leads to investigations that find that this code is fundamentally flawed + mov eax, [edx] + cmp [ecx], eax + je LOCAL_LABEL(WriteBarrier_CleanupShadowCheck_\rg) + mov DWORD PTR [ecx], INVALIDGCVALUE + +LOCAL_LABEL(WriteBarrier_CleanupShadowCheck_\rg): + pop eax + + jmp LOCAL_LABEL(WriteBarrier_ShadowCheckEnd_\rg) + +LOCAL_LABEL(WriteBarrier_NoShadow_\rg): + // If we come here then we haven't written the value to the GC and need to. + // ebp contains rg + // We restore ebp/ecx immediately after this, and if either of them is the src + // register it will regain its value as the src register. + mov DWORD PTR [edx], ebp +LOCAL_LABEL(WriteBarrier_ShadowCheckEnd_\rg): + pop ebp + pop ecx +#endif // WRITE_BARRIER_CHECK + + push eax + push ebx + mov eax, \rg + PREPARE_EXTERNAL_VAR g_ephemeral_low, ebx + cmp eax, [ebx] + pop ebx + pop eax + jb LOCAL_LABEL(WriteBarrier_NotInEphemeral_\rg) + push eax + push ebx + mov eax, \rg + PREPARE_EXTERNAL_VAR g_ephemeral_high, ebx + cmp eax, [ebx] + pop ebx + pop eax + jae LOCAL_LABEL(WriteBarrier_NotInEphemeral_\rg) + + shr edx, 10 + push eax + PREPARE_EXTERNAL_VAR g_card_table, eax + add edx, [eax] + pop eax + cmp BYTE PTR [edx], 0FFh + jne LOCAL_LABEL(WriteBarrier_UpdateCardTable_\rg) + ret + +LOCAL_LABEL(WriteBarrier_UpdateCardTable_\rg): + mov BYTE PTR [edx], 0FFh + ret + +LOCAL_LABEL(WriteBarrier_NotInHeap_\rg): + // If it wasn't in the heap then we haven't updated the dst in memory yet + mov DWORD PTR [edx], \rg + +LOCAL_LABEL(WriteBarrier_NotInEphemeral_\rg): + // If it is in the GC Heap but isn't in the ephemeral range we've already + // updated the Heap with the Object*. + ret +NESTED_END JIT_CheckedWriteBarrier\rg, _TEXT + +.endm + + +// *** +// JIT_ByRefWriteBarrier* - GC write barrier helper +// +// Purpose: +// Helper calls in order to assign an object to a byref field +// Enables book-keeping of the GC. +// +// Entry: +// EDI - address of ref-field (assigned to) +// ESI - address of the data (source) +// ECX can be trashed +// +// Exit: +// +// Uses: +// EDI and ESI are incremented by a DWORD +// +// Exceptions: +// +// ******************************************************************************* +// +// The code here is tightly coupled with AdjustContextForWriteBarrier, if you change +// anything here, you might need to change AdjustContextForWriteBarrier as well +// +.macro ByRefWriteBarrierHelper +.align 4 + +LEAF_ENTRY JIT_ByRefWriteBarrier, _TEXT + // test for dest in range + mov ecx, [esi] + push eax + PREPARE_EXTERNAL_VAR g_lowest_address, eax + cmp edi, [eax] + pop eax + jb LOCAL_LABEL(ByRefWriteBarrier_NotInHeap) + push eax + PREPARE_EXTERNAL_VAR g_highest_address, eax + cmp edi, [eax] + pop eax + jae LOCAL_LABEL(ByRefWriteBarrier_NotInHeap) + +#ifndef WRITE_BARRIER_CHECK + // write barrier + mov [edi], ecx +#endif // !WRITE_BARRIER_CHECK + +#ifdef WRITE_BARRIER_CHECK + // Test dest here so if it is bad AV would happen before we change register/stack + // status. This makes job of AdjustContextForWriteBarrier easier. + cmp BYTE PTR [edi], 0 + + // ALSO update the shadow GC heap if that is enabled + + // use edx for address in GC Shadow, + push edx + + // if g_GCShadow is 0, don't do the update + push ebx + PREPARE_EXTERNAL_VAR g_GCShadow, ebx + cmp DWORD PTR [ebx], 0 + pop ebx + je LOCAL_LABEL(ByRefWriteBarrier_NoShadow) + + mov edx, edi + push ebx + PREPARE_EXTERNAL_VAR g_lowest_address, ebx + sub edx, [ebx] // U/V + pop ebx + jb LOCAL_LABEL(ByRefWriteBarrier_NoShadow) + push eax + PREPARE_EXTERNAL_VAR g_GCShadow, eax + mov eax, [eax] + add edx, [eax] + PREPARE_EXTERNAL_VAR g_GCShadowEnd, eax + mov eax, [eax] + cmp edx, [eax] + pop eax + ja LOCAL_LABEL(ByRefWriteBarrier_NoShadow) + + // TODO: In Orcas timeframe if we move to P4+ only on X86 we should enable + // mfence barriers on either side of these two writes to make sure that + // they stay as close together as possible + + // edi contains address in GC + // edx contains address in ShadowGC + // ecx is the value to assign + + // When we're writing to the shadow GC heap we want to be careful to minimize + // the risk of a race that can occur here where the GC and ShadowGC don't match + mov DWORD PTR [edi], ecx + mov DWORD PTR [edx], ecx + + // We need a scratch register to verify the shadow heap. We also need to + // construct a memory barrier so that the write to the shadow heap happens + // before the read from the GC heap. We can do both by using SUB/XCHG + // rather than PUSH. + // + // TODO: Should be changed to a push if the mfence described above is added. + // + sub esp, 4 + xchg [esp], eax + + // As part of our race avoidance (see above) we will now check whether the values + // in the GC and ShadowGC match. There is a possibility that we're wrong here but + // being overaggressive means we might mask a case where someone updates GC refs + // without going to a write barrier, but by its nature it will be indeterminant + // and we will find real bugs whereas the current implementation is indeterminant + // but only leads to investigations that find that this code is fundamentally flawed + + mov eax, [edi] + cmp [edx], eax + je LOCAL_LABEL(ByRefWriteBarrier_CleanupShadowCheck) + mov DWORD PTR [edx], INVALIDGCVALUE +LOCAL_LABEL(ByRefWriteBarrier_CleanupShadowCheck): + pop eax + jmp LOCAL_LABEL(ByRefWriteBarrier_ShadowCheckEnd) + +LOCAL_LABEL(ByRefWriteBarrier_NoShadow): + // If we come here then we haven't written the value to the GC and need to. + mov DWORD PTR [edi], ecx + +LOCAL_LABEL(ByRefWriteBarrier_ShadowCheckEnd): + pop edx +#endif // WRITE_BARRIER_CHECK + + // test for *src in ephemeral segement + push eax + PREPARE_EXTERNAL_VAR g_ephemeral_low, eax + cmp ecx, [eax] + pop eax + jb LOCAL_LABEL(ByRefWriteBarrier_NotInEphemeral) + push eax + PREPARE_EXTERNAL_VAR g_ephemeral_high, eax + cmp ecx, [eax] + pop eax + jae LOCAL_LABEL(ByRefWriteBarrier_NotInEphemeral) + + mov ecx, edi + add esi, 4 + add edi, 4 + + shr ecx, 10 + push eax + PREPARE_EXTERNAL_VAR g_card_table, eax + add ecx, [eax] + pop eax + cmp BYTE PTR [ecx], 0FFh + jne LOCAL_LABEL(ByRefWriteBarrier_UpdateCardTable) + ret +LOCAL_LABEL(ByRefWriteBarrier_UpdateCardTable): + mov BYTE PTR [ecx], 0FFh + ret + +LOCAL_LABEL(ByRefWriteBarrier_NotInHeap): + // If it wasn't in the heap then we haven't updated the dst in memory yet + mov [edi], ecx +LOCAL_LABEL(ByRefWriteBarrier_NotInEphemeral): + // If it is in the GC Heap but isn't in the ephemeral range we've already + // updated the Heap with the Object*. + add esi, 4 + add edi, 4 + ret +NESTED_END JIT_ByRefWriteBarrier, _TEXT + +.endm + +// WriteBarrierStart and WriteBarrierEnd are used to determine bounds of +// WriteBarrier functions so can determine if got AV in them. +// +LEAF_ENTRY JIT_WriteBarrierStart, _TEXT + ret +LEAF_END JIT_WriteBarrierStart, _TEXT + +#ifdef FEATURE_USE_ASM_GC_WRITE_BARRIERS +// ******************************************************************************* +// Write barrier wrappers with fcall calling convention +// +.macro UniversalWriteBarrierHelper name +.align 4 + +LEAF_ENTRY JIT_\name, _TEXT + mov eax, edx + mov edx, ecx + jmp C_FUNC(JIT_\name\()EAX) +LEAF_END JIT_\name, _TEXT + +.endm + +// Only define these if we're using the ASM GC write barriers; if this flag is not defined, +// we'll use C++ versions of these write barriers. +UniversalWriteBarrierHelper CheckedWriteBarrier +UniversalWriteBarrierHelper WriteBarrier +#endif // FEATURE_USE_ASM_GC_WRITE_BARRIERS + +WriteBarrierHelper EAX +WriteBarrierHelper EBX +WriteBarrierHelper ECX +WriteBarrierHelper ESI +WriteBarrierHelper EDI +WriteBarrierHelper EBP + +ByRefWriteBarrierHelper + +LEAF_ENTRY JIT_WriteBarrierLast, _TEXT + ret +LEAF_END JIT_WriteBarrierLast, _TEXT + +// This is the first function outside the "keep together range". Used by BBT scripts. +LEAF_ENTRY JIT_WriteBarrierEnd, _TEXT + ret +LEAF_END JIT_WriteBarrierEnd, _TEXT + +// *********************************************************************/ +// In cases where we support it we have an optimized GC Poll callback. +// Normall (when we're not trying to suspend for GC, the CORINFO_HELP_POLL_GC +// helper points to this nop routine. When we're ready to suspend for GC, +// we whack the Jit Helper table entry to point to the real helper. When we're +// done with GC we whack it back. +LEAF_ENTRY JIT_PollGC_Nop, _TEXT + ret +LEAF_END JIT_PollGC_Nop, _TEXT + +// *********************************************************************/ +// llshl - long shift left +// +// Purpose: +// Does a Long Shift Left (signed and unsigned are identical) +// Shifts a long left any number of bits. +// +// NOTE: This routine has been adapted from the Microsoft CRTs. +// +// Entry: +// EDX:EAX - long value to be shifted +// ECX - number of bits to shift by +// +// Exit: +// EDX:EAX - shifted value +// +.align 16 +LEAF_ENTRY JIT_LLsh, _TEXT + cmp ecx, 32 + jae LOCAL_LABEL(LLshMORE32) + + // Handle shifts of between bits 0 and 31 + shld edx, eax, cl + shl eax, cl + ret + +LOCAL_LABEL(LLshMORE32): + // Handle shifts of between bits 32 and 63 + // The x86 shift instructions only use the lower 5 bits. + mov edx, eax + xor eax, eax + shl edx, cl + ret +LEAF_END JIT_LLsh, _TEXT + +// *********************************************************************/ +// LRsh - long shift right +// +// Purpose: +// Does a signed Long Shift Right +// Shifts a long right any number of bits. +// +// NOTE: This routine has been adapted from the Microsoft CRTs. +// +// Entry: +// EDX:EAX - long value to be shifted +// ECX - number of bits to shift by +// +// Exit: +// EDX:EAX - shifted value +// +.align 16 +LEAF_ENTRY JIT_LRsh, _TEXT + cmp ecx, 32 + jae LOCAL_LABEL(LRshMORE32) + + // Handle shifts of between bits 0 and 31 + shrd eax, edx, cl + sar edx, cl + ret + +LOCAL_LABEL(LRshMORE32): + // Handle shifts of between bits 32 and 63 + // The x86 shift instructions only use the lower 5 bits. + mov eax, edx + sar edx, 31 + sar eax, cl + ret +LEAF_END JIT_LRsh, _TEXT + +// *********************************************************************/ +// LRsz: +// Purpose: +// Does a unsigned Long Shift Right +// Shifts a long right any number of bits. +// +// NOTE: This routine has been adapted from the Microsoft CRTs. +// +// Entry: +// EDX:EAX - long value to be shifted +// ECX - number of bits to shift by +// +// Exit: +// EDX:EAX - shifted value +// +.align 16 +LEAF_ENTRY JIT_LRsz, _TEXT + cmp ecx, 32 + jae LOCAL_LABEL(LRszMORE32) + + // Handle shifts of between bits 0 and 31 + shrd eax, edx, cl + shr edx, cl + ret + +LOCAL_LABEL(LRszMORE32): + // Handle shifts of between bits 32 and 63 + // The x86 shift instructions only use the lower 5 bits. + mov eax, edx + xor edx, edx + shr eax, cl + ret +LEAF_END JIT_LRsz, _TEXT + +// *********************************************************************/ +// JIT_Dbl2LngP4x87 +// +// Purpose: +// converts a double to a long truncating toward zero (C semantics) +// +// uses stdcall calling conventions +// +// This code is faster on a P4 than the Dbl2Lng code above, but is +// slower on a PIII. Hence we choose this code when on a P4 or above. +// +LEAF_ENTRY JIT_Dbl2LngP4x87, _TEXT + // get some local space + sub esp, 8 + + #define arg1 [esp + 0Ch] + fld QWORD PTR arg1 // fetch arg + fnstcw WORD PTR arg1 // store FPCW + movzx eax, WORD PTR arg1 // zero extend - wide + or ah, 0Ch // turn on OE and DE flags + mov DWORD PTR [esp], eax // store new FPCW bits + fldcw WORD PTR [esp] // reload FPCW with new bits + fistp QWORD PTR [esp] // convert + + // reload FP result + mov eax, DWORD PTR [esp] + mov edx, DWORD PTR [esp + 4] + + // reload original FPCW value + fldcw WORD PTR arg1 + #undef arg1 + + // restore stack + add esp, 8 + + ret 8 +LEAF_END JIT_Dbl2LngP4x87, _TEXT + +// *********************************************************************/ +// JIT_Dbl2LngSSE3 +// +// Purpose: +// converts a double to a long truncating toward zero (C semantics) +// +// uses stdcall calling conventions +// +// This code is faster than the above P4 x87 code for Intel processors +// equal or later than Core2 and Atom that have SSE3 support +// +LEAF_ENTRY JIT_Dbl2LngSSE3, _TEXT + // get some local space + sub esp, 8 + + fld QWORD PTR [esp + 0Ch] // fetch arg + fisttp QWORD PTR [esp] // convert + mov eax, DWORD PTR [esp] // reload FP result + mov edx, DWORD PTR [esp + 4] + + // restore stack + add esp, 8 + + ret 8 +LEAF_END JIT_Dbl2LngSSE3, _TEXT + +// *********************************************************************/ +// JIT_Dbl2IntSSE2 +// +// Purpose: +// converts a double to a long truncating toward zero (C semantics) +// +// uses stdcall calling conventions +// +// This code is even faster than the P4 x87 code for Dbl2LongP4x87, +// but only returns a 32 bit value (only good for int). +// +LEAF_ENTRY JIT_Dbl2IntSSE2, _TEXT + movsd xmm0, [esp + 4] + cvttsd2si eax, xmm0 + ret 8 +LEAF_END JIT_Dbl2IntSSE2, _TEXT + +// *********************************************************************/ +// This is the small write barrier thunk we use when we know the +// ephemeral generation is higher in memory than older generations. +// The 0x0F0F0F0F values are bashed by the two functions above. +// This the generic version - wherever the code says ECX, +// the specific register is patched later into a copy +// Note: do not replace ECX by EAX - there is a smaller encoding for +// the compares just for EAX, which won't work for other registers. +// +// READ THIS!!!!!! +// it is imperative that the addresses of of the values that we overwrite +// (card table, ephemeral region ranges, etc) are naturally aligned since +// there are codepaths that will overwrite these values while the EE is running. +// +LEAF_ENTRY JIT_WriteBarrierReg_PreGrow, _TEXT + mov DWORD PTR [edx], ecx + cmp ecx, 0F0F0F0F0h + jb LOCAL_LABEL(NoWriteBarrierPre) + + shr edx, 10 + nop // padding for alignment of constant + cmp BYTE PTR [edx + 0F0F0F0F0h], 0FFh + jne LOCAL_LABEL(WriteBarrierPre) + +LOCAL_LABEL(NoWriteBarrierPre): + ret + nop // padding for alignment of constant + nop // padding for alignment of constant + +LOCAL_LABEL(WriteBarrierPre): + mov BYTE PTR [edx+0F0F0F0F0h], 0FFh + ret +LEAF_END JIT_WriteBarrierReg_PreGrow, _TEXT + +// *********************************************************************/ +// This is the larger write barrier thunk we use when we know that older +// generations may be higher in memory than the ephemeral generation +// The 0x0F0F0F0F values are bashed by the two functions above. +// This the generic version - wherever the code says ECX, +// the specific register is patched later into a copy +// Note: do not replace ECX by EAX - there is a smaller encoding for +// the compares just for EAX, which won't work for other registers. +// NOTE: we need this aligned for our validation to work properly +.align 4 +LEAF_ENTRY JIT_WriteBarrierReg_PostGrow, _TEXT + mov DWORD PTR [edx], ecx + cmp ecx, 0F0F0F0F0h + jb LOCAL_LABEL(NoWriteBarrierPost) + cmp ecx, 0F0F0F0F0h + jae LOCAL_LABEL(NoWriteBarrierPost) + + shr edx, 10 + nop // padding for alignment of constant + cmp BYTE PTR [edx + 0F0F0F0F0h], 0FFh + jne LOCAL_LABEL(WriteBarrierPost) + +LOCAL_LABEL(NoWriteBarrierPost): + ret + nop // padding for alignment of constant + nop // padding for alignment of constant + +LOCAL_LABEL(WriteBarrierPost): + mov BYTE PTR [edx + 0F0F0F0F0h], 0FFh + ret +LEAF_END JIT_WriteBarrierReg_PostGrow,_TEXT + +// PatchedCodeStart and PatchedCodeEnd are used to determine bounds of patched code. +// + +LEAF_ENTRY JIT_PatchedCodeStart, _TEXT + ret +LEAF_END JIT_PatchedCodeStart, _TEXT + +// ********************************************************************** +// Write barriers generated at runtime + +LEAF_ENTRY JIT_PatchedWriteBarrierStart, _TEXT + ret +LEAF_END JIT_PatchedWriteBarrierStart, _TEXT + +.macro PatchedWriteBarrierHelper rg +.align 8 +LEAF_ENTRY JIT_WriteBarrier\rg, _TEXT + // Just allocate space that will be filled in at runtime + .space 0CCH, 48 +LEAF_END JIT_WriteBarrier\rg, _TEXT + +.endm + +PatchedWriteBarrierHelper EAX +PatchedWriteBarrierHelper EBX +PatchedWriteBarrierHelper ECX +PatchedWriteBarrierHelper ESI +PatchedWriteBarrierHelper EDI +PatchedWriteBarrierHelper EBP + +LEAF_ENTRY JIT_PatchedWriteBarrierLast, _TEXT + ret +LEAF_END JIT_PatchedWriteBarrierLast, _TEXT + +LEAF_ENTRY JIT_PatchedCodeLast, _TEXT + ret +LEAF_END JIT_PatchedCodeLast, _TEXT + +// This is the first function outside the "keep together range". Used by BBT scripts. +LEAF_ENTRY JIT_PatchedCodeEnd, _TEXT + ret +LEAF_END JIT_PatchedCodeEnd, _TEXT + +// Note that the debugger skips this entirely when doing SetIP, +// since COMPlusCheckForAbort should always return 0. Excep.cpp:LeaveCatch +// asserts that to be true. If this ends up doing more work, then the +// debugger may need additional support. +// void __stdcall JIT_EndCatch(); +NESTED_ENTRY JIT_EndCatch, _TEXT, NoHandler + // make temp storage for return address, and push the address of that + // as the last arg to COMPlusEndCatch + mov ecx, [esp] + push ecx + push esp + + // push the rest of COMPlusEndCatch's args, right-to-left + push esi + push edi + push ebx + push ebp + + // returns old esp value in eax, stores jump address + call C_FUNC(COMPlusEndCatch) + // now eax = new esp, [esp] = new eip + + pop edx // edx = new eip + mov esp, eax // esp = new esp + jmp edx // eip = new eip +NESTED_END JIT_EndCatch, _TEXT diff --git a/src/vm/i386/jithelp.asm b/src/vm/i386/jithelp.asm index ac76728..9d2f6b7 100644 --- a/src/vm/i386/jithelp.asm +++ b/src/vm/i386/jithelp.asm @@ -92,6 +92,8 @@ EXTERN _TransparentProxyStub_CrossContext@0:PROC EXTERN _InContextTPQuickDispatchAsmStub@0:PROC endif +EXTERN _COMPlusEndCatch@20:PROC + .686P .XMM ; The following macro is needed because of a MASM issue with the @@ -2571,4 +2573,32 @@ ChkCastInterfaceIsNullInst: @JIT_ChkCastInterface@8 endp +; Note that the debugger skips this entirely when doing SetIP, +; since COMPlusCheckForAbort should always return 0. Excep.cpp:LeaveCatch +; asserts that to be true. If this ends up doing more work, then the +; debugger may need additional support. +; void __stdcall JIT_EndCatch(); +JIT_EndCatch PROC stdcall public + + ; make temp storage for return address, and push the address of that + ; as the last arg to COMPlusEndCatch + mov ecx, [esp] + push ecx; + push esp; + + ; push the rest of COMPlusEndCatch's args, right-to-left + push esi + push edi + push ebx + push ebp + + call _COMPlusEndCatch@20 ; returns old esp value in eax, stores jump address + ; now eax = new esp, [esp] = new eip + + pop edx ; edx = new eip + mov esp, eax ; esp = new esp + jmp edx ; eip = new eip + +JIT_EndCatch ENDP + end diff --git a/src/vm/i386/jitinterfacex86.cpp b/src/vm/i386/jitinterfacex86.cpp index 949b115..a80b5e6 100644 --- a/src/vm/i386/jitinterfacex86.cpp +++ b/src/vm/i386/jitinterfacex86.cpp @@ -57,10 +57,10 @@ extern "C" void STDCALL WriteBarrierAssert(BYTE* ptr, Object* obj) if (fVerifyHeap) { obj->Validate(FALSE); - if(GCHeap::GetGCHeap()->IsHeapPointer(ptr)) + if(GCHeapUtilities::GetGCHeap()->IsHeapPointer(ptr)) { Object* pObj = *(Object**)ptr; - _ASSERTE (pObj == NULL || GCHeap::GetGCHeap()->IsHeapPointer(pObj)); + _ASSERTE (pObj == NULL || GCHeapUtilities::GetGCHeap()->IsHeapPointer(pObj)); } } else @@ -72,6 +72,7 @@ extern "C" void STDCALL WriteBarrierAssert(BYTE* ptr, Object* obj) #endif // _DEBUG +#ifndef FEATURE_PAL /****************************************************************************/ /* assigns 'val to 'array[idx], after doing all the proper checks */ @@ -330,7 +331,9 @@ extern "C" __declspec(naked) Object* F_CALL_CONV JIT_ChkCastClassSpecial(MethodT jmp JITutil_ChkCastAny } } +#endif // FEATURE_PAL +#ifndef FEATURE_PAL HCIMPL1_V(INT32, JIT_Dbl2IntOvf, double val) { FCALL_CONTRACT; @@ -346,6 +349,7 @@ THROW: FCThrow(kOverflowException); } HCIMPLEND +#endif // FEATURE_PAL FCDECL1(Object*, JIT_New, CORINFO_CLASS_HANDLE typeHnd_); @@ -610,7 +614,7 @@ void JIT_TrialAlloc::EmitCore(CPUSTUBLINKER *psl, CodeLabel *noLock, CodeLabel * if (flags & (ALIGN8 | SIZE_IN_EAX | ALIGN8OBJ)) { // MOV EBX, [edx]Thread.m_alloc_context.alloc_ptr - psl->X86EmitOffsetModRM(0x8B, kEBX, kEDX, offsetof(Thread, m_alloc_context) + offsetof(alloc_context, alloc_ptr)); + psl->X86EmitOffsetModRM(0x8B, kEBX, kEDX, offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_ptr)); // add EAX, EBX psl->Emit16(0xC303); if (flags & ALIGN8) @@ -619,11 +623,11 @@ void JIT_TrialAlloc::EmitCore(CPUSTUBLINKER *psl, CodeLabel *noLock, CodeLabel * else { // add eax, [edx]Thread.m_alloc_context.alloc_ptr - psl->X86EmitOffsetModRM(0x03, kEAX, kEDX, offsetof(Thread, m_alloc_context) + offsetof(alloc_context, alloc_ptr)); + psl->X86EmitOffsetModRM(0x03, kEAX, kEDX, offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_ptr)); } // cmp eax, [edx]Thread.m_alloc_context.alloc_limit - psl->X86EmitOffsetModRM(0x3b, kEAX, kEDX, offsetof(Thread, m_alloc_context) + offsetof(alloc_context, alloc_limit)); + psl->X86EmitOffsetModRM(0x3b, kEAX, kEDX, offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_limit)); // ja noAlloc psl->X86EmitCondJump(noAlloc, X86CondCode::kJA); @@ -631,7 +635,7 @@ void JIT_TrialAlloc::EmitCore(CPUSTUBLINKER *psl, CodeLabel *noLock, CodeLabel * // Fill in the allocation and get out. // mov [edx]Thread.m_alloc_context.alloc_ptr, eax - psl->X86EmitIndexRegStore(kEDX, offsetof(Thread, m_alloc_context) + offsetof(alloc_context, alloc_ptr), kEAX); + psl->X86EmitIndexRegStore(kEDX, offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_ptr), kEAX); if (flags & (ALIGN8 | SIZE_IN_EAX | ALIGN8OBJ)) { @@ -1502,7 +1506,7 @@ void InitJITHelpers1() _ASSERTE(g_SystemInfo.dwNumberOfProcessors != 0); - JIT_TrialAlloc::Flags flags = GCHeap::UseAllocationContexts() ? + JIT_TrialAlloc::Flags flags = GCHeapUtilities::UseAllocationContexts() ? JIT_TrialAlloc::MP_ALLOCATOR : JIT_TrialAlloc::NORMAL; // Get CPU features and check for SSE2 support. diff --git a/src/vm/i386/stublinkerx86.cpp b/src/vm/i386/stublinkerx86.cpp index 0037a7d..63b9e87 100644 --- a/src/vm/i386/stublinkerx86.cpp +++ b/src/vm/i386/stublinkerx86.cpp @@ -64,6 +64,7 @@ extern "C" HRESULT __cdecl StubRareDisableHR(Thread *pThread); #endif // FEATURE_COMINTEROP extern "C" VOID __cdecl StubRareDisableTHROW(Thread *pThread, Frame *pFrame); +#ifndef FEATURE_ARRAYSTUB_AS_IL extern "C" VOID __cdecl ArrayOpStubNullException(void); extern "C" VOID __cdecl ArrayOpStubRangeException(void); extern "C" VOID __cdecl ArrayOpStubTypeMismatchException(void); @@ -78,10 +79,13 @@ EXCEPTION_HELPERS(ArrayOpStubNullException); EXCEPTION_HELPERS(ArrayOpStubRangeException); EXCEPTION_HELPERS(ArrayOpStubTypeMismatchException); #undef EXCEPTION_HELPERS +#endif // !_TARGET_AMD64_ +#endif // !FEATURE_ARRAYSTUB_AS_IL -#if defined(_DEBUG) +#if defined(_TARGET_AMD64_) +#if defined(_DEBUG) extern "C" VOID __cdecl DebugCheckStubUnwindInfo(); -#endif +#endif // _DEBUG #endif // _TARGET_AMD64_ // Presumably this code knows what it is doing with TLS. If we are hiding these @@ -2535,7 +2539,7 @@ VOID StubLinkerCPU::X86EmitCurrentAppDomainFetch(X86Reg dstreg, unsigned preserv #endif // FEATURE_IMPLICIT_TLS } -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) #ifdef PROFILING_SUPPORTED VOID StubLinkerCPU::EmitProfilerComCallProlog(TADDR pFrameVptr, X86Reg regFrame) @@ -2624,6 +2628,7 @@ VOID StubLinkerCPU::EmitProfilerComCallEpilog(TADDR pFrameVptr, X86Reg regFrame) #endif // PROFILING_SUPPORTED +#ifndef FEATURE_STUBS_AS_IL //======================================================================== // Prolog for entering managed code from COM // pushes the appropriate frame ptr @@ -2850,6 +2855,7 @@ 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. @@ -2882,6 +2888,7 @@ VOID StubLinkerCPU::EmitSetup(CodeLabel *pForwardRef) switch (mode) { case TLSACCESS_WNT: +#ifndef FEATURE_PAL { unsigned __int32 tlsofs = offsetof(TEB, TlsSlots) + (idx * sizeof(void*)); @@ -2889,6 +2896,9 @@ VOID StubLinkerCPU::EmitSetup(CodeLabel *pForwardRef) EmitBytes(code, sizeof(code)); Emit32(tlsofs); } +#else // !FEATURE_PAL + _ASSERTE("TLSACCESS_WNT mode is not supported"); +#endif // !FEATURE_PAL break; case TLSACCESS_GENERIC: @@ -2919,7 +2929,6 @@ VOID StubLinkerCPU::EmitSetup(CodeLabel *pForwardRef) X86EmitDebugTrashReg(kECX); X86EmitDebugTrashReg(kEDX); #endif - } VOID StubLinkerCPU::EmitRareSetup(CodeLabel *pRejoinPoint, BOOL fThrow) @@ -4824,8 +4833,9 @@ VOID StubLinkerCPU::EmitSecureDelegateInvoke(UINT_PTR hash) // Epilog EmitMethodStubEpilog(numStackBytes, SecureDelegateFrame::GetOffsetOfTransitionBlock()); } +#endif // !CROSSGEN_COMPILE && !FEATURE_STUBS_AS_IL -#ifndef FEATURE_ARRAYSTUB_AS_IL +#if !defined(CROSSGEN_COMPILE) && !defined(FEATURE_ARRAYSTUB_AS_IL) // Little helper to generate code to move nbytes bytes of non Ref memory @@ -5768,8 +5778,9 @@ COPY_VALUE_CLASS: #pragma warning(pop) #endif -#endif // FEATURE_ARRAYSTUB_AS_IL +#endif // !CROSSGEN_COMPILE && !FEATURE_ARRAYSTUB_AS_IL +#if !defined(CROSSGEN_COMPILE) && !defined(FEATURE_STUBS_AS_IL) //=========================================================================== // Emits code to break into debugger VOID StubLinkerCPU::EmitDebugBreak() @@ -5841,9 +5852,9 @@ Thread* __stdcall CreateThreadBlockReturnHr(ComMethodFrame *pFrame) #pragma warning(pop) #endif -#endif // defined(FEATURE_COMINTEROP) && defined(_TARGET_X86_) +#endif // FEATURE_COMINTEROP && _TARGET_X86_ -#endif // !defined(CROSSGEN_COMPILE) && !defined(FEATURE_STUBS_AS_IL) +#endif // !CROSSGEN_COMPILE && !FEATURE_STUBS_AS_IL #endif // !DACCESS_COMPILE diff --git a/src/vm/i386/stublinkerx86.h b/src/vm/i386/stublinkerx86.h index 237fc79..e361833 100644 --- a/src/vm/i386/stublinkerx86.h +++ b/src/vm/i386/stublinkerx86.h @@ -345,6 +345,11 @@ class StubLinkerCPU : public StubLinker VOID EmitSetup(CodeLabel *pForwardRef); VOID EmitRareSetup(CodeLabel* pRejoinPoint, BOOL fThrow); + +#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_ @@ -353,10 +358,8 @@ class StubLinkerCPU : public StubLinker void EmitComMethodStubEpilog(TADDR pFrameVptr, CodeLabel** rgRareLabels, CodeLabel** rgRejoinLabels, BOOL bShouldProfile); -#endif - - VOID EmitMethodStubProlog(TADDR pFrameVptr, int transitionBlockOffset); - VOID EmitMethodStubEpilog(WORD numArgBytes, int transitionBlockOffset); +#endif // _TARGET_X86_ +#endif // !FEATURE_STUBS_AS_IL VOID EmitUnboxMethodStub(MethodDesc* pRealMD); #if defined(FEATURE_SHARE_GENERIC_CODE) @@ -374,13 +377,16 @@ class StubLinkerCPU : public StubLinker BOOL bShouldProfile); #endif // FEATURE_COMINTEROP && _TARGET_X86_ +#ifndef FEATURE_STUBS_AS_IL //=========================================================================== // Computes hash code for MulticastDelegate.Invoke() static UINT_PTR HashMulticastInvoke(MetaSig* pSig); +#ifdef _TARGET_X86_ //=========================================================================== // Emits code for Delegate.Invoke() any delegate type VOID EmitDelegateInvoke(); +#endif // _TARGET_X86_ //=========================================================================== // Emits code for MulticastDelegate.Invoke() - sig specific @@ -389,22 +395,27 @@ class StubLinkerCPU : public StubLinker //=========================================================================== // Emits code for Delegate.Invoke() on delegates that recorded creator assembly VOID EmitSecureDelegateInvoke(UINT_PTR hash); +#endif // !FEATURE_STUBS_AS_IL //=========================================================================== // Emits code to adjust for a static delegate target. VOID EmitShuffleThunk(struct ShuffleEntry *pShuffleEntryArray); +#ifndef FEATURE_ARRAYSTUB_AS_IL //=========================================================================== // Emits code to do an array operation. VOID EmitArrayOpStub(const ArrayOpScript*); //Worker function to emit throw helpers for array ops. VOID EmitArrayOpStubThrow(unsigned exConst, unsigned cbRetArg); +#endif +#ifndef FEATURE_STUBS_AS_IL //=========================================================================== // Emits code to break into debugger VOID EmitDebugBreak(); +#endif // !FEATURE_STUBS_AS_IL #if defined(_DEBUG) && (defined(_TARGET_AMD64_) || defined(_TARGET_X86_)) && !defined(FEATURE_PAL) //=========================================================================== diff --git a/src/vm/i386/umthunkstub.S b/src/vm/i386/umthunkstub.S new file mode 100644 index 0000000..728964b --- /dev/null +++ b/src/vm/i386/umthunkstub.S @@ -0,0 +1,177 @@ +// 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. + +.intel_syntax noprefix +#include "unixasmmacros.inc" +#include "asmconstants.h" + +// +// eax = UMEntryThunk* +// +NESTED_ENTRY TheUMEntryPrestub, _TEXT, UnhandledExceptionHandlerUnix + // Preserve argument registers + push ecx + push edx + + push eax // UMEntryThunk* + call C_FUNC(TheUMEntryPrestubWorker) + pop edx + // eax = PCODE + + // Restore argument registers + pop edx + pop ecx + + jmp eax // Tail Jmp +NESTED_END TheUMEntryPrestub, _TEXT + +// +// eax: UMEntryThunk* +// +NESTED_ENTRY UMThunkStub, _TEXT, UnhandledExceptionHandlerUnix + +#define UMThunkStub_SAVEDREG (3*4) // ebx, esi, edi +#define UMThunkStub_LOCALVARS (2*4) // UMEntryThunk*, Thread* +#define UMThunkStub_INT_ARG_SPILL (2*4) // for save ecx, edx +#define UMThunkStub_UMENTRYTHUNK_OFFSET (UMThunkStub_SAVEDREG+4) +#define UMThunkStub_THREAD_OFFSET (UMThunkStub_UMENTRYTHUNK_OFFSET+4) +#define UMThunkStub_INT_ARG_OFFSET (UMThunkStub_THREAD_OFFSET+4) +#define UMThunkStub_FIXEDALLOCSIZE (UMThunkStub_LOCALVARS+UMThunkStub_INT_ARG_SPILL) + +// return address <-- entry ESP +// saved ebp <-- EBP +// saved ebx +// saved esi +// saved edi +// UMEntryThunk* +// Thread* +// save ecx +// save edx +// {optional stack args passed to callee} <-- new esp + + PROLOG_BEG + PROLOG_PUSH ebx + PROLOG_PUSH esi + PROLOG_PUSH edi + PROLOG_END + sub esp, UMThunkStub_FIXEDALLOCSIZE + + mov dword ptr [ebp - UMThunkStub_INT_ARG_OFFSET], ecx + mov dword ptr [ebp - UMThunkStub_INT_ARG_OFFSET - 0x04], edx + + mov dword ptr [ebp - UMThunkStub_UMENTRYTHUNK_OFFSET], eax + + call C_FUNC(GetThread) + test eax, eax + jz LOCAL_LABEL(DoThreadSetup) + +LOCAL_LABEL(HaveThread): + + mov dword ptr [ebp - UMThunkStub_THREAD_OFFSET], eax + + // FailFast if a native callable method is invoked via ldftn and calli. + cmp dword ptr [eax + Thread_m_fPreemptiveGCDisabled], 1 + jz LOCAL_LABEL(InvalidTransition) + + // disable preemptive GC + mov dword ptr [eax + Thread_m_fPreemptiveGCDisabled], 1 + + // catch returning thread here if a GC is in progress + PREPARE_EXTERNAL_VAR g_TrapReturningThreads, eax + cmp eax, 0 + jnz LOCAL_LABEL(DoTrapReturningThreadsTHROW) + +LOCAL_LABEL(InCooperativeMode): + +#if _DEBUG + mov eax, dword ptr [ebp - UMThunkStub_THREAD_OFFSET] + mov eax, dword ptr [eax + Thread__m_pDomain] + mov esi, dword ptr [eax + AppDomain__m_dwId] + + mov eax, dword ptr [ebp - UMThunkStub_UMENTRYTHUNK_OFFSET] + mov edi, dword ptr [eax + UMEntryThunk__m_dwDomainId] + + cmp esi, edi + jne LOCAL_LABEL(WrongAppDomain) +#endif + + mov eax, dword ptr [ebp - UMThunkStub_UMENTRYTHUNK_OFFSET] + mov ebx, dword ptr [eax + UMEntryThunk__m_pUMThunkMarshInfo] + mov eax, dword ptr [ebx + UMThunkMarshInfo__m_cbActualArgSize] + test eax, eax + jnz LOCAL_LABEL(UMThunkStub_CopyStackArgs) + +LOCAL_LABEL(UMThunkStub_ArgumentsSetup): + + mov ecx, dword ptr [ebp - UMThunkStub_INT_ARG_OFFSET] + mov edx, dword ptr [ebp - UMThunkStub_INT_ARG_OFFSET - 0x04] + + mov eax, dword ptr [ebp - UMThunkStub_UMENTRYTHUNK_OFFSET] + mov ebx, dword ptr [eax + UMEntryThunk__m_pUMThunkMarshInfo] + mov ebx, dword ptr [ebx + UMThunkMarshInfo__m_pILStub] + + call ebx + +LOCAL_LABEL(PostCall): + + mov ebx, dword ptr [ebp - UMThunkStub_THREAD_OFFSET] + mov dword ptr [ebx + Thread_m_fPreemptiveGCDisabled], 0 + + lea esp, [ebp - UMThunkStub_SAVEDREG] // deallocate arguments + EPILOG_BEG + EPILOG_POP edi + EPILOG_POP esi + EPILOG_POP ebx + EPILOG_END + ret + +LOCAL_LABEL(DoThreadSetup): + + call C_FUNC(CreateThreadBlockThrow) + jmp LOCAL_LABEL(HaveThread) + +LOCAL_LABEL(InvalidTransition): + + //No arguments to setup , ReversePInvokeBadTransition will failfast + call C_FUNC(ReversePInvokeBadTransition) + +LOCAL_LABEL(DoTrapReturningThreadsTHROW): + + // extern "C" VOID STDCALL UMThunkStubRareDisableWorker(Thread *pThread, UMEntryThunk *pUMEntryThunk) + mov eax, dword ptr [ebp - UMThunkStub_UMENTRYTHUNK_OFFSET] + push eax + mov eax, dword ptr [ebp - UMThunkStub_THREAD_OFFSET] + push eax + call C_FUNC(UMThunkStubRareDisableWorker) + + jmp LOCAL_LABEL(InCooperativeMode) + +LOCAL_LABEL(UMThunkStub_CopyStackArgs): + + // eax = m_cbActualArgSize + sub esp, eax + and esp, -16 // align with 16 byte + lea esi, [ebp + 0x08] + lea edi, [esp] + +LOCAL_LABEL(CopyLoop): + + // eax = number of bytes + // esi = src + // edi = dest + // edx = sratch + + add eax, -4 + mov edx, dword ptr [esi + eax] + mov dword ptr [edi + eax], edx + jnz LOCAL_LABEL(CopyLoop) + + jmp LOCAL_LABEL(UMThunkStub_ArgumentsSetup) + +#if _DEBUG +LOCAL_LABEL(WrongAppDomain): + int3 +#endif + +NESTED_END UMThunkStub, _TEXT diff --git a/src/vm/i386/unixstubs.cpp b/src/vm/i386/unixstubs.cpp new file mode 100644 index 0000000..9fe7127 --- /dev/null +++ b/src/vm/i386/unixstubs.cpp @@ -0,0 +1,106 @@ +// 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. + +#include "common.h" + +extern "C" +{ + void ThrowControlForThread() + { + PORTABILITY_ASSERT("Implement for PAL"); + } + + void NakedThrowHelper() + { + PORTABILITY_ASSERT("Implement for PAL"); + } + + void PInvokeStubForHost() + { + PORTABILITY_ASSERT("Implement for PAL"); + } + + void PInvokeStubForHostInner(DWORD dwStackSize, LPVOID pStackFrame, LPVOID pTarget) + { + PORTABILITY_ASSERT("Implement for PAL"); + } + + void ProfileEnterNaked(FunctionIDOrClientID functionIDOrClientID) + { + PORTABILITY_ASSERT("Implement for PAL"); + } + + void ProfileLeaveNaked(FunctionIDOrClientID functionIDOrClientID) + { + PORTABILITY_ASSERT("Implement for PAL"); + } + + void ProfileTailcallNaked(FunctionIDOrClientID functionIDOrClientID) + { + PORTABILITY_ASSERT("Implement for PAL"); + } + + void STDCALL JIT_ProfilerEnterLeaveTailcallStub(UINT_PTR ProfilerHandle) + { + } + + _Unwind_Reason_Code + UnhandledExceptionHandlerUnix( + IN int version, + IN _Unwind_Action action, + IN uint64_t exceptionClass, + IN struct _Unwind_Exception *exception, + IN struct _Unwind_Context *context + ) + { + PORTABILITY_ASSERT("UnhandledExceptionHandlerUnix"); + return _URC_FATAL_PHASE1_ERROR; + } + + BOOL CallRtlUnwind() + { + PORTABILITY_ASSERT("CallRtlUnwind"); + return FALSE; + } +}; + +VOID __cdecl PopSEHRecords(LPVOID pTargetSP) +{ + PORTABILITY_ASSERT("Implement for PAL"); +} + +EXTERN_C VOID SinglecastDelegateInvokeStub() +{ + PORTABILITY_ASSERT("SinglecastDelegateInvokeStub"); +} + +EXTERN_C VOID ResolveWorkerChainLookupAsmStub() +{ + PORTABILITY_ASSERT("ResolveWorkerChainLookupAsmStub"); +} + +EXTERN_C VOID BackPatchWorkerAsmStub() +{ + PORTABILITY_ASSERT("BackPatchWorkerAsmStub"); +} + +EXTERN_C VOID JIT_TailCall() +{ + PORTABILITY_ASSERT("JIT_TailCall"); +} + +EXTERN_C VOID JIT_TailCallReturnFromVSD() +{ + PORTABILITY_ASSERT("JIT_TailCallReturnFromVSD"); +} + +EXTERN_C VOID JIT_TailCallVSDLeave() +{ + PORTABILITY_ASSERT("JIT_TailCallVSDLeave"); +} + +EXTERN_C VOID JIT_TailCallLeave() +{ + PORTABILITY_ASSERT("JIT_TailCallLeave"); +} diff --git a/src/vm/i386/virtualcallstubcpu.hpp b/src/vm/i386/virtualcallstubcpu.hpp index 33ce819..8c16854 100644 --- a/src/vm/i386/virtualcallstubcpu.hpp +++ b/src/vm/i386/virtualcallstubcpu.hpp @@ -695,7 +695,7 @@ BOOL isDelegateCall(BYTE *interiorPtr) { LIMITED_METHOD_CONTRACT; - if (GCHeap::GetGCHeap()->IsHeapPointer((void*)interiorPtr)) + if (GCHeapUtilities::GetGCHeap()->IsHeapPointer((void*)interiorPtr)) { Object *delegate = (Object*)(interiorPtr - DelegateObject::GetOffsetOfMethodPtrAux()); VALIDATEOBJECTREF(ObjectToOBJECTREF(delegate)); diff --git a/src/vm/ilmarshalers.cpp b/src/vm/ilmarshalers.cpp index 114fbe3..c44e561 100644 --- a/src/vm/ilmarshalers.cpp +++ b/src/vm/ilmarshalers.cpp @@ -4177,7 +4177,7 @@ void ILNativeArrayMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit if (IsByref(m_dwMarshalFlags)) { // - // Reset the element count just in case there is a exception thrown in the code emitted by + // Reset the element count just in case there is an exception thrown in the code emitted by // EmitLoadElementCount. The best thing we can do here is to avoid a crash. // _ASSERTE(m_dwSavedSizeArg != LOCAL_NUM_UNUSED); diff --git a/src/vm/ilstubcache.cpp b/src/vm/ilstubcache.cpp index 4343ba8..9cd904a 100644 --- a/src/vm/ilstubcache.cpp +++ b/src/vm/ilstubcache.cpp @@ -128,7 +128,7 @@ MethodDesc* ILStubCache::CreateAndLinkNewILStubMethodDesc(LoaderAllocator* pAllo pStubLinker->GenerateCode(pbBuffer, cbCode); pStubLinker->GetLocalSig(pbLocalSig, cbSig); - pResolver->SetJitFlags(CORJIT_FLG_IL_STUB); + pResolver->SetJitFlags(CORJIT_FLAGS(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)); } pResolver->SetTokenLookupMap(pStubLinker->GetTokenLookupMap()); diff --git a/src/vm/ilstubresolver.cpp b/src/vm/ilstubresolver.cpp index 64ff99f..5ba6c8a 100644 --- a/src/vm/ilstubresolver.cpp +++ b/src/vm/ilstubresolver.cpp @@ -299,7 +299,7 @@ ILStubResolver::ILStubResolver() : m_pStubMD(dac_cast(nullptr)), m_pStubTargetMD(dac_cast(nullptr)), m_type(Unassigned), - m_dwJitFlags(0) + m_jitFlags() { LIMITED_METHOD_CONTRACT; @@ -488,16 +488,16 @@ bool ILStubResolver::IsILGenerated() return (dac_cast(m_pCompileTimeState) != ILNotYetGenerated); } -void ILStubResolver::SetJitFlags(DWORD dwFlags) +void ILStubResolver::SetJitFlags(CORJIT_FLAGS jitFlags) { LIMITED_METHOD_CONTRACT; - m_dwJitFlags = dwFlags; + m_jitFlags = jitFlags; } -DWORD ILStubResolver::GetJitFlags() +CORJIT_FLAGS ILStubResolver::GetJitFlags() { LIMITED_METHOD_CONTRACT; - return m_dwJitFlags; + return m_jitFlags; } // static diff --git a/src/vm/ilstubresolver.h b/src/vm/ilstubresolver.h index b100931..47181c8 100644 --- a/src/vm/ilstubresolver.h +++ b/src/vm/ilstubresolver.h @@ -64,8 +64,8 @@ public: void SetTokenLookupMap(TokenLookupMap* pMap); - void SetJitFlags(DWORD dwJitFlags); - DWORD GetJitFlags(); + void SetJitFlags(CORJIT_FLAGS jitFlags); + CORJIT_FLAGS GetJitFlags(); static void StubGenFailed(ILStubResolver* pResolver); @@ -116,7 +116,7 @@ protected: PTR_MethodDesc m_pStubMD; PTR_MethodDesc m_pStubTargetMD; ILStubType m_type; - DWORD m_dwJitFlags; + CORJIT_FLAGS m_jitFlags; }; typedef Holder, ILStubResolver::StubGenFailed, NULL> ILStubGenHolder; diff --git a/src/vm/interoputil.cpp b/src/vm/interoputil.cpp index 33f04b9..6a0fbde 100644 --- a/src/vm/interoputil.cpp +++ b/src/vm/interoputil.cpp @@ -2130,7 +2130,7 @@ void MinorCleanupSyncBlockComData(InteropSyncBlockInfo* pInteropInfo) NOTHROW; GC_NOTRIGGER; MODE_ANY; - PRECONDITION( GCHeap::IsGCInProgress() || ( (g_fEEShutDown & ShutDown_SyncBlock) && g_fProcessDetach ) ); + PRECONDITION( GCHeapUtilities::IsGCInProgress() || ( (g_fEEShutDown & ShutDown_SyncBlock) && g_fProcessDetach ) ); } CONTRACTL_END; diff --git a/src/vm/interpreter.cpp b/src/vm/interpreter.cpp index a540cff..b74672f 100644 --- a/src/vm/interpreter.cpp +++ b/src/vm/interpreter.cpp @@ -14,7 +14,7 @@ #include "openum.h" #include "fcall.h" #include "frames.h" -#include "gc.h" +#include "gcheaputilities.h" #include #include "jitinterface.h" #include "safemath.h" @@ -903,9 +903,10 @@ CorJitResult Interpreter::GenerateInterpreterStub(CEEInfo* comp, #endif { // But we also have to use r4, because ThumbEmitCondRegJump below requires a low register. + sl.ThumbEmitMovConstant(r11, 0); sl.ThumbEmitMovConstant(r12, UINT_PTR(interpMethInfo)); sl.ThumbEmitLoadRegIndirect(r12, r12, offsetof(InterpreterMethodInfo, m_jittedCode)); - sl.ThumbEmitCmpImm(r12, 0); // Set condition codes. + sl.ThumbEmitCmpReg(r12, r11); // Set condition codes. // If r12 is zero, then go on to do the interpretation. CodeLabel* doInterpret = sl.NewCodeLabel(); sl.ThumbEmitCondFlagJump(doInterpret, thumbCondEq.cond); @@ -1578,7 +1579,7 @@ CorJitResult Interpreter::GenerateInterpreterStub(CEEInfo* comp, #else #error unsupported platform #endif - stub = sl.Link(); + stub = sl.Link(SystemDomain::GetGlobalLoaderAllocator()->GetStubHeap()); *nativeSizeOfCode = static_cast(stub->GetNumCodeBytes()); // TODO: manage reference count of interpreter stubs. Look for examples... @@ -1736,13 +1737,13 @@ void Interpreter::JitMethodIfAppropriate(InterpreterMethodInfo* interpMethInfo, fprintf(GetLogFile(), "JITting method %s:%s.\n", md->m_pszDebugClassName, md->m_pszDebugMethodName); } #endif // _DEBUG - DWORD dwFlags = CORJIT_FLG_MAKEFINALCODE; + CORJIT_FLAGS jitFlags(CORJIT_FLAGS::CORJIT_FLAG_MAKEFINALCODE); NewHolder pDecoder(NULL); // Dynamic methods (e.g., IL stubs) do not have an IL decoder but may // require additional flags. Ordinary methods require the opposite. if (md->IsDynamicMethod()) { - dwFlags |= md->AsDynamicMethodDesc()->GetILStubResolver()->GetJitFlags(); + jitFlags.Add(md->AsDynamicMethodDesc()->GetILStubResolver()->GetJitFlags()); } else { @@ -1751,7 +1752,7 @@ void Interpreter::JitMethodIfAppropriate(InterpreterMethodInfo* interpMethInfo, md->GetMDImport(), &status); } - PCODE res = md->MakeJitWorker(pDecoder, dwFlags, 0); + PCODE res = md->MakeJitWorker(pDecoder, jitFlags); interpMethInfo->m_jittedCode = res; } } @@ -8607,6 +8608,8 @@ void Interpreter::BoxStructRefAt(unsigned ind, CORINFO_CLASS_HANDLE valCls) if (th.IsTypeDesc()) COMPlusThrow(kInvalidOperationException,W("InvalidOperation_TypeCannotBeBoxed")); + MethodTable* pMT = th.AsMethodTable(); + { Object* res = OBJECTREFToObject(pMT->Box(valPtr)); @@ -9578,7 +9581,9 @@ void Interpreter::DoCallWork(bool virtualCall, void* thisArg, CORINFO_RESOLVED_T // This is the argument slot that will be used to hold the return value. ARG_SLOT retVal = 0; +#ifndef _ARM_ _ASSERTE (NUMBER_RETURNVALUE_SLOTS == 1); +#endif // If the return type is a structure, then these will be initialized. CORINFO_CLASS_HANDLE retTypeClsHnd = NULL; @@ -10316,15 +10321,23 @@ void Interpreter::CallI() } else { - pMD = g_pPrepareConstrainedRegionsMethod; // A random static method. + pMD = g_pExecuteBackoutCodeHelperMethod; // A random static method. } MethodDescCallSite mdcs(pMD, &mSig, ftnPtr); +#if 0 // If the current method being interpreted is an IL stub, we're calling native code, so // change the GC mode. (We'll only do this at the call if the calling convention turns out // to be a managed calling convention.) MethodDesc* pStubContextMD = reinterpret_cast(m_stubContext); bool transitionToPreemptive = (pStubContextMD != NULL && !pStubContextMD->IsIL()); mdcs.CallTargetWorker(args, &retVal, sizeof(retVal), transitionToPreemptive); +#else + // TODO The code above triggers assertion at threads.cpp:6861: + // _ASSERTE(thread->PreemptiveGCDisabled()); // Should have been in managed code + // The workaround will likely break more things than what it is fixing: + // just do not make transition to preemptive GC for now. + mdcs.CallTargetWorker(args, &retVal, sizeof(retVal)); +#endif } // retVal is now vulnerable. GCX_FORBID(); diff --git a/src/vm/interpreter.h b/src/vm/interpreter.h index 92835be..1151b36 100644 --- a/src/vm/interpreter.h +++ b/src/vm/interpreter.h @@ -718,7 +718,7 @@ class InterpreterCEEInfo: public CEEInfo { CEEJitInfo m_jitInfo; public: - InterpreterCEEInfo(CORINFO_METHOD_HANDLE meth): CEEInfo((MethodDesc*)meth), m_jitInfo((MethodDesc*)meth, NULL, NULL, CorJitFlag(0)) { m_pOverride = this; } + InterpreterCEEInfo(CORINFO_METHOD_HANDLE meth): CEEInfo((MethodDesc*)meth), m_jitInfo((MethodDesc*)meth, NULL, NULL, CORJIT_FLAGS::CORJIT_FLAG_SPEED_OPT) { m_pOverride = this; } // Certain methods are unimplemented by CEEInfo (they hit an assert). They are implemented by CEEJitInfo, yet // don't seem to require any of the CEEJitInfo state we can't provide. For those case, delegate to the "partial" diff --git a/src/vm/jithelpers.cpp b/src/vm/jithelpers.cpp index 1626810..7b9389d 100644 --- a/src/vm/jithelpers.cpp +++ b/src/vm/jithelpers.cpp @@ -23,7 +23,7 @@ #include "security.h" #include "securitymeta.h" #include "dllimport.h" -#include "gc.h" +#include "gcheaputilities.h" #include "comdelegate.h" #include "jitperf.h" // to track jit perf #include "corprof.h" @@ -130,7 +130,7 @@ inline UINT64 ShiftToHi32Bits(UINT32 x) return ret.QuadPart; } -#if !defined(_TARGET_X86_) +#if !defined(_TARGET_X86_) || defined(FEATURE_PAL) /*********************************************************************/ HCIMPL2_VV(INT64, JIT_LMul, INT64 val1, INT64 val2) { @@ -145,7 +145,7 @@ HCIMPL2_VV(INT64, JIT_LMul, INT64 val1, INT64 val2) return (val1 * val2); } HCIMPLEND -#endif // !defined(_TARGET_X86_) +#endif // !_TARGET_X86_ || FEATURE_PAL /*********************************************************************/ HCIMPL2_VV(INT64, JIT_LMulOvf, INT64 val1, INT64 val2) @@ -513,7 +513,7 @@ HCIMPL1_V(double, JIT_ULng2Dbl, UINT64 val) HCIMPLEND /*********************************************************************/ -// needed for ARM +// needed for ARM and RyuJIT-x86 HCIMPL1_V(double, JIT_Lng2Dbl, INT64 val) { FCALL_CONTRACT; @@ -619,7 +619,7 @@ HCIMPL1_V(UINT64, JIT_Dbl2ULng, double val) else { // subtract 0x8000000000000000, do the convert then add it back again ret = FastDbl2Lng(val - two63) + I64(0x8000000000000000); -} + } return ret; } HCIMPLEND @@ -654,7 +654,7 @@ HCIMPL1_V(UINT64, JIT_Dbl2ULngOvf, double val) HCIMPLEND -#if !defined(_TARGET_X86_) +#if !defined(_TARGET_X86_) || defined(FEATURE_PAL) HCIMPL1_V(INT64, JIT_Dbl2Lng, double val) { @@ -755,7 +755,7 @@ HCIMPL2_VV(double, JIT_DblRem, double dividend, double divisor) } HCIMPLEND -#endif // !defined(_TARGET_X86_) +#endif // !_TARGET_X86_ || FEATURE_PAL #include @@ -2858,7 +2858,7 @@ HCIMPL1(Object*, JIT_NewS_MP_FastPortable, CORINFO_CLASS_HANDLE typeHnd_) do { - _ASSERTE(GCHeap::UseAllocationContexts()); + _ASSERTE(GCHeapUtilities::UseAllocationContexts()); // This is typically the only call in the fast path. Making the call early seems to be better, as it allows the compiler // to use volatile registers for intermediate values. This reduces the number of push/pop instructions and eliminates @@ -2872,7 +2872,7 @@ HCIMPL1(Object*, JIT_NewS_MP_FastPortable, CORINFO_CLASS_HANDLE typeHnd_) SIZE_T size = methodTable->GetBaseSize(); _ASSERTE(size % DATA_ALIGNMENT == 0); - alloc_context *allocContext = thread->GetAllocContext(); + gc_alloc_context *allocContext = thread->GetAllocContext(); BYTE *allocPtr = allocContext->alloc_ptr; _ASSERTE(allocPtr <= allocContext->alloc_limit); if (size > static_cast(allocContext->alloc_limit - allocPtr)) @@ -2997,7 +2997,7 @@ HCIMPL1(StringObject*, AllocateString_MP_FastPortable, DWORD stringLength) do { - _ASSERTE(GCHeap::UseAllocationContexts()); + _ASSERTE(GCHeapUtilities::UseAllocationContexts()); // Instead of doing elaborate overflow checks, we just limit the number of elements. This will avoid all overflow // problems, as well as making sure big string objects are correctly allocated in the big object heap. @@ -3021,7 +3021,7 @@ HCIMPL1(StringObject*, AllocateString_MP_FastPortable, DWORD stringLength) _ASSERTE(alignedTotalSize >= totalSize); totalSize = alignedTotalSize; - alloc_context *allocContext = thread->GetAllocContext(); + gc_alloc_context *allocContext = thread->GetAllocContext(); BYTE *allocPtr = allocContext->alloc_ptr; _ASSERTE(allocPtr <= allocContext->alloc_limit); if (totalSize > static_cast(allocContext->alloc_limit - allocPtr)) @@ -3161,7 +3161,7 @@ HCIMPL2(Object*, JIT_NewArr1VC_MP_FastPortable, CORINFO_CLASS_HANDLE arrayTypeHn do { - _ASSERTE(GCHeap::UseAllocationContexts()); + _ASSERTE(GCHeapUtilities::UseAllocationContexts()); // Do a conservative check here. This is to avoid overflow while doing the calculations. We don't // have to worry about "large" objects, since the allocation quantum is never big enough for @@ -3198,7 +3198,7 @@ HCIMPL2(Object*, JIT_NewArr1VC_MP_FastPortable, CORINFO_CLASS_HANDLE arrayTypeHn _ASSERTE(alignedTotalSize >= totalSize); totalSize = alignedTotalSize; - alloc_context *allocContext = thread->GetAllocContext(); + gc_alloc_context *allocContext = thread->GetAllocContext(); BYTE *allocPtr = allocContext->alloc_ptr; _ASSERTE(allocPtr <= allocContext->alloc_limit); if (totalSize > static_cast(allocContext->alloc_limit - allocPtr)) @@ -3238,7 +3238,7 @@ HCIMPL2(Object*, JIT_NewArr1OBJ_MP_FastPortable, CORINFO_CLASS_HANDLE arrayTypeH do { - _ASSERTE(GCHeap::UseAllocationContexts()); + _ASSERTE(GCHeapUtilities::UseAllocationContexts()); // Make sure that the total size cannot reach LARGE_OBJECT_SIZE, which also allows us to avoid overflow checks. The // "256" slack is to cover the array header size and round-up, using a constant value here out of laziness. @@ -3266,7 +3266,7 @@ HCIMPL2(Object*, JIT_NewArr1OBJ_MP_FastPortable, CORINFO_CLASS_HANDLE arrayTypeH _ASSERTE(ALIGN_UP(totalSize, DATA_ALIGNMENT) == totalSize); - alloc_context *allocContext = thread->GetAllocContext(); + gc_alloc_context *allocContext = thread->GetAllocContext(); BYTE *allocPtr = allocContext->alloc_ptr; _ASSERTE(allocPtr <= allocContext->alloc_limit); if (totalSize > static_cast(allocContext->alloc_limit - allocPtr)) @@ -6431,7 +6431,7 @@ HCIMPL0(VOID, JIT_StressGC) bool fSkipGC = false; if (!fSkipGC) - GCHeap::GetGCHeap()->GarbageCollect(); + GCHeapUtilities::GetGCHeap()->GarbageCollect(); // @TODO: the following ifdef is in error, but if corrected the // compiler complains about the *__ms->pRetAddr() saying machine state diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index 76d4568..2f9db3d 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -27,7 +27,7 @@ #include "security.h" #include "securitymeta.h" #include "dllimport.h" -#include "gc.h" +#include "gcheaputilities.h" #include "comdelegate.h" #include "jitperf.h" // to track jit perf #include "corprof.h" @@ -2303,11 +2303,21 @@ unsigned CEEInfo::getClassGClayout (CORINFO_CLASS_HANDLE clsHnd, BYTE* gcPtrs) MethodTable* pMT = VMClsHnd.GetMethodTable(); - if (pMT == g_TypedReferenceMT) + if (pMT->IsByRefLike()) { - gcPtrs[0] = TYPE_GC_BYREF; - gcPtrs[1] = TYPE_GC_NONE; - result = 1; + if (pMT == g_TypedReferenceMT) + { + gcPtrs[0] = TYPE_GC_BYREF; + gcPtrs[1] = TYPE_GC_NONE; + result = 1; + } + else + { + // TODO-SPAN: Proper GC reporting + memset(gcPtrs, TYPE_GC_NONE, + (VMClsHnd.GetSize() + sizeof(void*) -1)/ sizeof(void*)); + result = 0; + } } else if (VMClsHnd.IsNativeValueType()) { @@ -3988,7 +3998,7 @@ DWORD CEEInfo::getClassAttribsInternal (CORINFO_CLASS_HANDLE clsHnd) if (pMT->IsMarshaledByRef()) ret |= CORINFO_FLG_MARSHAL_BYREF; - if (pMT->ContainsPointers()) + if (pMT->ContainsPointers() || pMT == g_TypedReferenceMT) ret |= CORINFO_FLG_CONTAINS_GC_PTR; if (pMT->IsDelegate()) @@ -5027,6 +5037,7 @@ void CEEInfo::getCallInfo( } +#ifdef FEATURE_CER if (pMD == g_pPrepareConstrainedRegionsMethod && !isVerifyOnly()) { MethodDesc * methodFromContext = GetMethodFromContext(pResolvedToken->tokenContext); @@ -5048,6 +5059,7 @@ void CEEInfo::getCallInfo( } } } +#endif // FEATURE_CER TypeHandle exactType = TypeHandle(pResolvedToken->hClass); @@ -5093,6 +5105,19 @@ void CEEInfo::getCallInfo( // shared generic code - it may just resolve it to a candidate suitable for // JIT compilation, and require a runtime lookup for the actual code pointer // to call. + if (constrainedType.IsEnum()) + { + // Optimize constrained calls to enum's GetHashCode method. TryResolveConstraintMethodApprox would return + // null since the virtual method resolves to System.Enum's implementation and that's a reference type. + // We can't do this for any other method since ToString and Equals have different semantics for enums + // and their underlying type. + if (pMD->GetSlot() == MscorlibBinder::GetMethod(METHOD__OBJECT__GET_HASH_CODE)->GetSlot()) + { + // Pretend this was a "constrained. UnderlyingType" instruction prefix + constrainedType = TypeHandle(MscorlibBinder::GetElementType(constrainedType.GetVerifierCorElementType())); + } + } + MethodDesc * directMethod = constrainedType.GetMethodTable()->TryResolveConstraintMethodApprox( exactType, pMD, @@ -6767,6 +6792,28 @@ void getMethodInfoILMethodHeaderHelper( (CorInfoOptions)((header->GetFlags() & CorILMethod_InitLocals) ? CORINFO_OPT_INIT_LOCALS : 0) ; } +mdToken FindGenericMethodArgTypeSpec(IMDInternalImport* pInternalImport) +{ + STANDARD_VM_CONTRACT; + + HENUMInternalHolder hEnumTypeSpecs(pInternalImport); + mdToken token; + + static const BYTE signature[] = { ELEMENT_TYPE_MVAR, 0 }; + + hEnumTypeSpecs.EnumAllInit(mdtTypeSpec); + while (hEnumTypeSpecs.EnumNext(&token)) + { + PCCOR_SIGNATURE pSig; + ULONG cbSig; + IfFailThrow(pInternalImport->GetTypeSpecFromToken(token, &pSig, &cbSig)); + if (cbSig == sizeof(signature) && memcmp(pSig, signature, cbSig) == 0) + return token; + } + + COMPlusThrowHR(COR_E_BADIMAGEFORMAT); +} + /********************************************************************* IL is the most efficient and portable way to implement certain low level methods @@ -6878,10 +6925,165 @@ bool getILIntrinsicImplementation(MethodDesc * ftn, return true; } } +#ifdef FEATURE_SPAN_OF_T + else if (tk == MscorlibBinder::GetMethod(METHOD__JIT_HELPERS__BYREF_LESSTHAN)->GetMemberDef()) + { + // Compare the two arguments + static const BYTE ilcode[] = { CEE_LDARG_0, CEE_LDARG_1, CEE_PREFIX1, (CEE_CLT & 0xFF), CEE_RET }; + methInfo->ILCode = const_cast(ilcode); + methInfo->ILCodeSize = sizeof(ilcode); + methInfo->maxStack = 2; + methInfo->EHcount = 0; + methInfo->options = (CorInfoOptions)0; + return true; + } + else if (tk == MscorlibBinder::GetMethod(METHOD__JIT_HELPERS__GET_ARRAY_DATA)->GetMemberDef()) + { + mdToken tokArrayPinningHelper = MscorlibBinder::GetField(FIELD__ARRAY_PINNING_HELPER__M_ARRAY_DATA)->GetMemberDef(); + + static BYTE ilcode[] = { CEE_LDARG_0, + CEE_LDFLDA,0,0,0,0, + CEE_RET }; + + ilcode[2] = (BYTE)(tokArrayPinningHelper); + ilcode[3] = (BYTE)(tokArrayPinningHelper >> 8); + ilcode[4] = (BYTE)(tokArrayPinningHelper >> 16); + ilcode[5] = (BYTE)(tokArrayPinningHelper >> 24); + + methInfo->ILCode = const_cast(ilcode); + methInfo->ILCodeSize = sizeof(ilcode); + methInfo->maxStack = 1; + methInfo->EHcount = 0; + methInfo->options = (CorInfoOptions)0; + return true; + } + else if (tk == MscorlibBinder::GetMethod(METHOD__JIT_HELPERS__CONTAINSREFERENCES)->GetMemberDef()) + { + _ASSERTE(ftn->HasMethodInstantiation()); + Instantiation inst = ftn->GetMethodInstantiation(); + + _ASSERTE(ftn->GetNumGenericMethodArgs() == 1); + TypeHandle typeHandle = inst[0]; + MethodTable * methodTable = typeHandle.GetMethodTable(); + + static const BYTE returnTrue[] = { CEE_LDC_I4_1, CEE_RET }; + static const BYTE returnFalse[] = { CEE_LDC_I4_0, CEE_RET }; + + if (!methodTable->IsValueType() || methodTable->ContainsPointers()) + { + methInfo->ILCode = const_cast(returnTrue); + } + else + { + methInfo->ILCode = const_cast(returnFalse); + } + + methInfo->ILCodeSize = sizeof(returnTrue); + methInfo->maxStack = 1; + methInfo->EHcount = 0; + methInfo->options = (CorInfoOptions)0; + return true; + } +#endif // FEATURE_SPAN_OF_T return false; } +#ifdef FEATURE_SPAN_OF_T +bool getILIntrinsicImplementationForUnsafe(MethodDesc * ftn, + CORINFO_METHOD_INFO * methInfo) +{ + STANDARD_VM_CONTRACT; + + // Precondition: ftn is a method in mscorlib + _ASSERTE(ftn->GetModule()->IsSystem()); + + mdMethodDef tk = ftn->GetMemberDef(); + + if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__AS_POINTER)->GetMemberDef()) + { + // Return the argument that was passed in. + static const BYTE ilcode[] = { CEE_LDARG_0, CEE_CONV_U, CEE_RET }; + methInfo->ILCode = const_cast(ilcode); + methInfo->ILCodeSize = sizeof(ilcode); + methInfo->maxStack = 1; + methInfo->EHcount = 0; + methInfo->options = (CorInfoOptions)0; + return true; + } + if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__SIZEOF)->GetMemberDef()) + { + _ASSERTE(ftn->HasMethodInstantiation()); + Instantiation inst = ftn->GetMethodInstantiation(); + + _ASSERTE(ftn->GetNumGenericMethodArgs() == 1); + mdToken tokGenericArg = FindGenericMethodArgTypeSpec(MscorlibBinder::GetModule()->GetMDImport()); + + static BYTE ilcode[] = { CEE_PREFIX1, (CEE_SIZEOF & 0xFF), 0,0,0,0, CEE_RET }; + + ilcode[2] = (BYTE)(tokGenericArg); + ilcode[3] = (BYTE)(tokGenericArg >> 8); + ilcode[4] = (BYTE)(tokGenericArg >> 16); + ilcode[5] = (BYTE)(tokGenericArg >> 24); + + methInfo->ILCode = const_cast(ilcode); + methInfo->ILCodeSize = sizeof(ilcode); + methInfo->maxStack = 1; + methInfo->EHcount = 0; + methInfo->options = (CorInfoOptions)0; + return true; + } + else if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__BYREF_AS)->GetMemberDef()) + { + // Return the argument that was passed in. + static const BYTE ilcode[] = { CEE_LDARG_0, CEE_RET }; + methInfo->ILCode = const_cast(ilcode); + methInfo->ILCodeSize = sizeof(ilcode); + methInfo->maxStack = 1; + methInfo->EHcount = 0; + methInfo->options = (CorInfoOptions)0; + return true; + } + else if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__BYREF_ADD)->GetMemberDef()) + { + mdToken tokGenericArg = FindGenericMethodArgTypeSpec(MscorlibBinder::GetModule()->GetMDImport()); + + static BYTE ilcode[] = { CEE_LDARG_1, + CEE_PREFIX1, (CEE_SIZEOF & 0xFF), 0,0,0,0, + CEE_CONV_I, + CEE_MUL, + CEE_LDARG_0, + CEE_ADD, + CEE_RET }; + + ilcode[3] = (BYTE)(tokGenericArg); + ilcode[4] = (BYTE)(tokGenericArg >> 8); + ilcode[5] = (BYTE)(tokGenericArg >> 16); + ilcode[6] = (BYTE)(tokGenericArg >> 24); + + methInfo->ILCode = const_cast(ilcode); + methInfo->ILCodeSize = sizeof(ilcode); + methInfo->maxStack = 2; + methInfo->EHcount = 0; + methInfo->options = (CorInfoOptions)0; + return true; + } + else if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__BYREF_ARE_SAME)->GetMemberDef()) + { + // Compare the two arguments + static const BYTE ilcode[] = { CEE_LDARG_0, CEE_LDARG_1, CEE_PREFIX1, (CEE_CEQ & 0xFF), CEE_RET }; + methInfo->ILCode = const_cast(ilcode); + methInfo->ILCodeSize = sizeof(ilcode); + methInfo->maxStack = 2; + methInfo->EHcount = 0; + methInfo->options = (CorInfoOptions)0; + return true; + } + + return false; +} +#endif // FEATURE_SPAN_OF_T + bool getILIntrinsicImplementationForVolatile(MethodDesc * ftn, CORINFO_METHOD_INFO * methInfo) { @@ -7062,6 +7264,12 @@ getMethodInfoHelper( { fILIntrinsic = getILIntrinsicImplementation(ftn, methInfo); } +#ifdef FEATURE_SPAN_OF_T + else if (MscorlibBinder::IsClass(pMT, CLASS__UNSAFE)) + { + fILIntrinsic = getILIntrinsicImplementationForUnsafe(ftn, methInfo); + } +#endif else if (MscorlibBinder::IsClass(pMT, CLASS__INTERLOCKED)) { fILIntrinsic = getILIntrinsicImplementationForInterlocked(ftn, methInfo); @@ -7394,11 +7602,15 @@ CorInfoInline CEEInfo::canInline (CORINFO_METHOD_HANDLE hCaller, // If the callee wants debuggable code, don't allow it to be inlined - if (GetDebuggerCompileFlags(pCallee->GetModule(), 0) & CORJIT_FLG_DEBUG_CODE) { - result = INLINE_NEVER; - szFailReason = "Inlinee is debuggable"; - goto exit; + // Combining the next two lines, and eliminating jitDebuggerFlags, leads to bad codegen in x86 Release builds using Visual C++ 19.00.24215.1. + CORJIT_FLAGS jitDebuggerFlags = GetDebuggerCompileFlags(pCallee->GetModule(), CORJIT_FLAGS()); + if (jitDebuggerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE)) + { + result = INLINE_NEVER; + szFailReason = "Inlinee is debuggable"; + goto exit; + } } #endif @@ -8167,6 +8379,7 @@ bool CEEInfo::canTailCall (CORINFO_METHOD_HANDLE hCaller, } } +#ifdef FEATURE_CER // We cannot tail call from a root CER method, the thread abort algorithm to // detect CERs depends on seeing such methods on the stack. if (IsCerRootMethod(pCaller)) @@ -8175,6 +8388,7 @@ bool CEEInfo::canTailCall (CORINFO_METHOD_HANDLE hCaller, szFailReason = "Caller is a CER root"; goto exit; } +#endif // FEATURE_CER result = true; @@ -8627,6 +8841,9 @@ void CEEInfo::getFunctionEntryPoint(CORINFO_METHOD_HANDLE ftnHnd, JIT_TO_EE_TRANSITION(); MethodDesc * ftn = GetMethod(ftnHnd); +#if defined(FEATURE_GDBJIT) + MethodDesc * orig_ftn = ftn; +#endif // Resolve methodImpl. ftn = ftn->GetMethodTable()->MapMethodDeclToMethodImpl(ftn); @@ -8645,6 +8862,12 @@ void CEEInfo::getFunctionEntryPoint(CORINFO_METHOD_HANDLE ftnHnd, accessType = IAT_PVALUE; } + +#if defined(FEATURE_GDBJIT) + CalledMethod * pCM = new CalledMethod(orig_ftn, ret, m_pCalledMethods); + m_pCalledMethods = pCM; +#endif + EE_TO_JIT_TRANSITION(); _ASSERTE(ret != NULL); @@ -9103,7 +9326,7 @@ CorInfoTypeWithMod CEEInfo::getArgType ( CorElementType normType = typeHnd.GetInternalCorElementType(); // if we are looking up a value class, don't morph it to a refernece type - // (This can only happen in illegal IL + // (This can only happen in illegal IL) if (!CorTypeInfo::IsObjRef(normType) || type != ELEMENT_TYPE_VALUETYPE) { type = normType; @@ -11677,8 +11900,7 @@ static CorJitResult CompileMethodWithEtwWrapper(EEJitManager *jitMgr, CorJitResult invokeCompileMethodHelper(EEJitManager *jitMgr, CEEInfo *comp, struct CORINFO_METHOD_INFO *info, - unsigned flags, - unsigned flags2, + CORJIT_FLAGS jitFlags, BYTE **nativeEntry, ULONG *nativeSizeOfCode) { @@ -11689,13 +11911,9 @@ CorJitResult invokeCompileMethodHelper(EEJitManager *jitMgr, CorJitResult ret = CORJIT_SKIPPED; // Note that CORJIT_SKIPPED is an error exit status code - CORJIT_FLAGS jitFlags = { 0 }; - jitFlags.corJitFlags = flags; - jitFlags.corJitFlags2 = flags2; - #if !defined(FEATURE_CORECLR) // Ask the JIT to generate desktop-quirk-compatible code. - jitFlags.corJitFlags2 |= CORJIT_FLG2_DESKTOP_QUIRKS; + jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_DESKTOP_QUIRKS); #endif comp->setJitFlags(jitFlags); @@ -11711,7 +11929,7 @@ CorJitResult invokeCompileMethodHelper(EEJitManager *jitMgr, #if defined(CROSSGEN_COMPILE) && !defined(FEATURE_CORECLR) ret = getJit()->compileMethod( comp, info, - CORJIT_FLG_CALL_GETJITFLAGS, + CORJIT_FLAGS::CORJIT_FLAG_CALL_GETJITFLAGS, nativeEntry, nativeSizeOfCode); @@ -11720,18 +11938,18 @@ CorJitResult invokeCompileMethodHelper(EEJitManager *jitMgr, #if defined(ALLOW_SXS_JIT) && !defined(CROSSGEN_COMPILE) if (FAILED(ret) && jitMgr->m_alternateJit #ifdef FEATURE_STACK_SAMPLING - && (!samplingEnabled || (jitFlags.corJitFlags2 & CORJIT_FLG2_SAMPLING_JIT_BACKGROUND)) + && (!samplingEnabled || (jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SAMPLING_JIT_BACKGROUND))) #endif ) { ret = jitMgr->m_alternateJit->compileMethod( comp, info, - CORJIT_FLG_CALL_GETJITFLAGS, + CORJIT_FLAGS::CORJIT_FLAG_CALL_GETJITFLAGS, nativeEntry, nativeSizeOfCode ); #ifdef FEATURE_STACK_SAMPLING - if (jitFlags.corJitFlags2 & CORJIT_FLG2_SAMPLING_JIT_BACKGROUND) + if (jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SAMPLING_JIT_BACKGROUND)) { // Don't bother with failures if we couldn't collect a trace. ret = CORJIT_OK; @@ -11758,7 +11976,7 @@ CorJitResult invokeCompileMethodHelper(EEJitManager *jitMgr, { // If we're doing an "import_only" compilation, it's for verification, so don't interpret. // (We assume that importation is completely architecture-independent, or at least nearly so.) - if (FAILED(ret) && (jitFlags.corJitFlags & (CORJIT_FLG_IMPORT_ONLY | CORJIT_FLG_MAKEFINALCODE)) == 0) + if (FAILED(ret) && !jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY) && !jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_MAKEFINALCODE)) { ret = Interpreter::GenerateInterpreterStub(comp, info, nativeEntry, nativeSizeOfCode); } @@ -11769,7 +11987,7 @@ CorJitResult invokeCompileMethodHelper(EEJitManager *jitMgr, ret = CompileMethodWithEtwWrapper(jitMgr, comp, info, - CORJIT_FLG_CALL_GETJITFLAGS, + CORJIT_FLAGS::CORJIT_FLAG_CALL_GETJITFLAGS, nativeEntry, nativeSizeOfCode); } @@ -11778,7 +11996,7 @@ CorJitResult invokeCompileMethodHelper(EEJitManager *jitMgr, { // If we're doing an "import_only" compilation, it's for verification, so don't interpret. // (We assume that importation is completely architecture-independent, or at least nearly so.) - if (FAILED(ret) && (jitFlags.corJitFlags & (CORJIT_FLG_IMPORT_ONLY | CORJIT_FLG_MAKEFINALCODE)) == 0) + if (FAILED(ret) && !jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY) && !jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_MAKEFINALCODE)) { ret = Interpreter::GenerateInterpreterStub(comp, info, nativeEntry, nativeSizeOfCode); } @@ -11788,7 +12006,7 @@ CorJitResult invokeCompileMethodHelper(EEJitManager *jitMgr, { ret = jitMgr->m_jit->compileMethod( comp, info, - CORJIT_FLG_CALL_GETJITFLAGS, + CORJIT_FLAGS::CORJIT_FLAG_CALL_GETJITFLAGS, nativeEntry, nativeSizeOfCode); } @@ -11800,7 +12018,7 @@ CorJitResult invokeCompileMethodHelper(EEJitManager *jitMgr, // If the JIT fails we keep the IL around and will // try reJIT the same IL. VSW 525059 // - if (SUCCEEDED(ret) && !(jitFlags.corJitFlags & CORJIT_FLG_IMPORT_ONLY) && !((CEEJitInfo*)comp)->JitAgain()) + if (SUCCEEDED(ret) && !jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY) && !((CEEJitInfo*)comp)->JitAgain()) { ((CEEJitInfo*)comp)->CompressDebugInfo(); @@ -11815,6 +12033,14 @@ CorJitResult invokeCompileMethodHelper(EEJitManager *jitMgr, #endif // defined(CROSSGEN_COMPILE) && !defined(FEATURE_CORECLR) +#if defined(FEATURE_GDBJIT) + if (SUCCEEDED(ret) && *nativeEntry != NULL) + { + CodeHeader* pCH = ((CodeHeader*)((PCODE)*nativeEntry & ~1)) - 1; + pCH->SetCalledMethods((PTR_VOID)comp->GetCalledMethods()); + } +#endif + END_SO_TOLERANT_CODE; return ret; @@ -11825,8 +12051,7 @@ CorJitResult invokeCompileMethodHelper(EEJitManager *jitMgr, CorJitResult invokeCompileMethod(EEJitManager *jitMgr, CEEInfo *comp, struct CORINFO_METHOD_INFO *info, - unsigned flags, - unsigned flags2, + CORJIT_FLAGS jitFlags, BYTE **nativeEntry, ULONG *nativeSizeOfCode) { @@ -11841,7 +12066,7 @@ CorJitResult invokeCompileMethod(EEJitManager *jitMgr, GCX_PREEMP(); - CorJitResult ret = invokeCompileMethodHelper(jitMgr, comp, info, flags, flags2, nativeEntry, nativeSizeOfCode); + CorJitResult ret = invokeCompileMethodHelper(jitMgr, comp, info, jitFlags, nativeEntry, nativeSizeOfCode); // // Verify that we are still in preemptive mode when we return @@ -11853,9 +12078,9 @@ CorJitResult invokeCompileMethod(EEJitManager *jitMgr, return ret; } -CorJitFlag GetCompileFlagsIfGenericInstantiation( +CORJIT_FLAGS GetCompileFlagsIfGenericInstantiation( CORINFO_METHOD_HANDLE method, - CorJitFlag compileFlags, + CORJIT_FLAGS compileFlags, ICorJitInfo * pCorJitInfo, BOOL * raiseVerificationException, BOOL * unverifiableGenericCode); @@ -11863,8 +12088,7 @@ CorJitFlag GetCompileFlagsIfGenericInstantiation( CorJitResult CallCompileMethodWithSEHWrapper(EEJitManager *jitMgr, CEEInfo *comp, struct CORINFO_METHOD_INFO *info, - unsigned flags, - unsigned flags2, + CORJIT_FLAGS flags, BYTE **nativeEntry, ULONG *nativeSizeOfCode, MethodDesc *ftn) @@ -11880,8 +12104,7 @@ CorJitResult CallCompileMethodWithSEHWrapper(EEJitManager *jitMgr, EEJitManager *jitMgr; CEEInfo *comp; struct CORINFO_METHOD_INFO *info; - unsigned flags; - unsigned flags2; + CORJIT_FLAGS flags; BYTE **nativeEntry; ULONG *nativeSizeOfCode; MethodDesc *ftn; @@ -11891,7 +12114,6 @@ CorJitResult CallCompileMethodWithSEHWrapper(EEJitManager *jitMgr, param.comp = comp; param.info = info; param.flags = flags; - param.flags2 = flags2; param.nativeEntry = nativeEntry; param.nativeSizeOfCode = nativeSizeOfCode; param.ftn = ftn; @@ -11907,16 +12129,16 @@ CorJitResult CallCompileMethodWithSEHWrapper(EEJitManager *jitMgr, pParam->comp, pParam->info, pParam->flags, - pParam->flags2, pParam->nativeEntry, pParam->nativeSizeOfCode); } PAL_FINALLY { #if defined(DEBUGGING_SUPPORTED) && !defined(CROSSGEN_COMPILE) - if (!(flags & (CORJIT_FLG_IMPORT_ONLY | CORJIT_FLG_MCJIT_BACKGROUND)) + if (!flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY) && + !flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_MCJIT_BACKGROUND) #ifdef FEATURE_STACK_SAMPLING - && !(flags2 & CORJIT_FLG2_SAMPLING_JIT_BACKGROUND) + && !flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SAMPLING_JIT_BACKGROUND) #endif // FEATURE_STACK_SAMPLING ) { @@ -11954,7 +12176,7 @@ CorJitResult CallCompileMethodWithSEHWrapper(EEJitManager *jitMgr, /*********************************************************************/ // Figures out the compile flags that are used by both JIT and NGen -/* static */ DWORD CEEInfo::GetBaseCompileFlags(MethodDesc * ftn) +/* static */ CORJIT_FLAGS CEEInfo::GetBaseCompileFlags(MethodDesc * ftn) { CONTRACTL { THROWS; @@ -11965,16 +12187,16 @@ CorJitResult CallCompileMethodWithSEHWrapper(EEJitManager *jitMgr, // Figure out the code quality flags // - DWORD flags = 0; + CORJIT_FLAGS flags; if (g_pConfig->JitFramed()) - flags |= CORJIT_FLG_FRAMED; + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_FRAMED); if (g_pConfig->JitAlignLoops()) - flags |= CORJIT_FLG_ALIGN_LOOPS; + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_ALIGN_LOOPS); if (ReJitManager::IsReJITEnabled() || g_pConfig->AddRejitNops()) - flags |= CORJIT_FLG_PROF_REJIT_NOPS; + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROF_REJIT_NOPS); #ifdef _TARGET_X86_ if (g_pConfig->PInvokeRestoreEsp(ftn->GetModule()->IsPreV4Assembly())) - flags |= CORJIT_FLG_PINVOKE_RESTORE_ESP; + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_PINVOKE_RESTORE_ESP); #endif // _TARGET_X86_ //See if we should instruct the JIT to emit calls to JIT_PollGC for thread suspension. If we have a @@ -11982,9 +12204,9 @@ CorJitResult CallCompileMethodWithSEHWrapper(EEJitManager *jitMgr, #ifdef FEATURE_ENABLE_GCPOLL EEConfig::GCPollType pollType = g_pConfig->GetGCPollType(); if (EEConfig::GCPOLL_TYPE_POLL == pollType) - flags |= CORJIT_FLG_GCPOLL_CALLS; + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_GCPOLL_CALLS); else if (EEConfig::GCPOLL_TYPE_INLINE == pollType) - flags |= CORJIT_FLG_GCPOLL_INLINE; + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_GCPOLL_INLINE); #endif //FEATURE_ENABLE_GCPOLL // Set flags based on method's ImplFlags. @@ -11995,13 +12217,13 @@ CorJitResult CallCompileMethodWithSEHWrapper(EEJitManager *jitMgr, if (IsMiNoOptimization(dwImplFlags)) { - flags |= CORJIT_FLG_MIN_OPT; + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_MIN_OPT); } // Always emit frames for methods marked no-inline (see #define ETW_EBP_FRAMED in the JIT) if (IsMiNoInlining(dwImplFlags)) { - flags |= CORJIT_FLG_FRAMED; + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_FRAMED); } } @@ -12012,7 +12234,7 @@ CorJitResult CallCompileMethodWithSEHWrapper(EEJitManager *jitMgr, // Figures out (some of) the flags to use to compile the method // Returns the new set to use -DWORD GetDebuggerCompileFlags(Module* pModule, DWORD flags) +CORJIT_FLAGS GetDebuggerCompileFlags(Module* pModule, CORJIT_FLAGS flags) { STANDARD_VM_CONTRACT; @@ -12027,36 +12249,37 @@ DWORD GetDebuggerCompileFlags(Module* pModule, DWORD flags) #ifdef _DEBUG if (g_pConfig->GenDebuggableCode()) - flags |= CORJIT_FLG_DEBUG_CODE; + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE); #endif // _DEBUG #ifdef EnC_SUPPORTED if (pModule->IsEditAndContinueEnabled()) { - flags |= CORJIT_FLG_DEBUG_EnC; + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_EnC); } #endif // EnC_SUPPORTED // Debug info is always tracked - flags |= CORJIT_FLG_DEBUG_INFO; + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); #endif // DEBUGGING_SUPPORTED if (CORDisableJITOptimizations(pModule->GetDebuggerInfoBits())) { - flags |= CORJIT_FLG_DEBUG_CODE; + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE); } - if (flags & CORJIT_FLG_IMPORT_ONLY) + if (flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY)) { // If we are only verifying the method, dont need any debug info and this // prevents getVars()/getBoundaries() from being called unnecessarily. - flags &= ~(CORJIT_FLG_DEBUG_INFO|CORJIT_FLG_DEBUG_CODE); + flags.Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); + flags.Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE); } return flags; } -CorJitFlag GetCompileFlags(MethodDesc * ftn, DWORD flags, CORINFO_METHOD_INFO * methodInfo) +CORJIT_FLAGS GetCompileFlags(MethodDesc * ftn, CORJIT_FLAGS flags, CORINFO_METHOD_INFO * methodInfo) { STANDARD_VM_CONTRACT; @@ -12065,14 +12288,14 @@ CorJitFlag GetCompileFlags(MethodDesc * ftn, DWORD flags, CORINFO_METHOD_INFO * // // Get the compile flags that are shared between JIT and NGen // - flags |= CEEInfo::GetBaseCompileFlags(ftn); + flags.Add(CEEInfo::GetBaseCompileFlags(ftn)); // // Get CPU specific flags // - if ((flags & CORJIT_FLG_IMPORT_ONLY) == 0) + if (!flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY)) { - flags |= ExecutionManager::GetEEJitManager()->GetCPUCompileFlags(); + flags.Add(ExecutionManager::GetEEJitManager()->GetCPUCompileFlags()); } // @@ -12080,21 +12303,19 @@ CorJitFlag GetCompileFlags(MethodDesc * ftn, DWORD flags, CORINFO_METHOD_INFO * // #ifdef DEBUGGING_SUPPORTED - flags |= GetDebuggerCompileFlags(ftn->GetModule(), flags); + flags.Add(GetDebuggerCompileFlags(ftn->GetModule(), flags)); #endif #ifdef PROFILING_SUPPORTED - if (CORProfilerTrackEnterLeave() - && !ftn->IsNoMetadata() - ) - flags |= CORJIT_FLG_PROF_ENTERLEAVE; + if (CORProfilerTrackEnterLeave() && !ftn->IsNoMetadata()) + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE); if (CORProfilerTrackTransitions()) - flags |= CORJIT_FLG_PROF_NO_PINVOKE_INLINE; + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROF_NO_PINVOKE_INLINE); #endif // PROFILING_SUPPORTED // Set optimization flags - if (0 == (flags & CORJIT_FLG_MIN_OPT)) + if (!flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_MIN_OPT)) { unsigned optType = g_pConfig->GenOptimizeType(); _ASSERTE(optType <= OPT_RANDOM); @@ -12103,18 +12324,16 @@ CorJitFlag GetCompileFlags(MethodDesc * ftn, DWORD flags, CORINFO_METHOD_INFO * optType = methodInfo->ILCodeSize % OPT_RANDOM; if (g_pConfig->JitMinOpts()) - flags |= CORJIT_FLG_MIN_OPT; + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_MIN_OPT); - const static unsigned optTypeFlags[] = + if (optType == OPT_SIZE) { - 0, // OPT_BLENDED - CORJIT_FLG_SIZE_OPT, // OPT_CODE_SIZE - CORJIT_FLG_SPEED_OPT // OPT_CODE_SPEED - }; - - _ASSERTE(optType < OPT_RANDOM); - _ASSERTE((sizeof(optTypeFlags)/sizeof(optTypeFlags[0])) == OPT_RANDOM); - flags |= optTypeFlags[optType]; + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_SIZE_OPT); + } + else if (optType == OPT_SPEED) + { + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_SPEED_OPT); + } } // @@ -12123,22 +12342,21 @@ CorJitFlag GetCompileFlags(MethodDesc * ftn, DWORD flags, CORINFO_METHOD_INFO * #ifdef _DEBUG if (g_pConfig->IsJitVerificationDisabled()) - flags |= CORJIT_FLG_SKIP_VERIFICATION; + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION); #endif // _DEBUG - if ((flags & CORJIT_FLG_IMPORT_ONLY) == 0 && - Security::CanSkipVerification(ftn)) - flags |= CORJIT_FLG_SKIP_VERIFICATION; + if (!flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY) && Security::CanSkipVerification(ftn)) + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION); if (ftn->IsILStub()) { - flags |= CORJIT_FLG_SKIP_VERIFICATION; + flags.Set(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION); // no debug info available for IL stubs - flags &= ~CORJIT_FLG_DEBUG_INFO; + flags.Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); } - return (CorJitFlag)flags; + return flags; } #if defined(_WIN64) @@ -12148,12 +12366,12 @@ CorJitFlag GetCompileFlags(MethodDesc * ftn, DWORD flags, CORINFO_METHOD_INFO * // //This only works for real methods. If the method isn't IsIL, then IsVerifiable will AV. That would be a //bad thing (TM). -BOOL IsTransparentMethodSafeToSkipVerification(CorJitFlag flags, MethodDesc * ftn) +BOOL IsTransparentMethodSafeToSkipVerification(CORJIT_FLAGS flags, MethodDesc * ftn) { STANDARD_VM_CONTRACT; BOOL ret = FALSE; - if (!(flags & CORJIT_FLG_IMPORT_ONLY) && !(flags & CORJIT_FLG_SKIP_VERIFICATION) + if (!flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY) && !flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION) && Security::IsMethodTransparent(ftn) && ((ftn->IsIL() && !ftn->IsUnboxingStub()) || (ftn->IsDynamicMethod() && !ftn->IsILStub()))) @@ -12183,9 +12401,9 @@ BOOL IsTransparentMethodSafeToSkipVerification(CorJitFlag flags, MethodDesc * ft // failed, then we need to throw an exception whenever we try // to compile a real instantiation -CorJitFlag GetCompileFlagsIfGenericInstantiation( +CORJIT_FLAGS GetCompileFlagsIfGenericInstantiation( CORINFO_METHOD_HANDLE method, - CorJitFlag compileFlags, + CORJIT_FLAGS compileFlags, ICorJitInfo * pCorJitInfo, BOOL * raiseVerificationException, BOOL * unverifiableGenericCode) @@ -12196,7 +12414,7 @@ CorJitFlag GetCompileFlagsIfGenericInstantiation( *unverifiableGenericCode = FALSE; // If we have already decided to skip verification, keep on going. - if (compileFlags & CORJIT_FLG_SKIP_VERIFICATION) + if (compileFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION)) return compileFlags; CorInfoInstantiationVerification ver = pCorJitInfo->isInstantiationOfVerifiedGeneric(method); @@ -12206,13 +12424,14 @@ CorJitFlag GetCompileFlagsIfGenericInstantiation( case INSTVER_NOT_INSTANTIATION: // Non-generic, or open instantiation of a generic type/method if (IsTransparentMethodSafeToSkipVerification(compileFlags, (MethodDesc*)method)) - compileFlags = (CorJitFlag)(compileFlags | CORJIT_FLG_SKIP_VERIFICATION); + compileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION); return compileFlags; case INSTVER_GENERIC_PASSED_VERIFICATION: // If the typical instantiation is verifiable, there is no need // to verify the concrete instantiations - return (CorJitFlag)(compileFlags | CORJIT_FLG_SKIP_VERIFICATION); + compileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION); + return compileFlags; case INSTVER_GENERIC_FAILED_VERIFICATION: @@ -12238,9 +12457,9 @@ CorJitFlag GetCompileFlagsIfGenericInstantiation( // hits unverifiable code. Since we've already hit unverifiable code, // there's no point in starting the JIT, just to have it give up, so we // give up here. - _ASSERTE(compileFlags & CORJIT_FLG_PREJIT); + _ASSERTE(compileFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_PREJIT)); *raiseVerificationException = TRUE; - return (CorJitFlag)-1; // This value will not be used + return CORJIT_FLAGS(); // This value will not be used } #else // FEATURE_PREJIT // Need to have this case here to keep the MAC build happy @@ -12259,17 +12478,18 @@ CorJitFlag GetCompileFlagsIfGenericInstantiation( // branches while compiling the concrete instantiation. Instead, // just throw a VerificationException right away. *raiseVerificationException = TRUE; - return (CorJitFlag)-1; // This value will not be used + return CORJIT_FLAGS(); // This value will not be used } case CORINFO_VERIFICATION_CAN_SKIP: { - return (CorJitFlag)(compileFlags | CORJIT_FLG_SKIP_VERIFICATION); + compileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION); + return compileFlags; } case CORINFO_VERIFICATION_RUNTIME_CHECK: { - // Compile the method without CORJIT_FLG_SKIP_VERIFICATION. + // Compile the method without CORJIT_FLAG_SKIP_VERIFICATION. // The compiler will know to add a call to // CORINFO_HELP_VERIFICATION_RUNTIME_CHECK, and then to skip verification. return compileFlags; @@ -12344,8 +12564,8 @@ BOOL g_fAllowRel32 = TRUE; // Calls to this method that occur to check if inlining can occur on x86, // are OK since they discard the return value of this method. -PCODE UnsafeJitFunction(MethodDesc* ftn, COR_ILMETHOD_DECODER* ILHeader, - DWORD flags, DWORD flags2, ULONG * pSizeOfCode) +PCODE UnsafeJitFunction(MethodDesc* ftn, COR_ILMETHOD_DECODER* ILHeader, CORJIT_FLAGS flags, + ULONG * pSizeOfCode) { STANDARD_VM_CONTRACT; @@ -12359,9 +12579,9 @@ PCODE UnsafeJitFunction(MethodDesc* ftn, COR_ILMETHOD_DECODER* ILHeader, ftn->GetModule()->GetDomainFile()->IsZapRequired() && PartialNGenStressPercentage() == 0 && #ifdef FEATURE_STACK_SAMPLING - !(flags2 & CORJIT_FLG2_SAMPLING_JIT_BACKGROUND) && + !flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SAMPLING_JIT_BACKGROUND) && #endif - !(flags & CORJIT_FLG_IMPORT_ONLY)) + !flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY)) { StackSString ss(SString::Ascii, "ZapRequire: JIT compiler invoked for "); TypeString::AppendMethodInternal(ss, ftn); @@ -12398,6 +12618,13 @@ PCODE UnsafeJitFunction(MethodDesc* ftn, COR_ILMETHOD_DECODER* ILHeader, EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_EXECUTIONENGINE, W("Failed to load JIT compiler")); #endif // ALLOW_SXS_JIT } + + // If no compatjit wasn't used, but the user (normally a test case) requires that one is used, then fail. + // This is analogous to ZapRequire. + if (!jitMgr->m_fLegacyJitUsed && (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_RequireLegacyJit) == 1)) + { + EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_EXECUTIONENGINE, W("Failed to use legacy JIT compiler with RequireLegacyJit set")); + } #endif // CROSSGEN_COMPILE #ifdef _DEBUG @@ -12444,10 +12671,10 @@ PCODE UnsafeJitFunction(MethodDesc* ftn, COR_ILMETHOD_DECODER* ILHeader, getMethodInfoHelper(ftn, ftnHnd, ILHeader, &methodInfo); // If it's generic then we can only enter through an instantiated md (unless we're just verifying it) - _ASSERTE((flags & CORJIT_FLG_IMPORT_ONLY) != 0 || !ftn->IsGenericMethodDefinition()); + _ASSERTE(flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY) || !ftn->IsGenericMethodDefinition()); // If it's an instance method then it must not be entered from a generic class - _ASSERTE((flags & CORJIT_FLG_IMPORT_ONLY) != 0 || ftn->IsStatic() || + _ASSERTE(flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY) || ftn->IsStatic() || ftn->GetNumGenericClassArgs() == 0 || ftn->HasClassInstantiation()); // method attributes and signature are consistant @@ -12456,7 +12683,7 @@ PCODE UnsafeJitFunction(MethodDesc* ftn, COR_ILMETHOD_DECODER* ILHeader, flags = GetCompileFlags(ftn, flags, &methodInfo); #ifdef _DEBUG - if (!(flags & CORJIT_FLG_SKIP_VERIFICATION)) + if (!flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION)) { SString methodString; if (LoggingOn(LF_VERIFIER, LL_INFO100)) @@ -12488,10 +12715,10 @@ PCODE UnsafeJitFunction(MethodDesc* ftn, COR_ILMETHOD_DECODER* ILHeader, for (;;) { #ifndef CROSSGEN_COMPILE - CEEJitInfo jitInfo(ftn, ILHeader, jitMgr, (flags & CORJIT_FLG_IMPORT_ONLY) != 0); + CEEJitInfo jitInfo(ftn, ILHeader, jitMgr, flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY)); #else // This path should be only ever used for verification in crossgen and so we should not need EEJitManager - _ASSERTE((flags & CORJIT_FLG_IMPORT_ONLY) != 0); + _ASSERTE(flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY)); CEEInfo jitInfo(ftn, true); EEJitManager *jitMgr = NULL; #endif @@ -12550,7 +12777,7 @@ PCODE UnsafeJitFunction(MethodDesc* ftn, COR_ILMETHOD_DECODER* ILHeader, flags = GetCompileFlagsIfGenericInstantiation( ftnHnd, - (CorJitFlag)flags, + flags, &jitInfo, &raiseVerificationException, &unverifiableGenericCode); @@ -12571,7 +12798,7 @@ PCODE UnsafeJitFunction(MethodDesc* ftn, COR_ILMETHOD_DECODER* ILHeader, #ifdef PERF_TRACK_METHOD_JITTIMES //Because we're not calling QPC enough. I'm not going to track times if we're just importing. LARGE_INTEGER methodJitTimeStart = {0}; - if (!(flags & CORJIT_FLG_IMPORT_ONLY)) + if (!flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY)) QueryPerformanceCounter (&methodJitTimeStart); #endif @@ -12591,7 +12818,6 @@ PCODE UnsafeJitFunction(MethodDesc* ftn, COR_ILMETHOD_DECODER* ILHeader, &jitInfo, &methodInfo, flags, - flags2, &nativeEntry, &sizeOfCode, (MethodDesc*)ftn); @@ -12622,7 +12848,7 @@ PCODE UnsafeJitFunction(MethodDesc* ftn, COR_ILMETHOD_DECODER* ILHeader, #ifdef PERF_TRACK_METHOD_JITTIMES //store the time in the string buffer. Module name and token are unique enough. Also, do not //capture importing time, just actual compilation time. - if (!(flags & CORJIT_FLG_IMPORT_ONLY)) + if (!flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY)) { LARGE_INTEGER methodJitTimeStop; QueryPerformanceCounter(&methodJitTimeStop); @@ -12653,7 +12879,7 @@ PCODE UnsafeJitFunction(MethodDesc* ftn, COR_ILMETHOD_DECODER* ILHeader, ThrowExceptionForJit(res); } - if (flags & CORJIT_FLG_IMPORT_ONLY) + if (flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY)) { // The method must been processed by the verifier. Note that it may // either have been marked as verifiable or unverifiable. @@ -13372,19 +13598,19 @@ BOOL LoadDynamicInfoEntry(Module *currentModule, break; case READYTORUN_HELPER_DelayLoad_MethodCall: - result = (size_t)DelayLoad_MethodCall; + result = (size_t)GetEEFuncEntryPoint(DelayLoad_MethodCall); break; case READYTORUN_HELPER_DelayLoad_Helper: - result = (size_t)DelayLoad_Helper; + result = (size_t)GetEEFuncEntryPoint(DelayLoad_Helper); break; case READYTORUN_HELPER_DelayLoad_Helper_Obj: - result = (size_t)DelayLoad_Helper_Obj; + result = (size_t)GetEEFuncEntryPoint(DelayLoad_Helper_Obj); break; case READYTORUN_HELPER_DelayLoad_Helper_ObjObj: - result = (size_t)DelayLoad_Helper_ObjObj; + result = (size_t)GetEEFuncEntryPoint(DelayLoad_Helper_ObjObj); break; default: diff --git a/src/vm/jitinterface.h b/src/vm/jitinterface.h index 03983f2..ee13b9c 100644 --- a/src/vm/jitinterface.h +++ b/src/vm/jitinterface.h @@ -28,6 +28,9 @@ class FieldDesc; enum RuntimeExceptionKind; class AwareLock; class PtrArray; +#if defined(FEATURE_GDBJIT) +class CalledMethod; +#endif #include "genericdict.h" @@ -51,7 +54,7 @@ void InitJITHelpers1(); void InitJITHelpers2(); PCODE UnsafeJitFunction(MethodDesc* ftn, COR_ILMETHOD_DECODER* header, - DWORD flags, DWORD flags2, ULONG* sizeOfCode = NULL); + CORJIT_FLAGS flags, ULONG* sizeOfCode = NULL); void getMethodInfoHelper(MethodDesc * ftn, CORINFO_METHOD_HANDLE ftnHnd, @@ -644,7 +647,7 @@ public: ); // Returns that compilation flags that are shared between JIT and NGen - static DWORD GetBaseCompileFlags(MethodDesc * ftn); + static CORJIT_FLAGS GetBaseCompileFlags(MethodDesc * ftn); // Resolve metadata token into runtime method handles. void resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken); @@ -1090,6 +1093,9 @@ public: m_pThread(GetThread()), m_hMethodForSecurity_Key(NULL), m_pMethodForSecurity_Value(NULL) +#if defined(FEATURE_GDBJIT) + , m_pCalledMethods(NULL) +#endif { LIMITED_METHOD_CONTRACT; } @@ -1151,6 +1157,10 @@ public: MethodDesc * pTemplateMD /* for method-based slots */, CORINFO_LOOKUP *pResultLookup); +#if defined(FEATURE_GDBJIT) + CalledMethod * GetCalledMethods() { return m_pCalledMethods; } +#endif + protected: // NGen provides its own modifications to EE-JIT interface. From technical reason it cannot simply inherit // from code:CEEInfo class (because it has dependencies on VM that NGen does not want). @@ -1174,6 +1184,10 @@ protected: CORINFO_METHOD_HANDLE m_hMethodForSecurity_Key; MethodDesc * m_pMethodForSecurity_Value; +#if defined(FEATURE_GDBJIT) + CalledMethod * m_pCalledMethods; +#endif + // Tracking of module activation dependencies. We have two flavors: // - Fast one that gathers generic arguments from EE handles, but does not work inside generic context. // - Slow one that operates on typespec and methodspecs from metadata. @@ -1641,7 +1655,7 @@ struct VirtualFunctionPointerArgs FCDECL2(CORINFO_MethodPtr, JIT_VirtualFunctionPointer_Dynamic, Object * objectUNSAFE, VirtualFunctionPointerArgs * pArgs); -typedef TADDR (F_CALL_CONV * FnStaticBaseHelper)(TADDR arg0, TADDR arg1); +typedef HCCALL2_PTR(TADDR, FnStaticBaseHelper, TADDR arg0, TADDR arg1); struct StaticFieldAddressArgs { @@ -1677,8 +1691,8 @@ public: static FCDECL3(void, UnsafeSetArrayElement, PtrArray* pPtrArray, INT32 index, Object* object); }; -DWORD GetDebuggerCompileFlags(Module* pModule, DWORD flags); +CORJIT_FLAGS GetDebuggerCompileFlags(Module* pModule, CORJIT_FLAGS flags); -bool TrackAllocationsEnabled(); +bool __stdcall TrackAllocationsEnabled(); #endif // JITINTERFACE_H diff --git a/src/vm/jitinterfacegen.cpp b/src/vm/jitinterfacegen.cpp index 0a90dc3..f8a95bb 100644 --- a/src/vm/jitinterfacegen.cpp +++ b/src/vm/jitinterfacegen.cpp @@ -221,7 +221,7 @@ void InitJITHelpers1() )) { // if (multi-proc || server GC) - if (GCHeap::UseAllocationContexts()) + if (GCHeapUtilities::UseAllocationContexts()) { #ifdef FEATURE_IMPLICIT_TLS SetJitHelperFunction(CORINFO_HELP_NEWSFAST, JIT_NewS_MP_FastPortable); diff --git a/src/vm/marshalnative.cpp b/src/vm/marshalnative.cpp index 48911b7..5f05fa2 100644 --- a/src/vm/marshalnative.cpp +++ b/src/vm/marshalnative.cpp @@ -27,7 +27,7 @@ #include "log.h" #include "fieldmarshaler.h" #include "cgensys.h" -#include "gc.h" +#include "gcheaputilities.h" #include "security.h" #include "dbginterface.h" #include "objecthandle.h" diff --git a/src/vm/marshalnative.h b/src/vm/marshalnative.h index 4f6ac85..cff3f7e 100644 --- a/src/vm/marshalnative.h +++ b/src/vm/marshalnative.h @@ -229,7 +229,7 @@ public: static FCDECL2(void, ChangeWrapperHandleStrength, Object* orefUNSAFE, CLR_BOOL fIsWeak); static FCDECL2(void, InitializeWrapperForWinRT, Object *unsafe_pThis, IUnknown **ppUnk); static FCDECL2(void, InitializeManagedWinRTFactoryObject, Object *unsafe_pThis, ReflectClassBaseObject *unsafe_pType); - static FCDECL1(Object *, MarshalNative::GetNativeActivationFactory, ReflectClassBaseObject *unsafe_pType); + static FCDECL1(Object *, GetNativeActivationFactory, ReflectClassBaseObject *unsafe_pType); static void QCALLTYPE GetInspectableIIDs(QCall::ObjectHandleOnStack hobj, QCall::ObjectHandleOnStack retArrayGuids); static void QCALLTYPE GetCachedWinRTTypes(QCall::ObjectHandleOnStack hadObj, int * epoch, QCall::ObjectHandleOnStack retArrayMT); static void QCALLTYPE GetCachedWinRTTypeByIID(QCall::ObjectHandleOnStack hadObj, GUID iid, void * * ppMT); diff --git a/src/vm/mdaassistants.cpp b/src/vm/mdaassistants.cpp index cc598c0..e52e8ff 100644 --- a/src/vm/mdaassistants.cpp +++ b/src/vm/mdaassistants.cpp @@ -137,7 +137,7 @@ void TriggerGCForMDAInternal() EX_TRY { - GCHeap::GetGCHeap()->GarbageCollect(); + GCHeapUtilities::GetGCHeap()->GarbageCollect(); #ifdef FEATURE_SYNCHRONIZATIONCONTEXT_WAIT // @@ -868,7 +868,7 @@ LPVOID MdaInvalidOverlappedToPinvoke::CheckOverlappedPointer(UINT index, LPVOID { GCX_COOP(); - GCHeap *pHeap = GCHeap::GetGCHeap(); + IGCHeap *pHeap = GCHeapUtilities::GetGCHeap(); fHeapPointer = pHeap->IsHeapPointer(pOverlapped); } diff --git a/src/vm/memberload.cpp b/src/vm/memberload.cpp index 8b7b2ce..1b24300 100644 --- a/src/vm/memberload.cpp +++ b/src/vm/memberload.cpp @@ -30,7 +30,7 @@ #include "log.h" #include "fieldmarshaler.h" #include "cgensys.h" -#include "gc.h" +#include "gcheaputilities.h" #include "security.h" #include "dbginterface.h" #include "comdelegate.h" diff --git a/src/vm/message.cpp b/src/vm/message.cpp index fa0370d..093f9a2 100644 --- a/src/vm/message.cpp +++ b/src/vm/message.cpp @@ -249,7 +249,7 @@ void CMessage::GetObjectFromStack(OBJECTREF* ppDest, PVOID val, const CorElement _ASSERTE(ty.GetMethodTable()->IsValueType() || ty.GetMethodTable()->IsEnum()); - _ASSERTE(!GCHeap::GetGCHeap()->IsHeapPointer((BYTE *) ppDest) || + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsHeapPointer((BYTE *) ppDest) || !"(pDest) can not point to GC Heap"); MethodTable* pMT = ty.GetMethodTable(); diff --git a/src/vm/metasig.h b/src/vm/metasig.h index 5bf2903..a840461 100644 --- a/src/vm/metasig.h +++ b/src/vm/metasig.h @@ -302,7 +302,10 @@ DEFINE_METASIG(SM(Int_IntPtr_RetObj, i I, j)) DEFINE_METASIG(SM(IntPtr_IntPtr_Int_RetVoid, I I i, v)) DEFINE_METASIG_T(SM(Exception_RetInt, C(EXCEPTION), i)) +#ifdef FEATURE_REMOTING DEFINE_METASIG_T(SM(ContextBoundObject_RetObj, C(CONTEXT_BOUND_OBJECT), j)) +#endif + DEFINE_METASIG_T(SM(PMS_PMS_RetInt, C(PERMISSION_SET) C(PERMISSION_SET), i)) DEFINE_METASIG(SM(IntPtr_RetVoid, I, v)) diff --git a/src/vm/method.cpp b/src/vm/method.cpp index 70714b7..7afe0e9 100644 --- a/src/vm/method.cpp +++ b/src/vm/method.cpp @@ -1078,7 +1078,7 @@ BOOL MethodDesc::IsVerifiable() #endif // _VER_EE_VERIFICATION_ENABLED } - UnsafeJitFunction(this, pHeader, CORJIT_FLG_IMPORT_ONLY, 0); + UnsafeJitFunction(this, pHeader, CORJIT_FLAGS(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY)); _ASSERTE(IsVerified()); return (IsVerified() && (m_wFlags & mdcVerifiable)); @@ -3249,6 +3249,7 @@ bool MethodDesc::CanSkipDoPrestub ( return false; } +#ifdef FEATURE_CER // Can't hard bind to a method which contains one or more Constrained Execution Region roots (we need to force the prestub to // execute for such methods). if (ContainsPrePreparableCerRoot(this)) @@ -3256,6 +3257,7 @@ bool MethodDesc::CanSkipDoPrestub ( *pReason = CORINFO_INDIRECT_CALL_CER; return false; } +#endif // FEATURE_CER // Check whether our methoddesc needs restore if (NeedsRestore(GetAppDomain()->ToCompilationDomain()->GetTargetImage(), TRUE)) diff --git a/src/vm/method.hpp b/src/vm/method.hpp index 3cdd794..499112d 100644 --- a/src/vm/method.hpp +++ b/src/vm/method.hpp @@ -1649,7 +1649,7 @@ public: PCODE DoPrestub(MethodTable *pDispatchingMT); - PCODE MakeJitWorker(COR_ILMETHOD_DECODER* ILHeader, DWORD flags, DWORD flags2); + PCODE MakeJitWorker(COR_ILMETHOD_DECODER* ILHeader, CORJIT_FLAGS flags); VOID GetMethodInfo(SString &namespaceOrClassName, SString &methodName, SString &methodSignature); VOID GetMethodInfoWithNewSig(SString &namespaceOrClassName, SString &methodName, SString &methodSignature); @@ -3596,6 +3596,22 @@ inline BOOL MethodDesc::HasMethodInstantiation() const return mcInstantiated == GetClassification() && AsInstantiatedMethodDesc()->IMD_HasMethodInstantiation(); } +#if defined(FEATURE_GDBJIT) +class CalledMethod +{ +private: + MethodDesc * m_pMD; + void * m_CallAddr; + CalledMethod * m_pNext; +public: + CalledMethod(MethodDesc *pMD, void * addr, CalledMethod * next) : m_pMD(pMD), m_CallAddr(addr), m_pNext(next) {} + ~CalledMethod() {} + MethodDesc * GetMethodDesc() { return m_pMD; } + void * GetCallAddr() { return m_CallAddr; } + CalledMethod * GetNext() { return m_pNext; } +}; +#endif + #include "method.inl" #endif // !_METHOD_H diff --git a/src/vm/methodtable.cpp b/src/vm/methodtable.cpp index bf86382..52a2ce4 100644 --- a/src/vm/methodtable.cpp +++ b/src/vm/methodtable.cpp @@ -33,7 +33,7 @@ #include "log.h" #include "fieldmarshaler.h" #include "cgensys.h" -#include "gc.h" +#include "gcheaputilities.h" #include "security.h" #include "dbginterface.h" #include "comdelegate.h" @@ -9804,11 +9804,11 @@ BOOL MethodTable::Validate() } DWORD dwLastVerifiedGCCnt = m_pWriteableData->m_dwLastVerifedGCCnt; - // Here we used to assert that (dwLastVerifiedGCCnt <= GCHeap::GetGCHeap()->GetGcCount()) but + // Here we used to assert that (dwLastVerifiedGCCnt <= GCHeapUtilities::GetGCHeap()->GetGcCount()) but // this is no longer true because with background gc. Since the purpose of having // m_dwLastVerifedGCCnt is just to only verify the same method table once for each GC // I am getting rid of the assert. - if (g_pConfig->FastGCStressLevel () > 1 && dwLastVerifiedGCCnt == GCHeap::GetGCHeap()->GetGcCount()) + if (g_pConfig->FastGCStressLevel () > 1 && dwLastVerifiedGCCnt == GCHeapUtilities::GetGCHeap()->GetGcCount()) return TRUE; #endif //_DEBUG @@ -9835,7 +9835,7 @@ BOOL MethodTable::Validate() // It is not a fatal error to fail the update the counter. We will run slower and retry next time, // but the system will function properly. if (EnsureWritablePagesNoThrow(m_pWriteableData, sizeof(MethodTableWriteableData))) - m_pWriteableData->m_dwLastVerifedGCCnt = GCHeap::GetGCHeap()->GetGcCount(); + m_pWriteableData->m_dwLastVerifedGCCnt = GCHeapUtilities::GetGCHeap()->GetGcCount(); #endif //_DEBUG return TRUE; diff --git a/src/vm/methodtablebuilder.cpp b/src/vm/methodtablebuilder.cpp index 70c0e3b..682268e 100644 --- a/src/vm/methodtablebuilder.cpp +++ b/src/vm/methodtablebuilder.cpp @@ -191,6 +191,7 @@ MethodTableBuilder::CreateClass( Module *pModule, pEEClass->GetSecurityProperties()->SetFlags(dwSecFlags, dwNullDeclFlags); } +#ifdef FEATURE_CER // Cache class level reliability contract info. DWORD dwReliabilityContract = ::GetReliabilityContract(pInternalImport, cl); if (dwReliabilityContract != RC_NULL) @@ -201,6 +202,7 @@ MethodTableBuilder::CreateClass( Module *pModule, pEEClass->SetReliabilityContract(dwReliabilityContract); } +#endif // FEATURE_CER if (fHasLayout) pEEClass->SetHasLayout(); @@ -1218,7 +1220,7 @@ BOOL MethodTableBuilder::CheckIfSIMDAndUpdateSize() { STANDARD_VM_CONTRACT; -#ifdef _TARGET_AMD64_ +#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) if (!GetAssembly()->IsSIMDVectorAssembly()) return false; @@ -1245,8 +1247,8 @@ BOOL MethodTableBuilder::CheckIfSIMDAndUpdateSize() EEJitManager *jitMgr = ExecutionManager::GetEEJitManager(); if (jitMgr->LoadJIT()) { - DWORD cpuCompileFlags = jitMgr->GetCPUCompileFlags(); - if ((cpuCompileFlags & CORJIT_FLG_FEATURE_SIMD) != 0) + CORJIT_FLAGS cpuCompileFlags = jitMgr->GetCPUCompileFlags(); + if (cpuCompileFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_FEATURE_SIMD)) { unsigned intrinsicSIMDVectorLength = jitMgr->m_jit->getMaxIntrinsicSIMDVectorLength(cpuCompileFlags); if (intrinsicSIMDVectorLength != 0) @@ -1262,7 +1264,7 @@ BOOL MethodTableBuilder::CheckIfSIMDAndUpdateSize() } } #endif // !CROSSGEN_COMPILE -#endif // _TARGET_AMD64_ +#endif // defined(_TARGET_X86_) || defined(_TARGET_AMD64_) return false; } @@ -1860,6 +1862,11 @@ MethodTableBuilder::BuildMethodTableThrowing( pMT->SetHasBoxedRegularStatics(); } + if (bmtFP->fIsByRefLikeType) + { + pMT->SetIsByRefLike(); + } + if (IsValueClass()) { if (bmtFP->NumInstanceFieldBytes != totalDeclaredFieldSize || HasOverLayedField()) @@ -4212,14 +4219,12 @@ VOID MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList, goto GOT_ELEMENT_TYPE; } - // There are just few types with code:IsByRefLike set - see code:CheckForSystemTypes. - // Note: None of them will ever have self-referencing static ValueType field (we cannot assert it now because the IsByRefLike - // status for this type has not been initialized yet). + // Inherit IsByRefLike characteristic from fields if (!IsSelfRef(pByValueClass) && pByValueClass->IsByRefLike()) - { // Cannot have embedded valuetypes that contain a field that require stack allocation. - BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil); + { + bmtFP->fIsByRefLikeType = true; } - + if (!IsSelfRef(pByValueClass) && pByValueClass->GetClass()->HasNonPublicFields()) { // If a class has a field of type ValueType with non-public fields in it, // the class must "inherit" this characteristic @@ -10201,15 +10206,27 @@ void MethodTableBuilder::CheckForSystemTypes() MethodTable * pMT = GetHalfBakedMethodTable(); EEClass * pClass = GetHalfBakedClass(); - // We can exit early for generic types - there is just one case to check for. - if (g_pNullableClass != NULL && bmtGenerics->HasInstantiation()) + // We can exit early for generic types - there are just a few cases to check for. + if (bmtGenerics->HasInstantiation() && g_pNullableClass != NULL) { +#ifdef FEATURE_SPAN_OF_T + _ASSERTE(g_pByReferenceClass != NULL); + _ASSERTE(g_pByReferenceClass->IsByRefLike()); + + if (GetCl() == g_pByReferenceClass->GetCl()) + { + pMT->SetIsByRefLike(); + return; + } +#endif + _ASSERTE(g_pNullableClass->IsNullable()); // Pre-compute whether the class is a Nullable so that code:Nullable::IsNullableType is efficient // This is useful to the performance of boxing/unboxing a Nullable if (GetCl() == g_pNullableClass->GetCl()) pMT->SetIsNullable(); + return; } @@ -10257,6 +10274,12 @@ void MethodTableBuilder::CheckForSystemTypes() { pMT->SetIsNullable(); } +#ifdef FEATURE_SPAN_OF_T + else if (strcmp(name, g_ByReferenceName) == 0) + { + pMT->SetIsByRefLike(); + } +#endif else if (strcmp(name, g_ArgIteratorName) == 0) { // Mark the special types that have embeded stack poitners in them diff --git a/src/vm/methodtablebuilder.h b/src/vm/methodtablebuilder.h index 1e40ea9..1cf7149 100644 --- a/src/vm/methodtablebuilder.h +++ b/src/vm/methodtablebuilder.h @@ -2081,6 +2081,7 @@ private: DWORD NumGCPointerSeries; DWORD NumInstanceFieldBytes; + bool fIsByRefLikeType; bool fHasFixedAddressValueTypes; bool fHasSelfReferencingStaticValueTypeField_WithRVA; diff --git a/src/vm/microsoft.comservices_i.c b/src/vm/microsoft.comservices_i.c index d70bc8c..f31a92f 100644 --- a/src/vm/microsoft.comservices_i.c +++ b/src/vm/microsoft.comservices_i.c @@ -23,14 +23,13 @@ #if !defined(_M_IA64) && !defined(_M_AXP64) +#include +#include + #ifdef __cplusplus extern "C"{ #endif - -#include -#include - #ifdef _MIDL_USE_GUIDDEF_ #ifndef INITGUID @@ -109,14 +108,13 @@ MIDL_DEFINE_GUID(CLSID, CLSID_RegistrationHelperTx,0x89A86E7B,0xC229,0x4008,0x9B #if defined(_M_IA64) || defined(_M_AXP64) +#include +#include + #ifdef __cplusplus extern "C"{ #endif - -#include -#include - #ifdef _MIDL_USE_GUIDDEF_ #ifndef INITGUID @@ -153,7 +151,7 @@ typedef IID CLSID; #define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} -#endif !_MIDL_USE_GUIDDEF_ +#endif // !_MIDL_USE_GUIDDEF_ MIDL_DEFINE_GUID(IID, LIBID_Microsoft_ComServices,0xD7F68C66,0x3833,0x3832,0xB6,0xD0,0xB7,0x96,0xBB,0x7D,0x2D,0xFF); diff --git a/src/vm/mlinfo.cpp b/src/vm/mlinfo.cpp index ab25452..74bd536 100644 --- a/src/vm/mlinfo.cpp +++ b/src/vm/mlinfo.cpp @@ -4865,6 +4865,8 @@ void ArrayMarshalInfo::InitForHiddenLengthArray(TypeHandle thElement) { STANDARD_VM_CONTRACT; + MethodTable *pMT = NULL; + // WinRT supports arrays of any WinRT-legal types if (thElement.IsArray()) { @@ -4877,7 +4879,7 @@ void ArrayMarshalInfo::InitForHiddenLengthArray(TypeHandle thElement) m_thElement = thElement; - MethodTable *pMT = thElement.GetMethodTable(); + pMT = thElement.GetMethodTable(); if (pMT->IsString()) { m_vtElement = VTHACK_HSTRING; diff --git a/src/vm/mscorlib.h b/src/vm/mscorlib.h index 291c6ab..20d658b 100644 --- a/src/vm/mscorlib.h +++ b/src/vm/mscorlib.h @@ -462,8 +462,9 @@ DEFINE_METHOD(CONTEXT, CALLBACK, DoCallBackFromEE, DEFINE_METHOD(CONTEXT, RESERVE_SLOT, ReserveSlot, IM_RetInt) #endif +#ifdef FEATURE_REMOTING DEFINE_CLASS(CONTEXT_BOUND_OBJECT, System, ContextBoundObject) - +#endif #ifdef FEATURE_CRYPTO DEFINE_CLASS(CSP_PARAMETERS, Cryptography, CspParameters) @@ -592,9 +593,7 @@ DEFINE_FIELD_U(textInfo, CultureInfoBaseObject, textInfo) DEFINE_FIELD_U(numInfo, CultureInfoBaseObject, numInfo) DEFINE_FIELD_U(dateTimeInfo, CultureInfoBaseObject, dateTimeInfo) DEFINE_FIELD_U(calendar, CultureInfoBaseObject, calendar) -#ifndef FEATURE_CORECLR DEFINE_FIELD_U(m_consoleFallbackCulture, CultureInfoBaseObject, m_consoleFallbackCulture) -#endif // FEATURE_CORECLR DEFINE_FIELD_U(m_name, CultureInfoBaseObject, m_name) DEFINE_FIELD_U(m_nonSortName, CultureInfoBaseObject, m_nonSortName) DEFINE_FIELD_U(m_sortName, CultureInfoBaseObject, m_sortName) @@ -772,6 +771,7 @@ DEFINE_CLASS(I_RT_FIELD_INFO, System, IRuntimeFieldInfo) DEFINE_CLASS(FIELD_INFO, Reflection, FieldInfo) +#ifndef FEATURE_CORECLR DEFINE_CLASS_U(IO, FileStreamAsyncResult, AsyncResultBase) DEFINE_FIELD_U(_userCallback, AsyncResultBase, _userCallback) DEFINE_FIELD_U(_userStateObject, AsyncResultBase, _userStateObject) @@ -786,6 +786,7 @@ DEFINE_FIELD_U(_isWrite, AsyncResultBase, _isWrite) DEFINE_FIELD_U(_isComplete, AsyncResultBase, _isComplete) DEFINE_FIELD_U(_completedSynchronously, AsyncResultBase, _completedSynchronously) DEFINE_CLASS(FILESTREAM_ASYNCRESULT, IO, FileStreamAsyncResult) +#endif // !FEATURE_CORECLR DEFINE_CLASS_U(Security, FrameSecurityDescriptor, FrameSecurityDescriptorBaseObject) DEFINE_FIELD_U(m_assertions, FrameSecurityDescriptorBaseObject, m_assertions) @@ -1051,6 +1052,12 @@ DEFINE_FIELD(NULL, VALUE, Value) DEFINE_CLASS(NULLABLE, System, Nullable`1) +#ifdef FEATURE_SPAN_OF_T +DEFINE_CLASS(BYREFERENCE, System, ByReference`1) +DEFINE_CLASS(SPAN, System, Span`1) +DEFINE_CLASS(READONLY_SPAN, System, ReadOnlySpan`1) +#endif + // Keep this in sync with System.Globalization.NumberFormatInfo DEFINE_CLASS_U(Globalization, NumberFormatInfo, NumberFormatInfo) DEFINE_FIELD_U(numberGroupSizes, NumberFormatInfo, cNumberGroup) @@ -1085,9 +1092,7 @@ DEFINE_FIELD_U(numberNegativePattern, NumberFormatInfo, cNegativeNumberFormat DEFINE_FIELD_U(percentPositivePattern, NumberFormatInfo, cPositivePercentFormat) DEFINE_FIELD_U(percentNegativePattern, NumberFormatInfo, cNegativePercentFormat) DEFINE_FIELD_U(percentDecimalDigits, NumberFormatInfo, cPercentDecimals) -#ifndef FEATURE_COREFX_GLOBALIZATION DEFINE_FIELD_U(digitSubstitution, NumberFormatInfo, iDigitSubstitution) -#endif DEFINE_FIELD_U(isReadOnly, NumberFormatInfo, bIsReadOnly) #ifndef FEATURE_COREFX_GLOBALIZATION DEFINE_FIELD_U(m_useUserOverride, NumberFormatInfo, bUseUserOverride) @@ -1338,6 +1343,20 @@ DEFINE_METHOD(JIT_HELPERS, UNSAFE_ENUM_CAST, UnsafeEnumCast, NoSi DEFINE_METHOD(JIT_HELPERS, UNSAFE_ENUM_CAST_LONG, UnsafeEnumCastLong, NoSig) DEFINE_METHOD(JIT_HELPERS, UNSAFE_CAST_TO_STACKPTR,UnsafeCastToStackPointer, NoSig) #endif // _DEBUG +#ifdef FEATURE_SPAN_OF_T +DEFINE_METHOD(JIT_HELPERS, BYREF_LESSTHAN, ByRefLessThan, NoSig) +DEFINE_METHOD(JIT_HELPERS, GET_ARRAY_DATA, GetArrayData, NoSig) +DEFINE_METHOD(JIT_HELPERS, CONTAINSREFERENCES, ContainsReferences, NoSig) +#endif + +#ifdef FEATURE_SPAN_OF_T +DEFINE_CLASS(UNSAFE, CompilerServices, Unsafe) +DEFINE_METHOD(UNSAFE, AS_POINTER, AsPointer, NoSig) +DEFINE_METHOD(UNSAFE, SIZEOF, SizeOf, NoSig) +DEFINE_METHOD(UNSAFE, BYREF_AS, As, NoSig) +DEFINE_METHOD(UNSAFE, BYREF_ADD, Add, NoSig) +DEFINE_METHOD(UNSAFE, BYREF_ARE_SAME, AreSame, NoSig) +#endif DEFINE_CLASS(INTERLOCKED, Threading, Interlocked) DEFINE_METHOD(INTERLOCKED, COMPARE_EXCHANGE_T, CompareExchange, GM_RefT_T_T_RetT) @@ -1346,6 +1365,11 @@ DEFINE_METHOD(INTERLOCKED, COMPARE_EXCHANGE_OBJECT,CompareExchange, SM_ DEFINE_CLASS(PINNING_HELPER, CompilerServices, PinningHelper) DEFINE_FIELD(PINNING_HELPER, M_DATA, m_data) +#ifdef FEATURE_SPAN_OF_T +DEFINE_CLASS(ARRAY_PINNING_HELPER, CompilerServices, ArrayPinningHelper) +DEFINE_FIELD(ARRAY_PINNING_HELPER, M_ARRAY_DATA, m_arrayData) +#endif + DEFINE_CLASS(RUNTIME_WRAPPED_EXCEPTION, CompilerServices, RuntimeWrappedException) DEFINE_METHOD(RUNTIME_WRAPPED_EXCEPTION, OBJ_CTOR, .ctor, IM_Obj_RetVoid) DEFINE_FIELD(RUNTIME_WRAPPED_EXCEPTION, WRAPPED_EXCEPTION, m_wrappedException) @@ -1370,9 +1394,7 @@ DEFINE_CLASS(SAFE_PEFILE_HANDLE, SafeHandles, SafePEFileHandle) DEFINE_CLASS(SAFE_TOKENHANDLE, SafeHandles, SafeAccessTokenHandle) #endif -#ifndef FEATURE_CORECLR DEFINE_CLASS(SAFE_TYPENAMEPARSER_HANDLE, System, SafeTypeNameParserHandle) -#endif //!FEATURE_CORECLR #ifdef FEATURE_COMPRESSEDSTACK DEFINE_CLASS(SAFE_CSHANDLE, Threading, SafeCompressedStackHandle) diff --git a/src/vm/multicorejitplayer.cpp b/src/vm/multicorejitplayer.cpp index 0c69fdc..7d13bbc 100644 --- a/src/vm/multicorejitplayer.cpp +++ b/src/vm/multicorejitplayer.cpp @@ -556,7 +556,7 @@ bool MulticoreJitProfilePlayer::CompileMethodDesc(Module * pModule, MethodDesc * #endif // MakeJitWorker calls back to MulticoreJitCodeStorage::StoreMethodCode under MethodDesc lock - pMD->MakeJitWorker(& header, CORJIT_FLG_MCJIT_BACKGROUND, 0); + pMD->MakeJitWorker(& header, CORJIT_FLAGS(CORJIT_FLAGS::CORJIT_FLAG_MCJIT_BACKGROUND)); return true; } diff --git a/src/vm/nativeoverlapped.cpp b/src/vm/nativeoverlapped.cpp index 2e253f3..d0afbb6 100644 --- a/src/vm/nativeoverlapped.cpp +++ b/src/vm/nativeoverlapped.cpp @@ -35,14 +35,14 @@ FCIMPL3(void, CheckVMForIOPacket, LPOVERLAPPED* lpOverlapped, DWORD* errorCode, { FCALL_CONTRACT; -#ifndef FEATURE_PAL +#ifndef FEATURE_PAL Thread *pThread = GetThread(); DWORD adid = pThread->GetDomain()->GetId().m_dwId; size_t key=0; - _ASSERTE(pThread); + _ASSERTE(pThread); - //Poll and wait if GC is in progress, to avoid blocking GC for too long. + //Poll and wait if GC is in progress, to avoid blocking GC for too long. FC_GC_POLL(); *lpOverlapped = ThreadpoolMgr::CompletionPortDispatchWorkWithinAppDomain(pThread, errorCode, numBytes, &key, adid); @@ -59,13 +59,15 @@ FCIMPL3(void, CheckVMForIOPacket, LPOVERLAPPED* lpOverlapped, DWORD* errorCode, if(overlapped->m_iocb == NULL) { // no user delegate to callback - _ASSERTE((overlapped->m_iocbHelper == NULL) || !"This is benign, but should be optimized"); + _ASSERTE((overlapped->m_iocbHelper == NULL) || !"This is benign, but should be optimized"); +#ifndef FEATURE_CORECLR if (g_pAsyncFileStream_AsyncResultClass) { SetAsyncResultProperties(overlapped, *errorCode, *numBytes); - } - else + } + else +#endif // !FEATURE_CORECLR { //We're not initialized yet, go back to the Vm, and process the packet there. ThreadpoolMgr::StoreOverlappedInfoInThread(pThread, *errorCode, *numBytes, key, *lpOverlapped); @@ -75,7 +77,7 @@ FCIMPL3(void, CheckVMForIOPacket, LPOVERLAPPED* lpOverlapped, DWORD* errorCode, return; } else - { + { if(!pThread->IsRealThreadPoolResetNeeded()) { pThread->ResetManagedThreadObjectInCoopMode(ThreadNative::PRIORITY_NORMAL); @@ -84,7 +86,7 @@ FCIMPL3(void, CheckVMForIOPacket, LPOVERLAPPED* lpOverlapped, DWORD* errorCode, { //We may have to create a CP thread, go back to the Vm, and process the packet there. ThreadpoolMgr::StoreOverlappedInfoInThread(pThread, *errorCode, *numBytes, key, *lpOverlapped); - *lpOverlapped = NULL; + *lpOverlapped = NULL; } } else @@ -93,7 +95,7 @@ FCIMPL3(void, CheckVMForIOPacket, LPOVERLAPPED* lpOverlapped, DWORD* errorCode, //and process the packet there. ThreadpoolMgr::StoreOverlappedInfoInThread(pThread, *errorCode, *numBytes, key, *lpOverlapped); - *lpOverlapped = NULL; + *lpOverlapped = NULL; } } @@ -105,8 +107,8 @@ FCIMPL3(void, CheckVMForIOPacket, LPOVERLAPPED* lpOverlapped, DWORD* errorCode, *lpOverlapped = NULL; #endif // !FEATURE_PAL - return; -} + return; +} FCIMPLEND FCIMPL1(void*, AllocateNativeOverlapped, OverlappedDataObject* overlappedUNSAFE) diff --git a/src/vm/nativeoverlapped.h b/src/vm/nativeoverlapped.h index 854090c..0c0693d 100644 --- a/src/vm/nativeoverlapped.h +++ b/src/vm/nativeoverlapped.h @@ -22,6 +22,7 @@ class OverlappedDataObject : public Object { public: ASYNCRESULTREF m_asyncResult; + OBJECTREF m_iocb; OBJECTREF m_iocbHelper; OBJECTREF m_overlapped; @@ -62,7 +63,7 @@ public: STATIC_CONTRACT_SO_TOLERANT; _ASSERTE (nativeOverlapped != NULL); - _ASSERTE (GCHeap::GetGCHeap()->IsHeapPointer((BYTE *) nativeOverlapped)); + _ASSERTE (GCHeapUtilities::GetGCHeap()->IsHeapPointer((BYTE *) nativeOverlapped)); return (OverlappedDataObject*)((BYTE*)nativeOverlapped - offsetof(OverlappedDataObject, Internal)); } diff --git a/src/vm/object.cpp b/src/vm/object.cpp index 7c47e26..531c001 100644 --- a/src/vm/object.cpp +++ b/src/vm/object.cpp @@ -17,7 +17,7 @@ #include "threads.h" #include "excep.h" #include "eeconfig.h" -#include "gc.h" +#include "gcheaputilities.h" #ifdef FEATURE_REMOTING #include "remoting.h" #endif @@ -243,7 +243,7 @@ TypeHandle Object::GetGCSafeTypeHandleIfPossible() const // // where MyRefType2's module was unloaded by the time the GC occurred. In at least // one case, the GC was caused by the AD unload itself (AppDomain::Unload -> - // AppDomain::Exit -> GCInterface::AddMemoryPressure -> WKS::GCHeap::GarbageCollect). + // AppDomain::Exit -> GCInterface::AddMemoryPressure -> WKS::GCHeapUtilities::GarbageCollect). // // To protect against all scenarios, verify that // @@ -1764,9 +1764,9 @@ VOID Object::ValidateInner(BOOL bDeep, BOOL bVerifyNextHeader, BOOL bVerifySyncB BOOL bSmallObjectHeapPtr = FALSE, bLargeObjectHeapPtr = FALSE; if (!noRangeChecks) { - bSmallObjectHeapPtr = GCHeap::GetGCHeap()->IsHeapPointer(this, TRUE); + bSmallObjectHeapPtr = GCHeapUtilities::GetGCHeap()->IsHeapPointer(this, TRUE); if (!bSmallObjectHeapPtr) - bLargeObjectHeapPtr = GCHeap::GetGCHeap()->IsHeapPointer(this); + bLargeObjectHeapPtr = GCHeapUtilities::GetGCHeap()->IsHeapPointer(this); CHECK_AND_TEAR_DOWN(bSmallObjectHeapPtr || bLargeObjectHeapPtr); } @@ -1781,7 +1781,7 @@ VOID Object::ValidateInner(BOOL bDeep, BOOL bVerifyNextHeader, BOOL bVerifySyncB lastTest = 4; if (bDeep && (g_pConfig->GetHeapVerifyLevel() & EEConfig::HEAPVERIFY_GC)) { - GCHeap::GetGCHeap()->ValidateObjectMember(this); + GCHeapUtilities::GetGCHeap()->ValidateObjectMember(this); } lastTest = 5; @@ -1790,7 +1790,7 @@ VOID Object::ValidateInner(BOOL bDeep, BOOL bVerifyNextHeader, BOOL bVerifySyncB // we skip checking noRangeChecks since if skipping // is enabled bSmallObjectHeapPtr will always be false. if (bSmallObjectHeapPtr) { - CHECK_AND_TEAR_DOWN(!GCHeap::GetGCHeap()->IsObjectInFixedHeap(this)); + CHECK_AND_TEAR_DOWN(!GCHeapUtilities::GetGCHeap()->IsObjectInFixedHeap(this)); } lastTest = 6; @@ -1815,9 +1815,9 @@ VOID Object::ValidateInner(BOOL bDeep, BOOL bVerifyNextHeader, BOOL bVerifySyncB && bVerifyNextHeader && GCScan::GetGcRuntimeStructuresValid () //NextObj could be very slow if concurrent GC is going on - && !(GCHeap::IsGCHeapInitialized() && GCHeap::GetGCHeap ()->IsConcurrentGCInProgress ())) + && !(GCHeapUtilities::IsGCHeapInitialized() && GCHeapUtilities::GetGCHeap ()->IsConcurrentGCInProgress ())) { - Object * nextObj = GCHeap::GetGCHeap ()->NextObj (this); + Object * nextObj = GCHeapUtilities::GetGCHeap ()->NextObj (this); if ((nextObj != NULL) && (nextObj->GetGCSafeMethodTable() != g_pFreeObjectMethodTable)) { @@ -1949,7 +1949,7 @@ STRINGREF StringObject::NewString(const WCHAR *pwsz) // pinning and then later put into a struct and that struct is // then marshalled to managed. // - _ASSERTE(!GCHeap::GetGCHeap()->IsHeapPointer((BYTE *) pwsz) || + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsHeapPointer((BYTE *) pwsz) || !"pwsz can not point to GC Heap"); #endif // 0 @@ -1988,7 +1988,7 @@ STRINGREF StringObject::NewString(const WCHAR *pwsz, int length) { // pinning and then later put into a struct and that struct is // then marshalled to managed. // - _ASSERTE(!GCHeap::GetGCHeap()->IsHeapPointer((BYTE *) pwsz) || + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsHeapPointer((BYTE *) pwsz) || !"pwsz can not point to GC Heap"); #endif // 0 STRINGREF pString = AllocateString(length); @@ -2121,9 +2121,11 @@ STRINGREF __stdcall StringObject::StringInitCharHelper(LPCSTR pszSource, int len if (!pszSource || length == 0) { return StringObject::GetEmptyString(); } +#ifndef FEATURE_PAL else if ((size_t)pszSource < 64000) { COMPlusThrow(kArgumentException, W("Arg_MustBeStringPtrNotAtom")); } +#endif // FEATURE_PAL // Make sure we can read from the pointer. // This is better than try to read from the pointer and catch the access violation exceptions. @@ -2664,7 +2666,7 @@ OBJECTREF::OBJECTREF(const OBJECTREF & objref) // !!! Either way you need to fix the code. _ASSERTE(Thread::IsObjRefValid(&objref)); if ((objref.m_asObj != 0) && - ((GCHeap*)GCHeap::GetGCHeap())->IsHeapPointer( (BYTE*)this )) + ((IGCHeap*)GCHeapUtilities::GetGCHeap())->IsHeapPointer( (BYTE*)this )) { _ASSERTE(!"Write Barrier violation. Must use SetObjectReference() to assign OBJECTREF's into the GC heap!"); } @@ -2718,7 +2720,7 @@ OBJECTREF::OBJECTREF(Object *pObject) DEBUG_ONLY_FUNCTION; if ((pObject != 0) && - ((GCHeap*)GCHeap::GetGCHeap())->IsHeapPointer( (BYTE*)this )) + ((IGCHeap*)GCHeapUtilities::GetGCHeap())->IsHeapPointer( (BYTE*)this )) { _ASSERTE(!"Write Barrier violation. Must use SetObjectReference() to assign OBJECTREF's into the GC heap!"); } @@ -2901,7 +2903,7 @@ OBJECTREF& OBJECTREF::operator=(const OBJECTREF &objref) _ASSERTE(Thread::IsObjRefValid(&objref)); if ((objref.m_asObj != 0) && - ((GCHeap*)GCHeap::GetGCHeap())->IsHeapPointer( (BYTE*)this )) + ((IGCHeap*)GCHeapUtilities::GetGCHeap())->IsHeapPointer( (BYTE*)this )) { _ASSERTE(!"Write Barrier violation. Must use SetObjectReference() to assign OBJECTREF's into the GC heap!"); } @@ -2948,14 +2950,14 @@ void* __cdecl GCSafeMemCpy(void * dest, const void * src, size_t len) { Thread* pThread = GetThread(); - // GCHeap::IsHeapPointer has race when called in preemptive mode. It walks the list of segments + // GCHeapUtilities::IsHeapPointer has race when called in preemptive mode. It walks the list of segments // that can be modified by GC. Do the check below only if it is safe to do so. if (pThread != NULL && pThread->PreemptiveGCDisabled()) { // Note there is memcpyNoGCRefs which will allow you to do a memcpy into the GC // heap if you really know you don't need to call the write barrier - _ASSERTE(!GCHeap::GetGCHeap()->IsHeapPointer((BYTE *) dest) || + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsHeapPointer((BYTE *) dest) || !"using memcpy to copy into the GC heap, use CopyValueClass"); } } diff --git a/src/vm/object.h b/src/vm/object.h index 37560cf..73ecb62 100644 --- a/src/vm/object.h +++ b/src/vm/object.h @@ -1856,9 +1856,7 @@ private: OBJECTREF dateTimeInfo; OBJECTREF calendar; OBJECTREF m_cultureData; -#ifndef FEATURE_CORECLR OBJECTREF m_consoleFallbackCulture; -#endif // !FEATURE_CORECLR STRINGREF m_name; // "real" name - en-US, de-DE_phoneb or fj-FJ STRINGREF m_nonSortName; // name w/o sort info (de-DE for de-DE_phoneb) STRINGREF m_sortName; // Sort only name (de-DE_phoneb, en-us for fj-fj (w/us sort) @@ -2194,15 +2192,28 @@ public: } #endif // FEATURE_LEAK_CULTURE_INFO -#ifndef FEATURE_CORECLR +#ifdef FEATURE_SYNCHRONIZATIONCONTEXT_WAIT +#ifdef FEATURE_CORECLR OBJECTREF GetSynchronizationContext() { - LIMITED_METHOD_CONTRACT; + LIMITED_METHOD_CONTRACT; + return m_SynchronizationContext; + } +#else // !FEATURE_CORECLR + OBJECTREF GetSynchronizationContext() + { + LIMITED_METHOD_CONTRACT; if (m_ExecutionContext != NULL) + { return m_ExecutionContext->GetSynchronizationContext(); + } return NULL; } - OBJECTREF GetExecutionContext() +#endif // FEATURE_CORECLR +#endif // FEATURE_SYNCHRONIZATIONCONTEXT_WAIT + +#ifndef FEATURE_CORECLR + OBJECTREF GetExecutionContext() { LIMITED_METHOD_CONTRACT; return (OBJECTREF)m_ExecutionContext; @@ -2869,8 +2880,10 @@ class FrameSecurityDescriptorBaseObject : public Object LIMITED_METHOD_CONTRACT; m_declSecComputed = !!declSec; } +#ifndef FEATURE_PAL LPVOID GetCallerToken(); LPVOID GetImpersonationToken(); +#endif // FEATURE_PAL }; #ifdef FEATURE_COMPRESSEDSTACK @@ -4563,9 +4576,7 @@ public: INT32 cPositivePercentFormat; // positivePercentFormat INT32 cNegativePercentFormat; // negativePercentFormat INT32 cPercentDecimals; // percentDecimalDigits -#ifndef FEATURE_COREFX_GLOBALIZATION INT32 iDigitSubstitution; // digitSubstitution -#endif CLR_BOOL bIsReadOnly; // Is this NumberFormatInfo ReadOnly? #ifndef FEATURE_COREFX_GLOBALIZATION diff --git a/src/vm/prestub.cpp b/src/vm/prestub.cpp index 1f2e8c7..e0d4096 100644 --- a/src/vm/prestub.cpp +++ b/src/vm/prestub.cpp @@ -228,7 +228,7 @@ void DACNotifyCompilationFinished(MethodDesc *methodDesc) // Are we listed? USHORT jnt = jn.Requested((TADDR) modulePtr, t); if (jnt & CLRDATA_METHNOTIFY_GENERATED) - { + { // If so, throw an exception! #endif DACNotify::DoJITNotification(methodDesc); @@ -256,7 +256,7 @@ void DACNotifyCompilationFinished(MethodDesc *methodDesc) // which prevents us from trying to JIT the same method more that once. -PCODE MethodDesc::MakeJitWorker(COR_ILMETHOD_DECODER* ILHeader, DWORD flags, DWORD flags2) +PCODE MethodDesc::MakeJitWorker(COR_ILMETHOD_DECODER* ILHeader, CORJIT_FLAGS flags) { STANDARD_VM_CONTRACT; @@ -280,7 +280,7 @@ PCODE MethodDesc::MakeJitWorker(COR_ILMETHOD_DECODER* ILHeader, DWORD flags, DWO #ifdef FEATURE_MULTICOREJIT MulticoreJitManager & mcJitManager = GetAppDomain()->GetMulticoreJitManager(); - bool fBackgroundThread = (flags & CORJIT_FLG_MCJIT_BACKGROUND) != 0; + bool fBackgroundThread = flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_MCJIT_BACKGROUND); #endif { @@ -424,22 +424,30 @@ PCODE MethodDesc::MakeJitWorker(COR_ILMETHOD_DECODER* ILHeader, DWORD flags, DWO { BEGIN_PIN_PROFILER(CORProfilerTrackJITInfo()); +#ifdef FEATURE_MULTICOREJIT // Multicore JIT should be disabled when CORProfilerTrackJITInfo is on // But there could be corner case in which profiler is attached when multicore background thread is calling MakeJitWorker // Disable this block when calling from multicore JIT background thread - if (!IsNoMetadata() -#ifdef FEATURE_MULTICOREJIT - - && (! fBackgroundThread) + if (!fBackgroundThread) #endif - ) { - g_profControlBlock.pProfInterface->JITCompilationStarted((FunctionID) this, TRUE); - // The profiler may have changed the code on the callback. Need to - // pick up the new code. Note that you have to be fully trusted in - // this mode and the code will not be verified. - COR_ILMETHOD *pilHeader = GetILHeader(TRUE); - new (ILHeader) COR_ILMETHOD_DECODER(pilHeader, GetMDImport(), NULL); + if (!IsNoMetadata()) + { + g_profControlBlock.pProfInterface->JITCompilationStarted((FunctionID) this, TRUE); + // The profiler may have changed the code on the callback. Need to + // pick up the new code. Note that you have to be fully trusted in + // this mode and the code will not be verified. + COR_ILMETHOD *pilHeader = GetILHeader(TRUE); + new (ILHeader) COR_ILMETHOD_DECODER(pilHeader, GetMDImport(), NULL); + } + else + { + unsigned int ilSize, unused; + CorInfoOptions corOptions; + LPCBYTE ilHeaderPointer = this->AsDynamicMethodDesc()->GetResolver()->GetCodeInfo(&ilSize, &unused, &corOptions, &unused); + + g_profControlBlock.pProfInterface->DynamicMethodJITCompilationStarted((FunctionID) this, TRUE, ilHeaderPointer, ilSize); + } } END_PIN_PROFILER(); } @@ -457,13 +465,13 @@ PCODE MethodDesc::MakeJitWorker(COR_ILMETHOD_DECODER* ILHeader, DWORD flags, DWO if (!fBackgroundThread) #endif // FEATURE_MULTICOREJIT { - StackSampler::RecordJittingInfo(this, flags, flags2); + StackSampler::RecordJittingInfo(this, flags); } #endif // FEATURE_STACK_SAMPLING EX_TRY { - pCode = UnsafeJitFunction(this, ILHeader, flags, flags2, &sizeOfCode); + pCode = UnsafeJitFunction(this, ILHeader, flags, &sizeOfCode); } EX_CATCH { @@ -593,6 +601,10 @@ GotNewCode: pEntry->m_hrResultCode, TRUE); } + else + { + g_profControlBlock.pProfInterface->DynamicMethodJITCompilationFinished((FunctionID) this, pEntry->m_hrResultCode, TRUE); + } END_PIN_PROFILER(); } #endif // PROFILING_SUPPORTED @@ -1179,7 +1191,7 @@ PCODE MethodDesc::DoPrestub(MethodTable *pDispatchingMT) if (g_pConfig->ShouldPrestubGC(this)) { GCX_COOP(); - GCHeap::GetGCHeap()->GarbageCollect(-1); + GCHeapUtilities::GetGCHeap()->GarbageCollect(-1); } #endif // _DEBUG @@ -1203,12 +1215,12 @@ PCODE MethodDesc::DoPrestub(MethodTable *pDispatchingMT) RETURN GetStableEntryPoint(); } -#ifdef FEATURE_PREJIT +#if defined(FEATURE_PREJIT) && defined(FEATURE_CER) // If this method is the root of a CER call graph and we've recorded this fact in the ngen image then we're in the prestub in // order to trip any runtime level preparation needed for this graph (P/Invoke stub generation/library binding, generic // dictionary prepopulation etc.). GetModule()->RestoreCer(this); -#endif // FEATURE_PREJIT +#endif // FEATURE_PREJIT && FEATURE_CER #ifdef FEATURE_COMINTEROP /************************** INTEROP *************************/ @@ -1455,7 +1467,7 @@ PCODE MethodDesc::DoPrestub(MethodTable *pDispatchingMT) // Mark the code as hot in case the method ends up in the native image g_IBCLogger.LogMethodCodeAccess(this); - pCode = MakeJitWorker(pHeader, 0, 0); + pCode = MakeJitWorker(pHeader, CORJIT_FLAGS()); #ifdef FEATURE_INTERPRETER if ((pCode != NULL) && !HasStableEntryPoint()) @@ -1635,9 +1647,9 @@ PCODE MethodDesc::DoPrestub(MethodTable *pDispatchingMT) // use the prestub. //========================================================================== -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) static PCODE g_UMThunkPreStub; -#endif +#endif // _TARGET_X86_ && !FEATURE_STUBS_AS_IL #ifndef DACCESS_COMPILE @@ -1664,9 +1676,9 @@ void InitPreStubManager(void) return; } -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) g_UMThunkPreStub = GenerateUMThunkPrestub()->GetEntryPoint(); -#endif +#endif // _TARGET_X86_ && !FEATURE_STUBS_AS_IL ThePreStubManager::Init(); } @@ -1675,11 +1687,11 @@ PCODE TheUMThunkPreStub() { LIMITED_METHOD_CONTRACT; -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) return g_UMThunkPreStub; -#else +#else // _TARGET_X86_ && !FEATURE_STUBS_AS_IL return GetEEFuncEntryPoint(TheUMEntryPrestub); -#endif +#endif // _TARGET_X86_ && !FEATURE_STUBS_AS_IL } PCODE TheVarargNDirectStub(BOOL hasRetBuffArg) diff --git a/src/vm/profattach.cpp b/src/vm/profattach.cpp index f03db36..5b10e8f 100644 --- a/src/vm/profattach.cpp +++ b/src/vm/profattach.cpp @@ -806,7 +806,7 @@ void ProfilingAPIAttachDetach::InitializeAttachThreadingMode() // Environment variable trumps all, so check it first DWORD dwAlwaysOn = g_pConfig->GetConfigDWORD_DontUse_( CLRConfig::EXTERNAL_AttachThreadAlwaysOn, - GCHeap::IsServerHeap() ? 1 : 0); // Default depends on GC server mode + GCHeapUtilities::IsServerHeap() ? 1 : 0); // Default depends on GC server mode if (dwAlwaysOn == 0) { diff --git a/src/vm/profilinghelper.cpp b/src/vm/profilinghelper.cpp index 139ba89..1dd60b4 100644 --- a/src/vm/profilinghelper.cpp +++ b/src/vm/profilinghelper.cpp @@ -1413,7 +1413,7 @@ void ProfilingAPIUtility::TerminateProfiling() { // We know for sure GC has been fully initialized as we've turned off concurrent GC before _ASSERTE(IsGarbageCollectorFullyInitialized()); - GCHeap::GetGCHeap()->TemporaryEnableConcurrentGC(); + GCHeapUtilities::GetGCHeap()->TemporaryEnableConcurrentGC(); g_profControlBlock.fConcurrentGCDisabledForAttach = FALSE; } diff --git a/src/vm/proftoeeinterfaceimpl.cpp b/src/vm/proftoeeinterfaceimpl.cpp index 551b386..1aee26d 100644 --- a/src/vm/proftoeeinterfaceimpl.cpp +++ b/src/vm/proftoeeinterfaceimpl.cpp @@ -585,6 +585,10 @@ COM_METHOD ProfToEEInterfaceImpl::QueryInterface(REFIID id, void ** pInterface) { *pInterface = static_cast(this); } + else if (id == IID_ICorProfilerInfo8) + { + *pInterface = static_cast(this); + } else if (id == IID_IUnknown) { *pInterface = static_cast(static_cast(this)); @@ -754,7 +758,7 @@ struct GenerationTable //--------------------------------------------------------------------------------------- // -// This is a callback used by the GC when we call GCHeap::DescrGenerationsToProfiler +// This is a callback used by the GC when we call GCHeapUtilities::DiagDescrGenerations // (from UpdateGenerationBounds() below). The GC gives us generation information through // this callback, which we use to update the GenerationDesc in the corresponding // GenerationTable @@ -874,8 +878,8 @@ void __stdcall UpdateGenerationBounds() #endif // fill in the values by calling back into the gc, which will report // the ranges by calling GenWalkFunc for each one - GCHeap *hp = GCHeap::GetGCHeap(); - hp->DescrGenerationsToProfiler(GenWalkFunc, newGenerationTable); + IGCHeap *hp = GCHeapUtilities::GetGCHeap(); + hp->DiagDescrGenerations(GenWalkFunc, newGenerationTable); // remember the old table and plug in the new one GenerationTable *oldGenerationTable = s_currentGenerationTable; @@ -1018,7 +1022,7 @@ ClassID SafeGetClassIDFromObject(Object * pObj) //--------------------------------------------------------------------------------------- // -// Callback of type walk_fn used by GCHeap::WalkObject. Keeps a count of each +// Callback of type walk_fn used by GCHeapUtilities::DiagWalkObject. Keeps a count of each // object reference found. // // Arguments: @@ -1040,7 +1044,7 @@ BOOL CountContainedObjectRef(Object * pBO, void * context) //--------------------------------------------------------------------------------------- // -// Callback of type walk_fn used by GCHeap::WalkObject. Stores each object reference +// Callback of type walk_fn used by GCHeapUtilities::DiagWalkObject. Stores each object reference // encountered into an array. // // Arguments: @@ -1113,7 +1117,7 @@ BOOL HeapWalkHelper(Object * pBO, void * pvContext) if (pMT->ContainsPointersOrCollectible()) { // First round through calculates the number of object refs for this class - GCHeap::GetGCHeap()->WalkObject(pBO, &CountContainedObjectRef, (void *)&cNumRefs); + GCHeapUtilities::GetGCHeap()->DiagWalkObject(pBO, &CountContainedObjectRef, (void *)&cNumRefs); if (cNumRefs > 0) { @@ -1138,7 +1142,7 @@ BOOL HeapWalkHelper(Object * pBO, void * pvContext) // Second round saves off all of the ref values OBJECTREF * pCurObjRef = arrObjRef; - GCHeap::GetGCHeap()->WalkObject(pBO, &SaveContainedObjectRef, (void *)&pCurObjRef); + GCHeapUtilities::GetGCHeap()->DiagWalkObject(pBO, &SaveContainedObjectRef, (void *)&pCurObjRef); } } @@ -1959,7 +1963,7 @@ HRESULT GetFunctionInfoInternal(LPCBYTE ip, EECodeInfo * pCodeInfo) } -HRESULT GetFunctionFromIPInternal(LPCBYTE ip, EECodeInfo * pCodeInfo) +HRESULT GetFunctionFromIPInternal(LPCBYTE ip, EECodeInfo * pCodeInfo, BOOL failOnNoMetadata) { CONTRACTL { @@ -1979,11 +1983,14 @@ HRESULT GetFunctionFromIPInternal(LPCBYTE ip, EECodeInfo * pCodeInfo) { return hr; } - - // never return a method that the user of the profiler API cannot use - if (pCodeInfo->GetMethodDesc()->IsNoMetadata()) + + if (failOnNoMetadata) { - return E_FAIL; + // never return a method that the user of the profiler API cannot use + if (pCodeInfo->GetMethodDesc()->IsNoMetadata()) + { + return E_FAIL; + } } return S_OK; @@ -2043,7 +2050,7 @@ HRESULT ProfToEEInterfaceImpl::GetFunctionFromIP(LPCBYTE ip, FunctionID * pFunct EECodeInfo codeInfo; - hr = GetFunctionFromIPInternal(ip, &codeInfo); + hr = GetFunctionFromIPInternal(ip, &codeInfo, /* failOnNoMetadata */ TRUE); if (FAILED(hr)) { return hr; @@ -2096,7 +2103,7 @@ HRESULT ProfToEEInterfaceImpl::GetFunctionFromIP2(LPCBYTE ip, FunctionID * pFunc EECodeInfo codeInfo; - hr = GetFunctionFromIPInternal(ip, &codeInfo); + hr = GetFunctionFromIPInternal(ip, &codeInfo, /* failOnNoMetadata */ TRUE); if (FAILED(hr)) { return hr; @@ -4122,7 +4129,6 @@ DWORD ProfToEEInterfaceImpl::GetModuleFlags(Module * pModule) } #endif // Not NGEN or ReadyToRun. - if (pPEFile->HasOpenedILimage()) { PEImage * pILImage = pPEFile->GetOpenedILimage(); @@ -6051,7 +6057,7 @@ HRESULT ProfToEEInterfaceImpl::SetEnterLeaveFunctionHooks3WithInfo(FunctionEnter // The profiler must call SetEnterLeaveFunctionHooks3WithInfo during initialization, since // the enter/leave events are immutable and must also be set during initialization. - PROFILER_TO_CLR_ENTRYPOINT_SET_ELT((LF_CORPROF, + PROFILER_TO_CLR_ENTRYPOINT_SET_ELT((LF_CORPROF, LL_INFO10, "**PROF: SetEnterLeaveFunctionHooks3WithInfo 0x%p, 0x%p, 0x%p.\n", pFuncEnter3WithInfo, @@ -6373,6 +6379,294 @@ HRESULT ProfToEEInterfaceImpl::GetFunctionInfo2(FunctionID funcId, } /* +* IsFunctionDynamic +* +* This function takes a functionId that maybe of a metadata-less method like an IL Stub +* or LCG method and returns true in the pHasNoMetadata if it is indeed a metadata-less +* method. +* +* Parameters: +* functionId - The function that is being requested. +* isDynamic - An optional parameter for returning if the function has metadata or not. +* +* Returns: +* S_OK if successful. +*/ +HRESULT ProfToEEInterfaceImpl::IsFunctionDynamic(FunctionID functionId, BOOL *isDynamic) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + EE_THREAD_NOT_REQUIRED; + + // Generics::GetExactInstantiationsOfMethodAndItsClassFromCallInformation eventually + // reads metadata which causes us to take a reader lock. However, see + // code:#DisableLockOnAsyncCalls + DISABLED(CAN_TAKE_LOCK); + + // Asynchronous functions can be called at arbitrary times when runtime + // is holding locks that cannot be reentered without causing deadlock. + // This contract detects any attempts to reenter locks held at the time + // this function was called. + CANNOT_RETAKE_LOCK; + + SO_NOT_MAINLINE; + + PRECONDITION(CheckPointer(isDynamic, NULL_OK)); + } + CONTRACTL_END; + + // See code:#DisableLockOnAsyncCalls + PERMANENT_CONTRACT_VIOLATION(TakesLockViolation, ReasonProfilerAsyncCannotRetakeLock); + + PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach, + (LF_CORPROF, + LL_INFO1000, + "**PROF: IsFunctionDynamic 0x%p.\n", + functionId)); + + // + // Verify parameters. + // + + if (functionId == NULL) + { + return E_INVALIDARG; + } + + MethodDesc *pMethDesc = FunctionIdToMethodDesc(functionId); + + if (pMethDesc == NULL) + { + return E_INVALIDARG; + } + + // it's not safe to examine a methoddesc that has not been restored so do not do so + if (!pMethDesc->IsRestored()) + return CORPROF_E_DATAINCOMPLETE; + + // + // Fill in the pHasNoMetadata, if desired. + // + if (isDynamic != NULL) + { + *isDynamic = pMethDesc->IsNoMetadata(); + } + + return S_OK; +} + +/* +* GetFunctionFromIP3 +* +* This function takes an IP and determines if it is a managed function returning its +* FunctionID. This method is different from GetFunctionFromIP in that will return +* FunctionIDs even if they have no associated metadata. +* +* Parameters: +* ip - The instruction pointer. +* pFunctionId - An optional parameter for returning the FunctionID. +* pReJitId - The ReJIT id. +* +* Returns: +* S_OK if successful. +*/ +HRESULT ProfToEEInterfaceImpl::GetFunctionFromIP3(LPCBYTE ip, FunctionID * pFunctionId, ReJITID * pReJitId) +{ + CONTRACTL + { + NOTHROW; + + // Grabbing the rejitid requires entering the rejit manager's hash table & lock, + // which can switch us to preemptive mode and trigger GCs + GC_TRIGGERS; + MODE_ANY; + EE_THREAD_NOT_REQUIRED; + + // Grabbing the rejitid requires entering the rejit manager's hash table & lock, + CAN_TAKE_LOCK; + + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + // See code:#DisableLockOnAsyncCalls + PERMANENT_CONTRACT_VIOLATION(TakesLockViolation, ReasonProfilerAsyncCannotRetakeLock); + + PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX( + kP2EEAllowableAfterAttach | kP2EETriggers, + (LF_CORPROF, + LL_INFO1000, + "**PROF: GetFunctionFromIP3 0x%p.\n", + ip)); + + HRESULT hr = S_OK; + + EECodeInfo codeInfo; + + hr = GetFunctionFromIPInternal(ip, &codeInfo, /* failOnNoMetadata */ FALSE); + if (FAILED(hr)) + { + return hr; + } + + if (pFunctionId) + { + *pFunctionId = MethodDescToFunctionID(codeInfo.GetMethodDesc()); + } + + if (pReJitId != NULL) + { + MethodDesc * pMD = codeInfo.GetMethodDesc(); + *pReJitId = pMD->GetReJitManager()->GetReJitId(pMD, codeInfo.GetStartAddress()); + } + + return S_OK; +} + +/* +* GetDynamicFunctionInfo +* +* This function takes a functionId that maybe of a metadata-less method like an IL Stub +* or LCG method and gives information about it without failing like GetFunctionInfo. +* +* Parameters: +* functionId - The function that is being requested. +* pModuleId - An optional parameter for returning the module of the function. +* ppvSig - An optional parameter for returning the signature of the function. +* pbSig - An optional parameter for returning the size of the signature of the function. +* cchName - A parameter for indicating the size of buffer for the wszName parameter. +* pcchName - An optional parameter for returning the true size of the wszName parameter. +* wszName - A parameter to the caller allocated buffer of size cchName +* +* Returns: +* S_OK if successful. +*/ +HRESULT ProfToEEInterfaceImpl::GetDynamicFunctionInfo(FunctionID functionId, + ModuleID *pModuleId, + PCCOR_SIGNATURE* ppvSig, + ULONG* pbSig, + ULONG cchName, + ULONG *pcchName, + __out_ecount_part_opt(cchName, *pcchName) WCHAR wszName[]) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + EE_THREAD_NOT_REQUIRED; + + // Generics::GetExactInstantiationsOfMethodAndItsClassFromCallInformation eventually + // reads metadata which causes us to take a reader lock. However, see + // code:#DisableLockOnAsyncCalls + DISABLED(CAN_TAKE_LOCK); + + // Asynchronous functions can be called at arbitrary times when runtime + // is holding locks that cannot be reentered without causing deadlock. + // This contract detects any attempts to reenter locks held at the time + // this function was called. + CANNOT_RETAKE_LOCK; + + SO_NOT_MAINLINE; + + PRECONDITION(CheckPointer(pModuleId, NULL_OK)); + PRECONDITION(CheckPointer(ppvSig, NULL_OK)); + PRECONDITION(CheckPointer(pbSig, NULL_OK)); + PRECONDITION(CheckPointer(pcchName, NULL_OK)); + } + CONTRACTL_END; + + // See code:#DisableLockOnAsyncCalls + PERMANENT_CONTRACT_VIOLATION(TakesLockViolation, ReasonProfilerAsyncCannotRetakeLock); + + PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach, + (LF_CORPROF, + LL_INFO1000, + "**PROF: GetDynamicFunctionInfo 0x%p.\n", + functionId)); + + // + // Verify parameters. + // + + if (functionId == NULL) + { + return E_INVALIDARG; + } + + MethodDesc *pMethDesc = FunctionIdToMethodDesc(functionId); + + if (pMethDesc == NULL) + { + return E_INVALIDARG; + } + + // it's not safe to examine a methoddesc that has not been restored so do not do so + if (!pMethDesc->IsRestored()) + return CORPROF_E_DATAINCOMPLETE; + + + if (!pMethDesc->IsNoMetadata()) + return E_INVALIDARG; + + // + // Fill in the ModuleId, if desired. + // + if (pModuleId != NULL) + { + *pModuleId = (ModuleID)pMethDesc->GetModule(); + } + + // + // Fill in the ppvSig and pbSig, if desired + // + if (ppvSig != NULL && pbSig != NULL) + { + pMethDesc->GetSig(ppvSig, pbSig); + } + + HRESULT hr = S_OK; + + EX_TRY + { + if (wszName != NULL) + *wszName = 0; + if (pcchName != NULL) + *pcchName = 0; + + StackSString ss; + ss.SetUTF8(pMethDesc->GetName()); + ss.Normalize(); + LPCWSTR methodName = ss.GetUnicode(); + + ULONG trueLen = (ULONG)(wcslen(methodName) + 1); + + // Return name of method as required. + if (wszName && cchName > 0) + { + if (cchName < trueLen) + { + hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + } + else + { + wcsncpy_s(wszName, cchName, methodName, trueLen); + } + } + + // If they request the actual length of the name + if (pcchName) + *pcchName = trueLen; + } + EX_CATCH_HRESULT(hr); + + return (hr); +} + +/* * GetStringLayout * * This function describes to a profiler the internal layout of a string. @@ -7081,12 +7375,13 @@ Loop: // GC info will assist us in determining whether this is a non-EBP frame and // info about pushed arguments. - PTR_VOID gcInfo = codeInfo.GetGCInfo(); + GCInfoToken gcInfoToken = codeInfo.GetGCInfoToken(); + PTR_VOID gcInfo = gcInfoToken.Info; InfoHdr header; unsigned uiMethodSizeDummy; PTR_CBYTE table = PTR_CBYTE(gcInfo); table += decodeUnsigned(table, &uiMethodSizeDummy); - table = decodeHeader(table, &header); + table = decodeHeader(table, gcInfoToken.Version, &header); // Ok, GCInfo, can we do a simple EBP walk or what? @@ -7235,18 +7530,13 @@ HRESULT ProfToEEInterfaceImpl::DoStackSnapshot(ThreadID thread, ULONG32 contextSize) { -#ifdef _TARGET_ARM_ - // DoStackSnapshot is not supported on arm. Profilers can use OS apis to get the call stack. - return E_NOTIMPL; -#endif - -#if !defined(FEATURE_HIJACK) || !defined(PLATFORM_SUPPORTS_SAFE_THREADSUSPEND) +#if !defined(FEATURE_HIJACK) // DoStackSnapshot needs Thread::Suspend/ResumeThread functionality. // On platforms w/o support for these APIs return E_NOTIMPL. return E_NOTIMPL; -#else // !defined(FEATURE_HIJACK) || !defined(PLATFORM_SUPPORTS_SAFE_THREADSUSPEND) +#else // !defined(FEATURE_HIJACK) CONTRACTL { @@ -7414,6 +7704,10 @@ HRESULT ProfToEEInterfaceImpl::DoStackSnapshot(ThreadID thread, // First, check "1) Target thread to walk == current thread OR Target thread is suspended" if (pThreadToSnapshot != pCurrentThread) { +#ifndef PLATFORM_SUPPORTS_SAFE_THREADSUSPEND + hr = E_NOTIMPL; + goto Cleanup; +#else // Walking separate thread, so it must be suspended. First, ensure that // target thread exists. // @@ -7449,6 +7743,7 @@ HRESULT ProfToEEInterfaceImpl::DoStackSnapshot(ThreadID thread, hr = CORPROF_E_STACKSNAPSHOT_UNSAFE; goto Cleanup; } +#endif // !PLATFORM_SUPPORTS_SAFE_THREADSUSPEND } hostCallPreference = @@ -7481,7 +7776,10 @@ HRESULT ProfToEEInterfaceImpl::DoStackSnapshot(ThreadID thread, // (Note that this whole block is skipped if pThreadToSnapshot is in preemptive mode (the IF // above), as the context is unused in such a case--the EE Frame chain is used // to seed the walk instead.) - +#ifndef PLATFORM_SUPPORTS_SAFE_THREADSUSPEND + hr = E_NOTIMPL; + goto Cleanup; +#else if (!pThreadToSnapshot->GetSafelyRedirectableThreadContext(Thread::kDefaultChecks, &ctxCurrent, &rd)) { LOG((LF_CORPROF, LL_INFO100, "**PROF: GetSafelyRedirectableThreadContext failure leads to CORPROF_E_STACKSNAPSHOT_UNSAFE.\n")); @@ -7542,6 +7840,7 @@ HRESULT ProfToEEInterfaceImpl::DoStackSnapshot(ThreadID thread, { pctxSeed = &ctxCurrent; } +#endif // !PLATFORM_SUPPORTS_SAFE_THREADSUSPEND } // Second, check "2) Target thread to walk is currently executing JITted / NGENd code" @@ -7588,6 +7887,10 @@ HRESULT ProfToEEInterfaceImpl::DoStackSnapshot(ThreadID thread, // if (pThreadToSnapshot != pCurrentThread) { +#ifndef PLATFORM_SUPPORTS_SAFE_THREADSUSPEND + hr = E_NOTIMPL; + goto Cleanup; +#else if (pctxSeed == NULL) { if (pThreadToSnapshot->GetSafelyRedirectableThreadContext(Thread::kDefaultChecks, &ctxCurrent, &rd)) @@ -7604,9 +7907,9 @@ HRESULT ProfToEEInterfaceImpl::DoStackSnapshot(ThreadID thread, } } } +#endif // !PLATFORM_SUPPORTS_SAFE_THREADSUSPEND } -#endif - +#endif //_DEBUG // Third, verify the target thread is seeded or not in the midst of an unwind. if (pctxSeed == NULL) { @@ -7671,12 +7974,13 @@ HRESULT ProfToEEInterfaceImpl::DoStackSnapshot(ThreadID thread, INDEBUG(if (pCurrentThread) pCurrentThread->m_ulForbidTypeLoad = ulForbidTypeLoad;) - Cleanup: +#if defined(PLATFORM_SUPPORTS_SAFE_THREADSUSPEND) if (fResumeThread) { pThreadToSnapshot->ResumeThread(); } +#endif // PLATFORM_SUPPORTS_SAFE_THREADSUSPEND if (fResetSnapshotThreadExternalCount) { pThreadToSnapshot->DecExternalCountDANGEROUSProfilerOnly(); @@ -7684,7 +7988,7 @@ Cleanup: return hr; -#endif // !defined(FEATURE_HIJACK) || !defined(PLATFORM_SUPPORTS_SAFE_THREADSUSPEND) +#endif // !defined(FEATURE_HIJACK) } @@ -8439,7 +8743,7 @@ HRESULT ProfToEEInterfaceImpl::RequestProfilerDetach(DWORD dwExpectedCompletionM typedef struct _COR_PRF_ELT_INFO_INTERNAL { // Point to a platform dependent structure ASM helper push on the stack - void * platformSpecificHandle; + void * platformSpecificHandle; // startAddress of COR_PRF_FUNCTION_ARGUMENT_RANGE structure needs to point // TO the argument value, not BE the argument value. So, when the argument @@ -9461,7 +9765,7 @@ FCIMPL2(void, ProfilingFCallHelper::FC_RemotingClientSendingMessage, GUID *pId, // it is a value class declared on the stack and so GC doesn't // know about it. - _ASSERTE (!GCHeap::GetGCHeap()->IsHeapPointer(pId)); // should be on the stack, not in the heap + _ASSERTE (!GCHeapUtilities::GetGCHeap()->IsHeapPointer(pId)); // should be on the stack, not in the heap HELPER_METHOD_FRAME_BEGIN_NOPOLL(); { diff --git a/src/vm/proftoeeinterfaceimpl.h b/src/vm/proftoeeinterfaceimpl.h index 7bbd0bc..ed53ae2 100644 --- a/src/vm/proftoeeinterfaceimpl.h +++ b/src/vm/proftoeeinterfaceimpl.h @@ -133,7 +133,7 @@ typedef struct _PROFILER_STACK_WALK_DATA PROFILER_STACK_WALK_DATA; // from the profiler implementation. The profiler will call back on the v-table // to get at EE internals as required. -class ProfToEEInterfaceImpl : public ICorProfilerInfo7 +class ProfToEEInterfaceImpl : public ICorProfilerInfo8 { public: @@ -555,6 +555,28 @@ public: // end ICorProfilerInfo7 + // begin ICorProfilerInfo8 + + COM_METHOD IsFunctionDynamic( + FunctionID functionId, + BOOL *isDynamic); + + COM_METHOD GetFunctionFromIP3( + LPCBYTE ip, // in + FunctionID * pFunctionId, // out + ReJITID * pReJitId); // out + + COM_METHOD GetDynamicFunctionInfo( + FunctionID functionId, + ModuleID* moduleId, + PCCOR_SIGNATURE* ppvSig, + ULONG* pbSig, + ULONG cchName, + ULONG *pcchName, + WCHAR wszName[]); + + // end ICorProfilerInfo8 + protected: // Internal Helper Functions diff --git a/src/vm/rcwwalker.cpp b/src/vm/rcwwalker.cpp index ad71812..0b87536 100644 --- a/src/vm/rcwwalker.cpp +++ b/src/vm/rcwwalker.cpp @@ -129,10 +129,10 @@ STDMETHODIMP CLRServicesImpl::GarbageCollect(DWORD dwFlags) { GCX_COOP_THREAD_EXISTS(GET_THREAD()); if (dwFlags & GC_FOR_APPX_SUSPEND) { - GCHeap::GetGCHeap()->GarbageCollect(2, TRUE, collection_blocking | collection_optimized); + GCHeapUtilities::GetGCHeap()->GarbageCollect(2, TRUE, collection_blocking | collection_optimized); } else - GCHeap::GetGCHeap()->GarbageCollect(); + GCHeapUtilities::GetGCHeap()->GarbageCollect(); } END_EXTERNAL_ENTRYPOINT; return hr; diff --git a/src/vm/readytoruninfo.cpp b/src/vm/readytoruninfo.cpp index f867036..a0e44ce 100644 --- a/src/vm/readytoruninfo.cpp +++ b/src/vm/readytoruninfo.cpp @@ -401,6 +401,55 @@ static void LogR2r(const char *msg, PEFile *pFile) #define DoLog(msg) if (s_r2rLogFile != NULL) LogR2r(msg, pFile) +// Try to acquire an R2R image for exclusive use by a particular module. +// Returns true if successful. Returns false if the image is already been used +// by another module. Each R2R image has a space to store a pointer to the +// module that owns it. We set this pointer unless it has already be +// initialized to point to another Module. +static bool AcquireImage(Module * pModule, PEImageLayout * pLayout, READYTORUN_HEADER * pHeader) +{ + STANDARD_VM_CONTRACT; + + // First find the import sections of the image. + READYTORUN_IMPORT_SECTION * pImportSections = NULL; + READYTORUN_IMPORT_SECTION * pImportSectionsEnd = NULL; + READYTORUN_SECTION * pSections = (READYTORUN_SECTION*)(pHeader + 1); + for (DWORD i = 0; i < pHeader->NumberOfSections; i++) + { + if (pSections[i].Type == READYTORUN_SECTION_IMPORT_SECTIONS) + { + pImportSections = (READYTORUN_IMPORT_SECTION*)((PBYTE)pLayout->GetBase() + pSections[i].Section.VirtualAddress); + pImportSectionsEnd = (READYTORUN_IMPORT_SECTION*)((PBYTE)pImportSections + pSections[i].Section.Size); + break; + } + } + + // Go through the import sections to find the import for the module pointer. + for (READYTORUN_IMPORT_SECTION * pCurSection = pImportSections; pCurSection < pImportSectionsEnd; pCurSection++) + { + // The import for the module pointer is always in an eager fixup section, so skip delayed fixup sections. + if ((pCurSection->Flags & READYTORUN_IMPORT_SECTION_FLAGS_EAGER) == 0) + continue; + + // Found an eager fixup section. Check the signature of each fixup in this section. + PVOID *pFixups = (PVOID *)((PBYTE)pLayout->GetBase() + pCurSection->Section.VirtualAddress); + DWORD nFixups = pCurSection->Section.Size / sizeof(PVOID); + DWORD *pSignatures = (DWORD *)((PBYTE)pLayout->GetBase() + pCurSection->Signatures); + for (DWORD i = 0; i < nFixups; i++) + { + // See if we found the fixup for the Module pointer. + PBYTE pSig = (PBYTE)pLayout->GetBase() + pSignatures[i]; + if (pSig[0] == READYTORUN_FIXUP_Helper && pSig[1] == READYTORUN_HELPER_Module) + { + Module * pPrevious = InterlockedCompareExchangeT(EnsureWritablePages((Module **)(pFixups + i)), pModule, NULL); + return pPrevious == NULL || pPrevious == pModule; + } + } + } + + return false; +} + PTR_ReadyToRunInfo ReadyToRunInfo::Initialize(Module * pModule, AllocMemTracker *pamTracker) { STANDARD_VM_CONTRACT; @@ -478,6 +527,12 @@ PTR_ReadyToRunInfo ReadyToRunInfo::Initialize(Module * pModule, AllocMemTracker return NULL; } + if (!AcquireImage(pModule, pLayout, pHeader)) + { + DoLog("Ready to Run disabled - module already loaded in another AppDomain"); + return NULL; + } + LoaderHeap *pHeap = pModule->GetLoaderAllocator()->GetHighFrequencyHeap(); void * pMemory = pamTracker->Track(pHeap->AllocMem((S_SIZE_T)sizeof(ReadyToRunInfo))); @@ -636,6 +691,22 @@ PCODE ReadyToRunInfo::GetEntryPoint(MethodDesc * pMD, BOOL fFixups /*=TRUE*/) return NULL; } +#ifndef CROSSGEN_COMPILE +#ifdef PROFILING_SUPPORTED + BOOL fShouldSearchCache = TRUE; + { + BEGIN_PIN_PROFILER(CORProfilerTrackCacheSearches()); + g_profControlBlock.pProfInterface-> + JITCachedFunctionSearchStarted((FunctionID)pMD, &fShouldSearchCache); + END_PIN_PROFILER(); + } + if (!fShouldSearchCache) + { + return NULL; + } +#endif // PROFILING_SUPPORTED +#endif // CROSSGEN_COMPILE + uint id; offset = m_nativeReader.DecodeUnsigned(offset, &id); @@ -671,6 +742,17 @@ PCODE ReadyToRunInfo::GetEntryPoint(MethodDesc * pMD, BOOL fFixups /*=TRUE*/) m_entryPointToMethodDescMap.InsertValue(PCODEToPINSTR(pEntryPoint), pMD); } +#ifndef CROSSGEN_COMPILE +#ifdef PROFILING_SUPPORTED + { + BEGIN_PIN_PROFILER(CORProfilerTrackCacheSearches()); + g_profControlBlock.pProfInterface-> + JITCachedFunctionSearchFinished((FunctionID)pMD, COR_PRF_CACHED_FUNCTION_FOUND); + END_PIN_PROFILER(); + } +#endif // PROFILING_SUPPORTED +#endif // CROSSGEN_COMPILE + if (g_pDebugInterface != NULL) { g_pDebugInterface->JITComplete(pMD, pEntryPoint); diff --git a/src/vm/reflectioninvocation.cpp b/src/vm/reflectioninvocation.cpp index de50514..4edecdd 100644 --- a/src/vm/reflectioninvocation.cpp +++ b/src/vm/reflectioninvocation.cpp @@ -2508,6 +2508,7 @@ FCIMPL1(void, ReflectionInvocation::PrepareContractedDelegate, Object * delegate } CONTRACTL_END; +#ifdef FEATURE_CER if (delegateUNSAFE == NULL) return; @@ -2517,9 +2518,11 @@ FCIMPL1(void, ReflectionInvocation::PrepareContractedDelegate, Object * delegate PrepareDelegateHelper(&delegate, TRUE); HELPER_METHOD_FRAME_END(); +#endif // FEATURE_CER } FCIMPLEND +#ifdef FEATURE_CER void ReflectionInvocation::PrepareDelegateHelper(OBJECTREF *pDelegate, BOOL onlyContractedMethod) { CONTRACTL { @@ -2601,6 +2604,7 @@ void ReflectionInvocation::PrepareDelegateHelper(OBJECTREF *pDelegate, BOOL only onlyContractedMethod); } } +#endif // FEATURE_CER FCIMPL0(void, ReflectionInvocation::ProbeForSufficientStack) { @@ -2637,7 +2641,6 @@ FCIMPL0(void, ReflectionInvocation::EnsureSufficientExecutionStack) } FCIMPLEND -#ifdef FEATURE_CORECLR // As with EnsureSufficientExecutionStack, this method checks and returns whether there is // sufficient stack to execute the average Framework method, but rather than throwing, // it simply returns a Boolean: true for sufficient stack space, otherwise false. @@ -2654,7 +2657,6 @@ FCIMPL0(FC_BOOL_RET, ReflectionInvocation::TryEnsureSufficientExecutionStack) FC_RETURN_BOOL(current >= limit); } FCIMPLEND -#endif // FEATURE_CORECLR struct ECWGCFContext { @@ -2849,6 +2851,7 @@ FCIMPL3(void, ReflectionInvocation::ExecuteCodeWithGuaranteedCleanup, Object* co if (gc.backoutDelegate == NULL) COMPlusThrowArgumentNull(W("backoutCode")); +#ifdef FEATURE_CER if (!IsCompilationProcess()) { // Delegates are prepared as part of the ngen process, so only prepare the backout @@ -2859,6 +2862,7 @@ FCIMPL3(void, ReflectionInvocation::ExecuteCodeWithGuaranteedCleanup, Object* co // attempt to run the backout code. PrepareMethodDesc(g_pExecuteBackoutCodeHelperMethod, Instantiation(), Instantiation(), FALSE, TRUE); } +#endif // FEATURE_CER ExecuteCodeWithGuaranteedCleanupHelper(&gc); diff --git a/src/vm/reflectioninvocation.h b/src/vm/reflectioninvocation.h index fd14532..7f72b61 100644 --- a/src/vm/reflectioninvocation.h +++ b/src/vm/reflectioninvocation.h @@ -56,10 +56,8 @@ public: #endif // !FEATURE_CORECLR static FCDECL1(void, PrepareContractedDelegate, Object* delegateUNSAFE); static FCDECL0(void, ProbeForSufficientStack); - static FCDECL0(void, EnsureSufficientExecutionStack); -#ifdef FEATURE_CORECLR // currently only used from mscorlib in FEATURE_CORECLR - static FCDECL0(FC_BOOL_RET, TryEnsureSufficientExecutionStack); -#endif // FEATURE_CORECLR + static FCDECL0(void, EnsureSufficientExecutionStack); + static FCDECL0(FC_BOOL_RET, TryEnsureSufficientExecutionStack); static FCDECL3(void, ExecuteCodeWithGuaranteedCleanup, Object* pCodeDelegateUNSAFE, Object* pBackoutDelegateUNSAFE, Object* pUserDataUNSAFE); // TypedReference functions, should go somewhere else diff --git a/src/vm/rejit.cpp b/src/vm/rejit.cpp index 6b3caa9..0b6e922 100644 --- a/src/vm/rejit.cpp +++ b/src/vm/rejit.cpp @@ -178,22 +178,22 @@ CrstStatic ReJitManager::s_csGlobalRequest; //--------------------------------------------------------------------------------------- // Helpers -inline DWORD JitFlagsFromProfCodegenFlags(DWORD dwCodegenFlags) +inline CORJIT_FLAGS JitFlagsFromProfCodegenFlags(DWORD dwCodegenFlags) { LIMITED_METHOD_DAC_CONTRACT; - DWORD jitFlags = 0; + CORJIT_FLAGS jitFlags; // Note: COR_PRF_CODEGEN_DISABLE_INLINING is checked in // code:CEEInfo::canInline#rejit (it has no equivalent CORJIT flag). if ((dwCodegenFlags & COR_PRF_CODEGEN_DISABLE_ALL_OPTIMIZATIONS) != 0) { - jitFlags |= CORJIT_FLG_DEBUG_CODE; + jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE); } // In the future more flags may be added that need to be converted here (e.g., - // COR_PRF_CODEGEN_ENTERLEAVE / CORJIT_FLG_PROF_ENTERLEAVE) + // COR_PRF_CODEGEN_ENTERLEAVE / CORJIT_FLAG_PROF_ENTERLEAVE) return jitFlags; } @@ -2170,8 +2170,7 @@ PCODE ReJitManager::DoReJit(ReJitInfo * pInfo) pCodeOfRejittedCode = UnsafeJitFunction( pInfo->GetMethodDesc(), &ILHeader, - JitFlagsFromProfCodegenFlags(pInfo->m_pShared->m_dwCodegenFlags), - 0); + JitFlagsFromProfCodegenFlags(pInfo->m_pShared->m_dwCodegenFlags)); _ASSERTE(pCodeOfRejittedCode != NULL); diff --git a/src/vm/rexcep.h b/src/vm/rexcep.h index fe920bc..1d1d938 100644 --- a/src/vm/rexcep.h +++ b/src/vm/rexcep.h @@ -144,7 +144,11 @@ DEFINE_EXCEPTION(g_SystemNS, BadImageFormatException, true, DEFINE_EXCEPTION(g_SystemNS, CannotUnloadAppDomainException, false, COR_E_CANNOTUNLOADAPPDOMAIN) DEFINE_EXCEPTION(g_CodeContractsNS, ContractException, false, COR_E_CODECONTRACTFAILED) + +#ifdef FEATURE_REMOTING DEFINE_EXCEPTION(g_SystemNS, ContextMarshalException, false, COR_E_CONTEXTMARSHAL) +#endif + DEFINE_EXCEPTION(g_ReflectionNS, CustomAttributeFormatException, false, COR_E_CUSTOMATTRIBUTEFORMAT) #if defined(FEATURE_X509) || defined(FEATURE_CRYPTO) diff --git a/src/vm/runtimecallablewrapper.cpp b/src/vm/runtimecallablewrapper.cpp index d12d556..359b689 100644 --- a/src/vm/runtimecallablewrapper.cpp +++ b/src/vm/runtimecallablewrapper.cpp @@ -42,6 +42,7 @@ class Object; #include "olevariant.h" #include "interopconverter.h" #include "constrainedexecutionregion.h" +#include "typestring.h" #ifdef FEATURE_REMOTING #include "crossdomaincalls.h" #endif @@ -1591,7 +1592,7 @@ public: if (pRCW->IsValid()) { - if (!GCHeap::GetGCHeap()->IsPromoted(OBJECTREFToObject(pRCW->GetExposedObject())) && + if (!GCHeapUtilities::GetGCHeap()->IsPromoted(OBJECTREFToObject(pRCW->GetExposedObject())) && !pRCW->IsDetached()) { // No need to use InterlockedOr here since every other place that modifies the flags @@ -1612,7 +1613,7 @@ void RCWCache::DetachWrappersWorker() NOTHROW; GC_NOTRIGGER; MODE_ANY; - PRECONDITION(GCHeap::IsGCInProgress()); // GC is in progress and the runtime is suspended + PRECONDITION(GCHeapUtilities::IsGCInProgress()); // GC is in progress and the runtime is suspended } CONTRACTL_END; @@ -2808,7 +2809,7 @@ void RCW::MinorCleanup() NOTHROW; GC_NOTRIGGER; MODE_ANY; - PRECONDITION(GCHeap::IsGCInProgress() || ( (g_fEEShutDown & ShutDown_SyncBlock) && g_fProcessDetach )); + PRECONDITION(GCHeapUtilities::IsGCInProgress() || ( (g_fEEShutDown & ShutDown_SyncBlock) && g_fProcessDetach )); } CONTRACTL_END; diff --git a/src/vm/safehandle.cpp b/src/vm/safehandle.cpp index 3336e69..828b221 100644 --- a/src/vm/safehandle.cpp +++ b/src/vm/safehandle.cpp @@ -246,7 +246,7 @@ void SafeHandle::Dispose() // Suppress finalization on this object (we may be racing here but the // operation below is idempotent and a dispose should never race a // finalization). - GCHeap::GetGCHeap()->SetFinalizationRun(OBJECTREFToObject(sh)); + GCHeapUtilities::GetGCHeap()->SetFinalizationRun(OBJECTREFToObject(sh)); GCPROTECT_END(); } @@ -394,7 +394,7 @@ FCIMPL1(void, SafeHandle::SetHandleAsInvalid, SafeHandle* refThisUNSAFE) } while (InterlockedCompareExchange((LONG*)&sh->m_state, newState, oldState) != oldState); - GCHeap::GetGCHeap()->SetFinalizationRun(OBJECTREFToObject(sh)); + GCHeapUtilities::GetGCHeap()->SetFinalizationRun(OBJECTREFToObject(sh)); } FCIMPLEND diff --git a/src/vm/securityattributes.cpp b/src/vm/securityattributes.cpp index 2c89540..0facbbb 100644 --- a/src/vm/securityattributes.cpp +++ b/src/vm/securityattributes.cpp @@ -304,9 +304,7 @@ void SecurityAttributes::EncodePermissionSet(IN OBJECTREF* pRef, ppbData, pcbData); } -#endif // FEATURE_CAS_POLICY -#ifdef FEATURE_CAS_POLICY static void SetupRestrictSecAttributes() { CONTRACTL { @@ -334,7 +332,6 @@ static void SetupRestrictSecAttributes() } EX_END_CATCH(RethrowTerminalExceptions) } -#endif // FEATURE_CAS_POLICY Assembly* SecurityAttributes::LoadAssemblyFromToken(IMetaDataAssemblyImport *pImport, mdAssemblyRef tkAssemblyRef) { @@ -1182,7 +1179,6 @@ void SecurityAttributes::AttrSetBlobToPermissionSets( COMPlusThrowHR(hr); } -#ifdef FEATURE_CAS_POLICY HRESULT SecurityAttributes::TranslateSecurityAttributesHelper( CORSEC_ATTRSET *pAttrSet, BYTE **ppbOutput, @@ -1255,7 +1251,6 @@ HRESULT SecurityAttributes::TranslateSecurityAttributesHelper( EX_CATCH_HRESULT(hr); return hr; } -#endif // FEATURE_CAS_POLICY // Call into managed code to group permissions into a PermissionSet and serialize it to XML void SecurityAttributes::AttrArrayToPermissionSet(OBJECTREF* attrArray, @@ -1354,7 +1349,7 @@ void SecurityAttributes::AttrArrayToPermissionSet(OBJECTREF* attrArray, GCPROTECT_END(); } - +#endif // FEATURE_CAS_POLICY // // This is a public exported method diff --git a/src/vm/securitydeclarativecache.cpp b/src/vm/securitydeclarativecache.cpp index 29868f2..dcfc1e0 100644 --- a/src/vm/securitydeclarativecache.cpp +++ b/src/vm/securitydeclarativecache.cpp @@ -75,6 +75,7 @@ OBJECTREF PsetCacheEntry::CreateManagedPsetObject(DWORD dwAction, bool createEmp MODE_COOPERATIVE; } CONTRACTL_END; +#ifdef FEATURE_CAS_POLICY OBJECTREF orRet; orRet = GetManagedPsetObject(); @@ -106,7 +107,6 @@ OBJECTREF PsetCacheEntry::CreateManagedPsetObject(DWORD dwAction, bool createEmp } else { -#ifdef FEATURE_CAS_POLICY SecurityAttributes::XmlToPermissionSet(m_pKey->m_pbPset, m_pKey->m_cbPset, &gc.pset, @@ -115,10 +115,6 @@ OBJECTREF PsetCacheEntry::CreateManagedPsetObject(DWORD dwAction, bool createEmp 0, &gc.orNonCasPset, &gc.orNonCasEncoding); -#else - // The v1.x serialized permission set format is not supported on CoreCLR - COMPlusThrowHR(CORSECATTR_E_BAD_ATTRIBUTE); -#endif //FEATURE_CAS_POLICY } StoreFirstObjectInHandle(m_handle, gc.pset); @@ -135,6 +131,9 @@ OBJECTREF PsetCacheEntry::CreateManagedPsetObject(DWORD dwAction, bool createEmp orRet = GetManagedPsetObject(); return orRet; +#else + return NULL; +#endif } #endif // CROSSGEN_COMPILE diff --git a/src/vm/securityprincipal.h b/src/vm/securityprincipal.h index 3bde5fd..5d6b522 100644 --- a/src/vm/securityprincipal.h +++ b/src/vm/securityprincipal.h @@ -11,9 +11,11 @@ +#ifndef FEATURE_PAL class COMPrincipal { public: +#ifndef FEATURE_CORECLR static INT32 QCALLTYPE ImpersonateLoggedOnUser(HANDLE hToken); @@ -24,6 +26,8 @@ public: static INT32 QCALLTYPE SetThreadToken(HANDLE hToken); +#endif // !FEATURE_CORECLR static void CLR_ImpersonateLoggedOnUser(HANDLE hToken); }; +#endif // FEATURE_PAL diff --git a/src/vm/siginfo.cpp b/src/vm/siginfo.cpp index decd3c0..9adfb49 100644 --- a/src/vm/siginfo.cpp +++ b/src/vm/siginfo.cpp @@ -14,7 +14,7 @@ #include "clsload.hpp" #include "vars.hpp" #include "excep.h" -#include "gc.h" +#include "gcheaputilities.h" #include "field.h" #include "eeconfig.h" #include "runtimehandles.h" // for SignatureNative diff --git a/src/vm/stacksampler.cpp b/src/vm/stacksampler.cpp index 270d278..d95adb1 100644 --- a/src/vm/stacksampler.cpp +++ b/src/vm/stacksampler.cpp @@ -154,7 +154,7 @@ bool IsGoodMethodDesc(MethodDesc* pMD) // // An opportunity to record the parameters passed to the JIT at the time of JITting this method. /* static */ -void StackSampler::RecordJittingInfo(MethodDesc* pMD, DWORD dwFlags, DWORD dwFlags2) +void StackSampler::RecordJittingInfo(MethodDesc* pMD, CORJIT_FLAGS flags) { WRAPPER_NO_CONTRACT; if (g_pStackSampler == nullptr) @@ -167,10 +167,10 @@ void StackSampler::RecordJittingInfo(MethodDesc* pMD, DWORD dwFlags, DWORD dwFla return; } // Record in the hash map. - g_pStackSampler->RecordJittingInfoInternal(pMD, dwFlags); + g_pStackSampler->RecordJittingInfoInternal(pMD, flags); } -void StackSampler::RecordJittingInfoInternal(MethodDesc* pMD, DWORD dwFlags) +void StackSampler::RecordJittingInfoInternal(MethodDesc* pMD, CORJIT_FLAGS flags) { ADID dwDomainId = GetThread()->GetDomain()->GetId(); JitInfoHashEntry entry(pMD, dwDomainId); @@ -426,7 +426,7 @@ void StackSampler::JitAndCollectTrace(MethodDesc* pMD, const ADID& adId) // Indicate to the JIT or the JIT interface that we are JITting // in the background for stack sampling. - DWORD dwFlags2 = CORJIT_FLG2_SAMPLING_JIT_BACKGROUND; + CORJIT_FLAGS flags(CORJIT_FLAGS::CORJIT_FLAG_SAMPLING_JIT_BACKGROUND); _ASSERTE(pMD->IsIL()); @@ -447,7 +447,7 @@ void StackSampler::JitAndCollectTrace(MethodDesc* pMD, const ADID& adId) LOG((LF_JIT, LL_INFO100000, "%s:%s\n", pMD->GetMethodTable()->GetClass()->GetDebugClassName(), pMD->GetName())); #endif - PCODE pCode = UnsafeJitFunction(pMD, pDecoder, 0, dwFlags2); + PCODE pCode = UnsafeJitFunction(pMD, pDecoder, flags); } END_DOMAIN_TRANSITION; diff --git a/src/vm/stacksampler.h b/src/vm/stacksampler.h index 33fc6b9..0b9add1 100644 --- a/src/vm/stacksampler.h +++ b/src/vm/stacksampler.h @@ -21,7 +21,7 @@ class StackSampler public: // Interface static void Init(); - static void RecordJittingInfo(MethodDesc* pMD, DWORD dwFlags, DWORD dwFlags2); + static void RecordJittingInfo(MethodDesc* pMD, CORJIT_FLAGS flags); private: @@ -41,7 +41,7 @@ private: void JitAndCollectTrace(MethodDesc* pMD, const ADID& adId); - void RecordJittingInfoInternal(MethodDesc* pMD, DWORD flags); + void RecordJittingInfoInternal(MethodDesc* pMD, CORJIT_FLAGS flags); ADID GetDomainId(MethodDesc* pMD, const ADID& defaultId); diff --git a/src/vm/stackwalk.cpp b/src/vm/stackwalk.cpp index 3b0b472..18a8900 100644 --- a/src/vm/stackwalk.cpp +++ b/src/vm/stackwalk.cpp @@ -2416,7 +2416,7 @@ StackWalkAction StackFrameIterator::NextRaw(void) OBJECTREF orUnwind = NULL; if (m_crawl.GetCodeManager()->IsInSynchronizedRegion(m_crawl.GetRelOffset(), - m_crawl.GetGCInfo(), + m_crawl.GetGCInfoToken(), m_crawl.GetCodeManagerFlags())) { if (pMD->IsStatic()) @@ -2560,7 +2560,9 @@ StackWalkAction StackFrameIterator::NextRaw(void) // to recover from AVs during profiler stackwalk.) PTR_VOID newSP = PTR_VOID((TADDR)GetRegdisplaySP(m_crawl.pRD)); +#ifndef NO_FIXED_STACK_LIMIT FAIL_IF_SPECULATIVE_WALK(newSP >= m_crawl.pThread->GetCachedStackLimit()); +#endif // !NO_FIXED_STACK_LIMIT FAIL_IF_SPECULATIVE_WALK(newSP < m_crawl.pThread->GetCachedStackBase()); #undef FAIL_IF_SPECULATIVE_WALK @@ -2675,7 +2677,7 @@ StackWalkAction StackFrameIterator::NextRaw(void) // We are transitioning from unmanaged code to managed code... lets do some validation of our // EH mechanism on platforms that we can. -#if defined(_DEBUG) && !defined(DACCESS_COMPILE) && defined(_TARGET_X86_) +#if defined(_DEBUG) && !defined(DACCESS_COMPILE) && (defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL)) VerifyValidTransitionFromManagedCode(m_crawl.pThread, &m_crawl); #endif // _DEBUG && !DACCESS_COMPILE && _TARGET_X86_ } @@ -3158,7 +3160,7 @@ void StackFrameIterator::PreProcessingForManagedFrames(void) m_crawl.pFunc->IsSynchronized() && !m_crawl.pFunc->IsStatic() && m_crawl.GetCodeManager()->IsInSynchronizedRegion(m_crawl.GetRelOffset(), - m_crawl.GetGCInfo(), + m_crawl.GetGCInfoToken(), m_crawl.GetCodeManagerFlags())) { BEGIN_GCX_ASSERT_COOP; diff --git a/src/vm/stackwalk.h b/src/vm/stackwalk.h index 004d673..f8bd519 100644 --- a/src/vm/stackwalk.h +++ b/src/vm/stackwalk.h @@ -36,14 +36,14 @@ class AppDomain; // on the stack. The FEF is used for unwinding. If not defined, the unwinding // uses the exception context. #define USE_FEF // to mark where code needs to be changed to eliminate the FEF -#if defined(_TARGET_X86_) +#if defined(_TARGET_X86_) && !defined(FEATURE_PAL) #undef USE_FEF // Turn off the FEF use on x86. #define ELIMINATE_FEF #else #if defined(ELIMINATE_FEF) #undef ELIMINATE_FEF #endif -#endif // _86_ +#endif // _TARGET_X86_ && !FEATURE_PAL //************************************************************************ // Enumerate all functions. diff --git a/src/vm/stubcache.h b/src/vm/stubcache.h index 781d46c..b42ed16 100644 --- a/src/vm/stubcache.h +++ b/src/vm/stubcache.h @@ -50,7 +50,7 @@ public: //--------------------------------------------------------- // Destructor //--------------------------------------------------------- - ~StubCacheBase(); + virtual ~StubCacheBase(); //--------------------------------------------------------- // Returns the equivalent hashed Stub, creating a new hash diff --git a/src/vm/stubgen.cpp b/src/vm/stubgen.cpp index fffa52a..18a6c19 100644 --- a/src/vm/stubgen.cpp +++ b/src/vm/stubgen.cpp @@ -631,15 +631,7 @@ ILStubLinker::LogILStubWorker( } } -static inline void LogOneFlag(DWORD flags, DWORD flag, LPCSTR str, DWORD facility, DWORD level) -{ - if (flags & flag) - { - LOG((facility, level, str)); - } -} - -static void LogJitFlags(DWORD facility, DWORD level, DWORD dwJitFlags) +static void LogJitFlags(DWORD facility, DWORD level, CORJIT_FLAGS jitFlags) { CONTRACTL { @@ -647,29 +639,28 @@ static void LogJitFlags(DWORD facility, DWORD level, DWORD dwJitFlags) } CONTRACTL_END; - LOG((facility, level, "dwJitFlags: 0x%08x\n", dwJitFlags)); + LOG((facility, level, "jitFlags:\n")); -#define LOG_FLAG(name) LogOneFlag(dwJitFlags, name, " " #name "\n", facility, level); +#define LOG_FLAG(name) \ + if (jitFlags.IsSet(name)) \ + { \ + LOG((facility, level, " " #name "\n")); \ + jitFlags.Clear(name); \ + } // these are all we care about at the moment - LOG_FLAG(CORJIT_FLG_IL_STUB); - LOG_FLAG(CORJIT_FLG_PUBLISH_SECRET_PARAM); + LOG_FLAG(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB); + LOG_FLAG(CORJIT_FLAGS::CORJIT_FLAG_PUBLISH_SECRET_PARAM); #undef LOG_FLAGS - DWORD dwKnownMask = - CORJIT_FLG_IL_STUB | - CORJIT_FLG_PUBLISH_SECRET_PARAM | - NULL; - - DWORD dwUnknownFlags = dwJitFlags & ~dwKnownMask; - if (0 != dwUnknownFlags) + if (!jitFlags.IsEmpty()) { - LOG((facility, level, "UNKNOWN FLAGS: 0x%08x\n", dwUnknownFlags)); + LOG((facility, level, "UNKNOWN FLAGS also set\n")); } } -void ILStubLinker::LogILStub(DWORD dwJitFlags, SString *pDumpILStubCode) +void ILStubLinker::LogILStub(CORJIT_FLAGS jitFlags, SString *pDumpILStubCode) { CONTRACTL { @@ -683,7 +674,7 @@ void ILStubLinker::LogILStub(DWORD dwJitFlags, SString *pDumpILStubCode) INT iCurStack = 0; if (pDumpILStubCode == NULL) - LogJitFlags(LF_STUBS, LL_INFO1000, dwJitFlags); + LogJitFlags(LF_STUBS, LL_INFO1000, jitFlags); while (pCurrentStream) { @@ -841,7 +832,7 @@ size_t ILStubLinker::Link(UINT* puMaxStack) #ifdef _DEBUG if (fStackUnderflow) { - LogILStub(NULL); + LogILStub(CORJIT_FLAGS()); CONSISTENCY_CHECK_MSG(false, "IL stack underflow! -- see logging output"); } #endif // _DEBUG diff --git a/src/vm/stubgen.h b/src/vm/stubgen.h index e6d3f9e..7bebfa7 100644 --- a/src/vm/stubgen.h +++ b/src/vm/stubgen.h @@ -431,7 +431,7 @@ public: void ClearCodeStreams(); - void LogILStub(DWORD dwJitFlags, SString *pDumpILStubCode = NULL); + void LogILStub(CORJIT_FLAGS jitFlags, SString *pDumpILStubCode = NULL); protected: void LogILStubWorker(ILInstruction* pInstrBuffer, UINT numInstr, size_t* pcbCode, INT* piCurStack, SString *pDumpILStubCode = NULL); void LogILInstruction(size_t curOffset, bool isLabeled, INT iCurStack, ILInstruction* pInstruction, SString *pDumpILStubCode = NULL); diff --git a/src/vm/stubhelpers.cpp b/src/vm/stubhelpers.cpp index 6e7fb49..cbe1d37 100644 --- a/src/vm/stubhelpers.cpp +++ b/src/vm/stubhelpers.cpp @@ -19,7 +19,7 @@ #include "security.h" #include "eventtrace.h" #include "comdatetime.h" -#include "gc.h" +#include "gcheaputilities.h" #include "interoputil.h" #include "gcscan.h" #ifdef FEATURE_REMOTING @@ -70,7 +70,7 @@ void StubHelpers::ValidateObjectInternal(Object *pObjUNSAFE, BOOL fValidateNextO // and the next object as required if (fValidateNextObj) { - Object *nextObj = GCHeap::GetGCHeap()->NextObj(pObjUNSAFE); + Object *nextObj = GCHeapUtilities::GetGCHeap()->NextObj(pObjUNSAFE); if (nextObj != NULL) { // Note that the MethodTable of the object (i.e. the pointer at offset 0) can change from @@ -162,7 +162,7 @@ void StubHelpers::ProcessByrefValidationList() { entry = s_ByrefValidationEntries[i]; - Object *pObjUNSAFE = GCHeap::GetGCHeap()->GetGCHeap()->GetContainingObject(entry.pByref); + Object *pObjUNSAFE = GCHeapUtilities::GetGCHeap()->GetContainingObject(entry.pByref); ValidateObjectInternal(pObjUNSAFE, TRUE); } } @@ -2004,7 +2004,7 @@ FCIMPL3(void, StubHelpers::ValidateObject, Object *pObjUNSAFE, MethodDesc *pMD, AVInRuntimeImplOkayHolder AVOkay; // don't validate the next object if a BGC is in progress. we can race with background // sweep which could make the next object a Free object underneath us if it's dead. - ValidateObjectInternal(pObjUNSAFE, !(GCHeap::GetGCHeap()->IsConcurrentGCInProgress())); + ValidateObjectInternal(pObjUNSAFE, !(GCHeapUtilities::GetGCHeap()->IsConcurrentGCInProgress())); } EX_CATCH { @@ -2031,7 +2031,7 @@ FCIMPL3(void, StubHelpers::ValidateByref, void *pByref, MethodDesc *pMD, Object // perform the validation on next GC (see code:StubHelpers.ProcessByrefValidationList). // Skip byref if is not pointing inside managed heap - if (!GCHeap::GetGCHeap()->IsHeapPointer(pByref)) + if (!GCHeapUtilities::GetGCHeap()->IsHeapPointer(pByref)) { return; } @@ -2066,7 +2066,7 @@ FCIMPL3(void, StubHelpers::ValidateByref, void *pByref, MethodDesc *pMD, Object if (NumOfEntries > BYREF_VALIDATION_LIST_MAX_SIZE) { // if the list is too big, trigger GC now - GCHeap::GetGCHeap()->GarbageCollect(0); + GCHeapUtilities::GetGCHeap()->GarbageCollect(0); } HELPER_METHOD_FRAME_END(); diff --git a/src/vm/syncblk.cpp b/src/vm/syncblk.cpp index 3975542..171a8d3 100644 --- a/src/vm/syncblk.cpp +++ b/src/vm/syncblk.cpp @@ -1372,7 +1372,7 @@ void SyncBlockCache::GCWeakPtrScan(HANDLESCANPROC scanProc, uintptr_t lp1, uintp STRESS_LOG0 (LF_GC | LF_SYNC, LL_INFO100, "GCWeakPtrScan starting\n"); #endif - if (GCHeap::GetGCHeap()->GetCondemnedGeneration() < GCHeap::GetGCHeap()->GetMaxGeneration()) + if (GCHeapUtilities::GetGCHeap()->GetCondemnedGeneration() < GCHeapUtilities::GetGCHeap()->GetMaxGeneration()) { #ifdef VERIFY_HEAP //for VSW 294550: we saw stale obeject reference in SyncBlkCache, so we want to make sure the card @@ -1416,7 +1416,7 @@ void SyncBlockCache::GCWeakPtrScan(HANDLESCANPROC scanProc, uintptr_t lp1, uintp Object* o = SyncTableEntry::GetSyncTableEntry()[nb].m_Object; if (o && !((size_t)o & 1)) { - if (GCHeap::GetGCHeap()->IsEphemeral (o)) + if (GCHeapUtilities::GetGCHeap()->IsEphemeral (o)) { clear_card = FALSE; @@ -1615,8 +1615,8 @@ void SyncBlockCache::GCDone(BOOL demoting, int max_gen) CONTRACTL_END; if (demoting && - (GCHeap::GetGCHeap()->GetCondemnedGeneration() == - GCHeap::GetGCHeap()->GetMaxGeneration())) + (GCHeapUtilities::GetGCHeap()->GetCondemnedGeneration() == + GCHeapUtilities::GetGCHeap()->GetMaxGeneration())) { //scan the bitmap size_t dw = 0; @@ -1643,7 +1643,7 @@ void SyncBlockCache::GCDone(BOOL demoting, int max_gen) Object* o = SyncTableEntry::GetSyncTableEntry()[nb].m_Object; if (o && !((size_t)o & 1)) { - if (GCHeap::GetGCHeap()->WhichGeneration (o) < (unsigned int)max_gen) + if (GCHeapUtilities::GetGCHeap()->WhichGeneration (o) < (unsigned int)max_gen) { SetCard (card); break; @@ -1713,7 +1713,7 @@ void SyncBlockCache::VerifySyncTableEntry() DWORD idx = o->GetHeader()->GetHeaderSyncBlockIndex(); _ASSERTE(idx == nb || ((0 == idx) && (loop == max_iterations))); - _ASSERTE(!GCHeap::GetGCHeap()->IsEphemeral(o) || CardSetP(CardOf(nb))); + _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsEphemeral(o) || CardSetP(CardOf(nb))); } } } @@ -2498,10 +2498,10 @@ BOOL ObjHeader::Validate (BOOL bVerifySyncBlkIndex) //BIT_SBLK_GC_RESERVE (0x20000000) is only set during GC. But for frozen object, we don't clean the bit if (bits & BIT_SBLK_GC_RESERVE) { - if (!GCHeap::GetGCHeap()->IsGCInProgress () && !GCHeap::GetGCHeap()->IsConcurrentGCInProgress ()) + if (!GCHeapUtilities::IsGCInProgress () && !GCHeapUtilities::GetGCHeap()->IsConcurrentGCInProgress ()) { #ifdef FEATURE_BASICFREEZE - ASSERT_AND_CHECK (GCHeap::GetGCHeap()->IsInFrozenSegment(obj)); + ASSERT_AND_CHECK (GCHeapUtilities::GetGCHeap()->IsInFrozenSegment(obj)); #else //FEATURE_BASICFREEZE _ASSERTE(!"Reserve bit not cleared"); return FALSE; diff --git a/src/vm/syncclean.cpp b/src/vm/syncclean.cpp index e02c2f9..133f448 100644 --- a/src/vm/syncclean.cpp +++ b/src/vm/syncclean.cpp @@ -73,7 +73,7 @@ void SyncClean::CleanUp () // Only GC thread can call this. _ASSERTE (g_fProcessDetach || IsGCSpecialThread() || - (GCHeap::IsGCInProgress() && GetThread() == ThreadSuspend::GetSuspensionThread())); + (GCHeapUtilities::IsGCInProgress() && GetThread() == ThreadSuspend::GetSuspensionThread())); if (m_HashMap) { Bucket * pTempBucket = FastInterlockExchangePointer(m_HashMap.GetPointer(), NULL); diff --git a/src/vm/testhookmgr.cpp b/src/vm/testhookmgr.cpp index 9ec53f8..4837013 100644 --- a/src/vm/testhookmgr.cpp +++ b/src/vm/testhookmgr.cpp @@ -655,7 +655,7 @@ HRESULT CLRTestHookManager::GC(int generation) CONTRACTL_END; _ASSERTE(GetThread()==NULL || !GetThread()->PreemptiveGCDisabled()); - GCHeap::GetGCHeap()->GarbageCollect(generation); + GCHeapUtilities::GetGCHeap()->GarbageCollect(generation); FinalizerThread::FinalizerThreadWait(); return S_OK; } diff --git a/src/vm/threadpoolrequest.cpp b/src/vm/threadpoolrequest.cpp index 8d47e6b..a5c1c42 100644 --- a/src/vm/threadpoolrequest.cpp +++ b/src/vm/threadpoolrequest.cpp @@ -517,11 +517,11 @@ void UnManagedPerAppDomainTPCount::DispatchWorkItem(bool* foundWork, bool* wasNo firstIteration = false; *foundWork = true; - if (GCHeap::IsGCInProgress(TRUE)) + if (GCHeapUtilities::IsGCInProgress(TRUE)) { // GC is imminent, so wait until GC is complete before executing next request. // this reduces in-flight objects allocated right before GC, easing the GC's work - GCHeap::WaitForGCCompletion(TRUE); + GCHeapUtilities::WaitForGCCompletion(TRUE); } PREFIX_ASSUME(pWorkRequest != NULL); diff --git a/src/vm/threads.cpp b/src/vm/threads.cpp index cc2e4eb..38094ca 100644 --- a/src/vm/threads.cpp +++ b/src/vm/threads.cpp @@ -18,7 +18,7 @@ #include "excep.h" #include "comsynchronizable.h" #include "log.h" -#include "gc.h" +#include "gcheaputilities.h" #include "mscoree.h" #include "dbginterface.h" #include "corprof.h" // profiling @@ -2022,8 +2022,10 @@ Thread::Thread() m_ppvHJRetAddrPtr = (VOID**) 0xCCCCCCCCCCCCCCCC; m_pvHJRetAddr = (VOID*) 0xCCCCCCCCCCCCCCCC; +#ifndef PLATFORM_UNIX X86_ONLY(m_LastRedirectIP = 0); X86_ONLY(m_SpinCount = 0); +#endif // PLATFORM_UNIX #endif // FEATURE_HIJACK #if defined(_DEBUG) && defined(TRACK_SYNC) @@ -2232,7 +2234,7 @@ Thread::Thread() m_fGCSpecial = FALSE; -#if !defined(FEATURE_CORECLR) +#if !defined(FEATURE_PAL) m_wCPUGroup = 0; m_pAffinityMask = 0; #endif @@ -3889,14 +3891,14 @@ void Thread::OnThreadTerminate(BOOL holdingLock) #endif } - if (GCHeap::IsGCHeapInitialized()) + if (GCHeapUtilities::IsGCHeapInitialized()) { // Guaranteed to NOT be a shutdown case, because we tear down the heap before // we tear down any threads during shutdown. if (ThisThreadID == CurrentThreadID) { GCX_COOP(); - GCHeap::GetGCHeap()->FixAllocContext(&m_alloc_context, FALSE, NULL, NULL); + GCHeapUtilities::GetGCHeap()->FixAllocContext(&m_alloc_context, FALSE, NULL, NULL); m_alloc_context.init(); } } @@ -3957,11 +3959,11 @@ void Thread::OnThreadTerminate(BOOL holdingLock) #endif } - if (GCHeap::IsGCHeapInitialized() && ThisThreadID != CurrentThreadID) + if (GCHeapUtilities::IsGCHeapInitialized() && ThisThreadID != CurrentThreadID) { // We must be holding the ThreadStore lock in order to clean up alloc context. // We should never call FixAllocContext during GC. - GCHeap::GetGCHeap()->FixAllocContext(&m_alloc_context, FALSE, NULL, NULL); + GCHeapUtilities::GetGCHeap()->FixAllocContext(&m_alloc_context, FALSE, NULL, NULL); m_alloc_context.init(); } @@ -8245,7 +8247,9 @@ void CheckRegDisplaySP (REGDISPLAY *pRD) { if (pRD->SP && pRD->_pThread) { +#ifndef NO_FIXED_STACK_LIMIT _ASSERTE(PTR_VOID(pRD->SP) >= pRD->_pThread->GetCachedStackLimit()); +#endif // NO_FIXED_STACK_LIMIT _ASSERTE(PTR_VOID(pRD->SP) < pRD->_pThread->GetCachedStackBase()); } } @@ -9159,89 +9163,7 @@ void Thread::ReturnToContextAndOOM(ContextTransitionFrame* pFrame) COMPlusThrowOM(); } - -#ifdef FEATURE_CORECLR - -//--------------------------------------------------------------------------------------- -// Allocates an agile CrossAppDomainMarshaledException whose ToString() and ErrorCode -// matches the original exception. -// -// This is our "remoting" story for exceptions that leak across appdomains in Telesto. -//--------------------------------------------------------------------------------------- -static OBJECTREF WrapThrowableInCrossAppDomainMarshaledException(OBJECTREF pOriginalThrowable) -{ - CONTRACTL - { - GC_TRIGGERS; - THROWS; - MODE_COOPERATIVE; - } - CONTRACTL_END; - - _ASSERTE(GetThread() != NULL); - - - struct _gc - { - OBJECTREF pOriginalThrowable; - OBJECTREF pThrowable; - STRINGREF pOriginalMessage; - } - prot; - - - memset(&prot, 0, sizeof(prot)); - - GCPROTECT_BEGIN(prot); - prot.pOriginalThrowable = pOriginalThrowable; - prot.pOriginalMessage = GetExceptionMessage(prot.pOriginalThrowable); - HRESULT originalHResult = GetExceptionHResult(prot.pOriginalThrowable); - - MethodTable *pMT = MscorlibBinder::GetClass(CLASS__CROSSAPPDOMAINMARSHALEDEXCEPTION); - prot.pThrowable = AllocateObject(pMT); - - MethodDescCallSite exceptionCtor(METHOD__CROSSAPPDOMAINMARSHALEDEXCEPTION__STR_INT_CTOR); - - ARG_SLOT args1[] = { - ObjToArgSlot(prot.pThrowable), - ObjToArgSlot(prot.pOriginalMessage), - (ARG_SLOT)originalHResult, - }; - exceptionCtor.Call(args1); - -#ifndef FEATURE_PAL - // Since, on CoreCLR, we dont have serialization of exceptions going across - // AD transition boundaries, we will copy over the bucket details to the - // CrossAppDomainMarshalledException object from the original exception object - // if it isnt a preallocated exception. - if (IsWatsonEnabled() && (!CLRException::IsPreallocatedExceptionObject(prot.pOriginalThrowable))) - { - // If the watson buckets are present, then copy them over. - // They maybe missing if the original throwable couldnt get them from Watson helper functions - // during SetupInitialThrowBucketDetails due to OOM. - if (((EXCEPTIONREF)prot.pOriginalThrowable)->AreWatsonBucketsPresent()) - { - _ASSERTE(prot.pThrowable != NULL); - // Copy them to CrossADMarshalledException object - CopyWatsonBucketsBetweenThrowables(prot.pOriginalThrowable, prot.pThrowable); - - // The exception object should now have the buckets inside it - _ASSERTE(((EXCEPTIONREF)prot.pThrowable)->AreWatsonBucketsPresent()); - } - } -#endif // !FEATURE_PAL - - GCPROTECT_END(); //Prot - - - return prot.pThrowable; -} - - - -#endif - - +#ifdef FEATURE_REMOTING // for cases when marshaling is not needed // throws it is able to take a shortcut, otherwise just returns void Thread::RaiseCrossContextExceptionHelper(Exception* pEx, ContextTransitionFrame* pFrame) @@ -9411,15 +9333,7 @@ Thread::TryRaiseCrossContextException(Exception **ppExOrig, *ppThrowable = CLRException::GetThrowableFromException(exception); _ASSERTE(*ppThrowable != NULL); -#ifdef FEATURE_CORECLR - (*pOrBlob) = WrapThrowableInCrossAppDomainMarshaledException(*ppThrowable); -#if CHECK_APP_DOMAIN_LEAKS - (*pOrBlob)->SetAppDomainAgile(); -#endif //CHECK_APP_DOMAIN_LEAKS -#else AppDomainHelper::MarshalObject(ppThrowable, pOrBlob); -#endif //FEATURE_CORECLR - } } EX_CATCH @@ -9598,6 +9512,25 @@ void DECLSPEC_NORETURN Thread::RaiseCrossContextException(Exception* pExOrig, Co } } +#else // FEATURE_REMOTING + +void DECLSPEC_NORETURN Thread::RaiseCrossContextException(Exception* pExOrig, ContextTransitionFrame* pFrame) +{ + CONTRACTL + { + THROWS; + WRAPPER(GC_TRIGGERS); + } + CONTRACTL_END; + + // pEx is NULL means that the exception is CLRLastThrownObjectException + CLRLastThrownObjectException lastThrown; + Exception* pException = pExOrig ? pExOrig : &lastThrown; + COMPlusThrow(CLRException::GetThrowableFromException(pException)); +} + +#endif + struct FindADCallbackType { AppDomain *pSearchDomain; AppDomain *pPrevDomain; @@ -9846,7 +9779,7 @@ void Thread::DoExtraWorkForFinalizer() Thread::CleanupDetachedThreads(); } - if(ExecutionManager::IsCacheCleanupRequired() && GCHeap::GetGCHeap()->GetCondemnedGeneration()>=1) + if(ExecutionManager::IsCacheCleanupRequired() && GCHeapUtilities::GetGCHeap()->GetCondemnedGeneration()>=1) { ExecutionManager::ClearCaches(); } @@ -11186,7 +11119,7 @@ void Thread::SetHasPromotedBytes () m_fPromoted = TRUE; - _ASSERTE(GCHeap::IsGCInProgress() && IsGCThread ()); + _ASSERTE(GCHeapUtilities::IsGCInProgress() && IsGCThread ()); if (!m_fPreemptiveGCDisabled) { @@ -11616,7 +11549,7 @@ HRESULT Thread::GetMemStats (COR_GC_THREAD_STATS *pStats) CONTRACTL_END; // Get the allocation context which contains this counter in it. - alloc_context *p = &m_alloc_context; + gc_alloc_context *p = &m_alloc_context; pStats->PerThreadAllocation = p->alloc_bytes + p->alloc_bytes_loh; if (GetHasPromotedBytes()) pStats->Flags = COR_GC_THREAD_HAS_PROMOTED_BYTES; diff --git a/src/vm/threads.h b/src/vm/threads.h index ec047f2..144e17c 100644 --- a/src/vm/threads.h +++ b/src/vm/threads.h @@ -142,7 +142,7 @@ #include "regdisp.h" #include "mscoree.h" #include "appdomainstack.h" -#include "gc.h" +#include "gcheaputilities.h" #include "gcinfotypes.h" #include @@ -1072,7 +1072,7 @@ class Thread: public IUnknown friend DWORD MapWin32FaultToCOMPlusException(EXCEPTION_RECORD *pExceptionRecord); friend void STDCALL OnHijackWorker(HijackArgs * pArgs); #ifdef PLATFORM_UNIX - friend void PALAPI HandleGCSuspensionForInterruptedThread(CONTEXT *interruptedContext); + friend void HandleGCSuspensionForInterruptedThread(CONTEXT *interruptedContext); #endif // PLATFORM_UNIX #endif // FEATURE_HIJACK @@ -1739,9 +1739,9 @@ public: // on MP systems, each thread has its own allocation chunk so we can avoid // lock prefixes and expensive MP cache snooping stuff - alloc_context m_alloc_context; + gc_alloc_context m_alloc_context; - inline alloc_context *GetAllocContext() { LIMITED_METHOD_CONTRACT; return &m_alloc_context; } + inline gc_alloc_context *GetAllocContext() { LIMITED_METHOD_CONTRACT; return &m_alloc_context; } // This is the type handle of the first object in the alloc context at the time // we fire the AllocationTick event. It's only for tooling purpose. @@ -2796,7 +2796,8 @@ public: CONTRACTL_END; return (ObjectFromHandle(m_ExposedObject) != NULL) ; } -#ifndef FEATURE_CORECLR + +#ifdef FEATURE_SYNCHRONIZATIONCONTEXT_WAIT void GetSynchronizationContext(OBJECTREF *pSyncContextObj) { CONTRACTL @@ -2814,7 +2815,8 @@ public: if (ExposedThreadObj != NULL) *pSyncContextObj = ExposedThreadObj->GetSynchronizationContext(); } -#endif //!FEATURE_CORECLR +#endif // FEATURE_SYNCHRONIZATIONCONTEXT_WAIT + #ifdef FEATURE_COMPRESSEDSTACK OBJECTREF GetCompressedStack() { @@ -4884,7 +4886,7 @@ private: private: // When we create an object, or create an OBJECTREF, or create an Interior Pointer, or enter EE from managed // code, we will set this flag. - // Inside GCHeap::StressHeap, we only do GC if this flag is TRUE. Then we reset it to zero. + // Inside GCHeapUtilities::StressHeap, we only do GC if this flag is TRUE. Then we reset it to zero. BOOL m_fStressHeapCount; public: void EnableStressHeap() diff --git a/src/vm/threadsuspend.cpp b/src/vm/threadsuspend.cpp index c71855f..2e6563d 100644 --- a/src/vm/threadsuspend.cpp +++ b/src/vm/threadsuspend.cpp @@ -754,6 +754,7 @@ static StackWalkAction TAStackCrawlCallBackWorker(CrawlFrame* pCf, StackCrawlCon } #undef METHODNAME +#ifdef FEATURE_CER // If we're asking about CERs and we don't yet have a definite answer either way then take a closer look at the current method. if (pData->eType & StackCrawlContext::SCC_CheckWithinCer && !pData->fUnprotectedCode && !pData->fWithinCer) { @@ -775,6 +776,7 @@ static StackWalkAction TAStackCrawlCallBackWorker(CrawlFrame* pCf, StackCrawlCon pData->fUnprotectedCode = true; } } +#endif // FEATURE_CER // If we weren't asked about EH clauses then we can return now (stop the stack trace if we have a definitive answer on the CER // question, move to the next frame otherwise). @@ -1122,6 +1124,7 @@ struct CerStackCrawlContext bool m_fWithinCer; // The result }; +#ifdef FEATURE_CER // Callback used on the stack crawl described above. StackWalkAction CerStackCrawlCallBack(CrawlFrame *pCf, void *pData) { @@ -1164,6 +1167,7 @@ StackWalkAction CerStackCrawlCallBack(CrawlFrame *pCf, void *pData) // Otherwise everything looks OK so far and we need to investigate the next frame. return SWA_CONTINUE; } +#endif // FEATURE_CER // Determine whether the method at the given depth in the thread's execution stack is executing within a CER. BOOL Thread::IsWithinCer(CrawlFrame *pCf) @@ -1175,6 +1179,9 @@ BOOL Thread::IsWithinCer(CrawlFrame *pCf) } CONTRACTL_END; +#ifndef FEATURE_CER + return FALSE; +#else // There had better be a method associated with this frame. MethodDesc *pMD = pCf->GetFunction(); _ASSERTE(pMD != NULL); @@ -1291,6 +1298,7 @@ BOOL Thread::IsWithinCer(CrawlFrame *pCf) _ASSERTE(!sContext.m_fFirstFrame); return sContext.m_fWithinCer; +#endif // FEATURE_CER } #if defined(_TARGET_AMD64_) && defined(FEATURE_HIJACK) @@ -3276,7 +3284,7 @@ void Thread::RareDisablePreemptiveGC() __SwitchToThread(0, CALLER_LIMITS_SPINNING); } - if (!GCHeap::IsGCHeapInitialized()) + if (!GCHeapUtilities::IsGCHeapInitialized()) { goto Exit; } @@ -3284,7 +3292,7 @@ void Thread::RareDisablePreemptiveGC() // Note IsGCInProgress is also true for say Pause (anywhere SuspendEE happens) and GCThread is the // thread that did the Pause. While in Pause if another thread attempts Rev/Pinvoke it should get inside the following and // block until resume - if (((GCHeap::IsGCInProgress() && (this != ThreadSuspend::GetSuspensionThread())) || + if (((GCHeapUtilities::IsGCInProgress() && (this != ThreadSuspend::GetSuspensionThread())) || (m_State & (TS_UserSuspendPending | TS_DebugSuspendPending | TS_StackCrawlNeeded))) && (!g_fSuspendOnShutdown || IsFinalizerThread() || IsShutdownSpecialThread())) { @@ -3350,7 +3358,7 @@ void Thread::RareDisablePreemptiveGC() DWORD status = S_OK; SetThreadStateNC(TSNC_WaitUntilGCFinished); - status = GCHeap::GetGCHeap()->WaitUntilGCComplete(); + status = GCHeapUtilities::GetGCHeap()->WaitUntilGCComplete(); ResetThreadStateNC(TSNC_WaitUntilGCFinished); if (status == (DWORD)COR_E_STACKOVERFLOW) @@ -3359,7 +3367,7 @@ void Thread::RareDisablePreemptiveGC() // 1. GC is suspending the process. GC needs to wait. // 2. GC is proceeding after suspension. The current thread needs to spin. SetThreadState(TS_BlockGCForSO); - while (GCHeap::IsGCInProgress() && m_fPreemptiveGCDisabled.Load() == 0) + while (GCHeapUtilities::IsGCInProgress() && m_fPreemptiveGCDisabled.Load() == 0) { #undef Sleep // We can not go to a host for blocking operation due ot lack of stack. @@ -3376,7 +3384,7 @@ void Thread::RareDisablePreemptiveGC() break; } } - if (!GCHeap::IsGCInProgress()) + if (!GCHeapUtilities::IsGCInProgress()) { if (HasThreadState(TS_StackCrawlNeeded)) { @@ -3411,7 +3419,7 @@ void Thread::RareDisablePreemptiveGC() // thread while in this loop. This happens if you use the COM+ // debugger to suspend this thread and then release it. - } while ((GCHeap::IsGCInProgress() && (this != ThreadSuspend::GetSuspensionThread())) || + } while ((GCHeapUtilities::IsGCInProgress() && (this != ThreadSuspend::GetSuspensionThread())) || (m_State & (TS_UserSuspendPending | TS_DebugSuspendPending | TS_StackCrawlNeeded))); } STRESS_LOG0(LF_SYNC, LL_INFO1000, "RareDisablePreemptiveGC: leaving\n"); @@ -3705,7 +3713,7 @@ void Thread::PerformPreemptiveGC() if (!GCStressPolicy::IsEnabled() || !GCStress::IsEnabled()) return; - if (!GCHeap::IsGCHeapInitialized()) + if (!GCHeapUtilities::IsGCHeapInitialized()) return; if (!m_GCOnTransitionsOK @@ -3713,8 +3721,8 @@ void Thread::PerformPreemptiveGC() || RawGCNoTrigger() #endif || g_fEEShutDown - || GCHeap::IsGCInProgress(TRUE) - || GCHeap::GetGCHeap()->GetGcCount() == 0 // Need something that works for isolated heap. + || GCHeapUtilities::IsGCInProgress(TRUE) + || GCHeapUtilities::GetGCHeap()->GetGcCount() == 0 // Need something that works for isolated heap. || ThreadStore::HoldingThreadStore()) return; @@ -3738,7 +3746,7 @@ void Thread::PerformPreemptiveGC() { GCX_COOP(); m_bGCStressing = TRUE; - GCHeap::GetGCHeap()->StressHeap(); + GCHeapUtilities::GetGCHeap()->StressHeap(); m_bGCStressing = FALSE; } m_GCOnTransitionsOK = TRUE; @@ -4846,7 +4854,7 @@ HRESULT ThreadSuspend::SuspendRuntime(ThreadSuspend::SUSPEND_REASON reason) // Caller is expected to be holding the ThreadStore lock. Also, caller must // have set GcInProgress before coming here, or things will break; _ASSERTE(ThreadStore::HoldingThreadStore() || IsAtProcessExit()); - _ASSERTE(GCHeap::IsGCInProgress() ); + _ASSERTE(GCHeapUtilities::IsGCInProgress() ); STRESS_LOG1(LF_SYNC, LL_INFO1000, "Thread::SuspendRuntime(reason=0x%x)\n", reason); @@ -5547,7 +5555,7 @@ void ThreadSuspend::ResumeRuntime(BOOL bFinishedGC, BOOL SuspendSucceded) // reset GcInProgress, or threads will continue to suspend themselves and won't // be resumed until the next GC. _ASSERTE(IsGCSpecialThread() || ThreadStore::HoldingThreadStore()); - _ASSERTE(!GCHeap::IsGCInProgress() ); + _ASSERTE(!GCHeapUtilities::IsGCInProgress() ); STRESS_LOG2(LF_SYNC, LL_INFO1000, "Thread::ResumeRuntime(finishedGC=%d, SuspendSucceeded=%d) - Start\n", bFinishedGC, SuspendSucceded); @@ -5564,7 +5572,7 @@ void ThreadSuspend::ResumeRuntime(BOOL bFinishedGC, BOOL SuspendSucceded) { // If we the suspension was for a GC, tell the host what generation GC. DWORD Generation = (bFinishedGC - ? GCHeap::GetGCHeap()->GetCondemnedGeneration() + ? GCHeapUtilities::GetGCHeap()->GetCondemnedGeneration() : ~0U); pGCThreadControl->SuspensionEnding(Generation); @@ -5574,7 +5582,7 @@ void ThreadSuspend::ResumeRuntime(BOOL bFinishedGC, BOOL SuspendSucceded) { // If we the suspension was for a GC, tell the host what generation GC. DWORD Generation = (bFinishedGC - ? GCHeap::GetGCHeap()->GetCondemnedGeneration() + ? GCHeapUtilities::GetGCHeap()->GetCondemnedGeneration() : ~0U); BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread()); @@ -7275,18 +7283,8 @@ ReturnKind GetReturnKindFromMethodTable(Thread *pThread, EECodeInfo *codeInfo) ReturnKind GetReturnKind(Thread *pThread, EECodeInfo *codeInfo) { - ReturnKind returnKind = RT_Illegal; - -#ifdef _TARGET_X86_ - // X86 GCInfo updates yet to be implemented. -#else GCInfoToken gcInfoToken = codeInfo->GetGCInfoToken(); - if (gcInfoToken.IsReturnKindAvailable()) - { - GcInfoDecoder gcInfoDecoder(gcInfoToken, DECODE_RETURN_KIND); - returnKind = gcInfoDecoder.GetReturnKind(); - } -#endif // _TARGET_X86_ + ReturnKind returnKind = codeInfo->GetCodeManager()->GetReturnKind(gcInfoToken); if (!IsValidReturnKind(returnKind)) { @@ -7312,7 +7310,7 @@ VOID * GetHijackAddr(Thread *pThread, EECodeInfo *codeInfo) #ifdef _TARGET_X86_ if (returnKind == RT_Float) { - return reinterpret_cast(OnHijackTripThread); + return reinterpret_cast(OnHijackFPTripThread); } #endif // _TARGET_X86_ @@ -7898,7 +7896,7 @@ void ThreadSuspend::RestartEE(BOOL bFinishedGC, BOOL SuspendSucceded) // Revert to being a normal thread // ClrFlsClearThreadType (ThreadType_DynamicSuspendEE); - GCHeap::GetGCHeap()->SetGCInProgress(FALSE); + GCHeapUtilities::GetGCHeap()->SetGCInProgress(FALSE); // // Allow threads to enter COOP mode (though we still need to wake the ones @@ -7906,7 +7904,7 @@ void ThreadSuspend::RestartEE(BOOL bFinishedGC, BOOL SuspendSucceded) // // Note: this is the last barrier that keeps managed threads // from entering cooperative mode. If the sequence changes, - // you may have to change routine GCHeap::SafeToRestartManagedThreads + // you may have to change routine GCHeapUtilities::SafeToRestartManagedThreads // as well. // ThreadStore::TrapReturningThreads(FALSE); @@ -7915,7 +7913,7 @@ void ThreadSuspend::RestartEE(BOOL bFinishedGC, BOOL SuspendSucceded) // // Any threads that are waiting in WaitUntilGCComplete will continue now. // - GCHeap::GetGCHeap()->GetWaitForGCEvent()->Set(); + GCHeapUtilities::GetGCHeap()->GetWaitForGCEvent()->Set(); _ASSERTE(IsGCSpecialThread() || ThreadStore::HoldingThreadStore()); ResumeRuntime(bFinishedGC, SuspendSucceded); @@ -7964,7 +7962,7 @@ void ThreadSuspend::SuspendEE(SUSPEND_REASON reason) ETW::GCLog::ETW_GC_INFO Info; Info.SuspendEE.Reason = reason; Info.SuspendEE.GcCount = (((reason == SUSPEND_FOR_GC) || (reason == SUSPEND_FOR_GC_PREP)) ? - (ULONG)GCHeap::GetGCHeap()->GetGcCount() : (ULONG)-1); + (ULONG)GCHeapUtilities::GetGCHeap()->GetGcCount() : (ULONG)-1); FireEtwGCSuspendEEBegin_V1(Info.SuspendEE.Reason, Info.SuspendEE.GcCount, GetClrInstanceId()); @@ -8041,7 +8039,7 @@ retry_for_debugger: // // First, we reset the event that we're about to tell other threads to wait for. // - GCHeap::GetGCHeap()->GetWaitForGCEvent()->Reset(); + GCHeapUtilities::GetGCHeap()->GetWaitForGCEvent()->Reset(); // // Remember that we're the one doing the GC. Actually, maybe we're not doing a GC - @@ -8066,7 +8064,7 @@ retry_for_debugger: // It seems like much of the above is redundant. We should investigate reducing the number // of mechanisms we use to indicate that a suspension is in progress. // - GCHeap::GetGCHeap()->SetGCInProgress(TRUE); + GCHeapUtilities::GetGCHeap()->SetGCInProgress(TRUE); // // Gratuitous memory barrier. (may be needed - but I'm not sure why.) @@ -8214,7 +8212,7 @@ retry_for_debugger: // This function is called by PAL to check if the specified instruction pointer // is in a function where we can safely inject activation. -BOOL PALAPI CheckActivationSafePoint(SIZE_T ip, BOOL checkingCurrentThread) +BOOL CheckActivationSafePoint(SIZE_T ip, BOOL checkingCurrentThread) { Thread *pThread = GetThread(); // It is safe to call the ExecutionManager::IsManagedCode only if we are making the check for @@ -8241,7 +8239,7 @@ BOOL PALAPI CheckActivationSafePoint(SIZE_T ip, BOOL checkingCurrentThread) // address to take the thread to the appropriate stub (based on the return // type of the method) which will then handle preparing the thread for GC. // -void PALAPI HandleGCSuspensionForInterruptedThread(CONTEXT *interruptedContext) +void HandleGCSuspensionForInterruptedThread(CONTEXT *interruptedContext) { Thread *pThread = GetThread(); @@ -8357,7 +8355,7 @@ void ThreadSuspend::Initialize() BOOL Debug_IsLockedViaThreadSuspension() { LIMITED_METHOD_CONTRACT; - return GCHeap::IsGCInProgress() && + return GCHeapUtilities::IsGCInProgress() && (dbgOnly_IsSpecialEEThread() || IsGCSpecialThread() || GetThread() == ThreadSuspend::GetSuspensionThread()); @@ -8485,7 +8483,7 @@ void SuspendStatistics::EndSuspend(BOOL bForGC) // details on suspends... if (!bForGC) cntNonGCSuspends++; - if (GCHeap::GetGCHeap()->IsConcurrentGCInProgress()) + if (GCHeapUtilities::GetGCHeap()->IsConcurrentGCInProgress()) { cntSuspendsInBGC++; if (!bForGC) diff --git a/src/vm/typeparse.cpp b/src/vm/typeparse.cpp index 356cb78..28521f1 100644 --- a/src/vm/typeparse.cpp +++ b/src/vm/typeparse.cpp @@ -364,7 +364,7 @@ HRESULT __stdcall TypeName::GetAssemblyName(BSTR* pszAssemblyName) return hr; } -#if !defined(FEATURE_CORECLR) && !defined(CROSSGEN_COMPILE) +#if!defined(CROSSGEN_COMPILE) SAFEHANDLE TypeName::GetSafeHandle() { CONTRACTL @@ -588,7 +588,7 @@ void QCALLTYPE TypeName::QGetAssemblyName(TypeName * pTypeName, QCall::StringHan END_QCALL; } -#endif //!FEATURE_CORECLR && !CROSSGEN_COMPILE +#endif//!CROSSGEN_COMPILE // // TypeName::TypeNameParser @@ -1926,7 +1926,7 @@ DomainAssembly * LoadDomainAssembly( { Exception *ex = GET_EXCEPTION(); - // Let non-File-not-found execeptions propagate + // Let non-File-not-found exceptions propagate if (EEFileLoadException::GetFileLoadKind(ex->GetHR()) != kFileNotFoundException) EX_RETHROW; } diff --git a/src/vm/typeparse.h b/src/vm/typeparse.h index bf30730..00a3349 100644 --- a/src/vm/typeparse.h +++ b/src/vm/typeparse.h @@ -311,14 +311,14 @@ public: virtual ~TypeName(); public: -#ifndef FEATURE_CORECLR +#ifndef CROSSGEN_COMPILE static void QCALLTYPE QCreateTypeNameParser (LPCWSTR wszTypeName, QCall::ObjectHandleOnStack pNames, BOOL throwOnError); static void QCALLTYPE QReleaseTypeNameParser(TypeName * pTypeName); static void QCALLTYPE QGetNames (TypeName * pTypeName, QCall::ObjectHandleOnStack pNames); static void QCALLTYPE QGetTypeArguments (TypeName * pTypeName, QCall::ObjectHandleOnStack pTypeArguments); static void QCALLTYPE QGetModifiers (TypeName * pTypeName, QCall::ObjectHandleOnStack pModifiers); static void QCALLTYPE QGetAssemblyName (TypeName * pTypeName, QCall::StringHandleOnStack pAssemblyName); -#endif //!FEATURE_CORECLR +#endif //CROSSGEN_COMPILE //------------------------------------------------------------------------------------------- // Retrieves a type from an assembly. It requires the caller to know which assembly @@ -451,10 +451,7 @@ private: return GetTypeHaveAssemblyHelper(pAssembly, bThrowIfNotFound, bIgnoreCase, pKeepAlive, TRUE); } TypeHandle GetTypeHaveAssemblyHelper(Assembly* pAssembly, BOOL bThrowIfNotFound, BOOL bIgnoreCase, OBJECTREF *pKeepAlive, BOOL bRecurse); - -#ifndef FEATURE_CORECLR SAFEHANDLE GetSafeHandle(); -#endif //!FEATURE_CORECLR private: BOOL m_bIsGenericArgument; diff --git a/src/vm/util.cpp b/src/vm/util.cpp index 2cb3460..2cf6f7f 100644 --- a/src/vm/util.cpp +++ b/src/vm/util.cpp @@ -1950,17 +1950,18 @@ size_t GetLogicalProcessorCacheSizeFromOS() // Crack the information. Iterate through all the SLPI array entries for all processors in system. // Will return the greatest of all the processor cache sizes or zero - - size_t last_cache_size = 0; - - for (DWORD i=0; i < nEntries; i++) { - if (pslpi[i].Relationship == RelationCache) + size_t last_cache_size = 0; + + for (DWORD i=0; i < nEntries; i++) { - last_cache_size = max(last_cache_size, pslpi[i].Cache.Size); - } - } - cache_size = last_cache_size; + if (pslpi[i].Relationship == RelationCache) + { + last_cache_size = max(last_cache_size, pslpi[i].Cache.Size); + } + } + cache_size = last_cache_size; + } Exit: if(pslpi) @@ -1991,6 +1992,9 @@ DWORD GetLogicalCpuCountFromOS() DWORD nEntries = 0; + DWORD prevcount = 0; + DWORD count = 1; + // Try to use GetLogicalProcessorInformation API and get a valid pointer to the SLPI array if successful. Returns NULL // if API not present or on failure. SYSTEM_LOGICAL_PROCESSOR_INFORMATION *pslpi = IsGLPISupported(&nEntries) ; @@ -2001,9 +2005,6 @@ DWORD GetLogicalCpuCountFromOS() goto lDone; } - DWORD prevcount = 0; - DWORD count = 1; - for (DWORD j = 0; j < nEntries; j++) { if (pslpi[j].Relationship == RelationProcessorCore) @@ -2069,16 +2070,9 @@ lDone: #define CACHE_PARTITION_BITS 0x003FF000 // number of cache Physical Partitions is returned in EBX[21:12] (10 bits) using cpuid function 4 #define CACHE_LINESIZE_BITS 0x00000FFF // Linesize returned in EBX[11:0] (12 bits) using cpuid function 4 -#if defined(_TARGET_X86_) - // these are defined in cgenx86.cpp - extern DWORD getcpuid(DWORD arg1, unsigned char result[16]); - extern DWORD getextcpuid(DWORD arg1, DWORD arg2, unsigned char result[16]); -#elif defined(_TARGET_AMD64_) - // these are defined in src\VM\AMD64\asmhelpers.asm - extern "C" DWORD __stdcall getcpuid(DWORD arg1, unsigned char result[16]); - extern "C" DWORD __stdcall getextcpuid(DWORD arg1, DWORD arg2, unsigned char result[16]); -#endif - +// these are defined in src\VM\AMD64\asmhelpers.asm / cgenx86.cpp +extern "C" DWORD __stdcall getcpuid(DWORD arg1, unsigned char result[16]); +extern "C" DWORD __stdcall getextcpuid(DWORD arg1, DWORD arg2, unsigned char result[16]); // The following function uses a deterministic mechanism for enumerating/calculating the details of the cache hierarychy at runtime // by using deterministic cache parameter leafs on Prescott and higher processors. @@ -2557,7 +2551,7 @@ extern BOOL EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem); extern void ShutdownRuntimeWithoutExiting(int exitCode); extern BOOL IsRuntimeStarted(DWORD *pdwStartupFlags); -void * GetCLRFunction(LPCSTR FunctionName) +void * __stdcall GetCLRFunction(LPCSTR FunctionName) { void* func = NULL; diff --git a/src/vm/vars.cpp b/src/vm/vars.cpp index b737e66..626ca3c 100644 --- a/src/vm/vars.cpp +++ b/src/vm/vars.cpp @@ -69,6 +69,9 @@ GPTR_IMPL(MethodTable, g_pStringClass); GPTR_IMPL(MethodTable, g_pArrayClass); GPTR_IMPL(MethodTable, g_pSZArrayHelperClass); GPTR_IMPL(MethodTable, g_pNullableClass); +#ifdef FEATURE_SPAN_OF_T +GPTR_IMPL(MethodTable, g_pByReferenceClass); +#endif GPTR_IMPL(MethodTable, g_pExceptionClass); GPTR_IMPL(MethodTable, g_pThreadAbortExceptionClass); GPTR_IMPL(MethodTable, g_pOutOfMemoryExceptionClass); @@ -79,8 +82,12 @@ GPTR_IMPL(MethodTable, g_pMulticastDelegateClass); GPTR_IMPL(MethodTable, g_pValueTypeClass); GPTR_IMPL(MethodTable, g_pEnumClass); GPTR_IMPL(MethodTable, g_pThreadClass); +#ifdef FEATURE_CER GPTR_IMPL(MethodTable, g_pCriticalFinalizerObjectClass); +#endif +#ifndef FEATURE_CORECLR GPTR_IMPL(MethodTable, g_pAsyncFileStream_AsyncResultClass); +#endif // !FEATURE_CORECLR GPTR_IMPL(MethodTable, g_pFreeObjectMethodTable); GPTR_IMPL(MethodTable, g_pOverlappedDataClass); @@ -98,7 +105,9 @@ GPTR_IMPL(MethodTable, g_pICastableInterface); #endif // FEATURE_ICASTABLE +#ifdef FEATURE_CER GPTR_IMPL(MethodDesc, g_pPrepareConstrainedRegionsMethod); +#endif GPTR_IMPL(MethodDesc, g_pExecuteBackoutCodeHelperMethod); GPTR_IMPL(MethodDesc, g_pObjectCtorMD); diff --git a/src/vm/vars.hpp b/src/vm/vars.hpp index d197e05..62d6656 100644 --- a/src/vm/vars.hpp +++ b/src/vm/vars.hpp @@ -81,7 +81,7 @@ typedef unsigned short wchar_t; class ClassLoader; class LoaderHeap; -class GCHeap; +class IGCHeap; class Object; class StringObject; class TransparentProxyObject; @@ -402,6 +402,9 @@ GPTR_DECL(MethodTable, g_pStringClass); GPTR_DECL(MethodTable, g_pArrayClass); GPTR_DECL(MethodTable, g_pSZArrayHelperClass); GPTR_DECL(MethodTable, g_pNullableClass); +#ifdef FEATURE_SPAN_OF_T +GPTR_DECL(MethodTable, g_pByReferenceClass); +#endif GPTR_DECL(MethodTable, g_pExceptionClass); GPTR_DECL(MethodTable, g_pThreadAbortExceptionClass); GPTR_DECL(MethodTable, g_pOutOfMemoryExceptionClass); @@ -414,8 +417,12 @@ GPTR_DECL(MethodTable, g_pFreeObjectMethodTable); GPTR_DECL(MethodTable, g_pValueTypeClass); GPTR_DECL(MethodTable, g_pEnumClass); GPTR_DECL(MethodTable, g_pThreadClass); +#ifdef FEATURE_CER GPTR_DECL(MethodTable, g_pCriticalFinalizerObjectClass); +#endif +#ifndef FEATURE_CORECLR GPTR_DECL(MethodTable, g_pAsyncFileStream_AsyncResultClass); +#endif // !FEATURE_CORECLR GPTR_DECL(MethodTable, g_pOverlappedDataClass); GPTR_DECL(MethodTable, g_TypedReferenceMT); @@ -431,7 +438,9 @@ GPTR_DECL(MethodTable, g_pBaseRuntimeClass); GPTR_DECL(MethodTable, g_pICastableInterface); #endif // FEATURE_ICASTABLE +#ifdef FEATURE_CER GPTR_DECL(MethodDesc, g_pPrepareConstrainedRegionsMethod); +#endif GPTR_DECL(MethodDesc, g_pExecuteBackoutCodeHelperMethod); GPTR_DECL(MethodDesc, g_pObjectCtorMD); diff --git a/src/vm/virtualcallstub.cpp b/src/vm/virtualcallstub.cpp index 512b4f2..5fc66f6 100644 --- a/src/vm/virtualcallstub.cpp +++ b/src/vm/virtualcallstub.cpp @@ -1107,7 +1107,7 @@ BOOL VirtualCallStubManager::TraceManager(Thread *thread, #ifdef FEATURE_PREJIT // This is the case for the lazy slot fixup - if (GetIP(pContext) == GFN_TADDR(StubDispatchFixupPatchLabel)) { + if (GetIP(pContext) == GetEEFuncEntryPoint(StubDispatchFixupPatchLabel)) { *pRetAddr = (BYTE *)StubManagerHelpers::GetReturnAddress(pContext); diff --git a/src/vm/vm.settings b/src/vm/vm.settings index b4799d1..83d7d9f 100644 --- a/src/vm/vm.settings +++ b/src/vm/vm.settings @@ -1,5 +1,12 @@ + + + + + true + + diff --git a/src/vm/win32threadpool.cpp b/src/vm/win32threadpool.cpp index 1121417..e8a05c3 100644 --- a/src/vm/win32threadpool.cpp +++ b/src/vm/win32threadpool.cpp @@ -532,7 +532,9 @@ BOOL ThreadpoolMgr::SetMaxThreadsHelper(DWORD MaxWorkerThreads, CrstHolder csh(&WorkerCriticalSection); if (MaxWorkerThreads >= (DWORD)MinLimitTotalWorkerThreads && - MaxIOCompletionThreads >= (DWORD)MinLimitTotalCPThreads) + MaxIOCompletionThreads >= (DWORD)MinLimitTotalCPThreads && + MaxWorkerThreads != 0 && + MaxIOCompletionThreads != 0) { BEGIN_SO_INTOLERANT_CODE(GetThread()); @@ -2367,11 +2369,11 @@ Work: counts = oldCounts; } - if (GCHeap::IsGCInProgress(TRUE)) + if (GCHeapUtilities::IsGCInProgress(TRUE)) { // GC is imminent, so wait until GC is complete before executing next request. // this reduces in-flight objects allocated right before GC, easing the GC's work - GCHeap::WaitForGCCompletion(TRUE); + GCHeapUtilities::WaitForGCCompletion(TRUE); } { @@ -3677,6 +3679,8 @@ DWORD __stdcall ThreadpoolMgr::CompletionPortThreadStart(LPVOID lpArgs) BOOL fThreadInit = FALSE; Thread *pThread = NULL; + DWORD cpThreadWait = 0; + if (g_fEEStarted) { pThread = SetupThreadNoThrow(); if (pThread == NULL) { @@ -3711,7 +3715,7 @@ DWORD __stdcall ThreadpoolMgr::CompletionPortThreadStart(LPVOID lpArgs) ThreadCounter::Counts oldCounts; ThreadCounter::Counts newCounts; - DWORD cpThreadWait = CP_THREAD_WAIT; + cpThreadWait = CP_THREAD_WAIT; for (;; ) { Top: @@ -3986,7 +3990,7 @@ Top: if (key != 0) { - if (GCHeap::IsGCInProgress(TRUE)) + if (GCHeapUtilities::IsGCInProgress(TRUE)) { //Indicate that this thread is free, and waiting on GC, not doing any user work. //This helps in threads not getting injected when some threads have woken up from the @@ -4003,7 +4007,7 @@ Top: // GC is imminent, so wait until GC is complete before executing next request. // this reduces in-flight objects allocated right before GC, easing the GC's work - GCHeap::WaitForGCCompletion(TRUE); + GCHeapUtilities::WaitForGCCompletion(TRUE); while (true) { @@ -4217,7 +4221,7 @@ BOOL ThreadpoolMgr::ShouldGrowCompletionPortThreadpool(ThreadCounter::Counts cou if (counts.NumWorking >= counts.NumActive && NumCPInfrastructureThreads == 0 - && (counts.NumActive == 0 || !GCHeap::IsGCInProgress(TRUE)) + && (counts.NumActive == 0 || !GCHeapUtilities::IsGCInProgress(TRUE)) ) { // adjust limit if neeeded @@ -4618,7 +4622,7 @@ DWORD __stdcall ThreadpoolMgr::GateThreadStart(LPVOID lpArgs) EX_END_CATCH(SwallowAllExceptions); } - if (!GCHeap::IsGCInProgress(FALSE) ) + if (!GCHeapUtilities::IsGCInProgress(FALSE) ) { if (IgnoreNextSample) { @@ -4660,7 +4664,7 @@ DWORD __stdcall ThreadpoolMgr::GateThreadStart(LPVOID lpArgs) oldCounts.NumActive < MaxLimitTotalCPThreads && !g_fCompletionPortDrainNeeded && NumCPInfrastructureThreads == 0 && // infrastructure threads count as "to be free as needed" - !GCHeap::IsGCInProgress(TRUE)) + !GCHeapUtilities::IsGCInProgress(TRUE)) { BOOL status; diff --git a/src/vm/win32threadpool.h b/src/vm/win32threadpool.h index f712ef9..6b4f1df 100644 --- a/src/vm/win32threadpool.h +++ b/src/vm/win32threadpool.h @@ -505,22 +505,22 @@ public: static BOOL UnregisterWaitEx(HANDLE hWaitObject,HANDLE CompletionEvent); static void WaitHandleCleanup(HANDLE hWaitObject); - static BOOL BindIoCompletionCallback(HANDLE FileHandle, + static BOOL WINAPI BindIoCompletionCallback(HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags, DWORD& errorCode); - static void WaitIOCompletionCallback(DWORD dwErrorCode, + static void WINAPI WaitIOCompletionCallback(DWORD dwErrorCode, DWORD numBytesTransferred, LPOVERLAPPED lpOverlapped); - static VOID CallbackForInitiateDrainageOfCompletionPortQueue( + static VOID WINAPI CallbackForInitiateDrainageOfCompletionPortQueue( DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped ); - static VOID CallbackForContinueDrainageOfCompletionPortQueue( + static VOID WINAPI CallbackForContinueDrainageOfCompletionPortQueue( DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped diff --git a/src/vm/winrtredirector.h b/src/vm/winrtredirector.h index 2561252..f725ca8 100644 --- a/src/vm/winrtredirector.h +++ b/src/vm/winrtredirector.h @@ -137,7 +137,7 @@ class WinRTDelegateRedirector public: static MethodTable *GetWinRTTypeForRedirectedDelegateIndex(WinMDAdapter::RedirectedTypeIndex index); - static bool WinRTDelegateRedirector::ResolveRedirectedDelegate(MethodTable *pMT, WinMDAdapter::RedirectedTypeIndex *pIndex); + static bool ResolveRedirectedDelegate(MethodTable *pMT, WinMDAdapter::RedirectedTypeIndex *pIndex); }; #endif // WINRT_DELEGATE_REDIRECTOR_H diff --git a/src/vm/wks/wks.targets b/src/vm/wks/wks.targets index 0456236..0df66fe 100644 --- a/src/vm/wks/wks.targets +++ b/src/vm/wks/wks.targets @@ -107,6 +107,7 @@ + diff --git a/src/zap/zapcode.cpp b/src/zap/zapcode.cpp index adad361..167c0ed 100644 --- a/src/zap/zapcode.cpp +++ b/src/zap/zapcode.cpp @@ -1130,7 +1130,7 @@ void ZapUnwindInfo::Save(ZapWriter * pZapWriter) pZapWriter->Write(&runtimeFunction, sizeof(runtimeFunction)); } -#ifdef WIN64EXCEPTIONS +#if defined(WIN64EXCEPTIONS) && !defined(_TARGET_X86_) // Compare the unwind infos by their offset int __cdecl ZapUnwindInfo::CompareUnwindInfo(const void* a_, const void* b_) { diff --git a/src/zap/zapheaders.cpp b/src/zap/zapheaders.cpp index d8cd6fa..2422c98 100644 --- a/src/zap/zapheaders.cpp +++ b/src/zap/zapheaders.cpp @@ -249,19 +249,32 @@ void ZapImage::CopyWin32VersionResource() void ZapDebugDirectory::SaveOriginalDebugDirectoryEntry(ZapWriter *pZapWriter) { - if (m_pDebugData != NULL) + if (m_ppDebugData != nullptr) { - m_debugDirectory.SizeOfData = m_pDebugData->GetSize(); - m_debugDirectory.AddressOfRawData = m_pDebugData->GetRVA(); + for (DWORD i = 0; i < m_nDebugDirectory; i++) + { + if (m_ppDebugData[i] != nullptr) + { + m_pDebugDirectory[i].SizeOfData = m_ppDebugData[i]->GetSize(); + m_pDebugDirectory[i].AddressOfRawData = m_ppDebugData[i]->GetRVA(); - // Compute the absolute file (seek) pointer. We need to reach to the matching physical section to do that. - ZapPhysicalSection * pPhysicalSection = ZapImage::GetImage(pZapWriter)->m_pTextSection; + // Compute the absolute file (seek) pointer. We need to reach to the matching physical section to do that. + ZapPhysicalSection * pPhysicalSection = ZapImage::GetImage(pZapWriter)->m_pTextSection; - DWORD dwOffset = m_pDebugData->GetRVA() - pPhysicalSection->GetRVA(); - _ASSERTE(dwOffset < pPhysicalSection->GetSize()); - - m_debugDirectory.PointerToRawData = pPhysicalSection->GetFilePos() + dwOffset; - pZapWriter->Write(&m_debugDirectory, sizeof(m_debugDirectory)); + DWORD dwOffset = m_ppDebugData[i]->GetRVA() - pPhysicalSection->GetRVA(); + _ASSERTE(dwOffset < pPhysicalSection->GetSize()); + + m_pDebugDirectory[i].PointerToRawData = pPhysicalSection->GetFilePos() + dwOffset; + } + else + { + m_pDebugDirectory[i].SizeOfData = 0; + m_pDebugDirectory[i].AddressOfRawData = 0; + m_pDebugDirectory[i].PointerToRawData = 0; + } + } + + pZapWriter->Write(m_pDebugDirectory, sizeof(IMAGE_DEBUG_DIRECTORY) * m_nDebugDirectory); } } @@ -270,7 +283,10 @@ void ZapDebugDirectory::SaveNGenDebugDirectoryEntry(ZapWriter *pZapWriter) _ASSERTE(pZapWriter); IMAGE_DEBUG_DIRECTORY debugDirectory = {0}; - memcpy(&debugDirectory, &m_debugDirectory, sizeof(IMAGE_DEBUG_DIRECTORY)); + if (m_nDebugDirectory > 0) + { + memcpy(&debugDirectory, m_pDebugDirectory, sizeof(IMAGE_DEBUG_DIRECTORY)); + } debugDirectory.Type = IMAGE_DEBUG_TYPE_CODEVIEW; debugDirectory.SizeOfData = m_pNGenPdbDebugData->GetSize(); debugDirectory.AddressOfRawData = m_pNGenPdbDebugData->GetRVA(); @@ -288,18 +304,49 @@ void ZapDebugDirectory::Save(ZapWriter * pZapWriter) _ASSERTE(pZapWriter); if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_NGenEnableCreatePdb)) { - SaveOriginalDebugDirectoryEntry(pZapWriter); SaveNGenDebugDirectoryEntry(pZapWriter); - } else { - SaveNGenDebugDirectoryEntry(pZapWriter); SaveOriginalDebugDirectoryEntry(pZapWriter); - } } +ZapPEExports::ZapPEExports(LPCWSTR dllPath) +{ + m_dllFileName = wcsrchr(dllPath, DIRECTORY_SEPARATOR_CHAR_W); + if (m_dllFileName != NULL) + m_dllFileName++; + else + m_dllFileName = dllPath; +} + +DWORD ZapPEExports::GetSize() +{ + return DWORD(sizeof(IMAGE_EXPORT_DIRECTORY) + wcslen(m_dllFileName) + 1); +} + +void ZapPEExports::Save(ZapWriter * pZapWriter) +{ + _ASSERTE(pZapWriter); + + IMAGE_EXPORT_DIRECTORY exports; + ZeroMemory(&exports, sizeof(exports)); + + exports.Name = pZapWriter->GetCurrentRVA() + sizeof(exports); + + // Write out exports header + pZapWriter->Write(&exports, sizeof(exports)); + + // Write out string that exports.Name points at. + for (LPCWSTR ptr = m_dllFileName; ; ptr++) + { + pZapWriter->Write((PVOID) ptr, 1); + if (*ptr == 0) + break; + } +} + // If the IL image has IMAGE_DIRECTORY_ENTRY_DEBUG with information about the PDB, // copy that information over to the ngen image. // This lets the debugger find out information about the PDB without loading @@ -321,8 +368,9 @@ void ZapImage::CopyDebugDirEntry() // IL PDB entry: copy of the (first of possibly many) IMAGE_DEBUG_DIRECTORY entry // in the IL image + DWORD nDebugEntry = 0; PIMAGE_DEBUG_DIRECTORY pDebugDir = NULL; - ZapBlob *pDebugData = NULL; + ZapNode **ppDebugData = NULL; if (m_ModuleDecoder.HasDirectoryEntry(IMAGE_DIRECTORY_ENTRY_DEBUG)) { COUNT_T debugEntrySize; @@ -339,40 +387,48 @@ void ZapImage::CopyDebugDirEntry() // should be a multiple of sizeof(IMAGE_DEBUG_DIRECTORY). _ASSERTE(0 == (debugEntrySize % sizeof(IMAGE_DEBUG_DIRECTORY))); - // @TODO: pDebugEntry is an array of IMAGE_DEBUG_DIRECTORYs. Some tools - // (like ibcmerge) add an extra dummy IMAGE_DEBUG_DIRECTORY to indicate - // that the image was modified post-link. - // We need to copy all the IMAGE_DEBUG_DIRECTORYs. For now, we only copy - // the first one as it holds the relevant debug information. - - pDebugDir = PIMAGE_DEBUG_DIRECTORY(pDebugEntry); - - // Some compilers set PointerToRawData but not AddressOfRawData as they put the - // data at the end of the file in an unmapped part of the file + nDebugEntry = DWORD(debugEntrySize / sizeof(IMAGE_DEBUG_DIRECTORY)); + pDebugDir = new (GetHeap()) IMAGE_DEBUG_DIRECTORY[nDebugEntry]; + memcpy(pDebugDir, (const void *)pDebugEntry, sizeof(IMAGE_DEBUG_DIRECTORY) * nDebugEntry); + ppDebugData = new (GetHeap()) ZapNode*[nDebugEntry]; + memset(ppDebugData, 0, nDebugEntry * sizeof(ZapNode*)); - RVA rvaOfRawData = (pDebugDir->AddressOfRawData != NULL) - ? pDebugDir->AddressOfRawData : m_ModuleDecoder.OffsetToRva(pDebugDir->PointerToRawData); - - ULONG cbDebugData = pDebugDir->SizeOfData; - - if (cbDebugData != 0) { - if (!m_ModuleDecoder.CheckRva(rvaOfRawData, cbDebugData)) - m_zapper->Warning(W("IMAGE_DIRECTORY_ENTRY_DEBUG points to bad data\n")); - else - pDebugData = new (GetHeap()) ZapBlobPtr((PVOID)m_ModuleDecoder.GetRvaData(rvaOfRawData), cbDebugData); + for (DWORD i = 0; i < nDebugEntry; i++) + { + // Some compilers set PointerToRawData but not AddressOfRawData as they put the + // data at the end of the file in an unmapped part of the file + + RVA rvaOfRawData = (pDebugDir[i].AddressOfRawData != NULL) + ? pDebugDir[i].AddressOfRawData : m_ModuleDecoder.OffsetToRva(pDebugDir[i].PointerToRawData); + + ULONG cbDebugData = pDebugDir[i].SizeOfData; + + if (cbDebugData != 0) { + if (!m_ModuleDecoder.CheckRva(rvaOfRawData, cbDebugData)) + m_zapper->Warning(W("IMAGE_DIRECTORY_ENTRY_DEBUG points to bad data\n")); + else + ppDebugData[i] = new (GetHeap()) ZapBlobPtr((PVOID)m_ModuleDecoder.GetRvaData(rvaOfRawData), cbDebugData); + } } } } } ZapDebugDirectory * pDebugDirectory = new (GetHeap()) ZapDebugDirectory(m_pNGenPdbDebugData, - pDebugData ? pDebugDir : NULL, - pDebugData); + nDebugEntry, + pDebugDir, + ppDebugData); m_pDebugSection->Place(pDebugDirectory); m_pDebugSection->Place(m_pNGenPdbDebugData); - if (pDebugData) - m_pDebugSection->Place(pDebugData); + if (ppDebugData) + { + for (DWORD i = 0; i < nDebugEntry; i++) + { + if (ppDebugData[i] != nullptr) + m_pDebugSection->Place(ppDebugData[i]); + } + } SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_DEBUG, pDebugDirectory); } diff --git a/src/zap/zapheaders.h b/src/zap/zapheaders.h index 12b0a18..0755c0e 100644 --- a/src/zap/zapheaders.h +++ b/src/zap/zapheaders.h @@ -234,23 +234,22 @@ public: class ZapDebugDirectory : public ZapNode { ZapNode * m_pNGenPdbDebugData; - IMAGE_DEBUG_DIRECTORY m_debugDirectory; - ZapNode * m_pDebugData; + DWORD m_nDebugDirectory; + IMAGE_DEBUG_DIRECTORY * m_pDebugDirectory; + ZapNode ** m_ppDebugData; public: - ZapDebugDirectory(ZapNode *pNGenPdbDebugData, PIMAGE_DEBUG_DIRECTORY pDebugDirectory, ZapNode * pDebugData) + ZapDebugDirectory(ZapNode *pNGenPdbDebugData, DWORD nDebugDirectory, PIMAGE_DEBUG_DIRECTORY pDebugDirectory, ZapNode ** ppDebugData) : m_pNGenPdbDebugData(pNGenPdbDebugData), - m_pDebugData(pDebugData) + m_nDebugDirectory(nDebugDirectory), + m_pDebugDirectory(pDebugDirectory), + m_ppDebugData(ppDebugData) { - if (pDebugDirectory == NULL) - memset(&m_debugDirectory, 0, sizeof(IMAGE_DEBUG_DIRECTORY)); - else - memcpy(&m_debugDirectory, pDebugDirectory, sizeof(IMAGE_DEBUG_DIRECTORY)); } virtual DWORD GetSize() { - return m_pDebugData ? sizeof(IMAGE_DEBUG_DIRECTORY) * 2 : sizeof(IMAGE_DEBUG_DIRECTORY); + return sizeof(IMAGE_DEBUG_DIRECTORY) * (m_nDebugDirectory + 1); } virtual UINT GetAlignment() @@ -269,6 +268,23 @@ public: }; // +// PE Style exports. Currently can only save an empty list of exports +// but this is useful because it avoids the DLL being seen as Resource Only +// (which then causes SymServer to avoid copying its PDB to the cloud). +// + +class ZapPEExports : public ZapNode +{ + LPCWSTR m_dllFileName; // Just he DLL name without the path. + +public: + ZapPEExports(LPCWSTR dllPath); + virtual DWORD GetSize(); + virtual UINT GetAlignment() { return sizeof(DWORD); } + virtual void Save(ZapWriter * pZapWriter); +}; + +// // List of all sections for diagnostic purposes class ZapVirtualSectionsTable : public ZapNode diff --git a/src/zap/zapimage.cpp b/src/zap/zapimage.cpp index a435d6a..f39b8f8 100644 --- a/src/zap/zapimage.cpp +++ b/src/zap/zapimage.cpp @@ -291,6 +291,12 @@ void ZapImage::InitializeSectionsForReadyToRun() // Always allocate slot for module - it is used to determine that the image is used // m_pImportTable->GetPlacedHelperImport(READYTORUN_HELPER_Module); + + // + // Make sure the import sections table is in the image, so we can find the slot for module + // + _ASSERTE(m_pImportSectionsTable->GetSize() != 0); + GetReadyToRunHeader()->RegisterSection(READYTORUN_SECTION_IMPORT_SECTIONS, m_pImportSectionsTable); } #endif // FEATURE_READYTORUN_COMPILER @@ -395,7 +401,7 @@ void ZapImage::AllocateVirtualSections() // // If we're instrumenting allocate a section for writing profile data // - if (m_zapper->m_pOpt->m_compilerFlags & CORJIT_FLG_BBINSTR) + if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR)) { m_pInstrumentSection = NewVirtualSection(pDataSection, IBCUnProfiledSection | ColdRange | InstrumentSection, sizeof(TADDR)); } @@ -1163,6 +1169,14 @@ HANDLE ZapImage::SaveImage(LPCWSTR wszOutputFileName, CORCOMPILE_NGEN_SIGNATURE OutputTables(); + // Create a empty export table. This makes tools like symchk not think + // that native images are resoure-only DLLs. It is important to NOT + // be a resource-only DLL because those DLL's PDBS are not put up on the + // symbol server and we want NEN PDBS to be placed there. + ZapPEExports* exports = new(GetHeap()) ZapPEExports(wszOutputFileName); + m_pDebugSection->Place(exports); + SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_EXPORT, exports); + ComputeRVAs(); if (!IsReadyToRunCompilation()) @@ -1697,16 +1711,16 @@ void ZapImage::OutputTables() SetSizeOfStackCommit(m_ModuleDecoder.GetSizeOfStackCommit()); } -#if defined(_TARGET_ARM_) && defined(FEATURE_CORECLR) && defined(FEATURE_CORESYSTEM) +#if defined(FEATURE_PAL) + // PAL library requires native image sections to align to page bounaries. + SetFileAlignment(0x1000); +#elif defined(_TARGET_ARM_) && defined(FEATURE_CORECLR) && defined(FEATURE_CORESYSTEM) if (!IsReadyToRunCompilation()) { // On ARM CoreSys builds, crossgen will use 4k file alignment, as requested by Phone perf team // to improve perf on phones with compressed system partitions. SetFileAlignment(0x1000); } -#elif defined(FEATURE_PAL) - // PAL library requires native image sections to align to page bounaries. - SetFileAlignment(0x1000); #endif } @@ -1935,23 +1949,24 @@ struct CompileMethodStubContext //----------------------------------------------------------------------------- // static void __stdcall -void ZapImage::TryCompileMethodStub(LPVOID pContext, CORINFO_METHOD_HANDLE hStub, DWORD dwJitFlags) +void ZapImage::TryCompileMethodStub(LPVOID pContext, CORINFO_METHOD_HANDLE hStub, CORJIT_FLAGS jitFlags) { STANDARD_VM_CONTRACT; // The caller must always set the IL_STUB flag - _ASSERTE((dwJitFlags & CORJIT_FLG_IL_STUB) != 0); + _ASSERTE(jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)); CompileMethodStubContext *pCompileContext = reinterpret_cast(pContext); ZapImage *pImage = pCompileContext->pImage; - unsigned oldFlags = pImage->m_zapper->m_pOpt->m_compilerFlags; + CORJIT_FLAGS oldFlags = pImage->m_zapper->m_pOpt->m_compilerFlags; - pImage->m_zapper->m_pOpt->m_compilerFlags |= dwJitFlags; - pImage->m_zapper->m_pOpt->m_compilerFlags &= ~(CORJIT_FLG_PROF_ENTERLEAVE | - CORJIT_FLG_DEBUG_CODE | - CORJIT_FLG_DEBUG_EnC | - CORJIT_FLG_DEBUG_INFO); + CORJIT_FLAGS* pCompilerFlags = &pImage->m_zapper->m_pOpt->m_compilerFlags; + pCompilerFlags->Add(jitFlags); + pCompilerFlags->Clear(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE); + pCompilerFlags->Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE); + pCompilerFlags->Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_EnC); + pCompilerFlags->Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); mdMethodDef md = mdMethodDefNil; @@ -2191,7 +2206,7 @@ ZapImage::CompileStatus ZapImage::TryCompileMethodWorker(CORINFO_METHOD_HANDLE h if (GetCompiledMethod(handle) != NULL) return ALREADY_COMPILED; - _ASSERTE((m_zapper->m_pOpt->m_compilerFlags & CORJIT_FLG_IL_STUB) || IsNilToken(md) || handle == m_pPreloader->LookupMethodDef(md)); + _ASSERTE(m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB) || IsNilToken(md) || handle == m_pPreloader->LookupMethodDef(md)); CompileStatus result = NOT_COMPILED; @@ -2205,7 +2220,7 @@ ZapImage::CompileStatus ZapImage::TryCompileMethodWorker(CORINFO_METHOD_HANDLE h CORINFO_MODULE_HANDLE module; // We only compile IL_STUBs from the current assembly - if (m_zapper->m_pOpt->m_compilerFlags & CORJIT_FLG_IL_STUB) + if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) module = m_hModule; else module = m_zapper->m_pEEJitInfo->getMethodModule(handle); @@ -2263,7 +2278,7 @@ ZapImage::CompileStatus ZapImage::TryCompileMethodWorker(CORINFO_METHOD_HANDLE h if (m_stats != NULL) { - if ((m_zapper->m_pOpt->m_compilerFlags & CORJIT_FLG_IL_STUB) == 0) + if (!m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) m_stats->m_failedMethods++; else m_stats->m_failedILStubs++; @@ -2496,7 +2511,7 @@ HRESULT ZapImage::LocateProfileData() // the final image. // #if 0 - if ((m_zapper->m_pOpt->m_compilerFlags & CORJIT_FLG_BBINSTR) != 0) + if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR)) return S_FALSE; #endif @@ -3473,7 +3488,7 @@ bool ZapImage::canIntraModuleDirectCall( // No direct calls at all under some circumstances - if ((m_zapper->m_pOpt->m_compilerFlags & CORJIT_FLG_PROF_ENTERLEAVE) + if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE) && !m_pPreloader->IsDynamicMethod(callerFtn)) { *pReason = CORINFO_INDIRECT_CALL_PROFILING; diff --git a/src/zap/zapimage.h b/src/zap/zapimage.h index 8427918..02985f5 100644 --- a/src/zap/zapimage.h +++ b/src/zap/zapimage.h @@ -656,7 +656,7 @@ public: NOT_COMPILED = 0, COMPILE_EXCLUDED = 1, // Info COMPILE_SUCCEED = 10, ALREADY_COMPILED = 11}; // Success - static void __stdcall TryCompileMethodStub(LPVOID pContext, CORINFO_METHOD_HANDLE hStub, DWORD dwJitFlags); + static void __stdcall TryCompileMethodStub(LPVOID pContext, CORINFO_METHOD_HANDLE hStub, CORJIT_FLAGS jitFlags); BOOL IsVTableGapMethod(mdMethodDef md); diff --git a/src/zap/zapinfo.cpp b/src/zap/zapinfo.cpp index 232570f..d2362d4 100644 --- a/src/zap/zapinfo.cpp +++ b/src/zap/zapinfo.cpp @@ -141,13 +141,13 @@ void ZapInfo::InitMethodName() m_currentMethodName.AppendUTF8(szMethodName); } -int ZapInfo::ComputeJitFlags(CORINFO_METHOD_HANDLE handle) +CORJIT_FLAGS ZapInfo::ComputeJitFlags(CORINFO_METHOD_HANDLE handle) { - int jitFlags = m_zapper->m_pOpt->m_compilerFlags; + CORJIT_FLAGS jitFlags = m_zapper->m_pOpt->m_compilerFlags; - DWORD flags = 0; + CORJIT_FLAGS flags; IfFailThrow(m_pEECompileInfo->GetBaseJitFlags(handle, &flags)); - jitFlags |= flags; + jitFlags.Add(flags); // COMPlus_JitFramed specifies the default fpo setting for jitted and NGened code. // You can override the behavior for NGened code using COMPlus_NGenFramed. @@ -156,52 +156,56 @@ int ZapInfo::ComputeJitFlags(CORINFO_METHOD_HANDLE handle) if (dwNGenFramed == 0) { // NGened code should enable fpo - jitFlags &= ~CORJIT_FLG_FRAMED; + jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_FRAMED); } else if (dwNGenFramed == 1) { // NGened code should disable fpo - jitFlags |= CORJIT_FLG_FRAMED; + jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_FRAMED); } if (canSkipMethodVerification(m_currentMethodHandle) == CORINFO_VERIFICATION_CAN_SKIP) { - jitFlags |= CORJIT_FLG_SKIP_VERIFICATION; + jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION); } if (m_pImage->m_profileDataSections[MethodBlockCounts].pData && !m_zapper->m_pOpt->m_ignoreProfileData) { - jitFlags |= CORJIT_FLG_BBOPT; + jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_BBOPT); } // // By default we always enable Hot/Cold procedure splitting // - jitFlags |= CORJIT_FLG_PROCSPLIT; + jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT); if (m_zapper->m_pOpt->m_noProcedureSplitting) - jitFlags &= ~CORJIT_FLG_PROCSPLIT; + jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT); //never emit inlined polls for NGen'd code. The extra indirection is not optimal. - if (jitFlags & CORJIT_FLG_GCPOLL_INLINE) + if (jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_GCPOLL_INLINE)) { - jitFlags &= ~CORJIT_FLG_GCPOLL_INLINE; - jitFlags |= CORJIT_FLG_GCPOLL_CALLS; + jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_GCPOLL_INLINE); + jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_GCPOLL_CALLS); } // If the method is specified for min-opts then turn everything off - if (jitFlags & CORJIT_FLG_MIN_OPT) - jitFlags &= ~(CORJIT_FLG_BBINSTR | CORJIT_FLG_BBOPT | CORJIT_FLG_PROCSPLIT); + if (jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_MIN_OPT)) + { + jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR); + jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_BBOPT); + jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT); + } // Rejit is now enabled by default for NGEN'ed code. This costs us // some size in exchange for diagnostic functionality, but we've got // further work planned that should mitigate the size increase. - jitFlags |= CORJIT_FLG_PROF_REJIT_NOPS; + jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROF_REJIT_NOPS); #ifdef FEATURE_READYTORUN_COMPILER if (IsReadyToRunCompilation()) - jitFlags |= CORJIT_FLG_READYTORUN; + jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_READYTORUN); #endif return jitFlags; @@ -427,14 +431,13 @@ void ZapInfo::CompileMethod() // this they can add the hint and reduce the perf cost at runtime. m_pImage->m_pPreloader->PrePrepareMethodIfNecessary(m_currentMethodHandle); - m_jitFlags = { 0 }; - m_jitFlags.corJitFlags = ComputeJitFlags(m_currentMethodHandle); + m_jitFlags = ComputeJitFlags(m_currentMethodHandle); #ifdef FEATURE_READYTORUN_COMPILER if (IsReadyToRunCompilation()) { // READYTORUN: FUTURE: Producedure spliting - m_jitFlags.corJitFlags &= ~CORJIT_FLG_PROCSPLIT; + m_jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT); DWORD methodAttribs = getMethodAttribs(m_currentMethodHandle); if (!(methodAttribs & CORINFO_FLG_NOSECURITYWRAP) || (methodAttribs & CORINFO_FLG_SECURITYCHECK)) @@ -445,13 +448,13 @@ void ZapInfo::CompileMethod() } #endif - if ((m_jitFlags.corJitFlags & CORJIT_FLG_SKIP_VERIFICATION) == 0) + if (!m_jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION)) { BOOL raiseVerificationException, unverifiableGenericCode; - m_jitFlags.corJitFlags = GetCompileFlagsIfGenericInstantiation( + m_jitFlags = GetCompileFlagsIfGenericInstantiation( m_currentMethodHandle, - (CorJitFlag)m_jitFlags.corJitFlags, + m_jitFlags, this, &raiseVerificationException, &unverifiableGenericCode); @@ -465,7 +468,7 @@ void ZapInfo::CompileMethod() #if !defined(FEATURE_CORECLR) // Ask the JIT to generate desktop-quirk-compatible code. - m_jitFlags.corJitFlags2 |= CORJIT_FLG2_DESKTOP_QUIRKS; + m_jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_DESKTOP_QUIRKS); #endif if (m_pImage->m_stats) @@ -486,7 +489,7 @@ void ZapInfo::CompileMethod() res = m_zapper->m_alternateJit->compileMethod( this, &m_currentMethodInfo, - CORJIT_FLG_CALL_GETJITFLAGS, + CORJIT_FLAGS::CORJIT_FLAG_CALL_GETJITFLAGS, &pCode, &cCode ); if (FAILED(res)) @@ -504,7 +507,7 @@ void ZapInfo::CompileMethod() ICorJitCompiler * pCompiler = m_zapper->m_pJitCompiler; res = pCompiler->compileMethod(this, &m_currentMethodInfo, - CORJIT_FLG_CALL_GETJITFLAGS, + CORJIT_FLAGS::CORJIT_FLAG_CALL_GETJITFLAGS, &pCode, &cCode); @@ -813,7 +816,7 @@ void ZapInfo::PublishCompiledMethod() // // For now, the only methods eligible for de-duplication are IL stubs // - if (m_zapper->m_pOpt->m_compilerFlags & CORJIT_FLG_IL_STUB) + if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) { ZapMethodHeader * pDuplicateMethod = m_pImage->m_CodeDeduplicator.Lookup(pMethod); if (pDuplicateMethod != NULL) @@ -830,7 +833,7 @@ void ZapInfo::PublishCompiledMethod() // Stubs that have no metadata token cannot be tracked by IBC data. if (m_currentMethodProfilingDataFlags & (1 << ReadMethodCode)) { - if (m_zapper->m_pOpt->m_compilerFlags & CORJIT_FLG_IL_STUB) + if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) m_pImage->m_PrioritizedGCInfo.Append(pMethod->m_pGCInfo); } @@ -888,7 +891,7 @@ HRESULT ZapInfo::allocBBProfileBuffer ( { HRESULT hr; - if (m_zapper->m_pOpt->m_compilerFlags & CORJIT_FLG_IL_STUB) + if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) { *ppBlock = NULL; return E_NOTIMPL; @@ -965,7 +968,7 @@ HRESULT ZapInfo::getBBProfileData ( // the profile data is in that module // @TODO: Fetch the profile data from the other module. if ((m_currentMethodModule != m_pImage->m_hModule) || - (m_zapper->m_pOpt->m_compilerFlags & CORJIT_FLG_IL_STUB)) + m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) { return E_FAIL; } @@ -1054,7 +1057,7 @@ void ZapInfo::allocMem( void ** roDataBlock /* OUT */ ) { - bool optForSize = ((m_zapper->m_pOpt->m_compilerFlags & CORJIT_FLG_SIZE_OPT) == CORJIT_FLG_SIZE_OPT); + bool optForSize = m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SIZE_OPT); UINT align = DEFAULT_CODE_ALIGN; @@ -1194,7 +1197,7 @@ void ZapInfo::setEHinfo(unsigned EHnumber, { ilClause->ClassToken = clause->ClassToken; - if ((m_zapper->m_pOpt->m_compilerFlags & CORJIT_FLG_IL_STUB) && (clause->ClassToken != 0)) + if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB) && (clause->ClassToken != 0)) { // IL stub tokens are 'private' and do not resolve correctly in their parent module's metadata. @@ -2298,7 +2301,7 @@ unsigned ZapInfo::getClassDomainID (CORINFO_CLASS_HANDLE cls, void **ppIndirecti m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(cls); - if(!(m_zapper->m_pOpt->m_compilerFlags & CORJIT_FLG_DEBUG_CODE)) + if (!m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE)) { if (isRIDClassDomainID(cls)) { @@ -3706,7 +3709,7 @@ CorInfoCanSkipVerificationResult ZapInfo::canSkipMethodVerification ( { // ILStubs are generated internally by the CLR. There is no need to // verify it, or any of its callees. - if (m_zapper->m_pOpt->m_compilerFlags & CORJIT_FLG_IL_STUB) + if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) return CORINFO_VERIFICATION_CAN_SKIP; CorInfoCanSkipVerificationResult canSkipVer = diff --git a/src/zap/zapinfo.h b/src/zap/zapinfo.h index 3d8736f..97ecfb6 100644 --- a/src/zap/zapinfo.h +++ b/src/zap/zapinfo.h @@ -231,7 +231,7 @@ class ZapInfo void InitMethodName(); - int ComputeJitFlags(CORINFO_METHOD_HANDLE handle); + CORJIT_FLAGS ComputeJitFlags(CORINFO_METHOD_HANDLE handle); ZapDebugInfo * EmitDebugInfo(); ZapGCInfo * EmitGCInfo(); diff --git a/src/zap/zapmetadata.cpp b/src/zap/zapmetadata.cpp index e77dbb8..a3a9e2d 100644 --- a/src/zap/zapmetadata.cpp +++ b/src/zap/zapmetadata.cpp @@ -299,7 +299,7 @@ void ZapILMetaData::CopyMetaData() // unless we're producing an instrumented version - the IBC logging for meta data doesn't // work for the hot/cold split version. - if (m_pImage->m_zapper->m_pOpt->m_compilerFlags & CORJIT_FLG_BBINSTR) + if (m_pImage->m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR)) IfFailThrow(pIMetaDataCorProfileData->SetCorProfileData(NULL)); else IfFailThrow(pIMetaDataCorProfileData->SetCorProfileData(m_pImage->GetProfileData())); @@ -308,7 +308,7 @@ void ZapILMetaData::CopyMetaData() // If we are ngening with the tuning option, the IBC data that is // generated gets reordered and may be inconsistent with the // metadata in the original IL image. Let's just skip that case. - if (!(m_pImage->m_zapper->m_pOpt->m_compilerFlags & CORJIT_FLG_BBINSTR)) + if (!m_pImage->m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR)) { // Communicate the reordering option for saving NonVMComHolder pIMDInternalMetadataReorderingOptions; diff --git a/src/zap/zapper.cpp b/src/zap/zapper.cpp index bcb1b0e..2c7023a 100644 --- a/src/zap/zapper.cpp +++ b/src/zap/zapper.cpp @@ -425,12 +425,15 @@ ZapperOptions::ZapperOptions() : m_fPartialNGen(false), m_fPartialNGenSet(false), m_fNGenLastRetry(false), - m_compilerFlags(CORJIT_FLG_RELOC | CORJIT_FLG_PREJIT), + m_compilerFlags(), m_legacyMode(false) #ifdef FEATURE_CORECLR ,m_fNoMetaData(s_fNGenNoMetaData) #endif { + m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_RELOC); + m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PREJIT); + m_zapSet = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_ZapSet); if (m_zapSet != NULL && wcslen(m_zapSet) > 3) { @@ -519,18 +522,21 @@ Zapper::Zapper(NGenOptions *pOptions, bool fromDllHost) pOptions = ¤tVersionOptions; - zo->m_compilerFlags = CORJIT_FLG_RELOC | CORJIT_FLG_PREJIT; + zo->m_compilerFlags.Reset(); + zo->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_RELOC); + zo->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PREJIT); zo->m_autodebug = true; if (pOptions->fDebug) { - zo->m_compilerFlags |= CORJIT_FLG_DEBUG_INFO|CORJIT_FLG_DEBUG_CODE; + zo->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); + zo->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE); zo->m_autodebug = false; } if (pOptions->fProf) { - zo->m_compilerFlags |= CORJIT_FLG_PROF_ENTERLEAVE; + zo->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE); } #ifdef FEATURE_FUSION @@ -576,7 +582,7 @@ Zapper::Zapper(NGenOptions *pOptions, bool fromDllHost) #endif //FEATURE_FUSION if (pOptions->fInstrument) - zo->m_compilerFlags |= CORJIT_FLG_BBINSTR; + zo->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR); zo->m_verbose = pOptions->fVerbose; zo->m_statOptions = pOptions->uStats; @@ -1017,6 +1023,15 @@ void Zapper::DestroyDomain() CleanupAssembly(); // + // Shut down JIT compiler. + // + + if (m_pJitCompiler != NULL) + { + m_pJitCompiler->ProcessShutdownWork(NULL); + } + + // // Get rid of domain. // @@ -2032,10 +2047,10 @@ void Zapper::CreateCompilationDomain() BOOL fForceDebug = FALSE; if (!m_pOpt->m_autodebug) - fForceDebug = (m_pOpt->m_compilerFlags & CORJIT_FLG_DEBUG_INFO) != 0; + fForceDebug = m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); - BOOL fForceProfile = (m_pOpt->m_compilerFlags & CORJIT_FLG_PROF_ENTERLEAVE) != 0; - BOOL fForceInstrument = (m_pOpt->m_compilerFlags & CORJIT_FLG_BBINSTR) != 0; + BOOL fForceProfile = m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE); + BOOL fForceInstrument = m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR); InitEE(fForceDebug, fForceProfile, fForceInstrument); @@ -3323,28 +3338,29 @@ IMetaDataAssemblyEmit * Zapper::CreateAssemblyEmitter() void Zapper::InitializeCompilerFlags(CORCOMPILE_VERSION_INFO * pVersionInfo) { - m_pOpt->m_compilerFlags &= ~(CORJIT_FLG_DEBUG_INFO - | CORJIT_FLG_DEBUG_CODE - | CORJIT_FLG_PROF_ENTERLEAVE - | CORJIT_FLG_PROF_NO_PINVOKE_INLINE); + m_pOpt->m_compilerFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); + m_pOpt->m_compilerFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE); + m_pOpt->m_compilerFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE); + m_pOpt->m_compilerFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROF_NO_PINVOKE_INLINE); // We track debug info all the time in the ngen image - m_pOpt->m_compilerFlags |= CORJIT_FLG_DEBUG_INFO; + m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); if (pVersionInfo->wCodegenFlags & CORCOMPILE_CODEGEN_DEBUGGING) { - m_pOpt->m_compilerFlags |= (CORJIT_FLG_DEBUG_INFO| - CORJIT_FLG_DEBUG_CODE); + m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); + m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE); } if (pVersionInfo->wCodegenFlags & CORCOMPILE_CODEGEN_PROFILING) { - m_pOpt->m_compilerFlags |= CORJIT_FLG_PROF_ENTERLEAVE | CORJIT_FLG_PROF_NO_PINVOKE_INLINE; + m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE); + m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROF_NO_PINVOKE_INLINE); m_pOpt->m_ngenProfileImage = true; } if (pVersionInfo->wCodegenFlags & CORCOMPILE_CODEGEN_PROF_INSTRUMENTING) - m_pOpt->m_compilerFlags |= CORJIT_FLG_BBINSTR; + m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR); #if defined(_TARGET_X86_) @@ -3353,7 +3369,7 @@ void Zapper::InitializeCompilerFlags(CORCOMPILE_VERSION_INFO * pVersionInfo) switch (CPU_X86_FAMILY(pVersionInfo->cpuInfo.dwCPUType)) { case CPU_X86_PENTIUM_4: - m_pOpt->m_compilerFlags |= CORJIT_FLG_TARGET_P4; + m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_TARGET_P4); break; default: @@ -3362,20 +3378,25 @@ void Zapper::InitializeCompilerFlags(CORCOMPILE_VERSION_INFO * pVersionInfo) if (CPU_X86_USE_CMOV(pVersionInfo->cpuInfo.dwFeatures)) { - m_pOpt->m_compilerFlags |= CORJIT_FLG_USE_CMOV | - CORJIT_FLG_USE_FCOMI; + m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_CMOV); + m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_FCOMI); } +#if !defined(FEATURE_CORECLR) if (CPU_X86_USE_SSE2(pVersionInfo->cpuInfo.dwFeatures)) { - m_pOpt->m_compilerFlags |= CORJIT_FLG_USE_SSE2; + m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_SSE2); } +#else + // .NET Core requires SSE2. + m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_SSE2); +#endif // !defined(FEATURE_CORECLR) #endif // _TARGET_X86_ - if ( (m_pOpt->m_compilerFlags & CORJIT_FLG_DEBUG_INFO) - && (m_pOpt->m_compilerFlags & CORJIT_FLG_DEBUG_CODE) - && (m_pOpt->m_compilerFlags & CORJIT_FLG_PROF_ENTERLEAVE)) + if ( m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO) + && m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE) + && m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE)) { // // We've decided not to support debugging + optimizations disabled + profiling to diff --git a/src/zap/zapreadytorun.cpp b/src/zap/zapreadytorun.cpp index ea42a25..30ad296 100644 --- a/src/zap/zapreadytorun.cpp +++ b/src/zap/zapreadytorun.cpp @@ -291,9 +291,6 @@ void ZapImage::OutputEntrypointsTableForReadyToRun() pReadyToRunHeader->RegisterSection(READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS, pHashtableBlob); pReadyToRunHeader->RegisterSection(READYTORUN_SECTION_RUNTIME_FUNCTIONS, m_pRuntimeFunctionSection); - if (m_pImportSectionsTable->GetSize() != 0) - pReadyToRunHeader->RegisterSection(READYTORUN_SECTION_IMPORT_SECTIONS, m_pImportSectionsTable); - if (m_pLazyMethodCallHelperSection->GetNodeCount() != 0) pReadyToRunHeader->RegisterSection(READYTORUN_SECTION_DELAYLOAD_METHODCALL_THUNKS, m_pLazyMethodCallHelperSection); diff --git a/sync.cmd b/sync.cmd index e883ef7..094d0c1 100644 --- a/sync.cmd +++ b/sync.cmd @@ -1,4 +1,4 @@ -@if "%_echo%" neq "on" echo off +@if not defined _echo @echo off setlocal EnableDelayedExpansion if /I [%1] == [-?] goto Usage @@ -7,6 +7,7 @@ if /I [%1] == [-help] goto Usage @if [%1]==[] set __args=-p @call %~dp0run.cmd sync %__args% %* + @call %~dp0run.cmd sync -PublishTestNativeBins %__args% %* @exit /b %ERRORLEVEL% :Usage @@ -24,6 +25,8 @@ echo -AzureToken="Access token" echo To download a specific group of product packages, specify: echo -BuildMajor echo -BuildMinor +echo To download from a specific container, specify: +echo -Container="container name" echo. echo. echo If no option is specified then sync.cmd -p is implied. \ No newline at end of file diff --git a/tests/arm64/Tests.lst b/tests/arm64/Tests.lst index 15c0d17..5b2792b 100644 --- a/tests/arm64/Tests.lst +++ b/tests/arm64/Tests.lst @@ -2412,7 +2412,7 @@ RelativePath=baseservices\threading\interlocked\compareexchange\CompareExchangeT WorkingDir=baseservices\threading\interlocked\compareexchange\CompareExchangeTClass Expected=0 MaxAllowedDurationSeconds=600 -Categories=NEW;EXPECTED_PASS;UNSTABLE +Categories=NEW;EXPECTED_FAIL;UNSTABLE HostStyle=0 [CompareExchangeTClass_1.cmd_345] RelativePath=baseservices\threading\interlocked\compareexchange\CompareExchangeTClass_1\CompareExchangeTClass_1.cmd @@ -10532,7 +10532,7 @@ RelativePath=CoreMangLib\cti\system\globalization\regioninfo\RegionInfoCurrentRe WorkingDir=CoreMangLib\cti\system\globalization\regioninfo\RegionInfoCurrentRegion Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri1;RT;EXPECTED_PASS +Categories=Pri1;RT;EXPECTED_FAIL HostStyle=0 [RegionInfoEquals.cmd_1505] RelativePath=CoreMangLib\cti\system\globalization\regioninfo\RegionInfoEquals\RegionInfoEquals.cmd @@ -20990,7 +20990,7 @@ RelativePath=GC\Scenarios\FinalizeTimeout\FinalizeTimeout\FinalizeTimeout.cmd WorkingDir=GC\Scenarios\FinalizeTimeout\FinalizeTimeout Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;EXPECTED_PASS +Categories=Pri0;EXPECTED_FAIL HostStyle=0 [finalnstruct.cmd_3013] RelativePath=GC\Scenarios\FinalNStruct\finalnstruct\finalnstruct.cmd @@ -23930,7 +23930,7 @@ RelativePath=GC\Scenarios\GCSimulator\GCSimulator_81\GCSimulator_81.cmd WorkingDir=GC\Scenarios\GCSimulator\GCSimulator_81 Expected=0 MaxAllowedDurationSeconds=600 -Categories=NEW;EXPECTED_PASS +Categories=NEW;EXPECTED_FAIL HostStyle=0 [GCSimulator_82.cmd_3433] RelativePath=GC\Scenarios\GCSimulator\GCSimulator_82\GCSimulator_82.cmd @@ -42592,7 +42592,7 @@ RelativePath=JIT\Methodical\divrem\div\decimaldiv_cs_do\decimaldiv_cs_do.cmd WorkingDir=JIT\Methodical\divrem\div\decimaldiv_cs_do Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [decimaldiv_cs_r.cmd_6168] RelativePath=JIT\Methodical\divrem\div\decimaldiv_cs_r\decimaldiv_cs_r.cmd @@ -42606,7 +42606,7 @@ RelativePath=JIT\Methodical\divrem\div\decimaldiv_cs_ro\decimaldiv_cs_ro.cmd WorkingDir=JIT\Methodical\divrem\div\decimaldiv_cs_ro Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [i4div_cs_d.cmd_6170] RelativePath=JIT\Methodical\divrem\div\i4div_cs_d\i4div_cs_d.cmd @@ -42620,7 +42620,7 @@ RelativePath=JIT\Methodical\divrem\div\i4div_cs_do\i4div_cs_do.cmd WorkingDir=JIT\Methodical\divrem\div\i4div_cs_do Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [i4div_cs_r.cmd_6172] RelativePath=JIT\Methodical\divrem\div\i4div_cs_r\i4div_cs_r.cmd @@ -42634,7 +42634,7 @@ RelativePath=JIT\Methodical\divrem\div\i4div_cs_ro\i4div_cs_ro.cmd WorkingDir=JIT\Methodical\divrem\div\i4div_cs_ro Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [i8div_cs_d.cmd_6174] RelativePath=JIT\Methodical\divrem\div\i8div_cs_d\i8div_cs_d.cmd @@ -42648,7 +42648,7 @@ RelativePath=JIT\Methodical\divrem\div\i8div_cs_do\i8div_cs_do.cmd WorkingDir=JIT\Methodical\divrem\div\i8div_cs_do Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [i8div_cs_r.cmd_6176] RelativePath=JIT\Methodical\divrem\div\i8div_cs_r\i8div_cs_r.cmd @@ -42662,7 +42662,7 @@ RelativePath=JIT\Methodical\divrem\div\i8div_cs_ro\i8div_cs_ro.cmd WorkingDir=JIT\Methodical\divrem\div\i8div_cs_ro Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [negSignedMod.cmd_6178] RelativePath=JIT\Methodical\divrem\div\negSignedMod\negSignedMod.cmd @@ -42683,7 +42683,7 @@ RelativePath=JIT\Methodical\divrem\div\overlddiv_cs_do\overlddiv_cs_do.cmd WorkingDir=JIT\Methodical\divrem\div\overlddiv_cs_do Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [overlddiv_cs_r.cmd_6181] RelativePath=JIT\Methodical\divrem\div\overlddiv_cs_r\overlddiv_cs_r.cmd @@ -42697,7 +42697,7 @@ RelativePath=JIT\Methodical\divrem\div\overlddiv_cs_ro\overlddiv_cs_ro.cmd WorkingDir=JIT\Methodical\divrem\div\overlddiv_cs_ro Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [r4div_cs_d.cmd_6183] RelativePath=JIT\Methodical\divrem\div\r4div_cs_d\r4div_cs_d.cmd @@ -42711,7 +42711,7 @@ RelativePath=JIT\Methodical\divrem\div\r4div_cs_do\r4div_cs_do.cmd WorkingDir=JIT\Methodical\divrem\div\r4div_cs_do Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [r4div_cs_r.cmd_6185] RelativePath=JIT\Methodical\divrem\div\r4div_cs_r\r4div_cs_r.cmd @@ -42725,7 +42725,7 @@ RelativePath=JIT\Methodical\divrem\div\r4div_cs_ro\r4div_cs_ro.cmd WorkingDir=JIT\Methodical\divrem\div\r4div_cs_ro Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [r8div_cs_d.cmd_6187] RelativePath=JIT\Methodical\divrem\div\r8div_cs_d\r8div_cs_d.cmd @@ -42739,7 +42739,7 @@ RelativePath=JIT\Methodical\divrem\div\r8div_cs_do\r8div_cs_do.cmd WorkingDir=JIT\Methodical\divrem\div\r8div_cs_do Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [r8div_cs_r.cmd_6189] RelativePath=JIT\Methodical\divrem\div\r8div_cs_r\r8div_cs_r.cmd @@ -42753,7 +42753,7 @@ RelativePath=JIT\Methodical\divrem\div\r8div_cs_ro\r8div_cs_ro.cmd WorkingDir=JIT\Methodical\divrem\div\r8div_cs_ro Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [u4div_cs_d.cmd_6191] RelativePath=JIT\Methodical\divrem\div\u4div_cs_d\u4div_cs_d.cmd @@ -42767,7 +42767,7 @@ RelativePath=JIT\Methodical\divrem\div\u4div_cs_do\u4div_cs_do.cmd WorkingDir=JIT\Methodical\divrem\div\u4div_cs_do Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [u4div_cs_r.cmd_6193] RelativePath=JIT\Methodical\divrem\div\u4div_cs_r\u4div_cs_r.cmd @@ -42781,7 +42781,7 @@ RelativePath=JIT\Methodical\divrem\div\u4div_cs_ro\u4div_cs_ro.cmd WorkingDir=JIT\Methodical\divrem\div\u4div_cs_ro Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [u8div_cs_d.cmd_6195] RelativePath=JIT\Methodical\divrem\div\u8div_cs_d\u8div_cs_d.cmd @@ -42795,7 +42795,7 @@ RelativePath=JIT\Methodical\divrem\div\u8div_cs_do\u8div_cs_do.cmd WorkingDir=JIT\Methodical\divrem\div\u8div_cs_do Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [u8div_cs_r.cmd_6197] RelativePath=JIT\Methodical\divrem\div\u8div_cs_r\u8div_cs_r.cmd @@ -42809,7 +42809,7 @@ RelativePath=JIT\Methodical\divrem\div\u8div_cs_ro\u8div_cs_ro.cmd WorkingDir=JIT\Methodical\divrem\div\u8div_cs_ro Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [decimalrem_cs_d.cmd_6199] RelativePath=JIT\Methodical\divrem\rem\decimalrem_cs_d\decimalrem_cs_d.cmd @@ -42823,7 +42823,7 @@ RelativePath=JIT\Methodical\divrem\rem\decimalrem_cs_do\decimalrem_cs_do.cmd WorkingDir=JIT\Methodical\divrem\rem\decimalrem_cs_do Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [decimalrem_cs_r.cmd_6201] RelativePath=JIT\Methodical\divrem\rem\decimalrem_cs_r\decimalrem_cs_r.cmd @@ -42837,7 +42837,7 @@ RelativePath=JIT\Methodical\divrem\rem\decimalrem_cs_ro\decimalrem_cs_ro.cmd WorkingDir=JIT\Methodical\divrem\rem\decimalrem_cs_ro Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [i4rem_cs_d.cmd_6203] RelativePath=JIT\Methodical\divrem\rem\i4rem_cs_d\i4rem_cs_d.cmd @@ -42851,7 +42851,7 @@ RelativePath=JIT\Methodical\divrem\rem\i4rem_cs_do\i4rem_cs_do.cmd WorkingDir=JIT\Methodical\divrem\rem\i4rem_cs_do Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [i4rem_cs_r.cmd_6205] RelativePath=JIT\Methodical\divrem\rem\i4rem_cs_r\i4rem_cs_r.cmd @@ -42865,7 +42865,7 @@ RelativePath=JIT\Methodical\divrem\rem\i4rem_cs_ro\i4rem_cs_ro.cmd WorkingDir=JIT\Methodical\divrem\rem\i4rem_cs_ro Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [i8rem_cs_d.cmd_6207] RelativePath=JIT\Methodical\divrem\rem\i8rem_cs_d\i8rem_cs_d.cmd @@ -42879,7 +42879,7 @@ RelativePath=JIT\Methodical\divrem\rem\i8rem_cs_do\i8rem_cs_do.cmd WorkingDir=JIT\Methodical\divrem\rem\i8rem_cs_do Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [i8rem_cs_r.cmd_6209] RelativePath=JIT\Methodical\divrem\rem\i8rem_cs_r\i8rem_cs_r.cmd @@ -42893,7 +42893,7 @@ RelativePath=JIT\Methodical\divrem\rem\i8rem_cs_ro\i8rem_cs_ro.cmd WorkingDir=JIT\Methodical\divrem\rem\i8rem_cs_ro Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [overldrem_cs_d.cmd_6211] RelativePath=JIT\Methodical\divrem\rem\overldrem_cs_d\overldrem_cs_d.cmd @@ -42907,7 +42907,7 @@ RelativePath=JIT\Methodical\divrem\rem\overldrem_cs_do\overldrem_cs_do.cmd WorkingDir=JIT\Methodical\divrem\rem\overldrem_cs_do Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [overldrem_cs_r.cmd_6213] RelativePath=JIT\Methodical\divrem\rem\overldrem_cs_r\overldrem_cs_r.cmd @@ -42921,7 +42921,7 @@ RelativePath=JIT\Methodical\divrem\rem\overldrem_cs_ro\overldrem_cs_ro.cmd WorkingDir=JIT\Methodical\divrem\rem\overldrem_cs_ro Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [r4rem_cs_d.cmd_6215] RelativePath=JIT\Methodical\divrem\rem\r4rem_cs_d\r4rem_cs_d.cmd @@ -42935,7 +42935,7 @@ RelativePath=JIT\Methodical\divrem\rem\r4rem_cs_do\r4rem_cs_do.cmd WorkingDir=JIT\Methodical\divrem\rem\r4rem_cs_do Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [r4rem_cs_r.cmd_6217] RelativePath=JIT\Methodical\divrem\rem\r4rem_cs_r\r4rem_cs_r.cmd @@ -42949,7 +42949,7 @@ RelativePath=JIT\Methodical\divrem\rem\r4rem_cs_ro\r4rem_cs_ro.cmd WorkingDir=JIT\Methodical\divrem\rem\r4rem_cs_ro Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [r8rem_cs_d.cmd_6219] RelativePath=JIT\Methodical\divrem\rem\r8rem_cs_d\r8rem_cs_d.cmd @@ -42963,7 +42963,7 @@ RelativePath=JIT\Methodical\divrem\rem\r8rem_cs_do\r8rem_cs_do.cmd WorkingDir=JIT\Methodical\divrem\rem\r8rem_cs_do Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [r8rem_cs_r.cmd_6221] RelativePath=JIT\Methodical\divrem\rem\r8rem_cs_r\r8rem_cs_r.cmd @@ -42977,7 +42977,7 @@ RelativePath=JIT\Methodical\divrem\rem\r8rem_cs_ro\r8rem_cs_ro.cmd WorkingDir=JIT\Methodical\divrem\rem\r8rem_cs_ro Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [u4rem_cs_d.cmd_6223] RelativePath=JIT\Methodical\divrem\rem\u4rem_cs_d\u4rem_cs_d.cmd @@ -42991,7 +42991,7 @@ RelativePath=JIT\Methodical\divrem\rem\u4rem_cs_do\u4rem_cs_do.cmd WorkingDir=JIT\Methodical\divrem\rem\u4rem_cs_do Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [u4rem_cs_r.cmd_6225] RelativePath=JIT\Methodical\divrem\rem\u4rem_cs_r\u4rem_cs_r.cmd @@ -43005,7 +43005,7 @@ RelativePath=JIT\Methodical\divrem\rem\u4rem_cs_ro\u4rem_cs_ro.cmd WorkingDir=JIT\Methodical\divrem\rem\u4rem_cs_ro Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [u8rem_cs_d.cmd_6227] RelativePath=JIT\Methodical\divrem\rem\u8rem_cs_d\u8rem_cs_d.cmd @@ -43019,7 +43019,7 @@ RelativePath=JIT\Methodical\divrem\rem\u8rem_cs_do\u8rem_cs_do.cmd WorkingDir=JIT\Methodical\divrem\rem\u8rem_cs_do Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [u8rem_cs_r.cmd_6229] RelativePath=JIT\Methodical\divrem\rem\u8rem_cs_r\u8rem_cs_r.cmd @@ -43033,7 +43033,7 @@ RelativePath=JIT\Methodical\divrem\rem\u8rem_cs_ro\u8rem_cs_ro.cmd WorkingDir=JIT\Methodical\divrem\rem\u8rem_cs_ro Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;JIT;EXPECTED_PASS +Categories=Pri0;JIT;EXPECTED_FAIL HostStyle=0 [dblarray1_cs_d.cmd_6231] RelativePath=JIT\Methodical\doublearray\dblarray1_cs_d\dblarray1_cs_d.cmd @@ -47086,14 +47086,14 @@ RelativePath=JIT\Methodical\explicit\coverage\seq_byte_1_d\seq_byte_1_d.cmd WorkingDir=JIT\Methodical\explicit\coverage\seq_byte_1_d Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;EXPECTED_PASS +Categories=Pri0;EXPECTED_FAIL HostStyle=0 [seq_byte_1_r.cmd_6812] RelativePath=JIT\Methodical\explicit\coverage\seq_byte_1_r\seq_byte_1_r.cmd WorkingDir=JIT\Methodical\explicit\coverage\seq_byte_1_r Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;EXPECTED_PASS +Categories=Pri0;EXPECTED_FAIL HostStyle=0 [seq_double_1_d.cmd_6813] RelativePath=JIT\Methodical\explicit\coverage\seq_double_1_d\seq_double_1_d.cmd @@ -48059,7 +48059,7 @@ RelativePath=JIT\Methodical\fp\exgen\1000w1d_cs_do\1000w1d_cs_do.cmd WorkingDir=JIT\Methodical\fp\exgen\1000w1d_cs_do Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;EXPECTED_PASS +Categories=Pri0;EXPECTED_FAIL HostStyle=0 [1000w1d_cs_r.cmd_6951] RelativePath=JIT\Methodical\fp\exgen\1000w1d_cs_r\1000w1d_cs_r.cmd @@ -48073,7 +48073,7 @@ RelativePath=JIT\Methodical\fp\exgen\1000w1d_cs_ro\1000w1d_cs_ro.cmd WorkingDir=JIT\Methodical\fp\exgen\1000w1d_cs_ro Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;EXPECTED_PASS +Categories=Pri0;EXPECTED_FAIL HostStyle=0 [10w250d_cs_d.cmd_6953] RelativePath=JIT\Methodical\fp\exgen\10w250d_cs_d\10w250d_cs_d.cmd @@ -52560,7 +52560,7 @@ RelativePath=JIT\Methodical\tailcall\Desktop\_il_relthread-race\_il_relthread-ra WorkingDir=JIT\Methodical\tailcall\Desktop\_il_relthread-race Expected=0 MaxAllowedDurationSeconds=600 -Categories=Pri0;EXPECTED_PASS +Categories=Pri0;EXPECTED_FAIL HostStyle=0 [_il_dbgcompat_enum.cmd_7596] RelativePath=JIT\Methodical\tailcall\_il_dbgcompat_enum\_il_dbgcompat_enum.cmd @@ -64754,7 +64754,7 @@ RelativePath=Loader\classloader\generics\GenericMethods\VSW491668\VSW491668.cmd WorkingDir=Loader\classloader\generics\GenericMethods\VSW491668 Expected=0 MaxAllowedDurationSeconds=600 -Categories=NEW;EXPECTED_PASS +Categories=NEW;EXPECTED_FAIL HostStyle=0 [abstract01.cmd_9373] RelativePath=Loader\classloader\generics\Instantiation\Negative\abstract01\abstract01.cmd diff --git a/tests/build.proj b/tests/build.proj index 0dfd84d..63db903 100644 --- a/tests/build.proj +++ b/tests/build.proj @@ -38,6 +38,7 @@ + diff --git a/tests/debugger_tests/ConfigFilesGenerators/ConfigTemplate.txt b/tests/debugger_tests/ConfigFilesGenerators/ConfigTemplate.txt new file mode 100644 index 0000000..d674a72 --- /dev/null +++ b/tests/debugger_tests/ConfigFilesGenerators/ConfigTemplate.txt @@ -0,0 +1,32 @@ + + ..\.. + x64 + $(TestRoot)\Scripts + $(TestRoot)\Debuggees + $(DebuggeeRootDir)\Source + ##Insert_Runtime_Root## + ##Insert_Nuget_Cache_Root## + ProjectK + $(RuntimeRoot)\corerun.exe + $(RuntimeRoot)\dbgshim.dll + $(RuntimeRoot) + cli + 1.0.0-preview1-002702 + $(DebuggeeRootDir)\native + $(DebuggeeRootDir)\dotnet.$(CliVersion) + 1.0.0-rc2-23811 + 4.0.0-rc2-24027 + 4.0.1-rc2-23811 + ##Cli_Path## + $(NugetCacheRoot) + + myget.org dotnet-core=https://dotnet.myget.org/F/dotnet-core/api/v3/index.json; + myget.org=https://www.nuget.org/api/v2/ + + $(RuntimeRoot)\sos.dll + $(TestRoot)\mdbg + $(WorkingDir)\dumps\$(TestProduct) + $(DebuggeeDumpOutputRootDir) + $(TestRoot)\logs_$(Timestamp) + $(TestRoot)\Debuggers\cdb\cdb.exe + diff --git a/tests/debugger_tests/ConfigFilesGenerators/GenerateConfig.cmd b/tests/debugger_tests/ConfigFilesGenerators/GenerateConfig.cmd new file mode 100644 index 0000000..635df95 --- /dev/null +++ b/tests/debugger_tests/ConfigFilesGenerators/GenerateConfig.cmd @@ -0,0 +1,53 @@ +@echo off +setlocal EnableDelayedExpansion + +:: Set the default arguments for script generation. +set __RuntimeRoot=`$(TestRoot)\Runtimes\Coreclr1 +set __NugetCacheDir=`$(WorkingDir)\packages +set __CliPath= +set __ConfigFileName=Debugger.Tests.Config.txt +set __TemplateFileName=%~dp0\ConfigTemplate.txt + +:Arg_Loop +if "%1" == "" goto ArgsDone +if /i "%1" == "/?" goto Usage + +if /i "%1" == "rt" (set "__RuntimeRoot=%2"&shift&shift&goto Arg_Loop) +if /i "%1" == "nc" (set "__NugetCacheDir=%2"&shift&shift&goto Arg_Loop) +if /i "%1" == "cli" (set "__CliPath=%2"&shift&shift&goto Arg_Loop) + +echo Invalid commandline argument: %1 +goto Usage + +:ArgsDone + +if not exist %__TemplateFileName% ( + echo Template file %__TemplateFileName% doesn't exist. + exit /b 1 +) + +:: Delete previous config file. +if exist %__ConfigFileName% ( + echo Deleting current config file. + del %__ConfigFileName% +) + +:: powershell "Get-Content %__TemplateFileName% -replace (""##Insert_Runtime_Root##"", ""%__RuntimeRoot%"") | Output-File %__ConfigFileName% " +powershell "(Get-Content \"%__TemplateFileName%\")`"^ + "-replace \"##Insert_Runtime_Root##\", \"%__RuntimeRoot%\" `"^ + "|ForEach-Object{$_ -replace \"##Insert_Nuget_Cache_Root##\", \"%__NugetCacheDir%\"} `"^ + "|ForEach-Object{$_ -replace \"##Cli_Path##\", \"%__CliPath%\"} `"^ + "| Out-File \"%__ConfigFileName%\"" + +exit /b 0 + +:Usage +echo. +echo Usage: +echo %0 [rt ^] [nc ^] [cli ^] where: +echo. +echo ^: path to the runtime that you want to use for testing. +echo ^: path to the nuget cache. +echo ^: path to the cli tool. +exit /b 1 +endlocal diff --git a/tests/debugger_tests/ConfigFilesGenerators/GenerateConfig.sh b/tests/debugger_tests/ConfigFilesGenerators/GenerateConfig.sh new file mode 100644 index 0000000..38834ed --- /dev/null +++ b/tests/debugger_tests/ConfigFilesGenerators/GenerateConfig.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +function print_usage { + echo '' + echo 'Usage:' + echo '[rt=] [nc=] [cli=] where:' + echo ' : path to the runtime that you want to use for testing.' + echo ' : path to the nuget cache.' + echo ' : path to the cli tool.' + echo '' + echo '' +} + +# Argument variables +__RuntimeRoot='$(TestRoot)\Runtimes\Coreclr1' +__NugetCacheDir='$(WorkingDir)\packages' +__CliPath= +__ConfigFileName='Debugger.Tests.Config.txt' +__TemplateFileName='ConfigTemplate.txt' + +for i in "$@" +do + case $i in + -h|--help) + print_usage + exit $EXIT_CODE_SUCCESS + ;; + rt=*) + __RuntimeRoot=${i#*=} + ;; + nc=*) + __NugetCacheDir=${i#*=} + ;; + cli=*) + __CliPath=${i#*=} + ;; + *) + echo "Unknown switch: $i" + print_usage + exit $EXIT_CODE_SUCCESS + ;; + esac +done + +if ! -e "$__TemplateFileName" +then + echo '$__TemplateFileName does not exist' + exit 1 +fi + +if -e "$__ConfigFileName" +then + rm "$__ConfigFileName" +fi + +cp "$__TemplateFileName" "$__ConfigFileName" + +sed -i \ + 's/##Insert_Runtime_Root##/$__RuntimeRoot/g;' \ + 's/##Insert_Nuget_Cache_Root##/$__NugetCacheDir/g'\ + 's/##Cli_Path##/$__CliPath/g'\ + 's/corerun.exe/corerun/g'\ + "$__ConfigFileName" + +exit 0 \ No newline at end of file diff --git a/tests/debugger_tests/ScriptGenerator/Program.cs b/tests/debugger_tests/ScriptGenerator/Program.cs new file mode 100644 index 0000000000000000000000000000000000000000..1e9586d63e73a89bb93bd0f4a02f1045fb2548bf GIT binary patch literal 8256 zcmd5>ZEq7t5Z=#~`X7!o21k?&fmUrPX&Vx!pqeCd0tEqr#JMCE@k?z7h!FkhZJ%ex zzW(aXmM1r!I2)?h?PIE^&SLqx;f*;nJf|@M{3t zX~9@}X6!oPaN^GK-34{e4KXjzFFU6#TKrK-_rUE|(sV>qO7264*tMa-p*zO&cs7@| z4e*ZR6F0(B7f+Gf6kR9yruG{c8R4mi(ZjhVocmt96JZ8FBgi|N(M6y=2lWJ>$n8Pm z5WXFYEY7q!Sq}Dg)vbc!z@0%R=QA2(@eJdmk)cM^hMGt2Ek@7ri6A9`O|(%*BizZM zD;!4fLt1`bVuI*X#-V!+E)gO~FP!6>G87^7l-iPr24nEQQ^Gfbr*66r;C2JoL-3u# zwjp8>&HZ1d7w50d=kJMSXP7$$4}PDCrsE*qi|r)8Tb2B_!1V|`PsOKWckK} z4&8@%qNk_OLA|8dDz=346g^$gXCvAL0*{4zUyx>zTL;CL)`W zAubvFmfHbZ?*Zv8w}q>XUr%SxPk_P=jPE<<&Q6L$gx_t@zXa}gk+m&6b?~$cjn-YG z;B6x_yJ(izF9Nrhb1d)AaX5uOwDU}4{0aLQ@q4@dWS2*w^g=SXa?Y{6(F9)*=G7VAw~=#F*MSA zydl-aNMCZ1;ew2A0-;2Fhc3wE$NvxX6m>+TA?*O7>J1R0O< zyN$PLUl+x&QGyFazz8x%kU~xm+%|045!6J$?2;g-OtXeiMbMBq=Zu@PH%;Nl+SGy_ z_rX)Ky(RZ2^7fG+gGkn@vJG@R5c{?YW*3jDry^9_BXC)hc`G8LjXY`L=~FZzPWNSg zktW5XSxqz#R^Sa?FRe8FKAwxB&%fVB_Az68Rd@w#y@i}t z!gV^s_XJ2D;^R53Lv~t1$Y~XoJBHo-R^2>m`8&IAyo6M%OTNyqMiA{|@sn1|Ht=>2 z+HBx@iX8U!X?Y>f&^NwjvA*{qftBpSU57mSbdheWK@}t4U3l+U@}AYryhQKhvzzp+ zcDjbJ;|VK2DeBAr|EgzI?DKV#mVE{9?!nv4C|1foK8NtfG2U>zs-`ZxpBK=L;CuGF z33%mev1T?Uq-$puUHMorhQ-k(C*K=TURwSg!BF0oG)<^umg9!lasl6*qr)R2^W4&_ z4QKbzpG59i4Qj18TziZ7mT4Ke7qhCs-ftk!tdeP8?4YONx>0|vj(>ROP%YGw$n z`Z(@IRo-(~6r4boRd|zNm7e$Pej;1@-vF~csTB_q8`kxvVA*yF&)^?+{$up6lUZF( z^X7B$-ovOE#pav?cTe>5DUi+1`--gDw-<0W9_12@iusrBwSI@zj6wpLv@C%hOX%k& z(1yDk;?TONyFy3ba2Lc~7FP!PPHXs2c)lA{(QwqSED_?}!}`d*%~q6Ch^~W8tOnfkaUJGf@Dgi|Qnp|TcX5|FiYB~hRGtst*{>B)WIF-# zU3h2ZpQ5sJWiFrbVUFsMM^rKr?p)aaawj^3UFI8hbZJj%ebw%Ru{1ifIb5$j>Ykye zcmdn#`6bw8yRW56e-IIt3&aK2Iy(t4`JtW`(QF@*)@Dt#Dfequa(b6|FxUUnHMmtn zgAjp+BGv=;cZ?3R>MibzXqj<~_BM>hW6bBSUr%+`-4F7K7u-2x6EQfSVUxQOYH%S@ z;@YCQ<O>Nc)wOoX=5AK6?r-zWmg zS||KS}U0e@8G*wVsrvK)VKbOYa7vFR}=Cvjz4f1#*$KHXvsYP|n5E_GK4|*mu?X~kFkE)q=0;%1Ib_iwhs%!gyzly(s zt;7#czU^#^9Tf2t=AfbA07zm_J^@k~;e9;QYuxRy3mss*DZXEK?7LW>6p`r@U!7g$ z37)6Y3p|n6yflrqGwg#u;~QG=Z{*(rBqk!Cz1kEXW(QA#iDUYQ@6=aKtWjmuE11by z{kbo=4l={FI)~ipKlL)td8@fs`Ozwnb@QsZcJBjdqGyy>-PO5WjO%M?JrWDGS5Ufg z-*NRR3+Uj?a+F%B{Nlxz{oG8lrIxcRqVQMpM4- zo91@UTEHsEH^uci?1ZU#*gdlos^^Egu{TZYRMf2gA1gsoc4cOLdIgGSXCd?rD?lix z9=6O9yXRNB7=5PJ4Q5?_JTLjB{r(5Jj?A_I literal 0 HcmV?d00001 diff --git a/tests/debugger_tests/ScriptGenerator/project.json b/tests/debugger_tests/ScriptGenerator/project.json new file mode 100644 index 0000000000000000000000000000000000000000..25c7a269c6e5137258567789ff89bc8a1b90273e GIT binary patch literal 1106 zcmb7D%TB{E5S%j-|4{h|G%C=i3(HX$hbb&yT=GH(03mP+&yv-FPJkrMT|QXs2gO}U^{NZ zACq4YuNYy$_@vEIFk?x4#Q&+@@3I(df*ILsTv1ug*ahy1nd+5MD!X%HZ9OYbspOW7 z8MVrDOl-nh4R#4XdP1&<854YHWp7TTg_e^+MVF&Hwb?HEPOwN96}0{T5B`xos93W&E5L)+AP$zP2e@V@BJGuu-RL!E zVaPwHya(J{pVGGal;*SUwr+dcz)Dq$*)sORdMVUdc2#eDC;B7p>4> %DEBUGGERTESTS_INSTALL_LOG% + +if errorlevel 1 ( + echo Failed to install debuggertests to %__InstallDir% + goto Fail +) + +REM ========================================================================================= +REM === +REM === Setting up the right config file. +REM === +REM ========================================================================================= +echo Generating config file. + +call %__ThisScriptPath%\ConfigFilesGenerators\GenerateConfig.cmd rt %__CoreclrBinPath% nc %__NugetCacheDir% cli %__CliPath% +move Debugger.Tests.Config.txt %__InstallDir%\\Debugger.Tests\dotnet\Debugger.Tests.Config.txt + +REM ========================================================================================= +REM === +REM === Scripts generation. +REM === +REM ========================================================================================= +mkdir %__InstallDir%\ScriptGenerator +copy %__ThisScriptPath%\ScriptGenerator\* %__InstallDir%\ScriptGenerator\ +pushd %__InstallDir%\ScriptGenerator +%__CliPath%\dotnet restore +%__CliPath%\dotnet build +popd + +%__CliPath%\dotnet run --project %__InstallDir%\ScriptGenerator %__InstallDir% %__CoreclrBinPath% %__InstallDir%\Dotnet.Tests\dotnet + +REM Deleting runtests.cmd to avoid double test-running. +del %__InstallDir%\runtests.cmd + +if errorlevel 1 ( + echo Failed to build and run script generation. + goto Fail +) + + + +exit /b 0 + +:Fail +exit /b 1 + +REM ========================================================================================= +REM === +REM === Helper routines +REM === +REM ========================================================================================= + +:Usage +echo. +echo install debugger tests +echo. +echo Usage: +echo %__ThisScriptShort% /coreclrBinDir ^ /outputDir ^ /nugetCacheDir ^ +echo. +exit /b 1 diff --git a/tests/debugger_tests/setup-debuggertests.sh b/tests/debugger_tests/setup-debuggertests.sh new file mode 100644 index 0000000000000000000000000000000000000000..315359c373356f6ddc2a67c9cba99ed4877f7b36 GIT binary patch literal 6494 zcmd^D+iu%N5S`}&{RhStkTj@hImnY;_a-HU0V6JKrwCdEg{+Gu)Rq*Hiqa(g^)~0s zYP3s=m&!2;0|h}Y$=#Wqoy(co{paspc_4doDPx&v+m%E{@}+#C_fQu2-;)&mQ@lko zlevyf<#+TY(v>S2;Qt35AK{JH05l^|MDh?9xfS*FG42vvu9U|dvkbs7#U1G!eDBIN zt_bZ!`e;cr!=I`AiLV6nP@Wk^#uYP_%WwvMZy>`MdOmrM=s~u*{HXGGl&ew1R>UFc$j_d2<&<@FpR z@H3wElF)u*DYuzvD{Svpl5!bc&tL24+=Z@x$a!ldZ?Rg&L>Jb$h8`0gU*(^S&mxcE zf3L?)%dp?+>u1bH|2|sFHdOCr9J^SKWJenEJ)WfMqnE8|krqnScN%Mou;0ctF~>)Z zH+sl5Jp8K+9~)01l63S02L>&QEMz`L;^BB44PJs)*)pq^a`2I;pB???yVqi#kd2 zaq{`I*Ujj2@D6--B7fkX$`ViJO=5PcNK5o$)Vava`-y$ur${2E5z!faM3M=xfbYD= znmd2Pnws(+PohqF#Oz?iYuq1kMUti3^ysS5<(}rK4#A%Y$(kZWje5O$MA}!%A=YTC z&1dBc@OKr|OVkV}D?C00QoVr2SkW9oACHi2C#!GjDOn*-h{7R_L-0`Q4yfnqLz5D; zs+Vj8eXvGJ`{x6AL=*Eykb{*^5A76d zXhJgPwgDt{Iq@|zNwN2sB-Vy8&wM?>H3e^1ld-;@!wcN{Blrj3C@cHNm@P&BSha5z z|JUeaozIb1YbhMRA!b-WQsZA%%d?`gd3+TcLGRU=leeL_ih1{a@FB0o+xii$O-qM< zWEQnHfgKmHP7mYiJf@0|_dg=zF+4v;`wQxsGsMC%BH{(A9R4S69pNH|F4QL&JqwKA zm#28P@T|r*lRe-5U+ik@HpI4XYs>x{uGqM;Odm!&GkgN;%y4lh%2?-qnFz=Hp2c%o zfFro;tM!@Rh$3#*vgr2ttX1gowt9MTnCbcL zz1L^=ykr+^$s9^JA0>5B{tb1QN6gRDfyae%bj{*lUNhz&ZsoMEorl=oxS^`(|uM8GA94FoVst;wt9hD7X&y#`$khi89;Fm3oF}F)hdDZR=O^ zD>%&LIiAdve*am_t4b$fhUc71^(SnR%fe- z;#m;&vhDhvKlvzW$amn=guJwL3wL=f5lXvUoyL&%jdD1}b9;G;Xg1@Mx-zW$FK2c( z+RVM7CcFo5-_FX6H4;zh_En#(p3hN9QB$ljIf7>)1AI9zCmuF$Y0vHTcmL(3)j{L_IZ{dw literal 0 HcmV?d00001 diff --git a/tests/dir.props b/tests/dir.props index 9d93e93..43026ca 100644 --- a/tests/dir.props +++ b/tests/dir.props @@ -54,7 +54,8 @@ - + + diff --git a/tests/helix.targets b/tests/helix.targets deleted file mode 100644 index 16acf01..0000000 --- a/tests/helix.targets +++ /dev/null @@ -1,78 +0,0 @@ - - - - - $(PackagesDir)test.Microsoft.NETCore.Runtime.CoreClr\1.1.1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_TestCopyLocalByFileNameWithoutDuplicates Remove="@(ToRemove)" /> - - <_TestCopyLocalByFileNameWithoutDuplicates Include="@(ToReplace)"> - test.Microsoft.NETCore.Runtime.CoreClr - %(ToReplace.Identity) - - - <_TestCopyLocalByFileNameWithoutDuplicates Include="@(XunitConsoleExe)"> - xunit.runner.console - %(XunitConsoleExe.Identity) - - - - - diff --git a/tests/issues.targets b/tests/issues.targets index ee45e58..d1f3dc2 100644 --- a/tests/issues.targets +++ b/tests/issues.targets @@ -40,6 +40,9 @@ 3392 + + 6553 + 2414 @@ -181,75 +184,37 @@ 6707 + + 8418 + - + - 3392 + 3392, test is useful to have because it can be run manually when making changes to the GC that can have effects in OOM scenarios, but not appropriate to run on our current test infrastructure. - 3392 + 3392, test is useful to have because it can be run manually when making changes to the GC that can have effects in OOM scenarios, but not appropriate to run on our current test infrastructure. - 3392 + 3392, test is useful to have because it can be run manually when making changes to the GC that can have effects in OOM scenarios, but not appropriate to run on our current test infrastructure. - 3392 - - - needs triage - - - needs triage - - - needs triage - - - needs triage + 3392, test is useful to have because it can be run manually when making changes to the GC that can have effects in OOM scenarios, but not appropriate to run on our current test infrastructure. tail. call pop ret is only supported on amd64 - - needs triage - - - needs triage - - - needs triage - - x86 JIT doesn't support implicit tail call optimization or tail. call pop ret sequence - - - 6844 + 2420. x86 JIT doesn't support implicit tail call optimization or tail. call pop ret sequence - needs triage - - - needs triage - - - - - - - - 6778 - - - 6778 - - - 6553 + 7163, fails on both legacy backend and RyuJIT - - 7008 + + The test is too large for x86 and causes OutOfMemory exception. diff --git a/tests/override.targets b/tests/override.targets index 8bdff51..36a9615 100644 --- a/tests/override.targets +++ b/tests/override.targets @@ -3,8 +3,6 @@ Overrides for all other targets (including build tools) can go in this file. --> - - diff --git a/tests/publishdependency.targets b/tests/publishdependency.targets index 554b1ee..9e286fc 100644 --- a/tests/publishdependency.targets +++ b/tests/publishdependency.targets @@ -3,18 +3,50 @@ - - netcoreapp1.0 + + netcoreapp1.1 + + + $(__BuildArch) + x64 + win7 + win8 + win10 + + + + + + + + + + + + + + + + + + + + - - + + + $(ProjectDir)\..\bin\Product\$(BuildOS).$(BuildArch).$(BuildType) + $(ProductDestination)\ref + $(CORE_ROOT)\..\coreoverlay + + @@ -23,12 +55,12 @@ - @@ -58,4 +90,147 @@ + + + + + + + + + + + + + + + + + + + + + %(Identity) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/runtest.cmd b/tests/runtest.cmd index 5620789..23b4bb5 100644 --- a/tests/runtest.cmd +++ b/tests/runtest.cmd @@ -1,10 +1,11 @@ -@if not defined __echo @echo off +@if not defined _echo @echo off setlocal EnableDelayedExpansion :: Set the default arguments set __BuildArch=x64 set __BuildType=Debug set __BuildOS=Windows_NT +set __MSBuildBuildArch=x64 :: Default to highest Visual Studio version available set __VSVersion=vs2015 @@ -30,6 +31,8 @@ set __Sequential= set __msbuildExtraArgs= set __LongGCTests= set __GCSimulatorTests= +set __AgainstPackages= +set __JitDisasm= :Arg_Loop if "%1" == "" goto ArgsDone @@ -43,6 +46,7 @@ if /i "%1" == "-help" goto Usage if /i "%1" == "x64" (set __BuildArch=x64&set __MSBuildBuildArch=x64&shift&goto Arg_Loop) if /i "%1" == "x86" (set __BuildArch=x86&set __MSBuildBuildArch=x86&shift&goto Arg_Loop) +if /i "%1" == "arm" (set __BuildArch=arm&set __MSBuildBuildArch=arm&shift&goto Arg_Loop) if /i "%1" == "debug" (set __BuildType=Debug&shift&goto Arg_Loop) if /i "%1" == "release" (set __BuildType=Release&shift&goto Arg_Loop) @@ -55,6 +59,7 @@ if /i "%1" == "SkipWrapperGeneration" (set __SkipWrapperGeneration=true&shift&go if /i "%1" == "Exclude" (set __Exclude=%2&shift&shift&goto Arg_Loop) if /i "%1" == "Exclude0" (set __Exclude0=%2&shift&shift&goto Arg_Loop) if /i "%1" == "TestEnv" (set __TestEnv=%2&shift&shift&goto Arg_Loop) +if /i "%1" == "AgainstPackages" (set __AgainstPackages=1&shift&goto Arg_Loop) if /i "%1" == "sequential" (set __Sequential=1&shift&goto Arg_Loop) if /i "%1" == "crossgen" (set __DoCrossgen=1&shift&goto Arg_Loop) if /i "%1" == "longgc" (set __LongGCTests=1&shift&goto Arg_Loop) @@ -63,11 +68,12 @@ if /i "%1" == "jitstress" (set COMPlus_JitStress=%2&shift&shift&goto if /i "%1" == "jitstressregs" (set COMPlus_JitStressRegs=%2&shift&shift&goto Arg_Loop) if /i "%1" == "jitminopts" (set COMPlus_JITMinOpts=1&shift&shift&goto Arg_Loop) if /i "%1" == "jitforcerelocs" (set COMPlus_ForceRelocs=1&shift&shift&goto Arg_Loop) +if /i "%1" == "jitdisasm" (set __JitDisasm=1&shift&goto Arg_Loop) if /i "%1" == "GenerateLayoutOnly" (set __GenerateLayoutOnly=1&set __SkipWrapperGeneration=true&shift&goto Arg_Loop) if /i "%1" == "PerfTests" (set __PerfTests=true&set __SkipWrapperGeneration=true&shift&goto Arg_Loop) if /i "%1" == "runcrossgentests" (set RunCrossGen=true&shift&goto Arg_Loop) REM change it to COMPlus_GCStress when we stop using xunit harness -if /i "%1" == "gcstresslevel" (set __GCSTRESSLEVEL=%2&set __TestTimeout=1800000&shift&shift&goto Arg_Loop) +if /i "%1" == "gcstresslevel" (set __GCSTRESSLEVEL=%2&set __TestTimeout=1800000&shift&shift&goto Arg_Loop) if /i not "%1" == "msbuildargs" goto SkipMsbuildArgs :: All the rest of the args will be collected and passed directly to msbuild. @@ -142,6 +148,10 @@ if not defined __Sequential ( set __msbuildCommonArgs=%__msbuildCommonArgs% /p:ParallelRun=false ) +if defined __AgainstPackages ( + set __msbuildCommonArgs=%__msbuildCommonArgs% /p:BuildTestsAgainstPackages=true +) + REM Prepare the Test Drop REM Cleans any NI from the last run powershell "Get-ChildItem -path %__TestWorkingDir% -Include '*.ni.*' -Recurse -Force | Remove-Item -force" @@ -160,8 +170,8 @@ xcopy /s "%__BinDir%" "%CORE_ROOT%" :SkipCoreRootSetup -if defined __Exclude (if not exist %__Exclude% echo %__MsgPrefix%Error: Exclusion .targets file not found && exit /b 1) -if defined __TestEnv (if not exist %__TestEnv% echo %__MsgPrefix%Error: Test Environment script not found && exit /b 1) +if defined __Exclude (if not exist %__Exclude% echo %__MsgPrefix%Error: Exclusion file %__Exclude% not found && exit /b 1) +if defined __TestEnv (if not exist %__TestEnv% echo %__MsgPrefix%Error: Test Environment script %__TestEnv% not found && exit /b 1) REM These log files are created automatically by the test run process. Q: what do they depend on being set? set __TestRunHtmlLog=%__LogsDir%\TestRun_%__BuildOS%__%__BuildArch%__%__BuildType%.html @@ -185,7 +195,7 @@ call :PrecompileFX :SkipPrecompileFX if defined __GenerateLayoutOnly ( - exit /b 1 + exit /b 0 ) if not exist %CORE_ROOT%\coreclr.dll ( @@ -248,6 +258,8 @@ REM ============================================================================ REM Compile the managed assemblies in Core_ROOT before running the tests :PrecompileAssembly +if defined __JitDisasm goto :jitdisasm + REM Skip mscorlib since it is already precompiled. if /I "%3" == "mscorlib.dll" exit /b 0 if /I "%3" == "mscorlib.ni.dll" exit /b 0 @@ -267,6 +279,27 @@ if %__exitCode% neq 0 ( echo Successfully precompiled %2 exit /b 0 +:jitdisasm + +if /I "%3" == "mscorlib.ni.dll" exit /b 0 + +echo "%1\corerun" "%1\jit-dasm.dll" --crossgen %1\crossgen.exe --platform %CORE_ROOT% --output %__TestWorkingDir%\dasm "%2" +"%1\corerun" "%1\jit-dasm.dll" --crossgen %1\crossgen.exe --platform %CORE_ROOT% --output %__TestWorkingDir%\dasm "%2" +set /a __exitCode = %errorlevel% + +if "%__exitCode%" == "-2146230517" ( + echo %2 is not a managed assembly. + exit /b 0 +) + +if %__exitCode% neq 0 ( + echo Unable to precompile %2 + exit /b 0 +) + +echo Successfully precompiled and generated dasm for %2 +exit /b 0 + :PrecompileFX for %%F in (%CORE_ROOT%\*.dll) do call :PrecompileAssembly "%CORE_ROOT%" "%%F" %%~nF%%~xF exit /b 0 @@ -297,6 +330,7 @@ set __msbuildLogArgs=^ set __msbuildArgs=%* %__msbuildCommonArgs% %__msbuildLogArgs% @REM The next line will overwrite the existing log file, if any. +echo %_msbuildexe% %__msbuildArgs% echo Invoking: %_msbuildexe% %__msbuildArgs% > "%__BuildLog%" %_msbuildexe% %__msbuildArgs% @@ -334,13 +368,23 @@ if defined __GCSimulatorTests ( set RunningGCSimulatorTests=1 ) +if defined __JitDisasm ( + if defined __DoCrossgen ( + echo Running jit disasm on framework and test assemblies + ) + if not defined __DoCrossgen ( + echo Running jit disasm on test assemblies only + ) + set RunningJitDisasm=1 +) + set __BuildLogRootName=Tests_GenerateRuntimeLayout call :msbuild "%__ProjectFilesDir%\runtest.proj" /p:GenerateRuntimeLayout=true if errorlevel 1 ( echo Test Dependency Resolution Failed exit /b 1 ) -echo %__MsgPrefix% Created the runtime layout with all dependencies in %CORE_ROOT% +echo %__MsgPrefix%Created the runtime layout with all dependencies in %CORE_ROOT% exit /b 0 @@ -360,12 +404,14 @@ echo Set to "" to disable default exclusion file. echo Exclude- Optional parameter - this will exclude individual tests from running, specified by ExcludeList ItemGroup in an .targets file. echo TestEnv- Optional parameter - this will run a custom script to set custom test environment settings. echo VSVersion- Optional parameter - VS2013 or VS2015 ^(default: VS2015^) +echo AgainstPackages - Optional parameter - this indicates that we are running tests that were built against packages echo GenerateLayoutOnly - If specified will not run the tests and will only create the Runtime Dependency Layout echo RunCrossgenTests - Runs ReadytoRun tests echo jitstress n - Runs the tests with COMPlus_JitStress=n echo jitstressregs n - Runs the tests with COMPlus_JitStressRegs=n echo jitminopts - Runs the tests with COMPlus_JITMinOpts=1 echo jitforcerelocs - Runs the tests with COMPlus_ForceRelocs=1 +echo jitdisasm - Runs jit-dasm on the tests echo gcstresslevel n - Runs the tests with COMPlus_GCStress=n echo 0: None 1: GC on all allocs and 'easy' places echo 2: GC on transitions to preemptive GC 4: GC on every allowable JITed instr diff --git a/tests/runtest.proj b/tests/runtest.proj index c02b8c8..acc4545 100644 --- a/tests/runtest.proj +++ b/tests/runtest.proj @@ -64,7 +64,6 @@ $(_XunitEpilog) ]]> - 2.1.0 @@ -120,7 +119,6 @@ $(_XunitEpilog) %24(TestWrappersPackagesConfigFileDirectory)project.lock.json - $(XunitTestBinBase)\$(Category)\ @@ -307,31 +305,7 @@ namespace $([System.String]::Copy($(Category)).Replace(".","_").Replace("\",""). - - - - - { "dependencies": { "xunit.runner.msbuild": "$(XunitPackageVersion)" }, "frameworks": { "net45": {} } } - $(BaseOutputPath)\tempRestoreProject - $(XunitRunnerRestoreProjectDir)\project.json - - - - - - - - + @@ -349,6 +323,28 @@ namespace $([System.String]::Copy($(Category)).Replace(".","_").Replace("\",""). Properties="Language=C#" /> + + + + + + + + + + + + + + + + + + + $([MSBuild]::MakeRelative($(OutputPath), $(_CLRTestToRunFileFullPath)).Replace("\","/")) + $(MSBuildProjectName).exe + $(BaseOutputPathWithConfig.Replace("\","/"))dasm/$(BuildProjectRelativeDir.Replace("\","/")) + + + + + + + + + $([MSBuild]::MakeRelative($(OutputPath), $(_CLRTestToRunFileFullPath))) + $(MSBuildProjectName).exe + $(BaseOutputPathWithConfig)dasm\$(BuildProjectRelativeDir) + + + + + + + + + + + + + + + + + diff --git a/tests/src/Common/Platform/platformdefines.cpp b/tests/src/Common/Platform/platformdefines.cpp index 4caead5..82061ac 100644 --- a/tests/src/Common/Platform/platformdefines.cpp +++ b/tests/src/Common/Platform/platformdefines.cpp @@ -89,7 +89,7 @@ int TP_slen(LPWSTR str) return len; } -int TP_scmp_s(LPSTR str1, LPSTR str2) +int TP_scmp_s(LPCSTR str1, LPCSTR str2) { // < 0 str1 less than str2 // 0 str1 identical to str2 @@ -277,7 +277,7 @@ DWORD TP_GetFullPathName(LPWSTR fileName, DWORD nBufferLength, LPWSTR lpBuffer) return GetFullPathNameW(fileName, nBufferLength, lpBuffer, NULL); #else char nativeFullPath[MAX_PATH]; - realpath(HackyConvertToSTR(fileName), nativeFullPath); + (void)realpath(HackyConvertToSTR(fileName), nativeFullPath); LPWSTR fullPathForCLR = HackyConvertToWSTR(nativeFullPath); wcscpy_s(lpBuffer, MAX_PATH, fullPathForCLR); return wcslen(lpBuffer); diff --git a/tests/src/Common/Platform/platformdefines.h b/tests/src/Common/Platform/platformdefines.h index d0760fd..0961e86 100644 --- a/tests/src/Common/Platform/platformdefines.h +++ b/tests/src/Common/Platform/platformdefines.h @@ -72,7 +72,7 @@ LPWSTR HackyConvertToWSTR(char* pszInput); typedef pthread_t THREAD_ID; typedef void* (*MacWorker)(void*); -typedef DWORD (*LPTHREAD_START_ROUTINE)(void*); +typedef DWORD __stdcall (*LPTHREAD_START_ROUTINE)(void*); #ifdef UNICODE typedef WCHAR TCHAR; #else // ANSI @@ -87,7 +87,7 @@ typedef void* HMODULE; typedef void* ULONG_PTR; typedef unsigned error_t; typedef void* LPVOID; -typedef char BYTE; +typedef unsigned char BYTE; typedef WCHAR OLECHAR; #endif @@ -97,7 +97,7 @@ typedef WCHAR OLECHAR; error_t TP_scpy_s(LPWSTR strDestination, size_t sizeInWords, LPCWSTR strSource); error_t TP_scat_s(LPWSTR strDestination, size_t sizeInWords, LPCWSTR strSource); int TP_slen(LPWSTR str); -int TP_scmp_s(LPSTR str1, LPSTR str2); +int TP_scmp_s(LPCSTR str1, LPCSTR str2); int TP_wcmp_s(LPWSTR str1, LPWSTR str2); error_t TP_getenv_s(size_t* pReturnValue, LPWSTR buffer, size_t sizeInWords, LPCWSTR varname); error_t TP_putenv_s(LPTSTR name, LPTSTR value); diff --git a/tests/src/Common/build_against_pkg_dependencies/build_against_pkg_dependencies.csproj b/tests/src/Common/build_against_pkg_dependencies/build_against_pkg_dependencies.csproj new file mode 100644 index 0000000..63c5448 --- /dev/null +++ b/tests/src/Common/build_against_pkg_dependencies/build_against_pkg_dependencies.csproj @@ -0,0 +1,15 @@ + + + + + Debug + AnyCPU + BuildOnly + + + + + + + diff --git a/tests/src/Common/build_against_pkg_dependencies/project.json b/tests/src/Common/build_against_pkg_dependencies/project.json new file mode 100644 index 0000000..5624855 --- /dev/null +++ b/tests/src/Common/build_against_pkg_dependencies/project.json @@ -0,0 +1,32 @@ +{ + "dependencies": { + "Microsoft.NETCore.ILAsm": "1.2.0-beta-24820-02", + "Microsoft.NETCore.ILDAsm": "1.2.0-beta-24820-02", + "Microsoft.NETCore.Jit": "1.2.0-beta-24820-02", + "Microsoft.NETCore.Runtime.CoreCLR": "1.2.0-beta-24820-02", + "Microsoft.NETCore.TestHost": "1.2.0-beta-24820-02" + }, + "frameworks": { + "netcoreapp1.1": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] + } + }, + "runtimes": { + "win7-x86": {}, + "win7-x64": {}, + "win10-arm64": {}, + "ubuntu.14.04-x64": {}, + "ubuntu.16.04-x64": {}, + "ubuntu.16.10-x64": {}, + "osx.10.10-x64": {}, + "centos.7-x64": {}, + "rhel.7-x64": {}, + "debian.8-x64": {}, + "fedora.23-x64": {}, + "opensuse.13.2-x64": {}, + "opensuse.42.1-x64": {} + } +} diff --git a/tests/src/Common/empty/project.json b/tests/src/Common/empty/project.json index c6d5104..1954111 100644 --- a/tests/src/Common/empty/project.json +++ b/tests/src/Common/empty/project.json @@ -2,7 +2,7 @@ "dependencies": { }, "frameworks": { - "netcoreapp1.0": {} + "netcoreapp1.1": {} }, "runtimes": { "win7-x86": {}, diff --git a/tests/src/Common/netcoreapp/project.json b/tests/src/Common/netcoreapp/project.json new file mode 100644 index 0000000..51193fc --- /dev/null +++ b/tests/src/Common/netcoreapp/project.json @@ -0,0 +1,74 @@ +{ + "version": "1.0.0-*", + "buildOptions": { + "debugType": "portable", + "emitEntryPoint": true + }, + "dependencies": { + "Microsoft.NETCore.Platforms": "1.2.0-beta-24820-02", + "Microsoft.NETCore.Targets": "1.2.0-beta-24820-02", + "System.Threading.Thread": "4.4.0-beta-24820-02", + "System.Collections": "4.4.0-beta-24820-02", + "System.Xml.XmlSerializer": "4.4.0-beta-24820-02", + "System.Collections.Concurrent": "4.4.0-beta-24820-02", + "System.ObjectModel": "4.4.0-beta-24820-02", + "System.Runtime.Numerics": "4.4.0-beta-24820-02", + "System.Collections.NonGeneric": "4.4.0-beta-24820-02", + "System.Collections.Specialized": "4.4.0-beta-24820-02", + "System.ComponentModel": "4.4.0-beta-24820-02", + "System.Reflection.Emit.Lightweight": "4.4.0-beta-24820-02", + "System.Reflection.TypeExtensions": "4.4.0-beta-24820-02", + "System.Console": "4.4.0-beta-24820-02", + "System.Diagnostics.Contracts": "4.4.0-beta-24820-02", + "System.Diagnostics.Debug": "4.4.0-beta-24820-02", + "System.Diagnostics.Process": "4.4.0-beta-24820-02", + "System.Diagnostics.Tools": "4.4.0-beta-24820-02", + "System.Diagnostics.Tracing": "4.4.0-beta-24820-02", + "System.Dynamic.Runtime": "4.4.0-beta-24820-02", + "System.Globalization": "4.4.0-beta-24820-02", + "System.Globalization.Calendars": "4.4.0-beta-24820-02", + "System.IO": "4.4.0-beta-24820-02", + "System.IO.FileSystem": "4.4.0-beta-24820-02", + "System.IO.FileSystem.Primitives": "4.4.0-beta-24820-02", + "System.Linq": "4.4.0-beta-24820-02", + "System.Linq.Queryable": "4.4.0-beta-24820-02", + "System.Linq.Expressions": "4.4.0-beta-24820-02", + "System.Reflection": "4.4.0-beta-24820-02", + "System.Reflection.Extensions": "4.4.0-beta-24820-02", + "System.Resources.ResourceManager": "4.4.0-beta-24820-02", + "System.Runtime": "4.4.0-beta-24820-02", + "System.Runtime.CompilerServices.Unsafe": "4.4.0-beta-24820-02", + "System.Runtime.Extensions": "4.4.0-beta-24820-02", + "System.Runtime.Handles": "4.4.0-beta-24820-02", + "System.Runtime.InteropServices": "4.4.0-beta-24820-02", + "System.Runtime.InteropServices.RuntimeInformation": "4.4.0-beta-24820-02", + "System.Runtime.Loader": "4.4.0-beta-24820-02", + "System.Security.Cryptography.Algorithms": "4.4.0-beta-24820-02", + "System.Text.Encoding": "4.4.0-beta-24820-02", + "System.Text.Encoding.Extensions": "4.4.0-beta-24820-02", + "System.Text.RegularExpressions": "4.4.0-beta-24820-02", + "System.Threading": "4.4.0-beta-24820-02", + "System.Threading.AccessControl": "4.4.0-beta-24820-02", + "System.Threading.Overlapped": "4.4.0-beta-24820-02", + "System.Threading.Tasks": "4.4.0-beta-24820-02", + "System.Threading.Tasks.Parallel": "4.4.0-beta-24820-02", + "System.Threading.ThreadPool": "4.4.0-beta-24820-02", + "System.Threading.Timer": "4.4.0-beta-24820-02", + "System.Xml.ReaderWriter": "4.4.0-beta-24820-02", + "System.Xml.XDocument": "4.4.0-beta-24820-02", + "System.Xml.XmlDocument": "4.4.0-beta-24820-02", + "System.Xml.XPath": "4.4.0-beta-24820-02", + "System.Xml.XPath.XmlDocument": "4.4.0-beta-24820-02", + "System.Numerics.Vectors": "4.4.0-beta-24820-02" + }, + "frameworks": { + "netcoreapp1.1": { + "dependencies": { + "Microsoft.NETCore.Runtime.CoreCLR": "1.2.0-beta-24820-02" + } + } + }, + "runtimes": { + "win7-x64": {} + } +} diff --git a/tests/src/Common/targeting_pack_ref/project.json b/tests/src/Common/targeting_pack_ref/project.json new file mode 100644 index 0000000..c1f033b --- /dev/null +++ b/tests/src/Common/targeting_pack_ref/project.json @@ -0,0 +1,22 @@ +{ + "dependencies": { + "Microsoft.TargetingPack.Private.CoreCLR": "1.2.0-beta-24820-02" + }, + "frameworks": { + "netcoreapp1.1": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] + } + }, + "runtimes": { + "win7-x86": {}, + "win7-x64": {}, + "ubuntu.14.04-x64": {}, + "osx.10.10-x64": {}, + "centos.7-x64": {}, + "rhel.7-x64": {}, + "debian.8-x64": {} + } +} diff --git a/tests/src/Common/targeting_pack_ref/targeting_pack_ref.csproj b/tests/src/Common/targeting_pack_ref/targeting_pack_ref.csproj new file mode 100644 index 0000000..65e37c0 --- /dev/null +++ b/tests/src/Common/targeting_pack_ref/targeting_pack_ref.csproj @@ -0,0 +1,12 @@ + + + + + Debug + AnyCPU + BuildOnly + + + + diff --git a/tests/src/Common/test_dependencies/project.json b/tests/src/Common/test_dependencies/project.json index 46e2601..5f05914 100644 --- a/tests/src/Common/test_dependencies/project.json +++ b/tests/src/Common/test_dependencies/project.json @@ -1,76 +1,76 @@ { "dependencies": { - "xunit": "2.1.0", - "xunit.console.netcore": "1.0.2-prerelease-00101", - "xunit.runner.utility": "2.1.0", + "xunit": "2.2.0-beta2-build3300", + "xunit.console.netcore": "1.0.2-prerelease-00177", + "xunit.runner.utility": "2.2.0-beta2-build3300", "Microsoft.CodeAnalysis.Compilers": "1.1.1", - "Microsoft.DotNet.xunit.performance": "1.0.0-alpha-build0035", - "Microsoft.DotNet.xunit.performance.analysis": "1.0.0-alpha-build0035", - "Microsoft.DotNet.xunit.performance.runner.Windows": "1.0.0-alpha-build0035", - "Microsoft.Win32.Primitives": "4.3.0", - "Newtonsoft.Json": "7.0.1", - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Collections.Immutable": "1.3.0", - "System.Threading.Thread": "4.3.0", - "System.Collections": "4.3.0", - "System.Xml.XmlSerializer": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.ObjectModel": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Collections.NonGeneric": "4.3.0", - "System.Collections.Specialized": "4.3.0", - "System.ComponentModel": "4.3.0", - "System.Reflection.Emit.Lightweight": "4.3.0", - "System.Reflection.TypeExtensions": "4.3.0", - "System.Console": "4.3.0", - "System.Diagnostics.Contracts": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Process": "4.3.0", - "System.Diagnostics.Tools": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Dynamic.Runtime": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Linq": "4.3.0", - "System.Linq.Queryable": "4.3.0", - "System.Linq.Expressions": "4.3.0", - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.CompilerServices.Unsafe": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", - "System.Runtime.Loader": "4.3.0", - "System.Runtime.Serialization.Json": "4.3.0", - "System.Runtime.Serialization.Primitives": "4.1.1", - "System.Runtime.Serialization.Xml": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Text.RegularExpressions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.AccessControl": "4.3.0", - "System.Threading.Overlapped": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.Tasks.Parallel": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "System.Threading.Timer": "4.3.0", - "System.Xml.ReaderWriter": "4.3.0", - "System.Xml.XDocument": "4.3.0", - "System.Xml.XmlDocument": "4.3.0", - "System.Xml.XPath": "4.3.0", - "System.Xml.XPath.XmlDocument": "4.3.0", - "System.Numerics.Vectors": "4.3.0" + "Microsoft.DotNet.xunit.performance": "1.0.0-alpha-build0040", + "Microsoft.DotNet.xunit.performance.analysis": "1.0.0-alpha-build0040", + "Microsoft.DotNet.xunit.performance.runner.Windows": "1.0.0-alpha-build0040", + "Microsoft.Win32.Primitives": "4.4.0-beta-24820-02", + "Newtonsoft.Json": "8.0.3", + "Microsoft.NETCore.Platforms": "1.2.0-beta-24820-02", + "Microsoft.NETCore.Targets": "1.2.0-beta-24820-02", + "System.Collections.Immutable": "1.4.0-beta-24820-02", + "System.Threading.Thread": "4.4.0-beta-24820-02", + "System.Collections": "4.4.0-beta-24820-02", + "System.Xml.XmlSerializer": "4.4.0-beta-24820-02", + "System.Collections.Concurrent": "4.4.0-beta-24820-02", + "System.ObjectModel": "4.4.0-beta-24820-02", + "System.Runtime.Numerics": "4.4.0-beta-24820-02", + "System.Collections.NonGeneric": "4.4.0-beta-24820-02", + "System.Collections.Specialized": "4.4.0-beta-24820-02", + "System.ComponentModel": "4.4.0-beta-24820-02", + "System.Reflection.Emit.Lightweight": "4.4.0-beta-24820-02", + "System.Reflection.TypeExtensions": "4.4.0-beta-24820-02", + "System.Console": "4.4.0-beta-24820-02", + "System.Diagnostics.Contracts": "4.4.0-beta-24820-02", + "System.Diagnostics.Debug": "4.4.0-beta-24820-02", + "System.Diagnostics.Process": "4.4.0-beta-24820-02", + "System.Diagnostics.Tools": "4.4.0-beta-24820-02", + "System.Diagnostics.Tracing": "4.4.0-beta-24820-02", + "System.Dynamic.Runtime": "4.4.0-beta-24820-02", + "System.Globalization": "4.4.0-beta-24820-02", + "System.Globalization.Calendars": "4.4.0-beta-24820-02", + "System.IO": "4.4.0-beta-24820-02", + "System.IO.FileSystem": "4.4.0-beta-24820-02", + "System.IO.FileSystem.Primitives": "4.4.0-beta-24820-02", + "System.Linq": "4.4.0-beta-24820-02", + "System.Linq.Queryable": "4.4.0-beta-24820-02", + "System.Linq.Expressions": "4.4.0-beta-24820-02", + "System.Reflection": "4.4.0-beta-24820-02", + "System.Reflection.Extensions": "4.4.0-beta-24820-02", + "System.Resources.ResourceManager": "4.4.0-beta-24820-02", + "System.Runtime": "4.4.0-beta-24820-02", + "System.Runtime.CompilerServices.Unsafe": "4.4.0-beta-24820-02", + "System.Runtime.Extensions": "4.4.0-beta-24820-02", + "System.Runtime.Handles": "4.4.0-beta-24820-02", + "System.Runtime.InteropServices": "4.4.0-beta-24820-02", + "System.Runtime.InteropServices.RuntimeInformation": "4.4.0-beta-24820-02", + "System.Runtime.Loader": "4.4.0-beta-24820-02", + "System.Runtime.Serialization.Json": "4.4.0-beta-24820-02", + "System.Runtime.Serialization.Primitives": "4.4.0-beta-24820-02", + "System.Runtime.Serialization.Xml": "4.4.0-beta-24820-02", + "System.Security.Cryptography.Algorithms": "4.4.0-beta-24820-02", + "System.Text.Encoding": "4.4.0-beta-24820-02", + "System.Text.Encoding.Extensions": "4.4.0-beta-24820-02", + "System.Text.RegularExpressions": "4.4.0-beta-24820-02", + "System.Threading": "4.4.0-beta-24820-02", + "System.Threading.AccessControl": "4.4.0-beta-24820-02", + "System.Threading.Overlapped": "4.4.0-beta-24820-02", + "System.Threading.Tasks": "4.4.0-beta-24820-02", + "System.Threading.Tasks.Parallel": "4.4.0-beta-24820-02", + "System.Threading.ThreadPool": "4.4.0-beta-24820-02", + "System.Threading.Timer": "4.4.0-beta-24820-02", + "System.Xml.ReaderWriter": "4.4.0-beta-24820-02", + "System.Xml.XDocument": "4.4.0-beta-24820-02", + "System.Xml.XmlDocument": "4.4.0-beta-24820-02", + "System.Xml.XPath": "4.4.0-beta-24820-02", + "System.Xml.XPath.XmlDocument": "4.4.0-beta-24820-02", + "System.Numerics.Vectors": "4.4.0-beta-24820-02" }, "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "imports": [ "dnxcore50", "portable-net45+win8" diff --git a/tests/src/Common/test_dependencies/test_dependencies.csproj b/tests/src/Common/test_dependencies/test_dependencies.csproj index f475772..0649d2b 100644 --- a/tests/src/Common/test_dependencies/test_dependencies.csproj +++ b/tests/src/Common/test_dependencies/test_dependencies.csproj @@ -5,10 +5,10 @@ Debug AnyCPU BuildOnly - $(CORE_ROOT)\.nuget\pkg + .NETCoreApp,Version=v1.1 - + - $(CORE_ROOT)\.nuget\pkg + .NETCoreApp,Version=v1.1 - + diff --git a/tests/src/CoreMangLib/cti/system/datetime/datetimeparse1.cs b/tests/src/CoreMangLib/cti/system/datetime/datetimeparse1.cs index ee92958..d759d4f 100644 --- a/tests/src/CoreMangLib/cti/system/datetime/datetimeparse1.cs +++ b/tests/src/CoreMangLib/cti/system/datetime/datetimeparse1.cs @@ -472,7 +472,7 @@ public class DateTimeParse1 day = (TestLibrary.Generator.GetInt32(-55) % 27) + 1; year = (TestLibrary.Generator.GetInt32(-55) % 100) + 1900; month = (TestLibrary.Generator.GetInt32(-55) % 12); - hour = (TestLibrary.Generator.GetInt32(-55) % 12) + hourshift; // Parse will convert perform GMT -> PST conversion + hour = (TestLibrary.Generator.GetInt32(-55) % 12) + hourshift; // Parse will convert perform GMT -> Local conversion minute = (TestLibrary.Generator.GetInt32(-55) % 60); second = (TestLibrary.Generator.GetInt32(-55) % 60); dayOfWeek = (TestLibrary.Generator.GetInt32(-55) % 7); @@ -489,10 +489,9 @@ public class DateTimeParse1 || day != dateAfter.Day || year != dateAfter.Year || (DayOfWeek)dayOfWeek != dateAfter.DayOfWeek - || minute != dateAfter.Minute || second != dateAfter.Second) { - TestLibrary.TestFramework.LogError("017", "DateTime.Parse(" + dateBefore + ") did not equal (" + c_DAYS_SH[(int)dateAfter.DayOfWeek] + ", " + dateAfter.Day + " " + c_MONTHS_SH[dateAfter.Month-1] + " " + dateAfter.Year + " " + dateAfter.Hour + ":" + dateAfter.Minute + ":" + dateAfter.Second + " GMT)"); + TestLibrary.TestFramework.LogError("017", "DateTime.Parse(" + dateBefore + ") did not equal (" + c_DAYS_SH[(int)dateAfter.DayOfWeek] + ", " + dateAfter.Day + " " + c_MONTHS_SH[dateAfter.Month-1] + " " + dateAfter.Year + " " + dateAfter.Hour + ":" + dateAfter.Minute + ":" + dateAfter.Second + " " + dateAfter.Kind + ")"); retVal = false; } } @@ -683,10 +682,9 @@ public class DateTimeParse1 if (month != dateAfter.Month || day != dateAfter.Day || year != dateAfter.Year - || minute != dateAfter.Minute || second != dateAfter.Second) { - TestLibrary.TestFramework.LogError("025", "DateTime.Parse(" + dateBefore + ") did not equal (" + dateAfter.Year + "-" + dateAfter.Month + "-" + dateAfter.Day + " " + dateAfter.Hour + ":" + dateAfter.Minute + ":" + dateAfter.Second + "Z)"); + TestLibrary.TestFramework.LogError("025", "DateTime.Parse(" + dateBefore + ") did not equal (" + dateAfter.Year + "-" + dateAfter.Month + "-" + dateAfter.Day + " " + dateAfter.Hour + ":" + dateAfter.Minute + ":" + dateAfter.Second + " " + dateAfter.Kind + ")"); retVal = false; } } diff --git a/tests/src/CoreMangLib/system/span/BasicSpanTest.cs b/tests/src/CoreMangLib/system/span/BasicSpanTest.cs new file mode 100644 index 0000000..18ec6f8 --- /dev/null +++ b/tests/src/CoreMangLib/system/span/BasicSpanTest.cs @@ -0,0 +1,804 @@ +using System; +using System.Collections.Generic; + +class ReferenceType +{ + internal byte Value; + public ReferenceType(byte value) { Value = value; } +} + +struct ValueTypeWithoutPointers +{ + internal byte Value; + public ValueTypeWithoutPointers(byte value) { Value = value; } +} + +struct ValueTypeWithPointers +{ + internal object Reference; + public ValueTypeWithPointers(object reference) { Reference = reference; } +} + +struct SevenBytesStruct +{ +#pragma warning disable 0169 + byte b1, b2, b3, b4, b5, b6, b7; +#pragma warning restore 0169 +} + +class My +{ + static int Sum(Span span) + { + int sum = 0; + for (int i = 0; i < span.Length; i++) + sum += span[i]; + return sum; + } + + static void Main() + { + int failedTestsCount = 0; + + Test(CanAccessItemsViaIndexer, "CanAccessItemsViaIndexer", ref failedTestsCount); + Test(CanAccessItemsViaIndexerStartCtor, "CanAccessItemsViaIndexerStartCtor", ref failedTestsCount); + Test(CanAccessItemsViaIndexerStartLengthCtor, "CanAccessItemsViaIndexerStartLengthCtor", ref failedTestsCount); + + Test(TestBoundaryEmptySpanStartCtor, "TestBoundaryEmptySpanStartCtor", ref failedTestsCount); + Test(TestBoundaryEmptySpanStartLengthCtor, "TestBoundaryEmptySpanStartLengthCtor", ref failedTestsCount); + + Test(ReferenceTypesAreSupported, "ReferenceTypesAreSupported", ref failedTestsCount); + + Test(CanUpdateUnderlyingArray, "CanUpdateUnderlyingArray", ref failedTestsCount); + + Test(MustNotMoveGcTypesToUnmanagedMemory, "MustNotMoveGcTypesToUnmanagedMemory", ref failedTestsCount); + + Test(TestArrayCoVariance, "TestArrayCoVariance", ref failedTestsCount); + Test(TestArrayCoVarianceStartCtor, "TestArrayCoVarianceStartCtor", ref failedTestsCount); + Test(TestArrayCoVarianceStartLengthCtor, "TestArrayCoVarianceStartLengthCtor", ref failedTestsCount); + + Test(TestArrayCoVarianceReadOnly, "TestArrayCoVarianceReadOnly", ref failedTestsCount); + + Test(CanCopyValueTypesWithoutPointersToSlice, "CanCopyValueTypesWithoutPointersToSlice", ref failedTestsCount); + Test(CanCopyValueTypesWithoutPointersToArray, "CanCopyValueTypesWithoutPointersToArray", ref failedTestsCount); + + Test(CanCopyReferenceTypesToSlice, "CanCopyReferenceTypesToSlice", ref failedTestsCount); + Test(CanCopyReferenceTypesToArray, "CanCopyReferenceTypesToArray", ref failedTestsCount); + + Test(CanCopyValueTypesWithPointersToSlice, "CanCopyValueTypesWithPointersToSlice", ref failedTestsCount); + Test(CanCopyValueTypesWithPointersToArray, "CanCopyValueTypesWithPointersToArray", ref failedTestsCount); + + Test(CanCopyValueTypesWithoutPointersToUnmanagedMemory, "CanCopyValueTypesWithoutPointersToUnmanagedMemory", ref failedTestsCount); + + Test(CanCopyOverlappingSlicesOfValueTypeWithoutPointers, "CanCopyOverlappingSlicesOfValueTypeWithoutPointers", ref failedTestsCount); + Test(CanCopyOverlappingSlicesOfValueTypeWithPointers, "CanCopyOverlappingSlicesOfValueTypeWithPointers", ref failedTestsCount); + Test(CanCopyOverlappingSlicesOfReferenceTypes, "CanCopyOverlappingSlicesOfReferenceTypes", ref failedTestsCount); + + Test(MustNotCastSpanOfValueTypesWithPointers, "MustNotCastSpanOfValueTypesWithPointers", ref failedTestsCount); + Test(IntArraySpanCastedToByteArraySpanHasSameBytesAsOriginalArray, "IntArraySpanCastedToByteArraySpanHasSameBytesAsOriginalArray", ref failedTestsCount); + Test(ByteArraySpanCastedToIntArraySpanHasSameBytesAsOriginalArray, "ByteArraySpanCastedToIntArraySpanHasSameBytesAsOriginalArray", ref failedTestsCount); + Test(SourceTypeLargerThanTargetOneCorrectlyCalcsTargetsLength, "SourceTypeLargerThanTargetOneCorrectlyCalcsTargetsLength", ref failedTestsCount); + Test(WhenSourceDoesntFitIntoTargetLengthIsZero, "WhenSourceDoesntFitIntoTargetLengthIsZero", ref failedTestsCount); + Test(WhenSourceFitsIntoTargetOnceLengthIsOne, "WhenSourceFitsIntoTargetOnceLengthIsOne", ref failedTestsCount); + Test(WhenSourceTypeLargerThanTargetAndOverflowsInt32ThrowsException, "WhenSourceTypeLargerThanTargetAndOverflowsInt32ThrowsException", ref failedTestsCount); + Test(CanCreateSpanFromString, "CanCreateSpanFromString", ref failedTestsCount); + + Test(WhenStartLargerThanLengthThrowsExceptionStartCtor, "WhenStartLargerThanLengthThrowsExceptionStartCtor", ref failedTestsCount); + Test(WhenStartLargerThanLengthThrowsExceptionStartLengthCtor, "WhenStartLargerThanLengthThrowsExceptionStartLengthCtor", ref failedTestsCount); + Test(WhenStartAndLengthLargerThanLengthThrowsExceptionStartLengthCtor, "WhenStartAndLengthLargerThanLengthThrowsExceptionStartLengthCtor", ref failedTestsCount); + + Console.WriteLine(string.Format("{0} tests has failed", failedTestsCount)); + Environment.Exit(failedTestsCount); + } + + static void CanAccessItemsViaIndexer() + { + int[] a = new int[] { 1, 2, 3 }; + Span slice = new Span(a); + AssertTrue(Sum(slice) == 6, "Failed to sum slice"); + + Span subslice = slice.Slice(1, 2); + AssertTrue(Sum(subslice) == 5, "Failed to sum subslice"); + } + + static void CanAccessItemsViaIndexerStartCtor() + { + int[] a = new int[] { 1, 2, 3 }; + Span slice = new Span(a, start: 1); + AssertTrue(Sum(slice) == 5, "Failed to sum slice"); + } + + static void CanAccessItemsViaIndexerStartLengthCtor() + { + int[] a = new int[] { 1, 2, 3 }; + Span slice = new Span(a, start: 1, length: 1); + AssertTrue(Sum(slice) == 2, "Failed to sum slice"); + } + + static void TestBoundaryEmptySpanStartCtor() + { + int[] a = new int[5]; + + Span slice = new Span(a, start: a.Length); + AssertEqual(slice.Length, 0); + } + + static void TestBoundaryEmptySpanStartLengthCtor() + { + int[] a = new int[5]; + + Span slice = new Span(a, a.Length, 0); + AssertEqual(slice.Length, 0); + + Span subSlice = new Span(a).Slice(a.Length, 0); + AssertEqual(subSlice.Length, 0); + } + + static void ReferenceTypesAreSupported() + { + var underlyingArray = new ReferenceType[] { new ReferenceType(0), new ReferenceType(1), new ReferenceType(2) }; + var slice = new Span(underlyingArray); + + for (int i = 0; i < underlyingArray.Length; i++) + { + AssertTrue(underlyingArray[i].Value == slice[i].Value, "Values are different"); + AssertTrue(object.ReferenceEquals(underlyingArray[i], slice[i]), "References are broken"); + } + } + + static unsafe void MustNotMoveGcTypesToUnmanagedMemory() + { + byte* pointerToStack = stackalloc byte[256]; + + try + { + new Span(pointerToStack, 1); + AssertTrue(false, "Expected exception for value types with references not thrown"); + } + catch (System.ArgumentException ex) + { + AssertTrue(ex.Message == "Cannot use type 'ValueTypeWithPointers'. Only value types without pointers or references are supported.", + "Exception message is incorrect"); + } + + try + { + new Span(pointerToStack, 1); + AssertTrue(false, "Expected exception for reference types not thrown"); + } + catch (System.ArgumentException ex) + { + AssertTrue(ex.Message == "Cannot use type 'ReferenceType'. Only value types without pointers or references are supported.", + "Exception message is incorrect"); + } + } + + static void TestArrayCoVariance() + { + var array = new ReferenceType[1]; + var objArray = (object[])array; + try + { + new Span(objArray); + AssertTrue(false, "Expected exception not thrown"); + } + catch (ArrayTypeMismatchException) + { + } + + var objEmptyArray = Array.Empty(); + try + { + new Span(objEmptyArray); + AssertTrue(false, "Expected exception not thrown"); + } + catch (ArrayTypeMismatchException) + { + } + } + + static void TestArrayCoVarianceStartCtor() + { + var array = new ReferenceType[1]; + var objArray = (object[])array; + try + { + new Span(objArray, start: 0); + AssertTrue(false, "Expected exception not thrown"); + } + catch (ArrayTypeMismatchException) + { + } + + var objEmptyArray = Array.Empty(); + try + { + new Span(objEmptyArray, start: 0); + AssertTrue(false, "Expected exception not thrown"); + } + catch (ArrayTypeMismatchException) + { + } + } + + static void TestArrayCoVarianceStartLengthCtor() + { + var array = new ReferenceType[1]; + var objArray = (object[])array; + try + { + new Span(objArray, start: 0, length: 1); + AssertTrue(false, "Expected exception not thrown"); + } + catch (ArrayTypeMismatchException) + { + } + + var objEmptyArray = Array.Empty(); + try + { + new Span(objEmptyArray, start: 0, length: 1); + AssertTrue(false, "Expected exception not thrown"); + } + catch (ArrayTypeMismatchException) + { + } + } + + static void TestArrayCoVarianceReadOnly() + { + var array = new ReferenceType[1]; + var objArray = (object[])array; + AssertTrue(new ReadOnlySpan(objArray).Length == 1, "Unexpected length"); + + var objEmptyArray = Array.Empty(); + AssertTrue(new ReadOnlySpan(objEmptyArray).Length == 0, "Unexpected length"); + } + + static void CanUpdateUnderlyingArray() + { + var underlyingArray = new int[] { 1, 2, 3 }; + var slice = new Span(underlyingArray); + + slice[0] = 0; + slice[1] = 1; + slice[2] = 2; + + AssertTrue(underlyingArray[0] == 0, "Failed to update underlying array"); + AssertTrue(underlyingArray[1] == 1, "Failed to update underlying array"); + AssertTrue(underlyingArray[2] == 2, "Failed to update underlying array"); + } + + static void CanCopyValueTypesWithoutPointersToSlice() + { + var source = new Span( + new[] + { + new ValueTypeWithoutPointers(0), + new ValueTypeWithoutPointers(1), + new ValueTypeWithoutPointers(2), + new ValueTypeWithoutPointers(3) + }); + var underlyingArray = new ValueTypeWithoutPointers[4]; + var slice = new Span(underlyingArray); + + var result = source.TryCopyTo(slice); + + AssertTrue(result, "Failed to copy value types without pointers"); + for (int i = 0; i < 4; i++) + { + AssertTrue(source[i].Value == slice[i].Value, "Failed to copy value types without pointers, values were not equal"); + AssertTrue(source[i].Value == underlyingArray[i].Value, "Failed to copy value types without pointers to underlying array, values were not equal"); + } + } + + static void CanCopyValueTypesWithoutPointersToArray() + { + var source = new Span( + new[] + { + new ValueTypeWithoutPointers(0), + new ValueTypeWithoutPointers(1), + new ValueTypeWithoutPointers(2), + new ValueTypeWithoutPointers(3) + }); + var array = new ValueTypeWithoutPointers[4]; + + var result = source.TryCopyTo(array); + + AssertTrue(result, "Failed to copy value types without pointers"); + for (int i = 0; i < 4; i++) + { + AssertTrue(source[i].Value == array[i].Value, "Failed to copy value types without pointers, values were not equal"); + } + } + + static void CanCopyReferenceTypesToSlice() + { + var source = new Span( + new[] + { + new ReferenceType(0), + new ReferenceType(1), + new ReferenceType(2), + new ReferenceType(3) + }); + var underlyingArray = new ReferenceType[4]; + var slice = new Span(underlyingArray); + + var result = source.TryCopyTo(slice); + + AssertTrue(result, "Failed to copy reference types"); + for (int i = 0; i < 4; i++) + { + AssertTrue(source[i] != null && slice[i] != null, "Failed to copy reference types, references were null"); + AssertTrue(object.ReferenceEquals(source[i], slice[i]), "Failed to copy reference types, references were not equal"); + AssertTrue(source[i].Value == slice[i].Value, "Failed to copy reference types, values were not equal"); + + AssertTrue(underlyingArray[i] != null, "Failed to copy reference types to underlying array, references were null"); + AssertTrue(object.ReferenceEquals(source[i], underlyingArray[i]), "Failed to copy reference types to underlying array, references were not equal"); + AssertTrue(source[i].Value == underlyingArray[i].Value, "Failed to copy reference types to underlying array, values were not equal"); + } + } + + static void CanCopyReferenceTypesToArray() + { + var source = new Span( + new[] + { + new ReferenceType(0), + new ReferenceType(1), + new ReferenceType(2), + new ReferenceType(3) + }); + var array = new ReferenceType[4]; + + var result = source.TryCopyTo(array); + + AssertTrue(result, "Failed to copy reference types"); + for (int i = 0; i < 4; i++) + { + AssertTrue(source[i] != null && array[i] != null, "Failed to copy reference types, references were null"); + AssertTrue(object.ReferenceEquals(source[i], array[i]), "Failed to copy reference types, references were not equal"); + AssertTrue(source[i].Value == array[i].Value, "Failed to copy reference types, values were not equal"); + } + } + + static void CanCopyValueTypesWithPointersToSlice() + { + var source = new Span( + new[] + { + new ValueTypeWithPointers(new object()), + new ValueTypeWithPointers(new object()), + new ValueTypeWithPointers(new object()), + new ValueTypeWithPointers(new object()) + }); + var underlyingArray = new ValueTypeWithPointers[4]; + var slice = new Span(underlyingArray); + + var result = source.TryCopyTo(slice); + + AssertTrue(result, "Failed to copy value types with pointers"); + for (int i = 0; i < 4; i++) + { + AssertTrue(object.ReferenceEquals(source[i].Reference, slice[i].Reference), "Failed to copy value types with pointers, references were not the same"); + AssertTrue(object.ReferenceEquals(source[i].Reference, underlyingArray[i].Reference), "Failed to copy value types with pointers to underlying array, references were not the same"); + } + } + + static void CanCopyValueTypesWithPointersToArray() + { + var source = new Span( + new[] + { + new ValueTypeWithPointers(new object()), + new ValueTypeWithPointers(new object()), + new ValueTypeWithPointers(new object()), + new ValueTypeWithPointers(new object()) + }); + var array = new ValueTypeWithPointers[4]; + + var result = source.TryCopyTo(array); + + AssertTrue(result, "Failed to copy value types with pointers"); + for (int i = 0; i < 4; i++) + { + AssertTrue(object.ReferenceEquals(source[i].Reference, array[i].Reference), "Failed to copy value types with pointers, references were not the same"); + } + } + + static unsafe void CanCopyValueTypesWithoutPointersToUnmanagedMemory() + { + var source = new Span( + new byte[] + { + 0, + 1, + 2, + 3 + }); + byte* pointerToStack = stackalloc byte[256]; + + var result = source.TryCopyTo(new Span(pointerToStack, 4)); + + AssertTrue(result, "Failed to copy value types without pointers to unamanaged memory"); + for (int i = 0; i < 4; i++) + { + AssertTrue(source[i] == pointerToStack[i], "Failed to copy value types without pointers to unamanaged memory, values were not equal"); + } + } + + static void CanCopyOverlappingSlicesOfValueTypeWithoutPointers() + { + var sourceArray = new[] + { + new ValueTypeWithoutPointers(0), + new ValueTypeWithoutPointers(1), + new ValueTypeWithoutPointers(2) + }; + var firstAndSecondElements = new Span(sourceArray, 0, 2); // 0, 1 + var secondAndThirdElements = new Span(sourceArray, 1, 2); // 1, 2 + + // 0 1 2 sourceArray + // 0 1 - firstAndSecondElements + // - 1 2 secondAndThirdElements + var result = firstAndSecondElements.TryCopyTo(secondAndThirdElements); // to avoid overlap we should copy backward now + // - 0 1 secondAndThirdElements + // 0 0 - firstAndSecondElements + // 0 0 1 sourceArray + + AssertTrue(result, "Failed to copy overlapping value types without pointers"); + + AssertTrue(secondAndThirdElements[1].Value == 1, "secondAndThirdElements[1] should get replaced by 1"); + AssertTrue(secondAndThirdElements[0].Value == 0 && firstAndSecondElements[1].Value == 0, "secondAndThirdElements[0] and firstAndSecondElements[1] point to the same element, should get replaced by 0"); + AssertTrue(firstAndSecondElements[0].Value == 0, "firstAndSecondElements[0] should remain the same"); + + // let's try the other direction to make sure it works as well! + + sourceArray = new[] + { + new ValueTypeWithoutPointers(0), + new ValueTypeWithoutPointers(1), + new ValueTypeWithoutPointers(2) + }; + firstAndSecondElements = new Span(sourceArray, 0, 2); // 0, 1 + secondAndThirdElements = new Span(sourceArray, 1, 2); // 1, 2 + + // 0 1 2 sourceArray + // 0 1 - firstAndSecondElements + // - 1 2 secondAndThirdElements + result = secondAndThirdElements.TryCopyTo(firstAndSecondElements); // to avoid overlap we should copy forward now + // 1 2 - firstAndSecondElements + // - 2 2 secondAndThirdElements + // 1 2 2 sourceArray + + AssertTrue(result, "Failed to copy overlapping value types without pointers"); + + AssertTrue(secondAndThirdElements[1].Value == 2, "secondAndThirdElements[1] should remain the same"); + AssertTrue(firstAndSecondElements[1].Value == 2 && secondAndThirdElements[0].Value == 2, "secondAndThirdElements[0] && firstAndSecondElements[1] point to the same element, should get replaced by 2"); + AssertTrue(firstAndSecondElements[0].Value == 1, "firstAndSecondElements[0] should get replaced by 1"); + } + + static void CanCopyOverlappingSlicesOfValueTypeWithPointers() + { + string zero = "0", one = "1", two = "2"; + var sourceArray = new[] + { + new ValueTypeWithPointers(zero), + new ValueTypeWithPointers(one), + new ValueTypeWithPointers(two) + }; + var firstAndSecondElements = new Span(sourceArray, 0, 2); // 0, 1 + var secondAndThirdElements = new Span(sourceArray, 1, 2); // 1, 2 + + // 0 1 2 sourceArray + // 0 1 - firstAndSecondElements + // - 1 2 secondAndThirdElements + var result = firstAndSecondElements.TryCopyTo(secondAndThirdElements); // to avoid overlap we should copy backward now + // - 0 1 secondAndThirdElements + // 0 0 - firstAndSecondElements + // 0 0 1 sourceArray + + AssertTrue(result, "Failed to copy overlapping value types with pointers"); + + AssertTrue(object.ReferenceEquals(secondAndThirdElements[1].Reference, one), "secondAndThirdElements[1] should get replaced by 1"); + AssertTrue(object.ReferenceEquals(secondAndThirdElements[0].Reference, zero) && object.ReferenceEquals(firstAndSecondElements[1].Reference, zero), "secondAndThirdElements[0] and firstAndSecondElements[1] point to the same element, should get replaced by 0"); + AssertTrue(object.ReferenceEquals(firstAndSecondElements[0].Reference, zero), "firstAndSecondElements[0] should remain the same"); + + // let's try the other direction to make sure it works as well! + + sourceArray = new[] + { + new ValueTypeWithPointers(zero), + new ValueTypeWithPointers(one), + new ValueTypeWithPointers(two) + }; + firstAndSecondElements = new Span(sourceArray, 0, 2); // 0, 1 + secondAndThirdElements = new Span(sourceArray, 1, 2); // 1, 2 + + // 0 1 2 sourceArray + // 0 1 - firstAndSecondElements + // - 1 2 secondAndThirdElements + result = secondAndThirdElements.TryCopyTo(firstAndSecondElements); // to avoid overlap we should copy forward now + // 1 2 - firstAndSecondElements + // - 2 2 secondAndThirdElements + // 1 2 2 sourceArray + + AssertTrue(result, "Failed to copy overlapping value types with pointers"); + + AssertTrue(object.ReferenceEquals(secondAndThirdElements[1].Reference, two), "secondAndThirdElements[1] should remain the same"); + AssertTrue(object.ReferenceEquals(firstAndSecondElements[1].Reference, two) && object.ReferenceEquals(secondAndThirdElements[0].Reference, two), "secondAndThirdElements[0] && firstAndSecondElements[1] point to the same element, should get replaced by 2"); + AssertTrue(object.ReferenceEquals(firstAndSecondElements[0].Reference, one), "firstAndSecondElements[0] should get replaced by 1"); + } + + static void CanCopyOverlappingSlicesOfReferenceTypes() + { + var sourceArray = new ReferenceType[] { new ReferenceType(0), new ReferenceType(1), new ReferenceType(2) }; + + var firstAndSecondElements = new Span(sourceArray, 0, 2); // 0, 1 + var secondAndThirdElements = new Span(sourceArray, 1, 2); // 1, 2 + + // 0 1 2 sourceArray + // 0 1 - firstAndSecondElements + // - 1 2 secondAndThirdElements + var result = firstAndSecondElements.TryCopyTo(secondAndThirdElements); // to avoid overlap we should copy backward now + // - 0 1 secondAndThirdElements + // 0 0 - firstAndSecondElements + // 0 0 1 sourceArray + + AssertTrue(result, "Failed to copy overlapping reference types"); + + AssertTrue(secondAndThirdElements[1].Value == 1, "secondAndThirdElements[1] should get replaced by 1"); + AssertTrue(secondAndThirdElements[0].Value == 0 && firstAndSecondElements[1].Value == 0, "secondAndThirdElements[0] and firstAndSecondElements[1] point to the same element, should get replaced by 0"); + AssertTrue(firstAndSecondElements[0].Value == 0, "firstAndSecondElements[0] should remain the same"); + + // let's try the other direction to make sure it works as well! + + sourceArray = new[] + { + new ReferenceType(0), + new ReferenceType(1), + new ReferenceType(2) + }; + firstAndSecondElements = new Span(sourceArray, 0, 2); // 0, 1 + secondAndThirdElements = new Span(sourceArray, 1, 2); // 1, 2 + + // 0 1 2 sourceArray + // 0 1 - firstAndSecondElements + // - 1 2 secondAndThirdElements + result = secondAndThirdElements.TryCopyTo(firstAndSecondElements); // to avoid overlap we should copy forward now + // 1 2 - firstAndSecondElements + // - 2 2 secondAndThirdElements + // 1 2 2 sourceArray + + AssertTrue(result, "Failed to copy overlapping reference types"); + + AssertTrue(secondAndThirdElements[1].Value == 2, "secondAndThirdElements[1] should remain the same"); + AssertTrue(firstAndSecondElements[1].Value == 2 && secondAndThirdElements[0].Value == 2, "secondAndThirdElements[0] && firstAndSecondElements[1] point to the same element, should get replaced by 2"); + AssertTrue(firstAndSecondElements[0].Value == 1, "firstAndSecondElements[0] should get replaced by 1"); + } + + static void MustNotCastSpanOfValueTypesWithPointers() + { + var spanOfValueTypeWithPointers = new Span(new[] { new ValueTypeWithPointers(new object()) }); + + try + { + var impossible = spanOfValueTypeWithPointers.AsBytes(); + AssertTrue(false, "Expected exception for wrong type not thrown"); + } + catch (System.ArgumentException ex) + { + AssertTrue(ex.Message == "Cannot use type 'ValueTypeWithPointers'. Only value types without pointers or references are supported.", + "Exception message is incorrect"); + } + + try + { + var impossible = spanOfValueTypeWithPointers.NonPortableCast(); + AssertTrue(false, "Expected exception for wrong type not thrown"); + } + catch (System.ArgumentException ex) + { + AssertTrue(ex.Message == "Cannot use type 'ValueTypeWithPointers'. Only value types without pointers or references are supported.", + "Exception message is incorrect"); + } + + var spanOfBytes = new Span(new byte[10]); + try + { + var impossible = spanOfBytes.NonPortableCast(); + AssertTrue(false, "Expected exception for wrong type not thrown"); + } + catch (System.ArgumentException ex) + { + AssertTrue(ex.Message == "Cannot use type 'ValueTypeWithPointers'. Only value types without pointers or references are supported.", + "Exception message is incorrect"); + } + } + + static void IntArraySpanCastedToByteArraySpanHasSameBytesAsOriginalArray() + { + var ints = new int[100000]; + Random r = new Random(42324232); + for (int i = 0; i < ints.Length; i++) { ints[i] = r.Next(); } + var bytes = new Span(ints).AsBytes(); + AssertEqual(bytes.Length, ints.Length * sizeof(int)); + for (int i = 0; i < ints.Length; i++) + { + AssertEqual(bytes[i * 4], (ints[i] & 0xff)); + AssertEqual(bytes[i * 4 + 1], (ints[i] >> 8 & 0xff)); + AssertEqual(bytes[i * 4 + 2], (ints[i] >> 16 & 0xff)); + AssertEqual(bytes[i * 4 + 3], (ints[i] >> 24 & 0xff)); + } + } + + static void ByteArraySpanCastedToIntArraySpanHasSameBytesAsOriginalArray() + { + var bytes = new byte[100000]; + Random r = new Random(541345); + for (int i = 0; i < bytes.Length; i++) { bytes[i] = (byte)r.Next(256); } + var ints = new Span(bytes).NonPortableCast(); + AssertEqual(ints.Length, bytes.Length / sizeof(int)); + for (int i = 0; i < ints.Length; i++) + { + AssertEqual(BitConverter.ToInt32(bytes, i * 4), ints[i]); + } + } + + static void SourceTypeLargerThanTargetOneCorrectlyCalcsTargetsLength() + { + for (int sourceLength = 0; sourceLength <= 4; sourceLength++) + { + var sourceSlice = new Span(new SevenBytesStruct[sourceLength]); + + var targetSlice = sourceSlice.NonPortableCast(); + + AssertEqual((sourceLength * 7) / sizeof(short), targetSlice.Length); + } + } + + static void WhenSourceDoesntFitIntoTargetLengthIsZero() + { + for (int sourceLength = 0; sourceLength <= 3; sourceLength++) + { + var sourceSlice = new Span(new short[sourceLength]); + + var targetSlice = sourceSlice.NonPortableCast(); + + AssertEqual(0, targetSlice.Length); + } + } + + static void WhenSourceFitsIntoTargetOnceLengthIsOne() + { + foreach (var sourceLength in new int[] { 4, 6 }) + { + var sourceSlice = new Span(new short[sourceLength]); + + var targetSlice = sourceSlice.NonPortableCast(); + + AssertEqual(1, targetSlice.Length); + } + } + + static void WhenSourceTypeLargerThanTargetAndOverflowsInt32ThrowsException() + { + unsafe + { + byte dummy; + int sourceLength = 620000000; + var sourceSlice = new Span(&dummy, sourceLength); + + try + { + var targetSlice = sourceSlice.NonPortableCast(); + AssertTrue(false, "Expected exception for overflow not thrown"); + } + catch (System.OverflowException) + { + } + } + } + + static void CanCreateSpanFromString() + { + const string fullText = "new Span()"; + var spanFromFull = fullText.Slice(); + AssertEqualContent(fullText, spanFromFull); + + string firstHalfOfString = fullText.Substring(0, fullText.Length / 2); + var spanFromFirstHalf = fullText.Slice(0, fullText.Length / 2); + AssertEqualContent(firstHalfOfString, spanFromFirstHalf); + + string secondHalfOfString = fullText.Substring(fullText.Length / 2); + var spanFromSecondHalf = fullText.Slice(fullText.Length / 2); + AssertEqualContent(secondHalfOfString, spanFromSecondHalf); + } + + static void WhenStartLargerThanLengthThrowsExceptionStartCtor() + { + try + { + var data = new byte[10]; + var slice = new Span(data, start: 11); + AssertTrue(false, "Expected exception for Argument Out of Range not thrown"); + } + catch (System.ArgumentOutOfRangeException) + { + } + } + + static void WhenStartLargerThanLengthThrowsExceptionStartLengthCtor() + { + try + { + var data = new byte[10]; + var slice = new Span(data, start: 11, length: 0); + AssertTrue(false, "Expected exception for Argument Out of Range not thrown"); + } + catch (System.ArgumentOutOfRangeException) + { + } + } + + static void WhenStartAndLengthLargerThanLengthThrowsExceptionStartLengthCtor() + { + try + { + var data = new byte[10]; + var slice = new Span(data, start: 1, length: 10); + AssertTrue(false, "Expected exception for Argument Out of Range not thrown"); + } + catch (System.ArgumentOutOfRangeException) + { + } + } + + static void Test(Action test, string testName, ref int failedTestsCount) + { + try + { + test(); + + Console.WriteLine(testName + " test has passed"); + } + catch (System.Exception ex) + { + Console.WriteLine(testName + " test has failed with exception: " + ex.Message); + + ++failedTestsCount; + } + finally + { + Console.WriteLine("-------------------"); + } + } + + static void AssertTrue(bool condition, string errorMessage) + { + if (condition == false) + { + throw new Exception(errorMessage); + } + } + + static void AssertEqual(T left, T right) + where T : IEquatable + { + if (left.Equals(right) == false) + { + throw new Exception(string.Format("Values were not equal! {0} and {1}", left, right)); + } + } + + static void AssertEqualContent(string text, ReadOnlySpan span) + { + AssertEqual(text.Length, span.Length); + for (int i = 0; i < text.Length; i++) + { + AssertEqual(text[i], span[i]); + } + } +} diff --git a/tests/src/GC/API/GC/GetGenerationWR2.csproj b/tests/src/GC/API/GC/GetGenerationWR2.csproj index 35a05a6..6b109e9 100644 --- a/tests/src/GC/API/GC/GetGenerationWR2.csproj +++ b/tests/src/GC/API/GC/GetGenerationWR2.csproj @@ -13,6 +13,7 @@ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages ..\..\ + true 7a9bfb7d diff --git a/tests/src/GC/API/GCHandleCollector/Usage.cs b/tests/src/GC/API/GCHandleCollector/Usage.cs index 14088f0..b78271b 100644 --- a/tests/src/GC/API/GCHandleCollector/Usage.cs +++ b/tests/src/GC/API/GCHandleCollector/Usage.cs @@ -146,7 +146,8 @@ public class Usage // ensure threshold is increasing if (!CheckPercentageIncrease(handleCount, prevHandleCount)) { - Console.WriteLine("Case 3 failed: threshold not increasing!"); + // see github#4093 for the rationale for fail-fast in this test. + Environment.FailFast(string.Empty); return false; } prevHandleCount = handleCount; diff --git a/tests/src/GC/Features/HeapExpansion/pluggaps.csproj b/tests/src/GC/Features/HeapExpansion/pluggaps.csproj index cbeab56..42ba45a 100644 --- a/tests/src/GC/Features/HeapExpansion/pluggaps.csproj +++ b/tests/src/GC/Features/HeapExpansion/pluggaps.csproj @@ -14,6 +14,7 @@ ..\..\ 7a9bfb7d true + true diff --git a/tests/src/GC/Performance/Framework/GCPerfTestFramework.csproj b/tests/src/GC/Performance/Framework/GCPerfTestFramework.csproj index cc8261f..d013349 100644 --- a/tests/src/GC/Performance/Framework/GCPerfTestFramework.csproj +++ b/tests/src/GC/Performance/Framework/GCPerfTestFramework.csproj @@ -35,11 +35,12 @@ x64 - - packages\Microsoft.Diagnostics.Tracing.TraceEvent.1.0.39\lib\net40\Microsoft.Diagnostics.Tracing.TraceEvent.dll + + packages\Microsoft.Diagnostics.Tracing.TraceEvent.1.0.41\lib\net40\Microsoft.Diagnostics.Tracing.TraceEvent.dll True + packages\System.IO.FileSystem.4.0.0\lib\net46\System.IO.FileSystem.dll @@ -56,27 +57,27 @@ - packages\Microsoft.DotNet.xunit.performance.metrics.1.0.0-alpha-build0030\lib\net46\xunit.abstractions.dll + packages\Microsoft.DotNet.xunit.performance.metrics.1.0.0-alpha-build0040\lib\net46\xunit.abstractions.dll True - - packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll + + packages\xunit.extensibility.core.2.2.0-beta2-build3300\lib\netstandard1.0\xunit.core.dll True - - packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll + + packages\xunit.extensibility.execution.2.2.0-beta2-build3300\lib\net45\xunit.execution.desktop.dll True - - packages\Microsoft.DotNet.xunit.performance.metrics.1.0.0-alpha-build0030\lib\net46\xunit.performance.core.dll + + packages\Microsoft.DotNet.xunit.performance.metrics.1.0.0-alpha-build0040\lib\net46\xunit.performance.core.dll True - - packages\Microsoft.DotNet.xunit.performance.1.0.0-alpha-build0030\lib\net46\xunit.performance.execution.desktop.dll + + packages\Microsoft.DotNet.xunit.performance.1.0.0-alpha-build0040\lib\net46\xunit.performance.execution.desktop.dll True - - packages\Microsoft.DotNet.xunit.performance.metrics.1.0.0-alpha-build0030\lib\net46\xunit.performance.metrics.dll + + packages\Microsoft.DotNet.xunit.performance.metrics.1.0.0-alpha-build0040\lib\net46\xunit.performance.metrics.dll True @@ -102,12 +103,12 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + @@ -36,4 +37,4 @@ - \ No newline at end of file + diff --git a/tests/src/GC/Scenarios/DoublinkList/dlcollect.cs b/tests/src/GC/Scenarios/DoublinkList/dlcollect.cs index a3a0c53..a17e95a 100644 --- a/tests/src/GC/Scenarios/DoublinkList/dlcollect.cs +++ b/tests/src/GC/Scenarios/DoublinkList/dlcollect.cs @@ -77,6 +77,12 @@ namespace DoubLink { GC.WaitForPendingFinalizers(); + if (DLinkNode.FinalCount != iRep * iObj * 10) + { + // see github#4093 for the rationale for fail-fast in this test. + Environment.FailFast(string.Empty); + } + Console.WriteLine("{0} DLinkNodes finalized", DLinkNode.FinalCount); return (DLinkNode.FinalCount==iRep*iObj*10); } diff --git a/tests/src/GC/Scenarios/DoublinkList/dlstack.cs b/tests/src/GC/Scenarios/DoublinkList/dlstack.cs index 5aea958..5e207be 100644 --- a/tests/src/GC/Scenarios/DoublinkList/dlstack.cs +++ b/tests/src/GC/Scenarios/DoublinkList/dlstack.cs @@ -85,6 +85,12 @@ namespace DoubLink { curTotalMemory = GC.GetTotalMemory(false); } + if (DLinkNode.FinalCount != iRep * iObj * 10) + { + // see github#4093 for the rationale for fail-fast in this test. + Environment.FailFast(string.Empty); + } + Console.WriteLine("{0} DLinkNodes finalized", DLinkNode.FinalCount); return (DLinkNode.FinalCount==iRep*iObj*10); diff --git a/tests/src/GC/Scenarios/DoublinkList/doublinkgen.cs b/tests/src/GC/Scenarios/DoublinkList/doublinkgen.cs index 9c5e4b6..76436ea 100644 --- a/tests/src/GC/Scenarios/DoublinkList/doublinkgen.cs +++ b/tests/src/GC/Scenarios/DoublinkList/doublinkgen.cs @@ -71,6 +71,12 @@ namespace DoubLink { GC.WaitForPendingFinalizers(); GC.Collect(); + if (DLinkNode.FinalCount != iRep * iObj) + { + // see github#4093 for the rationale for fail-fast in this test. + Environment.FailFast(string.Empty); + } + Console.Write(DLinkNode.FinalCount); Console.WriteLine(" DLinkNodes finalized"); return (DLinkNode.FinalCount==iRep*iObj); diff --git a/tests/src/GC/Scenarios/FinalizeTimeout/FinalizeTimeout.cs b/tests/src/GC/Scenarios/FinalizeTimeout/FinalizeTimeout.cs index 0fda817..60a6861 100644 --- a/tests/src/GC/Scenarios/FinalizeTimeout/FinalizeTimeout.cs +++ b/tests/src/GC/Scenarios/FinalizeTimeout/FinalizeTimeout.cs @@ -17,6 +17,7 @@ public class FinalizeTimeout do { finalizableObject = new BlockingFinalizerOnShutdown(); + GC.KeepAlive(finalizableObject); } while (!BlockingFinalizerOnShutdown.finalizerCompletedOnce); // Start a bunch of threads that allocate continuously, to increase the chance that when Main returns, one of the @@ -42,12 +43,15 @@ public class FinalizeTimeout { byte[] b; while (true) + { b = new byte[1024]; + GC.KeepAlive(b); + } } private class BlockingFinalizerOnShutdown { - public static bool finalizerCompletedOnce = false; + public volatile static bool finalizerCompletedOnce = false; public bool isLastObject = false; ~BlockingFinalizerOnShutdown() @@ -68,6 +72,7 @@ public class FinalizeTimeout do { o = new object(); + GC.KeepAlive(o); } while ((++i & 0xff) != 0 || (elapsed = DateTime.Now - start) < timeout); Console.WriteLine("Finalizer end"); diff --git a/tests/src/GC/Scenarios/ServerModel/servermodel.csproj b/tests/src/GC/Scenarios/ServerModel/servermodel.csproj index 33fc4ef..dff52fc 100644 --- a/tests/src/GC/Scenarios/ServerModel/servermodel.csproj +++ b/tests/src/GC/Scenarios/ServerModel/servermodel.csproj @@ -15,6 +15,7 @@ 7a9bfb7d /numrequests:100 true + true diff --git a/tests/src/GC/Stress/Framework/ReliabilityFramework.csproj b/tests/src/GC/Stress/Framework/ReliabilityFramework.csproj index 9288e52..9dd878b 100644 --- a/tests/src/GC/Stress/Framework/ReliabilityFramework.csproj +++ b/tests/src/GC/Stress/Framework/ReliabilityFramework.csproj @@ -52,6 +52,6 @@ - + diff --git a/tests/src/GC/Stress/Tests/dir.targets b/tests/src/GC/Stress/Tests/dir.targets new file mode 100644 index 0000000..d4f8bf9 --- /dev/null +++ b/tests/src/GC/Stress/Tests/dir.targets @@ -0,0 +1,6 @@ + + + true + + + \ No newline at end of file diff --git a/tests/src/Interop/ArrayMarshalling/ByValArray/MarshalArrayByValNative.cpp b/tests/src/Interop/ArrayMarshalling/ByValArray/MarshalArrayByValNative.cpp index bf3d66d..27de41a 100644 --- a/tests/src/Interop/ArrayMarshalling/ByValArray/MarshalArrayByValNative.cpp +++ b/tests/src/Interop/ArrayMarshalling/ByValArray/MarshalArrayByValNative.cpp @@ -185,84 +185,84 @@ Function /*---------------------------------------------------------------------------- marshal sequential strut ----------------------------------------------------------------------------*/ -extern "C" DLL_EXPORT BOOL TakeIntArraySeqStructByVal( S_INTArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeIntArraySeqStructByVal( S_INTArray s, int size ) { CHECK_PARAM_NOT_EMPTY( s.arr ); INIT_EXPECTED( INT, ARRAY_SIZE ); return Equals( s.arr, size, expected, ARRAY_SIZE ); } -extern "C" DLL_EXPORT BOOL TakeUIntArraySeqStructByVal( S_UINTArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeUIntArraySeqStructByVal( S_UINTArray s, int size ) { CHECK_PARAM_NOT_EMPTY( s.arr ); INIT_EXPECTED( UINT, ARRAY_SIZE ); return Equals( s.arr, size, expected, ARRAY_SIZE ); } -extern "C" DLL_EXPORT BOOL TakeShortArraySeqStructByVal( S_SHORTArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeShortArraySeqStructByVal( S_SHORTArray s, int size ) { CHECK_PARAM_NOT_EMPTY( s.arr ); INIT_EXPECTED( SHORT, ARRAY_SIZE ); return Equals( s.arr, size, expected, ARRAY_SIZE ); } -extern "C" DLL_EXPORT BOOL TakeWordArraySeqStructByVal( S_WORDArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeWordArraySeqStructByVal( S_WORDArray s, int size ) { CHECK_PARAM_NOT_EMPTY( s.arr ); INIT_EXPECTED( WORD, ARRAY_SIZE ); return Equals( s.arr, size, expected, ARRAY_SIZE ); } -extern "C" DLL_EXPORT BOOL TakeLong64ArraySeqStructByVal( S_LONG64Array s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeLong64ArraySeqStructByVal( S_LONG64Array s, int size ) { CHECK_PARAM_NOT_EMPTY( s.arr ); INIT_EXPECTED( LONG64, ARRAY_SIZE ); return Equals( s.arr, size, expected, ARRAY_SIZE ); } -extern "C" DLL_EXPORT BOOL TakeULong64ArraySeqStructByVal( S_ULONG64Array s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeULong64ArraySeqStructByVal( S_ULONG64Array s, int size ) { CHECK_PARAM_NOT_EMPTY( s.arr ); INIT_EXPECTED( ULONG64, ARRAY_SIZE ); return Equals( s.arr, size, expected, ARRAY_SIZE ); } -extern "C" DLL_EXPORT BOOL TakeDoubleArraySeqStructByVal( S_DOUBLEArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeDoubleArraySeqStructByVal( S_DOUBLEArray s, int size ) { CHECK_PARAM_NOT_EMPTY( s.arr ); INIT_EXPECTED( DOUBLE, ARRAY_SIZE ); return Equals( s.arr, size, expected, ARRAY_SIZE ); } -extern "C" DLL_EXPORT BOOL TakeFloatArraySeqStructByVal( S_FLOATArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeFloatArraySeqStructByVal( S_FLOATArray s, int size ) { CHECK_PARAM_NOT_EMPTY( s.arr ); INIT_EXPECTED( FLOAT, ARRAY_SIZE ); return Equals( s.arr, size, expected, ARRAY_SIZE ); } -extern "C" DLL_EXPORT BOOL TakeByteArraySeqStructByVal( S_BYTEArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeByteArraySeqStructByVal( S_BYTEArray s, int size ) { CHECK_PARAM_NOT_EMPTY( s.arr ); INIT_EXPECTED( BYTE, ARRAY_SIZE ); return Equals( s.arr, size, expected, ARRAY_SIZE ); } -extern "C" DLL_EXPORT BOOL TakeCharArraySeqStructByVal( S_CHARArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeCharArraySeqStructByVal( S_CHARArray s, int size ) { CHECK_PARAM_NOT_EMPTY( s.arr ); INIT_EXPECTED( CHAR, ARRAY_SIZE ); return Equals( s.arr, size, expected, ARRAY_SIZE ); } -extern "C" DLL_EXPORT BOOL TakeIntPtrArraySeqStructByVal(S_DWORD_PTRArray s, int size) +extern "C" DLL_EXPORT BOOL WINAPI TakeIntPtrArraySeqStructByVal(S_DWORD_PTRArray s, int size) { CHECK_PARAM_NOT_EMPTY(s.arr); INIT_EXPECTED( DWORD_PTR, ARRAY_SIZE); return Equals(s.arr, size, expected, ARRAY_SIZE); } -extern "C" DLL_EXPORT BOOL TakeLPSTRArraySeqStructByVal( S_LPSTRArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeLPSTRArraySeqStructByVal( S_LPSTRArray s, int size ) { CHECK_PARAM_NOT_EMPTY( s.arr ); @@ -273,7 +273,7 @@ extern "C" DLL_EXPORT BOOL TakeLPSTRArraySeqStructByVal( S_LPSTRArray s, int siz return Equals( s.arr, size, expected, ARRAY_SIZE ); } -extern "C" DLL_EXPORT BOOL TakeLPCSTRArraySeqStructByVal( S_LPCSTRArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeLPCSTRArraySeqStructByVal( S_LPCSTRArray s, int size ) { CHECK_PARAM_NOT_EMPTY( s.arr ); @@ -286,7 +286,7 @@ extern "C" DLL_EXPORT BOOL TakeLPCSTRArraySeqStructByVal( S_LPCSTRArray s, int s -extern "C" DLL_EXPORT BOOL TakeStructArraySeqStructByVal( S_StructArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeStructArraySeqStructByVal( S_StructArray s, int size ) { CHECK_PARAM_NOT_EMPTY( s.arr ); @@ -297,69 +297,69 @@ extern "C" DLL_EXPORT BOOL TakeStructArraySeqStructByVal( S_StructArray s, int s /*---------------------------------------------------------------------------- marshal sequential class ----------------------------------------------------------------------------*/ -extern "C" DLL_EXPORT BOOL TakeIntArraySeqClassByVal( S_INTArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeIntArraySeqClassByVal( S_INTArray *s, int size ) { return TakeIntArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeUIntArraySeqClassByVal( S_UINTArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeUIntArraySeqClassByVal( S_UINTArray *s, int size ) { return TakeUIntArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeShortArraySeqClassByVal( S_SHORTArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeShortArraySeqClassByVal( S_SHORTArray *s, int size ) { return TakeShortArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeWordArraySeqClassByVal( S_WORDArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeWordArraySeqClassByVal( S_WORDArray *s, int size ) { return TakeWordArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeLong64ArraySeqClassByVal( S_LONG64Array *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeLong64ArraySeqClassByVal( S_LONG64Array *s, int size ) { return TakeLong64ArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeULong64ArraySeqClassByVal( S_ULONG64Array *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeULong64ArraySeqClassByVal( S_ULONG64Array *s, int size ) { return TakeULong64ArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeDoubleArraySeqClassByVal( S_DOUBLEArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeDoubleArraySeqClassByVal( S_DOUBLEArray *s, int size ) { return TakeDoubleArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeFloatArraySeqClassByVal( S_FLOATArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeFloatArraySeqClassByVal( S_FLOATArray *s, int size ) { return TakeFloatArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeByteArraySeqClassByVal( S_BYTEArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeByteArraySeqClassByVal( S_BYTEArray *s, int size ) { return TakeByteArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeCharArraySeqClassByVal( S_CHARArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeCharArraySeqClassByVal( S_CHARArray *s, int size ) { return TakeCharArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeLPSTRArraySeqClassByVal( S_LPSTRArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeLPSTRArraySeqClassByVal( S_LPSTRArray *s, int size ) { return TakeLPSTRArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeLPCSTRArraySeqClassByVal( S_LPCSTRArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeLPCSTRArraySeqClassByVal( S_LPCSTRArray *s, int size ) { return TakeLPCSTRArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeStructArraySeqClassByVal( S_StructArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeStructArraySeqClassByVal( S_StructArray *s, int size ) { return TakeStructArraySeqStructByVal( *s, size ); } @@ -367,69 +367,69 @@ extern "C" DLL_EXPORT BOOL TakeStructArraySeqClassByVal( S_StructArray *s, int s /*---------------------------------------------------------------------------- marshal explicit struct ----------------------------------------------------------------------------*/ -extern "C" DLL_EXPORT BOOL TakeIntArrayExpStructByVal( S_INTArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeIntArrayExpStructByVal( S_INTArray s, int size ) { return TakeIntArraySeqStructByVal( s, size ); } -extern "C" DLL_EXPORT BOOL TakeUIntArrayExpStructByVal( S_UINTArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeUIntArrayExpStructByVal( S_UINTArray s, int size ) { return TakeUIntArraySeqStructByVal( s, size ); } -extern "C" DLL_EXPORT BOOL TakeShortArrayExpStructByVal( S_SHORTArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeShortArrayExpStructByVal( S_SHORTArray s, int size ) { return TakeShortArraySeqStructByVal( s, size ); } -extern "C" DLL_EXPORT BOOL TakeWordArrayExpStructByVal( S_WORDArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeWordArrayExpStructByVal( S_WORDArray s, int size ) { return TakeWordArraySeqStructByVal( s, size ); } -extern "C" DLL_EXPORT BOOL TakeLong64ArrayExpStructByVal( S_LONG64Array s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeLong64ArrayExpStructByVal( S_LONG64Array s, int size ) { return TakeLong64ArraySeqStructByVal( s, size ); } -extern "C" DLL_EXPORT BOOL TakeULong64ArrayExpStructByVal( S_ULONG64Array s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeULong64ArrayExpStructByVal( S_ULONG64Array s, int size ) { return TakeULong64ArraySeqStructByVal( s, size ); } -extern "C" DLL_EXPORT BOOL TakeDoubleArrayExpStructByVal( S_DOUBLEArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeDoubleArrayExpStructByVal( S_DOUBLEArray s, int size ) { return TakeDoubleArraySeqStructByVal( s, size ); } -extern "C" DLL_EXPORT BOOL TakeFloatArrayExpStructByVal( S_FLOATArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeFloatArrayExpStructByVal( S_FLOATArray s, int size ) { return TakeFloatArraySeqStructByVal( s, size ); } -extern "C" DLL_EXPORT BOOL TakeByteArrayExpStructByVal( S_BYTEArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeByteArrayExpStructByVal( S_BYTEArray s, int size ) { return TakeByteArraySeqStructByVal( s, size ); } -extern "C" DLL_EXPORT BOOL TakeCharArrayExpStructByVal( S_CHARArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeCharArrayExpStructByVal( S_CHARArray s, int size ) { return TakeCharArraySeqStructByVal( s, size ); } -extern "C" DLL_EXPORT BOOL TakeLPSTRArrayExpStructByVal( S_LPSTRArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeLPSTRArrayExpStructByVal( S_LPSTRArray s, int size ) { return TakeLPSTRArraySeqStructByVal( s, size ); } -extern "C" DLL_EXPORT BOOL TakeLPCSTRArrayExpStructByVal( S_LPCSTRArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeLPCSTRArrayExpStructByVal( S_LPCSTRArray s, int size ) { return TakeLPCSTRArraySeqStructByVal( s, size ); } -extern "C" DLL_EXPORT BOOL TakeStructArrayExpStructByVal( S_StructArray s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeStructArrayExpStructByVal( S_StructArray s, int size ) { return TakeStructArraySeqStructByVal( s, size ); } @@ -437,69 +437,69 @@ extern "C" DLL_EXPORT BOOL TakeStructArrayExpStructByVal( S_StructArray s, int s /*---------------------------------------------------------------------------- marshal explicit class ----------------------------------------------------------------------------*/ -extern "C" DLL_EXPORT BOOL TakeIntArrayExpClassByVal( S_INTArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeIntArrayExpClassByVal( S_INTArray *s, int size ) { return TakeIntArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeUIntArrayExpClassByVal( S_UINTArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeUIntArrayExpClassByVal( S_UINTArray *s, int size ) { return TakeUIntArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeShortArrayExpClassByVal( S_SHORTArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeShortArrayExpClassByVal( S_SHORTArray *s, int size ) { return TakeShortArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeWordArrayExpClassByVal( S_WORDArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeWordArrayExpClassByVal( S_WORDArray *s, int size ) { return TakeWordArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeLong64ArrayExpClassByVal( S_LONG64Array *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeLong64ArrayExpClassByVal( S_LONG64Array *s, int size ) { return TakeLong64ArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeULong64ArrayExpClassByVal( S_ULONG64Array *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeULong64ArrayExpClassByVal( S_ULONG64Array *s, int size ) { return TakeULong64ArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeDoubleArrayExpClassByVal( S_DOUBLEArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeDoubleArrayExpClassByVal( S_DOUBLEArray *s, int size ) { return TakeDoubleArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeFloatArrayExpClassByVal( S_FLOATArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeFloatArrayExpClassByVal( S_FLOATArray *s, int size ) { return TakeFloatArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeByteArrayExpClassByVal( S_BYTEArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeByteArrayExpClassByVal( S_BYTEArray *s, int size ) { return TakeByteArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeCharArrayExpClassByVal( S_CHARArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeCharArrayExpClassByVal( S_CHARArray *s, int size ) { return TakeCharArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeLPSTRArrayExpClassByVal( S_LPSTRArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeLPSTRArrayExpClassByVal( S_LPSTRArray *s, int size ) { return TakeLPSTRArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeLPCSTRArrayExpClassByVal( S_LPCSTRArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeLPCSTRArrayExpClassByVal( S_LPCSTRArray *s, int size ) { return TakeLPCSTRArraySeqStructByVal( *s, size ); } -extern "C" DLL_EXPORT BOOL TakeStructArrayExpClassByVal( S_StructArray *s, int size ) +extern "C" DLL_EXPORT BOOL WINAPI TakeStructArrayExpClassByVal( S_StructArray *s, int size ) { return TakeStructArraySeqStructByVal( *s, size ); } @@ -507,77 +507,77 @@ extern "C" DLL_EXPORT BOOL TakeStructArrayExpClassByVal( S_StructArray *s, int s /*---------------------------------------------------------------------------- return a struct including a C array ----------------------------------------------------------------------------*/ -extern "C" DLL_EXPORT S_INTArray* S_INTArray_Ret() +extern "C" DLL_EXPORT S_INTArray* WINAPI S_INTArray_Ret() { INIT_EXPECTED_STRUCT( S_INTArray, ARRAY_SIZE, INT ); return expected; } -extern "C" DLL_EXPORT S_UINTArray* S_UINTArray_Ret() +extern "C" DLL_EXPORT S_UINTArray* WINAPI S_UINTArray_Ret() { INIT_EXPECTED_STRUCT( S_UINTArray, ARRAY_SIZE, UINT ); return expected; } -extern "C" DLL_EXPORT S_SHORTArray* S_SHORTArray_Ret() +extern "C" DLL_EXPORT S_SHORTArray* WINAPI S_SHORTArray_Ret() { INIT_EXPECTED_STRUCT( S_SHORTArray, ARRAY_SIZE, SHORT ); return expected; } -extern "C" DLL_EXPORT S_WORDArray* S_WORDArray_Ret() +extern "C" DLL_EXPORT S_WORDArray* WINAPI S_WORDArray_Ret() { INIT_EXPECTED_STRUCT( S_WORDArray, ARRAY_SIZE, WORD ); return expected; } -extern "C" DLL_EXPORT S_LONG64Array* S_LONG64Array_Ret() +extern "C" DLL_EXPORT S_LONG64Array* WINAPI S_LONG64Array_Ret() { INIT_EXPECTED_STRUCT( S_LONG64Array, ARRAY_SIZE, LONG64 ); return expected; } -extern "C" DLL_EXPORT S_ULONG64Array* S_ULONG64Array_Ret() +extern "C" DLL_EXPORT S_ULONG64Array* WINAPI S_ULONG64Array_Ret() { INIT_EXPECTED_STRUCT( S_ULONG64Array, ARRAY_SIZE, ULONG64 ); return expected; } -extern "C" DLL_EXPORT S_DOUBLEArray* S_DOUBLEArray_Ret() +extern "C" DLL_EXPORT S_DOUBLEArray* WINAPI S_DOUBLEArray_Ret() { INIT_EXPECTED_STRUCT( S_DOUBLEArray, ARRAY_SIZE, DOUBLE ); return expected; } -extern "C" DLL_EXPORT S_FLOATArray* S_FLOATArray_Ret() +extern "C" DLL_EXPORT S_FLOATArray* WINAPI S_FLOATArray_Ret() { INIT_EXPECTED_STRUCT( S_FLOATArray, ARRAY_SIZE, FLOAT ); return expected; } -extern "C" DLL_EXPORT S_BYTEArray* S_BYTEArray_Ret() +extern "C" DLL_EXPORT S_BYTEArray* WINAPI S_BYTEArray_Ret() { INIT_EXPECTED_STRUCT( S_BYTEArray, ARRAY_SIZE, BYTE ); return expected; } -extern "C" DLL_EXPORT S_CHARArray* S_CHARArray_Ret() +extern "C" DLL_EXPORT S_CHARArray* WINAPI S_CHARArray_Ret() { INIT_EXPECTED_STRUCT( S_CHARArray, ARRAY_SIZE, CHAR ); return expected; } -extern "C" DLL_EXPORT S_LPSTRArray* S_LPSTRArray_Ret() +extern "C" DLL_EXPORT S_LPSTRArray* WINAPI S_LPSTRArray_Ret() { S_LPSTRArray *expected = (S_LPSTRArray *)::CoTaskMemAlloc( sizeof(S_LPSTRArray) ); for ( int i = 0; i < ARRAY_SIZE; ++i ) @@ -587,7 +587,7 @@ extern "C" DLL_EXPORT S_LPSTRArray* S_LPSTRArray_Ret() } -extern "C" DLL_EXPORT S_StructArray* S_StructArray_Ret() +extern "C" DLL_EXPORT S_StructArray* WINAPI S_StructArray_Ret() { S_StructArray *expected = (S_StructArray *)::CoTaskMemAlloc( sizeof(S_StructArray) ); for ( int i = 0; i < ARRAY_SIZE; ++i ) diff --git a/tests/src/Interop/PrimitiveMarshalling/Bool/BoolNative.cpp b/tests/src/Interop/PrimitiveMarshalling/Bool/BoolNative.cpp index ba8c10b..79ab5c9 100644 --- a/tests/src/Interop/PrimitiveMarshalling/Bool/BoolNative.cpp +++ b/tests/src/Interop/PrimitiveMarshalling/Bool/BoolNative.cpp @@ -116,8 +116,10 @@ extern "C" DLL_EXPORT BOOL __stdcall MarshalPointer_Out(/*[out]*/ BOOL *pboolVal } #pragma warning(push) +#if _MSC_VER <= 1900 // 'BOOL' forcing value to bool 'true' or 'false' #pragma warning(disable: 4800) +#endif extern "C" DLL_EXPORT bool __stdcall Marshal_As_In(/*[in]*/bool boolValue) { diff --git a/tests/src/Interop/RefCharArray/RefCharArrayNative.cpp b/tests/src/Interop/RefCharArray/RefCharArrayNative.cpp index 09f4671..0d0af27 100755 --- a/tests/src/Interop/RefCharArray/RefCharArrayNative.cpp +++ b/tests/src/Interop/RefCharArray/RefCharArrayNative.cpp @@ -6,7 +6,7 @@ #include #include -size_t LEN = 10; +const int LEN = 10; extern "C" BOOL DLL_EXPORT _cdecl MarshalRefCharArray_Cdecl(char ** pstr) { //Check the Input diff --git a/tests/src/Interop/SimpleStruct/SimpleStructNative.cpp b/tests/src/Interop/SimpleStruct/SimpleStructNative.cpp index 5fe8214..fb855a4 100644 --- a/tests/src/Interop/SimpleStruct/SimpleStructNative.cpp +++ b/tests/src/Interop/SimpleStruct/SimpleStructNative.cpp @@ -30,7 +30,7 @@ DLL_EXPORT BOOL _cdecl CdeclSimpleStructByRef(Sstr *p) { p->a = 100; p->b=1; - strncpy(p->str,"after",6); + strcpy_s(p->str, 7, "after"); return TRUE; } @@ -81,7 +81,7 @@ DLL_EXPORT ExplStruct* _cdecl CdeclSimpleExplStruct(ExplStruct p,BOOL *result) } extern "C" -DLL_EXPORT voidPtr _cdecl GetFptr(int i) +DLL_EXPORT voidPtr __stdcall GetFptr(int i) { switch(i) { diff --git a/tests/src/Interop/StringMarshalling/UTF8/UTF8TestNative.cpp b/tests/src/Interop/StringMarshalling/UTF8/UTF8TestNative.cpp index f4e0f2f..7007651 100644 --- a/tests/src/Interop/StringMarshalling/UTF8/UTF8TestNative.cpp +++ b/tests/src/Interop/StringMarshalling/UTF8/UTF8TestNative.cpp @@ -6,7 +6,7 @@ const int NSTRINGS = 6; #ifdef _WIN32 -wchar_t *utf8strings[] = { L"Managed", +const wchar_t *utf8strings[] = { L"Managed", L"S\x00EEne kl\x00E2wen durh die wolken sint geslagen" , L"\x0915\x093E\x091A\x0902 \x0936\x0915\x094D\x0928\x094B\x092E\x094D\x092F\x0924\x094D\x0924\x0941\x092E\x094D \x0964 \x0928\x094B\x092A\x0939\x093F\x0928\x0938\x094D\x0924\x093F \x092E\x093E\x092E\x094D", L"\x6211\x80FD\x541E\x4E0B\x73BB\x7483\x800C\x4E0D\x4F24\x8EAB\x4F53", @@ -17,7 +17,7 @@ L"\0" -char* utf16_to_utf8(wchar_t *srcstring) +char* utf16_to_utf8(const wchar_t *srcstring) { if ((srcstring == NULL) || (*srcstring == L'\0')) { return 0; diff --git a/tests/src/Interop/StructMarshalling/PInvoke/MarshalStructAsParamDLL.cpp b/tests/src/Interop/StructMarshalling/PInvoke/MarshalStructAsParamDLL.cpp index fe9ceea..0895443 100644 --- a/tests/src/Interop/StructMarshalling/PInvoke/MarshalStructAsParamDLL.cpp +++ b/tests/src/Interop/StructMarshalling/PInvoke/MarshalStructAsParamDLL.cpp @@ -167,22 +167,10 @@ extern "C" DLL_EXPORT BOOL WINAPI MarshalStructAsParam_AsSeqByValOut3(CharSetAns } extern "C" DLL_EXPORT BOOL WINAPI MarshalStructAsParam_AsSeqByRefOut3(CharSetAnsiSequential* str1) { - char const* strSource = "change string"; - int len = strlen(strSource); - LPCSTR temp = (LPCSTR)TP_CoTaskMemAlloc((sizeof(char)*len)+1); - if(temp != NULL) - { - TP_CoTaskMemFree((void*)(str1->f1)); - strcpy((char*)temp,strSource); - str1->f1 = temp; - str1->f2 = 'n'; - return TRUE; - } - else - { - printf("Memory Allocated Failed !"); - return FALSE; - } + TP_CoTaskMemFree((void*)(str1->f1)); + str1->f1 = CoStrDup("change string"); + str1->f2 = 'n'; + return TRUE; } //////////////////////////////////////////////////////////////////////////////////////////////// @@ -663,7 +651,7 @@ extern "C" DLL_EXPORT BOOL WINAPI MarshalStructAsParam_AsSeqByVal14(S11 str1) { if( str1.i32 != 0 || str1.i != 32 ) return FALSE; - str1.i32 = (LPINT)(long)(str1.i); + str1.i32 = reinterpret_cast(static_cast(str1.i)); str1.i = 64; return TRUE; } @@ -673,7 +661,7 @@ extern "C" DLL_EXPORT BOOL WINAPI MarshalStructAsParam_AsSeqByRef14(S11* str1) return FALSE; else { - str1->i32 = (LPINT)(long)(str1->i); + str1->i32 = reinterpret_cast(static_cast(str1->i)); str1->i = 64; return TRUE; } @@ -684,7 +672,7 @@ extern "C" DLL_EXPORT BOOL WINAPI MarshalStructAsParam_AsSeqByRefIn14(S11* str1) return FALSE; else { - str1->i32 = (LPINT)(long)(str1->i); + str1->i32 = reinterpret_cast(static_cast(str1->i)); str1->i = 64; return TRUE; } @@ -698,7 +686,7 @@ extern "C" DLL_EXPORT BOOL WINAPI MarshalStructAsParam_AsSeqByValOut14(S11 str1) } extern "C" DLL_EXPORT BOOL WINAPI MarshalStructAsParam_AsSeqByRefOut14(S11* str1) { - str1->i32 = (LPINT)(long)(str1->i); + str1->i32 = reinterpret_cast(static_cast(str1->i)); str1->i = 64; return TRUE; } @@ -817,7 +805,7 @@ extern "C" DLL_EXPORT BOOL WINAPI MarshalStructAsParam_AsExpByValInnerArrayExpli return FALSE; } } - if(memcmp((&outer2)->f4,"some string2",12) != 0) + if(memcmp((&outer2)->s.f4,"some string2",12) != 0) { printf("\tMarshalStructAsParam_AsExpByVal3:InnerArrayExplicit param f4 not as expected\n"); return FALSE; @@ -835,7 +823,7 @@ extern "C" DLL_EXPORT BOOL WINAPI MarshalStructAsParam_AsExpByRefInnerArrayExpli return FALSE; } } - if(memcmp(outer2->f4,"some string2",12) != 0) + if(memcmp(outer2->s.f4,"some string2",12) != 0) { printf("\tMarshalStructAsParam_AsExpByRef3:InnerArrayExplicit param f4 not as expected\n"); return FALSE; @@ -844,11 +832,8 @@ extern "C" DLL_EXPORT BOOL WINAPI MarshalStructAsParam_AsExpByRefInnerArrayExpli { outer2->arr[i].f1 = 77; } - char const * temp = "change string2"; - size_t len = strlen(temp); - LPCSTR str = (LPCSTR)TP_CoTaskMemAlloc( sizeof(char)*(len+1) ); - strcpy((char*)str,temp); - outer2->f4 = str; + + outer2->s.f4 = CoStrDup("change string2"); return TRUE; } @@ -862,7 +847,7 @@ extern "C" DLL_EXPORT BOOL WINAPI MarshalStructAsParam_AsExpByRefInInnerArrayExp return FALSE; } } - if(memcmp(outer2->f4, "some string2",12*(sizeof(char))) != 0) + if(memcmp(outer2->s.f4, "some string2",12*(sizeof(char))) != 0) { printf("\tMarshalStructAsParam_AsExpByRefIn3:InnerArrayExplicit param f4 not as expected\n"); return FALSE; @@ -871,11 +856,7 @@ extern "C" DLL_EXPORT BOOL WINAPI MarshalStructAsParam_AsExpByRefInInnerArrayExp { outer2->arr[i].f1 = 77; } - char const * temp = "change string2"; - size_t len = strlen(temp); - LPCSTR str = (LPCSTR)TP_CoTaskMemAlloc( sizeof(char)*(len+1) ); - strcpy((char*)str,temp); - outer2->f4 = str; + outer2->s.f4 = CoStrDup("change string2"); return TRUE; } extern "C" DLL_EXPORT BOOL WINAPI MarshalStructAsParam_AsExpByRefOutInnerArrayExplicit(InnerArrayExplicit* outer2) @@ -884,11 +865,7 @@ extern "C" DLL_EXPORT BOOL WINAPI MarshalStructAsParam_AsExpByRefOutInnerArrayEx { outer2->arr[i].f1 = 77; } - char const * temp = "change string2"; - size_t len = strlen(temp); - LPCSTR str = (LPCSTR)TP_CoTaskMemAlloc( sizeof(char)*(len+1) ); - strcpy((char*)str,temp); - outer2->f4 = str; + outer2->s.f4 = CoStrDup("change string2"); return TRUE; } diff --git a/tests/src/Interop/StructMarshalling/PInvoke/MarshalStructAsParamDLL.h b/tests/src/Interop/StructMarshalling/PInvoke/MarshalStructAsParamDLL.h index bf76727..22ad037 100644 --- a/tests/src/Interop/StructMarshalling/PInvoke/MarshalStructAsParamDLL.h +++ b/tests/src/Interop/StructMarshalling/PInvoke/MarshalStructAsParamDLL.h @@ -1,6 +1,17 @@ #include "platformdefines.cpp" #include +inline char* CoStrDup(const char* str) +{ + size_t size = strlen(str) + 1; + char* dup = (char *)TP_CoTaskMemAlloc(size); + if (dup != nullptr) + { + strcpy_s(dup, size, str); + } + return dup; +} + const int NumArrElements = 2; struct InnerSequential { @@ -19,20 +30,7 @@ void ChangeInnerSequential(InnerSequential* p) { p->f1 = 77; p->f2 = 77.0; - - char const * lpstr = "changed string"; - size_t size = sizeof(char) * (strlen(lpstr) + 1); - LPSTR temp = (LPSTR)TP_CoTaskMemAlloc( size ); - memset(temp, 0, size); - if(temp) - { - strcpy( (char*)temp, lpstr ); - p->f3 = temp; - } - else - { - printf("Memory Allocated Failed!"); - } + p->f3 = CoStrDup("changed string"); } bool IsCorrectInnerSequential(InnerSequential* p) @@ -41,13 +39,7 @@ bool IsCorrectInnerSequential(InnerSequential* p) return false; if(p->f2 != 1.0) return false; - - char const * lpstr = "some string"; - size_t size = sizeof(char) * (strlen(lpstr) + 1); - LPSTR temp = (LPSTR)TP_CoTaskMemAlloc( size ); - memset(temp, 0, size); - - if( strcmp((char*)p->f3, temp) != 0 ) + if(strcmp(p->f3, "") != 0) return false; return true; @@ -62,6 +54,7 @@ typedef unsigned short WORD; typedef short SHORT; typedef float FLOAT; typedef double DOUBLE; +typedef long INT_PTR; #endif struct INNER2 // size = 12 bytes @@ -74,11 +67,7 @@ void ChangeINNER2(INNER2* p) { p->f1 = 77; p->f2 = 77.0; - char const * temp = "changed string"; - size_t len = strlen(temp); - LPCSTR str = (LPCSTR)TP_CoTaskMemAlloc( sizeof(char)*(len+1) ); - strcpy((char*)str,temp); - p->f3 = str; + p->f3 = CoStrDup("changed string"); } void PrintINNER2(INNER2* p, char const * name) { @@ -132,12 +121,7 @@ void PrintInnerExplicit(InnerExplicit* p, char const * name) void ChangeInnerExplicit(InnerExplicit* p) { p->f1 = 77; - - char const * temp = "changed string"; - size_t len = strlen(temp); - LPCSTR str = (LPCSTR)TP_CoTaskMemAlloc( sizeof(char)*(len+1) ); - strcpy((char*)str,temp); - p->f3 = str; + p->f3 = CoStrDup("changed string"); } struct InnerArraySequential @@ -157,25 +141,11 @@ void PrintInnerArraySequential(InnerArraySequential* p, char const * name) void ChangeInnerArraySequential(InnerArraySequential* p) { - char const * lpstr = "changed string"; - LPSTR temp; for(int i = 0; i < NumArrElements; i++) { (p->arr)[i].f1 = 77; (p->arr)[i].f2 = 77.0; - - size_t size = sizeof(char) * (strlen(lpstr) + 1); - temp = (LPSTR)TP_CoTaskMemAlloc( size ); - memset(temp, 0, size); - if(temp) - { - strcpy( (char*)temp, lpstr ); - (p->arr)[i].f3 = temp; - } - else - { - printf("Memory Allocated Failed!"); - } + (p->arr)[i].f3 = CoStrDup("changed string"); } } @@ -199,13 +169,14 @@ union InnerArrayExplicit // size = 32 bytes { LONG64 _unused0; LPCSTR f4; - }; - + } s; }; #ifdef WINDOWS #ifdef _WIN64 + #pragma warning(push) + #pragma warning(disable: 4201) // nonstandard extension used: nameless struct/union union OUTER3 // size = 32 bytes { struct InnerSequential arr[2]; @@ -215,6 +186,7 @@ union InnerArrayExplicit // size = 32 bytes LPCSTR f4; }; }; + #pragma warning(pop) #else struct OUTER3 // size = 28 bytes { @@ -244,22 +216,14 @@ void PrintOUTER3(OUTER3* p, char const * name) } void ChangeOUTER3(OUTER3* p) { - char const * temp = "changed string"; - size_t len = strlen(temp); - LPCSTR str = NULL; for(int i = 0; i < NumArrElements; i++) { (p->arr)[i].f1 = 77; (p->arr)[i].f2 = 77.0; - - str = (LPCSTR)TP_CoTaskMemAlloc( sizeof(char)*(len+1) ); - strcpy((char*)str,temp); - (p->arr)[i].f3 = str; + (p->arr)[i].f3 = CoStrDup("changed string"); } - str = (LPCSTR)TP_CoTaskMemAlloc( sizeof(char)*(len+1) ); - strcpy((char*)str,temp); - p->f4 = str; + p->f4 = CoStrDup("changed string"); } bool IsCorrectOUTER3(OUTER3* p) { @@ -293,19 +257,8 @@ void PrintCharSetAnsiSequential(CharSetAnsiSequential* p, char const * name) void ChangeCharSetAnsiSequential(CharSetAnsiSequential* p) { - char const * strSource = "change string"; - size_t size = strlen(strSource) + 1; - LPSTR temp = (LPSTR)TP_CoTaskMemAlloc(size); - if(temp != NULL) - { - strcpy((char*)temp,strSource); - p->f1 = temp; - p->f2 = 'n'; - } - else - { - printf("Memory Allocated Failed!"); - } + p->f1 = CoStrDup("change string"); + p->f2 = 'n'; } bool IsCorrectCharSetAnsiSequential(CharSetAnsiSequential* p) @@ -325,7 +278,11 @@ struct CharSetUnicodeSequential }; void PrintCharSetUnicodeSequential(CharSetUnicodeSequential* p, char const * name) { +#ifdef _WIN32 + wprintf(L"\t%S.f1 = %s\n", name, p->f1); +#else wprintf(L"\t%s.f1 = %S\n", name, p->f1); +#endif printf("\t%s.f2 = %c\n", name, p->f2); } @@ -336,7 +293,7 @@ void ChangeCharSetUnicodeSequential(CharSetUnicodeSequential* p) #else LPCWSTR strSource = u"change string"; #endif - int len = wcslen(strSource); + size_t len = wcslen(strSource); LPCWSTR temp = (LPCWSTR)TP_CoTaskMemAlloc(sizeof(WCHAR)*(len+1)); if(temp != NULL) { @@ -418,7 +375,7 @@ void ChangeNumberSequential(NumberSequential* p) bool IsCorrectNumberSequential(NumberSequential* p) { - if(p->i32 != -0x80000000 || p->ui32 != 0xffffffff || p->s1 != -0x8000 || p->us1 != 0xffff || p->b != 0 || + if(p->i32 != (-0x7fffffff - 1) || p->ui32 != 0xffffffff || p->s1 != -0x8000 || p->us1 != 0xffff || p->b != 0 || p->sb != 0x7f ||p->i16 != -0x8000 || p->ui16 != 0xffff || p->i64 != -1234567890 || p->ui64 != 1234567890 || (p->sgl) != 32.0 || p->d != 3.2) { @@ -448,17 +405,10 @@ void ChangeS3(S3* p) { p->flag = false; - char const * strSource = "change string"; - int len = strlen(strSource); - - LPCSTR temp = (LPCSTR)TP_CoTaskMemAlloc((sizeof(char)*len) + 1); - if(temp != NULL) - { - /*TP_CoTaskMemFree((void *)p->str);*/ - strcpy((char*)temp,strSource); - p->str = temp; - } - for(int i = 1;i<257;i++) + /*TP_CoTaskMemFree((void *)p->str);*/ + p->str = CoStrDup("change string"); + + for(int i = 1;i<257;i++) { p->vals[i-1] = i; } @@ -468,12 +418,7 @@ bool IsCorrectS3(S3* p) { int iflag = 0; - char const * lpstr = "some string"; - size_t size = sizeof(char) * (strlen(lpstr) + 1); - LPSTR temp = (LPSTR)TP_CoTaskMemAlloc( size ); - memset(temp, 0, size); - - if(!p->flag || strcmp((char*)p->str, temp) != 0) + if (!p->flag || strcmp(p->str, "") != 0) return false; for (int i = 0; i < 256; i++) { @@ -514,33 +459,16 @@ void PrintS5(S5* str, char const * name) } void ChangeS5(S5* str) { - Enum1 eInstance = e2; - char const * strSource = "change string"; - int len = strlen(strSource); - LPCSTR temp = (LPCSTR)TP_CoTaskMemAlloc(sizeof(char)*(len+1)); - if(temp != NULL) - { - strcpy((char*)temp,strSource); - str->s4.name = temp; - } + str->s4.name = CoStrDup("change string"); str->s4.age = 64; - str->ef = eInstance; + str->ef = e2; } bool IsCorrectS5(S5* str) { - Enum1 eInstance = e1; - - char const * lpstr = "some string"; - size_t size = sizeof(char) * (strlen(lpstr) + 1); - LPSTR temp = (LPSTR)TP_CoTaskMemAlloc( size ); - memset(temp, 0, size); - - if(str->s4.age != 32 || strcmp((char*)str->s4.name, temp) != 0) + if(str->s4.age != 32 || strcmp(str->s4.name, "") != 0) return false; - if(str->ef != eInstance) - { + if(str->ef != e1) return false; - } return true; } @@ -599,8 +527,13 @@ struct StringStructSequentialUnicode // size = 8 bytes void PrintStringStructSequentialUnicode(StringStructSequentialUnicode* str, char const * name) { +#ifdef _WIN32 + wprintf(L"\t%S.first = %s\n", name, str->first); + wprintf(L"\t%S.last = %s\n", name, str->last); +#else wprintf(L"\t%s.first = %s\n", name, str->first); wprintf(L"\t%s.last = %s\n", name, str->last); +#endif } bool IsCorrectStringStructSequentialUnicode(StringStructSequentialUnicode* str) @@ -674,19 +607,7 @@ bool IsCorrectS8(S8* str) void ChangeS8(S8* str) { - char const * lpstr = "world"; - size_t size = sizeof(char) * (strlen(lpstr) + 1); - LPSTR temp = (LPSTR)TP_CoTaskMemAlloc( size ); - memset(temp, 0, size); - if(temp) - { - strcpy( (char*)temp, lpstr ); - str->name = temp; - } - else - { - printf("Memory Allocated Failed!"); - } + str->name = CoStrDup("world"); str->gender = false; str->jobNum = 1; str->i32 = 256; @@ -787,7 +708,7 @@ void ChangeU(U* p) p->uiPtr = (LPVOID)(64); p->s = 32767; p->us = 0; - p->b = -1; + p->b = 255; p->sb = -128; p->l = -1234567890; p->ul = 0; diff --git a/tests/src/Interop/common/types.h b/tests/src/Interop/common/types.h index 7d7f776..cb59c42 100755 --- a/tests/src/Interop/common/types.h +++ b/tests/src/Interop/common/types.h @@ -28,7 +28,7 @@ typedef void* HMODULE; typedef void* ULONG_PTR; typedef unsigned error_t; typedef void* LPVOID; -typedef char BYTE; +typedef unsigned char BYTE; typedef WCHAR OLECHAR; typedef unsigned int UINT_PTR; @@ -54,4 +54,4 @@ typedef int* DWORD_PTR; #define FALSE 0 #endif -#endif //_INTEROP_TYPES__H \ No newline at end of file +#endif //_INTEROP_TYPES__H diff --git a/tests/src/JIT/CodeGenBringUpTests/Rotate.cs b/tests/src/JIT/CodeGenBringUpTests/Rotate.cs index 74a936e..9c5d959 100644 --- a/tests/src/JIT/CodeGenBringUpTests/Rotate.cs +++ b/tests/src/JIT/CodeGenBringUpTests/Rotate.cs @@ -102,12 +102,38 @@ public class Test [MethodImpl(MethodImplOptions.NoInlining)] static ulong rol64const() { - ulong value = flag() ? (ulong)0x123456789abcdef : (ulong)0x123456789abcdef; + ulong value = flag() ? (ulong)0x123456789abcdef : (ulong)0xabcdef123456789; int amount = 16; return (value >> (64 - amount)) | (value << amount); } [MethodImpl(MethodImplOptions.NoInlining)] + static ulong rol64_16(ulong value) + { + return (value >> (64 - 16)) | (value << 16); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ulong rol64_32(ulong value) + { + return (value >> (64 - 32)) | (value << 32); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ulong rol64_32_inplace(ulong value, ulong added) + { + ulong x = value + added; + x = (x >> (64 - 32)) | (x << 32); + return x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ulong rol64_33(ulong value) + { + return (value >> (64 - 33)) | (value << 33); + } + + [MethodImpl(MethodImplOptions.NoInlining)] ulong rol64field(int amount) { return (field << amount) | (field >> (64 - amount)); @@ -128,12 +154,38 @@ public class Test [MethodImpl(MethodImplOptions.NoInlining)] static ulong ror64const() { - ulong value = flag() ? (ulong)0x123456789abcdef : (ulong)0x123456789abcdef; + ulong value = flag() ? (ulong)0x123456789abcdef : (ulong)0xabcdef123456789; int amount = flag() ? 5 : 5; return (value << (64 - amount)) | (value >> amount); } [MethodImpl(MethodImplOptions.NoInlining)] + static ulong ror64_5(ulong value) + { + return (value << (64 - 5)) | (value >> 5); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ulong ror64_32(ulong value) + { + return (value << (64 - 32)) | (value >> 32); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ulong ror64_33(ulong value) + { + return (value << (64 - 33)) | (value >> 33); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ulong ror64_32_inplace(ulong value, ulong added) + { + ulong x = value + added; + x = (x << (64 - 32)) | (x >> 32); + return x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] static ulong ror64sfield(int amount) { return (s_field << (64 - amount)) | (s_field >> amount); @@ -244,6 +296,26 @@ public class Test return Fail; } + if (rol64_16(0x123456789abcdef) != 0x456789abcdef0123) + { + return Fail; + } + + if (rol64_32(0x123456789abcdef) != rol64(0x123456789abcdef, 32)) + { + return Fail; + } + + if (rol64_33(0x123456789abcdef) != rol64(0x123456789abcdef, 33)) + { + return Fail; + } + + if (rol64_32_inplace(0x123456789abcdef, 0) != rol64(0x123456789abcdef, 32)) + { + return Fail; + } + if (ror64(0x123456789abcdef, 0) != 0x123456789abcdef) { return Fail; @@ -259,6 +331,26 @@ public class Test return Fail; } + if (ror64_5(0x123456789abcdef) != 0x78091a2b3c4d5e6f) + { + return Fail; + } + + if (ror64_32(0x123456789abcdef) != ror64(0x123456789abcdef, 32)) + { + return Fail; + } + + if (ror64_33(0x123456789abcdef) != ror64(0x123456789abcdef, 33)) + { + return Fail; + } + + if (ror64_32_inplace(0x123456789abcdef, 0) != ror64(0x123456789abcdef, 32)) + { + return Fail; + } + if (rol32_call(0x12345678, 16) != 0x56781234) { return Fail; diff --git a/tests/src/JIT/CodeGenBringUpTests/Shift.cs b/tests/src/JIT/CodeGenBringUpTests/Shift.cs new file mode 100644 index 0000000..085ad3f --- /dev/null +++ b/tests/src/JIT/CodeGenBringUpTests/Shift.cs @@ -0,0 +1,86 @@ +// 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.Runtime.CompilerServices; + +public class Test +{ + [MethodImpl(MethodImplOptions.NoInlining)] + static ulong shl64(ulong shift, int count) + { + return shift << count; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ulong shl64_32_inplace(ulong shift, ulong addit) + { + ulong x = shift + addit; + x = x << 32; + return x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ulong shl64_33_inplace(ulong shift, ulong addit) + { + ulong x = shift + addit; + x = x << 33; + return x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ulong shr64(ulong shift, int count) + { + return shift >> count; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ulong shr64_32_inplace(ulong shift, ulong addit) + { + ulong x = shift + addit; + x = x >> 32; + return x; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static ulong shr1_32_add(ulong shift, ulong addit) + { + ulong x = (addit + (shift >> 1)) >> 31; + return x; + } + + public static int Main() + { + const int Pass = 100; + const int Fail = -1; + + if (shl64_32_inplace(0x123456789abcdef, 0) != shl64(0x123456789abcdef, 32)) + { + Console.WriteLine("shl64_32"); + return Fail; + } + + if (shl64_33_inplace(0x123456789abcdef, 0) != shl64(0x123456789abcdef, 33)) + { + Console.WriteLine("shl64_33"); + return Fail; + } + + if (shr64_32_inplace(0x123456789abcdef, 0) != shr64(0x123456789abcdef, 32)) + { + Console.WriteLine("shr64_32 {0:X} {1:X}", shr64_32_inplace(0x123456789abcdef, 0), shr64(0x123456789abcdef, 32)); + return Fail; + } + + if (shr1_32_add(0x123456789abcdef, 0) != shr64(0x123456789abcdef, 32)) + { + Console.WriteLine("HAHAHAHAHAHAHA {0:X}", shr1_32_add(0x123456789abcdef, 0)); + return Fail; + } + + return Pass; + } +} diff --git a/tests/src/JIT/CodeGenBringUpTests/Shift.csproj b/tests/src/JIT/CodeGenBringUpTests/Shift.csproj new file mode 100644 index 0000000..2189ed3 --- /dev/null +++ b/tests/src/JIT/CodeGenBringUpTests/Shift.csproj @@ -0,0 +1,40 @@ + + + + + Debug + AnyCPU + 2.0 + {AF7F2478-9B49-4776-BEAF-0BF8916E2D79} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + + + + + + + $(JitPackagesConfigFileDirectory)threading+thread\project.json + $(JitPackagesConfigFileDirectory)threading+thread\project.lock.json + + + + + diff --git a/tests/src/JIT/Directed/pinvoke/pinvoke-examples.cs b/tests/src/JIT/Directed/pinvoke/pinvoke-examples.cs new file mode 100644 index 0000000..26080d8 --- /dev/null +++ b/tests/src/JIT/Directed/pinvoke/pinvoke-examples.cs @@ -0,0 +1,223 @@ +// 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. + +// Test cases showing interaction of inlining and inline pinvoke, +// along with the impact of EH. + +using System; +using System.Runtime.CompilerServices; + + +namespace PInvokeTest +{ + internal class Test + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static int AsForceInline() + { + return Environment.ProcessorCount; + } + + static int AsNormalInline() + { + return Environment.ProcessorCount; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int AsNoInline() + { + return Environment.ProcessorCount; + } + + static bool FromTryCatch() + { + bool result = false; + try + { + // All pinvokes should be inline, except on x64 + result = (Environment.ProcessorCount == AsNormalInline()); + } + catch (Exception) + { + result = false; + } + return result; + } + + static bool FromTryFinally() + { + bool result = false; + bool result1 = false; + bool result2 = false; + try + { + // All pinvokes should be inline, except on x64 + result1 = (Environment.ProcessorCount == AsNormalInline()); + result2 = (Environment.ProcessorCount == AsNormalInline()); + } + finally + { + result = result1 && result2; + } + return result; + } + + static bool FromTryFinally2() + { + bool result = false; + bool result1 = false; + bool result2 = false; + + try + { + // These two pinvokes should be inline, except on x64 + result1 = (Environment.ProcessorCount == AsNormalInline()); + } + finally + { + // These two pinvokes should *not* be inline (finally) + result2 = (Environment.ProcessorCount == AsNormalInline()); + result = result1 && result2; + } + + return result; + } + + static bool FromTryFinally3() + { + bool result = false; + bool result1 = false; + bool result2 = false; + + try + { + // These two pinvokes should be inline, except on x64 + result1 = (Environment.ProcessorCount == AsNormalInline()); + } + finally + { + try + { + // These two pinvokes should *not* be inline (finally) + result2 = (Environment.ProcessorCount == AsNormalInline()); + } + catch (Exception) + { + result2 = false; + } + + result = result1 && result2; + } + + return result; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static bool FromInline() + { + // These two pinvokes should be inline + bool result = (Environment.ProcessorCount == AsForceInline()); + return result; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static bool FromInline2() + { + // These four pinvokes should be inline + bool result1 = (Environment.ProcessorCount == AsNormalInline()); + bool result2 = (Environment.ProcessorCount == AsForceInline()); + return result1 && result2; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static bool FromNoInline() + { + // The only pinvoke should be inline + bool result = (Environment.ProcessorCount == AsNoInline()); + return result; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static bool FromNoInline2() + { + // Three pinvokes should be inline + bool result1 = (Environment.ProcessorCount == AsNormalInline()); + bool result2 = (Environment.ProcessorCount == AsNoInline()); + return result1 && result2; + } + + static bool FromFilter() + { + bool result = false; + + try + { + throw new Exception("expected"); + } + // These two pinvokes should *not* be inline (filter) + // + // For the first call the jit won't inline the wrapper, so + // it just calls get_ProcessorCount. + // + // For the second call, the force inline works, and the + // subsequent inline of get_ProcessorCount exposes a call + // to the pinvoke GetProcessorCount. This pinvoke will + // not be inline. + catch (Exception) when (Environment.ProcessorCount == AsForceInline()) + { + result = true; + } + + return result; + } + + static bool FromColdCode() + { + int pc = 0; + bool result1 = false; + bool result2 = false; + + try + { + // This pinvoke should not be inline (cold) + pc = Environment.ProcessorCount; + throw new Exception("expected"); + } + catch (Exception) + { + // These two pinvokes should not be inline (catch) + // + // For the first call the jit won't inline the + // wrapper, so it just calls get_ProcessorCount. + // + // For the second call, the force inline works, and + // the subsequent inline of get_ProcessorCount exposes + // a call to the pinvoke GetProcessorCount. This + // pinvoke will not be inline. + result1 = (pc == Environment.ProcessorCount); + result2 = (pc == AsForceInline()); + } + + return result1 && result2; + } + + private static int Main() + { + bool result = true; + + result &= FromTryCatch(); + result &= FromTryFinally(); + result &= FromTryFinally2(); + result &= FromTryFinally3(); + result &= FromInline(); + result &= FromInline2(); + result &= FromNoInline(); + result &= FromNoInline2(); + result &= FromFilter(); + result &= FromColdCode(); + + return (result ? 100 : -1); + } + } +} diff --git a/tests/src/JIT/Directed/pinvoke/pinvoke-examples.csproj b/tests/src/JIT/Directed/pinvoke/pinvoke-examples.csproj new file mode 100644 index 0000000..78cf447 --- /dev/null +++ b/tests/src/JIT/Directed/pinvoke/pinvoke-examples.csproj @@ -0,0 +1,44 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + PdbOnly + + + + + + + + + $(JitPackagesConfigFileDirectory)minimal\project.json + $(JitPackagesConfigFileDirectory)minimal\project.lock.json + + + + + \ No newline at end of file diff --git a/tests/src/JIT/Methodical/fp/exgen/10w5d_cs_d.csproj b/tests/src/JIT/Methodical/fp/exgen/10w5d_cs_d.csproj index fed9ead..a405402 100644 --- a/tests/src/JIT/Methodical/fp/exgen/10w5d_cs_d.csproj +++ b/tests/src/JIT/Methodical/fp/exgen/10w5d_cs_d.csproj @@ -14,6 +14,9 @@ $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages ..\..\ 7a9bfb7d + + + true @@ -43,4 +46,4 @@ - \ No newline at end of file + diff --git a/tests/src/JIT/Methodical/fp/exgen/10w5d_cs_r.csproj b/tests/src/JIT/Methodical/fp/exgen/10w5d_cs_r.csproj index 7d311bf..bd5ae97 100644 --- a/tests/src/JIT/Methodical/fp/exgen/10w5d_cs_r.csproj +++ b/tests/src/JIT/Methodical/fp/exgen/10w5d_cs_r.csproj @@ -14,6 +14,9 @@ $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages ..\..\ 7a9bfb7d + + + true @@ -43,4 +46,4 @@ - \ No newline at end of file + diff --git a/tests/src/JIT/Methodical/structs/systemvbringup/structpinvoketests.cs b/tests/src/JIT/Methodical/structs/systemvbringup/structpinvoketests.cs index 7fc5203..8eae606 100644 --- a/tests/src/JIT/Methodical/structs/systemvbringup/structpinvoketests.cs +++ b/tests/src/JIT/Methodical/structs/systemvbringup/structpinvoketests.cs @@ -364,650 +364,698 @@ namespace structinreg s1.y = 2; s1.z = 3; s1.w = 4; - - InvokeCallback1((par) => { - Console.WriteLine("S1: {0}, {1}, {2}, {3}", par.x, par.y, par.z, par.w); - if (par.x != 1 || par.y != 2 || par.z != 3 || par.w != 4) - { - throw new System.Exception(); - } - }, s1); - S2 s2; - s2.x = 1; - s2.y = 2; - s2.z = 3; - InvokeCallback2((par) => { - Console.WriteLine("S2: {0}, {1}, {2}", par.x, par.y, par.z); - if (par.x != 1 || par.y != 2 || par.z != 3) + try + { + InvokeCallback1((par) => { - throw new System.Exception(); - } - }, s2); - - S3 s3; - s3.x = 1; - s3.y = 2; - s3.z = 3; - InvokeCallback3((par) => { - Console.WriteLine("S3: {0}, {1}, {2}", par.x, par.y, par.z); - if (par.x != 1 || par.y != 2 || par.z != 3) + Console.WriteLine("S1: {0}, {1}, {2}, {3}", par.x, par.y, par.z, par.w); + if (par.x != 1 || par.y != 2 || par.z != 3 || par.w != 4) + { + throw new System.Exception(); + } + }, s1); + + S2 s2; + s2.x = 1; + s2.y = 2; + s2.z = 3; + InvokeCallback2((par) => { - throw new System.Exception(); - } - }, s3); - - S4 s4; - s4.x = 1; - s4.y = 2; - InvokeCallback4((par) => { - Console.WriteLine("S4: {0}, {1}", par.x, par.y); - if (par.x != 1 || par.y != 2) + Console.WriteLine("S2: {0}, {1}, {2}", par.x, par.y, par.z); + if (par.x != 1 || par.y != 2 || par.z != 3) + { + throw new System.Exception(); + } + }, s2); + + S3 s3; + s3.x = 1; + s3.y = 2; + s3.z = 3; + InvokeCallback3((par) => { - throw new System.Exception(); - } - }, s4); - - S5 s5; - s5.x = 1; - s5.y = 2; - InvokeCallback5((par) => { - Console.WriteLine("S5: {0}, {1}", par.x, par.y); - if (par.x != 1 || par.y != 2) + Console.WriteLine("S3: {0}, {1}, {2}", par.x, par.y, par.z); + if (par.x != 1 || par.y != 2 || par.z != 3) + { + throw new System.Exception(); + } + }, s3); + + S4 s4; + s4.x = 1; + s4.y = 2; + InvokeCallback4((par) => { - throw new System.Exception(); - } - }, s5); - - S6 s6; - s6.x = 1; - s6.y = 2; - s6.z = 3; - s6.w = 4; - InvokeCallback6((par) => { - Console.WriteLine("S6: {0}, {1}, {2}, {3}", par.x, par.y, par.z, par.w); - if (par.x != 1 || par.y != 2 || par.z != 3 || par.w != 4) + Console.WriteLine("S4: {0}, {1}", par.x, par.y); + if (par.x != 1 || par.y != 2) + { + throw new System.Exception(); + } + }, s4); + + S5 s5; + s5.x = 1; + s5.y = 2; + InvokeCallback5((par) => { - throw new System.Exception(); - } - }, s6); - - S7 s7; - s7.x = 1; - s7.y = 2; - s7.z = 3; - InvokeCallback7((par) => { - Console.WriteLine("S7: {0}, {1}, {2}", par.x, par.y, par.z); - if (par.x != 1 || par.y != 2 || par.z != 3) + Console.WriteLine("S5: {0}, {1}", par.x, par.y); + if (par.x != 1 || par.y != 2) + { + throw new System.Exception(); + } + }, s5); + + S6 s6; + s6.x = 1; + s6.y = 2; + s6.z = 3; + s6.w = 4; + InvokeCallback6((par) => { - throw new System.Exception(); - } - }, s7); - - S8 s8; - s8.x = 1; - s8.y = 2; - InvokeCallback8((par) => { - Console.WriteLine("S8: {0}, {1}", par.x, par.y); - if (par.x != 1 || par.y != 2) + Console.WriteLine("S6: {0}, {1}, {2}, {3}", par.x, par.y, par.z, par.w); + if (par.x != 1 || par.y != 2 || par.z != 3 || par.w != 4) + { + throw new System.Exception(); + } + }, s6); + + S7 s7; + s7.x = 1; + s7.y = 2; + s7.z = 3; + InvokeCallback7((par) => { - throw new System.Exception(); - } - }, s8); - - S9 s9; - s9.x = 1; - s9.y = 2; - s9.z = 3; - s9.w = 4; - InvokeCallback9((par) => { - Console.WriteLine("S9: {0}, {1}, {2}, {3}", par.x, par.y, par.z, par.w); - if (par.x != 1 || par.y != 2 || par.z != 3 || par.w != 4) + Console.WriteLine("S7: {0}, {1}, {2}", par.x, par.y, par.z); + if (par.x != 1 || par.y != 2 || par.z != 3) + { + throw new System.Exception(); + } + }, s7); + + S8 s8; + s8.x = 1; + s8.y = 2; + InvokeCallback8((par) => { - throw new System.Exception(); - } - }, s9); - - S10 s10; - s10.a = 1; - s10.b = 2; - s10.c = 3; - s10.d = 4; - s10.e = 5; - s10.f = 6; - s10.g = 7; - s10.h = 8; - InvokeCallback10((par) => { - Console.WriteLine("S10: {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}", par.a, par.b, par.c, par.d, par.e, par.f, par.g, par.h); - if (par.a != 1 || par.b != 2 || par.c != 3 || par.d != 4 || - par.e != 5 || par.f != 6 || par.g != 7 || par.h != 8) + Console.WriteLine("S8: {0}, {1}", par.x, par.y); + if (par.x != 1 || par.y != 2) + { + throw new System.Exception(); + } + }, s8); + + S9 s9; + s9.x = 1; + s9.y = 2; + s9.z = 3; + s9.w = 4; + InvokeCallback9((par) => { - throw new System.Exception(); - } - }, s10); - - S11 s11; - s11.a = 1; - s11.b = 2; - s11.c = 3; - s11.d = 4; - s11.e = 5; - InvokeCallback11((par) => { - Console.WriteLine("S11: {0}, {1}, {2}, {3}, {4}", par.a, par.b, par.c, par.d, par.e); - if (par.a != 1 || par.b != 2 || par.c != 3 || par.d != 4 || par.e != 5) + Console.WriteLine("S9: {0}, {1}, {2}, {3}", par.x, par.y, par.z, par.w); + if (par.x != 1 || par.y != 2 || par.z != 3 || par.w != 4) + { + throw new System.Exception(); + } + }, s9); + + S10 s10; + s10.a = 1; + s10.b = 2; + s10.c = 3; + s10.d = 4; + s10.e = 5; + s10.f = 6; + s10.g = 7; + s10.h = 8; + InvokeCallback10((par) => { - throw new System.Exception(); - } - }, s11); - - S12 s12; - s12.a = 1; - s12.b = 2; - s12.c = 3; - s12.d = 4; - s12.e = 5; - s12.f = 6; - s12.g = 7; - s12.h = 8; - s12.i = 9; - InvokeCallback12((par) => { - Console.WriteLine("S12: {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}", par.a, par.b, par.c, par.d, par.e, par.f, par.g, par.h, par.i); - if (par.a != 1 || par.b != 2 || par.c != 3 || par.d != 4 || - par.e != 5 || par.f != 6 || par.g != 7 || par.h != 8 || par.i != 9) + Console.WriteLine("S10: {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}", par.a, par.b, par.c, par.d, par.e, par.f, par.g, par.h); + if (par.a != 1 || par.b != 2 || par.c != 3 || par.d != 4 || + par.e != 5 || par.f != 6 || par.g != 7 || par.h != 8) + { + throw new System.Exception(); + } + }, s10); + + S11 s11; + s11.a = 1; + s11.b = 2; + s11.c = 3; + s11.d = 4; + s11.e = 5; + InvokeCallback11((par) => { - throw new System.Exception(); - } - }, s12); - - S13 s13; - s13.hasValue = 1; - s13.x = 2; - InvokeCallback13((par) => { - Console.WriteLine("S13: {0}, {1}", par.hasValue, par.x); - if (par.hasValue != 1 || par.x != 2) + Console.WriteLine("S11: {0}, {1}, {2}, {3}, {4}", par.a, par.b, par.c, par.d, par.e); + if (par.a != 1 || par.b != 2 || par.c != 3 || par.d != 4 || par.e != 5) + { + throw new System.Exception(); + } + }, s11); + + S12 s12; + s12.a = 1; + s12.b = 2; + s12.c = 3; + s12.d = 4; + s12.e = 5; + s12.f = 6; + s12.g = 7; + s12.h = 8; + s12.i = 9; + InvokeCallback12((par) => { - throw new System.Exception(); - } - }, s13); - - S14 s14; - s14.x = 1; - s14.y = 2; - InvokeCallback14((par) => { - Console.WriteLine("S14: {0}, {1}", par.x, par.y); - if (par.x != 1 || par.y != 2) + Console.WriteLine("S12: {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}", par.a, par.b, par.c, par.d, par.e, par.f, par.g, par.h, par.i); + if (par.a != 1 || par.b != 2 || par.c != 3 || par.d != 4 || + par.e != 5 || par.f != 6 || par.g != 7 || par.h != 8 || par.i != 9) + { + throw new System.Exception(); + } + }, s12); + + S13 s13; + s13.hasValue = 1; + s13.x = 2; + InvokeCallback13((par) => { - throw new System.Exception(); - } - }, s14); - - S15 s15; - s15.a = 1; - s15.b = 2; - s15.c = 3; - s15.d = 4; - s15.e = 5; - s15.f = 6; - s15.g = 7; - s15.h = 8; - s15.i = 9; - InvokeCallback15((par) => { - Console.WriteLine("S15: {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}", par.a, par.b, par.c, par.d, par.e, par.f, par.g, par.h, par.i); - if (par.a != 1 || par.b != 2 || par.c != 3 || par.d != 4 || - par.e != 5 || par.f != 6 || par.g != 7 || par.h != 8 || par.i != 9) + Console.WriteLine("S13: {0}, {1}", par.hasValue, par.x); + if (par.hasValue != 1 || par.x != 2) + { + throw new System.Exception(); + } + }, s13); + + S14 s14; + s14.x = 1; + s14.y = 2; + InvokeCallback14((par) => { - throw new System.Exception(); - } - }, s15); - - S16 s16; - s16.x = 1; - s16.y = 2; - InvokeCallback16((par) => { - Console.WriteLine("S16: {0}, {1}", par.x, par.y); - if (par.x != 1 || par.y != 2) + Console.WriteLine("S14: {0}, {1}", par.x, par.y); + if (par.x != 1 || par.y != 2) + { + throw new System.Exception(); + } + }, s14); + + S15 s15; + s15.a = 1; + s15.b = 2; + s15.c = 3; + s15.d = 4; + s15.e = 5; + s15.f = 6; + s15.g = 7; + s15.h = 8; + s15.i = 9; + InvokeCallback15((par) => { - throw new System.Exception(); - } - }, s16); - - S17 s17; - s17.x = 1; - s17.y = 2; - InvokeCallback17((par) => { - Console.WriteLine("S17: {0}, {1}", par.x, par.y); - if (par.x != 1 || par.y != 2) + Console.WriteLine("S15: {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}", par.a, par.b, par.c, par.d, par.e, par.f, par.g, par.h, par.i); + if (par.a != 1 || par.b != 2 || par.c != 3 || par.d != 4 || + par.e != 5 || par.f != 6 || par.g != 7 || par.h != 8 || par.i != 9) + { + throw new System.Exception(); + } + }, s15); + + S16 s16; + s16.x = 1; + s16.y = 2; + InvokeCallback16((par) => { - throw new System.Exception(); - } - }, s17); - - S18 s18; - s18.x = 1; - s18.y = 2; - s18.z = 3; - InvokeCallback18((par) => { - Console.WriteLine("S18: {0}, {1}, {2}", par.x, par.y, par.z); - if (par.x != 1 || par.y != 2 || par.z != 3) + Console.WriteLine("S16: {0}, {1}", par.x, par.y); + if (par.x != 1 || par.y != 2) + { + throw new System.Exception(); + } + }, s16); + + S17 s17; + s17.x = 1; + s17.y = 2; + InvokeCallback17((par) => { - throw new System.Exception(); - } - }, s18); - - S19 s19; - s19.x = 1; - s19.y = 2; - s19.z = 3; - s19.w = 4; - InvokeCallback19((par) => { - Console.WriteLine("S19: {0}, {1}, {2}, {3}", par.x, par.y, par.z, par.w); - if (par.x != 1 || par.y != 2 || par.z != 3 || par.w != 4) + Console.WriteLine("S17: {0}, {1}", par.x, par.y); + if (par.x != 1 || par.y != 2) + { + throw new System.Exception(); + } + }, s17); + + S18 s18; + s18.x = 1; + s18.y = 2; + s18.z = 3; + InvokeCallback18((par) => { - throw new System.Exception(); - } - }, s19); - - S20 s20; - s20.x = 1; - s20.y = 2; - s20.z = 3; - s20.w = 4; - InvokeCallback20((par) => { - Console.WriteLine("S20: {0}, {1}, {2}, {3}", par.x, par.y, par.z, par.w); - if (par.x != 1 || par.y != 2 || par.z != 3 || par.w != 4) + Console.WriteLine("S18: {0}, {1}, {2}", par.x, par.y, par.z); + if (par.x != 1 || par.y != 2 || par.z != 3) + { + throw new System.Exception(); + } + }, s18); + + S19 s19; + s19.x = 1; + s19.y = 2; + s19.z = 3; + s19.w = 4; + InvokeCallback19((par) => { - throw new System.Exception(); - } - }, s20); - -/* These tests are not working on non Windows CoreCLR. Enable this when GH Issue #2076 is resolved. - TestClass testClass = new TestClass(); - S28 s28; - s28.x = null; - s28.y = 1; - - InvokeCallback28((par) => { - Console.WriteLine("S28: {0}, {1}", par.x == null ? "Null" : "Not null", par.y); - if (par.x != null || par.y != 1) + Console.WriteLine("S19: {0}, {1}, {2}, {3}", par.x, par.y, par.z, par.w); + if (par.x != 1 || par.y != 2 || par.z != 3 || par.w != 4) + { + throw new System.Exception(); + } + }, s19); + + S20 s20; + s20.x = 1; + s20.y = 2; + s20.z = 3; + s20.w = 4; + InvokeCallback20((par) => { - throw new System.Exception(); - } - }, s28); - - s28.x = testClass; - s28.y = 5; - - InvokeCallback28((par) => { - Console.WriteLine("S28: {0}, {1}", par.x == null ? "Null" : "Not null", par.y); - if (par.x != testClass || par.y != 5) + Console.WriteLine("S20: {0}, {1}, {2}, {3}", par.x, par.y, par.z, par.w); + if (par.x != 1 || par.y != 2 || par.z != 3 || par.w != 4) + { + throw new System.Exception(); + } + }, s20); + + /* These tests are not working on non Windows CoreCLR. Enable this when GH Issue #2076 is resolved. + TestClass testClass = new TestClass(); + S28 s28; + s28.x = null; + s28.y = 1; + + InvokeCallback28((par) => { + Console.WriteLine("S28: {0}, {1}", par.x == null ? "Null" : "Not null", par.y); + if (par.x != null || par.y != 1) + { + throw new System.Exception(); + } + }, s28); + + s28.x = testClass; + s28.y = 5; + + InvokeCallback28((par) => { + Console.WriteLine("S28: {0}, {1}", par.x == null ? "Null" : "Not null", par.y); + if (par.x != testClass || par.y != 5) + { + throw new System.Exception(); + } + }, s28); + + S29 s29; + s29.x = 1; + s29.y = null; + + InvokeCallback29((par) => { + Console.WriteLine("S29: {0}, {1}", par.x, par.y == null ? "Null" : "Not null"); + if (par.x != 1 || par.y != null) + { + throw new System.Exception(); + } + }, s29); + + s29.x = 5; + s29.y = testClass; + + InvokeCallback29((par) => { + Console.WriteLine("S29: {0}, {1}", par.x, par.y == null ? "Null" : "Not null"); + if (par.x != 5 || par.y != testClass) + { + throw new System.Exception(); + } + }, s29); + Enable this when GH Issue #2076 is resolved. */ + S30 s30; + s30.x = 1; + s30.y = 2; + + S30 s30_2; + s30_2.x = 3; + s30_2.y = 4; + + S30 s30_3; + s30_3.x = 5; + s30_3.y = 6; + + // Program p = new Program(); + InvokeCallback30(p.Test30, s30, s30_2, s30_3); + S1 s1r = InvokeCallback1R((par) => { - throw new System.Exception(); - } - }, s28); - - S29 s29; - s29.x = 1; - s29.y = null; - - InvokeCallback29((par) => { - Console.WriteLine("S29: {0}, {1}", par.x, par.y == null ? "Null" : "Not null"); - if (par.x != 1 || par.y != null) + Console.WriteLine("S1: {0}, {1}, {2}, {3}", par.x, par.y, par.z, par.w); + if (par.x != 1 || par.y != 2 || par.z != 3 || par.w != 4) + { + throw new System.Exception(); + } + + }, s1); + Console.WriteLine("S1R: {0}, {1}, {2}, {3}", s1r.x, s1r.y, s1r.z, s1r.w); + if (s1r.x != 1 || s1r.y != 2 || s1r.z != 3 || s1r.w != 4) { throw new System.Exception(); } - }, s29); - s29.x = 5; - s29.y = testClass; - - InvokeCallback29((par) => { - Console.WriteLine("S29: {0}, {1}", par.x, par.y == null ? "Null" : "Not null"); - if (par.x != 5 || par.y != testClass) + S2 s2r = InvokeCallback2R((par) => { - throw new System.Exception(); - } - }, s29); - Enable this when GH Issue #2076 is resolved. */ - S30 s30; - s30.x = 1; - s30.y = 2; - - S30 s30_2; - s30_2.x = 3; - s30_2.y = 4; - - S30 s30_3; - s30_3.x = 5; - s30_3.y = 6; - - // Program p = new Program(); - InvokeCallback30(p.Test30, s30, s30_2, s30_3); - S1 s1r = InvokeCallback1R((par) => { - Console.WriteLine("S1: {0}, {1}, {2}, {3}", par.x, par.y, par.z, par.w); - if (par.x != 1 || par.y != 2 || par.z != 3 || par.w != 4) + Console.WriteLine("S2: {0}, {1}, {2}", par.x, par.y, par.z); + if (par.x != 1 || par.y != 2 || par.z != 3) + { + throw new System.Exception(); + } + }, s2); + Console.WriteLine("S2R: {0}, {1}, {2}", s2r.x, s2r.y, s2r.z); + if (s2r.x != 1 || s2r.y != 2 || s2r.z != 3) { throw new System.Exception(); } - }, s1); - Console.WriteLine("S1R: {0}, {1}, {2}, {3}", s1r.x, s1r.y, s1r.z, s1r.w); - if (s1r.x != 1 || s1r.y != 2 || s1r.z != 3 || s1r.w != 4) - { - throw new System.Exception(); - } - - S2 s2r = InvokeCallback2R((par) => { - Console.WriteLine("S2: {0}, {1}, {2}", par.x, par.y, par.z); - if (par.x != 1 || par.y != 2 || par.z != 3) + S3 s3r = InvokeCallback3R((par) => + { + Console.WriteLine("S3: {0}, {1}, {2}", par.x, par.y, par.z); + if (par.x != 1 || par.y != 2 || par.z != 3) + { + throw new System.Exception(); + } + }, s3); + Console.WriteLine("S3R: {0}, {1}, {2}", s3r.x, s3r.y, s3r.z); + if (s3r.x != 1 || s3r.y != 2 || s3r.z != 3) { throw new System.Exception(); } - }, s2); - Console.WriteLine("S2R: {0}, {1}, {2}", s2r.x, s2r.y, s2r.z); - if (s2r.x != 1 || s2r.y != 2 || s2r.z != 3) - { - throw new System.Exception(); - } - S3 s3r = InvokeCallback3R((par) => { - Console.WriteLine("S3: {0}, {1}, {2}", par.x, par.y, par.z); - if (par.x != 1 || par.y != 2 || par.z != 3) + S4 s4r = InvokeCallback4R((par) => + { + Console.WriteLine("S4: {0}, {1}", par.x, par.y); + if (par.x != 1 || par.y != 2) + { + throw new System.Exception(); + } + }, s4); + Console.WriteLine("S4R: {0}, {1}", s4r.x, s4r.y); + if (s4r.x != 1 || s4r.y != 2) { throw new System.Exception(); } - }, s3); - Console.WriteLine("S3R: {0}, {1}, {2}", s3r.x, s3r.y, s3r.z); - if (s3r.x != 1 || s3r.y != 2 || s3r.z != 3) - { - throw new System.Exception(); - } - S4 s4r = InvokeCallback4R((par) => { - Console.WriteLine("S4: {0}, {1}", par.x, par.y); - if (par.x != 1 || par.y != 2) + S5 s5r = InvokeCallback5R((par) => + { + Console.WriteLine("S5: {0}, {1}", par.x, par.y); + if (par.x != 1 || par.y != 2) + { + throw new System.Exception(); + } + }, s5); + Console.WriteLine("S5R: {0}, {1}", s5r.x, s5r.y); + if (s5r.x != 1 || s5r.y != 2) { throw new System.Exception(); } - }, s4); - Console.WriteLine("S4R: {0}, {1}", s4r.x, s4r.y); - if (s4r.x != 1 || s4r.y != 2) - { - throw new System.Exception(); - } - S5 s5r = InvokeCallback5R((par) => { - Console.WriteLine("S5: {0}, {1}", par.x, par.y); - if (par.x != 1 || par.y != 2) + S6 s6r = InvokeCallback6R((par) => + { + Console.WriteLine("S6: {0}, {1}, {2}, {3}", par.x, par.y, par.z, par.w); + if (par.x != 1 || par.y != 2 || par.z != 3 || par.w != 4) + { + throw new System.Exception(); + } + }, s6); + Console.WriteLine("S6R: {0}, {1}, {2}, {3}", s6r.x, s6r.y, s6r.z, s6r.w); + if (s6r.x != 1 || s6r.y != 2 || s6r.z != 3 || s6r.w != 4) { throw new System.Exception(); } - }, s5); - Console.WriteLine("S5R: {0}, {1}", s5r.x, s5r.y); - if (s5r.x != 1 || s5r.y != 2) - { - throw new System.Exception(); - } - S6 s6r = InvokeCallback6R((par) => { - Console.WriteLine("S6: {0}, {1}, {2}, {3}", par.x, par.y, par.z, par.w); - if (par.x != 1 || par.y != 2 || par.z != 3 || par.w != 4) + S7 s7r = InvokeCallback7R((par) => + { + Console.WriteLine("S7: {0}, {1}, {2}", par.x, par.y, par.z); + if (par.x != 1 || par.y != 2 || par.z != 3) + { + throw new System.Exception(); + } + }, s7); + Console.WriteLine("S7R: {0}, {1}, {2}", s7r.x, s7r.y, s7r.z); + if (s7r.x != 1 || s7r.y != 2 || s7r.z != 3) { throw new System.Exception(); } - }, s6); - Console.WriteLine("S6R: {0}, {1}, {2}, {3}", s6r.x, s6r.y, s6r.z, s6r.w); - if (s6r.x != 1 || s6r.y != 2 || s6r.z != 3 || s6r.w != 4) - { - throw new System.Exception(); - } - S7 s7r = InvokeCallback7R((par) => { - Console.WriteLine("S7: {0}, {1}, {2}", par.x, par.y, par.z); - if (par.x != 1 || par.y != 2 || par.z != 3) + S8 s8r = InvokeCallback8R((par) => + { + Console.WriteLine("S8: {0}, {1}", par.x, par.y); + if (par.x != 1 || par.y != 2) + { + throw new System.Exception(); + } + }, s8); + Console.WriteLine("S8R: {0}, {1}", s8r.x, s8r.y); + if (s8r.x != 1 || s8r.y != 2) { throw new System.Exception(); } - }, s7); - Console.WriteLine("S7R: {0}, {1}, {2}", s7r.x, s7r.y, s7r.z); - if (s7r.x != 1 || s7r.y != 2 || s7r.z != 3) - { - throw new System.Exception(); - } - S8 s8r = InvokeCallback8R((par) => { - Console.WriteLine("S8: {0}, {1}", par.x, par.y); - if (par.x != 1 || par.y != 2) + S9 s9r = InvokeCallback9R((par) => + { + Console.WriteLine("S9: {0}, {1}, {2}, {3}", par.x, par.y, par.z, par.w); + if (par.x != 1 || par.y != 2 || par.z != 3 || par.w != 4) + { + throw new System.Exception(); + } + }, s9); + Console.WriteLine("S9R: {0}, {1}, {2}, {3}", s9r.x, s9r.y, s9r.z, s9r.w); + if (s9r.x != 1 || s9r.y != 2 || s9r.z != 3 || s9r.w != 4) { throw new System.Exception(); } - }, s8); - Console.WriteLine("S8R: {0}, {1}", s8r.x, s8r.y); - if (s8r.x != 1 || s8r.y != 2) - { - throw new System.Exception(); - } - S9 s9r = InvokeCallback9R((par) => { - Console.WriteLine("S9: {0}, {1}, {2}, {3}", par.x, par.y, par.z, par.w); - if (par.x != 1 || par.y != 2 || par.z != 3 || par.w != 4) + S10 s10r = InvokeCallback10R((par) => { - throw new System.Exception(); - } - }, s9); - Console.WriteLine("S9R: {0}, {1}, {2}, {3}", s9r.x, s9r.y, s9r.z, s9r.w); - if (s9r.x != 1 || s9r.y != 2 || s9r.z != 3 || s9r.w != 4) - { - throw new System.Exception(); - } - - S10 s10r = InvokeCallback10R((par) => { - Console.WriteLine("S10: {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}", par.a, par.b, par.c, par.d, par.e, par.f, par.g, par.h); - if (par.a != 1 || par.b != 2 || par.c != 3 || par.d != 4 || - par.e != 5 || par.f != 6 || par.g != 7 || par.h != 8) + Console.WriteLine("S10: {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}", par.a, par.b, par.c, par.d, par.e, par.f, par.g, par.h); + if (par.a != 1 || par.b != 2 || par.c != 3 || par.d != 4 || + par.e != 5 || par.f != 6 || par.g != 7 || par.h != 8) + { + throw new System.Exception(); + } + }, s10); + Console.WriteLine("S10R: {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}", s10r.a, s10r.b, s10r.c, s10r.d, s10r.e, s10r.f, s10r.g, s10r.h); + if (s10r.a != 1 || s10r.b != 2 || s10r.c != 3 || s10r.d != 4 || + s10r.e != 5 || s10r.f != 6 || s10r.g != 7 || s10r.h != 8) { throw new System.Exception(); } - }, s10); - Console.WriteLine("S10R: {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}", s10r.a, s10r.b, s10r.c, s10r.d, s10r.e, s10r.f, s10r.g, s10r.h); - if (s10r.a != 1 || s10r.b != 2 || s10r.c != 3 || s10r.d != 4 || - s10r.e != 5 || s10r.f != 6 || s10r.g != 7 || s10r.h != 8) - { - throw new System.Exception(); - } - S11 s11r = InvokeCallback11R((par) => { - Console.WriteLine("S11: {0}, {1}, {2}, {3}, {4}", par.a, par.b, par.c, par.d, par.e); - if (par.a != 1 || par.b != 2 || par.c != 3 || par.d != 4 || par.e != 5) + S11 s11r = InvokeCallback11R((par) => + { + Console.WriteLine("S11: {0}, {1}, {2}, {3}, {4}", par.a, par.b, par.c, par.d, par.e); + if (par.a != 1 || par.b != 2 || par.c != 3 || par.d != 4 || par.e != 5) + { + throw new System.Exception(); + } + }, s11); + Console.WriteLine("S11R: {0}, {1}, {2}, {3}, {4}", s11r.a, s11r.b, s11r.c, s11r.d, s11r.e); + if (s11r.a != 1 || s11r.b != 2 || s11r.c != 3 || s11r.d != 4 || s11r.e != 5) { throw new System.Exception(); } - }, s11); - Console.WriteLine("S11R: {0}, {1}, {2}, {3}, {4}", s11r.a, s11r.b, s11r.c, s11r.d, s11r.e); - if (s11r.a != 1 || s11r.b != 2 || s11r.c != 3 || s11r.d != 4 || s11r.e != 5) - { - throw new System.Exception(); - } - S12 s12r = InvokeCallback12R((par) => { - Console.WriteLine("S12: {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}", par.a, par.b, par.c, par.d, par.e, par.f, par.g, par.h, par.i); - if (par.a != 1 || par.b != 2 || par.c != 3 || par.d != 4 || - par.e != 5 || par.f != 6 || par.g != 7 || par.h != 8 || par.i != 9) + S12 s12r = InvokeCallback12R((par) => + { + Console.WriteLine("S12: {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}", par.a, par.b, par.c, par.d, par.e, par.f, par.g, par.h, par.i); + if (par.a != 1 || par.b != 2 || par.c != 3 || par.d != 4 || + par.e != 5 || par.f != 6 || par.g != 7 || par.h != 8 || par.i != 9) + { + throw new System.Exception(); + } + }, s12); + Console.WriteLine("S12R: {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}", s12r.a, s12r.b, s12r.c, s12r.d, s12r.e, s12r.f, s12r.g, s12r.h, s12r.i); + if (s12r.a != 1 || s12r.b != 2 || s12r.c != 3 || s12r.d != 4 || + s12r.e != 5 || s12r.f != 6 || s12r.g != 7 || s12r.h != 8 || s12r.i != 9) { throw new System.Exception(); } - }, s12); - Console.WriteLine("S12R: {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}", s12r.a, s12r.b, s12r.c, s12r.d, s12r.e, s12r.f, s12r.g, s12r.h, s12r.i); - if (s12r.a != 1 || s12r.b != 2 || s12r.c != 3 || s12r.d != 4 || - s12r.e != 5 || s12r.f != 6 || s12r.g != 7 || s12r.h != 8 || s12r.i != 9) - { - throw new System.Exception(); - } - S13 s13r = InvokeCallback13R((par) => { - Console.WriteLine("S13: {0}, {1}", par.hasValue, par.x); - if (par.hasValue != 1 || par.x != 2) + S13 s13r = InvokeCallback13R((par) => + { + Console.WriteLine("S13: {0}, {1}", par.hasValue, par.x); + if (par.hasValue != 1 || par.x != 2) + { + throw new System.Exception(); + } + }, s13); + Console.WriteLine("S13R: {0}, {1}", s13r.hasValue, s13r.x); + if (s13r.hasValue != 1 || s13r.x != 2) { throw new System.Exception(); } - }, s13); - Console.WriteLine("S13R: {0}, {1}", s13r.hasValue, s13r.x); - if (s13r.hasValue != 1 || s13r.x != 2) - { - throw new System.Exception(); - } - S14 s14r = InvokeCallback14R((par) => { - Console.WriteLine("S14: {0}, {1}", par.x, par.y); - if (par.x != 1 || par.y != 2) + S14 s14r = InvokeCallback14R((par) => + { + Console.WriteLine("S14: {0}, {1}", par.x, par.y); + if (par.x != 1 || par.y != 2) + { + throw new System.Exception(); + } + }, s14); + Console.WriteLine("S14R: {0}, {1}", s14r.x, s14r.y); + if (s14r.x != 1 || s14r.y != 2) { throw new System.Exception(); } - }, s14); - Console.WriteLine("S14R: {0}, {1}", s14r.x, s14r.y); - if (s14r.x != 1 || s14r.y != 2) - { - throw new System.Exception(); - } - S15 s15r = InvokeCallback15R((par) => { - Console.WriteLine("S15: {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}", par.a, par.b, par.c, par.d, par.e, par.f, par.g, par.h, par.i); - if (par.a != 1 || par.b != 2 || par.c != 3 || par.d != 4 || - par.e != 5 || par.f != 6 || par.g != 7 || par.h != 8 || par.i != 9) + S15 s15r = InvokeCallback15R((par) => + { + Console.WriteLine("S15: {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}", par.a, par.b, par.c, par.d, par.e, par.f, par.g, par.h, par.i); + if (par.a != 1 || par.b != 2 || par.c != 3 || par.d != 4 || + par.e != 5 || par.f != 6 || par.g != 7 || par.h != 8 || par.i != 9) + { + throw new System.Exception(); + } + }, s15); + Console.WriteLine("S15R: {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}", s15r.a, s15r.b, s15r.c, s15r.d, s15r.e, s15r.f, s15r.g, s15r.h, s15r.i); + if (s15r.a != 1 || s15r.b != 2 || s15r.c != 3 || s15r.d != 4 || + s15r.e != 5 || s15r.f != 6 || s15r.g != 7 || s15r.h != 8 || s15r.i != 9) { throw new System.Exception(); } - }, s15); - Console.WriteLine("S15R: {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}", s15r.a, s15r.b, s15r.c, s15r.d, s15r.e, s15r.f, s15r.g, s15r.h, s15r.i); - if (s15r.a != 1 || s15r.b != 2 || s15r.c != 3 || s15r.d != 4 || - s15r.e != 5 || s15r.f != 6 || s15r.g != 7 || s15r.h != 8 || s15r.i != 9) - { - throw new System.Exception(); - } - S16 s16r = InvokeCallback16R((par) => { - Console.WriteLine("S16: {0}, {1}", par.x, par.y); - if (par.x != 1 || par.y != 2) + S16 s16r = InvokeCallback16R((par) => + { + Console.WriteLine("S16: {0}, {1}", par.x, par.y); + if (par.x != 1 || par.y != 2) + { + throw new System.Exception(); + } + }, s16); + Console.WriteLine("S16R: {0}, {1}", s16r.x, s16r.y); + if (s16r.x != 1 || s16r.y != 2) { throw new System.Exception(); } - }, s16); - Console.WriteLine("S16R: {0}, {1}", s16r.x, s16r.y); - if (s16r.x != 1 || s16r.y != 2) - { - throw new System.Exception(); - } - S17 s17r = InvokeCallback17R((par) => { - Console.WriteLine("S17: {0}, {1}", par.x, par.y); - if (par.x != 1 || par.y!= 2) + S17 s17r = InvokeCallback17R((par) => + { + Console.WriteLine("S17: {0}, {1}", par.x, par.y); + if (par.x != 1 || par.y != 2) + { + throw new System.Exception(); + } + }, s17); + Console.WriteLine("S17R: {0}, {1}", s17r.x, s17r.y); + if (s17r.x != 1 || s17r.y != 2) { throw new System.Exception(); } - }, s17); - Console.WriteLine("S17R: {0}, {1}", s17r.x, s17r.y); - if (s17r.x != 1 || s17r.y != 2) - { - throw new System.Exception(); - } - S18 s18r = InvokeCallback18R((par) => { - Console.WriteLine("S18: {0}, {1}, {2}", par.x, par.y, par.z); - if (par.x != 1 || par.y != 2 || par.z != 3) + S18 s18r = InvokeCallback18R((par) => + { + Console.WriteLine("S18: {0}, {1}, {2}", par.x, par.y, par.z); + if (par.x != 1 || par.y != 2 || par.z != 3) + { + throw new System.Exception(); + } + }, s18); + Console.WriteLine("S18R: {0}, {1}, {2}", s18r.x, s18r.y, s18r.z); + if (s18r.x != 1 || s18r.y != 2 || s18r.z != 3) { throw new System.Exception(); } - }, s18); - Console.WriteLine("S18R: {0}, {1}, {2}", s18r.x, s18r.y, s18r.z); - if (s18r.x != 1 || s18r.y != 2 || s18r.z != 3) - { - throw new System.Exception(); - } - S19 s19r = InvokeCallback19R((par) => { - Console.WriteLine("S19: {0}, {1}, {2}, {3}", par.x, par.y, par.z, par.w); - if (par.x != 1 || par.y != 2 || par.z != 3 || par.w != 4) + S19 s19r = InvokeCallback19R((par) => + { + Console.WriteLine("S19: {0}, {1}, {2}, {3}", par.x, par.y, par.z, par.w); + if (par.x != 1 || par.y != 2 || par.z != 3 || par.w != 4) + { + throw new System.Exception(); + } + }, s19); + Console.WriteLine("S19R: {0}, {1}, {2}, {3}", s19r.x, s19r.y, s19r.z, s19r.w); + if (s19r.x != 1 || s19r.y != 2 || s19r.z != 3 || s19r.w != 4) { throw new System.Exception(); } - }, s19); - Console.WriteLine("S19R: {0}, {1}, {2}, {3}", s19r.x, s19r.y, s19r.z, s19r.w); - if (s19r.x != 1 || s19r.y != 2 || s19r.z != 3 || s19r.w != 4) - { - throw new System.Exception(); - } - S20 s20r = InvokeCallback20R((par) => { - Console.WriteLine("S20: {0}, {1}, {2}, {3}", par.x, par.y, par.z, par.w); - if (par.x != 1 || par.y != 2 || par.z != 3 || par.w != 4) + S20 s20r = InvokeCallback20R((par) => + { + Console.WriteLine("S20: {0}, {1}, {2}, {3}", par.x, par.y, par.z, par.w); + if (par.x != 1 || par.y != 2 || par.z != 3 || par.w != 4) + { + throw new System.Exception(); + } + }, s20); + Console.WriteLine("S20R: {0}, {1}, {2}, {3}", s20r.x, s20r.y, s20r.z, s20r.w); + if (s20r.x != 1 || s20r.y != 2 || s20r.z != 3 || s20r.w != 4) { throw new System.Exception(); } - }, s20); - Console.WriteLine("S20R: {0}, {1}, {2}, {3}", s20r.x, s20r.y, s20r.z, s20r.w); - if (s20r.x != 1 || s20r.y != 2 || s20r.z != 3 || s20r.w != 4) - { - throw new System.Exception(); - } -/* These tests are not working on non Windows CoreCLR. Enable this when GH Issue #2076 is resolved. - s28.x = null; - S28 s28r = InvokeCallback28R((par) => { - Console.WriteLine("S28: {0}, {1}", par.x == null ? "Null" : "Not null", par.y); - if (par.x == null || par.y != 5) + /* These tests are not working on non Windows CoreCLR. Enable this when GH Issue #2076 is resolved. + s28.x = null; + S28 s28r = InvokeCallback28R((par) => { + Console.WriteLine("S28: {0}, {1}", par.x == null ? "Null" : "Not null", par.y); + if (par.x == null || par.y != 5) + { + throw new System.Exception(); + } + }, s28); + Console.WriteLine("S28R: {0}, {1}", s28r.x == null ? "Null" : "Not null", s28r.y); + if (s28r.x == null || s28r.y != 5) { throw new System.Exception(); } - }, s28); - Console.WriteLine("S28R: {0}, {1}", s28r.x == null ? "Null" : "Not null", s28r.y); - if (s28r.x == null || s28r.y != 5) - { - throw new System.Exception(); - } - s28.x = testClass; - s28.y = 5; - - s28r = InvokeCallback28R((par) => { - Console.WriteLine("S28: {0}, {1}", par.x == null ? "Null" : "Not null", par.y); - if (par.x != testClass || par.y != 5) + s28.x = testClass; + s28.y = 5; + + s28r = InvokeCallback28R((par) => { + Console.WriteLine("S28: {0}, {1}", par.x == null ? "Null" : "Not null", par.y); + if (par.x != testClass || par.y != 5) + { + throw new System.Exception(); + } + }, s28); + Console.WriteLine("S28R: {0}, {1}", s28r.x == null ? "Null" : "Not null", s28r.y); + if (s28r.x != testClass || s28r.y != 5) { throw new System.Exception(); } - }, s28); - Console.WriteLine("S28R: {0}, {1}", s28r.x == null ? "Null" : "Not null", s28r.y); - if (s28r.x != testClass || s28r.y != 5) - { - throw new System.Exception(); - } - s29.y = null; - S29 s29r = InvokeCallback29R((par) => { - Console.WriteLine("S29: {0}, {1}", par.x, par.y == null ? "Null" : "Not null"); - if (par.x != 5 || par.y == null) + s29.y = null; + S29 s29r = InvokeCallback29R((par) => { + Console.WriteLine("S29: {0}, {1}", par.x, par.y == null ? "Null" : "Not null"); + if (par.x != 5 || par.y == null) + { + throw new System.Exception(); + } + }, s29); + Console.WriteLine("S29R: {0}, {1}", s29r.x, s29r.y == null ? "Null" : "Not null"); + if (s29r.x != 5 || s29r.y == null) { throw new System.Exception(); } - }, s29); - Console.WriteLine("S29R: {0}, {1}", s29r.x, s29r.y == null ? "Null" : "Not null"); - if (s29r.x != 5 || s29r.y == null) - { - throw new System.Exception(); - } - s29.x = 5; - s29.y = testClass; - s29r = InvokeCallback29R((par) => { - Console.WriteLine("S29: {0}, {1}", par.x, par.y == null ? "Null" : "Not null"); - if (par.x != 5 || par.y != testClass) + s29.x = 5; + s29.y = testClass; + s29r = InvokeCallback29R((par) => { + Console.WriteLine("S29: {0}, {1}", par.x, par.y == null ? "Null" : "Not null"); + if (par.x != 5 || par.y != testClass) + { + throw new System.Exception(); + } + }, s29); + Console.WriteLine("S29R: {0}, {1}", s29r.x, s29r.y == null ? "Null" : "Not null"); + if (s29r.x != 5 || s29r.y != testClass) { throw new System.Exception(); } - }, s29); - Console.WriteLine("S29R: {0}, {1}", s29r.x, s29r.y == null ? "Null" : "Not null"); - if (s29r.x != 5 || s29r.y != testClass) + Enable this when GH Issue #2076 is resolved. */ + } + catch (Exception e) { - throw new System.Exception(); + Console.WriteLine(e.Message); + return -1; } - Enable this when GH Issue #2076 is resolved. */ return 100; } diff --git a/tests/src/JIT/Methodical/structs/valuetuple.cs b/tests/src/JIT/Methodical/structs/valuetuple.cs new file mode 100644 index 0000000..9e8af5e --- /dev/null +++ b/tests/src/JIT/Methodical/structs/valuetuple.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. +// See the LICENSE file in the project root for more information. +// + +// This test is extracted and simplified from the corefx tests for the ValueTuple class. +// It exposed an issue with assertion propagation not validating the assertions +// for a containing struct when a field lclVar is defined. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +[StructLayout(LayoutKind.Auto)] +public struct ValueTuple +{ + public T1 Item1; + public T2 Item2; + public T3 Item3; + public ValueTuple(T1 item1, T2 item2, T3 item3) + { + Item1 = item1; + Item2 = item2; + Item3 = item3; + } + + public static ValueTuple Create(T1 item1, T2 item2, T3 item3) => + new ValueTuple(item1, item2, item3); + + public override bool Equals(object obj) + { + return obj is ValueTuple && Equals((ValueTuple)obj); + } + + public bool Equals(ValueTuple other) + { + return Item1.Equals(other.Item1) && Item2.Equals(other.Item2) && Item3.Equals(other.Item3); + } + public override int GetHashCode() + { + return 0; + } +} + +public static class TupleExtensions +{ + public static ValueTuple + ToValueTuple( + this Tuple value) + { + return ValueTuple.Create(value.Item1, value.Item2, value.Item3); + } + public static Tuple + ToTuple( + this ValueTuple value) + { + return Tuple.Create(value.Item1, value.Item2, value.Item3); + } +} + +public class StructOptsTest +{ + const int Pass = 100; + const int Fail = -1; + + public static int ConvertToRef3() + { + var refTuple = Tuple.Create(-1, -1, -1); + var valueTuple = ValueTuple.Create(1, 2, 3); + + refTuple = valueTuple.ToTuple(); + if (!String.Equals("(1, 2, 3)", refTuple.ToString())) + { + Console.WriteLine("Expected (1, 2, 3); got " + refTuple.ToString()); + return Fail; + } + return Pass; + } + + public static int Main() + { + int returnVal = Fail; + try + { + returnVal = ConvertToRef3(); + } + catch (Exception e) + { + Console.WriteLine("Unexpected exception " + e.Message); + returnVal = Fail; + } + return returnVal; + } +} diff --git a/tests/src/JIT/Methodical/structs/valuetuple.csproj b/tests/src/JIT/Methodical/structs/valuetuple.csproj new file mode 100644 index 0000000..486744b --- /dev/null +++ b/tests/src/JIT/Methodical/structs/valuetuple.csproj @@ -0,0 +1,41 @@ + + + + + Debug + AnyCPU + 2.0 + {0B8F1AF4-9355-4307-BC68-08A2947AD3B9} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + true + + + + + + + + + False + + + + + + + + + + $(JitPackagesConfigFileDirectory)threading+thread\project.json + $(JitPackagesConfigFileDirectory)threading+thread\project.lock.json + + + + + diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/Adams/Adams.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/Adams/Adams.cs index 427ec92..431d857 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchF/Adams/Adams.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Adams/Adams.cs @@ -18,6 +18,8 @@ using Microsoft.Xunit.Performance; [assembly: MeasureInstructionsRetired] #endif // XUNIT_PERF +namespace Benchstone.BenchF +{ public static class Adams { #if DEBUG @@ -41,7 +43,7 @@ public static class Adams #if VERBOSE Console.WriteLine(" ADAMS-MOULTON METHOD "); -#endif // VERBOSE +#endif // VERBOSE n = 4; h = 1.0 / 32.0; @@ -67,7 +69,7 @@ public static class Adams f[i] = xn + yn; #if VERBOSE Console.WriteLine("{0}, {1}, {2}, {3}, {4}", k, xn, yn, dn, en); -#endif // VERBOSE +#endif // VERBOSE } for (k = 4; k <= nstep; k++) @@ -137,7 +139,7 @@ public static class Adams bool result = true; // Note: we can't check xn or yn better because of the precision - // with which original results are given + // with which original results are given result &= System.Math.Abs(g_xn_base - g_xn) <= 1.5e-7; result &= System.Math.Abs(g_yn_base - g_yn) <= 1.5e-7; result &= System.Math.Abs(g_dn) <= 2.5e-9; @@ -161,3 +163,4 @@ public static class Adams return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/BenchMk2/BenchMk2.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/BenchMk2/BenchMk2.cs index 9701644..c4cfc0b 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchF/BenchMk2/BenchMk2.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchF/BenchMk2/BenchMk2.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchF +{ public static class BenchMk2 { #if DEBUG @@ -64,3 +66,4 @@ public static class BenchMk2 return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/BenchMrk/BenchMrk.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/BenchMrk/BenchMrk.cs index 27a5fe6..f342b2d8 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchF/BenchMrk/BenchMrk.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchF/BenchMrk/BenchMrk.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchF +{ public static class BenchMrk { #if DEBUG @@ -64,3 +66,4 @@ public static class BenchMrk return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/Bisect/Bisect.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/Bisect/Bisect.cs index 1c27003..724416a 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchF/Bisect/Bisect.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Bisect/Bisect.cs @@ -12,6 +12,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchF +{ public static class Bisect { #if DEBUG @@ -161,3 +163,4 @@ public static class Bisect return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/DMath/DMath.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/DMath/DMath.cs index a2c3a38..47c5e20 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchF/DMath/DMath.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchF/DMath/DMath.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchF +{ public static class DMath { #if DEBUG @@ -110,4 +112,5 @@ public static class DMath return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/FFT/FFT.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/FFT/FFT.cs index 3e85327..8881eae 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchF/FFT/FFT.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchF/FFT/FFT.cs @@ -13,6 +13,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchF +{ public static class FFT { #if DEBUG @@ -151,3 +153,4 @@ public static class FFT return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/InProd/InProd.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/InProd/InProd.cs index ff54ea7..26096b7 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchF/InProd/InProd.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchF/InProd/InProd.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchF +{ public static class InProd { #if DEBUG @@ -132,3 +134,4 @@ public static class InProd return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/InvMt/InvMt.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/InvMt/InvMt.cs index a5f387b..6ecfb62 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchF/InvMt/InvMt.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchF/InvMt/InvMt.cs @@ -12,6 +12,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchF +{ public static class InvMt { #if DEBUG @@ -135,3 +137,4 @@ public static class InvMt return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/LLoops/LLoops.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/LLoops/LLoops.cs index 6dcb6c4..73ec09a 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchF/LLoops/LLoops.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchF/LLoops/LLoops.cs @@ -60,6 +60,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchF +{ public class LLoops { #if DEBUG @@ -648,3 +650,4 @@ public class LLoops return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/Lorenz/Lorenz.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/Lorenz/Lorenz.cs index bff6398..5819446 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchF/Lorenz/Lorenz.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Lorenz/Lorenz.cs @@ -12,6 +12,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchF +{ public static class Lorenz { #if DEBUG @@ -132,3 +134,4 @@ public static class Lorenz return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/MatInv4/MatInv4.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/MatInv4/MatInv4.cs index eb5e33b..a00c29b 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchF/MatInv4/MatInv4.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchF/MatInv4/MatInv4.cs @@ -10,6 +10,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchF +{ public static class MatInv4 { #if DEBUG @@ -217,11 +219,11 @@ public static class MatInv4 // 0 < ik <= n^2 ik = nk + i; hold = a[ik - 1]; - // -n < ij <= 0 + // -n < ij <= 0 ij = i - n; for (j = 1; j <= n; ++j) { - // i <= n, ij <= n + n + ... + n (n times) or ij <= n * n + // i <= n, ij <= n + n + ... + n (n times) or ij <= n * n ij = ij + n; if (j == k) { @@ -237,7 +239,7 @@ public static class MatInv4 kj = k - n; for (j = 1; j <= n; ++j) { - // k <= n, kj <= n + n + ... + n (n times) or kj <= n * n + // k <= n, kj <= n + n + ... + n (n times) or kj <= n * n kj = kj + n; if (j == k) { @@ -268,11 +270,11 @@ public static class MatInv4 jr = n * (i - 1); for (j = 1; j <= n; ++j) { - // jk <= n^2 - n + n + // jk <= n^2 - n + n // jk <= n^2 jk = jq + j; hold = a[jk - 1]; - // ji <= n^2 - n + n + // ji <= n^2 - n + n // ji <= n^2 ji = jr + j; a[jk - 1] = -a[ji - 1]; @@ -288,7 +290,7 @@ public static class MatInv4 ki = k - n; for (i = 1; i <= n; ++i) { - // ki <= n + n + ... + n (n times) or ki <= n * n + // ki <= n + n + ... + n (n times) or ki <= n * n ki = ki + n; hold = a[ki - 1]; // if i=1, ji = (1 + (n-1) * n) - 1 + n ==> ij = n^2 @@ -378,7 +380,7 @@ public static class MatInv4 { if (j != k) { - // Accessing upto n^2 - n + n - 1 ==> n^2 - 1 + // Accessing upto n^2 - n + n - 1 ==> n^2 - 1 a[(i - 1) * n + (j - 1)] = a[(i - 1) * n + (k - 1)] * a[(k - 1) * n + (j - 1)] + a[(i - 1) * n + (j - 1)]; } } @@ -493,3 +495,4 @@ public static class MatInv4 return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/NewtE/NewtE.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/NewtE/NewtE.cs index 0fc1413..47f90d8 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchF/NewtE/NewtE.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchF/NewtE/NewtE.cs @@ -13,6 +13,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchF +{ public static class NewtE { #if DEBUG @@ -133,3 +135,4 @@ public static class NewtE return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/NewtR/NewtR.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/NewtR/NewtR.cs index cf945bc..c590f6e 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchF/NewtR/NewtR.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchF/NewtR/NewtR.cs @@ -12,6 +12,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchF +{ public static class NewtR { #if DEBUG @@ -129,3 +131,4 @@ public static class NewtR return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/Regula/Regula.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/Regula/Regula.cs index 9743ab6..0011288 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchF/Regula/Regula.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Regula/Regula.cs @@ -12,6 +12,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchF +{ public static class Regula { #if DEBUG @@ -191,3 +193,4 @@ public static class Regula return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/Romber/Romber.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/Romber/Romber.cs index 5824cd4..a4d56f7 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchF/Romber/Romber.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Romber/Romber.cs @@ -12,6 +12,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchF +{ public static class Romber { #if DEBUG @@ -167,3 +169,4 @@ public static class Romber return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/Secant/Secant.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/Secant/Secant.cs index e7d1ace..060fb5b 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchF/Secant/Secant.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Secant/Secant.cs @@ -12,6 +12,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchF +{ public static class Secant { #if DEBUG @@ -140,3 +142,4 @@ public static class Secant return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/Simpsn/Simpsn.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/Simpsn/Simpsn.cs index e1e9f0e..5b2df29 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchF/Simpsn/Simpsn.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Simpsn/Simpsn.cs @@ -12,6 +12,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchF +{ public static class Simpsn { #if DEBUG @@ -91,3 +93,4 @@ public static class Simpsn return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/SqMtx/SqMtx.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/SqMtx/SqMtx.cs index 673757c..b22aad8 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchF/SqMtx/SqMtx.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchF/SqMtx/SqMtx.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchF +{ public static class SqMtx { #if DEBUG @@ -101,3 +103,4 @@ public static class SqMtx return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/Trap/Trap.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/Trap/Trap.cs index a5e3e5c..3a0de10 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchF/Trap/Trap.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Trap/Trap.cs @@ -12,6 +12,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchF +{ public static class Trap { #if DEBUG @@ -94,3 +96,4 @@ public static class Trap return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/Whetsto/Whetsto.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/Whetsto/Whetsto.cs index 2ab0b61..ffe3fa5 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchF/Whetsto/Whetsto.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Whetsto/Whetsto.cs @@ -12,6 +12,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchF +{ public static class Whetsto { #if DEBUG @@ -240,3 +242,4 @@ public static class Whetsto return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/8Queens/8Queens.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/8Queens/8Queens.cs index 76ed0c8..e641ee0 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/8Queens/8Queens.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/8Queens/8Queens.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class EightQueens { @@ -68,7 +70,7 @@ public static class EightQueens } i = i + 1; } - + TryMe(1, ref q, b, a); return (q == 1); @@ -92,9 +94,10 @@ public static class EightQueens } return result; } - + public static int Main() { bool result = TestBase(); return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/Ackermann/Ackermann.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/Ackermann/Ackermann.cs index 512f35f..5bfa196 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/Ackermann/Ackermann.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Ackermann/Ackermann.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class Ackermann { @@ -40,7 +42,7 @@ public static class Ackermann int a33 = Acker(3, 3); return (a00 == 1) && (a11 == 3) && (a22 == 7) & (a33 == 61); } - + [Benchmark] public static void Test() { foreach (var iteration in Benchmark.Iterations) { @@ -59,9 +61,10 @@ public static class Ackermann } return result; } - + public static int Main() { bool result = TestBase(); return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/AddArray/AddArray.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/AddArray/AddArray.cs index 0fa2ff9..d38e6b4 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/AddArray/AddArray.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/AddArray/AddArray.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class AddArray { @@ -48,14 +50,14 @@ public static class AddArray m = j; flags4[m] = flags3[l] + m + m + m + m; } - + for (j = 0; j <= Size; j++) { k = j; l = j; m = j; flags1[j] = flags1[j] + flags2[k] + flags3[l] + flags4[m] - flags2[k - j + l]; } - + // Escape each flags array so that their elements will appear live-out Escape(flags1); Escape(flags2); @@ -83,9 +85,10 @@ public static class AddArray } return result; } - + public static int Main() { bool result = TestBase(); return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/AddArray2/AddArray2.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/AddArray2/AddArray2.cs index 865b944..a6004f0 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/AddArray2/AddArray2.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/AddArray2/AddArray2.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class AddArray2 { #if DEBUG @@ -129,3 +131,4 @@ public static class AddArray2 return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/Array1/Array1.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/Array1/Array1.cs index 8d5dbd6..780b7ce 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/Array1/Array1.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Array1/Array1.cs @@ -18,6 +18,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class Array1 { #if DEBUG @@ -152,3 +154,4 @@ public static class Array1 return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/Array2/Array2.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/Array2/Array2.cs index 1b720b9..dac100c 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/Array2/Array2.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Array2/Array2.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class Array2 { @@ -75,7 +77,7 @@ public static class Array2 } bool result = VerifyCopy(s, d); - + return result; } @@ -92,9 +94,10 @@ public static class Array2 bool result = Bench(Iterations); return result; } - + public static int Main() { bool result = TestBase(); return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/BenchE/BenchE.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/BenchE/BenchE.cs index 9cf7d77..b16c482 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/BenchE/BenchE.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/BenchE/BenchE.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class BenchE { #if DEBUG @@ -115,3 +117,4 @@ public static class BenchE return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort/BubbleSort.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort/BubbleSort.cs index 78626ff..558484d 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort/BubbleSort.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort/BubbleSort.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class BubbleSort { @@ -43,7 +45,7 @@ public static class BubbleSort return false; } } - + return true; } @@ -79,9 +81,10 @@ public static class BubbleSort } return result; } - + public static int Main() { bool result = TestBase(); return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort2/BubbleSort2.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort2/BubbleSort2.cs index 55e5a5f..8c2e63a 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort2/BubbleSort2.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort2/BubbleSort2.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class BubbleSort2 { @@ -82,9 +84,10 @@ public static class BubbleSort2 } return result; } - + public static int Main() { bool result = TestBase(); return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/CSieve/CSieve.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/CSieve/CSieve.cs index 606f740..aca2637 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/CSieve/CSieve.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/CSieve/CSieve.cs @@ -12,6 +12,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class CSieve { @@ -74,9 +76,10 @@ public static class CSieve } return result; } - + public static int Main() { bool result = TestBase(); return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/Fib/Fib.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/Fib/Fib.cs index 01064bb..ee028db 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/Fib/Fib.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Fib/Fib.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class Fib { @@ -30,7 +32,7 @@ public static class Fib return 1; } } - + [MethodImpl(MethodImplOptions.NoInlining)] static bool Bench() { int fib = Fibonacci(Number); @@ -55,9 +57,10 @@ public static class Fib } return result; } - + public static int Main() { bool result = TestBase(); return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/HeapSort/HeapSort.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/HeapSort/HeapSort.cs index 9fd7aa3..64b5c8f 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/HeapSort/HeapSort.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/HeapSort/HeapSort.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class HeapSort { @@ -32,7 +34,7 @@ public static class HeapSort j = i; k = j / 2; m = x[i]; - + // 0 < k <= (n / 2) // 1 <= j <= n while (k > 0) { @@ -113,9 +115,10 @@ public static class HeapSort } return result; } - + public static int Main() { bool result = TestBase(); return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/IniArray/IniArray.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/IniArray/IniArray.cs index 78fa233..268af7b 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/IniArray/IniArray.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/IniArray/IniArray.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class IniArray { @@ -52,9 +54,10 @@ public static class IniArray bool result = Bench(); return result; } - + public static int Main() { bool result = TestBase(); return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/LogicArray/LogicArray.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/LogicArray/LogicArray.cs index f5ff746..c5b4e3b 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/LogicArray/LogicArray.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/LogicArray/LogicArray.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class LogicArray { @@ -89,9 +91,10 @@ public static class LogicArray bool result = Bench(); return result; } - + public static int Main() { bool result = TestBase(); return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/Midpoint/Midpoint.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/Midpoint/Midpoint.cs index 6e4f193..9146874 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/Midpoint/Midpoint.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Midpoint/Midpoint.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class Midpoint { @@ -96,9 +98,10 @@ public static class Midpoint bool result = Bench(); return result; } - + public static int Main() { bool result = TestBase(); return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/MulMatrix/MulMatrix.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/MulMatrix/MulMatrix.cs index 3f9c224..a45c012 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/MulMatrix/MulMatrix.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/MulMatrix/MulMatrix.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class MulMatrix { @@ -19,7 +21,7 @@ public static class MulMatrix #else public const int Iterations = 100; #endif - + const int Size = 75; static volatile object VolatileObject; @@ -132,9 +134,10 @@ public static class MulMatrix bool result = Bench(); return result; } - + public static int Main() { bool result = TestBase(); return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/NDhrystone/NDhrystone.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/NDhrystone/NDhrystone.cs index c252674..33effcb 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/NDhrystone/NDhrystone.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/NDhrystone/NDhrystone.cs @@ -7,7 +7,7 @@ // Dhrystone: a synthetic systems programming benchmark // Reinhold P. Weicker // Communications of the ACM, Volume 27 Issue 10, Oct 1984, Pages 1013-1030 - + using Microsoft.Xunit.Performance; using System; using System.Runtime.CompilerServices; @@ -16,6 +16,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class NDhrystone { @@ -63,9 +65,9 @@ public static class NDhrystone int intLoc2; int intLoc3 = 0; Enumeration enumLoc; - + int i; /* modification */ - + m_ptrGlb.PtrComp = m_ptrGlbNext; m_ptrGlb.Discr = Enumeration.Ident1; m_ptrGlb.EnumComp = Enumeration.Ident3; @@ -117,12 +119,12 @@ public static class NDhrystone ptrParIn = ptrParIn.PtrComp; } } - + static void Proc2(ref int intParIO) { int intLoc; Enumeration enumLoc = Enumeration.Ident2; intLoc = intParIO + 10; - + for (;;) { if (s_char1Glob == 'A') { --intLoc; @@ -142,17 +144,17 @@ public static class NDhrystone else { s_intGlob = 100; } - + Proc7(10, s_intGlob, ref m_ptrGlb.IntComp); } - + static void Proc4() { bool boolLoc; boolLoc = s_char1Glob == 'A'; boolLoc |= s_boolGlob; s_char2Glob = 'B'; } - + static void Proc5() { s_char1Glob = 'A'; s_boolGlob = false; @@ -163,12 +165,12 @@ public static class NDhrystone if (!Func3(enumParIn)) { enumParOut = Enumeration.Ident4; } - + switch (enumParIn) { - case Enumeration.Ident1: + case Enumeration.Ident1: enumParOut = Enumeration.Ident1; break; - case Enumeration.Ident2: + case Enumeration.Ident2: if (s_intGlob > 100) { enumParOut = Enumeration.Ident1; } @@ -176,12 +178,12 @@ public static class NDhrystone enumParOut = Enumeration.Ident4; } break; - case Enumeration.Ident3: + case Enumeration.Ident3: enumParOut = Enumeration.Ident2; break; - case Enumeration.Ident4: + case Enumeration.Ident4: break; - case Enumeration.Ident5: + case Enumeration.Ident5: enumParOut = Enumeration.Ident3; break; } @@ -192,7 +194,7 @@ public static class NDhrystone intLoc = intParI1 + 2; intParOut = intParI2 + intLoc; } - + static void Proc8(int[] array1Par, int[][] array2Par, int intParI1, int intParI2) { int intLoc; intLoc = intParI1 + 5; @@ -206,7 +208,7 @@ public static class NDhrystone array2Par[intLoc + 20][intLoc] = array1Par[intLoc]; s_intGlob = 5; } - + static Enumeration Func1(char charPar1, char charPar2) { char charLoc1; char charLoc2; @@ -219,7 +221,7 @@ public static class NDhrystone return (Enumeration.Ident2); } } - + static bool Func2(char[] strParI1, char[] strParI2) { int intLoc; char charLoc = '\0'; @@ -243,18 +245,18 @@ public static class NDhrystone return true; } } - + return false; } } - + static bool Func3(Enumeration enumParIn) { Enumeration enumLoc; enumLoc = enumParIn; if (enumLoc == Enumeration.Ident3) { return true; } - + return false; } @@ -278,9 +280,10 @@ public static class NDhrystone bool result = Bench(); return result; } - + public static int Main() { bool result = TestBase(); return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/Permutate/Permutate.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/Permutate/Permutate.cs index d7457cd..43fc28b 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/Permutate/Permutate.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Permutate/Permutate.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public class Permutate { #if DEBUG @@ -114,3 +116,4 @@ public class Permutate return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/Pi/Pi.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/Pi/Pi.cs index 112ff6d..2fe0918 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/Pi/Pi.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Pi/Pi.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class Pi { @@ -78,9 +80,10 @@ public static class Pi } return result; } - + public static int Main() { bool result = TestBase(); return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/Puzzle/Puzzle.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/Puzzle/Puzzle.cs index 2b1c284..2271e02 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/Puzzle/Puzzle.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Puzzle/Puzzle.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public class Puzzle { #if DEBUG @@ -391,3 +393,4 @@ public class Puzzle return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/QuickSort/QuickSort.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/QuickSort/QuickSort.cs index 191211a..7cdac96 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/QuickSort/QuickSort.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/QuickSort/QuickSort.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class QuickSort { @@ -52,7 +54,7 @@ public static class QuickSort arr[j] = temp; } } - + // need to swap the pivot and a[i](or a[j] as i==j) so // that the pivot will be at its final place in the sorted array @@ -108,9 +110,10 @@ public static class QuickSort } return result; } - + public static int Main() { bool result = TestBase(); return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/TreeInsert/TreeInsert.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/TreeInsert/TreeInsert.cs index 8a24240..2867abc 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/TreeInsert/TreeInsert.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/TreeInsert/TreeInsert.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public class TreeInsert { #if DEBUG @@ -136,3 +138,4 @@ public class TreeInsert return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/TreeSort/TreeSort.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/TreeSort/TreeSort.cs index 68b5c96..e097134 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/TreeSort/TreeSort.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/TreeSort/TreeSort.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class TreeSort { @@ -74,7 +76,7 @@ public static class TreeSort else { Insert(n, t.Left); } - } + } else if (n < t.Val) { if (t.Right == null) { t.Right = new Node(n); @@ -117,7 +119,7 @@ public static class TreeSort bool result = CheckTree(tree); return result; } - + [MethodImpl(MethodImplOptions.NoInlining)] static bool Bench() { int[] sortList = new int[SortElements + 1]; @@ -143,9 +145,10 @@ public static class TreeSort } return result; } - + public static int Main() { bool result = TestBase(); return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/XposMatrix/XposMatrix.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/XposMatrix/XposMatrix.cs index 0bb17b8..de8b486 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchI/XposMatrix/XposMatrix.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchI/XposMatrix/XposMatrix.cs @@ -11,6 +11,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Benchstone.BenchI +{ public static class XposMatrix { public const int ArraySize = 100; @@ -48,11 +50,11 @@ public static class XposMatrix matrix[i][j] = 1; } } - + if (matrix[n][n] != 1) { return false; } - + Inner(matrix, n); if (matrix[n][n] != 1) { @@ -88,3 +90,4 @@ public static class XposMatrix return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csharp.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csharp.cs index e4118b2..c77e802 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csharp.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csharp.cs @@ -2,9 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. /* The Computer Language Benchmarks Game - http://benchmarksgame.alioth.debian.org/ + http://benchmarksgame.alioth.debian.org/ - contributed by Marek Safar + contributed by Marek Safar modified for use with xunit-performance */ @@ -17,6 +17,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace BenchmarksGame +{ public class BinaryTrees { private const int minDepth = 4; @@ -149,3 +151,4 @@ public class BinaryTrees return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta.csharp-2.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta.csharp-2.cs index c58ce0b..92fbceb 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta.csharp-2.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta.csharp-2.cs @@ -18,6 +18,8 @@ using System.Text; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace BenchmarksGame +{ public class Fasta { #if DEBUG @@ -218,3 +220,4 @@ public class Fasta s.Write(s_buf, 0, s_index); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fastaredux/fastaredux.csharp.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fastaredux/fastaredux.csharp.cs index 7128e32..df8999a 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fastaredux/fastaredux.csharp.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fastaredux/fastaredux.csharp.cs @@ -18,6 +18,8 @@ using System.Text; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace BenchmarksGame +{ public static class FastaRedux { #if DEBUG @@ -181,4 +183,5 @@ public static class FastaRedux if (br < BUF_LEN) s.Write(s_buf, 0, BUF_LEN - br); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csharp-3.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csharp-3.cs index 70c8709..2124cf4 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csharp-3.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csharp-3.cs @@ -15,6 +15,8 @@ using System; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace BenchmarksGame +{ public class NBody { public static int Main(String[] args) @@ -153,4 +155,5 @@ internal class NBodySystem return e; } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pi-digits.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pi-digits.cs index 3395e29..7e36f0e 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pi-digits.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pi-digits.cs @@ -6,7 +6,7 @@ * * Port of the C code that uses GMP * Just switched it to use C#'s BigInteger instead - * + * * To compile use csc /o+ /r:System.Numerics.dll * * modified for use with xunit-performance @@ -20,6 +20,8 @@ using System.Text; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace BenchmarksGame +{ public class pidigits { #if DEBUG @@ -111,4 +113,5 @@ public class pidigits } } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm.cs index 9e98486..01eeea07 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm.cs +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm.cs @@ -3,8 +3,8 @@ // See the LICENSE file in the project root for more information. /* The Computer Language Benchmarks Game http://benchmarksgame.alioth.debian.org/ - - contributed by Isaac Gouy + + contributed by Isaac Gouy modified for use with xunit-performance */ @@ -15,6 +15,8 @@ using System; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace BenchmarksGame +{ public class SpectralNorm { #if DEBUG @@ -78,7 +80,7 @@ public class SpectralNorm } // B=AtA A multiplied by A transposed - // v.Bv /(v.v) eigenvalue of v + // v.Bv /(v.v) eigenvalue of v double vBv = 0, vv = 0; for (int i = 0; i < n; i++) { @@ -124,3 +126,4 @@ public class SpectralNorm MultiplyAtv(n, u, AtAv); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsByte.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsByte.cs index 8271c40..3b28f87 100644 --- a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsByte.cs +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsByte.cs @@ -13,6 +13,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Inlining +{ public static class ConstantArgsByte { @@ -928,3 +930,4 @@ public static class ConstantArgsByte return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsChar.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsChar.cs index 0d1f928..0cc4b9c 100644 --- a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsChar.cs +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsChar.cs @@ -13,6 +13,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Inlining +{ public static class ConstantArgsChar { @@ -928,3 +930,4 @@ public static class ConstantArgsChar return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsDouble.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsDouble.cs index 6c95d48..4bd5683 100644 --- a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsDouble.cs +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsDouble.cs @@ -13,6 +13,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Inlining +{ public static class ConstantArgsDouble { @@ -808,3 +810,4 @@ public static class ConstantArgsDouble return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsFloat.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsFloat.cs index bbd65a4..f609a4b 100644 --- a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsFloat.cs +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsFloat.cs @@ -13,6 +13,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Inlining +{ public static class ConstantArgsFloat { @@ -808,3 +810,4 @@ public static class ConstantArgsFloat return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsInt.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsInt.cs index 03d59f9..f54e800 100644 --- a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsInt.cs +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsInt.cs @@ -13,6 +13,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Inlining +{ public static class ConstantArgsInt { @@ -928,3 +930,4 @@ public static class ConstantArgsInt return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsLong.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsLong.cs index f4e45f5..e5679f16 100644 --- a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsLong.cs +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsLong.cs @@ -13,6 +13,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Inlining +{ public static class ConstantArgsLong { @@ -928,3 +930,4 @@ public static class ConstantArgsLong return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsSByte.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsSByte.cs index b329122..0ec29b8 100644 --- a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsSByte.cs +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsSByte.cs @@ -13,6 +13,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Inlining +{ public static class ConstantArgsSByte { @@ -928,3 +930,4 @@ public static class ConstantArgsSByte return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsShort.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsShort.cs index 8718111..f8cf23e 100644 --- a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsShort.cs +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsShort.cs @@ -13,6 +13,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Inlining +{ public static class ConstantArgsShort { @@ -928,3 +930,4 @@ public static class ConstantArgsShort return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsString.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsString.cs index b731908..38a3f7e 100644 --- a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsString.cs +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsString.cs @@ -16,6 +16,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Inlining +{ public static class ConstantArgsString { @@ -328,3 +330,4 @@ public static class ConstantArgsString return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUInt.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUInt.cs index db3316e..e3f6e2a 100644 --- a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUInt.cs +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUInt.cs @@ -13,6 +13,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Inlining +{ public static class ConstantArgsUInt { @@ -888,3 +890,4 @@ public static class ConstantArgsUInt return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsULong.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsULong.cs index 7208707..7585a3e 100644 --- a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsULong.cs +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsULong.cs @@ -13,6 +13,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Inlining +{ public static class ConstantArgsULong { @@ -888,3 +890,4 @@ public static class ConstantArgsULong return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUShort.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUShort.cs index 249e985..c96274e 100644 --- a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUShort.cs +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUShort.cs @@ -13,6 +13,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Inlining +{ public static class ConstantArgsUShort { @@ -928,3 +930,4 @@ public static class ConstantArgsUShort return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/InlineGCStruct.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/InlineGCStruct.cs new file mode 100644 index 0000000..660627c --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/InlineGCStruct.cs @@ -0,0 +1,148 @@ +// 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. + +// In CoreCLR String.Format(ref, ref) is small and readily inlined. +// The inline introduces a System.Parms GC struct local which is +// untracked and must be zero initialized in the prolog. When the +// inlined callsite is in a cold path, the inline hurts performance. +// +// There are two test methods below, one of which calls String.Format +// on a cold path and the other which has similar structure but +// does not call String.Format. Expectation is that they will have +// similar performance. +// +// See https://github.com/dotnet/coreclr/issues/7569 for context. + +using Microsoft.Xunit.Performance; +using System; +using System.Runtime.CompilerServices; +using Xunit; + +[assembly: OptimizeForBenchmarks] +[assembly: MeasureInstructionsRetired] + +namespace Inlining +{ +public class InlineGCStruct +{ +#if DEBUG + public const int Iterations = 1; +#else + public const int Iterations = 2500000; +#endif + + [MethodImpl(MethodImplOptions.NoInlining)] + public static int FastFunctionNotCallingStringFormat(int param) + { + if (param < 0) + { + throw new Exception(String.Format("We do not like the value {0:N0}.", param)); + } + + if (param == int.MaxValue) + { + throw new Exception(String.Format("{0:N0} is maxed out.", param)); + } + + if (param > int.MaxValue / 2) + { + throw new Exception(String.Format("We do not like the value {0:N0} either.", param)); + } + + return param * 2; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static int FastFunctionNotHavingStringFormat(int param) + { + if (param < 0) + { + throw new ArgumentOutOfRangeException("param", "We do not like this value."); + } + + if (param == int.MaxValue) + { + throw new ArgumentOutOfRangeException("param", "Maxed out."); + } + + if (param > int.MaxValue / 2) + { + throw new ArgumentOutOfRangeException("param", "We do not like this value either."); + } + + return param * 2; + } + + [Benchmark] + public static bool WithFormat() + { + int result = 0; + + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + for (int i = 0; i < Iterations; i++) + { + result |= FastFunctionNotCallingStringFormat(11); + } + } + } + + return (result == 22); + } + + [Benchmark] + public static bool WithoutFormat() + { + int result = 0; + + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + for (int i = 0; i < Iterations; i++) + { + result |= FastFunctionNotHavingStringFormat(11); + } + } + } + + return (result == 22); + } + + public static bool WithoutFormatBase() + { + int result = 0; + + for (int i = 0; i < Iterations; i++) + { + result |= FastFunctionNotHavingStringFormat(11); + } + + return (result == 22); + } + + public static bool WithFormatBase() + { + int result = 0; + + for (int i = 0; i < Iterations; i++) + { + result |= FastFunctionNotCallingStringFormat(11); + } + + return (result == 22); + } + + public static int Main() + { + bool withFormat = WithFormatBase(); + bool withoutFormat = WithoutFormatBase(); + + return (withFormat && withoutFormat ? 100 : -1); + } +} +} + diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/InlineGCStruct.csproj b/tests/src/JIT/Performance/CodeQuality/Inlining/InlineGCStruct.csproj new file mode 100644 index 0000000..cb33816 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/InlineGCStruct.csproj @@ -0,0 +1,44 @@ + + + + + Debug + AnyCPU + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + pdbonly + true + + + pdbonly + true + + + + False + + + + + + + + + + $(JitPackagesConfigFileDirectory)benchmark\project.json + $(JitPackagesConfigFileDirectory)benchmark\project.lock.json + + + + + diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/NoThrowInline.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/NoThrowInline.cs index 9b689ce..dc05f44 100644 --- a/tests/src/JIT/Performance/CodeQuality/Inlining/NoThrowInline.cs +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/NoThrowInline.cs @@ -13,6 +13,8 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Inlining +{ public static class NoThrowInline { #if DEBUG @@ -34,7 +36,7 @@ public static class NoThrowInline // // We expect ThrowArgumentNullException to not be inlined into Bench, the throw code is pretty - // large and throws are extremly slow. However, we need to be careful not to degrade the + // large and throws are extremly slow. However, we need to be careful not to degrade the // non-exception path performance by preserving registers across the call. For this the compiler // will have to understand that ThrowArgumentNullException never returns and omit the register // preservation code. @@ -73,3 +75,4 @@ public static class NoThrowInline return (Bench("a", "bc", "def", "ghij") == 10) ? 100 : -1; } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/ConsoleMandel.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/ConsoleMandel.cs index ed7f675..5ab0820 100644 --- a/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/ConsoleMandel.cs +++ b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/ConsoleMandel.cs @@ -11,9 +11,9 @@ using Xunit; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] -namespace ConsoleMandel +namespace SIMD { - public static class Program + public static class ConsoleMandel { private const int Pass = 100; private const int Fail = -1; diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/RayTracerBench.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/RayTracerBench.cs index 064f860..254672b 100644 --- a/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/RayTracerBench.cs +++ b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/RayTracerBench.cs @@ -2,8 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. // -// Based on the Raytracer example from -// Samples for Parallel Programming with the .NET Framework +// Based on the Raytracer example from +// Samples for Parallel Programming with the .NET Framework // https://code.msdn.microsoft.com/windowsdesktop/Samples-for-Parallel-b4b76364 using Microsoft.Xunit.Performance; @@ -16,6 +16,8 @@ using System.Collections.Concurrent; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace SIMD +{ public class RayTracerBench { #if DEBUG @@ -142,3 +144,4 @@ public class RayTracerBench return (result ? 100 : -1); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/SeekUnroll/SeekUnroll.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/SeekUnroll/SeekUnroll.cs new file mode 100644 index 0000000..34c0ab8 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/SIMD/SeekUnroll/SeekUnroll.cs @@ -0,0 +1,159 @@ +// 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 Microsoft.Xunit.Performance; +using System; +using System.Numerics; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Reflection; +using System.Collections.Generic; +using Xunit; + +[assembly: OptimizeForBenchmarks] +[assembly: MeasureInstructionsRetired] + +public static class SeekUnroll +{ + + // The purpose of this micro-benchmark is to measure the effect of unrolling + // on this loop (taken from https://github.com/aspnet/KestrelHttpServer/pull/1138) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static int FindByte(ref Vector byteEquals) + { + var vector64 = Vector.AsVectorInt64(byteEquals); + long longValue = 0; + var i = 0; + for (; i < Vector.Count; i++) + { + longValue = vector64[i]; + if (longValue == 0) continue; + break; + } + + // Flag least significant power of two bit + var powerOfTwoFlag = (ulong)(longValue ^ (longValue - 1)); + // Shift all powers of two into the high byte and extract + var foundByteIndex = (int)((powerOfTwoFlag * _xorPowerOfTwoToHighByte) >> 57); + // Single LEA instruction with jitted const (using function result) + return i * 8 + foundByteIndex; + } + + // Magic constant used in FindByte + const ulong _xorPowerOfTwoToHighByte = (0x07ul | + 0x06ul << 8 | + 0x05ul << 16 | + 0x04ul << 24 | + 0x03ul << 32 | + 0x02ul << 40 | + 0x01ul << 48) + 1; + + // Inner loop to repeatedly call FindByte + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static void InnerLoop(ref int foundIndex, ref Vector vector) + { + for (int i = 0; i < InnerIterations; i++) + { + foundIndex = FindByte(ref vector); + } + } + + // Iteration counts for inner loop set to have each call take 1 or + // 2 seconds or so in release, finish quickly in debug. +#if DEBUG + const int InnerIterations = 1; +#else + const int InnerIterations = 1000000000; +#endif + + // Function to meaure InnerLoop using the xunit-perf benchmark measurement facilities + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static void XunitBenchmarkLoop(ref int foundIndex, ref Vector vector) + { + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + InnerLoop(ref foundIndex, ref vector); + } + } + } + + // Function to measure InnerLoop with manual use of a stopwatch timer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static void ManualTimerLoop(ref int foundIndex, ref Vector vector) + { + for (int iteration = 0; iteration < ManualLoopTimes.Length; ++iteration) + { + var timer = System.Diagnostics.Stopwatch.StartNew(); + InnerLoop(ref foundIndex, ref vector); + timer.Stop(); + ManualLoopTimes[iteration] = timer.ElapsedMilliseconds; + } + } + static long[] ManualLoopTimes; + + // Function that tests one input, dispatching to either the xunit-perf + // loop or the manual timer loop + static bool Test(int index, bool isXunitBenchmark) + { + if (index >= Vector.Count) + { + // FindByte assumes index is in range + index = 0; + } + var bytes = new Byte[Vector.Count]; + bytes[index] = 255; + Vector vector = new Vector(bytes); + + int foundIndex = -1; + + if (isXunitBenchmark) + { + XunitBenchmarkLoop(ref foundIndex, ref vector); + } + else + { + ManualTimerLoop(ref foundIndex, ref vector); + } + + Assert.Equal(index, foundIndex); + return (index == foundIndex); + } + + // Set of indices to pass to Test(int, bool) + static int[] IndicesToTest = new int[] { 1, 3, 11, 19, 27 }; + + // Entrypoint for xunit-perf to call the benchmark + [Benchmark] + [MemberData(nameof(ArrayedBoxedIndicesToTest))] + public static bool Test(object boxedIndex) + { + return Test((int)boxedIndex, true); + } + + // IndicesToTest wrapped up in arrays of boxes since that's + // what xunit-perf needs + public static IEnumerable ArrayedBoxedIndicesToTest = + IndicesToTest.Select((int index) => new object[] { index }); + + + // Main method entrypoint runs the manual timer loop + public static int Main() + { + int failures = 0; + foreach(int index in IndicesToTest) + { + ManualLoopTimes = new long[10]; + bool passed = Test(index, false); + if (!passed) + { + ++failures; + } + Console.WriteLine("Index {0}, times (ms) [{1}]", index, String.Join(", ", ManualLoopTimes)); + } + + return 100 + failures; + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/SeekUnroll/SeekUnroll.csproj b/tests/src/JIT/Performance/CodeQuality/SIMD/SeekUnroll/SeekUnroll.csproj new file mode 100644 index 0000000..53cfe42 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/SIMD/SeekUnroll/SeekUnroll.csproj @@ -0,0 +1,43 @@ + + + + + Debug + AnyCPU + 2.0 + {9AE6E18D-B3F9-4216-9809-125824387175} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + + + pdbonly + true + + + pdbonly + true + + + + False + + + + + + + + + + $(JitPackagesConfigFileDirectory)benchmark\project.json + $(JitPackagesConfigFileDirectory)benchmark\project.lock.json + + + + + diff --git a/tests/src/JIT/Performance/CodeQuality/Serialization/Deserialize.cs b/tests/src/JIT/Performance/CodeQuality/Serialization/Deserialize.cs index b0ed00d..56fc266 100644 --- a/tests/src/JIT/Performance/CodeQuality/Serialization/Deserialize.cs +++ b/tests/src/JIT/Performance/CodeQuality/Serialization/Deserialize.cs @@ -15,6 +15,8 @@ using Microsoft.Xunit.Performance; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Serialization +{ public class JsonBenchmarks { @@ -26,7 +28,7 @@ public class JsonBenchmarks public const int JsonNetIterations = 90000; #endif - const string DataContractXml = @"33SqMtx101.399.899.6100.42015-01-01T00:00:00-08:00"; + const string DataContractXml = @"33SqMtx101.399.899.6100.42015-01-01T00:00:00-08:00"; const string DataContractJson = @"{""Id"":33,""Name"":""SqMtx"",""Results"":[101.3,99.8,99.6,100.4],""WhenRun"":""\/Date(1420099200000-0800)\/""}"; @@ -83,7 +85,7 @@ public class JsonBenchmarks } [Benchmark] - private void DeserializeDataContract() + private void DeserializeDataContract() { foreach (var iteration in Benchmark.Iterations) { using (iteration.StartMeasurement()) { @@ -199,3 +201,4 @@ public class JsonBenchmarks return result ? 100 : -1; } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/Serialization/Serialize.cs b/tests/src/JIT/Performance/CodeQuality/Serialization/Serialize.cs index 905cf56..39ab587 100644 --- a/tests/src/JIT/Performance/CodeQuality/Serialization/Serialize.cs +++ b/tests/src/JIT/Performance/CodeQuality/Serialization/Serialize.cs @@ -14,6 +14,8 @@ using Microsoft.Xunit.Performance; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] +namespace Serialization +{ public class JsonBenchmarks { @@ -72,7 +74,7 @@ public class JsonBenchmarks } [Benchmark] - private void SerializeDataContract() + private void SerializeDataContract() { foreach (var iteration in Benchmark.Iterations) { using (iteration.StartMeasurement()) { @@ -186,3 +188,4 @@ public class JsonBenchmarks return result ? 100 : -1; } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/V8/Crypto/Crypto.cs b/tests/src/JIT/Performance/CodeQuality/V8/Crypto/Crypto.cs index 23eab8d..620e012 100644 --- a/tests/src/JIT/Performance/CodeQuality/V8/Crypto/Crypto.cs +++ b/tests/src/JIT/Performance/CodeQuality/V8/Crypto/Crypto.cs @@ -46,7 +46,7 @@ using System.Globalization; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] -namespace Crypto +namespace V8.Crypto { public class Support { diff --git a/tests/src/JIT/Performance/CodeQuality/V8/DeltaBlue/DeltaBlue.cs b/tests/src/JIT/Performance/CodeQuality/V8/DeltaBlue/DeltaBlue.cs index ee14b8b..27f7718 100644 --- a/tests/src/JIT/Performance/CodeQuality/V8/DeltaBlue/DeltaBlue.cs +++ b/tests/src/JIT/Performance/CodeQuality/V8/DeltaBlue/DeltaBlue.cs @@ -24,13 +24,15 @@ using System.Collections; [assembly: OptimizeForBenchmarks] [assembly: MeasureInstructionsRetired] -/* +/* Strengths are used to measure the relative importance of constraints. New strengths may be inserted in the strength hierarchy without disrupting current constraints. Strengths cannot be created outside this class, so pointer comparison can be used for value comparison. */ +namespace V8 +{ internal class Strength { private int _strengthValue; @@ -1066,3 +1068,4 @@ public class deltablue throw new Exception(s); } } +} diff --git a/tests/src/JIT/Performance/CodeQuality/V8/Richards/Richards.cs b/tests/src/JIT/Performance/CodeQuality/V8/Richards/Richards.cs index 6d26593..5095d22 100644 --- a/tests/src/JIT/Performance/CodeQuality/V8/Richards/Richards.cs +++ b/tests/src/JIT/Performance/CodeQuality/V8/Richards/Richards.cs @@ -20,7 +20,7 @@ using System.Collections.Generic; // using System.Diagnostics; // using System.Text.RegularExpressions; -namespace Richards +namespace V8.Richards { /// /// Support is used for a place to generate any 'miscellaneous' methods generated as part @@ -501,7 +501,7 @@ namespace Richards public #if !INTF_FOR_TASK - override + override #endif TaskControlBlock run(Packet packet) { @@ -521,7 +521,7 @@ namespace Richards public #if !INTF_FOR_TASK - override + override #endif String toString() { @@ -548,7 +548,7 @@ namespace Richards public #if !INTF_FOR_TASK - override + override #endif TaskControlBlock run(Packet packet) { @@ -568,7 +568,7 @@ namespace Richards public #if !INTF_FOR_TASK - override + override #endif String toString() { @@ -598,7 +598,7 @@ namespace Richards public #if !INTF_FOR_TASK - override + override #endif TaskControlBlock run(Packet packet) { @@ -630,7 +630,7 @@ namespace Richards public #if !INTF_FOR_TASK - override + override #endif String toString() { @@ -658,7 +658,7 @@ namespace Richards public #if !INTF_FOR_TASK - override + override #endif TaskControlBlock run(Packet packet) { @@ -700,7 +700,7 @@ namespace Richards public #if !INTF_FOR_TASK - override + override #endif String toString() { diff --git a/tests/src/JIT/Performance/RunBenchmarks/RunBenchmarks.cmd b/tests/src/JIT/Performance/RunBenchmarks/RunBenchmarks.cmd index e85e226..e7b8917 100644 --- a/tests/src/JIT/Performance/RunBenchmarks/RunBenchmarks.cmd +++ b/tests/src/JIT/Performance/RunBenchmarks/RunBenchmarks.cmd @@ -9,7 +9,7 @@ @rem of the enlistment(repo). It also requires that CoreCLR has been built, @rem and that all CoreCLR tests have been built. @rem -@rem The preformance harness "RunBencchmarks.exe" is built as a test case +@rem The preformance harness "RunBenchmarks.exe" is built as a test case @rem as are all the performance tests it runs. @rem @rem For the ByteMark tests, it must copy the command scripts to the diff --git a/tests/src/JIT/Performance/RunBenchmarks/RunBenchmarks.sh b/tests/src/JIT/Performance/RunBenchmarks/RunBenchmarks.sh new file mode 100755 index 0000000..ee70916 --- /dev/null +++ b/tests/src/JIT/Performance/RunBenchmarks/RunBenchmarks.sh @@ -0,0 +1,53 @@ +# *************************************************************************** +# RunBenchmarks.sh +# +# This is a sample script for how to run benchmarks on Unix-like system. +# +# It requires the user to set CORECLR_ROOT to the root directory +# of the enlistment(repo). It also requires that CoreCLR has been built, +# and that all CoreCLR tests have been built. +# +# The preformance harness "RunBenchmarks.exe" is built as a test case +# as are all the performance tests it runs. +# +# For the ByteMark tests, it must copy the command scripts to the +# binary directory for the tests. +# +# By default, the performance harness is run on top of CoreCLR. There +# is a commented out section that can be used to run on top of DesktopCLR. +# +# A standard benchmark run is done with one warmup run, and five iterations +# of the benchmark. +# +# *************************************************************************** + +ARCH=${1:-x64} +BUILD=${2:-Release} + +CORERUN=${CORERUN:-corerun} + +# *** set this appropriately for enlistment you are running benchmarks in + +if [ -z "$CORECLR_ROOT" ]; then + echo "You must set CORECLR_ROOT to be the root of your coreclr repo (e.g. /git/repos/coreclr)" + exit 1 +fi + +# *** Currently we can build test cases only on Windows, so "Windows_NT" is hard-coded in the variables. +BENCHMARK_ROOT_DIR="$CORECLR_ROOT/bin/tests/Windows_NT.$ARCH.$BUILD/JIT/Performance/CodeQuality" +BENCHMARK_SRC_DIR="$CORECLR_ROOT/tests/src/JIT/Performance/RunBenchmarks" +BENCHMARK_HOST="$CORERUN $CORECLR_ROOT/bin/tests/Windows_NT.$ARCH.$BUILD/JIT/Performance/RunBenchmarks/RunBenchmarks/RunBenchmarks.exe" +BENCHMARK_RUNNER="-runner $CORERUN" + +# *** need to copy command files for Bytemark +mkdir -p ${BENCHMARK_ROOT_DIR}/Bytemark/Bytemark +cp -rf $CORECLR_ROOT/tests/src/JIT/Performance/CodeQuality/Bytemark/commands ${BENCHMARK_ROOT_DIR}/Bytemark/Bytemark/commands + +BENCHMARK_CONTROLS="-run -v -w -n 5" +BENCHMARK_SET="-f $BENCHMARK_SRC_DIR/coreclr_benchmarks.xml -notags broken" +BENCHMARK_OUTPUT="-csvfile $BENCHMARK_SRC_DIR/coreclr_benchmarks.csv" +BENCHMARK_SWITCHES="$BENCHMARK_CONTROLS -r $BENCHMARK_ROOT_DIR" + +echo "$BENCHMARK_HOST $BENCHMARK_RUNNER $BENCHMARK_SET $BENCHMARK_OUTPUT $BENCHMARK_SWITCHES" +$BENCHMARK_HOST $BENCHMARK_RUNNER $BENCHMARK_SET $BENCHMARK_OUTPUT $BENCHMARK_SWITCHES + diff --git a/tests/src/JIT/Regression/CLR-x86-JIT/V2.0-RTM/b475589/b475589.il b/tests/src/JIT/Regression/CLR-x86-JIT/V2.0-RTM/b475589/b475589.il deleted file mode 100644 index dce3d69..0000000 --- a/tests/src/JIT/Regression/CLR-x86-JIT/V2.0-RTM/b475589/b475589.il +++ /dev/null @@ -1,71 +0,0 @@ -// 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. - -.assembly extern System.Console -{ - .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) - .ver 4:0:0:0 -} - -.assembly extern mscorlib { auto } -.assembly b475598 {} -.module b475589.exe - -.class Program -{ - .method static void Nasty() - { - .maxstack 2 - - call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::PrepareConstrainedRegions() - br start_try - - start_catch: - ldstr "Cathed!" - call void [System.Console]System.Console::WriteLine(string) - leave.s end - end_catch: - - start_try: - newobj instance void [mscorlib]System.Exception::.ctor() - throw - end_try: - - end: - ret - - .try start_try to end_try catch [mscorlib]System.Exception handler start_catch to end_catch - } - .method static int32 Main(string[] args) - { - .maxstack 2 - .entrypoint - - - start_try: - - call void Program::Nasty() - leave.s end_failure - - end_try: - start_catch: - - leave.s end_success - end_catch: - - end_success: - ldstr "Test SUCCESS" - call void [System.Console]System.Console::WriteLine(string) - ldc.i4 100 - ret - - end_failure: - ldstr "Test FAILURE" - call void [System.Console]System.Console::WriteLine(string) - ldc.i4 -1 - ret - - .try start_try to end_try catch [mscorlib]System.NotSupportedException handler start_catch to end_catch - } -} \ No newline at end of file diff --git a/tests/src/JIT/Regression/CLR-x86-JIT/V2.0-RTM/b475589/b475589.ilproj b/tests/src/JIT/Regression/CLR-x86-JIT/V2.0-RTM/b475589/b475589.ilproj deleted file mode 100644 index 14ed64f..0000000 --- a/tests/src/JIT/Regression/CLR-x86-JIT/V2.0-RTM/b475589/b475589.ilproj +++ /dev/null @@ -1,40 +0,0 @@ - - - - - Debug - AnyCPU - $(MSBuildProjectName) - 2.0 - {95DFC527-4DC1-495E-97D7-E94EE1F7140D} - Exe - Properties - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages - ..\..\ - 7a9bfb7d - - - - - - - - - False - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_142976/DevDiv_142976.cs b/tests/src/JIT/Regression/JitBlue/DevDiv_142976/DevDiv_142976.cs new file mode 100644 index 0000000..7b01517 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_142976/DevDiv_142976.cs @@ -0,0 +1,56 @@ +// 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.Runtime.CompilerServices; + +// This test case is meant to test an optimization in morph that +// transforms helper call JIT_Stelem_Ref(a, null, i) to a[i] = null, +// which further gets transformed into an array address and bounds +// check nodes with references to the array local and the index +// local. It is expected while doing such a transform, array +// local and index local are appropriately ref counted and Value +// number is updated post-global-morph and jit compilation +// won't run into any asserts. +class DevDiv_142976 +{ + [MethodImpl(MethodImplOptions.NoInlining)] + public static String Foo() + { + return null; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static void Bar() + { + String[] args = new String[10]; + if (args != null) + { + throw new Exception(); + } + + String s = Foo(); + if (s == null) + { + // This will result in JIT_Stelem_Ref(args, null, 0) call + // which gets re-morphed into args[0] = null. + args[0] = s; + } + } + + public static int Main() + { + try + { + Bar(); + } + catch (Exception) + { + } + + Console.WriteLine("Pass"); + return 100; + } +} \ No newline at end of file diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_142976/DevDiv_142976.csproj b/tests/src/JIT/Regression/JitBlue/DevDiv_142976/DevDiv_142976.csproj new file mode 100644 index 0000000..0c1a10e --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_142976/DevDiv_142976.csproj @@ -0,0 +1,46 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + 7a9bfb7d + + + + + + + + + False + + + + + True + + + + + + + + + $(JitPackagesConfigFileDirectory)minimal\project.json + $(JitPackagesConfigFileDirectory)minimal\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_255294/DevDiv_255294.cs b/tests/src/JIT/Regression/JitBlue/DevDiv_255294/DevDiv_255294.cs new file mode 100644 index 0000000..05f1d90 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_255294/DevDiv_255294.cs @@ -0,0 +1,62374 @@ +// 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.Runtime.CompilerServices; + +public class Test +{ + static bool f; + + public static int Main() + { + f = true; + Test test = new Test(); + return test.HugeMethod(); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public int HugeMethod() + { + int i = 0; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + if (f) i++; + + return i - 62248; + } +} diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_255294/DevDiv_255294.csproj b/tests/src/JIT/Regression/JitBlue/DevDiv_255294/DevDiv_255294.csproj new file mode 100644 index 0000000..9027bb5 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_255294/DevDiv_255294.csproj @@ -0,0 +1,46 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + 7a9bfb7d + + + + + + + + + False + + + + + True + + + + + + + + + $(JitPackagesConfigFileDirectory)minimal\project.json + $(JitPackagesConfigFileDirectory)minimal\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_278365/DevDiv_278365.cs b/tests/src/JIT/Regression/JitBlue/DevDiv_278365/DevDiv_278365.cs new file mode 100644 index 0000000..631175a --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_278365/DevDiv_278365.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. +// See the LICENSE file in the project root for more information. + + +using System; +using System.Runtime.CompilerServices; + +// This test is a reduced repro case for DevDiv VSO bug 278365. +// The failure mode is that the RyuJIT/x86 backend changed call to ROUND intrinsic +// with double return type to ROUND intrinsic with int return type, that is not supported. + +internal class Program +{ + [MethodImpl(MethodImplOptions.NoInlining)] + public static int Bar() + { + int sum = 0; + for (int i = 0; i < 100; ++i) + { + int v = (int)Math.Round(4.4 + i); + sum += v; + } + sum -= 4 * 100; + if (sum != 100 * 99 / 2) + { + return 0; + } + else + { + return 100; + } + } + + private static int Main(string[] args) + { + try + { + if (Bar() != 100) + return 0; + } + catch (Exception) + { + } + + Console.WriteLine("Pass"); + return 100; + } +} diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_278365/DevDiv_278365.csproj b/tests/src/JIT/Regression/JitBlue/DevDiv_278365/DevDiv_278365.csproj new file mode 100644 index 0000000..0abcfd8 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_278365/DevDiv_278365.csproj @@ -0,0 +1,46 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + 7a9bfb7d + + + + + + + + + False + + + + + True + + + + + + + + + $(JitPackagesConfigFileDirectory)minimal\project.json + $(JitPackagesConfigFileDirectory)minimal\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_278369/DevDiv_278369.il b/tests/src/JIT/Regression/JitBlue/DevDiv_278369/DevDiv_278369.il new file mode 100644 index 0000000..cf07778 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_278369/DevDiv_278369.il @@ -0,0 +1,58 @@ +// 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. + +// This test checks that value numbering does not incorrectly propagate the value number for an operand to its +// consuming operator unless the type of the operand and the operator agree. +// +// In particular, in the body of method N, the optimizer will fold the two `ceq` conditions together using a logical +// or of type int32. Value numbering will then determine that one operand to the logical or is a constant `0` (namely, +// the result of `ldloc.0` and attempt to propagate the value number of the logical or's other operand to the logical +// or itself. This should not succeed, as the type of the logical or is int32 and the type of its non-zero operand is +// `ref`. + +.assembly extern mscorlib {} + +.assembly r {} + +.class private auto ansi beforefieldinit C extends [mscorlib]System.Object +{ + .method private hidebysig static int32 N(object o) cil managed noinlining + { + .locals (int32) + + ldc.i4.0 + stloc.0 + ldarg.0 + isinst C + ldnull + ceq + brfalse.s label + ldloc.0 + ldc.i4.0 + ceq + brfalse.s label + ldc.i4.s 0 + ret + +label: + ldc.i4 100 + ret + } + + .method private hidebysig static int32 Main(string[] args) cil managed + { + .entrypoint + + newobj instance void C::.ctor() + call int32 C::N(object) + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ldarg.0 + call instance void [mscorlib]System.Object::.ctor() + ret + } +} diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_278369/DevDiv_278369.ilproj b/tests/src/JIT/Regression/JitBlue/DevDiv_278369/DevDiv_278369.ilproj new file mode 100644 index 0000000..deebeec --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_278369/DevDiv_278369.ilproj @@ -0,0 +1,41 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT .0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + None + True + + + + + + + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_278371/DevDiv_278371.il b/tests/src/JIT/Regression/JitBlue/DevDiv_278371/DevDiv_278371.il new file mode 100644 index 0000000..447392e --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_278371/DevDiv_278371.il @@ -0,0 +1,88 @@ +// 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. + +// Test for a bug involving an initblk with a non-constant size, +// which uses rep movs on x86 (x64 uses a helper call). + +.assembly extern legacy library mscorlib {} +.assembly extern System.Console +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) + .ver 4:0:0:0 +} + +.assembly DevDiv_278371 {} + +.class public sequential ansi sealed beforefieldinit S + extends [mscorlib]System.ValueType +{ + .field public uint32 val +} // end of class S + +.class private auto ansi beforefieldinit Program + extends [mscorlib]System.Object +{ + .method public hidebysig static void Init(valuetype S& s, + int32 size) cil managed noinlining + { + nop + ldarg.0 + ldc.i4 0xaa + ldarg.1 + initblk + ret + } // end of method Program::Init + + .method private hidebysig static int32 + Main() cil managed + { + .entrypoint + .locals init (valuetype S V_0, + bool V_1, + int32 V_2) + ldloca.s V_0 + initobj S + ldloca.s V_0 + ldc.i4 4 + call void Program::Init(valuetype S&, int32) + ldloc.0 + ldfld uint32 S::val + ldc.i4 0xaaaaaaaa + ceq + ldc.i4.0 + ceq + stloc.1 + ldloc.1 + brfalse.s L1 + + ldstr "Fail" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldc.i4.m1 + stloc.2 + br.s L2 + + L1: ldstr "Pass" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldc.i4.s 100 + stloc.2 + + L2: ldloc.2 + ret + } // end of method Program::Main + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + ldarg.0 + call instance void [mscorlib]System.Object::.ctor() + nop + ret + } // end of method Program::.ctor + +} // end of class Program + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_278371/DevDiv_278371.ilproj b/tests/src/JIT/Regression/JitBlue/DevDiv_278371/DevDiv_278371.ilproj new file mode 100644 index 0000000..11cfb62 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_278371/DevDiv_278371.ilproj @@ -0,0 +1,41 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + None + True + + + + + + + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_278372/DevDiv_278372.il b/tests/src/JIT/Regression/JitBlue/DevDiv_278372/DevDiv_278372.il new file mode 100644 index 0000000..1081877 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_278372/DevDiv_278372.il @@ -0,0 +1,156 @@ +// 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. + +// This test is a reduced repro case for DevDiv VSO bug 278372. +// The failure mode is that the RyuJIT/x86 backend was not correctly +// handling the case of a variable involving a variable V such that: +// - V is lvMustInit (therefore it must be undefined on some path) +// - V lives in multiple registers, but never on the stack +// - there is at least one other variable that is also lvMustInit, but that +// has a stack location. +// +// In this case, genFnProlog was attempting to zero-init V on the stack. +// +// It was difficult to construct a repro; this repro requires that the test +// be run with COMPlus_JitStressRegs=0x200 (which changes the location of +// variables at block boundaries). + + +// Metadata version: v4.0.30319 +.assembly extern System.Runtime +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: + .ver 4:1:0:0 +} +.assembly extern System.Console +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: + .ver 4:0:0:0 +} +.assembly DevDiv_278372 +{ +} + +// =============== CLASS MEMBERS DECLARATION =================== + +.class private auto ansi beforefieldinit DevDiv_278372 + extends [System.Runtime]System.Object +{ + .method public hidebysig static bool check(int32& dummy) cil managed noinlining + { + ldc.i4.1 + ret + } // end of method DevDiv_278372::check + + .method public hidebysig static int32 getX() cil managed noinlining + { + ldc.i4.s 25 + ret + } // end of method DevDiv_278372::getX + + .method public hidebysig static int32 getY() cil managed noinlining + { + ldc.i4.5 + ret + } // end of method DevDiv_278372::getY + + .method public hidebysig static int32 Test(int32 x, + int32 y, + int32 x2, + int32 y2, + int32 x3, + int32 y3) cil managed noinlining + { + .maxstack 2 + .locals init ([0] int32 z, + [1] int32 returnVal, + [2] int32 dummy, + [3] int32 z2) + + // Initialize returnVal to 100 + ldc.i4.s 100 + stloc.1 + + // Here we pass the address of "dummy" to ensure that we have a must-init on-stack variable. + ldloca.s dummy + call bool DevDiv_278372::check(int32&) + brfalse.s L1 + + // Here we are conditionally defining "z", so that it will be must-init + ldarg.0 + ldarg.1 + rem + stloc.0 + L1: ldloc.0 + brfalse.s L2 + + ldc.i4.m1 + stloc.1 + L2: ldarg.2 + ldarg.3 + rem + stloc.3 + ldarg.0 + ldarg.1 + add + stloc.0 + ldloc.0 + ldc.i4.s 30 + beq.s L3 + + ldc.i4.m1 + stloc.1 + L3: ldloc.3 + brfalse.s L4 + + ldc.i4.m1 + stloc.1 + L4: ldloc.1 + ldc.i4.s 100 + bne.un.s L5 + + ldstr "Pass" + call void [System.Console]System.Console::WriteLine(string) + br.s L6 + + L5: ldstr "Fail" + call void [System.Console]System.Console::WriteLine(string) + L6: ldloc.1 + ret + } // end of method DevDiv_278372::Test + + .method public hidebysig static int32 Main() cil managed + { + .entrypoint + // Code size 16 (0x10) + .maxstack 8 + ldc.i4.s 25 + ldc.i4.5 + ldc.i4.s 25 + ldc.i4.5 + ldc.i4.s 25 + ldc.i4.5 + call int32 DevDiv_278372::Test(int32, + int32, + int32, + int32, + int32, + int32) + ret + } // end of method DevDiv_278372::Main + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + ldarg.0 + call instance void [System.Runtime]System.Object::.ctor() + ret + } // end of method DevDiv_278372::.ctor + +} // end of class DevDiv_278372 + + +// ============================================================= diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_278372/DevDiv_278372.ilproj b/tests/src/JIT/Regression/JitBlue/DevDiv_278372/DevDiv_278372.ilproj new file mode 100644 index 0000000..f3da12d --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_278372/DevDiv_278372.ilproj @@ -0,0 +1,51 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + None + True + + + + + + + + + + + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_278375/DevDiv_278375.cs b/tests/src/JIT/Regression/JitBlue/DevDiv_278375/DevDiv_278375.cs new file mode 100644 index 0000000..ecd7e7f --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_278375/DevDiv_278375.cs @@ -0,0 +1,131 @@ +// 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.Runtime.CompilerServices; + +struct MyStruct +{ + // Struct containing 4 fields, 3 of which are longs that will be decomposed. + // The bug was that this resulted in 7 input registers to the GT_FIELD_LIST + // parameter, which can't be accommodated by the register allocator. + + public MyStruct(long l1, long l2, long l3, int i) + { + f1 = l1; + f2 = l2; + f3 = l3; + f4 = new int[i]; + f4[0] = i; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static MyStruct newMyStruct(long l1, long l2, long l3, int i) + { + return new MyStruct(l1, l2, l3, i); + } + + public long f1; + public long f2; + public long f3; + public int[] f4; +} + +struct MyStruct2 +{ + // This is a variation that includes a double field, to ensure that a mix of + // field types are supported. + public MyStruct2(long l1, long l2, double d, int i) + { + f1 = l1; + f2 = l2; + f3 = d; + f4 = new int[i]; + f4[0] = i; + } + + public long f1; + public long f2; + public double f3; + public int[] f4; +} + +struct MyStruct3 +{ + // And finally one that includes longs and a double, but no ref. + public MyStruct3(long l1, long l2, double d, int i) + { + f1 = l1; + f2 = l2; + f3 = d; + f4 = i; + } + + public long f1; + public long f2; + public double f3; + public int f4; +} + +class Program +{ + + static int Pass = 100; + static int Fail = -1; + + [MethodImpl(MethodImplOptions.NoInlining)] + static int AddFields(MyStruct s) + { + return (int)(s.f1 + s.f2 + s.f3 + s.f4[0]); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int AddFields2(MyStruct2 s) + { + return (int)(s.f1 + s.f2 + (int)s.f3 + s.f4[0]); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int AddFields3(MyStruct3 s) + { + return (int)(s.f1 + s.f2 + (int)s.f3 + s.f4); + } + + static int Main(string[] args) + { + int returnVal = Pass; + MyStruct s = new MyStruct(1, 2, 3, 4); + int sum = AddFields(s); + if (sum != 10) + { + Console.WriteLine("Failed first call"); + returnVal = Fail; + } + s = MyStruct.newMyStruct(1, 2, 3, 4); + sum = AddFields(s); + if (sum != 10) + { + Console.WriteLine("Failed second call"); + returnVal = Fail; + } + MyStruct2 s2 = new MyStruct2(1, 2, 3.0, 4); + sum = AddFields2(s2); + if (sum != 10) + { + Console.WriteLine("Failed third call"); + returnVal = Fail; + } + MyStruct3 s3 = new MyStruct3(1, 2, 3.0, 4); + sum = AddFields3(s3); + if (sum != 10) + { + Console.WriteLine("Failed fourth call"); + returnVal = Fail; + } + if (returnVal == Pass) + { + Console.WriteLine("Pass"); + } + return returnVal; + } +} \ No newline at end of file diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_278375/DevDiv_278375.csproj b/tests/src/JIT/Regression/JitBlue/DevDiv_278375/DevDiv_278375.csproj new file mode 100644 index 0000000..9477984 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_278375/DevDiv_278375.csproj @@ -0,0 +1,46 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + 7a9bfb7d + + + + + + + + + False + + + + + True + + + + + + + + + $(JitPackagesConfigFileDirectory)minimal\project.json + $(JitPackagesConfigFileDirectory)minimal\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_278376/DevDiv_278376.cs b/tests/src/JIT/Regression/JitBlue/DevDiv_278376/DevDiv_278376.cs new file mode 100644 index 0000000..63e3d29 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_278376/DevDiv_278376.cs @@ -0,0 +1,36 @@ +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// NOTE: the bug for this test was an assertion in RyuJIT/x86 when generating code for a double-returning call that +// was spilled by the RA and subsequently used. The call in question is the call to `C.GetDouble` in `C.Test`. +// To ensure that its return value is spilled, `C.GetDouble` is implemented as a P/Invoke method: the return +// value ends up spilled because there is a call to `TrapReturningThreads` between the call and the use of the +// return value by the cast. Because the bug is a simple assert, there is no need for the problematic code to +// actually run, so the implementation of `GetDouble` does not need to actually exist. + +sealed class C +{ + [DllImport("nonexistent.dll")] + extern static double GetDouble(); + + [MethodImpl(MethodImplOptions.NoInlining)] + static void UseDouble(double d) + { + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int Test(bool condition) + { + if (condition) + { + UseDouble((double)GetDouble()); + } + + return 100; + } + + static int Main(string[] args) + { + return Test(false); + } +} diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_278376/DevDiv_278376.csproj b/tests/src/JIT/Regression/JitBlue/DevDiv_278376/DevDiv_278376.csproj new file mode 100644 index 0000000..90327b2 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_278376/DevDiv_278376.csproj @@ -0,0 +1,46 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + 7a9bfb7d + + + + + + + + + False + + + + + True + + + + + + + + + $(JitPackagesConfigFileDirectory)minimal\project.json + $(JitPackagesConfigFileDirectory)minimal\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_278523/DevDiv_278523.il b/tests/src/JIT/Regression/JitBlue/DevDiv_278523/DevDiv_278523.il new file mode 100644 index 0000000..9c9ba49 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_278523/DevDiv_278523.il @@ -0,0 +1,113 @@ +// 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. + +.assembly extern mscorlib {} +.assembly a {} +.module a.exe + +// This test originally triggered an assert when computing the value number for a block assignment. In particular, the +// VN framework expected any block assignments to a tracked lclVar to have a destination address of the form +// `(addr (lclVar))` or `(addr (lclFld))`. The check that it was using to determine whether or not a block assignment +// targets a lclVar also admitted addresses formed by some combination of adds of constants to these patterns (e.g. +// `(add (const 4) (add (addr lclVar) (const 4)))`. The bits of IL that trigger the assert are called out in the method +// bodies below. They differ for 32- and 64-bit targets because on 64-bit targets, the importer will insert an +// int->long conversion when adding a constant int to any long. Due to the cast, the resulting IR is not considered to +// be an add of a constant and a lclVar address. In order to repro the bug on a 64-bit target, the input IL must +// directly produce a long constant. + +.class private sequential ansi sealed beforefieldinit S extends [mscorlib]System.ValueType +{ + .field public uint8 m_fld + .field public uint8 m_fld1 + .field public uint8 m_fld2 + .field public uint8 m_fld3 + .field public uint8 m_fld4 + .field public uint8 m_fld5 + .field public uint8 m_fld6 +} + +.class private sequential ansi sealed beforefieldinit T extends [mscorlib]System.ValueType +{ + .field public int32 m_int + .field public valuetype S m_fld +} + +.class private abstract auto ansi sealed beforefieldinit C extends [mscorlib]System.Object +{ + .method private static int32 Test32Bit(int32 i) noinlining + { + .locals init (valuetype S V_0, valuetype T V_1) + + ldloca.s V_0 + ldarg.0 + conv.u1 + stfld uint8 S::m_fld6 + + // This sequence of IL repros the issue. + ldloca.s V_1 + ldc.i4.4 + add + ldloc.0 + stobj S + + ldloca.s V_1 + ldfld valuetype S T::m_fld + ldfld uint8 S::m_fld6 + conv.i4 + ret + } + + .method private static int32 Test64Bit(int32 i) noinlining + { + .locals init (valuetype S V_0, valuetype T V_1) + + ldloca.s V_0 + ldarg.0 + conv.u1 + stfld uint8 S::m_fld6 + + // This sequence of IL repros the issue. Note that the `ldc.i8` is necessary (rather than an `ldc.i4` that is + // implicitly converted to a long byt the `add`). + ldloca.s V_1 + ldc.i8 4 + add + ldloc.0 + stobj S + + ldloca.s V_1 + ldfld valuetype S T::m_fld + ldfld uint8 S::m_fld6 + conv.i4 + ret + } + + .method private static int32 Main() + { + .entrypoint + .locals init (int32 V_0) + + ldc.i4 100 + dup + + sizeof [mscorlib]System.IntPtr + ldc.i4 8 + beq.s _64bit + + call int32 C::Test32Bit(int32) + bne.un.s fail + br.s success + +_64bit: + call int32 C::Test64Bit(int32) + bne.un.s fail + +success: + ldc.i4 100 + ret + +fail: + ldc.i4 101 + ret + } +} diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_278523/DevDiv_278523.ilproj b/tests/src/JIT/Regression/JitBlue/DevDiv_278523/DevDiv_278523.ilproj new file mode 100644 index 0000000..d4cfe45 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_278523/DevDiv_278523.ilproj @@ -0,0 +1,41 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT .0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + None + True + + + + + + + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_278526/DevDiv_278526.cs b/tests/src/JIT/Regression/JitBlue/DevDiv_278526/DevDiv_278526.cs new file mode 100644 index 0000000..e3c494b --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_278526/DevDiv_278526.cs @@ -0,0 +1,47 @@ +// 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. + +// This test was originally a repro for an assertion regarding incorrect value number of the tree in cse. +// The repro requires that the tree and its child are considered by cse and child is binary sub (a - b). +// Cse calls morph of the parent tree and morphs child to (a + (-b)) and sets the clean VN state to the child. +// It causes assert when cse processes the child with the clean vn state. + + +using System; + + +class Program +{ + public sealed class Variables + { + public static byte[] decryptedApplicationData + { + get; + set; + } + } + + private static bool VerifyMacvalueSSlV2(string sourceIP) + { + if (sourceIP == "skip") + return false; + + byte[] array3 = new byte[0]; + + // Assert happens on the next two statements. + int l = Variables.decryptedApplicationData.Length - array3.Length - 16; + byte[] array2 = new byte[l]; + + if (array3[0] != array2[0]) + return false; + return true; + } + + public static int Main(string[] args) + { + string s = "skip"; // Test checks commpilation process. + VerifyMacvalueSSlV2(s); + return 100; + } +} diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_278526/DevDiv_278526.csproj b/tests/src/JIT/Regression/JitBlue/DevDiv_278526/DevDiv_278526.csproj new file mode 100644 index 0000000..b1bd003 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_278526/DevDiv_278526.csproj @@ -0,0 +1,46 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + 7a9bfb7d + + + + + + + + + False + + + + + True + + + + + + + + + $(JitPackagesConfigFileDirectory)minimal\project.json + $(JitPackagesConfigFileDirectory)minimal\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_279396/DevDiv_279396.il b/tests/src/JIT/Regression/JitBlue/DevDiv_279396/DevDiv_279396.il new file mode 100644 index 0000000..70e0202 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_279396/DevDiv_279396.il @@ -0,0 +1,39 @@ +// 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. + +.assembly extern mscorlib {} +.assembly DevDiv_279396 {} +.module DevDiv_279396.exe + +// This test originally triggered an assertion in the emitter that ensured that no lclVar or lclFld access exceeded the +// bounds of its containing method's frame. The problematic access was created during morphing by folding +// `(ind long (addr int (lclVar int V0)))` into `(lclFld long V0 0)`. This corresponds to the body of `C::Test` below. + +.class private abstract auto ansi sealed beforefieldinit C extends [mscorlib]System.Object +{ + .method private static int64 Test(int32 i) noinlining + { + ldarga.s i + ldind.i8 + ret + } + + .method private static int32 Main() + { + .entrypoint + + ldc.i4 100 + dup + call int64 C::Test(int32) + conv.i4 + bne.un.s fail + + ldc.i4 100 + ret + +fail: + ldc.i4 101 + ret + } +} diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_279396/DevDiv_279396.ilproj b/tests/src/JIT/Regression/JitBlue/DevDiv_279396/DevDiv_279396.ilproj new file mode 100644 index 0000000..2a9f58b --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_279396/DevDiv_279396.ilproj @@ -0,0 +1,41 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT .0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + None + True + + + + + + + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_279829/DevDiv_279829.il b/tests/src/JIT/Regression/JitBlue/DevDiv_279829/DevDiv_279829.il new file mode 100644 index 0000000..96c22d2 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_279829/DevDiv_279829.il @@ -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. +// See the LICENSE file in the project root for more information. + +.assembly extern mscorlib {} + +.assembly DevDiv_279829.exe {} + +.class public Test +{ + .method private static int32 JmpTarget(int64) + { + .maxstack 1 + ldarg.0 + conv.i4 + ret + } + + .method private static int32 Jmp(int64) + { + .maxstack 1 + jmp int32 Test::JmpTarget(int64) + ldc.i4 0 + ret + } + + .method private static int32 Main(class [mscorlib]System.String[]) + { + .entrypoint + .maxstack 1 + + ldc.i8 100 + call int32 Test::Jmp(int64) + ret + } +} diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_279829/DevDiv_279829.ilproj b/tests/src/JIT/Regression/JitBlue/DevDiv_279829/DevDiv_279829.ilproj new file mode 100644 index 0000000..d4804c8 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_279829/DevDiv_279829.ilproj @@ -0,0 +1,46 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + true + 7a9bfb7d + + + + + + + + + False + + + + true + None + + + + + + + + + $(JitPackagesConfigFileDirectory)minimal\project.json + $(JitPackagesConfigFileDirectory)minimal\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_280120/DevDiv_280120.cs b/tests/src/JIT/Regression/JitBlue/DevDiv_280120/DevDiv_280120.cs new file mode 100644 index 0000000..39888b1 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_280120/DevDiv_280120.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. +// See the LICENSE file in the project root for more information. + +// This test was originally a repro for an assertion regarding incorrect lclVar ref counts due to a bug in the +// decomposition of a long-typed st.lclFld node. The repro requires that a dead store of this type survives until +// decomposition. We must therefore avoid running liveness before decomposition as part of this test, which requires +// skipping SSA (and dependent optimizations). This pass is disabled in the project file by setting JitDoSsa to 0 +// before running the test. + +struct S +{ + long m_fld; + int m_a, m_b, m_c, m_d; + + static int Main(string[] args) + { + S s; + s.m_fld = (long)args.Length; + return 100; + } +} diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_280120/DevDiv_280120.csproj b/tests/src/JIT/Regression/JitBlue/DevDiv_280120/DevDiv_280120.csproj new file mode 100644 index 0000000..bcbdc0f --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_280120/DevDiv_280120.csproj @@ -0,0 +1,56 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + 7a9bfb7d + + + + + + + + + False + + + + + True + + + + + + + + + + + + + $(JitPackagesConfigFileDirectory)minimal\project.json + $(JitPackagesConfigFileDirectory)minimal\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_280123/DevDiv_280123.cs b/tests/src/JIT/Regression/JitBlue/DevDiv_280123/DevDiv_280123.cs new file mode 100644 index 0000000..01e55ed --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_280123/DevDiv_280123.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. +// See the LICENSE file in the project root for more information. + +using System.Runtime.CompilerServices; + +// This test ensures that the value number store (and its users) behave properly in the event that VN data is requested +// for trees without value numbers. The original repro was a rather large method with a significant amount of dead code +// due to the pattern exhibited in C.N: an entry block that was not transformed from a conditional return to an +// unconditional return followed by dead code that must be kept due to the presence of EH. Value numbering does not +// assign value numbers to the dead code, but assertion prop still runs over the dead code and attempts to use VN info, +// which resulted in a number of asserts. + +static class C +{ + [MethodImpl(MethodImplOptions.NoInlining)] + static int N(ref int i) + { + bool b = true; + if (b) + { + return 100; + } + + try + { + b = i != 1; + } + finally + { + b = i != 0; + } + + return b ? 0 : 1; + } + + static int Main(string[] args) + { + int i = args.Length; + return N(ref i); + } +} diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_280123/DevDiv_280123.csproj b/tests/src/JIT/Regression/JitBlue/DevDiv_280123/DevDiv_280123.csproj new file mode 100644 index 0000000..a2ec975 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_280123/DevDiv_280123.csproj @@ -0,0 +1,46 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + 7a9bfb7d + + + + + + + + + False + + + + + True + + + + + + + + + $(JitPackagesConfigFileDirectory)minimal\project.json + $(JitPackagesConfigFileDirectory)minimal\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_280127/DevDiv_280127.cs b/tests/src/JIT/Regression/JitBlue/DevDiv_280127/DevDiv_280127.cs new file mode 100644 index 0000000..3f8270f --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_280127/DevDiv_280127.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.CompilerServices; + +// The original repro for this test was an assertion after code generation that the actual maximum depth of the stack +// was less than or identical to the estimated depth of the stack as calculated during morph. The calculation was +// incorrect when a math intrinsic was used as an argument to a function with on-stack parameters (e.g. the call to +// `M` on line 18). + +static class C +{ + struct S + { + int a, b, c, d; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int N(S s, float d) + { + return 100; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int M(double d) + { + N(new S(), (float)(Math.Atan2(d, 2.0) * 180 / Math.PI)); + return 100; + } + + static int Main() + { + return M(2.0); + } +} diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_280127/DevDiv_280127.csproj b/tests/src/JIT/Regression/JitBlue/DevDiv_280127/DevDiv_280127.csproj new file mode 100644 index 0000000..ec9776d --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_280127/DevDiv_280127.csproj @@ -0,0 +1,46 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + 7a9bfb7d + + + + + + + + + False + + + + + True + + + + + + + + + $(JitPackagesConfigFileDirectory)minimal\project.json + $(JitPackagesConfigFileDirectory)minimal\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_283795/DevDiv_283795.cs b/tests/src/JIT/Regression/JitBlue/DevDiv_283795/DevDiv_283795.cs new file mode 100644 index 0000000..55da5ba --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_283795/DevDiv_283795.cs @@ -0,0 +1,55 @@ +// 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.Runtime.CompilerServices; + +class C +{ + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static int[] M() + { + return null; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static bool Test(int i, int j, bool execute) + { + if (execute) + { + return M()[checked(i + j)] == 0; + } + + return true; + } + + static int Main() + { + // The original repro of the bug associated with this test involved an assert after re-morphing a tree modified + // by CSE: the original tree contained both a CSE def and a CSE use, and re-morphing eliminated the use, causing + // CSE to assert when attempting to replace the use with a reference to the CSE lclVar. This call to `Test` is + // intended to trigger that assert. + bool test1 = Test(0, 0, false); + + // The associated code in morph involves folding `(x + null)` to `x`. During the investigation of the original + // issue, it was found that the folding code also failed to check for side effects in `x` resulting in SBCG if + // side effects were in fact present in `x`. This call to `Test` is intended to ensure that the fold is not + // performed in the face of a tree that contains side-effects: in particular, the overflowing add in the + // called method should occur before any other exception. + bool test2 = false; + try + { + Test(int.MaxValue, int.MaxValue, true); + } + catch (System.OverflowException) + { + test2 = true; + } + catch (System.Exception e) + { + System.Console.WriteLine(e); + } + + return test1 && test2 ? 100 : 101; + } +} diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_283795/DevDiv_283795.csproj b/tests/src/JIT/Regression/JitBlue/DevDiv_283795/DevDiv_283795.csproj new file mode 100644 index 0000000..71bd55f --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_283795/DevDiv_283795.csproj @@ -0,0 +1,46 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + 7a9bfb7d + + + + + + + + + False + + + + + True + + + + + + + + + $(JitPackagesConfigFileDirectory)minimal\project.json + $(JitPackagesConfigFileDirectory)minimal\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_284785/DevDiv_284785.cs b/tests/src/JIT/Regression/JitBlue/DevDiv_284785/DevDiv_284785.cs new file mode 100644 index 0000000..944993f --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_284785/DevDiv_284785.cs @@ -0,0 +1,39 @@ +// 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. + +// This test exercises expression folding in the place of overflowing operations. The original failure was SBCG due to +// an incorrect application of the same: in the program below, the checked int -> ulong cast on line 24 was folded to a +// long -> ulong cast with an incorrect constant value that fit in a ulong, resulting in no overflow exception being +// thrown. + +using System; + +static class C +{ + static int Main() + { + int i = -4; + ulong l = 0; + + int rv = 0; + try + { + checked + { + l = (ulong)i; + } + } + catch (OverflowException) + { + rv = 100; + } + catch (Exception) + { + i = 0; + l = 0; + } + + return rv; + } +} diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_284785/DevDiv_284785.csproj b/tests/src/JIT/Regression/JitBlue/DevDiv_284785/DevDiv_284785.csproj new file mode 100644 index 0000000..d27b911 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_284785/DevDiv_284785.csproj @@ -0,0 +1,46 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + 7a9bfb7d + + + + + + + + + False + + + + + True + + + + + + + + + $(JitPackagesConfigFileDirectory)minimal\project.json + $(JitPackagesConfigFileDirectory)minimal\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_288222/DevDiv_288222.cs b/tests/src/JIT/Regression/JitBlue/DevDiv_288222/DevDiv_288222.cs new file mode 100644 index 0000000..e24c797 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_288222/DevDiv_288222.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. +// See the LICENSE file in the project root for more information. + + +using System; +using System.Runtime.CompilerServices; +using System.Numerics; + +// This test is a repro case for DevDiv VSO bug 288222. +// The failure mode is that the size was not being set for a "this" pointer +// with SIMD type. + +internal class Program +{ + // Declare a delegate type for calling the Vector2.CopyTo method. + public delegate void CopyToDelegate(float[] array, int start); + + [MethodImpl(MethodImplOptions.NoInlining)] + public static void MyCopyTo(CopyToDelegate doCopy, float[] array, int start) + { + doCopy(array, start); + } + + private static int Main(string[] args) + { + try + { + float x = 1.0F; + float y = 2.0F; + Vector2 v = new Vector2(x, y); + float[] array = new float[4]; + MyCopyTo(new CopyToDelegate(v.CopyTo), array, 2); + + if ((array[2] != x) || (array[3] != y)) + { + Console.WriteLine("Failed with wrong values"); + return -1; + } + } + catch (Exception e) + { + Console.WriteLine("Failed with exception: " + e.Message); + return -1; + } + + Console.WriteLine("Pass"); + return 100; + } +} diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_288222/DevDiv_288222.csproj b/tests/src/JIT/Regression/JitBlue/DevDiv_288222/DevDiv_288222.csproj new file mode 100644 index 0000000..0aa2d11 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_288222/DevDiv_288222.csproj @@ -0,0 +1,46 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + 7a9bfb7d + + + + + + + + + False + + + + + True + + + + + + + + + $(JitPackagesConfigFileDirectory)threading+thread\project.json + $(JitPackagesConfigFileDirectory)threading+thread\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_359734/DevDiv_359734.il b/tests/src/JIT/Regression/JitBlue/DevDiv_359734/DevDiv_359734.il new file mode 100644 index 0000000..43f55b6 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_359734/DevDiv_359734.il @@ -0,0 +1,118 @@ +// 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. + +// The original bug for this test was an assertion after the following sequence of events: +// - Assertion propagation constant propagated away the ldlocs, or, and shl in the IL at label "expr" +// - After constant propagation, the resulting expression--`(mod tmp0 cns)`--was remorphed, which +// replaced the modulus with `(sub tmp0 (mul (div tmp0 cns) cns))` and unset the "exception" flag. +// Critically, this transformation added a new use of `tmp0` without updating the ref count for `tmp0`. +// - After morphing, the resulting expression was both unsused and side-effect-free, and was removed +// - While removing the lclVar ref count for `tmp0` fell to `0` +// - Later, liveness found a reference to `tmp0` despite the `0` lclVar count and asserted. +// +// The fix was to bump lclVar ref counts after remorphing but before attempting to remove the expression. + +.assembly extern mscorlib{} +.assembly ILGEN_MODULE{} +.class ILGEN_CLASS +{ + .method static char ILGEN_METHOD(bool, char, int16, int32) + { + .maxstack 65535 + .locals init (int32, int16, int64, int16, unsigned int8, float32, unsigned int8) + + ldc.i8 0x80BBE1AB + ldc.i8 0x866D9EF3 + or + ldarg 0x1 + shl + ldc.i8 0xC09C2177 + sub.ovf.un + conv.ovf.u8.un + ldc.i8 0x82B1C678 + or + ldc.r8 -0.000000 + ldloc 0x5 + ckfinite + ldloc 0x5 + neg + neg + add + add + ldc.r8 0.000000 + clt + stloc.s 0x4 + ldc.i8 0xACB4FC40 + + expr: + ldloc.s 0x3 + ldloc.s 0x0 + or + shl + rem + + conv.ovf.i8 + ldloc.s 0x4 + conv.ovf.u + neg + brtrue IL_0089 + ldarg 0x0 + conv.ovf.i8 + conv.i8 + ldc.i8 0x2ECADED8 + ldloc 0x2 + shr + clt + pop + ldloc.s 0x1 + conv.ovf.u1.un + conv.ovf.u.un + starg 0x0 + + IL_0089: + ldarg.s 0x3 + conv.u8 + bgt IL_0094 + ldloc.s 0x5 + pop + + IL_0094: + ldc.r8 0.000000 + neg + conv.i + ldloc 0x5 + ckfinite + ldc.i8 0x8BD98F2C + conv.r4 + ckfinite + clt + pop + neg + ret + } + + .method static int32 Main() + { + .entrypoint + + .try + { + ldc.i4 0 + dup + dup + dup + call char ILGEN_CLASS::ILGEN_METHOD(bool, char, int16, int32) + pop + leave.s done + } + catch [mscorlib]System.Exception + { + leave.s done + } + + done: + ldc.i4 100 + ret + } +} diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_359734/DevDiv_359734.ilproj b/tests/src/JIT/Regression/JitBlue/DevDiv_359734/DevDiv_359734.ilproj new file mode 100644 index 0000000..b13550f --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_359734/DevDiv_359734.ilproj @@ -0,0 +1,41 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT .0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + None + True + + + + + + + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_359736/DevDiv_359736.cs b/tests/src/JIT/Regression/JitBlue/DevDiv_359736/DevDiv_359736.cs new file mode 100644 index 0000000..56f7b90 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_359736/DevDiv_359736.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. +// See the LICENSE file in the project root for more information. +// + +using System; +using System.Runtime.CompilerServices; + +// This testcase reproduces a bug where the tree re-sequencing was not correct for +// fgMorphModToSubMulDiv(), resulting in an assert in LSRA. + +static class Test +{ + static byte GetVal() + { + return 0; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int DoMod(SByte arg) + { + byte val = GetVal(); + return arg % val; + } + + static int Main() + { + int returnVal = -1; + try + { + DoMod(4); + Console.WriteLine("FAILED: No exception thrown"); + returnVal = -1; + } + catch (System.DivideByZeroException) + { + Console.WriteLine("PASS"); + returnVal = 100; + } + return returnVal; + } +} diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_359736/DevDiv_359736_d.csproj b/tests/src/JIT/Regression/JitBlue/DevDiv_359736/DevDiv_359736_d.csproj new file mode 100644 index 0000000..93bc9fd --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_359736/DevDiv_359736_d.csproj @@ -0,0 +1,45 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {23E1CE24-CCFB-4163-A861-D48A76295E8F} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + Full + False + + + + + + + + + $(JitPackagesConfigFileDirectory)threading+thread\project.json + $(JitPackagesConfigFileDirectory)threading+thread\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_359736/DevDiv_359736_do.csproj b/tests/src/JIT/Regression/JitBlue/DevDiv_359736/DevDiv_359736_do.csproj new file mode 100644 index 0000000..07c2edf --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_359736/DevDiv_359736_do.csproj @@ -0,0 +1,45 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {C8DB97C3-1D53-4192-AE65-74A66EFE0841} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + Full + True + + + + + + + + + $(JitPackagesConfigFileDirectory)threading+thread\project.json + $(JitPackagesConfigFileDirectory)threading+thread\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_359736/DevDiv_359736_r.csproj b/tests/src/JIT/Regression/JitBlue/DevDiv_359736/DevDiv_359736_r.csproj new file mode 100644 index 0000000..fcc7a16 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_359736/DevDiv_359736_r.csproj @@ -0,0 +1,45 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {C7C7808C-AFDF-4267-B295-C9D0E9EF5642} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + None + False + + + + + + + + + $(JitPackagesConfigFileDirectory)threading+thread\project.json + $(JitPackagesConfigFileDirectory)threading+thread\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_359736/DevDiv_359736_ro.csproj b/tests/src/JIT/Regression/JitBlue/DevDiv_359736/DevDiv_359736_ro.csproj new file mode 100644 index 0000000..c8a1bef --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/DevDiv_359736/DevDiv_359736_ro.csproj @@ -0,0 +1,45 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {30EFB3A3-FDAB-43C1-91E5-0496C0B9C689} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + None + True + + + + + + + + + $(JitPackagesConfigFileDirectory)threading+thread\project.json + $(JitPackagesConfigFileDirectory)threading+thread\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_7906/GitHub_7906.cs b/tests/src/JIT/Regression/JitBlue/GitHub_7906/GitHub_7906.cs new file mode 100644 index 0000000..47f16d7 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_7906/GitHub_7906.cs @@ -0,0 +1,47 @@ +// 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. + +// Regression test for insufficient guard on inference of initial values +// of induction variables. +using System.Numerics; + +namespace N +{ + public static class C + { + public static int Main(string[] args) + { + int x = 0; + + // When bottom-testing sees this loop, it (questionably for performance, + // but correctly) copies only the first part of the disjunctive loop condition + // so we get + // + // B1: i = Count // initialization + // B2: if (i < Count) goto B6 // duplicated loop condition (note the "zero trip" case goes to the 2nd loop condition disjunct) + // B3: x += i // loop body + // B4: ++i // increment + // B5: if (i < Count) goto B3 // first disjunct of loop condition + // B6: if (i < 20) goto B3 // second disjunct of loop condition + // B7: return x - 84 // post-loop + // + // At which point B3..B6 is an irreducible loop, but B3..B5 is a natural loop. + // This is a regression test for a bug where optRecordLoop would incorrectly + // identify B1 as the initial value of loop B3..B5 -- this is incorrect because + // the edge from B6 to B3 enters the loop with different values of i. + // + // The testcase is intentionally structured so that loop unrolling will try + // to unroll loop B3..B5 and generate incorrect code due to the incorrect + // initial value. + for (int i = Vector.Count; i < Vector.Count || i < 20; ++i) + { + x += i; + } + + // After running the loop above, the value of x should be (Count + 19) * (20 - Count) / 2. + // Return 100 + x - (expected x) so the test will return 100 on success. + return 100 + x - ((Vector.Count + 19) * (20 - Vector.Count) / 2); + } + } +} diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_7906/GitHub_7906.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_7906/GitHub_7906.csproj new file mode 100644 index 0000000..1dbbc3b --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_7906/GitHub_7906.csproj @@ -0,0 +1,44 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {76E69AA0-8C5A-4F76-8561-B8089FFA8D79} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + 7a9bfb7d + + + + + + + + + False + + + + + True + + + + + + + + + $(JitPackagesConfigFileDirectory)benchmark\project.json + $(JitPackagesConfigFileDirectory)benchmark\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_7907/GitHub_7907.cs b/tests/src/JIT/Regression/JitBlue/GitHub_7907/GitHub_7907.cs new file mode 100644 index 0000000..32ea54c --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_7907/GitHub_7907.cs @@ -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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.CompilerServices; + +#pragma warning disable 472 + +public class Bug7907 +{ + int _position = 10; + + [MethodImpl(MethodImplOptions.NoInlining)] + public static int G(int z, ref int r) + { + r -= z; + return 1; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public int F0(int count) + { + int initialCount = count; + + _position += G(_position, ref count); + + if (initialCount == count) + { + count--; + } + + return initialCount - count; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public int F1(int count) + { + // " != null" is known to be true - just to remove control flow + // since that by itself may force spilling and mask the bug + count -= (_position += G(_position, ref count)) != null ? count : 1; + + return count; + } + + public static int Main(string[] args) + { + int result0 = new Bug7907().F0(10); + int result1 = new Bug7907().F1(10); + Console.WriteLine("R0={0} R1={1}", result0, result1); + return (result0 == 10 && result1 == 10 ? 100 : -1); + } +} diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_7907/GitHub_7907.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_7907/GitHub_7907.csproj new file mode 100644 index 0000000..5c86d0f --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_7907/GitHub_7907.csproj @@ -0,0 +1,46 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + 7a9bfb7d + + + + + + + + + False + + + + pdbonly + True + + + + + + + + + $(JitPackagesConfigFileDirectory)minimal\project.json + $(JitPackagesConfigFileDirectory)minimal\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_8133/GitHub_8133.il b/tests/src/JIT/Regression/JitBlue/GitHub_8133/GitHub_8133.il new file mode 100644 index 0000000..be6720d --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_8133/GitHub_8133.il @@ -0,0 +1,112 @@ +// 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. + +.assembly extern mscorlib {} +.assembly a {} + +// The original repro for this test was SBCG due to incorrect computation of value numbers for the ref-typed locals +// in Test::Main(). Despite the fact that each local refers to a different array element, all of the locals were +// assigned the same value number. + +.class Test extends [mscorlib]System.Object +{ + .method static void Equal(int32 i, int32 j) cil noinlining + { + ldarg.0 + ldarg.1 + bne.un.s fail + ret + +fail: + newobj instance void [mscorlib]System.Exception::.ctor() + throw + } + + .method static !!0& Add(!!0& addr, int32 offset) + { + ldarg.0 + ldarg.1 + sizeof !!0 + conv.i + mul + add + ret + } + + .method public hidebysig static int32 RefAdd() cil managed + { + .entrypoint + + .locals init ( + [0] int32[] a, + [1] int32& r1, + [2] int32& r2, + [3] int32& r3) + + ldc.i4.4 + newarr [mscorlib]System.Int32 + dup + ldtoken field valuetype ''/'__StaticArrayInitTypeSize=16' ''::'6E9F9131664668938673AFE814BBDE210C6AE91F' + call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle) + stloc.0 + + ldloc.0 + ldc.i4.0 + ldelema [mscorlib]System.Int32 + ldc.i4.1 + call !!0& Test::Add(!!0&, int32) + stloc.1 + ldc.i4 0x234 + ldloc.1 + ldind.i4 + call void Test::Equal(int32, int32) + + ldloc.1 + ldc.i4.2 + call !!0& Test::Add(!!0&, int32) + stloc.2 + ldc.i4 0x456 + ldloc.2 + ldind.i4 + call void Test::Equal(int32, int32) + + ldloc.2 + ldc.i4.s -3 + call !!0& Test::Add(!!0&, int32) + stloc.3 + ldc.i4 0x123 + ldloc.3 + ldind.i4 + call void Test::Equal(int32, int32) + + ldc.i4 100 + ret + } +} + +.class private auto ansi sealed '' + extends [mscorlib]System.Object +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .class explicit ansi sealed nested private '__StaticArrayInitTypeSize=16' + extends [mscorlib]System.ValueType + { + .pack 1 + .size 16 + } + + .field static assembly initonly int32 '4C55E5E5FC2235CC8C201E69A345F7FAB3FB46FA' at I_000054DC + .field static assembly initonly int64 '67423EBFA8454F19AC6F4686D6C0DC731A3DDD6B' at I_000054E4 + .field static assembly initonly valuetype ''/'__StaticArrayInitTypeSize=16' '6E9F9131664668938673AFE814BBDE210C6AE91F' at I_000054EC + .field static assembly initonly int32 '9BCE73D0C8B9ECA4F24154F3BD3B8AA473B1C3A9' at I_000054FC +} + +.data cil I_000054DC = bytearray ( + 42 42 42 42) // BBBB +.data cil I_000054E4 = bytearray ( + 00 01 02 03 04 05 06 07) +.data cil I_000054EC = bytearray ( + 23 01 00 00 34 02 00 00 45 03 00 00 56 04 00 00) // #...4...E...V... +.data cil I_000054FC = bytearray ( + 12 34 56 78) // .4Vx diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_8133/GitHub_8133.ilproj b/tests/src/JIT/Regression/JitBlue/GitHub_8133/GitHub_8133.ilproj new file mode 100644 index 0000000..3d8d22e --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_8133/GitHub_8133.ilproj @@ -0,0 +1,41 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT .0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + None + True + + + + + + + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_8170/GitHub_8170.cs b/tests/src/JIT/Regression/JitBlue/GitHub_8170/GitHub_8170.cs new file mode 100644 index 0000000..d3fe8d9 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_8170/GitHub_8170.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. +// See the LICENSE file in the project root for more information. + +using System.Runtime.CompilerServices; + +// This test checks for proper behavior w.r.t. overflow for expressions of the form `val % constant` where `val` is an +// unsigned long and `constant` is a 32- or 64-bit integer constant in the range [2,0x3fffffff]. These expressions +// should never produce an overflow exception. + +static class C +{ + [MethodImpl(MethodImplOptions.NoInlining)] + static uint M(ulong l) + { + return (uint)(l % 10000000); + } + + static int Main() + { + return M(ulong.MaxValue) == 9551615 ? 100 : 101; + } +} diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_8170/GitHub_8170.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_8170/GitHub_8170.csproj new file mode 100644 index 0000000..81aa729 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_8170/GitHub_8170.csproj @@ -0,0 +1,46 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + 7a9bfb7d + + + + + + + + + False + + + + None + True + + + + + + + + + $(JitPackagesConfigFileDirectory)minimal\project.json + $(JitPackagesConfigFileDirectory)minimal\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_8220/GitHub_8220.cs b/tests/src/JIT/Regression/JitBlue/GitHub_8220/GitHub_8220.cs new file mode 100644 index 0000000..f38d5ba --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_8220/GitHub_8220.cs @@ -0,0 +1,170 @@ +// 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. + +// Regression test for Vector3 intrinsics using upper non-zero'd bits from +// a byref return. + +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Numerics; + +namespace Test +{ + + public class Program + { + static Random random; + + static Program() + { + random = new Random(1); + } + + [MethodImpl( MethodImplOptions.NoInlining )] + public static double StackScribble() + { + double d1 = random.NextDouble(); + double d2 = random.NextDouble(); + double d3 = random.NextDouble(); + double d4 = random.NextDouble(); + double d5 = random.NextDouble(); + double d6 = random.NextDouble(); + double d7 = random.NextDouble(); + double d8 = random.NextDouble(); + double d9 = random.NextDouble(); + double d10 = random.NextDouble(); + double d11 = random.NextDouble(); + double d12 = random.NextDouble(); + double d13 = random.NextDouble(); + double d14 = random.NextDouble(); + double d15 = random.NextDouble(); + double d16 = random.NextDouble(); + double d17 = random.NextDouble(); + double d18 = random.NextDouble(); + double d19 = random.NextDouble(); + double d20 = random.NextDouble(); + double d21 = random.NextDouble(); + double d22 = random.NextDouble(); + double d23 = random.NextDouble(); + double d24 = random.NextDouble(); + double d25 = random.NextDouble(); + double d26 = random.NextDouble(); + double d27 = random.NextDouble(); + double d28 = random.NextDouble(); + double d29 = random.NextDouble(); + double d30 = random.NextDouble(); + double d31 = random.NextDouble(); + double d32 = random.NextDouble(); + double d33 = random.NextDouble(); + double d34 = random.NextDouble(); + double d35 = random.NextDouble(); + double d36 = random.NextDouble(); + double d37 = random.NextDouble(); + double d38 = random.NextDouble(); + double d39 = random.NextDouble(); + double d40 = random.NextDouble(); + return d1 + d2 + d3 + d4 + d5 + d6 + d7 + d8 + d9 + d10 + + d11 + d12 + d13 + d14 + d15 + d16 + d17 + d18 + d19 + d20 + + d21 + d22 + d23 + d24 + d25 + d26 + d27 + d28 + d29 + d20 + + d31 + d32 + d33 + d34 + d35 + d36 + d37 + d38 + d39 + d40; + } + + [MethodImpl( MethodImplOptions.NoInlining )] + public static Vector3 getTestValue(float f1, float f2, float f3) + { + return new Vector3(f1, f2, f3); + } + + public static bool Check(float value, float expectedValue) + { + // These may differ in the last place. + float expectedValueLow; + float expectedValueHigh; + + unsafe + { + UInt32 expectedValueUInt = *(UInt32*)&expectedValue; + UInt32 expectedValueUIntLow = (expectedValueUInt == 0) ? 0 : expectedValueUInt - 1; + UInt32 expectedValueUIntHigh = (expectedValueUInt == 0xffffffff) ? 0xffffffff : expectedValueUInt + 1; + expectedValueLow = *(float*)&expectedValueUIntLow; + expectedValueHigh = *(float*)&expectedValueUIntHigh; + } + float errorMargin = Math.Abs(expectedValueHigh - expectedValueLow); + if (Math.Abs(value - expectedValue) > errorMargin) + { + return false; + } + return true; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static int testDotProduct(Vector3 v0) + { + float f1 = (float)random.NextDouble(); + float f2 = (float)random.NextDouble(); + float f3 = (float)random.NextDouble(); + + Vector3 v1 = Vector3.Normalize(getTestValue(f1, f2, f3) - v0); + Vector3 v2 = new Vector3(f1, f2, f3) - v0; + v2 = v2 / v2.Length(); + + if (!Check(v1.X, v2.X) || !Check(v1.Y, v2.Y) || !Check(v1.Z, v2.Z)) + { + Console.WriteLine("Vectors do not match " + v1 + v2); + return -1; + } + + return 100; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static int testEquals(Vector3 v0) + { + float f1 = (float)random.NextDouble(); + float f2 = (float)random.NextDouble(); + float f3 = (float)random.NextDouble(); + + Vector3 v1 = new Vector3(f1, f2, f3) - v0; + bool result = v1.Equals(getTestValue(f1, f2, f3) - v0); + + if ((result == false) || !v1.Equals(getTestValue(f1, f2, f3) - v0)) + { + Console.WriteLine("Equals returns wrong value " + v1); + return -1; + } + + return 100; + } + + public static int Main() + { + int returnValue = 100; + Console.WriteLine("Testing Dot Product"); + for (int i = 0; i < 10; i++) + { + StackScribble(); + if (testDotProduct(new Vector3(1.0F, 2.0F, 3.0F)) != 100) + { + Console.WriteLine("Failed on iteration " + i); + returnValue = -1; + break; + } + } + Console.WriteLine("Testing Equals"); + for (int i = 0; i < 10; i++) + { + StackScribble(); + if (testEquals(new Vector3(1.0F, 2.0F, 3.0F)) != 100) + { + Console.WriteLine("Failed on iteration " + i); + returnValue = -1; + break; + } + } + return returnValue; + } + } +} + diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_8220/GitHub_8220.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_8220/GitHub_8220.csproj new file mode 100644 index 0000000..939d010 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_8220/GitHub_8220.csproj @@ -0,0 +1,45 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {76E69AA0-8C5A-4F76-8561-B8089FFA8D79} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + 7a9bfb7d + + + + + + + + + False + + + + + True + True + + + + + + + + + $(JitPackagesConfigFileDirectory)benchmark\project.json + $(JitPackagesConfigFileDirectory)benchmark\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_8231/GitHub_8231.cs b/tests/src/JIT/Regression/JitBlue/GitHub_8231/GitHub_8231.cs new file mode 100644 index 0000000..4d2ec76 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_8231/GitHub_8231.cs @@ -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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; + +namespace N +{ + public static class C + { + // This is a regression test for a failure in loop unrolling when + // the unrolled loop contains a switch statement. + [MethodImpl(MethodImplOptions.NoInlining)] + static int Test() + { + int s = 0; + + // Loop to some Vector.Count to trigger unrolling. + for (int i = 0; i < Vector.Count; i++) + { + // Loop contains switch; the bug was that the clones + // of the switch were all sharing its BBswtDesc instead + // of getting their own, so updates to their jump targets + // were incorrectly shared. + switch (i) + { + case 1: s += 4; break; + case 2: s += 2; break; + case 3: s += i; break; + } + } + + return s; + } + + public static int Main(string[] args) + { + int result = Test(); + + // Expected result is a function of Vector.Count. + int expected; + switch(Vector.Count) + { + case 1: + expected = 4; + break; + case 2: + expected = 6; + break; + default: + expected = 9; + break; + } + + // Return 100 on success (result == expected), other + // values on failure. + return 100 + result - expected; + } + } +} diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_8231/GitHub_8231.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_8231/GitHub_8231.csproj new file mode 100644 index 0000000..844638f --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_8231/GitHub_8231.csproj @@ -0,0 +1,39 @@ + + + + + Debug + AnyCPU + 2.0 + {2649FAFE-07BF-4F93-8120-BA9A69285ABB} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + + + + + + + + False + + + + + + + + + + $(JitPackagesConfigFileDirectory)benchmark\project.json + $(JitPackagesConfigFileDirectory)benchmark\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_8460/GitHub_8460.cs b/tests/src/JIT/Regression/JitBlue/GitHub_8460/GitHub_8460.cs new file mode 100644 index 0000000..f5c9aa2 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_8460/GitHub_8460.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +namespace bug +{ + class Program + { + static int Pass = 100; + static int Fail = -1; + + // This test is meant to check that in case of + // GT_EQ/NE(shift, 0), JIT doesn't optimize out + // 'test' instruction incorrectly, because shift + // operations on xarch don't modify flags if the + // shift count is zero. + static int Main(string[] args) + { + // Absolute bits + int bitCount = 0; + while ((0 != (100 >> bitCount)) && (31 > bitCount)) + { + bitCount++; + } + // Sign bit + bitCount++; + + if (bitCount != 8) + { + return Fail; + } + + return Pass; + } + } +} diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_8460/GitHub_8460.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_8460/GitHub_8460.csproj new file mode 100644 index 0000000..b174dea --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_8460/GitHub_8460.csproj @@ -0,0 +1,46 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + 7a9bfb7d + + + + + + + + + False + + + + + True + + + + + + + + + $(JitPackagesConfigFileDirectory)minimal\project.json + $(JitPackagesConfigFileDirectory)minimal\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_8599/GitHub_8599.cs b/tests/src/JIT/Regression/JitBlue/GitHub_8599/GitHub_8599.cs new file mode 100644 index 0000000..95ff457 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_8599/GitHub_8599.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.CompilerServices; + +// TreeNodeInfoInitCmp attempts to eliminate the cast from cmp(cast(x), icon) +// by narrowing the compare to ubyte. This should only happen if the constant fits in +// a byte so it can be narrowed too, otherwise codegen produces an int sized compare. + +class Program +{ + [MethodImpl(MethodImplOptions.NoInlining)] + static int GetValue() => 301; + + static void Escape(ref int x) + { + } + + static int Main() + { + if ((byte)GetValue() > 300) + { + return -1; + } + + int x = GetValue(); + Escape(ref x); + if ((byte)x > 300) + { + return -2; + } + + if ((byte)(GetValue() | 2) > 300) + { + return -3; + } + + return 100; + } +} diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_8599/GitHub_8599.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_8599/GitHub_8599.csproj new file mode 100644 index 0000000..b174dea --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_8599/GitHub_8599.csproj @@ -0,0 +1,46 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + 7a9bfb7d + + + + + + + + + False + + + + + True + + + + + + + + + $(JitPackagesConfigFileDirectory)minimal\project.json + $(JitPackagesConfigFileDirectory)minimal\project.lock.json + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_CoreRT_2073/GitHub_CoreRT_2073.il b/tests/src/JIT/Regression/JitBlue/GitHub_CoreRT_2073/GitHub_CoreRT_2073.il new file mode 100644 index 0000000..28adbc4 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_CoreRT_2073/GitHub_CoreRT_2073.il @@ -0,0 +1,55 @@ +// 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. + +// Test for a issue when tail call with small return type +// doesn't pass tail call pattern assert. +// In addition there is "call->branch on return->return" tail call pattern check. + + +.assembly extern mscorlib {} + +.assembly GitHub_CoreRT_2073.exe {} + +.class public Test +{ + +.method private hidebysig static bool tailAsgReturn(int32 deep) cil managed +{ + // Code size 24 (0x18) + .maxstack 20 + IL_0000: ldarg.0 + IL_0001: ldc.i4.s -100 + IL_0003: bgt.s IL_0007 + IL_0005: ldc.i4.1 + IL_0006: ret + IL_0007: ldarg.0 + IL_0008: ldc.i4.0 + IL_0009: bgt.s IL_000f + + IL_000a: ldarg.0 + IL_000b: ldc.i4.1 + IL_000c: sub + IL_000d: call bool Test::tailAsgReturn(int32) + IL_000e: br IL_0017 + IL_000f: ldarg.0 + IL_0010: ldc.i4.2 + IL_0011: sub + IL_0012: call bool Test::tailAsgReturn(int32) + IL_0017: ret +} // end of method Test::tailAsgReturn + +.method public hidebysig static int32 Main(string[] args) cil managed +{ + .entrypoint + // Code size 14 (0xe) + .maxstack 8 + IL_0000: ldc.i4.s 100 + IL_0002: call bool Test::tailAsgReturn(int32) + IL_0007: brtrue.s IL_000b + IL_0009: ldc.i4.m1 + IL_000a: ret + IL_000b: ldc.i4.s 100 + IL_000d: ret +} // end of method Test::Main +} diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_CoreRT_2073/GitHub_CoreRT_2073.ilproj b/tests/src/JIT/Regression/JitBlue/GitHub_CoreRT_2073/GitHub_CoreRT_2073.ilproj new file mode 100644 index 0000000..fe8a3d3 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_CoreRT_2073/GitHub_CoreRT_2073.ilproj @@ -0,0 +1,38 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT .0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + None + True + + + + + + + + diff --git a/tests/src/JIT/Regression/VS-ia64-JIT/V2.0-Beta2/b311420/b311420.csproj b/tests/src/JIT/Regression/VS-ia64-JIT/V2.0-Beta2/b311420/b311420.csproj index b12149b..77a35cd 100644 --- a/tests/src/JIT/Regression/VS-ia64-JIT/V2.0-Beta2/b311420/b311420.csproj +++ b/tests/src/JIT/Regression/VS-ia64-JIT/V2.0-Beta2/b311420/b311420.csproj @@ -14,6 +14,9 @@ $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages ..\..\ 7a9bfb7d + + + true @@ -42,4 +45,4 @@ - \ No newline at end of file + diff --git a/tests/src/JIT/SIMD/Vector3Interop.cs b/tests/src/JIT/SIMD/Vector3Interop.cs index fa6f870..147adf4 100755 --- a/tests/src/JIT/SIMD/Vector3Interop.cs +++ b/tests/src/JIT/SIMD/Vector3Interop.cs @@ -112,7 +112,7 @@ class PInvokeTest // Expected return value = 1 + 2 + 3 + 10 + 11 + 12 = 39 if (nativeCall_PInvoke_Vector3Arg(iv, v1, str, v2) != 39) { - Console.Write("PInvoke Vector3Arg test failed\n"); + Console.WriteLine("PInvoke Vector3Arg test failed"); return false; } } @@ -130,7 +130,7 @@ class PInvokeTest f6, v2, // stack f7, f8); // stack if (sum != 1002) { - Console.Write("PInvoke Vector3Arg_Unix test failed\n"); + Console.WriteLine("PInvoke Vector3Arg_Unix test failed"); return false; } } @@ -151,7 +151,7 @@ class PInvokeTest v3, // stack f9); // stack if (sum != 1090) { - Console.Write("PInvoke Vector3Arg_Unix2 test failed\n"); + Console.WriteLine("PInvoke Vector3Arg_Unix2 test failed"); return false; } } diff --git a/tests/src/JIT/SIMD/VectorDot.cs b/tests/src/JIT/SIMD/VectorDot.cs index 2efe79e..22c1493 100644 --- a/tests/src/JIT/SIMD/VectorDot.cs +++ b/tests/src/JIT/SIMD/VectorDot.cs @@ -113,12 +113,17 @@ internal partial class VectorTest if (VectorDotTest.VectorDot(3ul, 2ul, 6ul * (ulong)Vector.Count) != Pass) returnVal = Fail; JitLog jitLog = new JitLog(); - // Dot is only recognized as an intrinsic for floating point element types. + // Dot is only recognized as an intrinsic for floating point element types + // and Vector on AVX. if (!jitLog.Check("Dot", "Single")) returnVal = Fail; if (!jitLog.Check("Dot", "Double")) returnVal = Fail; if (!jitLog.Check("System.Numerics.Vector4:Dot")) returnVal = Fail; if (!jitLog.Check("System.Numerics.Vector3:Dot")) returnVal = Fail; if (!jitLog.Check("System.Numerics.Vector2:Dot")) returnVal = Fail; + if (Vector.Count == 8) + { + if (!jitLog.Check("Dot", "Int32")) returnVal = Fail; + } jitLog.Dispose(); return returnVal; diff --git a/tests/src/JIT/SIMD/VectorIntEquals.cs b/tests/src/JIT/SIMD/VectorIntEquals.cs index bbbbbe5..fae49aa 100644 --- a/tests/src/JIT/SIMD/VectorIntEquals.cs +++ b/tests/src/JIT/SIMD/VectorIntEquals.cs @@ -17,12 +17,67 @@ internal partial class VectorTest Vector B = new Vector(3); Vector C = new Vector(5); - bool result = A.Equals(B); - if (!result) return Fail; + if (!result) + { + return Fail; + } result = A.Equals(C); - if (result) return Fail; + if (result) + { + return Fail; + } + + if (A.Equals(Vector.Zero)) + { + return Fail; + } + + if (!Vector.Zero.Equals(Vector.Zero)) + { + return Fail; + } + + if (Vector.Zero.Equals(B)) + { + return Fail; + } + + if (!(A == B)) + { + return Fail; + } + + if (A == Vector.Zero) + { + return Fail; + } + + if (!(A != Vector.Zero)) + { + return Fail; + } + + if (A != B) + { + return Fail; + } + + if (!(A != C)) + { + return Fail; + } + + if (!(Vector.Zero != A)) + { + return Fail; + } + + if (Vector.Zero != Vector.Zero) + { + return Fail; + } return Pass; } diff --git a/tests/src/JIT/SIMD/VectorUtil.cs b/tests/src/JIT/SIMD/VectorUtil.cs index d1b669d..6501aac 100644 --- a/tests/src/JIT/SIMD/VectorUtil.cs +++ b/tests/src/JIT/SIMD/VectorUtil.cs @@ -309,7 +309,7 @@ class JitLog : IDisposable } if (simdIntrinsicsSupported && methodFound) { - Console.WriteLine("Method " + method + " was compiled but should not have been\n"); + Console.WriteLine("Method " + method + " was compiled but should not have been"); return false; } // Useful when developing / debugging just to be sure that we reached here: diff --git a/tests/src/JIT/config/benchmark+roslyn/project.json b/tests/src/JIT/config/benchmark+roslyn/project.json index 3fc4bd5..e50dfd2 100644 --- a/tests/src/JIT/config/benchmark+roslyn/project.json +++ b/tests/src/JIT/config/benchmark+roslyn/project.json @@ -1,29 +1,29 @@ { "dependencies": { "Microsoft.CodeAnalysis.Compilers": "1.1.1", - "Microsoft.DotNet.xunit.performance": "1.0.0-alpha-build0035", - "Microsoft.DotNet.xunit.performance.analysis": "1.0.0-alpha-build0035", - "Microsoft.DotNet.xunit.performance.runner.Windows": "1.0.0-alpha-build0035", - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Console": "4.3.0", - "System.Dynamic.Runtime": "4.3.0", - "System.Linq": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Numerics.Vectors": "4.3.0", - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Reflection.TypeExtensions": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Text.RegularExpressions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.Tasks.Parallel": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "xunit": "2.1.0", - "xunit.console.netcore": "1.0.2-prerelease-00101", - "xunit.runner.utility": "2.1.0" + "Microsoft.DotNet.xunit.performance": "1.0.0-alpha-build0040", + "Microsoft.DotNet.xunit.performance.analysis": "1.0.0-alpha-build0040", + "Microsoft.DotNet.xunit.performance.runner.Windows": "1.0.0-alpha-build0040", + "Microsoft.NETCore.Platforms": "1.2.0-beta-24820-02", + "System.Console": "4.4.0-beta-24820-02", + "System.Dynamic.Runtime": "4.4.0-beta-24820-02", + "System.Linq": "4.4.0-beta-24820-02", + "System.IO.FileSystem": "4.4.0-beta-24820-02", + "System.Numerics.Vectors": "4.4.0-beta-24820-02", + "System.Reflection": "4.4.0-beta-24820-02", + "System.Reflection.Extensions": "4.4.0-beta-24820-02", + "System.Reflection.TypeExtensions": "4.4.0-beta-24820-02", + "System.Runtime": "4.4.0-beta-24820-02", + "System.Runtime.Extensions": "4.4.0-beta-24820-02", + "System.Runtime.Numerics": "4.4.0-beta-24820-02", + "System.Text.RegularExpressions": "4.4.0-beta-24820-02", + "System.Threading": "4.4.0-beta-24820-02", + "System.Threading.Tasks": "4.4.0-beta-24820-02", + "System.Threading.Tasks.Parallel": "4.4.0-beta-24820-02", + "System.Security.Cryptography.Algorithms": "4.4.0-beta-24820-02", + "xunit": "2.2.0-beta2-build3300", + "xunit.console.netcore": "1.0.2-prerelease-00177", + "xunit.runner.utility": "2.2.0-beta2-build3300" }, "frameworks": { "netstandard1.4": { diff --git a/tests/src/JIT/config/benchmark+serialize/project.json b/tests/src/JIT/config/benchmark+serialize/project.json index e7e1853..ac24df1 100644 --- a/tests/src/JIT/config/benchmark+serialize/project.json +++ b/tests/src/JIT/config/benchmark+serialize/project.json @@ -1,26 +1,29 @@ { "dependencies": { - "Microsoft.DotNet.xunit.performance": "1.0.0-alpha-build0035", - "Microsoft.DotNet.xunit.performance.analysis": "1.0.0-alpha-build0035", - "Microsoft.DotNet.xunit.performance.runner.Windows": "1.0.0-alpha-build0035", - "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.DotNet.xunit.performance": "1.0.0-alpha-build0040", + "Microsoft.DotNet.xunit.performance.analysis": "1.0.0-alpha-build0040", + "Microsoft.DotNet.xunit.performance.runner.Windows": "1.0.0-alpha-build0040", + "Microsoft.NETCore.Platforms": "1.2.0-beta-24820-02", "Newtonsoft.Json": "7.0.1", - "System.Console": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Linq": "4.3.0", - "System.ObjectModel": "4.3.0", - "System.Dynamic.Runtime": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Serialization.Json": "4.3.0", - "System.Runtime.Serialization.Primitives": "4.1.1", - "System.Runtime.Serialization.Xml": "4.3.0", - "System.Text.RegularExpressions": "4.3.0", - "System.Xml.XmlDocument": "4.3.0", - "System.Xml.XmlSerializer": "4.3.0", - "xunit": "2.1.0", - "xunit.console.netcore": "1.0.2-prerelease-00101", - "xunit.runner.utility": "2.1.0" + "System.Console": "4.4.0-beta-24820-02", + "System.IO": "4.4.0-beta-24820-02", + "System.IO.FileSystem": "4.4.0-beta-24820-02", + "System.Linq": "4.4.0-beta-24820-02", + "System.ObjectModel": "4.4.0-beta-24820-02", + "System.Dynamic.Runtime": "4.4.0-beta-24820-02", + "System.Reflection": "4.4.0-beta-24820-02", + "System.Reflection.Extensions": "4.4.0-beta-24820-02", + "System.Reflection.TypeExtensions": "4.4.0-beta-24820-02", + "System.Runtime": "4.4.0-beta-24820-02", + "System.Runtime.Serialization.Json": "4.4.0-beta-24820-02", + "System.Runtime.Serialization.Primitives": "4.4.0-beta-24820-02", + "System.Runtime.Serialization.Xml": "4.4.0-beta-24820-02", + "System.Text.RegularExpressions": "4.4.0-beta-24820-02", + "System.Xml.XmlDocument": "4.4.0-beta-24820-02", + "System.Xml.XmlSerializer": "4.4.0-beta-24820-02", + "xunit": "2.2.0-beta2-build3300", + "xunit.console.netcore": "1.0.2-prerelease-00177", + "xunit.runner.utility": "2.2.0-beta2-build3300" }, "frameworks": { "netstandard1.4": { diff --git a/tests/src/JIT/config/benchmark/project.json b/tests/src/JIT/config/benchmark/project.json index 8f1493c..97234d3 100644 --- a/tests/src/JIT/config/benchmark/project.json +++ b/tests/src/JIT/config/benchmark/project.json @@ -1,29 +1,32 @@ { "dependencies": { - "Microsoft.DotNet.xunit.performance": "1.0.0-alpha-build0035", - "Microsoft.DotNet.xunit.performance.analysis": "1.0.0-alpha-build0035", - "Microsoft.DotNet.xunit.performance.runner.Windows": "1.0.0-alpha-build0035", - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections.NonGeneric": "4.3.0", - "System.Console": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Linq": "4.3.0", - "System.Linq.Expressions": "4.3.0", - "System.Numerics.Vectors": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Text.RegularExpressions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.Tasks.Parallel": "4.3.0", - "System.Diagnostics.Process": "4.3.0", - "System.Xml.XmlDocument": "4.3.0", - "System.Xml.XPath": "4.3.0", - "System.Xml.XPath.XmlDocument": "4.3.0", - "xunit": "2.1.0", - "xunit.console.netcore": "1.0.2-prerelease-00101", - "xunit.runner.utility": "2.1.0" + "Microsoft.DotNet.xunit.performance": "1.0.0-alpha-build0040", + "Microsoft.DotNet.xunit.performance.analysis": "1.0.0-alpha-build0040", + "Microsoft.DotNet.xunit.performance.runner.Windows": "1.0.0-alpha-build0040", + "Microsoft.NETCore.Platforms": "1.2.0-beta-24820-02", + "System.Collections.NonGeneric": "4.4.0-beta-24820-02", + "System.Console": "4.4.0-beta-24820-02", + "System.IO.FileSystem": "4.4.0-beta-24820-02", + "System.Linq": "4.4.0-beta-24820-02", + "System.Linq.Expressions": "4.4.0-beta-24820-02", + "System.Numerics.Vectors": "4.4.0-beta-24820-02", + "System.Reflection": "4.4.0-beta-24820-02", + "System.Reflection.Extensions": "4.4.0-beta-24820-02", + "System.Reflection.TypeExtensions": "4.4.0-beta-24820-02", + "System.Runtime": "4.4.0-beta-24820-02", + "System.Runtime.Extensions": "4.4.0-beta-24820-02", + "System.Runtime.Numerics": "4.4.0-beta-24820-02", + "System.Text.RegularExpressions": "4.4.0-beta-24820-02", + "System.Threading": "4.4.0-beta-24820-02", + "System.Threading.Tasks": "4.4.0-beta-24820-02", + "System.Threading.Tasks.Parallel": "4.4.0-beta-24820-02", + "System.Diagnostics.Process": "4.4.0-beta-24820-02", + "System.Xml.XmlDocument": "4.4.0-beta-24820-02", + "System.Xml.XPath": "4.4.0-beta-24820-02", + "System.Xml.XPath.XmlDocument": "4.4.0-beta-24820-02", + "xunit": "2.2.0-beta2-build3300", + "xunit.console.netcore": "1.0.2-prerelease-00177", + "xunit.runner.utility": "2.2.0-beta2-build3300" }, "frameworks": { "netstandard1.4": { diff --git a/tests/src/JIT/config/extra/project.json b/tests/src/JIT/config/extra/project.json index 92b2fac..6268bc5 100644 --- a/tests/src/JIT/config/extra/project.json +++ b/tests/src/JIT/config/extra/project.json @@ -1,24 +1,24 @@ { "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Console": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", - "System.Diagnostics.Process": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Reflection.TypeExtensions": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.CompilerServices.Unsafe": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" + "Microsoft.NETCore.Platforms": "1.2.0-beta-24820-02", + "System.Collections": "4.4.0-beta-24820-02", + "System.Console": "4.4.0-beta-24820-02", + "System.Diagnostics.Debug": "4.4.0-beta-24820-02", + "System.Runtime.InteropServices.RuntimeInformation": "4.4.0-beta-24820-02", + "System.Diagnostics.Process": "4.4.0-beta-24820-02", + "System.Globalization": "4.4.0-beta-24820-02", + "System.IO": "4.4.0-beta-24820-02", + "System.IO.FileSystem": "4.4.0-beta-24820-02", + "System.Reflection": "4.4.0-beta-24820-02", + "System.Reflection.Extensions": "4.4.0-beta-24820-02", + "System.Reflection.TypeExtensions": "4.4.0-beta-24820-02", + "System.Runtime": "4.4.0-beta-24820-02", + "System.Runtime.Extensions": "4.4.0-beta-24820-02", + "System.Runtime.CompilerServices.Unsafe": "4.4.0-beta-24820-02", + "System.Runtime.InteropServices": "4.4.0-beta-24820-02" }, "frameworks": { - "netcoreapp1.0": {} + "netcoreapp1.1": {} }, "runtimes": { "win7-x86": {}, diff --git a/tests/src/JIT/config/minimal/project.json b/tests/src/JIT/config/minimal/project.json index 20eded4..6bc378e 100644 --- a/tests/src/JIT/config/minimal/project.json +++ b/tests/src/JIT/config/minimal/project.json @@ -1,13 +1,13 @@ { "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Console": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" + "Microsoft.NETCore.Platforms": "1.2.0-beta-24820-02", + "System.Console": "4.4.0-beta-24820-02", + "System.Runtime": "4.4.0-beta-24820-02", + "System.Runtime.Extensions": "4.4.0-beta-24820-02", + "System.Runtime.InteropServices": "4.4.0-beta-24820-02" }, "frameworks": { - "netcoreapp1.0": {} + "netcoreapp1.1": {} }, "runtimes": { "win7-x86": {}, diff --git a/tests/src/JIT/config/threading+thread/project.json b/tests/src/JIT/config/threading+thread/project.json index 4efc76c..f6576f1 100644 --- a/tests/src/JIT/config/threading+thread/project.json +++ b/tests/src/JIT/config/threading+thread/project.json @@ -1,15 +1,15 @@ { "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Console": "4.3.0", - "System.Numerics.Vectors": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Thread": "4.3.0" + "Microsoft.NETCore.Platforms": "1.2.0-beta-24820-02", + "System.Console": "4.4.0-beta-24820-02", + "System.Numerics.Vectors": "4.4.0-beta-24820-02", + "System.Runtime": "4.4.0-beta-24820-02", + "System.Runtime.Extensions": "4.4.0-beta-24820-02", + "System.Threading": "4.4.0-beta-24820-02", + "System.Threading.Thread": "4.4.0-beta-24820-02" }, "frameworks": { - "netcoreapp1.0": {} + "netcoreapp1.1": {} }, "runtimes": { "win7-x86": {}, diff --git a/tests/src/JIT/config/threading/project.json b/tests/src/JIT/config/threading/project.json index b0478ce..e62d355 100644 --- a/tests/src/JIT/config/threading/project.json +++ b/tests/src/JIT/config/threading/project.json @@ -1,13 +1,13 @@ { "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Console": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Threading": "4.3.0" + "Microsoft.NETCore.Platforms": "1.2.0-beta-24820-02", + "System.Console": "4.4.0-beta-24820-02", + "System.Runtime": "4.4.0-beta-24820-02", + "System.Runtime.Extensions": "4.4.0-beta-24820-02", + "System.Threading": "4.4.0-beta-24820-02" }, "frameworks": { - "netcoreapp1.0": {} + "netcoreapp1.1": {} }, "runtimes": { "win7-x86": {}, diff --git a/tests/src/JIT/jit64/opt/cse/HugeArray.csproj b/tests/src/JIT/jit64/opt/cse/HugeArray.csproj index 8926c0f..166482b 100644 --- a/tests/src/JIT/jit64/opt/cse/HugeArray.csproj +++ b/tests/src/JIT/jit64/opt/cse/HugeArray.csproj @@ -14,6 +14,9 @@ $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages ..\..\ 7a9bfb7d + + + true @@ -42,4 +45,4 @@ - \ No newline at end of file + diff --git a/tests/src/JIT/jit64/verif/sniff/fg/ver_fg_13.il b/tests/src/JIT/jit64/verif/sniff/fg/ver_fg_13.il index 9e422bb..5ad48d1 100644 --- a/tests/src/JIT/jit64/verif/sniff/fg/ver_fg_13.il +++ b/tests/src/JIT/jit64/verif/sniff/fg/ver_fg_13.il @@ -11,12 +11,7 @@ .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) .ver 4:0:0:0 } -.assembly test -{ - .custom instance void [mscorlib]System.Security.AllowPartiallyTrustedCallersAttribute::.ctor() = ( 01 00 01 00 00 ) - -} - +.assembly test { } .module ver_fg_13.exe diff --git a/tests/src/JIT/opt/Inline/regression/mismatch32/mismatch32.il b/tests/src/JIT/opt/Inline/regression/mismatch32/mismatch32.il index e23b0a8..73730d7 100644 --- a/tests/src/JIT/opt/Inline/regression/mismatch32/mismatch32.il +++ b/tests/src/JIT/opt/Inline/regression/mismatch32/mismatch32.il @@ -5,6 +5,10 @@ // When the jit considers inlining B it can get itself into // trouble because of the type mismatch. This test tries to // ensure the jit backs out of the inline successfully. +// +// By default (when no args are passed) execution avoids +// the problematic callsite, and the app should run without +// failing. .assembly extern mscorlib { } .assembly extern System.Console @@ -39,7 +43,7 @@ ldarg.0 ldlen ldc.i4 1 - bgt DONE + blt DONE newobj instance void F::.ctor() ldc.i4 33 call int32 B(int32, int32) diff --git a/tests/src/JIT/opt/Inline/regression/mismatch64/mismatch64.il b/tests/src/JIT/opt/Inline/regression/mismatch64/mismatch64.il index f952856..ba336c0 100644 --- a/tests/src/JIT/opt/Inline/regression/mismatch64/mismatch64.il +++ b/tests/src/JIT/opt/Inline/regression/mismatch64/mismatch64.il @@ -5,6 +5,10 @@ // When the jit considers inlining B it can get itself into // trouble because of the type mismatch. This test tries to // ensure the jit backs out of the inline successfully. +// +// By default (when no args are passed) execution avoids +// the problematic callsite, and the app should run without +// failing. .assembly extern mscorlib { } .assembly extern System.Console @@ -39,7 +43,7 @@ ldarg.0 ldlen ldc.i4 1 - bgt DONE + blt DONE newobj instance void F::.ctor() ldc.i8 44 call int64 B(int64, int64) diff --git a/tests/src/JIT/opt/Tailcall/TailcallVerifyWithPrefix.il b/tests/src/JIT/opt/Tailcall/TailcallVerifyWithPrefix.il index 9c5fcfd..763d95f 100644 --- a/tests/src/JIT/opt/Tailcall/TailcallVerifyWithPrefix.il +++ b/tests/src/JIT/opt/Tailcall/TailcallVerifyWithPrefix.il @@ -5610,6 +5610,9 @@ .method public hidebysig instance void Caller1() cil managed { + // This method depends on JIT compiler doing automatic tail call, which isn't supported by Ready-to-Run. + .custom instance void System.Runtime.BypassReadyToRunAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 53 (0x35) .maxstack 8 IL_0000: ldc.i4.0 @@ -5633,6 +5636,9 @@ .method public hidebysig instance void Caller1Recursive() cil managed { + // This method depends on JIT compiler doing automatic tail call, which isn't supported by Ready-to-Run. + .custom instance void System.Runtime.BypassReadyToRunAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 55 (0x37) .maxstack 8 IL_0000: ldc.i4.0 @@ -5670,6 +5676,9 @@ .method private hidebysig instance void Callee1Recursive(int32 i) cil managed { + // This method depends on JIT compiler doing automatic tail call, which isn't supported by Ready-to-Run. + .custom instance void System.Runtime.BypassReadyToRunAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 93 (0x5d) .maxstack 3 .locals init ([0] string stackTrace, @@ -5805,6 +5814,9 @@ Caller1(!V arg1, !K arg2) cil managed { + // This method depends on JIT compiler doing automatic tail call, which isn't supported by Ready-to-Run. + .custom instance void System.Runtime.BypassReadyToRunAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 54 (0x36) .maxstack 8 IL_0000: ldc.i4.0 @@ -6016,6 +6028,9 @@ .method private hidebysig static void Caller2() cil managed { + // This method depends on JIT compiler doing automatic tail call, which isn't supported by Ready-to-Run. + .custom instance void System.Runtime.BypassReadyToRunAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 52 (0x34) .maxstack 8 IL_0000: ldc.i4.0 @@ -10376,6 +10391,21 @@ .field static assembly valuetype '{D1242658-CA16-4D11-A740-6635F112F4B5}'/'__StaticArrayInitTypeSize=20' '$$method0x6000076-1' at I_00005C00 } // end of class '{D1242658-CA16-4D11-A740-6635F112F4B5}' +.class private auto ansi sealed beforefieldinit System.Runtime.BypassReadyToRunAttribute + extends [mscorlib]System.Attribute +{ + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Attribute::.ctor() + IL_0006: ret + } // end of method BypassReadyToRunAttribute::.ctor + +} // end of class System.Runtime.BypassReadyToRunAttribute + // ============================================================= diff --git a/tests/src/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_d.csproj b/tests/src/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_d.csproj index da9a36e..4a5818f 100644 --- a/tests/src/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_d.csproj +++ b/tests/src/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_d.csproj @@ -14,6 +14,9 @@ $(ProgramFiles)\Common Files\microsoft shared\VSTT .0\UITestExtensionPackages ..\..\ 7a9bfb7d + + + true diff --git a/tests/src/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_r.csproj b/tests/src/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_r.csproj index a7547ea..909d798 100644 --- a/tests/src/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_r.csproj +++ b/tests/src/JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_r.csproj @@ -14,6 +14,9 @@ $(ProgramFiles)\Common Files\microsoft shared\VSTT .0\UITestExtensionPackages ..\..\ 7a9bfb7d + + + true diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase0.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase0.il index 1dcd41e..f872145 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase0.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase0.il @@ -36,7 +36,10 @@ ldstr "A::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 @@ -59,12 +62,20 @@ .maxstack 8 ldstr "B::Bar2" ret - } .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -103,4 +114,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase1.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase1.il index 371ade9..05c6c99 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase1.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase1.il @@ -24,7 +24,10 @@ ldstr "A::Foo" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 @@ -43,12 +46,19 @@ ldstr "B::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -87,4 +97,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase2.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase2.il index 3c65974..6cf4e13 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase2.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase2.il @@ -24,7 +24,10 @@ ldstr "A::Foo" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private abstract auto ansi beforefieldinit B`2 @@ -43,12 +46,19 @@ ldstr "B::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -87,4 +97,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase3.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase3.il index 9fc5e81..d41d8cb 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase3.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase3.il @@ -19,7 +19,10 @@ .class interface nested family abstract auto ansi I`1 { .method public hidebysig newslot abstract virtual instance string Foo() cil managed {} } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 @@ -43,12 +46,19 @@ ldstr "B::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -87,4 +97,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase4.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase4.il index 137cf43..bbd564b 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase4.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase4.il @@ -18,8 +18,11 @@ { .class interface nested family abstract auto ansi I`1 { .method public hidebysig newslot abstract virtual instance string Foo() cil managed {} } - - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private abstract auto ansi beforefieldinit B`2 @@ -43,12 +46,19 @@ ldstr "B::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -87,4 +97,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase5.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase5.il index 3ff9b9a..1cb5217 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase5.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase5.il @@ -36,19 +36,29 @@ ldstr "A::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 extends class A`1 implements class A`1/I`1, J { - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -87,4 +97,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase6.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase6.il index 55a59a1..7c08f9c 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase6.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_I/TestCase6.il @@ -36,19 +36,29 @@ ldstr "A::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private abstract auto ansi beforefieldinit B`2 extends class A`1 implements class A`1/I`1, J { - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -87,4 +97,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase0.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase0.il index 1bb1dae..490c829 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase0.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase0.il @@ -36,7 +36,10 @@ ldstr "A::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 @@ -59,12 +62,20 @@ .maxstack 8 ldstr "B::Bar2" ret - } .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -103,4 +114,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase1.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase1.il index 7c099e2..5501eb4 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase1.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase1.il @@ -24,7 +24,10 @@ ldstr "A::Foo" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 @@ -43,12 +46,19 @@ ldstr "B::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -87,4 +97,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase2.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase2.il index f2c3c2f..900afd1 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase2.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase2.il @@ -24,7 +24,10 @@ ldstr "A::Foo" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private abstract auto ansi beforefieldinit B`2 @@ -43,12 +46,19 @@ ldstr "B::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -87,4 +97,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase3.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase3.il index ea83a0f..d8a6ded 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase3.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase3.il @@ -19,7 +19,10 @@ .method public hidebysig newslot abstract virtual instance string Bar2() cil managed {} } } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 @@ -43,12 +46,19 @@ ldstr "B::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -87,4 +97,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase4.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase4.il index b95f00d..14fe464 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase4.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase4.il @@ -19,7 +19,10 @@ .method public hidebysig newslot abstract virtual instance string Bar2() cil managed {} } } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private abstract auto ansi beforefieldinit B`2 @@ -43,12 +46,19 @@ ldstr "B::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -87,4 +97,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase5.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase5.il index 46b6c3a..03ff440 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase5.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase5.il @@ -36,18 +36,29 @@ ldstr "A::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 extends class A`1 implements class A`1/I`1, A`1/I`1/J { - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object @@ -87,4 +98,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase6.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase6.il index 365a6aa..bdc70e8 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase6.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_I_Nested_J/TestCase6.il @@ -36,19 +36,29 @@ ldstr "A::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private abstract auto ansi beforefieldinit B`2 extends class A`1 implements class A`1/I`1, A`1/I`1/J { - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase0.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase0.il index 356cd39..d4aecd8 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase0.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase0.il @@ -36,7 +36,10 @@ ldstr "A::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 @@ -59,12 +62,20 @@ .maxstack 8 ldstr "B::Bar2" ret - } .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -103,4 +114,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase1.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase1.il index bcf1b2b..f24aba9 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase1.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase1.il @@ -23,7 +23,10 @@ ldstr "A::Foo" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 @@ -42,12 +45,19 @@ ldstr "B::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -86,4 +96,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase2.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase2.il index 0d82b78..eda666b 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase2.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase2.il @@ -23,7 +23,10 @@ ldstr "A::Foo" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private abstract auto ansi beforefieldinit B`2 @@ -42,12 +45,19 @@ ldstr "B::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -86,4 +96,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase3.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase3.il index 7341902..e15e0ab 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase3.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase3.il @@ -18,7 +18,10 @@ .method public hidebysig newslot abstract virtual instance string Bar1() cil managed {} .method public hidebysig newslot abstract virtual instance string Bar2() cil managed {} } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 @@ -42,12 +45,19 @@ ldstr "B::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -86,4 +96,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase4.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase4.il index 75ef0e8..91ed358 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase4.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase4.il @@ -18,7 +18,10 @@ .method public hidebysig newslot abstract virtual instance string Bar1() cil managed {} .method public hidebysig newslot abstract virtual instance string Bar2() cil managed {} } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private abstract auto ansi beforefieldinit B`2 @@ -42,12 +45,19 @@ ldstr "B::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -86,4 +96,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase5.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase5.il index 4e7a639..1ceb777 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase5.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase5.il @@ -35,19 +35,29 @@ ldstr "A::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 extends class A`1 implements class I`1, A`1/J { - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -86,4 +96,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase6.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase6.il index f106b5f..52d4631 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase6.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_J/TestCase6.il @@ -35,19 +35,29 @@ ldstr "A::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private abstract auto ansi beforefieldinit B`2 extends class A`1 implements class I`1, A`1/J { - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -86,4 +96,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase0.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase0.il index fb4f32d..5fab5b8 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase0.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase0.il @@ -34,7 +34,10 @@ ldstr "A::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 @@ -57,12 +60,20 @@ .maxstack 8 ldstr "B::Bar2" ret - } .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -101,4 +112,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase1.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase1.il index fd46e20..d2a73e3 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase1.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase1.il @@ -22,7 +22,10 @@ ldstr "A::Foo" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 @@ -41,12 +44,19 @@ ldstr "B::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -85,4 +95,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase2.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase2.il index 065c132..6874dca 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase2.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase2.il @@ -22,7 +22,10 @@ ldstr "A::Foo" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private abstract auto ansi beforefieldinit B`2 @@ -41,12 +44,19 @@ ldstr "B::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -85,4 +95,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase3.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase3.il index 7f40457..03516e4 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase3.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase3.il @@ -17,7 +17,10 @@ .method public hidebysig newslot abstract virtual instance string Bar1() cil managed {} .method public hidebysig newslot abstract virtual instance string Bar2() cil managed {} } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 @@ -41,12 +44,19 @@ ldstr "B::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -85,4 +95,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase4.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase4.il index f4efdfd..72b3ed1 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase4.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase4.il @@ -17,7 +17,10 @@ .method public hidebysig newslot abstract virtual instance string Bar1() cil managed {} .method public hidebysig newslot abstract virtual instance string Bar2() cil managed {} } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private abstract auto ansi beforefieldinit B`2 @@ -41,12 +44,19 @@ ldstr "B::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -85,4 +95,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase5.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase5.il index a446ed3..0fb52a5 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase5.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase5.il @@ -34,19 +34,29 @@ ldstr "A::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 extends class A`1 implements class A`1/J/I`1, A`1/J { - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -85,4 +95,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase6.il b/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase6.il index baaabcc..fd5047e 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase6.il +++ b/tests/src/Loader/classloader/InterfaceFolding/Nested_J_Nested_I/TestCase6.il @@ -34,19 +34,29 @@ ldstr "A::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private abstract auto ansi beforefieldinit B`2 extends class A`1 implements class A`1/J/I`1, A`1/J { - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { @@ -85,4 +95,4 @@ FAILURE: ldc.i4.m1 ret } -} \ No newline at end of file +} diff --git a/tests/src/Loader/classloader/InterfaceFolding/TestCase0.il b/tests/src/Loader/classloader/InterfaceFolding/TestCase0.il index 0e5c131..068a309 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/TestCase0.il +++ b/tests/src/Loader/classloader/InterfaceFolding/TestCase0.il @@ -37,7 +37,10 @@ ldstr "A::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 @@ -60,12 +63,16 @@ .maxstack 8 ldstr "B::Bar2" ret - } .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { diff --git a/tests/src/Loader/classloader/InterfaceFolding/TestCase1.il b/tests/src/Loader/classloader/InterfaceFolding/TestCase1.il index 2f7be47..e5d4183 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/TestCase1.il +++ b/tests/src/Loader/classloader/InterfaceFolding/TestCase1.il @@ -25,7 +25,10 @@ ldstr "A::Foo" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 @@ -44,12 +47,19 @@ ldstr "B::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { diff --git a/tests/src/Loader/classloader/InterfaceFolding/TestCase2.il b/tests/src/Loader/classloader/InterfaceFolding/TestCase2.il index 1927d59..30e99dc 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/TestCase2.il +++ b/tests/src/Loader/classloader/InterfaceFolding/TestCase2.il @@ -25,7 +25,10 @@ ldstr "A::Foo" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private abstract auto ansi beforefieldinit B`2 @@ -44,12 +47,19 @@ ldstr "B::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { diff --git a/tests/src/Loader/classloader/InterfaceFolding/TestCase3.il b/tests/src/Loader/classloader/InterfaceFolding/TestCase3.il index e67f039..d84965c 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/TestCase3.il +++ b/tests/src/Loader/classloader/InterfaceFolding/TestCase3.il @@ -20,7 +20,10 @@ .class private abstract auto ansi beforefieldinit A`1 implements class I`1 { - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 @@ -44,12 +47,19 @@ ldstr "B::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { diff --git a/tests/src/Loader/classloader/InterfaceFolding/TestCase4.il b/tests/src/Loader/classloader/InterfaceFolding/TestCase4.il index e411d7a..f41de5c 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/TestCase4.il +++ b/tests/src/Loader/classloader/InterfaceFolding/TestCase4.il @@ -20,7 +20,10 @@ .class private abstract auto ansi beforefieldinit A`1 implements class I`1 { - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private abstract auto ansi beforefieldinit B`2 @@ -44,12 +47,19 @@ ldstr "B::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { diff --git a/tests/src/Loader/classloader/InterfaceFolding/TestCase5.il b/tests/src/Loader/classloader/InterfaceFolding/TestCase5.il index 30a61c9..51ddd83 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/TestCase5.il +++ b/tests/src/Loader/classloader/InterfaceFolding/TestCase5.il @@ -37,19 +37,29 @@ ldstr "A::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 extends class A`1 implements class I`1, J { - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { diff --git a/tests/src/Loader/classloader/InterfaceFolding/TestCase6.il b/tests/src/Loader/classloader/InterfaceFolding/TestCase6.il index 4b9dc2c..ceba545 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/TestCase6.il +++ b/tests/src/Loader/classloader/InterfaceFolding/TestCase6.il @@ -37,19 +37,29 @@ ldstr "A::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private abstract auto ansi beforefieldinit B`2 extends class A`1 implements class I`1, J { - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { diff --git a/tests/src/Loader/classloader/InterfaceFolding/TestCase7.il b/tests/src/Loader/classloader/InterfaceFolding/TestCase7.il index 92f6135..2513ae0 100644 --- a/tests/src/Loader/classloader/InterfaceFolding/TestCase7.il +++ b/tests/src/Loader/classloader/InterfaceFolding/TestCase7.il @@ -37,7 +37,10 @@ ldstr "A::Bar2" ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit B`2 @@ -61,12 +64,20 @@ .maxstack 8 ldstr "B::Bar2" ret - } .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class private auto ansi beforefieldinit C extends class B`2 -{ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed {} } - +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } +} .class public auto ansi beforefieldinit Test extends [mscorlib]System.Object { diff --git a/tests/src/Loader/classloader/PrivateInterfaceImpl/Test2_NonFriendPriInterface.csproj b/tests/src/Loader/classloader/PrivateInterfaceImpl/Test2_NonFriendPriInterface.csproj deleted file mode 100644 index 5c75304..0000000 --- a/tests/src/Loader/classloader/PrivateInterfaceImpl/Test2_NonFriendPriInterface.csproj +++ /dev/null @@ -1,35 +0,0 @@ - - - - - Test2_NonFriendPriInterface - Debug - AnyCPU - 2.0 - {95DFC527-4DC1-495E-97D7-E94EE1F7140D} - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 7a9bfb7d - true - false - Library - BuildOnly - 0 - - - - - False - - - - - - - - - - - - - diff --git a/tests/src/Loader/classloader/generics/Visibility/A_Types.csproj b/tests/src/Loader/classloader/generics/Visibility/A_Types.csproj deleted file mode 100644 index 023d1b9..0000000 --- a/tests/src/Loader/classloader/generics/Visibility/A_Types.csproj +++ /dev/null @@ -1,35 +0,0 @@ - - - - - A_Types - Debug - AnyCPU - 2.0 - {95DFC527-4DC1-495E-97D7-E94EE1F7140D} - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 7a9bfb7d - true - false - Library - BuildOnly - 0 - - - - - False - - - - - - - - - - - - - diff --git a/tests/src/Loader/classloader/generics/Visibility/B_Types.csproj b/tests/src/Loader/classloader/generics/Visibility/B_Types.csproj deleted file mode 100644 index 46c0601..0000000 --- a/tests/src/Loader/classloader/generics/Visibility/B_Types.csproj +++ /dev/null @@ -1,35 +0,0 @@ - - - - - B_Types - Debug - AnyCPU - 2.0 - {95DFC527-4DC1-495E-97D7-E94EE1F7140D} - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 7a9bfb7d - true - false - Library - BuildOnly - 0 - - - - - False - - - - - - - - - - - - - diff --git a/tests/src/Loader/classloader/methodoverriding/regressions/549411/exploit.csproj b/tests/src/Loader/classloader/methodoverriding/regressions/549411/exploit.csproj index ce7ca5e..29cb737 100644 --- a/tests/src/Loader/classloader/methodoverriding/regressions/549411/exploit.csproj +++ b/tests/src/Loader/classloader/methodoverriding/regressions/549411/exploit.csproj @@ -15,6 +15,7 @@ Exe BuildAndRun 0 + true diff --git a/tests/src/Loader/classloader/regressions/dev10_710121/dev10_710121.il b/tests/src/Loader/classloader/regressions/dev10_710121/dev10_710121.il index babb30d..96e28f6 100644 --- a/tests/src/Loader/classloader/regressions/dev10_710121/dev10_710121.il +++ b/tests/src/Loader/classloader/regressions/dev10_710121/dev10_710121.il @@ -21,12 +21,18 @@ The bug related to populating MethodDesc slots in generic dictionaries at runtim .class public DerivedDerived extends class Derived`2 { - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class public Derived`2 extends class Base`2 { - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } .class public Base`2 { @@ -40,7 +46,10 @@ The bug related to populating MethodDesc slots in generic dictionaries at runtim call string [mscorlib]System.String::Concat(object,object) ret } - .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + ret + } } diff --git a/tests/src/TestWrappersConfig/project.json b/tests/src/TestWrappersConfig/project.json index 07ede5f..f255e30 100644 --- a/tests/src/TestWrappersConfig/project.json +++ b/tests/src/TestWrappersConfig/project.json @@ -1,10 +1,17 @@ { "dependencies": { - "xunit": "2.1.0", - "xunit.assert": "2.1.0", - "xunit.core": "2.1.0" + "xunit": "2.2.0-beta2-build3300", + "xunit.assert": "2.2.0-beta2-build3300", + "xunit.core": "2.2.0-beta2-build3300", + "xunit.runner.msbuild": "2.2.0-beta2-build3300" }, "frameworks": { + "netcoreapp1.1": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] + }, "net45": { "imports": "portable-net45+win8" } diff --git a/tests/src/baseservices/compilerservices/FixedAddressValueType/FixedAddressValueType.cs b/tests/src/baseservices/compilerservices/FixedAddressValueType/FixedAddressValueType.cs new file mode 100644 index 0000000..bf10d81 --- /dev/null +++ b/tests/src/baseservices/compilerservices/FixedAddressValueType/FixedAddressValueType.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. +// See the LICENSE file in the project root for more information. +// +using System; +using System.Runtime.CompilerServices; + +public struct Age { + public int years; + public int months; +} + +public class FreeClass +{ + public static Age FreeAge; + + public static unsafe IntPtr AddressOfFreeAge() + { + fixed (Age* pointer = &FreeAge) + { return (IntPtr) pointer; } + } +} + +public class FixedClass +{ + [FixedAddressValueType] + public static Age FixedAge; + + public static unsafe IntPtr AddressOfFixedAge() + { + fixed (Age* pointer = &FixedAge) + { return (IntPtr) pointer; } + } +} + +public class Example +{ + public static int Main() + { + // Get addresses of static Age fields. + IntPtr freePtr1 = FreeClass.AddressOfFreeAge(); + + IntPtr fixedPtr1 = FixedClass.AddressOfFixedAge(); + + // Garbage collection. + GC.Collect(3, GCCollectionMode.Forced, true, true); + GC.WaitForPendingFinalizers(); + + // Get addresses of static Age fields after garbage collection. + IntPtr freePtr2 = FreeClass.AddressOfFreeAge(); + IntPtr fixedPtr2 = FixedClass.AddressOfFixedAge(); + + if(freePtr1 != freePtr2 && fixedPtr1 == fixedPtr2) + { + return 100; + } + + return -1; + } +} diff --git a/tests/src/baseservices/compilerservices/FixedAddressValueType/FixedAddressValueType.csproj b/tests/src/baseservices/compilerservices/FixedAddressValueType/FixedAddressValueType.csproj new file mode 100644 index 0000000..19a7791 --- /dev/null +++ b/tests/src/baseservices/compilerservices/FixedAddressValueType/FixedAddressValueType.csproj @@ -0,0 +1,44 @@ + + + + + Debug + AnyCPU + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + true + BuildAndRun + true + true + + + + + + + + + False + + + + + + + + + + + + + + + + diff --git a/tests/src/baseservices/compilerservices/RuntimeHelpers/ExecuteCodeWithGuaranteedCleanup.cs b/tests/src/baseservices/compilerservices/RuntimeHelpers/ExecuteCodeWithGuaranteedCleanup.cs new file mode 100644 index 0000000..58cee3c --- /dev/null +++ b/tests/src/baseservices/compilerservices/RuntimeHelpers/ExecuteCodeWithGuaranteedCleanup.cs @@ -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. +// See the LICENSE file in the project root for more information. +// +using System; +using System.Runtime.CompilerServices; + +namespace GCD +{ + /// + /// Summary description for Class1. + /// + class GCD + { + private int _val = -2; + private int _exitcode = -1; + public GCD() {} + public int GetExitCode(){ return _exitcode;} + public void g () + { + throw new System.Exception("TryCode test"); + } + public void TryCode0 (object obj) + { + _val = (int)obj; + g(); + } + public void CleanupCode0 (object obj, bool excpThrown) + { + if(excpThrown && ((int)obj == _val)) + { + _exitcode = 100; + } + } + } + + + class GCDTest + { + /// + /// The main entry point for the application. + /// + [STAThread] + static int Main(string[] args) + { + GCD gcd = new GCD(); + RuntimeHelpers.TryCode t = new RuntimeHelpers.TryCode(gcd.TryCode0); + RuntimeHelpers.CleanupCode c = new RuntimeHelpers.CleanupCode(gcd.CleanupCode0); + int val = 21; + try + { + RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(t, c, val); + } + catch (Exception Ex) + { + + } + + return gcd.GetExitCode(); + } + } +} diff --git a/tests/src/baseservices/compilerservices/RuntimeHelpers/ExecuteCodeWithGuaranteedCleanup.csproj b/tests/src/baseservices/compilerservices/RuntimeHelpers/ExecuteCodeWithGuaranteedCleanup.csproj new file mode 100644 index 0000000..605d11b --- /dev/null +++ b/tests/src/baseservices/compilerservices/RuntimeHelpers/ExecuteCodeWithGuaranteedCleanup.csproj @@ -0,0 +1,42 @@ + + + + + Debug + AnyCPU + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + true + BuildAndRun + + + + + + + + + False + + + + + + + + + + + + + + + + diff --git a/tests/src/baseservices/compilerservices/RuntimeWrappedException/RuntimeWrappedException.cs b/tests/src/baseservices/compilerservices/RuntimeWrappedException/RuntimeWrappedException.cs new file mode 100644 index 0000000..29fb347 --- /dev/null +++ b/tests/src/baseservices/compilerservices/RuntimeWrappedException/RuntimeWrappedException.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. +// See the LICENSE file in the project root for more information. +// +using System; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.Serialization; + +class Test +{ + public static int Main(string[] args) + { + int retVal = 0; + var thrower = new StringThrowerClass(); + try + { + thrower.InstanceMethod(); + } + + catch (RuntimeWrappedException ex) + { + + if ( !ex.WrappedException.ToString().Contains("Inside StringThrower") ) + { +// Console.WriteLine("Incorrect exception and/or message. Expected RuntimeWrappedException: An object that does not derive "+ +// "from System.Exception has been wrapped in a RuntimeWrappedException.\n But actually got: " + ex.InnerException); + retVal = -1; + } + + StreamingContext ctx; + +// TODO: Expose once we have access to FormatterConverter +// var info = new SerializationInfo(typeof(RuntimeWrappedException), new FormatterConverter()); +// ex.GetObjectData(info,ctx); +// + try + { + ex.GetObjectData(null,ctx); + } + catch (ArgumentNullException ex1) + { + retVal = 100; + } + catch (Exception ex1) + { + retVal = -1; + } + + + } + catch (Exception ex) + { +// Console.WriteLine("Incorrect exception thrown. Expected RuntimeWrappedException, but actually got: " + ex); + retVal = -2; + } + + + return retVal; + + + } +} diff --git a/tests/src/baseservices/compilerservices/RuntimeWrappedException/RuntimeWrappedException.csproj b/tests/src/baseservices/compilerservices/RuntimeWrappedException/RuntimeWrappedException.csproj new file mode 100644 index 0000000..4b0c5cf --- /dev/null +++ b/tests/src/baseservices/compilerservices/RuntimeWrappedException/RuntimeWrappedException.csproj @@ -0,0 +1,45 @@ + + + + + Debug + AnyCPU + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + true + BuildAndRun + + + + + + + + + False + + + + + + + + + + + + + + + + + + + diff --git a/tests/src/baseservices/compilerservices/RuntimeWrappedException/StringThrower.il b/tests/src/baseservices/compilerservices/RuntimeWrappedException/StringThrower.il new file mode 100644 index 0000000..92c9139 --- /dev/null +++ b/tests/src/baseservices/compilerservices/RuntimeWrappedException/StringThrower.il @@ -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. +// See the LICENSE file in the project root for more information. + +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 2:0:0:0 +} + +.assembly StringThrower {} + +.class public auto ansi StringThrowerClass + extends [mscorlib]System.Object +{ + .field public static int32 intStatic + + + .method public hidebysig instance void + InstanceMethod() cil managed noinlining + { + .maxstack 8 + + ldstr "Inside StringThrower" + throw + ret + } // end of method A::methodA + + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + + .maxstack 8 + ldarg.0 + call instance void class [mscorlib]System.Object::.ctor() + ret + } // end of method Test1::.ctor + +} diff --git a/tests/src/baseservices/compilerservices/RuntimeWrappedException/StringThrower.ilproj b/tests/src/baseservices/compilerservices/RuntimeWrappedException/StringThrower.ilproj new file mode 100644 index 0000000..79667cc --- /dev/null +++ b/tests/src/baseservices/compilerservices/RuntimeWrappedException/StringThrower.ilproj @@ -0,0 +1,40 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Library + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + + + + + + + + + + + + diff --git a/tests/src/baseservices/compilerservices/modulector/moduleCctor.il b/tests/src/baseservices/compilerservices/modulector/moduleCctor.il new file mode 100644 index 0000000..06bf6ac --- /dev/null +++ b/tests/src/baseservices/compilerservices/modulector/moduleCctor.il @@ -0,0 +1,110 @@ +// 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. + +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 2:0:0:0 +} + +.assembly moduleCctor {} +.assembly extern FieldTypes +{ + .publickeytoken = (C0 30 5C 36 38 0B A4 29 ) // .0\68..) + .ver 0:0:0:0 +} + + .method private hidebysig specialname rtspecialname static + void .cctor() cil managed + { + .maxstack 8 + nop + ldsfld int32 IntHolder::val + ldc.i4.1 + add + stsfld int32 IntHolder::val +// ldstr "modCctor.txt" +// ldstr "inside .cctor" +// call void [mscorlib]System.IO.File::WriteAllText(string, +// string) + ret + } // end of method Foo::.cctor + + +// =============== CLASS MEMBERS DECLARATION =================== +.class public auto ansi beforefieldinit IntHolder + extends [mscorlib]System.Object +{ + // Fields + .field public static int32 val + + // Methods + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed + { + // Method begins at RVA 0x2050 + // Code size 8 (0x8) + .maxstack 8 + + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method IntHolder::.ctor + + .method private hidebysig specialname rtspecialname static + void .cctor () cil managed + { + // Method begins at RVA 0x2059 + // Code size 7 (0x7) + .maxstack 8 + + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 IntHolder::val + IL_0006: ret + } // end of method IntHolder::.cctor + + .method public hidebysig static + void Assign ( + int32 arg + ) cil managed + { + // Method begins at RVA 0x2078 + // Code size 8 (0x8) + .maxstack 8 + + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stsfld int32 IntHolder::val + IL_0007: ret + } // end of method IntHolder::Assign + .method public hidebysig static + void Check ( + int32 arg + ) cil managed + { + // Method begins at RVA 0x2050 + // Code size 28 (0x1c) + .maxstack 2 + .locals init ( + [0] bool + ) + + IL_0000: nop + IL_0001: ldsfld int32 IntHolder::val + IL_0006: ldarg.0 + IL_0007: ceq + IL_0009: ldc.i4.0 + IL_000a: ceq + IL_000c: stloc.0 + IL_000d: ldloc.0 + IL_000e: brfalse.s IL_001b + + IL_0010: ldstr "Mod Ctor did not functon correctly" + IL_0015: newobj instance void [mscorlib]System.Exception::.ctor(string) + IL_001a: throw + + IL_001b: ret + } // end of method IntHolder::Check +} // end of class IntHolder diff --git a/tests/src/baseservices/compilerservices/modulector/moduleCctor.ilproj b/tests/src/baseservices/compilerservices/modulector/moduleCctor.ilproj new file mode 100644 index 0000000..c846e02 --- /dev/null +++ b/tests/src/baseservices/compilerservices/modulector/moduleCctor.ilproj @@ -0,0 +1,40 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Library + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + + + + + + + + + + + + diff --git a/tests/src/baseservices/compilerservices/modulector/runmoduleconstructor.cs b/tests/src/baseservices/compilerservices/modulector/runmoduleconstructor.cs new file mode 100644 index 0000000..d1192f1 --- /dev/null +++ b/tests/src/baseservices/compilerservices/modulector/runmoduleconstructor.cs @@ -0,0 +1,38 @@ +// 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.Reflection; +using System.IO; +using System.Runtime.Loader; +using System.Runtime.CompilerServices; +using System.Globalization; + +class RuntimeHelperTest +{ + public static int Main(string[] args) + { + AssemblyLoadContext resolver0 = AssemblyLoadContext.Default; + Assembly asm0 = resolver0.LoadFromAssemblyName(new AssemblyName("moduleCctor")); + Module mod = asm0.ManifestModule; + + RuntimeHelpers.RunModuleConstructor(mod.ModuleHandle); + var oType = asm0.GetType("IntHolder",true); + MethodInfo check = oType.GetMethod("Check"); + MethodInfo assign = oType.GetMethod("Assign"); + + object[] initial = {1}; + object[] final = {100}; + + check.Invoke(null, initial); + assign.Invoke(null, final); + check.Invoke(null, final); + RuntimeHelpers.RunModuleConstructor(mod.ModuleHandle); + check.Invoke(null, final); + + + return 100; + + } +} diff --git a/tests/src/baseservices/compilerservices/modulector/runmoduleconstructor.csproj b/tests/src/baseservices/compilerservices/modulector/runmoduleconstructor.csproj new file mode 100644 index 0000000..fff05ea --- /dev/null +++ b/tests/src/baseservices/compilerservices/modulector/runmoduleconstructor.csproj @@ -0,0 +1,45 @@ + + + + + Debug + AnyCPU + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + true + BuildAndRun + + + + + + + + + False + + + + + + + + + + + + + + + + + + + diff --git a/tests/src/dir.common.props b/tests/src/dir.common.props index f1700f5..d5de579 100644 --- a/tests/src/dir.common.props +++ b/tests/src/dir.common.props @@ -40,7 +40,7 @@ $(__TestRootDir)\ $(BaseOutputPath)\$(OSPlatformConfig)\ $(BaseOutputPathWithConfig) - $(ProjectDir)\..\bin\tests\obj\$(OSPlatformConfig)\Managed + $(ProjectDir)\..\bin\tests\obj\$(OSPlatformConfig)\Managed\ $(__ManagedTestIntermediatesDir)\ <__NativeTestIntermediatesDir Condition="'$(__NativeTestIntermediatesDir)' == ''">$([System.IO.Path]::GetFullPath($(BaseOutputPathWithConfig)..\obj\$(BuildOS).$(Platform).$(Configuration)\Native\)) $(MSBuildProjectName)\ @@ -58,11 +58,6 @@ $(TestRuntimeProjectJsonDir)\project.lock.json - - - BuildAndRun - 0 - diff --git a/tests/src/dir.props b/tests/src/dir.props index 3b2754c..e8cdfd4 100644 --- a/tests/src/dir.props +++ b/tests/src/dir.props @@ -10,7 +10,6 @@ 78,162,164,168,169,219,251,252,414,429,642,649,652,675,1691,1717,1718,3001,3002,3003,3005,3008 false - BuildAndRun true $(MSBuildThisFileDirectory)TestWrappersConfig\ @@ -35,6 +34,7 @@ true win7-x64 + net45 @@ -69,6 +69,14 @@ true + + + + netcoreapp1.0 + $(DefaultTestTFM) + $(DefaultTestTFM) + + 2 @@ -77,5 +85,8 @@ $(SourceDir)Common\test_dependencies\project.json $(SourceDir)Common\test_dependencies\project.lock.json + + + .NETCoreApp,Version=v1.1 diff --git a/tests/src/dir.targets b/tests/src/dir.targets index 31d9304..64b5666 100644 --- a/tests/src/dir.targets +++ b/tests/src/dir.targets @@ -1,8 +1,23 @@ + + + SharedLibrary + BuildAndRun + 0 + + + + + <_CLRTestCompilesSource>true + <_CLRTestNeedsToRun>false + false + <_CLRTestBuildsExecutable>false + + true @@ -28,14 +43,6 @@ <_CLRTestCompilesSource>false - - - <_CLRTestCompilesSource>true - <_CLRTestNeedsToRun>false - false - <_CLRTestBuildsExecutable>false - - @@ -80,11 +87,6 @@ - - - - - diff --git a/tests/src/jit/Directed/pinvoke/pinvoke-bug.cs b/tests/src/jit/Directed/pinvoke/pinvoke-bug.cs new file mode 100644 index 0000000..2d4b5f6 --- /dev/null +++ b/tests/src/jit/Directed/pinvoke/pinvoke-bug.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. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +// Test includes an intentional unreachable return +#pragma warning disable 162 + +namespace PInvokeTest +{ + internal class Test + { + [DllImport("msvcrt", EntryPoint = "sin")] + private static extern double sin(double x); + + private static double g; + private static bool b; + + public static int Main(string[] args) + { + bool result = false; + g = 0.0; + double val = 1.0; + b = false; + try + { + Func(val); + } + catch(Exception) + { + result = (Math.Abs(g - sin(val)) < 0.0001); + } + + return (result ? 100 : -1); + } + + // An inline pinvoke in a method with float math followed by a + // throw may causes trouble for liveness models for the inline + // frame var. + static double Func(double x) + { + g = sin(x); + + // A bit of control flow to throw off rareness detection + // Also we need float in here + if (b) + { + g = 0.0; + } + + throw new Exception(); + + // Deliberately unreachable return + return g; + } + } +} + diff --git a/tests/src/jit/Directed/pinvoke/pinvoke-bug.csproj b/tests/src/jit/Directed/pinvoke/pinvoke-bug.csproj new file mode 100644 index 0000000..2f8a246 --- /dev/null +++ b/tests/src/jit/Directed/pinvoke/pinvoke-bug.csproj @@ -0,0 +1,44 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + PdbOnly + + + + + + + + + $(JitPackagesConfigFileDirectory)minimal\project.json + $(JitPackagesConfigFileDirectory)minimal\project.lock.json + + + + + \ No newline at end of file diff --git a/tests/src/performance/perflab/BlockCopyPerf.cs b/tests/src/performance/perflab/BlockCopyPerf.cs index 076d436..5259d10 100644 --- a/tests/src/performance/perflab/BlockCopyPerf.cs +++ b/tests/src/performance/perflab/BlockCopyPerf.cs @@ -5,21 +5,24 @@ using Microsoft.Xunit.Performance; using System; using Xunit; -public class BlockCopyPerf +namespace PerfLabTests { - [Benchmark(InnerIterationCount=1000000)] - [InlineData(0)] - [InlineData(10)] - [InlineData(100)] - [InlineData(1000)] - public static void CallBlockCopy(int numElements) + public class BlockCopyPerf { - byte[] bytes = new byte[numElements * 2]; - Buffer.BlockCopy(bytes, 0, bytes, numElements, numElements); + [Benchmark(InnerIterationCount = 1000000)] + [InlineData(0)] + [InlineData(10)] + [InlineData(100)] + [InlineData(1000)] + public static void CallBlockCopy(int numElements) + { + byte[] bytes = new byte[numElements * 2]; + Buffer.BlockCopy(bytes, 0, bytes, numElements, numElements); - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for(int i=0; i : IMyInterface1 { } - -public class CastingPerf -{ - public const int NUM_ARRAY_ELEMENTS = 100; - - public static int[] j; - public static int[] k; - public static Foo[] foo; - public static Foo2[] foo2; - public static Foo[] n; - public static Foo_5[] foo_5; - public static FooSVT[] svt; - public static FooORVT[] orvt; - - public static Object o; - public static Object[] o_ar; - public static Foo[] f; - public static IFoo[] ifo; - public static IFoo_5[] if_5; - - static CastingPerf() + public interface IFoo { - j = new int[NUM_ARRAY_ELEMENTS]; - for (int i = 0; i < j.Length; i++) - { - j[i] = i; - } - foo = new Foo[NUM_ARRAY_ELEMENTS]; - for (int i = 0; i < foo.Length; i++) - { - foo[i] = new Foo(); - } - foo2 = new Foo2[NUM_ARRAY_ELEMENTS]; - for (int i = 0; i < foo2.Length; i++) - { - foo2[i] = new Foo2(); - } - n = new Foo[NUM_ARRAY_ELEMENTS]; - foo_5 = new Foo_5[NUM_ARRAY_ELEMENTS]; - for (int i = 0; i < foo_5.Length; i++) - { - foo_5[i] = new Foo_5(); - } - svt = new FooSVT[NUM_ARRAY_ELEMENTS]; - orvt = new FooORVT[NUM_ARRAY_ELEMENTS]; } - [Benchmark(InnerIterationCount=100000)] - public static void ObjFooIsObj() + public interface IFoo_1 { - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - o = foo; } - [Benchmark(InnerIterationCount=100000)] - public static void ObjFooIsObj2() + public interface IFoo_2 { - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - o_ar = foo; } - [Benchmark(InnerIterationCount=100000)] - public static void ObjObjIsFoo() + public interface IFoo_3 { - o = foo; - - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - o_ar = (Object[])o; } - [Benchmark(InnerIterationCount=100000)] - public static void FooObjIsFoo() + public interface IFoo_4 { - o = foo; - - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - f = (Foo[])o; } - [Benchmark(InnerIterationCount=100000)] - public static void FooObjIsFoo2() + public interface IFoo_5 { - o_ar = foo; - - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - f = (Foo[])o_ar; } - [Benchmark(InnerIterationCount=100000)] - public static void FooObjIsNull() + // C# lays the interfaces in reverse order in metadata. So IFoo is the first and IFoo_5 is last + public class Foo : IFoo_5, IFoo_4, IFoo_3, IFoo_2, IFoo_1, IFoo { - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - o = (Foo[])n; + public int m_i; } - [Benchmark(InnerIterationCount=100000)] - public static void FooObjIsDescendant() + public class Foo_1 : Foo { - o = foo_5; - - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - f = (Foo[])o; + public int m_j; } - [Benchmark(InnerIterationCount=100000)] - public static void IFooFooIsIFoo() + public class Foo_2 : Foo_1 { - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - ifo = foo; + public int m_k; } - [Benchmark(InnerIterationCount=100000)] - public static void IFooObjIsIFoo() + public class Foo_3 : Foo_2 { - o = foo; - - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - ifo = (IFoo[])o; + public int m_l; } - [Benchmark(InnerIterationCount=100000)] - public static void IFooObjIsIFooInterAlia() + public class Foo_4 : Foo_3 { - o = foo2; - - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - if_5 = (IFoo_5[])o; + public int m_m; } - [Benchmark(InnerIterationCount=100000)] - public static void IFooObjIsDescendantOfIFoo() + public class Foo_5 : Foo_4 { - o = foo_5; - - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - ifo = (IFoo[])o; + public int m_n; } - [Benchmark(InnerIterationCount=100000)] - public static void ObjInt() + // C# lays the interfaces in reverse order in metadata. So IFoo_1 is the first and IFoo is last + public class Foo2 : IFoo, IFoo_5, IFoo_4, IFoo_3, IFoo_2, IFoo_1 { - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - o = (Object)j; + public int m_i; } - [Benchmark(InnerIterationCount=100000)] - public static void IntObj() + public struct FooSVT { - o = (Object)j; - - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - k = (int[])o; + public int m_i; + public int m_j; } - [Benchmark(InnerIterationCount=100000)] - public static void ObjScalarValueType() + public struct FooORVT { - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - o = svt; + public Object m_o; + public Foo m_f; } - [Benchmark(InnerIterationCount=100000)] - public static void ScalarValueTypeObj() + public interface IMyInterface1 { } + public interface IMyInterface2 { } + public class MyClass1 : IMyInterface1 { } + public class MyClass2 : IMyInterface2 { } + public class MyClass4 : IMyInterface1 { } + + public class CastingPerf { - o = svt; + public const int NUM_ARRAY_ELEMENTS = 100; + + public static int[] j; + public static int[] k; + public static Foo[] foo; + public static Foo2[] foo2; + public static Foo[] n; + public static Foo_5[] foo_5; + public static FooSVT[] svt; + public static FooORVT[] orvt; + + public static Object o; + public static Object[] o_ar; + public static Foo[] f; + public static IFoo[] ifo; + public static IFoo_5[] if_5; + + static CastingPerf() + { + j = new int[NUM_ARRAY_ELEMENTS]; + for (int i = 0; i < j.Length; i++) + { + j[i] = i; + } + foo = new Foo[NUM_ARRAY_ELEMENTS]; + for (int i = 0; i < foo.Length; i++) + { + foo[i] = new Foo(); + } + foo2 = new Foo2[NUM_ARRAY_ELEMENTS]; + for (int i = 0; i < foo2.Length; i++) + { + foo2[i] = new Foo2(); + } + n = new Foo[NUM_ARRAY_ELEMENTS]; + foo_5 = new Foo_5[NUM_ARRAY_ELEMENTS]; + for (int i = 0; i < foo_5.Length; i++) + { + foo_5[i] = new Foo_5(); + } + svt = new FooSVT[NUM_ARRAY_ELEMENTS]; + orvt = new FooORVT[NUM_ARRAY_ELEMENTS]; + } - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - svt = (FooSVT[])o; - } + [Benchmark(InnerIterationCount = 100000)] + public static void ObjFooIsObj() + { + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + o = foo; + } - [Benchmark(InnerIterationCount=100000)] - public static void ObjObjrefValueType() - { - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - o = (Object)orvt; - } + [Benchmark(InnerIterationCount = 100000)] + public static void ObjFooIsObj2() + { + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + o_ar = foo; + } - [Benchmark(InnerIterationCount=100000)] - public static void ObjrefValueTypeObj() - { - o = (Object)orvt; + [Benchmark(InnerIterationCount = 100000)] + public static void ObjObjIsFoo() + { + o = foo; - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - orvt = (FooORVT[])o; - } + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + o_ar = (Object[])o; + } - [Benchmark(InnerIterationCount=100000)] - public static void FooObjCastIfIsa() - { - o = foo; + [Benchmark(InnerIterationCount = 100000)] + public static void FooObjIsFoo() + { + o = foo; - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - if (o is Foo[]) + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) f = (Foo[])o; - } + } - [Benchmark(InnerIterationCount=100000)] - public static bool CheckObjIsInterfaceYes() - { - bool res = false; - Object obj = new MyClass1(); - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - res = obj is IMyInterface1; - return res; - } + [Benchmark(InnerIterationCount = 100000)] + public static void FooObjIsFoo2() + { + o_ar = foo; - [Benchmark(InnerIterationCount=100000)] - public static bool CheckObjIsInterfaceNo() - { - bool res = false; - Object obj = new MyClass2(); - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - res = obj is IMyInterface1; - return res; - } + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + f = (Foo[])o_ar; + } - [Benchmark(InnerIterationCount=100000)] - public static bool CheckIsInstAnyIsInterfaceYes() - { - bool res = false; - Object obj = new MyClass4>(); - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - res = obj is IMyInterface1; - return res; - } + [Benchmark(InnerIterationCount = 100000)] + public static void FooObjIsNull() + { + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + o = (Foo[])n; + } - [Benchmark(InnerIterationCount=100000)] - public static bool CheckIsInstAnyIsInterfaceNo() - { - bool res = false; - Object obj = new MyClass4>(); - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - res = obj is IMyInterface2; - return res; - } + [Benchmark(InnerIterationCount = 100000)] + public static void FooObjIsDescendant() + { + o = foo_5; - [Benchmark(InnerIterationCount=100000)] - public static bool CheckArrayIsInterfaceYes() - { - bool res = false; - Object[] arr = new MyClass1[5]; - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - res = arr is IMyInterface1[]; - return res; - } + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + f = (Foo[])o; + } - [Benchmark(InnerIterationCount=100000)] - public static bool CheckArrayIsInterfaceNo() - { - bool res = false; - Object[] arr = new MyClass2[5]; - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - res = arr is IMyInterface1[]; - return res; + [Benchmark(InnerIterationCount = 100000)] + public static void IFooFooIsIFoo() + { + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + ifo = foo; + } + + [Benchmark(InnerIterationCount = 100000)] + public static void IFooObjIsIFoo() + { + o = foo; + + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + ifo = (IFoo[])o; + } + + [Benchmark(InnerIterationCount = 100000)] + public static void IFooObjIsIFooInterAlia() + { + o = foo2; + + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + if_5 = (IFoo_5[])o; + } + + [Benchmark(InnerIterationCount = 100000)] + public static void IFooObjIsDescendantOfIFoo() + { + o = foo_5; + + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + ifo = (IFoo[])o; + } + + [Benchmark(InnerIterationCount = 100000)] + public static void ObjInt() + { + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + o = (Object)j; + } + + [Benchmark(InnerIterationCount = 100000)] + public static void IntObj() + { + o = (Object)j; + + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + k = (int[])o; + } + + [Benchmark(InnerIterationCount = 100000)] + public static void ObjScalarValueType() + { + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + o = svt; + } + + [Benchmark(InnerIterationCount = 100000)] + public static void ScalarValueTypeObj() + { + o = svt; + + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + svt = (FooSVT[])o; + } + + [Benchmark(InnerIterationCount = 100000)] + public static void ObjObjrefValueType() + { + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + o = (Object)orvt; + } + + [Benchmark(InnerIterationCount = 100000)] + public static void ObjrefValueTypeObj() + { + o = (Object)orvt; + + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + orvt = (FooORVT[])o; + } + + [Benchmark(InnerIterationCount = 100000)] + public static void FooObjCastIfIsa() + { + o = foo; + + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + if (o is Foo[]) + f = (Foo[])o; + } + + [Benchmark(InnerIterationCount = 100000)] + public static bool CheckObjIsInterfaceYes() + { + bool res = false; + Object obj = new MyClass1(); + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + res = obj is IMyInterface1; + return res; + } + + [Benchmark(InnerIterationCount = 100000)] + public static bool CheckObjIsInterfaceNo() + { + bool res = false; + Object obj = new MyClass2(); + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + res = obj is IMyInterface1; + return res; + } + + [Benchmark(InnerIterationCount = 100000)] + public static bool CheckIsInstAnyIsInterfaceYes() + { + bool res = false; + Object obj = new MyClass4>(); + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + res = obj is IMyInterface1; + return res; + } + + [Benchmark(InnerIterationCount = 100000)] + public static bool CheckIsInstAnyIsInterfaceNo() + { + bool res = false; + Object obj = new MyClass4>(); + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + res = obj is IMyInterface2; + return res; + } + + [Benchmark(InnerIterationCount = 100000)] + public static bool CheckArrayIsInterfaceYes() + { + bool res = false; + Object[] arr = new MyClass1[5]; + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + res = arr is IMyInterface1[]; + return res; + } + + [Benchmark(InnerIterationCount = 100000)] + public static bool CheckArrayIsInterfaceNo() + { + bool res = false; + Object[] arr = new MyClass2[5]; + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + res = arr is IMyInterface1[]; + return res; + } } -} +} \ No newline at end of file diff --git a/tests/src/performance/perflab/CastingPerf2.cs b/tests/src/performance/perflab/CastingPerf2.cs index 1f874a5..82131ba 100644 --- a/tests/src/performance/perflab/CastingPerf2.cs +++ b/tests/src/performance/perflab/CastingPerf2.cs @@ -2,10 +2,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; -using CastingPerf2; +using PerfLabTests.CastingPerf2; using Microsoft.Xunit.Performance; -namespace CastingPerf2 +namespace PerfLabTests.CastingPerf2 { public interface IFoo { @@ -95,7 +95,7 @@ namespace CastingPerf2 public static IFoo ifo, ifo1, ifo2, ifo3, ifo4, ifo5, ifo6, ifo7, ifo8, ifo9; public static IFoo_5 if_0, if_1, if_2, if_3, if_4, if_5, if_6, if_7, if_8, if_9; - [Benchmark(InnerIterationCount=200000)] + [Benchmark(InnerIterationCount = 200000)] public static void ObjFooIsObj() { foreach (var iteration in Benchmark.Iterations) @@ -104,7 +104,7 @@ namespace CastingPerf2 o = foo; } - [Benchmark(InnerIterationCount=200000)] + [Benchmark(InnerIterationCount = 200000)] public static void FooObjIsFoo() { o = foo; @@ -115,7 +115,7 @@ namespace CastingPerf2 f = (Foo)o; } - [Benchmark(InnerIterationCount=200000)] + [Benchmark(InnerIterationCount = 200000)] public static void FooObjIsNull() { foreach (var iteration in Benchmark.Iterations) @@ -124,7 +124,7 @@ namespace CastingPerf2 o = (Foo)n; } - [Benchmark(InnerIterationCount=100000)] + [Benchmark(InnerIterationCount = 100000)] public static void FooObjIsDescendant() { o = foo_5; @@ -135,7 +135,7 @@ namespace CastingPerf2 f = (Foo)o; } - [Benchmark(InnerIterationCount=200000)] + [Benchmark(InnerIterationCount = 200000)] public static void IFooFooIsIFoo() { foreach (var iteration in Benchmark.Iterations) @@ -144,7 +144,7 @@ namespace CastingPerf2 ifo = foo; } - [Benchmark(InnerIterationCount=100000)] + [Benchmark(InnerIterationCount = 100000)] public static void IFooObjIsIFoo() { o = foo; @@ -155,7 +155,7 @@ namespace CastingPerf2 ifo = (IFoo)o; } - [Benchmark(InnerIterationCount=100000)] + [Benchmark(InnerIterationCount = 100000)] public static void IFooObjIsIFooInterAlia() { o = foo2; @@ -166,7 +166,7 @@ namespace CastingPerf2 if_0 = (IFoo_5)o; } - [Benchmark(InnerIterationCount=100000)] + [Benchmark(InnerIterationCount = 100000)] public static void IFooObjIsDescendantOfIFoo() { o = foo_5; @@ -177,7 +177,7 @@ namespace CastingPerf2 ifo = (IFoo)o; } - [Benchmark(InnerIterationCount=100000)] + [Benchmark(InnerIterationCount = 100000)] public static void ObjInt() { foreach (var iteration in Benchmark.Iterations) @@ -186,7 +186,7 @@ namespace CastingPerf2 o = (Object)j; } - [Benchmark(InnerIterationCount=200000)] + [Benchmark(InnerIterationCount = 200000)] public static void IntObj() { o = (Object)1; @@ -197,7 +197,7 @@ namespace CastingPerf2 j = (int)o; } - [Benchmark(InnerIterationCount=100000)] + [Benchmark(InnerIterationCount = 100000)] public static void ObjScalarValueType() { foreach (var iteration in Benchmark.Iterations) @@ -206,7 +206,7 @@ namespace CastingPerf2 o = svt; } - [Benchmark(InnerIterationCount=300000)] + [Benchmark(InnerIterationCount = 300000)] public static void ScalarValueTypeObj() { o = svt; @@ -217,7 +217,7 @@ namespace CastingPerf2 svt = (FooSVT)o; } - [Benchmark(InnerIterationCount=100000)] + [Benchmark(InnerIterationCount = 100000)] public static void ObjObjrefValueType() { foreach (var iteration in Benchmark.Iterations) @@ -226,7 +226,7 @@ namespace CastingPerf2 o = (Object)orvt; } - [Benchmark(InnerIterationCount=200000)] + [Benchmark(InnerIterationCount = 200000)] public static void ObjrefValueTypeObj() { o = (Object)orvt; @@ -237,7 +237,7 @@ namespace CastingPerf2 orvt = (FooORVT)o; } - [Benchmark(InnerIterationCount=100000)] + [Benchmark(InnerIterationCount = 100000)] public static void FooObjCastIfIsa() { o = foo; diff --git a/tests/src/performance/perflab/DelegatePerf.cs b/tests/src/performance/perflab/DelegatePerf.cs index abc311a..61f12a2 100644 --- a/tests/src/performance/perflab/DelegatePerf.cs +++ b/tests/src/performance/perflab/DelegatePerf.cs @@ -5,92 +5,96 @@ using Microsoft.Xunit.Performance; using System; using Xunit; -internal delegate long DelegateLong(Object obj, long x, long y); -internal delegate void MultiDelegate(Object obj, long x, long y); - -internal delegate int SerializeDelegate(); - -public class DelegatePerf +namespace PerfLabTests { - [Benchmark(InnerIterationCount=200000)] - public void DelegateInvoke() - { - DelegateLong dl = new DelegateLong(this.Invocable1); - Object obj = new Object(); - long ret = dl(obj, 100, 100); + internal delegate long DelegateLong(Object obj, long x, long y); + internal delegate void MultiDelegate(Object obj, long x, long y); - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - ret = dl(obj, 100, 100); - } + internal delegate int SerializeDelegate(); - [Benchmark(InnerIterationCount=1000)] - public void MulticastDelegateCombineInvoke() + public class DelegatePerf { - MultiDelegate md = null; - Object obj = new Object(); + [Benchmark(InnerIterationCount = 200000)] + public void DelegateInvoke() + { + DelegateLong dl = new DelegateLong(this.Invocable1); + Object obj = new Object(); + + long ret = dl(obj, 100, 100); - foreach (var iteration in Benchmark.Iterations) + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + ret = dl(obj, 100, 100); + } + + [Benchmark(InnerIterationCount = 1000)] + public void MulticastDelegateCombineInvoke() { - MultiDelegate md1 = new MultiDelegate(this.Invocable2); - MultiDelegate md2 = new MultiDelegate(this.Invocable2); - MultiDelegate md3 = new MultiDelegate(this.Invocable2); - MultiDelegate md4 = new MultiDelegate(this.Invocable2); - MultiDelegate md5 = new MultiDelegate(this.Invocable2); - MultiDelegate md6 = new MultiDelegate(this.Invocable2); - MultiDelegate md7 = new MultiDelegate(this.Invocable2); - MultiDelegate md8 = new MultiDelegate(this.Invocable2); - MultiDelegate md9 = new MultiDelegate(this.Invocable2); - MultiDelegate md10 = new MultiDelegate(this.Invocable2); - - using (iteration.StartMeasurement()) + MultiDelegate md = null; + Object obj = new Object(); + + foreach (var iteration in Benchmark.Iterations) { - for (int i = 0; i < Benchmark.InnerIterationCount; i++) + MultiDelegate md1 = new MultiDelegate(this.Invocable2); + MultiDelegate md2 = new MultiDelegate(this.Invocable2); + MultiDelegate md3 = new MultiDelegate(this.Invocable2); + MultiDelegate md4 = new MultiDelegate(this.Invocable2); + MultiDelegate md5 = new MultiDelegate(this.Invocable2); + MultiDelegate md6 = new MultiDelegate(this.Invocable2); + MultiDelegate md7 = new MultiDelegate(this.Invocable2); + MultiDelegate md8 = new MultiDelegate(this.Invocable2); + MultiDelegate md9 = new MultiDelegate(this.Invocable2); + MultiDelegate md10 = new MultiDelegate(this.Invocable2); + + using (iteration.StartMeasurement()) { - md = (MultiDelegate)Delegate.Combine(md1, md); - md = (MultiDelegate)Delegate.Combine(md2, md); - md = (MultiDelegate)Delegate.Combine(md3, md); - md = (MultiDelegate)Delegate.Combine(md4, md); - md = (MultiDelegate)Delegate.Combine(md5, md); - md = (MultiDelegate)Delegate.Combine(md6, md); - md = (MultiDelegate)Delegate.Combine(md7, md); - md = (MultiDelegate)Delegate.Combine(md8, md); - md = (MultiDelegate)Delegate.Combine(md9, md); - md = (MultiDelegate)Delegate.Combine(md10, md); + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + md = (MultiDelegate)Delegate.Combine(md1, md); + md = (MultiDelegate)Delegate.Combine(md2, md); + md = (MultiDelegate)Delegate.Combine(md3, md); + md = (MultiDelegate)Delegate.Combine(md4, md); + md = (MultiDelegate)Delegate.Combine(md5, md); + md = (MultiDelegate)Delegate.Combine(md6, md); + md = (MultiDelegate)Delegate.Combine(md7, md); + md = (MultiDelegate)Delegate.Combine(md8, md); + md = (MultiDelegate)Delegate.Combine(md9, md); + md = (MultiDelegate)Delegate.Combine(md10, md); + } } } - } - md(obj, 100, 100); - } + md(obj, 100, 100); + } - [Benchmark(InnerIterationCount=10000)] - [InlineData(100)] - [InlineData(1000)] - public void MulticastDelegateInvoke(int length) - { - MultiDelegate md = null; - Object obj = new Object(); + [Benchmark(InnerIterationCount = 10000)] + [InlineData(100)] + [InlineData(1000)] + public void MulticastDelegateInvoke(int length) + { + MultiDelegate md = null; + Object obj = new Object(); - for (long i = 0; i < length; i++) - md = (MultiDelegate)Delegate.Combine(new MultiDelegate(this.Invocable2), md); + for (long i = 0; i < length; i++) + md = (MultiDelegate)Delegate.Combine(new MultiDelegate(this.Invocable2), md); - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - md(obj, 100, 100); - } + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + md(obj, 100, 100); + } - internal virtual long Invocable1(Object obj, long x, long y) - { - long i = x + y; - return x; - } + internal virtual long Invocable1(Object obj, long x, long y) + { + long i = x + y; + return x; + } - internal virtual void Invocable2(Object obj, long x, long y) - { - long i = x + y; + internal virtual void Invocable2(Object obj, long x, long y) + { + long i = x + y; + } } } diff --git a/tests/src/performance/perflab/EnumPerf.cs b/tests/src/performance/perflab/EnumPerf.cs index bf8d89b..1e3a493 100644 --- a/tests/src/performance/perflab/EnumPerf.cs +++ b/tests/src/performance/perflab/EnumPerf.cs @@ -6,71 +6,74 @@ using System; using System.Reflection; using Xunit; -public enum Color +namespace PerfLabTests { - Black, - White, - Red, - Brown, - Yellow, - Purple, - Orange -} - -public class EnumPerf -{ - [Benchmark(InnerIterationCount=300000)] - [InlineData(Color.Red)] - public static void EnumCompareTo(Color color) + public enum Color { - Color white = Color.White; - - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - color.CompareTo(white); + Black, + White, + Red, + Brown, + Yellow, + Purple, + Orange } - [Benchmark(InnerIterationCount=300000)] - public static Type ObjectGetType() + public class EnumPerf { - Type tmp = null; - Color black = Color.Black; + [Benchmark(InnerIterationCount = 300000)] + [InlineData(Color.Red)] + public static void EnumCompareTo(Color color) + { + Color white = Color.White; - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - tmp = black.GetType(); + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + color.CompareTo(white); + } - return tmp; - } + [Benchmark(InnerIterationCount = 300000)] + public static Type ObjectGetType() + { + Type tmp = null; + Color black = Color.Black; - [Benchmark(InnerIterationCount=300000)] - public static Type ObjectGetTypeNoBoxing() - { - Type tmp = null; - object black = Color.Black; + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + tmp = black.GetType(); - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - tmp = black.GetType(); + return tmp; + } - return tmp; - } + [Benchmark(InnerIterationCount = 300000)] + public static Type ObjectGetTypeNoBoxing() + { + Type tmp = null; + object black = Color.Black; - [Benchmark(InnerIterationCount=300000)] - public static bool EnumEquals() - { - Color black = Color.Black; - Color white = Color.White; - bool tmp = false; + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + tmp = black.GetType(); + + return tmp; + } + + [Benchmark(InnerIterationCount = 300000)] + public static bool EnumEquals() + { + Color black = Color.Black; + Color white = Color.White; + bool tmp = false; - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - tmp = black.Equals(white); + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + tmp = black.Equals(white); - return tmp; + return tmp; + } } } diff --git a/tests/src/performance/perflab/LowLevelPerf.cs b/tests/src/performance/perflab/LowLevelPerf.cs index 30c6734..a1f1a40 100644 --- a/tests/src/performance/perflab/LowLevelPerf.cs +++ b/tests/src/performance/perflab/LowLevelPerf.cs @@ -7,796 +7,799 @@ using System.Collections.Generic; using System.Threading; using System.Runtime.CompilerServices; -public class LowLevelPerf +namespace PerfLabTests { - [Benchmark(InnerIterationCount=100000)] - public static void EmptyStaticFunction() + public class LowLevelPerf { - foreach (var iteration in Benchmark.Iterations) + [Benchmark(InnerIterationCount = 100000)] + public static void EmptyStaticFunction() { - using (iteration.StartMeasurement()) + foreach (var iteration in Benchmark.Iterations) { - for (int i = 0; i < Benchmark.InnerIterationCount; i++) + using (iteration.StartMeasurement()) { - Class.EmptyStaticFunction(); - Class.EmptyStaticFunction(); - Class.EmptyStaticFunction(); - Class.EmptyStaticFunction(); - Class.EmptyStaticFunction(); - Class.EmptyStaticFunction(); - Class.EmptyStaticFunction(); - Class.EmptyStaticFunction(); - Class.EmptyStaticFunction(); - Class.EmptyStaticFunction(); + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + Class.EmptyStaticFunction(); + Class.EmptyStaticFunction(); + Class.EmptyStaticFunction(); + Class.EmptyStaticFunction(); + Class.EmptyStaticFunction(); + Class.EmptyStaticFunction(); + Class.EmptyStaticFunction(); + Class.EmptyStaticFunction(); + Class.EmptyStaticFunction(); + Class.EmptyStaticFunction(); + } } } } - } - [Benchmark(InnerIterationCount=100000)] - public static void EmptyStaticFunction5Arg() - { - foreach (var iteration in Benchmark.Iterations) + [Benchmark(InnerIterationCount = 100000)] + public static void EmptyStaticFunction5Arg() { - using (iteration.StartMeasurement()) + foreach (var iteration in Benchmark.Iterations) { - for (int i = 0; i < Benchmark.InnerIterationCount; i++) + using (iteration.StartMeasurement()) { - Class.EmptyStaticFunction5Arg(1, 2, 3, 4, 5); - Class.EmptyStaticFunction5Arg(1, 2, 3, 4, 5); - Class.EmptyStaticFunction5Arg(1, 2, 3, 4, 5); - Class.EmptyStaticFunction5Arg(1, 2, 3, 4, 5); - Class.EmptyStaticFunction5Arg(1, 2, 3, 4, 5); - Class.EmptyStaticFunction5Arg(1, 2, 3, 4, 5); - Class.EmptyStaticFunction5Arg(1, 2, 3, 4, 5); - Class.EmptyStaticFunction5Arg(1, 2, 3, 4, 5); - Class.EmptyStaticFunction5Arg(1, 2, 3, 4, 5); - Class.EmptyStaticFunction5Arg(1, 2, 3, 4, 5); + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + Class.EmptyStaticFunction5Arg(1, 2, 3, 4, 5); + Class.EmptyStaticFunction5Arg(1, 2, 3, 4, 5); + Class.EmptyStaticFunction5Arg(1, 2, 3, 4, 5); + Class.EmptyStaticFunction5Arg(1, 2, 3, 4, 5); + Class.EmptyStaticFunction5Arg(1, 2, 3, 4, 5); + Class.EmptyStaticFunction5Arg(1, 2, 3, 4, 5); + Class.EmptyStaticFunction5Arg(1, 2, 3, 4, 5); + Class.EmptyStaticFunction5Arg(1, 2, 3, 4, 5); + Class.EmptyStaticFunction5Arg(1, 2, 3, 4, 5); + Class.EmptyStaticFunction5Arg(1, 2, 3, 4, 5); + } } } } - } - - [Benchmark(InnerIterationCount=100000)] - public static void EmptyInstanceFunction() - { - Class aClass = new Class(); - foreach (var iteration in Benchmark.Iterations) + [Benchmark(InnerIterationCount = 100000)] + public static void EmptyInstanceFunction() { - using (iteration.StartMeasurement()) + Class aClass = new Class(); + + foreach (var iteration in Benchmark.Iterations) { - for (int i = 0; i < Benchmark.InnerIterationCount; i++) + using (iteration.StartMeasurement()) { - aClass.EmptyInstanceFunction(); - aClass.EmptyInstanceFunction(); - aClass.EmptyInstanceFunction(); - aClass.EmptyInstanceFunction(); - aClass.EmptyInstanceFunction(); - aClass.EmptyInstanceFunction(); - aClass.EmptyInstanceFunction(); - aClass.EmptyInstanceFunction(); - aClass.EmptyInstanceFunction(); - aClass.EmptyInstanceFunction(); + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + aClass.EmptyInstanceFunction(); + aClass.EmptyInstanceFunction(); + aClass.EmptyInstanceFunction(); + aClass.EmptyInstanceFunction(); + aClass.EmptyInstanceFunction(); + aClass.EmptyInstanceFunction(); + aClass.EmptyInstanceFunction(); + aClass.EmptyInstanceFunction(); + aClass.EmptyInstanceFunction(); + aClass.EmptyInstanceFunction(); + } } } } - } - [Benchmark(InnerIterationCount=100000)] - public static void InterfaceInterfaceMethod() - { - AnInterface aInterface = new Class(); - - foreach (var iteration in Benchmark.Iterations) + [Benchmark(InnerIterationCount = 100000)] + public static void InterfaceInterfaceMethod() { - using (iteration.StartMeasurement()) + AnInterface aInterface = new Class(); + + foreach (var iteration in Benchmark.Iterations) { - for (int i = 0; i < Benchmark.InnerIterationCount; i++) + using (iteration.StartMeasurement()) { - CallInterfaceMethod(aInterface); - CallInterfaceMethod(aInterface); - CallInterfaceMethod(aInterface); - CallInterfaceMethod(aInterface); - CallInterfaceMethod(aInterface); - CallInterfaceMethod(aInterface); - CallInterfaceMethod(aInterface); - CallInterfaceMethod(aInterface); - CallInterfaceMethod(aInterface); - CallInterfaceMethod(aInterface); + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + CallInterfaceMethod(aInterface); + CallInterfaceMethod(aInterface); + CallInterfaceMethod(aInterface); + CallInterfaceMethod(aInterface); + CallInterfaceMethod(aInterface); + CallInterfaceMethod(aInterface); + CallInterfaceMethod(aInterface); + CallInterfaceMethod(aInterface); + CallInterfaceMethod(aInterface); + CallInterfaceMethod(aInterface); + } } } } - } - [MethodImpl(MethodImplOptions.NoInlining)] - private static void CallInterfaceMethod(AnInterface aInterface) - { - aInterface.InterfaceMethod(); - } - - [Benchmark(InnerIterationCount=100000)] - public static void InterfaceInterfaceMethodLongHierarchy() - { - AnInterface aInterface = new LongHierarchyChildClass(); - - //generate all the not-used call site first - CallInterfaceMethod(new LongHierarchyClass1()); - CallInterfaceMethod(new LongHierarchyClass2()); - CallInterfaceMethod(new LongHierarchyClass3()); - CallInterfaceMethod(new LongHierarchyClass4()); - CallInterfaceMethod(new LongHierarchyClass5()); - CallInterfaceMethod(new LongHierarchyClass6()); - CallInterfaceMethod(new LongHierarchyClass7()); - CallInterfaceMethod(new LongHierarchyClass8()); - CallInterfaceMethod(new LongHierarchyClass9()); - CallInterfaceMethod(new LongHierarchyClass11()); - CallInterfaceMethod(new LongHierarchyClass12()); - - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - CallInterfaceMethod(aInterface); - } + [MethodImpl(MethodImplOptions.NoInlining)] + private static void CallInterfaceMethod(AnInterface aInterface) + { + aInterface.InterfaceMethod(); + } - [Benchmark(InnerIterationCount=100000)] - public static void InterfaceInterfaceMethodSwitchCallType() - { - AnInterface aInterface = new LongHierarchyChildClass(); - AnInterface aInterface1 = new LongHierarchyClass1(); + [Benchmark(InnerIterationCount = 100000)] + public static void InterfaceInterfaceMethodLongHierarchy() + { + AnInterface aInterface = new LongHierarchyChildClass(); + + //generate all the not-used call site first + CallInterfaceMethod(new LongHierarchyClass1()); + CallInterfaceMethod(new LongHierarchyClass2()); + CallInterfaceMethod(new LongHierarchyClass3()); + CallInterfaceMethod(new LongHierarchyClass4()); + CallInterfaceMethod(new LongHierarchyClass5()); + CallInterfaceMethod(new LongHierarchyClass6()); + CallInterfaceMethod(new LongHierarchyClass7()); + CallInterfaceMethod(new LongHierarchyClass8()); + CallInterfaceMethod(new LongHierarchyClass9()); + CallInterfaceMethod(new LongHierarchyClass11()); + CallInterfaceMethod(new LongHierarchyClass12()); + + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + CallInterfaceMethod(aInterface); + } - foreach (var iteration in Benchmark.Iterations) + [Benchmark(InnerIterationCount = 100000)] + public static void InterfaceInterfaceMethodSwitchCallType() { - using (iteration.StartMeasurement()) + AnInterface aInterface = new LongHierarchyChildClass(); + AnInterface aInterface1 = new LongHierarchyClass1(); + + foreach (var iteration in Benchmark.Iterations) { - for (int i = 0; i < Benchmark.InnerIterationCount; i++) + using (iteration.StartMeasurement()) { - CallInterfaceMethod(aInterface); - CallInterfaceMethod(aInterface1); + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + CallInterfaceMethod(aInterface); + CallInterfaceMethod(aInterface1); + } } } } - } - [Benchmark(InnerIterationCount=100000)] - public static int ClassVirtualMethod() - { - SuperClass aClass = new Class(); + [Benchmark(InnerIterationCount = 100000)] + public static int ClassVirtualMethod() + { + SuperClass aClass = new Class(); - int x = 0; - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - x = aClass.VirtualMethod(); + int x = 0; + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + x = aClass.VirtualMethod(); - return x; - } + return x; + } - [Benchmark(InnerIterationCount=100000)] - public static void SealedClassInterfaceMethod() - { - SealedClass aSealedClass = new SealedClass(); + [Benchmark(InnerIterationCount = 100000)] + public static void SealedClassInterfaceMethod() + { + SealedClass aSealedClass = new SealedClass(); - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - aSealedClass.InterfaceMethod(); - } + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + aSealedClass.InterfaceMethod(); + } - [Benchmark(InnerIterationCount=100000)] - public static void StructWithInterfaceInterfaceMethod() - { - StructWithInterface aStructWithInterface = new StructWithInterface(); + [Benchmark(InnerIterationCount = 100000)] + public static void StructWithInterfaceInterfaceMethod() + { + StructWithInterface aStructWithInterface = new StructWithInterface(); - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - aStructWithInterface.InterfaceMethod(); - } + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + aStructWithInterface.InterfaceMethod(); + } - [Benchmark(InnerIterationCount=100000)] - public static void StaticIntPlus() - { - Class aClass = new Class(); + [Benchmark(InnerIterationCount = 100000)] + public static void StaticIntPlus() + { + Class aClass = new Class(); - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - Class.aStaticInt += 1; - } + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + Class.aStaticInt += 1; + } - [Benchmark(InnerIterationCount=100000)] - public static bool ObjectStringIsString() - { - object aObjectString = "aString1"; - bool b = false; + [Benchmark(InnerIterationCount = 100000)] + public static bool ObjectStringIsString() + { + object aObjectString = "aString1"; + bool b = false; - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - b = aObjectString is String; + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + b = aObjectString is String; - return b; - } + return b; + } - [Benchmark(InnerIterationCount=100000)] - public static void NewDelegateClassEmptyInstanceFn() - { - Class aClass = new Class(); - MyDelegate aMyDelegate; + [Benchmark(InnerIterationCount = 100000)] + public static void NewDelegateClassEmptyInstanceFn() + { + Class aClass = new Class(); + MyDelegate aMyDelegate; - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - aMyDelegate = new MyDelegate(aClass.EmptyInstanceFunction); - } + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + aMyDelegate = new MyDelegate(aClass.EmptyInstanceFunction); + } - [Benchmark(InnerIterationCount=100000)] - public static void NewDelegateClassEmptyStaticFn() - { - Class aClass = new Class(); - MyDelegate aMyDelegate; + [Benchmark(InnerIterationCount = 100000)] + public static void NewDelegateClassEmptyStaticFn() + { + Class aClass = new Class(); + MyDelegate aMyDelegate; - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - aMyDelegate = new MyDelegate(Class.EmptyStaticFunction); - } + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + aMyDelegate = new MyDelegate(Class.EmptyStaticFunction); + } - [Benchmark(InnerIterationCount=100000)] - public static void InstanceDelegate() - { - Class aClass = new Class(); - MyDelegate aInstanceDelegate = new MyDelegate(aClass.EmptyInstanceFunction); + [Benchmark(InnerIterationCount = 100000)] + public static void InstanceDelegate() + { + Class aClass = new Class(); + MyDelegate aInstanceDelegate = new MyDelegate(aClass.EmptyInstanceFunction); - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - aInstanceDelegate(); - } + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + aInstanceDelegate(); + } - [Benchmark(InnerIterationCount=100000)] - public static void StaticDelegate() - { - Class aClass = new Class(); - MyDelegate aStaticDelegate = new MyDelegate(Class.EmptyStaticFunction); + [Benchmark(InnerIterationCount = 100000)] + public static void StaticDelegate() + { + Class aClass = new Class(); + MyDelegate aStaticDelegate = new MyDelegate(Class.EmptyStaticFunction); - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - aStaticDelegate(); - } + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + aStaticDelegate(); + } - [Benchmark(InnerIterationCount=100000)] - public static void MeasureEvents() - { - Class aClass = new Class(); - aClass.AnEvent += new MyDelegate(aClass.EmptyInstanceFunction); + [Benchmark(InnerIterationCount = 100000)] + public static void MeasureEvents() + { + Class aClass = new Class(); + aClass.AnEvent += new MyDelegate(aClass.EmptyInstanceFunction); - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - aClass.MeasureFire100(); - } + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + aClass.MeasureFire100(); + } - [Benchmark(InnerIterationCount=100000)] - public static void GenericClassWithIntGenericInstanceField() - { - GenericClass aGenericClassWithInt = new GenericClass(); + [Benchmark(InnerIterationCount = 100000)] + public static void GenericClassWithIntGenericInstanceField() + { + GenericClass aGenericClassWithInt = new GenericClass(); - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - aGenericClassWithInt.aGenericInstanceFieldT = 1; - } + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + aGenericClassWithInt.aGenericInstanceFieldT = 1; + } - [Benchmark(InnerIterationCount=100000)] - public static void GenericClassGenericStaticField() - { - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - GenericClass.aGenericStaticFieldT = 1; - } + [Benchmark(InnerIterationCount = 100000)] + public static void GenericClassGenericStaticField() + { + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + GenericClass.aGenericStaticFieldT = 1; + } - [Benchmark(InnerIterationCount=100000)] - public static int GenericClassGenericInstanceMethod() - { - GenericClass aGenericClassWithInt = new GenericClass(); + [Benchmark(InnerIterationCount = 100000)] + public static int GenericClassGenericInstanceMethod() + { + GenericClass aGenericClassWithInt = new GenericClass(); - int x = 0; - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - x = aGenericClassWithInt.ClassGenericInstanceMethod(); + int x = 0; + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + x = aGenericClassWithInt.ClassGenericInstanceMethod(); - return x; - } + return x; + } - [Benchmark(InnerIterationCount=100000)] - public static int GenericClassGenericStaticMethod() - { - int x = 0; - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - x = GenericClass.ClassGenericStaticMethod(); + [Benchmark(InnerIterationCount = 100000)] + public static int GenericClassGenericStaticMethod() + { + int x = 0; + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + x = GenericClass.ClassGenericStaticMethod(); - return x; - } + return x; + } - [Benchmark(InnerIterationCount=100000)] - public static int GenericGenericMethod() - { - // Warmup - int x = 0; - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - x = Class.GenericMethod(); - - return x; - } + [Benchmark(InnerIterationCount = 100000)] + public static int GenericGenericMethod() + { + // Warmup + int x = 0; + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + x = Class.GenericMethod(); + + return x; + } - [Benchmark(InnerIterationCount=100000)] - public static void GenericClassWithSTringGenericInstanceMethod() - { - GenericClass aGenericClassWithString = new GenericClass(); - string aString = "foo"; + [Benchmark(InnerIterationCount = 100000)] + public static void GenericClassWithSTringGenericInstanceMethod() + { + GenericClass aGenericClassWithString = new GenericClass(); + string aString = "foo"; - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - aGenericClassWithString.aGenericInstanceFieldT = aString; - } + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + aGenericClassWithString.aGenericInstanceFieldT = aString; + } - [Benchmark(InnerIterationCount=100000)] - public static int ForeachOverList100Elements() - { - List iList = new List(); - for (int i = 0; i < 100; i++) - iList.Add(i); - - int iResult = 0; - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - foreach (int j in iList) - iResult = j; - - return iResult; - } + [Benchmark(InnerIterationCount = 100000)] + public static int ForeachOverList100Elements() + { + List iList = new List(); + for (int i = 0; i < 100; i++) + iList.Add(i); + + int iResult = 0; + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + foreach (int j in iList) + iResult = j; + + return iResult; + } - [Benchmark(InnerIterationCount=100000)] - public static Type TypeReflectionObjectGetType() - { - Type type = null; - object anObject = "aString"; + [Benchmark(InnerIterationCount = 100000)] + public static Type TypeReflectionObjectGetType() + { + Type type = null; + object anObject = "aString"; - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - type = anObject.GetType(); + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + type = anObject.GetType(); - return type; - } + return type; + } - [Benchmark(InnerIterationCount=100000)] - public static Type TypeReflectionArrayGetType() - { - Type type = null; - object anArray = new string[0]; + [Benchmark(InnerIterationCount = 100000)] + public static Type TypeReflectionArrayGetType() + { + Type type = null; + object anArray = new string[0]; - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - type = anArray.GetType(); + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + type = anArray.GetType(); - return type; - } + return type; + } - [Benchmark(InnerIterationCount=100000)] - public static string IntegerFormatting() - { - int number = Int32.MaxValue; + [Benchmark(InnerIterationCount = 100000)] + public static string IntegerFormatting() + { + int number = Int32.MaxValue; - string result = null; - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - result = number.ToString(); + string result = null; + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + result = number.ToString(); - return result; + return result; + } } -} -#region Support Classes -// classes and method needed to perform the experiments. + #region Support Classes + // classes and method needed to perform the experiments. -public interface AnInterface -{ - int InterfaceMethod(); -} - -public class SuperClass : AnInterface -{ - [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] - public virtual int InterfaceMethod() { return 2; } - - [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] - public virtual int VirtualMethod() + public interface AnInterface { - return 1; + int InterfaceMethod(); } -} -public struct ValueType -{ - public int x; - public int y; - public int z; -} + public class SuperClass : AnInterface + { + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] + public virtual int InterfaceMethod() { return 2; } -public delegate int MyDelegate(); + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] + public virtual int VirtualMethod() + { + return 1; + } + } -public struct StructWithInterface : AnInterface -{ - public int x; - [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] - public int InterfaceMethod() + public struct ValueType { - return x++; + public int x; + public int y; + public int z; } -} -public sealed class SealedClass : SuperClass -{ - public int aInstanceInt; - [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] - public override int VirtualMethod() + public delegate int MyDelegate(); + + public struct StructWithInterface : AnInterface { - return aInstanceInt++; + public int x; + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] + public int InterfaceMethod() + { + return x++; + } } - [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] - public override int InterfaceMethod() + + public sealed class SealedClass : SuperClass { - return aInstanceInt++; + public int aInstanceInt; + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] + public override int VirtualMethod() + { + return aInstanceInt++; + } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] + public override int InterfaceMethod() + { + return aInstanceInt++; + } } -} -/// -/// A example class. It inherits, overrides, has intefaces etc. -/// It excercises most of the common runtime features -/// -public class Class : SuperClass -{ - public event MyDelegate AnEvent; + /// + /// A example class. It inherits, overrides, has intefaces etc. + /// It excercises most of the common runtime features + /// + public class Class : SuperClass + { + public event MyDelegate AnEvent; - [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] - public override int VirtualMethod() { return aInstanceInt++; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] + public override int VirtualMethod() { return aInstanceInt++; } - [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] - public override int InterfaceMethod() { return aInstanceInt++; } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] + public override int InterfaceMethod() { return aInstanceInt++; } - public int aInstanceInt; - public string aInstanceString; + public int aInstanceInt; + public string aInstanceString; - public static int aStaticInt; - public static string aStaticString = "Hello"; - public static ValueType aStaticValueType; + public static int aStaticInt; + public static string aStaticString = "Hello"; + public static ValueType aStaticValueType; - [MethodImpl(MethodImplOptions.NoInlining)] - public static int EmptyStaticFunction() - { - return aStaticInt++; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static int EmptyStaticFunction5Arg(int arg1, int arg2, int arg3, int arg4, int arg5) - { - return aStaticInt++; - } + [MethodImpl(MethodImplOptions.NoInlining)] + public static int EmptyStaticFunction() + { + return aStaticInt++; + } - [MethodImpl(MethodImplOptions.NoInlining)] - public int EmptyInstanceFunction() - { - return aInstanceInt++; - } + [MethodImpl(MethodImplOptions.NoInlining)] + public static int EmptyStaticFunction5Arg(int arg1, int arg2, int arg3, int arg4, int arg5) + { + return aStaticInt++; + } - [MethodImpl(MethodImplOptions.NoInlining)] - public static int GenericMethod() - { - return aStaticInt++; - } + [MethodImpl(MethodImplOptions.NoInlining)] + public int EmptyInstanceFunction() + { + return aInstanceInt++; + } - public void MeasureFire100() - { - #region callAnEvent - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - AnEvent(); - //}); - #endregion - } -} + [MethodImpl(MethodImplOptions.NoInlining)] + public static int GenericMethod() + { + return aStaticInt++; + } -public class GenericClass -{ - [MethodImpl(MethodImplOptions.NoInlining)] - public T ClassGenericInstanceMethod() - { - tmp++; // need this to not be optimized away - return aGenericInstanceFieldT; + public void MeasureFire100() + { + #region callAnEvent + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + AnEvent(); + //}); + #endregion + } } - [MethodImpl(MethodImplOptions.NoInlining)] - public static T ClassGenericStaticMethod() + public class GenericClass { - sTmp++; // need this to not be optimized away - return aGenericStaticFieldT; - } + [MethodImpl(MethodImplOptions.NoInlining)] + public T ClassGenericInstanceMethod() + { + tmp++; // need this to not be optimized away + return aGenericInstanceFieldT; + } - public static int sTmp; - public int tmp; - public T aGenericInstanceFieldT; - public static T aGenericStaticFieldT; -} + [MethodImpl(MethodImplOptions.NoInlining)] + public static T ClassGenericStaticMethod() + { + sTmp++; // need this to not be optimized away + return aGenericStaticFieldT; + } -#region LongHierarchyClass -public class LongHierarchyClass1 : AnInterface -{ - [MethodImpl(MethodImplOptions.NoInlining)] - public virtual int InterfaceMethod() { return 2; } + public static int sTmp; + public int tmp; + public T aGenericInstanceFieldT; + public static T aGenericStaticFieldT; + } - [MethodImpl(MethodImplOptions.NoInlining)] - public virtual int VirtualMethod() + #region LongHierarchyClass + public class LongHierarchyClass1 : AnInterface { - return 1; - } -} + [MethodImpl(MethodImplOptions.NoInlining)] + public virtual int InterfaceMethod() { return 2; } -public class LongHierarchyClass2 : LongHierarchyClass1 -{ - [MethodImpl(MethodImplOptions.NoInlining)] - public override int InterfaceMethod() { return 2; } + [MethodImpl(MethodImplOptions.NoInlining)] + public virtual int VirtualMethod() + { + return 1; + } + } - [MethodImpl(MethodImplOptions.NoInlining)] - public override int VirtualMethod() + public class LongHierarchyClass2 : LongHierarchyClass1 { - return 1; - } -} + [MethodImpl(MethodImplOptions.NoInlining)] + public override int InterfaceMethod() { return 2; } -public class LongHierarchyClass3 : LongHierarchyClass2 -{ - [MethodImpl(MethodImplOptions.NoInlining)] - public override int InterfaceMethod() { return 2; } + [MethodImpl(MethodImplOptions.NoInlining)] + public override int VirtualMethod() + { + return 1; + } + } - [MethodImpl(MethodImplOptions.NoInlining)] - public override int VirtualMethod() + public class LongHierarchyClass3 : LongHierarchyClass2 { - return 1; - } -} + [MethodImpl(MethodImplOptions.NoInlining)] + public override int InterfaceMethod() { return 2; } -public class LongHierarchyClass4 : LongHierarchyClass3 -{ - [MethodImpl(MethodImplOptions.NoInlining)] - public override int InterfaceMethod() { return 2; } + [MethodImpl(MethodImplOptions.NoInlining)] + public override int VirtualMethod() + { + return 1; + } + } - [MethodImpl(MethodImplOptions.NoInlining)] - public override int VirtualMethod() + public class LongHierarchyClass4 : LongHierarchyClass3 { - return 1; - } -} + [MethodImpl(MethodImplOptions.NoInlining)] + public override int InterfaceMethod() { return 2; } -public class LongHierarchyClass5 : LongHierarchyClass4 -{ - [MethodImpl(MethodImplOptions.NoInlining)] - public override int InterfaceMethod() { return 2; } + [MethodImpl(MethodImplOptions.NoInlining)] + public override int VirtualMethod() + { + return 1; + } + } - [MethodImpl(MethodImplOptions.NoInlining)] - public override int VirtualMethod() + public class LongHierarchyClass5 : LongHierarchyClass4 { - return 1; - } -} + [MethodImpl(MethodImplOptions.NoInlining)] + public override int InterfaceMethod() { return 2; } -public class LongHierarchyClass6 : LongHierarchyClass5 -{ - [MethodImpl(MethodImplOptions.NoInlining)] - public override int InterfaceMethod() { return 2; } + [MethodImpl(MethodImplOptions.NoInlining)] + public override int VirtualMethod() + { + return 1; + } + } - [MethodImpl(MethodImplOptions.NoInlining)] - public override int VirtualMethod() + public class LongHierarchyClass6 : LongHierarchyClass5 { - return 1; - } -} + [MethodImpl(MethodImplOptions.NoInlining)] + public override int InterfaceMethod() { return 2; } -public class LongHierarchyClass7 : LongHierarchyClass6 -{ - [MethodImpl(MethodImplOptions.NoInlining)] - public override int InterfaceMethod() { return 2; } + [MethodImpl(MethodImplOptions.NoInlining)] + public override int VirtualMethod() + { + return 1; + } + } - [MethodImpl(MethodImplOptions.NoInlining)] - public override int VirtualMethod() + public class LongHierarchyClass7 : LongHierarchyClass6 { - return 1; - } -} + [MethodImpl(MethodImplOptions.NoInlining)] + public override int InterfaceMethod() { return 2; } -public class LongHierarchyClass8 : LongHierarchyClass7 -{ - [MethodImpl(MethodImplOptions.NoInlining)] - public override int InterfaceMethod() { return 2; } + [MethodImpl(MethodImplOptions.NoInlining)] + public override int VirtualMethod() + { + return 1; + } + } - [MethodImpl(MethodImplOptions.NoInlining)] - public override int VirtualMethod() + public class LongHierarchyClass8 : LongHierarchyClass7 { - return 1; - } -} + [MethodImpl(MethodImplOptions.NoInlining)] + public override int InterfaceMethod() { return 2; } -public class LongHierarchyClass9 : LongHierarchyClass8 -{ - [MethodImpl(MethodImplOptions.NoInlining)] - public override int InterfaceMethod() { return 2; } + [MethodImpl(MethodImplOptions.NoInlining)] + public override int VirtualMethod() + { + return 1; + } + } - [MethodImpl(MethodImplOptions.NoInlining)] - public override int VirtualMethod() + public class LongHierarchyClass9 : LongHierarchyClass8 { - return 1; - } -} + [MethodImpl(MethodImplOptions.NoInlining)] + public override int InterfaceMethod() { return 2; } -public class LongHierarchyClass10 : LongHierarchyClass9 -{ - [MethodImpl(MethodImplOptions.NoInlining)] - public override int InterfaceMethod() { return 2; } + [MethodImpl(MethodImplOptions.NoInlining)] + public override int VirtualMethod() + { + return 1; + } + } - [MethodImpl(MethodImplOptions.NoInlining)] - public override int VirtualMethod() + public class LongHierarchyClass10 : LongHierarchyClass9 { - return 1; - } -} + [MethodImpl(MethodImplOptions.NoInlining)] + public override int InterfaceMethod() { return 2; } -public class LongHierarchyClass11 : LongHierarchyClass10 -{ - [MethodImpl(MethodImplOptions.NoInlining)] - public override int InterfaceMethod() { return 2; } + [MethodImpl(MethodImplOptions.NoInlining)] + public override int VirtualMethod() + { + return 1; + } + } - [MethodImpl(MethodImplOptions.NoInlining)] - public override int VirtualMethod() + public class LongHierarchyClass11 : LongHierarchyClass10 { - return 1; - } -} + [MethodImpl(MethodImplOptions.NoInlining)] + public override int InterfaceMethod() { return 2; } -public class LongHierarchyClass12 : LongHierarchyClass11 -{ - [MethodImpl(MethodImplOptions.NoInlining)] - public override int InterfaceMethod() { return 2; } + [MethodImpl(MethodImplOptions.NoInlining)] + public override int VirtualMethod() + { + return 1; + } + } - [MethodImpl(MethodImplOptions.NoInlining)] - public override int VirtualMethod() + public class LongHierarchyClass12 : LongHierarchyClass11 { - return 1; - } -} + [MethodImpl(MethodImplOptions.NoInlining)] + public override int InterfaceMethod() { return 2; } -public class LongHierarchyChildClass : LongHierarchyClass12 -{ - [MethodImpl(MethodImplOptions.NoInlining)] - public override int InterfaceMethod() { return 2; } + [MethodImpl(MethodImplOptions.NoInlining)] + public override int VirtualMethod() + { + return 1; + } + } - [MethodImpl(MethodImplOptions.NoInlining)] - public override int VirtualMethod() + public class LongHierarchyChildClass : LongHierarchyClass12 { - return 1; + [MethodImpl(MethodImplOptions.NoInlining)] + public override int InterfaceMethod() { return 2; } + + [MethodImpl(MethodImplOptions.NoInlining)] + public override int VirtualMethod() + { + return 1; + } } -} -#endregion + #endregion -#endregion + #endregion +} diff --git a/tests/src/performance/perflab/ReflectionPerf.cs b/tests/src/performance/perflab/ReflectionPerf.cs index 954bbe7..03556c9 100644 --- a/tests/src/performance/perflab/ReflectionPerf.cs +++ b/tests/src/performance/perflab/ReflectionPerf.cs @@ -8,3309 +8,3312 @@ using System.Threading; using Microsoft.Xunit.Performance; #pragma warning disable 67 -public class GetMember +namespace PerfLabTests { - // all these fields will be initialized in init, so that they can be used directly in invocation - private static readonly TypeInfo s_t1; - private static readonly TypeInfo s_t2; - private static readonly TypeInfo s_t3; - private static readonly TypeInfo s_t4; - private static readonly TypeInfo s_t5; - private static readonly TypeInfo s_t6; - private static readonly TypeInfo s_t7; - private static readonly TypeInfo s_t8; - private static readonly TypeInfo s_t9; - private static readonly TypeInfo s_t10; - private static readonly TypeInfo s_t11; - private static readonly TypeInfo s_t12; - private static readonly TypeInfo s_t13; - private static readonly TypeInfo s_t14; - private static readonly TypeInfo s_t15; - private static readonly TypeInfo s_t16; - private static readonly TypeInfo s_t17; - private static readonly TypeInfo s_t18; - private static readonly TypeInfo s_t19; - private static readonly TypeInfo s_t20; - - static GetMember() + public class GetMember { - s_t1 = typeof(Class1).GetTypeInfo(); - s_t2 = typeof(Class2).GetTypeInfo(); - s_t3 = typeof(Class3).GetTypeInfo(); - s_t4 = typeof(Class4).GetTypeInfo(); - s_t5 = typeof(Class5).GetTypeInfo(); - s_t6 = typeof(Class6).GetTypeInfo(); - s_t7 = typeof(Class7).GetTypeInfo(); - s_t8 = typeof(Class8).GetTypeInfo(); - s_t9 = typeof(Class9).GetTypeInfo(); - s_t10 = typeof(Class10).GetTypeInfo(); - s_t11 = typeof(Class11).GetTypeInfo(); - s_t12 = typeof(Class12).GetTypeInfo(); - s_t13 = typeof(Class13).GetTypeInfo(); - s_t14 = typeof(Class14).GetTypeInfo(); - s_t15 = typeof(Class15).GetTypeInfo(); - s_t16 = typeof(Class16).GetTypeInfo(); - s_t17 = typeof(Class17).GetTypeInfo(); - s_t18 = typeof(Class18).GetTypeInfo(); - s_t19 = typeof(Class19).GetTypeInfo(); - s_t20 = typeof(Class20).GetTypeInfo(); - } + // all these fields will be initialized in init, so that they can be used directly in invocation + private static readonly TypeInfo s_t1; + private static readonly TypeInfo s_t2; + private static readonly TypeInfo s_t3; + private static readonly TypeInfo s_t4; + private static readonly TypeInfo s_t5; + private static readonly TypeInfo s_t6; + private static readonly TypeInfo s_t7; + private static readonly TypeInfo s_t8; + private static readonly TypeInfo s_t9; + private static readonly TypeInfo s_t10; + private static readonly TypeInfo s_t11; + private static readonly TypeInfo s_t12; + private static readonly TypeInfo s_t13; + private static readonly TypeInfo s_t14; + private static readonly TypeInfo s_t15; + private static readonly TypeInfo s_t16; + private static readonly TypeInfo s_t17; + private static readonly TypeInfo s_t18; + private static readonly TypeInfo s_t19; + private static readonly TypeInfo s_t20; + + static GetMember() + { + s_t1 = typeof(Class1).GetTypeInfo(); + s_t2 = typeof(Class2).GetTypeInfo(); + s_t3 = typeof(Class3).GetTypeInfo(); + s_t4 = typeof(Class4).GetTypeInfo(); + s_t5 = typeof(Class5).GetTypeInfo(); + s_t6 = typeof(Class6).GetTypeInfo(); + s_t7 = typeof(Class7).GetTypeInfo(); + s_t8 = typeof(Class8).GetTypeInfo(); + s_t9 = typeof(Class9).GetTypeInfo(); + s_t10 = typeof(Class10).GetTypeInfo(); + s_t11 = typeof(Class11).GetTypeInfo(); + s_t12 = typeof(Class12).GetTypeInfo(); + s_t13 = typeof(Class13).GetTypeInfo(); + s_t14 = typeof(Class14).GetTypeInfo(); + s_t15 = typeof(Class15).GetTypeInfo(); + s_t16 = typeof(Class16).GetTypeInfo(); + s_t17 = typeof(Class17).GetTypeInfo(); + s_t18 = typeof(Class18).GetTypeInfo(); + s_t19 = typeof(Class19).GetTypeInfo(); + s_t20 = typeof(Class20).GetTypeInfo(); + } - [Benchmark(InnerIterationCount=1000)] - public static void GetField() - { - foreach (var iteration in Benchmark.Iterations) + [Benchmark(InnerIterationCount = 1000)] + public static void GetField() { - using (iteration.StartMeasurement()) + foreach (var iteration in Benchmark.Iterations) { - for (int i = 0; i < Benchmark.InnerIterationCount; i++) + using (iteration.StartMeasurement()) { - s_t1.GetDeclaredField("f1"); - s_t1.GetDeclaredField("f2"); - s_t1.GetDeclaredField("f3"); + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + s_t1.GetDeclaredField("f1"); + s_t1.GetDeclaredField("f2"); + s_t1.GetDeclaredField("f3"); + } } } } - } - [Benchmark(InnerIterationCount=1000)] - public static void GetMethod1() - { - foreach (var iteration in Benchmark.Iterations) + [Benchmark(InnerIterationCount = 1000)] + public static void GetMethod1() { - using (iteration.StartMeasurement()) + foreach (var iteration in Benchmark.Iterations) { - for (int i = 0; i < Benchmark.InnerIterationCount; i++) + using (iteration.StartMeasurement()) { - s_t1.GetDeclaredMethod("m1"); - s_t1.GetDeclaredMethod("m2"); - s_t1.GetDeclaredMethod("m3"); + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + s_t1.GetDeclaredMethod("m1"); + s_t1.GetDeclaredMethod("m2"); + s_t1.GetDeclaredMethod("m3"); + } } } } - } - [Benchmark(InnerIterationCount=1000)] - public static void GetMethod2() - { - foreach (var iteration in Benchmark.Iterations) + [Benchmark(InnerIterationCount = 1000)] + public static void GetMethod2() { - using (iteration.StartMeasurement()) + foreach (var iteration in Benchmark.Iterations) { - for (int i = 0; i < Benchmark.InnerIterationCount; i++) + using (iteration.StartMeasurement()) { - s_t1.GetDeclaredMethod("m1"); - s_t1.GetDeclaredMethod("m2"); - s_t1.GetDeclaredMethod("m3"); - s_t2.GetDeclaredMethod("m1"); - s_t2.GetDeclaredMethod("m2"); - s_t2.GetDeclaredMethod("m3"); + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + s_t1.GetDeclaredMethod("m1"); + s_t1.GetDeclaredMethod("m2"); + s_t1.GetDeclaredMethod("m3"); + s_t2.GetDeclaredMethod("m1"); + s_t2.GetDeclaredMethod("m2"); + s_t2.GetDeclaredMethod("m3"); + } } } } - } - [Benchmark(InnerIterationCount=1000)] - public static void GetMethod3() - { - foreach (var iteration in Benchmark.Iterations) + [Benchmark(InnerIterationCount = 1000)] + public static void GetMethod3() { - using (iteration.StartMeasurement()) + foreach (var iteration in Benchmark.Iterations) { - for (int i = 0; i < Benchmark.InnerIterationCount; i++) + using (iteration.StartMeasurement()) { - s_t1.GetDeclaredMethod("m1"); - s_t1.GetDeclaredMethod("m2"); //TODO: check if we can really get the method - s_t1.GetDeclaredMethod("m3"); - s_t2.GetDeclaredMethod("m1"); - s_t2.GetDeclaredMethod("m2"); - s_t2.GetDeclaredMethod("m3"); - s_t3.GetDeclaredMethod("m1"); - s_t3.GetDeclaredMethod("m2"); - s_t3.GetDeclaredMethod("m3"); + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + s_t1.GetDeclaredMethod("m1"); + s_t1.GetDeclaredMethod("m2"); //TODO: check if we can really get the method + s_t1.GetDeclaredMethod("m3"); + s_t2.GetDeclaredMethod("m1"); + s_t2.GetDeclaredMethod("m2"); + s_t2.GetDeclaredMethod("m3"); + s_t3.GetDeclaredMethod("m1"); + s_t3.GetDeclaredMethod("m2"); + s_t3.GetDeclaredMethod("m3"); + } } } } - } - [Benchmark(InnerIterationCount=1000)] - public static void GetMethod4() - { - foreach (var iteration in Benchmark.Iterations) + [Benchmark(InnerIterationCount = 1000)] + public static void GetMethod4() { - using (iteration.StartMeasurement()) + foreach (var iteration in Benchmark.Iterations) { - for (int i = 0; i < Benchmark.InnerIterationCount; i++) + using (iteration.StartMeasurement()) { - s_t1.GetDeclaredMethod("m1"); - s_t1.GetDeclaredMethod("m2"); //TODO: check if we can really get the method - s_t1.GetDeclaredMethod("m3"); - s_t2.GetDeclaredMethod("m1"); - s_t2.GetDeclaredMethod("m2"); - s_t2.GetDeclaredMethod("m3"); - s_t3.GetDeclaredMethod("m1"); - s_t3.GetDeclaredMethod("m2"); - s_t3.GetDeclaredMethod("m3"); - s_t4.GetDeclaredMethod("m1"); - s_t4.GetDeclaredMethod("m2"); - s_t4.GetDeclaredMethod("m3"); + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + s_t1.GetDeclaredMethod("m1"); + s_t1.GetDeclaredMethod("m2"); //TODO: check if we can really get the method + s_t1.GetDeclaredMethod("m3"); + s_t2.GetDeclaredMethod("m1"); + s_t2.GetDeclaredMethod("m2"); + s_t2.GetDeclaredMethod("m3"); + s_t3.GetDeclaredMethod("m1"); + s_t3.GetDeclaredMethod("m2"); + s_t3.GetDeclaredMethod("m3"); + s_t4.GetDeclaredMethod("m1"); + s_t4.GetDeclaredMethod("m2"); + s_t4.GetDeclaredMethod("m3"); + } } } } - } - [Benchmark(InnerIterationCount=1000)] - public static void GetMethod5() - { - foreach (var iteration in Benchmark.Iterations) + [Benchmark(InnerIterationCount = 1000)] + public static void GetMethod5() { - using (iteration.StartMeasurement()) + foreach (var iteration in Benchmark.Iterations) { - for (int i = 0; i < Benchmark.InnerIterationCount; i++) + using (iteration.StartMeasurement()) { - s_t1.GetDeclaredMethod("m1"); - s_t1.GetDeclaredMethod("m2"); - s_t1.GetDeclaredMethod("m3"); - s_t2.GetDeclaredMethod("m1"); - s_t2.GetDeclaredMethod("m2"); - s_t2.GetDeclaredMethod("m3"); - s_t3.GetDeclaredMethod("m1"); - s_t3.GetDeclaredMethod("m2"); - s_t3.GetDeclaredMethod("m3"); - s_t4.GetDeclaredMethod("m1"); - s_t4.GetDeclaredMethod("m2"); - s_t4.GetDeclaredMethod("m3"); - s_t5.GetDeclaredMethod("m1"); - s_t5.GetDeclaredMethod("m2"); - s_t5.GetDeclaredMethod("m3"); + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + s_t1.GetDeclaredMethod("m1"); + s_t1.GetDeclaredMethod("m2"); + s_t1.GetDeclaredMethod("m3"); + s_t2.GetDeclaredMethod("m1"); + s_t2.GetDeclaredMethod("m2"); + s_t2.GetDeclaredMethod("m3"); + s_t3.GetDeclaredMethod("m1"); + s_t3.GetDeclaredMethod("m2"); + s_t3.GetDeclaredMethod("m3"); + s_t4.GetDeclaredMethod("m1"); + s_t4.GetDeclaredMethod("m2"); + s_t4.GetDeclaredMethod("m3"); + s_t5.GetDeclaredMethod("m1"); + s_t5.GetDeclaredMethod("m2"); + s_t5.GetDeclaredMethod("m3"); + } } } } - } - [Benchmark(InnerIterationCount=1000)] - public static void GetMethod10() - { - foreach (var iteration in Benchmark.Iterations) + [Benchmark(InnerIterationCount = 1000)] + public static void GetMethod10() { - using (iteration.StartMeasurement()) + foreach (var iteration in Benchmark.Iterations) { - for (int i = 0; i < Benchmark.InnerIterationCount; i++) + using (iteration.StartMeasurement()) { - s_t1.GetDeclaredMethod("m1"); - s_t1.GetDeclaredMethod("m2"); - s_t1.GetDeclaredMethod("m3"); - s_t2.GetDeclaredMethod("m1"); - s_t2.GetDeclaredMethod("m2"); - s_t2.GetDeclaredMethod("m3"); - s_t3.GetDeclaredMethod("m1"); - s_t3.GetDeclaredMethod("m2"); - s_t3.GetDeclaredMethod("m3"); - s_t4.GetDeclaredMethod("m1"); - s_t4.GetDeclaredMethod("m2"); - s_t4.GetDeclaredMethod("m3"); - s_t5.GetDeclaredMethod("m1"); - s_t5.GetDeclaredMethod("m2"); - s_t5.GetDeclaredMethod("m3"); - - s_t6.GetDeclaredMethod("m1"); - s_t6.GetDeclaredMethod("m2"); - s_t6.GetDeclaredMethod("m3"); - s_t7.GetDeclaredMethod("m1"); - s_t7.GetDeclaredMethod("m2"); - s_t7.GetDeclaredMethod("m3"); - s_t8.GetDeclaredMethod("m1"); - s_t8.GetDeclaredMethod("m2"); - s_t8.GetDeclaredMethod("m3"); - s_t9.GetDeclaredMethod("m1"); - s_t9.GetDeclaredMethod("m2"); - s_t9.GetDeclaredMethod("m3"); - s_t10.GetDeclaredMethod("m1"); - s_t10.GetDeclaredMethod("m2"); - s_t10.GetDeclaredMethod("m3"); + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + s_t1.GetDeclaredMethod("m1"); + s_t1.GetDeclaredMethod("m2"); + s_t1.GetDeclaredMethod("m3"); + s_t2.GetDeclaredMethod("m1"); + s_t2.GetDeclaredMethod("m2"); + s_t2.GetDeclaredMethod("m3"); + s_t3.GetDeclaredMethod("m1"); + s_t3.GetDeclaredMethod("m2"); + s_t3.GetDeclaredMethod("m3"); + s_t4.GetDeclaredMethod("m1"); + s_t4.GetDeclaredMethod("m2"); + s_t4.GetDeclaredMethod("m3"); + s_t5.GetDeclaredMethod("m1"); + s_t5.GetDeclaredMethod("m2"); + s_t5.GetDeclaredMethod("m3"); + + s_t6.GetDeclaredMethod("m1"); + s_t6.GetDeclaredMethod("m2"); + s_t6.GetDeclaredMethod("m3"); + s_t7.GetDeclaredMethod("m1"); + s_t7.GetDeclaredMethod("m2"); + s_t7.GetDeclaredMethod("m3"); + s_t8.GetDeclaredMethod("m1"); + s_t8.GetDeclaredMethod("m2"); + s_t8.GetDeclaredMethod("m3"); + s_t9.GetDeclaredMethod("m1"); + s_t9.GetDeclaredMethod("m2"); + s_t9.GetDeclaredMethod("m3"); + s_t10.GetDeclaredMethod("m1"); + s_t10.GetDeclaredMethod("m2"); + s_t10.GetDeclaredMethod("m3"); + } } } } - } - [Benchmark(InnerIterationCount=1000)] - public static void GetMethod12() - { - foreach (var iteration in Benchmark.Iterations) + [Benchmark(InnerIterationCount = 1000)] + public static void GetMethod12() { - using (iteration.StartMeasurement()) + foreach (var iteration in Benchmark.Iterations) { - for (int i = 0; i < Benchmark.InnerIterationCount; i++) + using (iteration.StartMeasurement()) { - s_t1.GetDeclaredMethod("m1"); - s_t1.GetDeclaredMethod("m2"); - s_t1.GetDeclaredMethod("m3"); - s_t2.GetDeclaredMethod("m1"); - s_t2.GetDeclaredMethod("m2"); - s_t2.GetDeclaredMethod("m3"); - s_t3.GetDeclaredMethod("m1"); - s_t3.GetDeclaredMethod("m2"); - s_t3.GetDeclaredMethod("m3"); - s_t4.GetDeclaredMethod("m1"); - s_t4.GetDeclaredMethod("m2"); - s_t4.GetDeclaredMethod("m3"); - s_t5.GetDeclaredMethod("m1"); - s_t5.GetDeclaredMethod("m2"); - s_t5.GetDeclaredMethod("m3"); - - s_t6.GetDeclaredMethod("m1"); - s_t6.GetDeclaredMethod("m2"); - s_t6.GetDeclaredMethod("m3"); - s_t7.GetDeclaredMethod("m1"); - s_t7.GetDeclaredMethod("m2"); - s_t7.GetDeclaredMethod("m3"); - s_t8.GetDeclaredMethod("m1"); - s_t8.GetDeclaredMethod("m2"); - s_t8.GetDeclaredMethod("m3"); - s_t9.GetDeclaredMethod("m1"); - s_t9.GetDeclaredMethod("m2"); - s_t9.GetDeclaredMethod("m3"); - s_t10.GetDeclaredMethod("m1"); - s_t10.GetDeclaredMethod("m2"); - s_t10.GetDeclaredMethod("m3"); - - s_t11.GetDeclaredMethod("m1"); - s_t11.GetDeclaredMethod("m2"); - s_t11.GetDeclaredMethod("m3"); - s_t12.GetDeclaredMethod("m1"); - s_t12.GetDeclaredMethod("m2"); - s_t12.GetDeclaredMethod("m3"); + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + s_t1.GetDeclaredMethod("m1"); + s_t1.GetDeclaredMethod("m2"); + s_t1.GetDeclaredMethod("m3"); + s_t2.GetDeclaredMethod("m1"); + s_t2.GetDeclaredMethod("m2"); + s_t2.GetDeclaredMethod("m3"); + s_t3.GetDeclaredMethod("m1"); + s_t3.GetDeclaredMethod("m2"); + s_t3.GetDeclaredMethod("m3"); + s_t4.GetDeclaredMethod("m1"); + s_t4.GetDeclaredMethod("m2"); + s_t4.GetDeclaredMethod("m3"); + s_t5.GetDeclaredMethod("m1"); + s_t5.GetDeclaredMethod("m2"); + s_t5.GetDeclaredMethod("m3"); + + s_t6.GetDeclaredMethod("m1"); + s_t6.GetDeclaredMethod("m2"); + s_t6.GetDeclaredMethod("m3"); + s_t7.GetDeclaredMethod("m1"); + s_t7.GetDeclaredMethod("m2"); + s_t7.GetDeclaredMethod("m3"); + s_t8.GetDeclaredMethod("m1"); + s_t8.GetDeclaredMethod("m2"); + s_t8.GetDeclaredMethod("m3"); + s_t9.GetDeclaredMethod("m1"); + s_t9.GetDeclaredMethod("m2"); + s_t9.GetDeclaredMethod("m3"); + s_t10.GetDeclaredMethod("m1"); + s_t10.GetDeclaredMethod("m2"); + s_t10.GetDeclaredMethod("m3"); + + s_t11.GetDeclaredMethod("m1"); + s_t11.GetDeclaredMethod("m2"); + s_t11.GetDeclaredMethod("m3"); + s_t12.GetDeclaredMethod("m1"); + s_t12.GetDeclaredMethod("m2"); + s_t12.GetDeclaredMethod("m3"); + } } } } - } - [Benchmark(InnerIterationCount=1000)] - public static void GetMethod15() - { - foreach (var iteration in Benchmark.Iterations) + [Benchmark(InnerIterationCount = 1000)] + public static void GetMethod15() { - using (iteration.StartMeasurement()) + foreach (var iteration in Benchmark.Iterations) { - for (int i = 0; i < Benchmark.InnerIterationCount; i++) + using (iteration.StartMeasurement()) { - s_t1.GetDeclaredMethod("m1"); - s_t1.GetDeclaredMethod("m2"); - s_t1.GetDeclaredMethod("m3"); - s_t2.GetDeclaredMethod("m1"); - s_t2.GetDeclaredMethod("m2"); - s_t2.GetDeclaredMethod("m3"); - s_t3.GetDeclaredMethod("m1"); - s_t3.GetDeclaredMethod("m2"); - s_t3.GetDeclaredMethod("m3"); - s_t4.GetDeclaredMethod("m1"); - s_t4.GetDeclaredMethod("m2"); - s_t4.GetDeclaredMethod("m3"); - s_t5.GetDeclaredMethod("m1"); - s_t5.GetDeclaredMethod("m2"); - s_t5.GetDeclaredMethod("m3"); - - s_t6.GetDeclaredMethod("m1"); - s_t6.GetDeclaredMethod("m2"); - s_t6.GetDeclaredMethod("m3"); - s_t7.GetDeclaredMethod("m1"); - s_t7.GetDeclaredMethod("m2"); - s_t7.GetDeclaredMethod("m3"); - s_t8.GetDeclaredMethod("m1"); - s_t8.GetDeclaredMethod("m2"); - s_t8.GetDeclaredMethod("m3"); - s_t9.GetDeclaredMethod("m1"); - s_t9.GetDeclaredMethod("m2"); - s_t9.GetDeclaredMethod("m3"); - s_t10.GetDeclaredMethod("m1"); - s_t10.GetDeclaredMethod("m2"); - s_t10.GetDeclaredMethod("m3"); - - s_t11.GetDeclaredMethod("m1"); - s_t11.GetDeclaredMethod("m2"); - s_t11.GetDeclaredMethod("m3"); - s_t12.GetDeclaredMethod("m1"); - s_t12.GetDeclaredMethod("m2"); - s_t12.GetDeclaredMethod("m3"); - s_t13.GetDeclaredMethod("m1"); - s_t13.GetDeclaredMethod("m2"); - s_t13.GetDeclaredMethod("m3"); - s_t14.GetDeclaredMethod("m1"); - s_t14.GetDeclaredMethod("m2"); - s_t14.GetDeclaredMethod("m3"); - s_t15.GetDeclaredMethod("m1"); - s_t15.GetDeclaredMethod("m2"); - s_t15.GetDeclaredMethod("m3"); + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + s_t1.GetDeclaredMethod("m1"); + s_t1.GetDeclaredMethod("m2"); + s_t1.GetDeclaredMethod("m3"); + s_t2.GetDeclaredMethod("m1"); + s_t2.GetDeclaredMethod("m2"); + s_t2.GetDeclaredMethod("m3"); + s_t3.GetDeclaredMethod("m1"); + s_t3.GetDeclaredMethod("m2"); + s_t3.GetDeclaredMethod("m3"); + s_t4.GetDeclaredMethod("m1"); + s_t4.GetDeclaredMethod("m2"); + s_t4.GetDeclaredMethod("m3"); + s_t5.GetDeclaredMethod("m1"); + s_t5.GetDeclaredMethod("m2"); + s_t5.GetDeclaredMethod("m3"); + + s_t6.GetDeclaredMethod("m1"); + s_t6.GetDeclaredMethod("m2"); + s_t6.GetDeclaredMethod("m3"); + s_t7.GetDeclaredMethod("m1"); + s_t7.GetDeclaredMethod("m2"); + s_t7.GetDeclaredMethod("m3"); + s_t8.GetDeclaredMethod("m1"); + s_t8.GetDeclaredMethod("m2"); + s_t8.GetDeclaredMethod("m3"); + s_t9.GetDeclaredMethod("m1"); + s_t9.GetDeclaredMethod("m2"); + s_t9.GetDeclaredMethod("m3"); + s_t10.GetDeclaredMethod("m1"); + s_t10.GetDeclaredMethod("m2"); + s_t10.GetDeclaredMethod("m3"); + + s_t11.GetDeclaredMethod("m1"); + s_t11.GetDeclaredMethod("m2"); + s_t11.GetDeclaredMethod("m3"); + s_t12.GetDeclaredMethod("m1"); + s_t12.GetDeclaredMethod("m2"); + s_t12.GetDeclaredMethod("m3"); + s_t13.GetDeclaredMethod("m1"); + s_t13.GetDeclaredMethod("m2"); + s_t13.GetDeclaredMethod("m3"); + s_t14.GetDeclaredMethod("m1"); + s_t14.GetDeclaredMethod("m2"); + s_t14.GetDeclaredMethod("m3"); + s_t15.GetDeclaredMethod("m1"); + s_t15.GetDeclaredMethod("m2"); + s_t15.GetDeclaredMethod("m3"); + } } } } - } - [Benchmark(InnerIterationCount=1000)] - public static void GetMethod20() - { - foreach (var iteration in Benchmark.Iterations) + [Benchmark(InnerIterationCount = 1000)] + public static void GetMethod20() { - using (iteration.StartMeasurement()) + foreach (var iteration in Benchmark.Iterations) { - for (int i = 0; i < Benchmark.InnerIterationCount; i++) + using (iteration.StartMeasurement()) { - s_t1.GetDeclaredMethod("m1"); - s_t1.GetDeclaredMethod("m2"); - s_t1.GetDeclaredMethod("m3"); - s_t2.GetDeclaredMethod("m1"); - s_t2.GetDeclaredMethod("m2"); - s_t2.GetDeclaredMethod("m3"); - s_t3.GetDeclaredMethod("m1"); - s_t3.GetDeclaredMethod("m2"); - s_t3.GetDeclaredMethod("m3"); - s_t4.GetDeclaredMethod("m1"); - s_t4.GetDeclaredMethod("m2"); - s_t4.GetDeclaredMethod("m3"); - s_t5.GetDeclaredMethod("m1"); - s_t5.GetDeclaredMethod("m2"); - s_t5.GetDeclaredMethod("m3"); - - s_t6.GetDeclaredMethod("m1"); - s_t6.GetDeclaredMethod("m2"); - s_t6.GetDeclaredMethod("m3"); - s_t7.GetDeclaredMethod("m1"); - s_t7.GetDeclaredMethod("m2"); - s_t7.GetDeclaredMethod("m3"); - s_t8.GetDeclaredMethod("m1"); - s_t8.GetDeclaredMethod("m2"); - s_t8.GetDeclaredMethod("m3"); - s_t9.GetDeclaredMethod("m1"); - s_t9.GetDeclaredMethod("m2"); - s_t9.GetDeclaredMethod("m3"); - s_t10.GetDeclaredMethod("m1"); - s_t10.GetDeclaredMethod("m2"); - s_t10.GetDeclaredMethod("m3"); - - s_t11.GetDeclaredMethod("m1"); - s_t11.GetDeclaredMethod("m2"); - s_t11.GetDeclaredMethod("m3"); - s_t12.GetDeclaredMethod("m1"); - s_t12.GetDeclaredMethod("m2"); - s_t12.GetDeclaredMethod("m3"); - s_t13.GetDeclaredMethod("m1"); - s_t13.GetDeclaredMethod("m2"); - s_t13.GetDeclaredMethod("m3"); - s_t14.GetDeclaredMethod("m1"); - s_t14.GetDeclaredMethod("m2"); - s_t14.GetDeclaredMethod("m3"); - s_t15.GetDeclaredMethod("m1"); - s_t15.GetDeclaredMethod("m2"); - s_t15.GetDeclaredMethod("m3"); - - s_t16.GetDeclaredMethod("m1"); - s_t16.GetDeclaredMethod("m2"); - s_t16.GetDeclaredMethod("m3"); - s_t17.GetDeclaredMethod("m1"); - s_t17.GetDeclaredMethod("m2"); - s_t17.GetDeclaredMethod("m3"); - s_t18.GetDeclaredMethod("m1"); - s_t18.GetDeclaredMethod("m2"); - s_t18.GetDeclaredMethod("m3"); - s_t19.GetDeclaredMethod("m1"); - s_t19.GetDeclaredMethod("m2"); - s_t19.GetDeclaredMethod("m3"); - s_t20.GetDeclaredMethod("m1"); - s_t20.GetDeclaredMethod("m2"); - s_t20.GetDeclaredMethod("m3"); + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + s_t1.GetDeclaredMethod("m1"); + s_t1.GetDeclaredMethod("m2"); + s_t1.GetDeclaredMethod("m3"); + s_t2.GetDeclaredMethod("m1"); + s_t2.GetDeclaredMethod("m2"); + s_t2.GetDeclaredMethod("m3"); + s_t3.GetDeclaredMethod("m1"); + s_t3.GetDeclaredMethod("m2"); + s_t3.GetDeclaredMethod("m3"); + s_t4.GetDeclaredMethod("m1"); + s_t4.GetDeclaredMethod("m2"); + s_t4.GetDeclaredMethod("m3"); + s_t5.GetDeclaredMethod("m1"); + s_t5.GetDeclaredMethod("m2"); + s_t5.GetDeclaredMethod("m3"); + + s_t6.GetDeclaredMethod("m1"); + s_t6.GetDeclaredMethod("m2"); + s_t6.GetDeclaredMethod("m3"); + s_t7.GetDeclaredMethod("m1"); + s_t7.GetDeclaredMethod("m2"); + s_t7.GetDeclaredMethod("m3"); + s_t8.GetDeclaredMethod("m1"); + s_t8.GetDeclaredMethod("m2"); + s_t8.GetDeclaredMethod("m3"); + s_t9.GetDeclaredMethod("m1"); + s_t9.GetDeclaredMethod("m2"); + s_t9.GetDeclaredMethod("m3"); + s_t10.GetDeclaredMethod("m1"); + s_t10.GetDeclaredMethod("m2"); + s_t10.GetDeclaredMethod("m3"); + + s_t11.GetDeclaredMethod("m1"); + s_t11.GetDeclaredMethod("m2"); + s_t11.GetDeclaredMethod("m3"); + s_t12.GetDeclaredMethod("m1"); + s_t12.GetDeclaredMethod("m2"); + s_t12.GetDeclaredMethod("m3"); + s_t13.GetDeclaredMethod("m1"); + s_t13.GetDeclaredMethod("m2"); + s_t13.GetDeclaredMethod("m3"); + s_t14.GetDeclaredMethod("m1"); + s_t14.GetDeclaredMethod("m2"); + s_t14.GetDeclaredMethod("m3"); + s_t15.GetDeclaredMethod("m1"); + s_t15.GetDeclaredMethod("m2"); + s_t15.GetDeclaredMethod("m3"); + + s_t16.GetDeclaredMethod("m1"); + s_t16.GetDeclaredMethod("m2"); + s_t16.GetDeclaredMethod("m3"); + s_t17.GetDeclaredMethod("m1"); + s_t17.GetDeclaredMethod("m2"); + s_t17.GetDeclaredMethod("m3"); + s_t18.GetDeclaredMethod("m1"); + s_t18.GetDeclaredMethod("m2"); + s_t18.GetDeclaredMethod("m3"); + s_t19.GetDeclaredMethod("m1"); + s_t19.GetDeclaredMethod("m2"); + s_t19.GetDeclaredMethod("m3"); + s_t20.GetDeclaredMethod("m1"); + s_t20.GetDeclaredMethod("m2"); + s_t20.GetDeclaredMethod("m3"); + } } } } - } - /* - [Benchmark(InnerIterationCount=1000)] - public static void GetConstructor() - { - foreach (var iteration in Benchmark.Iterations) + /* + [Benchmark(InnerIterationCount=1000)] + public static void GetConstructor() { - using (iteration.StartMeasurement()) + foreach (var iteration in Benchmark.Iterations) { - s_t1.GetConstructor(new Type[] { }); - s_t1.GetConstructor(new Type[] { typeof(int) }); - s_t1.GetConstructor(new Type[] { typeof(int), typeof(int) }); - s_t2.GetConstructor(new Type[] { }); - s_t2.GetConstructor(new Type[] { typeof(int) }); - s_t2.GetConstructor(new Type[] { typeof(int), typeof(int) }); - s_t3.GetConstructor(new Type[] { }); - s_t3.GetConstructor(new Type[] { typeof(int) }); - s_t3.GetConstructor(new Type[] { typeof(int), typeof(int) }); - s_t4.GetConstructor(new Type[] { }); - s_t4.GetConstructor(new Type[] { typeof(int) }); - s_t4.GetConstructor(new Type[] { typeof(int), typeof(int) }); - s_t5.GetConstructor(new Type[] { }); - s_t5.GetConstructor(new Type[] { typeof(int) }); - s_t5.GetConstructor(new Type[] { typeof(int), typeof(int) }); + using (iteration.StartMeasurement()) + { + s_t1.GetConstructor(new Type[] { }); + s_t1.GetConstructor(new Type[] { typeof(int) }); + s_t1.GetConstructor(new Type[] { typeof(int), typeof(int) }); + s_t2.GetConstructor(new Type[] { }); + s_t2.GetConstructor(new Type[] { typeof(int) }); + s_t2.GetConstructor(new Type[] { typeof(int), typeof(int) }); + s_t3.GetConstructor(new Type[] { }); + s_t3.GetConstructor(new Type[] { typeof(int) }); + s_t3.GetConstructor(new Type[] { typeof(int), typeof(int) }); + s_t4.GetConstructor(new Type[] { }); + s_t4.GetConstructor(new Type[] { typeof(int) }); + s_t4.GetConstructor(new Type[] { typeof(int), typeof(int) }); + s_t5.GetConstructor(new Type[] { }); + s_t5.GetConstructor(new Type[] { typeof(int) }); + s_t5.GetConstructor(new Type[] { typeof(int), typeof(int) }); + } } } - } - [Benchmark(InnerIterationCount=1000)] - public static void GetProperty() - { - foreach (var iteration in Benchmark.Iterations) + [Benchmark(InnerIterationCount=1000)] + public static void GetProperty() { - using (iteration.StartMeasurement()) + foreach (var iteration in Benchmark.Iterations) { - PropertyInfo pi = s_t1.GetProperty("p1"); - pi.GetSetMethod(); - pi.GetGetMethod(); - pi = s_t1.GetProperty("p2"); - pi.GetSetMethod(); - pi.GetGetMethod(); - pi = s_t1.GetProperty("p3"); - pi.GetSetMethod(); - pi.GetGetMethod(); - pi = s_t2.GetProperty("p1"); - pi.GetSetMethod(); - pi.GetGetMethod(); - pi = s_t2.GetProperty("p2"); - pi.GetSetMethod(); - pi.GetGetMethod(); - pi = s_t2.GetProperty("p3"); - pi.GetSetMethod(); - pi.GetGetMethod(); - s_t3.GetProperty("p1"); - s_t3.GetProperty("p2"); - s_t3.GetProperty("p3"); - s_t4.GetProperty("p1"); - s_t4.GetProperty("p2"); - s_t4.GetProperty("p3"); - s_t5.GetProperty("p1"); - s_t5.GetProperty("p2"); - s_t5.GetProperty("p3"); + using (iteration.StartMeasurement()) + { + PropertyInfo pi = s_t1.GetProperty("p1"); + pi.GetSetMethod(); + pi.GetGetMethod(); + pi = s_t1.GetProperty("p2"); + pi.GetSetMethod(); + pi.GetGetMethod(); + pi = s_t1.GetProperty("p3"); + pi.GetSetMethod(); + pi.GetGetMethod(); + pi = s_t2.GetProperty("p1"); + pi.GetSetMethod(); + pi.GetGetMethod(); + pi = s_t2.GetProperty("p2"); + pi.GetSetMethod(); + pi.GetGetMethod(); + pi = s_t2.GetProperty("p3"); + pi.GetSetMethod(); + pi.GetGetMethod(); + s_t3.GetProperty("p1"); + s_t3.GetProperty("p2"); + s_t3.GetProperty("p3"); + s_t4.GetProperty("p1"); + s_t4.GetProperty("p2"); + s_t4.GetProperty("p3"); + s_t5.GetProperty("p1"); + s_t5.GetProperty("p2"); + s_t5.GetProperty("p3"); + } } } - } - [Benchmark(InnerIterationCount=1000)] - public static void GetEvent() - { - foreach (var iteration in Benchmark.Iterations) + [Benchmark(InnerIterationCount=1000)] + public static void GetEvent() { - using (iteration.StartMeasurement()) + foreach (var iteration in Benchmark.Iterations) { - EventInfo ei = s_t1.GetEvent("e1"); - ei.GetAddMethod(); - ei.GetRaiseMethod(); - ei.GetRemoveMethod(); - s_t1.GetEvent("e2"); - ei.GetAddMethod(); - ei.GetRaiseMethod(); - ei.GetRemoveMethod(); - s_t1.GetEvent("e3"); - ei.GetAddMethod(); - ei.GetRaiseMethod(); - ei.GetRemoveMethod(); - s_t2.GetEvent("e1"); - ei.GetAddMethod(); - ei.GetRaiseMethod(); - ei.GetRemoveMethod(); - s_t2.GetEvent("e2"); - ei.GetAddMethod(); - ei.GetRaiseMethod(); - ei.GetRemoveMethod(); - s_t2.GetEvent("e3"); - ei.GetAddMethod(); - ei.GetRaiseMethod(); - ei.GetRemoveMethod(); - s_t3.GetEvent("e1"); - s_t3.GetEvent("e2"); - s_t3.GetEvent("e3"); - s_t4.GetEvent("e1"); - s_t4.GetEvent("e2"); - s_t4.GetEvent("e3"); - s_t5.GetEvent("e1"); - s_t5.GetEvent("e2"); - s_t5.GetEvent("e3"); + using (iteration.StartMeasurement()) + { + EventInfo ei = s_t1.GetEvent("e1"); + ei.GetAddMethod(); + ei.GetRaiseMethod(); + ei.GetRemoveMethod(); + s_t1.GetEvent("e2"); + ei.GetAddMethod(); + ei.GetRaiseMethod(); + ei.GetRemoveMethod(); + s_t1.GetEvent("e3"); + ei.GetAddMethod(); + ei.GetRaiseMethod(); + ei.GetRemoveMethod(); + s_t2.GetEvent("e1"); + ei.GetAddMethod(); + ei.GetRaiseMethod(); + ei.GetRemoveMethod(); + s_t2.GetEvent("e2"); + ei.GetAddMethod(); + ei.GetRaiseMethod(); + ei.GetRemoveMethod(); + s_t2.GetEvent("e3"); + ei.GetAddMethod(); + ei.GetRaiseMethod(); + ei.GetRemoveMethod(); + s_t3.GetEvent("e1"); + s_t3.GetEvent("e2"); + s_t3.GetEvent("e3"); + s_t4.GetEvent("e1"); + s_t4.GetEvent("e2"); + s_t4.GetEvent("e3"); + s_t5.GetEvent("e1"); + s_t5.GetEvent("e2"); + s_t5.GetEvent("e3"); + } } } + */ } - */ -} -#region ClassDef -public class Class1 -{ - public Class1() { } - public Class1(int i) { } - public Class1(int i, int ii) { } - public int f0 = 0; - static public int f1 = 0; - public int f2 = 0; - public int f3 = 0; - public int f4 = 0; - public int f5 = 0; - public int f6 = 0; - public int f7 = 0; - public int f8 = 0; - public int f9 = 0; - public int f10 = 0; - public int f11 = 0; - public int f12 = 0; - public int f13 = 0; - public int f14 = 0; - public int f15 = 0; - public int f16 = 0; - public int f17 = 0; - public int f18 = 0; - public int f19 = 0; - public int f20 = 0; - public int f21 = 0; - public int f22 = 0; - public int f23 = 0; - public int f24 = 0; - - public void m1() { } - static public void m2() { } - public void m3() { } - public void m4() { } - public void m5() { } - public void m6() { } - public void m7() { } - public void m8() { } - public void m9() { } - public void m10() { } - public void m11() { } - public void m12() { } - public void m13() { } - public void m14() { } - public void m15() { } - public void m16() { } - public void m17() { } - public void m18() { } - public void m19() { } - public void m20() { } - public void m21() { } - public void m22() { } - public void m23() { } - public void m24() { } - - public int p0 { get { return 1; } set { } } - static public int p1 { get { return 1; } set { } } - public int p2 { get { return 1; } set { } } - public int p3 { get { return 1; } set { } } - public int p4 { get { return 1; } set { } } - public int p5 { get { return 1; } set { } } - public int p6 { get { return 1; } set { } } - public int p7 { get { return 1; } set { } } - public int p8 { get { return 1; } set { } } - public int p9 { get { return 1; } set { } } - public int p10 { get { return 1; } set { } } - public int p11 { get { return 1; } set { } } - public int p12 { get { return 1; } set { } } - public int p13 { get { return 1; } set { } } - public int p14 { get { return 1; } set { } } - public int p15 { get { return 1; } set { } } - public int p16 { get { return 1; } set { } } - public int p17 { get { return 1; } set { } } - public int p18 { get { return 1; } set { } } - public int p19 { get { return 1; } set { } } - public int p20 { get { return 1; } set { } } - public int p21 { get { return 1; } set { } } - public int p22 { get { return 1; } set { } } - public int p23 { get { return 1; } set { } } - public int p24 { get { return 1; } set { } } - - public event d e0; - static public event d e1; - public event d e2; - public event d e3; - public event d e4; - public event d e5; - public event d e6; - public event d e7; - public event d e8; - public event d e9; - public event d e10; - public event d e11; - public event d e12; - public event d e13; - public event d e14; - public event d e15; - public event d e16; - public event d e17; - public event d e18; - public event d e19; - public event d e20; - public event d e21; - public event d e22; - public event d e23; - public event d e24; - - public void NoWarning() + #region ClassDef + public class Class1 { - e0 += new d(m1); - e1 += new d(m1); - e2 += new d(m1); - e3 += new d(m1); - e4 += new d(m1); - e5 += new d(m1); - e6 += new d(m1); - e7 += new d(m1); - e8 += new d(m1); - e9 += new d(m1); - e10 += new d(m1); - e11 += new d(m1); - e12 += new d(m1); - e13 += new d(m1); - e14 += new d(m1); - e15 += new d(m1); - e16 += new d(m1); - e17 += new d(m1); - e18 += new d(m1); - e19 += new d(m1); - e20 += new d(m1); - e21 += new d(m1); - e22 += new d(m1); - e23 += new d(m1); - e24 += new d(m1); + public Class1() { } + public Class1(int i) { } + public Class1(int i, int ii) { } + public int f0 = 0; + static public int f1 = 0; + public int f2 = 0; + public int f3 = 0; + public int f4 = 0; + public int f5 = 0; + public int f6 = 0; + public int f7 = 0; + public int f8 = 0; + public int f9 = 0; + public int f10 = 0; + public int f11 = 0; + public int f12 = 0; + public int f13 = 0; + public int f14 = 0; + public int f15 = 0; + public int f16 = 0; + public int f17 = 0; + public int f18 = 0; + public int f19 = 0; + public int f20 = 0; + public int f21 = 0; + public int f22 = 0; + public int f23 = 0; + public int f24 = 0; + + public void m1() { } + static public void m2() { } + public void m3() { } + public void m4() { } + public void m5() { } + public void m6() { } + public void m7() { } + public void m8() { } + public void m9() { } + public void m10() { } + public void m11() { } + public void m12() { } + public void m13() { } + public void m14() { } + public void m15() { } + public void m16() { } + public void m17() { } + public void m18() { } + public void m19() { } + public void m20() { } + public void m21() { } + public void m22() { } + public void m23() { } + public void m24() { } + + public int p0 { get { return 1; } set { } } + static public int p1 { get { return 1; } set { } } + public int p2 { get { return 1; } set { } } + public int p3 { get { return 1; } set { } } + public int p4 { get { return 1; } set { } } + public int p5 { get { return 1; } set { } } + public int p6 { get { return 1; } set { } } + public int p7 { get { return 1; } set { } } + public int p8 { get { return 1; } set { } } + public int p9 { get { return 1; } set { } } + public int p10 { get { return 1; } set { } } + public int p11 { get { return 1; } set { } } + public int p12 { get { return 1; } set { } } + public int p13 { get { return 1; } set { } } + public int p14 { get { return 1; } set { } } + public int p15 { get { return 1; } set { } } + public int p16 { get { return 1; } set { } } + public int p17 { get { return 1; } set { } } + public int p18 { get { return 1; } set { } } + public int p19 { get { return 1; } set { } } + public int p20 { get { return 1; } set { } } + public int p21 { get { return 1; } set { } } + public int p22 { get { return 1; } set { } } + public int p23 { get { return 1; } set { } } + public int p24 { get { return 1; } set { } } + + public event d e0; + static public event d e1; + public event d e2; + public event d e3; + public event d e4; + public event d e5; + public event d e6; + public event d e7; + public event d e8; + public event d e9; + public event d e10; + public event d e11; + public event d e12; + public event d e13; + public event d e14; + public event d e15; + public event d e16; + public event d e17; + public event d e18; + public event d e19; + public event d e20; + public event d e21; + public event d e22; + public event d e23; + public event d e24; + + public void NoWarning() + { + e0 += new d(m1); + e1 += new d(m1); + e2 += new d(m1); + e3 += new d(m1); + e4 += new d(m1); + e5 += new d(m1); + e6 += new d(m1); + e7 += new d(m1); + e8 += new d(m1); + e9 += new d(m1); + e10 += new d(m1); + e11 += new d(m1); + e12 += new d(m1); + e13 += new d(m1); + e14 += new d(m1); + e15 += new d(m1); + e16 += new d(m1); + e17 += new d(m1); + e18 += new d(m1); + e19 += new d(m1); + e20 += new d(m1); + e21 += new d(m1); + e22 += new d(m1); + e23 += new d(m1); + e24 += new d(m1); + } } -} -public class Class2 -{ - public Class2() { } - public Class2(int i) { } - public Class2(int i, int ii) { } - public int f0 = 0; - static public int f1 = 0; - public int f2 = 0; - public int f3 = 0; - public int f4 = 0; - public int f5 = 0; - public int f6 = 0; - public int f7 = 0; - public int f8 = 0; - public int f9 = 0; - public int f10 = 0; - public int f11 = 0; - public int f12 = 0; - public int f13 = 0; - public int f14 = 0; - public int f15 = 0; - public int f16 = 0; - public int f17 = 0; - public int f18 = 0; - public int f19 = 0; - public int f20 = 0; - public int f21 = 0; - public int f22 = 0; - public int f23 = 0; - public int f24 = 0; - - public void m1() { } - static public void m2() { } - public void m3() { } - public void m4() { } - public void m5() { } - public void m6() { } - public void m7() { } - public void m8() { } - public void m9() { } - public void m10() { } - public void m11() { } - public void m12() { } - public void m13() { } - public void m14() { } - public void m15() { } - public void m16() { } - public void m17() { } - public void m18() { } - public void m19() { } - public void m20() { } - public void m21() { } - public void m22() { } - public void m23() { } - public void m24() { } - - public int p0 { get { return 1; } set { } } - static public int p1 { get { return 1; } set { } } - public int p2 { get { return 1; } set { } } - public int p3 { get { return 1; } set { } } - public int p4 { get { return 1; } set { } } - public int p5 { get { return 1; } set { } } - public int p6 { get { return 1; } set { } } - public int p7 { get { return 1; } set { } } - public int p8 { get { return 1; } set { } } - public int p9 { get { return 1; } set { } } - public int p10 { get { return 1; } set { } } - public int p11 { get { return 1; } set { } } - public int p12 { get { return 1; } set { } } - public int p13 { get { return 1; } set { } } - public int p14 { get { return 1; } set { } } - public int p15 { get { return 1; } set { } } - public int p16 { get { return 1; } set { } } - public int p17 { get { return 1; } set { } } - public int p18 { get { return 1; } set { } } - public int p19 { get { return 1; } set { } } - public int p20 { get { return 1; } set { } } - public int p21 { get { return 1; } set { } } - public int p22 { get { return 1; } set { } } - public int p23 { get { return 1; } set { } } - public int p24 { get { return 1; } set { } } - - public event d e0; - static public event d e1; - public event d e2; - public event d e3; - public event d e4; - public event d e5; - public event d e6; - public event d e7; - public event d e8; - public event d e9; - public event d e10; - public event d e11; - public event d e12; - public event d e13; - public event d e14; - public event d e15; - public event d e16; - public event d e17; - public event d e18; - public event d e19; - public event d e20; - public event d e21; - public event d e22; - public event d e23; - public event d e24; - - public void NoWarning() + public class Class2 { - e0 += new d(m1); - e1 += new d(m1); - e2 += new d(m1); - e3 += new d(m1); - e4 += new d(m1); - e5 += new d(m1); - e6 += new d(m1); - e7 += new d(m1); - e8 += new d(m1); - e9 += new d(m1); - e10 += new d(m1); - e11 += new d(m1); - e12 += new d(m1); - e13 += new d(m1); - e14 += new d(m1); - e15 += new d(m1); - e16 += new d(m1); - e17 += new d(m1); - e18 += new d(m1); - e19 += new d(m1); - e20 += new d(m1); - e21 += new d(m1); - e22 += new d(m1); - e23 += new d(m1); - e24 += new d(m1); + public Class2() { } + public Class2(int i) { } + public Class2(int i, int ii) { } + public int f0 = 0; + static public int f1 = 0; + public int f2 = 0; + public int f3 = 0; + public int f4 = 0; + public int f5 = 0; + public int f6 = 0; + public int f7 = 0; + public int f8 = 0; + public int f9 = 0; + public int f10 = 0; + public int f11 = 0; + public int f12 = 0; + public int f13 = 0; + public int f14 = 0; + public int f15 = 0; + public int f16 = 0; + public int f17 = 0; + public int f18 = 0; + public int f19 = 0; + public int f20 = 0; + public int f21 = 0; + public int f22 = 0; + public int f23 = 0; + public int f24 = 0; + + public void m1() { } + static public void m2() { } + public void m3() { } + public void m4() { } + public void m5() { } + public void m6() { } + public void m7() { } + public void m8() { } + public void m9() { } + public void m10() { } + public void m11() { } + public void m12() { } + public void m13() { } + public void m14() { } + public void m15() { } + public void m16() { } + public void m17() { } + public void m18() { } + public void m19() { } + public void m20() { } + public void m21() { } + public void m22() { } + public void m23() { } + public void m24() { } + + public int p0 { get { return 1; } set { } } + static public int p1 { get { return 1; } set { } } + public int p2 { get { return 1; } set { } } + public int p3 { get { return 1; } set { } } + public int p4 { get { return 1; } set { } } + public int p5 { get { return 1; } set { } } + public int p6 { get { return 1; } set { } } + public int p7 { get { return 1; } set { } } + public int p8 { get { return 1; } set { } } + public int p9 { get { return 1; } set { } } + public int p10 { get { return 1; } set { } } + public int p11 { get { return 1; } set { } } + public int p12 { get { return 1; } set { } } + public int p13 { get { return 1; } set { } } + public int p14 { get { return 1; } set { } } + public int p15 { get { return 1; } set { } } + public int p16 { get { return 1; } set { } } + public int p17 { get { return 1; } set { } } + public int p18 { get { return 1; } set { } } + public int p19 { get { return 1; } set { } } + public int p20 { get { return 1; } set { } } + public int p21 { get { return 1; } set { } } + public int p22 { get { return 1; } set { } } + public int p23 { get { return 1; } set { } } + public int p24 { get { return 1; } set { } } + + public event d e0; + static public event d e1; + public event d e2; + public event d e3; + public event d e4; + public event d e5; + public event d e6; + public event d e7; + public event d e8; + public event d e9; + public event d e10; + public event d e11; + public event d e12; + public event d e13; + public event d e14; + public event d e15; + public event d e16; + public event d e17; + public event d e18; + public event d e19; + public event d e20; + public event d e21; + public event d e22; + public event d e23; + public event d e24; + + public void NoWarning() + { + e0 += new d(m1); + e1 += new d(m1); + e2 += new d(m1); + e3 += new d(m1); + e4 += new d(m1); + e5 += new d(m1); + e6 += new d(m1); + e7 += new d(m1); + e8 += new d(m1); + e9 += new d(m1); + e10 += new d(m1); + e11 += new d(m1); + e12 += new d(m1); + e13 += new d(m1); + e14 += new d(m1); + e15 += new d(m1); + e16 += new d(m1); + e17 += new d(m1); + e18 += new d(m1); + e19 += new d(m1); + e20 += new d(m1); + e21 += new d(m1); + e22 += new d(m1); + e23 += new d(m1); + e24 += new d(m1); + } } -} -public class Class3 -{ - public Class3() { } - public Class3(int i) { } - public Class3(int i, int ii) { } - public int f0 = 0; - static public int f1 = 0; - public int f2 = 0; - public int f3 = 0; - public int f4 = 0; - public int f5 = 0; - public int f6 = 0; - public int f7 = 0; - public int f8 = 0; - public int f9 = 0; - public int f10 = 0; - public int f11 = 0; - public int f12 = 0; - public int f13 = 0; - public int f14 = 0; - public int f15 = 0; - public int f16 = 0; - public int f17 = 0; - public int f18 = 0; - public int f19 = 0; - public int f20 = 0; - public int f21 = 0; - public int f22 = 0; - public int f23 = 0; - public int f24 = 0; - - public void m1() { } - static public void m2() { } - public void m3() { } - public void m4() { } - public void m5() { } - public void m6() { } - public void m7() { } - public void m8() { } - public void m9() { } - public void m10() { } - public void m11() { } - public void m12() { } - public void m13() { } - public void m14() { } - public void m15() { } - public void m16() { } - public void m17() { } - public void m18() { } - public void m19() { } - public void m20() { } - public void m21() { } - public void m22() { } - public void m23() { } - public void m24() { } - - public int p0 { get { return 1; } set { } } - static public int p1 { get { return 1; } set { } } - public int p2 { get { return 1; } set { } } - public int p3 { get { return 1; } set { } } - public int p4 { get { return 1; } set { } } - public int p5 { get { return 1; } set { } } - public int p6 { get { return 1; } set { } } - public int p7 { get { return 1; } set { } } - public int p8 { get { return 1; } set { } } - public int p9 { get { return 1; } set { } } - public int p10 { get { return 1; } set { } } - public int p11 { get { return 1; } set { } } - public int p12 { get { return 1; } set { } } - public int p13 { get { return 1; } set { } } - public int p14 { get { return 1; } set { } } - public int p15 { get { return 1; } set { } } - public int p16 { get { return 1; } set { } } - public int p17 { get { return 1; } set { } } - public int p18 { get { return 1; } set { } } - public int p19 { get { return 1; } set { } } - public int p20 { get { return 1; } set { } } - public int p21 { get { return 1; } set { } } - public int p22 { get { return 1; } set { } } - public int p23 { get { return 1; } set { } } - public int p24 { get { return 1; } set { } } - - public event d e0; - static public event d e1; - public event d e2; - public event d e3; - public event d e4; - public event d e5; - public event d e6; - public event d e7; - public event d e8; - public event d e9; - public event d e10; - public event d e11; - public event d e12; - public event d e13; - public event d e14; - public event d e15; - public event d e16; - public event d e17; - public event d e18; - public event d e19; - public event d e20; - public event d e21; - public event d e22; - public event d e23; - public event d e24; - - public void NoWarning() + public class Class3 { - e0 += new d(m1); - e1 += new d(m1); - e2 += new d(m1); - e3 += new d(m1); - e4 += new d(m1); - e5 += new d(m1); - e6 += new d(m1); - e7 += new d(m1); - e8 += new d(m1); - e9 += new d(m1); - e10 += new d(m1); - e11 += new d(m1); - e12 += new d(m1); - e13 += new d(m1); - e14 += new d(m1); - e15 += new d(m1); - e16 += new d(m1); - e17 += new d(m1); - e18 += new d(m1); - e19 += new d(m1); - e20 += new d(m1); - e21 += new d(m1); - e22 += new d(m1); - e23 += new d(m1); - e24 += new d(m1); + public Class3() { } + public Class3(int i) { } + public Class3(int i, int ii) { } + public int f0 = 0; + static public int f1 = 0; + public int f2 = 0; + public int f3 = 0; + public int f4 = 0; + public int f5 = 0; + public int f6 = 0; + public int f7 = 0; + public int f8 = 0; + public int f9 = 0; + public int f10 = 0; + public int f11 = 0; + public int f12 = 0; + public int f13 = 0; + public int f14 = 0; + public int f15 = 0; + public int f16 = 0; + public int f17 = 0; + public int f18 = 0; + public int f19 = 0; + public int f20 = 0; + public int f21 = 0; + public int f22 = 0; + public int f23 = 0; + public int f24 = 0; + + public void m1() { } + static public void m2() { } + public void m3() { } + public void m4() { } + public void m5() { } + public void m6() { } + public void m7() { } + public void m8() { } + public void m9() { } + public void m10() { } + public void m11() { } + public void m12() { } + public void m13() { } + public void m14() { } + public void m15() { } + public void m16() { } + public void m17() { } + public void m18() { } + public void m19() { } + public void m20() { } + public void m21() { } + public void m22() { } + public void m23() { } + public void m24() { } + + public int p0 { get { return 1; } set { } } + static public int p1 { get { return 1; } set { } } + public int p2 { get { return 1; } set { } } + public int p3 { get { return 1; } set { } } + public int p4 { get { return 1; } set { } } + public int p5 { get { return 1; } set { } } + public int p6 { get { return 1; } set { } } + public int p7 { get { return 1; } set { } } + public int p8 { get { return 1; } set { } } + public int p9 { get { return 1; } set { } } + public int p10 { get { return 1; } set { } } + public int p11 { get { return 1; } set { } } + public int p12 { get { return 1; } set { } } + public int p13 { get { return 1; } set { } } + public int p14 { get { return 1; } set { } } + public int p15 { get { return 1; } set { } } + public int p16 { get { return 1; } set { } } + public int p17 { get { return 1; } set { } } + public int p18 { get { return 1; } set { } } + public int p19 { get { return 1; } set { } } + public int p20 { get { return 1; } set { } } + public int p21 { get { return 1; } set { } } + public int p22 { get { return 1; } set { } } + public int p23 { get { return 1; } set { } } + public int p24 { get { return 1; } set { } } + + public event d e0; + static public event d e1; + public event d e2; + public event d e3; + public event d e4; + public event d e5; + public event d e6; + public event d e7; + public event d e8; + public event d e9; + public event d e10; + public event d e11; + public event d e12; + public event d e13; + public event d e14; + public event d e15; + public event d e16; + public event d e17; + public event d e18; + public event d e19; + public event d e20; + public event d e21; + public event d e22; + public event d e23; + public event d e24; + + public void NoWarning() + { + e0 += new d(m1); + e1 += new d(m1); + e2 += new d(m1); + e3 += new d(m1); + e4 += new d(m1); + e5 += new d(m1); + e6 += new d(m1); + e7 += new d(m1); + e8 += new d(m1); + e9 += new d(m1); + e10 += new d(m1); + e11 += new d(m1); + e12 += new d(m1); + e13 += new d(m1); + e14 += new d(m1); + e15 += new d(m1); + e16 += new d(m1); + e17 += new d(m1); + e18 += new d(m1); + e19 += new d(m1); + e20 += new d(m1); + e21 += new d(m1); + e22 += new d(m1); + e23 += new d(m1); + e24 += new d(m1); + } } -} -public class Class4 -{ - public Class4() { } - public Class4(int i) { } - public Class4(int i, int ii) { } - - public int f0 = 0; - static public int f1 = 0; - public int f2 = 0; - public int f3 = 0; - public int f4 = 0; - public int f5 = 0; - public int f6 = 0; - public int f7 = 0; - public int f8 = 0; - public int f9 = 0; - public int f10 = 0; - public int f11 = 0; - public int f12 = 0; - public int f13 = 0; - public int f14 = 0; - public int f15 = 0; - public int f16 = 0; - public int f17 = 0; - public int f18 = 0; - public int f19 = 0; - public int f20 = 0; - public int f21 = 0; - public int f22 = 0; - public int f23 = 0; - public int f24 = 0; - - public void m1() { } - static public void m2() { } - public void m3() { } - public void m4() { } - public void m5() { } - public void m6() { } - public void m7() { } - public void m8() { } - public void m9() { } - public void m10() { } - public void m11() { } - public void m12() { } - public void m13() { } - public void m14() { } - public void m15() { } - public void m16() { } - public void m17() { } - public void m18() { } - public void m19() { } - public void m20() { } - public void m21() { } - public void m22() { } - public void m23() { } - public void m24() { } - - public int p0 { get { return 1; } set { } } - static public int p1 { get { return 1; } set { } } - public int p2 { get { return 1; } set { } } - public int p3 { get { return 1; } set { } } - public int p4 { get { return 1; } set { } } - public int p5 { get { return 1; } set { } } - public int p6 { get { return 1; } set { } } - public int p7 { get { return 1; } set { } } - public int p8 { get { return 1; } set { } } - public int p9 { get { return 1; } set { } } - public int p10 { get { return 1; } set { } } - public int p11 { get { return 1; } set { } } - public int p12 { get { return 1; } set { } } - public int p13 { get { return 1; } set { } } - public int p14 { get { return 1; } set { } } - public int p15 { get { return 1; } set { } } - public int p16 { get { return 1; } set { } } - public int p17 { get { return 1; } set { } } - public int p18 { get { return 1; } set { } } - public int p19 { get { return 1; } set { } } - public int p20 { get { return 1; } set { } } - public int p21 { get { return 1; } set { } } - public int p22 { get { return 1; } set { } } - public int p23 { get { return 1; } set { } } - public int p24 { get { return 1; } set { } } - - public event d e0; - static public event d e1; - public event d e2; - public event d e3; - public event d e4; - public event d e5; - public event d e6; - public event d e7; - public event d e8; - public event d e9; - public event d e10; - public event d e11; - public event d e12; - public event d e13; - public event d e14; - public event d e15; - public event d e16; - public event d e17; - public event d e18; - public event d e19; - public event d e20; - public event d e21; - public event d e22; - public event d e23; - public event d e24; - - public void NoWarning() + public class Class4 { - e0 += new d(m1); - e1 += new d(m1); - e2 += new d(m1); - e3 += new d(m1); - e4 += new d(m1); - e5 += new d(m1); - e6 += new d(m1); - e7 += new d(m1); - e8 += new d(m1); - e9 += new d(m1); - e10 += new d(m1); - e11 += new d(m1); - e12 += new d(m1); - e13 += new d(m1); - e14 += new d(m1); - e15 += new d(m1); - e16 += new d(m1); - e17 += new d(m1); - e18 += new d(m1); - e19 += new d(m1); - e20 += new d(m1); - e21 += new d(m1); - e22 += new d(m1); - e23 += new d(m1); - e24 += new d(m1); + public Class4() { } + public Class4(int i) { } + public Class4(int i, int ii) { } + + public int f0 = 0; + static public int f1 = 0; + public int f2 = 0; + public int f3 = 0; + public int f4 = 0; + public int f5 = 0; + public int f6 = 0; + public int f7 = 0; + public int f8 = 0; + public int f9 = 0; + public int f10 = 0; + public int f11 = 0; + public int f12 = 0; + public int f13 = 0; + public int f14 = 0; + public int f15 = 0; + public int f16 = 0; + public int f17 = 0; + public int f18 = 0; + public int f19 = 0; + public int f20 = 0; + public int f21 = 0; + public int f22 = 0; + public int f23 = 0; + public int f24 = 0; + + public void m1() { } + static public void m2() { } + public void m3() { } + public void m4() { } + public void m5() { } + public void m6() { } + public void m7() { } + public void m8() { } + public void m9() { } + public void m10() { } + public void m11() { } + public void m12() { } + public void m13() { } + public void m14() { } + public void m15() { } + public void m16() { } + public void m17() { } + public void m18() { } + public void m19() { } + public void m20() { } + public void m21() { } + public void m22() { } + public void m23() { } + public void m24() { } + + public int p0 { get { return 1; } set { } } + static public int p1 { get { return 1; } set { } } + public int p2 { get { return 1; } set { } } + public int p3 { get { return 1; } set { } } + public int p4 { get { return 1; } set { } } + public int p5 { get { return 1; } set { } } + public int p6 { get { return 1; } set { } } + public int p7 { get { return 1; } set { } } + public int p8 { get { return 1; } set { } } + public int p9 { get { return 1; } set { } } + public int p10 { get { return 1; } set { } } + public int p11 { get { return 1; } set { } } + public int p12 { get { return 1; } set { } } + public int p13 { get { return 1; } set { } } + public int p14 { get { return 1; } set { } } + public int p15 { get { return 1; } set { } } + public int p16 { get { return 1; } set { } } + public int p17 { get { return 1; } set { } } + public int p18 { get { return 1; } set { } } + public int p19 { get { return 1; } set { } } + public int p20 { get { return 1; } set { } } + public int p21 { get { return 1; } set { } } + public int p22 { get { return 1; } set { } } + public int p23 { get { return 1; } set { } } + public int p24 { get { return 1; } set { } } + + public event d e0; + static public event d e1; + public event d e2; + public event d e3; + public event d e4; + public event d e5; + public event d e6; + public event d e7; + public event d e8; + public event d e9; + public event d e10; + public event d e11; + public event d e12; + public event d e13; + public event d e14; + public event d e15; + public event d e16; + public event d e17; + public event d e18; + public event d e19; + public event d e20; + public event d e21; + public event d e22; + public event d e23; + public event d e24; + + public void NoWarning() + { + e0 += new d(m1); + e1 += new d(m1); + e2 += new d(m1); + e3 += new d(m1); + e4 += new d(m1); + e5 += new d(m1); + e6 += new d(m1); + e7 += new d(m1); + e8 += new d(m1); + e9 += new d(m1); + e10 += new d(m1); + e11 += new d(m1); + e12 += new d(m1); + e13 += new d(m1); + e14 += new d(m1); + e15 += new d(m1); + e16 += new d(m1); + e17 += new d(m1); + e18 += new d(m1); + e19 += new d(m1); + e20 += new d(m1); + e21 += new d(m1); + e22 += new d(m1); + e23 += new d(m1); + e24 += new d(m1); + } } -} -public class Class5 -{ - public Class5() { } - public Class5(int i) { } - public Class5(int i, int ii) { } - - public int f0 = 0; - static public int f1 = 0; - public int f2 = 0; - public int f3 = 0; - public int f4 = 0; - public int f5 = 0; - public int f6 = 0; - public int f7 = 0; - public int f8 = 0; - public int f9 = 0; - public int f10 = 0; - public int f11 = 0; - public int f12 = 0; - public int f13 = 0; - public int f14 = 0; - public int f15 = 0; - public int f16 = 0; - public int f17 = 0; - public int f18 = 0; - public int f19 = 0; - public int f20 = 0; - public int f21 = 0; - public int f22 = 0; - public int f23 = 0; - public int f24 = 0; - - public void m1() { } - static public void m2() { } - public void m3() { } - public void m4() { } - public void m5() { } - public void m6() { } - public void m7() { } - public void m8() { } - public void m9() { } - public void m10() { } - public void m11() { } - public void m12() { } - public void m13() { } - public void m14() { } - public void m15() { } - public void m16() { } - public void m17() { } - public void m18() { } - public void m19() { } - public void m20() { } - public void m21() { } - public void m22() { } - public void m23() { } - public void m24() { } - - public int p0 { get { return 1; } set { } } - static public int p1 { get { return 1; } set { } } - public int p2 { get { return 1; } set { } } - public int p3 { get { return 1; } set { } } - public int p4 { get { return 1; } set { } } - public int p5 { get { return 1; } set { } } - public int p6 { get { return 1; } set { } } - public int p7 { get { return 1; } set { } } - public int p8 { get { return 1; } set { } } - public int p9 { get { return 1; } set { } } - public int p10 { get { return 1; } set { } } - public int p11 { get { return 1; } set { } } - public int p12 { get { return 1; } set { } } - public int p13 { get { return 1; } set { } } - public int p14 { get { return 1; } set { } } - public int p15 { get { return 1; } set { } } - public int p16 { get { return 1; } set { } } - public int p17 { get { return 1; } set { } } - public int p18 { get { return 1; } set { } } - public int p19 { get { return 1; } set { } } - public int p20 { get { return 1; } set { } } - public int p21 { get { return 1; } set { } } - public int p22 { get { return 1; } set { } } - public int p23 { get { return 1; } set { } } - public int p24 { get { return 1; } set { } } - - public event d e0; - static public event d e1; - public event d e2; - public event d e3; - public event d e4; - public event d e5; - public event d e6; - public event d e7; - public event d e8; - public event d e9; - public event d e10; - public event d e11; - public event d e12; - public event d e13; - public event d e14; - public event d e15; - public event d e16; - public event d e17; - public event d e18; - public event d e19; - public event d e20; - public event d e21; - public event d e22; - public event d e23; - public event d e24; - - public void NoWarning() + public class Class5 { - e0 += new d(m1); - e1 += new d(m1); - e2 += new d(m1); - e3 += new d(m1); - e4 += new d(m1); - e5 += new d(m1); - e6 += new d(m1); - e7 += new d(m1); - e8 += new d(m1); - e9 += new d(m1); - e10 += new d(m1); - e11 += new d(m1); - e12 += new d(m1); - e13 += new d(m1); - e14 += new d(m1); - e15 += new d(m1); - e16 += new d(m1); - e17 += new d(m1); - e18 += new d(m1); - e19 += new d(m1); - e20 += new d(m1); - e21 += new d(m1); - e22 += new d(m1); - e23 += new d(m1); - e24 += new d(m1); + public Class5() { } + public Class5(int i) { } + public Class5(int i, int ii) { } + + public int f0 = 0; + static public int f1 = 0; + public int f2 = 0; + public int f3 = 0; + public int f4 = 0; + public int f5 = 0; + public int f6 = 0; + public int f7 = 0; + public int f8 = 0; + public int f9 = 0; + public int f10 = 0; + public int f11 = 0; + public int f12 = 0; + public int f13 = 0; + public int f14 = 0; + public int f15 = 0; + public int f16 = 0; + public int f17 = 0; + public int f18 = 0; + public int f19 = 0; + public int f20 = 0; + public int f21 = 0; + public int f22 = 0; + public int f23 = 0; + public int f24 = 0; + + public void m1() { } + static public void m2() { } + public void m3() { } + public void m4() { } + public void m5() { } + public void m6() { } + public void m7() { } + public void m8() { } + public void m9() { } + public void m10() { } + public void m11() { } + public void m12() { } + public void m13() { } + public void m14() { } + public void m15() { } + public void m16() { } + public void m17() { } + public void m18() { } + public void m19() { } + public void m20() { } + public void m21() { } + public void m22() { } + public void m23() { } + public void m24() { } + + public int p0 { get { return 1; } set { } } + static public int p1 { get { return 1; } set { } } + public int p2 { get { return 1; } set { } } + public int p3 { get { return 1; } set { } } + public int p4 { get { return 1; } set { } } + public int p5 { get { return 1; } set { } } + public int p6 { get { return 1; } set { } } + public int p7 { get { return 1; } set { } } + public int p8 { get { return 1; } set { } } + public int p9 { get { return 1; } set { } } + public int p10 { get { return 1; } set { } } + public int p11 { get { return 1; } set { } } + public int p12 { get { return 1; } set { } } + public int p13 { get { return 1; } set { } } + public int p14 { get { return 1; } set { } } + public int p15 { get { return 1; } set { } } + public int p16 { get { return 1; } set { } } + public int p17 { get { return 1; } set { } } + public int p18 { get { return 1; } set { } } + public int p19 { get { return 1; } set { } } + public int p20 { get { return 1; } set { } } + public int p21 { get { return 1; } set { } } + public int p22 { get { return 1; } set { } } + public int p23 { get { return 1; } set { } } + public int p24 { get { return 1; } set { } } + + public event d e0; + static public event d e1; + public event d e2; + public event d e3; + public event d e4; + public event d e5; + public event d e6; + public event d e7; + public event d e8; + public event d e9; + public event d e10; + public event d e11; + public event d e12; + public event d e13; + public event d e14; + public event d e15; + public event d e16; + public event d e17; + public event d e18; + public event d e19; + public event d e20; + public event d e21; + public event d e22; + public event d e23; + public event d e24; + + public void NoWarning() + { + e0 += new d(m1); + e1 += new d(m1); + e2 += new d(m1); + e3 += new d(m1); + e4 += new d(m1); + e5 += new d(m1); + e6 += new d(m1); + e7 += new d(m1); + e8 += new d(m1); + e9 += new d(m1); + e10 += new d(m1); + e11 += new d(m1); + e12 += new d(m1); + e13 += new d(m1); + e14 += new d(m1); + e15 += new d(m1); + e16 += new d(m1); + e17 += new d(m1); + e18 += new d(m1); + e19 += new d(m1); + e20 += new d(m1); + e21 += new d(m1); + e22 += new d(m1); + e23 += new d(m1); + e24 += new d(m1); + } } -} -public class Class6 -{ - public Class6() { } - public Class6(int i) { } - public Class6(int i, int ii) { } - - public int f0 = 0; - static public int f1 = 0; - public int f2 = 0; - public int f3 = 0; - public int f4 = 0; - public int f5 = 0; - public int f6 = 0; - public int f7 = 0; - public int f8 = 0; - public int f9 = 0; - public int f10 = 0; - public int f11 = 0; - public int f12 = 0; - public int f13 = 0; - public int f14 = 0; - public int f15 = 0; - public int f16 = 0; - public int f17 = 0; - public int f18 = 0; - public int f19 = 0; - public int f20 = 0; - public int f21 = 0; - public int f22 = 0; - public int f23 = 0; - public int f24 = 0; - - public void m1() { } - static public void m2() { } - public void m3() { } - public void m4() { } - public void m5() { } - public void m6() { } - public void m7() { } - public void m8() { } - public void m9() { } - public void m10() { } - public void m11() { } - public void m12() { } - public void m13() { } - public void m14() { } - public void m15() { } - public void m16() { } - public void m17() { } - public void m18() { } - public void m19() { } - public void m20() { } - public void m21() { } - public void m22() { } - public void m23() { } - public void m24() { } - - public int p0 { get { return 1; } set { } } - static public int p1 { get { return 1; } set { } } - public int p2 { get { return 1; } set { } } - public int p3 { get { return 1; } set { } } - public int p4 { get { return 1; } set { } } - public int p5 { get { return 1; } set { } } - public int p6 { get { return 1; } set { } } - public int p7 { get { return 1; } set { } } - public int p8 { get { return 1; } set { } } - public int p9 { get { return 1; } set { } } - public int p10 { get { return 1; } set { } } - public int p11 { get { return 1; } set { } } - public int p12 { get { return 1; } set { } } - public int p13 { get { return 1; } set { } } - public int p14 { get { return 1; } set { } } - public int p15 { get { return 1; } set { } } - public int p16 { get { return 1; } set { } } - public int p17 { get { return 1; } set { } } - public int p18 { get { return 1; } set { } } - public int p19 { get { return 1; } set { } } - public int p20 { get { return 1; } set { } } - public int p21 { get { return 1; } set { } } - public int p22 { get { return 1; } set { } } - public int p23 { get { return 1; } set { } } - public int p24 { get { return 1; } set { } } - - public event d e0; - static public event d e1; - public event d e2; - public event d e3; - public event d e4; - public event d e5; - public event d e6; - public event d e7; - public event d e8; - public event d e9; - public event d e10; - public event d e11; - public event d e12; - public event d e13; - public event d e14; - public event d e15; - public event d e16; - public event d e17; - public event d e18; - public event d e19; - public event d e20; - public event d e21; - public event d e22; - public event d e23; - public event d e24; - - public void NoWarning() + public class Class6 { - e0 += new d(m1); - e1 += new d(m1); - e2 += new d(m1); - e3 += new d(m1); - e4 += new d(m1); - e5 += new d(m1); - e6 += new d(m1); - e7 += new d(m1); - e8 += new d(m1); - e9 += new d(m1); - e10 += new d(m1); - e11 += new d(m1); - e12 += new d(m1); - e13 += new d(m1); - e14 += new d(m1); - e15 += new d(m1); - e16 += new d(m1); - e17 += new d(m1); - e18 += new d(m1); - e19 += new d(m1); - e20 += new d(m1); - e21 += new d(m1); - e22 += new d(m1); - e23 += new d(m1); - e24 += new d(m1); + public Class6() { } + public Class6(int i) { } + public Class6(int i, int ii) { } + + public int f0 = 0; + static public int f1 = 0; + public int f2 = 0; + public int f3 = 0; + public int f4 = 0; + public int f5 = 0; + public int f6 = 0; + public int f7 = 0; + public int f8 = 0; + public int f9 = 0; + public int f10 = 0; + public int f11 = 0; + public int f12 = 0; + public int f13 = 0; + public int f14 = 0; + public int f15 = 0; + public int f16 = 0; + public int f17 = 0; + public int f18 = 0; + public int f19 = 0; + public int f20 = 0; + public int f21 = 0; + public int f22 = 0; + public int f23 = 0; + public int f24 = 0; + + public void m1() { } + static public void m2() { } + public void m3() { } + public void m4() { } + public void m5() { } + public void m6() { } + public void m7() { } + public void m8() { } + public void m9() { } + public void m10() { } + public void m11() { } + public void m12() { } + public void m13() { } + public void m14() { } + public void m15() { } + public void m16() { } + public void m17() { } + public void m18() { } + public void m19() { } + public void m20() { } + public void m21() { } + public void m22() { } + public void m23() { } + public void m24() { } + + public int p0 { get { return 1; } set { } } + static public int p1 { get { return 1; } set { } } + public int p2 { get { return 1; } set { } } + public int p3 { get { return 1; } set { } } + public int p4 { get { return 1; } set { } } + public int p5 { get { return 1; } set { } } + public int p6 { get { return 1; } set { } } + public int p7 { get { return 1; } set { } } + public int p8 { get { return 1; } set { } } + public int p9 { get { return 1; } set { } } + public int p10 { get { return 1; } set { } } + public int p11 { get { return 1; } set { } } + public int p12 { get { return 1; } set { } } + public int p13 { get { return 1; } set { } } + public int p14 { get { return 1; } set { } } + public int p15 { get { return 1; } set { } } + public int p16 { get { return 1; } set { } } + public int p17 { get { return 1; } set { } } + public int p18 { get { return 1; } set { } } + public int p19 { get { return 1; } set { } } + public int p20 { get { return 1; } set { } } + public int p21 { get { return 1; } set { } } + public int p22 { get { return 1; } set { } } + public int p23 { get { return 1; } set { } } + public int p24 { get { return 1; } set { } } + + public event d e0; + static public event d e1; + public event d e2; + public event d e3; + public event d e4; + public event d e5; + public event d e6; + public event d e7; + public event d e8; + public event d e9; + public event d e10; + public event d e11; + public event d e12; + public event d e13; + public event d e14; + public event d e15; + public event d e16; + public event d e17; + public event d e18; + public event d e19; + public event d e20; + public event d e21; + public event d e22; + public event d e23; + public event d e24; + + public void NoWarning() + { + e0 += new d(m1); + e1 += new d(m1); + e2 += new d(m1); + e3 += new d(m1); + e4 += new d(m1); + e5 += new d(m1); + e6 += new d(m1); + e7 += new d(m1); + e8 += new d(m1); + e9 += new d(m1); + e10 += new d(m1); + e11 += new d(m1); + e12 += new d(m1); + e13 += new d(m1); + e14 += new d(m1); + e15 += new d(m1); + e16 += new d(m1); + e17 += new d(m1); + e18 += new d(m1); + e19 += new d(m1); + e20 += new d(m1); + e21 += new d(m1); + e22 += new d(m1); + e23 += new d(m1); + e24 += new d(m1); + } } -} -public class Class7 -{ - public Class7() { } - public Class7(int i) { } - public Class7(int i, int ii) { } - - public int f0 = 0; - static public int f1 = 0; - public int f2 = 0; - public int f3 = 0; - public int f4 = 0; - public int f5 = 0; - public int f6 = 0; - public int f7 = 0; - public int f8 = 0; - public int f9 = 0; - public int f10 = 0; - public int f11 = 0; - public int f12 = 0; - public int f13 = 0; - public int f14 = 0; - public int f15 = 0; - public int f16 = 0; - public int f17 = 0; - public int f18 = 0; - public int f19 = 0; - public int f20 = 0; - public int f21 = 0; - public int f22 = 0; - public int f23 = 0; - public int f24 = 0; - - public void m1() { } - static public void m2() { } - public void m3() { } - public void m4() { } - public void m5() { } - public void m6() { } - public void m7() { } - public void m8() { } - public void m9() { } - public void m10() { } - public void m11() { } - public void m12() { } - public void m13() { } - public void m14() { } - public void m15() { } - public void m16() { } - public void m17() { } - public void m18() { } - public void m19() { } - public void m20() { } - public void m21() { } - public void m22() { } - public void m23() { } - public void m24() { } - - public int p0 { get { return 1; } set { } } - static public int p1 { get { return 1; } set { } } - public int p2 { get { return 1; } set { } } - public int p3 { get { return 1; } set { } } - public int p4 { get { return 1; } set { } } - public int p5 { get { return 1; } set { } } - public int p6 { get { return 1; } set { } } - public int p7 { get { return 1; } set { } } - public int p8 { get { return 1; } set { } } - public int p9 { get { return 1; } set { } } - public int p10 { get { return 1; } set { } } - public int p11 { get { return 1; } set { } } - public int p12 { get { return 1; } set { } } - public int p13 { get { return 1; } set { } } - public int p14 { get { return 1; } set { } } - public int p15 { get { return 1; } set { } } - public int p16 { get { return 1; } set { } } - public int p17 { get { return 1; } set { } } - public int p18 { get { return 1; } set { } } - public int p19 { get { return 1; } set { } } - public int p20 { get { return 1; } set { } } - public int p21 { get { return 1; } set { } } - public int p22 { get { return 1; } set { } } - public int p23 { get { return 1; } set { } } - public int p24 { get { return 1; } set { } } - - public event d e0; - static public event d e1; - public event d e2; - public event d e3; - public event d e4; - public event d e5; - public event d e6; - public event d e7; - public event d e8; - public event d e9; - public event d e10; - public event d e11; - public event d e12; - public event d e13; - public event d e14; - public event d e15; - public event d e16; - public event d e17; - public event d e18; - public event d e19; - public event d e20; - public event d e21; - public event d e22; - public event d e23; - public event d e24; - - public void NoWarning() + public class Class7 { - e0 += new d(m1); - e1 += new d(m1); - e2 += new d(m1); - e3 += new d(m1); - e4 += new d(m1); - e5 += new d(m1); - e6 += new d(m1); - e7 += new d(m1); - e8 += new d(m1); - e9 += new d(m1); - e10 += new d(m1); - e11 += new d(m1); - e12 += new d(m1); - e13 += new d(m1); - e14 += new d(m1); - e15 += new d(m1); - e16 += new d(m1); - e17 += new d(m1); - e18 += new d(m1); - e19 += new d(m1); - e20 += new d(m1); - e21 += new d(m1); - e22 += new d(m1); - e23 += new d(m1); - e24 += new d(m1); + public Class7() { } + public Class7(int i) { } + public Class7(int i, int ii) { } + + public int f0 = 0; + static public int f1 = 0; + public int f2 = 0; + public int f3 = 0; + public int f4 = 0; + public int f5 = 0; + public int f6 = 0; + public int f7 = 0; + public int f8 = 0; + public int f9 = 0; + public int f10 = 0; + public int f11 = 0; + public int f12 = 0; + public int f13 = 0; + public int f14 = 0; + public int f15 = 0; + public int f16 = 0; + public int f17 = 0; + public int f18 = 0; + public int f19 = 0; + public int f20 = 0; + public int f21 = 0; + public int f22 = 0; + public int f23 = 0; + public int f24 = 0; + + public void m1() { } + static public void m2() { } + public void m3() { } + public void m4() { } + public void m5() { } + public void m6() { } + public void m7() { } + public void m8() { } + public void m9() { } + public void m10() { } + public void m11() { } + public void m12() { } + public void m13() { } + public void m14() { } + public void m15() { } + public void m16() { } + public void m17() { } + public void m18() { } + public void m19() { } + public void m20() { } + public void m21() { } + public void m22() { } + public void m23() { } + public void m24() { } + + public int p0 { get { return 1; } set { } } + static public int p1 { get { return 1; } set { } } + public int p2 { get { return 1; } set { } } + public int p3 { get { return 1; } set { } } + public int p4 { get { return 1; } set { } } + public int p5 { get { return 1; } set { } } + public int p6 { get { return 1; } set { } } + public int p7 { get { return 1; } set { } } + public int p8 { get { return 1; } set { } } + public int p9 { get { return 1; } set { } } + public int p10 { get { return 1; } set { } } + public int p11 { get { return 1; } set { } } + public int p12 { get { return 1; } set { } } + public int p13 { get { return 1; } set { } } + public int p14 { get { return 1; } set { } } + public int p15 { get { return 1; } set { } } + public int p16 { get { return 1; } set { } } + public int p17 { get { return 1; } set { } } + public int p18 { get { return 1; } set { } } + public int p19 { get { return 1; } set { } } + public int p20 { get { return 1; } set { } } + public int p21 { get { return 1; } set { } } + public int p22 { get { return 1; } set { } } + public int p23 { get { return 1; } set { } } + public int p24 { get { return 1; } set { } } + + public event d e0; + static public event d e1; + public event d e2; + public event d e3; + public event d e4; + public event d e5; + public event d e6; + public event d e7; + public event d e8; + public event d e9; + public event d e10; + public event d e11; + public event d e12; + public event d e13; + public event d e14; + public event d e15; + public event d e16; + public event d e17; + public event d e18; + public event d e19; + public event d e20; + public event d e21; + public event d e22; + public event d e23; + public event d e24; + + public void NoWarning() + { + e0 += new d(m1); + e1 += new d(m1); + e2 += new d(m1); + e3 += new d(m1); + e4 += new d(m1); + e5 += new d(m1); + e6 += new d(m1); + e7 += new d(m1); + e8 += new d(m1); + e9 += new d(m1); + e10 += new d(m1); + e11 += new d(m1); + e12 += new d(m1); + e13 += new d(m1); + e14 += new d(m1); + e15 += new d(m1); + e16 += new d(m1); + e17 += new d(m1); + e18 += new d(m1); + e19 += new d(m1); + e20 += new d(m1); + e21 += new d(m1); + e22 += new d(m1); + e23 += new d(m1); + e24 += new d(m1); + } } -} -public class Class8 -{ - public Class8() { } - public Class8(int i) { } - public Class8(int i, int ii) { } - - public int f0 = 0; - static public int f1 = 0; - public int f2 = 0; - public int f3 = 0; - public int f4 = 0; - public int f5 = 0; - public int f6 = 0; - public int f7 = 0; - public int f8 = 0; - public int f9 = 0; - public int f10 = 0; - public int f11 = 0; - public int f12 = 0; - public int f13 = 0; - public int f14 = 0; - public int f15 = 0; - public int f16 = 0; - public int f17 = 0; - public int f18 = 0; - public int f19 = 0; - public int f20 = 0; - public int f21 = 0; - public int f22 = 0; - public int f23 = 0; - public int f24 = 0; - - public void m1() { } - static public void m2() { } - public void m3() { } - public void m4() { } - public void m5() { } - public void m6() { } - public void m7() { } - public void m8() { } - public void m9() { } - public void m10() { } - public void m11() { } - public void m12() { } - public void m13() { } - public void m14() { } - public void m15() { } - public void m16() { } - public void m17() { } - public void m18() { } - public void m19() { } - public void m20() { } - public void m21() { } - public void m22() { } - public void m23() { } - public void m24() { } - - public int p0 { get { return 1; } set { } } - static public int p1 { get { return 1; } set { } } - public int p2 { get { return 1; } set { } } - public int p3 { get { return 1; } set { } } - public int p4 { get { return 1; } set { } } - public int p5 { get { return 1; } set { } } - public int p6 { get { return 1; } set { } } - public int p7 { get { return 1; } set { } } - public int p8 { get { return 1; } set { } } - public int p9 { get { return 1; } set { } } - public int p10 { get { return 1; } set { } } - public int p11 { get { return 1; } set { } } - public int p12 { get { return 1; } set { } } - public int p13 { get { return 1; } set { } } - public int p14 { get { return 1; } set { } } - public int p15 { get { return 1; } set { } } - public int p16 { get { return 1; } set { } } - public int p17 { get { return 1; } set { } } - public int p18 { get { return 1; } set { } } - public int p19 { get { return 1; } set { } } - public int p20 { get { return 1; } set { } } - public int p21 { get { return 1; } set { } } - public int p22 { get { return 1; } set { } } - public int p23 { get { return 1; } set { } } - public int p24 { get { return 1; } set { } } - - public event d e0; - static public event d e1; - public event d e2; - public event d e3; - public event d e4; - public event d e5; - public event d e6; - public event d e7; - public event d e8; - public event d e9; - public event d e10; - public event d e11; - public event d e12; - public event d e13; - public event d e14; - public event d e15; - public event d e16; - public event d e17; - public event d e18; - public event d e19; - public event d e20; - public event d e21; - public event d e22; - public event d e23; - public event d e24; - - public void NoWarning() + public class Class8 { - e0 += new d(m1); - e1 += new d(m1); - e2 += new d(m1); - e3 += new d(m1); - e4 += new d(m1); - e5 += new d(m1); - e6 += new d(m1); - e7 += new d(m1); - e8 += new d(m1); - e9 += new d(m1); - e10 += new d(m1); - e11 += new d(m1); - e12 += new d(m1); - e13 += new d(m1); - e14 += new d(m1); - e15 += new d(m1); - e16 += new d(m1); - e17 += new d(m1); - e18 += new d(m1); - e19 += new d(m1); - e20 += new d(m1); - e21 += new d(m1); - e22 += new d(m1); - e23 += new d(m1); - e24 += new d(m1); + public Class8() { } + public Class8(int i) { } + public Class8(int i, int ii) { } + + public int f0 = 0; + static public int f1 = 0; + public int f2 = 0; + public int f3 = 0; + public int f4 = 0; + public int f5 = 0; + public int f6 = 0; + public int f7 = 0; + public int f8 = 0; + public int f9 = 0; + public int f10 = 0; + public int f11 = 0; + public int f12 = 0; + public int f13 = 0; + public int f14 = 0; + public int f15 = 0; + public int f16 = 0; + public int f17 = 0; + public int f18 = 0; + public int f19 = 0; + public int f20 = 0; + public int f21 = 0; + public int f22 = 0; + public int f23 = 0; + public int f24 = 0; + + public void m1() { } + static public void m2() { } + public void m3() { } + public void m4() { } + public void m5() { } + public void m6() { } + public void m7() { } + public void m8() { } + public void m9() { } + public void m10() { } + public void m11() { } + public void m12() { } + public void m13() { } + public void m14() { } + public void m15() { } + public void m16() { } + public void m17() { } + public void m18() { } + public void m19() { } + public void m20() { } + public void m21() { } + public void m22() { } + public void m23() { } + public void m24() { } + + public int p0 { get { return 1; } set { } } + static public int p1 { get { return 1; } set { } } + public int p2 { get { return 1; } set { } } + public int p3 { get { return 1; } set { } } + public int p4 { get { return 1; } set { } } + public int p5 { get { return 1; } set { } } + public int p6 { get { return 1; } set { } } + public int p7 { get { return 1; } set { } } + public int p8 { get { return 1; } set { } } + public int p9 { get { return 1; } set { } } + public int p10 { get { return 1; } set { } } + public int p11 { get { return 1; } set { } } + public int p12 { get { return 1; } set { } } + public int p13 { get { return 1; } set { } } + public int p14 { get { return 1; } set { } } + public int p15 { get { return 1; } set { } } + public int p16 { get { return 1; } set { } } + public int p17 { get { return 1; } set { } } + public int p18 { get { return 1; } set { } } + public int p19 { get { return 1; } set { } } + public int p20 { get { return 1; } set { } } + public int p21 { get { return 1; } set { } } + public int p22 { get { return 1; } set { } } + public int p23 { get { return 1; } set { } } + public int p24 { get { return 1; } set { } } + + public event d e0; + static public event d e1; + public event d e2; + public event d e3; + public event d e4; + public event d e5; + public event d e6; + public event d e7; + public event d e8; + public event d e9; + public event d e10; + public event d e11; + public event d e12; + public event d e13; + public event d e14; + public event d e15; + public event d e16; + public event d e17; + public event d e18; + public event d e19; + public event d e20; + public event d e21; + public event d e22; + public event d e23; + public event d e24; + + public void NoWarning() + { + e0 += new d(m1); + e1 += new d(m1); + e2 += new d(m1); + e3 += new d(m1); + e4 += new d(m1); + e5 += new d(m1); + e6 += new d(m1); + e7 += new d(m1); + e8 += new d(m1); + e9 += new d(m1); + e10 += new d(m1); + e11 += new d(m1); + e12 += new d(m1); + e13 += new d(m1); + e14 += new d(m1); + e15 += new d(m1); + e16 += new d(m1); + e17 += new d(m1); + e18 += new d(m1); + e19 += new d(m1); + e20 += new d(m1); + e21 += new d(m1); + e22 += new d(m1); + e23 += new d(m1); + e24 += new d(m1); + } } -} -public class Class9 -{ - public Class9() { } - public Class9(int i) { } - public Class9(int i, int ii) { } - - public int f0 = 0; - static public int f1 = 0; - public int f2 = 0; - public int f3 = 0; - public int f4 = 0; - public int f5 = 0; - public int f6 = 0; - public int f7 = 0; - public int f8 = 0; - public int f9 = 0; - public int f10 = 0; - public int f11 = 0; - public int f12 = 0; - public int f13 = 0; - public int f14 = 0; - public int f15 = 0; - public int f16 = 0; - public int f17 = 0; - public int f18 = 0; - public int f19 = 0; - public int f20 = 0; - public int f21 = 0; - public int f22 = 0; - public int f23 = 0; - public int f24 = 0; - - public void m1() { } - static public void m2() { } - public void m3() { } - public void m4() { } - public void m5() { } - public void m6() { } - public void m7() { } - public void m8() { } - public void m9() { } - public void m10() { } - public void m11() { } - public void m12() { } - public void m13() { } - public void m14() { } - public void m15() { } - public void m16() { } - public void m17() { } - public void m18() { } - public void m19() { } - public void m20() { } - public void m21() { } - public void m22() { } - public void m23() { } - public void m24() { } - - public int p0 { get { return 1; } set { } } - static public int p1 { get { return 1; } set { } } - public int p2 { get { return 1; } set { } } - public int p3 { get { return 1; } set { } } - public int p4 { get { return 1; } set { } } - public int p5 { get { return 1; } set { } } - public int p6 { get { return 1; } set { } } - public int p7 { get { return 1; } set { } } - public int p8 { get { return 1; } set { } } - public int p9 { get { return 1; } set { } } - public int p10 { get { return 1; } set { } } - public int p11 { get { return 1; } set { } } - public int p12 { get { return 1; } set { } } - public int p13 { get { return 1; } set { } } - public int p14 { get { return 1; } set { } } - public int p15 { get { return 1; } set { } } - public int p16 { get { return 1; } set { } } - public int p17 { get { return 1; } set { } } - public int p18 { get { return 1; } set { } } - public int p19 { get { return 1; } set { } } - public int p20 { get { return 1; } set { } } - public int p21 { get { return 1; } set { } } - public int p22 { get { return 1; } set { } } - public int p23 { get { return 1; } set { } } - public int p24 { get { return 1; } set { } } - - public event d e0; - static public event d e1; - public event d e2; - public event d e3; - public event d e4; - public event d e5; - public event d e6; - public event d e7; - public event d e8; - public event d e9; - public event d e10; - public event d e11; - public event d e12; - public event d e13; - public event d e14; - public event d e15; - public event d e16; - public event d e17; - public event d e18; - public event d e19; - public event d e20; - public event d e21; - public event d e22; - public event d e23; - public event d e24; - - public void NoWarning() + public class Class9 { - e0 += new d(m1); - e1 += new d(m1); - e2 += new d(m1); - e3 += new d(m1); - e4 += new d(m1); - e5 += new d(m1); - e6 += new d(m1); - e7 += new d(m1); - e8 += new d(m1); - e9 += new d(m1); - e10 += new d(m1); - e11 += new d(m1); - e12 += new d(m1); - e13 += new d(m1); - e14 += new d(m1); - e15 += new d(m1); - e16 += new d(m1); - e17 += new d(m1); - e18 += new d(m1); - e19 += new d(m1); - e20 += new d(m1); - e21 += new d(m1); - e22 += new d(m1); - e23 += new d(m1); - e24 += new d(m1); + public Class9() { } + public Class9(int i) { } + public Class9(int i, int ii) { } + + public int f0 = 0; + static public int f1 = 0; + public int f2 = 0; + public int f3 = 0; + public int f4 = 0; + public int f5 = 0; + public int f6 = 0; + public int f7 = 0; + public int f8 = 0; + public int f9 = 0; + public int f10 = 0; + public int f11 = 0; + public int f12 = 0; + public int f13 = 0; + public int f14 = 0; + public int f15 = 0; + public int f16 = 0; + public int f17 = 0; + public int f18 = 0; + public int f19 = 0; + public int f20 = 0; + public int f21 = 0; + public int f22 = 0; + public int f23 = 0; + public int f24 = 0; + + public void m1() { } + static public void m2() { } + public void m3() { } + public void m4() { } + public void m5() { } + public void m6() { } + public void m7() { } + public void m8() { } + public void m9() { } + public void m10() { } + public void m11() { } + public void m12() { } + public void m13() { } + public void m14() { } + public void m15() { } + public void m16() { } + public void m17() { } + public void m18() { } + public void m19() { } + public void m20() { } + public void m21() { } + public void m22() { } + public void m23() { } + public void m24() { } + + public int p0 { get { return 1; } set { } } + static public int p1 { get { return 1; } set { } } + public int p2 { get { return 1; } set { } } + public int p3 { get { return 1; } set { } } + public int p4 { get { return 1; } set { } } + public int p5 { get { return 1; } set { } } + public int p6 { get { return 1; } set { } } + public int p7 { get { return 1; } set { } } + public int p8 { get { return 1; } set { } } + public int p9 { get { return 1; } set { } } + public int p10 { get { return 1; } set { } } + public int p11 { get { return 1; } set { } } + public int p12 { get { return 1; } set { } } + public int p13 { get { return 1; } set { } } + public int p14 { get { return 1; } set { } } + public int p15 { get { return 1; } set { } } + public int p16 { get { return 1; } set { } } + public int p17 { get { return 1; } set { } } + public int p18 { get { return 1; } set { } } + public int p19 { get { return 1; } set { } } + public int p20 { get { return 1; } set { } } + public int p21 { get { return 1; } set { } } + public int p22 { get { return 1; } set { } } + public int p23 { get { return 1; } set { } } + public int p24 { get { return 1; } set { } } + + public event d e0; + static public event d e1; + public event d e2; + public event d e3; + public event d e4; + public event d e5; + public event d e6; + public event d e7; + public event d e8; + public event d e9; + public event d e10; + public event d e11; + public event d e12; + public event d e13; + public event d e14; + public event d e15; + public event d e16; + public event d e17; + public event d e18; + public event d e19; + public event d e20; + public event d e21; + public event d e22; + public event d e23; + public event d e24; + + public void NoWarning() + { + e0 += new d(m1); + e1 += new d(m1); + e2 += new d(m1); + e3 += new d(m1); + e4 += new d(m1); + e5 += new d(m1); + e6 += new d(m1); + e7 += new d(m1); + e8 += new d(m1); + e9 += new d(m1); + e10 += new d(m1); + e11 += new d(m1); + e12 += new d(m1); + e13 += new d(m1); + e14 += new d(m1); + e15 += new d(m1); + e16 += new d(m1); + e17 += new d(m1); + e18 += new d(m1); + e19 += new d(m1); + e20 += new d(m1); + e21 += new d(m1); + e22 += new d(m1); + e23 += new d(m1); + e24 += new d(m1); + } } -} -public class Class10 -{ - public Class10() { } - public Class10(int i) { } - public Class10(int i, int ii) { } - - public int f0 = 0; - static public int f1 = 0; - public int f2 = 0; - public int f3 = 0; - public int f4 = 0; - public int f5 = 0; - public int f6 = 0; - public int f7 = 0; - public int f8 = 0; - public int f9 = 0; - public int f10 = 0; - public int f11 = 0; - public int f12 = 0; - public int f13 = 0; - public int f14 = 0; - public int f15 = 0; - public int f16 = 0; - public int f17 = 0; - public int f18 = 0; - public int f19 = 0; - public int f20 = 0; - public int f21 = 0; - public int f22 = 0; - public int f23 = 0; - public int f24 = 0; - - public void m1() { } - static public void m2() { } - public void m3() { } - public void m4() { } - public void m5() { } - public void m6() { } - public void m7() { } - public void m8() { } - public void m9() { } - public void m10() { } - public void m11() { } - public void m12() { } - public void m13() { } - public void m14() { } - public void m15() { } - public void m16() { } - public void m17() { } - public void m18() { } - public void m19() { } - public void m20() { } - public void m21() { } - public void m22() { } - public void m23() { } - public void m24() { } - - public int p0 { get { return 1; } set { } } - static public int p1 { get { return 1; } set { } } - public int p2 { get { return 1; } set { } } - public int p3 { get { return 1; } set { } } - public int p4 { get { return 1; } set { } } - public int p5 { get { return 1; } set { } } - public int p6 { get { return 1; } set { } } - public int p7 { get { return 1; } set { } } - public int p8 { get { return 1; } set { } } - public int p9 { get { return 1; } set { } } - public int p10 { get { return 1; } set { } } - public int p11 { get { return 1; } set { } } - public int p12 { get { return 1; } set { } } - public int p13 { get { return 1; } set { } } - public int p14 { get { return 1; } set { } } - public int p15 { get { return 1; } set { } } - public int p16 { get { return 1; } set { } } - public int p17 { get { return 1; } set { } } - public int p18 { get { return 1; } set { } } - public int p19 { get { return 1; } set { } } - public int p20 { get { return 1; } set { } } - public int p21 { get { return 1; } set { } } - public int p22 { get { return 1; } set { } } - public int p23 { get { return 1; } set { } } - public int p24 { get { return 1; } set { } } - - public event d e0; - static public event d e1; - public event d e2; - public event d e3; - public event d e4; - public event d e5; - public event d e6; - public event d e7; - public event d e8; - public event d e9; - public event d e10; - public event d e11; - public event d e12; - public event d e13; - public event d e14; - public event d e15; - public event d e16; - public event d e17; - public event d e18; - public event d e19; - public event d e20; - public event d e21; - public event d e22; - public event d e23; - public event d e24; - - public void NoWarning() + public class Class10 { - e0 += new d(m1); - e1 += new d(m1); - e2 += new d(m1); - e3 += new d(m1); - e4 += new d(m1); - e5 += new d(m1); - e6 += new d(m1); - e7 += new d(m1); - e8 += new d(m1); - e9 += new d(m1); - e10 += new d(m1); - e11 += new d(m1); - e12 += new d(m1); - e13 += new d(m1); - e14 += new d(m1); - e15 += new d(m1); - e16 += new d(m1); - e17 += new d(m1); - e18 += new d(m1); - e19 += new d(m1); - e20 += new d(m1); - e21 += new d(m1); - e22 += new d(m1); - e23 += new d(m1); - e24 += new d(m1); + public Class10() { } + public Class10(int i) { } + public Class10(int i, int ii) { } + + public int f0 = 0; + static public int f1 = 0; + public int f2 = 0; + public int f3 = 0; + public int f4 = 0; + public int f5 = 0; + public int f6 = 0; + public int f7 = 0; + public int f8 = 0; + public int f9 = 0; + public int f10 = 0; + public int f11 = 0; + public int f12 = 0; + public int f13 = 0; + public int f14 = 0; + public int f15 = 0; + public int f16 = 0; + public int f17 = 0; + public int f18 = 0; + public int f19 = 0; + public int f20 = 0; + public int f21 = 0; + public int f22 = 0; + public int f23 = 0; + public int f24 = 0; + + public void m1() { } + static public void m2() { } + public void m3() { } + public void m4() { } + public void m5() { } + public void m6() { } + public void m7() { } + public void m8() { } + public void m9() { } + public void m10() { } + public void m11() { } + public void m12() { } + public void m13() { } + public void m14() { } + public void m15() { } + public void m16() { } + public void m17() { } + public void m18() { } + public void m19() { } + public void m20() { } + public void m21() { } + public void m22() { } + public void m23() { } + public void m24() { } + + public int p0 { get { return 1; } set { } } + static public int p1 { get { return 1; } set { } } + public int p2 { get { return 1; } set { } } + public int p3 { get { return 1; } set { } } + public int p4 { get { return 1; } set { } } + public int p5 { get { return 1; } set { } } + public int p6 { get { return 1; } set { } } + public int p7 { get { return 1; } set { } } + public int p8 { get { return 1; } set { } } + public int p9 { get { return 1; } set { } } + public int p10 { get { return 1; } set { } } + public int p11 { get { return 1; } set { } } + public int p12 { get { return 1; } set { } } + public int p13 { get { return 1; } set { } } + public int p14 { get { return 1; } set { } } + public int p15 { get { return 1; } set { } } + public int p16 { get { return 1; } set { } } + public int p17 { get { return 1; } set { } } + public int p18 { get { return 1; } set { } } + public int p19 { get { return 1; } set { } } + public int p20 { get { return 1; } set { } } + public int p21 { get { return 1; } set { } } + public int p22 { get { return 1; } set { } } + public int p23 { get { return 1; } set { } } + public int p24 { get { return 1; } set { } } + + public event d e0; + static public event d e1; + public event d e2; + public event d e3; + public event d e4; + public event d e5; + public event d e6; + public event d e7; + public event d e8; + public event d e9; + public event d e10; + public event d e11; + public event d e12; + public event d e13; + public event d e14; + public event d e15; + public event d e16; + public event d e17; + public event d e18; + public event d e19; + public event d e20; + public event d e21; + public event d e22; + public event d e23; + public event d e24; + + public void NoWarning() + { + e0 += new d(m1); + e1 += new d(m1); + e2 += new d(m1); + e3 += new d(m1); + e4 += new d(m1); + e5 += new d(m1); + e6 += new d(m1); + e7 += new d(m1); + e8 += new d(m1); + e9 += new d(m1); + e10 += new d(m1); + e11 += new d(m1); + e12 += new d(m1); + e13 += new d(m1); + e14 += new d(m1); + e15 += new d(m1); + e16 += new d(m1); + e17 += new d(m1); + e18 += new d(m1); + e19 += new d(m1); + e20 += new d(m1); + e21 += new d(m1); + e22 += new d(m1); + e23 += new d(m1); + e24 += new d(m1); + } } -} -public class Class11 -{ - public Class11() { } - public Class11(int i) { } - public Class11(int i, int ii) { } - - public int f0 = 0; - static public int f1 = 0; - public int f2 = 0; - public int f3 = 0; - public int f4 = 0; - public int f5 = 0; - public int f6 = 0; - public int f7 = 0; - public int f8 = 0; - public int f9 = 0; - public int f10 = 0; - public int f11 = 0; - public int f12 = 0; - public int f13 = 0; - public int f14 = 0; - public int f15 = 0; - public int f16 = 0; - public int f17 = 0; - public int f18 = 0; - public int f19 = 0; - public int f20 = 0; - public int f21 = 0; - public int f22 = 0; - public int f23 = 0; - public int f24 = 0; - - public void m1() { } - static public void m2() { } - public void m3() { } - public void m4() { } - public void m5() { } - public void m6() { } - public void m7() { } - public void m8() { } - public void m9() { } - public void m10() { } - public void m11() { } - public void m12() { } - public void m13() { } - public void m14() { } - public void m15() { } - public void m16() { } - public void m17() { } - public void m18() { } - public void m19() { } - public void m20() { } - public void m21() { } - public void m22() { } - public void m23() { } - public void m24() { } - - public int p0 { get { return 1; } set { } } - static public int p1 { get { return 1; } set { } } - public int p2 { get { return 1; } set { } } - public int p3 { get { return 1; } set { } } - public int p4 { get { return 1; } set { } } - public int p5 { get { return 1; } set { } } - public int p6 { get { return 1; } set { } } - public int p7 { get { return 1; } set { } } - public int p8 { get { return 1; } set { } } - public int p9 { get { return 1; } set { } } - public int p10 { get { return 1; } set { } } - public int p11 { get { return 1; } set { } } - public int p12 { get { return 1; } set { } } - public int p13 { get { return 1; } set { } } - public int p14 { get { return 1; } set { } } - public int p15 { get { return 1; } set { } } - public int p16 { get { return 1; } set { } } - public int p17 { get { return 1; } set { } } - public int p18 { get { return 1; } set { } } - public int p19 { get { return 1; } set { } } - public int p20 { get { return 1; } set { } } - public int p21 { get { return 1; } set { } } - public int p22 { get { return 1; } set { } } - public int p23 { get { return 1; } set { } } - public int p24 { get { return 1; } set { } } - - public event d e0; - static public event d e1; - public event d e2; - public event d e3; - public event d e4; - public event d e5; - public event d e6; - public event d e7; - public event d e8; - public event d e9; - public event d e10; - public event d e11; - public event d e12; - public event d e13; - public event d e14; - public event d e15; - public event d e16; - public event d e17; - public event d e18; - public event d e19; - public event d e20; - public event d e21; - public event d e22; - public event d e23; - public event d e24; - - public void NoWarning() + public class Class11 { - e0 += new d(m1); - e1 += new d(m1); - e2 += new d(m1); - e3 += new d(m1); - e4 += new d(m1); - e5 += new d(m1); - e6 += new d(m1); - e7 += new d(m1); - e8 += new d(m1); - e9 += new d(m1); - e10 += new d(m1); - e11 += new d(m1); - e12 += new d(m1); - e13 += new d(m1); - e14 += new d(m1); - e15 += new d(m1); - e16 += new d(m1); - e17 += new d(m1); - e18 += new d(m1); - e19 += new d(m1); - e20 += new d(m1); - e21 += new d(m1); - e22 += new d(m1); - e23 += new d(m1); - e24 += new d(m1); + public Class11() { } + public Class11(int i) { } + public Class11(int i, int ii) { } + + public int f0 = 0; + static public int f1 = 0; + public int f2 = 0; + public int f3 = 0; + public int f4 = 0; + public int f5 = 0; + public int f6 = 0; + public int f7 = 0; + public int f8 = 0; + public int f9 = 0; + public int f10 = 0; + public int f11 = 0; + public int f12 = 0; + public int f13 = 0; + public int f14 = 0; + public int f15 = 0; + public int f16 = 0; + public int f17 = 0; + public int f18 = 0; + public int f19 = 0; + public int f20 = 0; + public int f21 = 0; + public int f22 = 0; + public int f23 = 0; + public int f24 = 0; + + public void m1() { } + static public void m2() { } + public void m3() { } + public void m4() { } + public void m5() { } + public void m6() { } + public void m7() { } + public void m8() { } + public void m9() { } + public void m10() { } + public void m11() { } + public void m12() { } + public void m13() { } + public void m14() { } + public void m15() { } + public void m16() { } + public void m17() { } + public void m18() { } + public void m19() { } + public void m20() { } + public void m21() { } + public void m22() { } + public void m23() { } + public void m24() { } + + public int p0 { get { return 1; } set { } } + static public int p1 { get { return 1; } set { } } + public int p2 { get { return 1; } set { } } + public int p3 { get { return 1; } set { } } + public int p4 { get { return 1; } set { } } + public int p5 { get { return 1; } set { } } + public int p6 { get { return 1; } set { } } + public int p7 { get { return 1; } set { } } + public int p8 { get { return 1; } set { } } + public int p9 { get { return 1; } set { } } + public int p10 { get { return 1; } set { } } + public int p11 { get { return 1; } set { } } + public int p12 { get { return 1; } set { } } + public int p13 { get { return 1; } set { } } + public int p14 { get { return 1; } set { } } + public int p15 { get { return 1; } set { } } + public int p16 { get { return 1; } set { } } + public int p17 { get { return 1; } set { } } + public int p18 { get { return 1; } set { } } + public int p19 { get { return 1; } set { } } + public int p20 { get { return 1; } set { } } + public int p21 { get { return 1; } set { } } + public int p22 { get { return 1; } set { } } + public int p23 { get { return 1; } set { } } + public int p24 { get { return 1; } set { } } + + public event d e0; + static public event d e1; + public event d e2; + public event d e3; + public event d e4; + public event d e5; + public event d e6; + public event d e7; + public event d e8; + public event d e9; + public event d e10; + public event d e11; + public event d e12; + public event d e13; + public event d e14; + public event d e15; + public event d e16; + public event d e17; + public event d e18; + public event d e19; + public event d e20; + public event d e21; + public event d e22; + public event d e23; + public event d e24; + + public void NoWarning() + { + e0 += new d(m1); + e1 += new d(m1); + e2 += new d(m1); + e3 += new d(m1); + e4 += new d(m1); + e5 += new d(m1); + e6 += new d(m1); + e7 += new d(m1); + e8 += new d(m1); + e9 += new d(m1); + e10 += new d(m1); + e11 += new d(m1); + e12 += new d(m1); + e13 += new d(m1); + e14 += new d(m1); + e15 += new d(m1); + e16 += new d(m1); + e17 += new d(m1); + e18 += new d(m1); + e19 += new d(m1); + e20 += new d(m1); + e21 += new d(m1); + e22 += new d(m1); + e23 += new d(m1); + e24 += new d(m1); + } } -} -public class Class12 -{ - public Class12() { } - public Class12(int i) { } - public Class12(int i, int ii) { } - - public int f0 = 0; - static public int f1 = 0; - public int f2 = 0; - public int f3 = 0; - public int f4 = 0; - public int f5 = 0; - public int f6 = 0; - public int f7 = 0; - public int f8 = 0; - public int f9 = 0; - public int f10 = 0; - public int f11 = 0; - public int f12 = 0; - public int f13 = 0; - public int f14 = 0; - public int f15 = 0; - public int f16 = 0; - public int f17 = 0; - public int f18 = 0; - public int f19 = 0; - public int f20 = 0; - public int f21 = 0; - public int f22 = 0; - public int f23 = 0; - public int f24 = 0; - - public void m1() { } - static public void m2() { } - public void m3() { } - public void m4() { } - public void m5() { } - public void m6() { } - public void m7() { } - public void m8() { } - public void m9() { } - public void m10() { } - public void m11() { } - public void m12() { } - public void m13() { } - public void m14() { } - public void m15() { } - public void m16() { } - public void m17() { } - public void m18() { } - public void m19() { } - public void m20() { } - public void m21() { } - public void m22() { } - public void m23() { } - public void m24() { } - - public int p0 { get { return 1; } set { } } - static public int p1 { get { return 1; } set { } } - public int p2 { get { return 1; } set { } } - public int p3 { get { return 1; } set { } } - public int p4 { get { return 1; } set { } } - public int p5 { get { return 1; } set { } } - public int p6 { get { return 1; } set { } } - public int p7 { get { return 1; } set { } } - public int p8 { get { return 1; } set { } } - public int p9 { get { return 1; } set { } } - public int p10 { get { return 1; } set { } } - public int p11 { get { return 1; } set { } } - public int p12 { get { return 1; } set { } } - public int p13 { get { return 1; } set { } } - public int p14 { get { return 1; } set { } } - public int p15 { get { return 1; } set { } } - public int p16 { get { return 1; } set { } } - public int p17 { get { return 1; } set { } } - public int p18 { get { return 1; } set { } } - public int p19 { get { return 1; } set { } } - public int p20 { get { return 1; } set { } } - public int p21 { get { return 1; } set { } } - public int p22 { get { return 1; } set { } } - public int p23 { get { return 1; } set { } } - public int p24 { get { return 1; } set { } } - - public event d e0; - static public event d e1; - public event d e2; - public event d e3; - public event d e4; - public event d e5; - public event d e6; - public event d e7; - public event d e8; - public event d e9; - public event d e10; - public event d e11; - public event d e12; - public event d e13; - public event d e14; - public event d e15; - public event d e16; - public event d e17; - public event d e18; - public event d e19; - public event d e20; - public event d e21; - public event d e22; - public event d e23; - public event d e24; - - public void NoWarning() + public class Class12 { - e0 += new d(m1); - e1 += new d(m1); - e2 += new d(m1); - e3 += new d(m1); - e4 += new d(m1); - e5 += new d(m1); - e6 += new d(m1); - e7 += new d(m1); - e8 += new d(m1); - e9 += new d(m1); - e10 += new d(m1); - e11 += new d(m1); - e12 += new d(m1); - e13 += new d(m1); - e14 += new d(m1); - e15 += new d(m1); - e16 += new d(m1); - e17 += new d(m1); - e18 += new d(m1); - e19 += new d(m1); - e20 += new d(m1); - e21 += new d(m1); - e22 += new d(m1); - e23 += new d(m1); - e24 += new d(m1); + public Class12() { } + public Class12(int i) { } + public Class12(int i, int ii) { } + + public int f0 = 0; + static public int f1 = 0; + public int f2 = 0; + public int f3 = 0; + public int f4 = 0; + public int f5 = 0; + public int f6 = 0; + public int f7 = 0; + public int f8 = 0; + public int f9 = 0; + public int f10 = 0; + public int f11 = 0; + public int f12 = 0; + public int f13 = 0; + public int f14 = 0; + public int f15 = 0; + public int f16 = 0; + public int f17 = 0; + public int f18 = 0; + public int f19 = 0; + public int f20 = 0; + public int f21 = 0; + public int f22 = 0; + public int f23 = 0; + public int f24 = 0; + + public void m1() { } + static public void m2() { } + public void m3() { } + public void m4() { } + public void m5() { } + public void m6() { } + public void m7() { } + public void m8() { } + public void m9() { } + public void m10() { } + public void m11() { } + public void m12() { } + public void m13() { } + public void m14() { } + public void m15() { } + public void m16() { } + public void m17() { } + public void m18() { } + public void m19() { } + public void m20() { } + public void m21() { } + public void m22() { } + public void m23() { } + public void m24() { } + + public int p0 { get { return 1; } set { } } + static public int p1 { get { return 1; } set { } } + public int p2 { get { return 1; } set { } } + public int p3 { get { return 1; } set { } } + public int p4 { get { return 1; } set { } } + public int p5 { get { return 1; } set { } } + public int p6 { get { return 1; } set { } } + public int p7 { get { return 1; } set { } } + public int p8 { get { return 1; } set { } } + public int p9 { get { return 1; } set { } } + public int p10 { get { return 1; } set { } } + public int p11 { get { return 1; } set { } } + public int p12 { get { return 1; } set { } } + public int p13 { get { return 1; } set { } } + public int p14 { get { return 1; } set { } } + public int p15 { get { return 1; } set { } } + public int p16 { get { return 1; } set { } } + public int p17 { get { return 1; } set { } } + public int p18 { get { return 1; } set { } } + public int p19 { get { return 1; } set { } } + public int p20 { get { return 1; } set { } } + public int p21 { get { return 1; } set { } } + public int p22 { get { return 1; } set { } } + public int p23 { get { return 1; } set { } } + public int p24 { get { return 1; } set { } } + + public event d e0; + static public event d e1; + public event d e2; + public event d e3; + public event d e4; + public event d e5; + public event d e6; + public event d e7; + public event d e8; + public event d e9; + public event d e10; + public event d e11; + public event d e12; + public event d e13; + public event d e14; + public event d e15; + public event d e16; + public event d e17; + public event d e18; + public event d e19; + public event d e20; + public event d e21; + public event d e22; + public event d e23; + public event d e24; + + public void NoWarning() + { + e0 += new d(m1); + e1 += new d(m1); + e2 += new d(m1); + e3 += new d(m1); + e4 += new d(m1); + e5 += new d(m1); + e6 += new d(m1); + e7 += new d(m1); + e8 += new d(m1); + e9 += new d(m1); + e10 += new d(m1); + e11 += new d(m1); + e12 += new d(m1); + e13 += new d(m1); + e14 += new d(m1); + e15 += new d(m1); + e16 += new d(m1); + e17 += new d(m1); + e18 += new d(m1); + e19 += new d(m1); + e20 += new d(m1); + e21 += new d(m1); + e22 += new d(m1); + e23 += new d(m1); + e24 += new d(m1); + } } -} -public class Class13 -{ - public Class13() { } - public Class13(int i) { } - public Class13(int i, int ii) { } - - public int f0 = 0; - static public int f1 = 0; - public int f2 = 0; - public int f3 = 0; - public int f4 = 0; - public int f5 = 0; - public int f6 = 0; - public int f7 = 0; - public int f8 = 0; - public int f9 = 0; - public int f10 = 0; - public int f11 = 0; - public int f12 = 0; - public int f13 = 0; - public int f14 = 0; - public int f15 = 0; - public int f16 = 0; - public int f17 = 0; - public int f18 = 0; - public int f19 = 0; - public int f20 = 0; - public int f21 = 0; - public int f22 = 0; - public int f23 = 0; - public int f24 = 0; - - public void m1() { } - static public void m2() { } - public void m3() { } - public void m4() { } - public void m5() { } - public void m6() { } - public void m7() { } - public void m8() { } - public void m9() { } - public void m10() { } - public void m11() { } - public void m12() { } - public void m13() { } - public void m14() { } - public void m15() { } - public void m16() { } - public void m17() { } - public void m18() { } - public void m19() { } - public void m20() { } - public void m21() { } - public void m22() { } - public void m23() { } - public void m24() { } - - public int p0 { get { return 1; } set { } } - static public int p1 { get { return 1; } set { } } - public int p2 { get { return 1; } set { } } - public int p3 { get { return 1; } set { } } - public int p4 { get { return 1; } set { } } - public int p5 { get { return 1; } set { } } - public int p6 { get { return 1; } set { } } - public int p7 { get { return 1; } set { } } - public int p8 { get { return 1; } set { } } - public int p9 { get { return 1; } set { } } - public int p10 { get { return 1; } set { } } - public int p11 { get { return 1; } set { } } - public int p12 { get { return 1; } set { } } - public int p13 { get { return 1; } set { } } - public int p14 { get { return 1; } set { } } - public int p15 { get { return 1; } set { } } - public int p16 { get { return 1; } set { } } - public int p17 { get { return 1; } set { } } - public int p18 { get { return 1; } set { } } - public int p19 { get { return 1; } set { } } - public int p20 { get { return 1; } set { } } - public int p21 { get { return 1; } set { } } - public int p22 { get { return 1; } set { } } - public int p23 { get { return 1; } set { } } - public int p24 { get { return 1; } set { } } - - public event d e0; - static public event d e1; - public event d e2; - public event d e3; - public event d e4; - public event d e5; - public event d e6; - public event d e7; - public event d e8; - public event d e9; - public event d e10; - public event d e11; - public event d e12; - public event d e13; - public event d e14; - public event d e15; - public event d e16; - public event d e17; - public event d e18; - public event d e19; - public event d e20; - public event d e21; - public event d e22; - public event d e23; - public event d e24; - - public void NoWarning() + public class Class13 { - e0 += new d(m1); - e1 += new d(m1); - e2 += new d(m1); - e3 += new d(m1); - e4 += new d(m1); - e5 += new d(m1); - e6 += new d(m1); - e7 += new d(m1); - e8 += new d(m1); - e9 += new d(m1); - e10 += new d(m1); - e11 += new d(m1); - e12 += new d(m1); - e13 += new d(m1); - e14 += new d(m1); - e15 += new d(m1); - e16 += new d(m1); - e17 += new d(m1); - e18 += new d(m1); - e19 += new d(m1); - e20 += new d(m1); - e21 += new d(m1); - e22 += new d(m1); - e23 += new d(m1); - e24 += new d(m1); + public Class13() { } + public Class13(int i) { } + public Class13(int i, int ii) { } + + public int f0 = 0; + static public int f1 = 0; + public int f2 = 0; + public int f3 = 0; + public int f4 = 0; + public int f5 = 0; + public int f6 = 0; + public int f7 = 0; + public int f8 = 0; + public int f9 = 0; + public int f10 = 0; + public int f11 = 0; + public int f12 = 0; + public int f13 = 0; + public int f14 = 0; + public int f15 = 0; + public int f16 = 0; + public int f17 = 0; + public int f18 = 0; + public int f19 = 0; + public int f20 = 0; + public int f21 = 0; + public int f22 = 0; + public int f23 = 0; + public int f24 = 0; + + public void m1() { } + static public void m2() { } + public void m3() { } + public void m4() { } + public void m5() { } + public void m6() { } + public void m7() { } + public void m8() { } + public void m9() { } + public void m10() { } + public void m11() { } + public void m12() { } + public void m13() { } + public void m14() { } + public void m15() { } + public void m16() { } + public void m17() { } + public void m18() { } + public void m19() { } + public void m20() { } + public void m21() { } + public void m22() { } + public void m23() { } + public void m24() { } + + public int p0 { get { return 1; } set { } } + static public int p1 { get { return 1; } set { } } + public int p2 { get { return 1; } set { } } + public int p3 { get { return 1; } set { } } + public int p4 { get { return 1; } set { } } + public int p5 { get { return 1; } set { } } + public int p6 { get { return 1; } set { } } + public int p7 { get { return 1; } set { } } + public int p8 { get { return 1; } set { } } + public int p9 { get { return 1; } set { } } + public int p10 { get { return 1; } set { } } + public int p11 { get { return 1; } set { } } + public int p12 { get { return 1; } set { } } + public int p13 { get { return 1; } set { } } + public int p14 { get { return 1; } set { } } + public int p15 { get { return 1; } set { } } + public int p16 { get { return 1; } set { } } + public int p17 { get { return 1; } set { } } + public int p18 { get { return 1; } set { } } + public int p19 { get { return 1; } set { } } + public int p20 { get { return 1; } set { } } + public int p21 { get { return 1; } set { } } + public int p22 { get { return 1; } set { } } + public int p23 { get { return 1; } set { } } + public int p24 { get { return 1; } set { } } + + public event d e0; + static public event d e1; + public event d e2; + public event d e3; + public event d e4; + public event d e5; + public event d e6; + public event d e7; + public event d e8; + public event d e9; + public event d e10; + public event d e11; + public event d e12; + public event d e13; + public event d e14; + public event d e15; + public event d e16; + public event d e17; + public event d e18; + public event d e19; + public event d e20; + public event d e21; + public event d e22; + public event d e23; + public event d e24; + + public void NoWarning() + { + e0 += new d(m1); + e1 += new d(m1); + e2 += new d(m1); + e3 += new d(m1); + e4 += new d(m1); + e5 += new d(m1); + e6 += new d(m1); + e7 += new d(m1); + e8 += new d(m1); + e9 += new d(m1); + e10 += new d(m1); + e11 += new d(m1); + e12 += new d(m1); + e13 += new d(m1); + e14 += new d(m1); + e15 += new d(m1); + e16 += new d(m1); + e17 += new d(m1); + e18 += new d(m1); + e19 += new d(m1); + e20 += new d(m1); + e21 += new d(m1); + e22 += new d(m1); + e23 += new d(m1); + e24 += new d(m1); + } } -} -public class Class14 -{ - public Class14() { } - public Class14(int i) { } - public Class14(int i, int ii) { } - - public int f0 = 0; - static public int f1 = 0; - public int f2 = 0; - public int f3 = 0; - public int f4 = 0; - public int f5 = 0; - public int f6 = 0; - public int f7 = 0; - public int f8 = 0; - public int f9 = 0; - public int f10 = 0; - public int f11 = 0; - public int f12 = 0; - public int f13 = 0; - public int f14 = 0; - public int f15 = 0; - public int f16 = 0; - public int f17 = 0; - public int f18 = 0; - public int f19 = 0; - public int f20 = 0; - public int f21 = 0; - public int f22 = 0; - public int f23 = 0; - public int f24 = 0; - - public void m1() { } - static public void m2() { } - public void m3() { } - public void m4() { } - public void m5() { } - public void m6() { } - public void m7() { } - public void m8() { } - public void m9() { } - public void m10() { } - public void m11() { } - public void m12() { } - public void m13() { } - public void m14() { } - public void m15() { } - public void m16() { } - public void m17() { } - public void m18() { } - public void m19() { } - public void m20() { } - public void m21() { } - public void m22() { } - public void m23() { } - public void m24() { } - - public int p0 { get { return 1; } set { } } - static public int p1 { get { return 1; } set { } } - public int p2 { get { return 1; } set { } } - public int p3 { get { return 1; } set { } } - public int p4 { get { return 1; } set { } } - public int p5 { get { return 1; } set { } } - public int p6 { get { return 1; } set { } } - public int p7 { get { return 1; } set { } } - public int p8 { get { return 1; } set { } } - public int p9 { get { return 1; } set { } } - public int p10 { get { return 1; } set { } } - public int p11 { get { return 1; } set { } } - public int p12 { get { return 1; } set { } } - public int p13 { get { return 1; } set { } } - public int p14 { get { return 1; } set { } } - public int p15 { get { return 1; } set { } } - public int p16 { get { return 1; } set { } } - public int p17 { get { return 1; } set { } } - public int p18 { get { return 1; } set { } } - public int p19 { get { return 1; } set { } } - public int p20 { get { return 1; } set { } } - public int p21 { get { return 1; } set { } } - public int p22 { get { return 1; } set { } } - public int p23 { get { return 1; } set { } } - public int p24 { get { return 1; } set { } } - - public event d e0; - static public event d e1; - public event d e2; - public event d e3; - public event d e4; - public event d e5; - public event d e6; - public event d e7; - public event d e8; - public event d e9; - public event d e10; - public event d e11; - public event d e12; - public event d e13; - public event d e14; - public event d e15; - public event d e16; - public event d e17; - public event d e18; - public event d e19; - public event d e20; - public event d e21; - public event d e22; - public event d e23; - public event d e24; - - public void NoWarning() + public class Class14 { - e0 += new d(m1); - e1 += new d(m1); - e2 += new d(m1); - e3 += new d(m1); - e4 += new d(m1); - e5 += new d(m1); - e6 += new d(m1); - e7 += new d(m1); - e8 += new d(m1); - e9 += new d(m1); - e10 += new d(m1); - e11 += new d(m1); - e12 += new d(m1); - e13 += new d(m1); - e14 += new d(m1); - e15 += new d(m1); - e16 += new d(m1); - e17 += new d(m1); - e18 += new d(m1); - e19 += new d(m1); - e20 += new d(m1); - e21 += new d(m1); - e22 += new d(m1); - e23 += new d(m1); - e24 += new d(m1); + public Class14() { } + public Class14(int i) { } + public Class14(int i, int ii) { } + + public int f0 = 0; + static public int f1 = 0; + public int f2 = 0; + public int f3 = 0; + public int f4 = 0; + public int f5 = 0; + public int f6 = 0; + public int f7 = 0; + public int f8 = 0; + public int f9 = 0; + public int f10 = 0; + public int f11 = 0; + public int f12 = 0; + public int f13 = 0; + public int f14 = 0; + public int f15 = 0; + public int f16 = 0; + public int f17 = 0; + public int f18 = 0; + public int f19 = 0; + public int f20 = 0; + public int f21 = 0; + public int f22 = 0; + public int f23 = 0; + public int f24 = 0; + + public void m1() { } + static public void m2() { } + public void m3() { } + public void m4() { } + public void m5() { } + public void m6() { } + public void m7() { } + public void m8() { } + public void m9() { } + public void m10() { } + public void m11() { } + public void m12() { } + public void m13() { } + public void m14() { } + public void m15() { } + public void m16() { } + public void m17() { } + public void m18() { } + public void m19() { } + public void m20() { } + public void m21() { } + public void m22() { } + public void m23() { } + public void m24() { } + + public int p0 { get { return 1; } set { } } + static public int p1 { get { return 1; } set { } } + public int p2 { get { return 1; } set { } } + public int p3 { get { return 1; } set { } } + public int p4 { get { return 1; } set { } } + public int p5 { get { return 1; } set { } } + public int p6 { get { return 1; } set { } } + public int p7 { get { return 1; } set { } } + public int p8 { get { return 1; } set { } } + public int p9 { get { return 1; } set { } } + public int p10 { get { return 1; } set { } } + public int p11 { get { return 1; } set { } } + public int p12 { get { return 1; } set { } } + public int p13 { get { return 1; } set { } } + public int p14 { get { return 1; } set { } } + public int p15 { get { return 1; } set { } } + public int p16 { get { return 1; } set { } } + public int p17 { get { return 1; } set { } } + public int p18 { get { return 1; } set { } } + public int p19 { get { return 1; } set { } } + public int p20 { get { return 1; } set { } } + public int p21 { get { return 1; } set { } } + public int p22 { get { return 1; } set { } } + public int p23 { get { return 1; } set { } } + public int p24 { get { return 1; } set { } } + + public event d e0; + static public event d e1; + public event d e2; + public event d e3; + public event d e4; + public event d e5; + public event d e6; + public event d e7; + public event d e8; + public event d e9; + public event d e10; + public event d e11; + public event d e12; + public event d e13; + public event d e14; + public event d e15; + public event d e16; + public event d e17; + public event d e18; + public event d e19; + public event d e20; + public event d e21; + public event d e22; + public event d e23; + public event d e24; + + public void NoWarning() + { + e0 += new d(m1); + e1 += new d(m1); + e2 += new d(m1); + e3 += new d(m1); + e4 += new d(m1); + e5 += new d(m1); + e6 += new d(m1); + e7 += new d(m1); + e8 += new d(m1); + e9 += new d(m1); + e10 += new d(m1); + e11 += new d(m1); + e12 += new d(m1); + e13 += new d(m1); + e14 += new d(m1); + e15 += new d(m1); + e16 += new d(m1); + e17 += new d(m1); + e18 += new d(m1); + e19 += new d(m1); + e20 += new d(m1); + e21 += new d(m1); + e22 += new d(m1); + e23 += new d(m1); + e24 += new d(m1); + } } -} -public class Class15 -{ - public Class15() { } - public Class15(int i) { } - public Class15(int i, int ii) { } - - public int f0 = 0; - static public int f1 = 0; - public int f2 = 0; - public int f3 = 0; - public int f4 = 0; - public int f5 = 0; - public int f6 = 0; - public int f7 = 0; - public int f8 = 0; - public int f9 = 0; - public int f10 = 0; - public int f11 = 0; - public int f12 = 0; - public int f13 = 0; - public int f14 = 0; - public int f15 = 0; - public int f16 = 0; - public int f17 = 0; - public int f18 = 0; - public int f19 = 0; - public int f20 = 0; - public int f21 = 0; - public int f22 = 0; - public int f23 = 0; - public int f24 = 0; - - public void m1() { } - static public void m2() { } - public void m3() { } - public void m4() { } - public void m5() { } - public void m6() { } - public void m7() { } - public void m8() { } - public void m9() { } - public void m10() { } - public void m11() { } - public void m12() { } - public void m13() { } - public void m14() { } - public void m15() { } - public void m16() { } - public void m17() { } - public void m18() { } - public void m19() { } - public void m20() { } - public void m21() { } - public void m22() { } - public void m23() { } - public void m24() { } - - public int p0 { get { return 1; } set { } } - static public int p1 { get { return 1; } set { } } - public int p2 { get { return 1; } set { } } - public int p3 { get { return 1; } set { } } - public int p4 { get { return 1; } set { } } - public int p5 { get { return 1; } set { } } - public int p6 { get { return 1; } set { } } - public int p7 { get { return 1; } set { } } - public int p8 { get { return 1; } set { } } - public int p9 { get { return 1; } set { } } - public int p10 { get { return 1; } set { } } - public int p11 { get { return 1; } set { } } - public int p12 { get { return 1; } set { } } - public int p13 { get { return 1; } set { } } - public int p14 { get { return 1; } set { } } - public int p15 { get { return 1; } set { } } - public int p16 { get { return 1; } set { } } - public int p17 { get { return 1; } set { } } - public int p18 { get { return 1; } set { } } - public int p19 { get { return 1; } set { } } - public int p20 { get { return 1; } set { } } - public int p21 { get { return 1; } set { } } - public int p22 { get { return 1; } set { } } - public int p23 { get { return 1; } set { } } - public int p24 { get { return 1; } set { } } - - public event d e0; - static public event d e1; - public event d e2; - public event d e3; - public event d e4; - public event d e5; - public event d e6; - public event d e7; - public event d e8; - public event d e9; - public event d e10; - public event d e11; - public event d e12; - public event d e13; - public event d e14; - public event d e15; - public event d e16; - public event d e17; - public event d e18; - public event d e19; - public event d e20; - public event d e21; - public event d e22; - public event d e23; - public event d e24; - - public void NoWarning() + public class Class15 { - e0 += new d(m1); - e1 += new d(m1); - e2 += new d(m1); - e3 += new d(m1); - e4 += new d(m1); - e5 += new d(m1); - e6 += new d(m1); - e7 += new d(m1); - e8 += new d(m1); - e9 += new d(m1); - e10 += new d(m1); - e11 += new d(m1); - e12 += new d(m1); - e13 += new d(m1); - e14 += new d(m1); - e15 += new d(m1); - e16 += new d(m1); - e17 += new d(m1); - e18 += new d(m1); - e19 += new d(m1); - e20 += new d(m1); - e21 += new d(m1); - e22 += new d(m1); - e23 += new d(m1); - e24 += new d(m1); + public Class15() { } + public Class15(int i) { } + public Class15(int i, int ii) { } + + public int f0 = 0; + static public int f1 = 0; + public int f2 = 0; + public int f3 = 0; + public int f4 = 0; + public int f5 = 0; + public int f6 = 0; + public int f7 = 0; + public int f8 = 0; + public int f9 = 0; + public int f10 = 0; + public int f11 = 0; + public int f12 = 0; + public int f13 = 0; + public int f14 = 0; + public int f15 = 0; + public int f16 = 0; + public int f17 = 0; + public int f18 = 0; + public int f19 = 0; + public int f20 = 0; + public int f21 = 0; + public int f22 = 0; + public int f23 = 0; + public int f24 = 0; + + public void m1() { } + static public void m2() { } + public void m3() { } + public void m4() { } + public void m5() { } + public void m6() { } + public void m7() { } + public void m8() { } + public void m9() { } + public void m10() { } + public void m11() { } + public void m12() { } + public void m13() { } + public void m14() { } + public void m15() { } + public void m16() { } + public void m17() { } + public void m18() { } + public void m19() { } + public void m20() { } + public void m21() { } + public void m22() { } + public void m23() { } + public void m24() { } + + public int p0 { get { return 1; } set { } } + static public int p1 { get { return 1; } set { } } + public int p2 { get { return 1; } set { } } + public int p3 { get { return 1; } set { } } + public int p4 { get { return 1; } set { } } + public int p5 { get { return 1; } set { } } + public int p6 { get { return 1; } set { } } + public int p7 { get { return 1; } set { } } + public int p8 { get { return 1; } set { } } + public int p9 { get { return 1; } set { } } + public int p10 { get { return 1; } set { } } + public int p11 { get { return 1; } set { } } + public int p12 { get { return 1; } set { } } + public int p13 { get { return 1; } set { } } + public int p14 { get { return 1; } set { } } + public int p15 { get { return 1; } set { } } + public int p16 { get { return 1; } set { } } + public int p17 { get { return 1; } set { } } + public int p18 { get { return 1; } set { } } + public int p19 { get { return 1; } set { } } + public int p20 { get { return 1; } set { } } + public int p21 { get { return 1; } set { } } + public int p22 { get { return 1; } set { } } + public int p23 { get { return 1; } set { } } + public int p24 { get { return 1; } set { } } + + public event d e0; + static public event d e1; + public event d e2; + public event d e3; + public event d e4; + public event d e5; + public event d e6; + public event d e7; + public event d e8; + public event d e9; + public event d e10; + public event d e11; + public event d e12; + public event d e13; + public event d e14; + public event d e15; + public event d e16; + public event d e17; + public event d e18; + public event d e19; + public event d e20; + public event d e21; + public event d e22; + public event d e23; + public event d e24; + + public void NoWarning() + { + e0 += new d(m1); + e1 += new d(m1); + e2 += new d(m1); + e3 += new d(m1); + e4 += new d(m1); + e5 += new d(m1); + e6 += new d(m1); + e7 += new d(m1); + e8 += new d(m1); + e9 += new d(m1); + e10 += new d(m1); + e11 += new d(m1); + e12 += new d(m1); + e13 += new d(m1); + e14 += new d(m1); + e15 += new d(m1); + e16 += new d(m1); + e17 += new d(m1); + e18 += new d(m1); + e19 += new d(m1); + e20 += new d(m1); + e21 += new d(m1); + e22 += new d(m1); + e23 += new d(m1); + e24 += new d(m1); + } } -} -public class Class16 -{ - public Class16() { } - public Class16(int i) { } - public Class16(int i, int ii) { } - - public int f0 = 0; - static public int f1 = 0; - public int f2 = 0; - public int f3 = 0; - public int f4 = 0; - public int f5 = 0; - public int f6 = 0; - public int f7 = 0; - public int f8 = 0; - public int f9 = 0; - public int f10 = 0; - public int f11 = 0; - public int f12 = 0; - public int f13 = 0; - public int f14 = 0; - public int f15 = 0; - public int f16 = 0; - public int f17 = 0; - public int f18 = 0; - public int f19 = 0; - public int f20 = 0; - public int f21 = 0; - public int f22 = 0; - public int f23 = 0; - public int f24 = 0; - - public void m1() { } - static public void m2() { } - public void m3() { } - public void m4() { } - public void m5() { } - public void m6() { } - public void m7() { } - public void m8() { } - public void m9() { } - public void m10() { } - public void m11() { } - public void m12() { } - public void m13() { } - public void m14() { } - public void m15() { } - public void m16() { } - public void m17() { } - public void m18() { } - public void m19() { } - public void m20() { } - public void m21() { } - public void m22() { } - public void m23() { } - public void m24() { } - - public int p0 { get { return 1; } set { } } - static public int p1 { get { return 1; } set { } } - public int p2 { get { return 1; } set { } } - public int p3 { get { return 1; } set { } } - public int p4 { get { return 1; } set { } } - public int p5 { get { return 1; } set { } } - public int p6 { get { return 1; } set { } } - public int p7 { get { return 1; } set { } } - public int p8 { get { return 1; } set { } } - public int p9 { get { return 1; } set { } } - public int p10 { get { return 1; } set { } } - public int p11 { get { return 1; } set { } } - public int p12 { get { return 1; } set { } } - public int p13 { get { return 1; } set { } } - public int p14 { get { return 1; } set { } } - public int p15 { get { return 1; } set { } } - public int p16 { get { return 1; } set { } } - public int p17 { get { return 1; } set { } } - public int p18 { get { return 1; } set { } } - public int p19 { get { return 1; } set { } } - public int p20 { get { return 1; } set { } } - public int p21 { get { return 1; } set { } } - public int p22 { get { return 1; } set { } } - public int p23 { get { return 1; } set { } } - public int p24 { get { return 1; } set { } } - - public event d e0; - static public event d e1; - public event d e2; - public event d e3; - public event d e4; - public event d e5; - public event d e6; - public event d e7; - public event d e8; - public event d e9; - public event d e10; - public event d e11; - public event d e12; - public event d e13; - public event d e14; - public event d e15; - public event d e16; - public event d e17; - public event d e18; - public event d e19; - public event d e20; - public event d e21; - public event d e22; - public event d e23; - public event d e24; - - public void NoWarning() + public class Class16 { - e0 += new d(m1); - e1 += new d(m1); - e2 += new d(m1); - e3 += new d(m1); - e4 += new d(m1); - e5 += new d(m1); - e6 += new d(m1); - e7 += new d(m1); - e8 += new d(m1); - e9 += new d(m1); - e10 += new d(m1); - e11 += new d(m1); - e12 += new d(m1); - e13 += new d(m1); - e14 += new d(m1); - e15 += new d(m1); - e16 += new d(m1); - e17 += new d(m1); - e18 += new d(m1); - e19 += new d(m1); - e20 += new d(m1); - e21 += new d(m1); - e22 += new d(m1); - e23 += new d(m1); - e24 += new d(m1); + public Class16() { } + public Class16(int i) { } + public Class16(int i, int ii) { } + + public int f0 = 0; + static public int f1 = 0; + public int f2 = 0; + public int f3 = 0; + public int f4 = 0; + public int f5 = 0; + public int f6 = 0; + public int f7 = 0; + public int f8 = 0; + public int f9 = 0; + public int f10 = 0; + public int f11 = 0; + public int f12 = 0; + public int f13 = 0; + public int f14 = 0; + public int f15 = 0; + public int f16 = 0; + public int f17 = 0; + public int f18 = 0; + public int f19 = 0; + public int f20 = 0; + public int f21 = 0; + public int f22 = 0; + public int f23 = 0; + public int f24 = 0; + + public void m1() { } + static public void m2() { } + public void m3() { } + public void m4() { } + public void m5() { } + public void m6() { } + public void m7() { } + public void m8() { } + public void m9() { } + public void m10() { } + public void m11() { } + public void m12() { } + public void m13() { } + public void m14() { } + public void m15() { } + public void m16() { } + public void m17() { } + public void m18() { } + public void m19() { } + public void m20() { } + public void m21() { } + public void m22() { } + public void m23() { } + public void m24() { } + + public int p0 { get { return 1; } set { } } + static public int p1 { get { return 1; } set { } } + public int p2 { get { return 1; } set { } } + public int p3 { get { return 1; } set { } } + public int p4 { get { return 1; } set { } } + public int p5 { get { return 1; } set { } } + public int p6 { get { return 1; } set { } } + public int p7 { get { return 1; } set { } } + public int p8 { get { return 1; } set { } } + public int p9 { get { return 1; } set { } } + public int p10 { get { return 1; } set { } } + public int p11 { get { return 1; } set { } } + public int p12 { get { return 1; } set { } } + public int p13 { get { return 1; } set { } } + public int p14 { get { return 1; } set { } } + public int p15 { get { return 1; } set { } } + public int p16 { get { return 1; } set { } } + public int p17 { get { return 1; } set { } } + public int p18 { get { return 1; } set { } } + public int p19 { get { return 1; } set { } } + public int p20 { get { return 1; } set { } } + public int p21 { get { return 1; } set { } } + public int p22 { get { return 1; } set { } } + public int p23 { get { return 1; } set { } } + public int p24 { get { return 1; } set { } } + + public event d e0; + static public event d e1; + public event d e2; + public event d e3; + public event d e4; + public event d e5; + public event d e6; + public event d e7; + public event d e8; + public event d e9; + public event d e10; + public event d e11; + public event d e12; + public event d e13; + public event d e14; + public event d e15; + public event d e16; + public event d e17; + public event d e18; + public event d e19; + public event d e20; + public event d e21; + public event d e22; + public event d e23; + public event d e24; + + public void NoWarning() + { + e0 += new d(m1); + e1 += new d(m1); + e2 += new d(m1); + e3 += new d(m1); + e4 += new d(m1); + e5 += new d(m1); + e6 += new d(m1); + e7 += new d(m1); + e8 += new d(m1); + e9 += new d(m1); + e10 += new d(m1); + e11 += new d(m1); + e12 += new d(m1); + e13 += new d(m1); + e14 += new d(m1); + e15 += new d(m1); + e16 += new d(m1); + e17 += new d(m1); + e18 += new d(m1); + e19 += new d(m1); + e20 += new d(m1); + e21 += new d(m1); + e22 += new d(m1); + e23 += new d(m1); + e24 += new d(m1); + } } -} -public class Class17 -{ - public Class17() { } - public Class17(int i) { } - public Class17(int i, int ii) { } - - public int f0 = 0; - static public int f1 = 0; - public int f2 = 0; - public int f3 = 0; - public int f4 = 0; - public int f5 = 0; - public int f6 = 0; - public int f7 = 0; - public int f8 = 0; - public int f9 = 0; - public int f10 = 0; - public int f11 = 0; - public int f12 = 0; - public int f13 = 0; - public int f14 = 0; - public int f15 = 0; - public int f16 = 0; - public int f17 = 0; - public int f18 = 0; - public int f19 = 0; - public int f20 = 0; - public int f21 = 0; - public int f22 = 0; - public int f23 = 0; - public int f24 = 0; - - public void m1() { } - static public void m2() { } - public void m3() { } - public void m4() { } - public void m5() { } - public void m6() { } - public void m7() { } - public void m8() { } - public void m9() { } - public void m10() { } - public void m11() { } - public void m12() { } - public void m13() { } - public void m14() { } - public void m15() { } - public void m16() { } - public void m17() { } - public void m18() { } - public void m19() { } - public void m20() { } - public void m21() { } - public void m22() { } - public void m23() { } - public void m24() { } - - public int p0 { get { return 1; } set { } } - static public int p1 { get { return 1; } set { } } - public int p2 { get { return 1; } set { } } - public int p3 { get { return 1; } set { } } - public int p4 { get { return 1; } set { } } - public int p5 { get { return 1; } set { } } - public int p6 { get { return 1; } set { } } - public int p7 { get { return 1; } set { } } - public int p8 { get { return 1; } set { } } - public int p9 { get { return 1; } set { } } - public int p10 { get { return 1; } set { } } - public int p11 { get { return 1; } set { } } - public int p12 { get { return 1; } set { } } - public int p13 { get { return 1; } set { } } - public int p14 { get { return 1; } set { } } - public int p15 { get { return 1; } set { } } - public int p16 { get { return 1; } set { } } - public int p17 { get { return 1; } set { } } - public int p18 { get { return 1; } set { } } - public int p19 { get { return 1; } set { } } - public int p20 { get { return 1; } set { } } - public int p21 { get { return 1; } set { } } - public int p22 { get { return 1; } set { } } - public int p23 { get { return 1; } set { } } - public int p24 { get { return 1; } set { } } - - public event d e0; - static public event d e1; - public event d e2; - public event d e3; - public event d e4; - public event d e5; - public event d e6; - public event d e7; - public event d e8; - public event d e9; - public event d e10; - public event d e11; - public event d e12; - public event d e13; - public event d e14; - public event d e15; - public event d e16; - public event d e17; - public event d e18; - public event d e19; - public event d e20; - public event d e21; - public event d e22; - public event d e23; - public event d e24; - - public void NoWarning() + public class Class17 { - e0 += new d(m1); - e1 += new d(m1); - e2 += new d(m1); - e3 += new d(m1); - e4 += new d(m1); - e5 += new d(m1); - e6 += new d(m1); - e7 += new d(m1); - e8 += new d(m1); - e9 += new d(m1); - e10 += new d(m1); - e11 += new d(m1); - e12 += new d(m1); - e13 += new d(m1); - e14 += new d(m1); - e15 += new d(m1); - e16 += new d(m1); - e17 += new d(m1); - e18 += new d(m1); - e19 += new d(m1); - e20 += new d(m1); - e21 += new d(m1); - e22 += new d(m1); - e23 += new d(m1); - e24 += new d(m1); + public Class17() { } + public Class17(int i) { } + public Class17(int i, int ii) { } + + public int f0 = 0; + static public int f1 = 0; + public int f2 = 0; + public int f3 = 0; + public int f4 = 0; + public int f5 = 0; + public int f6 = 0; + public int f7 = 0; + public int f8 = 0; + public int f9 = 0; + public int f10 = 0; + public int f11 = 0; + public int f12 = 0; + public int f13 = 0; + public int f14 = 0; + public int f15 = 0; + public int f16 = 0; + public int f17 = 0; + public int f18 = 0; + public int f19 = 0; + public int f20 = 0; + public int f21 = 0; + public int f22 = 0; + public int f23 = 0; + public int f24 = 0; + + public void m1() { } + static public void m2() { } + public void m3() { } + public void m4() { } + public void m5() { } + public void m6() { } + public void m7() { } + public void m8() { } + public void m9() { } + public void m10() { } + public void m11() { } + public void m12() { } + public void m13() { } + public void m14() { } + public void m15() { } + public void m16() { } + public void m17() { } + public void m18() { } + public void m19() { } + public void m20() { } + public void m21() { } + public void m22() { } + public void m23() { } + public void m24() { } + + public int p0 { get { return 1; } set { } } + static public int p1 { get { return 1; } set { } } + public int p2 { get { return 1; } set { } } + public int p3 { get { return 1; } set { } } + public int p4 { get { return 1; } set { } } + public int p5 { get { return 1; } set { } } + public int p6 { get { return 1; } set { } } + public int p7 { get { return 1; } set { } } + public int p8 { get { return 1; } set { } } + public int p9 { get { return 1; } set { } } + public int p10 { get { return 1; } set { } } + public int p11 { get { return 1; } set { } } + public int p12 { get { return 1; } set { } } + public int p13 { get { return 1; } set { } } + public int p14 { get { return 1; } set { } } + public int p15 { get { return 1; } set { } } + public int p16 { get { return 1; } set { } } + public int p17 { get { return 1; } set { } } + public int p18 { get { return 1; } set { } } + public int p19 { get { return 1; } set { } } + public int p20 { get { return 1; } set { } } + public int p21 { get { return 1; } set { } } + public int p22 { get { return 1; } set { } } + public int p23 { get { return 1; } set { } } + public int p24 { get { return 1; } set { } } + + public event d e0; + static public event d e1; + public event d e2; + public event d e3; + public event d e4; + public event d e5; + public event d e6; + public event d e7; + public event d e8; + public event d e9; + public event d e10; + public event d e11; + public event d e12; + public event d e13; + public event d e14; + public event d e15; + public event d e16; + public event d e17; + public event d e18; + public event d e19; + public event d e20; + public event d e21; + public event d e22; + public event d e23; + public event d e24; + + public void NoWarning() + { + e0 += new d(m1); + e1 += new d(m1); + e2 += new d(m1); + e3 += new d(m1); + e4 += new d(m1); + e5 += new d(m1); + e6 += new d(m1); + e7 += new d(m1); + e8 += new d(m1); + e9 += new d(m1); + e10 += new d(m1); + e11 += new d(m1); + e12 += new d(m1); + e13 += new d(m1); + e14 += new d(m1); + e15 += new d(m1); + e16 += new d(m1); + e17 += new d(m1); + e18 += new d(m1); + e19 += new d(m1); + e20 += new d(m1); + e21 += new d(m1); + e22 += new d(m1); + e23 += new d(m1); + e24 += new d(m1); + } } -} -public class Class18 -{ - public Class18() { } - public Class18(int i) { } - public Class18(int i, int ii) { } - - public int f0 = 0; - static public int f1 = 0; - public int f2 = 0; - public int f3 = 0; - public int f4 = 0; - public int f5 = 0; - public int f6 = 0; - public int f7 = 0; - public int f8 = 0; - public int f9 = 0; - public int f10 = 0; - public int f11 = 0; - public int f12 = 0; - public int f13 = 0; - public int f14 = 0; - public int f15 = 0; - public int f16 = 0; - public int f17 = 0; - public int f18 = 0; - public int f19 = 0; - public int f20 = 0; - public int f21 = 0; - public int f22 = 0; - public int f23 = 0; - public int f24 = 0; - - public void m1() { } - static public void m2() { } - public void m3() { } - public void m4() { } - public void m5() { } - public void m6() { } - public void m7() { } - public void m8() { } - public void m9() { } - public void m10() { } - public void m11() { } - public void m12() { } - public void m13() { } - public void m14() { } - public void m15() { } - public void m16() { } - public void m17() { } - public void m18() { } - public void m19() { } - public void m20() { } - public void m21() { } - public void m22() { } - public void m23() { } - public void m24() { } - - public int p0 { get { return 1; } set { } } - static public int p1 { get { return 1; } set { } } - public int p2 { get { return 1; } set { } } - public int p3 { get { return 1; } set { } } - public int p4 { get { return 1; } set { } } - public int p5 { get { return 1; } set { } } - public int p6 { get { return 1; } set { } } - public int p7 { get { return 1; } set { } } - public int p8 { get { return 1; } set { } } - public int p9 { get { return 1; } set { } } - public int p10 { get { return 1; } set { } } - public int p11 { get { return 1; } set { } } - public int p12 { get { return 1; } set { } } - public int p13 { get { return 1; } set { } } - public int p14 { get { return 1; } set { } } - public int p15 { get { return 1; } set { } } - public int p16 { get { return 1; } set { } } - public int p17 { get { return 1; } set { } } - public int p18 { get { return 1; } set { } } - public int p19 { get { return 1; } set { } } - public int p20 { get { return 1; } set { } } - public int p21 { get { return 1; } set { } } - public int p22 { get { return 1; } set { } } - public int p23 { get { return 1; } set { } } - public int p24 { get { return 1; } set { } } - - public event d e0; - static public event d e1; - public event d e2; - public event d e3; - public event d e4; - public event d e5; - public event d e6; - public event d e7; - public event d e8; - public event d e9; - public event d e10; - public event d e11; - public event d e12; - public event d e13; - public event d e14; - public event d e15; - public event d e16; - public event d e17; - public event d e18; - public event d e19; - public event d e20; - public event d e21; - public event d e22; - public event d e23; - public event d e24; - - public void NoWarning() + public class Class18 { - e0 += new d(m1); - e1 += new d(m1); - e2 += new d(m1); - e3 += new d(m1); - e4 += new d(m1); - e5 += new d(m1); - e6 += new d(m1); - e7 += new d(m1); - e8 += new d(m1); - e9 += new d(m1); - e10 += new d(m1); - e11 += new d(m1); - e12 += new d(m1); - e13 += new d(m1); - e14 += new d(m1); - e15 += new d(m1); - e16 += new d(m1); - e17 += new d(m1); - e18 += new d(m1); - e19 += new d(m1); - e20 += new d(m1); - e21 += new d(m1); - e22 += new d(m1); - e23 += new d(m1); - e24 += new d(m1); + public Class18() { } + public Class18(int i) { } + public Class18(int i, int ii) { } + + public int f0 = 0; + static public int f1 = 0; + public int f2 = 0; + public int f3 = 0; + public int f4 = 0; + public int f5 = 0; + public int f6 = 0; + public int f7 = 0; + public int f8 = 0; + public int f9 = 0; + public int f10 = 0; + public int f11 = 0; + public int f12 = 0; + public int f13 = 0; + public int f14 = 0; + public int f15 = 0; + public int f16 = 0; + public int f17 = 0; + public int f18 = 0; + public int f19 = 0; + public int f20 = 0; + public int f21 = 0; + public int f22 = 0; + public int f23 = 0; + public int f24 = 0; + + public void m1() { } + static public void m2() { } + public void m3() { } + public void m4() { } + public void m5() { } + public void m6() { } + public void m7() { } + public void m8() { } + public void m9() { } + public void m10() { } + public void m11() { } + public void m12() { } + public void m13() { } + public void m14() { } + public void m15() { } + public void m16() { } + public void m17() { } + public void m18() { } + public void m19() { } + public void m20() { } + public void m21() { } + public void m22() { } + public void m23() { } + public void m24() { } + + public int p0 { get { return 1; } set { } } + static public int p1 { get { return 1; } set { } } + public int p2 { get { return 1; } set { } } + public int p3 { get { return 1; } set { } } + public int p4 { get { return 1; } set { } } + public int p5 { get { return 1; } set { } } + public int p6 { get { return 1; } set { } } + public int p7 { get { return 1; } set { } } + public int p8 { get { return 1; } set { } } + public int p9 { get { return 1; } set { } } + public int p10 { get { return 1; } set { } } + public int p11 { get { return 1; } set { } } + public int p12 { get { return 1; } set { } } + public int p13 { get { return 1; } set { } } + public int p14 { get { return 1; } set { } } + public int p15 { get { return 1; } set { } } + public int p16 { get { return 1; } set { } } + public int p17 { get { return 1; } set { } } + public int p18 { get { return 1; } set { } } + public int p19 { get { return 1; } set { } } + public int p20 { get { return 1; } set { } } + public int p21 { get { return 1; } set { } } + public int p22 { get { return 1; } set { } } + public int p23 { get { return 1; } set { } } + public int p24 { get { return 1; } set { } } + + public event d e0; + static public event d e1; + public event d e2; + public event d e3; + public event d e4; + public event d e5; + public event d e6; + public event d e7; + public event d e8; + public event d e9; + public event d e10; + public event d e11; + public event d e12; + public event d e13; + public event d e14; + public event d e15; + public event d e16; + public event d e17; + public event d e18; + public event d e19; + public event d e20; + public event d e21; + public event d e22; + public event d e23; + public event d e24; + + public void NoWarning() + { + e0 += new d(m1); + e1 += new d(m1); + e2 += new d(m1); + e3 += new d(m1); + e4 += new d(m1); + e5 += new d(m1); + e6 += new d(m1); + e7 += new d(m1); + e8 += new d(m1); + e9 += new d(m1); + e10 += new d(m1); + e11 += new d(m1); + e12 += new d(m1); + e13 += new d(m1); + e14 += new d(m1); + e15 += new d(m1); + e16 += new d(m1); + e17 += new d(m1); + e18 += new d(m1); + e19 += new d(m1); + e20 += new d(m1); + e21 += new d(m1); + e22 += new d(m1); + e23 += new d(m1); + e24 += new d(m1); + } } -} -public class Class19 -{ - public Class19() { } - public Class19(int i) { } - public Class19(int i, int ii) { } - - public int f0 = 0; - static public int f1 = 0; - public int f2 = 0; - public int f3 = 0; - public int f4 = 0; - public int f5 = 0; - public int f6 = 0; - public int f7 = 0; - public int f8 = 0; - public int f9 = 0; - public int f10 = 0; - public int f11 = 0; - public int f12 = 0; - public int f13 = 0; - public int f14 = 0; - public int f15 = 0; - public int f16 = 0; - public int f17 = 0; - public int f18 = 0; - public int f19 = 0; - public int f20 = 0; - public int f21 = 0; - public int f22 = 0; - public int f23 = 0; - public int f24 = 0; - - public void m1() { } - static public void m2() { } - public void m3() { } - public void m4() { } - public void m5() { } - public void m6() { } - public void m7() { } - public void m8() { } - public void m9() { } - public void m10() { } - public void m11() { } - public void m12() { } - public void m13() { } - public void m14() { } - public void m15() { } - public void m16() { } - public void m17() { } - public void m18() { } - public void m19() { } - public void m20() { } - public void m21() { } - public void m22() { } - public void m23() { } - public void m24() { } - - public int p0 { get { return 1; } set { } } - static public int p1 { get { return 1; } set { } } - public int p2 { get { return 1; } set { } } - public int p3 { get { return 1; } set { } } - public int p4 { get { return 1; } set { } } - public int p5 { get { return 1; } set { } } - public int p6 { get { return 1; } set { } } - public int p7 { get { return 1; } set { } } - public int p8 { get { return 1; } set { } } - public int p9 { get { return 1; } set { } } - public int p10 { get { return 1; } set { } } - public int p11 { get { return 1; } set { } } - public int p12 { get { return 1; } set { } } - public int p13 { get { return 1; } set { } } - public int p14 { get { return 1; } set { } } - public int p15 { get { return 1; } set { } } - public int p16 { get { return 1; } set { } } - public int p17 { get { return 1; } set { } } - public int p18 { get { return 1; } set { } } - public int p19 { get { return 1; } set { } } - public int p20 { get { return 1; } set { } } - public int p21 { get { return 1; } set { } } - public int p22 { get { return 1; } set { } } - public int p23 { get { return 1; } set { } } - public int p24 { get { return 1; } set { } } - - public event d e0; - static public event d e1; - public event d e2; - public event d e3; - public event d e4; - public event d e5; - public event d e6; - public event d e7; - public event d e8; - public event d e9; - public event d e10; - public event d e11; - public event d e12; - public event d e13; - public event d e14; - public event d e15; - public event d e16; - public event d e17; - public event d e18; - public event d e19; - public event d e20; - public event d e21; - public event d e22; - public event d e23; - public event d e24; - - public void NoWarning() + public class Class19 { - e0 += new d(m1); - e1 += new d(m1); - e2 += new d(m1); - e3 += new d(m1); - e4 += new d(m1); - e5 += new d(m1); - e6 += new d(m1); - e7 += new d(m1); - e8 += new d(m1); - e9 += new d(m1); - e10 += new d(m1); - e11 += new d(m1); - e12 += new d(m1); - e13 += new d(m1); - e14 += new d(m1); - e15 += new d(m1); - e16 += new d(m1); - e17 += new d(m1); - e18 += new d(m1); - e19 += new d(m1); - e20 += new d(m1); - e21 += new d(m1); - e22 += new d(m1); - e23 += new d(m1); - e24 += new d(m1); + public Class19() { } + public Class19(int i) { } + public Class19(int i, int ii) { } + + public int f0 = 0; + static public int f1 = 0; + public int f2 = 0; + public int f3 = 0; + public int f4 = 0; + public int f5 = 0; + public int f6 = 0; + public int f7 = 0; + public int f8 = 0; + public int f9 = 0; + public int f10 = 0; + public int f11 = 0; + public int f12 = 0; + public int f13 = 0; + public int f14 = 0; + public int f15 = 0; + public int f16 = 0; + public int f17 = 0; + public int f18 = 0; + public int f19 = 0; + public int f20 = 0; + public int f21 = 0; + public int f22 = 0; + public int f23 = 0; + public int f24 = 0; + + public void m1() { } + static public void m2() { } + public void m3() { } + public void m4() { } + public void m5() { } + public void m6() { } + public void m7() { } + public void m8() { } + public void m9() { } + public void m10() { } + public void m11() { } + public void m12() { } + public void m13() { } + public void m14() { } + public void m15() { } + public void m16() { } + public void m17() { } + public void m18() { } + public void m19() { } + public void m20() { } + public void m21() { } + public void m22() { } + public void m23() { } + public void m24() { } + + public int p0 { get { return 1; } set { } } + static public int p1 { get { return 1; } set { } } + public int p2 { get { return 1; } set { } } + public int p3 { get { return 1; } set { } } + public int p4 { get { return 1; } set { } } + public int p5 { get { return 1; } set { } } + public int p6 { get { return 1; } set { } } + public int p7 { get { return 1; } set { } } + public int p8 { get { return 1; } set { } } + public int p9 { get { return 1; } set { } } + public int p10 { get { return 1; } set { } } + public int p11 { get { return 1; } set { } } + public int p12 { get { return 1; } set { } } + public int p13 { get { return 1; } set { } } + public int p14 { get { return 1; } set { } } + public int p15 { get { return 1; } set { } } + public int p16 { get { return 1; } set { } } + public int p17 { get { return 1; } set { } } + public int p18 { get { return 1; } set { } } + public int p19 { get { return 1; } set { } } + public int p20 { get { return 1; } set { } } + public int p21 { get { return 1; } set { } } + public int p22 { get { return 1; } set { } } + public int p23 { get { return 1; } set { } } + public int p24 { get { return 1; } set { } } + + public event d e0; + static public event d e1; + public event d e2; + public event d e3; + public event d e4; + public event d e5; + public event d e6; + public event d e7; + public event d e8; + public event d e9; + public event d e10; + public event d e11; + public event d e12; + public event d e13; + public event d e14; + public event d e15; + public event d e16; + public event d e17; + public event d e18; + public event d e19; + public event d e20; + public event d e21; + public event d e22; + public event d e23; + public event d e24; + + public void NoWarning() + { + e0 += new d(m1); + e1 += new d(m1); + e2 += new d(m1); + e3 += new d(m1); + e4 += new d(m1); + e5 += new d(m1); + e6 += new d(m1); + e7 += new d(m1); + e8 += new d(m1); + e9 += new d(m1); + e10 += new d(m1); + e11 += new d(m1); + e12 += new d(m1); + e13 += new d(m1); + e14 += new d(m1); + e15 += new d(m1); + e16 += new d(m1); + e17 += new d(m1); + e18 += new d(m1); + e19 += new d(m1); + e20 += new d(m1); + e21 += new d(m1); + e22 += new d(m1); + e23 += new d(m1); + e24 += new d(m1); + } } -} -public class Class20 -{ - public Class20() { } - public Class20(int i) { } - public Class20(int i, int ii) { } - - public int f0 = 0; - static public int f1 = 0; - public int f2 = 0; - public int f3 = 0; - public int f4 = 0; - public int f5 = 0; - public int f6 = 0; - public int f7 = 0; - public int f8 = 0; - public int f9 = 0; - public int f10 = 0; - public int f11 = 0; - public int f12 = 0; - public int f13 = 0; - public int f14 = 0; - public int f15 = 0; - public int f16 = 0; - public int f17 = 0; - public int f18 = 0; - public int f19 = 0; - public int f20 = 0; - public int f21 = 0; - public int f22 = 0; - public int f23 = 0; - public int f24 = 0; - - public void m1() { } - static public void m2() { } - public void m3() { } - public void m4() { } - public void m5() { } - public void m6() { } - public void m7() { } - public void m8() { } - public void m9() { } - public void m10() { } - public void m11() { } - public void m12() { } - public void m13() { } - public void m14() { } - public void m15() { } - public void m16() { } - public void m17() { } - public void m18() { } - public void m19() { } - public void m20() { } - public void m21() { } - public void m22() { } - public void m23() { } - public void m24() { } - - public int p0 { get { return 1; } set { } } - static public int p1 { get { return 1; } set { } } - public int p2 { get { return 1; } set { } } - public int p3 { get { return 1; } set { } } - public int p4 { get { return 1; } set { } } - public int p5 { get { return 1; } set { } } - public int p6 { get { return 1; } set { } } - public int p7 { get { return 1; } set { } } - public int p8 { get { return 1; } set { } } - public int p9 { get { return 1; } set { } } - public int p10 { get { return 1; } set { } } - public int p11 { get { return 1; } set { } } - public int p12 { get { return 1; } set { } } - public int p13 { get { return 1; } set { } } - public int p14 { get { return 1; } set { } } - public int p15 { get { return 1; } set { } } - public int p16 { get { return 1; } set { } } - public int p17 { get { return 1; } set { } } - public int p18 { get { return 1; } set { } } - public int p19 { get { return 1; } set { } } - public int p20 { get { return 1; } set { } } - public int p21 { get { return 1; } set { } } - public int p22 { get { return 1; } set { } } - public int p23 { get { return 1; } set { } } - public int p24 { get { return 1; } set { } } - - public event d e0; - static public event d e1; - public event d e2; - public event d e3; - public event d e4; - public event d e5; - public event d e6; - public event d e7; - public event d e8; - public event d e9; - public event d e10; - public event d e11; - public event d e12; - public event d e13; - public event d e14; - public event d e15; - public event d e16; - public event d e17; - public event d e18; - public event d e19; - public event d e20; - public event d e21; - public event d e22; - public event d e23; - public event d e24; - - public void NoWarning() + public class Class20 { - e0 += new d(m1); - e1 += new d(m1); - e2 += new d(m1); - e3 += new d(m1); - e4 += new d(m1); - e5 += new d(m1); - e6 += new d(m1); - e7 += new d(m1); - e8 += new d(m1); - e9 += new d(m1); - e10 += new d(m1); - e11 += new d(m1); - e12 += new d(m1); - e13 += new d(m1); - e14 += new d(m1); - e15 += new d(m1); - e16 += new d(m1); - e17 += new d(m1); - e18 += new d(m1); - e19 += new d(m1); - e20 += new d(m1); - e21 += new d(m1); - e22 += new d(m1); - e23 += new d(m1); - e24 += new d(m1); + public Class20() { } + public Class20(int i) { } + public Class20(int i, int ii) { } + + public int f0 = 0; + static public int f1 = 0; + public int f2 = 0; + public int f3 = 0; + public int f4 = 0; + public int f5 = 0; + public int f6 = 0; + public int f7 = 0; + public int f8 = 0; + public int f9 = 0; + public int f10 = 0; + public int f11 = 0; + public int f12 = 0; + public int f13 = 0; + public int f14 = 0; + public int f15 = 0; + public int f16 = 0; + public int f17 = 0; + public int f18 = 0; + public int f19 = 0; + public int f20 = 0; + public int f21 = 0; + public int f22 = 0; + public int f23 = 0; + public int f24 = 0; + + public void m1() { } + static public void m2() { } + public void m3() { } + public void m4() { } + public void m5() { } + public void m6() { } + public void m7() { } + public void m8() { } + public void m9() { } + public void m10() { } + public void m11() { } + public void m12() { } + public void m13() { } + public void m14() { } + public void m15() { } + public void m16() { } + public void m17() { } + public void m18() { } + public void m19() { } + public void m20() { } + public void m21() { } + public void m22() { } + public void m23() { } + public void m24() { } + + public int p0 { get { return 1; } set { } } + static public int p1 { get { return 1; } set { } } + public int p2 { get { return 1; } set { } } + public int p3 { get { return 1; } set { } } + public int p4 { get { return 1; } set { } } + public int p5 { get { return 1; } set { } } + public int p6 { get { return 1; } set { } } + public int p7 { get { return 1; } set { } } + public int p8 { get { return 1; } set { } } + public int p9 { get { return 1; } set { } } + public int p10 { get { return 1; } set { } } + public int p11 { get { return 1; } set { } } + public int p12 { get { return 1; } set { } } + public int p13 { get { return 1; } set { } } + public int p14 { get { return 1; } set { } } + public int p15 { get { return 1; } set { } } + public int p16 { get { return 1; } set { } } + public int p17 { get { return 1; } set { } } + public int p18 { get { return 1; } set { } } + public int p19 { get { return 1; } set { } } + public int p20 { get { return 1; } set { } } + public int p21 { get { return 1; } set { } } + public int p22 { get { return 1; } set { } } + public int p23 { get { return 1; } set { } } + public int p24 { get { return 1; } set { } } + + public event d e0; + static public event d e1; + public event d e2; + public event d e3; + public event d e4; + public event d e5; + public event d e6; + public event d e7; + public event d e8; + public event d e9; + public event d e10; + public event d e11; + public event d e12; + public event d e13; + public event d e14; + public event d e15; + public event d e16; + public event d e17; + public event d e18; + public event d e19; + public event d e20; + public event d e21; + public event d e22; + public event d e23; + public event d e24; + + public void NoWarning() + { + e0 += new d(m1); + e1 += new d(m1); + e2 += new d(m1); + e3 += new d(m1); + e4 += new d(m1); + e5 += new d(m1); + e6 += new d(m1); + e7 += new d(m1); + e8 += new d(m1); + e9 += new d(m1); + e10 += new d(m1); + e11 += new d(m1); + e12 += new d(m1); + e13 += new d(m1); + e14 += new d(m1); + e15 += new d(m1); + e16 += new d(m1); + e17 += new d(m1); + e18 += new d(m1); + e19 += new d(m1); + e20 += new d(m1); + e21 += new d(m1); + e22 += new d(m1); + e23 += new d(m1); + e24 += new d(m1); + } } -} -#endregion + #endregion -public delegate void d(); + public delegate void d(); +} \ No newline at end of file diff --git a/tests/src/performance/perflab/StackWalk.cs b/tests/src/performance/perflab/StackWalk.cs index da36fd0..b845ef9 100644 --- a/tests/src/performance/perflab/StackWalk.cs +++ b/tests/src/performance/perflab/StackWalk.cs @@ -5,72 +5,75 @@ using Microsoft.Xunit.Performance; using System; using System.Runtime.CompilerServices; -public static class StackWalk +namespace PerfLabTests { - [Benchmark(InnerIterationCount=1000)] - public static void Walk() + public static class StackWalk { - A(5); - } + [Benchmark(InnerIterationCount = 1000)] + public static void Walk() + { + A(5); + } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int A(int a) { return B(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int B(int a) { return C(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int C(int a) { return D(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int D(int a) { return E(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int E(int a) { return F(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int F(int a) { return G(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int G(int a) { return H(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int H(int a) { return I(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int I(int a) { return J(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int J(int a) { return K(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int K(int a) { return L(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int L(int a) { return M(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int M(int a) { return N(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int N(int a) { return O(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int O(int a) { return P(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int P(int a) { return Q(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int Q(int a) { return R(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int R(int a) { return S(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int S(int a) { return T(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int T(int a) { return U(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int U(int a) { return V(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int V(int a) { return W(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int W(int a) { return X(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int X(int a) { return Y(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int Y(int a) { return Z(a + 5); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static int Z(int a) - { - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - GC.Collect(0); + [MethodImpl(MethodImplOptions.NoInlining)] + private static int A(int a) { return B(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int B(int a) { return C(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int C(int a) { return D(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int D(int a) { return E(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int E(int a) { return F(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int F(int a) { return G(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int G(int a) { return H(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int H(int a) { return I(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int I(int a) { return J(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int J(int a) { return K(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int K(int a) { return L(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int L(int a) { return M(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int M(int a) { return N(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int N(int a) { return O(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int O(int a) { return P(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int P(int a) { return Q(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int Q(int a) { return R(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int R(int a) { return S(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int S(int a) { return T(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int T(int a) { return U(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int U(int a) { return V(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int V(int a) { return W(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int W(int a) { return X(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int X(int a) { return Y(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int Y(int a) { return Z(a + 5); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static int Z(int a) + { + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + GC.Collect(0); - return 55; + return 55; + } } } \ No newline at end of file diff --git a/tests/src/performance/perflab/ThreadingPerf.cs b/tests/src/performance/perflab/ThreadingPerf.cs index 5cb16d4..13d6ba0 100644 --- a/tests/src/performance/perflab/ThreadingPerf.cs +++ b/tests/src/performance/perflab/ThreadingPerf.cs @@ -5,70 +5,73 @@ using Microsoft.Xunit.Performance; using System; using System.Threading; -public class JITIntrinsics +namespace PerfLabTests { - private static int s_i; - private static string s_s; - - [Benchmark(InnerIterationCount=100000)] - public static void CompareExchangeIntNoMatch() + public class JITIntrinsics { - s_i = 0; - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - Interlocked.CompareExchange(ref s_i, 5, -1); - } + private static int s_i; + private static string s_s; - [Benchmark(InnerIterationCount=100000)] - public static void CompareExchangeIntMatch() - { - foreach (var iteration in Benchmark.Iterations) + [Benchmark(InnerIterationCount = 100000)] + public static void CompareExchangeIntNoMatch() { - s_i = 1; - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - Interlocked.CompareExchange(ref s_i, 5, 1); + s_i = 0; + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + Interlocked.CompareExchange(ref s_i, 5, -1); } - } - [Benchmark(InnerIterationCount=100000)] - public static void CompareExchangeObjNoMatch() - { - s_s = "Hello"; - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - Interlocked.CompareExchange(ref s_s, "World", "What?"); - } + [Benchmark(InnerIterationCount = 100000)] + public static void CompareExchangeIntMatch() + { + foreach (var iteration in Benchmark.Iterations) + { + s_i = 1; + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + Interlocked.CompareExchange(ref s_i, 5, 1); + } + } - [Benchmark(InnerIterationCount=100000)] - public static void CompareExchangeObjMatch() - { - foreach (var iteration in Benchmark.Iterations) + [Benchmark(InnerIterationCount = 100000)] + public static void CompareExchangeObjNoMatch() { - s_s = "What?"; - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - Interlocked.CompareExchange(ref s_s, "World", "What?"); + s_s = "Hello"; + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + Interlocked.CompareExchange(ref s_s, "World", "What?"); } - } - [Benchmark(InnerIterationCount=100000)] - public static void InterlockedIncrement() - { - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - Interlocked.Increment(ref s_i); - } + [Benchmark(InnerIterationCount = 100000)] + public static void CompareExchangeObjMatch() + { + foreach (var iteration in Benchmark.Iterations) + { + s_s = "What?"; + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + Interlocked.CompareExchange(ref s_s, "World", "What?"); + } + } - [Benchmark(InnerIterationCount=100000)] - public static void InterlockedDecrement() - { - foreach (var iteration in Benchmark.Iterations) - using (iteration.StartMeasurement()) - for (int i = 0; i < Benchmark.InnerIterationCount; i++) - Interlocked.Decrement(ref s_i); + [Benchmark(InnerIterationCount = 100000)] + public static void InterlockedIncrement() + { + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + Interlocked.Increment(ref s_i); + } + + [Benchmark(InnerIterationCount = 100000)] + public static void InterlockedDecrement() + { + foreach (var iteration in Benchmark.Iterations) + using (iteration.StartMeasurement()) + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + Interlocked.Decrement(ref s_i); + } } } \ No newline at end of file diff --git a/tests/src/performance/project.json b/tests/src/performance/project.json index 7d98cbd..97234d3 100644 --- a/tests/src/performance/project.json +++ b/tests/src/performance/project.json @@ -1,32 +1,32 @@ { "dependencies": { - "Microsoft.DotNet.xunit.performance": "1.0.0-alpha-build0035", - "Microsoft.DotNet.xunit.performance.analysis": "1.0.0-alpha-build0035", - "Microsoft.DotNet.xunit.performance.runner.Windows": "1.0.0-alpha-build0035", - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections.NonGeneric": "4.3.0", - "System.Console": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Linq": "4.3.0", - "System.Linq.Expressions": "4.3.0", - "System.Numerics.Vectors": "4.3.0", - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Reflection.TypeExtensions": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Text.RegularExpressions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.Tasks.Parallel": "4.3.0", - "System.Diagnostics.Process": "4.3.0", - "System.Xml.XmlDocument": "4.3.0", - "System.Xml.XPath": "4.3.0", - "System.Xml.XPath.XmlDocument": "4.3.0", - "xunit": "2.1.0", - "xunit.console.netcore": "1.0.2-prerelease-00101", - "xunit.runner.utility": "2.1.0" + "Microsoft.DotNet.xunit.performance": "1.0.0-alpha-build0040", + "Microsoft.DotNet.xunit.performance.analysis": "1.0.0-alpha-build0040", + "Microsoft.DotNet.xunit.performance.runner.Windows": "1.0.0-alpha-build0040", + "Microsoft.NETCore.Platforms": "1.2.0-beta-24820-02", + "System.Collections.NonGeneric": "4.4.0-beta-24820-02", + "System.Console": "4.4.0-beta-24820-02", + "System.IO.FileSystem": "4.4.0-beta-24820-02", + "System.Linq": "4.4.0-beta-24820-02", + "System.Linq.Expressions": "4.4.0-beta-24820-02", + "System.Numerics.Vectors": "4.4.0-beta-24820-02", + "System.Reflection": "4.4.0-beta-24820-02", + "System.Reflection.Extensions": "4.4.0-beta-24820-02", + "System.Reflection.TypeExtensions": "4.4.0-beta-24820-02", + "System.Runtime": "4.4.0-beta-24820-02", + "System.Runtime.Extensions": "4.4.0-beta-24820-02", + "System.Runtime.Numerics": "4.4.0-beta-24820-02", + "System.Text.RegularExpressions": "4.4.0-beta-24820-02", + "System.Threading": "4.4.0-beta-24820-02", + "System.Threading.Tasks": "4.4.0-beta-24820-02", + "System.Threading.Tasks.Parallel": "4.4.0-beta-24820-02", + "System.Diagnostics.Process": "4.4.0-beta-24820-02", + "System.Xml.XmlDocument": "4.4.0-beta-24820-02", + "System.Xml.XPath": "4.4.0-beta-24820-02", + "System.Xml.XPath.XmlDocument": "4.4.0-beta-24820-02", + "xunit": "2.2.0-beta2-build3300", + "xunit.console.netcore": "1.0.2-prerelease-00177", + "xunit.runner.utility": "2.2.0-beta2-build3300" }, "frameworks": { "netstandard1.4": { diff --git a/tests/src/readytorun/generics.cs b/tests/src/readytorun/generics.cs index 8bd61b8..4c41756 100644 --- a/tests/src/readytorun/generics.cs +++ b/tests/src/readytorun/generics.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Runtime.CompilerServices; using System.Text; using System.Threading; @@ -34,46 +35,57 @@ class Program static void RunTest1() { - DateTime dt = new DateTime(1776, 7, 4); - string dtString = dt.ToString(); - Assert.AreEqual(new GenClass1c(dt).ToStringEx(7), dtString + " 7"); - Assert.AreEqual(new GenClass1c(1).ToStringEx(7), "1 7"); - Assert.AreEqual(new GenClass1c(2).ToStringEx(7), "2 7"); - Assert.AreEqual(new GenClass1c(3.14f).ToStringEx(7), "3.14 7"); - Assert.AreEqual(new GenClass1c(4.13).ToStringEx(7), "4.13 7"); - Assert.AreEqual(new GenClass1c(9).ToString(), "9"); - - Assert.AreEqual(new GenClass2(dt, 3.1416).ToString(), dtString + " 3.1416"); - Assert.AreEqual(new GenClass2(dt, 3.1416).ToStringEx(7, 8), dtString + " 3.1416 7 8"); - Assert.AreEqual(new GenClass2(new object(), "3.1416").ToString(), "System.Object 3.1416"); - Assert.AreEqual(new GenClass2(new object(), "3.1416").ToStringEx(7L, 8L), "System.Object 3.1416 7 8"); - Assert.AreEqual(GetString(7.0, 8.0), "7 8"); - - var gen1a = new GenClass1a(); - Assert.AreEqual(gen1a.CreateGenClass1b(), "GenClass1b`1[System.Object]"); - Assert.AreEqual(gen1a.CreateGenClass1bArray(), "GenClass1b`1[System.Object][]"); - - var gen1aInt = new GenClass1a(); - var gen1bInt = new GenClass1b(); - var gen1bLong = new GenClass1b(); - Assert.AreEqual(gen1bInt.IsGenClass1a(gen1aInt).ToString(), "True"); - Assert.AreEqual(gen1bLong.IsGenClass1a(gen1aInt).ToString(), "False"); - Assert.AreEqual(gen1bInt.AsGenClass1a(gen1aInt)?.ToString() ?? "null", gen1aInt.ToString()); - Assert.AreEqual(gen1bLong.AsGenClass1a(gen1aInt)?.ToString() ?? "null", "null"); - - var gen1aString = new GenClass1a(); - var gen1b = new GenClass1b(); - Assert.AreEqual(gen1b.IsGenClass1a(gen1aString).ToString(), "True"); - Assert.AreEqual(gen1b.AsGenClass1a(gen1aString)?.ToString() ?? "null", gen1aString.ToString()); - Assert.AreEqual(GenClass1a.CallVirtual(gen1b), "GenClass1b`1[System.String].VirtualMethod"); - Assert.AreEqual(GenClass1a.CallInterface(gen1b), "GenClass1b`1[System.String].InterfaceMethod1"); - Assert.AreEqual(GenClass1a.CallInterface(gen1b, "Test").ToString(), "GenClass1b`1[System.String]"); - - NormalClass n = new NormalClass(); - Assert.AreEqual(CallGenVirtMethod(n).ToString(), "GenClass1a`1[System.Int32]"); - Assert.AreEqual(CallGenVirtMethod(n, 42).ToString(), "System.Int32[]"); - Assert.AreEqual(CallGenVirtMethod(n).ToString(), "GenClass1a`1[System.String]"); - Assert.AreEqual(CallGenVirtMethod(n, "forty-two").ToString(), "System.String[]"); + var originalCultureInfo = CultureInfo.CurrentCulture; + + try + { + CultureInfo.CurrentCulture = CultureInfo.InvariantCulture; + + DateTime dt = new DateTime(1776, 7, 4); + string dtString = dt.ToString(); + Assert.AreEqual(new GenClass1c(dt).ToStringEx(7), dtString + " 7"); + Assert.AreEqual(new GenClass1c(1).ToStringEx(7), "1 7"); + Assert.AreEqual(new GenClass1c(2).ToStringEx(7), "2 7"); + Assert.AreEqual(new GenClass1c(3.14f).ToStringEx(7), "3.14 7"); + Assert.AreEqual(new GenClass1c(4.13).ToStringEx(7), "4.13 7"); + Assert.AreEqual(new GenClass1c(9).ToString(), "9"); + + Assert.AreEqual(new GenClass2(dt, 3.1416).ToString(), dtString + " 3.1416"); + Assert.AreEqual(new GenClass2(dt, 3.1416).ToStringEx(7, 8), dtString + " 3.1416 7 8"); + Assert.AreEqual(new GenClass2(new object(), "3.1416").ToString(), "System.Object 3.1416"); + Assert.AreEqual(new GenClass2(new object(), "3.1416").ToStringEx(7L, 8L), "System.Object 3.1416 7 8"); + Assert.AreEqual(GetString(7.0, 8.0), "7 8"); + + var gen1a = new GenClass1a(); + Assert.AreEqual(gen1a.CreateGenClass1b(), "GenClass1b`1[System.Object]"); + Assert.AreEqual(gen1a.CreateGenClass1bArray(), "GenClass1b`1[System.Object][]"); + + var gen1aInt = new GenClass1a(); + var gen1bInt = new GenClass1b(); + var gen1bLong = new GenClass1b(); + Assert.AreEqual(gen1bInt.IsGenClass1a(gen1aInt).ToString(), "True"); + Assert.AreEqual(gen1bLong.IsGenClass1a(gen1aInt).ToString(), "False"); + Assert.AreEqual(gen1bInt.AsGenClass1a(gen1aInt)?.ToString() ?? "null", gen1aInt.ToString()); + Assert.AreEqual(gen1bLong.AsGenClass1a(gen1aInt)?.ToString() ?? "null", "null"); + + var gen1aString = new GenClass1a(); + var gen1b = new GenClass1b(); + Assert.AreEqual(gen1b.IsGenClass1a(gen1aString).ToString(), "True"); + Assert.AreEqual(gen1b.AsGenClass1a(gen1aString)?.ToString() ?? "null", gen1aString.ToString()); + Assert.AreEqual(GenClass1a.CallVirtual(gen1b), "GenClass1b`1[System.String].VirtualMethod"); + Assert.AreEqual(GenClass1a.CallInterface(gen1b), "GenClass1b`1[System.String].InterfaceMethod1"); + Assert.AreEqual(GenClass1a.CallInterface(gen1b, "Test").ToString(), "GenClass1b`1[System.String]"); + + NormalClass n = new NormalClass(); + Assert.AreEqual(CallGenVirtMethod(n).ToString(), "GenClass1a`1[System.Int32]"); + Assert.AreEqual(CallGenVirtMethod(n, 42).ToString(), "System.Int32[]"); + Assert.AreEqual(CallGenVirtMethod(n).ToString(), "GenClass1a`1[System.String]"); + Assert.AreEqual(CallGenVirtMethod(n, "forty-two").ToString(), "System.String[]"); + } + finally + { + CultureInfo.CurrentCulture = originalCultureInfo; + } } static void RunTest2() diff --git a/tests/src/readytorun/main.cs b/tests/src/readytorun/main.cs index cce03b4..bbdd101 100644 --- a/tests/src/readytorun/main.cs +++ b/tests/src/readytorun/main.cs @@ -345,17 +345,9 @@ class Program static void TestMultipleLoads() { if (!LLILCJitEnabled) { - try - { - new MyLoadContext().TestMultipleLoads(); - } - catch (FileLoadException e) - { - Assert.AreEqual(e.ToString().Contains("Native image cannot be loaded multiple times"), true); - return; - } - - Assert.AreEqual("FileLoadException", "thrown"); + // Runtime should be able to load the same R2R image in another load context, + // even though it will be treated as an IL-only image. + new MyLoadContext().TestMultipleLoads(); } } #endif diff --git a/tests/src/reflection/ldtoken/byrefs.il b/tests/src/reflection/ldtoken/byrefs.il new file mode 100644 index 0000000..d0009b3 --- /dev/null +++ b/tests/src/reflection/ldtoken/byrefs.il @@ -0,0 +1,88 @@ +// 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. + +// +// This test makes sure that ByRef types are properly unified by the reflection stack +// and that a type constructed by reflection is equivalent to a type constructed through +// the LDTOKEN instruction. +// + +.assembly extern mscorlib { } +.assembly extern System.Console +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) + .ver 4:0:0:0 +} +.assembly byrefs +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) +} + +.class private auto ansi beforefieldinit Test + extends [mscorlib]System.Object +{ + .method private hidebysig static int32 Main() cil managed + { + .entrypoint + .maxstack 2 + + call bool Test::LdTokenEqualsMakeByRef() + brfalse Failed + + call bool Test::MakeByRefEqualsLdToken() + brfalse Failed + + ldc.i4 100 + ldstr "ByRefs look good" + br.s Done + Failed: + ldc.i4 666 + ldstr "ByRefs are broken" + Done: + call void class [System.Console]System.Console::WriteLine(string) + ret + } + + .method private hidebysig static bool LdTokenEqualsMakeByRef() cil managed + { + .maxstack 2 + + ldtoken valuetype MyType1& + call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + + ldtoken valuetype MyType1 + call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + callvirt instance class [mscorlib]System.Type [mscorlib]System.Type::MakeByRefType() + + ceq + + ret + } + + .method private hidebysig static bool MakeByRefEqualsLdToken() cil managed + { + .maxstack 2 + + ldtoken valuetype MyType2 + call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + callvirt instance class [mscorlib]System.Type [mscorlib]System.Type::MakeByRefType() + + ldtoken valuetype MyType2& + call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + + ceq + + ret + } +} + +.class private auto ansi beforefieldinit MyType1 + extends [mscorlib]System.ValueType +{ +} + +.class private auto ansi beforefieldinit MyType2 + extends [mscorlib]System.ValueType +{ +} diff --git a/tests/src/reflection/ldtoken/byrefs.ilproj b/tests/src/reflection/ldtoken/byrefs.ilproj new file mode 100644 index 0000000..3baecd4 --- /dev/null +++ b/tests/src/reflection/ldtoken/byrefs.ilproj @@ -0,0 +1,35 @@ + + + + + byrefs + Debug + AnyCPU + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 7a9bfb7d + true + true + Exe + BuildAndRun + 1 + + + + + False + + + + + + + + + + + + + diff --git a/tests/tests.targets b/tests/tests.targets index 56c6c5d..78028cd 100644 --- a/tests/tests.targets +++ b/tests/tests.targets @@ -1,7 +1,7 @@ - + <_SkipTestAssemblies Include="$(SkipTestAssemblies)" /> @@ -27,7 +27,7 @@ 5286 - needs triage + 7163 needs triage @@ -515,5 +515,11 @@ needs triage + + times out + + + 8077 + diff --git a/tests/x86_legacy_backend_issues.targets b/tests/x86_legacy_backend_issues.targets index 671e67d..4b97325 100644 --- a/tests/x86_legacy_backend_issues.targets +++ b/tests/x86_legacy_backend_issues.targets @@ -137,7 +137,7 @@ 2414 - needs triage + 2408 2414 @@ -229,16 +229,16 @@ 3392 - needs triage + 2413 - needs triage + 2413 - needs triage + 2412 - needs triage + 2412 tail. call pop ret is only supported on amd64 @@ -253,17 +253,23 @@ needs triage - x86 JIT doesn't support implicit tail call optimization or tail. call pop ret sequence + 2420. x86 JIT doesn't support implicit tail call optimization or tail. call pop ret sequence 6844 - needs triage + 7163 needs triage + + The test is too large for x86 and causes OutOfMemory exception. + + + The superpmi test depends on setting COMPlus_AltJit, so doesn't work with either the legacy jit test run, which also sets COMPlus_AltJit, or the compatjit test run, which sets COMPlus_UseWindowsX86CoreLegacyJit + @@ -436,5 +442,8 @@ needs triage + + 8077 + diff --git a/tests/xunitwrapper.targets b/tests/xunitwrapper.targets index 6d5c5e2..3b343bd 100644 --- a/tests/xunitwrapper.targets +++ b/tests/xunitwrapper.targets @@ -10,7 +10,7 @@ AllowFallbackOnTargetSelection="true" IncludeFrameworkReferences="false" NuGetPackagesDirectory="$(PackagesDir)" - RuntimeIdentifier="dotnet" + RuntimeIdentifier="$(TestNugetRuntimeId)" ProjectLanguage="$(Language)" ProjectLockFile="$(ProjectLockJson)" TargetMonikers="$(TargetFrameworkMoniker)"> diff --git a/verify-so.sh b/verify-so.sh new file mode 100755 index 0000000..3907cf1 --- /dev/null +++ b/verify-so.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# $1 contains full path to the .so to verify +# $2 contains message to print when the verification fails + +OSName=$(uname -s) +case $OSName in + Linux) + source /etc/os-release + # TODO: add support for verification on Alpine Linux + if [ "$ID" != "alpine" ]; then + ldd -r $1 | awk 'BEGIN {count=0} /undefined symbol:/ { if (count==0) {print "Undefined symbol(s) found:"} print " " $3; count++ } END {if (count>0) exit(1)}' + if [ $? != 0 ]; then + echo "$2" + exit 1 + fi + fi + ;; +esac + +# TODO: add support for verification on non-Linux Unixes (except of OSX) -- 2.7.4